/**
 * @brief       DSP Manager
 * @author      AXELL CORPORATION
 * @description DSP Manager
 * @note        none
 * @history     2017_09_04  初版
 * @history     2017_10_26  Ver2.0
 * @history     2019_03_08  [SDK2.2] DSPでのハンドラ取得済チャンネルを再取得した場合の不具合を修正 (#2201)
 * @history     2019_12_27  [SDK3.0] DSPマネージャでアトリビュートロックを初期化していない不具合を修正 (#2034)
 */
/* DOM-IGNORE-BEGIN */
/*
 * This program was created by AXELL CORPORATION.
 * Copyright (C) 2017-2019 AXELL CORPORATION, all rights reserved.
 */
/* DOM-IGNORE-END */

#include "AG903_common.h"

#include "dsp/dspprm.h"
#include "dsp/vodprm.h"
#include "dsp/dspmgr.h"

/* データ構造定義 */

/**
 * DSPチャンネル管理
 */
typedef struct _DSPChBlock {
	uint32_t channel;					/** チャネル */
	uint32_t *lock[AG903_DSP_ATTR_MAX];	/** アトリビュート使用中フラグ (NULL:未使用 ADDR:使用) */
}DSPChBlock;

/* グローバル変数定義 */

/**
 * DSP管理ブロック
 */
static struct {
	bool 				init;						/** 初期化済み false:未初期化 */
	DSPChBlock 			ch[AG903_DSP_CH_NUM];		/** DSPチャンネル管理 */
	AG903_DSPMgrHandle 	*lock[AG903_DSP_CH_NUM];	/** データ使用中フラグ (NULL:未使用 ADDR:使用) */
}gDSP;												/** DSP管理データ */

/* プロトタイプ定義 */
static void AG903_DSPMgrInitDSP(uint8_t ch);
static void AG903_DSPMgrInitVOD(uint8_t ch);
static int32_t DSPMgrCheckHandle(AG903_DSPMgrHandle *handle, uint8_t *ch);

/**
 * @brief           DSP初期化
 * @param           ch [in] チャンネル
 * @return          void
 * @description     指定したチャンネルのDSPモジュールを初期化します.
 * @note            各レジスタに初期値をセットし、不定部は0でクリアします.
*/
static void AG903_DSPMgrInitDSP(uint8_t ch) {
	if (ch > AG903_DSP_CH_NUM) return;

	DSPPrmParamMOD mod = {
		.de   = AG903_DSP_RGBDE_SIGNAL_DATA,
		.ip   = AG903_DSP_VMODE_NONINTERLACE,
		.upd  = AG903_DSP_ATTR_END_OF_VSYNC,
		.bmr  = AG903_DSP_BMU_WINDATA,
		.lut  = false,
		.dith = false,
	};
	DSPPrmParamSYNC sync = {
		.sel = AG903_DSP_EXSYNC_NONE,
		.dly = false,
		.ip  = AG903_DSP_VMODE_NONINTERLACE,
		.vp  = AG903_DSP_POLARITY_NEGA,
		.fp  = AG903_DSP_POLARITY_NEGA,
		.msk = true,
	};
	DSPPrmParamVTPRM0 vtprm0 = {
		.vpw = 2,
		.ofp = false,
		.obp = false,
		.efp = false,
		.ebp = false,
	};
	DSPPrmParamCDCTRL cdctrl = {
		.be = false,
		.ge = false,
		.re = false,
		.ae = false,
	};
	DSPPrmParamCOLDET coldet = {
		.b = 0x00000000,
		.g = 0x00000000,
		.r = 0x00000000,
		.a = 0x00000000,
	};
	DSPPrmParamERRCLR errclr = {
		.line = true,
		.ue   = true,
		.le   = true,
		.pe   = true,
	};
	DSPPrmParamINT intprm = {
		.line  = 0,
		.fcnt  = 0,
		.hline = AG903_DSP_INT_START_OF_LINE,
		.vblk  = AG903_DSP_INT_START_OF_VBLANK,
	};
	DSPPrmParamINTMASK intmask = {
		.vblk  = true,
		.hline = true,
		.doff  = true,
		.err   = true,
	};
	DSPPrmParamLUTR lutr = {
		.r0 = 0x00,
		.r1 = 0x00,
		.r2 = 0x00,
		.r3 = 0x00,
	};
	DSPPrmParamLUTG lutg = {
		.g0 = 0x00,
		.g1 = 0x00,
		.g2 = 0x00,
		.g3 = 0x00,
	};
	DSPPrmParamLUTB lutb = {
		.b0 = 0x00,
		.b1 = 0x00,
		.b2 = 0x00,
		.b3 = 0x00,
	};

	AG903_DSPPrmSetCTRL(ch, AG903_DSP_CTRL_OFF);
	AG903_DSPPrmSetMOD(ch, &mod);
	AG903_DSPPrmSetSYNC(ch, &sync);
	AG903_DSPPrmSetBGCOL(ch, 0x00000000);
	AG903_DSPPrmSetWINNUM(ch, 1);
	AG903_DSPPrmSetWATNUM(ch, 1);
	AG903_DSPPrmSetWATBASE(ch, 0x00000000);
	AG903_DSPPrmSetLSTCTRL(ch, false, false);
	AG903_DSPPrmSetHRZPRM0(ch, 0x060);
	AG903_DSPPrmSetHRZPRM1(ch, 0x010, 0x030);
	AG903_DSPPrmSetVTPRM0(ch, &vtprm0);
	AG903_DSPPrmSetVTPRM1(ch, 0x00A, 0x021);
	AG903_DSPPrmSetFRMSIZE(ch, 0x1E0, 0x280);
	AG903_DSPPrmSetCDCTRL(ch, &cdctrl);
	AG903_DSPPrmSetCOLDET(ch, &coldet);
	AG903_DSPPrmSetDITHAREA0A(ch, 0x7FF, 0x7FF);
	AG903_DSPPrmSetDITHAREA0B(ch, 0x000, 0x000);
	AG903_DSPPrmSetDITHAREA1A(ch, 0x7FF, 0x7FF);
	AG903_DSPPrmSetDITHAREA1B(ch, 0x000, 0x000);
	AG903_DSPPrmSetDITHAREA2A(ch, 0x7FF, 0x7FF);
	AG903_DSPPrmSetDITHAREA2B(ch, 0x000, 0x000);
	AG903_DSPPrmSetDITHAREA3A(ch, 0x7FF, 0x7FF);
	AG903_DSPPrmSetDITHAREA3B(ch, 0x000, 0x000);
	AG903_DSPPrmSetERRCLR(ch, &errclr);
	AG903_DSPPrmSetINT(ch, &intprm);
	AG903_DSPPrmSetTRIGGER(ch, AG903_DSP_EVENT_VT,
						   AG903_DSP_TRG_HRZ_START_OF_LINE,
						   AG903_DSP_TRG_VT_START_OF_VBLANK);
	AG903_DSPPrmSetINTCLR(ch, true,
						  true,
						  true);
	AG903_DSPPrmSetINTMASK(ch, &intmask);
	AG903_DSPPrmSetDMAREQ(ch, AG903_DSP_DMA_NONE);
	int32_t tnum;
	for(tnum=0; tnum<AG903_DSP_LUT_NUM; tnum++)
	{
		AG903_DSPPrmSetLUTR(ch, tnum, &lutr);
		AG903_DSPPrmSetLUTG(ch, tnum, &lutg);
		AG903_DSPPrmSetLUTB(ch, tnum, &lutb);
	}

	int listno;
	for (listno=0; listno<AG903_DSP_ATTR_MAX; listno++)
	{
		gDSP.ch[ch].lock[listno] = NULL;
	}
}

/**
 * @brief           VOD初期化
 * @param           ch [in] チャンネル
 * @return          void
 * @description     指定したチャンネルのDSPモジュールを初期化します.
 * @note            各レジスタに初期値をセットします.
 */
static void AG903_DSPMgrInitVOD(uint8_t ch) {
	if (ch > AG903_DSP_CH_NUM) return;

	VODPrmParamMOD mod = {
		.dp   = AG903_DSP_POLARITY_POSI,
		.vp	  = AG903_DSP_POLARITY_NEGA,
		.hp	  = AG903_DSP_POLARITY_NEGA,
		.fp	  = AG903_DSP_POLARITY_NEGA,
		.cdp  = AG903_DSP_POLARITY_POSI,
		.dex  = AG903_DSP_SIGNAL_ENABLE,
		.vex  = AG903_DSP_SIGNAL_ENABLE,
		.hex  = AG903_DSP_SIGNAL_ENABLE,
		.fex  = AG903_DSP_SIGNAL_ENABLE,
		.cdex = AG903_DSP_SIGNAL_ENABLE,
		.pex  = AG903_DSP_SIGNAL_ENABLE,
		.cp   = AG903_VOD_DOTCLK_LATCH_RISE,
		.code = false,
		.yuv  = AG903_VOD_MOD_YUV_BT601,
		.fmt  = 0,
		.ct0  = 0,
		.ct1  = 0,
	};

	if (ch == 0) {
		AG903_VODPrmSetPORTSEL(ch, AG903_VOD0_PORTSEL_LVCMOS24);
	} else {
		AG903_VODPrmSetPORTSEL(ch, AG903_VOD1_PORTSEL_LVDS_DUAL);
	}
	AG903_VODPrmSetMOD(ch, &mod);
	AG903_VODPrmSetBPWRMOD(ch, false, AG903_VOD_BPWR_UNIT_FRAME);
	AG903_VODPrmSetPPWRONCNT(ch, 0x00000000);
	AG903_VODPrmSetBPWRONCNT(ch, 0x00000000);
	AG903_VODPrmSetBLGTONCNT(ch, 0x00000000);
	AG903_VODPrmSetPPWROFFCNT(ch, 0x00000000);
	AG903_VODPrmSetBPWROFFCNT(ch, 0x00000000);
	AG903_VODPrmSetBLGTOFFCNT(ch, 0x00000000);
	AG903_VODPrmSetPWMPERIOD(ch, 0x00000000);
	AG903_VODPrmSetPWMCNT(ch, 0x00000000);
	AG903_VODPrmSetMACRO0(AG903_VOD_FR_8_16MHZ,
						  AG903_VOD_PM_AUTO, AG903_VOD_PDX_PWRDOWN);
	AG903_VODPrmSetMACRO1(AG903_VOD_FR_8_16MHZ,
						  AG903_VOD_PM_AUTO, AG903_VOD_PDX_PWRDOWN);
}

/**
 * @brief           DSPMgr全初期化
 * @param           void
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @description     全てのDSPモジュールを初期化し、DSPMgrを初期化します.
 */
int32_t AG903_DSPMgrInit(void)
{
	uint8_t ch;
	uint32_t attr;

	for (ch=0; ch<AG903_DSP_CH_NUM; ch++) {
		if (gDSP.init == false) {
			/* DSP,VOD全レジスタ初期化 */
			AG903_DSPMgrInitDSP(ch);
			AG903_DSPMgrInitVOD(ch);
		}
		/* 内部データ初期化 */
		gDSP.ch[ch].channel = ch;
		for (attr=0; attr<AG903_DSP_ATTR_MAX; attr++) {
			gDSP.ch[ch].lock[attr] = NULL;
		}
		gDSP.lock[ch] = NULL;
	}

	gDSP.init = true; /* 初期化済み設定 */

	return AG903_ENONE;
}

/**
 * @brief           DSPハンドル取得
 * @param           ch [in] チャンネル(0-1)
 * @param           handle [out] DSPハンドル
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @retval          -AG903_EBUSY ハンドル使用中
 * @description     指定したチャンネルのDSPハンドルを取得します.
 */
int32_t AG903_DSPMgrGetHandle(uint8_t ch, AG903_DSPMgrHandle **handle)
{
	int32_t	rc = AG903_ENONE;

	if ((ch > AG903_DSP_CH_NUM) || (handle == NULL)) {
		rc = -AG903_EINVAL;
	}

	if (rc == AG903_ENONE) {
		if (gDSP.init == false) {
			AG903_DSPMgrInit();					/* DSPモジュール初期化 */
		} else {
			if (gDSP.lock[ch] != NULL) {
				rc = -AG903_EBUSY;
			} else {
				AG903_DSPMgrInitDSP(ch);
				AG903_DSPMgrInitVOD(ch);
			}
		}
	}

	if (rc == AG903_ENONE) {
		(*handle) = (AG903_DSPMgrHandle *)&gDSP.ch[ch];
		gDSP.lock[ch] = (AG903_DSPMgrHandle *)(*handle);
	}

	return rc;
}

/**
 * @brief           DSPハンドル解放
 * @param           handle [in] DSPハンドル
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     DSPハンドルを返却します.
 */
int32_t AG903_DSPMgrReleaseHandle(AG903_DSPMgrHandle *handle)
{
	int32_t rc = AG903_ENONE;
	uint8_t ch;					/* 画面番号 */

	if (handle == NULL)
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		rc = AG903_DSPMgrCheckStopped(handle);
	}

	if (rc == AG903_ENONE) {
		AG903_DSPMgrIntStat stat;
		AG903_DSPMgrGetIntStat(handle, &stat);
		stat.clr_vt_blank	= stat.int_vt_blank;
		stat.clr_hrz_line	= stat.int_hrz_line;
		stat.clr_dspoff		= stat.int_dspoff;
		rc = AG903_DSPMgrClearIntStat(handle, &stat);
	}

	if (rc == AG903_ENONE) {
		gDSP.lock[ch] = NULL;
	}

	return rc;
}

/**
 * @brief           表示回路ON
 * @param           handle [in] DSPハンドル
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @retval          -AG903_EBUSY 回路動作中
 * @description     表示回路を有効にします.
 */
int32_t AG903_DSPMgrEnable(AG903_DSPMgrHandle *handle)
{
	int32_t rc = AG903_ENONE;
	uint8_t ch;					/* 画面番号 */

	if (handle == NULL)
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		uint32_t dspon;
		AG903_DSPPrmGetCTRL(ch, &dspon);
		if (dspon == AG903_DSP_CTRL_OFF) {
			AG903_DSPPrmSetCTRL(ch, AG903_DSP_CTRL_ON);
		} else {
			rc = -AG903_EBUSY;
		}
	}

	return rc;
}

/**
 * @brief           表示回路OFF
 * @param           handle [in] DSPハンドル
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     表示回路を無効にします.
 */
int32_t AG903_DSPMgrDisable(AG903_DSPMgrHandle *handle)
{
	int32_t rc = AG903_ENONE;
	uint8_t ch;				/* 画面番号 */

	if (handle == NULL)
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		AG903_DSPPrmSetCTRL(ch, false);
	}

	return rc;
}

/**
 * @brief           表示回路パラメータ取得
 * @param           handle [in] DSPハンドル
 * @param           param [in] 表示回路パラメータ
 * @return          エラーコード
 * @retval          AG903_ENONE  正常終了
 * @retval          -AG903_EINVAL  パラメータ異常
 * @description     設定されている表示回路パラメータを取得します.
 */
int32_t AG903_DSPMgrGetCtrlParam(AG903_DSPMgrHandle *handle, AG903_DSPMgrCtrlParam *param)
{
	int32_t			rc = AG903_ENONE;
	uint8_t			ch;				/* 画面番号 */

	if ((handle == NULL) || (param == NULL))
		return -AG903_EINVAL;
	if (param->syncparam == NULL)
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		DSPPrmParamMOD mod;
		DSPPrmParamSYNC sync;
		DSPPrmParamVTPRM0 vtprm0;

		AG903_DSPPrmGetMOD(ch, &mod);
		AG903_DSPPrmGetSYNC(ch, &sync);
		AG903_DSPPrmGetVTPRM0(ch, &vtprm0);

		param->ip_sel = mod.ip;
		AG903_DSPPrmGetFRMSIZE(ch,
							   &param->vt_framesize,
							   &param->hrz_framesize);

		param->syncparam->rgbde_sel				 = mod.de;
		param->syncparam->vsync_polarity		 = sync.vp;
		param->syncparam->field_hsync_polarity	 = sync.fp;
		param->syncparam->vt_pulsewidth			 = vtprm0.vpw;
		param->syncparam->odd_frontporch_plus1	 = vtprm0.ofp;
		param->syncparam->odd_backporch_plus1	 = vtprm0.obp;
		param->syncparam->even_frontporch_plus1	 = vtprm0.efp;
		param->syncparam->even_backporch_plus1	 = vtprm0.ebp;
		AG903_DSPPrmGetHRZPRM0(ch, &param->syncparam->hrz_pulsewidth);
		AG903_DSPPrmGetHRZPRM1(ch,
							   &param->syncparam->hrz_frontporch,
							   &param->syncparam->hrz_backporch);
		AG903_DSPPrmGetVTPRM1(ch,
							  &param->syncparam->vt_frontporch,
							  &param->syncparam->vt_backporch);
	}

	return rc;
}

/**
 * @brief           ウィンドウパラメータ設定
 * @param           handle [in] DSPハンドル
 * @param           param [in] ウィンドウパラメータ
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常, 境界条件違反
 * @retval          -AG903_EBUSY 表示回路動作中
 * @retval          -AG903_ECHRNG 最大ウィンドウ数超過
 * @description     ウィンドウパラメータの設定を変更します.
 * @note            表示回路動作中には設定できません.
 * @note            ウィンドウアトリビュートリストは8Byte境界に配置する必要があります.
 * @note            ウィンドウアトリビュートリストの領域のメモリ属性はキャッシュ不可として下さい.
 * @note            ウィンドウアトリビュートリストのウインドウ数の値が不正でエラーになった場合は関連するパラメターも含めて確認してください。
 * @note            リリースビルド等でPrimitive層をNDEBUGを定義してコンパイルしている場合、ウィンドウアトリビュートリストの値の妥当性はチェックされません。
 */
int32_t AG903_DSPMgrSetWindowParam(AG903_DSPMgrHandle *handle, AG903_DSPMgrWindowParam *param)
{
	int32_t rc = AG903_ENONE;
	uint8_t ch;					/* 画面番号 */

	if ((handle == NULL) || (param == NULL))
		return -AG903_EINVAL;
	if (param->window_attr_base & ~0xFFFFFFF8)
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		rc = AG903_DSPMgrCheckStopped(handle);
	}

	if (rc == AG903_ENONE) {
		DSPPrmParamMOD mod;
		uint32_t act, conf;

		AG903_DSPPrmGetMOD(ch, &mod);
		mod.upd = param->update_timing;
		AG903_DSPPrmSetMOD(ch, &mod);

		AG903_DSPPrmSetBGCOL(ch, param->background);			/* ウィンドウ背景色設定 */
		AG903_DSPPrmSetWINNUM(ch, param->num_config);			/* ウィンドウ数設定 */
		AG903_DSPPrmSetWATNUM(ch, param->num_attr);				/* アトリビュート個数指定 */
		AG903_DSPPrmSetWATBASE(ch, param->window_attr_base);	/* アトリビュートアドレス設定 */
		AG903_DSPPrmSetLSTCTRL(ch,
							   param->palette_update,			/* パレット更新設定 */
							   param->window_attr_update);		/* ウィンドウアトリビュート更新設定 */
		AG903_DSPPrmGetWINNUM(ch, &act, &conf);					/* ウィンドウ数確認 */
		if (param->num_config != act) {
			rc = -AG903_ECHRNG;
		}
	}

	return rc;
}

/**
 * @brief           アトリビュートリスト変更
 * @param           handle [in] DSPハンドル
 * @param           param [in] ウィンドウパラメータ
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     ウィンドウアトリビュートリストの設定を変更します.
 * @note            ウィンドウアトリビュートリストは8Byte境界に配置する必要があります.
 * @note            ウィンドウアトリビュートリストの領域のメモリ属性はキャッシュ不可として下さい.
 */
int32_t AG903_DSPMgrSetAttributeList(AG903_DSPMgrHandle *handle, AG903_DSPMgrWindowParam *param)
{
	int32_t			rc = AG903_ENONE;
	uint8_t			ch;								/* 画面番号 */

	if ((handle == NULL) || (param == NULL))
		return -AG903_EINVAL;
	if (param->window_attr_base & ~0xFFFFFFF8)
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		AG903_DSPPrmSetWATNUM(ch, param->num_attr);
		AG903_DSPPrmSetWATBASE(ch, param->window_attr_base);
	}

	return rc;
}

/**
 * @brief           割り込み設定
 * @param           handle [in] DSPハンドル
 * @param           param [in] 割込みパラメータ
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @retval          -AG903_EBUSY 表示回路動作中
 * @description     表示割り込みの設定を変更します.
 * @note            ウィンドウアトリビュートリストは8Byte境界に配置する必要があります.
 */
int32_t AG903_DSPMgrSetIntParam(AG903_DSPMgrHandle *handle, AG903_DSPMgrIntParam *param)
{
	int32_t rc = AG903_ENONE;
	uint8_t ch;					/* 画面番号 */

	if ((handle == NULL) || (param == NULL))
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		rc = AG903_DSPMgrCheckStopped(handle);
	}

	if (rc == AG903_ENONE) {
		DSPPrmParamMOD mod;
		AG903_DSPPrmGetMOD(ch, &mod);
		mod.bmr = param->bmureq_timing;
		AG903_DSPPrmSetMOD(ch, &mod);

		DSPPrmParamINT intprm = {
			.line  = param->int_line_no,
			.fcnt  = param->int_framecount,
			.hline = param->int_hrz_line,
			.vblk  = param->int_vt_blank,
		};
		AG903_DSPPrmSetINT(ch, &intprm);

		DSPPrmParamINTMASK intmask = {
			.vblk  = param->mask_vt_blank,
			.hline = param->mask_hrz_line,
			.doff  = param->mask_dspoff,
			.err   = param->mask_error,
		};
		AG903_DSPPrmSetINTMASK(ch, &intmask);

		AG903_DSPPrmSetTRIGGER(ch,
							   param->trigger_out,
							   param->trigger_hrz,
							   param->trigger_vt);
	}

	return rc;
}

/**
 * @brief           割り込みマスク設定
 * @param           handle [in] DSPハンドル
 * @param           param [in] 割込みパラメータ
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     表示割り込みマスク設定を変更します.
 * @description     paramの次のメンバをすべて設定して下さい.
 *                  * mask_vt_blank
 *                  * mask_hrz_line
 *                  * mask_dspoff
 *                  * mask_error
 */
int32_t AG903_DSPMgrSetIntMask(AG903_DSPMgrHandle *handle, AG903_DSPMgrIntParam *param)
{
	int32_t rc = AG903_ENONE;
	uint8_t ch;					/* 画面番号 */

	if ((handle == NULL) || (param == NULL))
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		DSPPrmParamINTMASK intmask = {
			.vblk  = param->mask_vt_blank,
			.hline = param->mask_hrz_line,
			.doff  = param->mask_dspoff,
			.err   = param->mask_error,
		};
		AG903_DSPPrmSetINTMASK(ch, &intmask);
	}

	return rc;
}

/**
 * @brief           割込み状態取得
 * @param           handle [in] DSPハンドル
 * @param           stat [in] 割込み状態
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     表示割り込みの状態を取得します.
 */
int32_t AG903_DSPMgrGetIntStat(AG903_DSPMgrHandle *handle, AG903_DSPMgrIntStat *stat)
{
	int32_t rc = AG903_ENONE;
	uint8_t ch;					/* 画面番号 */

	if ((handle == NULL) || (stat == NULL))
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		DSPPrmParamINTSTAT intstat;
		AG903_DSPPrmGetINTSTAT(ch, &intstat);
		stat->int_vt_blank = intstat.vblk;			/** 垂直ブランク割込み状態 */
		stat->int_hrz_line = intstat.hline;			/** ライン割込み状態 */
		stat->int_dspoff   = intstat.doff;			/** 表示回路停止割り込み状態 */
		stat->dreq         = intstat.dreq;			/** DMAリクエスト状態 */
	}

	return rc;
}

/**
 * @brief           割り込み要因クリア
 * @param           handle [in] DSPハンドル
 * @param           stat [in] 割込み状態
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     表示割り込み要因をクリアします.
 * @note            第二引数statのクリア関連メンバに従ってクリアします.
 * @note            この関数は非タスクコンテキストから実行することができます.
 */
int32_t AG903_DSPMgrClearIntStat(AG903_DSPMgrHandle *handle, AG903_DSPMgrIntStat *stat)
{
	int32_t rc = AG903_ENONE;
	uint8_t ch;					/* 画面番号 */

	if ((handle == NULL) || (stat == NULL))
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		AG903_DSPPrmSetINTCLR(ch,
							  stat->clr_vt_blank,
							  stat->clr_hrz_line,
							  stat->clr_dspoff);
	}

	return rc;
}

/**
 * @brief           回路動作状態取得
 * @param           handle [in] DSPハンドル
 * @param           stat [out] 回路状態
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     表示回路の動作状態を取得します.
 * @description     statの次のメンバが取得されます.
 *                  * work_line
 *                  * vt_status
 *                  * framecount
 *                  * work_pix
 *                  * hrz_status
 */
int32_t AG903_DSPMgrGetStat(AG903_DSPMgrHandle *handle, AG903_DSPMgrStat *stat)
{
	int32_t rc = AG903_ENONE;
	uint8_t ch;					/* 画面番号 */

	if ((handle == NULL) || (stat == NULL))
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		DSPPrmParamERRSTAT errstat;
		AG903_DSPPrmGetERRSTAT(ch, &errstat);
		stat->err_line = errstat.line;
		stat->err_ue = errstat.ue;
		stat->err_le = errstat.le;
		stat->err_pe = errstat.pe;
		AG903_DSPPrmGetVTSTAT(ch, &stat->work_line, &stat->vt_status, &stat->frameconut);
		AG903_DSPPrmGetHRZSTAT(ch, &stat->work_pix, &stat->hrz_status);

		uint32_t state;
		AG903_VODPrmGetSTAT(ch, &state);
		if (state == 0)
			stat->ctrl_status = AG903_DSP_CTRL_OFF;
		else
			stat->ctrl_status = AG903_DSP_CTRL_ON;
	}

	return rc;
}

/**
 * @brief           回路エラー状態クリア
 * @param           handle [in] DSPハンドル
 * @param           stat [out] 回路状態
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     各エラー要因をクリアします.
 * @description     statの次のメンバをすべて設定して下さい.
 *                  * errclr_line
 *                  * errclr_ue
 *                  * errclr_le
 *                  * errclr_pe
 */
int32_t AG903_DSPMgrClearStat(AG903_DSPMgrHandle *handle, AG903_DSPMgrStat *stat)
{
	int32_t rc = AG903_ENONE;
	uint8_t ch;					/* 画面番号 */

	if ((handle == NULL) || (stat == NULL))
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		DSPPrmParamERRCLR errclr;
		errclr.line = stat->errclr_line;
		errclr.ue = stat->errclr_ue;
		errclr.le = stat->errclr_le;
		errclr.pe = stat->errclr_pe;
		AG903_DSPPrmSetERRCLR(ch, &errclr);
	}

	return rc;
}

/**
 * @brief           ウィンドウアトリビュートの変更開始
 * @param           handle [in] DSPハンドル
 * @param           listno [in] アトリビュートリスト番号
 * @param           attr [out] ウィンドウアトリビュート格納バッファ
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EBUSY ウィドウアトリビュート使用中
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     指定されたリスト番号のウィンドウアトリビュートの変更を開始します.
 * @description     取得したポインタに対してウインドウアトリビュートを変更して下さい.
 * @note            AG903_DSPMgrSetAttributeと対で使用して下さい.
 * @note            変更中に新たに変更開始することはできません.
 */
int32_t AG903_DSPMgrGetAttribute(AG903_DSPMgrHandle *handle, uint8_t listno, AG903_DSPMgrWinAttribute **attr)
{
	int32_t				rc = AG903_ENONE;
	uint32_t			addr;						/* アトリビュートベースアドレス */
	uint8_t				ch;							/* 画面番号 */
	uint32_t			watnum;						/* アトリビュート数 */

	if ((handle == NULL) || (attr == NULL))
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		AG903_DSPPrmGetWATNUM(ch, &watnum);

		if (listno >= watnum) {
			rc = -AG903_EINVAL;
		}
	}

	if (rc == AG903_ENONE) {
		if (gDSP.ch[ch].lock[listno] != NULL) {
			rc = -AG903_EBUSY;
		}
	}

	if (rc == AG903_ENONE) {
		AG903_DSPPrmGetWATBASE(ch, &addr);
		(*attr) = ((AG903_DSPMgrWinAttribute *)addr + listno);
		gDSP.ch[ch].lock[listno] = (uint32_t *)(*attr);
	}

	return rc;
}

/**
 * @brief           ウィンドウアトリビュートの変更終了
 * @param           handle [in] DSPハンドル
 * @param           listno [in] アトリビュートリスト番号
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     指定されたリスト番号のウィンドウアトリビュートの変更を終了します.
 * @note            AG903_DSPMgrGetAttributeと対で使用して下さい.
 */
int32_t AG903_DSPMgrSetAttribute(AG903_DSPMgrHandle *handle, uint8_t listno)
{
	int32_t  rc = AG903_ENONE;
	uint8_t  ch;				/* 画面番号 */
	uint32_t watnum;			/* アトリビュート数 */

	if (handle == NULL)
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		AG903_DSPPrmGetWATNUM(ch, &watnum);

		if ((listno >= watnum)
			||  (gDSP.ch[ch].lock[listno] == NULL)) {
			rc = -AG903_EINVAL;
		}
	}

	if (rc == AG903_ENONE) {
		gDSP.ch[ch].lock[listno] = NULL;
	}

	return rc;
}

/**
 * @brief           外部同期パラメータ設定
 * @param           handle [in] DSPハンドル
 * @param           param [in] 外部同期パラメータ
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @retval          -AG903_EBUSY 表示回路動作中
 * @description     外部同期パラメータの設定を変更します.
 * @note            表示回路動作中には設定できません.
 */
int32_t AG903_DSPMgrSetExSyncParam(AG903_DSPMgrHandle *handle, AG903_DSPMgrExSyncParam *param)
{
	int32_t rc = AG903_ENONE;
	uint8_t ch;					/* 画面番号 */

	if ((handle == NULL) || (param == NULL))
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		rc = AG903_DSPMgrCheckStopped(handle);
	}

	if (rc == AG903_ENONE) {
		DSPPrmParamSYNC sync;
		sync.sel = param->sync_sel;
		sync.dly = param->delay_ctrl_en;
		sync.ip = param->ip_sel;
		sync.vp = param->vsync_polarity;
		sync.fp = param->field_hsync_polarity;
		sync.msk = param->sync_mask_en;
		AG903_DSPPrmSetSYNC(ch, &sync); /* 外部同期パラメータ設定 */
	}

	return rc;
}

/**
 * @brief           色補正パラメータ設定
 * @param           handle [in] DSPハンドル
 * @param           en [in] 機能有効化
 * @param           param [in] 色補正パラメータ
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     色補正パラメータの設定を変更します.
 * @note            第三引数paramにNULLを渡した場合、有効化設定のみを変更します.
 */
int32_t AG903_DSPMgrSetLutParam(AG903_DSPMgrHandle *handle, _Bool en, AG903_DSPMgrLutParam *param)
{
	int32_t  rc = AG903_ENONE;
	uint8_t  ch;				/* 画面番号 */
	uint32_t cnt;
	DSPPrmParamMOD mod;

	if (handle == NULL)
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		if (param != NULL) {
			DSPPrmParamLUTR lutr = {0};
			DSPPrmParamLUTG lutg = {0};
			DSPPrmParamLUTB lutb = {0};
			for (cnt = 0;cnt < AG903_DSP_LUT_NUM;cnt++) {
				lutr.r0 = param->LUTR[cnt].r0;
				lutr.r1 = param->LUTR[cnt].r1;
				lutr.r2 = param->LUTR[cnt].r2;
				lutr.r3 = param->LUTR[cnt].r3;
				lutg.g0 = param->LUTG[cnt].g0;
				lutg.g1 = param->LUTG[cnt].g1;
				lutg.g2 = param->LUTG[cnt].g2;
				lutg.g3 = param->LUTG[cnt].g3;
				lutb.b0 = param->LUTB[cnt].b0;
				lutb.b1 = param->LUTB[cnt].b1;
				lutb.b2 = param->LUTB[cnt].b2;
				lutb.b3 = param->LUTB[cnt].b3;
				AG903_DSPPrmSetLUTR(ch, cnt, &lutr);
				AG903_DSPPrmSetLUTG(ch, cnt, &lutg);
				AG903_DSPPrmSetLUTB(ch, cnt, &lutb);
			}
		}
		AG903_DSPPrmGetMOD(ch, &mod);
		mod.lut = en ? true : false;
		AG903_DSPPrmSetMOD(ch, &mod);
	}

	return rc;
}

/**
 * @brief           減色パラメータ設定
 * @param           handle [in] DSPハンドル
 * @param           en [in] 機能有効化
 * @param           param [in] 減色パラメータ
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     減色パラメータの設定を変更します.
 * @note            第三引数paramにNULLを渡した場合、有効化設定のみを変更します.
 */
int32_t AG903_DSPMgrSetDithParam(AG903_DSPMgrHandle *handle, _Bool en, AG903_DSPMgrDithParam *param)
{
	int32_t			rc = AG903_ENONE;
	uint8_t			ch;								/* 画面番号 */
	DSPPrmParamMOD	mod;

	if (handle == NULL)
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		if (param != NULL) {
			AG903_DSPPrmSetDITHAREA0A(ch, param->DITHAREA[0].x0, param->DITHAREA[0].y0);
			AG903_DSPPrmSetDITHAREA0B(ch, param->DITHAREA[0].x1, param->DITHAREA[0].y1);
			AG903_DSPPrmSetDITHAREA1A(ch, param->DITHAREA[1].x0, param->DITHAREA[1].y0);
			AG903_DSPPrmSetDITHAREA1B(ch, param->DITHAREA[1].x1, param->DITHAREA[1].y1);
			AG903_DSPPrmSetDITHAREA2A(ch, param->DITHAREA[2].x0, param->DITHAREA[2].y0);
			AG903_DSPPrmSetDITHAREA2B(ch, param->DITHAREA[2].x1, param->DITHAREA[2].y1);
			AG903_DSPPrmSetDITHAREA3A(ch, param->DITHAREA[3].x0, param->DITHAREA[3].y0);
			AG903_DSPPrmSetDITHAREA3B(ch, param->DITHAREA[3].x1, param->DITHAREA[3].y1);
		}
		AG903_DSPPrmGetMOD(ch, &mod);
		mod.dith = en ? true : false;
		AG903_DSPPrmSetMOD(ch, &mod);
	}

	return rc;
}

/**
 * @brief           色検出パラメータ設定
 * @param           handle [in] DSPハンドル
 * @param           param [in] 色検出パラメータ
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     色検出パラメータの設定を変更します.
 * @note            第三引数paramにNULLを渡した場合、色検出比較を全て無効に設定します.
 */
int32_t AG903_DSPMgrSetCDParam(AG903_DSPMgrHandle *handle, AG903_DSPMgrCDParam *param)
{
	int32_t			rc = AG903_ENONE;
	uint8_t			ch;								/* 画面番号 */

	if (handle == NULL)
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		DSPPrmParamCOLDET coldet;
		DSPPrmParamCDCTRL cdctrl;
		if (param == NULL) {
			AG903_DSPPrmGetCDCTRL(ch, &cdctrl);
			cdctrl.be = false;
			cdctrl.ge = false;
			cdctrl.re = false;
			cdctrl.ae = false;
			AG903_DSPPrmSetCDCTRL(ch, &cdctrl);
		} else {
			cdctrl.be = param->colordetect_en_b;
			cdctrl.ge = param->colordetect_en_g;
			cdctrl.re = param->colordetect_en_r;
			cdctrl.ae = param->colordetect_en_a;
			coldet.b  = param->colordetect_color_b;
			coldet.g  = param->colordetect_color_g;
			coldet.r  = param->colordetect_color_r;
			coldet.a  = param->colordetect_color_a;
			AG903_DSPPrmSetCOLDET(ch, &coldet); /* 色検出比較値設定 */
			AG903_DSPPrmSetCDCTRL(ch, &cdctrl); /* 色検出有効設定 */
		}
	}

	return rc;
}

/**
 * @brief           DMAリクエスト設定
 * @param           handle [in] DSPハンドル
 * @param           req [in] DMAリクエストタイミング
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     DMAリクエストの設定を変更します.
 */
int32_t AG903_DSPMgrSetDMAReq(AG903_DSPMgrHandle *handle, uint8_t req)
{
	int32_t rc = AG903_ENONE;
	uint8_t ch;					/* 画面番号 */

	if (handle == NULL)
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		AG903_DSPPrmSetDMAREQ(ch, req);
	}

	return rc;
}

/**
 * @brief           CMOS出力パラメータ設定
 * @param           handle [in] DSPハンドル
 * @param           ctrl [in] 表示回路パラメータ
 * @param           param [in] CMOS出力パラメータ
 * @return          エラーコード
 * @retval          AG903_ENONE  正常終了
 * @retval          -AG903_EINVAL  パラメータ異常
 * @retval          -AG903_EILLEGAL ドットクロック用PLL未設定
 * @description     CMOS出力パラメータの設定を変更します.
 */
int32_t AG903_DSPMgrSetCMOSParam(AG903_DSPMgrHandle *handle, AG903_DSPMgrCtrlParam *ctrl, AG903_DSPMgrCMOSParam *param)
{
	int32_t				rc = AG903_ENONE;
	uint8_t				ch;							/* 画面番号 */

	if ((handle == NULL) || (ctrl == NULL) || (param == NULL))
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		rc = AG903_DSPMgrCheckStopped(handle);
	}

	if (rc == AG903_ENONE) {
		DSPPrmParamMOD mod;
		DSPPrmParamSYNC sync;
		DSPPrmParamVTPRM0 vtprm0;

		AG903_DSPPrmGetMOD(ch, &mod);
		if (NULL != ctrl->syncparam) {
			mod.de   = ctrl->syncparam->rgbde_sel;
		}
		mod.ip   = ctrl->ip_sel;
		AG903_DSPPrmSetMOD(ch, &mod);

		if (NULL != ctrl->syncparam) {
			AG903_DSPPrmGetSYNC(ch, &sync);
			sync.vp = ctrl->syncparam->vsync_polarity;
			sync.fp = ctrl->syncparam->field_hsync_polarity;
			AG903_DSPPrmSetSYNC(ch, &sync);

			vtprm0.vpw = ctrl->syncparam->vt_pulsewidth;
			vtprm0.ofp = ctrl->syncparam->odd_frontporch_plus1;
			vtprm0.obp = ctrl->syncparam->odd_backporch_plus1;
			vtprm0.efp = ctrl->syncparam->even_frontporch_plus1;
			vtprm0.ebp = ctrl->syncparam->even_backporch_plus1;
			AG903_DSPPrmSetVTPRM0(ch, &vtprm0);

			AG903_DSPPrmSetHRZPRM0(ch, ctrl->syncparam->hrz_pulsewidth);
			AG903_DSPPrmSetHRZPRM1(ch, ctrl->syncparam->hrz_frontporch,
								   ctrl->syncparam->hrz_backporch);
			AG903_DSPPrmSetVTPRM1(ch, ctrl->syncparam->vt_frontporch,
								  ctrl->syncparam->vt_backporch);
		}
		AG903_DSPPrmSetFRMSIZE(ch, ctrl->vt_framesize, ctrl->hrz_framesize);

		if (rc == AG903_ENONE) {
			VODPrmParamMOD mod;
			AG903_VODPrmGetMOD(ch, &mod);
			mod.dp   = param->rgbde_polarity;
			mod.vp   = param->vsync_polarity;
			mod.hp   = param->hsync_polarity;
			mod.fp   = param->field_polarity;
			mod.cdp  = param->colordetect_polarity;
			mod.dex  = param->rgbde_en ? AG903_DSP_SIGNAL_ENABLE : AG903_DSP_SIGNAL_DISABLE;
			mod.vex  = param->vsync_en ? AG903_DSP_SIGNAL_ENABLE : AG903_DSP_SIGNAL_DISABLE;
			mod.hex  = param->hsync_en ? AG903_DSP_SIGNAL_ENABLE : AG903_DSP_SIGNAL_DISABLE;
			mod.fex  = param->field_en ? AG903_DSP_SIGNAL_ENABLE : AG903_DSP_SIGNAL_DISABLE;
			mod.cdex = param->colordetect_en ? AG903_DSP_SIGNAL_ENABLE : AG903_DSP_SIGNAL_DISABLE;
			mod.pex  = param->pixeldata_en ? AG903_DSP_SIGNAL_ENABLE : AG903_DSP_SIGNAL_DISABLE;
			mod.cp   = param->dotclk_polarity;
			mod.code = param->code_en;
			mod.yuv  = param->yuv_mode;
			AG903_VODPrmSetMOD(ch, &mod);
		}
	}

	return rc;
}

/**
 * @brief           LVDS出力パラメータ設定
 * @param           handle [in] DSPハンドル
 * @param           ctrl [in] 表示回路パラメータ
 * @param           param [in] LVDS出力パラメータ
 * @return          エラーコード
 * @retval          AG903_ENONE  正常終了
 * @retval          -AG903_EINVAL  パラメータ異常
 * @retval          -AG903_EILLEGAL ドットクロック用PLL未設定
 * @description     LVDS出力パラメータの設定を変更します.
 * @note            LVDSデュアルリンクの場合はCh1のハンドラを取得しそれに対して設定して下さい.
 */
int32_t AG903_DSPMgrSetLVDSParam(AG903_DSPMgrHandle *handle, AG903_DSPMgrCtrlParam *ctrl, AG903_DSPMgrLVDSParam *param)
{
	int32_t				rc = AG903_ENONE;
	uint8_t				ch;							/* 画面番号 */

	if ((handle == NULL) || (ctrl == NULL) || (param == NULL))
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		rc = AG903_DSPMgrCheckStopped(handle);
	}

	if (rc == AG903_ENONE) {
		DSPPrmParamMOD mod;
		DSPPrmParamSYNC sync;
		DSPPrmParamVTPRM0 vtprm0;

		AG903_DSPPrmGetMOD(ch, &mod);
		if (NULL != ctrl->syncparam) {
			mod.de   = ctrl->syncparam->rgbde_sel;
		}
		mod.ip   = ctrl->ip_sel;
		AG903_DSPPrmSetMOD(ch, &mod);

		if (NULL != ctrl->syncparam) {
			AG903_DSPPrmGetSYNC(ch, &sync);
			sync.vp = ctrl->syncparam->vsync_polarity;
			sync.fp = ctrl->syncparam->field_hsync_polarity;
			AG903_DSPPrmSetSYNC(ch, &sync);

			vtprm0.vpw = ctrl->syncparam->vt_pulsewidth;
			vtprm0.ofp = ctrl->syncparam->odd_frontporch_plus1;
			vtprm0.obp = ctrl->syncparam->odd_backporch_plus1;
			vtprm0.efp = ctrl->syncparam->even_frontporch_plus1;
			vtprm0.ebp = ctrl->syncparam->even_backporch_plus1;
			AG903_DSPPrmSetVTPRM0(ch, &vtprm0);

			AG903_DSPPrmSetHRZPRM0(ch, ctrl->syncparam->hrz_pulsewidth);
			AG903_DSPPrmSetHRZPRM1(ch, ctrl->syncparam->hrz_frontporch,
								   ctrl->syncparam->hrz_backporch);
			AG903_DSPPrmSetVTPRM1(ch, ctrl->syncparam->vt_frontporch,
								  ctrl->syncparam->vt_backporch);
		}
		AG903_DSPPrmSetFRMSIZE(ch, ctrl->vt_framesize, ctrl->hrz_framesize);
	}

	if (rc == AG903_ENONE) {
		VODPrmParamMOD mod;
		uint32_t portsel;
		AG903_VODPrmGetMOD(ch, &mod);
		mod.dp   = param->rgbde_polarity;
		mod.vp   = param->vsync_polarity;
		mod.hp   = param->hsync_polarity;
		mod.fp   = param->field_polarity;
		mod.cdp  = param->colordetect_polarity;
		mod.dex  = param->rgbde_en ? AG903_DSP_SIGNAL_ENABLE : AG903_DSP_SIGNAL_DISABLE;
		mod.vex  = param->vsync_en ? AG903_DSP_SIGNAL_ENABLE : AG903_DSP_SIGNAL_DISABLE;
		mod.hex  = param->hsync_en ? AG903_DSP_SIGNAL_ENABLE : AG903_DSP_SIGNAL_DISABLE;
		mod.fex  = param->field_en ? AG903_DSP_SIGNAL_ENABLE : AG903_DSP_SIGNAL_DISABLE;
		mod.cdex = param->colordetect_en ? AG903_DSP_SIGNAL_ENABLE : AG903_DSP_SIGNAL_DISABLE;
		mod.pex  = param->pixeldata_en ? AG903_DSP_SIGNAL_ENABLE : AG903_DSP_SIGNAL_DISABLE;
		mod.fmt  = param->format;
		mod.ct0  = param->ctrl0;
		mod.ct1  = param->ctrl1;
		AG903_VODPrmSetMOD(ch, &mod);
		AG903_VODPrmGetPORTSEL(1, &portsel);
		if (portsel == 0 || ch == 0) {
			AG903_VODPrmSetMACRO0(param->freq_range,
								  param->auto_powermanage,
								  param->macro_power);
		}
		if (ch == 1) {
			AG903_VODPrmSetMACRO1(param->freq_range,
								  param->auto_powermanage,
								  param->macro_power);
		}
	}

	return rc;
}

/**
 * @brief           バックライトパラメータ取得
 * @param           handle [in] DSPハンドル
 * @param           param [out] バックライトパラメータ
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     バックライト制御パラメータの設定を取得します.
 */
int32_t AG903_DSPMgrGetBPwrModeParam(AG903_DSPMgrHandle *handle, AG903_DSPMgrBPwrModeParam *param)
{
	int32_t			rc = AG903_ENONE;
	uint8_t			ch;								/* 画面番号 */

	if ((handle == NULL) || (param == NULL)) {
		rc = -AG903_EINVAL;
	}

	if (rc == AG903_ENONE) {
		rc = DSPMgrCheckHandle(handle, &ch);
	}

	if (rc == AG903_ENONE) {
		AG903_VODPrmGetBPWRMOD(ch, &param->backlight_en, &param->cnt_unit);
		AG903_VODPrmGetPPWRONCNT(ch, &param->panel_pwroncnt);
		AG903_VODPrmGetBPWRONCNT(ch, &param->backlight_pwroncnt);
		AG903_VODPrmGetBLGTONCNT(ch, &param->backlight_oncnt);
		AG903_VODPrmGetPPWROFFCNT(ch, &param->panel_pwroffcnt);
		AG903_VODPrmGetBPWROFFCNT(ch, &param->backlight_pwroffcnt);
		AG903_VODPrmGetBLGTOFFCNT(ch, &param->backlight_offcnt);
		AG903_VODPrmGetPWMPERIOD(ch, &param->pwm_period);
		AG903_VODPrmGetPWMCNT(ch, &param->pwm_cnt);
	}

	return rc;
}

/**
 * @brief           バックライトパラメータ設定
 * @param           handle [in] DSPハンドル
 * @param           param [in] バックライトパラメータ
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     バックライト制御パラメータの設定を変更します.
 */
int32_t AG903_DSPMgrSetBPwrModeParam(AG903_DSPMgrHandle *handle, AG903_DSPMgrBPwrModeParam *param)
{
	int32_t			rc = AG903_ENONE;
	uint8_t			ch;								/* 画面番号 */

	if ((handle == NULL) || (param == NULL)) {
		rc = -AG903_EINVAL;
	}

	if (rc == AG903_ENONE) {
		rc = DSPMgrCheckHandle(handle, &ch);
	}

	if (rc == AG903_ENONE) {
		AG903_VODPrmSetBPWRMOD(ch, param->backlight_en, param->cnt_unit);
		AG903_VODPrmSetPPWRONCNT(ch, param->panel_pwroncnt);
		AG903_VODPrmSetBPWRONCNT(ch, param->backlight_pwroncnt);
		AG903_VODPrmSetBLGTONCNT(ch, param->backlight_oncnt);
		AG903_VODPrmSetPPWROFFCNT(ch, param->panel_pwroffcnt);
		AG903_VODPrmSetBPWROFFCNT(ch, param->backlight_pwroffcnt);
		AG903_VODPrmSetBLGTOFFCNT(ch, param->backlight_offcnt);
		AG903_VODPrmSetPWMPERIOD(ch, param->pwm_period);
		AG903_VODPrmSetPWMCNT(ch, param->pwm_cnt);
	}

	return rc;
}

/**
 * @brief           画面出力状態取得
 * @param           handle [in] DSPハンドル
 * @param           stat [out] 画面出力状態<
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     画面出力の動作状態を取得します.
 */
int32_t AG903_DSPMgrGetVODStat(AG903_DSPMgrHandle *handle, uint32_t *stat)
{
	int32_t rc = AG903_ENONE;
	uint8_t ch;					/* 画面番号 */

	if ((handle == NULL) || (stat == NULL))
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		AG903_VODPrmGetSTAT(ch, stat);				/* 画面出力状態取得 */
	}

	return rc;
}

/**
 * @brief           画面出力ポート設定取得
 * @param           handle [in] DSPハンドル
 * @param           sel [out] 画面出力先
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @description     設定されている画面出力ポートを取得します.
 */
int32_t AG903_DSPMgrGetPortSel(AG903_DSPMgrHandle *handle, uint8_t *sel)
{
	int32_t  rc = AG903_ENONE;
	uint8_t  ch;					/* 画面番号 */
	uint32_t portsel;

	if ((handle == NULL) || (sel == NULL))
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		AG903_VODPrmGetPORTSEL(ch, &portsel);
		*sel = portsel & 0xFF;
	}

	return rc;
}

/**
 * @brief           画面出力ポート設定
 * @param           handle [in] DSPハンドル
 * @param           sel [in] 画面出力先
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @description     画面出力ポートの設定を変更します.
 */
int32_t AG903_DSPMgrSetPortSel(AG903_DSPMgrHandle *handle, uint8_t sel)
{
	int32_t  rc = AG903_ENONE;
	uint8_t  ch;					/* 画面番号 */

	if (handle == NULL)
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (ch == 0) {
		if (sel > AG903_VOD0_PORTSEL_LVDS_SINGLE)
			rc = -AG903_EINVAL;
	} else {
		if (sel > AG903_VOD1_PORTSEL_LVDS_SINGLE)
			rc = -AG903_EINVAL;
	}

	if (rc == AG903_ENONE) {
		AG903_VODPrmSetPORTSEL(ch, sel);
	}

	return rc;
}

/**
 * @brief           ハンドルチェック
 * @param           handle [in] DSPハンドル
 * @param           ch  [out] チャンネル番号
 * @return          エラーコード
 * @retval          AG903_ENONE 正常終了
 * @retval          -AG903_EINVAL パラメータ異常
 * @description     ハンドル値、チャンネルの正当性をチェックします.
 */
static int32_t DSPMgrCheckHandle(AG903_DSPMgrHandle *handle, uint8_t *ch)
{
	uint32_t channel = ((uint32_t)handle - (uint32_t)gDSP.ch) / sizeof(DSPChBlock);

	if ((channel >= AG903_DSP_CH_NUM) ||
		(gDSP.lock[channel] != handle)) {
		return -AG903_EINVAL;
	}

	*ch = (uint8_t)channel;

	return AG903_ENONE;
}

/**
 * @brief           表示回路停止完了チェック
 * @param           ch [in] チャンネル(0-1)
 * @return          エラーコード
 * @retval          AG903_ENONE 表示回路停止中
 * @retval          -AG903_EBUSY 表示回路動作中
 * @description     表示回路が停止しているかを判定します.<p>
 *                  バックライト制御の設定などによっては、<p>
 *                  停止設定と実際に回路が停止するタイミングが異なる場合があります.<p>
 *                  表示回路が停止していることを判定するために、本関数を使用してください.
 */
int32_t AG903_DSPMgrCheckStopped(AG903_DSPMgrHandle *handle)
{
	int32_t  rc = AG903_ENONE;
	uint8_t  ch;					/* 画面番号 */
	uint32_t stat;

	if (handle == NULL)
		return -AG903_EINVAL;

	rc = DSPMgrCheckHandle(handle, &ch);

	if (rc == AG903_ENONE) {
		AG903_VODPrmGetSTAT(ch, &stat);
		if (stat != 0)
			rc = -AG903_EBUSY;
	}

	return rc;
}

