Esempio n. 1
0
s32 amvdec2_loadmc(const u32 *p)
{
    if (HAS_VDEC2) {
        ulong timeout;
        s32 ret = 0;

#ifdef AMVDEC_USE_STATIC_MEMORY
        if (mc_addr == NULL)
#endif
        {
            mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
        }

        if (!mc_addr) {
            return -ENOMEM;
        }

        memcpy(mc_addr, p, MC_SIZE);

        mc_addr_map = dma_map_single(NULL, mc_addr, MC_SIZE, DMA_TO_DEVICE);

        WRITE_VREG(VDEC2_MPSR, 0);
        WRITE_VREG(VDEC2_CPSR, 0);

        /* Read CBUS register for timing */
        timeout = READ_VREG(VDEC2_MPSR);
        timeout = READ_VREG(VDEC2_MPSR);

        timeout = jiffies + HZ;

        WRITE_VREG(VDEC2_IMEM_DMA_ADR, mc_addr_map);
        WRITE_VREG(VDEC2_IMEM_DMA_COUNT, 0x1000);
        WRITE_VREG(VDEC2_IMEM_DMA_CTRL, (0x8000 | (7 << 16)));

        while (READ_VREG(VDEC2_IMEM_DMA_CTRL) & 0x8000) {
            if (time_before(jiffies, timeout)) {
                schedule();
            } else {
                printk("vdec2 load mc error\n");
                ret = -EBUSY;
                break;
            }
        }

        dma_unmap_single(NULL, mc_addr_map, MC_SIZE, DMA_TO_DEVICE);

#ifndef AMVDEC_USE_STATIC_MEMORY
        kfree(mc_addr);
        mc_addr = NULL;
#endif

        return ret;
    }
    else
    {
        return 0;
    }
}
Esempio n. 2
0
static inline u32 buf_wp(u32 type)
{
    u32 wp = 
#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
    (type == BUF_TYPE_HEVC) ? READ_VREG(HEVC_STREAM_WR_PTR) :
#endif
    (type == BUF_TYPE_VIDEO) ? READ_VREG(VLD_MEM_VIFIFO_WP) :
    (type == BUF_TYPE_AUDIO) ? READ_MPEG_REG(AIU_MEM_AIFIFO_MAN_WP) :
                               READ_MPEG_REG(PARSER_SUB_START_PTR);

    return wp;
}
Esempio n. 3
0
u32 stbuf_space(struct stream_buf_s *buf)
{
    /* reserved space for safe write, the parser fifo size is 1024byts, so reserve it */
    int size;

#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
    if (HAS_HEVC_VDEC && buf->type == BUF_TYPE_HEVC)
        size = buf->canusebuf_size - READ_VREG(HEVC_STREAM_LEVEL);
    else 
#endif
        size = (buf->canusebuf_size - _READ_ST_REG(LEVEL)) ;

#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD
    if ((buf->type == BUF_TYPE_VIDEO) && (vdec_on(VDEC_2))) {
        if ((_READ_VDEC2_ST_REG(START_PTR) == _READ_ST_REG(START_PTR)) &&
            (_READ_VDEC2_ST_REG(END_PTR)   == _READ_ST_REG(END_PTR))   &&
            (_READ_VDEC2_ST_REG(CONTROL) & MEM_CTRL_FILL_EN)) {
            size = min(size, (int)(buf->canusebuf_size - _READ_VDEC2_ST_REG(LEVEL)));
        }
    }
#endif

    if(buf->canusebuf_size>=buf->buf_size/2)
        size=size-6*1024;//old reversed value,tobe full, reversed only...

    if ((buf->type == BUF_TYPE_VIDEO) || (HAS_HEVC_VDEC && buf->type == BUF_TYPE_HEVC)) {
        size -= READ_MPEG_REG(PARSER_VIDEO_HOLE);
    }

    return size > 0 ? size : 0;
}
Esempio n. 4
0
s32 amhcodec_loadmc(const u32 *p)
{
#ifdef AMVDEC_USE_STATIC_MEMORY
    if (mc_addr == NULL)
#endif
    {
        mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
    }

    if (!mc_addr) {
        return -ENOMEM;
    }

    memcpy(mc_addr, p, MC_SIZE);

    mc_addr_map = dma_map_single(NULL, mc_addr, MC_SIZE, DMA_TO_DEVICE);

    WRITE_VREG(HCODEC_IMEM_DMA_ADR, mc_addr_map);
    WRITE_VREG(HCODEC_IMEM_DMA_COUNT, 0x100);
    WRITE_VREG(HCODEC_IMEM_DMA_CTRL, (0x8000 | (7 << 16)));

    while (READ_VREG(HCODEC_IMEM_DMA_CTRL) & 0x8000) {
        udelay(1000);
    }

    dma_unmap_single(NULL, mc_addr_map, MC_SIZE, DMA_TO_DEVICE);

#ifndef AMVDEC_USE_STATIC_MEMORY
    kfree(mc_addr);
#endif

    return 0;
}
Esempio n. 5
0
static irqreturn_t jpegdec_isr(int irq, void *dev_id)
{
    WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);

    if ((dec->state & JPEGDEC_STAT_INFO_READY) == 0) {
        dec->info.width = READ_VREG(JPEG_PIC_WIDTH);
        dec->info.height = READ_VREG(JPEG_PIC_HEIGHT);
        dec->info.comp_num = READ_VREG(JPEG_INFO) >> 1;

        pr_dbg("ucode report picture size %dx%d, comp_num %d\n",
               dec->info.width, dec->info.height, dec->info.comp_num);

        if ((dec->info.comp_num != 1) && (dec->info.comp_num != 3)) {
            dec->state |= JPEGDEC_STAT_INFO_READY | JPEGDEC_STAT_UNSUPPORT;
        } else {
            dec->state |= JPEGDEC_STAT_INFO_READY | JPEGDEC_STAT_WAIT_DECCONFIG;
        }
    } else {
Esempio n. 6
0
u32 stbuf_rp(struct stream_buf_s *buf)
{
#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
    if (HAS_HEVC_VDEC)
        return (buf->type == BUF_TYPE_HEVC) ? READ_VREG(HEVC_STREAM_RD_PTR) : _READ_ST_REG(RP);
    else
#endif
        return _READ_ST_REG(RP);
}
Esempio n. 7
0
static void amhevc_pg_enable(bool enable)
{
#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
    if (HAS_HEVC_VDEC) {
        ulong timeout;
        if(!vdec_on(VDEC_HEVC))
            return;
        if (enable) {
    //        WRITE_VREG(VDEC2_GCLK_EN, 0x3ff);
        } else {
            timeout = jiffies + HZ / 10;

            while (READ_VREG(HEVC_MDEC_PIC_DC_STATUS) != 0) {
                if (time_after(jiffies, timeout)) {
                    WRITE_VREG_BITS(HEVC_MDEC_PIC_DC_CTRL, 1, 0, 1);
                    WRITE_VREG_BITS(HEVC_MDEC_PIC_DC_CTRL, 0, 0, 1);
                    READ_VREG(HEVC_MDEC_PIC_DC_STATUS);
                    READ_VREG(HEVC_MDEC_PIC_DC_STATUS);
                    READ_VREG(HEVC_MDEC_PIC_DC_STATUS);
                    break;
                }
            }

            timeout = jiffies + HZ / 10;

            while (READ_VREG(HEVC_DBLK_STATUS) & 1) {
                if (time_after(jiffies, timeout)) {
                    WRITE_VREG(HEVC_DBLK_CTRL, 3);
                    WRITE_VREG(HEVC_DBLK_CTRL, 0);
                    READ_VREG(HEVC_DBLK_STATUS);
                    READ_VREG(HEVC_DBLK_STATUS);
                    READ_VREG(HEVC_DBLK_STATUS);
                    break;
                }
            }

            timeout = jiffies + HZ / 10;

            while (READ_VREG(HEVC_DCAC_DMA_CTRL) & 0x8000) {
                if (time_after(jiffies, timeout)) {
                    break;
                }
            }
        }
    }
#endif
}
Esempio n. 8
0
static void amvdec2_pg_enable(bool enable)
{
    if (HAS_VDEC2)
    {
        ulong timeout;
        if(!vdec_on(VDEC_2))
            return;
        if (enable) {
    //        WRITE_VREG(VDEC2_GCLK_EN, 0x3ff);
        } else {
            timeout = jiffies + HZ / 10;

            while (READ_VREG(VDEC2_MDEC_PIC_DC_STATUS) != 0) {
                if (time_after(jiffies, timeout)) {
                    WRITE_VREG_BITS(VDEC2_MDEC_PIC_DC_CTRL, 1, 0, 1);
                    WRITE_VREG_BITS(VDEC2_MDEC_PIC_DC_CTRL, 0, 0, 1);
                    READ_VREG(VDEC2_MDEC_PIC_DC_STATUS);
                    READ_VREG(VDEC2_MDEC_PIC_DC_STATUS);
                    READ_VREG(VDEC2_MDEC_PIC_DC_STATUS);
                    break;
                }
            }

            timeout = jiffies + HZ / 10;

            while (READ_VREG(VDEC2_DBLK_STATUS) & 1) {
                if (time_after(jiffies, timeout)) {
                    WRITE_VREG(VDEC2_DBLK_CTRL, 3);
                    WRITE_VREG(VDEC2_DBLK_CTRL, 0);
                    READ_VREG(VDEC2_DBLK_STATUS);
                    READ_VREG(VDEC2_DBLK_STATUS);
                    READ_VREG(VDEC2_DBLK_STATUS);
                    break;
                }
            }

            timeout = jiffies + HZ / 10;

            while (READ_VREG(VDEC2_DCAC_DMA_CTRL) & 0x8000) {
                if (time_after(jiffies, timeout)) {
                    break;
                }
            }
        }
    }
}
Esempio n. 9
0
static void amhevc_pg_enable(bool enable)
{
	if (has_hevc_vdec()) {
		ulong timeout;
		if (!vdec_on(VDEC_HEVC))
			return;
		if (enable) {
			/* WRITE_VREG(VDEC2_GCLK_EN, 0x3ff); */
		} else {
			timeout = jiffies + HZ / 10;

			while (READ_VREG(HEVC_MDEC_PIC_DC_STATUS) != 0) {
				if (time_after(jiffies, timeout)) {
					WRITE_VREG_BITS(HEVC_MDEC_PIC_DC_CTRL,
						1, 0, 1);
					WRITE_VREG_BITS(HEVC_MDEC_PIC_DC_CTRL,
						0, 0, 1);
					READ_VREG(HEVC_MDEC_PIC_DC_STATUS);
					READ_VREG(HEVC_MDEC_PIC_DC_STATUS);
					READ_VREG(HEVC_MDEC_PIC_DC_STATUS);
					break;
				}
			}

			timeout = jiffies + HZ / 10;

			while (READ_VREG(HEVC_DBLK_STATUS) & 1) {
				if (time_after(jiffies, timeout)) {
					WRITE_VREG(HEVC_DBLK_CTRL, 3);
					WRITE_VREG(HEVC_DBLK_CTRL, 0);
					READ_VREG(HEVC_DBLK_STATUS);
					READ_VREG(HEVC_DBLK_STATUS);
					READ_VREG(HEVC_DBLK_STATUS);
					break;
				}
			}

			timeout = jiffies + HZ / 10;

			while (READ_VREG(HEVC_DCAC_DMA_CTRL) & 0x8000) {
				if (time_after(jiffies, timeout))
					break;
			}
		}
	}
}
Esempio n. 10
0
static int vdec_is_paused(void)
{
    static unsigned long old_wp = -1, old_rp = -1, old_level = -1;
    unsigned long wp, rp, level;
    static int  paused_time = 0;

#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
    if (HAS_HEVC_VDEC) {
        if ((vdec_on(VDEC_HEVC)) && (READ_VREG(HEVC_STREAM_CONTROL) & 1)) {
            wp = READ_VREG(HEVC_STREAM_WR_PTR);
            rp = READ_VREG(HEVC_STREAM_RD_PTR);
            level = READ_VREG(HEVC_STREAM_LEVEL);
        } else {
            wp = READ_VREG(VLD_MEM_VIFIFO_WP);
            rp = READ_VREG(VLD_MEM_VIFIFO_RP);
            level = READ_VREG(VLD_MEM_VIFIFO_LEVEL);
        }
    } else
#endif
    {
        wp = READ_VREG(VLD_MEM_VIFIFO_WP);
        rp = READ_VREG(VLD_MEM_VIFIFO_RP);
        level = READ_VREG(VLD_MEM_VIFIFO_LEVEL);
    }

    if ((rp == old_rp && level > 1024) || /*have data,but output buffer is full */
        (rp == old_rp && wp == old_wp && level == level)) { /*no write && not read*/
        paused_time++;
    } else {
        paused_time = 0;
    }
    old_wp = wp;
    old_rp = rp;
    old_level = level;

    if (paused_time > 10) {
        return 1;
    }
    return 0;
}
Esempio n. 11
0
void amvdec_start(void)
{
#ifdef CONFIG_WAKELOCK
    amvdec_wake_lock();
#endif

#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6
    READ_VREG(DOS_SW_RESET0);
    READ_VREG(DOS_SW_RESET0);
    READ_VREG(DOS_SW_RESET0);

    WRITE_VREG(DOS_SW_RESET0, (1<<12)|(1<<11));
    WRITE_VREG(DOS_SW_RESET0, 0);

    READ_VREG(DOS_SW_RESET0);
    READ_VREG(DOS_SW_RESET0);
    READ_VREG(DOS_SW_RESET0);
#else
    /* additional cbus dummy register reading for timing control */
    READ_MPEG_REG(RESET0_REGISTER);
    READ_MPEG_REG(RESET0_REGISTER);
    READ_MPEG_REG(RESET0_REGISTER);
    READ_MPEG_REG(RESET0_REGISTER);

    WRITE_MPEG_REG(RESET0_REGISTER, RESET_VCPU | RESET_CCPU);

    READ_MPEG_REG(RESET0_REGISTER);
    READ_MPEG_REG(RESET0_REGISTER);
    READ_MPEG_REG(RESET0_REGISTER);
#endif

    WRITE_VREG(MPSR, 0x0001);
}
Esempio n. 12
0
void amhevc_stop(void)
{
	if (has_hevc_vdec()) {
		ulong timeout = jiffies + HZ;

		WRITE_VREG(HEVC_MPSR, 0);
		WRITE_VREG(HEVC_CPSR, 0);

		while (READ_VREG(HEVC_IMEM_DMA_CTRL) & 0x8000) {
			if (time_after(jiffies, timeout))
				break;
		}

		READ_VREG(DOS_SW_RESET3);
		READ_VREG(DOS_SW_RESET3);
		READ_VREG(DOS_SW_RESET3);

#ifdef CONFIG_WAKELOCK
		amvdec_wake_unlock();
#endif
	}
}
Esempio n. 13
0
void amvdec2_stop(void)
{
    if (HAS_VDEC2) {
        ulong timeout = jiffies + HZ;

        WRITE_VREG(VDEC2_MPSR, 0);
        WRITE_VREG(VDEC2_CPSR, 0);

        while (READ_VREG(VDEC2_IMEM_DMA_CTRL) & 0x8000) {
            if (time_after(jiffies, timeout)) {
                break;
            }
        }

        READ_VREG(DOS_SW_RESET2);
        READ_VREG(DOS_SW_RESET2);
        READ_VREG(DOS_SW_RESET2);

#ifdef CONFIG_WAKELOCK
        amvdec_wake_unlock();
#endif
    }
}
Esempio n. 14
0
static int vdec_is_paused(void)
{
    static unsigned long old_wp = -1, old_rp = -1, old_level = -1;
    unsigned long wp, rp, level;
    static int  paused_time = 0;

    wp = READ_VREG(VLD_MEM_VIFIFO_WP);
    rp = READ_VREG(VLD_MEM_VIFIFO_RP);
    level = READ_VREG(VLD_MEM_VIFIFO_LEVEL);
    if ((rp == old_rp && level > 1024) || /*have data,but output buffer is fulle*/
        (rp == old_rp && wp == old_wp && level == level)) { /*no write && not read*/
        paused_time++;
    } else {
        paused_time = 0;
    }
    old_wp = wp;
    old_rp = rp;
    old_level = level;

    if (paused_time > 10) {
        return 1;
    }
    return 0;
}
Esempio n. 15
0
void amvdec_stop(void)
{
    ulong timeout = jiffies + HZ;

    WRITE_VREG(MPSR, 0);
    WRITE_VREG(CPSR, 0);

    while (READ_VREG(IMEM_DMA_CTRL) & 0x8000) {
        if (time_after(jiffies, timeout)) {
            break;
        }
    }

#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6
    READ_VREG(DOS_SW_RESET0);
    READ_VREG(DOS_SW_RESET0);
    READ_VREG(DOS_SW_RESET0);

    WRITE_VREG(DOS_SW_RESET0, (1<<12)|(1<<11));
    WRITE_VREG(DOS_SW_RESET0, 0);

    READ_VREG(DOS_SW_RESET0);
    READ_VREG(DOS_SW_RESET0);
    READ_VREG(DOS_SW_RESET0);
#else
    WRITE_MPEG_REG(RESET0_REGISTER, RESET_VCPU | RESET_CCPU);

    /* additional cbus dummy register reading for timing control */
    READ_MPEG_REG(RESET0_REGISTER);
    READ_MPEG_REG(RESET0_REGISTER);
    READ_MPEG_REG(RESET0_REGISTER);
    READ_MPEG_REG(RESET0_REGISTER);
#endif

#ifdef CONFIG_WAKELOCK
    amvdec_wake_unlock();
#endif
}
Esempio n. 16
0
void amvdec2_start(void)
{
    if (HAS_VDEC2) {
#ifdef CONFIG_WAKELOCK
        amvdec_wake_lock();
#endif

        READ_VREG(DOS_SW_RESET2);
        READ_VREG(DOS_SW_RESET2);
        READ_VREG(DOS_SW_RESET2);

        WRITE_VREG(DOS_SW_RESET2, (1<<12)|(1<<11));
        WRITE_VREG(DOS_SW_RESET2, 0);

        READ_VREG(DOS_SW_RESET2);
        READ_VREG(DOS_SW_RESET2);
        READ_VREG(DOS_SW_RESET2);

        WRITE_VREG(VDEC2_MPSR, 0x0001);
    }
}
Esempio n. 17
0
void amhevc_start(void)
{
    if (HAS_HEVC_VDEC) {
#ifdef CONFIG_WAKELOCK
        amvdec_wake_lock();
#endif

        READ_VREG(DOS_SW_RESET3);
        READ_VREG(DOS_SW_RESET3);
        READ_VREG(DOS_SW_RESET3);

        WRITE_VREG(DOS_SW_RESET3, (1<<12)|(1<<11));
        WRITE_VREG(DOS_SW_RESET3, 0);

        READ_VREG(DOS_SW_RESET3);
        READ_VREG(DOS_SW_RESET3);
        READ_VREG(DOS_SW_RESET3);

        WRITE_VREG(HEVC_MPSR, 0x0001);
    }
}
Esempio n. 18
0
s32 tsdemux_init(u32 vid, u32 aid, u32 sid, u32 pcrid, bool is_hevc)
{
    s32 r;
    u32 parser_sub_start_ptr;
    u32 parser_sub_end_ptr;
    u32 parser_sub_rp;

#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6
    switch_mod_gate_by_type(MOD_DEMUX, 1);
#endif

    parser_sub_start_ptr = READ_MPEG_REG(PARSER_SUB_START_PTR);
    parser_sub_end_ptr = READ_MPEG_REG(PARSER_SUB_END_PTR);
    parser_sub_rp = READ_MPEG_REG(PARSER_SUB_RP);

    WRITE_MPEG_REG(RESET1_REGISTER, RESET_PARSER);

#ifdef ENABLE_DEMUX_DRIVER
    tsdemux_reset();
#else
    WRITE_MPEG_REG(RESET1_REGISTER, RESET_PARSER | RESET_DEMUXSTB);

    WRITE_MPEG_REG(STB_TOP_CONFIG, 0);
    WRITE_MPEG_REG(DEMUX_CONTROL, 0);
#endif

    /* set PID filter */
    printk("tsdemux video_pid = 0x%x, audio_pid = 0x%x, sub_pid = 0x%x, pcrid = 0x%x\n",
           vid, aid, sid, pcr_pid);

#ifndef ENABLE_DEMUX_DRIVER
    WRITE_MPEG_REG(FM_WR_DATA,
                   (((vid & 0x1fff) | (VIDEO_PACKET << 13)) << 16) |
                   ((aid & 0x1fff) | (AUDIO_PACKET << 13)));
    WRITE_MPEG_REG(FM_WR_ADDR, 0x8000);
    while (READ_MPEG_REG(FM_WR_ADDR) & 0x8000) {
        ;
    }

    WRITE_MPEG_REG(FM_WR_DATA,
                   (((sid & 0x1fff) | (SUB_PACKET << 13)) << 16) | 0xffff);
    WRITE_MPEG_REG(FM_WR_ADDR, 0x8001);
    while (READ_MPEG_REG(FM_WR_ADDR) & 0x8000) {
        ;
    }

    WRITE_MPEG_REG(MAX_FM_COMP_ADDR, 1);

    WRITE_MPEG_REG(STB_INT_MASK, 0);
    WRITE_MPEG_REG(STB_INT_STATUS, 0xffff);

    /* TS data path */
    WRITE_MPEG_REG(FEC_INPUT_CONTROL, 0x7000);
    WRITE_MPEG_REG(DEMUX_MEM_REQ_EN,
                   (1 << VIDEO_PACKET) |
                   (1 << AUDIO_PACKET) |
                   (1 << SUB_PACKET));
    WRITE_MPEG_REG(DEMUX_ENDIAN,
                   (7 << OTHER_ENDIAN)  |
                   (7 << BYPASS_ENDIAN) |
                   (0 << SECTION_ENDIAN));
    WRITE_MPEG_REG(TS_HIU_CTL, 1 << USE_HI_BSF_INTERFACE);
    WRITE_MPEG_REG(TS_FILE_CONFIG,
                   (demux_skipbyte << 16)                  |
                   (6 << DES_OUT_DLY)                      |
                   (3 << TRANSPORT_SCRAMBLING_CONTROL_ODD) |
                   (1 << TS_HIU_ENABLE)                    |
                   (4 << FEC_FILE_CLK_DIV));

    /* enable TS demux */
    WRITE_MPEG_REG(DEMUX_CONTROL, (1 << STB_DEMUX_ENABLE) | (1 << KEEP_DUPLICATE_PACKAGE));
#endif

    if (fetchbuf == 0) {
        printk("%s: no fetchbuf\n", __FUNCTION__);
        return -ENOMEM;
    }

    /* hook stream buffer with PARSER */
#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
    if (HAS_HEVC_VDEC && is_hevc) {
        WRITE_MPEG_REG(PARSER_VIDEO_START_PTR,
                       READ_VREG(HEVC_STREAM_START_ADDR));
        WRITE_MPEG_REG(PARSER_VIDEO_END_PTR,
                       READ_VREG(HEVC_STREAM_END_ADDR) - 8);

        CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR);

        WRITE_VREG(DOS_GEN_CTRL0, 3<<1);    // set vififo_vbuf_rp_sel=>hevc

        SET_VREG_MASK(HEVC_STREAM_CONTROL, (1<<3)|(0<<4)); // set use_parser_vbuf_wp
        SET_VREG_MASK(HEVC_STREAM_CONTROL, 1); // set stream_fetch_enable
        SET_VREG_MASK(HEVC_STREAM_FIFO_CTL, (1<<29)); // set stream_buffer_hole with 256 bytes
    } else
#endif
    {
        WRITE_MPEG_REG(PARSER_VIDEO_START_PTR,
                       READ_VREG(VLD_MEM_VIFIFO_START_PTR));
        WRITE_MPEG_REG(PARSER_VIDEO_END_PTR,
                       READ_VREG(VLD_MEM_VIFIFO_END_PTR));
        CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR);

        WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
        CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);

        if (HAS_HEVC_VDEC) {
            WRITE_VREG(DOS_GEN_CTRL0, 0);    // set vififo_vbuf_rp_sel=>vdec
        }
    }

    WRITE_MPEG_REG(PARSER_AUDIO_START_PTR,
                   READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR));
    WRITE_MPEG_REG(PARSER_AUDIO_END_PTR,
                   READ_MPEG_REG(AIU_MEM_AIFIFO_END_PTR));
    CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR);

    WRITE_MPEG_REG(PARSER_CONFIG,
                   (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) |
                   (1  << PS_CFG_MAX_ES_WR_CYCLE_BIT) |
                   (16 << PS_CFG_MAX_FETCH_CYCLE_BIT));

    WRITE_MPEG_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
    CLEAR_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);

    WRITE_MPEG_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr);
    WRITE_MPEG_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr);
    WRITE_MPEG_REG(PARSER_SUB_RP, parser_sub_rp);
    SET_MPEG_REG_MASK(PARSER_ES_CONTROL, (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR);

#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
    if (HAS_HEVC_VDEC)
        r = pts_start((is_hevc) ? PTS_TYPE_HEVC : PTS_TYPE_VIDEO);
    else
#endif
        r = pts_start(PTS_TYPE_VIDEO);

    if (r < 0) {
        printk("Video pts start failed.(%d)\n", r);
        goto err1;
    }

    if ((r = pts_start(PTS_TYPE_AUDIO)) < 0) {
        printk("Audio pts start failed.(%d)\n", r);
        goto err2;
    }

    r = request_irq(INT_PARSER, parser_isr,
                    IRQF_SHARED, "tsdemux-fetch",
                    (void *)tsdemux_fetch_id);
    if (r) {
        goto err3;
    }

    WRITE_MPEG_REG(PARSER_INT_STATUS, 0xffff);
    WRITE_MPEG_REG(PARSER_INT_ENABLE, PARSER_INTSTAT_FETCH_CMD << PARSER_INT_HOST_EN_BIT);

    WRITE_MPEG_REG(PARSER_VIDEO_HOLE, 0x400);
    WRITE_MPEG_REG(PARSER_AUDIO_HOLE, 0x400);

    discontinued_counter = 0;
#ifndef ENABLE_DEMUX_DRIVER
    r = request_irq(INT_DEMUX, tsdemux_isr,
                    IRQF_SHARED, "tsdemux-irq",
                    (void *)tsdemux_irq_id);
    WRITE_MPEG_REG(STB_INT_MASK,
                   (1 << SUB_PES_READY)
                   | (1 << NEW_PDTS_READY)
                   | (1 << DIS_CONTINUITY_PACKET));
    if (r) {
        goto err4;
    }
#else
    tsdemux_config();
    tsdemux_request_irq(tsdemux_isr, (void *)tsdemux_irq_id);
    if (vid < 0x1FFF) {
		curr_vid_id = vid;
        tsdemux_set_vid(vid);
    }
    if (aid < 0x1FFF) {
		curr_aud_id = aid;
        tsdemux_set_aid(aid);
    }
    if (sid < 0x1FFF) {
		curr_sub_id = sid;
        tsdemux_set_sid(sid);
    }

	curr_pcr_id = pcr_pid;
    if ((pcr_pid < 0x1FFF) && (pcr_pid != vid) && (pcr_pid != aid) && (pcr_pid != sid)) {
	tsdemux_set_pcrid(pcr_pid);
	}
#endif

	reset_pcr_regs();
	first_pcr = 0;
    pcrscr_valid=1;

    return 0;

#ifndef ENABLE_DEMUX_DRIVER
err4:
    free_irq(INT_PARSER, (void *)tsdemux_fetch_id);
#endif
err3:
    pts_stop(PTS_TYPE_AUDIO);
err2:
#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
    if (HAS_HEVC_VDEC)
        pts_stop((is_hevc) ? PTS_TYPE_HEVC : PTS_TYPE_VIDEO);
    else
#endif
        pts_stop(PTS_TYPE_VIDEO);
err1:
    printk("TS Demux init failed.\n");
    return -ENOENT;
}
Esempio n. 19
0
static void amvdec_pg_enable(bool enable)
{
	ulong timeout;

	if (enable) {
		AMVDEC_CLK_GATE_ON(MDEC_CLK_PIC_DC);
		AMVDEC_CLK_GATE_ON(MDEC_CLK_DBLK);
		AMVDEC_CLK_GATE_ON(MC_CLK);
		AMVDEC_CLK_GATE_ON(IQIDCT_CLK);
		/* AMVDEC_CLK_GATE_ON(VLD_CLK); */
		AMVDEC_CLK_GATE_ON(AMRISC);
		/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */
		if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8)
			WRITE_VREG(GCLK_EN, 0x3ff);
		/* #endif */
		CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31);
	} else {

		AMVDEC_CLK_GATE_OFF(AMRISC);
		timeout = jiffies + HZ / 10;

		while (READ_VREG(MDEC_PIC_DC_STATUS) != 0) {
			if (time_after(jiffies, timeout)) {
				WRITE_VREG_BITS(MDEC_PIC_DC_CTRL, 1, 0, 1);
				WRITE_VREG_BITS(MDEC_PIC_DC_CTRL, 0, 0, 1);
				READ_VREG(MDEC_PIC_DC_STATUS);
				READ_VREG(MDEC_PIC_DC_STATUS);
				READ_VREG(MDEC_PIC_DC_STATUS);
				break;
			}
		}

		AMVDEC_CLK_GATE_OFF(MDEC_CLK_PIC_DC);
		timeout = jiffies + HZ / 10;

		while (READ_VREG(DBLK_STATUS) & 1) {
			if (time_after(jiffies, timeout)) {
				WRITE_VREG(DBLK_CTRL, 3);
				WRITE_VREG(DBLK_CTRL, 0);
				READ_VREG(DBLK_STATUS);
				READ_VREG(DBLK_STATUS);
				READ_VREG(DBLK_STATUS);
				break;
			}
		}
		AMVDEC_CLK_GATE_OFF(MDEC_CLK_DBLK);
		timeout = jiffies + HZ / 10;

		while (READ_VREG(MC_STATUS0) & 1) {
			if (time_after(jiffies, timeout)) {
				SET_VREG_MASK(MC_CTRL1, 0x9);
				CLEAR_VREG_MASK(MC_CTRL1, 0x9);
				READ_VREG(MC_STATUS0);
				READ_VREG(MC_STATUS0);
				READ_VREG(MC_STATUS0);
				break;
			}
		}
		AMVDEC_CLK_GATE_OFF(MC_CLK);
		timeout = jiffies + HZ / 10;
		while (READ_VREG(DCAC_DMA_CTRL) & 0x8000) {
			if (time_after(jiffies, timeout))
				break;
		}
		AMVDEC_CLK_GATE_OFF(IQIDCT_CLK);
		/* AMVDEC_CLK_GATE_OFF(VLD_CLK); */
	}
}
Esempio n. 20
0
static void amvdec_pg_enable(bool enable)
{
    ulong timeout;

    if (enable) {
        AMVDEC_CLK_GATE_ON(MDEC_CLK_PIC_DC);
        AMVDEC_CLK_GATE_ON(MDEC_CLK_DBLK);
        AMVDEC_CLK_GATE_ON(MC_CLK);
        AMVDEC_CLK_GATE_ON(IQIDCT_CLK);
        //AMVDEC_CLK_GATE_ON(VLD_CLK);
        AMVDEC_CLK_GATE_ON(AMRISC);
    } else {
        AMVDEC_CLK_GATE_OFF(AMRISC);

        timeout = jiffies + HZ / 10;

        while (READ_VREG(MDEC_PIC_DC_STATUS) != 0) {
            if (time_after(jiffies, timeout)) {
                WRITE_VREG_BITS(MDEC_PIC_DC_CTRL, 1, 0, 1);
                WRITE_VREG_BITS(MDEC_PIC_DC_CTRL, 0, 0, 1);
                READ_VREG(MDEC_PIC_DC_STATUS);
                READ_VREG(MDEC_PIC_DC_STATUS);
                READ_VREG(MDEC_PIC_DC_STATUS);
                break;
            }
        }

        AMVDEC_CLK_GATE_OFF(MDEC_CLK_PIC_DC);

        timeout = jiffies + HZ / 10;

        while (READ_VREG(DBLK_STATUS) & 1) {
            if (time_after(jiffies, timeout)) {
                WRITE_VREG(DBLK_CTRL, 3);
                WRITE_VREG(DBLK_CTRL, 0);
                READ_VREG(DBLK_STATUS);
                READ_VREG(DBLK_STATUS);
                READ_VREG(DBLK_STATUS);
                break;
            }
        }
        AMVDEC_CLK_GATE_OFF(MDEC_CLK_DBLK);

        timeout = jiffies + HZ / 10;

        while (READ_VREG(MC_STATUS0) & 1) {
            if (time_after(jiffies, timeout)) {
                SET_VREG_MASK(MC_CTRL1, 0x9);
                CLEAR_VREG_MASK(MC_CTRL1, 0x9);
                READ_VREG(MC_STATUS0);
                READ_VREG(MC_STATUS0);
                READ_VREG(MC_STATUS0);
                break;
            }
        }
        AMVDEC_CLK_GATE_OFF(MC_CLK);

        timeout = jiffies + HZ / 10;
        while (READ_VREG(DCAC_DMA_CTRL) & 0x8000) {
            if (time_after(jiffies, timeout)) {
                break;
            }
        }

        AMVDEC_CLK_GATE_OFF(IQIDCT_CLK);

        //AMVDEC_CLK_GATE_OFF(VLD_CLK);
    }
}
Esempio n. 21
0
static irqreturn_t vmjpeg_isr(int irq, void *dev_id)
{
    u32 reg, offset, pts, pts_valid = 0;
    vframe_t *vf = NULL;

    WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);

    reg = READ_VREG(MREG_FROM_AMRISC);

    if (reg & PICINFO_BUF_IDX_MASK) {
        offset = READ_VREG(MREG_FRAME_OFFSET);

        if (pts_lookup_offset(PTS_TYPE_VIDEO, offset, &pts, 0) == 0) {
            pts_valid = 1;
        }

        if ((reg & PICINFO_INTERLACE) == 0) {
            u32 index = ((reg & PICINFO_BUF_IDX_MASK) - 1) & 3;

            if (index >= DECODE_BUFFER_NUM_MAX) {
                printk("fatal error, invalid buffer index.");
                return IRQ_HANDLED;
            }

            if (kfifo_get(&newframe_q, &vf) == 0) {
                printk("fatal error, no available buffer slot.");
                return IRQ_HANDLED;
            }

            set_frame_info(vf);

            vf->index = index;
#ifdef NV21
            vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | VIDTYPE_VIU_NV21;
#else
            vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD;
#endif
            vf->canvas0Addr = vf->canvas1Addr = index2canvas0(index);
            vf->pts = (pts_valid) ? pts : 0;
			vf->orientation = 0 ;
            vfbuf_use[index]++;

            kfifo_put(&display_q, (const vframe_t **)&vf);

            vf_notify_receiver(PROVIDER_NAME,VFRAME_EVENT_PROVIDER_VFRAME_READY,NULL);               

        } else {
            u32 index = ((reg & PICINFO_BUF_IDX_MASK) - 1) & 3;

            if (index >= DECODE_BUFFER_NUM_MAX) {
                printk("fatal error, invalid buffer index.");
                return IRQ_HANDLED;
            }

            if (kfifo_get(&newframe_q, &vf) == 0) {
                printk("fatal error, no available buffer slot.");
                return IRQ_HANDLED;
            }

            set_frame_info(vf);

            vf->index = index;
#if 0
            if (reg & PICINFO_AVI1) {
                /* AVI1 format */
                if (reg & PICINFO_INTERLACE_AVI1_BOT) {
                    vf->type = VIDTYPE_INTERLACE_BOTTOM | VIDTYPE_INTERLACE_FIRST;
                } else {
                    vf->type = VIDTYPE_INTERLACE_TOP;
                }
            } else {
                if (reg & PICINFO_INTERLACE_FIRST) {
                    vf->type = VIDTYPE_INTERLACE_TOP | VIDTYPE_INTERLACE_FIRST;
                } else {
                    vf->type = VIDTYPE_INTERLACE_BOTTOM;
                }
            }

            vf->type |= VIDTYPE_VIU_FIELD;
#ifdef NV21
            vf->type |= VIDTYPE_VIU_NV21;
#endif
            vf->duration >>= 1;
            vf->canvas0Addr = vf->canvas1Addr = index2canvas0(index);
			vf->orientation = 0 ;
            if ((vf->type & VIDTYPE_INTERLACE_FIRST) && (pts_valid)) {
                vf->pts = pts;
            } else {
                vf->pts = 0;
            }

            vfbuf_use[index]++;

            kfifo_put(&display_q, (const vframe_t **)&vf);
#else
            /* send whole frame by weaving top & bottom field */
#ifdef NV21
            vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_NV21;
#else
            vf->type = VIDTYPE_PROGRESSIVE;
#endif
            vf->canvas0Addr = index2canvas0(index);
            vf->canvas1Addr = index2canvas1(index);
			vf->orientation = 0 ;
            if (pts_valid) {
                vf->pts = pts;
            } else {
                vf->pts = 0;
            }

            vfbuf_use[index]++;

            kfifo_put(&display_q, (const vframe_t **)&vf);
            
		    vf_notify_receiver(PROVIDER_NAME,VFRAME_EVENT_PROVIDER_VFRAME_READY,NULL);            
#endif
        }

        WRITE_VREG(MREG_FROM_AMRISC, 0);
    }
static irqreturn_t audiodsp_mailbox_irq(int irq, void *data)
{
	struct audiodsp_priv *priv=(struct audiodsp_priv *)data;
	unsigned long status;
	struct mail_msg msg;
	int i = 0;
#if MESON_CPU_TYPE < MESON_CPU_TYPE_MESON8	
	unsigned long fiq_mask;
#endif
	status=READ_VREG(MB1_REG);
#if MESON_CPU_TYPE < MESON_CPU_TYPE_MESON8	
	fiq_mask=READ_VREG(MB1_SEL);
	status=status&fiq_mask;
#endif
	if(status&(1<<M1B_IRQ0_PRINT))
		{
		get_mailbox_data(priv,M1B_IRQ0_PRINT,&msg);
		SYS_CLEAR_IRQ(M1B_IRQ0_PRINT);
	//	inv_dcache_range((unsigned  long )msg.data,(unsigned long)msg.data+msg.len);
	
		DSP_PRNT("%s", msg.data);
	    //audiodsp_work.buf = msg.data;
	    //schedule_work(&audiodsp_work.audiodsp_workqueue);		
		}
	if(status&(1<<M1B_IRQ1_BUF_OVERFLOW))
		{
		SYS_CLEAR_IRQ(M1B_IRQ1_BUF_OVERFLOW);
		DSP_PRNT("DSP BUF over flow\n");
		}
	if(status&(1<<M1B_IRQ2_BUF_UNDERFLOW))
		{
		SYS_CLEAR_IRQ(M1B_IRQ2_BUF_UNDERFLOW);
		DSP_PRNT("DSP BUF over flow\n");
		}
	if(status&(1<<M1B_IRQ3_DECODE_ERROR))
		{
		SYS_CLEAR_IRQ(M1B_IRQ3_DECODE_ERROR);
		priv->decode_error_count++;
		}
	if(status&(1<<M1B_IRQ4_DECODE_FINISH_FRAME))
		{
		struct frame_info *info;
		SYS_CLEAR_IRQ(M1B_IRQ4_DECODE_FINISH_FRAME);
		get_mailbox_data(priv,M1B_IRQ4_DECODE_FINISH_FRAME,&msg);
		info=(struct frame_info *)msg.data;
		if(info!=NULL)
			{
			priv->cur_frame_info.offset=info->offset;
			priv->cur_frame_info.buffered_len=info->buffered_len;
			}
		priv->decoded_nb_frames ++;		
		complete(&priv->decode_completion);
		}
	if(status& (1<<M1B_IRQ5_STREAM_FMT_CHANGED))
		{
		struct frame_fmt *fmt;
		SYS_CLEAR_IRQ(M1B_IRQ5_STREAM_FMT_CHANGED);
		get_mailbox_data(priv,M1B_IRQ5_STREAM_FMT_CHANGED,&msg);
		fmt=(void *)msg.data;
		//DSP_PRNT("frame format changed");
		if(fmt==NULL || (sizeof(struct frame_fmt )<msg.len))
			{
			DSP_PRNT("frame format message error\n");
			}
		else
			{
			DSP_PRNT("frame format changed,fmt->valid 0x%x\n",fmt->valid);
			if(fmt->valid&SUB_FMT_VALID)
				{
				priv->frame_format.sub_fmt=fmt->sub_fmt;
				priv->frame_format.valid|=SUB_FMT_VALID;
				}
			if(fmt->valid&CHANNEL_VALID)
				{
				priv->frame_format.channel_num=((fmt->channel_num > 2) ? 2 : (fmt->channel_num));
				priv->frame_format.valid|=CHANNEL_VALID;
				}
			if(fmt->valid&SAMPLE_RATE_VALID)
				{
				priv->frame_format.sample_rate=fmt->sample_rate;
				priv->frame_format.valid|=SAMPLE_RATE_VALID;
				}
			if(fmt->valid&DATA_WIDTH_VALID)
				{
				priv->frame_format.data_width=fmt->data_width;
				priv->frame_format.valid|=DATA_WIDTH_VALID;
				}
			}
		/*
			if(fmt->data.pcm_encoded_info){
				set_pcminfo_data(fmt->data.pcm_encoded_info);
			}
		*/	
			DSP_PRNT("audio info from dsp:sample_rate=%d channel_num=%d\n",priv->frame_format.sample_rate,priv->frame_format.channel_num);
		}
        if(status & (1<<M1B_IRQ8_IEC958_INFO)){
            struct digit_raw_output_info* info;
            SYS_CLEAR_IRQ(M1B_IRQ8_IEC958_INFO);
            get_mailbox_data(priv, M1B_IRQ8_IEC958_INFO, &msg);
            info = (void*)msg.data;
#if 1
            IEC958_bpf = info->bpf;
            IEC958_brst = info->brst;
            IEC958_length = info->length;
            IEC958_padsize = info->padsize;
            IEC958_mode = info->mode;
            IEC958_syncword1 = info->syncword1;
            IEC958_syncword2 = info->syncword2;
            IEC958_syncword3 = info->syncword3;
            IEC958_syncword1_mask = info->syncword1_mask;
            IEC958_syncword2_mask = info->syncword2_mask;
            IEC958_syncword3_mask = info->syncword3_mask;
            IEC958_chstat0_l = info->chstat0_l;
            IEC958_chstat0_r = info->chstat0_r;
            IEC958_chstat1_l = info->chstat1_l;
            IEC958_chstat1_r = info->chstat1_r;
#endif			
  //          IEC958_mode_codec = info->can_bypass;
            
            DSP_PRNT( "MAILBOX: got IEC958 info\n");
            //schedule_work(&audiodsp_work.audiodsp_workqueue);		
        }

    	if(status& (1<<M1B_IRQ5_STREAM_RD_WD_TEST)){
            DSP_WD((0x84100000-4096+20*20),0);
    		SYS_CLEAR_IRQ(M1B_IRQ5_STREAM_RD_WD_TEST);
    		get_mailbox_data(priv,M1B_IRQ5_STREAM_RD_WD_TEST,&msg);
            
            for(i = 0;i<12;i++){
                if((DSP_RD((0x84100000-512*1024+i*20)))!= (0xff00|i)){
                    DSP_PRNT("a9 read dsp reg error ,now 0x%lx, should be 0x%x \n",(DSP_RD((0x84100000-512*1024+i*20))),12-i);
                }
               // DSP_PRNT("A9 audio dsp reg%d value 0x%x\n",i,DSP_RD((0x84100000-4096+i*20)));
            }
            for(i = 0;i<12;i++){
                DSP_WD((0x84100000-512*1024+i*20),(i%2)?i:(0xf0|i));
               
            }
            DSP_WD((0x84100000-512*1024+20*20),DSP_STATUS_HALT);
        //    DSP_PRNT("A9 mail box handle finished\n");
           // dsp_mailbox_send(priv, 1, M1B_IRQ5_STREAM_RD_WD_TEST, 0, NULL,0);

        }

	if(status & (1<<M1B_IRQ7_DECODE_FATAL_ERR)){
		int err_code;
		
		SYS_CLEAR_IRQ(M1B_IRQ7_DECODE_FATAL_ERR);
		get_mailbox_data(priv,M1B_IRQ7_DECODE_FATAL_ERR,&msg);

		err_code = msg.cmd;
		priv->decode_fatal_err = err_code;

		if(err_code & 0x01){
			timestamp_pcrscr_set(timestamp_vpts_get());
			timestamp_pcrscr_enable(1);
		}
		else if(err_code & 0x02){
		printk("Set decode_fatal_err flag, Reset audiodsp!\n");
		}
	}

	return 0;
}
Esempio n. 23
0
s32 esparser_init(struct stream_buf_s *buf)
{
    s32 r;
    u32 pts_type;
    u32 parser_sub_start_ptr;
    u32 parser_sub_end_ptr;
    u32 parser_sub_rp;
    bool first_use = false;

#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
    if (HAS_HEVC_VDEC && (buf->type == BUF_TYPE_HEVC)) {
        pts_type = PTS_TYPE_HEVC;
    } else
#endif
    if (buf->type == BUF_TYPE_VIDEO) {
        pts_type = PTS_TYPE_VIDEO;
    } else if (buf->type & BUF_TYPE_AUDIO) {
        pts_type = PTS_TYPE_AUDIO;
    } else if (buf->type & BUF_TYPE_SUBTITLE) {
        pts_type = PTS_TYPE_MAX;
    } else {
        return -EINVAL;
    }

    parser_sub_start_ptr = READ_MPEG_REG(PARSER_SUB_START_PTR);
    parser_sub_end_ptr = READ_MPEG_REG(PARSER_SUB_END_PTR);
    parser_sub_rp = READ_MPEG_REG(PARSER_SUB_RP);

    buf->flag |= BUF_FLAG_PARSER;

    if (atomic_add_return(1, &esparser_use_count) == 1) {
        first_use = true;

        if (fetchbuf == 0) {
            printk("%s: no fetchbuf\n", __FUNCTION__);
            r = -ENOMEM;
            goto Err_1;
        }

        if (search_pattern == NULL) {
            search_pattern = (unsigned char *)kcalloc(1, SEARCH_PATTERN_LEN, GFP_KERNEL);

            if (search_pattern == NULL) {
                printk("%s: no search_pattern\n", __FUNCTION__);
                r = -ENOMEM;
                goto Err_1;
            }

            /* build a fake start code to get parser interrupt */
            search_pattern[0] = 0x00;
            search_pattern[1] = 0x00;
            search_pattern[2] = 0x01;
            search_pattern[3] = 0xff;

            search_pattern_map = dma_map_single(NULL, search_pattern,
                                                SEARCH_PATTERN_LEN, DMA_TO_DEVICE);
        }

        /* reset PARSER with first esparser_init() call */
        WRITE_MPEG_REG(RESET1_REGISTER, RESET_PARSER);

        /* TS data path */
#ifndef CONFIG_AM_DVB
        WRITE_MPEG_REG(FEC_INPUT_CONTROL, 0);
#else
        tsdemux_set_reset_flag();
#endif
        CLEAR_MPEG_REG_MASK(TS_HIU_CTL, 1 << USE_HI_BSF_INTERFACE);
        CLEAR_MPEG_REG_MASK(TS_HIU_CTL_2, 1 << USE_HI_BSF_INTERFACE);
        CLEAR_MPEG_REG_MASK(TS_HIU_CTL_3, 1 << USE_HI_BSF_INTERFACE);

        CLEAR_MPEG_REG_MASK(TS_FILE_CONFIG, (1 << TS_HIU_ENABLE));

        WRITE_MPEG_REG(PARSER_CONFIG,
                       (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) |
                       (1  << PS_CFG_MAX_ES_WR_CYCLE_BIT) |
                       (16 << PS_CFG_MAX_FETCH_CYCLE_BIT));

        WRITE_MPEG_REG(PFIFO_RD_PTR, 0);
        WRITE_MPEG_REG(PFIFO_WR_PTR, 0);

        WRITE_MPEG_REG(PARSER_SEARCH_PATTERN, ES_START_CODE_PATTERN);
        WRITE_MPEG_REG(PARSER_SEARCH_MASK, ES_START_CODE_MASK);

        WRITE_MPEG_REG(PARSER_CONFIG,
                       (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) |
                       (1  << PS_CFG_MAX_ES_WR_CYCLE_BIT) |
                       PS_CFG_STARTCODE_WID_24   |
                       PS_CFG_PFIFO_ACCESS_WID_8 | /* single byte pop */
                       (16 << PS_CFG_MAX_FETCH_CYCLE_BIT));

        WRITE_MPEG_REG(PARSER_CONTROL, PARSER_AUTOSEARCH);

        tasklet_init(&esparser_tasklet, parser_tasklet, 0);
    }

#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
    /* hook stream buffer with PARSER */
    if (HAS_HEVC_VDEC && (pts_type == PTS_TYPE_HEVC)) {
        CLEAR_VREG_MASK(HEVC_STREAM_CONTROL, 1);

        WRITE_MPEG_REG(PARSER_VIDEO_START_PTR,
                       READ_VREG(HEVC_STREAM_START_ADDR));
        WRITE_MPEG_REG(PARSER_VIDEO_END_PTR,
                       READ_VREG(HEVC_STREAM_END_ADDR) - 8);

        CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR);

        WRITE_VREG(DOS_GEN_CTRL0, 3<<1);    // set vififo_vbuf_rp_sel=>hevc

        SET_VREG_MASK(HEVC_STREAM_CONTROL, (1<<3)|(0<<4)); // set use_parser_vbuf_wp
        SET_VREG_MASK(HEVC_STREAM_CONTROL, 1); // set stream_fetch_enable
        SET_VREG_MASK(HEVC_STREAM_FIFO_CTL, (1<<29)); // set stream_buffer_hole with 256 bytes

        video_data_parsed = 0;
    } else
#endif
    if (pts_type == PTS_TYPE_VIDEO) {
        WRITE_MPEG_REG(PARSER_VIDEO_START_PTR,
                       READ_VREG(VLD_MEM_VIFIFO_START_PTR));
        WRITE_MPEG_REG(PARSER_VIDEO_END_PTR,
                       READ_VREG(VLD_MEM_VIFIFO_END_PTR));
        CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR);

        WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
        CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);

        if (HAS_HEVC_VDEC) {
            WRITE_VREG(DOS_GEN_CTRL0, 0);    // set vififo_vbuf_rp_sel=>vdec
        }

        video_data_parsed = 0;
    } else if (pts_type == PTS_TYPE_AUDIO) {
        WRITE_MPEG_REG(PARSER_AUDIO_START_PTR,
                       READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR));
        WRITE_MPEG_REG(PARSER_AUDIO_END_PTR,
                       READ_MPEG_REG(AIU_MEM_AIFIFO_END_PTR));
        CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR);

        WRITE_MPEG_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
        CLEAR_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);

        audio_data_parsed = 0;
    } else if (buf->type & BUF_TYPE_SUBTITLE) {
        WRITE_MPEG_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr);
        WRITE_MPEG_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr);
        WRITE_MPEG_REG(PARSER_SUB_RP, parser_sub_rp);
        SET_MPEG_REG_MASK(PARSER_ES_CONTROL, (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR);
    }

    if (pts_type < PTS_TYPE_MAX) {
        r = pts_start(pts_type);

        if (r < 0) {
            printk("esparser_init: pts_start failed\n");
            goto Err_1;
        }
    }

#if 0
    if (buf->flag & BUF_FLAG_FIRST_TSTAMP) {
        if (buf->type == BUF_TYPE_VIDEO) {
            es_vpts_checkin(buf, buf->first_tstamp);
        } else if (buf->type == BUF_TYPE_AUDIO) {
            es_apts_checkin(buf, buf->first_tstamp);
        }

        buf->flag &= ~BUF_FLAG_FIRST_TSTAMP;
    }
#endif

    if (first_use) {
        r = request_irq(INT_PARSER, parser_isr,
                        IRQF_SHARED, "esparser", (void *)esparser_id);
        if (r) {
            printk("esparser_init: irq register failed.\n");
            goto Err_2;
        }

        WRITE_MPEG_REG(PARSER_INT_STATUS, 0xffff);
        WRITE_MPEG_REG(PARSER_INT_ENABLE,
                       PARSER_INTSTAT_SC_FOUND << PARSER_INT_HOST_EN_BIT);
    }

    return 0;

Err_2:
    pts_stop(pts_type);

Err_1:
    atomic_dec(&esparser_use_count);
    buf->flag &= ~BUF_FLAG_PARSER;
    return r;
}
Esempio n. 24
0
static void amvdec_pg_enable(bool enable)
{
    ulong timeout;

    if (enable) {
        CLK_GATE_ON(MDEC_CLK_PIC_DC);
        CLK_GATE_ON(MDEC_CLK_DBLK);
        CLK_GATE_ON(MC_CLK);
        CLK_GATE_ON(IQIDCT_CLK);
        //CLK_GATE_ON(VLD_CLK);
        CLK_GATE_ON(AMRISC);
    } else {
        CLK_GATE_OFF(AMRISC);

        timeout = jiffies + HZ / 10;

        while (READ_VREG(MDEC_PIC_DC_STATUS) != 0) {
            if (time_after(jiffies, timeout)) {
                WRITE_VREG_BITS(MDEC_PIC_DC_CTRL, 1, 0, 1);
                WRITE_VREG_BITS(MDEC_PIC_DC_CTRL, 0, 0, 1);
                READ_VREG(MDEC_PIC_DC_STATUS);
                READ_VREG(MDEC_PIC_DC_STATUS);
                READ_VREG(MDEC_PIC_DC_STATUS);
                break;
            }
        }

        CLK_GATE_OFF(MDEC_CLK_PIC_DC);

        timeout = jiffies + HZ / 10;

        while (READ_VREG(DBLK_STATUS) & 1) {
            if (time_after(jiffies, timeout)) {
                WRITE_VREG(DBLK_CTRL, 3);
                WRITE_VREG(DBLK_CTRL, 0);
                READ_VREG(DBLK_STATUS);
                READ_VREG(DBLK_STATUS);
                READ_VREG(DBLK_STATUS);
                break;
            }
        }
        CLK_GATE_OFF(MDEC_CLK_DBLK);

        timeout = jiffies + HZ / 10;

        while (READ_VREG(MC_STATUS0) & 1) {
            if (time_after(jiffies, timeout)) {
                SET_VREG_MASK(MC_CTRL1, 0x9);
                CLEAR_VREG_MASK(MC_CTRL1, 0x9);
                READ_VREG(MC_STATUS0);
                READ_VREG(MC_STATUS0);
                READ_VREG(MC_STATUS0);
                break;
            }
        }
        CLK_GATE_OFF(MC_CLK);

        timeout = jiffies + HZ / 10;
        while (READ_VREG(DCAC_DMA_CTRL) & 0x8000) {
            if (time_after(jiffies, timeout)) {
                break;
            }
        }

#ifdef CONFIG_ARCH_MESON6
        WRITE_VREG(DOS_SW_RESET0, (1 << 4));
        WRITE_VREG(DOS_SW_RESET0, 0);
        READ_VREG(DOS_SW_RESET0);
        READ_VREG(DOS_SW_RESET0);
        READ_VREG(DOS_SW_RESET0);
#else
        WRITE_MPEG_REG(RESET0_REGISTER, RESET_VLD_PART);
        READ_MPEG_REG(RESET0_REGISTER);
        READ_MPEG_REG(RESET0_REGISTER);
        READ_MPEG_REG(RESET0_REGISTER);
#endif
        CLK_GATE_OFF(IQIDCT_CLK);

        //CLK_GATE_OFF(VLD_CLK);
    }
}
Esempio n. 25
0
s32 rmparser_init(void)
{
    s32 r;
    parse_halt = 0;
    if (fetchbuf == 0) {
        printk("%s: no fetchbuf\n", __FUNCTION__);
        return -ENOMEM;
    }

    WRITE_MPEG_REG(RESET1_REGISTER, RESET_PARSER);

    /* TS data path */
	/* Ignore FEC control for WetekPlay */
#ifndef CONFIG_WETEK
#ifndef CONFIG_AM_DVB
    WRITE_MPEG_REG(FEC_INPUT_CONTROL, 0);
#else
    tsdemux_set_reset_flag();
#endif
#endif
    CLEAR_MPEG_REG_MASK(TS_HIU_CTL, 1 << USE_HI_BSF_INTERFACE);
    CLEAR_MPEG_REG_MASK(TS_HIU_CTL_2, 1 << USE_HI_BSF_INTERFACE);
    CLEAR_MPEG_REG_MASK(TS_HIU_CTL_3, 1 << USE_HI_BSF_INTERFACE);

    CLEAR_MPEG_REG_MASK(TS_FILE_CONFIG, (1 << TS_HIU_ENABLE));

    /* hook stream buffer with PARSER */
    WRITE_MPEG_REG(PARSER_VIDEO_START_PTR,
                   READ_VREG(VLD_MEM_VIFIFO_START_PTR));
    WRITE_MPEG_REG(PARSER_VIDEO_END_PTR,
                   READ_VREG(VLD_MEM_VIFIFO_END_PTR));
    CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR);

    WRITE_MPEG_REG(PARSER_AUDIO_START_PTR,
                   READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR));
    WRITE_MPEG_REG(PARSER_AUDIO_END_PTR,
                   READ_MPEG_REG(AIU_MEM_AIFIFO_END_PTR));
    CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR);

    WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
    CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);

    WRITE_MPEG_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
    CLEAR_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);

    WRITE_MPEG_REG(PFIFO_RD_PTR, 0);
    WRITE_MPEG_REG(PFIFO_WR_PTR, 0);

    WRITE_MPEG_REG(PARSER_SEARCH_MASK, 0);
    WRITE_MPEG_REG(PARSER_CONTROL, (ES_SEARCH | ES_PARSER_START));

#ifdef MANAGE_PTS
    if (pts_start(PTS_TYPE_VIDEO) < 0) {
        goto Err_1;
    }

    if (pts_start(PTS_TYPE_AUDIO) < 0) {
        goto Err_2;
    }
#endif

    /* enable interrupt */
    r = request_irq(INT_PARSER, rm_parser_isr,
                    IRQF_SHARED, "rmparser", (void *)rmparser_id);

    if (r) {
        printk("RM parser irq register failed.\n");
        goto Err_3;
    }

    WRITE_MPEG_REG(PARSER_INT_STATUS, 0xffff);
    WRITE_MPEG_REG(PARSER_INT_ENABLE,
                   ((PARSER_INT_ALL & (~PARSER_INTSTAT_FETCH_CMD)) << PARSER_INT_AMRISC_EN_BIT)
                   | (PARSER_INTSTAT_FETCH_CMD << PARSER_INT_HOST_EN_BIT));

    return 0;

Err_3:
    pts_stop(PTS_TYPE_AUDIO);
Err_2:
    pts_stop(PTS_TYPE_VIDEO);
Err_1:
    return -ENOENT;
}
Esempio n. 26
0
static inline u32 buf_wp(u32 type)
{
    return (type == BUF_TYPE_VIDEO) ? READ_VREG(VLD_MEM_VIFIFO_WP) :
           (type == BUF_TYPE_AUDIO) ? READ_MPEG_REG(AIU_MEM_AIFIFO_MAN_WP) :
                                      READ_MPEG_REG(PARSER_SUB_START_PTR);
}
Esempio n. 27
0
static s32 amvdec_loadmc(const u32 *p)
{
	ulong timeout;
	s32 ret = 0;

#ifdef AMVDEC_USE_STATIC_MEMORY
	if (mc_addr == NULL) {
#else
	{
#endif
		mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
	}

	if (!mc_addr)
		return -ENOMEM;

	memcpy(mc_addr, p, MC_SIZE);

	mc_addr_map = dma_map_single(amports_get_dma_device(),
		mc_addr, MC_SIZE, DMA_TO_DEVICE);

	WRITE_VREG(MPSR, 0);
	WRITE_VREG(CPSR, 0);

	/* Read CBUS register for timing */
	timeout = READ_VREG(MPSR);
	timeout = READ_VREG(MPSR);

	timeout = jiffies + HZ;

	WRITE_VREG(IMEM_DMA_ADR, mc_addr_map);
	WRITE_VREG(IMEM_DMA_COUNT, 0x1000);
	WRITE_VREG(IMEM_DMA_CTRL, (0x8000 | (7 << 16)));

	while (READ_VREG(IMEM_DMA_CTRL) & 0x8000) {
		if (time_before(jiffies, timeout))
			schedule();
		else {
			pr_err("vdec load mc error\n");
			ret = -EBUSY;
			break;
		}
	}

	dma_unmap_single(amports_get_dma_device(),
		mc_addr_map, MC_SIZE, DMA_TO_DEVICE);

#ifndef AMVDEC_USE_STATIC_MEMORY
	kfree(mc_addr);
	mc_addr = NULL;
#endif

	return ret;
}

s32 amvdec_loadmc_ex(enum vformat_e type, const char *name, char *def)
{
	return am_loadmc_ex(type, name, def, &amvdec_loadmc);
}

static s32 amvdec2_loadmc(const u32 *p)
{
	if (has_vdec2()) {
		ulong timeout;
		s32 ret = 0;

#ifdef AMVDEC_USE_STATIC_MEMORY
		if (mc_addr == NULL) {
#else
		{
#endif
			mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
		}

		if (!mc_addr)
			return -ENOMEM;

		memcpy(mc_addr, p, MC_SIZE);

		mc_addr_map = dma_map_single(amports_get_dma_device(),
			mc_addr, MC_SIZE, DMA_TO_DEVICE);

		WRITE_VREG(VDEC2_MPSR, 0);
		WRITE_VREG(VDEC2_CPSR, 0);

		/* Read CBUS register for timing */
		timeout = READ_VREG(VDEC2_MPSR);
		timeout = READ_VREG(VDEC2_MPSR);

		timeout = jiffies + HZ;

		WRITE_VREG(VDEC2_IMEM_DMA_ADR, mc_addr_map);
		WRITE_VREG(VDEC2_IMEM_DMA_COUNT, 0x1000);
		WRITE_VREG(VDEC2_IMEM_DMA_CTRL, (0x8000 | (7 << 16)));

		while (READ_VREG(VDEC2_IMEM_DMA_CTRL) & 0x8000) {
			if (time_before(jiffies, timeout))
				schedule();
			else {
				pr_err("vdec2 load mc error\n");
				ret = -EBUSY;
				break;
			}
		}

		dma_unmap_single(amports_get_dma_device(),
			mc_addr_map, MC_SIZE, DMA_TO_DEVICE);

#ifndef AMVDEC_USE_STATIC_MEMORY
		kfree(mc_addr);
		mc_addr = NULL;
#endif

		return ret;
	} else
		return 0;
}

s32 amvdec2_loadmc_ex(enum vformat_e type, const char *name, char *def)
{
	if (has_vdec2())
		return am_loadmc_ex(type, name, def, &amvdec2_loadmc);
	else
		return 0;
}

s32 amhcodec_loadmc(const u32 *p)
{
#ifdef AMVDEC_USE_STATIC_MEMORY
	if (mc_addr == NULL) {
#else
	{
#endif
		mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
	}

	if (!mc_addr)
		return -ENOMEM;

	memcpy(mc_addr, p, MC_SIZE);

	mc_addr_map = dma_map_single(amports_get_dma_device(),
			mc_addr, MC_SIZE, DMA_TO_DEVICE);

	WRITE_VREG(HCODEC_IMEM_DMA_ADR, mc_addr_map);
	WRITE_VREG(HCODEC_IMEM_DMA_COUNT, 0x100);
	WRITE_VREG(HCODEC_IMEM_DMA_CTRL, (0x8000 | (7 << 16)));

	while (READ_VREG(HCODEC_IMEM_DMA_CTRL) & 0x8000)
		udelay(1000);

	dma_unmap_single(amports_get_dma_device(),
			mc_addr_map, MC_SIZE, DMA_TO_DEVICE);

#ifndef AMVDEC_USE_STATIC_MEMORY
	kfree(mc_addr);
#endif

	return 0;
}

s32 amhcodec_loadmc_ex(enum vformat_e type, const char *name, char *def)
{
	return am_loadmc_ex(type, name, def, &amhcodec_loadmc);
}

static s32 amhevc_loadmc(const u32 *p)
{
	ulong timeout;
	s32 ret = 0;

	if (has_hevc_vdec()) {
#ifdef AMVDEC_USE_STATIC_MEMORY
		if (mc_addr == NULL) {
#else
		{
#endif
			mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
		}

		if (!mc_addr)
			return -ENOMEM;

		memcpy(mc_addr, p, MC_SIZE);

		mc_addr_map =
			dma_map_single(amports_get_dma_device(),
			mc_addr, MC_SIZE, DMA_TO_DEVICE);

		WRITE_VREG(HEVC_MPSR, 0);
		WRITE_VREG(HEVC_CPSR, 0);

		/* Read CBUS register for timing */
		timeout = READ_VREG(HEVC_MPSR);
		timeout = READ_VREG(HEVC_MPSR);

		timeout = jiffies + HZ;

		WRITE_VREG(HEVC_IMEM_DMA_ADR, mc_addr_map);
		WRITE_VREG(HEVC_IMEM_DMA_COUNT, 0x1000);
		WRITE_VREG(HEVC_IMEM_DMA_CTRL, (0x8000 | (7 << 16)));

		while (READ_VREG(HEVC_IMEM_DMA_CTRL) & 0x8000) {
			if (time_before(jiffies, timeout))
				schedule();
			else {
				pr_err("vdec2 load mc error\n");
				ret = -EBUSY;
				break;
			}
		}

		dma_unmap_single(amports_get_dma_device(),
				mc_addr_map, MC_SIZE, DMA_TO_DEVICE);

#ifndef AMVDEC_USE_STATIC_MEMORY
		kfree(mc_addr);
		mc_addr = NULL;
#endif
	}

	return ret;
}

s32 amhevc_loadmc_ex(enum vformat_e type, const char *name, char *def)
{
	if (has_hevc_vdec())
		return am_loadmc_ex(type, name, def, &amhevc_loadmc);
	else
		return 0;
}

void amvdec_start(void)
{
#ifdef CONFIG_WAKELOCK
	amvdec_wake_lock();
#endif

	/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
	if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) {
		READ_VREG(DOS_SW_RESET0);
		READ_VREG(DOS_SW_RESET0);
		READ_VREG(DOS_SW_RESET0);

		WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11));
		WRITE_VREG(DOS_SW_RESET0, 0);

		READ_VREG(DOS_SW_RESET0);
		READ_VREG(DOS_SW_RESET0);
		READ_VREG(DOS_SW_RESET0);
	} else {
		/* #else */
		/* additional cbus dummy register reading for timing control */
		READ_MPEG_REG(RESET0_REGISTER);
		READ_MPEG_REG(RESET0_REGISTER);
		READ_MPEG_REG(RESET0_REGISTER);
		READ_MPEG_REG(RESET0_REGISTER);

		WRITE_MPEG_REG(RESET0_REGISTER, RESET_VCPU | RESET_CCPU);

		READ_MPEG_REG(RESET0_REGISTER);
		READ_MPEG_REG(RESET0_REGISTER);
		READ_MPEG_REG(RESET0_REGISTER);
	}
	/* #endif */

	WRITE_VREG(MPSR, 0x0001);
}

void amvdec2_start(void)
{
	if (has_vdec2()) {
#ifdef CONFIG_WAKELOCK
		amvdec_wake_lock();
#endif

		READ_VREG(DOS_SW_RESET2);
		READ_VREG(DOS_SW_RESET2);
		READ_VREG(DOS_SW_RESET2);

		WRITE_VREG(DOS_SW_RESET2, (1 << 12) | (1 << 11));
		WRITE_VREG(DOS_SW_RESET2, 0);

		READ_VREG(DOS_SW_RESET2);
		READ_VREG(DOS_SW_RESET2);
		READ_VREG(DOS_SW_RESET2);

		WRITE_VREG(VDEC2_MPSR, 0x0001);
	}
}

void amhcodec_start(void)
{
	WRITE_VREG(HCODEC_MPSR, 0x0001);
}

void amhevc_start(void)
{
	if (has_hevc_vdec()) {
#ifdef CONFIG_WAKELOCK
		amvdec_wake_lock();
#endif

		READ_VREG(DOS_SW_RESET3);
		READ_VREG(DOS_SW_RESET3);
		READ_VREG(DOS_SW_RESET3);

		WRITE_VREG(DOS_SW_RESET3, (1 << 12) | (1 << 11));
		WRITE_VREG(DOS_SW_RESET3, 0);

		READ_VREG(DOS_SW_RESET3);
		READ_VREG(DOS_SW_RESET3);
		READ_VREG(DOS_SW_RESET3);

		WRITE_VREG(HEVC_MPSR, 0x0001);
	}
}

void amvdec_stop(void)
{
	ulong timeout = jiffies + HZ;

	WRITE_VREG(MPSR, 0);
	WRITE_VREG(CPSR, 0);

	while (READ_VREG(IMEM_DMA_CTRL) & 0x8000) {
		if (time_after(jiffies, timeout))
			break;
	}

	/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
	if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) {
		READ_VREG(DOS_SW_RESET0);
		READ_VREG(DOS_SW_RESET0);
		READ_VREG(DOS_SW_RESET0);

		WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11));
		WRITE_VREG(DOS_SW_RESET0, 0);

		READ_VREG(DOS_SW_RESET0);
		READ_VREG(DOS_SW_RESET0);
		READ_VREG(DOS_SW_RESET0);
	} else {
		/* #else */
		WRITE_MPEG_REG(RESET0_REGISTER, RESET_VCPU | RESET_CCPU);

		/* additional cbus dummy register reading for timing control */
		READ_MPEG_REG(RESET0_REGISTER);
		READ_MPEG_REG(RESET0_REGISTER);
		READ_MPEG_REG(RESET0_REGISTER);
		READ_MPEG_REG(RESET0_REGISTER);
	}
	/* #endif */

#ifdef CONFIG_WAKELOCK
	amvdec_wake_unlock();
#endif
}