From 0a5e4639e409e29ee8172309dbaa756a2b5a4679 Mon Sep 17 00:00:00 2001 From: Nanxin Qin Date: Mon, 19 Jun 2017 15:34:01 +0800 Subject: [PATCH] media: merged code from 43177e6a on the amlogic-3.14-dev PD#146152: merged code from 43177e6a on the amlogic-3.14-dev 1. support for multi-instance features 2. fixed in multi-instance codec_mm memory bugs and added some debugging information 3. optimization of vfm problems Change-Id: I43ba9d4894ae71d53c158df667490030735b9e1e Signed-off-by: Nanxin Qin Signed-off-by: KeLe Bai --- MAINTAINERS | 5 + arch/arm64/configs/meson64_defconfig | 3 + drivers/amlogic/media/Kconfig | 4 + drivers/amlogic/media/Makefile | 2 +- .../media/common/arch/registers/register_map.c | 88 + .../media/common/arch/registers/register_ops.c | 2 +- .../media/common/arch/registers/register_ops_m8.c | 48 + drivers/amlogic/media/common/canvas/canvas.c | 56 +- drivers/amlogic/media/common/canvas/canvas_mgr.c | 56 +- drivers/amlogic/media/common/codec_mm/Makefile | 1 + drivers/amlogic/media/common/codec_mm/codec_mm.c | 455 +++-- .../amlogic/media/common/codec_mm/codec_mm_priv.h | 4 - .../media/common/codec_mm/codec_mm_scatter.c | 724 ++++---- .../media/common/codec_mm/codec_mm_scatter_priv.h | 4 +- .../amlogic/media/common/codec_mm/configs/Makefile | 14 + .../media/common/codec_mm/configs/configs.c | 1094 ++++++++++++ .../media/common/codec_mm/configs/configs_module.c | 479 ++++++ .../media/common/codec_mm/configs/configs_priv.h | 34 + .../media/common/codec_mm/configs/configs_test.c | 145 ++ drivers/amlogic/media/common/ge2d/ge2d_hw.c | 4 +- drivers/amlogic/media/common/rdma/Makefile | 6 +- drivers/amlogic/media/common/rdma/rdma.c | 255 ++- drivers/amlogic/media/common/rdma/rdma_mgr.c | 537 +++--- drivers/amlogic/media/common/vfm/vfm.c | 459 ++++- drivers/amlogic/media/common/vfm/vfm.h | 13 + drivers/amlogic/media/common/vfm/vframe_provider.c | 156 +- drivers/amlogic/media/common/vfm/vframe_receiver.c | 3 +- drivers/amlogic/media/common/vfm/vftrace.c | 5 +- drivers/amlogic/media/deinterlace/deinterlace.c | 3 - drivers/amlogic/media/deinterlace/deinterlace.h | 24 +- drivers/amlogic/media/frame_sync/ptsserv.c | 118 +- drivers/amlogic/media/frame_sync/timestamp.c | 12 +- drivers/amlogic/media/frame_sync/tsync.c | 180 +- drivers/amlogic/media/frame_sync/tsync_pcr.c | 63 +- .../media/video_processor/ionvideo/ionvideo.c | 2 +- .../media/video_processor/video_dev/amlvideo.c | 103 +- .../media/video_processor/video_dev/amlvideo.h | 1 + .../media/video_processor/video_dev/amlvideo2.c | 68 +- drivers/amlogic/media/video_sink/Kconfig | 6 + drivers/amlogic/media/video_sink/amvideocap_priv.h | 69 + drivers/amlogic/media/video_sink/video.c | 1765 ++++++++++++++------ drivers/amlogic/media/video_sink/video_keeper.c | 15 +- drivers/amlogic/media/video_sink/video_priv.h | 5 +- drivers/amlogic/media/video_sink/vpp.c | 330 ++-- drivers/amlogic/wifi/wifi_dt.c | 1 - include/linux/amlogic/cpu_version.h | 11 +- include/linux/amlogic/major.h | 3 +- include/linux/amlogic/media/canvas/canvas.h | 4 +- include/linux/amlogic/media/canvas/canvas_mgr.h | 4 +- include/linux/amlogic/media/codec_mm/codec_mm.h | 20 +- .../amlogic/media/codec_mm/codec_mm_scatter.h | 6 +- include/linux/amlogic/media/codec_mm/configs.h | 270 +++ include/linux/amlogic/media/codec_mm/configs_api.h | 48 + include/linux/amlogic/media/frame_sync/ptsserv.h | 2 + include/linux/amlogic/media/frame_sync/tsync.h | 3 +- .../linux/amlogic/media/registers/register_map.h | 8 + .../linux/amlogic/media/registers/register_ops.h | 6 + .../linux/amlogic/media/registers/regs/aiu_regs.h | 7 + .../amlogic/media/registers/regs/demux_regs.h | 7 + .../linux/amlogic/media/registers/regs/dos_regs.h | 5 + .../linux/amlogic/media/registers/regs/hevc_regs.h | 2 + .../amlogic/media/registers/regs/parser_regs.h | 7 + .../linux/amlogic/media/registers/regs/sys_regs.h | 8 + .../linux/amlogic/media/registers/regs/vdin_regs.h | 1 + .../linux/amlogic/media/registers/regs/viu_regs.h | 2 + .../linux/amlogic/media/registers/regs/vpp_regs.h | 1 + include/linux/amlogic/media/tvin/tvin.h | 868 ++++++++++ include/linux/amlogic/media/tvin/tvin_v4l2.h | 825 +++++++++ include/linux/amlogic/media/utils/aformat.h | 6 +- include/linux/amlogic/media/utils/amports_config.h | 1 + include/linux/amlogic/media/utils/amstream.h | 51 +- include/linux/amlogic/media/utils/vdec_reg.h | 44 + include/linux/amlogic/media/vfm/vframe.h | 17 +- include/linux/amlogic/media/vfm/vframe_provider.h | 13 + .../linux/amlogic/media/video_sink/amvideocap.h | 64 + .../linux/amlogic/media/video_sink/ionvideo_ext.h | 2 +- include/linux/amlogic/media/video_sink/video.h | 3 +- include/linux/amlogic/media/video_sink/vpp.h | 45 +- 78 files changed, 8032 insertions(+), 1753 deletions(-) create mode 100644 drivers/amlogic/media/common/codec_mm/configs/Makefile create mode 100644 drivers/amlogic/media/common/codec_mm/configs/configs.c create mode 100644 drivers/amlogic/media/common/codec_mm/configs/configs_module.c create mode 100644 drivers/amlogic/media/common/codec_mm/configs/configs_priv.h create mode 100644 drivers/amlogic/media/common/codec_mm/configs/configs_test.c create mode 100644 drivers/amlogic/media/video_sink/amvideocap_priv.h create mode 100644 include/linux/amlogic/media/codec_mm/configs.h create mode 100644 include/linux/amlogic/media/codec_mm/configs_api.h create mode 100644 include/linux/amlogic/media/tvin/tvin.h create mode 100644 include/linux/amlogic/media/tvin/tvin_v4l2.h create mode 100644 include/linux/amlogic/media/video_sink/amvideocap.h diff --git a/MAINTAINERS b/MAINTAINERS index e257c81..ced5dc8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14047,3 +14047,8 @@ F: drivers/amlogic/media/vout/backlight/bl_extern/pmu_aml1218.c AMLOGIC MESONGXL ADD A113X 128m DTS M: Yuegui He F: arch/arm64/boot/dts/amlogic/axg_s420_128m.dts + +AMLOGIC multimedia +M: Nanxin Qin +F: drivers/amlogic/media/common/codec_mm/configs/* + diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 3e5caa7..4357d9c 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -221,15 +221,18 @@ CONFIG_AMLOGIC_PWM=y CONFIG_AMLOGIC_MEDIA_ENABLE=y CONFIG_AMLOGIC_MEDIA_COMMON=y CONFIG_AMLOGIC_MEDIA_DRIVERS=y +CONFIG_AMLOGIC_MEDIA_MULTI_DEC=y CONFIG_AMLOGIC_MEDIA_CODEC_MM=y CONFIG_AMLOGIC_MEDIA_CANVAS=y CONFIG_AMLOGIC_MEDIA_GE2D=y CONFIG_AMLOGIC_ION=y CONFIG_AMLOGIC_MEDIA_RDMA=y +CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA=y CONFIG_AMLOGIC_MEDIA_VFM=y CONFIG_AMLOGIC_VPU=y CONFIG_AMLOGIC_VIDEOBUF_RESOURCE=y CONFIG_AMLOGIC_MEDIA_VIDEO=y +CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE=y CONFIG_AMLOGIC_VOUT=y CONFIG_AMLOGIC_CVBS_OUTPUT=y CONFIG_AMLOGIC_WSS=y diff --git a/drivers/amlogic/media/Kconfig b/drivers/amlogic/media/Kconfig index e04b50f..009b3bb 100644 --- a/drivers/amlogic/media/Kconfig +++ b/drivers/amlogic/media/Kconfig @@ -35,6 +35,10 @@ config AMLOGIC_MEDIA_DRIVERS module, video decoder management module and post processing of the frame. +config AMLOGIC_MEDIA_MULTI_DEC + bool "Support multi-instance decoding" + default n + if AMLOGIC_MEDIA_COMMON source "drivers/amlogic/media/common/Kconfig" endif diff --git a/drivers/amlogic/media/Makefile b/drivers/amlogic/media/Makefile index e1ef9d6..d33bc71 100644 --- a/drivers/amlogic/media/Makefile +++ b/drivers/amlogic/media/Makefile @@ -7,4 +7,4 @@ obj-$(CONFIG_AMLOGIC_MEDIA_FB_EXT) += osd_ext/ obj-$(CONFIG_AMLOGIC_MEDIA_DEINTERLACE) += deinterlace/ obj-$(CONFIG_AMLOGIC_MEDIA_VIN) += vin/ obj-$(CONFIG_AMLOGIC_MEDIA_VIDEO_PROCESSOR) += video_processor/ -obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT) += enhancement/ \ No newline at end of file +obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT) += enhancement/ diff --git a/drivers/amlogic/media/common/arch/registers/register_map.c b/drivers/amlogic/media/common/arch/registers/register_map.c index ad62a0b..87f98cf 100644 --- a/drivers/amlogic/media/common/arch/registers/register_map.c +++ b/drivers/amlogic/media/common/arch/registers/register_map.c @@ -223,6 +223,94 @@ void codecio_write_dmcbus(unsigned int reg, unsigned int val) return; } +int codecio_read_parsbus(unsigned int reg) +{ + int ret, val; + + ret = codecio_reg_read(CODECIO_CBUS_BASE, reg << 2, &val); + if (ret) { + pr_err("read parser reg %x error %d\n", reg, ret); + return -1; + } + + return val; +} + +void codecio_write_parsbus(unsigned int reg, unsigned int val) +{ + int ret; + + ret = codecio_reg_write(CODECIO_CBUS_BASE, reg << 2, val); + if (ret) + pr_err("write parser reg %x error %d\n", reg, ret); +} + +int codecio_read_aiubus(unsigned int reg) +{ + int ret, val; + + ret = codecio_reg_read(CODECIO_CBUS_BASE, reg << 2, &val); + if (ret) { + pr_err("read aiu reg %x error %d\n", reg, ret); + return -1; + } + + return val; +} + +void codecio_write_aiubus(unsigned int reg, unsigned int val) +{ + int ret; + + ret = codecio_reg_write(CODECIO_CBUS_BASE, reg << 2, val); + if (ret) + pr_err("write aiu reg %x error %d\n", reg, ret); +} + +int codecio_read_demuxbus(unsigned int reg) +{ + int ret, val; + + ret = codecio_reg_read(CODECIO_CBUS_BASE, reg << 2, &val); + if (ret) { + pr_err("read demux reg %x error %d\n", reg, ret); + return -1; + } + + return val; +} + +void codecio_write_demuxbus(unsigned int reg, unsigned int val) +{ + int ret; + + ret = codecio_reg_write(CODECIO_CBUS_BASE, reg << 2, val); + if (ret) + pr_err("write demux reg %x error %d\n", reg, ret); +} + +int codecio_read_resetbus(unsigned int reg) +{ + int ret, val; + + ret = codecio_reg_read(CODECIO_CBUS_BASE, reg << 2, &val); + if (ret) { + pr_err("read reset reg %x error %d\n", reg, ret); + return -1; + } + + return val; +} + +void codecio_write_resetbus(unsigned int reg, unsigned int val) +{ + int ret; + + ret = codecio_reg_write(CODECIO_CBUS_BASE, reg << 2, val); + if (ret) + pr_err("write reset reg %x error %d\n", reg, ret); +} + static int codec_io_probe(struct platform_device *pdev) { int i = 0; diff --git a/drivers/amlogic/media/common/arch/registers/register_ops.c b/drivers/amlogic/media/common/arch/registers/register_ops.c index 2768d77..3711d44 100644 --- a/drivers/amlogic/media/common/arch/registers/register_ops.c +++ b/drivers/amlogic/media/common/arch/registers/register_ops.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/amlogic/media/common/arch/registers/register_ops_m8.c b/drivers/amlogic/media/common/arch/registers/register_ops_m8.c index c643b2a..5ec36c7 100644 --- a/drivers/amlogic/media/common/arch/registers/register_ops_m8.c +++ b/drivers/amlogic/media/common/arch/registers/register_ops_m8.c @@ -27,6 +27,7 @@ MESON_CPU_MAJOR_ID_GXL, \ MESON_CPU_MAJOR_ID_GXM, \ MESON_CPU_MAJOR_ID_TXL, \ + MESON_CPU_MAJOR_ID_TXLX, \ 0} #define REGISTER_FOR_GXCPU {\ MESON_CPU_MAJOR_ID_GXBB, \ @@ -34,6 +35,7 @@ MESON_CPU_MAJOR_ID_GXL, \ MESON_CPU_MAJOR_ID_GXM, \ MESON_CPU_MAJOR_ID_TXL, \ + MESON_CPU_MAJOR_ID_TXLX, \ 0} int codec_apb_read(unsigned int reg) { @@ -57,6 +59,10 @@ static struct chip_register_ops m8_ops[] __initdata = { {IO_HHI_BUS, 0, codecio_read_cbus, codecio_write_cbus}, {IO_AO_BUS, 0, codecio_read_aobus, codecio_write_aobus}, {IO_VPP_BUS, 0, codecio_read_vcbus, codecio_write_vcbus}, + {IO_PARSER_BUS, 0, codecio_read_parsbus, codecio_write_parsbus}, + {IO_AIU_BUS, 0, codecio_read_aiubus, codecio_write_aiubus}, + {IO_DEMUX_BUS, 0, codecio_read_demuxbus, codecio_write_demuxbus}, + {IO_RESET_BUS, 0, codecio_read_resetbus, codecio_write_resetbus}, }; static struct chip_register_ops ex_gx_ops[] __initdata = { @@ -75,6 +81,48 @@ static int __init vdec_reg_ops_init(void) { int cpus[] = REGISTER_FOR_CPU; int gxcpus[] = REGISTER_FOR_GXCPU; + int i = 0; + + /* + * because of register range of the parser ,demux + * reset and aiu has be changed in the txlx platform, + * so we have must be offset the old range of regs. + * + * the new 0x3860 of the reg base minus the old 0x2900 + * equal to the 0xf00 of the delta value + * #define PARSER_CONTROL 0x3860 + * 0xf00 == (0x3800 - 0x2900) + * + * #define AIU_958_BPF 0x1400 + * -0x100 == (0x1400 - 0x1500) + * + * #define FEC_INPUT_CONTROL 0x1802 + * 0x200 == (0x1802 - 0x1602) + * + * #define RESET0_REGISTER 0x0401 + * -0xd00 == (0x0401 - 0x1101) + */ + if (get_cpu_type() > MESON_CPU_MAJOR_ID_TXL) { + for (i = 0; i < ARRAY_SIZE(m8_ops); i++) { + switch (m8_ops[i].bus_type) { + case IO_PARSER_BUS: + m8_ops[i].ext_offset = 0xf00; + break; + + case IO_AIU_BUS: + m8_ops[i].ext_offset = -0x100; + break; + + case IO_DEMUX_BUS: + m8_ops[i].ext_offset = 0x200; + break; + + case IO_RESET_BUS: + m8_ops[i].ext_offset = -0xd00; + break; + } + } + } register_reg_ops_mgr(cpus, m8_ops, sizeof(m8_ops) / sizeof(struct chip_register_ops)); diff --git a/drivers/amlogic/media/common/canvas/canvas.c b/drivers/amlogic/media/common/canvas/canvas.c index 6781193..d81a7fd 100644 --- a/drivers/amlogic/media/common/canvas/canvas.c +++ b/drivers/amlogic/media/common/canvas/canvas.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -158,8 +159,11 @@ static void canvas_config_locked(u32 index, struct canvas_s *p) u32 reg_add = 0; canvas_lut_data_build(p->addr, - p->width, - p->height, p->wrap, p->blkmode, p->endian, &datal, &datah); + p->width, + p->height, + p->wrap, + p->blkmode, + p->endian, &datal, &datah); if ((get_cpu_type() == MESON_CPU_MAJOR_ID_M8M2) || (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB)) @@ -202,29 +206,25 @@ int canvas_read_hw(u32 index, struct canvas_s *canvas) } EXPORT_SYMBOL(canvas_read_hw); -static inline void canvas_lock(void) -{ - struct canvas_device_info *info = &canvas_info; +#define canvas_lock(info, f, f2) do {\ + spin_lock_irqsave(&info->lock, f);\ + raw_local_save_flags(f2);\ + local_fiq_disable();\ + } while (0) - raw_local_save_flags(info->fiq_flag); - local_fiq_disable(); - spin_lock_irqsave(&info->lock, info->flags); -} +#define canvas_unlock(info, f, f2) do {\ + raw_local_irq_restore(f2);\ + spin_unlock_irqrestore(&info->lock, f);\ + } while (0) -static inline void canvas_unlock(void) -{ - struct canvas_device_info *info = &canvas_info; - spin_unlock_irqrestore(&info->lock, info->flags); - raw_local_irq_restore(info->fiq_flag); -} void canvas_config_ex(u32 index, ulong addr, u32 width, u32 height, u32 wrap, u32 blkmode, u32 endian) { struct canvas_device_info *info = &canvas_info; struct canvas_s *canvas; - + unsigned long flags, fiqflags; if (!CANVAS_VALID(index)) return; @@ -233,7 +233,7 @@ void canvas_config_ex(u32 index, ulong addr, u32 width, u32 height, u32 wrap, dump_stack(); return; } - canvas_lock(); + canvas_lock(info, flags, fiqflags); canvas = &info->canvasPool[index]; canvas->addr = addr; canvas->width = width; @@ -242,7 +242,7 @@ void canvas_config_ex(u32 index, ulong addr, u32 width, u32 height, u32 wrap, canvas->blkmode = blkmode; canvas->endian = endian; canvas_config_locked(index, canvas); - canvas_unlock(); + canvas_unlock(info, flags, fiqflags); } EXPORT_SYMBOL(canvas_config_ex); @@ -275,6 +275,7 @@ void canvas_copy(u32 src, u32 dst) struct canvas_device_info *info = &canvas_info; struct canvas_s *canvas_src = &info->canvasPool[src]; struct canvas_s *canvas_dst = &info->canvasPool[dst]; + unsigned long flags, fiqflags; if (!CANVAS_VALID(src) || !CANVAS_VALID(dst)) return; @@ -287,7 +288,7 @@ void canvas_copy(u32 src, u32 dst) return; } - canvas_lock(); + canvas_lock(info, flags, fiqflags); canvas_dst->addr = canvas_src->addr; canvas_dst->width = canvas_src->width; canvas_dst->height = canvas_src->height; @@ -297,7 +298,7 @@ void canvas_copy(u32 src, u32 dst) canvas_dst->dataH = canvas_src->dataH; canvas_dst->dataL = canvas_src->dataL; canvas_config_locked(dst, canvas_dst); - canvas_unlock(); + canvas_unlock(info, flags, fiqflags); } EXPORT_SYMBOL(canvas_copy); @@ -305,6 +306,7 @@ void canvas_update_addr(u32 index, u32 addr) { struct canvas_device_info *info = &canvas_info; struct canvas_s *canvas; + unsigned long flags, fiqflags; if (!CANVAS_VALID(index)) return; @@ -315,11 +317,12 @@ void canvas_update_addr(u32 index, u32 addr) dump_stack(); return; } - canvas_lock(); + canvas_lock(info, flags, fiqflags); canvas->addr = addr; canvas_config_locked(index, canvas); - canvas_unlock(); + canvas_unlock(info, flags, fiqflags); + return; } EXPORT_SYMBOL(canvas_update_addr); @@ -495,7 +498,8 @@ static int canvas_probe(struct platform_device *pdev) } info->res = *res; size = (int)resource_size(res); - pr_info("canvas_probe reg=%p,size=%x\n", (void *)res->start, size); + pr_info("canvas_probe reg=%p,size=%x\n", + (void *)res->start, size); if (!devm_request_mem_region(&pdev->dev, res->start, size, pdev->name)) { dev_err(&pdev->dev, "Memory region busy\n"); @@ -514,7 +518,8 @@ static int canvas_probe(struct platform_device *pdev) for (i = 0; i < info->max_canvas_num; i++) { info->canvasPool[i].index = i; r = kobject_init_and_add(&info->canvasPool[i].kobj, - &canvas_attr_type, &pdev->dev.kobj, "%d", i); + &canvas_attr_type, + &pdev->dev.kobj, "%d", i); if (r) { pr_error("Unable to create canvas objects %d\n", i); goto err2; @@ -545,7 +550,8 @@ static int canvas_remove(struct platform_device *pdev) amcanvas_manager_exit(); devm_iounmap(&pdev->dev, info->reg_base); devm_release_mem_region(&pdev->dev, - info->res.start, resource_size(&info->res)); + info->res.start, + resource_size(&info->res)); pr_error("Canvas driver removed.\n"); return 0; diff --git a/drivers/amlogic/media/common/canvas/canvas_mgr.c b/drivers/amlogic/media/common/canvas/canvas_mgr.c index cfe6837..d564e64 100644 --- a/drivers/amlogic/media/common/canvas/canvas_mgr.c +++ b/drivers/amlogic/media/common/canvas/canvas_mgr.c @@ -25,6 +25,7 @@ #include #include +#include #include /*ignore canvas 0, @@ -63,11 +64,13 @@ canvas_pool_map_alloc_canvas_in(struct canvas_pool *pool, const char *owner) do { i = find_next_zero_bit(pool->canvas_map, - sizeof(pool->canvas_map), start_index); + pool->canvas_max, + start_index); if (!VALID_CANVAS(i)) { if (!looped) { start_index = 1; looped = 1; + continue; } else return -1; } @@ -105,7 +108,8 @@ int canvas_pool_map_alloc_canvas(const char *owner) */ static int canvas_pool_map_alloc_canvas_continue_set(struct canvas_pool *pool, - const char *owner, u32 *canvas, enum canvas_map_type_e type) + const char *owner, u32 *canvas, + enum canvas_map_type_e type) { int found_retry = 0; int found = 0; @@ -395,11 +399,12 @@ canvas_pool_map_show(struct class *class, test_bit(i, pool->canvas_map), info.fixed_onwer, o1, o2, info.alloc_time); size += snprintf(buf + size, PAGE_SIZE - size, - "\taddr=%08x,\ts=%d X %d,\trap=%d,\tmod=%d\n", - (unsigned int)canvas.addr, - (int)canvas.width, - (int)canvas.height, - (int)canvas.wrap, (int)canvas.blkmode); + "\taddr=%08x,\ts=%d X %d,\trap=%d,\tmod=%d\n", + (unsigned int)canvas.addr, + (int)canvas.width, + (int)canvas.height, + (int)canvas.wrap, + (int)canvas.blkmode); } pool->next_dump_index = i; if (pool->next_dump_index >= pool->canvas_max) @@ -415,18 +420,23 @@ canvas_pool_states_show(struct class *class, ssize_t size = 0; int i; struct canvas_pool *pool = get_canvas_pool(); - - size += snprintf(buf + size, PAGE_SIZE - size, "canvas tatol num: %d\n", - pool->canvas_max); - size += snprintf(buf + size, PAGE_SIZE - size, - "canvas next_dump_index: %d\n", pool->next_dump_index); - size += snprintf(buf + size, PAGE_SIZE - size, - "canvas next_alloced_index: %d\n", pool->next_alloced_index); + size += snprintf(buf + size, PAGE_SIZE - size, "canvas total num: %d\n", + pool->canvas_max); + size += + snprintf(buf + size, PAGE_SIZE - size, + "canvas next_dump_index: %d\n", pool->next_dump_index); + size += + snprintf(buf + size, PAGE_SIZE - size, + "canvas next_alloced_index: %d\n", + pool->next_alloced_index); size += snprintf(buf + size, PAGE_SIZE - size, "canvas map:\n"); - for (i = 0; i < sizeof(pool->canvas_map) / (8 * sizeof(u32)); i++) - size += snprintf(buf + size, PAGE_SIZE - size, - "% 3d - % 3d : %08x\n", i * 32, (i + 1) * 32 - 1, - (u32) pool->canvas_map[i]); + for (i = 0; i < CANVAS_MAX_NUM / BITS_PER_LONG; i++) + size += + snprintf(buf + size, PAGE_SIZE - size, + "% 3d - % 3d : %0lx\n", + i * BITS_PER_LONG, + (i + 1) * BITS_PER_LONG - 1, + (ulong) pool->canvas_map[i]); return size; } @@ -439,14 +449,15 @@ canvas_pool_debug_show(struct class *class, size += snprintf(buf + size, PAGE_SIZE - size, "help: echo n > canvas_pool_debug\n"); size += snprintf(buf + size, PAGE_SIZE - size, "1:next_dump_index=0\n"); - size += snprintf(buf + size, PAGE_SIZE - size, - "2:next_alloced_index=0\n"); + size += + snprintf(buf + size, PAGE_SIZE - size, "2:next_alloced_index=0\n"); return size; } static ssize_t canvas_pool_debug_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) + struct class_attribute *attr, const char *buf, + size_t size) { unsigned int val; ssize_t ret = 0; @@ -507,10 +518,13 @@ static void canvas_pool_config(void) canvas_pool_register_const_canvas(0x26, 0x39, "vdin"); canvas_pool_register_const_canvas(0x78, 0xbf, "amvdec"); canvas_pool_register_const_canvas(0x60, 0x65, "display"); + canvas_pool_register_const_canvas(0x66, 0x6b, "display2"); canvas_pool_register_const_canvas(0x70, 0x77, "ppmgr"); canvas_pool_register_const_canvas(0xe4, 0xef, "encoder"); canvas_pool_register_const_canvas(0x40, 0x48, "osd"); +#ifdef CONFIG_AMLOGIC_VIDEOIN_MANAGER canvas_pool_register_const_canvas(0x4e, 0x5f, "vm"); +#endif canvas_pool_register_const_canvas(0xc0, 0xd7, "amlvideo2"); /*please add static canvas later. */ } diff --git a/drivers/amlogic/media/common/codec_mm/Makefile b/drivers/amlogic/media/common/codec_mm/Makefile index 0260ebf..5c3293e 100644 --- a/drivers/amlogic/media/common/codec_mm/Makefile +++ b/drivers/amlogic/media/common/codec_mm/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_AMLOGIC_MEDIA_CODEC_MM) += codec_mm.o obj-$(CONFIG_AMLOGIC_MEDIA_CODEC_MM) += codec_mm_scatter.o obj-$(CONFIG_AMLOGIC_MEDIA_CODEC_MM) += codec_mm_keeper.o +obj-$(CONFIG_AMLOGIC_MEDIA_CODEC_MM) += configs/ diff --git a/drivers/amlogic/media/common/codec_mm/codec_mm.c b/drivers/amlogic/media/common/codec_mm/codec_mm.c index 1690238..7307227 100644 --- a/drivers/amlogic/media/common/codec_mm/codec_mm.c +++ b/drivers/amlogic/media/common/codec_mm/codec_mm.c @@ -36,6 +36,7 @@ #include #include +#include #include "codec_mm_priv.h" #include "codec_mm_scatter_priv.h" @@ -44,7 +45,14 @@ #define TVP_POOL_NAME "TVP_POOL" #define CMA_RES_POOL_NAME "CMA_RES" +#define CONFIG_PATH "media.codec_mm" +#define CONFIG_PREFIX "media" + + + #define RES_IS_MAPED +#define DEFAULT_TVP_SIZE_FOR_4K (256 * SZ_1M) +#define DEFAULT_TVP_SIZE_FOR_NO4K (160 * SZ_1M) #define ALLOC_MAX_RETRY 1 @@ -90,16 +98,18 @@ u32 codec_mm_get_keep_debug_mode(void) } EXPORT_SYMBOL(codec_mm_get_keep_debug_mode); +static int default_tvp_size; +static int default_tvp_4k_size; +static int default_cma_res_size; + #define TVP_MAX_SLOT 8 struct extpool_mgt_s { struct gen_pool *gen_pool[TVP_MAX_SLOT]; struct codec_mm_s *mm[TVP_MAX_SLOT]; int slot_num; - int default_size; - int default_4k_size; int alloced_size; int total_size; - spinlock_t lock; + struct mutex pool_lock; }; struct codec_mm_mgt_s { @@ -259,6 +269,7 @@ static int codec_mm_alloc_in( int try_cma_first = mem->flags & CODEC_MM_FLAGS_CMA_FIRST; int max_retry = ALLOC_MAX_RETRY; int have_space; + int alloc_trace_mask = 0; int can_from_res = ((mgt->res_pool != NULL) && /*have res */ !(mem->flags & CODEC_MM_FLAGS_CMA)) || /*must not CMA */ @@ -302,9 +313,11 @@ static int codec_mm_alloc_in( if ((mem->flags & CODEC_MM_FLAGS_DMA_CPU) && mem->page_count <= mgt->alloc_from_sys_pages_max && align_2n <= PAGE_SHIFT) { + alloc_trace_mask |= 1 << 0; mem->mem_handle = (void *)__get_free_pages(GFP_KERNEL, get_order(mem->buffer_size)); - mem->from_flags = AMPORTS_MEM_FLAGS_FROM_GET_FROM_PAGES; + mem->from_flags = + AMPORTS_MEM_FLAGS_FROM_GET_FROM_PAGES; if (mem->mem_handle) { mem->vbuffer = mem->mem_handle; mem->phy_addr = virt_to_phys(mem->mem_handle); @@ -317,6 +330,7 @@ static int codec_mm_alloc_in( /* *normal cma. */ + alloc_trace_mask |= 1 << 1; mem->mem_handle = dma_alloc_from_contiguous(mgt->dev, mem->page_count, align_2n - PAGE_SHIFT); @@ -324,8 +338,7 @@ static int codec_mm_alloc_in( if (mem->mem_handle) { mem->vbuffer = mem->mem_handle; mem->phy_addr = - page_to_phys((struct page *) - mem->mem_handle); + page_to_phys((struct page *)mem->mem_handle); #ifdef CONFIG_ARM64 if (mem->flags & CODEC_MM_FLAGS_CMA_CLEAR) { /*dma_clear_buffer((struct page *)*/ @@ -335,13 +348,14 @@ static int codec_mm_alloc_in( break; } } - /*reserved alloc.. */ - if (can_from_res && (align_2n <= RESERVE_MM_ALIGNED_2N)) { + /*reserved alloc..*/ + if (can_from_res && + (align_2n <= RESERVE_MM_ALIGNED_2N)) { int aligned_buffer_size = ALIGN(mem->buffer_size, (1 << RESERVE_MM_ALIGNED_2N)); - mem->mem_handle = - (void *)gen_pool_alloc(mgt->res_pool, - aligned_buffer_size); + alloc_trace_mask |= 1 << 2; + mem->mem_handle = (void *)gen_pool_alloc(mgt->res_pool, + aligned_buffer_size); mem->from_flags = AMPORTS_MEM_FLAGS_FROM_GET_FROM_REVERSED; if (mem->mem_handle) { @@ -364,7 +378,8 @@ static int codec_mm_alloc_in( */ int aligned_buffer_size = ALIGN(mem->buffer_size, - (1 << RESERVE_MM_ALIGNED_2N)); + (1 << RESERVE_MM_ALIGNED_2N)); + alloc_trace_mask |= 1 << 3; mem->mem_handle = (void *)codec_mm_extpool_alloc( &mgt->cma_res_pool, @@ -387,14 +402,15 @@ static int codec_mm_alloc_in( /* *normal cma. */ + alloc_trace_mask |= 1 << 4; mem->mem_handle = dma_alloc_from_contiguous(mgt->dev, - mem->page_count, align_2n - PAGE_SHIFT); + mem->page_count, + align_2n - PAGE_SHIFT); mem->from_flags = AMPORTS_MEM_FLAGS_FROM_GET_FROM_CMA; if (mem->mem_handle) { mem->vbuffer = mem->mem_handle; mem->phy_addr = - page_to_phys((struct page *) - mem->mem_handle); + page_to_phys((struct page *)mem->mem_handle); #ifdef CONFIG_ARM64 if (mem->flags & CODEC_MM_FLAGS_CMA_CLEAR) { /*dma_clear_buffer((struct page *)*/ @@ -404,14 +420,18 @@ static int codec_mm_alloc_in( break; } } - if (can_from_tvp && align_2n <= RESERVE_MM_ALIGNED_2N) { + if (can_from_tvp && + align_2n <= RESERVE_MM_ALIGNED_2N) { /* 64k,aligend */ int aligned_buffer_size = ALIGN(mem->buffer_size, - (1 << RESERVE_MM_ALIGNED_2N)); - mem->mem_handle = - (void *)codec_mm_extpool_alloc(&mgt->tvp_pool, - &mem->from_ext, aligned_buffer_size); - mem->from_flags = AMPORTS_MEM_FLAGS_FROM_GET_FROM_TVP; + (1 << RESERVE_MM_ALIGNED_2N)); + alloc_trace_mask |= 1 << 5; + mem->mem_handle = (void *)codec_mm_extpool_alloc( + &mgt->tvp_pool, + &mem->from_ext, + aligned_buffer_size); + mem->from_flags = + AMPORTS_MEM_FLAGS_FROM_GET_FROM_TVP; if (mem->mem_handle) { /*no vaddr for TVP MEMORY */ mem->vbuffer = NULL; @@ -422,10 +442,13 @@ static int codec_mm_alloc_in( } if ((mem->flags & CODEC_MM_FLAGS_DMA_CPU) && - mgt->enable_kmalloc_on_nomem && !try_alloced_from_sys) { + mgt->enable_kmalloc_on_nomem && + !try_alloced_from_sys) { + alloc_trace_mask |= 1 << 6; mem->mem_handle = (void *)__get_free_pages(GFP_KERNEL, get_order(mem->buffer_size)); - mem->from_flags = AMPORTS_MEM_FLAGS_FROM_GET_FROM_PAGES; + mem->from_flags = + AMPORTS_MEM_FLAGS_FROM_GET_FROM_PAGES; if (mem->mem_handle) { mem->vbuffer = mem->mem_handle; mem->phy_addr = @@ -436,11 +459,30 @@ static int codec_mm_alloc_in( } while (--max_retry > 0); if (mem->mem_handle) return 0; - else + else { + if (debug_mode & 0x10) { + pr_info("codec mm have space:%x\n", + have_space); + pr_info("canfrom: %d,%d,%d,%d\n", + can_from_tvp, + can_from_sys, + can_from_res, + can_from_cma); + pr_info("alloc flags:%d,align=%d,%d,pages:%d,s:%d\n", + mem->flags, + mem->align2n, + align_2n, + mem->page_count, + mem->buffer_size); + pr_info("try alloc mask:%x\n", + alloc_trace_mask); + } return -10003; + } } -static void codec_mm_free_in(struct codec_mm_mgt_s *mgt, struct codec_mm_s *mem) +static void codec_mm_free_in(struct codec_mm_mgt_s *mgt, + struct codec_mm_s *mem) { if (!(mem->flags & CODEC_MM_FLAGS_FOR_LOCAL_MGR)) mgt->total_alloced_size -= mem->buffer_size; @@ -459,16 +501,20 @@ static void codec_mm_free_in(struct codec_mm_mgt_s *mgt, struct codec_mm_s *mem) (unsigned long)mem->mem_handle, mem->buffer_size); mgt->alloced_res_size -= mem->buffer_size; } else if (mem->from_flags == AMPORTS_MEM_FLAGS_FROM_GET_FROM_TVP) { - codec_mm_extpool_free((struct gen_pool *)mem->from_ext, - mem->mem_handle, mem->buffer_size); + codec_mm_extpool_free( + (struct gen_pool *)mem->from_ext, + mem->mem_handle, + mem->buffer_size); mgt->tvp_pool.alloced_size -= mem->buffer_size; } else if (mem->from_flags == AMPORTS_MEM_FLAGS_FROM_GET_FROM_PAGES) { free_pages((unsigned long)mem->mem_handle, get_order(mem->buffer_size)); mgt->alloced_sys_size -= mem->buffer_size; } else if (mem->from_flags == AMPORTS_MEM_FLAGS_FROM_GET_FROM_CMA_RES) { - codec_mm_extpool_free((struct gen_pool *)mem->from_ext, - mem->mem_handle, mem->buffer_size); + codec_mm_extpool_free( + (struct gen_pool *)mem->from_ext, + mem->mem_handle, + mem->buffer_size); mgt->cma_res_pool.alloced_size -= mem->buffer_size; } @@ -489,13 +535,19 @@ struct codec_mm_s *codec_mm_alloc(const char *owner, int size, return NULL; } - if ((mgt->tvp_enable & 3) && (memflags & CODEC_MM_FLAGS_FOR_VDECODER)) { - /* - *if tvp & video decoder used tvp memory. - *Audio don't protect for default now. - */ - memflags = memflags & (~CODEC_MM_FLAGS_FROM_MASK); - memflags |= CODEC_MM_FLAGS_TVP; + if (mgt->tvp_enable & 3) { + /*if tvp & video decoder used tvp memory.*/ + /*Audio don't protect for default now.*/ + if (memflags & CODEC_MM_FLAGS_TVP) { + /*clear other flags, when tvp mode.*/ + memflags = memflags & (~CODEC_MM_FLAGS_FROM_MASK); + memflags |= CODEC_MM_FLAGS_TVP; + } + } else { /*tvp not enabled*/ + if (memflags & CODEC_MM_FLAGS_TVP) { + pr_err("TVP not enabled, when alloc from tvp %s need %d\n", + owner, size); + } } if ((memflags & CODEC_MM_FLAGS_FROM_MASK) == 0) memflags |= CODEC_MM_FLAGS_DMA; @@ -512,12 +564,16 @@ struct codec_mm_s *codec_mm_alloc(const char *owner, int size, !(memflags & CODEC_MM_FLAGS_FOR_SCATTER)) { /*if not scatter, free scatter caches. */ pr_err(" No mem ret=%d, clear scatter cache!!\n", ret); - codec_mm_scatter_free_all_ignorecache(); + codec_mm_scatter_free_all_ignorecache(1); ret = codec_mm_alloc_in(mgt, mem); } if (ret < 0) { pr_err("not enough mem for %s size %d, ret=%d\n", - owner, size, ret); + owner, size, ret); + pr_err("mem flags %d %d, %d\n", + memflags, + mem->flags, + align2n); kfree(mem); if (debug_mode & 0x10) dump_mem_infos(NULL, 0); @@ -559,10 +615,12 @@ struct codec_mm_s *codec_mm_alloc(const char *owner, int size, mgt->alloced_for_sc_cnt++; } spin_unlock_irqrestore(&mgt->lock, flags); + mem->alloced_jiffies = get_jiffies_64(); if (debug_mode & 0x20) - pr_err("%s alloc mem size %d at %lx from %d\n", + pr_err("%s alloc mem size %d at %lx from %d,flags:%d\n", owner, size, mem->phy_addr, - mem->from_flags); + mem->from_flags, + memflags); return mem; } EXPORT_SYMBOL(codec_mm_alloc); @@ -624,12 +682,12 @@ EXPORT_SYMBOL(codec_mm_dma_free_coherent); void codec_mm_release_with_check(struct codec_mm_s *mem, const char *owner) { + struct codec_mm_mgt_s *mgt = get_mem_mgt(); unsigned long flags; int ret; - - spin_lock_irqsave(&mem->lock, flags); + spin_lock_irqsave(&mgt->lock, flags); ret = codec_mm_valid_mm_locked(mem); - spin_unlock_irqrestore(&mem->lock, flags); + spin_unlock_irqrestore(&mgt->lock, flags); if (ret) { /*for check,*/ return codec_mm_release(mem, owner); @@ -637,7 +695,9 @@ void codec_mm_release_with_check(struct codec_mm_s *mem, const char *owner) } EXPORT_SYMBOL(codec_mm_release_with_check); -void codec_mm_dma_flush(void *vaddr, int size, enum dma_data_direction dir) +void codec_mm_dma_flush(void *vaddr, + int size, + enum dma_data_direction dir) { struct codec_mm_mgt_s *mgt = get_mem_mgt(); dma_addr_t dma_addr; @@ -697,13 +757,37 @@ unsigned long codec_mm_alloc_for_dma(const char *owner, int page_cnt, struct codec_mm_s *mem; mem = codec_mm_alloc(owner, page_cnt << PAGE_SHIFT, align2n, memflags); - if (!mem) return 0; return mem->phy_addr; } EXPORT_SYMBOL(codec_mm_alloc_for_dma); +unsigned long codec_mm_alloc_for_dma_ex( + const char *owner, + int page_cnt, + int align2n, + int memflags, + int ins_id, + int buffer_id) +{ + struct codec_mm_s *mem; + + mem = codec_mm_alloc(owner, page_cnt << PAGE_SHIFT, align2n, memflags); + if (!mem) + return 0; + mem->ins_id = ins_id; + mem->ins_buffer_id = buffer_id; + if (debug_mode & 0x20) { + pr_err("%s, for ins %d, buffer id:%d\n", + mem->owner[0] ? mem->owner[0] : "no", + mem->ins_id, + buffer_id); + } + return mem->phy_addr; +} +EXPORT_SYMBOL(codec_mm_alloc_for_dma_ex); + int codec_mm_free_for_dma(const char *owner, unsigned long phy_addr) { struct codec_mm_s *mem; @@ -718,8 +802,9 @@ int codec_mm_free_for_dma(const char *owner, unsigned long phy_addr) } EXPORT_SYMBOL(codec_mm_free_for_dma); -static int codec_mm_init_tvp_pool(struct extpool_mgt_s *tvp_pool, - struct codec_mm_s *mm) +static int codec_mm_init_tvp_pool( + struct extpool_mgt_s *tvp_pool, + struct codec_mm_s *mm) { struct gen_pool *pool; int ret; @@ -737,27 +822,32 @@ static int codec_mm_init_tvp_pool(struct extpool_mgt_s *tvp_pool, return 0; } -int codec_mm_extpool_pool_alloc(struct extpool_mgt_s *tvp_pool, +int codec_mm_extpool_pool_alloc( + struct extpool_mgt_s *tvp_pool, int size, int memflags, int for_tvp) { struct codec_mm_mgt_s *mgt = get_mem_mgt(); struct codec_mm_s *mem; - int alloced_size = tvp_pool->alloced_size; + int alloced_size = tvp_pool->total_size; int try_alloced_size = size; int ret; /*alloced from reserved*/ + mutex_lock(&tvp_pool->pool_lock); try_alloced_size = mgt->total_reserved_size - mgt->alloced_res_size; if (try_alloced_size > 0 && for_tvp) { try_alloced_size = min_t(int, size - alloced_size, try_alloced_size); mem = codec_mm_alloc(TVP_POOL_NAME, - try_alloced_size, - 0, - CODEC_MM_FLAGS_FOR_LOCAL_MGR | CODEC_MM_FLAGS_RESERVED); + try_alloced_size, + 0, + CODEC_MM_FLAGS_FOR_LOCAL_MGR | + CODEC_MM_FLAGS_RESERVED); if (mem) { - ret = codec_mm_init_tvp_pool(tvp_pool, mem); + ret = codec_mm_init_tvp_pool( + tvp_pool, + mem); if (ret < 0) { codec_mm_release(mem, TVP_POOL_NAME); } else { @@ -787,7 +877,9 @@ int codec_mm_extpool_pool_alloc(struct extpool_mgt_s *tvp_pool, CODEC_MM_FLAGS_CMA); if (mem) { - ret = codec_mm_init_tvp_pool(tvp_pool, mem); + ret = codec_mm_init_tvp_pool( + tvp_pool, + mem); if (ret < 0) { codec_mm_release(mem, TVP_POOL_NAME); } else { @@ -798,11 +890,10 @@ int codec_mm_extpool_pool_alloc(struct extpool_mgt_s *tvp_pool, } alloced_finished: - if (alloced_size > 0) { + if (alloced_size > 0) tvp_pool->total_size = alloced_size; - return alloced_size; - } - return -1; + mutex_unlock(&tvp_pool->pool_lock); + return alloced_size; } EXPORT_SYMBOL(codec_mm_extpool_pool_alloc); @@ -817,7 +908,7 @@ static int codec_mm_extpool_pool_release(struct extpool_mgt_s *tvp_pool) struct codec_mm_mgt_s *mgt = get_mem_mgt(); int i; int ignored = 0; - + mutex_lock(&tvp_pool->pool_lock); for (i = 0; i < tvp_pool->slot_num; i++) { struct gen_pool *gpool = tvp_pool->gen_pool[i]; int slot_mem_size = 0; @@ -860,6 +951,7 @@ static int codec_mm_extpool_pool_release(struct extpool_mgt_s *tvp_pool) } tvp_pool->slot_num = ignored; + mutex_unlock(&tvp_pool->pool_lock); return ignored; } @@ -968,20 +1060,25 @@ static int dump_mem_infos(void *buf, int size) int tsize = 0; int s; - if (!pbuf) + if (!pbuf) { pbuf = sbuf; - s = sprintf(pbuf, "codec mem info:\n\ttotal codec mem size:%d MB\n", + size = 512; + } + s = snprintf(pbuf, size - tsize, + "codec mem info:\n\ttotal codec mem size:%d MB\n", mgt->total_codec_mem_size / SZ_1M); tsize += s; pbuf += s; - s = sprintf(pbuf, "\talloced size= %d MB\n\tmax alloced: %d MB\n", + s = snprintf(pbuf, size - tsize, + "\talloced size= %d MB\n\tmax alloced: %d MB\n", mgt->total_alloced_size / SZ_1M, mgt->max_used_mem_size / SZ_1M); tsize += s; pbuf += s; - s = sprintf(pbuf, "\tCMA:%d,RES:%d,TVP:%d,SYS:%d MB\n", + s = snprintf(pbuf, size - tsize, + "\tCMA:%d,RES:%d,TVP:%d,SYS:%d MB\n", mgt->alloced_cma_size / SZ_1M, mgt->alloced_res_size / SZ_1M, mgt->tvp_pool.alloced_size / SZ_1M, @@ -990,7 +1087,7 @@ static int dump_mem_infos(void *buf, int size) pbuf += s; if (mgt->res_pool) { - s = sprintf(pbuf, + s = snprintf(pbuf, size - tsize, "\t[%d]RES size:%d MB,alloced:%d MB free:%d MB\n", AMPORTS_MEM_FLAGS_FROM_GET_FROM_REVERSED, (int)(gen_pool_size(mgt->res_pool) / SZ_1M), @@ -1000,17 +1097,18 @@ static int dump_mem_infos(void *buf, int size) pbuf += s; } - s = sprintf(pbuf, "\t[%d]CMA size:%d MB:alloced: %d MB,free:%d MB\n", - AMPORTS_MEM_FLAGS_FROM_GET_FROM_CMA, - (int)(dma_get_cma_size_int_byte(mgt->dev) / SZ_1M), - (int)(mgt->alloced_cma_size / SZ_1M), - (int)((dma_get_cma_size_int_byte(mgt->dev) - - mgt->alloced_cma_size) / SZ_1M)); + s = snprintf(pbuf, size - tsize, + "\t[%d]CMA size:%d MB:alloced: %d MB,free:%d MB\n", + AMPORTS_MEM_FLAGS_FROM_GET_FROM_CMA, + (int)(dma_get_cma_size_int_byte(mgt->dev) / SZ_1M), + (int)(mgt->alloced_cma_size / SZ_1M), + (int)((dma_get_cma_size_int_byte(mgt->dev) - + mgt->alloced_cma_size) / SZ_1M)); tsize += s; pbuf += s; if (mgt->tvp_pool.slot_num > 0) { - s = sprintf(pbuf, + s = snprintf(pbuf, size - tsize, "\t[%d]TVP size:%d MB,alloced:%d MB free:%d MB\n", AMPORTS_MEM_FLAGS_FROM_GET_FROM_TVP, (int)(mgt->tvp_pool.total_size / SZ_1M), @@ -1021,14 +1119,13 @@ static int dump_mem_infos(void *buf, int size) pbuf += s; } if (mgt->cma_res_pool.slot_num > 0) { - s = sprintf(pbuf, + s = snprintf(pbuf, size - tsize, "\t[%d]CMA_RES size:%d MB,alloced:%d MB free:%d MB\n", - AMPORTS_MEM_FLAGS_FROM_GET_FROM_CMA_RES, - (int)(mgt->cma_res_pool.total_size / SZ_1M), - (int)(mgt->cma_res_pool.alloced_size / SZ_1M), - (int)((mgt->cma_res_pool.total_size - - mgt->cma_res_pool.alloced_size) / - SZ_1M)); + AMPORTS_MEM_FLAGS_FROM_GET_FROM_CMA_RES, + (int)(mgt->cma_res_pool.total_size / SZ_1M), + (int)(mgt->cma_res_pool.alloced_size / SZ_1M), + (int)((mgt->cma_res_pool.total_size - + mgt->cma_res_pool.alloced_size) / SZ_1M)); tsize += s; pbuf += s; } @@ -1045,23 +1142,35 @@ static int dump_mem_infos(void *buf, int size) return tsize; } list_for_each_entry(mem, &mgt->mem_list, list) { - s = sprintf(pbuf, - "\towner:[%d] %s:%s,addr=%p,s=%d,from=%d,cnt=%d\n", - mem->mem_id, - mem->owner[0] ? mem->owner[0] : "no", - mem->owner[1] ? mem->owner[1] : "no", - (void *)mem->phy_addr, - mem->buffer_size, mem->from_flags, - atomic_read(&mem->use_cnt)); + s = snprintf(pbuf, size - tsize, + "\t[%d].%d:%s.%d,addr=%p,size=%d,from=%d,cnt=%d,", + mem->mem_id, + mem->ins_id, + mem->owner[0] ? mem->owner[0] : "no", + mem->ins_buffer_id, + (void *)mem->phy_addr, + mem->buffer_size, + mem->from_flags, + atomic_read(&mem->use_cnt) + ); + s += snprintf(pbuf + s, size - tsize, + "flags=%d,used:%lld ms\n", + mem->flags, + (get_jiffies_64() - mem->alloced_jiffies) * 100/HZ); + tsize += s; if (buf) { pbuf += s; - if (tsize + s > size - 128) - break; /*no memory for dump now. */ + if (tsize > size - 256) { + s += snprintf(pbuf + s, size - tsize, + "\n\t\t**NOT END**\n"); + tsize += s; + break;/*no memory for dump now.*/ + } } else { pr_info("%s", sbuf); + tsize = 0; } - tsize += s; } spin_unlock_irqrestore(&mgt->lock, flags); @@ -1107,8 +1216,8 @@ EXPORT_SYMBOL(codec_mm_get_total_size); int codec_mm_get_free_size(void) { struct codec_mm_mgt_s *mgt = get_mem_mgt(); - - return codec_mm_get_total_size() - mgt->total_alloced_size; + return codec_mm_get_total_size() - + mgt->total_alloced_size; } EXPORT_SYMBOL(codec_mm_get_free_size); @@ -1132,7 +1241,7 @@ int codec_mm_enough_for_size(int size, int with_wait) if (!have_mem && with_wait && mgt->alloced_for_sc_cnt > 0) { pr_err(" No mem, clear scatter cache!!\n"); - codec_mm_scatter_free_all_ignorecache(); + codec_mm_scatter_free_all_ignorecache(1); have_mem = codec_mm_alloc_pre_check_in(mgt, size, 0); if (have_mem) return 1; @@ -1164,7 +1273,8 @@ int codec_mm_mgt_init(struct device *dev) (~((1 << RESERVE_MM_ALIGNED_2N) - 1)); aligned_size = mgt->rmem.size - (int)(aligned_addr - (unsigned long)mgt->rmem.base); - gen_pool_add(mgt->res_pool, aligned_addr, aligned_size, -1); + gen_pool_add(mgt->res_pool, + aligned_addr, aligned_size, -1); pr_debug("add reserve memory %p(aligned %p) size=%x(aligned %x)\n", (void *)mgt->rmem.base, (void *)aligned_addr, (int)mgt->rmem.size, (int)aligned_size); @@ -1177,14 +1287,19 @@ int codec_mm_mgt_init(struct device *dev) mgt->total_cma_size = dma_get_cma_size_int_byte(mgt->dev); mgt->total_codec_mem_size += mgt->total_cma_size; /*2M for audio not protect.*/ - mgt->tvp_pool.default_4k_size = mgt->total_codec_mem_size - SZ_1M * 2; + default_tvp_4k_size = mgt->total_codec_mem_size - SZ_1M * 2; + if (default_tvp_4k_size > DEFAULT_TVP_SIZE_FOR_4K) + default_tvp_4k_size = DEFAULT_TVP_SIZE_FOR_4K; /*97MB -> 160MB, may not enough for h265*/ - mgt->tvp_pool.default_size = mgt->total_codec_mem_size > SZ_1M * 160 ? - SZ_1M * 160 : mgt->tvp_pool.default_4k_size; + default_tvp_size = (mgt->total_codec_mem_size - (SZ_1M * 2)) > + DEFAULT_TVP_SIZE_FOR_NO4K ? + DEFAULT_TVP_SIZE_FOR_NO4K : + default_tvp_4k_size; - mgt->cma_res_pool.default_size = mgt->total_cma_size; - mgt->cma_res_pool.default_4k_size = mgt->total_cma_size; + default_cma_res_size = mgt->total_cma_size; mgt->global_memid = 0; + mutex_init(&mgt->tvp_pool.pool_lock); + mutex_init(&mgt->cma_res_pool.pool_lock); spin_lock_init(&mgt->lock); return 0; } @@ -1273,7 +1388,8 @@ static ssize_t codec_mm_keeper_dump_show(struct class *class, } static ssize_t tvp_enable_help_show(struct class *class, - struct class_attribute *attr, char *buf) + struct class_attribute *attr, + char *buf) { ssize_t size = 0; @@ -1288,7 +1404,8 @@ static ssize_t tvp_enable_help_show(struct class *class, } static ssize_t tvp_enable_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) + struct class_attribute *attr, + const char *buf, size_t size) { struct codec_mm_mgt_s *mgt = get_mem_mgt(); unsigned int val; @@ -1304,7 +1421,7 @@ static ssize_t tvp_enable_store(struct class *class, tvp changes. */ codec_mm_keeper_free_all_keep(2); - codec_mm_scatter_free_all_ignorecache(); + codec_mm_scatter_free_all_ignorecache(3); switch (val) { case 0: ret = codec_mm_extpool_pool_release(&mgt->tvp_pool); @@ -1312,14 +1429,16 @@ static ssize_t tvp_enable_store(struct class *class, pr_info("disalbe tvp\n"); break; case 1: - codec_mm_extpool_pool_alloc(&mgt->tvp_pool, - mgt->tvp_pool.default_size, 0, 1); + codec_mm_extpool_pool_alloc( + &mgt->tvp_pool, + default_tvp_size, 0, 1); mgt->tvp_enable = 1; pr_info("enable tvp for 1080p\n"); break; case 2: - codec_mm_extpool_pool_alloc(&mgt->tvp_pool, - mgt->tvp_pool.default_4k_size, 0, 1); + codec_mm_extpool_pool_alloc( + &mgt->tvp_pool, + default_tvp_4k_size, 0, 1); mgt->tvp_enable = 2; pr_info("enable tvp for 4k\n"); break; @@ -1330,7 +1449,8 @@ static ssize_t tvp_enable_store(struct class *class, } static ssize_t fastplay_enable_help_show(struct class *class, - struct class_attribute *attr, char *buf) + struct class_attribute *attr, + char *buf) { ssize_t size = 0; @@ -1343,7 +1463,8 @@ static ssize_t fastplay_enable_help_show(struct class *class, } static ssize_t fastplay_enable_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) + struct class_attribute *attr, + const char *buf, size_t size) { struct codec_mm_mgt_s *mgt = get_mem_mgt(); unsigned int val; @@ -1361,8 +1482,9 @@ static ssize_t fastplay_enable_store(struct class *class, pr_err("disalbe fastplay\n"); break; case 1: - codec_mm_extpool_pool_alloc(&mgt->cma_res_pool, - mgt->cma_res_pool.default_4k_size, 0, 0); + codec_mm_extpool_pool_alloc( + &mgt->cma_res_pool, + default_cma_res_size, 0, 0); mgt->fastplay_enable = 1; pr_err("enable fastplay\n"); break; @@ -1375,38 +1497,23 @@ static ssize_t fastplay_enable_store(struct class *class, static ssize_t codec_mm_config_show(struct class *class, struct class_attribute *attr, char *buf) { - struct codec_mm_mgt_s *mgt = get_mem_mgt(); - size_t ret; + ssize_t ret; - ret = sprintf(buf, - "default_tvp_size:0x%x(%d MB)\n", - mgt->tvp_pool.default_size, mgt->tvp_pool.default_size / SZ_1M); - ret += sprintf(buf + ret, - "default_tvp_4k_size:0x%x(%d MB)\n", - mgt->tvp_pool.default_4k_size, - mgt->tvp_pool.default_4k_size / SZ_1M); - ret += codec_mm_scatter_mgt_get_config(buf + ret); + ret = configs_list_path_nodes(CONFIG_PATH, buf, PAGE_SIZE, + LIST_MODE_NODE_CMDVAL_ALL); return ret; } static ssize_t codec_mm_config_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t size) + struct class_attribute *attr, + const char *buf, size_t size) { - struct codec_mm_mgt_s *mgt = get_mem_mgt(); - unsigned int val; - ssize_t ret; + int ret; - ret = sscanf(buf, "default_tvp_size:0x%x", &val); - if (ret == 1) { - mgt->tvp_pool.default_size = val; - return size; - } - ret = sscanf(buf, "default_tvp_4k_size:0x%x", &val); - if (ret == 1) { - mgt->tvp_pool.default_4k_size = val; - return size; - } - return codec_mm_scatter_mgt_set_config(buf, size); + ret = configs_set_prefix_path_valonpath(CONFIG_PREFIX, buf); + if (ret < 0) + pr_err("set config failed %s\n", buf); + return size; } static ssize_t tvp_region_show(struct class *class, @@ -1542,6 +1649,9 @@ static ssize_t codec_mm_debug_store(struct class *class, case 10: codec_mm_keeper_free_all_keep(1); break; + case 11: + dump_mem_infos(NULL, 0); + break; case 20: { int cmd, len; unsigned int addr; @@ -1585,10 +1695,80 @@ static struct class_attribute codec_mm_class_attrs[] = { }; static struct class codec_mm_class = { - .name = "codec_mm", - .class_attrs = codec_mm_class_attrs, + .name = "codec_mm", + .class_attrs = codec_mm_class_attrs, + }; + +static struct mconfig codec_mm_configs[] = { + MC_PI32("default_tvp_size", &default_tvp_size), + MC_PI32("default_tvp_4k_size", &default_tvp_4k_size), + MC_PI32("default_cma_res_size", &default_cma_res_size), +}; +static struct mconfig_node codec_mm_trigger_node; +int codec_mm_trigger_fun(const char *trigger, int id, const char *buf, int size) +{ + int ret = size; + + switch (trigger[0]) { + case 't': + tvp_enable_store(NULL, NULL, buf, size); + break; + case 'f': + fastplay_enable_store(NULL, NULL, buf, size); + break; + case 'd': + codec_mm_debug_store(NULL, NULL, buf, size); + break; + default: + ret = -1; + } + return size; +} +int codec_mm_trigger_help_fun(const char *trigger, int id, char *sbuf, int size) +{ + int ret = -1; + void *buf, *getbuf = NULL; + + if (size < PAGE_SIZE) { + void *getbuf = (void *)__get_free_page(GFP_KERNEL); + + if (!getbuf) + return -ENOMEM; + buf = getbuf; + } else { + buf = sbuf; + } + switch (trigger[0]) { + case 't': + ret = tvp_enable_help_show(NULL, NULL, buf); + break; + case 'f': + ret = fastplay_enable_help_show(NULL, NULL, buf); + break; + case 'd': + ret = codec_mm_debug_show(NULL, NULL, buf); + break; + default: + pr_err("unknown trigger:[%s]\n", trigger); + ret = -1; + } + if (ret > 0 && getbuf != NULL) { + int ret = min_t(int, ret, size); + + strncpy(sbuf, buf, ret); + } + if (getbuf != NULL) + free_page((unsigned long)getbuf); + return ret; +} + +static struct mconfig codec_mm_trigger[] = { + MC_FUN("tvp_enable", codec_mm_trigger_help_fun, codec_mm_trigger_fun), + MC_FUN("fastplay", codec_mm_trigger_help_fun, codec_mm_trigger_fun), + MC_FUN("debug", codec_mm_trigger_help_fun, codec_mm_trigger_fun), }; + static int codec_mm_probe(struct platform_device *pdev) { @@ -1615,6 +1795,9 @@ static int codec_mm_probe(struct platform_device *pdev) codec_mm_keeper_mgr_init(); amstream_test_init(); codec_mm_scatter_mgt_test(); + REG_PATH_CONFIGS(CONFIG_PATH, codec_mm_configs); + INIT_REG_NODE_CONFIGS(CONFIG_PATH, &codec_mm_trigger_node, + "trigger", codec_mm_trigger, CONFIG_FOR_RW | CONFIG_FOR_T); return 0; } diff --git a/drivers/amlogic/media/common/codec_mm/codec_mm_priv.h b/drivers/amlogic/media/common/codec_mm/codec_mm_priv.h index 2bd7ca6..32cc094 100644 --- a/drivers/amlogic/media/common/codec_mm/codec_mm_priv.h +++ b/drivers/amlogic/media/common/codec_mm/codec_mm_priv.h @@ -52,10 +52,6 @@ extern void dma_clear_buffer(struct page *page, size_t size); -struct codec_mm_s *codec_mm_alloc(const char *owner, int size, - int align2n, int memflags); -void codec_mm_release(struct codec_mm_s *mem, const char *owner); -u32 get_codec_mm_profiles(void); u32 codec_mm_get_sc_debug_mode(void); u32 codec_mm_get_keep_debug_mode(void); diff --git a/drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c b/drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c index ed539cf..1505625 100644 --- a/drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c +++ b/drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "codec_mm_priv.h" #include "codec_mm_scatter_priv.h" @@ -113,25 +114,43 @@ #endif #define MAX_SC_LIST 64 +#define MK_TAG(a, b, c, d) (((a) << 24) | ((b) << 16) |\ + ((c) << 8) | d) +#define SMGT_IDENTIFY_TAG MK_TAG('Z', 'S', 'C', 'Z') + +struct codec_mm_scatter_s { + u32 keep_size_PAGE; + u32 reserved_block_mm_M; + u32 try_alloc_in_cma_page_cnt; + u32 try_alloc_in_sys_page_cnt_max; + u32 try_alloc_in_sys_page_cnt_min; + u32 enable_slot_from_sys; + u32 no_cache_size_M; + u32 support_from_slot_sys; +}; + struct codec_mm_scatter_mgt { + unsigned int tag;/*=*/ struct codec_mm_slot *slot_list_map[MAX_SID]; + int tvp_mode; int codec_mm_num; int total_page_num; int alloced_page_num; int max_alloced; - int try_alloc_in_cma_page_cnt; - int try_alloc_in_sys_page_cnt; - int try_alloc_in_sys_page_cnt_max; - int try_alloc_in_sys_page_cnt_min; + u32 try_alloc_in_cma_page_cnt; + u32 try_alloc_in_sys_page_cnt; + u32 try_alloc_in_sys_page_cnt_max; + u32 try_alloc_in_sys_page_cnt_min; int alloc_from_cma_first; - int enable_slot_from_sys; - int no_cache_size_M; - int support_from_slot_sys; + u32 enable_slot_from_sys; + u32 no_cache_size_M; + u32 support_from_slot_sys; int one_page_cnt; int scatters_cnt; int slot_cnt; - int reserved_block_mm_M; - int keep_size_PAGE; + u32 reserved_block_mm_M; + u32 keep_size_PAGE; + int mem_flags; int alloc_from_sys_sc_cnt; int alloc_from_sys_page_cnt; @@ -165,12 +184,19 @@ struct codec_mm_scatter_mgt { struct codec_mm_scatter *scmap[MAX_SC_LIST];/*used for valid check. */ }; +static struct codec_mm_scatter_s g_scatter; static struct codec_mm_scatter_mgt *scatter_mgt; - -static struct codec_mm_scatter_mgt *codec_mm_get_scatter_mgt(void) +static struct codec_mm_scatter_mgt *scatter_tvp_mgt; +static struct codec_mm_scatter_mgt *codec_mm_get_scatter_mgt( + int is_tvp) { + if (is_tvp) + return scatter_tvp_mgt; return scatter_mgt; } +static int codec_mm_scatter_valid_locked( + struct codec_mm_scatter_mgt *smgt, + struct codec_mm_scatter *mms); /*#define MY_MUTEX_DEBUG*/ #ifdef MY_MUTEX_DEBUG @@ -261,22 +287,25 @@ static inline void codec_mm_list_unlock( } static int codec_mm_scatter_alloc_want_pages_in( + struct codec_mm_scatter_mgt *smgt, struct codec_mm_scatter *mms, int want_pages); static struct workqueue_struct *codec_mm_scatter_wq_get(void) { - static struct workqueue_struct *codec_mm_scatter; + static struct workqueue_struct *codec_mm_scatter_wq; - if (!codec_mm_scatter) - codec_mm_scatter = create_singlethread_workqueue("codec_mm_sc"); - return codec_mm_scatter; + if (!codec_mm_scatter_wq) { + codec_mm_scatter_wq = + create_singlethread_workqueue("codec_mm_sc"); + } + return codec_mm_scatter_wq; } -static int codec_mm_schedule_delay_work(int delay_ms, int for_update) +static int codec_mm_schedule_delay_work(struct codec_mm_scatter_mgt *smgt, + int delay_ms, int for_update) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); bool ret; if (!for_update && delayed_work_pending(&smgt->dealy_work)) return 0; @@ -299,9 +328,9 @@ static inline u64 codec_mm_get_current_us(void) return div64_u64(timeval_to_ns(&tv), 1000); } -static void codec_mm_update_alloc_time(u64 startus) +static void codec_mm_update_alloc_time( + struct codec_mm_scatter_mgt *smgt, u64 startus) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); int spend_time_us; spend_time_us = (int)(codec_mm_get_current_us() - startus); @@ -332,10 +361,9 @@ static void codec_mm_update_alloc_time(u64 startus) } } -void codec_mm_clear_alloc_infos(void) +static void codec_mm_clear_alloc_infos_in( + struct codec_mm_scatter_mgt *smgt) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); - smgt->alloc_cnt = 0; smgt->alloc_10us_less_cnt = 0; smgt->alloc_10_50us_cnt = 0; @@ -347,11 +375,17 @@ void codec_mm_clear_alloc_infos(void) smgt->alloc_total_us = 0; smgt->alloc_max_us = 0; } +void codec_mm_clear_alloc_infos(void) +{ + codec_mm_clear_alloc_infos_in(codec_mm_get_scatter_mgt(0)); + codec_mm_clear_alloc_infos_in(codec_mm_get_scatter_mgt(1)); +} -static int codec_mm_set_slot_in_hash(struct codec_mm_slot *slot) +static int codec_mm_set_slot_in_hash( + struct codec_mm_scatter_mgt *smgt, + struct codec_mm_slot *slot) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); page_sid_type sid = SLOT_TO_SID(slot); @@ -388,9 +422,9 @@ static int codec_mm_set_slot_in_hash(struct codec_mm_slot *slot) } static struct codec_mm_slot *codec_mm_find_slot_in_hash( + struct codec_mm_scatter_mgt *smgt, page_sid_type sid, ulong addr) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); struct codec_mm_slot *fslot, *slot; if (!VALID_SID(sid)) @@ -430,9 +464,10 @@ err: return NULL; } -static int codec_mm_slot_free(struct codec_mm_slot *slot) +static int codec_mm_slot_free( + struct codec_mm_scatter_mgt *smgt, + struct codec_mm_slot *slot) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); int ret = 0; codec_mm_list_lock(smgt); @@ -487,11 +522,10 @@ static int codec_mm_slot_free(struct codec_mm_slot *slot) kfree(slot); return 0; } - -static int codec_mm_slot_try_free(struct codec_mm_slot *slot) +static int codec_mm_slot_try_free( + struct codec_mm_scatter_mgt *smgt, + struct codec_mm_slot *slot) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); - if (smgt->keep_size_PAGE > 0) { /*delay free, when size < delay_free_M MB */ int free_pages = smgt->total_page_num - smgt->alloced_page_num; @@ -499,7 +533,7 @@ static int codec_mm_slot_try_free(struct codec_mm_slot *slot) if (free_pages < smgt->keep_size_PAGE) return -1; } - return codec_mm_slot_free(slot); + return codec_mm_slot_free(smgt, slot); } static inline int codec_mm_slot_init_bitmap(struct codec_mm_slot *slot) @@ -523,9 +557,10 @@ static inline int codec_mm_slot_init_bitmap(struct codec_mm_slot *slot) /* *flags : 1. don't used codecmm. */ -static struct codec_mm_slot *codec_mm_slot_alloc(int size, int flags) +static struct codec_mm_slot *codec_mm_slot_alloc( + struct codec_mm_scatter_mgt *smgt, + int size, int flags) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); struct codec_mm_slot *slot; struct codec_mm_s *mm; int try_alloc_size = size; @@ -553,9 +588,12 @@ static struct codec_mm_slot *codec_mm_slot_alloc(int size, int flags) if (codec_mm_get_free_size() < try_alloc_size) try_alloc_size = codec_mm_get_free_size(); mm = codec_mm_alloc(SCATTER_MEM, try_alloc_size, 0, - CODEC_MM_FLAGS_CMA_FIRST | - CODEC_MM_FLAGS_FOR_VDECODER | - CODEC_MM_FLAGS_FOR_SCATTER); + CODEC_MM_FLAGS_CMA_FIRST | + CODEC_MM_FLAGS_FOR_VDECODER | + CODEC_MM_FLAGS_FOR_SCATTER | + (smgt->tvp_mode ? + CODEC_MM_FLAGS_TVP : 0) + ); if (mm != NULL) { slot->from_type = SLOT_FROM_CODEC_MM; slot->mm = mm; @@ -588,8 +626,8 @@ static struct codec_mm_slot *codec_mm_slot_alloc(int size, int flags) goto error; /*don't alloc 1 page with slot. */ } } - if (!have_alloced && codec_mm_video_tvp_enabled()) { - /*tvp not support alloc from sys. */ + if (!have_alloced && smgt->tvp_mode) { + /*tvp not support alloc from sys.*/ goto error; } while (!have_alloced) { @@ -629,7 +667,7 @@ static struct codec_mm_slot *codec_mm_slot_alloc(int size, int flags) have_alloced = 1; break; } - codec_mm_set_slot_in_hash(slot); + codec_mm_set_slot_in_hash(smgt, slot); return slot; error: @@ -637,9 +675,10 @@ error: return NULL; } -static int codec_mm_slot_free_page(struct codec_mm_slot *slot, ulong phy_addr) +static int codec_mm_slot_free_page( + struct codec_mm_scatter_mgt *smgt, + struct codec_mm_slot *slot, ulong phy_addr) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); int bit; if (!slot || !slot->pagemap || slot->page_num <= 0) @@ -663,10 +702,11 @@ static int codec_mm_slot_free_page(struct codec_mm_slot *slot, ulong phy_addr) return 0; } -static int codec_mm_slot_alloc_pages(struct codec_mm_slot *slot, - phy_addr_type *pages, int num) +static int codec_mm_slot_alloc_pages( + struct codec_mm_scatter_mgt *smgt, + struct codec_mm_slot *slot, + phy_addr_type *pages, int num) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); int alloced = 0; int need = num; int can_alloced; @@ -740,23 +780,24 @@ static inline page_sid_type codec_mm_get_page_sid( return PAGE_SID(page); } -static int codec_mm_page_free_to_slot(page_sid_type sid, ulong addr) +static int codec_mm_page_free_to_slot( + struct codec_mm_scatter_mgt *smgt, + page_sid_type sid, ulong addr) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); struct codec_mm_slot *slot; int ret; int slot_free = 0; - slot = codec_mm_find_slot_in_hash(sid, addr); + slot = codec_mm_find_slot_in_hash(smgt, sid, addr); if (!slot) return -1; - ret = codec_mm_slot_free_page(slot, addr); + ret = codec_mm_slot_free_page(smgt, slot, addr); if (ret != 0) ERR_LOG("free slot addr error =%p ret=%d\n", (void *)addr, ret); if (slot->alloced_page_num == 0) - slot_free = (codec_mm_slot_try_free(slot) == 0); + slot_free = (codec_mm_slot_try_free(smgt, slot) == 0); if (!slot_free) { /*move to have free list. */ codec_mm_list_lock(smgt); @@ -773,9 +814,10 @@ static int codec_mm_page_free_to_slot(page_sid_type sid, ulong addr) return 0; } -static int codec_mm_page_alloc_from_one_pages(phy_addr_type *pages, int num) +static int codec_mm_page_alloc_from_one_pages( + struct codec_mm_scatter_mgt *smgt, + phy_addr_type *pages, int num) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); int neednum = num; int alloced = 0; @@ -805,9 +847,10 @@ static int codec_mm_page_alloc_from_one_pages(phy_addr_type *pages, int num) return alloced; } -static int codec_mm_page_alloc_from_slot(phy_addr_type *pages, int num) +static int codec_mm_page_alloc_from_slot( + struct codec_mm_scatter_mgt *smgt, + phy_addr_type *pages, int num) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); struct codec_mm_slot *slot = NULL; int alloced = 0; int neednum = num; @@ -828,8 +871,8 @@ static int codec_mm_page_alloc_from_slot(phy_addr_type *pages, int num) if (smgt->total_page_num <= 0 || /*no codec mm. */ smgt->alloced_page_num == smgt->total_page_num || list_empty(&smgt->free_list)) { - /*codec_mm_scatter_info_dump(NULL, 0); */ - slot = codec_mm_slot_alloc(0, 0); + /*codec_mm_scatter_info_dump(NULL, 0);*/ + slot = codec_mm_slot_alloc(smgt, 0, 0); if (!slot) { /* *ERR_LOG("can't alloc slot from system\n"); @@ -862,7 +905,8 @@ static int codec_mm_page_alloc_from_slot(phy_addr_type *pages, int num) } codec_mm_list_unlock(smgt); if (slot) { - n = codec_mm_slot_alloc_pages(slot, + n = codec_mm_slot_alloc_pages(smgt, + slot, &pages[alloced], neednum); codec_mm_list_lock(smgt); slot->on_alloc_free--; /*alloc use end */ @@ -918,9 +962,9 @@ static int codec_mm_page_alloc_from_slot(phy_addr_type *pages, int num) static int codec_mm_page_alloc_from_free_scatter( + struct codec_mm_scatter_mgt *smgt, phy_addr_type *pages, int num) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); struct codec_mm_scatter *mms; int need = num; int alloced = 0; @@ -955,6 +999,7 @@ static int codec_mm_page_alloc_from_free_scatter( } static int codec_mm_page_alloc_all_locked( + struct codec_mm_scatter_mgt *smgt, phy_addr_type *pages, int num, int iscache) { int alloced = 0; @@ -966,18 +1011,21 @@ static int codec_mm_page_alloc_all_locked( new_alloc = 0; if (can_from_scatter) { new_alloc = codec_mm_page_alloc_from_free_scatter( + smgt, pages + alloced, num - alloced); if (new_alloc <= 0) can_from_scatter = 0; } else if (can_from_slot) { new_alloc = codec_mm_page_alloc_from_slot( + smgt, pages + alloced, num - alloced); if (new_alloc <= 0) can_from_slot = 0; - } else if (!codec_mm_video_tvp_enabled()) { + } else if (!smgt->tvp_mode) { new_alloc = codec_mm_page_alloc_from_one_pages( + smgt, pages + alloced, num - alloced); if (new_alloc <= 0) @@ -991,9 +1039,9 @@ static int codec_mm_page_alloc_all_locked( } static int codec_mm_pages_free_to_scatter( + struct codec_mm_scatter_mgt *smgt, struct codec_mm_scatter *src_mms) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); struct codec_mm_scatter *dst_mms; int moved = 0; int left; @@ -1025,40 +1073,15 @@ static int codec_mm_pages_free_to_scatter( return moved; } -#if 0 - -/* -*return: -*1:for valid; -*0:no valid mms. -*must check in -*codec_mm_list_lock -*/ -static int codec_mm_scatter_valid_check_inlock(struct codec_mm_scatter *mms) -{ - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); - struct list_head *pos, *to_check_list; - if (!mms) - return 0; - to_check_list = &mms->list; - if (list_empty(&smgt->scatter_list)) - return 0; - list_for_each(pos, &smgt->scatter_list) { - if (pos == to_check_list) - return 1; - } - return 0; -} -#endif /* *free one page in mms; */ static int codec_mm_scatter_free_page_id_locked( + struct codec_mm_scatter_mgt *smgt, struct codec_mm_scatter *mms, int id) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); page_sid_type sid; int ret; @@ -1078,7 +1101,7 @@ static int codec_mm_scatter_free_page_id_locked( mms->page_cnt--; return 0; } - ret = codec_mm_page_free_to_slot(sid, PAGE_ADDR_OF_MMS(mms, id)); + ret = codec_mm_page_free_to_slot(smgt, sid, PAGE_ADDR_OF_MMS(mms, id)); if (!ret) { mms->page_cnt--; mms->page_tail--; @@ -1089,10 +1112,12 @@ static int codec_mm_scatter_free_page_id_locked( /* *free one page in mms; */ -static int codec_mm_scatter_free_pages_in_locked(struct codec_mm_scatter *mms, +static int codec_mm_scatter_free_pages_in_locked( + struct codec_mm_scatter *mms, int start_id) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); + struct codec_mm_scatter_mgt *smgt = + (struct codec_mm_scatter_mgt *)mms->manager; int i; int ret; int id = start_id; @@ -1100,7 +1125,7 @@ static int codec_mm_scatter_free_pages_in_locked(struct codec_mm_scatter *mms, int not_continue_print = 1; for (i = mms->page_tail; i >= id; i--) { - ret = codec_mm_scatter_free_page_id_locked(mms, i); + ret = codec_mm_scatter_free_page_id_locked(smgt, mms, i); if (ret < 0) { if (not_continue_print) { ERR_LOG("page free error.%d,id=%d, addr:%d\n", @@ -1130,13 +1155,14 @@ static int codec_mm_scatter_free_tail_pages_in( int fast) { int id = start_free_id; - + struct codec_mm_scatter_mgt *smgt; if (!mms || id < 0 || id >= mms->page_cnt || mms->page_tail < 0) { if (mms) ERR_LOG("free mm scatters error id %d,page_cnt=%d\n", id, mms->page_cnt); return -1; } + smgt = (struct codec_mm_scatter_mgt *)mms->manager; codec_mm_scatter_lock(mms); mms->page_used = start_free_id; @@ -1145,7 +1171,7 @@ static int codec_mm_scatter_free_tail_pages_in( return 0; } if (fast == 2 || fast == 3) { - codec_mm_pages_free_to_scatter(mms); + codec_mm_pages_free_to_scatter(smgt, mms); if (fast == 2 || mms->page_used == mms->page_cnt) { codec_mm_scatter_unlock(mms); return 0; @@ -1156,27 +1182,34 @@ static int codec_mm_scatter_free_tail_pages_in( return 0; } -int codec_mm_scatter_free_tail_pages(struct codec_mm_scatter *mms, - int start_free_id) +int codec_mm_scatter_free_tail_pages( + struct codec_mm_scatter *mms, + int start_free_id) { int ret = 0; if (start_free_id < mms->page_cnt) - ret = codec_mm_scatter_free_tail_pages_in(mms, + ret = codec_mm_scatter_free_tail_pages_in( + mms, start_free_id, 0); return ret; } EXPORT_SYMBOL(codec_mm_scatter_free_tail_pages); -int codec_mm_scatter_free_tail_pages_fast(struct codec_mm_scatter *mms, +int codec_mm_scatter_free_tail_pages_fast( + struct codec_mm_scatter *mms, int start_free_id) { int ret = 0; - + if (!mms) + return -1; if (start_free_id < mms->page_cnt) - ret = codec_mm_scatter_free_tail_pages_in(mms, - start_free_id, 2); - codec_mm_schedule_delay_work(100, 0); + ret = codec_mm_scatter_free_tail_pages_in( + mms, + start_free_id, 2); + codec_mm_schedule_delay_work( + (struct codec_mm_scatter_mgt *)mms->manager, + 100, 0); return ret; } EXPORT_SYMBOL(codec_mm_scatter_free_tail_pages_fast); @@ -1205,9 +1238,9 @@ int codec_mm_scatter_free_all_pages(struct codec_mm_scatter *mms) EXPORT_SYMBOL(codec_mm_scatter_free_all_pages); static inline int codec_mm_scatter_map_add_locked( + struct codec_mm_scatter_mgt *smgt, struct codec_mm_scatter *mms) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); int i; for (i = 0; i < MAX_SC_LIST; i++) { @@ -1220,9 +1253,9 @@ static inline int codec_mm_scatter_map_add_locked( } static inline int codec_mm_scatter_map_del_locked( + struct codec_mm_scatter_mgt *smgt, struct codec_mm_scatter *mms) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); int i; for (i = 0; i < MAX_SC_LIST; i++) { @@ -1234,9 +1267,10 @@ static inline int codec_mm_scatter_map_del_locked( return 0; } -int codec_mm_scatter_valid_locked(struct codec_mm_scatter *mms) +int codec_mm_scatter_valid_locked( + struct codec_mm_scatter_mgt *smgt, + struct codec_mm_scatter *mms) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); int i; int valid = 0; @@ -1251,9 +1285,11 @@ int codec_mm_scatter_valid_locked(struct codec_mm_scatter *mms) EXPORT_SYMBOL(codec_mm_scatter_valid_locked); /*free scatter's all */ -static int codec_mm_scatter_free_on_nouser(struct codec_mm_scatter *mms) +static int codec_mm_scatter_free_on_nouser_ext( + struct codec_mm_scatter_mgt *smgt, + struct codec_mm_scatter *mms, + int not_in_mgt) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); int ret = 0; int free; @@ -1271,8 +1307,11 @@ static int codec_mm_scatter_free_on_nouser(struct codec_mm_scatter *mms) free = mms->page_cnt; if (!list_empty(&mms->list)) list_del(&mms->list); - smgt->scatters_cnt--; - codec_mm_scatter_map_del_locked(mms); + if (!not_in_mgt) { + smgt->scatters_cnt--; + codec_mm_scatter_map_del_locked(smgt, mms); + } + codec_mm_list_unlock(smgt); codec_mm_scatter_unlock(mms); if (mms->page_cnt > 0) @@ -1291,6 +1330,14 @@ static int codec_mm_scatter_free_on_nouser(struct codec_mm_scatter *mms) SC_FREE(mms); return ret; } +/*free scatter's all */ +static int codec_mm_scatter_free_on_nouser( + struct codec_mm_scatter_mgt *smgt, + struct codec_mm_scatter *mms) +{ + return codec_mm_scatter_free_on_nouser_ext( + smgt, mms, 0); +} /* *mask for other use it. @@ -1298,14 +1345,17 @@ static int codec_mm_scatter_free_on_nouser(struct codec_mm_scatter *mms) static int codec_mm_scatter_inc_user_in(struct codec_mm_scatter *mms, int cnt) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); + struct codec_mm_scatter_mgt *smgt; int ret = -1; int old_user; if (!mms) return -1; + smgt = (struct codec_mm_scatter_mgt *)mms->manager; + if (smgt->tag != SMGT_IDENTIFY_TAG) + return -2;/*not valid tag*/ codec_mm_list_lock(smgt); - if (!codec_mm_scatter_valid_locked(mms)) { + if (!codec_mm_scatter_valid_locked(smgt, mms)) { codec_mm_list_unlock(smgt); return -1; } @@ -1320,16 +1370,20 @@ static int codec_mm_scatter_inc_user_in(struct codec_mm_scatter *mms, } /*mask scatter's to free.*/ -static int codec_mm_scatter_dec_user_in(struct codec_mm_scatter *mms, - int delay_free_ms, int cnt) +static int codec_mm_scatter_dec_user_in( + struct codec_mm_scatter *mms, + int delay_free_ms, int cnt) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); + struct codec_mm_scatter_mgt *smgt; int after_users = 1; if (!mms) return -1; + smgt = (struct codec_mm_scatter_mgt *)mms->manager; + if (smgt->tag != SMGT_IDENTIFY_TAG) + return -2;/*not valid tag*/ codec_mm_list_lock(smgt); - if (!codec_mm_scatter_valid_locked(mms)) { + if (!codec_mm_scatter_valid_locked(smgt, mms)) { codec_mm_list_unlock(smgt); return -1; } @@ -1348,7 +1402,7 @@ static int codec_mm_scatter_dec_user_in(struct codec_mm_scatter *mms, } codec_mm_list_unlock(smgt); if (after_users == 0) - codec_mm_schedule_delay_work(0, 1); + codec_mm_schedule_delay_work(smgt, 0, 1); return 0; } @@ -1392,9 +1446,11 @@ EXPORT_SYMBOL(codec_mm_scatter_dec_owner_user); * max pages == support 4k,need pages; * page num = current size need pages; */ -struct codec_mm_scatter *codec_mm_scatter_alloc_new(int max_page, int page_num) +struct codec_mm_scatter *codec_mm_scatter_alloc_new( + struct codec_mm_scatter_mgt *smgt, + int max_page, + int page_num) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); struct codec_mm_scatter *mms; int ret; @@ -1414,11 +1470,13 @@ struct codec_mm_scatter *codec_mm_scatter_alloc_new(int max_page, int page_num) memset(mms->pages_list, 0, sizeof(phy_addr_type) * max_page); mms->page_cnt = 0; mms->page_tail = -1; + mms->manager = (void *)smgt; atomic_set(&mms->user_cnt, 0); mutex_init(&mms->mutex); if (page_num > 0) { - ret = codec_mm_page_alloc_all_locked(mms->pages_list, page_num, - mms == smgt->cache_sc); + ret = codec_mm_page_alloc_all_locked(smgt, + mms->pages_list, page_num, + mms == smgt->cache_sc); if (ret <= 0) goto error; mms->page_cnt = ret; @@ -1429,11 +1487,11 @@ struct codec_mm_scatter *codec_mm_scatter_alloc_new(int max_page, int page_num) mms->page_used = mms->page_cnt; list_add_tail(&mms->list, &smgt->scatter_list); smgt->scatters_cnt++; - codec_mm_scatter_map_add_locked(mms); + codec_mm_scatter_map_add_locked(smgt, mms); codec_mm_list_unlock(smgt); return mms; error: - codec_mm_scatter_free_on_nouser(mms); + codec_mm_scatter_free_on_nouser_ext(smgt, mms, 1); return NULL; } EXPORT_SYMBOL(codec_mm_scatter_alloc_new); @@ -1445,14 +1503,17 @@ EXPORT_SYMBOL(codec_mm_scatter_alloc_new); * max pages == support 4k,need pages; * page num = current size need pages; */ -struct codec_mm_scatter *codec_mm_scatter_alloc(int max_page, int page_num) +struct codec_mm_scatter *codec_mm_scatter_alloc( + int max_page, int page_num, + int istvp) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); + struct codec_mm_scatter_mgt *smgt; struct codec_mm_scatter *mms, *alloced_mms; struct list_head *pos, *next; int ret; u64 startus; + smgt = codec_mm_get_scatter_mgt(istvp); startus = codec_mm_get_current_us(); alloced_mms = NULL; codec_mm_list_lock(smgt); @@ -1480,17 +1541,17 @@ struct codec_mm_scatter *codec_mm_scatter_alloc(int max_page, int page_num) *just alloc mms first, *alloc pages later. */ - alloced_mms = codec_mm_scatter_alloc_new(max_page, 0); + alloced_mms = codec_mm_scatter_alloc_new(smgt, max_page, 0); } if (alloced_mms) { - ret = codec_mm_scatter_alloc_want_pages_in(alloced_mms, + ret = codec_mm_scatter_alloc_want_pages_in(smgt, alloced_mms, page_num); if (ret < 0) { atomic_sub(1000, &alloced_mms->user_cnt); return NULL; } /*pr_info("reused old mms! %p\n", alloced_mms);*/ - codec_mm_update_alloc_time(startus); + codec_mm_update_alloc_time(smgt, startus); return alloced_mms; } return NULL; @@ -1498,10 +1559,10 @@ struct codec_mm_scatter *codec_mm_scatter_alloc(int max_page, int page_num) EXPORT_SYMBOL(codec_mm_scatter_alloc); static int codec_mm_scatter_alloc_want_pages_in( - struct codec_mm_scatter *mms, - int want_pages) + struct codec_mm_scatter_mgt *smgt, + struct codec_mm_scatter *mms, + int want_pages) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); int ret; if (want_pages > mms->page_max_cnt) @@ -1510,6 +1571,7 @@ static int codec_mm_scatter_alloc_want_pages_in( mms->page_used = want_pages; if (want_pages > mms->page_cnt) { ret = codec_mm_page_alloc_all_locked( + smgt, &mms->pages_list[mms->page_tail + 1], want_pages - mms->page_cnt, mms == smgt->cache_sc); @@ -1530,7 +1592,7 @@ static int codec_mm_scatter_alloc_want_pages_in( codec_mm_scatter_unlock(mms); if (smgt->cached_pages < smgt->keep_size_PAGE / 2) { /*try alloc more cache.*/ - codec_mm_schedule_delay_work(0, 1); + codec_mm_schedule_delay_work(smgt, 0, 1); } return 0; } @@ -1539,19 +1601,22 @@ int codec_mm_scatter_alloc_want_pages( struct codec_mm_scatter *mms, int want_pages) { + struct codec_mm_scatter_mgt *smgt; int ret; u64 startus; - + if (!mms) + return -1; + smgt = (struct codec_mm_scatter_mgt *)mms->manager; startus = codec_mm_get_current_us(); - ret = codec_mm_scatter_alloc_want_pages_in(mms, want_pages); - codec_mm_update_alloc_time(startus); + ret = codec_mm_scatter_alloc_want_pages_in( + smgt, mms, want_pages); + codec_mm_update_alloc_time(smgt, startus); return ret; } EXPORT_SYMBOL(codec_mm_scatter_alloc_want_pages); -int codec_mm_free_all_free_slots(void) +int codec_mm_free_all_free_slots_in(struct codec_mm_scatter_mgt *smgt) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); struct codec_mm_slot *slot, *to_free; do { @@ -1576,15 +1641,23 @@ int codec_mm_free_all_free_slots(void) codec_mm_list_unlock(smgt); if (!to_free) break; - codec_mm_slot_free(to_free); + codec_mm_slot_free(smgt, to_free); } while (1); return 0; } EXPORT_SYMBOL(codec_mm_free_all_free_slots); -int codec_mm_scatter_info_dump(void *buf, int size) +int codec_mm_free_all_free_slots(void) +{ + codec_mm_free_all_free_slots_in(codec_mm_get_scatter_mgt(0)); + codec_mm_free_all_free_slots_in(codec_mm_get_scatter_mgt(1)); + return 0; +} + +static int codec_mm_scatter_info_dump_in( + struct codec_mm_scatter_mgt *smgt, + void *buf, int size) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); char *pbuf = buf; char sbuf[512]; int tsize = 0; @@ -1601,7 +1674,8 @@ int codec_mm_scatter_info_dump(void *buf, int size) pbuf += s; \ } while (0) - BUFPRINT("codec scattered memory info:\n"); + BUFPRINT("codec %sscattered memory info:\n", + smgt->tvp_mode ? "TVP " : ""); BUFPRINT("\ttotal size:%dM, %d Bytes,pages:%d\n", (smgt->total_page_num << PAGE_SHIFT) / SZ_1M, smgt->total_page_num << PAGE_SHIFT, @@ -1670,6 +1744,28 @@ int codec_mm_scatter_info_dump(void *buf, int size) } EXPORT_SYMBOL(codec_mm_scatter_info_dump); +int codec_mm_scatter_info_dump( + void *buf, int size) +{ + char *pbuf = buf; + int esize = size; + int ret; + + ret = codec_mm_scatter_info_dump_in( + codec_mm_get_scatter_mgt(0), + pbuf, + esize); + if (buf != NULL && ret > 0) { + pbuf += ret; + esize -= ret; + } + ret += codec_mm_scatter_info_dump_in( + codec_mm_get_scatter_mgt(1), + pbuf, + esize); + return ret; +} + int codec_mm_dump_slot(struct codec_mm_slot *slot, void *buf, int size) { char *pbuf = buf; @@ -1726,9 +1822,8 @@ int codec_mm_dump_slot(struct codec_mm_slot *slot, void *buf, int size) } EXPORT_SYMBOL(codec_mm_dump_slot); -int codec_mm_dump_all_slots(void) +int codec_mm_dump_all_slots_in(struct codec_mm_scatter_mgt *smgt) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); struct codec_mm_slot *slot, *fslot; int total_pages = 0; int alloced_pages = 0; @@ -1768,9 +1863,17 @@ int codec_mm_dump_all_slots(void) } EXPORT_SYMBOL(codec_mm_dump_all_slots); -int codec_mm_dump_all_hash_table(void) +int codec_mm_dump_all_slots(void) +{ + codec_mm_dump_all_slots_in(codec_mm_get_scatter_mgt(0)); + codec_mm_dump_all_slots_in(codec_mm_get_scatter_mgt(1)); + return 0; +} + + +int codec_mm_dump_all_hash_table_in( + struct codec_mm_scatter_mgt *smgt) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); struct codec_mm_slot *slot, *fslot; int i; int total_pages = 0; @@ -1815,9 +1918,16 @@ int codec_mm_dump_all_hash_table(void) } EXPORT_SYMBOL(codec_mm_dump_all_hash_table); -int codec_mm_dump_free_slots(void) +int codec_mm_dump_all_hash_table(void) +{ + codec_mm_dump_all_hash_table_in(codec_mm_get_scatter_mgt(0)); + codec_mm_dump_all_hash_table_in(codec_mm_get_scatter_mgt(1)); + return 0; +} + + +static int codec_mm_dump_free_slots_in(struct codec_mm_scatter_mgt *smgt) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); struct codec_mm_slot *slot; int total_pages = 0; int alloced_pages = 0; @@ -1846,7 +1956,16 @@ int codec_mm_dump_free_slots(void) } EXPORT_SYMBOL(codec_mm_dump_free_slots); -int codec_mm_dump_scatter(struct codec_mm_scatter *mms, void *buf, int size) +int codec_mm_dump_free_slots(void) +{ + codec_mm_dump_free_slots_in(codec_mm_get_scatter_mgt(0)); + codec_mm_dump_free_slots_in(codec_mm_get_scatter_mgt(1)); + return 0; +} + +int codec_mm_dump_scatter( + struct codec_mm_scatter *mms, + void *buf, int size) { char *pbuf = buf; char sbuf[512]; @@ -1886,9 +2005,8 @@ int codec_mm_dump_scatter(struct codec_mm_scatter *mms, void *buf, int size) } EXPORT_SYMBOL(codec_mm_dump_scatter); -int codec_mm_dump_all_scatters(void) +static int codec_mm_dump_all_scatters_in(struct codec_mm_scatter_mgt *smgt) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); struct codec_mm_scatter *mms; struct list_head *pos, *tmp; @@ -1911,137 +2029,39 @@ int codec_mm_dump_all_scatters(void) } EXPORT_SYMBOL(codec_mm_dump_all_scatters); -struct sc_configs { - int id; - const char *name; -}; - -enum config_id { - ID0_KEEP_SIZE, - ID1_RES_BLK_SIZEM, - ID2_ONCE_CMA_SIZEM, - ID3_MAX_SYS_PAGES, - ID4_MIN_SYS_PAGES, - ID5_SLOT_FROM_SYS, - ID6_NO_CACHE_SIZE, - IDX_MAX, -}; -struct sc_configs sc_global_config[] = { - {ID0_KEEP_SIZE, "keep_size"}, - {ID1_RES_BLK_SIZEM, "res_blk_size"}, - {ID2_ONCE_CMA_SIZEM, "once_cma_size"}, - {ID3_MAX_SYS_PAGES, "max_sys_pages"}, - {ID4_MIN_SYS_PAGES, "min_sys_pages"}, - {ID5_SLOT_FROM_SYS, "enable_slot_from_sys"}, - {ID6_NO_CACHE_SIZE, "no_cache_size_M"}, -}; - -static int codec_mm_scatter_mgt_get_config_in(int id) -{ - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); - - switch (id) { - case ID0_KEEP_SIZE: - return (smgt->keep_size_PAGE << PAGE_SHIFT) / SZ_1M; - case ID1_RES_BLK_SIZEM: - return smgt->reserved_block_mm_M; - case ID2_ONCE_CMA_SIZEM: - return smgt->try_alloc_in_cma_page_cnt; - case ID3_MAX_SYS_PAGES: - return smgt->try_alloc_in_sys_page_cnt_max; - case ID4_MIN_SYS_PAGES: - return smgt->try_alloc_in_sys_page_cnt_min; - case ID5_SLOT_FROM_SYS: - return smgt->enable_slot_from_sys; - case ID6_NO_CACHE_SIZE: - return smgt->no_cache_size_M; - default: - return 0; - } - return -1; -} - -static int codec_mm_scatter_mgt_set_config_in(int id, int newset) +int codec_mm_dump_all_scatters(void) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); - int val; - - switch (id) { - case ID0_KEEP_SIZE: - val = newset * (SZ_1M >> PAGE_SHIFT); - smgt->keep_size_PAGE = val; - break; - case ID1_RES_BLK_SIZEM: - smgt->reserved_block_mm_M = newset; - break; - case ID2_ONCE_CMA_SIZEM: - smgt->try_alloc_in_cma_page_cnt = newset; - break; - case ID3_MAX_SYS_PAGES: - smgt->try_alloc_in_sys_page_cnt_max = newset; - break; - case ID4_MIN_SYS_PAGES: - smgt->try_alloc_in_sys_page_cnt_min = newset; - break; - case ID5_SLOT_FROM_SYS: - smgt->enable_slot_from_sys = newset; - smgt->support_from_slot_sys = newset; - break; - case ID6_NO_CACHE_SIZE: - smgt->no_cache_size_M = newset; - break; - default: - return -1; - } + codec_mm_dump_all_scatters_in(codec_mm_get_scatter_mgt(0)); + codec_mm_dump_all_scatters_in(codec_mm_get_scatter_mgt(1)); return 0; } -int codec_mm_scatter_mgt_get_config(char *buf) -{ - size_t ret = 0; - int i; - for (i = 0; i < IDX_MAX; i++) { - ret += sprintf(buf + ret, - "scatter:%s:%d\n", - sc_global_config[i].name, - codec_mm_scatter_mgt_get_config_in(i)); - } - return ret; -} -EXPORT_SYMBOL(codec_mm_scatter_mgt_get_config); -int codec_mm_scatter_mgt_set_config(const char *buf, size_t size) +int codec_mm_scatter_update_config(struct codec_mm_scatter_mgt *smgt) { - size_t ret = 0; - char *str; - int i; - int val; - - for (i = 0; i < IDX_MAX; i++) { - str = strstr(buf, sc_global_config[i].name); - if (!str) - continue; /*to next. */ - str += strlen(sc_global_config[i].name); - if (str[0] != ':' || str[1] == '\0') - continue; /*to next. */ - ret = sscanf(str, ":%d", &val); - if (ret == 1) { - codec_mm_scatter_mgt_set_config_in(i, val); - return size; - } - } - pr_info("unknown cmd %s\n", buf); - return -1; + smgt->keep_size_PAGE = g_scatter.keep_size_PAGE; + smgt->reserved_block_mm_M = g_scatter.reserved_block_mm_M; + smgt->try_alloc_in_cma_page_cnt = g_scatter.try_alloc_in_cma_page_cnt; + smgt->try_alloc_in_sys_page_cnt_max + = g_scatter.try_alloc_in_sys_page_cnt_max; + smgt->try_alloc_in_sys_page_cnt_min + = g_scatter.try_alloc_in_sys_page_cnt_min; + smgt->enable_slot_from_sys = g_scatter.enable_slot_from_sys; + smgt->support_from_slot_sys = g_scatter.support_from_slot_sys; + smgt->no_cache_size_M = g_scatter.no_cache_size_M; + return 0; } -EXPORT_SYMBOL(codec_mm_scatter_mgt_set_config); -int codec_mm_scatter_mgt_delay_free_swith(int on, +int codec_mm_scatter_mgt_delay_free_swith( + int on, int delay_ms, - int wait_size_M) + int wait_size_M, + int is_tvp) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); + struct codec_mm_scatter_mgt *smgt; + smgt = codec_mm_get_scatter_mgt(is_tvp); codec_mm_list_lock(smgt); if (on) { smgt->delay_free_on++; @@ -2064,7 +2084,7 @@ int codec_mm_scatter_mgt_delay_free_swith(int on, smgt->force_cache_page_cnt = wait_size_M >> PAGE_SHIFT; smgt->delay_free_timeout_jiffies64 = get_jiffies_64() + 10000 * HZ/1000; - codec_mm_schedule_delay_work(0, 1);/*start cache*/ + codec_mm_schedule_delay_work(smgt, 0, 1);/*start cache*/ while (smgt->cached_pages < smgt->force_cache_page_cnt) { if (smgt->cache_sc && (smgt->cached_pages >= @@ -2085,15 +2105,16 @@ int codec_mm_scatter_mgt_delay_free_swith(int on, smgt->delay_free_timeout_jiffies64 = get_jiffies_64() + delay_ms * HZ/1000; } else if (on) { - codec_mm_schedule_delay_work(0, 1); + codec_mm_schedule_delay_work(smgt, 0, 1); } else { - codec_mm_schedule_delay_work(delay_ms, 0); + codec_mm_schedule_delay_work(smgt, delay_ms, 0); } return 0; } EXPORT_SYMBOL(codec_mm_scatter_mgt_delay_free_swith); -static void codec_mm_scatter_cache_manage(struct codec_mm_scatter_mgt *smgt) +static void codec_mm_scatter_cache_manage( + struct codec_mm_scatter_mgt *smgt) { struct codec_mm_scatter *mms; int alloced = 0; @@ -2137,6 +2158,7 @@ static void codec_mm_scatter_cache_manage(struct codec_mm_scatter_mgt *smgt) if (need > mms->page_cnt) { alloced = !codec_mm_scatter_alloc_want_pages_in( + smgt, mms, need); } else { @@ -2145,8 +2167,6 @@ static void codec_mm_scatter_cache_manage(struct codec_mm_scatter_mgt *smgt) } else { alloced = 0; } - /*int from_sys = codec_mm_get_free_size() < 16 * SZ_1M;*/ - /*alloced = !!codec_mm_slot_alloc(0, (from_sys ? 1 : 0));*/ } else if ((smgt->cached_pages > (smgt->keep_size_PAGE + 1000)) && time_after64(get_jiffies_64(), @@ -2161,33 +2181,35 @@ static void codec_mm_scatter_cache_manage(struct codec_mm_scatter_mgt *smgt) codec_mm_scatter_free_tail_pages(mms, free_start); } - codec_mm_free_all_free_slots(); - /*free some slots. */ + codec_mm_free_all_free_slots_in(smgt); + /*free some slots.*/ } } else if (smgt->delay_free_on <= 0 && time_after64(get_jiffies_64(), smgt->delay_free_timeout_jiffies64)) { /*free all free pages, no delay needed.*/ - codec_mm_free_all_free_slots(); + codec_mm_free_all_free_slots_in(smgt); } if (smgt->keep_size_PAGE > 0 && smgt->delay_free_on) { if (((smgt->force_cache_on || (total_free_page < smgt->keep_size_PAGE)) && - !codec_mm_video_tvp_enabled()) && + !smgt->tvp_mode) && alloced) {/*if failed may deadlock...*/ /*ignore keep on tvp mode.*/ if (smgt->force_cache_on) - codec_mm_schedule_delay_work(0, 1); + codec_mm_schedule_delay_work(smgt, 0, 1); else - codec_mm_schedule_delay_work(10, 0); + codec_mm_schedule_delay_work(smgt, 10, 0); } else - codec_mm_schedule_delay_work(100, 0); + codec_mm_schedule_delay_work(smgt, 100, 0); } else if (!smgt->delay_free_on && smgt->total_page_num > 0) { - codec_mm_schedule_delay_work(100, 0); + codec_mm_schedule_delay_work(smgt, 100, 0); } } -static int codec_mm_scatter_scatter_arrange(struct codec_mm_scatter_mgt *smgt) + +static int codec_mm_scatter_scatter_arrange( + struct codec_mm_scatter_mgt *smgt) { struct codec_mm_scatter *mms; struct codec_mm_scatter *first_free_mms = NULL; @@ -2195,8 +2217,8 @@ static int codec_mm_scatter_scatter_arrange(struct codec_mm_scatter_mgt *smgt) int n = 0; if (smgt->delay_free_on > 0 && !smgt->cache_sc) { - /*no free scatter. */ - mms = codec_mm_scatter_alloc_new(16384, 0); + /*no free scatter.*/ + mms = codec_mm_scatter_alloc_new(smgt, 16384, 0); if (mms) { codec_mm_list_lock(smgt); list_del_init(&mms->list); @@ -2213,7 +2235,7 @@ static int codec_mm_scatter_scatter_arrange(struct codec_mm_scatter_mgt *smgt) smgt->cached_pages = 0; codec_mm_list_unlock(smgt); codec_mm_scatter_dec_owner_user(mms, 0); - codec_mm_scatter_free_on_nouser(mms); + codec_mm_scatter_free_on_nouser(smgt, mms); } codec_mm_list_lock(smgt); @@ -2282,7 +2304,7 @@ static int codec_mm_scatter_scatter_clear( } codec_mm_list_unlock(smgt); if (to_free_mms != NULL) - codec_mm_scatter_free_on_nouser(to_free_mms); + codec_mm_scatter_free_on_nouser(smgt, to_free_mms); if (less_page_mms && (less_page_mms != to_free_mms)) codec_mm_scatter_free_unused_pages(less_page_mms); return (to_free_mms != NULL) || (less_page_mms != NULL); @@ -2295,11 +2317,12 @@ static int codec_mm_scatter_scatter_clear( *0 is all freeed. *N is have some pages not alloced. */ -int codec_mm_scatter_free_all_ignorecache(void) +static int codec_mm_scatter_free_all_ignorecache_in( + struct codec_mm_scatter_mgt *smgt) { - struct codec_mm_scatter_mgt *smgt = codec_mm_get_scatter_mgt(); int need_retry = 1; int retry_num = 0; + mutex_lock(&smgt->monitor_lock); pr_info("force free all scatter ignorecache!\n"); do { @@ -2314,7 +2337,7 @@ int codec_mm_scatter_free_all_ignorecache(void) codec_mm_list_unlock(smgt); if (mms) { codec_mm_scatter_dec_owner_user(mms, 0); - codec_mm_scatter_free_on_nouser(mms); + codec_mm_scatter_free_on_nouser(smgt, mms); } /*alloced again on timer?*/ /* check again. */ @@ -2326,7 +2349,7 @@ int codec_mm_scatter_free_all_ignorecache(void) pr_info("can't free all scatter, because some have used!!\n"); codec_mm_dump_all_scatters(); } - codec_mm_free_all_free_slots(); + codec_mm_free_all_free_slots_in(smgt); if (smgt->total_page_num > 0) { /*have some not free,dump tables for debug */ pr_info("Some slots have not free!!\n\n"); @@ -2337,12 +2360,25 @@ int codec_mm_scatter_free_all_ignorecache(void) } EXPORT_SYMBOL(codec_mm_scatter_free_all_ignorecache); +int codec_mm_scatter_free_all_ignorecache(int flags) +{ + if (flags & 1) + codec_mm_scatter_free_all_ignorecache_in( + codec_mm_get_scatter_mgt(0)); + if (flags & 2) + codec_mm_scatter_free_all_ignorecache_in( + codec_mm_get_scatter_mgt(1)); + return 0; +} + static void codec_mm_scatter_monitor(struct work_struct *work) { struct codec_mm_scatter_mgt *smgt = container_of(work, struct codec_mm_scatter_mgt, dealy_work.work); int needretry = 0; + + codec_mm_scatter_update_config(smgt); mutex_lock(&smgt->monitor_lock); smgt->scatter_task_run_num++; @@ -2350,49 +2386,97 @@ static void codec_mm_scatter_monitor(struct work_struct *work) needretry = codec_mm_scatter_scatter_clear(smgt, 0); if (needretry) - codec_mm_schedule_delay_work(10, 0); + codec_mm_schedule_delay_work(smgt, 10, 0); else if (smgt->scatters_cnt > 0) - codec_mm_schedule_delay_work(100, 0); + codec_mm_schedule_delay_work(smgt, 100, 0); codec_mm_scatter_cache_manage(smgt); mutex_unlock(&smgt->monitor_lock); } -int codec_mm_scatter_mgt_init(void) +static int codec_mm_scatter_mgt_alloc_in(struct codec_mm_scatter_mgt **psmgt) { - scatter_mgt = kmalloc(sizeof(struct codec_mm_scatter_mgt), GFP_KERNEL); - if (!scatter_mgt) { + struct codec_mm_scatter_mgt *smgt; + + smgt = kmalloc(sizeof(struct codec_mm_scatter_mgt), GFP_KERNEL); + if (!smgt) { ERR_LOG("ERR:codec mm mpt init ERROR\n"); return -1; } - memset(scatter_mgt, 0, sizeof(struct codec_mm_scatter_mgt)); - spin_lock_init(&scatter_mgt->list_lock); - scatter_mgt->alloced_page_num = 0; - scatter_mgt->try_alloc_in_cma_page_cnt = (4 * 1024 * 1024) / PAGE_SIZE; - scatter_mgt->try_alloc_in_sys_page_cnt_max = MAX_SYS_BLOCK_PAGE; - scatter_mgt->try_alloc_in_sys_page_cnt = MAX_SYS_BLOCK_PAGE; - scatter_mgt->try_alloc_in_sys_page_cnt_min = MIN_SYS_BLOCK_PAGE; - scatter_mgt->reserved_block_mm_M = 64; - scatter_mgt->keep_size_PAGE = 20 * SZ_1M >> PAGE_SHIFT; - scatter_mgt->alloc_from_cma_first = 1; - scatter_mgt->enable_slot_from_sys = 1; - scatter_mgt->support_from_slot_sys = - scatter_mgt->enable_slot_from_sys; + memset(smgt, 0, sizeof(struct codec_mm_scatter_mgt)); + spin_lock_init(&smgt->list_lock); + smgt->tag = SMGT_IDENTIFY_TAG; + smgt->alloced_page_num = 0; + smgt->try_alloc_in_cma_page_cnt = (4 * 1024 * 1024) / PAGE_SIZE; + smgt->try_alloc_in_sys_page_cnt_max = MAX_SYS_BLOCK_PAGE; + smgt->try_alloc_in_sys_page_cnt = MAX_SYS_BLOCK_PAGE; + smgt->try_alloc_in_sys_page_cnt_min = MIN_SYS_BLOCK_PAGE; + smgt->reserved_block_mm_M = 64; + smgt->keep_size_PAGE = 20 * SZ_1M >> PAGE_SHIFT; + smgt->alloc_from_cma_first = 1; + smgt->enable_slot_from_sys = 1; + smgt->support_from_slot_sys = + smgt->enable_slot_from_sys; + smgt->mem_flags = CODEC_MM_FLAGS_CMA_FIRST | + CODEC_MM_FLAGS_FOR_VDECODER | + CODEC_MM_FLAGS_FOR_SCATTER; if ((totalram_pages << PAGE_SHIFT) < 800 * SZ_1M) { /*less memory boards don't cache more,*/ /*after alloced many pages.*/ - scatter_mgt->no_cache_size_M = 100; + smgt->no_cache_size_M = 100; } else - scatter_mgt->no_cache_size_M = 0; - INIT_LIST_HEAD(&scatter_mgt->free_list); - INIT_LIST_HEAD(&scatter_mgt->scatter_list); - mutex_init(&scatter_mgt->monitor_lock); + smgt->no_cache_size_M = 0; + INIT_LIST_HEAD(&smgt->free_list); + INIT_LIST_HEAD(&smgt->scatter_list); + mutex_init(&smgt->monitor_lock); - INIT_DELAYED_WORK(&scatter_mgt->dealy_work, + INIT_DELAYED_WORK(&smgt->dealy_work, codec_mm_scatter_monitor); + *psmgt = smgt; + return 0; +} +static struct mconfig codec_mm_sc_configs[] = { + MC_PU32("keep_size_PAGE", &g_scatter.keep_size_PAGE), + MC_PU32("reserved_block_mm_M", &g_scatter.reserved_block_mm_M), + MC_PU32("try_alloc_in_cma_page_cnt", + &g_scatter.try_alloc_in_cma_page_cnt), + MC_PU32("try_alloc_in_sys_page_cnt_max", + &g_scatter.try_alloc_in_sys_page_cnt_max), + MC_PU32("try_alloc_in_sys_page_cnt_min", + &g_scatter.try_alloc_in_sys_page_cnt_min), + MC_PU32("enable_slot_from_sys", + &g_scatter.enable_slot_from_sys), + MC_PU32("no_cache_size_M", &g_scatter.no_cache_size_M), +}; + +static struct mconfig_node codec_mm_sc; + +int codec_mm_scatter_mgt_init(void) +{ + struct codec_mm_scatter_mgt *smgt; + + codec_mm_scatter_mgt_alloc_in(&scatter_mgt); + codec_mm_scatter_mgt_alloc_in(&scatter_tvp_mgt); + scatter_tvp_mgt->tvp_mode = 1; + scatter_tvp_mgt->mem_flags |= CODEC_MM_FLAGS_TVP; + smgt = scatter_mgt; + g_scatter.keep_size_PAGE = smgt->keep_size_PAGE; + g_scatter.reserved_block_mm_M = smgt->reserved_block_mm_M; + g_scatter.try_alloc_in_cma_page_cnt = smgt->try_alloc_in_cma_page_cnt; + g_scatter.try_alloc_in_sys_page_cnt_max + = smgt->try_alloc_in_sys_page_cnt_max; + g_scatter.try_alloc_in_sys_page_cnt_min + = smgt->try_alloc_in_sys_page_cnt_min; + g_scatter.enable_slot_from_sys = smgt->enable_slot_from_sys; + g_scatter.support_from_slot_sys = smgt->support_from_slot_sys; + g_scatter.no_cache_size_M = smgt->no_cache_size_M; + + INIT_REG_NODE_CONFIGS("media.codec_mm", + &codec_mm_sc, "scatter", + codec_mm_sc_configs, + CONFIG_FOR_RW); return 0; } -EXPORT_SYMBOL(codec_mm_scatter_mgt_init); int codec_mm_scatter_mgt_test(void) { @@ -2489,8 +2573,10 @@ int codec_mm_scatter_test(int mode, int p1, int p2) INFO_LOG(" alloc sc[%d] num %d:\n", p1, p2); if (p1 > 0 && p1 < 64) { if (sc[p1]) - codec_mm_scatter_free_on_nouser(sc[p1]); - sc[p1] = codec_mm_scatter_alloc(p2 * 2, p2); + codec_mm_scatter_free_on_nouser( + (struct codec_mm_scatter_mgt *)sc[p1]->manager, + sc[p1]); + sc[p1] = codec_mm_scatter_alloc(p2 * 2, p2, 0); } break; case 2: /*alloc more */ @@ -2506,7 +2592,9 @@ int codec_mm_scatter_test(int mode, int p1, int p2) case 4: INFO_LOG(" free sc[%d] all\n", p1); if (p1 > 0 && p1 < 64 && sc[p1]) { - codec_mm_scatter_free_on_nouser(sc[p1]); + codec_mm_scatter_free_on_nouser( + (struct codec_mm_scatter_mgt *)sc[p1]->manager, + sc[p1]); sc[p1] = NULL; } break; diff --git a/drivers/amlogic/media/common/codec_mm/codec_mm_scatter_priv.h b/drivers/amlogic/media/common/codec_mm/codec_mm_scatter_priv.h index 0d636ec..5695af4 100644 --- a/drivers/amlogic/media/common/codec_mm/codec_mm_scatter_priv.h +++ b/drivers/amlogic/media/common/codec_mm/codec_mm_scatter_priv.h @@ -64,8 +64,8 @@ int codec_mm_scatter_dec_keeper_user(void *sc_mm, int delay_ms); int codec_mm_scatter_mgt_get_config(char *buf); int codec_mm_scatter_mgt_set_config(const char *buf, size_t size); -int codec_mm_scatter_free_all_ignorecache(void); -int codec_mm_scatter_valid_locked(struct codec_mm_scatter *mms); +int codec_mm_scatter_free_all_ignorecache(int flags); + void codec_mm_clear_alloc_infos(void); diff --git a/drivers/amlogic/media/common/codec_mm/configs/Makefile b/drivers/amlogic/media/common/codec_mm/configs/Makefile new file mode 100644 index 0000000..c95b63b --- /dev/null +++ b/drivers/amlogic/media/common/codec_mm/configs/Makefile @@ -0,0 +1,14 @@ +########################################## +########## Amlogic codec memory manager ############### +########################################## + +########################################## +## The order of directories matter. +## Do not change. +########################################## + + +obj-$(CONFIG_AMLOGIC_MEDIA_CODEC_MM) += configs.o configs_module.o +obj-$(CONFIG_AMLOGIC_MEDIA_CODEC_MM) += configs_test.o + + diff --git a/drivers/amlogic/media/common/codec_mm/configs/configs.c b/drivers/amlogic/media/common/codec_mm/configs/configs.c new file mode 100644 index 0000000..87fbb8c --- /dev/null +++ b/drivers/amlogic/media/common/codec_mm/configs/configs.c @@ -0,0 +1,1094 @@ +/* + * drivers/amlogic/media/common/codec_mm/configs/configs.c + * + * Copyright (C) 2017 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 +#include "configs_priv.h" +static struct mconfig_node root_node; +static struct mconfig_node *configs_get_root_node(void) +{ + return &root_node; +} + +#ifdef DEBUG_CONFIG +#define config_debug(args...) pr_info(args) +#else +#define config_debug(args...) +#endif +int configs_inc_node_ref( + struct mconfig_node *node) +{ + return atomic_inc_return(&node->ref_cnt); +} + +int configs_dec_node_ref( + struct mconfig_node *node) +{ + return atomic_dec_return(&node->ref_cnt); +} + +static int configs_put_node(struct mconfig_node *node, + int del_parent_ref, struct mconfig_node *root_node) +{ + struct mconfig_node *pnode; + + if (!node) + return 0; + configs_dec_node_ref(node); + pnode = node->parent_node; + if (!del_parent_ref) + return 0; + while ((pnode != NULL) && (pnode != root_node)) { + configs_dec_node_ref(pnode); + pnode = pnode->parent_node; + } + return 0; +} + + +static int configs_parser_first_node( + const char *root_str, + char *sub_str, + int sub_size, + int *is_end_node) +{ + int node_size; + char *str; + char *pstr; + + if (strlen(root_str) <= 0) + return 0; + str = strchr(root_str, '.'); + if (str != NULL) { + node_size = str - root_str; + *is_end_node = 0; + } else { + str = strchr(root_str, '='); + if (str != NULL) + node_size = str - root_str; + else + node_size = strlen(root_str); + *is_end_node = 1; + } + if (node_size >= MAX_ITEM_NAME - 1) + node_size = MAX_ITEM_NAME - 1; + if (node_size > 0) { + strncpy(sub_str, root_str, node_size); + sub_str[node_size] = '\0'; + pstr = sub_str; + while (pstr[0] != '\0' && + pstr[0] != ' ' && + pstr[0] != '\r' && + pstr[0] != '\n') { + /*not space. */ + pstr++; + } + pstr[0] = '\0'; + } else + sub_str[0] = '\0'; + return node_size; +} + +static inline const char *configs_parser_str_valstr( + const char *root_str) +{ + char *str; + + if (strlen(root_str) <= 0) + return NULL; + str = strchr(root_str, '='); + if (str) + str = str + 1; /*del = */ + return str; +} + +static int configs_parser_value_u32(const char *str, u32 *val) +{ + int ret = 0; + const char *pstr; + + if (!str || strlen(str) <= 0) + return 0; + pstr = str; + while (pstr[0] == ' ') + pstr++; + if (pstr[0] == '-') { + ret = sscanf(pstr, "-%d", val); + *val = -((int)*val); + } else if (strstr(pstr, "0x")) + ret = sscanf(pstr, "0x%x", val); + else if (strstr(pstr, "0x")) + ret = sscanf(pstr, "0x%x", val); + else { + ret = kstrtou32(pstr, 0, val); + if (ret == 0) + ret = 1; + } + return ret; +} + +static int configs_parser_value_u64(const char *str, u64 *val) +{ + int ret = 0; + const char *pstr; + + if (!str || strlen(str) <= 0) + return 0; + pstr = str; + while (pstr[0] == ' ') + pstr++; + if (pstr[0] == '-') { + ret = sscanf(pstr, "-%lld", val); + *val = -((int)*val); + } else if (strstr(pstr, "0x")) + ret = sscanf(pstr, "0x%llx", val); + else if (strstr(pstr, "0x")) + ret = sscanf(pstr, "0x%llx", val); + else { + ret = kstrtou64(pstr, 0, val); + if (ret == 0) + ret = 1; + } + return ret; +} + +static int configs_parser_value_bool(const char *str, bool *pbool) +{ + const char *pstr; + + if (!str || strlen(str) <= 0) + return 0; + pstr = str; + while (pstr[0] == ' ') + pstr++; + if (str[0] == '1') { + *pbool = true; + } else if (str[0] == '0') { + *pbool = false; + } else if (!strcmp(str, "true") || + !strcmp(str, "TRUE") || + !strcmp(str, "true")) { + *pbool = true; + } else if (strcmp(str, "false") || + !strcmp(str, "FALSE") || + !strcmp(str, "False")) { + *pbool = false; + } else { + return 0; + } + return 1; +} + + +static struct mconfig_node *configs_get_node_with_name( + struct mconfig_node + *rootnode, const char *node_name) +{ + struct mconfig_node *snode, *need; + struct list_head *node_list, *next; + + need = NULL; + if (!rootnode) + rootnode = configs_get_root_node(); + mutex_lock(&rootnode->lock); + if (list_empty(&rootnode->son_node_list)) { + mutex_unlock(&rootnode->lock); + return NULL; + } + list_for_each_safe(node_list, next, &rootnode->son_node_list) { + snode = list_entry(node_list, struct mconfig_node, list); + if (!strcmp(snode->name, node_name)) { + need = snode; + if (snode->active <= 0 || + configs_inc_node_ref(need) < 0) + need = NULL; + break; + } + } + mutex_unlock(&rootnode->lock); + return need; +} + +int configs_init_new_node(struct mconfig_node *node, + const char *name, int rw_flags) +{ + node->configs = NULL; + node->configs_num = 0; + node->son_node_num = 0; + node->name = name; + node->rw_flags = rw_flags; + node->depth = 0; + node->active = 1; + node->prefix[0] = '\0'; + atomic_set(&node->ref_cnt, 0); + mutex_init(&node->lock); + INIT_LIST_HEAD(&node->list); + INIT_LIST_HEAD(&node->son_node_list); + return 0; +} +EXPORT_SYMBOL(configs_init_new_node); + +int configs_register_node(struct mconfig_node *parent, + struct mconfig_node *new_node) +{ + if (!parent) + parent = configs_get_root_node(); + if (!parent || new_node == parent) + return 0; /*top node add. */ + if (parent->depth >= MAX_DEPTH) + return -1; /*too deep path */ + if (strlen(parent->prefix) + strlen(parent->name) >= + MAX_PREFIX_NAME - 2) { + pr_err("unsupport deep path %s.%s,len=%d > %d\n", + parent->prefix, parent->name, + (int)(strlen(parent->prefix) + strlen(parent->name) + 1), + MAX_PREFIX_NAME - 1); + return -2; /*unsuport deep path */ + } + if (configs_get_node_with_name(parent, new_node->name) != NULL) { + pr_err("have register same node[%s] on %s before\n", + new_node->name, parent->name); + return -3; + } + /* + *root.name.bb + *depth:0.1.2 + *depth 0 &1 don't sed prefix. + *for ignore "root." + */ + new_node->depth = parent->depth + 1; + if (new_node->depth >= 2) { + if (parent->prefix[0]) { + strcpy(new_node->prefix, parent->prefix); + strcat(new_node->prefix, "."); + } + strcat(new_node->prefix, parent->name); + } + mutex_lock(&parent->lock); + new_node->parent_node = parent; + list_add_tail(&new_node->list, &parent->son_node_list); + /* + *node parent not have write permissions, + *del the the node write permissions; + *same as read. + */ + new_node->rw_flags = parent->rw_flags & new_node->rw_flags; + parent->son_node_num++; + new_node->active = 1; + mutex_unlock(&parent->lock); + return 0; +} +EXPORT_SYMBOL(configs_register_node); + +static struct mconfig_node *configs_get_node_path_end_node( + struct mconfig_node *root_node, const char *path) +{ + char sub_node_name[128]; + struct mconfig_node *node, *start_node, *parent_node; + int i, end; + const char *next_path = path; + + if (!path) + return NULL; + end = 0; + start_node = root_node; + if (!root_node) + start_node = configs_get_root_node(); + node = start_node; + while (!end) { + parent_node = node; + i = configs_parser_first_node(next_path, + sub_node_name, 128, &end); + if (i <= 0 || sub_node_name[0] == '\0') { + pr_err("can't find [%s] 's node!!\n", path); + return NULL; + } + /*only no top node. */ + if (end && !root_node && node == start_node) { + if (!strcmp(node->name, sub_node_name)) { + /*need node is top node */ + break; + } + } + config_debug("configs_parser_first_node{%s} end%d\n", + sub_node_name, end); + node = configs_get_node_with_name(parent_node, + sub_node_name); + if (node == NULL) { + pr_err("can't find node:[%s], from:[%s], path=%s\n", + sub_node_name, parent_node->name, path); + return NULL; + } + next_path = next_path + i + 1; /*media.vdec --> vdec */ + config_debug("get snode[%s] from node[%s], end=%d\n", + node->name, parent_node->name, end); + } + return node; +} +EXPORT_SYMBOL(configs_get_node_path_end_node); + +int configs_register_path_node(const char *path, + struct mconfig_node *new_node) +{ + struct mconfig_node *parent = NULL; + int ret; + + if (path && strlen(path) > 0) { + parent = configs_get_node_path_end_node(NULL, path); + if (!parent) + return -1; + } + ret = configs_register_node(parent, new_node); + configs_put_node(parent, 1, NULL); + return ret; +} +EXPORT_SYMBOL(configs_register_path_node); + +int configs_register_configs(struct mconfig_node *node, + struct mconfig *configs, int num) +{ + if (!node) + return -1; + if (node->configs != NULL || node->configs_num > 0) { + pr_err("node[%s] register config before!.\n", node->name); + return -2; + } + if (0) { + int i; + + for (i = 0; i < num; i++) { + pr_info("init node:%s, config[i].data %lx-%lx\n", + node->name, + configs[i].ldata[0], + configs[i].ldata[1]); + } + } + mutex_lock(&node->lock); + node->configs = configs; + node->configs_num = num; + mutex_unlock(&node->lock); + return 0; +} +EXPORT_SYMBOL(configs_register_configs); + +int configs_register_path_configs(const char *path, + struct mconfig *configs, int num) +{ + struct mconfig_node *parent = NULL; + int ret; + + if (path && strlen(path) > 0) { + parent = configs_get_node_path_end_node(NULL, path); + if (!parent) + return -1; + ret = configs_register_configs(parent, configs, num); + configs_put_node(parent, 1, NULL); + return ret; + } + return -1; +} +EXPORT_SYMBOL(configs_register_path_configs); + +int configs_del_endnode(struct mconfig_node *parent, + struct mconfig_node *node) +{ + struct mconfig_node *parent_node; + + parent_node = node->parent_node; + node->active = 0; + /*always set it to no active */ + if (atomic_read(&node->ref_cnt) != 0) + return -1; + /*always del configs. */ + node->configs = NULL; + node->configs_num = 0; + /*do't del node when have son node. */ + if (node->son_node_num > 0) + return -2; + if (parent) { + mutex_lock(&parent->lock); + list_del(&node->list); + parent->son_node_num--; + mutex_unlock(&parent->lock); + } + return 0; +} + +static struct mconfig *configs_get_node_config( + struct mconfig_node *node, char *name) +{ + int i; + struct mconfig *config = NULL; + + mutex_lock(&node->lock); + for (i = 0; i < node->configs_num; i++) { + struct mconfig *val = &node->configs[i]; + + if (val && !strcmp(val->item_name, name)) { + configs_inc_node_ref(node); + config = val; + break; + } + } + mutex_unlock(&node->lock); + config_debug("get config[%s] from %s-end-%p\n", + name, node->name, (void *)config); + return config; +} + +static int configs_config2str(struct mconfig *config, + char *buf, int size) +{ + int ret = 0; + + if (size < 1) + return 0; + switch (config->type) { + case CONFIG_TYPE_PBOOL: + ret = snprintf(buf, size, "%s", + config->pboolval[0] ? "true" : "false"); + break; + case CONFIG_TYPE_PI32: + ret = snprintf(buf, size, "%u", config->pival[0]); + break; + case CONFIG_TYPE_PU32: + ret = snprintf(buf, size, "%d", config->pu32val[0]); + break; + case CONFIG_TYPE_PU64: + ret = snprintf(buf, size, "%llx", config->pu64val[0]); + break; + case CONFIG_TYPE_PSTR: + case CONFIG_TYPE_PCSTR: + ret = snprintf(buf, size, "%s", config->str); + break; + case CONFIG_TYPE_BOOL: + ret = snprintf(buf, size, "%s", + config->pboolval ? "true" : "false"); + case CONFIG_TYPE_I32: + ret = snprintf(buf, size, "%d", config->ival); + break; + case CONFIG_TYPE_U32: + ret = snprintf(buf, size, "%u", config->u32val); + break; + case CONFIG_TYPE_U64: + ret = snprintf(buf, size, "0x%llx", config->u64val); + break; + case CONFIG_TYPE_FUN: + if (!config->f_get) + ret = 0; + else + ret = config->f_get(config->item_name, + config->id, buf, size); + break; + default: + ret = -4; + } + if (ret <= 0) { + pr_err("config2str error %s-type:%d,%lx-%lx,ret=%d\n", + config->item_name, config->type, + config->ldata[0], config->ldata[1], ret); + } else if (ret >= size) { + buf[size - 1] = '\0'; + ret = size - 1; + } + return ret; +} + +static int configs_str2config(struct mconfig *config, + const char *str) +{ + int ret = 0; + u32 val; + u64 val64; + bool bval; + + if (!str || strlen(str) <= 0) + return 0; + switch (config->type) { + case CONFIG_TYPE_PBOOL: + case CONFIG_TYPE_BOOL: + ret = configs_parser_value_bool(str, &bval); + if (ret <= 0) + break; + if (config->type == CONFIG_TYPE_PBOOL) + config->pboolval[0] = bval; + else + config->boolval = bval; + break; + case CONFIG_TYPE_PI32: + case CONFIG_TYPE_PU32: + ret = configs_parser_value_u32(str, (u32 *) &val); + if (ret > 0) + config->pu32val[0] = val; + break; + case CONFIG_TYPE_PU64: + ret = configs_parser_value_u64(str, (u64 *) &val64); + if (ret > 0) + config->pu64val[0] = val64; + break; + case CONFIG_TYPE_PSTR: + strncpy(config->str, str, config->size); + ret = strlen(config->str); + break; + case CONFIG_TYPE_I32: + case CONFIG_TYPE_U32: + ret = configs_parser_value_u32(str, (u32 *) &val); + if (ret > 0) + config->u32val = val; + break; + case CONFIG_TYPE_U64: + ret = configs_parser_value_u64(str, (u64 *) &val64); + if (ret > 0) + config->u64val = val64; + break; + case CONFIG_TYPE_FUN: + if (!config->f_set) + ret = -1; + else + ret = config->f_set(config->item_name, + config->id, + str, strlen(str)); + break; + case CONFIG_TYPE_PCSTR: /*can't set. */ + default: + ret = -4; + } + return ret; +} + +static char *configs_build_prefix( + struct mconfig_node *node, + const char *prefix, + int mode, + char *buf, + int size) +{ + if (!buf) + return ""; + buf[0] = '\0'; + if (mode & LIST_MODE_PATH_FULLPREFIX) { + if (node->prefix[0]) { + snprintf(buf, size, "%s", + node->prefix); + } + } else if (mode & LIST_MODE_PATH_PREFIX) { + if (prefix && prefix[0]) { + snprintf(buf, size, "%s", + prefix); + } + } + if (buf[0] && buf[strlen(buf) - 1] != '.') + strncat(buf, ".", size); + return buf; +} + +static int configs_list_node_configs_locked( + struct mconfig_node *node, + char *buf, int size, const char *prefix, + int mode) +{ + int i; + int ret; + int pn_size = 0; + struct mconfig *config = NULL; + const char *cprefix = prefix; + + if (!buf || size < 8 || !node->configs) + return 0; + if (!cprefix) + cprefix = ""; + for (i = 0; i < node->configs_num && (size - pn_size) > 8; i++) { + config = &node->configs[i]; + ret = snprintf(buf + pn_size, + size - pn_size, + " %s%s.%s%s", + cprefix, + node->name, + config->item_name, + (node->rw_flags & CONFIG_FOR_R) ? "=" : ""); + if (ret > 0) + pn_size += ret; + if ((mode & LIST_MODE_VAL) && + ((mode & CONFIG_FOR_T) || + !(CONFIG_FOR_T & node->rw_flags)) && + (node->rw_flags & CONFIG_FOR_R)) { + ret = configs_config2str(config, + buf + pn_size, size - pn_size); + if (ret > 0) { + if ((pn_size + ret) < size) { + strcat(buf, "\n"); + ret++; + } + pn_size += ret; + } else { + if (ret == 0 && (pn_size + ret) < size) { + strcat(buf, "\n"); + ret++; + continue; + } + break; + } + } else { + ret = snprintf(buf + pn_size, size - pn_size, "\n"); + if (ret > 0) + pn_size += ret; + } + } + return pn_size; +} + +int configs_list_node_configs(struct mconfig_node *node, + char *buf, int size, + int mode) +{ + int ret; + + mutex_lock(&node->lock); + ret = configs_list_node_configs_locked(node, buf, + size, NULL, mode); + mutex_unlock(&node->lock); + return ret; +} + +static int configs_list_nodes_in(struct mconfig_node *node, + char *buf, int size, const char *prefix, + int mode) +{ + int ret; + int pn_size = 0; + char cprefix[MAX_PREFIX_NAME + MAX_ITEM_NAME]; + char *c_prefix; + char rw[4][4] = { "N", "r", "w", "rw" }; + + if (!node || !buf || size <= 0) + return 0; + if (!(node->rw_flags & mode)) + return 0;/*LIST_MODE_LIST_RD/WD flags*/ + config_debug("start dump node %s...\n", node->name); + c_prefix = configs_build_prefix(node, + prefix, + mode, + cprefix, + MAX_PREFIX_NAME + MAX_ITEM_NAME); + mutex_lock(&node->lock); + if (mode & LIST_MODE_NODE_INFO) { + ret = snprintf(buf + pn_size, size - pn_size, + "[NODE]%s%s:[%s/%d/%d/%d]\n", + c_prefix, + node->name, + rw[(node->rw_flags & 3)], + atomic_read(&node->ref_cnt), + node->configs_num, + node->depth); + if (ret > 0) + pn_size += ret; + } + if (mode & LIST_MODE_CONFIGS_VAL) { + ret = configs_list_node_configs_locked(node, buf + pn_size, + size - pn_size, c_prefix, mode); + if (ret > 0) + pn_size += ret; + } + if ((mode & LIST_MODE_SUB_NODES) && node->son_node_num > 0) { + struct mconfig_node *snode; + struct list_head *node_list, *next; + + if (mode & LIST_MODE_PATH_PREFIX) { + if (node->depth > 0)/*not root.*/ + strncat(cprefix, node->name, + MAX_PREFIX_NAME + MAX_ITEM_NAME); + } + list_for_each_safe(node_list, next, &node->son_node_list) { + snode = list_entry(node_list, + struct mconfig_node, list); + if (snode) { + ret = configs_list_nodes_in(snode, + buf + pn_size, size - pn_size, + cprefix, mode); + if (ret > 0) + pn_size += ret; + } + } + } + mutex_unlock(&node->lock); + return pn_size; +} + +int configs_list_nodes(struct mconfig_node *node, + char *buf, int size, int mode) +{ + if (!node) + node = configs_get_root_node(); + return configs_list_nodes_in(node, buf, size, + NULL, + mode); +} + +int configs_list_path_nodes(const char *prefix, + char *buf, int size, int mode) +{ + struct mconfig_node *node; + int ret = 0; + + node = configs_get_node_path_end_node(NULL, prefix); + if (node != NULL) { + ret = configs_list_nodes(node, buf, size, mode); + configs_put_node(node, 1, NULL); + } + return ret; +} + +static int configs_get_node_path_config( + struct mconfig_node *root_node, + struct mconfig **config_ret, + const char *path, + struct mconfig_node **hold_node, int set) +{ + char sub_node_name[128]; + struct mconfig_node *node, *parent_node; + struct mconfig *config = NULL; + int i, end; + const char *next_path = path; + int err = 0; + + if (!path) + return -EIO; + end = 0; + if (!root_node) + root_node = configs_get_root_node(); + node = root_node; + while (!end) { + parent_node = node; + i = configs_parser_first_node(next_path, + sub_node_name, 128, &end); + if (i <= 0 || sub_node_name[0] == '\0') { + pr_err("can't find [%s] 's node!!\n", path); + return -1; + } + config_debug("configs_parser_first_node{%s} end%d\n", + sub_node_name, end); + if (!end) { + node = configs_get_node_with_name(parent_node, + sub_node_name); + if (node == NULL) { + if (parent_node != root_node) { + node = parent_node; + goto out; + } + /*for reset refs. */ + pr_err("can't find node:[%s], from:[%s], path=%s\n", + sub_node_name, parent_node->name, path); + err = -ENOENT; + goto out; + } + next_path = next_path + i + 1; /*media.vdec --> vdec */ + config_debug("get snode[%s] from node[%s], end=%d\n", + node->name, parent_node->name, end); + } + } + if (set && !(node->rw_flags & CONFIG_FOR_W)) { + err = -ENOENT; + goto out; + } + if (!set && !(node->rw_flags & CONFIG_FOR_R)) { + err = -EPERM; + goto out; + } + config = configs_get_node_config(node, sub_node_name); + if (!config) { + /*release node refs. */ + err = -EPERM; + } else + *hold_node = node; + out: + if (config == NULL) { + if (node) { + configs_put_node(node, 1, root_node); + pr_err("can't find node %s's config:%s\n", + node->name, sub_node_name); + } else + pr_err("can't find node %s from %s\n", + sub_node_name, root_node->name); + } else { + *config_ret = config; + err = 0; + } + return err; +} + +static int configs_setget_config_value(struct mconfig *config, + const void *val_set, void *val_get, int size, int set) +{ + int s; + int ret; + void *dst; + const void *src; + + if (set) { + dst = config->buf_ptr; + src = val_set; + } else { + dst = val_get; + src = config->buf_ptr; + } + if (!dst || !src) + return -1; + switch (config->type) { + case CONFIG_TYPE_PU32: + case CONFIG_TYPE_PI32: + if (size < sizeof(u32)) + return -2; + ((u32 *) dst)[0] = ((const u32 *)src)[0]; + ret = sizeof(u32); + break; + case CONFIG_TYPE_PU64: + if (size < sizeof(u64)) + return -2; + ((u64 *) dst)[0] = ((const u64 *)src)[0]; + ret = sizeof(u64); + break; + case CONFIG_TYPE_PCSTR: + if (set) { + ret = -3; + break; + } + /*rd same as CONFIG_TYPE_PSTR */ + case CONFIG_TYPE_PSTR: + s = min_t(int, size - 1, config->size - 1); + if (s > 0) + strncpy(dst, src, s); + else + ret = -3; + ret = s; + break; + case CONFIG_TYPE_U32: + case CONFIG_TYPE_I32: + if (size < sizeof(u32)) + return -2; + if (set) + config->u32val = ((const u32 *)src)[0]; + else + ((u32 *) dst)[0] = config->u32val; + ret = sizeof(u32); + break; + case CONFIG_TYPE_U64: + if (size < sizeof(u64)) + return -2; + if (set) + config->u64val = ((const u64 *)src)[0]; + else + ((u64 *) dst)[0] = config->u64val; + ret = sizeof(u64); + break; + default: + ret = -4; + } + return ret; +} + +static int configs_setget_node_path_value( + struct mconfig_node *topnode, + const char *path, + const void *val_set, void *val_get, + int size, int set) +{ + struct mconfig_node *node; + struct mconfig *config; + int ret; + + ret = configs_get_node_path_config(topnode, &config, path, &node, set); + if (ret != 0) + return ret; + if (set) + pr_err("start set config val config=%s, val=%x\n", + config->item_name, *(int *)val_set); + ret = configs_setget_config_value(config, val_set, + val_get, size, set); + config_debug("setget config val config=%s, ret=%x end\n", + config->item_name, ret); + configs_put_node(node, 0, topnode); + configs_put_node(node, 1, topnode); + return ret; +} + +int configs_set_node_path_str(struct mconfig_node *topnode, + const char *path, const char *val) +{ + struct mconfig_node *node; + struct mconfig *config; + int ret = -1; + + if (!val || !path || strlen(path) <= 0 || strlen(val) <= 0) + return -1; + ret = configs_get_node_path_config(topnode, &config, path, &node, 1); + if (ret != 0) + return ret; + config_debug("start set config val config=%s, %s\n", + config->item_name, val); + mutex_lock(&node->lock); + ret = configs_str2config(config, val); + mutex_unlock(&node->lock); + configs_put_node(node, 0, topnode); + configs_put_node(node, 1, topnode); + if (ret > 0) + ret = 0;/*set ok*/ + else if (ret == 0) + ret = -1;/*val not changed.*/ + return ret; +} +int configs_set_node_nodepath_str(struct mconfig_node *topnode, + const char *path, const char *val) +{ + if (topnode == NULL) { + return configs_set_node_path_str(topnode, + path, val); + } + if (strncmp(topnode->name, path, strlen(topnode->name))) { + pr_err("nodepath(%s) must start from node=%s\n", + path, topnode->name); + return -1; + } + return configs_set_node_path_str(topnode, + path + strlen(topnode->name) + 1, val); +} + +int configs_set_prefix_path_str(const char *prefix, + const char *path, const char *str) +{ + struct mconfig_node *topnode = NULL; + int ret; + + if (prefix && strlen(prefix) > 0) { + topnode = configs_get_node_path_end_node(NULL, prefix); + if (!topnode) { + pr_err("[0]can't get node from %s\n", prefix); + return -1; + } + } + ret = configs_set_node_path_str(topnode, path, str); + configs_put_node(topnode, 1, NULL); + return ret; +} + +int configs_set_node_path_valonpath( + struct mconfig_node *topnode, + const char *path) +{ + return configs_set_node_path_str(topnode, path, + configs_parser_str_valstr(path)); +} + +int configs_set_prefix_path_valonpath(const char *prefix, + const char *path) +{ + struct mconfig_node *topnode = NULL; + int ret; + + if (prefix && strlen(prefix) > 0) { + topnode = configs_get_node_path_end_node(NULL, prefix); + if (!topnode) { + pr_err("can't get node from %s\n", prefix); + return -1; + } + } + ret = configs_set_node_path_str(topnode, path, + configs_parser_str_valstr(path)); + configs_put_node(topnode, 1, NULL); + return ret; +} + +int configs_get_node_path_str(struct mconfig_node *topnode, + const char *path, char *buf, int size) +{ + struct mconfig_node *node; + struct mconfig *config; + int ret = -1; + + if (!path || strlen(path) <= 0) + return -1; + ret = configs_get_node_path_config(topnode, + &config, path, &node, 0); + if (ret != 0) + return ret; + config_debug("startget config val config=%s\n", + config->item_name); + ret = configs_config2str(config, buf, size); + configs_put_node(node, 0, topnode); + configs_put_node(node, 1, topnode); + return ret; +} +int configs_get_node_nodepath_str(struct mconfig_node *topnode, + const char *path, char *buf, int size) +{ + if (topnode == NULL) + return configs_get_node_path_str(topnode, path, buf, size); + if (strncmp(topnode->name, path, strlen(topnode->name))) { + pr_err("nodepath(%s) must start from node=%s\n", + path, topnode->name); + return -1; + } + return configs_get_node_path_str(topnode, + path + strlen(topnode->name) + 1, + buf, size); + +} + +static inline int configs_set_node_path_value( + struct mconfig_node *topnode, + const char *path, const void *val, int size) +{ + return configs_setget_node_path_value(topnode, + path, val, NULL, size, 1); +} + +static int configs_get_node_path_value(struct mconfig_node *topnode, + const char *path, void *val, int size) +{ + return configs_setget_node_path_value(topnode, + path, NULL, val, size, 0); +} + +int configs_get_node_path_u32(struct mconfig_node *topnode, + const char *path, u32 *val) +{ + return configs_get_node_path_value(topnode, path, val, sizeof(u32)); +} + +int configs_get_node_path_u64(struct mconfig_node *topnode, + const char *path, u64 *val) +{ + return configs_get_node_path_value(topnode, path, val, sizeof(u64)); +} + +int configs_set_node_path_u32(struct mconfig_node *topnode, + const char *path, u32 val) +{ + return configs_set_node_path_value(topnode, path, &val, sizeof(u32)); +} + +int configs_set_node_path_u64(struct mconfig_node *topnode, + const char *path, u64 val) +{ + return configs_set_node_path_value(topnode, path, &val, + sizeof(u64)); +} + +int configs_config_system_init(void) +{ + configs_init_new_node(&root_node, "root", CONFIG_FOR_RW); + configs_register_node(NULL, &root_node); + return 0; +} diff --git a/drivers/amlogic/media/common/codec_mm/configs/configs_module.c b/drivers/amlogic/media/common/codec_mm/configs/configs_module.c new file mode 100644 index 0000000..0087625 --- /dev/null +++ b/drivers/amlogic/media/common/codec_mm/configs/configs_module.c @@ -0,0 +1,479 @@ +/* + * drivers/amlogic/media/common/codec_mm/configs/configs_module.c + * + * Copyright (C) 2017 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define MAX_OPENED_CNT 65536 +#include "configs_priv.h" +#define MODULE_NAME "media-configs-dev" + +static struct class *config_dev_class; +static unsigned int config_major; +struct mediaconfig_node { + const char *parent; + const char *name; + const char *dev_name; + int rw_flags; + atomic_t opened_cnt; + struct device *class_dev; + struct mconfig_node node; + +}; + +static ssize_t all_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + ssize_t s; + + s = configs_list_nodes(NULL, buf, PAGE_SIZE, + LIST_MODE_NODE_CMDVAL_ALL); + if (s > 0) + return s; + return -EPERM; +} + +static ssize_t media_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + ssize_t s; + + s = configs_list_path_nodes("media", buf, PAGE_SIZE, + LIST_MODE_NODE_CMDVAL_ALL); + if (s > 0) + return s; + return -EPERM; +} + +static ssize_t video_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + ssize_t s; + + s = configs_list_path_nodes("media.video", buf, PAGE_SIZE, + LIST_MODE_NODE_CMDVAL_ALL); + if (s > 0) + return s; + return -EPERM; +} +static ssize_t decoder_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + ssize_t s; + + s = configs_list_path_nodes("media.decoder", buf, PAGE_SIZE, + LIST_MODE_NODE_CMDVAL_ALL); + if (s > 0) + return s; + return -EPERM; +} +static ssize_t vdec_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + ssize_t s; + + s = configs_list_path_nodes("media.vdec", buf, PAGE_SIZE, + LIST_MODE_NODE_CMDVAL_ALL); + if (s > 0) + return s; + return -EPERM; +} +static ssize_t tsync_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + ssize_t s; + + s = configs_list_path_nodes("media.tsync", buf, PAGE_SIZE, + LIST_MODE_NODE_CMDVAL_ALL); + if (s > 0) + return s; + return -EPERM; +} + + +static ssize_t amports_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + ssize_t s; + + s = configs_list_path_nodes("media.amports", buf, PAGE_SIZE, + LIST_MODE_NODE_CMDVAL_ALL); + if (s > 0) + return s; + return -EPERM; +} +static ssize_t parser_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + ssize_t s; + + s = configs_list_path_nodes("media.parser", buf, PAGE_SIZE, + LIST_MODE_NODE_CMDVAL_ALL); + if (s > 0) + return s; + return -EPERM; +} + + + +static ssize_t show_config(struct class *class, + struct class_attribute *attr, char *buf) +{ + ssize_t s; + + s = configs_list_nodes(NULL, buf, PAGE_SIZE, + LIST_MODE_NODE_CMDVAL_ALL); + if (s > 0) + return s; + return -EPERM; +} + +static ssize_t store_config(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size) +{ + ssize_t ret; + + ret = configs_set_path_valonpath(buf); + if (ret >= 0) + return size; + return ret; +} + +static ssize_t show_config_debug(struct class *class, + struct class_attribute *attr, char *buf) +{ + return config_dump(buf, PAGE_SIZE); +} + +static ssize_t store_config_debug(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size) +{ + configs_config_setstr(buf); + return size; +} + +static ssize_t audio_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + ssize_t s; + + s = configs_list_path_nodes("media.audio", buf, PAGE_SIZE, + LIST_MODE_NODE_CMDVAL_ALL); + if (s > 0) + return s; + return -EPERM; +} +static ssize_t vfm_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + ssize_t s; + + s = configs_list_path_nodes("media.vfm", buf, PAGE_SIZE, + LIST_MODE_NODE_CMDVAL_ALL); + if (s > 0) + return s; + return -EPERM; +} + +static struct class_attribute configs_class_attrs[] = { + __ATTR_RO(all), + __ATTR_RO(media), + __ATTR_RO(video), + __ATTR_RO(decoder), + __ATTR_RO(amports), + __ATTR_RO(tsync), + __ATTR_RO(parser), + __ATTR_RO(vdec), + __ATTR_RO(audio), + __ATTR_RO(vfm), + __ATTR(config, 0664, + show_config, store_config), + __ATTR(debug, 0664, + show_config_debug, store_config_debug), + __ATTR_NULL +}; + +static struct class media_configs_class = { + .name = "media-configs", + .class_attrs = configs_class_attrs, +}; + +static struct mediaconfig_node mediaconfig_nodes[] = { + {"", "media", "media", CONFIG_FOR_RW}, + {"media", "decoder", "media.decoder", CONFIG_FOR_RW}, + {"media", "parser", "media.parser", CONFIG_FOR_RW}, + {"media", "video", "media.video", CONFIG_FOR_RW}, + {"media", "amports", "media.amports", CONFIG_FOR_RW}, + {"media", "tsync", "media.tsync", CONFIG_FOR_RW}, + {"media", "codec_mm", "media.codec_mm", CONFIG_FOR_RW}, + {"media", "audio", "media.audio", CONFIG_FOR_RW}, + {"media", "vfm", "media.vfm", CONFIG_FOR_RW}, +}; + +struct config_file_private { + struct mediaconfig_node *node; + char common[128]; + pid_t pid; + pid_t tgid; + long opened_jiffies; + long last_access_jiffies; + long access_get_cnt; + long access_set_cnt; + long access_dump_cnt; + long error_cnt; + int enable_trace_get; + int enable_trace_set; + int last_read_end; +}; + +static int configs_open(struct inode *inode, struct file *file) +{ + struct mediaconfig_node *node = &mediaconfig_nodes[iminor(inode)]; + struct config_file_private *priv; + + if (atomic_read(&node->opened_cnt) > MAX_OPENED_CNT) { + pr_err("too many files opened.!!\n"); + return -EMFILE; + } + priv = kzalloc(sizeof(struct config_file_private), GFP_KERNEL); + if (!priv) + return -ENOMEM; + file->private_data = priv; + priv->pid = current->pid; + priv->tgid = current->tgid; + priv->opened_jiffies = jiffies; + priv->node = node; + atomic_inc(&node->opened_cnt); + configs_inc_node_ref(&node->node); + return 0; +} +static ssize_t configs_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct config_file_private *priv = file->private_data; + struct mediaconfig_node *node = priv->node; + int ret; + + if (*ppos > 0) + return 0;/*don't support seek read. read end.*/ + if (!access_ok(VERIFY_WRITE, buf, count)) + return -EIO; + ret = configs_list_nodes(&node->node, buf, count, + LIST_MODE_NODE_CMDVAL_ALL); + if (ret > 0) + *ppos = ret; + return ret; +} + +static int configs_close(struct inode *inode, struct file *file) +{ + struct config_file_private *priv = file->private_data; + struct mediaconfig_node *node = priv->node; + + configs_dec_node_ref(&node->node); + atomic_dec(&node->opened_cnt); + + kfree(priv); + + return 0; +} +static long configs_ioctl(struct file *file, unsigned int cmd, ulong arg) +{ + struct config_file_private *priv = file->private_data; + struct mediaconfig_node *node = priv->node; + struct media_config_io_str io; + struct media_config_io_str *user_io = (void *)arg; + int r = -1; + + priv->last_access_jiffies = jiffies; + switch (cmd) { + case MEDIA_CONFIG_SET_CMD_STR: + priv->access_set_cnt++; + r = copy_from_user(io.cmd_path, + user_io->cmd_path, sizeof(io.cmd_path)); + r |= copy_from_user(io.val, user_io->val, sizeof(io.val)); + /*pr_info("set%s:%s dev=%s\n", io.cmd_path,*/ + /*io.val, node->dev_name);*/ + if (r) { + r = -EIO; + break; + } + if (!strncmp(io.cmd_path, node->dev_name, + strlen(node->dev_name))) + r = configs_set_node_nodepath_str(NULL, + io.cmd_path, + io.val); + else + pr_info("set %s %s not match devname=%s\n", + io.cmd_path, io.val, node->dev_name); + break; + case MEDIA_CONFIG_GET_CMD_STR: + r = -1; + priv->access_get_cnt++; + r = copy_from_user(&io.cmd_path, + user_io->cmd_path, sizeof(io.cmd_path)); + if (r) { + r = -EIO; + break; + } + io.val[0] = '\0'; + if (!strncmp(io.cmd_path, node->dev_name, + strlen(node->dev_name))) { + r = configs_get_node_nodepath_str(NULL, + io.cmd_path, + io.val, + sizeof(io.val)); + + /*pr_info("configs_get_node_nodepath_str*/ + /*ret %x [%s]\n", r, io.val);*/ + if (r > 0 && r <= sizeof(io.val) - 1) { + /*+1 for end str.*/ + if (copy_to_user(user_io->val, io.val, r + 1) != 0) { + r = -EIO; + break; + } + put_user(r, &user_io->ret); + r = 0; + } else { + put_user(-1, &user_io->ret); + } + } else + pr_info("set %s %s not match devname=%s\n", + io.cmd_path, io.val, node->dev_name); + break; + default: + r = -EINVAL; + pr_err("unsupport cmd %x\n", cmd); + } + if (r < 0) + priv->error_cnt++; + return r; +} + + + +#ifdef CONFIG_COMPAT +static long configs_compat_ioctl(struct file *file, + unsigned int cmd, ulong arg) +{ + return configs_ioctl(file, cmd, (ulong)compat_ptr(arg)); +} +#endif +static const struct file_operations configs_fops = { + .owner = THIS_MODULE, + .open = configs_open, + .read = configs_read, + .release = configs_close, + .unlocked_ioctl = configs_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = configs_compat_ioctl, +#endif +}; + + +static int __init configs_init_devices(void) +{ + int i; + int num = sizeof(mediaconfig_nodes)/sizeof(struct mediaconfig_node); + + int r; + + r = class_register(&media_configs_class); + if (r) { + pr_err("configs class create fail.\n"); + goto error1; + } + + r = register_chrdev(0, MODULE_NAME, &configs_fops); + if (r < 0) { + pr_err("Can't allocate major for config device\n"); + goto error1; + } + config_major = r; + + config_dev_class = class_create(THIS_MODULE, MODULE_NAME); + num = sizeof(mediaconfig_nodes)/sizeof(struct mediaconfig_node); + for (i = 0; i < num; i++) { + struct mediaconfig_node *mnode = &mediaconfig_nodes[i]; + + mnode->class_dev = device_create(config_dev_class, NULL, + MKDEV(config_major, i), NULL, + mnode->dev_name); + if (mnode->class_dev == NULL) { + pr_err("device_create %s failed\n", mnode->dev_name); + r = -1; + goto error2; + } + } + return 0; +#if 0 +error3: + for (mnode = &mediaconfig_nodes[0], i = 0; i < num; i++, mnode++) + device_destroy(config_dev_class, MKDEV(config_major, i)); + class_destroy(config_dev_class); +#endif +error2: + unregister_chrdev(config_major, MODULE_NAME); +error1: + class_destroy(&media_configs_class); + return r; +} +module_init(configs_init_devices); + +static int __init media_configs_system_init(void) +{ + int i; + int num = sizeof(mediaconfig_nodes)/sizeof(struct mediaconfig_node); + struct mediaconfig_node *mnode; + int r; + + pr_info("media_configs_system_init\n"); + configs_config_system_init(); + for (i = 0; i < num; i++) { + mnode = &mediaconfig_nodes[i]; + configs_init_new_node(&mnode->node, mnode->name, + mnode->rw_flags); + r = configs_register_path_node(mnode->parent, + &mnode->node); + if (r < 0) { + pr_err("ERR!!!.register node[%s] to [%s] failed!\n", + mnode->name, mnode->parent); + return r; + } + } + + return 0; +} + +arch_initcall(media_configs_system_init); +MODULE_DESCRIPTION("AMLOGIC config modules driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/amlogic/media/common/codec_mm/configs/configs_priv.h b/drivers/amlogic/media/common/codec_mm/configs/configs_priv.h new file mode 100644 index 0000000..82c6025 --- /dev/null +++ b/drivers/amlogic/media/common/codec_mm/configs/configs_priv.h @@ -0,0 +1,34 @@ +/* + * drivers/amlogic/media/common/codec_mm/configs/configs_priv.h + * + * Copyright (C) 2017 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 AMLOGIC_MEDIA_CONFIG_HEADER_PRIV__ +#define AMLOGIC_MEDIA_CONFIG_HEADER_PRIV__ + +#include +#include +#include +#include +int configs_config_system_init(void); +int configs_inc_node_ref_locked( + struct mconfig_node *node); +int configs_dec_node_ref_locked( + struct mconfig_node *node); +int config_dump(void *buf, int size); +int configs_config_setstr(const char *buf); + +#endif + diff --git a/drivers/amlogic/media/common/codec_mm/configs/configs_test.c b/drivers/amlogic/media/common/codec_mm/configs/configs_test.c new file mode 100644 index 0000000..c0f4eb8 --- /dev/null +++ b/drivers/amlogic/media/common/codec_mm/configs/configs_test.c @@ -0,0 +1,145 @@ +/* + * drivers/amlogic/media/common/codec_mm/configs/configs_test.c + * + * Copyright (C) 2017 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 + +static struct mconfig_node media; +static struct mconfig_node vdec; +static struct mconfig_node decoder; +static struct mconfig_node parser; +static struct mconfig_node codec; +static struct mconfig_node fast; +static struct mconfig_node fast2; + + +static struct mconfig vdec_configs[] = { + MC_I32("vdec", 1), + MC_I32("vdec1", 1), + MC_I32("vdec2", 2), + MC_I32("vdec3", 3), + MC_I32("vdec4", 4), + +}; + +static struct mconfig decoder_configs[] = { + MC_I32("264", 1), + MC_I32("265", 1), + MC_U32("vp9", 2), + MC_U32("vc1", 3), + MC_U32("rmvb", 4), +}; + + + +static struct mconfig parser_configs[] = { + MC_I32("ts", 1), + MC_I32("es", 1), + MC_I32("demux", 2), + MC_U32("rm", 3), + MC_U32("ps", 4), +}; + +static struct mconfig vdec_profile[] = { + MC_CSTR("265", "compress,di,c,mmu"), + MC_CSTR("264", "compress,di,c,4k"), + MC_CSTR("263", "compress,di,c"), + MC_CSTR("vc1", "compress,di,c"), + MC_CSTR("rm", "compress,di,di,ps"), +}; +static int a, b, c, d, e; +struct mconfig fast_profile[] = { + MC_PI32("265", &a), + MC_PI32("264", &b), + MC_PI32("263", &c), + MC_PI32("vc1", &d), + MC_PI32("rm", &e), +}; + +int dump_set(const char *trigger, int id, const char *buf, int size) +{ + pr_err("trigger-->[%s]\n", buf); + return size; +} + + +struct mconfig fast2_profile[] = { + MC_FUN("trigger", NULL, &dump_set), +}; + + + + + + +static int config_test(void) +{ + static int init; + + if (init > 0) + return 0; + init++; + configs_init_new_node(&media, "debug", CONFIG_FOR_RW); + configs_register_node(NULL, &media); + + configs_init_new_node(&vdec, "vdec", CONFIG_FOR_RW); + configs_register_node(&media, &vdec); + REG_CONFIGS(&vdec, vdec_configs); + + configs_init_new_node(&decoder, "decoder", CONFIG_FOR_RW); + REG_CONFIGS(&decoder, decoder_configs); + configs_register_node(&media, &decoder); + + configs_init_new_node(&parser, "parser", CONFIG_FOR_W); + REG_CONFIGS(&parser, parser_configs); + configs_register_node(&media, &parser); + + configs_init_new_node(&codec, "codec", CONFIG_FOR_R); + REG_CONFIGS(&codec, vdec_profile); + configs_register_node(&media, &codec); + + configs_init_new_node(&fast, "fast", CONFIG_FOR_RW); + REG_CONFIGS(&fast, fast_profile); + configs_register_node(&media, &fast); + + configs_init_new_node(&fast2, "trigger", CONFIG_FOR_W); + REG_CONFIGS(&fast2, fast2_profile); + configs_register_node(&media, &fast2); + + /* configs_register_configs(); */ + return 0; +} +int config_dump(void *buf, int size) +{ + config_test(); + b++; + c = b+3; + a++; + d += 2; + return configs_list_nodes(NULL, buf, size, + LIST_MODE_FULL_CMDVAL_ALL); +} +int configs_config_setstr(const char *buf) +{ + int ret; + + config_test(); + pr_info("-----------start configs_config_setstr\n\n"); + ret = configs_set_path_valonpath(buf); + pr_info("-----------end configs_config_setstr\n\n"); + return ret; +} + diff --git a/drivers/amlogic/media/common/ge2d/ge2d_hw.c b/drivers/amlogic/media/common/ge2d/ge2d_hw.c index 9766edb..8d88c99 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_hw.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_hw.c @@ -933,7 +933,7 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) * scale_out_done(test1823) hang issue when * scaling down ratio is high. */ - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TXLX) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX) ge2d_reg_set_bits(GE2D_GEN_CTRL4, cfg->hang_flag, 0, 1); ge2d_reg_write(GE2D_CMD_CTRL, (cfg->src2_fill_color_en << 9) | @@ -980,7 +980,7 @@ void ge2d_set_gen(struct ge2d_gen_s *cfg) (cfg->vfmt_onoff_en << 15) | (cfg->dp_off_cnt << 0) ); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TXLX) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX) { ge2d_reg_set_bits(GE2D_GEN_CTRL4, (cfg->fifo_size << 26) | (cfg->fifo_size << 24) | diff --git a/drivers/amlogic/media/common/rdma/Makefile b/drivers/amlogic/media/common/rdma/Makefile index d519938..4d61427e 100644 --- a/drivers/amlogic/media/common/rdma/Makefile +++ b/drivers/amlogic/media/common/rdma/Makefile @@ -1,5 +1,5 @@ -obj-$(CONFIG_AMLOGIC_MEDIA_RDMA) += rdma_module.o -rdma_module-objs += rdma_mgr.o +obj-$(CONFIG_AMLOGIC_MEDIA_RDMA) += rdma_mgr.o + ifeq ($(CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA),y) -rdma_module-objs += rdma.o +obj-$(CONFIG_AMLOGIC_MEDIA_RDMA) += rdma.o endif diff --git a/drivers/amlogic/media/common/rdma/rdma.c b/drivers/amlogic/media/common/rdma/rdma.c index deaca89..f31374d 100644 --- a/drivers/amlogic/media/common/rdma/rdma.c +++ b/drivers/amlogic/media/common/rdma/rdma.c @@ -47,28 +47,17 @@ #define Wr_reg_bits(adr, val, start, len) \ WRITE_VCBUS_REG_BITS(adr, val, start, len) - -/*#define CONFIG_RDMA_IN_RDMAIRQ*/ -/*#define CONFIG_RDMA_IN_TASK*/ - #define RDMA_TABLE_SIZE (8 * (PAGE_SIZE)) - static int vsync_rdma_handle; - static int irq_count; - static int enable; - -static int enable_mask = 0x400ff; - +static int cur_enable; static int pre_enable_; - static int debug_flag; - static int vsync_cfg_count; - -#define RDMA_VSYNC_INPUT_TRIG 0x1 -static bool vsync_rdma_config_delay_flag; +static u32 force_rdma_config; +static bool first_config; +static bool rdma_done; static void vsync_rdma_irq(void *arg); @@ -77,99 +66,80 @@ struct rdma_op_s vsync_rdma_op = { NULL }; -static struct semaphore rdma_sema; -struct task_struct *rdma_task; -static unsigned int rdma_config_flag; - -static unsigned char rdma_start_flag; - - -static int rdma_task_handle(void *data) -{ - int ret = 0; - - while (1) { - ret = down_interruptible(&rdma_sema); - if (debug_flag & 2) - pr_info("%s: %x\r\n", __func__, rdma_config_flag); - if (rdma_config_flag == 1) { - rdma_config_flag = 0; - if (rdma_config(vsync_rdma_handle, - RDMA_VSYNC_INPUT_TRIG) != 1){ - rdma_config_flag = 2; - /* - *fail or rdma table empty, - *there is no rdma irq - */ - } - } - if (rdma_start_flag) { - if (vsync_rdma_handle <= 0) - vsync_rdma_handle = - rdma_register(&vsync_rdma_op, - NULL, RDMA_TABLE_SIZE); - rdma_start_flag = 0; - } - } - return 0; -} - - void vsync_rdma_config(void) { - int enable_ = ((enable & enable_mask) | (enable_mask >> 8)) & 0xff; + int iret = 0; + int enable_ = cur_enable & 0xf; - if (vsync_rdma_handle == 0) + if (vsync_rdma_handle <= 0) return; + /* first frame not use rdma */ + if (!first_config) { + cur_enable = enable; + pre_enable_ = enable_; + first_config = true; + rdma_done = false; + return; + } + + /* if rdma mode changed, reset rdma */ if (pre_enable_ != enable_) { - if (((enable_mask >> 17) & 0x1) == 0) - rdma_clear(vsync_rdma_handle); - vsync_rdma_config_delay_flag = false; + rdma_clear(vsync_rdma_handle); + force_rdma_config = 1; } - if (enable == 1) - rdma_watchdog_setting(1); - else - rdma_watchdog_setting(0); - if (enable_ == 1) { -#ifdef CONFIG_RDMA_IN_TASK - if (debug_flag & 2) { - pr_info("%s: %d : %d :\r\n", __func__, - rdma_config_flag, pre_enable_); - } - if ((rdma_config_flag == 2) || (pre_enable_ != enable)) { - rdma_config_flag = 1; - up(&rdma_sema); - } - -#elif (defined CONFIG_RDMA_IN_RDMAIRQ) - if (pre_enable_ != enable_) - rdma_config(vsync_rdma_handle, RDMA_VSYNC_INPUT_TRIG); -#else - rdma_config(vsync_rdma_handle, RDMA_VSYNC_INPUT_TRIG); - vsync_cfg_count++; -#endif - } else if (enable_ == 2) - rdma_config(vsync_rdma_handle, - RDMA_TRIGGER_MANUAL); /*manually in cur vsync*/ - else if (enable_ == 3) - ; - else if (enable_ == 4) - rdma_config(vsync_rdma_handle, - RDMA_TRIGGER_DEBUG1); /*for debug*/ - else if (enable_ == 5) - rdma_config(vsync_rdma_handle, - RDMA_TRIGGER_DEBUG2); /*for debug*/ - else if (enable_ == 6) - ; + if (force_rdma_config) + rdma_done = true; + + if (enable_ == 1) { + if (rdma_done) + iret = rdma_watchdog_setting(0); + else + iret = rdma_watchdog_setting(1); + } else { + /* not vsync mode */ + iret = rdma_watchdog_setting(0); + force_rdma_config = 1; + } + rdma_done = false; + if (iret) + force_rdma_config = 1; + + iret = 0; + if (force_rdma_config) { + if (enable_ == 1) { + iret = rdma_config(vsync_rdma_handle, + RDMA_TRIGGER_VSYNC_INPUT); + if (iret) + vsync_cfg_count++; + } else if (enable_ == 2) + /*manually in cur vsync*/ + rdma_config(vsync_rdma_handle, + RDMA_TRIGGER_MANUAL); + else if (enable_ == 3) + ; + else if (enable_ == 4) + rdma_config(vsync_rdma_handle, + RDMA_TRIGGER_DEBUG1); /*for debug*/ + else if (enable_ == 5) + rdma_config(vsync_rdma_handle, + RDMA_TRIGGER_DEBUG2); /*for debug*/ + else if (enable_ == 6) + ; + if (!iret) + force_rdma_config = 1; + else + force_rdma_config = 0; + } pre_enable_ = enable_; + cur_enable = enable; } EXPORT_SYMBOL(vsync_rdma_config); void vsync_rdma_config_pre(void) { - int enable_ = ((enable&enable_mask)|(enable_mask>>8))&0xff; + int enable_ = cur_enable & 0xf; if (vsync_rdma_handle == 0) return; @@ -182,48 +152,32 @@ EXPORT_SYMBOL(vsync_rdma_config_pre); static void vsync_rdma_irq(void *arg) { -#ifdef CONFIG_RDMA_IN_TASK - int enable_ = ((enable&enable_mask) | (enable_mask >> 8)) & 0xff; + int iret; + int enable_ = cur_enable & 0xf; if (enable_ == 1) { - rdma_config_flag = 1; - up(&rdma_sema); + /*triggered by next vsync*/ + iret = rdma_config(vsync_rdma_handle, + RDMA_TRIGGER_VSYNC_INPUT); + if (iret) + vsync_cfg_count++; } else - rdma_config(vsync_rdma_handle, 0); - -#elif (defined CONFIG_RDMA_IN_RDMAIRQ) - int enable_ = ((enable&enable_mask) | (enable_mask >> 8)) & 0xff; + iret = rdma_config(vsync_rdma_handle, 0); + pre_enable_ = enable_; - if (enable_ == 1) - rdma_config(vsync_rdma_handle, - RDMA_VSYNC_INPUT_TRIG); /*triggered by next vsync*/ + if ((!iret) || (enable_ != 1)) + force_rdma_config = 1; else - rdma_config(vsync_rdma_handle, 0); -#endif + force_rdma_config = 0; + rdma_done = true; irq_count++; + return; } -MODULE_PARM_DESC(enable, "\n enable\n"); -module_param(enable, uint, 0664); - -MODULE_PARM_DESC(enable_mask, "\n enable_mask\n"); -module_param(enable_mask, uint, 0664); - -MODULE_PARM_DESC(irq_count, "\n irq_count\n"); -module_param(irq_count, uint, 0664); - - - -MODULE_PARM_DESC(debug_flag, "\n debug_flag\n"); -module_param(debug_flag, uint, 0664); - - -MODULE_PARM_DESC(vsync_cfg_count, "\n vsync_cfg_count\n"); -module_param(vsync_cfg_count, uint, 0664); - u32 VSYNC_RD_MPEG_REG(u32 adr) { - int enable_ = ((enable&enable_mask) | (enable_mask >> 8)) & 0xff; + int enable_ = cur_enable & 0xf; + u32 read_val = Rd(adr); if ((enable_ != 0) && (vsync_rdma_handle > 0)) @@ -235,7 +189,7 @@ EXPORT_SYMBOL(VSYNC_RD_MPEG_REG); int VSYNC_WR_MPEG_REG(u32 adr, u32 val) { - int enable_ = ((enable & enable_mask) | (enable_mask >> 8)) & 0xff; + int enable_ = cur_enable & 0xf; if ((enable_ != 0) && (vsync_rdma_handle > 0)) { rdma_write_reg(vsync_rdma_handle, adr, val); @@ -250,11 +204,11 @@ EXPORT_SYMBOL(VSYNC_WR_MPEG_REG); int VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len) { - int enable_ = ((enable & enable_mask) | (enable_mask >> 8)) & 0xff; + int enable_ = cur_enable & 0xf; if ((enable_ != 0) && (vsync_rdma_handle > 0)) { rdma_write_reg_bits(vsync_rdma_handle, adr, val, start, len); - } else { + } else { u32 read_val = Rd(adr); u32 write_val = (read_val & ~(((1L<<(len))-1)<<(start))) |((unsigned int)(val) << (start)); @@ -269,21 +223,14 @@ EXPORT_SYMBOL(VSYNC_WR_MPEG_REG_BITS); bool is_vsync_rdma_enable(void) { - int enable_ = ((enable & enable_mask) | (enable_mask >> 8)) & 0xff; + bool ret; + int enable_ = cur_enable & 0xf; - return (enable_ != 0) && (((enable_mask >> 19) & 0x1) == 0); + ret = (enable_ != 0); + return ret; } EXPORT_SYMBOL(is_vsync_rdma_enable); -void start_rdma(void) -{ - if (vsync_rdma_handle <= 0) { - rdma_start_flag = 1; - up(&rdma_sema); - } -} -EXPORT_SYMBOL(start_rdma); - void enable_rdma_log(int flag) { if (flag) @@ -302,14 +249,30 @@ EXPORT_SYMBOL(enable_rdma); static int __init rdma_init(void) { - WRITE_VCBUS_REG(VPU_VDISP_ASYNC_HOLD_CTRL, 0x18101810); - WRITE_VCBUS_REG(VPU_VPUARB2_ASYNC_HOLD_CTRL, 0x18101810); - + vsync_rdma_handle = + rdma_register(&vsync_rdma_op, + NULL, RDMA_TABLE_SIZE); + pr_info("%s video rdma handle = %d.\n", __func__, + vsync_rdma_handle); + cur_enable = 0; enable = 1; - - sema_init(&rdma_sema, 1); - kthread_run(rdma_task_handle, NULL, "kthread_h265"); + force_rdma_config = 1; return 0; } module_init(rdma_init); + +MODULE_PARM_DESC(enable, "\n enable\n"); +module_param(enable, uint, 0664); + +MODULE_PARM_DESC(irq_count, "\n irq_count\n"); +module_param(irq_count, uint, 0664); + +MODULE_PARM_DESC(debug_flag, "\n debug_flag\n"); +module_param(debug_flag, uint, 0664); + +MODULE_PARM_DESC(vsync_cfg_count, "\n vsync_cfg_count\n"); +module_param(vsync_cfg_count, uint, 0664); + +MODULE_PARM_DESC(force_rdma_config, "\n force_rdma_config\n"); +module_param(force_rdma_config, uint, 0664); diff --git a/drivers/amlogic/media/common/rdma/rdma_mgr.c b/drivers/amlogic/media/common/rdma/rdma_mgr.c index 03dc8d6..3b626e5 100644 --- a/drivers/amlogic/media/common/rdma/rdma_mgr.c +++ b/drivers/amlogic/media/common/rdma/rdma_mgr.c @@ -51,22 +51,21 @@ #define rdma_io_read(addr) readl(addr) #define rdma_io_write(addr, val) writel((val), addr) -#define RDMA_VSYNC_INPUT_TRIG 0x1 -#define SKIP_OSD_CHANNEL +/* #define SKIP_OSD_CHANNEL */ int rdma_mgr_irq_request; +int rdma_reset_tigger_flag; -static int debug_flag_mgr; - +static int debug_flag; /* burst size 0=16; 1=24; 2=32; 3=48.*/ static int ctrl_ahb_rd_burst_size = 3; static int ctrl_ahb_wr_burst_size = 3; -static int rdma_watchdog = 4; +static int rdma_watchdog = 10; static int reset_count; static int rdma_watchdog_count; -static int rdma_vsync_isr_done; -static int rdma_monitor_reg; static int rdma_force_reset = -1; +static u16 trace_reg; + #define RDMA_NUM 8 struct rdma_regadr_s { u32 rdma_ahb_start_addr; @@ -92,6 +91,7 @@ struct rdma_instance_s { u32 *rdma_table_addr; u32 rdma_table_phy_addr; int rdma_item_count; + int rdma_write_count; unsigned char keep_buf; unsigned char used; int prev_trigger_type; @@ -109,93 +109,121 @@ static struct rdma_device_info rdma_info; static struct rdma_regadr_s rdma_regadr[RDMA_NUM] = { {RDMA_AHB_START_ADDR_MAN, - RDMA_AHB_END_ADDR_MAN, - 0, 0, - RDMA_ACCESS_MAN, 1, - RDMA_ACCESS_MAN, 2, - 24, 24}, + RDMA_AHB_END_ADDR_MAN, + 0, 0, + RDMA_ACCESS_MAN, 1, + RDMA_ACCESS_MAN, 2, + 24, 24 + }, {RDMA_AHB_START_ADDR_1, - RDMA_AHB_END_ADDR_1, - RDMA_ACCESS_AUTO, 8, - RDMA_ACCESS_AUTO, 1, - RDMA_ACCESS_AUTO, 5, - 25, 25}, + RDMA_AHB_END_ADDR_1, + RDMA_ACCESS_AUTO, 8, + RDMA_ACCESS_AUTO, 1, + RDMA_ACCESS_AUTO, 5, + 25, 25 + }, {RDMA_AHB_START_ADDR_2, RDMA_AHB_END_ADDR_2, - RDMA_ACCESS_AUTO, 16, - RDMA_ACCESS_AUTO, 2, - RDMA_ACCESS_AUTO, 6, - 26, 26}, + RDMA_ACCESS_AUTO, 16, + RDMA_ACCESS_AUTO, 2, + RDMA_ACCESS_AUTO, 6, + 26, 26 + }, {RDMA_AHB_START_ADDR_3, - RDMA_AHB_END_ADDR_3, - RDMA_ACCESS_AUTO, 24, - RDMA_ACCESS_AUTO, 3, - RDMA_ACCESS_AUTO, 7, - 27, 27}, + RDMA_AHB_END_ADDR_3, + RDMA_ACCESS_AUTO, 24, + RDMA_ACCESS_AUTO, 3, + RDMA_ACCESS_AUTO, 7, + 27, 27 + }, {RDMA_AHB_START_ADDR_4, RDMA_AHB_END_ADDR_4, RDMA_ACCESS_AUTO3, 0, RDMA_ACCESS_AUTO2, 0, RDMA_ACCESS_AUTO2, 4, - 28, 28}, + 28, 28 + }, {RDMA_AHB_START_ADDR_5, - RDMA_AHB_END_ADDR_5, - RDMA_ACCESS_AUTO3, 8, - RDMA_ACCESS_AUTO2, 1, - RDMA_ACCESS_AUTO2, 5, - 29, 29}, + RDMA_AHB_END_ADDR_5, + RDMA_ACCESS_AUTO3, 8, + RDMA_ACCESS_AUTO2, 1, + RDMA_ACCESS_AUTO2, 5, + 29, 29 + }, {RDMA_AHB_START_ADDR_6, - RDMA_AHB_END_ADDR_6, - RDMA_ACCESS_AUTO3, 16, - RDMA_ACCESS_AUTO2, 2, - RDMA_ACCESS_AUTO2, 6, - 30, 30}, + RDMA_AHB_END_ADDR_6, + RDMA_ACCESS_AUTO3, 16, + RDMA_ACCESS_AUTO2, 2, + RDMA_ACCESS_AUTO2, 6, + 30, 30 + }, {RDMA_AHB_START_ADDR_7, - RDMA_AHB_END_ADDR_7, - RDMA_ACCESS_AUTO3, 24, - RDMA_ACCESS_AUTO2, 3, - RDMA_ACCESS_AUTO2, 7, - 31, 31} + RDMA_AHB_END_ADDR_7, + RDMA_ACCESS_AUTO3, 24, + RDMA_ACCESS_AUTO2, 3, + RDMA_ACCESS_AUTO2, 7, + 31, 31 + } }; int rdma_register(struct rdma_op_s *rdma_op, void *op_arg, int table_size) { int i; + unsigned long flags; struct rdma_device_info *info = &rdma_info; dma_addr_t dma_handle; - + spin_lock_irqsave(&rdma_lock, flags); for (i = 1; i < RDMA_NUM; i++) { /* 0 is reserved for RDMA MANUAL */ if (info->rdma_ins[i].op == NULL && - info->rdma_ins[i].used == 0) { - info->rdma_ins[i].not_process = 0; - info->rdma_ins[i].op_arg = op_arg; - - if (info->rdma_ins[i].rdma_table_size == 0) { - info->rdma_ins[i].rdma_table_addr = - dma_alloc_coherent(&info->rdma_dev->dev, - table_size, &dma_handle, GFP_KERNEL); - info->rdma_ins[i].rdma_table_phy_addr = - (u32) (dma_handle); - - info->rdma_ins[i].reg_buf = - kmalloc(table_size, GFP_KERNEL); - pr_info("%s, rdma_table_addr %p rdma_table_addr_phy %x reg_buf %p\n", - __func__, info->rdma_ins[i].rdma_table_addr, - info->rdma_ins[i].rdma_table_phy_addr, - info->rdma_ins[i].reg_buf); - info->rdma_ins[i].rdma_table_size = table_size; - } + info->rdma_ins[i].used == 0) { info->rdma_ins[i].op = rdma_op; break; } } + spin_unlock_irqrestore(&rdma_lock, flags); if (i < RDMA_NUM) { + info->rdma_ins[i].not_process = 0; + info->rdma_ins[i].op_arg = op_arg; + info->rdma_ins[i].rdma_item_count = 0; + info->rdma_ins[i].rdma_write_count = 0; + if (info->rdma_ins[i].rdma_table_size == 0) { + info->rdma_ins[i].rdma_table_addr = + dma_alloc_coherent( + &info->rdma_dev->dev, table_size, + &dma_handle, GFP_KERNEL); + info->rdma_ins[i].rdma_table_phy_addr + = (u32)(dma_handle); + info->rdma_ins[i].reg_buf = + kmalloc(table_size, GFP_KERNEL); + pr_info("%s, rdma_table_addr %p rdma_table_addr_phy %x reg_buf %p\n", + __func__, + info->rdma_ins[i].rdma_table_addr, + info->rdma_ins[i].rdma_table_phy_addr, + info->rdma_ins[i].reg_buf); + info->rdma_ins[i].rdma_table_size = table_size; + } + if (info->rdma_ins[i].rdma_table_addr == NULL || info->rdma_ins[i].reg_buf == NULL) { + if (!info->rdma_ins[i].keep_buf) { + kfree(info->rdma_ins[i].reg_buf); + info->rdma_ins[i].reg_buf = NULL; + } + if (info->rdma_ins[i].rdma_table_addr) { + dma_free_coherent( + &info->rdma_dev->dev, + table_size, + info->rdma_ins[i].rdma_table_addr, + (dma_addr_t) + info->rdma_ins[i].rdma_table_phy_addr); + info->rdma_ins[i].rdma_table_addr = NULL; + } + info->rdma_ins[i].rdma_table_size = 0; info->rdma_ins[i].op = NULL; i = -1; - pr_info("%s: memory allocate fail\n", __func__); + pr_info("%s: memory allocate fail\n", + __func__); } else pr_info("%s success, handle %d table_size %d\n", __func__, i, table_size); @@ -212,43 +240,44 @@ void rdma_unregister(int i) pr_info("%s(%d)\r\n", __func__, i); if (i > 0 && i < RDMA_NUM && info->rdma_ins[i].op) { - int table_size; - - /*rdma_clear(i); */ - spin_lock_irqsave(&rdma_lock, flags); - table_size = info->rdma_ins[i].rdma_table_size; - info->rdma_ins[i].op = NULL; - if (!info->rdma_ins[i].keep_buf) - info->rdma_ins[i].rdma_table_size = 0; - spin_unlock_irqrestore(&rdma_lock, flags); - + /*rdma_clear(i);*/ info->rdma_ins[i].op_arg = NULL; if (!info->rdma_ins[i].keep_buf) { kfree(info->rdma_ins[i].reg_buf); info->rdma_ins[i].reg_buf = NULL; - if (info->rdma_ins[i].rdma_table_addr) { - dma_free_coherent(&info->rdma_dev->dev, - table_size, - info->rdma_ins[i].rdma_table_addr, - (dma_addr_t) - info->rdma_ins[i].rdma_table_phy_addr); - } } + if (info->rdma_ins[i].rdma_table_addr) { + dma_free_coherent(&info->rdma_dev->dev, + info->rdma_ins[i].rdma_table_size, + info->rdma_ins[i].rdma_table_addr, + (dma_addr_t) + info->rdma_ins[i].rdma_table_phy_addr); + info->rdma_ins[i].rdma_table_addr = NULL; + } + info->rdma_ins[i].rdma_table_size = 0; + spin_lock_irqsave(&rdma_lock, flags); + info->rdma_ins[i].op = NULL; + spin_unlock_irqrestore(&rdma_lock, flags); } } EXPORT_SYMBOL(rdma_unregister); static void rdma_reset(unsigned char external_reset) { - if (debug_flag_mgr & 4) - pr_info("%s(%d)\n", __func__, external_reset); + if (debug_flag & 4) + pr_info("%s(%d)\n", + __func__, external_reset); if (external_reset) { - WRITE_MPEG_REG(RESET4_REGISTER, (1 << 5)); + WRITE_MPEG_REG( + RESET4_REGISTER, + (1 << 5)); } else { WRITE_VCBUS_REG(RDMA_CTRL, (0x1 << 1)); WRITE_VCBUS_REG(RDMA_CTRL, (0x1 << 1)); - WRITE_VCBUS_REG(RDMA_CTRL, (ctrl_ahb_wr_burst_size << 4) | - (ctrl_ahb_rd_burst_size << 2) | (0x0 << 1)); + WRITE_VCBUS_REG(RDMA_CTRL, + (ctrl_ahb_wr_burst_size << 4) | + (ctrl_ahb_rd_burst_size << 2) | + (0x0 << 1)); } reset_count++; } @@ -260,14 +289,13 @@ irqreturn_t rdma_mgr_isr(int irq, void *dev_id) int retry_count = 0; u32 rdma_status; int i; - - if (debug_flag_mgr & 0x10) + if (debug_flag & 0x10) return IRQ_HANDLED; rdma_isr_count++; QUERY: retry_count++; rdma_status = READ_VCBUS_REG(RDMA_STATUS); - if ((debug_flag_mgr & 4) && ((rdma_isr_count % 30) == 0)) + if ((debug_flag & 4) && ((rdma_isr_count % 30) == 0)) pr_info("%s: %x\r\n", __func__, rdma_status); for (i = 0; i < RDMA_NUM; i++) { struct rdma_instance_s *ins = &info->rdma_ins[i]; @@ -281,19 +309,15 @@ QUERY: if (i == 3) continue; #endif - if (ins->prev_trigger_type == RDMA_VSYNC_INPUT_TRIG) { - rdma_vsync_isr_done = 1; - ; - } if (rdma_status & (1 << ins->rdma_regadr->irq_status_bitpos)) { - if (debug_flag_mgr & 2) + if (debug_flag & 2) pr_info("%s: process %d\r\n", __func__, i); - WRITE_VCBUS_REG(RDMA_CTRL, - (1 << ins->rdma_regadr->clear_irq_bitpos)); - if (ins->op && ins->op->irq_cb) ins->op->irq_cb(ins->op->arg); + + WRITE_VCBUS_REG(RDMA_CTRL, + (1 << ins->rdma_regadr->clear_irq_bitpos)); } } rdma_status = READ_VCBUS_REG(RDMA_STATUS); @@ -328,15 +352,19 @@ int rdma_config(int handle, int trigger_type) struct rdma_instance_s *ins = &info->rdma_ins[handle]; bool auto_start = false; - if (handle == 0) - pr_info("%s error, rdma_config(handle == 0) not allowed\n", - __func__); + if (handle == 0 || handle >= RDMA_NUM) { + pr_info( + "%s error, rdma_config(handle == %d) not allowed\n", + __func__, handle); + return -1; + } spin_lock_irqsave(&rdma_lock, flags); if (ins->op == NULL) { spin_unlock_irqrestore(&rdma_lock, flags); - pr_info("%s: handle (%d) not register\n", __func__, handle); + pr_info("%s: handle (%d) not register\n", + __func__, handle); return -1; } @@ -367,87 +395,92 @@ int rdma_config(int handle, int trigger_type) ins->rdma_regadr->trigger_mask_reg_bitpos, 8); ret = 1; + ins->rdma_write_count = 0; } else if (ins->rdma_item_count <= 0 || trigger_type == 0) { if (trigger_type == RDMA_TRIGGER_MANUAL) WRITE_VCBUS_REG(RDMA_ACCESS_MAN, READ_VCBUS_REG(RDMA_ACCESS_MAN) & (~1)); - if (debug_flag_mgr & 2) { - pr_info("%s: trigger_type %d : %d\r\n", + if (debug_flag & 2) { + pr_info("%s: trigger_type %d : %d\r\n", __func__, trigger_type, ins->rdma_item_count); - } - WRITE_VCBUS_REG_BITS(ins->rdma_regadr->trigger_mask_reg, + } + WRITE_VCBUS_REG_BITS( + ins->rdma_regadr->trigger_mask_reg, 0, ins->rdma_regadr->trigger_mask_reg_bitpos, 8); - rdma_vsync_isr_done = 1; + ins->rdma_write_count = 0; ret = 0; } else { memcpy(ins->rdma_table_addr, ins->reg_buf, ins->rdma_item_count * 2 * sizeof(u32)); if (trigger_type > 0 && trigger_type <= RDMA_TRIGGER_MANUAL) { + ins->rdma_write_count = ins->rdma_item_count; ins->prev_trigger_type = trigger_type; if (trigger_type == RDMA_TRIGGER_MANUAL) { /*manual RDMA */ struct rdma_instance_s *man_ins = &info->rdma_ins[0]; WRITE_VCBUS_REG(RDMA_ACCESS_MAN, - READ_VCBUS_REG(RDMA_ACCESS_MAN) - & (~1)); - WRITE_VCBUS_REG(man_ins-> - rdma_regadr->rdma_ahb_start_addr, - ins->rdma_table_phy_addr); - WRITE_VCBUS_REG(man_ins-> - rdma_regadr->rdma_ahb_end_addr, - ins->rdma_table_phy_addr + - ins->rdma_item_count * 8 - 1); - - WRITE_VCBUS_REG_BITS(man_ins-> - rdma_regadr->addr_inc_reg, 0, - man_ins-> - rdma_regadr->addr_inc_reg_bitpos, 1); - WRITE_VCBUS_REG_BITS(man_ins-> - rdma_regadr->rw_flag_reg, 1, - man_ins-> - rdma_regadr->rw_flag_reg_bitpos, 1); - /* Manual-start RDMA */ + READ_VCBUS_REG(RDMA_ACCESS_MAN) & (~1)); + WRITE_VCBUS_REG( + man_ins->rdma_regadr->rdma_ahb_start_addr, + ins->rdma_table_phy_addr); + WRITE_VCBUS_REG( + man_ins->rdma_regadr->rdma_ahb_end_addr, + ins->rdma_table_phy_addr + + ins->rdma_item_count * 8 - 1); + + WRITE_VCBUS_REG_BITS( + man_ins->rdma_regadr->addr_inc_reg, + 0, + man_ins->rdma_regadr->addr_inc_reg_bitpos, + 1); + WRITE_VCBUS_REG_BITS( + man_ins->rdma_regadr->rw_flag_reg, + 1, + man_ins->rdma_regadr->rw_flag_reg_bitpos, + 1); + /* Manual-start RDMA*/ WRITE_VCBUS_REG(RDMA_ACCESS_MAN, - READ_VCBUS_REG(RDMA_ACCESS_MAN) - | 1); + READ_VCBUS_REG(RDMA_ACCESS_MAN) | 1); - if (debug_flag_mgr & 2) + if (debug_flag & 2) pr_info("%s: manual config %d:\r\n", - __func__, ins->rdma_item_count); - } else { /* interrupt input trigger RDMA */ - if (debug_flag_mgr & 2) + __func__, ins->rdma_item_count); + } else { + /* interrupt input trigger RDMA */ + if (debug_flag & 2) pr_info("%s: case 3 : %d:\r\n", - __func__, ins->rdma_item_count); - WRITE_VCBUS_REG_BITS(ins-> - rdma_regadr->trigger_mask_reg, 0, - ins-> - rdma_regadr->trigger_mask_reg_bitpos, - 8); - - WRITE_VCBUS_REG(ins-> - rdma_regadr->rdma_ahb_start_addr, + __func__, ins->rdma_item_count); + WRITE_VCBUS_REG_BITS( + ins->rdma_regadr->trigger_mask_reg, + 0, + ins->rdma_regadr->trigger_mask_reg_bitpos, + 8); + + WRITE_VCBUS_REG( + ins->rdma_regadr->rdma_ahb_start_addr, ins->rdma_table_phy_addr); - WRITE_VCBUS_REG(ins-> - rdma_regadr->rdma_ahb_end_addr, - ins->rdma_table_phy_addr + - ins->rdma_item_count * 8 - 1); - - WRITE_VCBUS_REG_BITS(ins-> - rdma_regadr->addr_inc_reg, 0, + WRITE_VCBUS_REG( + ins->rdma_regadr->rdma_ahb_end_addr, + ins->rdma_table_phy_addr + + ins->rdma_item_count * 8 - 1); + + WRITE_VCBUS_REG_BITS( + ins->rdma_regadr->addr_inc_reg, + 0, ins->rdma_regadr->addr_inc_reg_bitpos, 1); - WRITE_VCBUS_REG_BITS(ins-> - rdma_regadr->rw_flag_reg, 1, + WRITE_VCBUS_REG_BITS( + ins->rdma_regadr->rw_flag_reg, + 1, ins->rdma_regadr->rw_flag_reg_bitpos, 1); - WRITE_VCBUS_REG_BITS(ins-> - rdma_regadr->trigger_mask_reg, - trigger_type, - ins-> - rdma_regadr->trigger_mask_reg_bitpos, - 8); + WRITE_VCBUS_REG_BITS( + ins->rdma_regadr->trigger_mask_reg, + trigger_type, + ins->rdma_regadr->trigger_mask_reg_bitpos, + 8); } } else if (trigger_type == 0x101) { /* debug mode */ int i; @@ -455,30 +488,31 @@ int rdma_config(int handle, int trigger_type) for (i = 0; i < ins->rdma_item_count; i++) { WRITE_VCBUS_REG(ins->rdma_table_addr[i << 1], ins->rdma_table_addr[(i << 1) + 1]); - if (debug_flag_mgr & 1) + if (debug_flag & 1) pr_info("WR(%x)<=%x\n", - ins->rdma_table_addr[i << 1], - ins->rdma_table_addr[(i << 1) + - 1]); + ins->rdma_table_addr[i << 1], + ins->rdma_table_addr[(i << 1) + 1]); } - } else if (trigger_type == 0x102) { /* debug mode */ + ins->rdma_write_count = 0; + } else if (trigger_type == 0x102) { /* debug mode */ int i; for (i = 0; i < ins->rdma_item_count; i++) { WRITE_VCBUS_REG(ins->reg_buf[i << 1], ins->reg_buf[(i << 1) + 1]); - if (debug_flag_mgr & 1) + if (debug_flag & 1) pr_info("WR(%x)<=%x\n", ins->reg_buf[i << 1], ins->reg_buf[(i << 1) + 1]); } + ins->rdma_write_count = 0; } ret = 1; } ins->rdma_item_count = 0; spin_unlock_irqrestore(&rdma_lock, flags); - if (debug_flag_mgr & 2) + if (debug_flag & 2) pr_info("%s: (%d 0x%x) ret %d\r\n", __func__, handle, trigger_type, ret); @@ -489,18 +523,23 @@ EXPORT_SYMBOL(rdma_config); int rdma_clear(int handle) { int ret = 0; + unsigned long flags; struct rdma_device_info *info = &rdma_info; struct rdma_instance_s *ins = &info->rdma_ins[handle]; - - if (handle == 0 || ins->op == NULL) { + spin_lock_irqsave(&rdma_lock, flags); + if (handle <= 0 || + handle >= RDMA_NUM || + ins->op == NULL) { + spin_unlock_irqrestore(&rdma_lock, flags); pr_info("%s error, handle (%d) not register\n", __func__, handle); return -1; } - - WRITE_VCBUS_REG_BITS(ins->rdma_regadr->trigger_mask_reg, + WRITE_VCBUS_REG_BITS( + ins->rdma_regadr->trigger_mask_reg, 0, ins->rdma_regadr->trigger_mask_reg_bitpos, 8); - + ins->rdma_write_count = 0; + spin_unlock_irqrestore(&rdma_lock, flags); return ret; } EXPORT_SYMBOL(rdma_clear); @@ -508,6 +547,9 @@ EXPORT_SYMBOL(rdma_clear); u32 rdma_read_reg(int handle, u32 adr) { int i; + u32 *write_table; + int match = 0; + int read_from = 0; struct rdma_device_info *info = &rdma_info; struct rdma_instance_s *ins = &info->rdma_ins[handle]; u32 read_val = READ_VCBUS_REG(adr); @@ -515,29 +557,72 @@ u32 rdma_read_reg(int handle, u32 adr) for (i = (ins->rdma_item_count - 1); i >= 0; i--) { if (ins->reg_buf[i << 1] == adr) { read_val = ins->reg_buf[(i << 1) + 1]; + match = 1; + read_from = 1; break; } } + if (!match) { + write_table = ins->rdma_table_addr; + for (i = (ins->rdma_write_count - 1); + i >= 0; i--) { + if (write_table[i << 1] == adr) { + read_val = + write_table[(i << 1) + 1]; + read_from = 2; + break; + } + } + } + if (adr == trace_reg) { + if (read_from == 2) + pr_info("(%s) handle %d, %04x=0x%08x from write table(%d)\n", + __func__, + handle, adr, + read_val, + ins->rdma_write_count); + else if (read_from == 1) + pr_info("(%s) handle %d, %04x=0x%08x from item table(%d)\n", + __func__, + handle, adr, + read_val, + ins->rdma_item_count); + else + pr_info("(%s) handle %d, %04x=0x%08x from real reg\n", + __func__, + handle, adr, + read_val); + } return read_val; } EXPORT_SYMBOL(rdma_read_reg); -int rdma_reset_tigger_flag; int rdma_watchdog_setting(int flag) { - if (rdma_vsync_isr_done) { - rdma_watchdog_count = 0; - rdma_vsync_isr_done = 0; - } + int ret = 0; if (flag == 0) rdma_watchdog_count = 0; else rdma_watchdog_count++; - if (debug_flag_mgr & 8) { + + if (debug_flag & 8) { rdma_force_reset = 1; - debug_flag_mgr = 0; + debug_flag = 0; } - return 0; + if (((rdma_watchdog > 0) && + (rdma_watchdog_count > rdma_watchdog)) + || (rdma_force_reset > 0)) { + pr_info("%s rdma reset: %d, force flag:%d\n", + __func__, + rdma_watchdog_count, + rdma_force_reset); + rdma_watchdog_count = 0; + rdma_force_reset = 0; + rdma_reset(1); + rdma_reset_tigger_flag = 1; + ret = 1; + } + return ret; } EXPORT_SYMBOL(rdma_watchdog_setting); @@ -549,7 +634,7 @@ int rdma_write_reg(int handle, u32 adr, u32 val) if (ins->rdma_table_size == 0) return -1; - if (debug_flag_mgr & 1) + if (debug_flag & 1) pr_info("rdma_write(%d) %d(%x)<=%x\n", handle, ins->rdma_item_count, adr, val); if (((ins->rdma_item_count << 1) + 1) < @@ -559,34 +644,24 @@ int rdma_write_reg(int handle, u32 adr, u32 val) ins->rdma_item_count++; } else { int i; - - if (debug_flag_mgr & 4) + if (debug_flag & 4) pr_info("%s(%d, %x, %x ,%d) buf overflow\n", - __func__, rdma_watchdog_count, handle, adr, - val); + __func__, rdma_watchdog_count, handle, adr, val); for (i = 0; i < ins->rdma_item_count; i++) WRITE_VCBUS_REG(ins->reg_buf[i << 1], ins->reg_buf[(i << 1) + 1]); ins->rdma_item_count = 0; + ins->rdma_write_count = 0; ins->reg_buf[ins->rdma_item_count << 1] = adr; ins->reg_buf[(ins->rdma_item_count << 1) + 1] = val; ins->rdma_item_count++; } - if ((rdma_watchdog > 0) && (rdma_watchdog_count > rdma_watchdog)) { - pr_info("%s rdma reset :%d\n", __func__, rdma_watchdog_count); - rdma_watchdog_count = 0; - rdma_reset(1); - rdma_config(handle, ins->prev_trigger_type); - rdma_reset_tigger_flag = 1; - } - if (rdma_force_reset == 1) { - rdma_force_reset = 0; - rdma_reset_tigger_flag = 1; - rdma_watchdog_count = 0; - rdma_reset(1); - rdma_config(handle, ins->prev_trigger_type); - pr_info("%s rdma force reset\n", __func__); - } + if (adr == trace_reg) + pr_info("(%s) handle %d, %04x=0x%08x (%d)\n", + __func__, + handle, adr, + val, + ins->rdma_item_count); return 0; } EXPORT_SYMBOL(rdma_write_reg); @@ -594,7 +669,9 @@ EXPORT_SYMBOL(rdma_write_reg); int rdma_write_reg_bits(int handle, u32 adr, u32 val, u32 start, u32 len) { int i; + u32 *write_table; int match = 0; + int read_from = 0; struct rdma_device_info *info = &rdma_info; struct rdma_instance_s *ins = &info->rdma_ins[handle]; u32 read_val = READ_VCBUS_REG(adr); @@ -607,16 +684,52 @@ int rdma_write_reg_bits(int handle, u32 adr, u32 val, u32 start, u32 len) if (ins->reg_buf[i << 1] == adr) { read_val = ins->reg_buf[(i << 1) + 1]; match = 1; + read_from = 1; break; } } - write_val = (read_val & ~(((1L << (len)) - 1) << (start))) - | ((unsigned int)(val) << (start)); + if (!match) { + write_table = ins->rdma_table_addr; + for (i = (ins->rdma_write_count - 1); + i >= 0; i--) { + if (write_table[i << 1] == adr) { + read_val = + write_table[(i << 1) + 1]; + read_from = 2; + break; + } + } + } + write_val = (read_val & ~(((1L<<(len))-1)<<(start))) + |((unsigned int)(val) << (start)); + + if (adr == trace_reg) { + if (read_from == 2) + pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from write table(%d)\n", + __func__, + handle, adr, + read_val, + write_val, + ins->rdma_write_count); + else if (read_from == 1) + pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from item table(%d)\n", + __func__, + handle, adr, + read_val, + write_val, + ins->rdma_item_count); + else + pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from real reg\n", + __func__, + handle, adr, + read_val, + write_val); + } if (match) { ins->reg_buf[(i << 1) + 1] = write_val; return 0; } - if (debug_flag_mgr & 1) + if (debug_flag & 1) pr_info("rdma_write(%d) %d(%x)<=%x\n", handle, ins->rdma_item_count, adr, write_val); @@ -625,8 +738,8 @@ int rdma_write_reg_bits(int handle, u32 adr, u32 val, u32 start, u32 len) } EXPORT_SYMBOL(rdma_write_reg_bits); -MODULE_PARM_DESC(debug_flag_mgr, "\n debug_flag_mgr\n"); -module_param(debug_flag_mgr, uint, 0664); +MODULE_PARM_DESC(debug_flag, "\n debug_flag\n"); +module_param(debug_flag, uint, 0664); MODULE_PARM_DESC(rdma_watchdog, "\n rdma_watchdog\n"); module_param(rdma_watchdog, uint, 0664); @@ -634,15 +747,15 @@ module_param(rdma_watchdog, uint, 0664); MODULE_PARM_DESC(reset_count, "\n reset_count\n"); module_param(reset_count, uint, 0664); -MODULE_PARM_DESC(rdma_monitor_reg, "\n rdma_monitor_reg\n"); -module_param(rdma_monitor_reg, uint, 0664); - MODULE_PARM_DESC(ctrl_ahb_rd_burst_size, "\n ctrl_ahb_rd_burst_size\n"); module_param(ctrl_ahb_rd_burst_size, uint, 0664); MODULE_PARM_DESC(ctrl_ahb_wr_burst_size, "\n ctrl_ahb_wr_burst_size\n"); module_param(ctrl_ahb_wr_burst_size, uint, 0664); +MODULE_PARM_DESC(trace_reg, "\n trace_addr\n"); +module_param(trace_reg, ushort, 0664); + /* static int __devinit rdma_probe(struct platform_device *pdev) */ static int rdma_probe(struct platform_device *pdev) { @@ -654,17 +767,26 @@ static int rdma_probe(struct platform_device *pdev) int_rdma = platform_get_irq_byname(pdev, "rdma"); pr_info("%s\n", __func__); + + WRITE_VCBUS_REG(VPU_VDISP_ASYNC_HOLD_CTRL, 0x18101810); + WRITE_VCBUS_REG(VPU_VPUARB2_ASYNC_HOLD_CTRL, 0x18101810); + rdma_mgr_irq_request = 0; + trace_reg = 0; + for (i = 0; i < RDMA_NUM; i++) { info->rdma_ins[i].rdma_table_size = 0; info->rdma_ins[i].rdma_regadr = &rdma_regadr[i]; info->rdma_ins[i].keep_buf = 1; /*do not change it in normal case */ info->rdma_ins[i].used = 0; + info->rdma_ins[i].prev_trigger_type = 0; + info->rdma_ins[i].rdma_write_count = 0; } - WRITE_MPEG_REG(RESET4_REGISTER, (1 << 5)); -#if 1 - info->rdma_ins[3].used = 1; /* OSD driver uses this channel */ + WRITE_MPEG_REG(RESET4_REGISTER, + (1 << 5)); +#ifdef SKIP_OSD_CHANNEL + info->rdma_ins[3].used = 1; /* OSD driver uses this channel */ #endif if (int_rdma == -ENXIO) { dev_err(&pdev->dev, "cannot get rdma irq resource\n"); @@ -677,8 +799,9 @@ static int rdma_probe(struct platform_device *pdev) } rdma_mgr_irq_request = 1; - data32 = 0; - data32 |= 0 << 6; + data32 = 0; + data32 |= 1 << 7; /* wrtie ddr urgent */ + data32 |= 1 << 6; /* read ddr urgent */ data32 |= ctrl_ahb_wr_burst_size << 4; data32 |= ctrl_ahb_rd_burst_size << 2; data32 |= 0 << 1; diff --git a/drivers/amlogic/media/common/vfm/vfm.c b/drivers/amlogic/media/common/vfm/vfm.c index 25f0520..ab0001a 100644 --- a/drivers/amlogic/media/common/vfm/vfm.c +++ b/drivers/amlogic/media/common/vfm/vfm.c @@ -25,15 +25,18 @@ #include #include #include - +#include +#include /* Amlogic headers */ #include #include #include +#include /*for dumpinfos*/ #include #include +#include /* Local headers */ #include "vftrace.h" @@ -47,7 +50,7 @@ static DEFINE_SPINLOCK(lock); #define VFM_NAME_LEN 100 #define VFM_MAP_SIZE 10 #define VFM_MAP_COUNT 20 - +static struct device *vfm_dev; struct vfm_map_s { char id[VFM_NAME_LEN]; char name[VFM_MAP_SIZE][VFM_NAME_LEN]; @@ -154,52 +157,94 @@ int vfm_map_add(char *id, char *name_chain) { int i, j; int ret = -1; - char *ptr, *token; + char *ptr, *token = NULL; struct vfm_map_s *p; + int old_num = vfm_map_num; + unsigned long flags; + int add_ok = 0; + int cnt = 10; p = kmalloc(sizeof(struct vfm_map_s), GFP_KERNEL); - if (p) { - memset(p, 0, sizeof(struct vfm_map_s)); - memcpy(p->id, id, strlen(id)); - p->valid = 1; - ptr = name_chain; - while (1) { - token = strsep(&ptr, "\n "); - if (token == NULL) - break; - if (*token == '\0') - continue; - memcpy(p->name[p->vfm_map_size], token, strlen(token)); - p->vfm_map_size++; - } - for (i = 0; i < vfm_map_num; i++) { - if (vfm_map[i] && (vfm_map[i]->vfm_map_size == - p->vfm_map_size) && - (!strcmp(vfm_map[i]->id, p->id))) { - for (j = 0; j < p->vfm_map_size; j++) { - if (strcmp(vfm_map[i]->name[j], - p->name[j])) { - break; - } - } - if (j == p->vfm_map_size) { - vfm_map[i]->valid = 1; - kfree(p); + if (!p) { + pr_err("%s: Error, map no mem!!\n", __func__); + return -ENOMEM; + } + memset(p, 0, sizeof(struct vfm_map_s)); + memcpy(p->id, id, strlen(id)); + p->valid = 1; + ptr = name_chain; + + do { + token = strsep(&ptr, "\n "); + if (token == NULL) + break; + if (*token == '\0') + continue; + memcpy(p->name[p->vfm_map_size], token, strlen(token)); + p->vfm_map_size++; + } while (token && cnt--); + + cnt = 10; /*limit the cnt of retry to avoid the infinite loop*/ + +retry: + for (i = 0; i < vfm_map_num; i++) { + struct vfm_map_s *pi = vfm_map[i]; + + if (!pi || (strcmp(pi->id, p->id))) { + /*not same id to next one*/ + continue; + } else if (pi->valid) { + for (j = 0; j < p->vfm_map_size; j++) { + if (strcmp(pi->name[j], + p->name[j])){ break; } } + if (j == p->vfm_map_size) { + pi->valid = 1; + kfree(p); + add_ok = 1; + break; + } + } else if (!pi->valid) { + /* + *over write old setting. + * don't free old one, + * because it may on used. + */ + for (j = 0; j < p->vfm_map_size; j++) { + /*over write node.*/ + strcpy(pi->name[j], p->name[j]); + } + pi->vfm_map_size = p->vfm_map_size; + pi->valid = 1; + kfree(p); + add_ok = 1; + break; + } + } + if (!add_ok) { + spin_lock_irqsave(&lock, flags); + if (i == old_num && old_num != vfm_map_num && cnt--) { + spin_unlock_irqrestore(&lock, flags); + pr_err("%s: vfm_map changed on add, need retry!\n", + __func__); + goto retry; } if (i == vfm_map_num) { if (i < VFM_MAP_COUNT) { vfm_map[i] = p; vfm_map_num++; - } else { + add_ok = 1; + } else{ pr_err("%s: Error, map full\n", __func__); ret = -1; } } - ret = 0; + spin_unlock_irqrestore(&lock, flags); } + if (add_ok) + ret = 0; return ret; } EXPORT_SYMBOL(vfm_map_add); @@ -214,7 +259,6 @@ static char *vf_get_provider_name_inmap(int i, const char *receiver_name) if ((j > 0) && ((vfm_map[i]->active >> (j - 1)) & 0x1)) { provider_name = vfm_map[i]->name[j - 1]; - ; } break; } @@ -254,7 +298,6 @@ static char *vf_get_receiver_name_inmap(int i, const char *provider_name) } if ((!strncmp(vfm_map[i]->name[j], provider_name, namelen)) && ((j + 1) < vfm_map[i]->vfm_map_size)) { - receiver_name = vfm_map[i]->name[j + 1]; if (namelen == provide_namelen) { /* exact match */ @@ -295,13 +338,17 @@ char *vf_get_receiver_name(const char *provider_name) static void vfm_init(void) { #if ((defined CONFIG_AMLOGIC_POST_PROCESS_MANAGER) && \ - (defined CONFIG_DEINTERLACE)) + (defined CONFIG_AMLOGIC_MEDIA_DEINTERLACE)) char def_id[] = "default"; +#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC char def_name_chain[] = "decoder ppmgr deinterlace amvideo"; +#else + char def_name_chain[] = "decoder amvideo"; +#endif #elif (defined CONFIG_AMLOGIC_POST_PROCESS_MANAGER) char def_id[] = "default"; char def_name_chain[] = "decoder ppmgr amvideo"; -#elif (defined CONFIG_DEINTERLACE) +#elif (defined CONFIG_AMLOGIC_MEDIA_DEINTERLACE) char def_id[] = "default"; char def_name_chain[] = "decoder deinterlace amvideo"; #else /**/ @@ -323,9 +370,6 @@ static void vfm_init(void) #endif /**/ #endif /**/ #endif /**/ - char def_osd_id[] = "default_osd"; - char def_osd_name_chain[] = "osd amvideo4osd"; - /* char def_osd_name_chain[] = "osd amvideo"; */ #ifdef CONFIG_VDIN_MIPI char def_mipi_id[] = "default_mipi"; char def_mipi_name_chain[] = "vdin mipi"; @@ -343,11 +387,22 @@ static void vfm_init(void) char tvpath_chain[] = "vdin0 deinterlace amvideo"; #endif #endif /**/ +#ifdef CONFIG_AM_VDEC_DV + char def_dvbl_id[] = "dvblpath"; +/* char def_dvbl_chain[] = "dvbldec dvbl amvideo";*/ + char def_dvbl_chain[] = "dvbldec amvideo"; + + char def_dvel_id[] = "dvelpath"; + char def_dvel_chain[] = "dveldec dvel"; +#endif +#if 1/*def CONFIG_AM_HDMIIN_DV*/ + char def_dvhdmiin_id[] = "dvhdmiin"; + char def_dvhdmiin_chain[] = "dv_vdin amvideo"; +#endif int i; for (i = 0; i < VFM_MAP_COUNT; i++) vfm_map[i] = NULL; - vfm_map_add(def_osd_id, def_osd_name_chain); vfm_map_add(def_id, def_name_chain); #ifdef CONFIG_VDIN_MIPI vfm_map_add(def_mipi_id, def_mipi_name_chain); @@ -362,6 +417,13 @@ static void vfm_init(void) #ifdef CONFIG_AMLOGIC_V4L_VIDEO2 vfm_map_add(def_amlvideo2_id, def_amlvideo2_chain); #endif /**/ +#ifdef CONFIG_AM_VDEC_DV + vfm_map_add(def_dvbl_id, def_dvbl_chain); + vfm_map_add(def_dvel_id, def_dvel_chain); +#endif +#if 1/*def CONFIG_AM_HDMIIN_DV*/ + vfm_map_add(def_dvhdmiin_id, def_dvhdmiin_chain); +#endif } /* @@ -375,14 +437,15 @@ static ssize_t vfm_map_show(struct class *class, for (i = 0; i < vfm_map_num; i++) { if (vfm_map[i] && vfm_map[i]->valid) { - len += sprintf(buf + len, "%s { ", vfm_map[i]->id); + len += sprintf(buf + len, "[%02d] %s { ", + i,/*in slot num.*/ + vfm_map[i]->id); for (j = 0; j < vfm_map[i]->vfm_map_size; j++) { if (j < (vfm_map[i]->vfm_map_size - 1)) { len += sprintf(buf + len, "%s(%d) ", - vfm_map[i]->name[j], - (vfm_map[i]->active >> j) & - 0x1); - } else { + vfm_map[i]->name[j], + (vfm_map[i]->active >> j) & 0x1); + } else{ len += sprintf(buf + len, "%s", vfm_map[i]->name[j]); } @@ -395,20 +458,20 @@ static ssize_t vfm_map_show(struct class *class, return len; } -static int vf_get_states(struct vframe_provider_s *vfp, +static int vfm_vf_get_states(struct vframe_provider_s *vfp, struct vframe_states *states) { int ret = -1; unsigned long flags; spin_lock_irqsave(&lock, flags); - if (vfp && vfp->ops && vfp->ops->vf_states) - ret = vfp->ops->vf_states(states, vfp->op_arg); + ret = vf_get_states(vfp, states); spin_unlock_irqrestore(&lock, flags); return ret; } -static inline struct vframe_s *vmf_vf_peek(struct vframe_provider_s *vfp) +static inline struct vframe_s *vfm_vf_peek( + struct vframe_provider_s *vfp) { if (!(vfp && vfp->ops && vfp->ops->peek)) return NULL; @@ -421,53 +484,144 @@ static void vfm_dump_provider(const char *name) struct vframe_states states; unsigned long flags; struct vframe_s *vf; + char *buf, *pbuf; if (!prov) return; - if (!vf_get_states(prov, &states)) { - pr_info("vframe_pool_size=%d\n", states.vf_pool_size); - pr_info("vframe buf_free_num=%d\n", states.buf_free_num); - pr_info("vframe buf_recycle_num=%d\n", states.buf_recycle_num); - pr_info("vframe buf_avail_num=%d\n", states.buf_avail_num); + + buf = kzalloc(0x400, GFP_KERNEL); + if (IS_ERR_OR_NULL(buf)) + return; + + pbuf = buf; + + if (!vfm_vf_get_states(prov, &states)) { + pr_info("vframe_pool_size=%d\n", + states.vf_pool_size); + pr_info("vframe buf_free_num=%d\n", + states.buf_free_num); + pr_info("vframe buf_recycle_num=%d\n", + states.buf_recycle_num); + pr_info("vframe buf_avail_num=%d\n", + states.buf_avail_num); spin_lock_irqsave(&lock, flags); - vf = vmf_vf_peek(prov); + vf = vfm_vf_peek(prov); if (vf) { - pr_info("vframe ready frame delayed =%dms\n", + pbuf += sprintf(pbuf, + "vframe ready frame delayed =%dms\n", (int)(jiffies_64 - - vf->ready_jiffies64) * 1000 / HZ); - pr_info("vf index=%d\n", vf->index); - pr_info("vf->pts=%d\n", vf->pts); - pr_info("vf canvas0Addr=%x\n", vf->canvas0Addr); - pr_info("vf canvas1Addr=%x\n", vf->canvas1Addr); - pr_info("vf canvas0Addr.y.addr=%x(%d)\n", - canvas_get_addr(canvasY(vf->canvas0Addr)), - canvas_get_addr(canvasY(vf->canvas0Addr))); - pr_info("vf canvas0Adr.uv.adr=%x(%d)\n", - canvas_get_addr(canvasUV(vf->canvas0Addr)), - canvas_get_addr(canvasUV(vf->canvas0Addr))); + vf->ready_jiffies64) * 1000 / + HZ); + pbuf += sprintf(pbuf, "vf index=%d\n", vf->index); + pbuf += sprintf(pbuf, "vf->pts=%d\n", vf->pts); + pbuf += sprintf(pbuf, "vf->type=%d\n", vf->type); + if (vf->type & VIDTYPE_COMPRESS) { + pbuf += sprintf(pbuf, "vf compHeadAddr=%x\n", + vf->compHeadAddr); + pbuf += sprintf(pbuf, "vf compBodyAddr =%x\n", + vf->compBodyAddr); + } else { + pbuf += sprintf(pbuf, "vf canvas0Addr=%x\n", + vf->canvas0Addr); + pbuf += sprintf(pbuf, "vf canvas1Addr=%x\n", + vf->canvas1Addr); + pbuf += sprintf(pbuf, + "vf canvas0Addr.y.addr=%x(%d)\n", + canvas_get_addr( + canvasY(vf->canvas0Addr)), + canvas_get_addr( + canvasY(vf->canvas0Addr))); + pbuf += sprintf(pbuf, + "vf canvas0Adr.uv.adr=%x(%d)\n", + canvas_get_addr( + canvasUV(vf->canvas0Addr)), + canvas_get_addr( + canvasUV(vf->canvas0Addr))); + } } spin_unlock_irqrestore(&lock, flags); + + pr_info("%s\n", buf); } vftrace_dump_trace_infos(prov->traceget); vftrace_dump_trace_infos(prov->traceput); + + kfree(buf); } #define VFM_CMD_ADD 1 #define VFM_CMD_RM 2 #define VFM_CMD_DUMP 3 +#define VFM_CMD_ADDDUMMY 4 + +/*dummy receiver*/ + +static int dummy_receiver_event_fun(int type, void *data, void *arg) +{ + struct vframe_receiver_s *dummy_vf_recv + = (struct vframe_receiver_s *)arg; + if (type == VFRAME_EVENT_PROVIDER_UNREG) { + char *provider_name = (char *)data; + + pr_info("%s, provider %s unregistered\n", + __func__, provider_name); + } else if (type == + VFRAME_EVENT_PROVIDER_VFRAME_READY) { + struct vframe_s *vframe_tmp = vf_get(dummy_vf_recv->name); + + while (vframe_tmp) { + vf_put(vframe_tmp, dummy_vf_recv->name); + vf_notify_provider(dummy_vf_recv->name, + VFRAME_EVENT_RECEIVER_PUT, NULL); + vframe_tmp = vf_get(dummy_vf_recv->name); + } + } else if (type == VFRAME_EVENT_PROVIDER_QUREY_STATE) { + return RECEIVER_ACTIVE; + } else if (type == VFRAME_EVENT_PROVIDER_REG) { + char *provider_name = (char *)data; + + pr_info("%s, provider %s registered\n", + __func__, provider_name); + } + return 0; +} + +static const struct vframe_receiver_op_s dummy_vf_receiver = { + .event_cb = dummy_receiver_event_fun +}; + +static void add_dummy_receiver(char *vfm_name_) +{ + struct vframe_receiver_s *dummy_vf_recv = + kmalloc(sizeof(struct vframe_receiver_s), GFP_KERNEL); + pr_info("%s(%s)\n", __func__, vfm_name_); + if (dummy_vf_recv) { + char *vfm_name = kmalloc(16, GFP_KERNEL); + + snprintf(vfm_name, 16, "%s", vfm_name_); + vf_receiver_init(dummy_vf_recv, vfm_name, + &dummy_vf_receiver, dummy_vf_recv); + vf_reg_receiver(dummy_vf_recv); + pr_info("%s: %s\n", __func__, dummy_vf_recv->name); + } +} + +/**/ /* * echo add > /sys/class/vfm/map * echo rm > /sys/class/vfm/map * echo rm all > /sys/class/vfm/map * echo dump providername > /sys/class/vfm/map + * echo dummy name > /sys/class/vfm/map * the name of the path. * the name of the nodes in the path. */ static ssize_t vfm_map_store(struct class *class, - struct class_attribute *attr, const char *buf, size_t count) + struct class_attribute *attr, + const char *buf, size_t count) { char *buf_orig, *ps, *token; int i = 0; @@ -492,6 +646,8 @@ static ssize_t vfm_map_store(struct class *class, cmd = VFM_CMD_RM; else if (!strcmp(token, "dump")) cmd = VFM_CMD_DUMP; + else if (!strcmp(token, "dummy")) + cmd = VFM_CMD_ADDDUMMY; else break; } else if (i == 1) { @@ -505,6 +661,8 @@ static ssize_t vfm_map_store(struct class *class, count = 0; } else if (cmd == VFM_CMD_DUMP) { vfm_dump_provider(token); + } else if (cmd == VFM_CMD_ADDDUMMY) { + add_dummy_receiver(token); } break; } @@ -517,6 +675,159 @@ static ssize_t vfm_map_store(struct class *class, static CLASS_ATTR(map, 0664, vfm_map_show, vfm_map_store); static struct class vfm_class = { .name = CLS_NAME, + }; +int vfm_map_store_fun(const char *trigger, int id, const char *buf, int size) +{ + int ret = size; + + switch (id) { + case 0: return vfm_map_store(NULL, NULL, buf, size); + default: + ret = -1; + } + return size; +} +int vfm_map_show_fun(const char *trigger, int id, char *sbuf, int size) +{ + int ret = -1; + + void *buf, *getbuf = NULL; + + if (size < PAGE_SIZE) { + getbuf = (void *)__get_free_page(GFP_KERNEL); + if (!getbuf) + return -ENOMEM; + buf = getbuf; + } else { + buf = sbuf; + } + + switch (id) { + case 0: + ret = vfm_map_show(NULL, NULL, buf); + break; + default: + ret = -1; + } + if (ret > 0 && getbuf != NULL) { + ret = min_t(int, ret, size); + strncpy(sbuf, buf, ret); + } + if (getbuf != NULL) + free_page((unsigned long)getbuf); + return ret; +} + +static struct mconfig vfm_configs[] = { + MC_FUN_ID("map", vfm_map_show_fun, vfm_map_store_fun, 0), +}; + +/********************************************************* + * /dev/vfm APIs + *********************************************************/ +static int vfm_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int vfm_release(struct inode *inode, struct file *file) +{ + return 0; +} + +static long vfm_ioctl(struct file *file, unsigned int cmd, ulong arg) +{ + long ret = 0; + + struct vfmctl *user_argp = (void __user *)arg; + struct vfmctl argp; + + switch (cmd) { + case VFM_IOCTL_CMD_SET:{ + ret = + copy_from_user(argp.name, user_argp->name, sizeof(argp.name)); + ret |= + copy_from_user(argp.val, user_argp->val, sizeof(argp.val)); + if (ret) + ret = -EINVAL; + else + ret = + vfm_map_store(NULL, NULL, argp.val, sizeof(argp.val)); + } + break; + case VFM_IOCTL_CMD_GET:{ + /* + *overflow bug, need fixed. + *vfm_map_show(NULL, NULL, argp.val); + *ret = copy_to_user(user_argp->val, argp.val, sizeof(argp.val)); + *if (ret != 0) + * return -EIO; + *} + */ + return -EIO; + } + break; + case VFM_IOCTL_CMD_ADD:{ + ret = + copy_from_user(argp.name, user_argp->name, sizeof(argp.name)); + ret |= + copy_from_user(argp.val, user_argp->val, sizeof(argp.val)); + if (ret) + ret = -EINVAL; + else + ret = vfm_map_add(argp.name, argp.val); + } + break; + case VFM_IOCTL_CMD_RM:{ + ret = + copy_from_user(argp.val, user_argp->val, sizeof(argp.val)); + if (ret) + ret = -EINVAL; + else + ret = vfm_map_remove(argp.val); + } + break; + case VFM_IOCTL_CMD_DUMP:{ + ret = + copy_from_user(argp.val, user_argp->val, sizeof(argp.val)); + if (ret) + ret = -EINVAL; + vfm_dump_provider(argp.val); + } + break; + case VFM_IOCTL_CMD_ADDDUMMY:{ + ret = + copy_from_user(argp.val, user_argp->val, sizeof(argp.val)); + if (ret) + ret = -EINVAL; + add_dummy_receiver(argp.val); + } + + break; + default: + return -EINVAL; + } + return ret; +} + +#ifdef CONFIG_COMPAT +static long vfm_compat_ioctl(struct file *file, unsigned int cmd, ulong arg) +{ + long ret = 0; + + ret = vfm_ioctl(file, cmd, (ulong)compat_ptr(arg)); + return ret; +} +#endif +static const struct file_operations vfm_fops = { + .owner = THIS_MODULE, + .open = vfm_open, + .release = vfm_release, + .unlocked_ioctl = vfm_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = vfm_compat_ioctl, +#endif + .poll = NULL, }; static int __init vfm_class_init(void) @@ -534,12 +845,24 @@ static int __init vfm_class_init(void) pr_err("%s: class_create_file failed\n", __func__); class_unregister(&vfm_class); } + REG_PATH_CONFIGS("media.vfm", vfm_configs); + + + /* create vfm device */ + error = register_chrdev(VFM_MAJOR, "vfm", &vfm_fops); + if (error < 0) { + pr_err("Can't register major for vfm device\n"); + return error; + } + vfm_dev = device_create(&vfm_class, NULL, + MKDEV(VFM_MAJOR, 0), NULL, DEV_NAME); return error; } static void __exit vfm_class_exit(void) { class_unregister(&vfm_class); + unregister_chrdev(VFM_MAJOR, DEV_NAME); } fs_initcall(vfm_class_init); diff --git a/drivers/amlogic/media/common/vfm/vfm.h b/drivers/amlogic/media/common/vfm/vfm.h index e0320eb..f0dcfa8 100644 --- a/drivers/amlogic/media/common/vfm/vfm.h +++ b/drivers/amlogic/media/common/vfm/vfm.h @@ -40,4 +40,17 @@ extern int vfm_debug_flag; extern int vfm_trace_enable; /* 1; */ extern int vfm_trace_num; /* */ +struct vfmctl { + char name[10]; + char val[300]; +}; + +#define VFM_IOC_MAGIC 'V' +#define VFM_IOCTL_CMD_ADD _IOW(VFM_IOC_MAGIC, 0x00, struct vfmctl) +#define VFM_IOCTL_CMD_RM _IOW(VFM_IOC_MAGIC, 0x01, struct vfmctl) +#define VFM_IOCTL_CMD_DUMP _IOW(VFM_IOC_MAGIC, 0x02, struct vfmctl) +#define VFM_IOCTL_CMD_ADDDUMMY _IOW(VFM_IOC_MAGIC, 0x03, struct vfmctl) +#define VFM_IOCTL_CMD_SET _IOW(VFM_IOC_MAGIC, 0x04, struct vfmctl) +#define VFM_IOCTL_CMD_GET _IOWR(VFM_IOC_MAGIC, 0x05, struct vfmctl) + #endif diff --git a/drivers/amlogic/media/common/vfm/vframe_provider.c b/drivers/amlogic/media/common/vfm/vframe_provider.c index 54f34aa..3a60462 100644 --- a/drivers/amlogic/media/common/vfm/vframe_provider.c +++ b/drivers/amlogic/media/common/vfm/vframe_provider.c @@ -86,17 +86,68 @@ struct vframe_provider_s *vf_get_provider(const char *receiver_name) } EXPORT_SYMBOL(vf_get_provider); +/*#define NO_CHEKC_PROVIDER_USE*/ +#ifdef NO_CHEKC_PROVIDER_USE +static inline int use_provider(struct vframe_provider_s *prov) +{ + return prov != NULL; +} +static inline void unuse_provider(struct vframe_provider_s *prov) +{ +} +static int vf_provider_close(struct vframe_provider_s *prov) +{ + return 1; +} +#else +static inline int use_provider(struct vframe_provider_s *prov) +{ + int ret = 0; + + if (prov) { + ret = atomic_inc_return(&prov->use_cnt); + if (ret <= 0) + atomic_dec_return(&prov->use_cnt); + } + return ret > 0; +} +static inline void unuse_provider(struct vframe_provider_s *prov) +{ + if (prov) + atomic_dec_return(&prov->use_cnt); +} +#define CLOSED_CNT -100000 +static int vf_provider_close(struct vframe_provider_s *prov) +{ + int ret; + int wait_max = 10000; + + if (!prov) + return -1; + ret = atomic_add_return(CLOSED_CNT, &prov->use_cnt); + while (ret > CLOSED_CNT && wait_max-- > 0) { + schedule();/*shecule and wait for complete.*/ + ret = atomic_read(&prov->use_cnt); + }; + if (ret > CLOSED_CNT) { + pr_err("**ERR***,release, provider %s not finised,%d, wait=%d\n", + prov->name, ret, wait_max); + } + return 0; +} +#endif int vf_notify_provider(const char *receiver_name, int event_type, void *data) { int ret = -1; struct vframe_provider_s *provider = vf_get_provider(receiver_name); - if (provider) { + if (use_provider(provider)) { if (provider->ops && provider->ops->event_cb) { provider->ops->event_cb(event_type, data, provider->op_arg); ret = 0; } + unuse_provider(provider); } else { /* pr_err("Error: %s, fail to get provider of receiver %s\n",*/ /*__func__, receiver_name); */ @@ -111,12 +162,13 @@ int vf_notify_provider_by_name(const char *provider_name, int event_type, int ret = -1; struct vframe_provider_s *provider = vf_get_provider_by_name(provider_name); - if (provider) { + if (use_provider(provider)) { if (provider->ops && provider->ops->event_cb) { provider->ops->event_cb(event_type, data, provider->op_arg); ret = 0; } + unuse_provider(provider); } else{ /* pr_err("Error: %s, fail to get provider of receiver %s\n",*/ /*__func__, receiver_name); */ @@ -126,7 +178,8 @@ int vf_notify_provider_by_name(const char *provider_name, int event_type, EXPORT_SYMBOL(vf_notify_provider_by_name); void vf_provider_init(struct vframe_provider_s *prov, - const char *name, const struct vframe_operations_s *ops, void *op_arg) + const char *name, + const struct vframe_operations_s *ops, void *op_arg) { if (!prov) return; @@ -134,6 +187,9 @@ void vf_provider_init(struct vframe_provider_s *prov, prov->name = name; prov->ops = ops; prov->op_arg = op_arg; + prov->traceget = NULL; + prov->traceput = NULL; + atomic_set(&prov->use_cnt, 0); INIT_LIST_HEAD(&prov->list); } EXPORT_SYMBOL(vf_provider_init); @@ -146,6 +202,8 @@ int vf_reg_provider(struct vframe_provider_s *prov) if (!prov || !prov->name) return -1; + prov->traceget = NULL; + prov->traceput = NULL; for (i = 0; i < MAX_PROVIDER_NUM; i++) { p = provider_table[i]; if (p) { @@ -164,8 +222,9 @@ int vf_reg_provider(struct vframe_provider_s *prov) receiver = vf_get_receiver(prov->name); if (receiver && receiver->ops && receiver->ops->event_cb) { receiver->ops->event_cb(VFRAME_EVENT_PROVIDER_REG, - (void *)prov->name, receiver->op_arg); - } else { + (void *)prov->name, + receiver->op_arg); + } else{ pr_err("%s Error to notify receiver\n", __func__); } if (vfm_debug_flag & 1) @@ -173,11 +232,10 @@ int vf_reg_provider(struct vframe_provider_s *prov) } else { pr_err("%s: Error, provider_table full\n", __func__); } - prov->traceget = NULL; + atomic_set(&prov->use_cnt, 0);/*set it ready for use.*/ if (vfm_trace_enable & 1) prov->traceget = vftrace_alloc_trace(prov->name, 1, - vfm_trace_num); - prov->traceput = NULL; + vfm_trace_num); if (vfm_trace_enable & 2) prov->traceput = vftrace_alloc_trace(prov->name, 0, vfm_trace_num); @@ -202,15 +260,16 @@ void vf_unreg_provider(struct vframe_provider_s *prov) vftrace_free_trace(p->traceput); p->traceput = NULL; } + vf_provider_close(prov); provider_table[i] = NULL; if (vfm_debug_flag & 1) pr_err("%s:%s\n", __func__, prov->name); receiver = vf_get_receiver(prov->name); if (receiver && receiver->ops && receiver->ops->event_cb) { - receiver-> - ops->event_cb - (VFRAME_EVENT_PROVIDER_UNREG, NULL, + receiver->ops->event_cb( + VFRAME_EVENT_PROVIDER_UNREG, + NULL, receiver->op_arg); } else { pr_err("%s Error to notify receiver\n", @@ -237,9 +296,8 @@ void vf_light_unreg_provider(struct vframe_provider_s *prov) receiver = vf_get_receiver(p->name); if (receiver && receiver->ops && receiver->ops->event_cb) { - receiver-> - ops->event_cb - (VFRAME_EVENT_PROVIDER_LIGHT_UNREG, + receiver->ops->event_cb( + VFRAME_EVENT_PROVIDER_LIGHT_UNREG, NULL, receiver->op_arg); } break; @@ -264,10 +322,9 @@ void vf_ext_light_unreg_provider(struct vframe_provider_s *prov) receiver = vf_get_receiver(prov->name); if (receiver && receiver->ops && receiver->ops->event_cb) { - receiver-> - ops->event_cb - (VFRAME_EVENT_PROVIDER_LIGHT_UNREG, - NULL, receiver->op_arg); + receiver->ops->event_cb( + VFRAME_EVENT_PROVIDER_LIGHT_UNREG, + NULL, receiver->op_arg); } vf_update_active_map(); break; @@ -279,11 +336,14 @@ EXPORT_SYMBOL(vf_ext_light_unreg_provider); struct vframe_s *vf_peek(const char *receiver) { struct vframe_provider_s *vfp; - + struct vframe_s *vf = NULL; vfp = vf_get_provider(receiver); - if (!(vfp && vfp->ops && vfp->ops->peek)) - return NULL; - return vfp->ops->peek(vfp->op_arg); + if (use_provider(vfp)) { + if (vfp->ops && vfp->ops->peek) + vf = vfp->ops->peek(vfp->op_arg); + unuse_provider(vfp); + } + return vf; } EXPORT_SYMBOL(vf_peek); @@ -291,14 +351,15 @@ struct vframe_s *vf_get(const char *receiver) { struct vframe_provider_s *vfp; - struct vframe_s *vf; - + struct vframe_s *vf = NULL; vfp = vf_get_provider(receiver); - if (!(vfp && vfp->ops && vfp->ops->get)) - return NULL; - vf = vfp->ops->get(vfp->op_arg); - if (vf) - vftrace_info_in(vfp->traceget, vf); + if (use_provider(vfp)) { + if (vfp->ops && vfp->ops->get) + vf = vfp->ops->get(vfp->op_arg); + if (vf) + vftrace_info_in(vfp->traceget, vf); + unuse_provider(vfp); + } return vf; } EXPORT_SYMBOL(vf_get); @@ -308,10 +369,37 @@ void vf_put(struct vframe_s *vf, const char *receiver) struct vframe_provider_s *vfp; vfp = vf_get_provider(receiver); - if (!(vfp && vfp->ops && vfp->ops->put)) - return; - if (vf) - vftrace_info_in(vfp->traceput, vf); - vfp->ops->put(vf, vfp->op_arg); + if (use_provider(vfp)) { + if (vfp->ops && vfp->ops->put) + vfp->ops->put(vf, vfp->op_arg); + if (vf) + vftrace_info_in(vfp->traceput, vf); + unuse_provider(vfp); + } } EXPORT_SYMBOL(vf_put); + +int vf_get_states(struct vframe_provider_s *vfp, + struct vframe_states *states) +{ + int ret = -1; + + if (use_provider(vfp)) { + if (vfp->ops && vfp->ops->vf_states) + ret = vfp->ops->vf_states(states, vfp->op_arg); + unuse_provider(vfp); + } + return ret; +} +EXPORT_SYMBOL(vf_get_states); +int vf_get_states_by_name(const char *receiver_name, + struct vframe_states *states) +{ + struct vframe_provider_s *vfp; + + vfp = vf_get_provider(receiver_name); + return vf_get_states(vfp, states); +} +EXPORT_SYMBOL(vf_get_states_by_name); + + diff --git a/drivers/amlogic/media/common/vfm/vframe_receiver.c b/drivers/amlogic/media/common/vfm/vframe_receiver.c index 7761907..f25b39f 100644 --- a/drivers/amlogic/media/common/vfm/vframe_receiver.c +++ b/drivers/amlogic/media/common/vfm/vframe_receiver.c @@ -139,7 +139,8 @@ int vf_notify_receiver_by_name(const char *receiver_name, int event_type, EXPORT_SYMBOL(vf_notify_receiver_by_name); void vf_receiver_init(struct vframe_receiver_s *recv, - const char *name, const struct vframe_receiver_op_s *ops, void *op_arg) + const char *name, + const struct vframe_receiver_op_s *ops, void *op_arg) { if (!recv) return; diff --git a/drivers/amlogic/media/common/vfm/vftrace.c b/drivers/amlogic/media/common/vfm/vftrace.c index c7ded87..7ec062d 100644 --- a/drivers/amlogic/media/common/vfm/vftrace.c +++ b/drivers/amlogic/media/common/vfm/vftrace.c @@ -111,7 +111,10 @@ static void vftrace_dump_trace_info(struct trace_info *info, int i) i, info->vf, info->index, - info->type, info->pts, info->duration, info->in_time_us); + info->type, + info->pts, + info->duration, + info->in_time_us); } void vftrace_dump_trace_infos(void *vhandle) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 90ee85a..f788666 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -65,9 +65,6 @@ #include "deinterlace_mtn.h" #include "deinterlace_dbg.h" #include -#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA -#include "rdma.h" -#endif #if defined(NEW_DI_TV) #define ENABLE_SPIN_LOCK_ALWAYS #endif diff --git a/drivers/amlogic/media/deinterlace/deinterlace.h b/drivers/amlogic/media/deinterlace/deinterlace.h index d06a4b0..b209bf46 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.h +++ b/drivers/amlogic/media/deinterlace/deinterlace.h @@ -55,15 +55,6 @@ #define DET3D #undef SUPPORT_MPEG_TO_VDIN /* for all ic after m6c@20140731 */ -#ifndef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA -#ifndef VSYNC_WR_MPEG_REG -#define VSYNC_WR_MPEG_REG(adr, val) aml_write_vcbus(adr, val) -#define VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \ - aml_vcbus_update_bits(adr, ((1<> 16; - offset = READ_MPEG_REG(PARSER_AUDIO_WP); - page2 = READ_MPEG_REG(PARSER_AV_WRAP_COUNT) >> 16; + page1 = READ_PARSER_REG(PARSER_AV_WRAP_COUNT) >> 16; + offset = READ_PARSER_REG(PARSER_AUDIO_WP); + page2 = READ_PARSER_REG(PARSER_AV_WRAP_COUNT) >> 16; local_irq_restore(flags); } while (page1 != page2); @@ -163,11 +163,11 @@ static inline void get_rdpage_offset(u8 type, u32 *page, u32 *page_offset) local_irq_save(flags); page1 = - READ_MPEG_REG(AIU_MEM_AIFIFO_BUF_WRAP_COUNT) & + READ_AIU_REG(AIU_MEM_AIFIFO_BUF_WRAP_COUNT) & 0xffff; - offset = READ_MPEG_REG(AIU_MEM_AIFIFO_MAN_RP); + offset = READ_AIU_REG(AIU_MEM_AIFIFO_MAN_RP); page2 = - READ_MPEG_REG(AIU_MEM_AIFIFO_BUF_WRAP_COUNT) & + READ_AIU_REG(AIU_MEM_AIFIFO_BUF_WRAP_COUNT) & 0xffff; local_irq_restore(flags); @@ -500,9 +500,9 @@ static int pts_checkin_offset_inline(u8 type, u32 offset, u32 val, u64 uS64) pr_info("init apts[%d] at 0x%x\n", type, val); if (type == PTS_TYPE_VIDEO) - WRITE_MPEG_REG(VIDEO_PTS, val); + WRITE_PARSER_REG(VIDEO_PTS, val); else if (type == PTS_TYPE_AUDIO) - WRITE_MPEG_REG(AUDIO_PTS, val); + WRITE_PARSER_REG(AUDIO_PTS, val); pTable->status = PTS_RUNNING; } @@ -1042,6 +1042,53 @@ int pts_set_rec_size(u8 type, u32 val) } } EXPORT_SYMBOL(pts_set_rec_size); + +/** + * return number of recs if the offset is bigger + */ +int pts_get_rec_num(u8 type, u32 val) +{ + ulong flags; + struct pts_table_s *pTable; + struct pts_rec_s *p; + int r = 0; + + if (type >= PTS_TYPE_MAX) + return 0; + + pTable = &pts_table[type]; + + if (list_empty(&pTable->valid_list)) + return 0; + + spin_lock_irqsave(&lock, flags); + + if (pTable->pts_search == &pTable->valid_list) { + p = list_entry(pTable->valid_list.next, + struct pts_rec_s, list); + } else { + p = list_entry(pTable->pts_search, struct pts_rec_s, + list); + } + + if (OFFSET_LATER(val, p->offset)) { + list_for_each_entry_continue(p, &pTable->valid_list, + list) { + if (OFFSET_LATER(p->offset, val)) + break; + } + } + + list_for_each_entry_continue(p, &pTable->valid_list, list) { + r++; + } + + spin_unlock_irqrestore(&lock, flags); + + return r; +} +EXPORT_SYMBOL(pts_get_rec_num); + /* #define SIMPLE_ALLOC_LIST */ static void free_pts_list(struct pts_table_s *pTable) { @@ -1151,16 +1198,21 @@ int pts_start(u8 type) return -ENOMEM; /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ if (has_hevc_vdec() && (type == PTS_TYPE_HEVC)) { +#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC + pTable->buf_start = READ_PARSER_REG( + PARSER_VIDEO_START_PTR); + pTable->buf_size = READ_PARSER_REG(PARSER_VIDEO_END_PTR) + - pTable->buf_start + 8; +#else pTable->buf_start = READ_VREG(HEVC_STREAM_START_ADDR); pTable->buf_size = READ_VREG(HEVC_STREAM_END_ADDR) - - pTable->buf_start; - WRITE_MPEG_REG(VIDEO_PTS, 0); + - pTable->buf_start; +#endif + WRITE_PARSER_REG(VIDEO_PTS, 0); timestamp_pcrscr_set(0); - /* - *video always need - * the pcrscr,Clear - *it to use later - */ + /* video always need the pcrscr,*/ + /*Clear it to use later */ + timestamp_firstvpts_set(0); pTable->first_checkin_pts = -1; pTable->first_lookup_ok = 0; @@ -1168,14 +1220,20 @@ int pts_start(u8 type) } else /* #endif */ if (type == PTS_TYPE_VIDEO) { +#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC + pTable->buf_start = READ_PARSER_REG( + PARSER_VIDEO_START_PTR); + pTable->buf_size = READ_PARSER_REG( + PARSER_VIDEO_END_PTR) + - pTable->buf_start + 8; +#else pTable->buf_start = READ_VREG( VLD_MEM_VIFIFO_START_PTR); pTable->buf_size = READ_VREG( VLD_MEM_VIFIFO_END_PTR) - pTable->buf_start + 8; - - /* - *since the HW buffer wrap counter only have +#endif + /* since the HW buffer wrap counter only have * 16 bits, a too small buf_size will make pts i * lookup fail with streaming offset wrapped * before 32 bits boundary. @@ -1184,29 +1242,25 @@ int pts_start(u8 type) */ /* BUG_ON(pTable->buf_size <= 0x10000); */ - WRITE_MPEG_REG(VIDEO_PTS, 0); + WRITE_PARSER_REG(VIDEO_PTS, 0); timestamp_pcrscr_set(0); - /* - *video always - *need the - *pcrscr, - *Clear it - *to use later - */ + /* video always need the pcrscr, */ + /*Clear it to use later*/ + timestamp_firstvpts_set(0); pTable->first_checkin_pts = -1; pTable->first_lookup_ok = 0; pTable->first_lookup_is_fail = 0; } else if (type == PTS_TYPE_AUDIO) { pTable->buf_start = - READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR); - pTable->buf_size = READ_MPEG_REG( + READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR); + pTable->buf_size = READ_AIU_REG( AIU_MEM_AIFIFO_END_PTR) - pTable->buf_start + 8; /* BUG_ON(pTable->buf_size <= 0x10000); */ - WRITE_MPEG_REG(AUDIO_PTS, 0); + WRITE_PARSER_REG(AUDIO_PTS, 0); timestamp_firstapts_set(0); pTable->first_checkin_pts = -1; pTable->first_lookup_ok = 0; diff --git a/drivers/amlogic/media/frame_sync/timestamp.c b/drivers/amlogic/media/frame_sync/timestamp.c index c226325..f85f8e7 100644 --- a/drivers/amlogic/media/frame_sync/timestamp.c +++ b/drivers/amlogic/media/frame_sync/timestamp.c @@ -49,31 +49,31 @@ void set_timestamp_inc_factor(u32 factor) u32 timestamp_vpts_get(void) { - return (u32) READ_MPEG_REG(VIDEO_PTS); + return (u32) READ_PARSER_REG(VIDEO_PTS); } EXPORT_SYMBOL(timestamp_vpts_get); void timestamp_vpts_set(u32 pts) { - WRITE_MPEG_REG(VIDEO_PTS, pts); + WRITE_PARSER_REG(VIDEO_PTS, pts); } EXPORT_SYMBOL(timestamp_vpts_set); void timestamp_vpts_inc(s32 val) { - WRITE_MPEG_REG(VIDEO_PTS, READ_MPEG_REG(VIDEO_PTS) + val); + WRITE_PARSER_REG(VIDEO_PTS, READ_PARSER_REG(VIDEO_PTS) + val); } EXPORT_SYMBOL(timestamp_vpts_inc); u32 timestamp_apts_get(void) { - return (u32) READ_MPEG_REG(AUDIO_PTS); + return (u32) READ_PARSER_REG(AUDIO_PTS); } EXPORT_SYMBOL(timestamp_apts_get); void timestamp_apts_set(u32 pts) { - WRITE_MPEG_REG(AUDIO_PTS, pts); + WRITE_PARSER_REG(AUDIO_PTS, pts); } EXPORT_SYMBOL(timestamp_apts_set); @@ -83,7 +83,7 @@ void timestamp_apts_inc(s32 inc) #ifdef MODIFY_TIMESTAMP_INC_WITH_PLL inc = inc * timestamp_inc_factor / PLL_FACTOR; #endif - WRITE_MPEG_REG(AUDIO_PTS, READ_MPEG_REG(AUDIO_PTS) + inc); + WRITE_PARSER_REG(AUDIO_PTS, READ_PARSER_REG(AUDIO_PTS) + inc); } } EXPORT_SYMBOL(timestamp_apts_inc); diff --git a/drivers/amlogic/media/frame_sync/tsync.c b/drivers/amlogic/media/frame_sync/tsync.c index a132df3..7498ba7 100644 --- a/drivers/amlogic/media/frame_sync/tsync.c +++ b/drivers/amlogic/media/frame_sync/tsync.c @@ -30,7 +30,7 @@ #include #include #include - +#include /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ /* TODO: for stream buffer register bit define only */ @@ -125,7 +125,9 @@ static const struct { AVEVENT_FLAG_PARAM }, { "AUDIO_PRE_START", 15, AUDIO_PRE_START, 0 - }, + }, { + "AUDIO_WAIT", 10, AUDIO_WAIT, 0 + } }; static const char * const tsync_mode_str[] = { @@ -216,9 +218,9 @@ static void tsync_pcr_recover_with_audio(void) #if 0 /* MESON_CPU_TYPE < MESON_CPU_TYPE_MESON6 */ if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6) { - u32 ab_level = READ_MPEG_REG(AIU_MEM_AIFIFO_LEVEL); - u32 ab_size = READ_MPEG_REG(AIU_MEM_AIFIFO_END_PTR) - - READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR) + 8; + u32 ab_level = READ_AIU_REG(AIU_MEM_AIFIFO_LEVEL); + u32 ab_size = READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR) + - READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR) + 8; u32 vb_level = READ_VREG(VLD_MEM_VIFIFO_LEVEL); u32 vb_size = READ_VREG(VLD_MEM_VIFIFO_END_PTR) - READ_VREG(VLD_MEM_VIFIFO_START_PTR) + 8; @@ -228,7 +230,7 @@ static void tsync_pcr_recover_with_audio(void) bool lower_than_high = false; bool higher_than_low = false; - if ((READ_MPEG_REG(AIU_MEM_I2S_CONTROL) & + if ((READ_AIU_REG(AIU_MEM_I2S_CONTROL) & (MEM_CTRL_EMPTY_EN | MEM_CTRL_EMPTY_EN)) == 0) return; /* @@ -471,7 +473,7 @@ static bool tsync_pcr_recover_use_video(void) *mixer so audio playback has no direct relationship with *applications. TODO. */ - return ((READ_MPEG_REG(AIU_MEM_I2S_CONTROL) & + return ((READ_AIU_REG(AIU_MEM_I2S_CONTROL) & (MEM_CTRL_EMPTY_EN | MEM_CTRL_EMPTY_EN)) == 0) ? true : false; } @@ -811,6 +813,9 @@ void tsync_avevent_locked(enum avevent_e event, u32 param) timestamp_apts_start(0); break; + case AUDIO_WAIT: + timestamp_pcrscr_set(timestamp_vpts_get()); + break; case AUDIO_START: /* reset discontinue var */ tsync_set_sync_adiscont(0); @@ -917,12 +922,12 @@ void tsync_avevent_locked(enum avevent_e event, u32 param) case VIDEO_START: case AUDIO_START: case AUDIO_RESUME: - /*amvdev_resume();*///DEBUG_TMP + /*amvdev_resume();*//*DEBUG_TMP*/ break; case VIDEO_STOP: case AUDIO_STOP: case AUDIO_PAUSE: - /*amvdev_pause();*///DEBUG_TMP + /*amvdev_pause();*//*DEBUG_TMP*/ break; case VIDEO_PAUSE: /* @@ -1075,7 +1080,7 @@ int tsync_set_apts(unsigned int pts) timestamp_apts_set(pts); /*if (get_vsync_pts_inc_mode() && (tsync_mode != TSYNC_MODE_VMASTER))*/ - /*tsync_mode = TSYNC_MODE_VMASTER;*///DEBUG_TMP + /*tsync_mode = TSYNC_MODE_VMASTER;*//*DEBUG_TMP*/ if (tsync_mode == TSYNC_MODE_AMASTER) t = timestamp_pcrscr_get(); @@ -1916,6 +1921,159 @@ static struct class tsync_class = { .class_attrs = tsync_class_attrs, }; + +int tsync_store_fun(const char *trigger, int id, const char *buf, int size) +{ + int ret = size; + + switch (id) { + case 0: return store_vpts(NULL, NULL, buf, size); + case 1: return store_apts(NULL, NULL, buf, size); + case 2: return dobly_store_sync(NULL, NULL, buf, size); + case 3: return store_pcrscr(NULL, NULL, buf, size); + case 4: return store_event(NULL, NULL, buf, size); + case 5: return store_mode(NULL, NULL, buf, size); + case 6: return store_enable(NULL, NULL, buf, size); + case 7: return store_pcr_recover(NULL, NULL, buf, size); + case 8: return store_discontinue(NULL, NULL, buf, size); + case 9: return store_debug_pts_checkin(NULL, NULL, buf, size); + case 10:return store_debug_pts_checkout(NULL, NULL, buf, size); + case 11:return store_debug_vpts(NULL, NULL, buf, size); + case 12:return store_debug_apts(NULL, NULL, buf, size); + case 13:return store_av_threshold_min(NULL, NULL, buf, size); + case 14:return store_av_threshold_max(NULL, NULL, buf, size); + /*case 15:return -1;*/ + /*case 16:return -1;*/ + case 17:return store_vpause_flag(NULL, NULL, buf, size); + case 18:return store_slowsync_enable(NULL, NULL, buf, size); + case 19:return store_startsync_mode(NULL, NULL, buf, size); + case 20:return store_firstapts(NULL, NULL, buf, size); + case 21:return -1; + default: + ret = -1; + } + return size; +} +int tsync_show_fun(const char *trigger, int id, char *sbuf, int size) +{ + int ret = -1; + void *buf, *getbuf = NULL; + + if (size < PAGE_SIZE) { + getbuf = (void *)__get_free_page(GFP_KERNEL); + if (!getbuf) + return -ENOMEM; + buf = getbuf; + } else { + buf = sbuf; + } + + switch (id) { + case 0: + ret = show_vpts(NULL, NULL, buf); + break; + case 1: + ret = show_apts(NULL, NULL, buf); + break; + case 2: + ret = dobly_show_sync(NULL, NULL, buf); + break; + case 3: + ret = show_pcrscr(NULL, NULL, buf); + break; + case 4: + ret = -1; + break; + case 5: + ret = show_mode(NULL, NULL, buf); + break; + case 6: + ret = show_enable(NULL, NULL, buf); + break; + case 7: + ret = show_pcr_recover(NULL, NULL, buf); + break; + case 8: + ret = show_discontinue(NULL, NULL, buf); + break; + case 9: + ret = show_debug_pts_checkin(NULL, NULL, buf); + break; + case 10: + ret = show_debug_pts_checkout(NULL, NULL, buf); + break; + case 11: + ret = show_debug_vpts(NULL, NULL, buf); + break; + case 12: + ret = show_debug_apts(NULL, NULL, buf); + break; + case 13: + ret = show_av_threshold_min(NULL, NULL, buf); + break; + case 14: + ret = show_av_threshold_max(NULL, NULL, buf); + break; + case 15: + ret = show_last_checkin_apts(NULL, NULL, buf); + break; + case 16: + ret = show_firstvpts(NULL, NULL, buf); + break; + case 17: + ret = show_vpause_flag(NULL, NULL, buf); + break; + case 18: + ret = show_slowsync_enable(NULL, NULL, buf); + break; + case 19: + ret = show_startsync_mode(NULL, NULL, buf); + break; + case 20: + ret = show_firstapts(NULL, NULL, buf); + break; + case 21: + ret = show_checkin_firstvpts(NULL, NULL, buf); + break; + default: + ret = -1; + } + if (ret > 0 && getbuf != NULL) { + ret = min_t(int, ret, size); + strncpy(sbuf, buf, ret); + } + if (getbuf != NULL) + free_page((unsigned long)getbuf); + return ret; +} + + +static struct mconfig tsync_configs[] = { + MC_FUN_ID("pts_video", tsync_show_fun, tsync_store_fun, 0), + MC_FUN_ID("pts_audio", tsync_show_fun, tsync_store_fun, 1), + MC_FUN_ID("dobly_av_sync", tsync_show_fun, tsync_store_fun, 2), + MC_FUN_ID("pts_pcrscr", tsync_show_fun, tsync_store_fun, 3), + MC_FUN_ID("event", tsync_show_fun, tsync_store_fun, 4), + MC_FUN_ID("mode", tsync_show_fun, tsync_store_fun, 5), + MC_FUN_ID("enable", tsync_show_fun, tsync_store_fun, 6), + MC_FUN_ID("pcr_recover", tsync_show_fun, tsync_store_fun, 7), + MC_FUN_ID("discontinue", tsync_show_fun, tsync_store_fun, 8), + MC_FUN_ID("debug_pts_checkin", tsync_show_fun, tsync_store_fun, 9), + MC_FUN_ID("debug_pts_checkout", tsync_show_fun, tsync_store_fun, 10), + MC_FUN_ID("debug_video_pts", tsync_show_fun, tsync_store_fun, 11), + MC_FUN_ID("debug_audio_pts", tsync_show_fun, tsync_store_fun, 12), + MC_FUN_ID("av_threshold_min", tsync_show_fun, tsync_store_fun, 13), + MC_FUN_ID("av_threshold_max", tsync_show_fun, tsync_store_fun, 14), + MC_FUN_ID("last_checkin_apts", tsync_show_fun, NULL, 15), + MC_FUN_ID("firstvpts", tsync_show_fun, NULL, 16), + MC_FUN_ID("vpause_flag", tsync_show_fun, tsync_store_fun, 17), + MC_FUN_ID("slowsync_enable", tsync_show_fun, tsync_store_fun, 18), + MC_FUN_ID("startsync_mode", tsync_show_fun, tsync_store_fun, 19), + MC_FUN_ID("firstapts", tsync_show_fun, tsync_store_fun, 20), + MC_FUN_ID("checkin_firstvpts", tsync_show_fun, NULL, 21), +}; + + static int __init tsync_module_init(void) { int r; @@ -1929,6 +2087,8 @@ static int __init tsync_module_init(void) tsync_pcr_init(); + REG_PATH_CONFIGS("media.tsync", tsync_configs); + return 0; } diff --git a/drivers/amlogic/media/frame_sync/tsync_pcr.c b/drivers/amlogic/media/frame_sync/tsync_pcr.c index 9af1ab3..4868932 100644 --- a/drivers/amlogic/media/frame_sync/tsync_pcr.c +++ b/drivers/amlogic/media/frame_sync/tsync_pcr.c @@ -26,7 +26,7 @@ #include #include -#include +#include #ifdef CONFIG_AM_PCRSYNC_LOG #define AMLOG @@ -120,8 +120,8 @@ static u32 tsync_pcr_discontinue_threshold = (TIME_UNIT90K * 1.5); static u32 tsync_pcr_ref_latency = (TIME_UNIT90K * 0.3); /* use for pcr valid mode */ -static u32 tsync_pcr_max_cache_time = TIME_UNIT90K * 1.5; -static u32 tsync_pcr_up_cache_time = TIME_UNIT90K * 1.2; +static u32 tsync_pcr_max_cache_time = TIME_UNIT90K * 2.4; +static u32 tsync_pcr_up_cache_time = TIME_UNIT90K * 2.2; /* modify it by dolby av sync */ static u32 tsync_pcr_down_cache_time = TIME_UNIT90K * 0.8; /* 0.6 */ static u32 tsync_pcr_min_cache_time = TIME_UNIT90K * 0.4; /* 0.2 */ @@ -193,6 +193,18 @@ static DEFINE_SPINLOCK(tsync_pcr_lock); #define LTRACE() pr_info("[%s:%d]\n", __func__, __LINE__) +module_param(tsync_pcr_max_cache_time, uint, 0664); +MODULE_PARM_DESC(tsync_pcr_max_cache_time, "\n tsync pcr max cache time\n"); + +module_param(tsync_pcr_up_cache_time, uint, 0664); +MODULE_PARM_DESC(tsync_pcr_up_cache_time, "\n tsync pcr up cache time\n"); + +module_param(tsync_pcr_down_cache_time, uint, 0664); +MODULE_PARM_DESC(tsync_pcr_down_cache_time, "\n tsync pcr down cache time\n"); + +module_param(tsync_pcr_min_cache_time, uint, 0664); +MODULE_PARM_DESC(tsync_pcr_min_cache_time, "\n tsync pcr min cache time\n"); + u32 get_stbuf_rp(int type) { #if 0//DEBUG_TMP @@ -211,7 +223,7 @@ u32 get_stbuf_rp(int type) pbuf = get_buf_by_type(PTS_TYPE_VIDEO); if (pbuf != NULL && pbuf->flag & BUF_FLAG_IN_USE) - return stbuf_rp(pbuf) + return stbuf_rp(pbuf); } else { /* audio */ pbuf = get_buf_by_type(PTS_TYPE_AUDIO); @@ -517,7 +529,7 @@ void tsync_pcr_avevent_locked(enum avevent_e event, u32 param) case VIDEO_TSTAMP_DISCONTINUITY: { /* unsigned oldpts=timestamp_vpts_get(); */ - /*u32 tsdemux_pcr = 0;*//*tsdemux_pcrscr_get();*///DEBUG_TMP + /*u32 tsdemux_pcr = 0;*//*tsdemux_pcrscr_get();*//*DEBUG_TMP*/ /* if((abs(param-oldpts)>AV_DISCONTINUE_THREDHOLD_MIN) && *(!get_vsync_pts_inc_mode())){ */ @@ -695,18 +707,18 @@ void tsync_pcr_avevent_locked(enum avevent_e event, u32 param) case VIDEO_START: case AUDIO_START: case AUDIO_RESUME: - /*amvdev_resume();*///DEBUG_TMP + /*amvdev_resume();*//*DEBUG_TMP*/ break; case VIDEO_STOP: case AUDIO_STOP: case AUDIO_PAUSE: - /*amvdev_pause();*///DEBUG_TMP + /*amvdev_pause();*//*DEBUG_TMP*/ break; case VIDEO_PAUSE: /*if (tsync_pcr_vpause_flag)*/ - /*amvdev_pause();*///DEBUG_TMP + /*amvdev_pause();*//*DEBUG_TMP*/ /*else*/ - /*amvdev_resume();*///DEBUG_TMP + /*amvdev_resume();*//*DEBUG_TMP*/ break; default: break; @@ -734,7 +746,7 @@ static unsigned long tsync_pcr_check(void) || tsync_pcr_freerun_mode == 1) return res; - tsdemux_pcr = 0;/*tsdemux_pcrscr_get();*///DEBUG_TMP + tsdemux_pcr = 0;/*tsdemux_pcrscr_get();*//*DEBUG_TMP*/ if (tsync_pcr_usepcr == 1) { /* To monitor the pcr discontinue */ tsdemux_pcr_diff = abs(tsdemux_pcr - tsync_pcr_last_tsdemuxpcr); @@ -755,12 +767,17 @@ static unsigned long tsync_pcr_check(void) tsync_pcr_discontinue_waited = TIME_UNIT90K * 5; pr_info - ("[tsync_pcr_check] refpcr_discontinue. "); + ("[tsync_pcr_check] refpcr_discontinue.\n"); pr_info - ("tsdemux_pcr_diff=%x, last refpcr=%x, ", + ("tsdemux_pcr_diff=%x, last refpcr=%x,\n", tsdemux_pcr_diff, tsync_pcr_last_tsdemuxpcr); pr_info("repcr=%x,waited=%x\n", tsdemux_pcr, tsync_pcr_discontinue_waited); + pr_info("last checkin vpts:%d\n", + (u32)get_last_checkin_pts(PTS_TYPE_VIDEO)); + pr_info("last checkin apts:%d\n", + (u32)get_last_checkin_pts(PTS_TYPE_AUDIO)); + tsync_pcr_discontinue_local_point = timestamp_pcrscr_get(); tsync_pcr_discontinue_point = @@ -777,6 +794,12 @@ static unsigned long tsync_pcr_check(void) pr_info (" discontinue didn't happen, waited=%x\n", tsync_pcr_discontinue_waited); + pr_info + (" timestamp_pcrscr_get() =%x\n", + timestamp_pcrscr_get()); + pr_info + (" tsync_pcr_discontinue_local_point =%x\n", + tsync_pcr_discontinue_local_point); /* the v-discontinue did'n happen */ tsync_pcr_tsdemuxpcr_discontinue = 0; tsync_pcr_discontinue_point = 0; @@ -858,17 +881,18 @@ static unsigned long tsync_pcr_check(void) cur_vpts = timestamp_vpts_get(); /*set pcr after discontinue according to apts and vpts*/ - if (tsync_pcr_tsdemuxpcr_discontinue & + if ((tsync_pcr_tsdemuxpcr_discontinue & + (AUDIO_DISCONTINUE | VIDEO_DISCONTINUE)) == (AUDIO_DISCONTINUE | VIDEO_DISCONTINUE)) { if (cur_apts < cur_vpts && cur_vpts - cur_apts < 3 * 90000 && last_checkin_minpts - cur_apts > 54000) timestamp_pcrscr_set(cur_apts + 6300); else timestamp_pcrscr_set(cur_apts); -/* - * pr_info("after discontinue, pcr = 0x%x,apts=0x%x,vpts=0x%x\n", - * timestamp_pcrscr_get(), cur_apts, cur_vpts); - */ + + pr_info("after discontinue, pcr = 0x%x,apts=0x%x,vpts=0x%x\n", + timestamp_pcrscr_get(), cur_apts, cur_vpts); + } if (tsync_pcr_reset_flag == 0) { @@ -1064,7 +1088,8 @@ static unsigned long tsync_pcr_check(void) u64 ref_pcr = (u64) tsdemux_pcr; u64 cur_pcr = (u64) timestamp_pcrscr_get(); int64_t cur_delta = (int64_t) ref_pcr - (int64_t) cur_pcr; - int64_t diff = (cur_delta - tsync_pcr_stream_delta); + /* int64_t diff = (cur_delta - tsync_pcr_stream_delta); */ + int64_t diff = cur_delta; /* if(diff > OPEN_RECOVERY_THRESHOLD && cur_pcrindex != 8) + mutex_lock(&dev->vfpMutex); AMLVIDEO_DBG("AML:VFRAME_EVENT_PROVIDER_UNREG\n"); if (vf_get_receiver(dev->vf_provider_name)) { AMLVIDEO_DBG("unreg:amlvideo\n"); @@ -241,17 +243,20 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) dev->vf = NULL; dev->first_frame = 0; + mutex_unlock(&dev->vfpMutex); } else if (type == VFRAME_EVENT_PROVIDER_QUREY_STATE) { amlvideo_vf_states(&states, dev); - if (states.buf_avail_num > 0) + if (states.buf_avail_num > 0) { return RECEIVER_ACTIVE; - if (vf_notify_receiver( - dev->vf_provider_name, - VFRAME_EVENT_PROVIDER_QUREY_STATE, - NULL) == RECEIVER_ACTIVE) - return RECEIVER_ACTIVE; - return RECEIVER_INACTIVE; - + } else { + if (vf_notify_receiver( + dev->vf_provider_name, + VFRAME_EVENT_PROVIDER_QUREY_STATE, + NULL) + == RECEIVER_ACTIVE) + return RECEIVER_ACTIVE; + return RECEIVER_INACTIVE; + } /*break;*/ } else if (type == VFRAME_EVENT_PROVIDER_START) { AMLVIDEO_DBG("AML:VFRAME_EVENT_PROVIDER_START\n"); @@ -270,6 +275,12 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) VFRAME_EVENT_PROVIDER_START, NULL); } + } else if (type == VFRAME_EVENT_PROVIDER_FR_HINT) { + vf_notify_receiver(dev->vf_provider_name, + VFRAME_EVENT_PROVIDER_FR_HINT, data); + } else if (type == VFRAME_EVENT_PROVIDER_FR_END_HINT) { + vf_notify_receiver(dev->vf_provider_name, + VFRAME_EVENT_PROVIDER_FR_END_HINT, data); } return 0; } @@ -507,6 +518,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) dev->vf = vf_get(dev->vf_receiver_name); if (!dev->vf) { /* printk("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */ + mutex_unlock(&dev->vfpMutex); return -EAGAIN; } @@ -593,6 +605,7 @@ static int amlvideo_open(struct file *file) dev->vf = NULL; dev->index = 0; + mutex_unlock(&dev->vfpMutex); mutex_lock(&dev->mutex); dev->users++; if (dev->users > 1) { @@ -605,15 +618,15 @@ static int amlvideo_open(struct file *file) dev->users--; mutex_unlock(&dev->mutex); return -ENOMEM; + } else { + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (fh == NULL) { + kfree(res); + dev->users--; + mutex_unlock(&dev->mutex); + retval = -ENOMEM; + } } - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (fh == NULL) { - kfree(res); - dev->users--; - mutex_unlock(&dev->mutex); - retval = -ENOMEM; - } - mutex_unlock(&dev->mutex); file->private_data = fh; @@ -677,6 +690,7 @@ static int amlvideo_close(struct file *file) videobuf_mmap_free(&fh->vb_vidq); kfree(fh); dev->index = 8; + mutex_unlock(&dev->vfpMutex); /* if (dev->res) { */ kfree(dev->res); dev->res = NULL; @@ -802,6 +816,7 @@ static int __init amlvideo_create_instance(int inst) /* initialize locks */ spin_lock_init(&dev->slock); mutex_init(&dev->mutex); + mutex_init(&dev->vfpMutex); ret = -ENOMEM; vfd = video_device_alloc(); @@ -862,7 +877,16 @@ free_dev: kfree(dev); return ret; } -static int amlvideo_driver_probe(struct platform_device *pdev) +#undef NORM_MAXW +#undef NORM_MAXH +/* #define __init */ +/* This routine allocates from 1 to n_devs virtual drivers.*/ +/* + *The real maximum number of virtual drivers will depend on how many drivers + *will succeed. This is limited to the maximum number of devices that + *videodev supports, which is equal to VIDEO_NUM_DEVICES. + */ +static int __init amlvideo_init(void) { int ret = 0, i; @@ -899,51 +923,10 @@ static int amlvideo_driver_probe(struct platform_device *pdev) return ret; } -static int amlvideo_drv_remove(struct platform_device *pdev) +static void __exit amlvideo_exit(void) { /*vf_unreg_receiver(&video_vf_recv);*/ amlvideo_release(); - return 0; -} - -static const struct of_device_id amlvideo_dt_match[] = { - { - .compatible = "amlogic, amlvideo", - }, -}; - -/* general interface for a linux driver .*/ -static struct platform_driver amlvideo_drv = { -.probe = amlvideo_driver_probe, -.remove = amlvideo_drv_remove, -.driver = { - .name = "amlvideo", - .owner = THIS_MODULE, - .of_match_table = amlvideo_dt_match, - } -}; - -#undef NORM_MAXW -#undef NORM_MAXH -/* #define __init */ -/* This routine allocates from 1 to n_devs virtual drivers. - * The real maximum number of virtual drivers will depend on how many drivers - * will succeed. This is limited to the maximum number of devices that - * videodev supports, which is equal to VIDEO_NUM_DEVICES. - */ -static int __init amlvideo_init(void) -{ - if (platform_driver_register(&amlvideo_drv)) { - pr_err("Failed to register amlvideo driver\n"); - return -ENODEV; - } - - return 0; -} - -static void __exit amlvideo_exit(void) -{ - platform_driver_unregister(&amlvideo_drv); } module_init(amlvideo_init); diff --git a/drivers/amlogic/media/video_processor/video_dev/amlvideo.h b/drivers/amlogic/media/video_processor/video_dev/amlvideo.h index 5ad5aea..7f0bf72 100644 --- a/drivers/amlogic/media/video_processor/video_dev/amlvideo.h +++ b/drivers/amlogic/media/video_processor/video_dev/amlvideo.h @@ -72,6 +72,7 @@ struct vivi_dev { struct vframe_s *vf; struct vframe_s *amlvideo_pool_ready[AMLVIDEO_POOL_SIZE + 1]; int index; + struct mutex vfpMutex; int amlvideo_v4l_num; char vf_receiver_name[AMLVIDEO_VF_NAME_SIZE]; char vf_provider_name[AMLVIDEO_VF_NAME_SIZE]; diff --git a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c index 9ab3761..3494e3d 100644 --- a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c +++ b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c @@ -4680,17 +4680,52 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); } #endif - -static enum tvin_scan_mode_e vmode2scan_mode(const struct vinfo_s *vinfo) +static enum tvin_scan_mode_e vmode2scan_mode(enum vmode_e mode) { enum tvin_scan_mode_e scan_mode = TVIN_SCAN_MODE_NULL;/* 1: progressive 2:interlaced */ - if (vinfo->height == vinfo->field_height) - scan_mode = TVIN_SCAN_MODE_PROGRESSIVE; - else +#if 0 //DEBUG_TMP + switch (mode) { + case VMODE_480I: + case VMODE_480CVBS: + case VMODE_NTSC_M: + case VMODE_576I: + case VMODE_576CVBS: + case VMODE_PAL_M: + case VMODE_PAL_N: + case VMODE_1080I: + case VMODE_1080I_50HZ: scan_mode = TVIN_SCAN_MODE_INTERLACED; - + break; + case VMODE_480P: + case VMODE_576P: + case VMODE_720P: + case VMODE_1080P: + case VMODE_720P_50HZ: + case VMODE_1080P_50HZ: + case VMODE_1080P_24HZ: + case VMODE_4K2K_30HZ: + case VMODE_4K2K_25HZ: + case VMODE_4K2K_24HZ: + case VMODE_4K2K_SMPTE: + case VMODE_VGA: + case VMODE_SVGA: + case VMODE_XGA: + case VMODE_SXGA: + case VMODE_LCD: + case VMODE_4K2K_50HZ: + case VMODE_4K2K_50HZ_Y420: + case VMODE_4K2K_60HZ: + case VMODE_4K2K_60HZ_Y420: + scan_mode = TVIN_SCAN_MODE_PROGRESSIVE; + break; + default: + pr_err("unknown mode=%d\n", mode); + break; + } + /* pr_err("mode=%d, scan_mode=%d\n", mode, scan_mode); */ +#endif return scan_mode; } @@ -4751,7 +4786,7 @@ static int amlvideo2_start_tvin_service(struct amlvideo2_node *node) para.vs_bp = 0; para.dfmt = TVIN_NV21;/* TVIN_YUV422; */ para.scan_mode = vmode2scan_mode( - vinfo);/* TVIN_SCAN_MODE_PROGRESSIVE; */ + vinfo->mode);/* TVIN_SCAN_MODE_PROGRESSIVE; */ if (para.scan_mode == TVIN_SCAN_MODE_INTERLACED) para.v_active = para.v_active / 2; @@ -4868,8 +4903,7 @@ int amlvideo2_notify_callback(struct notifier_block *block, unsigned long cmd, } /*debug provider vf state*/ if (amlvideo2_dbg_en) { - if (vfp && vfp->ops && vfp->ops->vf_states) - ret = vfp->ops->vf_states(&states, vfp->op_arg); + ret = vf_get_states(vfp, &states); if (ret == 0) { pr_info("vf_pool_size = %d, buf_free_num = %d .\n", states.vf_pool_size, states.buf_free_num); @@ -4992,7 +5026,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) para.vs_bp = 0; para.dfmt = TVIN_NV21;/* TVIN_YUV422; */ para.scan_mode = vmode2scan_mode( - vinfo);/* TVIN_SCAN_MODE_PROGRESSIVE; */ + vinfo->mode);/* TVIN_SCAN_MODE_PROGRESSIVE; */ if (para.scan_mode == TVIN_SCAN_MODE_INTERLACED) para.v_active = para.v_active / 2; @@ -5453,6 +5487,7 @@ static int amlvideo2_open(struct file *file) pr_err("alloc amlvideo2.0 cma buffer failed.\n"); else pr_err("alloc amlvideo2.1 cma buffer failed.\n"); + node->users--; mutex_unlock(&node->mutex); return -ENOMEM; } @@ -5461,6 +5496,7 @@ static int amlvideo2_open(struct file *file) if (fh == NULL) { node->users--; /* node->provider = NULL; */ + amlvideo2_cma_buf_uninit(node->vid_dev, node->vid); mutex_unlock(&node->mutex); return -ENOMEM; } @@ -5469,6 +5505,8 @@ static int amlvideo2_open(struct file *file) reserve = &node->vid_dev->memobj; if (!reserve) { pr_err("alloc reserve buffer failed !\n"); + node->users--; + amlvideo2_cma_buf_uninit(node->vid_dev, node->vid); mutex_unlock(&node->mutex); return -ENOMEM; } @@ -5631,15 +5669,11 @@ static struct video_device amlvideo2_template = { /* .current_norm = V4L2_STD_NTSC_M, */ }; -static int vf_get_states(struct vframe_states *states, int node_index) +static int amlvideo2_vf_get_states(struct vframe_states *states, int node_index) { int ret = -1; - struct vframe_provider_s *vfp; const char *name = (node_index == 0) ? DEVICE_NAME0 : DEVICE_NAME1; - - vfp = vf_get_provider(name); - if (vfp && vfp->ops && vfp->ops->vf_states) - ret = vfp->ops->vf_states(states, vfp->op_arg); + ret = vf_get_states_by_name(name, states); return ret; } @@ -5720,7 +5754,7 @@ static int amlvideo2_receiver_event_fun(int type, void *data, node->amlvideo2_pool_ready = NULL; node->amlvideo2_pool_size = 0; node->video_blocking = false; - if (vf_get_states(&frame_states, node->vid) == 0) + if (amlvideo2_vf_get_states(&frame_states, node->vid) == 0) node->amlvideo2_pool_size = frame_states.vf_pool_size; else node->amlvideo2_pool_size = 4; diff --git a/drivers/amlogic/media/video_sink/Kconfig b/drivers/amlogic/media/video_sink/Kconfig index 908c859..68c8f4b 100644 --- a/drivers/amlogic/media/video_sink/Kconfig +++ b/drivers/amlogic/media/video_sink/Kconfig @@ -23,4 +23,10 @@ config AMLOGIC_MEDIA_VSYNC_RDMA endif +config AMLOGIC_MEDIA_VIDEOCAPTURE + bool "Amlogic Video Capture support" + default n + help + Internal Video Capture driver + endmenu diff --git a/drivers/amlogic/media/video_sink/amvideocap_priv.h b/drivers/amlogic/media/video_sink/amvideocap_priv.h new file mode 100644 index 0000000..40b2fb2 --- /dev/null +++ b/drivers/amlogic/media/video_sink/amvideocap_priv.h @@ -0,0 +1,69 @@ +/* + * drivers/amlogic/media/video_sink/amvideocap_priv.h + * + * Copyright (C) 2017 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 AMVIDEOCAP_PRIV_HHH +#define AMVIDEOCAP_PRIV_HHH +#include +#include + +struct video_frame_info { + int at_flags; + int width; + int height; + int fmt; + int width_aligned; + int byte_per_pix; + u64 timestamp_ms; +}; + +struct src_cap_rect { + int x; + int y; + int width; + int height; +}; + +struct amvideocap_private { + int flags; + int buf_size; + unsigned long phyaddr; + u8 *vaddr; + enum amvideocap_state state; + int sended_end_frame_cap_req; + int wait_max_ms; + + struct video_frame_info src; + struct video_frame_info want; + struct video_frame_info out; + struct src_cap_rect src_rect; +}; + +struct amvideocap_req_data { + struct amvideocap_private *privdata; +}; + +struct amvideocap_req { + int (*callback)(unsigned long data, struct vframe_s *vfput, + int index); + unsigned long data; + int at_flags; /*AT_ */ + u64 timestamp_ms; +}; + +s32 amvideocap_register_memory(unsigned char *phybufaddr, int phybufsize); + +#endif diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 5933a6c..349007b 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -64,7 +64,7 @@ #include #include #include "videolog.h" -#ifdef CONFIG_AM_VIDEOCAPTURE +#ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE #include "amvideocap_priv.h" #endif #ifdef CONFIG_AM_VIDEO_LOG @@ -82,17 +82,19 @@ MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_DEFAULT_LEVEL_DESC, LOG_MASK_DESC); #endif #include #include +#include + +#include "../common/vfm/vfm.h" static u32 osd_vpp_misc; static u32 osd_vpp_misc_mask; static bool update_osd_vpp_misc; int video_vsync = -ENXIO; - +/*global video manage cmd. */ #define DEBUG_TMP 0 - -#define CONFIG_AM_VOUT +static int video_global_output = 1; #ifdef CONFIG_GE2D_KEEP_FRAME /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ @@ -114,6 +116,12 @@ static int output_fps; static u32 omx_pts; static int omx_pts_interval_upper = 11000; static int omx_pts_interval_lower = -5500; +static int drop_frame_count; +static int receive_frame_count; +static int display_frame_count; + +#define DURATION_GCD 750 + static bool bypass_pps; /*For 3D usage ----0: mbx 1: tv */ bool platform_type = 1; @@ -128,6 +136,7 @@ bool omx_secret_mode; #define RECEIVER_NAME "amvideo" static s32 amvideo_poll_major; +/*static s8 dolby_first_delay;*/ /* for bug 145902 */ static int video_receiver_event_fun(int type, void *data, void *); @@ -183,6 +192,8 @@ static DEFINE_SPINLOCK(video_onoff_lock); static int video_onoff_state = VIDEO_ENABLE_STATE_IDLE; static DEFINE_SPINLOCK(video2_onoff_lock); static int video2_onoff_state = VIDEO_ENABLE_STATE_IDLE; +static u32 hdmiin_frame_check = 1; +static u32 hdmiin_frame_check_cnt; #ifdef FIQ_VSYNC #define BRIDGE_IRQ INT_TIMER_C @@ -266,6 +277,7 @@ static int video2_onoff_state = VIDEO_ENABLE_STATE_IDLE; spin_lock_irqsave(&video_onoff_lock, flags); \ video_onoff_state = VIDEO_ENABLE_STATE_ON_REQ; \ video_enabled = 1;\ + video_status_saved = 1;\ spin_unlock_irqrestore(&video_onoff_lock, flags); \ } while (0) @@ -275,6 +287,7 @@ static int video2_onoff_state = VIDEO_ENABLE_STATE_IDLE; spin_lock_irqsave(&video_onoff_lock, flags); \ video_onoff_state = VIDEO_ENABLE_STATE_OFF_REQ; \ video_enabled = 0;\ + video_status_saved = 0;\ spin_unlock_irqrestore(&video_onoff_lock, flags); \ } while (0) @@ -394,7 +407,7 @@ static int video2_onoff_state = VIDEO_ENABLE_STATE_IDLE; #define DisableVPP2VideoLayer() \ CLEAR_VCBUS_REG_MASK(VPP2_MISC, \ VPP_VD1_PREBLEND|VPP_VD2_PREBLEND|\ - VPP_VD2_POSTBLEND|VPP_VD1_POSTBLEND); + VPP_VD2_POSTBLEND|VPP_VD1_POSTBLEND) #endif /*********************************************************/ @@ -427,6 +440,11 @@ static int vpts_chase_counter; static int vpts_chase_pts_diff; #endif + +static int step_enable; +static int step_flag; + + /*seek values on.video_define.h*/ static int debug_flag; int get_video_debug_flags(void) @@ -457,6 +475,16 @@ static int pause_one_3d_fl_frame; MODULE_PARM_DESC(pause_one_3d_fl_frame, "\n pause_one_3d_fl_frame\n"); module_param(pause_one_3d_fl_frame, uint, 0664); +/*debug info control for skip & repeate vframe case*/ +static unsigned int video_dbg_vf; +MODULE_PARM_DESC(video_dbg_vf, "\n video_dbg_vf\n"); +module_param(video_dbg_vf, uint, 0664); + +static unsigned int video_get_vf_cnt; +static unsigned int video_drop_vf_cnt; +MODULE_PARM_DESC(video_drop_vf_cnt, "\n video_drop_vf_cnt\n"); +module_param(video_drop_vf_cnt, uint, 0664); + enum toggle_out_fl_frame_e { OUT_FA_A_FRAME, OUT_FA_BANK_FRAME, @@ -518,9 +546,8 @@ static u32 video_scaler_mode; static int content_top = 0, content_left = 0, content_w = 0, content_h; static int scaler_pos_changed; #endif -#if DEBUG_TMP + static struct amvideocap_req *capture_frame_req; -#endif static struct video_prot_s video_prot; static u32 video_angle; u32 get_video_angle(void) @@ -590,7 +617,6 @@ void amvideo_set_scaler_para(int x, int y, int w, int h, int flag) vpp_set_video_layer_position(x, y, w, h); video_property_changed = true; mutex_unlock(&video_module_mutex); - return; } u32 amvideo_get_scaler_mode(void) @@ -606,12 +632,12 @@ bool to_notify_trick_wait; #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA static struct vframe_s *cur_rdma_buf; /* -void vsync_rdma_config(void); -void vsync_rdma_config_pre(void); -bool is_vsync_rdma_enable(void); -void start_rdma(void); -void enable_rdma_log(int flag); -*/ + *void vsync_rdma_config(void); + *void vsync_rdma_config_pre(void); + *bool is_vsync_rdma_enable(void); + *void start_rdma(void); + *void enable_rdma_log(int flag); + */ static int enable_rdma_log_count; bool rdma_enable_pre; @@ -695,6 +721,7 @@ static u32 force_blackout; /* disable video */ static u32 disable_video = VIDEO_DISABLE_NONE; static u32 video_enabled __nosavedata; +static u32 video_status_saved __nosavedata; u32 get_video_enabled(void) { return video_enabled; @@ -726,6 +753,7 @@ int get_video0_frame_info(struct vframe_s *vf) { unsigned long flags; int ret = -1; + spin_lock_irqsave(&lock, flags); if (is_vpp_postblend() && cur_dispbuf && vf) { *vf = *cur_dispbuf; @@ -753,6 +781,8 @@ static u32 vsync_slow_factor = 1; static u32 last_frame_count; static u32 frame_count; static u32 new_frame_count; +static u32 first_frame_toggled; +static u32 toggle_count; static u32 last_frame_time; static u32 timer_count; static u32 vsync_count; @@ -791,6 +821,11 @@ char file_name[512]; #define FREERUN_DUR 2 /* freerun with duration */ static u32 freerun_mode; static u32 slowsync_repeat_enable; +static bool dmc_adjust = true; +module_param_named(dmc_adjust, dmc_adjust, bool, 0644); +static u32 dmc_config_state; +static u32 last_toggle_count; +static u32 toggle_same_count; void set_freerun_mode(int mode) { @@ -819,6 +854,7 @@ static wait_queue_head_t amvideo_sizechange_wait; #define VPU_DELAYWORK_MEM_POWER_OFF_VD2 4 #define VPU_DELAYWORK_MEM_POWER_OFF_PROT 8 #define VPU_VIDEO_LAYER1_CHANGED 16 +#define VPU_UPDATE_DOLBY_VISION 32 #define VPU_MEM_POWEROFF_DELAY 100 static struct work_struct vpu_delay_work; @@ -837,6 +873,9 @@ static int video_play_clone_rate = 60; static int android_clone_rate = 30; static int noneseamless_play_clone_rate = 5; #endif + +#define CONFIG_AM_VOUT //DEBUG_TMP + void safe_disble_videolayer(void) { #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER @@ -859,6 +898,7 @@ static inline struct vframe_s *video_vf_peek(void) static inline struct vframe_s *video_vf_get(void) { struct vframe_s *vf = NULL; + vf = vf_get(RECEIVER_NAME); if (vf) { @@ -882,11 +922,11 @@ static inline struct vframe_s *video_vf_get(void) mvc_flag = 0; } if (((process_3d_type & MODE_FORCE_3D_TO_2D_LR) -#if DEBUG_TMP || (process_3d_type & MODE_FORCE_3D_LR) -#endif + || (process_3d_type & MODE_FORCE_3D_FA_LR) ) - && (!(vf->type & VIDTYPE_MVC))) { + && (!(vf->type & VIDTYPE_MVC)) + && (vf->trans_fmt != TVIN_TFMT_3D_FP)) { vf->trans_fmt = TVIN_TFMT_3D_DET_LR; vf->left_eye.start_x = 0; vf->left_eye.start_y = 0; @@ -898,11 +938,11 @@ static inline struct vframe_s *video_vf_get(void) vf->right_eye.width = vf->width / 2; } if (((process_3d_type & MODE_FORCE_3D_TO_2D_TB) -#if DEBUG_TMP || (process_3d_type & MODE_FORCE_3D_TB) -#endif + || (process_3d_type & MODE_FORCE_3D_FA_TB) ) - && (!(vf->type & VIDTYPE_MVC))) { + && (!(vf->type & VIDTYPE_MVC)) + && (vf->trans_fmt != TVIN_TFMT_3D_FP)) { vf->trans_fmt = TVIN_TFMT_3D_TB; vf->left_eye.start_x = 0; vf->left_eye.start_y = 0; @@ -914,22 +954,20 @@ static inline struct vframe_s *video_vf_get(void) vf->right_eye.width = vf->width; vf->right_eye.height = vf->height/2; } - + receive_frame_count++; #endif } return vf; } -static int vf_get_states(struct vframe_states *states) +static int video_vf_get_states(struct vframe_states *states) { int ret = -1; unsigned long flags; - struct vframe_provider_s *vfp; - vfp = vf_get_provider(RECEIVER_NAME); + spin_lock_irqsave(&lock, flags); - if (vfp && vfp->ops && vfp->ops->vf_states) - ret = vfp->ops->vf_states(states, vfp->op_arg); + ret = vf_get_states_by_name(RECEIVER_NAME, states); spin_unlock_irqrestore(&lock, flags); return ret; } @@ -937,7 +975,8 @@ static int vf_get_states(struct vframe_states *states) static inline void video_vf_put(struct vframe_s *vf) { struct vframe_provider_s *vfp = vf_get_provider(RECEIVER_NAME); - if (vfp && atomic_dec_and_test(&vf->use_cnt)) { + + if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) { vf_put(vf, RECEIVER_NAME); #if DEBUG_TMP if (is_dolby_vision_enable()) @@ -956,7 +995,39 @@ int ext_get_cur_video_frame(struct vframe_s **vf, int *canvas_index) *vf = cur_dispbuf; return 0; } -#ifdef CONFIG_AM_VIDEOCAPTURE +static void dump_vframe_status(const char *name) +{ + int ret = 0; + struct vframe_states states; + struct vframe_provider_s *vfp; + + vfp = vf_get_provider_by_name(name); + if (vfp && vfp->ops && vfp->ops->vf_states) + ret = vfp->ops->vf_states(&states, vfp->op_arg); + + if (ret == 0) { + ret += pr_info("%s_pool_size=%d\n", + name, states.vf_pool_size); + ret += pr_info("%s buf_free_num=%d\n", + name, states.buf_free_num); + ret += pr_info("%s buf_avail_num=%d\n", + name, states.buf_avail_num); + } else { + ret += pr_info("%s vframe no states\n", name); + } +} + +static void dump_vdin_reg(void) +{ + unsigned int reg001, reg002; + + reg001 = READ_VCBUS_REG(0x1204); + reg002 = READ_VCBUS_REG(0x1205); + pr_info("VDIN_LCNT_STATUS:0x%x,VDIN_COM_STATUS0:0x%x\n", + reg001, reg002); +} + +#ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE int ext_put_video_frame(struct vframe_s *vf) { @@ -965,8 +1036,8 @@ int ext_put_video_frame(struct vframe_s *vf) video_vf_put(vf); return 0; } -#if DEBUG_TMP -int is_need_framepacking_output(void) + +static int is_need_framepacking_output(void) { int ret = 0; @@ -976,7 +1047,6 @@ int is_need_framepacking_output(void) } return ret; } -#endif int ext_register_end_frame_callback(struct amvideocap_req *req) { @@ -993,6 +1063,7 @@ int ext_frame_capture_poll(int endflags) int index; int ret; struct amvideocap_req *req = capture_frame_req; + ret = ext_get_cur_video_frame(&vf, &index); if (!ret) { req->callback(req->data, vf, index); @@ -1139,6 +1210,7 @@ static void vpp_settings_v(struct vpp_frame_par_s *framePtr) u32 v_phase; u32 v_skip_flag = 0; int x, y, w, h; + r = framePtr->VPP_vsc_endp - framePtr->VPP_vsc_startp; afbc_enble_flag = 0; if (is_meson_gxbb_cpu()) @@ -1224,8 +1296,7 @@ static void vpp_settings_v(struct vpp_frame_par_s *framePtr) VPP_VD1_END_BIT)); } - if (/*is_need_framepacking_output()*/0) { -#if DEBUG_TMP + if (is_need_framepacking_output()) { VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END + cur_dev->vpp_off, (((((framePtr->VPP_vd_end_lines_ - @@ -1233,7 +1304,6 @@ static void vpp_settings_v(struct vpp_frame_par_s *framePtr) VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | (((framePtr->VPP_vd_end_lines_) & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); -#endif } else { VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END + cur_dev->vpp_off, @@ -1265,8 +1335,7 @@ static void vpp_settings_v(struct vpp_frame_par_s *framePtr) VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); } - if (/*is_need_framepacking_output()*/0) { -#if DEBUG_TMP + if (is_need_framepacking_output()) { VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END + cur_dev->vpp_off, (((((framePtr->VPP_vd_end_lines_ - @@ -1274,7 +1343,6 @@ static void vpp_settings_v(struct vpp_frame_par_s *framePtr) VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | (((framePtr->VPP_vd_end_lines_) & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); -#endif } else { VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END + cur_dev->vpp_off, @@ -1327,6 +1395,9 @@ static void zoom_get_horz_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls, u32 *le, u32 *rs, u32 *re) { u32 crop_sx, crop_ex, crop_sy, crop_ey; + + if (!vf) + return; vpp_get_video_source_crop(&crop_sy, &crop_sx, &crop_ey, &crop_ex); switch (vpp_3d_mode) { @@ -1367,14 +1438,13 @@ static void zoom_get_horz_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls, } break; } - - return; } static void zoom_get_vert_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls, u32 *le, u32 *rs, u32 *re) { u32 crop_sx, crop_ex, crop_sy, crop_ey, height; + vpp_get_video_source_crop(&crop_sy, &crop_sx, &crop_ey, &crop_ex); if (vf->type & VIDTYPE_INTERLACE) @@ -1487,15 +1557,15 @@ static void zoom_get_vert_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls, *le = *re = zoom_end_y_lines; break; } - - return; } #endif static void zoom_display_horz(int hscale) { u32 ls, le, rs, re; +#ifdef TV_REVERSE int content_w, content_l, content_r; +#endif #ifdef TV_3D_FUNCTION_OPEN if (process_3d_type & MODE_3D_ENABLE) { zoom_get_horz_pos(cur_dispbuf, cur_frame_par->vpp_3d_mode, &ls, @@ -1533,6 +1603,7 @@ static void zoom_display_horz(int hscale) if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { int l_aligned; int r_aligned; + int h_skip = cur_frame_par->hscale_skip_count + 1; if ((zoom_start_x_lines > 0) || (zoom_end_x_lines < ori_end_x_lines)) { l_aligned = round_down(ori_start_x_lines, 32); @@ -1542,8 +1613,8 @@ static void zoom_display_horz(int hscale) r_aligned = round_up(zoom_end_x_lines + 1, 32); } VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_W, - ((r_aligned - l_aligned) << 16) | - (r_aligned / 2 - l_aligned / 2)); + (((r_aligned - l_aligned) / h_skip) << 16) | + ((r_aligned / 2 - l_aligned / 2) / h_skip)); VSYNC_WR_MPEG_REG(AFBC_MIF_HOR_SCOPE, ((l_aligned / 32) << 16) | @@ -1552,7 +1623,7 @@ static void zoom_display_horz(int hscale) if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { VSYNC_WR_MPEG_REG(AFBC_SIZE_OUT, (VSYNC_RD_MPEG_REG(AFBC_SIZE_OUT) & 0xffff) | - ((r_aligned - l_aligned) << 16)); + (((r_aligned - l_aligned) / h_skip) << 16)); } #ifdef TV_REVERSE if (reverse) { @@ -1601,8 +1672,9 @@ static void zoom_display_horz(int hscale) static void vd2_zoom_display_horz(int hscale) { u32 ls, le, rs, re; +#ifdef TV_REVERSE int content_w, content_l, content_r; - +#endif ls = rs = zoom2_start_x_lines; le = re = zoom2_end_x_lines; @@ -1666,9 +1738,9 @@ static void vd2_zoom_display_horz(int hscale) (re / 2 << VDIF_PIC_END_BIT)); VSYNC_WR_MPEG_REG(VIU_VD2_FMT_W + cur_dev->viu_off, - (((zoom2_end_x_lines - zoom2_start_x_lines + + (((le - ls + 1) >> hscale) << VD1_FMT_LUMA_WIDTH_BIT) | - (((zoom2_end_x_lines / 2 - zoom2_start_x_lines / 2 + + (((le / 2 - ls / 2 + 1) >> hscale) << VD1_FMT_CHROMA_WIDTH_BIT)); } #endif @@ -1677,6 +1749,7 @@ static void zoom_display_vert(void) { u32 ls, le, rs, re; + if (platform_type == 1) { if (process_3d_type & MODE_3D_ENABLE) { zoom_get_vert_pos(cur_dispbuf, @@ -1698,8 +1771,7 @@ static void zoom_display_vert(void) } if ((cur_dispbuf) && (cur_dispbuf->type & VIDTYPE_MVC)) { - if (/*is_need_framepacking_output()*/0) { -#if DEBUG_TMP + if (is_need_framepacking_output()) { VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_Y0, (ls << VDIF_PIC_START_BIT) | (le << VDIF_PIC_END_BIT)); @@ -1715,7 +1787,6 @@ static void zoom_display_vert(void) VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_Y0, ((rs / 2) << VDIF_PIC_START_BIT) | ((re / 2) << VDIF_PIC_END_BIT)); -#endif } else { VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_Y0 + cur_dev->viu_off, (ls * 2 << VDIF_PIC_START_BIT) | @@ -1772,10 +1843,16 @@ static void zoom_display_vert(void) if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { int t_aligned; int b_aligned; + int ori_t_aligned; + int ori_b_aligned; + int v_skip = cur_frame_par->vscale_skip_count + 1; t_aligned = round_down(zoom_start_y_lines, 4); b_aligned = round_up(zoom_end_y_lines + 1, 4); + + ori_t_aligned = round_down(ori_start_y_lines, 4); + ori_b_aligned = round_up(ori_end_y_lines + 1, 4); VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_H, - b_aligned - t_aligned); + (b_aligned - t_aligned) / 2 / v_skip); VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE, ((t_aligned / 4) << 16) | @@ -1784,15 +1861,22 @@ static void zoom_display_vert(void) VSYNC_WR_MPEG_REG(AFBC_PIXEL_VER_SCOPE, ((zoom_start_y_lines - t_aligned) << 16) | (zoom_end_y_lines - t_aligned)); + /* afbc pixel vertical output region must be + * [0, zoom_end_y_lines - zoom_start_y_lines] + */ + VSYNC_WR_MPEG_REG(AFBC_PIXEL_VER_SCOPE, + (zoom_end_y_lines - zoom_start_y_lines)); VSYNC_WR_MPEG_REG(AFBC_SIZE_IN, - (VSYNC_RD_MPEG_REG(AFBC_SIZE_IN) & 0xffff0000) | - (b_aligned - t_aligned)); + (VSYNC_RD_MPEG_REG(AFBC_SIZE_IN) + & 0xffff0000) | + (ori_b_aligned - ori_t_aligned)); if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { VSYNC_WR_MPEG_REG(AFBC_SIZE_OUT, (VSYNC_RD_MPEG_REG(AFBC_SIZE_OUT) & - 0xffff0000) | (b_aligned - t_aligned)); - } + 0xffff0000) | + ((b_aligned - t_aligned) / v_skip)); + } } } @@ -1802,8 +1886,8 @@ static void vd2_zoom_display_vert(void) u32 ls, le, rs, re; - ls = rs = zoom2_start_x_lines; - le = re = zoom2_end_x_lines; + ls = rs = zoom2_start_y_lines; + le = re = zoom2_end_y_lines; /* vd2 */ VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_Y0, @@ -1829,8 +1913,9 @@ static void vd2_zoom_display_vert(void) t_aligned = round_down(zoom2_start_y_lines, 4); b_aligned = round_up(zoom2_end_y_lines + 1, 4); + /* TODO: afbc setting only support 420 for now */ VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_H, - b_aligned - t_aligned); + (b_aligned - t_aligned) / 2); VSYNC_WR_MPEG_REG(VD2_AFBC_MIF_VER_SCOPE, ((t_aligned / 4) << 16) | @@ -1867,26 +1952,26 @@ static void judge_3d_fa_out_mode(void) /* toggle_3d_fa_frame determine*/ /*the out frame is L or R or blank */ if ((process_3d_type & MODE_3D_OUT_FA_L_FIRST)) { - if ((vsync_count == 0) % 2) + if ((vsync_count % 2) == 0) toggle_3d_fa_frame = OUT_FA_A_FRAME; else toggle_3d_fa_frame = OUT_FA_B_FRAME; } else if ((process_3d_type & MODE_3D_OUT_FA_R_FIRST)) { - if ((vsync_count == 0) % 2) + if ((vsync_count % 2) == 0) toggle_3d_fa_frame = OUT_FA_B_FRAME; else toggle_3d_fa_frame = OUT_FA_A_FRAME; } else if ((process_3d_type & MODE_3D_OUT_FA_LB_FIRST)) { - if ((vsync_count == 0) % 4) + if ((vsync_count % 4) == 0) toggle_3d_fa_frame = OUT_FA_A_FRAME; - else if ((vsync_count == 2) % 4) + else if ((vsync_count % 4) == 2) toggle_3d_fa_frame = OUT_FA_B_FRAME; else toggle_3d_fa_frame = OUT_FA_BANK_FRAME; } else if ((process_3d_type & MODE_3D_OUT_FA_RB_FIRST)) { - if ((vsync_count == 0) % 4) + if ((vsync_count % 4) == 0) toggle_3d_fa_frame = OUT_FA_B_FRAME; - else if ((vsync_count == 2) % 4) + else if ((vsync_count % 4) == 2) toggle_3d_fa_frame = OUT_FA_A_FRAME; else toggle_3d_fa_frame = OUT_FA_BANK_FRAME; @@ -1896,24 +1981,56 @@ static void judge_3d_fa_out_mode(void) } #endif -#if DEBUG_TMP + static void vframe_canvas_set(struct canvas_config_s *config, u32 planes, u32 *index) { int i; u32 *canvas_index = index; + struct canvas_config_s *cfg = config; for (i = 0; i < planes; i++, canvas_index++, cfg++) canvas_config_config(*canvas_index, cfg); } + +bool has_enhanced_layer(struct vframe_s *vf) +{ + struct provider_aux_req_s req; + + if (!vf) + return 0; + if (vf->source_type != VFRAME_SOURCE_TYPE_OTHERS) + return 0; +#if DEBUG_TMP + if (!is_dolby_vision_on()) + return 0; #endif + req.vf = vf; + req.bot_flag = 0; + req.aux_buf = NULL; + req.aux_size = 0; + req.dv_enhance_exist = 0; + vf_notify_provider_by_name("dvbldec", + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&req); + return req.dv_enhance_exist; +} u32 property_changed_true; static void vsync_toggle_frame(struct vframe_s *vf) { u32 first_picture = 0; - unsigned long flags; + unsigned long flags = 0; + bool vf_with_el = false; + + if (vf == NULL) + return; frame_count++; + toggle_count++; +#if DEBUG_TMP + if (is_dolby_vision_enable()) + vf_with_el = has_enhanced_layer(vf); +#endif ori_start_x_lines = 0; ori_end_x_lines = ((vf->type & VIDTYPE_COMPRESS) ? vf->compWidth : vf->width) - 1; @@ -1967,6 +2084,8 @@ static void vsync_toggle_frame(struct vframe_s *vf) } } else { new_frame_count++; + if (new_frame_count == 1) + first_picture = 1; #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA if (is_vsync_rdma_enable()) { #ifdef RDMA_RECYCLE_ORDERED_VFRAMES @@ -1985,6 +2104,7 @@ static void vsync_toggle_frame(struct vframe_s *vf) #endif } else { int i; + for (i = 0; i < dispbuf_to_put_num; i++) { if (dispbuf_to_put[i]) { video_vf_put( @@ -2044,17 +2164,19 @@ static void vsync_toggle_frame(struct vframe_s *vf) vf->plane_num, &disp_canvas_index[rdma_canvas_id][0]); } - if (vf->canvas1Addr != (u32)-1) { - canvas_copy(vf->canvas1Addr & 0xff, - disp_canvas_index[rdma_canvas_id][3]); - canvas_copy((vf->canvas1Addr >> 8) & 0xff, - disp_canvas_index[rdma_canvas_id][4]); - canvas_copy((vf->canvas1Addr >> 16) & 0xff, - disp_canvas_index[rdma_canvas_id][5]); - } else { - vframe_canvas_set(&vf->canvas1_config[0], - vf->plane_num, - &disp_canvas_index[rdma_canvas_id][3]); + if (!vf_with_el) { + if (vf->canvas1Addr != (u32)-1) { + canvas_copy(vf->canvas1Addr & 0xff, + disp_canvas_index[rdma_canvas_id][3]); + canvas_copy((vf->canvas1Addr >> 8) & 0xff, + disp_canvas_index[rdma_canvas_id][4]); + canvas_copy((vf->canvas1Addr >> 16) & 0xff, + disp_canvas_index[rdma_canvas_id][5]); + } else { + vframe_canvas_set(&vf->canvas1_config[0], + vf->plane_num, + &disp_canvas_index[rdma_canvas_id][3]); + } } VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off, @@ -2062,34 +2184,43 @@ static void vsync_toggle_frame(struct vframe_s *vf) if (platform_type == 0) { VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + cur_dev->viu_off, disp_canvas[rdma_canvas_id][0]); - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); + if (!vf_with_el) { + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS1 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + } } else { - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][0]); + if (!vf_with_el) + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); if (cur_frame_par && (cur_frame_par->vpp_2pic_mode == 1)) { VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + cur_dev->viu_off, disp_canvas[rdma_canvas_id][0]); - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[rdma_canvas_id][0]); + if (!vf_with_el) + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][0]); } else { VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + cur_dev->viu_off, disp_canvas[rdma_canvas_id][1]); - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); + if (!vf_with_el) + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][0]); } } if (cur_frame_par && (process_3d_type & MODE_3D_ENABLE) && (process_3d_type & MODE_3D_TO_2D_R) - && (cur_frame_par->vpp_2pic_mode == VPP_SELECT_PIC1)) { + && (cur_frame_par->vpp_2pic_mode == VPP_SELECT_PIC1) + && !vf_with_el) { VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off, disp_canvas[rdma_canvas_id][1]); VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + cur_dev->viu_off, @@ -2131,34 +2262,44 @@ static void vsync_toggle_frame(struct vframe_s *vf) canvas_copy((vf->canvas1Addr >> 16) & 0xff, disp_canvas_index[5]); if (platform_type == 0) { - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[0]); - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[0]); - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[1]); - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[1]); + VSYNC_WR_MPEG_REG( + VD1_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[0]); + VSYNC_WR_MPEG_REG( + VD1_IF0_CANVAS1 + cur_dev->viu_off, + disp_canvas[0]); + if (!vf_with_el) + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[1]); + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS1 + cur_dev->viu_off, + disp_canvas[1]); + } } else { VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off, disp_canvas[0]); - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[0]); + if (!vf_with_el) + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[0]); if (cur_frame_par && (cur_frame_par->vpp_2pic_mode == 1)) { VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + cur_dev->viu_off, disp_canvas[0]); - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[0]); + if (!vf_with_el) + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[0]); } else { VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + cur_dev->viu_off, disp_canvas[1]); - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[1]); + if (!vf_with_el) + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[1]); } /* VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS0 +*/ /*cur_dev->viu_off, disp_canvas[0]); */ @@ -2220,8 +2361,8 @@ static void vsync_toggle_frame(struct vframe_s *vf) } /* enable new config on the new frames */ - if ((first_picture) || - (cur_dispbuf->bufWidth != vf->bufWidth) || + if ((first_picture) || (cur_dispbuf && + ((cur_dispbuf->bufWidth != vf->bufWidth) || (cur_dispbuf->width != vf->width) || (cur_dispbuf->height != vf->height) || (cur_dispbuf->bitdepth != vf->bitdepth) || @@ -2232,10 +2373,10 @@ static void vsync_toggle_frame(struct vframe_s *vf) (vf->type_backup & VIDTYPE_INTERLACE)) || (cur_dispbuf->type != vf->type) #if HAS_VPU_PROT - || (cur_dispbuf->video_angle != vf->video_angle) + || cur_dispbuf && (cur_dispbuf->video_angle != vf->video_angle) || video_prot.angle_changed) { #else - ) { + ))) { #endif last_process_3d_type = process_3d_type; atomic_inc(&video_sizechange); @@ -2259,13 +2400,16 @@ static void vsync_toggle_frame(struct vframe_s *vf) if (has_vpu_prot()) { if (use_prot) { struct vframe_s tmp_vf = *vf; + video_prot.angle = vf->video_angle; if ((first_picture) || video_prot.angle_changed - || (cur_dispbuf->video_angle != + || cur_dispbuf && + (cur_dispbuf->video_angle != vf->video_angle || cur_dispbuf->width != vf->width || cur_dispbuf->height != vf->height)) { u32 angle_orientation = 0; + video_prot_init(&video_prot, &tmp_vf); angle_orientation = vf->video_angle; video_prot_set_angle(&video_prot, @@ -2405,18 +2549,31 @@ static void vsync_toggle_frame(struct vframe_s *vf) if ((vf->type & VIDTYPE_MVC) || (cur_dispbuf2 && (cur_dispbuf2->type & VIDTYPE_VD2))) EnableVideoLayer2(); + else if (cur_dispbuf2 && + !(cur_dispbuf2->type & VIDTYPE_COMPRESS)) + VD2_MEM_POWER_ON(); + else if (vf_with_el) + EnableVideoLayer2(); } } if (cur_dispbuf && (cur_dispbuf->type != vf->type)) { if ((vf->type & VIDTYPE_MVC) || (cur_dispbuf2 && (cur_dispbuf2->type & VIDTYPE_VD2))) EnableVideoLayer2(); - else - DisableVideoLayer2(); + else { + if (cur_dispbuf2 && + !(cur_dispbuf2->type & VIDTYPE_COMPRESS)) + VD2_MEM_POWER_ON(); + else if (vf_with_el) + EnableVideoLayer2(); + else + DisableVideoLayer2(); + } } cur_dispbuf = vf; if (first_picture) { frame_par_ready_to_set = 1; + first_frame_toggled = 1; #ifdef VIDEO_PTS_CHASE av_sync_flag = 0; @@ -2429,11 +2586,12 @@ static void vsync_toggle_frame(struct vframe_s *vf) static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) { u32 r; - u32 vphase, vini_phase; + u32 vphase, vini_phase, vformatter; u32 pat, loop; static const u32 vpat[] = { 0, 0x8, 0x9, 0xa, 0xb, 0xc }; u32 u, v; u32 type = vf->type, bit_mode = 0; + bool vf_with_el = false; if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { if (frame_par->nocomp) @@ -2467,25 +2625,56 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) 0x80 << (u + 10) | 0x80 << v); /* chroma formatter */ + /* TODO: afbc setting only cover 420 for now */ #ifdef TV_REVERSE if (reverse) { - VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_CTRL, - /*HFORMATTER_RRT_PIXEL0 |*/ - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_RPTLINE0_EN | - /*(0xa << VFORMATTER_INIPHASE_BIT) |*/ - (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); + if (is_meson_txlx_package_962X() + /*&& !is_dolby_vision_stb_mode()*/ + /*&& is_dolby_vision_on()*/)/*DEBUG_TMP*/ + VSYNC_WR_MPEG_REG( + AFBC_VD_CFMT_CTRL, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + else + VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_CTRL, + (is_dolby_vision_on() ? + HFORMATTER_REPEAT | + (0xc << VFORMATTER_INIPHASE_BIT) : + HFORMATTER_RRT_PIXEL0) | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); } else #endif { - VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_CTRL, - HFORMATTER_RRT_PIXEL0 | + if (is_meson_txlx_package_962X() + /*&& !is_dolby_vision_stb_mode()*/ + /*&& is_dolby_vision_on()*/)/*DEBUG_TMP*/ + VSYNC_WR_MPEG_REG( + AFBC_VD_CFMT_CTRL, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + else + VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_CTRL, + (is_dolby_vision_on() ? + HFORMATTER_REPEAT | + (0xc << VFORMATTER_INIPHASE_BIT) : + HFORMATTER_RRT_PIXEL0) | HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | - /*(0xa << VFORMATTER_INIPHASE_BIT) |*/ (0x8 << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); } @@ -2511,13 +2700,13 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } else { bit_mode = 0; } - VSYNC_WR_MPEG_REG(VD1_IF0_GEN_REG3, - ((bit_mode&0x3)<<8) | (3<<4) | 3); - VSYNC_WR_MPEG_REG(DI_IF1_GEN_REG3, - ((bit_mode&0x3)<<8) | (3<<4) | 3); - if (is_meson_txl_cpu()) - VSYNC_WR_MPEG_REG(DI_IF2_GEN_REG3, - ((bit_mode&0x3)<<8) | (3<<4) | 3); + VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG3, + (bit_mode&0x3), 8, 2); + VSYNC_WR_MPEG_REG_BITS(DI_IF1_GEN_REG3, + (bit_mode&0x3), 8, 2); + if (is_meson_txl_cpu() || is_meson_txlx_cpu()) + VSYNC_WR_MPEG_REG_BITS(DI_IF2_GEN_REG3, + (bit_mode&0x3), 8, 2); if ((VSYNC_RD_MPEG_REG(DI_POST_CTRL) & 0x100) == 0) VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0 + cur_dev->viu_off, 0, 16, 3); @@ -2556,11 +2745,16 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } } #endif +#if DEBUG_TMP + if (is_dolby_vision_enable()) + vf_with_el = has_enhanced_layer(vf); +#endif if (frame_par->hscale_skip_count) r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG; VSYNC_WR_MPEG_REG(VD1_IF0_GEN_REG + cur_dev->viu_off, r); - VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG, r); + if (!vf_with_el) + VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG, r); /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { @@ -2592,13 +2786,13 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) if (reverse) { VSYNC_WR_MPEG_REG_BITS((VD1_IF0_GEN_REG2 + cur_dev->viu_off), 0xf, 2, 4); - if (vf->type & VIDTYPE_MVC) + if ((vf->type & VIDTYPE_MVC) && (!vf_with_el)) VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 + cur_dev->viu_off), 0xf, 2, 4); } else { VSYNC_WR_MPEG_REG_BITS((VD1_IF0_GEN_REG2 + cur_dev->viu_off), 0, 2, 4); - if (vf->type & VIDTYPE_MVC) + if ((vf->type & VIDTYPE_MVC) && (!vf_with_el)) VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 + cur_dev->viu_off), 0, 2, 4); } @@ -2611,47 +2805,89 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) if (type & VIDTYPE_VIU_444) { VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_1_1); - VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, + if (!vf_with_el) + VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_1_1); } else if (type & VIDTYPE_VIU_FIELD) { vini_phase = 0xc << VFORMATTER_INIPHASE_BIT; vphase = ((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << VFORMATTER_PHASE_BIT; - if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu()) { - if ((vf->width >= 3840) && + + /*vlsi suggest only for yuv420 vformatter shold be 1*/ + if (type & VIDTYPE_VIU_NV21) + vformatter = VFORMATTER_EN; + else + vformatter = 0; + if (is_meson_txlx_package_962X() + /*&& !is_dolby_vision_stb_mode()*/ + /*&& is_dolby_vision_on()*/) {/*DEBUG_TMP*/ + VSYNC_WR_MPEG_REG( + VIU_VD1_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + ((type & VIDTYPE_VIU_422) ? + VFORMATTER_RPTLINE0_EN : + VFORMATTER_ALWAYS_RPT) | + (0 << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | + ((type & VIDTYPE_VIU_422) ? + 0 : + VFORMATTER_EN)); + pr_info("\tvd1 set fmt(dovi tv)\n"); + } else if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || + is_meson_txlx_cpu()) { + if ((vf->width >= 3840) && (vf->height >= 2160) && (type & VIDTYPE_VIU_422)) { - VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off, - HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | - VFORMATTER_RPTLINE0_EN | vini_phase | vphase); - - VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, - HFORMATTER_RRT_PIXEL0 | HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | - vini_phase | vphase); + VSYNC_WR_MPEG_REG( + VIU_VD1_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | vini_phase | vphase); + if (!vf_with_el) + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_RRT_PIXEL0 | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase); } else { - VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off, - HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | - VFORMATTER_RPTLINE0_EN | vini_phase | vphase | - VFORMATTER_EN); - - VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, - HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | - VFORMATTER_RPTLINE0_EN | vini_phase | vphase | - VFORMATTER_EN); + VSYNC_WR_MPEG_REG( + VIU_VD1_FMT_CTRL + cur_dev->viu_off, + (/*is_dolby_vision_on()*/0 ?/*DEBUG_TMP*/ + HFORMATTER_REPEAT : 0) | + HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | vini_phase | vphase | + vformatter); + if (!vf_with_el) + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase | + vformatter); } } else { - VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off, + VSYNC_WR_MPEG_REG( + VIU_VD1_FMT_CTRL + cur_dev->viu_off, + (/*is_dolby_vision_on()*/0 ?/*DEBUG_TMP*/ + HFORMATTER_REPEAT : 0) | HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | vini_phase | vphase | - VFORMATTER_EN); - - VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, - HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | - VFORMATTER_RPTLINE0_EN | vini_phase | vphase | - VFORMATTER_EN); + vformatter); + if (!vf_with_el) + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase | + vformatter); } } else if (type & VIDTYPE_MVC) { VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off, @@ -2661,23 +2897,23 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) (0xe << VFORMATTER_INIPHASE_BIT) | (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); - VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, + if (!vf_with_el) + VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | (0xa << VFORMATTER_INIPHASE_BIT) | (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); } else if ((type & VIDTYPE_INTERLACE) - && - (((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP))) { + && (((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP))) { VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | (0xe << VFORMATTER_INIPHASE_BIT) | (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); - - VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, + if (!vf_with_el) + VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | @@ -2685,15 +2921,33 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); } else { - VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off, - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_RPTLINE0_EN | - (0xa << VFORMATTER_INIPHASE_BIT) | - (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) - << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); - - VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, + if (is_meson_txlx_package_962X() + /*&& !is_dolby_vision_stb_mode()*/ + /*&& is_dolby_vision_on()*/) {/*DEBUG_TMP*/ + VSYNC_WR_MPEG_REG( + VIU_VD1_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + } else { + VSYNC_WR_MPEG_REG( + VIU_VD1_FMT_CTRL + cur_dev->viu_off, + (/*is_dolby_vision_on()*/0 ?/*DEBUG_TMP*/ + HFORMATTER_REPEAT : 0) | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xa << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); + } + if (!vf_with_el) + VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | @@ -2724,13 +2978,10 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) pat = vpat[frame_par->vscale_skip_count >> 1]; } else if (type & VIDTYPE_MVC) { loop = 0x11; - if (/*is_need_framepacking_output()*/0) { -#if DEBUG_TMP + if (is_need_framepacking_output()) { pat = 0; -#endif - } else { + } else pat = 0x80; - } } else if ((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) { loop = 0x11; pat <<= 4; @@ -2742,8 +2993,8 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) (loop << VDIF_LUMA_LOOP1_BIT) | (loop << VDIF_CHROMA_LOOP0_BIT) | (loop << VDIF_LUMA_LOOP0_BIT)); - - VSYNC_WR_MPEG_REG(VD2_IF0_RPT_LOOP, + if (!vf_with_el) + VSYNC_WR_MPEG_REG(VD2_IF0_RPT_LOOP, (loop << VDIF_CHROMA_LOOP1_BIT) | (loop << VDIF_LUMA_LOOP1_BIT) | (loop << VDIF_CHROMA_LOOP0_BIT) | @@ -2755,18 +3006,17 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA1_RPT_PAT + cur_dev->viu_off, pat); if (type & VIDTYPE_MVC) { - if (/*is_need_framepacking_output()*/0) { -#if DEBUG_TMP + if (is_need_framepacking_output()) pat = 0; -#endif - } else + else pat = 0x88; } - - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA0_RPT_PAT, pat); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA0_RPT_PAT, pat); - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA1_RPT_PAT, pat); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA1_RPT_PAT, pat); + if (!vf_with_el) { + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA0_RPT_PAT, pat); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA0_RPT_PAT, pat); + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA1_RPT_PAT, pat); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA1_RPT_PAT, pat); + } if (platform_type == 0) { /* picture 0/1 control */ @@ -2790,8 +3040,10 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) cur_dev->viu_off, 0); VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL, 0); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL, 0); + if (!vf_with_el) { + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL, 0); + } } } else { /* picture 0/1 control */ @@ -2839,39 +3091,46 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) (0x01)); /* loop pattern */ } + } else if (process_3d_type & MODE_3D_OUT_FA_MASK) { + /*FA LR/TB output , do nothing*/ } else { if (frame_par->vpp_2pic_mode & VPP_SELECT_PIC1) { VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + cur_dev->viu_off, 0); VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); + if (!vf_with_el) { + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + } } else { VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + cur_dev->viu_off, 0); VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL, 0); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL, 0); + if (!vf_with_el) { + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL, 0); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_PSEL, 0); + } } } } } -static void vd2_set_dcu(struct vframe_s *vf) +static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) { u32 r; u32 vphase, vini_phase; u32 pat, loop; static const u32 vpat[] = { 0, 0x8, 0x9, 0xa, 0xb, 0xc }; u32 u, v; - u32 type = vf->type; + u32 type = vf->type, bit_mode = 0; u32 skip_count = 0; - pr_info("set dcu for vd2\n"); + pr_info("set dcu for vd2 %p, type:0x%x\n", vf, type); if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { if (type & VIDTYPE_COMPRESS) { r = (3 << 24) | @@ -2890,6 +3149,8 @@ static void vd2_set_dcu(struct vframe_s *vf) #endif if (vf->bitdepth & BITDEPTH_SAVING_MODE) r |= (1<<28); /* mem_saving_mode */ + if (type & VIDTYPE_SCATTER) + r |= (1<<29); VSYNC_WR_MPEG_REG(VD2_AFBC_MODE, r); VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0x1700); VSYNC_WR_MPEG_REG(VD2_AFBC_CONV_CTRL, 0x100); @@ -2900,36 +3161,91 @@ static void vd2_set_dcu(struct vframe_s *vf) 0x80 << (u + 10) | 0x80 << v); /* chroma formatter */ + /* TODO: afbc setting only cover 420 for now */ #ifdef TV_REVERSE if (reverse) { - VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_CTRL, - /*HFORMATTER_RRT_PIXEL0 |*/ - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_RPTLINE0_EN | - /*(0xa << VFORMATTER_INIPHASE_BIT) |*/ - (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); - } else + if (is_meson_txlx_package_962X() + /*&& !is_dolby_vision_stb_mode()*/ + /*&& is_dolby_vision_on()*/) {/*DEBUG_TMP*/ + VSYNC_WR_MPEG_REG( + VD2_AFBC_VD_CFMT_CTRL, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + } else + VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_CTRL, + (is_dolby_vision_on() ? + HFORMATTER_REPEAT : + HFORMATTER_RRT_PIXEL0) | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (is_dolby_vision_on() ? + (0xc << VFORMATTER_INIPHASE_BIT) : 0) | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + } else { #endif - { - VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_CTRL, - HFORMATTER_RRT_PIXEL0 | + if (is_meson_txlx_package_962X() + /*&& !is_dolby_vision_stb_mode()*/ + /*&& is_dolby_vision_on()*/) {/*DEBUG_TMP*/ + VSYNC_WR_MPEG_REG( + VD2_AFBC_VD_CFMT_CTRL, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + } else + VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_CTRL, + (is_dolby_vision_on() ? + HFORMATTER_REPEAT : + HFORMATTER_RRT_PIXEL0) | HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | - /*(0xa << VFORMATTER_INIPHASE_BIT) |*/ + (is_dolby_vision_on() ? + (0xc << VFORMATTER_INIPHASE_BIT) : 0) | (0x8 << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); +#ifdef TV_REVERSE } +#endif VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL1 + cur_dev->viu_off, 1, 1, 1); return; - } else { + if ((vf->bitdepth & BITDEPTH_Y10) && + (!frame_par->nocomp)) { + if (vf->type & VIDTYPE_VIU_444) { + bit_mode = 2; + } else { + if (vf->bitdepth & FULL_PACK_422_MODE) + bit_mode = 3; + else + bit_mode = 1; + } + } else { + bit_mode = 0; + } + VSYNC_WR_MPEG_REG_BITS( + VD2_IF0_GEN_REG3, + (bit_mode&0x3), 8, 2); VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL1 + cur_dev->viu_off, 0, 1, 1); VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0); + if (type & VIDTYPE_VIU_NV21) + VSYNC_WR_MPEG_REG_BITS( + VD2_IF0_GEN_REG2, 1, 0, 1); + else + VSYNC_WR_MPEG_REG_BITS( + VD2_IF0_GEN_REG2, 0, 0, 1); } } @@ -2978,24 +3294,46 @@ static void vd2_set_dcu(struct vframe_s *vf) vphase = ((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << VFORMATTER_PHASE_BIT; - if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu()) { - if ((vf->width >= 3840) && - (vf->height >= 2160) && - (type & VIDTYPE_VIU_422)) { - - VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, - HFORMATTER_RRT_PIXEL0 | HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | - vini_phase | vphase); + if (is_meson_txlx_package_962X() + /*&& !is_dolby_vision_stb_mode()*/ + /*&& is_dolby_vision_on()*/) {/*DEBUG_TMP*/ + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + pr_info("\tvd2 set fmt(dovi tv)\n"); + } else if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || + is_meson_txlx_cpu()) { + if ((vf->width >= 3840) && + (vf->height >= 2160) && + (type & VIDTYPE_VIU_422)) { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_RRT_PIXEL0 | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | + vini_phase | vphase); } else { - VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, - HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | - VFORMATTER_RPTLINE0_EN | vini_phase | vphase | - VFORMATTER_EN); + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + (/*is_dolby_vision_on()*/0 ?/*DEBUG_TMP*/ + HFORMATTER_REPEAT : 0) | + HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase | + VFORMATTER_EN); } } else { - - VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + (/*is_dolby_vision_on()*/0 ?/*DEBUG_TMP*/ + HFORMATTER_REPEAT : 0) | HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | vini_phase | vphase | VFORMATTER_EN); @@ -3023,15 +3361,37 @@ static void vd2_set_dcu(struct vframe_s *vf) VFORMATTER_RPTLINE0_EN | (0xe << VFORMATTER_INIPHASE_BIT) | (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) - << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); + << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); } else { - VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, + if (is_meson_txlx_package_962X() + /*&& !is_dolby_vision_stb_mode()*/ + /*&& is_dolby_vision_on()*/) {/*DEBUG_TMP*/ + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + pr_info("\tvd2 set fmt(dovi tv)\n"); + } else { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + (/*is_dolby_vision_on()*/0 ?/*DEBUG_TMP*/ + HFORMATTER_REPEAT : 0) | HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | - (0xa << VFORMATTER_INIPHASE_BIT) | + (0xc << VFORMATTER_INIPHASE_BIT) | (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); + pr_info("\tvd2 set fmt(dovi:%d)\n", + /*is_dolby_vision_on()*/0);/*DEBUG_TMP*/ + } } /* LOOP/SKIP pattern */ pat = vpat[skip_count]; @@ -3079,12 +3439,20 @@ static void vd2_set_dcu(struct vframe_s *vf) /* picture 0/1 control */ if ((((type & VIDTYPE_INTERLACE) == 0) && ((type & VIDTYPE_VIU_FIELD) == 0) && - ((type & VIDTYPE_MVC) == 0))) { + ((type & VIDTYPE_MVC) == 0)) || + (next_frame_par->vpp_2pic_mode & 0x3)) { /* progressive frame in two pictures */ } else { - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL, 0); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL, 0); + if (next_frame_par->vpp_2pic_mode & VPP_SELECT_PIC1) { + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + } else { + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL, 0); + } } } } @@ -3220,6 +3588,15 @@ static inline bool vpts_expire(struct vframe_s *cur_vf, if ((freerun_mode == FREERUN_NODUR) || hdmi_in_onvideo) return true; + if (step_enable) { + if (step_flag) + return false; + if (!step_flag) { + step_flag = 1; + return true; + } + } + if ((trickmode_i == 1) || ((trickmode_fffb == 1))) { if (((atomic_read(&trickmode_framedone) == 0) || (trickmode_i == 1)) && (!to_notify_trick_wait) @@ -3251,6 +3628,7 @@ static inline bool vpts_expire(struct vframe_s *cur_vf, } /* check video PTS discontinuity */ else if ((enable_video_discontinue_report) && + (first_frame_toggled) && (abs(systime - pts) > tsync_vpts_discontinuity_margin()) && ((next_vf->flag & VFRAME_FLAG_NO_DISCONTINUE) == 0)) { /* @@ -3293,12 +3671,14 @@ static inline bool vpts_expire(struct vframe_s *cur_vf, if (vsync_pts_inc_upint && (!freerun_mode)) { struct vframe_states frame_states; u32 delayed_ms, t1, t2; + delayed_ms = calculation_stream_delayed_ms(PTS_TYPE_VIDEO, &t1, &t2); - if (vf_get_states(&frame_states) == 0) { + if (video_vf_get_states(&frame_states) == 0) { u32 pcr = timestamp_pcrscr_get(); u32 vpts = timestamp_vpts_get(); u32 diff = pcr - vpts; + if (delayed_ms > 200) { vsync_freerun++; if (pcr < next_vf->pts @@ -3375,12 +3755,12 @@ static inline bool vpts_expire(struct vframe_s *cur_vf, } else { int aud_start = (timestamp_apts_get() != -1); - if (!av_sync_flag && aud_start && (abs(scr_pts - pts) < 9000) - && ((int)(scr_pts - pts) < 0)) { - av_sync_flag = 1; - pr_info("av sync ok\n"); - } - return ((int)(scr_pts - pts)) >= 0; + if (!av_sync_flag && aud_start && (abs(scr_pts - pts) < 9000) + && ((int)(scr_pts - pts) < 0)) { + av_sync_flag = 1; + pr_info("av sync ok\n"); + } + return ((int)(scr_pts - pts)) >= 0; } #else if (smooth_sync_enable) { @@ -3502,7 +3882,50 @@ void vsync_rdma_process(void) static enum vmode_e old_vmode = VMODE_MAX; /* #endif */ static enum vmode_e new_vmode = VMODE_MAX; - +static inline bool video_vf_disp_mode_check(struct vframe_s *vf) +{ + struct provider_disp_mode_req_s req; + //int ret = -1; + req.vf = vf; + req.disp_mode = 0; + req.req_mode = 1; +#if DEBUG_TMP + if (is_dolby_vision_enable()) { + ret = vf_notify_provider_by_name("dv_vdin", + VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); + if (ret == -1) + vf_notify_provider_by_name("vdin0", + VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); + } else +#endif + vf_notify_provider_by_name("vdin0", + VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); + if (req.disp_mode == VFRAME_DISP_MODE_OK) + return false; + /*whether need to check pts??*/ + video_vf_put(vf); + return true; +} +static enum vframe_disp_mode_e video_vf_disp_mode_get(struct vframe_s *vf) +{ + struct provider_disp_mode_req_s req; + //int ret = -1; + req.vf = vf; + req.disp_mode = 0; + req.req_mode = 0; +#if DEBUG_TMP + if (is_dolby_vision_enable()) { + ret = vf_notify_provider_by_name("dv_vdin", + VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); + if (ret == -1) + vf_notify_provider_by_name("vdin0", + VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); + } else +#endif + vf_notify_provider_by_name("vdin0", + VFRAME_EVENT_RECEIVER_DISP_MODE, (void *)&req); + return req.disp_mode; +} static inline bool video_vf_dirty_put(struct vframe_s *vf) { if (!vf->frame_dirty) @@ -3538,6 +3961,173 @@ static inline bool video_vf_dirty_put(struct vframe_s *vf) return true; } + +#if DEBUG_TMP +struct vframe_s *dolby_vision_toggle_frame(struct vframe_s *vf) +{ + struct vframe_s *toggle_vf = NULL; + int width_bl, width_el; + int height_bl, height_el; + int ret = dolby_vision_update_metadata(vf); + + cur_dispbuf2 = dolby_vision_vf_peek_el(vf); + if (cur_dispbuf2) { + if (cur_dispbuf2->type & VIDTYPE_COMPRESS) { + VSYNC_WR_MPEG_REG(VD2_AFBC_HEAD_BADDR, + cur_dispbuf2->compHeadAddr>>4); + VSYNC_WR_MPEG_REG(VD2_AFBC_BODY_BADDR, + cur_dispbuf2->compBodyAddr>>4); + } else { + vframe_canvas_set(&cur_dispbuf2->canvas0_config[0], + cur_dispbuf2->plane_num, + &disp_canvas_index[rdma_canvas_id][3]); + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + } + + width_el = (cur_dispbuf2->type + & VIDTYPE_COMPRESS) ? + cur_dispbuf2->compWidth : + cur_dispbuf2->width; + if (!(cur_dispbuf2->type & VIDTYPE_VD2)) { + width_bl = (vf->type + & VIDTYPE_COMPRESS) ? + vf->compWidth : + vf->width; + if (width_el >= width_bl) + width_el = width_bl; + else if (width_el != width_bl / 2) + width_el = width_bl / 2; + } + ori2_start_x_lines = 0; + ori2_end_x_lines = + width_el - 1; + + height_el = (cur_dispbuf2->type + & VIDTYPE_COMPRESS) ? + cur_dispbuf2->compHeight : + cur_dispbuf2->height; + if (!(cur_dispbuf2->type & VIDTYPE_VD2)) { + height_bl = (vf->type + & VIDTYPE_COMPRESS) ? + vf->compHeight : + vf->height; + if (height_el >= height_bl) + height_el = height_bl; + else if (height_el != height_bl / 2) + height_el = height_bl / 2; + } + ori2_start_y_lines = 0; + ori2_end_y_lines = + height_el - 1; + } + if (ret == 0) { + /* setting generated for this frame */ + /* or DOVI in bypass mode */ + toggle_vf = vf; + dolby_vision_set_toggle_flag(1); + } else { + /* fail generating setting for this frame */ + toggle_vf = NULL; + dolby_vision_set_toggle_flag(0); + } + return toggle_vf; +} +#endif + +#if DEBUG_TMP +static int dolby_vision_need_wait(void) +{ + struct vframe_s *vf; + + vf = video_vf_peek(); + if (!vf || (dolby_vision_wait_metadata(vf) == 1)) + return 1; + return 0; +} +#endif + +/* patch for 4k2k bandwidth issue, skiw mali and vpu mif */ +static void dmc_adjust_for_mali_vpu(unsigned int width, unsigned int height) +{ + if (toggle_count == last_toggle_count) + toggle_same_count++; + else { + last_toggle_count = toggle_count; + toggle_same_count = 0; + } + /*avoid 3840x2160 crop*/ + if ((width >= 2000) && (height >= 1400) && + (dmc_config_state != 1) && (toggle_same_count < 30)) { + if (0) {/* if (is_dolby_vision_enable()) { */ + /* vpu dmc */ + WRITE_DMCREG( + DMC_AM0_CHAN_CTRL, + 0x85f403f4); + WRITE_DMCREG( + DMC_AM1_CHAN_CTRL, + 0x85f403f4); + WRITE_DMCREG( + DMC_AM2_CHAN_CTRL, + 0x85f403f4); + + /* mali dmc */ + WRITE_DMCREG( + DMC_AXI1_CHAN_CTRL, + 0xff10ff4); + WRITE_DMCREG( + DMC_AXI2_CHAN_CTRL, + 0xff10ff4); + WRITE_DMCREG( + DMC_AXI1_HOLD_CTRL, + 0x08040804); + WRITE_DMCREG( + DMC_AXI2_HOLD_CTRL, + 0x08040804); + } else { + /* mali dmc */ + WRITE_DMCREG( + DMC_AXI1_HOLD_CTRL, + 0x10080804); + WRITE_DMCREG( + DMC_AXI2_HOLD_CTRL, + 0x10080804); + } + dmc_config_state = 1; + } else if (((toggle_same_count >= 30) || + ((width < 2000) && (height < 1400))) && + (dmc_config_state != 2)) { + /* vpu dmc */ + WRITE_DMCREG( + DMC_AM0_CHAN_CTRL, + 0x8FF003C4); + WRITE_DMCREG( + DMC_AM1_CHAN_CTRL, + 0x8FF003C4); + WRITE_DMCREG( + DMC_AM2_CHAN_CTRL, + 0x8FF003C4); + + /* mali dmc */ + WRITE_DMCREG( + DMC_AXI1_CHAN_CTRL, + 0x8FF00FF4); + WRITE_DMCREG( + DMC_AXI2_CHAN_CTRL, + 0x8FF00FF4); + WRITE_DMCREG( + DMC_AXI1_HOLD_CTRL, + 0x18101810); + WRITE_DMCREG( + DMC_AXI2_HOLD_CTRL, + 0x18101810); + toggle_same_count = 30; + dmc_config_state = 2; + } +} + #ifdef FIQ_VSYNC void vsync_fisr(void) #else @@ -3565,6 +4155,7 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) int ret; #endif int video1_off_req = 0; + struct vframe_s *cur_dispbuf_back = cur_dispbuf; if (debug_flag & DEBUG_FLAG_VSYNC_DONONE) return IRQ_HANDLED; @@ -3572,6 +4163,7 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) #ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 const char *dev_id_s = (const char *)dev_id; int dev_id_len = strlen(dev_id_s); + if (cur_dev == &video_dev[1]) { if (cur_dev_idx == 0) { cur_dev = &video_dev[0]; @@ -3636,6 +4228,18 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) if (enc_line > vsync_enter_line_max) vsync_enter_line_max = enc_line; + if (is_meson_txlx_cpu() && dmc_adjust) { + if (vf) + dmc_adjust_for_mali_vpu( + vf->width, vf->height); + else if (cur_dispbuf) + dmc_adjust_for_mali_vpu( + cur_dispbuf->width, + cur_dispbuf->height); + else + dmc_adjust_for_mali_vpu( + 0, 0); + } #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA vsync_rdma_config_pre(); @@ -3655,10 +4259,15 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) enable_rdma_log_count--; } #endif - +#if DEBUG_TMP + /* check video frame before VECM process */ + if (is_dolby_vision_enable() && vf) + dolby_vision_check_hdr10(vf); #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) amvecm_on_vs(vf); #endif +#endif + #ifdef CONFIG_TVIN_VDIN /* patch for m8 4k2k wifidisplay bandwidth bottleneck */ if (get_cpu_type() == MESON_CPU_MAJOR_ID_M8) { @@ -3701,12 +4310,16 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) if (omx_secret_mode == true) { u32 system_time = timestamp_pcrscr_get(); int diff = system_time - omx_pts; + if ((diff - omx_pts_interval_upper) > 0 || (diff - omx_pts_interval_lower) < 0) { timestamp_pcrscr_enable(1); /*pr_info("system_time=%d, omx_pts=%d, diff=%d\n",*/ /*system_time, omx_pts, diff);*/ - timestamp_pcrscr_set(omx_pts); + /*add greatest common divisor of duration*/ + /*1500(60fps) 3000(30fps) 3750(24fps) for some video*/ + /*that pts is not evenly*/ + timestamp_pcrscr_set(omx_pts + DURATION_GCD); } } else omx_pts = 0; @@ -3801,7 +4414,8 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) } else if ((cur_dispbuf == &vf_local) && (video_property_changed)) { if (!(blackout | force_blackout)) { - if ((READ_VCBUS_REG(DI_IF1_GEN_REG) & + if (cur_dispbuf && + (VSYNC_RD_MPEG_REG(DI_IF1_GEN_REG) & 0x1) == 0) { /* setting video display*/ /*property in unregister mode */ @@ -3834,8 +4448,21 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) if ((!vf) && cur_dispbuf && (video_property_changed)) vsync_toggle_frame(cur_dispbuf); - if (!vf) + /*debug info for skip & repeate vframe case*/ + if (!vf) { underflow++; + if (video_dbg_vf&(1<<0)) + dump_vframe_status("vdin0"); + if (video_dbg_vf&(1<<1)) + dump_vframe_status("deinterlace"); + if (video_dbg_vf&(1<<2)) + dump_vframe_status("amlvideo2"); + if (video_dbg_vf&(1<<3)) + dump_vframe_status("ppmgr"); + if (video_dbg_vf&(1<<4)) + dump_vdin_reg(); + } + video_get_vf_cnt = 0; if (platform_type == 1) { /* toggle_3d_fa_frame*/ /* determine the out frame is L or R or blank */ @@ -3854,22 +4481,39 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) "skipped\n"); #if DEBUG_TMP - if (is_dolby_vision_enable()) { - ret = dolby_vision_wait_metadata(vf); - if (ret == 2) - break; - } -#endif #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) refresh_on_vs(vf); #endif + if (is_dolby_vision_enable() + && dolby_vision_need_wait()) + break; +#endif + /* + *two special case: + *case1:4k display case,input buffer not enough & + * quickly for display + *case2:input buffer all not OK + */ + if (vf && hdmiin_frame_check && + (vf->source_type == VFRAME_SOURCE_TYPE_HDMI) && + (video_vf_disp_mode_get(vf) != + VFRAME_DISP_MODE_OK) && + (hdmiin_frame_check_cnt++ < 10)) + break; + + hdmiin_frame_check_cnt = 0; + vf = video_vf_get(); if (!vf) break; if (video_vf_dirty_put(vf)) break; + if (vf && hdmiin_frame_check && (vf->source_type == + VFRAME_SOURCE_TYPE_HDMI) && + video_vf_disp_mode_check(vf)) + break; force_blackout = 0; if ((platform_type == 1) || (platform_type == 0)) { @@ -3885,43 +4529,9 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) } vsync_toggle_frame(vf); #if DEBUG_TMP - if (is_dolby_vision_enable()) { - ret = dolby_vision_update_metadata(vf); - cur_dispbuf2 = dolby_vision_vf_peek_el(vf); - if (cur_dispbuf2) { - VSYNC_WR_MPEG_REG(VD2_AFBC_HEAD_BADDR, - cur_dispbuf2->compHeadAddr>>4); - VSYNC_WR_MPEG_REG(VD2_AFBC_BODY_BADDR, - cur_dispbuf2->compBodyAddr>>4); - ori2_start_x_lines = 0; - ori2_end_x_lines = - ((cur_dispbuf2->type - & VIDTYPE_COMPRESS) ? - cur_dispbuf2->compWidth : - cur_dispbuf2->width) - 1; - ori2_start_y_lines = 0; - ori2_end_y_lines = - ((cur_dispbuf2->type - & VIDTYPE_COMPRESS) ? - cur_dispbuf2->compHeight : - cur_dispbuf2->height) - 1; - } - if (ret == 0) { - toggle_vf = vf; - dolby_vision_set_toggle_flag(1); - } else if (ret == -1) { - /* not enough meta, wait */ - toggle_vf = NULL; - dolby_vision_set_toggle_flag(0); - break; - } else if (ret == -2) { - /* no meta, mostly SDR */ - toggle_vf = NULL; - dolby_vision_set_toggle_flag(1); - dolby_vision_process(toggle_vf); - break; - } - } else + if (is_dolby_vision_enable()) + toggle_vf = dolby_vision_toggle_frame(vf); + else #endif cur_dispbuf2 = NULL; @@ -3947,20 +4557,27 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) vf = video_vf_peek(); if (!vf) next_peek_underflow++; - +#if DEBUG_TMP + if (for_dolby_vision_certification() + && toggle_vf) + break; +#endif if (debug_flag & DEBUG_FLAG_TOGGLE_FRAME_PER_VSYNC) break; + video_get_vf_cnt++; + if (video_get_vf_cnt >= 2) + video_drop_vf_cnt++; } else { /* check if current frame's duration has expired, - *in this example - * it compares current frame display duration - * with 1/1/1/1.5 frame duration - * every 4 frames there will be one frame play - * longer than usual. - * you can adjust this array for any slow sync - * control as you want. - * The playback can be smoother than previous method. - */ + *in this example + * it compares current frame display duration + * with 1/1/1/1.5 frame duration + * every 4 frames there will be one frame play + * longer than usual. + * you can adjust this array for any slow sync + * control as you want. + * The playback can be smoother than previous method. + */ if (slowsync_repeat_enable) { if (duration_expire (cur_dispbuf, vf, @@ -3973,10 +4590,22 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) "sys.time = 0x%x, video time = 0x%x\n", timestamp_pcrscr_get(), timestamp_vpts_get()); +#if DEBUG_TMP + if (is_dolby_vision_enable() + && dolby_vision_need_wait()) + break; +#endif vf = video_vf_get(); if (!vf) break; vsync_toggle_frame(vf); +#if DEBUG_TMP + if (is_dolby_vision_enable()) + toggle_vf = + dolby_vision_toggle_frame(vf); + else +#endif + cur_dispbuf2 = NULL; frame_repeat_count = 0; vf = video_vf_peek(); @@ -4013,10 +4642,6 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) toggle_cnt++; #endif } -#if DEBUG_TMP - if (toggle_vf && is_dolby_vision_enable()) - dolby_vision_process(toggle_vf); -#endif #ifdef INTERLACE_FIELD_MATCH_PROCESS if (interlace_field_type_need_match(vout_type, vf)) { @@ -4030,7 +4655,19 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) field_matching_count = 0; #endif - SET_FILTER: +SET_FILTER: +#if DEBUG_TMP + if (is_dolby_vision_enable()) { + u32 skip_mode = 0; + + if (cur_frame_par) + skip_mode = + (cur_frame_par->hscale_skip_count << 16) + | cur_frame_par->vscale_skip_count; + dolby_vision_process(toggle_vf, skip_mode); + dolby_vision_update_setting(); + } +#endif /* filter setting management */ if ((frame_par_ready_to_set) || (frame_par_force_to_set)) { cur_frame_par = next_frame_par; @@ -4042,19 +4679,26 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) frame_par_force_to_set = 1; } } + if (cur_dispbuf_back != cur_dispbuf) { + display_frame_count++; + drop_frame_count = receive_frame_count - display_frame_count; + } if (cur_dispbuf) { struct f2v_vphase_s *vphase; u32 vin_type = cur_dispbuf->type & VIDTYPE_TYPEMASK; { int need_afbc = (cur_dispbuf->type & VIDTYPE_COMPRESS); - int afbc_need_reset = video_enabled && need_afbc && - (!(READ_VCBUS_REG(AFBC_ENABLE) & 0x100)); + int afbc_need_reset = + video_enabled && + need_afbc && + (!(READ_VCBUS_REG(AFBC_ENABLE) & 0x100)); /*video on && afbc is off && is compress frame.*/ - if (frame_par_ready_to_set || afbc_need_reset) + if (frame_par_ready_to_set || afbc_need_reset) { viu_set_dcu(cur_frame_par, cur_dispbuf); - if ((cur_dispbuf2) - && (frame_par_ready_to_set || afbc_need_reset)) - vd2_set_dcu(cur_dispbuf2); + if (cur_dispbuf2) + vd2_set_dcu(cur_frame_par, + cur_dispbuf2); + } } { #if 0 @@ -4075,7 +4719,8 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) if (platform_type == 1) { if ((cur_frame_par->hscale_skip_count) - && (cur_dispbuf->type & VIDTYPE_VIU_FIELD)) { + && cur_dispbuf && + (cur_dispbuf->type & VIDTYPE_VIU_FIELD)) { VSYNC_WR_MPEG_REG_BITS(VIU_VD1_FMT_CTRL + cur_dev->viu_off, 0, 20, 1); /* HFORMATTER_EN */ @@ -4148,30 +4793,30 @@ static irqreturn_t vsync_isr(int irq, void *dev_id) cur_dev->viu_off, 0x4000000); } /* -VSYNC_WR_MPEG_REG_BITS(VPP_MISC + -cur_dev->vpp_off,1,15,1);//VPP_VD2_PREBLEND enable -//VSYNC_WR_MPEG_REG_BITS(VPP_MISC + -cur_dev->vpp_off,1,11,1);//VPP_VD2_POSTBLEND enable -VSYNC_WR_MPEG_REG_BITS(VPP_MISC + -cur_dev->vpp_off,1,6,1);//PREBLEND enable must be set! -VSYNC_WR_MPEG_REG_BITS(VPP_MISC + -cur_dev->vpp_off,0x1ff, -VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set -*/ + *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + *cur_dev->vpp_off,1,15,1);//VPP_VD2_PREBLEND enable + *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + *cur_dev->vpp_off,1,11,1);//VPP_VD2_POSTBLEND enable + *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + *cur_dev->vpp_off,1,6,1);//PREBLEND enable must be set! + *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + *cur_dev->vpp_off,0x1ff, + *VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set + */ } /* -else{ -VSYNC_WR_MPEG_REG_BITS(VPP_MISC + -cur_dev->vpp_off,0,15,1);//VPP_VD2_PREBLEND enable -//VSYNC_WR_MPEG_REG_BITS(VPP_MISC + -cur_dev->vpp_off,1,11,1);//VPP_VD2_POSTBLEND enable -VSYNC_WR_MPEG_REG_BITS(VPP_MISC + -cur_dev->vpp_off,0,6,1);//PREBLEND enable -VSYNC_WR_MPEG_REG_BITS(VPP_MISC + -cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set -} -*/ + *else{ + *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + *cur_dev->vpp_off,0,15,1);//VPP_VD2_PREBLEND enable + *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + *cur_dev->vpp_off,1,11,1);//VPP_VD2_POSTBLEND enable + *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + *cur_dev->vpp_off,0,6,1);//PREBLEND enable + *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + *cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set + *} + */ } /* vertical phase */ vphase = @@ -4257,15 +4902,12 @@ cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set zoom_end_y = cur_frame_par->VPP_vd_end_lines_; } else { - //if (is_need_framepacking_output()) { - if (0) { -#if DEBUG_TMP + if (is_need_framepacking_output()) { zoom_start_y = cur_frame_par->VPP_vd_start_lines_ >> 1; zoom_end_y = ((cur_frame_par->VPP_vd_end_lines_ - framepacking_blank + 1) >> 1) - 1; -#endif } else { zoom_start_y = cur_frame_par->VPP_vd_start_lines_ >> 1; @@ -4283,7 +4925,6 @@ cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set zoom_start_y_lines = zoom_start_y; zoom_end_y_lines = zoom_end_y; zoom_display_vert(); - #if DEBUG_TMP if (is_dolby_vision_enable() && cur_dispbuf2) { zoom2_start_x_lines = ori2_start_x_lines; @@ -4308,27 +4949,35 @@ cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set cur_frame_par->spsc1_w_in, cur_frame_par->spsc1_h_in, cur_frame_par->supsc1_hori_ratio, - cur_frame_par->supsc1_vert_ratio); + cur_frame_par->supsc1_vert_ratio, + cur_frame_par->vpp_postblend_out_width, + cur_frame_par->vpp_postblend_out_height); /* vpp filters */ /* SET_MPEG_REG_MASK(VPP_SC_MISC + cur_dev->vpp_off, */ /* VPP_SC_TOP_EN | VPP_SC_VERT_EN | VPP_SC_HORZ_EN); */ - VSYNC_WR_MPEG_REG(VPP_SC_MISC + cur_dev->vpp_off, + if (/*for_dolby_vision_certification()*/0) {/*DEBUG_TMP*/ + /* turn off PPS for Dolby Vision certification */ + VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off, + 0, VPP_SC_TOP_EN_BIT, VPP_SC_TOP_EN_WID); + } else { + VSYNC_WR_MPEG_REG(VPP_SC_MISC + cur_dev->vpp_off, READ_VCBUS_REG(VPP_SC_MISC + cur_dev->vpp_off) | VPP_SC_TOP_EN | VPP_SC_VERT_EN | VPP_SC_HORZ_EN); - /* pps pre hsc&vsc en */ - VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off, - vpp_filter->vpp_pre_hsc_en, - VPP_SC_PREHORZ_EN_BIT, 1); - VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off, - vpp_filter->vpp_pre_vsc_en, - VPP_SC_PREVERT_EN_BIT, 1); - VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off, - vpp_filter->vpp_pre_vsc_en, - VPP_LINE_BUFFER_EN_BIT, 1); + /* pps pre hsc&vsc en */ + VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off, + vpp_filter->vpp_pre_hsc_en, + VPP_SC_PREHORZ_EN_BIT, 1); + VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off, + vpp_filter->vpp_pre_vsc_en, + VPP_SC_PREVERT_EN_BIT, 1); + VSYNC_WR_MPEG_REG_BITS(VPP_SC_MISC + cur_dev->vpp_off, + vpp_filter->vpp_pre_vsc_en, + VPP_LINE_BUFFER_EN_BIT, 1); + } /* for bypass pps debug */ if ((vpp_filter->vpp_hsc_start_phase_step == 0x1000000) && (vpp_filter->vpp_vsc_start_phase_step == 0x1000000) && @@ -4395,6 +5044,7 @@ cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set /* vertical chroma filter settings */ if (vpp_filter->vpp_vert_chroma_filter_en) { const u32 *pCoeff = vpp_filter->vpp_vert_chroma_coeff; + VSYNC_WR_MPEG_REG( VPP_SCALE_COEF_IDX + cur_dev->vpp_off, VPP_COEF_VERT_CHROMA|VPP_COEF_SEP_EN); @@ -4417,19 +5067,16 @@ cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set (cur_frame_par->vscale_skip_count + 1); if (cur_dispbuf->type & VIDTYPE_MVC) cur_frame_par->VPP_pic_in_height_ *= 2; - if (/*is_need_framepacking_output()*/0) { -#if DEBUG_TMP + if (is_need_framepacking_output()) { cur_frame_par->VPP_pic_in_height_ += framepacking_blank; -#endif } cur_frame_par->VPP_line_in_length_ = (zoom_end_x_lines - zoom_start_x_lines + 1) / (cur_frame_par->hscale_skip_count + 1); } } - if ((is_meson_gxtvbb_cpu() || is_meson_txl_cpu()) && - cur_dispbuf) { + if (super_scaler && cur_dispbuf) { if (cur_dispbuf->type & VIDTYPE_INTERLACE) { cur_frame_par->VPP_pic_in_height_ = (zoom_end_y_lines - zoom_start_y_lines + 1) << @@ -4444,11 +5091,9 @@ cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set cur_frame_par->supsc0_vert_ratio; if (cur_dispbuf->type & VIDTYPE_MVC) cur_frame_par->VPP_pic_in_height_ *= 2; - if (/*is_need_framepacking_output()*/0) { -#if DEBUG_TMP + if (is_need_framepacking_output()) { cur_frame_par->VPP_pic_in_height_ += framepacking_blank; -#endif } cur_frame_par->VPP_line_in_length_ = ((zoom_end_x_lines - zoom_start_x_lines + 1) / @@ -4518,6 +5163,12 @@ cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set /* VPP one time settings */ wait_sync = 0; + if (vinfo && VSYNC_RD_MPEG_REG( + VPP_POSTBLEND_H_SIZE + cur_dev->vpp_off) + != vinfo->width) + VSYNC_WR_MPEG_REG( + VPP_POSTBLEND_H_SIZE + cur_dev->vpp_off, + vinfo->width); if (cur_dispbuf && cur_dispbuf->process_fun) { /* for new deinterlace driver */ #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA @@ -4538,7 +5189,10 @@ cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set vpp_misc_save = READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off); vpp_misc_set = vpp_misc_save; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM - vpp_misc_set |= VPP_CM_ENABLE; + if (!0/*is_dolby_vision_on()*/)/*DEBUG_TMP*/ + vpp_misc_set |= VPP_CM_ENABLE; + else + vpp_misc_set &= ~VPP_CM_ENABLE; #endif if (update_osd_vpp_misc) { vpp_misc_set &= ~osd_vpp_misc_mask; @@ -4550,10 +5204,16 @@ cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set } if ((video_enabled == 1) && ((vpp_misc_save & VPP_VD1_POSTBLEND) == 0) && (video_onoff_state == VIDEO_ENABLE_STATE_IDLE)) { - SET_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, - VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND - | VPP_POSTBLEND_EN); - pr_info("VPP_VD1_POSTBLEND register rdma write fail!"); + /* + *SET_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, + * VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND + * | VPP_POSTBLEND_EN); + *pr_info("VPP_VD1_POSTBLEND register rdma write fail!"); + */ + vpp_misc_set |= + VPP_VD1_PREBLEND | + VPP_VD1_POSTBLEND | + VPP_POSTBLEND_EN; } if ((video_enabled == 1) && cur_frame_par && (cur_dispbuf != &vf_local) && (first_set == 0) @@ -4579,9 +5239,9 @@ cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set if (video_onoff_state == VIDEO_ENABLE_STATE_ON_REQ) { /* - * the video layer is enabled one vsync later,assumming - * all registers are ready from RDMA. - */ + * the video layer is enabled one vsync later,assumming + * all registers are ready from RDMA. + */ video_onoff_state = VIDEO_ENABLE_STATE_ON_PENDING; } else if (video_onoff_state == VIDEO_ENABLE_STATE_ON_PENDING) { @@ -4642,6 +5302,16 @@ cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set spin_unlock_irqrestore(&video_onoff_lock, flags); } + if (video_global_output == 0) { + video_enabled = 0; + vpp_misc_set &= ~(VPP_VD1_PREBLEND | + VPP_VD2_PREBLEND | + VPP_VD2_POSTBLEND | + VPP_VD1_POSTBLEND); + } else { + video_enabled = video_status_saved; + } + if (likely(video2_onoff_state != VIDEO_ENABLE_STATE_IDLE)) { /* state change for video layer2 enable/disable */ @@ -4661,8 +5331,10 @@ cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set VPP_PREBLEND_EN | VPP_VD2_PREBLEND | (0x1ff << VPP_VD2_ALPHA_BIT)); #else - vpp_misc_set |= VPP_PREBLEND_EN | VPP_VD2_PREBLEND | - (0x1ff << VPP_VD2_ALPHA_BIT); + if (!0/*is_dolby_vision_on()*/) /*DEBUG_TMP*/ + vpp_misc_set |= + VPP_PREBLEND_EN | VPP_VD2_PREBLEND; + vpp_misc_set |= (0x1ff << VPP_VD2_ALPHA_BIT); #endif video2_onoff_state = VIDEO_ENABLE_STATE_IDLE; @@ -4702,8 +5374,18 @@ cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set spin_unlock_irqrestore(&video2_onoff_lock, flags); } +#if 0 //DEBUG_TMP + if (is_dolby_vision_on() + && (dolby_first_delay > 0) + && (vpp_misc_set & VPP_VD1_POSTBLEND)) { + vpp_misc_set &= + ~(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND); + dolby_first_delay--; + } +#endif if (vpp_misc_save != vpp_misc_set) { - VSYNC_WR_MPEG_REG(VPP_MISC + cur_dev->vpp_off, + VSYNC_WR_MPEG_REG( + VPP_MISC + cur_dev->vpp_off, vpp_misc_set); } /*vpp_misc_set maybe have same,but need off.*/ @@ -4816,6 +5498,7 @@ static void vsync_fiq_down(void) static void vsync2_fiq_up(void) { int r; + r = request_irq(INT_VIU2_VSYNC, &vsync_isr, IRQF_SHARED, "vsync", (void *)video_dev_id2); } @@ -4873,6 +5556,7 @@ static void video_vf_unreg_provider(void) ulong flags; new_frame_count = 0; + first_frame_toggled = 0; atomic_set(&video_unreg_flag, 1); spin_lock_irqsave(&lock, flags); @@ -4890,7 +5574,10 @@ static void video_vf_unreg_provider(void) cur_dispbuf = &vf_local; cur_dispbuf->video_angle = 0; } - +#if DEBUG_TMP + if (is_dolby_vision_enable()) + cur_dispbuf2 = NULL; +#endif if (trickmode_fffb) { atomic_set(&trickmode_framedone, 0); to_notify_trick_wait = false; @@ -5004,8 +5691,6 @@ static int get_display_info(void *data) static int video_receiver_event_fun(int type, void *data, void *private_data) { - char *configured[2]; - char framerate[20] = {0}; #ifdef CONFIG_AM_VIDEO2 char *provider_name; #endif @@ -5014,12 +5699,18 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) #ifdef CONFIG_AM_VIDEO2 set_clone_frame_rate(android_clone_rate, 200); #endif + drop_frame_count = 0; + receive_frame_count = 0; + display_frame_count = 0; } else if (type == VFRAME_EVENT_PROVIDER_RESET) { video_vf_light_unreg_provider(); } else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) video_vf_light_unreg_provider(); else if (type == VFRAME_EVENT_PROVIDER_REG) { enable_video_discontinue_report = 1; + drop_frame_count = 0; + receive_frame_count = 0; + display_frame_count = 0; #ifdef CONFIG_AM_VIDEO2 provider_name = (char *)data; if (strncmp(provider_name, "decoder", 7) == 0 @@ -5049,31 +5740,13 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) } } else if (type == VFRAME_EVENT_PROVIDER_FR_HINT) { #ifdef CONFIG_AM_VOUT - if (data != NULL) { - if (video_seek_flag == 0) { - /*set_vframe_rate_hint((unsigned long)(data));*/ - sprintf(framerate, "FRAME_RATE_HINT=%lu", - (unsigned long)data); - configured[0] = framerate; - configured[1] = NULL; - kobject_uevent_env(&(amvideo_dev->kobj), - KOBJ_CHANGE, configured); - pr_info("%s: sent uevent %s\n", - __func__, configured[0]); - } - } + if ((data != NULL) && (video_seek_flag == 0)) + set_vframe_rate_hint((unsigned long)data); #endif } else if (type == VFRAME_EVENT_PROVIDER_FR_END_HINT) { #ifdef CONFIG_AM_VOUT - if (video_seek_flag == 0) { - configured[0] = "FRAME_RATE_END_HINT"; - configured[1] = NULL; - /*set_vframe_rate_end_hint();*/ - kobject_uevent_env(&(amvideo_dev->kobj), - KOBJ_CHANGE, configured); - pr_info("%s: sent uevent %s\n", - __func__, configured[0]); - } + if (video_seek_flag == 0) + set_vframe_rate_end_hint(); #endif } else if (type == VFRAME_EVENT_PROVIDER_QUREY_DISPLAY_INFO) { get_display_info(data); @@ -5157,9 +5830,16 @@ int _video_set_disable(u32 val) static void _set_video_crop(int *p) { - vpp_set_video_source_crop(p[0], p[1], p[2], p[3]); + int last_l, last_r, last_t, last_b; + int new_l, new_r, new_t, new_b; - video_property_changed = true; + vpp_get_video_source_crop(&last_t, &last_l, &last_b, &last_r); + vpp_set_video_source_crop(p[0], p[1], p[2], p[3]); + vpp_get_video_source_crop(&new_t, &new_l, &new_b, &new_r); + if ((new_t != last_t) || (new_l != last_l) + || (new_b != last_b) || (new_r != last_r)) { + video_property_changed = true; + } } static void _set_video_window(int *p) @@ -5271,6 +5951,7 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) switch (cmd) { case AMSTREAM_IOC_SET_OMX_VPTS:{ u32 pts; + get_user(pts, (u32 __user *)argp); omx_pts = pts; } @@ -5354,7 +6035,8 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) case AMSTREAM_IOC_VF_STATUS:{ struct vframe_states vfsta; struct vframe_states states; - vf_get_states(&vfsta); + + video_vf_get_states(&vfsta); states.vf_pool_size = vfsta.vf_pool_size; states.buf_avail_num = vfsta.buf_avail_num; states.buf_free_num = vfsta.buf_free_num; @@ -5368,9 +6050,14 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) put_user(disable_video, (u32 __user *)argp); break; - case AMSTREAM_IOC_SET_VIDEO_DISABLE: - ret = _video_set_disable(arg); - break; + case AMSTREAM_IOC_SET_VIDEO_DISABLE:{ + u32 val; + + if (copy_from_user(&val, argp, sizeof(u32)) == 0) + ret = _video_set_disable(val); + else + ret = -EFAULT; + } case AMSTREAM_IOC_GET_VIDEO_DISCONTINUE_REPORT: put_user(enable_video_discontinue_report, (u32 __user *)argp); @@ -5407,6 +6094,7 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) case AMSTREAM_IOC_SET_VIDEO_AXIS:{ int axis[4]; + if (copy_from_user(axis, argp, sizeof(axis)) == 0) _set_video_window(axis); else @@ -5428,6 +6116,7 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) case AMSTREAM_IOC_SET_VIDEO_CROP:{ int crop[4]; + if (copy_from_user(crop, argp, sizeof(crop)) == 0) _set_video_crop(crop); else @@ -5442,6 +6131,7 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) case AMSTREAM_IOC_SET_SCREEN_MODE:{ u32 mode; + if (copy_from_user(&mode, argp, sizeof(u32)) == 0) { if (mode >= VIDEO_WIDEOPTION_MAX) ret = -EINVAL; @@ -5461,6 +6151,7 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) case AMSTREAM_IOC_SET_BLACKOUT_POLICY:{ u32 mode; + if (copy_from_user(&mode, argp, sizeof(u32)) == 0) { if (mode > 2) ret = -EINVAL; @@ -5473,6 +6164,7 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) case AMSTREAM_IOC_CLEAR_VBUF:{ unsigned long flags; + spin_lock_irqsave(&lock, flags); cur_dispbuf = NULL; spin_unlock_irqrestore(&lock, flags); @@ -5512,13 +6204,15 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) unsigned int set_3d = VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE; unsigned int type = (unsigned int)arg; + if (type != process_3d_type) { process_3d_type = type; if (mvc_flag) process_3d_type |= MODE_3D_MVC; video_property_changed = true; if ((process_3d_type & MODE_3D_FA) - && !cur_dispbuf->trans_fmt) + && cur_dispbuf + && !cur_dispbuf->trans_fmt) /*notify di 3d mode is frame*/ /*alternative mode,passing two*/ /*buffer in one frame */ @@ -5545,14 +6239,13 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) #ifdef TV_3D_FUNCTION_OPEN { int source_video_3d_type = VPP_3D_MODE_NULL; + if (!cur_frame_par) source_video_3d_type = VPP_3D_MODE_NULL; -#if DEBUG_TMP else get_vpp_3d_mode(process_3d_type, cur_frame_par->trans_fmt, &source_video_3d_type); -#endif put_user(source_video_3d_type, (u32 __user *)argp); } #endif @@ -5569,6 +6262,17 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) vsync_slow_factor = arg; break; + case AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT: + if (arg != 0) + video_global_output = 1; + else + video_global_output = 0; + break; + + case AMSTREAM_IOC_GLOBAL_GET_VIDEO_OUTPUT: + put_user(video_global_output, (u32 __user *)argp); + break; + default: return -EINVAL; } @@ -5605,6 +6309,7 @@ static long amvideo_compat_ioctl(struct file *file, unsigned int cmd, ulong arg) case AMSTREAM_IOC_GET_3D_TYPE: case AMSTREAM_IOC_GET_SOURCE_VIDEO_3D_TYPE: case AMSTREAM_IOC_GET_VSYNC_SLOW_FACTOR: + case AMSTREAM_IOC_GLOBAL_GET_VIDEO_OUTPUT: arg = (unsigned long) compat_ptr(arg); case AMSTREAM_IOC_TRICKMODE: case AMSTREAM_IOC_VPAUSE: @@ -5624,6 +6329,7 @@ static long amvideo_compat_ioctl(struct file *file, unsigned int cmd, ulong arg) case AMSTREAM_IOC_SET_3D_TYPE: case AMSTREAM_IOC_SET_VSYNC_UPINT: case AMSTREAM_IOC_SET_VSYNC_SLOW_FACTOR: + case AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT: return amvideo_ioctl(file, cmd, arg); default: return -EINVAL; @@ -5799,6 +6505,7 @@ static ssize_t video_state_show(struct class *cla, { ssize_t len = 0; struct vppfilter_mode_s *vpp_filter = NULL; + if (!cur_frame_par) return len; vpp_filter = &cur_frame_par->vpp_filter; @@ -5921,6 +6628,7 @@ static ssize_t video_global_offset_show(struct class *cla, struct class_attribute *attr, char *buf) { int x, y; + vpp_get_global_offset(&x, &y); return snprintf(buf, 40, "%d %d\n", x, y); @@ -6396,7 +7104,18 @@ static u32 eight2ten(u32 yuv) int y = (yuv >> 16) & 0xff; int cb = (yuv >> 8) & 0xff; int cr = yuv & 0xff; - return (y << 20) | (cb << 10) | cr; + u32 data32; + + /* txlx need check vd1 path bit width by s2u registers */ + if (get_cpu_type() == MESON_CPU_MAJOR_ID_TXLX) { + data32 = READ_VCBUS_REG(0x1d94) & 0xffff; + if ((data32 == 0x2000) || + (data32 == 0x800)) + return ((y << 20)<<2) | ((cb << 10)<<2) | (cr<<2); + else + return (y << 20) | (cb << 10) | cr; + } else + return (y << 20) | (cb << 10) | cr; } static u32 rgb2yuv(u32 rgb) @@ -6436,19 +7155,23 @@ static ssize_t video_test_screen_store(struct class *cla, else data &= (~VPP_VD1_POSTBLEND); #endif - /* - if (test_screen & 0x04000000) - data |= VPP_VD2_PREBLEND; - else - data &= (~VPP_VD2_PREBLEND); - - if (test_screen & 0x08000000) - data |= VPP_VD2_POSTBLEND; - else - data &= (~VPP_VD2_POSTBLEND); - */ + +#if 0 //DEBUG_TMP + if (test_screen & 0x04000000) + data |= VPP_VD2_PREBLEND; + else + data &= (~VPP_VD2_PREBLEND); + + if (test_screen & 0x08000000) + data |= VPP_VD2_POSTBLEND; + else + data &= (~VPP_VD2_POSTBLEND); +#endif + /* show test screen YUV blend*/ - if (is_meson_gxm_cpu()) /* bit width change to 10bit in gxm */ + if (is_meson_gxm_cpu() || + (get_cpu_type() == MESON_CPU_MAJOR_ID_TXLX)) + /* bit width change to 10bit in gxm, 10/12 in txlx*/ WRITE_VCBUS_REG(VPP_DUMMY_DATA1, eight2ten(test_screen & 0x00ffffff)); else if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB) @@ -6485,8 +7208,9 @@ static ssize_t video_rgb_screen_store(struct class *cla, if (r < 0) return -EINVAL; +#if 0 //DEBUG_TMP /* vdin0 pre post blend enable or disabled */ - /* + data = READ_VCBUS_REG(VPP_MISC); if (rgb_screen & 0x01000000) data |= VPP_VD1_PREBLEND; @@ -6497,18 +7221,17 @@ static ssize_t video_rgb_screen_store(struct class *cla, data |= VPP_VD1_POSTBLEND; else data &= (~VPP_VD1_POSTBLEND); - */ - /* - if (test_screen & 0x04000000) - data |= VPP_VD2_PREBLEND; - else - data &= (~VPP_VD2_PREBLEND); - - if (test_screen & 0x08000000) - data |= VPP_VD2_POSTBLEND; - else - data &= (~VPP_VD2_POSTBLEND); - */ + + if (test_screen & 0x04000000) + data |= VPP_VD2_PREBLEND; + else + data &= (~VPP_VD2_PREBLEND); + + if (test_screen & 0x08000000) + data |= VPP_VD2_POSTBLEND; + else + data &= (~VPP_VD2_POSTBLEND); +#endif /* show test screen YUV blend*/ if (is_meson_gxtvbb_cpu()) { WRITE_VCBUS_REG(VPP_DUMMY_DATA1, @@ -6638,8 +7361,9 @@ static ssize_t threedim_mode_store(struct class *cla, if (mvc_flag) process_3d_type |= MODE_3D_MVC; video_property_changed = true; - if ((process_3d_type & MODE_3D_FA) && !cur_dispbuf->trans_fmt) - /*notify di 3d mode is frame alternative mode,*/ + if ((process_3d_type & MODE_3D_FA) + && cur_dispbuf && !cur_dispbuf->trans_fmt) + /*notify di 3d mode is frame alternative mode,1*/ /*passing two buffer in one frame */ vf_notify_receiver_by_name("deinterlace", VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE, @@ -6841,7 +7565,7 @@ static ssize_t vframe_states_show(struct class *cla, unsigned long flags; struct vframe_s *vf; - if (vf_get_states(&states) == 0) { + if (video_vf_get_states(&states) == 0) { ret += sprintf(buf + ret, "vframe_pool_size=%d\n", states.vf_pool_size); ret += sprintf(buf + ret, "vframe buf_free_num=%d\n", @@ -6912,6 +7636,7 @@ static ssize_t device_resolution_show(struct class *cla, { #ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 const struct vinfo_s *info; + if (cur_dev == &video_dev[0]) info = get_current_vinfo(); else @@ -6950,6 +7675,7 @@ static ssize_t video_debugflags_show(struct class *cla, struct class_attribute *attr, char *buf) { int len = 0; + len += sprintf(buf + len, "value=%d\n", debugflags); len += sprintf(buf + len, "bit0:playing as fast!\n"); len += sprintf(buf + len, @@ -6965,18 +7691,18 @@ static ssize_t video_debugflags_store(struct class *cla, int value = -1, seted = 1; /* - r = sscanf(buf, "%d", &value); - if (r == 1) { - debugflags = value; - seted = 1; - } else { - r = sscanf(buf, "0x%x", &value); - if (r == 1) { - debugflags = value; - seted = 1; - } - } -*/ + * r = sscanf(buf, "%d", &value); + * if (r == 1) { + * debugflags = value; + * seted = 1; + * } else { + * r = sscanf(buf, "0x%x", &value); + * if (r == 1) { + * debugflags = value; + * seted = 1; + * } + * } + */ r = kstrtoint(buf, 0, &value); if (r < 0) @@ -7208,6 +7934,7 @@ static ssize_t video_free_keep_buffer_store(struct class *cla, { size_t r; int val; + if (debug_flag & DEBUG_FLAG_BLACKOUT) pr_info("%s(%s)\n", __func__, buf); r = kstrtoint(buf, 0, &val); @@ -7526,6 +8253,7 @@ static struct class amvideo_poll_class = { static int __init vpp_axis_reverse(char *str) { unsigned char *ptr = str; + pr_info("%s: bootargs is %s\n", __func__, str); if (strstr(ptr, "1")) reverse = true; @@ -7636,8 +8364,6 @@ static void vout_hook(void) #if DEBUG_TMP set_current_vmode(VMODE_720P); #endif - set_current_vmode(10); - vinfo = get_current_vinfo(); } @@ -7719,12 +8445,19 @@ static void do_vpu_delay_work(struct work_struct *work) unsigned long flags; unsigned int r; +#if DEBUG_TMP + if (vpu_delay_work_flag & VPU_UPDATE_DOLBY_VISION) { + vpu_delay_work_flag &= ~VPU_UPDATE_DOLBY_VISION; + dolby_vision_update_setting(); + if (!vpu_delay_work_flag) + return; + } if (vpu_delay_work_flag & VPU_VIDEO_LAYER1_CHANGED) { vpu_delay_work_flag &= ~VPU_VIDEO_LAYER1_CHANGED; -#if DEBUG_TMP + switch_set_state(&video1_state_sdev, !!video_enabled); -#endif } +#endif spin_lock_irqsave(&delay_work_lock, flags); if (vpu_delay_work_flag & VPU_DELAYWORK_VPU_CLK) { @@ -7800,23 +8533,16 @@ struct device *get_video_device(void) static int __init video_early_init(void) { - const struct vinfo_s *vinfo; - /* todo: move this to clock tree, enable VPU clock */ -#if DEBUG_TMP - WRITE_CBUS_REG(HHI_VPU_CLK_CNTL, - (1<<9) | (1<<8) | (3)); // fclk_div3/4 = ~200M - WRITE_CBUS_REG(HHI_VPU_CLK_CNTL, - (3<<9) | (1<<8) | (0)); // fclk_div7/1 = 364M - //moved to vpu.c, default config by dts -#endif - vinfo = get_current_vinfo(); - if (!vinfo) - return -1; + /* WRITE_CBUS_REG(HHI_VPU_CLK_CNTL,*/ + /*(1<<9) | (1<<8) | (3)); // fclk_div3/4 = ~200M */ + /* WRITE_CBUS_REG(HHI_VPU_CLK_CNTL,*/ + /*(3<<9) | (1<<8) | (0)); // fclk_div7/1 = 364M*/ + /*moved to vpu.c, default config by dts */ - if (vinfo->mode >= VMODE_MAX) { + if (/*get_logo_vmode()*/0 >= VMODE_MAX) {/*DEBUG_TMP*/ #if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - if (is_meson_gxtvbb_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0xfff, VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); else @@ -7828,7 +8554,7 @@ static int __init video_early_init(void) #endif #endif /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ } else { - if (is_meson_gxtvbb_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0xfff, VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); } @@ -7836,7 +8562,7 @@ static int __init video_early_init(void) WRITE_VCBUS_REG(VPP_PREBLEND_VD1_H_START_END, 4096); WRITE_VCBUS_REG(VPP_BLEND_VD2_H_START_END, 4096); #endif - if (is_meson_txl_cpu()) { + if (is_meson_txl_cpu() || is_meson_txlx_cpu()) { /* fifo max size on txl :128*3=384[0x180] */ WRITE_VCBUS_REG(VD1_IF0_LUMA_FIFO_SIZE, 0x180); WRITE_VCBUS_REG(VD2_IF0_LUMA_FIFO_SIZE, 0x180); @@ -7846,7 +8572,7 @@ static int __init video_early_init(void) if (is_meson_gxbb_cpu()) SET_VCBUS_REG_MASK(VPP_MISC, VPP_OUT_SATURATE); - if (vinfo->mode >= VMODE_MAX) { + if (/*get_logo_vmode()*/0 >= VMODE_MAX) {/*DEBUG_TMP*/ CLEAR_VCBUS_REG_MASK(VPP_VSC_PHASE_CTRL, VPP_PHASECTL_TYPE_INTERLACE); #ifndef CONFIG_FB_AML_TCON @@ -7855,7 +8581,7 @@ static int __init video_early_init(void) WRITE_VCBUS_REG(VPP_HOLD_LINES + cur_dev->vpp_off, 0x08080808); } #ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 - if (vinfo->mode >= VMODE_MAX) { + if (/*get_logo_vmode()*/0 >= VMODE_MAX) {/*DEBUG_TMP*/ CLEAR_VCBUS_REG_MASK(VPP2_VSC_PHASE_CTRL, VPP_PHASECTL_TYPE_INTERLACE); #ifndef CONFIG_FB_AML_TCON @@ -7871,9 +8597,9 @@ static int __init video_early_init(void) VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); #endif /* - WRITE_VCBUS_REG_BITS(VPU_OSD3_MMC_CTRL, 1, 12, 2); - select vdisp_mmc_arb for VIU2_OSD1 request - */ + *WRITE_VCBUS_REG_BITS(VPU_OSD3_MMC_CTRL, 1, 12, 2); + *select vdisp_mmc_arb for VIU2_OSD1 request + */ WRITE_VCBUS_REG_BITS(VPU_OSD3_MMC_CTRL, 2, 12, 2); /* select vdin_mmc_arb for VIU2_OSD1 request */ #endif @@ -7882,13 +8608,16 @@ static int __init video_early_init(void) WRITE_VCBUS_REG_BITS(VIU_MISC_CTRL1, 0xff, 16, 8); WRITE_VCBUS_REG(VPP_DOLBY_CTRL, 0x22000); /* - default setting is black for dummy data1& dumy data0, - for dummy data1 the y/cb/cr data width is 10bit on gxm, - for dummy data the y/cb/cr data width is 8bit but - vpp_dummy_data will be left shift 2bit auto on gxm!!! - */ + *default setting is black for dummy data1& dumy data0, + *for dummy data1 the y/cb/cr data width is 10bit on gxm, + *for dummy data the y/cb/cr data width is 8bit but + *vpp_dummy_data will be left shift 2bit auto on gxm!!! + */ WRITE_VCBUS_REG(VPP_DUMMY_DATA1, 0x1020080); WRITE_VCBUS_REG(VPP_DUMMY_DATA, 0x42020); + } else if (is_meson_txlx_cpu()) { + /*black 10bit*/ + WRITE_VCBUS_REG(VPP_DUMMY_DATA, 0x4080200); } /* temp: enable VPU arb mem */ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) @@ -7897,6 +8626,51 @@ static int __init video_early_init(void) return 0; } +static struct mconfig video_configs[] = { + MC_PI32("pause_one_3d_fl_frame", &pause_one_3d_fl_frame), + MC_PI32("debug_flag", &debug_flag), + MC_PU32("force_3d_scaler", &force_3d_scaler), + MC_PU32("video_3d_format", &video_3d_format), + MC_PI32("vsync_enter_line_max", &vsync_enter_line_max), + MC_PI32("vsync_exit_line_max", &vsync_exit_line_max), +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + MC_PI32("vsync_rdma_line_max", &vsync_rdma_line_max), +#endif + MC_PU32("underflow", &underflow), + MC_PU32("next_peek_underflow", &next_peek_underflow), + MC_PU32("smooth_sync_enable", &smooth_sync_enable), + MC_PU32("hdmi_in_onvideo", &hdmi_in_onvideo), +#ifdef CONFIG_AM_VIDEO2 + MC_PI32("video_play_clone_rate", &video_play_clone_rate), + MC_PI32("android_clone_rate", &android_clone_rate), + MC_PI32("video_play_clone_rate", &video_play_clone_rate), + MC_PI32("android_clone_rate", &android_clone_rate), + MC_PI32("noneseamless_play_clone_rate", &noneseamless_play_clone_rate), +#endif + MC_PU32("smooth_sync_enable", &smooth_sync_enable), + MC_PU32("hdmi_in_onvideo", &hdmi_in_onvideo), + MC_PI32("cur_dev_idx", &cur_dev_idx), + MC_PU32("new_frame_count", &new_frame_count), + MC_PU32("omx_pts", &omx_pts), + MC_PI32("omx_pts_interval_upper", &omx_pts_interval_upper), + MC_PI32("omx_pts_interval_lower", &omx_pts_interval_lower), + MC_PBOOL("bypass_pps", &bypass_pps), + MC_PBOOL("platform_type", &platform_type), + MC_PU32("process_3d_type", &process_3d_type), + MC_PU32("omx_pts", &omx_pts), + MC_PU32("framepacking_support", &framepacking_support), + MC_PU32("framepacking_width", &framepacking_width), + MC_PU32("framepacking_height", &framepacking_height), + MC_PU32("framepacking_blank", &framepacking_blank), + MC_PU32("video_seek_flag", &video_seek_flag), + MC_PU32("slowsync_repeat_enable", &slowsync_repeat_enable), + MC_PU32("toggle_count", &toggle_count), + MC_PBOOL("show_first_frame_nosync", &show_first_frame_nosync), +#ifdef TV_REVERSE + MC_PBOOL("reverse", &reverse), +#endif +}; + static int amvideom_probe(struct platform_device *pdev) { int ret = 0; @@ -7944,11 +8718,11 @@ static int __init video_init(void) { int r = 0; /* - #ifdef CONFIG_ARCH_MESON1 - ulong clk = clk_get_rate(clk_get_sys("clk_other_pll", NULL)); - #elif !defined(CONFIG_ARCH_MESON3) && !defined(CONFIG_ARCH_MESON6) - ulong clk = clk_get_rate(clk_get_sys("clk_misc_pll", NULL)); - #endif + *#ifdef CONFIG_ARCH_MESON1 + *ulong clk = clk_get_rate(clk_get_sys("clk_other_pll", NULL)); + *#elif !defined(CONFIG_ARCH_MESON3) && !defined(CONFIG_ARCH_MESON6) + *ulong clk = clk_get_rate(clk_get_sys("clk_misc_pll", NULL)); + *#endif */ #ifdef CONFIG_ARCH_MESON1 @@ -8125,7 +8899,7 @@ static int __init video_init(void) #ifdef CONFIG_AM_VIDEO2 set_clone_frame_rate(android_clone_rate, 0); #endif - + REG_PATH_CONFIGS("media.video", video_configs); return 0; err5: device_destroy(&amvideo_class, MKDEV(AMVIDEO_MAJOR, 0)); @@ -8209,6 +8983,15 @@ MODULE_PARM_DESC(underflow, "\n Underflow count\n"); module_param(next_peek_underflow, uint, 0664); MODULE_PARM_DESC(skip, "\n Underflow count\n"); +module_param(hdmiin_frame_check, uint, 0664); +MODULE_PARM_DESC(hdmiin_frame_check, "\n hdmiin_frame_check\n"); + +module_param(step_enable, uint, 0664); +MODULE_PARM_DESC(step_enable, "\n step_enable\n"); + +module_param(step_flag, uint, 0664); +MODULE_PARM_DESC(step_flag, "\n step_flag\n"); + /*arch_initcall(video_early_init);*/ module_init(video_init); @@ -8239,6 +9022,9 @@ module_param(cur_dev_idx, uint, 0664); MODULE_PARM_DESC(new_frame_count, "\n new_frame_count\n"); module_param(new_frame_count, uint, 0664); +MODULE_PARM_DESC(first_frame_toggled, "\n first_frame_toggled\n"); +module_param(first_frame_toggled, uint, 0664); + MODULE_PARM_DESC(omx_pts, "\n omx_pts\n"); module_param(omx_pts, uint, 0664); @@ -8248,6 +9034,15 @@ module_param(omx_pts_interval_upper, int, 0664); MODULE_PARM_DESC(omx_pts_interval_lower, "\n omx_pts_interval\n"); module_param(omx_pts_interval_lower, int, 0664); +MODULE_PARM_DESC(drop_frame_count, "\n drop_frame_count\n"); +module_param(drop_frame_count, int, 0664); + +MODULE_PARM_DESC(receive_frame_count, "\n receive_frame_count\n"); +module_param(receive_frame_count, int, 0664); + +MODULE_PARM_DESC(display_frame_count, "\n display_frame_count\n"); +module_param(display_frame_count, int, 0664); + MODULE_PARM_DESC(bypass_pps, "\n pps_bypass\n"); module_param(bypass_pps, bool, 0664); @@ -8274,6 +9069,10 @@ module_param(framepacking_blank, uint, 0664); module_param(reverse, bool, 0644); MODULE_PARM_DESC(reverse, "reverse /disable reverse"); #endif + +MODULE_PARM_DESC(toggle_count, "\n toggle count\n"); +module_param(toggle_count, uint, 0664); + MODULE_DESCRIPTION("AMLOGIC video output driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media/video_sink/video_keeper.c b/drivers/amlogic/media/video_sink/video_keeper.c index df11c89..dfaf9bd 100644 --- a/drivers/amlogic/media/video_sink/video_keeper.c +++ b/drivers/amlogic/media/video_sink/video_keeper.c @@ -665,10 +665,11 @@ static int alloc_keep_buffer(void) goto err1; } } - pr_info("alloced keep buffer yaddr=%p,u_addr=%p,v_addr=%p\n", + pr_info("alloced keep buffer yaddr=%p,u_addr=%p,v_addr=%p,tvp=%d\n", (void *)keep_y_addr, (void *)keep_u_addr, - (void *)keep_v_addr); + (void *)keep_v_addr, + codec_mm_video_tvp_enabled()); return 0; err1: @@ -782,7 +783,7 @@ unsigned int vf_keep_current(struct vframe_s *cur_dispbuf) return 0; } -#ifdef CONFIG_AM_VIDEOCAPTURE +#ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE ext_frame_capture_poll(1); /*pull if have capture end frame */ #endif if (get_blackout_policy()) { @@ -825,6 +826,14 @@ unsigned int vf_keep_current(struct vframe_s *cur_dispbuf) } } } + +#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC + if (codec_mm_video_tvp_enabled()) { + pr_info("keep exit is TVP\n"); + return 0; + } +#endif + if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) && (cur_dispbuf->type & VIDTYPE_COMPRESS)) { /* todo: duplicate compressed video frame */ diff --git a/drivers/amlogic/media/video_sink/video_priv.h b/drivers/amlogic/media/video_sink/video_priv.h index 77144c3..1ef5955 100644 --- a/drivers/amlogic/media/video_sink/video_priv.h +++ b/drivers/amlogic/media/video_sink/video_priv.h @@ -54,13 +54,10 @@ int get_video_debug_flags(void); int _video_set_disable(u32 val); u32 get_video_enabled(void); -#ifdef CONFIG_AM_VIDEOCAPTURE +#ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE int ext_frame_capture_poll(int endflags); #endif -#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA extern u32 disp_canvas_index[2][6]; #endif -#endif - /*VIDEO_PRIV_HEADER_HH*/ diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index 3b7eb09..0cf1dc38 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -307,8 +307,8 @@ static uint coeff(uint *settings, uint ratio, uint phase, } coeff_type = settings[coeff_select]; /* TODO: add future TV chips */ - if ((get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB) || - (get_cpu_type() == MESON_CPU_MAJOR_ID_TXL)) { + if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || + is_meson_txlx_cpu()) { if (coeff_type == COEF_BICUBIC_SHARP) coeff_type = COEF_BICUBIC; } else { @@ -407,7 +407,7 @@ static unsigned int super_debug; module_param(super_debug, uint, 0664); MODULE_PARM_DESC(super_debug, "super_debug"); -static unsigned int super_scaler = 1; +unsigned int super_scaler = 1; module_param(super_scaler, uint, 0664); MODULE_PARM_DESC(super_scaler, "super_scaler"); @@ -435,6 +435,7 @@ static unsigned int horz_scaler_filter = 0xff; module_param(horz_scaler_filter, uint, 0664); MODULE_PARM_DESC(horz_scaler_filter, "horz_scaler_filter"); +/*need check this value,*/ static unsigned int bypass_ratio = 205; module_param(bypass_ratio, uint, 0664); MODULE_PARM_DESC(bypass_ratio, "bypass_ratio"); @@ -455,7 +456,7 @@ module_param(force_vskip_cnt, uint, 0664); #define DECL_PARM(name)\ static int name;\ MODULE_PARM_DESC(name, #name);\ -module_param(name, int, 0664) +module_param(name, int, 0664); DECL_PARM(debug_wide_mode) DECL_PARM(debug_video_left) @@ -582,6 +583,31 @@ calculate_non_linear_ratio(unsigned int middle_ratio, * (1.25 * 3840 / 1920) for 1080p mode. */ #define MIN_RATIO_1000 1250 +unsigned int cur_skip_ratio; +MODULE_PARM_DESC(cur_skip_ratio, "cur_skip_ratio"); +module_param(cur_skip_ratio, uint, 0444); +unsigned int cur_vf_type; +MODULE_PARM_DESC(cur_vf_type, "cur_vf_type"); +module_param(cur_vf_type, uint, 0444); + +/* + *test on txlx: + *Time_out = (V_out/V_screen_total)/FPS_out; + *if di bypas: + *Time_in = (H_in * V_in)/Clk_vpu; + *if di work; for di clk is less than vpu usually; + *Time_in = (H_in * V_in)/Clk_di; + *if Time_in < Time_out,need do vskip; + *but in effect,test result may have some error. + *ratio1:V_out test result may larger than calc result; + *--after test is large ratio is 1.09; + *--so wo should choose the largest ratio_v_out = 110/100; + *ratio2:use clk_di or clk_vpu; + *--txlx di clk is 250M or 500M; + *--before txlx di clk is 333M; + *So need adjust bypass_ratio; + */ + static int vpp_process_speed_check(s32 width_in, s32 height_in, @@ -590,25 +616,72 @@ vpp_process_speed_check(s32 width_in, struct vpp_frame_par_s *next_frame_par, const struct vinfo_s *vinfo, struct vframe_s *vf) { - u32 cur_ratio; + u32 cur_ratio, bpp = 1; + int min_ratio_1000 = 0; + u32 vtotal, clk_in_pps = 0; + if (vf) + cur_vf_type = vf->type; + if (force_vskip_cnt == 0xff)/*for debug*/ + return SPEED_CHECK_DONE; if (next_frame_par->vscale_skip_count < force_vskip_cnt) return SPEED_CHECK_VSKIP; + if (vf->type & VIDTYPE_PRE_INTERLACE) { + if (is_meson_txlx_cpu()) + clk_in_pps = 250000000; + else + clk_in_pps = 333000000; + } else { + clk_in_pps = get_vpu_clk(); + } + if (vf->type & VIDTYPE_COMPRESS) { + if (vf->width > 720) + min_ratio_1000 = (MIN_RATIO_1000 * 1400)/1000; + else + min_ratio_1000 = (1750 * 1400)/1000; + } else { + if (vf->width > 720) + min_ratio_1000 = MIN_RATIO_1000; + else + min_ratio_1000 = 1750; + } + if (vinfo->field_height < vinfo->height) + vtotal = 525 / 2;//vinfo->vtotal/2; + else + vtotal = 525;//vinfo->vtotal;//DEBUG_TMP /* #if (MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8) */ if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) && !is_meson_mtvd_cpu()) { if ((width_in <= 0) || (height_in <= 0) || (height_out <= 0) || (height_screen <= 0)) return SPEED_CHECK_DONE; - if (height_in > height_out) { + if ((next_frame_par->vscale_skip_count > 0) + && (vf->type & VIDTYPE_VIU_444)) + bpp = 2; + if (height_in * bpp > height_out) { + /* + *don't need do skip for under 5% scaler down + *reason:for 1080p input,4k output, if di clk is 250M, + *the clac height is 1119;which is bigger than 1080! + */ + if (height_in > height_out && + ((height_in - height_out) < height_in/20)) + return SPEED_CHECK_DONE; if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { cur_ratio = div_u64((u64)height_in * (u64)vinfo->height * 1000, height_out * 2160); - if ((cur_ratio > MIN_RATIO_1000) && + /* di process first, need more a bit of ratio */ + if (vf->type & VIDTYPE_PRE_INTERLACE) + cur_ratio = (cur_ratio * 105) / 100; + if ((next_frame_par->vscale_skip_count > 0) + && (vf->type & VIDTYPE_VIU_444)) + cur_ratio = cur_ratio * 2; + cur_skip_ratio = cur_ratio; + if ((cur_ratio > min_ratio_1000) && (vf->source_type != VFRAME_SOURCE_TYPE_TUNER) && (vf->source_type != VFRAME_SOURCE_TYPE_CVBS)) return SPEED_CHECK_VSKIP; @@ -620,10 +693,10 @@ vpp_process_speed_check(s32 width_in, (u64)width_in * (u64)height_in * (u64)vinfo->sync_duration_num * - (u64)height_screen, + (u64)vtotal, height_out * vinfo->sync_duration_den * - bypass_ratio) > get_vpu_clk()) + bypass_ratio) > clk_in_pps) return SPEED_CHECK_VSKIP; else return SPEED_CHECK_DONE; @@ -634,10 +707,10 @@ vpp_process_speed_check(s32 width_in, (u64)width_in * (u64)height_in * (u64)vinfo->sync_duration_num * - (u64)height_screen, + (u64)vtotal, height_out * vinfo->sync_duration_den * 256) - > get_vpu_clk()) + > clk_in_pps) return SPEED_CHECK_VSKIP; /* 4K down scaling to non 4K > 30hz,*/ /*skip lines for memory bandwidth */ @@ -649,7 +722,9 @@ vpp_process_speed_check(s32 width_in, (vinfo->sync_duration_num > (30 * vinfo->sync_duration_den)) && (get_cpu_type() != - MESON_CPU_MAJOR_ID_GXTVBB)) + MESON_CPU_MAJOR_ID_GXTVBB) && + (get_cpu_type() != + MESON_CPU_MAJOR_ID_GXM)) return SPEED_CHECK_VSKIP; else return SPEED_CHECK_DONE; @@ -756,6 +831,10 @@ vpp_set_filters2(u32 process_3d_type, u32 width_in, } } + if (is_meson_txlx_cpu()) { + next_frame_par->vpp_postblend_out_width = vinfo->width; + next_frame_par->vpp_postblend_out_height = vinfo->height; + } #ifndef TV_3D_FUNCTION_OPEN next_frame_par->vscale_skip_count = 0; next_frame_par->hscale_skip_count = 0; @@ -941,9 +1020,9 @@ RESTART: ratio_y = (height_after_ratio << 18) / screen_height; if (super_debug) - pr_info("height_after_ratio=%d,%d,%d,%d\n", + pr_info("height_after_ratio=%d,%d,%d,%d,%d\n", height_after_ratio, ratio_x, ratio_y, - aspect_factor); + aspect_factor, wide_mode); if (wide_mode == VIDEO_WIDEOPTION_NORMAL) { ratio_x = ratio_y = max(ratio_x, ratio_y); @@ -1132,7 +1211,8 @@ RESTART: (vpp_zoom_center_x << 10)) / ratio_x; end = (w_in << 18) / ratio_x + start - 1; - pr_info("left:start =%d,%d,%d,%d %d,%d,%d\n", + if (super_debug) + pr_info("left:start =%d,%d,%d,%d %d,%d,%d\n", start, end, video_left, video_width, w_in, ratio_x, vpp_zoom_center_x); #endif @@ -1239,9 +1319,9 @@ RESTART: (next_frame_par->VPP_vd_end_lines_ - next_frame_par->VPP_vd_start_lines_ + 1) / (next_frame_par->vscale_skip_count + 1), - next_frame_par->VPP_vsc_endp - - next_frame_par->VPP_vsc_startp, - height_out >> + (next_frame_par->VPP_vsc_endp - + next_frame_par->VPP_vsc_startp + 1), + vinfo->height >> ((vpp_flags & VPP_FLAG_INTERLACE_OUT) ? 1 : 0), next_frame_par, vinfo, @@ -1290,8 +1370,9 @@ RESTART: next_frame_par->vscale_skip_count = skip_policy & 0xf; goto RESTART; } else if (skip_policy & 0x80) { - if ((vf->width >= 4096) && - (!(vf->type & VIDTYPE_COMPRESS)) + if ((((vf->width >= 4096) && + (!(vf->type & VIDTYPE_COMPRESS))) || + (vf->flag & VFRAME_FLAG_HIGH_BANDWIDTH)) && (next_frame_par->vscale_skip_count == 0)) { next_frame_par->vscale_skip_count = skip_policy & 0xf; @@ -1331,7 +1412,7 @@ RESTART: cur_vert_chroma_filter = COEF_NULL; filter->vpp_vert_chroma_filter_en = false; } - + /* avoid hscaler fitler adjustion affect on picture shift*/ filter->vpp_horz_filter = coeff(horz_coeff_settings, filter->vpp_hf_start_phase_step, @@ -1340,8 +1421,7 @@ RESTART: != VIDTYPE_PROGRESSIVE), vf->combing_cur_lev); /*for gxl cvbs out index*/ - if ((vinfo->mode == VMODE_CVBS) && - (vinfo->height == 576) && + if ((vinfo->mode == VMODE_CVBS) && //DEBUG_TMP (filter->vpp_hf_start_phase_step == (1 << 24))) filter->vpp_horz_filter = COEF_BICUBIC_SHARP; filter->vpp_horz_coeff = @@ -1512,7 +1592,9 @@ int vpp_set_super_scaler_regs(int scaler_path_sel, int reg_srscl1_hsize, int reg_srscl1_vsize, int reg_srscl1_hori_ratio, - int reg_srscl1_vert_ratio) + int reg_srscl1_vert_ratio, + int vpp_postblend_out_width, + int vpp_postblend_out_height) { int tmp_data = 0; @@ -1600,19 +1682,33 @@ int vpp_set_super_scaler_regs(int scaler_path_sel, VSYNC_WR_MPEG_REG(SRSHARP1_SHARP_HVSIZE, tmp_data); sharpness1_sr2_ctrl_3280 = tmp_data; } - - if (scaler_path_sel == sup0_pp_sp1_scpath) { - tmp_data = ((reg_srscl1_hsize & 0x1fff) << 16) | - (reg_srscl1_vsize & 0x1fff); - tmp_data2 = READ_VCBUS_REG(VPP_VE_H_V_SIZE); - if (tmp_data != tmp_data2) - VSYNC_WR_MPEG_REG(VPP_VE_H_V_SIZE, tmp_data); - } else if (scaler_path_sel == sup0_pp_post_blender) { - tmp_data = ((reg_srscl1_hsize & 0x1fff) << 16) | - (reg_srscl1_vsize & 0x1fff); - tmp_data2 = READ_VCBUS_REG(VPP_PSR_H_V_SIZE); - if (tmp_data != tmp_data2) - VSYNC_WR_MPEG_REG(VPP_PSR_H_V_SIZE, tmp_data); + /*ve input size setting*/ + tmp_data = ((reg_srscl1_hsize & 0x1fff) << 16) | + (reg_srscl1_vsize & 0x1fff); + tmp_data2 = READ_VCBUS_REG(VPP_VE_H_V_SIZE); + if (tmp_data != tmp_data2) + VSYNC_WR_MPEG_REG(VPP_VE_H_V_SIZE, tmp_data); + /*chroma blue stretch size setting*/ + if (is_meson_txlx_cpu()) { + tmp_data = (((vpp_postblend_out_width & 0x1fff) << 16) | + (vpp_postblend_out_height & 0x1fff)); + VSYNC_WR_MPEG_REG(VPP_OUT_H_V_SIZE, tmp_data); + } else { + if (scaler_path_sel == sup0_pp_sp1_scpath) { + tmp_data = (((reg_srscl1_hsize & 0x1fff) << + reg_srscl1_hori_ratio) << 16) | + ((reg_srscl1_vsize & 0x1fff) << + reg_srscl1_vert_ratio); + tmp_data2 = READ_VCBUS_REG(VPP_PSR_H_V_SIZE); + if (tmp_data != tmp_data2) + VSYNC_WR_MPEG_REG(VPP_PSR_H_V_SIZE, tmp_data); + } else if (scaler_path_sel == sup0_pp_post_blender) { + tmp_data = ((reg_srscl1_hsize & 0x1fff) << 16) | + (reg_srscl1_vsize & 0x1fff); + tmp_data2 = READ_VCBUS_REG(VPP_PSR_H_V_SIZE); + if (tmp_data != tmp_data2) + VSYNC_WR_MPEG_REG(VPP_PSR_H_V_SIZE, tmp_data); + } } /* path config */ @@ -1664,64 +1760,72 @@ static void vpp_set_scaler(u32 process_3d_type, u32 src_width, ver_sc_multiple_num = height_out*SUPER_SCALER_V_FACTOR / src_height; /* just calcuate the enable sclaer module */ - if ((hor_sc_multiple_num >= 4) || (ver_sc_multiple_num >= - (4*SUPER_SCALER_V_FACTOR))) { - if (bypass_spscl0 == 0) - next_frame_par->supsc0_enable = 1; - if (bypass_spscl1 == 0) - next_frame_par->supsc1_enable = 1; - } else if ((hor_sc_multiple_num >= 2) || (ver_sc_multiple_num >= - (2*SUPER_SCALER_V_FACTOR))) { - if (((src_width > SUPER_CORE0_WIDTH_MAX/2) - && (src_width <= SUPER_CORE0_WIDTH_MAX) - && (bypass_spscl1 == 0)) - || (bypass_spscl0 == 1)) { - next_frame_par->supsc0_enable = 0; - next_frame_par->supsc1_enable = 1; - } else if ((src_width > SUPER_CORE0_WIDTH_MAX/2) - && (src_width <= SUPER_CORE0_WIDTH_MAX) - && (bypass_spscl1 == 1)) { - next_frame_par->supsc0_enable = 0; - next_frame_par->supsc1_enable = 0; - } else { - next_frame_par->supsc0_enable = 1; - next_frame_par->supsc1_enable = 0; - } - } else { - next_frame_par->supsc0_enable = 0; - next_frame_par->supsc1_enable = 0; - } - if (src_width > SUPER_CORE0_WIDTH_MAX) - next_frame_par->supsc0_enable = 0; - if (width_out > SUPER_CORE1_WIDTH_MAX*2) - next_frame_par->supsc1_enable = 0; - - if (ver_sc_multiple_num >= (2*SUPER_SCALER_V_FACTOR)) { - if (src_width > SUPER_CORE0_WIDTH_MAX/2) - next_frame_par->supsc0_vert_ratio = 0; - else - next_frame_par->supsc0_vert_ratio = - next_frame_par->supsc0_enable ? 1 : 0; - if (width_out > SUPER_CORE1_WIDTH_MAX*2) + /* + *note:if first check h may cause v can't do scaling; + * for example: 1920x1080(input),3840x2160(output); + * todo:if you have better idea,you can improve it + */ + /* step1: judge core0&core1 vertical enable or disable*/ + if (ver_sc_multiple_num >= 2*SUPER_SCALER_V_FACTOR) { + next_frame_par->supsc0_vert_ratio = + (src_width < SUPER_CORE0_WIDTH_MAX/2) ? 1 : 0; + next_frame_par->supsc1_vert_ratio = + ((width_out < SUPER_CORE1_WIDTH_MAX) && + (src_width < SUPER_CORE1_WIDTH_MAX/2)) ? 1 : 0; + if (next_frame_par->supsc0_vert_ratio && + (ver_sc_multiple_num < 4*SUPER_SCALER_V_FACTOR)) next_frame_par->supsc1_vert_ratio = 0; - else - next_frame_par->supsc1_vert_ratio = - next_frame_par->supsc1_enable ? 1 : 0; + next_frame_par->supsc0_enable = + next_frame_par->supsc0_vert_ratio ? 1 : 0; + next_frame_par->supsc1_enable = + next_frame_par->supsc1_vert_ratio ? 1 : 0; } else { + next_frame_par->supsc0_enable = 0; next_frame_par->supsc0_vert_ratio = 0; + next_frame_par->supsc1_enable = 0; next_frame_par->supsc1_vert_ratio = 0; } + /* step2: judge core0&core1 horizontal enable or disable*/ if (hor_sc_multiple_num >= 2) { - next_frame_par->supsc0_hori_ratio = - next_frame_par->supsc0_enable ? 1 : 0; - next_frame_par->supsc1_hori_ratio = - next_frame_par->supsc1_enable ? 1 : 0; + if ((src_width > SUPER_CORE0_WIDTH_MAX) || + ((src_width > SUPER_CORE0_WIDTH_MAX/2) && + next_frame_par->supsc0_vert_ratio) || + (((src_width << 1) > SUPER_CORE1_WIDTH_MAX/2) && + next_frame_par->supsc1_vert_ratio)) + next_frame_par->supsc0_hori_ratio = 0; + else + next_frame_par->supsc0_hori_ratio = 1; + if (((width_out >> 1) > SUPER_CORE1_WIDTH_MAX) || + (((width_out >> 1) > SUPER_CORE1_WIDTH_MAX/2) && + next_frame_par->supsc1_vert_ratio) || + (next_frame_par->supsc0_hori_ratio && + (hor_sc_multiple_num < 4))) + next_frame_par->supsc1_hori_ratio = 0; + else + next_frame_par->supsc1_hori_ratio = 1; + next_frame_par->supsc0_enable = + (next_frame_par->supsc0_hori_ratio || + next_frame_par->supsc0_enable) ? 1 : 0; + next_frame_par->supsc1_enable = + (next_frame_par->supsc1_hori_ratio || + next_frame_par->supsc1_enable) ? 1 : 0; } else { + next_frame_par->supsc0_enable = + next_frame_par->supsc0_vert_ratio ? 1 : 0; next_frame_par->supsc0_hori_ratio = 0; + next_frame_par->supsc1_enable = + next_frame_par->supsc1_vert_ratio ? 1 : 0; next_frame_par->supsc1_hori_ratio = 0; - next_frame_par->supsc0_vert_ratio = 0; + } + /*double check core1 input width for core1_vert_ratio!!!*/ + if (next_frame_par->supsc1_vert_ratio && + (width_out >> next_frame_par->supsc1_hori_ratio > + SUPER_CORE1_WIDTH_MAX/2)) { next_frame_par->supsc1_vert_ratio = 0; + if (next_frame_par->supsc1_hori_ratio == 0) + next_frame_par->supsc1_enable = 0; } + /* option add patch */ if ((ver_sc_multiple_num <= super_scaler_v_ratio) && (src_height >= SUPER_CORE0_WIDTH_MAX/2) && (src_height <= 1088) && @@ -1874,7 +1978,7 @@ static void vpp_set_scaler(u32 process_3d_type, u32 src_width, } #ifdef TV_3D_FUNCTION_OPEN -void get_vpp_3d_mode(u32 trans_fmt, u32 *vpp_3d_mode) +void get_vpp_3d_mode(u32 process_3d_type, u32 trans_fmt, u32 *vpp_3d_mode) { switch (trans_fmt) { case TVIN_TFMT_3D_LRH_OLOR: @@ -1889,6 +1993,8 @@ void get_vpp_3d_mode(u32 trans_fmt, u32 *vpp_3d_mode) case TVIN_TFMT_3D_DET_TB: case TVIN_TFMT_3D_FA: *vpp_3d_mode = VPP_3D_MODE_TB; + if (process_3d_type & MODE_3D_MVC) + *vpp_3d_mode = VPP_3D_MODE_FA; break; case TVIN_TFMT_3D_LA: case TVIN_TFMT_3D_DET_INTERLACE: @@ -1957,7 +2063,8 @@ vpp_get_video_source_size(u32 *src_width, u32 *src_height, break; } - } else if (process_3d_type & MODE_3D_LR) { + } else if ((process_3d_type & MODE_3D_LR) || + (process_3d_type & MODE_FORCE_3D_LR)) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_LR; if (process_3d_type & MODE_3D_TO_2D_MASK) { *src_width = vf->width >> 1; @@ -1972,7 +2079,8 @@ vpp_get_video_source_size(u32 *src_width, u32 *src_height, next_frame_par->vpp_2pic_mode = 1; } - } else if (process_3d_type & MODE_3D_TB) { + } else if ((process_3d_type & MODE_3D_TB) || + (process_3d_type & MODE_FORCE_3D_TB)) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_TB; if (process_3d_type & MODE_3D_TO_2D_MASK) { *src_width = vf->width; @@ -1986,6 +2094,12 @@ vpp_get_video_source_size(u32 *src_width, u32 *src_height, *src_height = vf->height; next_frame_par->vpp_2pic_mode = 1; } + if (process_3d_type & MODE_3D_MVC) { + *src_width = vf->width; + *src_height = vf->height << 1; + next_frame_par->vpp_2pic_mode = 2; + next_frame_par->vpp_3d_mode = VPP_3D_MODE_FA; + } } else if (process_3d_type & MODE_3D_LA) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_LA; *src_height = vf->height - 1; @@ -2004,11 +2118,34 @@ vpp_get_video_source_size(u32 *src_width, u32 *src_height, next_frame_par->vscale_skip_count = 1; next_frame_par->vpp_3d_scale = 0; } - } else if (process_3d_type & MODE_3D_FA) { + } else if ((process_3d_type & MODE_3D_FA) + || (process_3d_type & MODE_FORCE_3D_FA_LR) + || (process_3d_type & MODE_FORCE_3D_FA_TB)) { + next_frame_par->vpp_3d_mode = VPP_3D_MODE_FA; if (process_3d_type & MODE_3D_TO_2D_MASK) { - *src_width = vf->width; - *src_height = vf->height; + + if (process_3d_type & MODE_FORCE_3D_FA_TB) { + next_frame_par->vpp_3d_mode = VPP_3D_MODE_TB; + *src_width = vf->width; + *src_height = vf->height >> 1; + } + if (process_3d_type & MODE_FORCE_3D_FA_LR) { + next_frame_par->vpp_3d_mode = VPP_3D_MODE_LR; + *src_width = vf->width >> 1; + *src_height = vf->height; + } + if (process_3d_type & MODE_3D_MVC) { + *src_width = vf->width; + *src_height = vf->height; + next_frame_par->vpp_3d_mode = VPP_3D_MODE_FA; + } + if (vf->trans_fmt == TVIN_TFMT_3D_FP) { + next_frame_par->vpp_3d_mode = VPP_3D_MODE_TB; + *src_width = vf->width; + *src_height = vf->left_eye.height; + } + next_frame_par->vpp_2pic_mode = 0; } else if (process_3d_type & MODE_3D_OUT_LR) { *src_width = vf->width << 1; *src_height = vf->height; @@ -2092,7 +2229,7 @@ vpp_set_filters(u32 process_3d_type, u32 wide_mode, next_frame_par->vpp_3d_scale = 0; } next_frame_par->trans_fmt = vf->trans_fmt; - get_vpp_3d_mode(next_frame_par->trans_fmt, + get_vpp_3d_mode(process_3d_type, next_frame_par->trans_fmt, &next_frame_par->vpp_3d_mode); if (vpp_3d_scale) next_frame_par->vpp_3d_scale = 1; @@ -2384,8 +2521,8 @@ void vpp_set_3d_scale(bool enable) void vpp_super_scaler_support(void) { - if ((get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB) || - (get_cpu_type() == MESON_CPU_MAJOR_ID_TXL)) + if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || + is_meson_txlx_cpu()) super_scaler = 1; else super_scaler = 0; @@ -2393,10 +2530,11 @@ void vpp_super_scaler_support(void) void vpp_bypass_ratio_config(void) { - if ((get_cpu_type() == MESON_CPU_MAJOR_ID_GXBB) - || (get_cpu_type() == MESON_CPU_MAJOR_ID_GXL) - || (get_cpu_type() == MESON_CPU_MAJOR_ID_GXM)) + if (is_meson_gxbb_cpu() || is_meson_gxl_cpu() || + is_meson_gxm_cpu()) bypass_ratio = 125; + else if (is_meson_txlx_cpu() || is_meson_txl_cpu()) + bypass_ratio = 247;/*0x110 * (100/110)=0xf7*/ else bypass_ratio = 205; } diff --git a/drivers/amlogic/wifi/wifi_dt.c b/drivers/amlogic/wifi/wifi_dt.c index be0d53f..a8923c7 100644 --- a/drivers/amlogic/wifi/wifi_dt.c +++ b/drivers/amlogic/wifi/wifi_dt.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include diff --git a/include/linux/amlogic/cpu_version.h b/include/linux/amlogic/cpu_version.h index a4bdc71..407f2fd 100644 --- a/include/linux/amlogic/cpu_version.h +++ b/include/linux/amlogic/cpu_version.h @@ -18,7 +18,7 @@ #ifndef __PLAT_MESON_CPU_H #define __PLAT_MESON_CPU_H -#define MESON_CPU_MAJOR_ID_M8B 0x1B +#define MESON_CPU_MAJOR_ID_M8B 0x1B #define MESON_CPU_MAJOR_ID_GXBB 0x1F #define MESON_CPU_MAJOR_ID_GXTVBB 0x20 #define MESON_CPU_MAJOR_ID_GXL 0x21 @@ -145,4 +145,13 @@ static inline bool cpu_after_eq(unsigned int id) return get_cpu_type() >= id; } +static inline bool is_meson_txlx_package_962X(void) +{ + return is_meson_txlx_cpu() && package_id_is(0x10); +} + +static inline bool is_meson_txlx_package_962E(void) +{ + return is_meson_txlx_cpu() && package_id_is(0x20); +} #endif diff --git a/include/linux/amlogic/major.h b/include/linux/amlogic/major.h index f52db1d..4d2f9c2 100644 --- a/include/linux/amlogic/major.h +++ b/include/linux/amlogic/major.h @@ -27,7 +27,8 @@ #define AMAUDIO_MAJOR (11+(AML_BASE)) #define AMVIDEO2_MAJOR (12+(AML_BASE)) #define AMAUDIO2_MAJOR (13+(AML_BASE)) - +#define VFM_MAJOR (14+(AML_BASE)) +#define IONVIDEO_MAJOR (15+(AML_BASE)) /* *#define UIO_MAJOR 4+(AML_BASE) *#define USB_DEV_EP_MAJOR 5+(AML_BASE) diff --git a/include/linux/amlogic/media/canvas/canvas.h b/include/linux/amlogic/media/canvas/canvas.h index 8044448..b5ad471 100644 --- a/include/linux/amlogic/media/canvas/canvas.h +++ b/include/linux/amlogic/media/canvas/canvas.h @@ -58,8 +58,8 @@ struct canvas_config_s { /*for progressive mjpeg (nv21 output)use*/ #define PPMGR_DEINTERLACE_BUF_NV21_CANVAS 0x7e -#define PPMGR2_MAX_CANVAS 8 -#define PPMGR2_CANVAS_INDEX 0x70 /* 0x70-0x7f for PPMGR2 (IONVIDEO)/ */ +#define PPMGR2_MAX_CANVAS 16 +#define PPMGR2_CANVAS_INDEX 0x70 /* 0x70-0x7f for PPMGR2 (IONVIDEO)/ */ /* *the following reserved canvas index value diff --git a/include/linux/amlogic/media/canvas/canvas_mgr.h b/include/linux/amlogic/media/canvas/canvas_mgr.h index 56ca7aa..dc48eca 100644 --- a/include/linux/amlogic/media/canvas/canvas_mgr.h +++ b/include/linux/amlogic/media/canvas/canvas_mgr.h @@ -18,6 +18,8 @@ #ifndef CANVAS_MGR_HEADER_ #define CANVAS_MGR_HEADER_ +#include + #define CANVAS_MAX_NUM 256 struct canvas_info { @@ -34,7 +36,7 @@ struct canvas_pool { int canvas_max; int free_num; struct canvas_info info[CANVAS_MAX_NUM]; - unsigned long canvas_map[CANVAS_MAX_NUM / sizeof(unsigned long)]; + unsigned long canvas_map[(CANVAS_MAX_NUM / BITS_PER_LONG) + 1]; int next_alloced_index; int next_dump_index; unsigned long last_cat_map; diff --git a/include/linux/amlogic/media/codec_mm/codec_mm.h b/include/linux/amlogic/media/codec_mm/codec_mm.h index 02ea099..5de94ec 100644 --- a/include/linux/amlogic/media/codec_mm/codec_mm.h +++ b/include/linux/amlogic/media/codec_mm/codec_mm.h @@ -69,9 +69,12 @@ #define CODEC_MM_FLAGS_DMA_CPU (CODEC_MM_FLAGS_DMA | CODEC_MM_FLAGS_CPU) #define CODEC_MM_FLAGS_ANY CODEC_MM_FLAGS_DMA_CPU +/*--------------------------------------------------*/ struct codec_mm_s { /*can be shared by many user */ const char *owner[8]; + int ins_id;/*used by with channel?*/ + int ins_buffer_id;/*canbe for buffer id*/ /*virtual buffer of this memory */ char *vbuffer; void *mem_handle; /*used for top level.alloc/free */ @@ -101,17 +104,30 @@ struct codec_mm_s { char *pagemap; int pagemap_size; int alloced_page_num; + u64 alloced_jiffies; int mem_id; int next_bit; struct list_head list; }; struct codec_mm_s *codec_mm_alloc(const char *owner, int size, int align2n, int memflags); +unsigned long codec_mm_alloc_for_dma_ex( + const char *owner, + int page_cnt, + int align2n, + int memflags, + int ins_id, + int buffer_id); + void codec_mm_release(struct codec_mm_s *mem, const char *owner); int codec_mm_request_shared_mem(struct codec_mm_s *mem, const char *owner); /*call if not make sure valid data.*/ void codec_mm_release_with_check(struct codec_mm_s *mem, const char *owner); unsigned long dma_get_cma_size_int_byte(struct device *dev); + + +/*---------------------------------------------------------------*/ + unsigned long codec_mm_alloc_for_dma(const char *owner, int page_cnt, int align2n, int memflags); int codec_mm_free_for_dma(const char *owner, unsigned long phy_addr); @@ -119,7 +135,9 @@ int codec_mm_free_for_dma(const char *owner, unsigned long phy_addr); void *codec_mm_phys_to_virt(unsigned long phy_addr); unsigned long codec_mm_virt_to_phys(void *vaddr); -void codec_mm_dma_flush(void *vaddr, int size, enum dma_data_direction dir); +void codec_mm_dma_flush(void *vaddr, + int size, + enum dma_data_direction dir); int codec_mm_get_total_size(void); int codec_mm_get_free_size(void); diff --git a/include/linux/amlogic/media/codec_mm/codec_mm_scatter.h b/include/linux/amlogic/media/codec_mm/codec_mm_scatter.h index 920b237..5e02182 100644 --- a/include/linux/amlogic/media/codec_mm/codec_mm_scatter.h +++ b/include/linux/amlogic/media/codec_mm/codec_mm_scatter.h @@ -34,6 +34,7 @@ #define PAGE_INDEX(page) (page >> PAGE_SHIFT) struct codec_mm_scatter { + void *manager; phy_addr_type *pages_list; int page_max_cnt; int page_cnt; /*page num */ @@ -55,11 +56,12 @@ int codec_mm_scatter_free_tail_pages_fast(struct codec_mm_scatter *mms, int codec_mm_scatter_free_tail_pages_fast(struct codec_mm_scatter *mms, int start_free_id); -struct codec_mm_scatter *codec_mm_scatter_alloc(int max_page, int page_num); +struct codec_mm_scatter *codec_mm_scatter_alloc(int max_page, + int page_num, int istvp); int codec_mm_scatter_alloc_want_pages(struct codec_mm_scatter *mms, int want_pages); int codec_mm_scatter_mgt_delay_free_swith(int on, int delay_ms, - int wait_size_M); + int wait_size_M, int istvp); int codec_mm_dump_scatter(struct codec_mm_scatter *mms, void *buf, int size); int codec_mm_scatter_dec_owner_user(void *sc_mm, int delay_ms); diff --git a/include/linux/amlogic/media/codec_mm/configs.h b/include/linux/amlogic/media/codec_mm/configs.h new file mode 100644 index 0000000..e0147f3 --- /dev/null +++ b/include/linux/amlogic/media/codec_mm/configs.h @@ -0,0 +1,270 @@ +/* + * include/linux/amlogic/media/codec_mm/configs.h + * + * Copyright (C) 2017 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 AMLOGIC_MEDIA_CONFIG_HEADER__ +#define AMLOGIC_MEDIA_CONFIG_HEADER__ + +#include +#include +#include +#include +#include + +#define MAX_DEPTH 8 + +typedef int (*get_fun)(const char *trigger, int id, char *buf, int size); + +typedef int (*set_fun)(const char *trigger, int id, const char *buf, int size); + +struct mconfig { +#define CONFIG_TYPE_PI32 1 +#define CONFIG_TYPE_PU32 2 +#define CONFIG_TYPE_PU64 4 +#define CONFIG_TYPE_PBOOL 5 + +#define CONFIG_TYPE_PSTR 7 +#define CONFIG_TYPE_PCSTR 8 +#define CONFIG_TYPE_I32 21 +#define CONFIG_TYPE_U32 22 +#define CONFIG_TYPE_U64 24 +#define CONFIG_TYPE_BOOL 25 + +#define CONFIG_TYPE_FUN 100 + int type; + int id; + const char *item_name; + union { + void *buf_ptr; + char *str; + const char *cstr; + + int *pival; + u32 *pu32val; + u64 *pu64val; + + int ival; + u32 u32val; + u32 u32mval[2]; + u64 u64val; + bool boolval; + bool *pboolval; + char b[8]; + long ldata[2]; + struct { + get_fun f_get; /*used 0 */ + set_fun f_set; /*used 1 */ + }; + }; + int size; +}; + +struct mconfig_node { + char prefix[MAX_PREFIX_NAME]; + const char *name; + int active; + int depth; + struct mconfig_node *parent_node; + struct list_head list; + int son_node_num; + struct list_head son_node_list; + struct mutex lock; + int configs_num; + struct mconfig *configs; + atomic_t ref_cnt; + /* + *rw_flags: + * CONFIG_FOR_R: support read. + * CONFIG_FOR_W: support write. + * CONFIG_FOR_T: CONFIG FOR TRIGGER; + */ +#define CONFIG_FOR_R 1 +#define CONFIG_FOR_W 2 +#define CONFIG_FOR_T 4 +#define CONFIG_FOR_RW (CONFIG_FOR_R | CONFIG_FOR_W) + int rw_flags; +}; + +#define MC_U32(n, v) \ + {.type = CONFIG_TYPE_U32, .item_name = (n), .u32val = (v)} + +#define MC_I32(n, v) \ + {.type = CONFIG_TYPE_I32, .item_name = (n), .ival = (v)} + +#define MC_U64(n, v) \ + {.type = CONFIG_TYPE_U32, .item_name = (n), .u64val = (v)} +#define MC_BOOL(n, v) \ + {.type = CONFIG_TYPE_BOOL, .item_name = (n), .boolval = (v)} + +#define MC_STR(n, v) \ + {.type = CONFIG_TYPE_PSTR, .item_name = (n), .str = (v)} + +#define MC_CSTR(n, v) \ + {.type = CONFIG_TYPE_PCSTR, .item_name = (n), .cstr = (v)} + +#define MC_PI32(n, v) \ + {.type = CONFIG_TYPE_PI32, .item_name = (n), .pival = (v)} + +#define MC_PU32(n, v) \ + {.type = CONFIG_TYPE_PU32, .item_name = (n), .pu32val = (v)} + +#define MC_PU64(n, v) \ + {.type = CONFIG_TYPE_PU64, .item_name = (n), .pu64val = (v)} + +#define MC_PBOOL(n, v) \ + {.type = CONFIG_TYPE_PBOOL, .item_name = (n), .pboolval = (v)} + +#define MC_FUN(n, fget, fset) \ + {.type = CONFIG_TYPE_FUN, .item_name = (n),\ + .f_get = (fget), .f_set = (fset)} + +#define MC_FUN_ID(n, fget, fset, cid) \ + {.type = CONFIG_TYPE_FUN, .item_name = (n),\ + .f_get = (fget), .f_set = (fset), .id = (cid)} + + +#define REG_CONFIGS(node, configs) \ + configs_register_configs(node, configs,\ + sizeof(configs)/sizeof(struct mconfig)) + +#define REG_PATH_CONFIGS(path, configs) \ + configs_register_path_configs(path, configs,\ + sizeof(configs)/sizeof(struct mconfig)) + +#define INIT_REG_NODE_CONFIGS(prefix, node, name, config, rw)\ + do {\ + configs_init_new_node(node, name, rw);\ + REG_CONFIGS(node, config);\ + configs_register_path_node(prefix, node);\ + } while (0) + +int configs_inc_node_ref(struct mconfig_node *node); +int configs_dec_node_ref(struct mconfig_node *node); + +int configs_init_new_node( + struct mconfig_node *node, const char *name, + int rw_flags); + +int configs_register_node( + struct mconfig_node *parent, + struct mconfig_node *new_node); +int configs_register_path_node( + const char *path, struct mconfig_node *new_node); + +int configs_register_configs( + struct mconfig_node *node, struct mconfig *configs, + int num); +int configs_register_path_configs( + const char *path, struct mconfig *configs, + int num); + +int configs_del_endnode( + struct mconfig_node *parent, struct mconfig_node *node); +int configs_get_node_path_u32( + struct mconfig_node *topnode, const char *path, + u32 *val); +int configs_get_node_path_u64( + struct mconfig_node *topnode, const char *path, + u64 *val); +int configs_get_node_path_2u32( + struct mconfig_node *topnode, const char *path, + u32 *val); +int configs_get_node_path_buf( + struct mconfig_node *topnode, const char *path, + char *buf, int size); +int configs_set_node_path_u32( + struct mconfig_node *topnode, const char *path, + u32 val); +int configs_set_node_path_u64( + struct mconfig_node *topnode, const char *path, + u64 val); +int configs_set_node_path_2u32( + struct mconfig_node *topnode, const char *path, + u32 val1, u32 val2); + +int configs_set_node_path_str( + struct mconfig_node *topnode, const char *path, + const char *val); +int configs_set_node_path_valonpath( + struct mconfig_node *topnode, + const char *path); + +static inline int configs_set_path_str( + const char *path, const char *val) +{ + return configs_set_node_path_str(NULL, path, val); +} + +int configs_set_node_path_str( + struct mconfig_node *topnode, const char *path, + const char *val); + +int configs_set_node_nodepath_str( + struct mconfig_node *topnode, + const char *path, const char *val); + +static inline int configs_set_path_valonpath( + const char *path) +{ + return configs_set_node_path_valonpath(NULL, path); +} + +int configs_set_prefix_path_valonpath( + const char *prfix, const char *pathval); +int configs_set_prefix_path_str( + const char *prfix, const char *path, + const char *str); + +int configs_get_node_path_str( + struct mconfig_node *topnode, const char *path, + char *buf, int size); + +int configs_get_node_nodepath_str( + struct mconfig_node *topnode, + const char *path, char *buf, int size); + +#define LIST_MODE_LIST_RD (CONFIG_FOR_R) +#define LIST_MODE_LIST_WD (CONFIG_FOR_W) +#define LIST_MODE_LIST_RW (LIST_MODE_LIST_RD | LIST_MODE_LIST_WD) +#define LIST_MODE_VAL (1<<8) +#define LIST_MODE_CONFIGS (1<<9) +#define LIST_MODE_CONFIGS_VAL (LIST_MODE_VAL | LIST_MODE_CONFIGS) +#define LIST_MODE_NODE_INFO (1<<10) +#define LIST_MODE_PATH_NODE (1<<11) +#define LIST_MODE_PATH_PREFIX (1<<12) +#define LIST_MODE_PATH_FULLPREFIX (1<<13) +#define LIST_MODE_SUB_NODES (1<<15) + +#define LIST_MODE_NODE_PATH_CONFIGS \ + (LIST_MODE_LIST_RW | LIST_MODE_PATH_PREFIX | LIST_MODE_CONFIGS) +#define LIST_MODE_NODE_CMD_VAL \ + (LIST_MODE_NODE_PATH_CONFIGS | LIST_MODE_VAL) +#define LIST_MODE_NODE_CMD_ALL \ + (LIST_MODE_NODE_CMD_VAL | LIST_MODE_SUB_NODES | LIST_MODE_NODE_INFO) +#define LIST_MODE_NODE_CMDVAL_ALL \ + (LIST_MODE_NODE_CMD_ALL | LIST_MODE_VAL) +#define LIST_MODE_FULL_CMA_ALL \ + (LIST_MODE_NODE_CMD_ALL | LIST_MODE_PATH_FULLPREFIX) +#define LIST_MODE_FULL_CMDVAL_ALL \ + (LIST_MODE_FULL_CMA_ALL | LIST_MODE_VAL) + +int configs_list_node_configs(struct mconfig_node *node, char *buf, int size, + int mode); +int configs_list_nodes(struct mconfig_node *node, char *buf, int size, + int mode); +int configs_list_path_nodes(const char *prefix, char *buf, int size, int mode); + +#endif diff --git a/include/linux/amlogic/media/codec_mm/configs_api.h b/include/linux/amlogic/media/codec_mm/configs_api.h new file mode 100644 index 0000000..0bf44fc --- /dev/null +++ b/include/linux/amlogic/media/codec_mm/configs_api.h @@ -0,0 +1,48 @@ +/* + * include/linux/amlogic/media/codec_mm/configs_api.h + * + * Copyright (C) 2017 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 AMLOGIC_MEDIA_CONFIG_API__ +#define AMLOGIC_MEDIA_CONFIG_API__ +#include +#define MAX_ITEM_NAME 128 +#define MAX_PREFIX_NAME 128 +#define MAX_VALUE_NAME 256 +struct media_config_io_str { + union{ + int subcmd; + int ret; + }; + union { + int para[10]; + char cmd_path[MAX_PREFIX_NAME + MAX_ITEM_NAME + 4]; + }; + union { + char val[MAX_VALUE_NAME]; + char *ptr; + }; +}; + + +#define AML_CONFIG 'C' +#define MEDIA_CONFIG_SET_CMD_STR _IOW((AML_CONFIG), 0x1,\ + struct media_config_io_str) +#define MEDIA_CONFIG_GET_CMD_STR _IOWR((AML_CONFIG), 0x2,\ + struct media_config_io_str) + +#endif + + diff --git a/include/linux/amlogic/media/frame_sync/ptsserv.h b/include/linux/amlogic/media/frame_sync/ptsserv.h index 0e1d74e..1422adc 100644 --- a/include/linux/amlogic/media/frame_sync/ptsserv.h +++ b/include/linux/amlogic/media/frame_sync/ptsserv.h @@ -54,6 +54,8 @@ extern int pts_set_resolution(u8 type, u32 level); extern int pts_set_rec_size(u8 type, u32 val); +extern int pts_get_rec_num(u8 type, u32 val); + extern int pts_start(u8 type); extern int pts_stop(u8 type); diff --git a/include/linux/amlogic/media/frame_sync/tsync.h b/include/linux/amlogic/media/frame_sync/tsync.h index bba553b..1fc9d6c 100644 --- a/include/linux/amlogic/media/frame_sync/tsync.h +++ b/include/linux/amlogic/media/frame_sync/tsync.h @@ -34,7 +34,8 @@ enum avevent_e { AUDIO_RESUME, AUDIO_STOP, AUDIO_TSTAMP_DISCONTINUITY, - AUDIO_PRE_START + AUDIO_PRE_START, + AUDIO_WAIT }; enum tsync_mode_e { diff --git a/include/linux/amlogic/media/registers/register_map.h b/include/linux/amlogic/media/registers/register_map.h index 7999e57..d638fec 100644 --- a/include/linux/amlogic/media/registers/register_map.h +++ b/include/linux/amlogic/media/registers/register_map.h @@ -29,4 +29,12 @@ int codecio_read_vcbus(unsigned int reg); void codecio_write_vcbus(unsigned int reg, unsigned int val); int codecio_read_dmcbus(unsigned int reg); void codecio_write_dmcbus(unsigned int reg, unsigned int val); +int codecio_read_parsbus(unsigned int reg); +void codecio_write_parsbus(unsigned int reg, unsigned int val); +int codecio_read_aiubus(unsigned int reg); +void codecio_write_aiubus(unsigned int reg, unsigned int val); +int codecio_read_demuxbus(unsigned int reg); +void codecio_write_demuxbus(unsigned int reg, unsigned int val); +int codecio_read_resetbus(unsigned int reg); +void codecio_write_resetbus(unsigned int reg, unsigned int val); #endif diff --git a/include/linux/amlogic/media/registers/register_ops.h b/include/linux/amlogic/media/registers/register_ops.h index 3887eb1..23d28a4 100644 --- a/include/linux/amlogic/media/registers/register_ops.h +++ b/include/linux/amlogic/media/registers/register_ops.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,7 @@ enum IO_HEVC_BUS, IO_VPP_BUS, IO_DMC_BUS, + IO_RESET_BUS, BUS_MAX }; @@ -107,5 +109,9 @@ DEF_BUS_OPS(IO_C_BUS, c); DEF_BUS_OPS(IO_VC_BUS, vc); DEF_BUS_OPS(IO_HHI_BUS, hhi); DEF_BUS_OPS(IO_DMC_BUS, dmc); +DEF_BUS_OPS(IO_PARSER_BUS, pars); +DEF_BUS_OPS(IO_AIU_BUS, aiu); +DEF_BUS_OPS(IO_DEMUX_BUS, demux); +DEF_BUS_OPS(IO_RESET_BUS, reset); #endif diff --git a/include/linux/amlogic/media/registers/regs/aiu_regs.h b/include/linux/amlogic/media/registers/regs/aiu_regs.h index 9b6d3ca..90c0924 100644 --- a/include/linux/amlogic/media/registers/regs/aiu_regs.h +++ b/include/linux/amlogic/media/registers/regs/aiu_regs.h @@ -18,6 +18,13 @@ #ifndef _AML_AIU_REGS_H #define _AML_AIU_REGS_H +/* + * pay attention : the regs range has + * changed to 0x14xx in txlx, it was + * converted automatically based on + * the platform at init. + * #define AIU_958_BPF 0x1400 + */ #define AIU_958_BPF 0x1500 #define AIU_958_BRST 0x1501 diff --git a/include/linux/amlogic/media/registers/regs/demux_regs.h b/include/linux/amlogic/media/registers/regs/demux_regs.h index 96e0713..b5dd501 100644 --- a/include/linux/amlogic/media/registers/regs/demux_regs.h +++ b/include/linux/amlogic/media/registers/regs/demux_regs.h @@ -17,6 +17,13 @@ #ifndef DEMUX_REGS_HEADER_ #define DEMUX_REGS_HEADER_ +/* + * pay attention : the regs range has + * changed to 0x18xx in txlx, it was + * converted automatically based on + * the platform at init. + * #define FEC_INPUT_CONTROL 0x1802 + */ #define FEC_INPUT_CONTROL 0x1602 #define FEC_INPUT_CONTROL_2 0x1652 diff --git a/include/linux/amlogic/media/registers/regs/dos_regs.h b/include/linux/amlogic/media/registers/regs/dos_regs.h index a91921e..08411ef 100644 --- a/include/linux/amlogic/media/registers/regs/dos_regs.h +++ b/include/linux/amlogic/media/registers/regs/dos_regs.h @@ -71,6 +71,7 @@ #define MC_CTRL_GCLK_CTRL 0x094d #define MC_OTHER_GCLK_CTRL 0x094e #define MC_CTRL2 0x094f +#define MDEC_PIC_DC_MUX_CTRL 0x98d #define MDEC_PIC_DC_CTRL 0x098e #define MDEC_PIC_DC_STATUS 0x098f #define ANC0_CANVAS_ADDR 0x0990 @@ -154,6 +155,10 @@ #define MDEC_DOUBLEW_CFG6 0x09e1 #define MDEC_DOUBLEW_CFG7 0x09e2 #define MDEC_DOUBLEW_STATUS 0x09e3 +#define MDEC_EXTIF_CFG0 0x09e4 +#define MDEC_EXTIF_CFG1 0x09e5 + + /**/ #define DBLK_RST 0x0950 #define DBLK_CTRL 0x0951 diff --git a/include/linux/amlogic/media/registers/regs/hevc_regs.h b/include/linux/amlogic/media/registers/regs/hevc_regs.h index cd0fdc9..d0423f2 100644 --- a/include/linux/amlogic/media/registers/regs/hevc_regs.h +++ b/include/linux/amlogic/media/registers/regs/hevc_regs.h @@ -285,6 +285,8 @@ #define HEVCD_MPP_ANC_CANVAS_DATA_ADDR 0x34c1 #define HEVCD_MPP_DECOMP_CTL1 0x34c2 #define HEVCD_MPP_DECOMP_CTL2 0x34c3 +#define HEVCD_MPP_DECOMP_PERFMON_CTL 0x34c5 +#define HEVCD_MPP_DECOMP_PERFMON_DATA 0x34c6 #define HEVCD_MCRCC_CTL1 0x34f0 #define HEVCD_MCRCC_CTL2 0x34f1 #define HEVCD_MCRCC_CTL3 0x34f2 diff --git a/include/linux/amlogic/media/registers/regs/parser_regs.h b/include/linux/amlogic/media/registers/regs/parser_regs.h index 532638a..cb0f133 100644 --- a/include/linux/amlogic/media/registers/regs/parser_regs.h +++ b/include/linux/amlogic/media/registers/regs/parser_regs.h @@ -18,6 +18,13 @@ #ifndef PARSER_REGS_HEADER_ #define PARSER_REGS_HEADER_ +/* + * pay attention : the regs range has + * changed to 0x38xx in txlx, it was + * converted automatically based on + * the platform at init. + * #define PARSER_CONTROL 0x3860 + */ #define PARSER_CONTROL 0x2960 #define PARSER_FETCH_ADDR 0x2961 #define PARSER_FETCH_CMD 0x2962 diff --git a/include/linux/amlogic/media/registers/regs/sys_regs.h b/include/linux/amlogic/media/registers/regs/sys_regs.h index 630c162..a68ef52 100644 --- a/include/linux/amlogic/media/registers/regs/sys_regs.h +++ b/include/linux/amlogic/media/registers/regs/sys_regs.h @@ -18,6 +18,14 @@ #ifndef SYS_REGS_HEADER_ #define SYS_REGS_HEADER_ +/* + * pay attention : the regs range has + * changed to 0x04xx in txlx, it was + * converted automatically based on + * the platform at init. + * #define RESET0_REGISTER 0x0401 + */ + #define RESET0_REGISTER 0x1101 #define RESET1_REGISTER 0x1102 #define RESET2_REGISTER 0x1103 diff --git a/include/linux/amlogic/media/registers/regs/vdin_regs.h b/include/linux/amlogic/media/registers/regs/vdin_regs.h index 25b5cde..8b6276c 100644 --- a/include/linux/amlogic/media/registers/regs/vdin_regs.h +++ b/include/linux/amlogic/media/registers/regs/vdin_regs.h @@ -48,6 +48,7 @@ #define VDIN_LFIFO_CTRL 0x121a #define VDIN_COM_GCLK_CTRL 0x121b #define VDIN_INTF_WIDTHM1 0x121c +#define VDIN_LFIFO_URG_CTRL 0x121e #define VDIN_WR_CTRL2 0x121f #define VDIN_WR_CTRL 0x1220 #define VDIN_WR_H_START_END 0x1221 diff --git a/include/linux/amlogic/media/registers/regs/viu_regs.h b/include/linux/amlogic/media/registers/regs/viu_regs.h index 90c8da1..059e2d7 100644 --- a/include/linux/amlogic/media/registers/regs/viu_regs.h +++ b/include/linux/amlogic/media/registers/regs/viu_regs.h @@ -205,5 +205,7 @@ #define VD2_AFBC_PIXEL_VER_SCOPE 0x3190 #define VD2_AFBC_VD_CFMT_H 0x3191 +#define VD2_IF0_GEN_REG3 0x1aa8 + #endif diff --git a/include/linux/amlogic/media/registers/regs/vpp_regs.h b/include/linux/amlogic/media/registers/regs/vpp_regs.h index 39a4764..4b7aed5 100644 --- a/include/linux/amlogic/media/registers/regs/vpp_regs.h +++ b/include/linux/amlogic/media/registers/regs/vpp_regs.h @@ -150,6 +150,7 @@ #define VPP_VE_DEMO_CENTER_BAR 0x1da3 #define VPP_VE_H_V_SIZE 0x1da4 #define VPP_PSR_H_V_SIZE 0x1da5 +#define VPP_OUT_H_V_SIZE 0x1da5 #define VPP_IN_H_V_SIZE 0x1da6 #define VPP_VDO_MEAS_CTRL 0x1da8 #define VPP_VDO_MEAS_VS_COUNT_HI 0x1da9 diff --git a/include/linux/amlogic/media/tvin/tvin.h b/include/linux/amlogic/media/tvin/tvin.h new file mode 100644 index 0000000..cba2613 --- /dev/null +++ b/include/linux/amlogic/media/tvin/tvin.h @@ -0,0 +1,868 @@ +/* + * include/linux/amlogic/media/tvin/tvin.h + * + * Copyright (C) 2017 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 __TVIN_H +#define __TVIN_H + +#include +#include + +enum { + MEMP_VDIN_WITHOUT_3D = 0, + MEMP_VDIN_WITH_3D, + MEMP_DCDR_WITHOUT_3D, + MEMP_DCDR_WITH_3D, + MEMP_ATV_WITHOUT_3D, + MEMP_ATV_WITH_3D, +}; + +/* *********************************************************************** */ +/* * TVIN general definition/enum/struct *********************************** */ +/* ************************************************************************ */ +/* tvin input port select */ +enum tvin_port_e { + TVIN_PORT_NULL = 0x00000000, + TVIN_PORT_MPEG0 = 0x00000100, + TVIN_PORT_BT656 = 0x00000200, + TVIN_PORT_BT601, + TVIN_PORT_CAMERA, + TVIN_PORT_BT656_HDMI, + TVIN_PORT_BT601_HDMI, + TVIN_PORT_VGA0 = 0x00000400, + TVIN_PORT_VGA1, + TVIN_PORT_VGA2, + TVIN_PORT_VGA3, + TVIN_PORT_VGA4, + TVIN_PORT_VGA5, + TVIN_PORT_VGA6, + TVIN_PORT_VGA7, + TVIN_PORT_COMP0 = 0x00000800, + TVIN_PORT_COMP1, + TVIN_PORT_COMP2, + TVIN_PORT_COMP3, + TVIN_PORT_COMP4, + TVIN_PORT_COMP5, + TVIN_PORT_COMP6, + TVIN_PORT_COMP7, + TVIN_PORT_CVBS0 = 0x00001000, + TVIN_PORT_CVBS1, + TVIN_PORT_CVBS2, + TVIN_PORT_CVBS3, + TVIN_PORT_CVBS4, + TVIN_PORT_CVBS5, + TVIN_PORT_CVBS6, + TVIN_PORT_CVBS7, + TVIN_PORT_SVIDEO0 = 0x00002000, + TVIN_PORT_SVIDEO1, + TVIN_PORT_SVIDEO2, + TVIN_PORT_SVIDEO3, + TVIN_PORT_SVIDEO4, + TVIN_PORT_SVIDEO5, + TVIN_PORT_SVIDEO6, + TVIN_PORT_SVIDEO7, + TVIN_PORT_HDMI0 = 0x00004000, + TVIN_PORT_HDMI1, + TVIN_PORT_HDMI2, + TVIN_PORT_HDMI3, + TVIN_PORT_HDMI4, + TVIN_PORT_HDMI5, + TVIN_PORT_HDMI6, + TVIN_PORT_HDMI7, + TVIN_PORT_DVIN0 = 0x00008000, + TVIN_PORT_VIDEO = 0x0000a000, + TVIN_PORT_VIU = 0x0000C000, + TVIN_PORT_MIPI = 0x00010000, + TVIN_PORT_ISP = 0x00020000, + TVIN_PORT_MAX = 0x80000000, +}; + +const char *tvin_port_str(enum tvin_port_e port); + +/* tvin signal format table */ +enum tvin_sig_fmt_e { + TVIN_SIG_FMT_NULL = 0, + /* VGA Formats */ + TVIN_SIG_FMT_VGA_512X384P_60HZ_D147 = 0x001, + TVIN_SIG_FMT_VGA_560X384P_60HZ_D147 = 0x002, + TVIN_SIG_FMT_VGA_640X200P_59HZ_D924 = 0x003, + TVIN_SIG_FMT_VGA_640X350P_85HZ_D080 = 0x004, + TVIN_SIG_FMT_VGA_640X400P_59HZ_D940 = 0x005, + TVIN_SIG_FMT_VGA_640X400P_85HZ_D080 = 0x006, + TVIN_SIG_FMT_VGA_640X400P_59HZ_D638 = 0x007, + TVIN_SIG_FMT_VGA_640X400P_56HZ_D416 = 0x008, + TVIN_SIG_FMT_VGA_640X480P_66HZ_D619 = 0x009, + TVIN_SIG_FMT_VGA_640X480P_66HZ_D667 = 0x00a, + TVIN_SIG_FMT_VGA_640X480P_59HZ_D940 = 0x00b, + TVIN_SIG_FMT_VGA_640X480P_60HZ_D000 = 0x00c, + TVIN_SIG_FMT_VGA_640X480P_72HZ_D809 = 0x00d, + TVIN_SIG_FMT_VGA_640X480P_75HZ_D000_A = 0x00e, + TVIN_SIG_FMT_VGA_640X480P_85HZ_D008 = 0x00f, + TVIN_SIG_FMT_VGA_640X480P_59HZ_D638 = 0x010, + TVIN_SIG_FMT_VGA_640X480P_75HZ_D000_B = 0x011, + TVIN_SIG_FMT_VGA_640X870P_75HZ_D000 = 0x012, + TVIN_SIG_FMT_VGA_720X350P_70HZ_D086 = 0x013, + TVIN_SIG_FMT_VGA_720X400P_85HZ_D039 = 0x014, + TVIN_SIG_FMT_VGA_720X400P_70HZ_D086 = 0x015, + TVIN_SIG_FMT_VGA_720X400P_87HZ_D849 = 0x016, + TVIN_SIG_FMT_VGA_720X400P_59HZ_D940 = 0x017, + TVIN_SIG_FMT_VGA_720X480P_59HZ_D940 = 0x018, + TVIN_SIG_FMT_VGA_768X480P_59HZ_D896 = 0x019, + TVIN_SIG_FMT_VGA_800X600P_56HZ_D250 = 0x01a, + TVIN_SIG_FMT_VGA_800X600P_60HZ_D000 = 0x01b, + TVIN_SIG_FMT_VGA_800X600P_60HZ_D000_A = 0x01c, + TVIN_SIG_FMT_VGA_800X600P_60HZ_D317 = 0x01d, + TVIN_SIG_FMT_VGA_800X600P_72HZ_D188 = 0x01e, + TVIN_SIG_FMT_VGA_800X600P_75HZ_D000 = 0x01f, + TVIN_SIG_FMT_VGA_800X600P_85HZ_D061 = 0x020, + TVIN_SIG_FMT_VGA_832X624P_75HZ_D087 = 0x021, + TVIN_SIG_FMT_VGA_848X480P_84HZ_D751 = 0x022, + TVIN_SIG_FMT_VGA_960X600P_59HZ_D635 = 0x023, + TVIN_SIG_FMT_VGA_1024X768P_59HZ_D278 = 0x024, + TVIN_SIG_FMT_VGA_1024X768P_60HZ_D000 = 0x025, + TVIN_SIG_FMT_VGA_1024X768P_60HZ_D000_A = 0x026, + TVIN_SIG_FMT_VGA_1024X768P_60HZ_D000_B = 0x027, + TVIN_SIG_FMT_VGA_1024X768P_74HZ_D927 = 0x028, + TVIN_SIG_FMT_VGA_1024X768P_60HZ_D004 = 0x029, + TVIN_SIG_FMT_VGA_1024X768P_70HZ_D069 = 0x02a, + TVIN_SIG_FMT_VGA_1024X768P_75HZ_D029 = 0x02b, + TVIN_SIG_FMT_VGA_1024X768P_84HZ_D997 = 0x02c, + TVIN_SIG_FMT_VGA_1024X768P_74HZ_D925 = 0x02d, + TVIN_SIG_FMT_VGA_1024X768P_60HZ_D020 = 0x02e, + TVIN_SIG_FMT_VGA_1024X768P_70HZ_D008 = 0x02f, + TVIN_SIG_FMT_VGA_1024X768P_75HZ_D782 = 0x030, + TVIN_SIG_FMT_VGA_1024X768P_77HZ_D069 = 0x031, + TVIN_SIG_FMT_VGA_1024X768P_71HZ_D799 = 0x032, + TVIN_SIG_FMT_VGA_1024X1024P_60HZ_D000 = 0x033, + TVIN_SIG_FMT_VGA_1152X864P_60HZ_D000 = 0x034, + TVIN_SIG_FMT_VGA_1152X864P_70HZ_D012 = 0x035, + TVIN_SIG_FMT_VGA_1152X864P_75HZ_D000 = 0x036, + TVIN_SIG_FMT_VGA_1152X864P_84HZ_D999 = 0x037, + TVIN_SIG_FMT_VGA_1152X870P_75HZ_D062 = 0x038, + TVIN_SIG_FMT_VGA_1152X900P_65HZ_D950 = 0x039, + TVIN_SIG_FMT_VGA_1152X900P_66HZ_D004 = 0x03a, + TVIN_SIG_FMT_VGA_1152X900P_76HZ_D047 = 0x03b, + TVIN_SIG_FMT_VGA_1152X900P_76HZ_D149 = 0x03c, + TVIN_SIG_FMT_VGA_1280X720P_59HZ_D855 = 0x03d, + TVIN_SIG_FMT_VGA_1280X720P_60HZ_D000_A = 0x03e, + TVIN_SIG_FMT_VGA_1280X720P_60HZ_D000_B = 0x03f, + TVIN_SIG_FMT_VGA_1280X720P_60HZ_D000_C = 0x040, + TVIN_SIG_FMT_VGA_1280X720P_60HZ_D000_D = 0x041, + TVIN_SIG_FMT_VGA_1280X768P_59HZ_D870 = 0x042, + TVIN_SIG_FMT_VGA_1280X768P_59HZ_D995 = 0x043, + TVIN_SIG_FMT_VGA_1280X768P_60HZ_D100 = 0x044, + TVIN_SIG_FMT_VGA_1280X768P_85HZ_D000 = 0x045, + TVIN_SIG_FMT_VGA_1280X768P_74HZ_D893 = 0x046, + TVIN_SIG_FMT_VGA_1280X768P_84HZ_D837 = 0x047, + TVIN_SIG_FMT_VGA_1280X800P_59HZ_D810 = 0x048, + TVIN_SIG_FMT_VGA_1280X800P_59HZ_D810_A = 0x049, + TVIN_SIG_FMT_VGA_1280X800P_60HZ_D000 = 0x04a, + TVIN_SIG_FMT_VGA_1280X800P_85HZ_D000 = 0x04b, + TVIN_SIG_FMT_VGA_1280X960P_60HZ_D000 = 0x04c, + TVIN_SIG_FMT_VGA_1280X960P_60HZ_D000_A = 0x04d, + TVIN_SIG_FMT_VGA_1280X960P_75HZ_D000 = 0x04e, + TVIN_SIG_FMT_VGA_1280X960P_85HZ_D002 = 0x04f, + TVIN_SIG_FMT_VGA_1280X1024P_60HZ_D020 = 0x050, + TVIN_SIG_FMT_VGA_1280X1024P_60HZ_D020_A = 0x051, + TVIN_SIG_FMT_VGA_1280X1024P_75HZ_D025 = 0x052, + TVIN_SIG_FMT_VGA_1280X1024P_85HZ_D024 = 0x053, + TVIN_SIG_FMT_VGA_1280X1024P_59HZ_D979 = 0x054, + TVIN_SIG_FMT_VGA_1280X1024P_72HZ_D005 = 0x055, + TVIN_SIG_FMT_VGA_1280X1024P_60HZ_D002 = 0x056, + TVIN_SIG_FMT_VGA_1280X1024P_67HZ_D003 = 0x057, + TVIN_SIG_FMT_VGA_1280X1024P_74HZ_D112 = 0x058, + TVIN_SIG_FMT_VGA_1280X1024P_76HZ_D179 = 0x059, + TVIN_SIG_FMT_VGA_1280X1024P_66HZ_D718 = 0x05a, + TVIN_SIG_FMT_VGA_1280X1024P_66HZ_D677 = 0x05b, + TVIN_SIG_FMT_VGA_1280X1024P_76HZ_D107 = 0x05c, + TVIN_SIG_FMT_VGA_1280X1024P_59HZ_D996 = 0x05d, + TVIN_SIG_FMT_VGA_1280X1024P_60HZ_D000 = 0x05e, + TVIN_SIG_FMT_VGA_1360X768P_59HZ_D799 = 0x05f, + TVIN_SIG_FMT_VGA_1360X768P_60HZ_D015 = 0x060, + TVIN_SIG_FMT_VGA_1360X768P_60HZ_D015_A = 0x061, + TVIN_SIG_FMT_VGA_1360X850P_60HZ_D000 = 0x062, + TVIN_SIG_FMT_VGA_1360X1024P_60HZ_D000 = 0x063, + TVIN_SIG_FMT_VGA_1366X768P_59HZ_D790 = 0x064, + TVIN_SIG_FMT_VGA_1366X768P_60HZ_D000 = 0x065, + TVIN_SIG_FMT_VGA_1400X1050P_59HZ_D978 = 0x066, + TVIN_SIG_FMT_VGA_1440X900P_59HZ_D887 = 0x067, + TVIN_SIG_FMT_VGA_1440X1080P_60HZ_D000 = 0x068, + TVIN_SIG_FMT_VGA_1600X900P_60HZ_D000 = 0x069, + TVIN_SIG_FMT_VGA_1600X1024P_60HZ_D000 = 0x06a, + TVIN_SIG_FMT_VGA_1600X1200P_59HZ_D869 = 0x06b, + TVIN_SIG_FMT_VGA_1600X1200P_60HZ_D000 = 0x06c, + TVIN_SIG_FMT_VGA_1600X1200P_65HZ_D000 = 0x06d, + TVIN_SIG_FMT_VGA_1600X1200P_70HZ_D000 = 0x06e, + TVIN_SIG_FMT_VGA_1680X1050P_59HZ_D954 = 0x06f, + TVIN_SIG_FMT_VGA_1680X1080P_60HZ_D000 = 0x070, + TVIN_SIG_FMT_VGA_1920X1080P_49HZ_D929 = 0x071, + TVIN_SIG_FMT_VGA_1920X1080P_59HZ_D963_A = 0x072, + TVIN_SIG_FMT_VGA_1920X1080P_59HZ_D963 = 0x073, + TVIN_SIG_FMT_VGA_1920X1080P_60HZ_D000 = 0x074, + TVIN_SIG_FMT_VGA_1920X1200P_59HZ_D950 = 0x075, + TVIN_SIG_FMT_VGA_1024X768P_60HZ_D000_C = 0x076, + TVIN_SIG_FMT_VGA_1024X768P_60HZ_D000_D = 0x077, + TVIN_SIG_FMT_VGA_1920X1200P_59HZ_D988 = 0x078, + TVIN_SIG_FMT_VGA_1400X900P_60HZ_D000 = 0x079, + TVIN_SIG_FMT_VGA_1680X1050P_60HZ_D000 = 0x07a, + TVIN_SIG_FMT_VGA_800X600P_60HZ_D062 = 0x07b, + TVIN_SIG_FMT_VGA_800X600P_60HZ_317_B = 0x07c, + TVIN_SIG_FMT_VGA_RESERVE8 = 0x07d, + TVIN_SIG_FMT_VGA_RESERVE9 = 0x07e, + TVIN_SIG_FMT_VGA_RESERVE10 = 0x07f, + TVIN_SIG_FMT_VGA_RESERVE11 = 0x080, + TVIN_SIG_FMT_VGA_RESERVE12 = 0x081, + TVIN_SIG_FMT_VGA_MAX = 0x082, + TVIN_SIG_FMT_VGA_THRESHOLD = 0x200, + /* Component Formats */ + TVIN_SIG_FMT_COMP_480P_60HZ_D000 = 0x201, + TVIN_SIG_FMT_COMP_480I_59HZ_D940 = 0x202, + TVIN_SIG_FMT_COMP_576P_50HZ_D000 = 0x203, + TVIN_SIG_FMT_COMP_576I_50HZ_D000 = 0x204, + TVIN_SIG_FMT_COMP_720P_59HZ_D940 = 0x205, + TVIN_SIG_FMT_COMP_720P_50HZ_D000 = 0x206, + TVIN_SIG_FMT_COMP_1080P_23HZ_D976 = 0x207, + TVIN_SIG_FMT_COMP_1080P_24HZ_D000 = 0x208, + TVIN_SIG_FMT_COMP_1080P_25HZ_D000 = 0x209, + TVIN_SIG_FMT_COMP_1080P_30HZ_D000 = 0x20a, + TVIN_SIG_FMT_COMP_1080P_50HZ_D000 = 0x20b, + TVIN_SIG_FMT_COMP_1080P_60HZ_D000 = 0x20c, + TVIN_SIG_FMT_COMP_1080I_47HZ_D952 = 0x20d, + TVIN_SIG_FMT_COMP_1080I_48HZ_D000 = 0x20e, + TVIN_SIG_FMT_COMP_1080I_50HZ_D000_A = 0x20f, + TVIN_SIG_FMT_COMP_1080I_50HZ_D000_B = 0x210, + TVIN_SIG_FMT_COMP_1080I_50HZ_D000_C = 0x211, + TVIN_SIG_FMT_COMP_1080I_60HZ_D000 = 0x212, + TVIN_SIG_FMT_COMP_MAX = 0x213, + TVIN_SIG_FMT_COMP_THRESHOLD = 0x400, + /* HDMI Formats */ + TVIN_SIG_FMT_HDMI_640X480P_60HZ = 0x401, + TVIN_SIG_FMT_HDMI_720X480P_60HZ = 0x402, + TVIN_SIG_FMT_HDMI_1280X720P_60HZ = 0x403, + TVIN_SIG_FMT_HDMI_1920X1080I_60HZ = 0x404, + TVIN_SIG_FMT_HDMI_1440X480I_60HZ = 0x405, + TVIN_SIG_FMT_HDMI_1440X240P_60HZ = 0x406, + TVIN_SIG_FMT_HDMI_2880X480I_60HZ = 0x407, + TVIN_SIG_FMT_HDMI_2880X240P_60HZ = 0x408, + TVIN_SIG_FMT_HDMI_1440X480P_60HZ = 0x409, + TVIN_SIG_FMT_HDMI_1920X1080P_60HZ = 0x40a, + TVIN_SIG_FMT_HDMI_720X576P_50HZ = 0x40b, + TVIN_SIG_FMT_HDMI_1280X720P_50HZ = 0x40c, + TVIN_SIG_FMT_HDMI_1920X1080I_50HZ_A = 0x40d, + TVIN_SIG_FMT_HDMI_1440X576I_50HZ = 0x40e, + TVIN_SIG_FMT_HDMI_1440X288P_50HZ = 0x40f, + TVIN_SIG_FMT_HDMI_2880X576I_50HZ = 0x410, + TVIN_SIG_FMT_HDMI_2880X288P_50HZ = 0x411, + TVIN_SIG_FMT_HDMI_1440X576P_50HZ = 0x412, + TVIN_SIG_FMT_HDMI_1920X1080P_50HZ = 0x413, + TVIN_SIG_FMT_HDMI_1920X1080P_24HZ = 0x414, + TVIN_SIG_FMT_HDMI_1920X1080P_25HZ = 0x415, + TVIN_SIG_FMT_HDMI_1920X1080P_30HZ = 0x416, + TVIN_SIG_FMT_HDMI_2880X480P_60HZ = 0x417, + TVIN_SIG_FMT_HDMI_2880X576P_50HZ = 0x418, + TVIN_SIG_FMT_HDMI_1920X1080I_50HZ_B = 0x419, + TVIN_SIG_FMT_HDMI_1920X1080I_100HZ = 0x41a, + TVIN_SIG_FMT_HDMI_1280X720P_100HZ = 0x41b, + TVIN_SIG_FMT_HDMI_720X576P_100HZ = 0x41c, + TVIN_SIG_FMT_HDMI_1440X576I_100HZ = 0x41d, + TVIN_SIG_FMT_HDMI_1920X1080I_120HZ = 0x41e, + TVIN_SIG_FMT_HDMI_1280X720P_120HZ = 0x41f, + TVIN_SIG_FMT_HDMI_720X480P_120HZ = 0x420, + TVIN_SIG_FMT_HDMI_1440X480I_120HZ = 0x421, + TVIN_SIG_FMT_HDMI_720X576P_200HZ = 0x422, + TVIN_SIG_FMT_HDMI_1440X576I_200HZ = 0x423, + TVIN_SIG_FMT_HDMI_720X480P_240HZ = 0x424, + TVIN_SIG_FMT_HDMI_1440X480I_240HZ = 0x425, + TVIN_SIG_FMT_HDMI_1280X720P_24HZ = 0x426, + TVIN_SIG_FMT_HDMI_1280X720P_25HZ = 0x427, + TVIN_SIG_FMT_HDMI_1280X720P_30HZ = 0x428, + TVIN_SIG_FMT_HDMI_1920X1080P_120HZ = 0x429, + TVIN_SIG_FMT_HDMI_1920X1080P_100HZ = 0x42a, + TVIN_SIG_FMT_HDMI_1280X720P_60HZ_FRAME_PACKING = 0x42b, + TVIN_SIG_FMT_HDMI_1280X720P_50HZ_FRAME_PACKING = 0x42c, + TVIN_SIG_FMT_HDMI_1280X720P_24HZ_FRAME_PACKING = 0x42d, + TVIN_SIG_FMT_HDMI_1280X720P_30HZ_FRAME_PACKING = 0x42e, + TVIN_SIG_FMT_HDMI_1920X1080I_60HZ_FRAME_PACKING = 0x42f, + TVIN_SIG_FMT_HDMI_1920X1080I_50HZ_FRAME_PACKING = 0x430, + TVIN_SIG_FMT_HDMI_1920X1080P_24HZ_FRAME_PACKING = 0x431, + TVIN_SIG_FMT_HDMI_1920X1080P_30HZ_FRAME_PACKING = 0x432, + TVIN_SIG_FMT_HDMI_800X600_00HZ = 0x433, + TVIN_SIG_FMT_HDMI_1024X768_00HZ = 0x434, + TVIN_SIG_FMT_HDMI_720X400_00HZ = 0x435, + TVIN_SIG_FMT_HDMI_1280X768_00HZ = 0x436, + TVIN_SIG_FMT_HDMI_1280X800_00HZ = 0x437, + TVIN_SIG_FMT_HDMI_1280X960_00HZ = 0x438, + TVIN_SIG_FMT_HDMI_1280X1024_00HZ = 0x439, + TVIN_SIG_FMT_HDMI_1360X768_00HZ = 0x43a, + TVIN_SIG_FMT_HDMI_1366X768_00HZ = 0x43b, + TVIN_SIG_FMT_HDMI_1600X1200_00HZ = 0x43c, + TVIN_SIG_FMT_HDMI_1920X1200_00HZ = 0x43d, + TVIN_SIG_FMT_HDMI_1440X900_00HZ = 0x43e, + TVIN_SIG_FMT_HDMI_1400X1050_00HZ = 0x43f, + TVIN_SIG_FMT_HDMI_1680X1050_00HZ = 0x440, + /* for alternative and 4k2k */ + TVIN_SIG_FMT_HDMI_1920X1080I_60HZ_ALTERNATIVE = 0x441, + TVIN_SIG_FMT_HDMI_1920X1080I_50HZ_ALTERNATIVE = 0x442, + TVIN_SIG_FMT_HDMI_1920X1080P_24HZ_ALTERNATIVE = 0x443, + TVIN_SIG_FMT_HDMI_1920X1080P_30HZ_ALTERNATIVE = 0x444, + TVIN_SIG_FMT_HDMI_3840_2160_00HZ = 0x445, + TVIN_SIG_FMT_HDMI_4096_2160_00HZ = 0x446, + TVIN_SIG_FMT_HDMI_1600X900_60HZ = 0x447, + TVIN_SIG_FMT_HDMI_RESERVE8 = 0x448, + TVIN_SIG_FMT_HDMI_RESERVE9 = 0x449, + TVIN_SIG_FMT_HDMI_RESERVE10 = 0x44a, + TVIN_SIG_FMT_HDMI_RESERVE11 = 0x44b, + TVIN_SIG_FMT_HDMI_720X480P_60HZ_FRAME_PACKING = 0x44c, + TVIN_SIG_FMT_HDMI_720X576P_50HZ_FRAME_PACKING = 0x44d, + TVIN_SIG_FMT_HDMI_640X480P_72HZ = 0x44e, + TVIN_SIG_FMT_HDMI_640X480P_75HZ = 0x44f, + TVIN_SIG_FMT_HDMI_MAX = 0x450, + TVIN_SIG_FMT_HDMI_THRESHOLD = 0x600, + /* Video Formats */ + TVIN_SIG_FMT_CVBS_NTSC_M = 0x601, + TVIN_SIG_FMT_CVBS_NTSC_443 = 0x602, + TVIN_SIG_FMT_CVBS_PAL_I = 0x603, + TVIN_SIG_FMT_CVBS_PAL_M = 0x604, + TVIN_SIG_FMT_CVBS_PAL_60 = 0x605, + TVIN_SIG_FMT_CVBS_PAL_CN = 0x606, + TVIN_SIG_FMT_CVBS_SECAM = 0x607, + TVIN_SIG_FMT_CVBS_NTSC_50 = 0x608, + TVIN_SIG_FMT_CVBS_MAX = 0x609, + TVIN_SIG_FMT_CVBS_THRESHOLD = 0x800, + /* 656 Formats */ + TVIN_SIG_FMT_BT656IN_576I_50HZ = 0x801, + TVIN_SIG_FMT_BT656IN_480I_60HZ = 0x802, + /* 601 Formats */ + TVIN_SIG_FMT_BT601IN_576I_50HZ = 0x803, + TVIN_SIG_FMT_BT601IN_480I_60HZ = 0x804, + /* Camera Formats */ + TVIN_SIG_FMT_CAMERA_640X480P_30HZ = 0x805, + TVIN_SIG_FMT_CAMERA_800X600P_30HZ = 0x806, + TVIN_SIG_FMT_CAMERA_1024X768P_30HZ = 0x807, + TVIN_SIG_FMT_CAMERA_1920X1080P_30HZ = 0x808, + TVIN_SIG_FMT_CAMERA_1280X720P_30HZ = 0x809, + TVIN_SIG_FMT_BT601_MAX = 0x80a, + TVIN_SIG_FMT_BT601_THRESHOLD = 0xa00, + TVIN_SIG_FMT_MAX, +}; + +/* tvin signal status */ +enum tvin_sig_status_e { + TVIN_SIG_STATUS_NULL = 0, +/* processing status from init to the finding of the 1st confirmed status */ + + TVIN_SIG_STATUS_NOSIG, /* no signal - physically no signal */ + TVIN_SIG_STATUS_UNSTABLE, /* unstable - physically bad signal */ + TVIN_SIG_STATUS_NOTSUP, +/* not supported - physically good signal & not supported */ + + TVIN_SIG_STATUS_STABLE, +/* stable - physically good signal & supported */ +}; + +const char *tvin_sig_status_str(enum tvin_sig_status_e status); + +/* tvin parameters */ +#define TVIN_PARM_FLAG_CAP 0x00000001 +/* tvin_parm_t.flag[ 0]: 1/enable or 0/disable frame capture function */ + +#define TVIN_PARM_FLAG_CAL 0x00000002 +/* tvin_parm_t.flag[ 1]: 1/enable or 0/disable adc calibration */ + + +/*used for processing 3d in ppmgr set this flag*/ +/*to drop one field and send real height in vframe*/ +#define TVIN_PARM_FLAG_2D_TO_3D 0x00000004 +/* tvin_parm_t.flag[ 2]: 1/enable or 0/disable 2D->3D mode */ + +enum tvin_trans_fmt { + TVIN_TFMT_2D = 0, + TVIN_TFMT_3D_LRH_OLOR, +/* 1 Primary: Side-by-Side(Half) Odd/Left picture, Odd/Right p */ + + TVIN_TFMT_3D_LRH_OLER, +/* 2 Primary: Side-by-Side(Half) Odd/Left picture, Even/Right picture */ + + TVIN_TFMT_3D_LRH_ELOR, +/* 3 Primary: Side-by-Side(Half) Even/Left picture, Odd/Right picture */ + + TVIN_TFMT_3D_LRH_ELER, +/* 4 Primary: Side-by-Side(Half) Even/Left picture, Even/Right picture */ + + TVIN_TFMT_3D_TB, /* 5 Primary: Top-and-Bottom */ + TVIN_TFMT_3D_FP, /* 6 Primary: Frame Packing */ + TVIN_TFMT_3D_FA, /* 7 Secondary: Field Alternative */ + TVIN_TFMT_3D_LA, /* 8 Secondary: Line Alternative */ + TVIN_TFMT_3D_LRF, /* 9 Secondary: Side-by-Side(Full) */ + TVIN_TFMT_3D_LD, /* 10 Secondary: L+depth */ + TVIN_TFMT_3D_LDGD,/* 11 Secondary: L+depth+Graphics+Graphics-depth */ + /* normal 3D format */ + TVIN_TFMT_3D_DET_TB, /* 12 */ + TVIN_TFMT_3D_DET_LR, /* 13 */ + TVIN_TFMT_3D_DET_INTERLACE, /* 14 */ + TVIN_TFMT_3D_DET_CHESSBOARD, /* 15 */ +}; + +const char *tvin_trans_fmt_str(enum tvin_trans_fmt trans_fmt); + +enum tvin_color_fmt_e { + TVIN_RGB444 = 0, + TVIN_YUV422, /* 1 */ + TVIN_YUV444, /* 2 */ + TVIN_YUYV422, /* 3 */ + TVIN_YVYU422, /* 4 */ + TVIN_UYVY422, /* 5 */ + TVIN_VYUY422, /* 6 */ + TVIN_NV12, /* 7 */ + TVIN_NV21, /* 8 */ + TVIN_BGGR, /* 9 raw data */ + TVIN_RGGB, /* 10 raw data */ + TVIN_GBRG, /* 11 raw data */ + TVIN_GRBG, /* 12 raw data */ + TVIN_COLOR_FMT_MAX, +}; + +enum tvin_color_fmt_range_e { + TVIN_FMT_RANGE_NULL = 0, /* depend on vedio fromat */ + TVIN_RGB_FULL, /* 1 */ + TVIN_RGB_LIMIT, /* 2 */ + TVIN_YUV_FULL, /* 3 */ + TVIN_YUV_LIMIT, /* 4 */ + TVIN_COLOR_FMT_RANGE_MAX, +}; + +const char *tvin_color_fmt_str(enum tvin_color_fmt_e color_fmt); +enum tvin_scan_mode_e { + TVIN_SCAN_MODE_NULL = 0, + TVIN_SCAN_MODE_PROGRESSIVE, + TVIN_SCAN_MODE_INTERLACED, +}; + +struct tvin_info_s { + enum tvin_trans_fmt trans_fmt; + enum tvin_sig_fmt_e fmt; + enum tvin_sig_status_e status; + enum tvin_color_fmt_e cfmt; + unsigned int fps; + unsigned int reserved; +}; + +struct tvin_buf_info_s { + unsigned int vf_size; + unsigned int buf_count; + unsigned int buf_width; + unsigned int buf_height; + unsigned int buf_size; + unsigned int wr_list_size; +}; + +struct tvin_video_buf_s { + unsigned int index; + unsigned int reserved; +}; + +/* hs=he=vs=ve=0 is to disable Cut Window */ +struct tvin_cutwin_s { + unsigned short hs; + unsigned short he; + unsigned short vs; + unsigned short ve; +}; + +struct tvin_parm_s { + int index; /* index of frontend for vdin */ + enum tvin_port_e port; /* must set port in IOCTL */ + struct tvin_info_s info; + unsigned int hist_pow; + unsigned int luma_sum; + unsigned int pixel_sum; + unsigned short histgram[64]; + unsigned int flag; + unsigned short dest_width; /* for vdin horizontal scale down */ + unsigned short dest_height; /* for vdin vertical scale down */ + bool h_reverse; /* for vdin horizontal reverse */ + bool v_reverse; /* for vdin vertical reverse */ + unsigned int reserved; +}; + +/* ************************************************************************* */ +/* *** AFE module definition/enum/struct *********************************** */ +/* ************************************************************************* */ +#if 0 +enum tvafe_cmd_status_e { + /* idle, be ready for TVIN_IOC_S_AFE_VGA_AUTO command */ + TVAFE_CMD_STATUS_IDLE = 0, + /* TVIN_IOC_S_AFE_VGA_AUTO command is in process */ + TVAFE_CMD_STATUS_PROCESSING, + /* TVIN_IOC_S_AFE_VGA_AUTO command is done with success */ + TVAFE_CMD_STATUS_SUCCESSFUL, + /* TVIN_IOC_S_AFE_VGA_AUTO command is done with failure */ + TVAFE_CMD_STATUS_FAILED, + /* TVIN_IOC_S_AFE_VGA_AUTO command is terminated by others related */ + TVAFE_CMD_STATUS_TERMINATED, +}; + +struct tvafe_vga_edid_s { + unsigned char value[256]; /* 256 byte EDID */ +}; + +struct tvafe_comp_wss_s { + unsigned int wss1[5]; + unsigned int wss2[5]; +}; +#endif +struct tvafe_vga_parm_s { + signed short clk_step; /* clock < 0, tune down clock freq */ + /* clock > 0, tune up clock freq */ + unsigned short phase; /* phase is 0~31, it is absolute value */ + signed short hpos_step; /* hpos_step < 0, shift display to left */ + /* hpos_step > 0, shift display to right */ + signed short vpos_step; /* vpos_step < 0, shift display to top */ + /* vpos_step > 0, shift display to bottom */ + unsigned int vga_in_clean; /* flage for vga clean screen */ +}; +#if 0 +#define TVAFE_ADC_CAL_VALID 0x00000001 +struct tvafe_adc_cal_s { + /* ADC A */ + unsigned short a_analog_clamp; /* 0x00~0x7f */ + unsigned short a_analog_gain; /* 0x00~0xff, means 0dB~6dB */ + unsigned short a_digital_offset1; /* offset for fine-tuning */ + /* s11.0: signed value, 11 integer bits, 0 fraction bits */ + unsigned short a_digital_gain; /* 0~3.999 */ + /* u2.10: unsigned value, 2 integer bits, 10 fraction bits */ + unsigned short a_digital_offset2; /* offset for format */ + /* s11.0: signed value, 11 integer bits, 0 fraction bits */ + /* ADC B */ + unsigned short b_analog_clamp; /* ditto to ADC A */ + unsigned short b_analog_gain; + unsigned short b_digital_offset1; + unsigned short b_digital_gain; + unsigned short b_digital_offset2; + /* ADC C */ + unsigned short c_analog_clamp; /* ditto to ADC A */ + unsigned short c_analog_gain; + unsigned short c_digital_offset1; + unsigned short c_digital_gain; + unsigned short c_digital_offset2; + /* ADC D */ + unsigned short d_analog_clamp; /* ditto to ADC A */ + unsigned short d_analog_gain; + unsigned short d_digital_offset1; + unsigned short d_digital_gain; + unsigned short d_digital_offset2; + unsigned int reserved; /* bit[ 0]: TVAFE_ADC_CAL_VALID */ +}; + +struct tvafe_adc_cal_clamp_s { + short a_analog_clamp_diff; + short b_analog_clamp_diff; + short c_analog_clamp_diff; +}; + +struct tvafe_adc_comp_cal_s { + struct tvafe_adc_cal_s comp_cal_val[3]; +}; +#endif +enum tvafe_cvbs_video_e { + TVAFE_CVBS_VIDEO_HV_UNLOCKED = 0, + TVAFE_CVBS_VIDEO_H_LOCKED, + TVAFE_CVBS_VIDEO_V_LOCKED, + TVAFE_CVBS_VIDEO_HV_LOCKED, +}; + +/* for pin selection */ +enum tvafe_adc_pin_e { + TVAFE_ADC_PIN_NULL = 0, + /* TODO Only M8 first */ + /*(MESON_CPU_TYPE > MESON_CPU_TYPE_MESONG9TV)*/ + TVAFE_CVBS_IN0 = 1, + TVAFE_CVBS_IN1 = 2, + TVAFE_CVBS_IN2 = 3, + TVAFE_CVBS_IN3 = 4,/*as atvdemod to tvafe*/ + /*for (MESON_CPU_TYPE < MESON_CPU_TYPE_MESONG9TV)*/ + TVAFE_ADC_PIN_A_PGA_0 = 1, + TVAFE_ADC_PIN_A_PGA_1 = 2, + TVAFE_ADC_PIN_A_PGA_2 = 3, + TVAFE_ADC_PIN_A_PGA_3 = 4, + TVAFE_ADC_PIN_A_PGA_4 = 5, + TVAFE_ADC_PIN_A_PGA_5 = 6, + TVAFE_ADC_PIN_A_PGA_6 = 7, + TVAFE_ADC_PIN_A_PGA_7 = 8, + TVAFE_ADC_PIN_A_0 = 9, + TVAFE_ADC_PIN_A_1 = 10, + TVAFE_ADC_PIN_A_2 = 11, + TVAFE_ADC_PIN_A_3 = 12, + TVAFE_ADC_PIN_A_4 = 13, + TVAFE_ADC_PIN_A_5 = 14, + TVAFE_ADC_PIN_A_6 = 15, + TVAFE_ADC_PIN_A_7 = 16, + TVAFE_ADC_PIN_B_0 = 17, + TVAFE_ADC_PIN_B_1 = 18, + TVAFE_ADC_PIN_B_2 = 19, + TVAFE_ADC_PIN_B_3 = 20, + TVAFE_ADC_PIN_B_4 = 21, + TVAFE_ADC_PIN_B_5 = 22, + TVAFE_ADC_PIN_B_6 = 23, + TVAFE_ADC_PIN_B_7 = 24, + TVAFE_ADC_PIN_C_0 = 25, + TVAFE_ADC_PIN_C_1 = 26, + TVAFE_ADC_PIN_C_2 = 27, + TVAFE_ADC_PIN_C_3 = 28, + TVAFE_ADC_PIN_C_4 = 29, + TVAFE_ADC_PIN_C_5 = 30, + TVAFE_ADC_PIN_C_6 = 31, + TVAFE_ADC_PIN_C_7 = 32, + TVAFE_ADC_PIN_D_0 = 33, + TVAFE_ADC_PIN_D_1 = 34, + TVAFE_ADC_PIN_D_2 = 35, + TVAFE_ADC_PIN_D_3 = 36, + TVAFE_ADC_PIN_D_4 = 37, + TVAFE_ADC_PIN_D_5 = 38, + TVAFE_ADC_PIN_D_6 = 39, + TVAFE_ADC_PIN_D_7 = 40, + TVAFE_ADC_PIN_SOG_0 = 41, + TVAFE_ADC_PIN_SOG_1 = 42, + TVAFE_ADC_PIN_SOG_2 = 43, + TVAFE_ADC_PIN_SOG_3 = 44, + TVAFE_ADC_PIN_SOG_4 = 45, + TVAFE_ADC_PIN_SOG_5 = 46, + TVAFE_ADC_PIN_SOG_6 = 47, + TVAFE_ADC_PIN_SOG_7 = 48, + TVAFE_ADC_PIN_MAX, +}; + +enum tvafe_src_sig_e { + /* TODO Only M8 first */ + +/*#if (MESON_CPU_TYPE == MESON_CPU_TYPE_MESONG9TV)*/ + CVBS_IN0 = 0, + CVBS_IN1, + CVBS_IN2, + CVBS_IN3, +#if 0 + /*m6tv*/ + CVBS0_Y = 0, + CVBS0_SOG, + CVBS1_Y, + CVBS1_SOG, + CVBS2_Y, + CVBS2_SOG, + CVBS3_Y, + CVBS3_SOG, + CVBS4_Y, + CVBS4_SOG, + CVBS5_Y, + CVBS5_SOG, + CVBS6_Y, + CVBS6_SOG, + CVBS7_Y, + CVBS7_SOG, + S_VIDEO0_Y, + S_VIDEO0_C, + S_VIDEO0_SOG, + S_VIDEO1_Y, + S_VIDEO1_C, + S_VIDEO1_SOG, + S_VIDEO2_Y, + S_VIDEO2_C, + S_VIDEO2_SOG, + S_VIDEO3_Y, + S_VIDEO3_C, + S_VIDEO3_SOG, + S_VIDEO4_Y, + S_VIDEO4_C, + S_VIDEO4_SOG, + S_VIDEO5_Y, + S_VIDEO5_C, + S_VIDEO5_SOG, + S_VIDEO6_Y, + S_VIDEO6_C, + S_VIDEO6_SOG, + S_VIDEO7_Y, + S_VIDEO7_C, + S_VIDEO7_SOG, + VGA0_G, + VGA0_B, + VGA0_R, + VGA0_SOG, + VGA1_G, + VGA1_B, + VGA1_R, + VGA1_SOG, + VGA2_G, + VGA2_B, + VGA2_R, + VGA2_SOG, + VGA3_G, + VGA3_B, + VGA3_R, + VGA3_SOG, + VGA4_G, + VGA4_B, + VGA4_R, + VGA4_SOG, + VGA5_G, + VGA5_B, + VGA5_R, + VGA5_SOG, + VGA6_G, + VGA6_B, + VGA6_R, + VGA6_SOG, + VGA7_G, + VGA7_B, + VGA7_R, + VGA7_SOG, + COMP0_Y, + COMP0_PB, + COMP0_PR, + COMP0_SOG, + COMP1_Y, + COMP1_PB, + COMP1_PR, + COMP1_SOG, + COMP2_Y, + COMP2_PB, + COMP2_PR, + COMP2_SOG, + COMP3_Y, + COMP3_PB, + COMP3_PR, + COMP3_SOG, + COMP4_Y, + COMP4_PB, + COMP4_PR, + COMP4_SOG, + COMP5_Y, + COMP5_PB, + COMP5_PR, + COMP5_SOG, + COMP6_Y, + COMP6_PB, + COMP6_PR, + COMP6_SOG, + COMP7_Y, + COMP7_PB, + COMP7_PR, + COMP7_SOG, + SCART0_G, + SCART0_B, + SCART0_R, + SCART0_CVBS, + SCART1_G, + SCART1_B, + SCART1_R, + SCART1_CVBS, + SCART2_G, + SCART2_B, + SCART2_R, + SCART2_CVBS, + SCART3_G, + SCART3_B, + SCART3_R, + SCART3_CVBS, + SCART4_G, + SCART4_B, + SCART4_R, + SCART4_CVBS, + SCART5_G, + SCART5_B, + SCART5_R, + SCART5_CVBS, + SCART6_G, + SCART6_B, + SCART6_R, + SCART6_CVBS, + SCART7_G, + SCART7_B, + SCART7_R, + SCART7_CVBS, +#endif + TVAFE_SRC_SIG_MAX_NUM, +}; + +struct tvafe_pin_mux_s { + enum tvafe_adc_pin_e pin[TVAFE_SRC_SIG_MAX_NUM]; +}; + +/* ************************************************************************* */ +/* *** IOCTL command definition ******************************************* */ +/* ************************************************************************* */ + +#define _TM_T 'T' + +/* GENERAL */ +#define TVIN_IOC_OPEN _IOW(_TM_T, 0x01, struct tvin_parm_s) +#define TVIN_IOC_START_DEC _IOW(_TM_T, 0x02, struct tvin_parm_s) +#define TVIN_IOC_STOP_DEC _IO(_TM_T, 0x03) +#define TVIN_IOC_CLOSE _IO(_TM_T, 0x04) +#define TVIN_IOC_G_PARM _IOR(_TM_T, 0x05, struct tvin_parm_s) +#define TVIN_IOC_S_PARM _IOW(_TM_T, 0x06, struct tvin_parm_s) +#define TVIN_IOC_G_SIG_INFO _IOR(_TM_T, 0x07, struct tvin_info_s) +#define TVIN_IOC_G_BUF_INFO _IOR(_TM_T, 0x08, struct tvin_buf_info_s) +#define TVIN_IOC_START_GET_BUF _IO(_TM_T, 0x09) +#define TVIN_IOC_GET_BUF _IOR(_TM_T, 0x10, struct tvin_video_buf_s) +#define TVIN_IOC_PAUSE_DEC _IO(_TM_T, 0x41) +#define TVIN_IOC_RESUME_DEC _IO(_TM_T, 0x42) +#define TVIN_IOC_VF_REG _IO(_TM_T, 0x43) +#define TVIN_IOC_VF_UNREG _IO(_TM_T, 0x44) +#define TVIN_IOC_FREEZE_VF _IO(_TM_T, 0x45) +#define TVIN_IOC_UNFREEZE_VF _IO(_TM_T, 0x46) +#define TVIN_IOC_SNOWON _IO(_TM_T, 0x47) +#define TVIN_IOC_SNOWOFF _IO(_TM_T, 0x48) + +/* TVAFE */ +#if 0 +#define TVIN_IOC_S_AFE_ADC_CAL _IOW(_TM_T, 0x11, struct tvafe_adc_cal_s) +#define TVIN_IOC_G_AFE_ADC_CAL _IOR(_TM_T, 0x12, struct tvafe_adc_cal_s) +#define TVIN_IOC_G_AFE_COMP_WSS _IOR(_TM_T, 0x13, struct tvafe_comp_wss_s) +#define TVIN_IOC_S_AFE_VGA_EDID _IOW(_TM_T, 0x14, struct tvafe_vga_edid_s) +#define TVIN_IOC_G_AFE_VGA_EDID _IOR(_TM_T, 0x15, struct tvafe_vga_edid_s) +#endif +#define TVIN_IOC_S_AFE_VGA_PARM _IOW(_TM_T, 0x16, struct tvafe_vga_parm_s) +#define TVIN_IOC_G_AFE_VGA_PARM _IOR(_TM_T, 0x17, struct tvafe_vga_parm_s) +#define TVIN_IOC_S_AFE_VGA_AUTO _IO(_TM_T, 0x18) +#if 0 +#define TVIN_IOC_G_AFE_CMD_STATUS _IOR(_TM_T, 0x19, enum tvafe_cmd_status_e) +#endif +#define TVIN_IOC_G_AFE_CVBS_LOCK _IOR(_TM_T, 0x1a, enum tvafe_cvbs_video_e) +#define TVIN_IOC_S_AFE_CVBS_STD _IOW(_TM_T, 0x1b, enum tvin_sig_fmt_e) +#define TVIN_IOC_CALLMASTER_SET _IOW(_TM_T, 0x1c, enum tvin_port_e) +#define TVIN_IOC_CALLMASTER_GET _IO(_TM_T, 0x1d) +#if 0 +#define TVIN_IOC_S_AFE_ADC_COMP_CAL \ + _IOW(_TM_T, 0x1e, struct tvafe_adc_comp_cal_s) +#define TVIN_IOC_G_AFE_ADC_COMP_CAL \ + _IOR(_TM_T, 0x1f, struct tvafe_adc_comp_cal_s) +#endif +#define TVIN_IOC_LOAD_REG _IOW(_TM_T, 0x20, struct am_regs_s) +#if 0 +#define TVIN_IOC_S_AFE_ADC_DIFF _IOW(_TM_T, 0x21, struct tvafe_adc_cal_clamp_s) +#endif +#define TVIN_IOC_S_AFE_SONWON _IO(_TM_T, 0x22) +#define TVIN_IOC_S_AFE_SONWOFF _IO(_TM_T, 0x23) + +/* + * function defined applied for other driver + */ +/* + * adc pll ctl, atv demod & tvafe use the same adc module + * module index: atv demod:0x01; tvafe:0x2 + */ +extern void adc_set_pll_cntl(bool on, unsigned int module_sel); + +#endif diff --git a/include/linux/amlogic/media/tvin/tvin_v4l2.h b/include/linux/amlogic/media/tvin/tvin_v4l2.h new file mode 100644 index 0000000..23561b4 --- /dev/null +++ b/include/linux/amlogic/media/tvin/tvin_v4l2.h @@ -0,0 +1,825 @@ +/* + * include/linux/amlogic/media/tvin/tvin_v4l2.h + * + * Copyright (C) 2017 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 __TVIN_V4L2_H +#define __TVIN_V4L2_H +#include "tvin.h" +/*below macro defined applied to camera driver*/ +enum camera_light_mode_e { + ADVANCED_AWB = 0, + SIMPLE_AWB, + MANUAL_DAY, + MANUAL_A, + MANUAL_CWF, + MANUAL_CLOUDY, +}; + +enum camera_saturation_e { + SATURATION_N4_STEP = 0, + SATURATION_N3_STEP, + SATURATION_N2_STEP, + SATURATION_N1_STEP, + SATURATION_0_STEP, + SATURATION_P1_STEP, + SATURATION_P2_STEP, + SATURATION_P3_STEP, + SATURATION_P4_STEP, +}; + +enum camera_brightness_e { + BRIGHTNESS_N4_STEP = 0, + BRIGHTNESS_N3_STEP, + BRIGHTNESS_N2_STEP, + BRIGHTNESS_N1_STEP, + BRIGHTNESS_0_STEP, + BRIGHTNESS_P1_STEP, + BRIGHTNESS_P2_STEP, + BRIGHTNESS_P3_STEP, + BRIGHTNESS_P4_STEP, +}; + +enum camera_contrast_e { + CONTRAST_N4_STEP = 0, + CONTRAST_N3_STEP, + CONTRAST_N2_STEP, + CONTRAST_N1_STEP, + CONTRAST_0_STEP, + CONTRAST_P1_STEP, + CONTRAST_P2_STEP, + CONTRAST_P3_STEP, + CONTRAST_P4_STEP, +}; + +enum camera_hue_e { + HUE_N180_DEGREE = 0, + HUE_N150_DEGREE, + HUE_N120_DEGREE, + HUE_N90_DEGREE, + HUE_N60_DEGREE, + HUE_N30_DEGREE, + HUE_0_DEGREE, + HUE_P30_DEGREE, + HUE_P60_DEGREE, + HUE_P90_DEGREE, + HUE_P120_DEGREE, + HUE_P150_DEGREE, +}; + +enum camera_special_effect_e { + SPECIAL_EFFECT_NORMAL = 0, + SPECIAL_EFFECT_BW, + SPECIAL_EFFECT_BLUISH, + SPECIAL_EFFECT_SEPIA, + SPECIAL_EFFECT_REDDISH, + SPECIAL_EFFECT_GREENISH, + SPECIAL_EFFECT_NEGATIVE, +}; + +enum camera_exposure_e { + EXPOSURE_N4_STEP = 0, + EXPOSURE_N3_STEP, + EXPOSURE_N2_STEP, + EXPOSURE_N1_STEP, + EXPOSURE_0_STEP, + EXPOSURE_P1_STEP, + EXPOSURE_P2_STEP, + EXPOSURE_P3_STEP, + EXPOSURE_P4_STEP, +}; + +enum camera_sharpness_e { + SHARPNESS_1_STEP = 0, + SHARPNESS_2_STEP, + SHARPNESS_3_STEP, + SHARPNESS_4_STEP, + SHARPNESS_5_STEP, + SHARPNESS_6_STEP, + SHARPNESS_7_STEP, + SHARPNESS_8_STEP, + SHARPNESS_AUTO_STEP, +}; + +enum camera_mirror_flip_e { + MF_NORMAL = 0, + MF_MIRROR, + MF_FLIP, + MF_MIRROR_FLIP, +}; + +enum camera_wb_flip_e { + CAM_WB_AUTO = 0, + CAM_WB_CLOUD, + CAM_WB_DAYLIGHT, + CAM_WB_INCANDESCENCE, + CAM_WB_TUNGSTEN, + CAM_WB_FLUORESCENT, + CAM_WB_MANUAL, + CAM_WB_SHADE, + CAM_WB_TWILIGHT, + CAM_WB_WARM_FLUORESCENT, +}; + +enum camera_focus_mode_e { + CAM_FOCUS_MODE_RELEASE = 0, + CAM_FOCUS_MODE_FIXED, + CAM_FOCUS_MODE_INFINITY, + CAM_FOCUS_MODE_AUTO, + CAM_FOCUS_MODE_MACRO, + CAM_FOCUS_MODE_EDOF, + CAM_FOCUS_MODE_CONTI_VID, + CAM_FOCUS_MODE_CONTI_PIC, +}; + +/* removed this when move to new v4l2 */ +#define V4L2_CID_AUTO_FOCUS_START (V4L2_CID_CAMERA_CLASS_BASE+28) +#define V4L2_CID_AUTO_FOCUS_STOP (V4L2_CID_CAMERA_CLASS_BASE+29) +#define V4L2_CID_AUTO_FOCUS_STATUS (V4L2_CID_CAMERA_CLASS_BASE+30) +#define V4L2_AUTO_FOCUS_STATUS_IDLE (0 << 0) +#define V4L2_AUTO_FOCUS_STATUS_BUSY (1 << 0) +#define V4L2_AUTO_FOCUS_STATUS_REACHED (1 << 1) +#define V4L2_AUTO_FOCUS_STATUS_FAILED (1 << 2) +/* removed this when move to new v4l2 */ + +enum camera_night_mode_flip_e { + CAM_NM_AUTO = 0, + CAM_NM_ENABLE, +}; + +enum camera_effect_flip_e { + CAM_EFFECT_ENC_NORMAL = 0, + CAM_EFFECT_ENC_GRAYSCALE, + CAM_EFFECT_ENC_SEPIA, + CAM_EFFECT_ENC_SEPIAGREEN, + CAM_EFFECT_ENC_SEPIABLUE, + CAM_EFFECT_ENC_COLORINV, +}; + +enum camera_banding_flip_e { + CAM_BANDING_DISABLED = 0, + CAM_BANDING_50HZ, + CAM_BANDING_60HZ, + CAM_BANDING_AUTO, + CAM_BANDING_OFF, +}; + +struct camera_info_s { + const char *camera_name; + enum camera_saturation_e saturation; + enum camera_brightness_e brighrness; + enum camera_contrast_e contrast; + enum camera_hue_e hue; + /* enum camera_special_effect_e special_effect; */ + enum camera_exposure_e exposure; + enum camera_sharpness_e sharpness; + enum camera_mirror_flip_e mirro_flip; + enum tvin_sig_fmt_e resolution; + enum camera_wb_flip_e white_balance; + enum camera_night_mode_flip_e night_mode; + enum camera_effect_flip_e effect; + int qulity; +}; + +/* ---------- enum ---------- */ + +/* LPF responding time: cycles to reach 90% target */ +enum xml_resp_s { + XML_RESP_0 = 0, /* immediately */ + XML_RESP_1, /* 10 cycles */ + XML_RESP_2, /* 20 cycles */ + XML_RESP_3, /* 50 cycles */ + XML_RESP_4, /* 100 cycles */ + XML_RESP_5, /* 200 cycles */ + XML_RESP_6, /* 400 cycles */ + XML_RESP_7, /* 800 cycles */ + XML_RESP_8, /* 1600 cycles */ + XML_RESP_9, /* 3200 cycles */ +}; + +enum cam_scanmode_e { + CAM_SCANMODE_NULL = 0, /* turn off af */ + CAM_SCANMODE_PROBE, + CAM_SCANMODE_FULL, +}; +/*state for cmd*/ +enum cam_cmd_state_e { + CAM_STATE_NULL, + CAM_STATE_DOING, + CAM_STATE_ERROR, + CAM_STATE_SUCCESS, +}; + +enum cam_command_e { + /* common */ + CAM_COMMAND_INIT = 0, + CAM_COMMAND_GET_STATE, + CAM_COMMAND_SCENES, + CAM_COMMAND_EFFECT, + CAM_COMMAND_AWB, + CAM_COMMAND_MWB, + CAM_COMMAND_SET_WORK_MODE, + /* ae related */ + CAM_COMMAND_AE_ON, + CAM_COMMAND_AE_OFF, + CAM_COMMAND_SET_AE_LEVEL, + /* af related */ + CAM_COMMAND_AF, + CAM_COMMAND_FULLSCAN, + CAM_COMMAND_TOUCH_FOCUS, + CAM_COMMAND_CONTINUOUS_FOCUS_ON, + CAM_COMMAND_CONTINUOUS_FOCUS_OFF, + CAM_COMMAND_BACKGROUND_FOCUS_ON, + CAM_COMMAND_BACKGROUND_FOCUS_OFF, + /* flash related */ + CAM_COMMAND_SET_FLASH_MODE, + /* torch related */ + CAM_COMMAND_TORCH, + /* bypass isp for raw data */ + CMD_ISP_BYPASS, +}; +extern const char *cam_cmd_to_str(enum cam_command_e cmd); + +/* ---------- xml struct ---------- */ + +/* all "0" means no vcm */ +struct xml_vcm_s { + unsigned short vcm_max; + unsigned short vcm_min; + unsigned short vcm_reseponding_time; + /* in the unit of mS, responding_cycle =*/ + /*responding_time/sensor_frame_rate + 1, 1 for IIC and so on */ +}; + +/* "0" means no flash */ +enum flash_mode_s { + FLASH_MODE_NULL = 0, /* no use flash */ + FLASH_MODE_ON, + FLASH_MODE_OFF, + FLASH_MODE_AUTO, +}; + +#define WAVE_PARM_NUM 12 +struct wave_s { + unsigned int torch_rising_time; + unsigned int flash_rising_time; + unsigned int torch_flash_ratio; + unsigned int wave_clock_div; /* u16 */ + unsigned int pulse_init_time; /* u11 */ + unsigned int pulse_high_time; /* u11 */ + unsigned int pulse_low_time; /* u11 */ + unsigned int time_to_latch; /* u26 */ + unsigned int latch_time; /* u26 */ + unsigned int latch_time_timeout; /* u26 */ + unsigned int time_to_off; /* u11 */ + unsigned int pulse_qty_max; /* u8 */ +}; + +struct xml_window_s { + unsigned char ratio_x0; /* 0 ~ 255, x0 = (format.h * ratio_x0) >> 8 */ + unsigned char ratio_y0; /* 0 ~ 255, y0 = (format.v * ratio_y0) >> 8 */ + unsigned char ratio_x1; /* 0 ~ 255, x1 = (format.h * ratio_x1) >> 8 */ + unsigned char ratio_y1; /* 0 ~ 255, y1 = (format.v * ratio_y1) >> 8 */ +}; + +#define AE_PARM_NUM 67 +struct xml_algorithm_ae_s { + unsigned int ae_algorithm; /* 0:basic; 1:enhanced */ + unsigned int ae_statistics[3]; /* 0: false, 1: true */ + unsigned int ae_exp[3]; /* 0: false, 1: true */ + unsigned int ae_ag[3]; /* 0: false, 1: true */ + unsigned int ae_skip[3]; /* 0: false, 1: true */ + unsigned int ratio_winl; /* 0 ~ 1024 */ + unsigned int ratio_winr; /* 0 ~ 1024 */ + unsigned int ratio_wint; /* 0 ~ 1024 */ + unsigned int ratio_winb; /* 0 ~ 1024 */ + unsigned int alert_mode; /* 0: disable, 1: enable */ + unsigned int tune_mode; /* 0: average mode, 1: blind up mode */ + unsigned int ratio_r; /* 0 ~ 255 */ + unsigned int ratio_g; /* 0 ~ 255 */ + unsigned int ratio_b; /* 0 ~ 255 */ + unsigned int stepdnr; /* 0 ~ 255 */ + unsigned int stepdng; /* 0 ~ 255 */ + unsigned int stepdnb; /* 0 ~ 255 */ + unsigned int stepup; /* 0 ~ 255 */ + unsigned int slow_lpfcoef; /* 0 ~ 255 */ + unsigned int fast_lpfcoef; /* 0 ~ 255 */ + unsigned int coef_cur[16]; /* 0 ~ 1023 */ + unsigned int coef_env[16]; /* 0 ~ 1023 */ + unsigned int env_hign; /* 0 ~ 255 */ + unsigned int env_hign2mid; /* 0 ~ 255 */ + unsigned int env_low2mid; /* 0 ~ 255 */ + unsigned int env_low; /* 0 ~ 255 */ + unsigned int thr_r_high; /* 0 ~ 255 */ + unsigned int thr_r_mid; /* 0 ~ 255 */ + unsigned int thr_r_low; /* 0 ~ 255 */ + unsigned int thr_g_high; /* 0 ~ 255 */ + unsigned int thr_g_mid; /* 0 ~ 255 */ + unsigned int thr_g_low; /* 0 ~ 255 */ + unsigned int thr_b_high; /* 0 ~ 255 */ + unsigned int thr_b_mid; /* 0 ~ 255 */ + unsigned int thr_b_low; /* 0 ~ 255 */ + unsigned int lpftype_high; /* 0 ~ 255 */ + unsigned int lpftype_mid; /* 0 ~ 255 */ + unsigned int lpftype_low; /* 0 ~ 255 */ + unsigned int targethigh; /* 0 ~ 255 */ + unsigned int targetmid; /* 0 ~ 255 */ + unsigned int targetlow; /* 0 ~ 255 */ + unsigned int radium_inner_h; /* 0 ~ 255 */ + unsigned int radium_inner_m; /* 0 ~ 255 */ + unsigned int radium_inner_l; /* 0 ~ 255 */ + unsigned int radium_outer_h; /* 0 ~ 255 */ + unsigned int radium_outer_m; /* 0 ~ 255 */ + unsigned int radium_outer_l; /* 0 ~ 255 */ + unsigned int flash_thr; /* 0 ~ 255 */ + + /***********************AE_ENH********************************/ + + unsigned int ratio_histr; /* 0 ~1023 */ + unsigned int ratio_histg; /* 0 ~1023 */ + unsigned int ratio_histb; /* 0 ~1023 */ + unsigned int target_r; /* 0 ~ 255 */ + unsigned int target_g; /* 0 ~ 255 */ + unsigned int target_b; /* 0 ~ 255 */ + unsigned int maxrate_inner; /* 0 ~1023 */ + unsigned int maxrate_outer; /* 0 ~1023 */ + unsigned int slow_lpfcoef_enh; /* 0 ~ 255 */ + unsigned int fast_lpfcoef_enh; /* 0 ~ 255 */ + unsigned int flash_thr_enh; /* 0 ~ 255 */ + /***********************AE_ADD********************************/ + unsigned int ae_ratio_low; /* 0 ~ 1024 0x00000005 */ + unsigned int ae_ratio_low2mid; /* 0 ~ 1024 0x0000000f */ + unsigned int ae_ratio_mid2high; /* 0 ~ 1024 0x0000001e */ + unsigned int ae_ratio_high; /* 0 ~ 1024 0x00000028 */ + unsigned int ae_min_diff; /* 0 ~ 255 0x00000032 */ + unsigned int ae_max_diff; /* 0 ~ 255 0x0000000f */ + + unsigned int reserve[16]; + unsigned int aet_fmt_gain; /* 0db for each fmt */ + +}; + +#define AWB_PARM_NUM 58 +struct xml_algorithm_awb_s { + unsigned int awb_algorithm; /* 0:basic; 1:enhanced */ + unsigned int ratio_winl; /* 0 ~ 1024 */ + unsigned int ratio_winr; /* 0 ~ 1024 */ + unsigned int ratio_wint; /* 0 ~ 1024 */ + unsigned int ratio_winb; /* 0 ~ 1024 */ + unsigned int ratio_rgb; /* 0 ~ 255 */ + unsigned int ratio_yh; /* 0 ~ 255 */ + unsigned int ratio_ym; /* 0 ~ 255 */ + unsigned int ratio_yl; /* 0 ~ 255 */ + unsigned int yyh; /* 0 ~ 255 */ + unsigned int yym; /* 0 ~ 255 */ + unsigned int yyl; /* 0 ~ 255 */ + unsigned int coef_r[4]; /* 0 ~ 255 */ + unsigned int coef_g[4]; /* 0 ~ 255 */ + unsigned int coef_b[4]; /* 0 ~ 255 */ + unsigned int inner_rg; /* 0 ~ 1023 */ + unsigned int inner_bg; /* 0 ~ 1023 */ + unsigned int outer_rg; /* 0 ~ 1023 */ + unsigned int outer_bg; /* 0 ~ 1023 */ + unsigned int r_max; /* 0 ~ 4095 */ + unsigned int r_min; /* 0 ~ 4095 */ + unsigned int b_max; /* 0 ~ 4095 */ + unsigned int b_min; /* 0 ~ 4095 */ + unsigned int thr_gb_h; /* 0 ~ 255 */ + unsigned int thr_gb_m; /* 0 ~ 255 */ + unsigned int thr_gb_l; /* 0 ~ 255 */ + unsigned int thr_gr_h; /* 0 ~ 255 */ + unsigned int thr_gr_m; /* 0 ~ 255 */ + unsigned int thr_gr_l; /* 0 ~ 255 */ + unsigned int thr_br_h; /* 0 ~ 255 */ + unsigned int thr_br_m; /* 0 ~ 255 */ + unsigned int thr_br_l; /* 0 ~ 255 */ + unsigned int thr_du_h; /* 0 ~ 255 */ + unsigned int thr_du_m; /* 0 ~ 255 */ + unsigned int thr_du_l; /* 0 ~ 255 */ + unsigned int thr_dv_h; /* 0 ~ 255 */ + unsigned int thr_dv_m; /* 0 ~ 255 */ + unsigned int thr_dv_l; /* 0 ~ 255 */ + unsigned int thr_yh_h; /* 0 ~ 255 */ + unsigned int thr_yh_m; /* 0 ~ 255 */ + unsigned int thr_yh_l; /* 0 ~ 255 */ + unsigned int thr_yl_h; /* 0 ~ 255 */ + unsigned int thr_yl_m; /* 0 ~ 255 */ + unsigned int thr_yl_l; /* 0 ~ 255 */ + /*********************awb_enh****************/ + unsigned int ratio_yuv; + unsigned int slow_lpfcoef; /* 0 ~ 255 */ + unsigned int fast_lpfcoef; /* 0 ~ 255 */ + unsigned int outer; /* 0 ~ 1023 */ + unsigned int inner; /* 0 ~ 1023 */ + unsigned int rw_limith; /* 0 ~ 4095 */ + unsigned int rw_limitl; /* 0 ~ 4095 */ + unsigned int gw_limith; /* 0 ~ 4095 */ + unsigned int gw_limitl; /* 0 ~ 4095 */ + unsigned int bw_limith; /* 0 ~ 4095 */ + unsigned int bw_limitl; /* 0 ~ 4095 */ + unsigned int thr_u[20]; /* 0 ~ 255 */ + unsigned int thr_v[20]; /* 0 ~ 255 */ + unsigned int reserve[16]; +}; + +#define AF_PARM_NUM 13 + +#define FOCUS_GRIDS 16 + +struct xml_algorithm_af_s { + /*for lose focus */ + unsigned int enter_static_ratio; /* 10bit/1024 */ + unsigned int detect_step_cnt; + unsigned int ave_vdc_thr; /* the threshold of enter move */ + /*full scan & detect window ratio */ + unsigned int + win_ratio;/* cut 4 border in top bottom left right widht=1/ratio */ + /*for climbing algorithm */ + unsigned int step[FOCUS_GRIDS]; + unsigned int valid_step_cnt; + unsigned int jump_offset; + unsigned int field_delay; + /*window for touch focus */ + unsigned int x; /* x coord of touch focus win */ + unsigned int y; /* y coord of touch focus win */ + unsigned int radius_ratio; /* radius of touch focus win */ + unsigned int hillside_fall; + unsigned int reserve[15]; +}; + +#define XML_LUT_LS 1025 /* 32*32 32-bit */ +struct xml_lut_ls_s { + unsigned int reg_map[XML_LUT_LS]; +}; + +#define XML_LUT_GC 257 /* 257*3 10-bit */ +struct xml_lut_gc_s { + unsigned short gamma_r[XML_LUT_GC]; + unsigned short gamma_g[XML_LUT_GC]; + unsigned short gamma_b[XML_LUT_GC]; +}; + +#define XML_TOP 9 /* top */ +struct xml_top_s { + unsigned int reg_map[XML_TOP]; +}; + +#define XML_TP 20 /* test pattern */ +struct xml_tp_s { + unsigned int reg_map[XML_TP]; +}; + +#define XML_CG 6 /* clamp & gain */ +struct xml_cg_s { + unsigned int reg_map[XML_CG]; +}; + +#define XML_LS 5 /* lens shielding */ +struct xml_ls_s { + unsigned int reg_map[XML_LS]; +}; + +#define XML_GC 1 /* gamma curve */ +struct xml_gc_s { + unsigned int reg_map[XML_GC]; +}; + +#define XML_DP 11 /* defect pixel */ +struct xml_dp_s { + unsigned int reg_map[XML_DP]; +}; + +#define XML_DM 2 /* demosaicing */ +struct xml_dm_s { + unsigned int reg_map[XML_DM]; +}; + +#define XML_CSC 9 /* colr space conversion */ +struct xml_csc_s { + unsigned int reg_map[XML_CSC << 1]; /* sd/hd sensitive */ +}; + +#define XML_NR 13 /* noise reduction */ +struct xml_nr_s { + unsigned int reg_map[XML_NR]; +}; + +#define XML_SH 33 /* shanrpness */ +struct xml_sharp_s { + unsigned int reg_map[XML_SH]; +}; + +#define XML_DBG 2 /* debug */ +struct xml_dbg_s { + unsigned int reg_map[XML_DBG]; +}; + +#define XML_BN 3 /* black level & noise meter */ +struct xml_bn_s { + unsigned int reg_map[XML_BN]; +}; + +#define XML_AE 6 /* auto explosure statistics */ +struct xml_ae_s { + unsigned int reg_map[XML_AE]; +}; + +#define XML_AWB 5 /* auto white balance statistics */ +struct xml_awb_s { + unsigned int reg_map[XML_AWB]; +}; + +#define XML_AF 17 /* auto focus statistics */ +struct xml_af_s { + unsigned int reg_map[XML_AF]; +}; +/* + *#define XML_WAVE 1 // wave generatore + *struct xml_wave_s { + * unsigned int reg_map[XML_WAVE]; + *} xml_wave_t; + */ +struct xml_peripheral_s { + /* struct xml_sensor_s sensor; */ + /* struct xml_ae_level_s ae_level; */ + struct xml_vcm_s vcm; +}; + +struct xml_default_regs_s { + struct xml_top_s top; + struct xml_tp_s tp; /* disable */ + struct xml_cg_s cg; /* straight */ + struct xml_ls_s ls; + struct xml_gc_s gc; + struct xml_dp_s dp; /* w/o static lut */ + struct xml_dm_s dm; + struct xml_csc_s csc; /* RGB->YUV */ + struct xml_nr_s nr; /* disable */ + struct xml_sharp_s sharp; /* disable */ + struct xml_dbg_s dbg; /* disable */ + struct xml_bn_s bn; /* disable */ + struct xml_ae_s ae_reg; + struct xml_awb_s awb_reg; + struct xml_af_s af_reg; + struct xml_lut_ls_s lnsd; + struct xml_lut_gc_s lut_gc; +}; + +struct xml_scenes_s { + struct xml_algorithm_ae_s ae; + struct xml_algorithm_awb_s awb; + struct xml_algorithm_af_s af; +}; +/*only G0 R1 B2 G3*/ +struct xml_wb_manual_s { + unsigned int reg_map[2]; +}; + +struct xml_effect_manual_s { + struct xml_csc_s csc; + /* RGB->YUV with effect: r, g, b,*/ + /*brightness, contrast, hue, saturation, y_mirror, ... */ +}; + +/* ---------- camera struct ---------- */ +/* start tvin service will get format information */ +/* + *struct cam_format_s { + * unsigned short h; + * unsigned short v; + * unsigned short frame_time; // + * //in the unit of uS, for example, frame_time = 40(mS) means 25Hz format. + *} cam_format_t; + */ +struct cam_function_s { + bool (*set_af_new_step)(void *priv, unsigned int af_debug_control); + unsigned int (*get_aet_current_step)(void *priv); + unsigned int (*get_aet_current_gain)(void *priv); + unsigned int (*get_aet_min_gain)(void *priv); + unsigned int (*get_aet_max_gain)(void *priv); + unsigned int (*get_aet_max_step)(void *priv); + unsigned int (*get_aet_gain_by_step)(void *priv, + unsigned int new_step); + bool (*set_aet_new_step)(void *priv, unsigned int new_step, + bool exp_mode, bool ag_mode); + bool (*check_mains_freq)(void *priv); + void *priv_data; +}; + +struct cam_manual_s { + unsigned short ae_step; + unsigned short focus; + unsigned short torch; +}; + +struct cam_window_s { + unsigned short x0; + unsigned short y0; + unsigned short x1; + unsigned short y1; +}; + +#define CAP_PARM_NUM 8 +struct xml_capture_s { + unsigned int ae_try_max_cnt; + unsigned int sigle_count; + unsigned int skip_step; + unsigned int multi_capture_num; + enum cam_scanmode_e af_mode; + unsigned int eyetime; /* ms */ + unsigned int pretime; /* ms */ + unsigned int postime; /* ms */ +}; +/*for isp work mode*/ +enum camera_mode_e { + CAMERA_PREVIEW, + CAMERA_CAPTURE, + CAMERA_RECORD, +}; + +/*this parameter must be passed to vdin when stream on*/ +struct cam_parameter_s { + enum cam_command_e cam_command; + enum cam_scanmode_e cam_scanmode; + struct cam_function_s cam_function; + struct cam_manual_s cam_manual; + struct cam_window_s cam_touch_window; + struct xml_peripheral_s *xml_peripheral; + struct xml_scenes_s *xml_scenes; + struct xml_default_regs_s *xml_regs_map; + struct xml_effect_manual_s *xml_effect_manual; + struct xml_wb_manual_s *xml_wb_manual; + struct xml_capture_s *xml_capture; + struct wave_s *xml_wave; + unsigned int level; /* the torch light level */ + enum flash_mode_s flash_mode; /* the flash mode */ + enum camera_mode_e cam_mode; /* set the isp work mode */ + int exposure_level; /* manual exposure level 2db by each step */ +}; + +struct isp_status_s { + unsigned short focus; + bool fullscan_done; +}; + +enum vdin_format_convert_e { + VDIN_MATRIX_XXX_YUV_BLACK = 0, + VDIN_FORMAT_CONVERT_YUV_YUV422, + VDIN_FORMAT_CONVERT_YUV_YUV444, + VDIN_FORMAT_CONVERT_YUV_RGB, + VDIN_FORMAT_CONVERT_YUV_GBR, + VDIN_FORMAT_CONVERT_YUV_BRG, + VDIN_FORMAT_CONVERT_RGB_YUV422, + VDIN_FORMAT_CONVERT_GBR_YUV422, + VDIN_FORMAT_CONVERT_BRG_YUV422, + VDIN_FORMAT_CONVERT_RGB_YUV444, + VDIN_FORMAT_CONVERT_RGB_RGB, + VDIN_FORMAT_CONVERT_YUV_NV12, + VDIN_FORMAT_CONVERT_YUV_NV21, + VDIN_FORMAT_CONVERT_RGB_NV12, + VDIN_FORMAT_CONVERT_RGB_NV21, + VDIN_FORMAT_CONVERT_MAX, +}; + +enum vdin_cmd_e { + VDIN_CMD_NULL = 0, + VDIN_CMD_SET_CSC, + VDIN_CMD_SET_CM2, + VDIN_CMD_ISR, + VDIN_CMD_MPEGIN_START, + VDIN_CMD_GET_HISTGRAM, + VDIN_CMD_MPEGIN_STOP, + VDIN_CMD_FORCE_GO_FIELD, +}; + +struct vdin_arg_s { + enum vdin_cmd_e cmd; + unsigned int h_active; + unsigned int v_active; + unsigned char matrix_id; + enum vdin_format_convert_e color_convert; + unsigned int *cm2; + void *private; +}; + +enum bt_path_e { + BT_PATH_GPIO = 0, + BT_PATH_CSI2, + BT_PATH_GPIO_B, +}; + +enum clk_channel_e { + CLK_CHANNEL_A = 0, + CLK_CHANNEL_B, +}; + +enum cam_interface_e { + CAM_DVP = 0, + CAM_MIPI, +}; + +/* *********************************************************************** */ +/* *** IOCTL command definitions ***************************************** */ +/* *********************************************************************** */ + +#define CAMERA_IOC_MAGIC 'C' + +#define CAMERA_IOC_START \ + _IOW(CAMERA_IOC_MAGIC, 0x01, struct camera_info_s) +#define CAMERA_IOC_STOP \ + _IO(CAMERA_IOC_MAGIC, 0x02) +#define CAMERA_IOC_SET_PARA \ + _IOW(CAMERA_IOC_MAGIC, 0x03, struct camera_info_s) +#define CAMERA_IOC_GET_PARA \ + _IOR(CAMERA_IOC_MAGIC, 0x04, struct camera_info_s) +#define CAMERA_IOC_START_CAPTURE_PARA \ + _IOR(CAMERA_IOC_MAGIC, 0x05, struct camera_info_s) +#define CAMERA_IOC_STOP_CAPTURE_PARA \ + _IOR(CAMERA_IOC_MAGIC, 0x06, struct camera_info_s) + +struct csi_parm_s { + /* am_csi2_hw_t *hw_info; */ + unsigned char lanes; + unsigned char channel; + unsigned char mode; + unsigned char clock_lane_mode; /* 0 clock gate 1: always on */ + unsigned int active_pixel; + unsigned int active_line; + unsigned int frame_size; + unsigned int ui_val; /* ns */ + unsigned int hs_freq; /* hz */ + unsigned int urgent; + unsigned int settle; + + unsigned int lane_mask; + + enum clk_channel_e clk_channel; + unsigned int skip_frames; + enum tvin_color_fmt_e csi_ofmt; +}; + +/* add for vdin called by backend driver */ +struct vdin_parm_s { + enum tvin_port_e port; + enum tvin_sig_fmt_e + fmt;/* >max:use the information*/ + /*from parameter rather than format table */ + enum tvin_color_fmt_e + cfmt; /* for camera input mainly,the data sequence is different */ + enum tvin_scan_mode_e scan_mode;/* 1: progressive 2:interlaced */ + unsigned short h_active; + unsigned short v_active; + unsigned short frame_rate; + /*for bt656 */ + enum bt_path_e bt_path; /* 0:from gpio,1:from csi2 */ + unsigned char hsync_phase; /* 1: inverted 0: original */ + unsigned char vsync_phase; /* 1: inverted 0: origianl */ + unsigned short hs_bp;/* the horizontal start postion of bt656 window */ + unsigned short vs_bp;/* the vertical start postion of bt656 window */ + /*for isp tell different frontends such as bt656/mipi */ + enum tvin_port_e isp_fe_port; + /*for vdin cfmt convert & scale&skip */ + enum tvin_color_fmt_e + dfmt; /* vdin will convert color space accroding to dfmt */ + unsigned short dest_hactive; /* for vdin scale down */ + unsigned short dest_vactive; + unsigned short skip_count; /* for skip frame */ + + struct csi_parm_s csi_hw_info; + /*for reserved */ + uintptr_t reserved; +}; + +struct fe_arg_s { + enum tvin_port_e port; + int index; + void *arg; +}; + +struct vdin_v4l2_ops_s { + int (*start_tvin_service)(int no, struct vdin_parm_s *para); + int (*stop_tvin_service)(int no); + void (*set_tvin_canvas_info)(int start, int num); + void (*get_tvin_canvas_info)(int *start, int *num); + int (*tvin_fe_func)(int no, struct fe_arg_s *arg);/* for isp command */ + int (*tvin_vdin_func)(int no, struct vdin_arg_s *arg); + void *private; +}; + +/*macro defined applied to camera driver is ending*/ +extern int v4l2_vdin_ops_init(struct vdin_v4l2_ops_s *vdin_v4l2p); +extern struct vdin_v4l2_ops_s *get_vdin_v4l2_ops(void); +extern int vdin_reg_v4l2(struct vdin_v4l2_ops_s *ops); +#endif diff --git a/include/linux/amlogic/media/utils/aformat.h b/include/linux/amlogic/media/utils/aformat.h index 316a476..13b86d0 100644 --- a/include/linux/amlogic/media/utils/aformat.h +++ b/include/linux/amlogic/media/utils/aformat.h @@ -47,8 +47,10 @@ enum aformat_e { AFORMAT_MPEG1 = 26, AFORMAT_MPEG2 = 27, AFORMAT_WMAVOI = 28, - AFORMAT_UNSUPPORT = 29, - AFORMAT_MAX = 30 + AFORMAT_WMALOSSLESS = 29, + AFORMAT_PCM_S24LE = 30, + AFORMAT_UNSUPPORT = 31, + AFORMAT_MAX = 32 }; #endif /* AFORMAT_H */ diff --git a/include/linux/amlogic/media/utils/amports_config.h b/include/linux/amlogic/media/utils/amports_config.h index 5b1ace2..a184f6e 100644 --- a/include/linux/amlogic/media/utils/amports_config.h +++ b/include/linux/amlogic/media/utils/amports_config.h @@ -18,6 +18,7 @@ #ifndef AMPORTS_CONFIG_HHH #define AMPORTS_CONFIG_HHH #include +#include #include /* diff --git a/include/linux/amlogic/media/utils/amstream.h b/include/linux/amlogic/media/utils/amstream.h index e8daf60..fcef9f8 100644 --- a/include/linux/amlogic/media/utils/amstream.h +++ b/include/linux/amlogic/media/utils/amstream.h @@ -86,6 +86,9 @@ #define AMSTREAM_IOC_TS_SKIPBYTE _IOW((_A_M), 0x1d, int) #define AMSTREAM_IOC_SUB_TYPE _IOW((_A_M), 0x1e, int) #define AMSTREAM_IOC_CLEAR_VIDEO _IOW((_A_M), 0x1f, int) +#define AMSTREAM_IOC_VDECINFO _IOR((_A_M), 0x20, int) +#define AMSTREAM_IOC_GLOBAL_GET_VIDEO_OUTPUT _IOR((_A_M), 0x21, int) +#define AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT _IOW((_A_M), 0x22, int) #define AMSTREAM_IOC_APTS _IOR((_A_M), 0x40, int) #define AMSTREAM_IOC_VPTS _IOR((_A_M), 0x41, int) @@ -115,6 +118,7 @@ #define AMSTREAM_IOC_SET_BLACKOUT_POLICY _IOW((_A_M), 0x53, int) #define AMSTREAM_IOC_UD_LENGTH _IOR((_A_M), 0x54, int) #define AMSTREAM_IOC_UD_POC _IOR((_A_M), 0x55, int) +#define AMSTREAM_IOC_UD_FLUSH_USERDATA _IOR((_A_M), 0x56, int) #define AMSTREAM_IOC_GET_SCREEN_MODE _IOR((_A_M), 0x58, int) #define AMSTREAM_IOC_SET_SCREEN_MODE _IOW((_A_M), 0x59, int) #define AMSTREAM_IOC_GET_VIDEO_DISCONTINUE_REPORT _IOR((_A_M), 0x5a, int) @@ -255,6 +259,26 @@ struct vdec_status { unsigned int status; }; +struct vdec_info { + char vdec_name[16]; + unsigned int ver; + unsigned int frame_width; + unsigned int frame_height; + unsigned int frame_rate; + unsigned int bit_rate; + unsigned int frame_dur; + unsigned int frame_data; + unsigned int error_count; + unsigned int status; + unsigned int frame_count; + unsigned int error_frame_count; + unsigned int drop_frame_count; + unsigned long long total_data; + unsigned int samp_cnt; + unsigned int offset; + char reserved[32]; +}; + struct adec_status { unsigned int channels; unsigned int sample_rate; @@ -280,6 +304,19 @@ struct am_io_param { struct adec_status astatus; }; }; + +struct am_io_info { + union { + int data; + int id; + }; + int len; + union { + char buf[1]; + struct vdec_info vinfo; + }; +}; + struct audio_info { int valid; @@ -412,6 +449,9 @@ struct userdata_poc_info_t { #define AMSTREAM_SET_VSYNC_UPINT 0x172 #define AMSTREAM_SET_VSYNC_SLOW_FACTOR 0x173 #define AMSTREAM_SET_FRAME_BASE_PATH 0x174 +#define AMSTREAM_SET_EOS 0x175 +#define AMSTREAM_SET_RECEIVE_ID 0x176 + /* video set ex cmd */ #define AMSTREAM_SET_EX_VIDEO_AXIS 0x260 #define AMSTREAM_SET_EX_VIDEO_CROP 0x261 @@ -440,7 +480,7 @@ struct userdata_poc_info_t { #define AMSTREAM_GET_AUDIO_AVG_BITRATE_BPS 0x810 #define AMSTREAM_GET_VIDEO_AVG_BITRATE_BPS 0x811 #define AMSTREAM_GET_ION_ID 0x812 - +#define AMSTREAM_GET_NEED_MORE_DATA 0x813 /* video get cmd */ #define AMSTREAM_GET_OMX_VPTS 0x860 #define AMSTREAM_GET_TRICK_STAT 0x861 @@ -547,12 +587,13 @@ struct tsdemux_ops { void tsdemux_set_ops(struct tsdemux_ops *ops); int tsdemux_set_reset_flag(void); -void set_adec_func(int (*adec_func) (struct adec_status *)); +void set_adec_func(int (*adec_func)(struct adec_status *)); void wakeup_sub_poll(void); -void set_userdata_poc(struct userdata_poc_info_t poc); void init_userdata_fifo(void); -int wakeup_userdata_poll(int wp, unsigned long start_phyaddr, int buf_size, - int data_length); +void reset_userdata_fifo(int bInit); +int wakeup_userdata_poll(struct userdata_poc_info_t poc, + int wp, unsigned long start_phyaddr, + int buf_size, int data_length); int get_sub_type(void); #endif /**/ diff --git a/include/linux/amlogic/media/utils/vdec_reg.h b/include/linux/amlogic/media/utils/vdec_reg.h index 81818eb..37fc657 100644 --- a/include/linux/amlogic/media/utils/vdec_reg.h +++ b/include/linux/amlogic/media/utils/vdec_reg.h @@ -125,12 +125,56 @@ #define SET_MPEG_REG_MASK(r, mask)\ WRITE_MPEG_REG(r, READ_MPEG_REG(r) | (mask)) +#define WRITE_PARSER_REG(r, val) codec_parsbus_write(r, val) +#define READ_PARSER_REG(r) codec_parsbus_read(r) +#define WRITE_PARSER_REG_BITS(r, val, start, len) \ + WRITE_PARSER_REG(r, (READ_PARSER_REG(r) & ~(((1L<<(len))-1)<<(start)))|\ + ((unsigned int)((val)&((1L<<(len))-1)) << (start))) + +#define CLEAR_PARSER_REG_MASK(r, mask)\ + WRITE_PARSER_REG(r, READ_PARSER_REG(r) & ~(mask)) +#define SET_PARSER_REG_MASK(r, mask)\ + WRITE_PARSER_REG(r, READ_PARSER_REG(r) | (mask)) + #define WRITE_HHI_REG(r, val) codec_hhibus_write(r, val) #define READ_HHI_REG(r) codec_hhibus_read(r) #define WRITE_HHI_REG_BITS(r, val, start, len) \ WRITE_HHI_REG(r, (READ_HHI_REG(r) & ~(((1L<<(len))-1)<<(start)))|\ ((unsigned int)((val)&((1L<<(len))-1)) << (start))) +#define WRITE_AIU_REG(r, val) codec_aiubus_write(r, val) +#define READ_AIU_REG(r) codec_aiubus_read(r) +#define WRITE_AIU_REG_BITS(r, val, start, len) \ + WRITE_AIU_REG(r, (READ_AIU_REG(r) & ~(((1L<<(len))-1)<<(start)))|\ + ((unsigned int)((val)&((1L<<(len))-1)) << (start))) + +#define CLEAR_AIU_REG_MASK(r, mask)\ + WRITE_AIU_REG(r, READ_AIU_REG(r) & ~(mask)) +#define SET_AIU_REG_MASK(r, mask)\ + WRITE_AIU_REG(r, READ_AIU_REG(r) | (mask)) + +#define WRITE_DEMUX_REG(r, val) codec_demuxbus_write(r, val) +#define READ_DEMUX_REG(r) codec_demuxbus_read(r) +#define WRITE_DEMUX_REG_BITS(r, val, start, len) \ + WRITE_DEMUX_REG(r, (READ_DEMUX_REG(r) & ~(((1L<<(len))-1)<<(start)))|\ + ((unsigned int)((val)&((1L<<(len))-1)) << (start))) + +#define CLEAR_DEMUX_REG_MASK(r, mask)\ + WRITE_DEMUX_REG(r, READ_DEMUX_REG(r) & ~(mask)) +#define SET_DEMUX_REG_MASK(r, mask)\ + WRITE_DEMUX_REG(r, READ_DEMUX_REG(r) | (mask)) + +#define WRITE_RESET_REG(r, val) codec_resetbus_write(r, val) +#define READ_RESET_REG(r) codec_resetbus_read(r) +#define WRITE_RESET_REG_BITS(r, val, start, len) \ + WRITE_RESET_REG(r, (READ_RESET_REG(r) & ~(((1L<<(len))-1)<<(start)))|\ + ((unsigned int)((val)&((1L<<(len))-1)) << (start))) + +#define CLEAR_RESET_REG_MASK(r, mask)\ + WRITE_RESET_REG(r, READ_RESET_REG(r) & ~(mask)) +#define SET_RESET_REG_MASK(r, mask)\ + WRITE_RESET_REG(r, READ_RESET_REG(r) | (mask)) + #define ASSIST_MBOX1_CLR_REG VDEC_ASSIST_MBOX1_CLR_REG #define ASSIST_MBOX1_MASK VDEC_ASSIST_MBOX1_MASK #define ASSIST_AMR1_INT0 VDEC_ASSIST_AMR1_INT0 diff --git a/include/linux/amlogic/media/vfm/vframe.h b/include/linux/amlogic/media/vfm/vframe.h index 28abccc..0aa2f38 100644 --- a/include/linux/amlogic/media/vfm/vframe.h +++ b/include/linux/amlogic/media/vfm/vframe.h @@ -70,15 +70,8 @@ #define VFRAME_FLAG_NO_DISCONTINUE 1 #define VFRAME_FLAG_SWITCHING_FENSE 2 #define VFRAME_FLAG_HIGH_BANDWIDTH 4 - -#define TB_DETECT_MASK 0x00000040 -#define TB_DETECT_MASK_BIT 6 -#define TB_DETECT_NONE 0 -#define TB_DETECT_INVERT 1 -#define TB_DETECT_NC 0 -#define TB_DETECT_TFF 1 -#define TB_DETECT_BFF 2 -#define TB_DETECT_TBF 3 +#define VFRAME_FLAG_ERROR_RECOVERY 8 +#define VFRAME_FLAG_SYNCFRAME 0x10 enum pixel_aspect_ratio_e { PIXEL_ASPECT_RATIO_1_1, @@ -205,6 +198,12 @@ enum vframe_secam_phase_e { VFRAME_PHASE_DB = 0, VFRAME_PHASE_DR, }; +enum vframe_disp_mode_e { + VFRAME_DISP_MODE_NULL = 0, + VFRAME_DISP_MODE_UNKNOWN, + VFRAME_DISP_MODE_SKIP, + VFRAME_DISP_MODE_OK, +}; #define BITDEPTH_Y_SHIFT 8 #define BITDEPTH_Y8 (0 << BITDEPTH_Y_SHIFT) diff --git a/include/linux/amlogic/media/vfm/vframe_provider.h b/include/linux/amlogic/media/vfm/vframe_provider.h index 01a4ad4..081571e 100644 --- a/include/linux/amlogic/media/vfm/vframe_provider.h +++ b/include/linux/amlogic/media/vfm/vframe_provider.h @@ -38,6 +38,7 @@ struct vframe_states { #define VFRAME_EVENT_RECEIVER_RESET 0x20 #define VFRAME_EVENT_RECEIVER_FORCE_UNREG 0x40 #define VFRAME_EVENT_RECEIVER_GET_AUX_DATA 0x80 +#define VFRAME_EVENT_RECEIVER_DISP_MODE 0x100 /* for VFRAME_EVENT_RECEIVER_GET_AUX_DATA*/ struct provider_aux_req_s { @@ -49,6 +50,13 @@ struct provider_aux_req_s { int aux_size; int dv_enhance_exist; }; +struct provider_disp_mode_req_s { + /*input*/ + struct vframe_s *vf; + unsigned int req_mode;/*0:peak;1:get*/ + /*output*/ + enum vframe_disp_mode_e disp_mode; +}; struct vframe_operations_s { struct vframe_s *(*peek)(void *op_arg); @@ -63,6 +71,7 @@ struct vframe_provider_s { const struct vframe_operations_s *ops; void *op_arg; struct list_head list; + atomic_t use_cnt; void *traceget; void *traceput; } /*vframe_provider_t */; @@ -88,6 +97,10 @@ struct vframe_provider_s *vf_get_provider(const char *name); struct vframe_s *vf_peek(const char *receiver); struct vframe_s *vf_get(const char *receiver); void vf_put(struct vframe_s *vf, const char *receiver); +int vf_get_states(struct vframe_provider_s *vfp, + struct vframe_states *states); +int vf_get_states_by_name(const char *receiver_name, + struct vframe_states *states); unsigned int get_post_canvas(void); diff --git a/include/linux/amlogic/media/video_sink/amvideocap.h b/include/linux/amlogic/media/video_sink/amvideocap.h new file mode 100644 index 0000000..a94f411 --- /dev/null +++ b/include/linux/amlogic/media/video_sink/amvideocap.h @@ -0,0 +1,64 @@ +/* + * include/linux/amlogic/media/video_sink/amvideocap.h + * + * Copyright (C) 2017 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 __AMVIDEOCAP_HEADHER_ +#define __AMVIDEOCAP_HEADHER_ +#define AC_MAGIC 'V' +#include + +#define CAP_FLAG_AT_CURRENT 0 +#define CAP_FLAG_AT_TIME_WINDOW 1 +#define CAP_FLAG_AT_END 2 + +/* + *format see linux/ge2d/ge2d.h + *like: + *GE2D_FORMAT_S24_RGB + */ + +#define AMVIDEOCAP_IOW_SET_WANTFRAME_FORMAT _IOW((AC_MAGIC), 0x01, int) +#define AMVIDEOCAP_IOW_SET_WANTFRAME_WIDTH _IOW((AC_MAGIC), 0x02, int) +#define AMVIDEOCAP_IOW_SET_WANTFRAME_HEIGHT _IOW((AC_MAGIC), 0x03, int) +#define AMVIDEOCAP_IOW_SET_WANTFRAME_TIMESTAMP_MS _IOW((AC_MAGIC), 0x04, u64) +#define AMVIDEOCAP_IOW_SET_WANTFRAME_WAIT_MAX_MS _IOW((AC_MAGIC), 0x05, u64) +#define AMVIDEOCAP_IOW_SET_WANTFRAME_AT_FLAGS _IOW((AC_MAGIC), 0x06, int) + +#define AMVIDEOCAP_IOR_GET_FRAME_FORMAT _IOR((AC_MAGIC), 0x10, int) +#define AMVIDEOCAP_IOR_GET_FRAME_WIDTH _IOR((AC_MAGIC), 0x11, int) +#define AMVIDEOCAP_IOR_GET_FRAME_HEIGHT _IOR((AC_MAGIC), 0x12, int) +#define AMVIDEOCAP_IOR_GET_FRAME_TIMESTAMP_MS _IOR((AC_MAGIC), 0x13, int) + +#define AMVIDEOCAP_IOR_GET_SRCFRAME_FORMAT _IOR((AC_MAGIC), 0x20, int) +#define AMVIDEOCAP_IOR_GET_SRCFRAME_WIDTH _IOR((AC_MAGIC), 0x21, int) +#define AMVIDEOCAP_IOR_GET_SRCFRAME_HEIGHT _IOR((AC_MAGIC), 0x22, int) + +#define AMVIDEOCAP_IOR_GET_STATE _IOR((AC_MAGIC), 0x31, int) +#define AMVIDEOCAP_IOW_SET_START_CAPTURE _IOW((AC_MAGIC), 0x32, int) +#define AMVIDEOCAP_IOW_SET_CANCEL_CAPTURE _IOW((AC_MAGIC), 0x33, int) + +#define AMVIDEOCAP_IOR_SET_SRC_X _IOR((AC_MAGIC), 0x40, int) +#define AMVIDEOCAP_IOR_SET_SRC_Y _IOR((AC_MAGIC), 0x41, int) +#define AMVIDEOCAP_IOR_SET_SRC_WIDTH _IOR((AC_MAGIC), 0x42, int) +#define AMVIDEOCAP_IOR_SET_SRC_HEIGHT _IOR((AC_MAGIC), 0x43, int) + +enum amvideocap_state { + AMVIDEOCAP_STATE_INIT = 0, + AMVIDEOCAP_STATE_ON_CAPTURE = 200, + AMVIDEOCAP_STATE_FINISHED_CAPTURE = 300, + AMVIDEOCAP_STATE_ERROR = 0xffff, +}; +#endif /* __AMVIDEOCAP_HEADHER_ */ diff --git a/include/linux/amlogic/media/video_sink/ionvideo_ext.h b/include/linux/amlogic/media/video_sink/ionvideo_ext.h index 4e93164..2388ae6 100644 --- a/include/linux/amlogic/media/video_sink/ionvideo_ext.h +++ b/include/linux/amlogic/media/video_sink/ionvideo_ext.h @@ -20,7 +20,7 @@ extern int ionvideo_assign_map(char **receiver_name, int *inst); -extern int ionvideo_alloc_map(char **receiver_name, int *inst); +extern int ionvideo_alloc_map(int *inst); extern void ionvideo_release_map(int inst); diff --git a/include/linux/amlogic/media/video_sink/video.h b/include/linux/amlogic/media/video_sink/video.h index c2f5d4b..d6aca57 100644 --- a/include/linux/amlogic/media/video_sink/video.h +++ b/include/linux/amlogic/media/video_sink/video.h @@ -254,7 +254,8 @@ extern void set_clone_frame_rate(unsigned int frame_rate, unsigned int delay); #endif extern void prot_get_parameter(u32 wide_mode, struct vframe_s *vf, - struct vpp_frame_par_s *next_frame_par, const struct vinfo_s *vinfo); + struct vpp_frame_par_s *next_frame_par, + const struct vinfo_s *vinfo); u32 get_blackout_policy(void); int get_video0_frame_info(struct vframe_s *vf); diff --git a/include/linux/amlogic/media/video_sink/vpp.h b/include/linux/amlogic/media/video_sink/vpp.h index 1cf1d47..0808cde 100644 --- a/include/linux/amlogic/media/video_sink/vpp.h +++ b/include/linux/amlogic/media/video_sink/vpp.h @@ -132,6 +132,8 @@ struct vpp_frame_par_s { u32 spsc0_h_in; u32 spsc1_w_in; u32 spsc1_h_in; + u32 vpp_postblend_out_width; + u32 vpp_postblend_out_height; bool nocomp; @@ -152,10 +154,19 @@ struct vpp_frame_par_s { extern bool reverse; #endif extern bool platform_type; +extern unsigned int super_scaler; + enum select_scaler_path_e { sup0_pp_sp1_scpath, sup0_pp_post_blender, }; +/* + * note from vlsi!!! + * if core0 v enable,core0 input width max=1024; + * if core0 v disable,core0 input width max=2048; + * if core1 v enable,core1 input width max=2048; + * if core1 v disable,core1 input width max=4096; + */ #define SUPER_CORE0_WIDTH_MAX 2048 #define SUPER_CORE1_WIDTH_MAX 4096 @@ -177,6 +188,11 @@ enum select_scaler_path_e { #define MODE_3D_OUT_LR 0x00020000 #define MODE_FORCE_3D_TO_2D_LR 0x00100000 #define MODE_FORCE_3D_TO_2D_TB 0x00200000 +#define MODE_FORCE_3D_LR 0x01000000 +#define MODE_FORCE_3D_TB 0x02000000 +#define MODE_3D_FP 0x04000000 +#define MODE_FORCE_3D_FA_LR 0x10000000 +#define MODE_FORCE_3D_FA_TB 0x20000000 /*when the output mode is field alterlative*/ @@ -211,12 +227,13 @@ enum select_scaler_path_e { extern void vpp_set_3d_scale(bool enable); extern -void get_vpp_3d_mode(u32 trans_fmt, u32 *vpp_3d_mode); +void get_vpp_3d_mode(u32 process_3d_type, u32 trans_fmt, u32 *vpp_3d_mode); #endif extern void vpp_set_filters(u32 process_3d_type, u32 wide_mode, struct vframe_s *vf, - struct vpp_frame_par_s *next_frame_par, const struct vinfo_s *vinfo); + struct vpp_frame_par_s *next_frame_par, + const struct vinfo_s *vinfo); extern void vpp_set_video_source_crop(u32 t, u32 l, u32 b, u32 r); @@ -253,7 +270,8 @@ extern void vpp_bypass_ratio_config(void); #ifdef CONFIG_AM_VIDEO2 extern void vpp2_set_filters(u32 wide_mode, struct vframe_s *vf, - struct vpp_frame_par_s *next_frame_par, const struct vinfo_s *vinfo); + struct vpp_frame_par_s *next_frame_par, + const struct vinfo_s *vinfo); extern void vpp2_set_video_layer_position(s32 x, s32 y, s32 w, s32 h); @@ -266,14 +284,17 @@ extern u32 vpp2_get_zoom_ratio(void); extern int video_property_notify(int flag); extern int vpp_set_super_scaler_regs(int scaler_path_sel, - int reg_srscl0_enable, - int reg_srscl0_hsize, - int reg_srscl0_vsize, - int reg_srscl0_hori_ratio, - int reg_srscl0_vert_ratio, - int reg_srscl1_enable, - int reg_srscl1_hsize, - int reg_srscl1_vsize, - int reg_srscl1_hori_ratio, int reg_srscl1_vert_ratio); + int reg_srscl0_enable, + int reg_srscl0_hsize, + int reg_srscl0_vsize, + int reg_srscl0_hori_ratio, + int reg_srscl0_vert_ratio, + int reg_srscl1_enable, + int reg_srscl1_hsize, + int reg_srscl1_vsize, + int reg_srscl1_hori_ratio, + int reg_srscl1_vert_ratio, + int vpp_postblend_out_width, + int vpp_postblend_out_height); #endif /* VPP_H */ -- 2.7.4