/**
 * @brief       PGP Manager (Exec)
 * @author      AXELL CORPORATION
 * @description PGP Manager Layer.
 * @note        none
 * @history     2017_02_22  初版
 * @history     2017_10_26  Ver2.0
*/
/* DOM-IGNORE-BEGIN */
/*
 * This program was created by AXELL CORPORATION.
 * Copyright (C) 2017 AXELL CORPORATION, all rights reserved.
 */
/* DOM-IGNORE-END */

#include <stdio.h>
#include "pgpmgr_common.h"
#include "pgp/pgpprm.h"

/* Primitive Layer経由でレジスタを設定するための関数 */
static void PgpMgrDebugSetRegister(AG903_PgpMgrPipelineHandle *handle)
{
    int32_t id = handle->pipeline_no;

    AG903_PgpPrmSetPGPnINTCTRLI(id, handle->input_intr_field,
                                (handle->input_intr_fcnt == AG903_PGP_MGR_INTR_CTRL_MAX_FRAME_CNT) ? 0 : handle->input_intr_fcnt,
                                handle->input_intr_line);
    AG903_PgpPrmSetPGPnINTCTRLO(id, handle->output_intr_field,
                                (handle->output_intr_fcnt == AG903_PGP_MGR_INTR_CTRL_MAX_FRAME_CNT) ? 0 : handle->output_intr_fcnt,
                                handle->output_intr_line);

    PGPPrmParamPGPnINTEN inten;
    inten.nd      = handle->intr_nd_enable;
    inten.voicpl  = handle->intr_voicpl_enable;
    inten.vooflw  = handle->intr_vooflw_enable;
    inten.ifcofs  = handle->intr_ifcofs_enable;
    inten.ifcofm  = handle->intr_ifcofm_enable;
    inten.lblcrpt = handle->intr_lblcrpt_enable;
    inten.lblcpl  = handle->intr_lblcpl_enable;
    inten.hgmicpl = handle->intr_hgmicpl_enable;
    inten.hgmcpl  = handle->intr_hgmcpl_enable;
    inten.vsynco  = handle->intr_vsynco_enable;
    inten.vlineo  = handle->intr_vlineo_enable;
    inten.vsynci  = handle->intr_vsynci_enable;
    inten.vlinei  = handle->intr_vlinei_enable;
    AG903_PgpPrmSetPGPnINTEN(id, &inten);

    AG903_PgpPrmSetPGPnTRGCTRLI(id, handle->input_trig_field,
                                (handle->input_trig_fcnt == AG903_PGP_MGR_TRIG_CTRL_MAX_FRAME_CNT) ? 0 : handle->input_trig_fcnt,
                                handle->input_trig_line);
    AG903_PgpPrmSetPGPnTRGCTRLO(id, handle->output_trig_field,
                                (handle->output_trig_fcnt == AG903_PGP_MGR_TRIG_CTRL_MAX_FRAME_CNT) ? 0 : handle->output_trig_fcnt,
                                handle->output_trig_line);

    PGPPrmParamPGPnTRGEN trgen;
    trgen.vsynco = handle->trig_vsynco_enable;
    trgen.vlineo = handle->trig_vlineo_enable;
    trgen.vsynci = handle->trig_vsynci_enable;
    trgen.vlinei = handle->trig_vlinei_enable;
    AG903_PgpPrmSetPGPnTRGEN(id, &trgen);

    PGPPrmParamPGPnINCTRL inctrl;
    inctrl.hdly = handle->input_hsync_delay;
    inctrl.md   = handle->input_mode;
    inctrl.tick = handle->input_timer_clk;
    inctrl.trg  = handle->input_trig_timer_ch;
    inctrl.sel  = handle->input_port;
    inctrl.fmt  = handle->input_format;
    AG903_PgpPrmSetPGPnINCTRL(id, &inctrl);

    PGPPrmParamPGPnFUNCCTRL funcctrl;
    funcctrl.out    = handle->frame_out_enable;
    funcctrl.ifcodr = handle->ifc_order;
    funcctrl.ifc    = handle->ifc_enable;
    funcctrl.thr    = handle->thr_enable;
    funcctrl.dgc    = handle->dgc_enable;
    funcctrl.hsv1   = handle->hsv1_enable;
    funcctrl.spf    = handle->spf_enable;
    funcctrl.scale  = handle->scale_enable;
    funcctrl.csc1   = handle->csc1_enable;
    funcctrl.nrf    = handle->nrf_enable;
    AG903_PgpPrmSetPGPnFUNCCTRL(id, &funcctrl);
    AG903_PgpPrmSetPGPnSIZE(id, (handle->input_vsize == AG903_PGP_MGR_MAX_INPUT_SIZE) ?  0 : handle->input_vsize,
                                (handle->input_hsize == AG903_PGP_MGR_MAX_INPUT_SIZE) ? 0 : handle->input_hsize);

    PGPPrmParamPGPnPOS pos;
    pos.epos = handle->input_epos;
    pos.opos = handle->input_opos;
    pos.scan = handle->input_scan;
    pos.vpos = handle->input_vpos;
    pos.hpos = handle->input_hpos;
    AG903_PgpPrmSetPGPnPOS(id, &pos);

    PGPPrmParamPGPnOUTCTRL0 outctrl0;
    outctrl0.pad   = handle->output_pad;
    outctrl0.limit = handle->output_limit;
    outctrl0.fai   = handle->output_fai_enable;
    outctrl0.dth   = handle->output_dither_enable;
    outctrl0.bmu   = handle->output_bmu;
    outctrl0.scan  = handle->output_scan;
    outctrl0.dim   = handle->output_dim;
    outctrl0.swapw = handle->output_word_swap_enable;
    outctrl0.swaph = handle->output_hword_swap_enable;
    outctrl0.swap4 = handle->output_4bit_swap_enable;
    outctrl0.swap1 = handle->output_1bit_swap_enable;
    outctrl0.md    = handle->output_md;
    outctrl0.fmt   = handle->output_format;
    AG903_PgpPrmSetPGPnOUTCTRL0(id, &outctrl0);

    AG903_PgpPrmSetPGPnOUTCTRL1(id, handle->output_red_enable, handle->output_green_enable, handle->output_blue_enable);
    AG903_PgpPrmSetPGPnOUTBASE(id, (handle->output_base_addr >> 3));
    AG903_PgpPrmSetPGPnOUTHSIZE(id, (handle->output_vram_stride == AG903_PGP_MGR_OUTPUT_MAX_STRIDE_BYTE) ? 0 : handle->output_vram_stride);
    AG903_PgpPrmSetPGPnIPCPRM(id, handle->ipc_limit, handle->ipc_blk_y, handle->ipc_blk_c);
    AG903_PgpPrmSetPGPnCSC1CTRL(id, handle->csc1_limit, handle->csc1_shift);
    AG903_PgpPrmSetPGPnCSC1PRM0(id, handle->csc1_matrix[0][1], handle->csc1_matrix[0][0]);
    AG903_PgpPrmSetPGPnCSC1PRM1(id, handle->csc1_matrix[0][2]);
    AG903_PgpPrmSetPGPnCSC1PRM2(id, handle->csc1_matrix[0][3]);
    AG903_PgpPrmSetPGPnCSC1PRM3(id, handle->csc1_matrix[1][1], handle->csc1_matrix[1][0]);
    AG903_PgpPrmSetPGPnCSC1PRM4(id, handle->csc1_matrix[1][2]);
    AG903_PgpPrmSetPGPnCSC1PRM5(id, handle->csc1_matrix[1][3]);
    AG903_PgpPrmSetPGPnCSC1PRM6(id, handle->csc1_matrix[2][1], handle->csc1_matrix[2][0]);
    AG903_PgpPrmSetPGPnCSC1PRM7(id, handle->csc1_matrix[2][2]);
    AG903_PgpPrmSetPGPnCSC1PRM8(id, handle->csc1_matrix[2][3]);

    PGPPrmParamPGPnSCCTRL scctrl;
    scctrl.limit = handle->scale_limit;
    scctrl.mtd   = handle->scale_mtd;
    scctrl.nmrv  = (handle->scale_v_nmr == AG903_PGP_MGR_MAX_SCALING_VALUE) ? 0 : handle->scale_v_nmr;
    scctrl.dnmv  = (handle->scale_v_dnm == AG903_PGP_MGR_MAX_SCALING_VALUE) ? 0 : handle->scale_v_dnm;
    scctrl.nmrh  = (handle->scale_h_nmr == AG903_PGP_MGR_MAX_SCALING_VALUE) ? 0 : handle->scale_h_nmr;
    scctrl.dnmh  = (handle->scale_h_dnm == AG903_PGP_MGR_MAX_SCALING_VALUE) ? 0 : handle->scale_h_dnm;
    AG903_PgpPrmSetPGPnSCCTRL(id, &scctrl);

    PGPPrmParamPGPnSPFCTRL spfctrl;
    spfctrl.sft = handle->spf_shift;
    spfctrl.bc  = handle->spf_border_sel;
    spfctrl.r   = handle->spf_border_red;
    spfctrl.g   = handle->spf_border_green;
    spfctrl.b   = handle->spf_border_blue;
    AG903_PgpPrmSetPGPnSPFCTRL(id, &spfctrl);

    AG903_PgpPrmSetPGPnSPFPRM0(id, handle->spf_coeff[2], handle->spf_coeff[1], handle->spf_coeff[0]);
    AG903_PgpPrmSetPGPnSPFPRM1(id, handle->spf_coeff[5], handle->spf_coeff[4], handle->spf_coeff[3]);
    AG903_PgpPrmSetPGPnSPFPRM2(id, handle->spf_coeff[8], handle->spf_coeff[7], handle->spf_coeff[6]);
    AG903_PgpPrmSetPGPnSPFPRM3(id, handle->spf_offset);
    AG903_PgpPrmSetPGPnHSV1CTRL(id, handle->hsv_hls_sel);

    PGPPrmParamPGPnHGMCTRL hgmctrl;
    hgmctrl.inv  = handle->hgm_invalidate;
    hgmctrl.bmu  = handle->hgm_bmu;
    hgmctrl.exc  = handle->hgm_exc;
    hgmctrl.thr  = handle->hgm_thr;
    hgmctrl.sft  = handle->hgm_shift;
    hgmctrl.vinc = handle->hgm_vinc;
    hgmctrl.hinc = handle->hgm_hinc;
    AG903_PgpPrmSetPGPnHGMCTRL(id, &hgmctrl);
    AG903_PgpPrmSetPGPnHGMSIZE(id, (handle->hgm_vsize == AG903_PGP_MGR_MAX_HGM_SIZE) ? 0 : handle->hgm_vsize,
                               (handle->hgm_hsize == AG903_PGP_MGR_MAX_HGM_SIZE) ? 0 : handle->hgm_hsize);
    AG903_PgpPrmSetPGPnHGMPOS(id, handle->hgm_vpos, handle->hgm_hpos);
    AG903_PgpPrmSetPGPnHGMDST(id, handle->hgm_addr >> 3);

    PGPPrmParamPGPnTHRCTRL thrctrl;
    thrctrl.limit  = handle->thr_limit;
    thrctrl.spf1   = handle->thr_spf1_enable;
    thrctrl.msk    = handle->thr_msk_enable;
    thrctrl.csc2   = handle->thr_csc2_enable;
    thrctrl.hsv2   = handle->thr_hsv2_enable;
    thrctrl.thr8   = handle->thr_thr8bit_enable;
    thrctrl.outsel = handle->thr_out_sel;
    thrctrl.c8sel  = handle->thr_clut8_sel;
    AG903_PgpPrmSetPGPnTHRCTRL(id, &thrctrl);

    AG903_PgpPrmSetPGPnHSV2CTRL(id, handle->thr_hsv_hls_sel);
    AG903_PgpPrmSetPGPnCSC2CTRL(id, handle->thr_csc2_limit, handle->thr_csc2_shift);
    AG903_PgpPrmSetPGPnCSC2PRM0(id, handle->thr_csc2_matrix[0][1], handle->thr_csc2_matrix[0][0]);
    AG903_PgpPrmSetPGPnCSC2PRM1(id, handle->thr_csc2_matrix[0][2]);
    AG903_PgpPrmSetPGPnCSC2PRM2(id, handle->thr_csc2_matrix[0][3]);
    AG903_PgpPrmSetPGPnCSC2PRM3(id, handle->thr_csc2_matrix[1][1], handle->thr_csc2_matrix[1][0]);
    AG903_PgpPrmSetPGPnCSC2PRM4(id, handle->thr_csc2_matrix[1][2]);
    AG903_PgpPrmSetPGPnCSC2PRM5(id, handle->thr_csc2_matrix[1][3]);
    AG903_PgpPrmSetPGPnCSC2PRM6(id, handle->thr_csc2_matrix[2][1], handle->thr_csc2_matrix[2][0]);
    AG903_PgpPrmSetPGPnCSC2PRM7(id, handle->thr_csc2_matrix[2][2]);
    AG903_PgpPrmSetPGPnCSC2PRM8(id, handle->thr_csc2_matrix[2][3]);

    AG903_PgpPrmSetPGPnMSK0PRM0(id, handle->thr_msk_h[AG903_PGP_MGR_THR_CHANNEL_B], handle->thr_msk_l[AG903_PGP_MGR_THR_CHANNEL_B],
                                handle->thr_msk_x[AG903_PGP_MGR_THR_CHANNEL_B]);
    PGPPrmParamPGPnMSK0PRM1 msk0prm1;
    msk0prm1.hmax = handle->thr_msk_hmax[AG903_PGP_MGR_THR_CHANNEL_B];
    msk0prm1.hmin = handle->thr_msk_hmin[AG903_PGP_MGR_THR_CHANNEL_B];
    msk0prm1.lmax = handle->thr_msk_lmax[AG903_PGP_MGR_THR_CHANNEL_B];
    msk0prm1.lmin = handle->thr_msk_lmin[AG903_PGP_MGR_THR_CHANNEL_B];
    AG903_PgpPrmSetPGPnMSK0PRM1(id, &msk0prm1);
    AG903_PgpPrmSetPGPnMSK1PRM0(id, handle->thr_msk_h[AG903_PGP_MGR_THR_CHANNEL_G], handle->thr_msk_l[AG903_PGP_MGR_THR_CHANNEL_G],
                                handle->thr_msk_x[AG903_PGP_MGR_THR_CHANNEL_G]);
    PGPPrmParamPGPnMSK1PRM1 msk1prm1;
    msk1prm1.hmax = handle->thr_msk_hmax[AG903_PGP_MGR_THR_CHANNEL_G];
    msk1prm1.hmin = handle->thr_msk_hmin[AG903_PGP_MGR_THR_CHANNEL_G];
    msk1prm1.lmax = handle->thr_msk_lmax[AG903_PGP_MGR_THR_CHANNEL_G];
    msk1prm1.lmin = handle->thr_msk_lmin[AG903_PGP_MGR_THR_CHANNEL_G];
    AG903_PgpPrmSetPGPnMSK1PRM1(id, &msk1prm1);
    AG903_PgpPrmSetPGPnMSK2PRM0(id, handle->thr_msk_h[AG903_PGP_MGR_THR_CHANNEL_R], handle->thr_msk_l[AG903_PGP_MGR_THR_CHANNEL_R],
                                handle->thr_msk_x[AG903_PGP_MGR_THR_CHANNEL_R]);
    PGPPrmParamPGPnMSK2PRM1 msk2prm1;
    msk2prm1.hmax = handle->thr_msk_hmax[AG903_PGP_MGR_THR_CHANNEL_R];
    msk2prm1.hmin = handle->thr_msk_hmin[AG903_PGP_MGR_THR_CHANNEL_R];
    msk2prm1.lmax = handle->thr_msk_lmax[AG903_PGP_MGR_THR_CHANNEL_R];
    msk2prm1.lmin = handle->thr_msk_lmin[AG903_PGP_MGR_THR_CHANNEL_R];
    AG903_PgpPrmSetPGPnMSK2PRM1(id, &msk2prm1);

    PGPPrmParamPGPnTHR8PRM0 thr8prm0;
    thr8prm0.type   = handle->thr_thr8_prm_type[AG903_PGP_MGR_THR_CHANNEL_B];
    thr8prm0.maxval = handle->thr_thr8_prm_maxval[AG903_PGP_MGR_THR_CHANNEL_B];
    thr8prm0.maxthr = handle->thr_thr8_prm_maxthr[AG903_PGP_MGR_THR_CHANNEL_B];
    thr8prm0.minthr = handle->thr_thr8_prm_minthr[AG903_PGP_MGR_THR_CHANNEL_B];
    AG903_PgpPrmSetPGPnTHR8PRM0(id, &thr8prm0);

    PGPPrmParamPGPnTHR8PRM1 thr8prm1;
    thr8prm1.type   = handle->thr_thr8_prm_type[AG903_PGP_MGR_THR_CHANNEL_G];
    thr8prm1.maxval = handle->thr_thr8_prm_maxval[AG903_PGP_MGR_THR_CHANNEL_G];
    thr8prm1.maxthr = handle->thr_thr8_prm_maxthr[AG903_PGP_MGR_THR_CHANNEL_G];
    thr8prm1.minthr = handle->thr_thr8_prm_minthr[AG903_PGP_MGR_THR_CHANNEL_G];
    AG903_PgpPrmSetPGPnTHR8PRM1(id, &thr8prm1);

    PGPPrmParamPGPnTHR8PRM2 thr8prm2;
    thr8prm2.type   = handle->thr_thr8_prm_type[AG903_PGP_MGR_THR_CHANNEL_R];
    thr8prm2.maxval = handle->thr_thr8_prm_maxval[AG903_PGP_MGR_THR_CHANNEL_R];
    thr8prm2.maxthr = handle->thr_thr8_prm_maxthr[AG903_PGP_MGR_THR_CHANNEL_R];
    thr8prm2.minthr = handle->thr_thr8_prm_minthr[AG903_PGP_MGR_THR_CHANNEL_R];
    AG903_PgpPrmSetPGPnTHR8PRM2(id, &thr8prm2);
    AG903_PgpPrmSetPGPnTHR1PRM0(id, handle->thr_thr1_h, handle->thr_thr1_l, handle->thr_thr1_x);

    PGPPrmParamPGPnTHR1PRM1 thr1prm1;
    thr1prm1.hmax = handle->thr_thr1_hmax;
    thr1prm1.hmin = handle->thr_thr1_hmin;
    thr1prm1.lmax = handle->thr_thr1_lmax;
    thr1prm1.lmin = handle->thr_thr1_lmin;
    AG903_PgpPrmSetPGPnTHR1PRM1(id, &thr1prm1);

    PGPPrmParamPGPnSPF1PRM0 spf1prm0;
    spf1prm0.h10 = handle->thr_spf1_coeff[5];
    spf1prm0.h00 = handle->thr_spf1_coeff[4];
    spf1prm0.hm0 = handle->thr_spf1_coeff[3];
    spf1prm0.h1m = handle->thr_spf1_coeff[2];
    spf1prm0.h0m = handle->thr_spf1_coeff[1];
    spf1prm0.hmm = handle->thr_spf1_coeff[0];
    AG903_PgpPrmSetPGPnSPF1PRM0(id, &spf1prm0);

    PGPPrmParamPGPnSPF1PRM1 spf1prm1;
    spf1prm1.thr = handle->thr_spf1_thr;
    spf1prm1.h11 = handle->thr_spf1_coeff[8];
    spf1prm1.h01 = handle->thr_spf1_coeff[7];
    spf1prm1.hm1 = handle->thr_spf1_coeff[6];
    AG903_PgpPrmSetPGPnSPF1PRM1(id, &spf1prm1);

    PGPPrmParamPGPnLBLCTRL lblctrl;
    lblctrl.vld   = (handle->lbl_valid == AG903_PGP_MGR_MAX_LBL_OUTPUT_VALIDATE) ? 0 : handle->lbl_valid;
    lblctrl.inv   = handle->lbl_invalid;
    lblctrl.cnct  = handle->lbl_connect;
    lblctrl.bmu   = handle->lbl_bmu;
    lblctrl.flthr = handle->lbl_flush_thr;
    lblctrl.maxid = handle->lbl_maxid;
    AG903_PgpPrmSetPGPnLBLCTRL(id, &lblctrl);
    AG903_PgpPrmSetPGPnLBLSIZE(id, (handle->lbl_vsize == AG903_PGP_MGR_MAX_LBL_VSIZE) ? 0 : handle->lbl_vsize, handle->lbl_hsize);
    AG903_PgpPrmSetPGPnLBLPOS(id, handle->lbl_vpos, handle->lbl_hpos);
    AG903_PgpPrmSetPGPnLBLDST(id, handle->lbl_addr >> 3);

    PGPPrmParamPGPnIFCCTRL ifcctrl;
    ifcctrl.scan  = handle->ifc_scan;
    ifcctrl.limit = handle->ifc_limit;
    ifcctrl.src   = handle->ifc_slave_src;
    ifcctrl.op    = handle->ifc_operation;
    ifcctrl.sft1  = handle->ifc_slave_shift;
    ifcctrl.sft0  = handle->ifc_master_shift;
    AG903_PgpPrmSetPGPnIFCCTRL(id, &ifcctrl);
    AG903_PgpPrmSetPGPnIFCPRM(id, handle->ifc_slave_gain, handle->ifc_master_gain);
}

/* Primitive Layerを通してレジスタ値を設定します */
static void PgpMgrSetRegister(AG903_PgpMgrPipelineHandle *handle)
{
    int32_t config;

    /* Primitive Layerを通してレジスタ値を設定します */
    PgpMgrDebugSetRegister(handle);

    /* 全レジスタの更新が行なわれたため、Dirtyフラグは全てリセットします */
    handle->is_dirty = false;
    for (config = 0; config < AG903_PGP_MGR_CONFIG_DIRTY_NUM; config++) {
        handle->is_config_dirty[config] = false;
    }
}


/* Primitive Layerを通してレジスタ値を設定します */
static void PgpMgrSetRegisterWithPrimitive(AG903_PgpMgrPipelineHandle *handle)
{
    int32_t config;
    int32_t id = handle->pipeline_no;

    handle->is_dirty = false;
    /* ConfigのDirtyフラグが設定されているレジスタのみ更新します */
    for (config = 0; config < AG903_PGP_MGR_CONFIG_DIRTY_NUM; config++) {
        if (handle->is_config_dirty[config] == true) {
            switch (config) {
                case AG903_PGP_MGR_CONFIG_INTR_CTRL:
                    AG903_PgpPrmSetPGPnINTCTRLI(id, handle->input_intr_field,
                                (handle->input_intr_fcnt == AG903_PGP_MGR_INTR_CTRL_MAX_FRAME_CNT) ? 0 : handle->input_intr_fcnt,
                                handle->input_intr_line);
                    AG903_PgpPrmSetPGPnINTCTRLO(id, handle->output_intr_field,
                                (handle->output_intr_fcnt == AG903_PGP_MGR_INTR_CTRL_MAX_FRAME_CNT) ? 0 : handle->output_intr_fcnt,
                                handle->output_intr_line);
                    break;
                case AG903_PGP_MGR_CONFIG_TRIG_CTRL:
                    AG903_PgpPrmSetPGPnTRGCTRLI(id, handle->input_trig_field,
                                (handle->input_trig_fcnt == AG903_PGP_MGR_TRIG_CTRL_MAX_FRAME_CNT) ? 0 : handle->input_trig_fcnt,
                                handle->input_trig_line);
                    AG903_PgpPrmSetPGPnTRGCTRLO(id, handle->output_trig_field,
                                (handle->output_trig_fcnt == AG903_PGP_MGR_TRIG_CTRL_MAX_FRAME_CNT) ? 0 : handle->output_trig_fcnt,
                                handle->output_trig_line);
                    break;
                case AG903_PGP_MGR_CONFIG_INPUT_TRIG_CH:
                    {
                        PGPPrmParamPGPnINCTRL inctrl;
                        inctrl.hdly = handle->input_hsync_delay;
                        inctrl.md   = handle->input_mode;
                        inctrl.tick = handle->input_timer_clk;
                        inctrl.trg  = handle->input_trig_timer_ch;
                        inctrl.sel  = handle->input_port;
                        inctrl.fmt  = handle->input_format;
                        AG903_PgpPrmSetPGPnINCTRL(id, &inctrl);
                    }
                    break;
                case AG903_PGP_MGR_CONFIG_OUTPUT_CTRL:
                    {
                        PGPPrmParamPGPnOUTCTRL0 outctrl0;
                        outctrl0.pad   = handle->output_pad;
                        outctrl0.limit = handle->output_limit;
                        outctrl0.fai   = handle->output_fai_enable;
                        outctrl0.dth   = handle->output_dither_enable;
                        outctrl0.bmu   = handle->output_bmu;
                        outctrl0.scan  = handle->output_scan;
                        outctrl0.dim   = handle->output_dim;
                        outctrl0.swapw = handle->output_word_swap_enable;
                        outctrl0.swaph = handle->output_hword_swap_enable;
                        outctrl0.swap4 = handle->output_4bit_swap_enable;
                        outctrl0.swap1 = handle->output_1bit_swap_enable;
                        outctrl0.md    = handle->output_md;
                        outctrl0.fmt   = handle->output_format;
                        AG903_PgpPrmSetPGPnOUTCTRL0(id, &outctrl0);
                    }
                    break;
                case AG903_PGP_MGR_CONFIG_OUTPUT_COLOR_MASK:
                    AG903_PgpPrmSetPGPnOUTCTRL1(id, handle->output_red_enable, handle->output_green_enable, handle->output_blue_enable);
                    break;
                case AG903_PGP_MGR_CONFIG_OUTPUT_BASE_ADDR:
                    AG903_PgpPrmSetPGPnOUTBASE(id, (handle->output_base_addr >> 3));
                    break;
                case AG903_PGP_MGR_CONFIG_IP_CONV:
                    AG903_PgpPrmSetPGPnIPCPRM(id, handle->ipc_limit, handle->ipc_blk_y, handle->ipc_blk_c);
                    break;
                case AG903_PGP_MGR_CONFIG_COLOR_SPACE:
                    AG903_PgpPrmSetPGPnCSC1CTRL(id, handle->csc1_limit, handle->csc1_shift);
                    AG903_PgpPrmSetPGPnCSC1PRM0(id, handle->csc1_matrix[0][1], handle->csc1_matrix[0][0]);
                    AG903_PgpPrmSetPGPnCSC1PRM1(id, handle->csc1_matrix[0][2]);
                    AG903_PgpPrmSetPGPnCSC1PRM2(id, handle->csc1_matrix[0][3]);
                    AG903_PgpPrmSetPGPnCSC1PRM3(id, handle->csc1_matrix[1][1], handle->csc1_matrix[1][0]);
                    AG903_PgpPrmSetPGPnCSC1PRM4(id, handle->csc1_matrix[1][2]);
                    AG903_PgpPrmSetPGPnCSC1PRM5(id, handle->csc1_matrix[1][3]);
                    AG903_PgpPrmSetPGPnCSC1PRM6(id, handle->csc1_matrix[2][1], handle->csc1_matrix[2][0]);
                    AG903_PgpPrmSetPGPnCSC1PRM7(id, handle->csc1_matrix[2][2]);
                    AG903_PgpPrmSetPGPnCSC1PRM8(id, handle->csc1_matrix[2][3]);
                    break;
                case AG903_PGP_MGR_CONFIG_SCALING:
                    {
                        PGPPrmParamPGPnSCCTRL scctrl;
                        scctrl.limit = handle->scale_limit;
                        scctrl.mtd   = handle->scale_mtd;
                        scctrl.nmrv  = (handle->scale_v_nmr == AG903_PGP_MGR_MAX_SCALING_VALUE) ? 0 : handle->scale_v_nmr;
                        scctrl.dnmv  = (handle->scale_v_dnm == AG903_PGP_MGR_MAX_SCALING_VALUE) ? 0 : handle->scale_v_dnm;
                        scctrl.nmrh  = (handle->scale_h_nmr == AG903_PGP_MGR_MAX_SCALING_VALUE) ? 0 : handle->scale_h_nmr;
                        scctrl.dnmh  = (handle->scale_h_dnm == AG903_PGP_MGR_MAX_SCALING_VALUE) ? 0 : handle->scale_h_dnm;
                        AG903_PgpPrmSetPGPnSCCTRL(id, &scctrl);
                    }
                    break;
                case AG903_PGP_MGR_CONFIG_SP_FILTER:
                    {
                        PGPPrmParamPGPnSPFCTRL spfctrl;
                        spfctrl.sft = handle->spf_shift;
                        spfctrl.bc  = handle->spf_border_sel;
                        spfctrl.r   = handle->spf_border_red;
                        spfctrl.g   = handle->spf_border_green;
                        spfctrl.b   = handle->spf_border_blue;
                        AG903_PgpPrmSetPGPnSPFCTRL(id, &spfctrl);
                        AG903_PgpPrmSetPGPnSPFPRM0(id, handle->spf_coeff[2], handle->spf_coeff[1], handle->spf_coeff[0]);
                        AG903_PgpPrmSetPGPnSPFPRM1(id, handle->spf_coeff[5], handle->spf_coeff[4], handle->spf_coeff[3]);
                        AG903_PgpPrmSetPGPnSPFPRM2(id, handle->spf_coeff[8], handle->spf_coeff[7], handle->spf_coeff[6]);
                        AG903_PgpPrmSetPGPnSPFPRM3(id, handle->spf_offset);
                    }
                    break;
                case AG903_PGP_MGR_CONFIG_HSVHSL_CONV:
                    AG903_PgpPrmSetPGPnHSV1CTRL(id, handle->hsv_hls_sel);
                    break;
                case AG903_PGP_MGR_CONFIG_HGM_PARAM:
                    {
                        PGPPrmParamPGPnHGMCTRL hgmctrl;
                        hgmctrl.inv  = handle->hgm_invalidate;
                        hgmctrl.bmu  = handle->hgm_bmu;
                        hgmctrl.exc  = handle->hgm_exc;
                        hgmctrl.thr  = handle->hgm_thr;
                        hgmctrl.sft  = handle->hgm_shift;
                        hgmctrl.vinc = handle->hgm_vinc;
                        hgmctrl.hinc = handle->hgm_hinc;
                        AG903_PgpPrmSetPGPnHGMCTRL(id, &hgmctrl);
                    }
                    break;
                case AG903_PGP_MGR_CONFIG_HGM_SIZE:
                    AG903_PgpPrmSetPGPnHGMSIZE(id, (handle->hgm_vsize == AG903_PGP_MGR_MAX_HGM_SIZE) ? 0 : handle->hgm_vsize,
                               (handle->hgm_hsize == AG903_PGP_MGR_MAX_HGM_SIZE) ? 0 : handle->hgm_hsize);
                    break;
                case AG903_PGP_MGR_CONFIG_HGM_POS:
                    AG903_PgpPrmSetPGPnHGMPOS(id, handle->hgm_vpos, handle->hgm_hpos);
                    break;
                case AG903_PGP_MGR_CONFIG_HGM_BASE_ADDR:
                    AG903_PgpPrmSetPGPnHGMDST(id, handle->hgm_addr >> 3);
                    break;
                case AG903_PGP_MGR_CONFIG_THR:
                    {
                        PGPPrmParamPGPnTHRCTRL thrctrl;
                        thrctrl.limit  = handle->thr_limit;
                        thrctrl.spf1   = handle->thr_spf1_enable;
                        thrctrl.msk    = handle->thr_msk_enable;
                        thrctrl.csc2   = handle->thr_csc2_enable;
                        thrctrl.hsv2   = handle->thr_hsv2_enable;
                        thrctrl.thr8   = handle->thr_thr8bit_enable;
                        thrctrl.outsel = handle->thr_out_sel;
                        thrctrl.c8sel  = handle->thr_clut8_sel;
                        AG903_PgpPrmSetPGPnTHRCTRL(id, &thrctrl);
                    }
                    break;
                case AG903_PGP_MGR_CONFIG_THR_HSCHLS_CONV:
                    AG903_PgpPrmSetPGPnHSV2CTRL(id, handle->thr_hsv_hls_sel);
                    break;
                case AG903_PGP_MGR_CONFIG_THR_COLOR_SPACE:
                    AG903_PgpPrmSetPGPnCSC2CTRL(id, handle->thr_csc2_limit, handle->thr_csc2_shift);
                    AG903_PgpPrmSetPGPnCSC2PRM0(id, handle->thr_csc2_matrix[0][1], handle->thr_csc2_matrix[0][0]);
                    AG903_PgpPrmSetPGPnCSC2PRM1(id, handle->thr_csc2_matrix[0][2]);
                    AG903_PgpPrmSetPGPnCSC2PRM2(id, handle->thr_csc2_matrix[0][3]);
                    AG903_PgpPrmSetPGPnCSC2PRM3(id, handle->thr_csc2_matrix[1][1], handle->thr_csc2_matrix[1][0]);
                    AG903_PgpPrmSetPGPnCSC2PRM4(id, handle->thr_csc2_matrix[1][2]);
                    AG903_PgpPrmSetPGPnCSC2PRM5(id, handle->thr_csc2_matrix[1][3]);
                    AG903_PgpPrmSetPGPnCSC2PRM6(id, handle->thr_csc2_matrix[2][1], handle->thr_csc2_matrix[2][0]);
                    AG903_PgpPrmSetPGPnCSC2PRM7(id, handle->thr_csc2_matrix[2][2]);
                    AG903_PgpPrmSetPGPnCSC2PRM8(id, handle->thr_csc2_matrix[2][3]);
                    break;
                case AG903_PGP_MGR_CONFIG_THR_MASK:
                    {
                        AG903_PgpPrmSetPGPnMSK0PRM0(id, handle->thr_msk_h[AG903_PGP_MGR_THR_CHANNEL_B],
                                    handle->thr_msk_l[AG903_PGP_MGR_THR_CHANNEL_B],
                                    handle->thr_msk_x[AG903_PGP_MGR_THR_CHANNEL_B]);
                        PGPPrmParamPGPnMSK0PRM1 msk0prm1;
                        msk0prm1.hmax = handle->thr_msk_hmax[AG903_PGP_MGR_THR_CHANNEL_B];
                        msk0prm1.hmin = handle->thr_msk_hmin[AG903_PGP_MGR_THR_CHANNEL_B];
                        msk0prm1.lmax = handle->thr_msk_lmax[AG903_PGP_MGR_THR_CHANNEL_B];
                        msk0prm1.lmin = handle->thr_msk_lmin[AG903_PGP_MGR_THR_CHANNEL_B];
                        AG903_PgpPrmSetPGPnMSK0PRM1(id, &msk0prm1);
                        AG903_PgpPrmSetPGPnMSK1PRM0(id, handle->thr_msk_h[AG903_PGP_MGR_THR_CHANNEL_G],
                                    handle->thr_msk_l[AG903_PGP_MGR_THR_CHANNEL_G],
                                    handle->thr_msk_x[AG903_PGP_MGR_THR_CHANNEL_G]);
                        PGPPrmParamPGPnMSK1PRM1 msk1prm1;
                        msk1prm1.hmax = handle->thr_msk_hmax[AG903_PGP_MGR_THR_CHANNEL_G];
                        msk1prm1.hmin = handle->thr_msk_hmin[AG903_PGP_MGR_THR_CHANNEL_G];
                        msk1prm1.lmax = handle->thr_msk_lmax[AG903_PGP_MGR_THR_CHANNEL_G];
                        msk1prm1.lmin = handle->thr_msk_lmin[AG903_PGP_MGR_THR_CHANNEL_G];
                        AG903_PgpPrmSetPGPnMSK1PRM1(id, &msk1prm1);
                        AG903_PgpPrmSetPGPnMSK2PRM0(id, handle->thr_msk_h[AG903_PGP_MGR_THR_CHANNEL_R],
                                    handle->thr_msk_l[AG903_PGP_MGR_THR_CHANNEL_R],
                                    handle->thr_msk_x[AG903_PGP_MGR_THR_CHANNEL_R]);
                        PGPPrmParamPGPnMSK2PRM1 msk2prm1;
                        msk2prm1.hmax = handle->thr_msk_hmax[AG903_PGP_MGR_THR_CHANNEL_R];
                        msk2prm1.hmin = handle->thr_msk_hmin[AG903_PGP_MGR_THR_CHANNEL_R];
                        msk2prm1.lmax = handle->thr_msk_lmax[AG903_PGP_MGR_THR_CHANNEL_R];
                        msk2prm1.lmin = handle->thr_msk_lmin[AG903_PGP_MGR_THR_CHANNEL_R];
                        AG903_PgpPrmSetPGPnMSK2PRM1(id, &msk2prm1);
                    }
                    break;
                case AG903_PGP_MGR_CONFIG_THR_8BIT:
                    {
                        PGPPrmParamPGPnTHR8PRM0 thr8prm0;
                        thr8prm0.type   = handle->thr_thr8_prm_type[AG903_PGP_MGR_THR_CHANNEL_B];
                        thr8prm0.maxval = handle->thr_thr8_prm_maxval[AG903_PGP_MGR_THR_CHANNEL_B];
                        thr8prm0.maxthr = handle->thr_thr8_prm_maxthr[AG903_PGP_MGR_THR_CHANNEL_B];
                        thr8prm0.minthr = handle->thr_thr8_prm_minthr[AG903_PGP_MGR_THR_CHANNEL_B];
                        AG903_PgpPrmSetPGPnTHR8PRM0(id, &thr8prm0);
                        PGPPrmParamPGPnTHR8PRM1 thr8prm1;
                        thr8prm1.type   = handle->thr_thr8_prm_type[AG903_PGP_MGR_THR_CHANNEL_G];
                        thr8prm1.maxval = handle->thr_thr8_prm_maxval[AG903_PGP_MGR_THR_CHANNEL_G];
                        thr8prm1.maxthr = handle->thr_thr8_prm_maxthr[AG903_PGP_MGR_THR_CHANNEL_G];
                        thr8prm1.minthr = handle->thr_thr8_prm_minthr[AG903_PGP_MGR_THR_CHANNEL_G];
                        AG903_PgpPrmSetPGPnTHR8PRM1(id, &thr8prm1);
                        PGPPrmParamPGPnTHR8PRM2 thr8prm2;
                        thr8prm2.type   = handle->thr_thr8_prm_type[AG903_PGP_MGR_THR_CHANNEL_R];
                        thr8prm2.maxval = handle->thr_thr8_prm_maxval[AG903_PGP_MGR_THR_CHANNEL_R];
                        thr8prm2.maxthr = handle->thr_thr8_prm_maxthr[AG903_PGP_MGR_THR_CHANNEL_R];
                        thr8prm2.minthr = handle->thr_thr8_prm_minthr[AG903_PGP_MGR_THR_CHANNEL_R];
                        AG903_PgpPrmSetPGPnTHR8PRM2(id, &thr8prm2);
                    }
                    break;
                case AG903_PGP_MGR_CONFIG_THR_1BIT:
                    {
                        AG903_PgpPrmSetPGPnTHR1PRM0(id, handle->thr_thr1_h, handle->thr_thr1_l, handle->thr_thr1_x);
                        PGPPrmParamPGPnTHR1PRM1 thr1prm1;
                        thr1prm1.hmax = handle->thr_thr1_hmax;
                        thr1prm1.hmin = handle->thr_thr1_hmin;
                        thr1prm1.lmax = handle->thr_thr1_lmax;
                        thr1prm1.lmin = handle->thr_thr1_lmin;
                        AG903_PgpPrmSetPGPnTHR1PRM1(id, &thr1prm1);
                    }
                    break;
                case AG903_PGP_MGR_CONFIG_THR_SP_FILTER_1BIT:
                    {
                        PGPPrmParamPGPnSPF1PRM0 spf1prm0;
                        spf1prm0.h10 = handle->thr_spf1_coeff[5];
                        spf1prm0.h00 = handle->thr_spf1_coeff[4];
                        spf1prm0.hm0 = handle->thr_spf1_coeff[3];
                        spf1prm0.h1m = handle->thr_spf1_coeff[2];
                        spf1prm0.h0m = handle->thr_spf1_coeff[1];
                        spf1prm0.hmm = handle->thr_spf1_coeff[0];
                        AG903_PgpPrmSetPGPnSPF1PRM0(id, &spf1prm0);
                        PGPPrmParamPGPnSPF1PRM1 spf1prm1;
                        spf1prm1.thr = handle->thr_spf1_thr;
                        spf1prm1.h11 = handle->thr_spf1_coeff[8];
                        spf1prm1.h01 = handle->thr_spf1_coeff[7];
                        spf1prm1.hm1 = handle->thr_spf1_coeff[6];
                        AG903_PgpPrmSetPGPnSPF1PRM1(id, &spf1prm1);
                    }
                    break;
                case AG903_PGP_MGR_CONFIG_LBL_PARAM:
                    {
                        PGPPrmParamPGPnLBLCTRL lblctrl;
                        lblctrl.vld   = (handle->lbl_valid == AG903_PGP_MGR_MAX_LBL_OUTPUT_VALIDATE) ? 0 : handle->lbl_valid;
                        lblctrl.inv   = handle->lbl_invalid;
                        lblctrl.cnct  = handle->lbl_connect;
                        lblctrl.bmu   = handle->lbl_bmu;
                        lblctrl.flthr = handle->lbl_flush_thr;
                        lblctrl.maxid = handle->lbl_maxid;
                        AG903_PgpPrmSetPGPnLBLCTRL(id, &lblctrl);
                    }
                    break;
                case AG903_PGP_MGR_CONFIG_LBL_SIZE:
                    AG903_PgpPrmSetPGPnLBLSIZE(id, (handle->lbl_vsize == AG903_PGP_MGR_MAX_LBL_VSIZE) ?
                               0 : handle->lbl_vsize, handle->lbl_hsize);
                    break;
                case AG903_PGP_MGR_CONFIG_LBL_POS:
                    AG903_PgpPrmSetPGPnLBLPOS(id, handle->lbl_vpos, handle->lbl_hpos);
                    break;
                case AG903_PGP_MGR_CONFIG_LBL_BASE_ADDR:
                    AG903_PgpPrmSetPGPnLBLDST(id, handle->lbl_addr >> 3);
                    break;
                case AG903_PGP_MGR_CONFIG_IFC_PARAM:
                    {
                        PGPPrmParamPGPnIFCCTRL ifcctrl;
                        ifcctrl.scan  = handle->ifc_scan;
                        ifcctrl.limit = handle->ifc_limit;
                        ifcctrl.src   = handle->ifc_slave_src;
                        ifcctrl.op    = handle->ifc_operation;
                        ifcctrl.sft1  = handle->ifc_slave_shift;
                        ifcctrl.sft0  = handle->ifc_master_shift;
                        AG903_PgpPrmSetPGPnIFCCTRL(id, &ifcctrl);
                    }
                    break;
                case AG903_PGP_MGR_CONFIG_IFC_GAIN:
                    AG903_PgpPrmSetPGPnIFCPRM(id, handle->ifc_slave_gain, handle->ifc_master_gain);
                    break;
                case AG903_PGP_MGR_CONFIG_INTR_ENABLE:
                default:
                    {
                        PGPPrmParamPGPnINTEN inten;
                        inten.nd      = handle->intr_nd_enable;
                        inten.voicpl  = handle->intr_voicpl_enable;
                        inten.vooflw  = handle->intr_vooflw_enable;
                        inten.ifcofs  = handle->intr_ifcofs_enable;
                        inten.ifcofm  = handle->intr_ifcofm_enable;
                        inten.lblcrpt = handle->intr_lblcrpt_enable;
                        inten.lblcpl  = handle->intr_lblcpl_enable;
                        inten.hgmicpl = handle->intr_hgmicpl_enable;
                        inten.hgmcpl  = handle->intr_hgmcpl_enable;
                        inten.vsynco  = handle->intr_vsynco_enable;
                        inten.vlineo  = handle->intr_vlineo_enable;
                        inten.vsynci  = handle->intr_vsynci_enable;
                        inten.vlinei  = handle->intr_vlinei_enable;
                        AG903_PgpPrmSetPGPnINTEN(id, &inten);
                    }
                    break;
            }
        }
        handle->is_config_dirty[config] = false;
    }
}

/* 現在実行中のパイプラインハンドルに登録されているコールバックを参照先に設定します */
static void PgpMgrSetCallbackFunc(AG903_PgpMgrPipelineHandle *handle)
{
    PgpMgrContext *ctx = PgpGetContext();
    int32_t id = handle->pipeline_no;

    ctx->intr_input_func[id] = handle->intr_input_func;
    ctx->intr_output_func[id] = handle->intr_output_func;
    ctx->intr_done_func[id] = handle->intr_done_func;
    ctx->intr_vram_error_func[id] = handle->intr_vram_error_func;
    ctx->intr_lbl_error_func[id] = handle->intr_lbl_error_func;
    ctx->intr_hgm_error_func[id] = handle->intr_hgm_error_func;
    ctx->intr_nd_func[id] = handle->intr_nd_func;
    ctx->intr_ifc_ovf_func[id] = handle->intr_ifc_ovf_func;
    ctx->intr_input_line_func[id] = handle->intr_input_line_func;
    ctx->intr_output_line_func[id] = handle->intr_output_line_func;
    ctx->intr_lbl_done_func[id] = handle->intr_lbl_done_func;
    ctx->intr_hgm_done_func[id] = handle->intr_hgm_done_func;
}


/* 濃度変換テーブルを入れ換えます */
static void PgpMgrSetDGCTable(AG903_PgpMgrPipelineHandle *handle)
{
    int32_t id;
    AG903_PgpMgrDGCLookupTable *dgc_lut = handle->dgc_lut;
    id = handle->pipeline_no;

    /* Primitive Layerを通して濃度変換テーブルを変更します */
    AG903_PgpPrmSetPGPnDGCFLUTB(id, dgc_lut->lut_data[0]);
    AG903_PgpPrmSetPGPnDGCFLUTG(id, dgc_lut->lut_data[1]);
    AG903_PgpPrmSetPGPnDGCFLUTR(id, dgc_lut->lut_data[2]);
    handle->dgc_lut_dirty = false;
}

/* 指定されたコマンドによるパイプラインの実行が可能かチェックします */
static int32_t PgpMgrCheckExecute(AG903_PgpMgrPipelineHandle *handle, uint32_t cmd)
{
    PgpMgrContext *ctx = PgpGetContext();
    PGPPrmParamPGPnSTATE state;

    /* 実行先の物理パイプラインのステータスを取得 */
    AG903_PgpPrmGetPGPnSTATE(handle->pipeline_no, &state);
    /* 他のパイプラインハンドルが現在実行中の場合はエラー */
    if ((ctx->exec_pipeline[handle->pipeline_no] != handle ) && (state.st != AG903_PGP_MGR_STATE_IDLE)) {
        return -AG903_EBUSY;
    }
    /* コマンドの実行が可能かチェック */
    switch (cmd) {
        case AG903_PGP_MGR_CMD_EXEC:
        case AG903_PGP_MGR_CMD_TRIG:
            /* コマンドキューに空きがない、または、他のコマンドが実行中の場合エラー */
            if ((state.queue == (AG903_PGP_MGR_PIPELINE_CMD_MAX_QUEUE - 1)) || ((state.st != AG903_PGP_MGR_STATE_IDLE) && (cmd != state.st))) {
                return -AG903_EBUSY;
            }
            break;
        case AG903_PGP_MGR_CMD_EXEC_CONTINUE:
        case AG903_PGP_MGR_CMD_TRIG_CONTINUE:
            /* 連続キャプチャコマンドはアイドル時のみ受けつけ可能 */
            if (state.st != AG903_PGP_MGR_STATE_IDLE) {
                return -AG903_EBUSY;
            }
            break;
        default:
            break;
    }

    return 0;
}


/**
 * @brief   パイプラインハンドルを割り当て先の物理パイプラインで実行します。
 * @param   handle [in] 実行するパイプラインハンドルを指定します。
 * @param   cmd [in] 実行コマンドを指定します。
 * @return  AG903_ENONE 正常終了
 * @return  -AG903_EBUSY 実行する物理パイプラインが他のパイプラインハンドルによって実行中の場合
 * @return  -AG903_EBUSY パイプラインのコマンドキューに空きが無い場合、コマンドを受けつける状態では無い場合
 * @note    本関数はユーザー側が直接使用することはありません。
*/
int32_t PgpMgrExecPipelineHandle(AG903_PgpMgrPipelineHandle *handle, uint32_t cmd)
{
    PgpMgrContext *ctx = PgpGetContext();

    /* 指定されたコマンドによるパイプラインの実行が可能かチェックします */
    if (PgpMgrCheckExecute(handle, cmd) != 0) {
        return -AG903_EBUSY;
    }
    /* レジスタを設定(現在物理パイプラインで実行中の場合は最低限のレジスタ設定をPrimitive Layer経由で行なう) */
    if (ctx->exec_pipeline[handle->pipeline_no] != handle) {
        PgpMgrSetRegister(handle);
    } else {
        PgpMgrSetRegisterWithPrimitive(handle);
    }
    /* 濃度変換テーブルが変更されている場合は更新します */
    if (handle->dgc_lut_dirty == true) {
        PgpMgrSetDGCTable(handle);
    }

    /* 割り込みに対応するコールバックの設定 */
    PgpMgrSetCallbackFunc(handle);

    /* コマンド発行 */
    AG903_PgpPrmSetPGPnCMD(handle->pipeline_no, cmd);

    /* 現在実行中のパイプライン情報を更新します */
    ctx->exec_pipeline[handle->pipeline_no] = handle;
    return AG903_ENONE;
}


/**
 * @brief   フレーム間演算ハンドルハンドルを割り当て先の物理パイプラインで実行します。
 * @param   handle [in] 実行するフレーム間演算ハンドルを指定します。
 * @param   cmd [in] 実行コマンドを指定します。
 * @return  AG903_ENONE 正常終了
 * @return  -AG903_EBUSY 実行する物理パイプラインが他のパイプラインハンドルによって実行中の場合
 * @return  -AG903_EBUSY コマンドのキューに空きが無い場合
 * @note    マスタ側スレーブ側には同じコマンドを発行します。<p>
 *          本関数はユーザー側が直接使用することはありません。
*/
int32_t PgpMgrExecFrameCalcHandle(AG903_PgpMgrFrameCalcHandle *handle, uint32_t cmd)
{
    AG903_PgpMgrPipelineHandle *slave = NULL;
    PgpMgrContext *ctx = PgpGetContext();

    /* 指定されたコマンドによるマスタ側パイプラインの実行が可能かチェックします */
    if (PgpMgrCheckExecute(handle->master_handle, cmd) != 0) {
        return -AG903_EBUSY;
    }
    /* スレーブ側がパイプラインハンドルの場合、マスタ側と同じ確認をします */
    if (handle->slave_pipeline == true) {
        slave = (AG903_PgpMgrPipelineHandle *)handle->slave_handle;
        /* 指定されたコマンドによるマスタ側パイプラインの実行が可能かチェックします */
        if (PgpMgrCheckExecute(slave, cmd) != 0) {
            return -AG903_EBUSY;
        }
        /* レジスタを設定(現在物理パイプラインで実行中の場合は最低限のレジスタ設定をPrimitive Layer経由で行なう) */
        if (ctx->exec_pipeline[slave->pipeline_no] != slave) {
            PgpMgrSetRegister(slave);
        } else {
            PgpMgrSetRegisterWithPrimitive(slave);
        }
        /* 現在実行中のパイプライン情報を更新します */
        ctx->exec_pipeline[slave->pipeline_no] = slave;
    }
    /* スレーブ側がVRAM入力ハンドルの場合、レジスタを設定 */
    else {
        /* コマンドはハードウェアから自動で発行されるので、レジスタ設定のみ */
        AG903_PgpMgrVRAMInputHandle *vramin_handle;
        vramin_handle = (AG903_PgpMgrVRAMInputHandle *)handle->slave_handle;
        PgpMgrExecVRAMInputHandle(vramin_handle, AG903_PGP_MGR_VI_CMD_NONE);
    }

    /* レジスタを設定(現在物理パイプラインで実行中の場合は最低限のレジスタ設定をPrimitive Layer経由で行なう) */
    if (ctx->exec_pipeline[handle->master_handle->pipeline_no] != handle->master_handle) {
        PgpMgrSetRegister(handle->master_handle);
    } else {
        PgpMgrSetRegisterWithPrimitive(handle->master_handle);
    }
    /* 現在実行中のパイプライン情報を更新します */
    ctx->exec_pipeline[handle->master_handle->pipeline_no] = handle->master_handle;

    /* 割り込みに対応するコールバックの設定 */
    PgpMgrSetCallbackFunc(handle->master_handle);

    /* コマンド発行(マスタ、スレーブの順で発行) */
    AG903_PgpPrmSetPGPnCMD(handle->master_handle->pipeline_no, cmd);
    if (handle->slave_pipeline == true) {
        /* 割り込みに対応するコールバックの設定 */
        PgpMgrSetCallbackFunc(slave);
        AG903_PgpPrmSetPGPnCMD(slave->pipeline_no, cmd);
    }

    return AG903_ENONE;
}


/* Primitive Layer経由でレジスタを設定するための関数 */
static void PgpMgrDebugSetRegisterVRAM(AG903_PgpMgrVRAMInputHandle *handle)
{
    int32_t id = handle->port_no;

    PGPPrmParamPGPVInCTRL0 victrl;
    victrl.fai   = handle->fai_enable;
    victrl.bmu   = handle->bmu;
    victrl.scan  = handle->scan;
    victrl.dim   = handle->dim;
    victrl.swapw = handle->vram_word_swap_enable;
    victrl.swaph = handle->vram_hword_swap_enable;
    victrl.swap4 = handle->vram_4bit_swap_enable;
    victrl.swap1 = handle->vram_1bit_swap_enable;
    victrl.md    = handle->md;
    victrl.fmt   = handle->format;
    AG903_PgpPrmSetPGPVInCTRL0(id, &victrl);
    AG903_PgpPrmSetPGPVInCTRL1(id, (handle->div == AG903_PGP_MGR_MAX_VI_DIV) ? 0 : handle->div, 
                               (handle->valid == AG903_PGP_MGR_MAX_VI_VALIDATE) ? 0 : handle->valid, handle->invalid);
    AG903_PgpPrmSetPGPVInBASE(id, handle->addr >> 3);
    AG903_PgpPrmSetPGPVInHSIZE(id, (handle->stride == AG903_PGP_MGR_VI_MAX_STRIDE_BYTE) ? 0 : handle->stride);
    AG903_PgpPrmSetPGPVInHPRM0(id, (handle->h_pulse_width == AG903_PGP_MGR_MAX_VI_H_PULES_WIDTH) ? 0 : handle->h_pulse_width);
    AG903_PgpPrmSetPGPVInHPRM1(id, (handle->h_front_porch == AG903_PGP_MGR_MAX_VI_H_FRONT_PORCH) ? 0 : handle->h_front_porch,
                               (handle->h_back_porch == AG903_PGP_MGR_MAX_VI_H_BACK_PORCH) ? 0 : handle->h_back_porch);

    PGPPrmParamPGPVInVPRM0 vivprm0;
    vivprm0.ebp = handle->adjust_even_vbp;
    vivprm0.efp = handle->adjust_even_vfp;
    vivprm0.obp = handle->adjust_odd_vbp;
    vivprm0.ofp = handle->adjust_odd_vfp;
    vivprm0.vpw = (handle->v_pulse_width == AG903_PGP_MGR_MAX_VI_V_PULES_WIDTH) ? 0 : handle->v_pulse_width;
    AG903_PgpPrmSetPGPVInVPRM0(id, &vivprm0);
    AG903_PgpPrmSetPGPVInVPRM1(id, (handle->v_front_porch == AG903_PGP_MGR_MAX_VI_V_FRONT_PORCH) ? 0 : handle->v_front_porch,
                               (handle->v_back_porch == AG903_PGP_MGR_MAX_VI_V_BACK_PORCH) ? 0 : handle->v_back_porch);
    AG903_PgpPrmSetPGPVInSIZE(id, handle->adjust_odd_vsize,
                               (handle->v_frame_size == AG903_PGP_MGR_MAX_VI_V_SIZE) ? 0 : handle->v_frame_size,
                               (handle->h_frame_size == AG903_PGP_MGR_MAX_VI_H_SIZE) ? 0 : handle->h_frame_size);
}

/* Primitive Layerを通してレジスタ値を設定します */
static void PgpMgrSetRegisterVRAM(AG903_PgpMgrVRAMInputHandle *handle)
{
    int32_t config;

    /* Primitive Layerを通してレジスタ値を設定します */
    PgpMgrDebugSetRegisterVRAM(handle);

    /* 全レジスタの更新が行なわれたため、Dirtyフラグは全てリセットします */
    handle->is_dirty = false;
    for (config = 0; config < AG903_PGP_MGR_CONFIG_VI_DIRTY_NUM; config++) {
        handle->is_config_dirty[config] = false;
    }
}

/* Primitive Layerを通してレジスタ値を設定します */
static void PgpMgrSetRegisterVRAMWithPrimitive(AG903_PgpMgrVRAMInputHandle *handle)
{
    int32_t config;
    int32_t id = handle->port_no;

    handle->is_dirty = false;
    for (config = 0; config < AG903_PGP_MGR_CONFIG_VI_DIRTY_NUM; config++) {
        if (handle->is_config_dirty[config] == true) {
            switch (config) {
                case AG903_PGP_MGR_CONFIG_VI_CTRL:
                    {
                        PGPPrmParamPGPVInCTRL0 victrl;
                        victrl.fai   = handle->fai_enable;
                        victrl.bmu   = handle->bmu;
                        victrl.scan  = handle->scan;
                        victrl.dim   = handle->dim;
                        victrl.swapw = handle->vram_word_swap_enable;
                        victrl.swaph = handle->vram_hword_swap_enable;
                        victrl.swap4 = handle->vram_4bit_swap_enable;
                        victrl.swap1 = handle->vram_1bit_swap_enable;
                        victrl.md    = handle->md;
                        victrl.fmt   = handle->format;
                        AG903_PgpPrmSetPGPVInCTRL0(id, &victrl);
                    }
                    break;
                case AG903_PGP_MGR_CONFIG_VI_CTRL1:
                    AG903_PgpPrmSetPGPVInCTRL1(id, (handle->div == AG903_PGP_MGR_MAX_VI_DIV) ? 0 : handle->div, 
                               (handle->valid == AG903_PGP_MGR_MAX_VI_VALIDATE) ? 0 : handle->valid, handle->invalid);
                    break;
                case AG903_PGP_MGR_CONFIG_VI_BASE:
                    AG903_PgpPrmSetPGPVInBASE(id, handle->addr >> 3);
                    break;
                case AG903_PGP_MGR_CONFIG_VI_ADJUST_FRAME:
                default:
                    {
                        PGPPrmParamPGPVInVPRM0 vivprm0;
                        vivprm0.ebp = handle->adjust_even_vbp;
                        vivprm0.efp = handle->adjust_even_vfp;
                        vivprm0.obp = handle->adjust_odd_vbp;
                        vivprm0.ofp = handle->adjust_odd_vfp;
                        vivprm0.vpw = (handle->v_pulse_width == AG903_PGP_MGR_MAX_VI_V_PULES_WIDTH) ? 0 : handle->v_pulse_width;
                        AG903_PgpPrmSetPGPVInVPRM0(id, &vivprm0);
                        AG903_PgpPrmSetPGPVInSIZE(id, handle->adjust_odd_vsize,
                                   (handle->v_frame_size == AG903_PGP_MGR_MAX_VI_V_SIZE) ? 0 : handle->v_frame_size,
                                   (handle->h_frame_size == AG903_PGP_MGR_MAX_VI_H_SIZE) ? 0 : handle->h_frame_size);
                    }
                    break;
            }
        }
        handle->is_config_dirty[config] = false;
    }
}


/**
 * @brief   VRAM入力ハンドルを割り当て先の物理VRAM入力ポートで実行します。
 * @param   handle [in] 実行するVRAM入力ポートハンドルを指定します。
 * @param   cmd [in] 実行コマンドを指定します。
 * @return  none
 * @note    本関数はユーザー側が直接使用することはありません。
*/
void PgpMgrExecVRAMInputHandle(AG903_PgpMgrVRAMInputHandle *handle, uint32_t cmd)
{
    PgpMgrContext *ctx = PgpGetContext();

    /* レジスタを設定(現在物理VRAM入力ポートで実行中の場合は最低限のレジスタ設定をPrimitive Layer経由で行なう) */
    if (ctx->exec_vram[handle->port_no] != handle) {
        PgpMgrSetRegisterVRAM(handle);
    } else {
        PgpMgrSetRegisterVRAMWithPrimitive(handle);
    }
    /* Primitive Layerを通してコマンドを発行 */
    AG903_PgpPrmSetPGPVInCMD(handle->port_no, cmd);
    /* 現在実行中のVRAM入力パイプライン情報を更新します */
    ctx->exec_vram[handle->port_no] = handle;
}

