diff --git a/configs/beaglebone b/configs/beaglebone index 6cd0be3a..3517725a 100644 --- a/configs/beaglebone +++ b/configs/beaglebone @@ -313,7 +313,7 @@ CONFIG_ARCH_OMAP2PLUS=y # # OMAP Feature Selections # -CONFIG_OMAP_RESET_CLOCKS=y +CONFIG_OMAP_RESET_CLOCKS=n CONFIG_OMAP_MUX=y CONFIG_OMAP_MUX_DEBUG=y CONFIG_OMAP_MUX_WARNINGS=y @@ -3889,3 +3889,4 @@ CONFIG_CLZ_TAB=y # CONFIG_DDR is not set CONFIG_MPILIB=m CONFIG_OID_REGISTRY=m +CONFIG_NXP_TDA998X_OLD=y diff --git a/patch.sh b/patch.sh index 1a1b92cc..75f0a0c9 100755 --- a/patch.sh +++ b/patch.sh @@ -26,7 +26,7 @@ EXTERNAL_SHA="3587b1b097d70c2eb9fee95ea7995d13c05f66e5" #PATCHSET="pruss pwm2 fixes" # BAD: rtc -PATCHSET="dma cpsw pinctrl cpufreq adc pwm i2c usb da8xx-fb mmc fixes f2fs 6lowpan capebus" +PATCHSET="dma cpsw pinctrl cpufreq adc pwm i2c usb da8xx-fb mmc fixes f2fs 6lowpan capebus hdmi" git_kernel_stable () { git pull git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git master --tags || true diff --git a/patches/hdmi/0001-Import-working-HDMI-driver-from-3.2-kernel.patch b/patches/hdmi/0001-Import-working-HDMI-driver-from-3.2-kernel.patch new file mode 100644 index 00000000..171fd946 --- /dev/null +++ b/patches/hdmi/0001-Import-working-HDMI-driver-from-3.2-kernel.patch @@ -0,0 +1,72651 @@ +From 574ab851cb14db876495117c382963913b053a12 Mon Sep 17 00:00:00 2001 +From: Joel A Fernandes +Date: Tue, 13 Nov 2012 11:41:09 -0500 +Subject: [PATCH 1/6] Import working HDMI driver from 3.2 kernel + +Fixes ontop of the original driver: +6a3b828 hdmi: Fix Video port mapping in NXP driver +ac8ac07 Replace entire code with version recommended by NXP, add late_initcall to tda988x.c + +Signed-off-by: Joel A Fernandes +--- + drivers/video/nxp/MakeModules | 59 + + drivers/video/nxp/Makefile | 204 + + .../nxp/comps/tmbslHdmiTx/inc/tmbslHdmiTx_types.h | 1804 +++++ + .../tmbslTDA9989/inc/tmbslHdmiTx_funcMapping.h | 141 + + .../tmbslTDA9989/inc/tmbslTDA9989_Functions.h | 3060 ++++++++ + .../nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid.c | 1572 ++++ + .../comps/tmbslTDA9989/src/tmbslTDA9989_Edid_l.h | 62 + + .../nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP.c | 655 ++ + .../comps/tmbslTDA9989/src/tmbslTDA9989_HDCP_l.h | 72 + + .../comps/tmbslTDA9989/src/tmbslTDA9989_InOut.c | 5101 +++++++++++++ + .../comps/tmbslTDA9989/src/tmbslTDA9989_InOut_l.h | 112 + + .../nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc.c | 2512 +++++++ + .../comps/tmbslTDA9989/src/tmbslTDA9989_Misc_l.h | 62 + + .../comps/tmbslTDA9989/src/tmbslTDA9989_State.c | 240 + + .../comps/tmbslTDA9989/src/tmbslTDA9989_State_l.h | 56 + + .../comps/tmbslTDA9989/src/tmbslTDA9989_local.c | 670 ++ + .../comps/tmbslTDA9989/src/tmbslTDA9989_local.h | 2056 ++++++ + .../tmbslTDA9989/src/tmbslTDA9989_local_otp.h | 54 + + .../nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_IW.h | 305 + + .../nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_Linux.c | 436 ++ + .../nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_cfg.h | 107 + + .../docs/02_sw_req_an/tmdlHdmiCEC_API.zip | Bin 0 -> 148480 bytes + .../docs/14_user_doc/HDMI_CEC_User_Manual.pdf | Bin 0 -> 171295 bytes + .../video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC.h | 46 + + .../comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Functions.h | 3166 ++++++++ + .../nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Types.h | 1083 +++ + .../video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC.c | 7575 ++++++++++++++++++++ + .../nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.c | 280 + + .../nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.h | 221 + + .../tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c | 570 ++ + .../comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_cfg.c | 624 ++ + .../video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_IW.h | 290 + + .../nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_cfg.h | 298 + + .../docs/02_sw_req_an/tmdlHdmiTx_API.zip | Bin 0 -> 131083 bytes + .../TRANSMITTER_TDA998X_SW_UM_Devlib.pdf | Bin 0 -> 610544 bytes + .../video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx.h | 52 + + .../comps/tmdlHdmiTx/inc/tmdlHdmiTx_Functions.h | 1806 +++++ + .../nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h | 1066 +++ + .../video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx.c | 7166 ++++++++++++++++++ + .../nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.c | 342 + + .../nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.h | 702 ++ + drivers/video/nxp/inc/tmFlags.h | 237 + + drivers/video/nxp/inc/tmNxCompId.h | 1743 +++++ + drivers/video/nxp/inc/tmNxTypes.h | 366 + + drivers/video/nxp/linux_hdmi_release_note.txt | 417 ++ + drivers/video/nxp/tda998x.c | 2307 ++++++ + drivers/video/nxp/tda998x.h | 143 + + drivers/video/nxp/tda998x_cec.c | 2157 ++++++ + drivers/video/nxp/tda998x_cec.h | 140 + + drivers/video/nxp/tda998x_ioctl.h | 1123 +++ + drivers/video/nxp/tda998x_version.h | 17 + + drivers/video/nxp/test/Makefile | 28 + + drivers/video/nxp/test/demo_tda.c | 758 ++ + 53 files changed, 54063 insertions(+) + create mode 100755 drivers/video/nxp/MakeModules + create mode 100755 drivers/video/nxp/Makefile + create mode 100755 drivers/video/nxp/comps/tmbslHdmiTx/inc/tmbslHdmiTx_types.h + create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/inc/tmbslHdmiTx_funcMapping.h + create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/inc/tmbslTDA9989_Functions.h + create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid.c + create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid_l.h + create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP.c + create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP_l.h + create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_InOut.c + create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_InOut_l.h + create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc.c + create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc_l.h + create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_State.c + create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_State_l.h + create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local.c + create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local.h + create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local_otp.h + create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_IW.h + create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_Linux.c + create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_cfg.h + create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/docs/02_sw_req_an/tmdlHdmiCEC_API.zip + create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/docs/14_user_doc/HDMI_CEC_User_Manual.pdf + create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC.h + create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Functions.h + create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Types.h + create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC.c + create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.c + create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.h + create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c + create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_cfg.c + create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_IW.h + create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_cfg.h + create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/docs/02_sw_req_an/tmdlHdmiTx_API.zip + create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/docs/14_user_doc/TRANSMITTER_TDA998X_SW_UM_Devlib.pdf + create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx.h + create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Functions.h + create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h + create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx.c + create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.c + create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.h + create mode 100755 drivers/video/nxp/inc/tmFlags.h + create mode 100755 drivers/video/nxp/inc/tmNxCompId.h + create mode 100755 drivers/video/nxp/inc/tmNxTypes.h + create mode 100755 drivers/video/nxp/linux_hdmi_release_note.txt + create mode 100755 drivers/video/nxp/tda998x.c + create mode 100755 drivers/video/nxp/tda998x.h + create mode 100755 drivers/video/nxp/tda998x_cec.c + create mode 100755 drivers/video/nxp/tda998x_cec.h + create mode 100755 drivers/video/nxp/tda998x_ioctl.h + create mode 100755 drivers/video/nxp/tda998x_version.h + create mode 100755 drivers/video/nxp/test/Makefile + create mode 100755 drivers/video/nxp/test/demo_tda.c + +diff --git a/drivers/video/nxp/MakeModules b/drivers/video/nxp/MakeModules +new file mode 100755 +index 0000000..fae8495 +--- /dev/null ++++ b/drivers/video/nxp/MakeModules +@@ -0,0 +1,59 @@ ++PACKAGE_NAME:=hdmi ++ ++RULES:=compile ++ ++ARCH:=arm ++CROSS_COMPILE:=/home/joel/oe-arm-angstrom-linux-gnueabi- ++VARS:= ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) ++# VARS:= V=1 ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) ++ ++# module to be put in driver/video/hdmi ++ ++LINUX_DIR=/home/joel/work/code/kernel/linux-dvi-audio/git/ ++LINUXKERNEL_SRC=$(LINUX_DIR) ++ ++all: $(RULES) ++ ++compile: ++ @echo "\t-----> $(PACKAGE_NAME):$@" ++# @rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.* ++# @mv tda998x_version.h temp && cat temp | awk '$$2~"PATCHLEVEL" {$$3=$$3+1};{print};' >tda998x_version.h && rm temp ++ $(MAKE) -C $(LINUXKERNEL_SRC) M=`pwd` $(VARS) modules ++# @touch $@ ++ ++uptx: ++ adb shell hdmi_off ++ adb shell rm hdmitx.ko ++ adb shell rmmod hdmitx ++ adb push hdmitx.ko hdmitx.ko ++ adb shell insmod hdmitx.ko verbose=1 ++ adb shell hdmi_on ++ ++upcec: ++ adb shell rm hdmicec.ko ++ adb shell rmmod hdmicec ++ adb push hdmicec.ko hdmicec.ko ++ adb shell insmod hdmicec.ko verbose=1 device=4 ++ ++strip: ++ strip -g -I elf32-little hdmitx.ko -o hdmitx_striped.ko ++ strip -g -I elf32-little hdmicec.ko -o hdmicec_striped.ko ++ ++clean: ++ @echo "\t-----> $(PACKAGE_NAME):$@" ++ @rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.* *.symvers *.order ++ @if [ -e comps/tmdlHdmiTx/src ]; then cd comps/tmdlHdmiTx/src && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi ++ @if [ -e comps/tmdlHdmiTx/cfg/TDA9989 ]; then cd comps/tmdlHdmiTx/cfg/TDA9989 && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi ++ @if [ -e comps/tmdlHdmiCEC/src ]; then cd comps/tmdlHdmiCEC/src && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi ++ @if [ -e comps/tmdlHdmiCEC/cfg ]; then cd comps/tmdlHdmiCEC/cfg && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi ++ @if [ -e comps/tmdlTDA9983/src ]; then cd comps/tmdlTDA9983/src && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi ++ @if [ -e comps/tmdlTDA9983/cfg ]; then cd comps/tmdlTDA9983/cfg && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi ++ @if [ -e comps/tmbslTDA9989/src ]; then cd comps/tmbslTDA9989/src && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi ++ @if [ -e comps/tmbslTDA9984NoHdcp/src ]; then cd comps/tmbslTDA9984NoHdcp/src && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi ++ @if [ -e comps/tmbslTDA9983/src ]; then cd comps/tmbslTDA9983/src && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi ++ ++ @if [ -e .compiled ]; then rm .compiled; fi ++ ++# install: .install ++# .install: ++# cp .... +diff --git a/drivers/video/nxp/Makefile b/drivers/video/nxp/Makefile +new file mode 100755 +index 0000000..f583226 +--- /dev/null ++++ b/drivers/video/nxp/Makefile +@@ -0,0 +1,204 @@ ++ ++############### select your chip + platform here ################### ++ ++# TDA_TX := TDA19989 ++TDA_TX := TDA19988 ++# TDA_TX := TDA9984 ++# TDA_TX := TDA9983 ++# TDA_TX := TDA9981 ++ ++TDA_PLATFORM := ZOOMII ++# TDA_PLATFORM := OTHERS ++ ++############### features on demand ################################# ++ ++#TDA_HDCP := 0 ++TDA_HDCP := TMFL_HDCP_SUPPORT ++TDA_CEC := TDA9950 ++ ++# add this if INTERRUPT is wired, otherwise polling with timer is used ++#EXTRA_CFLAGS += -DIRQ ++ ++# add this to get PC video format ++# EXTRA_CFLAGS += -DFORMAT_PC ++ ++# add this to disable automatic set of input/output video resolution ++# EXTRA_CFLAGS += -DUSER_SET_INPUT_OUTPUT ++ ++#################################################################### ++ ++EXTRA_CFLAGS += -DFUNC_PTR=" " -DCONST_DAT="const " -DRAM_DAT=" " ++EXTRA_CFLAGS += -DTDA_NAME=$(TDA_TX) ++EXTRA_CFLAGS += -DTMFL_LINUX_OS_KERNEL_DRIVER ++EXTRA_CFLAGS += -DTMFL_NO_RTOS ++# EXTRA_CFLAGS += -DI2C_DBG ++ ++ifeq ($(TDA_PLATFORM),ZOOMII) ++EXTRA_CFLAGS += -DTMFL_CFG_ZOOMII ++EXTRA_CFLAGS += -DZOOMII_PATCH ++EXTRA_CFLAGS += -DTWL4030_HACK ++# EXTRA_CFLAGS += -DANDROID_DSS ++EXTRA_CFLAGS += -DGUI_OVER_HDMI ++endif ++ ++ifeq ($(TDA_TX),TDA19988) ++EXTRA_CFLAGS += -DTMFL_TDA19988 ++TDA_TX := TDA19989 ++endif ++ ++ifeq ($(TDA_TX),TDA19989) ++EXTRA_CFLAGS += -DTMFL_TDA19989 -DTMFL_TDA9989 ++ifeq ($(TDA_HDCP),TMFL_HDCP_SUPPORT) ++EXTRA_CFLAGS += -D$(TDA_HDCP) ++else ++EXTRA_CFLAGS += -DNO_HDCP ++endif ++endif ++ ++ifeq ($(TDA_TX),TDA9984) ++EXTRA_CFLAGS += -DNO_HDCP ++endif ++ ++ifeq ($(TDA_TX),TDA9981) ++EXTRA_CFLAGS += -DTMFL_TDA9981_SUPPORT -DTMFL_RX_SENSE_ON ++endif ++ ++########## devlib ################################################## ++ ++ifeq ($(TDA_TX),TDA19989) ++TXSRC := comps/tmdlHdmiTx/src ++TXCFG := comps/tmdlHdmiTx/cfg/TDA9989 ++CECSRC := comps/tmdlHdmiCEC/src ++CECCFG := comps/tmdlHdmiCEC/cfg ++endif ++ ++ifeq ($(TDA_TX),TDA9984) ++TXSRC := comps/tmdlHdmiTx/src ++TXCFG := comps/tmdlHdmiTx/cfg/TDA9989 ++endif ++ ++ifeq ($(TDA_TX),TDA9983) ++TXSRC := comps/tmdlTDA9983/src ++TXCFG := comps/tmdlTDA9983/cfg ++endif ++ ++ifeq ($(TDA_TX),TDA9981) ++TXSRC := comps/tmdlTDA9983/src ++TXCFG := comps/tmdlTDA9983/cfg ++endif ++ ++########## board service layer ##################################### ++ ++ifeq ($(TDA_TX),TDA19989) ++BSL := comps/tmbslTDA9989/src ++endif ++ ++ifeq ($(TDA_TX),TDA9984) ++BSL := comps/tmbslTDA9984NoHdcp/src ++endif ++ ++ifeq ($(TDA_TX),TDA9983) ++BSL := comps/tmbslTDA9983/src ++endif ++ ++ifeq ($(TDA_TX),TDA9981) ++BSL := comps/tmbslTDA9983/src ++endif ++ ++#################################################################### ++ ++obj-y += hdmitx.o ++ifeq ($(TDA_CEC),TDA9950) ++obj-m += hdmicec.o ++endif ++ ++# Linux module ++hdmitx-objs := tda998x.o ++hdmicec-objs := tda998x_cec.o ++ ++# NXP comps ++ifeq ($(TDA_TX),TDA19989) ++hdmitx-objs += $(TXSRC)/tmdlHdmiTx.o ++hdmitx-objs += $(TXSRC)/tmdlHdmiTx_local.o ++hdmitx-objs += $(TXCFG)/tmdlHdmiTx_cfg.o ++hdmitx-objs += $(BSL)/tmbslTDA9989_local.o ++hdmitx-objs += $(BSL)/tmbslTDA9989_InOut.o ++hdmitx-objs += $(BSL)/tmbslTDA9989_HDCP.o ++hdmitx-objs += $(BSL)/tmbslTDA9989_State.o ++hdmitx-objs += $(BSL)/tmbslTDA9989_Misc.o ++hdmitx-objs += $(BSL)/tmbslTDA9989_Edid.o ++hdmicec-objs += $(CECSRC)/tmdlHdmiCEC.o ++hdmicec-objs += $(CECSRC)/tmdlHdmiCEC_local.o ++hdmicec-objs += $(CECCFG)/tmdlHdmiCEC_Linux.o ++endif ++ ++ifeq ($(TDA_TX),TDA9984) ++hdmitx-objs += $(TXSRC)/tmdlHdmiTx.o ++hdmitx-objs += $(TXSRC)/tmdlHdmiTx_local.o ++hdmitx-objs += $(TXCFG)/tmdlHdmiTx_Linux.o ++hdmitx-objs += $(BSL)/tmbslTDA9984_local.o ++hdmitx-objs += $(BSL)/tmbslTDA9984_InOut.o ++hdmitx-objs += $(BSL)/tmbslTDA9984_HDCP.o ++hdmitx-objs += $(BSL)/tmbslTDA9984_State.o ++hdmitx-objs += $(BSL)/tmbslTDA9984_Misc.o ++hdmitx-objs += $(BSL)/tmbslTDA9984_Edid.o ++endif ++ ++ifeq ($(TDA_TX),TDA9983) ++hdmitx-objs += $(BSL)/tmbslHdmiTx_2.o ++hdmitx-objs += $(BSL)/tmbslHdmiTx_1.o ++hdmitx-objs += $(BSL)/tmbslHdmiTx_local.o ++hdmitx-objs += $(TXSRC)/tmdlHdmiTx.o ++hdmitx-objs += $(TXCFG)/tmdlHdmiTx_Linux.o ++endif ++ ++ifeq ($(TDA_TX),TDA9981) ++hdmitx-objs += $(BSL)/tmbslHdmiTx_2.o ++hdmitx-objs += $(BSL)/tmbslHdmiTx_1.o ++hdmitx-objs += $(BSL)/tmbslHdmiTx_local.o ++hdmitx-objs += $(TXSRC)/tmdlHdmiTx.o ++hdmitx-objs += $(TXCFG)/tmdlHdmiTx_Linux.o ++endif ++ ++#################################################################### ++ ++EXTRA_CFLAGS += -I$(obj) ++EXTRA_CFLAGS += -I$(obj)/inc ++ ++ifeq ($(TDA_TX),TDA19989) ++EXTRA_CFLAGS += -I$(obj)/comps/tmbslHdmiTx/inc ++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiTx/src ++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiTx/cfg ++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiTx/inc ++EXTRA_CFLAGS += -I$(obj)/comps/tmbslTDA9989/inc ++EXTRA_CFLAGS += -I$(obj)/comps/tmbslTDA9989/src ++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiCEC/inc ++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiCEC/src ++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiCEC/cfg ++endif ++ ++ifeq ($(TDA_TX),TDA9984) ++EXTRA_CFLAGS += -I$(obj)/comps/tmbslHdmiTx/inc ++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiTx/src ++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiTx/cfg ++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiTx/inc ++EXTRA_CFLAGS += -I$(obj)/comps/tmbslTDA9984NoHdcp/inc ++EXTRA_CFLAGS += -I$(obj)/comps/tmbslTDA9984NoHdcp/src ++endif ++ ++ifeq ($(TDA_TX),TDA9983) ++EXTRA_CFLAGS += -I$(obj)/comps/tmbslTDA9983/inc ++EXTRA_CFLAGS += -I$(obj)/comps/tmdlTDA9983/inc ++EXTRA_CFLAGS += -I$(obj)/comps/tmdlTDA9983/src ++EXTRA_CFLAGS += -I$(obj)/comps/tmdlTDA9983/cfg ++endif ++ ++ifeq ($(TDA_TX),TDA9981) ++EXTRA_CFLAGS += -I$(obj)/comps/tmbslTDA9983/inc ++EXTRA_CFLAGS += -I$(obj)/comps/tmdlTDA9983/inc ++EXTRA_CFLAGS += -I$(obj)/comps/tmdlTDA9983/src ++EXTRA_CFLAGS += -I$(obj)/comps/tmdlTDA9983/cfg ++endif ++ ++ ++ +diff --git a/drivers/video/nxp/comps/tmbslHdmiTx/inc/tmbslHdmiTx_types.h b/drivers/video/nxp/comps/tmbslHdmiTx/inc/tmbslHdmiTx_types.h +new file mode 100755 +index 0000000..6827b24 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmbslHdmiTx/inc/tmbslHdmiTx_types.h +@@ -0,0 +1,1804 @@ ++/** ++ * Copyright (C) 2007 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmbslHdmiTx_types.h ++ * ++ * \version $Revision: 18 $ ++ * ++ * \date $Date: 17/03/08 $ ++ * ++ * \brief HDMI Transmitter common types ++ * ++ * \section refs Reference Documents ++ * ++ * \section info Change Information ++ * ++ * \verbatim ++ ++ $History: tmbslHdmiTx_types.h $ ++ * ++ * ++ * **************** Version 18 ****************** ++ * User: G.Burnouf Date: 01/04/08 ++ * Updated in $/Source/tmbslHdmiTx/inc ++ * PR1468 : add new function tmbslTDA9984GetSinkCategory ++ * ++ * ++ * **************** Version 17 ****************** ++ * User: G.Burnouf Date: 17/03/08 ++ * Updated in $/Source/tmbslHdmiTx/inc ++ * PR1430 : Increase size of table for ++ * Short Audio Descriptor ++ * ++ * **************** Version 16 ****************** ++ * User: G.Burnouf Date: 06/03/08 ++ * Updated in $/Source/tmbslHdmiTx/inc ++ * PR1406 : new reset audio fifo sequence ++ * ++ * **************** Version 15 ****************** ++ * User: G.Burnouf Date: 05/02/08 ++ * Updated in $/Source/tmbslHdmiTx/inc ++ * PR1251 : add new type for function ++ * tmbslTDA9984EdidGetBasicDisplayParam ++ * ++ ****************** Version 14 ****************** ++ * User: G.Burnouf Date: 14/01/08 ++ * Updated in $/Source/tmbslHdmiTx/inc ++ * PR580 - Change BSL error base address ++ * ++ ****************** Version 13 ****************** ++ * User: G.Burnouf Date: 10/01/08 ++ * Updated in $/Source/tmbslHdmiTx/inc ++ * PR606 - Apply audio port config in function ++ * of audio format ++ * ++ * **************** Version 12 ****************** ++ * User: G.Burnouf Date: 10/12/07 Time: 08:30 ++ * Updated in $/Source/tmbslHdmiTx/inc ++ * PR1145 : return DTD and monitor description ++ * ++ * ***************** Version 11 ***************** ++ * User: G.Burnouf Date: 04/12/07 ++ * Updated in $/Source/tmbslHdmiTx/inc ++ * PR948 : add new formats, 1080p24/25/30 ++ * ++ * ***************** Version 10 ***************** ++ * User: C. Diehl Date: 27/11/07 ++ * Updated in $/Source/tmbslHdmiTx/inc ++ * PR1030 : - Align with the common interface ++ * reworked for the LIPP4200 ++ * ++ * ***************** Version 9 ***************** ++ * User: J.Lamotte Date: 23/11/07 Time: 09:35 ++ * Updated in $/Source/tmbslHdmiTx/src ++ * PR1078 : - update HDMI_TX_SVD_MAX_CNT from 30 ++ * to 113 ++ * ++ * ***************** Version 8 ***************** ++ * User: G.Burnouf Date: 13/11/07 Time: 09:29 ++ * Updated in $/Source/tmbslHdmiTx/src ++ * PR1008 : - update type tmbslHdmiTxHwFeature_t ++ * ++ * ***************** Version 7 ***************** ++ * User: G.Burnouf Date: 16/10/07 Time: 14:32 ++ * Updated in $/Source/tmbslHdmiTx/src ++ * PR882 : - add type tmbslHdmiTxPowerState_t ++ * - add type tmbslHdmiTxPktGmt_t for gamut ++ * - add new interrupt callback for VS ++ * ++ * ***************** Version 6 ***************** ++ * User: G.Burnouf Date: 05/10/07 Time: 14:32 ++ * Updated in $/Source/tmbslHdmiTx/src ++ * PR824 : add type for enum _tmbslHdmiTxCallbackInt ++ * ++ * ***************** Version 5 ***************** ++ * User: J.Turpin Date: 13/09/07 Time: 14:32 ++ * Updated in $/Source/tmbslHdmiTx/src ++ * PR693 : add black pattern functionality ++ * - add HDMITX_PATTERN_BLACK in ++ * enum tmbslHdmiTxTestPattern_t ++ * ++ * ***************** Version 4 ***************** ++ * User: G.Burnouf Date: 06/09/07 Time: 17:22 ++ * Updated in $/Source/tmbslTDA9984/Inc ++ * PR656 : - add HBR format ++ * - add format I2s Philips left and right justified ++ * ++ * ***************** Version 3 ***************** ++ * User: G. Burnouf Date: 07/08/07 Time: 10:30 ++ * Updated in $/Source/tmbslTDA9984/Inc ++ * PR572 - change type name of tmbslTDA9984_ to tmbslHdmiTx_ ++ * ++ * ***************** Version 2 ***************** ++ * User: B.Vereecke Date: 07/08/07 Time: 10:30 ++ * Updated in $/Source/tmbslTDA9984/Inc ++ * PR551 - Add a new Pattern type in tmbslHdmiTxTestPattern_t ++ * it is used for set the bluescreen ++ * ++ * ***************** Version 1 ***************** ++ * User: G. Burnouf Date: 05/07/07 Time: 17:00 ++ * Updated in $/Source/tmbslTDA9984/Inc ++ * PR 414 : Add new edid management ++ * ++ \endverbatim ++ * ++*/ ++ ++#ifndef TMBSLHDMITX_TYPES_H ++#define TMBSLHDMITX_TYPES_H ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#include "tmNxCompId.h" ++ ++ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*============================================================================*/ ++/* MACRO DEFINITIONS */ ++/*============================================================================*/ ++ ++/** ++ * The maximum number of supported HDMI Transmitter units ++ */ ++#define HDMITX_UNITS_MAX 2 ++ ++/** \name Errors ++ * The group of error codes returned by all API and internal functions ++ */ ++/*@{*/ ++/** The base offset for all error codes. ++ * This needs defining as non-zero if this component is integrated with others ++ * and all component error ranges are to be kept separate. ++ */ ++#define TMBSL_ERR_HDMI_BASE CID_BSL_HDMITX ++ ++/** Define the OK code if not defined already */ ++#ifndef TM_OK ++#define TM_OK 0 ++#endif ++ ++/** SW interface compatibility error */ ++#define TMBSL_ERR_HDMI_COMPATIBILITY (TMBSL_ERR_HDMI_BASE + 0x001U) ++ ++/** SW major version error */ ++#define TMBSL_ERR_HDMI_MAJOR_VERSION (TMBSL_ERR_HDMI_BASE + 0x002U) ++ ++/** SW component version error */ ++#define TMBSL_ERR_HDMI_COMP_VERSION (TMBSL_ERR_HDMI_BASE + 0x003U) ++ ++/** Invalid device unit number */ ++#define TMBSL_ERR_HDMI_BAD_UNIT_NUMBER (TMBSL_ERR_HDMI_BASE + 0x005U) ++ ++/** Invalid input parameter other than unit number */ ++#define TMBSL_ERR_HDMI_BAD_PARAMETER (TMBSL_ERR_HDMI_BASE + 0x009U) ++ ++/* Ressource not available */ ++#define TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE (TMBSL_ERR_HDMI_BASE + 0x00CU) ++ ++/** Inconsistent input parameters */ ++#define TMBSL_ERR_HDMI_INCONSISTENT_PARAMS (TMBSL_ERR_HDMI_BASE + 0x010U) ++ ++/** Component is not initialized */ ++#define TMBSL_ERR_HDMI_NOT_INITIALIZED (TMBSL_ERR_HDMI_BASE + 0x011U) ++ ++/** Command not supported for current device */ ++#define TMBSL_ERR_HDMI_NOT_SUPPORTED (TMBSL_ERR_HDMI_BASE + 0x013U) ++ ++/** Initialization failed */ ++#define TMBSL_ERR_HDMI_INIT_FAILED (TMBSL_ERR_HDMI_BASE + 0x014U) ++ ++/** Component is busy and cannot do a new operation */ ++#define TMBSL_ERR_HDMI_BUSY (TMBSL_ERR_HDMI_BASE + 0x015U) ++ ++/** I2C read error */ ++#define TMBSL_ERR_HDMI_I2C_READ (TMBSL_ERR_HDMI_BASE + 0x017U) ++ ++/** I2C write error */ ++#define TMBSL_ERR_HDMI_I2C_WRITE (TMBSL_ERR_HDMI_BASE + 0x018U) ++ ++/** Assertion failure */ ++#define TMBSL_ERR_HDMI_ASSERTION (TMBSL_ERR_HDMI_BASE + 0x049U) ++ ++/** Bad EDID block checksum */ ++#define TMBSL_ERR_HDMI_INVALID_STATE (TMBSL_ERR_HDMI_BASE + 0x066U) ++#define TMBSL_ERR_HDMI_INVALID_CHECKSUM TMBSL_ERR_HDMI_INVALID_STATE ++ ++/** No connection to HPD pin */ ++#define TMBSL_ERR_HDMI_NULL_CONNECTION (TMBSL_ERR_HDMI_BASE + 0x067U) ++ ++/** Not allowed in DVI mode */ ++#define TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED (TMBSL_ERR_HDMI_BASE + 0x068U) ++ ++/** Maximum error code defined */ ++#define TMBSL_ERR_HDMI_MAX TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED ++ ++/*============================================================================*/ ++ ++#define HDMITX_ENABLE_VP_TABLE_LEN 3 ++#define HDMITX_GROUND_VP_TABLE_LEN 3 ++ ++/** EDID block size */ ++#define EDID_BLOCK_SIZE 128 ++ ++/** size descriptor block of monitor descriptor */ ++#define EDID_MONITOR_DESCRIPTOR_SIZE 13 ++ ++/*@}*/ ++ ++ ++/*============================================================================*/ ++/* ENUM OR TYPE DEFINITIONS */ ++/*============================================================================*/ ++ ++/** ++* \brief TX IP/IC versions ++*/ ++typedef enum ++{ ++ BSLHDMITX_UNKNOWN = 0x00, /**< IC/IP is not recognized */ ++ BSLHDMITX_TDA9984, /**< IC is a TDA9984 */ ++ BSLHDMITX_TDA9989, /**< IC is a TDA9989 (TDA9989N2 64 balls) */ ++ BSLHDMITX_TDA9981, /**< IC is a TDA9981 */ ++ BSLHDMITX_TDA9983, /**< IC is a TDA9983 */ ++ BSLHDMITX_TDA19989, /**< IC is a TDA19989 */ ++ BSLHDMITX_TDA19988, /**< ok, u got it, it's a 19988 :p */ ++} tmbslHdmiTxVersion_t; ++ ++ ++/** ++ * \brief System function pointer type, to call user I2C read/write functions ++ * \param slaveAddr The I2C slave address ++ * \param firstRegister The first device register address to read or write ++ * \param lenData Length of data to read or write (i.e. no. of registers) ++ * \param pData Pointer to data to write, or to buffer to receive data ++ * \return The call result: ++ * - TM_OK: the call was successful ++ * - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing ++ * - TMBSL_ERR_HDMI_I2C_READ: failed when reading ++ */ ++typedef struct _tmbslHdmiTxSysArgs_t ++{ ++ UInt8 slaveAddr; ++ UInt8 firstRegister; ++ UInt8 lenData; ++ UInt8 *pData; ++} tmbslHdmiTxSysArgs_t; ++typedef tmErrorCode_t (FUNC_PTR * ptmbslHdmiTxSysFunc_t) ++ (tmbslHdmiTxSysArgs_t *pSysArgs); ++ ++/** ++ * \brief System function pointer type, to call user I2C EDID read function ++ * \param segPtrAddr The EDID segment pointer address 0 to 7Fh ++ * \param segPtr The EDID segment pointer 0 to 7Fh ++ * \param dataRegAddr The EDID data register address 0 to 7Fh ++ * \param wordOffset The first word offset 0 to FFh to read ++ * \param lenData Length of data to read (i.e. number of registers), ++ 1 to max starting at wordOffset ++ * \param pData Pointer to buffer to receive lenData data bytes ++ * \return The call result: ++ * - TM_OK: the call was successful ++ * - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing ++ * - TMBSL_ERR_HDMI_I2C_READ: failed when reading ++ */ ++typedef struct _tmbslHdmiTxSysArgsEdid_t ++{ ++ UInt8 segPtrAddr; ++ UInt8 segPtr; ++ UInt8 dataRegAddr; ++ UInt8 wordOffset; ++ UInt8 lenData; ++ UInt8 *pData; ++} tmbslHdmiTxSysArgsEdid_t; ++ ++ ++/** ++ * \brief EDID function pointer type, to call application EDID read function ++ * \param pSysArgs pointer to the structure containing necessary information to read EDID ++ */ ++typedef tmErrorCode_t (FUNC_PTR * ptmbslHdmiTxSysFuncEdid_t) ++ (tmbslHdmiTxSysArgsEdid_t *pSysArgs); ++ ++/** ++ * \brief Timer function pointer type, to call an application timer ++ * \param ms delay in milliseconds ++ */ ++typedef Void (FUNC_PTR * ptmbslHdmiTxSysFuncTimer_t) (UInt16 ms); ++ ++/*============================================================================*/ ++/** ++ * \brief Callback function pointer type, to call a user interrupt handler ++ * \param txUnit: The transmitter unit that interrupted, 0 to max ++ */ ++typedef Void (FUNC_PTR * ptmbslHdmiTxCallback_t) (tmUnitSelect_t txUnit); ++ ++/*============================================================================*/ ++/** ++ * EIA/CEA-861B video format type ++ */ ++typedef enum ++{ ++ HDMITX_VFMT_NULL = 0, /**< Not a valid format... */ ++ HDMITX_VFMT_NO_CHANGE = 0, /**< ...or no change required */ ++ HDMITX_VFMT_TV_MIN = 1, /**< Lowest valid TV format */ ++ HDMITX_VFMT_01_640x480p_60Hz = 1, /**< Format 01 640 x 480p 60Hz */ ++ HDMITX_VFMT_02_720x480p_60Hz = 2, /**< Format 02 720 x 480p 60Hz */ ++ HDMITX_VFMT_03_720x480p_60Hz = 3, /**< Format 03 720 x 480p 60Hz */ ++ HDMITX_VFMT_04_1280x720p_60Hz = 4, /**< Format 04 1280 x 720p 60Hz */ ++ HDMITX_VFMT_05_1920x1080i_60Hz = 5, /**< Format 05 1920 x 1080i 60Hz */ ++ HDMITX_VFMT_06_720x480i_60Hz = 6, /**< Format 06 720 x 480i 60Hz */ ++ HDMITX_VFMT_07_720x480i_60Hz = 7, /**< Format 07 720 x 480i 60Hz */ ++ HDMITX_VFMT_08_720x240p_60Hz = 8, /**< Format 08 720 x 240p 60Hz */ ++ HDMITX_VFMT_09_720x240p_60Hz = 9, /**< Format 09 720 x 240p 60Hz */ ++ HDMITX_VFMT_10_720x480i_60Hz = 10, /**< Format 10 720 x 480i 60Hz */ ++ HDMITX_VFMT_11_720x480i_60Hz = 11, /**< Format 11 720 x 480i 60Hz */ ++ HDMITX_VFMT_12_720x240p_60Hz = 12, /**< Format 12 720 x 240p 60Hz */ ++ HDMITX_VFMT_13_720x240p_60Hz = 13, /**< Format 13 720 x 240p 60Hz */ ++ HDMITX_VFMT_14_1440x480p_60Hz = 14, /**< Format 14 1440 x 480p 60Hz */ ++ HDMITX_VFMT_15_1440x480p_60Hz = 15, /**< Format 15 1440 x 480p 60Hz */ ++ HDMITX_VFMT_16_1920x1080p_60Hz = 16, /**< Format 16 1920 x 1080p 60Hz */ ++ HDMITX_VFMT_17_720x576p_50Hz = 17, /**< Format 17 720 x 576p 50Hz */ ++ HDMITX_VFMT_18_720x576p_50Hz = 18, /**< Format 18 720 x 576p 50Hz */ ++ HDMITX_VFMT_19_1280x720p_50Hz = 19, /**< Format 19 1280 x 720p 50Hz */ ++ HDMITX_VFMT_20_1920x1080i_50Hz = 20, /**< Format 20 1920 x 1080i 50Hz */ ++ HDMITX_VFMT_21_720x576i_50Hz = 21, /**< Format 21 720 x 576i 50Hz */ ++ HDMITX_VFMT_22_720x576i_50Hz = 22, /**< Format 22 720 x 576i 50Hz */ ++ HDMITX_VFMT_23_720x288p_50Hz = 23, /**< Format 23 720 x 288p 50Hz */ ++ HDMITX_VFMT_24_720x288p_50Hz = 24, /**< Format 24 720 x 288p 50Hz */ ++ HDMITX_VFMT_25_720x576i_50Hz = 25, /**< Format 25 720 x 576i 50Hz */ ++ HDMITX_VFMT_26_720x576i_50Hz = 26, /**< Format 26 720 x 576i 50Hz */ ++ HDMITX_VFMT_27_720x288p_50Hz = 27, /**< Format 27 720 x 288p 50Hz */ ++ HDMITX_VFMT_28_720x288p_50Hz = 28, /**< Format 28 720 x 288p 50Hz */ ++ HDMITX_VFMT_29_1440x576p_50Hz = 29, /**< Format 29 1440 x 576p 50Hz */ ++ HDMITX_VFMT_30_1440x576p_50Hz = 30, /**< Format 30 1440 x 576p 50Hz */ ++ HDMITX_VFMT_31_1920x1080p_50Hz = 31, /**< Format 31 1920 x 1080p 50Hz */ ++ HDMITX_VFMT_32_1920x1080p_24Hz = 32, /**< Format 32 1920 x 1080p 24Hz */ ++ ++ HDMITX_VFMT_TV_NO_REG_MIN = 32, /**< Lowest TV format without prefetched table */ ++ ++ HDMITX_VFMT_33_1920x1080p_25Hz = 33, /**< Format 33 1920 x 1080p 25Hz */ ++ HDMITX_VFMT_34_1920x1080p_30Hz = 34, /**< Format 34 1920 x 1080p 30Hz */ ++ HDMITX_VFMT_35_2880x480p_60Hz = 35, /**< Format 35 2880 x 480p 60Hz 4:3 */ ++ HDMITX_VFMT_36_2880x480p_60Hz = 36, /**< Format 36 2880 x 480p 60Hz 16:9 */ ++ HDMITX_VFMT_37_2880x576p_50Hz = 37, /**< Format 37 2880 x 576p 50Hz 4:3 */ ++ HDMITX_VFMT_38_2880x576p_50Hz = 38, /**< Format 38 2880 x 576p 50Hz 16:9 */ ++ ++ HDMITX_VFMT_INDEX_60_1280x720p_24Hz = 39,/**< Index of HDMITX_VFMT_60_1280x720p_24Hz */ ++ HDMITX_VFMT_60_1280x720p_24Hz = 60, /**< Format 60 1280 x 720p 23.97/24Hz 16:9 */ ++ HDMITX_VFMT_61_1280x720p_25Hz = 61, /**< Format 61 1280 x 720p 25Hz 16:9 */ ++ HDMITX_VFMT_62_1280x720p_30Hz = 62, /**< Format 60 1280 x 720p 29.97/30Hz 16:9 */ ++ ++ HDMITX_VFMT_TV_MAX = 62, /**< Highest valid TV format value */ ++ HDMITX_VFMT_TV_NUM = 42, /**< Number of TV formats + null, it is also the Index of PC_MIN */ ++ ++ HDMITX_VFMT_PC_MIN = 128, /**< Lowest valid PC format */ ++ HDMITX_VFMT_PC_640x480p_60Hz = 128, /**< PC format 128 */ ++ HDMITX_VFMT_PC_800x600p_60Hz = 129, /**< PC format 129 */ ++ HDMITX_VFMT_PC_1152x960p_60Hz = 130, /**< PC format 130 */ ++ HDMITX_VFMT_PC_1024x768p_60Hz = 131, /**< PC format 131 */ ++ HDMITX_VFMT_PC_1280x768p_60Hz = 132, /**< PC format 132 */ ++ HDMITX_VFMT_PC_1280x1024p_60Hz = 133, /**< PC format 133 */ ++ HDMITX_VFMT_PC_1360x768p_60Hz = 134, /**< PC format 134 */ ++ HDMITX_VFMT_PC_1400x1050p_60Hz = 135, /**< PC format 135 */ ++ HDMITX_VFMT_PC_1600x1200p_60Hz = 136, /**< PC format 136 */ ++ HDMITX_VFMT_PC_1024x768p_70Hz = 137, /**< PC format 137 */ ++ HDMITX_VFMT_PC_640x480p_72Hz = 138, /**< PC format 138 */ ++ HDMITX_VFMT_PC_800x600p_72Hz = 139, /**< PC format 139 */ ++ HDMITX_VFMT_PC_640x480p_75Hz = 140, /**< PC format 140 */ ++ HDMITX_VFMT_PC_1024x768p_75Hz = 141, /**< PC format 141 */ ++ HDMITX_VFMT_PC_800x600p_75Hz = 142, /**< PC format 142 */ ++ HDMITX_VFMT_PC_1024x864p_75Hz = 143, /**< PC format 143 */ ++ HDMITX_VFMT_PC_1280x1024p_75Hz = 144, /**< PC format 144 */ ++ HDMITX_VFMT_PC_640x350p_85Hz = 145, /**< PC format 145 */ ++ HDMITX_VFMT_PC_640x400p_85Hz = 146, /**< PC format 146 */ ++ HDMITX_VFMT_PC_720x400p_85Hz = 147, /**< PC format 147 */ ++ HDMITX_VFMT_PC_640x480p_85Hz = 148, /**< PC format 148 */ ++ HDMITX_VFMT_PC_800x600p_85Hz = 149, /**< PC format 149 */ ++ HDMITX_VFMT_PC_1024x768p_85Hz = 150, /**< PC format 150 */ ++ HDMITX_VFMT_PC_1152x864p_85Hz = 151, /**< PC format 151 */ ++ HDMITX_VFMT_PC_1280x960p_85Hz = 152, /**< PC format 152 */ ++ HDMITX_VFMT_PC_1280x1024p_85Hz = 153, /**< PC format 153 */ ++ HDMITX_VFMT_PC_1024x768i_87Hz = 154, /**< PC format 154 */ ++ HDMITX_VFMT_PC_MAX = 154, /**< Highest valid PC format */ ++ HDMITX_VFMT_PC_NUM = (1+154-128) /**< Number of PC formats */ ++} tmbslHdmiTxVidFmt_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984AudioInSetConfig() parameter types ++ */ ++/** Audio input formats */ ++typedef enum ++{ ++ HDMITX_AFMT_SPDIF = 0, /**< SPDIF */ ++ HDMITX_AFMT_I2S = 1, /**< I2S */ ++ HDMITX_AFMT_OBA = 2, /**< One bit audio / DSD */ ++ HDMITX_AFMT_DST = 3, /**< DST */ ++ HDMITX_AFMT_HBR = 4, /**< HBR */ ++ HDMITX_AFMT_NUM = 5, /**< Number of Audio input format */ ++ HDMITX_AFMT_INVALID = 5 /**< Invalid format */ ++} tmbslHdmiTxaFmt_t; ++ ++/** I2s formats */ ++typedef enum ++{ ++ HDMITX_I2SFOR_PHILIPS_L = 0, /**< Philips like format */ ++ HDMITX_I2SFOR_OTH_L = 2, /**< Other non Philips left justified */ ++ HDMITX_I2SFOR_OTH_R = 3, /**< Other non Philips right justified */ ++ HDMITX_I2SFOR_INVALID = 4 /**< Invalid format*/ ++} tmbslHdmiTxI2sFor_t; ++ ++/** DSD clock polarities */ ++typedef enum ++{ ++ HDMITX_CLKPOLDSD_ACLK = 0, /**< Same as ACLK */ ++ HDMITX_CLKPOLDSD_NACLK = 1, /**< Not ACLK, i.e. inverted */ ++ HDMITX_CLKPOLDSD_NO_CHANGE = 2, /**< No change */ ++ HDMITX_CLKPOLDSD_INVALID = 3 /**< Invalid */ ++} tmbslHdmiTxClkPolDsd_t; ++ ++/** DSD data swap values */ ++typedef enum ++{ ++ HDMITX_SWAPDSD_OFF = 0, /**< No swap */ ++ HDMITX_SWAPDSD_ON = 1, /**< Swap */ ++ HDMITX_SWAPDSD_NO_CHANGE = 2, /**< No change */ ++ HDMITX_SWAPDSD_INVALID = 3 /**< Invalid */ ++} tmbslHdmiTxSwapDsd_t; ++ ++/** DST data transfer rates */ ++typedef enum ++{ ++ HDMITX_DSTRATE_SINGLE = 0, /**< Single transfer rate */ ++ HDMITX_DSTRATE_DOUBLE = 1, /**< Double data rate */ ++ HDMITX_DSTRATE_NO_CHANGE = 2, /**< No change */ ++ HDMITX_DSTRATE_INVALID = 3 /**< Invalid */ ++} tmbslHdmiTxDstRate_t; ++ ++/** I2S, SPDIF and DSD channel allocation values */ ++enum _tmbslHdmiTxChan ++{ ++ HDMITX_CHAN_MIN = 0, ++ HDMITX_CHAN_MAX = 31, ++ HDMITX_CHAN_NO_CHANGE = 32, ++ HDMITX_CHAN_INVALID = 33 ++}; ++ ++/** Audio layout values */ ++enum _tmbslHdmiTxLayout ++{ ++ HDMITX_LAYOUT_MIN = 0, ++ HDMITX_LAYOUT_MAX = 1, ++ HDMITX_LAYOUT_NO_CHANGE = 2, ++ HDMITX_LAYOUT_INVALID = 3 ++}; ++ ++/** Audio FIFO read latency values */ ++enum _tmbslHdmiTxlatency_rd ++{ ++ HDMITX_LATENCY_MIN = 0x000, ++ HDMITX_LATENCY_CURRENT = 0x080, ++ HDMITX_LATENCY_MAX = 0x0FF, ++ HDMITX_LATENCY_NO_CHANGE = 0x100, ++ HDMITX_LATENCY_INVALID = 0x101 ++}; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984AudioInSetCts() parameter types ++ */ ++/** Clock Time Stamp reference source */ ++typedef enum ++{ ++ HDMITX_CTSREF_ACLK = 0, /**< Clock input pin for I2S */ ++ HDMITX_CTSREF_MCLK = 1, /**< Clock input pin for EXTREF */ ++ HDMITX_CTSREF_FS64SPDIF = 2, /**< 64xsample rate, for SPDIF */ ++ HDMITX_CTSREF_INVALID = 3 /**< Invalid value */ ++} tmbslHdmiTxctsRef_t; ++ ++/** Audio sample rate kHz indexes */ ++typedef enum ++{ ++ HDMITX_AFS_32k = 0, /**< 32kHz */ ++ HDMITX_AFS_44_1k = 1, /**< 44.1kHz */ ++ HDMITX_AFS_48K = 2, /**< 48kHz */ ++ HDMITX_AFS_88_2K = 3, /**< 88.2kHz */ ++ HDMITX_AFS_96K = 4, /**< 96kHz */ ++ HDMITX_AFS_176_4K = 5, /**< 176.4kHz */ ++ HDMITX_AFS_192K = 6, /**< 192kHz */ ++ HDMITX_AFS_768K = 7, /**< 768kHz */ ++ HDMITX_AFS_NOT_INDICATED = 8, /**< Not Indicated (Channel Status) */ ++ HDMITX_AFS_INVALID = 8, /**< Invalid */ ++ HDMITX_AFS_NUM = 8 /**< # rates */ ++} tmbslHdmiTxafs_t; ++ ++/** Vertical output frequencies */ ++typedef enum ++{ ++ HDMITX_VFREQ_24Hz = 0, /**< 24Hz */ ++ HDMITX_VFREQ_25Hz = 1, /**< 25Hz */ ++ HDMITX_VFREQ_30Hz = 2, /**< 30Hz */ ++ HDMITX_VFREQ_50Hz = 3, /**< 50Hz */ ++ HDMITX_VFREQ_59Hz = 4, /**< 59.94Hz */ ++ HDMITX_VFREQ_60Hz = 5, /**< 60Hz */ ++#ifndef FORMAT_PC ++ HDMITX_VFREQ_INVALID = 6, /**< Invalid */ ++ HDMITX_VFREQ_NUM = 6 /**< No. of values */ ++#else /* FORMAT_PC */ ++ HDMITX_VFREQ_70Hz = 6, /**< 70Hz */ ++ HDMITX_VFREQ_72Hz = 7, /**< 72Hz */ ++ HDMITX_VFREQ_75Hz = 8, /**< 75Hz */ ++ HDMITX_VFREQ_85Hz = 9, /**< 85Hz */ ++ HDMITX_VFREQ_87Hz = 10, /**< 87Hz */ ++ HDMITX_VFREQ_INVALID = 11, /**< Invalid */ ++ HDMITX_VFREQ_NUM = 11 /**< No. of values */ ++#endif /* FORMAT_PC */ ++} tmbslHdmiTxVfreq_t; ++ ++/** Clock Time Stamp predivider - scales N */ ++typedef enum ++{ ++ HDMITX_CTSK1 = 0, /**< k=1 */ ++ HDMITX_CTSK2 = 1, /**< k=2 */ ++ HDMITX_CTSK3 = 2, /**< k=3 */ ++ HDMITX_CTSK4 = 3, /**< k=4 */ ++ HDMITX_CTSK8 = 4, /**< k=8 */ ++ HDMITX_CTSK_USE_CTSX = 5, /**< Calculate from ctsX factor */ ++ HDMITX_CTSK_INVALID = 6 /**< Invalid */ ++} tmbslHdmiTxctsK_t; ++ ++/** Clock Time Stamp postdivider measured time stamp */ ++typedef enum ++{ ++ HDMITX_CTSMTS = 0, /**< =mts */ ++ HDMITX_CTSMTS2 = 1, /**< =mts%2 */ ++ HDMITX_CTSMTS4 = 2, /**< =mts%4 */ ++ HDMITX_CTSMTS8 = 3, /**< =mts%8 */ ++ HDMITX_CTSMTS_USE_CTSX = 4, /**< Calculate from ctsX factor */ ++ HDMITX_CTSMTS_INVALID = 5 /**< Invalid */ ++} tmbslHdmiTxctsM_t; ++ ++/** Cycle Time Stamp values */ ++enum _tmbslHdmiTxCts ++{ ++ HDMITX_CTS_AUTO = 0, ++ HDMITX_CTS_MIN = 0x000001 ++}; ++ ++/** Cycle Time Stamp X factors */ ++enum _tmbslHdmiTxCtsX ++{ ++ HDMITX_CTSX_16 = 0, ++ HDMITX_CTSX_32 = 1, ++ HDMITX_CTSX_48 = 2, ++ HDMITX_CTSX_64 = 3, ++ HDMITX_CTSX_128 = 4, ++ HDMITX_CTSX_NUM = 5, ++ HDMITX_CTSX_UNUSED = 5, /**< CTX value unused when K and Mts used */ ++ HDMITX_CTSX_INVALID = 6 ++}; ++ ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984AudioOutSetChanStatus() parameter types ++ */ ++ ++typedef enum ++{ ++ HDMITX_AUDIO_DATA_PCM = 0, /**< Main data field represents linear PCM samples. */ ++ HDMITX_AUDIO_DATA_OTHER = 1, /**< Main data field used for purposes other purposes. */ ++ HDMITX_AUDIO_DATA_INVALID = 2 /**< Invalid value */ ++} tmbslHdmiTxAudioData_t; ++ ++/** BYTE 0: Channel Status Format information */ ++typedef enum ++{ ++ HDMITX_CSFI_PCM_2CHAN_NO_PRE = 0, /**< PCM 2 channels without pre-emphasis */ ++ HDMITX_CSFI_PCM_2CHAN_PRE = 1, /**< PCM 2 channels with 50us/15us pre-emphasis */ ++ HDMITX_CSFI_PCM_2CHAN_PRE_RSVD1 = 2, /**< PCM Reserved for 2 channels with pre-emphasis */ ++ HDMITX_CSFI_PCM_2CHAN_PRE_RSVD2 = 3, /**< PCM Reserved for 2 channels with pre-emphasis */ ++ HDMITX_CSFI_NOTPCM_DEFAULT = 4, /**< Non-PCM Default state */ ++ HDMITX_CSFI_INVALID = 5 /**< Invalid value */ ++} tmbslHdmiTxCSformatInfo_t; ++ ++/** BYTE 0: Channel Status Copyright assertion */ ++typedef enum ++{ ++ HDMITX_CSCOPYRIGHT_PROTECTED = 0, /**< Copyright protected */ ++ HDMITX_CSCOPYRIGHT_UNPROTECTED = 1, /**< Not copyright protected */ ++ HDMITX_CSCOPYRIGHT_INVALID = 2 /**< Invalid value */ ++} tmbslHdmiTxCScopyright_t; ++ ++/** BYTE 3: Channel Status Clock Accuracy */ ++typedef enum ++{ ++ HDMITX_CSCLK_LEVEL_II = 0, /**< Level II */ ++ HDMITX_CSCLK_LEVEL_I = 1, /**< Level I */ ++ HDMITX_CSCLK_LEVEL_III = 2, /**< Level III */ ++ HDMITX_CSCLK_NOT_MATCHED = 3, /**< Not matched to sample freq. */ ++ HDMITX_CSCLK_INVALID = 4 /**< Invalid */ ++} tmbslHdmiTxCSclkAcc_t; ++ ++/** BYTE 4: Channel Status Maximum sample word length */ ++typedef enum ++{ ++ HDMITX_CSMAX_LENGTH_20 = 0, /**< Max word length is 20 bits */ ++ HDMITX_CSMAX_LENGTH_24 = 1, /**< Max word length is 24 bits */ ++ HDMITX_CSMAX_INVALID = 2 /**< Invalid value */ ++} tmbslHdmiTxCSmaxWordLength_t; ++ ++ ++/** BYTE 4: Channel Status Sample word length */ ++typedef enum ++{ ++ HDMITX_CSWORD_DEFAULT = 0, /**< Word length is not indicated */ ++ HDMITX_CSWORD_20_OF_24 = 1, /**< Sample length is 20 bits out of max 24 possible */ ++ HDMITX_CSWORD_16_OF_20 = 1, /**< Sample length is 16 bits out of max 20 possible */ ++ HDMITX_CSWORD_22_OF_24 = 2, /**< Sample length is 22 bits out of max 24 possible */ ++ HDMITX_CSWORD_18_OF_20 = 2, /**< Sample length is 18 bits out of max 20 possible */ ++ HDMITX_CSWORD_RESVD = 3, /**< Reserved - shall not be used */ ++ HDMITX_CSWORD_23_OF_24 = 4, /**< Sample length is 23 bits out of max 24 possible */ ++ HDMITX_CSWORD_19_OF_20 = 4, /**< Sample length is 19 bits out of max 20 possible */ ++ HDMITX_CSWORD_24_OF_24 = 5, /**< Sample length is 24 bits out of max 24 possible */ ++ HDMITX_CSWORD_20_OF_20 = 5, /**< Sample length is 20 bits out of max 20 possible */ ++ HDMITX_CSWORD_21_OF_24 = 6, /**< Sample length is 21 bits out of max 24 possible */ ++ HDMITX_CSWORD_17_OF_20 = 6, /**< Sample length is 17 bits out of max 20 possible */ ++ HDMITX_CSWORD_INVALID = 7 /**< Invalid */ ++} tmbslHdmiTxCSwordLength_t; ++ ++/** BYTE 4: Channel Status Original sample frequency */ ++typedef enum ++{ ++ HDMITX_CSOFREQ_NOT_INDICATED = 0, /**< Not Indicated */ ++ HDMITX_CSOFREQ_192k = 1, /**< 192kHz */ ++ HDMITX_CSOFREQ_12k = 2, /**< 12kHz */ ++ HDMITX_CSOFREQ_176_4k = 3, /**< 176.4kHz */ ++ HDMITX_CSOFREQ_RSVD1 = 4, /**< Reserved */ ++ HDMITX_CSOFREQ_96k = 5, /**< 96kHz */ ++ HDMITX_CSOFREQ_8k = 6, /**< 8kHz */ ++ HDMITX_CSOFREQ_88_2k = 7, /**< 88.2kHz */ ++ HDMITX_CSOFREQ_16k = 8, /**< 16kHz */ ++ HDMITX_CSOFREQ_24k = 9, /**< 24kHz */ ++ HDMITX_CSOFREQ_11_025k = 10, /**< 11.025kHz */ ++ HDMITX_CSOFREQ_22_05k = 11, /**< 22.05kHz */ ++ HDMITX_CSOFREQ_32k = 12, /**< 32kHz */ ++ HDMITX_CSOFREQ_48k = 13, /**< 48kHz */ ++ HDMITX_CSOFREQ_RSVD2 = 14, /**< Reserved */ ++ HDMITX_CSOFREQ_44_1k = 15, /**< 44.1kHz */ ++ HDMITX_CSAFS_INVALID = 16 /**< Invalid value */ ++} tmbslHdmiTxCSorigAfs_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984AudioOutSetChanStatusMapping() parameter types ++ */ ++/** Channel Status source/channel number limits */ ++enum _tmbslHdmiTxChanStatusChanLimits ++{ ++ HDMITX_CS_CHANNELS_MAX = 0x0F, ++ HDMITX_CS_SOURCES_MAX = 0x0F ++}; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984AudioOutSetMute() parameter type ++ */ ++/** Audio mute state */ ++typedef enum ++{ ++ HDMITX_AMUTE_OFF = 0, /**< Mute off */ ++ HDMITX_AMUTE_ON = 1, /**< Mute on */ ++ HDMITX_AMUTE_INVALID = 2 /**< Invalid */ ++} tmbslHdmiTxaMute_t; ++ ++/** Number of 3 byte Short Audio Descriptors stored in pEdidAFmts */ ++#define HDMI_TX_SAD_MAX_CNT 30 ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984EdidGetBlockData() parameter types ++ */ ++/** An enum to represent the current EDID status */ ++enum _tmbslHdmiTxEdidSta_t ++{ ++ HDMITX_EDID_READ = 0, /* All blocks read OK */ ++ HDMITX_EDID_READ_INCOMPLETE = 1, /* All blocks read OK but buffer too ++ small to return all of them */ ++ HDMITX_EDID_ERROR_CHK_BLOCK_0 = 2, /* Block 0 checksum error */ ++ ++ HDMITX_EDID_ERROR_CHK = 3, /* Block 0 OK, checksum error in one ++ or more other blocks */ ++ HDMITX_EDID_NOT_READ = 4, /* EDID not read */ ++ ++ HDMITX_EDID_STATUS_INVALID = 5 /**< Invalid */ ++ ++}; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984EdidGetSinkType() parameter types ++ */ ++/** Sink device type */ ++typedef enum ++{ ++ HDMITX_SINK_DVI = 0, /**< DVI */ ++ HDMITX_SINK_HDMI = 1, /**< HDMI */ ++ HDMITX_SINK_EDID = 2, /**< As currently defined in EDID */ ++ HDMITX_SINK_INVALID = 3 /**< Invalid */ ++} tmbslHdmiTxSinkType_t; ++ ++/*============================================================================*/ ++/** ++ * \brief The tmbslTDA9984EdidGetVideoPreferred() parameter type ++ * Detailed timining description structure ++ */ ++typedef struct _tmbslHdmiTxEdidDtd_t ++{ ++ UInt16 uPixelClock; /**< Pixel Clock/10,000 */ ++ UInt16 uHActivePixels; /**< Horizontal Active Pixels */ ++ UInt16 uHBlankPixels; /**< Horizontal Blanking Pixels */ ++ UInt16 uVActiveLines; /**< Vertical Active Lines */ ++ UInt16 uVBlankLines; /**< Vertical Blanking Lines */ ++ UInt16 uHSyncOffset; /**< Horizontal Sync Offset */ ++ UInt16 uHSyncWidth; /**< Horiz. Sync Pulse Width */ ++ UInt16 uVSyncOffset; /**< Vertical Sync Offset */ ++ UInt16 uVSyncWidth; /**< Vertical Sync Pulse Width */ ++ UInt16 uHImageSize; /**< Horizontal Image Size */ ++ UInt16 uVImageSize; /**< Vertical Image Size */ ++ UInt16 uHBorderPixels; /**< Horizontal Border */ ++ UInt16 uVBorderPixels; /**< Vertical Border */ ++ UInt8 Flags; /**< Interlace/sync info */ ++} tmbslHdmiTxEdidDtd_t; ++ ++ ++/*============================================================================*/ ++/** ++ * First monitor descriptor structure ++ */ ++typedef struct _tmbslHdmiTxEdidFirstMD_t ++{ ++ Bool bDescRecord; /**< True when parameters of struct are available */ ++ UInt8 uMonitorName[EDID_MONITOR_DESCRIPTOR_SIZE]; /**< Monitor Name */ ++} tmbslHdmiTxEdidFirstMD_t; ++ ++/*============================================================================*/ ++/** ++ * Second monitor descriptor structure ++ */ ++typedef struct _tmbslHdmiTxEdidSecondMD_t ++{ ++ Bool bDescRecord; /**< True when parameters of struct are available */ ++ UInt8 uMinVerticalRate; /**< Min vertical rate in Hz */ ++ UInt8 uMaxVerticalRate; /**< Max vertical rate in Hz */ ++ UInt8 uMinHorizontalRate; /**< Min horizontal rate in Hz */ ++ UInt8 uMaxHorizontalRate; /**< Max horizontal rate in Hz */ ++ UInt8 uMaxSupportedPixelClk; /**< Max suuported pixel clock rate in MHz */ ++} tmbslHdmiTxEdidSecondMD_t; ++ ++/*============================================================================*/ ++/** ++ * Other monitor descriptor structure ++ */ ++typedef struct _tmbslHdmiTxEdidOtherMD_t ++{ ++ Bool bDescRecord; /**< True when parameters of struct are available */ ++ UInt8 uOtherDescriptor[EDID_MONITOR_DESCRIPTOR_SIZE]; /**< Other monitor Descriptor */ ++} tmbslHdmiTxEdidOtherMD_t; ++ ++/*============================================================================*/ ++/** ++ * basic display parameters structure ++ */ ++typedef struct _tmbslHdmiTxEdidBDParam_t ++{ ++ UInt8 uVideoInputDef; /**< Video Input Definition */ ++ UInt8 uMaxHorizontalSize; /**< Max. Horizontal Image Size in cm */ ++ UInt8 uMaxVerticalSize; /**< Max. Vertical Image Size in cm */ ++ UInt8 uGamma; /**< Gamma */ ++ UInt8 uFeatureSupport; /**< Feature support */ ++} tmbslHdmiTxEdidBDParam_t; ++ ++/*============================================================================*/ ++/** ++ * \brief The tmbslTDA9984EdidGetAudioCapabilities() parameter type ++ */ ++typedef struct _tmbslHdmiTxEdidSad_t ++{ ++ UInt8 ModeChans; /* Bits[6:3]: EIA/CEA861 mode; Bits[2:0]: channels */ ++ UInt8 Freqs; /* Bits for each supported frequency */ ++ UInt8 Byte3; /* EIA/CEA861B p83: data depending on audio mode */ ++}tmbslHdmiTxEdidSad_t; ++ ++/*============================================================================*/ ++/** ++ * \brief struc to store parameter provide by function tmbslTDA9984EdidRequestBlockData() ++ */ ++typedef struct _tmbslHdmiTxEdidToApp_t ++{ ++ UInt8 *pRawEdid; /* pointer on a tab to store edid requested by application */ ++ Int numBlocks; /* number of edid block requested by application */ ++}tmbslHdmiTxEdidToApp_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984EdidGetVideoCapabilities() parameter types ++ */ ++/** Number of 1 byte Short Video Descriptors stored in pEdidVFmts */ ++#define HDMI_TX_SVD_MAX_CNT 113 ++ ++/** number of detailed timing descriptor stored in BSL */ ++#define NUMBER_DTD_STORED 10 ++ ++ ++ ++/** Flag set in Short Video Descriptor to indicate native format */ ++#define HDMI_TX_SVD_NATIVE_MASK 0x80 ++#define HDMI_TX_SVD_NATIVE_NOT 0x7F ++ ++/** Video capability flags */ ++enum _tmbslHdmiTxVidCap_t ++{ ++ HDMITX_VIDCAP_UNDERSCAN = 0x80, /**< Underscan supported */ ++ HDMITX_VIDCAP_YUV444 = 0x40, /**< YCbCr 4:4:4 supported */ ++ HDMITX_VIDCAP_YUV422 = 0x20, /**< YCbCr 4:2:2 supported */ ++ HDMITX_VIDCAP_UNUSED = 0x1F /**< Unused flags */ ++}; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984HdcpCheck() parameter type ++ */ ++/** HDCP check result */ ++typedef enum ++{ ++ HDMITX_HDCP_CHECK_NOT_STARTED = 0, /**< Check not started */ ++ HDMITX_HDCP_CHECK_IN_PROGRESS = 1, /**< No failures, more to do */ ++ HDMITX_HDCP_CHECK_PASS = 2, /**< Final check has passed */ ++ HDMITX_HDCP_CHECK_FAIL_FIRST = 3, /**< First check failure code */ ++ HDMITX_HDCP_CHECK_FAIL_DRIVER_STATE = 3, /**< Driver not AUTHENTICATED */ ++ HDMITX_HDCP_CHECK_FAIL_DEVICE_T0 = 4, /**< A T0 interrupt occurred */ ++ HDMITX_HDCP_CHECK_FAIL_DEVICE_RI = 5, /**< Device RI changed */ ++ HDMITX_HDCP_CHECK_FAIL_DEVICE_FSM = 6, /**< Device FSM not 10h */ ++ HDMITX_HDCP_CHECK_NUM = 7 /**< Number of check results */ ++}tmbslHdmiTxHdcpCheck_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984HdcpConfigure() parameter type ++ */ ++/** HDCP DDC slave addresses */ ++enum _tmbslHdmiTxHdcpSlaveAddress ++{ ++ HDMITX_HDCP_SLAVE_PRIMARY = 0x74, ++ HDMITX_HDCP_SLAVE_SECONDARY = 0x76 ++}; ++ ++/** HDCP transmitter modes */ ++typedef enum ++{ ++ HDMITX_HDCP_TXMODE_NOT_SET = 0, ++ HDMITX_HDCP_TXMODE_REPEATER = 1, ++ HDMITX_HDCP_TXMODE_TOP_LEVEL = 2, ++ HDMITX_HDCP_TXMODE_MAX = 2 ++}tmbslHdmiTxHdcpTxMode_t; ++ ++/** HDCP option flags */ ++typedef enum ++{ ++ HDMITX_HDCP_OPTION_FORCE_PJ_IGNORED = 0x01,/* Not set: obey PJ result */ ++ HDMITX_HDCP_OPTION_FORCE_SLOW_DDC = 0x02,/* Not set: obey BCAPS setting */ ++ HDMITX_HDCP_OPTION_FORCE_NO_1_1 = 0x04,/* Not set: obey BCAPS setting */ ++ HDMITX_HDCP_OPTION_FORCE_REPEATER = 0x08,/* Not set: obey BCAPS setting */ ++ HDMITX_HDCP_OPTION_FORCE_NO_REPEATER= 0x10,/* Not set: obey BCAPS setting */ ++ HDMITX_HDCP_OPTION_FORCE_V_EQU_VBAR = 0x20,/* Not set: obey V=V' result */ ++ HDMITX_HDCP_OPTION_FORCE_VSLOW_DDC = 0x40,/* Set: 50kHz DDC */ ++ HDMITX_HDCP_OPTION_DEFAULT = 0x00,/* All the above Not Set vals */ ++ HDMITX_HDCP_OPTION_MASK = 0x7F,/* Only these bits are allowed */ ++ HDMITX_HDCP_OPTION_MASK_BAD = 0x80 /* These bits are not allowed */ ++}tmbslHdmiTxHdcpOptions_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984HdcpDownloadKeys() parameter type ++ */ ++/** HDCP decryption mode */ ++typedef enum ++{ ++ HDMITX_HDCP_DECRYPT_DISABLE = 0, ++ HDMITX_HDCP_DECRYPT_ENABLE = 1, ++ HDMITX_HDCP_DECRYPT_MAX = 1 ++}tmbslHdmiTxDecrypt_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984HdcpHandleBSTATUS() parameter type ++ */ ++/** BSTATUS bit fields */ ++enum _tmbslHdmiTxHdcpHandleBSTATUS ++{ ++ HDMITX_HDCP_BSTATUS_HDMI_MODE = 0x1000, ++ HDMITX_HDCP_BSTATUS_MAX_CASCADE_EXCEEDED = 0x0800, ++ HDMITX_HDCP_BSTATUS_CASCADE_DEPTH = 0x0700, ++ HDMITX_HDCP_BSTATUS_MAX_DEVS_EXCEEDED = 0x0080, ++ HDMITX_HDCP_BSTATUS_DEVICE_COUNT = 0x007F ++}; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984HdcpHandleSHA_1() parameter types ++ */ ++/** KSV list sizes */ ++enum _tmbslHdmiTxHdcpHandleSHA_1 ++{ ++ HDMITX_KSV_LIST_MAX_DEVICES = 128, ++ HDMITX_KSV_BYTES_PER_DEVICE = 5 ++}; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984HotPlugGetStatus() parameter type ++ */ ++/** Current hotplug status */ ++typedef enum ++{ ++ HDMITX_HOTPLUG_INACTIVE = 0, /**< Hotplug inactive */ ++ HDMITX_HOTPLUG_ACTIVE = 1, /**< Hotplug active */ ++ HDMITX_HOTPLUG_INVALID = 2 /**< Invalid Hotplug */ ++} tmbslHdmiTxHotPlug_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984RxSenseGetStatus() parameter type ++ */ ++/** Current RX Sense status */ ++typedef enum ++{ ++ HDMITX_RX_SENSE_INACTIVE = 0, /**< RxSense inactive */ ++ HDMITX_RX_SENSE_ACTIVE = 1, /**< RxSense active */ ++ HDMITX_RX_SENSE_INVALID = 2 /**< Invalid RxSense */ ++} tmbslHdmiTxRxSense_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984HwGetCapabilities() parameter type ++ */ ++/** List of HW features that may be supported by HW */ ++typedef enum ++{ ++ HDMITX_FEATURE_HW_HDCP = 0, /**< HDCP feature */ ++ HDMITX_FEATURE_HW_SCALER = 1, /**< Scaler feature */ ++ HDMITX_FEATURE_HW_AUDIO_OBA = 2, /**< One Bit Audio feature */ ++ HDMITX_FEATURE_HW_AUDIO_DST = 3, /**< DST Audio feature */ ++ HDMITX_FEATURE_HW_AUDIO_HBR = 4, /**< HBR Audio feature */ ++ HDMITX_FEATURE_HW_HDMI_1_1 = 5, /**< HDMI 1.1 feature */ ++ HDMITX_FEATURE_HW_HDMI_1_2A = 6, /**< HDMI 1.2a feature */ ++ HDMITX_FEATURE_HW_HDMI_1_3A = 7, /**< HDMI 1.3a feature */ ++ HDMITX_FEATURE_HW_DEEP_COLOR_30 = 8, /**< 30 bits deep color support */ ++ HDMITX_FEATURE_HW_DEEP_COLOR_36 = 9, /**< 36 bits deep color support */ ++ HDMITX_FEATURE_HW_DEEP_COLOR_48 = 11, /**< 48 bits deep color support */ ++ HDMITX_FEATURE_HW_UPSAMPLER = 12, /**< Up sampler feature */ ++ HDMITX_FEATURE_HW_DOWNSAMPLER = 13, /**< Down sampler feature */ ++ HDMITX_FEATURE_HW_COLOR_CONVERSION = 14 /**< Color conversion matrix */ ++} tmbslHdmiTxHwFeature_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984Init() parameter types ++ */ ++/** Supported range of I2C slave addresses */ ++enum _tmbslHdmiTxSlaveAddress ++{ ++ HDMITX_SLAVE_ADDRESS_MIN = 1, ++ HDMITX_SLAVE_ADDRESS_MAX = 127 ++}; ++ ++/** ++ * Indexes into the funcCallback[] array of interrupt callback function pointers ++ */ ++typedef enum _tmbslHdmiTxCallbackInt ++{ ++ HDMITX_CALLBACK_INT_SECURITY = 0, /**< HDCP encryption switched off */ ++ HDMITX_CALLBACK_INT_ENCRYPT = 0, /**< HDCP encrypt as above (Obsolete) */ ++ HDMITX_CALLBACK_INT_HPD = 1, /**< Transition on HPD input */ ++ HDMITX_CALLBACK_INT_T0 = 2, /**< HDCP state machine in state T0 */ ++ HDMITX_CALLBACK_INT_BCAPS = 3, /**< BCAPS available */ ++ HDMITX_CALLBACK_INT_BSTATUS = 4, /**< BSTATUS available */ ++ HDMITX_CALLBACK_INT_SHA_1 = 5, /**< sha-1(ksv,bstatus,m0)=V' */ ++ HDMITX_CALLBACK_INT_PJ = 6, /**< pj=pj' check fails */ ++ HDMITX_CALLBACK_INT_R0 = 7, /**< R0 interrupt */ ++ HDMITX_CALLBACK_INT_SW_INT = 8, /**< SW DEBUG interrupt */ ++ HDMITX_CALLBACK_INT_RX_SENSE = 9, /**< RX SENSE interrupt */ ++ HDMITX_CALLBACK_INT_EDID_BLK_READ = 10, /**< EDID BLK READ interrupt */ ++ HDMITX_CALLBACK_INT_PLL_LOCK = 11, /**< Pll Lock (Serial or Formatter) */ ++ HDMITX_CALLBACK_INT_VS_RPT = 12, /**< VS Interrupt for Gamut packets */ ++ HDMITX_CALLBACK_INT_NUM = 13 /**< Number of callbacks */ ++}tmbslHdmiTxCallbackInt_t; ++ ++/** Pixel rate */ ++typedef enum ++{ ++ HDMITX_PIXRATE_DOUBLE = 0, /**< Double pixel rate */ ++ HDMITX_PIXRATE_SINGLE = 1, /**< Single pixel rate */ ++ HDMITX_PIXRATE_SINGLE_REPEATED = 2, /**< Single pixel repeated */ ++ HDMITX_PIXRATE_NO_CHANGE = 3, /**< No Change */ ++ HDMITX_PIXRATE_INVALID = 4 /**< Invalid */ ++} tmbslHdmiTxPixRate_t; ++ ++/** ++ * \brief The tmbslTDA9984Init() parameter structure ++ */ ++typedef struct _tmbslHdmiTxCallbackList_t ++{ ++ /** Interrupt callback function pointers (each ptr if null = not used) */ ++ ptmbslHdmiTxCallback_t funcCallback[HDMITX_CALLBACK_INT_NUM]; ++ ++} tmbslHdmiTxCallbackList_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984MatrixSetCoeffs() parameter type ++ */ ++/** Parameter structure array size */ ++enum _tmbslHdmiTxMatCoeff ++{ ++ HDMITX_MAT_COEFF_NUM = 9 ++}; ++ ++ ++/** \brief The tmbslTDA9984MatrixSetCoeffs() parameter structure */ ++/** Array of coefficients (values -1024 to +1023) */ ++typedef struct _tmbslHdmiTxMatCoeff_t ++{ ++ /** Array of coefficients (values -1024 to +1023) */ ++ Int16 Coeff[HDMITX_MAT_COEFF_NUM]; ++} tmbslHdmiTxMatCoeff_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984MatrixSetConversion() parameter type ++ */ ++/** Video input mode */ ++typedef enum ++{ ++ HDMITX_VINMODE_CCIR656 = 0, /**< ccir656 */ ++ HDMITX_VINMODE_RGB444 = 1, /**< RGB444 */ ++ HDMITX_VINMODE_YUV444 = 2, /**< YUV444 */ ++ HDMITX_VINMODE_YUV422 = 3, /**< YUV422 */ ++ HDMITX_VINMODE_NO_CHANGE = 4, /**< No change */ ++ HDMITX_VINMODE_INVALID = 5 /**< Invalid */ ++} tmbslHdmiTxVinMode_t; ++ ++/** Video output mode */ ++typedef enum ++{ ++ HDMITX_VOUTMODE_RGB444 = 0, /**< RGB444 */ ++ HDMITX_VOUTMODE_YUV422 = 1, /**< YUV422 */ ++ HDMITX_VOUTMODE_YUV444 = 2, /**< YUV444 */ ++ HDMITX_VOUTMODE_NO_CHANGE = 3, /**< No change */ ++ HDMITX_VOUTMODE_INVALID = 4 /**< Invalid */ ++} tmbslHdmiTxVoutMode_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984MatrixSetMode() parameter types ++ */ ++/** Matrix control values */ ++typedef enum ++{ ++ HDMITX_MCNTRL_ON = 0, /**< Matrix on */ ++ HDMITX_MCNTRL_OFF = 1, /**< Matrix off */ ++ HDMITX_MCNTRL_NO_CHANGE = 2, /**< Matrix unchanged */ ++ HDMITX_MCNTRL_MAX = 2, /**< Max value */ ++ HDMITX_MCNTRL_INVALID = 3 /**< Invalid */ ++} tmbslHdmiTxmCntrl_t; ++ ++/** Matrix scale values */ ++typedef enum ++{ ++ HDMITX_MSCALE_256 = 0, /**< Factor 1/256 */ ++ HDMITX_MSCALE_512 = 1, /**< Factor 1/512 */ ++ HDMITX_MSCALE_1024 = 2, /**< Factor 1/1024 */ ++ HDMITX_MSCALE_NO_CHANGE = 3, /**< Factor unchanged */ ++ HDMITX_MSCALE_MAX = 3, /**< Max value */ ++ HDMITX_MSCALE_INVALID = 4 /**< Invalid value */ ++} tmbslHdmiTxmScale_t; ++ ++/*============================================================================*/ ++/** ++ * Data Island Packet structure ++ */ ++/** Parameter structure array sizes */ ++enum _tmbslHdmiTxPkt ++{ ++ HDMITX_PKT_DATA_BYTE_CNT = 28 ++}; ++ ++/** \brief The parameter structure for tmbslTDA9984Pkt*() APIs */ ++typedef struct _tmbslHdmiTxPkt_t ++{ ++ UInt8 dataByte[HDMITX_PKT_DATA_BYTE_CNT]; /**< Packet Data */ ++} tmbslHdmiTxPkt_t; ++ ++/*============================================================================*/ ++/** ++ * \brief The Audio Infoframe Parameter structure ++ */ ++typedef struct _tmbslHdmiTxPktAif_t ++{ ++ UInt8 CodingType; /**< Coding Type 0 to 0Fh */ ++ UInt8 ChannelCount; /**< Channel Count 0 to 07h */ ++ UInt8 SampleFreq; /**< Sample Frequency 0 to 07h */ ++ UInt8 SampleSize; /**< Sample Size 0 to 03h */ ++ UInt8 ChannelAlloc; /**< Channel Allocation 0 to FFh */ ++ Bool DownMixInhibit; /**< Downmix inhibit flag 0/1 */ ++ UInt8 LevelShift; /**< Level Shift 0 to 0Fh */ ++} tmbslHdmiTxPktAif_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984PktSetMpegInfoframe() parameter types ++ */ ++/** MPEG frame types */ ++typedef enum ++{ ++ HDMITX_MPEG_FRAME_UNKNOWN = 0, /**< Unknown */ ++ HDMITX_MPEG_FRAME_I = 1, /**< i-frame */ ++ HDMITX_MPEG_FRAME_B = 2, /**< b-frame */ ++ HDMITX_MPEG_FRAME_P = 3, /**< p-frame */ ++ HDMITX_MPEG_FRAME_INVALID = 4 /**< Invalid */ ++} tmbslHdmiTxMpegFrame_t; ++ ++/** \brief The MPEG Infoframe Parameter structure */ ++typedef struct _tmbslHdmiTxPktMpeg_t ++{ ++ UInt32 bitRate; /**< MPEG bit rate in Hz */ ++ tmbslHdmiTxMpegFrame_t frameType; /**< MPEG frame type */ ++ Bool bFieldRepeat; /**< 0: new field, 1:repeated field */ ++}tmbslHdmiTxPktMpeg_t; ++ ++/*============================================================================*/ ++/** ++ * Source Product Description Infoframe Parameter types ++ */ ++/** SDI frame types */ ++typedef enum ++{ ++ HDMITX_SPD_INFO_UNKNOWN = 0, ++ HDMITX_SPD_INFO_DIGITAL_STB = 1, ++ HDMITX_SPD_INFO_DVD = 2, ++ HDMITX_SPD_INFO_DVHS = 3, ++ HDMITX_SPD_INFO_HDD_VIDEO = 4, ++ HDMITX_SPD_INFO_DVC = 5, ++ HDMITX_SPD_INFO_DSC = 6, ++ HDMITX_SPD_INFO_VIDEO_CD = 7, ++ HDMITX_SPD_INFO_GAME = 8, ++ HDMITX_SPD_INFO_PC = 9, ++ HDMITX_SPD_INFO_INVALID = 10 ++} tmbslHdmiTxSourceDev_t; ++ ++#define HDMI_TX_SPD_VENDOR_SIZE 8 ++#define HDMI_TX_SPD_DESCR_SIZE 16 ++#define HDMI_TX_SPD_LENGTH 25 ++ ++/** \brief The Source Product Description Infoframe Parameter structure */ ++typedef struct _tmbslHdmiTxPktSpd_t ++{ ++ UInt8 VendorName[HDMI_TX_SPD_VENDOR_SIZE]; /**< Vendor name */ ++ UInt8 ProdDescr[HDMI_TX_SPD_DESCR_SIZE]; /**< Product Description */ ++ tmbslHdmiTxSourceDev_t SourceDevInfo; /**< Source Device Info */ ++} tmbslHdmiTxPktSpd_t; ++ ++/*============================================================================*/ ++/** ++ * \brief The Video Infoframe Parameter structure ++ */ ++typedef struct _tmbslHdmiTxPktVif_t ++{ ++ UInt8 Colour; /**< 0 to 03h */ ++ Bool ActiveInfo; /**< 0/1 */ ++ UInt8 BarInfo; /**< 0 to 03h */ ++ UInt8 ScanInfo; /**< 0 to 03h */ ++ UInt8 Colorimetry; /**< 0 to 03h */ ++ UInt8 PictureAspectRatio; /**< 0 to 03h */ ++ UInt8 ActiveFormatRatio; /**< 0 to 0Fh */ ++ UInt8 Scaling; /**< 0 to 03h */ ++ UInt8 VidFormat; /**< 0 to 7Fh */ ++ UInt8 PixelRepeat; /**< 0 to 0Fh */ ++ UInt16 EndTopBarLine; ++ UInt16 StartBottomBarLine; ++ UInt16 EndLeftBarPixel; ++ UInt16 StartRightBarPixel; ++} tmbslHdmiTxPktVif_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984ScalerGetMode() parameter types ++ */ ++/** Scaler modes */ ++typedef enum ++{ ++ HDMITX_SCAMODE_OFF = 0, /**< Off */ ++ HDMITX_SCAMODE_ON = 1, /**< On */ ++ HDMITX_SCAMODE_AUTO = 2, /**< Auto */ ++ HDMITX_SCAMODE_NO_CHANGE = 3, /**< No change */ ++ HDMITX_SCAMODE_INVALID = 4 /**< Invalid */ ++} tmbslHdmiTxScaMode_t; ++ ++/*============================================================================*/ ++/** ++ * \brief The tmbslTDA9984ScalerGet() parameter type ++ */ ++typedef struct _tmbslHdmiTxScalerDiag_t ++{ ++ UInt16 maxBuffill_p; /**< Filling primary video buffer */ ++ UInt16 maxBuffill_d; /**< Filling video deinterlaced buffer */ ++ UInt8 maxFifofill_pi; /**< Filling primary video input FIFO */ ++ UInt8 minFifofill_po1; /**< Filling primary video output FIFO #1 */ ++ UInt8 minFifofill_po2; /**< Filling primary video output FIFO #2 */ ++ UInt8 minFifofill_po3; /**< Filling primary video output FIFO #3 */ ++ UInt8 minFifofill_po4; /**< Filling primary video output FIFO #4 */ ++ UInt8 maxFifofill_di; /**< Filling deinterlaced video input FIFO */ ++ UInt8 maxFifofill_do; /**< Filling deinterlaced video output FIFO */ ++} tmbslHdmiTxScalerDiag_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984ScalerSetCoeffs() parameter types ++ */ ++/** Scaler lookup table selection */ ++typedef enum ++{ ++ HDMITX_SCALUT_DEFAULT_TAB1 = 0, /**< Use default table 1 */ ++ HDMITX_SCALUT_DEFAULT_TAB2 = 1, /**< Use default table 2 */ ++ HDMITX_SCALUT_USE_VSLUT = 2, /**< Use vsLut parameter */ ++ HDMITX_SCALUT_INVALID = 3 /**< Invalid value */ ++} tmbslHdmiTxScaLut_t; ++ ++/** Scaler control parameter structure array size */ ++enum _tmbslHdmiTxvsLut ++{ ++ HDMITX_VSLUT_COEFF_NUM = 45 ++}; ++/*============================================================================*/ ++/** ++ * tmbslTDA9984ScalerSetFieldOrder() parameter types ++ */ ++/** IntExt values */ ++typedef enum ++{ ++ HDMITX_INTEXT_INTERNAL = 0, /**< Internal */ ++ HDMITX_INTEXT_EXTERNAL = 1, /**< External */ ++ HDMITX_INTEXT_NO_CHANGE = 2, /**< No change */ ++ HDMITX_INTEXT_INVALID = 3 /**< Invalid */ ++} tmbslHdmiTxIntExt_t; ++ ++/** TopSel values */ ++typedef enum ++{ ++ HDMITX_TOPSEL_INTERNAL = 0, /**< Internal */ ++ HDMITX_TOPSEL_VRF = 1, /**< VRF */ ++ HDMITX_TOPSEL_NO_CHANGE = 2, /**< No change */ ++ HDMITX_TOPSEL_INVALID = 3 /**< Invalid */ ++} tmbslHdmiTxTopSel_t; ++ ++/** TopTgl values */ ++typedef enum ++{ ++ HDMITX_TOPTGL_NO_ACTION = 0, /**< NO action */ ++ HDMITX_TOPTGL_TOGGLE = 1, /**< Toggle */ ++ HDMITX_TOPTGL_NO_CHANGE = 2, /**< No change */ ++ HDMITX_TOPTGL_INVALID = 3 /**< Invalid */ ++} tmbslHdmiTxTopTgl_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984ScalerSetPhase() parameter types ++ */ ++/** Phases_h values */ ++typedef enum ++{ ++ HDMITX_H_PHASES_16 = 0, /**< 15 horizontal phases */ ++ HDMITX_H_PHASES_15 = 1, /**< 16 horizontal phases */ ++ HDMITX_H_PHASES_INVALID = 2 /**< Invalid */ ++} tmbslHdmiTxHPhases_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984ScalerSetFine() parameter types ++ */ ++/** Reference pixel values */ ++enum _tmbslHdmiTxScalerFinePixelLimits ++{ ++ HDMITX_SCALER_FINE_PIXEL_MIN = 0x0000, ++ HDMITX_SCALER_FINE_PIXEL_MAX = 0x1FFF, ++ HDMITX_SCALER_FINE_PIXEL_NO_CHANGE = 0x2000, ++ HDMITX_SCALER_FINE_PIXEL_INVALID = 0x2001 ++}; ++ ++/** Reference line values */ ++enum _tmbslHdmiTxScalerFineLineLimits ++{ ++ HDMITX_SCALER_FINE_LINE_MIN = 0x0000, ++ HDMITX_SCALER_FINE_LINE_MAX = 0x07FF, ++ HDMITX_SCALER_FINE_LINE_NO_CHANGE = 0x0800, ++ HDMITX_SCALER_FINE_LINE_INVALID = 0x0801 ++}; ++/*============================================================================*/ ++/** ++ * tmbslTDA9984ScalerSetSync() parameter types ++ */ ++/** Video sync method */ ++typedef enum ++{ ++ HDMITX_VSMETH_V_H = 0, /**< V and H */ ++ HDMITX_VSMETH_V_XDE = 1, /**< V and X-DE */ ++ HDMITX_VSMETH_NO_CHANGE = 2, /**< No change */ ++ HDMITX_VSMETH_INVALID = 3 /**< Invalid */ ++} tmbslHdmiTxVsMeth_t; ++ ++/** Line/pixel counters sync */ ++typedef enum ++{ ++ HDMITX_VSONCE_EACH_FRAME = 0, /**< Sync on each frame */ ++ HDMITX_VSONCE_ONCE = 1, /**< Sync once only */ ++ HDMITX_VSONCE_NO_CHANGE = 2, /**< No change */ ++ HDMITX_VSONCE_INVALID = 3 /**< Invalid */ ++} tmbslHdmiTxVsOnce_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984TmdsSetOutputs() parameter types ++ */ ++/** TMDS output mode */ ++typedef enum ++{ ++ HDMITX_TMDSOUT_NORMAL = 0, /**< Normal outputs */ ++ HDMITX_TMDSOUT_NORMAL1 = 1, /**< Normal outputs, same as 0 */ ++ HDMITX_TMDSOUT_FORCED0 = 2, /**< Forced 0 outputs */ ++ HDMITX_TMDSOUT_FORCED1 = 3, /**< Forced 1 outputs */ ++ HDMITX_TMDSOUT_INVALID = 4 /**< Invalid */ ++} tmbslHdmiTxTmdsOut_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984TmdsSetSerializer() parameter types ++ */ ++/** Serializer phase limits */ ++enum _tmbslHdmiTxTmdsPhase ++{ ++ HDMITX_TMDSPHASE_MIN = 0, ++ HDMITX_TMDSPHASE_MAX = 15, ++ HDMITX_TMDSPHASE_INVALID = 16 ++}; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984TestSetPattern() parameter types ++ */ ++/** Test pattern types */ ++typedef enum ++{ ++ HDMITX_PATTERN_OFF = 0, /**< Insert test pattern */ ++ HDMITX_PATTERN_CBAR4 = 1, /**< Insert 4-bar colour bar */ ++ HDMITX_PATTERN_CBAR8 = 2, /**< Insert 8-bar colour bar */ ++ HDMITX_PATTERN_BLUE = 3, /**< Insert Blue screen */ ++ HDMITX_PATTERN_BLACK = 4, /**< Insert Blue screen */ ++ HDMITX_PATTERN_INVALID = 5 /**< Invalid pattern */ ++} tmbslHdmiTxTestPattern_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984TestSetMode() parameter types ++ */ ++/** Test modes */ ++typedef enum ++{ ++ HDMITX_TESTMODE_PAT = 0,/**< Insert test pattern */ ++ HDMITX_TESTMODE_656 = 1,/**< Inject CCIR-656 video via audio port */ ++ HDMITX_TESTMODE_SERPHOE = 2,/**< Activate srl_tst_ph2_o & srl_tst_ph3_o */ ++ HDMITX_TESTMODE_NOSC = 3,/**< Input nosc predivider = PLL-ref input */ ++ HDMITX_TESTMODE_HVP = 4,/**< Test high voltage protection cells */ ++ HDMITX_TESTMODE_PWD = 5,/**< Test PLLs in sleep mode */ ++ HDMITX_TESTMODE_DIVOE = 6,/**< Enable scaler PLL divider test output */ ++ HDMITX_TESTMODE_INVALID = 7 /**< Invalid test */ ++} tmbslHdmiTxTestMode_t; ++ ++/** Test states */ ++typedef enum ++{ ++ HDMITX_TESTSTATE_OFF = 0, /**< Disable the selected test */ ++ HDMITX_TESTSTATE_ON = 1, /**< Enable the selected test */ ++ HDMITX_TESTSTATE_INVALID = 2 /**< Invalid value */ ++} tmbslHdmiTxTestState_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984VideoInSetBlanking() parameter types ++ */ ++/** Blankit Source */ ++typedef enum ++{ ++ HDMITX_BLNKSRC_NOT_DE = 0, /**< Source=Not DE */ ++ HDMITX_BLNKSRC_VS_HS = 1, /**< Source=VS And HS */ ++ HDMITX_BLNKSRC_VS_NOT_HS = 2, /**< Source=VS And Not HS */ ++ HDMITX_BLNKSRC_VS_HEMB_VEMB = 3, /**< Source=Hemb And Vemb */ ++ HDMITX_BLNKSRC_NO_CHANGE = 4, /**< No change */ ++ HDMITX_BLNKSRC_INVALID = 5 /**< Invalid */ ++} tmbslHdmiTxBlnkSrc_t; ++ ++/** Blanking Codes */ ++typedef enum ++{ ++ HDMITX_BLNKCODE_ALL_0 = 0, /**< Code=All Zero */ ++ HDMITX_BLNKCODE_RGB444 = 1, /**< Code=RGB444 */ ++ HDMITX_BLNKCODE_YUV444 = 2, /**< Code=YUV444 */ ++ HDMITX_BLNKCODE_YUV422 = 3, /**< Code=YUV422 */ ++ HDMITX_BLNKCODE_NO_CHANGE = 4, /**< No change */ ++ HDMITX_BLNKCODE_INVALID = 5 /**< Invalid */ ++} tmbslHdmiTxBlnkCode_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984VideoInSetConfig() parameter types ++ */ ++/** Sample edge */ ++typedef enum ++{ ++ HDMITX_PIXEDGE_CLK_POS = 0, /**< Pixel Clock Positive Edge */ ++ HDMITX_PIXEDGE_CLK_NEG = 1, /**< Pixel Clock Negative Edge */ ++ HDMITX_PIXEDGE_NO_CHANGE = 2, /**< No Change */ ++ HDMITX_PIXEDGE_INVALID = 3 /**< Invalid */ ++} tmbslHdmiTxPixEdge_t; ++ ++/** Upsample modes */ ++typedef enum ++{ ++ HDMITX_UPSAMPLE_BYPASS = 0, /**< Bypass */ ++ HDMITX_UPSAMPLE_COPY = 1, /**< Copy */ ++ HDMITX_UPSAMPLE_INTERPOLATE = 2, /**< Interpolate */ ++ HDMITX_UPSAMPLE_AUTO = 3, /**< Auto: driver chooses best value */ ++ HDMITX_UPSAMPLE_NO_CHANGE = 4, /**< No Change */ ++ HDMITX_UPSAMPLE_INVALID = 5 /**< Invalid */ ++} tmbslHdmiTxUpsampleMode_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984VideoInSetFine() parameter types ++ */ ++/** Subpacket count */ ++typedef enum ++{ ++ HDMITX_PIXSUBPKT_FIX_0 = 0, /**< Fix At 0 */ ++ HDMITX_PIXSUBPKT_FIX_1 = 1, /**< Fix At 1 */ ++ HDMITX_PIXSUBPKT_FIX_2 = 2, /**< Fix At 2 */ ++ HDMITX_PIXSUBPKT_FIX_3 = 3, /**< Fix At 3 */ ++ HDMITX_PIXSUBPKT_SYNC_FIRST = 4, /**< First Sync value */ ++ HDMITX_PIXSUBPKT_SYNC_HEMB = 4, /**< Sync By Hemb */ ++ HDMITX_PIXSUBPKT_SYNC_DE = 5, /**< Sync By Rising Edge DE */ ++ HDMITX_PIXSUBPKT_SYNC_HS = 6, /**< Sync By Rising Edge HS */ ++ HDMITX_PIXSUBPKT_NO_CHANGE = 7, /**< No Change */ ++ HDMITX_PIXSUBPKT_INVALID = 8, /**< Invalid */ ++ HDMITX_PIXSUBPKT_SYNC_FIXED = 3 /**< Not used as a parameter value, ++ * but used internally when ++ * Fix at 0/1/2/3 values are set */ ++} tmbslHdmiTxPixSubpkt_t; ++ ++/** Toggling */ ++typedef enum ++{ ++ HDMITX_PIXTOGL_NO_ACTION = 0, /**< No Action */ ++ HDMITX_PIXTOGL_ENABLE = 1, /**< Toggle */ ++ HDMITX_PIXTOGL_NO_CHANGE = 2, /**< No Change */ ++ HDMITX_PIXTOGL_INVALID = 3 /**< Invalid */ ++} tmbslHdmiTxPixTogl_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984VideoInSetMapping() parameter types ++ */ ++/** Video input port parameter structure array size and limits */ ++enum _tmbslHdmiTxVinPortMap ++{ ++ HDMITX_VIN_PORT_MAP_TABLE_LEN = 6, ++ ++ HDMITX_VIN_PORT_SWAP_NO_CHANGE = 6, ++ HDMITX_VIN_PORT_SWAP_INVALID = 7, ++ ++ HDMITX_VIN_PORT_MIRROR_NO_CHANGE = 2, ++ HDMITX_VIN_PORT_MIRROR_INVALID = 3 ++}; ++ ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984VideoInSetSyncAuto() parameter types ++ */ ++/** Sync source - was Embedded sync HDMITX_PIXEMBSYNC_ */ ++typedef enum ++{ ++ HDMITX_SYNCSRC_EMBEDDED = 0, /**< Embedded sync */ ++ HDMITX_SYNCSRC_EXT_VREF = 1, /**< External sync Vref, Href, Fref */ ++ HDMITX_SYNCSRC_EXT_VS = 2, /**< External sync Vs, Hs */ ++ HDMITX_SYNCSRC_NO_CHANGE = 3, /**< No Change */ ++ HDMITX_SYNCSRC_INVALID = 4 /**< Invalid */ ++} tmbslHdmiTxSyncSource_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984VideoInSetSyncManual() parameter types ++ */ ++/** Video output frame pixel values */ ++enum _tmbslHdmiTxVoutFinePixelLimits ++{ ++ HDMITX_VOUT_FINE_PIXEL_MIN = 0x0000, ++ HDMITX_VOUT_FINE_PIXEL_MAX = 0x1FFF, ++ HDMITX_VOUT_FINE_PIXEL_NO_CHANGE = 0x2000, ++ HDMITX_VOUT_FINE_PIXEL_INVALID = 0x2001 ++}; ++ ++/** Video output frame line values */ ++enum _tmbslHdmiTxVoutFineLineLimits ++{ ++ HDMITX_VOUT_FINE_LINE_MIN = 0x0000, ++ HDMITX_VOUT_FINE_LINE_MAX = 0x07FF, ++ HDMITX_VOUT_FINE_LINE_NO_CHANGE = 0x0800, ++ HDMITX_VOUT_FINE_LINE_INVALID = 0x0801 ++}; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984VideoOutSetConfig() parameter types ++ */ ++/** Prefilter */ ++typedef enum ++{ ++ HDMITX_VOUT_PREFIL_OFF = 0, /**< Off */ ++ HDMITX_VOUT_PREFIL_121 = 1, /**< 121 */ ++ HDMITX_VOUT_PREFIL_109 = 2, /**< 109 */ ++ HDMITX_VOUT_PREFIL_CCIR601 = 3, /**< CCIR601 */ ++ HDMITX_VOUT_PREFIL_NO_CHANGE = 4, /**< No Change */ ++ HDMITX_VOUT_PREFIL_INVALID = 5 /**< Invalid */ ++} tmbslHdmiTxVoutPrefil_t; ++ ++/** YUV blanking */ ++typedef enum ++{ ++ HDMITX_VOUT_YUV_BLNK_16 = 0, /**< 16 */ ++ HDMITX_VOUT_YUV_BLNK_0 = 1, /**< 0 */ ++ HDMITX_VOUT_YUV_BLNK_NO_CHANGE = 2, /**< No Change */ ++ HDMITX_VOUT_YUV_BLNK_INVALID = 3 /**< Invalid */ ++} tmbslHdmiTxVoutYuvBlnk_t; ++ ++/** Video quantization range */ ++typedef enum ++{ ++ HDMITX_VOUT_QRANGE_FS = 0, /**< Full Scale */ ++ HDMITX_VOUT_QRANGE_RGB_YUV = 1, /**< RGB Or YUV */ ++ HDMITX_VOUT_QRANGE_YUV = 2, /**< YUV */ ++ HDMITX_VOUT_QRANGE_NO_CHANGE = 3, /**< No Change */ ++ HDMITX_VOUT_QRANGE_INVALID = 4 /**< Invalid */ ++} tmbslHdmiTxVoutQrange_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984VideoOutSetSync() parameter types ++ */ ++/** Video sync source */ ++typedef enum ++{ ++ HDMITX_VSSRC_INTERNAL = 0, /**< Internal */ ++ HDMITX_VSSRC_EXTERNAL = 1, /**< External */ ++ HDMITX_VSSRC_NO_CHANGE = 2, /**< No change */ ++ HDMITX_VSSRC_INVALID = 3 /**< Invalid */ ++} tmbslHdmiTxVsSrc_t; ++ ++/** Video sync toggle */ ++typedef enum ++{ ++ HDMITX_VSTGL_TABLE = 0, /**< Vs/Hs polarity from table */ ++ HDMITX_VSTGL_UNUSED_1 = 1, /**< Unused */ ++ HDMITX_VSTGL_UNUSED_2 = 2, /**< Unused */ ++ HDMITX_VSTGL_UNUSED_3 = 3, /**< Unused */ ++ HDMITX_VSTGL_NO_ACTION = 4, /**< No toggle */ ++ HDMITX_VSTGL_HS = 5, /**< Toggle Hs */ ++ HDMITX_VSTGL_VS = 6, /**< Toggle Vs */ ++ HDMITX_VSTGL_HS_VS = 7, /**< Toggle Hs & Vs */ ++ HDMITX_VSTGL_NO_CHANGE = 8, /**< No change */ ++ HDMITX_VSTGL_INVALID = 9 /**< Invalid */ ++} tmbslHdmiTxVsTgl_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984VideoSetInOut() parameter types ++ */ ++/** Pixel repetition values */ ++enum _tmbslHdmiTxPixRepeat ++{ ++ HDMITX_PIXREP_NONE = 0, /**< No repetition */ ++ HDMITX_PIXREP_MIN = 0, /**< 1 repetition */ ++ ++ HDMITX_PIXREP_0 = 0, ++ HDMITX_PIXREP_1 = 1, ++ HDMITX_PIXREP_2 = 2, ++ HDMITX_PIXREP_3 = 3, ++ HDMITX_PIXREP_4 = 4, ++ HDMITX_PIXREP_5 = 5, ++ HDMITX_PIXREP_6 = 6, ++ HDMITX_PIXREP_7 = 7, ++ HDMITX_PIXREP_8 = 8, ++ HDMITX_PIXREP_9 = 9, ++ ++ HDMITX_PIXREP_MAX = 9, /**< 10 repetitions */ ++ HDMITX_PIXREP_DEFAULT = 10, /**< Default repetitions for output format */ ++ HDMITX_PIXREP_NO_CHANGE = 11, /**< No change */ ++ HDMITX_PIXREP_INVALID = 12 /**< Invalid */ ++}; ++ ++/** Matrix modes */ ++typedef enum ++{ ++ HDMITX_MATMODE_OFF = 0, /**< Off */ ++ HDMITX_MATMODE_AUTO = 1, /**< Auto */ ++ HDMITX_MATMODE_NO_CHANGE = 2, /**< No change */ ++ HDMITX_MATMODE_INVALID = 3 /**< Invalid */ ++} tmbslHdmiTxMatMode_t; ++ ++/** Datapath bitwidth */ ++typedef enum ++{ ++ HDMITX_VOUT_DBITS_12 = 0, /**< 12 bits */ ++ HDMITX_VOUT_DBITS_8 = 1, /**< 8 bits */ ++ HDMITX_VOUT_DBITS_10 = 2, /**< 10 bits */ ++ HDMITX_VOUT_DBITS_NO_CHANGE = 3, /**< No change */ ++ HDMITX_VOUT_DBITS_INVALID = 4 /**< Invalid */ ++} tmbslHdmiTxVoutDbits_t; ++ ++/** Color depth */ ++typedef enum ++{ ++ HDMITX_COLORDEPTH_24 = 0, /**< 24 bits per pixel */ ++ HDMITX_COLORDEPTH_30 = 1, /**< 30 bits per pixel */ ++ HDMITX_COLORDEPTH_36 = 2, /**< 36 bits per pixel */ ++ HDMITX_COLORDEPTH_48 = 3, /**< 48 bits per pixel */ ++ HDMITX_COLORDEPTH_NO_CHANGE = 4, /**< No change */ ++ HDMITX_COLORDEPTH_INVALID = 5 /**< Invalid */ ++} tmbslHdmiTxColorDepth; ++ ++/** the supported transmission formats of 3D video data */ ++typedef enum ++{ ++ HDMITX_3D_NONE = 0, /**< 3D video data not present */ ++ HDMITX_3D_FRAME_PACKING = 1, /**< 3D video data Frame Packing structure */ ++ HDMITX_3D_TOP_AND_BOTTOM = 2, /**< 3D video data Top and Bottom structure */ ++ HDMITX_3D_SIDE_BY_SIDE_HALF = 3, /**< 3D video data Side by Side Half structure */ ++ HDMITX_3D_INVALID = 4 /**< Invalid */ ++} tmbslHdmiTx3DStructure_t; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9984MatrixSetInputOffset() parameter type ++ */ ++/** Parameter structure array size */ ++enum _tmbslHdmiTxMatOffset ++{ ++ HDMITX_MAT_OFFSET_NUM = 3 ++}; ++ ++/** \brief The tmbslTDA9984MatrixSetInputOffset() parameter structure */ ++typedef struct _tmbslHdmiTxMatOffset_t ++{ ++ /** Offset array (values -1024 to +1023) */ ++ Int16 Offset[HDMITX_MAT_OFFSET_NUM]; ++} tmbslHdmiTxMatOffset_t; ++ ++/** Matrix numeric limits */ ++enum _tmbslHdmiTxMatLimits ++{ ++ HDMITX_MAT_OFFSET_MIN = -1024, ++ HDMITX_MAT_OFFSET_MAX = 1023 ++}; ++ ++/*============================================================================*/ ++/** ++ * tmbslTDA9989PowerSetState() and tmbslTDA9989PowerGetState() parameter types ++ */ ++typedef enum ++{ ++ HDMITX_POWER_STATE_STAND_BY = 0, /**< Stand by mode */ ++ HDMITX_POWER_STATE_SLEEP_MODE = 1, /**< Sleep mode */ ++ HDMITX_POWER_STATE_ON = 2, /**< On mode */ ++ HDMITX_POWER_STATE_INVALID = 3 /**< Invalid format */ ++} tmbslHdmiTxPowerState_t; ++ ++/** ++ * \brief Structure describing gamut metadata packet (P0 or P1 profiles) ++ */ ++typedef struct ++{ ++ UInt8 HB[3]; /**< Header bytes (HB0, HB1 & HB2) */ ++ UInt8 PB[28]; /**< Payload bytes 0..27 */ ++} tmbslHdmiTxPktGamut_t; ++ ++ ++/** ++ * \brief Structure describing RAW AVI infoframe ++ */ ++typedef struct ++{ ++ UInt8 HB[3]; /**< Header bytes (HB0, HB1 & HB2) */ ++ UInt8 PB[28]; /**< Payload bytes 0..27 */ ++} tmbslHdmiTxPktRawAvi_t; ++ ++ ++/** Sink category */ ++typedef enum ++{ ++ HDMITX_SINK_CAT_NOT_REPEATER = 0, /**< Not repeater */ ++ HDMITX_SINK_CAT_REPEATER = 1, /**< repeater */ ++ HDMITX_SINK_CAT_INVALID = 3 /**< Invalid */ ++} tmbslHdmiTxSinkCategory_t; ++ ++ ++typedef struct ++{ ++ Bool latency_available; ++ Bool Ilatency_available; ++ UInt8 Edidvideo_latency; ++ UInt8 Edidaudio_latency; ++ UInt8 EdidIvideo_latency; ++ UInt8 EdidIaudio_latency; ++ ++} tmbslHdmiTxEdidLatency_t; ++ ++/** ++ * \brief Structure defining additional VSDB data ++ */ ++typedef struct ++{ ++ UInt8 maxTmdsClock; /* maximum supported TMDS clock */ ++ UInt8 cnc0; /* content type Graphics (text) */ ++ UInt8 cnc1; /* content type Photo */ ++ UInt8 cnc2; /* content type Cinema */ ++ UInt8 cnc3; /* content type Game */ ++ UInt8 hdmiVideoPresent; /* additional video format */ ++ UInt8 h3DPresent; /* 3D support by the HDMI Sink */ ++ UInt8 h3DMultiPresent; /* 3D multi strctures present */ ++ UInt8 imageSize; /* additional info for the values in the image size area */ ++ UInt8 hdmi3DLen; /* total length of 3D video formats */ ++ UInt8 hdmiVicLen; /* total length of extended video formats */ ++ UInt8 ext3DData[21]; /* max_len-10, ie: 31-10=21 */ ++} tmbslHdmiTxEdidExtraVsdbData_t; ++ ++/** ++ * \brief Enum defining possible quantization range ++ */ ++typedef enum ++{ ++ HDMITX_VQR_DEFAULT = 0, /* Follow HDMI spec. */ ++ HDMITX_RGB_FULL = 1, /* Force RGB FULL , DVI only */ ++ HDMITX_RGB_LIMITED = 2 /* Force RGB LIMITED , DVI only */ ++} tmbslHdmiTxVQR_t; ++ ++ ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMBSLHDMITX_TYPES_H */ ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ ++ +diff --git a/drivers/video/nxp/comps/tmbslTDA9989/inc/tmbslHdmiTx_funcMapping.h b/drivers/video/nxp/comps/tmbslTDA9989/inc/tmbslHdmiTx_funcMapping.h +new file mode 100755 +index 0000000..8fc3084 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmbslTDA9989/inc/tmbslHdmiTx_funcMapping.h +@@ -0,0 +1,141 @@ ++/** ++ * Copyright (C) 2009 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmbslHdmiTx_funcMapping.h ++ * ++ * \version $Revision: 2 $ ++ * ++*/ ++ ++ ++ ++#ifndef TMDLHDMITXTDA9989_CFG_H ++#define TMDLHDMITXTDA9989_CFG_H ++ ++#include "tmbslTDA9989_Functions.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define tmbslHdmiTxInit tmbslTDA9989Init ++#define tmbslHdmiTxEdidRequestBlockData tmbslTDA9989EdidRequestBlockData ++#define tmbslHdmiTxVideoOutSetConfig tmbslTDA9989VideoOutSetConfig ++#define tmbslHdmiTxAudioInResetCts tmbslTDA9989AudioInResetCts ++#define tmbslHdmiTxAudioInSetConfig tmbslTDA9989AudioInSetConfig ++#define tmbslHdmiTxAudioInSetCts tmbslTDA9989AudioInSetCts ++#define tmbslHdmiTxAudioOutSetChanStatus tmbslTDA9989AudioOutSetChanStatus ++#define tmbslHdmiTxAudioOutSetChanStatusMapping tmbslTDA9989AudioOutSetChanStatusMapping ++#define tmbslHdmiTxAudioOutSetMute tmbslTDA9989AudioOutSetMute ++#define tmbslHdmiTxDeinit tmbslTDA9989Deinit ++#define tmbslHdmiTxEdidGetAudioCapabilities tmbslTDA9989EdidGetAudioCapabilities ++#define tmbslHdmiTxEdidGetBlockCount tmbslTDA9989EdidGetBlockCount ++#define tmbslHdmiTxEdidGetStatus tmbslTDA9989EdidGetStatus ++#define tmbslHdmiTxEdidGetSinkType tmbslTDA9989EdidGetSinkType ++#define tmbslHdmiTxEdidGetSourceAddress tmbslTDA9989EdidGetSourceAddress ++#define tmbslHdmiTxEdidGetVideoCapabilities tmbslTDA9989EdidGetVideoCapabilities ++#define tmbslHdmiTxEdidGetVideoPreferred tmbslTDA9989EdidGetVideoPreferred ++#define tmbslHdmiTxHdcpCheck tmbslTDA9989HdcpCheck ++#define tmbslHdmiTxHdcpConfigure tmbslTDA9989HdcpConfigure ++#define tmbslHdmiTxHdcpDownloadKeys tmbslTDA9989HdcpDownloadKeys ++#define tmbslHdmiTxHdcpEncryptionOn tmbslTDA9989HdcpEncryptionOn ++#define tmbslHdmiTxHdcpGetOtp tmbslTDA9989HdcpGetOtp ++#define tmbslHdmiTxHdcpGetT0FailState tmbslTDA9989HdcpGetT0FailState ++#define tmbslHdmiTxHdcpHandleBCAPS tmbslTDA9989HdcpHandleBCAPS ++#define tmbslHdmiTxHdcpHandleBKSV tmbslTDA9989HdcpHandleBKSV ++#define tmbslHdmiTxHdcpHandleBKSVResult tmbslTDA9989HdcpHandleBKSVResult ++#define tmbslHdmiTxHdcpHandleBSTATUS tmbslTDA9989HdcpHandleBSTATUS ++#define tmbslHdmiTxHdcpHandleENCRYPT tmbslTDA9989HdcpHandleENCRYPT ++#define tmbslHdmiTxHdcpHandlePJ tmbslTDA9989HdcpHandlePJ ++#define tmbslHdmiTxHdcpHandleSHA_1 tmbslTDA9989HdcpHandleSHA_1 ++#define tmbslHdmiTxHdcpHandleSHA_1Result tmbslTDA9989HdcpHandleSHA_1Result ++#define tmbslHdmiTxHdcpHandleT0 tmbslTDA9989HdcpHandleT0 ++#define tmbslHdmiTxHdcpInit tmbslTDA9989HdcpInit ++#define tmbslHdmiTxHdcpRun tmbslTDA9989HdcpRun ++#define tmbslHdmiTxHdcpStop tmbslTDA9989HdcpStop ++#define tmbslHdmiTxHotPlugGetStatus tmbslTDA9989HotPlugGetStatus ++#define tmbslHdmiTxRxSenseGetStatus tmbslTDA9989RxSenseGetStatus ++#define tmbslHdmiTxHwGetRegisters tmbslTDA9989HwGetRegisters ++#define tmbslHdmiTxHwGetVersion tmbslTDA9989HwGetVersion ++#define tmbslHdmiTxHwGetCapabilities tmbslTDA9989HwGetCapabilities ++#define tmbslHdmiTxHwHandleInterrupt tmbslTDA9989HwHandleInterrupt ++#define tmbslHdmiTxHwSetRegisters tmbslTDA9989HwSetRegisters ++#define tmbslHdmiTxHwStartup tmbslTDA9989HwStartup ++#define tmbslHdmiTxMatrixSetCoeffs tmbslTDA9989MatrixSetCoeffs ++#define tmbslHdmiTxMatrixSetConversion tmbslTDA9989MatrixSetConversion ++#define tmbslHdmiTxMatrixSetInputOffset tmbslTDA9989MatrixSetInputOffset ++#define tmbslHdmiTxMatrixSetMode tmbslTDA9989MatrixSetMode ++#define tmbslHdmiTxMatrixSetOutputOffset tmbslTDA9989MatrixSetOutputOffset ++#define tmbslHdmiTxPktSetAclkRecovery tmbslTDA9989PktSetAclkRecovery ++#define tmbslHdmiTxPktSetAcp tmbslTDA9989PktSetAcp ++#define tmbslHdmiTxPktSetAudioInfoframe tmbslTDA9989PktSetAudioInfoframe ++#define tmbslHdmiTxPktSetGeneralCntrl tmbslTDA9989PktSetGeneralCntrl ++#define tmbslHdmiTxPktSetIsrc1 tmbslTDA9989PktSetIsrc1 ++#define tmbslHdmiTxPktSetIsrc2 tmbslTDA9989PktSetIsrc2 ++#define tmbslHdmiTxPktSetMpegInfoframe tmbslTDA9989PktSetMpegInfoframe ++#define tmbslHdmiTxPktSetNullInsert tmbslTDA9989PktSetNullInsert ++#define tmbslHdmiTxPktSetNullSingle tmbslTDA9989PktSetNullSingle ++#define tmbslHdmiTxPktSetSpdInfoframe tmbslTDA9989PktSetSpdInfoframe ++#define tmbslHdmiTxPktSetVideoInfoframe tmbslTDA9989PktSetVideoInfoframe ++#define tmbslHdmiTxPktSetVsInfoframe tmbslTDA9989PktSetVsInfoframe ++#define tmbslHdmiTxPktSetRawVideoInfoframe tmbslTDA9989PktSetRawVideoInfoframe ++#define tmbslHdmiTxPowerGetState tmbslTDA9989PowerGetState ++#define tmbslHdmiTxPowerSetState tmbslTDA9989PowerSetState ++#define tmbslHdmiTxReset tmbslTDA9989Reset ++#define tmbslHdmiTxScalerGet tmbslTDA9989ScalerGet ++#define tmbslHdmiTxScalerGetMode tmbslTDA9989ScalerGetMode ++#define tmbslHdmiTxScalerInDisable tmbslTDA9989ScalerInDisable ++#define tmbslHdmiTxScalerSetCoeffs tmbslTDA9989ScalerSetCoeffs ++#define tmbslHdmiTxScalerSetFieldOrder tmbslTDA9989ScalerSetFieldOrder ++#define tmbslHdmiTxScalerSetFine tmbslTDA9989ScalerSetFine ++#define tmbslHdmiTxScalerSetPhase tmbslTDA9989ScalerSetPhase ++#define tmbslHdmiTxScalerSetLatency tmbslTDA9989ScalerSetLatency ++#define tmbslHdmiTxScalerSetSync tmbslTDA9989ScalerSetSync ++#define tmbslHdmiTxSwGetVersion tmbslTDA9989SwGetVersion ++#define tmbslHdmiTxSysTimerWait tmbslTDA9989SysTimerWait ++#define tmbslHdmiTxTmdsSetOutputs tmbslTDA9989TmdsSetOutputs ++#define tmbslHdmiTxTmdsSetSerializer tmbslTDA9989TmdsSetSerializer ++#define tmbslHdmiTxTestSetPattern tmbslTDA9989TestSetPattern ++#define tmbslHdmiTxTestSetMode tmbslTDA9989TestSetMode ++#define tmbslHdmiTxVideoInSetBlanking tmbslTDA9989VideoInSetBlanking ++#define tmbslHdmiTxVideoInSetConfig tmbslTDA9989VideoInSetConfig ++#define tmbslHdmiTxVideoInSetFine tmbslTDA9989VideoInSetFine ++#define tmbslHdmiTxVideoInSetMapping tmbslTDA9989VideoInSetMapping ++#define tmbslHdmiTxSetVideoPortConfig tmbslTDA9989SetVideoPortConfig ++#define tmbslHdmiTxSetAudioPortConfig tmbslTDA9989SetAudioPortConfig ++#define tmbslHdmiTxSetAudioClockPortConfig tmbslTDA9989SetAudioClockPortConfig ++#define tmbslHdmiTxVideoInSetSyncAuto tmbslTDA9989VideoInSetSyncAuto ++#define tmbslHdmiTxVideoInSetSyncManual tmbslTDA9989VideoInSetSyncManual ++#define tmbslHdmiTxVideoOutDisable tmbslTDA9989VideoOutDisable ++#define tmbslHdmiTxVideoOutSetSync tmbslTDA9989VideoOutSetSync ++#define tmbslHdmiTxVideoSetInOut tmbslTDA9989VideoSetInOut ++#define tmbslHdmiTxFlagSwInt tmbslTDA9989FlagSwInt ++#define tmbslHdmiTxSet5vpower tmbslTDA9989Set5vpower ++#define tmbslHdmiTxEnableCallback tmbslTDA9989EnableCallback ++#define tmbslHdmiTxSetColorDepth tmbslTDA9989SetColorDepth ++#define tmbslHdmiTxSetDefaultPhase tmbslTDA9989SetDefaultPhase ++#define tmbslHdmiTxPktFillGamut tmbslTDA9989PktFillGamut ++#define tmbslHdmiTxPktSendGamut tmbslTDA9989PktSendGamut ++#define tmbslHdmiTxEdidGetMonitorDescriptors tmbslTDA9989EdidGetMonitorDescriptors ++#define tmbslHdmiTxEdidGetDetailedTimingDescriptors tmbslTDA9989EdidGetDetailedTimingDescriptors ++#define tmbslHdmiTxEdidGetBasicDisplayParam tmbslTDA9989EdidGetBasicDisplayParam ++#define tmbslHdmiTxHdcpGetSinkCategory tmbslTDA9989HdcpGetSinkCategory ++#define tmbslHdmiTxEdidGetLatencyInfo tmbslTDA9989EdidGetLatencyInfo ++#define tmbslHdmiTxEdidGetExtraVsdbData tmbslTDA9989EdidGetExtraVsdbData ++#ifdef TMFL_TDA19989 ++#define tmbslHdmiTxHdcpPowerDown tmbslTDA9989HdcpPowerDown ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMDLHDMITXTDA9989_CFG_H */ ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmbslTDA9989/inc/tmbslTDA9989_Functions.h b/drivers/video/nxp/comps/tmbslTDA9989/inc/tmbslTDA9989_Functions.h +new file mode 100755 +index 0000000..0f9a3e3 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmbslTDA9989/inc/tmbslTDA9989_Functions.h +@@ -0,0 +1,3060 @@ ++/** ++ * Copyright (C) 2009 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmbslTDA9989_functions.h ++ * ++ * \version $Revision: 2 $ ++ * ++ * ++*/ ++ ++#ifndef TMBSLTDA9989_FUNCTIONS_H ++#define TMBSLTDA9989_FUNCTIONS_H ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#include "tmNxCompId.h" ++#include "tmbslHdmiTx_types.h" ++ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*============================================================================*/ ++/* EXTERN FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/** ++ \brief Reset the Clock Time Stamp generator in HDMI mode only ++ ++ \param[in] txUnit Transmitter unit number ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: in DVI mode ++ */ ++tmErrorCode_t ++tmbslTDA9989AudioInResetCts ++( ++ tmUnitSelect_t txUnit ++); ++ ++/** ++ \brief Set audio input configuration in HDMI mode only ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] aFmt Audio input format ++ \param[in] i2sFormat I2s format type ++ \param[in] chanI2s I2S channel allocation ++ \param[in] chanDsd DSD channel allocation ++ \param[in] clkPolDsd DSD clock polarity ++ \param[in] swapDsd DSD data swap ++ \param[in] layout Sample layout ++ \param[in] latency_rd Audio FIFO read latency ++ \param[in] dstRate Dst rate (not used) ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: in DVI mode ++ */ ++tmErrorCode_t ++tmbslTDA9989AudioInSetConfig ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxaFmt_t aFmt, ++ tmbslHdmiTxI2sFor_t i2sFormat, ++ UInt8 chanI2s, ++ UInt8 chanDsd, ++ tmbslHdmiTxClkPolDsd_t clkPolDsd, ++ tmbslHdmiTxSwapDsd_t swapDsd, ++ UInt8 layout, ++ UInt16 latency_rd, ++ tmbslHdmiTxDstRate_t dstRate ++); ++ ++ ++/** ++ \brief Set the Clock Time Stamp generator in HDMI mode only ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] ctsRef Clock Time Stamp reference source ++ \param[in] afs Audio input sample frequency ++ \param[in] voutFmt Video output format ++ \param[in] voutFreq Vertical output frequency ++ \param[in] uCts Manual Cycle Time Stamp ++ \param[in] uCtsX Clock Time Stamp factor x ++ \param[in] ctsK Clock Time Stamp predivider k ++ \param[in] ctsM Clock Time Stamp postdivider m ++ \param[in] dstRate Dst rate (not used) ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: in DVI mode ++ */ ++tmErrorCode_t ++tmbslTDA9989AudioInSetCts ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxctsRef_t ctsRef, ++ tmbslHdmiTxafs_t afs, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ tmbslHdmiTxVfreq_t voutFreq, ++ UInt32 uCts, ++ UInt16 uCtsX, ++ tmbslHdmiTxctsK_t ctsK, ++ tmbslHdmiTxctsM_t ctsM, ++ tmbslHdmiTxDstRate_t dstRate ++); ++ ++/** ++ \brief Set the Channel Status Bytes 0,1,3 & 4 ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] copyright Byte 0 Copyright bit (bit2) ++ \param[in] formatInfo Byte 0 Audio sample format (bit1) and additional info (bit345) ++ \param[in] categoryCode Byte 1 Category code (bits8-15) ++ \param[in] sampleFreq Byte 3 Sample Frequency (bits24-27) ++ \param[in] clockAccuracy Byte 3 Clock Accuracy (bits38-31) ++ \param[in] maxWordLength Byte 4 Maximum word length (bit32) ++ \param[in] wordLength Byte 4 Word length (bits33-35) ++ \param[in] origSampleFreq Byte 4 Original Sample Frequency (bits36-39) ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: in DVI mode ++ ++ \note The consumer use bit (bit0) and Mode bits (bits6-7) are forced to zero. ++ Use tmbslTDA9989AudioOutSetChanStatusMapping to set CS Byte 2. ++ ++ */ ++tmErrorCode_t ++tmbslTDA9989AudioOutSetChanStatus ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxAudioData_t pcmIdentification, ++ tmbslHdmiTxCSformatInfo_t formatInfo, ++ tmbslHdmiTxCScopyright_t copyright, ++ UInt8 categoryCode, ++ tmbslHdmiTxafs_t sampleFreq, ++ tmbslHdmiTxCSclkAcc_t clockAccuracy, ++ tmbslHdmiTxCSmaxWordLength_t maxWordLength, ++ tmbslHdmiTxCSwordLength_t wordLength, ++ tmbslHdmiTxCSorigAfs_t origSampleFreq ++); ++ ++/** ++ \brief Set the Channel Status Byte2 for Audio Port 0 ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] sourceLeft L Source Number: 0 don't take into account, 1-15 ++ \param[in] channelLeft L Channel Number: 0 don't take into account, 1-15 ++ \param[in] sourceRight R Source Number: 0 don't take into account, 1-15 ++ \param[in] channelRight R Channel Number: 0 don't take into account, 1-15 ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: in DVI mode ++ ++ \note Use tmbslTDA9989AudioOutSetChanStatus to set all other CS bytes ++ This function only sets the mapping for Audio Port 0. ++ ++ */ ++tmErrorCode_t ++tmbslTDA9989AudioOutSetChanStatusMapping ++( ++ tmUnitSelect_t txUnit, ++ UInt8 sourceLeft[4], ++ UInt8 channelLeft[4], ++ UInt8 sourceRight[4], ++ UInt8 channelRight[4] ++); ++ ++/** ++ \brief Mute or un-mute the audio output by controlling the audio FIFO, ++ in HDMI mode only ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] aMute Audio mute: On, Off ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: in DVI mode ++ ++ \note tmbslTDA9989PktSetGeneralCntrl must be used to control the audio ++ mute in outgoing data island packets ++ ++ */ ++tmErrorCode_t ++tmbslTDA9989AudioOutSetMute ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxaMute_t aMute ++); ++ ++ ++/*============================================================================*/ ++/** ++ \brief Disable an HDMI Transmitter output and destroy its driver ++ instance ++ ++ \param[in] txUnit Transmitter unit number ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: the unit is not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989Deinit ++( ++ tmUnitSelect_t txUnit ++); ++ ++ ++/** ++ \brief Get supported audio format(s) from previously read EDID ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pEdidAFmts Pointer to the array of structures to receive the ++ supported Short Audio Descriptors ++ \param[in] aFmtLength Number of SADs supported in buffer pEdidAFmts, ++ up to HDMI_TX_SAD_MAX_CNT ++ \param[out] pAFmtsAvail Pointer to receive the number of SADs available ++ \param[out] pAudioFlags Pointer to the byte to receive the Audio Capability ++ Flags ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++ \note \verbatim ++ Supported Short Audio Descriptors array: ++ EdidAFmts[0].ModeChans SAD 1 - Mode byte ++ EdidAFmts[0].Freqs SAD 1 - Frequencies byte ++ EdidAFmts[0].Byte3 SAD 1 - Byte 3 ++ ... ++ EdidAFmts[n-1].ModeChans SAD n - Mode byte ++ EdidAFmts[n-1].Freqs SAD n - Frequencies byte ++ EdidAFmts[n-1].Byte3 SAD n - Byte 3 ++ (Where n is the smaller of aFmtLength and pAFmtAvail) ++ \endverbatim ++ */ ++tmErrorCode_t ++tmbslTDA9989EdidGetAudioCapabilities ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxEdidSad_t *pEdidAFmts, ++ UInt aFmtLength, ++ UInt *pAFmtsAvail, ++ UInt8 *pAudioFlags ++); ++ ++/*============================================================================*/ ++/** ++ \brief Get the EDID block count ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] puEdidBlockCount Pointer to data byte in which to return the ++ block count ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ */ ++tmErrorCode_t ++tmbslTDA9989EdidGetBlockCount ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *puEdidBlockCount ++); ++ ++/*============================================================================*/ ++/** ++ \brief Get the EDID status ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] puEdidBlockCount Pointer to data byte in which to return the ++ edid status ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ */ ++tmErrorCode_t ++tmbslTDA9989EdidGetStatus ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *puEdidStatus ++); ++ ++/** ++ \brief Request read of EDID blocks from the sink device via DDC ++ function not synchronous edid will available on ++ EDID_BLK_READ callback ++ ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pRawEdid Pointer to a buffer supplied by the caller to accept ++ the raw EDID data. ++ \param[in] numBlocks Number of blocks to read ++ \param[in] lenRawEdid Length in bytes of the supplied buffer ++ \param[out] pEdidStatus Pointer to status value E_EDID_READ or E_EDID_ERROR ++ valid only when the return value is TM_OK ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE: EDID not read ++ ++ \note NA ++ ++ */ ++ ++tmErrorCode_t ++tmbslTDA9989EdidRequestBlockData ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pRawEdid, ++ Int numBlocks, /* Only relevant if pRawEdid valid */ ++ Int lenRawEdid /* Only relevant if pRawEdid valid */ ++); ++ ++ ++/** ++ \brief Get Sink Type by analysis of EDID content ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pSinkType Pointer to returned Sink Type: DVI or HDMI ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : edid not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_NULL_CONNECTION: HPD pin is inactive ++ ++ \sa tmbslTDA9989EdidGetBlockData ++ */ ++tmErrorCode_t ++tmbslTDA9989EdidGetSinkType ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxSinkType_t *pSinkType ++); ++ ++/*============================================================================*/ ++/** ++ \brief Get Source Physical Address by analysis of EDID content ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pSourceAddress Pointer to returned Source Physical Address (ABCDh) ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++ \sa tmbslTDA9989EdidGetBlockData ++ */ ++tmErrorCode_t ++tmbslTDA9989EdidGetSourceAddress ++( ++ tmUnitSelect_t txUnit, ++ UInt16 *pSourceAddress ++); ++ ++/** ++ \brief Get supported video format(s) from previously read EDID ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pEdidVFmts Pointer to the array to receive the supported Short ++ Video Descriptors ++ \param[in] vFmtLength Number of SVDs supported in buffer pEdidVFmts, ++ up to HDMI_TX_SVD_MAX_CNT ++ \param[out] pVFmtsAvail Pointer to receive the number of SVDs available ++ \param[out] pVidFlags Ptr to the byte to receive Video Capability Flags ++ b7: underscan supported ++ b6: YCbCr 4:4:4 supported ++ b5: YCbCr 4:2:2 supported ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_NULL_CONNECTION: HPD pin is inactive ++ ++ \note \verbatim ++ Supported Short Video Descriptors array: ++ (HDMI_TX_SVD_NATIVE_MASK bit set to indicate native format) ++ EdidVFmts[0] EIA/CEA Short Video Descriptor 1, or 0 ++ ... ++ EdidVFmts[n-1] EIA/CEA Short Video Descriptor 32, or 0 ++ (Where n is the smaller of vFmtLength and pVFmtAvail) ++ \endverbatim ++ \sa tmbslTDA9989EdidGetBlockData ++ */ ++tmErrorCode_t ++tmbslTDA9989EdidGetVideoCapabilities ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pEdidVFmts, ++ UInt vFmtLength, ++ UInt *pVFmtsAvail, ++ UInt8 *pVidFlags ++); ++/** ++ \brief Get detailed timing descriptor from previously read EDID ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pEdidDTD Pointer to the array to receive the Detailed timing descriptor ++ ++ \param[in] nb_size Number of DTD supported in buffer pEdidDTD ++ ++ \param[out] pDTDAvail Pointer to receive the number of DTD available ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++*/ ++tmErrorCode_t ++tmbslTDA9989EdidGetDetailedTimingDescriptors ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxEdidDtd_t *pEdidDTD, ++ UInt8 nb_size, ++ UInt8 *pDTDAvail ++); ++ ++/** ++ \brief Get detailed Monitor descriptor from previously read EDID ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pEdidFirstMD Pointer to the First Monitor descriptor ++ \param[out] pEdidSecondMD Pointer to the Second Monitor descriptor ++ \param[out] pEdidOtherMD Pointer to the Other Monitor descriptor ++ \param[in] sizeOtherMD Not used ++ \param[out] pOtherMDAvail Not used ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++*/ ++tmErrorCode_t ++tmbslTDA9989EdidGetMonitorDescriptors ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxEdidFirstMD_t *pEdidFirstMD, ++ tmbslHdmiTxEdidSecondMD_t *pEdidSecondMD, ++ tmbslHdmiTxEdidOtherMD_t *pEdidOtherMD, ++ UInt8 sizeOtherMD, ++ UInt8 *pOtherMDAvail ++); ++ ++/** ++ \brief Get basic display parameters from previously read EDID ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pEdidBDParam Pointer to the Basic Display Parameters ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++*/ ++tmErrorCode_t ++tmbslTDA9989EdidGetBasicDisplayParam ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxEdidBDParam_t *pEdidBDParam ++); ++ ++ ++/** ++ \brief Get preferred video format from previously read EDID ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pEdidDTD Pointer to the structure to receive the Detailed ++ Timing Descriptor parameters of the preferred video ++ format ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_NULL_CONNECTION: HPD pin is inactive ++ ++ \note \verbatim ++ Detailed Timing Descriptor parameters output structure: ++ UInt16 uPixelClock Pixel Clock (MHz/10,000) ++ UInt16 uHActivePixels Horizontal Active Pixels ++ UInt16 uHBlankPixels Horizontal Blanking Pixels ++ UInt16 uVActiveLines Vertical Active Lines ++ UInt16 uVBlankLines Vertical Blanking Lines ++ UInt16 uHSyncOffset Horizontal Sync Offset (Pixels) ++ UInt16 uHSyncWidth Horizontal Sync Pulse Width (Pixels) ++ UInt16 uVSyncOffset Vertical Sync Offset (Lines) ++ UInt16 uVSyncWidth Vertical Sync Pulse Width (Lines) ++ UInt16 uHImageSize Horizontal Image Size (mm) ++ UInt16 uVImageSize Vertical Image Size (mm) ++ UInt16 uHBorderPixels Horizontal Border (Pixels) ++ UInt16 uVborderPixels Vertical Border (Pixels) ++ UInt8 Flags Interlace/sync info ++ \endverbatim ++ \sa tmbslTDA9989EdidGetBlockData ++ */ ++tmErrorCode_t ++tmbslTDA9989EdidGetVideoPreferred ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxEdidDtd_t *pEdidDTD ++); ++ ++/** ++ \brief Check the result of an HDCP encryption attempt, called at ++ intervals (set by uTimeSinceLastCallMs) after tmbslTDA9989HdcpRun ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] uTimeSinceLastCallMs Time in ms since this was last called ++ \param[out] pResult The outcome of the check ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP ++ */ ++tmErrorCode_t ++tmbslTDA9989HdcpCheck ++( ++ tmUnitSelect_t txUnit, ++ UInt16 uTimeSinceLastCallMs, ++ tmbslHdmiTxHdcpCheck_t *pResult ++); ++ ++/** ++ \brief Configure various HDCP parameters ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] slaveAddress DDC I2C slave address ++ \param[in] txMode Mode of our transmitter device ++ \param[in] options Options flags to control behaviour of HDCP ++ \param[in] uCheckIntervalMs HDCP check interval in milliseconds ++ \param[in] uChecksToDo Number of HDCP checks to do after HDCP starts ++ A value of 2 or more is valid for checking ++ May be set to 0 to disabling checking ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP ++ ++ \note Must be called before all other HDCP APIs ++ */ ++tmErrorCode_t ++tmbslTDA9989HdcpConfigure ++( ++ tmUnitSelect_t txUnit, ++ UInt8 slaveAddress, ++ tmbslHdmiTxHdcpTxMode_t txMode, ++ tmbslHdmiTxHdcpOptions_t options, ++ UInt16 uCheckIntervalMs, ++ UInt8 uChecksToDo ++); ++ ++/** ++ \brief Download keys and AKSV data from OTP memory to the device ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] seed Seed value ++ \param[in] keyDecryption State of key decryption 0 to 1 (disabled, enabled) ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP ++ */ ++tmErrorCode_t ++tmbslTDA9989HdcpDownloadKeys ++( ++ tmUnitSelect_t txUnit, ++ UInt16 seed, ++ tmbslHdmiTxDecrypt_t keyDecryption ++); ++ ++/*============================================================================*/ ++/** ++ \brief Switch HDCP encryption on or off without disturbing Infoframes ++ (Not normally used) ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] bOn Encryption state: 1=on, 0=off ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP ++*/ ++tmErrorCode_t ++tmbslTDA9989HdcpEncryptionOn ++( ++ tmUnitSelect_t txUnit, ++ Bool bOn ++); ++ ++/*============================================================================*/ ++/** ++ \brief Get HDCP OTP registers ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] otpAddress OTP start address 0-FF ++ \param[out] pOtpData Ptr to a three-byte array to hold the data read: ++ [0] = OTP_DATA_MSB ++ [1] = OTP_DATA_ISB ++ [2] = OTP_DATA_LSB ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP ++*/ ++tmErrorCode_t ++tmbslTDA9989HdcpGetOtp ++( ++ tmUnitSelect_t txUnit, ++ UInt8 otpAddress, ++ UInt8 *pOtpData ++); ++ ++/*============================================================================*/ ++/** ++ \brief Return the failure state that caused the last T0 interrupt ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pFailState Ptr to the unit's last T0 fail state ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP ++*/ ++tmErrorCode_t ++tmbslTDA9989HdcpGetT0FailState ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pFailState ++); ++ ++/*============================================================================*/ ++/** ++ \brief Handle BCAPS interrupt ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ ++ \param[in] txUnit Transmitter unit number ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ ++ \note The user BCAPS interrupt handler (registered with ++ tmbslTDA9989Init) calls this API before calling ++ tmbslTDA9989HdcpHandleBKSV ++*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandleBCAPS ++( ++ tmUnitSelect_t txUnit ++); ++ ++/*============================================================================*/ ++/** ++ \brief Read BKSV registers ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pBksv Pointer to 5-byte BKSV array returned to caller ++ (1st byte is MSB) ++ \param[out] pbCheckRequired Pointer to a result variable to tell the caller ++ whether to check for BKSV in a revocation list: ++ 0 or 1 (check not required, check required) ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ ++ \note The user BCAPS interrupt handler (registered with ++ tmbslTDA9989Init) calls this API after calling ++ tmbslTDA9989HdcpHandleBCAPS ++*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandleBKSV ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pBksv, ++ Bool *pbCheckRequired ++); ++ ++/*============================================================================*/ ++/** ++ \brief Declare BKSV result to be secure or not secure ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] bSecure Result of user's check of BKSV against a ++ revocation list: ++ 0 (not secure: BKSV found in revocation list) ++ 1 (secure: BKSV not found in revocation list) ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ ++ \note The user BCAPS interrupt handler (registered with ++ tmbslTDA9989Init) calls this API after calling ++ tmbslTDA9989HdcpHandleBKSV ++*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandleBKSVResult ++( ++ tmUnitSelect_t txUnit, ++ Bool bSecure ++); ++ ++/** ++ \brief Handle BSTATUS interrupt ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pBstatus Pointer to 16-bit BSTATUS value returned to caller ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ ++ \note Called by user's BSTATUS interrupt handler registered with ++ tmbslTDA9989Init ++*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandleBSTATUS ++( ++ tmUnitSelect_t txUnit, ++ UInt16 *pBstatus ++); ++ ++/*============================================================================*/ ++/** ++ \brief Handle ENCRYPT interrupt ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ ++ \note Called by user's ENCRYPT interrupt handler registered with ++ tmbslTDA9989Init ++*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandleENCRYPT ++( ++ tmUnitSelect_t txUnit ++); ++ ++/*============================================================================*/ ++/** ++ \brief Handle PJ interrupt ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ ++ \param[in] txUnit Transmitter unit number ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ ++ \note Called by user's PJ interrupt handler registered with ++ tmbslTDA9989Init ++*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandlePJ ++( ++ tmUnitSelect_t txUnit ++); ++ ++/** ++ \brief Handle SHA-1 interrupt ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] maxKsvDevices Maximum number of 5-byte devices that will fit ++ in *pKsvList: 0 to 128 devices ++ If 0, no KSV read is done and it is treated as ++ secure ++ \param[out] pKsvList Pointer to KSV list array supplied by caller: ++ Sets of 5-byte KSVs, 1 per device, 1st byte is ++ LSB of 1st device ++ May be null if maxKsvDevices is 0 ++ \param[out] pnKsvDevices Pointer to number of KSV devices copied to ++ *pKsvList: 0 to 128 ++ If 0, no KSV check is needed and it is treated ++ as secure ++ May be null if maxKsvDevices is 0 ++ \param[out] pDepth Connection tree depth ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: two parameters disagree ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ ++ \note Called by user's SHA-1 interrupt handler registered with ++ tmbslTDA9989Init ++*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandleSHA_1 ++( ++ tmUnitSelect_t txUnit, ++ UInt8 maxKsvDevices, ++ UInt8 *pKsvList, ++ UInt8 *pnKsvDevices, ++ UInt8 *pDepth ++); ++ ++/*============================================================================*/ ++/** ++ \brief Declare KSV list result to be secure or not secure ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] bSecure Result of user's check of KSV list against a ++ revocation list: ++ 0 (not secure: one or more KSVs are in r.list) ++ 1 (secure: no KSV found in revocation list) ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ ++ \note The user SHA_1 interrupt handler (registered with ++ tmbslTDA9989Init) calls this API after calling ++ tmbslTDA9989HdcpHandleSHA_1 ++*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandleSHA_1Result ++( ++ tmUnitSelect_t txUnit, ++ Bool bSecure ++); ++ ++/*============================================================================*/ ++/** ++ \brief Handle T0 interrupt ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ ++ \note Called by user's T0 interrupt handler registered with ++ tmbslTDA9989Init ++*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandleT0 ++( ++ tmUnitSelect_t txUnit ++); ++ ++/*============================================================================*/ ++/** ++ \brief Prepare for HDCP operation ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] voutFmt Video output format ++ \param[in] voutFreq Vertical output frequency ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP ++ ++ \note Must be called before tmbslTDA9989HdcpRun ++*/ ++tmErrorCode_t ++tmbslTDA9989HdcpInit ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ tmbslHdmiTxVfreq_t voutFreq ++); ++ ++/*============================================================================*/ ++/** ++ \brief Start HDCP operation ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP ++ ++ \note Must be called after tmbslTDA9989HdcpInit ++*/ ++tmErrorCode_t ++tmbslTDA9989HdcpRun ++( ++ tmUnitSelect_t txUnit ++); ++ ++/*============================================================================*/ ++/** ++ \brief Stop HDCP operation, and cease encrypting the output ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP ++ ++ \note This will trigger an Encrypt interrupt ++*/ ++tmErrorCode_t ++tmbslTDA9989HdcpStop ++( ++ tmUnitSelect_t txUnit ++); ++/** ++ \brief Get the hot plug input status last read by tmbslTDA9989Init ++ or tmbslTDA9989HwHandleInterrupt ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pHotPlugStatus Pointer to returned Hot Plug Detect status ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ */ ++tmErrorCode_t ++tmbslTDA9989HotPlugGetStatus ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxHotPlug_t *pHotPlugStatus, ++ Bool client /* Used to determine whether the request comes from the application */ ++); ++ ++/** ++ \brief Get the rx sense input status last read by tmbslTDA9989Init ++ or tmbslTDA9989HwHandleInterrupt ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pRxSenseStatus Pointer to returned Rx Sense Detect status ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ */ ++tmErrorCode_t ++tmbslTDA9989RxSenseGetStatus ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxRxSense_t *pRxSenseStatus, ++ Bool client /* Used to determine whether the request comes from the application */ ++); ++ ++/*============================================================================*/ ++/** ++ \brief Get one or more hardware I2C register values ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] regPage The device register's page: 00h, 01h, 02h, 11h, 12h ++ \param[in] regAddr The starting register address on the page: 0 to FFh ++ \param[out] pRegBuf Pointer to buffer to receive the register data ++ \param[in] nRegs Number of contiguous registers to read: 1 to 254 ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989HwGetRegisters ++( ++ tmUnitSelect_t txUnit, ++ Int regPage, ++ Int regAddr, ++ UInt8 *pRegBuf, ++ Int nRegs ++); ++ ++/*============================================================================*/ ++/** ++ \brief Get the transmitter device version read at initialization ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] puDeviceVersion Pointer to returned hardware version ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ */ ++tmErrorCode_t ++tmbslTDA9989HwGetVersion ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *puDeviceVersion ++); ++ ++ ++/** ++ \brief Get the transmitter device feature read at initialization ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] deviceFeature Hardware feature to check ++ \param[out] pFeatureSupported Hardware feature supported or not ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989HwGetCapabilities ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxHwFeature_t deviceCapability, ++ Bool *pFeatureSupported ++); ++ ++ ++/*============================================================================*/ ++/** ++ \brief Handle all hardware interrupts from a transmitter unit ++ ++ \param[in] txUnit Transmitter unit number ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ \note This function must be called at task level not interrupt level, ++ as I2C access is required ++ */ ++tmErrorCode_t ++tmbslTDA9989HwHandleInterrupt ++( ++ tmUnitSelect_t txUnit ++); ++ ++ ++/*============================================================================*/ ++/** ++ \brief Set one or more hardware I2C registers ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] regPage The device register's page: 00h, 01h, 02h, 11h, 12h ++ \param[in] regAddr The starting register address on the page: 0 to FFh ++ \param[in] pRegBuf Ptr to buffer from which to write the register data ++ \param[in] nRegs Number of contiguous registers to write: 0 to 254. ++ The page register (255) may not be written - it is ++ written to automatically here. If nRegs is 0, the ++ page register is the only register written. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989HwSetRegisters ++( ++ tmUnitSelect_t txUnit, ++ Int regPage, ++ Int regAddr, ++ UInt8 *pRegBuf, ++ Int nRegs ++); ++ ++ ++/*============================================================================*/ ++/** ++ \brief Handle hardware startup by resetting Device Instance Data ++ */ ++void ++tmbslTDA9989HwStartup ++( ++ void ++); ++ ++/** ++ \brief Create an instance of an HDMI Transmitter: initialize the ++ driver, reset the transmitter device and get the current ++ Hot Plug state ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] uHwAddress Device I2C slave address ++ \param[in] sysFuncWrite System function to write I2C ++ \param[in] sysFuncRead System function to read I2C ++ \param[in] sysFuncEdidRead System function to read EDID blocks via I2C ++ \param[in] sysFuncTimer System function to run a timer ++ \param[in] funcIntCallbacks Pointer to interrupt callback function list ++ The list pointer is null for no callbacks; ++ each pointer in the list may also be null. ++ \param[in] bEdidAltAddr Use alternative i2c address for EDID data ++ register between Driver and TDA9983/2: ++ 0 - use default address (A0) ++ 1 - use alternative address (A2) ++ \param[in] vinFmt EIA/CEA Video input format: 1 to 31, 0 = No Change ++ \param[in] pixRate Single data (repeated or not) or double data rate ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: the unit number is wrong or ++ the transmitter instance is already initialised ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMBSL_ERR_HDMI_INIT_FAILED: the unit instance is already ++ initialised ++ - TMBSL_ERR_HDMI_COMPATIBILITY: the driver is not compatiable ++ with the internal device version code ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989Init ++( ++ tmUnitSelect_t txUnit, ++ UInt8 uHwAddress, ++ ptmbslHdmiTxSysFunc_t sysFuncWrite, ++ ptmbslHdmiTxSysFunc_t sysFuncRead, ++ ptmbslHdmiTxSysFuncEdid_t sysFuncEdidRead, ++ ptmbslHdmiTxSysFuncTimer_t sysFuncTimer, ++ tmbslHdmiTxCallbackList_t *funcIntCallbacks, ++ Bool bEdidAltAddr, ++ tmbslHdmiTxVidFmt_t vinFmt, ++ tmbslHdmiTxPixRate_t pixRate ++); ++ ++/** ++ \brief Set colour space converter matrix coefficients ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pMatCoeff Pointer to Matrix Coefficient structure ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ ++ \note Matrix Coefficient parameter structure: ++ Int16 Coeff[9]: Array of coefficients (values -1024 to +1023) ++ */ ++tmErrorCode_t ++tmbslTDA9989MatrixSetCoeffs ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxMatCoeff_t *pMatCoeff ++); ++ ++/** ++ \brief Set colour space conversion using preset values ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] vinFmt Input video format ++ \param[in] vinMode Input video mode ++ \param[in] voutFmt Output video format ++ \param[in] voutMode Output video mode ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ */ ++tmErrorCode_t ++tmbslTDA9989MatrixSetConversion ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxVidFmt_t vinFmt, ++ tmbslHdmiTxVinMode_t vinMode, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ tmbslHdmiTxVoutMode_t voutMode, ++ tmbslHdmiTxVQR_t dviVqr ++); ++ ++/** ++ \brief Set colour space converter matrix offset at input ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pMatOffset Pointer to Matrix Offset structure ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++ \note Matrix Offset structure parameter structure: ++ Int16 Offset[3]: Offset array (values -1024 to +1023) ++ */ ++tmErrorCode_t ++tmbslTDA9989MatrixSetInputOffset ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxMatOffset_t *pMatOffset ++); ++ ++/** ++ \brief Set colour space converter matrix mode ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] mControl Matrix Control: On, Off, No change ++ \param[in] mScale Matrix Scale Factor: 1/256, 1/512, 1/1024, No change ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++ \note NA ++ ++ \sa NA ++ */ ++tmErrorCode_t ++tmbslTDA9989MatrixSetMode ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxmCntrl_t mControl, ++ tmbslHdmiTxmScale_t mScale ++); ++ ++/*============================================================================*/ ++/** ++ \brief Set colour space converter matrix offset at output ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pMatOffset Pointer to Matrix Offset structure ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++ \note Matrix Offset parameter structure: ++ nt16 Offset[3]: Offset array (values -1024 to +1023) ++ */ ++tmErrorCode_t ++tmbslTDA9989MatrixSetOutputOffset ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxMatOffset_t *pMatOffset ++); ++ ++/*============================================================================*/ ++/** ++ \brief Enable audio clock recovery packet insertion ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] bEnable Enable or disable packet insertion ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: when in DVI mode ++ ++ \note tmbslTDA9989AudioInSetCts sets CTS and N values ++ */ ++tmErrorCode_t ++tmbslTDA9989PktSetAclkRecovery ++( ++ tmUnitSelect_t txUnit, ++ Bool bEnable ++); ++ ++/** ++ \brief Set audio content protection packet & enable/disable packet ++ insertion ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pPkt Pointer to Data Island Packet structure ++ \param[in] byteCnt Packet buffer byte count ++ \param[in] uAcpType Content protection type ++ \param[in] bEnable Enable or disable packet insertion ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: pointer suppied with byte count of zero ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: not possible with this device ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++ \note Data Island Packet parameter structure: ++ UInt8 dataByte[28] Packet Data ++ ++ \sa NA ++ */ ++tmErrorCode_t ++tmbslTDA9989PktSetAcp ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPkt_t *pPkt, ++ UInt byteCnt, ++ UInt8 uAcpType, ++ Bool bEnable ++); ++ ++/** ++ \brief Set audio info frame packet & enable/disable packet insertion ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pPkt Pointer to Audio Infoframe structure ++ \param[in] bEnable Enable or disable packet insertion ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++ \note Audio Infoframe structure: ++ UInt8 CodingType ++ UInt8 ChannelCount ++ UInt8 SampleFreq ++ UInt8 SampleSize ++ UInt8 ChannelAlloc ++ Bool DownMixInhibit ++ UInt8 LevelShift ++ */ ++tmErrorCode_t ++tmbslTDA9989PktSetAudioInfoframe ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPktAif_t *pPkt, ++ Bool bEnable ++); ++ ++ ++/*============================================================================*/ ++/** ++ \brief Set contents of general control packet & enable/disable ++ packet insertion ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] paMute Pointer to Audio Mute; if Null, no change to packet ++ contents is made ++ \param[in] bEnable Enable or disable packet insertion ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++ \note tmbslTDA9989AudioOutSetMute must be used to mute the audio output ++ */ ++tmErrorCode_t ++tmbslTDA9989PktSetGeneralCntrl ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxaMute_t *paMute, ++ Bool bEnable ++); ++ ++/*============================================================================*/ ++/** ++ \brief Set ISRC1 packet & enable/disable packet insertion ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pPkt Pointer to Data Island Packet structure ++ \param[in] byteCnt Packet buffer byte count ++ \param[in] bIsrcCont ISRC continuation flag ++ \param[in] bIsrcValid ISRC valid flag ++ \param[in] uIsrcStatus ISRC Status ++ \param[in] bEnable Enable or disable packet insertion ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: pointer suppied with byte count of zero ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: not possible with this device ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++ \note Data Island Packet parameter structure: ++ UInt8 dataByte[28] Packet Data ++ ++ \sa NA ++ */ ++tmErrorCode_t ++tmbslTDA9989PktSetIsrc1 ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPkt_t *pPkt, ++ UInt byteCnt, ++ Bool bIsrcCont, ++ Bool bIsrcValid, ++ UInt8 uIsrcStatus, ++ Bool bEnable ++); ++ ++/*============================================================================*/ ++/** ++ \brief Set ISRC2 packet & enable/disable packet insertion ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pPkt Pointer to Data Island Packet structure ++ \param[in] byteCnt Packet buffer byte count ++ \param[in] bEnable Enable or disable packet insertion ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: pointer suppied with byte count of zero ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: not possible with this device ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++ \note Data Island Packet parameter structure: ++ UInt8 dataByte[28] Packet Data ++ ++ \sa NA ++ */ ++tmErrorCode_t ++tmbslTDA9989PktSetIsrc2 ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPkt_t *pPkt, ++ UInt byteCnt, ++ Bool bEnable ++); ++ ++/** ++ \brief Set MPEG infoframe packet & enable/disable packet insertion ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pPkt Pointer to MPEG Infoframe structure ++ \param[in] bEnable Enable or disable packet insertion ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: not possible with this device ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++ \note MPEG Infoframe structure: ++ UInt32 bitRate ++ tmbslHdmiTxMpegFrame_t frameType ++ Bool bFieldRepeat ++ ++ \sa NA ++ */ ++tmErrorCode_t ++tmbslTDA9989PktSetMpegInfoframe ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPktMpeg_t *pPkt, ++ Bool bEnable ++); ++ ++/*============================================================================*/ ++/** ++ \brief Enable NULL packet insertion ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] bEnable Enable or disable packet insertion ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ */ ++tmErrorCode_t ++tmbslTDA9989PktSetNullInsert ++( ++ tmUnitSelect_t txUnit, ++ Bool bEnable ++); ++ ++/*============================================================================*/ ++/** ++ \brief Set single Null packet insertion (flag auto-resets after ++ transmission) ++ ++ \param[in] txUnit Transmitter unit number ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++ \note Operation resets after single transmission ++ */ ++tmErrorCode_t ++tmbslTDA9989PktSetNullSingle ++( ++ tmUnitSelect_t txUnit ++); ++ ++/** ++ \brief Set audio info frame packet & enable/disable packet insertion ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pPkt Pointer to Audio Infoframe structure ++ \param[in] bEnable Enable or disable packet insertion ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: not possible with this device ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++ \note Audio Infoframe structure: ++ UInt8 VendorName[8] ++ UInt8 ProdDescr[16] ++ tmbslHdmiTxSourceDev_t SourceDevInfo ++ */ ++tmErrorCode_t ++tmbslTDA9989PktSetSpdInfoframe ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPktSpd_t *pPkt, ++ Bool bEnable ++); ++ ++/** ++ \brief Set video infoframe packet & enable/disable packet insertion ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pPkt Pointer to Video Infoframe structure ++ \param[in] bEnable Enable or disable packet insertion ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++ \note Video Infoframe structure: ++ UInt8 Colour ++ Bool ActiveInfo ++ UInt8 BarInfo ++ UInt8 ScanInfo ++ UInt8 Colorimetry ++ UInt8 PictureAspectRatio ++ UInt8 ActiveFormatRatio ++ UInt8 Scaling ++ UInt8 VidFormat ++ UInt8 PixelRepeat ++ UInt16 EndTopBarLine ++ UInt16 StartBottomBarLine ++ UInt16 EndLeftBarPixel ++ UInt16 StartRightBarPixel (incorrectly named in [HDMI1.2]) ++ */ ++tmErrorCode_t ++tmbslTDA9989PktSetVideoInfoframe ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPktVif_t *pPkt, ++ Bool bEnable ++); ++ ++/*============================================================================*/ ++/** ++ \brief Set Vendor Specific Infoframe packet & enable/disable packet insertion ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pPkt Pointer to Data Island Packet structure ++ \param[in] byteCnt Packet buffer byte count ++ \param[in] uVersion Version number for packet header ++ \param[in] bEnable Enable or disable packet insertion ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: pointer suppied with byte count of zero ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: not possible with this device ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++ \note Data Island Packet parameter structure: ++ UInt8 dataByte[28] Packet Data (only use 27 bytes max) ++ ++ \sa NA ++ */ ++tmErrorCode_t ++tmbslTDA9989PktSetVsInfoframe ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPkt_t *pPkt, ++ UInt byteCnt, ++ UInt8 uVersion, ++ Bool bEnable ++); ++ ++/*============================================================================*/ ++/** ++ \brief Set raw video Infoframe packet & enable/disable packet insertion ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pPkt Pointer to raw Packet structure ++ \param[in] bEnable Enable or disable packet insertion ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++ \note Data Island Packet parameter structure: ++ UInt8 dataByte[28] Packet Data ++ ++ \sa NA ++ */ ++tmErrorCode_t tmbslTDA9989PktSetRawVideoInfoframe ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPktRawAvi_t *pPkt, ++ Bool bEnable ++); ++ ++ ++/*============================================================================*/ ++/** ++ \brief Get the power state of the transmitter ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pePowerState Pointer to the power state of the device now ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++ \note Power states: ++ - tmPowerOn ++ - tmPowerStandby ++ */ ++tmErrorCode_t ++tmbslTDA9989PowerGetState ++( ++ tmUnitSelect_t txUnit, ++ tmPowerState_t *pePowerState ++); ++ ++/*============================================================================*/ ++/** ++ \brief Set the power state of the transmitter ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] ePowerState Power state to set ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ ++ \note Power states (Off and Suspend are treated the same as Standby): ++ - tmPowerOn ++ - tmPowerStandby ++ - tmPowerSuspend ++ - tmPowerOff ++ */ ++tmErrorCode_t ++tmbslTDA9989PowerSetState ++( ++ tmUnitSelect_t txUnit, ++ tmPowerState_t ePowerState ++); ++ ++ ++/*============================================================================*/ ++/** ++ \brief Reset the HDMI transmitter ++ ++ \param[in] txUnit Transmitter unit number ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ ++ \note NA ++ ++ \sa tmbslTDA9989Init ++ */ ++tmErrorCode_t ++tmbslTDA9989Reset ++( ++ tmUnitSelect_t txUnit ++); ++ ++/** ++ \brief Get diagnostic counters from the scaler ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pScalerDiag Pointer to structure to receive scaler diagnostic ++ registers ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ ++ \note scaler diagnostic registers structure: ++ UInt16 maxBuffill_p Filling primary video buffer ++ UInt16 maxBuffill_d Filling video deinterlaced buffer ++ UInt8 maxFifofill_pi Filling primary video input FIFO ++ UInt8 minFifofill_po1 Filling primary video output FIFO #1 ++ UInt8 minFifofill_po2 Filling primary video output FIFO #2 ++ UInt8 minFifofill_po3 Filling primary video output FIFO #3 ++ UInt8 minFifofill_po4 Filling primary video output FIFO #4 ++ UInt8 maxFifofill_di Filling deinterlaced video input FIFO ++ UInt8 maxFifofill_do Filling deinterlaced video output FIFO ++ */ ++tmErrorCode_t ++tmbslTDA9989ScalerGet ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxScalerDiag_t *pScalerDiag ++); ++ ++ ++ ++/** ++ \brief Get the current scaler mode ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ ++ \param[in] txUnit Transmitter unit number ++ \param[out] pScalerMode Pointer to variable to receive scaler mode ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++*/ ++tmErrorCode_t ++tmbslTDA9989ScalerGetMode ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxScaMode_t *pScalerMode ++); ++ ++ ++/*============================================================================*/ ++/** ++ \brief Enable or disable scaler input frame ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] bDisable Enable or disable scaler input ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989ScalerInDisable ++( ++ tmUnitSelect_t txUnit, ++ Bool bDisable ++); ++ ++/** ++ \brief Set the active coefficient lookup table for the vertical scaler ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] lutSel Coefficient lookup table selection ++ \param[in] pVsLut Table of HDMITX_VSLUT_COEFF_NUM coefficient values ++ (may be null if lutSel not HDMITX_SCALUT_USE_VSLUT) ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: two parameters disagree ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989ScalerSetCoeffs ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxScaLut_t lutSel, ++ UInt8 *pVsLut ++); ++ ++/** ++ \brief Set scaler field positions ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] topExt Internal, External, No Change ++ \param[in] deExt Internal, External, No Change ++ \param[in] topSel Internal, VRF, No Change ++ \param[in] topTgl No Action, Toggle, No Change ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989ScalerSetFieldOrder ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxIntExt_t topExt, ++ tmbslHdmiTxIntExt_t deExt, ++ tmbslHdmiTxTopSel_t topSel, ++ tmbslHdmiTxTopTgl_t topTgl ++); ++ ++/** ++ \brief Set scaler fine adjustment options ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] uRefPix Ref. pixel preset 0 to 1FFFh (2000h = No Change) ++ \param[in] uRefLine Ref. line preset 0 to 7FFh (800h = No Change) ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989ScalerSetFine ++( ++ tmUnitSelect_t txUnit, ++ UInt16 uRefPix, ++ UInt16 uRefLine ++); ++ ++/** ++ \brief Set scaler phase for scaling 1080p ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] tmbslHdmiTxHPhases_t Ref. 0 to 15_horizontal_phases 1 to 16_horizontal_phases ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++ ++tmErrorCode_t ++tmbslTDA9989ScalerSetPhase ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxHPhases_t horizontalPhases ++); ++ ++/** ++ \brief configure scaler latency to set run in run out ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] UInt8 Ref. 0 to 255 ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989ScalerSetLatency ++( ++ tmUnitSelect_t txUnit, ++ UInt8 scaler_latency ++); ++ ++/** ++ \brief Set scaler synchronization options ++ On a TDA9989 this function is not supported and ++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] method Sync. combination method ++ \param[in] once Line/pixel counters sync once or each frame ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989ScalerSetSync ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxVsMeth_t method, ++ tmbslHdmiTxVsOnce_t once ++); ++ ++ ++/*============================================================================*/ ++/** ++ \brief Get the driver software version and compatibility numbers ++ ++ \param[out] pSWVersion Pointer to the software version structure returned ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ */ ++tmErrorCode_t ++tmbslTDA9989SwGetVersion ++( ++ ptmSWVersion_t pSWVersion ++); ++ ++ ++/*============================================================================*/ ++/** ++ \brief Get the driver software version and compatibility numbers ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] waitMs Period in milliseconds to wait ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ */ ++tmErrorCode_t ++tmbslTDA9989SysTimerWait ++( ++ tmUnitSelect_t txUnit, ++ UInt16 waitMs ++); ++ ++/** ++ \brief Set the TMDS outputs to normal active operation or to a forced ++ state ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] tmdsOut TMDS output mode ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ */ ++tmErrorCode_t ++tmbslTDA9989TmdsSetOutputs ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxTmdsOut_t tmdsOut ++); ++ ++/** ++ \brief Fine-tune the TMDS serializer ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] uPhase2 Serializer phase 2 ++ \param[in] uPhase3 Serializer phase 3 ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ */ ++tmErrorCode_t ++tmbslTDA9989TmdsSetSerializer ++( ++ tmUnitSelect_t txUnit, ++ UInt8 uPhase2, ++ UInt8 uPhase3 ++); ++ ++/** ++ \brief Set a colour bar test pattern ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pattern Test pattern ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989TestSetPattern ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxTestPattern_t pattern ++); ++ ++/** ++ \brief Set or clear one or more simultaneous test modes ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] testMode Mode: tst_pat, tst_656, tst_serphoe, tst_nosc, ++ tst_hvp, tst_pwd, tst_divoe ++ \param[in] testState State: 1=On, 0=Off ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989TestSetMode ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxTestMode_t testMode, ++ tmbslHdmiTxTestState_t testState ++); ++ ++/** ++ \brief Enable blanking between active data ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] blankitSource Blankit Source: Not DE, VS And HS, ++ VS And Not HS, Hemb And Vemb, No Change ++ \param[in] blankingCodes Blanking Codes: All Zero, RGB444, YUV444, ++ YUV422, No Change ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ ++ \note NA ++ ++ \sa NA ++ */ ++tmErrorCode_t ++tmbslTDA9989VideoInSetBlanking ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxBlnkSrc_t blankitSource, ++ tmbslHdmiTxBlnkCode_t blankingCodes ++); ++ ++/** ++ \brief Configure video input options and control the upsampler ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] vinMode Video input mode ++ \param[in] voutFmt EIA/CEA Video output format: 1 to 31, 0 = No Change ++ \param[in] sampleEdge Sample edge: ++ Pixel Clock Positive Edge, ++ Pixel Clock Negative Edge, No Change ++ \param[in] pixRate Single data or double data rate ++ \param[in] upsampleMode Upsample mode ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989VideoInSetConfig ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxVinMode_t vinMode, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ tmbslHdmiTx3DStructure_t structure3D, ++ tmbslHdmiTxPixEdge_t sampleEdge, ++ tmbslHdmiTxPixRate_t pixRate, ++ tmbslHdmiTxUpsampleMode_t upsampleMode ++); ++ ++/** ++ \brief Set fine image position ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] subpacketCount Subpacket Count fixed values and sync options ++ \param[in] toggleClk1 Toggle clock 1 phase w.r.t. clock 2 ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ ++ \note NA ++ ++ \sa NA ++ */ ++tmErrorCode_t ++tmbslTDA9989VideoInSetFine ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPixSubpkt_t subpacketCount, ++ tmbslHdmiTxPixTogl_t toggleClk1 ++); ++ ++/** ++ \brief Set video input port swapping and mirroring ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pSwapTable Pointer to 6-byte port swap table ++ \param[in] pMirrorTable Pointer to 6-byte port mirror table ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ ++ \note UInt8 pSwapTable[6] ++ ++ Each table position 0 to 5 represents a group of 4 port bits: ++ [0]=23:20, [1]=16:19, [2]=15:12, [3]=11:8, [4]=4:7, [5]=0:3 ++ Table position values are 0 to 6, denoting the group of 4 port ++ bits to swap to: 0=23:20, 1=16:19, 2=15:12, 3=11:8, 4=4:7, 5=0:3. ++ For example, to swap port bits 15:12 to bits 4:7: pSwapTable[2]=4 ++ ++ UInt8 pMirrorTable[6] ++ ++ Each table position 0 to 5 represents a group of 4 port bits: ++ [0]=23:20, [1]=16:19, [2]=15:12, [3]=11:8, [4]=4:7, [5]=0:3. ++ Cell values are 0 to 2 (Not Mirrored, Mirrored, No Change). ++ For example, to mirror port bits 11:8 to bits 8:11: ++ pMirrorTable[3]=1. ++ */ ++tmErrorCode_t ++tmbslTDA9989VideoInSetMapping ++#ifdef TMFL_RGB_DDR_12BITS ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pSwapTable, ++ UInt8 *pMirrorTable, ++ UInt8 *pMux ++); ++#else ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pSwapTable, ++ UInt8 *pMirrorTable ++); ++#endif ++/** ++ \brief Set video input port (enable, ground) ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pEnaVideoPortTable Pointer to 3-byte video port enable table ++ \param[in] pGndVideoPortTable Pointer to 3-byte video port ground table ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ ++ \note UInt8 pEnaVideoPortTable[3] ++ ++ Each table position 0 to 2 represents a group of 8 port bits: ++ [0]=7:0, [1]=15:8, [2]=23:16 ++ bitn = '1' means enable port n ++ bitn = '0' means disable port n ++ For example, to enable port 0 to 7 only : pEnaVideoPortTable[0]= 0xFF ++ pEnaVideoPortTable[1]= 0x00, pEnaVideoPortTable[2]= 0x00 ++ ++ UInt8 pGndVideoPortTable[3] ++ ++ Each table position 0 to 2 represents a group of 8 port bits: ++ [0]=7:0, [1]=15:8, [2]=23:16 ++ bitn = '1' means pulldown port n ++ bitn = '0' means not pulldown port n ++ For example, to pulldown port 8 to 15 only : pEnaVideoPortTable[0]= 0x00 ++ pEnaVideoPortTable[1]= 0xFF, pEnaVideoPortTable[2]= 0x00 ++ */ ++tmErrorCode_t ++tmbslTDA9989SetVideoPortConfig ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pEnaVideoPortTable, ++ UInt8 *pGndVideoPortTable ++); ++ ++/*============================================================================*/ ++/** ++ \brief Set audio input port (enable, ground) ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pEnaAudioPortTable Pointer to 1-byte audio port enable configuration ++ \param[in] pGndAudioPortTable Pointer to 1-byte audio port ground configuration ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ ++ \note UInt8 pEnaAudioPortTable[1] ++ bitn = '1' means enable port n ++ bitn = '0' means disable port n ++ For example, to enable all audio port (0:7) : pEnaAudioPortTable[0]= 0xFF ++ ++ UInt8 pGndAudioPortTable[1] ++ bitn = '1' means pulldown port n ++ bitn = '0' means not pulldown port n ++ For example, to pulldown audio port (0:7) : pEnaAudioPortTable[0]= 0xFF ++*/ ++tmErrorCode_t ++tmbslTDA9989SetAudioPortConfig ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pEnaAudioPortTable, ++ UInt8 *pGndAudioPortTable ++); ++ ++/*============================================================================*/ ++/** ++ \brief Set audio input Clock port (enable, ground) ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pEnaAudioClockPortTable Pointer to 1-byte audio Clock port enable configuration ++ \param[in] pGndAudioClockPortTable Pointer to 1-byte audio Clock port ground configuration ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ ++ \note UInt8 pEnaAudioClockPortTable[1] ++ bitn = '1' means enable port n ++ bitn = '0' means disable port n ++ For example, to enable all audio Clock port (0) : pEnaAudioPortTable[0]= 0x01 ++ ++ UInt8 pGndAudioClockPortTable[1] ++ bitn = '1' means pulldown port n ++ bitn = '0' means not pulldown port n ++ For example, to pulldown audio Clock port (0:7) : pEnaAudioPortTable[0]= 0x01 ++*/ ++tmErrorCode_t ++tmbslTDA9989SetAudioClockPortConfig ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pEnaAudioClockPortTable, ++ UInt8 *pGndAudioClockPortTable ++); ++ ++/** ++ \brief Configure video input sync automatically ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] syncSource Sync Source: ++ Embedded, External Vref, External Vs ++ No Change ++ \param[in] vinFmt EIA/CEA Video input format: 1 to 31, 0 = No Change ++ \param[in] vinMode Input video mode ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989VideoInSetSyncAuto ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxSyncSource_t syncSource, ++ tmbslHdmiTxVidFmt_t vinFmt, ++ tmbslHdmiTxVinMode_t vinMode, ++ tmbslHdmiTx3DStructure_t structure3D ++); ++ ++/** ++ \brief Configure video input sync with manual parameters ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] syncSource Sync Source: ++ Embedded, External Vref, External Vs ++ No Change ++ \param[in] syncMethod Sync method: V And H, V And X-DE, No Change ++ \param[in] toggleV VS Toggle: ++ No Action, Toggle VS/Vref, No Change ++ \param[in] toggleH HS Toggle: ++ No Action, Toggle HS/Href, No Change ++ \param[in] toggleX DE/FREF Toggle: ++ No Action, Toggle DE/Fref, No Change ++ \param[in] uRefPix Ref. pixel preset 0 to 1FFFh (2000h = No Change) ++ \param[in] uRefLine Ref. line preset 0 to 7FFh (800h = No Change) ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989VideoInSetSyncManual ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxSyncSource_t syncSource, ++ tmbslHdmiTxVsMeth_t syncMethod, ++ tmbslHdmiTxPixTogl_t toggleV, ++ tmbslHdmiTxPixTogl_t toggleH, ++ tmbslHdmiTxPixTogl_t toggleX, ++ UInt16 uRefPix, ++ UInt16 uRefLine ++); ++ ++ ++/*============================================================================*/ ++/** ++ \brief Enable or disable output video frame ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] bDisable Enable or disable scaler input ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989VideoOutDisable ++( ++ tmUnitSelect_t txUnit, ++ Bool bDisable ++); ++ ++/** ++ \brief Configure sink type, configure video output colour and ++ quantization, control the downsampler, and force RGB output ++ and mute audio in DVI mode ++ ++ \param[in] txUnit Transmitter unit number: ++ \param[in] sinkType Sink device type: DVI or HDMI or copy from EDID ++ \param[in] voutMode Video output mode ++ \param[in] preFilter Prefilter: Off, 121, 109, CCIR601, No Change ++ \param[in] yuvBlank YUV blanking: 16, 0, No Change ++ \param[in] quantization Video quantization range: ++ Full Scale, RGB Or YUV, YUV, No Change ++ ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989VideoOutSetConfig ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxSinkType_t sinkType, ++ tmbslHdmiTxVoutMode_t voutMode, ++ tmbslHdmiTxVoutPrefil_t preFilter, ++ tmbslHdmiTxVoutYuvBlnk_t yuvBlank, ++ tmbslHdmiTxVoutQrange_t quantization ++); ++ ++/** ++ \brief Set video synchronization ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] srcH Horizontal sync source: Internal, Exter'l, No Change ++ \param[in] srcV Vertical sync source: Internal, Exter'l, No Change ++ \param[in] srcX X sync source: Internal, Exter'l, No Change ++ \param[in] toggle Sync toggle: Hs, Vs, Off, No Change ++ \param[in] once Line/pixel counters sync once or each frame ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989VideoOutSetSync ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxVsSrc_t srcH, ++ tmbslHdmiTxVsSrc_t srcV, ++ tmbslHdmiTxVsSrc_t srcX, ++ tmbslHdmiTxVsTgl_t toggle, ++ tmbslHdmiTxVsOnce_t once ++); ++ ++/** ++ \brief Set main video input and output parameters ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] vinFmt EIA/CEA Video input format: 1 to 31, 0 = No Change ++ \param[in] scaMode Scaler mode: Off, On, Auto, No Change ++ On TDA9989, only scaler mode off is possible ++ \param[in] voutFmt EIA/CEA Video output format: 1 to 31, 0 = No Change ++ \param[in] uPixelRepeat Pixel repetition factor: 0 to 9, 10 = default, ++ 11 = no change ++ \param[in] matMode Matrix mode: 0 = off, 1 = auto ++ \param[in] datapathBits Datapath bitwidth: 0 to 3 (8, 10, 12, No Change) ++ \param[in] Desired VQR in dvi mode ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: params are inconsistent ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989VideoSetInOut ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxVidFmt_t vinFmt, ++ tmbslHdmiTx3DStructure_t structure3D, ++ tmbslHdmiTxScaMode_t scaMode, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ UInt8 uPixelRepeat, ++ tmbslHdmiTxMatMode_t matMode, ++ tmbslHdmiTxVoutDbits_t datapathBits, ++ tmbslHdmiTxVQR_t dviVqr ++); ++ ++/** ++ \brief Use only for debug to flag the software debug interrupt ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] uSwInt Interrupt to be generated (not relevant) ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++tmErrorCode_t ++tmbslTDA9989FlagSwInt ++( ++ tmUnitSelect_t txUnit, ++ UInt32 uSwInt ++); ++ ++ ++/** ++ \brief Enable or disable 5v power ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] pwrEnable 5v Power enable(True)/disable(False) ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: functionnality not supported by this device ++ */ ++tmErrorCode_t ++tmbslTDA9989Set5vpower ++( ++ tmUnitSelect_t txUnit, ++ Bool pwrEnable ++); ++ ++/** ++ \brief Enable or disable a callback source ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] callbackSource Callback source ++ \param[in] enable Callback source enable(True)/disable(False) ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: impossible to disable this interrupt ++ */ ++tmErrorCode_t ++tmbslTDA9989EnableCallback ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxCallbackInt_t callbackSource, ++ Bool enable ++); ++ ++/** ++ \brief Configure the deep color mode ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] colorDepth Number of bits per pixel to be processed ++ \param[in] termEnable Enable transmitter termination ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: mode not supported ++ */ ++tmErrorCode_t ++tmbslTDA9989SetColorDepth ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxColorDepth colorDepth, ++ Bool termEnable ++); ++ ++/** ++ \brief Configure the default phase for a specific deep color mode ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] bEnable Enable(true)/disable(False) default phase ++ \param[in] colorDepth Concerned deepcolor mode ++ \param[in] videoFormat Number of bits per pixel to be processed ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: functionnality not supported by this device ++ */ ++tmErrorCode_t ++tmbslTDA9989SetDefaultPhase ++( ++ tmUnitSelect_t txUnit, ++ Bool bEnable, ++ tmbslHdmiTxColorDepth colorDepth, ++ UInt8 videoFormat ++); ++ ++ ++ ++/** ++ \brief Control (Enable/Disable) VS interrupt ++ ++ \param[in] txUnit Transmitter unit number ++ \param[in] uIntFlag Enable/Disable VS interrupt ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - Else a problem has been detected: ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ */ ++ ++tmErrorCode_t ++tmbslTDA9989CtlVsInterrupt ++( ++ tmUnitSelect_t txUnit, ++ Bool uIntFlag ++); ++ ++/*============================================================================*/ ++/** ++ \brief Fill Gamut metadata packet into one of the gamut HW buffer. this ++ function is not sending any gamut metadata into the HDMI stream, ++ it is only loading data into the HW. ++ ++ \param txUnit Transmitter unit number ++ \param pPkt pointer to the gamut packet structure ++ \param bufSel number of the gamut buffer to fill ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C ++ bus ++ ++ ******************************************************************************/ ++tmErrorCode_t tmbslTDA9989PktFillGamut ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPktGamut_t *pPkt, ++ UInt8 bufSel ++); ++ ++/*============================================================================*/ ++/** ++ \brief Enable transmission of gamut metadata packet. Calling this function ++ tells HW which gamut buffer to send into the HDMI stream. HW will ++ only take into account this command at the next VS, not during the ++ current one. ++ ++ \param txUnit Transmitter unit number ++ \param bufSel Number of the gamut buffer to be sent ++ \param enable Enable/disable gamut packet transmission ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C ++ bus ++ ++ ******************************************************************************/ ++tmErrorCode_t tmbslTDA9989PktSendGamut ++( ++ tmUnitSelect_t txUnit, ++ UInt8 bufSel, ++ Bool bEnable ++); ++ ++ ++/** ++ \brief Return the category of equipement connected ++ ++ \param txUnit Transmitter unit number ++ \param category return category type ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: params are inconsistent ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE hdcp not started ++ ++*/ ++tmErrorCode_t tmbslTDA9989HdcpGetSinkCategory ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxSinkCategory_t *category ++); ++ ++ ++/** ++ \brief Return the sink latency information if any ++ ++ \param txUnit Transmitter unit number ++ \param pEdidLatency latency data structure to return ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: params are inconsistent ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE hdcp not started ++ ++*/ ++tmErrorCode_t tmbslTDA9989EdidGetLatencyInfo ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxEdidLatency_t * pEdidLatency ++); ++ ++ ++/** ++ \brief Return the sink additional VSDB data information if any ++ ++ \param txUnit Transmitter unit number ++ \param p3Ddata 3D data structure to return ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: params are inconsistent ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE hdcp not started ++ ++*/ ++tmErrorCode_t tmbslTDA9989EdidGetExtraVsdbData ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxEdidExtraVsdbData_t **pExtraVsdbData ++); ++ ++ ++#ifdef TMFL_HDCP_OPTIMIZED_POWER ++/** ++ \brief Optimized power by frozing useless clocks related to HDCP ++ ++ \param txUnit Transmitter unit number ++ \param request power down request ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: params are inconsistent ++ ++*/ ++tmErrorCode_t ++tmbslTDA9989HdcpPowerDown ++( ++ tmUnitSelect_t txUnit, ++ Bool requested ++); ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMBSLTDA9989_FUNCTIONS_H */ ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ ++ +diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid.c b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid.c +new file mode 100755 +index 0000000..488b950 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid.c +@@ -0,0 +1,1572 @@ ++/** ++ * Copyright (C) 2009 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmbslTDA9989_edid.c ++ * ++ * \version $Revision: 2 $ ++ * ++*/ ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#include "tmbslHdmiTx_types.h" ++#include "tmbslTDA9989_Functions.h" ++#include "tmbslTDA9989_local.h" ++#include "tmbslTDA9989_State_l.h" ++#include "tmbslTDA9989_Edid_l.h" ++ ++ ++/*============================================================================*/ ++/* TYPES DECLARATIONS */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* CONSTANTS DECLARATIONS */ ++/*============================================================================*/ ++#define EDID_NUMBER_MAX_DTD_BLK_1 6 ++/** EDID block 0 parse start point */ ++#define EDID_BLK0_BASE_DTD 0x36 ++ ++#define EDID_BLK1_OFFSET_BASE_DTD 2 ++ ++/** EDID block 0 extension block count */ ++#define EDID_BLK0_EXT_CNT 0x7E ++ ++/** EDID extension block parse start point */ ++#define EDID_BLK_EXT_BASE 0x04 ++ ++/** CEA extension block type */ ++#define EDID_CEA_EXTENSION 0x02 ++ ++/** CEA Block Map */ ++#define EDID_BLOCK_MAP 0xF0 ++ ++/** NB Max of descriptor DTD or monitor in block 0 */ ++#define EDID_NB_MAX_DESCRIP_BLK_IN_BLK_0 4 ++ ++#define EDID_MONITOR_NAME_DESC_DATA_TYPE 252 ++ ++#define EDID_MONITOR_RANGE_DESC_DATA_TYPE 253 ++ ++/*============================================================================*/ ++/* DEFINES DECLARATIONS */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* VARIABLES DECLARATIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++ ++static tmErrorCode_t requestEdidBlock(tmHdmiTxobject_t *pDis); ++ ++static tmErrorCode_t parseEdidBlock (tmHdmiTxobject_t *pDis, ++ Int blockNumber); ++static Bool storeDtdBlock (tmHdmiTxobject_t *pDis, ++ UInt8 blockPtr); ++ ++static Bool storeMonitorDescriptor (tmHdmiTxobject_t *pDis, ++ UInt8 blockPtr); ++ ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989HwGetCapabilities */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HwGetCapabilities ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxHwFeature_t deviceCapability, ++ Bool *pFeatureSupported ++ ) ++{ ++ tmHdmiTxobject_t *pDis; ++ tmErrorCode_t err = TM_OK; ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ RETIF_BADPARAM(pFeatureSupported == Null) ++ ++ *pFeatureSupported = False; ++ ++ ++ switch (deviceCapability) ++ { ++ case HDMITX_FEATURE_HW_HDCP: ++ if((pDis->uDeviceFeatures & E_MASKREG_P00_VERSION_not_h) == 0) ++ { ++ *pFeatureSupported = True; ++ } ++ break; ++ case HDMITX_FEATURE_HW_SCALER: ++ if((pDis->uDeviceFeatures & E_MASKREG_P00_VERSION_not_s) == 0) ++ { ++ *pFeatureSupported = True; ++ } ++ break; ++ case HDMITX_FEATURE_HW_AUDIO_OBA: ++ *pFeatureSupported = True; ++ break; ++ case HDMITX_FEATURE_HW_AUDIO_DST: ++ *pFeatureSupported = False; ++ break; ++ case HDMITX_FEATURE_HW_AUDIO_HBR: ++ *pFeatureSupported = False; ++ break; ++ case HDMITX_FEATURE_HW_HDMI_1_1: ++ *pFeatureSupported = True; ++ break; ++ case HDMITX_FEATURE_HW_HDMI_1_2A: ++ *pFeatureSupported = True; ++ break; ++ case HDMITX_FEATURE_HW_HDMI_1_3A: ++ *pFeatureSupported = False; ++ break; ++ ++ case HDMITX_FEATURE_HW_DEEP_COLOR_30: ++ *pFeatureSupported = False; ++ break; ++ ++ case HDMITX_FEATURE_HW_DEEP_COLOR_36: ++ *pFeatureSupported = False; ++ break; ++ ++ case HDMITX_FEATURE_HW_DEEP_COLOR_48: ++ *pFeatureSupported = False; ++ break; ++ ++ case HDMITX_FEATURE_HW_UPSAMPLER: ++ *pFeatureSupported = True; ++ break; ++ ++ case HDMITX_FEATURE_HW_DOWNSAMPLER: ++ *pFeatureSupported = True; ++ break; ++ ++ case HDMITX_FEATURE_HW_COLOR_CONVERSION: ++ *pFeatureSupported = True; ++ break; ++ ++ default: ++ *pFeatureSupported = False; ++ break; ++ } ++ ++ ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989EdidGetAudioCapabilities */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989EdidGetAudioCapabilities ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxEdidSad_t *pEdidAFmts, ++ UInt aFmtLength, ++ UInt *pAFmtsAvail, ++ UInt8 *pAudioFlags ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt i; /* Loop index */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(pEdidAFmts == Null) ++ RETIF_BADPARAM(aFmtLength < 1) ++ RETIF_BADPARAM(pAFmtsAvail == Null) ++ RETIF_BADPARAM(pAudioFlags == Null) ++ ++ if ((pDis->EdidStatus == HDMITX_EDID_READ) || ++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK)) ++ { ++ /* allow if edid are read or if there are a chk error on an other block than block 0 */ ++ ++ /* Copy the Device Instance Structure EdidAFmts descriptors to ++ * pEdidAFmts until we run out or no more space in structure. ++ */ ++ if (pDis->EdidSadCnt > 0) ++ { ++ for (i = 0; (i < (UInt)pDis->EdidSadCnt) && (i < aFmtLength); i++) ++ { ++ pEdidAFmts[i].ModeChans = pDis->EdidAFmts[i].ModeChans; ++ pEdidAFmts[i].Freqs = pDis->EdidAFmts[i].Freqs; ++ pEdidAFmts[i].Byte3 = pDis->EdidAFmts[i].Byte3; ++ } ++ } ++ else ++ { ++ /* No pEdidAFmts to copy so set a zero format to be safe */ ++ pEdidAFmts[0].ModeChans = 0; ++ pEdidAFmts[0].Freqs = 0; ++ pEdidAFmts[0].Byte3 = 0; ++ } ++ ++ /* Fill Audio Flags parameter */ ++ *pAudioFlags = ((pDis->EdidCeaFlags & 0x40) << 1); /* Basic audio */ ++ if (pDis->EdidSinkAi == True) ++ { ++ *pAudioFlags += 0x40; /* Mask in AI support */ ++ } ++ ++ /* Fill number of SADs available parameter */ ++ *pAFmtsAvail = pDis->EdidSadCnt; ++ } ++ else ++ { ++ /* Not allowed if EdidStatus value is not valid */ ++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE; ++ } ++ return err; ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989EdidGetBlockCount */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989EdidGetBlockCount ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *puEdidBlockCount ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(puEdidBlockCount == Null) ++ ++ if ((pDis->EdidStatus == HDMITX_EDID_READ) || ++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK)) ++ { ++ /* allow if edid are read or if there are a chk error on an other block than block 0 */ ++ *puEdidBlockCount = pDis->EdidBlockCnt; ++ } ++ else ++ { ++ /* Not allowed if EdidStatus value is not valid */ ++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE; ++ } ++ ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989EdidGetStatus */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989EdidGetStatus ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *puEdidStatus ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(puEdidStatus == Null) ++ ++ if (puEdidStatus) ++ { ++ *puEdidStatus = pDis->EdidStatus; ++ } ++ ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989EdidRequestBlockData */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989EdidRequestBlockData ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pRawEdid, ++ Int numBlocks, /* Only relevant if pRawEdid valid */ ++ Int lenRawEdid /* Only relevant if pRawEdid valid */ ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regval; /* Byte value write to register */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ #ifdef TMFL_TDA9989_PIXEL_CLOCK_ON_DDC ++ ++ if ( (pDis->vinFmt == HDMITX_VFMT_16_1920x1080p_60Hz) || (pDis->vinFmt == HDMITX_VFMT_31_1920x1080p_50Hz)) { ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P02_PLL_SERIAL_3_RW, ++ E_MASKREG_P02_PLL_SERIAL_3_srl_ccir, ++ 0x01); ++ RETIF_REG_FAIL(err) ++ ++ } ++ ++ #endif /* TMFL_TDA9989_PIXEL_CLOCK_ON_DDC */ ++ ++#ifdef TMFL_RGB_DDR_12BITS ++ /* RAM on */ ++ setHwRegisterField(pDis, E_REG_P12_TX4_RW, E_MASKREG_P12_TX4_pd_ram, 0); ++#endif ++ ++ /* enable edid read */ ++ err = setHwRegister(pDis, E_REG_P00_INT_FLAGS_2_RW, ++ E_MASKREG_P00_INT_FLAGS_2_edid_blk_rd); ++ ++ /* Check remaining parameter(s) ++ * We do allow a null pRawEdid pointer, in which case buffer length is ++ * irrelevant. If pRawEdid pointer is valid, there is no point in ++ * continuing if insufficient space for at least one block. ++ */ ++ RETIF_BADPARAM((pRawEdid != Null) && (lenRawEdid < EDID_BLOCK_SIZE)) ++ /* Sensible value of numBlocks? */ ++ RETIF((pRawEdid != Null) && ((numBlocks < 1) || (numBlocks > 255)), ++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS) ++ /* Enough space for the data requested? */ ++ RETIF((pRawEdid != Null) && (lenRawEdid < (numBlocks * EDID_BLOCK_SIZE)), ++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS) ++ ++ /* Read the HPD pin via the hpd_in flag in the first interrupt status ++ * register and return a TMBSL_ERR_HDMI_NULL_CONNECTION error if it is ++ * not set. ++ * We must use the flag in the Device Instance Structure to avoid ++ * clearing pending interrupt flags. ++ */ ++ RETIF(pDis->hotPlugStatus != HDMITX_HOTPLUG_ACTIVE, ++ TMBSL_ERR_HDMI_NULL_CONNECTION) ++ ++ if (pDis->EdidReadStarted == False) ++ { ++ ++ /* Reset the EdidStatus in the Device Instance Structure */ ++ pDis->EdidStatus = HDMITX_EDID_NOT_READ; ++ ++ pDis->EdidReadStarted = True; ++ ++ /* Reset stored parameters from EDID in the Device Instance Structure */ ++ pDis->EdidSinkType = HDMITX_SINK_DVI; ++ pDis->EdidSinkAi = False; ++ pDis->EdidCeaFlags = 0; ++ pDis->EdidCeaXVYCCFlags = 0; ++ pDis->EdidSvdCnt = 0; ++ pDis->EdidSadCnt = 0; ++ pDis->EdidSourceAddress = 0; /* 0.0.0.0 */ ++ pDis->NbDTDStored = 0; ++ pDis->EdidFirstMonitorDescriptor.bDescRecord = False; ++ pDis->EdidSecondMonitorDescriptor.bDescRecord = False; ++ pDis->EdidOtherMonitorDescriptor.bDescRecord = False; ++ ++ pDis->EdidLatency.latency_available = False; ++ pDis->EdidLatency.Ilatency_available = False; ++ ++ pDis->EdidExtraVsdbData.hdmiVideoPresent = False; ++ ++ ++ pDis->EdidToApp.pRawEdid = pRawEdid; ++ pDis->EdidToApp.numBlocks = numBlocks; ++ ++ /* Enable the T0 interrupt for detecting the Read_EDID failure */ ++ regval = E_MASKREG_P00_INT_FLAGS_0_t0 ; ++ err = setHwRegister(pDis, E_REG_P00_INT_FLAGS_0_RW, regval); ++ RETIF(err != TM_OK, err); ++ ++ ++ /* Launch the read of first EDID block into Device Instance workspace */ ++ pDis->EdidBlockRequested = 0; ++ err = requestEdidBlock(pDis); ++ } ++ else ++ { ++ /* Not allowed if read edid is on going */ ++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE; ++ } ++ ++ return err; ++} ++ ++ ++/*============================================================================*/ ++/* EdidBlockAvailable */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++EdidBlockAvailable (tmUnitSelect_t txUnit, Bool * pSendEDIDCallback) ++{ ++ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 chksum; /* Checksum value */ ++ UInt8 LoopIndex; /* Loop index */ ++ UInt8 extBlockCnt; ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ err = TM_OK; ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(pSendEDIDCallback == Null) ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ if (pDis->EdidReadStarted == True) ++ { ++ ++ err = tmbslTDA9989HwGetRegisters(txUnit, kPageIndexToPage[E_PAGE_09], ++ SPA2ADDR(E_REG_P09_EDID_DATA_0_R), pDis->EdidBlock, EDID_BLOCK_SIZE); ++ RETIF(err != TM_OK, err) ++ ++ if(pSendEDIDCallback) ++ { ++ *pSendEDIDCallback = False; ++ } ++ ++ if (pDis->EdidStatus == HDMITX_EDID_NOT_READ) ++ { ++ err = getHwRegisters(pDis, E_REG_P09_EDID_DATA_0_R, pDis->EdidBlock, ++ EDID_BLOCK_SIZE); ++ RETIF_REG_FAIL(err) ++ ++ /* Add up all the values of the EDID block bytes, including the ++ * checksum byte ++ */ ++ chksum = 0; ++ for (LoopIndex = 0; LoopIndex < EDID_BLOCK_SIZE; LoopIndex++) ++ { ++ chksum = chksum + pDis->EdidBlock[LoopIndex]; ++ } ++ ++ /* IF the EDID block does not yield a checksum of zero ++ */ ++ if(chksum != 0) ++ { ++ if (pDis->EdidBlockRequested == 0) ++ { ++ /* THEN return a HDMITX_EDID_ERROR error.*/ ++ pDis->EdidStatus = HDMITX_EDID_ERROR_CHK_BLOCK_0; ++ } ++ else ++ { ++ /* THEN return a HDMITX_EDID_ERROR_CHK error.*/ ++ pDis->EdidStatus = HDMITX_EDID_ERROR_CHK; ++ } ++ } ++ } ++ ++ if (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK_BLOCK_0) ++ { ++ /* PR11 : On i2c error or bad checksum in block 0 */ ++ /* allow driver to go in state CONNECTED */ ++ /* On the other block, we also accept INVALID_CHECKSUM which means ++ * there was a checksum error */ ++ ++ if(pSendEDIDCallback) ++ { ++ *pSendEDIDCallback = True; ++ } ++ ++ setState(pDis, EV_GETBLOCKDATA); ++ if (pDis->rxSenseStatus == HDMITX_RX_SENSE_ACTIVE) ++ { ++ setState(pDis, EV_SINKON); ++ } ++ pDis->EdidReadStarted = False; ++ return err; ++ } ++ ++ /* Check if block 0 */ ++ if (pDis->EdidBlockRequested == 0) ++ { ++ /* Could check block 0 header (0x00,6 x 0xFF,0x00) here but not ++ * certain to be future proof [CEA861C A.2.3] ++ */ ++ ++ /* Read block count from penultimate byte of block and store in DIS */ ++ extBlockCnt = pDis->EdidBlock[EDID_BLK0_EXT_CNT]; ++ ++ pDis->EdidBlockCnt = extBlockCnt + 1; /* Total = Block 0 + extensions */ ++ ++ } ++ ++ /* If pointer was supplied, copy block from DIS to buffer */ ++ if (pDis->EdidToApp.pRawEdid != Null) ++ { ++ /* Check if we've copied as many as requested yet? */ ++ if (pDis->EdidBlockRequested < pDis->EdidToApp.numBlocks) ++ { ++ lmemcpy(pDis->EdidToApp.pRawEdid + (pDis->EdidBlockRequested * EDID_BLOCK_SIZE), ++ pDis->EdidBlock, ++ EDID_BLOCK_SIZE); ++ } ++ } ++ parseEdidBlock(pDis, pDis->EdidBlockRequested); ++ ++ /* If extension blocks are present, process them */ ++ if ( (pDis->EdidBlockRequested + 1) < pDis->EdidBlockCnt) ++ { ++ pDis->EdidBlockRequested = pDis->EdidBlockRequested + 1; ++ /* Launch an edid block read */ ++ err = requestEdidBlock(pDis); ++ } ++ else ++ { ++ if (pDis->EdidStatus == HDMITX_EDID_NOT_READ) ++ { ++ pDis->EdidStatus = HDMITX_EDID_READ; ++ ++#ifdef TMFL_RGB_DDR_12BITS ++ /* RAM off */ ++ setHwRegisterField(pDis, E_REG_P12_TX4_RW, E_MASKREG_P12_TX4_pd_ram, 1); ++#endif ++ } ++ ++ if(pSendEDIDCallback) ++ { ++ *pSendEDIDCallback = True; ++ } ++ ++ setState(pDis, EV_GETBLOCKDATA); ++ ++ if (pDis->rxSenseStatus == HDMITX_RX_SENSE_ACTIVE) ++ { ++ setState(pDis, EV_SINKON); ++ } ++ pDis->EdidReadStarted = False; ++ } ++ } ++ else ++ { ++ /* function called in an invalid state */ ++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE; ++ } ++ ++ return err; ++ ++} ++ ++/*============================================================================*/ ++/* ClearEdidRequest */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++ClearEdidRequest (tmUnitSelect_t txUnit) ++{ ++ ++ tmErrorCode_t err; /* Error code */ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ err = TM_OK; ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ ++ /* Reset the EdidStatus in the Device Instance Structure */ ++ pDis->EdidStatus = HDMITX_EDID_NOT_READ; ++ ++ pDis->EdidReadStarted = False; ++ ++ /* Reset stored parameters from EDID in the Device Instance Structure */ ++ pDis->EdidSinkType = HDMITX_SINK_DVI; ++ pDis->EdidSinkAi = False; ++ pDis->EdidCeaFlags = 0; ++ pDis->EdidCeaXVYCCFlags = 0; ++ pDis->EdidSvdCnt = 0; ++ pDis->EdidSadCnt = 0; ++ pDis->EdidSourceAddress = 0; /* 0.0.0.0 */ ++ pDis->NbDTDStored = 0; ++ pDis->EdidFirstMonitorDescriptor.bDescRecord = False; ++ pDis->EdidSecondMonitorDescriptor.bDescRecord = False; ++ pDis->EdidOtherMonitorDescriptor.bDescRecord = False; ++ ++ pDis->EdidLatency.latency_available = False; ++ pDis->EdidLatency.Ilatency_available = False; ++ ++ pDis->EdidExtraVsdbData.hdmiVideoPresent = False; ++ ++ /* Launch the read of first EDID block into Device Instance workspace */ ++ pDis->EdidBlockRequested = 0; ++ ++ ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989EdidGetSinkType */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989EdidGetSinkType ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxSinkType_t *pSinkType ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(pSinkType == Null) ++ ++ if ((pDis->EdidStatus == HDMITX_EDID_READ) || ++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK)) ++ { ++ /* allow if edid are read or if there are a chk error on an other block than block 0 */ ++ ++ *pSinkType = pDis->EdidSinkType; ++ } ++ else ++ { ++ /* Not allowed if EdidStatus value is not valid */ ++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE; ++ } ++ return err; ++ ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989EdidGetSourceAddress */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++tmbslTDA9989EdidGetSourceAddress ++( ++ tmUnitSelect_t txUnit, ++ UInt16 *pSourceAddress ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(pSourceAddress == Null) ++ ++ if ((pDis->EdidStatus == HDMITX_EDID_READ) || ++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK)) ++ { ++ /* allow if edid are read or if there are a chk error on an other block than block 0 */ ++ ++ *pSourceAddress = pDis->EdidSourceAddress; ++ } ++ else ++ { ++ /* Not allowed if EdidStatus value is not valid */ ++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE; ++ } ++ return err; ++ ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989EdidGetDetailedTimingDescriptors */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989EdidGetDetailedTimingDescriptors ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxEdidDtd_t *pEdidDTD, ++ UInt8 nb_size, ++ UInt8 *pDTDAvail ++) ++{ ++ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(pEdidDTD == Null) ++ RETIF_BADPARAM(pDTDAvail == Null) ++ RETIF_BADPARAM(nb_size == 0) ++ ++ if ((pDis->EdidStatus == HDMITX_EDID_READ) || ++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK)) ++ { ++ /* allow if edid are read or if there are a chk error on an other block than block 0 */ ++ if (nb_size > pDis->NbDTDStored) ++ { ++ *pDTDAvail = pDis->NbDTDStored; ++ } ++ else ++ { ++ *pDTDAvail = nb_size; ++ } ++ ++ lmemcpy(pEdidDTD, pDis->EdidDTD, sizeof(tmbslHdmiTxEdidDtd_t) * (*pDTDAvail)); ++ } ++ else ++ { ++ /* Not allowed if EdidStatus value is not valid */ ++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE; ++ } ++ ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989EdidGetMonitorDescriptors */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989EdidGetMonitorDescriptors ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxEdidFirstMD_t *pEdidFirstMD, ++ tmbslHdmiTxEdidSecondMD_t *pEdidSecondMD, ++ tmbslHdmiTxEdidOtherMD_t *pEdidOtherMD, ++ UInt8 sizeOtherMD, ++ UInt8 *pOtherMDAvail ++) ++{ ++ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(pEdidFirstMD == Null) ++ RETIF_BADPARAM(pEdidSecondMD == Null) ++ RETIF_BADPARAM(pEdidOtherMD == Null) ++ ++ DUMMY_ACCESS(pOtherMDAvail); ++ DUMMY_ACCESS(sizeOtherMD); ++ ++ if ((pDis->EdidStatus == HDMITX_EDID_READ) || ++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK)) ++ { ++ *pOtherMDAvail = 1; ++ lmemcpy(pEdidFirstMD, &(pDis->EdidFirstMonitorDescriptor), sizeof(tmbslHdmiTxEdidFirstMD_t)); ++ lmemcpy(pEdidSecondMD, &(pDis->EdidSecondMonitorDescriptor), sizeof(tmbslHdmiTxEdidSecondMD_t)); ++ lmemcpy(pEdidOtherMD, &(pDis->EdidOtherMonitorDescriptor), sizeof(tmbslHdmiTxEdidOtherMD_t)); ++ } ++ else ++ { ++ /* Not allowed if EdidStatus value is not valid */ ++ *pOtherMDAvail = 0; ++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE; ++ } ++ ++ return TM_OK; ++ ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989EdidGetBasicDisplayParam */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989EdidGetBasicDisplayParam ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxEdidBDParam_t *pEdidBDParam ++) ++{ ++ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(pEdidBDParam == Null) ++ ++ if ((pDis->EdidStatus == HDMITX_EDID_READ) || ++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK)) ++ { ++ lmemcpy(pEdidBDParam, &(pDis->EDIDBasicDisplayParam), sizeof(tmbslHdmiTxEdidBDParam_t)); ++ } ++ else ++ { ++ /* Not allowed if EdidStatus value is not valid */ ++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE; ++ } ++ ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989EdidGetVideoCapabilities */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989EdidGetVideoCapabilities ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pEdidVFmts, ++ UInt vFmtLength, ++ UInt *pVFmtsAvail, ++ UInt8 *pVidFlags ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt i; /* Loop index */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(pEdidVFmts == Null) ++ RETIF_BADPARAM(vFmtLength < 1) ++ RETIF_BADPARAM(pVFmtsAvail == Null) ++ RETIF_BADPARAM(pVidFlags == Null) ++ ++ if ((pDis->EdidStatus == HDMITX_EDID_READ) || ++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK)) ++ { ++ /* allow if edid are read or if there are a chk error on an other block than block 0 */ ++ ++ /* Copy the Device Instance Structure EdidVFmts descriptors to ++ * pEdidVFmts until we run out or no more space in structure. ++ */ ++ if (pDis->EdidSvdCnt > 0) ++ { ++ for (i = 0; (i < (UInt)pDis->EdidSvdCnt) && (i < vFmtLength); i++) ++ { ++ pEdidVFmts[i] = pDis->EdidVFmts[i]; ++ } ++ } ++ else ++ { ++ /* No pEdidVFmts to copy so set a zero format to be safe */ ++ pEdidVFmts[0] = HDMITX_VFMT_NULL; ++ } ++ ++ /* Fill Video Flags parameter */ ++ *pVidFlags = ((pDis->EdidCeaFlags & 0x80) | /* Underscan */ ++ ((pDis->EdidCeaFlags & 0x30) << 1) ); /* YUV444, YUV422 */ ++ ++ ++ /* Add info regarding xvYCC support */ ++ *pVidFlags = *pVidFlags | (pDis->EdidCeaXVYCCFlags & 0x03); ++ ++ /* Fill number of SVDs available parameter */ ++ *pVFmtsAvail = pDis->EdidSvdCnt; ++ } ++ else ++ { ++ /* Not allowed if EdidStatus value is not valid */ ++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE; ++ } ++ ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989EdidGetVideoPreferred */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++tmbslTDA9989EdidGetVideoPreferred ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxEdidDtd_t *pEdidDTD ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(pEdidDTD == Null) ++ ++ if ((pDis->EdidStatus == HDMITX_EDID_READ) || ++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK)) ++ { ++ /* allow if edid are read or if there are a chk error on an other block than block 0 */ ++ ++ /* Populate the Detailed Timing Descriptor structure pEdidDTD from ++ * EdidDtd in the Device Instance Structure. ++ */ ++ lmemcpy(pEdidDTD, &pDis->EdidDTD, sizeof(tmbslHdmiTxEdidDtd_t)); ++ } ++ else ++ { ++ /* Not allowed if EdidStatus value is not valid */ ++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE; ++ } ++ return err; ++ ++} ++ ++ ++/*============================================================================*/ ++/* STATIC FUNCTION */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* requestEdidBlock - reads an entire edid block */ ++/*============================================================================*/ ++static tmErrorCode_t ++requestEdidBlock ++( ++ tmHdmiTxobject_t *pDis /* Device instance strucure to use */ ++ ) ++{ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 segptr; /* Segment ptr value */ ++ UInt8 offset; /* Word offset value */ ++ ++ /* Check block number is valid [CEA861C A.2.1] */ ++ RETIF_BADPARAM(pDis->EdidBlockRequested >= 255) ++ ++ err = setHwRegister(pDis, E_REG_P09_DDC_ADDR_RW, DDC_EDID_ADDRESS); ++ RETIF_REG_FAIL(err) ++ ++ /* For even blocks we need an offset of 0, odd blocks we need 128 */ ++ offset = (((UInt8)pDis->EdidBlockRequested & 1) == 1) ? 128 : 0; ++ ++ err = setHwRegister(pDis, E_REG_P09_DDC_OFFS_RW, offset); ++ RETIF_REG_FAIL(err) ++ ++ err = setHwRegister(pDis, E_REG_P09_DDC_SEGM_ADDR_RW, DDC_SGMT_PTR_ADDRESS); ++ RETIF_REG_FAIL(err) ++ ++ /* Calculate which segment of the EDID we need (2 blocks per segment) */ ++ segptr = (UInt8)pDis->EdidBlockRequested / 2; ++ ++ err = setHwRegister(pDis, E_REG_P09_DDC_SEGM_RW, segptr); ++ RETIF_REG_FAIL(err) ++ ++ /* Enable reading EDID */ ++ err = setHwRegister(pDis, E_REG_P09_EDID_CTRL_RW, 0x1); ++ RETIF_REG_FAIL(err) ++ ++ /* The flag to start the EDID reading must cleared by software*/ ++ err = setHwRegister(pDis, E_REG_P09_EDID_CTRL_RW, 0x0); ++ RETIF_REG_FAIL(err) ++ ++ return err; ++} ++ ++/*============================================================================*/ ++/* parseEdidBlock */ ++/*============================================================================*/ ++static tmErrorCode_t ++parseEdidBlock ++( ++ tmHdmiTxobject_t *pDis, /* Device instance strucure holding block */ ++ Int blockNumber /* Block number */ ++ ) ++{ ++ UInt8 i; /* Loop index */ ++ UInt8 blockPtr, endPtr; /* Parsing pointers */ ++ UInt8 blockType, blockLength; ++ Bool dtdFound; ++ UInt8 NbBlkRead, offset3D=0; ++ ++ /* Check block number is valid [CEA861C A.2.1] */ ++ RETIF_BADPARAM(blockNumber >= 255) ++ ++ NbBlkRead = 0; ++ dtdFound = True; ++ blockPtr = 0; ++ ++ if (blockNumber == 0) ++ { ++ pDis->EDIDBasicDisplayParam.uVideoInputDef = pDis->EdidBlock[0x14]; ++ pDis->EDIDBasicDisplayParam.uMaxHorizontalSize = pDis->EdidBlock[0x15]; ++ pDis->EDIDBasicDisplayParam.uMaxVerticalSize = pDis->EdidBlock[0x16]; ++ pDis->EDIDBasicDisplayParam.uGamma = pDis->EdidBlock[0x17]; ++ pDis->EDIDBasicDisplayParam.uFeatureSupport = pDis->EdidBlock[0x18]; ++ ++ /* Block 0 - contains DTDs but no video data block (SVDs) */ ++ for (i = 0; (i < 2) && (dtdFound); i++) /* search 2 possible DTD blocks in block 0 */ ++ { ++ blockPtr = (UInt8)(EDID_BLK0_BASE_DTD + (i * EDID_DTD_BLK_SIZE)); ++ if ((blockPtr + EDID_DTD_BLK_SIZE - 1) < EDID_BLOCK_SIZE) ++ { ++ dtdFound = storeDtdBlock(pDis, blockPtr); ++ if (dtdFound) ++ { ++ NbBlkRead++; ++ } ++ } ++ } ++ ++ dtdFound = True; ++ ++ /* Parse monitor descriptor */ ++ for (i = NbBlkRead; (i < EDID_NB_MAX_DESCRIP_BLK_IN_BLK_0) && (dtdFound); i++) ++ { ++ blockPtr = (UInt8)(EDID_BLK0_BASE_DTD + (i * EDID_DTD_BLK_SIZE)); ++ if ((blockPtr + EDID_DTD_BLK_SIZE - 1) < EDID_BLOCK_SIZE) ++ { ++ dtdFound = storeMonitorDescriptor(pDis, blockPtr); ++ } ++ } ++ } ++ else if (blockNumber >= 1) ++ { ++ switch (pDis->EdidBlock[0]) ++ { ++ /* CEA EXTENSION */ ++ case EDID_CEA_EXTENSION: ++ /* Read CEA flag bits here - lockout when read once??? */ ++ pDis->EdidCeaFlags = pDis->EdidBlock[3]; ++ ++ blockPtr = EDID_BLK_EXT_BASE; /* data block start always fixed */ ++ endPtr = pDis->EdidBlock[2]; /* byte after end of data blocks */ ++ if (endPtr >= (EDID_BLK_EXT_BASE + 2) && (endPtr <= EDID_BLOCK_SIZE)) ++ /* Only try reading if data blocks take up 2 bytes or more, since ++ * a video data block must be at least 2 bytes ++ */ ++ { ++ while (blockPtr < endPtr) ++ { ++ blockType = (UInt8)((pDis->EdidBlock[blockPtr] & 0xE0) >> 5); ++ blockLength = (pDis->EdidBlock[blockPtr] & 0x1F); ++ ++ switch((Int)blockType) ++ { ++ case E_CEA_VIDEO_BLOCK: /* We have a video data block */ ++ for (i = 1; i <= blockLength; i++) ++ { ++ if ((blockPtr + i) < (EDID_BLOCK_SIZE)) ++ { ++ /* If space, store non-zero SVDs */ ++ if ((pDis->EdidBlock[blockPtr + i] != 0) && ++ (pDis->EdidSvdCnt < HDMI_TX_SVD_MAX_CNT)) ++ { ++ pDis->EdidVFmts[pDis->EdidSvdCnt] = ++ pDis->EdidBlock[blockPtr + i]; ++ pDis->EdidSvdCnt++; ++ } ++ } ++ else ++ { ++ /* do nothing */ ++ } ++ } ++ break; ++ case E_CEA_AUDIO_BLOCK: /* We have an audio data block */ ++ for (i = 1; (i + 2) <= blockLength; i += 3) ++ { /* Must loop in steps of 3 (SAD size) */ ++ /* If space, store non-zero SADs */ ++ if ((blockPtr) < (EDID_BLOCK_SIZE -(i +2))) ++ { ++ if (((pDis->EdidBlock[blockPtr + i] & 0x78) != 0) && ++ (pDis->EdidSadCnt < HDMI_TX_SAD_MAX_CNT)) ++ { ++ pDis->EdidAFmts[pDis->EdidSadCnt].ModeChans = ++ pDis->EdidBlock[blockPtr + i]; ++ pDis->EdidAFmts[pDis->EdidSadCnt].Freqs = ++ pDis->EdidBlock[blockPtr + i + 1]; ++ pDis->EdidAFmts[pDis->EdidSadCnt].Byte3 = ++ pDis->EdidBlock[blockPtr + i + 2]; ++ pDis->EdidSadCnt++; ++ } ++ } ++ else ++ { ++ /* do nothing */ ++ } ++ } ++ break; ++ case E_CEA_VSDB: /* We have a VSDB */ ++ /* 5 bytes expected, but this is EDID land so double check*/ ++ if (blockLength >= 5) ++ { ++ if ((blockPtr) < (EDID_BLOCK_SIZE - 5)) ++ { ++ if ((pDis->EdidBlock[blockPtr + 1] == 0x03) && ++ (pDis->EdidBlock[blockPtr + 2] == 0x0C) && ++ (pDis->EdidBlock[blockPtr + 3] == 0x00)) ++ { ++ pDis->EdidSinkType = HDMITX_SINK_HDMI; ++ if ((blockPtr) < (EDID_BLOCK_SIZE - 5)) ++ { ++ pDis->EdidSourceAddress = ++ ((UInt16)pDis->EdidBlock[blockPtr + 4] << 8) + ++ pDis->EdidBlock[blockPtr + 5]; ++ } ++ else ++ { ++ /* do nothing */ ++ } ++ } ++ else ++ { ++ pDis->EdidSinkType = HDMITX_SINK_DVI; ++ } ++ } ++ else ++ { ++ /* do nothing */ ++ } ++ } ++ ++ if (blockLength >= 6) /* Space for byte with AI flag */ ++ { /* Mask AI bit */ ++ if ((blockPtr ) < (EDID_BLOCK_SIZE - 6)) ++ { ++ if((pDis->EdidBlock[blockPtr + 6] & 0x80) == 0x80) ++ { ++ pDis->EdidSinkAi = True; ++ } ++ } ++ else ++ { ++ /* do nothing */ ++ } ++ } ++ ++ /* Read Max_TMDS_Clock */ ++ if (blockLength >= 7) ++ pDis->EdidExtraVsdbData.maxTmdsClock = pDis->EdidBlock[blockPtr + 7]; ++ else ++ pDis->EdidExtraVsdbData.maxTmdsClock = 0; ++ ++ ++ /* latency, HDMI Video present and content type fields */ ++ if (blockLength >= 8) { ++ if ((blockPtr) < (EDID_BLOCK_SIZE - 10)) ++ { ++ /* Read CNC0~3 */ ++ pDis->EdidExtraVsdbData.cnc0 = pDis->EdidBlock[blockPtr + 8] & 0x01; /* 1=True, 0=False */ ++ pDis->EdidExtraVsdbData.cnc1 = (pDis->EdidBlock[blockPtr + 8] & 0x02) >> 1; ++ pDis->EdidExtraVsdbData.cnc2 = (pDis->EdidBlock[blockPtr + 8] & 0x04) >> 2; ++ pDis->EdidExtraVsdbData.cnc3 = (pDis->EdidBlock[blockPtr + 8] & 0x08) >> 3; ++ ++ if( (pDis->EdidBlock[blockPtr + 8] & 0xC0) == 0xC0 ) { ++ /* Read video_latency, audio_latency, I_video_latency, I_audio_latency */ ++ ++ if ((blockPtr) < (EDID_BLOCK_SIZE - 12)) ++ { ++ pDis->EdidLatency.Edidvideo_latency = pDis->EdidBlock[blockPtr + 9]; ++ pDis->EdidLatency.Edidaudio_latency = pDis->EdidBlock[blockPtr + 10]; ++ pDis->EdidLatency.EdidIvideo_latency = pDis->EdidBlock[blockPtr + 11]; ++ pDis->EdidLatency.EdidIaudio_latency = pDis->EdidBlock[blockPtr + 12]; ++ ++ pDis->EdidLatency.latency_available = True; ++ pDis->EdidLatency.Ilatency_available = True; ++ ++ offset3D = 13; /* offset to the '3D_present' field */ ++ ++ } ++ else ++ { ++ /* do nothing */ ++ } ++ } ++ else if ((pDis->EdidBlock[blockPtr + 8] & 0x80) == 0x80) { ++ /* Read video_latency, audio_latency */ ++ ++ pDis->EdidLatency.Edidvideo_latency = pDis->EdidBlock[blockPtr + 9]; ++ pDis->EdidLatency.Edidaudio_latency = pDis->EdidBlock[blockPtr + 10]; ++ ++ pDis->EdidLatency.latency_available = True; ++ ++ offset3D = 11; ++ } ++ else { ++ pDis->EdidLatency.latency_available = False; ++ pDis->EdidLatency.Ilatency_available = False; ++ offset3D = 9; ++ } ++ ++ /* Read HDMI_Video_present */ ++ pDis->EdidExtraVsdbData.hdmiVideoPresent = (pDis->EdidBlock[blockPtr + 8] & 0x20) >> 5; ++ ++ } ++ else ++ { ++ /* do nothing */ ++ } ++ } ++ else { ++ pDis->EdidLatency.latency_available = False; ++ pDis->EdidLatency.Ilatency_available = False; ++ pDis->EdidExtraVsdbData.hdmiVideoPresent = False; ++ pDis->EdidExtraVsdbData.cnc0 = False; ++ pDis->EdidExtraVsdbData.cnc1 = False; ++ pDis->EdidExtraVsdbData.cnc2 = False; ++ pDis->EdidExtraVsdbData.cnc3 = False; ++ } ++ ++ ++ /* 3D data fields according to HDMI 1.4a standard */ ++ if (pDis->EdidExtraVsdbData.hdmiVideoPresent) { ++ ++ /* read 3D_present */ ++ pDis->EdidExtraVsdbData.h3DPresent = (pDis->EdidBlock[blockPtr + offset3D] & 0x80) >> 7; ++ /* read 3D_Multi_present */ ++ pDis->EdidExtraVsdbData.h3DMultiPresent = (pDis->EdidBlock[blockPtr + offset3D] & 0x60) >> 5; ++ /* read image_Size */ ++ pDis->EdidExtraVsdbData.imageSize = (pDis->EdidBlock[blockPtr + offset3D] & 0x18) >> 3; ++ ++ /* read HDMI_3D_LEN and HDMI_XX_LEN */ ++ offset3D += 1; ++ pDis->EdidExtraVsdbData.hdmi3DLen = pDis->EdidBlock[blockPtr + offset3D] & 0x1F; ++ pDis->EdidExtraVsdbData.hdmiVicLen = (pDis->EdidBlock[blockPtr + offset3D] & 0xE0) >> 5; ++ ++ if((pDis->EdidExtraVsdbData.hdmi3DLen + pDis->EdidExtraVsdbData.hdmiVicLen) > 0) ++ { ++ /* copy the rest of the bytes*/ ++ lmemcpy(pDis->EdidExtraVsdbData.ext3DData, &(pDis->EdidBlock[blockPtr + offset3D + 1]), blockLength-offset3D); ++ } ++ } ++ else { ++ pDis->EdidExtraVsdbData.h3DPresent = False; ++ pDis->EdidExtraVsdbData.h3DMultiPresent = 0; ++ pDis->EdidExtraVsdbData.imageSize = 0; ++ pDis->EdidExtraVsdbData.hdmi3DLen = 0; ++ pDis->EdidExtraVsdbData.hdmiVicLen = 0; ++ } ++ ++ ++ break; ++ ++ ++ case E_CEA_EXTENDED: /* Use extended Tag */ ++ ++ /* we need to read the extended tag code */ ++ ++ if ((blockPtr ) < (EDID_BLOCK_SIZE -2)) ++ { ++ switch ( pDis->EdidBlock[blockPtr + 1]) ++ { ++ case EXT_CEA_COLORIMETRY_DB: ++ ++ /* look at xvYCC709 and xvYCC601 support */ ++ pDis->EdidCeaXVYCCFlags = pDis->EdidBlock[blockPtr + 2]; ++ ++ break; ++ } ++ } ++ else ++ { ++ /* do nothing */ ++ } ++ break; /* E_CEA_EXTENDED */ ++ ++ ++ ++ default: ++ break; ++ } ++ blockPtr += (blockLength + 1); /* Point to next block */ ++ } ++ } ++ dtdFound = True; ++ ++ for (i = 0; (i < EDID_NUMBER_MAX_DTD_BLK_1) && (dtdFound); i++) /* search possible DTD blocks in block 1 */ ++ { ++ blockPtr = ((UInt8)pDis->EdidBlock[EDID_BLK1_OFFSET_BASE_DTD]) + ((UInt8)(i * EDID_DTD_BLK_SIZE)); ++ if ((blockPtr + EDID_DTD_BLK_SIZE - 1) < EDID_BLOCK_SIZE) ++ { ++ dtdFound = storeDtdBlock(pDis, blockPtr); ++ } ++ } ++ ++ break; ++ ++ ++ case EDID_BLOCK_MAP: ++ /* BLOCK MAP */ ++ ++ if (pDis->EdidBlockCnt > 1) { ++ if ((pDis->EdidBlockCnt - 1) < EDID_BLOCK_SIZE) ++ { ++ if (pDis->EdidBlock[pDis->EdidBlockCnt - 1] == EDID_CEA_EXTENSION) { ++ /* Some devices have been incorrectly designed so that the block map is not counted in the */ ++ /* extension count. Design of compliant devices should take compatibility with those non-compliant */ ++ /* devices into consideration. */ ++ pDis->EdidBlockCnt = pDis->EdidBlockCnt + 1; ++ } ++ } ++ else ++ { ++ /* do nothing */ ++ } ++ } ++ ++ ++ break; ++ ++ ++ } ++ ++ } ++ ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* storeDtdBlock */ ++/*============================================================================*/ ++static Bool ++storeDtdBlock ++( ++ tmHdmiTxobject_t *pDis, /* Device instance strucure holding block */ ++ UInt8 blockPtr ++) ++{ ++ ++ Bool dtdFound = False; ++ ++ if (blockPtr >= (EDID_BLOCK_SIZE-17)) ++ { ++ /* do nothing */ ++ return dtdFound; ++ } ++ ++ /* First, select blocks that are DTDs [CEA861C A.2.10] */ ++ if (((pDis->EdidBlock[blockPtr+0] != 0) || ++ (pDis->EdidBlock[blockPtr+1] != 0) || ++ (pDis->EdidBlock[blockPtr+2] != 0) || ++ (pDis->EdidBlock[blockPtr+4] != 0)) ++ && ++ (pDis->NbDTDStored < NUMBER_DTD_STORED)) ++ { /* Store the first DTD we find, others will be skipped */ ++ pDis->EdidDTD[pDis->NbDTDStored].uPixelClock = ++ ((UInt16)pDis->EdidBlock[blockPtr+1] << 8) | ++ (UInt16)pDis->EdidBlock[blockPtr+0]; ++ ++ pDis->EdidDTD[pDis->NbDTDStored].uHActivePixels = ++ (((UInt16)pDis->EdidBlock[blockPtr+4] & 0x00F0) << 4) | ++ (UInt16)pDis->EdidBlock[blockPtr+2]; ++ ++ pDis->EdidDTD[pDis->NbDTDStored].uHBlankPixels = ++ (((UInt16)pDis->EdidBlock[blockPtr+4] & 0x000F) << 8) | ++ (UInt16)pDis->EdidBlock[blockPtr+3]; ++ ++ pDis->EdidDTD[pDis->NbDTDStored].uVActiveLines = ++ (((UInt16)pDis->EdidBlock[blockPtr+7] & 0x00F0) << 4) | ++ (UInt16)pDis->EdidBlock[blockPtr+5]; ++ ++ pDis->EdidDTD[pDis->NbDTDStored].uVBlankLines = ++ (((UInt16)pDis->EdidBlock[blockPtr+7] & 0x000F) << 8) | ++ (UInt16)pDis->EdidBlock[blockPtr+6]; ++ ++ pDis->EdidDTD[pDis->NbDTDStored].uHSyncOffset = ++ (((UInt16)pDis->EdidBlock[blockPtr+11] & 0x00C0) << 2) | ++ (UInt16)pDis->EdidBlock[blockPtr+8]; ++ ++ pDis->EdidDTD[pDis->NbDTDStored].uHSyncWidth = ++ (((UInt16)pDis->EdidBlock[blockPtr+11] & 0x0030) << 4) | ++ (UInt16)pDis->EdidBlock[blockPtr+9]; ++ ++ pDis->EdidDTD[pDis->NbDTDStored].uVSyncOffset = ++ (((UInt16)pDis->EdidBlock[blockPtr+11] & 0x000C) << 2) | ++ (((UInt16)pDis->EdidBlock[blockPtr+10] & 0x00F0) >> 4); ++ ++ pDis->EdidDTD[pDis->NbDTDStored].uVSyncWidth = ++ (((UInt16)pDis->EdidBlock[blockPtr+11] & 0x0003) << 4) | ++ ((UInt16)pDis->EdidBlock[blockPtr+10] & 0x000F); ++ ++ pDis->EdidDTD[pDis->NbDTDStored].uHImageSize = ++ (((UInt16)pDis->EdidBlock[blockPtr+14] & 0x00F0) << 4) | ++ (UInt16)pDis->EdidBlock[blockPtr+12]; ++ ++ pDis->EdidDTD[pDis->NbDTDStored].uVImageSize = ++ (((UInt16)pDis->EdidBlock[blockPtr+14] & 0x000F) << 8) | ++ (UInt16)pDis->EdidBlock[blockPtr+13]; ++ ++ pDis->EdidDTD[pDis->NbDTDStored].uHBorderPixels = ++ (UInt16)pDis->EdidBlock[blockPtr+15]; ++ ++ pDis->EdidDTD[pDis->NbDTDStored].uVBorderPixels = ++ (UInt16)pDis->EdidBlock[blockPtr+16]; ++ ++ pDis->EdidDTD[pDis->NbDTDStored].Flags = pDis->EdidBlock[blockPtr+17]; ++ ++ pDis->NbDTDStored++; ++ ++ dtdFound = True; /* Stop any more DTDs being parsed */ ++ } ++ ++ return (dtdFound); ++} ++ ++ ++/*============================================================================*/ ++/* storeMonitorBlock */ ++/*============================================================================*/ ++static Bool ++storeMonitorDescriptor ++( ++ tmHdmiTxobject_t *pDis, /* Device instance strucure holding block */ ++ UInt8 blockPtr ++) ++{ ++ ++ Bool dtdFound = False; ++ ++ if (blockPtr >= (EDID_BLOCK_SIZE-5)) ++ { ++ /* do nothing */ ++ return dtdFound; ++ } ++ ++ /* First, select blocks that are DTDs [CEA861C A.2.10] */ ++ if ((pDis->EdidBlock[blockPtr+0] == 0) && ++ (pDis->EdidBlock[blockPtr+1] == 0) && ++ (pDis->EdidBlock[blockPtr+2] == 0) ++ ) ++ { ++ if (pDis->EdidBlock[blockPtr+3] == EDID_MONITOR_NAME_DESC_DATA_TYPE) ++ { ++ if (pDis->EdidFirstMonitorDescriptor.bDescRecord == False) ++ { ++ pDis->EdidFirstMonitorDescriptor.bDescRecord = True; ++ lmemcpy(&(pDis->EdidFirstMonitorDescriptor.uMonitorName) , ++ &(pDis->EdidBlock[blockPtr+5]), EDID_MONITOR_DESCRIPTOR_SIZE); ++ dtdFound = True; ++ } ++ else if ((pDis->EdidOtherMonitorDescriptor.bDescRecord == False)) ++ { ++ pDis->EdidOtherMonitorDescriptor.bDescRecord = True; ++ lmemcpy(&(pDis->EdidOtherMonitorDescriptor.uOtherDescriptor) , ++ &(pDis->EdidBlock[blockPtr+5]), EDID_MONITOR_DESCRIPTOR_SIZE); ++ dtdFound = True; ++ } ++ } ++ else if (pDis->EdidBlock[blockPtr+3] == EDID_MONITOR_RANGE_DESC_DATA_TYPE) ++ { ++ if (pDis->EdidSecondMonitorDescriptor.bDescRecord == False) ++ { ++ if (blockPtr < (EDID_BLOCK_SIZE-9)) ++ { ++ pDis->EdidSecondMonitorDescriptor.bDescRecord = True; ++ pDis->EdidSecondMonitorDescriptor.uMinVerticalRate = pDis->EdidBlock[blockPtr+5]; ++ pDis->EdidSecondMonitorDescriptor.uMaxVerticalRate = pDis->EdidBlock[blockPtr+6]; ++ pDis->EdidSecondMonitorDescriptor.uMinHorizontalRate = pDis->EdidBlock[blockPtr+7]; ++ pDis->EdidSecondMonitorDescriptor.uMaxHorizontalRate = pDis->EdidBlock[blockPtr+8]; ++ pDis->EdidSecondMonitorDescriptor.uMaxSupportedPixelClk = pDis->EdidBlock[blockPtr+9]; ++ dtdFound = True; ++ } ++ else ++ { ++ /* do nothing */ ++ } ++ } ++ } ++ } ++ ++ return (dtdFound); ++ ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989EdidGetLatencyInfo */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989EdidGetLatencyInfo ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxEdidLatency_t * pEdidLatency ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(pEdidLatency == Null) ++ ++ if ((pDis->EdidStatus == HDMITX_EDID_READ) || ++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK)) ++ { ++ /* allow if edid are read or if there are a chk error on an other block than block 0 */ ++ ++ *pEdidLatency = pDis->EdidLatency; ++ } ++ else ++ { ++ /* Not allowed if EdidStatus value is not valid */ ++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE; ++ } ++ return err; ++ ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989EdidGetExtraVsdbData */ ++/*============================================================================*/ ++tmErrorCode_t tmbslTDA9989EdidGetExtraVsdbData ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxEdidExtraVsdbData_t **pExtraVsdbData ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(pExtraVsdbData == Null) ++ ++ if ((pDis->EdidStatus == HDMITX_EDID_READ) || ++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK)) ++ { ++ /* allow if edid are read or if there are a chk error on an other block than block 0 */ ++ *pExtraVsdbData = &(pDis->EdidExtraVsdbData); ++ } ++ else ++ { ++ /* Not allowed if EdidStatus value is not valid */ ++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE; ++ } ++ return err; ++} ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid_l.h b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid_l.h +new file mode 100755 +index 0000000..25cad98 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid_l.h +@@ -0,0 +1,62 @@ ++/** ++ * Copyright (C) 2009 Koninklijke Philips Electronics N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of Koninklijke Philips Electronics N.V. and is confidential in ++ * nature. Under no circumstances is this software to be exposed to or placed ++ * under an Open Source License of any type without the expressed written ++ * permission of Koninklijke Philips Electronics N.V. ++ * ++ * \file tmbslTDA9989_Edid_l.h ++ * ++ * \version $Revision: 2 $ ++ * ++ * \date $Date: 04/07/07 17:00 $ ++ * ++ * ++*/ ++ ++#ifndef TMBSLTDA9989_EDID_L_H ++#define TMBSLTDA9989_EDID_L_H ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*============================================================================*/ ++/* MACRO DEFINITIONS */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* ENUM OR TYPE DEFINITIONS */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* EXTERN DATA DEFINITION */ ++/*============================================================================*/ ++ ++extern tmErrorCode_t ++EdidBlockAvailable (tmUnitSelect_t txUnit, Bool * pSendEDIDCallback); ++ ++extern tmErrorCode_t ++ClearEdidRequest (tmUnitSelect_t txUnit); ++ ++/*============================================================================*/ ++/* EXTERN FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++ ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMBSLTDA9989_EDID_L_H */ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP.c b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP.c +new file mode 100755 +index 0000000..33ab4d1 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP.c +@@ -0,0 +1,655 @@ ++/** ++ * Copyright (C) 2009 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmbslTDA9989_HDCP.c ++ * ++ * \version $Revision: 2 $ ++ * ++ */ ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#include "tmbslHdmiTx_types.h" ++#include "tmbslTDA9989_Functions.h" ++#include "tmbslTDA9989_local.h" ++#include "tmbslTDA9989_State_l.h" ++#include "tmbslTDA9989_InOut_l.h" ++ ++/*============================================================================*/ ++/* TYPES DECLARATIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* CONSTANTS DECLARATIONS EXPORTED */ ++/*============================================================================*/ ++ ++/** ++ * Table of registers to switch HDMI HDCP mode off for DVI ++ */ ++ ++CONST_DAT tmHdmiTxRegMaskVal_t kVoutHdcpOff[] = ++ { ++ {E_REG_P00_TBG_CNTRL_1_W, E_MASKREG_P00_TBG_CNTRL_1_dwin_dis, 1}, ++ {E_REG_P12_TX33_RW, E_MASKREG_P12_TX33_hdmi, 0}, ++ {0,0,0} ++ }; ++ ++/** ++ * Table of registers to switch HDMI HDCP mode on for HDMI ++ */ ++CONST_DAT tmHdmiTxRegMaskVal_t kVoutHdcpOn[] = ++ { ++ {E_REG_P00_TBG_CNTRL_1_W, E_MASKREG_P00_TBG_CNTRL_1_dwin_dis, 0}, ++ {E_REG_P11_ENC_CNTRL_RW, E_MASKREG_P11_ENC_CNTRL_ctl_code, 1}, ++ {E_REG_P12_TX33_RW, E_MASKREG_P12_TX33_hdmi, 1}, ++ {0,0,0} ++ }; ++ ++#ifdef __LINUX_ARM_ARCH__ ++ ++#include ++ ++typedef struct { ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpCheck) ++ ( ++ tmUnitSelect_t txUnit, ++ UInt16 uTimeSinceLastCallMs, ++ tmbslHdmiTxHdcpCheck_t *pResult ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpConfigure) ++ ( ++ tmUnitSelect_t txUnit, ++ UInt8 slaveAddress, ++ tmbslHdmiTxHdcpTxMode_t txMode, ++ tmbslHdmiTxHdcpOptions_t options, ++ UInt16 uCheckIntervalMs, ++ UInt8 uChecksToDo ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpDownloadKeys) ++ ( ++ tmUnitSelect_t txUnit, ++ UInt16 seed, ++ tmbslHdmiTxDecrypt_t keyDecryption ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpEncryptionOn) ++ ( ++ tmUnitSelect_t txUnit, ++ Bool bOn ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpGetOtp) ++ ( ++ tmUnitSelect_t txUnit, ++ UInt8 otpAddress, ++ UInt8 *pOtpData ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpGetT0FailState) ++ ( ++ tmUnitSelect_t txUnit, ++ UInt8 *pFailState ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpHandleBCAPS) ++ ( ++ tmUnitSelect_t txUnit ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpHandleBKSV) ++ ( ++ tmUnitSelect_t txUnit, ++ UInt8 *pBksv, ++ Bool *pbCheckRequired /* May be null, but only for testing */ ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpHandleBKSVResult) ++ ( ++ tmUnitSelect_t txUnit, ++ Bool bSecure ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpHandleBSTATUS) ++ ( ++ tmUnitSelect_t txUnit, ++ UInt16 *pBstatus /* May be null */ ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpHandleENCRYPT) ++ ( ++ tmUnitSelect_t txUnit ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpHandlePJ) ++ ( ++ tmUnitSelect_t txUnit ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpHandleSHA_1) ++ ( ++ tmUnitSelect_t txUnit, ++ UInt8 maxKsvDevices, ++ UInt8 *pKsvList, /* May be null if maxKsvDevices is 0 */ ++ UInt8 *pnKsvDevices, /* May be null if maxKsvDevices is 0 */ ++ UInt8 *pDepth /* Connection tree depth returned with KSV list */ ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpHandleSHA_1Result) ++ ( ++ tmUnitSelect_t txUnit, ++ Bool bSecure ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpHandleT0) ++ ( ++ tmUnitSelect_t txUnit ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpInit) ++ ( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ tmbslHdmiTxVfreq_t voutFreq ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpRun) ++ ( ++ tmUnitSelect_t txUnit ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpStop) ++ ( ++ tmUnitSelect_t txUnit ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989HdcpGetSinkCategory) ++ ( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxSinkCategory_t *category ++ ); ++ tmErrorCode_t ++ (*tmbslTDA9989handleBKSVResultSecure) ++ ( ++ tmUnitSelect_t txUnit ++ ); ++ tmErrorCode_t (*f1)(tmHdmiTxobject_t *pDis); ++ int (*f2)(tmHdmiTxobject_t *pDis); ++} hdcp_private_t; ++ ++#include /* need for EXPORT_SYMBOL */ ++ ++hdcp_private_t *h; ++ ++void register_hdcp_private(hdcp_private_t *hdcp) ++{ ++ h = hdcp; ++} ++EXPORT_SYMBOL(register_hdcp_private); ++ ++tmErrorCode_t rej_f1(tmHdmiTxobject_t *pDis) { ++ return (h?h->f1(pDis):0); ++} ++ ++int rej_f2(tmHdmiTxobject_t *pDis) { ++ return (h?h->f2(pDis):0); ++} ++ ++tmErrorCode_t rej_f3(tmUnitSelect_t txUnit) { ++ return (h?h->tmbslTDA9989handleBKSVResultSecure(txUnit):TM_OK); ++} ++ ++#endif ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpCheck */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpCheck ++( ++ tmUnitSelect_t txUnit, ++ UInt16 uTimeSinceLastCallMs, ++ tmbslHdmiTxHdcpCheck_t *pResult ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpCheck ++ ( ++ txUnit, ++ uTimeSinceLastCallMs, ++ pResult ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpConfigure */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpConfigure ++( ++ tmUnitSelect_t txUnit, ++ UInt8 slaveAddress, ++ tmbslHdmiTxHdcpTxMode_t txMode, ++ tmbslHdmiTxHdcpOptions_t options, ++ UInt16 uCheckIntervalMs, ++ UInt8 uChecksToDo ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpConfigure ++ ( ++ txUnit, ++ slaveAddress, ++ txMode, ++ options, ++ uCheckIntervalMs, ++ uChecksToDo ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpDownloadKeys */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpDownloadKeys ++( ++ tmUnitSelect_t txUnit, ++ UInt16 seed, ++ tmbslHdmiTxDecrypt_t keyDecryption ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpDownloadKeys ++ ( ++ txUnit, ++ seed, ++ keyDecryption ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpEncryptionOn */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpEncryptionOn ++( ++ tmUnitSelect_t txUnit, ++ Bool bOn ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpEncryptionOn ++ ( ++ txUnit, ++ bOn ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpGetOtp */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpGetOtp ++( ++ tmUnitSelect_t txUnit, ++ UInt8 otpAddress, ++ UInt8 *pOtpData ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpGetOtp ++ ( ++ txUnit, ++ otpAddress, ++ pOtpData ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpGetT0FailState */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpGetT0FailState ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pFailState ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpGetT0FailState ++ ( ++ txUnit, ++ pFailState ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpHandleBCAPS */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandleBCAPS ++( ++ tmUnitSelect_t txUnit ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpHandleBCAPS ++ ( ++ txUnit ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++ ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpHandleBKSV */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandleBKSV ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pBksv, ++ Bool *pbCheckRequired /* May be null, but only for testing */ ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpHandleBKSV ++ ( ++ txUnit, ++ pBksv, ++ pbCheckRequired /* May be null, but only for testing */ ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++ ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpHandleBKSVResult */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandleBKSVResult ++( ++ tmUnitSelect_t txUnit, ++ Bool bSecure ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpHandleBKSVResult ++ ( ++ txUnit, ++ bSecure ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++ ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpHandleBSTATUS */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandleBSTATUS ++( ++ tmUnitSelect_t txUnit, ++ UInt16 *pBstatus /* May be null */ ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpHandleBSTATUS ++ ( ++ txUnit, ++ pBstatus /* May be null */ ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++ ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpHandleENCRYPT */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandleENCRYPT ++( ++ tmUnitSelect_t txUnit ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpHandleENCRYPT ++ ( ++ txUnit ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++ ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpHandlePJ */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandlePJ ++( ++ tmUnitSelect_t txUnit ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpHandlePJ ++ ( ++ txUnit ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++ ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpHandleSHA_1 */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandleSHA_1 ++( ++ tmUnitSelect_t txUnit, ++ UInt8 maxKsvDevices, ++ UInt8 *pKsvList, /* May be null if maxKsvDevices is 0 */ ++ UInt8 *pnKsvDevices, /* May be null if maxKsvDevices is 0 */ ++ UInt8 *pDepth /* Connection tree depth returned with KSV list */ ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpHandleSHA_1 ++ ( ++ txUnit, ++ maxKsvDevices, ++ pKsvList, /* May be null if maxKsvDevices is 0 */ ++ pnKsvDevices, /* May be null if maxKsvDevices is 0 */ ++ pDepth /* Connection tree depth returned with KSV list */ ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpHandleSHA_1Result */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandleSHA_1Result ++( ++ tmUnitSelect_t txUnit, ++ Bool bSecure ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpHandleSHA_1Result ++ ( ++ txUnit, ++ bSecure ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpHandleT0 */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpHandleT0 ++( ++ tmUnitSelect_t txUnit ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpHandleT0 ++ ( ++ txUnit ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpInit */ ++/* RETIF_REG_FAIL NOT USED HERE AS ALL ERRORS SHOULD BE TRAPPED IN ALL BUILDS */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpInit ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ tmbslHdmiTxVfreq_t voutFreq ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpInit ++ ( ++ txUnit, ++ voutFmt, ++ voutFreq ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpRun */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpRun ++( ++ tmUnitSelect_t txUnit ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpRun ++ ( ++ txUnit ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpStop */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpStop ++( ++ tmUnitSelect_t txUnit ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpStop ++ ( ++ txUnit ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HdcpGetSinkCategory */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpGetSinkCategory ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxSinkCategory_t *category ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989HdcpGetSinkCategory ++ ( ++ txUnit, ++ category ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++ ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989handleBKSVResultSecure */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989handleBKSVResultSecure ++( ++ tmUnitSelect_t txUnit ++ ) ++{ ++#ifdef __LINUX_ARM_ARCH__ ++ if (h) return h->tmbslTDA9989handleBKSVResultSecure ++ ( ++ txUnit ++ ); ++/* else {printk("%s is empty\n",__func__);}*/ ++#endif ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP_l.h b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP_l.h +new file mode 100755 +index 0000000..7e74ab6 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP_l.h +@@ -0,0 +1,72 @@ ++/** ++ * Copyright (C) 2008 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmbslTDA9989_HDCP_l.h ++ * ++ * \version %version: 2 % ++ * ++ * \date %date_modified: % ++ * ++ * \brief BSL driver component local definitions for the TDA998x ++ * HDMI Transmitter. ++ * ++ * \section info Change Information ++ * ++ * ++*/ ++ ++#ifndef TMBSLTDA9989_HDCP_L_H ++#define TMBSLTDA9989_HDCP_L_H ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#ifdef __LINUX_ARM_ARCH__ ++ ++#define HDCP_F1 { \ ++ int rej_f2(tmHdmiTxobject_t *pDis); \ ++ regVal = rej_f2(pDis); \ ++ } ++ ++#define HDCP_F2 { \ ++ tmErrorCode_t rej_f1(tmHdmiTxobject_t *pDis); \ ++ err = rej_f1(pDis); \ ++ RETIF(err != TM_OK, err); \ ++} ++ ++#define HDCP_F3 { \ ++ if (fInterruptStatus & (1 << HDMITX_CALLBACK_INT_R0)) \ ++ { \ ++ tmErrorCode_t rej_f3(tmUnitSelect_t txUnit); \ ++ err = rej_f3(txUnit); \ ++ RETIF(err != TM_OK, err); \ ++ } \ ++} ++ ++#else ++ ++#define HDCP_F1 {regVal = 0;} ++ ++#define HDCP_F2 {} ++ ++#define HDCP_F3 {} ++ ++#endif /*TMFL_HDCP_SUPPORT*/ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMBSLTDA9989_HDCP_L_H */ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_InOut.c b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_InOut.c +new file mode 100755 +index 0000000..8ff0b65 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_InOut.c +@@ -0,0 +1,5101 @@ ++/** ++ * Copyright (C) 2009 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmbslTDA9989_InOut.c ++ * ++ * \version %version: 3 % ++ * ++ * ++*/ ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++#include ++#include ++#endif ++ ++#include "tmbslHdmiTx_types.h" ++#include "tmbslTDA9989_Functions.h" ++#include "tmbslTDA9989_local.h" ++#include "tmbslTDA9989_HDCP_l.h" ++#include "tmbslTDA9989_State_l.h" ++#include "tmbslTDA9989_Misc_l.h" ++#include "tmbslTDA9989_InOut_l.h" ++ ++/*============================================================================*/ ++/* TYPES DECLARATIONS */ ++/*============================================================================*/ ++ ++#define SSD_UNUSED_VALUE 0xF0 ++ ++#ifdef FORMAT_PC ++#define DEPTH_COLOR_PC 1 /* PC_FORMAT only 8 bits available */ ++#endif /* FORMAT_PC */ ++ ++#define REG_VAL_SEL_AIP_SPDIF 0 ++#define REG_VAL_SEL_AIP_I2S 1 ++#define REG_VAL_SEL_AIP_OBA 2 ++#define REG_VAL_SEL_AIP_DST 3 ++#define REG_VAL_SEL_AIP_HBR 5 ++ ++struct vic2reg { ++ unsigned char vic; ++ unsigned char reg; ++}; ++ ++struct sync_desc { ++ UInt16 Vs2; ++ UInt8 pix_rep; ++ UInt8 v_toggle; ++ UInt8 h_toggle; ++ UInt16 hfp; /* Output values for Vs/Hs input sync */ ++ UInt16 vfp; ++ UInt16 href; /* Output values for all other input sync sources */ ++ UInt16 vref; ++}; ++ ++/*============================================================================*/ ++/* CONSTANTS DECLARATIONS EXPORTED */ ++/*============================================================================*/ ++ ++extern CONST_DAT tmHdmiTxRegMaskVal_t kVoutHdcpOff[]; ++extern CONST_DAT tmHdmiTxRegMaskVal_t kVoutHdcpOn[]; ++ ++/** ++ * Lookup table of input port control registers and their swap and mirror masks ++ */ ++CONST_DAT tmbslTDA9989RegVip ++ kRegVip[HDMITX_VIN_PORT_MAP_TABLE_LEN] = ++{ ++ {E_REG_P00_VIP_CNTRL_0_W, ++ E_MASKREG_P00_VIP_CNTRL_0_swap_a, ++ E_MASKREG_P00_VIP_CNTRL_0_mirr_a ++ }, /* Port group 0 */ ++ {E_REG_P00_VIP_CNTRL_0_W, ++ E_MASKREG_P00_VIP_CNTRL_0_swap_b, ++ E_MASKREG_P00_VIP_CNTRL_0_mirr_b ++ }, /* Port group 1 */ ++ {E_REG_P00_VIP_CNTRL_1_W, ++ E_MASKREG_P00_VIP_CNTRL_1_swap_c, ++ E_MASKREG_P00_VIP_CNTRL_1_mirr_c ++ }, /* Port group 2 */ ++ {E_REG_P00_VIP_CNTRL_1_W, ++ E_MASKREG_P00_VIP_CNTRL_1_swap_d, ++ E_MASKREG_P00_VIP_CNTRL_1_mirr_d ++ }, /* Port group 3 */ ++ {E_REG_P00_VIP_CNTRL_2_W, ++ E_MASKREG_P00_VIP_CNTRL_2_swap_e, ++ E_MASKREG_P00_VIP_CNTRL_2_mirr_e ++ }, /* Port group 4 */ ++ {E_REG_P00_VIP_CNTRL_2_W, ++ E_MASKREG_P00_VIP_CNTRL_2_swap_f, ++ E_MASKREG_P00_VIP_CNTRL_2_mirr_f ++ } /* Port group 5 */ ++}; ++ ++/** ++ * Table of PLL settings registers to configure for all video input format (vinFmt) ++ */ ++CONST_DAT tmHdmiTxRegMaskVal_t kCommonPllCfg[] = ++{ ++ {E_REG_P02_PLL_SERIAL_1_RW, E_MASKREG_ALL, 0x00}, ++ {E_REG_P02_PLL_SERIAL_2_RW, E_MASKREG_ALL, 0x01}, ++ {E_REG_P02_PLL_SERIAL_3_RW, E_MASKREG_ALL, 0x00}, ++ {E_REG_P02_SERIALIZER_RW, E_MASKREG_ALL, 0x00}, ++ {E_REG_P02_BUFFER_OUT_RW, E_MASKREG_ALL, 0x00}, ++ {E_REG_P02_PLL_SCG1_RW, E_MASKREG_ALL, 0x00}, ++ {E_REG_P02_AUDIO_DIV_RW, E_MASKREG_ALL, 0x03}, ++ /*{E_REG_P02_TEST2_RW, E_MASKREG_ALL, 0x00},*/ ++ {E_REG_P02_SEL_CLK_RW, E_MASKREG_ALL, 0x09}, ++ {0,0,0} ++}; ++ ++/** ++ * Table of PLL settings registers to configure double mode pixel rate, ++ * vinFmt other than 480i or 576i ++ */ ++CONST_DAT tmHdmiTxRegMaskVal_t kDoublePrateVfmtOtherPllCfg[] = ++{ ++ {E_REG_P02_PLL_SCG2_RW, E_MASKREG_ALL, 0x00}, ++ {0,0,0} ++}; ++ ++/** ++ * Table of PLL settings registers to configure for single mode pixel rate, ++ * vinFmt 480i or 576i only ++ */ ++CONST_DAT tmHdmiTxRegMaskVal_t kSinglePrateVfmt480i576iPllCfg[] = ++{ ++ {E_REG_P02_PLL_SCG2_RW, E_MASKREG_ALL, 0x11}, ++ {0,0,0} ++}; ++ ++/** ++ * Table of PLL settings registers to configure single mode pixel rate, ++ * vinFmt other than 480i or 576i ++ */ ++CONST_DAT tmHdmiTxRegMaskVal_t kSinglePrateVfmtOtherPllCfg[] = ++{ ++ {E_REG_P02_PLL_SCG2_RW, E_MASKREG_ALL, 0x10}, ++ {0,0,0} ++}; ++ ++/** ++ * Table of PLL settings registers to configure for single repeated mode pixel rate, ++ * vinFmt 480i or 576i only ++ */ ++CONST_DAT tmHdmiTxRegMaskVal_t kSrepeatedPrateVfmt480i576iPllCfg[] = ++{ ++ {E_REG_P02_PLL_SCG2_RW, E_MASKREG_ALL, 0x01}, ++ {0,0,0} ++}; ++ ++/** ++ * Table of PLL settings registers to configure for 480i and 576i vinFmt ++ */ ++CONST_DAT tmHdmiTxRegMaskVal_t kVfmt480i576iPllCfg[] = ++{ ++ {E_REG_P02_PLL_SCGN1_RW, E_MASKREG_ALL, 0x14}, ++ {E_REG_P02_PLL_SCGN2_RW, E_MASKREG_ALL, 0x00}, ++ {E_REG_P02_PLL_SCGR1_RW, E_MASKREG_ALL, 0x0A}, ++ {E_REG_P02_PLL_SCGR2_RW, E_MASKREG_ALL, 0x00}, ++ {0,0,0} ++}; ++ ++/** ++ * Table of PLL settings registers to configure for other vinFmt than 480i and 576i ++ */ ++CONST_DAT tmHdmiTxRegMaskVal_t kVfmtOtherPllCfg[] = ++{ ++ {E_REG_P02_PLL_SCGN1_RW, E_MASKREG_ALL, 0xFA}, ++ {E_REG_P02_PLL_SCGN2_RW, E_MASKREG_ALL, 0x00}, ++ {E_REG_P02_PLL_SCGR1_RW, E_MASKREG_ALL, 0x5B}, ++ {E_REG_P02_PLL_SCGR2_RW, E_MASKREG_ALL, 0x00}, ++ {0,0,0} ++}; ++ ++/** ++ * Lookup table to convert from EIA/CEA TV video formats used in the EDID and ++ * in API parameters to pixel clock frequencies, according to SCS Table ++ * "HDMI Pixel Clock Frequencies per EIA/CEA-861B Video Output Format". ++ * The other index is the veritical frame frequency. ++ */ ++ ++CONST_DAT UInt8 kVfmtToPixClk_TV[HDMITX_VFMT_TV_MAX][HDMITX_VFREQ_NUM] = ++{ ++ /* HDMITX_VFREQ_24Hz HDMITX_VFREQ_25Hz HDMITX_VFREQ_30Hz HDMITX_VFREQ_50Hz HDMITX_VFREQ_59Hz HDMITX_VFREQ_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_25175, E_PIXCLK_25200}, /* HDMITX_VFMT_01_640x480p_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_27027}, /* HDMITX_VFMT_02_720x480p_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_27027}, /* HDMITX_VFMT_03_720x480p_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_74175, E_PIXCLK_74250}, /* HDMITX_VFMT_04_1280x720p_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_74175, E_PIXCLK_74250}, /* HDMITX_VFMT_05_1920x1080i_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_27027}, /* HDMITX_VFMT_06_720x480i_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_27027}, /* HDMITX_VFMT_07_720x480i_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_27027}, /* HDMITX_VFMT_08_720x240p_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_27027}, /* HDMITX_VFMT_09_720x240p_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_54054}, /* HDMITX_VFMT_10_720x480i_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_54054}, /* HDMITX_VFMT_11_720x480i_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_54054}, /* HDMITX_VFMT_12_720x240p_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_54054}, /* HDMITX_VFMT_13_720x240p_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_54054}, /* HDMITX_VFMT_14_1440x480p_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_54054}, /* HDMITX_VFMT_15_1440x480p_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_148350, E_PIXCLK_148500}, /* HDMITX_VFMT_16_1920x1080p_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_17_720x576p_50Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_18_720x576p_50Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_74250, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_19_1280x720p_50Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_74250, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_20_1920x1080i_50Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_21_720x576i_50Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_22_720x576i_50Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_23_720x288p_50Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_24_720x288p_50Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_25_720x576i_50Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_26_720x576i_50Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_27_720x288p_50Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_28_720x288p_50Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_29_1440x576p_50Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_30_1440x576p_50Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_148500, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_31_1920x1080p_50Hz */ ++ {E_PIXCLK_74250, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_32_1920x1080p_24Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_74250, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_33_1920x1080p_25Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_74250, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_34_1920x1080p_30Hz */ ++ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_108000, E_PIXCLK_108108}, /* HDMITX_VFMT_35_2880x480p_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_108000, E_PIXCLK_108108}, /* HDMITX_VFMT_36_2880x480p_60Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_108000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_37_2880x576p_50Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_108000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_38_2880x576p_50Hz */ ++ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_39_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_40_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_41_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_42_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_43_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_44_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_45_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_46_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_47_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_48_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_49_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_50_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_51_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_52_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_53_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_54_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_55_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_56_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_57_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_58_ */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_59_ */ ++ ++ {E_PIXCLK_59400, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_60_1280x720p_24Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_74250, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_61_1280x720p_25Hz */ ++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_74250, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID} /* HDMITX_VFMT_62_1280x720p_30Hz */ ++}; ++ ++/*============================================================================*/ ++/* CONSTANTS DECLARATIONS */ ++/*============================================================================*/ ++ ++ ++/** ++ * Lookup table to convert PC formats used in API parameters to pixel clock ++ * frequencies. ++ * The other index is the veritical frame frequency. ++ */ ++#ifdef FORMAT_PC ++CONST_DAT UInt8 kVfmtToPixClk_PC[HDMITX_VFMT_PC_NUM] = ++{ ++ /* HDMITX_VFREQ_60Hz HDMITX_VFREQ_70Hz HDMITX_VFREQ_72Hz HDMITX_VFREQ_75Hz HDMITX_VFREQ_85Hz HDMITX_VFREQ_87Hz*/ ++ E_PIXCLK_25175 , /* HDMITX_VFMT_PC_640x480p_60Hz */ ++ E_PIXCLK_40000 , /* HDMITX_VFMT_PC_800x600p_60Hz */ ++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_1152x960p_60Hz */ ++ E_PIXCLK_65000 , /* HDMITX_VFMT_PC_1024x768p_60Hz */ ++ E_PIXCLK_79500 , /* HDMITX_VFMT_PC_1280x768p_60Hz */ ++ E_PIXCLK_108000 , /* HDMITX_VFMT_PC_1280x1024p_60Hz */ ++ E_PIXCLK_85500 , /* HDMITX_VFMT_PC_1360x768p_60Hz */ ++ E_PIXCLK_121750 , /* HDMITX_VFMT_PC_1400x1050p_60Hz */ ++ E_PIXCLK_162000 , /* HDMITX_VFMT_PC_1600x1200p_60Hz */ ++ E_PIXCLK_75000 , /* HDMITX_VFMT_PC_1024x768p_70Hz */ ++ E_PIXCLK_31500 , /* HDMITX_VFMT_PC_640x480p_72Hz */ ++ E_PIXCLK_50000 , /* HDMITX_VFMT_PC_800x600p_72Hz */ ++ E_PIXCLK_31500 , /* HDMITX_VFMT_PC_640x480p_75Hz */ ++ E_PIXCLK_78750 , /* HDMITX_VFMT_PC_1024x768p_75Hz */ ++ E_PIXCLK_49500 , /* HDMITX_VFMT_PC_800x600p_75Hz */ ++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_1024x864p_75Hz */ ++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_1280x1024p_75Hz */ ++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_640x350p_85Hz */ ++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_640x400p_85Hz */ ++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_720x400p_85Hz */ ++ E_PIXCLK_36000 , /* HDMITX_VFMT_PC_640x480p_85Hz */ ++ E_PIXCLK_56250 , /* HDMITX_VFMT_PC_800x600p_85Hz */ ++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_1024x768p_85Hz */ ++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_1152x864p_85Hz */ ++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_1280x960p_85Hz */ ++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_1280x1024p_85Hz */ /* PR1570 FIXED */ ++ E_PIXCLK_INVALID /* HDMITX_VFMT_PC_1024x768i_87Hz */ ++}; ++#endif ++ ++/** ++ * Lookup table to convert from EIA/CEA TV video formats used in the EDID and in ++ * API parameters to the format used in the E_REG_P00_VIDFORMAT_W register ++ */ ++ ++#ifdef TMFL_RGB_DDR_12BITS ++static CONST_DAT struct vic2reg vic2reg_TV[] = { ++ {HDMITX_VFMT_01_640x480p_60Hz, E_REGVFMT_640x480p_60Hz}, ++ {HDMITX_VFMT_02_720x480p_60Hz, E_REGVFMT_720x480p_60Hz}, ++ {HDMITX_VFMT_03_720x480p_60Hz, E_REGVFMT_720x480p_60Hz}, ++ {HDMITX_VFMT_04_1280x720p_60Hz, E_REGVFMT_1280x720p_60Hz}, ++ {HDMITX_VFMT_05_1920x1080i_60Hz,E_REGVFMT_1920x1080i_60Hz}, ++ {HDMITX_VFMT_06_720x480i_60Hz, E_REGVFMT_720x480i_60Hz}, ++ {HDMITX_VFMT_07_720x480i_60Hz, E_REGVFMT_720x480i_60Hz}, ++ {HDMITX_VFMT_08_720x240p_60Hz, E_REGVFMT_720x240p_60Hz}, ++ {HDMITX_VFMT_09_720x240p_60Hz, E_REGVFMT_720x240p_60Hz}, ++ {HDMITX_VFMT_10_720x480i_60Hz, E_REGVFMT_2880x480i_60Hz_PR4}, ++ {HDMITX_VFMT_11_720x480i_60Hz, E_REGVFMT_2880x480i_60Hz_PR4}, ++ {HDMITX_VFMT_14_1440x480p_60Hz, E_REGVFMT_1440x480p_60Hz}, ++ {HDMITX_VFMT_15_1440x480p_60Hz, E_REGVFMT_1440x480p_60Hz}, ++ {HDMITX_VFMT_16_1920x1080p_60Hz,E_REGVFMT_1920x1080p_60Hz}, ++ {HDMITX_VFMT_17_720x576p_50Hz, E_REGVFMT_720x576p_50Hz}, ++ {HDMITX_VFMT_18_720x576p_50Hz, E_REGVFMT_720x576p_50Hz}, ++ {HDMITX_VFMT_19_1280x720p_50Hz, E_REGVFMT_1280x720p_50Hz}, ++ {HDMITX_VFMT_20_1920x1080i_50Hz,E_REGVFMT_1920x1080i_50Hz}, ++ {HDMITX_VFMT_21_720x576i_50Hz, E_REGVFMT_720x576i_50Hz}, ++ {HDMITX_VFMT_22_720x576i_50Hz, E_REGVFMT_720x576i_50Hz}, ++ {HDMITX_VFMT_23_720x288p_50Hz, E_REGVFMT_720x288p_50Hz}, ++ {HDMITX_VFMT_24_720x288p_50Hz, E_REGVFMT_720x288p_50Hz}, ++ {HDMITX_VFMT_25_720x576i_50Hz, E_REGVFMT_2880x576i_50Hz}, /* FIXME PR 2 */ ++ {HDMITX_VFMT_26_720x576i_50Hz, E_REGVFMT_2880x576i_50Hz}, /* FIXME PR 2 */ ++ {HDMITX_VFMT_29_1440x576p_50Hz, E_REGVFMT_1440x576p_50Hz}, ++ {HDMITX_VFMT_30_1440x576p_50Hz, E_REGVFMT_1440x576p_50Hz}, ++ {HDMITX_VFMT_31_1920x1080p_50Hz,E_REGVFMT_1920x1080p_50Hz}, ++ {HDMITX_VFMT_32_1920x1080p_24Hz,E_REGVFMT_1920x1080p_24Hz}, ++ {HDMITX_VFMT_33_1920x1080p_25Hz,E_REGVFMT_1920x1080p_25Hz}, ++ {HDMITX_VFMT_34_1920x1080p_30Hz,E_REGVFMT_1920x1080p_30Hz}, ++ {HDMITX_VFMT_35_2880x480p_60Hz, E_REGVFMT_2880x480p_60Hz}, ++ {HDMITX_VFMT_36_2880x480p_60Hz, E_REGVFMT_2880x480p_60Hz}, ++ {HDMITX_VFMT_37_2880x576p_50Hz, E_REGVFMT_720x576p_50Hz}, ++ {HDMITX_VFMT_38_2880x576p_50Hz, E_REGVFMT_720x576p_50Hz}, ++ {HDMITX_VFMT_60_1280x720p_24Hz, E_REGVFMT_1280x720p_24Hz}, ++ {HDMITX_VFMT_61_1280x720p_25Hz, E_REGVFMT_1280x720p_25Hz}, ++ {HDMITX_VFMT_62_1280x720p_30Hz, E_REGVFMT_1280x720p_30Hz} ++}; ++static CONST_DAT struct vic2reg vic2reg_TV_FP[] = { ++ {HDMITX_VFMT_01_640x480p_60Hz, E_REGVFMT_720x480p_60Hz_FP}, ++ {HDMITX_VFMT_02_720x480p_60Hz, E_REGVFMT_720x480p_60Hz_FP}, ++ {HDMITX_VFMT_03_720x480p_60Hz, E_REGVFMT_720x480p_60Hz_FP}, ++ {HDMITX_VFMT_04_1280x720p_60Hz, E_REGVFMT_1280x720p_60Hz_FP}, ++ {HDMITX_VFMT_05_1920x1080i_60Hz,E_REGVFMT_1920x1080i_60Hz_FP}, ++ {HDMITX_VFMT_17_720x576p_50Hz, E_REGVFMT_720x576p_50Hz_FP}, ++ {HDMITX_VFMT_18_720x576p_50Hz, E_REGVFMT_720x576p_50Hz_FP}, ++ {HDMITX_VFMT_19_1280x720p_50Hz, E_REGVFMT_1280x720p_50Hz_FP}, ++ {HDMITX_VFMT_20_1920x1080i_50Hz,E_REGVFMT_1920x1080i_50Hz_FP}, ++ {HDMITX_VFMT_32_1920x1080p_24Hz,E_REGVFMT_1920x1080p_24Hz_FP}, ++ {HDMITX_VFMT_33_1920x1080p_25Hz,E_REGVFMT_1920x1080p_25Hz_FP}, ++ {HDMITX_VFMT_34_1920x1080p_30Hz,E_REGVFMT_1920x1080p_30Hz_FP}, ++ {HDMITX_VFMT_60_1280x720p_24Hz, E_REGVFMT_1280x720p_24Hz_FP}, ++ {HDMITX_VFMT_61_1280x720p_25Hz, E_REGVFMT_1280x720p_25Hz_FP}, ++ {HDMITX_VFMT_62_1280x720p_30Hz, E_REGVFMT_1280x720p_30Hz_FP} ++}; ++#else ++static CONST_DAT struct vic2reg vic2reg_TV[] = { ++ {HDMITX_VFMT_01_640x480p_60Hz, E_REGVFMT_640x480p_60Hz}, ++ {HDMITX_VFMT_02_720x480p_60Hz, E_REGVFMT_720x480p_60Hz}, ++ {HDMITX_VFMT_03_720x480p_60Hz, E_REGVFMT_720x480p_60Hz}, ++ {HDMITX_VFMT_04_1280x720p_60Hz, E_REGVFMT_1280x720p_60Hz}, ++ {HDMITX_VFMT_05_1920x1080i_60Hz,E_REGVFMT_1920x1080i_60Hz}, ++ {HDMITX_VFMT_06_720x480i_60Hz, E_REGVFMT_720x480i_60Hz}, ++ {HDMITX_VFMT_07_720x480i_60Hz, E_REGVFMT_720x480i_60Hz}, ++ {HDMITX_VFMT_08_720x240p_60Hz, E_REGVFMT_720x240p_60Hz}, ++ {HDMITX_VFMT_09_720x240p_60Hz, E_REGVFMT_720x240p_60Hz}, ++ {HDMITX_VFMT_16_1920x1080p_60Hz,E_REGVFMT_1920x1080p_60Hz}, ++ {HDMITX_VFMT_17_720x576p_50Hz, E_REGVFMT_720x576p_50Hz}, ++ {HDMITX_VFMT_18_720x576p_50Hz, E_REGVFMT_720x576p_50Hz}, ++ {HDMITX_VFMT_19_1280x720p_50Hz, E_REGVFMT_1280x720p_50Hz}, ++ {HDMITX_VFMT_20_1920x1080i_50Hz,E_REGVFMT_1920x1080i_50Hz}, ++ {HDMITX_VFMT_21_720x576i_50Hz, E_REGVFMT_720x576i_50Hz}, ++ {HDMITX_VFMT_22_720x576i_50Hz, E_REGVFMT_720x576i_50Hz}, ++ {HDMITX_VFMT_23_720x288p_50Hz, E_REGVFMT_720x288p_50Hz}, ++ {HDMITX_VFMT_24_720x288p_50Hz, E_REGVFMT_720x288p_50Hz}, ++ {HDMITX_VFMT_31_1920x1080p_50Hz,E_REGVFMT_1920x1080p_50Hz}, ++ {HDMITX_VFMT_32_1920x1080p_24Hz,E_REGVFMT_1920x1080p_24Hz}, ++ {HDMITX_VFMT_33_1920x1080p_25Hz,E_REGVFMT_1920x1080p_25Hz}, ++ {HDMITX_VFMT_34_1920x1080p_30Hz,E_REGVFMT_1920x1080p_30Hz}, ++ {HDMITX_VFMT_35_2880x480p_60Hz, E_REGVFMT_720x480p_60Hz}, ++ {HDMITX_VFMT_36_2880x480p_60Hz, E_REGVFMT_720x480p_60Hz}, ++ {HDMITX_VFMT_37_2880x576p_50Hz, E_REGVFMT_720x576p_50Hz}, ++ {HDMITX_VFMT_38_2880x576p_50Hz, E_REGVFMT_720x576p_50Hz}, ++ {HDMITX_VFMT_60_1280x720p_24Hz, E_REGVFMT_1280x720p_24Hz}, ++ {HDMITX_VFMT_61_1280x720p_25Hz, E_REGVFMT_1280x720p_25Hz}, ++ {HDMITX_VFMT_62_1280x720p_30Hz, E_REGVFMT_1280x720p_30Hz} ++}; ++static CONST_DAT struct vic2reg vic2reg_TV_FP[] = { ++ {HDMITX_VFMT_04_1280x720p_60Hz, E_REGVFMT_1280x720p_60Hz_FP}, ++ {HDMITX_VFMT_05_1920x1080i_60Hz,E_REGVFMT_1920x1080i_60Hz_FP}, ++ {HDMITX_VFMT_19_1280x720p_50Hz, E_REGVFMT_1280x720p_50Hz_FP}, ++ {HDMITX_VFMT_20_1920x1080i_50Hz,E_REGVFMT_1920x1080i_50Hz_FP}, ++ {HDMITX_VFMT_32_1920x1080p_24Hz,E_REGVFMT_1920x1080p_24Hz_FP}, ++ {HDMITX_VFMT_33_1920x1080p_25Hz,E_REGVFMT_1920x1080p_25Hz_FP}, ++ {HDMITX_VFMT_34_1920x1080p_30Hz,E_REGVFMT_1920x1080p_30Hz_FP}, ++ {HDMITX_VFMT_60_1280x720p_24Hz, E_REGVFMT_1280x720p_24Hz_FP}, ++ {HDMITX_VFMT_61_1280x720p_25Hz, E_REGVFMT_1280x720p_25Hz_FP}, ++ {HDMITX_VFMT_62_1280x720p_30Hz, E_REGVFMT_1280x720p_30Hz_FP} ++}; ++#endif ++ ++#ifdef FORMAT_PC ++static CONST_DAT struct vic2reg vic2reg_PC[HDMITX_VFMT_PC_NUM] = { ++ {HDMITX_VFMT_PC_640x480p_60Hz, E_REGVFMT_640x480p_60Hz}, ++ {HDMITX_VFMT_PC_800x600p_60Hz, E_REGVFMT_800x600p_60Hz}, ++ {HDMITX_VFMT_PC_1024x768p_60Hz, E_REGVFMT_1024x768p_60Hz}, ++ {HDMITX_VFMT_PC_1280x768p_60Hz, E_REGVFMT_1280x768p_60Hz}, ++ {HDMITX_VFMT_PC_1280x1024p_60Hz,E_REGVFMT_1280x1024p_60Hz}, ++ {HDMITX_VFMT_PC_1360x768p_60Hz, E_REGVFMT_1360x768p_60Hz}, ++ {HDMITX_VFMT_PC_1400x1050p_60Hz,E_REGVFMT_1400x1050p_60Hz}, ++ {HDMITX_VFMT_PC_1600x1200p_60Hz,E_REGVFMT_1600x1200p_60Hz}, ++ {HDMITX_VFMT_PC_1024x768p_70Hz, E_REGVFMT_1024x768p_70Hz}, ++ {HDMITX_VFMT_PC_640x480p_72Hz, E_REGVFMT_640x480p_72Hz}, ++ {HDMITX_VFMT_PC_800x600p_72Hz, E_REGVFMT_800x600p_72Hz}, ++ {HDMITX_VFMT_PC_640x480p_75Hz, E_REGVFMT_640x480p_75Hz}, ++ {HDMITX_VFMT_PC_1024x768p_75Hz, E_REGVFMT_1024x768p_75Hz}, ++ {HDMITX_VFMT_PC_800x600p_75Hz, E_REGVFMT_800x600p_75Hz}, ++ {HDMITX_VFMT_PC_640x480p_85Hz, E_REGVFMT_640x480p_85Hz}, ++ {HDMITX_VFMT_PC_800x600p_85Hz, E_REGVFMT_800x600p_85Hz}, ++ {HDMITX_VFMT_PC_1280x1024p_85Hz,E_REGVFMT_1280x1024p_85Hz} ++}; ++#endif /* FORMAT PC */ ++ ++ ++/** ++ * Lookup table to convert from video format codes used in the ++ * E_REG_P00_VIDFORMAT_W register to corresponding VS_PIX_STRT_2 ++ * register values, to correct the output window for interlaced ++ * output formats, with or without the scaler. ++ * ++ * The correction is VS_PIX_STRT_2=VS_PIX_STRT_2+VS_PIX_STRT_1. ++ * The same value is also applied to VS_PIX_END_2. ++ */ ++ ++/** ++ * Lookup table to convert from video format codes used in the ++ * E_REG_P00_VIDFORMAT_W register to corresponding ++ * pixel repetition values in the PLL_SERIAL_2 register. ++ * 0=no repetition (pixel sent once) ++ * 1=one repetition (pixel sent twice) etc ++ */ ++ ++/** ++ * Lookup table to convert from video format codes used in the ++ * E_REG_P00_VIDFORMAT_W register to corresponding ++ * trios of 2-bit values in the srl_nosc, scg_nosc and de_nosc ++ * PLL control registers ++ * ++ * Rational for dummies by André ;) ++ * ----------------------------- ++ * the TMDS serializer multiply x10 the pixclk (this is a PLL;) ++ * --> --> -->
++ * 576i or 480i 13.5 Mhz (*2) 270 Mhz 4 ++ * 576p 27 Mhz 270 Mhz 4 ++ * 720p or 1080i 74.25 Mhz 742 Mhz 2 ++ * 1080p 148.5 Mhz 1485 Mhz 1 ++ * ++ */ ++ ++static CONST_DAT UInt8 pll[] = { ++ /* prefetch */ ++ 2, /* E_REGVFMT_640x480p_60Hz */ ++ 2, /* E_REGVFMT_720x480p_60Hz */ ++ 1, /* E_REGVFMT_1280x720p_60Hz */ ++ 1, /* E_REGVFMT_1920x1080i_60Hz */ ++ 3, /* E_REGVFMT_720x480i_60Hz */ ++ 0, /* E_REGVFMT_720x240p_60Hz */ /** \todo Need nosc PLL value */ ++ 0, /* E_REGVFMT_1920x1080p_60Hz */ ++ 2, /* E_REGVFMT_720x576p_50Hz */ ++ 1, /* E_REGVFMT_1280x720p_50Hz */ ++ 1, /* E_REGVFMT_1920x1080i_50Hz */ ++ 3, /* E_REGVFMT_720x576i_50Hz */ ++ 0, /* E_REGVFMT_720x288p_50Hz */ /** \todo Need nosc PLL value */ ++ 0, /* E_REGVFMT_1920x1080p_50Hz */ ++#ifdef TMFL_RGB_DDR_12BITS ++ 0, /* E_REGVFMT_1920x1080p_24Hz */ ++ 1, /* E_REGVFMT_1440x576p_50Hz */ ++ 1, /* E_REGVFMT_1440x480p_50Hz */ ++ 0, /* E_REGVFMT_2880x480p_50Hz */ ++ 0, /* E_REGVFMT_2880x576p_50Hz */ ++ 1, /* E_REGVFMT_2880x480i_60Hz */ ++ 2, /* E_REGVFMT_2880x480i_60Hz_PR2*/ ++ 2, /* E_REGVFMT_2880x480i_60Hz_PR4*/ ++ 1, /* E_REGVFMT_2880x576i_50Hz */ ++ 2, /* E_REGVFMT_2880x576i_50Hz_PR2*/ ++ 1, /* E_REGVFMT_720x480p_60Hz_FP */ ++ 0, /* E_REGVFMT_1280x720p_60Hz_FP */ ++ 1, /* E_REGVFMT_720x576p_50Hz_FP */ ++ 0, /* E_REGVFMT_1280x720p_50Hz_FP */ ++ 0, /* E_REGVFMT_1920x1080p_23Hz_FP*/ ++ 0, /* E_REGVFMT_1920x1080p_25Hz_FP*/ ++ 0, /* E_REGVFMT_1920x1080p_29Hz_FP*/ ++ 0, /* E_REGVFMT_1920x1080i_60Hz_FP*/ ++ 0, /* E_REGVFMT_1920x1080i_50Hz_FP*/ ++#endif ++ /* extra list */ ++#ifndef TMFL_RGB_DDR_12BITS ++ 1, /* E_REGVFMT_1920x1080p_24Hz */ ++#endif ++ 1, /* E_REGVFMT_1920x1080p_25Hz */ ++ 1, /* E_REGVFMT_1920x1080p_30Hz */ ++ 1, /* E_REGVFMT_1280x720p_24Hz */ ++ 1, /* E_REGVFMT_1280x720p_25Hz */ ++ 1, /* E_REGVFMT_1280x720p_30Hz */ ++#ifndef TMFL_RGB_DDR_12BITS ++ 0, /* E_REGVFMT_1280x720p_60Hz_FP */ ++ 0, /* E_REGVFMT_1920x1080i_60Hz_FP */ ++ 0, /* E_REGVFMT_1280x720p_50Hz_FP */ ++ 0, /* E_REGVFMT_1920x1080i_50Hz_FP */ ++ 0, /* E_REGVFMT_1920x1080p_24Hz_FP */ ++ 0, /* E_REGVFMT_1920x1080p_25Hz_FP */ ++ 0, /* E_REGVFMT_1920x1080p_30Hz_FP */ ++#endif ++ 0, /* E_REGVFMT_1280x720p_24Hz_FP */ ++ 0, /* E_REGVFMT_1280x720p_25Hz_FP */ ++ 0, /* E_REGVFMT_1280x720p_30Hz_FP */ ++#ifdef FORMAT_PC ++ 2, /* E_REGVFMT_640x480p_72Hz */ ++ 2, /* E_REGVFMT_640x480p_75Hz */ ++ 2, /* E_REGVFMT_640x480p_85Hz */ ++ 1, /* E_REGVFMT_800x600p_60Hz */ ++ 1, /* E_REGVFMT_800x600p_72Hz */ ++ 1, /* E_REGVFMT_800x600p_75Hz */ ++ 1, /* E_REGVFMT_800x600p_85Hz */ ++ 1, /* E_REGVFMT_1024x768p_60Hz */ ++ 1, /* E_REGVFMT_1024x768p_70Hz */ ++ 1, /* E_REGVFMT_1024x768p_75Hz */ ++ 0, /* E_REGVFMT_1280x768p_60Hz */ ++ 0, /* E_REGVFMT_1280x1024p_60Hz */ ++ 0, /* E_REGVFMT_1360x768p_60Hz */ ++ 0, /* E_REGVFMT_1400x1050p_60Hz */ ++ 0, /* E_REGVFMT_1600x1200p_60Hz */ ++ 1 /* E_REGVFMT_1280x1024p_85Hz */ ++#endif /* FORMAT_PC */ ++}; ++ ++ ++ ++/** ++ * Lokup table to convert from video format codes used in the ++ * E_REG_P00_VIDFORMAT_W register to RefPix and RefLine values ++ * according to sync source ++ */ ++/* prefetch list */ ++static CONST_DAT struct sync_desc ref_sync[] = ++{ ++ /* ++ designer world <==> CEA-861 reader world ++ ---------------------------------------- ++ t_hs_s : hfp+1 ++ t_vsl_s1 : vfp+1 ++ t_de_s : href+1 ++ t_vw_s1 : vref+1 ++ ++ For the story, designer have defined VsPixRef and VsLineRef concept ++ that are the position of VSync in pixel and line starting from the top ++ of the frame. ++ So we have in fact : VSync that is hfp + vfp*total_h_active away from top ++ ++ */ ++ /* Vs2 PR Vtg Htg HFP VFP HREF VREF */ ++ {0, 0, 1, 1, 17, 2, 161, 36}, /* E_REGVFMT_640x480p_60Hz */ ++ {0, 0, 1, 1, 17, 8, 139, 43}, /* E_REGVFMT_720x480p_60Hz */ ++ {0, 0, 0, 0, 111, 2, 371, 26}, /* E_REGVFMT_1280x720p_60Hz */ ++ {1100+88, 0, 0, 0, 89, 2, 281, 21}, /* E_REGVFMT_1920x1080i_60Hz */ ++ {429+19, 1, 1, 1, 20, 5, 139, 22}, /* E_REGVFMT_720x480i_60Hz */ ++ {0, 1, 1, 1, 20, 5, 139, 22}, /* E_REGVFMT_720x240p_60Hz */ ++ {0, 0, 0, 0, 89, 2, 281, 42}, /* E_REGVFMT_1920x1080p_60Hz */ ++ {0, 0, 1, 1, 13, 2, 145, 45}, /* E_REGVFMT_720x576p_50Hz */ ++ {0, 0, 0, 0, 441, 2, 701, 26}, /* E_REGVFMT_1280x720p_50Hz */ ++ {1320+528,0, 0, 0, 529, 2, 721, 21}, /* E_REGVFMT_1920x1080i_50Hz */ ++ {432+12, 1, 1, 1, 13, 2, 145, 23}, /* E_REGVFMT_720x576i_50Hz */ ++ {0, 1, 1, 1, 13, 2, 145, 23}, /* E_REGVFMT_720x288p_50Hz */ ++ {0, 0, 0, 0, 529, 2, 721, 42}, /* E_REGVFMT_1920x1080p_50Hz */ ++#ifdef TMFL_RGB_DDR_12BITS ++ {0, 0, 0, 0, 639, 2, 831, 42}, /* E_REGVFMT_1920x1080p_24Hz */ ++ {0, 0, 1, 1, 25, 2, 289, 45}, /* E_REGVFMT_1440x576p_50Hz */ ++ {0, 0, 1, 1, 33, 8, 277, 43}, /* E_REGVFMT_1440x480p_50Hz */ ++ {0, 0, 1, 1, 65, 8, 553, 43}, /* E_REGVFMT_2880x480p_50Hz */ ++ {0, 0, 1, 1, 49, 2, 577, 45}, /* E_REGVFMT_2880x576p_50Hz */ ++ {1716+76, 0, 1, 1, 77, 5, 553, 22}, /* E_REGVFMT_2880x480i_60Hz */ ++ {858+38, 1, 1, 1, 39, 5, 277, 22}, /* E_REGVFMT_2880x480i_60Hz_PR2*/ ++ {429+19, 2, 1, 1, 20, 5, 139, 22}, /* E_REGVFMT_2880x480i_60Hz_PR4*/ ++ {1728+48, 0, 1, 1, 49, 2, 577, 23}, /* E_REGVFMT_2880x576i_50Hz */ ++ {864+24, 1, 1, 1, 25, 2, 289, 23} /* E_REGVFMT_2880x576i_50Hz_PR*/ ++#endif ++}; ++ ++/* extra list */ ++static CONST_DAT struct sync_desc ref_sync_extra[] = ++{ ++ /* Vs2 PR Vtg Htg HFP VFP HREF VREF */ ++#ifndef TMFL_RGB_DDR_12BITS ++ {0, 0, 0, 0, 639, 2, 831, 42}, /* E_REGVFMT_1920x1080p_24Hz */ ++#endif ++ {0, 0, 0, 0, 529, 2, 721, 42}, /* E_REGVFMT_1920x1080p_25Hz */ ++ {0, 0, 0, 0, 89, 2, 281, 42}, /* E_REGVFMT_1920x1080p_30Hz */ ++ {0, 0, 0, 0, 1761, 2, 2021,26}, /* E_REGVFMT_1280x720p_24Hz */ ++ {0, 0, 0, 0, 2421, 2, 2681,26}, /* E_REGVFMT_1280x720p_25Hz */ ++ {0, 0, 0, 0, 1761, 2, 2021,26} /* E_REGVFMT_1280x720p_30Hz */ ++}; ++ ++#ifdef FORMAT_PC ++ /* PC list */ ++static CONST_DAT struct sync_desc ref_sync_PC[] = ++{ ++ /* Vs2 PR Vtg Htg HFP VFP HREF VREF */ ++ {0, 0, 1, 1, 25, 2, 195, 32}, /* E_REGVFMT_640x480p_72Hz */ ++ {0, 0, 1, 1, 17, 2, 203, 20}, /* E_REGVFMT_640x480p_75Hz */ ++ {0, 0, 1, 1, 57, 2, 195, 29}, /* E_REGVFMT_640x480p_85Hz */ ++ {0, 0, 0, 0, 41, 2, 259, 28}, /* E_REGVFMT_800x600p_60Hz */ ++ {0, 0, 0, 0, 57, 2, 243, 30}, /* E_REGVFMT_800x600p_72Hz */ ++ {0, 0, 0, 0, 17, 2, 259, 25}, /* E_REGVFMT_800x600p_75Hz */ ++ {0, 0, 0, 0, 33, 2, 251, 31}, /* E_REGVFMT_800x600p_85Hz */ ++ {0, 0, 1, 1, 25, 2, 323, 36}, /* E_REGVFMT_1024x768p_60Hz */ ++ {0, 0, 1, 1, 25, 2, 307, 36}, /* E_REGVFMT_1024x768p_70Hz */ ++ {0, 0, 0, 0, 17, 2, 291, 32}, /* E_REGVFMT_1024x768p_75Hz */ ++ {0, 0, 0, 1, 65, 2, 387, 28}, /* E_REGVFMT_1280x768p_60Hz */ ++ {0, 0, 0, 0, 49, 2, 411, 42}, /* E_REGVFMT_1280x1024p_60Hz */ ++ {0, 0, 0, 0, 65, 2, 435, 25}, /* E_REGVFMT_1360x768p_60Hz */ ++ {0, 0, 0, 1, 89, 2, 467, 37}, /* E_REGVFMT_1400x1050p_60Hz */ ++ {0, 0, 0, 0, 65, 2, 563, 50}, /* E_REGVFMT_1600x1200p_60Hz */ ++ {0, 0, 0, 0, 65, 2, 451, 48} /* E_REGVFMT_1280x1024p_85Hz */ ++}; ++#endif/* FORMAT_PC */ ++ ++static CONST_DAT tmHdmiTxVidReg_t format_param_extra[] = { ++ /* NPIX NLINE VsLineStart VsPixStart VsLineEnd VsPixEnd HsStart HsEnd ActiveVideoStart ActiveVideoEnd DeStart DeEnd */ ++ /* npix nline vsl_s1 vsp_s1 vsl_e1 vsp_e1 hs_e hs_e vw_s1 vw_e1 de_s de_e */ ++#ifndef TMFL_RGB_DDR_12BITS ++ {2750, 1125, 1, 638, 6, 638, 638, 682, 41, 1121, 830, 2750, 0, 0},/* E_REGVFMT_1920x1080p_24Hz */ ++#endif ++ {2640, 1125, 1, 528, 6, 528, 528, 572, 41, 1121, 720, 2640, 0, 0},/* E_REGVFMT_1920x1080p_25Hz */ ++ {2200, 1125, 1, 88, 6, 88, 88, 132, 41, 1121, 280, 2200, 0, 0},/* E_REGVFMT_1920x1080p_30Hz */ ++ {3300, 750, 1, 1760, 6, 1760, 1760, 1800, 25, 745, 2020, 3300, 0, 0},/* E_REGVFMT_1280x720p_24Hz */ ++ {3960, 750, 1, 2420, 6, 2420, 2420, 2460, 25, 745, 2680, 3960, 0, 0},/* E_REGVFMT_1280x720p_25Hz */ ++ {3300, 750, 1, 1760, 6, 1760, 1760, 1800, 25, 745, 2020, 3300, 0, 0},/* E_REGVFMT_1280x720p_30Hz */ ++#ifndef TMFL_RGB_DDR_12BITS ++ {1650, 1500, 1, 110, 6, 110, 110, 150, 25, 1495, 370, 1650, 746, 776},/* E_REGVFMT_1280x720p_60Hz_FP */ ++ {2200, 2250, 1, 88, 6, 88, 88, 132, 20, 2248, 280, 2200, 0, 0},/* E_REGVFMT_1920x1080i_60Hz_FP */ ++ {1980, 1500, 1, 440, 6, 440, 440, 480, 25, 1495, 700, 1980, 746, 776},/* E_REGVFMT_1280x720p_50Hz_FP */ ++ {2640, 2250, 1, 528, 6, 528, 528, 572, 20, 2248, 720, 2640, 0, 0},/* E_REGVFMT_1920x1080i_50Hz_FP */ ++ {2750, 2250, 1, 638, 6, 638, 638, 682, 41, 2246, 830, 2750, 1122, 1167},/* E_REGVFMT_1920x1080p_24Hz_FP */ ++ {2640, 2250, 1, 528, 6, 528, 528, 572, 41, 2246, 720, 2640, 1122, 1167},/* E_REGVFMT_1920x1080p_25Hz_FP */ ++ {2200, 2250, 1, 88, 6, 88, 88, 132, 41, 2246, 280, 2200, 1122, 1167},/* E_REGVFMT_1920x1080p_30Hz_FP */ ++#endif ++ {3300, 1500, 1, 1760, 6, 1760, 1760, 1800, 25, 1495, 2020, 3300, 0, 0},/* E_REGVFMT_1280x720p_24Hz_FP */ ++ {3960, 1500, 1, 2420, 6, 2420, 2420, 2460, 25, 1495, 2680, 3960, 0, 0},/* E_REGVFMT_1280x720p_25Hz_FP */ ++ {3300, 1500, 1, 1760, 6, 1760, 1760, 1800, 25, 1495, 2020, 3300, 0, 0},/* E_REGVFMT_1280x720p_30Hz_FP */ ++}; ++ ++#ifdef FORMAT_PC ++static CONST_DAT tmHdmiTxVidReg_t format_param_PC[HDMITX_VFMT_PC_NUM] = ++{ ++ /* NPIX NLINE VsLineStart VsPixStart VsLineEnd VsPixEnd HsStart HsEnd ActiveVideoStart ActiveVideoEnd DeStart DeEnd */ ++ /* npix nline vsl_s1 vsp_s1 vsl_e1 vsp_e1 hs_e hs_e vw_s1 vw_e1 de_s de_e */ ++ {832, 520, 1, 24, 4, 24, 24, 64, 31, 511, 192, 832, 0, 0},/* E_REGVFMT_640x480p_72Hz */ ++ {840, 500, 1, 16, 4, 16, 16, 80, 19, 499, 200, 840, 0, 0},/* E_REGVFMT_640x480p_75Hz */ ++ {832, 509, 1, 56, 4, 56, 56, 112, 28, 508, 192, 832, 0, 0},/* E_REGVFMT_640x480p_85Hz */ ++ {1056, 628, 1, 40, 5, 40, 40, 168, 27, 627, 256, 1056, 0, 0},/* E_REGVFMT_800x600p_60Hz */ ++ {1040, 666, 1, 56, 7, 56, 56, 176, 29, 619, 240, 1040, 0, 0},/* E_REGVFMT_800x600p_72Hz */ ++ {1056, 625, 1, 16, 4, 16, 16, 96, 24, 624, 256, 1056, 0, 0},/* E_REGVFMT_800x600p_75Hz */ ++ {1048, 631, 1, 32, 4, 32, 32, 96, 30, 630, 248, 1048, 0, 0},/* E_REGVFMT_800x600p_85Hz */ ++ {1344, 806, 1, 24, 7, 24, 24, 160, 35, 803, 320, 1344, 0, 0},/* E_REGVFMT_1024x768p_60Hz */ ++ {1328, 806, 1, 24, 7, 24, 24, 160, 35, 803, 304, 1328, 0, 0},/* E_REGVFMT_1024x768p_70Hz */ ++ {1312, 800, 1, 16, 4, 16, 16, 112, 31, 799, 288, 1312, 0, 0},/* E_REGVFMT_1024x768p_75Hz */ ++ {1664, 798, 1, 64, 8, 64, 64, 192, 27, 795, 384, 1664, 0, 0},/* E_REGVFMT_1280x768p_60Hz */ ++ {1688, 1066, 1, 48, 4, 48, 48, 160, 41, 1065, 408, 1688, 0, 0},/* E_REGVFMT_1280x1024p_60Hz */ ++ {1792, 795, 1, 64, 7, 64, 64, 176, 24, 792, 432, 1792, 0, 0},/* E_REGVFMT_1360x768p_60Hz */ ++ {1864, 1089, 1, 88, 5, 88, 88, 232, 36, 1086, 464, 1864, 0, 0},/* E_REGVFMT_1400x1050p_60Hz */ ++ {2160, 1250, 1, 64, 4, 64, 64, 256, 49, 1249, 560, 2160, 0, 0},/* E_REGVFMT_1600x1200p_60Hz */ ++ {1728, 1072, 1, 64, 4, 64, 64, 224, 47, 1071, 448, 1728, 0, 0} /* E_REGVFMT_1280x1024p_85Hz */ ++}; ++#endif/* FORMAT_PC */ ++ ++ /** ++ * Lookup table for each pixel clock frequency's CTS value in kHz ++ * according to SCS table "Audio Clock Recovery CTS Values" ++ */ ++static CONST_DAT UInt32 kPixClkToAcrCts[E_PIXCLK_NUM][HDMITX_AFS_NUM] = ++{ ++ /* HDMITX_AFS_32k _AFS_48K _AFS_96K _AFS_192K */ ++ /* _AFS_44_1k _AFS_88_2K _AFS_176_4K */ ++ { 28125, 31250, 28125, 31250, 28125, 31250, 28125}, /* E_PIXCLK_25175 */ ++ { 25200, 28000, 25200, 28000, 25200, 28000, 25200}, /* E_PIXCLK_25200 */ ++ { 27000, 30000, 27000, 30000, 27000, 30000, 27000}, /* E_PIXCLK_27000 */ ++ { 27027, 30030, 27027, 30030, 27027, 30030, 27027}, /* E_PIXCLK_27027 */ ++ { 54000, 60000, 54000, 60000, 54000, 60000, 54000}, /* E_PIXCLK_54000 */ ++ { 54054, 60060, 54054, 60060, 54054, 60060, 54054}, /* E_PIXCLK_54054 */ ++ { 59400, 65996, 59400, 65996, 59400, 65996, 59400}, /* E_PIXCLK_59400 */ ++ {210937, 234375, 140625, 234375, 140625, 234375, 140625}, /* E_PIXCLK_74175 */ ++ { 74250, 82500, 74250, 82500, 74250, 82500, 74250}, /* E_PIXCLK_74250 */ ++ {421875, 234375, 140625, 234375, 140625, 234375, 140625}, /* E_PIXCLK_148350*/ ++ {148500, 165000, 148500, 165000, 148500, 165000, 148500} /* E_PIXCLK_148500*/ ++#ifdef FORMAT_PC ++ ,{ 31500, 35000, 31500, 35000, 31500, 35000, 31500}, /* E_PIXCLK_31500 */ ++ { 36000, 40000, 36000, 40000, 36000, 40000, 36000}, /* E_PIXCLK_36000 */ ++ { 40000, 44444, 40000, 44444, 40000, 44444, 40000}, /* E_PIXCLK_40000 */ ++ { 49500, 55000, 49500, 55000, 49500, 55000, 49500}, /* E_PIXCLK_49500 */ ++ { 50000, 55556, 50000, 55556, 50000, 55556, 50000}, /* E_PIXCLK_50000 */ ++ { 56250, 62500, 56250, 62500, 56250, 62500, 56250}, /* E_PIXCLK_56250 */ ++ { 65000, 72222, 65000, 72222, 65000, 72222, 65000}, /* E_PIXCLK_65000 */ ++ { 75000, 83333, 75000, 83333, 75000, 83333, 75000}, /* E_PIXCLK_75000 */ ++ { 78750, 87500, 78750, 87500, 78750, 87500, 78750}, /* E_PIXCLK_78750 */ ++ {162000, 180000, 162000, 180000, 162000, 180000, 162000}, /* E_PIXCLK_162000*/ ++ {157500, 175000, 157500, 175000, 157500, 175000, 157500} /* E_PIXCLK_157500 */ ++#endif /* FORMAT_PC */ ++}; ++ ++/** ++ * Lookup table for each pixel clock frequency's Audio Clock Regeneration N, ++ * according to SCS Table "Audio Clock Recovery N Values" ++ */ ++static CONST_DAT UInt32 kPixClkToAcrN[E_PIXCLK_NUM][HDMITX_AFS_NUM] = ++{ ++ /* HDMITX_AFS_32k _AFS_48K _AFS_96K _AFS_192K */ ++ /* _AFS_44_1k _AFS_88_2K _AFS_176_4K */ ++ { 4576, 7007, 6864, 14014, 13728, 28028, 27456}, /* E_PIXCLK_25175 */ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_25200 */ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_27000 */ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_27027 */ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_54000 */ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_54054 */ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_59400 */ ++ {11648, 17836, 11648, 35672, 23296, 71344, 46592}, /* E_PIXCLK_74175 */ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_74250 */ ++ {11648, 8918, 5824, 17836, 11648, 35672, 23296}, /* E_PIXCLK_148350*/ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576} /* E_PIXCLK_148500*/ ++#ifdef FORMAT_PC ++ ,{ 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_31500 */ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_36000 */ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_40000 */ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_49500 */ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_50000 */ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_56250 */ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_65000 */ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_75000 */ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_78750 */ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_162000*/ ++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576} /* E_PIXCLK_157500*/ ++#endif /* FORMAT_PC */ ++}; ++ ++/** ++ * Lookup table for each pixel clock frequency's Audio Divider, according to ++ * SCS Table "Audio Clock Recovery Divider Values" ++ */ ++static CONST_DAT UInt8 kPixClkToAdiv[E_PIXCLK_NUM][HDMITX_AFS_NUM] = ++{ ++ /* HDMITX_AFS_32k _AFS_48K _AFS_96K _AFS_192K */ ++ /* _AFS_44_1k _AFS_88_2K _AFS_176_4K */ ++ {2, 2, 2, 1, 1, 0, 0}, /* E_PIXCLK_25175 */ ++ {2, 2, 2, 1, 1, 0, 0}, /* E_PIXCLK_25200 */ ++ {2, 2, 2, 1, 1, 0, 0}, /* E_PIXCLK_27000 */ ++ {2, 2, 2, 1, 1, 0, 0}, /* E_PIXCLK_27027 */ ++ {3, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_54000 */ ++ {3, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_54054 */ ++ {3, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_59400 */ ++ {4, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_74175 */ ++ {4, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_74250 */ ++ {5, 4, 4, 3, 3, 2, 2}, /* E_PIXCLK_148350 */ ++ {5, 4, 4, 3, 3, 2, 2} /* E_PIXCLK_148500 */ ++#ifdef FORMAT_PC ++ ,{2, 2, 2, 1, 1, 0, 0}, /* E_PIXCLK_31500 */ ++ {3, 2, 2, 1, 1, 0, 0}, /* E_PIXCLK_36000 */ ++ {3, 2, 2, 1, 1, 0, 0}, /* E_PIXCLK_40000 */ ++ {3, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_49500 */ ++ {3, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_50000 */ ++ {3, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_56250 */ ++ {4, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_65000 */ ++ {4, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_75000 */ ++ {4, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_78750 */ ++ {5, 4, 4, 3, 3, 2, 2}, /* E_PIXCLK_162000 */ ++ {5, 4, 4, 3, 3, 2, 2} /* E_PIXCLK_157500 */ ++#endif /* FORMAT_PC */ ++ ++}; ++ ++/** ++ * Lookup table for converting a sampling frequency into the values ++ * required in channel status byte 3 according to IEC60958-3 ++ */ ++static CONST_DAT UInt8 kAfsToCSbyte3[HDMITX_AFS_NUM+1] = ++{ ++ 3, /* HDMITX_AFS_32k */ ++ 0, /* HDMITX_AFS_44_1k */ ++ 2, /* HDMITX_AFS_48k */ ++ 8, /* HDMITX_AFS_88_2k */ ++ 10, /* HDMITX_AFS_96k */ ++ 12, /* HDMITX_AFS_176_4k */ ++ 14, /* HDMITX_AFS_192k */ ++ 9, /* HDMITX_AFS_768k */ ++ 1, /* HDMITX_AFS_NOT_INDICATED */ ++}; ++ ++ ++ ++/** ++ * Lookup table for each CTS X factor's k and m register values ++ */ ++static CONST_DAT UInt8 kCtsXToMK[HDMITX_CTSX_NUM][2] = ++{ ++/* Register values Actual values */ ++/* m k m, k */ ++ {3, 0}, /* 8, 1 */ ++ {3, 1}, /* 8, 2 */ ++ {3, 2}, /* 8, 3 */ ++ {3, 3}, /* 8, 4 */ ++ {0, 0} /* 1, 1 */ ++}; ++ ++/** ++ * Table of registers to reset and release the CTS generator ++ */ ++static CONST_DAT tmHdmiTxRegMaskVal_t kResetCtsGenerator[] = ++{ ++ {E_REG_P11_AIP_CNTRL_0_RW, E_MASKREG_P11_AIP_CNTRL_0_rst_cts, 1}, ++ {E_REG_P11_AIP_CNTRL_0_RW, E_MASKREG_P11_AIP_CNTRL_0_rst_cts, 0}, ++ {0,0,0} ++}; ++ ++/** ++ * Table of registers to bypass colour processing (up/down sampler & matrix) ++ */ ++static CONST_DAT tmHdmiTxRegMaskVal_t kBypassColourProc[] = ++{ ++ /* Bypass upsampler for RGB colourbars */ ++ {E_REG_P00_HVF_CNTRL_0_W, E_MASKREG_P00_HVF_CNTRL_0_intpol, 0}, ++ /* Bypass matrix for RGB colourbars */ ++ {E_REG_P00_MAT_CONTRL_W, E_MASKREG_P00_MAT_CONTRL_mat_bp, 1}, ++ /* Bypass downsampler for RGB colourbars */ ++ {E_REG_P00_HVF_CNTRL_1_W, E_MASKREG_P00_HVF_CNTRL_1_for, 0}, ++ {0,0,0} ++}; ++ ++/** ++ * Table of registers to configure video input mode CCIR656*/ ++static CONST_DAT tmHdmiTxRegMaskVal_t kVinModeCCIR656[] = ++{ ++ {E_REG_P00_VIP_CNTRL_4_W, E_MASKREG_P00_VIP_CNTRL_4_ccir656, 1}, ++ {E_REG_P00_HVF_CNTRL_1_W, E_MASKREG_P00_HVF_CNTRL_1_semi_planar, 1}, ++ /*{E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_sel_clk1, 1},*/ ++ {E_REG_P02_PLL_SERIAL_3_RW, E_MASKREG_P02_PLL_SERIAL_3_srl_ccir, 1}, ++ {E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_sel_vrf_clk, 1}, ++ {0,0,0} ++}; ++ ++ /* Table of registers to configure video input mode for CCIR656 DDR with 1280*720p and 1920*1080i formats*/ ++static CONST_DAT tmHdmiTxRegMaskVal_t kVinModeCCIR656_DDR_above720p[] = ++{ ++ {E_REG_P00_VIP_CNTRL_4_W, E_MASKREG_P00_VIP_CNTRL_4_ccir656, 1}, ++ {E_REG_P00_HVF_CNTRL_1_W, E_MASKREG_P00_HVF_CNTRL_1_semi_planar, 1},/*To be defined*/ ++ /*{E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_sel_clk1, 0},To be defined*/ ++ {E_REG_P02_PLL_SERIAL_3_RW, E_MASKREG_P02_PLL_SERIAL_3_srl_ccir, 0}, ++ {E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_sel_vrf_clk, 0}, ++ {0,0,0} ++}; ++/** ++ * Table of registers to configure video input mode RGB444 or YUV444 ++ */ ++static CONST_DAT tmHdmiTxRegMaskVal_t kVinMode444[] = ++{ ++ {E_REG_P00_VIP_CNTRL_4_W, E_MASKREG_P00_VIP_CNTRL_4_ccir656, 0}, ++ {E_REG_P00_HVF_CNTRL_1_W, E_MASKREG_P00_HVF_CNTRL_1_semi_planar, 0}, ++ /* {E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_sel_clk1, 0},*/ ++ {E_REG_P02_PLL_SERIAL_3_RW, E_MASKREG_P02_PLL_SERIAL_3_srl_ccir, 0}, ++ {E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_sel_vrf_clk, 0}, ++ {0,0,0} ++}; ++ ++/** ++ * Table of registers to configure video input mode YUV422 ++ */ ++static CONST_DAT tmHdmiTxRegMaskVal_t kVinModeYUV422[] = ++{ ++ {E_REG_P00_VIP_CNTRL_4_W, E_MASKREG_P00_VIP_CNTRL_4_ccir656, 0}, ++ {E_REG_P00_HVF_CNTRL_1_W, E_MASKREG_P00_HVF_CNTRL_1_semi_planar, 1}, ++ /*{E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_sel_clk1, 0},*/ ++ {E_REG_P02_PLL_SERIAL_3_RW, E_MASKREG_P02_PLL_SERIAL_3_srl_ccir, 0}, ++ {E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_sel_vrf_clk, 0}, ++ {0,0,0} ++}; ++ ++ ++/** ++ * Lookup table for colour space conversion matrix register sets. ++ * Each array consists of 31 register values from MAT_CONTROL through ++ * to MAT_OO3_LSB ++ */ ++static CONST_DAT UInt8 kMatrixPreset[MATRIX_PRESET_QTY][MATRIX_PRESET_SIZE] = ++{ ++ {0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x6F, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x3, 0x6F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, ++ 0x6F, 0x0, 0x40, 0x0, 0x40, 0x0, 0x40 ++ }, /* RGB Full to RGB Limited */ ++ ++ {0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x4, 0x1, 0x7, 0x0, ++ 0x64, 0x6, 0x88, 0x1, 0xC2, 0x7, 0xB7, 0x6, 0xD6, 0x7, 0x68, 0x1, ++ 0xC2, 0x0, 0x40, 0x2, 0x0, 0x2, 0x0 ++ }, /* RGB Full to BT601 */ ++ ++ {0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x75, 0x0, 0xBB, 0x0, ++ 0x3F, 0x6, 0x68, 0x1, 0xC2, 0x7, 0xD7, 0x6, 0xA6, 0x7, 0x99, 0x1, ++ 0xC2, 0x0, 0x40, 0x2, 0x0, 0x2, 0x0 ++ }, /* RGB Full to BT709 */ ++ ++ {0x1, 0x7, 0xC0, 0x7, 0xC0, 0x7, 0xC0, 0x2, 0x54, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x2, 0x54, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, ++ 0x54, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ++ }, /* RGB Limited to RGB Full */ ++ ++ {0x2, 0x7, 0xC0, 0x7, 0xC0, 0x7, 0xC0, 0x2, 0x59, 0x1, 0x32, 0x0, ++ 0x75, 0x6, 0x4A, 0x2, 0x0C, 0x7, 0xAB, 0x6, 0xA5, 0x7, 0x4F, 0x2, ++ 0x0C, 0x0, 0x40, 0x2, 0x0, 0x2, 0x0 ++ }, /* RGB Limited to BT601 */ ++ ++ {0x2, 0x7, 0xC0, 0x7, 0xC0, 0x7, 0xC0, 0x2, 0xDC, 0x0, 0xDA, 0x0, ++ 0x4A, 0x6, 0x24, 0x2, 0x0C, 0x7, 0xD0, 0x6, 0x6C, 0x7, 0x88, 0x2, ++ 0x0C, 0x0, 0x40, 0x2, 0x0, 0x2, 0x0 ++ }, /* RGB Limited to BT709 */ ++ ++ {0x0, 0x7, 0xC0, 0x6, 0x0, 0x6, 0x0, 0x1, 0x2A, 0x7, 0x30, 0x7, ++ 0x9C, 0x1, 0x2A, 0x1, 0x99, 0x0, 0x0, 0x1, 0x2A, 0x0, 0x0, 0x2, ++ 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ++ }, /* BT601 to RGB Full */ ++ ++ {0x1, 0x7, 0xC0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x6, 0x9A, 0x7, ++ 0x54, 0x2, 0x0, 0x2, 0xBE, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x3, ++ 0x77, 0x0, 0x40, 0x0, 0x40, 0x0, 0x40 ++ }, /* BT601 to RGB Limited */ ++ ++ {0x1, 0x7, 0xC0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x7, 0x96, 0x7, ++ 0xC5, 0x0, 0x0, 0x2, 0x0D, 0x0, 0x26, 0x0, 0x0, 0x0, 0x3B, 0x2, ++ 0x0A, 0x0, 0x40, 0x2, 0x0, 0x2, 0x0 ++ }, /* BT601 to BT709 */ ++ ++ {0x0, 0x7, 0xC0, 0x6, 0x0, 0x6, 0x0, 0x1, 0x2A, 0x7, 0x77, 0x7, ++ 0xC9, 0x1, 0x2A, 0x1, 0xCB, 0x0, 0x0, 0x1, 0x2A, 0x0, 0x0, 0x2, ++ 0x1D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ++ }, /* BT709 to RGB Full */ ++ ++ {0x1, 0x7, 0xC0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x7, 0x16, 0x7, ++ 0xA2, 0x2, 0x0, 0x3, 0x14, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x3, ++ 0xA1, 0x0, 0x40, 0x0, 0x40, 0x0, 0x40 ++ }, /* BT709 to RGB Limited */ ++ ++ {0x1, 0x7, 0xC0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x0, 0x62, 0x0, ++ 0x33, 0x0, 0x0, 0x1, 0xF7, 0x7, 0xDB, 0x0, 0x0, 0x7, 0xC7, 0x1, ++ 0xFB, 0x0, 0x40, 0x2, 0x0, 0x2, 0x0 ++ } /* BT709 to BT601 */ ++}; ++ ++/** ++ * This table gives us the index into the kMatrixPreset array, based ++ * on the input and output colourspaces. ++ * The co-ordinates into this array are tmbslTDA9989Colourspace_t enums. ++ * The value of -1 is returned for matching input/output colourspaces. ++ */ ++static CONST_DAT Int kMatrixIndex[HDMITX_CS_NUM][HDMITX_CS_NUM] = ++{ ++ {-1, E_MATRIX_RGBF_2_RGBL, E_MATRIX_RGBF_2_BT601, E_MATRIX_RGBF_2_BT709}, ++ {E_MATRIX_RGBL_2_RGBF, -1, E_MATRIX_RGBL_2_BT601, E_MATRIX_RGBL_2_BT709}, ++ {E_MATRIX_BT601_2_RGBF, E_MATRIX_BT601_2_RGBL, -1, E_MATRIX_BT601_2_BT709}, ++ {E_MATRIX_BT709_2_RGBF, E_MATRIX_BT709_2_RGBL, E_MATRIX_BT709_2_BT601, -1} ++}; ++ ++/** ++ * Blue filter Lookup table for colour space conversion. ++ * Each array consists of 31 register values from MAT_CONTROL through ++ * to MAT_OO3_LSB ++ */ ++static CONST_DAT UInt8 MatrixCoeffBlueScreen[][MATRIX_PRESET_SIZE] = ++{ ++ {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0 ++ }, /* blue screen for RGB output color space */ ++ ++ {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x1, 0x0, 0x3, 0x0 ++ }, /* blue screen for YCbCr422 output color space */ ++ ++ {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x1, 0x0, 0x3, 0x0 ++ }, /* blue screen for YCbCr444 output color space */ ++}; ++ ++/** ++ * Black filter Lookup table for colour space conversion. ++ * Each array consists of 31 register values from MAT_CONTROL through ++ * to MAT_OO3_LSB ++ */ ++static CONST_DAT UInt8 MatrixCoeffBlackScreen[][MATRIX_PRESET_SIZE] = ++{ ++ {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ++ }, /* black screen for RGB output color space */ ++ ++ {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x2, 0x0, 0x2, 0x0 ++ }, /* black screen for YCbCr422 output color space */ ++ ++ {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x2, 0x0, 0x2, 0x0 ++ }, /* black screen for YCbCr444 output color space */ ++}; ++ ++ ++/*============================================================================*/ ++/* DEFINES DECLARATIONS */ ++/*============================================================================*/ ++#define HDMITX_LAT_SCO_MAX_VAL 40 ++#define HDMITX_LAT_SCO_MIN_VAL 34 ++ ++/*============================================================================*/ ++/* VARIABLES DECLARATIONS */ ++/*============================================================================*/ ++ ++/* Register values per device to restore colour processing after test pattern */ ++static RAM_DAT UInt8 gMatContrl[HDMITX_UNITS_MAX]; ++static RAM_DAT UInt8 gHvfCntrl0[HDMITX_UNITS_MAX]; ++static RAM_DAT UInt8 gHvfCntrl1[HDMITX_UNITS_MAX]; ++ ++/*============================================================================*/ ++/* FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++ ++static tmErrorCode_t setDeVs(tmHdmiTxobject_t *pDis, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ tmbslHdmiTx3DStructure_t structure3D); ++static tmErrorCode_t setPixelRepeat(tmHdmiTxobject_t *pDis, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ UInt8 uPixelRepeat, ++ tmbslHdmiTx3DStructure_t structure3D); ++static tmErrorCode_t setSampling(tmHdmiTxobject_t *pDis); ++static UInt8 calculateChecksum(UInt8 *pData, Int numBytes); ++static UInt8 reg_vid_fmt(tmbslHdmiTxVidFmt_t fmt, \ ++ tmbslHdmiTx3DStructure_t structure3D, \ ++ UInt8 *idx, \ ++ UInt8 *idx3d, \ ++ struct sync_desc **sync); ++UInt8 pix_clk(tmbslHdmiTxVidFmt_t fmt, tmbslHdmiTxVfreq_t freq, UInt8 *pclk); ++static tmErrorCode_t InputConfig(tmHdmiTxobject_t *pDis, ++ tmbslHdmiTxVinMode_t vinMode, ++ tmbslHdmiTxPixEdge_t sampleEdge, ++ tmbslHdmiTxPixRate_t pixRate, ++ tmbslHdmiTxUpsampleMode_t upsampleMode, ++ UInt8 uPixelRepeat, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ tmbslHdmiTx3DStructure_t structure3D); ++/*============================================================================*/ ++/* tmbslTDA9989AudioInResetCts */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989AudioInResetCts ++( ++ tmUnitSelect_t txUnit ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return if sink is not an HDMI device */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Reset and release the CTS generator */ ++ err = setHwRegisterFieldTable(pDis, &kResetCtsGenerator[0]); ++ return err; ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989AudioInSetConfig */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989AudioInSetConfig ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxaFmt_t aFmt, ++ tmbslHdmiTxI2sFor_t i2sFormat, ++ UInt8 chanI2s, ++ UInt8 chanDsd, ++ tmbslHdmiTxClkPolDsd_t clkPolDsd, ++ tmbslHdmiTxSwapDsd_t swapDsd, ++ UInt8 layout, ++ UInt16 uLatency_rd, ++ tmbslHdmiTxDstRate_t dstRate ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regVal; /* Value to write in register */ ++ ++ DUMMY_ACCESS(dstRate); ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return if sink is not an HDMI device */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Check remaining parameters */ ++#ifdef TMFL_HBR_SUPPORT ++ RETIF_BADPARAM((aFmt != HDMITX_AFMT_SPDIF) && ++ (aFmt != HDMITX_AFMT_I2S) && ++ (aFmt != HDMITX_AFMT_OBA) && ++ (aFmt != HDMITX_AFMT_HBR)) ++ ++#else /* TMFL_HBR_SUPPORT */ ++ RETIF_BADPARAM((aFmt != HDMITX_AFMT_SPDIF) && ++ (aFmt != HDMITX_AFMT_I2S) && ++ (aFmt != HDMITX_AFMT_OBA)) ++ ++ ++#endif /* TMFL_HBR_SUPPORT */ ++ ++ RETIF_BADPARAM(chanI2s >= HDMITX_CHAN_INVALID) ++ RETIF_BADPARAM(chanDsd >= HDMITX_CHAN_INVALID) ++ RETIF_BADPARAM(clkPolDsd >= HDMITX_CLKPOLDSD_INVALID) ++ RETIF_BADPARAM(swapDsd >= HDMITX_SWAPDSD_INVALID) ++ RETIF_BADPARAM(layout >= HDMITX_LAYOUT_INVALID) ++ RETIF_BADPARAM(uLatency_rd >= HDMITX_LATENCY_INVALID) ++ ++ if ((aFmt == HDMITX_AFMT_I2S) ++#ifdef TMFL_HBR_SUPPORT ++ || (aFmt == HDMITX_AFMT_HBR) ++#endif /* TMFL_HBR_SUPPORT */ ++ ) ++ { ++ RETIF_BADPARAM((i2sFormat != HDMITX_I2SFOR_PHILIPS_L) && ++ (i2sFormat != HDMITX_I2SFOR_OTH_L) && ++ (i2sFormat != HDMITX_I2SFOR_OTH_R) ++ ) ++ } ++ ++#ifdef TMFL_HDCP_OPTIMIZED_POWER ++ /* ++ power management : ++ freeze/wakeup SPDIF clock ++ */ ++ err = setHwRegisterField(pDis, E_REG_FEAT_POWER_DOWN, \ ++ E_MASKREG_FEAT_POWER_DOWN_spdif, \ ++ (aFmt != HDMITX_AFMT_SPDIF)); ++ RETIF_REG_FAIL(err); ++#endif ++ ++ switch (aFmt) ++ { ++ case HDMITX_AFMT_SPDIF: ++ regVal = (UInt8)REG_VAL_SEL_AIP_SPDIF; ++ /* configure MUX_AP */ ++ err = setHwRegister(pDis, E_REG_P00_MUX_AP_RW, TDA19989_MUX_AP_SELECT_SPDIF); ++ RETIF_REG_FAIL(err) ++ break; ++ ++ case HDMITX_AFMT_I2S: ++ regVal = (UInt8)REG_VAL_SEL_AIP_I2S; ++ /* configure MUX_AP */ ++ err = setHwRegister(pDis, E_REG_P00_MUX_AP_RW, TDA19989_MUX_AP_SELECT_I2S); ++ RETIF_REG_FAIL(err) ++ break; ++ ++ case HDMITX_AFMT_OBA: ++ regVal = (UInt8)REG_VAL_SEL_AIP_OBA; ++ break; ++ ++ case HDMITX_AFMT_HBR: ++ regVal = (UInt8)REG_VAL_SEL_AIP_HBR; ++ break; ++ ++ default: ++ return TMBSL_ERR_HDMI_BAD_PARAMETER; ++ } ++ ++ ++ /* Set the audio input processor format to aFmt. */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_AIP_CLKSEL_W, ++ E_MASKREG_P00_AIP_CLKSEL_sel_aip, ++ regVal); ++ RETIF_REG_FAIL(err) ++ ++ /* Channel status on 1 channel */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_CA_I2S_RW, ++ E_MASKREG_P11_CA_I2S_hbr_chstat_4, ++ 0); ++ RETIF_REG_FAIL(err) ++ ++ /* Select the audio format */ ++ if ((aFmt == HDMITX_AFMT_I2S) ++#ifdef TMFL_HBR_SUPPORT ++ || (aFmt == HDMITX_AFMT_HBR) ++#endif /* TMFL_HBR_SUPPORT */ ++ ) ++ { ++ if (chanI2s != HDMITX_CHAN_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P11_CA_I2S_RW, ++ E_MASKREG_P11_CA_I2S_ca_i2s, ++ (UInt8)chanI2s); ++ } ++ ++ /* Select the I2S format */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_I2S_FORMAT_RW, ++ E_MASKREG_P00_I2S_FORMAT_i2s_format, ++ (UInt8)i2sFormat); ++ RETIF_REG_FAIL(err) ++ ++//#ifdef TMFL_HBR_SUPPORT ++ //if (aFmt == HDMITX_AFMT_HBR) ++ // { ++ /* Channel status on 1 channel */ ++ // err = setHwRegisterField(pDis, ++ // E_REG_P11_CA_I2S_RW, ++ // E_MASKREG_P11_CA_I2S_hbr_chstat_4, ++ // 1); ++ // RETIF_REG_FAIL(err) ++ // } ++//#endif /* TMFL_HBR_SUPPORT */ ++ } ++ else if (aFmt == HDMITX_AFMT_OBA) ++ { ++ if (chanDsd != HDMITX_CHAN_NO_CHANGE) ++ { ++ err = setHwRegister(pDis, E_REG_P11_CA_DSD_RW, chanDsd); ++ RETIF_REG_FAIL(err) ++ } ++ if (clkPolDsd != HDMITX_CLKPOLDSD_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_AIP_CLKSEL_W, ++ E_MASKREG_P00_AIP_CLKSEL_sel_pol_clk, ++ (UInt8)clkPolDsd); ++ RETIF_REG_FAIL(err) ++ } ++ if (swapDsd != HDMITX_SWAPDSD_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P11_AIP_CNTRL_0_RW, ++ E_MASKREG_P11_AIP_CNTRL_0_swap, ++ (UInt8)swapDsd); ++ RETIF_REG_FAIL(err) ++ } ++ } ++ ++ /* Set layout and latency */ ++ if (layout != HDMITX_LAYOUT_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P11_AIP_CNTRL_0_RW, ++ E_MASKREG_P11_AIP_CNTRL_0_layout, ++ layout); ++ RETIF_REG_FAIL(err) ++ } ++ if (uLatency_rd != HDMITX_LATENCY_NO_CHANGE) ++ { ++ err = setHwRegister(pDis, E_REG_P11_LATENCY_RD_RW, (UInt8)uLatency_rd); ++ RETIF_REG_FAIL(err) ++ } ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989AudioInSetCts */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989AudioInSetCts ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxctsRef_t ctsRef, ++ tmbslHdmiTxafs_t afs, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ tmbslHdmiTxVfreq_t voutFreq, ++ UInt32 uCts, ++ UInt16 uCtsX, ++ tmbslHdmiTxctsK_t ctsK, ++ tmbslHdmiTxctsM_t ctsM, ++ tmbslHdmiTxDstRate_t dstRate ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regVal; /* Register value */ ++ UInt8 pixClk; /* Pixel clock index */ ++ UInt32 acrN; /* Audio clock recovery N */ ++ ++ DUMMY_ACCESS(dstRate); ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return if sink is not an HDMI device */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Check remaining parameters */ ++ RETIF_BADPARAM(ctsRef >= HDMITX_CTSREF_INVALID) ++ RETIF_BADPARAM(afs >= HDMITX_AFS_INVALID) ++ RETIF_BADPARAM(!IS_VALID_FMT(voutFmt)) ++ RETIF_BADPARAM(voutFreq >= HDMITX_VFREQ_INVALID) ++ RETIF_BADPARAM(uCtsX >= HDMITX_CTSX_INVALID) ++ RETIF_BADPARAM(ctsK >= HDMITX_CTSK_INVALID) ++ RETIF_BADPARAM(ctsM >= HDMITX_CTSMTS_INVALID) ++ ++ ++ if (IS_TV(voutFmt)) ++ { ++ if (voutFreq == HDMITX_VFREQ_50Hz) ++ { ++ RETIF(((voutFmt < HDMITX_VFMT_17_720x576p_50Hz) \ ++ || (voutFmt > HDMITX_VFMT_31_1920x1080p_50Hz)), ++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS); ++ } ++ else if (voutFreq == HDMITX_VFREQ_24Hz) ++ { ++ RETIF((voutFmt != HDMITX_VFMT_32_1920x1080p_24Hz) \ ++ && (voutFmt != HDMITX_VFMT_60_1280x720p_24Hz), ++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS); ++ } ++ else if (voutFreq == HDMITX_VFREQ_25Hz) ++ { ++ RETIF((voutFmt != HDMITX_VFMT_33_1920x1080p_25Hz) \ ++ && (voutFmt != HDMITX_VFMT_20_1920x1080i_50Hz) \ ++ && (voutFmt != HDMITX_VFMT_61_1280x720p_25Hz), ++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS); ++ } ++ else if (voutFreq == HDMITX_VFREQ_30Hz) ++ { ++ RETIF((voutFmt != HDMITX_VFMT_34_1920x1080p_30Hz) \ ++ && (voutFmt != HDMITX_VFMT_05_1920x1080i_60Hz) \ ++ && (voutFmt != HDMITX_VFMT_62_1280x720p_30Hz), ++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS); ++ } ++ else ++ { ++ RETIF(voutFmt >= HDMITX_VFMT_17_720x576p_50Hz, ++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS); ++ } ++ } ++ ++#ifdef FORMAT_PC ++ if (IS_PC(voutFmt)) ++ { ++ if (voutFreq == HDMITX_VFREQ_60Hz) ++ { ++ RETIF(voutFmt > HDMITX_VFMT_PC_1600x1200p_60Hz, ++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS) ++ } ++ else if (voutFreq == HDMITX_VFREQ_70Hz) ++ { ++ RETIF(voutFmt != HDMITX_VFMT_PC_1024x768p_70Hz, ++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS) ++ } ++ else if (voutFreq == HDMITX_VFREQ_72Hz) ++ { ++ RETIF( ((voutFmt < HDMITX_VFMT_PC_640x480p_72Hz) || ++ (voutFmt > HDMITX_VFMT_PC_800x600p_72Hz)), ++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS) ++ } ++ else if (voutFreq == HDMITX_VFREQ_75Hz) ++ { ++ RETIF( ((voutFmt < HDMITX_VFMT_PC_640x480p_75Hz) || ++ (voutFmt > HDMITX_VFMT_PC_1280x1024p_75Hz)), ++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS) ++ } ++ else if (voutFreq == HDMITX_VFREQ_85Hz) ++ { ++ RETIF( ((voutFmt < HDMITX_VFMT_PC_640x350p_85Hz) || ++ (voutFmt > HDMITX_VFMT_PC_1280x1024p_85Hz)), ++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS) ++ } ++ else ++ { ++ RETIF(voutFmt != HDMITX_VFMT_PC_1024x768i_87Hz, ++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS) ++ } ++ } ++#endif /* FORMAT_PC */ ++ ++ /* Check for auto or manual CTS */ ++ if (uCts == HDMITX_CTS_AUTO) ++ { ++ /* Auto */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_AIP_CNTRL_0_RW, ++ E_MASKREG_P11_AIP_CNTRL_0_acr_man, ++ 0); ++ RETIF_REG_FAIL(err) ++ } ++ else ++ { ++ /* Manual */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_AIP_CNTRL_0_RW, ++ E_MASKREG_P11_AIP_CNTRL_0_acr_man, ++ 1); ++ RETIF_REG_FAIL(err) ++ } ++ ++ /* Derive M and K from X? */ ++ if ((ctsM == HDMITX_CTSMTS_USE_CTSX) || (ctsK == HDMITX_CTSK_USE_CTSX)) ++ { ++ RETIF_BADPARAM(uCtsX == HDMITX_CTSX_UNUSED) ++ ctsM = (tmbslHdmiTxctsM_t) kCtsXToMK[uCtsX][0]; ++ ctsK = (tmbslHdmiTxctsK_t)kCtsXToMK[uCtsX][1]; ++ } ++ ++ /* Set the Post-divider measured timestamp factor */ ++ regVal = (UInt8)ctsM; ++ err = setHwRegisterField(pDis, ++ E_REG_P11_CTS_N_RW, ++ E_MASKREG_P11_CTS_N_m_sel, ++ regVal); ++ RETIF_REG_FAIL(err) ++ ++ /* Set the Pre-divider scale */ ++ regVal = (UInt8)ctsK; ++ err = setHwRegisterField(pDis, ++ E_REG_P11_CTS_N_RW, ++ E_MASKREG_P11_CTS_N_k_sel, ++ regVal); ++ RETIF_REG_FAIL(err); ++ ++ /* Use voutFmt and voutFreq to index into a lookup table to get ++ * the current pixel clock value. */ ++ pix_clk(voutFmt, voutFreq, &pixClk); ++ ++ if (pixClk != E_PIXCLK_INVALID) ++ { ++ /* Set the Audio Clock Recovery N multiplier based on the audio sample ++ * frequency afs and current pixel clock. */ ++ acrN = kPixClkToAcrN[pixClk][afs]; ++ ++ /* Set ACR N multiplier [19 to 16] */ ++ regVal = (UInt8)(acrN >> 16); ++ err = setHwRegister(pDis, E_REG_P11_ACR_N_2_RW, regVal); ++ RETIF_REG_FAIL(err) ++ /* Set ACR N multiplier [15 to 8] */ ++ regVal = (UInt8)(acrN >> 8); ++ err = setHwRegister(pDis, E_REG_P11_ACR_N_1_RW, regVal); ++ RETIF_REG_FAIL(err) ++ /* Set ACR N multiplier [7 to 0] */ ++ regVal = (UInt8)acrN; ++ err = setHwRegister(pDis, E_REG_P11_ACR_N_0_RW, regVal); ++ RETIF_REG_FAIL(err) ++ ++ /* Set the CDC Audio Divider register based on the audio sample frequency ++ * afs and current pixel clock. */ ++ regVal = kPixClkToAdiv[pixClk][afs]; ++ err = setHwRegister(pDis, E_REG_P02_AUDIO_DIV_RW, regVal); ++ RETIF_REG_FAIL(err) ++ ++ /* If auto CTS, get CTS value based on the audio sample ++ * frequency afs and current pixel clock. */ ++ if (uCts == HDMITX_CTS_AUTO) ++ { ++ uCts = kPixClkToAcrCts[pixClk][afs]; ++ } ++ } ++ ++ /* Set manual or pixel clock CTS */ ++ if (uCts != HDMITX_CTS_AUTO) ++ { ++ /* Set manual ACR CTS [19 to 16 */ ++ regVal = (UInt8)(uCts >> 16); ++ err = setHwRegister(pDis, E_REG_P11_ACR_CTS_2_RW, regVal); ++ RETIF_REG_FAIL(err) ++ /* Set manual ACR CTS [15 to 8] */ ++ regVal = (UInt8)(uCts >> 8); ++ err = setHwRegister(pDis, E_REG_P11_ACR_CTS_1_RW, regVal); ++ RETIF_REG_FAIL(err) ++ /* Set manual ACR CTS [7 to 0] */ ++ regVal = (UInt8)uCts; ++ err = setHwRegister(pDis, E_REG_P11_ACR_CTS_0_RW, regVal); ++ RETIF_REG_FAIL(err) ++ } ++ ++ /* Set the CTS clock reference register according to ctsRef */ ++ regVal = (UInt8)ctsRef; ++ err = setHwRegisterField(pDis, ++ E_REG_P00_AIP_CLKSEL_W, ++ E_MASKREG_P00_AIP_CLKSEL_sel_fs, ++ regVal); ++ RETIF_REG_FAIL(err) ++ ++ /* Reset and release the CTS generator */ ++ err = setHwRegisterFieldTable(pDis, &kResetCtsGenerator[0]); ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989AudioOutSetChanStatus */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989AudioOutSetChanStatus ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxAudioData_t pcmIdentification, ++ tmbslHdmiTxCSformatInfo_t formatInfo, ++ tmbslHdmiTxCScopyright_t copyright, ++ UInt8 categoryCode, ++ tmbslHdmiTxafs_t sampleFreq, ++ tmbslHdmiTxCSclkAcc_t clockAccuracy, ++ tmbslHdmiTxCSmaxWordLength_t maxWordLength, ++ tmbslHdmiTxCSwordLength_t wordLength, ++ tmbslHdmiTxCSorigAfs_t origSampleFreq ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 buf[4]; /* Buffer to hold channel status data */ ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return if sink is not an HDMI device */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Check remaining parameters */ ++ RETIF_BADPARAM(formatInfo >= HDMITX_CSFI_INVALID) ++ RETIF_BADPARAM(copyright >= HDMITX_CSCOPYRIGHT_INVALID) ++ RETIF_BADPARAM(sampleFreq > HDMITX_AFS_NOT_INDICATED) ++ RETIF_BADPARAM(clockAccuracy >= HDMITX_CSCLK_INVALID) ++ RETIF_BADPARAM(maxWordLength >= HDMITX_CSMAX_INVALID) ++ RETIF_BADPARAM(wordLength >= HDMITX_CSWORD_INVALID) ++ RETIF_BADPARAM(wordLength == HDMITX_CSWORD_RESVD) ++ RETIF_BADPARAM(origSampleFreq >= HDMITX_CSAFS_INVALID) ++ RETIF_BADPARAM(pcmIdentification >=HDMITX_AUDIO_DATA_INVALID) ++ ++ /* Prepare Byte 0 */ ++ buf[0] = ((UInt8)formatInfo << 3) | ((UInt8)copyright << 2) | ((UInt8)pcmIdentification<< 1); ++ ++ /* Prepare Byte 1 */ ++ buf[1] = categoryCode; ++ ++ /* Prepare Byte 3 - note Byte 2 not in sequence in TDA9983 register map */ ++ buf[2] = ((UInt8)clockAccuracy << 4) | kAfsToCSbyte3[sampleFreq]; ++ ++ /* Prepare Byte 4 */ ++ buf[3] = ((UInt8)origSampleFreq << 4) | ((UInt8)wordLength << 1) | ++ (UInt8)maxWordLength; ++ ++ /* Write 4 Channel Status bytes */ ++ err = setHwRegisters(pDis, E_REG_P11_CH_STAT_B_0_RW, &buf[0], 4); ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989AudioOutSetChanStatusMapping */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++tmbslTDA9989AudioOutSetChanStatusMapping ++( ++ tmUnitSelect_t txUnit, ++ UInt8 sourceLeft[4], ++ UInt8 channelLeft[4], ++ UInt8 sourceRight[4], ++ UInt8 channelRight[4] ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 buf[2]; /* Buffer to hold channel status data */ ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return if sink is not an HDMI device */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Check remaining parameters */ ++ RETIF_BADPARAM(sourceLeft[0] > HDMITX_CS_SOURCES_MAX) ++ RETIF_BADPARAM(channelLeft[0] > HDMITX_CS_CHANNELS_MAX) ++ RETIF_BADPARAM(sourceRight[0] > HDMITX_CS_SOURCES_MAX) ++ RETIF_BADPARAM(channelRight[0] > HDMITX_CS_CHANNELS_MAX) ++ ++ /* Prepare Left byte */ ++ buf[0] = ((UInt8)channelLeft[0] << 4) | (UInt8)sourceLeft[0]; ++ ++ /* Prepare Right byte */ ++ buf[1] = ((UInt8)channelRight[0] << 4) | (UInt8)sourceRight[0]; ++ ++ /* Write 2 Channel Status bytes */ ++ err = setHwRegisters(pDis, E_REG_P11_CH_STAT_B_2_ap0_l_RW, &buf[0], 2); ++ return err; ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989AudioOutSetMute */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989AudioOutSetMute ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxaMute_t aMute ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return if sink is not an HDMI device */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Check remaining parameters */ ++ RETIF_BADPARAM(aMute >= HDMITX_AMUTE_INVALID) ++ ++ /* audio mute workaround, un-map audio input before muting */ ++ if (aMute == HDMITX_AMUTE_ON) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_SR_REG_W, ++ E_MASKREG_P00_SR_REG_sr_audio, ++ (UInt8)aMute); ++ RETIF(err != TM_OK, err) ++ ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_SR_REG_W, ++ E_MASKREG_P00_SR_REG_sr_audio, ++ (UInt8) !aMute); ++ RETIF(err != TM_OK, err) ++ ++ } ++ ++ /* Reset the audio FIFO to mute audio */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_AIP_CNTRL_0_RW, ++ E_MASKREG_P11_AIP_CNTRL_0_rst_fifo, ++ (UInt8)aMute); ++ RETIF(err != TM_OK, err) ++ ++ ++ return TM_OK; ++ ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989ScalerGet */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++tmbslTDA9989ScalerGet ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxScalerDiag_t *pScalerDiag ++) ++{ ++ DUMMY_ACCESS(txUnit); /* else not referenced */ ++ DUMMY_ACCESS(pScalerDiag); /* else not referenced */ ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989ScalerGetMode */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989ScalerGetMode ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxScaMode_t *pScalerMode ++) ++{ ++ DUMMY_ACCESS(txUnit); /* else not referenced */ ++ DUMMY_ACCESS(pScalerMode); /* else is declared but not used */ ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989ScalerInDisable */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989ScalerInDisable ++( ++ tmUnitSelect_t txUnit, ++ Bool bDisable ++) ++{ ++ DUMMY_ACCESS(txUnit); /* else not referenced */ ++ DUMMY_ACCESS(bDisable); ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++ ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989ScalerSetCoeffs */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++tmbslTDA9989ScalerSetCoeffs ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxScaLut_t lutSel, ++ UInt8 *pVsLut ++) ++{ ++ DUMMY_ACCESS(txUnit); /* else not referenced */ ++ DUMMY_ACCESS(lutSel); /* else is declared but not used */ ++ DUMMY_ACCESS(pVsLut); /* else is declared but not used */ ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++ ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989ScalerSetFieldOrder */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989ScalerSetFieldOrder ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxIntExt_t topExt, ++ tmbslHdmiTxIntExt_t deExt, ++ tmbslHdmiTxTopSel_t topSel, ++ tmbslHdmiTxTopTgl_t topTgl ++) ++{ ++ DUMMY_ACCESS(txUnit); /* else not referenced */ ++ DUMMY_ACCESS(deExt); /* else is declared but not used */ ++ DUMMY_ACCESS(topExt); /* else is declared but not used */ ++ DUMMY_ACCESS(topSel); /* else is declared but not used */ ++ DUMMY_ACCESS(topTgl); /* else is declared but not used */ ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++ ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989ScalerSetPhase */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989ScalerSetPhase ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxHPhases_t horizontalPhases ++) ++{ ++ DUMMY_ACCESS(txUnit); /* else not referenced */ ++ DUMMY_ACCESS(horizontalPhases); /* else is declared but not used */ ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++ ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989ScalerSetLatency */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989ScalerSetLatency ++( ++ tmUnitSelect_t txUnit, ++ UInt8 scaler_latency ++) ++{ ++ DUMMY_ACCESS(txUnit); /* else not referenced */ ++ DUMMY_ACCESS(scaler_latency); /* else is declared but not used */ ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++ ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989ScalerSetFine */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989ScalerSetFine ++( ++ tmUnitSelect_t txUnit, ++ UInt16 uRefPix, ++ UInt16 uRefLine ++) ++{ ++ DUMMY_ACCESS(txUnit); /* else not referenced */ ++ DUMMY_ACCESS(uRefPix); /* else is declared but not used */ ++ DUMMY_ACCESS(uRefLine); /* else is declared but not used */ ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++ ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989ScalerSetSync */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989ScalerSetSync ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxVsMeth_t method, ++ tmbslHdmiTxVsOnce_t once ++) ++{ ++ DUMMY_ACCESS(txUnit); /* else not referenced */ ++ DUMMY_ACCESS(method); /* else is declared but not used */ ++ DUMMY_ACCESS(once); /* else is declared but not used */ ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++ ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989TmdsSetOutputs */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989TmdsSetOutputs ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxTmdsOut_t tmdsOut ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM(tmdsOut >= HDMITX_TMDSOUT_INVALID) ++ ++ /* Set the TMDS output mode */ ++ err = setHwRegisterField(pDis, ++ E_REG_P02_BUFFER_OUT_RW, ++ E_MASKREG_P02_BUFFER_OUT_srl_force, ++ (UInt8)tmdsOut); ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989TmdsSetSerializer */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989TmdsSetSerializer ++( ++ tmUnitSelect_t txUnit, ++ UInt8 uPhase2, ++ UInt8 uPhase3 ++) ++{ ++ ++ DUMMY_ACCESS(txUnit); ++ DUMMY_ACCESS(uPhase2); ++ DUMMY_ACCESS(uPhase3); ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989TestSetPattern */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989TestSetPattern ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxTestPattern_t pattern ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 serviceMode; /* Register value */ ++ UInt8 bars8; /* Register value */ ++ UInt8 buf[MATRIX_PRESET_SIZE]; /* Temp buffer */ ++ UInt8 i; /* Loop index */ ++ UInt8 *MatrixCoeff=Null; ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check pattern parameters */ ++ switch (pattern) ++ { ++ case HDMITX_PATTERN_CBAR4: ++ serviceMode = 1; ++ bars8 = 0; ++ break; ++ case HDMITX_PATTERN_BLUE: ++ MatrixCoeff = (UInt8*)&MatrixCoeffBlueScreen[pDis->voutMode][0]; //point to the blue matrix ++ serviceMode = 1; ++ bars8 = 1; ++ break; ++ case HDMITX_PATTERN_BLACK: ++ MatrixCoeff = (UInt8*)&MatrixCoeffBlackScreen[pDis->voutMode][0]; //point to the black matrix ++ case HDMITX_PATTERN_CBAR8: ++ serviceMode = 1; ++ bars8 = 1; ++ break; ++ case HDMITX_PATTERN_OFF: ++ serviceMode = 0; ++ bars8 = 0; ++ break; ++ default: ++ return TMBSL_ERR_HDMI_BAD_PARAMETER; ++ } ++ ++ if (serviceMode) ++ { ++ if (!pDis->prevPattern) /* if a pattern is on, registers are already saved */ ++ { ++ /* The kBypassColourProc registers are saved in tmbslTDA9989VideoSetInOut API */ ++ /* Bypass up/down sampler and matrix for RGB colourbars */ ++ setHwRegisterFieldTable(pDis, &kBypassColourProc[0]); ++ } ++ if (( pattern == HDMITX_PATTERN_BLUE )||( pattern == HDMITX_PATTERN_BLACK )) /* blue or black screen pattern */ ++ { ++ ++ /* To create blue or black screen, we use the internal color bar 8 on which we apply a matrix to change it to blue or black */ ++ /* Set the first block byte separately, as it is shadowed and can't ++ * be set by setHwRegisters */ ++ ++ /* Set the first block byte separately, as it is shadowed and can't ++ * be set by setHwRegisters */ ++ err = setHwRegister(pDis, ++ E_REG_P00_MAT_CONTRL_W, ++ MatrixCoeff[0]); ++ RETIF_REG_FAIL(err) ++ ++ for (i = 0; i < MATRIX_PRESET_SIZE; i++) ++ { ++ buf[i] = MatrixCoeff[i]; ++ } ++ ++ /* Set the rest of the block */ ++ err = setHwRegisters(pDis, ++ E_REG_P00_MAT_OI1_MSB_W, ++ &buf[1], ++ MATRIX_PRESET_SIZE - 1); ++ RETIF_REG_FAIL(err) ++ pDis->prevFilterPattern = True; ++ } ++ else /* colour bars patterns */ ++ { ++ /* Set number of colour bars */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_HVF_CNTRL_0_W, ++ E_MASKREG_P00_HVF_CNTRL_0_rwb, ++ bars8); ++ RETIF_REG_FAIL(err) ++ ++ /* Bypass up/down sampler and matrix for RGB colourbars */ ++ setHwRegisterFieldTable(pDis, &kBypassColourProc[0]); ++ } ++ pDis->prevPattern = True; ++ } ++ else /* serviceMode == 0 */ ++ { ++ if (pDis->prevFilterPattern) ++ { ++ /* Restore the previous Matrix when pattern goes off */ ++ err = tmbslTDA9989MatrixSetConversion ( txUnit, pDis->vinFmt, pDis->vinMode, pDis->voutFmt, pDis->voutMode,pDis->dviVqr); ++ RETIF_REG_FAIL(err) ++ ++ pDis->prevFilterPattern = False; ++ } ++ /* Restore kBypassColourProc registers when pattern goes off */ ++ setHwRegister(pDis, E_REG_P00_MAT_CONTRL_W, gMatContrl[txUnit]); ++ setHwRegister(pDis, E_REG_P00_HVF_CNTRL_0_W, gHvfCntrl0[txUnit]); ++ setHwRegister(pDis, E_REG_P00_HVF_CNTRL_1_W, gHvfCntrl1[txUnit]); ++ pDis->prevPattern = False; ++ } ++ ++ /* Set Service Mode on or off */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_HVF_CNTRL_0_W, ++ E_MASKREG_P00_HVF_CNTRL_0_sm, ++ serviceMode); ++#ifdef TMFL_HDCP_SUPPORT ++ pDis->HDCPIgnoreEncrypt = True; /* Skip the next encrypt IT */ ++#endif /* TMFL_HDCP_SUPPORT */ ++ ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989VideoInSetBlanking */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989VideoInSetBlanking ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxBlnkSrc_t blankitSource, ++ tmbslHdmiTxBlnkCode_t blankingCodes ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM(blankitSource >= HDMITX_BLNKSRC_INVALID) ++ RETIF_BADPARAM(blankingCodes >= HDMITX_BLNKCODE_INVALID) ++ ++ /* For each parameter that is not No Change, set its register */ ++ if (blankitSource != HDMITX_BLNKSRC_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_4_W, ++ E_MASKREG_P00_VIP_CNTRL_4_blankit, ++ (UInt8)blankitSource); ++ RETIF_REG_FAIL(err) ++ } ++ if (blankingCodes != HDMITX_BLNKCODE_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_4_W, ++ E_MASKREG_P00_VIP_CNTRL_4_blc, ++ (UInt8)blankingCodes); ++ RETIF_REG_FAIL(err) ++ } ++ ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989VideoInSetConfig */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989VideoInSetConfig ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxVinMode_t vinMode, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ tmbslHdmiTx3DStructure_t structure3D, ++ tmbslHdmiTxPixEdge_t sampleEdge, ++ tmbslHdmiTxPixRate_t pixRate, ++ tmbslHdmiTxUpsampleMode_t upsampleMode ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM(vinMode >= HDMITX_VINMODE_INVALID) ++ RETIF_BADPARAM(sampleEdge >= HDMITX_PIXEDGE_INVALID) ++ RETIF_BADPARAM(pixRate >= HDMITX_PIXRATE_INVALID) ++ RETIF_BADPARAM(upsampleMode >= HDMITX_UPSAMPLE_INVALID) ++ ++ err = InputConfig(pDis, ++ vinMode, ++ sampleEdge, ++ pixRate, ++ upsampleMode, ++ HDMITX_PIXREP_NO_CHANGE, ++ voutFmt, ++ structure3D); ++ RETIF_REG_FAIL(err) ++ ++ return TM_OK; ++} ++/*============================================================================*/ ++/* tmbslTDA9989VideoInSetFine */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989VideoInSetFine ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPixSubpkt_t subpacketCount, ++ tmbslHdmiTxPixTogl_t toggleClk1 ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM(subpacketCount >= HDMITX_PIXSUBPKT_INVALID) ++ RETIF_BADPARAM(toggleClk1 >= HDMITX_PIXTOGL_INVALID) ++ ++ /* IF subpacketCount is Fix at 0/1/2/3 THEN set subpacket count register ++ * to 0/1/2/3 and set subpacket sync register to 3 ++ */ ++ if (subpacketCount <= HDMITX_PIXSUBPKT_FIX_3) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_5_W, ++ E_MASKREG_P00_VIP_CNTRL_5_sp_cnt, ++ (UInt8)subpacketCount); ++ RETIF_REG_FAIL(err) ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_3_W, ++ E_MASKREG_P00_VIP_CNTRL_3_sp_sync, ++ HDMITX_PIXSUBPKT_SYNC_FIXED); ++ RETIF_REG_FAIL(err) ++ } ++ /* ELSE IF subpacketCount is Sync by Hemb/ Sync by Rising Edge DE/ ++ * Sync by Rising Edge HS THEN set the unused subpacket count to zero and ++ * set subpacket sync register to 0/1/2 ++ */ ++ else if (subpacketCount != HDMITX_PIXSUBPKT_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_5_W, ++ E_MASKREG_P00_VIP_CNTRL_5_sp_cnt, ++ HDMITX_PIXSUBPKT_FIX_0); ++ RETIF_REG_FAIL(err) ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_3_W, ++ E_MASKREG_P00_VIP_CNTRL_3_sp_sync, ++ (UInt8)(subpacketCount - HDMITX_PIXSUBPKT_SYNC_FIRST)); ++ RETIF_REG_FAIL(err) ++ } ++ ++ /* IF toggleClk1 is not No Change THEN set ckcase bitfield */ ++ if (toggleClk1 != HDMITX_PIXTOGL_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_5_W, ++ E_MASKREG_P00_VIP_CNTRL_5_ckcase, ++ (UInt8)toggleClk1); ++ RETIF_REG_FAIL(err) ++ } ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989VideoInSetMapping */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989VideoInSetMapping ++#ifdef TMFL_RGB_DDR_12BITS ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pSwapTable, ++ UInt8 *pMirrorTable, ++ UInt8 *pMux ++) ++#else ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pSwapTable, ++ UInt8 *pMirrorTable ++) ++#endif ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ Int i; /* Loop counter */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM(pSwapTable == Null) ++ RETIF_BADPARAM(pMirrorTable == Null) ++ for (i = 0; i < HDMITX_VIN_PORT_MAP_TABLE_LEN; i++) ++ { ++ RETIF_BADPARAM(pSwapTable[i] >= HDMITX_VIN_PORT_SWAP_INVALID) ++ RETIF_BADPARAM(pMirrorTable[i] >= HDMITX_VIN_PORT_MIRROR_INVALID) ++ } ++ ++ /* IF pswapTable[n] is not No Change THEN set the port swap registers from ++ * pswapTable[n] ++ */ ++ for (i = 0; i < HDMITX_VIN_PORT_MAP_TABLE_LEN; i++) ++ { ++ if (pSwapTable[0] < HDMITX_VIN_PORT_SWAP_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ kRegVip[i].Register, ++ kRegVip[i].MaskSwap, ++ pSwapTable[i]); ++ RETIF_REG_FAIL(err) ++ } ++ } ++ ++ /* IF pMirrorTable[n] is not No Change THEN set the port mirror registers ++ * from pMirrorTable[n] ++ */ ++ for (i = 0; i < HDMITX_VIN_PORT_MAP_TABLE_LEN; i++) ++ { ++ if (pMirrorTable[0] < HDMITX_VIN_PORT_MIRROR_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ kRegVip[i].Register, ++ kRegVip[i].MaskMirror, ++ pMirrorTable[i]); ++ RETIF_REG_FAIL(err) ++ } ++ } ++ ++#ifdef TMFL_RGB_DDR_12BITS ++ /* ++ mux for RGB_DDR_12bits ++ */ ++ err = setHwRegister(pDis,E_REG_P00_MUX_VP_VIP_OUT_RW, *pMux); ++ RETIF_REG_FAIL(err); ++#endif ++ ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989SetVideoPortConfig */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989SetVideoPortConfig ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pEnaVideoPortTable, ++ UInt8 *pGndVideoPortTable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM(pEnaVideoPortTable == Null) ++ RETIF_BADPARAM(pGndVideoPortTable == Null) ++ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_VP_0_RW, ++ pEnaVideoPortTable[0]); ++ RETIF_REG_FAIL(err) ++ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_VP_1_RW, ++ pEnaVideoPortTable[1]); ++ RETIF_REG_FAIL(err) ++ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_VP_2_RW, ++ pEnaVideoPortTable[2]); ++ RETIF_REG_FAIL(err) ++ ++ /* err = setHwRegister(pDis, ++ E_REG_P00_GND_VP_0_RW, ++ pGndVideoPortTable[0]); ++ RETIF_REG_FAIL(err)*/ ++ ++ /* err = setHwRegister(pDis, ++ E_REG_P00_GND_VP_1_RW, ++ pGndVideoPortTable[1]); ++ RETIF_REG_FAIL(err)*/ ++ ++ /* err = setHwRegister(pDis, ++ E_REG_P00_GND_VP_2_RW, ++ pGndVideoPortTable[2]); ++ RETIF_REG_FAIL(err)*/ ++ ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989SetAudioPortConfig */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989SetAudioPortConfig ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pEnaAudioPortTable, ++ UInt8 *pGndAudioPortTable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM(pEnaAudioPortTable == Null) ++ RETIF_BADPARAM(pGndAudioPortTable == Null) ++ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_AP_RW, ++ pEnaAudioPortTable[0]); ++ RETIF_REG_FAIL(err) ++ ++ /* err = setHwRegister(pDis, ++ E_REG_P00_GND_AP_RW, ++ pGndAudioPortTable[0]); ++ RETIF_REG_FAIL(err)*/ ++ ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989SetAudioClockPortConfig */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989SetAudioClockPortConfig ++( ++ tmUnitSelect_t txUnit, ++ UInt8 *pEnaAudioClockPortTable, ++ UInt8 *pGndAudioClockPortTable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM(pEnaAudioClockPortTable == Null) ++ RETIF_BADPARAM(pGndAudioClockPortTable == Null) ++ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_ACLK_RW, ++ pEnaAudioClockPortTable[0]); ++ RETIF_REG_FAIL(err) ++ ++ /*err = setHwRegister(pDis, ++ E_REG_P00_GND_ACLK_RW, ++ pGndAudioClockPortTable[0]); ++ RETIF_REG_FAIL(err)*/ ++ ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* set_video replace E_REG_P00_VIDFORMAT_W register */ ++/* use it for new video format */ ++/*============================================================================*/ ++tmErrorCode_t set_video(tmHdmiTxobject_t *pDis,tmbslHdmiTxVidFmt_t reg_idx,tmHdmiTxVidReg_t *format_param) ++{ ++ tmErrorCode_t err; ++ UInt8 regVal; ++ ++ regVal = 0x00;/* PR1570 FIXED */ ++ err = setHwRegister(pDis, E_REG_P00_VIDFORMAT_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)format_param[reg_idx].nPix; ++ err = setHwRegister(pDis, E_REG_P00_NPIX_LSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)(format_param[reg_idx].nPix>>8); ++ err = setHwRegister(pDis, E_REG_P00_NPIX_MSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)format_param[reg_idx].nLine; ++ err = setHwRegister(pDis, E_REG_P00_NLINE_LSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)(format_param[reg_idx].nLine>>8); ++ err = setHwRegister(pDis, E_REG_P00_NLINE_MSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)format_param[reg_idx].VsLineStart; ++ err = setHwRegister(pDis, E_REG_P00_VS_LINE_STRT_1_LSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)format_param[reg_idx].VsPixStart; ++ err = setHwRegister(pDis, E_REG_P00_VS_PIX_STRT_1_LSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)(format_param[reg_idx].VsPixStart>>8); ++ err = setHwRegister(pDis, E_REG_P00_VS_PIX_STRT_1_MSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)format_param[reg_idx].VsLineEnd; ++ err = setHwRegister(pDis, E_REG_P00_VS_LINE_END_1_LSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)format_param[reg_idx].VsPixEnd; ++ err = setHwRegister(pDis, E_REG_P00_VS_PIX_END_1_LSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)(format_param[reg_idx].VsPixEnd>>8); ++ err = setHwRegister(pDis, E_REG_P00_VS_PIX_END_1_MSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)format_param[reg_idx].HsStart; ++ err = setHwRegister(pDis, E_REG_P00_HS_PIX_START_LSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)(format_param[reg_idx].HsStart>>8); ++ err = setHwRegister(pDis, E_REG_P00_HS_PIX_START_MSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)format_param[reg_idx].HsEnd; ++ err = setHwRegister(pDis, E_REG_P00_HS_PIX_STOP_LSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)(format_param[reg_idx].HsEnd>>8); ++ err = setHwRegister(pDis, E_REG_P00_HS_PIX_STOP_MSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)format_param[reg_idx].ActiveVideoStart; ++ err = setHwRegister(pDis, E_REG_P00_VWIN_START_1_LSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ err = setHwRegister(pDis, E_REG_P00_VWIN_START_1_MSB_W, 0); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)format_param[reg_idx].ActiveVideoEnd; ++ err = setHwRegister(pDis, E_REG_P00_VWIN_END_1_LSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)(format_param[reg_idx].ActiveVideoEnd>>8); ++ err = setHwRegister(pDis, E_REG_P00_VWIN_END_1_MSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)format_param[reg_idx].DeStart; ++ err = setHwRegister(pDis, E_REG_P00_DE_START_LSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)(format_param[reg_idx].DeStart>>8); ++ err = setHwRegister(pDis, E_REG_P00_DE_START_MSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)format_param[reg_idx].DeEnd; ++ err = setHwRegister(pDis, E_REG_P00_DE_STOP_LSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)(format_param[reg_idx].DeEnd>>8); ++ err = setHwRegister(pDis, E_REG_P00_DE_STOP_MSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++#ifdef TMFL_RGB_DDR_12BITS ++ if (format_param[reg_idx].ActiveSpaceStart) { ++ /* enable active space */ ++ err = setHwRegisterField(pDis, E_REG_P00_ENABLE_SPACE_W, 0x01, 0x01); ++ RETIF_REG_FAIL(err); ++ ++ /* set active space to black */ ++ err = setHwRegister(pDis, E_REG_P00_VSPACE_Y_DATA_W, 0x00); ++ RETIF_REG_FAIL(err); ++ ++ err = setHwRegister(pDis, E_REG_P00_VSPACE_U_DATA_W, 0x80); ++ RETIF_REG_FAIL(err); ++ ++ err = setHwRegister(pDis, E_REG_P00_VSPACE_V_DATA_W, 0x80); ++ RETIF_REG_FAIL(err); ++ ++ /* active space definition */ ++ regVal = (UInt8)format_param[reg_idx].ActiveSpaceStart; ++ err = setHwRegister(pDis, E_REG_P00_VSPACE_START_LSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)((format_param[reg_idx].ActiveSpaceStart>>8) & 0x0F); ++ err = setHwRegister(pDis, E_REG_P00_VSPACE_START_MSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)format_param[reg_idx].ActiveSpaceEnd; ++ err = setHwRegister(pDis, E_REG_P00_VSPACE_END_LSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ ++ regVal = (UInt8)((format_param[reg_idx].ActiveSpaceEnd>>8) & 0x0F); ++ err = setHwRegister(pDis, E_REG_P00_VSPACE_END_MSB_W, regVal); ++ RETIF_REG_FAIL(err); ++ } ++ else { ++ /* let incoming pixels feel the active space (if any) */ ++ err = setHwRegisterField(pDis, E_REG_P00_ENABLE_SPACE_W, 0x01, 0x00); ++ RETIF_REG_FAIL(err); ++ } ++#endif ++ ++ return TM_OK; ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989VideoInSetSyncAuto */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989VideoInSetSyncAuto ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxSyncSource_t syncSource, ++ tmbslHdmiTxVidFmt_t vinFmt, ++ tmbslHdmiTxVinMode_t vinMode, ++ tmbslHdmiTx3DStructure_t structure3D ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 reg_idx,reg_idx3D; /* Video i/p fmt value used for comparison */ ++ UInt8 embedded; /* Register value */ ++ UInt8 syncMethod; /* Sync method */ ++ UInt8 toggleV; /* V toggle */ ++ UInt8 toggleH; /* H toggle */ ++ UInt8 toggleX; /* X toggle */ ++ UInt16 uRefPix; /* Output refpix */ ++ UInt16 uRefLine; /* Output refline */ ++#ifdef FORMAT_PC ++ UInt8 regVal;/* PR1570 FIXED */ ++#endif /* FORMAT_PC */ ++ struct sync_desc *sync; ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err); ++ ++ /* Check parameters - syncSource must be specified */ ++ RETIF_BADPARAM(syncSource >= HDMITX_SYNCSRC_NO_CHANGE); ++ RETIF_BADPARAM(!IS_VALID_FMT(vinFmt)); ++ ++ /* Look up the VIDFORMAT register format from the register format table */ ++ /* Quit if the input format does not map to the register format */ ++ RETIF_BADPARAM(reg_vid_fmt(vinFmt,structure3D,®_idx,®_idx3D,&sync)); ++ ++ /* Select values according to sync source */ ++ embedded = 0; ++ switch (syncSource) ++ { ++ case HDMITX_SYNCSRC_EXT_VS: ++ syncMethod = 0; ++ toggleV = sync[BASE(reg_idx)].v_toggle; ++ toggleH = sync[BASE(reg_idx)].h_toggle; ++ toggleX = 0; ++ uRefPix = sync[BASE(reg_idx)].hfp; ++ uRefLine = sync[BASE(reg_idx)].vfp; ++ break; ++ case HDMITX_SYNCSRC_EMBEDDED: ++ embedded++; ++ /* fall thru */ ++ case HDMITX_SYNCSRC_EXT_VREF: ++ default: ++ syncMethod = 1; ++ toggleV = 1; ++ toggleH = 1; ++ toggleX = 1; ++ uRefPix = sync[BASE(reg_idx)].href; ++ uRefLine = sync[BASE(reg_idx)].vref; ++ break; ++ } ++ /* Table has +1 added to refpix values which are not needed in ++ RGB444, YUV444 and YUV422 modes, but +2 is required in those cases */ ++ if (vinMode != HDMITX_VINMODE_CCIR656) ++ { ++ uRefPix = uRefPix + 2; ++ } ++ ++ /* ---------------------------------------------------------- */ ++ /* Synchronicity software workaround issue number 106 */ ++ /* ---------------------------------------------------------- */ ++ if (vinMode == HDMITX_VINMODE_CCIR656) { ++ if (syncSource == HDMITX_SYNCSRC_EXT_VS) { ++ if (pDis->pixRate == HDMITX_PIXRATE_DOUBLE) { ++ ++ switch (reg_idx) { ++ case E_REGVFMT_720x480p_60Hz: ++ case E_REGVFMT_720x480i_60Hz: ++ case E_REGVFMT_720x576p_50Hz: ++ case E_REGVFMT_720x576i_50Hz: ++ uRefPix = uRefPix + 1; ++ break; ++ default: ++ /* do nothing... well I would say : FIXME */ ++ break; ++ } ++ ++ } ++ } ++ } ++ ++ ++ /* Set embedded sync */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_3_W, ++ E_MASKREG_P00_VIP_CNTRL_3_emb, ++ embedded); ++ RETIF_REG_FAIL(err) ++ ++ /* Set sync method */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_TBG_CNTRL_0_W, ++ E_MASKREG_P00_TBG_CNTRL_0_sync_mthd, ++ syncMethod); ++ RETIF_REG_FAIL(err) ++ ++/* printk("DBG auto toggle X:%d V:%d H:%d\n",toggleX,toggleV,toggleH); */ ++ /* Set VH toggle */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_3_W, ++ E_MASKREG_P00_VIP_CNTRL_3_v_tgl, ++ toggleV); ++ RETIF_REG_FAIL(err) ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_3_W, ++ E_MASKREG_P00_VIP_CNTRL_3_h_tgl, ++ toggleH); ++ RETIF_REG_FAIL(err) ++ ++ /* Set X toggle */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_3_W, ++ E_MASKREG_P00_VIP_CNTRL_3_x_tgl, ++ toggleX); ++ RETIF_REG_FAIL(err); ++ ++#ifdef TMFL_RGB_DDR_12BITS ++ if (syncSource == HDMITX_SYNCSRC_EXT_VREF) { ++ if (structure3D == HDMITX_3D_FRAME_PACKING) { ++ /* ++ stereo sync signaling : ++ ----------------------- ++ ++ When there is a positive sync at the input pins, therefore a negative sync ++ at input of the TBG, then 3d_neg_vs signal has to be set at 1 (OR-function) ++ to create the correct VS to preset the line and pixel counters ++ ++ case Vs > 0: ++ ----------- ++ Vs : __/¨¨\__ ++ Vs(TBG): ¨¨\__/¨¨ where Vs(TBG)=NOT(Vs) ++ 3D : ¨¨\_____ ++ Stereo : ¨¨\__/¨¨ where Stereo = Vs(TBG) OR 3D because 3d_neg_vs = 1 ++ ++ case Vs < 0: ++ ----------- ++ Vs : ¨¨\__/¨¨ ++ Vs(TBG): __/¨¨\__ where Vs(TBG)=NOT(Vs) ++ 3D : ¨¨\_____ ++ Stereo : __/¨¨\__ where Stereo = Vs(TBG) AND NOT(3D) because 3d_neg_vs = 0 ++ ++ ++ It is possible to invert the incoming VS, HS and DE. In case of 3D format ++ the DE input will be the 3D signal. This signal will only be used to remove ++ 1 of the VS depending on the polarity of the 3D signal. When there is a need ++ to switch the Left or Right it is possible to invert the 3D signal with an ++ already existing register. ++ ++ */ ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIDFORMAT_W, ++ E_MASKREG_P00_VIDFORMAT_3d_neg_vs, ++ toggleV); ++ RETIF_REG_FAIL(err); ++ } ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIDFORMAT_W, ++ E_MASKREG_P00_VIDFORMAT_3d, ++ (structure3D == HDMITX_3D_FRAME_PACKING)); ++ RETIF_REG_FAIL(err); ++ } ++#endif ++ ++ ++ if (EXTRA(reg_idx) && (structure3D != HDMITX_3D_FRAME_PACKING)) { ++ /* 2d extra video format */ ++ RETIF_REG_FAIL(set_video(pDis,BASE(reg_idx),(tmHdmiTxVidReg_t *)format_param_extra)); ++ } ++ else if (EXTRA(reg_idx3D) && (structure3D == HDMITX_3D_FRAME_PACKING)) { ++ /* 3d extra frame packing */ ++ RETIF_REG_FAIL(set_video(pDis,BASE(reg_idx3D),(tmHdmiTxVidReg_t *)format_param_extra)); ++ } ++ else { ++ /* see video set up using E_REG_P00_VIDFORMAT_W */ ++ } ++ ++ ++#ifdef FORMAT_PC ++ ++ if (IS_PC(vinFmt)) ++ { ++ RETIF_REG_FAIL(set_video(pDis,reg_idx,(tmHdmiTxVidReg_t *)format_param_PC)); ++ ++ regVal = DEPTH_COLOR_PC; ++ err = setHwRegisterField(pDis, ++ E_REG_P00_HVF_CNTRL_1_W, ++ E_MASKREG_P00_HVF_CNTRL_1_pad, ++ regVal); ++ RETIF_REG_FAIL(err); ++ } ++#endif /* FORMAT_PC */ ++ ++ /* Set refpix, refline */ ++ err = setHwRegisterMsbLsb(pDis, E_REG_P00_REFPIX_MSB_W, uRefPix); ++ RETIF_REG_FAIL(err) ++ err = setHwRegisterMsbLsb(pDis, E_REG_P00_REFLINE_MSB_W, uRefLine); ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989VideoInSetSyncManual */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989VideoInSetSyncManual ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxSyncSource_t syncSource, ++ tmbslHdmiTxVsMeth_t syncMethod, ++ tmbslHdmiTxPixTogl_t toggleV, ++ tmbslHdmiTxPixTogl_t toggleH, ++ tmbslHdmiTxPixTogl_t toggleX, ++ UInt16 uRefPix, ++ UInt16 uRefLine ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 embedded; /* Register value */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM(syncSource >= HDMITX_SYNCSRC_INVALID) ++ RETIF_BADPARAM(syncMethod >= HDMITX_VSMETH_INVALID) ++ RETIF_BADPARAM(toggleV >= HDMITX_PIXTOGL_INVALID) ++ RETIF_BADPARAM(toggleH >= HDMITX_PIXTOGL_INVALID) ++ RETIF_BADPARAM(toggleX >= HDMITX_PIXTOGL_INVALID) ++ RETIF_BADPARAM(uRefPix >= HDMITX_VOUT_FINE_PIXEL_INVALID) ++ RETIF_BADPARAM(uRefLine >= HDMITX_VOUT_FINE_LINE_INVALID) ++ ++ if (syncSource != HDMITX_SYNCSRC_NO_CHANGE) ++ { ++ if (syncSource == HDMITX_SYNCSRC_EMBEDDED) ++ { ++ embedded = 1; ++ } ++ else ++ { ++ embedded = 0; ++ } ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_3_W, ++ E_MASKREG_P00_VIP_CNTRL_3_emb, ++ embedded); ++ RETIF_REG_FAIL(err) ++ } ++ if (syncMethod != HDMITX_VSMETH_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_TBG_CNTRL_0_W, ++ E_MASKREG_P00_TBG_CNTRL_0_sync_mthd, ++ (UInt8)syncMethod); ++ RETIF_REG_FAIL(err) ++ } ++/* printk("DBG manual toggle X:%d V:%d H:%d\n",toggleX,toggleV,toggleH); */ ++ if (toggleV != HDMITX_PIXTOGL_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_3_W, ++ E_MASKREG_P00_VIP_CNTRL_3_v_tgl, ++ (UInt8)toggleV); ++ RETIF_REG_FAIL(err) ++ } ++ if (toggleH != HDMITX_PIXTOGL_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_3_W, ++ E_MASKREG_P00_VIP_CNTRL_3_h_tgl, ++ (UInt8)toggleH); ++ RETIF_REG_FAIL(err) ++ } ++ if (toggleX != HDMITX_PIXTOGL_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_3_W, ++ E_MASKREG_P00_VIP_CNTRL_3_x_tgl, ++ (UInt8)toggleX); ++ RETIF_REG_FAIL(err) ++ } ++ if (uRefPix < HDMITX_VOUT_FINE_PIXEL_NO_CHANGE) ++ { ++ err = setHwRegisterMsbLsb(pDis, E_REG_P00_REFPIX_MSB_W, uRefPix); ++ RETIF_REG_FAIL(err) ++ } ++ if (uRefLine < HDMITX_VOUT_FINE_LINE_NO_CHANGE) ++ { ++ err = setHwRegisterMsbLsb(pDis, E_REG_P00_REFLINE_MSB_W, uRefLine); ++ RETIF_REG_FAIL(err) ++ } ++ ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989VideoOutDisable */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++tmbslTDA9989VideoOutDisable ++( ++ tmUnitSelect_t txUnit, ++ Bool bDisable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM(bDisable > True) ++ ++ /* Set or clear frame_dis in the scaler Timebase Control 0 register ++ * according to bDisable ++ */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_TBG_CNTRL_0_W, ++ E_MASKREG_P00_TBG_CNTRL_0_frame_dis, ++ (UInt8)bDisable); ++ if (bDisable) ++ { ++ setState(pDis, EV_OUTDISABLE); ++ } ++ return err; ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989VideoOutSetConfig */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989VideoOutSetConfig ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxSinkType_t sinkType, ++ tmbslHdmiTxVoutMode_t voutMode, ++ tmbslHdmiTxVoutPrefil_t preFilter, ++ tmbslHdmiTxVoutYuvBlnk_t yuvBlank, ++ tmbslHdmiTxVoutQrange_t quantization ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regVal; /* Register value */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM(sinkType >= HDMITX_SINK_INVALID) ++ RETIF_BADPARAM(voutMode >= HDMITX_VOUTMODE_INVALID) ++ RETIF_BADPARAM(preFilter >= HDMITX_VOUT_PREFIL_INVALID) ++ RETIF_BADPARAM(yuvBlank >= HDMITX_VOUT_YUV_BLNK_INVALID) ++ RETIF_BADPARAM(quantization >= HDMITX_VOUT_QRANGE_INVALID) ++ ++ if (sinkType == HDMITX_SINK_EDID) ++ { ++ if (pDis->EdidStatus == HDMITX_EDID_NOT_READ) ++ { ++ /* EDID has not been read so assume simplest sink */ ++ pDis->sinkType = HDMITX_SINK_DVI; ++ } ++ else ++ { ++ /* EDID has been read so set sink to the type that was read */ ++ pDis->sinkType = pDis->EdidSinkType; ++ } ++ } ++ else ++ { ++ /* Set demanded sink type */ ++ pDis->sinkType = sinkType; ++ } ++ ++ /* Is DVI sink required? */ ++ if (pDis->sinkType == HDMITX_SINK_DVI) ++ { ++ /* Mute the audio FIFO */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_AIP_CNTRL_0_RW, ++ E_MASKREG_P11_AIP_CNTRL_0_rst_fifo, ++ 1); ++ RETIF_REG_FAIL(err) ++ ++ /* Force RGB mode for DVI sink */ ++ voutMode = HDMITX_VOUTMODE_RGB444; ++ ++ /* Set HDMI HDCP mode off for DVI */ ++ err = setHwRegisterFieldTable(pDis, &kVoutHdcpOff[0]); ++ RETIF_REG_FAIL(err); ++ ++ HDCP_F1; ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_ENC_CNTRL_RW, ++ E_MASKREG_P11_ENC_CNTRL_ctl_code, ++ regVal); ++ RETIF_REG_FAIL(err) ++ } ++ else ++ { ++ /* Unmute the audio FIFO */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_AIP_CNTRL_0_RW, ++ E_MASKREG_P11_AIP_CNTRL_0_rst_fifo, ++ 0); ++ RETIF_REG_FAIL(err) ++ ++ /* Set HDMI HDCP mode on for HDMI */ ++ /* Also sets E_MASKREG_P11_ENC_CNTRL_ctl_code */ ++ err = setHwRegisterFieldTable(pDis, &kVoutHdcpOn[0]); ++ RETIF_REG_FAIL(err) ++ } ++ ++ /* For each parameter that is not No Change, set its register */ ++ if (voutMode != HDMITX_VOUTMODE_NO_CHANGE) ++ { ++ /* Save the output mode for later use by the matrix & downsampler */ ++ pDis->voutMode = voutMode; ++ } ++ if (preFilter < HDMITX_VOUT_PREFIL_NO_CHANGE) ++ { ++#ifdef TMFL_HDCP_OPTIMIZED_POWER ++ /* ++ power management : ++ freeze/wakeup SPDIF clock ++ */ ++ err = setHwRegisterField(pDis, E_REG_FEAT_POWER_DOWN, \ ++ E_MASKREG_FEAT_POWER_DOWN_prefilt, \ ++ (preFilter == HDMITX_VOUT_PREFIL_OFF)); ++ RETIF_REG_FAIL(err); ++#endif ++ err = setHwRegisterField(pDis, ++ E_REG_P00_HVF_CNTRL_0_W, ++ E_MASKREG_P00_HVF_CNTRL_0_prefil, ++ (UInt8)preFilter); ++ RETIF_REG_FAIL(err) ++ } ++ if (yuvBlank < HDMITX_VOUT_YUV_BLNK_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_HVF_CNTRL_1_W, ++ E_MASKREG_P00_HVF_CNTRL_1_yuvblk, ++ (UInt8)yuvBlank); ++ RETIF_REG_FAIL(err) ++ } ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989VideoOutSetSync */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989VideoOutSetSync ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxVsSrc_t srcH, ++ tmbslHdmiTxVsSrc_t srcV, ++ tmbslHdmiTxVsSrc_t srcX, ++ tmbslHdmiTxVsTgl_t toggle, ++ tmbslHdmiTxVsOnce_t once ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 reg_idx; ++ struct sync_desc *sync; ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM(srcH >= HDMITX_VSSRC_INVALID) ++ RETIF_BADPARAM(srcV >= HDMITX_VSSRC_INVALID) ++ RETIF_BADPARAM(srcX >= HDMITX_VSSRC_INVALID) ++ RETIF_BADPARAM(toggle >= HDMITX_VSTGL_INVALID) ++ RETIF_BADPARAM(once >= HDMITX_VSONCE_INVALID) ++ ++ /* For each parameter that is not No Change, set its register */ ++ if (srcH != HDMITX_VSSRC_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_TBG_CNTRL_1_W, ++ E_MASKREG_P00_TBG_CNTRL_1_vhx_ext_hs, ++ (UInt8)srcH); ++ RETIF_REG_FAIL(err) ++ } ++ if (srcV != HDMITX_VSSRC_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_TBG_CNTRL_1_W, ++ E_MASKREG_P00_TBG_CNTRL_1_vhx_ext_vs, ++ (UInt8)srcV); ++ RETIF_REG_FAIL(err) ++ } ++ if (srcX != HDMITX_VSSRC_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_TBG_CNTRL_1_W, ++ E_MASKREG_P00_TBG_CNTRL_1_vhx_ext_de, ++ (UInt8)srcX); ++ RETIF_REG_FAIL(err) ++ } ++ { ++ /* Hs Vs polarity fix */ ++ /* set polarity back when VIDFORMAT_TABLE (E_REG_P00_VIDFORMAT_W) is not used */ ++ RETIF_BADPARAM(reg_vid_fmt(pDis->vinFmt,0,®_idx,0,&sync)); ++ if (EXTRA(reg_idx)) { ++ toggle= E_MASKREG_P00_TBG_CNTRL_1_vh_tgl & \ ++ (0x04 | sync[BASE(reg_idx)].v_toggle | sync[BASE(reg_idx)].h_toggle); ++ } ++ } ++ ++ ++ if (toggle != HDMITX_VSTGL_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_TBG_CNTRL_1_W, ++ E_MASKREG_P00_TBG_CNTRL_1_vh_tgl, ++ (UInt8)toggle); ++/* printk("DBG toogl CNTRL1:%d\n",toggle); */ ++ RETIF_REG_FAIL(err) ++ } ++ if (once != HDMITX_VSONCE_NO_CHANGE) ++ { ++ /* Must be last register set */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_TBG_CNTRL_0_W, ++ E_MASKREG_P00_TBG_CNTRL_0_sync_once, ++ (UInt8)once); ++ RETIF_REG_FAIL(err) ++ } ++ ++ /* Toggle TMDS serialiser force flags - stability fix */ ++ err = setHwRegisterField(pDis, ++ E_REG_P02_BUFFER_OUT_RW, ++ E_MASKREG_P02_BUFFER_OUT_srl_force, ++ (UInt8)HDMITX_TMDSOUT_FORCED0); ++ RETIF_REG_FAIL(err) ++ err = setHwRegisterField(pDis, ++ E_REG_P02_BUFFER_OUT_RW, ++ E_MASKREG_P02_BUFFER_OUT_srl_force, ++ (UInt8)HDMITX_TMDSOUT_NORMAL); ++ RETIF_REG_FAIL(err) ++ ++ ++ if (once == HDMITX_VSONCE_ONCE) ++ { ++ /* Toggle output Sync Once flag for settings to take effect */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_TBG_CNTRL_0_W, ++ E_MASKREG_P00_TBG_CNTRL_0_sync_once, ++ (UInt8)HDMITX_VSONCE_EACH_FRAME); ++ RETIF_REG_FAIL(err) ++ err = setHwRegisterField(pDis, ++ E_REG_P00_TBG_CNTRL_0_W, ++ E_MASKREG_P00_TBG_CNTRL_0_sync_once, ++ (UInt8)HDMITX_VSONCE_ONCE); ++ RETIF_REG_FAIL(err) ++ } ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989VideoSetInOut */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989VideoSetInOut ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxVidFmt_t vinFmt, ++ tmbslHdmiTx3DStructure_t structure3D, ++ tmbslHdmiTxScaMode_t scaModeRequest, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ UInt8 uPixelRepeat, ++ tmbslHdmiTxMatMode_t matMode, ++ tmbslHdmiTxVoutDbits_t datapathBits, ++ tmbslHdmiTxVQR_t dviVqr ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ tmbslHdmiTxScaMode_t scaMode; /* Scaler mode */ ++ UInt8 reg_idx,reg_idx3D; /* Video o/p format value used for register */ ++ UInt8 regVal; ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM(!IS_VALID_FMT(vinFmt)) ++ RETIF_BADPARAM(!IS_VALID_FMT(voutFmt)) ++ ++ RETIF_BADPARAM(scaModeRequest >= HDMITX_SCAMODE_INVALID) ++ RETIF_BADPARAM(uPixelRepeat >= HDMITX_PIXREP_INVALID) ++ RETIF_BADPARAM(matMode >= HDMITX_MATMODE_INVALID) ++ RETIF_BADPARAM(datapathBits >= HDMITX_VOUT_DBITS_INVALID) ++ ++ scaMode = HDMITX_SCAMODE_OFF; ++ pDis->scaMode = HDMITX_SCAMODE_OFF; ++ ++ /* Get current input format if it must not change */ ++ if (vinFmt == HDMITX_VFMT_NO_CHANGE) ++ { ++ RETIF(pDis->vinFmt == HDMITX_VFMT_NULL, ++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS) ++ vinFmt = pDis->vinFmt; ++ } ++ else ++ { ++ pDis->vinFmt = vinFmt; ++ pDis->h3dFpOn = (structure3D == HDMITX_3D_FRAME_PACKING); ++ ++#ifdef TMFL_TDA9989_PIXEL_CLOCK_ON_DDC ++ ++ if (IS_TV(pDis->vinFmt)) { ++ ++ err = setHwRegister(pDis, E_REG_P00_TIMER_H_W, 0); ++ RETIF(err != TM_OK, err); ++ ++ err = setHwRegister(pDis, E_REG_P00_NDIV_IM_W, kndiv_im[vinFmt]); ++ RETIF(err != TM_OK, err); ++ ++ err = setHwRegister(pDis, E_REG_P12_TX3_RW, kclk_div[vinFmt]); ++ RETIF(err != TM_OK, err); ++ ++ } ++ else { ++ ++ err = setHwRegister(pDis, E_REG_P00_TIMER_H_W, E_MASKREG_P00_TIMER_H_im_clksel); ++ RETIF(err != TM_OK, err); ++ err = setHwRegister(pDis, E_REG_P12_TX3_RW, 17); ++ RETIF(err != TM_OK, err); ++ } ++#endif /* TMFL_TDA9989_PIXEL_CLOCK_ON_DDC */ ++ ++ ++ } ++ ++ /* Get current output format if it must not change */ ++ if (voutFmt == HDMITX_VFMT_NO_CHANGE) ++ { ++ RETIF(pDis->voutFmt == HDMITX_VFMT_NULL, ++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS) ++ voutFmt = pDis->voutFmt; ++ } ++ else ++ { ++ pDis->voutFmt = voutFmt; ++ } ++ if (pDis->voutMode == HDMITX_VOUTMODE_RGB444) ++ { ++ if ((pDis->voutFmt >= HDMITX_VFMT_02_720x480p_60Hz) && (IS_TV(pDis->voutFmt))) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_HVF_CNTRL_1_W, ++ E_MASKREG_P00_HVF_CNTRL_1_vqr, ++ (UInt8) HDMITX_VOUT_QRANGE_RGB_YUV); ++ RETIF_REG_FAIL(err) ++ } ++ else /*Format PC or VGA*/ ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_HVF_CNTRL_1_W, ++ E_MASKREG_P00_HVF_CNTRL_1_vqr, ++ (UInt8) HDMITX_VOUT_QRANGE_FS); ++ RETIF_REG_FAIL(err) ++ } ++ } ++ else ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_HVF_CNTRL_1_W, ++ E_MASKREG_P00_HVF_CNTRL_1_vqr, ++ (UInt8) HDMITX_VOUT_QRANGE_YUV); ++ RETIF_REG_FAIL(err); ++ } ++ ++ /* Set pixel repetition - sets pixelRepeatCount, used by setScalerFormat */ ++ err = setPixelRepeat(pDis, voutFmt, uPixelRepeat, structure3D); ++ RETIF(err != TM_OK, err); ++ ++ /* If scaler mode is auto then set mode based on input and output format */ ++ if (scaMode != HDMITX_SCAMODE_NO_CHANGE) ++ { ++ /* Set scaler clock */ ++ regVal = 0; ++ if ((pDis->pixelRepeatCount > HDMITX_PIXREP_MIN) && ++ (pDis->pixelRepeatCount <= HDMITX_PIXREP_MAX)) ++ { ++ regVal = 2; ++ } ++ else if (pDis->vinMode == HDMITX_VINMODE_CCIR656) ++ { ++ regVal = (UInt8)((pDis->scaMode == HDMITX_SCAMODE_ON) ? 0 : 1); ++ ++ if (pDis->pixRate == HDMITX_PIXRATE_DOUBLE) ++ { ++ regVal = 0; ++ } ++ } ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P02_SEL_CLK_RW, ++ E_MASKREG_P02_SEL_CLK_sel_vrf_clk, ++ regVal); ++ RETIF_REG_FAIL(err); ++ ++ /* Look up the VIDFORMAT register format from the register format table */ ++ RETIF_BADPARAM(reg_vid_fmt(vinFmt,structure3D,®_idx,®_idx3D,0)); ++ ++ /* Set format register for the selected output format voutFmt */ ++ if (PREFETCH(reg_idx3D) && (structure3D == HDMITX_3D_FRAME_PACKING)) { ++ /* embedded 3D video format */ ++ err = setHwRegister(pDis, E_REG_P00_VIDFORMAT_W,reg_idx3D); ++ } ++ else if (PREFETCH(reg_idx) && (structure3D != HDMITX_3D_FRAME_PACKING)) { ++ /* embedded 2D video format */ ++/* printk("DBG %s E_REG_P00_VIDFORMAT_W used\n",__func__); */ ++ err = setHwRegister(pDis, E_REG_P00_VIDFORMAT_W,reg_idx); ++ } ++ else { ++ /* see video set up using set_video() */ ++ } ++ RETIF_REG_FAIL(err); ++ ++ } ++ ++ /* Set VS and optional DE */ ++ err = setDeVs(pDis, voutFmt, structure3D); ++ RETIF(err != TM_OK, err); ++ ++ /* If matrix mode is auto then set mode based on input and output format */ ++ if (matMode != HDMITX_MATMODE_NO_CHANGE) ++ { ++ if (matMode == HDMITX_MATMODE_AUTO) ++ { ++ err = tmbslTDA9989MatrixSetConversion(txUnit, vinFmt, ++ pDis->vinMode, voutFmt, pDis->voutMode,pDis->dviVqr); ++ } ++ else ++ { ++ err = tmbslTDA9989MatrixSetMode(txUnit, HDMITX_MCNTRL_OFF, ++ HDMITX_MSCALE_NO_CHANGE); ++ } ++ RETIF(err != TM_OK, err) ++ } ++ ++ /* Set upsampler and downsampler */ ++ err = setSampling(pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Set colour component bit depth */ ++ if (datapathBits != HDMITX_VOUT_DBITS_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_HVF_CNTRL_1_W, ++ E_MASKREG_P00_HVF_CNTRL_1_pad, ++ (UInt8)datapathBits); ++ RETIF_REG_FAIL(err) ++ } ++ ++ /* Save kBypassColourProc registers before pattern goes on */ ++ getHwRegister(pDis, E_REG_P00_MAT_CONTRL_W, &gMatContrl[txUnit]); ++ getHwRegister(pDis, E_REG_P00_HVF_CNTRL_0_W, &gHvfCntrl0[txUnit]); ++ getHwRegister(pDis, E_REG_P00_HVF_CNTRL_1_W, &gHvfCntrl1[txUnit]); ++ ++ setState(pDis, EV_SETINOUT); ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989MatrixSetCoeffs */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++tmbslTDA9989MatrixSetCoeffs ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxMatCoeff_t *pMatCoeff ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ Int i; /* Loop index */ ++ UInt8 buf[HDMITX_MAT_COEFF_NUM * 2]; /* Temp buffer */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(pMatCoeff == (tmbslHdmiTxMatCoeff_t *)0) ++ for (i = 0; i < HDMITX_MAT_COEFF_NUM; i++) ++ { ++ RETIF_BADPARAM((pMatCoeff->Coeff[i] < HDMITX_MAT_OFFSET_MIN) || ++ (pMatCoeff->Coeff[i] > HDMITX_MAT_OFFSET_MAX)) ++ } ++ ++ /* Convert signed 11 bit values from Coeff array to pairs of MSB-LSB ++ * register values, and write to register pairs ++ */ ++ for (i = 0; i < HDMITX_MAT_COEFF_NUM; i++) ++ { ++ /* Mask & copy MSB */ ++ buf[i*2] = (UInt8)(((UInt16)pMatCoeff->Coeff[i] & 0x0700) >> 8); ++ /* Copy LSB */ ++ buf[(i*2)+1] = (UInt8)((UInt16)pMatCoeff->Coeff[i] & 0x00FF); ++ } ++ err = setHwRegisters(pDis, ++ E_REG_P00_MAT_P11_MSB_W, ++ &buf[0], ++ HDMITX_MAT_COEFF_NUM * 2); ++ return err; ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989MatrixSetConversion */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989MatrixSetConversion ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxVidFmt_t vinFmt, ++ tmbslHdmiTxVinMode_t vinMode, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ tmbslHdmiTxVoutMode_t voutMode, ++ tmbslHdmiTxVQR_t dviVqr ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Ptr to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ tmbslTDA9989Colourspace_t cspace_in; /* Input colourspaces */ ++ tmbslTDA9989Colourspace_t cspace_out; /* Output colourspaces */ ++ Int matrixIndex;/* Index into matrix preset array */ ++ UInt8 buf[MATRIX_PRESET_SIZE]; /* Temp buffer */ ++ UInt8 i; /* Loop index */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(!IS_VALID_FMT(vinFmt)) ++ RETIF_BADPARAM(!IS_VALID_FMT(voutFmt)) ++ /* NB: NO_CHANGE is not valid for this function, so limit to actual values*/ ++ RETIF_BADPARAM(vinMode >= HDMITX_VINMODE_NO_CHANGE) ++ /* NB: NO_CHANGE is not valid for this function, so limit to actual values*/ ++ RETIF_BADPARAM(voutMode >= HDMITX_VOUTMODE_NO_CHANGE) ++ ++ /* Since vinMode and voutMode are different types, we don't use a local ++ function to do this and use inline code twice */ ++ ++ ++ /* Calculate input colour space */ ++ switch (vinFmt) ++ { /* Catch the HD modes */ ++ case HDMITX_VFMT_04_1280x720p_60Hz: ++ case HDMITX_VFMT_05_1920x1080i_60Hz: ++ case HDMITX_VFMT_16_1920x1080p_60Hz: ++ case HDMITX_VFMT_19_1280x720p_50Hz: ++ case HDMITX_VFMT_20_1920x1080i_50Hz: ++ case HDMITX_VFMT_31_1920x1080p_50Hz: ++ case HDMITX_VFMT_32_1920x1080p_24Hz: ++ case HDMITX_VFMT_33_1920x1080p_25Hz: ++ case HDMITX_VFMT_34_1920x1080p_30Hz: ++ case HDMITX_VFMT_60_1280x720p_24Hz: ++ case HDMITX_VFMT_61_1280x720p_25Hz: ++ case HDMITX_VFMT_62_1280x720p_30Hz: ++ ++ if(vinMode == HDMITX_VINMODE_RGB444) /* RGB */ ++ { ++ cspace_in = HDMITX_CS_RGB_LIMITED; ++ } ++ else /* CCIR656, YUV444, YU422 */ ++ { ++ cspace_in = HDMITX_CS_YUV_ITU_BT709; ++ } ++ break; ++ default: /* Now all the SD modes */ ++ if(vinMode == HDMITX_VINMODE_RGB444) /* we're RGB */ ++ { ++ cspace_in = HDMITX_CS_RGB_LIMITED; ++ } ++ else /* CCIR656, YUV444, YU422 */ ++ { ++ cspace_in = HDMITX_CS_YUV_ITU_BT601; ++ } ++ break; ++ } ++ ++/* } */ ++ ++ /* Calculate output colour space */ ++#ifdef FORMAT_PC ++ if(IS_PC(voutFmt)) ++ { ++ /* Catch the PC formats */ ++ cspace_in = HDMITX_CS_RGB_FULL; /* PR1570 FIXED */ ++ cspace_out = HDMITX_CS_RGB_FULL; ++ } ++ else ++ { ++#endif ++ switch (voutFmt) ++ { /* Catch the HD modes */ ++ case HDMITX_VFMT_04_1280x720p_60Hz: ++ case HDMITX_VFMT_05_1920x1080i_60Hz: ++ case HDMITX_VFMT_16_1920x1080p_60Hz: ++ case HDMITX_VFMT_19_1280x720p_50Hz: ++ case HDMITX_VFMT_20_1920x1080i_50Hz: ++ case HDMITX_VFMT_31_1920x1080p_50Hz: ++ case HDMITX_VFMT_32_1920x1080p_24Hz: ++ case HDMITX_VFMT_33_1920x1080p_25Hz: ++ case HDMITX_VFMT_34_1920x1080p_30Hz: ++ case HDMITX_VFMT_60_1280x720p_24Hz: ++ case HDMITX_VFMT_61_1280x720p_25Hz: ++ case HDMITX_VFMT_62_1280x720p_30Hz: ++ ++ if(voutMode == HDMITX_VOUTMODE_RGB444) /* RGB */ ++ { ++ cspace_out = HDMITX_CS_RGB_LIMITED; ++ } ++ else /* YUV444 or YUV422 */ ++ { ++ cspace_out = HDMITX_CS_YUV_ITU_BT709; ++ } ++ break; ++ default: /* Now all the SD modes */ ++ if(voutMode == HDMITX_VOUTMODE_RGB444) /* RGB */ ++ { ++ cspace_out = HDMITX_CS_RGB_LIMITED; ++ } ++ else /* YUV444 or YUV422 */ ++ { ++ cspace_out = HDMITX_CS_YUV_ITU_BT601; ++ } ++ break; ++ } ++#ifdef FORMAT_PC ++ } ++#endif ++ ++#ifdef TMFL_HDCP_OPTIMIZED_POWER ++ /* ++ power management : ++ freeze/wakeup color space conversion clock ++ */ ++ err = setHwRegisterField(pDis, E_REG_FEAT_POWER_DOWN, \ ++ E_MASKREG_FEAT_POWER_DOWN_csc, \ ++ (cspace_in == cspace_out)); ++ RETIF_REG_FAIL(err); ++#endif ++ ++ if (cspace_in == cspace_out) ++ { ++ /* Switch off colour matrix by setting bypass flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_MAT_CONTRL_W, ++ E_MASKREG_P00_MAT_CONTRL_mat_bp, ++ 1); ++ } ++ else ++ { ++ /* Load appropriate values into matrix - we have preset blocks of ++ * 31 register vales in a table, just need to work out which set to use ++ */ ++ matrixIndex = kMatrixIndex[cspace_in][cspace_out]; ++ ++ /* Set the first block byte separately, as it is shadowed and can't ++ * be set by setHwRegisters */ ++ err = setHwRegister(pDis, ++ E_REG_P00_MAT_CONTRL_W, ++ kMatrixPreset[matrixIndex][0]); ++ RETIF_REG_FAIL(err) ++ ++ for (i = 0; i < MATRIX_PRESET_SIZE; i++) ++ { ++ buf[i] = kMatrixPreset[matrixIndex][i]; ++ } ++ ++ /* Set the rest of the block */ ++ err = setHwRegisters(pDis, ++ E_REG_P00_MAT_OI1_MSB_W, ++ &buf[1], ++ MATRIX_PRESET_SIZE - 1); ++ } ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989MatrixSetInputOffset */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++tmbslTDA9989MatrixSetInputOffset ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxMatOffset_t *pMatOffset ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ Int i; /* Loop index */ ++ UInt8 buf[HDMITX_MAT_OFFSET_NUM * 2]; /* Temp buffer */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(pMatOffset == (tmbslHdmiTxMatOffset_t *)0) ++ for (i = 0; i < HDMITX_MAT_OFFSET_NUM; i++) ++ { ++ RETIF_BADPARAM((pMatOffset->Offset[i] < HDMITX_MAT_OFFSET_MIN) || ++ (pMatOffset->Offset[i] > HDMITX_MAT_OFFSET_MAX)) ++ } ++ ++ /* Convert signed 11 bit values from Offset array to pairs of MSB-LSB ++ * register values, and write to register pairs ++ */ ++ for (i = 0; i < HDMITX_MAT_OFFSET_NUM; i++) ++ { ++ /* Mask & copy MSB */ ++ buf[i*2] = (UInt8)(((UInt16)pMatOffset->Offset[i] & 0x0700) >> 8); ++ /* Copy LSB */ ++ buf[(i*2)+1] = (UInt8)((UInt16)pMatOffset->Offset[i] & 0x00FF); ++ } ++ err = setHwRegisters(pDis, ++ E_REG_P00_MAT_OI1_MSB_W, ++ &buf[0], ++ HDMITX_MAT_OFFSET_NUM * 2); ++ return err; ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989MatrixSetMode */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989MatrixSetMode ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxmCntrl_t mControl, ++ tmbslHdmiTxmScale_t mScale ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM((mControl > HDMITX_MCNTRL_MAX) || ++ (mScale > HDMITX_MSCALE_MAX)) ++ ++ /* For each value that is not NoChange, update the appropriate register */ ++ if (mControl != HDMITX_MCNTRL_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_MAT_CONTRL_W, ++ E_MASKREG_P00_MAT_CONTRL_mat_bp, ++ (UInt8)mControl); ++ RETIF_REG_FAIL(err) ++ } ++ ++ if (mScale != HDMITX_MSCALE_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_MAT_CONTRL_W, ++ E_MASKREG_P00_MAT_CONTRL_mat_sc, ++ (UInt8)mScale); ++ RETIF_REG_FAIL(err) ++ } ++ ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989MatrixSetOutputOffset */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++tmbslTDA9989MatrixSetOutputOffset ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxMatOffset_t *pMatOffset ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ Int i; /* Loop index */ ++ UInt8 buf[HDMITX_MAT_OFFSET_NUM * 2]; /* Temp buffer */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM(pMatOffset == (tmbslHdmiTxMatOffset_t *)0) ++ for (i = 0; i < HDMITX_MAT_OFFSET_NUM; i++) ++ { ++ RETIF_BADPARAM((pMatOffset->Offset[i] < HDMITX_MAT_OFFSET_MIN) || ++ (pMatOffset->Offset[i] > HDMITX_MAT_OFFSET_MAX)) ++ } ++ ++ /* Convert signed 11 bit values from Offset array to pairs of MSB-LSB ++ * register values, and write to register pairs ++ */ ++ for (i = 0; i < HDMITX_MAT_OFFSET_NUM; i++) ++ { ++ /* Mask & copy MSB */ ++ buf[i*2] = (UInt8)(((UInt16)pMatOffset->Offset[i] & 0x0700) >> 8); ++ /* Copy LSB */ ++ buf[(i*2)+1] = (UInt8)((UInt16)pMatOffset->Offset[i] & 0x00FF); ++ } ++ err = setHwRegisters(pDis, ++ E_REG_P00_MAT_OO1_MSB_W, ++ &buf[0], ++ HDMITX_MAT_OFFSET_NUM * 2); ++ return err; ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989PktSetAclkRecovery */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++tmbslTDA9989PktSetAclkRecovery ++( ++ tmUnitSelect_t txUnit, ++ Bool bEnable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the ++ * sinkType is not HDMI ++ */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM((bEnable != True) && (bEnable != False)) ++ ++ /* Write the ACR packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_FLAGS_RW, ++ E_MASKREG_P11_DIP_FLAGS_acr, ++ (UInt8)bEnable); ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989PktSetAcp */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989PktSetAcp ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPkt_t *pPkt, ++ UInt byteCnt, ++ UInt8 uAcpType, ++ Bool bEnable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 buf[3]; /* Temp buffer to hold header bytes */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the ++ * sinkType is not HDMI ++ */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Only supported for device N4 or later */ ++ ++ /* Check remaining parameter(s) - NULL pointer allowed */ ++ RETIF_BADPARAM((bEnable != True) && (bEnable != False)) ++ ++ if(pPkt != Null) ++ { ++ /* Pointer to structure provided so check parameters */ ++ RETIF_BADPARAM(byteCnt > HDMITX_PKT_DATA_BYTE_CNT) ++ RETIF(byteCnt == 0, TMBSL_ERR_HDMI_INCONSISTENT_PARAMS) ++ ++ /* Data to change, start by clearing ACP packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_FLAGS_RW, ++ E_MASKREG_P11_DIP_FLAGS_acp, ++ 0x00); ++ RETIF_REG_FAIL(err) ++ ++ /* Prepare ACP header */ ++ buf[0] = 0x04; /* ACP packet */ ++ buf[1] = uAcpType; ++ buf[2] = 0; /* Reserved [HDMI 1.2] */ ++ ++ ++ /* Write 3 header bytes to registers */ ++ err = setHwRegisters(pDis, ++ E_REG_P11_ACP_HB0_RW, ++ &buf[0], ++ 3); ++ RETIF_REG_FAIL(err) ++ ++ /* Write "byteCnt" bytes of data to registers */ ++ err = setHwRegisters(pDis, ++ E_REG_P11_ACP_PB0_RW, ++ &pPkt->dataByte[0], ++ (UInt16)byteCnt); ++ RETIF_REG_FAIL(err) ++ } ++ ++ /* Write the ACP packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_FLAGS_RW, ++ E_MASKREG_P11_DIP_FLAGS_acp, ++ (UInt8)bEnable); ++ return err; ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989PktSetAudioInfoframe */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989PktSetAudioInfoframe ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPktAif_t *pPkt, ++ Bool bEnable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 buf[9]; /* Temp buffer to hold header/packet bytes */ ++ UInt16 bufReg; /* Base register used for writing InfoFrame*/ ++ UInt16 flagReg;/* Flag register to be used */ ++ UInt8 flagMask;/* Mask used for writing flag register */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the ++ * sinkType is not HDMI ++ */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Check remaining parameter(s) - NULL pointer allowed */ ++ RETIF_BADPARAM((bEnable != True) && (bEnable != False)) ++ if(pPkt != Null) ++ { ++ /* Pointer to structure provided so check parameters */ ++ RETIF_BADPARAM(pPkt->CodingType > 0x0F) ++ RETIF_BADPARAM(pPkt->ChannelCount > 0x07) ++ RETIF_BADPARAM(pPkt->SampleFreq > 0x07) ++ RETIF_BADPARAM(pPkt->SampleSize > 0x03) ++ /* No need to check ChannelAlloc - all values are allowed */ ++ RETIF_BADPARAM((pPkt->DownMixInhibit != True) && ++ (pPkt->DownMixInhibit != False)) ++ RETIF_BADPARAM(pPkt->LevelShift > 0x0F) ++ } ++ ++ /* Only supported for device N4 or later */ ++ ++ /* We're using n4 or later, use IF4 buffer for Audio InfoFrame */ ++ bufReg = E_REG_P10_IF4_HB0_RW; ++ flagReg = E_REG_P11_DIP_IF_FLAGS_RW; ++ flagMask = E_MASKREG_P11_DIP_IF_FLAGS_if4; ++ ++ if(pPkt != Null) ++ { ++ /* Data to change, start by clearing AIF packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ flagReg, ++ flagMask, ++ 0x00); ++ RETIF_REG_FAIL(err) ++ ++ /* Prepare AIF header */ ++ buf[0] = 0x84; /* Audio InfoFrame */ ++ buf[1] = 0x01; /* Version 1 [HDMI 1.2] */ ++ buf[2] = 0x0A; /* Length [HDMI 1.2] */ ++ ++ /* Prepare AIF packet (byte numbers offset by 3) */ ++ buf[0+3] = 0; /* Preset checksum to zero so calculation works! */ ++ buf[1+3] = ((pPkt->CodingType & 0x0F) << 4) | ++ (pPkt->ChannelCount & 0x07); /* CT3-0, CC2-0 */ ++ buf[2+3] = ((pPkt->SampleFreq & 0x07) << 2) | ++ (pPkt->SampleSize & 0x03); /* SF2-0, SS1-0 */ ++ buf[3+3] = 0; /* [HDMI 1.2] */ ++ buf[4+3] = pPkt->ChannelAlloc; /* CA7-0 */ ++ buf[5+3] = ((pPkt->LevelShift & 0x0F) << 3); /* LS3-0 */ ++ if(pPkt->DownMixInhibit == True) ++ { ++ buf[5+3] += 0x80; /* DMI bit */ ++ } ++ ++ /* Calculate checksum - this is worked out on "Length" bytes of the ++ * packet, the checksum (which we've preset to zero), and the three ++ * header bytes. We exclude bytes PB6 to PB10 (which we ++ * are not writing) since they are zero. ++ */ ++ buf[0+3] = calculateChecksum(&buf[0], 0x0A+1+3-5); ++ ++ /* Write header and packet bytes in one operation */ ++ err = setHwRegisters(pDis, ++ bufReg, ++ &buf[0], ++ 9); ++ RETIF_REG_FAIL(err) ++ } ++ ++ /* Write AIF packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ flagReg, ++ flagMask, ++ (UInt8)bEnable); ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989PktSetGeneralCntrl */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++tmbslTDA9989PktSetGeneralCntrl ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxaMute_t *paMute, ++ Bool bEnable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the ++ * sinkType is not HDMI ++ */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Check remaining parameter(s) - NULL pointer allowed */ ++ RETIF_BADPARAM((bEnable != True) && (bEnable != False)) ++ ++ if(paMute != Null) ++ { ++ RETIF_BADPARAM((*paMute != HDMITX_AMUTE_OFF) && (*paMute != HDMITX_AMUTE_ON)) ++ ++ if (*paMute == HDMITX_AMUTE_ON) ++ { ++ err = setHwRegister(pDis, E_REG_P11_GC_AVMUTE_RW, 0x02); ++ RETIF_REG_FAIL(err) ++ } ++ else ++ { ++ err = setHwRegister(pDis, E_REG_P11_GC_AVMUTE_RW, 0x01); ++ RETIF_REG_FAIL(err) ++ } ++ } ++ ++ /* Set or clear GC packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_FLAGS_RW, ++ E_MASKREG_P11_DIP_FLAGS_gc, ++ (UInt8)bEnable); ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989PktSetIsrc1 */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989PktSetIsrc1 ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPkt_t *pPkt, ++ UInt byteCnt, ++ Bool bIsrcCont, ++ Bool bIsrcValid, ++ UInt8 uIsrcStatus, ++ Bool bEnable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 buf[3]; /* Temp buffer to hold header bytes */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the ++ * sinkType is not HDMI ++ */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Only supported for device N4 or later */ ++ ++ /* Check remaining parameter(s) - NULL pointer allowed */ ++ RETIF_BADPARAM((bEnable != True) && (bEnable != False)) ++ ++ if(pPkt != Null) ++ { ++ /* Pointer to structure provided so check parameters */ ++ RETIF_BADPARAM((bIsrcCont != True) && (bIsrcCont != False)) ++ RETIF_BADPARAM((bIsrcValid != True) && (bIsrcValid != False)) ++ RETIF_BADPARAM(uIsrcStatus > 7) /* 3 bits */ ++ RETIF_BADPARAM(byteCnt > HDMITX_PKT_DATA_BYTE_CNT) ++ RETIF(byteCnt == 0, TMBSL_ERR_HDMI_INCONSISTENT_PARAMS) ++ ++ /* Data to change, start by clearing ISRC1 packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_FLAGS_RW, ++ E_MASKREG_P11_DIP_FLAGS_isrc1, ++ 0x00); ++ RETIF_REG_FAIL(err) ++ ++ /* Prepare ISRC1 header */ ++ buf[0] = 0x05; /* ISRC1 packet */ ++ buf[1] = (uIsrcStatus & 0x07); ++ if(bIsrcValid == True) ++ { ++ buf[1] += 0x40; ++ } ++ if(bIsrcCont == True) ++ { ++ buf[1] += 0x80; ++ } ++ buf[2] = 0; /* Reserved [HDMI 1.2] */ ++ ++ /* Write 3 header bytes to registers */ ++ err = setHwRegisters(pDis, ++ E_REG_P11_ISRC1_HB0_RW, ++ &buf[0], ++ 3); ++ RETIF_REG_FAIL(err) ++ ++ /* Write "byteCnt" bytes of data to registers */ ++ err = setHwRegisters(pDis, ++ E_REG_P11_ISRC1_PB0_RW, ++ &pPkt->dataByte[0], ++ (UInt16)byteCnt); ++ RETIF_REG_FAIL(err) ++ } ++ ++ /* Write the ISRC1 packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_FLAGS_RW, ++ E_MASKREG_P11_DIP_FLAGS_isrc1, ++ (UInt8)bEnable); ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989PktSetIsrc2 */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989PktSetIsrc2 ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPkt_t *pPkt, ++ UInt byteCnt, ++ Bool bEnable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 buf[3]; /* Temp buffer to hold header bytes */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the ++ * sinkType is not HDMI ++ */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Only supported for device N4 or later */ ++ ++ /* Check remaining parameter(s) - NULL pointer allowed */ ++ RETIF_BADPARAM((bEnable != True) && (bEnable != False)) ++ ++ if(pPkt != Null) ++ { ++ /* Pointer to structure provided so check parameters */ ++ RETIF_BADPARAM(byteCnt > HDMITX_PKT_DATA_BYTE_CNT) ++ RETIF(byteCnt == 0, TMBSL_ERR_HDMI_INCONSISTENT_PARAMS) ++ ++ /* Data to change, start by clearing ISRC2 packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_FLAGS_RW, ++ E_MASKREG_P11_DIP_FLAGS_isrc2, ++ 0x00); ++ RETIF_REG_FAIL(err) ++ ++ /* Prepare ISRC2 header */ ++ buf[0] = 0x06; /* ISRC2 packet */ ++ buf[1] = 0; /* Reserved [HDMI 1.2] */ ++ buf[2] = 0; /* Reserved [HDMI 1.2] */ ++ ++ /* Write 3 header bytes to registers */ ++ err = setHwRegisters(pDis, ++ E_REG_P11_ISRC2_HB0_RW, ++ &buf[0], ++ 3); ++ RETIF_REG_FAIL(err) ++ ++ /* Write "byteCnt" bytes of data to registers */ ++ err = setHwRegisters(pDis, ++ E_REG_P11_ISRC2_PB0_RW, ++ &pPkt->dataByte[0], ++ (UInt16)byteCnt); ++ RETIF_REG_FAIL(err) ++ } ++ ++ /* Write the ISRC2 packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_FLAGS_RW, ++ E_MASKREG_P11_DIP_FLAGS_isrc2, ++ (UInt8)bEnable); ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989PktSetMpegInfoframe */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989PktSetMpegInfoframe ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPktMpeg_t *pPkt, ++ Bool bEnable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 buf[9]; /* Temp buffer to hold packet */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the ++ * sinkType is not HDMI ++ */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Only supported for device N4 or later */ ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM((bEnable != True) && (bEnable != False)) ++ ++ if(pPkt != Null) ++ { ++ /* Pointer to structure provided so check parameters */ ++ RETIF_BADPARAM((pPkt->bFieldRepeat != True) && (pPkt->bFieldRepeat != False)) ++ RETIF_BADPARAM(pPkt->frameType >= HDMITX_MPEG_FRAME_INVALID) ++ ++ /* Data to change, start by clearing MPEG packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_IF_FLAGS_RW, ++ E_MASKREG_P11_DIP_IF_FLAGS_if5, ++ 0x00); ++ RETIF_REG_FAIL(err) ++ ++ /* Prepare MPEG header */ ++ buf[0] = 0x85; /* MPEG Source InfoFrame */ ++ buf[1] = 0x01; /* Version 1 [HDMI 1.2] */ ++ buf[2] = 0x0A; /* Length [HDMI 1.2] */ ++ ++ /* Prepare MPEG packet (byte numbers offset by 3) */ ++ buf[0+3] = 0; /* Preset checksum to zero so calculation works! */ ++ buf[1+3] = (UInt8)(pPkt->bitRate & 0x000000FF); ++ buf[2+3] = (UInt8)((pPkt->bitRate & 0x0000FF00) >> 8); ++ buf[3+3] = (UInt8)((pPkt->bitRate & 0x00FF0000) >> 16); ++ buf[4+3] = (UInt8)((pPkt->bitRate & 0xFF000000) >> 24); ++ buf[5+3] = pPkt->frameType; /* MF1-0 */ ++ if(pPkt->bFieldRepeat == True) ++ { ++ buf[5+3] += 0x10; /* FR0 bit */ ++ } ++ ++ /* Calculate checksum - this is worked out on "Length" bytes of the ++ * packet, the checksum (which we've preset to zero), and the three ++ * header bytes. We exclude bytes PB6 to PB10 (which we ++ * are not writing) since they are zero. ++ */ ++ buf[0+3] = calculateChecksum(&buf[0], 0x0A+1+3-5); ++ ++ /* Write header and packet bytes in one operation */ ++ err = setHwRegisters(pDis, ++ E_REG_P10_IF5_HB0_RW, ++ &buf[0], ++ 9); ++ RETIF_REG_FAIL(err) ++ } ++ ++ /* Write the MPEG packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_IF_FLAGS_RW, ++ E_MASKREG_P11_DIP_IF_FLAGS_if5, ++ (UInt8)bEnable); ++ return err; ++} ++/*============================================================================*/ ++/* tmbslTDA9989PktSetNullInsert */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989PktSetNullInsert ++( ++ tmUnitSelect_t txUnit, ++ Bool bEnable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the ++ * sinkType is not HDMI ++ */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM((bEnable != True) && (bEnable != False)) ++ ++ /* Set or clear FORCE_NULL packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_FLAGS_RW, ++ E_MASKREG_P11_DIP_FLAGS_force_null, ++ (UInt8)bEnable); ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989PktSetNullSingle */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989PktSetNullSingle ++( ++ tmUnitSelect_t txUnit ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the ++ * sinkType is not HDMI ++ */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Set NULL packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_FLAGS_RW, ++ E_MASKREG_P11_DIP_FLAGS_null, ++ 0x01); ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989PktSetSpdInfoframe */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989PktSetSpdInfoframe ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPktSpd_t *pPkt, ++ Bool bEnable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 buf[29];/* Temp buffer to hold packet */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the ++ * sinkType is not HDMI ++ */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Only supported for device N4 or later */ ++ ++ /* Check remaining parameter(s) */ ++ RETIF_BADPARAM((bEnable != True) && (bEnable != False)) ++ ++ if(pPkt != Null) ++ { ++ /* Pointer to structure provided so check parameters */ ++ RETIF_BADPARAM(pPkt->SourceDevInfo >= HDMITX_SPD_INFO_INVALID) ++ ++ /* Data to change, start by clearing SPD packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_IF_FLAGS_RW, ++ E_MASKREG_P11_DIP_IF_FLAGS_if3, ++ 0x00); ++ RETIF_REG_FAIL(err) ++ ++ /* Prepare SPD header */ ++ buf[0] = 0x83; /* Source. Product Descriptor InfoFrame */ ++ buf[1] = 0x01; /* Version 1 [CEA 861B] */ ++ buf[2] = 0x19; /* Length [HDMI 1.2] */ ++ ++ /* Prepare SPD packet (byte numbers offset by 3) */ ++ buf[0+3] = 0; /* Preset checksum to zero so calculation works! */ ++ lmemcpy(&buf[1+3], &pPkt->VendorName[0], HDMI_TX_SPD_VENDOR_SIZE); ++ lmemcpy(&buf[1+3+HDMI_TX_SPD_VENDOR_SIZE], &pPkt->ProdDescr[0], ++ HDMI_TX_SPD_DESCR_SIZE); ++ ++ ++ buf[HDMI_TX_SPD_LENGTH+3] = pPkt->SourceDevInfo; ++ ++ /* Calculate checksum - this is worked out on "Length" bytes of the ++ * packet, the checksum (which we've preset to zero), and the three ++ * header bytes. ++ */ ++ buf[0+3] = calculateChecksum(&buf[0], HDMI_TX_SPD_LENGTH+1+3); ++ ++ /* Write header and packet bytes in one operation */ ++ err = setHwRegisters(pDis, ++ E_REG_P10_IF3_HB0_RW, ++ &buf[0], ++ 29); ++ RETIF_REG_FAIL(err) ++ } ++ ++ /* Write the SPD packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_IF_FLAGS_RW, ++ E_MASKREG_P11_DIP_IF_FLAGS_if3, ++ (UInt8)bEnable); ++ return err; ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989PktSetVideoInfoframe */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989PktSetVideoInfoframe ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPktVif_t *pPkt, ++ Bool bEnable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 buf[17];/* Temp buffer to hold header/packet bytes */ ++ UInt16 bufReg; /* Base register used for writing InfoFrame*/ ++ UInt16 flagReg;/* Flag register to be used */ ++ UInt8 flagMask;/* Mask used for writing flag register */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the ++ * sinkType is not HDMI ++ */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Check remaining parameter(s) - NULL pointer allowed */ ++ RETIF_BADPARAM((bEnable != True) && (bEnable != False)) ++ if(pPkt != Null) ++ { ++ /* Pointer to structure provided so check parameters */ ++ RETIF_BADPARAM(pPkt->Colour > 0x03) ++ RETIF_BADPARAM((pPkt->ActiveInfo != True) && (pPkt->ActiveInfo != False)) ++ RETIF_BADPARAM(pPkt->BarInfo > 0x03) ++ RETIF_BADPARAM(pPkt->ScanInfo > 0x03) ++ RETIF_BADPARAM(pPkt->Colorimetry > 0x03) ++ RETIF_BADPARAM(pPkt->PictureAspectRatio > 0x03) ++ RETIF_BADPARAM(pPkt->ActiveFormatRatio > 0x0F) ++ RETIF_BADPARAM(pPkt->Scaling > 0x03) ++ RETIF_BADPARAM(pPkt->VidFormat > 0x7F) ++ RETIF_BADPARAM(pPkt->PixelRepeat > 0x0F) ++ } ++ ++ /* Only supported for device N4 or later */ ++ ++ /* We're using n4 or later, use IF2 buffer for Video InfoFrame */ ++ bufReg = E_REG_P10_IF2_HB0_RW; ++ flagReg = E_REG_P11_DIP_IF_FLAGS_RW; ++ flagMask = E_MASKREG_P11_DIP_IF_FLAGS_if2; ++ ++ if(pPkt != Null) ++ { ++ /* Data to change, start by clearing VIF packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ flagReg, ++ flagMask, ++ 0x00); ++ RETIF_REG_FAIL(err) ++ ++ /* Prepare VIF header */ ++ buf[0] = 0x82; /* Video InfoFrame */ ++ buf[1] = 0x02; /* Version 2 [HDMI 1.2] */ ++ buf[2] = 0x0D; /* Length [HDMI 1.2] */ ++ ++ /* Prepare VIF packet (byte numbers offset by 3) */ ++ buf[0+3] = 0; /* Preset checksum to zero so calculation works! */ ++ buf[1+3] = ((pPkt->Colour & 0x03) << 5) | /* Y1-0, B1-0,S1-0 */ ++ ((pPkt->BarInfo & 0x03) << 2) | ++ (pPkt->ScanInfo & 0x03); ++ if(pPkt->ActiveInfo == True) ++ { ++ buf[1+3] += 0x10; /* AI bit */ ++ } ++ buf[2+3] = ((pPkt->Colorimetry & 0x03) << 6) | /* C1-0, M1-0, R3-0 */ ++ ((pPkt->PictureAspectRatio & 0x03) << 4) | ++ (pPkt->ActiveFormatRatio & 0x0F); ++ buf[3+3] = (pPkt->Scaling & 0x03); /* SC1-0 */ /* [HDMI 1.2] */ ++ buf[4+3] = (pPkt->VidFormat & 0x7F); /* VIC6-0 */ ++ buf[5+3] = (pPkt->PixelRepeat & 0x0F); /* PR3-0 */ ++ buf[6+3] = (UInt8)(pPkt->EndTopBarLine & 0x00FF); ++ buf[7+3] = (UInt8)((pPkt->EndTopBarLine & 0xFF00) >> 8); ++ buf[8+3] = (UInt8)(pPkt->StartBottomBarLine & 0x00FF); ++ buf[9+3] = (UInt8)((pPkt->StartBottomBarLine & 0xFF00) >> 8); ++ buf[10+3] = (UInt8)(pPkt->EndLeftBarPixel & 0x00FF); ++ buf[11+3] = (UInt8)((pPkt->EndLeftBarPixel & 0xFF00) >> 8); ++ buf[12+3] = (UInt8)(pPkt->StartRightBarPixel & 0x00FF); ++ buf[13+3] = (UInt8)((pPkt->StartRightBarPixel & 0xFF00) >> 8); ++ ++ /* Calculate checksum - this is worked out on "Length" bytes of the ++ * packet, the checksum (which we've preset to zero), and the three ++ * header bytes. ++ */ ++ buf[0+3] = calculateChecksum(&buf[0], 0x0D+1+3); ++ ++ /* Write header and packet bytes in one operation */ ++ err = setHwRegisters(pDis, ++ bufReg, ++ &buf[0], ++ 17); ++ RETIF_REG_FAIL(err) ++ } ++ ++ /* Write VIF packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ flagReg, ++ flagMask, ++ (UInt8)bEnable); ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989PktSetRawVideoInfoframe */ ++/*============================================================================*/ ++tmErrorCode_t tmbslTDA9989PktSetRawVideoInfoframe ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPktRawAvi_t *pPkt, ++ Bool bEnable ++) ++{ ++ ++ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the ++ * sinkType is not HDMI ++ */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Check remaining parameter(s) - NULL pointer allowed */ ++ RETIF_BADPARAM((bEnable != True) && (bEnable != False)) ++ ++ /* use IF2 buffer */ ++ if(pPkt != Null) ++ { ++ /* Data to change, start by clearing VIF packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_IF_FLAGS_RW, ++ E_MASKREG_P11_DIP_IF_FLAGS_if2, ++ 0x00); ++ RETIF_REG_FAIL(err) ++ ++ ++ /* Write VIF raw header bytes 0-2 */ ++ err = setHwRegisters(pDis, ++ E_REG_P10_IF2_HB0_RW, ++ pPkt->HB, ++ 3); ++ RETIF_REG_FAIL(err) ++ ++ /* Write VIF raw payload bytes 0-27 */ ++ err = setHwRegisters(pDis, ++ E_REG_P10_IF2_PB0_RW, ++ pPkt->PB, ++ 28); ++ ++ RETIF_REG_FAIL(err) ++ ++ } ++ ++ /* Write VIF packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_IF_FLAGS_RW, ++ E_MASKREG_P11_DIP_IF_FLAGS_if2, ++ (UInt8)bEnable); ++ ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989PktSetVsInfoframe */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++tmbslTDA9989PktSetVsInfoframe ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPkt_t *pPkt, ++ UInt byteCnt, ++ UInt8 uVersion, ++ Bool bEnable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 buf[31];/* Temp buffer to hold packet */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the ++ * sinkType is not HDMI ++ */ ++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI, ++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ ++ /* Only supported for device N4 or later */ ++ ++ /* Check remaining parameter(s) - NULL pointer allowed */ ++ RETIF_BADPARAM((bEnable != True) && (bEnable != False)) ++ ++ if(pPkt != Null) ++ { ++ /* Pointer to structure provided so check parameters */ ++ /* InfoFrame needs a checksum, so 1 usable byte less than full pkt */ ++ RETIF_BADPARAM(byteCnt > (HDMITX_PKT_DATA_BYTE_CNT-1)) ++ RETIF(byteCnt == 0, TMBSL_ERR_HDMI_INCONSISTENT_PARAMS) ++ ++ /* Data to change, start by clearing VS_IF packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_IF_FLAGS_RW, ++ E_MASKREG_P11_DIP_IF_FLAGS_if1, ++ 0x00); ++ RETIF_REG_FAIL(err) ++ ++ /* Prepare VS_IF header */ ++ lmemset(&buf[0], 0, 31); /* Clear buffer as user may vary length used */ ++ buf[0] = 0x81; /* Vendor Specific InfoFrame */ ++ buf[1] = uVersion; /* Vendor defined version */ ++ buf[2] = (UInt8)byteCnt; /* Length [HDMI 1.2] */ ++ ++ /* Prepare VS_IF packet (byte numbers offset by 3) */ ++ buf[0+3] = 0; /* Preset checksum to zero so calculation works! */ ++ lmemcpy(&buf[1+3], &pPkt->dataByte[0], byteCnt); ++ ++ /* Calculate checksum - this is worked out on "Length" bytes of the ++ * packet, the checksum (which we've preset to zero), and the three ++ * header bytes. ++ */ ++ buf[0+3] = calculateChecksum(&buf[0], byteCnt+1+3); ++ ++ /* Write header and packet bytes in one operation - write entire ++ * buffer even though we may not be using it all so that zeros ++ * are placed in the unused registers. */ ++ err = setHwRegisters(pDis, ++ E_REG_P10_IF1_HB0_RW, ++ &buf[0], ++ 31); ++ RETIF_REG_FAIL(err) ++ } ++ ++ /* Write the VS_IF packet insertion flag */ ++ err = setHwRegisterField(pDis, ++ E_REG_P11_DIP_IF_FLAGS_RW, ++ E_MASKREG_P11_DIP_IF_FLAGS_if1, ++ (UInt8)bEnable); ++ return err; ++} ++ ++/*============================================================================*/ ++/* STATIC FUNCTIONS */ ++/*============================================================================*/ ++ ++/*===============================================================================*/ ++/* reg_vid_fmt(): get register index for normal and 3D, plus sync table */ ++/*===============================================================================*/ ++static UInt8 reg_vid_fmt(tmbslHdmiTxVidFmt_t fmt, \ ++ tmbslHdmiTx3DStructure_t structure3D, \ ++ UInt8 *idx, \ ++ UInt8 *idx3d, \ ++ struct sync_desc **sync) ++{ ++ struct vic2reg *hash; ++ int i; ++ ++ (*idx)=REGVFMT_INVALID; ++ if (idx3d) (*idx3d)=REGVFMT_INVALID; ++ if (IS_TV(fmt)) { ++ VIC2REG_LOOP(vic2reg_TV,idx); ++ if (idx3d) { ++ if (structure3D == HDMITX_3D_FRAME_PACKING) { ++ /* any 3D FP prefetch ? */ ++ VIC2REG_LOOP(vic2reg_TV_FP,idx3d); ++ } ++ } ++ } ++#ifdef FORMAT_PC ++ else { ++ VIC2REG_LOOP(vic2reg_PC,idx); ++ } ++#endif ++ /* PR1570 FIXED */ ++ if (sync) { ++ if PREFETCH(*idx) { ++ *sync = (struct sync_desc *)ref_sync; ++ } ++#ifdef FORMAT_PC ++ else if PCFORMAT(*idx) { ++ *sync = (struct sync_desc *)ref_sync_PC; ++ *idx = *idx - E_REGVFMT_MAX_EXTRA; ++ } ++#endif //FORMAT_PC ++ else { ++ *sync = (struct sync_desc *)ref_sync_extra; ++ } ++ } ++ return ((*idx)==REGVFMT_INVALID); ++} ++ ++/*===============================================================================*/ ++/* pix_clk(): get pixel clock */ ++/*===============================================================================*/ ++UInt8 pix_clk(tmbslHdmiTxVidFmt_t fmt, tmbslHdmiTxVfreq_t freq, UInt8 *pclk) ++{ ++ ++ (*pclk)=REGVFMT_INVALID; ++#ifdef FORMAT_PC ++ if (IS_PC(fmt)) { ++ (*pclk)=kVfmtToPixClk_PC[fmt - HDMITX_VFMT_PC_MIN]; ++ } ++#endif ++ if (IS_TV(fmt)) { ++ (*pclk)=kVfmtToPixClk_TV[fmt - HDMITX_VFMT_TV_MIN][freq]; ++ } ++ return ((*pclk)==REGVFMT_INVALID); ++} ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++EXPORT_SYMBOL(pix_clk); ++#endif ++ ++/*===============================================================================*/ ++/* calculateVidFmtIndex(): Calculate table index according to video format value */ ++/*===============================================================================*/ ++tmbslHdmiTxVidFmt_t calculateVidFmtIndex(tmbslHdmiTxVidFmt_t vidFmt) ++{ ++ tmbslHdmiTxVidFmt_t vidFmtIndex = vidFmt; ++ ++ /* Hanlde VIC or table index discontinuity */ ++ if((vidFmt >= HDMITX_VFMT_60_1280x720p_24Hz) && (vidFmt <= HDMITX_VFMT_62_1280x720p_30Hz)) ++ { ++ vidFmtIndex = (tmbslHdmiTxVidFmt_t)(HDMITX_VFMT_INDEX_60_1280x720p_24Hz + (vidFmt - HDMITX_VFMT_60_1280x720p_24Hz)); ++ } ++#ifdef FORMAT_PC ++ else if (IS_PC(vidFmt)) ++ { ++ vidFmtIndex = (tmbslHdmiTxVidFmt_t)(HDMITX_VFMT_TV_NUM + (vidFmt - HDMITX_VFMT_PC_MIN)); ++ } ++#endif /* FORMAT_PC */ ++ return(vidFmtIndex); ++} ++ ++/*============================================================================*/ ++/* setDeVs */ ++/*============================================================================*/ ++static tmErrorCode_t ++setDeVs ++( ++ tmHdmiTxobject_t *pDis, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ tmbslHdmiTx3DStructure_t structure3D ++) ++{ ++ tmErrorCode_t err; /* Error code */ ++ UInt16 vsPixStrt2; /* VS pixel number for start pulse in field 2 */ ++ UInt8 reg_idx; /* Video format value used for register */ ++ struct sync_desc *sync; ++ ++ /* IF voutFmt = No Change THEN return TM_OK */ ++ RETIF(voutFmt == HDMITX_VFMT_NO_CHANGE, TM_OK); ++ ++ /* Quit if the output format does not map to the register format */ ++ RETIF_BADPARAM(reg_vid_fmt(voutFmt,structure3D,®_idx,0,&sync)); ++ ++ /* DE_START & DE_STOP no longer set because N2 device no longer supported */ ++ ++ /* Adjust VS_PIX_STRT_2 and VS_PIX_END_2 for interlaced output formats */ ++ vsPixStrt2 = sync[BASE(reg_idx)].Vs2; ++ err = setHwRegisterMsbLsb(pDis, E_REG_P00_VS_PIX_STRT_2_MSB_W, vsPixStrt2); ++ RETIF_REG_FAIL(err) ++ err = setHwRegisterMsbLsb(pDis, E_REG_P00_VS_PIX_END_2_MSB_W, vsPixStrt2); ++/* printk("DBG %s vs2:%d\n",__func__,vsPixStrt2); */ ++ ++ return err; ++} ++ ++/*============================================================================*/ ++/* setPixelRepeat */ ++/*============================================================================*/ ++static tmErrorCode_t ++setPixelRepeat ++( ++ tmHdmiTxobject_t *pDis, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ UInt8 uPixelRepeat, ++ tmbslHdmiTx3DStructure_t structure3D ++) ++{ ++ tmErrorCode_t err = TM_OK; /* Error code */ ++ ++ RETIF(voutFmt == HDMITX_VFMT_NO_CHANGE, TM_OK) ++ ++ err = InputConfig(pDis, ++ HDMITX_VINMODE_NO_CHANGE, ++ HDMITX_PIXEDGE_NO_CHANGE, ++ HDMITX_PIXRATE_NO_CHANGE, ++ HDMITX_UPSAMPLE_NO_CHANGE, ++ uPixelRepeat, ++ voutFmt, ++ structure3D); ++ ++ return err; ++} ++/*============================================================================*/ ++/* setSampling */ ++/*============================================================================*/ ++static tmErrorCode_t ++setSampling ++( ++ tmHdmiTxobject_t *pDis ++) ++{ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 upSample; /* 1 if upsampler must be enabled */ ++ UInt8 downSample; /* 1 if downsampler must be enabled */ ++ UInt8 matrixBypass; /*>0 if matrix has been bypassed */ ++ ++ if ((pDis->vinMode == HDMITX_VINMODE_YUV422) ++ || (pDis->vinMode == HDMITX_VINMODE_CCIR656)) ++ { ++ if (pDis->voutMode == HDMITX_VOUTMODE_YUV422) ++ { ++ /* Input 422/656, output 422 */ ++ err = getHwRegister(pDis, E_REG_P00_MAT_CONTRL_W, &matrixBypass); ++ RETIF_REG_FAIL(err) ++ matrixBypass &= E_MASKREG_P00_MAT_CONTRL_mat_bp; ++ /* Has matrix been bypassed? */ ++ if (matrixBypass > 0) ++ { ++ upSample = 0; ++ downSample = 0; ++ } ++ else ++ { ++ upSample = 1; ++ downSample = 1; ++ } ++ } ++ else ++ { ++ /* Input 422/656, output not 422 */ ++ upSample = 1; ++ downSample = 0; ++ } ++ } ++ else ++ { ++ if (pDis->voutMode == HDMITX_VOUTMODE_YUV422) ++ { ++ /* Input not 422/656, output 422 */ ++ upSample = 0; ++ downSample = 1; ++ } ++ else ++ { ++ /* Input not 422/656, output not 422 */ ++ upSample = 0; ++ downSample = 0; ++ } ++ } ++ ++ /* Check upsample mode saved by tmbslTDA9989VideoInSetConfig */ ++ if (pDis->upsampleMode != HDMITX_UPSAMPLE_AUTO) ++ { ++ /* Saved upsample mode overrides local one */ ++ upSample = pDis->upsampleMode; ++ } ++ ++ /* Set upsampler */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_HVF_CNTRL_0_W, ++ E_MASKREG_P00_HVF_CNTRL_0_intpol, ++ upSample); ++ RETIF_REG_FAIL(err) ++ ++ /* Set downsampler */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_HVF_CNTRL_1_W, ++ E_MASKREG_P00_HVF_CNTRL_1_for, ++ downSample); ++ return err; ++} ++ ++ ++/*============================================================================*/ ++/* calculateChecksum - returns the byte needed to yield a checksum of zero */ ++/*============================================================================*/ ++static UInt8 ++calculateChecksum ++( ++ UInt8 *pData, /* Pointer to checksum data */ ++ Int numBytes /* Number of bytes over which to calculate */ ++ ) ++{ ++ UInt8 checksum = 0; /* Working checksum calculation */ ++ UInt8 result = 0; /* Value to be returned */ ++ Int i; ++ ++ if((pData != Null) && (numBytes > 0)) ++ { ++ for (i = 0; i < numBytes; i++) ++ { ++ checksum = checksum + (*(pData + i)); ++ } ++ result = (255 - checksum) + 1; ++ } ++ return result; /* returns 0 in the case of null ptr or 0 bytes */ ++} ++ ++/*============================================================================*/ ++/* InputConfig */ ++/*============================================================================*/ ++static tmErrorCode_t ++InputConfig ++( ++ tmHdmiTxobject_t *pDis, ++ tmbslHdmiTxVinMode_t vinMode, ++ tmbslHdmiTxPixEdge_t sampleEdge, ++ tmbslHdmiTxPixRate_t pixRate, ++ tmbslHdmiTxUpsampleMode_t upsampleMode, ++ UInt8 uPixelRepeat, ++ tmbslHdmiTxVidFmt_t voutFmt, ++ tmbslHdmiTx3DStructure_t structure3D ++) ++{ ++ tmErrorCode_t err = TM_OK; /* Error code */ ++ UInt8 reg_idx,reg_idx3D; /* Video format value used for register */ ++ UInt8 ssd=0; /* Packed srl, scg and de */ ++ struct sync_desc *sync; ++ ++ /****************Check Parameters********************/ ++ /* Check parameters */ ++ RETIF_BADPARAM(vinMode >= HDMITX_VINMODE_INVALID); ++ RETIF_BADPARAM(sampleEdge >= HDMITX_PIXEDGE_INVALID); ++ RETIF_BADPARAM(pixRate >= HDMITX_PIXRATE_INVALID); ++ RETIF_BADPARAM(upsampleMode >= HDMITX_UPSAMPLE_INVALID); ++ ++ RETIF(voutFmt == HDMITX_VFMT_NO_CHANGE, TM_OK); ++ RETIF_BADPARAM(!IS_VALID_FMT(voutFmt)); ++ ++ /* Quit if the output format does not map to the register format */ ++ RETIF_BADPARAM(reg_vid_fmt(voutFmt,structure3D,®_idx,®_idx3D,&sync)); ++ ++/****************Set the VinMode************************ ++- P00_VIP_CNTRL_4_ccir656 ++- P00_HVF_CNTRL_1_semi_planar ++- P02_PLL_SERIAL_3_srl_ccir ++- P02_SEL_CLK_sel_vrf_clk ++*/ ++ if (vinMode != HDMITX_VINMODE_NO_CHANGE) ++ { ++ pDis->vinMode = vinMode; ++ } ++/****************Set the sampleEdge*********************** ++-P00_VIP_CNTRL_3_edge*/ ++ ++ if (sampleEdge != HDMITX_PIXEDGE_NO_CHANGE) ++ { ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_3_W, ++ E_MASKREG_P00_VIP_CNTRL_3_edge, ++ (UInt8)sampleEdge); ++ RETIF_REG_FAIL(err) ++ } ++ ++/****************Set the Pixel Rate*********************** ++-P02_CCIR_DIV_refdiv2 ++-P02_P02_PLL_SCG2_selpllclkin ++-P02_P02_PLL_DE_bypass_pllde ++-P00_VIP_CNTRL_4_656_alt */ ++ ++ if (pixRate != HDMITX_PIXRATE_NO_CHANGE) ++ { ++ pDis->pixRate = pixRate; ++ } ++ ++ if ((pixRate != HDMITX_PIXRATE_NO_CHANGE)||(vinMode != HDMITX_VINMODE_NO_CHANGE)) ++ { ++ switch (pDis->vinMode) ++ { ++ case HDMITX_VINMODE_RGB444: ++ case HDMITX_VINMODE_YUV444: ++ ++ if (pDis->pixRate == HDMITX_PIXRATE_SINGLE) ++ { ++ err = setHwRegisterFieldTable(pDis, &kVinMode444[0]); ++ ++ RETIF_REG_FAIL(err) ++ ++ ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_4_W, ++ E_MASKREG_P00_VIP_CNTRL_4_656_alt, ++ 0); ++ RETIF_REG_FAIL(err) ++ ++ } ++ else if (pDis->pixRate == HDMITX_PIXRATE_SINGLE_REPEATED) ++ { ++ err = setHwRegisterFieldTable(pDis, &kVinMode444[0]); ++ ++ RETIF_REG_FAIL(err) ++ ++ ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_4_W, ++ E_MASKREG_P00_VIP_CNTRL_4_656_alt, ++ 0); ++ RETIF_REG_FAIL(err) ++ ++ } ++ else ++ { ++ /* Not supported*/ ++ } ++ break; ++ case HDMITX_VINMODE_YUV422: ++ if (pDis->pixRate == HDMITX_PIXRATE_SINGLE) ++ { ++ err = setHwRegisterFieldTable(pDis, &kVinModeYUV422[0]); ++ ++ RETIF_REG_FAIL(err) ++ ++ ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_4_W, ++ E_MASKREG_P00_VIP_CNTRL_4_656_alt, ++ 0); ++ RETIF_REG_FAIL(err) ++ ++ } ++ else if (pDis->pixRate == HDMITX_PIXRATE_SINGLE_REPEATED) ++ { ++ err = setHwRegisterFieldTable(pDis, &kVinModeYUV422[0]); ++ ++ RETIF_REG_FAIL(err) ++ ++ ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_4_W, ++ E_MASKREG_P00_VIP_CNTRL_4_656_alt, ++ 0); ++ RETIF_REG_FAIL(err) ++ ++ } ++ else ++ { ++ /* Not supported*/ ++ return TMBSL_ERR_HDMI_BAD_PARAMETER; ++ } ++ break; ++ case HDMITX_VINMODE_CCIR656: ++ if(pDis->pixRate == HDMITX_PIXRATE_SINGLE) ++ { ++ ++ err = setHwRegisterFieldTable(pDis, &kVinModeCCIR656[0]); ++ ++ RETIF_REG_FAIL(err) ++ ++ ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_4_W, ++ E_MASKREG_P00_VIP_CNTRL_4_656_alt, ++ 0); ++ RETIF_REG_FAIL(err) ++ ++ } ++ else if (pDis->pixRate == HDMITX_PIXRATE_SINGLE_REPEATED) ++ { ++ err = setHwRegisterFieldTable(pDis, &kVinModeCCIR656[0]); ++ ++ RETIF_REG_FAIL(err) ++ ++ ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_4_W, ++ E_MASKREG_P00_VIP_CNTRL_4_656_alt, ++ 0); ++ RETIF_REG_FAIL(err) ++ ++ } ++ else if (pDis->pixRate == HDMITX_PIXRATE_DOUBLE) ++ { ++ err = setHwRegisterFieldTable(pDis, &kVinModeCCIR656_DDR_above720p[0]); ++ ++ RETIF_REG_FAIL(err) ++ ++ ++ ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_VIP_CNTRL_4_W, ++ E_MASKREG_P00_VIP_CNTRL_4_656_alt, ++ 1); ++ RETIF_REG_FAIL(err) ++ ++ } ++ break; ++ default: ++ err = setHwRegisterFieldTable(pDis, &kVinMode444[0]); ++ ++ RETIF_REG_FAIL(err) ++ break; ++ } ++ ++ } ++ /****************Update the Sample Mode***********************/ ++ ++ if (upsampleMode != HDMITX_UPSAMPLE_NO_CHANGE) { ++ pDis->upsampleMode = upsampleMode; ++ } ++ ++/****************Set the Pixel repeat PLL Value *********************** ++- P02_PLL_SERIAL_2_srl_nosc ++- P02_PLL_DE_pllde_nosc */ ++ ++ if ((structure3D == HDMITX_3D_FRAME_PACKING) && \ ++ (reg_idx3D != REGVFMT_INVALID)) { ++ /* embedded 3D video format */ ++ ssd = pll[reg_idx3D]; ++ } ++ else { ++ /* embedded 2D video format */ ++ ssd = pll[reg_idx]; ++ } ++ ++ if ( ssd < SSD_UNUSED_VALUE) { ++ err = setHwRegisterField(pDis, E_REG_P02_PLL_SERIAL_2_RW, ++ E_MASKREG_P02_PLL_SERIAL_2_srl_nosc, ++ ssd); ++/* printk("DBG nosc:%d\n",ssd); */ ++ } ++ ++/*****************Set the Pixel Repetition*********************** ++- P02_PLL_SERIAL_2_srl_pr*/ ++ ++ /* Set pixel repetition */ ++ if (uPixelRepeat != HDMITX_PIXREP_NO_CHANGE) ++ { ++ if (uPixelRepeat == HDMITX_PIXREP_DEFAULT) ++ { ++ /* Look up default pixel repeat value for this output format */ ++ uPixelRepeat = sync[BASE(reg_idx)].pix_rep; ++ } ++ ++ /* Update current pixel repetition count */ ++ pDis->pixelRepeatCount = uPixelRepeat; ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P02_PLL_SERIAL_2_RW, ++ E_MASKREG_P02_PLL_SERIAL_2_srl_pr, ++ uPixelRepeat); ++ RETIF_REG_FAIL(err) ++ /* Set pixel repetition count for Repetitor module */ ++ err = setHwRegister(pDis, E_REG_P00_RPT_CNTRL_W, uPixelRepeat); ++ } ++ ++/*******************Fixe other settings********************* ++- P02_PLL_SERIAL_1_srl_man_iz = 0 ++- P02_PLL_SERIAL_3_srl_de = 0 ++- Pol Clk Sel = P02_SERIALIZER_RW = 0 ++- P02_BUFFER_OUT_srl_force = 0 ++- P02_BUFFER_OUT_srl_clk = 0 ++- P02_PLL_DE_pllde_iz = 0 ++*/ ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P02_PLL_SERIAL_1_RW, ++ E_MASKREG_P02_PLL_SERIAL_1_srl_man_iz, ++ 0); ++ ++ ++RETIF_REG_FAIL(err) ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P02_PLL_SERIAL_3_RW, ++ E_MASKREG_P02_PLL_SERIAL_3_srl_de, ++ 0); ++RETIF_REG_FAIL(err) ++ ++err = setHwRegister(pDis, E_REG_P02_SERIALIZER_RW, 0); ++RETIF_REG_FAIL(err) ++ ++return err; ++} ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ ++ +diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_InOut_l.h b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_InOut_l.h +new file mode 100755 +index 0000000..343e41b +--- /dev/null ++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_InOut_l.h +@@ -0,0 +1,112 @@ ++/** ++ * Copyright (C) 2009 Koninklijke Philips Electronics N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of Koninklijke Philips Electronics N.V. and is confidential in ++ * nature. Under no circumstances is this software to be exposed to or placed ++ * under an Open Source License of any type without the expressed written ++ * permission of Koninklijke Philips Electronics N.V. ++ * ++ * \file tmbslTDA9989_InOut_l.h ++ * ++ * \version $Revision: 2 $ ++ * ++ * ++*/ ++ ++#ifndef TMBSLTDA9989_INOUT_L_H ++#define TMBSLTDA9989_INOUT_L_H ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*============================================================================*/ ++/* MACRO DEFINITIONS */ ++/*============================================================================*/ ++ ++#define IS_TV(fmt) (fmt >= HDMITX_VFMT_TV_MIN && fmt <= HDMITX_VFMT_TV_MAX) ++#define IS_VALID_FMT(fmt) IS_TV(fmt) ++#ifdef FORMAT_PC ++#define IS_PC(fmt) (fmt >= HDMITX_VFMT_PC_MIN && fmt <= HDMITX_VFMT_PC_MAX) ++#define IS_VALID_FMT(fmt) (IS_TV(fmt)||IS_PC(fmt)) ++#endif ++#define VIC2REG_LOOP(array,idx) do { \ ++ hash=(struct vic2reg *)(array); \ ++ for (i=0;i<(sizeof(array)/sizeof(struct vic2reg));i++) { \ ++ if (hash[i].vic==fmt) { \ ++ (*idx)=hash[i].reg; \ ++ break; \ ++ } \ ++ } \ ++} while (0); ++ ++/*============================================================================*/ ++/* ENUM OR TYPE DEFINITIONS */ ++/*============================================================================*/ ++ ++typedef struct ++{ ++ UInt16 Register; ++ UInt8 MaskSwap; ++ UInt8 MaskMirror; ++} tmbslTDA9989RegVip; ++ ++/*============================================================================*/ ++/* EXTERN DATA DEFINITION */ ++/*============================================================================*/ ++ ++extern CONST_DAT tmHdmiTxRegMaskVal_t kCommonPllCfg[]; ++ ++/** ++ * Table of PLL settings registers to configure for 480i and 576i vinFmt ++ */ ++extern CONST_DAT tmHdmiTxRegMaskVal_t kVfmt480i576iPllCfg[]; ++ ++/** ++ * Table of PLL settings registers to configure for single mode pixel rate, ++ * vinFmt 480i or 576i only ++ */ ++extern CONST_DAT tmHdmiTxRegMaskVal_t kSinglePrateVfmt480i576iPllCfg[]; ++ ++/** ++ * Table of PLL settings registers to configure for single repeated mode pixel rate, ++ * vinFmt 480i or 576i only ++ */ ++extern CONST_DAT tmHdmiTxRegMaskVal_t kSrepeatedPrateVfmt480i576iPllCfg[]; ++ ++/** ++ * Table of PLL settings registers to configure for other vinFmt than 480i and 576i ++ */ ++extern CONST_DAT tmHdmiTxRegMaskVal_t kVfmtOtherPllCfg[]; ++ ++/** ++ * Table of PLL settings registers to configure single mode pixel rate, ++ * vinFmt other than 480i or 576i ++ */ ++extern CONST_DAT tmHdmiTxRegMaskVal_t kSinglePrateVfmtOtherPllCfg[]; ++ ++/** ++ * Table of PLL settings registers to configure double mode pixel rate, ++ * vinFmt other than 480i or 576i ++ */ ++extern CONST_DAT tmHdmiTxRegMaskVal_t kDoublePrateVfmtOtherPllCfg[]; ++ ++ ++/*============================================================================*/ ++/* EXTERN FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++extern tmbslHdmiTxVidFmt_t calculateVidFmtIndex(tmbslHdmiTxVidFmt_t vidFmt); ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMBSLTDA9989_INOUT_L_H */ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc.c b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc.c +new file mode 100755 +index 0000000..d45cc25 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc.c +@@ -0,0 +1,2512 @@ ++/** ++ * Copyright (C) 2009 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmbslTDA9989_misc.c ++ * ++ * \version %version: 3 % ++ * ++ * ++*/ ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++#include ++#endif ++#include "tmbslHdmiTx_types.h" ++#include "tmbslTDA9989_Functions.h" ++#include "tmbslTDA9989_local.h" ++#include "tmbslTDA9989_HDCP_l.h" ++#include "tmbslTDA9989_State_l.h" ++#include "tmbslTDA9989_InOut_l.h" ++#include "tmbslTDA9989_Edid_l.h" ++#include "tmbslTDA9989_Misc_l.h" ++ ++/*============================================================================*/ ++/* TYPES DECLARATIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* CONSTANTS DECLARATIONS EXPORTED */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* CONSTANTS DECLARATIONS */ ++/*============================================================================*/ ++ ++/** Preset default values for an object instance */ ++static CONST_DAT tmHdmiTxobject_t kHdmiTxInstanceDefault ++= ++{ ++ ST_UNINITIALIZED, /* state */ ++ 0, /* nIgnoredEvents */ ++ tmUnit0, /* txUnit */ ++ 0, /* uHwAddress */ ++ (ptmbslHdmiTxSysFunc_t)0, /* sysFuncWrite */ ++ (ptmbslHdmiTxSysFunc_t)0, /* sysFuncRead */ ++ (ptmbslHdmiTxSysFuncEdid_t)0, /* sysFuncEdidRead */ ++ (ptmbslHdmiTxSysFuncTimer_t)0, /* sysFuncTimer */ ++ { /* funcIntCallbacks[] */ ++ (ptmbslHdmiTxCallback_t)0 ++ }, ++ 0, /* InterruptsEnable */ ++ { /* uSupportedVersions[] */ ++ E_DEV_VERSION_N2, ++ E_DEV_VERSION_TDA19989, ++ E_DEV_VERSION_TDA19989_N2, ++ E_DEV_VERSION_TDA19988, ++ E_DEV_VERSION_LIST_END ++ }, ++ E_DEV_VERSION_LIST_END, /* uDeviceVersion */ ++ E_DEV_VERSION_LIST_END, /* uDeviceFeatures */ ++ (tmbslHdmiTxPowerState_t)tmPowerOff, /* ePowerState */ ++ False, /* EdidAlternateAddr */ ++ HDMITX_SINK_DVI, /* sinkType */ ++ HDMITX_SINK_DVI, /* EdidSinkType */ ++ False, /* EdidSinkAi */ ++ 0, /* EdidCeaFlags */ ++ ++ 0, /* EdidCeaXVYCCFlags */ ++ { ++ False, /* latency_available */ ++ False, /* Ilatency_available */ ++ 0, /* Edidvideo_latency */ ++ 0, /* Edidaudio_latency */ ++ 0, /* EdidIvideo_latency */ ++ 0}, /* EdidIaudio_latency */ ++ ++ { ++ 0, /* maximum supported TMDS clock */ ++ 0, /* content type Graphics (text) */ ++ 0, /* content type Photo */ ++ 0, /* content type Cinema */ ++ 0, /* content type Game */ ++ 0, /* additional video format */ ++ 0, /* 3D support by the HDMI Sink */ ++ 0, /* 3D multi strctures present */ ++ 0, /* additional info for the values in the image size area */ ++ 0, /* total length of 3D video formats */ ++ 0, /* total length of extended video formats */ ++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} /* max_len-10, ie: 31-10=21 */ ++ }, ++ ++ HDMITX_EDID_NOT_READ, /* EdidStatus */ ++ 0, /* NbDTDStored */ ++ { /* EdidDTD: */ /* * NUMBER_DTD_STORED */ ++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*1 */ ++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*2 */ ++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*3 */ ++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*4 */ ++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*5 */ ++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*6 */ ++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*7 */ ++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*8 */ ++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*9 */ ++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0} /*10*/ ++ }, ++ { /* EdidMonitorDescriptor */ ++ False, /* bDescRecord */ ++ {0,0,0,0,0,0,0,0,0,0,0,0,0} /* uMonitorName[EDID_MONITOR_DESCRIPTOR_SIZE] */ ++ }, ++ { ++ False, /* bDescRecord */ ++ 0, /* uMinVerticalRate */ ++ 0, /* uMaxVerticalRate */ ++ 0, /* uMinHorizontalRate */ ++ 0, /* uMaxHorizontalRate */ ++ 0 /* uMaxSupportedPixelClk */ ++ }, ++ { ++ False, /* bDescRecord */ ++ {0,0,0,0,0,0,0,0,0,0,0,0,0} /* uOtherDescriptor[EDID_MONITOR_DESCRIPTOR_SIZE] */ ++ }, ++ { /* EdidVFmts[] */ ++ HDMITX_VFMT_NULL ++ }, ++ 0, /* EdidSvdCnt */ ++ { /* EdidAFmts[]. */ ++ {0,0,0} /* {ModeChans, Freqs, Byte3} */ ++ }, ++ 0, /* EdidSadCnt */ ++ { ++ 0 /* EdidBlock[ ] */ ++ }, ++ 0, /* EdidBlockCnt */ ++ 0, /* EdidSourceAddress */ ++ 0, /* EdidBlockRequested */ ++ False, /* EdidReadStarted */ ++ { /* EdidToApp */ ++ 0, /* pRawEdid */ ++ 0 /* numBlocks */ ++ }, ++ { /* EDIDBasicDisplayParam */ ++ 0, /* uVideoInputDef */ ++ 0, /* uMaxHorizontalSize */ ++ 0, /* uMaxVerticalSize */ ++ 0, /* uGamma */ ++ 0, /* uFeatureSupport */ ++ }, ++#ifdef TMFL_HDCP_SUPPORT ++ False, /* HDCPIgnoreEncrypt */ ++ 0, /* HdcpPortAddress */ ++ HDMITX_HDCP_TXMODE_NOT_SET, /* HdcpTxMode */ ++ HDMITX_HDCP_OPTION_DEFAULT, /* HdcpOptions */ ++ 0, /* HdcpBcaps */ ++ 0, /* HdcpBstatus */ ++ 0, /* HdcpRi */ ++ 0, /* HdcpFsmState */ ++ 0, /* HdcpT0FailState */ ++ 0, /* HdcpSeed */ ++ {0, 0, 0, 0, 0}, /* HdcpAksv */ ++ (ptmHdmiTxFunc_t)0, /* HdcpFuncScheduled */ ++ 0, /* HdcpFuncRemainingMs */ ++ 0, /* HdcpCheckIntervalMs */ ++ 0, /* HdcpCheckRemainingMs */ ++ 0, /* HdcpCheckNum */ ++ 0, /* HdcpChecksToDo */ ++#endif /* TMFL_HDCP_SUPPORT */ ++ HDMITX_VFMT_NULL, /* vinFmt */ ++ HDMITX_VFMT_NULL, /* voutFmt */ ++ HDMITX_PIXRATE_DOUBLE, /* pixRate */ ++ HDMITX_VINMODE_RGB444, /* vinMode */ ++ HDMITX_VOUTMODE_RGB444, /* voutMode */ ++ HDMITX_VFREQ_INVALID, /* voutFreq */ ++ HDMITX_SCAMODE_OFF, /* scaMode */ ++ HDMITX_UPSAMPLE_AUTO, /* upsampleMode */ ++ HDMITX_PIXREP_MIN, /* pixelRepeatCount */ ++ HDMITX_HOTPLUG_INVALID, /* hotPlugStatus */ ++ HDMITX_RX_SENSE_INVALID, /* rxSenseStatus */ ++ E_PAGE_INVALID, /* curRegPage */ ++ { ++ /* These match power-up defaults. shadowReg[]: */ ++ 0x00, /* E_SP00_INT_FLAGS_0 */ ++ 0x00, /* E_SP00_INT_FLAGS_1 */ ++ 0x00, /* E_SP00_INT_FLAGS_2 */ ++ 0x01, /* E_SP00_VIP_CNTRL_0 */ ++ 0x24, /* E_SP00_VIP_CNTRL_1 */ ++ 0x56, /* E_SP00_VIP_CNTRL_2 */ ++ 0x17, /* E_SP00_VIP_CNTRL_3 */ ++ 0x01, /* E_SP00_VIP_CNTRL_4 */ ++ 0x00, /* E_SP00_VIP_CNTRL_5 */ ++ 0x05, /* E_SP00_MAT_CONTRL */ ++ 0x00, /* E_SP00_TBG_CNTRL_0 */ ++ 0x00, /* E_SP00_TBG_CNTRL_1 */ ++ 0x00, /* E_SP00_HVF_CNTRL_0 */ ++ 0x00, /* E_SP00_HVF_CNTRL_1 */ ++ 0x00, /* E_SP00_TIMER_H */ ++ 0x00, /* E_SP00_DEBUG_PROBE */ ++ 0x00 /* E_SP00_AIP_CLKSEL */ ++ ,0x00 /* E_SP01_SC_VIDFORMAT*/ ++ ,0x00 /* E_SP01_SC_CNTRL */ ++ ,0x00 /* E_SP01_TBG_CNTRL_0 */ ++#ifdef TMFL_HDCP_SUPPORT ++ ,0x00 /* E_SP12_CTRL */ ++ ,0x00 /* E_SP12_BCAPS */ ++#endif /* TMFL_HDCP_SUPPORT */ ++ }, ++ False, /* Init prevFilterPattern to false */ ++ False, /* Init prevPattern to false */ ++ False, /* bInitialized */ ++ HDMITX_VQR_DEFAULT ++}; ++ ++ ++/** ++ * Table of shadow registers, as packed Shad/Page/Addr codes. ++ * This allows shadow index values to be searched for using register page ++ * and address values. ++ */ ++static CONST_DAT UInt16 kShadowReg[E_SNUM] = ++{/* Shadow Index Packed Shad/Page/Addr */ ++ E_REG_P00_INT_FLAGS_0_RW, /* E_SP00_INT_FLAGS_0 */ ++ E_REG_P00_INT_FLAGS_1_RW, /* E_SP00_INT_FLAGS_1 */ ++ E_REG_P00_INT_FLAGS_2_RW, /* E_SP00_INT_FLAGS_2 */ ++ E_REG_P00_VIP_CNTRL_0_W , /* E_SP00_VIP_CNTRL_0 */ ++ E_REG_P00_VIP_CNTRL_1_W , /* E_SP00_VIP_CNTRL_1 */ ++ E_REG_P00_VIP_CNTRL_2_W , /* E_SP00_VIP_CNTRL_2 */ ++ E_REG_P00_VIP_CNTRL_3_W , /* E_SP00_VIP_CNTRL_3 */ ++ E_REG_P00_VIP_CNTRL_4_W , /* E_SP00_VIP_CNTRL_4 */ ++ E_REG_P00_VIP_CNTRL_5_W , /* E_SP00_VIP_CNTRL_5 */ ++ E_REG_P00_MAT_CONTRL_W , /* E_SP00_MAT_CONTRL */ ++ E_REG_P00_TBG_CNTRL_0_W , /* E_SP00_TBG_CNTRL_0 */ ++ E_REG_P00_TBG_CNTRL_1_W , /* E_SP00_TBG_CNTRL_1 */ ++ E_REG_P00_HVF_CNTRL_0_W , /* E_SP00_HVF_CNTRL_0 */ ++ E_REG_P00_HVF_CNTRL_1_W , /* E_SP00_HVF_CNTRL_1 */ ++ E_REG_P00_TIMER_H_W , /* E_SP00_TIMER_H */ ++ E_REG_P00_DEBUG_PROBE_W , /* E_SP00_DEBUG_PROBE */ ++ E_REG_P00_AIP_CLKSEL_W, /* E_SP00_AIP_CLKSEL */ ++ E_REG_P01_SC_VIDFORMAT_W, /* E_SP01_SC_VIDFORMAT */ ++ E_REG_P01_SC_CNTRL_W, /* E_SP01_SC_CNTRL */ ++ E_REG_P01_TBG_CNTRL_0_W /* E_SP01_TBG_CNTRL_0 */ ++#ifdef TMFL_HDCP_SUPPORT ++ ,E_REG_P12_CTRL_W /* E_SP12_CTRL */ ++ ,E_REG_P12_BCAPS_W /* E_SP12_BCAPS */ ++#endif /* TMFL_HDCP_SUPPORT */ ++}; ++ ++ ++/** ++ * Table of registers to switch to low power (standby) ++ ++static CONST_DAT tmHdmiTxRegMaskVal_t kPowerOff[] = ++{ ++ {E_REG_P02_TEST2_RW, E_MASKREG_P02_TEST2_pwd1v8, 1}, ++ {E_REG_P02_PLL_SCG1_RW, E_MASKREG_P02_PLL_SCG1_scg_fdn, 1}, ++ {E_REG_P02_PLL_SERIAL_1_RW, E_MASKREG_P02_PLL_SERIAL_1_srl_fdn, 1}, ++ {E_REG_P02_PLL_DE_RW, E_MASKREG_P02_PLL_DE_pllde_fdn, 1}, ++ {E_REG_P02_BUFFER_OUT_RW, E_MASKREG_P02_BUFFER_OUT_srl_force, 2}, ++ {E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_ena_sc_clk, 0}, ++ {E_REG_P00_CCLK_ON_RW, E_MASKREG_P00_CCLK_ON_cclk_on, 0}, ++ {0,0,0} ++}; ++*/ ++/** ++ * Table of registers to switch to normal power (resume) ++ ++static CONST_DAT tmHdmiTxRegMaskVal_t kPowerOn[] = ++{ ++ {E_REG_P02_TEST2_RW, E_MASKREG_P02_TEST2_pwd1v8, 0}, ++ {E_REG_P02_PLL_SERIAL_1_RW, E_MASKREG_P02_PLL_SERIAL_1_srl_fdn, 0}, ++ {E_REG_P02_PLL_DE_RW, E_MASKREG_P02_PLL_DE_pllde_fdn, 0}, ++ {E_REG_P02_PLL_SCG1_RW, E_MASKREG_P02_PLL_SCG1_scg_fdn, 0}, ++ {E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_ena_sc_clk, 1}, ++ {E_REG_P02_BUFFER_OUT_RW, E_MASKREG_P02_BUFFER_OUT_srl_force, 0}, ++ {E_REG_P00_TBG_CNTRL_0_W, E_MASKREG_P00_TBG_CNTRL_0_sync_once,0}, ++ {E_REG_P00_CCLK_ON_RW, E_MASKREG_P00_CCLK_ON_cclk_on, 1}, ++ {0,0,0} ++}; ++*/ ++ ++static CONST_DAT tmbslHdmiTxCallbackInt_t kITCallbackPriority[HDMITX_CALLBACK_INT_NUM] = ++{ ++ HDMITX_CALLBACK_INT_R0, /**< R0 interrupt */ ++ HDMITX_CALLBACK_INT_ENCRYPT, /**< HDCP encryption switched off */ ++ HDMITX_CALLBACK_INT_HPD, /**< Transition on HPD input */ ++ HDMITX_CALLBACK_INT_T0, /**< HDCP state machine in state T0 */ ++ HDMITX_CALLBACK_INT_BCAPS, /**< BCAPS available */ ++ HDMITX_CALLBACK_INT_BSTATUS, /**< BSTATUS available */ ++ HDMITX_CALLBACK_INT_SHA_1, /**< sha-1(ksv,bstatus,m0)=V' */ ++ HDMITX_CALLBACK_INT_PJ, /**< pj=pj' check fails */ ++ HDMITX_CALLBACK_INT_SW_INT, /**< SW DEBUG interrupt */ ++ HDMITX_CALLBACK_INT_RX_SENSE, /**< RX SENSE interrupt */ ++ HDMITX_CALLBACK_INT_EDID_BLK_READ, /**< EDID BLK READ interrupt */ ++ HDMITX_CALLBACK_INT_VS_RPT, /**< VS interrupt */ ++ HDMITX_CALLBACK_INT_PLL_LOCK /** PLL LOCK not present on TDA9984 */ ++}; ++ ++ ++ ++#ifdef TMFL_TDA9989_PIXEL_CLOCK_ON_DDC ++ ++ CONST_DAT UInt8 kndiv_im[] = ++{ ++ 0, /* HDMITX_VFMT_NO_CHANGE */ ++ 4, /* HDMITX_VFMT_01_640x480p_60Hz */ ++ 4, /* HDMITX_VFMT_02_720x480p_60Hz */ ++ 4, /* HDMITX_VFMT_03_720x480p_60Hz */ ++ 12, /* HDMITX_VFMT_04_1280x720p_60Hz */ ++ 12, /* HDMITX_VFMT_05_1920x1080i_60Hz */ ++ 4, /* HDMITX_VFMT_06_720x480i_60Hz */ ++ 4, /* HDMITX_VFMT_07_720x480i_60Hz */ ++ 4, /* HDMITX_VFMT_08_720x240p_60Hz */ ++ 4, /* HDMITX_VFMT_09_720x240p_60Hz */ ++ 4, /* HDMITX_VFMT_10_720x480i_60Hz */ ++ 4, /* HDMITX_VFMT_11_720x480i_60Hz */ ++ 4, /* HDMITX_VFMT_12_720x240p_60Hz */ ++ 4, /* HDMITX_VFMT_13_720x240p_60Hz */ ++ 4, /* HDMITX_VFMT_14_1440x480p_60Hz */ ++ 4, /* HDMITX_VFMT_15_1440x480p_60Hz */ ++ 12,/* HDMITX_VFMT_16_1920x1080p_60Hz */ ++ 4, /* HDMITX_VFMT_17_720x576p_50Hz */ ++ 4, /* HDMITX_VFMT_18_720x576p_50Hz */ ++ 12, /* HDMITX_VFMT_19_1280x720p_50Hz */ ++ 12, /* HDMITX_VFMT_20_1920x1080i_50Hz */ ++ 4, /* HDMITX_VFMT_21_720x576i_50Hz */ ++ 4, /* HDMITX_VFMT_22_720x576i_50Hz */ ++ 4, /* HDMITX_VFMT_23_720x288p_50Hz */ ++ 4, /* HDMITX_VFMT_24_720x288p_50Hz */ ++ 4, /* HDMITX_VFMT_25_720x576i_50Hz */ ++ 4, /* HDMITX_VFMT_26_720x576i_50Hz */ ++ 4, /* HDMITX_VFMT_27_720x288p_50Hz */ ++ 4, /* HDMITX_VFMT_28_720x288p_50Hz */ ++ 4, /* HDMITX_VFMT_29_1440x576p_50Hz */ ++ 4, /* HDMITX_VFMT_30_1440x576p_50Hz */ ++ 12,/* HDMITX_VFMT_31_1920x1080p_50Hz */ ++ 12, /* HDMITX_VFMT_32_1920x1080p_24Hz */ ++ 12, /* HDMITX_VFMT_33_1920x1080p_25Hz */ ++ 12, /* HDMITX_VFMT_34_1920x1080p_30Hz */ ++ ++}; ++ ++ CONST_DAT UInt8 kclk_div[] = ++ { ++ 0, /* HDMITX_VFMT_NO_CHANGE */ ++ 44, /* HDMITX_VFMT_01_640x480p_60Hz */ ++ 44, /* HDMITX_VFMT_02_720x480p_60Hz */ ++ 44, /* HDMITX_VFMT_03_720x480p_60Hz */ ++ 44, /* HDMITX_VFMT_04_1280x720p_60Hz */ ++ 44, /* HDMITX_VFMT_05_1920x1080i_60Hz */ ++ 44, /* HDMITX_VFMT_06_720x480i_60Hz */ ++ 44, /* HDMITX_VFMT_07_720x480i_60Hz */ ++ 44, /* HDMITX_VFMT_08_720x240p_60Hz */ ++ 44, /* HDMITX_VFMT_09_720x240p_60Hz */ ++ 44, /* HDMITX_VFMT_10_720x480i_60Hz */ ++ 44, /* HDMITX_VFMT_11_720x480i_60Hz */ ++ 44, /* HDMITX_VFMT_12_720x240p_60Hz */ ++ 44, /* HDMITX_VFMT_13_720x240p_60Hz */ ++ 44, /* HDMITX_VFMT_14_1440x480p_60Hz */ ++ 44, /* HDMITX_VFMT_15_1440x480p_60Hz */ ++ 44,/* HDMITX_VFMT_16_1920x1080p_60Hz */ ++ 44, /* HDMITX_VFMT_17_720x576p_50Hz */ ++ 44, /* HDMITX_VFMT_18_720x576p_50Hz */ ++ 44, /* HDMITX_VFMT_19_1280x720p_50Hz */ ++ 44, /* HDMITX_VFMT_20_1920x1080i_50Hz */ ++ 44, /* HDMITX_VFMT_21_720x576i_50Hz */ ++ 44, /* HDMITX_VFMT_22_720x576i_50Hz */ ++ 44, /* HDMITX_VFMT_23_720x288p_50Hz */ ++ 44, /* HDMITX_VFMT_24_720x288p_50Hz */ ++ 44, /* HDMITX_VFMT_25_720x576i_50Hz */ ++ 44, /* HDMITX_VFMT_26_720x576i_50Hz */ ++ 44, /* HDMITX_VFMT_27_720x288p_50Hz */ ++ 44, /* HDMITX_VFMT_28_720x288p_50Hz */ ++ 44, /* HDMITX_VFMT_29_1440x576p_50Hz */ ++ 44, /* HDMITX_VFMT_30_1440x576p_50Hz */ ++ 44,/* HDMITX_VFMT_31_1920x1080p_50Hz */ ++ 44, /* HDMITX_VFMT_32_1920x1080p_24Hz */ ++ 44, /* HDMITX_VFMT_33_1920x1080p_25Hz */ ++ 44, /* HDMITX_VFMT_34_1920x1080p_30Hz */ ++ }; ++ ++#endif /* TMFL_TDA9989_PIXEL_CLOCK_ON_DDC */ ++ ++ ++/*============================================================================*/ ++/* FUNCTIONS DECLARATIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* VARIABLES DECLARATIONS */ ++/*============================================================================*/ ++ ++#ifdef TMFL_HDCP_SUPPORT ++static UInt32 sgBcapsCounter = 0; ++#endif /* TMFL_HDCP_SUPPORT */ ++ ++#define TDA19989_DDC_SPEED_FACTOR 39 ++ ++static Bool gMiscInterruptHpdRxEnable = False; /* Enable HPD and RX sense IT after */ ++ /* first call done by init function */ ++static UInt8 int_level=0xFF; ++/*============================================================================*/ ++/* FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* tmbslTDA9989Deinit */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989Deinit ++( ++ tmUnitSelect_t txUnit ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 EnableModeMask = 0; /* Local Variable */ ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* patch to get successfull soft reset even if powerstate has been set to standby mode */ ++ /*Write data in ENAMODS CEC Register */ ++ EnableModeMask = 0x40; ++ EnableModeMask |= E_MASKREG_CEC_ENAMODS_ena_hdmi; /*Enable HDMI Mode*/ ++ EnableModeMask &= ~E_MASKREG_CEC_ENAMODS_dis_fro; /* Enable FRO */ ++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, EnableModeMask); ++ RETIF_REG_FAIL(err) ++ ++ /* Hold the device in reset to disable it */ ++ err = setHwRegisterField(pDis, E_REG_P00_MAIN_CNTRL0_RW, ++ E_MASKREG_P00_MAIN_CNTRL0_sr, 1); ++ RETIF_REG_FAIL(err) ++ ++ /* patch to get successfull soft reset even if powerstate has been set to standby mode */ ++ EnableModeMask &= ~E_MASKREG_CEC_ENAMODS_ena_hdmi; /* Disable HDMI Mode*/ ++ EnableModeMask &= ~E_MASKREG_CEC_ENAMODS_ena_rxs; /* Reset RxSense Mode*/ ++ EnableModeMask |= E_MASKREG_CEC_ENAMODS_dis_fro; /* Disable FRO */ ++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, EnableModeMask); ++ RETIF_REG_FAIL(err) ++ ++ /* Clear the Initialized flag to destroy the device instance */ ++ pDis->bInitialized = False; ++ ++ setState(pDis, EV_DEINIT); ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HotPlugGetStatus */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HotPlugGetStatus ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxHotPlug_t *pHotPlugStatus, ++ Bool client /* Used to determine whether the request comes from the application */ ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regVal; /* Register value */ ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameters */ ++ RETIF_BADPARAM(pHotPlugStatus == (tmbslHdmiTxHotPlug_t *)0) ++ ++ /* Read HPD RXS level */ ++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,®Val); ++ RETIF(err != TM_OK, err) ++ ++ /* Read Hot Plug input status to know the actual level that caused the interrupt */ ++ if (client) ++ { ++ *pHotPlugStatus = (regVal & E_MASKREG_CEC_RXSHPDLEV_hpd_level) ? ++ HDMITX_HOTPLUG_ACTIVE : HDMITX_HOTPLUG_INACTIVE; ++ } ++ else { ++ ++ *pHotPlugStatus = pDis->hotPlugStatus; ++ ++ } ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989RxSenseGetStatus */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989RxSenseGetStatus ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxRxSense_t *pRxSenseStatus, ++ Bool client /* Used to determine whether the request comes from the application */ ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regVal; /* Register value */ ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameters */ ++ RETIF_BADPARAM(pRxSenseStatus == (tmbslHdmiTxRxSense_t *)0) ++ ++ ++ /* Read HPD RXS level */ ++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,®Val); ++ RETIF(err != TM_OK, err) ++ ++ ++ /*Read RXS_FIL status to know the actual level that caused the interrupt */ ++ if (client) ++ { ++ *pRxSenseStatus = (regVal & E_MASKREG_CEC_RXSHPDLEV_rxs_level) ? ++ HDMITX_RX_SENSE_ACTIVE : HDMITX_RX_SENSE_INACTIVE; ++ } ++ else { ++ *pRxSenseStatus = pDis->rxSenseStatus; ++ } ++ ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HwGetRegisters */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HwGetRegisters ++( ++ tmUnitSelect_t txUnit, ++ Int regPage, ++ Int regAddr, ++ UInt8 *pRegBuf, ++ Int nRegs ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ Int i; /* Loop index */ ++ UInt8 newRegPage; /* The register's new page number */ ++ UInt8 regShad; /* Index to the register's shadow copy */ ++ UInt16 regShadPageAddr;/* Packed shadowindex/page/address */ ++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */ ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameters */ ++ RETIF_BADPARAM((regPage < kPageIndexToPage[E_PAGE_00]) ++ || ((regPage > kPageIndexToPage[E_PAGE_02]) ++ && (regPage < kPageIndexToPage[E_PAGE_09])) ++ || ((regPage > kPageIndexToPage[E_PAGE_09]) ++ && (regPage < kPageIndexToPage[E_PAGE_11])) ++ || (regPage > kPageIndexToPage[E_PAGE_12])) ++ RETIF_BADPARAM((regAddr < E_REG_MIN_ADR) || (regAddr >= E_REG_CURPAGE_ADR_W)) ++ RETIF_BADPARAM(pRegBuf == (pUInt8)0) ++ RETIF_BADPARAM((nRegs < 1) || ((nRegs + regAddr) > E_REG_CURPAGE_ADR_W)) ++ ++ /* Set page register if required */ ++ newRegPage = (UInt8)regPage; ++ if (pDis->curRegPage != newRegPage) ++ { ++ /* All non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = E_REG_CURPAGE_ADR_W; ++ sysArgs.lenData = 1; ++ sysArgs.pData = &newRegPage; ++ err = pDis->sysFuncWrite(&sysArgs); ++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE) ++ pDis->curRegPage = newRegPage; ++ } ++ ++ /* Read each register in the range. nRegs must start at 1 or more */ ++ for ( ; nRegs > 0; pRegBuf++, regAddr++, nRegs--) ++ { ++ /* Find shadow register index. ++ * This loop is not very efficient, but it is assumed that this API ++ * will not be used often. The alternative is to use a huge sparse ++ * array indexed by page and address and containing the shadow index. ++ */ ++ regShad = E_SNONE; ++ for (i = 0; i < E_SNUM; i++) ++ { ++ /* Check lookup table for match with page and address */ ++ regShadPageAddr = kShadowReg[i]; ++ if ((SPA2PAGE(regShadPageAddr) == newRegPage) ++ && (SPA2ADDR(regShadPageAddr) == regAddr)) ++ { ++ /* Found page and address - look up the shadow index */ ++ regShad = SPA2SHAD(regShadPageAddr); ++ break; ++ } ++ } ++ /* Read the shadow register if available, as device registers that ++ * are shadowed cannot be read directly */ ++ if (regShad != E_SNONE) ++ { ++ *pRegBuf = pDis->shadowReg[regShad]; ++ } ++ else ++ { ++ /* Read the device register - all non-OK results are errors. ++ * Note that some non-shadowed registers are also write-only and ++ * cannot be read. */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = (UInt8)regAddr; ++ sysArgs.lenData = 1; ++ sysArgs.pData = pRegBuf; ++ err = pDis->sysFuncRead(&sysArgs); ++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_READ) ++ } ++ } ++ ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HwGetVersion */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++tmbslTDA9989HwGetVersion ++( ++ tmUnitSelect_t txUnit, ++ pUInt8 pHwVersion ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regVal; ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameters */ ++ RETIF_BADPARAM(pHwVersion == (pUInt8)0) ++ ++ /* Get MSB version Value*/ ++ err = getHwRegister(pDis, E_REG_P00_VERSION_MSB_RW, ®Val); ++ RETIF(err != TM_OK, err) ++ ++ switch (regVal) ++ { ++ case 0x01: ++ *pHwVersion = (UInt8)(BSLHDMITX_TDA9989); ++ break; ++ case 0x02: ++ *pHwVersion = (UInt8)(BSLHDMITX_TDA19989); ++ break; ++ case 0x03: ++ *pHwVersion = (UInt8)(BSLHDMITX_TDA19988); ++ break; ++ default: ++ *pHwVersion = (UInt8)(BSLHDMITX_UNKNOWN); ++ break; ++ } ++ ++ return TM_OK; ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989HwHandleInterrupt */ ++/* RETIF_REG_FAIL NOT USED HERE AS ALL ERRORS SHOULD BE TRAPPED IN ALL BUILDS */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HwHandleInterrupt ++( ++ tmUnitSelect_t txUnit ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regVal; /* Register value */ ++ UInt8 regVal1; /* Register value */ ++ UInt16 fInterruptStatus; /* Interrupt flags */ ++ UInt16 fInterruptMask; /* Mask to test each interrupt bit */ ++ tmbslHdmiTxRxSense_t newRxs_fil; /* Latest copy of rx_sense */ ++ Int i; /* Loop counter */ ++ tmbslHdmiTxHotPlug_t newHpdIn; /* Latest copy of hpd input */ ++ Bool sendEdidCallback; ++ Bool hpdOrRxsLevelHasChanged = False; ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ fInterruptStatus = 0; ++ sendEdidCallback = False; ++ ++ ++ ++ /* Read HPD RXS int status */ ++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDINT_R,®Val); ++ RETIF(err != TM_OK, err); ++ ++ /* Read HPD RXS level */ ++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,®Val1); ++ RETIF(err != TM_OK, err); ++ ++ if (int_level!=0xFF) { /* init should be done */ ++ /* check multi-transition */ ++ if ((regVal==0) && (int_level!=regVal1)) { ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++ printk("HDMI Int multi-transition\n"); ++#endif ++ err = setCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, 0x00); ++ err += setCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, \ ++ E_MASKREG_CEC_RXSHPDINTENA_ena_rxs_int | \ ++ E_MASKREG_CEC_RXSHPDINTENA_ena_hpd_int); ++ err += getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,®Val1); ++ RETIF(err != TM_OK, err) ++ } ++ } ++ int_level=regVal1; ++ ++ /* Read Hot Plug input status to know the actual level that caused the interrupt */ ++ newHpdIn = (regVal1 & E_MASKREG_CEC_RXSHPDLEV_hpd_level) ? ++ HDMITX_HOTPLUG_ACTIVE : HDMITX_HOTPLUG_INACTIVE; ++ ++ /*Read RXS_FIL status to know the actual level that caused the interrupt */ ++ newRxs_fil = (regVal1 & E_MASKREG_CEC_RXSHPDLEV_rxs_level) ? ++ HDMITX_RX_SENSE_ACTIVE : HDMITX_RX_SENSE_INACTIVE; ++ ++ /*Fill fInterruptStatus with HPD Interrupt flag*/ ++ ++ if (newHpdIn != pDis->hotPlugStatus) ++ { ++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_HPD); ++ /* Yes: save new HPD level */ ++ pDis->hotPlugStatus = newHpdIn; ++ hpdOrRxsLevelHasChanged = True; ++ } ++ ++ /*Fill fInterruptStatus with RX Sense Interrupt flag*/ ++ if (newRxs_fil != pDis->rxSenseStatus) ++ { ++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_RX_SENSE); ++ /* Yes: save new rxSense level */ ++ pDis->rxSenseStatus = newRxs_fil; ++ hpdOrRxsLevelHasChanged = True; ++ } ++ ++ ++ ++ /* is it HDMI interrupt ? */ ++ err = getCECHwRegister(pDis, E_REG_CEC_INTERRUPTSTATUS_R,®Val); ++ RETIF(err != TM_OK, err) ++ ++ /* there is no HDMI int to handle, give up */ ++ if ((regVal & E_MASKREG_CEC_INTERRUPTSTATUS_hdmi_int) == 0x00) { ++ ++ if (hpdOrRxsLevelHasChanged == True) { ++ } ++ else { ++ return TM_OK; ++ } ++ } ++ ++ ++ ++ /************************************************************************************************/ ++ /***********************************End of Temporary code****************************************/ ++ /************************************************************************************************/ ++ ++ /* Do only if HDMI is On*/ ++ if(pDis->ePowerState == tmPowerOn) ++ { ++ /* Read the main interrupt flags register to determine the source(s) ++ * of the interrupt. (The device resets these register flags after they ++ * have been read.) ++ */ ++ err = getHwRegister(pDis, E_REG_P00_INT_FLAGS_0_RW, ®Val); ++ RETIF(err != TM_OK, err) ++ ++#ifdef TMFL_HDCP_SUPPORT ++ /* encrypt */ ++ if ((regVal & E_MASKREG_P00_INT_FLAGS_0_encrypt) != 0) ++ { ++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_ENCRYPT); ++ } ++#endif /* TMFL_HDCP_SUPPORT */ ++ ++ /* get TO interrupt Flag*/ ++ if ((regVal & E_MASKREG_P00_INT_FLAGS_0_t0) != 0) ++ { ++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_T0); ++ } ++ ++#ifdef TMFL_HDCP_SUPPORT ++ /* bcaps */ ++ if ((regVal & E_MASKREG_P00_INT_FLAGS_0_bcaps) != 0) ++ { ++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_BCAPS); ++ ++ /* TDA19989 N1 only */ ++ if (pDis->uDeviceVersion == E_DEV_VERSION_TDA19989) { ++ ++ /* WA: HDCP ATC Test 1B_03 */ ++ ++ sgBcapsCounter++; ++ ++ if (sgBcapsCounter == 49) { ++ sgBcapsCounter = 0; ++ /* force a T0 interrupt */ ++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_T0); ++ } ++ ++ } /* TDA19989 N1 only */ ++ ++ } ++ ++ /* bstatus */ ++ if ((regVal & E_MASKREG_P00_INT_FLAGS_0_bstatus) != 0) ++ { ++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_BSTATUS); ++ ++ /* TDA19989 N1 only */ ++ if (pDis->uDeviceVersion == E_DEV_VERSION_TDA19989) { ++ ++ /* WA: HDCP ATC Test 1B_03 */ ++ sgBcapsCounter = 0; ++ ++ } /* TDA19989 N1 only */ ++ ++ } ++ ++ /* sha_1 */ ++ if ((regVal & E_MASKREG_P00_INT_FLAGS_0_sha_1) != 0) ++ { ++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_SHA_1); ++ } ++ ++ /* pj */ ++ if ((regVal & E_MASKREG_P00_INT_FLAGS_0_pj) != 0) ++ { ++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_PJ); ++ } ++ ++ /* r0 */ ++ if ((regVal & E_MASKREG_P00_INT_FLAGS_0_r0) != 0) ++ { ++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_R0); ++ ++ /* TDA19989 N1 only */ ++ if (pDis->uDeviceVersion == E_DEV_VERSION_TDA19989) { ++ ++ /* WA: HDCP ATC Test 1B_03 */ ++ sgBcapsCounter = 0; ++ ++ } /* TDA19989 N1 only */ ++ ++ } ++#endif /* TMFL_HDCP_SUPPORT */ ++ ++ ++ err = getHwRegister(pDis, E_REG_P00_INT_FLAGS_1_RW, ®Val); ++ RETIF(err != TM_OK, err) ++ ++ ++ /* Read the software interrupt flag */ ++ if ((regVal & E_MASKREG_P00_INT_FLAGS_1_sw_int) != 0) ++ { ++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_SW_INT); ++ } ++ ++ /* Read the VS_rpt interrupt flag */ ++ if (((pDis->InterruptsEnable & E_MASKREG_P00_INT_FLAGS_1_vs_rpt) != 0) && ++ ((regVal & E_MASKREG_P00_INT_FLAGS_1_vs_rpt) != 0) ++ ) ++ { ++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_VS_RPT); ++ } ++ ++ /* Read INT_FLAGS_2 interrupt flag register. ++ *(The device resets these register flags after they ++ * have been read.) */ ++ err = getHwRegister(pDis, E_REG_P00_INT_FLAGS_2_RW, ®Val); ++ RETIF(err != TM_OK, err) ++ ++ /* Has the EDID_blk_rd interrupt occurs */ ++ if ((regVal & E_MASKREG_P00_INT_FLAGS_2_edid_blk_rd) != 0) ++ { ++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_EDID_BLK_READ); ++ } ++ } ++ ++ ++ /* Handle the HPD Interrupt */ ++ if ((fInterruptStatus & (1 << HDMITX_CALLBACK_INT_HPD))!=0 ) ++ { ++ /* Callback disable on first tmbslTDA9989HwHandleInterrupt call */ ++ if(gMiscInterruptHpdRxEnable) ++ { ++ /* Reset EDID status */ ++ err = ClearEdidRequest(txUnit); ++ ++ /* Reset all simultaneous HDCP interrupts on hot plug, ++ * preserving only the high-priority hpd interrupt rx_sense and sw interrupt for debug*/ ++ fInterruptStatus &= (1 << HDMITX_CALLBACK_INT_HPD) | ++ (1 << HDMITX_CALLBACK_INT_RX_SENSE) | ++ (1 << HDMITX_CALLBACK_INT_SW_INT); ++ ++ if(pDis->ePowerState == tmPowerOn) ++ { ++ if ((pDis->hotPlugStatus == HDMITX_HOTPLUG_ACTIVE)) ++ { ++ ++ /* TDA19989 N1 only */ ++ if (pDis->uDeviceVersion == E_DEV_VERSION_TDA19989) { ++ ++ err = tmbslTDA9989Reset(txUnit); ++ RETIF(err != TM_OK, err) ++ ++ err = hotPlugRestore(txUnit); ++ RETIF(err != TM_OK, err) ++ ++ } /* TDA19989 N1 only */ ++ ++ else { /* TDA19989 N2 */ ++ ++ HDCP_F2; ++ } ++ ++ #ifdef TMFL_TDA9989_PIXEL_CLOCK_ON_DDC ++ ++ err = tmbslTDA9989Reset(txUnit); ++ RETIF(err != TM_OK, err) ++ ++ err = hotPlugRestore(txUnit); ++ RETIF(err != TM_OK, err) ++ ++ #endif /* TMFL_TDA9989_PIXEL_CLOCK_ON_DDC */ ++ ++ ++ ++ setState(pDis, EV_PLUGGEDIN); ++ } ++ else ++ { ++ setState(pDis, EV_UNPLUGGED); ++ } ++ } ++ } ++ } ++ else ++ { ++ /* Clear HPD status if level has not changed */ ++ fInterruptStatus &= ~(1 << HDMITX_CALLBACK_INT_HPD); ++ ++ if (fInterruptStatus & (1 << HDMITX_CALLBACK_INT_EDID_BLK_READ)) ++ { ++ err = EdidBlockAvailable(txUnit,&sendEdidCallback); ++ RETIF(err != TM_OK, err) ++ if (sendEdidCallback == False) ++ { ++ /* Read EDID not finished clear callback */ ++ fInterruptStatus &= ~(1 << HDMITX_CALLBACK_INT_EDID_BLK_READ); ++ } ++ else { ++ #ifdef TMFL_TDA9989_PIXEL_CLOCK_ON_DDC ++ ++ if ( (pDis->vinFmt == HDMITX_VFMT_16_1920x1080p_60Hz) || (pDis->vinFmt == HDMITX_VFMT_31_1920x1080p_50Hz)) { ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P02_PLL_SERIAL_3_RW, ++ E_MASKREG_P02_PLL_SERIAL_3_srl_ccir, ++ 0x00); ++ RETIF_REG_FAIL(err) ++ } ++ ++ #endif /* TMFL_TDA9989_PIXEL_CLOCK_ON_DDC */ ++ } ++ ++ ++ } ++ } ++ ++ /*Handle RxSense Interrupt*/ ++ if ((fInterruptStatus &( 1 << HDMITX_CALLBACK_INT_RX_SENSE))!= 0) ++ { ++ /* Callback disable on first tmbslTDA9989HwHandleInterrupt call */ ++ if(gMiscInterruptHpdRxEnable) ++ { ++ ++ ++ fInterruptStatus &= (1 << HDMITX_CALLBACK_INT_HPD) | ++ (1 << HDMITX_CALLBACK_INT_RX_SENSE) | ++ (1 << HDMITX_CALLBACK_INT_SW_INT); ++ ++ if (pDis->rxSenseStatus == HDMITX_RX_SENSE_ACTIVE) ++ { ++ setState(pDis, EV_SINKON); ++ } ++ else ++ { ++ setState(pDis, EV_SINKOFF); ++ } ++ } ++ } ++ else ++ { ++ /* Clear RX_sense IT if level has not changed */ ++ fInterruptStatus &= ~(1 << HDMITX_CALLBACK_INT_RX_SENSE); ++ } ++ ++ /* Ignore other simultaneous HDCP interrupts if T0 interrupt, ++ * preserving any hpd interrupt */ ++ ++ if (fInterruptStatus & (1 << HDMITX_CALLBACK_INT_T0)) ++ { ++ if (pDis->EdidReadStarted) ++ { ++ ++#ifdef TMFL_HDCP_SUPPORT ++ err = getHwRegister(pDis, E_REG_P12_TX0_RW, ®Val); ++ RETIF(err != TM_OK, err) ++ ++ /* EDID read failure */ ++ if ((regVal & E_MASKREG_P12_TX0_sr_hdcp) != 0) { ++ ++#endif /* TMFL_HDCP_SUPPORT */ ++ ++ ++ /* Reset EDID status */ ++ err = ClearEdidRequest(txUnit); ++ RETIF(err != TM_OK, err) ++ ++ /* enable EDID callback */ ++ fInterruptStatus = (UInt16) (fInterruptStatus & (~(1 << HDMITX_CALLBACK_INT_T0))); ++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_EDID_BLK_READ); ++ ++#ifdef TMFL_HDCP_SUPPORT ++ } ++#endif /* TMFL_HDCP_SUPPORT */ ++ ++ } ++ else ++ { ++ fInterruptStatus &= ++ ( ++ (1 << HDMITX_CALLBACK_INT_HPD) ++ |(1 << HDMITX_CALLBACK_INT_T0) ++ |(1 << HDMITX_CALLBACK_INT_RX_SENSE) ++ |(1 << HDMITX_CALLBACK_INT_SW_INT) ++ ); ++ } ++ } ++ ++ HDCP_F3; ++ ++ /* For each interrupt flag that is set, check the corresponding registered ++ * callback function pointer in the Device Instance Structure ++ * funcIntCallbacks array. ++ */ ++ fInterruptMask = 1; ++ for (i = 0; i < HDMITX_CALLBACK_INT_NUM; i++) ++ { ++ if ( i != HDMITX_CALLBACK_INT_PLL_LOCK) /* PLL LOCK not present on TDA9989 */ ++ { ++ ++ fInterruptMask = 1; ++ fInterruptMask = fInterruptMask << ((UInt16)kITCallbackPriority[i]); ++ ++ if (fInterruptStatus & fInterruptMask) ++ { ++ /* IF a registered callback pointer is non-null THEN call it. */ ++ if (pDis->funcIntCallbacks[kITCallbackPriority[i]] != (ptmbslHdmiTxCallback_t)0) ++ { ++ pDis->funcIntCallbacks[kITCallbackPriority[i]](txUnit); ++ } ++ } ++ ++ } ++ } ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989FlagSwInt */ ++/* Use only for debug to flag the software debug interrupt */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989FlagSwInt ++( ++ tmUnitSelect_t txUnit, ++ UInt32 uSwInt ++ ) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ DUMMY_ACCESS(uSwInt); ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ err = setHwRegister(pDis, E_REG_P00_SW_INT_W, ++ E_MASKREG_P00_SW_INT_sw_int); ++ ++ ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989HwSetRegisters */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++tmbslTDA9989HwSetRegisters ++( ++ tmUnitSelect_t txUnit, ++ Int regPage, ++ Int regAddr, ++ UInt8 *pRegBuf, ++ Int nRegs ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ Int i; /* Loop index */ ++ UInt8 newRegPage; /* The register's new page number */ ++ UInt8 regShad; /* Index to the register's shadow copy */ ++ UInt16 regShadPageAddr;/* Packed shadowindex/page/address */ ++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */ ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameters */ ++ RETIF_BADPARAM((regPage < kPageIndexToPage[E_PAGE_00]) ++ || ((regPage > kPageIndexToPage[E_PAGE_02]) ++ && (regPage < kPageIndexToPage[E_PAGE_11])) ++ || (regPage > kPageIndexToPage[E_PAGE_12])) ++ RETIF_BADPARAM((regAddr < E_REG_MIN_ADR) || (regAddr >= E_REG_CURPAGE_ADR_W)) ++ RETIF_BADPARAM(pRegBuf == (pUInt8)0) ++ RETIF_BADPARAM((nRegs < 0) || ((nRegs + regAddr) > E_REG_CURPAGE_ADR_W)) ++ ++ /* Set page register if required */ ++ newRegPage = (UInt8)regPage; ++ if (pDis->curRegPage != newRegPage) ++ { ++ /* All non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = E_REG_CURPAGE_ADR_W; ++ sysArgs.lenData = 1; ++ sysArgs.pData = &newRegPage; ++ err = pDis->sysFuncWrite(&sysArgs); ++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE) ++ pDis->curRegPage = newRegPage; ++ } ++ ++ /* Write each register in the range. nRegs = 0 is ok, to allow only ++ * the page register to be written if required (above) ++ */ ++ for ( ; nRegs > 0; pRegBuf++, regAddr++, nRegs--) ++ { ++ /* Find shadow register index. ++ * This loop is not very efficient, but it is assumed that this API ++ * will not be used often. The alternative is to use a huge sparse ++ * array indexed by page and address and containing the shadow index. ++ */ ++ for (i = 0; i < E_SNUM; i++) ++ { ++ /* Check lookup table for match with page and address */ ++ regShadPageAddr = kShadowReg[i]; ++ if ((SPA2PAGE(regShadPageAddr) == newRegPage) ++ && (SPA2ADDR(regShadPageAddr) == regAddr)) ++ { ++ /* Found index - write the shadow register */ ++ regShad = SPA2SHAD(regShadPageAddr); ++ pDis->shadowReg[regShad] = *pRegBuf; ++ break; ++ } ++ } ++ /* Write the device register - all non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = (UInt8)regAddr; ++ sysArgs.lenData = 1; ++ sysArgs.pData = pRegBuf; ++ err = pDis->sysFuncWrite(&sysArgs); ++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE) ++ } ++ ++ return TM_OK; ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989HwStartup */ ++/*============================================================================*/ ++void ++tmbslTDA9989HwStartup ++( ++ void ++) ++{ ++ /* Reset device instance data for when compiler doesn't do it */ ++ lmemset(&gHdmiTxInstance, 0, sizeof(gHdmiTxInstance)); ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989Init */ ++/* RETIF_REG_FAIL NOT USED HERE AS ALL ERRORS SHOULD BE TRAPPED IN ALL BUILDS */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989Init ++( ++ tmUnitSelect_t txUnit, ++ UInt8 uHwAddress, ++ ptmbslHdmiTxSysFunc_t sysFuncWrite, ++ ptmbslHdmiTxSysFunc_t sysFuncRead, ++ ptmbslHdmiTxSysFuncEdid_t sysFuncEdidRead, ++ ptmbslHdmiTxSysFuncTimer_t sysFuncTimer, ++ tmbslHdmiTxCallbackList_t *funcIntCallbacks, ++ Bool bEdidAltAddr, ++ tmbslHdmiTxVidFmt_t vinFmt, ++ tmbslHdmiTxPixRate_t pixRate ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ Int i; /* Loop index */ ++ Bool bFound; /* T=found, F=not found */ ++ UInt8 EnableIntMask = 0; /* Mask used to enable HPD and RX Sense interrupt*/ ++ UInt8 EnableModeMask; /* Mask used to Set HDMI and RxSense modes*/ ++ UInt16 val16Bits; /* Value on 16 bit */ ++ UInt8 regVal; /* Register value */ ++ ++ /* Check unit parameter and point to its object */ ++ RETIF(txUnit < tmUnit0, TMBSL_ERR_HDMI_BAD_UNIT_NUMBER) ++ RETIF(txUnit >= HDMITX_UNITS_MAX, TMBSL_ERR_HDMI_BAD_UNIT_NUMBER) ++ pDis = &gHdmiTxInstance[txUnit]; ++ ++ /* IF the bInitialized flag is set THEN return (only Init does this) */ ++ RETIF(pDis->bInitialized, TMBSL_ERR_HDMI_INIT_FAILED) ++ ++ /* Check remaining parameters */ ++ RETIF_BADPARAM(uHwAddress < HDMITX_SLAVE_ADDRESS_MIN) ++ RETIF_BADPARAM(uHwAddress > HDMITX_SLAVE_ADDRESS_MAX) ++ RETIF_BADPARAM(sysFuncWrite == (ptmbslHdmiTxSysFunc_t)0) ++ RETIF_BADPARAM(sysFuncRead == (ptmbslHdmiTxSysFunc_t)0) ++ /*RETIF_BADPARAM(sysFuncEdidRead == (ptmbslHdmiTxSysFuncEdid_t)0)*/ /*Previously on TDA9983*/ ++ /*RETIF_BADPARAM(sysFuncTimer == (ptmbslHdmiTxSysFuncTimer_t)0)*/ ++ RETIF_BADPARAM((bEdidAltAddr != True) && (bEdidAltAddr != False)) ++ RETIF_BADPARAM(!IS_VALID_FMT(vinFmt)) ++ RETIF_BADPARAM(pixRate >= HDMITX_PIXRATE_INVALID) ++ ++ /* Set all Device Instance Structure members to default values */ ++ lmemcpy(pDis, &kHdmiTxInstanceDefault, sizeof(*pDis)); ++ ++ /* Copy txUnit, uHwAddress, sysFuncWrite and sysFuncRead values to ++ * the defaulted Device Instance Structure BEFORE FIRST DEVICE ACCESS. ++ */ ++ pDis->txUnit = txUnit; ++#ifdef UNIT_TEST ++ /* Unit test build can't support 127 device sets of dummy registers, so use ++ * smaller range instead, indexed by unit number not I2C address */ ++ pDis->uHwAddress = (UInt8)txUnit; ++#else ++ /* Store actual I2C address */ ++ pDis->uHwAddress = uHwAddress; ++#endif ++ pDis->sysFuncWrite = sysFuncWrite; ++ pDis->sysFuncRead = sysFuncRead; ++ pDis->sysFuncEdidRead = sysFuncEdidRead; ++ pDis->sysFuncTimer = sysFuncTimer; ++ ++ /* IF the funcIntCallbacks array pointer is defined ++ * THEN for each funcIntCallbacks pointer that is not null: ++ * - Copy the pointer to the Device Instance Structure ++ * funcIntCallbacks array. ++ */ ++ ++ for (i = 0; i < HDMITX_CALLBACK_INT_NUM; i++) ++ { ++ if ((funcIntCallbacks != (tmbslHdmiTxCallbackList_t *)0) ++ && (funcIntCallbacks->funcCallback[i] != (ptmbslHdmiTxCallback_t)0)) ++ { ++ pDis->funcIntCallbacks[i] = funcIntCallbacks->funcCallback[i]; ++ } ++ else ++ { ++ pDis->funcIntCallbacks[i] = (ptmbslHdmiTxCallback_t)0; ++ } ++ } ++ ++ /* Set the EDID alternate address flag if needed*/ ++ pDis->bEdidAlternateAddr = bEdidAltAddr; ++ ++//*****************************************************************************************// ++//*****************************************************************************************// ++//**********************Enable HDMI and RxSense************************/// ++ ++ /* reset ENAMODS */ ++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, 0x40); ++ RETIF_REG_FAIL(err) ++ ++ ++ ++ ++ ++ /*Read data out of ENAMODS CEC Register */ ++ err = getCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, &EnableModeMask); ++ ++ /*Enable required modes*/ ++ EnableModeMask |= E_MASKREG_CEC_ENAMODS_ena_hdmi; /*Enable HDMI Mode*/ ++ EnableModeMask |= E_MASKREG_CEC_ENAMODS_ena_rxs; /*Enable RxSense Mode*/ ++ EnableModeMask &= ~E_MASKREG_CEC_ENAMODS_dis_fro; /* Enable FRO */ ++ ++ /*Write data in ENAMODS CEC Register */ ++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, EnableModeMask); ++ ++ pDis->ePowerState = (tmbslHdmiTxPowerState_t) tmPowerOn; ++ ++ /* Set the bInitialized flag to enable other APIs */ ++ pDis->bInitialized = True; ++ ++ /* Reset the device */ ++ err = tmbslTDA9989Reset(txUnit); ++ RETIF(err != TM_OK, err) ++ ++//***************************************************************************************// ++//****************Get Device Version and Capabilities************************************// ++ /* Read the device version register to uDeviceVersion in the ++ * Device Instance Structure ++ */ ++ err = getHwRegister(pDis, E_REG_P00_VERSION_R, ®Val); ++ RETIF(err != TM_OK, err) ++ ++ /* Copy N4 features bits to DIS */ ++ pDis->uDeviceFeatures = regVal & ++ (E_MASKREG_P00_VERSION_not_h | E_MASKREG_P00_VERSION_not_s); ++ ++ pDis->uDeviceVersion = regVal; ++ ++ /* Get MSB version Value*/ ++ err = getHwRegister(pDis, E_REG_P00_VERSION_MSB_RW, ®Val); ++ RETIF(err != TM_OK, err) ++ ++ /* Build Device Version Info */ ++ val16Bits = regVal; ++ pDis->uDeviceVersion = pDis->uDeviceVersion | (val16Bits << 8); ++ val16Bits = pDis->uDeviceFeatures; ++ pDis->uDeviceVersion &= ~val16Bits; ++ ++ if (pDis->uDeviceVersion != E_DEV_VERSION_LIST_END) ++ { ++ /* Search for the device version in the Supported Version ++ * List in the Device Instance Structure. ++ */ ++ for (i = 0, bFound = False; i < E_DEV_VERSION_LIST_NUM; i++) ++ { ++ if (pDis->uDeviceVersion == pDis->uSupportedVersions[i]) ++ { ++ bFound = True; ++ } ++ } ++ if (bFound == False) ++ { ++ /* IF the device version is not found in the Supported Version List THEN ++ * this driver component is not compatible with the device.*/ ++ err = tmbslTDA9989Deinit(txUnit); ++ RETIF(err != TM_OK, err) ++ return TMBSL_ERR_HDMI_COMPATIBILITY; ++ } ++ } ++ else ++ { ++ /* Quit if version reads zero */ ++ err = tmbslTDA9989Deinit(txUnit); ++ RETIF(err != TM_OK, err) ++ return TMBSL_ERR_HDMI_COMPATIBILITY; ++ } ++ ++/***************************************************************************************/ ++/************Set the BIAS_tmds Value (general control for Analogu module)***************/ ++ regVal = HDMI_TX_VSWING_VALUE; ++ ++ err = setHwRegister(pDis, E_REG_P02_ANA_GENERAL_RW, regVal); ++ RETIF(err != TM_OK, err) ++ ++/*****************************************************************************************/ ++/*****************************************************************************************/ ++ ++ /* Set the PLL before resetting the device */ ++ /* PLL registers common configuration */ ++ err = setHwRegisterFieldTable(pDis, &kCommonPllCfg[0]); ++ RETIF_REG_FAIL(err) ++ ++ /*Reset 656_Alt bit in VIP_CONTROL_4 Register*/ ++ err = setHwRegisterField( pDis, E_REG_P00_VIP_CNTRL_4_W, E_MASKREG_P00_VIP_CNTRL_4_656_alt, 0); ++ ++ switch (vinFmt) ++ { ++ /* 480i or 576i video input format */ ++ case HDMITX_VFMT_06_720x480i_60Hz: ++ case HDMITX_VFMT_07_720x480i_60Hz: ++ case HDMITX_VFMT_21_720x576i_50Hz: ++ case HDMITX_VFMT_22_720x576i_50Hz: ++ err = setHwRegisterFieldTable(pDis, &kVfmt480i576iPllCfg[0]); ++ RETIF_REG_FAIL(err) ++ ++ switch (pixRate) ++ { ++ case HDMITX_PIXRATE_SINGLE: ++ /* Single edge mode, vinFmt 480i or 576i */ ++ err = setHwRegisterFieldTable(pDis, &kSinglePrateVfmt480i576iPllCfg[0]); ++ RETIF_REG_FAIL(err) ++ ++ break; ++ case HDMITX_PIXRATE_SINGLE_REPEATED: ++ /* Single repeated edge mode, vinFmt 480i or 576i */ ++ err = setHwRegisterFieldTable(pDis, &kSrepeatedPrateVfmt480i576iPllCfg[0]); ++ RETIF_REG_FAIL(err) ++ ++ break; ++ default: ++ /* Double edge mode doesn't exist for vinFmt 480i or 576i */ ++ return(TMBSL_ERR_HDMI_INCONSISTENT_PARAMS); ++ } ++ ++ break; ++ ++ ++ /* Others video input format */ ++ default: ++ err = setHwRegisterFieldTable(pDis, &kVfmtOtherPllCfg[0]); ++ RETIF_REG_FAIL(err) ++ ++ switch (pixRate) ++ { ++ case HDMITX_PIXRATE_SINGLE: ++ /* Single edge mode, vinFmt other than 480i or 576i */ ++ err = setHwRegisterFieldTable(pDis, &kSinglePrateVfmtOtherPllCfg[0]); ++ RETIF_REG_FAIL(err) ++ break; ++ case HDMITX_PIXRATE_DOUBLE: ++ /* Double edge mode, vinFmt other than 480i or 576i */ ++ err = setHwRegisterFieldTable(pDis, &kDoublePrateVfmtOtherPllCfg[0]); ++ RETIF_REG_FAIL(err) ++ break; ++ default: ++ /* Single repeated edge mode doesn't exist for other vinFmt */ ++ return(TMBSL_ERR_HDMI_INCONSISTENT_PARAMS); ++ } ++ break; ++ ++ } ++ ++ /* DDC interface is disable for TDA9989 after reset, enable it */ ++ err = setHwRegister(pDis, E_REG_P00_DDC_DISABLE_RW, 0x00); ++ RETIF(err != TM_OK, err) ++ ++ /* Set clock speed of the DDC channel */ ++ ++ err = setHwRegister(pDis, E_REG_P12_TX3_RW, TDA19989_DDC_SPEED_FACTOR); ++ RETIF(err != TM_OK, err) ++ ++ /* TDA19989 N1 only */ ++ if (pDis->uDeviceVersion == E_DEV_VERSION_TDA19989) { ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_I2C_MASTER_RW, ++ E_MASKREG_P00_I2C_MASTER_dis_mm, ++ 0); /* 0: enable multi master mode */ ++ RETIF_REG_FAIL(err) ++ ++ } /* TDA19989 N1 only */ ++ ++ ++ err = setCECHwRegister(pDis, E_REG_CEC_FRO_IM_CLK_CTRL_RW, E_MASKREG_CEC_FRO_IM_CLK_CTRL_ghost_dis | E_MASKREG_CEC_FRO_IM_CLK_CTRL_imclk_sel); ++ RETIF_REG_FAIL(err) ++ ++ /* The DIS hotplug status is HDMITX_HOTPLUG_INVALID, so call the main ++ * interrupt handler to read the current Hot Plug status and run any ++ * registered HPD callback before interrupts are enabled below */ ++ //err = tmbslTDA9989HwHandleInterrupt(txUnit); ++ RETIF(err != TM_OK, err) ++ ++ /* enable sw _interrupt and VS_interrupt for debug */ ++ err = setHwRegister(pDis, E_REG_P00_INT_FLAGS_1_RW, ++ E_MASKREG_P00_INT_FLAGS_1_sw_int); ++ ++ /* enable edid read */ ++ err = setHwRegister(pDis, E_REG_P00_INT_FLAGS_2_RW, ++ E_MASKREG_P00_INT_FLAGS_2_edid_blk_rd); ++ ++ ++ /* Read HPD RXS level */ ++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,®Val); ++ RETIF(err != TM_OK, err) ++ ++ /* Read Hot Plug input status to know the actual level that caused the interrupt */ ++ pDis->hotPlugStatus = (regVal & E_MASKREG_CEC_RXSHPDLEV_hpd_level) ? ++ HDMITX_HOTPLUG_ACTIVE : HDMITX_HOTPLUG_INACTIVE; ++ ++ /*Read RXS_FIL status to know the actual level that caused the interrupt */ ++ pDis->rxSenseStatus = (regVal & E_MASKREG_CEC_RXSHPDLEV_rxs_level) ? ++ HDMITX_RX_SENSE_ACTIVE : HDMITX_RX_SENSE_INACTIVE; ++ ++ /*Disable required Interrupts*/ ++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, &EnableIntMask); ++ EnableIntMask |= E_MASKREG_CEC_RXSHPDINTENA_ena_rxs_int; /* Enable RxSense Interrupt*/ ++ EnableIntMask |= E_MASKREG_CEC_RXSHPDINTENA_ena_hpd_int; /* Enable HPD Interrupt*/ ++ ++ /* Switch BSL State machine into UNINITIALIZED State */ ++ setState(pDis, EV_INIT); ++ ++ /*Write data in RXSHPD Register*/ ++ err += setCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, EnableIntMask); ++ err += getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&int_level); ++ ++ /* Enable HPD and RX sense IT after first call done by init function */ ++ gMiscInterruptHpdRxEnable = True; ++ ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989PowerGetState */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++tmbslTDA9989PowerGetState ++( ++ tmUnitSelect_t txUnit, ++ tmPowerState_t *pePowerState ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check remaining parameters */ ++ RETIF_BADPARAM(pePowerState == (tmPowerState_t)0) ++ ++ /*return parameter*/ ++ *pePowerState = (tmPowerState_t) pDis->ePowerState; ++ ++ return TM_OK; ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989PowerSetState */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989PowerSetState ++( ++ tmUnitSelect_t txUnit, ++ tmPowerState_t ePowerState ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 RegVal = 0; /* Local Variable */ ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ if (ePowerState == tmPowerOff) { ++ ePowerState = tmPowerStandby; ++ } ++ ++ ++ /* Check remaining parameters */ ++ RETIF_BADPARAM((ePowerState != tmPowerStandby) ++ &&(ePowerState != tmPowerSuspend) ++ &&(ePowerState != tmPowerOn) ++ ) ++ ++ if ((ePowerState == tmPowerStandby)&&(pDis->ePowerState != tmPowerStandby)) ++ { ++ /*Disable HPD and RxSense Interrupts*/ ++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, &RegVal); ++ RegVal &= ~E_MASKREG_CEC_RXSHPDINTENA_ena_hpd_int; ++ RegVal &= ~E_MASKREG_CEC_RXSHPDINTENA_ena_rxs_int; ++ err += setCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, RegVal); ++ err += getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&int_level); ++ RETIF_REG_FAIL(err) ++ ++ /* Disable if coming from ACTIVE */ ++ if (pDis->ePowerState == tmPowerOn) ++ { ++ ++ /* Disable audio and video ports */ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_AP_RW, ++ 0x00); /* 0: disable */ ++ RETIF_REG_FAIL(err) ++ ++ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_VP_0_RW, ++ 0x00); /* 0: disable */ ++ RETIF_REG_FAIL(err) ++ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_VP_1_RW, ++ 0x00); /* 0: disable */ ++ RETIF_REG_FAIL(err) ++ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_VP_2_RW, ++ 0x00); /* 0: disable */ ++ RETIF_REG_FAIL(err) ++ ++ /* Disable DDC */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_DDC_DISABLE_RW, ++ E_MASKREG_P00_DDC_DISABLE_ddc_dis, ++ 1); /* 1: disable */ ++ RETIF_REG_FAIL(err); ++ ++#ifdef TMFL_HDCP_OPTIMIZED_POWER ++ /* power down clocks */ ++ tmbslTDA9989HdcpPowerDown(txUnit,True); ++ err = setHwRegisterField(pDis, E_REG_FEAT_POWER_DOWN, \ ++ E_MASKREG_FEAT_POWER_DOWN_all, \ ++ 0x0F); ++#endif ++ } ++ ++ /*Disable HDMI and RxSense Modes AND FRO if required*/ ++ err = getCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, &RegVal); ++ RegVal &= ~E_MASKREG_CEC_ENAMODS_ena_hdmi; /* Reset HDMI Mode*/ ++ ++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, RegVal); ++ RETIF_REG_FAIL(err) ++ ++ err = getCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, &RegVal); ++ RETIF_REG_FAIL(err) ++ RegVal |= E_MASKREG_CEC_ENAMODS_ena_hdmi; /* Set HDMI Mode*/ ++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, RegVal); ++ RETIF_REG_FAIL(err) ++ ++ err = getCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, &RegVal); ++ RegVal &= ~E_MASKREG_CEC_ENAMODS_ena_hdmi; /* Reset HDMI Mode*/ ++ ++ RegVal &= ~E_MASKREG_CEC_ENAMODS_ena_rxs; /* Reset RxSense Mode*/ ++ ++ ++ /* disable FRO */ ++ RegVal |= E_MASKREG_CEC_ENAMODS_dis_fro; ++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, RegVal); ++ RETIF_REG_FAIL(err) ++ ++ ++ /*Send STANDBY event to the BSL State Machine */ ++ setState(pDis, EV_STANDBY); ++ } ++ else if ((ePowerState == tmPowerSuspend)&&(pDis->ePowerState != tmPowerSuspend)) ++ { ++ ++ /* Disable if coming from ACTIVE */ ++ if (pDis->ePowerState == tmPowerOn) ++ { ++ /* Disable audio and video ports */ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_AP_RW, ++ 0x00); /* 0: disable */ ++ RETIF_REG_FAIL(err) ++ ++ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_VP_0_RW, ++ 0x00); /* 0: disable */ ++ RETIF_REG_FAIL(err) ++ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_VP_1_RW, ++ 0x00); /* 0: disable */ ++ RETIF_REG_FAIL(err) ++ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_VP_2_RW, ++ 0x00); /* 0: disable */ ++ RETIF_REG_FAIL(err); ++ ++ /* Disable DDC */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_DDC_DISABLE_RW, ++ E_MASKREG_P00_DDC_DISABLE_ddc_dis, ++ 1); /* 1: disable */ ++ RETIF_REG_FAIL(err); ++ ++#ifdef TMFL_HDCP_OPTIMIZED_POWER ++ /* power down clocks */ ++ tmbslTDA9989HdcpPowerDown(txUnit,True); ++ err = setHwRegisterField(pDis, E_REG_FEAT_POWER_DOWN, \ ++ E_MASKREG_FEAT_POWER_DOWN_all, \ ++ 0x0F); ++#endif ++ } ++ ++ /*Enable RxSense Mode and Disable HDMI Mode*/ ++ err = getCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, &RegVal); ++ RegVal &= ~E_MASKREG_CEC_ENAMODS_ena_hdmi; /* Reset HDMI Mode*/ ++ RegVal |= E_MASKREG_CEC_ENAMODS_ena_rxs; /* Set RxSense Mode*/ ++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, RegVal); ++ RETIF_REG_FAIL(err) ++ ++ /*Enable HPD and RxS Interupt in case of the current Device Power States is STANDBY*/ ++ /*In other cases, those interrupts have already been enabled*/ ++ if(pDis->ePowerState == tmPowerStandby) ++ { ++ /* Enable FRO if coming from STANDBY */ ++ err = getCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, &RegVal); ++ RegVal &= ~E_MASKREG_CEC_ENAMODS_dis_fro; /* Enable FRO */ ++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, RegVal); ++ RETIF_REG_FAIL(err) ++ ++ /*Enable HPD and RxS Interupt*/ ++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, &RegVal); ++ RegVal |= E_MASKREG_CEC_RXSHPDINTENA_ena_hpd_int; /* Enable HPD Interrupt*/ ++ RegVal |= E_MASKREG_CEC_RXSHPDINTENA_ena_rxs_int; /* Enable RxSense Interrupt*/ ++ err += setCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, RegVal); ++ err += getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&int_level); ++ RETIF_REG_FAIL(err) ++ ++ /* force interrupt HPD and RXS level reading */ ++ err = tmbslTDA9989HwHandleInterrupt(txUnit); ++ RETIF(err != TM_OK, err) ++ ++ ++ } ++ ++ /*Send the SLEEP event to the BSL State Machine */ ++ setState(pDis, EV_SLEEP); ++ ++ } ++ ++ else if ((ePowerState == tmPowerOn)&&(pDis->ePowerState != tmPowerOn)) ++ { ++ ++ /* Enable RxSense HDMI Modes */ ++ err = getCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, &RegVal); ++ RegVal |= E_MASKREG_CEC_ENAMODS_ena_hdmi; /* Set HDMI Mode*/ ++ RegVal |= E_MASKREG_CEC_ENAMODS_ena_rxs; /* Set RxSense Mode*/ ++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, RegVal); ++ RETIF_REG_FAIL(err) ++ ++ /*Enable HPD and RxS Interupt in case of the current Device Power States is STANDBY*/ ++ /*In other cases, those interrupts have already been enabled*/ ++ if(pDis->ePowerState == tmPowerStandby) ++ { ++ /* Enable FRO if coming from STANDBY */ ++ err = getCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, &RegVal); ++ RegVal &= ~E_MASKREG_CEC_ENAMODS_dis_fro; /* Enable FRO */ ++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, RegVal); ++ RETIF_REG_FAIL(err) ++ ++ ++ /*Apply the required mode, Reset RxS and HDMI bits*/ ++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, &RegVal); ++ RegVal |= E_MASKREG_CEC_RXSHPDINTENA_ena_hpd_int; /* Enable HPD Interrupt*/ ++ RegVal |= E_MASKREG_CEC_RXSHPDINTENA_ena_rxs_int; /* Enable RxSense Interrupt*/ ++ err += setCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, RegVal); ++ err += getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&int_level); ++ RETIF_REG_FAIL(err) ++ } ++ ++ ++ /* Restore BIAS TMDS */ ++ RegVal = HDMI_TX_VSWING_VALUE; ++ err = setHwRegister(pDis, E_REG_P02_ANA_GENERAL_RW, RegVal); ++ RETIF(err != TM_OK, err) ++ ++ ++ err = tmbslTDA9989Reset(txUnit); ++ RETIF(err != TM_OK, err) ++ ++ ++ err = setHwRegisterField( pDis, E_REG_P00_VIP_CNTRL_4_W, E_MASKREG_P00_VIP_CNTRL_4_656_alt, 0); ++ ++ err = setHwRegister(pDis, E_REG_P12_TX3_RW, TDA19989_DDC_SPEED_FACTOR); ++ RETIF(err != TM_OK, err) ++ ++ /* TDA19989 N1 only */ ++ if (pDis->uDeviceVersion == E_DEV_VERSION_TDA19989) { ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_I2C_MASTER_RW, ++ E_MASKREG_P00_I2C_MASTER_dis_mm, ++ 0); ++ RETIF_REG_FAIL(err) ++ ++ } /* TDA19989 N1 only */ ++ ++ err = setCECHwRegister(pDis, E_REG_CEC_FRO_IM_CLK_CTRL_RW, E_MASKREG_CEC_FRO_IM_CLK_CTRL_ghost_dis | E_MASKREG_CEC_FRO_IM_CLK_CTRL_imclk_sel); ++ RETIF_REG_FAIL(err) ++ ++#ifdef TMFL_HDCP_SUPPORT ++ if (pDis->HdcpSeed) { ++ err = tmbslTDA9989HdcpDownloadKeys(txUnit, pDis->HdcpSeed, HDMITX_HDCP_DECRYPT_ENABLE); ++ } ++#endif /* TMFL_HDCP_SUPPORT */ ++ ++ ++ /* Enable DDC */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_DDC_DISABLE_RW, ++ E_MASKREG_P00_DDC_DISABLE_ddc_dis, ++ 0); /* 0: enable */ ++ RETIF_REG_FAIL(err) ++ ++ /* Enable audio and video ports */ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_AP_RW, ++ 0xFF); /* 1: enable */ ++ RETIF_REG_FAIL(err) ++ ++ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_VP_0_RW, ++ 0xFF); /* 1: enable */ ++ RETIF_REG_FAIL(err) ++ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_VP_1_RW, ++ 0xFF); /* 1: enable */ ++ RETIF_REG_FAIL(err) ++ ++ err = setHwRegister(pDis, ++ E_REG_P00_ENA_VP_2_RW, ++ 0xFF); /* 1: enable */ ++ RETIF_REG_FAIL(err) ++ ++ ++ /*Send the Hot Plug detection status event to the BSL State Machine */ ++ if (pDis->hotPlugStatus == HDMITX_HOTPLUG_ACTIVE) ++ { ++ setState(pDis, EV_PLUGGEDIN); ++ } ++ else ++ { ++ setState(pDis, EV_UNPLUGGED); ++ } ++ ++ } ++ ++ /* Set the current Device Power status to the required Power Status */ ++ pDis->ePowerState = (tmbslHdmiTxPowerState_t) ePowerState; ++ ++ ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989Reset */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989Reset ++( ++ tmUnitSelect_t txUnit ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to its object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Reset I2C master and Audio*/ ++ (void)setHwRegisterField(pDis, E_REG_P00_SR_REG_W, ++ E_MASKREG_P00_SR_REG_sr_i2c_ms | ++ E_MASKREG_P00_SR_REG_sr_audio, 1); ++ ++ pDis->sysFuncTimer(50); /* ms */ ++ ++ (void)setHwRegisterField(pDis, E_REG_P00_SR_REG_W, ++ E_MASKREG_P00_SR_REG_sr_i2c_ms | ++ E_MASKREG_P00_SR_REG_sr_audio, 0); ++ ++ pDis->sysFuncTimer(50); /* ms */ ++ ++ /* Write to the transmitter to do a soft reset. Don't abort after any ++ * error here, to ensure full reset. ++ */ ++ (void)setHwRegisterField(pDis, E_REG_P00_MAIN_CNTRL0_RW, ++ E_MASKREG_P00_MAIN_CNTRL0_sr, 1); ++ /* pDis->sysFuncTimer(50); */ /* ms */ ++ (void)setHwRegisterField(pDis, E_REG_P00_MAIN_CNTRL0_RW, ++ E_MASKREG_P00_MAIN_CNTRL0_sr, 0); ++ /* pDis->sysFuncTimer(50); */ /* ms */ ++ /* Clear any colourbars */ ++ (void)setHwRegisterField(pDis, E_REG_P00_HVF_CNTRL_0_W, ++ E_MASKREG_P00_HVF_CNTRL_0_sm, 0); ++ ++#ifdef TMFL_HDCP_SUPPORT ++ /* Disable any scheduled function and HDCP check timer */ ++ pDis->HdcpFuncRemainingMs = 0; ++ pDis->HdcpCheckNum = 0; ++#endif /* TMFL_HDCP_SUPPORT */ ++ ++ /* Switch BSL State machine into UNINITIALIZED State */ ++ setState(pDis, EV_DEINIT); ++ /* Switch Power State into STAND_BY State */ ++ //pDis->ePowerState = tmPowerStandby; ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989SwGetVersion */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989SwGetVersion ++( ++ ptmSWVersion_t pSWVersion ++) ++{ ++ /* Check parameters */ ++ RETIF_BADPARAM(pSWVersion == (ptmSWVersion_t)0) ++ ++ /* Get the version details of the component. */ ++ pSWVersion->compatibilityNr = HDMITX_BSL_COMP_NUM; ++ pSWVersion->majorVersionNr = HDMITX_BSL_MAJOR_VER; ++ pSWVersion->minorVersionNr = HDMITX_BSL_MINOR_VER; ++ ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989SysTimerWait */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989SysTimerWait ++( ++ tmUnitSelect_t txUnit, ++ UInt16 waitMs ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Return if this device timer is not set up */ ++ RETIF(!pDis->sysFuncTimer, TMBSL_ERR_HDMI_NOT_INITIALIZED) ++ ++ /* Wait for the requested time */ ++ pDis->sysFuncTimer(waitMs); ++ ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989TestSetMode */ ++/*============================================================================*/ ++ ++tmErrorCode_t ++tmbslTDA9989TestSetMode ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxTestMode_t testMode, ++ tmbslHdmiTxTestState_t testState ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ /* Register used to activate a test */ ++ UInt16 testReg = E_REG_P00_VIP_CNTRL_4_W; ++ /* Register bitfield mask used */ ++ UInt8 testMask = E_MASKREG_P00_VIP_CNTRL_4_tst_pat; ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM(testMode >= HDMITX_TESTMODE_INVALID) ++ RETIF_BADPARAM(testState >= HDMITX_TESTSTATE_INVALID) ++ ++ /* Set the mode selected by testMode to the state indicated by testState */ ++ switch (testMode) ++ { ++ case HDMITX_TESTMODE_PAT: ++ testReg = E_REG_P00_VIP_CNTRL_4_W; ++ testMask = E_MASKREG_P00_VIP_CNTRL_4_tst_pat; ++ break; ++ case HDMITX_TESTMODE_656: ++ testReg = E_REG_P00_VIP_CNTRL_4_W; ++ testMask = E_MASKREG_P00_VIP_CNTRL_4_tst_656; ++ break; ++ case HDMITX_TESTMODE_SERPHOE: ++ /*testReg = E_REG_P02_TEST1_RW; ++ testMask = E_MASKREG_P02_TEST1_tstserphoe;*/ ++ break; ++ case HDMITX_TESTMODE_NOSC: ++ testReg = E_REG_P02_TEST1_RW; ++ testMask = E_MASKREG_P02_TEST1_tst_nosc; ++ break; ++ case HDMITX_TESTMODE_HVP: ++ /*testReg = E_REG_P02_TEST1_RW; ++ testMask = E_MASKREG_P02_TEST1_tst_hvp;*/ ++ break; ++ case HDMITX_TESTMODE_PWD: ++ /*testReg = E_REG_P02_TEST2_RW; ++ testMask = E_MASKREG_P02_TEST2_pwd1v8;*/ ++ break; ++ case HDMITX_TESTMODE_DIVOE: ++ /*testReg = E_REG_P02_TEST2_RW; ++ testMask = E_MASKREG_P02_TEST2_divtestoe;*/ ++ break; ++ case HDMITX_TESTMODE_INVALID: ++ break; ++ } ++ err = setHwRegisterField(pDis, testReg, testMask, (UInt8)testState); ++ return err; ++} ++ ++/*============================================================================*/ ++/** ++ \brief Fill Gamut metadata packet into one of the gamut HW buffer. this ++ function is not sending any gamut metadata into the HDMI stream, ++ it is only loading data into the HW. ++ ++ \param txUnit Transmitter unit number ++ \param pPkt pointer to the gamut packet structure ++ \param bufSel number of the gamut buffer to fill ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMBSL_ERR_BSLHDMIRX_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMBSL_ERR_BSLHDMIRX_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMBSL_ERR_BSLHDMIRX_I2C_WRITE: failed when writing to the I2C ++ bus ++ ++ ******************************************************************************/ ++tmErrorCode_t tmbslTDA9989PktFillGamut ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxPktGamut_t *pPkt, ++ UInt8 bufSel ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM((bufSel != 0) && (bufSel != 1)) ++ ++ /* Fill Gamut registers*/ ++ /*Fill buffer 0*/ ++ if(bufSel == 0) ++ { ++ /*Write Header*/ ++ err = setHwRegisters(pDis, E_REG_P13_GMD_0_HB0_RW, &pPkt->HB[0], 3); ++ RETIF(err != TM_OK, err) ++ /*Write Payload*/ ++ err = setHwRegisters(pDis, E_REG_P13_GMD_0_PB0_RW, &pPkt->PB[0], 28); ++ RETIF(err != TM_OK, err) ++ } ++ ++ /*Fill buffer 1*/ ++ else ++ { ++ /*Write Header*/ ++ err = setHwRegisters(pDis, E_REG_P13_GMD_1_HB0_RW, &pPkt->HB[0], 3); ++ RETIF(err != TM_OK, err) ++ /*Write Payload*/ ++ err = setHwRegisters(pDis, E_REG_P13_GMD_1_PB0_RW, &pPkt->PB[0], 28); ++ RETIF(err != TM_OK, err) ++ } ++ ++return err; ++} ++ ++/*============================================================================*/ ++/** ++ \brief Enable transmission of gamut metadata packet. Calling this function ++ tells HW which gamut buffer to send into the HDMI stream. HW will ++ only take into account this command at the next VS, not during the ++ current one. ++ ++ \param txUnit Transmitter unit number ++ \param bufSel Number of the gamut buffer to be sent ++ \param enable Enable/disable gamut packet transmission ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMBSL_ERR_BSLHDMIRX_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMBSL_ERR_BSLHDMIRX_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMBSL_ERR_BSLHDMIRX_I2C_WRITE: failed when writing to the I2C ++ bus ++ ++ ******************************************************************************/ ++tmErrorCode_t tmbslTDA9989PktSendGamut ++( ++ tmUnitSelect_t txUnit, ++ UInt8 bufSel, ++ Bool bEnable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 GMD_Ctrl_Val; /*GMD control Value*/ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM((bufSel != 0) && (bufSel != 1)) ++ ++ /*Init Value*/ ++ GMD_Ctrl_Val = 0x00; ++ ++ /*Enable Send of Gamut MetaData*/ ++ if(bEnable) ++ { ++ /*Send Buffer 0*/ ++ if(bufSel == 0) ++ { ++ GMD_Ctrl_Val |= E_MASKREG_P13_GMD_CONTROL_enable; ++ GMD_Ctrl_Val &= ~E_MASKREG_P13_GMD_CONTROL_buf_sel; ++ err = setHwRegister(pDis, E_REG_P13_GMD_CONTROL_RW, GMD_Ctrl_Val); ++ RETIF(err != TM_OK, err) ++ } ++ /*Send Buffer 1*/ ++ else ++ { ++ GMD_Ctrl_Val |= E_MASKREG_P13_GMD_CONTROL_enable; ++ GMD_Ctrl_Val |= E_MASKREG_P13_GMD_CONTROL_buf_sel; ++ err = setHwRegister(pDis, E_REG_P13_GMD_CONTROL_RW, GMD_Ctrl_Val); ++ RETIF(err != TM_OK, err) ++ } ++ } ++ /*Disable Send of Gamut MetaData*/ ++ else ++ { ++ GMD_Ctrl_Val &= ~E_MASKREG_P13_GMD_CONTROL_enable; ++ GMD_Ctrl_Val &= ~E_MASKREG_P13_GMD_CONTROL_buf_sel; ++ err = setHwRegister(pDis, E_REG_P13_GMD_CONTROL_RW, GMD_Ctrl_Val); ++ RETIF(err != TM_OK, err) ++ } ++ ++ return err; ++} ++ ++ ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989EnableCallback */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989EnableCallback ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxCallbackInt_t callbackSource, ++ Bool enable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err = TM_OK; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM( callbackSource >= HDMITX_CALLBACK_INT_NUM ) ++ ++ switch (callbackSource) ++ { ++ case HDMITX_CALLBACK_INT_VS_RPT: ++ /* Enable or disable VS Interrupt */ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_INT_FLAGS_1_RW, ++ E_MASKREG_P00_INT_FLAGS_1_vs_rpt, ++ (UInt8)enable); ++ if (enable) ++ { ++ pDis->InterruptsEnable |= (1 << callbackSource); ++ } ++ else ++ { ++ pDis->InterruptsEnable &= ~(1 << callbackSource); ++ } ++ break; ++ default: ++ err = TMBSL_ERR_HDMI_NOT_SUPPORTED; ++ break; ++ } ++ ++ return err; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989SetColorDepth */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989SetColorDepth ++( ++ tmUnitSelect_t txUnit, ++ tmbslHdmiTxColorDepth colorDepth, ++ Bool termEnable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err = TM_OK; /* Error code */ ++ ++ DUMMY_ACCESS(termEnable); ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Check parameters */ ++ RETIF_BADPARAM( colorDepth >= HDMITX_COLORDEPTH_INVALID ) ++ ++ switch (colorDepth) ++ { ++ case HDMITX_COLORDEPTH_NO_CHANGE: ++ break; ++ ++ case HDMITX_COLORDEPTH_24: ++ ++ break; ++ ++ default: ++ err = TMBSL_ERR_HDMI_NOT_SUPPORTED; ++ break; ++ } ++ ++ return err; ++ ++} ++ ++ ++/*============================================================================*/ ++/* tmbslTDA9989Set5vpower */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989Set5vpower ++( ++ tmUnitSelect_t txUnit, ++ Bool pwrEnable ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ DUMMY_ACCESS(pwrEnable); ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++/*============================================================================*/ ++/* tmbslTDA9989SetDefaultPhase */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989SetDefaultPhase ++( ++ tmUnitSelect_t txUnit, ++ Bool bEnable, ++ tmbslHdmiTxColorDepth colorDepth, ++ UInt8 videoFormat ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ DUMMY_ACCESS(bEnable); ++ DUMMY_ACCESS(colorDepth); ++ DUMMY_ACCESS(videoFormat); ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ return TMBSL_ERR_HDMI_NOT_SUPPORTED; ++} ++ ++ ++ ++/*============================================================================*/ ++/* tmbslDebugWriteFakeRegPage */ ++/*============================================================================*/ ++tmErrorCode_t tmbslDebugWriteFakeRegPage( tmUnitSelect_t txUnit ) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ err = checkUnitSetDis(txUnit, &pDis); ++ ++ pDis->curRegPage = 0x20; ++ ++ return err; ++} ++ ++ ++/*============================================================================*/ ++/* hotPlugRestore */ ++/*============================================================================*/ ++tmErrorCode_t hotPlugRestore ( tmUnitSelect_t txUnit ) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regVal; ++ UInt8 EnableIntMask = 0; /* Mask used to enable HPD and RX Sense interrupt*/ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Set the BIAS_tmds Value */ ++ regVal = HDMI_TX_VSWING_VALUE; ++ err = setHwRegister(pDis, E_REG_P02_ANA_GENERAL_RW, regVal); ++ RETIF(err != TM_OK, err) ++ ++ /* PLL registers common configuration */ ++ err = setHwRegisterFieldTable(pDis, &kCommonPllCfg[0]); ++ RETIF_REG_FAIL(err) ++ ++ /*Reset 656_Alt bit in VIP_CONTROL_4 Register*/ ++ err = setHwRegisterField( pDis, E_REG_P00_VIP_CNTRL_4_W, E_MASKREG_P00_VIP_CNTRL_4_656_alt, 0); ++ ++ /* DDC interface is disable for TDA9989 after reset, enable it */ ++ err = setHwRegister(pDis, E_REG_P00_DDC_DISABLE_RW, 0x00); ++ RETIF(err != TM_OK, err) ++ ++ err = setHwRegister(pDis, E_REG_P12_TX3_RW, TDA19989_DDC_SPEED_FACTOR); ++ RETIF(err != TM_OK, err) ++ ++ /* TDA19989 N1 only */ ++ if (pDis->uDeviceVersion == E_DEV_VERSION_TDA19989) { ++ ++ err = setHwRegisterField(pDis, ++ E_REG_P00_I2C_MASTER_RW, ++ E_MASKREG_P00_I2C_MASTER_dis_mm, ++ 0); /* 0: enable multi master mode */ ++ RETIF_REG_FAIL(err) ++ ++ } /* TDA19989 N1 only */ ++ ++ ++ err = setCECHwRegister(pDis, E_REG_CEC_FRO_IM_CLK_CTRL_RW, E_MASKREG_CEC_FRO_IM_CLK_CTRL_ghost_dis | E_MASKREG_CEC_FRO_IM_CLK_CTRL_imclk_sel); ++ RETIF_REG_FAIL(err) ++ ++ ++ ++ ++ /* enable sw_interrupt for debug */ ++ err = setHwRegister(pDis, E_REG_P00_INT_FLAGS_1_RW, ++ E_MASKREG_P00_INT_FLAGS_1_sw_int); ++ ++ /* enable edid read */ ++ err = setHwRegister(pDis, E_REG_P00_INT_FLAGS_2_RW, ++ E_MASKREG_P00_INT_FLAGS_2_edid_blk_rd); ++ ++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, &EnableIntMask); ++ EnableIntMask |= E_MASKREG_CEC_RXSHPDINTENA_ena_rxs_int; /* Enable RxSense Interrupt*/ ++ EnableIntMask |= E_MASKREG_CEC_RXSHPDINTENA_ena_hpd_int; /* Enable HPD Interrupt*/ ++ err += setCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, EnableIntMask); ++ err += getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&int_level); ++ ++#ifdef TMFL_HDCP_SUPPORT ++ ++ if (pDis->HdcpSeed) ++ { ++ err = tmbslTDA9989HdcpDownloadKeys(txUnit, pDis->HdcpSeed, HDMITX_HDCP_DECRYPT_ENABLE); ++ } ++ ++#endif /* TMFL_HDCP_SUPPORT */ ++ ++ setState(pDis, EV_INIT); ++ ++ return err; ++} ++ ++#ifdef TMFL_TDA9989_PIXEL_CLOCK_ON_DDC ++ ++tmErrorCode_t hotPlugRestore ( tmUnitSelect_t txUnit ) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regVal; ++ UInt8 EnableIntMask = 0; /* Mask used to enable HPD and RX Sense interrupt*/ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err) ++ ++ /* Set the BIAS_tmds Value */ ++ regVal = HDMI_TX_VSWING_VALUE; ++ err = setHwRegister(pDis, E_REG_P02_ANA_GENERAL_RW, regVal); ++ RETIF(err != TM_OK, err) ++ ++ /* PLL registers common configuration */ ++ err = setHwRegisterFieldTable(pDis, &kCommonPllCfg[0]); ++ RETIF_REG_FAIL(err) ++ ++ /*Reset 656_Alt bit in VIP_CONTROL_4 Register*/ ++ err = setHwRegisterField( pDis, E_REG_P00_VIP_CNTRL_4_W, E_MASKREG_P00_VIP_CNTRL_4_656_alt, 0); ++ ++ /* DDC interface is disable for TDA9989 after reset, enable it */ ++ err = setHwRegister(pDis, E_REG_P00_DDC_DISABLE_RW, 0x00); ++ RETIF(err != TM_OK, err) ++ ++ ++ ++ if ( (pDis->vinFmt != HDMITX_VFMT_NO_CHANGE) && (pDis->vinFmt <= HDMITX_VFMT_TV_MAX ) ) { ++ ++ err = setHwRegister(pDis, E_REG_P00_TIMER_H_W, 0); ++ RETIF(err != TM_OK, err) ++ ++ err = setHwRegister(pDis, E_REG_P00_NDIV_IM_W, kndiv_im[pDis->vinFmt]); ++ RETIF(err != TM_OK, err) ++ ++ err = setHwRegister(pDis, E_REG_P12_TX3_RW, kclk_div[pDis->vinFmt]); ++ RETIF(err != TM_OK, err) ++ ++ } ++ else if (pDis->vinFmt > HDMITX_VFMT_TV_MAX) { ++ ++ err = setHwRegister(pDis, E_REG_P00_TIMER_H_W, E_MASKREG_P00_TIMER_H_im_clksel); ++ RETIF(err != TM_OK, err) ++ err = setHwRegister(pDis, E_REG_P12_TX3_RW, 17); ++ RETIF(err != TM_OK, err) ++ } ++ ++ ++ ++ ++ ++ /* enable sw_interrupt for debug */ ++ err = setHwRegister(pDis, E_REG_P00_INT_FLAGS_1_RW, ++ E_MASKREG_P00_INT_FLAGS_1_sw_int); ++ ++ /* enable edid read */ ++ err = setHwRegister(pDis, E_REG_P00_INT_FLAGS_2_RW, ++ E_MASKREG_P00_INT_FLAGS_2_edid_blk_rd); ++ ++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, &EnableIntMask); ++ EnableIntMask |= E_MASKREG_CEC_RXSHPDINTENA_ena_rxs_int; /* Enable RxSense Interrupt*/ ++ EnableIntMask |= E_MASKREG_CEC_RXSHPDINTENA_ena_hpd_int; /* Enable HPD Interrupt*/ ++ err += setCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, EnableIntMask); ++ err += getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&int_level); ++ ++ return err; ++} ++ ++#endif /* TMFL_TDA9989_PIXEL_CLOCK_ON_DDC */ ++ ++#ifdef TMFL_HDCP_OPTIMIZED_POWER ++/*============================================================================*/ ++/* tmbslTDA9989HdcpPowerDown */ ++/* RETIF_REG_FAIL NOT USED HERE AS ALL ERRORS SHOULD BE TRAPPED IN ALL BUILDS */ ++/*============================================================================*/ ++tmErrorCode_t ++tmbslTDA9989HdcpPowerDown ++( ++ tmUnitSelect_t txUnit, ++ Bool requested ++) ++{ ++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */ ++ tmErrorCode_t err; /* Error code */ ++ ++ /* Check unit parameter and point to TX unit object */ ++ err = checkUnitSetDis(txUnit, &pDis); ++ RETIF(err != TM_OK, err); ++ ++ err = setHwRegisterField(pDis, E_REG_P12_TX4_RW, \ ++ E_MASKREG_P12_TX4_pd_all, \ ++ (requested?0x07:0x00)); ++ return err; ++ ++} ++#endif ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc_l.h b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc_l.h +new file mode 100755 +index 0000000..990ee5c +--- /dev/null ++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc_l.h +@@ -0,0 +1,62 @@ ++/** ++ * Copyright (C) 2009 Koninklijke Philips Electronics N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of Koninklijke Philips Electronics N.V. and is confidential in ++ * nature. Under no circumstances is this software to be exposed to or placed ++ * under an Open Source License of any type without the expressed written ++ * permission of Koninklijke Philips Electronics N.V. ++ * ++ * \file tmbslTDA9989_Misc_l.h ++ * ++ * \version $Revision: 2 $ ++ * ++*/ ++ ++#ifndef TMBSLTDA9989_MISC_L_H ++#define TMBSLTDA9989_MISC_L_H ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*============================================================================*/ ++/* MACRO DEFINITIONS */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* ENUM OR TYPE DEFINITIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* EXTERN DATA DEFINITION */ ++/*============================================================================*/ ++ ++#ifdef TMFL_TDA9989_PIXEL_CLOCK_ON_DDC ++extern CONST_DAT UInt8 kndiv_im[]; ++extern CONST_DAT UInt8 kclk_div[]; ++#endif /* TMFL_TDA9989_PIXEL_CLOCK_ON_DDC */ ++ ++ ++/*============================================================================*/ ++/* EXTERN FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++ ++tmErrorCode_t hotPlugRestore ( tmUnitSelect_t txUnit ); ++ ++#ifdef TMFL_TDA9989_PIXEL_CLOCK_ON_DDC ++tmErrorCode_t hotPlugRestore ( tmUnitSelect_t txUnit ); ++#endif /* TMFL_TDA9989_PIXEL_CLOCK_ON_DDC */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMBSLTDA9989_MISC_L_H */ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_State.c b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_State.c +new file mode 100755 +index 0000000..887f8e1 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_State.c +@@ -0,0 +1,240 @@ ++/** ++ * Copyright (C) 2009 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmbslTDA9989_state.c ++ * ++ * \version $Revision: 2 $ ++ * ++*/ ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++#include ++#include ++#endif ++ ++#include "tmbslTDA9989_Functions.h" ++#include "tmbslTDA9989_local.h" ++#include "tmbslTDA9989_State_l.h" ++ ++ ++/*============================================================================*/ ++/* TYPES DECLARATIONS */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* CONSTANTS DECLARATIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* DEFINES DECLARATIONS */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* VARIABLES DECLARATIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* setState */ ++/*============================================================================*/ ++tmErrorCode_t ++setState ++( ++ tmHdmiTxobject_t *pDis, ++ tmbslTDA9989Event_t event ++) ++{ ++ tmbslTDA9989State_t state = pDis->state; ++ UInt8 nIgnoredEvents = pDis->nIgnoredEvents; ++ ++ switch (state) ++ { ++ case ST_UNINITIALIZED: ++ switch (event) ++ { ++ case EV_INIT: state = ST_STANDBY; break; ++ case EV_DEINIT: state = ST_UNINITIALIZED; break; ++ case EV_PLUGGEDIN: state = ST_AWAIT_EDID; break; ++ default: nIgnoredEvents++; break; ++ } ++ break; ++ ++ case ST_STANDBY: ++ switch (event) ++ { ++ case EV_UNPLUGGED: state = ST_DISCONNECTED; break; /*Only when PowerSetState(ON)*/ ++ case EV_PLUGGEDIN: state = ST_AWAIT_EDID; break; /*Only when PowerSetState(ON)*/ ++ case EV_SLEEP: state = ST_SLEEP; break; ++ case EV_DEINIT: state = ST_UNINITIALIZED; break; ++ case EV_SETINOUT: state = ST_VIDEO_NO_HDCP; break; ++ case EV_STANDBY: state = ST_STANDBY; break; ++ ++ default: nIgnoredEvents++; break; ++ } ++ break; ++ case ST_SLEEP: ++ switch (event) ++ { ++ case EV_UNPLUGGED: state = ST_DISCONNECTED; break; /*Only when PowerSetState(ON)*/ ++ case EV_PLUGGEDIN: state = ST_AWAIT_EDID; break; /*Only when PowerSetState(ON)*/ ++ case EV_DEINIT: state = ST_UNINITIALIZED; break; ++ case EV_STANDBY: state = ST_STANDBY; break; ++ default: nIgnoredEvents++; break; ++ } ++ break; ++ ++ case ST_DISCONNECTED: ++ switch (event) ++ { ++ case EV_PLUGGEDIN: state = ST_AWAIT_EDID; break; ++ case EV_DEINIT: state = ST_UNINITIALIZED; break; ++ case EV_STANDBY: state = ST_STANDBY; break; ++ case EV_SLEEP: state = ST_SLEEP; break; ++ default: nIgnoredEvents++; break; ++ } ++ break; ++ case ST_AWAIT_EDID: ++ switch (event) ++ { ++ case EV_GETBLOCKDATA: state = ST_AWAIT_RX_SENSE; break; ++ case EV_DEINIT: state = ST_UNINITIALIZED; break; ++ case EV_STANDBY: state = ST_STANDBY; break; ++ case EV_SLEEP: state = ST_SLEEP; break; ++ case EV_UNPLUGGED: state = ST_SLEEP; break; ++ default: nIgnoredEvents++; break; ++ } ++ break; ++ ++ case ST_AWAIT_RX_SENSE: ++ switch (event) ++ { ++ case EV_SINKON: state = ST_SINK_CONNECTED; break; ++ case EV_DEINIT: state = ST_UNINITIALIZED; break; ++ case EV_STANDBY: state = ST_STANDBY; break; ++ case EV_SLEEP: state = ST_SLEEP; break; ++ case EV_UNPLUGGED: state = ST_SLEEP; break; ++ default: nIgnoredEvents++; break; ++ } ++ break; ++ ++ case ST_SINK_CONNECTED: ++ switch (event) ++ { ++ case EV_SETINOUT: state = ST_VIDEO_NO_HDCP; break; ++ case EV_SINKOFF: state = ST_AWAIT_RX_SENSE; break; ++ case EV_DEINIT: state = ST_UNINITIALIZED; break; ++ case EV_STANDBY: state = ST_STANDBY; break; ++ case EV_SLEEP: state = ST_SLEEP; break; ++ case EV_UNPLUGGED: state = ST_SLEEP; break; ++ default: nIgnoredEvents++; break; ++ } ++ break; ++ case ST_VIDEO_NO_HDCP: ++ switch (event) ++ { ++ case EV_OUTDISABLE: state = ST_SINK_CONNECTED; break; ++ case EV_HDCP_RUN: state = ST_HDCP_WAIT_RX; break; ++ case EV_SINKOFF: state = ST_AWAIT_RX_SENSE; break; ++ case EV_DEINIT: state = ST_UNINITIALIZED; break; ++ case EV_STANDBY: state = ST_STANDBY; break; ++ case EV_SLEEP: state = ST_SLEEP; break; ++ case EV_UNPLUGGED: state = ST_SLEEP; break; ++ default: nIgnoredEvents++; break; ++ } ++ break; ++ case ST_HDCP_WAIT_RX: ++ switch (event) ++ { ++ case EV_HDCP_BKSV_NREPEAT: state = ST_HDCP_AUTHENTICATED;break; ++ case EV_HDCP_BKSV_REPEAT: state = ST_HDCP_WAIT_BSTATUS; break; ++ case EV_HDCP_BKSV_NSECURE: state = ST_HDCP_WAIT_RX; break; ++ case EV_HDCP_T0: state = ST_HDCP_WAIT_RX; break; ++ case EV_HDCP_STOP: state = ST_VIDEO_NO_HDCP; break; ++ case EV_SINKOFF: state = ST_AWAIT_RX_SENSE; break; ++ case EV_DEINIT: state = ST_UNINITIALIZED; break; ++ case EV_STANDBY: state = ST_STANDBY; break; ++ case EV_SLEEP: state = ST_SLEEP; break; ++ case EV_UNPLUGGED: state = ST_SLEEP; break; ++ default: nIgnoredEvents++; break; ++ } ++ break; ++ case ST_HDCP_WAIT_BSTATUS: ++ switch (event) ++ { ++ case EV_HDCP_BSTATUS_GOOD: state = ST_HDCP_WAIT_SHA_1; break; ++ case EV_HDCP_T0: state = ST_HDCP_WAIT_RX; break; ++ case EV_HDCP_STOP: state = ST_VIDEO_NO_HDCP; break; ++ case EV_SINKOFF: state = ST_AWAIT_RX_SENSE; break; ++ case EV_DEINIT: state = ST_UNINITIALIZED; break; ++ case EV_STANDBY: state = ST_STANDBY; break; ++ case EV_SLEEP: state = ST_SLEEP; break; ++ case EV_UNPLUGGED: state = ST_SLEEP; break; ++ default: nIgnoredEvents++; break; ++ } ++ break; ++ case ST_HDCP_WAIT_SHA_1: ++ switch (event) ++ { ++ case EV_HDCP_KSV_SECURE: state = ST_HDCP_AUTHENTICATED;break; ++ case EV_HDCP_T0: state = ST_HDCP_WAIT_RX; break; ++ case EV_HDCP_STOP: state = ST_VIDEO_NO_HDCP; break; ++ case EV_SINKOFF: state = ST_AWAIT_RX_SENSE; break; ++ case EV_DEINIT: state = ST_UNINITIALIZED; break; ++ case EV_STANDBY: state = ST_STANDBY; break; ++ case EV_SLEEP: state = ST_SLEEP; break; ++ case EV_UNPLUGGED: state = ST_SLEEP; break; ++ default: nIgnoredEvents++; break; ++ } ++ break; ++ case ST_HDCP_AUTHENTICATED: ++ switch (event) ++ { ++ case EV_HDCP_T0: state = ST_HDCP_WAIT_RX; break; ++ case EV_HDCP_STOP: state = ST_VIDEO_NO_HDCP; break; ++ case EV_SINKOFF: state = ST_AWAIT_RX_SENSE; break; ++ case EV_DEINIT: state = ST_UNINITIALIZED; break; ++ case EV_STANDBY: state = ST_STANDBY; break; ++ case EV_SLEEP: state = ST_SLEEP; break; ++ case EV_UNPLUGGED: state = ST_SLEEP; break; ++ default: nIgnoredEvents++; break; ++ } ++ break; ++ ++ case ST_INVALID: ++ nIgnoredEvents++; ++ break; ++ ++ default: ++ break; ++ } ++ ++ pDis->state = state; ++ pDis->nIgnoredEvents = nIgnoredEvents; ++ ++ if (nIgnoredEvents) ++ { ++ /* int cbeDebug = 1; */ ++ } ++ ++ return TM_OK; ++} ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++EXPORT_SYMBOL(setState); ++#endif ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_State_l.h b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_State_l.h +new file mode 100755 +index 0000000..c0e7857 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_State_l.h +@@ -0,0 +1,56 @@ ++/** ++ * Copyright (C) 2009 Koninklijke Philips Electronics N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of Koninklijke Philips Electronics N.V. and is confidential in ++ * nature. Under no circumstances is this software to be exposed to or placed ++ * under an Open Source License of any type without the expressed written ++ * permission of Koninklijke Philips Electronics N.V. ++ * ++ * \file tmbslTDA9989_State.h ++ * ++ * \version $Revision: 2 $ ++ * ++ * ++*/ ++ ++#ifndef TMBSLTDA9989_STATE_L_H ++#define TMBSLTDA9989_STATE_L_H ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*============================================================================*/ ++/* MACRO DEFINITIONS */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* ENUM OR TYPE DEFINITIONS */ ++/*============================================================================*/ ++ ++ ++ ++/*============================================================================*/ ++/* EXTERN DATA DEFINITION */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* EXTERN FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++ ++tmErrorCode_t setState (tmHdmiTxobject_t *pDis, tmbslTDA9989Event_t event); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMBSLTDA9989_STATE_L_H */ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local.c b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local.c +new file mode 100755 +index 0000000..9030ebc +--- /dev/null ++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local.c +@@ -0,0 +1,670 @@ ++/** ++ * Copyright (C) 2009 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmbslTDA9989_local.c ++ * ++ * \version $Revision: 2 $ ++ * ++ * ++*/ ++ ++/*============================================================================*/ ++/* FILE CONFIGURATION */ ++/*============================================================================*/ ++ ++/* Defining this symbol on the compiler command line excludes some API checks */ ++/* #define NO_RETIF_BADPARAM */ ++ ++/*============================================================================*/ ++/* STANDARD INCLUDE FILES */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* PROJECT INCLUDE FILES */ ++/*============================================================================*/ ++#include "tmbslHdmiTx_types.h" ++#include "tmbslTDA9989_Functions.h" ++#include "tmbslTDA9989_local.h" ++ ++/*============================================================================*/ ++/* MACRO DEFINITIONS */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* TYPE DEFINITIONS */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* PUBLIC VARIABLE DEFINITIONS */ ++/*============================================================================*/ ++ ++/** The array of object instances for all concurrently supported HDMI ++ * Transmitter units ++ */ ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++#ifdef USE_SHARED_HDMI_INSTANCE ++extern tmHdmiTxobject_t gHdmiTxInstance[HDMITX_UNITS_MAX]; ++#else ++#include ++#include ++RAM_DAT tmHdmiTxobject_t gHdmiTxInstance[HDMITX_UNITS_MAX]; ++EXPORT_SYMBOL(gHdmiTxInstance); ++#endif ++#else ++RAM_DAT tmHdmiTxobject_t gHdmiTxInstance[HDMITX_UNITS_MAX]; ++#endif ++ ++/** ++ * Lookup table to map register page index to actual page number ++ */ ++CONST_DAT UInt8 kPageIndexToPage[E_PAGE_NUM] = ++{ ++ 0x00, /* E_PAGE_00 */ ++ 0x01, /* E_PAGE_01 */ ++ 0x02, /* E_PAGE_02 */ ++ 0x09, /* E_PAGE_09 */ ++ 0x10, /* E_PAGE_10 */ ++ 0x11, /* E_PAGE_11 */ ++ 0x12, /* E_PAGE_12 */ ++ 0x13 /* E_PAGE_13 */ ++}; ++ ++ ++/*============================================================================*/ ++/* STATIC VARIABLE DECLARATIONS */ ++/*============================================================================*/ ++ ++/** ++ * Lookup table to map an 8-bit mask to a number of left shifts ++ * needed to shift a value starting at bit 0 onto the mask. ++ * Indexed by mask 0-255. For example, mask 0x00 and 0x01 need ++ * no shift, mask 0x02 needs one shift, mask 0x03 needs no shift, ++ * mask 0x04 needs 2 shifts, etc. ++ * Rows were formatted by "HDMI Driver - Register List.xls" and pasted here ++ */ ++static CONST_DAT UInt8 kMaskToShift[256] = ++{/* Mask index: */ ++ /*x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ ++ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x */ ++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 1x */ ++ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 2x */ ++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 3x */ ++ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 4x */ ++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 5x */ ++ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 6x */ ++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 7x */ ++ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 8x */ ++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 9x */ ++ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Ax */ ++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Bx */ ++ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Cx */ ++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Dx */ ++ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Ex */ ++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* Fx */ ++}; ++ ++/*============================================================================*/ ++/* STATIC FUNCTION DECLARATIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* PUBLIC FUNCTION DEFINITIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* checkUnitSetDis */ ++/*============================================================================*/ ++tmErrorCode_t ++checkUnitSetDis ++( ++ tmUnitSelect_t txUnit, ++ tmHdmiTxobject_t **ppDis ++) ++{ ++ /* Return error if unit numbr is out of range */ ++ RETIF(txUnit < tmUnit0, TMBSL_ERR_HDMI_BAD_UNIT_NUMBER) ++ RETIF(txUnit >= HDMITX_UNITS_MAX, TMBSL_ERR_HDMI_BAD_UNIT_NUMBER) ++ ++ /* Point to unit's Device Instance Structure */ ++ *ppDis = &gHdmiTxInstance[txUnit]; ++ ++ /* Return if this device instance is not initialised */ ++ if(!(*ppDis)->bInitialized) ++ { ++ return TMBSL_ERR_HDMI_NOT_INITIALIZED; ++ } ++ ++ return TM_OK; ++} ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++EXPORT_SYMBOL(checkUnitSetDis); ++#endif ++ ++/*============================================================================*/ ++/* getHwRegisters */ ++/*============================================================================*/ ++tmErrorCode_t ++getHwRegisters ++( ++ tmHdmiTxobject_t *pDis, ++ UInt16 regShadPageAddr, ++ UInt8 *pData, ++ UInt16 lenData ++ ) ++{ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regShad; /* The index to the register's shadow copy */ ++ UInt8 regPage; /* The index to the register's page */ ++ UInt8 regAddr; /* The register's address on the page */ ++ UInt8 newRegPage; /* The register's new page number */ ++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */ ++ ++ /* Unpack 1st register's shadow index, page index and address */ ++ regShad = SPA2SHAD(regShadPageAddr); ++ regPage = SPA2PAGE(regShadPageAddr); ++ regAddr = SPA2ADDR(regShadPageAddr); ++ newRegPage = kPageIndexToPage[regPage]; ++ ++ /* Check length does not overflow page */ ++ RETIF_BADPARAM((regAddr+lenData) > E_REG_CURPAGE_ADR_W) ++ ++ /* Check 1st reg does not have a shadow - whole range assumed likewise */ ++ RETIF_BADPARAM(regShad != E_SNONE) ++ ++ /* Set page register if required */ ++ if (pDis->curRegPage != newRegPage) ++ { ++ /* All non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = E_REG_CURPAGE_ADR_W; ++ sysArgs.lenData = 1; ++ sysArgs.pData = &newRegPage; ++ err = pDis->sysFuncWrite(&sysArgs); ++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE) ++ pDis->curRegPage = newRegPage; ++ } ++ ++ /* Get I2C register range - all non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = regAddr; ++ sysArgs.lenData = (UInt8)lenData; ++ sysArgs.pData = pData; ++ err = pDis->sysFuncRead(&sysArgs); ++ return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_READ; ++} ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++EXPORT_SYMBOL(getHwRegisters); ++#endif ++ ++/*============================================================================*/ ++/* getHwRegister */ ++/*============================================================================*/ ++tmErrorCode_t ++getHwRegister ++( ++ tmHdmiTxobject_t *pDis, ++ UInt16 regShadPageAddr, ++ UInt8 *pRegValue ++) ++{ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regShad; /* The index to the register's shadow copy */ ++ UInt8 regPage; /* The index to the register's page */ ++ UInt8 regAddr; /* The register's address on the page */ ++ UInt8 newRegPage; /* The register's new page number */ ++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */ ++ ++ /* Unpack register shadow index, page index and address */ ++ regShad = SPA2SHAD(regShadPageAddr); ++ regPage = SPA2PAGE(regShadPageAddr); ++ regAddr = SPA2ADDR(regShadPageAddr); ++ newRegPage = kPageIndexToPage[regPage]; ++ ++ /* Set page register if required */ ++ if (pDis->curRegPage != newRegPage) ++ { ++ /* All non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = E_REG_CURPAGE_ADR_W; ++ sysArgs.lenData = 1; ++ sysArgs.pData = &newRegPage; ++ err = pDis->sysFuncWrite(&sysArgs); ++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE) ++ pDis->curRegPage = newRegPage; ++ } ++ ++ if ((regShad != E_SNONE) ++ && (regShadPageAddr != E_REG_P00_INT_FLAGS_0_RW) ++ && (regShadPageAddr != E_REG_P00_INT_FLAGS_1_RW) ++ && (regShadPageAddr != E_REG_P00_INT_FLAGS_2_RW)) ++ { ++ /* Get shadow copy - shadowed registers can't be read */ ++ /* Don't read shadow copy of interrupt status flags! */ ++ *pRegValue = pDis->shadowReg[regShad]; ++ return TM_OK; ++ } ++ else ++ { ++ /* Get I2C register - all non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = regAddr; ++ sysArgs.lenData = 1; ++ sysArgs.pData = pRegValue; ++ err = pDis->sysFuncRead(&sysArgs); ++ return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_READ; ++ } ++} ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++EXPORT_SYMBOL(getHwRegister); ++#endif ++ ++/*============================================================================*/ ++/* setHwRegisters */ ++/*============================================================================*/ ++tmErrorCode_t ++setHwRegisters ++( ++ tmHdmiTxobject_t *pDis, ++ UInt16 regShadPageAddr, ++ UInt8 *pData, ++ UInt16 lenData ++ ) ++{ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regShad; /* The index to the register's shadow copy */ ++ UInt8 regPage; /* The index to the register's page */ ++ UInt8 regAddr; /* The register's address on the page */ ++ UInt8 newRegPage; /* The register's new page number */ ++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */ ++ ++ /* Unpack 1st register's shadow index, page index and address */ ++ regShad = SPA2SHAD(regShadPageAddr); ++ regPage = SPA2PAGE(regShadPageAddr); ++ regAddr = SPA2ADDR(regShadPageAddr); ++ newRegPage = kPageIndexToPage[regPage]; ++ ++ /* Check length does not overflow page */ ++ RETIF_BADPARAM((regAddr+lenData) > E_REG_CURPAGE_ADR_W) ++ ++ /* Check 1st reg does not have a shadow - whole range assumed likewise */ ++ RETIF_BADPARAM(regShad != E_SNONE) ++ ++ /* Set page register if required - whole range is on same page */ ++ if (pDis->curRegPage != newRegPage) ++ { ++ /* All non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = E_REG_CURPAGE_ADR_W; ++ sysArgs.lenData = 1; ++ sysArgs.pData = &newRegPage; ++ err = pDis->sysFuncWrite(&sysArgs); ++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE) ++ pDis->curRegPage = newRegPage; ++ } ++ ++ /* Write to I2C register range - all non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = regAddr; ++ sysArgs.lenData = (UInt8)lenData; ++ sysArgs.pData = pData; ++ err = pDis->sysFuncWrite(&sysArgs); ++ return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_WRITE; ++} ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++EXPORT_SYMBOL(setHwRegisters); ++#endif ++ ++ ++/*============================================================================*/ ++/* setHwRegisterMsbLsb */ ++/*============================================================================*/ ++tmErrorCode_t ++setHwRegisterMsbLsb ++( ++ tmHdmiTxobject_t *pDis, ++ UInt16 regShadPageAddr, ++ UInt16 regWord ++) ++{ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regPage; /* The index to the register's page */ ++ UInt8 regAddr; /* The register's address on the page */ ++ UInt8 newRegPage; /* The register's new page number */ ++ UInt8 msbLsb[2]; /* The bytes from regWord */ ++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */ ++ ++ /* Unpack register shadow index, page index and address */ ++ regPage = SPA2PAGE(regShadPageAddr); ++ regAddr = SPA2ADDR(regShadPageAddr); ++ newRegPage = kPageIndexToPage[regPage]; ++ ++ /* Unpack regWord bytes, MSB first */ ++ msbLsb[0] = (UInt8)(regWord >> 8); ++ msbLsb[1] = (UInt8)(regWord & 0xFF); ++ ++ /* Set page register if required */ ++ if (pDis->curRegPage != newRegPage) ++ { ++ /* All non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = E_REG_CURPAGE_ADR_W; ++ sysArgs.lenData = 1; ++ sysArgs.pData = &newRegPage; ++ err = pDis->sysFuncWrite(&sysArgs); ++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE) ++ pDis->curRegPage = newRegPage; ++ } ++ ++ /* No word registers are shadowed */ ++ ++ /* Write to I2C - all non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = regAddr; ++ sysArgs.lenData = 2; ++ sysArgs.pData = &msbLsb[0]; ++ err = pDis->sysFuncWrite(&sysArgs); ++ return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_WRITE; ++} ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++EXPORT_SYMBOL(setHwRegisterMsbLsb); ++#endif ++ ++/*============================================================================*/ ++/* setHwRegister */ ++/*============================================================================*/ ++tmErrorCode_t ++setHwRegister_main ++( ++ tmHdmiTxobject_t *pDis, ++ UInt16 regShadPageAddr, ++ UInt8 regValue ++) ++{ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regShad; /* The index to the register's shadow copy */ ++ UInt8 regPage; /* The index to the register's page */ ++ UInt8 regAddr; /* The register's address on the page */ ++ UInt8 newRegPage; /* The register's new page number */ ++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */ ++ ++ /* Unpack register shadow index, page index and address */ ++ regShad = SPA2SHAD(regShadPageAddr); ++ regPage = SPA2PAGE(regShadPageAddr); ++ regAddr = SPA2ADDR(regShadPageAddr); ++ newRegPage = kPageIndexToPage[regPage]; ++ ++ /* Set page register if required */ ++ if (pDis->curRegPage != newRegPage) ++ { ++ /* All non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = E_REG_CURPAGE_ADR_W; ++ sysArgs.lenData = 1; ++ sysArgs.pData = &newRegPage; ++ err = pDis->sysFuncWrite(&sysArgs); ++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE) ++ pDis->curRegPage = newRegPage; ++ } ++ ++ /* Set shadow copy */ ++ if (regShad != E_SNONE) ++ { ++ pDis->shadowReg[regShad] = regValue; ++ } ++ ++ /* Write to I2C - all non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = regAddr; ++ sysArgs.lenData = 1; ++ sysArgs.pData = ®Value; ++ err = pDis->sysFuncWrite(&sysArgs); ++ return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_WRITE; ++} ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++EXPORT_SYMBOL(setHwRegister_main); ++#endif ++ ++/*============================================================================*/ ++/* setHwRegisterField */ ++/*============================================================================*/ ++tmErrorCode_t ++setHwRegisterField ++( ++ tmHdmiTxobject_t *pDis, ++ UInt16 regShadPageAddr, ++ UInt8 fieldMask, ++ UInt8 fieldValue ++) ++{ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regShad; /* The index to the register's shadow copy */ ++ UInt8 regPage; /* The index to the register's page */ ++ UInt8 regAddr; /* The register's address on the page */ ++ UInt8 newRegPage; /* The register's new page number */ ++ UInt8 regValue; /* The register's current value */ ++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */ ++ ++ /* Unpack register shadow index, page index and address */ ++ regShad = SPA2SHAD(regShadPageAddr); ++ regPage = SPA2PAGE(regShadPageAddr); ++ regAddr = SPA2ADDR(regShadPageAddr); ++ newRegPage = kPageIndexToPage[regPage]; ++ ++ /* Set page register if required */ ++ if (pDis->curRegPage != newRegPage) ++ { ++ /* All non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = E_REG_CURPAGE_ADR_W; ++ sysArgs.lenData = 1; ++ sysArgs.pData = &newRegPage; ++ err = pDis->sysFuncWrite(&sysArgs); ++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE) ++ pDis->curRegPage = newRegPage; ++ } ++ ++ if (regShad != E_SNONE) ++ { ++ /* Get shadow copy */ ++ regValue = pDis->shadowReg[regShad]; ++ } ++ else ++ { ++ /* Read I2C register value. ++ * All bitfield registers are either shadowed or can be read. ++ */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = regAddr; ++ sysArgs.lenData = 1; ++ sysArgs.pData = ®Value; ++ err = pDis->sysFuncRead(&sysArgs); ++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_READ) ++ } ++ ++ /* Reset register bits that are set in the mask */ ++ regValue = regValue & (UInt8)(~fieldMask); ++ ++ /* Shift the field value left to align its bits with the mask */ ++ fieldValue <<= kMaskToShift[fieldMask]; ++ ++ /* Reset shifted field bits that are not set in the mask */ ++ fieldValue &= fieldMask; ++ ++ /* Set the shifted bitfield */ ++ regValue |= fieldValue; ++ ++ /* Set shadow copy */ ++ if (regShad != E_SNONE) ++ { ++ pDis->shadowReg[regShad] = regValue; ++ } ++ ++ /* Write to I2C - all non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->uHwAddress; ++ sysArgs.firstRegister = regAddr; ++ sysArgs.lenData = 1; ++ sysArgs.pData = ®Value; ++ err = pDis->sysFuncWrite(&sysArgs); ++ return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_WRITE; ++} ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++EXPORT_SYMBOL(setHwRegisterField); ++#endif ++ ++/*============================================================================*/ ++/* getCECHwRegister */ ++/*============================================================================*/ ++tmErrorCode_t ++getCECHwRegister ++( ++ tmHdmiTxobject_t *pDis, ++ UInt16 regAddr, ++ UInt8 *pRegValue ++) ++{ ++ tmErrorCode_t err; /* Error code */ ++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */ ++ UInt8 CECAddress; /* CEC Address deduced from uHwAddress */ ++ ++ /*Convert HwAddress into CEC Address*/ ++ CECAddress = pDis->uHwAddress; ++ CECAddress = CECAddress ^ 0x44; /*Convert address to obtain the correspondance in CEC*/ ++ /*CECAddress = ((~CECAddress & 0x44)||(CECAddress & 0xBB)); */ ++ /*Prepare Write operation*/ ++ sysArgs.slaveAddr = CECAddress; ++ sysArgs.firstRegister = (UInt8)regAddr; ++ sysArgs.lenData = 1; ++ sysArgs.pData = pRegValue; ++ ++ /*Read data in Chip*/ ++ err = pDis->sysFuncRead(&sysArgs); /* Call IC Read function*/ ++ ++ return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_READ; ++ ++} ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++EXPORT_SYMBOL(getCECHwRegister); ++#endif ++ ++/*============================================================================*/ ++/* setCECHwRegister */ ++/*============================================================================*/ ++tmErrorCode_t ++setCECHwRegister ++( ++ tmHdmiTxobject_t *pDis, ++ UInt16 regAddr, ++ UInt8 regValue ++) ++{ ++ tmErrorCode_t err; /* Error code */ ++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */ ++ UInt8 CECAddress; /* CEC Address deduced from uHwAddress */ ++ ++ /*Convert HwAddress into CEC Address*/ ++ CECAddress = pDis->uHwAddress; ++ CECAddress = CECAddress ^ 0x44; /*Convert address to obtain the correspondance in CEC*/ ++ ++ /*Prepare Write operation*/ ++ sysArgs.slaveAddr = CECAddress; ++ sysArgs.firstRegister = (UInt8)regAddr; ++ sysArgs.lenData = 1; ++ sysArgs.pData = ®Value; ++ ++ /*Write data in Chip*/ ++ err = pDis->sysFuncWrite(&sysArgs); /* Call IC Write function*/ ++ ++ return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_WRITE; ++} ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++EXPORT_SYMBOL(setCECHwRegister); ++#endif ++ ++/*============================================================================*/ ++/* setHwRegisterFieldTable */ ++/*============================================================================*/ ++tmErrorCode_t ++setHwRegisterFieldTable ++( ++ tmHdmiTxobject_t *pDis, ++ const tmHdmiTxRegMaskVal_t *pTable ++) ++{ ++ tmErrorCode_t err; /* Error code */ ++ Int i; /* Table index */ ++ ++ /* Set register, mask and value from table until terminator is reached */ ++ for (i = 0; pTable[i].Reg > 0; i++) ++ { ++ err = setHwRegisterField(pDis, pTable[i].Reg, pTable[i].Mask, pTable[i].Val); ++ RETIF(err != TM_OK, err) ++ } ++ return TM_OK; ++} ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++EXPORT_SYMBOL(setHwRegisterFieldTable); ++#endif ++ ++ ++/*============================================================================*/ ++/* lmemcpy */ ++/*============================================================================*/ ++tmErrorCode_t ++lmemcpy ++( ++ void *pTable1, ++ const void * pTable2, ++ UInt Size ++) ++{ ++ char *ptrSource = (char*) pTable1; ++ char *endSource = (char*)pTable1 + Size; ++ char *ptrDest = (char *)pTable2; ++ ++ RETIF_BADPARAM(pTable1 == Null) ++ RETIF_BADPARAM(pTable2 == Null) ++ ++ while (endSource > ptrSource) ++ { ++ *(ptrSource++) = *(ptrDest++); ++ } ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* lmemset */ ++/*============================================================================*/ ++tmErrorCode_t ++lmemset ++( ++ void *pTable1, ++ const UInt8 value, ++ UInt Size ++) ++{ ++ char *ptrSource = (char*) pTable1; ++ char *endSource = (char*)pTable1 + Size; ++ ++ RETIF_BADPARAM(pTable1 == Null) ++ ++ while (endSource > ptrSource) ++ { ++ *(ptrSource++) = value; ++ } ++ return TM_OK; ++} ++ ++/*============================================================================*/ ++/* STATIC FUNCTION DEFINTIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local.h b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local.h +new file mode 100755 +index 0000000..02843e2 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local.h +@@ -0,0 +1,2056 @@ ++/** ++ * Copyright (C) 2009 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmbslTDA9989_local.h ++ * ++ * \version %version: 3 % ++ * ++*/ ++ ++#ifndef TMBSLTDA9989_LOCAL_H ++#define TMBSLTDA9989_LOCAL_H ++#define setHwRegister(pDis, regShadPageAddr, regValue) setHwRegister_main(pDis, regShadPageAddr, regValue); printk("Setting " # regShadPageAddr "\n"); ++ ++/* ++ ++ INCLUDE FILES */ ++/*============================================================================*/ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*============================================================================*/ ++/* MACRO DEFINITIONS */ ++/*============================================================================*/ ++#ifndef DUMMY_ACCESS ++#ifdef _WINDOWS ++#define DUMMY_ACCESS(x) x ++#else ++#define DUMMY_ACCESS(x) ++#endif ++#endif /* DUMMY_ACCESS */ ++ ++/** \name Versions ++ * A group of macros to set the software component number and version ++ */ ++/*@{*/ ++/** Compatibility number */ ++#define HDMITX_BSL_COMP_NUM 1 ++ ++/** Major software version 1 to 255 */ ++#define HDMITX_BSL_MAJOR_VER 5 ++ ++/** Minor software version 0 to 9 */ ++#define HDMITX_BSL_MINOR_VER 4 ++/*@}*/ ++ ++/** \name ErrorChecks ++ * A group of checks ensuring that public error codes match DVP standard errors ++ */ ++/*@{*/ ++/** SW interface compatibility error */ ++#if TMBSL_ERR_HDMI_COMPATIBILITY != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_COMPATIBILITY) ++#error ++#endif ++ ++/** SW major version error */ ++#if TMBSL_ERR_HDMI_MAJOR_VERSION != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_MAJOR_VERSION) ++#error ++#endif ++ ++/** SW component version error */ ++#if TMBSL_ERR_HDMI_COMP_VERSION != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_COMP_VERSION) ++#error ++#endif ++ ++/** Invalid device unit number */ ++#if TMBSL_ERR_HDMI_BAD_UNIT_NUMBER != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_BAD_UNIT_NUMBER) ++#error ++#endif ++ ++/** Invalid input parameter other than unit number */ ++#if TMBSL_ERR_HDMI_BAD_PARAMETER != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_BAD_PARAMETER) ++#error ++#endif ++ ++/** Inconsistent input parameters */ ++#if TMBSL_ERR_HDMI_INCONSISTENT_PARAMS != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_INCONSISTENT_PARAMS) ++#error ++#endif ++ ++/** Component is not initialized */ ++#if TMBSL_ERR_HDMI_NOT_INITIALIZED != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_NOT_INITIALIZED) ++#error ++#endif ++ ++/** Command not supported for current device */ ++#if TMBSL_ERR_HDMI_NOT_SUPPORTED != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_NOT_SUPPORTED) ++#error ++#endif ++ ++/** Initialization failed */ ++#if TMBSL_ERR_HDMI_INIT_FAILED != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_INIT_FAILED) ++#error ++#endif ++ ++/** Component is busy and cannot do a new operation */ ++#if TMBSL_ERR_HDMI_BUSY != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_BUSY) ++#error ++#endif ++ ++/** I2C read error */ ++#if TMBSL_ERR_HDMI_I2C_READ != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_READ) ++#error ++#endif ++ ++/** I2C write error */ ++#if TMBSL_ERR_HDMI_I2C_WRITE != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_WRITE) ++#error ++#endif ++ ++/** Assertion failure */ ++#if TMBSL_ERR_HDMI_ASSERTION != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_ASSERTION) ++#error ++#endif ++ ++/** Bad EDID block checksum */ ++#if TMBSL_ERR_HDMI_INVALID_CHECKSUM != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_INVALID_STATE) ++#error ++#endif ++ ++/** No connection to HPD pin */ ++#if TMBSL_ERR_HDMI_NULL_CONNECTION != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_NULL_CONNECTION) ++#error ++#endif ++ ++/** Not allowed in DVI mode */ ++#if TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_OPERATION_NOT_PERMITTED) ++#error ++#endif ++ ++/** Ressource not available*/ ++#if TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE != \ ++(TMBSL_ERR_HDMI_BASE + TM_ERR_NO_RESOURCES) ++#error ++#endif ++ ++ ++/*@}*/ ++ ++/** ++ * A macro to check a condition and if true return a result ++ */ ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++#include ++#define RETIF(cond, rslt) if ((cond)){printk(KERN_INFO "%s %d\n",__func__,__LINE__);return (rslt);} ++#else ++#define RETIF(cond, rslt) if ((cond)){return (rslt);} ++#endif ++ ++/** ++ * A macro to check a condition and if true return ++ * TMBSL_ERR_HDMI_BAD_PARAMETER. ++ * To save code space, it can be compiled out by defining NO_RETIF_BADPARAM on ++ * the compiler command line. ++ */ ++#ifdef NO_RETIF_BADPARAM ++#define RETIF_BADPARAM(cond) ++#else ++#define RETIF_BADPARAM(cond) if ((cond)){return TMBSL_ERR_HDMI_BAD_PARAMETER;} ++#endif ++ ++/** ++ * A macro to check the result of a register API and if not TM_OK to return it. ++ * To save code space, it can be compiled out by defining NO_RETIF_REG_FAIL on ++ * the compiler command line. ++ */ ++#ifdef NO_RETIF_REG_FAIL ++#define RETIF_REG_FAIL(result) ++#else ++#define RETIF_REG_FAIL(result) if ((result) != TM_OK){return (result);} ++#endif ++ ++/** ++ * Check the consistancy of BSL structure ++ */ ++/* #define BSL_CONSISTANCY(_x_,_y_) do { \ */ ++/* #if ((_x_) != (_y_) * (_x_)[0]) \ */ ++/* #error "BSL HAS WRONG ARRAY SIZE" \ */ ++/* #endif \ */ ++/* } while (0) */ ++ ++ ++/*============================================================================*/ ++/* ENUM OR TYPE DEFINITIONS */ ++/*============================================================================*/ ++ ++/** ++ * Driver events and states used for diagnosis ++ */ ++typedef enum _tmbslTDA9989Event ++{ ++ EV_DEINIT = 0, ++ EV_INIT = 1, ++ EV_STANDBY = 2, ++ EV_SLEEP = 3, ++ EV_ON = 4, ++ EV_UNPLUGGED = 5, ++ EV_PLUGGEDIN = 6, ++ EV_RESUME_UNPLUGGED = 7, ++ EV_RESUME_PLUGGEDIN = 8, ++ EV_GETBLOCKDATA = 9, ++ EV_SETINOUT = 10, ++ EV_OUTDISABLE = 11, ++ EV_HDCP_RUN = 12, ++ EV_HDCP_BKSV_NREPEAT = 13, ++ EV_HDCP_BKSV_NSECURE = 14, ++ EV_HDCP_BKSV_REPEAT = 15, ++ EV_HDCP_BSTATUS_GOOD = 16, ++ EV_HDCP_KSV_SECURE = 17, ++ EV_HDCP_T0 = 18, ++ EV_HDCP_STOP = 19, ++ EV_SINKON = 20, ++ EV_SINKOFF = 21, ++ EV_INVALID = 22 ++} tmbslTDA9989Event_t; ++ ++typedef enum _tmbslTDA9989State ++{ ++ ST_UNINITIALIZED = 0, ++ ST_STANDBY = 1, ++ ST_SLEEP = 2, ++ ST_DISCONNECTED = 3, ++ ST_AWAIT_EDID = 4, ++ ST_SINK_CONNECTED = 5, ++ ST_VIDEO_NO_HDCP = 6, ++ ST_HDCP_WAIT_RX = 7, ++ ST_HDCP_WAIT_BSTATUS = 8, ++ ST_HDCP_WAIT_SHA_1 = 9, ++ ST_HDCP_AUTHENTICATED = 10, ++ ST_AWAIT_RX_SENSE = 11, ++ ST_INVALID = 12, ++ ST_NUM = 13 ++} tmbslTDA9989State_t; ++ ++/** ++ * An enum to index into the Device Instance Data shadowReg array ++ */ ++enum _eShad ++{ ++ E_SP00_INT_FLAGS_0 = 0, ++ E_SP00_INT_FLAGS_1 = 1, ++ E_SP00_INT_FLAGS_2 = 2, ++ E_SP00_VIP_CNTRL_0 = 3, ++ E_SP00_VIP_CNTRL_1 = 4, ++ E_SP00_VIP_CNTRL_2 = 5, ++ E_SP00_VIP_CNTRL_3 = 6, ++ E_SP00_VIP_CNTRL_4 = 7, ++ E_SP00_VIP_CNTRL_5 = 8, ++ E_SP00_MAT_CONTRL = 9, ++ E_SP00_TBG_CNTRL_0 = 10, ++ E_SP00_TBG_CNTRL_1 = 11, ++ E_SP00_HVF_CNTRL_0 = 12, ++ E_SP00_HVF_CNTRL_1 = 13, ++ E_SP00_TIMER_H = 14, ++ E_SP00_DEBUG_PROBE = 15, ++ E_SP00_AIP_CLKSEL = 16, ++ E_SP01_SC_VIDFORMAT = 17, ++ E_SP01_SC_CNTRL = 18, ++ E_SP01_TBG_CNTRL_0 = 19, ++#ifdef TMFL_HDCP_SUPPORT ++ E_SP12_CTRL = 20, ++ E_SP12_BCAPS = 21, ++ E_SNUM = 22, /* Number of shadow registers */ ++ E_SNONE = 22 /* Index value indicating no shadow register */ ++#else /* TMFL_HDCP_SUPPORT */ ++ E_SNUM = 20, /* Number of shadow registers */ ++ E_SNONE = 20 /* Index value indicating no shadow register */ ++#endif /* TMFL_HDCP_SUPPORT */ ++}; ++ ++/** ++ * Page list ++ * These are indexes to the allowed register page numbers ++ */ ++enum _ePage ++{ ++ E_PAGE_00 = 0, ++ E_PAGE_01 = 1, ++ E_PAGE_02 = 2, ++ E_PAGE_09 = 3, ++ E_PAGE_10 = 4, ++ E_PAGE_11 = 5, ++ E_PAGE_12 = 6, ++ E_PAGE_13 = 7, ++ E_PAGE_NUM = 8, /* Number of pages */ ++ E_PAGE_INVALID = 8 /* Index value indicating invalid page */ ++}; ++ ++/** ++ * Macros to initialize and access the following register list enum _eReg ++ */ ++/* Pack shadow index s, page index p and register address a into UInt16 */ ++#define SPA(s,p,a) (UInt16)(((s)<<11)|((p)<<8)|(a)) ++/* Unpacks shadow index s from UInt16 */ ++#define SPA2SHAD(spa) (UInt8)((spa)>>11) ++/* Unpacks page index p from UInt16 */ ++#define SPA2PAGE(spa) (UInt8)(((spa)>>8)&0x0007) ++/* Unpacks register address a from UInt16 */ ++#define SPA2ADDR(spa) (UInt8)((spa)&0x00FF) ++ ++/** ++ * Register list ++ * ++ * Each register symbol has these fields: E_REG_page_register_access ++ * ++ * The symbols have a 16-bit value as follows, including an index to ++ * the Device Instance Data shadowReg[] array: ++ * ++ * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ ++ * |15 |14 |13 |12 |11 |10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ++ * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ ++ * | Shadow Index |Page Index | Register Address | ++ * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ ++ * ++ */ ++enum _eReg ++{ ++ /*************************************************************************/ ++ /** Rows formatted in "HDMI Driver - Register List.xls" and pasted here **/ ++ /*************************************************************************/ ++ E_REG_MIN_ADR = 0x00, /* First register on all pages */ ++ E_REG_CURPAGE_ADR_W = 0xFF, /* Address register on all pages */ ++ /*CEC Registers*/ ++ ++ E_REG_CEC_INTERRUPTSTATUS_R = 0xEE, ++ E_REG_CEC_RXSHPDINTENA_RW = 0xFC, ++ E_REG_CEC_RXSHPDINT_R = 0xFD, ++ E_REG_CEC_RXSHPDLEV_R = 0xFE, ++ E_REG_CEC_ENAMODS_RW = 0xFF, ++ E_REG_CEC_FRO_IM_CLK_CTRL_RW = 0xFB, ++ ++ E_REG_P00_VERSION_R = SPA(E_SNONE , E_PAGE_00, 0x00), ++ E_REG_P00_MAIN_CNTRL0_RW = SPA(E_SNONE , E_PAGE_00, 0x01), ++ E_REG_P00_VERSION_MSB_RW = SPA(E_SNONE , E_PAGE_00, 0x02), ++ E_REG_P00_PACKAGE_TYPE_R = SPA(E_SNONE , E_PAGE_00, 0x03), ++ E_REG_P00_SR_REG_W = SPA(E_SNONE , E_PAGE_00, 0x0A), ++ E_REG_P00_DDC_DISABLE_RW = SPA(E_SNONE , E_PAGE_00, 0x0B), ++ E_REG_P00_CCLK_ON_RW = SPA(E_SNONE , E_PAGE_00, 0x0C), ++ E_REG_P00_I2C_MASTER_RW = SPA(E_SNONE , E_PAGE_00, 0x0D), ++#ifdef TMFL_HDCP_OPTIMIZED_POWER ++ E_REG_FEAT_POWER_DOWN = SPA(E_SNONE , E_PAGE_00, 0x0E), ++#endif ++ ++ E_REG_P00_INT_FLAGS_0_RW = SPA(E_SP00_INT_FLAGS_0 , E_PAGE_00, 0x0F), ++ E_REG_P00_INT_FLAGS_1_RW = SPA(E_SP00_INT_FLAGS_1 , E_PAGE_00, 0x10), ++ E_REG_P00_INT_FLAGS_2_RW = SPA(E_SP00_INT_FLAGS_2 , E_PAGE_00, 0x11), ++ /*E_REG_P00_INT_FLAGS_3_R = SPA(E_SNONE , E_PAGE_00, 0x12),*/ ++ E_REG_P00_SW_INT_W = SPA(E_SNONE , E_PAGE_00, 0x15), ++ E_REG_P00_ENA_ACLK_RW = SPA(E_SNONE , E_PAGE_00, 0x16), ++ E_REG_P00_ENA_VP_0_RW = SPA(E_SNONE , E_PAGE_00, 0x18), ++ E_REG_P00_ENA_VP_1_RW = SPA(E_SNONE , E_PAGE_00, 0x19), ++ E_REG_P00_ENA_VP_2_RW = SPA(E_SNONE , E_PAGE_00, 0x1A), ++ E_REG_P00_ENA_AP_RW = SPA(E_SNONE , E_PAGE_00, 0x1E), ++ E_REG_P00_VIP_CNTRL_0_W = SPA(E_SP00_VIP_CNTRL_0 , E_PAGE_00, 0x20), ++ E_REG_P00_VIP_CNTRL_1_W = SPA(E_SP00_VIP_CNTRL_1 , E_PAGE_00, 0x21), ++ E_REG_P00_VIP_CNTRL_2_W = SPA(E_SP00_VIP_CNTRL_2 , E_PAGE_00, 0x22), ++ E_REG_P00_VIP_CNTRL_3_W = SPA(E_SP00_VIP_CNTRL_3 , E_PAGE_00, 0x23), ++ E_REG_P00_VIP_CNTRL_4_W = SPA(E_SP00_VIP_CNTRL_4 , E_PAGE_00, 0x24), ++ E_REG_P00_VIP_CNTRL_5_W = SPA(E_SP00_VIP_CNTRL_5 , E_PAGE_00, 0x25), ++ E_REG_P00_MUX_AP_RW = SPA(E_SNONE , E_PAGE_00, 0x26), ++ E_REG_P00_MUX_VP_VIP_OUT_RW = SPA(E_SNONE , E_PAGE_00, 0x27), ++ E_REG_P00_MAT_CONTRL_W = SPA(E_SP00_MAT_CONTRL , E_PAGE_00, 0x80), ++ E_REG_P00_MAT_OI1_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x81), ++ E_REG_P00_MAT_OI1_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x82), ++ E_REG_P00_MAT_OI2_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x83), ++ E_REG_P00_MAT_OI2_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x84), ++ E_REG_P00_MAT_OI3_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x85), ++ E_REG_P00_MAT_OI3_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x86), ++ E_REG_P00_MAT_P11_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x87), ++ E_REG_P00_MAT_P11_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x88), ++ E_REG_P00_MAT_P12_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x89), ++ E_REG_P00_MAT_P12_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x8A), ++ E_REG_P00_MAT_P13_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x8B), ++ E_REG_P00_MAT_P13_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x8C), ++ E_REG_P00_MAT_P21_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x8D), ++ E_REG_P00_MAT_P21_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x8E), ++ E_REG_P00_MAT_P22_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x8F), ++ E_REG_P00_MAT_P22_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x90), ++ E_REG_P00_MAT_P23_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x91), ++ E_REG_P00_MAT_P23_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x92), ++ E_REG_P00_MAT_P31_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x93), ++ E_REG_P00_MAT_P31_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x94), ++ E_REG_P00_MAT_P32_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x95), ++ E_REG_P00_MAT_P32_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x96), ++ E_REG_P00_MAT_P33_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x97), ++ E_REG_P00_MAT_P33_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x98), ++ E_REG_P00_MAT_OO1_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x99), ++ E_REG_P00_MAT_OO1_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x9A), ++ E_REG_P00_MAT_OO2_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x9B), ++ E_REG_P00_MAT_OO2_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x9C), ++ E_REG_P00_MAT_OO3_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x9D), ++ E_REG_P00_MAT_OO3_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x9E), ++ E_REG_P00_VIDFORMAT_W = SPA(E_SNONE , E_PAGE_00, 0xA0), ++ E_REG_P00_REFPIX_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xA1), ++ E_REG_P00_REFPIX_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xA2), ++ E_REG_P00_REFLINE_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xA3), ++ E_REG_P00_REFLINE_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xA4), ++ E_REG_P00_NPIX_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xA5), ++ E_REG_P00_NPIX_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xA6), ++ E_REG_P00_NLINE_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xA7), ++ E_REG_P00_NLINE_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xA8), ++ E_REG_P00_VS_LINE_STRT_1_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xA9), ++ E_REG_P00_VS_LINE_STRT_1_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xAA), ++ E_REG_P00_VS_PIX_STRT_1_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xAB), ++ E_REG_P00_VS_PIX_STRT_1_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xAC), ++ E_REG_P00_VS_LINE_END_1_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xAD), ++ E_REG_P00_VS_LINE_END_1_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xAE), ++ E_REG_P00_VS_PIX_END_1_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xAF), ++ E_REG_P00_VS_PIX_END_1_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xB0), ++ E_REG_P00_VS_LINE_STRT_2_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xB1), ++ E_REG_P00_VS_LINE_STRT_2_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xB2), ++ E_REG_P00_VS_PIX_STRT_2_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xB3), ++ E_REG_P00_VS_PIX_STRT_2_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xB4), ++ E_REG_P00_VS_LINE_END_2_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xB5), ++ E_REG_P00_VS_LINE_END_2_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xB6), ++ E_REG_P00_VS_PIX_END_2_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xB7), ++ E_REG_P00_VS_PIX_END_2_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xB8), ++ E_REG_P00_HS_PIX_START_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xB9), ++ E_REG_P00_HS_PIX_START_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xBA), ++ E_REG_P00_HS_PIX_STOP_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xBB), ++ E_REG_P00_HS_PIX_STOP_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xBC), ++ E_REG_P00_VWIN_START_1_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xBD), ++ E_REG_P00_VWIN_START_1_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xBE), ++ E_REG_P00_VWIN_END_1_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xBF), ++ E_REG_P00_VWIN_END_1_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xC0), ++ E_REG_P00_VWIN_START_2_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xC1), ++ E_REG_P00_VWIN_START_2_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xC2), ++ E_REG_P00_VWIN_END_2_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xC3), ++ E_REG_P00_VWIN_END_2_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xC4), ++ E_REG_P00_DE_START_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xC5), ++ E_REG_P00_DE_START_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xC6), ++ E_REG_P00_DE_STOP_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xC7), ++ E_REG_P00_DE_STOP_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xC8), ++ E_REG_P00_COLBAR_WIDTH_W = SPA(E_SNONE , E_PAGE_00, 0xC9), ++ E_REG_P00_TBG_CNTRL_0_W = SPA(E_SP00_TBG_CNTRL_0 , E_PAGE_00, 0xCA), ++ E_REG_P00_TBG_CNTRL_1_W = SPA(E_SP00_TBG_CNTRL_1 , E_PAGE_00, 0xCB), ++ E_REG_P00_VBL_OFFSET_START_W = SPA(E_SNONE , E_PAGE_00, 0xCC), ++ E_REG_P00_VBL_OFFSET_END_W = SPA(E_SNONE , E_PAGE_00, 0xCD), ++ E_REG_P00_HBL_OFFSET_START_W = SPA(E_SNONE , E_PAGE_00, 0xCE), ++ E_REG_P00_HBL_OFFSET_END_W = SPA(E_SNONE , E_PAGE_00, 0xCF), ++ E_REG_P00_DWIN_RE_DE_W = SPA(E_SNONE , E_PAGE_00, 0xD0), ++ E_REG_P00_DWIN_FE_DE_W = SPA(E_SNONE , E_PAGE_00, 0xD1), ++#ifdef TMFL_RGB_DDR_12BITS ++ E_REG_P00_VSPACE_START_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xD2), ++ E_REG_P00_VSPACE_START_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xD3), ++ E_REG_P00_VSPACE_END_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xD4), ++ E_REG_P00_VSPACE_END_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xD5), ++ E_REG_P00_ENABLE_SPACE_W = SPA(E_SNONE , E_PAGE_00, 0xD6), ++ E_REG_P00_VSPACE_Y_DATA_W = SPA(E_SNONE , E_PAGE_00, 0xD7), ++ E_REG_P00_VSPACE_U_DATA_W = SPA(E_SNONE , E_PAGE_00, 0xD8), ++ E_REG_P00_VSPACE_V_DATA_W = SPA(E_SNONE , E_PAGE_00, 0xD9), ++#endif ++ ++ E_REG_P00_TIMER_RI_PJ_RW = SPA(E_SNONE , E_PAGE_00, 0xE1), ++ E_REG_P00_BCAPS_POLL_RW = SPA(E_SNONE , E_PAGE_00, 0xE2), ++ E_REG_P00_100us_RW = SPA(E_SNONE , E_PAGE_00, 0xE3), ++ ++ E_REG_P00_HVF_CNTRL_0_W = SPA(E_SP00_HVF_CNTRL_0 , E_PAGE_00, 0xE4), ++ E_REG_P00_HVF_CNTRL_1_W = SPA(E_SP00_HVF_CNTRL_1 , E_PAGE_00, 0xE5), ++ ++ E_REG_P00_TIMER_H_W = SPA(E_SP00_TIMER_H , E_PAGE_00, 0xE8), ++ E_REG_P00_TIMER_M_W = SPA(E_SNONE , E_PAGE_00, 0xE9), ++ E_REG_P00_TIMER_L_W = SPA(E_SNONE , E_PAGE_00, 0xEA), ++ E_REG_P00_TIMER_2SEC_W = SPA(E_SNONE , E_PAGE_00, 0xEB), ++ E_REG_P00_TIMER_5SEC_W = SPA(E_SNONE , E_PAGE_00, 0xEC), ++ E_REG_P00_NDIV_IM_W = SPA(E_SNONE , E_PAGE_00, 0xEE), ++ E_REG_P00_NDIV_PF_W = SPA(E_SNONE , E_PAGE_00, 0xEF), ++ E_REG_P00_RPT_CNTRL_W = SPA(E_SNONE , E_PAGE_00, 0xF0), ++ E_REG_P00_LEAD_OFF_W = SPA(E_SNONE , E_PAGE_00, 0xF1), ++ E_REG_P00_TRAIL_OFF_W = SPA(E_SNONE , E_PAGE_00, 0xF2), ++ E_REG_P00_MISR_EXP_0_RW = SPA(E_SNONE , E_PAGE_00, 0xF3), ++ E_REG_P00_MISR_EXP_1_RW = SPA(E_SNONE , E_PAGE_00, 0xF4), ++ E_REG_P00_MISR_EXP_2_RW = SPA(E_SNONE , E_PAGE_00, 0xF5), ++ E_REG_P00_MISR_0_R = SPA(E_SNONE , E_PAGE_00, 0xF6), ++ E_REG_P00_MISR_1_R = SPA(E_SNONE , E_PAGE_00, 0xF7), ++ E_REG_P00_DEBUG_PROBE_W = SPA(E_SP00_DEBUG_PROBE , E_PAGE_00, 0xF8), ++ E_REG_P00_GHOST_XADDR_W = SPA(E_SNONE , E_PAGE_00, 0xF9), ++ E_REG_P00_MISR_2_R = SPA(E_SNONE , E_PAGE_00, 0xFA), ++ E_REG_P00_I2S_FORMAT_RW = SPA(E_SNONE , E_PAGE_00, 0xFC), ++ E_REG_P00_AIP_CLKSEL_W = SPA(E_SP00_AIP_CLKSEL , E_PAGE_00, 0xFD), ++ E_REG_P00_GHOST_ADDR_W = SPA(E_SNONE , E_PAGE_00, 0xFE), ++ E_REG_P01_SC_VIDFORMAT_W = SPA(E_SP01_SC_VIDFORMAT, E_PAGE_01, 0x00), ++ ++ E_REG_P01_SC_CNTRL_W = SPA(E_SP01_SC_CNTRL , E_PAGE_01, 0x01), ++ E_REG_P01_SC_DELTA_PHASE_V_W = SPA(E_SNONE , E_PAGE_01, 0x02), ++ E_REG_P01_SC_DELTA_PHASE_H_W = SPA(E_SNONE , E_PAGE_01, 0x03), ++ E_REG_P01_SC_START_PHASE_H_W = SPA(E_SNONE , E_PAGE_01, 0x04), ++ E_REG_P01_SC_NPIX_IN_LSB_W = SPA(E_SNONE , E_PAGE_01, 0x05), ++ E_REG_P01_SC_NPIX_IN_MSB_W = SPA(E_SNONE , E_PAGE_01, 0x06), ++ E_REG_P01_SC_NPIX_OUT_LSB_W = SPA(E_SNONE , E_PAGE_01, 0x07), ++ E_REG_P01_SC_NPIX_OUT_MSB_W = SPA(E_SNONE , E_PAGE_01, 0x08), ++ E_REG_P01_SC_NLINE_IN_LSB_W = SPA(E_SNONE , E_PAGE_01, 0x09), ++ E_REG_P01_SC_NLINE_IN_MSB_W = SPA(E_SNONE , E_PAGE_01, 0x0A), ++ E_REG_P01_SC_NLINE_OUT_LSB_W = SPA(E_SNONE , E_PAGE_01, 0x0B), ++ E_REG_P01_SC_NLINE_OUT_MSB_W = SPA(E_SNONE , E_PAGE_01, 0x0C), ++ E_REG_P01_SC_NLINE_SKIP_W = SPA(E_SNONE , E_PAGE_01, 0x0D), ++ E_REG_P01_SC_SAMPLE_BUFFILL_R = SPA(E_SNONE , E_PAGE_01, 0x0E), ++ E_REG_P01_SC_MAX_BUFFILL_P_0_R = SPA(E_SNONE , E_PAGE_01, 0x0F), ++ E_REG_P01_SC_MAX_BUFFILL_P_1_R = SPA(E_SNONE , E_PAGE_01, 0x10), ++ E_REG_P01_SC_MAX_BUFFILL_D_0_R = SPA(E_SNONE , E_PAGE_01, 0x11), ++ E_REG_P01_SC_MAX_BUFFILL_D_1_R = SPA(E_SNONE , E_PAGE_01, 0x12), ++ E_REG_P01_SC_SAMPLE_FIFOFILL_R = SPA(E_SNONE , E_PAGE_01, 0x13), ++ E_REG_P01_SC_MAX_FIFOFILL_PI_R = SPA(E_SNONE , E_PAGE_01, 0x14), ++ E_REG_P01_SC_MIN_FIFOFILL_PO1_R = SPA(E_SNONE , E_PAGE_01, 0x15), ++ E_REG_P01_SC_MIN_FIFOFILL_PO2_R = SPA(E_SNONE , E_PAGE_01, 0x16), ++ E_REG_P01_SC_MIN_FIFOFILL_PO3_R = SPA(E_SNONE , E_PAGE_01, 0x17), ++ E_REG_P01_SC_MIN_FIFOFILL_PO4_R = SPA(E_SNONE , E_PAGE_01, 0x18), ++ E_REG_P01_SC_MAX_FIFOFILL_DI_R = SPA(E_SNONE , E_PAGE_01, 0x19), ++ E_REG_P01_SC_MAX_FIFOFILL_DO_R = SPA(E_SNONE , E_PAGE_01, 0x1A), ++ E_REG_P01_SC_VS_LUT_0_W = SPA(E_SNONE , E_PAGE_01, 0x1B), ++ E_REG_P01_SC_VS_LUT_1_W = SPA(E_SNONE , E_PAGE_01, 0x1C), ++ E_REG_P01_SC_VS_LUT_2_W = SPA(E_SNONE , E_PAGE_01, 0x1D), ++ E_REG_P01_SC_VS_LUT_3_W = SPA(E_SNONE , E_PAGE_01, 0x1E), ++ E_REG_P01_SC_VS_LUT_4_W = SPA(E_SNONE , E_PAGE_01, 0x1F), ++ E_REG_P01_SC_VS_LUT_5_W = SPA(E_SNONE , E_PAGE_01, 0x20), ++ E_REG_P01_SC_VS_LUT_6_W = SPA(E_SNONE , E_PAGE_01, 0x21), ++ E_REG_P01_SC_VS_LUT_7_W = SPA(E_SNONE , E_PAGE_01, 0x22), ++ E_REG_P01_SC_VS_LUT_8_W = SPA(E_SNONE , E_PAGE_01, 0x23), ++ E_REG_P01_SC_VS_LUT_9_W = SPA(E_SNONE , E_PAGE_01, 0x24), ++ E_REG_P01_SC_VS_LUT_10_W = SPA(E_SNONE , E_PAGE_01, 0x25), ++ E_REG_P01_SC_VS_LUT_11_W = SPA(E_SNONE , E_PAGE_01, 0x26), ++ E_REG_P01_SC_VS_LUT_12_W = SPA(E_SNONE , E_PAGE_01, 0x27), ++ E_REG_P01_SC_VS_LUT_13_W = SPA(E_SNONE , E_PAGE_01, 0x28), ++ E_REG_P01_SC_VS_LUT_14_W = SPA(E_SNONE , E_PAGE_01, 0x29), ++ E_REG_P01_SC_VS_LUT_15_W = SPA(E_SNONE , E_PAGE_01, 0x2A), ++ E_REG_P01_SC_VS_LUT_16_W = SPA(E_SNONE , E_PAGE_01, 0x2B), ++ E_REG_P01_SC_VS_LUT_17_W = SPA(E_SNONE , E_PAGE_01, 0x2C), ++ E_REG_P01_SC_VS_LUT_18_W = SPA(E_SNONE , E_PAGE_01, 0x2D), ++ E_REG_P01_SC_VS_LUT_19_W = SPA(E_SNONE , E_PAGE_01, 0x2E), ++ E_REG_P01_SC_VS_LUT_20_W = SPA(E_SNONE , E_PAGE_01, 0x2F), ++ E_REG_P01_SC_VS_LUT_21_W = SPA(E_SNONE , E_PAGE_01, 0x30), ++ E_REG_P01_SC_VS_LUT_22_W = SPA(E_SNONE , E_PAGE_01, 0x31), ++ E_REG_P01_SC_VS_LUT_23_W = SPA(E_SNONE , E_PAGE_01, 0x32), ++ E_REG_P01_SC_VS_LUT_24_W = SPA(E_SNONE , E_PAGE_01, 0x33), ++ E_REG_P01_SC_VS_LUT_25_W = SPA(E_SNONE , E_PAGE_01, 0x34), ++ E_REG_P01_SC_VS_LUT_26_W = SPA(E_SNONE , E_PAGE_01, 0x35), ++ E_REG_P01_SC_VS_LUT_27_W = SPA(E_SNONE , E_PAGE_01, 0x36), ++ E_REG_P01_SC_VS_LUT_28_W = SPA(E_SNONE , E_PAGE_01, 0x37), ++ E_REG_P01_SC_VS_LUT_29_W = SPA(E_SNONE , E_PAGE_01, 0x38), ++ E_REG_P01_SC_VS_LUT_30_W = SPA(E_SNONE , E_PAGE_01, 0x39), ++ E_REG_P01_SC_VS_LUT_31_W = SPA(E_SNONE , E_PAGE_01, 0x3A), ++ E_REG_P01_SC_VS_LUT_32_W = SPA(E_SNONE , E_PAGE_01, 0x3B), ++ E_REG_P01_SC_VS_LUT_33_W = SPA(E_SNONE , E_PAGE_01, 0x3C), ++ E_REG_P01_SC_VS_LUT_34_W = SPA(E_SNONE , E_PAGE_01, 0x3D), ++ E_REG_P01_SC_VS_LUT_35_W = SPA(E_SNONE , E_PAGE_01, 0x3E), ++ E_REG_P01_SC_VS_LUT_36_W = SPA(E_SNONE , E_PAGE_01, 0x3F), ++ E_REG_P01_SC_VS_LUT_37_W = SPA(E_SNONE , E_PAGE_01, 0x40), ++ E_REG_P01_SC_VS_LUT_38_W = SPA(E_SNONE , E_PAGE_01, 0x41), ++ E_REG_P01_SC_VS_LUT_39_W = SPA(E_SNONE , E_PAGE_01, 0x42), ++ E_REG_P01_SC_VS_LUT_40_W = SPA(E_SNONE , E_PAGE_01, 0x43), ++ E_REG_P01_SC_VS_LUT_41_W = SPA(E_SNONE , E_PAGE_01, 0x44), ++ E_REG_P01_SC_VS_LUT_42_W = SPA(E_SNONE , E_PAGE_01, 0x45), ++ E_REG_P01_SC_VS_LUT_43_W = SPA(E_SNONE , E_PAGE_01, 0x46), ++ E_REG_P01_SC_VS_LUT_44_W = SPA(E_SNONE , E_PAGE_01, 0x47), ++ E_REG_P01_SC_LAT_SCO_RW = SPA(E_SNONE , E_PAGE_01, 0x48), ++ E_REG_P01_VIDFORMAT_W = SPA(E_SNONE , E_PAGE_01, 0xA0), ++ E_REG_P01_REFPIX_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xA1), ++ E_REG_P01_REFPIX_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xA2), ++ E_REG_P01_REFLINE_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xA3), ++ E_REG_P01_REFLINE_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xA4), ++ E_REG_P01_NPIX_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xA5), ++ E_REG_P01_NPIX_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xA6), ++ E_REG_P01_NLINE_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xA7), ++ E_REG_P01_NLINE_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xA8), ++ E_REG_P01_VWIN_START_1_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xBD), ++ E_REG_P01_VWIN_START_1_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xBE), ++ E_REG_P01_VWIN_END_1_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xBF), ++ E_REG_P01_VWIN_END_1_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xC0), ++ E_REG_P01_VWIN_START_2_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xC1), ++ E_REG_P01_VWIN_START_2_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xC2), ++ E_REG_P01_VWIN_END_2_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xC3), ++ E_REG_P01_VWIN_END_2_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xC4), ++ E_REG_P01_DE_START_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xC5), ++ E_REG_P01_DE_START_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xC6), ++ E_REG_P01_DE_STOP_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xC7), ++ E_REG_P01_DE_STOP_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xC8), ++ E_REG_P01_TBG_CNTRL_0_W = SPA(E_SP01_TBG_CNTRL_0 , E_PAGE_01, 0xCA), ++ E_REG_P02_PLL_SERIAL_1_RW = SPA(E_SNONE , E_PAGE_02, 0x00), ++ E_REG_P02_PLL_SERIAL_2_RW = SPA(E_SNONE , E_PAGE_02, 0x01), ++ E_REG_P02_PLL_SERIAL_3_RW = SPA(E_SNONE , E_PAGE_02, 0x02), ++ E_REG_P02_SERIALIZER_RW = SPA(E_SNONE , E_PAGE_02, 0x03), ++ E_REG_P02_BUFFER_OUT_RW = SPA(E_SNONE , E_PAGE_02, 0x04), ++ E_REG_P02_PLL_SCG1_RW = SPA(E_SNONE , E_PAGE_02, 0x05), ++ E_REG_P02_PLL_SCG2_RW = SPA(E_SNONE , E_PAGE_02, 0x06), ++ E_REG_P02_PLL_SCGN1_RW = SPA(E_SNONE , E_PAGE_02, 0x07), ++ E_REG_P02_PLL_SCGN2_RW = SPA(E_SNONE , E_PAGE_02, 0x08), ++ E_REG_P02_PLL_SCGR1_RW = SPA(E_SNONE , E_PAGE_02, 0x09), ++ E_REG_P02_PLL_SCGR2_RW = SPA(E_SNONE , E_PAGE_02, 0x0A), ++ E_REG_P02_VAI_PLL_R = SPA(E_SNONE , E_PAGE_02, 0x0D), ++ E_REG_P02_AUDIO_DIV_RW = SPA(E_SNONE , E_PAGE_02, 0x0E), ++ E_REG_P02_TEST1_RW = SPA(E_SNONE , E_PAGE_02, 0x0F), ++ /*E_REG_P02_TEST2_RW = SPA(E_SNONE , E_PAGE_02, 0x10),*/ ++ E_REG_P02_SEL_CLK_RW = SPA(E_SNONE , E_PAGE_02, 0x11), ++ E_REG_P02_ANA_GENERAL_RW = SPA(E_SNONE , E_PAGE_02, 0x12), ++ E_REG_P02_BUFFER_OUT2_RW = SPA(E_SNONE , E_PAGE_02, 0x13), ++ E_REG_P02_SRL_TSTPAT0_RW = SPA(E_SNONE , E_PAGE_02, 0x14), ++ E_REG_P02_SRL_TSTPAT1_RW = SPA(E_SNONE , E_PAGE_02, 0x15), ++ E_REG_P02_SRL_TSTPAT2_RW = SPA(E_SNONE , E_PAGE_02, 0x16), ++ E_REG_P02_SRL_TSTPAT3_RW = SPA(E_SNONE , E_PAGE_02, 0x17), ++ ++ E_REG_P09_EDID_DATA_0_R = SPA(E_SNONE , E_PAGE_09, 0x00), ++ E_REG_P09_EDID_DATA_1_R = SPA(E_SNONE , E_PAGE_09, 0x01), ++ E_REG_P09_EDID_DATA_2_R = SPA(E_SNONE , E_PAGE_09, 0x02), ++ E_REG_P09_EDID_DATA_3_R = SPA(E_SNONE , E_PAGE_09, 0x03), ++ E_REG_P09_EDID_DATA_4_R = SPA(E_SNONE , E_PAGE_09, 0x04), ++ E_REG_P09_EDID_DATA_5_R = SPA(E_SNONE , E_PAGE_09, 0x05), ++ E_REG_P09_EDID_DATA_6_R = SPA(E_SNONE , E_PAGE_09, 0x06), ++ E_REG_P09_EDID_DATA_7_R = SPA(E_SNONE , E_PAGE_09, 0x07), ++ E_REG_P09_EDID_DATA_8_R = SPA(E_SNONE , E_PAGE_09, 0x08), ++ E_REG_P09_EDID_DATA_9_R = SPA(E_SNONE , E_PAGE_09, 0x09), ++ E_REG_P09_EDID_DATA_10_R = SPA(E_SNONE , E_PAGE_09, 0x0A), ++ E_REG_P09_EDID_DATA_11_R = SPA(E_SNONE , E_PAGE_09, 0x0B), ++ E_REG_P09_EDID_DATA_12_R = SPA(E_SNONE , E_PAGE_09, 0x0C), ++ E_REG_P09_EDID_DATA_13_R = SPA(E_SNONE , E_PAGE_09, 0x0D), ++ E_REG_P09_EDID_DATA_14_R = SPA(E_SNONE , E_PAGE_09, 0x0E), ++ E_REG_P09_EDID_DATA_15_R = SPA(E_SNONE , E_PAGE_09, 0x0F), ++ E_REG_P09_EDID_DATA_16_R = SPA(E_SNONE , E_PAGE_09, 0x10), ++ E_REG_P09_EDID_DATA_17_R = SPA(E_SNONE , E_PAGE_09, 0x11), ++ E_REG_P09_EDID_DATA_18_R = SPA(E_SNONE , E_PAGE_09, 0x12), ++ E_REG_P09_EDID_DATA_19_R = SPA(E_SNONE , E_PAGE_09, 0x13), ++ E_REG_P09_EDID_DATA_20_R = SPA(E_SNONE , E_PAGE_09, 0x14), ++ E_REG_P09_EDID_DATA_21_R = SPA(E_SNONE , E_PAGE_09, 0x15), ++ E_REG_P09_EDID_DATA_22_R = SPA(E_SNONE , E_PAGE_09, 0x16), ++ E_REG_P09_EDID_DATA_23_R = SPA(E_SNONE , E_PAGE_09, 0x17), ++ E_REG_P09_EDID_DATA_24_R = SPA(E_SNONE , E_PAGE_09, 0x18), ++ E_REG_P09_EDID_DATA_25_R = SPA(E_SNONE , E_PAGE_09, 0x19), ++ E_REG_P09_EDID_DATA_26_R = SPA(E_SNONE , E_PAGE_09, 0x1A), ++ E_REG_P09_EDID_DATA_27_R = SPA(E_SNONE , E_PAGE_09, 0x1B), ++ E_REG_P09_EDID_DATA_28_R = SPA(E_SNONE , E_PAGE_09, 0x1C), ++ E_REG_P09_EDID_DATA_29_R = SPA(E_SNONE , E_PAGE_09, 0x1D), ++ E_REG_P09_EDID_DATA_30_R = SPA(E_SNONE , E_PAGE_09, 0x1E), ++ E_REG_P09_EDID_DATA_31_R = SPA(E_SNONE , E_PAGE_09, 0x1F), ++ E_REG_P09_EDID_DATA_32_R = SPA(E_SNONE , E_PAGE_09, 0x20), ++ E_REG_P09_EDID_DATA_33_R = SPA(E_SNONE , E_PAGE_09, 0x21), ++ E_REG_P09_EDID_DATA_34_R = SPA(E_SNONE , E_PAGE_09, 0x22), ++ E_REG_P09_EDID_DATA_35_R = SPA(E_SNONE , E_PAGE_09, 0x23), ++ E_REG_P09_EDID_DATA_36_R = SPA(E_SNONE , E_PAGE_09, 0x24), ++ E_REG_P09_EDID_DATA_37_R = SPA(E_SNONE , E_PAGE_09, 0x25), ++ E_REG_P09_EDID_DATA_38_R = SPA(E_SNONE , E_PAGE_09, 0x26), ++ E_REG_P09_EDID_DATA_39_R = SPA(E_SNONE , E_PAGE_09, 0x27), ++ E_REG_P09_EDID_DATA_40_R = SPA(E_SNONE , E_PAGE_09, 0x28), ++ E_REG_P09_EDID_DATA_41_R = SPA(E_SNONE , E_PAGE_09, 0x29), ++ E_REG_P09_EDID_DATA_42_R = SPA(E_SNONE , E_PAGE_09, 0x2A), ++ E_REG_P09_EDID_DATA_43_R = SPA(E_SNONE , E_PAGE_09, 0x2B), ++ E_REG_P09_EDID_DATA_44_R = SPA(E_SNONE , E_PAGE_09, 0x2C), ++ E_REG_P09_EDID_DATA_45_R = SPA(E_SNONE , E_PAGE_09, 0x2D), ++ E_REG_P09_EDID_DATA_46_R = SPA(E_SNONE , E_PAGE_09, 0x2E), ++ E_REG_P09_EDID_DATA_47_R = SPA(E_SNONE , E_PAGE_09, 0x2F), ++ E_REG_P09_EDID_DATA_48_R = SPA(E_SNONE , E_PAGE_09, 0x30), ++ E_REG_P09_EDID_DATA_49_R = SPA(E_SNONE , E_PAGE_09, 0x31), ++ E_REG_P09_EDID_DATA_50_R = SPA(E_SNONE , E_PAGE_09, 0x32), ++ E_REG_P09_EDID_DATA_51_R = SPA(E_SNONE , E_PAGE_09, 0x33), ++ E_REG_P09_EDID_DATA_52_R = SPA(E_SNONE , E_PAGE_09, 0x34), ++ E_REG_P09_EDID_DATA_53_R = SPA(E_SNONE , E_PAGE_09, 0x35), ++ E_REG_P09_EDID_DATA_54_R = SPA(E_SNONE , E_PAGE_09, 0x36), ++ E_REG_P09_EDID_DATA_55_R = SPA(E_SNONE , E_PAGE_09, 0x37), ++ E_REG_P09_EDID_DATA_56_R = SPA(E_SNONE , E_PAGE_09, 0x38), ++ E_REG_P09_EDID_DATA_57_R = SPA(E_SNONE , E_PAGE_09, 0x39), ++ E_REG_P09_EDID_DATA_58_R = SPA(E_SNONE , E_PAGE_09, 0x3A), ++ E_REG_P09_EDID_DATA_59_R = SPA(E_SNONE , E_PAGE_09, 0x3B), ++ E_REG_P09_EDID_DATA_60_R = SPA(E_SNONE , E_PAGE_09, 0x3C), ++ E_REG_P09_EDID_DATA_61_R = SPA(E_SNONE , E_PAGE_09, 0x3D), ++ E_REG_P09_EDID_DATA_62_R = SPA(E_SNONE , E_PAGE_09, 0x3E), ++ E_REG_P09_EDID_DATA_63_R = SPA(E_SNONE , E_PAGE_09, 0x3F), ++ E_REG_P09_EDID_DATA_64_R = SPA(E_SNONE , E_PAGE_09, 0x40), ++ E_REG_P09_EDID_DATA_65_R = SPA(E_SNONE , E_PAGE_09, 0x41), ++ E_REG_P09_EDID_DATA_66_R = SPA(E_SNONE , E_PAGE_09, 0x42), ++ E_REG_P09_EDID_DATA_67_R = SPA(E_SNONE , E_PAGE_09, 0x43), ++ E_REG_P09_EDID_DATA_68_R = SPA(E_SNONE , E_PAGE_09, 0x44), ++ E_REG_P09_EDID_DATA_69_R = SPA(E_SNONE , E_PAGE_09, 0x45), ++ E_REG_P09_EDID_DATA_70_R = SPA(E_SNONE , E_PAGE_09, 0x46), ++ E_REG_P09_EDID_DATA_71_R = SPA(E_SNONE , E_PAGE_09, 0x47), ++ E_REG_P09_EDID_DATA_72_R = SPA(E_SNONE , E_PAGE_09, 0x48), ++ E_REG_P09_EDID_DATA_73_R = SPA(E_SNONE , E_PAGE_09, 0x49), ++ E_REG_P09_EDID_DATA_74_R = SPA(E_SNONE , E_PAGE_09, 0x4A), ++ E_REG_P09_EDID_DATA_75_R = SPA(E_SNONE , E_PAGE_09, 0x4B), ++ E_REG_P09_EDID_DATA_76_R = SPA(E_SNONE , E_PAGE_09, 0x4C), ++ E_REG_P09_EDID_DATA_77_R = SPA(E_SNONE , E_PAGE_09, 0x4D), ++ E_REG_P09_EDID_DATA_78_R = SPA(E_SNONE , E_PAGE_09, 0x4E), ++ E_REG_P09_EDID_DATA_79_R = SPA(E_SNONE , E_PAGE_09, 0x4F), ++ E_REG_P09_EDID_DATA_80_R = SPA(E_SNONE , E_PAGE_09, 0x50), ++ E_REG_P09_EDID_DATA_81_R = SPA(E_SNONE , E_PAGE_09, 0x51), ++ E_REG_P09_EDID_DATA_82_R = SPA(E_SNONE , E_PAGE_09, 0x52), ++ E_REG_P09_EDID_DATA_83_R = SPA(E_SNONE , E_PAGE_09, 0x53), ++ E_REG_P09_EDID_DATA_84_R = SPA(E_SNONE , E_PAGE_09, 0x54), ++ E_REG_P09_EDID_DATA_85_R = SPA(E_SNONE , E_PAGE_09, 0x55), ++ E_REG_P09_EDID_DATA_86_R = SPA(E_SNONE , E_PAGE_09, 0x56), ++ E_REG_P09_EDID_DATA_87_R = SPA(E_SNONE , E_PAGE_09, 0x57), ++ E_REG_P09_EDID_DATA_88_R = SPA(E_SNONE , E_PAGE_09, 0x58), ++ E_REG_P09_EDID_DATA_89_R = SPA(E_SNONE , E_PAGE_09, 0x59), ++ E_REG_P09_EDID_DATA_90_R = SPA(E_SNONE , E_PAGE_09, 0x5A), ++ E_REG_P09_EDID_DATA_91_R = SPA(E_SNONE , E_PAGE_09, 0x5B), ++ E_REG_P09_EDID_DATA_92_R = SPA(E_SNONE , E_PAGE_09, 0x5C), ++ E_REG_P09_EDID_DATA_93_R = SPA(E_SNONE , E_PAGE_09, 0x5D), ++ E_REG_P09_EDID_DATA_94_R = SPA(E_SNONE , E_PAGE_09, 0x5E), ++ E_REG_P09_EDID_DATA_95_R = SPA(E_SNONE , E_PAGE_09, 0x5F), ++ E_REG_P09_EDID_DATA_96_R = SPA(E_SNONE , E_PAGE_09, 0x60), ++ E_REG_P09_EDID_DATA_97_R = SPA(E_SNONE , E_PAGE_09, 0x61), ++ E_REG_P09_EDID_DATA_98_R = SPA(E_SNONE , E_PAGE_09, 0x62), ++ E_REG_P09_EDID_DATA_99_R = SPA(E_SNONE , E_PAGE_09, 0x63), ++ E_REG_P09_EDID_DATA_100_R = SPA(E_SNONE , E_PAGE_09, 0x64), ++ E_REG_P09_EDID_DATA_101_R = SPA(E_SNONE , E_PAGE_09, 0x65), ++ E_REG_P09_EDID_DATA_102_R = SPA(E_SNONE , E_PAGE_09, 0x66), ++ E_REG_P09_EDID_DATA_103_R = SPA(E_SNONE , E_PAGE_09, 0x67), ++ E_REG_P09_EDID_DATA_104_R = SPA(E_SNONE , E_PAGE_09, 0x68), ++ E_REG_P09_EDID_DATA_105_R = SPA(E_SNONE , E_PAGE_09, 0x69), ++ E_REG_P09_EDID_DATA_106_R = SPA(E_SNONE , E_PAGE_09, 0x6A), ++ E_REG_P09_EDID_DATA_107_R = SPA(E_SNONE , E_PAGE_09, 0x6B), ++ E_REG_P09_EDID_DATA_108_R = SPA(E_SNONE , E_PAGE_09, 0x6C), ++ E_REG_P09_EDID_DATA_109_R = SPA(E_SNONE , E_PAGE_09, 0x6D), ++ E_REG_P09_EDID_DATA_110_R = SPA(E_SNONE , E_PAGE_09, 0x6E), ++ E_REG_P09_EDID_DATA_111_R = SPA(E_SNONE , E_PAGE_09, 0x6F), ++ E_REG_P09_EDID_DATA_112_R = SPA(E_SNONE , E_PAGE_09, 0x70), ++ E_REG_P09_EDID_DATA_113_R = SPA(E_SNONE , E_PAGE_09, 0x71), ++ E_REG_P09_EDID_DATA_114_R = SPA(E_SNONE , E_PAGE_09, 0x72), ++ E_REG_P09_EDID_DATA_115_R = SPA(E_SNONE , E_PAGE_09, 0x73), ++ E_REG_P09_EDID_DATA_116_R = SPA(E_SNONE , E_PAGE_09, 0x74), ++ E_REG_P09_EDID_DATA_117_R = SPA(E_SNONE , E_PAGE_09, 0x75), ++ E_REG_P09_EDID_DATA_118_R = SPA(E_SNONE , E_PAGE_09, 0x76), ++ E_REG_P09_EDID_DATA_119_R = SPA(E_SNONE , E_PAGE_09, 0x77), ++ E_REG_P09_EDID_DATA_120_R = SPA(E_SNONE , E_PAGE_09, 0x78), ++ E_REG_P09_EDID_DATA_121_R = SPA(E_SNONE , E_PAGE_09, 0x79), ++ E_REG_P09_EDID_DATA_122_R = SPA(E_SNONE , E_PAGE_09, 0x7A), ++ E_REG_P09_EDID_DATA_123_R = SPA(E_SNONE , E_PAGE_09, 0x7B), ++ E_REG_P09_EDID_DATA_124_R = SPA(E_SNONE , E_PAGE_09, 0x7C), ++ E_REG_P09_EDID_DATA_125_R = SPA(E_SNONE , E_PAGE_09, 0x7D), ++ E_REG_P09_EDID_DATA_126_R = SPA(E_SNONE , E_PAGE_09, 0x7E), ++ E_REG_P09_EDID_DATA_127_R = SPA(E_SNONE , E_PAGE_09, 0x7F), ++ E_REG_P09_EDID_CTRL_RW = SPA(E_SNONE , E_PAGE_09, 0xFA), ++ E_REG_P09_DDC_ADDR_RW = SPA(E_SNONE , E_PAGE_09, 0xFB), ++ E_REG_P09_DDC_OFFS_RW = SPA(E_SNONE , E_PAGE_09, 0xFC), ++ E_REG_P09_DDC_SEGM_ADDR_RW = SPA(E_SNONE , E_PAGE_09, 0xFD), ++ E_REG_P09_DDC_SEGM_RW = SPA(E_SNONE , E_PAGE_09, 0xFE), ++ ++ E_REG_P10_IF1_HB0_RW = SPA(E_SNONE , E_PAGE_10, 0x20), ++ E_REG_P10_IF1_HB1_RW = SPA(E_SNONE , E_PAGE_10, 0x21), ++ E_REG_P10_IF1_HB2_RW = SPA(E_SNONE , E_PAGE_10, 0x22), ++ E_REG_P10_IF1_PB0_RW = SPA(E_SNONE , E_PAGE_10, 0x23), ++ E_REG_P10_IF1_PB1_RW = SPA(E_SNONE , E_PAGE_10, 0x24), ++ E_REG_P10_IF1_PB2_RW = SPA(E_SNONE , E_PAGE_10, 0x25), ++ E_REG_P10_IF1_PB3_RW = SPA(E_SNONE , E_PAGE_10, 0x26), ++ E_REG_P10_IF1_PB4_RW = SPA(E_SNONE , E_PAGE_10, 0x27), ++ E_REG_P10_IF1_PB5_RW = SPA(E_SNONE , E_PAGE_10, 0x28), ++ E_REG_P10_IF1_PB6_RW = SPA(E_SNONE , E_PAGE_10, 0x29), ++ E_REG_P10_IF1_PB7_RW = SPA(E_SNONE , E_PAGE_10, 0x2A), ++ E_REG_P10_IF1_PB8_RW = SPA(E_SNONE , E_PAGE_10, 0x2B), ++ E_REG_P10_IF1_PB9_RW = SPA(E_SNONE , E_PAGE_10, 0x2C), ++ E_REG_P10_IF1_PB10_RW = SPA(E_SNONE , E_PAGE_10, 0x2D), ++ E_REG_P10_IF1_PB11_RW = SPA(E_SNONE , E_PAGE_10, 0x2E), ++ E_REG_P10_IF1_PB12_RW = SPA(E_SNONE , E_PAGE_10, 0x2F), ++ E_REG_P10_IF1_PB13_RW = SPA(E_SNONE , E_PAGE_10, 0x30), ++ E_REG_P10_IF1_PB14_RW = SPA(E_SNONE , E_PAGE_10, 0x31), ++ E_REG_P10_IF1_PB15_RW = SPA(E_SNONE , E_PAGE_10, 0x32), ++ E_REG_P10_IF1_PB16_RW = SPA(E_SNONE , E_PAGE_10, 0x33), ++ E_REG_P10_IF1_PB17_RW = SPA(E_SNONE , E_PAGE_10, 0x34), ++ E_REG_P10_IF1_PB18_RW = SPA(E_SNONE , E_PAGE_10, 0x35), ++ E_REG_P10_IF1_PB19_RW = SPA(E_SNONE , E_PAGE_10, 0x36), ++ E_REG_P10_IF1_PB20_RW = SPA(E_SNONE , E_PAGE_10, 0x37), ++ E_REG_P10_IF1_PB21_RW = SPA(E_SNONE , E_PAGE_10, 0x38), ++ E_REG_P10_IF1_PB22_RW = SPA(E_SNONE , E_PAGE_10, 0x39), ++ E_REG_P10_IF1_PB23_RW = SPA(E_SNONE , E_PAGE_10, 0x3A), ++ E_REG_P10_IF1_PB24_RW = SPA(E_SNONE , E_PAGE_10, 0x3B), ++ E_REG_P10_IF1_PB25_RW = SPA(E_SNONE , E_PAGE_10, 0x3C), ++ E_REG_P10_IF1_PB26_RW = SPA(E_SNONE , E_PAGE_10, 0x3D), ++ E_REG_P10_IF1_PB27_RW = SPA(E_SNONE , E_PAGE_10, 0x3E), ++ E_REG_P10_IF2_HB0_RW = SPA(E_SNONE , E_PAGE_10, 0x40), ++ E_REG_P10_IF2_HB1_RW = SPA(E_SNONE , E_PAGE_10, 0x41), ++ E_REG_P10_IF2_HB2_RW = SPA(E_SNONE , E_PAGE_10, 0x42), ++ E_REG_P10_IF2_PB0_RW = SPA(E_SNONE , E_PAGE_10, 0x43), ++ E_REG_P10_IF2_PB1_RW = SPA(E_SNONE , E_PAGE_10, 0x44), ++ E_REG_P10_IF2_PB2_RW = SPA(E_SNONE , E_PAGE_10, 0x45), ++ E_REG_P10_IF2_PB3_RW = SPA(E_SNONE , E_PAGE_10, 0x46), ++ E_REG_P10_IF2_PB4_RW = SPA(E_SNONE , E_PAGE_10, 0x47), ++ E_REG_P10_IF2_PB5_RW = SPA(E_SNONE , E_PAGE_10, 0x48), ++ E_REG_P10_IF2_PB6_RW = SPA(E_SNONE , E_PAGE_10, 0x49), ++ E_REG_P10_IF2_PB7_RW = SPA(E_SNONE , E_PAGE_10, 0x4A), ++ E_REG_P10_IF2_PB8_RW = SPA(E_SNONE , E_PAGE_10, 0x4B), ++ E_REG_P10_IF2_PB9_RW = SPA(E_SNONE , E_PAGE_10, 0x4C), ++ E_REG_P10_IF2_PB10_RW = SPA(E_SNONE , E_PAGE_10, 0x4D), ++ E_REG_P10_IF2_PB11_RW = SPA(E_SNONE , E_PAGE_10, 0x4E), ++ E_REG_P10_IF2_PB12_RW = SPA(E_SNONE , E_PAGE_10, 0x4F), ++ E_REG_P10_IF2_PB13_RW = SPA(E_SNONE , E_PAGE_10, 0x50), ++ E_REG_P10_IF2_PB14_RW = SPA(E_SNONE , E_PAGE_10, 0x51), ++ E_REG_P10_IF2_PB15_RW = SPA(E_SNONE , E_PAGE_10, 0x52), ++ E_REG_P10_IF2_PB16_RW = SPA(E_SNONE , E_PAGE_10, 0x53), ++ E_REG_P10_IF2_PB17_RW = SPA(E_SNONE , E_PAGE_10, 0x54), ++ E_REG_P10_IF2_PB18_RW = SPA(E_SNONE , E_PAGE_10, 0x55), ++ E_REG_P10_IF2_PB19_RW = SPA(E_SNONE , E_PAGE_10, 0x56), ++ E_REG_P10_IF2_PB20_RW = SPA(E_SNONE , E_PAGE_10, 0x57), ++ E_REG_P10_IF2_PB21_RW = SPA(E_SNONE , E_PAGE_10, 0x58), ++ E_REG_P10_IF2_PB22_RW = SPA(E_SNONE , E_PAGE_10, 0x59), ++ E_REG_P10_IF2_PB23_RW = SPA(E_SNONE , E_PAGE_10, 0x5A), ++ E_REG_P10_IF2_PB24_RW = SPA(E_SNONE , E_PAGE_10, 0x5B), ++ E_REG_P10_IF2_PB25_RW = SPA(E_SNONE , E_PAGE_10, 0x5C), ++ E_REG_P10_IF2_PB26_RW = SPA(E_SNONE , E_PAGE_10, 0x5D), ++ E_REG_P10_IF2_PB27_RW = SPA(E_SNONE , E_PAGE_10, 0x5E), ++ E_REG_P10_IF3_HB0_RW = SPA(E_SNONE , E_PAGE_10, 0x60), ++ E_REG_P10_IF3_HB1_RW = SPA(E_SNONE , E_PAGE_10, 0x61), ++ E_REG_P10_IF3_HB2_RW = SPA(E_SNONE , E_PAGE_10, 0x62), ++ E_REG_P10_IF3_PB0_RW = SPA(E_SNONE , E_PAGE_10, 0x63), ++ E_REG_P10_IF3_PB1_RW = SPA(E_SNONE , E_PAGE_10, 0x64), ++ E_REG_P10_IF3_PB2_RW = SPA(E_SNONE , E_PAGE_10, 0x65), ++ E_REG_P10_IF3_PB3_RW = SPA(E_SNONE , E_PAGE_10, 0x66), ++ E_REG_P10_IF3_PB4_RW = SPA(E_SNONE , E_PAGE_10, 0x67), ++ E_REG_P10_IF3_PB5_RW = SPA(E_SNONE , E_PAGE_10, 0x68), ++ E_REG_P10_IF3_PB6_RW = SPA(E_SNONE , E_PAGE_10, 0x69), ++ E_REG_P10_IF3_PB7_RW = SPA(E_SNONE , E_PAGE_10, 0x6A), ++ E_REG_P10_IF3_PB8_RW = SPA(E_SNONE , E_PAGE_10, 0x6B), ++ E_REG_P10_IF3_PB9_RW = SPA(E_SNONE , E_PAGE_10, 0x6C), ++ E_REG_P10_IF3_PB10_RW = SPA(E_SNONE , E_PAGE_10, 0x6D), ++ E_REG_P10_IF3_PB11_RW = SPA(E_SNONE , E_PAGE_10, 0x6E), ++ E_REG_P10_IF3_PB12_RW = SPA(E_SNONE , E_PAGE_10, 0x6F), ++ E_REG_P10_IF3_PB13_RW = SPA(E_SNONE , E_PAGE_10, 0x70), ++ E_REG_P10_IF3_PB14_RW = SPA(E_SNONE , E_PAGE_10, 0x71), ++ E_REG_P10_IF3_PB15_RW = SPA(E_SNONE , E_PAGE_10, 0x72), ++ E_REG_P10_IF3_PB16_RW = SPA(E_SNONE , E_PAGE_10, 0x73), ++ E_REG_P10_IF3_PB17_RW = SPA(E_SNONE , E_PAGE_10, 0x74), ++ E_REG_P10_IF3_PB18_RW = SPA(E_SNONE , E_PAGE_10, 0x75), ++ E_REG_P10_IF3_PB19_RW = SPA(E_SNONE , E_PAGE_10, 0x76), ++ E_REG_P10_IF3_PB20_RW = SPA(E_SNONE , E_PAGE_10, 0x77), ++ E_REG_P10_IF3_PB21_RW = SPA(E_SNONE , E_PAGE_10, 0x78), ++ E_REG_P10_IF3_PB22_RW = SPA(E_SNONE , E_PAGE_10, 0x79), ++ E_REG_P10_IF3_PB23_RW = SPA(E_SNONE , E_PAGE_10, 0x7A), ++ E_REG_P10_IF3_PB24_RW = SPA(E_SNONE , E_PAGE_10, 0x7B), ++ E_REG_P10_IF3_PB25_RW = SPA(E_SNONE , E_PAGE_10, 0x7C), ++ E_REG_P10_IF3_PB26_RW = SPA(E_SNONE , E_PAGE_10, 0x7D), ++ E_REG_P10_IF3_PB27_RW = SPA(E_SNONE , E_PAGE_10, 0x7E), ++ E_REG_P10_IF4_HB0_RW = SPA(E_SNONE , E_PAGE_10, 0x80), ++ E_REG_P10_IF4_HB1_RW = SPA(E_SNONE , E_PAGE_10, 0x81), ++ E_REG_P10_IF4_HB2_RW = SPA(E_SNONE , E_PAGE_10, 0x82), ++ E_REG_P10_IF4_PB0_RW = SPA(E_SNONE , E_PAGE_10, 0x83), ++ E_REG_P10_IF4_PB1_RW = SPA(E_SNONE , E_PAGE_10, 0x84), ++ E_REG_P10_IF4_PB2_RW = SPA(E_SNONE , E_PAGE_10, 0x85), ++ E_REG_P10_IF4_PB3_RW = SPA(E_SNONE , E_PAGE_10, 0x86), ++ E_REG_P10_IF4_PB4_RW = SPA(E_SNONE , E_PAGE_10, 0x87), ++ E_REG_P10_IF4_PB5_RW = SPA(E_SNONE , E_PAGE_10, 0x88), ++ E_REG_P10_IF4_PB6_RW = SPA(E_SNONE , E_PAGE_10, 0x89), ++ E_REG_P10_IF4_PB7_RW = SPA(E_SNONE , E_PAGE_10, 0x8A), ++ E_REG_P10_IF4_PB8_RW = SPA(E_SNONE , E_PAGE_10, 0x8B), ++ E_REG_P10_IF4_PB9_RW = SPA(E_SNONE , E_PAGE_10, 0x8C), ++ E_REG_P10_IF4_PB10_RW = SPA(E_SNONE , E_PAGE_10, 0x8D), ++ E_REG_P10_IF4_PB11_RW = SPA(E_SNONE , E_PAGE_10, 0x8E), ++ E_REG_P10_IF4_PB12_RW = SPA(E_SNONE , E_PAGE_10, 0x8F), ++ E_REG_P10_IF4_PB13_RW = SPA(E_SNONE , E_PAGE_10, 0x90), ++ E_REG_P10_IF4_PB14_RW = SPA(E_SNONE , E_PAGE_10, 0x91), ++ E_REG_P10_IF4_PB15_RW = SPA(E_SNONE , E_PAGE_10, 0x92), ++ E_REG_P10_IF4_PB16_RW = SPA(E_SNONE , E_PAGE_10, 0x93), ++ E_REG_P10_IF4_PB17_RW = SPA(E_SNONE , E_PAGE_10, 0x94), ++ E_REG_P10_IF4_PB18_RW = SPA(E_SNONE , E_PAGE_10, 0x95), ++ E_REG_P10_IF4_PB19_RW = SPA(E_SNONE , E_PAGE_10, 0x96), ++ E_REG_P10_IF4_PB20_RW = SPA(E_SNONE , E_PAGE_10, 0x97), ++ E_REG_P10_IF4_PB21_RW = SPA(E_SNONE , E_PAGE_10, 0x98), ++ E_REG_P10_IF4_PB22_RW = SPA(E_SNONE , E_PAGE_10, 0x99), ++ E_REG_P10_IF4_PB23_RW = SPA(E_SNONE , E_PAGE_10, 0x9A), ++ E_REG_P10_IF4_PB24_RW = SPA(E_SNONE , E_PAGE_10, 0x9B), ++ E_REG_P10_IF4_PB25_RW = SPA(E_SNONE , E_PAGE_10, 0x9C), ++ E_REG_P10_IF4_PB26_RW = SPA(E_SNONE , E_PAGE_10, 0x9D), ++ E_REG_P10_IF4_PB27_RW = SPA(E_SNONE , E_PAGE_10, 0x9E), ++ E_REG_P10_IF5_HB0_RW = SPA(E_SNONE , E_PAGE_10, 0xA0), ++ E_REG_P10_IF5_HB1_RW = SPA(E_SNONE , E_PAGE_10, 0xA1), ++ E_REG_P10_IF5_HB2_RW = SPA(E_SNONE , E_PAGE_10, 0xA2), ++ E_REG_P10_IF5_PB0_RW = SPA(E_SNONE , E_PAGE_10, 0xA3), ++ E_REG_P10_IF5_PB1_RW = SPA(E_SNONE , E_PAGE_10, 0xA4), ++ E_REG_P10_IF5_PB2_RW = SPA(E_SNONE , E_PAGE_10, 0xA5), ++ E_REG_P10_IF5_PB3_RW = SPA(E_SNONE , E_PAGE_10, 0xA6), ++ E_REG_P10_IF5_PB4_RW = SPA(E_SNONE , E_PAGE_10, 0xA7), ++ E_REG_P10_IF5_PB5_RW = SPA(E_SNONE , E_PAGE_10, 0xA8), ++ E_REG_P10_IF5_PB6_RW = SPA(E_SNONE , E_PAGE_10, 0xA9), ++ E_REG_P10_IF5_PB7_RW = SPA(E_SNONE , E_PAGE_10, 0xAA), ++ E_REG_P10_IF5_PB8_RW = SPA(E_SNONE , E_PAGE_10, 0xAB), ++ E_REG_P10_IF5_PB9_RW = SPA(E_SNONE , E_PAGE_10, 0xAC), ++ E_REG_P10_IF5_PB10_RW = SPA(E_SNONE , E_PAGE_10, 0xAD), ++ E_REG_P10_IF5_PB11_RW = SPA(E_SNONE , E_PAGE_10, 0xAE), ++ E_REG_P10_IF5_PB12_RW = SPA(E_SNONE , E_PAGE_10, 0xAF), ++ E_REG_P10_IF5_PB13_RW = SPA(E_SNONE , E_PAGE_10, 0xB0), ++ E_REG_P10_IF5_PB14_RW = SPA(E_SNONE , E_PAGE_10, 0xB1), ++ E_REG_P10_IF5_PB15_RW = SPA(E_SNONE , E_PAGE_10, 0xB2), ++ E_REG_P10_IF5_PB16_RW = SPA(E_SNONE , E_PAGE_10, 0xB3), ++ E_REG_P10_IF5_PB17_RW = SPA(E_SNONE , E_PAGE_10, 0xB4), ++ E_REG_P10_IF5_PB18_RW = SPA(E_SNONE , E_PAGE_10, 0xB5), ++ E_REG_P10_IF5_PB19_RW = SPA(E_SNONE , E_PAGE_10, 0xB6), ++ E_REG_P10_IF5_PB20_RW = SPA(E_SNONE , E_PAGE_10, 0xB7), ++ E_REG_P10_IF5_PB21_RW = SPA(E_SNONE , E_PAGE_10, 0xB8), ++ E_REG_P10_IF5_PB22_RW = SPA(E_SNONE , E_PAGE_10, 0xB9), ++ E_REG_P10_IF5_PB23_RW = SPA(E_SNONE , E_PAGE_10, 0xBA), ++ E_REG_P10_IF5_PB24_RW = SPA(E_SNONE , E_PAGE_10, 0xBB), ++ E_REG_P10_IF5_PB25_RW = SPA(E_SNONE , E_PAGE_10, 0xBC), ++ E_REG_P10_IF5_PB26_RW = SPA(E_SNONE , E_PAGE_10, 0xBD), ++ E_REG_P10_IF5_PB27_RW = SPA(E_SNONE , E_PAGE_10, 0xBE), ++ E_REG_P11_AIP_CNTRL_0_RW = SPA(E_SNONE , E_PAGE_11, 0x00), ++ E_REG_P11_CA_I2S_RW = SPA(E_SNONE , E_PAGE_11, 0x01), ++ E_REG_P11_CA_DSD_RW = SPA(E_SNONE , E_PAGE_11, 0x02), ++ E_REG_P11_OBA_PH_RW = SPA(E_SNONE , E_PAGE_11, 0x03), ++ E_REG_P11_LATENCY_RD_RW = SPA(E_SNONE , E_PAGE_11, 0x04), ++ E_REG_P11_ACR_CTS_0_RW = SPA(E_SNONE , E_PAGE_11, 0x05), ++ E_REG_P11_ACR_CTS_1_RW = SPA(E_SNONE , E_PAGE_11, 0x06), ++ E_REG_P11_ACR_CTS_2_RW = SPA(E_SNONE , E_PAGE_11, 0x07), ++ E_REG_P11_ACR_N_0_RW = SPA(E_SNONE , E_PAGE_11, 0x08), ++ E_REG_P11_ACR_N_1_RW = SPA(E_SNONE , E_PAGE_11, 0x09), ++ E_REG_P11_ACR_N_2_RW = SPA(E_SNONE , E_PAGE_11, 0x0A), ++ E_REG_P11_GC_AVMUTE_RW = SPA(E_SNONE , E_PAGE_11, 0x0B), ++ E_REG_P11_CTS_N_RW = SPA(E_SNONE , E_PAGE_11, 0x0C), ++ E_REG_P11_ENC_CNTRL_RW = SPA(E_SNONE , E_PAGE_11, 0x0D), ++ E_REG_P11_DIP_FLAGS_RW = SPA(E_SNONE , E_PAGE_11, 0x0E), ++ E_REG_P11_DIP_IF_FLAGS_RW = SPA(E_SNONE , E_PAGE_11, 0x0F), ++ E_REG_P11_CH_STAT_B_0_RW = SPA(E_SNONE , E_PAGE_11, 0x14), ++ E_REG_P11_CH_STAT_B_1_RW = SPA(E_SNONE , E_PAGE_11, 0x15), ++ E_REG_P11_CH_STAT_B_3_RW = SPA(E_SNONE , E_PAGE_11, 0x16), ++ E_REG_P11_CH_STAT_B_4_RW = SPA(E_SNONE , E_PAGE_11, 0x17), ++ E_REG_P11_CH_STAT_B_2_ap0_l_RW = SPA(E_SNONE , E_PAGE_11, 0x18), ++ E_REG_P11_CH_STAT_B_2_ap0_r_RW = SPA(E_SNONE , E_PAGE_11, 0x19), ++ E_REG_P11_CH_STAT_B_2_ap1_l_RW = SPA(E_SNONE , E_PAGE_11, 0x1A), ++ E_REG_P11_CH_STAT_B_2_ap1_r_RW = SPA(E_SNONE , E_PAGE_11, 0x1B), ++ E_REG_P11_CH_STAT_B_2_ap2_l_RW = SPA(E_SNONE , E_PAGE_11, 0x1C), ++ E_REG_P11_CH_STAT_B_2_ap2_r_RW = SPA(E_SNONE , E_PAGE_11, 0x1D), ++ E_REG_P11_CH_STAT_B_2_ap3_l_RW = SPA(E_SNONE , E_PAGE_11, 0x1E), ++ E_REG_P11_CH_STAT_B_2_ap3_r_RW = SPA(E_SNONE , E_PAGE_11, 0x1F), ++ E_REG_P11_ISRC1_HB0_RW = SPA(E_SNONE , E_PAGE_11, 0x20), ++ E_REG_P11_ISRC1_HB1_RW = SPA(E_SNONE , E_PAGE_11, 0x21), ++ E_REG_P11_ISRC1_HB2_RW = SPA(E_SNONE , E_PAGE_11, 0x22), ++ E_REG_P11_ISRC1_PB0_RW = SPA(E_SNONE , E_PAGE_11, 0x23), ++ E_REG_P11_ISRC1_PB1_RW = SPA(E_SNONE , E_PAGE_11, 0x24), ++ E_REG_P11_ISRC1_PB2_RW = SPA(E_SNONE , E_PAGE_11, 0x25), ++ E_REG_P11_ISRC1_PB3_RW = SPA(E_SNONE , E_PAGE_11, 0x26), ++ E_REG_P11_ISRC1_PB4_RW = SPA(E_SNONE , E_PAGE_11, 0x27), ++ E_REG_P11_ISRC1_PB5_RW = SPA(E_SNONE , E_PAGE_11, 0x28), ++ E_REG_P11_ISRC1_PB6_RW = SPA(E_SNONE , E_PAGE_11, 0x29), ++ E_REG_P11_ISRC1_PB7_RW = SPA(E_SNONE , E_PAGE_11, 0x2A), ++ E_REG_P11_ISRC1_PB8_RW = SPA(E_SNONE , E_PAGE_11, 0x2B), ++ E_REG_P11_ISRC1_PB9_RW = SPA(E_SNONE , E_PAGE_11, 0x2C), ++ E_REG_P11_ISRC1_PB10_RW = SPA(E_SNONE , E_PAGE_11, 0x2D), ++ E_REG_P11_ISRC1_PB11_RW = SPA(E_SNONE , E_PAGE_11, 0x2E), ++ E_REG_P11_ISRC1_PB12_RW = SPA(E_SNONE , E_PAGE_11, 0x2F), ++ E_REG_P11_ISRC1_PB13_RW = SPA(E_SNONE , E_PAGE_11, 0x30), ++ E_REG_P11_ISRC1_PB14_RW = SPA(E_SNONE , E_PAGE_11, 0x31), ++ E_REG_P11_ISRC1_PB15_RW = SPA(E_SNONE , E_PAGE_11, 0x32), ++ E_REG_P11_ISRC1_PB16_RW = SPA(E_SNONE , E_PAGE_11, 0x33), ++ E_REG_P11_ISRC1_PB17_RW = SPA(E_SNONE , E_PAGE_11, 0x34), ++ E_REG_P11_ISRC1_PB18_RW = SPA(E_SNONE , E_PAGE_11, 0x35), ++ E_REG_P11_ISRC1_PB19_RW = SPA(E_SNONE , E_PAGE_11, 0x36), ++ E_REG_P11_ISRC1_PB20_RW = SPA(E_SNONE , E_PAGE_11, 0x37), ++ E_REG_P11_ISRC1_PB21_RW = SPA(E_SNONE , E_PAGE_11, 0x38), ++ E_REG_P11_ISRC1_PB22_RW = SPA(E_SNONE , E_PAGE_11, 0x39), ++ E_REG_P11_ISRC1_PB23_RW = SPA(E_SNONE , E_PAGE_11, 0x3A) , ++ E_REG_P11_ISRC1_PB24_RW = SPA(E_SNONE , E_PAGE_11, 0x3B) , ++ E_REG_P11_ISRC1_PB25_RW = SPA(E_SNONE , E_PAGE_11, 0x3C), ++ E_REG_P11_ISRC1_PB26_RW = SPA(E_SNONE , E_PAGE_11, 0x3D), ++ E_REG_P11_ISRC1_PB27_RW = SPA(E_SNONE , E_PAGE_11, 0x3E), ++ E_REG_P11_ISRC2_HB0_RW = SPA(E_SNONE , E_PAGE_11, 0x40), ++ E_REG_P11_ISRC2_HB1_RW = SPA(E_SNONE , E_PAGE_11, 0x41), ++ E_REG_P11_ISRC2_HB2_RW = SPA(E_SNONE , E_PAGE_11, 0x42), ++ E_REG_P11_ISRC2_PB0_RW = SPA(E_SNONE , E_PAGE_11, 0x43), ++ E_REG_P11_ISRC2_PB1_RW = SPA(E_SNONE , E_PAGE_11, 0x44), ++ E_REG_P11_ISRC2_PB2_RW = SPA(E_SNONE , E_PAGE_11, 0x45), ++ E_REG_P11_ISRC2_PB3_RW = SPA(E_SNONE , E_PAGE_11, 0x46), ++ E_REG_P11_ISRC2_PB4_RW = SPA(E_SNONE , E_PAGE_11, 0x47), ++ E_REG_P11_ISRC2_PB5_RW = SPA(E_SNONE , E_PAGE_11, 0x48), ++ E_REG_P11_ISRC2_PB6_RW = SPA(E_SNONE , E_PAGE_11, 0x49), ++ E_REG_P11_ISRC2_PB7_RW = SPA(E_SNONE , E_PAGE_11, 0x4A), ++ E_REG_P11_ISRC2_PB8_RW = SPA(E_SNONE , E_PAGE_11, 0x4B), ++ E_REG_P11_ISRC2_PB9_RW = SPA(E_SNONE , E_PAGE_11, 0x4C), ++ E_REG_P11_ISRC2_PB10_RW = SPA(E_SNONE , E_PAGE_11, 0x4D), ++ E_REG_P11_ISRC2_PB11_RW = SPA(E_SNONE , E_PAGE_11, 0x4E), ++ E_REG_P11_ISRC2_PB12_RW = SPA(E_SNONE , E_PAGE_11, 0x4F), ++ E_REG_P11_ISRC2_PB13_RW = SPA(E_SNONE , E_PAGE_11, 0x50), ++ E_REG_P11_ISRC2_PB14_RW = SPA(E_SNONE , E_PAGE_11, 0x51), ++ E_REG_P11_ISRC2_PB15_RW = SPA(E_SNONE , E_PAGE_11, 0x52), ++ E_REG_P11_ISRC2_PB16_RW = SPA(E_SNONE , E_PAGE_11, 0x53), ++ E_REG_P11_ISRC2_PB17_RW = SPA(E_SNONE , E_PAGE_11, 0x54), ++ E_REG_P11_ISRC2_PB18_RW = SPA(E_SNONE , E_PAGE_11, 0x55), ++ E_REG_P11_ISRC2_PB19_RW = SPA(E_SNONE , E_PAGE_11, 0x56), ++ E_REG_P11_ISRC2_PB20_RW = SPA(E_SNONE , E_PAGE_11, 0x57), ++ E_REG_P11_ISRC2_PB21_RW = SPA(E_SNONE , E_PAGE_11, 0x58), ++ E_REG_P11_ISRC2_PB22_RW = SPA(E_SNONE , E_PAGE_11, 0x59), ++ E_REG_P11_ISRC2_PB23_RW = SPA(E_SNONE , E_PAGE_11, 0x5A), ++ E_REG_P11_ISRC2_PB24_RW = SPA(E_SNONE , E_PAGE_11, 0x5B), ++ E_REG_P11_ISRC2_PB25_RW = SPA(E_SNONE , E_PAGE_11, 0x5C), ++ E_REG_P11_ISRC2_PB26_RW = SPA(E_SNONE , E_PAGE_11, 0x5D), ++ E_REG_P11_ISRC2_PB27_RW = SPA(E_SNONE , E_PAGE_11, 0x5E), ++ E_REG_P11_ACP_HB0_RW = SPA(E_SNONE , E_PAGE_11, 0x60), ++ E_REG_P11_ACP_HB1_RW = SPA(E_SNONE , E_PAGE_11, 0x61), ++ E_REG_P11_ACP_HB2_RW = SPA(E_SNONE , E_PAGE_11, 0x62), ++ E_REG_P11_ACP_PB0_RW = SPA(E_SNONE , E_PAGE_11, 0x63), ++ E_REG_P11_ACP_PB1_RW = SPA(E_SNONE , E_PAGE_11, 0x64), ++ E_REG_P11_ACP_PB2_RW = SPA(E_SNONE , E_PAGE_11, 0x65), ++ E_REG_P11_ACP_PB3_RW = SPA(E_SNONE , E_PAGE_11, 0x66), ++ E_REG_P11_ACP_PB4_RW = SPA(E_SNONE , E_PAGE_11, 0x67), ++ E_REG_P11_ACP_PB5_RW = SPA(E_SNONE , E_PAGE_11, 0x68), ++ E_REG_P11_ACP_PB6_RW = SPA(E_SNONE , E_PAGE_11, 0x69), ++ E_REG_P11_ACP_PB7_RW = SPA(E_SNONE , E_PAGE_11, 0x6A), ++ E_REG_P11_ACP_PB8_RW = SPA(E_SNONE , E_PAGE_11, 0x6B), ++ E_REG_P11_ACP_PB9_RW = SPA(E_SNONE , E_PAGE_11, 0x6C), ++ E_REG_P11_ACP_PB10_RW = SPA(E_SNONE , E_PAGE_11, 0x6D), ++ E_REG_P11_ACP_PB11_RW = SPA(E_SNONE , E_PAGE_11, 0x6E), ++ E_REG_P11_ACP_PB12_RW = SPA(E_SNONE , E_PAGE_11, 0x6F), ++ E_REG_P11_ACP_PB13_RW = SPA(E_SNONE , E_PAGE_11, 0x70), ++ E_REG_P11_ACP_PB14_RW = SPA(E_SNONE , E_PAGE_11, 0x71), ++ E_REG_P11_ACP_PB15_RW = SPA(E_SNONE , E_PAGE_11, 0x72), ++ E_REG_P11_ACP_PB16_RW = SPA(E_SNONE , E_PAGE_11, 0x73), ++ E_REG_P11_ACP_PB17_RW = SPA(E_SNONE , E_PAGE_11, 0x74), ++ E_REG_P11_ACP_PB18_RW = SPA(E_SNONE , E_PAGE_11, 0x75), ++ E_REG_P11_ACP_PB19_RW = SPA(E_SNONE , E_PAGE_11, 0x76), ++ E_REG_P11_ACP_PB20_RW = SPA(E_SNONE , E_PAGE_11, 0x77), ++ E_REG_P11_ACP_PB21_RW = SPA(E_SNONE , E_PAGE_11, 0x78), ++ E_REG_P11_ACP_PB22_RW = SPA(E_SNONE , E_PAGE_11, 0x79), ++ E_REG_P11_ACP_PB23_RW = SPA(E_SNONE , E_PAGE_11, 0x7A), ++ E_REG_P11_ACP_PB24_RW = SPA(E_SNONE , E_PAGE_11, 0x7B), ++ E_REG_P11_ACP_PB25_RW = SPA(E_SNONE , E_PAGE_11, 0x7C), ++ E_REG_P11_ACP_PB26_RW = SPA(E_SNONE , E_PAGE_11, 0x7D), ++ E_REG_P11_ACP_PB27_RW = SPA(E_SNONE , E_PAGE_11, 0x7E), ++ E_REG_P13_GMD_0_HB0_RW = SPA(E_SNONE , E_PAGE_13, 0x00), ++ E_REG_P13_GMD_0_HB1_RW = SPA(E_SNONE , E_PAGE_13, 0x01), ++ E_REG_P13_GMD_0_HB2_RW = SPA(E_SNONE , E_PAGE_13, 0x02), ++ E_REG_P13_GMD_0_PB0_RW = SPA(E_SNONE , E_PAGE_13, 0x03), ++ E_REG_P13_GMD_0_PB1_RW = SPA(E_SNONE , E_PAGE_13, 0x04), ++ E_REG_P13_GMD_0_PB2_RW = SPA(E_SNONE , E_PAGE_13, 0x05), ++ E_REG_P13_GMD_0_PB3_RW = SPA(E_SNONE , E_PAGE_13, 0x06), ++ E_REG_P13_GMD_0_PB4_RW = SPA(E_SNONE , E_PAGE_13, 0x07), ++ E_REG_P13_GMD_0_PB5_RW = SPA(E_SNONE , E_PAGE_13, 0x08), ++ E_REG_P13_GMD_0_PB6_RW = SPA(E_SNONE , E_PAGE_13, 0x09), ++ E_REG_P13_GMD_0_PB7_RW = SPA(E_SNONE , E_PAGE_13, 0x0A), ++ E_REG_P13_GMD_0_PB8_RW = SPA(E_SNONE , E_PAGE_13, 0x0B), ++ E_REG_P13_GMD_0_PB9_RW = SPA(E_SNONE , E_PAGE_13, 0x0C), ++ E_REG_P13_GMD_0_PB10_RW = SPA(E_SNONE , E_PAGE_13, 0x0D), ++ E_REG_P13_GMD_0_PB11_RW = SPA(E_SNONE , E_PAGE_13, 0x0E), ++ E_REG_P13_GMD_0_PB12_RW = SPA(E_SNONE , E_PAGE_13, 0x0F), ++ E_REG_P13_GMD_0_PB13_RW = SPA(E_SNONE , E_PAGE_13, 0x10), ++ E_REG_P13_GMD_0_PB14_RW = SPA(E_SNONE , E_PAGE_13, 0x11), ++ E_REG_P13_GMD_0_PB15_RW = SPA(E_SNONE , E_PAGE_13, 0x12), ++ E_REG_P13_GMD_0_PB16_RW = SPA(E_SNONE , E_PAGE_13, 0x13), ++ E_REG_P13_GMD_0_PB17_RW = SPA(E_SNONE , E_PAGE_13, 0x14), ++ E_REG_P13_GMD_0_PB18_RW = SPA(E_SNONE , E_PAGE_13, 0x15), ++ E_REG_P13_GMD_0_PB19_RW = SPA(E_SNONE , E_PAGE_13, 0x16), ++ E_REG_P13_GMD_0_PB20_RW = SPA(E_SNONE , E_PAGE_13, 0x17), ++ E_REG_P13_GMD_0_PB21_RW = SPA(E_SNONE , E_PAGE_13, 0x18), ++ E_REG_P13_GMD_0_PB22_RW = SPA(E_SNONE , E_PAGE_13, 0x19), ++ E_REG_P13_GMD_0_PB23_RW = SPA(E_SNONE , E_PAGE_13, 0x1A), ++ E_REG_P13_GMD_0_PB24_RW = SPA(E_SNONE , E_PAGE_13, 0x1B), ++ E_REG_P13_GMD_0_PB25_RW = SPA(E_SNONE , E_PAGE_13, 0x1C), ++ E_REG_P13_GMD_0_PB26_RW = SPA(E_SNONE , E_PAGE_13, 0x1D), ++ E_REG_P13_GMD_0_PB27_RW = SPA(E_SNONE , E_PAGE_13, 0x1E), ++ E_REG_P13_GMD_CONTROL_RW = SPA(E_SNONE , E_PAGE_13, 0x1F), ++ E_REG_P13_GMD_1_HB0_RW = SPA(E_SNONE , E_PAGE_13, 0x20), ++ E_REG_P13_GMD_1_HB1_RW = SPA(E_SNONE , E_PAGE_13, 0x21), ++ E_REG_P13_GMD_1_HB2_RW = SPA(E_SNONE , E_PAGE_13, 0x22), ++ E_REG_P13_GMD_1_PB0_RW = SPA(E_SNONE , E_PAGE_13, 0x23), ++ E_REG_P13_GMD_1_PB1_RW = SPA(E_SNONE , E_PAGE_13, 0x24), ++ E_REG_P13_GMD_1_PB2_RW = SPA(E_SNONE , E_PAGE_13, 0x25), ++ E_REG_P13_GMD_1_PB3_RW = SPA(E_SNONE , E_PAGE_13, 0x26), ++ E_REG_P13_GMD_1_PB4_RW = SPA(E_SNONE , E_PAGE_13, 0x27), ++ E_REG_P13_GMD_1_PB5_RW = SPA(E_SNONE , E_PAGE_13, 0x28), ++ E_REG_P13_GMD_1_PB6_RW = SPA(E_SNONE , E_PAGE_13, 0x29), ++ E_REG_P13_GMD_1_PB7_RW = SPA(E_SNONE , E_PAGE_13, 0x2A), ++ E_REG_P13_GMD_1_PB8_RW = SPA(E_SNONE , E_PAGE_13, 0x2B), ++ E_REG_P13_GMD_1_PB9_RW = SPA(E_SNONE , E_PAGE_13, 0x2C), ++ E_REG_P13_GMD_1_PB10_RW = SPA(E_SNONE , E_PAGE_13, 0x2D), ++ E_REG_P13_GMD_1_PB11_RW = SPA(E_SNONE , E_PAGE_13, 0x2E), ++ E_REG_P13_GMD_1_PB12_RW = SPA(E_SNONE , E_PAGE_13, 0x2F), ++ E_REG_P13_GMD_1_PB13_RW = SPA(E_SNONE , E_PAGE_13, 0x30), ++ E_REG_P13_GMD_1_PB14_RW = SPA(E_SNONE , E_PAGE_13, 0x31), ++ E_REG_P13_GMD_1_PB15_RW = SPA(E_SNONE , E_PAGE_13, 0x32), ++ E_REG_P13_GMD_1_PB16_RW = SPA(E_SNONE , E_PAGE_13, 0x33), ++ E_REG_P13_GMD_1_PB17_RW = SPA(E_SNONE , E_PAGE_13, 0x34), ++ E_REG_P13_GMD_1_PB18_RW = SPA(E_SNONE , E_PAGE_13, 0x35), ++ E_REG_P13_GMD_1_PB19_RW = SPA(E_SNONE , E_PAGE_13, 0x36), ++ E_REG_P13_GMD_1_PB20_RW = SPA(E_SNONE , E_PAGE_13, 0x37), ++ E_REG_P13_GMD_1_PB21_RW = SPA(E_SNONE , E_PAGE_13, 0x38), ++ E_REG_P13_GMD_1_PB22_RW = SPA(E_SNONE , E_PAGE_13, 0x39), ++ E_REG_P13_GMD_1_PB23_RW = SPA(E_SNONE , E_PAGE_13, 0x3A), ++ E_REG_P13_GMD_1_PB24_RW = SPA(E_SNONE , E_PAGE_13, 0x3B), ++ E_REG_P13_GMD_1_PB25_RW = SPA(E_SNONE , E_PAGE_13, 0x3C), ++ E_REG_P13_GMD_1_PB26_RW = SPA(E_SNONE , E_PAGE_13, 0x3D), ++ E_REG_P13_GMD_1_PB27_RW = SPA(E_SNONE , E_PAGE_13, 0x3E) ++}; ++#undef SPR ++ ++/** ++ * Register bitfield masks, with a macro to allow binary initializers. ++ * Enum names are derived directly from TDA998x register and bitfield names. ++ */ ++#define BINARY(d7,d6,d5,d4,d3,d2,d1,d0) \ ++ (((d7)<<7)|((d6)<<6)|((d5)<<5)|((d4)<<4)|((d3)<<3)|((d2)<<2)|((d1)<<1)|(d0)) ++ ++enum _eMaskReg ++{ ++ E_MASKREG_NONE = BINARY(0,0,0,0, 0,0,0,0), ++ E_MASKREG_ALL = BINARY(1,1,1,1, 1,1,1,1), ++ ++ /* N4 features flags read from version register: ++ * not_h = no HDCP support ++ * not_s = no scaler support ++ * ++ * N5 = a flag that is not a register bit, but is derived by the ++ * driver from the new N5 registers DWIN_RE_DE and DWIN_FE_DE, ++ * because the N5 device still uses the N4 version register value. ++ * This bit position would clash with version register, so is not ++ * present in the driver's copy (uDeviceVersion) of the version ++ * register, but only in the driver's features byte (uDeviceFeatures). ++ */ ++ ++ /* CEC Masks*/ ++ ++ E_MASKREG_CEC_INTERRUPTSTATUS_hdmi_int = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_CEC_INTERRUPTSTATUS_cec_int = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_CEC_RXSHPDINTENA_ena_hpd_int = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_CEC_RXSHPDINTENA_ena_rxs_int = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_CEC_RXSHPDINT_hpd_int = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_CEC_RXSHPDINT_rxs_int = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_CEC_RXSHPDLEV_hpd_level = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_CEC_RXSHPDLEV_rxs_level = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_CEC_ENAMODS_dis_fro = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_CEC_ENAMODS_dis_cclk = BINARY(0,0,1,0, 0,0,0,0), ++ E_MASKREG_CEC_ENAMODS_ena_rxs = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_CEC_ENAMODS_ena_hdmi = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_CEC_ENAMODS_ena_cec = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_CEC_FRO_IM_CLK_CTRL_ghost_dis = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_CEC_FRO_IM_CLK_CTRL_ena_otp = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_CEC_FRO_IM_CLK_CTRL_imclk_sel = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_CEC_FRO_IM_CLK_CTRL_fro_div = BINARY(0,0,0,0, 0,0,0,1), ++ ++ /* HDMI Masks*/ ++ E_MASKREG_P00_VERSION_not_h = BINARY(0,0,1,0, 0,0,0,0), ++ E_MASKREG_P00_VERSION_not_s = BINARY(0,0,0,1, 0,0,0,0), ++ E_MASKREG_P00_FEATURE_N5 = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_MAIN_CNTRL0_scaler = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P00_MAIN_CNTRL0_cehs = BINARY(0,0,0,1, 0,0,0,0), ++ E_MASKREG_P00_MAIN_CNTRL0_cecs = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P00_MAIN_CNTRL0_dehs = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P00_MAIN_CNTRL0_decs = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P00_MAIN_CNTRL0_sr = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_SR_REG_sr_i2c_ms = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P00_SR_REG_sr_audio = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_DDC_DISABLE_ddc_dis = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_CCLK_ON_cclk_ddc_on = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_I2C_MASTER_app_strt_lat = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P00_I2C_MASTER_dis_filt = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P00_I2C_MASTER_dis_mm = BINARY(0,0,0,0, 0,0,0,1), ++ ++#ifdef TMFL_TDA19989 ++ E_MASKREG_FEAT_POWER_DOWN_spdif = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_FEAT_POWER_DOWN_otp = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_FEAT_POWER_DOWN_csc = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_FEAT_POWER_DOWN_prefilt = BINARY(0,0,0,0, 0,0,0,1), ++ E_MASKREG_FEAT_POWER_DOWN_all = BINARY(0,0,0,0, 1,1,1,1), ++#endif ++ ++ E_MASKREG_P00_INT_FLAGS_0_r0 = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P00_INT_FLAGS_0_pj = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P00_INT_FLAGS_0_sha_1 = BINARY(0,0,1,0, 0,0,0,0), ++ E_MASKREG_P00_INT_FLAGS_0_bstatus = BINARY(0,0,0,1, 0,0,0,0), ++ E_MASKREG_P00_INT_FLAGS_0_bcaps = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P00_INT_FLAGS_0_t0 = BINARY(0,0,0,0, 0,1,0,0), ++ /*E_MASKREG_P00_INT_FLAGS_0_hpd = BINARY(0,0,0,0, 0,0,1,0),*/ ++ E_MASKREG_P00_INT_FLAGS_0_encrypt = BINARY(0,0,0,0, 0,0,0,1), ++ ++ /*E_MASKREG_P00_INT_FLAGS_1_hpd_in = BINARY(1,0,0,0, 0,0,0,0),*/ ++ E_MASKREG_P00_INT_FLAGS_1_sw_int = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P00_INT_FLAGS_1_sc_deil = BINARY(0,0,1,0, 0,0,0,0), ++ E_MASKREG_P00_INT_FLAGS_1_sc_vid = BINARY(0,0,0,1, 0,0,0,0), ++ E_MASKREG_P00_INT_FLAGS_1_sc_out = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P00_INT_FLAGS_1_sc_in = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P00_INT_FLAGS_1_otp = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P00_INT_FLAGS_1_vs_rpt = BINARY(0,0,0,0, 0,0,0,1), ++ /*E_MASKREG_P00_INT_FLAGS_2_rx_sense = BINARY(0,0,0,0, 0,0,0,1),*/ ++ E_MASKREG_P00_INT_FLAGS_2_edid_blk_rd = BINARY(0,0,0,0, 0,0,1,0), ++ ++ /*E_MASKREG_P00_INT_FLAGS_3_rxs_fil = BINARY(0,0,0,0, 0,0,0,1),*/ ++ ++ E_MASKREG_P00_SW_INT_sw_int = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_ENA_ACLK_ena_aclk = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_GND_ACLK_gnd_aclk = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_ENA_VP_0_ena_vp7 = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P00_ENA_VP_0_ena_vp6 = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P00_ENA_VP_0_ena_vp5 = BINARY(0,0,1,0, 0,0,0,0), ++ E_MASKREG_P00_ENA_VP_0_ena_vp4 = BINARY(0,0,0,1, 0,0,0,0), ++ E_MASKREG_P00_ENA_VP_0_ena_vp3 = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P00_ENA_VP_0_ena_vp2 = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P00_ENA_VP_0_ena_vp1 = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P00_ENA_VP_0_ena_vp0 = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_ENA_VP_1_ena_vp15 = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P00_ENA_VP_1_ena_vp14 = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P00_ENA_VP_1_ena_vp13 = BINARY(0,0,1,0, 0,0,0,0), ++ E_MASKREG_P00_ENA_VP_1_ena_vp12 = BINARY(0,0,0,1, 0,0,0,0), ++ E_MASKREG_P00_ENA_VP_1_ena_vp11 = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P00_ENA_VP_1_ena_vp10 = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P00_ENA_VP_1_ena_vp9 = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P00_ENA_VP_1_ena_vp8 = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_ENA_VP_2_ena_vp23 = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P00_ENA_VP_2_ena_vp22 = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P00_ENA_VP_2_ena_vp21 = BINARY(0,0,1,0, 0,0,0,0), ++ E_MASKREG_P00_ENA_VP_2_ena_vp20 = BINARY(0,0,0,1, 0,0,0,0), ++ E_MASKREG_P00_ENA_VP_2_ena_vp19 = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P00_ENA_VP_2_ena_vp18 = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P00_ENA_VP_2_ena_vp17 = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P00_ENA_VP_2_ena_vp16 = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_ENA_AP_ena_ap7 = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P00_ENA_AP_ena_ap6 = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P00_ENA_AP_ena_ap5 = BINARY(0,0,1,0, 0,0,0,0), ++ E_MASKREG_P00_ENA_AP_ena_ap4 = BINARY(0,0,0,1, 0,0,0,0), ++ E_MASKREG_P00_ENA_AP_ena_ap3 = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P00_ENA_AP_ena_ap2 = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P00_ENA_AP_ena_ap1 = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P00_ENA_AP_ena_ap0 = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_VIP_CNTRL_0_mirr_a = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_0_swap_a = BINARY(0,1,1,1, 0,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_0_mirr_b = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_0_swap_b = BINARY(0,0,0,0, 0,1,1,1), ++ ++ E_MASKREG_P00_VIP_CNTRL_1_mirr_c = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_1_swap_c = BINARY(0,1,1,1, 0,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_1_mirr_d = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_1_swap_d = BINARY(0,0,0,0, 0,1,1,1), ++ ++ E_MASKREG_P00_VIP_CNTRL_2_mirr_e = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_2_swap_e = BINARY(0,1,1,1, 0,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_2_mirr_f = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_2_swap_f = BINARY(0,0,0,0, 0,1,1,1), ++ ++#ifdef TMFL_TDA19989 ++ E_MASKREG_P00_MUX_VP_VIP_OUT_red = BINARY(0,0,1,1, 0,0,0,0), ++ E_MASKREG_P00_MUX_VP_VIP_OUT_green = BINARY(0,0,0,0, 1,1,0,0), ++ E_MASKREG_P00_MUX_VP_VIP_OUT_blue = BINARY(0,0,0,0, 0,0,1,1), ++#endif ++ ++ E_MASKREG_P00_VIP_CNTRL_3_edge = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_3_de_int = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_3_sp_sync = BINARY(0,0,1,1, 0,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_3_emb = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_3_v_tgl = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P00_VIP_CNTRL_3_h_tgl = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P00_VIP_CNTRL_3_x_tgl = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_VIP_CNTRL_4_tst_pat = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_4_tst_656 = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_4_656_alt = BINARY(0,0,1,0, 0,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_4_ccir656 = BINARY(0,0,0,1, 0,0,0,0), ++ E_MASKREG_P00_VIP_CNTRL_4_blankit = BINARY(0,0,0,0, 1,1,0,0), ++ E_MASKREG_P00_VIP_CNTRL_4_blc = BINARY(0,0,0,0, 0,0,1,1), ++ ++ E_MASKREG_P00_VIP_CNTRL_5_sp_cnt = BINARY(0,0,0,0, 0,1,1,0), ++ E_MASKREG_P00_VIP_CNTRL_5_ckcase = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_MAT_CONTRL_mat_bp = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P00_MAT_CONTRL_mat_sc = BINARY(0,0,0,0, 0,0,1,1), ++ ++#ifdef TMFL_TDA19989 ++ E_MASKREG_P00_VIDFORMAT_3d = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P00_VIDFORMAT_3d_neg_vs = BINARY(0,1,0,0, 0,0,0,0), ++#endif ++ E_MASKREG_P00_VIDFORMAT_vidformat = BINARY(0,0,0,1, 1,1,1,1), ++ ++ E_MASKREG_P00_TBG_CNTRL_0_sync_once = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P00_TBG_CNTRL_0_sync_mthd = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P00_TBG_CNTRL_0_frame_dis = BINARY(0,0,1,0, 0,0,0,0), ++ ++ E_MASKREG_P00_TBG_CNTRL_1_dwin_dis = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P00_TBG_CNTRL_1_vhx_ext = BINARY(0,0,1,1, 1,0,0,0), ++ E_MASKREG_P00_TBG_CNTRL_1_vhx_ext_vs = BINARY(0,0,1,0, 0,0,0,0), ++ E_MASKREG_P00_TBG_CNTRL_1_vhx_ext_hs = BINARY(0,0,0,1, 0,0,0,0), ++ E_MASKREG_P00_TBG_CNTRL_1_vhx_ext_de = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P00_TBG_CNTRL_1_vh_tgl = BINARY(0,0,0,0, 0,1,1,1), ++ E_MASKREG_P00_TBG_CNTRL_1_vh_tgl_2 = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P00_TBG_CNTRL_1_vh_tgl_1 = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P00_TBG_CNTRL_1_vh_tgl_0 = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_I2C_TIMER_RI = BINARY(0,0,0,0, 1,1,1,1), ++ E_MASKREG_P00_I2C_TIMER_PJ = BINARY(1,1,1,1, 0,0,0,0), ++ ++ E_MASKREG_P00_HVF_CNTRL_0_sm = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P00_HVF_CNTRL_0_rwb = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P00_HVF_CNTRL_0_prefil = BINARY(0,0,0,0, 1,1,0,0), ++ E_MASKREG_P00_HVF_CNTRL_0_intpol = BINARY(0,0,0,0, 0,0,1,1), ++ ++ E_MASKREG_P00_HVF_CNTRL_1_semi_planar = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P00_HVF_CNTRL_1_pad = BINARY(0,0,1,1, 0,0,0,0), ++ E_MASKREG_P00_HVF_CNTRL_1_vqr = BINARY(0,0,0,0, 1,1,0,0), ++ E_MASKREG_P00_HVF_CNTRL_1_yuvblk = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P00_HVF_CNTRL_1_for = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_TIMER_H_wd_clksel = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P00_TIMER_H_tim_h = BINARY(0,0,0,0, 0,0,1,1), ++ ++ E_MASKREG_P00_DEBUG_PROBE_sel = BINARY(0,0,1,1, 0,0,0,0), ++ E_MASKREG_P00_DEBUG_PROBE_bypass = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P00_DEBUG_PROBE_vid_de = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P00_DEBUG_PROBE_di_de = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P00_DEBUG_PROBE_woo_en = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P00_I2S_FORMAT_i2s_format = BINARY(0,0,0,0, 0,0,1,1), ++ ++ E_MASKREG_P00_I2S_FORMAT_i2s_data_size = BINARY(0,0,0,0, 1,1,0,0), ++ ++ E_MASKREG_P00_AIP_CLKSEL_dst_rate = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P00_AIP_CLKSEL_sel_aip_SHIFT = 3, ++ E_MASKREG_P00_AIP_CLKSEL_sel_aip = BINARY(0,0,1,1, 1,0,0,0), ++ E_MASKREG_P00_AIP_CLKSEL_sel_pol_clk = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P00_AIP_CLKSEL_sel_fs = BINARY(0,0,0,0, 0,0,1,1), ++ E_MASKREG_P01_SC_VIDFORMAT_lut_sel = BINARY(1,1,0,0, 0,0,0,0), ++ E_MASKREG_P01_SC_VIDFORMAT_vid_format_o = BINARY(0,0,1,1, 1,0,0,0), ++ E_MASKREG_P01_SC_VIDFORMAT_vid_format_i = BINARY(0,0,0,0, 0,1,1,1), ++ ++ E_MASKREG_P01_SC_CNTRL_phases_h = BINARY(0,0,0,1, 0,0,0,0), ++ E_MASKREG_P01_SC_CNTRL_il_out_on = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P01_SC_CNTRL_phases_v = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P01_SC_CNTRL_vs_on = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P01_SC_CNTRL_deil_on = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P01_VIDFORMAT_vidformat = BINARY(0,0,0,0, 0,1,1,1), ++ ++ E_MASKREG_P01_TBG_CNTRL_0_sync_once = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P01_TBG_CNTRL_0_sync_mthd = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P01_TBG_CNTRL_0_frame_dis = BINARY(0,0,1,0, 0,0,0,0), ++ E_MASKREG_P01_TBG_CNTRL_0_top_ext = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P01_TBG_CNTRL_0_de_ext = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P01_TBG_CNTRL_0_top_sel = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P01_TBG_CNTRL_0_top_tgl = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P02_PLL_SERIAL_1_srl_man_iz = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P02_PLL_SERIAL_1_srl_iz = BINARY(0,0,0,0, 0,1,1,0), ++ E_MASKREG_P02_PLL_SERIAL_1_srl_fdn = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P02_PLL_SERIAL_2_srl_pr = BINARY(1,1,1,1, 0,0,0,0), ++ E_MASKREG_P02_PLL_SERIAL_2_srl_nosc = BINARY(0,0,0,0, 0,0,1,1), ++ ++ E_MASKREG_P02_PLL_SERIAL_3_srl_pxin_sel = BINARY(0,0,0,1, 0,0,0,0), ++ E_MASKREG_P02_PLL_SERIAL_3_srl_de = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P02_PLL_SERIAL_3_srl_ccir = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P02_SERIALIZER_srl_phase3 = BINARY(1,1,1,1, 0,0,0,0), ++ E_MASKREG_P02_SERIALIZER_srl_phase2 = BINARY(0,0,0,0, 1,1,1,1), ++ ++ E_MASKREG_P02_BUFFER_OUT_srl_force = BINARY(0,0,0,0, 1,1,0,0), ++ E_MASKREG_P02_BUFFER_OUT_srl_clk = BINARY(0,0,0,0, 0,0,1,1), ++ ++ E_MASKREG_P02_PLL_SCG1_scg_fdn = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P02_PLL_SCG2_bypass_scg = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P02_PLL_SCG2_selpllclkin = BINARY(0,0,0,1, 0,0,0,0), ++ E_MASKREG_P02_PLL_SCG2_scg_nosc = BINARY(0,0,0,0, 0,0,1,1), ++ ++ E_MASKREG_P02_VAI_PLL_pllde_hvp = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P02_VAI_PLL_pllscg_hvp = BINARY(0,0,1,0, 0,0,0,0), ++ E_MASKREG_P02_VAI_PLL_pllsrl_hvp = BINARY(0,0,0,1, 0,0,0,0), ++ E_MASKREG_P02_VAI_PLL_pllscg_lock = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P02_VAI_PLL_pllsrl_lock = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P02_AUDIO_DIV_audio_div = BINARY(0,0,0,0, 0,1,1,1), ++ ++ E_MASKREG_P02_TEST1_srldat = BINARY(1,1,0,0, 0,0,0,0), ++ E_MASKREG_P02_TEST1_tst_nosc = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P02_TEST1_tst_enahvp = BINARY(0,0,0,0, 0,0,0,1), ++ ++ //E_MASKREG_P02_TEST2_pwd1v8 = BINARY(0,0,0,0, 0,0,1,0), ++ //E_MASKREG_P02_TEST2_divtestoe = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P02_SEL_CLK_ena_sc_clk = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P02_SEL_CLK_sel_vrf_clk = BINARY(0,0,0,0, 0,1,1,0), ++ E_MASKREG_P02_SEL_CLK_sel_clk1 = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P02_BUFF_OUT2_force_dat2 = BINARY(0,0,1,1, 0,0,0,0), ++ E_MASKREG_P02_BUFF_OUT2_force_dat1 = BINARY(0,0,0,0, 1,1,0,0), ++ E_MASKREG_P02_BUFF_OUT2_force_dat0 = BINARY(0,0,0,0, 0,0,1,1), ++ ++ E_MASKREG_P09_EDID_CTRL_edid_rd = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P11_AIP_CNTRL_0_rst_cts = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P11_AIP_CNTRL_0_acr_man = BINARY(0,0,1,0, 0,0,0,0), ++ E_MASKREG_P11_AIP_CNTRL_0_layout = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P11_AIP_CNTRL_0_swap = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P11_AIP_CNTRL_0_rst_fifo = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P11_CA_I2S_hbr_chstat_4 = BINARY(0,0,1,0, 0,0,0,0), ++ E_MASKREG_P11_CA_I2S_ca_i2s = BINARY(0,0,0,1, 1,1,1,1), ++ ++ E_MASKREG_P11_GC_AVMUTE_set_mute = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P11_GC_AVMUTE_clr_mute = BINARY(0,0,0,0, 0,0,0,1), ++ E_MASKREG_P11_GC_AVMUTE_setclr_mute = BINARY(0,0,0,0, 0,0,1,1), ++ ++ E_MASKREG_P11_CTS_N_m_sel = BINARY(0,0,1,1, 0,0,0,0), ++ E_MASKREG_P11_CTS_N_k_sel = BINARY(0,0,0,0, 0,1,1,1), ++ ++ E_MASKREG_P11_ENC_CNTRL_ctl_code = BINARY(0,0,0,0, 1,1,0,0), ++ E_MASKREG_P11_ENC_CNTRL_rst_sel = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P11_ENC_CNTRL_rst_enc = BINARY(0,0,0,0, 0,0,0,1), ++ E_MASKREG_P11_DIP_FLAGS_force_null = BINARY(1,0,0,0, 0,0,0,0), ++ E_MASKREG_P11_DIP_FLAGS_null = BINARY(0,1,0,0, 0,0,0,0), ++ E_MASKREG_P11_DIP_FLAGS_acp = BINARY(0,0,0,1, 0,0,0,0), ++ E_MASKREG_P11_DIP_FLAGS_isrc2 = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P11_DIP_FLAGS_isrc1 = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P11_DIP_FLAGS_gc = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P11_DIP_FLAGS_acr = BINARY(0,0,0,0, 0,0,0,1), ++ ++ E_MASKREG_P11_DIP_IF_FLAGS_if5 = BINARY(0,0,1,0, 0,0,0,0), ++ E_MASKREG_P11_DIP_IF_FLAGS_if4 = BINARY(0,0,0,1, 0,0,0,0), ++ E_MASKREG_P11_DIP_IF_FLAGS_if3 = BINARY(0,0,0,0, 1,0,0,0), ++ E_MASKREG_P11_DIP_IF_FLAGS_if2 = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P11_DIP_IF_FLAGS_if1 = BINARY(0,0,0,0, 0,0,1,0), ++ ++ E_MASKREG_P13_GMD_CONTROL_buf_sel = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P13_GMD_CONTROL_enable = BINARY(0,0,0,0, 0,0,0,1) ++}; ++#undef BINARY ++ ++/** ++ * 3 enum for the video formats : ++ * - 1 used in the E_REG_P00_VIDFORMAT_W register ++ * - 1 for new format that are not prefetch ++ * - 1 for PC ++ */ ++#define REGVFMT_INVALID 0xFF ++ ++enum _eRegVfmt { ++ E_REGVFMT_640x480p_60Hz = 0, /* 1 */ ++ E_REGVFMT_720x480p_60Hz , /* 2/3 */ ++ E_REGVFMT_1280x720p_60Hz , /* 4 */ ++ E_REGVFMT_1920x1080i_60Hz , /* 5 */ ++ E_REGVFMT_720x480i_60Hz , /* 6/4 */ ++ E_REGVFMT_720x240p_60Hz , /*NT 8/9 */ ++ E_REGVFMT_1920x1080p_60Hz , /* 16 */ ++ E_REGVFMT_720x576p_50Hz , /* 17/18 */ ++ E_REGVFMT_1280x720p_50Hz , /* 19 */ ++ E_REGVFMT_1920x1080i_50Hz , /* 20 */ ++ E_REGVFMT_720x576i_50Hz , /* 21/22 */ ++ E_REGVFMT_720x288p_50Hz , /* 23/24 */ ++ E_REGVFMT_1920x1080p_50Hz , /* 31 */ ++#ifdef TMFL_RGB_DDR_12BITS ++ E_REGVFMT_1920x1080p_24Hz , /* 32 */ ++ E_REGVFMT_1440x576p_50Hz , /* 29/30 */ ++ E_REGVFMT_1440x480p_60Hz , /* 14/15 */ ++ E_REGVFMT_2880x480p_60Hz , /* 35/36 */ ++ E_REGVFMT_2880x576p_50Hz , /* 37/38 */ ++ E_REGVFMT_2880x480i_60Hz , /* 10/11*/ ++ E_REGVFMT_2880x480i_60Hz_PR2, /* 10/11*/ ++ E_REGVFMT_2880x480i_60Hz_PR4, /* 10/11*/ ++ E_REGVFMT_2880x576i_50Hz , /* 25/26 */ ++ E_REGVFMT_2880x576i_50Hz_PR2, /* 25/26 */ ++ E_REGVFMT_720x480p_60Hz_FP , /* 2/3 FP */ ++ E_REGVFMT_1280x720p_60Hz_FP , /* 4 FP */ ++ E_REGVFMT_720x576p_50Hz_FP , /* 17/18 FP */ ++ E_REGVFMT_1280x720p_50Hz_FP , /* 19 FP */ ++ E_REGVFMT_1920x1080p_24Hz_FP, /* 32 FP */ ++ E_REGVFMT_1920x1080p_25Hz_FP, /* 33 FP */ ++ E_REGVFMT_1920x1080p_30Hz_FP, /* 34 FP */ ++ E_REGVFMT_1920x1080i_60Hz_FP, /* 5 FP */ ++ E_REGVFMT_1920x1080i_50Hz_FP, /* 20 FP */ ++#endif ++ E_REGVFMT_MAX_PREFETCH , ++ E_REGVFMT_NUM_PREFETCH = E_REGVFMT_MAX_PREFETCH ++}; ++ ++enum _eRegVfmtExtra { ++#ifndef TMFL_RGB_DDR_12BITS ++ E_REGVFMT_1920x1080p_24Hz = E_REGVFMT_MAX_PREFETCH, /* 32 */ ++ E_REGVFMT_1920x1080p_25Hz , /* 33 */ ++#else ++ E_REGVFMT_1920x1080p_25Hz = E_REGVFMT_MAX_PREFETCH, ++#endif ++ E_REGVFMT_1920x1080p_30Hz, /* 34 */ ++ E_REGVFMT_1280x720p_24Hz, /* 60 */ ++ E_REGVFMT_1280x720p_25Hz, /* 61 */ ++ E_REGVFMT_1280x720p_30Hz , /* 62 */ ++#ifndef TMFL_RGB_DDR_12BITS ++ E_REGVFMT_1280x720p_60Hz_FP, ++ E_REGVFMT_1920x1080i_60Hz_FP, ++ E_REGVFMT_1280x720p_50Hz_FP, ++ E_REGVFMT_1920x1080i_50Hz_FP, ++ E_REGVFMT_1920x1080p_24Hz_FP, ++ E_REGVFMT_1920x1080p_25Hz_FP, ++ E_REGVFMT_1920x1080p_30Hz_FP, ++#endif ++ E_REGVFMT_1280x720p_24Hz_FP, ++ E_REGVFMT_1280x720p_25Hz_FP, ++ E_REGVFMT_1280x720p_30Hz_FP, ++ E_REGVFMT_MAX_EXTRA , ++ E_REGVFMT_NUM_EXTRA = E_REGVFMT_MAX_EXTRA - E_REGVFMT_MAX_PREFETCH ++}; ++ ++#ifdef FORMAT_PC ++enum _eRegVfmtPC { ++ E_REGVFMT_640x480p_72Hz = E_REGVFMT_MAX_EXTRA, ++ E_REGVFMT_640x480p_75Hz , ++ E_REGVFMT_640x480p_85Hz , ++ E_REGVFMT_800x600p_60Hz , ++ E_REGVFMT_800x600p_72Hz , ++ E_REGVFMT_800x600p_75Hz , ++ E_REGVFMT_800x600p_85Hz , ++ E_REGVFMT_1024x768p_60Hz , ++ E_REGVFMT_1024x768p_70Hz , ++ E_REGVFMT_1024x768p_75Hz , ++ E_REGVFMT_1280x768p_60Hz , ++ E_REGVFMT_1280x1024p_60Hz , ++ E_REGVFMT_1360x768p_60Hz , ++ E_REGVFMT_1400x1050p_60Hz , ++ E_REGVFMT_1600x1200p_60Hz , ++ E_REGVFMT_1280x1024p_85Hz , ++ E_REGVFMT_MAX_PC , ++ E_REGVFMT_NUM_PC = E_REGVFMT_MAX_PC - E_REGVFMT_MAX_EXTRA ++}; ++#define E_REGVFMT_MAX E_REGVFMT_MAX_PC ++#else ++#define E_REGVFMT_MAX E_REGVFMT_MAX_EXTRA ++#endif /*FORMAT_PC*/ ++ ++#define PREFETCH(fmt) ((fmt) < E_REGVFMT_MAX_PREFETCH) ++#define EXTRA(fmt) (!PREFETCH(fmt)) ++#define PCFORMAT(fmt) ((fmt) >= E_REGVFMT_MAX_EXTRA)/* PR1570 FIXED */ ++#define BASE(fmt) (PREFETCH(fmt)?(fmt):(fmt)-E_REGVFMT_MAX_PREFETCH) ++ ++ ++/** ++ * An enum for the video input formats used in the E_REG_P01_SC_VIDFORMAT_W ++ * register ++ */ ++enum _eRegVfmtScIn ++{ ++ E_REGVFMT_SCIN_480i_60Hz = 0, ++ E_REGVFMT_SCIN_576i_50Hz = 1, ++ E_REGVFMT_SCIN_480p_60Hz = 2, ++ E_REGVFMT_SCIN_576p_50Hz = 3, ++ E_REGVFMT_SCIN_720p_50Hz_60Hz = 4, ++ E_REGVFMT_SCIN_1080i_50Hz_60Hz = 5, ++ E_REGVFMT_SCIN_MAX = 5, ++ E_REGVFMT_SCIN_NUM = 6, ++ E_REGVFMT_SCIN_INVALID = 6 ++}; ++ ++/** ++ * An enum to list all supported pixel clock frequencies in kHz ++ */ ++enum _ePixClk ++{ ++ E_PIXCLK_25175 = 0, ++ E_PIXCLK_25200 = 1, ++ E_PIXCLK_27000 = 2, ++ E_PIXCLK_27027 = 3, ++ E_PIXCLK_54000 = 4, ++ E_PIXCLK_54054 = 5, ++ E_PIXCLK_59400 = 6, ++ E_PIXCLK_74175 = 7, ++ E_PIXCLK_74250 = 8, ++ E_PIXCLK_148350 = 9, ++ E_PIXCLK_148500 = 10, ++ E_PIXCLK_108000 = 11, ++ E_PIXCLK_108108 = 12, ++#ifndef FORMAT_PC ++ E_PIXCLK_MAX = 12, ++ E_PIXCLK_INVALID = 13, ++ E_PIXCLK_NUM = 13 ++#else /* FORMAT_PC */ ++ E_PIXCLK_31500 = 13, ++ E_PIXCLK_36000 = 14, ++ E_PIXCLK_40000 = 15, ++ E_PIXCLK_49500 = 16, ++ E_PIXCLK_50000 = 17, ++ E_PIXCLK_56250 = 18, ++ E_PIXCLK_65000 = 19, ++ E_PIXCLK_75000 = 20, ++ E_PIXCLK_78750 = 21, ++ E_PIXCLK_79500 = 22, ++ E_PIXCLK_85500 = 23, ++ E_PIXCLK_PC_108000 = 24, ++ E_PIXCLK_121750 = 25, ++ E_PIXCLK_162000 = 26, ++ E_PIXCLK_MAX = 26, ++ E_PIXCLK_INVALID = 27, ++ E_PIXCLK_NUM = 27 ++#endif /* FORMAT_PC */ ++}; ++ ++/** ++ * An enum to list all device version codes supported by this driver. ++ * The values form a list, with non-zero version codes first in any order. ++ * The E_DEV_VERSION_END_LIST must be the last value in the list. ++ */ ++enum _eDevVersion ++{ ++ E_DEV_VERSION_N2 = 0x101, /**< TDA9989 n2 */ ++ E_DEV_VERSION_TDA19989 = 0x201, /**< TDA19989 */ ++ E_DEV_VERSION_TDA19989_N2 = 0x202, /**< TDA19989 N2 */ ++ E_DEV_VERSION_TDA19988 = 0x301, /**< TDA19988 */ ++ E_DEV_VERSION_LIST_END = 0x00, ++ E_DEV_VERSION_LIST_NUM = 5 /**< Number of items in list */ ++}; ++ ++/** ++ * An enum to list all CEA Data Block Tag Codes we may find in EDID. ++ */ ++enum _eCeaBlockTags ++{ ++ E_CEA_RESERVED_0 = 0x00, ++ E_CEA_AUDIO_BLOCK = 0x01, ++ E_CEA_VIDEO_BLOCK = 0x02, ++ E_CEA_VSDB = 0x03, ++ E_CEA_SPEAKER_ALLOC = 0x04, ++ E_CEA_VESA_DTC = 0x05, ++ E_CEA_RESERVED_6 = 0x06, ++ E_CEA_EXTENDED = 0x07 ++}; ++ ++/** ++ * An enum to list all CEA Data Block Extended Tag Codes we may find in EDID. ++ */ ++enum _eCeaExtendedBlockTags ++{ ++ EXT_CEA_MISC_VIDEO_FIELDS = 0x00, ++ EXT_CEA_VS_VIDEO_DB = 0x01, ++ EXT_CEA_COLORIMETRY_DB = 0x05, ++ EXT_CEA_MISC_AUDIO_FIELDS = 0x10, ++ EXT_CEA_VS_AUDIO_DB = 0x11 ++}; ++ ++/** A typedef for colourspace values */ ++typedef enum ++{ ++ HDMITX_CS_RGB_FULL = 0, /**< RGB Full (PC) */ ++ HDMITX_CS_RGB_LIMITED = 1, /**< RGB Limited (TV) */ ++ HDMITX_CS_YUV_ITU_BT601 = 2, /**< YUV ITUBT601 (SDTV) */ ++ HDMITX_CS_YUV_ITU_BT709 = 3, /**< YUV ITUBT709 (HDTV) */ ++ HDMITX_CS_NUM = 4 /**< Number Cspaces we support */ ++} tmbslTDA9989Colourspace_t; ++ ++/** Matrix register block size */ ++#define MATRIX_PRESET_SIZE 31 ++ ++/** Matrix register block size */ ++#define MATRIX_PRESET_QTY 12 ++ ++/** The enum that vectors us into the MatrixPreset table */ ++enum _eMatrixPresetIndex ++{ ++ E_MATRIX_RGBF_2_RGBL = 0, ++ E_MATRIX_RGBF_2_BT601 = 1, ++ E_MATRIX_RGBF_2_BT709 = 2, ++ E_MATRIX_RGBL_2_RGBF = 3, ++ E_MATRIX_RGBL_2_BT601 = 4, ++ E_MATRIX_RGBL_2_BT709 = 5, ++ E_MATRIX_BT601_2_RGBF = 6, ++ E_MATRIX_BT601_2_RGBL = 7, ++ E_MATRIX_BT601_2_BT709 = 8, ++ E_MATRIX_BT709_2_RGBF = 9, ++ E_MATRIX_BT709_2_RGBL = 10, ++ E_MATRIX_BT709_2_BT601 = 11 ++}; ++ ++/** EDID i2c address */ ++#define DDC_EDID_ADDRESS 0xA0 ++ ++/** EDID alternate i2c address */ ++#define DDC_EDID_ADDRESS_ALT 0xA2 ++ ++/** EDID Segment Pointer address */ ++#define DDC_SGMT_PTR_ADDRESS 0x60 ++ ++/** EDID DTD block descriptor size */ ++#define EDID_DTD_BLK_SIZE 0x12 ++ ++/** number of detailed timing descriptor stored in pDis */ ++#define NUMBER_DTD_STORED 10 ++ ++/** MUX_AP audio selection values */ ++#define MUX_AP_SELECT_I2S 0xE4 ++#define MUX_AP_SELECT_SPDIF 0x27 ++ ++#define TDA19989_MUX_AP_SELECT_I2S 0x64 ++#define TDA19989_MUX_AP_SELECT_SPDIF 0x24 ++ ++/** VSWING default value */ ++#define HDMI_TX_VSWING_VALUE 0x09 ++ ++ ++/** ++ * \brief A structure type to form arrays that hold a series of registers and ++ * values ++ */ ++typedef struct _tmHdmiTxRegVal_t ++{ ++ UInt16 Reg; ++ UInt8 Val; ++} tmHdmiTxRegVal_t; ++ ++/** ++ * \brief A structure type to form arrays that hold a series of registers, ++ * bitfield masks and bitfield values ++ */ ++typedef struct _tmHdmiTxRegMaskVal_t ++{ ++ UInt16 Reg; ++ UInt8 Mask; ++ UInt8 Val; ++} tmHdmiTxRegMaskVal_t; ++ ++/** ++ * \brief A function pointer type to call a function and return a result ++ */ ++typedef tmErrorCode_t (FUNC_PTR * ptmHdmiTxFunc_t) (tmUnitSelect_t txUnit); ++ ++/** ++ * \brief The structure of a TM998x object, one per device unit ++ **************************************************************************** ++ ** Copy changes to kTestDisNames tab in "HDMI Driver - Register List.xls" ** ++ **************************************************************************** ++ */ ++ ++typedef struct _tmHdmiTxobject_t ++{ ++ /** Component State */ ++ tmbslTDA9989State_t state; ++ ++ /** Count of events ignored by setState() */ ++ UInt8 nIgnoredEvents; ++ ++ /** Device unit number */ ++ tmUnitSelect_t txUnit; ++ ++ /** Device I2C slave address */ ++ UInt8 uHwAddress; ++ ++ /** System function to write to the I2C driver */ ++ ptmbslHdmiTxSysFunc_t sysFuncWrite; ++ ++ /** System function to read from the I2C driver */ ++ ptmbslHdmiTxSysFunc_t sysFuncRead; ++ ++ /** System function to read EDID blocks via the I2C driver */ ++ ptmbslHdmiTxSysFuncEdid_t sysFuncEdidRead; ++ ++ /** System function to run a timer */ ++ ptmbslHdmiTxSysFuncTimer_t sysFuncTimer; ++ ++ /** Array of registered interrupt handler callback functions */ ++ ptmbslHdmiTxCallback_t funcIntCallbacks[HDMITX_CALLBACK_INT_NUM]; ++ ++ /** Flags to store disable or enable of interrupts */ ++ UInt16 InterruptsEnable; /* At moment used only for VS Interrupt */ ++ ++ /** Device version(s) supported by this component */ ++ UInt16 uSupportedVersions[E_DEV_VERSION_LIST_NUM]; ++ ++ /** Device version read from register, with features flags masked out */ ++ UInt16 uDeviceVersion; ++ ++ /** Device features flags read from version register */ ++ UInt8 uDeviceFeatures; ++ ++ /** The device's power state */ ++ tmbslHdmiTxPowerState_t ePowerState; ++ ++ /*=== E D I D ===*/ ++ ++ /** EDID Use alternative i2c address flag */ ++ Bool bEdidAlternateAddr; ++ ++ /** The sink type set by the user (may or may not match EdidSinkType) */ ++ tmbslHdmiTxSinkType_t sinkType; ++ ++ /** EDID Sink Type for receiver */ ++ tmbslHdmiTxSinkType_t EdidSinkType; ++ ++ /** EDID AI_Support from HDMI VSDB */ ++ Bool EdidSinkAi; ++ ++ /** EDID CEA flags from extension block */ ++ UInt8 EdidCeaFlags; ++ ++ /** EDID CEA flags from colorimetry block */ ++ UInt8 EdidCeaXVYCCFlags; ++ ++ /** EDID latency information */ ++ tmbslHdmiTxEdidLatency_t EdidLatency; ++ ++ /** EDID 3D data structure */ ++ tmbslHdmiTxEdidExtraVsdbData_t EdidExtraVsdbData; ++ ++ /** EDID Read Status */ ++ UInt8 EdidStatus; ++ ++ /** NB DTD stored in EdidDTD */ ++ UInt8 NbDTDStored; ++ ++ /** EDID Detailed Timing Descriptor */ ++ tmbslHdmiTxEdidDtd_t EdidDTD[NUMBER_DTD_STORED]; ++ ++ /** EDID First Moniteur descriptor */ ++ tmbslHdmiTxEdidFirstMD_t EdidFirstMonitorDescriptor; ++ ++ /** EDID Second Moniteur descriptor */ ++ tmbslHdmiTxEdidSecondMD_t EdidSecondMonitorDescriptor; ++ ++ /** EDID Other Moniteur descriptor */ ++ tmbslHdmiTxEdidOtherMD_t EdidOtherMonitorDescriptor; ++ ++ /** EDID supported Short Video Descriptors */ ++ UInt8 EdidVFmts[HDMI_TX_SVD_MAX_CNT]; ++ ++ /** Counter for supported short video descriptors */ ++ UInt8 EdidSvdCnt; ++ ++ /** EDID supported Short Audio Descriptors */ ++ tmbslHdmiTxEdidSad_t EdidAFmts[HDMI_TX_SAD_MAX_CNT]; ++ ++ /** Counter for supported short audio descriptors */ ++ UInt8 EdidSadCnt; ++ ++ /** EDID block workspace */ ++ UInt8 EdidBlock[EDID_BLOCK_SIZE]; ++ ++ /** EDID Block Count */ ++ UInt8 EdidBlockCnt; ++ ++ /** CEC Source Address read from EDID as "A.B.C.D" nibbles */ ++ UInt16 EdidSourceAddress; ++ ++ /** EDID block number which is reading */ ++ UInt8 EdidBlockRequested; ++ ++ /** EDID read on going*/ ++ Bool EdidReadStarted; ++ ++ /** Parameter for return edid block requested by application */ ++ tmbslHdmiTxEdidToApp_t EdidToApp; ++ ++ /** EDID Basic Display Parameters */ ++ tmbslHdmiTxEdidBDParam_t EDIDBasicDisplayParam; ++ ++#ifdef TMFL_HDCP_SUPPORT ++ /*=== H D C P === */ ++ ++ Bool HDCPIgnoreEncrypt; ++ ++ /** Configured DDC I2C slave address */ ++ UInt8 HdcpSlaveAddress; ++ ++ /** Configured mode of our transmitter device */ ++ tmbslHdmiTxHdcpTxMode_t HdcpTxMode; ++ ++ /** Configured HDCP options */ ++ tmbslHdmiTxHdcpOptions_t HdcpOptions; ++ ++ /** BCAPS read from sink */ ++ UInt8 HdcpBcaps; ++ ++ /** BSTATUS read from sink */ ++ UInt16 HdcpBstatus; ++ ++ /** Device value generated for Ri=Ri' comparison */ ++ UInt16 HdcpRi; ++ ++ /** Device HDCP FSM state */ ++ UInt8 HdcpFsmState; ++ ++ /** Device failure state that caused T0 interrupt */ ++ UInt8 HdcpT0FailState; ++ ++ /** Otp Seed key from user*/ ++ UInt16 HdcpSeed; ++ ++ /* Key Selection Vector for transmitter */ ++ UInt8 HdcpAksv[HDMITX_KSV_BYTES_PER_DEVICE]; ++ ++ /** Local callback scheduled to be called after HdcpFuncRemainingMs */ ++ ptmHdmiTxFunc_t HdcpFuncScheduled; ++ ++ /** Period in ms after which to call HdcpFuncScheduled; 0=disabled */ ++ UInt16 HdcpFuncRemainingMs; ++ ++ /** Configured period in ms after which to do HDCP check */ ++ UInt16 HdcpCheckIntervalMs; ++ ++ /** Period in ms until next HDCP check */ ++ UInt16 HdcpCheckRemainingMs; ++ ++ /** Number of the HDCP check since HDCP was started; 0=disabled */ ++ UInt8 HdcpCheckNum; ++ ++ /** Configured number of HDCP checks to do after HDCP is started */ ++ UInt8 HdcpChecksToDo; ++#endif /* TMFL_HDCP_SUPPORT */ ++ ++ /*=== V I D E O ===*/ ++ ++ /** Current EIA/CEA video input format */ ++ tmbslHdmiTxVidFmt_t vinFmt; ++ ++ /** Current EIA/CEA video output format */ ++ tmbslHdmiTxVidFmt_t voutFmt; ++ ++ /** Current pix Rate*/ ++ tmbslHdmiTxPixRate_t pixRate; ++ ++ /** Video input mode */ ++ tmbslHdmiTxVinMode_t vinMode; ++ ++ /** Video output mode */ ++ tmbslHdmiTxVoutMode_t voutMode; ++ ++ /** Vertical output frequency */ ++ tmbslHdmiTxVfreq_t voutFreq; ++ ++ /** Current scaler mode */ ++ tmbslHdmiTxScaMode_t scaMode; ++ ++ /** Current upsampler mode */ ++ tmbslHdmiTxUpsampleMode_t upsampleMode; ++ ++ /** Current pixel repetition count */ ++ UInt8 pixelRepeatCount; ++ ++ /** Status of hot plug detect pin last read at interrupt */ ++ tmbslHdmiTxHotPlug_t hotPlugStatus; ++ ++ /** Status of rx sense detect pin last read at interrupt */ ++ tmbslHdmiTxRxSense_t rxSenseStatus; ++ ++ /** Current register page */ ++ UInt8 curRegPage; ++ ++ /** Shadow copies of write-only registers with bitfields */ ++ UInt8 shadowReg[E_SNUM]; ++ ++ /** TRUE: Blue screen is the previous test pattern ; FALSE: is not */ ++ Bool prevFilterPattern; ++ ++ /** TRUE: last screen is test pattern ; FALSE: is not */ ++ Bool prevPattern; ++ ++ /** TRUE: Unit has been initialized; FALSE: not initialized */ ++ Bool bInitialized; ++ ++ tmbslHdmiTxVQR_t dviVqr; ++ ++ /** TRUE: 3D Frame Packing video is ongoing */ ++ Bool h3dFpOn; ++ ++} tmHdmiTxobject_t; ++ ++/** ++ * \The structure of registers for video format , ++ * used by PC_formats and chip_unknown formats ++ */ ++ ++typedef struct _tmHdmiTxVidReg_t ++{ ++ UInt16 nPix; ++ UInt16 nLine; ++ UInt8 VsLineStart; ++ UInt16 VsPixStart; ++ UInt8 VsLineEnd; ++ UInt16 VsPixEnd; ++ UInt16 HsStart; ++ UInt16 HsEnd; ++ UInt8 ActiveVideoStart; ++ UInt16 ActiveVideoEnd; ++ UInt16 DeStart; ++ UInt16 DeEnd; ++ UInt16 ActiveSpaceStart; ++ UInt16 ActiveSpaceEnd; ++} tmHdmiTxVidReg_t; ++ ++ ++/*============================================================================*/ ++/* EXTERN DATA DEFINITION */ ++/*============================================================================*/ ++ ++#include "tmbslTDA9989_local_otp.h" ++ ++extern RAM_DAT tmHdmiTxobject_t gHdmiTxInstance[HDMITX_UNITS_MAX]; ++extern CONST_DAT UInt8 kPageIndexToPage[E_PAGE_NUM]; ++ ++/*============================================================================*/ ++/* EXTERN FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++ ++tmErrorCode_t checkUnitSetDis (tmUnitSelect_t txUnit, ++ tmHdmiTxobject_t **ppDis); ++tmErrorCode_t getHwRegisters (tmHdmiTxobject_t *pDis, ++ UInt16 regShadPageAddr, ++ UInt8 *pData, UInt16 lenData); ++tmErrorCode_t getHwRegister (tmHdmiTxobject_t *pDis, ++ UInt16 regShadPageAddr, ++ UInt8 *pRegValue); ++tmErrorCode_t setHwRegisters (tmHdmiTxobject_t *pDis, ++ UInt16 regShadPageAddr, ++ UInt8 *pData, UInt16 lenData); ++tmErrorCode_t setHwRegisterMsbLsb (tmHdmiTxobject_t *pDis, ++ UInt16 regShadPageAddr, ++ UInt16 regWord); ++ ++tmErrorCode_t setHwRegister_main (tmHdmiTxobject_t *pDis, ++ UInt16 regShadPageAddr, ++ UInt8 regValue); ++tmErrorCode_t setHwRegisterField (tmHdmiTxobject_t *pDis, ++ UInt16 regShadPageAddr, ++ UInt8 fieldMask, UInt8 fieldValue); ++tmErrorCode_t setHwRegisterFieldTable(tmHdmiTxobject_t *pDis, ++ const tmHdmiTxRegMaskVal_t *pTable); ++tmErrorCode_t getCECHwRegister(tmHdmiTxobject_t *pDis, ++ UInt16 regAddr, ++ UInt8 *pRegValue); ++tmErrorCode_t setCECHwRegister(tmHdmiTxobject_t *pDis, ++ UInt16 regAddr, ++ UInt8 regValue); ++ ++tmErrorCode_t lmemcpy (void *pTable1, ++ const void *pTable2, ++ UInt Size); ++tmErrorCode_t lmemset (void *pTable1, ++ const UInt8 value, ++ UInt Size); ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMBSLTDA9989_LOCAL_H */ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local_otp.h b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local_otp.h +new file mode 100755 +index 0000000..43cb78d +--- /dev/null ++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local_otp.h +@@ -0,0 +1,54 @@ ++/** ++ * Copyright (C) 2009 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmbslTDA9989_local_otp.h ++ * ++ * \version %version: 1 % ++ * ++*/ ++ ++#ifndef TMBSLTDA9989_LOCAL_OTP_H ++#define TMBSLTDA9989_LOCAL_OTP_H ++ ++ ++/*============================================================================*/ ++/* ENUM OR TYPE DEFINITIONS */ ++/*============================================================================*/ ++ ++#define BINARY(d7,d6,d5,d4,d3,d2,d1,d0) \ ++ (((d7)<<7)|((d6)<<6)|((d5)<<5)|((d4)<<4)|((d3)<<3)|((d2)<<2)|((d1)<<1)|(d0)) ++ ++enum _eRegOtp { ++#ifdef TMFL_HDCP_SUPPORT ++ E_REG_P12_CTRL_W = SPA(E_SP12_CTRL , E_PAGE_12, 0x40), ++#ifdef BCAPS_REPEATER ++ E_REG_P12_BCAPS_W = SPA(E_SP12_BCAPS , E_PAGE_12, 0x49), ++#else ++ E_REG_P12_BCAPS_W = SPA(E_SNONE , E_PAGE_12, 0x49), ++#endif /* BCAPS_REPEATER */ ++#endif ++ E_REG_P12_TX0_RW = SPA(E_SNONE , E_PAGE_12, 0x97), ++ E_REG_P12_TX3_RW = SPA(E_SNONE , E_PAGE_12, 0x9A), ++#ifdef TMFL_HDCP_OPTIMIZED_POWER ++ E_REG_P12_TX4_RW = SPA(E_SNONE , E_PAGE_12, 0x9B), ++#endif ++ E_REG_P12_TX33_RW = SPA(E_SNONE , E_PAGE_12, 0xB8), ++}; ++ ++enum _eMaskRegOtp ++{ ++ E_MASKREG_P12_TX33_hdmi = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P12_TX0_sr_hdcp = BINARY(0,0,0,0, 0,0,0,1), ++#ifdef TMFL_HDCP_OPTIMIZED_POWER ++ E_MASKREG_P12_TX4_pd_rg = BINARY(0,0,0,0, 0,1,0,0), ++ E_MASKREG_P12_TX4_pd_ram = BINARY(0,0,0,0, 0,0,1,0), ++ E_MASKREG_P12_TX4_pd_hdcp = BINARY(0,0,0,0, 0,0,0,1), ++ E_MASKREG_P12_TX4_pd_all = BINARY(0,0,0,0, 0,1,1,1), ++#endif ++}; ++ ++#endif /* TMBSLTDA9989_LOCAL_OTP_H */ +diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_IW.h b/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_IW.h +new file mode 100755 +index 0000000..fac6b7d +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_IW.h +@@ -0,0 +1,305 @@ ++/** ++ * Copyright (C) 2007 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmdlHdmiCEC_IW.h ++ * ++ * \version $Revision: 1 $ ++ * ++ * \date $Date: $ ++ * ++ * \brief devlib driver component API for the CEC messages ++ * ++ * \section refs Reference Documents ++ * ++ * \section info Change Information ++ * ++ * \verbatim ++ ++ $History: tmdlHdmiCEC_IW.h $ ++ * ++ \endverbatim ++ * ++*/ ++ ++#ifndef TMDLHDMICEC_IW_H ++#define TMDLHDMICEC_IW_H ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++#include ++#else ++#ifdef TMFL_OS_WINDOWS ++#define _WIN32_WINNT 0x0500 ++#include "windows.h" ++#else ++#include "RTL.h" ++#endif ++#endif ++ ++#include "tmNxTypes.h" ++#include "tmdlHdmiCEC_Types.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++/*============================================================================*/ ++/* TYPE DEFINITIONS */ ++/*============================================================================*/ ++typedef void (*tmdlHdmiTxIWFuncPtr_t) (void); ++typedef UInt8 tmdlHdmiTxIWTaskHandle_t; ++typedef UInt8 tmdlHdmiTxIWQueueHandle_t; ++#ifdef TMFL_OS_WINDOWS ++typedef HANDLE tmdlHdmiTxIWSemHandle_t; ++#else ++typedef UInt8 tmdlHdmiTxIWSemHandle_t; ++#endif ++ ++/** ++ * \brief Enum listing all available devices for enable/disable interrupts ++ */ ++typedef enum ++{ ++ TMDL_HDMI_IW_RX_1, ++ TMDL_HDMI_IW_RX_2, ++ TMDL_HDMI_IW_TX_1, ++ TMDL_HDMI_IW_TX_2, ++ TMDL_HDMI_IW_CEC_1, ++ TMDL_HDMI_IW_CEC_2 ++} tmdlHdmiIWDeviceInterrupt_t; ++ ++/*============================================================================*/ ++/* EXTERN FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++ ++/** ++ \brief This function creates a task and allocates all the necessary ++ resources. Note that creating a task do not start it automatically, ++ an explicit call to IWTaskStart must be made. ++ ++ \param pFunc Pointer to the function that will be executed in the task context. ++ \param Priority Priority of the task. The minimum priority is 0, the maximum is 255. ++ \param StackSize Size of the stack to allocate for this task. ++ \param pHandle Pointer to the handle buffer. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMIRX_NO_RESOURCES: the resource is not available ++ - TMDL_ERR_DLHDMIRX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWTaskCreate(tmdlHdmiTxIWFuncPtr_t pFunc,UInt8 priority, UInt16 stackSize, tmdlHdmiTxIWTaskHandle_t *pHandle); ++ ++/*============================================================================*/ ++ ++/** ++ \brief This function destroys an existing task and frees resources used by it. ++ ++ \param Handle Handle of the task to be destroyed, as returned by IWTaskCreate. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMIRX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMIRX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWTaskDestroy(tmdlHdmiTxIWTaskHandle_t handle); ++ ++/*============================================================================*/ ++ ++/** ++ \brief This function start an existing task. ++ ++ \param Handle Handle of the task to be started. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMIRX_ALREADY_STARTED: the function is already started ++ - TMDL_ERR_DLHDMIRX_NOT_STARTED: the function is not started ++ - TMDL_ERR_DLHDMIRX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWTaskStart(tmdlHdmiTxIWTaskHandle_t handle); ++ ++/*============================================================================*/ ++ ++/** ++ \brief This function blocks the current task for the specified amount time. This is a passive wait. ++ ++ \param Duration Duration of the task blocking in milliseconds. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMIRX_NO_RESOURCES: the resource is not available ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWWait(UInt16 duration); ++ ++/*============================================================================*/ ++ ++/** ++ \brief This function creates a message queue. ++ ++ \param QueueSize Maximum number of messages in the message queue. ++ \param pHandle Pointer to the handle buffer. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMIRX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMIRX_NO_RESOURCES: the resource is not available ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWQueueCreate(UInt8 queueSize, tmdlHdmiTxIWQueueHandle_t *pHandle); ++ ++/*============================================================================*/ ++ ++/** ++ \brief This function destroys an existing message queue. ++ ++ \param Handle Handle of the queue to be destroyed. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMIRX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMIRX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWQueueDestroy(tmdlHdmiTxIWQueueHandle_t handle); ++ ++/*============================================================================*/ ++ ++/** ++ \brief This function sends a message into the specified message queue. ++ ++ \param Handle Handle of the queue that will receive the message. ++ \param Message Message to be sent. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMIRX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMIRX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMIRX_FULL: the queue is full ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWQueueSend(tmdlHdmiTxIWQueueHandle_t handle, UInt8 message); ++ ++/*============================================================================*/ ++ ++/** ++ \brief This function reads a message from the specified message queue. ++ ++ \param Handle Handle of the queue from which to read the message. ++ \param pMessage Pointer to the message buffer. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMIRX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMIRX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMIRX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWQueueReceive(tmdlHdmiTxIWQueueHandle_t handle, UInt8 *pMessage); ++ ++/*============================================================================*/ ++ ++/** ++ \brief This function creates a semaphore. ++ ++ \param pHandle Pointer to the handle buffer. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMIRX_NO_RESOURCES: the resource is not available ++ - TMDL_ERR_DLHDMIRX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWSemaphoreCreate(tmdlHdmiTxIWSemHandle_t *pHandle); ++ ++/*============================================================================*/ ++ ++/** ++ \brief This function destroys an existing semaphore. ++ ++ \param Handle Handle of the semaphore to be destroyed. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMIRX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWSemaphoreDestroy(tmdlHdmiTxIWSemHandle_t handle); ++ ++/*============================================================================*/ ++ ++/** ++ \brief This function acquires the specified semaphore. ++ ++ \param Handle Handle of the semaphore to be acquired. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMIRX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWSemaphoreP(tmdlHdmiTxIWSemHandle_t handle); ++ ++/*============================================================================*/ ++ ++/** ++ \brief This function releases the specified semaphore. ++ ++ \param Handle Handle of the semaphore to be released. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMIRX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWSemaphoreV(tmdlHdmiTxIWSemHandle_t handle); ++ ++/****************************************************************************** ++ \brief This function disables the interrupts for a specific device. ++ ++ \param ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ ++******************************************************************************/ ++void tmdlHdmiTxIWDisableInterrupts(tmdlHdmiIWDeviceInterrupt_t device); ++ ++/****************************************************************************** ++ \brief This function enables the interrupts for a specific device. ++ ++ \param ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ ++******************************************************************************/ ++void tmdlHdmiTxIWEnableInterrupts(tmdlHdmiIWDeviceInterrupt_t device); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMDLHDMICEC_IW_H */ ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ ++ +diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_Linux.c b/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_Linux.c +new file mode 100755 +index 0000000..a775288 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_Linux.c +@@ -0,0 +1,436 @@ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "tmdlHdmiCEC_IW.h" ++#include "tmNxTypes.h" ++#include "tmdlHdmiCEC.h" ++#include "tmdlHdmiCEC_cfg.h" ++ ++struct i2c_client *GetThisI2cClient(void); ++unsigned char my_i2c_data[255]; ++ ++/*============================================================================*/ ++/* MACROS */ ++/*============================================================================*/ ++#define RETIF(cond, rslt) if ((cond)){return (rslt);} ++#define I2C_M_WR 0 ++ ++/*============================================================================*/ ++/* FUNCTIONS DECLARATIONS */ ++/*============================================================================*/ ++ ++ ++tmErrorCode_t I2cReadFunction(tmdlHdmiCecSysArgs_t *pSysArgs); ++tmErrorCode_t I2cWriteFunction(tmdlHdmiCecSysArgs_t *pSysArgs); ++ ++ ++/*============================================================================*/ ++/* CONSTANTS DECLARATIONS */ ++/*============================================================================*/ ++ ++ ++#define COMMAND_TASK_PRIORITY_0 250 ++#define COMMAND_TASK_STACKSIZE_0 128 ++#define COMMAND_TASK_QUEUESIZE_0 8 ++ ++/* I2C adress of the unit */ ++#ifdef TMFL_TDA9996 ++ #define UNIT_I2C_ADDRESS_0 0x60 /* I2C Address of TDA9950 */ ++#else ++ #define UNIT_I2C_ADDRESS_0 0x34 /* I2C Address of TDA9950 */ ++#endif ++ ++ ++ ++/*============================================================================*/ ++/* VARIABLES DECLARATIONS */ ++/*============================================================================*/ ++ ++ ++tmdlHdmiCecCapabilities_t CeccapabilitiesList = {TMDL_HDMICEC_DEVICE_UNKNOWN, CEC_VERSION_1_3a}; ++ ++tmdlHdmiCecDriverConfigTable_t CecdriverConfigTable[MAX_UNITS] = { ++ { ++ COMMAND_TASK_PRIORITY_0, ++ COMMAND_TASK_STACKSIZE_0, ++ COMMAND_TASK_QUEUESIZE_0, ++ UNIT_I2C_ADDRESS_0, ++ I2cReadFunction, ++ I2cWriteFunction, ++ &CeccapabilitiesList ++ } ++}; ++ ++ ++int blockwrite_reg(struct i2c_client *client, ++ u8 reg, u16 alength, u8 *val, u16 *out_len) ++{ ++ int err = 0,i,initiator,receiver; ++ struct i2c_msg msg[1]; ++ ++ if (!client->adapter) { ++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__); ++ return -ENODEV; ++ } ++ ++ msg->addr = client->addr; ++ msg->flags = I2C_M_WR; ++ msg->len = alength+1; ++ msg->buf = my_i2c_data; ++ ++ msg->buf[0] = reg; ++ for (i=0; ibuf[i+1] = val[i]; ++/* printk(KERN_INFO "buf[%d]=%d val[%d]=%d\n",i+1,msg->buf[i+1],i,val[i]); */ ++ } ++ ++ err = i2c_transfer(client->adapter, msg, 1); ++ udelay(50); ++ ++ if (reg==7) { ++ /* CEC message */ ++ extern char *cec_opcode(int op); ++ initiator = (msg->buf[3] >> 4) & 0x0f; ++ receiver = msg->buf[3] & 0x0f; ++/* printk(KERN_INFO "reg:%d alength:%d \n",reg, alength); */ ++ if (alength==3) { ++ printk(KERN_INFO "hdmicec:polling:[%x--->%x] \n", initiator,receiver); ++ } ++ else { ++ printk(KERN_INFO "hdmicec:Tx:[%x--->%x] %s %02x%02x%02x%02x\n", \ ++ initiator,receiver,cec_opcode(msg->buf[4]),msg->buf[4],msg->buf[5],msg->buf[6],msg->buf[7]); ++ } ++ } ++/* dev_dbg(&client->dev, "<%s> i2c Block write at 0x%x, " */ ++/* "*val=%d flags=%d byte[%d] err=%d\n", */ ++/* __func__, data[0], data[1], msg->flags, i, err); */ ++ return (err < 0?err:0); ++ ++#if 0 ++ int err = 0, i; ++ struct i2c_msg msg[1]; ++ u8 data[2]; ++ ++ if (!client->adapter) { ++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__); ++ return -ENODEV; ++ } ++ ++ msg->addr = client->addr; ++ msg->flags = I2C_M_WR; ++ msg->len = 2; ++ msg->buf = data; ++ ++ /* high byte goes out first */ ++ data[0] = reg >> 8; ++ ++ for (i = 0; i < alength - 1; i++) { ++ data[1] = val[i]; ++ err = i2c_transfer(client->adapter, msg, 1); ++ udelay(50); ++ dev_dbg(&client->dev, "<%s> i2c Block write at 0x%x, " ++ "*val=%d flags=%d byte[%d] err=%d\n", ++ __func__, data[0], data[1], msg->flags, i, err); ++ if (err < 0) ++ break; ++ } ++ /* set the number of bytes written*/ ++ *out_len = i; ++ ++ if (err < 0) { ++ dev_err(&client->dev, "<%s> ERROR: i2c Block Write at 0x%x, " ++ "*val=%d flags=%d bytes written=%d " ++ "err=%d\n", ++ __func__, data[0], data[1], msg->flags, i, err); ++ return err; ++ } ++ return 0; ++#endif ++} ++ ++int blockread_reg(struct i2c_client *client, u16 data_length, ++ u8 reg, u16 alength, u8 *val, u16 *out_len) ++{ ++ int err = 0; ++ struct i2c_msg msg[1]; ++ u8 data[2]; ++ ++ if (!client->adapter) { ++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__); ++ return -ENODEV; ++ } ++ ++ msg->addr = client->addr; ++ msg->flags = I2C_M_WR; ++ msg->len = 1; ++ msg->buf = data; ++ data[0] = reg; /* High byte goes out first */ ++ err = i2c_transfer(client->adapter, msg, 1); ++ if (err<0) goto BLOCK_READ_OUPS; ++ ++ msg->flags = I2C_M_RD; ++ msg->len = alength; ++ msg->buf = val; ++ err = i2c_transfer(client->adapter, msg, 1); ++ if (err<0) goto BLOCK_READ_OUPS; ++ ++/* printk(KERN_INFO "DBG blockread_reg addr:%x len:%d buf:%02x%02x%02x%02x\n",msg->addr,msg->len,\ */ ++/* msg->buf[0],msg->buf[1],msg->buf[2],msg->buf[3]); */ ++ ++ return 0; ++ ++ BLOCK_READ_OUPS: ++/* printk(KERN_INFO "DBG blockread_reg addr:%x len:%d ERROR\n",msg->addr,msg->len); */ ++ dev_err(&client->dev, "<%s> ERROR: i2c Read at 0x%x, " ++ "*val=%d flags=%d bytes err=%d\n", ++ __func__, reg, *val, msg->flags, err); ++ return err; ++ ++#if 0 ++ int err = 0, i; ++ struct i2c_msg msg[1]; ++ u8 data[2]; ++ ++ if (!client->adapter) { ++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__); ++ return -ENODEV; ++ } ++ ++ msg->addr = client->addr; ++ msg->flags = I2C_M_WR; ++ msg->len = 1; ++ msg->buf = data; ++ ++ /* High byte goes out first */ ++ data[0] = reg; ++ ++ for (i = 0; i < alength; i++) { ++ err = i2c_transfer(client->adapter, msg, 1); ++ dev_dbg(&client->dev, "<%s> i2c Block Read1 at 0x%x, " ++ "*val=%d flags=%d err=%d\n", ++ __func__, data[0], data[1], msg->flags, err); ++ if (err >= 0) { ++ mdelay(3); ++ msg->flags = I2C_M_RD; ++ msg->len = data_length; ++ err = i2c_transfer(client->adapter, msg, 1); ++ } else ++ break; ++ if (err >= 0) { ++ val[i] = 0; ++ /* High byte comes first */ ++ if (data_length == 1) ++ val[i] = data[0]; ++ else if (data_length == 2) ++ val[i] = data[1] + (data[0] << 8); ++ dev_dbg(&client->dev, "<%s> i2c Block Read2 at 0x%x, " ++ "*val=%d flags=%d byte=%d " ++ "err=%d\n", ++ __func__, reg, val[i], msg->flags, i, err); ++ } else ++ break; ++ } ++ *out_len = i; ++ dev_info(&client->dev, "<%s> i2c Block Read at 0x%x, bytes read = %d\n", ++ __func__, reg, *out_len); ++ ++ if (err < 0) { ++ dev_err(&client->dev, "<%s> ERROR: i2c Read at 0x%x, " ++ "*val=%d flags=%d bytes read=%d err=%d\n", ++ __func__, reg, *val, msg->flags, i, err); ++ return err; ++ } ++ return 0; ++#endif ++} ++ ++ ++int write_reg(struct i2c_client *client, u8 reg, u8 val) ++{ ++ int err = 0; ++ struct i2c_msg msg[1]; ++ u8 data[2]; ++ int retries = 0; ++ ++ if (!client->adapter) { ++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__); ++ return -ENODEV; ++ } ++ ++ retry: ++ msg->addr = client->addr; ++ msg->flags = I2C_M_WR; ++ msg->len = 2; ++ msg->buf = data; ++ ++ data[0] = reg; ++ data[1] = val; ++ ++ err = i2c_transfer(client->adapter, msg, 1); ++ dev_dbg(&client->dev, "<%s> i2c write at=%x " ++ "val=%x flags=%d err=%d\n", ++ __func__, data[0], data[1], msg->flags, err); ++ udelay(50); ++ ++/* printk(KERN_INFO "DBG write_reg addr:%x reg:%d data:%x %s\n",msg->addr,reg,val,(err<0?"ERROR":"")); */ ++ if (err >= 0) ++ return 0; ++ ++ dev_err(&client->dev, "<%s> ERROR: i2c write at=%x " ++ "val=%x flags=%d err=%d\n", ++ __func__, data[0], data[1], msg->flags, err); ++ if (retries <= 5) { ++ dev_info(&client->dev, "Retrying I2C... %d\n", retries); ++ retries++; ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ schedule_timeout(msecs_to_jiffies(20)); ++ goto retry; ++ } ++ ++ return err; ++} ++ ++int read_reg(struct i2c_client *client, u16 data_length, u8 reg, u8 *val) ++{ ++ int err = 0; ++ struct i2c_msg msg[1]; ++ u8 data[2]; ++ ++ if (!client->adapter) { ++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__); ++ return -ENODEV; ++ } ++ ++ msg->addr = client->addr; ++ msg->flags = I2C_M_WR; ++ msg->len = 1; ++ msg->buf = data; ++ ++ data[0] = reg; ++ err = i2c_transfer(client->adapter, msg, 1); ++ dev_dbg(&client->dev, "<%s> i2c Read1 reg=%x val=%d " ++ "flags=%d err=%d\n", ++ __func__, reg, data[1], msg->flags, err); ++ ++ if (err >= 0) { ++ mdelay(3); ++ msg->flags = I2C_M_RD; ++ msg->len = data_length; ++ err = i2c_transfer(client->adapter, msg, 1); ++ } ++ ++ if (err >= 0) { ++ *val = 0; ++ if (data_length == 1) ++ *val = data[0]; ++ else if (data_length == 2) ++ *val = data[1] + (data[0] << 8); ++ dev_dbg(&client->dev, "<%s> i2c Read2 at 0x%x, *val=%d " ++ "flags=%d err=%d\n", ++ __func__, reg, *val, msg->flags, err); ++ return 0; ++ } ++ ++ dev_err(&client->dev, "<%s> ERROR: i2c Read at 0x%x, " ++ "*val=%d flags=%d err=%d\n", ++ __func__, reg, *val, msg->flags, err); ++ return err; ++} ++ ++ ++tmErrorCode_t I2cReadFunction (tmdlHdmiCecSysArgs_t *pSysArgs) ++{ ++ tmErrorCode_t errCode = TM_OK; ++ u16 outLenght=0; ++ struct i2c_client *client=GetThisI2cClient(); ++ u32 client_main_addr=client->addr; ++ ++ /* DevLib needs address control, so let it be */ ++ client->addr=pSysArgs->slaveAddr; ++ ++ if (pSysArgs->lenData == 1) { ++ /* single byte */ ++ errCode = read_reg(GetThisI2cClient(),1,pSysArgs->firstRegister,pSysArgs->pData); ++ } ++ else { ++ /* block */ ++ errCode = blockread_reg(GetThisI2cClient(),1, \ ++ pSysArgs->firstRegister, \ ++ pSysArgs->lenData, \ ++ pSysArgs->pData, &outLenght); ++ } ++ ++ /* restore default client address */ ++ client->addr=client_main_addr; ++ ++ return errCode; ++} ++ ++ ++tmErrorCode_t I2cWriteFunction(tmdlHdmiCecSysArgs_t *pSysArgs) ++{ ++ ++ tmErrorCode_t errCode = TM_OK; ++ u16 outLenght=0; ++ struct i2c_client *client=GetThisI2cClient(); ++ u32 client_main_addr=client->addr; ++ ++ /* DevLib needs address control, so let it be */ ++ client->addr=pSysArgs->slaveAddr; ++ ++ if (pSysArgs->lenData == 1) { ++ /* single byte */ ++ errCode = write_reg(GetThisI2cClient(),pSysArgs->firstRegister,*pSysArgs->pData); ++ } ++ else { ++ /* block */ ++ errCode = blockwrite_reg(GetThisI2cClient(), \ ++ pSysArgs->firstRegister, \ ++ pSysArgs->lenData, \ ++ pSysArgs->pData,&outLenght); ++ } ++ ++ /* restore default client address */ ++ client->addr=client_main_addr; ++ ++ return errCode; ++ ++} ++ ++tmErrorCode_t tmdlHdmiTxIWWait ++( ++ UInt16 duration ++) ++{ ++ ++ mdelay((unsigned long)duration); ++ ++ return(TM_OK); ++} ++ ++tmErrorCode_t tmdlHdmiCecCfgGetConfig ++( ++ tmUnitSelect_t unit, ++ tmdlHdmiCecDriverConfigTable_t *pConfig ++) ++{ ++ /* check if unit number is in range */ ++ RETIF((unit < 0) || (unit >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER) ++ ++ /* check if pointer is Null */ ++ RETIF(pConfig == Null, TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS) ++ ++ *pConfig = CecdriverConfigTable[unit]; ++ ++ return(TM_OK); ++}; ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_cfg.h b/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_cfg.h +new file mode 100755 +index 0000000..ecf98d7 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_cfg.h +@@ -0,0 +1,107 @@ ++/** ++ * Copyright (C) 2006 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmdlHdmiCEC_cfg.h ++ * ++ * \version $Revision: 1 $ ++ * ++ * \date $Date: $ ++ * ++ * \brief devlib driver component API for the CEC messages ++ * ++ * \section refs Reference Documents ++ * ++ * \section info Change Information ++ * ++ * \verbatim ++ * ++ $History: tmdlHdmiCEC_cfg.h ++ * ++ * ++ \endverbatim ++ * ++*/ ++/****************************************************************************** ++****************************************************************************** ++* THIS FILE MUST NOT BE MODIFIED BY CUSTOMER * ++****************************************************************************** ++*****************************************************************************/ ++ ++#ifndef TMDLHDMICEC_CFG_H ++#define TMDLHDMICEC_CFG_H ++ ++#include "tmNxTypes.h" ++#include "tmdlHdmiCEC_Types.h" ++#include "tmdlHdmiCEC_Functions.h" ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* Number of HW units supported by SW driver */ ++#define MAX_UNITS 1 ++ ++ ++#ifndef TMFL_CEC_AVAILABLE ++typedef struct _tmbslHdmiTxSysArgs_t ++{ ++ UInt8 slaveAddr; ++ UInt8 firstRegister; ++ UInt8 lenData; ++ UInt8 *pData; ++} tmbslHdmiTxSysArgs_t; ++#endif ++ ++ ++ ++/*============================================================================*/ ++/* TYPES DECLARATIONS */ ++/*============================================================================*/ ++typedef struct ++{ ++ UInt8 commandTaskPriority; ++ UInt8 commandTaskStackSize; ++ UInt8 commandTaskQueueSize; ++ UInt8 i2cAddress; ++ ptmdlHdmiCecSysFunc_t i2cReadFunction; ++ ptmdlHdmiCecSysFunc_t i2cWriteFunction; ++ tmdlHdmiCecCapabilities_t *pCapabilitiesList; ++} tmdlHdmiCecDriverConfigTable_t; ++ ++/*============================================================================*/ ++/* FUNCTIONS DECLARATIONS */ ++/*============================================================================*/ ++ ++/** ++ \brief This function allows to the main driver to retrieve its ++ configuration parameters. ++ ++ \param pConfig Pointer to the config structure ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiCecCfgGetConfig ++( ++ tmUnitSelect_t unit, ++ tmdlHdmiCecDriverConfigTable_t *pConfig ++); ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMDLHDMICEC_CFG_H */ ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/docs/02_sw_req_an/tmdlHdmiCEC_API.zip b/drivers/video/nxp/comps/tmdlHdmiCEC/docs/02_sw_req_an/tmdlHdmiCEC_API.zip +new file mode 100755 +index 0000000000000000000000000000000000000000..0e96788c87aec8afb3a0753fe2ce8f6a6673791e +GIT binary patch +literal 148480 +zcmeFZWpE_Tk}X&*Y%w!4Gcz+YGc!|*nVFecYB8(C%-CY7#nfWv?U{u)GyC1O_hB2`ZyN&ZZ0H93_01*6xi~r)1-qgYK +z|MB=AUjJ{8!&)*f8=S~J=Nk361nyE>1E9)x77}1T*M9EZ9 +zh3>cWwr`50&k;0`T#x-u&ujtWy=H+ +zI5oP=Q>RJT#hgjaDsyoGFFH-x1y}M}10zJgN#RNt>zvGaVCTbU$mu1YY4fAqt9v;qJ@GU%6bnZAj*gKc=GQv0IO>WfsD +z+Xe-BH}4gQ1WE?*jW=wpevbq}Hj*MHU?B#mLf18DA%iiC53E4U@U#wtlQiToVOvL` +zHz6T+z*QmUGtX~TuU#QD3*x(xNrSb-h?^K8e=k~d-Pc6c*GV0jDs2ZdL1n$X)H0AB +z=;`*)lR(X11haLWu|%dRIh^AV-D5>3 +z4H0X69K$kO;Pa9pP))Mrlq$>O*-z)=;Bk4+;XmG(j*rRnq{0khj0iIH>_EX}X#}Xn +z1nUwCZT>V?&=k}|mE;i2!8u%mfx|T3Rkj44h8WbA({W@>(c0 +zk`1hHqKQ06`9U*@X!C}eA=W3kBFJ_WL={*pe!bz2c`kUl(2hWzd~*tP?j}@{4eZ^> +zVc+I27D;qD%q{oaaW)MkCtKajB4KN7Enn$*m2m2=RfpS?PTDW|_5u1ozA~K7t;mEYXLeaoK$EZV4X +z9=ctEHpp`rG9xJsge((FLs}RX|2LfAp;-pg1OyEUwVEZoT>T|(Wsr4*=+juVj2f&@ +z&*qWX<61{eWBS>EBBbk2)|J>r0d13noZRkJ0gX;`uBJFiur*Uz2?edrad-)nj)Xil +z#Iun6{JOk?J{OewQ*iu6V*Rsg=A=_=(Ob3emu{n7iED;Hk_T$kkua>@UV~uQmG@0S +zK6yD)I3lyBwnZH4N=?6Y;-d{gLb?H~0bQE1vt+;Kaoow{L2j2G+=)5~$H%)ogB{0- +z0-_UEa`j6_R-pXglFyu=VJaY1rw!TIGYrcW15t-af)SSxEj^pR2*N9xl|ooGcc5JH +z71JxjE#{O@mu>4Ze}O?OwQjN2%COIyV{OtaQ%LAfF;&^g;-xz?lA@Czl> +zAqY4WrmL*(*uQ<0xymI4mW{+uNMXmymBJl&aVifJ*~Y(Y1V|!V=d8Eidhv<%0BO!)t~?{0J{PoZ_qL@RbsPj+^c-5 +zZ|IL5oEY9*GJ+3wq+0-9Rk-;0mfOXE1C^+e-GQ|*T!j*m+~xuMEk4LjX=qb;&yigz +zeo+Mj?=vgC+i%I>+|7k4EB{4Jjo()`jgxKib22;v+1~ULi!6o=32bO%dIaGW`Rk~A +zP!1(qijq?&xZ1*O0M6L)ZBu@B`sMK3g5k)#YUez(xOBb)G5dNBv^wmR0soS6iP9@` +zaVPgx?k?xMZeJ4v)f?zrK?eek93J2%kxQu`LXEERU +z<*zos`1L;7mnW&`*II-50+u4T9SaK91kYXuh!yLgJkBzSBJVR4&Z@85Za?Di1^neX +zvV96B{(xf#fN&3rJSN~Zf}s9zw}WQAnxc@1de15mQ$(!DDS?;{)<{4x+!lPElL=!% +z1=Quoho3WeIRPP${V~$lQqbPD>}Tl>`8Lz>g{Vuf{k+%sL2|;-YKLDe14|`_PgWOg +zVZ28^ze@%Kgs;|PPR(b7r`2r +zf#2_}ke}Sezz62Raq}mzWB!lGEb0v=6K-Tb@L_|TlP=q&e>9I11lIqD9$ICneSlKR +zki#eKGhd-X#{rWJ!Z`&64gMW5PnSVfOmJ~WCYkHdv;Tk3MA8Clxh(!BGa-K)&Oc-# +zmS#q#X3q4Mu6DNnn1ztV3c(K&!h&6O4>UU4y#(wsSgk^9CyV|TdGXD5UQcu{Nwiff +zCP|86)4LX-DT|o&KM|i?i^E{wSb@H|%PC6xkn7mR;w;y`)VY#{!*1VDyobe1jztNC +zBe+XP%zeg69!(T?HTdt7_AETwSou5Qf^YvkX>$h$*Z;3c`zlV#4>BTlAJeF#;}V^2 +z&7`XDDMlg)%DX$EzbMthsl7eKW>-agcUs@doS(4-0PaZ>US!4XP&H@ivDuVqNvj+R +zpri13YbiOI)5dK(FP)U=q+htu0sf#GbHvbx-Rz58npbah5Md5UQ&a5abfP(VUzi5KhoJdKxHj1sgI887*D +zd2e0pT!un*RZ?Om5k@NI24%z_E|`@nd6|NQ8=dh33wb?%yAZ~cKvJ`DQz=P7*<{R1RKgP2CNrl^2J +zUK453!z?^Nu>uP6O5Kdti<$2uHwqmgBiC#ZG>kH-3(I&1W)SuzN-iOYBTEVjw?!aR +z8KL<$5aY{2?gdPVB2pp-$9~_&cuZ&RmQ;KZTtI{l-MjGwIVO!1`Ary7X2MG5LWoGa +z2L?676x8_i?R!5oqP!F{LJ*-;7bc-z*$*b=$!KK)$?#;@Fe7HjL{?E3V~6GlBOWs; +zLMdc1CCnfxUZm&|MP?zT6v}brwa8>~B-LA=oFSnsE0_UT^yvYo93#v$GbFIY2>Hz0 +z-IUP7*PsA0^!mxhlW@ySiKKDTpz>W-nn~nInMO$$+;9p|FRY83TQbq#hi-3sEja=zzG41%qYa)gNTuDZ{aCpiK$2<6TrrUtpGC(P-uM +z-54cijWC7J5xuHuoJLyT*063I(h`WZOv$>nLQ)hxL1(@%I0qONCsM{(J2C5#dy`7V +z1!zT_;yh#dMBc6EWyI=GA>S7Gxu>X~+nYbO +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 +zl18V0>$H9lq1|GB|W!5ycX5>H>;1v^C; +z-m|n8XK{J%nlxmH3O75O_D6+}6=C#cK&iVQ&(3Sx$vArm+U(iaB4+7(htF&A@KC=! +zlLE(3D8QgqYfF=(mN1Uutjj!iX~7%m`w5a41JCK{t<1dlEtD|#vXoU;#Gft;tNtM9 +zjiCOxJNvd#gX0Iq2Cf+`hP1p+qca$>TB69!{E47#>B`(%{EXINp||Mfn4Tb3x*JyJ +zR@m;G#i+QndpdcCOitlq@SIwAx&CU~%TA{Ck}cBao)iP_Vy$nB<%i-w8uGB%ZKQIO +z<00=g;~qDC7`t7#jrO}%0)SFSG|Rv4R6OofwkP?qEa}okvk34cE(Ez +zStExjKje2r%p&t<1S?ViOlu#z#`kHrZVK5y`3)wUPJ$FcsPf|+e^_fiP6SYOc6{$Hwtww3 +zO%3qog+p}H6T{`Wr(N1yUxJQaNG1gd1488#=;2gj8L3;+jYtc~vPz&SI!t1S9j6YY +zBOusbGj|&6`>hpmuem&Ho|}lB$BRDNHEo^cKkd5TWjAHLUiJoxe>@wS0w^ejsa!vm +zr>$w(N7kL|DX~0b7!ECK6n_O2KfBF4zTv;_Jtz>iRBVZ88ch#k&T{PvPv(zpuhRGVSOsz%|0=R2!!;6HPh-ba6D7*OjLAomS48Yes>o +z+w^4Sv9T_`AA_JA_FVT=MucDh4dkhmVET~q+uI;8yS(7y9ZuFRUpRCv*x0Nazd(y8 +z7AMQscYyXBqAq6cW?G-%l)-8?bI)6f)7x>3{(wxTeL5B7v+nk=>u1aI9?|}>#$}>& +zJan-{HPbYL)5Pad+>R+?ZWM&R{Z&@a{1Ka(p8WK>fK*s9hLK`4!!}m>+49YP&_H%; +zD$8Nh`pksAt@FJ)-jz~;yuYgH@@jj8rfZlxwk;z+#!qPPV+k#lTy}b_F9F_e_8DT3 +zOpgSS4k@68@7&9IXjAl*PRc3|E_&9Xrm|Mwn~OSo+x2=>fDIpu35SSfE~$lV1_HEw +z9tK_#mF+3&L63fchnY`bRd=!|gF?)r+17^Ktz#x&!#1@1f*_Js9-Nd +zWrD_lQw0sO@Q<$b6~nt$l%YaNf|OAMhr6VI5&rFy|0mVWmIObKd(j(pt(NA6Pj$eO +zQdIVh&am_E*8&>JS9HSM+FBJZs!try9y8JI(NBz6VhH<{$4zgx(@CeioZF7cfDck(#Zl +zTR%#7e4kzC9e)R+fAvzItI>nh1hxjEe?mw_q9het0>b;I|99 +z>$O|mJayW{BKlmSD+e_2={6G~4@B={>V4#_A;Ugf_&Ad43fAaO!q>^mZA>}0l7 +zt)-)nG>?;c0M9rs>fZpa%(lok`t_+`+<(YGkvcROip_Q8_xZ^o@w65mA}c={GG|T_ +z?qpYJeoeK(hMD2qRD%tdiCw7ySAFQMl#-j)kBgITU?vsVz)2^h$=wNfiOxh6X}}#K +zar0!ZzCaa-fUBXt8rb&JgoSzMS}Pm<+uo2kIM*nD5QVUK{+#;i8&p=u01bX +z>f*un2m?)*`rV_i>-B4Vgt3&tdkMCzRD;)s<kO2kvS +za%Y1FLZkI)8r;$@AC-0VvRU&wB8dAr +zw$d?rPR^$kJHMWiKEE#V6j_Y)7cuV|?7j-?$v1u^G#CXQSoV$q0*0X&!NhK1p!=S| +zk)ZmiCH2~W7EX*O|4I(Cb*W@P}zDb_lfYY!8+c*O1donD`NkTMDV|A4gQVT|BcxH +zjoAN<*#C{#|NlVj{|g@fSI+KV!sGu*-2G4F{%_*$-^AU&iMxLjcmF2t{!QHdzlb}U +z-cOc=zp@!vuzyw_|A)|r!OGs$%=2GseqvSS95xtXflnHaAgwy@i9f-AtwDsj+p)L` +z23+cop_{-YlPM&vc=r0K9<<2SyK!ZfY@-lJ&5Ip-tK|Yv@tl!hnSuAv)pfeons?|% +z-+C}UYEKRik7X=n1u$dRL4CCA3M5H*l~b2?3Y*%gv?QKOoZPcLVt?f!@jc` +zj`Q04Vgr_?5=ZXE?1n`1IikTg3&bb+percanKvrM;Jg}TZ(THLzb_>~G@CkFqI&!^ +z6(~V(H){&WO%4HBb72yjpz$oX;qVFZN9y=B5g{qK-X#Vb5)Ysz04pP +z&ST-FIHK6Tn{^#Houo!YDXS4*>vdGzHG=w`A> +zOv^jVmuqd~+avlUG;V@4`|VcNPcT2w|Be?Uo6o$hK>&cyzsjM1Qm6mt8Zo!BHFNpb +zYh+n%$6=8X(Qn7VNi(R8+-evxh7@^yRh_j&dILu|6~zF>CQi@R!{+6j>v;56>QC9d +zZ#PLfvrjKQSGM_!>m1YqAd)r*#F(Z(PSK8zm5F3q`q*OnIEp$@V|hP(pi8aN#ETyR +z`Q|E;`}947)Rhi}t?gr)ayLq+xS-M0CNmDGo!Ij%*V$y|Q~T?qM1%s;`}F?Wm<@$H +z)$`x!6^jq?!BKHISq{LQfa#tt$P{n6 +zU%Es}cT+l)%JweI0fq4>cw)28Rm&4A#qVV`e*}az-v|8(|f`O +zq;&%XHMBcy)pAPmFt$!5`3~=le{U`H48u(lv=m^wB2q0UXZ6;3bLq@f*oz^#8oZBX +zrqVTp`_jbrT@mHYR6WNI;%U&BzR1Znzwc=kv#r +zt8lP)TmG$2#s0D3>g4m_*b=#|MGZ+0jDLMi-Vi9iP^ti%fp&q4rlC$UqJt1plo)lHED?Q +zs~M3pc&V9bHftqwq)1IDXOkR^%GYx)N&!S-3WZwjaujDz*X)arM^7|HwbdR0 +zz>|rr(63KoSXJ1U4KDfIae_M?k0*>MKQcf#o($DGz-I9f8_Xx`CZ!De_g)V|o=QDN +z5pvomXhVV0MpWW9d`Yw5T#21ji)2L%l^S}5nD|Cok;|ba$XA~Wv|Be50><-Qsd_L? +zma-5koKbfGeLe#@EBK22sy&P~8!5CRB=vQmU;-l5#;;ylxYJE->I4N_pwVP68EvRH +zb77u{&odR?*RB?S~k4R!hRb%vu%mQZuB&2mY`ZX7vZN|z+>j|IldCKu93vZlE-E-W;23hs2??#5!r?_p*R+ +zR7vc;FJc6eG+H?d!jd4q-9M4mi_lTOM8)k6Wv^u!t0FWrGNzqn)5LXUSIQgLCE#O) +zLG#3EMUBOgOF~mD+gf*NxRU}>MEbz+Yg9?$n%jDf@ih!5_U_5zmspTg-^MaP=DbG8 +zMi}Lt(zS#^a;BU~lLqv{n1Hfu9I$*U%1f&uwy7f4G-t9Pv$DfJWzIH4_+b^|KIpPk +zsQF4vX3F+hgF~DziVB;tW@j$iWwW~&$$x4>WGVJ~-B8cMYftoDy4*ZfkXCAiJ&TAr +zs%%!|@<#BTPf2_ZZ;vUwa*I^Z)z)p}gE2;wgB +zKZ9J73va@jVwno%MHg#Cx7MJ}F1tj{!CnMP!2sZUt6DvSvHfxfo4yK)WwG_0NTc2lEZhBQLVx!z +zGFrm@7JzI28*iEDYwgy#+nce}5Is>>^Amw~AeugC-tOtB(|cpZY^jB+L}?g!-np6- +zKcFQ&c}Q?UBtSt+M-IPp2eQf8P`qHghv**vS>STl;td7-oIXT+#LdpARaiZiYKblp +zVjgTnw7KZ-4rVhV=z^a-5ZH?UY9X03D{CnZ^2ar5AT@yTa-lO=00+6@=$qY!>u$5Q +zb*Gv0zVL2MwM1|DRTIZHg-;tafepiFL!!!_Tf9bT7{|XYku`l48|tGA-|4tAxxf2n +zQt0&#^=A96^|kZcJ+3YMU30u0rQ{=loz72iQln&4w{aa+n+LC;n1-}1-GM9tRi};G +z6@S_aXz3enD*cdbhTC*fShwhUxTA3@DP#j4(i-cH`S%8^eLX9`*tt3jRKL+jaE&vI +zv3KpHvJhef7;g7w+8+`qm)nsjcFl6vzOf3{mI?*PP>n45dR7J-$O62#}%50!QYfY +z6BNMxzY}^5#NF&oT&*1JUH*5X@RXjN%SLPC=e9v$Ckvk)g;Rt^lHDHGio5o#)SsBc +zlH)0$2XC{ePL5;=ywvbb&gXL%KoY8i3<*{1S610CmxfvPoCmqPBTjQ3j-xER51Q&P;|R +z&KQ@FIDwqvl{#0k&IK)0fAK}uZf_UH(A)5RS{^|wPH&fl!}un~>@Xw0fZI{A=OaRd +z-lICxz+wme-UT>s-)vd@-Ptw~+h&a{GtX$> +z6uF2nudi2vt*uCF-i<0N#OfZL-xtbkrHtsFT$j?@E0H{!75a|Qm({HCg1PvaUh25I +zTzNYj87?(0`I$aTaF;SeNDCFxxrU%9p0QIImBJFY^xCkAH)7Noy2k7lkD2A;zUhG8 +z|NDYsT;c{|;q^K3xS{c&MEm40E#_c&X%gztiSsuU;GDn}G3HOL?{w^9Q5VE!4AKul +z_(eWhv@Xj!ga}8qDbESwUhvBd1FraHTD2^)SeFGPPEE8;eA}&$@AtJ@Q#;DC*2iC| +zO^Q8h+=m(uhLCLRQ2Tm~Jt386`aUNaD~QoQPJjNOD9AX(2?siFYBgz2dyQ;~wD)L|o +zj`hL>hc^R30y-cSE6{4Vpc>kW%a+ey?^mCI{)H-Y)QrpeKSzZ)!xV~>=ZP#Gn$~lR +zp#+urB4O$wrgSJaM&OxYF0grf^W%Rq)P2VKu`>|D6K;*J&lug +zMmJYFIX~>45r=Mb^JP^W%y%38CDsJ&D9j<4Q(VNjcHv#7tQ +zqn}`Qe-m`k4Ocq&PS2SjHhAsElz3cI?XTM5&mOmxYx*o9o%K(SohHjq`9*fPz>ksZ +zzQBCQzB{37=d|pj3P)Pn%XC0HNBY;hR-&TXya>S7lPm4))Sipwd@$`Hx2KD%tFu#U +z|G93ooZ}dy_;k}7f45rUM9)zu4oXu+$sC+l)! +zySi!qaI`wPDLZ=dJbO}renx)f12i_5RIo8XyWpVTrz}XTMO_^XL52%qs+ta>8Ie7# +z#4((WG!%02lU6SIo-}jJtM~C;YIZ&_)&H`qkBgIeZ2QJ8>FDZ#G)bO|Y)nF6toLUz +zA6QtGR&@+U6<8YC{iZ&UUBOu`r+~m;$)Q3RGM$ga)v*JOyS<2yo0eso0u(hIp|p)b +z!O&g4Al&(M0md2i(309s7{A1elSxdwLiE%*G%|C#Fb!}9Am)%r*U)w))q{){{V`jh +z8_<(~*sB}*r3E5ixZmJRZB4Q9^z_0|W(ad}`U)&aJ-!cA&kH?cjYi@5JpkgH!EZid +z`7^R*F2D?&QZqQ+IVs$r$jMW))*(HNW%9;;>@d;AwZOU0%+pv%D;)eF{SNzAuSxQ2Mb<38=XuIlel4De)Ne7l=}SQ~D!zdNxw)rsE& +zzmHn8SINm019YP_OQ#%OXM3^P{lejI>etLih;HaP0XK0%Gf9oYLraSo(cD?aJolEv +zJbxn_3Bs@gq*CFpc@^-O!8usO +zNACG|q(h=h&S@+R2`(Y4$?#i}`nRTRBnSr6E;I%c5{_d-)v|tt^CbjCXLR^kwW?9{ +z5skrX=V?r2aIqY>aBa1gf1&9!IQ}^RvFsUZmx)Z>Q}*=JlQ%CkPm)enE#o#T_%Y*F|2jE}|2nzTy)*mARzVZ_@)ZhC=3*GDNtm4jcrHYI +zy2n-FpJwv;Aicg8GO@f#?5d3M3cX$y^DWKgnaM8yNhO_BGb4htY})m=?`lg~H0y2+ +zHW%rbQV#QMvNhV-boE+#Rpg~n+F*z8um@ma4M`=*ls$D@5j$t%?Iyk?<&&y)lGS7T +z=!maGN;b|DYT;TP+>5M76YD~F0I27O1JqM8$K|g5A$!#|QA_nEEe{fGDgO-=I#Z02 +z`5_3}*scecd8Kl(inL*fn}g7IHW_`wlYww6*1RIAYfI@y%wY#3%$hS@nT5RjTNU-~ +z@0xs*^_roU(2bbqZAzbrW`(YbY4-KMkz{+UFzd+7B!8mF3hAa~eJa|b5M#@gUi^R= +z{PrCu2KJcddf)n^@szn!aofp`)-%nd-(i?qn(>`YE@+%{%-PDQuVVAr*R5uCC=*^j +zXhZAS81=x5Gui0@W5o!XGof6GktcwMHJe`BOQxazDJ{+8j(s`!u)&=I{c~ZS7+1n0 +z{={Bwcp|!|ks^&r_Ko16*bP@|W=FT;i^pJR;C%G#4%MAsjn=dJxZ{U@@hC0A@inQ< +z&eEms>P|<8EJr&XMtxkeR->#^8MS{Qn|@;qh2Ssc`q7eMvl%oa6rKR?nVlZp2iMyD +zZujC69agli4{?3b +zrnJn!*^jLH&QJ9LZG#B&TaDSZ34@E%ns7TBEuDi`VPo$?BfN8(Q;53zk(CMI<&}nu +zDIFdA?3&i>?p58!`4W|buFiKWrO&F+TlCzT*x&`-#g%BjE%2pURxg<6^GAnwrDzYk +zw^yjkv-77%_iO39e8b$en-+r9%>~ds8-$2DP?S#>XxV4?K&X5-_mBc9SAxU-sR6h> +zjyk3Oo|9p?y)NH&p?7!opsS}7IHI`4VvZ2b+8E=#grD1pdvkGryVbSUq1{{{(GZf} +z-_B{ntzl&zM;P~u;U)}mbHYWO@$v|cCrU~m?JpCwn6r} +z-9$s=uq(?r!tUbRG0sC)!+8p9q;UhP#J|11G3+}#em4J=hr7)s(9;hTeXB?at_qT+ +zn*L_q=#s6)@<0~yAngma3#wuuEDCuh6Tw6KKsL0I{F+poJtli5Q^7*{K!*Ax?7OCN +zrZa_-{DLfvdPkPB&b$K$mZ4}qIgRbbSlDf*r^YQ?Vd>=?i-ux7y~LhqA`B!NyAh9* +zt=ReG;w_yB;gV|uT(p1%#B#KvFfC2n3&AaO*I-c@fmI6JzbGmVWWb@3#UMzELD}ff +zi)%8_tbac@5yLS`OM~`!Jt*j&UA7HLR_`9*$L&ZBULPXza8aD0d((40E@1!G2LV3; +zbl3aiaah1U-{s3`*+qzNg*3D=C1hvp@!_O6S%HVt%>Yk5q=>sj&bk5v*%JBNZNFfE +zARzcM1~%)^kp})pS!+3D6GGD=kX3JbcDc|9Wi?t|goO4?2u4duDBG{^_E%}+JCeBA +z1C#wKl<4MBE~=>oU^d9Tv)f?(G^)_5d>W$TqIvNFqAd4kFT=%Vr_4`b9zI^$i+f3i +z=464=+(TW}?z?!({H)}rgF^geUe$1PkDEE@8(VnjOT#RE5|tVynOVEef*CTmC3}qY +znk0$YFPd?aSi09Zv17Y}aQ5(A} +z5ocg+gJ4t43e3vg2Yx%goA$6lMX+~?&k_-zGQTwn7;ALX&y@IeTkj32my;RA0&EL!tSx-LHwoS(48|%OyTcg55m94 +zjNN<{`K_B&exe)}vv-|#D)V=;v|6N*yeajZ(OX+FUQXNzMovq^rRvv7PU8gdcf#F; +zGcK84y(VuWstI3B`gBgs`QD2?1W#==P?lsf(~%owDhrc$#x|GS*k<<2{pxJ;(nBKK +za?ey=xT05)4%;@9mP*$vOM&m6Oj+>t$W*p&`fC{dHP&b8RgC({ZIXe6DJf@s6)92Z +zfpW<@%4e&w3##2fm+Dzv1Zl+ZV4LaNTKJ>D8W?X +zc3{mnPlIcfvrqI{bnGyei@WtYqf``~6|p<7fa=-T!xsD5+B&o~QSoAD^|xH(K($6? +z)g@||d{vs3=1q@qfE&G&l@V?XzXXgGf&kbl7*N<>^yWY?SGmBy1KP|u9nr4?nqbLc +z0$ZKDnrdc%SP4`Sx&GRQ(O{~i5>R}7zeokrMGD`0baKwBdGNy4~Q7QAdC8hFUu#(!s3~LRo +zGhQ6Z_q!@)dFgO=41cw!q0SiL59|!vD(G+}&IBQ*|7W;#TxRe#UAL?f?x9kGhIy|X +zYn`J6VwHB#dKH;@3;M6HmH3w32V*nY(WHrk;G>%-#KbSo#zSVFJw*gF73^yEb2JJLHT`5{iI}~Q<4^La76S>^?R?`gwye~>pl&#Us5_TA7Gc3{> +z!?@KUT2ofpj50@N@^0qg3`V?xTuy$S+|+gWg=X?DezZsTNd(bcz6Ybm7p<>M8?}BZ +z1qxMd1x;1AHG31)ztEZ5WX(1sM#M^&sT;N$Sz5h43`jN^Wq*X?gq`*|4luVSeg6YfVOV0SLRwN0 +z&t%ooEI80ebRI`M4+&^A6t&IR$N&uV!pX3DsSf{EQ)}b~8%8xZ5R-zmObqUf#Hl|1 +zDP+9{?ZtQm!$mPs3^{UEp@ZrNH!5Q(YC40O9icgI?$uewx_QV9v5(3no~@8*iux3! +zn{pqh+r0eu>RL3P_w1_SRr>TJKdRLESFnu>F{00*^>H@OVg`qse(q#!RpE(mxkpZy +z%vCdvExp2r#LTk2pzl9v$7;D<4Bk7jSw=Hexp*p^J(;!Lgg4m3E04UoB`~u$2d6a9 +z{~bWMCos3x1*b6KKvJ0ua!X>Jj|xRqL%yJ5i^_E&mu0#qf`HpNCaMc&b9hO%HHnTq +zxh33M8y{x*sp>Y|=BBk;bfdc(vN0rAc13A6-Q*&xiJD_+Bx;T1E19M_Rgcl`>!%k- +zL)(DSrZTEm_eY`GAMQfGf|;u1IHdnzL|AxpG^@)fi>qhE78MW=J{h(|Tq^3{YCUJ1 +zzjDVT58M7ZD4Kr3E$bPK&oLUZv)j&fqz$`Ui}Q<`@i58AXrlC^PxXN|XJ_DDYQg`A +zIaY<If)*{Nh|W1mx5tY5a44<4PFsXj+xpXy|& +zfwl8;kW8{uKakGiaQ17zoiQ%bU&vU}T*yE>AW%$f434wh +zJ~|p7UhI|(a=#11VCZlyBh#8pa=!Zzlq6@aGdHCj>(F(3XM|1ILO>8%$faOpV`#|q +zfcO%&^1~OL +zXjchH=ENekca-ono?VjohQBf?9ip1J_@zf3&Z5z{9Nej$x)v9)Z`R2>j9K&@;K(w~ +zBso?Qn+;Y^TJ@|5R_nLwnz7g)PFlI0V3P +z%?e1?Dv2Rz9D^Ry+ZmhC+YFEB>YvzYPy#PHXC)mRwj5NKH+Wn=FCIge(ZhF2$9+T| +z=`XeBNa_fF96Sie^IFgUw(oboe88bS-k$qwxIv}4IIJ3SJ#~Ujb~rGF_-6mL!{O3g +zddm$vR*URyVCp;SNRBogqB2~1)rNB3#QrvFsHH4vquX85@yL^_eyWgWB +zx^h`N9lQ0}Ivw8w**fdF*lerCF)$IT=E2GFSUdaBMLcZ`N0&}O?u6Jn`-%u+FZt(B +z($@|^?xhMRz}-`+F;;C94?*7SR67Xc)DMFyTsXkJ#E;s||dw~>ba<3Bpg6ZF{SDe-^MbdJH1J@4C(ZJQI@ +z-q^P72{-n}wr$(C&5iYqoeeg|KJ$O7elM=B>vQ#aaq866%=GELyBCXa|G;g5dJ0FF +z_t0Bs4v9sX!dcsNdnwNwV?3d5Z13Y=B(5CipJ*zL1}Sw`AV`M33%Y8qes0UO|B{@X +zp+=mTxvl^9*@zeo2N$-tx9|%w_zwcS?qC*fO$JgnW$N?e22~BHhNWxa`92M9mJn|C +z*s^d@&0j%{eFs+=G6!MMs5^)aodaDMJO?pq!R2ebxAAq{Eyg03GiofDt&fkwkzbFQ +zSZX3I5*R+jJ)?9ZiXtAUi +zLWthAP+Ah&2W^U|NF|6Qjc>7J8Oq1zCrse&?n8qX;im@igDOxgFHXhBBQI`IvY(%@ +z=!&^VtOq1x)eOTTRYQ-k{4L8DK-c3RDKyV&0pX2t+_k2SwO*}uT{%4WWeA#d$7*wd +z%s`u6z;df2hO8dXlx`O9P36p_0~DEa+QarqN#{Nux2t{LeoyvO-OJj`jwf#hEq*j#O1wpUMo5XGAcKGfYV2ts$@Xur(mSd~i-lp3;hoNUE4HyU?D52h#F +zZ95AZP}<6-bXv=04-2U;%id-sS9gAgJMouXg(9O+<-okg9-p66vFR2q1Y3% +z#7R!lc|b_wFL_bCNR(-mhizUA&Pns;W*LMx{Q>9jWdA*{Z<%ZS=n +z{&eNi`(LB~+j_mv4grdKcnCROXp8;*ffmQ&?P~j(;H_^PDzecm?V4b@+dh1RC2{FDPN&lbKD75kNU6#@?hOV}*-2Mcb4(%ZQV# +zYDOM~hA5i~3ULspB+SUSxES(Tslg +zi&A9?%bA&K9Xt(=4;}nkw=u=3rzJuq2m0z$rU|v=>sZ~iX`qV>BjdNU9 +zcBvNxv0x2po9XDs)>f&d|E^*J#)%??j)3lui&@N>z>v}r$ +z3XWG(AF1mohsr%Srae3LF9$~BA+pg_Y|3hh!-BFyUV<8;1|V&DRR-_et3b1XT`i^-2_sIg7($*_I+Tc!!f2Tm*lO8=kg_1U +z4n;?fmLaSpRV<;0ABE9n36L9~lu4aspj2g-k}5v-dP_~l!;eb#26a#;C$)Zw1-PfI +zRrK`0FqdY;({54{+ZKggtHv0>AZq%C(Vp~*rFK&^pp~f@k;^GQA<&^lT;5;&H|F)s +zPdIH{-|@1r>J5gtv@Bg_dr^|y`d2kmLB6v~DHbc!L)fcyF>*Dme1%|b?dAP!x4qXe +zeL^pNZ$UshMC9Pl-e$PIljF6xmDhfe&*Rv8)D3EnX4m)a%|D0XnuZE!WUh%_Mv8dr +z$04?oxra7a>PYOdIrTP!-9F~q_#WQ6#H;nOn3w^UZ~9r%8m6xomfL@0#-y_aqS9`B91V|++^#6BK+p?B9S~8`;=AJuY{Z{f2Fnv!%qJ1&01=IgSFcX3(DrGZ0auGU-hbU|UZ%M{8Hc=gf}cg+f&b50AM +zGx@7KbXqK<0ECj21u|1_4Lj(dxOa`8*X?P0)+nAxA}XI8nBKSX_iC(`t152%m~>}< +zoERB-4EQgN|vh|KfQDX)y!-hVD>}`qp2|!kJ6s$k-*e0YaA{IyKm=wICL!$aG}`LM!yKC +z8cVt?J9Pvrj27gSrV#}8F3Q&c +z+M@L;Dm8x-&@e7$#vTI7Lu82#v*Jlu#@4bI%=u5HwmXDAyEr-r@p!r9`kyg1#4lb( +ze^~v-sb1|@oFJ$hH>eOQmDp?N6%AgKg@!MsWk^B^&Z1Y+gp^ +zAS;lTp5>9&4!0uYQ<9$5qNgEdJG$U>3q@K%=iu`~5u5#$9+Ei#9~=U8J>nNau`waJ +zXWGAD^?X0Rm=0sFu}Bs4=>iVZ&TsxhI0g|cw(O +znmS0aZ*vAK$ESr)ewuq0g`9Ys)%PfJhQ%y#-OspO(x}>nl4X@`awfWWaz+N}fjt}F +z8$Tze7ipZ-XdDzv7#&;MYQ)4oQ~asOP&^;84p%4f$jV3PQJD=ld~sJBAya`38LWqc +z0asy#6BKjsYJauWf6C8}2!*7;G2I?loC +zQLwAc|K44jgMF`5=$rTScHE~k`657x$}Doy_Px?Dhf6777b~YgUjk2~<}XZ^fQ3PZ +z8@W-7fYw-U3=~rcq-SR=!~oHAV_-A_;`yv8I59TPqT6RwXC|DTXmNONVx>2MOel%W +z=fl~Yi?(JC3|8A+VdY6-;<|m|otRNe+w-}2wAsNo#d^q(V>7d=upbtzq`wn>C~xl$ +zrO65XsN1#pNccKjxOsnTa+z;TScpJllwl)5p^!un_iV|53cs~tQAgUHJ6$PFsh4iB +zX43-meXjyNO4;j}p)b%D__KbH=93YAl{3p736UL&oMpL +zzrv|gHtVe%e#NOCnTVGm%e&)UR%Uv)2uR*glZb_sp56boDrLBFXOg +z*T2Q$SyM6M@$z*T;T&3JX!;p1gu=9!rhKx#>f`Q(4DQ!Em%a&;490sz2j-{njqOOk +z!u$#+)fr}VhaR5!4~!0-H9_k2^LK)>uV5_Jj4*u#Y@_R>2ztcq;VaCRJlYgb;Mpl5 +znb|AMWUn8j2GTxQUY66H8T0;s7M}-wneM>*xZF!79+J`n!r}<0ze7smg1j%IAu*=% +zk}Y8p`tpK6UK^EwnM9p|cf0~&C7weu5(M1*AGXEBq_MJ^V+Fzeu$l{3GiG|`s*$7B`8hYM` +z7?~`an7}UC`akz>ewjb>p_H}CEPae$Q;Yr~Y{4BAV`uWx!x3lm#^H=93X?E+r_IWG +z3((8Lr|Pn_N*$e?rJZ8nC;>=WNy%D)LRU~2J2Oi=^uLazSp|3g`SnH>NP#jVeJMJ8 +za1XhQ(0oLz$L{ACHSG_{3+&YZ)#&Q4;t&EN395Zom7e3$)7hY^W7OC>uQ8unM&zvExUsSn<2_ +zt~L{zi3H^Ie>J0YEaM_sDYAvLw#d`Dd@85Tl7+K;2&u5{?7S-9YBwa>Ij$O~4}Zi? +z0&t$o&MTv3AYl9|k7Pu|{(0|AzdSxt +zHA#$GK|xKTWVz?Xo5ltTIVMJ`atTo@Tm(s!sQ%Ysdw8Jo7xEFFhQK2I2a3{(4pDBk +z83uce-lJmLil4f>WVTba3P@fS(VwGXvtPF2Eg0}cZyN;nf|bOeuQaC-G_PMOJ#S<8 +zU}B>r9Wfl+=YYt(VdnYkutIc!CiC1)a`~tY0=5fVl86nxQb~IzSITxRw#d2`f?Z54 +z3B27Lr!%f@9>{slZk~OjhBr&-;qyKFwAJ&y*o^UW5*cHdo-k4_iY{7$3M&Y8wNrdL~8LOQUNnvE{7+rdVv-$S)QIVL&NwwMr`ui*TTnC6q?X+q3gy +zA%QK5CwR4P5`J~kt+NnrdK@A%-iXW~{tN@SHDeqU(K&P_%FhyTyVJ7&VyD;|t$-Lh +zE!|LgK@6hS&XQE;NGc#%WfYP^;_n8t!Xy$FvjOwH(U6ZeRbklSB|_xDm&})QOw^44 +z;WkQYVw}>mE`my0<6e5Y_(xrqma!9)(|8LE4CaDTpwLPeAJf&+QXv*MgFPrIjV(!A +zYg~dr7r!-bMy%B)P}hqbAJbfno%$GHf>RA+RYVM$xqA5g1@<_Gr9zlVm1pbW)6CVz +zvAWhP*F&%#pPrO(va$knC5;b{4B^geQDWNS?ucm{c%8`Ceu9(cSw)ja=Od?1*%)Tc +z8pa8ql5J;IpeM@5VEes3do6ALp3Nuaw#M90ai-&Y222iNP`A+grRS;Bzx(&_ulN}n +z8iV&sUHZty;Rnk=pRS)#MuYLpNe55N$Yc3dpZCY}4eBn31mlh7@v;$>(N@j1yf1cJ +zt9Dk#Gd<9@!IkCa>AFm4csH(SXIIC{lP7(07rBteX>VI*4oSD+`a@xlnfE_dp`GJ? +zj^uySJN?hOtvO>bDJ49-LjGpsLB%NF;s?S1R18$_ND(wZimYH#1S4bRtxGa_>)p=k +z3p*mGKCHNj@it!ASqEQYfr|#%`O>P@-V|jn%cg_TQJcP4`)0*+yALVfgbY?D@4bEe +z?tjSJja7CNIn;U)S+2hgIyTycjMCkOoa*U@#c1h`&|@aW&9_kYtkjar#tdux-DvWkC~h1dt^ZD}|y>!mz-h6QxMPh}?6lQ#{tJ +z`_@sZ0Zpfs{r=qk>SuOwd +z7al&cl^Q_inv)n9%SH~KwH^v(5epALISUHUvJ(R(M(Y9Npv(vpBhgktrtpZziuoGo +z`tNqgm}Y@Gm4^acGCU_Ru=q^$U|#U5!~ASJ&x)x-@&*lNnlCh{n<9c$g%%`wbT(Ut +z^lb@pB4zXBg>Wq>GVEkXAx9Dj{wQy_bF5SHKvm+f9P#8{b{mU|DgJ5DCef!x-8BPS +zesF%FlvPx28$j9N<6gIm_Pv|3N*R!hm;mdQH#z*zQl<3EqIm(k`>=v6nI9us3tx%zq!a +zFaHi3P)`?7owm&pj=xe++z;h|LiOsY*F4G=WCcn&j90si5Qxmp_6-6Cnz{apWGeNgwlU$4+Afj#>t%$xIx7ut)koRH{+&W9O~fF}}zw+xzs256MAy_=mmyx1|%4A;UtXONzXI?>o5xH4;UzhJMibA1iNp +zgzfWpuD9%;xyGvD1+E$(;mk#+RKP|aGM(jM_+MAEjo$B +z##K%}JQI|RE5AcR6N&$YO$=YjuOCm}<^DFA*Q;kYK=Yv@_>0cd +zxP=~|DyfKT0?tj)uqw4>$E&l4UG5}Ydio^Xq@o2>0y(?bF%`SmI9e7j>L9)Zj2*aF +zfa!_Xai+0CU|VEtsdrSYg={1ei%+D2FA2~q7HYv9ApMXTAVvwDyl9dcmzv_UjH1-o +zrwELwuuvv{udwv=YC}nquMj`JjCPAOC<00H9PMS*RP|On=fk~?x0Yni?$f=`FrXz2 +zV4BH5gv_===+eBqn?DLpo+i?2dPpBNnplH{Azn`{i`1p2GxbBPVSz1*r`4$7%617k +zjt9=ixIdu#BVqHoh=YP+(6rw-wQozPm6AOqtJ7JaH)23wUfJ`Xep=7`5(RId@YK7P +z@fxeUBuZ2rrdCyR!&2bBAZ1e{g>^zP1YyND65dn_%vp`poy-#~f9=1_Wls +z`q6{R!+K0GxE`PCeX46I>yW+rn+A5B_BUkTPfXkVbav7k4rC%LUPHW*;y(oAj^E54 +zSNi$TM=tY;?OXK%;1wpS8fr#nfW}NezI=WoWHk61qj?kA4$yk0t)ynT-#G9>nBDey +zzp}V$uWd^um;OUoLfv*8IjZZWY}$Y>zj+c9>0#1wT$q7?lrz)cDW?@J^_y+j?~Sge +zUqjc;Qd&W!9-E%7<>==fXiOhHnKsSxX0MIt99u2f`WI!Zj9IBxr0D`cMc6%A^6@>0y{&{uDVn7 +zwVFcqitLip^wccq2zU$3bL`xULk3ZF)C_2_7D|MK_O^}mWK +z4k>(h3)j{@zlGURDDk;bR!Ae0t|Oq#EEJn*g{F!Hsgfn5D0NeF=U$2ovc5=exns(1 +z-gMh$x!2em-kZOuvy!>H#CLywwFtY4f(oCFMY12?80}o5W&g5V)!f0E+iBQZs*} +z(9M*4$Yjy9i7!(6*Wr+~)l>URMWmYJ6Ei(2#M`1!5@hApu(iS^>o+gj!9VRgqGO|J +z1&ePCId3J1Y?xk-;|#}ZRhbrJMJPl#<`(ZQ8pMvn(q;E3Kd#7*wSaM!_uCT`YNoF1 +z(x)!Wd4|(-Ns$Ku#%Td$eN%(U=2#eBz*sS}O7xr&OEZuWv*9qq!Z;+- +z%FNd*VM8!Xi&c#c-_Jg>smFsZzhqL56?+t8Lr{=mVUh}pdZn76PMoxFDBmrKbVZW3@I~Ghi*B48ZE8=^LnrC_HKAP>ImoZ_VXziGiNSnj +zw9rOD|FGjryb(RF(Ay>3g{M!Q9II4TOZ_~#+~syxvFdxW +z)mj_#!pO^s+FQ`_Ry6YGZRzFDII-9H6zOEzTT~QRq;42RfTJSIH;f91t?&Yf#k3Jv +zcNzkSm>W6f)IE}OcUr{><*j0#_dIH1e;6% +z>^KcJh-l6>bsgk{YRcp8gXrs6{i**MIBDMo;1TakmUJUlejSWRYfli~T{?Z_Oza-6 +zytnkA;80%Orp|Gpv+T>T%sk&K=QyjBWjU*ya2*uVI}D4anGK6-ZiI#a>)~N()s$!z +zrs1<>_`)(d58iVCVkQ?*YLXHU*)YUt80bO-?Kgpok=|QYBodPU_;E*a=x^Aubi +zYY%D$EPIB%M)q@rW(7A}WDW>M3bgY+wX+CoIp!agH#kmFd=iosL=emr; +z7oY800hgUQ;3F;g&m7WD)OwwWu1&uhzZd2WI-y8qN|!=sIkQ!Ar7)9iIEz^0r~ykh +zVzvZ|nTjRwa0H4XATlLToRlo7>Yf%yBW~M6o8%~p5Ns*q`P*n7&#M9PWvRqONz_q5 +z5|2_&g}$4a=!W=TvLm<>?F9~4nj2zbs#{NAyJ>wI_>fP_+h(usix!*%sA|26kqnQX +z995jk!n87!H(V}ogP>^l%j)eW&AN-VV)?tsl{OQvVSgWnBq2$Qa?TBj$5Q+LesNDX +zL8|5lsh06eQCYW8!YzEPn3pSA!iwwX(u*yBCP7Dg`AW^PO;qn+TmJ(xP^l;F9nF|SY$ORm)4u$4-*RA!>!UAuSGU!Bg=kLxU +zDGjl|u=2@;!9f4@Q`S4aWs3UdhEz+w2KUtfCZ~K|2T>gVqB)4D>2!-xjfVF(9U@Ck +zOOma(s4a@5vUKDC|NL`#c)mEt5kEpD6+4-CKdFHERu2b;6&Q-)_{Gn}O +zPN-X;Y2l)o;(}VWMdjq-bD9f- +zzbPx%UOudMzr}>b3Uue +zjYT1d-Da9Q` +zN^rOU(I!_S=Op=FoF*ck0$MJk=4>)k(hrS0`|?_RNmRXQ3Ctc;vMZJ`i!aUz^9-K5Lt|wKz|EP +zVA +ztj8~Eqw(rk@9AqPtgI+IR|;h_ot_t>->mwFGo7>)2K`z*RcCpws7(4ddl*l1psme+ +zh@1QnH~qm7`^JcQ>ZzCEHDoj*h{(D?ZIW+lx`(U8yX%e+-ambC4MUq9SR4g@oOwe?=NABOvoPT$_;?H9OjE8{dDNqa +zR1<>(6QUJ}>#xi2Thl+AvGpXRB=(KwXCr?_aY#*VF_EzI0?M&xAi|^1z{IJF2UVv2 +zaclxs +z%?HB@2j9&oc1e#a_P`eU_pk&;Mo~}%NRV-D@@zskg<|!~NN{tAksgA~?gC7=1{1;p +znO0=2sp><@Y%4dgMgL=B;^}hcaChw#vbRy|&dk&GrL)V3kw+kB>6h=z=5^y&`$j|m +zt+8O89P6rj`l9t2($izh<5l-1`oYKnw^JF8C#(%1sGbu^N(8qQ4&)mnrwNxH+-b +zKa^+2@UARDxER+k^vKEG&B>fqHf@fJs59lEKFir*!R0D=PT~lEhSS!Z4`C=O*EOXux&J_hrY&3g%&7RAB5?k3$Bz>?o7Rp0BHVpI`!CB5 +zcA=P`+zST^dLfv)`N1oQ5R8A6cYXUQpl?T?C0_LU6o^zX|0B8uq9`?*5nP?Z1xg_* +z5+M@<{GN9kV&m*3Z=XK`Q+eg1=x2!l4Gp@QdU=>i)GVPGRkIsh+GHvkeUhbkr9^qC +zN|eO;5XO-^RdelnTBU-KwtH-e1DNLCy4>&9hPJR=;MNL1L{_vk>y77_9O=P#(m6bG +zslY%_TS!kD?U^IhW#~?wL=i|-Y-QJ^9Zccx9}ztZcKWux`)%Z{O%&AZYY+w>a(ZZA +zq;^8ToEiF`8Q!R1cu!sr|DL_sPl{rn5`?$Yh+ +z)VY1BnX~FM?t3+n&5XM)2w_;82J5Qb5)qbno(txd|*1vMi=x;@IQ$an`zfO8-s{?dXrN26Cv4o=eX7A-x +zn7)I#m7>561LwbW@U&ii#oviYc7Imoaa=#Gh>%2r`&+U6SQPwS_*tOk=#?^>Nb +zbBuN74Kl0Nh9PZkwEpa#YHLp#SxU2Bct&KwE^KeoOE3QJ)X#Hp+*HxC-J1^k;4NB~ +zlT$5AOKl#8!5T}gKVdDT&8x2}<&;;XD&qsv(~VJis#Oo9fJ^FXZUh!HhS$y_RqU?@ +z7RP>pK}NHac%n-HwtHhrjcZA+$@9Z1{!}|2eSY?P%AdhmihZ2(r;@Jew&DWogH=*= +z^x82ky<75VS@Lcqyye<4Pb@*8JmpawDJMA1wyBhwG3QY%sNSAJqMbX^qj@#AbM`~E +zp7MQ<*?IoUvKeGgYx=6pC{l@Inn38PZ}*P($B9Kn~U4{X5+!0 +zk|WU&>|xtRvHV0B0lX3iyT+rY&HKczF^i9`wl8UJPh)%kd*;I5KKcxu!hf=7$nQ$> +z&06+uAbTQ>m$|nEgaw>{Rgor4X@Hn?dRr7G_w1VGSlOB7Vs@u=oV2o*)=Gt`<>F?0 +z5YXxBX^@kcD$sCpRD*c#H@u?e1et%6@$P_;p%Cw0C_%ozH0L87wOUG5GF#P@Mwp&f +zwE+`@CXL379JuC;T#yCEG0&AU51ed#6r!V9;H#l$ +znbMWSxedvW2Uv%w4yOaGON#p7W&2U~+6MLgj*f3a9OADd|EAX?E!#g6iOxx)voFEj +zh#-62Fpx3{n`Abgl0IMxjQ@D_*=@}X(&1ua*DZ6I^wJWA!Czn<^N%|yjdo%BHg%ly +z^?ZXs|INS=(ACFH^E9FRy7z-bp=$4A)#}N+tId_Mei(4Id%Gk}e0{XYC(Ev=IyBA) +zpb3ga&&Qs`Lk|O)EHI1M%3_gmH~<(v<%)!0tXZTN9+Uj&hz$t^$!hsn3k%Roa-k1^ +zEHYk6b6}c!BowabXRh&IUf4*0nA90ep=OVlg${tvcte!2iz{Sxw6Y}|Pl&uGiY;|@ +z6z>gOC#DKoVO&pwkIY>6nr_@>LmdedV26@0lOwRtIMDY*QS`l~OH#%Pl`XZdIwf`O +zuzkM0`sA}IgdYk;9OqBYnwHX=$uHc_g{z*lR0pnb(#u%xk`!D;RP^BzHl%@K$(D9z +zyHv3ORh}I9y*i4mNJx+M8F>sUvs0MXpq=!O`6b@O>I^8C3O&h)Kk +zB0RD5^bPY%W8st3?nOE<2H0kZHZd#__FCp!4hPS$Le#8q>ORS?yG1^u5iOox +z)r_KBt_BLp-AuxMPO@vRfpY2y#)83}TX}<{h6fbAaue!r`aI}g;HMG|qeOV%t!5)&*};pm2F8{{p-2jI +zlcz?I*!E&PlBH_1!-hV{Ns6CO5D0r?>jZh7=mhcdk!z7Dsnm+(E<)D?!NC`QFM^Pbb+Bwbev}jlOr)w!+n{^AfqoS^Ebcw}xb}x#zy-1q$t`G=Ypjk1owz7*%WCku +zWU8!=i|s)`w;D?%nlc4lo}Coayc%n8TxF#JgwS*tc0jHeUT1eHvL3FgZ62%wpcDB| +zuvaCNHAuT~l~fC{&l1BS|HqgGc{U`oo&a_>VYMOp@9$Piutma{^ +z@1?I%pW%XE!37@XZ-7dyJOX(&NwY_iqywIoTI1J_Tu*SY6NDkVP4s=^7DFw(3-mcK_tU=n!t7L!Ct7B;HV_%4UXsNx%{_L +zp6=-8kQu}?`(G*&#~{8H>j*0cYMX=llXqKR`)La0yT0+NC3w8ixr=4h!V4^qwz;H2 +ztKGj7=EjceYzPC;vctTIwPjs2k7i}QVTFR%IMICM>oNlgH|c=YUSVlgjAsf<}T +z7O0L>5`&{ugjE~?i=&iw7Kx6XO}v_WDDGE|Se(?L2Kok>Bq^ZQFll;`Og5T$P0&=Tkq-XV8C)DkGpB+pR6)U3 +z7kW%K@%5|0Qtov)c!y#iwd@2W%Ps49Pb#Tl%0D#Zy&Ck4-$o(Lqt<18EG}I$HMsW6nO}XNSE1YM#{d! +zV0&=*uwnIbueRNz`@-dC&tAO~sS|F`)4)~=hXLAw$J^@7z&%)BPt$)^WzUyatJ91& +zwJ0?|8JT%JwST>F3Gdf6;P#Y(ubu2YKpX$yenQ8G-B+7klm0ZkT9IKz@)0M9DrkG8 +zmBaQ_vkh_~e}tJ1qbH`trKeJ1*4Py3QlSfSDJq9N5i^B25lcf(MNFenK`E7{xo^c8 +z;J5I(VeZhDPen~dETj3I+^<)P-Uc<0m1dGAR4pb$jNe63c~!!a_6EtoSzsu$BF>0 +zsT>(UiK!eo2r4HExWwLzbu&}oS{%;)V|C=H{j6mW3MKE8Nc6@i<)hI_ +zc>aJA%z~M^a)xU~L#w#4_Dex=65gi;Z-6`hHp?2iOzXn+cfmlGtW6&7RhO-x$4x$b +zpwGZH0@T}Fy@-mn=Hcqx*v;J6>ety!&H}3ES;4&U-an!fOicNj(DgyjRGTBt` +zM1Zsf2>^alP-Yo#zMon#Qtz9IWuo~U2srI#J5KAa?WAPo +zqgwmKAjKRQWevz89%O-iWBkQ9aZ;RWghDy@-(k!7@V8-f$m3Y68mxbnOnVgg>uFVhb`F~x?G|YQH +z8Lfpp$7v@0F)=w(=T%n9#L>=WyUOFqp^6P@0JR=@Xv$kpwa5zGsFgpXY})wA1tDMq +zu_1dZkeiI_VEC`EejkV?Q*&vO!D)gdR7{T+8eA=c7Tr^lcVbK3HKVoBGG&?AJv=?! +z1O80WLvx7wO#6i78>m7g29DwpZOcPS2gF~P)#dVc(|8FT`^6jG{G}ul`h>_wIqNiu +zZ_3LW-F%%OrYaR&Ok3iwlG-##JME>7b&`mI85+UFCfZqmff;)(wv@mX>tbjU>}=m^ +zmb`x6O6dsb*a4eH8Em-=oVhxpTAz>)P?(TM;Wt{wbMEcU!^U(?Pes(S{Vx?<)Up+= +z_n$tWM)`$%&Au6MCHVD%N2;^s+)8i4Vdf6V1tz|?ygDV{);?bjjn=JQE%8JazWll> +z;hIB}6*ZyK3frB!uQ3}Q;?AkmXDS>v%0?Xg13!?rjJ-Nz4nxuV}M||CG@Y5WlggexbdpW4&s~sjjQjNq(7s +zFv13H)i;!+S5uJo%W;gl+$LU=6GUZvet%wemsc2p9v6~o4uJ+cX!2{Co(ntWn~_-h +zY1n(-I=V@+s~%`5d331H*8W0dMo#r3+6y%*fjTdb$;mN?=hwjZ@=3l;Eh)E9q*gu* +zw}qN{`F~AypHXlo^&#or7O-&#On#n|F +zOG%VLNQUL_Sh8#@(B_Nl@GHO>>qXv1q-j4C2CE`Sk|*{b?Gmyz$S8D2J7&V*?y@4% +zb(@mNxLxI!G^L!wC@gkLf_!09&UyRl>~*9gJ_q7} +zAwg4IH*eSUs->fa00zTmd?97>O?$S9;ih9n-Rh(V?$Jf>BH`e*y>w#>5Ai*11KR!r +zLZKrb6_|HfR=DC4x`#1X81h9`V^KafHx_h!MB(7Han2DrtzyWyxJtC|sJMy>D+w}D +zth7J$Q5Rh_)_Ub;eN?3Y7j`^3hyuDrNZjVF<#$c +zW;IOA4EnW7`PNG}af&d5WbP9owp3b2_CO58lVHpEu_gEZ+_`Z}woh`s`QKITdP>x4 +zlfcQT-7+K;v3&S3s`6)(&TJ@ +zb7GOt(HM}jAYagU7Q +zcxSpqYrG3)!sFhz)NSYrZ}pqhFg-f8OplD?J&jketEFpj4L;~`S^~;#Yy_q_3~{V6 +z2{M$kW{FanMUaB6J&;5pI;edRL?M}|9}q<1-?3*%-rV^dt@~c{Xnb(J&xN?439b7) +zWaIes4LuX32BbT(FC}Bfd*636+4B`#`S;v@9gGd?`Q&=;pKE=MI=Jp+kZai6wI~+) +zElT{Egv;rb=RburW42I!US;Nt6S%6k!n+zSa!viGSLh4;iL^QmP&KWRD;{2^1T|_Z +z7})7*uU%@jHL7o=?3Nc~ui>P}F_M};m~qEG?U4!W&A`yx=mU(?)8?}uZaaEt8(
NP$+9#IO!BAe)>f&VnZU(VJnd7q+7 +z@gQZM<@Ki<_gl-5B9!!}oeMzbaWFGu%#e*Gg!jCWu{H!{=9Bl_nWs&zkAoR&zvd@k +zrJkR0#^W#&s8%q;?$10Ee_@b5G;axj0Uvcay-ojfa;Qt?=O$XBo9|HANC&}NF6;iC +zxiB*nT`6y85Wqx{(nrmHVRx*xSV5Cx0wIXG<(K3o_!E7fh8cqQC;FkP;Ut+1+#K>=Q?ryUAY_`3?S(KaS8>Zk^x+ +zL+wP4HaG-#bQh4XsW4n@?9)D(c=(n5c!&nZvEJ1zpf~NA4LX|0Z{^K+D`{gMIHPXy +zN!^PZ^Ul=~5e}o;=$b8cif#(4(GB#)@Pyf5 +z?Hs489^)eI9AJ3$J(crM%?7G+sP~GyNTo!izhN~h4|E3{J*Rkb!HnpjTQ4%UvwseB +z)p--ajzN=@kaP|n0az~|cyEHb1;@!H2}rDkBnbMsvKL_tNmdFAXUtDw-PRw}9fl1_ +zT*G>Z#$XSarD+9kT`YhSuB9NkNpKbOL99le!l_Wcn}4^pi$qgCo2O|vEV(lCw%(s% +zz1V2hZlJBYv~QH5pC(ocXokMub4`~WxEC%wW6&cG$!f2G_AOV8x;*P8m~O4(<_jdM +zy)3Dsu_gIW4tD?es0(4dvc_zo+zLujy^LCi9~DjnZlanntwgKf$Yq(=XuV1NNZVU2 +zA1fq`AX*a5OjrZwp@+r#*fX%7c +zqcg);bP$Zt2lvAci*RQ#XgP?GX6GW!UeVf-Cy@c+lyJH|&6F73myZQI^(f=#mV#I|kQww;YO*x0ts +zjcwc3n{&?d<^A^m)>U;?&HVbVzNfmo<|@O*p4s_@pY!C2)B4KDGv`(xA}u>`sly5pvr-T9gy&Ny$L1zI_`+i*>%5g*+ +zfPO!hww261jfRtyJ&pCNZ>E=H)hK*PoClc;u}L=p4x%%!y6`XmTF*!E-65KYNi +z+@GV-i?GIwu2s?BOYn4Kd*a^3UhbXdf#mJ(`75!fk&gqYUkN#Y-Kf**y&EvBpa6H! +z;v3oWSsp82IxIuQ>bsZSf+}+>Hq#mWz!Cz?;e@lLo-E}onTEwHSE?-+8-P-y=U`M5 +zEeHgle-B%6!3^$d^=ILm+sM?v+M#LcFV%F7@I_@MR#_F!aQ-S}5^x0nd!tp@hw%n< +ztlt*Y9msRCdo|L$qCV-azt8nhE#M4RX_3Yol;rU6eQ#Z38s`~!DSw+3-^UX?E?%yu +z_ic9B7G5cNNzq46T)!mKL&X_=gv5qV??DV4IlxtvZkEi-P>B5)B_1BL@=K{vSu-AJ +zvZ5b^B(wu|is<YO +zOFWW#gM;%DC=}Bx7_!<>_B22O0mNiS@fP_f$cn;_GK-2AdhkwSO)^i+iE@aG592>N +zyG+a}KM#q2pS-s24`w{PftCKTEm*5(4@0;>Nt4LGEoh-{4-)EPgGVRP+z)o<$`|6C +zw=4sFD|-b6O_;85ZH;*1_|L$MM9t1wzcDA=;wS2yCz-3XCmGZn`pvU^{6E8r+nYqB +z_0whp1uxMEfx<{*mK>xmF)L`p*mqJ$IX-eoXqtEcKZ9D>=Xn4E(zP>DiE&v_^%GBJ +zGwoiZ&2P{nQrR~HXfxm1AZS-tS%vlf6^(U5PF8J{a~xcz%ixl9c>>kJ;N1yyR|6o{gJ7z;F73{cr?NBpFBj>#y@bv +z)#}Vcks;B@?_5FAf?4eZ15s|^DPS%TjWKP~{YZYnkWu7QRK$m)=?NLO0VS+2oEry| +zjL)#t(v<4Y&?=g=5(#HqrC`k4DI4Z?bc;Q65Fk(aFq87ppuJkh7b`4ixSt6=v!-P( +z$T4l7K3db4ea;m3Sshg^?oAH4GS`Xj(@H)Sk;3-+U{RzM@UFJ3PJUHgcs(vpjgYq! +zl9aEVoa=Or6iliP<#pV*5X1~jyLRJ95R)j!Mn&NExcu<&RCSzE*^O`Vq7WSWppZ&_ +zO<_>L)2zdZTm_)YdM*P{pL(y5o8+p7ro7oD +zahsp7bk)^x79xHVhskR7%OI*n2mMW`hgLVQKAMOo<_n{12gbVmGQU^Ncr}r7?#e6{ +z9DM6sb^TZA^(Ln|xduSMkFb9H +z-SSw&VoNfiDozBKDNkzlV-gn*=tD*hT5;!2`>KFkMap%s<3Ri>*SyUZDQw}ZtKP&RZv3Ku2&92{4^hdLOZ`-n4dj +zU~hEAZR+XhiN(iBvAqfK6|2X0zf< +zoN57jmN*EA=`|<_=l>I5zp{tD$^Ro)|C`euXX2;N7hHu>TIA6XXD=6*k=hIzM?nmc +zu4EINmfGKZ%CW;(X-lBx(A44QQ-4r0FcLXlp0#*vAW;T{81KV{%OC1~ht_vf`vcM+ +zS+1(S&+gyaaunC4%6rGEx8_f;pXJTz-L@OY@30erIxWtu72!E(^lBj!F-8Z4S +z&W1tKxrDEG0#$|R*WEv{uQA%r#*?V;-(OfGWd)CIndI`HUG~J}s_=9DaX1`3(At@A +zAbqz_nTeTbN|2FzPcc89&sK1sk6&$%2QK0GIs$#KZ(omJL2{ywj`Jw{wnL9& +zz*F(5BbnqrFJ9=M4k$nc`Lp(HbG2g#r=hu~3f^}5TEPTfk!K#wINe2@$=Qir_B +zp8IPMT&CVIIg_W-ElSubC}xe=?~DFW>do$s?(B)Hvq9!_t2eZKazN(;WHwxjztXB* +z8!|T)U!V4)GvNEM6I{b_{5qT97tB>Zma~8d4WIFoV^W74-(V|S?LGcgBi4OS=6_%x +zyY^Lc+f@|5ly?_S{Im77262NPw3Fny1}R>WQjUbM09jjGo9OOg2dvrg0eihreTCu} +za&76Kmv>~ZT&EHVTp$!x_on~o%f^eBzAb0ZkYBX_g_!L#<_WM#x3q1O8w)6s(TJeR +zWdDx&`XmWButA#%(LV^?RJ%VZj}paillWail6uRD(3E#HB>Vi^Mybkn?r!PVa|dxs +z1972+@(Jtp(k9%`b8h^5hHJu#y`ya`3l*4m5Qa_^L~9J*Pqgw+txQRoOjN=T8uj6= +ztbc<%x7%RbUDiP`sCYgio$Iz)l&>}9jNJU`wy3@6?QFO4zr~n@vTPJ9ZPBDqGcm6x +zqjCdvqzgkVsm&>a1!_AUPfO=UVuMD@bYIA( +zq`pd$4?cwQATjnN6;?;(_-HeIPNZ65#wBWH(m2?q&%;VX3Vb7W@el)vowg#>JwL%oH;WdR-GDr4Lt|7c@sCP`ui@oi5 +zh3k<*q>t6Cdpj4PDYyuh*>S#Xrj>Z6$ur*N%k1&xHM&)%yP|qF59mj_-*E$hIwH1E +z^MfAD?fgecM9LL<>UN^YNUZIr!a1Sx`|FbIE%}C8{Z`s55o9DTFqIrRSQ@U5OaUcF +z`(wK@pFv$xK|5&NQ<54e9HjtL{O|7X2Zm=*~2 +zMH;hs`hpz(q09N1q=BjWi3CUAth!vgQeXVX4ly)o#~YA6p-EryPKcpe1V?{%A9iy@ +zE+5>KxY-?EgIg)wCG$-9I*P(YpHe^RcICT1AOKE}Fr!?Ky&e8o>B`>xlx_BOYaDbI +z?~pRJu=X1)Co_kA>eJ6YIEh{{hk=FVwIIY~EsCqz*=DN3@#QJh=YE~cqlTb$7L&Vh +zB!z1K!rLa#uJh!1C=0ndtYGKesme}31-RR-@N@sEwXV3euTg2(dEM+uKV4RTMv=QrgsqTLS84$F +zFtE@Gp;R!iAn5B`RiL96o1{y_tgqQj_3y@lP^Dz(EUz)9W5^yKxW{fD8Dyer-m@CF +zrK}KInQQ99d)3R1X%?ykW +zQypOPFzBu7n=Pp!DXy`VUL(-DBY@QiX=GmO?I~t21Y6@FMFXCPKJ=lr!$}qQp>YRu +zWH4D%^k>FIBdQnd@9`y1MjA?UltmRXgHjD%Wx0-qf&(PrJ)9Ma}FW +zcZmXbmA&M}^T$I|%jrAQC8Izql(l2JB^5X_6FHIji9ERMDX?#M9qXf+oms(co2 +zeI#*6joKd$dXEiKH5}3^5tjwk3BrYmWl5?>EJWXr5e_2v?96hO!I_$lu +z_|NmzLjNhB5ey6Cjacyoyvq;x&YZg?U@;AoGvW^-v_e8-S-2qWlg8|GjL=qkc>$Vv +zB%+deFPJLd{zYxjIj8{3ohXnkXsU05Z-drmO6buYG>A4{ho?3Y{yBH9S*!nD;7$%> +zPhFzW%>{5F^O4od6`JsBynyH8@Ro{Kq^cgN>lW5_455!_l3V-mr%6<3Xol1k^UX?{ +z@q0!5CprW3th(-A#KGjsMBNdzRFU^LrP7f*_n(vRxF7C5V0!~D&_7BtqK>oQ?V@=s&58v=kUilYkg7ZgZZPwoW@2> +zEmV?!nxrhU!hBBv4ACx!DOR-&8u0?fsw!@YDV@>Ly5K!uJ*{-JsT{q)k+$(?Q%i3i +zy|eKR)6vQ{SW-<(PvmiF<>#_|%91)^C;s={z>uV{&Ae;PfiN0J@sKco{6cRRp)P(G +zBdkbh@CUr64pBRi1VO?`fS>H5pbWcp<$Ee4L?waC!_<5VCEmvw<@yG7$##eS!1^pg +zN;3o2{EIcV^Y8q8`~hDJ6sq8SOCT+Qf$mBN~xA_i6B +z?>2mZiInn+Xp9IoRQ6s>oMJ;nkdDcq*tm5@t?!bI6O8ER@E$&lXigMI@o$3SAyYfI +zFb9C)wF);e#gjeWq)xLvZh0ibJ?s6OxmDKEJ32K}+U`2s@IbII>tVetnq_6+Wzoq!2mB*u6ZOkgD +zx<>^Ke8@=&a)rRD@I_BP#43sNSEtj5$>BCm1>dcbC0KrC`~70|00;@MWNiFTUS|F5 +zMTBr;y#@Kib3 +zV}?C~je%5WbnauZMLz{ZKa!1Tunkt$B0hBVoQMq%Q-C86_3ww!eo?#Wk8R`sRxvacR57>|Gp*DMal8l2hd}zN6NpM0 +zY7|kVw$Fj_NVZWptr5#&2bKQhJc92?%|QM|$`*y}LOKkmaR5rM8aN3MGw6}trK-^s +zGSILqvY#w%WeCB{+lWLKGcT}kcTIt&i#JLMyXSU(7xxYwiR;%-s%)i9!a$-*_>fla +zPf&AD4#t*TGJ(@@#-J^?XyR_hn(N)xN9AbFSv@|vW+7uFClh~do}$mpckD?)-rht; +zWwds>o$14GO6szB8YO-_6PSz=_`!NB+XD97M|I5w0=d(D{KjV+1Kz9{=H;Ij#+r`% +zUB~Y|u*%H2Z2q +zdrHX5dIGenhkZ&Y(*(H_V@u+}n`cO_z!_U1=(gujd)~=9(c2l54EuEs@)Q3ms93tD +zmrd-msQm5hC%A$`Qd03CJaohk1%MRg<|u$uBv5*7fhjk-PStx|HZmmLW2vWlPag28 +z1o6mKvKdi|W7ho^=$hn_gW>`PvGN6n$tngB)NGShjArs$2aGZMpN^5A#EX|6Qt{1F +z^eI=q@Gz9nN;}V5W}qa%qar`ElmE^!N-p}b-X%)Ycn1_Rh*k37R3Mv)&mt<`la=wvCY!((+l$!1F$Ryouf#+;Lst{Zr +z_!adRY*dR!r>w!b!c)6==&F~uYpmI&5k07EeBh62(X*08mx7_XKE%mz4$<174v{XWQmKRd`tRw3nh?C%P6#EF>+!&qLZDJr^w +zuk5)RmT+TO1KX{pbm!@Q9n_%pA8qkY#^c92LXg6w%K9Uwfz~V1H71;M{MCk!c!QTt +zv1mGX>2+LtJjf^6wd4Be!6amp9n{?sf!W<)Qq&?GA>Z7%0Du;;sZuzjQjSP$GIa(4 +zDn?xPEyZp!^vr +z**7I10(pF2EB~2<6pUNSqz$h$YKDpmw{Fmso9LuYVag~-4RLRoq!f&6il$NDX)rID +zg+2@!x!}Ge6fs#5=qy@^d88AYv})9b2t$8*#8s(*LHO@Y_J;%;M5 +zarUt1?QX0byg0XU)MuZPcim54wAmpdLr5UkoGr`$d-9%SLQR~ANLp%<;T+k$2KLXt +z3#9gpPi%DB2#FfenV-Dxkh>Em&PTF9T +zc^kvE0iN47I8=7E1M5cXQY0@b8Y$eG7x(`Wl +zxbsp61Q|18G#k0wDc1&J;Y0V=h8J`251%QcDl&(FlPjIE#^>U_ +zr!pla^`*V}3_rXJ5|fbdI)4x_L&yCj?v#Q?P4T?;rv3`~Wq6>bsLZ0J`nws`$|PeY +zM=XWV%!_A@xN&!MKjRCdt$?tYca(^&EY2>jHGzQSi8mB+w?hV6rN4|=3Mqc<*Yp*N +zaN};fSWO+3PM_zOlhG=h>Lr+l@9m-&qj*OFAE5HQ%%P$xvY{NxNbLu{mNQ2!W=K~T +zHCK+jX)`AHXFgM&!Bb{TyUZfm)qK*Sem$m|2o-&mL?u{Z*By^e+{~RE_gUr0MnOT! +zon*JbJmhrCu63g%Fa7EVKBI9)79rMn*IXbyzal#xvCA~=BB9RMkhss?ogt5UbaB!P +z^`TE@0JhjoKnc90wY{LUYNVJctx)PiUcy|sJSGp6xM!@E2c;|-c}jp19e(kAYL;Uf +z@bnAEg=Uz(k-Yla37|}BR(zvTx{pQ5U_QT|c3%P7HAB0mE!9;@;7uMDCi<}Kt%TlH +zn*Cx5@T~KkZ}#kFkZ%!aE-o1Su=k5X9*2!!-ozS)+OmgwhirMe-gN(!fru1r2`jX= +zYGk~;NC9Jm%}m+`lXu~J2iMFQvBBnpDpU!vW6j^`!3Hx)4HIb7|LXNrs242H{LB1f +z<8)G~oQ`YqsKRe2v-%X(brOX0mg=lWjKWmPO12oAqsZA)L231OWnMRuvq@IJ%@=!*d4{v~IvqK&s?HaG~I?ibV9ls7Qb +zDs-mY&2u55%7Gx&3bD*aIEYFYga%gRRdD9i!oi8jmx~JhEdX58%Gj|tS +zB)xI)Cu1~&690Geu2?bl^r`|>#DW8DFyae(T@5-|u;Dtg54fp!j=zcjE~%)2$G%BP +zLaFBph{M_J5@4Nqz|$=BD#60`w?Bur%k_zwoL7>zwfYi4xmyeFP^C^pTmhv7eGN~! +zP8tF6Hci_vasHNCphaWgN{m6=_2=z<4`T>ttZxh{juw`DERBi3y0Z)4&R2ffWlc?t +zQbwl)Ro(T>BOB~yEHy@)Tf6S#&bHlDoULm30*5<5=C%XAAC(kBkHD{v#z)Fbt5LNk +zK+m3MNktn7<%#?TbSE3Lts@_G8Ykow%5g=YQ)lc}{8`~*7SnC?N59<;4g*|;`oK@N +zU06*2o-BHEMyZ6Q`f2B!=?%IJWOJxNQ0>iB$%S3ENny^D6s*W^_zBiHGJASSf& +zpH=bzseS^iDu7ew)=5x(AF|1t+3vJ%K<#;Ag7tBuDul%WrEfq627NobMY9lorg!ga|ym +zqb|-HhkCqumA#^*_8H@*Ev4CeUZvxv&mX3?3O+DlJu*7mNT>E})Ggrj+Gt>0P66#D +zX#>Z+y*kUW1e-`BV79Yo{#wl2c}y+@^zQ0Abto+k(CeNu$iqwBN(ymQ>+BG=v!Kno +zd;K>b)tUzdP+af@8G=6{fGvQ!7V*9mcR4f +z5`_9>D(r>T866B7MU7nT$e>%`-_FV8;8&yz7i=Rf>2cl6VuhD!oe28=O*p(w9__rg +za3UB@bdZAt+c3ni%$PR<)dK+#_Xhlk1-ssH_O3QZUdnO^J}WOo2>^49)uSA)Ir|>n +z^QE<*aDi;%r@_}Z^W_tp&VPF9g!^2o`4!oYSA3~9qNi%CdsCS$IVvGElXKBlH+CY4 +zJ-y{xUWx2bdPLmQCTU*_7uFrSdNVH-N9nDj>>nJ$s)D_7ZgEi$jC +zmM%sjQ*y_k`>jpSZ^?m`2~WXq4R_|32q6gh%B~0>s29IN`-iHMiTnLToZ=H|YUxczMu>;;jOTTDIgJ;pq9wKBU3kSw +z5BCW|)DJPax8&n2m?eIuI#h9BW`OAw&JIvtH|J5!?Vnn*ijr_-?EVW#E@K_k**R5< +zg|mI{P$HpkMe{w@hHY%XUUv$%F8iq;&X#oxGDwXpPt;&q0 +zL6*P`Whppi#@E!E*DT-LYZhl2tRgE-y{dAZ0j3u~lU!YI8i#;5#<1b^+E&UYw4LGb +zSlL3R_&BdSRJndAE5yWwp95$47?bdqI3&e7N)-sNab*$KlBD#X==Z=;dQ5Avz}o-- +zPf`yZ6JW2|H~+rKk!Fa6Ig)9(nx<{HbWU6KRVq~_K~Steb>Rb&qK)6z%k2mhG_4Ww +zgIQDc@!OV7QfK){6vc@ScXjo7F>HIcuU>JUTaEn9ZJvOBSv6R%O98((=DDZ%Hh9vY +z@YZU;l&%U)75j2B`HMXJ(yilxI044E@gdbtdnRid>LoimVb2Wp`a-Civt-9Z(QQey +zqbr!-L%m>qud{#pOg0x2k!Tn;?4w{k-OY#;_OO({O3e^Qa`|$EN>SGWZ@1HilE +z#-{6b@*H*IFJsF{_{zwY!@89PrrTe2V%UG^_cae4obRma?1VR`l;>d~=wm +zj)ti_0W(Lt&r0!XayjeVM$L?(Sb%VKM6z;Z!;Y0mI^U_F=PG_b3k(Xj5CEw0m(^t+ +zR>Dl0Fu);xdq5@-eV@+Tb4#`G>R@f{mo83K?xS{E#9A+F-y?qRpO}u&7wwX0qcdR* +zpw*XpNz{N3u8+nbxKv^!`mR+I1#3I8U5}3H17)F}UdqC1?~; +z+Ky9i}=JlyO?Cl_%5){2_F`$2IT<4F>sri=Q +z?>MM;=8v6tt!^iq;-t%2zgRPbbE`A7auChO_EgbxlBi`FEC&#ioM3TMOahIuY4qYT +zt}1)@sG$qhdK_N9Fa7nvsKK8M}w&xrm>YL|%mRaE)9+Gb;NlOV&_vxnB>G85!% +zH>^g1^1Lx1g2I7!7w4L!kh)1>Cx(~7GM3zet3jO6 +zb6xd~NkD2!5X&#M#a#$`M%fPXC7Puuo>#M1mUN`M1)I&Zg_c*Yxs^UgTomq9bXIoK +zJW`NaP!2&ON9T!!DYbDj`TEQp{I +zYamE>uKpNMEbyQs3?MFs(VniQY=Tf=5?-VrO5ocY$HLH(&C43-`UGGsY#?O}1vX&2 +zM2uEo(qJIFIf#E;97u0!sRS{=SemA`FKpH@B>lNq`~eX9hH$W4#>{2EAnjqmar!85 +zR!r@03^L41RjjT57mL1@Wj{7Iz)WvDWa +zqA<Db(qCTj(U@*K%h2LQn=>-#1 +zjUCN`Xh0N~iKKBF=h`*=CcYY5rmZ5FY3!lC4U6d_W~T|vg?oydyVQ6skdu?Rt>)yPyI1LZRuSUDxeG%u1uRO#rL@a{!c{p!yIfAtGv4SKh>xw +z;!k(n!v8GsccRrj2llqT0yI0SGuXiNiH9g0V3Ld@L?h+83K)?id~lKmNTm}wGWOB< +z5K;bTTsCEx*ve(z9_XL5zOVV0VoM?TKNRX&MhiS?C@Df-V)P;g=@E)A!O1if_WcA1 +z4JD~^;*Yb3Q)`miSb+L?uRBOmB1N!dT>~NscFGU4)Q|&0>;F?#7(t!AelIN$h$cu0 +ztX|>>;s{0~k(NOF-U+H+L{D67FwtS-dq8$k{HanTrZvd{%TU)%_5R=Y>r8vrFM3ZV +zv(y?{N!7a-zJQvP$m}AX$`UVj*uUIxs7dHvvLb*=fR$mHzW}EKIk$ +z0*F#lXNucoAMT4)Cw=08T}d35NqlC6I*O9gf0AoOSWU8M_%`OJb+JI&KWA|Faqz;p +zTk~W$bLbvUr1#|YNxHE9Yf-$C6V^$Knx@Al8@AbHv(IH?5mwRmY@mA^Zcpg%B(X<_ +zS|iLLX`X8!>IxE%R7EnqMd%gE7Z^PlQB^)lw&c%Bc8RtAe{#_v+5hM5vI-#a%6gKS0{%xYo>Zt +zuX)DwEO6H7s;(?lv`ULI_N^25q4NzEw-`UbKD9&&I6P`c{ptSPY`itbT{K4?(2{v8{(7tZ0(LyK|S_>ht=(h`7aTE7&)T^&F+)$4VSg +zzV1j-KG>j*u43AX{%KwgS7>dlTkFWO4skSY*cT_foiu*^@`a^j#I3w?FvXSzn`?A9 +zazJ9cX?guqstrEFT1`xoyJ(|v9eAodo?Td@dC8XHFKPl~v7TG>hwk$1=xAeFn6gqT +zLk{?N4`3FOz^!M~Ix7KJz9Xyng?Fi3G`q*Bt)W&_7Rr0`I9c>#>v9#00sQbU{D9@F +zgJZA2+JUCStCQB@No%1+$3_#St7-q{fow9sI7)F4^Du@^i0Y97!prhoSsv16m(z51 +zw6V0554$-KD^z2~dA?!M)>e~?MjxSVkNt>%)T4V?Y}3D)(=d+t#!Z_%_B}lK$(tOV +zr%*V}5;E6?T7V)$=~g)LFF%|v>y-JMi5bl^!yQ*ZxmdMm+8j{@4B^G#XPdU^_7S7@ +zcYCev=ex}331b@U)>>_AbIJwTuK#_U@%pSI=QwrLo1FIW`caT5zqO?&Hl*Ih;`~~v +zYM(5DzTV>LW!pxujF3J#^m3>WakOR!JSqw&Vn7U`e(wE_`E8B0OZBkeG6MvsMaa*D +z5w&sP*C9XlQ0r&3&p3<;Qc!kiPm%tzEB>~QNI*?J%JKwZlOp+Srwzp&b$SghLQ}I* +zb#S(8FOdxY{gt@zoVtcg>K=Z7-i=N&sKGF44I9AP>X>+G?I+141qj!r%MQ`~xc}y; +zbM0?t;$SDWdKi#lM2ajxFtx*aNahzQSPs?Q!Nr9+%dR(VXx|qKE~E&5`%CF57>XN= +z!fqk{li@=5_cgKaI3nuA;`3~b+!Y;=j2^~9DTZ|C)1Jk+InF>vP)`(Ok_*C3jg%)D +zO=uq#_3(M{&I`sR?=?)S9l_hG$QRXQd{eR$T6Tp}H;`?-(w%$ou~S_Cch>Z`Jps!) +zsdWVJilQxALYgrtiw7F*gM&BEqAc}Y>HrJheN)tburxL +zE5}&;5ndpSUSdwv=M?qa!N%Lddmb}WF#o;yQ{Qaa$rZ%^%(7kH$5CvQT;i9-L4JBV +zFiMjC9ZA90ln&hLIUn~g`ld!xe7Ov1YOwNt)TG`(ZQ0bTx4R@B>j(~%mVj4Y*d3|a +z!8E*AWwf7R{C1Ny>!&N$;*)%K3utSVza0Yp+Af$UirvQ9QgcRTWi8W0{$yI>T&s54 +zsciFM&yk~%^xe3?3w)_l*uNU5s-qpns`73RO=iY_aBVFLzq0KwLwj>)B5R}CZ58?0 +z`Z)QCLglnBkU!1WRud(x`rT$HsJh +zfpr9WAtwy;amrT-P(ZwB><4QQhQR1h=){#a +zzqJjFG3i&*)yRK{`j|{JT$yg1XnvLiy(@6N6tKK#S$AQ-1(aDA>mx1=H#DYB~2aH)xeKml(U=31C%+*H_CImeU%s(R-?q^|YV2uFP?q +zVWy8`BBS#!nY|LG?h@z6Z|=eH83fRJUOt;emnZe#26nAm*jsJ_i@CY*m?2E;Jy9bI +z{rKpZlA>d2xo?xT+X5SeQNsmo)g_OJ81oE*@+P0q-%AY1F&B86ou5(Uy_V}(7Cvk= +z+Izt3$dAn=NapfKzx$Q9E2wZxg=;Z{{=`wV#lTWh5Q`OV_D5vqLEmWvNet--4S%<) +zxV+n(+2&}@0gd@M&HVd#Lcg}A}5=C_TdkKca#7KQV> +zwt6a+6~ph!XTR~KroHX19$BN$1u$H)y`lz0-qjilFbc&pB$Ri`#Z6|BzbnTFnkX;D +zI95Nm#po+fA76&?Z$j7pnLpj>Q<4X?zC8S4dBVEp>D~Qhf~k$9<$00om-f=eBT7S- +zpcju96@M9BQR^jknFlma;8treYF2Rt(jArDl0er3N +zoQ+LwmhLE499@h+uG-y7#kLLc=@!J352)TK;cGJZO^2_fti8)JcM1Kp!_FU6V3lU1~Sva);zKPqq +zSL;l)09^$(J7O-_w5C47NbjJzzwY3AldFQsVyEj+IGY|pj>B-eJ=3AUf2pG>i`H_Zy;NPSguOYG!BaG +z_j>?~C4@O|-E4Ixue+0vy3}SJ%?zF9{%S4Xfm9;pU7dih4~t=-qV@uTu3lmP;+uhu +zJdLq@iHp1~D&i~#WaTfICzFeHu6PzZ?l5~e>%RgP5rNyG_Iis`KK%#%odA!cVic%x +zQ0NK11Eff*~@s~4g+ +zGltMgSnU~g*c+H%clPVu{6zT3@z_(h1HJJosTH>EuR4EXB$-xA%07^e%L}x@Eou_= +zgH&8J2vIFx3O^^dEW!Jh@cwQ2sih%(X{|SYHN{YzY&}(zcmuQ(Cn>xi$yX3aq#6oh +z7*4*&uG=}F7)Q8&_5HYFmUS7w>XVe{6%ca?e3M^_-$u{?YcK?@S!ym%|j= +zzqyBr563wk^CY(wec{;!6YUY{l;XyudsA8I*`z0HXKl*XbtV4MatmhucA@_V*UkVw_EMORxpptaHvh}FNiGVD?CN7Xz2G))vIZ&}@ +z4(k_!xy}OTMv5YYHOnMm{oO&>%Zmfe>tHPCYm8jr={Cn=Dflm=cH9$xUw3_tq&l_v +z*D+c)@F$`WUQW^O47~8I4DE|^Cb458p_XSnp%$GYws!_9Ru!B<463T_fT{G+waj6C +z8TtAT$pr_F+%>;(ZG1qM{e%bpl9;OxLTOnSX%!CEDePEAdM_Y+(ZZ2iKp?F({7w14!IdpRyR|4|eG&>iWN3}Z-}lcLaLR_UAh^unb65fz +z?G2hpL~2C$j0Tnsic&YpGah|P@(sF5wF6ER( +z<>WinpUO)s37 +zr7RmA6mc1(;4z$K{jmnw5pfm?AKd;TKX(; +z0mQ1!U?04(!s!N13X>oq^@Ki?E!)nixvp}{6+0D*9ld{<7R`U;PRvT};+?uoeF>QU +z+UX9AY2cD5=2G6sJX^$(Ck@_H&TM$~f0t +zpBO5=USxAhZxiIi)J0qV%^vl-Z115f|tygZpwm)YU~=Y}Z$mA-+<^ZBAZ +zA}cKuwyCWJYO675dPz}K)NfZ+0M?AT-8UbP)Z1DGwjS)2TS{W;>+uh@DAXBe>OuLZ +zn!A#CI^L`S0GqbQ2D2rcJRYgPRUP!Qq(_t_;2S~-XRijyBms58k|l+?odc&GkMIqi +zR`w_V22*~6J?KLF>Fj&$CBk<2F#AyGKKM%suC~oW^N|>N5k#tMnRPDD_G1SV>_TkO9 +z+I^_6CnVd5F!ZhjuET!p{{&&hQ2f~Uw@ZDV@4?R%=U)GHBBkw*$mSl5L;#mN*ACl> +zPu_9weMY+;m~z2E0^&0LJc8qf5_79eLcjpiUgn-L`2QID#u!neX4}CT+qP}nwr$(C +zZQHhO&z!Ms+rHvgAMRFp+o-?$bp);#s(YxCnQcsMM^2# +z&|ri7Ki7i^yDybw$9P&)woGnQqH=WssQfr&3 +z_5TZ?|6W|cb^gFK@tt*Z?d*)&!DKJ@?=8S47|~iKJB^d;PXJgoU>8K$Gn`E2 +zQE=q`6s-S`!4fq@p()Fv&xcom)4Ga;=bx!kpFIQ|n)|#1c1WR%JyGE)CjbescF2B- +z;?T7M96B2;e(B#6dV%W6^32sHt(1Q$kNq5J3R7|xxJ`o-TO|IoqH!zc%jv+G20RDS +zqs2)qRzeJ>W-awe`?kGcz)@+)(a=Gz#yN%j$L@R%TV-DRl2-$d6A54rWJn8>`!ur@ +zGA9os6$0Qa@a!Lhjx7qUJh2-Ol$b7kj)?Qzwc*pij7-7>U}rvO)I~lQ6@>qHK&BcFVb;?*QQgXB#z`^V? +zZCUl66EAyvUpmgvR0)1mAa_rs~OO)1#kYm +zx#to`OcX9jNlLjulHD;TKP`kHnJcmfu+nAwpW1r%wX(I(kXq)++@K&U=u#Ru>Zy81 +zv(n`Q7-~5-#Jy*6{`jL^%q5w-dtG&IDn$p$3e +zF*BxeTe?u5xU?lp3OWzF9vco_A+EsBx)du?gzQ`XJR0=A@vyCt87kp4@N}$6$av^B +z>``k{(N*BnwnTK^f)s6c&jE$UC`%enrTkG*M${@Ho}r`lUsES(B|^heL*7(~w7CqI +zsXTAZS+-HsYO{%0i;Z1tCIsZf04jclnBzdx8k5>6m6X^jwD{bVlsuqJ5&maTWg&5J +zw8ANon3PQ!P6)3#B)Jx(<9HE!^&Lx0OZC&LB&H_xm9Shujc$!iYsP6=YgM*BMKrv0 +zm+0!3iVgGa@>;Z!qBIi#iDhgUyVOVE4TUnwq!G#b?`$BtjvILIZQJ+3GL3OjuVK&F +zbj-h_LYWvA>B#e-ZhCQ;SR~8 +zl-*&P^>t4yj3qlKLFSA*D6KVb~*uT4^!`L114%nA!{ +zv4MBDGK)wWD{nG7o~5mKas@4ig3d4QWX-z|JzKB)XRBld{Lc$?uQJGCFZaFQ+EQYI +zq{)@@7#M-oL_2hw;COem3`}G$){;UTQqv&HG$dNqa@Lhmi0LyaOStjHXL}qfx6TYF +zED^aTu;mM?_5x6~@oXVYkyTp(=;cEXxn=y1#o0N+TFg!X5FCM02fi@?f_8*`R1yIxFTf7UjWQedLN;Cz$BxdW0O?FLxbNp +z^4^_4Q2>zC{YDzXmHbGN4=mZ`` +z`)1olUHklrCE`9+T5YNXHdhaEk!KHI_>3}HJ|WvUc<(3&rlb4(pa^-jI|@OX=?A=M +z$jkq}4vY%~ux9gfuzW*QD20)!(+Anwc;{Uk?Gs507dzT%~Xmg6H}7C +z)85;4==K|wnI>B6^EUOwMsq-9z$1+V{ge=fy1qlwqShQTH5SV%zWRz(N)U6+@R_rlvdi|Tm1*II6<{E$!vrPG8OU*_NyI%YO)R!hgMdy^Z +zOnakt3jIj3^(}p3)jc=S=J7OK=0fclxAG~ifE2o)T$vyK-qnqNV+3BJFwEYQJDO33I7Dnm +zT0?!*r602wM;>-ksT#+w9$Z9tuh;GJk+)qNAn@FK`pAQQ>Yl#{v_rb+ +z$2;l9Dk|P&dt4G+L0OyFfv&aP9fDaj%p8JwVw=4PRmJlwhLV5e3>1l8*Tsq$Z^;0q +z6pmD$V(&pjMeDPJTtr7_@QD7#MZ6`A+oNYDCIN(n!oI}wKu^c7Ra>}k1&&1{DJOy<;s5CyF6|6Ntymrakd-A1k +znlU?)X3*;lCZbk+Am&<8=4?R5#E1KYc$n}|Cgq}DIB0-+2;>L}`?t-vwc9cyUj7D= +zi0EyRsfAlgBHu7snX-=jlyLPaV4+(u(=)Hjp8yoq)z}~={d>auj=?B7S4VJ2rCF!u +z$}Wbj6TpgPP)znQ9xCnEnQE@*R0R@_M;Q}$F!kUCp76o&fPdP%=&?SHYiqd69igsK +zW|i`8BDb!CipdY+X4oPhTgmh2fT2*#Y9xGo=~`UUftk>{+h#fGj?hw|EaW +z8CSL^_AteOSPoDO`fxdN2AVfD+ljGrB8Ifw4(H|v3Ke0c;ca{9zJ}@&vbA3W?O^87 +zdj#d;F2_R!*@#f9FRS&eGzV*a02A}zPcZf&91aTg+Yfp(!7H&eziy50cK^#1O!Ovg +z+1q$m`#~OVIi-?!^=3lQ!Qs~BzFgo&+o8`e;lm;z@ke{aOHw7M*fRl=OfiRezDob* +z&*H;R+9eb#6;-h^3uG@JC2?!J)$zcVtW(Y_wDy11TglQ%-cSv#!W +z%}0prac>k}5$RNb7p6MjZzw!0jXU +z4T!bf)@hd-Uyx1CYG7&K=`A-_MqdWoAn=RHhIeZ3Zn)^aS)w2xqXoFu*MTQ!tkyK& +zfbeUpeAL4fr$EBxssG9JYGJG&6$J6WhG{<5xM)WvO5G( +z+t+i;w~ozA*s(B&tzfxbSG7@KqIdmA2yO>tzuoCoO8u8QW90Q+{iBRU-(Pq-zd^bD +ze7)ZXyZ=c7gkAA*4E+ZHzycBgfc$?$0>o}kYwm1gt)dJ80K8wSEA^j4#r+R}7aB4^ +zi>i&?1uOE;j-Eqm)wPlYkj-jZh`3sPt96@>%3QNVQhWqlM9c7B>qRIfzpvOF`TR7; +zDw!z$i0eZqT)xv834YgF@`Y!p9n)*{%TuecNt}mt*S>K%aS$iLfh|Au<5Q;7eecrZ +zvC{;g`r!oKPVjq-1P6hq7$VdmcPBC`{QTQk87Wd+{_&3pnPNoO=o-5g%y)~8WTP`* +zyUw1F8C-R-(i)qFB${r%wDc$TP1)*JVoJ1L7+oG +zg`M(aa_Mnh7jRm|8uK++aAL58ajZ_zrffnv%3KDSP6@>!(@A*a{6JDT)^~1=IxkF@ +z-3A=gJOP|eJ}Lhc!0sQ^AF+Ixh#jPu0qK|Agxe8BDAr04I>6Tm;S$wip~Yiq6ymj5 +z15~0{17$WoWHEToCl%)_Vq?CFvK);eqv&xH +z>VSC9xJ@P#0@)^fxJb?$=jq^mnp#;%f2}^NYdF%e`aeKQVScdvpB}Au@seK@*C_l5>6PG5h+M+tQXRdK@Z?$qlR> +z#s)KP=KhTmmj+s`gNuO7Q%f9DUkg=y +zEt+|nHQN|@VP1CN>p2V;hj4Ebz_^V(ystyM-yZgNn*+yV+z;;XV(S~x-q3=gf7gOb +zs2|WhK?}rKL)-Kt1gs$WR-S9Z!<(1F=W-(3DUUZZz#` +zx@30x!qT|Ofu;7rNOZ-Uu7pnO@E_J!V=4XH)rU6RUScia6O=ejx-OmLyzye1j?fyf +zgfK-I#=z^BpWn1BLLFJb(~LpVmkf +z@G`Ud141nIx?M8M4kHNv?vUNs(!xT$k+uD&1mn~CwhRAZaLcTC=rpe{7g#!<7>AsR +zcMC_TVq{9}f+mjy+7izLic!Xbktm6sMC#&^$-A7O32VBHSc<1#|M>XfdTRgb0WqpE +zRd^8=W2|C!0WK#7c7lnu3}VSxf;R20S;%~x&p8#Pu}Lifuv?ap)67)j0>Th1ps(^p +z5VEm%ox1n$_%rog{tY`=Fa|4+A^av%}Nlq@UcPqf?hmfC6^SEB_uU@P}qlkUg8k9 +zA~>FT7+15No +zWmra-H^m;-SdO?;uaa5=gVR=21etrB?XzUh5RXrJHD79!KzUKVhj)c!2gu0dM5OOW +zocBla10i`%T&P<04>4{SZp@ocUi0m%GE +z<@RZxt~oe3k|GA^a~bRT7!zPgcEi5Xm|oOi3yB*?g;n1_DSk^R=4zFIt}%dm^esSV +z@wNhX611l9MYkA#XJ)QtmwDw$+LKeIJ&Jg$)7Jn*GRY*U +zR7ktN{!J0}*^U3=8#8amnWM`&x#CW1e1MaWmxVbyFmi;Vrk`^i92h^?jaSY=6J4dJ +z7vKnF)JIdfa7+)_ie+m%vM_GoO2YTZJjF;x7#RQQ;U2W5sdTj4dI1y7?VR_OF}m<# +zK78w?^ncb+aQS{RqJ(O47bn|bgj6zS)-=wZQDLxj)4Eo`1qz!hFNfI=$7O^yx`o;x +zL#A%1>NlGCS#YcDvu6FAGN6ZHhxxtVF3G5}PDe-=!ha{KAM~IX80l&zX7kCHGV|$# +zq#qI%Lq5Hc-*JYV)RH0peL*1=O&EOW1L9p|lO6K@;6z?)v9lW+Z`?4Z+`Ons3s|Bl +zi|_OSD_%K4t<%>5S}DM(HoaVS=&JPCG{Wz`Mh*r84Tj5jJqD1>8r@I&+afIkQX(J1 +zj+%lhQh^L}+e&rG9%u}e@#9bT4oE^mv>pG@PeB2Pr3eZ#@OVWL(%qtf_MpHVLA5Y4 +zr8-i1=1HJ-I|UbL8X##^$`}rWE00^2SoUvlKZY4HHFO+xu%lVFDjDY3;a;ul%Udm)La!EI)&@{*)CI{ulBBhv@UWyk)6YxD^bl=S9^y8rl`-G+0i-5A1D~9O166-3xKKui_-Zb7n5IBvfh58d-Vj$sWg3i# +zZNj-ul8hLZ8Q*KrTY{**)KsD%l9~9zf(IgK5`Q7U-f_^%%(x2ni4!S5lb8&34SSUQ +zmZ5c57EA$moI!7oMf7eXfTe*#%-(2^s*N*=Z^r@2%;V%0Ca#>tMc5tAPH!&5Je@$y +z-W;?LW3lr2Oz@Tp0I-!|DL*TpuRNyiQ=+I5nFF^Z1o;Y_I*~!!?8Cu55Zfo%xTEreyjYTH25i#px +zllr;X5Lv_uAf%K=|E}&Jw37>_VEowKfSmB~klydBSOd{uo)0gFbZ;l*>mXGL7?e9;n-e6(0fu|a=!nnkeE +zw^l*gUPP2VDh`TNg`;=yGG2gET;2IGjwCEd8GyMgj(!^1BkPzTjT8UL5Iy9cYb%FI +zED>NLH}I#$f0pK^)Xb4>+=l|^vv>-;RL!6S8O3jKWBWzao54)MUQnsSGI^gj{yBN( +zkV^XuNm!Tqjp&V8CqCcML}(Ia1Fl!df5MKM-XTin!iH7<0a~hi2vo8jUd2275`{x% +zEOfGh8jwJPW~3)pQ@n6w)m|WnAbzyPGh+S>6{AZ;;aNKJ +zf*Drm41~^*PqD!eiKdb{T(?EViXZ9$S1|*O07a4~fi*xgPhuf`tet0?kgUzUI(NcI +zBCIoM;s`{#EoJ~!Q}B*xa(8y&#@0chr=Vt=s7H(c-I=dM(|fy5fIQ3?k+$rI9DWYL +z@^!Q^B_~(QTFY(>lFKPiV5;273riRYX@kLyf_TgD>jO(woI2yEPkF__BzK)Phd+I? +zrueX8+Kz(!!!{xC`(`HJed{JIt+(I^HA4t@>i7zEXzf(XxZMt6 +zkcqnGDOy*RMs&oW*SE_gZEA3^4*eHJvu&TV4k>{F;*YfKFt4-Vn8V+Z%yY)RnqDnw +zEx$#eq{pg+G)B}O|M$#;QyWBOoc4oZY+C!$7;SKIUkg6hsMQO*UkD=#X_Iuw59?DCp_u23tMcU!^TnHLp#l@U4)#%?@sU&UEeQqJV) +zYFI9o66ArY%wq`<&V7Of{2z*hre=V-3_iPOn5t=Z3e}c>)&;UMKRl?~jg;IdR+6FM +z8tqC;v#?$=bD?$@?W!tuw905pHXd%WPiw5~By>u&`&u?Ko1%fbb`vExwwj%nJ{i?# +z+O6RFY +z|C&VH9;62JS}^@%?_Io$UvKT8>QRL3f!Ep5fDnG_u3=PC0&24+4OPRth~BC +zk#7s^k3K$HTXQjgq-$;N(TbYRYRM4HCc1z%WzO88kUoJ(MjNGcQU!SBYr0&%q8icZ +zS$FC0$+%-u!RkF>o)l=JT`JmSu6+WH=3g8=Pg`IS_n;|du%*CmqVG*DOkFR?iYLPy +zZ42M7VY!(pkhu~o9Jn#nsv#GyRGE9GPiLE)AjE1z4P={{*c7*R@O|cWm%RnS)>NZZQzpk;H+wC6)vuRqzB;3sUjGWIob!$IRC2CNe{QMIWI+ +zC__Tt(}InnX;aN^>ts>CTdnV^i+t=&!iugCU^1VtN3~~TT(a-5G)Kc=r4>F@?X`Vo~1@$?9l4Y620+0F{y-GNY3M}g4B{!}BNLl_ss +zri_##DeG56`>Q{nJga%DI*D{wTM%*9BZOqrA(CPTL$iS65Ka1CtYySz<=SvJr#wIV +zJlW#V1VN~A0U3Q1lLA07*t6tbtc@YVM(Xf4DO)P*{c8{irY-%WhEr))?7+QMY0_-g +zZxq|sGmc7&^?2UlAefI_4}+gTDm~1$z}ILhT7=&gVPg{u1~3D#I(Mn2-*}IbgdrOW +z^A!&c3ZbwX0U7F2PL}u3-sj=I=y(pYP5t5;REnnhYmqs()Y&(-jIoUcS8b8m#qxOq +za_rPmSk^f7pP-Ry%|Q!7ZDnc|8WQwiG^Hje*8mJA5p#JI3C)-C)e?a9Sy`Cp$Uo+# +zIDY)oPI1O3OXD`MN)XGy85%{mF42ogec@S*6sZrMd^=zyP#`whdXES!@u$7}#)m3xe^qsixJ|iz77w08#zhhJV`HEMr&n-kZjhf?*?ts=;r> +z>zOUnj<~K$(2FSH1cVMfKsgIFn*Ae|)qZ5hKtliedOAZA*&L0nYW({ghRfKQG(*TS +zI=#qfPOBFjKKH!hcsa}*+hm3c%Ehm2+rVqJM3tS#s>Ovs5h!V-k?W+1ZgV?!iZUsi +z=6zRx>_DBWgP?3n@46O1Ql=763R%Jk#I$i&xzjN05V=^}E~?W<1ZDqM2K9lNR%0~BMGIYs=>Dz-tY5r@kvO{V8u +z3)B_4X9rN008$GDLtFb!z{K+p1d1y6W`(h6p7R=mS+06I6GE0I$~ix1x0>b0ERjo3 +z;n{}gVRm>+9(iv1h534-$?$}61C^XTlDNVukY$xxf?;Yd5$aOA2sPYCTmA_iyw+!i +z{{bol&ssMKxg{`uW4)L{;-eTB#R}3Fs__jf9M4*3)-;_a%G(GVkxg6q<-ki$vCs6E +ze=D(7!b%&yMcdoaz#ghZQAeMpB}NdNF!hp>Q>x~~@rhQZt}XXFs{Iiv7!Nw_&^(5- +zU1kf`a{(23UQEE`J3t&=L)VQYC-47 +zAPie76iOQg&%xR$;Z->=|AvD`ktm(^OlBZn=g0|67wUkN;E7tn1MJ~t`LnIhiGj=2 +zVCt+UQrp6O#?qbh#9WlFsS$GX>=M6iLbX=)ZoONS@vn5Q6LfEuw(pT=zY1G(h6#?B +z367OeD;xmnGD%XNq{XGf4xx41cxQpcijSf9Qyo;QX$rsk2u%FLW^ub`JUJf)+YNQ@ +zomD2|TnQmVkLPh&IL1>IXo8%wgNSpr$kEIKd*tKv!;`r)D61oYA~em9u27qK!@j8w +zao*#5dI?z)Uy(o6FE$Hvugu+!K(^SI!b7+)?BKw0Bq#w+m~=1!6;4G}!S6Wl1i|J) +z9j^&xAaADaXe) +zD9O@pSz}($E&0FX`A@ipFSkZOtDX!3?t3(?9kYIz@;h +z86+Sr(9tzQ;I|IuT`@mfqU0~xAb`0X-w#S4<9_apj>R~kMG;JNZdzGD!t9cLY+>3I +zr__4bLtrz9BcY4%nGiBL@b@1i#shSqx^l&U1Y_B`j*=4`0OI13TgF}PkZC3KO(M%z{0rH&8qL(t4 +zJdJK@CeUlCW-8T}Nu5a73mZTaMNX4>dDdVKiR+!CshT6TRY>E4xmd8U-}hJDBR~?b +z$}gv&ZY!U_Ny_}f8C{9T5s`0WmUG|i{7v_rFQRoWb&y;H$%vpX3D_HPswh?YNxf0L +ziW3Opzv)6K;)WWUOxG>ebvK7%ZZa|S9-~2YF7thwXCBW-fXnX~UHVLHsiOKQ +zt)1)8?`W=kE41UKFAb*VGf)F(lv4wqR+14u^IAwws3XGX-+Ol^tx5V`BqDh`xW2?k +z-cNC0QOQ-EE^rJN%1ANh;-;fRVp3lcG@4i=Pv1~apdtL3(H2$#KM@~=^d&_BkX4Q+ +zPLNn(RoyPsbHg;Col&_~ZRq5nZ-dCvplI&BLV|O{3?Q0CmqTM?O?tw7<3_dXZHK&e +zekqL>()r29P=ob&Rqw`{rz-7jtQ}X*Lo3*x@}jHZ=)@w`de#bt8tv0rf4$==rAp^V +z;Ge9wxZx5VG{Xjvcfqv0fuI}$fgE@~Uys}N#UNng3p!3jM+Q$&y +zb&-DJk;((hf~dJBIX&SK{9$<=1dh%jpOsZ0zl+YI=@&2uAcdyWA#uJ?GKJU1w>XcG +zzs%qsHUUXL;|PuDmBHD9L8b|pcGY?5CcNY#ZT#pUO|V;IV#_qMOIld%?2-{g<)MX6 +zs)(Z6Zz`iUq&PD`&VTu0?&DXJ*8RIa5>cMgR$>+rt`pUo?y8>!){DnT3~XI!oz*u{ +z1nnz$PVadGDZGA1v)DAJC9-}yu*W)q?&nc@?CNx5zblE7CZD^d%zTN>0{WF+qRtz= +z{aN62&LkT|uXK?2`~v$AF}Db&x|zj`X@kJ*{y;*xfeL&{lXr@L9A|ktXc;+N&)7D; +zihh}`!a4Nu3-a`*#I0?36=7TYk#=1gwV&VioY&f1)qd{hUfY~GR6ksdo_vhz_p~)I +z!0UxekN=uTzaW}FMrZFQfVzJ{a76cb(|(ctg?n{#4gHmZJ$4-TQnYYt$Ha+V`C21t +z1u@zie{~4L +z!Oq3=nT_b!%lCoz#T44w2MRk_^)Kl +z3wwsg$>Wg&h&}Qw8Ww%HWJd8LY+L}EL<2S{-ZH**OFoB?5|D5*YGZLBxA;()+q;r3 +z`R&3l`PDl;d29m%@vYJ=$vZf5f6jSkY-F8eWyGGNTeVj%47zs)lk5pBc)2HuRqFpy=&dH+@_QZs# +zyHG^7pSQX{;_a7TES(>&kGpt_j +z=T`@td!Fo^UA(_v4UFoUbs-{WL0&|`rHXg@1?LWD)wp*zk9Q}R+wZ4#t87JfY`@xm +zy>IDIt+GPJ(BSbwv+qjaaua<&{a}Cs)_+7lT?WGaKKg@SWrgS`d3XZmOZA)m77P!l +zVB{b|FNWk*3s;Pwj{lVo!VZSda-;IstDrshIVm%_G?-WqPh_D_{F4axJ^~{0^~A?g +zXUw1*q>N{s$A?!y&tBvxZxuC%9!%RxPFzaR&0yqVLA!anxVk>LKfGTN9OD=B(ZI5u +z@eRC&8bDW1*;a=J?4RB}i9vCEkp+zA`Wu+(+0zF&&PQ4RAL~i=4W%Ge-f^8SlMBeQ48$=|BgO~;yyN0Fr%8m +zpp?4U8--j>qP{W^3zxhblUQ?_5yhH$bN2a{Wo0?kMTw9b8S;zUKQI!=eX|+Lw^ZR<`~ct +zA)KcCs0w?Ocnl0>P&8`QYqi@w;eCED&?zhDWiFQnZU)OMi?=*zQmm<+=J&sZnnGh( +z%TB+DLN~4+&M|DO;ZV<@IIDR97iFi75`S~MT$V&)W{LFx0=|6iC4N3){%-qqAN_XQ +z;I}{)*QPt3S1ttO$W^;Wqhklri5Vw#`65nkID0jA>mN99vkc88c*xzI?>*>zj31$B +z9imiSk8xTaj3vgbIJ+7hi}34GKNu#UMRltmjVw$=wfr0TTk>swSmxcXYhJ#r#ZJ#A +z#9c6pGg?-XlHZw$=VP4|7rO~)y$LuZy$P6& +z^G3~OjxC6Z|JYlRDb4(V@+C)d#E%CKzy?3!#|Hxn83-4T2r^uJ@Htt9|mQCf-xcSe5mgW_1In@h+t&{11f-d*Uqw#bim&_~o>K$+Mu?oD| +zAqJ9Klj5@vlyn!y2$c>UDfR0Nw{bYx(Hm_xaXg(9j{TE;S3wu0-5*u2v9Ru#R31Au +z`nNXv7p|Z*JU%Pr0^wj}kGSeGn6bU7R5GSj)#kf=fx1kSK`O*}i|L5{u +z7m`0g7roHt+tAzC{hMbnw&nc{&LL;eV=>>`FU=hnvr&jiq#f=T+|_(G7%e}G-#6MT +z+ML#cQC!14I}`A7G$Z(X=iU~?M^Q1}0o~2)?H(F^@7a57o1};=st!$5Eg%erVVf3@ +zM!35xA%U>qN@Dz>Z$>bG(!J~&7_@M65zKY`c1FCL`mUZ>rAwQ$g3%*36KD3*Wg>a5lwVpL`-b76FW}8@uLivC< +zd&n6SCpo1WEgsX>169XodFzHc{TOj)G~$nZ(paCD=F>SULVV#*itrbMK7aF5eq|B3 +z-j#M!lu#o7DmZ&+HUZ&Q5u)TOb-&|;sRyF=OQ4&Nm_1pgDw@~3KMuyt=Z4J$%?UFr +z6*Ht~KnCh)=&DGAv>6Z)@n+uZ=HUkKWo1ZikR@7pl5UFNB}tbjr1hQPr*zS+-#JoI +zh5bEFW7Fa#{B7q?88ITzB@XrkVQff6Ox@vtot2p;*dx>IXrHOa@gfrOqmKHw4d9GJ +z%k2z$0ABvmZ(d|42+ +z_(?uV5y`B^DpNgIkQ@;Rz3yN73|ggjy1nKQeDYs3X4N9ah-%1jKs$r8y~)>pDfgE+N&*LKLZE6yP*S{VNndb*n-1ZI^XwdHhO4 +zv-j7kXFeM1pfGXJ_(xob8K|{G6^of(FtxLGwP8W~XOGX~{zG>~<^AyX@Z^BOBPne| +z?@4ICn!y|vVf1PnLetAl9DjNrP}q%Wn+{ZI0oA{?)W7dffsRb$#Y2sSx~Dlh3_Mr> +z|K^O$IP<0KBfe1SAEQ(2`b}TSZ0!XPViw;0_yQxFuJGthYl6z5;O1dJ^sN!dm9Gzf +zbLy717!R+LrVb<@v*8^rq_S-ClZ=|On^eHPl&EAC3|hxPHRa$ggTXy3hH6&^q`oP{ +z1AvfzM-%lA9jf_(a8#fP?|i`1_ZyV=i{mWPs8}G>ek4zc(orUsH#6qe=P?2!&(fg5 +z5<({CpfI$wDzrg9WD+hp5ts`})%HHS$m8+XrKfrCJIS$^EF$tf0^vhNQ`c`d_S1h6 +z+XWP$&5XQ3T8*+qfkc{2a+5YG?(h@DX6=KZ+6TAb^{~t(add_e#<6o{sG7g;wF`<+ +zN{V(!`SRIsGTkc)U1#MwoQV4V#XbsJmk6%`(og8DZRd#9;<292i;O#~%o#tueY6sM +z*ES|i%qW-rz)X)=eG_Lxx--7SkXDTEXWGv$M_w|y0-OHXk~8+^0r52k({NlIL|6$r +zZ+F+aO2l6(Bfx4BmXf78)z*trg4*0i1tQ;zpHLqq-(43`ZK<@Pu@*xXcc|eu;8ux% +zBSyAKD|ysT9kvK^%GUB55G-G;D8otM;pNz8ov*&0Wve!XU(f*bJbe#=n<l9bGer@x(@r?CnY`1}8i`KhAKFi)imdCUR +zZK&MW9caU>0^>@K6rl+DBPQO332xNj8;0*o>=eJ^={(P7s?4o=K!(j;zj!DSxM)~} +z$PbYYzn>M2G5D)aBWvvXP5@c&6^U7f$K5l&s^rq3uhsGB@{qa#M{o5;oCI)=fE35@ +zW`&?sdLXWT_l?_LWDKAdg$T6f^bHNJH)|S$6Xhg6kj`^;E(1RYLUNAX5&)CaZHbDP +zPXIIpNK@&>0P +z=q&ow6T4~N5S;=o$;f_dpkHBWtaG_lL*o#|jaHk;&W}`*6!jCM_Mgb*I3i}@93h(y +zgQHq*-86ub*C@=-S|C`U?~H}fPUT8C=!@uAU!85Y+HcW~7dRlkYraHYOlDM#=4sDCiwjKWbdL*&^erK<{PFkUbo*ZC3k +zb6igF4|mHvI0-ljv1GTMKO$R#4-A%ulzTj!Tswbz{pL*J2*SBeKspVECFeTq4)-hS|ul*w{m14e=xss7=JNmJ^mCa +zo3#2)`l?vJKtF;1Vg4=vyJ*Ci;QrYv2D9ogzrVn}2Xfx4;Nhd;+BMyx(W@cQwLB4) +zAc<1{w$pM@EtdVO-C~mttABPUJp{A$trlYc%R*=wlL^%NLo(Uts-4=&YjZ-y<-Zmm +zZA>QbT|%g&OB4k=h2F2o?6qcIq9u!lg~VuvJkws8N=zP`JWeJdEG4Ig4dNY|o(X`> +zBFAM+13z>S*8sXPX*!yW*azLe#m*^E2`-JkQI1lbQnf5Ra>%*K6OE^BdT#%Cwq1GB +z)ASmScgatCMA^!mIJfbE&(>@fsQiauKHwl6G#I8Gy9VYRl*)prP9 +z?~G3qjhw@xyQ<$Bjoa7vG079=d5SeWpf~+SKp*QLcwKu^CsfoEq`;Ek(yWhVD$$A< +zACL5~g&576+j$AKs+8PpwpRdw<){w`cI1SXD7pCn(KyUkIn3dBk-wVq@H%K;rQ49z +zmo}8NFyr>RWrVs6-2w$^ne)32Wxnid`Ejp}Vegobk{j;(@8{(&3Kz+d^_ +zAG2h9Eb2e||8Qfa3l}f3gAwiHy3*`A-@5^rIgtk(c)d@S596u24DKxcDU9g)0P||A +z>{jD&hA(s0ifo}=?I2NI#Hr%=lFwS^Cw^Yv?uZQ*<>hq1U>wxrPgq|3K#ftCIPGO~ +zDCMN||9V_ppNHb)!komcLhaoUZUs6d&jISd7%O0sHB@!61uEN=B~QN}`K~btU73!^ +zFlWUer46(CQOciyz+E8+$b;~mvYP=zaM3;=7hNR$e3tu#!@97O(GpO?Grs_?L4iVs +z>dBv_2Si28jO0(Vg3}R1R~k-;k+DrQ8$$NG=G@I7u<$f(t_tVz2p77x;5^fsImXR` +zZG{GMredqv;Z*(}$uZU4AyC#C4(q4T>TvBl~yZRrY{st-TW5?jG5f|xfXl=9Ud06L5*N;;EArC)26#>N9AZ5_(yQ~ +za}w732&Az9Fz3fvf-Dwu4npSeDxk&xH>}dplUVH=L^vI2qm(~&DbC_oX_gp-_(RioBhO~tiNBzoQnw>#ZZ1Q +zW$`opRqMhpjM#uqbtbL^UkmI*;YF*JNRH}Xsw23)s(;B0VYVAW;asHbcK%2YRl~Sn +z==CFaUX5_%8yygq?{Ud+ld*o(<21Z>vA2LIgA3vbViiqpQ}2sjjpjOB7hwzsjJ>9# +zE5f2PVjyAct63a3RL^toNdKf_N!zPP@iX3H$ZnM)&IY^?dx1b%G8LY106N5DbHg&GurxzY+f1cWM7~4}J5F +z?CDsaGzg`<<|JggAqC(lJGAog_8z2{3)5SUa5wM>mkN`_i~RxP&1(}~4BwcM0Z8i^ +zR0oLGCEI=#(9vVYq1E0iQNo~&@~0c~allzyyQC%HRS0;mX93Bht`);G4|LP4+5Yfd +ztv4@p+C+70avtC_#dJ5YOu^pjBh(>w$>IJYbPMJK$;j2b%YbRfx$ +zokWWZ=JE*<{RMI~FEcRF?KG2)UuHc4ltF+Ml#Gc0ynKS5V~yTJeL77^>ff?CHk+v{ +zancJsc2aHBqYGK8UmX*2CPq?Y*tLpHYCO +z#<^2mg{l9Gv44yXrHQ&l;n=oq+qP}n&W>$s$F`m9*tTukc5?H)=bU@ThadMxSJ&w7 +zQB|XRRMqUY=9)_Kz)P2NBRdIf|let4ynm;nGH|Ygo*z+=|x1TPb-o +zF}AmD=k=IiAH+;8_9@-sIs!esMBWY+xZ4m9^^+7jYmgDY3UBQa0fIB-c8KG_*9gnE +zJmxb*b*G6rNCC`@>A3n;!#O1?U1B08YSo{+dnwxKh#?!wC{C+EBQbbkY7?&IUOGO0 +zM$Cp~H-;aN&Z@_%<0^L^BQ#OA{I*79!6zcPH;Y^VxX!V{=w8apgI}yUmN79mlF({*%*Na_v +zio?vN(?gOmmto$(8!WZU-S_XyiQRqd+&u|7g~yihwK`-?6>cBorkK@tkK_RSVe@=e +zgl$T*3klG1CIaJ>=(VfR`2@4VK7Y|fzh}f&k@jr=THU_^_9|)bML5O^pL{D8yffRZl +z{QVZ#J#rujEiOS{!08L2)eRj`Nq>NlnBzd7kHJSep$fv#%Vpj7?pWTkbyI>h=hQZa +zeEkSTFOJp;Q=lTi4y!7i)H#xmWRW>l$)TuV%f8HFp-kB~raOa;9<(41#pVU6Y(>yG +zh5$%jlKk*UKr7&1zcfUj&yEar{LC4oVZ86`#M$C8rNfzyQQ}zN5S%<78^qc1HHNnB +z)+DV0U)KYsMjn>c!RJBZw@=FIaOP|}*Eao9XZ5k)6q*Q?b}LmrOoD@|(~yY>GO*t>Vw~@>|ipr+bag+kqRR8+<;7xd+=|zTnfi^b7jn1?5dUGqKQ+ +z%wQzQ>~)});Tq_gkxj=8e{YmtppY~KC^{OKD^xiIvsDZa}{I +zZIY(c#8<*-;YfqlXsZotk*cWr7MyEwW~-kN1a=YryK>ScH}fJM<}^YHi#_W;Zz3NZftl>2 +zr)_rK%Mh30P%?8ofMtG-tv*MUlLnE=6(r`5zPCLXN?5~{k8R<+ +z5x>r*YSVDeHg59Flh;$fy7`|WqEn+3$x#>&_NVRW`)0!F2GcCl9zT`Lf9}u8tBYJt +z$&Y*GM`Ob%L$6)1K)@uwS)?XR^|2Siaz`!h&`T#8)O#Ilc5$q&SwfgId3Ga-BG5@>Kwu;4Wu!=GLc**<9cK>2fNpBX* +z%52m9m#*z}p|W8IEptlz+}FDXvI608Y`7+@Udw46ID +zy}+FAl<*sjz_sWR8Uv5UgS8S5bVuQK3i`>4SNY$hAaE*L(ap}?S7|A?G%s&k0|l2^ +z*OqhLx-|@%te3D_j7YN_w)V(A4cnvc0Ena0)>sR3b7*R@5^ICaa`n7R*KP2*^uoLo +zP*U+LCvD+iqb+PKZx#FtQ-;J2a8)M&#N*j#p@V*p?_hj+x +z0iBSCvIO=(q66dq-WU40Cxb*U3I{$74zVn5u*x8k4|gD4>Ew`QXAG214{-^Qvt|A; +z&0XY_|mDO!3LQ?!KLZIC +z8BF}&o|ZgyOmBwv5fZEN{OzGe5~h-A;Ay-^9fB~K%xv0LA7X10O*^C^8j`3^>Zs30 +zAD^gBi)#x@zf|M)vd4Y-Q5-LQnlPm#59<;w!+*$vR|OCEcalEIPD7oC(CP*eC8|2m +zKm;dSWal6k=0X?ib=lxTlG!W*#>l82I8IvNDdDO1Ql0a64%4Y^`6M+Vj*%1p?#YbK +zz}9N$H8k#NA}83raUt8<&ZVr6gKXv7iZ?Q}*Zoy?M4nm8C~*7a`MCFT_`=k5^ILSd +zI-ZdZ|K-ax@wgHn&-HW0`jXix2yIbrv|{Szk%58MY|5OH9q|M9>~B8)9o<#Br3Ke@ +z+cnrXPOF#GdmxXHtVphOmn5?#wR|*$x@&UVM1Ky;3iu4#iS)DHT?}=Eu(Kl)+K>w7 +zV<8gSZ#tI>8C*cdEXdHZ<}Dl%FZLdwaF{x3D?40VXV${83ro*mmE<0U9U6?lb?t+z +zHkenO|g8E#LpnZnDRu43=Ich8ZmS^@?+V+cOU+D0pMeuSQDS-o7vV;sj--Co>XSIcg*OJ-H +zm3h_MX|pswr2}*`Cp0R>&nPSB(6Op0d`(OY^n}~lc)|#g)$Z!Bm|b|+_Q437%-YGg +zlbQI+;pM{x;+3YOBc*o5g^Y}dSOo?~LU-g1N{?w1NUI26GhT&@$~>T^eKE79KDSRDI)=~w?^VZETE+d{_Q8$4G#{@7< +zcaI>kp_E*$l}D<3U9mltfAbcTyF8afRx1(^37D5S&zU}1nXwatJirw;Ta5Hi)1qLp=`g5X%|dZBaa~mLvZ=-3Iw%4oFmdue_1HE +zO{YkW4nbb@1m5MlNfjOr#6Eo)kO=QZLVUy#`(KYj+zlg5@m>X0Y@V?H-%(RoHJ_W! +z$2^qHG|1upr83KC;hlf9%&F(Q1EBY<0=HPoxE&fQL=DD)0vv6)9GV@CUUzwWayU9x +z5ShtN1Sm_DNj#!TJiiP*Wmc*zkKG1Nf9%C_)L8G$*wFF*pe#^DKi6Tvy*{@@P7>~L +z`kUz(N2HPNmrz+#&YHc`g$)*@phA9?UJ97#QhKJYzQY#uI;lN$6yH0e(_TexE`r#N +zf9Alyu@<8MpoR(v!*X{~+-R?cG!^yQk{JDvq9o0Y!F8xo0)`k*{S4E|8WVHqBGAoA +zXgEtxNYNS`ZamCp=58nN^#Pv?$dCj*@6e+%T%0x4fOrR9VYGHUxGz1PuIpd_KHN@K +zVwi~_DlsSb;5GV&W55Yny>_XY3(|92n+@9$Noc0Nz`ud*EeE}uZVcz1Aaw0og0#Db +zcsKM#G~ee>zg?2liVB2TxI`|}@K#>_EYW@k+?k%xF$xor)_p!enh6}VAfH0tLY+B8@aMN +z7gz5fp(>Ykw^p!{cXA>w!%*0bxuxW{b&xR4QKq}^1j|@V5ry+1_>`S`W@%%WK~`qq +zr`96!#%mX|B!`mR&$dUm`r}LDn@mO@aMl|S=XH{|ed6(I_Reg}BulU^NH06cNG*&Vd|;|jqh9r(|r;pYeS+U)7AB;OMlLBQdYNTqm8?>veK?%^3*BVL2(y+maKF0 +z>I*ucm+DgfBYbSdMQTE0cAfD*zwy`2{ePKa!l?h3DJHDv!@#$Q|MW?S6= +z9ESxq3YK~i7bX+Jva|q_6f`3X>phUWQge^^gAT$r#Kg3@1^Go7nUJS$HA5N +z=*7--ZT5pSiSfmEQuiZbnu!S>vjHBr-8+Lk7{fHJ25RBOcr2_iP)r1g{z_7=%yb~T +zpx+mQK~5|B0_n*TRyrffNhdBzzNcJ@RaPx~1jse>cHk}a(JcriEF(!@C235z5XwrJ +z2qg$5od7cFoC}x%Pytff3gz0|@6`I*4X2yc6nK^RWmV(;0wL3M%iNby2H^i0Cv}@lfUO9KfJMNXqhJnG-BlB8-&{PEHCMgq +zsQ(U7()p=28zY^%LA{Gt3;K_B-|8SJ%9> +zR9xPgtpL55jOLV)(RKR~e>>d5L&pC{T6u`}kum1r;PaIh*rA-ocLRNV3BFeaA`B-F +zuZ6sO3BC!w;SRca;s1@Ex>mM0`H}AZ&g%7@N37Eia0@Z$B7g&O0ebSxi=7B1$R_Xs +zC(x~EMaqkk-wFRg2%;ehlPBb%?cK%D=GKV +z^G5=jgCA$}Qar_~2+<8ySIE`@VeGGXXB;-KWTLI(g=yo5k({d+nOKUVnG?EQ!0|m- +zTj?;*fyKg927Uz2=|4a|v^XxaGf#?aB0i7dQd>tf3)34qNA@<{X30VPX7BT>naIz) +z0)|=&FH%umM@2KjWoF0I*h-o}!FK07As<3ZL8)v_@iRB>)qHk+B8?bKp?p1^t(A +z90tx$APPWQp=RSb4^SLGDbxNp4iT6HY&8e)n%&61Kwy~sPpRIm-vfBd +zTVZm551c(%a+onU(V(9%aDTNH(ztV&<&VVV8hh|P{LIe +zO~xmH@7U|1gcI<~EM~{UQ6jX41kkYmsdT%{ZbW01ouWgj5{e*&tKi4?hx=6#gY5+& +zUn=N(exOUVBI2)&h)y3956$XgF`^$A@+x +zdQS?_Y-OiayO!%N{svBvM)=OkG2FvMqM`}oO;Nk}J+P$vDRmE&2Wp+HVrYHB +z$8sb@wRNdKmnHp1uYq^gjLYlGeU6)jaTDE>J|c8DcI((5{lml?TE2Y-HkvRx4Xe`|n$l;o5F1ddnD005u}B}D{P+_SE-rkwUAko-?Hy_c~sUErmA +z9gSVDjxWQT+Uz^_)|nUB#Jx`0aNOD%=S_)iV5qVoe4~@#S)Yi85c=4bW +zlat>lsij#eJ|X4we5p44??s7cAy|NZ)B6$w!~n1WDS-E#_h=RevHoL%V0!uQ)_+&a +zxPWRwYlMH6Aqh8f*82oS5qTofw;Kg^zw5*|U@K#LUuHhyh7chTGL;-bE-X8qmAnA$ +zS6%e+PkUo8!SMu0>l8Y0Dq-C +zzVQsTrwzyrE2r{up;Sl#DaL{kXpld1+EC|^&f=f=MK`G_j(iM1YrSs +zCiKUA53e9h>*J$`{Xth%5jMcF3BUu3B$P5e`YcuH-6wP +zfB_;l_Uep_t{@oYYnz)7AcDBpS-{aX5=8_Ni{;Z$7K82tL +zzz!g+7Q`|dgJ4i&6>jirgHX7(HAzm2>J^wH!jvi|>U|%zmw2K>4G1U_hciuwxc!Dy +zky4I;VE7^2j6c;T0s>Y{g_*ub*yST5$ggGrS%sH6Tv0~@`YbJp?!=w=j?VLE09j)n +zdPSN$Ks2FLdO2pm5tQ?u^VO5XmE0%AL1%~-%R{sP$wL&t31svi`)*%Z7&dc``kskE +zQC|=1W!B`@egx1)sw&nhZX?@mX=%jtt&IlJ%LZ4Hp +z+iXP;OlL!+@llu&INEy~T~PbT&N2?2x{K0g#lD!|V+t37|d(|--b@{$#)OQy$Wqnf= +z!K@=+H8e<7n8L0*EZ5197407!y`BkfKS==ul%E1DACNx?y94Q)YS*mX +z5D01i4w#wEK3TpFUuy(nrjlkut|%~ShpDk`8V%`cJ-wf4?89XBoUK{j?gYTU{v3!% +z*$jySuGF7?o&K-B(g43-tnK?@7j-H;Jy>n--*xp`Y=?*;BK;I&fco(NcVEXY97n() +zlW7}<6Rx;B$#cw&e18nF1Ip5jXUeDTW%aMDdMhuZZOS~Bd8@J{BC0t+bOzc1Z4-<6 +zGM^BjK!7}JFh%RGy%*D8CJywMkly|gxX;Mn_RXW +zu~7isiVtGkDbfdt8a=NC+ADTlKYR +z8neU;cgey72OvaH7>tP(dmDBMB*K94`_8*3&fVs=(Q0>GFapAX)|rq%yQ_N__Bewf +zWb9-{Y{3)-KHSt?p+KDPUFU!kYv}E5fE?k;h;yL%xE@d-Ea+OHo%%)q0=Utl3Wk2a +z<85`{Z+kkk_gqgNP#`MCY0%d|ASD_o;-3T}vu(%2;W`Md_gr!9brHK)tO5XTtYww1uL45D%D;RYU +z`zZ{X=g;_$zySk6bs1MbR*WyE^${)n+KEJTMje81v<;ySz}`;Wm!N#bD4+s1J}w9> +zhO&|b>I#^RgnpW}A)h)(5dM{4+l@EBCl>t9ykEv27N7{i=?&t1l(z?IC;j}icY<2d +z9W<+-2JwsgDa3syl7tut^P1yb#r}pIzl-mRYafBDLVxxH2K1PTyX>JpZi< +zaEu~hhfV~4BDTwG^LVg6L~_7Hpl6yJ(|DjhMLRGerNQPaA3hv02OFTFOPw9$F>pj2 +zW<)4Tiw9q#AYh2tEU;D-)gFSe1NcBDvfn15 +zJqA6KqVuv4{Ee*B2N@+q6qFzY`i^vrHl+j3+qageyrhl%G8FwStHeIIz-B-`RS40_Phx^C(Am7uw2I8xr +z1zfq-qNzjQ8~MB->a@}}{PS(*gBispRF3t>o#ltV5C%nzZ&JQl?)ZwLZvpBXxUCdD +zPJA=rO>01d>06Y?t{iL6fOx+=;Z9codAvMeJ(~|N<>v!Za~c-E6|0CgzE{9QKc +zUTvjO@9Xd-uB0o!V*0_9SP-Rnd5 +zA`!&;{tej2==c)IsUZr|&HV?#1pWu4{hrFO0(&z44<`9qU=^;jIo} +zzyUG&(O{qXruNj;VSvI{)=xbGUsCdOskT|3BhQ_b7(n+%NA~(}qAo +zG6$4t`S^23G;r*#a|E71t0HO)lJQlE@Bq~0)@w80I3E7(0v~5CHL+rKqicw<&X5WiAb_Dz0yk3Aaj&+*;r4(Q=df&iZ +zDrw^`t)5_#Ji^W5ylK2=)X+O4vafZT{Q3bS6gdO03#unjHps0|Y~jFQF8Et*Kz&SK +zf0h>ODzT-GPaW&v)ao{YGBB=TPIt1jiJqc+Ob~sfds{>~ggcEMfF2k^8~?lkA)Jgt +zMOF&MQu?Cvzom-!XUq_Sf2zr%6rJ2h73M{Fxx+wn7yM4v^nBtqkkvv1KpjHxko9QK +z(6a6e*BwaSx9p6TN}^3`w5e>0ZSpy`oW25TQ36pvGz60#uvMD+uA3s6%Qr4qJjIo< +z;$=YQRvo**Hy$1S6ZJ8&v;^wlTq2($XA!6$*DpyDGv6+R3q0^IIL>v>Z|d!y*4S>s +z1fuQ!lc!P+Z@r>jYu5y^%*^148yE +zKF7?wof9HUPyg38{Izw#SDcc*`H;I62QXO^Z_8JdX`su3)hWNH82m~2tn>>K*m!(b +z!}hH@j55A^Vl5eLVH`dq=xz37m&W`AcGJ(yi&BVUEXmiM+Xb(^W2~A6i6nNk4&EZN +zLm0=EMVtpTgZ(o40`R_?pq@1m*FXIh!Shezn~_ys`#*kJ77HfJH0%4vlp+^x?*RqX +zEO$&I(B__Xkaz>8X`u{;;Vt(7E#Yo@yz*IiiVOf7E@^?7qCc>djoMz6Vpa4Cp|Ghj +zt};9P0hA|)@Qr3-+VnD$qAWpo*8L?pR+@)^2;2679H51#m|s>AjY}U4axJGLLa58G +zPY}l5&pagy`Ze%vl +zGdocFPD86Rh=Dyvb8SOSPdzCQK6+H0tl#?CbG55uxhpbFlL=uNOFgB#8c7GnWXQA) +zIiL->k3+&T-g<*IzhjVPLXaxIk*I}(;TXmjbVk1B_s}lv=%fM7H}vq9_Mj@ahLu-M +z-^`sGO-A&UI!tk+KR;x3ex*K5WMNKnz;LOvZ@V+x!;aj67tRFLN949I=>R`u2+sLk +z90Ty4oWSRRLIWj&ZsEzZ%yhDfm%M~bP0+(;1^Iz*r+s#d9IiC(s+l-(FMk_ye|PP* +zme}4oX%ji&ZMtH+c+oVn#60Xat<0i=e=joe?qtN;!-oAz9Hl?(YFHhv{?n0f{BwZe +z3XOHrSGhTQVLpWw9lOs`=z!<_jQy5n5zEHbd0^u%e#q0RnzpIce1lQL>+)ydHw8qA +zBVK2Pj9!%3`*V;fjC&icGAF!m$n?c;XyXdf0=JZTKL>Xq6YW;B&cYMS#Kb#cizBl{ +zHspnoaM-g#rtHk3*sWT?Bg+^8Jzp(DMXHB +zRcwdq%Bfxg!8^Rj$E%RZlt%E?xO<6B&U1P_34P!rkFCgJ_xI^_qjI^S3v=PA+@II! +z45e%zs`A|Hm1ZQ#`a13k~P=8@dijZop>88e!5pp6Bob%^W#!+qC&<*1=Q#kAb9$1zL+FV +zsk|Dv+O%h?YQ)TNn%WU$r1dS;U#YZTC$5|?kis|}>jW43xGHNtM0=gkNFhJ5sw3hn +zp@(4JD$t2{=*Ekn^VyQ4v +zR^7NcS6(u&C;bfuF@m?{q>T1D7`cL)Kc<6@C>L`$?`QN^?~648A1X?^%$qglZ9m^n +zsjk+My*uo0Pqmx#t#SPx8$t*X2zZH+C=xzHawwWI0Mu$5@C@cM7uDls2C#usX6Yjg +z@%wHVp=3Fuv)wrY|F#-@&cdfg44zLi#h%Y2o%Jc#((X`0zO%3f`FkdGaF|*=;=zVc +z)xcA)BgNRu;|Ar5gda5?VJ8o6sk@WUk~+nypEiJqXo;Eh2OdF5NGON(U{*Bvjc0-j +z?>!r3F(YqsB<{$!pqFZRpQJMEjW3pdq7by?LOPV%v~kJ8-pe)x_7KfN4zh@y!zuh- +zFC^QK>Jy$ZhRT71OxUYl@dcVm78=oU2mpr(6ZKn~58jk7+$MbMyuAuGfSEW!_yA`; +zz7QAyY +zYZ1$s)jkYYJTfLEPhqXnfs5H~{sFAx!N^vf9bFU+dE2v@PFeqPpA(q2O0fo=tLg%0 +zC@?-10h%~IU4_JAXc9MgF0ZKT6$!Ua@1~H%Dn6s_jxFBjjYdN0>${`+!}XL$ZsytP +zVq=?UU3224PZnBh>~rmT`~s(cB68Rvb6<0eS*X}8k}M3-iNH$+!X!N6z&o-ih7!Ko +zKnT_*)N7oN__wSsy2g)FtW@Qg!I><~-5@lMW4D=|^i;BKr|w^Z&j~#4K`x&Y`oD5V +zEbIbWW(#Y-OH24UKXGgUHn3^2hDrz7=j-ago89vG=^6ptI7X-si5BZ+fS}QLrAeXc +zG*KpKVJ7BLTX-rggF`N7mxV|04L}qgFvjFnlDHCNQSL +zmWa94kgO!e5u<+KIE)za)zCb>Xu{u6!I2>Mbp&_YycI}Ks%pxw#$yXEryWyngtkin +z#Z)fXMN92dY#HrWzy?%|3-PsUK_2QMT2sRK$Y@(G23tQ1ZsVy3MJ@@>>_-qXJ~i{vn|wpKD6DIQCCVuvc9~&^KeD`re?MpyOB%FJNz+@`#m*Mprsg +zd8AS~#mug97LCQf>-bCmREMio#qnP3nd321LR_1BKkc>cASnQ<(AC;xV@j +zNsm~I2&IWE(WB7BJ>zquz7&1`n4bq)zp!eGIpG4VlT71MC68R{GFV9U2%cbTD(;iy +z86jZ9d%}aBnEA-8vxlFqCO!B&QBvosJEHH{c#ZtmF2J0^mY3YuL&F4ALb#T65s>8y +zPS@CC9Vf?X)FkNMl9;5=wk8xk+X9c-B2ySN@bmBW2u{*_6|mbzWN!?OJc94C${nFV +z!3|nrax}Rvbz|X*8{nea!Y||f*@(MQMw`yiUZO5Ajr|H@J~uiJ7Gp-GYvbJ#l(9Yv +z4~+Qwqnp<_?9piF9B2vYu5=Z7LWX@B31WrQvhz*hc5X`cH0X5OaZ>g4(mTQ& +zk(%47RuY4JudN?=ue*c5mhRL!_+7X06I0fTLJG;T5U%(#nEAozc>NITG6ky;R#m0HQXJArS0_#nWYuD;?^Uto=oH}>5 +zHXQio9o|`3aE;cV=dwm|weFSG1X!HpgNLwfV6hmjuRwE_!GEUKH&gal8)s(>~te_>zhHnS$z!XNyGj=6%2{ +zR~pHS1)<>$Lj+e}!}7g4?j)nkxT4gkvta+aXz+~S+m13mw<>^GzRJg6V5~&cO};p( +z?cc7et$Dwct~UK8mC6=Sq})nho_!`KzMA06fzSz!hN#S@G6WByH5W)g^N@tDVk3U% +zATNlN3#Oy@*8p|kbrw<0fap?d5P?~$7L2(Bhmzbs${!(`MEE-iO`r-m3e`L7iudnt +z#z!Xr6LQ{kzY1w +zr*;E6SCd}M3mA4rp`RJXl7A+7J!XlW78tuswf;#XbDi1H&8gq+*^4h&YZT9VrJ?@@{wwVKOvX9J@3irPGP{jqKKFCHzfX1_ZfDF_)&f +zn~w^b&}QZ^p}Zt66u9RWtaCL}&8OBi#S4tJabrw@ +zeNY507_wUvI?PG_w484Ixv@6}l91IFhCz~w?U9ZxdZ%Q4xddw7Ed}>`e%NP~9 +z>U=lRIK%ev<4<65NfFO=*?kTX#iBn66-LMN{3RQ-3qy^X8*b>pS +zWNR{_)bGec?7Qh3@*vmKgs$+XIG!$p6CsP-0AswK|DqC#gyRR#Ut4g$aQAI^JcGR> +zqbcHW4A8j*zBS=la5nG*<3*L!Mmw{pn9J26)5pv(I}ab~#EYbPi^j9@-Ns1t8M}BG +zLf8KszU6T8)j-7fQ`p3pAEguP<6~wt;Na3Iix)#4@>goxd9=Rav`zFy@ur +z0=aVA^qx!nW)#$8%`ztgP;)oSu{qQ^C=~vy3A5+vm-^)syIDXt^h$c1z>&P59eWCj +zq-25zAH%P3SRXH*8C~Kw0_)AFS}*nVfWERg2fuFMZ!@@cb8kDt*N1ROUd5=56rkP>oTt`6MbhIYa+_#O7g;fqi?9~)UdrkQ0Mf!e>!AbnH&4O1( +zWU~!~CZta_N6swH2Q`7**|ozs94gvK=r}Mc%K%&mN8FO=ZLrA)%$}QEKK9saUW%S%xw2lv>W6`WvLIB$uuwGi4ml-$t{e7z&}C +ziT%h)oqmP&5yY;+Xh>(vX9-$V-$oWtDK+2UTR}-#ByOX<$Y~|F9fK5~LB@g2LgAv8 +z_xhAxa*81~pq1+2b|YEm#iW`0mNo{9!S|*K{iWEq+KuV96}Y>IVeCMX!n%k4q+_xc +zqX{fNeSNV02FEtKhR4%Y{@6^k=FgjV4%5bEs%W#H9Biu8%zO6oA_=rh$7o)qZu!g= +zkx4z-I94JGoZDtXB_!bYtQ0ak7CRI%dD%r(D7%Hc={)wc(g0hl2dx+ENRDTjSHchr +zm#RW5xVlp=q(8ODZ2}ZoHYL?3n1(A_#x-JbaxA;><3^NXgH}sI$r=dAByQ0=Zpu(k +z;NTV9$5H^0qhw6MVXU%GXzeYI@BsGsvne1%ewW13jT#dMlR+nYRlwCN8LAJe9r_Oa +zM|4)RUEBzkE?{?aZxxX^y$}cdu`r7jg^m<%GSlY`GNQQ8TaVljcFa +zn9tcJO$sg;CgD;+T|ckWRi(?lYH76tw{7tPMN!08FGe-Rz%oh^giP3AuxeXjsFEv^ +z+fEa0H +zN1_r1fSp@ul23po>mW~47mPgR2e_3VG3dw@{-Rv6FS|vcm~~+V;uc+~ro> +z04gRKn-*W?dPZ3bSwX8UPL=|v4zQ+?`{L`9uRJjMW{%^*MoXS+6Q$%d%I!@5P0nH} +zb=l|p +zxf5F7ae->trbyiU2H*IoS|dUvc5~C4gzRe_O7`B9vSwx2MBMR~ow`&Xd~;x9?{8oe +zwFtdwFsJg)0Pko59B-DP`Y<+WpQ4h@wZACz)Z!zEX>d0>X#SEf6-D4;$*sMzIu%Ib +za7$~l?NPM2)7V6r?_dj}&$bZvpy32l&CR_gZkUItXOJ5CZg*QGI<_hF0F;!zfQA{D +zu4D1wSn?l#>CF8)iWZ}h{AjK*oK@nrOr@&r(CW47#brA53#S-H3t`R8*)=BWR`+u3 +zHG9v^&%T_V+oX?tt`kjfne5uGMMT@j4?bHpWGn3_kl&PuWpt{MYHf!PxQQ{4>DhJ> +z_8;j~y*X-bFC>XmWB1FJ=MW(}|$-Wy^io?=H! +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 +zM2gR;6++vTNrYxO7HO +zICMKUa^Xj3C!OzKFDG7SlHOVA#`=}i@qmB#XOi-EA7h%AWrt|# +zR*kgIIR3czMUn@kVhH|vkvEfr9Jrgv!6)E%KR>q~@4(rq`~%Jr3RANuz_hhy*%O52 +z2njpedp)So?rgZ9PGxl1WJ7Tb+p}65tNoBx`3hOOgYf)o&6_81+ONau_Cwn}-mh0f +z*!p+t{KRgem6Xx2O#jX5^>X-aaQ02E_Q?C}DVKqPls5=29U(4Vrp~Z}xDUsi^+OfU +zn_VSQ45E)RL>z<}IhdP=3x1X@MCW#D%b3 +zj#2*I)wJBgG~VyV!#k*l`h3?pkeS_XDxL2DZ>3eLg6WSKof$N~>;AZBH{WDLey>ju +z813*iPp+J2cqaVS*zM%CMg}(!r@o;mB`koL|CsX13KBW*E$kSJ-T+KMe!05q2 +zFWRNe`Xn+D8FJ&TjBM%@HzF=NLXq`d5V~KY%3EOo*L++x|2m576ZOdmw{YKqW>vo0 +z5_TehW9I?VEh^|0>*Dn*2hlI<&AGqh$nygS*d%~p`OhT_z55a`()D(x8wNhKkBt{_ +z&T99CfK+QPJ&VSg5-n8SezD&7#q)X7K1yPslSj#~%+?VP5Z(|0FIl)JHg-zrpMz?g +zkKUTc47&bc4t6o-c|)~72wA1|w+$4CP2YHs +zRKrh`tnAnHh6!H09}(q7-zh)~Ac(B8_DG@(wi!Jjq9Y&~ycNOuNFWA?iOECpp*#-{ +zvx#8>z`snu@^ebvLPr)Jxz(1d +zx}|Sdia@j~28^hfHMsutu_D}t;I6?vW0ORME-jJ&#^qwbJ&t};iHZ%&Mz-x>T98Gq +z;}o}DLN*?)_>3O`Ru>5|)({b7_u6q}T0a!?O5>yndE&0=EM!Jt%!5;TLS^7^<*f(+ +zLs}hrV~9!hn_UiTwB4#}SvM75X*r+xt>?je_8rmMoQ?V3j@wzAR*k<;6)6hT_i#Is +z>-ROdjHiVV=hB;Bu)8>4AI&&b)*4Ws_1SGcEI@!nj)J0zOJm5T$Ro@<)~F4kBgzV +zKj{!^v8tAl{V4;m$FZdzPY<6*=+^YXYPc}+GYcyTEpGvngb^7j8HtD_){q)9>m5Uv +zDnUyVcXQ3C2HSn>KJjf(qC8RgfMl51S}!HIif`CSo-kfMqqVonX(34bKvzzR +z<6W%CZy}!$*5L#n;$8o5>#VXgVB?1dJ=HHRYz}S9Fzmbr`XxxkGJ4i +z>8W|!n?$PBPm$(Jr9*N63+c9A?$t9P!ycb5qzr_Nf&1NH>^0peQF1!9J)ao_zpG)T +z6=en=WryHD*}hv(zO=8Vwfy5RuzvIQWbvU+fCL^`&}|$;eEo_x+kMT{qd{SdiCPB! +zTCnv}P3lKOX%5n$f*`;ZGBn0f(Z2C6eGnuXra{kUp4EHJORADl$5&LajAXK(o8PBe +zI%x-|6GVf74#wd&#(d+VnpP7&@TlWr(l(@oV*V}hPRZo-sPx&9Uww8Q*QLJwd~W{5 +zRAeVG#Q#^}VgKVVaM~T-8p)>8pDLgCmL^U_4L!QzY2FT_UwCex8>}10zu{>kj5G*l +z8^c0{U7OQMIPgB;e!Tu(Ct5%hW +zDvreM{0;>7L>qr=E3CLf7)M*=^W<*q)92Hxb(B>dsRU7dPu?nbt)t4Xg_GlBd=t;`n9xsf>@tt}xo~k5dWV+yD|1+v6{l5tu*+wq +zs3s#*na(yNr3vSNGL2V|z7tZk?*>cdqcBS)FZ=4NQ#2_!x$cn +zRk~AfC5oJN>t^Ssymf)fldRogCwHUWe!6Ju?IaePb}-IpSqLNOeA5U18yNa|XrA1% +zVr8NG`|c3819~|{xbK=8?mA4)3nSiGH!sBZXaMW9XFJ|jvI%puvL!!mPq)jqZyQ>V*jj$t`v%SN3yBl@HB?H$obbCWC;pW+jB|B(HST8y +zrY_cR*b~DY;do}wj&6q9ZchVbZFf>fW>?jX@zTbC@>Qzo&$Ed*lsSLSVpK#%$@@?R +zwuf~?fQHYnE0c`mc`ZWWq8$8f0;kypj{RKW3-yPR7Kx%ypXEk){+92%?rCG3~vlGWHd3C9SiYW6zDJLSGRgt +z(2nJ5Ta~#Sb8VXq3y`hmqZ)&o*mBQJ` +zuV7gQliv%4g8qS=f0#>zCRq{SkgqEJ%jaTGQ|JWf_DJs>B46Av1+&ph-e;vc-7ajI +zXlnU3m`@@_)&@=-MAyM@>-A0Hn*lr3Vr02-TH<}*29h31bv6pWytviBO0gi$Xls}$ +zI(qIma$ +z7eYBMv4^L|q@N!?-VEg8h$Z&Y(?%(707TGpltVIdhP9&T;pm2gjzvYRg9srd1t6#@ +z7STnswr +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 +zi&M{31Jb)84G6de +zsV)1=VzYqe(Uy)3tRfb%U{fl3u(3K3$h1*@YC3@E8P+^^*-q +zhvYAEl&g76i}W(duV~rJ$CmRL&{`78_*$8;`%xXtS{)p*5fY*Z5;p$&R|4C3Fw%3V +zfaavB-9n)<4Jfv4^3~a#=7^1@#(MjQS>Jd|qGs3WW`y!~7t5{fe3*?)*%K$FTj$ty +zy-YqTTVX9t=by)F=UQ{7u18gT-W+<` +zI{xI{c)@}z%7H8LfiI{i|1n^O#;KhsdD09?)a-!U_UTm_#hD_i44qeq^rkMvvKFXj +zJh`WF>_C%*q?70pp0kZGw_%1zET%817|Lnd!M3|K)f?dIF6u#o`VQ4_^Jmd1wxUX_7s6iFc(JghRQRB9E1?S{b;z1B+8{ +zzEg)!Xo!y-)3X$^4}my_qZ+@~N9N65mpW1vM6I%I)J{h!y&!LJ>7ac{%WpdwHFjh6 +zc>DU!#Gs1x*D(?r(=CBS?P1k@gbC3YFD})XkVj7&n*v*if;EdrpbzNK^|{EjIil9~ +zpNT3)S)YQb%p$AvV0)zDLgs>_FYO2yS1(MF#pFWth9*6R{>G~N%`XVvW8Jlm^FzHt +zzOU}{2s7(SIa=o28b+S+GYB$gZ_j~xCKpHh?YFYIO5&bw@kJI3RC!6D-$J%Rl0uj` +z^12Cd1u&AiS#6It2?e`tTnl%GbO2!3>d-*O@Dde%!(>fiZOCp5G8zFGdQbKwCcK2+ +z+oft#n#WOV6aJ$E@J_YC@!Rp>N!8e72(JR%`K9k~Y6Re`4LGo(tZqOoB>r-h+Dd{e +z7oAPHm_K52F&zl&>qio2r<}San-NSuLXMJ@)2!xEGyofY{v2aK%#m#62Ep>7$h3mg +zuzdZ}uAJp6#Ks=`RILP8#W+r&nfA{|Z@|P-Qj{NoHCkAWfPb@^rnDnuA}L0vB9GtF +zotNo#Y12b&tsg1RJ~{YB81FJd=Cz7>N60^$s=BH`##Wjm`Gu6e?Nl|{%FQj^hRMFW +z*QbB}hl*Mu+7_F;B$#>q13VOK5o840h0Msd21~j4!v>nrYY~n8%Z}mnUDFBb`y{wN +zmAh6i7ST8Nd$kvb;p&wOJ@gC1(5%32g>3n5TnUEL{EDk$*f1>d@8wjUE#n~P*vaub +z4VJ7PFhjS7T5B5RUYnVPR&r6W*-z%rR?b&MTMAVgg8NOIhzXRBMn)!+T)E^;fw4IT +zG4`Qj)0Pb4e31F%R^!z9b$*lH*+$bq(`KIaIiEn8ckVK@h$#(y2NEuPqBu6b68 +zWh{z4qMXG$gs0X%Sr3Uf_8%N>Shnrl7y>p&^)Q^sA8UIa!2FQWixX2{gbuH+rK}RF +zvsIk4>#@fHW>Nu +zd@!Dl`cAV9n8@K)JaDXA#gxekr-}?a57TladGbT2v)frUJzLde$+lxAMZCua)lw6P +zSx66QSYgKwuu)!J-t6jg1bG^VkM>>0t2dGtdD7z^lQfSXF0HoyKFO}e{KEmiOMf>YDVaf!8z7o|O@<mkXxzCpfvkVFu0xrtf*bt##tnU}w`VwX!ikAnkM +zS4qzg;CuHhPrl)A>`uaIVJr&2Wmq8~4&LCz)}5Ld0~d9csq#ij&xc4%#iS|8a2ds3 +ze+fbBxRbWA@^Fga<3c5zHa5tRqY)@5b-XK^-ou$Tz3wV>L@$q-HM<897_Vdkvo_&S +z#T(hKZH6TBNl%oBTs$$d*5R;rbim9+%x5H6aRxI7C+9%M(eKdEnJ>dPoX$4@ufKL; +z*?z;Ns+T%cjtz_dl;dvz7$VGAw|yOhk1l$LN@|s2Fr4)ktPmMIKiEELf3TJH_}H^u +z@n{SqkTY#5K6oKOGU;iq?&lysycmE8jNikzcGEk>)|cnsii@eAEJYHEL@uf;cO~Dn +zu5NTpw6lI-y)7jerGmr6P5RYuQen`cy__NzC`>{R6>r2;X;KXiB<{(dG)59s!2IB> +zrOauh_v2|XOK(3wh1(6ky4KHa>0sKR@i#W9Rd1iDB-CD+osN2^>8sVR~yiTTrgQqP*5EEpF97o#%}#{W3IQ35(Ewl}xU*{TqJZD+WS +z*n5v|@67j@47|B1RF};r=#C?@F|L!D_oQ#NWh~JPuQYJ6?)yyIXMf`IF1Won0b91w +zHZZ|Q2+`u)Mxm7w>_D6!Yy28jc*SmKO>B>l5>vfwe`qBkPj!bbuLmC=aMlbfUgXbf +zG93}~G1NS+^N1le)M@hahRmCBORJyx(oOMmse61i^^1_-O-xz0net#|X68r3N7(I| +z2dMp=4Yib5RQmoNy?ur=p=5ye^b;G=*QY!-C(nfpoDsv?L9V*5VX(5wW;i@Jwc%q63V(Gkxj>ajbG?b^pr~DOL-Z`m-E+>Vv^;nh5PYf6G>G +zjG$E~x#6iR|MA)fcq-Oy^wa}2^9P{cz)tS!&~^x#Y=OWrH-n&z1kEupBc+Y&q<-}> +z#L<3O+(H_j^>d#c3DQ0RBgRf|)?tY|8Q3>0^ZtY0kuu^siwtX +z7O_`no4K-;ggREX!3A;`AWJrdTnuSBZs4FCn* +zujf~ueC|zXBO(a-$Uhvd47kHYF-HhOV%I#w=~8uG<1{ptyd3|$ab*rGWQDAQFK#=> +zM%?IB72rM=v|k$GR|5z`)n0#MYgN;P$Zkg=i&SqGK-S +z-JM;(Vf^YM@)o=+h6p(dyA``8(@KT9D5}lFvG(`2(?~V>6l3MW4~6;}Ds}QdxOX`m +zI0coHALbeq0z&9xCw-L(K|Xshnr;>Y;XAgbo&-%@MY0_z8nws|T$~5XV7TR(WE$(2jX%Ce@Rs)+qChMSR +z+f8!H;nfy84_Aj+%u=A(=uO^b9p<^|Qa@Q$MqRi`XLo)b=h^jAGpWdR;K2vZI=Vbp +zdrn*ENgp&~R}z`j-`UjB+8SXcIqkcN5aKZURXS=GQ)pUznb^S%)iwoGY0GE)?FNkP +z*9GOJz&;j%|xe10oLF~0~u_msVI>)UpA{TGd(+se+d +z#oieXn@|<$x0Ma%byv#{#OgSHB5(E6n862JcAkV+IDU4I2k9ZhEd=+7%r5Gw_}m3v +zaJK`oLMVFqep)ad$B3Y$CH{6y47lGxcVhl+t?J+bR6;?f9jBtM?G8=5nkcmlbP3Cm +zEF4!aGD)$zRN={~inv*$g2?&fz}5ociN=Q#F2*PPpf=~{n908aGr#|YSPTW0hdW?z +zZx50?N4iVhUuDw@q|7w%pl@u}Y=9aflriqlMA33BXGrhpM_gn*zGg5L8bghXCqQOU +z#@GME(!PjtcO4}oLyaG;sy%1>wljJ>0vK%&8xDvCM`~U>tBblwT?`DRj$UWbD*fDX +zNn&O<@oz@DlgCayGVT=r7>n!6Z0|{uO-RkSh$aj~giKA0^;}@i`^V&|tuheNxS%ATp?W-+j|Jpj6 +z^?96Wl{B6E36*?(l4r9@#ti;XRlsws1<3YP%tk-h4*iw`vA9b~KHk<20_|)GRI$iS +zA{ELqG?z2{a2#O$?<&~@izvO`2Df?X))hAHvKP~9dQATjn;L#+B#l=ld!PBuw*GTG +zbq5COq!{-6x%WZx*`KsbOIs3PW!qv|drPUC8r_&B;kr!c85Uhd`kSyPnp23)Be2?m +zi#Yt6zg(W&KVz*h#=Z=)Z0KL^)l$t;>#o!6;Hoatz9SXmMfY?{wYrYmta2H&RK#zT +z+kC@(q!8&57WTAzbdPIVvYja14?OKZ)L25U!+P;(!%faTc|eNfAG6Bl +z`t@DfAj^LlO0lb|x5Ebm%Gy35{wLW?E=fH7z%`pF|FvPVs>du}L+1q?pe_9Yx67|t +zeG;r(EqbU(d_z5gK(sPfR!9*BW(s2P?A*X2C7I}S87Z4mnG(UmYI0i#rmj`_^Z2~1 +zsY4~JBw{BiLXO;O6cHK~&ROh?GRSackYj>_KM|iuh=&^GY3yGTT5v2~L`LV6|a1oisR;5=7ZfY!UZ{9wd4oCcyvR +z%?|rgx08@O-&^GeayFVoFzcmeP$C$2Pxmfgj~~pnv?$`yDv>Sw1eZgm;)GXU+y2JG +zh#4)nUnG`c9xGsQDRI%RT5#q($em*=VML|}m=Y|0oHIu%f69$V>F+-l +zBR0s4{)4?Fh@rHF`a8tmj3hp6{3@EgWQd^@BEr$vr;D0kzJBHu9oH55abcMmIF;+i +zG(Nn$JhvBO%xHhj-pDkk%k6@ZBEWADX+CyUryWxK5E3U_O$m=+CZrn|D_}fn@;p^r +zZo+<>6q`N)M6*r-m3H1yHJ}*<1kKhxJSM>)wbTGXq0J`@5#ybW_GS|(Io+^v!@_7N +zm8Fa|@7-2OthbaJCOVoRzEJ?EF)hfFez5}@ATJt0;yH-NOCM0EhufXC%wX81bpJ%uc!fcwG*s=hPLC+I-X +zBL{jF7yAt?3x7SS0RdKH#LX3We<%_|WXy<0JAC$`DrbW^^D;m*HOi{H(wiXzgPI^d +z*s9x=Qrru7*77-!{k6xB(vU^|q9uVfB0UZTx*2)JQ}bA6pv)ib6H*cmcfuX?L0$e!|dj +znl4xX82wK7`IAn_zVC$kJ=qljT|!`pdKuor<6=B@H92=ULyQGIW|VU;WTY$u#sJbp +z31;K~_x{F6;^*NXdH5qY!qAOU(Aj-~)9`*9Cv==x{8278FQp3bOdlX>FOw`hgp@)gr)1 +ztOT#^%!1-WBQZ|0=pu@XBzvsHcDlb*fv+_oP&S+fKwDn45+m~+^;_PLq!_UQRi*hn +ziRro$y4sjnvB8jVT)}2^O>2okN&x)ml^085g&4KSpgjds(|pA?g9N8JW4jFsdTZG# +zL5KGsh=%v7;vIq?cykqOAS1U$jG~UoTP`SDRS?_mNDZzB^qPH9#oufZ<$RA*@|PG?ZeMgz&v*Oak#er4u*LoE4i*g5otU +z+70Vv=IZ;{^xYjlDDabX6^Wu?M4Xx*qDR_#^>)vaKbNoQwX3K30{eO>d#z`8L>6Ve +zWNG8!ekv|_?Ph1A9A@7N^U1jFcbC3xy9MPvy>XKSo9)t9gIgpvV?P|D4Qj55zFuI< +zRvLn#tz?%qOum#4L;g+P`rN=SjWd#&dxb{`exJ6UbS~W#XqCh;`Z1|7Mbxd +zDe$y?3X2jJWOA^$?(Y5GmCF7e{s#V!wEQtiUuB8_!u)>@w*Mn?Qej6c0|!%UtA7Ye +z|F0SPfd&9HsSf{Q=%?WKp#fZw{2N0*fSw;f(*M7q=fBmPc46W`0F +zNvpL#h(J3XAje$72trS-iIUT?X)oG@?`eWy_yWIHj!As12SYDc6%0S>x025<)*!I> +zuwXa%+xBxRyp4FBjQBEYhV})K<6;KZLk~1IOJo*2>orhFY%K(<7{zb8L4c0JA^UMd +zZN(;F{kDSVlM$}O6JB3cR1m=%RES_BnwFnbzjSAdZ4U^L&M%HPmehW@8E)?}W_|u` +zRyt_Q#kS(fRIp>Aj}^@@x!6WnS$(i8!lE_sLcS7h8O)U&H6(yxmTZh^tmWBE9m99k +zcPE;|u7d)%Wl2Y7$!}?n+hX=M)B$@OIS@zOj7C-Ify#&84_w3UMYa3o)?24>CgVz1 +zWv8HbHYK=S65@<;(rBh~1{CUiCq)GH +z7N2vEuJ8Ct3VZ{+!`Mv#;in3@WUoWaZOqwf)tN$FoZc8vIAENe}Lxkf2 +zTe}WSgEg;>SAv8%!F!yj*^&tdW++&TI=rQqy0dr-uG*r{CGJ-{7^XY1BM76mf^omw>F2CgzE)WYb9mF< +z5+>aUGjV;7)hTV#dH$DfBFrXCiWAwNbXMhcvkpV110yAy=O}s|Y92Y@n1|YV!4A#$ +z7mu6b56ZrN+~Mo;Sj!|%n0s51TQh5tv`~LiYDxMuQnNskFOj@mz_*QxdI9JBBY5=4 +z2mAxj?f(O}@V~2SWJdGXO9G(#&%yow0AItuHvb93|F8`Ik4(e=v&zQ*jA6om$MF9K +zzy;ti9se1?tN#Yzl}Wp`-~RxZznc50ucvk%o>vCZ#Yf(L8i*&ZMK>E77}uaD$*LAu +z!)@$pEGhR_?#d5bQIdYaq|UdQstLmuBx7sVw3z_1C?YnRttiqk?>*1lv=&;w=>WPL +z(iE=f)SvUdKA-b(xGnyuL_~3!-DFs|{SBIGlEwT^Feqv(Isu5~Nl;QcjxZ=qj~3pI +z*m-A(C`1jA5y=~I*o<39eguS^H^pb@8iO9(I`6rUCgg&T#_6|7vkXNRL97Jy62y{# +zKlVr&jHc{M(KG$@Rb`ak5rzI~PLbCyLqNb%3EqJQ{2Jvpql4YSz#K|Y8UmpW@K_PHSA%UbH$K@7vG15yUm|Fxb)uFTZ@hyUD +zm3-tT}*0X5hE<)N%<>QE{ZO&>m9AP$bQk)5y5hp4)X6oVKOCWo!_B`IA;GwTt6LHo#ah&Q{2{j5L@M(GA|z8AOu3=u#9p8U +zyk?m<*z-sK8M~+eMI5MqDdNbQG94QL6lZZaz3!-;-xBhwR-GYboxFq4IB-EiOBu6T&eRTx2rNyJgXrdv(=Xrab#mFJf +zPERMKUxk)f_veyXTpL%qCs0bkNC5uKj9BunMOA{+M6ORE@(U2RP3s7q5G{r`waICfkpgC*1MX#7AT6p&!XS+4Ne|ILQx=?m~?v>jV_tqMBF;$;Bwwh +z-0AaInd4!Use4C#CU-;!o7e&cVAY7dJ6|%`AK6b>IJT9i}OCSiMWc3SXLIV%!lZSYIgY^_`3 +zUSb`}^OU_7VHI>slV`OrXP0&sW`?J(mw@uf7oxm$#kDmJ-=ogFQR7bhXNSo`%q?%QK+yf|mDbrYC9NF2xz@4%^4 +zsTog6n#3B0Z}LQ=M{B06YZXH=W`Va?iv|3t!MUPK@ovy4S +zPNwO!&0S`7iAjlaSEtizSzsQmWr4v*Kb7YXnH1T0{=4c3r?m453Bo2PtGFkSjT!B# +zPC`y*8e~-UH{~KTa_`%uf{1L_dMwo_j0GnK`WDtWi~AKN$CE5p1`&ZWaSARwREfsf +zO6j$sXYQ&s<^vm7&XoKo*DX{fR6dASmcH$%Gf~2K*X;B=(9nR3cns +z8^44Y6rrM!onc&U&T-*ptmj4Fl3_uWzryEDP=Ut{^NQq7tn!bz`x&oeOGMCUGoym~ +zvq4pMm}Kzv_&vDgq!9tP&BdfO4*gti$UZL96x`%jH=yW}bKvv1;2}VO7#5tBfzc +z$wdp3m4*|LVdtd^_d_Lgu~xWT?F@;P%l)1=lJqkG`?tcspz`^vt +z8n_%R4J||sElmZ41a$tppuzvWtx*jaKmV)004(HP2DteD@)w5xo4+7qz4jXw=*A0t +z>Jy^<3OUd~$#mu(9(vjIuTAC>e^erYR1~)UiU^c#7G1eKe@(ZhCHX1`1kE=C-{EjJ +zTh!>_ +zyKw4c}QM!kNQ(Y?VzlRLxrg-){#TPlTd@BTbuRx-F!mOC!4urI^YD_lDXbHsi2~v2)nSD*SMA4IstIDQ(EI1~y~k!J2g}R-_ah)#gXu68*0tF{~nyD7(w?Q`A&_AOjS# +z%7&jMzrMFYDtvEkg6M2<&BBEtWNv)q&S%|7BAkG^pv(E-yCK~;`^gjyplT=(E4iyi +z+2HqoXa0C+^EYqC6_y%y&@7sh_#T@NhF2vy{r-vF*=Eg&HIwr$&4v27cjq?7L0>LeZ8wr$(C^{)THd-gu} +z?tS*TW2`yG8gs4>>%*KitLj(vJQW{!F)i7WFc|m3d#fk2Q^^L7OqJCh=v74^mInpj +z#_Ljm6=YY$8K$(`=Gdd&VUg+KPMmmkq67HUB?LjV{i9Vyj;%%4jbP-C +z3wBvJXnIUFQad9!>2<4L7kXx!gTypA#WdhxvAmWszZ46BY6O0-_@<>%lt{CEzANlU +zq0yhkh)sZn&>tg;hmZQ*Q}XG4>Pja-<}2`a^Y2mMI(ax@=8`S`$K;|A{Su)VNG>oj +z{t3A-`%fwVkI6;7rmgc1JJN?AkX*>W9)q#lvdp5TY)d-jqSBAWHv5fz^{k#BLP<11 +zc{!!&G;l!p0d|MlP+w{e$kL-b86e+&M+8~Nl1kxQlIVpS{7@u^O^rkvNEuV?mJE4< +z!8C|tY=%W;Z^H%~H~9hs&Y1EeXO&(x%9ay#5{V|`v2AIjv1oySa*t0T9bE#S1P5`< +zDv)n-tJKmQ>>Y94%~0B%yf^Xvd3y(pKTl8$E{sv9yWU4njPjd>t9Cb;uC6ALm93yD +z;a5fZx(miS|9pqtMb43Yh +zs=02;&ve3gU3#LMGLSpeKXlvX(N@)#jOH%~ggS{D +z6-63r+>4M>Ai>sNz?~36oTof30yH=BdsYx`b;0#hB8ZGbAW6FWG^HD0ixp>Bt2O)f +zxRpUsa4<(S*5{PxW{L&Air_lGTbf?=&L?dSE%IZgYjb#9K+fohp|mAZ6CE56?^QoB +zLAQMn#PTu_t~X@Gk;RmAB}t{1zppH;58DC_sfM~KSB2pIVcSkj7@8zK +z7AMg>y=SILZHBj*Iocu#eLp+Jh!s;9Aw)*}T3`GJ +ziay5H@bX<|jh3LlNP(@2!@aX4hRFaY3*3E2P1&%`mS!K^c6I_O5!s5Y#)`p?K6Swd +znwr@Iwze3RI!!(~@rMWjl)aH}1dbA!ms&vR%%(M+zVY5FCxjcoN +z_p0ZUh`kTVbDp)F7*BblQ(HbaySylE)z;fuIT^rWj+?&L%V(I#^AbVqpmz=00xCFxFyV3BCt#nU5K4j#N^=Ij~`he#yKLhG8?2H~e%m4Mg= +zOtneg^R~FTS#Xs)=MyyD*SzXl3=;L@JeDocoMKX_T`-I%>NMQBV@`FbkT?jija*)m +z+;>^5s5Z>Mko)i`Oga;;Wf~(~R2G$kgi(y=3fo+t+y>5Mi{5?fUIF#3A2hx+j4zB+tMfrd7ME(z+^8fCM^!^7)Sr+;?lCt#?s^`82 +z5o*j9F#`Z;mZz4xR3VaJ#o-!^CfXsH;+!l*hlzNnc|7Z*E9m-4gKFv*;L-Fz@%Rj( +zcAUy9`^H^c6{>)UQRRMhe)Zv9cU9d@92cQFX{0w`O4x#u-Zc+BkwdnX!0)Rc%1~=B +zQs^asC!LuPl1<(jRN&*XKc*n7j6&Xy%teu0GmwFo6-$qq=xCbZ=tx4QRwaK`&Q4#u +zJM6=(VAh^Z8g9KvN3T11AI1yZcN!0!#^+~J0IF_!zS^c{O0FJwCbR}Gd+>KivcWP2F<|EEP +z#g(ka9ULvxGX%-HzaN6wC3 +zH{#KS?vK1c_blBKnhlaRZxTYNHwR9S$L2v$!s*7u? +zjR#N)Ztm`st?>R6<{AR|tU--!?pK1QaWSL-`8mxks4w~hFe4*CMXk<-YCC;PbU;S2nf$VdP1FDoLr4v0D!*{6GE;g +zmi8(@OT^U~c>W&~mvxOz`&D)%ze#|jaaG&$OLg6lu9V<(nQa)x*QB~iFuG|JrpPUcK$HY*9rASM18c3F|_Vp@E>iP0SlNqqKj*cK&n8(moh-81^(q(E2 +zx{GX$0i-F}y}qSrgFmKYC{^ifqY`u6m@w6~cH3cOcPq(u+ke4YYY1-<&PT^y4q+ +zc-)c&stZ~K2moc7?Sa}EYqOYUqyFjT?I#_)UMRaWB`9w#t&05R`u8LjB|_6iWGktD +zk0-qpIRtUUy84!(l|5u4IDY%Y07L1>GG#Uz`Q|cF01GGT!#oB&DoI?X&gcyWxZOyU +zo0)1Q4SUz>`i}dU4%B^FH!g|&KB>;`;0zgalWL0@_s?7-;WA4-=VdsS+CPce&ErRj +zmgoK23M> +zfC9%}>o^e!3`H^Lyn9MntF*;_1;$g0AX39Jc%7ac0$(oFd}1wr{oRG^ydM!f74Dk= +z&9pm|fjIwFp7LxD6rzk!CQQvQ$#2deNGQXdDGhBXzPV+u{K8TxP3O{$uDyvTZ}%99d$$_@PpmN_ +z;V&eTFdk;ZJ=X~_7coqDhg~T!Ou&S(no@sM1Yp@_$jr0?QyH`ZuaTF$9b~o?#&RvU4 +z9x&*iLg$bk0*dX$D)uk-#h9>fwxfzoJO%jb(!sXP*tj!1Rym#)FdEvfPbu5%M05B~ +z=SmDU1i1QVB2kB-*<$Tj!n0P4Z!`xue^zqprc`2?-1JdrB}BNJZMcgLB52((l%$v3 +z(tM3mkBg8(!C?U@>@l^guQxtfM!{{f{H^<0-IuCh{1N^@dW3N;Be_fZp>It{oAU|U +zO|WD^c;2{uTLGF!VZ;0f+ZRiIL-K9;DM;6xuuJtjf$z0o29X-l!>XGi=~;RvEg4M +z%6|$F=bE+(xLimd6O}0}-2AH2HBzv)#~0FkO$`~^(C8f!6J9menTr$42){mFa4%tp +z#i8NREL>X-OZCMwD!_2_a(HAG3%9_3-zDyv|`)#8pxLgb(ev +z?19nVoXjvbP$C<94i(n;<^}1;)Ena2b{$;xZ9NK#ZOg-`FUZgD^nQ!Ps%|YWU>Hn( +ze4JPUzW1X@fHz40Cx&SVC>ldiTI&}8vsBK^3JR(DEoI3kn)`=foE`Sr+afqJ4o6Dpt#ri4ru^)rUXrOj) +ze~!3V8nM|uG?G_8P;+lfE#UFiYHpka;Ky+D +zSIoRY_!{;#MaFuST5*2)UCqg~k?xc?&22o$bGf&)_MnR0LZwSBFu2#mDu;7%5#O9$j$AP{*Yj_E9QR{haY*V>`2+gKc}YiM3&NUtGEqf< +zE3=`Ug|H}XrxUU0o=a99^A;0p)=_eZ`MoOmRFRIqzj%(>18NO?odb!$W#z1t((C!* +zd%>MrtkoYRd0UUQ+ERba+D0ihF9T)UiJMOw%Z&1Q +z=1HB0_RE{+pyLyTVCbSI%5kIgh7+a1HJgM_!OW96b~WCok;^)kL$pg4P*T|TV6jnW|~ +z?X)g+Eu^A!$F49gj_d-zA{CSaTDFN66cKd>Inq{QYPOw14GMFcwXRQ)`5@ +z+4f=aXWTg{!iqlk9izdL2%gj*(VJa~$O&pd>CV@0rC;_914J0wQTo>wb$xg1+mOzr +zc@)@C8+$lPo1qSEdwJi8l6qit!;y1b@CyV0AT0MI7P)*~h3PayaSweDE@b!aMP-@? +z`NGdk&M^V#)D#nyi4KWKSpk4bQTaBHJ1Hc}n40{0Mjfniinhf=nGb0(z~hrx0xee5m}1iv(%h_t{cMWo;^mA$slp{^jJD4wy``m>W6FmIr}a?ZjPet1^Cj##B0Rqf^5ZQ+Fn`FgOW +zO5IyycM|3gI>3kC-%sHOz3`W1K^PBb{w^BDbH0n+CAl5+M#3FBYCafq@B2IknpdpH +zUv;whl*b!`J7|Q-MpX51eV`|x_ClbaMWh6!E^%3gHa#poMoCEYs2-~@JbutM@W-t_ +z(UlO9RHg(-OBVOE)>Y7h6HOjEx3&37dU({Z@*kntQH`n+^9`dUzB$C8VU;aDaK}$J +z+;E&#wURmr7c`@~a*5PI)ea10uqo?&6AFVWHp}ifFI8(_pQ5e0IF6rfyx3(nyU}(( +z@_t6EgTHKQSDD+?*q_fHjJA9+$8H$)s*trDDA0x6^O3jf(9;8~uh}{Lh@P@LKC+@KwnM=dL+{Z_iTAkqpM{YpE9LWf)+nVcWr)afUoTti1;8AN0ae%FsdMR3`A +z*})SbZN2*a4CGrmHr+aeK2XGr+NeajoAv@e?_YFppF_0MbQskuVPLbDf-K2lA;G&s +zmF_w-nM>X#>?a9*AMk_+TCH)p +zLd3gKSd-y^a_kKMv=8VBcCh4M0SAl>sRgu;S@w_~awQSh|62YJU5=~D?P6d8$< +z>S&wGR${egdVa1M?F}RqxpL49=Fw*IG>E_ZY+>yKS_s?O;!d<@$rQV3xE9(<=yXE^ +z)ke>5Radqxhr}7h;~zeBwMx^@=!wCO-S?>*v%dF|6D`ZCSSCs9j1lCGyX>TRh$DrQ +zwwk;|VxBDv;l`ekwCu)3`lqz3zl_>`uU=Ht;YK61t%|l~yGZ7VeuB2qMKyyNPp-&n +z*F+#t5zsIHFz><8bux#a18Y!+{45qn5R1d>^pIkHyKWbx>tdtySc!}hmcTac;H@&n +zEQR!jUk~fthFcCp(P=4Ao7`;x&CFaM5tq4YNUHR-JY~WrAHK}jm^2afLYG6CLFd4B1j4<#qnlaYRp;N?w@c)px^a&F-NDZgHB1TCFrf+Pz6b3eCtskj>dN#eCb +zvC+|`N#TJTu!!`ibsY4ye!+QW;}Pe4YM;4lv=Ehof#TQ=5~k!HC-Yfq)s<2Ma_P50 +zZe3^Y@*?`8CM!AXSC1DIPObsq@gX3y<=wpW-T$fTi9_!O6aAh1!<_5^V?JiUKg3Ex +zzCJIzVr9>8e#7hiNo?LbD%`waM+=r75ufwWwD3S@ym_(3KV%_X{72P_Ykmt<78NLmaXz +zOH)A;`T~X1i-|h3^_E|g6tL|iT&5#qhdY4}+Ngg6?fAA(;3wRyk&mpyv}hCU-x)1_ +z6+>fJv{ya^$tn4CvS3J_&`9pQ@Bi +z`D_fz+C713tNXYfL%*mCG9TBlz4f=Kt7@3n_)Q~1y9{`48$I9&LtGV@b&E%!%g-7v +z8-rvXNIUE2oTWwG8R(yyon9MS3Tf;1gqZ!y1Y~e^xX*%0o2IEMVQ(|{} +zkYK6tGNs;tXyzjulf=2)&ly0U-6G?5af$IvvF>e3HBoe=N={(PJ+U)Mu7e>Fz;1Sg +ztG~D`kb=_gNjl582e0#j-BBMqYso;DvdyP-QD6w$k0#9W=Oy#9JCQNW&72_-XC@j +zjG8RoHsc#}Hju5Sk3kor(u)20Aw|X>Fi?CQ`l0LJ+Q!`>S|V}>->eFk@A({(WBCI# +zwZSRYZ*#^GuthEOmGt|={I#HiM;`A<92T$OxcTq6`F-T^{eLd;Kpg(0X|gBjEb@50 +z0wmaZD^BK)kyMTWVQB2k(bTV2>`9F51s;(>x^xy{Z4A+NpO5qnkbl=2DgWTJ$xa@m#c4~d1F +z!5)U0#Iu`atg0Ovb#gl|Zs0~`n8&CDA*?=g=sA_0Q1=2;GYfKagjtH`6}3GLsv|SO +zq1JX~hc;e3Jkn0QGWMBu@8{^@okd_iaqaxWfJ~FYU*@}K)s-OA-~)unX905V(;J9@ +zIyOy}Z7%ik{0dj)D4_o)H?;p6g@~D~;m#Xo-0fC*l-Bi#CqV~a(k9uefMEG1d&BVe +zaKzkKc2oxj0>T9OPv$fKE~fsLGyRL+Z@HSB{VF3|`=N#d{esRJ=~85QJv`d@3saq7 +z)d2w|iY;tBnL=E;NvB`JIlE=GU4NB|XzHG~Pku_>P5p=jh-Ij32snQG9gH&o)|Jl6 +z^Ll@$4Siv;!qCSPH(P+i$Se8ebL +z4E=drL?=dnR;ZN7f%j?UUaLvvAlqLgafly +z8l_&=to~V4te?XXs8Dq-23_dR^ih72bPl-iU${vSz(k+%<8d&``dAIQ@J{QkC${PZ +z|I}ZDdVbAfncV77DX2f%i2MCZ^$f{R%DgFYqLZp>ehny`h#m?=$u>fCsB6tmn4U@+ +zvmnS7YSh>jN{>&S857zFznsjl0@P=ON+XDoYWDKu!2v{93oDH1w4}L2Fj`$`U4mP| +zdsrezstUIjWK%4~MUU96g-=QaT#k8nsB`du_;al2B{;b-ms4L2X3Gv5Bh4oJwRp7K34S*d9kTwGV9q#4 +zOD?{xk{l#|o;KSZleN{^Wo?AKE@3ZyKhJ-$(p;uV<_06Ik*&G*7dDJB6%-l4#zhzx +zW%h=Gq1?I+o+4U7jcHU_AfGe;|U|+S{{O@L1v@pCnCIgdQMfA +zJ+4t#iIzDG@sowMKMUhgQ{?`{ciMIn1fE=Cw|z@*GkNuXsiE)IlE2ifOrVm}9U-PX +zthI3Tb@r}p@}HR=srju2oUOA)2&PAyj%No9L@gWZiDkRPuOOtZ2m|LENTpM3~V0g^6K8VWtmJZt$LO*T~ND%gwQfcD0GR_;xXkOkU+g2PT4p8PgLQ4?c_vjCEo7&^cfuf}DVi(u8-4 +z{Ziq|`r*$>(fkPyAynC|LG{$&BV(kMdJu@G*%;L@5G2w_wA2S52myE6lD8i-@J`K| +z4&Sv1;W@e|(XGoy5r6&U&1}Gu8V8yUU2!G?s-t2uW<9<>^xuPZHtJN(44?cikV +zUV?A)_CxUYc)X&gTVF++fFDkBWPRA3FtGSuO2#tjPv@;)GGGWXhyE}h?zXcQyV>m; +zQR&uK40fkQMsrohC_A>_`d0m;kUT8cG(4y-^f9XzAa%)XHe-2}VfX*gXyWSaGD|Q~ +z-RE^mw$Im=^~XTr#=fnlWfzp6IjLb+?I`3k)HL?m`>4kAr-G997R2Od+Ojqayw580Vg1G{D>FS4AXJ;pG*Z1d_2RqckE4#IF3cXwpImf=4fNrf7 +zwm3_hfd6i6!VKpcB><&?G}8a(T`Xb&jHa8~{EzBjU31lLjUCDNQA5^}RYCu}ACogi +zUC@vt0v3u9<*}IZO9d+pa={Rt)bmW`<*(llNo5RTKQMf!BhkWHc%6YA?K-#Uu?LVD +z9M5CG(L6K-ld~L^KvFd4=kr_Jfpl)$R?OkQV-3s1bPhEVq@Zy+CkD(qZJqEwh+j)b +zh|7}Pq8wf53%FJAEmf(dkFw@yS55}=DFNvU&NPz)B5Ve8_@mtsl!^Co6)Z#M@lBwg +z9~RseI5q2iOOTX@vQQot+S2&H~dM(_);f&tn +zyM7LB_I_iW*MO=0TduV&7D95>Jh{y2wH-kpS><;@EgW->`YJxLp?b=%l&}@z-xs#V +zQLikIjaDXQTy!O+?1r;5-WCYV>CU|3=fi_d%HO)Zj$vnk}*vAYUB#?V5N&5YhtLZP@6gpri_X= +zoezY^#wqy_f@{P%%~y#6R*mUfAz2y~E|UcvyN^&8ucbmSmc#KM8f$W97gd?do}zwG(7xJA{j5sTB_3|Y)Lp!Ke&xgWYMqx>88jy?{C@BiCc&wDRJn+{ +z;VcLabjDp`ln +zEM`{ho|ij=_|~G#{s2WK+J1^@_Vn-O +zekYzLLj%Dw0B@Y1no*BK_V$!e>mbBR&-c(pIm!DC78=bW%x%X&=Uh=F0(U_jydHrP +z3VbinW2UB!u|8cmVxoaw2Je? +zAG7(TtWI-x6Iv4KS~z{c!WCGG_gAlxL2+Q%x6}|q1#$FR-SN!&fc=P1JTrkKqwi7( +zLZgMaSTd*mMjdN$#v1wl_ljBAz-($TW_gatE)C`35Y6EcTjDKNm(2K&?1Iz|pLhF$ +znR$N?oWM`CsMj3*;OxPy?7>eAf#RdhDFXG1N7(rrBQ}l}Xxz;Vgs_(w +z5Co;{0=jkVWBO#@&8t~M8e@Jd)Sp4d7?YS~JX_WLhJjzxvwyp^Ik_>r2g6!t_7S$U +zEZdqF+cqVnB4XH0YyMmw_w`GVJ&J2~gScO(>tWCZ^~G-IOUKKOmN#I=`I*&1;7(xi +zuJ=W!8=*1p-R)^KN}|B2m?l%zh~VeSA|XR1ePt)DBOFwH^s6|<<{+NC?uw!%_Ye1L +z!$-`X&A;bb6-%(gT0s2U0QPVM{za}OCh{Nn_n!l2Q>XvI$X&Gq5-#6K4Ow*7C9rxE +z*yc*w9LcnGG$~}4*$$jKQ5hSm8M0zIAP8O&ucELw8qIz=kCIa+HTO8kz?Rms#mTY< +zHDMzwur-)v?6tH@i}R<&b-URemXZs}d27q>se;I}G84p|$AI+9g)J$fr2GNg)6ftC +ztwu{a@D|jsi94M3I^7FABSIiY-GwRIDuWPHTOx-tTYP2BvBX+h?#qFlRAFpxBY8FI +zO*!qgyqUAs#`Y#h9>OUS^jI1nG{L?!d9lX`bljK2Cf71c$a6xvi9cq~=D +z!L2%U*LlwLsH25R<#O0&GmVT=ESEQBpl;B8Y^>>I2d6im7 +z@lYKXYF`g>Fnq1R?n7CA7-LLdb3){RqYYwHA{`xtiPWtvIm|{9np=}+r+DNILP0di +zq}igRI3G`$gmyzo4rt3bm7Tb*4h;|bMG7a)Mh=nlj|<(BxRPTmn33nW1Ts{$qhm5E +z-AQ@zKDmg)nmnVlgXOh>Z|4%&uaqS-A4T`XMD}P}VB2LVD*YuZUFMriPN@RV2^Su# +zChm{laKs5noXOQh#>SZDQ3t$(9)hczS;g4_b%)1S-!jbxR_zCrHdrj-`Cq3xvtU`4 +z{gnhL*j>Nz1lJC&HJ(^TW@+EAU0Uum;e;p%{(_9Z(w4Dn+5e5(Rp%}3n!7YJG8yZ1 +z3czfSPkH4kfF)1C|6&AE3K!~6dS=T{P}u6N6eB=SHv+Mw3lHFs>*H_!(>%+nUisUW +z(ZnQrpBjV`g0i{=Tlt>Wj|h{H@R1c&xM4z=qm1>QHSNdXrg*z7T7eP+rkDjwKCMlQ +zOpxjKPT~Z7BsuJ7CY}?xy9Ydh2J=SMa-QCIp5-r8qD6_6;h2(USF|RrD(;cc`0i0S +zk(SZ2;e8u9FfRRu-<_eN6kz#Cwwv?(3W+Xp+5+$p%J2~Ml@Sm@n^1c8u!XTm_dmH%)a`WX`jh^*gdi!P+t^*^04Eki^1Vsd6?1d6aH&K&NnM{e+Jk|xTXML`vM>+U?SQFGobqpHROrYu%{ +z6+*=EIFsoawVjft}8x6sl7!Y;BX7ol)JPk +zHqyRxq|>P;oIWd+)xqfuLw&L7B`;I=ds +zS}zSS@0R#qFLBhHuU}lFM=6+8oqr37tmP=;p +z&sSa;y>@El~(D)N@0w#SnpYWD~H#AV!7(D)?Owi=aBskngv!iyB|W^p>kz#rZtwPex+anNH5Tadg^@ +z=iXl?u2mJ*T~9O=d{b4`B4dE&l`%@+*ryu|Avx1xu0AG%J##U1r?#X~g&ZH-!K5tp +z8ZTZgf-A^()(A^GEHY-f;-9LrJ~3k0Y-QMgq-5DF>;hf{=qcok(mLc!VxlrpbBuOw +z>t17&(|Kj%Q>-*svF6E{;K?5uV}~gK0g=O9OR8n$z$?^Qa(aiNA@~;|8F4A>m(T~H +z-^mUj<=_N<*{;w5ub=RjE#?Zd;ulKEO3V+q%+^agy!?oi8iQ97@p7V!I4;^+B!0f9 +zd%AzeL%(1bRdeMf`|IpTzk^BxQJ4@5euyQCv&h_hq1Q?Lh`#TvXG!4&r)%~Exx&4w +zf?mPdY{XGkOxIV!ZoI|pg)?tbH;N9 +zYM~K}o{wtO=;d_igy2zrDixOdS76HNnJZn6)2f6v4M*s+IsSFturFOqMG7O)ec;VK +z3zMS6rkHPIp@x$>hM4YDn6XX}o@L#ITLEK2lBMDS>b)Q3Tzr&!C*lZRG5u2oe!uH9S5(8scbSfk0NOxV~ +z$Jc2KI+`$lGtc8WNURFGOl|=0yox`wYgE4q-@J+j)h0;ibf%H+VOqjJjy$K_6m(4j +zP48l$=`H;)qx1iBz_DHJQel-5>3ss=2#d3sRyQBUE=g?bB1rM8B=IuQ8h~mYlevsA +z^?uJY7>H3vD4X^`)!=;ic(Fc8R_U8J0v^yNPTmugr0*44U?0+g7R~$W!XBS^CrdZI +zAsyo!xH1~O2aM%t5M(ssKVCs_SSUG%AS*htkb-l_S+nkg_-Kw1P42uS%SgSWTScW4 +z7gO=?PmmcXp-0^6gjR^(K|k3>iS1l(m=opj4%H5E0C1}d21}>E(ktef5*7_8ll) +zZJCgf$Tg%%-zpgRA~E977I7k)aI$ekI89)dlvqbIJH{+4{5}4jZB+=eCV}+08U<2J +zg1|a-=!sB%d!$Aw?#*wV_EL!nm!x06onDE2MYW+4@*?fVyb``1EvKcmva9FN4Rk3L +zCqWarvYqLUdUV2)U*qXfy+!i(XnZ*GQseP4O;dc&V!sKmAAX)u{<`f>poiBKp>mWZQq!S9vvrEH +z={ML$QrD@o1HXIn%$cDTT;OV&B2QziQ|Z^Q@yDz2*G#g5@z>d5wxT&NB*Eq;wTCwT +z@&I;p&QVLJk!NBp-HFPBsQtVcb#*qmv+nI-PEgwmT5EqO*;b+c%>7!! +z8uM$!`+s9P|Fw96{`<<+F3=$F0;ci)_0Wx|tJD7+4BprH8?9!aWMYikr>`Z5>&`*t +z7MPRHkDDMVBl>SzZS60uw)smZ3cf`UV54uwX>K+FSNyv^lTraBG70$vlCy3NMtvnF +z(t72(6i|WDPM$>5TxU>rVGY|^jXo>804E+0q=y!w?P^VyS_dMqz9ASJTHDhcG%AoY +zZ^NdbouFWCj4~xVhHA_al$ykp9J|=NQE!2F#m3FIF~!5oaf6we!qAOaZ%JL4go*krw`nBmc$v{Bgbr}oP1TjkXQt;j1`oFWTe4Fc%eEmU +z-?0(|!j=P#8sK$GM}OlB2n8Ko#z3U}cJy3yVz~l8zro2f2>^+XZ2Bqypff0Nk+6ZG +z=Kx(gj$@W->ay`yPb;uIQOrcMPL>qY@*FXx^BUQbU3%nsOu^D!?QPcGAPOG4slmsd +zKTQ+!e-vvIUE!uNhtEp!r0LEfL;sVnoW{&InQJCo23?@b?r64<|G+}=!>|U;@=|@@ +zM;Rj#c5RQ5jdM^s=R)E#A-`qO1YYz?e1gqh8y3*pSK|8o8eNx6#2|#pw&PY%rl$9- +zi6{I-IJz?P!kOXbsjP3T>$B5IsA??Bm)veTSjC+Eb4U^_&SeST&F6ZDe!~y+wL2(P +z`?j8E9qMC`aAqdH>yvgVQszSJJA{os+z0x-yjWHzE`XHmr*;4Q$#f%({^pa^?&|&3#O|<~PiFm=BlluX$^8YOgz0^wH~OpIdwt0h +z(d|;Zg#t3|Jj$&=EqoQOKSc2{1@fnt`rVWApoGh_?KY+sgVBOEeAs7bXqYR87A8T+ +z@Go_RA_t5-TrvgryQPmu83i +zSv+IEB1Q3eKb*xGEG((-Nq}heTI|zb%{b9$+O0~rRcL?gJYvqC_9tj-YXb9oGO+%& +zWV5nKaF79~D@_Q}^A!oe{N9@vSFjCM1I#K6{iaafvXd~5Zg#?74J6s`)wtcVy(we{ +z95n1iN$V@QI==`_dqL=QimZbD1>hjBBBlNmo1)XQGpaSFr%7Rv?V7kC1cTC3BZJR+ +z2<4*9r9gX5n)cgCec6JFfX&*or%HB^vQC1xM3~&`Da+~|gey)M;hvmcx(3t8N~||K +zVA7%Gg2WvM?69?M5AcsT09Oo5WPR-bIFXk~JeP-RD^6o~!sKObJILtd-IigmR|aBT +z$bU)6RpPgAI^GMk^Nb+Hu7VFf?(7U?k?SfTG2o)7HlxB!*=m%oC6&Vam1nc>R7jmf +z=&Tj#+P{@rHR+DbG%Z#ORZe+8iKFti2KPhzG_D`%G5HByYPXHI)NwHPul!z17cFf< +zMM_q_A~TVCT}e~f?ogSFvaS~*!jPlM2F&kO2cLfd=Jx`hpwF~a +z%%sOPDiYe2V+fRZ^ou{tN0NZ~J-9hAb~VV)QvMjRw5+#~vE84SU{=r-Y~6?D4WxH* +zju$fE>8{Oo)uU5-cRC}#Y>KKI}SH|Khy=sPz0;SH}_Y(u-Qj<&u<|1QW|s%q*;vwnY?kmEr|>Tu9+`e0*lmXd} +zJunXN59`eTEiPkfEbe4zYbtKKf98r?xbX^%xMc)Fm)D$wDD*^AFo?4V~jSM)RQDYJbS5b;cd9LNg4D;_pBEp +zY4q2zR&H=@wNDO!BRakPEryQ0u+qrhFAjFN2OVue(v39bO->*T7j{GnJ5G+4RC5AT +zSRJ&I!MBBp^0EQhXJcxZPwtL-us{ +zK_lHyYG=`K@$k0MRJUdibqFtX_MrhvX^EZ%*bF~IOH2kiGbA5kYxl5-o+49cB<7mhRCFl8s3P@l|ZVBTK$i)ix7w9Stgp|By=}lAL +zy_u{f7*i?>lth+|Vfv*nr%0aV*`@lYl*i5>hE)Ur<9R*bTO6;5+%ohNFYOX}e$tBT +z)ExmB>VWAyfqoI$KNOrA$7lo-VBiD_shMR6A%wSd=>q;O6c51}+iwF~}*1KbUPlBZ%|Mjx_{Vk|Uvbe^un}*-c{z +zMd9xf#NPt#-}Xl@GfthDsdZLpRvlv-xv~k~V_AsqP-tJ+KPTuG@!F6tA4DkY!Kbp+f=0?fE-{JlJ69Ul{%7 +z52F>*DNK20x+cCwA3k-|uKjzC4slI$a`}DttY|U5RKf`hepFrPcCh)i7Cb-oT?um33UB4j_=b81|NqXCb;2x3Ey0STdv3zFxrndLrMxaT%fp_ +z%d9Dz7x}jP*CKNxmL}`+zsr&IzSu2pu{t%mMz{|_TB6{{E~Z@`UE6Vn;Hp}rh#;Ke +zkKMUx{0?&DjTkg%#EVmr=gT1q6rxY9pFIj!#A{UA6fEo`2%>B?|Nl69#~@qUZe6o% +z+qP}nwr#ss*|u%1vTd!hZDW<~>UzI@PV_!s_ul7pM`Zq(GiGK+%#3G@5zn~qYY6oR +zrlgb61SvPSOo4t-##5H$)NX>$q#NJN7R>*+8YLAWuv*}I$uO^iUG1T4RIh^7p4y(8 +z1;%z%T9bcG9rC@9Sk^cyTN|s(&$sUC9%LTl!%qOH)c_k&RXsiEN*6~5`2)7}| +zS$wQ(EJ!3U^CRfsjrFgnLg3(oDn?VvQ9?S;4kz$}^=>h&k3|+43nA%WHTVDErF4Rt +zZdGP+8j%Z})|`Ts&*ZB+x +zHnP&X)`N30;_*evum?Kj4J$T-cXIcKS6yC1m=tQr@9+yRK$fgyW;p?U*#%QE7CcHI +zFC^F>@=19yj{^p6m0Fg@f^* +z8!5$-)bB;gKdKgTL#|kVNyXomC=z&=@_Mb+C$$E|ZIz`5bEiHxP`StXAi#chr_oK8 +z9l%ef^^40glo1we8gL_aSwwioA}eXb03w{kNm}@_x1q$k##ruB +zOK-v(2EI@Fsw3Zvdw~95*UNLL8!_NdrN8z6LF!^^tZe9JDr@TOY-n!!-{;XEsmlh( +zKTY0ArqwRZ#1PqdS5rXSd1*A*Ws8QHf6{0@${Fby$<@kre6sgOscR${XajwNM-H?3 +zG>j;EjJ2sJhyu%xs4lSfM^q=h!t?_b-w#x0e~8t0wzixq`^lmc3?KVtNziUTky0u$RouB +zF^^%HM%1qlCX7C>e~IeSt9O<7tE_4a(htXOV8DR0RS3cCZbJUaqQ-Y|3eo)WZ~_)2 +zKUq{yxxgUs3zd>~Ph{$1AC;%&A1Qq6CT&k~?0~F+sbw3lNmRRldFRpf4K5$lUpTEc +zl@w&HHQSAAkhBYe&gMmCs`ue*V{3E6j?!vI(>WOY6~U7`F$jzjL(h#HIl@1nr<@8m +zzacpIZ?U!x!N|n8buBaem~AoG4`8V1jsls; +zRJNKg0@VtR$cYtW3vPUBu}(}G?-!3c`}^6Bf$rfOHH#m*3!w9r7OiYVwm90NV9U^t +z^wr06M*j>ow-sXNTAsLQ`$mLGd=oonb^Mcb6Yf}z%hlh_jsmapV6J19?=og#6+!D~ +z!Ym6()neZ|1^CFrI4Qq%Jk~CVrGxxCNDA{UqCjnlZy2_qNn8vdI}cl!jP{thDUMDp +zEm1_U@zT8Ml5gGtT>Xn3Uusl1Q`Z={dC5!sLV*G>yq5y;vpgkfm_0G)LH>F)+tdTh +z!6I9~Db)AXO>=A6Yi?Fb70soVa~HBh`p~CakC>#J_9o^OlX0#|S_igtT#T+b2)wn8 +z93(t~G(`{b?O?-PTx9rI&-hlXu{=Fr4{uSX<`+sr3NAPx{G*9a&?U}(d^g&9nKkCy +zqW19--83(DCpcbWJ1``ze$GJQ +z`m&IciC?_vQS)g}ZQ=4=BFzM!IO&&4a(nu`!)fzA8`jRYi)Hxkbd;&d>E^gda +z99TPt1#ka-1ZqQxQW_rZs;xe^aU<-^UNZK1yIQ;cTF>bvh^jB);#tv`YkZnuw9W7D +z2p((@1LDL!xnDJ}KslN)d@EQb`_}{)aJe#xk%_H0nVZCxPoOx6|v& +z!$>7vX^0y@u^*xt{>7pVk%o;F72jekPV<*%S)57@GVppi87qT1rm{>a%oD(o6uJ8^ +z7)#aVA7dZ@j_xD@)=TwAOW=fGz5-1a80dId#WElTS!n>9d*E3hBeH*cGBPm_h>9QVib!Zu!)c_O6|M#wO3wo0ozXA%R{=$-}s(~|;)D2&V=aDWOzby>eS +z9c3r17Jwas)bHYBphs3`}yx}6%yAXtp? +z2Xq+>N4$vI>ecSi1E4G@73?o|uxR5Q?MUw8P}F8v#{_ND#k0B<%p}|<0G6#D8DeOW +za3#_V`{NAmnlPop8sE)euvaHzp3CSQ^8J-fq8=_p4nCY)gO$>-4E~o$j)z*6$`Gdd`lMzos6$w7+rP`&zWgCD2mQw50&3) +zzbZg^&3r&ofUZl$Pj!{-qDGj>oRtMq0GmsW{WiV_gwcp-g{kKY=6d;rtbJ;yqhf)V +zlq!^;27V9s7mhJ~Yt<(^KGY*`j86cf-m+OuV&+ym<)AOO#@d{Yils{~8XyP3ig~-{ +ze!Px?$UJ|ATFlC37Irp@c|`2c%_J_o^1M1Y@kuj0jqTj8EuDcd$-id-c|lqO&!6Xl +z-Y*m-^>n$ij1vom4QcJCU-`;ujF7rh3d0y+5A8O>Rp~O~;Nf*a8GSgOu!YXCA>WwB +z_0Hyf9jxZ4uIiP@M)&|~q6V5i_Cdj-Y|snevBp?W4VcVJC%24OO)p~0$uh!<4ered +z(&q&^&Q3fTV7Qn9;OmZBjUBwJu4m}a_sy(nmgTpe+!XM3mRPZ_ZuV0DwG9PHClZ9| +z$>bjZ#_foGxa@1*&U&qD$QS*hOdEUg!d +ze`u;L;U^*1(!%dbho?b@=j}|_;~gLMxM05T{1SX7pA#OI8XmTj9X<#i(RPvI_otz) +z>8s-2ap%tQTl*HVQ+lI!;jssa>AhXSVe6+b9pTmAzBBzzrK_B$Dx|{Rvd~hl?(>}% +za^2}+E?gjR@5ks>w_qD_NIw=xCr9`7scze{YSNxo#S2v>>xLhOJx-*%|14wEKfvnS +zteK~~MOHg-%U87%wtg1ce=P#kgNY|MQcFJQg8?r-7^o;Ba)(SIL-W*lNpwdZ*tlUJx!XwgF4}H$d36*Ig&T+*H{F8$d{4F?sdcWzx9bM +zsTQB5e=0tcA90`H|MA|gilwcolY*1|j|Rrp*3?AO&dmP5t^EEGIsXrNA12FB%ZS*q +zQBSkas1Y5#({{F4Uexe^I<=k7R@@~dQx9d?(1%vt^lcQeoTewUnTt`-TTsRT1#}oP +z+o8LDx<;w1Ovw0+iM>A0Pl;(VdDbb`TB$VJf10&^kW=avAv>#?mSoCc#C@Em%-~9@ +zcK>Ync5&(p;4Dup(}AS<2^OsVl7ni3S2BjMAUhsf)$W(+|Jm@hXSb1~>8vkcmVn!@ +z3&pHeaf|Zfj~2TL_-Dfxv&wEyW^40UW`H9d~hAr?WS+R;hVVL^cu +zKs^YnZ;#11)hR&rvx)^eu+Nh}oV~_?%6N=0t)iR>Onji{YQUfnwjj*By-TDt{m7D$ +z>GwRP_5OL5M^wIpUaXT2#(IvzOmi6lxDrBFcBZ}=|$d*J(a2{#Hl$^%?D*VjeAc)79Y{~mz`2mLa +zG-^S*|2w;$HEmN9u-U&lv%e9gN*&)Z(n+5r|`Pioq#&2D1YYA2nesy25+r7x7oX0yitEQ7=`Od~c&Bepk16-v;pU(YNj3-Sr!^HcKN3@A +z=<-=AwJ!845C)&M!S#2yIxBGOgB?-rjp_CUSCp(|h{V5a+ilsp+ca@OV<>OLdI3&@0%yGbCT}k +zqU59Qqipd$qvU!AS*j1LW3B067qP>pRx;|o+8+MRC#jG=_h|W3L#qAMkpCO#%zxV8 +z`B(V*4@Tbq)}L|tpAi#zSekCy4n+*%$wi@>-5c +zYM4oE11?3;O!2O-4t(6j$x^CCe*wg+M5A4S>eIFcmbB0fbrv4i`uX|{TbI()Hdk{N +zrJA8dFWK7dv9}mxj%D{F?tXM+!MFd${#WB$H(QtqN;>oiG!4IC-iDDFbvn-JpU7qQ +zugEq0PvpX8BTn5~O~{JJBPlX4Vp1Qb{rYfl0kO~chnCm(fi}H3WjjU^T_nkpJ1~bR +zH$L|hx-l!*L);J_Xu?p|u)JM3g;s;rJ32eQcShg6}diqnvt&^ZBzroifXOQjh1 +zQK6G3E)0jVku%j{S$wjW<;*(C%p)muom7Q7>(~HeR9|Kc+7Pd1RA9RHqeUuMD?pT7 +zi1+hE&6~))h|LzTJh;X{&2dn$aqtpN6w&E|pkhbHe5h1Br;Ml;1K)O5 +zCYgtFo3?aQbqsGZ?uyuGE7xhRa<;M;OvR%njw}SGvSDiP>fn6m5XT5F5YV!cQdXMT +zJY9y|LJRyF$XaOzF862$fUEcko7AInh6x2}WziTK$o#v&Gt7vH!R}I6pr#cpjuZe? +zH?dH;muAThL<|mOlIk^pwk>FGG^^$7)va7zi=)}!nvQhnQ0Ne|K^5iF;26B=SWY2d +zd&fCEK2H~Chr?qFX*qLz()qtxZ<9g>NK9VzDR>Ca@GJdq@k|2^2Tmz*!0g1oWyIv{ +zF71uZa3I(Bu!N_BEiCr-+psf2k9~tXs*x#XWu8^1$t;=NSu$ZFB8?}bLcC6!<5i@a +zV7B&3vMu%0{^`9@!NmIjuXMUdM2} +zQ?|?t#Js97O42P{t^9_%$&cCg9YBcfW5C<8U_2?@-2m?VsFy6+%Wz$fnC`N{r_vcS +z{0F&`nx$!i;;+tC8TbARyoTU(`WUOdj?x_r*9(;C2)XMwhcPsL2xfv-A75yHFBNGR +zQEXh^McwlQCk^@Ccxai37YXHv=0bhMqkyt?C- +zZQMi)AupY$VI?N!=xv-yJQ3p~Tw*b`%wMdd4S96ff>)Yf5a)rx_E(kaKTh?p`ONNe +zJ@}TDYspnmKEdMz6g-ZpzFd!|o~P_nupa82(h01%?Qe8#(TZBtjngLskaPHCm+yB4 +z{xr~;`d-i;f&Invb?T~|>R5Bw#IfdQl-Hr^fRba5*12(`5HUWkG4cG#`l88OVq(8VGj0vz0}9u +zM=LcmgGKJR)Ab&OwzMi%m{4hDMU`6H0kT}Gi-<9Mx4L8E6(;1dI^;W%I;-e<1t-I1 +z;uv-mZ0l#FMhZ1_t7uwFcr~DSr%UqzM^${XS^>~dxqMZxW96t@ZfYIeeQ}cRT10yq +za&Mncjw~OQKhTs{b5Ayil9)IQ-_`AOThoY&3WN$~GzQuqh{2NV6Hlg$;XT#7j~(WR +z5a}-e?Zm=Z)Pe_8k_V38Stg5xz;_U+_DF0?b@#@{(vc!1bAc3UiuasuyiOOlpP#Q| +z`@kGNH~6zC;o5}~j*+Fnoyp?XSnPo7-M^Vma*DE^O0WO`$dLg72>+|P)ZE72$k4|5 +zzwX>Mxe2l|?3M+GM?6uAu44d0KD|o#fEO`CA3Hs-G64Kt4ElbbBTFdau3i +z!Jf*LZLEZ!a&q}(fokdH-(t&3c9W#&#j}gvxY7E`^v@HZ%z7?w${IwuHAgTp39#P$5H$|>>FEG +z3!~hZ3;GY2r?2qgGdb*?W=-pH=W|-8OzXb5OMf3vHMjkueXHFo-?UCY@#dB!8aP;o@FpDsE`qEiIgOXxg*4?xTNyyimZXU@VrM +zJNR{9lRiALS1#>*y-IzX`7G*EG+gnksfOfVQa{(&Mts-EI)Cgf{Dp7o{r-|;lb!MS +z%4w}w+1MC0>#+9qv|(eHhnR6#@>D7_aP8z0$dBMUb!=akYwdi0+qF-FU5sAWpFh;z +z*33jzO@6UV4e?c+S|A8UX|x_xEYNmTRHGUKaCtArRIu*?W6 +z=OefI0#zp4*2Ga0)dDp{G`pt|WL0j7V|vXlPK!8Y%rnG)veeoiKC8+!+mm0~d=G>@ +zS|ati#r(jL1veRXQhd1lq^sVFguJScU^ +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 +zup!nt@8*?iTBeH%WELw>Ah +zJOo+UeY^GaSJ?Tbw-}mXOq&CjF3$;~MKt!$OCwUJjtM3YOH-#}&(0|RV%k21{UWw$ +zZY~t4-cE!S< +zLyrMp&yJ7_K`~RvK}7&t(PxQCtQv!Cxyde&K&O7nJ7jOk2Gj{6e`|RdfJRF6HdCat +zO*9YdNOG~l!o^Ote&Q+67+^NXtp(vj2f#6t}|7gxL(!7MV7F8P6!?4K9C%9dp?oWuE;lq-LmZL|OK5mQ= +zMTFY%=$Ux8ud(f;IyK0XHahK58EI= +zl`W=Zr(E0G8aK6Or%i8v{wW9r{`;)FVhz3XI1U`aWgjl|Iln4YkPC8%awp?=apR@i +z)?z+s=6QM%@1gv=urvHVjcT@^x_#p4`v=Xt4~*Tj*WhpPrk7TNgI@yYa*(TLkV +z%(wO;-t*B_@cv}b8|5e0jvbu)E`pQls5Jo!a`u)R?+%^fH5cJ*;nWIkD5vA=cx4Sz +zdY)JHE}S!k8AZTWaR4^N7#~(URM5;#YUy@zqRX63>V_`LF11_J@Ggxak`W#z;y7bzrW^NkeD@5TmlJcx6XLpb>rhH$}biVl;_V%k;4_6JA7=U1S_qyB} +z$6C35N|vAXpt}Mw!`{t*S1??1XgX`kSjXNDpOchImRw2n&3o%&zV^t>)gT>Nb#3^m +z)r?%1)>t2{S-ZkKr+H?zJMv;r-c-5 +zV_@|{N3^kG*QHnH+$%K7p?s(yk~UMC)csXa{ROp=x;2Sh#rL+&(oI*Md5w#5led5N?qfJ$t|vz5wO#qdiv%J(eWXimJIfPow+CU2Y%L4vLFWib +z<%k@=0KzNma-y3mCj2RgBG4|U1VhZW{yT*c3eghMU=)tw+~Mo?5`3LnxcXZF>e^-Z +ze(Nwm?V*@3(pyI>In(oWZ`RCFagPtk&VAa@QKLJJYI0FYN=OaKDE*h;{J3mlr=X$! +zIJ-BcZAkVWz;p|WgBTr*?$Kh`g0tXKJpZuRPMgjOCsXegPDHWJy5fl#-el`tIr=EE +z55asS9tV{F;x`F6T!q;x6mlVi#h4{37JdksKn-fO019x$V$vu@0I)LUqFjJDP%Aj~ +z0LX6VS||e{7;#A-x(2vH?QhLPP0oo!EdC^5iu;EPj2$9?oay7{#Zl>0JOed*>8gWS2$K!w~*_O|Q2&v0536m4Ob}&g- +zS_&()$Urh&%q}&O-6s*3sDnbsj&!AwnNj+g7iK-JOYDvekYh0n*vz1E*@&@Ehn~q +z#JOtz{)5+k#od~ULFo)V7>Al%n#15q8kS#t)#=c1dmq-F?8;gJ4?>zE9z=hGHPr(z +zyzqu7z)4h5$>x19c6rHu0A1=EYTfTPY|rP!6K0xaq#Bb=y3%1;)-8ChH{4jeTJY!S +z*Wu42oYUHsySy3D?-rn^h9?)_rVR&mGi=$6ZE3t12F>nAJ8$OW*1Vn~D$7Ol)|q@f +zXV%iHjLxy$9gf7+?IyifoR@s8x=gwCTB;^&bu0X4Rv&G~LwSW24%pGMF*mqdpRSM5 +zk0LLJoDQpgbED#~q*d;hJ!Ru?HqI>6E@=LGD56laKC64zI@F2ASus@gL0EgDt$SPi +zrTAIG%in|XboKWm?W>yn$1)A_j|Bh!MihyoA42f_*j4^HCI73&*S}fWM1}vKiiZEc +zm?FTR`C|VAQzV!)KlJl~N?5pal;2L1Do!pYU9nG4%>D5|5D=J8n3DLqA2f+y1qc_H5 +zs*M#;ehu5E+KHkvVlvqVWGE$W63s_y@5+@MC@lD^Eq_+vuVw2Hf(nuUbtF{_6JAs9 +zAxX6%J%Wb|&P52$jkzllg0ubQ$mbd3*ii#&v!883uhI12zNqbYgiihF8=`~Wpw_T +zzr_qwMmk#R0L284RawN84p-`7v%`gSv|EfO_A`I?Dx^m%M1dr-E;rdLtVk^QbjM|p +z<4$gLh4&(F?h7R)Z1xH;ULh1{%n3|R?aY&*GSTu|DijD89O}Cz3I_TX%-aO(GWjq5IFX-a +zg!rJaz*n_-NfZV{_axDu?~XMk(NN-&A|d9Ll|NW?u@FZ20-C}Bi>_bITz}{>Q9pi{ +z3)E;(seh?bxDZ5PLXrjmSt{t|XA9S`bmD-<{oF_8Xxb=wEvlUf8%nu6zvDN7c0paP +z_fWf#WWE6FENJ9!f|1BHbVw8`sy}KJj-ZUzrl6)o$`2nI_k}i4pls#Mq!d+5LX=hK +zb!*kKMO}I@k#avrs^a#o^6dSL;NP*qH@db9jPY&xzwZW}VGXT4@TrjFL4tD-`6h`p +zogodasuUR{6LJMS7p6_Z+#wCB_F-V6c( +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 +zYB0F2!%uO0eM6Ag+n!A1XRWG_ +zhRI5M`Q6*0Y&Sk{8)rIx6)l#h>160An}s}|WJsQT+1mp^+*2%9o0*RVz1pW#+u^*H +z`qSwNd`Zq{HU6Tz9)r^t`ipD752uaJnq^ATK?9ZasE~UT&|y!cSsA?meQRfrZ7(k^ +zg1rl%2cDRS(6Hdu0uPBB-9oH->=8vG2t$K!yj +zL$KqBy;$CbIl~j+{{2}jC%f@rRIoDvlGG=Rx&WE5<-oMhoD*0?tNz}kHSJj@^4rq= +zL;1Je!a@oHz +zU?VkdiW)qJ)_C>1t%*~77%h!6+SZY2d6(|nj+o@J?@}+9XQ8LJW)eyFSZ4W>AJ5Xm +zyQ{7W1kOYHQRX~V8ULO%jgoYcG_YNXK2XVZh3|oQfvubtORhf4iXUUgnY>+3bN;Q) +z`}ufMNh+ceY{JtAbe~@e)}4v*t8o@SX6*fs>hGtqu&*tY?Qlmj_@@gmfMZ@9uLNH` +z#}f=eofOeDI7aO@ChgN#glMi?a7yZJCq^%7o&^ggV508KEj>OCsk&cEivvkG0m2wa +z@dHNes2+_Rlw-be9KnEFpZpPK=*_e6aRU~*6qjjQp=1%8)2wA8OHV@%{q!2?GC)#$ +zBh^#aV&2=TvMgj8BSo+DTUxV;dAXDtvW52vI|fK6rfs>nZiY7Mt+CPdwGyFPb&leB +zD2>D&4!BeK!Wiw9nqkOW=9!fje6B-iHH~1{#*c7JCT5tL8_Ju0vv?!(*+;26&%EnHC%SmptgedX^4b?5_GHTVY`p|0XN(EuNP`8h1k}pmlxuv_ +zRWt&0VmnhksuR!h(=iJh{;$%`JD%$AkK@<=ilpq!tYn9TjATd13RxEy*Shu=*&{Pl +zGD3*VvS(Sz%nI4NuNe&^>GzTPx}S<}j~|bZ$NlT|Jn#2;f6h7XIp_V3Z4xdK=_AFJ +zrn~*3`4-yek!`m2HnrTg$S0=E#pbLsP+KBIq-S%R&$-X_Yf57tYj(-13|yhw^dg_x +z`{D(rxyE~G$=>PL!7NY6P~X5j{W+pceF(~vInPnan7<-6q1nJL*qd>_xfklP8Q}2d +zxF=AbwqTq7rU>4bXDM5R40JPE#oh{Sw9q_Lv&7Kc#PkJ(!X$Y-Q*CDG6G>L$LL +z!*SMRkE&~N_OcufA4>ToMBVzr*oE(U-ANeab|lTTw*pza+moCAzhZfmdrzuzYSVVCi1&WR* +z>*)#Hz1za1W(v3N6vVl!`H4|?eB-pa=0o+j_N!d;PXZgyZAD&9kPr5s1&Vo>N%TtS +zuPSxjIOX7W(d}zhqCPY1XV*;#Ef~-v-98_iY8ib*@933Bl4Z{Ho2x +z){YO)D~E(aVSOg^AtnSfik#_Y7lP4SNy~%m!Zi((?>8>R7QgUK9vw)TT|Q<-nQ+1W +zQP*W^)$)sd=Ii0O8Hu*suX8>&(rm|!cAkciZn^frMB)dmMnZ9mXgNZrnN%N{wT$b()zu6ar(|=yve6c +zvc(eRwoQ(BU(9U2E*E$%nlF<8 +zWB=-IS0^?)t7mrGt_>LwI*WGa$)eqMooYORwvOfTgsn)l;BBZ0cA;#)uU>O7b7OFI +zq@&-mjAo)B8FgMeWhSSdlaRluwz6+RYRI|!FWI{q#3+Zg(W7A@;bd_LwJ_?%qSX~X +zLsiTbUSsvzhqW`;q8AC0HXjsKz4n|_R;GL1gy(71mr9i5(dL;$n=+>CenkT}3mdPl +z#YNoqaeQL=)}Tz}xvu^NGlPa1{~-qp`?s&&Oiu#2bOluK=#$s$+FoFawYevwmkCB> +zE{{5P@k_b{>bUZn3`tZdi)C_Kz9+s_R#tF_(+YQqGHtZST2l22I{OKcAoiW3(f804 +z7Tz<+>2i22;vf*U;yX7R*b`(%-zxrV;y;hxI;<{JQ6yLx;Nj3GDxA)_^7#rLhT1FD +zVrWvbdX*G>W$kQ?l_0q-6is0uzRDI39c$_O_u^vUPy=*FLWR_55-yp5sncJzUc`r; +zUDIOU`j(n4Jjgy!mBwq3WpYtTZFRHP^_7;}F;d)d=TsiG?8wZGD3O0=n=mzej#lKM +zKW~szcO#_J6$!8!Qet}OTR1BcW!qqEoOWp<^eFr+`4g2Lx94>pbJD|_;RHHHO#RSl +zk6B{%b9OpXSA>!@BXyX$N)#S=XD6LbXXB54)^jZ9ahX;`yrsJKGsgmR53lZQ$W3 +zcUd&))JQDL2H}j4ERIWWykZb_D97&5R1gONk7UY +zK8z7qbKCR-MRZ&ouo)@6qMI^{Whu#lWtD6hR7Dg&7`kHO)kgYYZf@R26%ls?ag7$-)Cd1U_YdV9i{MPwom|Uw`hKe~L9j +zXPtpL)ZC7)?`=hW8Q0n)#Fm6bw8||^3|iKbi{9bSO0!vb<;(Pa0#3=8zMJ&UVKFG= +zDYwhbnLcu{hNB~QjK5<6@qC4cWO?2-~l29uaD0wGVLr2j2>3z1KI_cD?xJ#Y^b?+=m +ziOakaG%117eWaSD(Zi$(m5|}=$*0d&-O0KGT!{UT`k1BkknFhII$)CN*w#}iK?{AH +zw{G}r8VHHfD2)L(HLWibVw~T2MiI +zfq7yYBIC<&nYil{&TVHmrWF#)-q=(|geW|Cn!ADH5nurw(eo+3obak8Z)k_EOkw@W +zefesGCqy-7qx_ilqL%)_X@(V1=56(SH5`8aM~twxYof^o@ci|Bdgx?<`n@;V1g06y +zR-*(Bu*dp|;`nhXBT|pZPf<~yICEZ)vqxnKVxND~40yG$Ey`*cZk1Cgz^6qpe-e|0*S!x|ltP{nO +zp0Bk?z2zjFvX1Cf&#cQ_s5B&Tj=5(__wmRMB4OaIM{;_ATc6Qr{tbSmOi$}CH?r9l +z7hj&N!j8bg&gLX53*yjX=yoD24Ro66sQuD0V-u<$UP~R0>3s;eqdV5PEc*%WEG~qTJCp4I8dO%w%NGm +zM4Du#@Q%x;{_T;K()Xca9oC$4cUJN_IT2CLuTBWW8F_BB2W#AGw&+oiFjP<*h#T+^ +zm^x21?6)F+im5~4x_mz_0cM?QBvI#CY$28wsvNmU{H}Q&Hxu4GHO0o^C7*!1!>JYi +zHFG6B?W9|I>HNyv9>aW^b{X%)UPHs$DE_tfkZxw8mVO!C`4GR$&^U)ShS5sI9&;oy +z3O_l{UpC~XRMeD+=ShjQJ8GM&t!^U$0>nJn>{oOYM3qGrwQ9H1tb*zOtMs+Vxy=bEaSgf +zG8x?L7Z_Y~mO)_ixJnJnP#bx5(dSvxnX}7JtY@}5LP +zK3&?Y`*~q`6;>b0j6~WLq`>Lt4QlK?$P=Zsk7Nji9R>Xd3|fs +znyg=Q7r$Ekj6d=^Uzo8w%tjVfB|seLjEMn*fwZbhsrRy$2)Bp1$l)$e$--PTtO_Y%EV +zP +zCsjbVJR)y-QlIx0!isn`m|jVr?v2th==-bFK;}g>bTW)1yE_CB26-XjZy&z@A%p;F +z=)e6CLYBmLKOo)4*B4io<5E|{f?!N!=*g?QKp=Zk`{`Xhbnll60Q(Bs^biQ`cPTUo +z8iett#BZdKq=7vKmqV4~ZsrP_0vdk6LkUuD2Y5(I-x_HKgBru^zF#*zq`fXFvqSxW +z;sanm1gz?V`>U!60^xv)s)|xD)-m8zz*FG)p$hD`0A9!hy#8}rO|A7U5vB-EQ@F{Y +z9w=pykJAQbS|%z8gdF4nOknQ)S=G$g3eIU{Z~q&~-}n3vNeE=O=d*w`4Zlc!bE^Gb +z1WbY=;P;XwpkVs&J4s+I@H@Tzh`OgnO-B#(1vl`}{ig?kJiIAP_M0Z|>H(qT3hZ0$ +zReU<6^N}4&{hvd3r3>i}kOp}b?1KF!BX|FPlXtuSI`aX#KgYm9(rmRmyxl;o;sc3* +z_TR7FCRei`APu)RhPnLtO$aWUcQ*$Tuf)IRDC?G(N+^2zqdjB9*>~m+8c)*z5hvPd9=ry3* +z%vjKV9ffvZad3d>>%*;$EdThvCr@&yT~LESaJVsk3PeL*6gc`ndg{*>MaJ!9s{vWg +zcOL +zyBR>C;udiL7bv%kaDY0%jQ{LND9crKkzI>`hYw^GZ_EMe$f5CHm!W7(Cdmpx7GMk+ +zFjaw#>A!OT&g93K@n>UV<`i}K0Yi2lL69-86An;6z!=oKr$g5LL@L0;0S2ZEpzd)2 +z);!4ayKB4Mf6ck}jw}LM;;f7!k1L0Y8QT +zM-&x6)S!o`Q&FoIc1SZ8*s}4n0ORii#{YOH_U3~#S*SJxW^_Q3@k6-iN4pAy0rNwE +zbs2a{xRiS+7un@@@Sm!(90D{7gAgzSK+a!)bA>1a9qf(3IkpY~@-*bUEdo{xXMxqi +zk5Jz8tWycfz`qPCysx+`UxD8I2Pho@p55chQDef4B%n4>L%1c}0S?T$|5cJW#87Za +zdF0t0y#_Vte+8CNb}qP#Gl*ILm(1T4b^gWL{YeB|b#;%tHxswN_)GG^HCTV)?@uP+ +zx`N1-TePFf|G!5Ka6vZYMwGrnxe>pVXFJ4daMdPcAVwd`z@KY49l`_GU_s`k52D69 +zpd!m5OmKY%WM=gUYD_7KzaNOfS@MyoOXH|f56GE+h^63U*~m=o8I+knr_Mfv2M6Va +zMdppoqsIGwDdC_jv4^n1Nga{dNh^QF{#}a4L%86aW5`_Rj|XtU8OVOo-X8MYwYq=Azq&BfpwLX`dvLZZaFVJ5Ym +zCFu7)ZvIlmcr!_Pr>_}UxnGyUb+=b(YuSnaV&0p*P1?A;Q(>Zv=wj|$NOQS;cbCEO2B>OMaXXF$cK3|-FH&i<#GWn#~Y6g +z&vd5S$062$r&Gmp*U^=hTRq^=>k_{*GfifSS)PUn5S--(<#3@3U>d!fAuxHzCJ5Xh*%b>zj3DAm@lifNf^WVUtm>k$nAhIVbYhkKcf>C3s3y!Q|-nlk&eDS2j +z=@4r`OheBY`K*u(^yjJu7|6_o*dc+t-{1J5xd#FX5(ehk@sA-?bC?YJ5Rh&ckWSdt +zQ>r5}aZB--quBg4+#jHdgO<=1*%#s*G;M|jsUu2`P#rV~ +zd6{1>R4ooXt%@Whef7p{n)MIt*@Sg-iLze#<$QrQ_1R55MsC_+o8X}b;3FG`-k3x= +z1w>932}p2CL?Se6JF_}wF)mfhJo|JA2<(zV%HV*qVrG1zngv6u +zdL*`&q(@14^$Y#v2zpm|AWhk&2ZJo*8CW!KkW@BKHhe_4L5lfho^NNHPQ^LED_F1X +z)2{h>a}K1=32^}A{2C(U2m^FBP&oi-&fV~zWHF+0je=TV)qKLflW?Spewe@8>T7+x*tgv49_`EyX-VF@H)#S(s}*qAOG3T6VQPU|$Ctm%r^yR1_<(FK--4@lPX; +z!P0aaR;v +zq#tI#HA_M7E358K`)H;Rr%ncbjPVW)vyRB!qlS2cR7^hgg1RV}EI{CeBMQK~Ny$gI +z+`sH8S1oX(4}=IPmxkDdC+MvKPU{>JaEF|SL;0ed@zB`b(wIG^bi_Oz$X!B4uvtRE +ztwUKL$|=WypRvgCK3dFK?}DBq-^^->GKmRfA~BG`4x3_I?gDO}pgL=Pt!m=~lQPw^ +z=1QNU8Z-Tk8RfgYSbCqk~z=EVa?WKTo5kl(MSzh`<)xyzgc||&*t%z+ +zY*0lmz=)A@U*_4HR40MDTeWEA*WiM3`k>&pFv*~!@)UrGu0V6fu$;N>x|?I*5^Svfvl`g-=S8++!?( +z?=r9?hs*e9;twwHfgpfUC8tG`0b5(b6Qdk?xKU4}MV1BbsTATS0LD&j&WZv!op}6-ad=Bn?)0r=rlx3LxcS%7GiC@%^3O_T1vuO4 +z?LZ-n8+|RwqK|tW3ZK>1*FICnBn@Xm2j7mo8;Q6~(xg!AtajHzjW>UJ0%0=O?!lTc+^l&MP|X9E>LrjAJyyK +z)zxSfqt+sWG0JP|;rm%r#uhp%Dg^v>Z;XRsmOmS)=kyKyd@ydq)SU|~^z0;Mmy^&Y +z_r9mjCEB4SWO~Tg6`zRq6dm!{M{L7RAzdL*0a*UBjA^+-?8=YHBwVweHUhn_-&Ns7 +z8T{o0nSi`&=pBUep4NTLJzfR!Sty}zqFt8y0_`rdITBkyfxC{UZ(^=as<^WIxj<$) +zb%{Sf$?dz8RDCZ+3KPbUE$icmk~6Z +z;;jTM+1U1Z)vb-Evf#1pB#5Q~pOD|vDU#0VYqY-ytM!$|=3|7=Z7wR0w%HX$k7-Pn +zJjkgKS3Hly{l@Qx_xjk;IY*{;CjSRC|GD}Poc;$%|1&bNv9dz_pE*XB{~}k$|G@13 +zKe}pa+pDl6`0eRC;>}gIjJ`_eYf+Sn1|dn%E2*jyY64MgkO*up>hImV_OvyZK+&RB +z&AE>r-Fx)SIj2=eB8`$?{7wZQJ)-8~{n=YuS(!vS_zgjSetYxj^6%(+-IigvyjzJv +zI?FLRz|Bq}(~?Vb`t2WjT&aIt3Pm(UL4Bm3(n2^$S$t&1k(T~sPOWw-Fc*>yf!_Gwfo3T;)H(dJJ{apKM2zrzZ5%rcms#z&Jgh%=iAYz~{d +zO=Bg-+0J_ZE{b4V9OoJYH)K|Nc!%J%b?DH|(1)feKWQHtOCaOsJamyvY2Y%2x{6#- +ztumNA*g|y~seS^dGmp&5r5Mi@*5Ssamhb_=@3prZtN2Z8b3 +z2O5-BZu4}2%_CGJBkAMOCIPW*kvpg_bqNtlu`VXiW*dD1Fzy;>o+A{`;jrBH$!xTm +zX<8l&#Wa$UNPtgPJey?08LBP)rZ|wN($K01n0%Ni`f_9w+uZ?6=bpG(w1SEAj+Lx7 +zdb85x#;~3wVD^Pco#Q*--G2>*B+6~ffMT2W%Fbb42M4_6D^)TaCT(4rC2KK$XZ^Fr +z0#4aeT7)GfT~eGfAY-jrS8X00fB?Ge33-gtt|50IT~n%~W^|gdi~+aw*xMUsN#Fr> +zdT?-IK+2kn5{lZIYe1Cy^kmoU$`8 +zzak~YYe`8EYsM8XzisjB(v~C;dBeEzAzs%lZYSeulOJ_{xiY6OqYbg7WVJsa=f0X6 +zbP-vZQWcEbJXv`x6_goe){gds?KIp90-6`2G)$)Y3ziauSy7-+Uhta&j9rM4vBak0 +zIn09@fvP5IHMX|(@DY55q@3o-8&Jr&nf2ZsN-2~I6_x+z)zpg>65am{U1?AX77O@l +z`a=8Vcp!0}3#ow1^qiXBRR0XC2XL4e_AKH4<1c@x*Vs8tb?`Q28B{+kx?PQpa7bQ^ +zL&%ng1wY_cV5yIF-CmfDBnI7l$|p)if~l+J7k%wbK( +zyaA8@HF9lEjMv_br|v*B6V(|)OSYr+`xmgs(;EG@8@=>%xH3|Tk|nj2>eyTOtzgOm +zqn?ROi6W0iNABTfXnd+O1)$mu>@fs;OSv#ms3K;Z>-@Tw9fAwbkPPD*HuH$8AgtGE +z!{u%kI2l<=c!3+|iWn>(hH|DwRa95FaR4u#@cDg*S^QopS?hDFg+|Y#k7SdOBoh3p +zK)Cp&kV%pz1Yxj&<>V!6+GMm+dA3qSI=c#I%K)5KmNUE%^MR2h*pRI1NEXH%n#PEF +zd_Zb}5;=v%Ur3|NKhiQT3`{F*J>b+4pmWM6`<8|ze;~+l`0jbh+%LdhzH{FY&oID2 +z>xqn6L+yT>5)Pb(=}cq~Fq`g5An_)EzcuCaK-!KiZGkGwGTsr;=OtT5=-i)|0LoXq>4|2f@L%6V(W?5Dw~~EjZ8hE +zus2ect$guU->}{`b_M9i2Yt3ZHO@(Al=i9Asn~BoK+l)jD>1J_NSj}VmIlN&xQq&F +zFl|Cfo8yL%7Uwp=6oKI@BoiB+A7B{7k12TZ)NLH)3u=6kC+-l__>j=p^f&Ot;XL+> +zAAq*mvXo>FO<8kcbmmfIfSgORlH+U#udsetDE^$0ms#at{et9!bAbo>Lb&98nOr$aFHWWvC+4DT!KenUUQFHJvwtH!bxrxmhD(r#xuc*`wW2tz!m8R%O +ziqvyJUWc-?#s*;zuHA1NRdhh!gtW891!XVn-G5OGhSw;x-3Ow19%uu01>CZI^&{Ty +zfY=x}$d26=AH*hSl!m-+TK1OoI3hKpFZ6u@i;VKfP9gMa_yC6j#N7NZSO3?p|6}Wn +zoQy30&(=Bq+txY%C$@gAtC_srhUk~C&lo=xUg&`DIqBuzS}GFWi}fx+mFh&I={T8W +zEa^AiFAppXG=n*fuq_-NNI6wXmn85{68+%=kiBaswWQQWdex`z@#`m;qJI0`IcyKL +z?EE~kH+X;kJWOGYkVWy2KWxJ&SE=V?uL)&}azoW9-ncMsE~5>$dcII5)-DZ2TOV}Z!ysJ07}HqV +zqVTh*SOS%&%l5bV0kUI~-qJ$F8Hv5%0iA2tB2*Vlobg9neo)hfjK4 +zV)myEv4zy=Tt(_JZDY$7&-S~P?gPhfT!pe#|Glm!%oSYu#j4V-?G4V!Owqv3GPJbO +zTEm;zp+CuInFpRv=4W60&f$jdyx0|Uwg0%_vPJQ`adp9JI+&Z;461s803XEmZIJs>*D0;i#i<7=@^$tip)6gxN%;z +z8jw{Qb}v26wrs0IkeFn7riu_7#8&@d*gi1+iccQS8EHe?!M$+8`QSD*w6 +zr|bSKZL4x>szBX}=55u^-Zpo;PAo$Kgnlp<{qnSSa5yj-Sj)88HGzLro|Mnwwxw7uPMNkRK?*d +zlxfUCQ?Y=}y01$Pdmh +zhHcjX8H~5`fI|w$mW_P~@msjN1Z=!r?gP&jL;H$+x)7vv;+H^ongScs{fPIhiqzw= +zt+eU_Aqt`+@LbeUU9r)4yE)`{{Wl~k#WF*VYt7a(n7m|ijbs%IZ8$0>mPn(RlQ|&e +z^K&>HMG5iC+hGK?e&-OQ2$(2^YACab3yA2QB!VzEvD=6cm?LluI3-d!OdyiwaG6Ye +zibIlh$9nHJ%qO8P7qLaADhtPxVx{Snar}m5z>0LNkkk|;^lOxAD05O`iT_5qJ5Gls071S^rTaQ{VGE +zlh~1>dgrk@4OEvOuKo9=HS$BstC8*3UA?#n9{&#T@x<2(SG>&Q^$K(jjY?~?Fa9oWe{6c^U2fPcN!Xj)T%)y6MYr=%Y_MSE`yYnG2(z<6?Y{73?~ +zcOnMsOEa$`F=govhG4PT!?imP)B#pnKe$95P9*n4Ht+*7ajmDb^nfOWeQ$@1YAEwv +z5ucnHzWATtXGq6Waym?mvz)*=gU~&gpiu8@B?3DuXG2Gr>xeV>;2_Z&yO9n~0z^Zo +z)DH#&+aVb;+cnk%mSVilzGG4)52@FHRyQEijphuDyX`=D0=B+sPeXQ*!8Qpn>B$)8 +zcvywAbPy8ICX|E2ld?vW!wd7NIOB&;0>5YB=yq`I^pggB?JR(#iX)R1n2IBJaPO4z +z7ZBhO1!D-KsbIHhV*+(VFK@;1rfC3V{JaprBU>K@#q$LJT#9bBcA1bm3Ga-^6Vr-CyUboO`Dk$Fxj%E|wV}vcW0^2Lh12TZs-F0KH1V&)k_z#-wZoR?cr*KD6*m9_xn8M6(3N3x`X}D +zuO@q&G3CI%|2xM)yG-xQl{4h`@Wut{% +z%a(m@0`H%Zg^Xl90P>?@%8Fm?ijTb%#TteL +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 +zi$4=WQMdiI1%r8 +z_*`(K{;9^|#=T`m`GPthE&C?kH7~(V7`Dwwl-l%Z2fOHcBU2g{qpJRFQJ@#pCgxBm +zx2X9L2js3YAq)=y+x55vggnSSrzbXqOs^9V05_MO7Xi}entol@C!F%%otJLV9 +zUOe~COadXzO9rlSid`G{_WskVP*fn)W^*5Ut2xQjQ6Z`m*X(FP0CT=nx0z5oZnDWVilgF8J#0kDOwh?odc&FRK7L*d=IjDwNwd~$ +zn_Q$hy*NMr`M3nDt8PQoT?ymwbaZL7s7}B8{Tz87WM%qVbDw`%5PhEcIXus+HCX+b +zD6;K&m3s0mS}bF%a;t%@(dG>|M;2p?%iItH7;?k)zb?rv)Y=aiEs3bpW%>&GE8@OT^qn5 +zUIg0Ru=7-|7g_q#V5wB` +zuxRVC32Gd2XZN2QHfYKri5)Bk+RQqoKyxngCf(jj(g=z_v(W^%_Yo&(d4;s5%}LU+ +zQn7~+%|4T`R}TZr3A#w9Ti+vd(59PG?G43_s4_Ox$~!gasiqt6;@Q4aen%+b%q`y3UyuddJtd>Rf$Fw2#6Lfg#T-^vcBdA5 +zHW0N|1T;8#3Q}zY*Wg-cODsY`qyaFL&R@7Iu?f@oSE%R17{n@0zyXwwxXKUwrb>3R +zN|h%Qf12+QY$id5Zt(|Kd_%U{0y+blF}L3^3;_OgO#(HzYK{V(!Wvcn1ypnI)s%L? +ztW*VBN1$bk*aTTcwpx0-iyU$Z+At|ZuES^i){fzSbKqKp59x-msNk*zpYc}vkOa6a +z<-@=S_+o+&t;|`GzXV%oib>w*zF*A?=7fYET@yy!<^~utwcL3LL(P$Y +zEK}hJ;&dtApo4U{}c^>N#&kR)at5iFVGB +za1^p2*Fl1$;fO@hGXEBmv*7w>6EU%^oz4yq-6#4}-nwd;3+Ds2=4mtb*dz~1ZVmW& +z{g6%?Co=LJzKmA`k^il9Bte7(wP&r?W?MZ8aO9N(7JRq47+x-FYhSS{&}y<+3+lVyVDZmw7fL`9s+rttihmApZ`v_;t++7xcDaj@K3W3HZs`Jr=$(8j|D6P9VrrES44~udBZadCSAE0d9xfTrN +zt|el`!G>pG?D__2Kuipa#X-Uy2ZHB3_Fo`QxdRK|>}dZ`?5#48 +ziC{AkTVmb-tU_#!pEfUU^}dlIPWzY)1Ol$@Xt;~#OXUrQPdWj?f)t3dDTTHD@a8Y4 +zqZ&iUagCl!|3=f$Kzr#YAvc68=b-=uCCFBc;%Eoq8Yv&EFvxd+rA8dPIV1pP6e;EoeCYBe(L#ueZuXAvFGoOc*p6x`@J +z^|qyeG7@+jv!;>I!GWQsSzk*;3s0e3u3KRd;TR#l(WM$iBPM}5hjbe~CsA7~?Eo4z +zuAvxZ`ra{AlPUoWAkQez$bZ;jV?lpm14me&x#<41kC$^`;s#x)PgYWdZfu)t9dbqvFX|WhNno1b-X;X}ybc&mr0F3p4F@i&{j|ZT(iq=v +zEXr628-p%D=Me79VEr@-C^8x2Jk6gvHGn*4>&SP10DbuSF@>FE^5k0~3_J`QVak8- +z<8^l)Wz?bVK<#i57DnfmbLv+Y?bXC+xC%K$w1yZ7W5K1Zgu#6rsmv4D>kKtqe=nuf +zalf4AS|!U6gY-^~3St3Pw>rUt+)|S7=edFmEe2M5SS1qF2w+%4bmA{@S=AJ8EA8Ram;&mbsKK9V+^zIP^MbCOD>b;?n6&rS)fa|0H +z=RIj$d2ZRb86cEOn|TUw=7IkQJHsFrqmZecEYez8(e3mOxaE`20H92HJ*3l$XDU4E +zv|cHCR6XM0+HgcUEy!B{qh4tG;C76;X0KD^t>L|EtaZ+$Cvnps)=T~t*>-xzzZM#?irkSZD(lPdi~p3LCvH$4YlDlGdxL$1YtOI +z7{$Y=&F_$?JcYAZPvVF*)bgQ3lHYC8$n3)bnbZtQzh6Vu!<})$vc)aWThegi4#miH +z4&saXmf7S(G_>*rKt92xN~IAg{xr+DrBRP~5?d2}IotbZl@rX5kCvxLYevK*c_Rej +zCH$_3f9h!;h6%#?V^Bz$56ZoZ2f(oO5a&Piuym#rvtuiBnP|}z#y9Lz{^SQSru}u# +zHYP?#^x}+_=X!|fM5wnV7vYHqU<3uEPZ)Z-#;ti_>JLD%u&FwYVYGIrFJnP?uWeD) +zHinTo?naxt-w4hp58@F+PaWgna2od%c+VFCR9w>^95@6m2>5zVq<4-*7`JI;QQ3z* +z@2PPt%kl1h*lwz5Sv`1g5kljfT=OJyF-fD>HI$B};~IU&6?1H_yuR~Cew#(hQfFNEex9qTkH(s7V +zA@^Y;MR1x#rO|B1%(R1X-Am)+?-}tj&Gh&jp2Dd;8bas9H%?o;1sIdN#ArBhkFXYa +z%?#VF!yqPl;D>*? +zrmjppMlly-cYUS;0kz%N9k}7j)3v~qDS0sD;oG0Yd&UPXbvpZwby6b5)l3QU6EV@u +ztnZw|cuah1x|=sv&Q45Z+JwBwMZ15jxfMhC*>BPHs-(hhtzv6STDp+nD8%2wo~uJG +zxpaMXIxbjae)(oLygB*Lt`EHqdTU+QI_Etb6$T?79(jIJCg0zfV@CALqx;p{(%-HWJmF83 +zD*-6L`q!^faeuz>^j$M?JXyq_Wyk{@T#ka +z;U=A@l%yJ`(E%E#afn*l(T0Xg*4rdT0dhHCg3LXoG`tlgeVkq8!L9H9GiC@ +zKNm&Ho$0qWbZIK}sxLU7y_#Q5G2^SezTjkO>Skl&B0FCQyjN~kU8y9c=HgQ2tmm#R +zTItMRj!vDwUf({&;g4kV&#Rerh~(`1Ga_2|j2iSwZuF(GPxqb;tqfJ6M`z@qnC12d +zE*tOlrK^;kZ*SsYHb$wo{z*})(&sZK8o!a_U$Ydb%dJ?n`LSvyfhfUxdp2!S78vYR +zd^Wi^gWysmzFTzTTD@C`5?-`=HmW&L+U^;Dxjt~#5xU6Z>>`;bQRR6(5P20)T{%Df +zN)r(Y$gG^4z?Yv)P^M99XdqkP-Ea_ODnO>ELoL7yrNCvkhMa<05JLZeFii*G!!$be +z);mNoFwN9P4bR3#0+YMGi2hbKNJu5SU|`!3!Ll=oCD&_DNUlYqjfBPm54fJ6g|^zx|P+DT=XVd(o +zyF~)l4rIcA+&c8T(W$t)iw(j1LHkqyuPWLxib>aJ%ddcR?ldjc)&a!QO~GW$O0*Uq +zfIYWPN +zqzClUvFU51CX*M({6t`3oL5Hu*2GAL_Lti^X8L+boY6x;g~2u*Ve{E-`vG2nXe2)3 +zD2_DiUXTD*qpOqRi9r*~?6re+saJ4m4y~B6zR;pYRq0SlED3b5g-+HDIrkyJbf1mk +zdy89m5u|R}H(moovk#$CqpQ#>mXj%8ZApk08_47t-W^IYWEp4OqfubL=3Fc +zJCj{AWnNHbOS@$9bM*XoqCr}Kk7!j$?o9iUgW@iQO_)k>NnK@@_lYH%(YeL2}+(?g#uo +zJA^>D_qQJ`iUkOca9ES97kxwcMz1X2vjVzcR}tQ(u=Ed=;{(d1}x83)f8J^y78PtaOrT)fE#2LG}49QA? +z80=uQCOSD!10)f+_nfnj8M}idflkdF_y(c792w%tgGe7;#jVIs=MoI|FUQFUz{D +zUMRrMEwjafo=3nL>Zr;c +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 +zucO)BmR*UOAp1?VV}*EQd5EBO$ +zC*duf88>1QUts*;yw#h4f;fAo=nDela}pdtH%O +zl(BJT66?S0T@l`Oz>2i$=gv`p%7s$4_EZIISKe*k3@W{BbX@a3uMYZQD9@Jp27g|3 +zP%6Lf$4KR23Z$S_>RI^m_eN2xLj=)NZ;2lK1stEWEE%S$B{^B3*a2tF)#Ij-(@!dw +z1;GiCM)-B5WX7yGEEg{|JUKN{kRf77oO{ipT-tnMD+++t+~RV1etD%byZ)22o<6C$ +zkqj(yDCLet3l-)KDc|fvm=?OI?7mvEPSesa9$mbI#MDj`en{%dk82~PrHEZ>PB^5d +z!%-M2Ct?uPwqJjb`NKFBC$jOlsGw>;TSm3lNT$4LNbIGGSWC98b~RftRhG^NnQoIR +z(?F8IqGRqos9*I0uPm#qYBp6y#+#LzDmLZG0;Z!LZNY0#QLCCuO;oCah*I=uOM&Xv +zqgcnTV1WBM4knbi7+BCv!ds$Y@XF*C#gJ#7(Ks-wGG1AuD(6YEsuLkxPAPmzWAtl< +zdDrk({~ZCH{LTLL?&Rdw$h6YXs^;$`Ri+JN9bQ3X5TM|Z``0n{-xR!D=f}EDcH19p +zJRS<<;|FF2zKa!`WBEV_Z(RmlCR=LD@|(oCuKBUF)y2+S=%?a+F4H$!#4m2k+r=Xx +z&HeW~Jrqi~T +z0)^7}XFaXk**9MC8AIhh-_of+p72L?+3Q|am$*+wY79~LpLvv7Xt|FNAc{|=L2`LDtxhP7;C +zv0D+pYxMK&m(b7#Q+0a|m2ufEY9+KvRRe)U6)6&?-JHmEeL6tCUU07yvi7boCEaZm +zvBQ2HIdI@i^E?QBH6;n16-W6$7`XSwP3-jd!bj$!>7~7v=H?x2ece}1?ML!=l2)y6 +z(iK4vHdW**PfSB?&~-1~^-g{5-&FFmNx9S{nmx6e*@i&snycS9w%IIeQEa&SJ)wVk +zSuE4qP#Jpcc+7cOb}W&TY&|`2h1j`T71fP+uT{r5u1b|(S;Y>LMX{>alNWIqZ%WRx4p>g6mc-W|HLQ|wp@w52@u)dih^rMMl +z+9#F-=y6D^fJ(FR)2J{EgaVLc@><-~DiRo1*$L(~N53E#2$Kqg>20b7bR-csN^`_4 +z{N+1)K?f+>038<+jPZB?&Er(l(a3Ky(EbWh$?jHcu|q&8S89N5-vmqCDHbSeyTEZR +z5w+0O;NP&<8f~6x#W?qLYX2%x69|)xK|;l)PtIhz%5&y}K@rB~WzlP$MNrmo9Xfr@ +zQr(mtwyagK;`i96xcXM5Kr_5r(4sf)uLL*4au#^4-)!lo{k?MtyTR$LIl{;!s37{)^`?|^))actB{AG4|pPM3UxEh;G +zHI8-RfDz0Ejq|WI$TD??u8}k|bG#k1HGY6gZbT$AtPZ_YSUG6fceWwopm8WVGuRNe +z;QKwcFq@2R)NQ-#z|I20+t`3PrYuc*P_;rJ^E{iV&l>}YS@8-5eWQMd-DDK%kCk1w +z46kPOZ%-Pj!Fqj`yFvTSq_%JwoTxz`ul1p6d-t5S_Z@;IC~r}N`dA8y +zmmM`~7RR0x_^EBjwuf-7`QEf}3mm@<)_`=Qq&=Ikr;law(A`TiW{OIgd=H<+28wDi +za#EsEkr+l4Q}8F8o)Nk+@&@`*Mhf>30Msl8InLn?i;}9zD;HvxmFJby`QYAfbhbC1 +zmBc)Q!7vN6Ptl0l>FT48WYzeS-^7XL0(Z(__)}DANVN`EhEeaZ2|sP$Ueh~-`QBz2 +z=iR5_q;6h_U4rl^&UVS*V@!uDQa!n#?2t1;Ncr$v29$syD{I3j2e|mSB;0wyk~0kFo`JiuZP+-y9b4|M +zs0(a+Yl-7yDC}&&!MuVX){)%>lhi+nF#V3XJH=IsQE=4=j_D{B(ECs~8Ixi;`Cu&! +zWI7NXPyx8%1vcoVZ|R|TOHlK$jacHp;pO0pUK=`m%hz}?3jl_0Z)wDYgRAOvK7Q|O +z-z<0d$)6eT!vo%HpZNAN({XlCr{7>B@6l{w4PhH$*31V){gjt{B@GGiSw$zMK9Pq19#(O!)0h +zc9b`O#@2QKTu5aS%|uqn^jnM^E75B^e?e7dP{Lg-sPvvOQ1xcQRR+5zdx+(6&KUD* +zB0>Pr^|Dj(6VrU;^x)4U@Mw~(&*<9@Ntda6kD$=GdAB5oux{c(BXvmG6nhm4YlRGk +zp+bd`K9@#^8ihsf-N*EV!kaIXKhmg2tasJI7K#Yp;z&5<+~RHP5Lb8`7;DyaUmdwv +zj))O+6Yj+@43BD9?w^FPD#%Lo!wyklwWbP`+Ef&lEu@7-sBSXG=1@?kxU})46GtVg +zGw+HPmn<>xct5DSIn0V8Ui67vhwl?5`FXBx1v5FiNtG7G%lwA!ei1hbMIZI{qv5Uq +z=UdFGJ{x1{^S!Ja^BW314k>hcz@gPxqi$|RJCY$CS0w(zUNYdRcmo|nWU;g;r@V%v +zPdsHrolhIrL3M+p4af6jXVlfSnwnm(@S9!XQ4=8NVvT#Wp3Cke!XhIWB5X%NllL%A +z4sVvBcuXB(!S6<&vwbmlnT~p6#dI7H_hJZbhH&9Aj4@>td^;MjyR5Cm@g$Z!h8W{M +zJXPs~98|7n)pSdj2=HmcS$k!{10dKOZaRrb#sEOGH5kp>O8sXYXgGCKY6sQ=rtS`? +z;kKxpGh0K{TTc8^H= +zam`nws0++GOr(u)1Ly)SWoaX$NHg~R8lj(0L{v=KVD(LP(p5gj=ODO#vQC_)oAzMC +z$&wM>AzsExO;Fw6#)WDUml8M}vI%=6D8)A61xy}MRJAnBLJ^@fKz>=!2DYLmg@`N@V*A9))8KSS`wJt1NODfZ1B{_STR|_dm@r8I +z(}yU>wvg)iRU?Y(VhIP`rY+mf(KbxXU)}Tx^{}a1Ead5xCUPPtp@{}9U4{*1 +z>6c`-euU}RFRVs8xba^4VjD~YYs@Rl9Lajaw0=0vwDX`dCOjCKh%#os5#d12&AULP +zpP2Oo%Pe+!Dz!pS$?1K}E3q@xUl7B!pVytsvd5?GjU3-Asr)Wu0KVr_6$P3i-4-@IpRR=r6z48_RAh5X%IU$30{YCtS46oYK}Z+ +zVe&y%Y}>qn%C^Fi2!gM97W~i=kxtzHVFhhZRWd8D!KyH&1tl?jk_T=-62i?xV(1{F +z{}Hh*7FsScZ>o{LWrjU+ZJO>w!^agLe~|D;NJhX%>ou1=u}W&}jYFffKNxb=N4y6r +zT=Y7JlSm-Mjt(S_>?x(GWJ3J12j<1Fo2*j2pJ3~}*j*C~+R4-uaAol#;2c;*a@;@Jdq4nHDN9i4ENEv!CYZB3-T6NV_bu!FkD<3!(i2RMW!Giarpgi*Gsv2Z>#Ylx5ne^ax +z1hQt42Fhaf@!_q;+#^_y`pHI_6T|w&>VpACOp4#CI^P2akNn^bc*5{y{y@)=h>PRc +zfgz=lO#}KlWMM+3(eP$DoJBCgX|Sdf^wjeL1)1Lt61u#;6C4bS35Xlikr2?HCfEp! +zGwL8II93}tM@=WN)pQsKZZE)eIv!G$NKXzag;kySZcT}spLeuQQI`_U#aqRN`!J4O +zhe$4m#ojZ{(qz7N?vKnolx9FsOIA3YY|Nn+n=)M((p%nV2?!YR;HC7o+Tr#2q?`@Xj|d3d4^50G$E!CBGT~PTUvPg=884QTHgQK6F$7u2_eFt?--si_5{zTK%Yp(-&}Ry_DIu +z-kvrkEzP=iQL-Q$dfaOB1o@%|Zri;}8i4aqb_k9hutQdl_YP|v4rF&jfK2rPEI>27%jn4t=y{L%1prqdMp--6Fg$z?IhWBKn>vHi~uG8L;?FJ19!kOip2~^#6uZ% +zV1ctVnr1c%)_N`@Fyiwf8)oKq*!lti!B$`rs({W~lOMJ~L@HFcH0uBoG^c`WKruj) +zK@jYz5ox`UUsS+m)c2KmP6j&bMzO#hFp~HGZu^CdHnYP(7P2|mQj(Sk_W4sTGlc;W +zrV2Jl(Q=;Ntmx+G5D5;glWMicdftR|1$%f+rJf_cK&R8)s8Jm@Kdk2nVH%#dKoz%M +z&d!HI9+Qjwb3vAm{xwra@d2prCLy$FYv5s&m}`sHdB-H)_@%Qxk-$DY>#`B@IWG4; +zD3wU^g3VUZ02_vog47YrKsW9L8$@#>bM9W{^h1^Ndq>J)vm&~5@#K;|mvo?Kh`+=y +z&OD|v_`Ml<-xwp%0|r8irOp$@Q;@4AOPT +zhKDR-E^^ft?SWQM$=0Tk7{uNKA1bxsf%nV^oXj4hDR`kxj~^#0wianIoUDUHq7cA# +zUYc|trjUO6$=2ON3V)=nl6*LNe-H%R{!~N2sW3t}DnaI!VkLP9A +zGFy8GBf{YjLAg9~8tJE^wQVTcqf-GuD6aTaE&H4x7a7XsSc?0`x@eo?-|0FSLlzT_ +z>=hOC;tv<*;CiD6BW*IK?2#2wU6hrldhrm0(sozOa=?70s~$8nK*y3AcyXi^u! +zx(6=kh9<5cW{a<9---Ca+g~cfR}rQG(%YJNKQQ^rM4JQ$>#nY2OA*X(XVA;@n#QdfsI|1weGw~s*ne61o1X_q +z`dALd16~SuQSxmIi++I$5SC$Cu@csT3p3a*fn|$flqr%{H`Bkju +zeQFmU#>154jri^xC6c@4A<`~uaVF%(IhO6$&VryMAz7?dpyo)YK>d*Hq!^UE(hdO)`;5~_7h)(>N7s#oX@u?{X3c>eOSPHyP)@O +z_}f0ujd1`D8XxE<+l#SWuC-%h7yykHx|E3ONZR(oNK&f{qrc7Nl*rfVP-AAYbfAl* +zOW3mBoWQK>+9bEAb`cZwt4El($zv0&Z+SHktnf~wj +zm6hpVh9y?!|HiO%rSn%4*$(TwqCTl@rlc6|-tdqV-Po$~oY1^qL?u~lBH2TdGNL)Q +zed$huk5eZZbP8t1(s0;}-%vxlV8I5F&<7|`ccM?tYSF0lCU2dki&wsMa{Kd8=#N|6 +zfBaJd-sJ1n{ysG}N8cMs?QwCq7LPUJ=;Gy7qRt1?U!B18R+~6c*jv@RecCTxd-*<- +zY0SMk_fhxV!mgfa%zV1*tHpo47&%oREQtCyYT433QnS}@tuselk1!dmU3t!FI_a2v9N2}7CX;)Z?Hi=mILrk33gVop??)Q3fOgtL+F +zDvQqR!K&~#HMmN7% +zU={30pui~M%^(EuIiN|}kSj1vYRusoR0(plGQpwxEF-j?;O6_ds&yCOG(lxc4Zlyb +zBY_D_{%`-wO%95W-fgD2RT_@WD9_^H>ZOKH##m;H+0{&hmo3?62s2ej{-zYziv*veB7k4;u1Bqu#uPwm!>eQE&AeA8UL}k)CP;(9GtJc +zKcLO`P+lQTLF!9XRXx2NUTy#gS50+6qGGTF0cU7zu<8yowLKp=nLGFqUUmvKz`5D6 +zXoZ+mx14F6En1e)-XH*b=RFt~;MFU=fw%xg7>y|gqZivg=}R!rtRf1|MKxScb3+6i +z&=p4EMWY<)`9L6{#qy1Am_nQwS5Vx!#+8mseqU>1nf+qfhRAr>sKlN}RS)fBm) +z3>1~mA}RN3Q03E7q|)r44)Td=d5!u()Hc;pqj5%i +zAQQ>UKht^xqZZ^bR*44ur1cZP2HaczJZh3Bob-a`a0O|iq%GpH1i(C^nQyBHyU;LW$tE(< +zZ$Mvq{I1Sij-|O_k*rK|YBJXa!LK~WT2i=q+@N4J@888kzToySO)A4<&EQQkVE595+-YN~_kT=V3OPVKAme!46ZKMYnu +ztJspffKuC$X90f~0qo$HlT_Nu>>n@$Fs!*Jvg?$D?B0Yx*Cd%?Z#Tm5;9YzLLy+dXPMB)XPX9Mc-hp +zOX_|OQxR=RG+))c1>r-!4zTRUFD_{FCW@^!Tj8rTBqH~0rKNlYC4!!yN=%yj6Qn~o +z)J?{xky6WMOh{)S6c9i8;{F%lLn~t=A)Y8?yo|7L+zk=p4XHNOVZcNV(Kt`^h4ZjC +z6z#8Mb|m}z=XL`MUa(Uk1d2`#sX#qDKuqZks@ljntx)W4&7U|#Nk9a|V(o!1kf +z6czoGvN{1&kccy&oh4}tuy)JHd!U%QK+fRfM=8N8yKh=iL1s+y5}ZOgMu?O*FV-VwRoV?p1vHCBdBQpH#Ua=`fN;NfH^pOtcaAXIr!TevSxo +zKI_>0T*3{@+a0{Ls4|ZR;+|X1R6fS)Ep6;VZ3t=Z50{cUvDtJf?Iv}>jpgZ_WW^#= +zq~4`1!jnbv-sn=-8W?cKOWNsm(1ozeoKF +z3cJJlT{MTnIrEUmk?NEU`UFD>i`=-vLBsNMZ!Z3Vkx`F2D1-}hd3E?NXHeq}YRIC+ +z+bR_#3(x&_4PSyKP$j<8P>2Bmyk9Cre8}Q$9mR|NVzVQ~_bIad7w+77k*zqhZz$mE +zE51P#sg<1eb*`b+%p&91UOpjt?Zr2TiyV^-Pu42?G3jp{eiCeNXoi&PaPz3U^9ZT= +zTELh?6#KuXcKh2y$P`-QRuToY(#Jlf4c?uu5hf0}Mj`P(@>}nyYbPPNTAgmqx$d?F +zapEC9!d(gpR1LZVvEr?Qu^(ln +zWO4Y-hXlR>98B+^|Dk*@6^o7ctKQ2wIoCdhP(Na97MNh4AKxBkXizKsDHnhd2LfyV +zeM}749a?e(w1k+~F(2_r?xj+E>vJ*(Df})#y-vWZ?3nczc9Udx7;`1QVWNV5Q_d?? +zIWun#l&IF4UYyr*?)Kv`yysW}o+M|y%DBW=6vQ1!`VGBhkmzt$lPhKoh+?ZR4AK6c +z^GNtf5Cg@4wgciU{cj@p?#VU==TsFVw5^EA0?nJT0_$ilFbYrpNuDOGJs> +z5lY@cDetivD5xh-hpsLoF9)#^QMcDepZ4QwoREXGwYhmvCh{-p_fODxsh3-q;ybdK!73X7tCQMrLQ`fNn +zw-W#rgxvGTz=BWgxE1c`>eoRjPyodvB0B^+J!a$n;>(&sT +zK#0n3!>kzvvSAnYq)uPD&vftFrXtH6eb{JEgmiK3y!97-XDK6=6OclXA9IMsAW~J^Z%^9!yCOuu{FF7!Zzb6IZ +z?C6sJOqs5Arb!n&Iqyw=jmMBl#)gt8^81mR^sP*cFW|=Q +zc=F>e>rdNPn0=uK#dOcrC7Ep3Y~6&c)eY-FV#iYwUhq;H7BZ2dqyaOwJmB$qjb|=E +zBg^>%kcLn&7Q+{Z=s){Z>8Es}Syz+-B}G2Xtu3XE-~Y}TZB?l+4ZUjnbUR5xE>Pb53UJprHnez#ojNjBEZ;)PyYfyCv@WN?Q3p~^{QAqgC+4sHn +ze>RbI;^T;MF~r_NGizJLWjB^517bVjq*5Ug4>i3Bf=V7&3}gl`Q19r#V*a09CY +zh@2#sNa6|i7IhStNE+jvFbj`#3KfIR5R_>_>V*8aVq{w7n<9TJhP9I5Uu$lXlLk42 +z_)CXtx_vGbrCzapF(@Fp2SKc88=wEuCHru%=XF(60j#=T8LU0erYPv%p1nFxhR>P% +zLRRUMG`Bu}W>Nz8wK5vBOD#Kf`EjH9LXL#=G{kGlGr +zXe9H1Q_p)F;r2Bq;JL20?M2Y*XVqlni=qx(_-7ur;f)FLy#Gj(pz=$&kgg1RvAoi@ +z*rg9Rd+wMCZm48388Tq?Ds3b7q29S75K%V>tVS-Lq~Y0oL@HTuRr08=SsY1bR66`l +zH~&gWEZ#~o(k_2?8Bb9=mFw9f#iydL=h2ul>_pn`_F=!TbI0^UxRrWnd&iBu6pP>b4W7*r^&lr*%rqII}AA +zz|vuHB;h-1xa^ov27eQTNh_u-d|_B +z&pw#a&WDD08aTMQY)$&sa{@de9Jmh#>aO!^6Zdbm+;z$~ah;DDh(gFiEoi?;B=XS7 +zvi$rYnHRSmD!1&2o*Y^W$9}1aylp#&)2$Us;2OknTNdxhd*9!NW|H +zo!%fc6)ty#=N;_F%Rda6k5Ah2{RRR;CyEJJEmTWY2h;M +zw>E9_!B=EPQU$rP}$T~Cvsnz*dEqZr*dD(YS$#q +z9k;ilo4y5o9}>yi+0Z4|h|1&p6Iyf0mpj|3erkS)5MI>X=?`-NH_bl0xzkno;!6^; +zy7icw)P}0IyDV=;s!rm)3|?mH%feaT)G>htHu|`Q8YQY5WFz?|%YxwdxHVWn?j5x2 +zI9ockhAbUFIQg{HUv_~kz2TkkTDssB&M>YRmsEPS$z6`};Z_n5G_jsNPI5zak6>dX +z5*A(c5)vIfUZ-ear$+dr(GLX7tVxU~`W&O7cmG!@Jp&sdKCvLUC{^ygQZLjG;s(syaW#p52 +z7o^ep)|_dU>}fCeD_85A_nbp_mY-t(+B}b7kW&e*tKsN_yR<+FgaQd40Eqjp?ZxD{ +z%=I71(8N^mr(^8bkIUUBL1oGx{TF~#c|E%x4zAbB{0)K1!cuV8rIx?>ZOrwIEe&1^ +zi}OFukN3Mb8z0uq&0EnxaXqw8=ZUaBPb(ti$CTYXmHVHy`tGOPsR8^Lhx%` +zlSO6r@KhhXKsDJ~yUfW2s_;dfK2Ax^3gLA2{bp7uyZ{K3%h45dkQB$OBXGr0X@%hM +zMPUxQMqqRGkO*}f_^(WhLKm-R)e>P|6ML9{v7_25?tT^%qnhlGOYI+*bgiBc#st+$ +z-A>YCzzS0*+z0$8c?st3Y8~9N +zmqzwLd@qKWEF^=uZsD{^wzLK&WiWqpyIl15a=G)VwmM2+LJh=yIXLKdd8u}mYb~vym8FN}%VA|~j^?|(>XZozf;@9TJ=OFW{X_Xv+LKC> +zgKC_IDMAxGmVHN96N=+SqPr~gadAIA@@%^qSr_Z3z%rJxJ3XD+MgNp#Y8R-P;^{I--?uiz^w3~|(l){8 +z1sa-hcP-XG3s>$jo-?)1M8?#Vvsb~rwlIhweT^*pu01U@{Vt +z-nRmJ#O9Q%p+$m_BGKy%hqS_pI7SJ=`$WC7rR=lq=Pjxds +zZhk081*FPjE|O4Fey-(;kkoOTJMw3C=D?HL=HB^)=zY^d?dVw^8n&6AG{OJR4HuJX +zC6KVj3uSw~Sn#V|;hucyt5^gZa_AD>oaq*Y7Iqn(axtr{*+G+G+Jg!`_-VR8lGZ*R +zB`-t%Bd3>7ubLX|DwBJ0axa)srPc<~uveD!&F^E70C3}aSKcYDb)Ov6$3z`Q3S-E! +z=nRpR>bOSLx@(v>QYsAD~rs+8~1tlot6ke^)$HSbQZDcssb`f=cr;^`+RB+dcPfh-%(WGUv +z=}C-WK@dgWjs#s1bt+eok*@Apc(SysXYm)ZGO;-^@Il6?@}yk^C^yxC(c}j0mtR9P +zZaqdroisayGb;AE=5iK)5UH(>bK$~Kk4Htq|E!BSHKY*28OCJa(EH +zu*lH*2LllMgt2RFZ5;A+!{1vUu@1cx57*!q+Yq-=W;?-A>5A%B$hB&9oUCPF$_MYI +z2ns6oZZKQ*o{bor&wlEHL&1b2xk2^Um!cP-4f|-L>gWa1)v3W)AC3~&9uhIJP;^eB +z03jr=8Ombs#L00s>`-YqzoHO~z~)6tj$S+=&)F2gA>*Sh;Ok!LuKVM(G!tqux>f8LR#_KReQtRiyjH@OWcvYaF)rwG7 +zJj6rR2TioRaTctQZ4H)HV79r_>0xOz96MCiW3l4n512Q?Ak;3WFooM3OD|(+irygy +zVDUR|p@UtM4&8P@4pJgOa-~k-QW4VKA%<|g=xR-eg2%p)`IX?rv6iKWwmeU`?IXc7P`_0_Cp8izEYa`cxdbm>x3-HrhL(QM?^KsIi$H*g%n&!7*@b6= +zTye;o!w_@MSo63o4i59(f@(6{P7OEykn4yn`13J=nNz?{znxHg_6)WLtps4F@vTJL(iY|+a5XqMW-#dlQKs(Y4oI<4sI!3t>zDS +zW=JT$Qz+9JbKwUl^F7pY(qXd7`=i|Zjk7p8Iwvk3LH?cQq72ol$!#5Jl5`GWcJl0{a(s@lfs*h!QN~-p +zd;1QNdrL0)HN*2kYNk6ajclPKC0bMqO}MQQF(={ZNjrMT(UobU?Uzo)nn22t;t5d8 +zw+K}Wkcy1bgk$r}G>iVHCyA32T5}y!RDW8zwU?@`b*yYRc)33t{27V^lsw;^uj$_@ +z6<9-R(cW;RXeVh8gj;tS!d~%AHGD3!I)7DlB0bXTO^kOngvvo6s~r~@`Gh?n7l9%r +zJ*(iEk1%l->TunDM{p})RJ9n(6&JYxmgyo*lYNEBNE1}hP+t#!lf^!ycjQwe4fRJX +za9cZve!bK`TbD2z1$X`GLA8u+{R% +z@a!FRuKcx|7I#8;a!&V)vw19}R{#}h*RM-nhcK>X8%&+L1mI@tQV!)yZapy}Hs;%o +z!qtnMiMh?Z;PvnF!KR7~S1c4eqtw4yY9CX3F9D>6f!Z;p4GV?T0kcAS(aREM<@OAR +zy<4((1j72`h6YF!Auv?o5)dd+f+!r%8gF5s0a5(tT3bTM%hpOuH9cx31W0921rje- +zne<{qO#@D7C8Y@6mm1Z1pjiLZK=z43T~o2S4{LRI3ZYolXJL+)49ik@bP1Hf^E+(z +zOS(LE_ACz*8aH&Xvjc*RQ#!Odj)45Z?7G5lEK^Z#=i0Gz6x;?r`}lPbtt>D!ROWV*al@=Ifv^2TXHT%G0)BQSux)DH_pZxaB2X15Rnmyk_gT+Tm(ir +z3L>R*yP|9dL0<34^ei_Sj4v;dmF`x${9_!a!W&hpLy#($=&w!uF3&`&gzn6K#|dOO +zoEQ7;%|o`BWwM(D+VJIYnR5mxDw$2_KJd~xIQUB9*pJh|YvQ!kZ9|uZh{{%cOMiIF +z@xRZbu9o9N_q%+bpw(>04x;I3Mbw42t65(nkhpDH+lMF{#?g26AlHj9=(EROg3pWF +zrf$g>AT^G_llD3k5;Y3K^xttzAu)gCkH$Gw@1vJ-0R|lf+19FJSs{-9a>2!iQ=m1 +znP)uYan5h;=Aw&7Jkm)D^jNf_rN#k^t_;JuQU +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 +zN?zSVp9{TCnqk+8 +zH(m7Y6uNLdCVr=%cbg{RevaO8Cz8MNKzjcN9kuYve6?ANt;L_a%;W=mECajvn%!Q7 +zviq=e-waQGp?yC-Q^$atmk{riAL-i9N8~M%%^f~&tsb`Ww4tty4y5{y^Y~pJn~Hc{ +z_A7gu$^up*bIO +z6$LjY)I8DOLY7?_iPNYo$d@V){ +zV?Uu>f91+4)vm9|8GYxvL;$TR0@|X3 +z5>0%C+Cj^Y+vHh-SRuT2yi_g9psL3r>GpZwKh@ok(dm~iNw^Qonu4)taAn8Nlmv)n +zr?yjFe3W=<<*kQdnp37$l}FZXTU_V4!b~C +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 +z^Zmh3%+Pu2}?a7`} +z&0Q7OJ}{4rW-ga&UoMw$P6Jro!Ofyd|2H@BOub|P&wZw$cmi1b{{dsJebNg=3BX?n +z5BvktaT8;5>V8!uowN$sVHxEn4ljD(z;FAIs`&q6@ZTT?utnT>V1D`lK<0o|{s)GY +z0+9DOQx8~>oY$VRh_1R-Lu_ZLFfU|9AeXV39R5B2nK%Gef`Sj3gi3Ih$?t}b0lGyT +z@`4cT!#IGV;|ETm6cHw;6Fg2)7C6h%V;c%Ia2$FctTAT$G^!U?pb46p_+AF=JrnPT +z_S&LY6I7xEpqpXU5U}CC=Z^9ZcdGw12!O$(vFc(Qo`$LklkR7a&8Fd3N#XH4@-@w? +z-FnMO@T8@0QyxY)TMs7)>Chrkt$TdGZs>tHEg9giD)#tI?)@Tr$Ta|iZC*lB72~yqf+gNOP&~v5kmvasfqe&Fn@DKsJI-srMzuP`6cIUHq^@3j||LORP +z0h|Rkutx+ycL~A57MLvzU`M{0jG6pT7UEuI0@UdOVZZ+bXRfY&$Uw0E2M&|N{}Z-K +zCq9Mxe5Lr8JTedR?0f^|-RqKN0OxQXS_K+Uy6@&5J*t6#?jCu7u_)aKW&e!he}UGR +z?O=QV`opgHeg+=&#|6yqePRNT1^`My&RZ-XP%HvuMZSk;)kz?jk_U`u>COK;WHo@_ +z)BY>z0Jx2RbgP7oevgz7o&HHV0G%Rn{z)nP|2hl0Lsrr`k$t`X>6QpGW?$T94`?b<~7G~L`>Q+Qkiy&ZM% +zX2hjP~6#9&+g6 +znOCvsXoX@!_+X-Rtlw`1=>OVXrF=WxEUV!vmpD%F=_ +zm~5c-JELi>bS>V&>68v4$c>Z|b4XX4vk}L!upE$*QOA#6rPmo7l9pttIA|A;`kDWt +zZffi2VD-VW?^+&?p^Msg)-7-1orxmx^Zc4mG0HdhB&IFAkjy|a;?ZzZF>g3uK +zSqbb4GbwfL&o%nwx~U{{RVBRat=ID0*so3d65GRG!Fa5)71CXw>!Zl!rCM;r?5JHb +zK9O*>5hTp6|3Z9nc%(=y*L+G5cZ>E_0~m&;CYo2ak_8Pknp7RKwzPa=c^& +zA=T1)GY-=4A7gX8QF*dcG|~qlCj9lAY4gc&LU5toxNp<6fiM*g$w@gs0f;*qE?Br2 +zO8$beb4UU7O#D>NzKyEzopbi_)Slm53Yn>@Y>NU8@{l2aD&8g^i6>u|7_wRBW-U +zV250Efr5~PL{Ee~d~?kndn`uFtaA+w-C8+c7LgT-M!yo0>SJ~5P@dTQEbGLc)ulof +zmO4q7R>(Un;EeitW@_1b)9Gn1<&UwmX=>vvn9|fyGH?Zj`f8$NF~G^O03W +zfq|Z>=Z73#n4i*Kcw$|w`D9jkP=qO+og`I!`KeVmH58`Z$R}igX?{9(Nr%dE3JeR;HhAHA_xR7SgEG&FN9JV&B%qKs< +zQe_8+xw;rq>{546L%HVB@SCzavJtj@)SL<|!vfoP>Bs97*_SY%YE3>|K=+-pAbo6BTsYMtB>-W^5%7Adomlu4Y7 +zlajH8);8C46)iK&oq4o#U{8DVvhjSACbqdgqHNTZuYa@yoZ=HD)q7nL*b3p%|BhIt +z%bPe}VSoNb6c4!gAVdusV$DR$$nmr}d$7^oX_0yFNB)j%48+HOLJXBoW1PE|g)C7{ +z=-M4eUyB3yzwR@G)q|!>!#%!Vs18SAWC6TdDM}rm1qq1JK1EiEs8ANN;7P@NJSy74{l5yn0o<3?Ji+$$%J7g~G +zhBfS(=+N8r<9Ig;?J;w5#^opMrNJiV<3WAMq7Yf+shy*Pk-LfbY%cH4#r8R$RO=3X +zDQ4D0$nE}!B_&oogfc;nxFGcF$j#R&nkOGNq~5L6U1frDIx3p@2`0*uvB|d)kJ@Th +z;zCJ-JC9q;>>FG_PnLqqQN_N(QQTzqpve|_EJ#7Bw(O52;;zXs;3+MuiprJKSg|hn +zVT)G0y0(S?ZVn(L(veV^vsk9y&eA_k9ctHU(XNoK%>D4*4W>CwK9egAmW8xqqP~ +z9+lzr$oBQl+p~5Sv_xgt$S3QXrh1yx)3&aHy-SHx-w0Hp0n>e1$-vjiALrwlQhAI+ +zuCfnByrYIc1Giy6<3sM!N-U>xx5ddc^9=F2W$f}+b#_(LT~@GnY#~A{$Q*lVYZ=^8 +z@!DEG62bd~v5!y~e&5P@tAUJ}tU|KORvy92ajellr)0Ybaq2x3GP)`A6meJDF;RK9 +zE60OBD)XkebYQUospIWcyD;&lq5+~#Z?KZs2S@hu@hR2g%_j)&J+XVjuN!Z-Krg`D9cC%EB+Izm|&8YD-$#4o4GbSV=t5-fLbs>Y~ +zT!L(ps__}y)bhDOMTN689QT&yud3OV +zaXhK`4z9OK#a0t0gbN{0aHRL?a+!>B;DBjLNz({IwrWC#qcwHw?me%@Z)lCIh>wI1(v4z*Yfi#7JWfx +zk}WHB0*rQ8h>OwrLW^apkmS^#?;5a2F85b&${*dxx!Df9YRtq^4=`A%m||I@r09$8 +z*+j+idnUBRA5!RDhBg*g`c +zikfCWa;qSbi=p9ZakrlYQKy*y`&?LbO|a+64l5i;Q9faOFX(YCTT +z+s_GK7T)+uo;-2Gk%hq|1veU+*5|VrBC3P5iafSyyeq`Tp7wJ`W862KQ0EH@c`s== +zYBglklMg}#1~un8^@P{;LFZlOx1?P)`U?xZET1pBWGK!jI*O$a{o}&qm|mRx>e>?5 +zD%~_2pDed@Tn&CMV1=<^QTd9Qo~j`xHq3*ujFl3pVYX>1+W;Koyc!)u7@k(ZgzJyo +zXeK@tuJt8$Ea-92vFzrn-~B#iM;eMm6S_lKAF8`f_;{GT*e0o?dZeOy%%ggk_#sPf +z>}wSt4eY?Qj>;Wv8p!zM*~vek$nCvE?Y#uj7AVdG(=CTWUwXI)db0!iDcUqR$Ch*m +zVlNfg!{aA;R%{s9C&#JR>5T0wZ5gJ>U`5ce`@kg`y=eT +zTo{bv9gO0eB|x#mgu#Jy;U +zQo=#8MQF4KgwR#Apx_X|jvn$reH^~+(+B +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 +zgLUzyy}Z{1{I@t1SEyOf +z5vqQFx#uIu^`7zT9}qVDPz%r98;A~POk?m(+zc3Wcu!j~!aWxj>>i>)i+e6#9=J>> +znLU0&Nwv3a1w*1V6$3KBApW*WWEYCrvypJB2Z(jV17-Plb^RUj6JSVdT_t<%_Zy`3c!}Xs8anYfZOz2p!Q%8IsieOz5wpn0@wnSJrE5B+!x~+ +zy(DA=AgK2oz@5qh&|;26!lW!%FF^5ie5eNgfcNLHv{tZ)6Xj>=kpG$wTui*7W5iFn7Jfq#7g +zD9s-r=#r2mc!x&ts~!Ol*C?^L3pJc#3Gg-557ia+IaV-`mxT^PtmE?IP0o4oe(F?p +zaU?)^+Q%#djD$7@J|3qL`rfX4Kj=8mj81nGzt0H@-Z;PAbhP(rnmpz{8sI#D;1p$2 +zZiXTA-lQbYWwcsug>6q7__@apI_4T3O`Z_)X}KNdMn7Fz=I&!U+)W9b_*GI|7ojB1 +zT_z(q>Fq*Yvp|}G+z5cj+Y00lG9q?&H}6cT_iiVydzA +z{>}|2@Hd2cYoW7BX?INmlW^(H&21u4${s>39aYnW?Ffa+!W3dQT@UfH5}g$$xH<8u +z2U$vAj(8sL7`lPq+`*9Xc9G~u$HuezoZDWr>kI0W=9SwF;}~F%6UjxfZ#0O@5T2mL +zR1%}EKuj`gXqC>}7t;R~lBXna^Q1eeETq4to-FJ52MY+Qc8eNz{Q~g<19>S@tnS_E +zMx8W)rq^bk#*D10tDSd7VZ>AM9g^)>Y{nI5`U~qCKSb_UZLs4ml1{tdbF95568=KjOEDb +z(dKX*$?A>5WV0k)OKS(m2E_Yn$rcA|O7a#EvYq;R(c@W#!T(|G8>1|3c7@xvZQGo-ZM&!KY1_6jZFAc8^t5f;w)yRO&pqe6 +zYn?y$->xK;O6@1fs#QrUlUy-l+%=iJn2oiQO-YS7l9=R00fT1XN->$WHGSwP+tS!S +zOF{Z@+z?U>ciO3lf1m)HJY4IFUlvfr2bRGun;lV{S2}ng +zwi^2%T7YNs{t(loj&r^03K=A@X>dY)RBLryZ0)Onk5%T>6gpa!>XY_p^veCM;{&mF +zz8>rYuHk^;0DiqRU1hinvwcR~+XvqGX7~dI!~FalLNX8v9cCNhFI!Vg&2s-x0+a%I +z!^~`eq}!1YB&zpF`6K{=V)F}vQX(y$W(0#HA^vAk5>cv83LQ=f+T(R@)zH6K=D?Og +zsOFV6=r@?^M&V#-jCXdeaK&tEN@&=$>B~8oq+^r5K^RGYs1%fK`G1!D&LCxRJVI(U +zp7VFbJ~bj?Q&41@LUiZqY_cj<;SL3G64k!*e{nn~5{5b=|cgX0BS#x +z&d1AXWDr6t5==w;Y^_Bs>;jlcrz_qu1x=aYFzA7r53{HUZe13ru2>sNlP&{; +z!tjw!QzXR}UJU@#6hUtc3}jdRt*bnJDH9B(#^mK{*Vm1T$#({Ipi!3pJQYW46l6_V +zu3;69GAsCfI49_@sNn3$2Kk{R_5Ms{`R_30rr{_kl*kT)nK+}kW%-=}IFXXJ;6c1w +zvP5ZcN~n@T^YMI;e+7lLqO#8mC1C*^r}D#tQ&v@TNFi< +zVxZLx0nAa<%$p);|Xe7wc%jpfvh1xP}uM +z($;On%Wz%cmcuje9@d#A5VK?3#dcviT=(Y-mf^;i<)t2b3YP_pIIWJ@NiEgopl_}u +z$*+Rm)!c{Y5ji<(?kHN>I_~%Hxy{o(hL3Y+yS@FmA%uwfJ +zRrU5Q{)W!PN*joL-w^tBUnyxe;E)vc3ey_@^Qv)yQHOY~@OfUY +z@IlITF?-AOgqYQm-G*PC@_T66Tfy?QB%uITbzwsx7KGNc;;{QN^v>Y?Nax8i+x5Al +z{Mcjh`Q1I`84-BtZE?w50fK&MZX_nDX*gHk`L-l!W`Z?;7u~~c?F1FtV|j9eG`FfV +zN4m=~)zD0Kbljo9&A{W2#)YZb6)&qS=}i-9U-D4~(L2+#QToy2cs!R`zff!vv2Zjz +zvhg_@YpdflW`b<{kE6bcGwx}qVc<{wG=d7pJD-wU-}dvaqrxyN(cG*4WgX~I*3Naj +zKVh-s-wB3l6Rvy)UOt4#MX;HhIdb-W@H4!QQVqYfIg#$YGyjxP-$u&>V6#%Qii58Q +z{n;=6ObKHCew|*!_(}M}Td4ToVU>S39pqr;X8U(oh4a6g4s!mVnhtL0ojK|b{rHS4 +zUH1Fk9{8}%=vqt@`AgH0P6zW)*|bd+4LC7T&>uyL+xOQuBhTuMtraa0G$TsWa#fx# +zKGu!7xjPqy+?9bRUYBXJ(osNUWh9EV=?(tl>HPey!MXMzcQk%VLI3>oU}j}XAddI+ +z;rJwjXFn^u`dioC4$?XUwaVwy@xTh}+BG8cGq +zdNwmbAE4V2<5k#>1kM@ne^1xmyf17L3Omn8!TYIE?qzZNjg#u#>`mxnYRx;ge9aYZ +zC1%Vr5IUxZ)>AvnD7}fm^{LJu%(R&Etci?g{QL%Z<15DhTUt`MCJEhL6Xw%$(py9iliNRac7zepXcNA23E}ZNm?u9+1U09z2y%Fm&bbo +zL1)J>b~=_*K^Uw}BQ@PWd_8aPoOd^2xv`!Bk5wxJ#|R|>Ip)tiOrEVU)SL4mjr(Ma +z9jJLN;w%B8J=AfNm_WMQ3aNxJioC+pt3bf9NU_t8?;?v)N(znd!Pj%vV)QjwQ3f}8 +z(YYWrxi`9@fg{qKt$y!PytAs@`f#R(8--7hxb7=wt1$#T_~8#74H5!xdoPe)dx$Hi +zIQT3VHiY!HJhSp|MJgNNY@Q;7KO5w#tAk1LqQHJ_UGGiU(7dKin8a8OGr!JNlZu%2 +zg;R$7a*~{<#4CuUjv-E(lxv?LZuxyS7mGs^_>&4(`tiLML4JEWuZ*wjXF;Y}$?t)> +z-cl99-@fcaZ9f(0ULA}3Yp5!YB`rkwO-H&j@FE1PlSb%+@e<{_5%p|ut#0n!`T1y7 +zq&(%t+UP)PbZu92eA);v7*S4+saFMZY4706_bf^Vcrd}Rz{Rt4_ZcG(h05Er2E2b~ +z`%PWmn#J~4`mkQy6-8U7DBHPGri6s}^8K1YpV6mVZg{x|^+M;Jj=Igi+s5?4m@!*3 +z*J|IIEETwF5}=y(X`~y8Qw(2v?13$KmUQy&qt9hrKNYW%Zjw397}ex&7Q#eRws|Y! +z<4=RtJv8Kl!Uk)2+@c0?07%0>xG9uu3Jv%ES*B@3hjT>j?$o;E>?M0=HtkWe5mg0My +z#=0mB@+{%o>FnoetZ^Z_qO--GxxjAUfM!-ycO0Wc#kx>dncp@aKb6_Wz?a`<(?A)p +z03&7h_1uFf<6s>n$PmF)YK`eKj+{Mbyjl*#y%PV|!~6Bb`Z=7+(%p%pqnJ4aWhfdj +z_ih64#Y+FJDIu_mLC)029i+7Tm{N#51S7J$4&xyIqEo~Gt!RhtMPV9jr?CH}%{o5n +z%IjtuiXjv47~ktbw;W4HH?izB7!1^h-yuPr9Z~WZV{E-*_E8s}Zf=H`CF| +z8bdU6@WiDwxu(f!H(+(;&&y}%vKt0%BZpLUaP!~z$ecdEvyL%|gVWA91nBr=Gprsm +zSU1V?a}^>%L!P%!`i|P%P~DBm^{FqntX-0%V|*4n?_Ivs81dp=CDfRYxdjJrw#7ZC +zSt|X;sLvhC_WXu)_U3rguU%`V0Av?SITq#9v5Yy^>nXAR4c+F9-*umtCfdilZDNq~ +zW#+=_U1if}{Z{#WJH{3H +zOEAoSyO9Z5f$uQkC{a{;Z1MykZxvC?S6Lk2a)xW+pR4!WcFx5b!K1=wWOU2-Af +z2mJ_EVV20`b$E(<&;LpP#kPPX@;S$!sD>K;;vH!u;a3k<{AT?73L{fL_}EV6N(k=C +zNIV45lcNwpixkGLxeTeBUvc!v!0zMHSQ6=n`w(yR)3kj1w1~IGtVqnu)4^zQhp(H) +z=6ph6q`ddz!aW=^1V1|bkkBilm%(POBG2_1c4$K;!tnRI@TZh_!lbbaen#{AcoB!f +za8W|vPB`rz0ftEW&bG?2(w&|ZUV-&6Kfg;Gg4OJml*?~KEDl>7VH|B}Vqqdq756g0 +zG81W@G6B){++ZooZ+mb{xBIOJy;}OtGgFw6Ozh~FCOvuF>nz{2kys2 +zJ|}Fr6Wg?P^|%%?R~&K8nvdYGi}(0-E0U@oABjVBHtg`)=;rvOU52!nI{s8KulwX3 +z!>@dGTU75)2x-x8;c%3qkxtqKfHR)Og4}(UcGAgZE&(Nt4QTPpMAvsBcz0g5OA#f% +z#=+gqy^wXv?2k!|T%jaa5IP}vsw$s}p=ixx9aIEBjwR6(%BT4(J~SvL`Ze)Qr6z@5 +zU%a8U#wt2PX<4n@NIuYq-Q}yVi +z?Fyu4LpaOr!_;dICz*(D7d=_kd89GQVt6^CQw9gxSN7G6T5o8?jahSy8O1SGE$emL +z>?jyaid1u9*+Uv$}J(xEQb_CtY?`a<_+*l0h=ooy392ZQW;H3!le%h^%LE +zK@bjs+zg}Fr&V6cxGxU|a&br~&*ZvCwM!brl5+hXk3;3#2lmDN-G-z7x^A^7nFdEL#V~FSdWO5cXFt^Ad>;1qI}AQ +z(|z~tFjlKU$2_R@I+!~)L?!p4Qv4a6M76T_n_dzhpfQ}+SsES1Yu_ +zyG266o!NdL^^$km3WnXm-uP!%%dPkO(nl-gjkxDr0U0$N<=wMdmhNRDJ?3;fzWrW+ +zhr=OUrcBp6U085ANgc)*e>+-#o?Hp=YX?M-1(q&}` +ze6_DIIyN8}mRXahj4`9!jn*>-dyD$8*W6j`i`S20U%x!2HgSIw=rfdqNqpZgmw{;J +z?77^+QhadgJ%oJg`cpFNb8^fm} +zWXw@#A^KxWSV}n-wR%&KO!v!t3BHr>7J_36WAcjY8FA-F_DCo938*enxdzHZ_50hO +z2G-Ks$+e$3mx(vLxISHluMG_jM7LAsmQT=4pSB%J+SRE!$2S8(x=zvUx=wKU>#_DN +z@?Xtk99OIPDbA9Y!5Jlb@=YFCe~?-UP_PcGal@U4y2y#!r(~2-aj7urN@Vf%PklTl +z=?N$9{eSE^1|(!XITRt^B%^!1Vc(2>Ai=xYHdTDS($~nKjolU~Q@p8`S!?4K{xZ=} +zzFlM52XVo&6|o0A9{x`rn!+q5AP +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 +z5dY(qL8fY!64!&e3wvvla +z{gSIvVEAbw+mbWPCEZ?qbEn`8GHHrYsM~t$NZv#B55uicd7?$8`+e!xXC$ZP8*Efd +z>aaAq&r$Y;lfc%yWsB=qTk@69v@sxLwV_{tJW`w?xla}6Tz$j|i~+D&w@WOTeaBy0 +zac@(<78wD-Dv>R}64ss8ulJYTg{8ehOnu{vOYdT~tL4bEoCE&jn0>lSp*5r-u^nA~ +zRu_Ov;~(*wmgS%4voN3Vwx#HNj5-<3ZKkc9{IeCRyQ1*k)bA?d%5{%#&!Vs{mbysA +zc-n+9Xi0_(Y5VY5v+rGg*N>NYz0qqdv8s=bfcO-G8rLY};-F~6BH#UJNlPsXe +z^<^@9T9Z7Pv+Mdpt1E)f9)s4k>Hg7cE19v~+lQ_D-RT#lFKXewkxxw{ZnbCkMlj;w +z+7uVw?(v1W%@vh_vq>bhBK_^aUZ9mz`s9SamGkPU39eSW5Jxqmh)3Dr0A{&L3~)TM +zua-E#txE}*T%TXf=*@@4LK4z5DY&oR2RK51#C8B{O)z>Xp5yJiP$m)FRm4!fD7t}; +zu0bSyYHQHP_IweSXaXM17;laL_MNTwjZ`Bbg2)VR`e9||3q(@2_VK@BRR6@D{ytB_ +z!O8NU(jU(MZqv;9e`?dbp!>f{e@(00C1}#fD}Zhg`ga2d{Sm+)A88M=^gI0Xa0cu2O#bn8x~qVBu)pS) +zou6A{K=}FjGQjAYi#UJwG6w5Z(FC#P@rX1>9U{V9{qgYrFwkT0IX9DI96M<6xpp&} +z>m9?a_o+^RI7I7KPd(`PBD=XsPy<5Ee*gTcDW8u;$k>xovXp&g6_fTP;UwLShRV3r +zIAjSp)%RC(Vb6xOEJZ +zCZ*cm&8F?r8gCMtBSI*yDJ8phf-Zyb`M{Xh9^e& +z_@@zY5a*Ot9#v%vh2Z=@@PP87O!OzgKO+oSATR9fHobhm@%1*x!=A`8YPAW2J>1~H +zSW4Np4MG$ZLKXE7BpcMQ=F$RBd>_5#oc86}_dQ=eyi1)K)V`b=Uy_}2^C0GaYA-QW +zq~yokh;FG@w9x%6{%ILnPIa0qi|9ai;Z#|lHnVK2F_}dR?cvo|^OPT)9nbo%$TCIQ +z#r`~1_)x0olu%yV(a@cp#fvi(QPe^WuY^=nu13l$$;-P!X_N^)+mbp%#zHTU$|A~Q +zlUu6y@puefK*?($s6T?VMDzY@d6tbC3mgnRSTu1W-vD7zO$J}%{@-W5@=ni4lUG;f&pFz(w +ziezU3+7lO=pji*bIQExJNOqy}+aMu9YOFXo0 +z*#n~UvWAD?_y}`s!l0==Jd50VO8|ar$_0$#^~|0@9P4$WV3ve`@NY2c;B^PsY}qH5 +z-=ke8KtXt$UH;gEDW&8o>cfn$9HPIEF)xBsWo$02 +zrW;Qzy^_8Pp*pz48lg6zxj6AwfV@^J+>@G-u$t4jq$$y@Vn?7VtyU0q&~KviM+au_ +zV(phZHKQN9L3c^mv<#A7-th`9<5w+9Fcn61`i8*VWYGn6rCQSM(4H#a6Rn1mZ_P5} +z8s67lMZtj6yr46Xik;)K6Bow`%I}FHW6yjNvMIeq_>}v%U-&I)EUUHw^*=c4_AH%# +z#~Jnx43;>U+OOX%uF*$3U*Z;0{Cr4u8b02NbgL*?bydr6{=2W~XIr5lIry~A0Mn0z~ +z-f(0C>!6)*-_nKP=t4Y!26_yJCb|!k(cYzF<}everxL$=&Y`ONGAwmHY5NA1CF{eB +zey;~rbe5^!!G{6eRocYzX0xono=E&lIR`Ld6ew-ma?Vw()vSRZmUU}QB9)H-clG}E{b1Br1ucw)f1Slb;RMcLIwHb +z=(Pkyz((jAYcw`Pdkj~tv}yC3l!kx+h3)_E>}7`9kt*G8jq9 +z{!0J0uY6|ZYV;N1 +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 +zduIzLg7+<{j|x^<;w(q=Lu2zTu+n5>D}dkW +zRDLG|!O^XxO$d|{Rk0nI1=2mA<_Htacf63GW^7CT4pL38*#VEX=YmywBz;U{m?MOq +z#4-=@hly&GUqzON4#AZUGW{%rY7S#TzifU)+R>CDj6ak?B9~)P9?mCSmK?V<73sTi +z#PE{P8gqO})F144_K^cc!)OC#R=gPsHGAv$RQ@`M2V}WScV)2V!{T6ASO*isnm|Zm +zCgnBYDU|Joj8{a5jfN;PRIkjE} +z_`)3zAxWXOpC_|W0BKp^JsT?x=KrIZiQYV}nq<=RBquMiTK!}u)xeaZdTOG`K +zUQ(~#1|Q_IjI(9ITOHTuC;354GwNZgKux7BbOA|jWw4Thd<su{^Cka}T>Qmro8K`tC;;W?&xRiNE#=aKy8prUw} +zix%OWXmx#1ebdj{zCHEGN=iRWt%LALJnt(^4VMwI#CbEPkKK#=`qlhWN#U&$;2_=O +z;r(#5&;?OWh?R;^wsx$+O`5h}`Z+S3-;FyYySA6eA=aru!_b)EG!kb|mABXhjb(yK +zV?9BUp`wgwC^R>VoQ1|MlZ0>oflkQRff`bRV}Nz20NWLrn2|LaL|Kl=Ku}@~_GDFNeBg!n{lEZHmr?ivDSZU1?{tP_x6rK-5-)C$jv3qGsHSn_&pch^^}I`@#%_RaO5Y2)p54(mzzj +zL3-Vs=~^$(fB^6Y7!7O?bkh$pwjHC|V2JR|%z18VLd(REavDXY)E>R=oEao9V`k}? +zYNWnoBn~8eS(e6u6cv<0l2ofxGZOI>yOBEm26B62=0f^{QCLR4kA7pxti1$hc;*yA +zrGr+n*>iQwmfCx3y-zd~@-uu-s9GVb?SoT|>d=0yCy3N6ppNuNCpP4L&jv7K6xcQw2pa-*~ +zd}XA6O&O1`p?H5x|qCBQPcV2t(U56jH(7S +z5(AfMj_6BeX7!AOG}?VfkI3)hp(|1uXY@kb4fV0{z$f$>*mqD<=bZleN){#(jm+wz +zR3#@W2gA~sc)Ht^xlu%2W8+>~Me2g){*X_E?0-Dittj}}gJrPs(uiXqu}~oNp-^~{ +zq9a`*Lrgy0H)5!6NR#x64{2R7x{*j}xvjrS;)YzLMXy9e%cyKRon0R$th)li!ba2- +z?s%6XsU@ZZ*JU2x)ySpU{wbjm^ZTihSR%|{ws`v|E3}ZO +z{Pburbh%H5gd%PIX|#m{6Kf#En3`&Blj%6rFY@62qA^K=1^s>jnY4riI&Bg%b)USb +zo^@)S9dT6H2w#+wW{WLj2N|=RvjnrR{&i;sk2(mS2m=a}!to-Hy!j>N4S#zuG3M0t^fACGQjMQ0m1~dih1PzicKk!Bb +z>RW_2{pZnq3z@gFs}>mamJk@frmRYb2L%&8BUghJB9?}O0O^m>@HZ)EwT3!x#<$1l +zUl}lH%*RHVIdIRY@8)jTbMts#r5dRpr{gw?o~&!=(GiEa8$zPckx=GtwSKPVJ`m-# +zz6~k(*hTBmel4#ZM<*PfxHP9F0p2*B2FqUy*=?Lu;w{Ux?FYFiR)UIy_4rh!nL-+4 +znJh0QO{3c)A{QC&5ZY`>UpTFkWJw0TPcY!7x3ruE(aqFJ1}O%0#^~>zUN^h%I2N=? +z1~W^1^K-m{wDekumfGcX@1HZBneR?cb|z+f0^@7H8YlS-(GStge2;qJhf3|+KKrJ% +zT5fhfGNt1_lDs}=#u`$yy1$m*a=10Jp1mABvb_fMymp2Y5Vu^We4K7G_5M_Q*)4w@ +zkzSq&5Mj25G6LT8z52W@Cru+b?)mH;`!g5i$Nf3Kb~>jQbJZN(7(GEi$jy4n!24)k +zlhw-A?f1MbQKS2Q{B}6V{>Mq?Eo>fLDcS#HHZ93S%H<1 +zIoXe|D<5HRj~4>#Je5avnS?6p=oqwVsoizfh_!ykGJCCS&uyH^T^~ydiARG7?Q*CJ +zewv=Iy5)_H!Qo8DDtACsOk|>^Rqt_TYz%FLJWK?MBbZ#4P+4=fIznDp&mZ|SP<8!nO +z%7_;B=`&HXgBjcH@&1{bi~lw0d-1zxQ{JQdMPk5K$B)y`_%X|-`Cz+hFyZCyX`o+K*T;EWu&wRmKo +z;LNHyEKLYZ!yJzM^S#xh-GeWlV(PG`f|OU+FF0-=4Yn(;pbFe#Mu*_ +z-qW5QV|JFq25AR}Zs&8(hU3|e`Ihc>yMkS))aj7SMu&V_Godk9z}@vHt22o{ydXwzkazI$I$BO`5fq*lax}8AbZ6qH_G3q;kxXmrYU;;Mo0grzr1j`MNAI|f79_O@FX|W +z`8D$9(`jYD`E4}yx##ohhp)Z*QLz5!^~k!n<3`@#4^P*PE!+!tFo@GGI{(`W>3i+|fTr77_R+)4;9a79#MJyY1{WUS +z08wXk#@FmoUuMDP7R^^>u+1i}o1*myzOY}PFGrbj|V +zo((6>O^}eH7T45d#ZRCW2jI1DMqI{>rVRG-oJxXEFU3o}O7<5C_GbH?$P=t+jHcv4 +zz#l_@mt?TEJV0mi%G~D@Teh7JTJO=yZ+`jJb@*H#r=X +zxW+_Xau!bkF3)=oZwv_k2tx97-30j-H?U&1%zhz`(;!qKmZ^oJzcIGjN9d+o)nAC@ +z!9CjkJU!tuw7`-Uq77Z&obc45B%iF@Mm{f{#ntJdRJI^4o>6s*{ARrj^-RNb&bdEs +zf-P1n(M=rDwUF-QIz*b015dKAEvak2Xk`anJ|xR4*B(e|pcU+}rMzmvZ=odJFDJEq +z%}@OS>+GcQ2&dSLeZ}m#EcKe(%Q-!p*EgW=79+VT@^+v?tM~LFV*hrNW~fGJILuK} +zZ)lOxCF^1<6!_ev_T{Um_AL^dH-dV`Zu>pJpJrMSg4fNcsLikGBBOS;Q~{(QQgg+W +z?L?A&aGbbr>Vs1o(n;>F;9H5yD@?%4N4EVqtS0c;LhoZJe^A$rzM-4@#-I6QCHG&_ +z>%Sz`e|(6nEDUV_VP$aqH-enwe}y1l=8=lR9kp*DNxYBD=cs>huIW$k&{%0=|j+24! +zEl&u}{^NQ}n)`*q+Ivaz<;dzwvj_0r;zHQT4lm!m*{_M!kW#&U|Q`e#@Gw08t +z3nBMeGuwmIn$qc;Z2qw#m<|^fAQBH42o>sk{TkQ!r?M0MR%-Nfd +z8P!Nox~<^@Lgp94czgD)g$TGIj2yC?>F}p$=U%p-`PHXMCAVR+3d-PvJ+ox^8`(@# +z;Ph8YXfr^Ad2jQbF+rlG*NF^ak`tK%)E>7bM7jRhNUQ1Ax$LC1sWpkbKqB+aBpc6Yb@7)O +zrYzMjt~~&tH_ggH`xw6gC+@Z_mmIq4k^MGwah8BV{1#|<>p>2AlL+8+N6ANkTgge| +z(k^FlDBa@sG>*=?SU3}S5)~{)x*}3;ON5w{Yq(AgQAIHEX_&ecX|Zw^hL)!ETDoQ= +z`J}!R(0I$XVF##LB6{PNggPfcC*C}iq>GehK_GBQCW^f0&yh<@W@Gh2OaYA5KKYfj +zKO-}j=a4A#l8_h9@%p#~1o8tZshp4ZF_g-B(nXA_!Hj6%Wx5o;bMW>YzXtU%!G$G( +zinBwL+j8`*WJbFdEqqvS!$A3B$>TFy>)dh82tY5)VK;`cMF>A^X55SddqAhaw8AaU +zRkg>sGDkVCPg=F$%FMHif-FaI#UU?2I-GTR1g@9;PUV8L&2J1!9B>1< +z<2RsJ)dA{}Ocqjz@ZrrfT0Cw!* +zx$Kf4tSnqQlH8fB%Dg~a`G&miO5X)?BPGsMG9j!Lbcc|1fEcU+nAk`(0qEdV +zLPb`ju}GyQgeZJx2eG8tf1YsG+{1CbB%yA% +z$~c3ww_j*j_hpA0SfRR(Q=S{1BvYJo8d|Yd`0O6o27nnC<W?bS=a|Ko?IirY8cVPU8^ktt1et9VH4=_hJfKM^SJ8WFgj1(-QM>=A9-XEf? +zrI{MpW-t-gfhfUz5?1}hND&FxM^uaQFD4Vu;shW{bYRlviAA~UlG8vV9II!N +zQQfy`z)m?*yx~SFDQDLrGBpr~$`-QxD;E(?5_pNXDL#X2D#^q((yXmDN(jHs!j&;f +z0Ta$L$kRCu{+Mccu$>8@kXj2qsON*JHL2CG0($Ec>3XQ49Q-9CSAzO=gj^ybj+v*8 +zDo~i_?gO3+n8LXZN7ZkBrYNo9oqX0Rk3H5%CvlBlG$GTS9xjFsRyjT)GFXI$$gnx( +zba+xPoP6#-`0<$3pUTm5rFT1U2Im?0oVSV}e(A0mnNv8c)KxutgZD=%wIi#nXXT?H +zmfn#@bMok0Um*bSw3UyM6qV+-rV_ +zy7pug%-LIl7sSRp_H)mpTy50d^FhZMR`RUjb_Yq@n&>SJjz!;daBuJ?U~g(; +z(E>EgppnJ%kd7SDO(!Gi*;{RJuBTFV{jS&VrRtEmwfJ1myar7tp?8m%pR3pJgOA@H +z==%5!LofW8uTG-}K@EMMV`Qn*WaC6!^ +z`c6#sX-i%${YtKc)6f#K)uxTv8}Q3uwoAz)Q4;Bg?gxzD0cmZeII}!HHZb3YD8|5& +zjxYDLJs{~ +zDwZs^$+19yW3``oHexaBgWVKD|33>FGSa;p)F +zUFsFcp9e@$mC1O2{6lh~y(mRlWb7MJ*3C_}cDXLyK2 +zHi(4rZ3eiGGKCk5iPG-gsWSE%Rl{BMoY72cXS%>COaCo*IBso4o6b^Rjb&15X@2S9 +z6>VsDhHNS=@gjKT;vldn0mZQ!?00X-a}koT&WTZ507Bl3_tZ5f*1o)5V-V9xE0LAm +z@t#&dh^S86p5W7&0fFwAgYV$(Cm85qo>GQ!sU#JZ5G`M +zd}Du}%X=WD;I3nl9KU#R6vlT*R!jA3RbADv^&bI?nl7;XRpu&a@f=~xz9AM5Nl +z=Pfe=u2wOw@F*#jF04;R8XA#JocD5Q8RW5iGhhzP+S_fgu+da(KOiP3|HCM-O25{l +z$+xgg#ap6aDg^lX#rR$rv!Q?@e~io}|KhXZ)~A&dTTp>2Uin2q17e}Lj)p_JutqqU}e@Ohi>1l-Vk#7SRBeYN#ND~D2 +zQoI_dKk6iAFotaS(Z7boW8}adjQkgY#r*Nf`-ig3Em1VhZpi}&2Ch|5fO=ru^+YI> +z@TgG|IK7vY$^f3b2ejVP{P2N-{g(FJ0=N9KFDQeg6>W{*wcF?4<@JFZBrtCCnXpee +z`}@mHvK#k0gyaD_Q{ZNpAP9pF1k!YCSa6srev&J!P;bjo(ygT<6#qI=7eUXS3mDcG +z%esB|93mldM|fnG>7N13!YcBMy{F5dd<5 +z>Zucih^O^|4E=O~p*~0_lKX_hdt2XAjUbQ#{>BVjT*F4t_K*iykUa}@XaxErcnpRE +zZI{p~jNLFVHv&O$eWbQYKn{S$1BA~K1li-jj~p1#k^Xn#M2#z{D123+k3j +z>gF1OVo=oKn4Sq>I@Auyzo; +zudr-p7a+m0gh29hT0b_OY5&wPjwFD0yt{XKbZr5O;}6X1dR&n|gF=umJJ+bojygqUbf}+zwH?L`Il+ +zEAHCYds9`!mgOEq7hnGR&_3wso*$Zax-4iUh4Q%dvD;RJInRvt449ONX3c#}QH^ZU +zB!;R~Rrx}<&YR>-TZgwI^Ca!KkU;@tqeiWm4j7(QanbzT{SUV#KXV!rxXjz{l$4Sn +zr4BMfgI5ME-edhwJ6r8y^fbIuU8RT^^V~}B-;)6p6^cV{9UX7`YJA{9^QFzBYg!*M +z5i36{JrLS*@|V8dx*dvg4frby`WMX4v$7LfK?ZN^R>R*X}7%ztsO5_E38WTI&= +z-kn>N+gPr#BnG*XOLca0Fi@xQKjUUcxBaOdEFwIVq9l&0{Ewuha-*r3s*Xd+9tWSC +zZhHN13s#5eDvvrJkb@H9yx%LgBt@bPAU%CrOeB5J^43v3iDZG6?oX}Mt2WEPgiW;< +zeGA#ka^vwOld*?mogv?{e%|dlYL*WbCV84(Vg&U8XptAs)JY?*s}|_U6vD(R +z%7nJZ#3|H{LuD@>Su90Wca?i#8aIHk)K_UAgFkKq7&!A~5p?eZdYNDJA}ke@|1I16 +z2XV^6!ou_)*@ltfzZs{D4F4<0>6MmyBB=;sY~P*-R$U!MSjTh3faPPeGyW$j5D^H~ +zCmG2Xvx%x}w>NVg7~;9?l&qRDu7>+3Q)TD*a~~NU7@E(- +z;P*5t_D;y|Mdcl3~hpLu1v_K)+{n1o05^t-ng&Pa6HUrDB#e_&(KzEEEgES6o2{jVgWyW3at5l`2( +zdXX3}Bg!@U_|C!eSCY}d-#et_E3rv%?CfEWfPBZu0l%Gzc*?dPBnKSac-mHw8=M0HyKIEnD&)VRqX +z-vJcAne`{6jF#`48v)^UON*216EaehA)vE?boM(|&&ObR12@CKNbR$^cF@L?H89#s +zmI@v!Q~*p|Nt^l>rQ~Pab1-BTpCrxM5y+91oXsR4W^_0HdRHwcc3dgHj@^=75d{Qg +z<9z6$8+6px)QwFMRH`oqh9;o3jp8bET%mw*4O_%b+P}BLS?U(dN5u1Cw&CHy9uZ`c +z!W&DI$`1wm!D!D)YK0T&?^Mi%K7m+a>^~JOk|Z8gX)-bfZaEC*AxuXlGd3$v2V6|h +zNR|vVkkYz5|55;oM7r!^a==YhZ@$IaP-LWrR9X$;V@(Rs+^+S^25~_uQqsSw?p_9` +zHeSoaY+|tStFdAj%pP2BW(Js7g_lw%Sp$KAc&wWPE*e8AKu4BAuamRO1kvjSHpvHE +z+X>yn*$S9j@derkYXzW=!irB!p@UL{0)ytMkpq7UXMt&04Pit_n3qkkL>TtWCw&<) +zkix&jZi^j5(N@wJb!LHqggQz3tTn^jq5_Xm&;-H<(8hzg^Qg0_?k73Dbyf1E?k+O) +zRwU=Bl4B2?r?%r!bVcus6D;(!yJ~}$dH8I#|6c5v8=~NtsG8M=(`b5_;OI7r>d%n# +zfPDtWu(T9^p%5W&o4SWdJd6U5R8TJ5r!Q=Ws_ZLJzAIv{(C7-@7@7#dH%eheUTY$YfT#j9bg=M-Jtts0IU-DK6z`&Y-h^{!U;lNa +zs1B`r^V^SlVykaYl_YwnLY6yKxoRrsfK&g%pn7@+;C7J@9IiSrt|routEXB}H!#@E +zdjUYK1Yg3Qi8v4mIqoY5FxPOuiebDM +zE_Lm-PMsV%4pW|v`YS8T6e)?h76Bv@KafNyF8+p`F8m;rTGqEu&ZbgGtqa!)Kwd@& +z3e#_jI*SktQ#8PZNE8?`N;e>L2$b9eU3JenL?Fa1w3-eKS?tHXp0#%CqF;sc2G0AQ +zek?F^3QF)|y?ixgana(M>ru+&b=$hkEaH-I`uYh4avth_3SV(?&_r-;9V_{TrNNYg +z5m|PqV?~6(`-^~Qilgc4G0zrg))5!qJ}6iOX_-%Y`dY?4xexrP!N7A(j#g&jX?E?kDO$lM-_B<721DcUF&Tt6`GTQ(Fi!2~$cPY&jZc08i7 +zLE9qgpTKcF5PAK=7wo+#Z90*VOTBy^pun`R%)2<0ki#j}ks*jnYbnLK6GwtD8!MBIp`CAxtw28s%U7{qBo(F!0Dm5b74mT6TJ*JxJj}?yl%0-P +zyxdAfqrU==rM5icy{fJeyRbX{y5@Xtjt;8rZs@{%#XVv +zky}L?pr+5+*)@}y1Rx@$qTT_ClgW%_v?0r%MO2;1;=w@>s8K5L_R>W4TC)@fI|sC9 +zH*A|1v~Qv<@=+)qad~mTD?Y-p4GW&Vhx^UZ7P9Rb07K(V3g?}49t_RG?nShnY3Iky +z0s}r?hjR2SW*t;HP$dU11l<60U@b-vePevIm> +z?iV~9o|@C2+Q_}ZyJVlY8VD?SJxW$Hp(6ALxtRSz?X^|CaJ}uUN1LzhThRIPThI&7 +z{cb8@_rCYh1@Nx5=NSmWM6EJ!sLcTgfX^)f0UdrFaAIO@4Cr(=Z?I9)*x7@&wdgtl +zH!n7(!r&l{i!$`PyZSmr7e#s9+(9v>vzNO&aA!dD1NPL{R~%HBF(!57tEE(dT+4;4 +zw~Zv4ynP0e$-02|?9v1KCQ{mLvXqiyhT%{p5jSF?(}4DrndDNZKN?b|tVuR))@PdBl4?7xj}Z#%%{aDabsu?;kE;H2A{XV_)31g# +z`?29E{Ni1dz6*^h{POU}a+?*g5iN70w@%>u6qH)wuQAh@N$dx(LiMk_^I+Pngy*hQ1w9O8wW<+( +zY<9@q8RN8LkKK%dFu4ZOxEE)PVFTr)bVC#YZE=xd(B%aOzvzhQiXtMQ%f;;o)ljs> +z|B@Jg)ljs>MS!3yiVO#93u}v`qM|z>+7qfMYmW&c+vkTD1k3)74GZB9fNl?9{Y3nC +zghJCNA>9#?<(rVUxX9lpzZAbI=#HRd-wNB}sHo_U3bO9h>|<1GA}-;mTAY7_rhDMNsAE}2>Q!eP7+V_gHo=Mb}fFq1jc?5 +zzomt^xcXV<{ki1hy;Fep;^Sevh)}6&0Z11`Q4IWr&aG?3;@_R<56F5yEM%cXxWfU% +z{<_;}uzh_?no{)^0+=QpkJ8K8c_!Il5fK&lDf~3Bey0X6#ju%0lvua>n+zoL{4g%3 +z92}ku?KE+t3N^~W!P4(MN-83#@+!etVQ-Eomyym{lTT-FIrj>Ja>G1a_nzqt8dylo +zZaoRP*nrspjQL`?*r_rdJoC+gTkfT(Q@-BNSP0*Z3XKvzH|gBak^?&_)p +zLext3_DoxWoCc|UEkI9P26Oj0%sA+Sk$;8D!WI}tE)h(yqcl;TIhMSb+LWtZl;D|(>Fj|a{y3pi_s0A5-UkeCw|3x$;C3GS&C{1fFu*lKV +zR>nrk3C#?V95>8Ml9>=k_)B1kAnvykeGq%1!W3_jh!O$N4`&E)Q^e>T6<)O_kw0*A +z&{3V<$zScqd@Un2CG2Z0A?n*r?qTdCkv9f$z(;VctgBo3V~>NL7)s}|ZEjfMA`Miz +zvVz`Pt1muCN5ie90``WO_?*Stk4p6kNBm+%18O*VjF`a5d)QJ9EosG+v&Eme_t`fX>#oJ+;og7C)tC*8kbB;W_bj6j`JPBgB=Mqc${uQP>rbCNBE +zc-=HW9A13lU*JCNi8_26(3kvzS#BhC`$6|j$D}}**&y(0qIMvw50NnpbT9g~8tH*~ +z;^65IoXgj`v`k$O8vc>nO_Z}Y#>*uqG{iP>6VYev=^qp +zs5^fSe9Ep}+ve{UEgrlpe0YuliVQvqrQ%s)WG!ww!nHlx75KPu(=6p> +zm1TA_YYvN^-oB%JudZj6d7>S9gRtA~hIp=EcGBbI;HK6+y;2Cfg4tRRv +z?#7;E%eOn4)=!ECtdWp7WZL=AN9;4MsCgm +zKhJgt?|A079?pGC-`?SSEtEZ7Jdt$Qo+RFmJD-Pm5y%uJI{nkuIbpvQSSo#5Qgys4 +zXtI*+Tpc}}AS>@;=ci1cC8wLw+ODC=UMYPxva8s +z9a~p*Ktik)%KFd^PT9OxS(5bVg{n64p(fXm41_p-V>^hj{? +z$+z`E`xZSBxT-;pVn0WPbI?WSep3Iipj)-uNzXd8go~z+RXXW}kR6+G7ueO!iZn$v +z03X$PL9n{f=P)Sp)T(#&a+qu`_F8d$N&nia;}zfGjmRCY=fKLOQ#)pk-!{yL=R05H +zpXoUUGA2x{OtDoJ_w2^=+=0}P+U^OA^{wi<5&>~pkoRm?sqSdkQn5v2AwO;ejZ3^= +zMIe#wfTOp9;~?<>5JCWVswWYSnB_J-eHn-RWV%E=82VD^dtQQ)=?`4xt2%LEKfJ&+ +zcdx@=i=erkb3o`$+eMOOw}e_VD#kp6Sko^4&M^qxy6Dl8<9o3^&3de}IDyRpj}7lz +z=mdzlINPb~3Q@SNJ7M{nOz93>?xmWMsB$_XooL*B$k--k_1flz*|xuT)XtSo^;seb +zqAcSiwKBl4FaiQRpiYJUM| +zlwu8g)U&+Atsc5X{Nz>N)(h4soZept|^ZPT8VuBpha(Kex +zOuwiS<-(Ibbm;^!5HnhC9wcwmB{a=!fyPE#jNhBJ1j8e%3drcjnj>q;NsVwZ3Z9sq +z&Awv?%RiRMC>q@=zQD&COP;Qe2a*PFe9xFIWE +zH`M|s{ikJqG3ZBHahB{|pd>C*b(dv^@X`?MY`kbBVZ=8`g|_5Fgfu|AU#gaB3LGo +z%Z*5lBAgF|Dbs8O!b~}8z|8>tpuaW%lTR2i%*9lRB=CK#fYqsyPy(eU0c3y$(@OrB +za){(#E9vFQpE!*^hu2MTj!OW+hc^OUk9)g!nu<%Jb|S)f7QxYs21GU1+KY-CD5vhW +zOryxMWrL8M62%qvaj|jEQ^|U9L$9{`OH(9;(42yj7i=v(vRj%E25G5Ijn?v9ri)}h +zd@UGqI@_Rnm))$)B2^9uJ??ahC9ad`Swqe*KEO(O2+-4kqL{GRI) +z?(rB1jt*K0cQZI9XSLr5p+UEH@N;#QhWOqZmMQ4>_N7$$&had0*$mp +z?Dwbe0*tiZGE0Yhia>Li_-q?%XG)aIG2alr5dI-H{)0!lUtR1}l1}dZyT!^z3Ry88 +zCuQG?EYU}?sVV0)BzT_>TAkf94MCBom4aV`0AFxYVA3wU)eWh+|1j8i%$W7efUasO +z!KW7bZbW!on$X9Sa@mHqnCfoMB_{Q;yOkt?Nx$|O^D0FD#wxs3dW%6NlxLZpH)yG! +zRuKCL2%j6peEK`Awqjc>9YpK{I^zy!-#=a&L&;e~`pD2Z8wS(mCyT1tRZ@q- +z(VvY+dmQj|5WUjN5Vyt`Br)GedL1Z^7pH%Coa+*=#^w=N9R5s|o#ZwIPQdrt?fkNT +zC=ZiXawM5s;L6L8K8Di@ewQ<@jUdc{v9IWNipe4kal9ShQbWxE> +z-qC4)i8e|PqZAS4Us$bCOO6rbGfh?j#?6?Uq*)&RuiUUo!#GU?mE4355o8?Mq>-!_ +z(E~Iyz;tG^t`m<=7c`|pUz>~3cUd(;r)QdX>a7#QIW-I1AoIn^ygI_eXLitMr(ghn +zCyGferQjDFxKb6E->WMQKbFXzKbD2Wr56MqTuEeE +zHQM;O2t0h8|IVn=?ejOT(+}G2<|znzf*)I3-n=w_FxW8+ +zI#nqowW~x>mE;ovoW5jId)gTcPz`~mgGnM(nVY9Vlp(uTi+yu~%#1~sZUK5(ve%eP +zTrHhqU94Obes{tl-v>R9Nrg<>dB*5h!}g@zxC>dw9r;`P3T4@ziy|OeQaGf-)nzpT +z-1+*-hJ@Y}iFP0@11JK-e4^FbDZjuoJ9%Hb(d_*bgU8ZXn?`eMDf_}O=S5v&&taeW +zZvh63E#Qgch_-}T!nZ#|P3D2M&DC)NNRG+jy0-Tdcc#(k5wq)3$B(Z{+5z5cXT0zl +zXb@cL9Qv041F@J0(aM +zrJt9B!)xO@Qq={jHY3!~i6Zahjda%G!VQ3cfh&T06scLnK`Rg- +z6>mKn*3HsD3BR{N^bHK;r3bb@QV!&az%l=M3*G{Ou`#%HBw@~JWt1FKN=<3nL!3X- +z*2#Dc3oGN(2?CBdI(F+b+lYb4?CCh&C!|LPZ0V17V<}2So19GhYzY(tSB~2zRzOUO +zQOGSI*>lGu@s*)czTvr98GjoOiZN_E9+)bSf856$PGb9wM#%3S_WmgN`hm7#4~dW# +z=~I6MipDZ)kjCU2pBk361G#bbh$IS;|L!;>8_`u41S0HXFJU-Pr^m!9&jHFZ{)Xzm +zJ@X6d>UOcgmu?3Dr@Yfp>^#~~%w?E=o_d)Mmz#(z!lR`>J_a{?w(;g*%N^)|rLmXU +zIuLyEKqd;;;cOGdU5a!lnN*v2-*!*1wQX-2QEb=aeNj|wahs;#tWpN|V*>vy`8=gU +zrWA=(Ou{XMH8eD1@YRo>|Lxln?pj-#Z(`c`KtM>DjTrc+nbxUKD!s)scI{dy@WIXZH +zM`G~LXLr9q(={#`N@Hh+njcivk2v!?V#<%OjyFJVZ<}I9HhXq^aPvjEwmpY4B5j^g +z%fx`+5>l;i*fpQ5toqb0xjPqP?=s%Z-nAe0a&Kn~YOm2bKMO$V{H1!7IK;DnEnq~u +z!@GJ6E}GD*!0SEyWQKEcn>(W`{PCILUUj#LF&||jE@ksE +zH_semsc3e~YHrIrn+QriME?4ZXXm{uQ~PcIpZmjqFeS_kEDZm1e_;G?P6;F9{|Z#n +ztZ8kF&5rb4qgTJ%p(Q}GtM^%c!eXY`B%*l{0c37}yY6tX(y%ooS?hb@vk%)&VyY^o +zA$uT&5TpqgI+*T`2iN{#I+`Ab8|y1|_`7j$d-e9_>0mb4lNyOja$D-p2tq +zN>hiH1Den*{$1FVrm^Eed*nwobGY(5RFL5iM(vA!P>~Tes{TvL%4JZI$sqdf3zJU= +z{x2WH!ORA1w&`Tzah1X&{@oa&WEU<=O+u +zH9Y_HSikXt3};BeMVLY1^XZ5o{^_wQFe*wc2!SDtU-S>zT|ySdM +zsoAbzgS=MzR0~(ORdPqeqlLN$S`r|f7x2D9f>2&fzr|G-I^%qQ^n80f9PMF0Hm`dJ +zp4b_JphoVFSQSTKC(%TU1ju~5#xRphgQn=EHDSIK7f#N~TY|RC; +za+-Byk*rfLduhyt{SK??2x4ZLDDVqQHRk99wk0{(NN{b1w+s799I +z($wr_+%B6e)%)~~tQ1ZGced2!mOY9KVfQH~7LaJJD1{qA`ZS+NH(S=lJ +zXrcsH=hvDRBwVP&VDjzFGY=y>sxl5w*4MRw^T8KGic5^}BF9HA2CEn^E1ebHBulQe +zG9R!)&?wa}$2=iJPOInFCq!-Notz2JM9a~DE9pGn6Z{dj=*R`o)B-)@b0?Lk^QR#*pEzOGf42#GDqa`vZ +z42g-J`lJdVcc1+qejc-IDeN(^hdor|_8`){{?+OaY%x2=3sk$B-sFVR_?BpXR{;zks?{}JSfX5U) +zg#>5{q7;2*T%z)&wN&3E^3Zqwnv3y}8a`i8)6Su~Ej80l$PDq~y1z~&i9OhwcAA!B=ev5MmcAfy6ib<&LuCNsMYw68hVfc9;HPkC) +z$$$+JGA0t>~bzS7|G7NG`$!1t|T;6a2hQ~j(dz51y4FqD{bOtVxuhl +z)S|@uB0iD6LNGcikNm4MB{9TtlZZ3gV?Wm8A0#iN?bnfbpi(!w)zVt#y^9#4Qx31A +z#B)?i=+YtpifZ5J9tA(0HSujMF=n)k5j@U|7C`TY%ysxh_q&=?$dq;!*jE`-H~~2Y +z);%{*MSHU1^=O4fzb#0|uAI&>jkjCnxB79JU6N&GLEex+f=JgMfM9FwfcV3je>K~5V9Z( +zM4jZrFBh&cH4l%Y21J=A#6iwVGAt;Nd~X>3DfFx#8MxnH^$%!K_~|v@JMRG%DN2Ut +z_VOa>mMQJBUJFs9LzXV}M3b?#p(88SX(^4%jiVi*#-0S1$K&Ms=7C_))?ln&kJ#5( +zpwc6Wb`L7Whr#1L_HHYr$M$%RbwMOWuO>=A?VoVy&D!CnP#KEbfKrIOvof^f1-Inn +z*Z<0%CBD10r-^{Sl)l^l@c3G3&um}Yw+JL&Xb +zx3v~s@?nnh2Dq_?dBLe};*sz0K}5Ryx;FTx2mH=FxU5@iZYSu;6QWjHxHri_}OAu5pH)GN|&n~UoC8D>dk}Ud}2=M1*WBgW8lOXCTx9htJ!qq3-GYD +zkJ^$XCSuoh6855?xPX84UOA_u{HYb8@ukJ@8~Iga;|z393~p_>5*)~7;(xy4OIMR} +z3MGURIj&MW98Ym8D!4$`&8aYd0Pv699{&87Y@C^2AQTe&TPc?Bj$bO1tH@3OF~H*; +zQN~*3XH&O~P6GpP_ZSiYLGgP)1;3so!ISJBb!hbyXit7jQxZD3UWf|Kz3D6uk(XJbR&*}6{}ys +zmE%X~R}PK5&9wGlZE`Ra3kf)w>(?Aw90O@9@!fBu!#@DP8>6THU9J7A2Kz_tWn$*| +zzZN-076Jx>e^z;T=%tNqOr6XK7#Ugrt|`)snp-&;I}p%|S{XPQ3mY5S8X5EPK{+}( +z7#mnaxn*5xYT0VHBKqv=+3$3KpE7mny)P}iJa|m1+LQ6qxq*`W1J4}S2uauYmf4+{u@ZsiwVj+W7quo(WWR3YIu3Cg#&je +z`A@|**-PZiUBhBEVc^E=QNpWc;vQa=X|5ZhpVAr6T-kME;*K1e;b@+E!qGKopji@R +zH~B?@SyfL24Y4zR+-Xmm22yY1&W-g?$!78T`yHeD_#TGT+TM*hq7B^+?vVelcZ>Or +zuui`+KdE(Hv2Qkuv?PG^!k1Q9ekvG%=EAXVXSd*&q(-@5esc5)g1%6{K&XVybf5M> +z{5l}tsKm73crSpVvbKMR`?w6|mcP-Q3Pp6HS|J!|cC*G;@`}IxoWn7U`XqU_Zk}vs +z!#$Q2iN+iq%`O_&dZW!#t^&uOEu*}$l0CwuSqLD0THjcOyCO1Kcsv0PdNJf!#}Sla +zYx~XzBDx#0y*4#7mV&{XQ5C=XV<4Kva{;3k(O8&T(SH?fl)|g$j)&U)t_*Q_G8M2E +z+A>l-RswtqC77}g1w|2AAzF5{$+3#qc2>s`dfwcBxjg>4Y9hLa$eb9dD0}`QOqX>3KLBB+0O>6sVljbK` +zfw20=wQx+V3df#EYX})Uf(NbPZy<Xj6RT2v9iEzENbjHVo1c*1^*|qxwI8@Zt_^HJL +z5(Co(wpb>Gg8fXhoP~7Oy6B41icWSlU;2Yh+~1Y^u+JqljOP@$&=L#aLG@gAz( +zY-j=hhrPFes_NCaf9TF-jT}mS@DJ^yR +zpNsMJd7kh4zW?8Ut>?SeyVn1%b1BReFP?uxq3y0}z??bu +z*xN8J+J~ay2;4Oi*~E5^^qeS)-;>{+?EyFT4&+ZMjB$EctWg({mYlh*zC*@zq@HEo +z$YdyR>warfAGpq>uCrK7obUVYY_#C1I}={6lUrwe+T*H&RZXJtb-imarFR1)QsKmb +z=*&1F22s1WpXr3msg}ti&0^~&d6B2r=qXa*jytO|C=hx#9rf<`sP6g)dIoplmlIZp +z(c2|A)EL}bUw%9d?SHKoG0Y_AY5Qhde)Y!CYRcS!8js5ebX0m6KH`7<*dmO&XNXrR}Vih32 +ztR!x=Ar`#cR%6dFI;H6lIizrjD_7WU#t6UN&kviPX<+)a;gjMy6L+skl4XNP?PZrH +zHv2Kq+Bj+c?IxjZBUY(tr?CyDjO!qiH4*O9@y#~mt^4RsMAQPLMkAP;Q?ZkDDTRgl +ztXWe7pY<9_W(xeq?`u^-ta&z_y$IA@_{I1Jcr**odu8uW+(}5c#D3QVhJXC|LLq21 +zlkO=QxWSEy{zm~)$vEH4OfUspw~+-BClM9FmPCp}BCTZ1YY%91a?=4XFW{qq;7Kzz +z=ch#@GzE-f<{@`U<@^M8uH$!YHEmD!Ekaud{fy!>O{eVBb5&JK)6Gma=v}v$=o2ST +zWtgY2NK3RrS(zHe(;vI74IJYy62`#3qOS*EeDLZs+hB+Y{&Gp;7+87lWi5fpA`ABM +z63dfGFF7fm>#4YJUGl^g#dJ>5o7zPX*SN6ubGH!%gWWzFxGPC%OomjErY&pVuV=f5 +z=MhcXfam)WN>`IC6&NLc9Y&fc85upJdOLZ8e#TNEY~c8d0=O`g?(A{zEmgJ+qR +z9QG!T&x#;}wmkwXD{MlQpX+RIx)sN2122IB9su+F5Y*-$Yv?dqjOFs-wDPyJw2jp^Si@MJsX|k>pJqsT9c5?8wiccl2`Ti@Ph6N|58%q3 +zOgQXxYMoy@E~qNcxNjrIjz6W8;+n72JIY0%`$dF6(qrS~$MAldb(94gwG)g_NLIvu +zUT(wGdCa$$7f)FQ+)X2_oD3cll6bVkweY;4akp8||5G;^uF(g4vAQxplZjdUmJO@f +z@_GK-$H)4TT=oWZLB8^N4F`A4ed%6Ry)iorPPZB}jxyEDM^kP{FKWZgNEc!YhPjT_2Df5Fskz!_oD|#i3*?~ +zNOcd)C00=#YR>geubYVHa`O(hpcQ&n>}T{flrl2mLm_F!@1RBUSIUT)y? +zT8bt%=B92S5QXDV3^qweun>0mUJexu5P`CZgV$iWu2fez6@Kd%?eLm@g4zE9nLo+< +zK@NPC#J`bqg{80V{i5fWgA{D>f0-WepZNZh9{Asu{7DZ7oMHbAe>i^E{a1H!{N~wD +z{&4)-we#QM&;LTKAV1~tsvjYL!#4GFyAOZS +z^UujM=Wky8LC^0#{6)_{C(m5JdGQxLT)+G9Cp}#MoIG>==EWcM{O-eF^!#)3%>A1e +zf6(*04}a3b{m;oW_itYOMGyDyKKw<`KPS)Jzj^ToJ-_?#7d`)7dA^$0#QvACi3iS& +zU$BYiH*J5>d-W!XKj$}||E_%fAL!+UbL$tq?Dzgg0I&Xk?N5T)@BMQU$bRo{MDWMf +z;(sOSpA$m%dw(N^?Du|m^-nQmzxUsj!#{BX``_Vn_N%o3|H38qe@?Zsv;StuU$W2s +zA0YiNfCYzUufY=an{9!QlRph5JXAt04*2cO~fX-yf+z +zx)i+rNsm4i*fe+0JmTQ^%kKKaAOb7+19yO#jopmx94&vf@dv4(A?Idn2Bv^U)^Az= +zB}0Dd{uW7H@IbZHQ3=cnw_JIs*|y)Ioo}64{K9%6)7Unyif`EJd`c3?sOhiOX +z+WZ{++W+IvWh;Pp4G;o`kPvPIhV1Sf{YBN`hn>HG9JneYIadnd}U*_+s*_Wfl-;)Xv8Yo2vvr@(LzjI +zg3vK;5)qS-(%qqFU}S=Fa&hzU@`>MLRT;eqW!L`FtJMuWEt0nroQ +za6DubYIf8cqRME-&iJ=E0MP*jBq0>NAz7d+Z3}M`)g?^#ig*WZ0W&iIQ7WDtA +zWxpHtSGy(wEF=W5^N{cWVPM_C!BV$Std9zz3t&GiXdZLE1O%5Zf##P){=3KAXR9Zp +zoO^^!imB_zf?n;~R(9649S_7I=9j>e2!ETAGPN5xQpg%Bsa~x3rs?1dX9aCPecWxj +z1R4qs*PIs^re>e}R6GB-+|c#w7&VX`t(Hmdmi=Sli*rs3$3wOQ&U8{}G!vVup4TPdTFI{Um?}t+YHhpzASjd}1M!b9 +zj?E5CXyp=kcnR=@*n&u9x>+<;DqI`ZAEL{meGsWpV`y6rcbzw7`%cn<+llGKma96*w!`JR^HrsRE)xyy1ZgtLzWT=T&;;j~c*=(y^ +ztkCz!WTZny?PDu`+1vB@>()#Ak7lIua!eQArncwH&`3|Ez92KblPuxq{3R^;Lhb^a +zH669?;oyJ5`ge*d*CcG^4^(a?JtJ}RFk +zO2foL8S)S$2$X(((KtOX0ZLc@X8%-iRsBn#b9!zkeO2jGhx+&Bbzi*i$|Jh|oh63b +zxXbF*x7Y*)x;l3>F98Zdiz%3($tB?A&lKNWI{Z>c_Qqsqe9jmC>^K23QrSEr4Ku3aGCIzqQ0sYC0~{4@ +zHg8-=_$KPJS#tW#olrdDcsOKUrQwN@eOCb}+_9(VS1RwKp$dmpXJ=_&0v|s{n8EU@ +zI5Cwy?Nq;aGWl)HfN#v`OefWR*)MxFA}G>@#`j)*oAcaI>Bs1#qCrNyRx;@1!WX)? +zFU=JHVv~<`GI>tq=(=oLW(`bGX4Q)6iXh<3>3Q+;oxw|Z4Gbz0{IAyh1O1{z}Ql9D^8*|!9ne=%4 +z{{0tZ7E(^Hh59(t!%C;}ZpY!#p^L4Xj$l|UOK +zy>K7lRocP8=5znmtVh+A5>5gQ!Jf9e+*;2|QN==dl+nA@5z{3Ir{m(Hf;}UIN$N4xAr9JuJT2Op!!$)}75H-9NobI5ea{ +zu!!y|QtB{eOpDh~p*`EglG`S`Ud3Ym%yU=htDCsgM~Vdg7rg2;+-? +z#h1-&O4jO9SBi?xh)Pe+H}FEHIBb*vBphCnS1EU?rz$ZM5+etG_9(Q<3cz5<3J|`W +z_?!3v+&KS<2~~J7t_&4674~}|goUGBHWhA+E7972$|!`aqw5oS5E5xDDry_{L*Aoy949LHgcy;|V +z{eOUnxp<+!5it~uy8O=|F@%?!{r?_Jj1Y@h^Z#SwE3E&2JtjWj6SHQ-21v4@v9UmX +zHgrS+KpskZph61h4a(C|XP9hfLnp;WaQaB{RFsetv!Oi<2q%Agd@u+mbCRH}nwAj-poNc&frFGhcr^P{wX +zKRVKj@ +z1?J`rfwu_2(@F`d+zgbg==cC4sEQ?l60%xIeB>aaipsDOA}K^pKEqhr+8P_6qhrj; +zK#Uwt5*I<21l8w_=-3f?fE6q*Y!Im+Z{^>QecaG0pgt=)1`2Er$w&Y!1k*!Ffcx(w +zoUJ)o0XIWIdaZsv9uL2Uh+s-^LoEWxC9Ug0%0MC$GtiWig4UN=jI7P*t+u9OHCu>{wXIiLX1pYR2{sZqHiJvnY7JaNAxX4wk +zgf(00CPDNPj!JjV&$*X`-+_NIUifIPA*IAs3h>eI=ckA#43+$8@Nt8k14;v%zKBD@-Gq#{0HSO0cs4z%|3Bhkm1QS +z)g#+FKhv}FZA?DTV+`9sPG!yB@p@a`!HDQy70jbuq^R&s~kKfqMckBi+Z{+%H(=639r0i4ph(tNuLm<(w9(xcKzl +zKe1Sr`G&2a@%1XrcVfbiGj!TxG)A+cqE^k_d8i5&4~k!+u_Qs#xbA(=x&(0d`E8h= +z!6rt9SC?CMqQLI6Tc_OLn>+5h1Tf0M4op9KDKv0;lG-7`;e}87TCY;yHD;qq +zFG`z|1B$tLXtMne*Xf_es`oK27LIy+o+VI|1H#?e%0GO~6sEr5sEr&u#y`U +z!5uxp1H9|$fS_u6cqIS>a`j9SBSg{)iRgoZvqSwN?Kq*m*R$o)OJLq`xWaZM^Bnr{h!b}4 +zgg{xB%m{%N*MPYu^^^3FMLZOXCDU>u1+}%$S@{wuRV*l*)2fZ$k$7AC#8d7r&NE0@ +zbPmSShXbk1Ae|aDd6hkq(vD11GNtLd`|*smPfU-+5z!113p>iK$KHxcesK4Jv +zLk_PyzhFvc|J%jab{W5g1HM|Yvvn&$UcxgofF-O*|qy1gga5yilY({ +zeLgr%WToE0N3USK@za)lQz242?TyDwAL;u-oa#IHTvNufi$1e_uC^^`+Vj{N*!A(T +zoUHd1ze6T)&}sSr?|;`^DUjsLkyD{ewsoWE2} +z^!Th>oJZyKN2*l;NHi|RXuQXp_7WRSoD2!!xYws!dX(ddd?+17&uz_F-gx)1UuplcCRj{D58nnJ6 +zY}mIX2msT`FkfW}fcPkzVifFu=EPn324+#dFo?PC+;D?U>#pXxuPE#Urd~>ZCyX8A +zV4_!9f^dz3r<$%Yw*Glw8mcwq{j#4|KzMhfRr-+wd9Ok +zqU?}Ga_|FzHXnnLYop8dk`hPG>4Rb01fplA*Sn4El@*mH4i3sZHAZN|r^JU%l1U@t +z?ep-$BIufT``N>pOPa>3rZD4b8{dX7CZpL>1RT&0zv#1+f1POD&=kr@A_ur0`}sWq +zjBO0a8WWVQ-7bO3$%vW9b>W&)5=y8fQrIJtId8vRjE>kqXe-d^8bjByC)ybJxbtjf +z$!#WO*!01dpvbws{E*r2@w#jJ+Ts-9ZQCT%iEfYD3U55}vgx4w*BuZMlG=E_<*f>i +zKD%%S!pT{BGi+jFCOzzlf`bdx?eRq^Z&EUC^!HmPu1zVXG_z#}ULiAgx3=xHS+nE6 +zvh<_hLOZhqu6EF9is;Wk;d#QOs;GNIG +zK@rk>ZjW6(QAfUR41FnY$5nQg6}DO2z`612P0nQBR6=*=pqehoDys1MXEMB#(VJ=1 +zRSj>OB)nkVwirE@-8-Y#rHC`IM!&%_BCBBLg-!Y*vsp_g_K^rG&YeDV-!9H~4HA<+ +z%eZk+tysrkkSr5jU9a7dDM06Tyj=J$a^-M_%+=I=!g-0 +z3!6Gq!*;aEb7q#uZ%8oQuJS_{s?IMK={S?A2cl5=Z++&AL)-6MRkiulsaT_V|Ar!M +zF_z5wCg{EWl&7_h?O9;M6~ZZMu^t%Me;zi7B1rUp{K%Q8v8FbDqu(1j)AKs|Vp8Ba +z^!QWKlfH}Tq3RKPOvgJ!ACUrD!ym;7l`asDRO|YRqb1^_K)TZpsl#uUeSBmzZu}-n +z?d~q5<7DYgn$&Wz2+8=p=_$Evt(iFQt!Pcl2T`wC+Xq_uPBmcG?0p1q>>R6vxDqz3 +zEP|N?0l^-t6$tH!pcc`gfZk9Ni11uxk{B5fM&UP9torB(0E<{s_-#pR1~~Q%1$5w# +zvD~rB$-q*)ezD>Io#>#%W?~mjOBk-Ei-+NAdYk+E-pM0T2?C8(D$s!nYGm*|GpLGy +zW@;y_S}3d0&lV=46T)|qrg(w;=?=Y{4>4ljt^cboB5_$2fn1 +zQB`f?{Fwmzl#{t)>`j`;N$o!Utt#UB@#41IxM3+Zsr} +zueUYBxti2s}By^ +z)|vC5q`>0sZ$}v{`lOs#lPRA5(5e1b-j5V{)$VVZcGO2p)bH5Z%J~f^s-iRvd}$Sm +zYm~M^ib#0x^VrGeX4He)>mNDv@9#x6=AhjzL3?mI8e>fwci2(r%Gq>t$CXTy=R@Y3 +zuGTGj@?Cv>)Bv81x40^AUub!=EWF&w4U!0xB?j^%6-yOM*J`8J%iS%~>|AyIQnO{w +zOPh`t9622$YDCdr +zjIj9)MIATCje%~hv^y_rzJ3z989u(p9f^>_*hT-XPn58^*tB#VGWGerGs<*9Ti6$A +zz%-9J3;Hw{aB=Z+*uDhLWNjO319!+^>-S1>iMA1aVCqn3{l20#_L)1ZcNd~%dQ!rZ +zrGyTLRg@5hqeB^htjHm7oHG6zdH>TBEP4MD%5Q96wGJ!F4})PS7t9oInJC{&^)LEI +zuq7-JC`&lFU{aoro`xP^K3AC?*Ur5JG)ajZAgv^vtGhpt)E;c6>|miW>_309LY#QxXY43+$@-L9mo7-h4ku4>ex +z4%EhaiPftev>&(^=7OR6@=qeM<n_mIHtHB@A3B +z|9(_^6|!NPE5Rl7@2qYCBW@b8%~0cKFnr!nhOD>voft0uCBKI!mE=Xa@*l&qP3hQa +zdF-nKL7O6BujdOeCV>q7ZKtzi)A1#Ppjbr-(K9C(8Vjh9s!CfSFfv;6gND3kKB=P* +zAPd^;81`VcYu5ZKLn7!Puwg)8#AeKa0v=i6qp52MKk&4QMc6N_EpZ2QORx}tjt`*f +z|8N_$;d2P85MGqK2d~WyS8SLXY@iLb9eM&SLNz1hH=R>M&&0D}2j>3+Vsm`v?0jjJ%3rf*_Kg6Yi$w0~d!M(%3xHotS$aa=1JpDGbUpKe-@pKK8EW2OhO4Pvf +z#{iR9f?FVhSVYQJS)t4P@BWArBL3a^YXNmI9yJICu;LuY(LyhQ#o1~9njaGd&+m!C +zD4+hc{WR2`S9qLlRK*u@dail{ltmQd$wR_=`{5t_V|^Cl +z&S8nmDC8{!V2I1ffINbd$^wkoEYu)ha&xW@J0j?y@B-G1)>Qzhbv~GGPf!&SaDC86 +zS=tH!xi=Z}7N7&|J9xGqlN<;as#HK|A@MIKN +zeN)&e%zd@lzV^879Gk+v{5WBc^J!&-Yk6A!-X&n@yk=nLKWEq9{sbGrlQ-Mn$ +z;q)v*Y#;w@<78-s9-d2R-(I*G%$00?v3r&4MVkM|3%|~c6A&8t`SS^U1`z;Q>G6*Y +zhI}Jui+fOCo?{%J^s9W{|C;X-NWCgaU;`v&$?C{?o9s{+UaQDeE8Tu(-v^`410WTo +zf90bX{@GXxyQ{`>!P}yTmTG=+c>a>YJ>mG%pY{5$bb|NSez30fq{eX0uxr?R9R4%3 +zxi~GDtGEnnUTlnBxi(t)ku-333TBd0d3sW?2~uoSmK>Y`1x(=iNS +zKgd~UCL|LmFBB|T(wKR@P`QEME%6)Fp0lNW%xK>{`Or-8660?^SKc^8t+cB+=y{|B^OrmWvL%i0j2+W6$gb%44t<0y+`rPKg>mU+d +zR0|2kqsG%SE}aRxBmMrdO0#V^hNPWC+H4)wMx8BsUKSh-cyWaL%nt9}PJLiFg)yfk`T3z2T +z?{&4Ct^w#+J~z+=tq{z{?>oA~LU*tmpM88v$^Tj<1NULLuNroNKFikdbSF#QOZ(QB +z+PWw?ZB&bqUIW8rLUCk~vr;P@7kTQjgk&9R48(_L)g;3P+IQktwsNCYZ%T(TQ0Q(G +zQ(UYe#GlT`u`DHxZEbDiP0+I9&LF1*ZsIT+jhdycOfuT#Jl5+NzP}uZB7&CUCU8)Q +z8vfkU9NqNxBy&K11jHq-?O;RgV2b~JfwmlX8gGAOCK_wq`R|vN}M0j&{EVZQVh1%ESjm*!2%>3FSsCy9t|Q}6lrGk{;FtHN5~ +zg@KCY#nYb&@H%$#SEZ7PK;4k_rR&+lB7vgh-WON;LINCcU#EHTaATxmRK278ue3u8 +zs2rG|QsYK5>=ik3uwAJi_`~^5OZS~SpDUf>>3*v-)iPfMA{TF$e(w1YHq?ugWGRJ3 +z9jmtRX)?am9L1{0Sur(gQ#tj>(8fn+kxV0`N9k2|>PwaTc<)1B7l)|^4F@XC^xZCD +zfKP9sH^B+%n)P3kK{nL=tCo*PzOT1{!_8r7T9Y?YxA0hM^&FA+N7DEPAr6sa4DPm! +zt6Iuatg;=;*JQ4(6FzGz2x-iZ+*+xVkc{Mg8Prfd%jCRoIvD_!r&FmL+bsPMqAiW* +z?fd$1RLk~m`1c}B(mj#Z$JXk3p;TG)Sjn9li{*I?NH&pU%7r>rHVfh*>6`QRymKk0 +z8k~@Fz_5@kIA8yOT?pVT#X|oBRl(Zf|qfe~SJ*J>7n-n!`RsEYbcmOdS|ARIp9f +zULwMYDRJtC*ms%D>~q(C*LX6UV%elyP_|MVX9~_G9t2C4f^B)&6nKDok}*$0|CtPR +z`Xlz3sPGh%fZNsMMa*f4nb44kv+OC*Q>R?Bi5JzGBW6y_;*59t014OPKC6NR +zk6j7q8$wCz7PnTc_?fW9T7_!c2QB(yGfNmnL-j9fQhTJgaq~Gbt*NIU9J^M3_FHhR +zW$s|FCGOxiDbtxswhAT5iA#I|k@luNbEA9$Xk~$cC=?bj?1Y#d=aQF0fEOh~Oca0i +ze4%2cg7%=SSsIBnu%wN*9dI!;5{mVEe5$E=M0b#TQx3Ej(?8?pGLC${!JguyseMFv +zkk@YUMzTc8&<0q3)GGQ_?jp^PS(~l&gJ_tl^i9raDe2a0B_9yI56O#WOUY_<9*(qO +zbnOlE}r-?AVtFZg=a1pU<1N4oS*%` +zJMg?TQSyRscuJX>IdYtJvpygV=ZB9nk|`lhbXEhUC}e8N8Gu?9u+I2HV1Dul1;kf~ +zq*oKp70$$^A?b9?b?wfX{pe>+*XvPqG*DkoBivj^OoMD>D!8Xu?IyT!lli5_3d2sR +z!K9owC9|DU2>U9@T>9H^@ExeB;ek-padgwLb_c~B*bvQ4Vyf$@1pC`e<|FQm(A?oA +zuAw&a%C?mt?VJ;j!VV$BNAd>A+BG4rx1?N`OM>WM-G5kZ8h{|If-2H3LI3P-c3f2S +zQc#-U;c~W*O;yg&XIbZnxOXx7f_gF{kE5x@4f&=}f>>VkRBt +zaz{bPOkm!*&&EKPWv2LDZ+FV|jWKCnozo%v{=8_BVtOE{_sZzI{VR#P&XC{&wN{eeq)6#)7E=yrbfU`9>a +zJL9|Io9& +z-0!9}iboUnL?c=J6#hM5rgWkcAKJJWWyVgNj!yr +z+)}O;Fr5=fk~uJo*S@2jNC&ydB+f8;YNTiMO%yTUCbwW&_1#^m+IWMg2qpq#;yDZ_l1_;F>yy3)DT|VE; +z5po&uUsu;qd5iml2!-yvogG3K8dB0)q|v2=nsqhIcNj +zD#rF7(Pc4WEpt1V(=v7nkUgsAqmodUm_$R665W!y`y5M=wzrTJQTx?56u_jkcSLvM +zZbAg=2Bkn(4&pZZr>SV?9px8ih19lraf?Y1K-WnGhnUeW{AAjnY4V<~p6K;^?X*;= +zVFbvy`CnByn^-t{20MoHF_vAV7DY%J^oDO0EOINlL{FA%YXw(SZVi&9_tY>Em(B-! +z#$Y)+@Y;u>%F87I%5u_-RzNPu4g_b(p|5fh0D{CV35MJZWDJP%B$jT6UrVVh->63V +z?iM9zkwQcWRK;p_we8QlJ-RW(WI9ANXz@||Y?VkZ#g@uZi%4*uj+HKCrH%05>ki6R#;`+LG;!>^O$a58Kl8;3p$W#Wwd5}}}md)o6 +zGn(zZVS{Iu;>Vtrj^l|LP2U9KxlP;zjqt>lVSwrn9uSHqS#h&ggX_wrVNNT%{jQV}I~An)ksvRYKHS +z01hasOQU%*g@1r-CX93QwmVURgxuOF +zy0+x9xoLI7Ju0lj0UM8GPtGNd%4cJN@3vmHeqEba@5+=Ge-?S?i1jnM)**D22f3ny +zmo_aHVW27DW9EA4(a37s-HBvJ9?TSksl(zJ=ti-1dh^AHz`$p0v()I_g6pbWDRwzd +zySJ=o;(GSTBhYrYG}KLE#ToQo?U|ZfW1c!uLe)s1EjvoU6$n2TQ@vgJFdK_KaEhGS +zBqOwE5`ESxQ$1=wTCiV{P!IrZxV*?gIBsLJQ8)l%L0=u*%Yee6xwqiiA;xHj;m2Xd +zA$}Vvs7DQd>UIDmYpfD2(baCSSoG-e$$JL_Vel=c>od8-(>g3|sH}}+4VlPG_*=o+ +z8<`*CxsD2Mue +zf +zc{g%!*fHd06M!T2tF$x_?Sw{~Hj0q!vg25a-q*C(VP9iGI}_X@FeaC5yOEgR{9K)s +z+wcw}4gY6)0kYjjmQ!W-k_Y|wiSMHYNy-#m0+XKU`=kDIw}Yb=8S_nbl`Er9jIGYA +zT9;(a(9(~!)M`E6>9a~3a7I0*W$193@}dzQe|-s5fv)Y<@-;^PsvY6gau^>2{YKRp +zB&!PL?$%JqxYp=(Uoy3cGQ%^4eVDKRVphbK+`!4!B@iBp1kYF4M^dJHrt&*&?vJ!0 +z)CA6+OTcFK5*TnicT>J71~()Kw(Jgx_<5vTxO?Xkf=f&ON-h1D)cVC-R_`(uL5tm6 +zcY78G3rdUSCHbGV8ODYe`6}7V;bDY-bd`+Hl0kAS6wR1c9?z-*BQsVoaN$m@+FxoE +zKU7Cl?uTsv;CE425HXZxWU)c-E2x=&q`~nr0AIuc{EJH>Isl&{ +zjzCrFE`?2M#eVl9G3YE}N)`xh^Kx7sp&f}I%iKo~8(3jPz%+}5q{U*5yng#sxmq{b +ze@ +zrTYpI;^Jg4UAOopbgxDF8s9YD +zQ#Ed`7@^$N`?D&^nlE~Z>9pR=FE+EQSNUL|ExEJMRfA2T2vZiQq@ +zF4*9!LdwB-!tz-ZFUHVmdBl;OM +zKB!QKM%xWvZ8No|X#L3M4)wdAsSqKfPV73QI`ZT}EZu(dHAtzw#W7X*(~E=y7tK3w +zKfF2}Iy!5H2n0{2kJ3-`4vksFaDMb_-hlabp9~#sl%MR-uSy*~JbTK=7d9weX1Mjq +zaDN8$wF%9*gR(idpM56e_db? +z`A+N0mhGq@T%X6upRKtz!xFcbBHkZ8?Ts0zmtMrms5A?#4lJ_o7xa|KgM49M0j#R#ZJvxyTh%T$cNh@O-U6Xc%$N`el(`1BZ3t>qNRGwkG*5+ +zlR*!+bEdLfo$_>`W^?N+5|2K$V3-gM=pNR1i}vV7Ed9-;P=8~^9ZpIk@Sv9!T)BR5 +z3B-PEsNLg=oKTgoN$!q}>agk0hLs9cCpb-srTgHps$+>suitgxj?!6kVU8cpp$)gq +z4Oq4k6l*Og6^G^j77=4sb2!O2kND#G+yN}r1n5*K_ye?LF +zqkjK3TV3?~3gWZsOf}Z57Tra`hzX1)*)aNUHbc%=H6bMy|dgqe>F_DCDAX_ +zy)M(aEOQYrq;8P1GC|kcGgrsnHR(su8uFTT?`;(=CQArbb +z>TM&wpCnxDpKr)oa~C8!o*DRWXPjeGPL5mx?!ru&@)nq*fjWEigF2PsXFC4d`O8vA +zC6~aAVo&A$=j)7~7-Tor1m!8WzV^dMgeF^M>Tkv2fMV7zt9Ji~Me3fK6FIzM_QY7$mH2UplZzIXv-Z&a5!s3kj$S7eIZsoTSBBiy8f$7R&m~#2?AOUL#&Yem2Lza@ +z-9_G0;l+gZagKwblFl$naMzaVvqA>Co@?E(cL^}x{EI!SUnjO6p-ZQI3d`EWhM&O| +zuLI!vt7du1t5b0MAdPO7@?lcyyH09Xq^SocF(l-j&dTHA;NCoH-0wii`hj(K5BeL5 +zg-+L{ns?4=wgx>;i>0nab`oGDsDas5&P2jXD}7OVoSz(nEHr5U7J=_*h1)q3^FV`8 +zHGvS+&G-@s4TZ1a7#GX{y+Oa?qlmnQJz}spy0?Q5UDc{Jrt*6prS}(o9bR?hTs3Ki +zeC)Uc@O;Px?4#7H4NuVe4k-I`YIv0&jQKB-a}WCSEeo8sAn^uDAcC4MsbBHV5ed&N +zJqk&G*$tHmQaTNecDvF#h6rBXvx!aqPo!l-4Gm-*DZxAXZbZ)0&t}I>MrIggXe`ch +zkh&B7H4(h?lkMjH1>@9BL +z{Z=qKe5auVS5y)$BV+SO73LaNA1_1f{i2q|H~$e*=S{SQlK0PJ&9*o#EG+MZjGQMl>CrpT=~_ +zThVR#sT?9AcKav#8pPt;Cc0&!ouXf7s~I!sQ$A0vYyziStCVF{Na*gixs8GOw^$a` +zLO0CJihAD1)HxxhX6(;RRvj{**rgKQO`GSTjk7a7D8%yc7YzUG?^Cja-q}mMCw)v` +zs%rpXrg&svZAq?gL1i3D)o-WVHxsf@XbVe2QV61e)X|efcD{F3 +zR62SVmNYh!WG7FyPcq5T(!_-7lCg*sUVqO1pmrE~X8j;iyCYl_IdGJsB~4ztx;m(z +zjdhalIV1&lf0F@^`vA1)!2s?bI%-Ser>276{9}bBdvQV?2$rAwgWFjfLdtX&VM5?? +z`G+718h@1|dN-M9ddx(QEX{g9efAL{xu+N-b29jS!n(l7@KtRgx88x9Hr&X$PxWmK +zQIGIvLVbEfPbDubk(`Eyv-xL1b@UZ|wven5L!Q#_;TrWbY$=)&xHBcPw0X6%?wp`b +zqV@;(b{oQGqkhH{GYlH~Fd<0N(;43s!frWyrI-n84@NpP6- +zPci2|+MY>6t2V>viMZ4B%r1V?qo!Ua)~wu7r?S9C*j`;C!h~^vo|n^Lm@sXfC-sP# +zLSA>w&bSJ%>cJz^pq$m+d{#xP@;Wz&;&z3D8gX%W35;i-c}9Fc +z<^?wzgG+9t#@0PBv&tHT7eHMC5T>ilOjnP+mz_uS0z3!_eV_}A$cd=#tLJ|CXVtYi +z2PJX?-_I0}Z5?I48c@)GALb126epTFXSxN~NKix9Zv~Ez)=o#2V7K}1T>|aTRYDoc +zwT^<|fsmhH48DQ$;5+BSuZl=5C5k7(3%YaRRF&aVjQt9KQh_GNU82m9$%~-}V=X_l +zkzf7{!Hh0Ubi@yBzf5%i1YrqT(b?MMv3L|xLzFvDDtdvOUWXKjX +zFq_de?_c~CHiqKM%l6$(Cw|3SuPH{l*Jt^qc;Hv%=VSr*A5uIzq_EwdTHZr_bco~} +zGXrCY4}IMAC6@T~5~!9ncVFrZpYsWHkvp|Y#hD-R16K;xzGVMjA#lIU)#vkvnyQY+5-yWcvxK8l7ek^O@e&f&;EIfj3*3E9 +zh7DyMaQm>o;)V#mYCBg71CR?kzxc-=eySPw$xbeeX8Cq!W?~iV1ZGmjOrzAC#-B~* +zpsb1%I9@36nt`YRHpJI673>h>?fX6zCUS!NF+BOrjIFBr3#I5U*fH|UTdN=Iq&r;K +zx@?|KZMUpeJ`#)A!Yn`895d*PaWTZBJ4jNDuGzUuX=#yCQbhdP0O4y?ngZWKjh+5v +z$8&sBJm$bWyLg<9(9<=pv^ +zW0&&g=Q6i<2|{DN{#KwdGhlK4gmRMGAHF?Ds?ylC;GE%{IRQ2V&XZ|dCm6z24xq)~ +z2vTM7ZdFynWo}aQDy!T@t~Y1{P3;j}Bx9yZL#sjC-P*u^zyn^IX8NzvigNqRzG@EZ +z(UkOJQWFbR=au35^c7=8D$ArXN2 +zdac#J)k_WV(~oE$JVkhFYoNr=VYDfxm5%B{_yj>37U{|=&cVVmGGE#0l4+G3;X-+_tUtNUa4Tx*t +z5<;Y??XaokKEj2MfsycJFTBc+7(kHl4Wyd)T*G8e=5cLb%~b3uYf52pM>a0vjUJ|r +zxoI|3r9Q^w<1bhV%H}0d6$U-Pi)gubB +zyCN?04mmKhY`@oBbPZ0_R6X(@>pTszl&9i3_w-5%OB&M%jAD7ZY`1QaGvB6Ge?Sds +z=&Z5xbn`5ttV9&DehH~jDsD&n#84jP3Hn?ZC6kdfA_CZXGWyV^OWjT%U2m4FGNm(> +zhf6LGIU8insaRS3&Py(&59kYOF0=fn8PKY*ORu~nj-XYytOO8hD#&}`*_sd- +zLHFtaS1<6&MZ}6OOo15rC@+q3+DrM;7T*k03sL^4p0mYdOwM +zi$l@3mG}Yjmw3^Xp7#fFQ9Pw=0irSHy9_S2pF4_k%-qx{^?ZcxMteT?mVUVTv8bq!0OLL!Z!x{a%S-1N6kDQ@&yht0;wGaM$a3~7%c^Ib +zjC@EBIU7WsBd^)sfVZ!GtmokvP9bsxW<@ +zOUmyqepQ$ws?%@oMvuQ@g8Uc|`rpHGT*9%qli9oM-a~vvBi%`eDbg# +zLdK|_wZ(L5vFiO~k{N)$WDtn{B9`G%CqWr+_mNhemsOcZ9^7sz*f*a%96uNH{dc+T +zhdFRH{{G5x+3(NaZL81Wp3Xqe@|a^3HMkKE~dgT|s&BMSm +z%I`q4I# +zUsY`!f+ieDCHj^Bd`%#eeFTG2In(`JBUHA>xs4~ED8Rt-v^BC*^v&-(@5@#FAfBmk +zK!ID>;d=eqKaLE0nd?42Hl79?3zaWnS%=(6&7S^ghu*~I`Gct}Tp{l-D@q`cx@ayn +zqI8cP(}FE#j-kRLvnkKLdTl%|*AiZ-0iD4D3yq-wd%C7goTrt}yoKg0mEH05&y2s( +zCyB_ht?Ht2xwbswoqPPm=v9hCQb4~e4?7F^ct~wE+g1mV)OvNx#HH5&x3Wz!<@}kZ +z9v4DyDMlu0?kB6WhAbX^{-gs{%@cOOi948(1;e_Wnh*)vC<>lUn0v`5F5Kd?Pv&tw +zc)nK!lDBGosoa-Ksw#20w+WK8Sb}$Dc!E0Da&`Llhl9@bGDs)tOx0vSjt7Js&TpLX +z=n?&^R{8-tX!Rw5x2JAM)U0Jc{YQCPrFLH`BJ=^ji>_d)lQ;I-wgO+1%29-@K6==O +zf~;A#og!A$n%jMP3c{lvT_CrV%A6~9xL&k0_CDNX_{L-!^JVVoOMmSPtrTXw4>INy +z2+QOuj#BINdh!^-ZTFSUb(j5w_KKa&w_gvBj4Q{ql}UR!8HjB^>huC +ze*R)&7qcSF!+SwAKKw-`s)DrQ?OiM83l7&~#mO2`t5yM$lSmp&(u-Weyw{e4C-z4r +zB0{C|3RcXB+1UfP1Rx@_~~29!@vOW~MgCn~kXL7n24Gg|M#*By~wM)NMb*>&yr=J3+?KIzjF2>f` +z+Wbk0byS+g(FN2Nbn=;=8BA;T+L@tHItF7M&c8pPgzjx=EtutmlT%u51d0>JT=);y +zrR?tZNcJ319$i~8$x8IbNnS-svnn5Y0yrc`el_C@&TPqH4qj7U8V90bM{n2;S-KxO +z0@=N^>coe-2!+cb?S8}b>ULCIwp-oB+5-Cu3l5XhZ*#HUT~E`A^WE-e2$OF}-2$Y= +z#McROayU@(#}`jN;7(ihFH6BZWq9ZjLV20zhs3inQEdI)j}|UAS-8O^QBB*P2{zG@ +zkWMs?-#grEJS;5<5KGJ-Vwrf%KkHP$TSFAwGJ<{gN*G_U4bMXq8$p{Wa-B{rocsz< +zF}#r*4MPtUrH&sbFLwf`CPhQfv0xtJ#XyRH#r(GE+hp-%*FeqGUv2qafPWHYp;`e0F@iyvU(|fV&%Ri)i0C@*K +znQ;)tkFwZ2*||@7PbBfv;B(VBLWB^!Z2ZTZ526>~uyaGW4u$cCH@4iYD)=Gpggk?D +z_K;jQRBS^pqsE$d!z2jIARVlnJ=}6_j@I0T#x3le3Btro*VKw>8O?L*6y*w-gN_l +z5}C!Rl{OhDUb@`d%e(pq(mNFI8pPe#>GFrzvS^aIx^%w0V);}pK_jr_0Ih1Gw3hzJ +zq9mx!F&9sII1IjAx&f66TTf?jw}@*9bP- +z>3>uef}`f@h*!;rqJYS2liB@f250KBI;NR_S3os7mv!`^k3jh&a^eFG(hcny!Tc#< +zqUOwODbEn2C(sYi_?x8gpsJ?Cw4H7)O!ua^w&5m?(!W&Os1Ukbq_0}q`1$hogJsgd +zoF$pT{3-DgjI~fv5Q<^3cd*B6hauByR~SVO^wqtvF&`Za!26ouRK_Dio|fq-(inO6 +zUhBYpV5@fg!@>ILYZ^=j!V&}XS@w4nREdE+Yk?;vLA`&x!-j|)cqIpN3XtpzU%HKx +zk2A6!jZdUZ9+D%{?D{^%J1IQNuO9rZ$G{gy4NQnvl@U4<+C5s>kPX&s +z@tMhUH*|+kH+}ajcIDa0+%{nu>;vP6C`M^Wom*=A;f@>g6DSFP)Qelm(Aej^}>8P+>~|A^+4ktdnfn>y(;5cm}^cCmRVTZ(H`9z)T{J* +zUl`l^=+H`FZxvC>HN|EbBhzy&54QMRBzZ*#n3up-U<>5hQ=l;Ye7EIv*Ozz&SrP9Z +zaBu0_6Ogm(<$u<4nQ`CsdyL9s`nzm<0Nu$f&;F}8C_#k_vcH)gahTmxM|v;^*;@cQ +zHyvJ_R+T-9|GO_0R%JpSG62xT1N^K(hFP(Wbe2f{AX6E;=;7dX-R4X7mhoSC9s%WV#-Y>jrc@3ZYPA?Z<^nyu@Blc}msLLvX@7Z5{R+ +zme%%s6CH0)o4}bwE!B$fnGxWep4kbH;#zo?jirP1+=!SCUw_cD9)Vovt34aRAWg1D +z;DQB_>K=o#AB@;1$qCqycgRm*embcHM#V+>0z&?<0?Qq&AMjMU^_BXGOWp$zP*@4M +zS-y|341tp(o-2j`Za}Qkh>t^+PO)HKjQRjr@5Y6`(RLNJmQDG~{;Pgj;rk)s2B+W! +zy)~s#RZgK%l6%59LcK6s4}Da;qtMU4r^iazKl|&Cy44=Ne2v7@nj3X7 +z#k5nLBzDN8nk0bfcaL|l**ydC8pyw#9!qNC5A~o~QK>>zlEIG!SL7v9x`a_m2;)cC +z%303hTF}H**woZIq?0cLI~kd)zQiXQ;I$~Axj48R5JU7qp2rXTXCm%bBPrDT4dIQd +zGCNO;Z8NGvhP4aci`(b-u;AhkNFHOsm~EFqfTbe;l9KeW8$uT{q8PY3ubDy!q3UyD +zm_)!cB1=mJJgZILe8!67dI+l!h-iOuoPh-GMZ7xD>xsWDO?CA_l{^NU%zr3EM**JH +z7E(lX{vk(t1!lG4=jWE{z#&QMgRB|SbaLzB&NuK#mDHdU|$UM^h6T8mTL1sP66} +zMoaV>*gW&Tg}=drfeHb~H18y#Uffe{=%w9$!G<~T@S^KCpwk&h81oeQ5#(~G<;(lr +z3?#9f7ZE_-nzP~Sa8h7J->bd>-PVEt`6voqxIS4}lDnkTI~svPxz9%DHq0?Wm2aWI +z+6wIN5a^WyJ_NGhy(LJPtTZhwcI6vg4aA<5&^qvV9K^E**EiFOPAxpc=ms?kxmVs-x7SHCEJ_Yzn!}uRRCsL>atYN6q_n%*Y?;%h- +zFuM0cx<`wI#ypD|lY0py4rJ|^39DkemlppXt8;P5%VBKqd +zfrz)5g0jRZ;MrDPiro;L9sK&u2$=7AZv*Mmkxen(rct&2G1UKlF>OO3tokdPrv!8~+gRQKxnt5yU +zSf)Wkb(Z=&r8NTHE~4J&IPHdjahu}Cm`j2DoffygK9B&~oM#fKy{6nMzjS(J*e77*Xk0w^1jYhw2olrd +zbbX>S1yv~;QjaDC$=B+EElr +zRlaBI=?zbU)G6}G@Y2X52lj2V-9E4Fj@bU~p72q7i +z?{3X14Fls2BZl{Hq^Ky2cxRIGi&0VnoFD<4-k+)T?$pJ9`4oa;l&NFMLmR`YBs_Cm +ztn~K4E3(v|S1v?VAXUZQdIvesvFc;Ho^Ul>u?y+!>q48&g;>(*>iObx;%I4EXHY+|CVg-VEfEbb#gWT=fHIc|^>npU&KXL^y?LVQTYjgLVO~WCJ-OSEGB- +zat2s!UzI`wXko2yyA0^7C*~a>D!kh{G^+?4whD^5n+qz6!sR+Ld~tKM3K9l2f?&R+ +zkI)4>tHL=67bha^sK+5Yq1W5reTk;2vb7qmb9#pHpD&}c2<=QEl2loK?-}3l*U=Vb +ze-$n*GeCq+FCyz`qjNqo@WK`ld=aGPb*|dV`Yop#q|9vhTD-(_&izqS+yF>E+(wt$n(@f9ksfN`oP#0|+}22DAm5~Jm4=!+kw>x^tc!kEdV_1 +zzytdHZpr*fJhvkOP#ka*=*7GAnA2>VREGu4P-$!b+rN~n^A~bZ*g&^6H${p!@)g3t> +z>B(Lb!dg2;@kfSNDG?S6ZOPw&B%^4mVgn=`7OUM!IytjVaT;zi$es +zPni22M?sT#Vj3*oM&#(D?=&$pU*XcA$yBwq65h&8Y^_kT;ffcow@Q+CMW0zYT+EPr +zNG>stYZxDy4ygPtj_z2!O$0qB%d_%CX+~sWA<|v=;`T`JaHB)_Y|=74ya>b$957_O +zcycXD9y1JAz;(Vr?CoC7iq>nOk=KYq;LDNJ2c%&JZ3M#+01jCt*L3%oq-aa~p`mP9-!_Zrw{JT|`D=r>j +z#e^!MBhoVBinx>@b()Z-kU`-10M#21EVys9d(zx>%YPiWYGxPTia6g)ztfIV#bi4T +z0%l1*iaQLT09u01EM!pSr^4WZwTpl%cd|J^>EcY4OzKzxuG#ZehMpIu0Wwj9dCPo> +zXTigMy`9Sipg^-ZbfM{3{&MwW{(B1bOP|v*@Ltky1&Th_a0+8SVUYkmLD{#Zeh+!cC{eNH(oJy0%?^>A7c&CEv0w0iDmQ)Yz9b) +z!^D)eOZkHrRR#^se#EhAV6-vRa1}o~_ac5{4HxRiKYnef*<;jD6AF4(^l2^s6U~J> +zs$38s7sc0IGa)U>KsMs#IET~&o|$)8p*D&aU`NG|b;pbJ`Y +z*@zWAgXPfV>t>Rld*e_Wq1<&!S8s)f35`RrlZsjG1k7F6e=`(f{g3kyU%_aXp=uYN+cr0?4K`YKR0Hju4-XBsRj9t*#DI6E)? +zb#}1E@u~q+-1Wm^+C6z1{CCQNe`}P(EZA4ji~vqY2Pi~@ +z6Mzg!hir01%|-g`e*yC)1GqJ9K+8&_fnH$QMMK?du8-($1&_Bc(+@jZ_AR!O0rs_CF1xbhuTKV5kU_QwqQCFnQnbUMbhw2ToPmaLjV8- +zC19by6Q6!t_yMtv6%aJdJ76CInSq;%;&(IquPFIj2iyoiiw^~4(hNYo6a$%TLG}US +zfy4Ht&l-Ph!O$fvg>oNzzgc#WB;HoLs?i +zXpWsilLfw?mWb3@T`#&D)4MK(-+D}g@H#|WUL4n6(`ODlsyjZDw%K(V3$n8vk$IHU +ztlZx2Ut_;)l&f4Bt&VG-9G|F<@*oZlk0|NuNRIB*dCOij6uUDxh(h|5NG_yJ%Fly9 +zSD0$)V*rV<5z;+R^e@$qN62jW9`ILb*M0-R(XHjlkA&nJI1%J`K`u`gzG=O6!vU`V +z%+&5jiDB2S^Q37RP9!8d3)}nz4WpooXRm8RuKXicnpZb-D#zZc8n$$YzR+D@WoUsW?3-R9p6y6c}%cF&F64T#qK=0E}H(EaX(qv^^>VN_L +z^P2li@uU{Ak#~Jz2RJ1HDC-H_YYt$Ik%eM;moQ%dwqT!`D_R(a8_?))v)eG^BmB%7 +zyvgJN>y>yBu+aS+wI{&L{Y}&Z*zT{%IqKZSiDI*#x$7SV$bY0XsBSRc9k?e{x1-DT +zglj+CL6}JJ^B_my(Ax;^!CExfvU9F-IZvbabi1*}gwmDd+9XPA_PhhUTe?yap{_^o +z&ma4;KwEbtCIt(fx=CU@D29K%e*7vyPyZx)n`9x^_WW@Kr2+-|Hp!^B|8$K&7(QUL5~J^h}^2E!^wcazlA+y-UF+`f4u_BrqE~KsuLa&oj7va+-acT6vp*1u;Y4 +z4H0%I%u6{cCT0=7l$H*Qo8;YeNKrdV(&~QD*%PExM=Wj`-1;b|J{V&P`T5eDa5ai1&t%jrDV +z{$Q@{D`7+qr#s=kpXgRigmseOxHXlfTz>8Um$ZNPT0dV7G_7?v>7`u(U4Sd(-#+hz +zrk}(m|2g9Gzi8_Bt4BYwf841S0O;tB`oPFw4mdx7L?C +zJT{U!U{r*Yng-CjIf8&)23Z6K;7=mi!_oS{Hy1M3t=cjPI7$LvcW$b;zG?r{KR!@| +z9YDpx{6F*$&>Qerx6nSbzdJPlE(+=I$IAa#hvwhK3H?inzZ{x>7ryhq$aWhk>py3^ +z3wHTmWV;O_^nlF8>yAOH@=!MMd1e{pY>k^8kUIZEnLh%aAbw +z<$%~;E;hDKWI!WALca&*V&~xfBL)F=Mm0+M&7c3S-nKJiB#3^yzs%5O@(nQ&HBIyp +zRe(G*5@nYV#`#UY@DG1@6f(=&r#H|jcUg`N1{!E{rr^CKf_3mni(fi7fSk2;FVnfa +zxsfEB_e0I_w?Hh0CxqIV;vS_-Ri>p6+Z|W6Y+iUaL4meU9$eqHKk8ETx}_KzZNYu* +ze8hbX29kDe({Fkn+(3_S=-|L7E_ye^RdzR5thdQf(%a7i)Mt>}GFOY>tH9FRl#^=G +z9mvgf{d`K0AA`@aPpLYj^ophB=9myVeNtU>UD9$Q38}0ewxOPwk=~l#v48fevKmh+ +zu=*jqBtHrj3RB#yPiH4q=l%fsO@H2wK>&eO+XJf`h=C0U!AW&FCdOwBGZ_1_&-aj6 +zga__vh~P0ev`b(D4RaiW +z$UlT(69}GMy?-cF|-|4A%hX`P-de +zmEV9qx!r)iZ^e-w@LIGSe}x?3l#1sE)*L^6XnVSA05RQMI6ODH0r>(NZ^zf`_`+LQLhWYlm1;gA6DK7Ce!~7FSwg}C7Z-^~J +z;%oXACg_(oB~EOCEiP~z_zdj^bfs%GqeIoFJwj%N$H|EUmym?2Mt`ZTS2-EYHGs3%`2l3Ji|Hv;^g{148bVbp&2SI**ZN3*&D)@;Gb>?bLwS%w +zX{nLKa1Z>CxlLzO<6IKu(goBNKh)1OWSA+>5-lAb6&&?0LEyS<=21(OQF>a-XE7ux +zcu5t^%kXbNzclCkYiEz|JVoe{rwmT)GeZN{4#3mzxHYIG;JBt*l~5S +znSq0|ZIO;Bp;XQGF8iw#?~7FD9nBchYK;THazJuBlw&(yP+@|IYcDAvf`?Wv+^w49;{W@B+jaD`cUq!G6+1Pdh9xc!apvm#8bSk3yFzUa~ZEX+7 +z7Z&w(=nD6Ibo5*KoYF3`F8zE3x66WV9q!Zgc20L +z4y~bH?P%90ZWawajMy71{iVArzRRD3=B^Q;0rX05VP5~!yV!pH50p`&Yng6TuTo#* +zUOeT;*y=(jg};$c#yOUs-l6C{>%M8vy;EhX0@7{vAp^Q{~a#+6El@T09wJN!hL$Z^}eW| +zA1YGca_t&%0}`Xcfi3;VzHbo2fqU>z4_f3rk;U*rgEDX^h*hV7shjIUe=RbKeH2d2 +z_w7HFYslM_b)y#*%o%rre~7d~C-Y>lRgjNh=r7Ff*Tq?D!BW2JIz9Dlz)R)mKTIFj +z5C%lXeBg)zoC8_ToUgrX?W*J^6l8}{ox>l5irF?Dw2_u3H)_+I7J#ru9gzJkKpxP0 +zbCp#0rezsycLUOiIL=Rtt8pqs#pY(RjkNp01qCeIb6Rv&*si?K0TF{D4&b!9xIly< +z%OlHGaD|P~4EAcp0eqJ^dnX$5(nm#yLA$z&YgqDG==vF$bs1C5 +ziuvaa@4Lr&``Yi{WQC3>QK~-ny1ueNByVmbAZ+8$)^Q&Y#J+%z*;$)bJBsw=I`XT6 +zt7U=HaTQOxTbjXiOgQu<@%hi=*V3GO@n&)ZP6(sfP&&q|SxKBG* +z#6Ew?#g6|qr9J8N%9oS$;v^dAb52+0V=3r*QSuwD)p-qS{;XJJ9yok>{ZYSN1rQ1g +z&jwIK@n33CztA0>;C?)>p*DW3YOC7H{OTYzuUb9AsGqfx3p!zy>+UDe%P)kUfb7fV +zKVtEzU*q40BkP-yQo)=iVSx-sNeD(hlEXv+r{1rf8-}MEMX63!hDYg^H?H@mmyeBG +zIN*=~HuGcwxLEPeA +zKV?xisDUU2t&O@!E{u{X*tG)1Y`6k?*X0sFpSD(`!p7{xLP}G2G((AKIn=pxO>OH> +zBoro{T@2}ZqyPXSJ-|ng6n;{AcA8nOpQH(IxEO64UKho^x39wh;QOIJw664^ppc3w +zHw+uwR~3ZDuiX5{7#r%EKVUp^Q`DUm7wZ|=XrZ%b{j>vYY8L$InS7FS#f&)H0XfGb +zH?kMjA<*%Y5zkV{*P@nR36rL-ocp2Vs@d~=RU~)3HJW{>s)JLd?U!w*@Yuv($?2~I +z)&@x7%LafJQ0fjodO|N<9w#o7$b*O}Ml?!SDXM +z{nOSHp4JoU4?nx&kG@yg!0pa^;7(a3e27mOK+ga;z!!!KGaix_0B36rbA^m^xV*s^ +zM{Z~FU#E-sm0WO3vMhF{sce$ZC|%&D6K$+*mZKlCXD?oLzVlR-|Mj&wY5&|2=no-X +z_x9GoN90PhXVbVP6ro82ZhIf;zNHWoDMr|K!_}kxb~qruw11E;>=yQ +zTswlt>)-ah$gy%bWU!^waR?*^r>fZSjg{ay2K6iYx{;(Wk9NQKazsaGD|;;Kytvatd-K__QN69XG$_mrJfZw0J1;!bsOVk_a)oNywk +zXf@O!HKWJDOB^HQ62_IW`k%hM>G@`#JuE%S(ir@T^$qQ3#qZjD%}4KWqqQiosFWE3 +z9&D`hP`zt5rzXl`fAiH}i&#REx{b%|)FVyM*3ItJ6@7BO`}A;uad2L!X0Uhf^2(=W +z&0x04>y+m%5IqGxV(VQ<`s`PWw+X)Agzay?KiMz)W$z!RU8-W=Uc&QBfzylKiAm6I +zukg^|5pTay5dGk8zXRcZ*3tHR9qW&X;O4^F^9s3F#%sH1qC2XYuXCwZyA+^pa{~wK +zle4{1-(S9hOIBl!V0~RSSaNX`JW6mLPrW*ISX|mJ5f~VHWhM|>i&%f-vwEaBsGV+9 +zj{Ux+a+HYoHT2lh`{F?XXS}yvvdPwZ&l~(fp)(5}e9!5x=x}q4h=VU1F5J4`@7F^X +zb=AGqo^6t!ubc^ZMIK{!NZzd +z2Um>aaAbmazl=Z=`ySsZbqAkbgAbWW{$AvKEqf~J$XVlu14aw$p|6QfMf8`pzZnM-U_g`_032FzLQ8|=7reY@g`RE+C4RWi@6{Pr8FgcF1PwEH#^DV +z@7Abcybf)gjOeWXOcLE60;1)odltHM`XV0HY|YLWCr&XsxOVd6e^rKWbzmA9RLS{j +z|8dxJS`nK|&&lOGuL>cR3Coabi;qo +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 +zJFze_gQI +zS$H{rS+E}{s2r1Y-k4!x;CdL-#l5$n+@tiGmKnQ2jtO8T!?^cS<)f +zTcB4v=U|`o8{URw1$W-JnD9?A;JI}l8UWU=mCzq)D~ +zoAJ>-ClX)vd9JI%gQ9D6Cxe|EDx@qc3LPFdE{SCA`Im)FSMeVMx5C0uQKikqt~k-q +z=4R*SEG;d=zHsF_kz;)st6Gx;gZsf8o~iTSTj^Re3yPm)pQOy^+qqo}oJg3+7PjgK +z3Ecnuct}ZJey~BSxOFJYnThE8@_LS|OL4*Z5;QO1(fw{h$V`G4e^4DOPG{hz_ZN8* +zyBnf_n&QO6`-OY324MmXOW +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 +z#2@Ov!Oh63xe_2j5GW?^l^Z)qmf3)cSpT5ob +zw*{AfcjCX>$oP-jcK?;{Z*37Wa553Ivvmfp%UHXbI9nJQ08~8eO#p9kFaS|oBRgXY +zTQfpN#<%S~CBUB+)^B-$R<3X3{YFcFB>#)5e!u_cn*b5u+{VPw#Ma2fNgIZl6X4)t +z=WOBxEYsQqhLMHskFcYKnYr^HUSmURYZKFd2Yx5PFtT$1oZal4Tn4i0|ns3ZZi#S{oxac;)v}gWj|Du +zHee72hHDrL1krjvJ{0fgMsMnS|i9_ix>_}O+o9GAZZKC@6Urhv5_15wAb%^H>Mf-q@hlq +zVH0NKkKjxF)F?94YOWru!XH4GKmXtC;x{MwU$IG2ML|?ejYiPX!oZsL4V=HJL&U_% +z$kD?7?es6_8`&uVRP0o3Er0}LLih(1fieFkB{2&}Cud=E1K?R +zb0=*=HbzE5b|$9Z4=XDh;oHLmygA|R`7{14&s#h*GczG8`yY9LaWKrl3G-XNx3oX= +zyoKNVe?4sMztcH@d4c(W*BbmuqQKVvu@(OpbpUTmcx(B;iR_OY|483&^zvs(z|PnT +z+B#YM75)$6X9TDKL;!*STMJtgfXQ!)cd|DyG66^egaHx&JAf0w8DQhW2rvTJ0vurg +z)&LWLF~9&|0WbuZ0qg;y09Sww!2R#E|2IADFS`AM_J4!vZ^Qpr-~N+v{bu+7E4&pH +zWMzeA{($#?f%=Vi{yzhjh56rr1rGdgAp8pezX1i5N=!gtzX6OD=zmN94dgeV0rS22 +zfxj?s>A&*<^St@r0RNW8$-?qG{FayF4H@3@0pERl-qQb-7v?vj0MmZQz10a!e@lCN +z*#G7KGe0oyKat{(qZ)q=+&>`2-=xxiGX4J(q|gAOg&;r%@CPm!0l{tuumXqylmPMo +z1t4aK0*qmRIN%Dz21g*8r~|P<8HfkAKxB~w$N}-f-T)|Ge#?yCzCQ#85N||)2xSVy +z9CLs;zy;t203HMZc$zrc{SATMg#G^t{r}|Le<$HT(HclFf1GIfYi#}#ss2d*M{4;` +zg7^>d_qS#NA^6|z`U9_(>}(8d|K6zoO&fl*q`x=eO`!jqW&K8LIRhIY@% +z*JdE3V`5|=Q|$i%?O#_*@W1ah#y-NFJqy5SA&tfJbm$G0oTDqk|4m{+P) +zQc9W>8><5KNy3&eTp$P>D)k)+Iw2fFEL4~wtfC?d$Hy{%WmFpo+~yJ$5Y!*!702U& +z@D0KRHvE?@HR#&Ot-fIm@ueMO72xajRdZgaRUI!6uU=J;N6be)A#Jw{W;xoBgdn-0 +z^lP~#4ss4ulw-q2sl(ddHrnE)Ji?HKb9C*#pLd;Z13Nk+5J3u|rMZ)J%O18q;`2bTGgu+2MQcZ+C&MR`BDiA@eIKgQbrOzfM}Ewm +zuu`M5l}<9DJ+zr?SRT*o80iAVEZ5lATyV8{?0>p3h+n9&yiQl~n9VA0+ibpx#y&+6 +zBY+|*o-7RBS>j_)gf5%&I}f9_*wRain) +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 +zesd!(_qd_0T69TcDwMF9rW%rWWTa9zvmT +z#(#V&9OUH3QrTG3JDIYXw-Fchi$A``EXtU+VG^6)C;SDMsU~ujWK{IYi7QOqm7O|?V88!A2&S7Q;X73DQ +zy!>syXq$)!AEiWY>FR`c6n-_v*gf}(;6cyU&BjJ;!vIIax7BEdn1VS|sKW=xGN5Ur +z8CCDG3~`XP)rW7uScjQP`Vneuh0G_NuC13G?X +zUE~&xJBfGE8oa$uC%bS}fFDQ;nm6iF>DskI-kJ-N0>e%58ta-`TvJPzhLJGFcvv-( +z0eY8QP#csu5-FJ*+PZKMDP4+_d%-m2apH}XIH^Gu3#nqkJmm@6ZG^apK@|t7lDsVB +z42>_EF6>fqAr9j+E+`_hOj(i+EBt1Y!PU3zyATTvwww!ZJ%Q*Cu_O@2cA(#@{HMR} +ze+g3O$$C$H_HLh?u9lu*zy~*v7%4L-dw&HiXJPsL2ZtL!XQt4-Bh>pc5zN(%{);^B4@dJe`2Wld_i96~mD?VKPC$lP`3Q+SLS@GKg2OEjX$HF6E(uI;AgGwGKiGW@Yfjw{=$;qk%B5+E_9idl +z{LH47c*Qcpel&RzN~IzSLWbe%^&mb1LOPzf`V-}o_e(iMkNS$$=J=-`4;~`o&(Fr$ +z2TSKs;Ze>?w<{@g>0AyNFLV)C6uEsNrX +zB&SkCBAKS@ha^c8g?$z5Bq_2|cXZWHgNr%1@xruF4G~hbv=_A7Nv+|vi2*1i%K7;W +zc!m}_U^c1DX)HaE7{cAe@<&Iw`ur1XxyKU1Ug_$OjTun~cZN5u!JaX5iC2$I +z%AFUR$BGjR7XU|;X36A^iS>{$5C!Lwm=8s3z4K +z=Z&N<$nh7Kq}ziUxcA9@S@|_PpC>ggW67^N?&{N-iE4mo<+ +zc$f1ujLxay?3YzqmV7raZyAl5QM$&c%zsfbc- +z3|R0{mac*!7e7<0T;nU9$%PkZZjBpYQ~pV6Iu3@~77dT}-hrg$zLBmp2^0kMiq9XH +zQzy8hl@B~;4w_%K2-!mHQHlOCCL=TbJ!Zc|u&dbg>fZk0ne>FubZ$JIZT!#yf%uwfXOmibvt%tqk*$t%hS +zhtMqUHC!2vS1EdNjxgLW-)A`v{{Rxuvwi?0@4 +z@uwdY9ODw+0shKlFwlc|O9MV5W`=qg4l&Ik!LWP0D`j(&pU +z@n&Ay2ksh!wu2(__lu<_Ji*#w%qP)eNQL?Og;NjVAzV>(#8-6=TkXtE`U0NxHs;bR +z8*P~!Kq<#R2ZlF$Hpw)`>z8Yp>SednH*q%Uc66U7zF_@iuGC#<32cGMp~A9ni?z{D +zaTQ<0n;jAKZHeA%*!&*PY5IOg$TIoX$;dd8PKUS10S?az=~O-Kt60Ja@=5>EU?FcB +zDYJ6j7UObhTsf)yXo1I92~E2R^<9>oaooPFZcCl~HNHwc46YS(QZeTqJ;0YP4&#qrK}>u$%AT;KjH^xYsd<}p>t^~ +zPJI&aaM#f+pXqG@CDWpl6_R6n|3HF! +zB%ezBgECK!=4BNT>V?@v>EU1 +zuARQ%iFN7OCC|(2A=`EgI#5dmZnf!XJa2m$+ca}qhDNKovJ)j<5}txZlli0u0?4N4 +z5Z}x8I`uX6olX`f4x4PYe0}rmtPirNSzTPex^MW?`RZVXrWBq<95t4(da+mn2k4Db +z6d62t^$tvg*bF|qsfVYtl=7?Os5xQ6vE5uF2|a|nb%fuZC7KyyN%Wmc&2dMwYlZc0 +zQ~Wg0y>ZB5z9k5PpXtsUWv(#O=9UlUQas9%8JFoRcqe!HD|L@rL?3|;QCO2IRd#I% +z8c8&HKSD=4Tyjds?cVcJmD}$EUa{kxXh5#@@&3|oipDOR*GW_SvRu_z?k2M++ld|d +zxP<`4$=`2wBC0OWS7Gz0}82I8LMI=cT-)jV}1K6 +z^|aE`GSf^UDhze_P$AWfV8*-=_E*D8%=g0aC8d^^0N)9kNvaXL$7zFlKDa!ng94%= +zQTgo8+1?;c#>ABytnU+`6Q{rH#Sx5ULm6-f@ah3V0p~>ynf9dT-zwL^*va+2ph}u_ +zR_T#3qxf`nIxSB#^Ym==H*EdvO6t;H3vk;`bNhN)yJGSSn!9Ii+Rn+&s$*^1*Cm@? +zKF4mPu>yUz^b|=&Dc!iSc;WcI&i@itDf_ItTK8G{1ieB*78{!Eo2)>{8Vhw2r{6b{ +z@{jP91v$eh$I--kCb96z)p-VaaSU#R#oS$ezVQ^h8WAj+=T6-`cesg_I%Io>lYzV_ +zj8e8GA{*laE6XW0269qO=AF#4=516}jNataiyp*13`4mI{%Vtpi&Efmw;rkMp1iIZ +zx=;*LtQo2M7c)J)oacRJ;fN@1@zS6<19ReA4f@&iBoJ&5!ya*)+i0%m#gW75h$$IC7@s#l2dI3UicnQ_>J-^Ii5U +z@Jo;LndjBjvNTO2zHlp3w7vzB+i)jIP|Qbs^=!jxWW_EX;Xkzlw3n^V{eP+$<`?-k +ze;H$THLgDzPBpMR=D|^NrO(Eh8C(FZ$SPzV(Y9<{pxsxKG_D$x9ya-co?t%(`L5Id +zR51No=qmZeT(Nf&tC7yr@{TV4_9uagjIM^N%Sfi=V{l;FrxX-|SJzh?-bfsnr6=j# +zLHJ~kDxSxqPhUQOeTxePxtnTIqO(o{C_=XuUPOLq6p#vPdxs9r`ty-054&C;mRiz! +zZBGT>JbZS0B4y8nw|I93f60?tS1kEnx(&Sq^K$MiRqDG +z$d?sh&QUsh=P{%gZI2rk;O_)HAD-Egdl4p{rnmQjQ+$?vzreFnc=b!MH4*QFAa7Oi +z;H&NB7|jnrl9i8J4PGQvJTwQ0H?Gk0yCvVH65KX!^6?_80U*@8q1_3XZK};#@rPL;Tl=+TD9v23N +zkbd%ptYrhwn$&6&~yaw(IfAh@zw&LOO +zvBXJpE&2yy7Gjg@cSt5Zr?%`oR8gO1S?9$7LtoFH@6juQZsCu;>Y~eWXI|v#N!nbq +zI$y_XzTe1rynm$IFyJ!^x*X&CrMReP@qqXq!}8< +zsm-zI`y!25DuY8)mmXZ|?Pa`N6_xQpHyeb}w}7~OBr4;D(h+*`>a%032YaYdZlDz|q!iPu@gj;OwbL}VKM +zC{+R;2ze#e=|D^T?TgWp$!-24bOa`Ub*{BeZ&O4ZgNz8^OAn$3Yh`8~g>VPAXH&WM~&)} +z(6LfX6^3{mvQ4vXvPt6azmO(hqF$p;4Kg3xLHY=5>GlOqc3XZP^~ZtKInpDMP%DaL +zshEYrZc*Pp=qFz&@*aeUI%>&@b_R(w$<&;o@^IT=^^rSO28q~?j_N!Td+5* +zG+1ap;_YF|@u%K#oZt5B_dLQ9$4mqi<8Zt3xvho&Oxw+lw5saMS_^t58na{+qjjgm +zQrA$Mw{>0GTas%$)MITsxNFi`dV877ORQ^}yr +z-u^Ji1*k6L^|fSr(YDxtC4;fm3)YNBF?2uD%~t2hj9F$b7(n2R7(5Gh1wxvbGFl0W +zDaFPi3^wFv;ge#X7$*FrM^=+=RVX*ZYHOSjfUATXuySeEvJ^8^i_$pHMa<$vHx&0d +z3|BZP6wl;(r&v@{z>A)w1~t4lUlLQ)A0zuTQ{CjyJAzYXtCcQSp2uvLDf5&xFV}X3 +z{9NuVclkWlem5VW+RN`14h|)@*3*%Zbvi=X(tzBuK#idZypjO5251}nKD|%f(nZ`= +zoh|D}unX#B_vpS(g{`M&#ic?0Vrgn*vgT*&aVbcWQX!);_C2s5&4>x8%E#1Wch%AI +z_ +zQN7eQYA-Xk9Gk0B<2J^qcLe7ld6D@)m5(+!&g{S=p+7@-zy>H?YfSErt}HKUv@o|RFGU|q4?o)X;xzs#)|JcGpg +zV*D`>d;ScQ{8w3$9V+s6ssB$q^gfqC#i*442GrX%o0J6(d%f+_$Zc +zl^%UNeZg|OEaDFi8auW&89e;`%M7OxrPM;E82lGKFORQb4MU=*&SNTiGA+AmAq5zA+NBQhb9yyu_2B$nLOnth`un^jhqyI +z#A46-bDB$ai{$VJre8g+wOx=t6%|BP4QF+>^OfH*#%L?#s_4e|10geb+a#*K{c;zl +z|K|T30YMqTmWobvZQ(+dsUFJ&5@n0V!plcBmOC>sk3lJGhXkV=IPItS5IIj +zj)Q9s_4MUm5dkBv+p{_Y0!nFOy57aLcAsg=X`Y5IQbN?wB8P{5L1g$`Ezw{kjiJkY +zx^b*pu*~HHUKWAj+u9U2{k8UDr=t9A9cQmr;6!J|Ku8 +zyGiqk0WM&gCH(5Jwk|4dipzoM?I@?q_4Q{75SmEXZ<#o#jPSsk|${t)$Z)un`&=L$FjaUka-mwN$ON8N2t +z8-3sIK`?WF47W=;QIR>e6Iw%ijAGc8YcF%hgFb1C=2`s?%$;;*jZ@~MGx^%qs{uKQ +zQOcJ-yzr0gAYt6&lYzz?AX_AEG||D_(kb+d&Ia`5Fx*}3T3W@WPSX$0_>~-f(Ol`P +zNgd3uR1S@G(vA8{Rgv2SLj;5D0=^EusBE|cuMGObDY|Lvmb7kEp98kG$<&iSV|^7f +zRLsd7ktYAfnHrad1!bv_DW?3xFnKpce8dBvM+~x8Zm}z(JiBk1rMUyui&?$n85xLyA3g1g6Zt)`6l;@7RDN5>=x1Fo9=%YJr>cfI-_28e><1)1y?Wq31!>D +zbB%gYb1+l~n7W_aqj*=(0a2VTCUZHtvp^hu>>S!8T(3J<rzVDH~B**#Cm~ZM`ZH9Y8h0guBFpaux +z0jC>k4fpxt?rXZchqB{X%+1lhhxHhK!wOxv)!lKE9%`RXOutcIv8-%CGJ|?al?<%e +zwByv()TAZzOLm^A!=pK^tJ;HC2+ZwRFk`c987mfi0b?`g>PH4h8FI3_$(Kh;pS}`m +zmBRfV{+|7yG`7oiTDcCwn*cS_lg&{-c=+10!(Xa)M1~9URoH|q4z{`5?P4l5$17hV +zZQG2_Yq=HcWu;MG<1ytjWn0zx-R?-)$8VQ5eOhvs!Xdw7`Ijlowu_JcqDQL#G>n`K +zV+Bz;KWV68yH|aNU9Y%1JMri&iB~bpdhoR}r!wJ^4Ei{uAfFs@n%o6i?}tadRe?!y +zFnyhM-BCU6x3dqZ;84ZoIg|90fhpL<-#z_}yY^JKTRC%VTt+!SqgCJ{W_2~wQA8L5}crYP!VidIQeC;V6cqu{Z)WY^RQytQG)-Y`^aP5Db4c&E~7rb +z`f8=0M9Xq5x0wLN%-z<~;*Z))vQHz)BeUF&wnM7w;0HaP$Idr}LKdKx`k-&?_+$gHZINjwNcJUZUoU+He~ +zJuXLw!ep+~q@$=*D4v2jk}x&G=8WizBv_Q-g;y)V&sH4c8JcNI)I-gC)-k(4B& +zq9+YrSV2K$Oj=hp?O`r%|72OJyo>UfdI+~XJ|^Oe&{pAyLvT)bREB>^lcyXD!?xuZ +zhZHw2L1>oQxbjPe_=XHvBJBhc_qOf|ZhA`5+yu{@Q1;oi$09j~!%VT{O!v`G)DQ7d +zLRMydAX}t1?)WrAf~$0T(mdU?6mF*0qy*P{)JEhZ-ka2{NMh_dryJj{pXWlu^a`<~zTG{KrE+ET +zvuI#qFR&BRgu$7+Ywui#maZ%hU-ErP8;m +z*77C0qQm#~ox^L+Kl2H68rqf0+P6P!Y=8-e?`R9BVVzp4s>h?RKhms|S(JIyi9m?aM3YUXd;?D)0k?|gsiL_d{-bm7qNcY2ro1%F81n9D)`iizfC$603+{`URM3}RMY*8xX4YHK>JBPNC +z$$MrMa~FbMfO?2?RbZ&ZN4kZ17(zs;%aS2qfYqu^f=ftXi<3)S8#mVpKPKHJ72aHe +zmI$EkP?#5;F|z_LONUrSyhXkRb*MRkeb>As?2zU9>Jj=X;3QYD>n^EeW!)MI7*9N( +zN%z#t8s%n1WnpGjw{pD%oOMiRZqJ}l7msaxOy^liu{Cp-kef^E4w{qTQGh5BsMt{0 +z6@Gsa*(DiWU2a{s9r7JSRhvo`HeZc<(pyVfL#@H+8yiRfx&RUcsJwcTRs}?>xgHM2 +z&~%t_MQNL2hcbWR?iFrXk%^X?4QJK^OK1Dn%kh_rXfC{?^!-c&OWv}r+`A_`@FVdb +z3cGu!{v}I$ZIgOwwYAUKF^gri4AGcq1bs`2R%W{{L1ZT2tb>XB+Z=ccsZBXLzIUoj +zyfuMKN%KBWJ_iLl8({Gn3Wyz&MPzy(wRDp-I#UYNvZ`fVm(1HIZldn7aH=M`qFe(b +z!XQ5kN)Bo8Ng8FstB1V@G4#v8_6WA)BkIQ`n{J2 +z*9FFv+FGKY-Ope`!y@9;jI>U4NTF}Ly6tVgvrBy?DYJTN>^^dOg%+KDr#ZFv9f#|A +zqLLouIa6r^q(wnrj!w%MD*OqzgvgC^mtcrMh*IG%*Bs{&t{Gr=gh*t9rSm?}2Xdt% +zI1wTekAqW9AXihq;(h>mJOg8$t1xdVvcD*`O0KTySGy^G_c|c%;&9HADW|8xcu_?X +zb|l{|=C9WEsLNXq5mdk*M&xKgk$#%4R@=AN=7t;00R32gx#!iwQ +z*>wN3q=66m=(8piTl*1gb~T0p#{d?LUV0snHx`fqx>HY*`}hijAE-*TdM=M|8hQm7 +z@-*^7q-Rm{$#X1%yB*+Hr+T$q|H1t@)&BCZR1K}NFHweH|LYa{*x5JfAFQqZW{CKg +zti^b0frFXj-}VV?z^fep +zvgiidC$xEZtBB4r=%~7Nv@QR7Om=qTT87>iAcPJQAWb354f0{`6bbM@sx6?jbVn0h +z8ppbY&=GUMNk?MLWj0Nma4=YN=#0Y(R@C`PxycX}u>T^b>h?4Dl4sSs^myLDSx>5)J5<;11^J+yKau66=K`9IccSU$~CATSUS$( +z46PNdJq5p?G1d5mK(Ir|>pOp8OC0q51TF_cVF$`f;tT8ntol;)iJ17g%^-8Xe{r4A +z*yDthGveIv=GD`c1*RalE{xIIgu63{TRixZ5B>w1*SV)H>C*PPGgBLZCxjximj8+1 +zdZ6=!_`ldX2N+RezTK~_v$k#9wr$(CZQHwNZQC}^+P3X)-#0g3 +zZgOu1>2x}iCevxs_W%4IoB@STt_Ep(=%YXa?Ob0hj(GrP9MKPS?KjA8w05Z2%J#Ik +z`LjP`Q10z1hFD*?Unn0A7`fqQ@w~9hr0I!FH+wQ-!c}gT~8tA6djN} +z5#J$K?)16QbbZjbo?VbTkvAjYw*;RU7_ub^!-rP3fUSWauzWzV<)4(_n0uUiV0Vqm +zLY98#y-GilX{EJ7Ndb7QeW!L}@O@cVBH;60_ShnLhJaahD6#ahyJxRZ>@@>ydttv) +z2X@=AQtSb|{n0F}S-itV{}abOID@P@A$LW01$KhWzdwlypCd2uZfVYb@q*>k*EHFnMv$OW(V5ZkZhq=$Hxwp +z?Jk=*+KFC4UU?t!T*E%_Vwq}h2zq^^ZyqOl&tpIL4!MOsng}Qj&(HnhB4zu}L5}-Fke#CwtzPTaCjt7wT +zlxqQOzd8;s3S?TOu*3p)AkO|#z!kbAn?q!biI~wRcS=oRFym`d&Ns6BvOPUPozI6` +zTfbl~J<`lOl|!rf=yiI+rQ4|;r>{4V7f#LroMFTt{CB2WL-=dLIEN&EXx~A2Bux3> +zPWZ1(t$OVTKDh=^Fg4k_1f4&{uJ1w=tIr<}NhNm}q_E!#hn!s=l +zRUQFfkfXox-&ojk`3R)@q4|MogjWhs&S1@R=K6XgPKe-U`5C^^&0C+eIq(ARE$1j@ +z@)w`|oo|47=(DllX>@n99s1A~1%6{$M|JYa+;{Us@DEOcP(O$)(Ml8GnDy!m=Qttm +zYD-JUyGqI6HOFt56 +z4tW?;HXT@f05=#eMfCdatjb`Ja)q>B-R6~*vw9f5;OyNP%vU?-Ma-!=;q2Z}xc9Vc +zkW`9E<8{vFHyzz~ip(9~>zyGg%>_ImGsAPmdJ{pIwItDrO69O@|G{yUnx4j=_p1O? +zQB8n9(p{{yGAk^UwvppfMWYH26nu8+_uV{rZqk+x)>yGt4qGdtX#6S!h|p7(MZ{Wz +zlkQT9@#1p5Z1ptbWPx-m5q4a_lpT=R_ELR_Hpwif+!(SFKG6V5CiABQyCz?L3q +zU{^#2$AOCq_u#ml9D)1TVj@{XlXPHkXLqY%S^%&k`at(MZvqweh;1QPNW^M&>i*W4 +zAaB~HN#J1MaL8S0MY@)g0>}W6@XQ}|)|sK30^I$BT@#774iF&unpbd<&~rw{5lD<$ +zn$FG2W^OOARmMlOxYWuVB03SKlPo+9FQ)15$WORrkZ>?oG>n6!E4B-=g}9--+H^Du +z3#GM`NIwxhnX$DLcWlHuV|oPPc2iz(dULpeS7~eaF&-@0HUr*F<-8f7ueM!lpvd0j +zZ7+CPgP6v`+QYS{iHNaXW5mSuA;PcswM5SqWo2b0z7usfPVa&Ashs+lj#{2iO%>TI +zM#TA}Q)i+89Y4}b5>ZkW)%5l?vi-<#SPN~Jv5XKyYy~_&vQ`w>nQcCq?9%BYy6X0v +z(et;HnI~vfM^y`zUdt2s!E=To+@)0hD;amnkhAdAqYq*HHk&@Wm;maAIohZl8VX<(J=0~^>aK46a);1%@=8w@j-ycwlyvI7s +z?AiWtVL}Z>K@DL{Nahd*IHRWkAE_1Bcys4=)KH*bU_PL&85dI&*80ZGSwm +z>knP&iOI~0T+Fgu?ixbP#zNw-%~w;SWyV90*NjO)v5_$_8oow22)iq4dP8|BQ#EsX +zk~d5bq0xCeP9lu8SHFV +zND$y4vpS#6aVpKZ#)86 +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 +z$XliYyy9P25(ORo+Hl +z%f%{FC-qhim#vbGsYo7vLf=-(b(d*F)UL?==U1OM+zLr``hf$11Rznl+7;8ri8qG} +zA46Ig!ejAa(s3YGoyf9Rld(>k0s7y +z5>Db0gsK&&tT=%<4^(NwebUC2Vcwqtwg|R{0N=ul)fI(zQ4HlHMxY9sI>LS2h||b{%Om5PaM7NIz-07p$5>v+WcR +z>XNyn-^35B^~Cp(3G(#b@oi<>5;qD(9i=LOM;0wpHiXfJhsqGj_wUW4mG4HL0ckHgnY`mCM?#?Y^;~t|y_5 +z2jPY4j+Z@F9fxnH~X9ctdKAwNd<}6DOd61!>Mt&<^Ev{d(i{3 +zPA7}Wl$s{9pZiHU&BY|vf1XX%yg5A>;x!&n1JNTkoLyBNz-Ct-1WIy&uzo)k%sH}L +z>Au~tGp+MF0(Jq*X4j@~C^EdiUocyx<7B^dK1)&h9M*1t7p0(Mrw)<`4)O$)OZRtZZrbYKWuTdP#Yq#BK}-LDz)quo!NDM^E0Fr2qgy(8)SQJvvSR{1SCeJa +zQdh#oBGXD`x^{tR-C-&U5=v~ZJ8i0jtU*doTDw(qA^z;e?Q7E(NLED8D0CfYj1MTc +zjZ{)Vm{$wDQ%6eo;%Wz8WBMEWAJ^cM#Kyn(VqOnZp)8%JK;d}=9Un%p7?Qa*G=h!{C=)_YRr56) +z)?YPNrod6Hb?h!w*alM>6ciV7EEM)Ib9&eva5mEkO!ooqDNhwr`OdE$v; +zEt&+b*}00r&P%h~_IIn`b&##!`J~_G+{_my%;+)J;KN9^2YQ$W_oQ!94;}_d)wTbB~5C<8+g3%>?2BNlVx@`Gb1&fVx1fF&~0>=GU= +zYajKsmF<-n03$8aW_MSld(@~Rk2V#RHmnmVEcf5rBB4|-Y>dE!MoRnHjHaQ#`h1!m +zOX(OeyZm+8gZcnVv65ZD7%!kDM}d4y^PM%+s+KtmGUO^(|A2mh2KB96%&@I14lyvP +zs?Y;KMg_I9Je+HbTGosQ!V~>uv~q@WWI|*{F7CPGTYjt%2!69QPRLDYFlcbo7^r9} +zdr^9OSz=_x6h^Ms{_k;2b6@)%9io=D;uhid(ys3$amXr8uD*EE%9wgJL$B81TAtW?k +zt?D%wPH`W)KL@C44z$d=L(7Zgk7YLz`#e1-kuM)`sJ&;Nz3R9}BX7>JOJ^YZtv_{D +z4DpiF&QKxT1a^f@#SNLYv^;Tqt22z|>FQS7#=c9RIY*trx+)gKU8<_;XB2Vl +z-Hq?m7eenKlU2>jT2&iW7L|3=9gFYHDUF$p7cqK=s`zr4v@%GgTGP(!^^wl7W0tUv +zxp4PGxHnfb`tpKJNqI7IE+Up5@k~z{)zhMcS?z`if|hW`G4*sz+uj6nrLBUPdrTSV +z_K607{=IV<2>8$W1DjoHs{*w2RU%-KR(JMYe%@x;{5 +zMWQo_r}WDWNBbrSEgQr|1|b^tH)+!ruOdb`6dD2-Mbpspk<^&nZVGc|<1}2Z`-a7i +z4*GEK86LV-M!b^Y0#v(PZW1gFZ_!vV8UvES}|V?`>m;v +z!Ju3M<*_6~#mSWssvu$^XyI*OBZRP7t}%buU)cQ`H?1w|SUTw*=@Qe_QCDdl^!9IH +zy3Kg^Ircy1?*5)g?TC4d3ZBK&Q75lWWPgQdW)Va;${^CB#vXnp@l|KAq@|!iLV*Zi +zs;JFb-lO6&8cZ9fYf4v>@-{vj7;;-0R^paOcSQn{p~Gi5LQj%*6ib|mX+<+i$}L(} +zsp0b?eHoZ4gQ5`?BL)5K#38$boC>q2$qna_hNYQk0`RswRCpeUR-untHsCTrnNkm# +z!MsWyR99p3VSaAdZAsz<`nVreetOi4bv# +z%DK+G-)2R=DL))Is3p+jx{tE$#^{R5O{d8zB;oy-ZI+HSWzkOO<6rG^)$aggu_ +zSk&3>L)~lKNuqTk-$v`Z@~AOE+l0E2uFVBYkAI)h4Prhc)~;E#On$=bR{hi)j2la= +zGob>*=ojyeZI;k5R#fY;u?0x_o~zcRkAvtz^pAp-Q;$jl0Nb^5$q)f9;b#q$B=P-a +zPP9c4dGm)|`IWc%!9t4F!o*Zj!sSg#L;ot7@#Wk3tTcdC7zcK`7&~LU=m!4npKE$B +z&Nnl*=H{!VSxk@aO@1QfYY{!muZen+XkFdhiI5+)W$Jk7{k)5x>rwIbexLOQyS~@t +zw!cM))#x}gZJ&BPCX+D&Rcw?Wo?0&y7FI+h2RW10aYCOdMqj8#I^=+XQ!Kcg +z6UFBLn^)U_){BRe6#LsWq=YDw%ubP4kG;64=o^ZHv9{VoT)!rEf21aR-VN1i=&j~v +zS5P_MS6{^;YoRK%2=CZZh%sc1zcid5%>)9RF*t*F7>&hk_p@|UrSbU8LgSWvbq&YY +zYk5_ZChU_one-!lhMrs12`H(fjj}d&^7j*YrpO>F$-S@e+LTz*BbW%4=>xo +z_ErL7wvqO322O`W=afTO+J)(8lr?;iacJv6=jL>sZ&TT#LzFoJ9#|3loIplCdfcQz +zCJwx-1ANxD1-Nj)&i7?oxuBqD)G&x(`2Z60hEsm^xz5IUQ<0 +zrc;0-DQX~L605kUn+(M$X#zq$W#kcw8;or*YTbf%Pir-JhdW*wM +z%$C@g@xw00O06IE>@D|ZtWf^tbQ}AVz&RI9m(vcA_lFA+8aI^Y5FoKN%C;b`HN$-l +zRLk3h_m@woUHgshgHP%xO~a0&wZuE8PgmT2(JEfWR1!`08me-A6md3OE>c3rbVQCt +zSihGc_x_koI*sBbE`3`fjVf_q!9+F02Mi@C?;wz2U^X?P{1hP|sItAh1uNLC46FR< +z6c|*m{vuo)-O3C1b{OF)vg)5#fKtTnA^#eKY>=W}sf%;V5`#d@ +zj>JWkYBN-UoJ?BEMDn1JVv1*g1raTPAV8f417KPI?5e7{B48>oRn>WX=rWdyC2f?N +zvh5a|tU&v +zVPnMXza{BT+2u17lpZ}@ib|UrnANPXj!v^dw9ITcsTG>tX$LKd>evUzF#R{s@?^%(}TH +zf_|PMqW+D-#s>7!wgtaCDdvn7Yte>Puh7{gxPs08)K}h)tg{KvqV4*i)RNylR_TpH +zb~5vFUm5uYJvG*ec17*J0dm=kfC> +zZsz0RdB@k`rAV!2=kD<+?aKUCE;eO0M%m>HVwF4qo?}SnYl%hpy{x +zVUlhheUUVny#r}5!t6%GR^L0VG_lAQnyJ?4lfNc*!)#Au5h1R2fhb7n`Vb`AT0p=t +zQ`t$Hff7um1ZA^apDoL16KvyMamta5BtQ@cI>#o^pe1L&^a~lY(S%qbJDC_NM_<~y +zv>iuUmNERaaL*Pj1PB*Xg6v@)9ZzL5V`QE8lIKd!mG6!opXq%Gwk3aw*J+#S +zxXl%wDDJki$Z|HlwJ+?kLsNWZSS_5iIlu!!69k{2hzV7b&O~L-l%fep5kX0DjhZIP +zjRu*~Ho|osb0b@GeS82Ee6q+46O|5 +z6R+D5rmj0mAIe!~th_~QZ`$>7B?3hXxHriAxcb(HP#ZE3={@ban1;^@6v)v&C^T^O +zwaxAAnV+lOekNL8-(!d)DR;ALtq!`tDOMoEkx&G)a3+)))3-2t$wOo&oWJQ>*@{m7 +ziNLFptXi9yGddNBo#?K0?8^~b&xDvOobzyhb@XAW=UfKbP&I{f(cJ4LF$SR->TB2Y +zbtkG7;_UGv7K#XCBONG6)uMt@G$)0nh<3WQKH()0Tml8){&yIpDQ9x8c1@D=_oT8bhFBuC`?gZF`65dir%HuC; +z5>Hj>(=@(zppbeh!6cx+3PY?EM)VQzgBbxFIK)f~XTU;78;;Ge=VVNWXY7udwS2NL +z9`EaBMpBmCVMg88vJV%2M&K=1^}#$SFXlvXZ?%&@K9E)ch-YdOt=Ln~iXKouLBUb1 +zI11lsp6+w5uJW6;1pZAvR-tm#)r}D!l=fJX@7h8&9j*~Kt*-b(&0Y5(&nih$!nHwY +z{ikPICJKJN$&x{-E;9qAQ+laAT_I4%e0Arf{?d7HF?$9xb)KY;m9G1BQYS##ZF4jI +z?*8l^BxzDQUIIvVNX|P~Gg$8x|7mw=pywuUbo}4?bvv=M$2rhM+6uqwu<>0H4-k@Y +z%TuwXy(zThQQxo7o4iT +zLW;|Qt7wo_UjX6SBZ?G-)5joZu8qB6=k%Z)_$AgRtC=|L*{ +zp2(SE4)3FoL;o{0^@)TUzTiZ4<7r!3za5YT+sM|!;tzc38j!mIx_SlV%+)Dtho;{s +z;Lni`NGWBF2$g;o1KbXw=D$4~BQC-m3Qr*Iqk|}@{LN14=fRi2hgvOoeJTCmGlR-) +z!M>K9L=eJ4lo(PE=e>44mcIQgL<=|X)1_u!s3s0gxkato1=OWYk0>zANU+S){W7I7 +zEi1NZu?)Ow>u^L`TonQL=u-ce9e$c|5wQ`?OHLj>m9NA6DyN`Q*K0RoYre!_(r;~> +z-fc6K!29zVvXRzuwbe<^?N7Vkcojh_-+~XBMdxLM#LMRTm+nlT;##2-()4w`Hl&MrDCH(sS=n{7^!JnI=#0HQkU}S=f8p5 +z+}p&X?W^tL*2PIL4#ho3rZw)Rnv1m<^`GTBc|T+I({31OUaE+k(67q$#;t|6KuZJBBkQIHvYZ|}F1t;#W%G-@2*4XiEe*$495ged<=)WgB3m$t4) +z8Ej_C8EZYt#7go*BeKiHbEddIvngibG56jM1=MPmLYKeM@7*q%-QC+dCpL(g$rPH6 +z-D^CpvNSe+y=QFLsg!EUBy8Y_NZX#F?jmc +z_)nh@f`$T7)_qiHhQ|D^D+`dvo+fUr4Ec-p$Rm^=Qs@$y$Y5daeF}4bn!dQt8G)^7 +zgiWbjZZ4&>HKbudF?=#Avr{xn{7z>r@!57$m2nW5`{Z;^F6Dd~lYvLu-;|wduW)#{ +z3eB~HWVI%g4JsTH>=OnS+ap{Z%vJcAlQodVx?_G6;5jq{5to{E3E7`N-ox2 +z?Kc03Vz-?hH<$Oi;=OM8?Ri^!96Ygof4tQ8f&s55YmSNe2f8N5(J|VxTKP0PHF?I= +z!jcUVBVQZE9;b9pJcu6Bz}vx23ULbo8Sxka$J~P+lgcUSCv>fL$!nc!V4uSD9(nJ4 +z^!!wR9?TrPjSigEaZQjl1zX|s31dyiEty*4WqqfnEl78yIDuP)t2={NlNvvv;40Ra +zU|L44SKJ$j4$u>kt=iJMK8pIJi-VhD8 +z``0Z~;aBCLAn-mN_|t3E0iuip4HPh_=z6OPv!fw=JFuq@2R)r{&+CiHmUrmLzJCG>M}f}`o0%g(Rtn1FIBq!MTP2JWAwO>IqSrg&1pB-jK5~u +zBm#f#{hqm~?Ur&m6Ga$K3kc=({AFbx_hH5rd6V!Z=1u5L)gFt8q@ifkvpWw5vSVbS +z-zQWc+ojZNBe?2=Q_TIC>HYpnugh~@<;)57pBheTBRYs)8A(W&M$bP(I-E5udD;>$ +zB}$ibEUu>SL|02P%TzB)+SSFqG-LRbNJa7dBsSjWs{`xMwAieMLvzqMZ{DB%C?{|p +zRp!z*lM~mi6sVSqc@CWb&|e&J4xoCw)aZrLDxxSe7zNq^}aQHKv+ +zJl|K+aGxOn8FLV-u`9Pp+a)X%v!rE?Nhb+C5*oyHj5UpQjV0sl)vq%P8y|dyytck=rwRL8cRQn7!yH+q_~61${04C3Gp__| +zyvX6l{sY+YVrep0Z%a%^h3OhcUwds)Y)_L9i~8aLwaLT3&8#P)N24dFCy00c82T;s +zE%yC2{stBA?hDNP0H{ZQUT9FF(`vO(crdK*Zy%=V$EzFHR!T-$p-Sygo1W5kB6lL1 +zvxK*)LR`CN-r;7u91J)KJ>I1m)LVV;oEdvp%F*LJBP!s7sUxKt@3WVnUb^lX^kSv= +zl*nB@L}6`^_8cinYTw^kkV^QJUBq`}PZ0@QJ6zyX6aeq~FkR(+v$)9LVOmSFTWZq! +z{j#H?EKxzoSXO-%`eX=`Iv9x{ASVEnvF{HmZ4-k+YyIBZ0JXNz$pO7j$@D}ZOGcke +z|9m#^5mr2`8*43k9?CndI3_X`nK2p?QUprGU3V2-OACOB%?eaYx_Gr|2T3FtIbPWfyEOlKlusB63koqaKMh{ZOA1h{ms6y1nO)=QreL@iwByWI_ +zCT`9mGvC@i#ujzm#ML?j;Pb!vWnx>GWsYXbG74Q~co^y&W#?pC)w}s0QX10bEz_=F +zC>L~C=pVzAZgSYXZHLR{YTu?Mxy-eiZN3Q`I;d^WAzWtE-ft5@H+xQjQED?-F0%iy +zsD8s5f*CF%g(944({FMXnEz5@PC1o@pbW0CO>eq>D=EuDFYd%6?%5s|^jgZFseZ9P +z)p5n_0W`hS512+pavUxv2g`&=1Tw8P0V(^_Jf~xnlC;Z~TP37QRWGPUh|!DLr6nqs +zI*TK&sUBVC9wkLb5qDrj(fFHC|4_$o4SQ!gfaiRjQ40k@Xb|BW^@@Lt5grZ)x$1lp +zxj`WNpuxUl^JxsK5_MRWC9Y6WHmNaTu^8n}8G^(#pQ~`j)N)dsM;zm+In5_7Sk-QQ +zO)_nM8^q;;c7CSb@k)PxepDa8HDf)@ +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 +za__7-)cWA)AX ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt16 PhysicalAddress \n ++ Physical address of the device.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecActiveSource ++( ++ tmInstance_t Instance, ++ UInt16 PhysicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to indicate the supported CEC version in response ++ to a ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress\n ++ Address of message receiver. \n ++ ++ \param tmdlHdmiCECVersion_t CECVersion \n ++ Supported CEC Version.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecVersion ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECVersion_t CECVersion ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to clear an Analogue timer block of a device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param UInt8 DayOfMonth \n ++ Day of the month.\n ++ ++ \param UInt8 MonthOfYear \n ++ Month of the year.\n ++ ++ \param UInt16 StartTime \n ++ Start time for a timer based recording.\n ++ ++ \param UInt16 Duration \n ++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n ++ ++ \param UInt8 Recording Sequence \n ++ Indicates if recording is repeated and, if so, on which day ++ For repeated recording the recording sequence value is the ++ bitwise OR of the days when recordings are required ++ Shall be set to 0x00 when recording is not repeated.\n ++ ++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n ++ "Cable,Sattellite,Terrestrial".\n ++ ++ \param UInt16 AnalogueFrequency \n ++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n ++ ++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n ++ Specify information about the colour system, the sound carrier and ++ the IF-frequency.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecClearAnalogueTimer ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 DayOfMonth, ++ UInt8 MonthOfYear, ++ UInt16 StartTime, ++ tmdlHdmiCECDuration_t *pDuration, ++ UInt8 RecordingSequence, ++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType, ++ UInt16 AnalogueFrequency, ++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem ++); ++ ++ ++//========================================================================== ++/*! ++ \brief This message is used to clear a digital timer block of a device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param UInt8 DayOfMonth \n ++ Day of the month.\n ++ ++ \param UInt8 MonthOfYear \n ++ Month of the year.\n ++ ++ \param UInt16 StartTime \n ++ Start time for a timer based recording.\n ++ ++ \param UInt16 Duration \n ++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n ++ ++ \param UInt8 Recording Sequence \n ++ Indicates if recording is repeated and, if so, on which day ++ For repeated recording the recording sequence value is the ++ bitwise OR of the days when recordings are required ++ Shall be set to 0x00 when recording is not repeated.\n ++ ++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n ++ Pointer to the structure Digital Service Identification ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecClearDigitalTimer ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 DayOfMonth, ++ UInt8 MonthOfYear, ++ UInt16 StartTime, ++ tmdlHdmiCECDuration_t *pDuration, ++ UInt8 RecordingSequence, ++ tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to clear a digital timer block of a device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param UInt8 DayOfMonth \n ++ Day of the month.\n ++ ++ \param UInt8 MonthOfYear \n ++ Month of the year.\n ++ ++ \param UInt16 StartTime \n ++ Start time for a timer based recording.\n ++ ++ \param UInt16 Duration \n ++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n ++ ++ \param UInt8 Recording Sequence \n ++ Indicates if recording is repeated and, if so, on which day ++ For repeated recording the recording sequence value is the ++ bitwise OR of the days when recordings are required ++ Shall be set to 0x00 when recording is not repeated.\n ++ ++ \param tmdlHdmiCECExternalPlug_t ExternalPlug \n ++ indicates external plug number (1 to 255 )on the recording device.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecClearExternalTimerWithExternalPlug ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 DayOfMonth, ++ UInt8 MonthOfYear, ++ UInt16 StartTime, ++ tmdlHdmiCECDuration_t *pDuration, ++ UInt8 RecordingSequence, ++ tmdlHdmiCECExternalPlug_t ExternalPlug ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to clear a digital timer block of a device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param UInt8 DayOfMonth \n ++ Day of the month.\n ++ ++ \param UInt8 MonthOfYear \n ++ Month of the year.\n ++ ++ \param UInt16 StartTime \n ++ Start time for a timer based recording.\n ++ ++ \param UInt16 Duration \n ++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n ++ ++ \param UInt8 Recording Sequence \n ++ Indicates if recording is repeated and, if so, on which day ++ For repeated recording the recording sequence value is the ++ bitwise OR of the days when recordings are required ++ Shall be set to 0x00 when recording is not repeated.\n ++ ++ \param tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress \n ++ Defines the path between the TV an a device-thus giving it a physical ++ address within the cluster.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecClearExternalTimerWithPhysicalAddress ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 DayOfMonth, ++ UInt8 MonthOfYear, ++ UInt16 StartTime, ++ tmdlHdmiCECDuration_t *pDuration, ++ UInt8 RecordingSequence, ++ tmdlHdmiCECExternalPhysicalAddress_t ExternalPhysicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to conrol a device's media functions ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECDecControlMode_t DeckControlMode \n ++ Used in message \n ++ ++ \note The "Skip Forward / Wind" and "Skip Reverse / Rewind" values are ++ used for example in a DVD as next xhapter and previous chapter and ++ in a VCR as wind and rewind. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecDeckControl ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECDecControlMode_t DeckControlMode ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to provide a deck's status to the initiator ++ of the message ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECDecInfo_t DeckInfo \n ++ Information on the device's current status \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecDeckStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECDecInfo_t DeckInfo ++); ++ ++//========================================================================== ++/*! ++ \brief This message report the vendor ID of this device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt32 VendorID \n ++ Indentifier for a specific Vendor \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecDeviceVendorID ++( ++ tmInstance_t Instance, ++ UInt32 VendorID ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used as a reponse to indicate that the device does ++ not support the requested message type, or that it cannot execute it ++ at the present time. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECFeatureOpcode_t FeatureOpcode \n ++ Opcode of the aborted message. \n ++ ++ \param tmdlHdmiCECAbortReason_t AbortReason \n ++ The reason why message cannot respond. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecFeatureAbort ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECFeatureOpcode_t FeatureOpcode, ++ tmdlHdmiCECAbortReason_t AbortReason ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used by a device to enquire which version of CEC ++ the target supports ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGetCecVersion ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is sent by a device capable of character generation ++ (for OSD and Menus) to a TV in order to discover the currently selected ++ Menu Language. Also used by a TV during installation to dicover the ++ currently set menu language of other devices. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGetMenuLanguage ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is requests an amplifier to send its volume and mute status ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGiveAudioStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to request the status of a device regardless ++ of whether or not it is the current active source. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECStatusRequest_t StatusRequest \n ++ Allows the initiator to request the status once or on all future state ++ change. Or to cancel a previous ["On"] request. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGiveDeckStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECStatusRequest_t StatusRequest ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to determine the current power status of a ++ target device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGiveDevicePowerStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is request the vendor ID from a device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGiveDeviceVendorID ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to request preferred OSD name of a device ++ for use in menus associated with that device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGiveOsdName ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is a request to a device to return its physical Address ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGivePhysicalAddress ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message request the status of the system audio mode ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGiveSystemAudioModeStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to request the status of a tuner device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECStatusRequest_t StatusRequest \n ++ Allows the initiator to request the status once or on all future state ++ change. Or to cancel a previous ["On"] request. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGiveTunerDeviceStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECStatusRequest_t StatusRequest ++); ++ ++//========================================================================== ++/*! ++ \brief This message sent by a source device to the TV whenever it enters ++ the active state ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receivers. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecImageViewOn ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used by the currently active source to inform the ++ TV that it has no video to be presented to the user, or is going ++ into standby as the result of a lcoal user command on the device. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress, \n ++ Address of message receiver. \n ++ ++ \param tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress \n ++ Physical Address of the device. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecInactiveSource ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message request from the TV for a device to show/remove a ++ menu or to query if a device is currently showing a menu ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECMenuRequestType_t MenuRequestType \n ++ Indicates if the menu request is to activate or deactivate the ++ devices menu or simply query the devices menu status. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecMenuRequest ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECMenuRequestType_t MenuRequestType ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to indicate to the TV that the device is ++ showing/has removed a menu and requets the remote control keys to ++ be passed though ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECMenuState_t MenuState \n ++ Indicates if the device is in the 'Device Menu Active' state or ++ 'Device Menu Inactive' state. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecMenuStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECMenuState_t MenuState ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to control the playback behaviour of a source ++ device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECPlayMode_t PlayMode \n ++ In which mode to play media. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecPlay ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECPlayMode_t PlayMode ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used by any device for device discovery - similar to ++ ping in other protocols ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecPollingMessage ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message request a device to stop a recording ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRecordOff ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message attempt to record analogue source ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n ++ "Cable,Sattellite,Terrestrial".\n ++ ++ \param UInt16 AnalogueFrequency \n ++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n ++ ++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n ++ Specify information about the colour system, the sound carrier and ++ the IF-frequency.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRecordOnAnalogueService ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType, ++ UInt16 AnalogueFrequency, ++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem ++); ++ ++//========================================================================== ++/*! ++ \brief This message attempt to record digital source ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n ++ Pointer to the structure Digital Service Identification ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRecordOnDigitalService ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification ++); ++ ++//========================================================================== ++/*! ++ \brief This message attempt to record an external physical address source ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress \n ++ Defines the path between the TV an a device-thus giving it a physical ++ address within the cluster.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRecordOnExternalPhysicalAddress ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECExternalPhysicalAddress_t ExternalPhysicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message attempt to record an external plug source ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param tmdlHdmiCECExternalPlug_t ExternalPlug \n ++ indicates external plug number (1 to 255 )on the recording device.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRecordOnExternalPlug ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECExternalPlug_t ExternalPlug ++); ++ ++//========================================================================== ++/*! ++ \brief This message attempt to record an external plug source ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRecordOnOwnSource ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used by a recording device to inform the initiator ++ of the message about its status. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param tmdlHdmiCECRecordStatusInfo_t RecordStatusInfo \n ++ The recording status of the device.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRecordStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECRecordStatusInfo_t RecordStatusInfo ++); ++ ++//========================================================================== ++/*! ++ \brief This message request by the recording device to record the presently ++ displayed source. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRecordTvScreen ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message report an amplifier's volume and mute. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECAudioStatus_t AudioStatus \n ++ Volume and mute status. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecReportAudioStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ ptmdlHdmiCECAudioStatus_t pAudioStatus ++); ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecReportShortAudioDescriptor( ) ++ \brief This message Report Audio Capability. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param UInt32 ShortAudioDecriptor \n ++ Audio Descriptor. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecReportShortAudioDescriptor ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt32 ShortAudioDecriptor ++); ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRequestShortAudioDescriptor( ) ++ \brief This message Request Audio Capability. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param UInt8 AudioFormatID \n ++ ++ \param UInt8 AudioFormatCode \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRequestShortAudioDescriptor ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 AudioFormatID, ++ UInt8 AudioFormatCode ++ ++); ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecIniateARC( ) ++ \brief This message Used by an ARC RX device to activate the ++ ARC functionality in an ARC TX device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecIniateARC ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecReportArcInitiated( ) ++ \brief This message Used by an ARC TX device to indicate that ++ its ARC functionality has been activated ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecReportArcInitiated ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecReportArcTerminated( ) ++ \brief This message Used by an ARC TX device to indicate that its ARC functionality ++ has been deactivated. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecReportArcTerminated ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRequestArcInitiation( ) ++ \brief This message Used by an ARC TX device to request an ARC RX device to ++ activate the ARC functionality in the ARC TX device. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRequestArcInitiation ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRequestArcTerminiation( ) ++ \brief Used by an ARC TX device to request an ARC RX device to deactivate ++ the ARC functionality in the ARC TX device. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRequestArcTerminiation ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecTerminateARC( ) ++ \brief Used by an ARC TX device to request an ARC RX device to deactivate ++ the ARC functionality in the ARC TX device. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecTerminateARC ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to inform all other devices of the mapping ++ between physical and logical address of the initiator. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt16 PhysicalAddress \n ++ Device physical address within the cluster. \n ++ ++ \param tmdlHdmiCECDeviceType_t DeviceType \n ++ Type of the device (TV, Playback, tuner,...). \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecReportPhysicalAddress ++( ++ tmInstance_t Instance, ++ UInt16 PhysicalAddress, ++ tmdlHdmiCECDeviceType_t DeviceType ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to inform a requesting device of the current ++ power status. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECPowerStatus_t PowerStatus \n ++ Current power status. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecReportPowerStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECPowerStatus_t PowerStatus ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used by a new device to discover the status of ++ the system. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRequestActiveSource ++( ++ tmInstance_t Instance ++); ++ ++//========================================================================== ++/*! ++ \brief This message is sent by a CEC switch when it is manually switched to ++ inform all other devices on the network that the active route below ++ the switch has changed. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt16 OriginalAddress \n ++ Previous address that the switch was switched to. \n ++ ++ \param UInt16 NewAddress \n ++ The new address it has been moved to. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRoutingChange ++( ++ tmInstance_t Instance, ++ UInt16 OriginalAddress, ++ UInt16 NewAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is sent by a CEC switch to indicate the active route ++ below the switch. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt16 PhysicalAddress \n ++ The current active route to the sink in the CEC switch. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRoutingInformation ++( ++ tmInstance_t Instance, ++ UInt16 PhysicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message select directly an analogue TV Service. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n ++ "Cable,Sattellite,Terrestrial".\n ++ ++ \param UInt16 AnalogueFrequency \n ++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n ++ ++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n ++ Specify information about the colour system, the sound carrier and ++ the IF-frequency.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSelectAnalogueService ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType, ++ UInt16 AnalogueFrequency, ++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem ++); ++ ++//========================================================================== ++/*! ++ \brief This message select directly a digital TV, Radio or Data Broadcast ++ Service. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n ++ Pointer to the structure Digital Service Identification ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSelectDigitalService ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ ptmdlHdmiCECDigitalServiceIdentification_t pServiceIdentification ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to set asingle timer block on an analogue ++ recording device. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param UInt8 DayOfMonth \n ++ Day of the month.\n ++ ++ \param UInt8 MonthOfYear \n ++ Month of the year.\n ++ ++ \param UInt16 StartTime \n ++ Start time for a timer based recording.\n ++ ++ \param UInt16 Duration \n ++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n ++ ++ \param UInt8 Recording Sequence \n ++ Indicates if recording is repeated and, if so, on which day ++ For repeated recording the recording sequence value is the ++ bitwise OR of the days when recordings are required ++ Shall be set to 0x00 when recording is not repeated.\n ++ ++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n ++ "Cable,Sattellite,Terrestrial".\n ++ ++ \param UInt16 AnalogueFrequency \n ++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n ++ ++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n ++ Specify information about the colour system, the sound carrier and ++ the IF-frequency.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetAnalogueTimer ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 DayOfMonth, ++ UInt8 MonthOfYear, ++ UInt16 StartTime, ++ tmdlHdmiCECDuration_t *pDuration, ++ UInt8 RecordingSequence, ++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType, ++ UInt16 AnalogueFrequency, ++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to control audio rate from Source device. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECAudioRate_t AudioRate \n ++ The audio rate requested. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetAudioRate ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECAudioRate_t AudioRate ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to set a digital timer block on a digital ++ recording device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param UInt8 DayOfMonth \n ++ Day of the month.\n ++ ++ \param UInt8 MonthOfYear \n ++ Month of the year.\n ++ ++ \param UInt16 StartTime \n ++ Start time for a timer based recording.\n ++ ++ \param UInt16 Duration \n ++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n ++ ++ \param UInt8 Recording Sequence \n ++ Indicates if recording is repeated and, if so, on which day ++ For repeated recording the recording sequence value is the ++ bitwise OR of the days when recordings are required ++ Shall be set to 0x00 when recording is not repeated.\n ++ ++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n ++ Pointer to the structure Digital Service Identification ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetDigitalTimer ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 DayOfMonth, ++ UInt8 MonthOfYear, ++ UInt16 StartTime, ++ tmdlHdmiCECDuration_t *pDuration, ++ UInt8 RecordingSequence, ++ tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to set a single timer block to record from an ++ external device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 DayOfMonth \n ++ Day of the month.\n ++ ++ \param UInt8 MonthOfYear \n ++ Month of the year.\n ++ ++ \param UInt16 StartTime \n ++ Start time for a timer based recording.\n ++ ++ \param UInt16 Duration \n ++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n ++ ++ \param UInt8 Recording Sequence \n ++ Indicates if recording is repeated and, if so, on which day ++ For repeated recording the recording sequence value is the ++ bitwise OR of the days when recordings are required ++ Shall be set to 0x00 when recording is not repeated.\n ++ ++ \param tmdlHdmiCECExternalPlug_t ExternalPlug \n ++ indicates external plug number (1 to 255 )on the recording device.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetExternalTimerWithExternalPlug ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 DayOfMonth, ++ UInt8 MonthOfYear, ++ UInt16 StartTime, ++ tmdlHdmiCECDuration_t *pDuration, ++ UInt8 RecordingSequence, ++ tmdlHdmiCECExternalPlug_t ExternalPlug ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to set a single timer block to record from an ++ external device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 DayOfMonth \n ++ Day of the month.\n ++ ++ \param UInt8 MonthOfYear \n ++ Month of the year.\n ++ ++ \param UInt16 StartTime \n ++ Start time for a timer based recording.\n ++ ++ \param UInt16 Duration \n ++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n ++ ++ \param UInt8 Recording Sequence \n ++ Indicates if recording is repeated and, if so, on which day ++ For repeated recording the recording sequence value is the ++ bitwise OR of the days when recordings are required ++ Shall be set to 0x00 when recording is not repeated.\n ++ ++ \param tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress \n ++ Defines the path between the TV an a device-thus giving it a physical ++ address within the cluster.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetExternalTimerWithPhysicalAddress ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 DayOfMonth, ++ UInt8 MonthOfYear, ++ UInt16 StartTime, ++ tmdlHdmiCECDuration_t *pDuration, ++ UInt8 RecordingSequence, ++ tmdlHdmiCECExternalPhysicalAddress_t ExternalPhysicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used by a TV or another device to indicate the menu ++ Language. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param const char *pLanguage \n ++ Pointer on the user's menu language choice. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetMenuLanguage ++( ++ tmInstance_t Instance, ++ const char *pLanguage ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to set the preferred OSD name of a device ++ for use in manus associated with that device. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param const char *pOsdName \n ++ Pointer on the preferred name of the device. \n ++ ++ \param UInt8 OsdNameLength \n ++ Length of Osd Name String. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetOsdName ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ const char *pOsdName, ++ UInt8 OsdNameLength ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to send a test message to output on a TV. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECDisplayControl_t DisplayControl \n ++ Display timing. \n ++ ++ \param const char *pOsdString \n ++ Pointer on the Text to display. \n ++ ++ \param UInt8 OsdStringLength \n ++ Length of Osd String. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetOsdString ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECDisplayControl_t DisplayControl, ++ const char *pOsdString, ++ UInt8 OsdStringLength ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used by a TV to request a streaming path from ++ the specified physical address. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt16 PhysicalAddress \n ++ Physical address of the device.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetStreamPath ++( ++ tmInstance_t Instance, ++ UInt16 PhysicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message turn the system audio Mode ON or OFF. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECSystemAudioStatus_t SystemAudioStatus \n ++ Specifies if the system audio mode is ON or OFF.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetSystemAudioMode ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECSystemAudioStatus_t SystemAudioStatus ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to set the name of a program associated ++ with a timer block.Sent directly after sending a ++ or message. The name ++ is then associated with that timer block. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param const char *pProgramTitleString \n ++ Pointer on the program title. \n ++ ++ \param UInt8 ProgramTitleLength \n ++ Length of Program Title String. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetTimerProgramTitle ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ const char *pProgramTitleString, ++ UInt8 ProgramTitleLength ++); ++ ++//========================================================================== ++/*! ++ \brief This message switches one or all devices into standby mode.Can be ++ be used as a broadcast message o be addressed to a specific device. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecStandby ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief A device implementing System Audio Control and which has volume ++ control RC button(eg TV or STB) request to use System Audio Mode ++ to the amplifier. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt16 PhysicalAddress \n ++ Physical address of the device.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSystemAudioModeRequest ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt16 PhysicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief Reports the current status of the System Audio Mode. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECSystemAudioStatus_t SystemAudioStatus \n ++ Current system audio mode.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSystemAudioModeStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECSystemAudioStatus_t SystemAudioStatus ++); ++ ++//========================================================================== ++/*! ++ \brief This message as , but should also remove any text, ++ menus and PIP windows from the TV's display ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecTextViewOn ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to give the status of a , ++ or message. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECTimerClearedStatusData_t TimerClearedStatusData \n ++ Indicates if the timer was cleared successfully. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecTimerClearedStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECTimerClearedStatusData_t TimerClearedStatusData ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to send timer status to the initiator of a ++ message. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECTimerStatusData_t *pTimerStatusData \n ++ Pointer on the Timer status. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecTimerStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECTimerStatusData_t *pTimerStatusData ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used by a tuner device to provide its status to the ++ initiator of the message. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECRecordingFlag_t RecordingFlag \n ++ Indicates if the tuner is being used as a source of a recording. \n ++ ++ \param tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo \n ++ Indicates if the the device is currently deplaying its tuner or not. \n ++ ++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n ++ "Cable,Sattellite,Terrestrial".\n ++ ++ \param UInt16 AnalogueFrequency \n ++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n ++ ++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n ++ Specify information about the colour system, the sound carrier and ++ the IF-frequency.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecTunerDeviceStatusAnalogue ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECRecordingFlag_t RecordingFlag, ++ tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo, ++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType, ++ UInt16 AnalogueFrequency, ++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used by a tuner device to provide its status to the ++ initiator of the message. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECRecordingFlag_t RecordingFlag \n ++ Indicates if the tuner is being used as a source of a recording. \n ++ ++ \param tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo \n ++ Indicates if the the device is currently deplaying its tuner or not. \n ++ ++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n ++ Pointer to the structure Digital Service Identification ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecTunerDeviceStatusDigital ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECRecordingFlag_t RecordingFlag, ++ tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo, ++ ptmdlHdmiCECDigitalServiceIdentification_t pServiceIdentification ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to tune to next lowest service in a tuner's ++ service list.Can be used for PIP. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecTunerStepDecrement ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to tune to next highest service in a tuner's ++ service list.Can be used for PIP. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecTunerStepIncrement ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to indicate that the user pressed a remote button ++ or switched from one remote control button to another. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECUserRemoteControlCommand_t UICommand \n ++ Relevant UI command issued by user. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecUserControlPressed ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECUserRemoteControlCommand_t UICommand ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to indicate that the user pressed a remote button ++ or switched from one remote control button to another. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECPlayMode_t PlayMode \n ++ In which mode to play media. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecUserControlPressedPlay ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECPlayMode_t PlayMode ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to indicate that the user pressed a remote button ++ or switched from one remote control button to another. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 SelectAudioInput \n ++ Number of the Audio Input (Audio input number between 1 and 255). \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecUserControlPressedSelectAudioInput ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 SelectAudioInput ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to indicate that the user pressed a remote button ++ or switched from one remote control button to another. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 SelectAVInput \n ++ Number of the A/V Input (A/V input number between 1 and 255). \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecUserControlPressedSelectAVInput ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 SelectAVInput ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to indicate that the user pressed a remote button ++ or switched from one remote control button to another. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 SelectMedia \n ++ Number of Media (Media number between 1 and 255). \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecUserControlPressedSelectMedia ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 SelectMedia ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to indicate that the user pressed a remote button ++ or switched from one remote control button to another. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECChannelIdentifier_t *pChannelIdentifier \n ++ Pointer to the structure of Major and Minor Channel number ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecUserControlPressedTune ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECChannelIdentifier_t *pChannelIdentifier ++); ++ ++//========================================================================== ++/*! ++ \brief This message is used to indicate that the user released a remote button ++ The last one indicated by the Message. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecUserControlReleased ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief This message is allows vendor specific commands to be sent between ++ two devices. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 *pVendorSpecificData \n ++ Pointer to the Vendor Specific datas ++ ++ \param UInt8 VendorSpecificDataLength \n ++ Length of VendorSpecificData. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecVendorCommand ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 *pVendorSpecificData, ++ UInt8 VendorSpecificDataLength ++); ++ ++//========================================================================== ++/*! ++ \brief This message is allows vendor specific commands to be sent between ++ two devices or broadcast. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt32 VendorID \n ++ Indentifier for a specific Vendor \n ++ ++ \param UInt8 *pVendorSpecificData \n ++ Pointer to the Vendor Specific datas ++ ++ \param UInt8 VendorSpecificDataLength \n ++ Length of VendorSpecificData. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecVendorCommandWithID ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt32 VendorID, ++ UInt8 *pVendorSpecificData, ++ UInt8 VendorSpecificDataLength ++); ++ ++//========================================================================== ++/*! ++ \brief This message indicates that a remote control button has been depressed. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 *pVendorSpecificRcCode \n ++ Pointer to the Vendor Specific remote control code. ++ its recommended t keep this to a minimum size. ++ The maximum length shall not exceed 14 data blocks to avoid saturating bus ++ ++ \param UInt8 VendorSpecificRcCodeLength \n ++ Length of VendorSpecificRcCode. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecVendorRemoteButtonDown ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 *pVendorSpecificRcCode, ++ UInt8 VendorSpecificRcCodeLength ++); ++ ++//========================================================================== ++/*! ++ \brief This message indicates that a remote control button (the last button ++ pressed indicated by the message) has ++ been released. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecVendorRemoteButtonUp ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \brief Get the software version of the driver. ++ This function is synchronous. ++ This function is ISR friendly. ++ ++ \param pSWVersion Pointer to the version structure ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGetSWVersion ++( ++ tmSWVersion_t *pSWVersion ++); ++ ++//========================================================================== ++/*! ++ \brief Get the number of available CEC devices in the system. ++ A unit directly represents a physical device. ++ This function is synchronous. ++ This function is ISR friendly. ++ ++ \param pUnitCount Pointer to the number of available units. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGetNumberOfUnits ++( ++ UInt32 *pUnitCount ++); ++ ++//========================================================================== ++/*! ++ \brief Get the capabilities of unit 0. Capabilities are stored into a ++ dedicated structure. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param pCapabilities Pointer to the capabilities structure. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGetCapabilities ++( ++ tmdlHdmiCecCapabilities_t *pCapabilities ++); ++ ++//========================================================================== ++/*! ++ \brief Get the capabilities of a specific unit. Capabilities are stored ++ into a dedicated structure ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param unit Unit to be probed. ++ \param pCapabilities Pointer to the capabilities structure. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGetCapabilitiesM ++( ++ tmUnitSelect_t unit, ++ tmdlHdmiCecCapabilities_t *pCapabilities ++); ++ ++//========================================================================== ++/*! ++ \brief Open unit 0 of CEC driver and provides the instance number to ++ the caller. Note that one unit of CEC represents one physical ++ CEC device and that only one instance per unit can be opened. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param pInstance Pointer to the variable that will receive the instance ++ identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_OWNED: the resource is already in use ++ - TMDL_ERR_DLHDMICEC_INIT_FAILED: the unit instance is already ++ initialised or something wrong happened at lower level. ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMICEC_NO_RESOURCES: the resource is not available ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecOpen ++( ++ tmInstance_t *pInstance ++); ++ ++//========================================================================== ++/*! ++ \brief Open a specific unit of CEC driver and provides the instance ++ number to the caller. Note that one unit of CEC represents one ++ physical CEC device and that only one instance per unit can be ++ opened. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param pInstance Pointer to the structure that will receive the instance ++ identifier. ++ \param unit Unit number to be opened. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_OWNED: the resource is already in use ++ - TMDL_ERR_DLHDMICEC_INIT_FAILED: the unit instance is already ++ initialised or something wrong happened at lower level. ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMICEC_NO_RESOURCES: the resource is not available ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecOpenM ++( ++ tmInstance_t *pInstance, ++ tmUnitSelect_t unit ++); ++ ++//========================================================================== ++/*! ++ \brief Close an instance of CEC driver. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecClose ++( ++ tmInstance_t instance ++); ++ ++//========================================================================== ++/*! ++ \brief Set the power state of an instance of the CEC device. ON ++ state corresponds to a fully supplied, up and running device. Other ++ modes correspond to the powerdown state of the device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ ++ \param instance Instance identifier. ++ \param powerState Power state to set. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetPowerState ++( ++ tmInstance_t instance, ++ tmPowerState_t powerState ++); ++ ++//========================================================================== ++/*! ++ \brief Get the power state of an instance of the CEC device. ON ++ state corresponds to a fully supplied, up and running device. Other ++ modes correspond to the powerdown state of the device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pPowerState Pointer to the power state. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGetPowerState ++( ++ tmInstance_t instance, ++ tmPowerState_t *pPowerState ++); ++ ++//========================================================================== ++/*! ++ \brief Set the configuration of instance attributes. This function is ++ required by DVP architecture rules but actually does nothing in this ++ driver ++ This function is synchronous. ++ This function is ISR friendly. ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecInstanceConfig ++( ++ tmInstance_t instance ++); ++ ++//========================================================================== ++/*! ++ \brief Setup the instance with its configuration parameters. This function ++ allows basic instance configuration like Logical Address or device ++ state. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pSetupInfo Pointer to the structure containing all setup parameters ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecInstanceSetup ++( ++ tmInstance_t instance, ++ ptmdlHdmiCecInstanceSetup_t pSetupInfo ++); ++ ++//========================================================================== ++/*! ++ \brief Get instance setup parameters. ++ ++ \param instance Instance identifier. ++ \param pSetupInfo Pointer to the structure that will receive setup ++ parameters ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGetInstanceSetup ++( ++ tmInstance_t instance, ++ ptmdlHdmiCecInstanceSetup_t pSetupInfo ++); ++ ++//========================================================================== ++/*! ++ \brief Make device library handle an incoming interrupt. This function is ++ used by application to tell the device library that the hardware ++ sent an interrupt. It can also be used to poll the interrupt status ++ of the device if the interrupt line is not physically connected to ++ the CPU. ++ This function is synchronous. ++ This function is ISR friendly. ++ ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_FULL: the queue is full ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecHandleInterrupt ++( ++ tmInstance_t instance ++); ++ ++//========================================================================== ++/*! ++ \brief Register event callbacks. Only one callback is registered through ++ this API. This callback will received the type of event that ++ occured throug a dedicated parameter and will be called as many ++ times as there is pending events. ++ This function is synchronous. ++ This function is ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pCallback Pointer to the callback function that will handle events ++ from the devlib. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_INVALID_STATE: the state is invalid for ++ the function ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRegisterCallbacks ++( ++ tmInstance_t instance, ++ ptmdlHdmiCecCallbackFunc_t pkCallback ++); ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSetLogicalAddress( ) ++ \brief Set Device Logical Address ++ ++ \param instance Instance identifier. ++ \param LogicalAddress Logical Address value. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetLogicalAddress ++( ++ tmInstance_t instance, ++ tmdlHdmiCECLogicalAddress_t LogicalAddress ++); ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSetRetry( ) ++ \brief Change the number of retransmission ++ ++ \param instance Instance identifier. ++ \param NbRetry Number of retry. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetRetry ++( ++ tmInstance_t instance, ++ UInt8 NbRetry ++); ++ ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t getCecLastMessage( ) ++ \brief Return the Addresses and the Opcode of the last CEC ++ transmitted message ++ ++ \param pSaveMessage Pointer to the CEC Save Message ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t getCecLastMessage ++( ++ tmdlHdmiCecSaveMessage_t *pSaveMessage ++); ++ ++ ++//========================================================================== ++/*! ++ \brief This function allows enabling a specific event of devlib. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param event Event to enable ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecEnableEvent ++( ++ tmInstance_t instance, ++ tmdlHdmiCecEvent_t event ++); ++ ++//========================================================================== ++/*! ++ \brief This function allows disabling a specific event of devlib. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param event Event to disable ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecDisableEvent ++( ++ tmInstance_t instance, ++ tmdlHdmiCecEvent_t event ++); ++ ++ ++//========================================================================== ++/*! ++ \brief This function enables calibration depending on CEC clock source ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param cecClockSource CEC clock source ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecEnableCalibration ++( ++ tmInstance_t instance, ++ tmdlHdmiCecClockSource_t cecClockSource ++); ++ ++ ++//========================================================================== ++/*! ++ \brief This function disable calibration depending on CEC clock source ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecDisableCalibration( ++ tmInstance_t instance ++); ++ ++//========================================================================== ++/*! ++ \brief This function allow to send a generic CEC message ++ This function has to be used when CEC messages are construct in ++ the middleware ++ ++ \param instance Instance identifier. ++ ++ \param *pData Pointer to the CEC data buffer ++ ++ \param lenData Lenght of I2C data buffer ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSendMessage( ++ ++ tmInstance_t instance, ++ UInt8 *pData, ++ UInt16 lenData ++); ++ ++unsigned char tmdlHdmiCecGetRegister(tmInstance_t instance, UInt32 offset); ++tmErrorCode_t tmdlHdmiCecSetRegister(tmInstance_t instance,UInt32 offset,UInt32 value); ++ ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMDLHDMICEC_FUNCTIONS_H */ ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ ++ +diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Types.h b/drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Types.h +new file mode 100755 +index 0000000..d0bd632 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Types.h +@@ -0,0 +1,1083 @@ ++//============================================================================= ++// Copyright (C) 2007 NXP N.V., All Rights Reserved. ++// This source code and any compilation or derivative thereof is the proprietary ++// information of NXP N.V. and is confidential in nature. Under no circumstances ++// is this software to be exposed to or placed under an Open Source License of ++// any type without the expressed written permission of NXP N.V. ++//============================================================================= ++/*! ++ \file tmdlHdmiCEC_Types.h ++ ++ \version 1.0 ++ ++ \date 04/07/2007 ++ ++ \brief This provides interfaces description of CEC messages. ++ ++ \section refs Reference Documents ++ TDA998X Driver - tmdlHdmiTx - SCS.doc ++ \note None. ++ ++ HISTORY : ++ \verbatim ++ Date Modified by CRPRNr TASKNr Maintenance description ++ -------------|-----------|-------|-------|----------------------------------- ++ 04/07/2007 | F.G | | | Creation. ++ -------------|-----------|-------|-------|----------------------------------- ++ \endverbatim ++*/ ++//========================================================================== ++ ++#ifndef TMDLHDMICEC_TYPES_H ++#define TMDLHDMICEC_TYPES_H ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#include "tmNxTypes.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*============================================================================*/ ++/* MACRO DEFINITIONS */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* DEFINES */ ++/*============================================================================*/ ++ ++/**< Error Codes */ ++#define TMDL_ERR_DLHDMICEC_BASE CID_DL_HDMICEC ++#define TMDL_ERR_DLHDMICEC_COMPATIBILITY (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_COMPATIBILITY) /**< SW Interface compatibility */ ++#define TMDL_ERR_DLHDMICEC_MAJOR_VERSION (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_MAJOR_VERSION) /**< SW Major Version error */ ++#define TMDL_ERR_DLHDMICEC_COMP_VERSION (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_COMP_VERSION) /**< SW component version error */ ++#define TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_BAD_UNIT_NUMBER) /**< Invalid device unit number */ ++#define TMDL_ERR_DLHDMICEC_BAD_INSTANCE (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_BAD_INSTANCE) /**< Bad input instance value */ ++#define TMDL_ERR_DLHDMICEC_BAD_HANDLE (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_BAD_HANDLE) /**< Bad input handle */ ++#define TMDL_ERR_DLHDMICEC_BAD_PARAMETER (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_BAD_PARAMETER) /**< Invalid input parameter */ ++#define TMDL_ERR_DLHDMICEC_NO_RESOURCES (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_NO_RESOURCES) /**< Resource is not available */ ++#define TMDL_ERR_DLHDMICEC_RESOURCE_OWNED (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_RESOURCE_OWNED) /**< Resource is already in use */ ++#define TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_RESOURCE_NOT_OWNED) /**< Caller does not own resource */ ++#define TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_INCONSISTENT_PARAMS) /**< Inconsistent input params */ ++#define TMDL_ERR_DLHDMICEC_NOT_INITIALIZED (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_NOT_INITIALIZED) /**< Component is not initialized */ ++#define TMDL_ERR_DLHDMICEC_NOT_SUPPORTED (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_NOT_SUPPORTED) /**< Function is not supported */ ++#define TMDL_ERR_DLHDMICEC_INIT_FAILED (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_INIT_FAILED) /**< Initialization failed */ ++#define TMDL_ERR_DLHDMICEC_BUSY (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_BUSY) /**< Component is busy */ ++#define TMDL_ERR_DLHDMICEC_I2C_READ (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_READ) /**< Read error */ ++#define TMDL_ERR_DLHDMICEC_I2C_WRITE (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_WRITE) /**< Write error */ ++#define TMDL_ERR_DLHDMICEC_FULL (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_FULL) /**< Queue is full */ ++#define TMDL_ERR_DLHDMICEC_NOT_STARTED (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_NOT_STARTED) /**< Function is not started */ ++#define TMDL_ERR_DLHDMICEC_ALREADY_STARTED (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_ALREADY_STARTED) /**< Function is already started */ ++#define TMDL_ERR_DLHDMICEC_ASSERTION (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_ASSERTION) /**< Assertion failure */ ++#define TMDL_ERR_DLHDMICEC_INVALID_STATE (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_INVALID_STATE) /**< Invalid state for function */ ++#define TMDL_ERR_DLHDMICEC_OPERATION_NOT_PERMITTED (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_OPERATION_NOT_PERMITTED) /**< corresponds to posix EPERM */ ++ ++/*============================================================================*/ ++/* ENUM OR TYPE DEFINITIONS */ ++/*============================================================================*/ ++ ++/*! ++ \enum tmdlHdmiCECAbortReason_t ++ \brief This enum indicates the reason for a response ++*/ ++typedef enum ++{ ++ CEC_ABORT_UNKNOWN_OPCODE = 0, /*!< Unrecognized opcode */ ++ CEC_ABORT_INCORRECT_MODE = 1, /*!< Not in correct mode to respond */ ++ CEC_ABORT_NO_SOURCE = 2, /*!< cannot provide source */ ++ CEC_ABORT_INVALID_OPERAND = 3, /*!< Invalid operand */ ++ CEC_ABORT_REFUSED = 4, /*!< Refused */ ++ CEC_ABORT_UNABLE_TO_DETERMINE = 5 /*!< Unable to Determine */ ++} tmdlHdmiCECAbortReason_t; ++ ++/*! ++ \enum tmdlHdmiCECAnalogueBroadcastType_t ++ \brief This enum indicates the analogue broadcast type ++*/ ++typedef enum ++{ ++ CEC_BROADCAST_TYPE_CABLE = 0x00, /*!< Cable */ ++ CEC_BROADCAST_TYPE_SATELLITE = 0x01, /*!< Satellite*/ ++ CEC_BROADCAST_TYPE_TERRESTRIAL = 0x02 /*!< Terrestrial */ ++} tmdlHdmiCECAnalogueBroadcastType_t; ++ ++/*! ++ \enum _tmdlHdmiCECAnalogueFrequency ++ \brief This enum specify the min and max frequency used by an analogue tuner ++*/ ++enum _tmdlHdmiCECAnalogueFrequency ++{ ++ CEC_ANALOG_FREQ_MIN = 0x0000, /*!< Min frequency used by analogue tuner */ ++ CEC_ANALOG_FREQ_MAX = 0xFFFF /*!< Max frequency used by analogue tuner */ ++}; ++ ++/*! ++ \enum _tmdlHdmiCECAsciiDigit ++ \brief This enum represent the min and max of a printable digit character ++*/ ++enum _tmdlHdmiCECAsciiDigit ++{ ++ CEC_ASCII_DIGIT_MIN = 0x30, /*!< Min of a printable digit character */ ++ CEC_ASCII_DIGIT_MAX = 0x39 /*!< Max of a printable digit character */ ++}; ++ ++/*! ++ \enum _tmdlHdmiCECAscii ++ \brief This enum represent the min and max of a printable character ++*/ ++enum _tmbsHdmiCECAscii ++{ ++ CEC_ASCII_CHARACTER_MIN = 0x20, /*!< Min of a printable character */ ++ CEC_ASCII_CHARACTER_MAX = 0x7E /*!< Max of a printable character */ ++}; ++ ++/*! ++ \enum _tmdlHdmiCECAudioFormatCode ++ \brief This enum represent the min and max of a Audio Format Code is defined ++ in CEA-861-D for CEA Short Audio Descriptor ++*/ ++enum _tmdlHdmiCECAudioFormatCode ++{ ++ CEC_AUDIO_FORMAT_CODE_MIN = 0x01, /*!< Min of a Audio Format Code */ ++ CEC_AUDIO_FORMAT_CODE_MAX = 0x0F /*!< Max of a Audio Format Code */ ++}; ++ ++/*! ++ \enum tmdlHdmiCECAudioRate_t ++ \brief This enum indicates the audio range control ++*/ ++typedef enum ++{ ++ CEC_AUDIO_RATE_OFF = 0, /*!< Rate Control off */ ++ CEC_AUDIO_RATE_WIDE_RANGE_STANDARD_RATE = 1, /*!< Standard rate : 100% rate */ ++ CEC_AUDIO_RATE_WIDE_RANGE_FAST_RATE = 2, /*!< Fast rate : Max 101% rate */ ++ CEC_AUDIO_RATE_WIDE_RANGE_SLOW_RATE = 3, /*!< Sloaw rate : 99% rate */ ++ CEC_AUDIO_RATE_NARROW_RANGE_STANDARD_RATE = 4, /*!< Standard rate : 100% rate */ ++ CEC_AUDIO_RATE_NARROW_RANGE_FAST_RATE = 5, /*!< Fast rate : Max 101% rate */ ++ CEC_AUDIO_RATE_NARROW_RANGE_SLOW_RATE = 6 /*!< Sloaw rate : 99% rate */ ++} tmdlHdmiCECAudioRate_t; ++ ++/*! ++ \enum tmdlHdmiCECAudioMute_t ++ \brief This enum indicates the audio current audio mute status ++*/ ++typedef enum ++{ ++ CEC_AUDIO_MUTE_OFF = 0, /*!< Audio Mute off */ ++ CEC_AUDIO_MUTE_ON = 1 /*!< Audio Mute on */ ++} tmdlHdmiCECAudioMute_t; ++ ++ ++/*! ++ \struct tmdlHdmiCECAudioStatus_t ++ \brief This union indicates the current audio status of a device ++*/ ++typedef struct _tmdlHdmiCECAudioStatus_t ++{ ++ tmdlHdmiCECAudioMute_t audioMuteStatus ; /*!< Audio Mute Status */ ++ UInt8 audioVolumeStatus ; /*!< Audio Volume Status */ ++} tmdlHdmiCECAudioStatus_t, *ptmdlHdmiCECAudioStatus_t; ++ ++ ++/*! ++ \enum tmdlHdmiCECBoolean_t ++ \brief This enum indicates a Flag ++*/ ++typedef enum ++{ ++ CEC_FALSE = 0, /*!< False */ ++ CEC_TRUE = 1, /*!< True */ ++} tmdlHdmiCECBoolean_t; ++ ++ ++/*! ++ \enum tmdlHdmiCECBroadcastSystem_t ++ \brief This enum indicates information about the color system, the sound carrier and IF-frequency ++*/ ++typedef enum ++{ /*!< Sound / Sound Modulation / Video Modulation / Vertical Frequency / Color sub-carier */ ++ CEC_BROADCAST_SYSTEM_PAL_BG = 0, /*!< 5.5MHZ / FM NEG 50HZ 4.43 MHZ */ ++ CEC_BROADCAST_SYSTEM_PAL_SECAM_L = 1, /*!< 6.5MHZ / AM POS 50HZ Fob 4.25MHz,For 4.406Mhz */ ++ CEC_BROADCAST_SYSTEM_PAL_M = 2, /*!< 4.5MHZ / FM NEG 60HZ 3.5756 MHZ */ ++ CEC_BROADCAST_SYSTEM_NTSC_M = 3, /*!< 4.5MHZ / FM NEG 60HZ 3.5795 MHZ */ ++ CEC_BROADCAST_SYSTEM_PAL_I = 4, /*!< 6.0MHZ / FM NEG 50HZ 4.43 MHZ */ ++ CEC_BROADCAST_SYSTEM_SECAM_DK = 5, /*!< 6.5MHZ / FM NEG 50HZ Fob 4.25MHz,For 4.406Mhz */ ++ CEC_BROADCAST_SYSTEM_SECAM_BG = 6, /*!< 5.5MHZ / FM NEG 50HZ Fob 4.25MHz,For 4.406Mhz */ ++ CEC_BROADCAST_SYSTEM_SECAM_L = 7, /*!< 6.5MHZ / AM POS 50HZ Fob 4.25MHz,For 4.406Mhz */ ++ CEC_BROADCAST_SYSTEM_PAL_DK = 8, /*!< 5.5MHZ / FM NEG 50HZ 4.43MHZ */ ++ CEC_BROADCAST_SYSTEM_FUTURE_USE = 9, /*!< Future Use */ ++ CEC_BROADCAST_SYSTEM_OTHER_SYSTEM = 31 /*!< Other System */ ++} tmdlHdmiCECBroadcastSystem_t; ++ ++/*! ++ \enum tmdlHdmiCECVersion_t ++ \brief This enum indicates the supported CEC version ++*/ ++typedef enum ++{ ++ CEC_VERSION_Reserved = 0x00, /*!< CEC Reserved */ ++ CEC_VERSION_Reserved1 = 0x01, /*!< CEC Reserved */ ++ CEC_VERSION_Reserved2 = 0x02, /*!< CEC Reserved */ ++ CEC_VERSION_Reserved3 = 0x03, /*!< CEC Reserved */ ++ CEC_VERSION_1_3a = 0x04, /*!< CEC Version 1.3a */ ++ CEC_VERSION_1_4 = 0x05 /*!< CEC Version 1.4 */ ++} tmdlHdmiCECVersion_t; ++ ++/*! ++ \enum tmdlHdmiCECChanNumFormat_t ++ \brief This enum indicates the Channel Format ++*/ ++typedef enum ++{ ++ CEC_FIRST_CHAN_NUMBER = 0x01, /*!< 1-part channel number */ ++ CEC_SECOND_CHAN_NUMBER = 0x02 /*!< 2-part channel number */ ++} tmdlHdmiCECChanNumFormat_t; ++ ++/*! ++ \struct tmdlHdmiCECChannelIdentifier_t ++ \brief This struct indicates a 1-part Logical or Virtual Channel Number or ++ a 2-part Major and Minor channel combination ++*/ ++typedef struct ++{ ++ tmdlHdmiCECChanNumFormat_t ChanNumFormat ; /*!< Channel Format */ ++ UInt16 MajorChanNumber ; /*!< Major Channel Number (if channel is 2-part) */ ++ UInt16 MinorChanNumber ; /*!< 1-part Channel Number ,or a Minor Channel Number (if channel is 2-part) */ ++} tmdlHdmiCECChannelIdentifier_t ; ++ ++/*! ++ \enum tmdlHdmiCECDayOfMonth_t ++ \brief This enum indicates the day of the month ++*/ ++typedef enum ++{ ++ CEC_FIRST_DAY_OF_MONTH = 1, /*!< First day of the month */ ++ CEC_LAST_DAY_OF_MONTH = 31 /*!< Last day of the month */ ++} tmdlHdmiCECDayOfMonth_t; ++ ++/*! ++ \enum tmdlHdmiCECDecControlMode_t ++ \brief This enum indicates command used for opcode ++*/ ++typedef enum ++{ ++ CEC_DECK_CONTROL_WIND = 1, /*!< Skip Forward / Wind */ ++ CEC_DECK_CONTROL_REWIND = 2, /*!< Skip Reverse / Rewind */ ++ CEC_DECK_CONTROL_STOP = 3, /*!< Stop */ ++ CEC_DECK_CONTROL_EJECT = 4 /*!< Eject */ ++} tmdlHdmiCECDecControlMode_t; ++ ++/*! ++ \enum tmdlHdmiCECDecInfo_t ++ \brief This enum indicates the current status of a tape or disk deck ++*/ ++typedef enum ++{ ++ CEC_DECK_INFO_PLAY = 0x11, /*!< Play */ ++ CEC_DECK_INFO_RECORD = 0x12, /*!< Record */ ++ CEC_DECK_INFO_PLAY_REVERSE = 0x13, /*!< Play Reverse */ ++ CEC_DECK_INFO_STILL = 0x14, /*!< Still */ ++ CEC_DECK_INFO_SLOW = 0x15, /*!< Slow */ ++ CEC_DECK_INFO_SLOW_REVERSE = 0x16, /*!< Slow Reverse */ ++ CEC_DECK_INFO_FAST_FORWARD = 0x17, /*!< Fast Forward */ ++ CEC_DECK_INFO_FAST_REVERSE = 0x18, /*!< Fast Reverse */ ++ CEC_DECK_INFO_NO_MEDIA = 0x19, /*!< No Media */ ++ CEC_DECK_INFO_STOP = 0x1A, /*!< Stop */ ++ CEC_DECK_INFO_WIND = 0x1B, /*!< Skip Forward / Wind */ ++ CEC_DECK_INFO_REWIND = 0x1C, /*!< Skip Reverse / Rewind */ ++ CEC_DECK_INFO_ID_SEARCH_FORWARD = 0x1D, /*!< Index Search Forward */ ++ CEC_DECK_INFO_ID_SEARCH_REVERSE = 0x1E, /*!< Index Search Forward */ ++ CEC_DECK_INFO_OTHER_STATUS = 0x1F /*!< Other Status */ ++} tmdlHdmiCECDecInfo_t; ++ ++ ++/*! ++ \enum tmdlHdmiCECDeviceType_t ++ \brief This enum indicates the device type ++*/ ++typedef enum ++{ ++ CEC_DEVICE_TYPE_TV = 0, /*!< TV */ ++ CEC_DEVICE_TYPE_REC_DEVICE = 1, /*!< Recording Device */ ++ CEC_DEVICE_TYPE_RESERVED = 2, /*!< Reserved */ ++ CEC_DEVICE_TYPE_TUNER = 3, /*!< Tuner */ ++ CEC_DEVICE_TYPE_PLAYBACK_DEVICE = 4, /*!< PlayBack Device */ ++ CEC_DEVICE_TYPE_AUDIO_DEVICE = 5, /*!< Audio System */ ++ CEC_DEVICE_TYPE_PURE_CEC_SWITCTH = 6, /*!< Pure CEC Switch */ ++ CEC_DEVICE_TYPE_VIDEO_PROCESSOR = 7 /*!< Video Processor */ ++} tmdlHdmiCECDeviceType_t; ++ ++/*! ++ \enum tmdlHdmiCECServiceIdentMethod_t ++ \brief This enum indicates a Service Indentification Method ++*/ ++typedef enum ++{ ++ CEC_SERVICE_DIGITAL = 0, /*!< Service identified by digital IDs */ ++ CEC_SERVICE_CHANNEL = 1 /*!< Service identified by channel */ ++} tmdlHdmiCECServiceIdentMethod_t; ++ ++/*! ++ \enum tmdlHdmiCECDigitalBroadcastSystem_t ++ \brief This enum indicates the Digital Broadcast System of required service ++*/ ++typedef enum ++{ ++ CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_GENERIC = 0x01, /*!< ARIB generic */ ++ CEC_DIGITAL_BROADCAST_SYSTEM_ATSC_GENERIC = 0x02, /*!< ATSC generic */ ++ CEC_DIGITAL_BROADCAST_SYSTEM_DVB_GENERIC = 0x03, /*!< DVB generic */ ++ CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_BS = 0x08, /*!< ARIB-BS */ ++ CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_CS = 0x09, /*!< ARIB-CS */ ++ CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_T = 0x0A, /*!< ARIB-T */ ++ CEC_DIGITAL_BROADCAST_SYSTEM_CABLE = 0x10, /*!< Cable */ ++ CEC_DIGITAL_BROADCAST_SYSTEM_SATELLITE = 0x11, /*!< Satellite */ ++ CEC_DIGITAL_BROADCAST_SYSTEM_TERRESTRIAL = 0x12, /*!< Terrestrial */ ++ CEC_DIGITAL_BROADCAST_SYSTEM_DVB_C = 0x18, /*!< DVB-C */ ++ CEC_DIGITAL_BROADCAST_SYSTEM_DVB_S = 0x19, /*!< DVB-S */ ++ CEC_DIGITAL_BROADCAST_SYSTEM_DVB_S2 = 0x1A, /*!< DVB-S2 */ ++ CEC_DIGITAL_BROADCAST_SYSTEM_DVB_T = 0x1B /*!< DVB-T */ ++} tmdlHdmiCECDigitalBroadcastSystem_t; ++ ++/*! ++ \struct tmdlHdmiCECAribData_t ++ \brief This struct indicates the ARIB Data ++*/ ++typedef struct ++{ ++ UInt16 TransportStreamID ; /*!< Tansport_stream_id of the transport stream carrying the required service */ ++ UInt16 ServiceID ; /*!< Service_ID of the required service */ ++ UInt16 OriginalNetworkID ; /*!< Original_network_ID of the network carrying the transport stream for the required service */ ++} tmdlHdmiCECAribData_t ; ++ ++/*! ++ \struct tmdlHdmiCECAtscData_t ++ \brief This struct indicates the ATSC Data ++*/ ++typedef struct ++{ ++ UInt16 TransportStreamID ; /*!< Tansport_stream_id of the transport stream carrying the required service */ ++ UInt16 ProgramNumber ; /*!< Program Number of the required service */ ++ UInt16 Reserved ; /*!< Reserved */ ++} tmdlHdmiCECAtscData_t ; ++ ++/*! ++ \struct tmdlHdmiCECDvbData_t ++ \brief This struct indicates the DVB Data ++*/ ++typedef struct ++{ ++ UInt16 TransportStreamID ; /*!< Tansport_stream_id of the transport stream carrying the required service */ ++ UInt16 ServiceID ; /*!< Service_ID of the required service */ ++ UInt16 OriginalNetworkID ; /*!< Original_network_ID of the network carrying the transport stream for the required service */ ++} tmdlHdmiCECDvbData_t ; ++ ++/*! ++ \struct tmdlHdmiCECChannelData_t ++ \brief This struct indicates the Channel Data ++*/ ++typedef struct ++{ ++ tmdlHdmiCECChannelIdentifier_t ChannelIdentifier ; /*!< Logical or virtual channel number of a service */ ++ UInt16 Reserved ; /*!< Reserved */ ++} tmdlHdmiCECChannelData_t ; ++ ++/*! ++ \struct tmdlHdmiCECDigitalServiceIdentification_t ++ \brief This struct indicates the Digital Broadcast System ++ and the parameters to identify a specific service ++*/ ++typedef struct _tmdlHdmiCECDigitalServiceIdentification_t ++{ ++ tmdlHdmiCECServiceIdentMethod_t ServiceIdentificationMethod ; /*!< See tmdlHdmiCECServiceIdentMethod_t */ ++ tmdlHdmiCECDigitalBroadcastSystem_t DigitalBroadcastSystem ; /*!< See tmdlHdmiCECDigitalBroadcastSystem_t */ ++ void *pServiceIdentification ; /*!< tmdlHdmiCECAribData_t or tmdlHdmiCECAtscData_t or tmdlHdmiCECDvbData_t or tmdlHdmiCECChannelData_t */ ++}tmdlHdmiCECDigitalServiceIdentification_t, *ptmdlHdmiCECDigitalServiceIdentification_t; ++ ++/*! ++ \enum tmdlHdmiCECDisplayControl_t ++ \brief This enum indicates the display mode for an on screen display message ++*/ ++typedef enum ++{ ++ CEC_DISPLAY_CONTROL_DEFAULT_TIME = 0 , /*!< Display for default time */ ++ CEC_DISPLAY_CONTROL_UNTIL_CLEARED = 64 , /*!< Display until cleared */ ++ CEC_DISPLAY_CONTROL_CLEAR_PREVIOUS_MESSAGE = 128, /*!< Clear previous message */ ++ CEC_DISPLAY_CONTROL_RESERVED = 192 /*!< Clear previous message */ ++} tmdlHdmiCECDisplayControl_t; ++ ++/*! ++ \struct tmdlHdmiCECDuration_t ++ \brief This struct indicates a duration in BCD format ++*/ ++typedef struct ++{ ++ UInt8 Hours ; /*!< Duration hours in bcd format between 0 and 99 */ ++ UInt8 Minute ; /*!< Duration minute in bcd format between 0 and 59 */ ++} tmdlHdmiCECDuration_t ; ++ ++/*! ++ \brief This typedef indicates physical adress of device that is to be used as the source of a recording ++*/ ++typedef UInt16 tmdlHdmiCECExternalPhysicalAddress_t ; ++ ++/*! ++ \brief This typedef indicates external plug number (1 to 255 )on the recording device ++*/ ++typedef UInt8 tmdlHdmiCECExternalPlug_t; ++ ++/*! ++ \enum tmdlHdmiCECExternalSourceSpecifier_t ++ \brief This enum indicates External source specifier ++*/ ++typedef enum ++{ ++ CEC_EXTERNAL_PLUG = 4 , /*!< Display for default time */ ++ CEC_EXTERNAL_PHYSICAL_ADDRESS = 5 /*!< Display until cleared */ ++} tmdlHdmiCECExternalSourceSpecifier_t; ++ ++/*! ++ \brief This typedef indicates External Source is specified bey exeternal plug number on the recording device ++ or by the External physical Adress of the required source ++*/ ++typedef UInt8 ExternalSourceSpecifier; ++ ++ ++/*! ++ \enum tmdlHdmiCECFeatureOpcode_t ++ \brief This enum defines command to be performed ++*/ ++typedef enum ++{ ++ CEC_OPCODE_FEATURE_ABORT = 0x00, /*!< */ ++ CEC_OPCODE_IMAGE_VIEW_ON = 0x04, /*!< */ ++ CEC_OPCODE_TUNER_STEP_INCREMENT = 0x05, /*!< */ ++ CEC_OPCODE_TUNER_STEP_DECREMENT = 0x06, /*!< */ ++ CEC_OPCODE_TUNER_DEVICE_STATUS = 0x07, /*!< */ ++ CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS = 0x08, /*!< */ ++ CEC_OPCODE_RECORD_ON = 0x09, /*!< */ ++ CEC_OPCODE_RECORD_STATUS = 0x0A, /*!< */ ++ CEC_OPCODE_RECORD_OFF = 0x0B, /*!< */ ++ CEC_OPCODE_TEXT_VIEW_ON = 0x0D, /*!< */ ++ CEC_OPCODE_RECORD_TV_SCREEN = 0x0F, /*!< */ ++ CEC_OPCODE_GIVE_DECK_STATUS = 0x1A, /*!< */ ++ CEC_OPCODE_DECK_STATUS = 0x1B, /*!< */ ++ CEC_OPCODE_SET_MENU_LANGUAGE = 0x32, /*!< */ ++ CEC_OPCODE_CLEAR_ANALOGUE_TIMER = 0x33, /*!< */ ++ CEC_OPCODE_SET_ANALOGUE_TIMER = 0x34, /*!< */ ++ CEC_OPCODE_TIMER_STATUS = 0x35, /*!< */ ++ CEC_OPCODE_STANDBY = 0x36, /*!< */ ++ CEC_OPCODE_PLAY = 0x41, /*!< */ ++ CEC_OPCODE_DESCK_CONTROL = 0x42, /*!< */ ++ CEC_OPCODE_TIMER_CLEARED_STATUS = 0x43, /*!< */ ++ CEC_OPCODE_USER_CONTROL_PRESSED = 0x44, /*!< */ ++ CEC_OPCODE_USER_CONTROL_RELEASED = 0x45, /*!< */ ++ CEC_OPCODE_GIVE_OSD_NAME = 0x46, /*!< */ ++ CEC_OPCODE_SET_OSD_NAME = 0x47, /*!< */ ++ CEC_OPCODE_SET_OSD_STRING = 0x64, /*!< */ ++ CEC_OPCODE_SET_TIMER_PROGRAM_TITLE = 0x67, /*!< */ ++ CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST = 0x70, /*!< */ ++ CEC_OPCODE_GIVE_AUDIO_STATUS = 0x71, /*!< */ ++ CEC_OPCODE_SET_SYSTEM_AUDIO_MODE = 0x72, /*!< */ ++ CEC_OPCODE_REPORT_AUDIO_STATUS = 0x7A, /*!< */ ++ CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D, /*!< */ ++ CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS = 0x7E, /*!< */ ++ CEC_OPCODE_ROUTING_CHANGE = 0x80, /*!< */ ++ CEC_OPCODE_ROUTING_INFORMATION = 0x81, /*!< */ ++ CEC_OPCODE_ACTIVE_SOURCE = 0x82, /*!< */ ++ CEC_OPCODE_GIVE_PHYSICAL_ADDRESS = 0x83, /*!< */ ++ CEC_OPCODE_REPORT_PHYSICAL_ADDRESS = 0x84, /*!< */ ++ CEC_OPCODE_REQUEST_ACTIVE_SOURCE = 0x85, /*!< */ ++ CEC_OPCODE_SET_STREAM_PATH = 0x86, /*!< */ ++ CEC_OPCODE_DEVICE_VENDOR_ID = 0x87, /*!< */ ++ CEC_OPCODE_VENDOR_COMMAND = 0x89, /*!< */ ++ CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN = 0x8A, /*!< */ ++ CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP = 0x8B, /*!< */ ++ CEC_OPCODE_GIVE_DEVICE_VENDOR_ID = 0x8C, /*!< */ ++ CEC_OPCODE_MENU_REQUEST = 0x8D, /*!< */ ++ CEC_OPCODE_MENU_STATUS = 0x8E, /*!< */ ++ CEC_OPCODE_GIVE_DEVICE_POWER_STATUS = 0x8F, /*!< */ ++ CEC_OPCODE_REPORT_POWER_STATUS = 0x90, /*!< */ ++ CEC_OPCODE_GET_MENU_LANGUAGE = 0x91, /*!< */ ++ CEC_OPCODE_SET_ANALOGUE_SERVICE = 0x92, /*!< */ ++ CEC_OPCODE_SET_DIGITAL_SERVICE = 0x93, /*!< */ ++ CEC_OPCODE_SET_DIGITAL_TIMER = 0x97, /*!< */ ++ CEC_OPCODE_CLEAR_DIGITAL_TIMER = 0x99, /*!< */ ++ CEC_OPCODE_SET_AUDIO_RATE = 0x9A, /*!< */ ++ CEC_OPCODE_INACTIVE_SOURCE = 0x9D, /*!< */ ++ CEC_OPCODE_CEC_VERSION = 0x9E, /*!< */ ++ CEC_OPCODE_GET_CEC_VERSION = 0x9F, /*!< */ ++ CEC_OPCODE_VENDOR_COMMAND_WITH_ID = 0xA0, /*!< */ ++ CEC_OPCODE_CLEAR_EXTERNAL_TIMER = 0xA1, /*!< */ ++ CEC_OPCODE_SET_EXTERNAL_TIMER = 0xA2, /*!< */ ++ CEC_OPCODE_REPORT_SHORT_AUDIO_DESCRIPTOR = 0xA3, /*!< */ ++ CEC_OPCODE_REQUEST_SHORT_AUDIO_DESCRIPTOR = 0xA4, /*!< */ ++ CEC_OPCODE_INITATE_ARC = 0xC0, /*!< */ ++ CEC_OPCODE_REPORT_ARC_INITIATED = 0xC1, /*!< */ ++ CEC_OPCODE_REPORT_ARC_TERMINATED = 0xC2, /*!< */ ++ CEC_OPCODE_REPORT_ARC_INITIATION = 0xC3, /*!< */ ++ CEC_OPCODE_REPORT_ARC_TERMINATION = 0xC4, /*!< */ ++ CEC_OPCODE_TERMINATE_ARC = 0xC5, /*!< */ ++ CEC_OPCODE_ABORT_MESSAGE = 0xFF /*!< This message is reserved for testing*/ ++} tmdlHdmiCECFeatureOpcode_t; ++ ++ ++/*! ++ \enum tmdlHdmiCECMenuRequestType_t ++ \brief This enum specifies wether to activate or desactivate a devices menu or ++ simply query its current menu status ++*/ ++typedef enum ++{ ++ CEC_MENU_TYPE_ACTIVATE = 0 , /*!< Activate */ ++ CEC_MENU_TYPE_DEACTIVATE = 1 , /*!< Deactivate */ ++ CEC_MENU_TYPE_QUERY = 2 /*!< Query */ ++} tmdlHdmiCECMenuRequestType_t; ++ ++/*! ++ \enum tmdlHdmiCECMenuState_t ++ \brief This enum pecifies state of the device menu ++*/ ++typedef enum ++{ ++ CEC_MENU_STATE_ACTIVATE = 0 , /*!< Activate */ ++ CEC_MENU_STATE_DEACTIVATE = 1 /*!< Deactivate */ ++} tmdlHdmiCECMenuState_t; ++ ++/*! ++ \enum tmdlHdmiCECPlayMode_t ++ \brief This enum indicates in which mode to play media ++*/ ++typedef enum ++{ ++ CEC_MODE_PLAY_FORWARD = 0x24 , ++ CEC_MODE_PLAY_REVERSE = 0x20 , ++ CEC_MODE_FAST_FORWARD_MIN_SPEED = 0x05 , ++ CEC_MODE_FAST_FORWARD_MEDIUM_SPEED = 0x06 , ++ CEC_MODE_FAST_FORWARD_MAX_SPEED = 0x07 , ++ CEC_MODE_FAST_REVERSE_MIN_SPEED = 0x09 , ++ CEC_MODE_FAST_REVERSE_MEDIUM_SPEED = 0x0A , ++ CEC_MODE_FAST_REVERSE_MAX_SPEED = 0x0B , ++ CEC_MODE_SLOW_FORWARD_MIN_SPEED = 0x15 , ++ CEC_MODE_SLOW_FORWARD_MEDIUM_SPEED = 0x16 , ++ CEC_MODE_SLOW_FORWARD_MAX_SPEED = 0x17 , ++ CEC_MODE_SLOW_REVERSE_MIN_SPEED = 0x19 , ++ CEC_MODE_SLOW_REVERSE_MEDIUM_SPEED = 0x1A , ++ CEC_MODE_SLOW_REVERSE_MAX_SPEED = 0x1B ++} tmdlHdmiCECPlayMode_t; ++ ++/*! ++ \enum tmdlHdmiCECPowerStatus_t ++ \brief This enum indicates the current power status of a device ++*/ ++typedef enum ++{ ++ CEC_POWER_STATUS_ON = 0x00 , /*!< On */ ++ CEC_POWER_STATUS_STANDBY = 0x01 , /*!< Standby */ ++ CEC_POWER_STATUS_TRANSITION_STANDBY_TO_ON = 0x02 , /*!< In Transition Standby to On */ ++ CEC_POWER_STATUS_TRANSITION_ON_TO_STANDBY = 0x03 /*!< In Transition On to StandBy */ ++} tmdlHdmiCECPowerStatus_t; ++ ++/*! ++ \enum tmdlHdmiCECRecordSourceType_t ++ \brief This enum allows the record source to be specified for a recording ++*/ ++typedef enum ++{ ++ CEC_RECORD_SOURCE_OWN_SOURCE = 1 , /*!< Own Source */ ++ CEC_RECORD_SOURCE_DIGITAL_SERVICE = 2 , /*!< Digital Service */ ++ CEC_RECORD_SOURCE_ANALOGUE_SERVICE = 3 , /*!< Analogue Service */ ++ CEC_RECORD_SOURCE_EXTERNAL_PLUG = 4 , /*!< External Plug */ ++ CEC_RECORD_SOURCE_EXTERNAL_PHYSICAL_ADDRESS = 5 /*!< External Physical Address */ ++} tmdlHdmiCECRecordSourceType_t; ++ ++/*! ++ \enum tmdlHdmiCECRecordStatusInfo_t ++ \brief This enum indicates the status of a recording ++*/ ++typedef enum ++{ ++ CEC_RECORD_STATUS_INFO_RECORDING_CURRENTLY_SELECTED_SOURCE = 1 , /*!< */ ++ CEC_RECORD_STATUS_INFO_RECORDING_DIGITAL_SERVICE = 2 , /*!< */ ++ CEC_RECORD_STATUS_INFO_RECORDING_ANALOGUE_SERVCICE = 3 , /*!< */ ++ CEC_RECORD_STATUS_INFO_RECORDING_EXTERNAL_INPUT = 4 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_UNABLE_TO_RECORD_DIGITAL_SERVICE = 5 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_UNABLE_TO_RECORD_ANALOGUE_SERVICE = 6 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_UNABLE_TO_SELECT_REQUIRED_SERVICE = 7 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_INVALID_EXTERNAL_PLUG_NUMBER = 9 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_INVALID_EXTERNAL_PHYSICAL_ADDRESS = 10 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_CA_SYSTEM_NOT_SUPPORTED = 11 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_NO_OR_INSUFFICIENT_CA_ENTITLEMENTS = 12 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_NOT_ALLOWED_TO_COPY_SOURCE = 13 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_NO_FURTHER_COPY_ALLOWED = 14 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_NO_MEDIA = 16 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_PLAYING = 17 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_ALREADY_RECORDING = 18 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_MEDIA_PROTECTED = 19 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_NO_SOURCE_SIGNAL = 20 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_MEDIA_PROBLEM = 21 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_NOT_ENOUGH_SPACE_AVAILABLE = 22 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_REC_PARENTAL_LOCK_ON = 23 , /*!< */ ++ CEC_RECORD_STATUS_INFO_RECORDING_TERMINATED_NORMALLY = 26 , /*!< */ ++ CEC_RECORD_STATUS_INFO_RECORDING_HAS_ALREADY_TERMINATED = 27 , /*!< */ ++ CEC_RECORD_STATUS_INFO_NO_RECORDING_OTHER_REASON = 31 /*!< */ ++} tmdlHdmiCECRecordStatusInfo_t; ++ ++ ++/*! ++ \enum tmdlHdmiCECRecordingSequence_t ++ \brief This enum indicates the status of a recording ++*/ ++typedef enum ++{ ++ CEC_RECORDING_SEQUENCE_ONCE_ONLY = 0 , /*!< */ ++ CEC_RECORDING_SEQUENCE_SYNDAY = 1 , /*!< */ ++ CEC_RECORDING_SEQUENCE_MONDAY = 2 , /*!< */ ++ CEC_RECORDING_SEQUENCE_TUESDAY = 4 , /*!< */ ++ CEC_RECORDING_SEQUENCE_WEDNESDAY = 8 , /*!< */ ++ CEC_RECORDING_SEQUENCE_THURSDAY = 16, /*!< */ ++ CEC_RECORDING_SEQUENCE_FRIDAY = 32, /*!< */ ++ CEC_RECORDING_SEQUENCE_SATURDAY = 64 /*!< */ ++} tmdlHdmiCECRecordingSequence_t; ++ ++/*! ++ \enum tmdlHdmiCECStatusRequest_t ++ \brief This enum contains the status request mode which can be report once or ++ on all future state changes or reporting off. ++*/ ++typedef enum ++{ ++ CEC_STATUS_REQUEST_ON = 1 , /*!< Status Request ON */ ++ CEC_STATUS_REQUEST_OFF = 2 , /*!< Status Request OFF */ ++ CEC_STATUS_REQUEST_ONCE = 3 /*!< Status Request ONCE */ ++} tmdlHdmiCECStatusRequest_t; ++ ++/*! ++ \enum tmdlHdmiCECSystemAudioStatus_t ++ \brief This enum indicates if the system audio Mode is On or Off ++*/ ++typedef enum ++{ ++ CEC_SYSTEM_AUDIO_STATUS_OFF = 0 , /*!< Status Request OFF */ ++ CEC_SYSTEM_AUDIO_STATUS_ON = 1 /*!< Status Request ON */ ++} tmdlHdmiCECSystemAudioStatus_t; ++ ++/*! ++ \enum tmdlHdmiCECTimerClearedStatusData_t ++ \brief This enum indicates status in message ++*/ ++typedef enum ++{ ++ CEC_TIMER_STATUS_TIMER_NOT_CLEARED_RECORDING = 0, /*!< */ ++ CEC_TIMER_STATUS_TIMER_NOT_CLEARED_NO_MATCHING = 1, /*!< */ ++ CEC_TIMER_STATUS_TIMER_NOT_CLEARED_NO_INFO_AVAILABLE = 2, /*!< */ ++ CEC_TIMER_STATUS_TIMER_NOT_TIMER_CLEARED = 128 /*!< */ ++} tmdlHdmiCECTimerClearedStatusData_t; ++ ++ ++/*! ++ \enum tmdlHdmiCECTimerOverlapWarning_t ++ \brief This enum indicates if there is another timer block already set which ++ overlaps with this new recording request ++*/ ++typedef enum ++{ ++ CEC_TIMER_OVERLAP_WARNING_NO_OVERLAP = 0, /*!< No Overlap */ ++ CEC_TIMER_OVERLAP_WARNING_TIMER_BLOCKS_OVERLAP = 1 /*!< Timer blocks overlap */ ++} tmdlHdmiCECTimerOverlapWarning_t; ++ ++/*! ++ \enum tmdlHdmiCECMediaInfo_t ++ \brief This enum indicates if removable media is present and its write protect state ++*/ ++typedef enum ++{ ++ CEC_MEDIA_INFO_MEDIA_PRESENT_AND_NOT_PROTECTED = 0, /*!< Media present and not protected */ ++ CEC_MEDIA_INFO_MEDIA_PRESENT_BUT_PROTECTED = 1, /*!< Media present but protected */ ++ CEC_MEDIA_INFO_MEDIA_NOT_PRESENT = 2, /*!< Media not present */ ++ CEC_MEDIA_INFO_FUTURE_USE = 3 /*!< Future use */ ++} tmdlHdmiCECMediaInfo_t; ++ ++ ++/*! ++ \enum tmdlHdmiCECProgrammedIndicator_t ++ \brief This enum indicates a selector for [Timer Programmed Info] ++*/ ++typedef enum ++{ ++ CEC_PROGRAM_INDICATOR_NOT_PROGRAMMED = 0, /*!< */ ++ CEC_PROGRAM_INDICATOR_PROGRAMMED = 1 /*!< */ ++} tmdlHdmiCECProgrammedIndicator_t; ++ ++/*! ++ \enum tmdlHdmiCECProgrammedInfo_t ++ \brief This enum indicates any non-fatal issues with the programming request ++*/ ++typedef enum ++{ ++ CEC_PROGRAM_INFO_ENOUGHT_SPACE_AVAILABLE_FOR_RECORDING = 8, /*!< */ ++ CEC_PROGRAM_INFO_NOT_ENOUGHT_SPACE_AVAILABLE_FOR_RECORDING = 9, /*!< */ ++ CEC_PROGRAM_INFO_NO_MEDIA_INFO_AVAILABLE = 10,/*!< */ ++ CEC_PROGRAM_INFO_MAY_NOT_BE_ENOUGH_SPACE_AVAILABLE = 11 /*!< */ ++} tmdlHdmiCECProgrammedInfo_t; ++ ++ ++/*! ++ \enum tmdlHdmiCECNotProgrammedErrorInfo_t ++ \brief This enum indicates reason for programming failure ++*/ ++typedef enum ++{ ++ CEC_PROGRAM_ERROR_INFO_FUTURE_USE = 0, /*!< */ ++ CEC_PROGRAM_ERROR_INFO_NO_FREE_TIMER_AVAILABLE = 1, /*!< */ ++ CEC_PROGRAM_ERROR_INFO_DATE_OUT_OF_RANGE = 2, /*!< */ ++ CEC_PROGRAM_ERROR_INFO_RECORDING_SEQUENCE_ERROR = 3, /*!< */ ++ CEC_PROGRAM_ERROR_INFO_INVALID_EXTERNAL_PLUG_NUMBER = 4, /*!< */ ++ CEC_PROGRAM_ERROR_INFO_INVALID_EXTERNAL_PHYSICAL_ADDRESS = 5, /*!< */ ++ CEC_PROGRAM_ERROR_INFO_CA_SYSTEM_NOT_SUPPORTED = 6, /*!< */ ++ CEC_PROGRAM_ERROR_INFO_NO_OR_INSUFFICIENT_CA_ENTITLMENTS = 7, /*!< */ ++ CEC_PROGRAM_ERROR_INFO_DOES_NOT_SUPPORT_RESOLUTION = 8, /*!< Tuner or recorder does not support HD */ ++ CEC_PROGRAM_ERROR_INFO_PARENTAL_LOCK_ON = 9, /*!< */ ++ CEC_PROGRAM_ERROR_INFO_CLOCK_FAILURE = 10, /*!< */ ++ CEC_PROGRAM_ERROR_INFO_DUPLICATE_ALREADY_PROGRAMMED = 14 /*!< A timer block with identical details has already been programmed*/ ++} tmdlHdmiCECNotProgrammedErrorInfo_t; ++ ++/*! ++ \struct tmdlHdmiCECTimerProgrammedInfo_t ++ \brief This struct ++*/ ++typedef struct ++{ ++ tmdlHdmiCECProgrammedIndicator_t SelectProgramInfo ; /*!< tmdlHdmiCECProgrammedIndicator_t */ ++ UInt8 ProgramInfo; /*!< tmdlHdmiCECProgrammedInfo_t or tmdlHdmiCECNotProgrammedErrorInfo_t*/ ++ UInt16 DurationAvailable ; /*!< Optional paramter : If [Programmed Info] is "Not enough space available" */ ++} tmdlHdmiCECTimerProgrammedInfo_t ; /*!< If [Not Programmed Info] is "Duplicate : already programmed" */ ++ ++/*! ++ \struct tmdlHdmiCECTimerStatusData_t ++ \brief This struct is used by recording device to respond to the initiator ++ of a message ++*/ ++typedef struct ++{ ++ tmdlHdmiCECTimerOverlapWarning_t TimerOverlapWarning ; /*!< Indicates if there is another timer block already set which overlaps with this bew recording request*/ ++ tmdlHdmiCECMediaInfo_t MediaInfo ; /*!< Indicate if removable media is present and its write protect state */ ++ tmdlHdmiCECTimerProgrammedInfo_t TimerProgrammedInfo ; /*!< Give information about how and if the programming request has been done */ ++} tmdlHdmiCECTimerStatusData_t ; ++ ++ ++/*! ++ \enum tmdlHdmiCECRecordingFlag_t ++ \brief This enum indicates if the tuner is being used as a source of a recording ++*/ ++typedef enum ++{ ++ CEC_RECORDING_FLAG_NOT_BEING_USED_FOR_RECORDING = 0, /*!< Not Being used for recording */ ++ CEC_RECORDING_FLAG_BEING_USED_FOR_RECORDING = 1 /*!< Being used for recording */ ++} tmdlHdmiCECRecordingFlag_t; ++ ++/*! ++ \enum tmdlHdmiCECTunerDisplayInfo_t ++ \brief This enum indicates if the device is currently displaying its tuner or not. ++ (it may for example be displaying an external source or media) ++*/ ++typedef enum ++{ ++ CEC_TUNER_DISPLAY_MEDIA_DISPLAYING_DIGITAL_TUNER = 0, /*!< Displaying Digital Tuner */ ++ CEC_TUNER_DISPLAY_MEDIA_NOT_DISPLAYING_TUNER = 1, /*!< Not Displaying Tuner */ ++ CEC_TUNER_DISPLAY_MEDIA_DISPLAYING_ANALOGUE_TUNER = 2 /*!< Not Displaying Tuner */ ++} tmdlHdmiCECTunerDisplayInfo_t; ++ ++/*! ++ \enum tmdlHdmiCECUiBroadcastType_t ++ \brief This enum indicates type of broadcast ++*/ ++typedef enum ++{ ++ CEC_UI_BROADCAST_TYPE_ALL_AVAILABLE = 0x00 , /*!< */ ++ CEC_UI_BROADCAST_TYPE_DIGITAL_ANALOGUE_TOGGLE = 0x01 , /*!< */ ++ CEC_UI_BROADCAST_TYPE_ANALOGUE = 0x10 , /*!< */ ++ CEC_UI_BROADCAST_TYPE_ANALOGUE_TERRESTRIAL = 0x20 , /*!< */ ++ CEC_UI_BROADCAST_TYPE_ANALOGUE_CABLE = 0x30 , /*!< */ ++ CEC_UI_BROADCAST_TYPE_ANALOGUE_SATELLITE = 0x40 , /*!< */ ++ CEC_UI_BROADCAST_TYPE_DIGITAL = 0x50 , /*!< */ ++ CEC_UI_BROADCAST_TYPE_DIGITAL_TERRESTRIAL = 0x60 , /*!< */ ++ CEC_UI_BROADCAST_TYPE_DIGITAL_CABLE = 0x70 , /*!< */ ++ CEC_UI_BROADCAST_TYPE_DIGITAL_SATELLITE = 0x80 , /*!< */ ++ CEC_UI_BROADCAST_TYPE_DIGITAL_COM_SATELLITE = 0x90 , /*!< */ ++ CEC_UI_BROADCAST_TYPE_DIGITAL_COM_SATELLITE_2 = 0x91 , /*!< */ ++ CEC_UI_BROADCAST_TYPE_IP = 0xA0 /*!< */ ++} tmdlHdmiCECUiBroadcastType_t; ++ ++/*! ++ \enum tmdlHdmiCECUiSoundPresentationControl_t ++ \brief This enum indicates the selected command ++*/ ++typedef enum ++{ ++ CEC_UI_PRESENTATION_CONTROL_SOUND_MIX_DUAL_MONO = 0x20 , /*!< "Sound Mixing Mode (Dual Mono)" */ ++ CEC_UI_PRESENTATION_CONTROL_SOUND_MIX_KARAOKE = 0x30 , /*!< "Sound Mixing Mode (Karaoke)" */ ++ CEC_UI_PRESENTATION_CONTROL_SELECT_AUDIO_DOWNMIX = 0x80 , /*!< "Select Audio Downmix Mode" */ ++ CEC_UI_PRESENTATION_CONTROL_SELECT_AUDIO_REVERBERATION = 0x90 , /*!< "Select Audio Reverberation Processing Mode" */ ++ CEC_UI_PRESENTATION_CONTROL_SELECT_AUDIO_EQUALIZER = 0xA0 , /*!< "Select Audio Equalizer Mode" */ ++ CEC_UI_PRESENTATION_CONTROL_BASS_STEP_PLUS = 0xB1 , /*!< "bass step + " */ ++ CEC_UI_PRESENTATION_CONTROL_BASS_NEUTRAL_POSITION = 0xB2 , /*!< "bass neutral position" */ ++ CEC_UI_PRESENTATION_CONTROL_BASS_STEP_MINUS = 0xB3 , /*!< "bass step - " */ ++ CEC_UI_PRESENTATION_CONTROL_TREBLE_STEP_PLUS = 0xC1 , /*!< "Treble step + " */ ++ CEC_UI_PRESENTATION_CONTROL_TREBLE_NEUTRAL_POSITION = 0xC2 , /*!< "Treble neutral position" */ ++ CEC_UI_PRESENTATION_CONTROL_TREBLE_STEP_MINUS = 0xC3 /*!< "Treble step - " */ ++ ++} tmdlHdmiCECUiSoundPresentationControl_t; ++ ++/*! ++ \enum tmdlHdmiCECUserRemoteControlCommand_t ++ \brief This enum indicates the remote control button pressed ++*/ ++typedef enum ++{ ++ CEC_REMOTE_BUTTON_SELECT = 0, ++ CEC_REMOTE_BUTTON_UP = 1, ++ CEC_REMOTE_BUTTON_DOWN = 2, ++ CEC_REMOTE_BUTTON_LEFT = 3, ++ CEC_REMOTE_BUTTON_RIGHT = 4, ++ CEC_REMOTE_BUTTON_RIGHT_UP = 5, ++ CEC_REMOTE_BUTTON_RIGHT_DOWN = 6, ++ CEC_REMOTE_BUTTON_LEFT_UP = 7, ++ CEC_REMOTE_BUTTON_LEFT_DOWN = 8, ++ CEC_REMOTE_BUTTON_ROOT_MENU = 9, ++ CEC_REMOTE_BUTTON_SETUP_MENU = 10, ++ CEC_REMOTE_BUTTON_CONTENTS_MENU = 11, ++ CEC_REMOTE_BUTTON_FAVORITE_MENU = 12, ++ CEC_REMOTE_BUTTON_EXIT = 13, ++ CEC_REMOTE_BUTTON_MEDIA_TOP_MENU = 16, ++ CEC_REMOTE_BUTTON_MEDIA_CONTEXT = 17, ++ CEC_REMOTE_BUTTON_NUMBER_ENTRY_MODE = 29, ++ CEC_REMOTE_BUTTON_NUMBER_11 = 30, ++ CEC_REMOTE_BUTTON_NUMBER_12 = 31, ++ CEC_REMOTE_BUTTON_NUMBER_0_OR_NUMBER_10 = 32, ++ CEC_REMOTE_BUTTON_NUMBER_1 = 33, ++ CEC_REMOTE_BUTTON_NUMBER_2 = 34, ++ CEC_REMOTE_BUTTON_NUMBER_3 = 35, ++ CEC_REMOTE_BUTTON_NUMBER_4 = 36, ++ CEC_REMOTE_BUTTON_NUMBER_5 = 37, ++ CEC_REMOTE_BUTTON_NUMBER_6 = 38, ++ CEC_REMOTE_BUTTON_NUMBER_7 = 39, ++ CEC_REMOTE_BUTTON_NUMBER_8 = 40, ++ CEC_REMOTE_BUTTON_NUMBER_9 = 41, ++ CEC_REMOTE_BUTTON_DOT = 42, ++ CEC_REMOTE_BUTTON_ENTER = 43, ++ CEC_REMOTE_BUTTON_CLEAR = 44, ++ CEC_REMOTE_BUTTON_NEXT_FAVORITE = 47, ++ CEC_REMOTE_BUTTON_CHANNEL_UP = 48, ++ CEC_REMOTE_BUTTON_CHANNEL_DOWN = 49, ++ CEC_REMOTE_BUTTON_PREVIOUS_CHANNEL = 50, ++ CEC_REMOTE_BUTTON_SOUND_SELECT = 51, ++ CEC_REMOTE_BUTTON_INPUT_SELECT = 52, ++ CEC_REMOTE_BUTTON_DISPLAY_INFORMATION = 53, ++ CEC_REMOTE_BUTTON_HELP = 54, ++ CEC_REMOTE_BUTTON_PAGE_UP = 55, ++ CEC_REMOTE_BUTTON_PAGE_DOWN = 56, ++ CEC_REMOTE_BUTTON_POWER = 64, ++ CEC_REMOTE_BUTTON_VOLUME_UP = 65, ++ CEC_REMOTE_BUTTON_VOLUME_DOWN = 66, ++ CEC_REMOTE_BUTTON_MUTE = 67, ++ CEC_REMOTE_BUTTON_PLAY = 68, ++ CEC_REMOTE_BUTTON_STOP = 69, ++ CEC_REMOTE_BUTTON_PAUSE = 70, ++ CEC_REMOTE_BUTTON_RECORD = 71, ++ CEC_REMOTE_BUTTON_REWIND = 72, ++ CEC_REMOTE_BUTTON_FAST_FORWARD = 73, ++ CEC_REMOTE_BUTTON_EJECT = 74, ++ CEC_REMOTE_BUTTON_FORWARD = 75, ++ CEC_REMOTE_BUTTON_BACKWARD = 76, ++ CEC_REMOTE_BUTTON_STOP_RECORD = 77, ++ CEC_REMOTE_BUTTON_PAUSE_RECORD = 78, ++ CEC_REMOTE_BUTTON_ANGLE = 80, ++ CEC_REMOTE_BUTTON_SUB_PICTURE = 81, ++ CEC_REMOTE_BUTTON_VIDEO_ON_DEMAND = 82, ++ CEC_REMOTE_BUTTON_ELECTRONIC_PROGRAM_GUIDE = 83, ++ CEC_REMOTE_BUTTON_TIMER_PROGRAMMING = 84, ++ CEC_REMOTE_BUTTON_INITIAL_CONFIGURATION = 85, ++ CEC_REMOTE_BUTTON_SELECT_BROADCAST_TYPE = 86, ++ CEC_REMOTE_BUTTON_SELECT_SOUND_PRESENTATION = 87, ++ CEC_REMOTE_BUTTON_PLAY_FUNCTION = 96, ++ CEC_REMOTE_BUTTON_PAUSE_PLAY_FUNCTION = 97, ++ CEC_REMOTE_BUTTON_RECORD_FUNCTION = 98, ++ CEC_REMOTE_BUTTON_PAUSE_RECORD_FUNCTION = 99, ++ CEC_REMOTE_BUTTON_STOP_FUNCTION = 100, ++ CEC_REMOTE_BUTTON_MUTE_FUNCTION = 101, ++ CEC_REMOTE_BUTTON_RESTORE_VOLUME_FUNCTION = 102, ++ CEC_REMOTE_BUTTON_TUNE_FUNCTION = 103, ++ CEC_REMOTE_BUTTON_SELECT_MEDIA_FUNCTION = 104, ++ CEC_REMOTE_BUTTON_SELECT_AV_INPUT_FUNCTION = 105, ++ CEC_REMOTE_BUTTON_SELECT_AUDIO_INPUT_FUNCTION = 106, ++ CEC_REMOTE_BUTTON_POWER_TOGGLE_FUNCTION = 107, ++ CEC_REMOTE_BUTTON_POWER_OFF_FUNCTION = 108, ++ CEC_REMOTE_BUTTON_POWER_ON_FUNCTION = 109, ++ CEC_REMOTE_BUTTON_F1_BLUE = 113, ++ CEC_REMOTE_BUTTON_F2_RED = 114, ++ CEC_REMOTE_BUTTON_F3_GREEN = 115, ++ CEC_REMOTE_BUTTON_F4_YELLOW = 116, ++ CEC_REMOTE_BUTTON_F5 = 117, ++ CEC_REMOTE_BUTTON_DATA = 118 ++} tmdlHdmiCECUserRemoteControlCommand_t; ++ ++/*! ++ \enum tmdlHdmiCECLogicalAddress_t ++ \brief This enum indicates the logical address of the a device ++*/ ++typedef enum ++{ ++ CEC_LOGICAL_ADDRESS_TV = 0, /*!< TV */ ++ CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_1 = 1, /*!< Recording Device 1 */ ++ CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_2 = 2, /*!< Recording Device 1 */ ++ CEC_LOGICAL_ADDRESS_TUNER_1 = 3, /*!< Tuner 1 */ ++ CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_1 = 4, /*!< Playback Device 1 */ ++ CEC_LOGICAL_ADDRESS_AUDIO_SYSTEM = 5, /*!< Audio System */ ++ CEC_LOGICAL_ADDRESS_TUNER_2 = 6, /*!< Tuner 2 */ ++ CEC_LOGICAL_ADDRESS_TUNER_3 = 7, /*!< Tuner 3 */ ++ CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_2 = 8, /*!< Playback Device 2 */ ++ CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_3 = 9, /*!< Recording Device 3 */ ++ CEC_LOGICAL_ADDRESS_TUNER_4 = 10, /*!< Tuner 4 */ ++ CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_3 = 11, /*!< Playback Device 3 */ ++ CEC_LOGICAL_ADDRESS_RESERVED1 = 12, /*!< Reserved */ ++ CEC_LOGICAL_ADDRESS_RESERVED2 = 13, /*!< Reserved */ ++ CEC_LOGICAL_ADDRESS_SPECIFIC_USE = 14, /*!< Specific Use */ ++ CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST = 15 /*!< Unregistred/Broadcast */ ++} tmdlHdmiCECLogicalAddress_t; ++ ++ ++/*! ++ \enum tmdlHdmiCecEvent_t ++ \brief Enum listing all events that can be signalled to application ++ */ ++typedef enum ++{ ++ TMDL_HDMICEC_CALLBACK_MESSAGE_AVAILABLE = 0, /**< A message is available on CEC line */ ++ TMDL_HDMICEC_CALLBACK_STATUS = 1, /**< Status of CEC line */ ++} tmdlHdmiCecEvent_t; ++ ++/*! ++ \enum tmdlHdmiCecEventStatus_t ++ \brief Enum listing all available event status ++ */ ++typedef enum ++{ ++ TMDL_HDMICEC_EVENT_ENABLED, /*!< Event is enabled */ ++ TMDL_HDMICEC_EVENT_DISABLED /*!< Event is disabled */ ++} tmdlHdmiCecEventStatus_t; ++ ++/** ++ * \brief System function pointer type, to call user I2C read/write functions ++ * \param slaveAddr The I2C slave address ++ * \param firstRegister The first device register address to read or write ++ * \param lenData Length of data to read or write (i.e. no. of registers) ++ * \param pData Pointer to data to write, or to buffer to receive data ++ * \return The call result: ++ * - TM_OK: the call was successful ++ * - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing ++ * - TMBSL_ERR_HDMI_I2C_READ: failed when reading ++ */ ++typedef struct ++{ ++ UInt8 slaveAddr; ++ UInt8 firstRegister; ++ UInt8 lenData; ++ UInt8 *pData; ++} tmdlHdmiCecSysArgs_t; ++typedef tmErrorCode_t (*ptmdlHdmiCecSysFunc_t) (tmdlHdmiCecSysArgs_t *pSysArgs); ++ ++ ++/*! ++ \brief Timer function pointer type, to call an application timer ++ \param Parameter ms: Delay in milliseconds required ++ */ ++typedef Void (*ptmbslHdmiCecSysFuncTimer_t) (UInt16 ms); ++ ++/*! ++ \brief Callback function pointer type, used to allow driver to callback ++ application when activity status is changing at input. ++ \param Event Identifier of the source event. ++ */ ++typedef void (*ptmdlHdmiCecCallbackFunc_t) (tmdlHdmiCecEvent_t event, ++ UInt8 *pdata, ++ UInt8 size); ++ ++/*! ++ \brief Enum listing all supported device versions ++ */ ++ typedef enum ++ { ++ TMDL_HDMICEC_DEVICE_UNKNOWN, /*!< HW device is unknown */ ++ TMDL_HDMICEC_DEVICE_TDA9950, /*!< HW device is a TDA9950 */ ++ TMDL_HDMICEC_DEVICE_TDA9989, /*!< HW device is a TDA9989 */ ++ } tmdlHdmiCecDeviceVersion_t; ++ ++ ++/*! ++ \brief Enum listing possible CEC clock source ++ */ ++ typedef enum ++ { ++ TMDL_HDMICEC_CLOCK_XTAL, ++ TMDL_HDMICEC_CLOCK_FRO, ++ TMDL_HDMICEC_CLOCK_PCLK ++ } tmdlHdmiCecClockSource_t; ++ ++ ++/** ++ * \brief Structure describing unit capabilities ++ */ ++typedef struct ++{ ++ tmdlHdmiCecDeviceVersion_t DeviceVersion; /*!< HW device version */ ++ tmdlHdmiCECVersion_t HdmiCecVersion; /*!< Supported HDMI CEC standard version */ ++} tmdlHdmiCecCapabilities_t; ++ ++ ++/*! ++ \struct tmdlHdmiCECInstanceSetup_t ++ \brief This struct is used to setup CEC driver by application ++ Application setup the device and state of the device. ++*/ ++ ++typedef struct _tmdlHdmiCecInstanceSetup_t ++{ ++ tmdlHdmiCECLogicalAddress_t DeviceLogicalAddress; ++ tmdlHdmiCecClockSource_t cecClockSource; ++// tmdlHdmiCECDeviceState_t DeviceState; ++} tmdlHdmiCecInstanceSetup_t, *ptmdlHdmiCecInstanceSetup_t; ++ ++ ++/** ++ * \brief The structure of a CEC Data Register Protocol ++*/ ++typedef struct ++{ ++ UInt8 AddressByte; ++ Bool MessageTypePolling; /* Indicate if it's a poolling message "1" or a normal CEC message "0" */ ++ UInt8 Opcode; ++}tmdlHdmiCecSaveMessage_t; ++ ++typedef struct ++{ ++ UInt8 FrameByteCount; ++ UInt8 AddressByte; ++ UInt8 DataBytes[15]; ++}tmdlHdmiCecFrameFormat_t; ++ ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMDLHDMICEC_TYPES_H */ ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ ++ +diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC.c b/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC.c +new file mode 100755 +index 0000000..26df9b3 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC.c +@@ -0,0 +1,7575 @@ ++//============================================================================= ++// Copyright (C) 2007 NXP N.V., All Rights Reserved. ++// This source code and any compilation or derivative thereof is the proprietary ++// information of NXP N.V. and is confidential in nature. Under no circumstances ++// is this software to be exposed to or placed under an Open Source License of ++// any type without the expressed written permission of NXP N.V. ++//============================================================================= ++/*! ++ \file tmdlHdmiCEC.c ++ ++ \version 1.0 ++ ++ \date 24/07/2007 ++ ++ \brief devlib driver component API for the CEC features. ++ ++ \section refs Reference Documents ++ TDA998X Driver - tmdlHdmiTx - SCS.doc ++ \note None. ++ ++ HISTORY : ++ \verbatim ++ Date Modified by CRPRNr TASKNr Maintenance description ++ -------------|-----------|-------|-------|----------------------------------- ++ 24/07/2007 | F.G | | | Creation. ++ -------------|-----------|-------|-------|----------------------------------- ++ \endverbatim ++*/ ++//========================================================================== ++ ++/*============================================================================*/ ++/* FILE CONFIGURATION */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* STANDARD INCLUDE FILES */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* PROJECT INCLUDE FILES */ ++/*============================================================================*/ ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++#include ++#else ++#include ++#include ++#endif ++#include "tmdlHdmiCEC_IW.h" ++#include "tmdlHdmiCEC_cfg.h" ++#include "tmdlHdmiCEC.h" ++#include "tmdlHdmiCEC_local.h" ++ ++/*============================================================================*/ ++/* MACRO DEFINITIONS */ ++/*============================================================================*/ ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++#define DV_DBG_PRINT printk ++#else ++#define DV_DBG_PRINT printf ++#endif ++ ++/*============================================================================*/ ++/* TYPE DEFINITIONS */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* PUBLIC VARIABLE DEFINITIONS */ ++/*============================================================================*/ ++tmdlHdmiCecUnitConfig_t UnitTable[MAX_UNITS] = { ++ {0,CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST,False, TMDL_HDMICEC_DEVICE_TDA9950, CEC_STATE_NOT_INITIALIZED, 0} ++}; ++ ++tmdlHdmiCecDriverConfigTable_t gtmdlHdmiCecDriverConfigTable[MAX_UNITS]; ++ ++tmdlHdmiCecSaveMessage_t gtmdlHdmiCecDriverSaveMessage; ++ ++ ++/*============================================================================*/ ++/* STATIC CONSTANT DECLARATIONS */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* STATIC VARIABLE DECLARATIONS */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* STATIC FUNCTION DECLARATIONS */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* FUNCTIONS */ ++/*============================================================================*/ ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecGetSWVersion( ) ++ \brief Get the software version of the driver. ++ ++ \param pSWVersion Pointer to the version structure ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGetSWVersion ++( ++ tmSWVersion_t *pSWVersion ++) ++{ ++ /* check that input pointer is not NULL */ ++ RETIF(pSWVersion == Null, TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS) ++ ++ /* copy SW version */ ++ pSWVersion->compatibilityNr = VERSION_COMPATIBILITY; ++ pSWVersion->majorVersionNr = VERSION_MAJOR; ++ pSWVersion->minorVersionNr = VERSION_MINOR; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecGetNumberOfUnits( ) ++ \brief Get the number of available CEC devices in the system. ++ A unit directly represents a physical device. ++ ++ \param pUnitCount Pointer to the number of available units. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGetNumberOfUnits ++( ++ UInt32 *pUnitCount ++) ++{ ++ /* check that input pointer is not NULL */ ++ RETIF(pUnitCount == Null, TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS) ++ ++ /* copy the maximum number of units */ ++ *pUnitCount = MAX_UNITS; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecGetInstanceSetup( ) ++ \brief Get instance setup parameters. ++ ++ \param instance Instance identifier. ++ \param pSetupInfo Pointer to the structure that will receive setup ++ parameters ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGetInstanceSetup ++( ++ tmInstance_t instance, ++ ptmdlHdmiCecInstanceSetup_t pSetupInfo ++) ++{ ++ /* check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check that input pointer is not NULL */ ++ RETIF(pSetupInfo == Null, TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ pSetupInfo->DeviceLogicalAddress = UnitTable[instance].DeviceLogicalAddress; ++ ++ ++ return(TM_OK); ++} ++ ++//========================= ================================================= ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecHandleInterrupt( ) ++ \brief Make device library handle an incoming interrupt. This function is ++ used by application to tell the device library that the hardware ++ sent an interrupt. It can also be used to poll the interrupt status ++ of the device if the interrupt line is not physically connected to ++ the CPU. ++ This function is synchronous. ++ This function is ISR friendly. ++ ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_FULL: the queue is full ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecHandleInterrupt ++( ++ tmInstance_t instance ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_ReadBuffer[19] ; /* I2C Read data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ tmdlHdmiCecUnitConfig_t *pCecObject; /* Pointer to Cec Object */ ++ tmdlHdmiCecFrameFormat_t ReadFrame; ++ tmdlHdmiCecSaveMessage_t LastSendMessage; ++ int i; ++ ++ ++ pDis = >mdlHdmiCecDriverConfigTable[instance]; ++ pCecObject = &UnitTable[instance]; ++ ++#ifdef TMFL_TDA9989 ++ //Check if pending CEC interruption ++ errCode = getCecHwRegisters(pDis, E_REG_CEC_INT, I2c_ReadBuffer,1); ++ RETIF(errCode != TM_OK, errCode) ++ ++ if ((I2c_ReadBuffer[0] & CEC_INT_MASK) == 0x00) ++ { ++ //No CEC interruption pending. ++ return TM_OK; ++ } ++#endif ++ ++ errCode = getCecHwRegisters(pDis, E_REG_CDR0,I2c_ReadBuffer,19); ++ RETIF(errCode != TM_OK, errCode) ++ ++ /*Fill Frame structure with read data*/ ++ ++ /* Case of Receiving CECData.cnf*/ ++ /*Inform Success or reason of failure of CEC message sending*/ ++ if (I2c_ReadBuffer[1]== 0x01) ++ { ++ /* Get Infos of last message send */ ++ getCecLastMessage(&LastSendMessage); ++ ++ if (LastSendMessage.MessageTypePolling) ++ { ++ ReadFrame.FrameByteCount = I2c_ReadBuffer[0]; ++ ReadFrame.AddressByte = LastSendMessage.AddressByte; ++ ReadFrame.DataBytes[0]= I2c_ReadBuffer[2]; ++ } ++ else ++ { ++ ReadFrame.FrameByteCount = I2c_ReadBuffer[0]+1; ++ ReadFrame.AddressByte = LastSendMessage.AddressByte; ++ ReadFrame.DataBytes[0]= I2c_ReadBuffer[2]; ++ ReadFrame.DataBytes[1]= LastSendMessage.Opcode; ++ } ++ ++ pCecObject->MessageCallback(TMDL_HDMICEC_CALLBACK_STATUS ++ , (Void *) &ReadFrame, ReadFrame.FrameByteCount); ++ } ++ ++ /* Case of Receiving CECData.ind*/ ++ /*Give receive data from CEC bus*/ ++ if (I2c_ReadBuffer[1]== 0x81) ++ { ++ ReadFrame.FrameByteCount = I2c_ReadBuffer[0]; ++ ReadFrame.AddressByte = I2c_ReadBuffer[2]; ++ for (i=0; i<15; i++) ++ { ++ ReadFrame.DataBytes[i] = I2c_ReadBuffer[i+3]; ++ } ++ ++ pCecObject->MessageCallback(TMDL_HDMICEC_CALLBACK_MESSAGE_AVAILABLE ++ , (Void *) &ReadFrame, ReadFrame.FrameByteCount); ++ } ++ ++ return(TM_OK); ++ ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecOpen( ) ++ \brief Open unit 0 of CEC and provides the instance number to ++ the caller. Note that one unit of CEC represents one physical ++ CEC device and that only one instance per unit can be opened. ++ ++ \param pInstance Pointer to the variable that will receive the instance ++ identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_OWNED: the resource is already in use ++ - TMDL_ERR_DLHDMICEC_INIT_FAILED: the unit instance is already ++ initialised or something wrong happened at lower level. ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMICEC_NO_RESOURCES: the resource is not available ++ - TMDL_ERR_DLHDMICEC_INVALID_STATE: the state is invalid for ++ the function ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecOpen ++( ++ tmInstance_t *pInstance ++) ++{ ++ /* directly call OpenM function for unit 0 and return the result */ ++ return(tmdlHdmiCecOpenM(pInstance, (tmUnitSelect_t)0)); ++} ++ ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecOpenM( ) ++ \brief Open a specific unit of CEC driver and provides the instance ++ number to the caller. Note that one unit of CEC represents one ++ physical CEC device and that only one instance per unit can be ++ opened. This function switches driver's state machine to ++ "initialized" state. ++ ++ \param pInstance Pointer to the structure that will receive the instance ++ identifier. ++ \param unit Unit number to be opened. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_OWNED: the resource is already in use ++ - TMDL_ERR_DLHDMICEC_INIT_FAILED: the unit instance is already ++ initialised or something wrong happened at lower level. ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMICEC_NO_RESOURCES: the resource is not available ++ - TMDL_ERR_DLHDMICEC_INVALID_STATE: the state is invalid for ++ the function ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecOpenM ++( ++ tmInstance_t *pInstance, ++ tmUnitSelect_t unit ++) ++{ ++ ++ /* check if unit number is in range */ ++ RETIF((unit < 0) || (unit >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER) ++ ++ /* check if Instance pointer is Null */ ++ RETIF(pInstance == Null, TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS) ++ ++ /* check if unit is already instanciated */ ++ RETIF(UnitTable[unit].opened == True, TMDL_ERR_DLHDMICEC_RESOURCE_OWNED) ++ ++ /* Ckeck the state */ ++ RETIF(UnitTable[unit].state != CEC_STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ /* instanciate unit and return corresponding instance number */ ++ /* Since HW unit are only instanciable once, instance = unit */ ++ UnitTable[unit].opened = True; ++ UnitTable[unit].MessageCallback = Null; ++ /* Give a logical Address to Device */ ++ UnitTable[unit].DeviceLogicalAddress = CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST; ++ ++ /* Recover the configuration of the device library */ ++ RETIF(tmdlHdmiCecCfgGetConfig(unit, >mdlHdmiCecDriverConfigTable[unit])!= TM_OK, TMDL_ERR_DLHDMICEC_INIT_FAILED) ++ ++ *pInstance = (tmInstance_t)unit; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecClose( ) ++ \brief Close an instance of CEC driver. ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecClose ++( ++ tmInstance_t instance ++) ++{ ++ /* check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* close instance */ ++ UnitTable[instance].opened = False; ++ UnitTable[instance].state = CEC_STATE_NOT_INITIALIZED; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecInstanceConfig( ) ++ \brief Set the configuration of instance attributes. This function is ++ required by DVP architecture rules but actually does nothing in this ++ driver ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecInstanceConfig ++( ++ tmInstance_t instance ++) ++{ ++ if (instance); ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecInstanceSetup( ) ++ \brief Setup the instance with its configuration parameters. This function ++ allows basic instance configuration for CEC Stack Processor. ++ ++ \param instance Instance identifier. ++ \param pSetupInfo Pointer to the structure containing all setup parameters ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecInstanceSetup ++( ++ tmInstance_t instance, ++ tmdlHdmiCecInstanceSetup_t *pSetupInfo ++) ++{ ++ tmErrorCode_t errCode; ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++#ifdef TMFL_TDA9989 ++ unsigned char I2c_ReadBuffer[1]; ++#endif ++ ++ ++ /* check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check that input pointer is not NULL */ ++ RETIF(pSetupInfo == Null, TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* Ckeck the state */ ++ RETIF(UnitTable[instance].state != CEC_STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[instance]; ++ ++ /* Wait for 250 ms */ ++ RETIF( (errCode = tmdlHdmiTxIWWait(500) ) != TM_OK, errCode) ++ ++#ifdef TMFL_TDA9989 ++ /* Enable CEC Stack Processor */ ++ errCode = getCecHwRegisters(pDis, E_REG_CDR0,I2c_ReadBuffer,1); ++ RETIF(errCode != TM_OK, errCode) ++ ++ errCode = getCecHwRegisters(pDis, E_REG_ENAMODS,I2c_ReadBuffer,1); ++ RETIF(errCode != TM_OK, errCode) ++ ++ I2c_ReadBuffer[0] |= DEFAULT_ENAMODS; ++ ++ errCode = setCecHwRegister(pDis, E_REG_ENAMODS, I2c_ReadBuffer[0]); ++ if (errCode != TM_OK) ++ { ++ //TODO WA still needed? ++ errCode = setCecHwRegister(pDis, E_REG_ENAMODS, I2c_ReadBuffer[0]); ++ RETIF(errCode != TM_OK, errCode) ++ } ++ ++ RETIF( (errCode = tmdlHdmiTxIWWait(TDA9950_RESET_DELAY_MS) ) != TM_OK, errCode) ++ ++ /* Select CEC clock source and divider value */ ++ ++ if (pSetupInfo->cecClockSource == TMDL_HDMICEC_CLOCK_XTAL) ++ { ++ errCode = getCecHwRegisters(pDis, E_REG_CEC_CLK,I2c_ReadBuffer,1); ++ RETIF(errCode != TM_OK, errCode) ++ ++ I2c_ReadBuffer[0] &= CEC_CLK_SEL; ++ errCode = setCecHwRegister(pDis, E_REG_CEC_CLK, I2c_ReadBuffer[0]); ++ } ++ ++ RETIF( (errCode = tmdlHdmiTxIWWait(TDA9950_RESET_DELAY_MS) ) != TM_OK, errCode) ++ ++ //TODO WA to avoid spurious interrupts ++ errCode = getCecHwRegisters(pDis, E_REG_CDR0,I2c_ReadBuffer,1); ++ RETIF(errCode != TM_OK, errCode) ++#endif ++ ++ ++ /* Reset CEC Stack Processor */ ++ errCode = setCecHwRegister(pDis, E_REG_CCR, 0x80); ++ RETIF(errCode != TM_OK, errCode) ++ ++ ++ /* Wait for 250 ms */ ++ RETIF( (errCode = tmdlHdmiTxIWWait(TDA9950_RESET_DELAY_MS) ) != TM_OK, errCode) ++ ++ /* Configure Stack Processor (Retry = 5)*/ ++ errCode = setCecHwRegister(pDis, E_REG_CCONR, 0x05); ++ RETIF(errCode != TM_OK, errCode) ++ ++ ++ UnitTable[instance].DeviceLogicalAddress = pSetupInfo->DeviceLogicalAddress; ++ ++ ++ /* CEC Control register */ ++ errCode = setCecHwRegisterMsbLsb(pDis, E_REG_ACKH, 0x1 << (UnitTable[instance].DeviceLogicalAddress)); ++ RETIF(errCode != TM_OK, errCode) ++ ++ ++ /* CEC Stack Processor enable*/ ++ errCode = setCecHwRegister(pDis, E_REG_CCR, 0x40); ++ RETIF(errCode != TM_OK, errCode) ++ ++ ++ /* switch instance to its new state */ ++ UnitTable[instance].state = CEC_STATE_CONFIGURED; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRegisterCallback( ) ++ \brief Register event callbacks. Three types of callbacks can be ++ registered : input activity related callback, data related ++ callback (infoframes, packets, etc.) and general information ++ callback. A null pointer means that no callback are registered. ++ ++ \param instance Instance identifier. ++ \param MessageCallback Pointer to the callback function that will ++ handle message related events. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_INVALID_STATE: the state is invalid for ++ the function ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRegisterCallbacks ++( ++ tmInstance_t instance, ++ ptmdlHdmiCecCallbackFunc_t MessageCallback ++) ++{ ++ /* check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ /* store callback pointers */ ++ UnitTable[instance].MessageCallback = MessageCallback; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSetLogicalAddress( ) ++ \brief Set Device Logical Address ++ ++ \param instance Instance identifier. ++ \param LogicalAddress Logical address value. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetLogicalAddress ++( ++ tmInstance_t instance, ++ tmdlHdmiCECLogicalAddress_t LogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* Ckeck the state */ ++ RETIF(UnitTable[instance].state != CEC_STATE_CONFIGURED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[instance]; ++ ++ UnitTable[instance].DeviceLogicalAddress = LogicalAddress; ++ ++ errCode = setCecHwRegisterMsbLsb(pDis, E_REG_ACKH, 0x1 << (UnitTable[instance].DeviceLogicalAddress)); ++ RETIF(errCode != TM_OK, errCode) ++ ++ return(TM_OK); ++} ++ ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSetRetry( ) ++ \brief Change the number of retransmission ++ ++ \param instance Instance identifier. ++ \param NbRetry Number of retry. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetRetry ++( ++ tmInstance_t instance, ++ UInt8 NbRetry ++) ++{ ++ tmErrorCode_t errCode; ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* Ckeck the state */ ++ RETIF(UnitTable[instance].state != CEC_STATE_CONFIGURED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[instance]; ++ ++ /* Configure Retry register */ ++ errCode = setCecHwRegister(pDis, E_REG_CCONR, NbRetry); ++ RETIF(errCode != TM_OK, errCode) ++ ++ return(TM_OK); ++} ++ ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t getCecLastMessage( ) ++ \brief Return the Addresses and the Opcode of the last CEC ++ transmitted message ++ ++ \param pSaveMessage Pointer to the CEC Save Message ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t getCecLastMessage ++( ++ tmdlHdmiCecSaveMessage_t *pSaveMessage ++) ++{ ++ /* copy Last CEC message datas */ ++ pSaveMessage->AddressByte = gtmdlHdmiCecDriverSaveMessage.AddressByte; ++ pSaveMessage->MessageTypePolling = gtmdlHdmiCecDriverSaveMessage.MessageTypePolling; ++ pSaveMessage->Opcode = gtmdlHdmiCecDriverSaveMessage.Opcode; ++ ++ return(TM_OK); ++} ++ ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecImageViewOn( ) ++ \brief This message sent by a source device to the TV whenever it enters ++ the active state ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receivers. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecImageViewOn ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C Write data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ //RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Image View On command */ ++ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_IMAGE_VIEW_ON ; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecInactiveSource( ) ++ \brief This message is used by the currently active source to inform the ++ TV that it has no video to be presented to the user, or is going ++ into standby as the result of a lcoal user command on the device. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress, \n ++ Address of message receiver. \n ++ ++ \param tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress \n ++ Physical Address of the device. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecInactiveSource ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ //======To do : make a prepare message function with parameter ++ /* Inactive source command */ ++ I2c_Buffer[0] = 0x06; ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_INACTIVE_SOURCE ; /* Inactive Source*/ ++ I2c_Buffer[4] = (unsigned char)(PhysicalAddress >> 8); /* MsByte of Physical Address */ ++ I2c_Buffer[5] = (unsigned char)PhysicalAddress; /* LsByte of Physical Address */ ++ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecActiveSource() ++ \brief This message is used by a new source to indicate that it has started ++ to transmit a stream OR used in reponse to a ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt16 PhysicalAddress \n ++ Physical address of the device.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecActiveSource ++( ++ tmInstance_t Instance, ++ UInt16 PhysicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Active Source command */ ++ I2c_Buffer[0] = 0x06; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= 0x0F; /* Broadcast*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_ACTIVE_SOURCE ; /* Active source */ ++ I2c_Buffer[4] = (unsigned char)(PhysicalAddress >> 8); /* MsByte of Physical Address */ ++ I2c_Buffer[5] = (unsigned char)PhysicalAddress; /* LsByte of Physical Address */ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecVersion() ++ \brief This message is used to indicate the supported CEC version in response ++ to a ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress\n ++ Address of message receiver. \n ++ ++ \param tmdlHdmiCECVersion_t CECVersion \n ++ Supported CEC Version.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecVersion ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECVersion_t CECVersion ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* CEC Version command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_CEC_VERSION ; /* CECVersion*/ ++ I2c_Buffer[4] = CECVersion; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecClearAnalogueTimer( ) ++ \brief This message is used to clear an Analogue timer block of a device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param UInt8 DayOfMonth \n ++ Day of the month.\n ++ ++ \param UInt8 MonthOfYear \n ++ Month of the year.\n ++ ++ \param UInt16 StartTime \n ++ Start time for a timer based recording.\n ++ ++ \param UInt16 Duration \n ++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n ++ ++ \param UInt8 Recording Sequence \n ++ Indicates if recording is repeated and, if so, on which day ++ For repeated recording the recording sequence value is the ++ bitwise OR of the days when recordings are required ++ Shall be set to 0x00 when recording is not repeated.\n ++ ++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n ++ "Cable,Sattellite,Terrestrial".\n ++ ++ \param UInt16 AnalogueFrequency \n ++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n ++ ++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n ++ Specify information about the colour system, the sound carrier and ++ the IF-frequency.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecClearAnalogueTimer ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 DayOfMonth, ++ UInt8 MonthOfYear, ++ UInt16 StartTime, ++ tmdlHdmiCECDuration_t *pDuration, ++ UInt8 RecordingSequence, ++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType, ++ UInt16 AnalogueFrequency, ++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[15] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Clear Analogue Timer command */ ++ I2c_Buffer[0] = 0x0f; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_CLEAR_ANALOGUE_TIMER ; ++ I2c_Buffer[4] = DayOfMonth; /*Day of Month*/ ++ I2c_Buffer[5] = MonthOfYear; /*Month of Year*/ ++ I2c_Buffer[6] = (unsigned char)(StartTime >> 8); /*Start Time*/ ++ I2c_Buffer[7] = (UInt8)StartTime; ++ I2c_Buffer[8] = pDuration -> Hours; /*Duration Hours*/ ++ I2c_Buffer[9] = pDuration -> Minute; /*Duration minute*/ ++ I2c_Buffer[10] = RecordingSequence; /*Recording Sequence*/ ++ I2c_Buffer[11] = AnalogueBroadcastType; /*Analogue Broadcast Type*/ ++ I2c_Buffer[12] = (unsigned char)(AnalogueFrequency >> 8); /*Analogue Frequency*/ ++ I2c_Buffer[13] = (unsigned char)AnalogueFrequency; ++ I2c_Buffer[14] = BroadcastSystem; /*BroadcastSystem*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,15); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecClearDigitalTimer( ) ++ \brief This message is used to clear a digital timer block of a device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param UInt8 DayOfMonth \n ++ Day of the month.\n ++ ++ \param UInt8 MonthOfYear \n ++ Month of the year.\n ++ ++ \param UInt16 StartTime \n ++ Start time for a timer based recording.\n ++ ++ \param UInt16 Duration \n ++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n ++ ++ \param UInt8 Recording Sequence \n ++ Indicates if recording is repeated and, if so, on which day ++ For repeated recording the recording sequence value is the ++ bitwise OR of the days when recordings are required ++ Shall be set to 0x00 when recording is not repeated.\n ++ ++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n ++ Pointer to the structure Digital Service Identification ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecClearDigitalTimer ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 DayOfMonth, ++ UInt8 MonthOfYear, ++ UInt16 StartTime, ++ tmdlHdmiCECDuration_t *pDuration, ++ UInt8 RecordingSequence, ++ tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[18] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ tmdlHdmiCECAribData_t *pARIB_Pointer; ++ tmdlHdmiCECAtscData_t *pATSC_Pointer; ++ tmdlHdmiCECDvbData_t *pDVB_Pointer; ++ ++ unsigned char Regval; /* Local variable*/ ++ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ ++ //======To do : make a prepare message function with parameter ++ /* Clear Digital Timer command */ ++ I2c_Buffer[0] = 0x12; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_CLEAR_DIGITAL_TIMER ; ++ I2c_Buffer[4] = DayOfMonth; /*Day of Month*/ ++ I2c_Buffer[5] = MonthOfYear; /*Month of Year*/ ++ I2c_Buffer[6] = (unsigned char)(StartTime >> 8); /*Start Time*/ ++ I2c_Buffer[7] = (UInt8)StartTime; ++ I2c_Buffer[8] = pDuration -> Hours; /*Duration Hours*/ ++ I2c_Buffer[9] = pDuration -> Minute; /*Durantion Minute*/ ++ I2c_Buffer[10] = RecordingSequence; /*Recording Sequence*/ ++ ++ /* Digital service Identification*/ ++ /*Merge Service Method and Digital Broadcast System in the same Byte*/ ++ Regval = (unsigned char)(pServiceIdentification->ServiceIdentificationMethod & 0x01); /*bit 7 is Service Method*/ ++ Regval = Regval << 7; ++ Regval |= (unsigned char)(pServiceIdentification->DigitalBroadcastSystem & 0x7F); /*bits 6 to 0 are Digital Broadcast*/ ++ I2c_Buffer[11] = Regval; ++ ++ ++ /*Case of a ARIB Generic*/ ++ if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_GENERIC) ++ { ++ pARIB_Pointer = pServiceIdentification->pServiceIdentification; ++ ++ I2c_Buffer[12] = (unsigned char)(pARIB_Pointer->TransportStreamID >> 8); ++ I2c_Buffer[13] = (unsigned char)pARIB_Pointer->TransportStreamID; ++ I2c_Buffer[14] = (unsigned char)(pARIB_Pointer->ServiceID >> 8); ++ I2c_Buffer[15] = (unsigned char)pARIB_Pointer->ServiceID; ++ I2c_Buffer[16] = (unsigned char)(pARIB_Pointer->OriginalNetworkID >> 8); ++ I2c_Buffer[17] = (unsigned char)pARIB_Pointer->OriginalNetworkID; ++ ++ } ++ /*Case of a ATSC Generic*/ ++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ATSC_GENERIC) ++ { ++ pATSC_Pointer = pServiceIdentification->pServiceIdentification; ++ ++ I2c_Buffer[12] = (unsigned char)(pATSC_Pointer->TransportStreamID >> 8); ++ I2c_Buffer[13] = (unsigned char)pATSC_Pointer->TransportStreamID; ++ I2c_Buffer[14] = (unsigned char)(pATSC_Pointer->ProgramNumber >> 8); ++ I2c_Buffer[15] = (unsigned char)pATSC_Pointer->ProgramNumber; ++ I2c_Buffer[16] = (unsigned char)(pATSC_Pointer->Reserved >> 8); ++ I2c_Buffer[17] = (unsigned char)pATSC_Pointer->Reserved; ++ } ++ /*Case of a DVB Generic*/ ++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_DVB_GENERIC) ++ { ++ pDVB_Pointer = pServiceIdentification->pServiceIdentification; ++ ++ I2c_Buffer[12] = (unsigned char)(pDVB_Pointer->TransportStreamID >> 8); ++ I2c_Buffer[13] = (unsigned char)pDVB_Pointer->TransportStreamID; ++ I2c_Buffer[14] = (unsigned char)(pDVB_Pointer->ServiceID >> 8); ++ I2c_Buffer[15] = (unsigned char)pDVB_Pointer->ServiceID; ++ I2c_Buffer[16] = (unsigned char)(pDVB_Pointer->OriginalNetworkID >> 8); ++ I2c_Buffer[17] = (unsigned char)pDVB_Pointer->OriginalNetworkID; ++ } ++ /*other cases, Buffer are empty*/ ++ else ++ { ++ I2c_Buffer[12] = 0xFF; ++ I2c_Buffer[13] = 0xFF; ++ I2c_Buffer[14] = 0xFF; ++ I2c_Buffer[15] = 0xFF; ++ I2c_Buffer[16] = 0xFF; ++ I2c_Buffer[17] = 0xFF; ++ } ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,18); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecClearExternalTimerWithExternalPlug( ) ++ \brief This message is used to clear a digital timer block of a device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param UInt8 DayOfMonth \n ++ Day of the month.\n ++ ++ \param UInt8 MonthOfYear \n ++ Month of the year.\n ++ ++ \param UInt16 StartTime \n ++ Start time for a timer based recording.\n ++ ++ \param UInt16 Duration \n ++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n ++ ++ \param UInt8 Recording Sequence \n ++ Indicates if recording is repeated and, if so, on which day ++ For repeated recording the recording sequence value is the ++ bitwise OR of the days when recordings are required ++ Shall be set to 0x00 when recording is not repeated.\n ++ ++ \param tmdlHdmiCECExternalPlug_t ExternalPlug \n ++ indicates external plug number (1 to 255 )on the recording device.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecClearExternalTimerWithExternalPlug ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 DayOfMonth, ++ UInt8 MonthOfYear, ++ UInt16 StartTime, ++ tmdlHdmiCECDuration_t *pDuration, ++ UInt8 RecordingSequence, ++ tmdlHdmiCECExternalPlug_t ExternalPlug ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[13] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ // RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Clear External Timer with External Plug Command*/ ++ I2c_Buffer[0] = 0x0D; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_CLEAR_EXTERNAL_TIMER ; ++ I2c_Buffer[4] = DayOfMonth; /*Day of Month*/ ++ I2c_Buffer[5] = MonthOfYear; /*Month of Year*/ ++ I2c_Buffer[6] = (unsigned char)(StartTime >> 8); /*Start Time*/ ++ I2c_Buffer[7] = (unsigned char)StartTime; ++ I2c_Buffer[8] = pDuration -> Hours; /*Duration Hours*/ ++ I2c_Buffer[9] = pDuration -> Minute; /*Duration minute*/ ++ I2c_Buffer[10] = RecordingSequence; /*Recording Sequence*/ ++ I2c_Buffer[11] = CEC_EXTERNAL_PLUG; /*External Source Specifier = External Plug */ ++ I2c_Buffer[12] = ExternalPlug; /*External Plug*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,13); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecClearExternalTimerWithPhysicalAddress( ) ++ \brief This message is used to clear a digital timer block of a device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param UInt8 DayOfMonth \n ++ Day of the month.\n ++ ++ \param UInt8 MonthOfYear \n ++ Month of the year.\n ++ ++ \param UInt16 StartTime \n ++ Start time for a timer based recording.\n ++ ++ \param UInt16 Duration \n ++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n ++ ++ \param UInt8 Recording Sequence \n ++ Indicates if recording is repeated and, if so, on which day ++ For repeated recording the recording sequence value is the ++ bitwise OR of the days when recordings are required ++ Shall be set to 0x00 when recording is not repeated.\n ++ ++ \param tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress \n ++ Defines the path between the TV an a device-thus giving it a physical ++ address within the cluster.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecClearExternalTimerWithPhysicalAddress ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 DayOfMonth, ++ UInt8 MonthOfYear, ++ UInt16 StartTime, ++ tmdlHdmiCECDuration_t *pDuration, ++ UInt8 RecordingSequence, ++ tmdlHdmiCECExternalPhysicalAddress_t ExternalPhysicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[14] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ /* Clear External Timer with Physical Address Command */ ++ I2c_Buffer[0] = 0x0E; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_CLEAR_EXTERNAL_TIMER ; /*Clear External Timer*/ ++ I2c_Buffer[4] = DayOfMonth; /*Day of Month*/ ++ I2c_Buffer[5] = MonthOfYear; /*Month of Year*/ ++ I2c_Buffer[6] = (unsigned char)(StartTime >> 8); /*Start Time*/ ++ I2c_Buffer[7] = (unsigned char)StartTime; ++ I2c_Buffer[8] = pDuration -> Hours; /*Duration Hours*/ ++ I2c_Buffer[9] = pDuration -> Minute; /*Duration Minute*/ ++ I2c_Buffer[10] = RecordingSequence; /*Recording Sequence*/ ++ I2c_Buffer[11] = CEC_EXTERNAL_PHYSICAL_ADDRESS; /*External Source Specifier = External Address*/ ++ I2c_Buffer[12] = (unsigned char)(ExternalPhysicalAddress >> 8); /*External Address*/ ++ I2c_Buffer[13] = (unsigned char)ExternalPhysicalAddress; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,14); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecTextViewOn( ) ++ \brief This message as , but should also remove any text, ++ menus and PIP windows from the TV's display ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecTextViewOn ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to Instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if Instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ /* Text View On command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_TEXT_VIEW_ON ; /* Text View On */ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecTimerClearedStatus( ) ++ \brief This message is used to give the status of a , ++ or message. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECTimerClearedStatusData_t TimerClearedStatusData \n ++ Indicates if the timer was cleared successfully. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecTimerClearedStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECTimerClearedStatusData_t TimerClearedStatusData ++) ++{ ++ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ /* Timer Clear Status command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_TIMER_CLEARED_STATUS; /* System Audio Status*/ ++ I2c_Buffer[4] = TimerClearedStatusData; /* Timer Cleared Status*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecTimerStatus( ) ++ \brief This message is used to send timer status to the initiator of a ++ message. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECTimerStatusData_t *pTimerStatusData \n ++ Pointer on the Timer status. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecTimerStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECTimerStatusData_t *pTimerStatusData ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[7] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ tmdlHdmiCECTimerProgrammedInfo_t *pTimerProgInfo; ++ unsigned char Regval; ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Timer Status command */ ++ I2c_Buffer[0] = 0x07; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_TIMER_CLEARED_STATUS; /* System Audio Status*/ ++ /* First Byte Building */ ++ Regval = ((unsigned char)(pTimerStatusData->TimerOverlapWarning)& 0x01) << 7 ; // bit 7 for Timer Overlap Warning ++ Regval |= ((unsigned char)(pTimerStatusData->MediaInfo)& 0x03) << 5; // bit 6 to 5 for Media Info ++ ++ pTimerProgInfo = &(pTimerStatusData->TimerProgrammedInfo); ++ Regval |= ((unsigned char)(pTimerProgInfo->SelectProgramInfo)& 0x01)<< 4; // bit 4 for Timer Programed Indicator ++ Regval |= (unsigned char)(pTimerProgInfo->ProgramInfo)& 0x0F; // bit 3 to 0 for Program Information ++ I2c_Buffer[4] = Regval; ++ ++ /* 2 Duration Available Bytes Building */ ++ /* Duration Available is only filled in the the both following conditions*/ ++ if((pTimerProgInfo->SelectProgramInfo == CEC_PROGRAM_INDICATOR_NOT_PROGRAMMED)&&(pTimerProgInfo->ProgramInfo == CEC_PROGRAM_ERROR_INFO_DUPLICATE_ALREADY_PROGRAMMED)) ++ { ++ I2c_Buffer[5] = (unsigned char)(pTimerProgInfo->DurationAvailable >> 8); ++ I2c_Buffer[6] = (unsigned char)pTimerProgInfo->DurationAvailable; ++ } ++ else if((pTimerProgInfo->SelectProgramInfo == CEC_PROGRAM_INDICATOR_PROGRAMMED)&&(pTimerProgInfo->ProgramInfo == CEC_PROGRAM_INFO_NOT_ENOUGHT_SPACE_AVAILABLE_FOR_RECORDING)) ++ { ++ I2c_Buffer[5] = (unsigned char)(pTimerProgInfo->DurationAvailable >> 8); ++ I2c_Buffer[6] = (unsigned char)pTimerProgInfo->DurationAvailable; ++ } ++ /*Else, 2 bytes of Duration Available are filled with 0xFF*/ ++ else ++ { ++ I2c_Buffer[5] = 0xFF; ++ I2c_Buffer[6] = 0xFF; ++ } ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,7); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecTunerDeviceStatusAnalogue( ) ++ \brief This message is used by a tuner device to provide its status to the ++ initiator of the message. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECRecordingFlag_t RecordingFlag \n ++ Indicates if the tuner is being used as a source of a recording. \n ++ ++ \param tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo \n ++ Indicates if the the device is currently deplaying its tuner or not. \n ++ ++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n ++ "Cable,Sattellite,Terrestrial".\n ++ ++ \param UInt16 AnalogueFrequency \n ++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n ++ ++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n ++ Specify information about the colour system, the sound carrier and ++ the IF-frequency.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecTunerDeviceStatusAnalogue ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECRecordingFlag_t RecordingFlag, ++ tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo, ++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType, ++ UInt16 AnalogueFrequency, ++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem ++ ) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[9] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ unsigned char Regval; /*Local Variable*/ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Select Aanalogue Service command */ ++ I2c_Buffer[0] = 0x09; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_TUNER_DEVICE_STATUS ; /* Tuner Device Status*/ ++ /* Build First Byte*/ ++ Regval = ((unsigned char)RecordingFlag & 0X01)<< 7; /*bit 7 is Recording Flag */ ++ Regval |= (unsigned char)TunerDisplayInfo & 0X7F; /*bit 6 to 0 are Tuner display Info*/ ++ I2c_Buffer[4] = Regval; ++ ++ I2c_Buffer[5] = AnalogueBroadcastType; /*Analogue Broadcast System type*/ ++ I2c_Buffer[6] = (unsigned char)(AnalogueFrequency >> 8); /*Analogue Frequency*/ ++ I2c_Buffer[7] = (unsigned char)AnalogueFrequency; ++ I2c_Buffer[8] = BroadcastSystem; /*Broadcast System*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,9); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecTunerDeviceStatusDigital( ) ++ \brief This message is used by a tuner device to provide its status to the ++ initiator of the message. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECRecordingFlag_t RecordingFlag \n ++ Indicates if the tuner is being used as a source of a recording. \n ++ ++ \param tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo \n ++ Indicates if the the device is currently deplaying its tuner or not. \n ++ ++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n ++ Pointer to the structure Digital Service Identification ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecTunerDeviceStatusDigital ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECRecordingFlag_t RecordingFlag, ++ tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo, ++ ptmdlHdmiCECDigitalServiceIdentification_t pServiceIdentification ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[12] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ tmdlHdmiCECAribData_t *pARIB_Pointer; ++ tmdlHdmiCECAtscData_t *pATSC_Pointer; ++ tmdlHdmiCECDvbData_t *pDVB_Pointer; ++ ++ unsigned char Regval; /* Local variable*/ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Record On Digital Service command */ ++ I2c_Buffer[0] = 0x0C; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_TUNER_DEVICE_STATUS ; /* Tuner Device Status*/ ++ ++ /* Merge Recording Flag With Tuner Display Info*/ ++ Regval = ((unsigned char)RecordingFlag & 0X01)<< 7; /* bit 7 is Recording Flag*/ ++ Regval |= (unsigned char)TunerDisplayInfo & 0X7F; /* bit 6 to 0 are Tuner display Info*/ ++ I2c_Buffer[4] = Regval; ++ ++ /* Digital service Identification*/ ++ /*Merge Service Method and Digital Broadcast System in the same Byte*/ ++ Regval = (unsigned char)(pServiceIdentification->ServiceIdentificationMethod & 0x01) << 7; /* bit 7 is Service Method*/ ++ Regval |= (unsigned char)(pServiceIdentification->DigitalBroadcastSystem & 0x7F); /* bits 6 to 0 are Digital Broadcast*/ ++ I2c_Buffer[5] = Regval; ++ ++ /*Case of a ARIB Generic*/ ++ if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_GENERIC) ++ { ++ pARIB_Pointer = pServiceIdentification->pServiceIdentification; ++ ++ I2c_Buffer[6] = (unsigned char)(pARIB_Pointer->TransportStreamID >> 8); ++ I2c_Buffer[7] = (unsigned char)pARIB_Pointer->TransportStreamID; ++ I2c_Buffer[8] = (unsigned char)(pARIB_Pointer->ServiceID >> 8); ++ I2c_Buffer[9] = (unsigned char)pARIB_Pointer->ServiceID; ++ I2c_Buffer[10] = (unsigned char)(pARIB_Pointer->OriginalNetworkID >> 8); ++ I2c_Buffer[11] = (unsigned char)pARIB_Pointer->OriginalNetworkID; ++ } ++ /*Case of a ATSC Generic*/ ++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ATSC_GENERIC) ++ { ++ pATSC_Pointer = pServiceIdentification->pServiceIdentification; ++ ++ I2c_Buffer[6] = (unsigned char)(pATSC_Pointer->TransportStreamID >> 8); ++ I2c_Buffer[7] = (unsigned char)pATSC_Pointer->TransportStreamID; ++ I2c_Buffer[8] = (unsigned char)(pATSC_Pointer->ProgramNumber >> 8); ++ I2c_Buffer[9] = (unsigned char)pATSC_Pointer->ProgramNumber; ++ I2c_Buffer[10] = (unsigned char)(pATSC_Pointer->Reserved >> 8); ++ I2c_Buffer[11] = (unsigned char)pATSC_Pointer->Reserved; ++ } ++ /*Case of a DVB Generic*/ ++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_DVB_GENERIC) ++ { ++ pDVB_Pointer = pServiceIdentification->pServiceIdentification; ++ ++ I2c_Buffer[6] = (unsigned char)(pDVB_Pointer->TransportStreamID >> 8); ++ I2c_Buffer[7] = (unsigned char)pDVB_Pointer->TransportStreamID; ++ I2c_Buffer[8] = (unsigned char)(pDVB_Pointer->ServiceID >> 8); ++ I2c_Buffer[9] = (unsigned char)pDVB_Pointer->ServiceID; ++ I2c_Buffer[10] = (unsigned char)(pDVB_Pointer->OriginalNetworkID >> 8); ++ I2c_Buffer[11] = (unsigned char)pDVB_Pointer->OriginalNetworkID; ++ } ++ /*other cases, Buffer are empty*/ ++ else ++ { ++ I2c_Buffer[6] = 0xFF; ++ I2c_Buffer[7] = 0xFF; ++ I2c_Buffer[8] = 0xFF; ++ I2c_Buffer[9] = 0xFF; ++ I2c_Buffer[10] = 0xFF; ++ I2c_Buffer[11] = 0xFF; ++ } ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,12); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRequestActiveSource( ) ++ \brief This message is used by a new device to discover the status of ++ the system. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_Instance: the Instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRequestActiveSource ++( ++ tmInstance_t Instance ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* IRequest Active Source command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= 0x0F; /* Broadcast*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_REQUEST_ACTIVE_SOURCE ; /* Request Active Source */ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRoutingChange( ) ++ \brief This message is sent by a CEC switch when it is manually switched to ++ inform all other devices on the network that the active route below ++ the switch has changed. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt16 OriginalAddress \n ++ Previous address that the switch was switched to. \n ++ ++ \param UInt16 NewAddress \n ++ The new address it has been moved to. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRoutingChange ++( ++ tmInstance_t Instance, ++ UInt16 OriginalAddress, ++ UInt16 NewAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[8] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Routing Change command */ ++ I2c_Buffer[0] = 0x08; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= 0x0F; /* Broadcast*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_ROUTING_CHANGE ; /* Routing Change */ ++ I2c_Buffer[4] = (unsigned char)(OriginalAddress >> 8); /* MsByte of Original Address*/ ++ I2c_Buffer[5] = (unsigned char)OriginalAddress; /* LsByte of Original Address */ ++ I2c_Buffer[6] = (unsigned char)(NewAddress >> 8); /* MsByte of New Address */ ++ I2c_Buffer[7] = (unsigned char)NewAddress; /* LsByte of New Address */ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,8); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRoutingInformation( ) ++ \brief This message is sent by a CEC switch to indicate the active route ++ below the switch. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt16 PhysicalAddress \n ++ The current active route to the sink in the CEC switch. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRoutingInformation ++( ++ tmInstance_t Instance, ++ UInt16 PhysicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Routing Information command */ ++ I2c_Buffer[0] = 0x06; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= 0x0F; /* Broadcast*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_ROUTING_INFORMATION ; /* Routing Information */ ++ I2c_Buffer[4] = (unsigned char)(PhysicalAddress >> 8); /* MsByte of Physical Address*/ ++ I2c_Buffer[5] = (unsigned char)PhysicalAddress; /* LsByte of Physical Address */ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSelectAnalogueService( ) ++ \brief This message select directly an analogue TV Service. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n ++ "Cable,Sattellite,Terrestrial".\n ++ ++ \param UInt16 AnalogueFrequency \n ++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n ++ ++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n ++ Specify information about the colour system, the sound carrier and ++ the IF-frequency.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSelectAnalogueService ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType, ++ UInt16 AnalogueFrequency, ++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[8] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Select Aanalogue Service command */ ++ I2c_Buffer[0] = 0x08; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_SET_ANALOGUE_SERVICE ; /* Select Analogue Service*/ ++ I2c_Buffer[4] = AnalogueBroadcastType; ++ I2c_Buffer[5] = (unsigned char)(AnalogueFrequency >> 8); ++ I2c_Buffer[6] = (unsigned char)AnalogueFrequency; ++ I2c_Buffer[7] = BroadcastSystem; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,8); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSetStreamPath( ) ++ \brief This message is used by a TV to request a streaming path from ++ the specified physical address. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt16 PhysicalAddress \n ++ Physical address of the device.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetStreamPath ++( ++ tmInstance_t Instance, ++ UInt16 PhysicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Set Stream Path command */ ++ I2c_Buffer[0] = 0x06; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= 0x0F; /* Broadcast*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_SET_STREAM_PATH ; /* Set Stream Path */ ++ I2c_Buffer[4] = (unsigned char)(PhysicalAddress >> 8); /* MsByte of Physical Address*/ ++ I2c_Buffer[5] = (unsigned char)PhysicalAddress; /* LsByte of Physical Address */ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ //========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSetSystemAudioMode( ) ++ \brief This message turn the system audio Mode ON or OFF. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECSystemAudioStatus_t SystemAudioStatus \n ++ Specifies if the system audio mode is ON or OFF.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetSystemAudioMode ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECSystemAudioStatus_t SystemAudioStatus ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Set System Audio Mode Command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_SET_SYSTEM_AUDIO_MODE ; /* Set System Audio Mode*/ ++ I2c_Buffer[4] = SystemAudioStatus; /*System Audio Status*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSetTimerProgramTitle( ) ++ \brief This message is used to set the name of a program associated ++ with a timer block.Sent directly after sending a ++ or message. The name ++ is then associated with that timer block. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param const char *pProgramTitleString \n ++ Pointer on the program title. \n ++ ++ \param UInt8 ProgramTitleLength \n ++ Length of Program Title String. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetTimerProgramTitle ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ const char *pProgramTitleString, ++ UInt8 ProgramTitleLength ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[19] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ unsigned char loci; /* Local increment variable*/ ++ unsigned char MessLength; /* Local Message length*/ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ /* Set Timer Program Title */ ++ MessLength = ProgramTitleLength+4; /* Calculate Message length*/ ++ ++ I2c_Buffer[0] = (unsigned char)MessLength; ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_SET_TIMER_PROGRAM_TITLE ; /* Set Timer Program Title*/ ++ ++ for(loci = 0; loci <= ProgramTitleLength ; loci++) ++ { ++ I2c_Buffer[(loci+4)] = pProgramTitleString[loci]; /* Fill Table with Program Title characters*/ ++ } ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,(MessLength)); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecStandby( ) ++ \brief This message switches one or all devices into standby mode.Can be ++ be used as a broadcast message o be addressed to a specific device. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecStandby ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Standby command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_STANDBY ; /* Standby */ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSystemAudioModeRequest( ) ++ \brief A device implementing System Audio Control and which has volume ++ control RC button(eg TV or STB) request to use System Audio Mode ++ to the amplifier. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt16 PhysicalAddress \n ++ Physical address of the device.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSystemAudioModeRequest ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt16 PhysicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* System Audio Mode Request command */ ++ I2c_Buffer[0] = 0x06; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST ; /* System Audio Mode Request*/ ++ I2c_Buffer[4] = (unsigned char)(PhysicalAddress >> 8); /* MsByte of Physical Address */ ++ I2c_Buffer[5] = (unsigned char)PhysicalAddress; /* LsByte of Physical Address */ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSystemAudioModeStatus( ) ++ \brief Reports the current status of the System Audio Mode. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECSystemAudioStatus_t SystemAudioStatus \n ++ Current system audio mode.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSystemAudioModeStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECSystemAudioStatus_t SystemAudioStatus ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* System Audio Mode Status command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS ; /* System Audio Mode Status*/ ++ I2c_Buffer[4] = SystemAudioStatus; /* System Audio Status*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecGiveTunerDeviceStatus( ) ++ \brief This message is used to request the status of a tuner device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECStatusRequest_t StatusRequest \n ++ Allows the initiator to request the status once or on all future state ++ change. Or to cancel a previous ["On"] request. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGiveTunerDeviceStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECStatusRequest_t StatusRequest ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* System Audio Mode Request command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS ; /* Give Tuner Device Status*/ ++ I2c_Buffer[4] = (unsigned char)StatusRequest; /* Status Request */ ++ ++ errCode = setCecHwRegisters(pDis,E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRecordTvScreen( ) ++ \brief This message request by the recording device to record the presently ++ displayed source. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRecordTvScreen ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Record TV Sreen command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_RECORD_TV_SCREEN ; /* Record TV screen */ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecReportAudioStatus( ) ++ \brief This message report an amplifier's volume and mute. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param tmdlHdmiCECAudioStatus_t AudioStatus \n ++ Volume and mute status. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecReportAudioStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ ptmdlHdmiCECAudioStatus_t pAudioStatus ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ unsigned char Regval; /*Local Variable*/ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Report Audio Status command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_REPORT_AUDIO_STATUS ; /* Report Audio Statust*/ ++ Regval = (((unsigned char)pAudioStatus -> audioMuteStatus) & 0x01 )<< 7; /* bit 7 Mute Status*/ ++ Regval |= ((unsigned char)pAudioStatus -> audioVolumeStatus) & 0x7F; /* bit 6 to 0 Volum Status*/ ++ I2c_Buffer[4] = Regval; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecReportShortAudioDescriptor( ) ++ \brief This message Report Audio Capability. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param UInt32 ShortAudioDecriptor \n ++ Audio Descriptor. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecReportShortAudioDescriptor ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt32 ShortAudioDecriptor ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[7] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ /* Report Short Audio Decriptor */ ++ I2c_Buffer[0] = 0x07; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_REPORT_SHORT_AUDIO_DESCRIPTOR ; /* Report Audio Capability*/ ++ I2c_Buffer[4] = (unsigned char)(ShortAudioDecriptor >> 16); /* MSByte of ShortAudioDecriptor*/ ++ I2c_Buffer[5] = (unsigned char)(ShortAudioDecriptor >> 8); ++ I2c_Buffer[6] = (unsigned char)ShortAudioDecriptor; /* LSByte of ShortAudioDecriptor*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,7); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRequestShortAudioDescriptor( ) ++ \brief This message Request Audio Capability. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param UInt8 AudioFormatID \n ++ ++ \param UInt8 AudioFormatCode \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRequestShortAudioDescriptor ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 AudioFormatID, ++ UInt8 AudioFormatCode ++ ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ unsigned char Regval; /*Local Variable*/ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ /* Report Short Audio Decriptor */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_REQUEST_SHORT_AUDIO_DESCRIPTOR ; /* Request Audio Capability*/ ++ Regval = (((unsigned char)AudioFormatCode) & 0x3F )<< 2; /* bit 3 to 7 AudioFormatCode*/ ++ Regval |= ((unsigned char)AudioFormatID) & 0x03; /* bit 1 to 0 AudioFormatID*/ ++ I2c_Buffer[4] = Regval; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,7); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecIniateARC( ) ++ \brief This message Used by an ARC RX device to activate the ++ ARC functionality in an ARC TX device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecIniateARC ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ /* Report Short Audio Decriptor */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_INITATE_ARC ; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecReportArcInitiated( ) ++ \brief This message Used by an ARC TX device to indicate that ++ its ARC functionality has been activated ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecReportArcInitiated ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ /* Report Short Audio Decriptor */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_REPORT_ARC_INITIATED ; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecReportArcTerminated( ) ++ \brief This message Used by an ARC TX device to indicate that its ARC functionality ++ has been deactivated. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecReportArcTerminated ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ /* Report Short Audio Decriptor */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_REPORT_ARC_TERMINATED ; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRequestArcInitiation( ) ++ \brief This message Used by an ARC TX device to request an ARC RX device to ++ activate the ARC functionality in the ARC TX device. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRequestArcInitiation ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ /* Report Short Audio Decriptor */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_REPORT_ARC_INITIATION ; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRequestArcTerminiation( ) ++ \brief Used by an ARC TX device to request an ARC RX device to deactivate ++ the ARC functionality in the ARC TX device. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRequestArcTerminiation ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ /* Report Short Audio Decriptor */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_REPORT_ARC_TERMINATION ; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecTerminateARC( ) ++ \brief Used by an ARC TX device to request an ARC RX device to deactivate ++ the ARC functionality in the ARC TX device. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecTerminateARC ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ /* Report Short Audio Decriptor */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_TERMINATE_ARC ; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecGivePhysicalAddress( ) ++ \brief This message is a request to a device to return its physical Address ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGivePhysicalAddress ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Give physical Address command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_GIVE_PHYSICAL_ADDRESS ; /* Give Physical Address */ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecGiveSystemAudioModeStatus( ) ++ \brief This message request the status of the system audio mode ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGiveSystemAudioModeStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Give System Audio Mode Status command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS ; /* Give System Audio Mode Status*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecGetMenuLanguage( ) ++ \brief This message is sent by a device capable of character generation ++ (for OSD and Menus) to a TV in order to discover the currently selected ++ Menu Language. Also used by a TV during installation to dicover the ++ currently set menu language of other devices. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGetMenuLanguage ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Get Menu Language command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_GET_MENU_LANGUAGE ; /* Get Menu Address */ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecGiveAudioStatus( ) ++ \brief This message is requests an amplifier to send its volume and mute status ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGiveAudioStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Give Audio Mode Status command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_GIVE_AUDIO_STATUS ; /* Message Abort*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecPollingMessage( ) ++ \brief This message is used by any device for device discovery - similar to ++ ping in other protocols ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecPollingMessage ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[3] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Polling Message command */ ++ I2c_Buffer[0] = 0x03; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,3); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 1; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = 0; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRecordStatus( ) ++ \brief This message is used by a recording device to inform the initiator ++ of the message about its status. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param tmdlHdmiCECRecordStatusInfo_t RecordStatusInfo \n ++ The recording status of the device.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRecordStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECRecordStatusInfo_t RecordStatusInfo ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Record Status command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_RECORD_STATUS ; /* Record Status */ ++ I2c_Buffer[4] = RecordStatusInfo; /* Record Status */ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRecordOff( ) ++ \brief This message request a device to stop a recording ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRecordOff ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Record Off command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_RECORD_OFF ; /* Record Off */ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRecordOnAnalogueService( ) ++ \brief This message attempt to record analogue source ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n ++ "Cable,Sattellite,Terrestrial".\n ++ ++ \param UInt16 AnalogueFrequency \n ++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n ++ ++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n ++ Specify information about the colour system, the sound carrier and ++ the IF-frequency.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRecordOnAnalogueService ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType, ++ UInt16 AnalogueFrequency, ++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[9] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ /* Record On Analogue Device command */ ++ I2c_Buffer[0] = 0x09; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_RECORD_ON ; /*Record On*/ ++ ++ I2c_Buffer[4] = CEC_RECORD_SOURCE_ANALOGUE_SERVICE; /*RecordSourceType = CEC_RECORD_SOURCE_ANALOGUE_SERVICE*/ ++ I2c_Buffer[5] = AnalogueBroadcastType; /*Analogue Brodcast Type*/ ++ I2c_Buffer[6] = (unsigned char)(AnalogueFrequency >> 8); /*Analogue Frequency*/ ++ I2c_Buffer[7] = (unsigned char)AnalogueFrequency; ++ I2c_Buffer[8] = BroadcastSystem; /*Brodcast System*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,9); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRecordOnDigitalService( ) ++ \brief This message attempt to record digital source ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n ++ Pointer to the structure Digital Service Identification ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRecordOnDigitalService ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[12] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ tmdlHdmiCECAribData_t *pARIB_Pointer; ++ tmdlHdmiCECAtscData_t *pATSC_Pointer; ++ tmdlHdmiCECDvbData_t *pDVB_Pointer; ++ ++ unsigned char Regval; /* Local variable*/ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Record On Digital Service command */ ++ I2c_Buffer[0] = 0x0C; /* Param number = 10*/ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_RECORD_ON ; /* Record On Digital Service*/ ++ ++ I2c_Buffer[4] = CEC_RECORD_SOURCE_DIGITAL_SERVICE; /* RecordSourceType = CEC_RECORD_SOURCE_DIGITAL_SERVICE */ ++ ++ /* Digital Service Identification*/ ++ /*Merge Service Method and Digital Broadcast System in the same Byte*/ ++ Regval = (unsigned char)(pServiceIdentification->ServiceIdentificationMethod & 0x01); /*bit 7 is Service Method*/ ++ Regval = Regval << 7; ++ Regval |= (unsigned char)(pServiceIdentification->DigitalBroadcastSystem & 0x7F); /*bits 6 to 0 are Digital Broadcast*/ ++ I2c_Buffer[5] = Regval; ++ ++ /*Case of a ARIB Generic*/ ++ if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_GENERIC) ++ { ++ pARIB_Pointer = pServiceIdentification->pServiceIdentification; ++ ++ I2c_Buffer[6] = (unsigned char)(pARIB_Pointer->TransportStreamID >> 8); ++ I2c_Buffer[7] = (unsigned char)pARIB_Pointer->TransportStreamID; ++ I2c_Buffer[8] = (unsigned char)(pARIB_Pointer->ServiceID >> 8); ++ I2c_Buffer[9] = (unsigned char)pARIB_Pointer->ServiceID; ++ I2c_Buffer[10] = (unsigned char)(pARIB_Pointer->OriginalNetworkID >> 8); ++ I2c_Buffer[11] = (unsigned char)pARIB_Pointer->OriginalNetworkID; ++ } ++ /*Case of a ATSC Generic*/ ++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ATSC_GENERIC) ++ { ++ pATSC_Pointer = pServiceIdentification->pServiceIdentification; ++ ++ I2c_Buffer[6] = (unsigned char)(pATSC_Pointer->TransportStreamID >> 8); ++ I2c_Buffer[7] = (unsigned char)pATSC_Pointer->TransportStreamID; ++ I2c_Buffer[8] = (unsigned char)(pATSC_Pointer->ProgramNumber >> 8); ++ I2c_Buffer[9] = (unsigned char)pATSC_Pointer->ProgramNumber; ++ I2c_Buffer[10] = (unsigned char)(pATSC_Pointer->Reserved >> 8); ++ I2c_Buffer[11] = (unsigned char)pATSC_Pointer->Reserved; ++ } ++ /*Case of a DVB Generic*/ ++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_DVB_GENERIC) ++ { ++ pDVB_Pointer = pServiceIdentification->pServiceIdentification; ++ ++ I2c_Buffer[6] = (unsigned char)(pDVB_Pointer->TransportStreamID >> 8); ++ I2c_Buffer[7] = (unsigned char)pDVB_Pointer->TransportStreamID; ++ I2c_Buffer[8] = (unsigned char)(pDVB_Pointer->ServiceID >> 8); ++ I2c_Buffer[9] = (unsigned char)pDVB_Pointer->ServiceID; ++ I2c_Buffer[10] = (unsigned char)(pDVB_Pointer->OriginalNetworkID >> 8); ++ I2c_Buffer[11] = (unsigned char)pDVB_Pointer->OriginalNetworkID; ++ } ++ /*other cases, Buffer are empty*/ ++ else ++ { ++ I2c_Buffer[6] = 0xFF; ++ I2c_Buffer[7] = 0xFF; ++ I2c_Buffer[8] = 0xFF; ++ I2c_Buffer[9] = 0xFF; ++ I2c_Buffer[10] = 0xFF; ++ I2c_Buffer[11] = 0xFF; ++ } ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,12); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRecordOnExternalPhysicalAddress( ) ++ \brief This message attempt to record an external physical address source ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress \n ++ Defines the path between the TV an a device-thus giving it a physical ++ address within the cluster.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRecordOnExternalPhysicalAddress ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECExternalPhysicalAddress_t ExternalPhysicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[7] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Record On External Physial Address command */ ++ I2c_Buffer[0] = 0x07; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_RECORD_ON ; /*Record On*/ ++ I2c_Buffer[4] = CEC_RECORD_SOURCE_EXTERNAL_PHYSICAL_ADDRESS; /*RecordSourceType = CEC_RECORD_SOURCE_EXTERNAL_PHYSICAL_ADDRESS*/ ++ I2c_Buffer[5] = (unsigned char)(ExternalPhysicalAddress >> 8); /*External Physical Address*/ ++ I2c_Buffer[6] = (unsigned char)ExternalPhysicalAddress; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,7); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRecordOnExternalPlug( ) ++ \brief This message attempt to record an external plug source ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param tmdlHdmiCECExternalPlug_t ExternalPlug \n ++ indicates external plug number (1 to 255 )on the recording device.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRecordOnExternalPlug ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECExternalPlug_t ExternalPlug ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Record On External Plug command */ ++ I2c_Buffer[0] = 0x06; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_RECORD_ON ; /* Record On*/ ++ ++ I2c_Buffer[4] = CEC_RECORD_SOURCE_EXTERNAL_PLUG; /* RecordSourceType = CEC_RECORD_SOURCE_EXTERNAL_PLUG*/ ++ I2c_Buffer[5] = ExternalPlug; /*External Plug*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecRecordOnOwnSource( ) ++ \brief This message attempt to record an external plug source ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecRecordOnOwnSource ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Record On Own Source command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_RECORD_ON ; /* Record On*/ ++ ++ I2c_Buffer[4] = CEC_RECORD_SOURCE_OWN_SOURCE; /* RecordSourceType = CEC_RECORD_SOURCE_OWN_SOURCE*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecReportPhysicalAddress( ) ++ \brief This message is used to inform all other devices of the mapping ++ between physical and logical address of the initiator. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt16 PhysicalAddress \n ++ Device physical address within the cluster. \n ++ ++ \param tmdlHdmiCECDeviceType_t DeviceType \n ++ Type of the device (TV, Playback, tuner,...). \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecReportPhysicalAddress ++( ++ tmInstance_t Instance, ++ UInt16 PhysicalAddress, ++ tmdlHdmiCECDeviceType_t DeviceType ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[7] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Report Physical Address command */ ++ I2c_Buffer[0] = 0x07; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= 0x0F; /* Broadcast*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_REPORT_PHYSICAL_ADDRESS ; /* Report Physical Address */ ++ I2c_Buffer[4] = (unsigned char)(PhysicalAddress >> 8); /* MsByte of Physical Address*/ ++ I2c_Buffer[5] = (unsigned char)PhysicalAddress; /* LsByte of Physical Address */ ++ ++ I2c_Buffer[6] = DeviceType ; /* Device Type*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,7); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSetMenuLanguage( ) ++ \brief This message is used by a TV or another device to indicate the menu ++ Language. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param const char *pLanguage \n ++ Pointer on the user's menu language choice. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetMenuLanguage ++( ++ tmInstance_t Instance, ++ const char *pLanguage ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[7] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ // RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Set Menu Language command */ ++ I2c_Buffer[0] = 0x07; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= 0x0F; /* Broadcast*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_SET_MENU_LANGUAGE ; /* Set Menu Language*/ ++ I2c_Buffer[4] = pLanguage[0]; /* First Tocken*/ ++ I2c_Buffer[5] = pLanguage[1]; ++ I2c_Buffer[6] = pLanguage[2]; /* Last Tocken*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,7); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecDeckControl() ++ \brief This message is used to conrol a device's media functions ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECDecControlMode_t DeckControlMode \n ++ Used in message \n ++ ++ \note The "Skip Forward / Wind" and "Skip Reverse / Rewind" values are ++ used for example in a DVD as next xhapter and previous chapter and ++ in a VCR as wind and rewind. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecDeckControl ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECDecControlMode_t DeckControlMode ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if Instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to Instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if Instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Deck Control command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_DESCK_CONTROL; /* Deck Control Mode*/ ++ I2c_Buffer[4] = DeckControlMode; /* Deck Control Value*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecDeckStatus() ++ \brief This message is used to provide a deck's status to the initiator ++ of the message ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECDecInfo_t DeckInfo \n ++ Information on the device's current status \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecDeckStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECDecInfo_t DeckInfo ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Deck Status command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_DECK_STATUS; /* Deck Status*/ ++ I2c_Buffer[4] = DeckInfo; /* Deck Status Mode Information*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecGiveDeckStatus( ) ++ \brief This message is used to request the status of a device regardless ++ of whether or not it is the current active source. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECStatusRequest_t StatusRequest \n ++ Allows the initiator to request the status once or on all future state ++ change. Or to cancel a previous ["On"] request. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGiveDeckStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECStatusRequest_t StatusRequest ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if Instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Give Deck Status command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_GIVE_DECK_STATUS; /* Give Deck Status*/ ++ I2c_Buffer[4] = StatusRequest; /* Deck Status Request Information*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecPlay( ) ++ \brief This message is used to control the playback behaviour of a source ++ device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECPlayMode_t PlayMode \n ++ In which mode to play media. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecPlay ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECPlayMode_t PlayMode ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Play command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_PLAY; /* Play*/ ++ I2c_Buffer[4] = (unsigned char)PlayMode; /* Play Mode Information Information*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSelectDigitalService( ) ++ \brief This message select directly a digital TV, Radio or Data Broadcast ++ Service. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n ++ Pointer to the structure Digital Service Identification ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSelectDigitalService ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ ptmdlHdmiCECDigitalServiceIdentification_t pServiceIdentification ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[11] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ tmdlHdmiCECAribData_t *pARIB_Pointer; ++ tmdlHdmiCECAtscData_t *pATSC_Pointer; ++ tmdlHdmiCECDvbData_t *pDVB_Pointer; ++ ++ unsigned char Regval; /*Local Variable*/ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Select Digital Service command */ ++ I2c_Buffer[0] = 0x0B; /* Param number = 10*/ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_SET_DIGITAL_SERVICE ; /* Select Digital Service*/ ++ ++ /*Merge Service Method and Digital Broadcast System in the same Byte*/ ++ Regval = (unsigned char)(pServiceIdentification->ServiceIdentificationMethod & 0x01); /* Load the 1 bit of Service Method*/ ++ Regval = Regval << 7; ++ Regval |= (unsigned char)(pServiceIdentification->DigitalBroadcastSystem & 0x7F); /*Merge with the 7 bits of Digital Broadcast*/ ++ I2c_Buffer[4] = Regval; ++ ++ /*Case of a ARIB Generic*/ ++ if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_GENERIC) ++ { ++ pARIB_Pointer = pServiceIdentification->pServiceIdentification; ++ ++ I2c_Buffer[5] = (unsigned char)(pARIB_Pointer->TransportStreamID >> 8); /* Service Identification */ ++ I2c_Buffer[6] = (unsigned char)pARIB_Pointer->TransportStreamID; ++ I2c_Buffer[7] = (unsigned char)(pARIB_Pointer->ServiceID >> 8); ++ I2c_Buffer[8] = (unsigned char)pARIB_Pointer->ServiceID; ++ I2c_Buffer[9] = (unsigned char)(pARIB_Pointer->OriginalNetworkID >> 8); ++ I2c_Buffer[10] = (unsigned char)pARIB_Pointer->OriginalNetworkID; ++ } ++ /*Case of a ATSC Generic*/ ++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ATSC_GENERIC) ++ { ++ pATSC_Pointer = pServiceIdentification->pServiceIdentification; ++ ++ I2c_Buffer[5] = (unsigned char)(pATSC_Pointer->TransportStreamID >> 8); /* Service Identification */ ++ I2c_Buffer[6] = (unsigned char)pATSC_Pointer->TransportStreamID; ++ I2c_Buffer[7] = (unsigned char)(pATSC_Pointer->ProgramNumber >> 8); ++ I2c_Buffer[8] = (unsigned char)pATSC_Pointer->ProgramNumber; ++ I2c_Buffer[9] = (unsigned char)(pATSC_Pointer->Reserved >> 8); ++ I2c_Buffer[10] = (unsigned char)pATSC_Pointer->Reserved; ++ } ++ /*Case of a DVB Generic*/ ++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_DVB_GENERIC) ++ { ++ pDVB_Pointer = pServiceIdentification->pServiceIdentification; ++ ++ I2c_Buffer[5] = (unsigned char)(pDVB_Pointer->TransportStreamID >> 8); /* Service Identification */ ++ I2c_Buffer[6] = (unsigned char)pDVB_Pointer->TransportStreamID; ++ I2c_Buffer[7] = (unsigned char)(pDVB_Pointer->ServiceID >> 8); ++ I2c_Buffer[8] = (unsigned char)pDVB_Pointer->ServiceID; ++ I2c_Buffer[9] = (unsigned char)(pDVB_Pointer->OriginalNetworkID >> 8); ++ I2c_Buffer[10] = (unsigned char)pDVB_Pointer->OriginalNetworkID; ++ } ++ /*other cases, Buffer are empty*/ ++ else ++ { ++ I2c_Buffer[5] = 0xFF; /* Service Identification */ ++ I2c_Buffer[6] = 0xFF; ++ I2c_Buffer[7] = 0xFF; ++ I2c_Buffer[8] = 0xFF; ++ I2c_Buffer[9] = 0xFF; ++ I2c_Buffer[10] = 0xFF; ++ } ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,11); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSetAnalogueTimer( ) ++ \brief This message is used to set asingle timer block on an analogue ++ recording device. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param UInt8 DayOfMonth \n ++ Day of the month.\n ++ ++ \param UInt8 MonthOfYear \n ++ Month of the year.\n ++ ++ \param UInt16 StartTime \n ++ Start time for a timer based recording.\n ++ ++ \param UInt16 Duration \n ++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n ++ ++ \param UInt8 Recording Sequence \n ++ Indicates if recording is repeated and, if so, on which day ++ For repeated recording the recording sequence value is the ++ bitwise OR of the days when recordings are required ++ Shall be set to 0x00 when recording is not repeated.\n ++ ++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n ++ "Cable,Sattellite,Terrestrial".\n ++ ++ \param UInt16 AnalogueFrequency \n ++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n ++ ++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n ++ Specify information about the colour system, the sound carrier and ++ the IF-frequency.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetAnalogueTimer ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 DayOfMonth, ++ UInt8 MonthOfYear, ++ UInt16 StartTime, ++ tmdlHdmiCECDuration_t *pDuration, ++ UInt8 RecordingSequence, ++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType, ++ UInt16 AnalogueFrequency, ++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[15] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Set Analogue Timer command */ ++ I2c_Buffer[0] = 0x0F; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_SET_ANALOGUE_TIMER ; /* Message Abort*/ ++ I2c_Buffer[4] = DayOfMonth; ++ I2c_Buffer[5] = MonthOfYear; ++ I2c_Buffer[6] = (unsigned char)(StartTime >> 8); ++ I2c_Buffer[7] = (unsigned char)StartTime; ++ I2c_Buffer[8] = pDuration -> Hours; ++ I2c_Buffer[9] = pDuration -> Minute; ++ I2c_Buffer[10] = RecordingSequence; ++ I2c_Buffer[11] = AnalogueBroadcastType; ++ I2c_Buffer[12] = (unsigned char)(AnalogueFrequency >> 8); ++ I2c_Buffer[13] = (unsigned char)AnalogueFrequency; ++ I2c_Buffer[14] = BroadcastSystem; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,15); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSetAudioRate( ) ++ \brief This message is used to control audio rate from Source device. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECAudioRate_t AudioRate \n ++ The audio rate requested. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetAudioRate ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECAudioRate_t AudioRate ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Set Audio Rate command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_SET_AUDIO_RATE ; /* Set Audio Rate */ ++ I2c_Buffer[4] = AudioRate; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSetDigitalTimer( ) ++ \brief This message is used to set a digital timer block on a digital ++ recording device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress \n ++ Address of message receiver. \n ++ ++ \param UInt8 DayOfMonth \n ++ Day of the month.\n ++ ++ \param UInt8 MonthOfYear \n ++ Month of the year.\n ++ ++ \param UInt16 StartTime \n ++ Start time for a timer based recording.\n ++ ++ \param UInt16 Duration \n ++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n ++ ++ \param UInt8 Recording Sequence \n ++ Indicates if recording is repeated and, if so, on which day ++ For repeated recording the recording sequence value is the ++ bitwise OR of the days when recordings are required ++ Shall be set to 0x00 when recording is not repeated.\n ++ ++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n ++ Pointer to the structure Digital Service Identification ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetDigitalTimer ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 DayOfMonth, ++ UInt8 MonthOfYear, ++ UInt16 StartTime, ++ tmdlHdmiCECDuration_t *pDuration, ++ UInt8 RecordingSequence, ++ tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[18] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ tmdlHdmiCECAribData_t *pARIB_Pointer; ++ tmdlHdmiCECAtscData_t *pATSC_Pointer; ++ tmdlHdmiCECDvbData_t *pDVB_Pointer; ++ ++ unsigned char Regval; /* Local variable*/ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Set Digital Timer command */ ++ I2c_Buffer[0] = 0x12; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_SET_DIGITAL_TIMER ; /* Set Digital Timer*/ ++ I2c_Buffer[4] = DayOfMonth; /* Day of Month*/ ++ I2c_Buffer[5] = MonthOfYear; /* Month of Year*/ ++ I2c_Buffer[6] = (unsigned char)(StartTime >> 8); /* Start Time*/ ++ I2c_Buffer[7] = (unsigned char)StartTime; ++ I2c_Buffer[8] = pDuration -> Hours; /* Duration Hours*/ ++ I2c_Buffer[9] = pDuration -> Minute; /* Duration Minute*/ ++ I2c_Buffer[10] = RecordingSequence; /*Recording Sequence*/ ++ ++ /* Digital service Identification*/ ++ /*Merge Service Method and Digital Broadcast System in the same Byte*/ ++ Regval = (unsigned char)(pServiceIdentification->ServiceIdentificationMethod & 0x01); /*bit 7 is Service Method*/ ++ Regval = Regval << 7; ++ Regval |= (unsigned char)(pServiceIdentification->DigitalBroadcastSystem & 0x7F); /*bits 6 to 0 are Digital Broadcast*/ ++ I2c_Buffer[11] = Regval; ++ ++ /*Case of a ARIB Generic*/ ++ if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_GENERIC) ++ { ++ pARIB_Pointer = pServiceIdentification->pServiceIdentification; ++ ++ I2c_Buffer[12] = (unsigned char)(pARIB_Pointer->TransportStreamID >> 8); ++ I2c_Buffer[13] = (unsigned char)pARIB_Pointer->TransportStreamID; ++ I2c_Buffer[14] = (unsigned char)(pARIB_Pointer->ServiceID >> 8); ++ I2c_Buffer[15] = (unsigned char)pARIB_Pointer->ServiceID; ++ I2c_Buffer[16] = (unsigned char)(pARIB_Pointer->OriginalNetworkID >> 8); ++ I2c_Buffer[17] = (unsigned char)pARIB_Pointer->OriginalNetworkID; ++ } ++ /*Case of a ATSC Generic*/ ++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ATSC_GENERIC) ++ { ++ pATSC_Pointer = pServiceIdentification->pServiceIdentification; ++ ++ I2c_Buffer[12] = (unsigned char)(pATSC_Pointer->TransportStreamID >> 8); ++ I2c_Buffer[13] = (unsigned char)pATSC_Pointer->TransportStreamID; ++ I2c_Buffer[14] = (unsigned char)(pATSC_Pointer->ProgramNumber >> 8); ++ I2c_Buffer[15] = (unsigned char)pATSC_Pointer->ProgramNumber; ++ I2c_Buffer[16] = (unsigned char)(pATSC_Pointer->Reserved >> 8); ++ I2c_Buffer[17] = (unsigned char)pATSC_Pointer->Reserved; ++ } ++ /*Case of a DVB Generic*/ ++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_DVB_GENERIC) ++ { ++ pDVB_Pointer = pServiceIdentification->pServiceIdentification; ++ ++ I2c_Buffer[12] = (unsigned char)(pDVB_Pointer->TransportStreamID >> 8); ++ I2c_Buffer[13] = (unsigned char)pDVB_Pointer->TransportStreamID; ++ I2c_Buffer[14] = (unsigned char)(pDVB_Pointer->ServiceID >> 8); ++ I2c_Buffer[15] = (unsigned char)pDVB_Pointer->ServiceID; ++ I2c_Buffer[16] = (unsigned char)(pDVB_Pointer->OriginalNetworkID >> 8); ++ I2c_Buffer[17] = (unsigned char)pDVB_Pointer->OriginalNetworkID; ++ } ++ /*other cases, Buffer are empty*/ ++ else ++ { ++ I2c_Buffer[12] = 0xFF; ++ I2c_Buffer[13] = 0xFF; ++ I2c_Buffer[14] = 0xFF; ++ I2c_Buffer[15] = 0xFF; ++ I2c_Buffer[16] = 0xFF; ++ I2c_Buffer[17] = 0xFF; ++ } ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,18); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSetExternalTimerWithExternalPlug( ) ++ \brief This message is used to set a single timer block to record from an ++ external device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 DayOfMonth \n ++ Day of the month.\n ++ ++ \param UInt8 MonthOfYear \n ++ Month of the year.\n ++ ++ \param UInt16 StartTime \n ++ Start time for a timer based recording.\n ++ ++ \param UInt16 Duration \n ++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n ++ ++ \param UInt8 Recording Sequence \n ++ Indicates if recording is repeated and, if so, on which day ++ For repeated recording the recording sequence value is the ++ bitwise OR of the days when recordings are required ++ Shall be set to 0x00 when recording is not repeated.\n ++ ++ \param tmdlHdmiCECExternalPlug_t ExternalPlug \n ++ indicates external plug number (1 to 255 )on the recording device.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetExternalTimerWithExternalPlug ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 DayOfMonth, ++ UInt8 MonthOfYear, ++ UInt16 StartTime, ++ tmdlHdmiCECDuration_t *pDuration, ++ UInt8 RecordingSequence, ++ tmdlHdmiCECExternalPlug_t ExternalPlug ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[13] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Set External Timer With External Plug command */ ++ I2c_Buffer[0] = 0x0D; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_SET_EXTERNAL_TIMER ; /*SetDigital Timer*/ ++ ++ I2c_Buffer[4] = DayOfMonth; /*Day of Month*/ ++ I2c_Buffer[5] = MonthOfYear; /*Month of Year*/ ++ I2c_Buffer[6] = (unsigned char)(StartTime >> 8); /*Start Time*/ ++ I2c_Buffer[7] = (unsigned char)StartTime; ++ I2c_Buffer[8] = pDuration -> Hours; /*Duration Hours*/ ++ I2c_Buffer[9] = pDuration -> Minute; /*Duration Minute*/ ++ I2c_Buffer[10] = RecordingSequence; /*Recording Sequence*/ ++ I2c_Buffer[11] = CEC_EXTERNAL_PLUG; /*External Source Specifier = External Plug */ ++ I2c_Buffer[12] = ExternalPlug; /*External Plug*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,13); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSetExternalTimerWithPhysicalAddress( ) ++ \brief This message is used to set a single timer block to record from an ++ external device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 DayOfMonth \n ++ Day of the month.\n ++ ++ \param UInt8 MonthOfYear \n ++ Month of the year.\n ++ ++ \param UInt16 StartTime \n ++ Start time for a timer based recording.\n ++ ++ \param UInt16 Duration \n ++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n ++ ++ \param UInt8 Recording Sequence \n ++ Indicates if recording is repeated and, if so, on which day ++ For repeated recording the recording sequence value is the ++ bitwise OR of the days when recordings are required ++ Shall be set to 0x00 when recording is not repeated.\n ++ ++ \param tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress \n ++ Defines the path between the TV an a device-thus giving it a physical ++ address within the cluster.\n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetExternalTimerWithPhysicalAddress ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 DayOfMonth, ++ UInt8 MonthOfYear, ++ UInt16 StartTime, ++ tmdlHdmiCECDuration_t *pDuration, ++ UInt8 RecordingSequence, ++ tmdlHdmiCECExternalPhysicalAddress_t ExternalPhysicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[14] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Set external Timer With External Physical Address command */ ++ I2c_Buffer[0] = 0x0E; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_SET_EXTERNAL_TIMER ; /* SetDigital Timer*/ ++ ++ I2c_Buffer[4] = DayOfMonth; /* Day of Month*/ ++ I2c_Buffer[5] = MonthOfYear; /* Month of Year*/ ++ I2c_Buffer[6] = (unsigned char)(StartTime >> 8); /* Start Time*/ ++ I2c_Buffer[7] = (unsigned char)StartTime; ++ I2c_Buffer[8] = pDuration -> Hours; /* Duration Hours*/ ++ I2c_Buffer[9] = pDuration -> Minute; /* Duration Minute*/ ++ I2c_Buffer[10] = RecordingSequence; /* Recording Sequence*/ ++ I2c_Buffer[11] = CEC_EXTERNAL_PHYSICAL_ADDRESS; /*External Source Specifier = External Address*/ ++ I2c_Buffer[12] = (unsigned char)(ExternalPhysicalAddress >> 8); /*External Address*/ ++ I2c_Buffer[13] = (unsigned char) ExternalPhysicalAddress; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,14); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecTunerStepDecrement( ) ++ \brief This message is used to tune to next lowest service in a tuner's ++ service list.Can be used for PIP. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecTunerStepDecrement ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Tuner Step Decrement command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_TUNER_STEP_DECREMENT ; /* Tuner Step Decrement*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecTunerStepIncrement( ) ++ \brief This message is used to tune to next highest service in a tuner's ++ service list.Can be used for PIP. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecTunerStepIncrement ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Tuner Step Increment command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_TUNER_STEP_INCREMENT ; /* Tuner Step Increment*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecDeviceVendorID() ++ \brief This message report the vendor ID of this device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt32 VendorID \n ++ Indentifier for a specific Vendor \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecDeviceVendorID ++( ++ tmInstance_t Instance, ++ UInt32 VendorID ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[7] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Device Vendor ID command */ ++ I2c_Buffer[0] = 0x07; /* Param number in case of Vendor ID is 32 Bytes*/ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= 0x0F; /* Broadcast*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_DEVICE_VENDOR_ID ; /* Device Vendor ID opcode = 0x87*/ ++ I2c_Buffer[4] = (unsigned char)(VendorID >> 16); /* MSByte of Vendor ID*/ ++ I2c_Buffer[5] = (unsigned char)(VendorID >> 8); ++ I2c_Buffer[6] = (unsigned char)VendorID; /* LSByte of Vendor ID*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,7); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecGiveDeviceVendorID( ) ++ \brief This message is request the vendor ID from a device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGiveDeviceVendorID ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Give Device Vendor ID command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_GIVE_DEVICE_VENDOR_ID ; /* Give Device Vendor*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecVendorCommand( ) ++ \brief This message is allows vendor specific commands to be sent between ++ two devices. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 *pVendorSpecificData \n ++ Pointer to the Vendor Specific datas ++ ++ \param UInt8 VendorSpecificDataLength \n ++ Length of VendorSpecificData. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecVendorCommand ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 *pVendorSpecificData, ++ UInt8 VendorSpecificDataLength ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[19] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ unsigned char loci; /* Local increment variable*/ ++ unsigned char MessLength; /* Local Message length*/ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Vendor Command command */ ++ MessLength = VendorSpecificDataLength + 4; /* Calculate Message length*/ ++ ++ I2c_Buffer[0] = MessLength; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_VENDOR_COMMAND ; /* Vendor Command*/ ++ ++ for(loci = 0; loci <= VendorSpecificDataLength ; loci++) ++ { ++ I2c_Buffer[(loci+7)] = pVendorSpecificData[loci]; /* Fill Table with vendorSpecific Data characters*/ ++ } ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,MessLength); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecVendorCommandWithID( ) ++ \brief This message is allows vendor specific commands to be sent between ++ two devices or broadcast. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt32 VendorID \n ++ Indentifier for a specific Vendor \n ++ ++ \param UInt8 *pVendorSpecificData \n ++ Pointer to the Vendor Specific datas ++ ++ \param UInt8 VendorSpecificDataLength \n ++ Length of VendorSpecificData. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecVendorCommandWithID ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt32 VendorID, ++ UInt8 *pVendorSpecificData, ++ UInt8 VendorSpecificDataLength ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[19] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ unsigned char loci; /* Local increment variable*/ ++ unsigned char MessLength; /* Local Message length*/ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Vendor Command With ID command */ ++ MessLength = VendorSpecificDataLength + 7; /* Calculate Message length*/ ++ ++ I2c_Buffer[0] = MessLength; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_VENDOR_COMMAND_WITH_ID ; /* Vendor Command*/ ++ I2c_Buffer[4] = (unsigned char)(VendorID >> 16); /* MSByte of Vendor ID*/ ++ I2c_Buffer[5] = (unsigned char)(VendorID >> 8); ++ I2c_Buffer[6] = (unsigned char)VendorID; /* LSByte of Vendor ID*/ ++ ++ for(loci = 0; loci <= VendorSpecificDataLength ; loci++) ++ { ++ I2c_Buffer[(loci+7)] = pVendorSpecificData[loci]; /* Fill Table with vendorSpecific Data characters*/ ++ } ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,MessLength); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecVendorRemoteButtonDown( ) ++ \brief This message indicates that a remote control button has been depressed. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 *pVendorSpecificRcCode \n ++ Pointer to the Vendor Specific remote control code. ++ its recommended t keep this to a minimum size. ++ The maximum length shall not exceed 14 data blocks to avoid saturating bus ++ ++ \param UInt8 VendorSpecificRcCodeLength \n ++ Length of VendorSpecificRcCode. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecVendorRemoteButtonDown ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 *pVendorSpecificRcCode, ++ UInt8 VendorSpecificRcCodeLength ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[19] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ unsigned char loci; /* Local increment variable*/ ++ unsigned char MessLength; /* Local Message length*/ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ /* Vendor Remote Button Down command */ ++ MessLength = VendorSpecificRcCodeLength + 4; /* Calculate Message length*/ ++ ++ I2c_Buffer[0] = MessLength; /* Message Length */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN ; /* Vendor Remote Button Down Opcode*/ ++ /*Vendor Specific RC code Parameter*/ ++ for(loci = 0; loci <= VendorSpecificRcCodeLength ; loci++) ++ { ++ I2c_Buffer[(loci+4)] = pVendorSpecificRcCode[loci]; /* Fill Table with Vendor Specific RC Code data*/ ++ } ++ /*Send message Via I2C*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,MessLength); ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecVendorRemoteButtonUp( ) ++ \brief This message indicates that a remote control button (the last button ++ pressed indicated by the message) has ++ been released. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecVendorRemoteButtonUp ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Vendor Remote Button Up command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP ; /* Vendor Remote Button Up*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSetOsdString( ) ++ \brief This message is used to send a test message to output on a TV. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECDisplayControl_t DisplayControl \n ++ Display timing. \n ++ ++ \param const char *pOsdString \n ++ Pointer on the Text to display. \n ++ ++ \param UInt8 OsdStringLength \n ++ Length of Osd String. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetOsdString ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECDisplayControl_t DisplayControl, ++ const char *pOsdString, ++ UInt8 OsdStringLength ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[19] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ unsigned char loci; /* Local increment variable*/ ++ unsigned char MessLength; /* Local Message length*/ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Set OSD String command */ ++ ++ MessLength = OsdStringLength+5; /* Calculate Message length*/ ++ ++ I2c_Buffer[0] = (unsigned char)MessLength; ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_SET_OSD_STRING ; /* Set Osd String*/ ++ I2c_Buffer[4] = DisplayControl; /*Display Control*/ ++ for(loci = 0; loci <= OsdStringLength ; loci++) ++ { ++ I2c_Buffer[(loci+5)] = pOsdString[loci]; /* Fill Table with OSD Name characters*/ ++ } ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,(MessLength)); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecGiveOsdName( ) ++ \brief This message is used to request preferred OSD name of a device ++ for use in menus associated with that device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGiveOsdName ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Give OSD Name command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_GIVE_OSD_NAME ; /* Give OSD Name*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSetOsdName( ) ++ \brief This message is used to set the preferred OSD name of a device ++ for use in manus associated with that device. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param const char *pOsdName \n ++ Pointer on the preferred name of the device. \n ++ ++ \param UInt8 OsdNameLength \n ++ Length of Osd Name String. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetOsdName ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ const char *pOsdName, ++ UInt8 OsdNameLength ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[19] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ unsigned char loci; /* Local increment variable*/ ++ unsigned char MessLength; /* Local Message length*/ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Set OSD Name command */ ++ ++ MessLength = OsdNameLength+4; /* Calculate Message length*/ ++ ++ I2c_Buffer[0] = (unsigned char)MessLength; ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_SET_OSD_NAME ; /* Set Osd Name*/ ++ for(loci = 0; loci <= OsdNameLength ; loci++) ++ { ++ I2c_Buffer[(loci+4)] = pOsdName[loci]; /* Fill Table with OSD Name characters*/ ++ } ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,(MessLength)); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecMenuRequest( ) ++ \brief This message request from the TV for a device to show/remove a ++ menu or to query if a device is currently showing a menu ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECMenuRequestType_t MenuRequestType \n ++ Indicates if the menu request is to activate or deactivate the ++ devices menu or simply query the devices menu status. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecMenuRequest ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECMenuRequestType_t MenuRequestType ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Menu Request command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_MENU_REQUEST ; /* Menu Request*/ ++ I2c_Buffer[4] = MenuRequestType; /*Menu Request Type */ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecMenuStatus( ) ++ \brief This message is used to indicate to the TV that the device is ++ showing/has removed a menu and requets the remote control keys to ++ be passed though ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECMenuState_t MenuState \n ++ Indicates if the device is in the 'Device Menu Active' state or ++ 'Device Menu Inactive' state. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecMenuStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECMenuState_t MenuState ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Menu Status command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_MENU_STATUS; /* Menu Status*/ ++ I2c_Buffer[4] = MenuState; /* Menu State*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecUserControlPressed( ) ++ \brief This message is used to indicate that the user pressed a remote button ++ or switched from one remote control button to another. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECUserRemoteControlCommand_t UICommand \n ++ Relevant UI command issued by user. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecUserControlPressed ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECUserRemoteControlCommand_t UICommand ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* User Control Pressed command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_USER_CONTROL_PRESSED; /* User Control pressed*/ ++ I2c_Buffer[4] = UICommand; /* UI Command*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecUserControlPressedPlay( ) ++ \brief This message is used to indicate that the user pressed a remote button ++ or switched from one remote control button to another. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECPlayMode_t PlayMode \n ++ In which mode to play media. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecUserControlPressedPlay ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECPlayMode_t PlayMode ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* User Control Presses Play command */ ++ I2c_Buffer[0] = 0x06; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_USER_CONTROL_PRESSED; /* User Control Pressed*/ ++ ++ I2c_Buffer[4] = CEC_REMOTE_BUTTON_PLAY_FUNCTION; /* UI Command = CEC_REMOTE_BUTTON_PLAY_FUNCTION */ ++ I2c_Buffer[5] = PlayMode; /* Play Mode*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecUserControlPressedSelectAudioInput( ) ++ \brief This message is used to indicate that the user pressed a remote button ++ or switched from one remote control button to another. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 SelectAudioInput \n ++ Number of the Audio Input (Audio input number between 1 and 255). \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecUserControlPressedSelectAudioInput ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 SelectAudioInput ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* User Control Pressed Select Audio Input command */ ++ I2c_Buffer[0] = 0x06; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_USER_CONTROL_PRESSED; /* User Control Pressed*/ ++ ++ I2c_Buffer[4] = CEC_REMOTE_BUTTON_SELECT_AUDIO_INPUT_FUNCTION; /* UI Command = CEC_REMOTE_BUTTON_SELECT_AUDIO_INPUT_FUNCTION*/ ++ I2c_Buffer[5] = SelectAudioInput; /* UI Function Select Audio mode*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecUserControlPressedSelectAVInput( ) ++ \brief This message is used to indicate that the user pressed a remote button ++ or switched from one remote control button to another. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 SelectAVInput \n ++ Number of the A/V Input (A/V input number between 1 and 255). \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecUserControlPressedSelectAVInput ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 SelectAVInput ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* User Control Pressed Select AV Input command */ ++ I2c_Buffer[0] = 0x06; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_USER_CONTROL_PRESSED; /* User Control Pressed*/ ++ ++ I2c_Buffer[4] = CEC_REMOTE_BUTTON_SELECT_AV_INPUT_FUNCTION; /* UI Command = CEC_REMOTE_BUTTON_SELECT_AV_INPUT_FUNCTION */ ++ I2c_Buffer[5] = SelectAVInput; /* UI Function Select A/V Input*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecUserControlPressedSelectMedia( ) ++ \brief This message is used to indicate that the user pressed a remote button ++ or switched from one remote control button to another. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 SelectMedia \n ++ Number of Media (Media number between 1 and 255). \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecUserControlPressedSelectMedia ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ UInt8 SelectMedia ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* User Control Pressed Select Media command */ ++ I2c_Buffer[0] = 0x06; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_USER_CONTROL_PRESSED; /* User Control Pressed*/ ++ ++ I2c_Buffer[4] = CEC_REMOTE_BUTTON_SELECT_MEDIA_FUNCTION; /* UI Command = CEC_REMOTE_BUTTON_SELECT_MEDIA_FUNCTION*/ ++ I2c_Buffer[5] = SelectMedia; /* UI Function Media*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecUserControlPressedTune( ) ++ \brief This message is used to indicate that the user pressed a remote button ++ or switched from one remote control button to another. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECChannelIdentifier_t *pChannelIdentifier \n ++ Pointer to the structure of Major and Minor Channel number ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecUserControlPressedTune ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECChannelIdentifier_t *pChannelIdentifier ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[10] ; /* I2C data buffer */ ++ UInt16 Regval16 ; /* Local variable used for conversion*/ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* User Control Pressed Tune command */ ++ I2c_Buffer[0] = 0x0A; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_USER_CONTROL_PRESSED; /* User Control Pressed Opcode*/ ++ ++ I2c_Buffer[4] = CEC_REMOTE_BUTTON_TUNE_FUNCTION; /* UI Command = CEC_REMOTE_BUTTON_TUNE_FUNCTION*/ ++ ++ /* Merge 6 bits of ChanNum with 10 bits of Major channel*/ ++ Regval16 = (UInt16)(pChannelIdentifier->ChanNumFormat & 0x003F); // Save the 6 lsbits ++ Regval16 = Regval16 << 10; ++ Regval16 |= (UInt16)(pChannelIdentifier->MajorChanNumber & 0x03FF); ++ ++ /* Load the 4 information bytes of Channel ID*/ ++ I2c_Buffer[5] = (unsigned char)(Regval16 >> 8); ++ I2c_Buffer[6] = (unsigned char)Regval16; ++ I2c_Buffer[7] = (unsigned char)(pChannelIdentifier->MinorChanNumber >> 8); ++ I2c_Buffer[8] = (unsigned char)pChannelIdentifier->MinorChanNumber; ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,9); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecUserControlReleased( ) ++ \brief This message is used to indicate that the user released a remote button ++ The last one indicated by the Message. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecUserControlReleased ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* User Control Released command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_USER_CONTROL_RELEASED ; /* User Control Released */ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecGiveDevicePowerStatus( ) ++ \brief This message is used to determine the current power status of a ++ target device ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGiveDevicePowerStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Give Device power Status Power Status command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_GIVE_DEVICE_POWER_STATUS ; /* Give Device Power Status */ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecReportPowerStatus( ) ++ \brief This message is used to inform a requesting device of the current ++ power status. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECPowerStatus_t PowerStatus \n ++ Current power status. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecReportPowerStatus ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECPowerStatus_t PowerStatus ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Report Power Status command */ ++ I2c_Buffer[0] = 0x05; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_REPORT_POWER_STATUS ; /* Report Power Status*/ ++ I2c_Buffer[4] = PowerStatus; /* Power Status*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecFeatureAbort() ++ \brief This message is used as a reponse to indicate that the device does ++ not support the requested message type, or that it cannot execute it ++ at the present time. ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param tmdlHdmiCECFeatureOpcode_t FeatureOpcode \n ++ Opcode of the aborted message. \n ++ ++ \param tmdlHdmiCECAbortReason_t AbortReason \n ++ The reason why message cannot respond. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecFeatureAbort ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress, ++ tmdlHdmiCECFeatureOpcode_t FeatureOpcode, ++ tmdlHdmiCECAbortReason_t AbortReason ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Feature Abort command */ ++ I2c_Buffer[0] = 0x06; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_FEATURE_ABORT ; /* Feature Abort*/ ++ I2c_Buffer[4] = FeatureOpcode; /* Feature Opcode*/ ++ I2c_Buffer[5] = AbortReason; /* Abort Reason*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecGetCecVersion( ) ++ \brief This message is used by a device to enquire which version of CEC ++ the target supports ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGetCecVersion ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* Get CEC Version command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_GET_CEC_VERSION ; /* Get CEC Version*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecAbortMessage( ) ++ \brief This message is reserved for testing purposes ++ ++ \param tmInstance_t Instance \n ++ Instance identifier. \n ++ ++ \param UInt8 ReceiverLogicalAddress\n ++ Address of message receiver. \n ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecAbortMessage ++( ++ tmInstance_t Instance, ++ UInt8 ReceiverLogicalAddress ++) ++{ ++ tmErrorCode_t errCode; ++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if instance state is correct */ ++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[Instance]; ++ ++ //======To do : make a prepare message function with parameter ++ /* CEC Abort Message command */ ++ I2c_Buffer[0] = 0x04; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/ ++ ++ I2c_Buffer[3] = CEC_OPCODE_ABORT_MESSAGE ; /* Message Abort*/ ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3]; ++ ++ return(TM_OK); ++} ++ ++//Non Functional function used to provide easy way to access register ++ ++//========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecGetRegister( ) ++ \brief Setup the instance with its configuration parameters. This function ++ allows basic instance configuration for CEC Stack Processor. ++ ++ \param instance Instance identifier. ++ \param pSetupInfo Pointer to the structure containing all setup parameters ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++unsigned char tmdlHdmiCecGetRegister ++( ++ tmInstance_t instance, ++ UInt32 offset ++) ++{ ++ tmErrorCode_t errCode; ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ unsigned char I2c_ReadBuffer[1]; ++ ++ ++ /* check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), 0xFF) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[instance].opened == False, 0xFF) ++ ++ /* Ckeck the state */ ++ //RETIF(UnitTable[instance].state != CEC_STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[instance]; ++ ++ errCode = getCecHwRegisters(pDis, (UInt8) offset,I2c_ReadBuffer,1); ++ RETIF(errCode != TM_OK, 0xff) ++ ++ return(I2c_ReadBuffer[0]); ++} ++ ++//QB 10 Jan ========================================================================== ++/*! ++ \fn tmErrorCode_t tmdlHdmiCecSetRegister( ) ++ \brief Setup the instance with its configuration parameters. This function ++ allows basic instance configuration for CEC Stack Processor. ++ ++ \param instance Instance identifier. ++ \param pSetupInfo Pointer to the structure containing all setup parameters ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetRegister ++( ++ tmInstance_t instance, ++ UInt32 offset, ++ UInt32 value ++) ++{ ++ tmErrorCode_t errCode; ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ ++ /* check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* Ckeck the state */ ++ //RETIF(UnitTable[instance].state != CEC_STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[instance]; ++ ++ errCode = setCecHwRegister(pDis, (UInt8) offset,(UInt8)value); ++ RETIF(errCode != TM_OK, errCode) ++ ++ return(TM_OK); ++} ++ ++ ++ ++//========================================================================== ++/*! ++ \brief Set the power state of an instance of the CEC device. ON ++ state corresponds to a fully supplied, up and running device. Other ++ modes correspond to the powerdown state of the device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ ++ \param instance Instance identifier. ++ \param powerState Power state to set. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSetPowerState ++( ++ tmInstance_t instance, ++ tmPowerState_t powerState ++) ++{ ++ tmErrorCode_t errCode = TM_OK; ++ ++#ifdef TMFL_TDA9989 ++ unsigned char I2c_ReadBuffer[1]; ++ ++ tmdlHdmiCecDriverConfigTable_t *pDis; ++ ++ pDis = >mdlHdmiCecDriverConfigTable[instance]; ++ ++ /* check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ if (powerState == tmPowerOn) { ++ ++ errCode = getCecHwRegisters(pDis, E_REG_ENAMODS,I2c_ReadBuffer,1); ++ RETIF(errCode != TM_OK, errCode) ++ ++ I2c_ReadBuffer[0] |= DEFAULT_ENAMODS; ++ ++ errCode = setCecHwRegister(pDis, E_REG_ENAMODS, I2c_ReadBuffer[0]); ++ RETIF(errCode != TM_OK, errCode) ++ ++ ++ } ++ else if (powerState == tmPowerStandby) { ++ ++ errCode = getCecHwRegisters(pDis, E_REG_ENAMODS,I2c_ReadBuffer,1); ++ RETIF(errCode != TM_OK, errCode) ++ ++ I2c_ReadBuffer[0] &= ~(DEFAULT_ENAMODS); ++ ++ errCode = setCecHwRegister(pDis, E_REG_ENAMODS, I2c_ReadBuffer[0]); ++ RETIF(errCode != TM_OK, errCode) ++ ++ UnitTable[instance].state = CEC_STATE_NOT_INITIALIZED; ++ ++ } ++ else { ++ return TMDL_ERR_DLHDMICEC_BAD_PARAMETER; ++ } ++ ++#endif /* TMFL_TDA9989 */ ++ ++ return errCode; ++} ++ ++ ++//========================================================================== ++/*! ++ \brief Get the power state of an instance of the CEC device. ON ++ state corresponds to a fully supplied, up and running device. Other ++ modes correspond to the powerdown state of the device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pPowerState Pointer to the power state. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecGetPowerState ++( ++ tmInstance_t instance, ++ tmPowerState_t *pPowerState ++) ++{ ++ tmErrorCode_t errCode = TM_OK; ++ ++#ifdef TMFL_TDA9989 ++ ++ unsigned char I2c_ReadBuffer[1]; ++ ++ tmdlHdmiCecDriverConfigTable_t *pDis; ++ ++ pDis = >mdlHdmiCecDriverConfigTable[instance]; ++ ++ ++ /* check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ if (pPowerState == NULL) return TMDL_ERR_DLHDMICEC_BAD_PARAMETER; ++ ++ ++ errCode = getCecHwRegisters(pDis, E_REG_ENAMODS,I2c_ReadBuffer,1); ++ RETIF(errCode != TM_OK, errCode) ++ ++ if ((I2c_ReadBuffer[0] & DEFAULT_ENAMODS) == DEFAULT_ENAMODS) { ++ *pPowerState = tmPowerOn; ++ } ++ else { ++ *pPowerState = tmPowerStandby; ++ } ++ ++ ++#endif /* TMFL_TDA9989 */ ++ ++ return errCode; ++ ++} ++ ++//========================================================================== ++/*! ++ \brief This function allow to send a generic CEC message ++ This function has to be used when CEC messages are construct in ++ the middleware ++ ++ \param instance Instance identifier. ++ ++ \param *pData Pointer to the CEC data buffer ++ ++ \param lenData Lenght of I2C data buffer ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++*/ ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecSendMessage( ++ ++ tmInstance_t instance, ++ UInt8 *pData, ++ UInt16 lenData ++) ++{ ++ ++ tmErrorCode_t errCode = TM_OK; ++ ++#ifdef TMFL_TDA9989 ++ ++ unsigned char I2c_Buffer[19] ; /* I2C data buffer */ ++ unsigned char Loci; /* Local increment variable*/ ++ unsigned char MessLength; /* Local Message length*/ ++ ++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */ ++ ++ /* check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* check if unit corresponding to instance is opened */ ++ RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED) ++ ++ /* check if CEC message is not too long */ ++ RETIF((lenData > 16), TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS) ++ ++ pDis = >mdlHdmiCecDriverConfigTable[instance]; ++ ++ /* Calculate Internal Message length*/ ++ MessLength = (lenData-1)+3; /* real data is less ReceiverLogical address */ ++ ++ I2c_Buffer[0] = MessLength; /* Param number */ ++ ++ I2c_Buffer[1] = 0x00; /* Request CEC data */ ++ ++ /*Build Initiator and Reciever Logical Address Byte*/ ++ I2c_Buffer[2] = (unsigned char)(UnitTable[instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/ ++ I2c_Buffer[2] = I2c_Buffer[2] << 4; ++ I2c_Buffer[2] |= pData[0] & 0x0F; ++ ++ for(Loci = 0; Loci <= lenData ; Loci++) ++ { ++ I2c_Buffer[(Loci+3)] = pData[(Loci+1)]; /* Fill Table with Data from middleware, Data begin at position 1*/ ++ } ++ ++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,MessLength); /* CEC Data register */ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Save Datas of the CEC message send */ ++ gtmdlHdmiCecDriverSaveMessage.AddressByte = pData[2]; ++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0; ++ gtmdlHdmiCecDriverSaveMessage.Opcode = pData[3]; ++ ++#endif /* TMFL_TDA9989 */ ++ ++ return errCode; ++ ++} ++ ++ ++ ++//========================================================================== ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecEnableCalibration(tmInstance_t instance,tmdlHdmiCecClockSource_t cecClockSource) ++{ ++ tmErrorCode_t errCode = TM_OK; ++ ++#ifdef TMFL_TDA9989 ++ ++ unsigned char I2c_ReadBuffer[1]; ++ tmdlHdmiCecDriverConfigTable_t *pDis; ++ ++ pDis = >mdlHdmiCecDriverConfigTable[instance]; ++ ++ /* check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* CLOCK SOURCE is FRO */ ++ if (cecClockSource == TMDL_HDMICEC_CLOCK_FRO) { ++ ++ ++ ++ /* cf PR1795 set desired frequency to 12 Mhz*/ ++ ++ tmdlHdmiCecSetRegister(instance, 0xF3, 0xC0); ++ ++ RETIF(errCode != TM_OK, errCode) ++ ++ tmdlHdmiCecSetRegister(instance, 0xF4, 0xD4); ++ ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* set calibration in automatic mode */ ++ errCode = getCecHwRegisters(pDis, E_REG_CEC_DES_FREQ2,I2c_ReadBuffer,1); ++ RETIF(errCode != TM_OK, errCode) ++ I2c_ReadBuffer[0] &= CEC_AUTOMATIC_CALIBRATION_MSK; ++ errCode = setCecHwRegister(pDis, E_REG_CEC_DES_FREQ2, I2c_ReadBuffer[0]); ++ RETIF(errCode != TM_OK, errCode) ++ ++ ++ /* select FRO clock mode, osc_freq shall be also set to one */ ++ I2c_ReadBuffer[0] = CEC_SELECT_FRO_CLOCK_SOURCE; ++ errCode = setCecHwRegister(pDis, E_REG_CEC_CLK, I2c_ReadBuffer[0]); ++ RETIF(errCode != TM_OK, errCode) ++ ++ ++ /* Enable cec_clk AND FRO */ ++ errCode = getCecHwRegisters(pDis, E_REG_ENAMODS,I2c_ReadBuffer,1); ++ RETIF(errCode != TM_OK, errCode) ++ I2c_ReadBuffer[0] |= CEC_ENABLE_CEC_CLK_MSK; ++ I2c_ReadBuffer[0] &= CEC_ENABLE_FRO_MSK; ++ errCode = setCecHwRegister(pDis, E_REG_ENAMODS, I2c_ReadBuffer[0]); ++ RETIF(errCode != TM_OK, errCode) ++ ++ /* Enable calibration */ ++ I2c_ReadBuffer[0] = CEC_ENABLE_CALIBRATION; ++ errCode = setCecHwRegister(pDis, E_REG_CEC_CAL_XOSC_CTRL1, I2c_ReadBuffer[0]); ++ RETIF(errCode != TM_OK, errCode) ++ ++ } /* CLOCK SOURCE is FRO */ ++ ++#endif /* TMFL_TDA9989 */ ++ ++ return errCode; ++} ++ ++ ++//========================================================================== ++//========================================================================== ++tmErrorCode_t tmdlHdmiCecDisableCalibration(tmInstance_t instance) ++{ ++ tmErrorCode_t errCode = TM_OK; ++ ++#ifdef TMFL_TDA9989 ++ ++ unsigned char I2c_ReadBuffer[1]; ++ tmdlHdmiCecDriverConfigTable_t *pDis; ++ ++ pDis = >mdlHdmiCecDriverConfigTable[instance]; ++ ++ /* check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE) ++ ++ /* Disable calibration */ ++ I2c_ReadBuffer[0] = CEC_DISABLE_CALIBRATION; ++ errCode = setCecHwRegister(pDis, E_REG_CEC_CAL_XOSC_CTRL1, I2c_ReadBuffer[0]); ++ RETIF(errCode != TM_OK, errCode) ++ ++#endif /* TMFL_TDA9989 */ ++ ++ return errCode; ++} ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.c b/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.c +new file mode 100755 +index 0000000..ed422d7 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.c +@@ -0,0 +1,280 @@ ++/** ++ * Copyright (C) 2006 Koninklijke Philips Electronics N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of Koninklijke Philips Electronics N.V. and is confidential in ++ * nature. Under no circumstances is this software to be exposed to or placed ++ * under an Open Source License of any type without the expressed written ++ * permission of Koninklijke Philips Electronics N.V. ++ * ++ * \file tmdlHdmiCEC_local.c ++ * ++ * \version $Revision: $ ++ * ++ * \date $Date: $ ++ * ++ * \brief dev lib driver component for the CEC messages ++ * ++ * \section refs Reference Documents ++ * \section info Change Information ++ * ++ * \verbatim ++ $History: tmdlHdmiCEC_local.c $ ++ * ++ \endverbatim ++ * ++*/ ++ ++/*============================================================================*/ ++/* FILE CONFIGURATION */ ++/*============================================================================*/ ++ ++/* Defining this symbol on the compiler command line excludes some API checks */ ++/* #define NO_RETIF_BADPARAM */ ++ ++/*============================================================================*/ ++/* STANDARD INCLUDE FILES */ ++/*============================================================================*/ ++ ++ ++/*============================================================================*/ ++/* PROJECT INCLUDE FILES */ ++/*============================================================================*/ ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++#include ++#else ++#include ++#endif ++#include "tmdlHdmiCEC.h" ++#include "tmdlHdmiCEC_local.h" ++ ++/*============================================================================*/ ++/* MACRO DEFINITIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* TYPE DEFINITIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* PUBLIC VARIABLE DEFINITIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* STATIC VARIABLE DECLARATIONS */ ++/*============================================================================*/ ++ ++/** ++ * Lookup table to map an 8-bit mask to a number of left shifts ++ * needed to shift a value starting at bit 0 onto the mask. ++ * Indexed by mask 0-255. For example, mask 0x00 and 0x01 need ++ * no shift, mask 0x02 needs one shift, mask 0x03 needs no shift, ++ * mask 0x04 needs 2 shifts, etc. ++ * Rows were formatted by "HDMI Driver - Register List.xls" and pasted here ++ */ ++static CONST_DAT UInt8 kMaskToShift[256] = ++{/* Mask index: */ ++ /*x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ ++ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x */ ++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 1x */ ++ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 2x */ ++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 3x */ ++ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 4x */ ++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 5x */ ++ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 6x */ ++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 7x */ ++ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 8x */ ++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 9x */ ++ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Ax */ ++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Bx */ ++ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Cx */ ++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Dx */ ++ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Ex */ ++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* Fx */ ++}; ++ ++/*============================================================================*/ ++/* STATIC FUNCTION DECLARATIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* PUBLIC FUNCTION DEFINITIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* getCecHwRegisters */ ++/*============================================================================*/ ++tmErrorCode_t ++getCecHwRegisters ++( ++ tmdlHdmiCecDriverConfigTable_t *pDis, ++ UInt8 regAddr, ++ UInt8 *pData, ++ UInt16 lenData ++ ) ++{ ++ tmErrorCode_t err; /* Error code */ ++ tmdlHdmiCecSysArgs_t sysArgs; /* Arguments passed to system function */ ++ ++ /* Get I2C register range - all non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->i2cAddress; ++ sysArgs.firstRegister = regAddr; ++ sysArgs.lenData = (UInt8)lenData; ++ sysArgs.pData = pData; ++ err = pDis->i2cReadFunction(&sysArgs); ++ return (err == TM_OK) ? TM_OK : TMDL_ERR_DLHDMICEC_I2C_READ; ++} ++ ++/*============================================================================*/ ++/* getCecHwRegister */ ++/*============================================================================*/ ++tmErrorCode_t ++getCecHwRegister ++( ++ tmdlHdmiCecDriverConfigTable_t *pDis, ++ UInt8 regAddr, ++ UInt8 *pRegValue ++) ++{ ++ tmErrorCode_t err; /* Error code */ ++ tmdlHdmiCecSysArgs_t sysArgs; /* Arguments passed to system function */ ++ ++ /* Get I2C register - all non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->i2cAddress; ++ sysArgs.firstRegister = regAddr; ++ sysArgs.lenData = 1; ++ sysArgs.pData = pRegValue; ++ err = pDis->i2cReadFunction(&sysArgs); ++ return (err == TM_OK) ? TM_OK : TMDL_ERR_DLHDMICEC_I2C_READ; ++ ++} ++ ++/*============================================================================*/ ++/* setCecHwRegisters */ ++/*============================================================================*/ ++tmErrorCode_t ++setCecHwRegisters ++( ++ tmdlHdmiCecDriverConfigTable_t *pDis, ++ UInt8 regAddr, ++ UInt8 *pData, ++ UInt16 lenData ++ ) ++{ ++ tmErrorCode_t err; /* Error code */ ++ tmdlHdmiCecSysArgs_t sysArgs; /* Arguments passed to system function */ ++ ++ /* Write to I2C register range - all non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->i2cAddress; ++ sysArgs.firstRegister = regAddr; ++ sysArgs.lenData = (UInt8)lenData; ++ sysArgs.pData = pData; ++ err = pDis->i2cWriteFunction(&sysArgs); ++ return (err == TM_OK) ? TM_OK : TMDL_ERR_DLHDMICEC_I2C_WRITE; ++} ++ ++/*============================================================================*/ ++/* setCecHwRegisterMsbLsb */ ++/*============================================================================*/ ++tmErrorCode_t ++setCecHwRegisterMsbLsb ++( ++ tmdlHdmiCecDriverConfigTable_t *pDis, ++ UInt8 regAddr, ++ UInt16 regWord ++) ++{ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 msbLsb[2]; /* The bytes from regWord */ ++ tmdlHdmiCecSysArgs_t sysArgs; /* Arguments passed to system function */ ++ ++ /* Unpack regWord bytes, MSB first */ ++ msbLsb[0] = (UInt8)(regWord >> 8); ++ msbLsb[1] = (UInt8)(regWord & 0xFF); ++ ++ /* Write to I2C - all non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->i2cAddress; ++ sysArgs.firstRegister = regAddr; ++ sysArgs.lenData = 2; ++ sysArgs.pData = &msbLsb[0]; ++ err = pDis->i2cWriteFunction(&sysArgs); ++ return (err == TM_OK) ? TM_OK : TMDL_ERR_DLHDMICEC_I2C_WRITE; ++} ++ ++/*============================================================================*/ ++/* setCecHwRegister */ ++/*============================================================================*/ ++tmErrorCode_t ++setCecHwRegister ++( ++ tmdlHdmiCecDriverConfigTable_t *pDis, ++ UInt8 regAddr, ++ UInt8 regValue ++) ++{ ++ tmErrorCode_t err; /* Error code */ ++ tmdlHdmiCecSysArgs_t sysArgs; /* Arguments passed to system function */ ++ ++ /* Write to I2C - all non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->i2cAddress; ++ sysArgs.firstRegister = regAddr; ++ sysArgs.lenData = 1; ++ sysArgs.pData = ®Value; ++ err = pDis->i2cWriteFunction(&sysArgs); ++ return (err == TM_OK) ? TM_OK : TMDL_ERR_DLHDMICEC_I2C_WRITE; ++} ++ ++/*============================================================================*/ ++/* setCecHwRegisterField */ ++/*============================================================================*/ ++tmErrorCode_t ++setCecHwRegisterField ++( ++ tmdlHdmiCecDriverConfigTable_t *pDis, ++ UInt8 regAddr, ++ UInt8 fieldMask, ++ UInt8 fieldValue ++) ++{ ++ tmErrorCode_t err; /* Error code */ ++ UInt8 regValue; /* The register's current value */ ++ tmdlHdmiCecSysArgs_t sysArgs; /* Arguments passed to system function */ ++ ++ /* Read I2C register value. ++ * All bitfield registers are either shadowed or can be read. ++ */ ++ sysArgs.slaveAddr = pDis->i2cAddress; ++ sysArgs.firstRegister = regAddr; ++ sysArgs.lenData = 1; ++ sysArgs.pData = ®Value; ++ err = pDis->i2cReadFunction(&sysArgs); ++ RETIF(err != TM_OK, TMDL_ERR_DLHDMICEC_I2C_READ) ++ ++ /* Reset register bits that are set in the mask */ ++ regValue = regValue & (UInt8)(~fieldMask); ++ ++ /* Shift the field value left to align its bits with the mask */ ++ fieldValue <<= kMaskToShift[fieldMask]; ++ ++ /* Reset shifted field bits that are not set in the mask */ ++ fieldValue &= fieldMask; ++ ++ /* Set the shifted bitfield */ ++ regValue |= fieldValue; ++ ++ /* Write to I2C - all non-OK results are errors */ ++ sysArgs.slaveAddr = pDis->i2cAddress; ++ sysArgs.firstRegister = regAddr; ++ sysArgs.lenData = 1; ++ sysArgs.pData = ®Value; ++ err = pDis->i2cWriteFunction(&sysArgs); ++ return (err == TM_OK) ? TM_OK : TMDL_ERR_DLHDMICEC_I2C_WRITE; ++} ++ ++ ++/*============================================================================*/ ++/* STATIC FUNCTION DEFINTIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.h b/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.h +new file mode 100755 +index 0000000..c0baa18 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.h +@@ -0,0 +1,221 @@ ++//============================================================================= ++// Copyright (C) 2007 NXP N.V., All Rights Reserved. ++// This source code and any compilation or derivative thereof is the proprietary ++// information of NXP N.V. and is confidential in nature. Under no circumstances ++// is this software to be exposed to or placed under an Open Source License of ++// any type without the expressed written permission of NXP N.V. ++//============================================================================= ++/*! ++ \file tmdlHdmiCEC_local.h ++ ++ \version 1.0 ++ ++ \date 24/07/2007 ++ ++ \brief devlib driver component API for the CEC messages. ++ ++ \section refs Reference Documents ++ TDA998X Driver - tmdlHdmiTx - SCS.doc ++ \note None. ++ ++ HISTORY : ++ \verbatim ++ Date Modified by CRPRNr TASKNr Maintenance description ++ -------------|-----------|-------|-------|----------------------------------- ++ 24/07/2007 | F.G | | | Creation. ++ -------------|-----------|-------|-------|----------------------------------- ++ \endverbatim ++*/ ++//========================================================================== ++ ++#ifndef TMDLHDMICEC_LOCAL_H ++#define TMDLHDMICEC_LOCAL_H ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++//#include "tmdlHdmiCEC_IW.h" ++#include "tmdlHdmiCEC_cfg.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*============================================================================*/ ++/* MACRO DEFINITIONS */ ++/*============================================================================*/ ++ ++/* Version of the SW driver */ ++#define VERSION_COMPATIBILITY 0 ++#define VERSION_MAJOR 1 ++#define VERSION_MINOR 4 ++ ++/** ++ * A macro to check a condition and if true return a result ++ */ ++#define RETIF(cond, rslt) if ((cond)){return (rslt);} ++ ++/** ++ * A macro to check a condition and if true return ++ * TMBSL_ERR_HDMI_BAD_PARAMETER. ++ * To save code space, it can be compiled out by defining NO_RETIF_BADPARAM on ++ * the compiler command line. ++ */ ++#ifdef NO_RETIF_BADPARAM ++#define RETIF_BADPARAM(cond) ++#else ++#define RETIF_BADPARAM(cond) if ((cond)){return TMBSL_ERR_HDMI_BAD_PARAMETER;} ++#endif ++ ++/** ++ * A macro to check the result of a register API and if not TM_OK to return it. ++ * To save code space, it can be compiled out by defining NO_RETIF_REG_FAIL on ++ * the compiler command line. ++ */ ++#ifdef NO_RETIF_REG_FAIL ++#define RETIF_REG_FAIL(result) ++#else ++#define RETIF_REG_FAIL(result) if ((result) != TM_OK){return (result);} ++#endif ++ ++#define TDA9950_RESET_DELAY_MS 250 ++ ++/*============================================================================*/ ++/* ENUM OR TYPE DEFINITIONS */ ++/*============================================================================*/ ++ ++#ifdef TMFL_TDA9989 ++ ++#define E_REG_ENAMODS 0xFF ++#define E_REG_CEC_CLK 0xF6 ++#define E_REG_CEC_INT 0xEE ++#define E_REG_COMBI_INT 0xEC ++#define DEFAULT_ENAMODS 0x81 ++#define CEC_CLK_SEL 0xE6 ++#define CEC_INT_MASK 0x01 ++ ++#define E_REG_CEC_CAL_XOSC_CTRL1 0xF2 ++#define E_REG_CEC_DES_FREQ2 0xF5 ++ ++ ++#define CEC_AUTOMATIC_CALIBRATION_MSK 0x7F ++#define CEC_SELECT_FRO_CLOCK_SOURCE 0x11 ++#define CEC_ENABLE_CEC_CLK_MSK 0x80 ++#define CEC_ENABLE_FRO_MSK 0xBF ++#define CEC_ENABLE_CALIBRATION 0x01 ++#define CEC_DISABLE_CALIBRATION 0x00 ++ ++ ++#endif /* TMFL_TDA9989 */ ++ ++/*! ++ \enum CEC Stack Processor Regsiters ++ \brief The CSP is controlled via a series of registers ++*/ ++ ++enum _eReg ++{ ++ E_REG_APR = 0x00, /*!< Address Pointer Regsiter (Write) */ ++ E_REG_CSR = 0x00, /*!< CSP Status Register (Read) */ ++ E_REG_CER = 0x01, /*!< CSP Error Register (Read) */ ++ E_REG_CVR = 0x02, /*!< CSP Version Register(Read) */ ++ E_REG_CCR = 0x03, /*!< CSP Control Register (Read/Write) */ ++ E_REG_ACKH = 0x04, /*!< CEC Address ACK High Register (Read/Write) */ ++ E_REG_ACKL = 0x05, /*!< CEC Address ACK Low Register (Read/Write) */ ++ E_REG_CCONR = 0x06, /*!< CEC Config Register (Read/Write) */ ++ E_REG_CDR0 = 0x07, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR1 = 0x08, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR2 = 0x09, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR3 = 0x0A, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR4 = 0x0B, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR5 = 0x0C, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR6 = 0x0D, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR7 = 0x0E, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR8 = 0x0F, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR9 = 0x10, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR10 = 0x11, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR11 = 0x12, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR12 = 0x13, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR13 = 0x14, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR14 = 0x15, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR15 = 0x16, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR16 = 0x17, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR17 = 0x18, /*!< CEC Data Register (Read/Write) */ ++ E_REG_CDR18 = 0x19 /*!< CEC Data Register (Read/Write) */ ++}; ++ ++ ++/* possible states of the state driver */ ++typedef enum ++{ ++ CEC_STATE_NOT_INITIALIZED, /**< Driver is not initialized */ ++ CEC_STATE_UNLOCKED , /**< Driver is not locked */ ++ CEC_STATE_LOCKED, /**< Driver is locked */ ++ CEC_STATE_CONFIGURED /**< Driver is configured */ ++} tmdlHdmiCecDriverState_t; ++ ++/** ++ * \brief The structure of a CEC object, one per device unit ++*/ ++typedef struct ++{ ++ tmInstance_t instance; ++ tmdlHdmiCECLogicalAddress_t DeviceLogicalAddress; ++ Bool opened; /**< is unit instanciated ? */ ++ tmdlHdmiCecDeviceVersion_t deviceVersion; /**< Version of the HW device */ ++ tmdlHdmiCecDriverState_t state; /**< Current state of the driver */ ++ ptmdlHdmiCecCallbackFunc_t MessageCallback; /**< Message callback */ ++}tmdlHdmiCecUnitConfig_t; ++ ++ ++/** ++ * \brief States of CEC Status ++*/ ++#define CEC_MSG_SUCCESS 0x00 /*Message transmisson Succeed*/ ++#define CEC_CSP_OFF_STATE 0x80 /*CSP in Off State*/ ++#define CEC_BAD_REQ_SERVICE 0x81 /*Bad .req service*/ ++#define CEC_MSG_FAIL_UNABLE_TO_ACCESS 0x82 /*Message transmisson failed: Unable to access CEC line*/ ++#define CEC_MSG_FAIL_ARBITRATION_ERROR 0x83 /*Message transmisson failed: Arbitration error*/ ++#define CEC_MSG_FAIL_BIT_TIMMING_ERROR 0x84 /*Message transmisson failed: Bit timming error*/ ++#define CEC_MSG_FAIL_DEST_NOT_ACK 0x85 /*Message transmisson failed: Destination Address not aknowledged*/ ++#define CEC_MSG_FAIL_DATA_NOT_ACK 0x86 /*Message transmisson failed: Databyte not acknowledged*/ ++ ++ ++/*============================================================================*/ ++/* EXTERN DATA DEFINITION */ ++/*============================================================================*/ ++ ++extern tmdlHdmiCecDriverConfigTable_t gtmdlHdmiCecDriverConfigTable[MAX_UNITS]; ++ ++/*============================================================================*/ ++/* EXTERN FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++ ++tmErrorCode_t getCecHwRegisters (tmdlHdmiCecDriverConfigTable_t *pDis, ++ UInt8 regAddr, ++ UInt8 *pData, UInt16 lenData); ++tmErrorCode_t getCecHwRegister (tmdlHdmiCecDriverConfigTable_t *pDis, ++ UInt8 regAddr, ++ UInt8 *pRegValue); ++tmErrorCode_t setCecHwRegisters (tmdlHdmiCecDriverConfigTable_t *pDis, ++ UInt8 regAddr, ++ UInt8 *pData, UInt16 lenData); ++tmErrorCode_t setCecHwRegisterMsbLsb (tmdlHdmiCecDriverConfigTable_t *pDis, ++ UInt8 regAddr, ++ UInt16 regWord); ++tmErrorCode_t setCecHwRegister (tmdlHdmiCecDriverConfigTable_t *pDis, ++ UInt8 regAddr, ++ UInt8 regValue); ++tmErrorCode_t setCecHwRegisterField (tmdlHdmiCecDriverConfigTable_t *pDis, ++ UInt8 regAddr, ++ UInt8 fieldMask, UInt8 fieldValue); ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMDLHDMI_CEC_LOCAL_H */ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c b/drivers/video/nxp/comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c +new file mode 100755 +index 0000000..aae2c10 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c +@@ -0,0 +1,570 @@ ++/** ++ * Copyright (C) 2009 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmdlHdmiTx_LinuxCfg.c ++ * ++ * \version Revision: 1 ++ * ++ * \date Date: 25/03/11 11:00 ++ * ++ * \brief devlib driver component API for the TDA998x HDMI Transmitters ++ * ++ * \section refs Reference Documents ++ * HDMI Tx Driver - FRS.doc, ++ * ++ * \section info Change Information ++ * ++ * \verbatim ++ ++ History: tmdlHdmiTx_LinuxCfg.c ++ * ++ * ***************** Version 2 ***************** ++ * User: V. Vrignaud Date: March 25th, 2011 ++ * ++ * ***************** Version 1 ***************** ++ * User: A. Lepine Date: October 1st, 2009 ++ * initial version ++ * ++ ++ \endverbatim ++ * ++*/ ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* MACRO */ ++/*============================================================================*/ ++/* macro for quick error handling */ ++#define RETIF(cond, rslt) if ((cond)){return (rslt);} ++#define I2C_M_WR 0 ++ ++/*============================================================================*/ ++/* STATIC FUNCTION DECLARATIONS */ ++/*============================================================================*/ ++tmErrorCode_t TxI2cReadFunction(tmbslHdmiTxSysArgs_t *pSysArgs); ++tmErrorCode_t TxI2cWriteFunction(tmbslHdmiTxSysArgs_t *pSysArgs); ++ ++/****************************************************************************** ++ ****************************************************************************** ++ * THIS PART CAN BE MODIFIED BY CUSTOMER * ++ ****************************************************************************** ++ *****************************************************************************/ ++struct i2c_client *GetThisI2cClient(void); ++unsigned char my_i2c_data[255]; ++ ++/* The following includes are used by I2C access function. If */ ++/* you need to rewrite these functions for your own SW infrastructure, then */ ++/* it can be removed */ ++# include ++# include ++# include ++# include ++# include ++# include ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++/* I2C adress of the unit */ ++/* Put there the I2C slave adress of the Tx transmitter IC */ ++#define UNIT_I2C_ADDRESS_0 0x70 ++ ++/* Intel CE 4100 I2C bus number */ ++/* Put there the number of I2C bus handling the Rx transmitter IC */ ++#define I2C_BUS_NUMBER_0 0 // initial:0 ++ ++/* I2C Number of bytes in the data buffer. */ ++#define SUB_ADDR_BYTE_COUNT_0 1 ++ ++/* Priority of the command task */ ++/* Command task is an internal task that handles incoming event from the IC */ ++/* put there a value that will ensure a response time of ~20ms in your system */ ++#define COMMAND_TASK_PRIORITY_0 250 ++#define COMMAND_TASK_PRIORITY_1 250 ++ ++/* Priority of the hdcp check tasks */ ++/* HDCP task is an internal task that handles periodical HDCP processing */ ++/* put there a value that will ensure a response time of ~20ms in your system */ ++#define HDCP_CHECK_TASK_PRIORITY_0 250 ++ ++/* Stack size of the command tasks */ ++/* This value depends of the type of CPU used, and also from the length of */ ++/* the customer callbacks. Increase this value if you are making a lot of */ ++/* processing (function calls & local variables) and that you experience */ ++/* stack overflows */ ++#define COMMAND_TASK_STACKSIZE_0 128 ++#define COMMAND_TASK_STACKSIZE_1 128 ++ ++/* stack size of the hdcp check tasks */ ++/* This value depends of the type of CPU used, default value should be enough */ ++/* for all configuration */ ++#define HDCP_CHECK_TASK_STACKSIZE_0 128 ++ ++/* Size of the message queues for command tasks */ ++/* This value defines the size of the message queue used to link the */ ++/* the tmdlHdmiTxHandleInterrupt function and the command task. The default */ ++/* value below should fit any configuration */ ++#define COMMAND_TASK_QUEUESIZE_0 128 ++#define COMMAND_TASK_QUEUESIZE_1 128 ++ ++/* HDCP key seed */ ++/* HDCP key are stored encrypted into the IC, this value allows the IC to */ ++/* decrypt them. This value is provided to the customer by NXP customer */ ++/* support team. */ ++#define KEY_SEED 0x1234 ++ ++/* Video port configuration for YUV444 input */ ++/* You can specify in this table how are connected video ports in case of */ ++/* YUV444 input signal. Each line of the array corresponds to a quartet of */ ++/* pins of one video port (see comment on the left to identify them). Just */ ++/* change the enum to specify which signal you connected to it. See file */ ++/* tmdlHdmiTx_cfg.h to get the list of possible values */ ++const tmdlHdmiTxCfgVideoSignal444 videoPortMapping_YUV444[MAX_UNITS][6] = { ++ { ++ TMDL_HDMITX_VID444_BU_0_TO_3, /* Signals connected to VPA[0..3] */ ++ TMDL_HDMITX_VID444_BU_4_TO_7, /* Signals connected to VPA[4..7] */ ++ TMDL_HDMITX_VID444_GY_0_TO_3, /* Signals connected to VPB[0..3] */ ++ TMDL_HDMITX_VID444_GY_4_TO_7, /* Signals connected to VPB[4..7] */ ++ TMDL_HDMITX_VID444_VR_0_TO_3, /* Signals connected to VPC[0..3] */ ++ TMDL_HDMITX_VID444_VR_4_TO_7 /* Signals connected to VPC[4..7] */ ++ } ++}; ++ ++/* Video port configuration for RGB444 input */ ++/* You can specify in this table how are connected video ports in case of */ ++/* RGB444 input signal. Each line of the array corresponds to a quartet of */ ++/* pins of one video port (see comment on the left to identify them). Just */ ++/* change the enum to specify which signal you connected to it. See file */ ++/* tmdlHdmiTx_cfg.h to get the list of possible values */ ++const tmdlHdmiTxCfgVideoSignal444 videoPortMapping_RGB444[MAX_UNITS][6] = { ++ { ++ TMDL_HDMITX_VID444_GY_0_TO_3, /* Signals connected to VPA[0..3] */ ++ TMDL_HDMITX_VID444_GY_4_TO_7, /* Signals connected to VPA[4..7] */ ++ TMDL_HDMITX_VID444_BU_0_TO_3, /* Signals connected to VPC[0..3] */ ++ TMDL_HDMITX_VID444_BU_4_TO_7, /* Signals connected to VPC[4..7] */ ++ TMDL_HDMITX_VID444_VR_0_TO_3, /* Signals connected to VPB[0..3] */ ++ TMDL_HDMITX_VID444_VR_4_TO_7 /* Signals connected to VPB[4..7] */ ++ } ++}; ++ ++/* Video port configuration for YUV422 input */ ++/* You can specify in this table how are connected video ports in case of */ ++/* YUV422 input signal. Each line of the array corresponds to a quartet of */ ++/* pins of one video port (see comment on the left to identify them). Just */ ++/* change the enum to specify which signal you connected to it. See file */ ++/* tmdlHdmiTx_cfg.h to get the list of possible values */ ++const tmdlHdmiTxCfgVideoSignal422 videoPortMapping_YUV422[MAX_UNITS][6] = { ++ { ++ TMDL_HDMITX_VID422_Y_4_TO_7, /* Signals connected to VPA[0..3] */ ++ TMDL_HDMITX_VID422_Y_8_TO_11, /* Signals connected to VPA[4..7] */ ++ TMDL_HDMITX_VID422_UV_4_TO_7, /* Signals connected to VPB[0..3] */ ++ TMDL_HDMITX_VID422_UV_8_TO_11, /* Signals connected to VPB[4..7] */ ++ TMDL_HDMITX_VID422_NOT_CONNECTED, /* Signals connected to VPC[0..3] */ ++ TMDL_HDMITX_VID422_NOT_CONNECTED /* Signals connected to VPC[4..7] */ ++ } ++}; ++ ++/* Video port configuration for CCIR656 input */ ++/* You can specify in this table how are connected video ports in case of */ ++/* CCIR656 input signal. Each line of the array corresponds to a quartet of */ ++/* pins of one video port (see comment on the left to identify them). Just */ ++/* change the enum to specify which signal you connected to it. See file */ ++/* tmdlHdmiTx_cfg.h to get the list of possible values */ ++const tmdlHdmiTxCfgVideoSignalCCIR656 videoPortMapping_CCIR656[MAX_UNITS][6] = { ++ { ++ TMDL_HDMITX_VIDCCIR_4_TO_7, /* Signals connected to VPA[0..3] */ ++ TMDL_HDMITX_VIDCCIR_8_TO_11, /* Signals connected to VPA[4..7] */ ++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED, /* Signals connected to VPB[0..3] */ ++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED, /* Signals connected to VPB[4..7] */ ++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED, /* Signals connected to VPC[0..3] */ ++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED /* Signals connected to VPC[4..7] */ ++ } ++}; ++ ++/* ++ * ++ * Linux wrapping starts here............................... ++ * ++ */ ++/* ++ * Write a bloc to a register in Tx device. ++ */ ++int blockwrite_reg(struct i2c_client *client, u8 reg, u16 alength, u8 *val) ++{ ++ int err = 0; ++ int i; ++ struct i2c_msg msg[1]; ++ ++ if (!client->adapter) { ++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__); ++ return -ENODEV; ++ } ++ ++ msg->addr = client->addr; ++ msg->flags = I2C_M_WR; ++ msg->len = alength+1; ++ msg->buf = my_i2c_data; ++ ++ msg->buf[0] = reg; ++ for (i=1; i<=alength; i++) msg->buf[i] = (*val++); ++ ++ err = i2c_transfer(client->adapter, msg, 1); ++ udelay(50); ++ ++ ++/* printk(KERN_INFO "DBG blockwrite_reg addr:%x reg:%d data:%x %s\n",msg->addr,reg,val,(err<0?"ERROR":"")); */ ++ ++/* dev_dbg(&client->dev, "<%s> i2c Block write at 0x%x, " */ ++/* "*val=%d flags=%d byte[%d] err=%d\n", */ ++/* __func__, data[0], data[1], msg->flags, i, err); */ ++ ++ return (err < 0?err:0); ++} ++ ++/* ++ * Read a bloc to a register in Tx device. ++ */ ++int blockread_reg(struct i2c_client *client, u8 reg, u16 alength, u8 *val) ++{ ++ int err = 0; ++ struct i2c_msg msg[1]; ++ u8 data[2]; ++ ++ if (!client->adapter) { ++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__); ++ return -ENODEV; ++ } ++ ++ msg->addr = client->addr; ++ msg->flags = I2C_M_WR; ++ msg->len = 1; ++ msg->buf = data; ++ data[0] = reg; /* High byte goes out first */ ++ err = i2c_transfer(client->adapter, msg, 1); ++/* printk(KERN_INFO "DBG blockread_reg #1 addr:%x len:%d buf:%02x%02x%02x%02x %s\n",msg->addr,msg->len,\ */ ++/* msg->buf[0],msg->buf[1],msg->buf[2],msg->buf[3],(err<0?"ERROR":"")); */ ++ if (err<0) goto BLOCK_READ_OUPS; ++ ++ msg->flags = I2C_M_RD; ++ msg->len = alength; ++ msg->buf = val; ++ err = i2c_transfer(client->adapter, msg, 1); ++/* printk(KERN_INFO "DBG blockread_reg #2 addr:%x len:%d buf:%02x%02x%02x%02x %s\n",msg->addr,msg->len,\ */ ++/* msg->buf[0],msg->buf[1],msg->buf[2],msg->buf[3],(err<0?"ERROR":"")); */ ++ ++ if (err<0) goto BLOCK_READ_OUPS; ++ ++ return 0; ++ ++ BLOCK_READ_OUPS: ++ dev_err(&client->dev, "<%s> ERROR: i2c Read at 0x%x, " ++ "*val=%d flags=%d bytes err=%d\n", ++ __func__, reg, *val, msg->flags, err); ++ ++ return err; ++} ++ ++/* ++ * Write a byte to a register in Tx device. ++ */ ++int write_reg(struct i2c_client *client, u8 reg, u8 val) ++{ ++ int err = 0; ++ struct i2c_msg msg[1]; ++ u8 data[2]; ++ int retries = 0; ++ ++ if (!client->adapter) { ++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__); ++ return -ENODEV; ++ } ++ ++ retry: ++ msg->addr = client->addr; ++ msg->flags = I2C_M_WR; ++ msg->len = 2; ++ msg->buf = data; ++ ++ data[0] = reg; ++ data[1] = val; ++ ++ err = i2c_transfer(client->adapter, msg, 1); ++ dev_dbg(&client->dev, "<%s> i2c write at=%x " ++ "val=%x flags=%d err=%d\n", ++ __func__, data[0], data[1], msg->flags, err); ++ udelay(50); ++ ++/* printk(KERN_INFO "DBG write_reg addr:%x reg:%d data:%x %s\n",msg->addr,reg,val,(err<0?"ERROR":"")); */ ++ ++ if (err >= 0) ++ return 0; ++ ++ dev_err(&client->dev, "<%s> ERROR: i2c write at=%x " ++ "val=%x flags=%d err=%d\n", ++ __func__, data[0], data[1], msg->flags, err); ++ if (retries <= 5) { ++ dev_info(&client->dev, "Retrying I2C... %d\n", retries); ++ retries++; ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ schedule_timeout(msecs_to_jiffies(20)); ++ goto retry; ++ } ++ ++ return err; ++} ++ ++/* ++ * Read a byte from a register in Tx device. ++ */ ++int read_reg(struct i2c_client *client, u16 data_length, u8 reg, u8 *val) ++{ ++ int err = 0; ++ struct i2c_msg msg[1]; ++ u8 data[2]; ++ ++ if (!client->adapter) { ++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__); ++ return -ENODEV; ++ } ++ ++ msg->addr = client->addr; ++ msg->flags = I2C_M_WR; ++ msg->len = 1; ++ msg->buf = data; ++ ++ data[0] = reg; ++ err = i2c_transfer(client->adapter, msg, 1); ++ dev_dbg(&client->dev, "<%s> i2c Read1 reg=%x val=%d " ++ "flags=%d err=%d\n", ++ __func__, reg, data[1], msg->flags, err); ++ ++ if (err >= 0) { ++ mdelay(3); ++ msg->flags = I2C_M_RD; ++ msg->len = data_length; ++ err = i2c_transfer(client->adapter, msg, 1); ++ } ++ ++ if (err >= 0) { ++ *val = 0; ++ if (data_length == 1) ++ *val = data[0]; ++ else if (data_length == 2) ++ *val = data[1] + (data[0] << 8); ++ dev_dbg(&client->dev, "<%s> i2c Read2 at 0x%x, *val=%d " ++ "flags=%d err=%d\n", ++ __func__, reg, *val, msg->flags, err); ++ return 0; ++ } ++ ++ dev_err(&client->dev, "<%s> ERROR: i2c Read at 0x%x, " ++ "*val=%d flags=%d err=%d\n", ++ __func__, reg, *val, msg->flags, err); ++ ++ return err; ++} ++/* ++ * ++ * Linux wrapping end............................... ++ * ++ */ ++ ++/* The following function must be rewritten by the customer to fit its own */ ++/* SW infrastructure. This function allows reading through I2C bus. */ ++/* tmbslHdmiTxSysArgs_t definition is located into tmbslHdmiTx_type.h file. */ ++tmErrorCode_t TxI2cReadFunction(tmbslHdmiTxSysArgs_t *pSysArgs) ++{ ++ tmErrorCode_t errCode = TM_OK; ++ struct i2c_client *client=GetThisI2cClient(); ++ u32 client_main_addr=client->addr; ++ ++ /* DevLib needs address control, so let it be */ ++ client->addr=pSysArgs->slaveAddr; ++ ++ if (pSysArgs->lenData == 1) { ++ /* single byte */ ++ errCode = read_reg(GetThisI2cClient(),1,pSysArgs->firstRegister,pSysArgs->pData); ++ } ++ else { ++ /* block */ ++ errCode = blockread_reg(GetThisI2cClient(), \ ++ pSysArgs->firstRegister, \ ++ pSysArgs->lenData, \ ++ pSysArgs->pData); ++ } ++ ++ /* restore default client address */ ++ client->addr=client_main_addr; ++ ++ return errCode; ++} ++ ++/* The following function must be rewritten by the customer to fit its own */ ++/* SW infrastructure. This function allows writing through I2C bus. */ ++/* tmbslHdmiTxSysArgs_t definition is located into tmbslHdmiTx_type.h file. */ ++tmErrorCode_t TxI2cWriteFunction(tmbslHdmiTxSysArgs_t *pSysArgs) ++{ ++ tmErrorCode_t errCode = TM_OK; ++ struct i2c_client *client=GetThisI2cClient(); ++ u32 client_main_addr=client->addr; ++ ++ /* DevLib needs address control, so let it be */ ++ client->addr=pSysArgs->slaveAddr; ++ ++ if (pSysArgs->lenData == 1) { ++ /* single byte */ ++ errCode = write_reg(GetThisI2cClient(),pSysArgs->firstRegister,*pSysArgs->pData); ++ } ++ else { ++ /* block */ ++ errCode = blockwrite_reg(GetThisI2cClient(), \ ++ pSysArgs->firstRegister, \ ++ pSysArgs->lenData, \ ++ pSysArgs->pData); ++ } ++ ++ /* restore default client address */ ++ client->addr=client_main_addr; ++ ++ return errCode; ++} ++ ++ ++/****************************************************************************** ++ \brief This function blocks the current task for the specified amount time. ++ This is a passive wait. ++ ++ \param Duration Duration of the task blocking in milliseconds. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWWait ++( ++ UInt16 duration ++) ++{ ++ mdelay((unsigned long)duration); ++ ++ return(TM_OK); ++} ++ ++/****************************************************************************** ++ \brief This function creates a semaphore. ++ ++ \param pHandle Pointer to the handle buffer. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWSemaphoreCreate ++( ++ tmdlHdmiTxIWSemHandle_t *pHandle ++) ++{ ++ struct semaphore * mutex; ++ ++ /* check that input pointer is not NULL */ ++ RETIF(pHandle == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ mutex = (struct semaphore *)kmalloc(sizeof(struct semaphore),GFP_KERNEL); ++ if (!mutex) { ++ printk(KERN_ERR "malloc failed in %s\n",__func__); ++ return TMDL_ERR_DLHDMITX_NO_RESOURCES; ++ } ++ ++ sema_init(mutex, 1); ++ *pHandle = (tmdlHdmiTxIWSemHandle_t)mutex; ++ ++ RETIF(pHandle == NULL, TMDL_ERR_DLHDMITX_NO_RESOURCES) ++ ++ return(TM_OK); ++} ++ ++/****************************************************************************** ++ \brief This function destroys an existing semaphore. ++ ++ \param Handle Handle of the semaphore to be destroyed. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWSemaphoreDestroy ++( ++ tmdlHdmiTxIWSemHandle_t handle ++) ++{ ++ RETIF(handle == False, TMDL_ERR_DLHDMITX_BAD_HANDLE); ++ ++ if (atomic_read((atomic_t*)&((struct semaphore *)handle)->count) < 1) { ++ printk(KERN_ERR "release catched semaphore"); ++ } ++ ++ kfree((void*)handle); ++ ++ return(TM_OK); ++} ++ ++/****************************************************************************** ++ \brief This function acquires the specified semaphore. ++ ++ \param Handle Handle of the semaphore to be acquired. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWSemaphoreP ++( ++ tmdlHdmiTxIWSemHandle_t handle ++) ++{ ++ down((struct semaphore *)handle); ++ ++ return(TM_OK); ++} ++ ++/****************************************************************************** ++ \brief This function releases the specified semaphore. ++ ++ \param Handle Handle of the semaphore to be released. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWSemaphoreV ++( ++ tmdlHdmiTxIWSemHandle_t handle ++) ++{ ++ up((struct semaphore *)handle); ++ ++ return(TM_OK); ++} ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ ++ +diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_cfg.c b/drivers/video/nxp/comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_cfg.c +new file mode 100755 +index 0000000..23c5437 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_cfg.c +@@ -0,0 +1,624 @@ ++/** ++ * Copyright (C) 2006 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmdlHdmiTx_cfg.c ++ * ++ * \version Revision: 1 ++ * ++ * \date Date: 25/03/11 11:00 ++ * ++ * \brief devlib driver component API for the TDA998x HDMI Transmitters ++ * ++ * \section refs Reference Documents ++ * HDMI Tx Driver - FRS.doc, ++ * ++ * \section info Change Information ++ * ++ * \verbatim ++ ++ History: tmdlHdmiTx_cfg.c ++ * ++ * ***************** Version 2 ***************** ++ * User: V. Vrignaud Date: March 25th, 2011 ++ * ++ * ***************** Version 1 ***************** ++ * User: J. Lamotte Date: 08/08/07 Time: 11:00 ++ * initial version ++ * ++ ++ \endverbatim ++ * ++*/ ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#include "tmdlHdmiTx_IW.h" ++#include "tmdlHdmiTx.h" ++#include "tmdlHdmiTx_cfg.h" ++ ++#ifdef TMFL_CEC_AVAILABLE ++#include "tmdlHdmiCEC_functions.h" ++#define CEC_UNIT_I2C_ADDRESS_0 0x34 ++#define CEC_UNIT_I2C_ADDRESS_1 0x34 ++#endif ++ ++//#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++#ifdef TMFL_CFG_ZOOMII // OMAP Zoom II ++# include "tmdlHdmiTx_Linux_cfg.c" ++#elif TMFL_CFG_INTELCE4100 // Intel CE 4100 ++# include "tmdlHdmiTx_IntelCE4100_cfg.c" ++#elif TMFL_OS_WINDOWS // Windows demo application ++# include "tmdlHdmiTx_Win_cfg.c" ++#else // Section to be modified by customer - Default configuration for NXP evalkit ++ ++/*============================================================================*/ ++/* MACRO */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* STATIC FUNCTION DECLARATIONS */ ++/*============================================================================*/ ++tmErrorCode_t TxI2cReadFunction(tmbslHdmiTxSysArgs_t *pSysArgs); ++tmErrorCode_t TxI2cWriteFunction(tmbslHdmiTxSysArgs_t *pSysArgs); ++ ++/****************************************************************************** ++ ****************************************************************************** ++ * THIS PART CAN BE MODIFIED BY CUSTOMER * ++ ****************************************************************************** ++ *****************************************************************************/ ++/* The following includes are used by I2C access function for ARM7. If */ ++/* you need to rewrite these functions for your own SW infrastructure, then */ ++/* it can be removed */ ++#include "I2C.h" ++#include ++ ++/* I2C adress of the unit */ ++/* Put there the I2C slave adress of the Tx transmitter IC */ ++#define UNIT_I2C_ADDRESS_0 0x70 ++ ++/* Priority of the command task */ ++/* Command task is an internal task that handles incoming event from the IC */ ++/* put there a value that will ensure a response time of ~20ms in your system */ ++#define COMMAND_TASK_PRIORITY_0 250 ++#define COMMAND_TASK_PRIORITY_1 250 ++ ++/* Priority of the hdcp check tasks */ ++/* HDCP task is an internal task that handles periodical HDCP processing */ ++/* put there a value that will ensure a response time of ~20ms in your system */ ++#define HDCP_CHECK_TASK_PRIORITY_0 250 ++ ++/* Stack size of the command tasks */ ++/* This value depends of the type of CPU used, and also from the length of */ ++/* the customer callbacks. Increase this value if you are making a lot of */ ++/* processing (function calls & local variables) and that you experience */ ++/* stack overflows */ ++#define COMMAND_TASK_STACKSIZE_0 128 ++#define COMMAND_TASK_STACKSIZE_1 128 ++ ++/* stack size of the hdcp check tasks */ ++/* This value depends of the type of CPU used, default value should be enough */ ++/* for all configuration */ ++#define HDCP_CHECK_TASK_STACKSIZE_0 128 ++ ++/* Size of the message queues for command tasks */ ++/* This value defines the size of the message queue used to link the */ ++/* the tmdlHdmiTxHandleInterrupt function and the command task. The default */ ++/* value below should fit any configuration */ ++#define COMMAND_TASK_QUEUESIZE_0 128 ++#define COMMAND_TASK_QUEUESIZE_1 128 ++ ++/* HDCP key seed */ ++/* HDCP key are stored encrypted into the IC, this value allows the IC to */ ++/* decrypt them. This value is provided to the customer by NXP customer */ ++/* support team. */ ++#define KEY_SEED 0x1234 ++ ++/* Video port configuration for YUV444 input */ ++/* You can specify in this table how are connected video ports in case of */ ++/* YUV444 input signal. Each line of the array corresponds to a quartet of */ ++/* pins of one video port (see comment on the left to identify them). Just */ ++/* change the enum to specify which signal you connected to it. See file */ ++/* tmdlHdmiTx_cfg.h to get the list of possible values */ ++const tmdlHdmiTxCfgVideoSignal444 videoPortMapping_YUV444[MAX_UNITS][6] = { ++ { ++ TMDL_HDMITX_VID444_GY_0_TO_3, /* Signals connected to VPB[0..3] */ ++ TMDL_HDMITX_VID444_GY_4_TO_7, /* Signals connected to VPB[4..7] */ ++ TMDL_HDMITX_VID444_BU_0_TO_3, /* Signals connected to VPA[0..3] */ ++ TMDL_HDMITX_VID444_BU_4_TO_7, /* Signals connected to VPA[4..7] */ ++ TMDL_HDMITX_VID444_VR_0_TO_3, /* Signals connected to VPC[0..3] */ ++ TMDL_HDMITX_VID444_VR_4_TO_7 /* Signals connected to VPC[4..7] */ ++ } ++}; ++ ++/* Video port configuration for RGB444 input */ ++/* You can specify in this table how are connected video ports in case of */ ++/* RGB444 input signal. Each line of the array corresponds to a quartet of */ ++/* pins of one video port (see comment on the left to identify them). Just */ ++/* change the enum to specify which signal you connected to it. See file */ ++/* tmdlHdmiTx_cfg.h to get the list of possible values */ ++const tmdlHdmiTxCfgVideoSignal444 videoPortMapping_RGB444[MAX_UNITS][6] = { ++ { ++ TMDL_HDMITX_VID444_GY_0_TO_3, /* Signals connected to VPB[0..3] */ ++ TMDL_HDMITX_VID444_GY_4_TO_7, /* Signals connected to VPB[4..7] */ ++ TMDL_HDMITX_VID444_BU_0_TO_3, /* Signals connected to VPA[0..3] */ ++ TMDL_HDMITX_VID444_BU_4_TO_7, /* Signals connected to VPA[4..7] */ ++ TMDL_HDMITX_VID444_VR_0_TO_3, /* Signals connected to VPC[0..3] */ ++ TMDL_HDMITX_VID444_VR_4_TO_7 /* Signals connected to VPC[4..7] */ ++ } ++}; ++ ++/* Video port configuration for YUV422 input */ ++/* You can specify in this table how are connected video ports in case of */ ++/* YUV422 input signal. Each line of the array corresponds to a quartet of */ ++/* pins of one video port (see comment on the left to identify them). Just */ ++/* change the enum to specify which signal you connected to it. See file */ ++/* tmdlHdmiTx_cfg.h to get the list of possible values */ ++const tmdlHdmiTxCfgVideoSignal422 videoPortMapping_YUV422[MAX_UNITS][6] = { ++ { ++ TMDL_HDMITX_VID422_NOT_CONNECTED, /* Signals connected to VPC[0..3] */ ++ TMDL_HDMITX_VID422_NOT_CONNECTED, /* Signals connected to VPB[4..7] */ ++ TMDL_HDMITX_VID422_UV_4_TO_7, /* Signals connected to VPC[4..7] */ ++ TMDL_HDMITX_VID422_UV_8_TO_11, /* Signals connected to VPB[0..3] */ ++ TMDL_HDMITX_VID422_Y_4_TO_7, /* Signals connected to VPA[0..3] */ ++ TMDL_HDMITX_VID422_Y_8_TO_11 /* Signals connected to VPA[4..7] */ ++ } ++}; ++ ++/* Video port configuration for CCIR656 input */ ++/* You can specify in this table how are connected video ports in case of */ ++/* CCIR656 input signal. Each line of the array corresponds to a quartet of */ ++/* pins of one video port (see comment on the left to identify them). Just */ ++/* change the enum to specify which signal you connected to it. See file */ ++/* tmdlHdmiTx_cfg.h to get the list of possible values */ ++const tmdlHdmiTxCfgVideoSignalCCIR656 videoPortMapping_CCIR656[MAX_UNITS][6] = { ++ { ++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED, /* Signals connected to VPB[0..3] */ ++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED, /* Signals connected to VPB[4..7] */ ++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED, /* Signals connected to VPC[0..3] */ ++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED, /* Signals connected to VPC[4..7] */ ++ TMDL_HDMITX_VIDCCIR_4_TO_7, /* Signals connected to VPA[4..7] */ ++ TMDL_HDMITX_VIDCCIR_8_TO_11 /* Signals connected to VPA[0..3] */ ++ } ++}; ++ ++/* The following function must be rewritten by the customer to fit its own */ ++/* SW infrastructure. This function allows reading through I2C bus. */ ++/* tmbslHdmiTxSysArgs_t definition is located into tmbslHdmiTx_type.h file. */ ++tmErrorCode_t TxI2cReadFunction(tmbslHdmiTxSysArgs_t *pSysArgs) ++{ ++ tmErrorCode_t errCode = TM_OK; ++ ++ if (pSysArgs->slaveAddr == 0x70) ++ { ++ errCode = i2cRead(reg_TDA998X, (tmbslHdmiSysArgs_t *) pSysArgs); ++ } ++ else if (pSysArgs->slaveAddr == 0x34) ++ { ++ errCode = i2cRead(reg_TDA9989_CEC, (tmbslHdmiSysArgs_t *) pSysArgs); ++ } ++ else ++ { ++ errCode = ~TM_OK; ++ } ++ ++ return errCode; ++} ++ ++/* The following function must be rewritten by the customer to fit its own */ ++/* SW infrastructure. This function allows writing through I2C bus. */ ++/* tmbslHdmiTxSysArgs_t definition is located into tmbslHdmiTx_type.h file. */ ++tmErrorCode_t TxI2cWriteFunction(tmbslHdmiTxSysArgs_t *pSysArgs) ++{ ++ tmErrorCode_t errCode = TM_OK; ++ ++ if (pSysArgs->slaveAddr == 0x70) ++ { ++ errCode = i2cWrite(reg_TDA998X, (tmbslHdmiSysArgs_t *) pSysArgs); ++ ++ } ++ else if (pSysArgs->slaveAddr == 0x34) ++ { ++ errCode = i2cWrite(reg_TDA9989_CEC, (tmbslHdmiSysArgs_t *) pSysArgs); ++ } ++ else ++ { ++ errCode = ~TM_OK; ++ } ++ ++ return errCode; ++} ++ ++#endif ++ ++#ifdef TMFL_RGB_DDR_12BITS ++ ++/* Video port configuration for RGB 24 bits input received with only 12 bits */ ++/* using the double data rate */ ++/* ++ The main difference between RGB12 bits and CCIR 656 formats is that for the new format ++ RGB888 the“Green� data is separated on rising and on falling edge. This is in principle ++ no problem only the result is that the colors RGB will be swabbed. ++ After the Video Input Processing (VIP) module there will be a multiplexer structure ++ implemented which can swab all colors and combinations. ++ ++ Extra information on request ++ ++ P:\Partages\BCT_TV_FE\Product_Development\Project folders\TDA19988 \ ++ 14_Design\Video_pipe_Schematic_RGB888.pdf ++ ++ but ok, let's give it a try... ++ ++ In DDR, VIP input latches on failing and raising clock edge, ++ so VIP internal input is doubled from 24 to 48 bits ++ ++ VIP input ------>[ T ]---[ T ]--------------------> VIP internal input ++ /24 | | ° /24 | /48 ++ | | | | ++ | pclk----------- | ++ | | | ++ | ° | ++ ------>[ T ]------------------ ++ /24 ++ ++ But in the 24 VIP input, only 12 bits are used : ++ ++ ------------------------------------------------------------------- ++ | | | | | | | ++ | Vpc[7:4] | Vpc[3:0] | Vpb[7:4] | Vpb[3:0] | Vpa[7:4] | Vpa[3:0] | ++ | | | ........ | | ........ | ........ | ++ ------------------------------------------------------------------- ++ ^ ^ ^ ++ | | | ++ | | | ++ location of valid data ------------------------------------- ++ ++ So we get first RGB 12 bits on bits 24 to 47 of VIP internal input ++ and second RGB 12 bits on bits 0 to 23 of VIP internal input ++ ++ 1)first edge (failing) R[7:4] R[3:0] G[7:4] ++ | | | ++ | | | ++ V V V ++ --------------------------------------------------------------------.. ++ | | | | | | | ++ | 47...44 | 43...40 | 39...36 | 35...32 | 31...28 | 27...24 | ++ | | | | | | | ++ --------------------------------------------------------------------.. ++ ++ 2)2nd edge (raising) G[3:0] B[7:3] B[3:0] ++ | | | ++ | | | ++ V V V ++..------------------------------------------------------------------- ++ | | | | | | | ++ | 23...20 | 19...16 | 15...12 | 11...8 | 7...4 | 3...0 | ++ | | | | | | | ++..------------------------------------------------------------------- ++ ++ ++ ++ ++ ++ ++ After port swaping, internal video bus goes back from 48 to 24 bits ++ ++ VIP internal ------------>[ swap ]-------[ T ]----------> ++ /48 | | /24 ++ | | ++ i2c_swap_a/f ------ pclk --- ++ ++ ------------------------------------------------------------------- ++ | | | | | | | ++ | 23...20 | 19...16 | 15...12 | 11...8 | 7...4 | 3...0 | ++ | | | | | | | ++ ------------------------------------------------------------------- ++ R[7:4] R[3:0] G[7:4] G[3:0] B[7:3] B[3:0] ++ ++ Here is the swapping code : ++ ++IF i2c_swap_a = "000" THEN vp_alt_d2(11 downto 8) <= vp_alt_i_r(23 downto 20); vp_alt_d2(23 downto 20) <= vp_alt_i_r(47 downto 44); ++ELSIF i2c_swap_a = "001" THEN vp_alt_d2(11 downto 8) <= vp_alt_i_r(19 downto 16); vp_alt_d2(23 downto 20) <= vp_alt_i_r(43 downto 40); ++ELSIF i2c_swap_a = "010" THEN vp_alt_d2(11 downto 8) <= vp_alt_i_r(15 downto 12); vp_alt_d2(23 downto 20) <= vp_alt_i_r(39 downto 36); ++ELSIF i2c_swap_a = "011" THEN vp_alt_d2(11 downto 8) <= vp_alt_i_r(11 downto 8 ); vp_alt_d2(23 downto 20) <= vp_alt_i_r(35 downto 32); ++ELSIF i2c_swap_a = "100" THEN vp_alt_d2(11 downto 8) <= vp_alt_i_r( 7 downto 4 ); vp_alt_d2(23 downto 20) <= vp_alt_i_r(31 downto 28); ++ELSE vp_alt_d2(11 downto 8) <= vp_alt_i_r( 3 downto 0 ); vp_alt_d2(23 downto 20) <= vp_alt_i_r(27 downto 24); END IF; ++ ++IF i2c_swap_b = "000" THEN vp_alt_d2( 7 downto 4) <= vp_alt_i_r(23 downto 20); vp_alt_d2(19 downto 16) <= vp_alt_i_r(47 downto 44); ++ELSIF i2c_swap_b = "001" THEN vp_alt_d2( 7 downto 4) <= vp_alt_i_r(19 downto 16); vp_alt_d2(19 downto 16) <= vp_alt_i_r(43 downto 40); ++ELSIF i2c_swap_b = "010" THEN vp_alt_d2( 7 downto 4) <= vp_alt_i_r(15 downto 12); vp_alt_d2(19 downto 16) <= vp_alt_i_r(39 downto 36); ++ELSIF i2c_swap_b = "011" THEN vp_alt_d2( 7 downto 4) <= vp_alt_i_r(11 downto 8 ); vp_alt_d2(19 downto 16) <= vp_alt_i_r(35 downto 32); ++ELSIF i2c_swap_b = "100" THEN vp_alt_d2( 7 downto 4) <= vp_alt_i_r( 7 downto 4 ); vp_alt_d2(19 downto 16) <= vp_alt_i_r(31 downto 28); ++ELSE vp_alt_d2( 7 downto 4) <= vp_alt_i_r( 3 downto 0 ); vp_alt_d2(19 downto 16) <= vp_alt_i_r(27 downto 24); END IF; ++ ++IF i2c_swap_c = "000" THEN vp_alt_d2( 3 downto 0) <= vp_alt_i_r(23 downto 20); vp_alt_d2(15 downto 12) <= vp_alt_i_r(47 downto 44); ++ELSIF i2c_swap_c = "001" THEN vp_alt_d2( 3 downto 0) <= vp_alt_i_r(19 downto 16); vp_alt_d2(15 downto 12) <= vp_alt_i_r(43 downto 40); ++ELSIF i2c_swap_c = "010" THEN vp_alt_d2( 3 downto 0) <= vp_alt_i_r(15 downto 12); vp_alt_d2(15 downto 12) <= vp_alt_i_r(39 downto 36); ++ELSIF i2c_swap_c = "011" THEN vp_alt_d2( 3 downto 0) <= vp_alt_i_r(11 downto 8 ); vp_alt_d2(15 downto 12) <= vp_alt_i_r(35 downto 32); ++ELSIF i2c_swap_c = "100" THEN vp_alt_d2( 3 downto 0) <= vp_alt_i_r( 7 downto 4 ); vp_alt_d2(15 downto 12) <= vp_alt_i_r(31 downto 28); ++ELSE vp_alt_d2( 3 downto 0) <= vp_alt_i_r( 3 downto 0 ); vp_alt_d2(15 downto 12) <= vp_alt_i_r(27 downto 24); END IF; ++ ++ in case of RGB DDR 12 bits, we get : ++ . i2c_swap_a = "010" ++ . i2c_swap_b = "011" ++ . i2c_swap_c > "100" ++ ++ ;) ++ ++*/ ++ ++const tmdlHdmiTxCfgVideoSignal_RGB_DDR_12bits VideoPortMapping_RGB_DDR_12bits[MAX_UNITS][6] = { ++ { ++ TMDL_HDMITX_VID_B_0_3_G_4_7, /* Signals connected to VPA[0..3] */ ++ TMDL_HDMITX_VID_DDR_NOT_CONNECTED, /* Signals connected to VPA[4..7] */ ++ TMDL_HDMITX_VID_B_4_7_R_0_3, /* Signals connected to VPB[0..3] */ ++ TMDL_HDMITX_VID_G_0_3_R_4_7, /* Signals connected to VPB[4..7] */ ++ TMDL_HDMITX_VID_DDR_NOT_CONNECTED, /* Signals connected to VPC[0..3] */ ++ TMDL_HDMITX_VID_DDR_NOT_CONNECTED /* Signals connected to VPC[4..7] */ ++ } ++}; ++ ++/* ++ ++ Then VIP targeted order is not RGB but BGR ++ so we use a new register for TDA19988 MUX_VP_VIP_OUT ++ with VIP_OUTPUT_RGB_GBR as defined in cfg.h file ++ ++ ------------------------------------------------------------------- ++ | | | | | | | ++ | 23...20 | 19...16 | 15...12 | 11...8 | 7...4 | 3...0 | ++ | | | | | | | ++ ------------------------------------------------------------------- ++ R[7:4] R[3:0] G[7:4] G[3:0] B[7:3] B[3:0] ++ - . . ++ - . . ++ - . . ++ - . . ++ . - . ++ . - . ++ . - . ++ . - ++ . . - ++ . . - ++ . . - ++ ++ G[7:4] G[3:0] B[7:4] B[3:0] R[7:3] R[3:0] ++ ++*/ ++ ++const UInt8 VideoPortMux_RGB_DDR_12bits[MAX_UNITS] = { ++ VIP_MUX_R_R | VIP_MUX_G_G | VIP_MUX_B_B ++}; ++ ++const UInt8 VideoPortNoMux[MAX_UNITS] = { ++ VIP_MUX_G_B | VIP_MUX_B_R | VIP_MUX_R_G ++}; ++ ++#endif /* TMFL_RGB_DDR_12BITS */ ++ ++/* Audio port configuration for SPDIF */ ++/* Here you can specify the audio port routing configuration for SPDIF input. */ ++/* enableAudioPortSPDIF and groundAudioPortSPDIF should be filled with a */ ++/* value build as follows : each bit represent an audio port, LSB is port 0. */ ++/* enableAudioClockPortSPDIF and groundAudioClockPortSPDIF can be configured */ ++/* with the corresponding enums (See file tmdlHdmiTx_cfg.h for more details). */ ++UInt8 enableAudioPortSPDIF[MAX_UNITS] = {0x02}; ++UInt8 enableAudioClockPortSPDIF[MAX_UNITS] = {DISABLE_AUDIO_CLOCK_PORT}; ++UInt8 groundAudioPortSPDIF[MAX_UNITS] = {0xFD}; ++UInt8 groundAudioClockPortSPDIF[MAX_UNITS] = {ENABLE_AUDIO_CLOCK_PORT_PULLDOWN}; ++ ++/* Audio port configuration for I2S */ ++/* Here you can specify the audio port routing configuration for SPDIF input. */ ++/* enableAudioPortI2S and groundAudioPortI2S should be filled with a */ ++/* value build as follows : each bit represent an audio port, LSB is port 0. */ ++/* enableAudioClockPortI2S and groundAudioClockPortI2S can be configured */ ++/* with the corresponding enums (See file tmdlHdmiTx_cfg.h for more details). */ ++UInt8 enableAudioPortI2S[MAX_UNITS] = {0x03}; ++UInt8 enableAudioPortI2S8C[MAX_UNITS] = {0x1f}; ++UInt8 enableAudioClockPortI2S[MAX_UNITS] = {ENABLE_AUDIO_CLOCK_PORT}; ++UInt8 groundAudioPortI2S[MAX_UNITS] = {0xfc}; ++UInt8 groundAudioPortI2S8C[MAX_UNITS] = {0xe0}; ++UInt8 groundAudioClockPortI2S[MAX_UNITS] = {DISABLE_AUDIO_CLOCK_PORT_PULLDOWN}; ++ ++/* Audio port configuration for OBA */ ++/* Here you can specify the audio port routing configuration for SPDIF input. */ ++/* enableAudioPortOBA and groundAudioPortOBA should be filled with a */ ++/* value build as follows : each bit represent an audio port, LSB is port 0. */ ++/* enableAudioClockPortOBA and groundAudioClockPortOBA can be configured */ ++/* with the corresponding enums (See file tmdlHdmiTx_cfg.h for more details). */ ++UInt8 enableAudioPortOBA[MAX_UNITS] = {0xFF}; ++UInt8 enableAudioClockPortOBA[MAX_UNITS] = {ENABLE_AUDIO_CLOCK_PORT}; ++UInt8 groundAudioPortOBA[MAX_UNITS] = {0x00}; ++UInt8 groundAudioClockPortOBA[MAX_UNITS] = {DISABLE_AUDIO_CLOCK_PORT_PULLDOWN}; ++ ++/* Audio port configuration for DST */ ++/* Here you can specify the audio port routing configuration for SPDIF input. */ ++/* enableAudioPortDST and groundAudioPortDST should be filled with a */ ++/* value build as follows : each bit represent an audio port, LSB is port 0. */ ++/* enableAudioClockPortDST and groundAudioClockPortDST can be configured */ ++/* with the corresponding enums (See file tmdlHdmiTx_cfg.h for more details). */ ++UInt8 enableAudioPortDST[MAX_UNITS] = {0xFF}; ++UInt8 enableAudioClockPortDST[MAX_UNITS] = {ENABLE_AUDIO_CLOCK_PORT}; ++UInt8 groundAudioPortDST[MAX_UNITS] = {0x00}; ++UInt8 groundAudioClockPortDST[MAX_UNITS] = {DISABLE_AUDIO_CLOCK_PORT_PULLDOWN}; ++ ++/* Audio port configuration for HBR */ ++/* Here you can specify the audio port routing configuration for SPDIF input. */ ++/* enableAudioPortHBR and groundAudioPortHBR should be filled with a */ ++/* value build as follows : each bit represent an audio port, LSB is port 0. */ ++/* enableAudioClockPortHBR and groundAudioClockPortHBR can be configured */ ++/* with the corresponding enums (See file tmdlHdmiTx_cfg.h for more details). */ ++UInt8 enableAudioPortHBR[MAX_UNITS] = {0x1f}; ++UInt8 enableAudioClockPortHBR[MAX_UNITS] = {ENABLE_AUDIO_CLOCK_PORT}; ++UInt8 groundAudioPortHBR[MAX_UNITS] = {0xe0}; ++UInt8 groundAudioClockPortHBR[MAX_UNITS] = {DISABLE_AUDIO_CLOCK_PORT_PULLDOWN}; ++ ++/***************************************************************************** ++****************************************************************************** ++* THIS PART MUST NOT BE MODIFIED BY CUSTOMER * ++****************************************************************************** ++*****************************************************************************/ ++ ++/* DO NOT MODIFY, those tables are filled dynamically by */ ++/* dlHdmiTxGenerateCfgVideoPortTables API */ ++UInt8 mirrorTableCCIR656[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; ++UInt8 swapTableCCIR656[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; ++UInt8 enableVideoPortCCIR656[MAX_UNITS][3] = {{0x00, 0x00, 0x00}}; ++UInt8 groundVideoPortCCIR656[MAX_UNITS][3] = {{0xFF, 0xFF, 0xFF}}; ++UInt8 mirrorTableYUV422[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; ++UInt8 swapTableYUV422[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; ++UInt8 enableVideoPortYUV422[MAX_UNITS][3] = {{0x00, 0x00, 0x00}}; ++UInt8 groundVideoPortYUV422[MAX_UNITS][3] = {{0xFF, 0xFF, 0xFF}}; ++UInt8 mirrorTableYUV444[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; ++UInt8 swapTableYUV444[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; ++UInt8 enableVideoPortYUV444[MAX_UNITS][3] = {{0x00, 0x00, 0x00}}; ++UInt8 groundVideoPortYUV444[MAX_UNITS][3] = {{0xFF, 0xFF, 0xFF}}; ++UInt8 mirrorTableRGB444[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; ++UInt8 swapTableRGB444[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; ++UInt8 enableVideoPortRGB444[MAX_UNITS][3] = {{0x00, 0x00, 0x00}}; ++UInt8 groundVideoPortRGB444[MAX_UNITS][3] = {{0xFF, 0xFF, 0xFF}}; ++#ifdef TMFL_RGB_DDR_12BITS ++UInt8 mirrorTableRGB_DDR_12bits[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; ++UInt8 swapTableRGB_DDR_12bits[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; ++UInt8 enableVideoPortRGB_DDR_12bits[MAX_UNITS][3] = {{0x00, 0x00, 0x00}}; ++UInt8 groundVideoPortRGB_DDR_12bits[MAX_UNITS][3] = {{0xFF, 0xFF, 0xFF}}; ++UInt8 NoMux[MAX_UNITS] = {0x00}; ++UInt8 Mux_RGB_DDR_12bits[MAX_UNITS] = {0x00}; ++#endif ++ ++/* DO NOT MODIFY, this table is used for transmission of the configuration to */ ++/* the core driver */ ++tmdlHdmiTxDriverConfigTable_t driverConfigTableTx[MAX_UNITS] = { ++ { ++ COMMAND_TASK_PRIORITY_0, ++ COMMAND_TASK_STACKSIZE_0, ++ COMMAND_TASK_QUEUESIZE_0, ++ HDCP_CHECK_TASK_PRIORITY_0, ++ HDCP_CHECK_TASK_STACKSIZE_0, ++ UNIT_I2C_ADDRESS_0, ++ TxI2cReadFunction, ++ TxI2cWriteFunction, ++ Null, /* filled dynamically, do not modify */ ++ &mirrorTableCCIR656[0][0], /* filled dynamically, do not modify */ ++ &swapTableCCIR656[0][0], /* filled dynamically, do not modify */ ++ &enableVideoPortCCIR656[0][0], /* filled dynamically, do not modify */ ++ &groundVideoPortCCIR656[0][0], /* filled dynamically, do not modify */ ++ &mirrorTableYUV422[0][0], /* filled dynamically, do not modify */ ++ &swapTableYUV422[0][0], /* filled dynamically, do not modify */ ++ &enableVideoPortYUV422[0][0], /* filled dynamically, do not modify */ ++ &groundVideoPortYUV422[0][0], /* filled dynamically, do not modify */ ++ &mirrorTableYUV444[0][0], /* filled dynamically, do not modify */ ++ &swapTableYUV444[0][0], /* filled dynamically, do not modify */ ++ &enableVideoPortYUV444[0][0], /* filled dynamically, do not modify */ ++ &groundVideoPortYUV444[0][0], /* filled dynamically, do not modify */ ++ &mirrorTableRGB444[0][0], /* filled dynamically, do not modify */ ++ &swapTableRGB444[0][0], /* filled dynamically, do not modify */ ++ &enableVideoPortRGB444[0][0], /* filled dynamically, do not modify */ ++ &groundVideoPortRGB444[0][0], /* filled dynamically, do not modify */ ++#ifdef TMFL_RGB_DDR_12BITS ++ &mirrorTableRGB_DDR_12bits[0][0], ++ &swapTableRGB_DDR_12bits[0][0], ++ &NoMux[0], ++ &Mux_RGB_DDR_12bits[0], ++ &enableVideoPortRGB_DDR_12bits[0][0], ++ &groundVideoPortRGB_DDR_12bits[0][0], ++#endif ++ &enableAudioPortSPDIF[0], ++ &groundAudioPortSPDIF[0], ++ &enableAudioClockPortSPDIF[0], ++ &groundAudioClockPortSPDIF[0], ++ &enableAudioPortI2S[0], ++ &groundAudioPortI2S[0], ++ &enableAudioPortI2S8C[0], ++ &groundAudioPortI2S8C[0], ++ &enableAudioClockPortI2S[0], ++ &groundAudioClockPortI2S[0], ++ &enableAudioPortOBA[0], ++ &groundAudioPortOBA[0], ++ &enableAudioClockPortOBA[0], ++ &groundAudioClockPortOBA[0], ++ &enableAudioPortDST[0], ++ &groundAudioPortDST[0], ++ &enableAudioClockPortDST[0], ++ &groundAudioClockPortDST[0], ++ &enableAudioPortHBR[0], ++ &groundAudioPortHBR[0], ++ &enableAudioClockPortHBR[0], ++ &groundAudioClockPortHBR[0], ++ KEY_SEED, ++ TMDL_HDMITX_PATTERN_BLUE, ++ 1 /* DE signal is available */ ++ } ++ }; ++ ++#ifdef TMFL_CEC_AVAILABLE ++ ++tmdlHdmiCecCapabilities_t CeccapabilitiesList = {TMDL_HDMICEC_DEVICE_UNKNOWN, CEC_VERSION_1_3a}; ++ ++/** ++ * \brief Configuration Tables. This table can be modified by the customer ++ to choose its prefered configuration ++ */ ++ ++tmdlHdmiCecDriverConfigTable_t CecdriverConfigTable[MAX_UNITS] = { ++ { ++ COMMAND_TASK_PRIORITY_0, ++ COMMAND_TASK_STACKSIZE_0, ++ COMMAND_TASK_QUEUESIZE_0, ++ CEC_UNIT_I2C_ADDRESS_0, ++ TxI2cReadFunction, ++ TxI2cWriteFunction, ++ &CeccapabilitiesList ++ } ++}; ++ ++ ++/****************************************************************************** ++****************************************************************************** ++* THIS PART MUST NOT BE MODIFIED BY CUSTOMER * ++****************************************************************************** ++*****************************************************************************/ ++ ++/** ++ \brief This function allows to the main driver to retrieve its ++ configuration parameters. ++ ++ \param pConfig Pointer to the config structure ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiCecCfgGetConfig ++( ++ tmUnitSelect_t unit, ++ tmdlHdmiCecDriverConfigTable_t *pConfig ++) ++{ ++ /* check if unit number is in range */ ++ if((unit < 0) || (unit >= MAX_UNITS)) ++ return TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER; ++ ++ /* check if pointer is Null */ ++ if(pConfig == Null) ++ return TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS; ++ ++ *pConfig = CecdriverConfigTable[unit]; ++ ++ return TM_OK; ++} ++ ++#endif ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_IW.h b/drivers/video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_IW.h +new file mode 100755 +index 0000000..1b8cd29 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_IW.h +@@ -0,0 +1,290 @@ ++/** ++ * Copyright (C) 2007 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmdlHdmiTx_IW.h ++ * ++ * \version $Revision: 1 $ ++ * ++ * \date $Date: 07/08/07 16:00 $ ++ * ++ * \brief devlib driver component API for the TDA998x HDMI Transmitters ++ * ++ * \section refs Reference Documents ++ * TDA998x Driver - FRS.doc, ++ * TDA998x Driver - tmdlHdmiTx - SCS.doc ++ * ++ * \section info Change Information ++ * ++ * \verbatim ++ ++ $History: tmdlHdmiTx_IW.h $ ++ * ++ * ***************** Version 1 ***************** ++ * User: J. Lamotte Date: 07/08/07 Time: 16:00 ++ * Updated in $/Source/tmdlHdmiTx/inc ++ * initial version ++ * ++ ++ \endverbatim ++ * ++*/ ++ ++#ifndef TMDLHDMITX_IW_H ++#define TMDLHDMITX_IW_H ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#ifdef TMFL_OS_WINDOWS ++#define _WIN32_WINNT 0x0500 ++#include "windows.h" ++#endif ++ ++#include "tmNxTypes.h" ++#include "tmdlHdmiTx_Types.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*============================================================================*/ ++/* TYPE DEFINITIONS */ ++/*============================================================================*/ ++typedef void (*tmdlHdmiTxIWFuncPtr_t) (void); ++typedef UInt8 tmdlHdmiTxIWTaskHandle_t; ++typedef UInt8 tmdlHdmiTxIWQueueHandle_t; ++#ifdef TMFL_OS_WINDOWS ++typedef HANDLE tmdlHdmiTxIWSemHandle_t; ++#else ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++typedef unsigned long tmdlHdmiTxIWSemHandle_t; ++#else ++typedef UInt8 tmdlHdmiTxIWSemHandle_t; ++#endif ++#endif ++ ++/** ++ * \brief Enum listing all available devices for enable/disable interrupts ++ */ ++typedef enum ++{ ++ TMDL_HDMI_IW_RX_1, ++ TMDL_HDMI_IW_RX_2, ++ TMDL_HDMI_IW_TX_1, ++ TMDL_HDMI_IW_TX_2, ++ TMDL_HDMI_IW_CEC_1, ++ TMDL_HDMI_IW_CEC_2 ++} tmdlHdmiIWDeviceInterrupt_t; ++ ++/*============================================================================*/ ++/* EXTERN FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++ ++/****************************************************************************** ++ \brief This function creates a task and allocates all the necessary ++ resources. Note that creating a task do not start it automatically, ++ an explicit call to tmdlHdmiTxIWTaskStart must be made. ++ ++ \param pFunc Pointer to the function that will be executed in the task context. ++ \param Priority Priority of the task. The minimum priority is 0, the maximum is 255. ++ \param StackSize Size of the stack to allocate for this task. ++ \param pHandle Pointer to the handle buffer. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWTaskCreate(tmdlHdmiTxIWFuncPtr_t pFunc,UInt8 priority, UInt16 stackSize, tmdlHdmiTxIWTaskHandle_t *pHandle); ++ ++/****************************************************************************** ++ \brief This function destroys an existing task and frees resources used by it. ++ ++ \param Handle Handle of the task to be destroyed, as returned by tmdlHdmiTxIWTaskCreate. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWTaskDestroy(tmdlHdmiTxIWTaskHandle_t handle); ++ ++/****************************************************************************** ++ \brief This function start an existing task. ++ ++ \param Handle Handle of the task to be started. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_ALREADY_STARTED: the function is already started ++ - TMDL_ERR_DLHDMITX_NOT_STARTED: the function is not started ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWTaskStart(tmdlHdmiTxIWTaskHandle_t handle); ++ ++/****************************************************************************** ++ \brief This function blocks the current task for the specified amount time. This is a passive wait. ++ ++ \param Duration Duration of the task blocking in milliseconds. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWWait(UInt16 duration); ++ ++/****************************************************************************** ++ \brief This function creates a message queue. ++ ++ \param QueueSize Maximum number of messages in the message queue. ++ \param pHandle Pointer to the handle buffer. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWQueueCreate(UInt8 queueSize, tmdlHdmiTxIWQueueHandle_t *pHandle); ++ ++/****************************************************************************** ++ \brief This function destroys an existing message queue. ++ ++ \param Handle Handle of the queue to be destroyed. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWQueueDestroy(tmdlHdmiTxIWQueueHandle_t handle); ++ ++/****************************************************************************** ++ \brief This function sends a message into the specified message queue. ++ ++ \param Handle Handle of the queue that will receive the message. ++ \param Message Message to be sent. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMITX_FULL: the queue is full ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWQueueSend(tmdlHdmiTxIWQueueHandle_t handle, UInt8 message); ++ ++/****************************************************************************** ++ \brief This function reads a message from the specified message queue. ++ ++ \param Handle Handle of the queue from which to read the message. ++ \param pMessage Pointer to the message buffer. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWQueueReceive(tmdlHdmiTxIWQueueHandle_t handle, UInt8 *pMessage); ++ ++/****************************************************************************** ++ \brief This function creates a semaphore. ++ ++ \param pHandle Pointer to the handle buffer. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWSemaphoreCreate(tmdlHdmiTxIWSemHandle_t *pHandle); ++ ++/****************************************************************************** ++ \brief This function destroys an existing semaphore. ++ ++ \param Handle Handle of the semaphore to be destroyed. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWSemaphoreDestroy(tmdlHdmiTxIWSemHandle_t handle); ++ ++/****************************************************************************** ++ \brief This function acquires the specified semaphore. ++ ++ \param Handle Handle of the semaphore to be acquired. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWSemaphoreP(tmdlHdmiTxIWSemHandle_t handle); ++ ++/****************************************************************************** ++ \brief This function releases the specified semaphore. ++ ++ \param Handle Handle of the semaphore to be released. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxIWSemaphoreV(tmdlHdmiTxIWSemHandle_t handle); ++ ++/****************************************************************************** ++ \brief This function disables the interrupts for a specific device. ++ ++ \param ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ ++******************************************************************************/ ++void tmdlHdmiTxIWDisableInterrupts(tmdlHdmiIWDeviceInterrupt_t device); ++ ++/****************************************************************************** ++ \brief This function enables the interrupts for a specific device. ++ ++ \param ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ ++******************************************************************************/ ++void tmdlHdmiTxIWEnableInterrupts(tmdlHdmiIWDeviceInterrupt_t device); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMDLHDMITX_IW_H */ ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ ++ +diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_cfg.h b/drivers/video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_cfg.h +new file mode 100755 +index 0000000..1a672aa +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_cfg.h +@@ -0,0 +1,298 @@ ++/** ++ * Copyright (C) 2006 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmdlHdmiTx_cfg.h ++ * ++ * \version $Revision: 1 $ ++ * ++ * \date $Date: 08/08/07 11:00 $ ++ * ++ * \brief devlib driver component API for the TDA998x HDMI Transmitters ++ * ++ * \section refs Reference Documents ++ * HDMI Tx Driver - FRS.doc, ++ * ++ * \section info Change Information ++ * ++ * \verbatim ++ ++ $History: tmbslHdmiTx_cfg.h $ ++ * ++ * ***************** Version 1 ***************** ++ * User: J. Lamotte Date: 08/08/07 Time: 11:00 ++ * initial version ++ * ++ ++ \endverbatim ++ * ++*/ ++ ++/*****************************************************************************/ ++/*****************************************************************************/ ++/* THIS FILE MUST NOT BE MODIFIED BY CUSTOMER */ ++/* Customer specific configuration is set in tmdlHdmiTx_cfg.c file */ ++/*****************************************************************************/ ++/*****************************************************************************/ ++ ++#ifndef TMDLHDMITX_CFG_H ++#define TMDLHDMITX_CFG_H ++ ++#include "tmNxTypes.h" ++#include "tmbslHdmiTx_types.h" ++#include "tmdlHdmiTx_Types.h" ++ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*============================================================================*/ ++/* TYPES DECLARATIONS */ ++/*============================================================================*/ ++ ++/** ++ * \brief Video signals that can be input to video ports in RGB/YUV 4:4:4 mode ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_VID444_GY_4_TO_7 = 0x00, /**< Video signal G/Y, bits 4 to 7 */ ++ TMDL_HDMITX_VID444_GY_0_TO_3 = 0x01, /**< Video signal G/Y, bits 0 to 3 */ ++ TMDL_HDMITX_VID444_BU_4_TO_7 = 0x02, /**< Video signal B/U, bits 4 to 7 */ ++ TMDL_HDMITX_VID444_BU_0_TO_3 = 0x03, /**< Video signal B/U, bits 0 to 3 */ ++ TMDL_HDMITX_VID444_VR_4_TO_7 = 0x04, /**< Video signal V/R, bits 4 to 7 */ ++ TMDL_HDMITX_VID444_VR_0_TO_3 = 0x05, /**< Video signal V/R, bits 0 to 3 */ ++ TMDL_HDMITX_VID444_GY_7_TO_4 = 0x80, /**< Video signal G/Y, bits 7 to 4 (mirrored) */ ++ TMDL_HDMITX_VID444_GY_3_TO_0 = 0x81, /**< Video signal G/Y, bits 3 to 0 (mirrored) */ ++ TMDL_HDMITX_VID444_BU_7_TO_4 = 0x82, /**< Video signal B/U, bits 7 to 4 (mirrored) */ ++ TMDL_HDMITX_VID444_BU_3_TO_0 = 0x83, /**< Video signal B/U, bits 3 to 0 (mirrored) */ ++ TMDL_HDMITX_VID444_VR_7_TO_4 = 0x84, /**< Video signal V/R, bits 7 to 4 (mirrored) */ ++ TMDL_HDMITX_VID444_VR_3_TO_0 = 0x85, /**< Video signal V/R, bits 3 to 0 (mirrored) */ ++ TMDL_HDMITX_VID444_NOT_CONNECTED = 0x100 /**< No signal connected */ ++} tmdlHdmiTxCfgVideoSignal444; ++ ++/** ++ * \brief Video signals that can be input to video ports in semi-planar YUV 4:2:2 mode ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_VID422_Y_8_TO_11 = 0x00, /**< Video signal G/Y, bits 8 to 11 */ ++ TMDL_HDMITX_VID422_Y_4_TO_7 = 0x01, /**< Video signal G/Y, bits 4 to 7 */ ++ TMDL_HDMITX_VID422_Y_0_TO_3 = 0x02, /**< Video signal G/Y, bits 0 to 3 */ ++ TMDL_HDMITX_VID422_UV_8_TO_11 = 0x03, /**< Video signal B/U, bits 8 to 11 */ ++ TMDL_HDMITX_VID422_UV_4_TO_7 = 0x04, /**< Video signal B/U, bits 4 to 7 */ ++ TMDL_HDMITX_VID422_UV_0_TO_3 = 0x05, /**< Video signal B/U, bits 0 to 3 */ ++ TMDL_HDMITX_VID422_Y_11_TO_8 = 0x80, /**< Video signal G/Y, bits 11 to 8 (mirrored) */ ++ TMDL_HDMITX_VID422_Y_7_TO_4 = 0x81, /**< Video signal G/Y, bits 7 to 4 (mirrored) */ ++ TMDL_HDMITX_VID422_Y_3_TO_0 = 0x82, /**< Video signal G/Y, bits 3 to 0 (mirrored) */ ++ TMDL_HDMITX_VID422_UV_11_TO_8 = 0x83, /**< Video signal B/U, bits 11 to 8 (mirrored) */ ++ TMDL_HDMITX_VID422_UV_7_TO_4 = 0x84, /**< Video signal B/U, bits 7 to 4 (mirrored) */ ++ TMDL_HDMITX_VID422_UV_3_TO_0 = 0x85, /**< Video signal B/U, bits 3 to 0 (mirrored) */ ++ TMDL_HDMITX_VID422_NOT_CONNECTED = 0x100 /**< No signal connected */ ++} tmdlHdmiTxCfgVideoSignal422; ++ ++/** ++ * \brief Video signals that can be input to video ports in semi-planar CCIR 656 mode ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_VIDCCIR_8_TO_11 = 0x00, /**< Video signal CCIR, bits 8 to 11 */ ++ TMDL_HDMITX_VIDCCIR_4_TO_7 = 0x01, /**< Video signal CCIR, bits 4 to 7 */ ++ TMDL_HDMITX_VIDCCIR_0_TO_3 = 0x02, /**< Video signal CCIR, bits 0 to 3 */ ++ TMDL_HDMITX_VIDCCIR_11_TO_8 = 0x80, /**< Video signal CCIR, bits 11 to 8 (mirrored) */ ++ TMDL_HDMITX_VIDCCIR_7_TO_4 = 0x81, /**< Video signal CCIR, bits 7 to 4 (mirrored) */ ++ TMDL_HDMITX_VIDCCIR_3_TO_0 = 0x82, /**< Video signal CCIR, bits 3 to 0 (mirrored) */ ++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED = 0x100 /**< No signal connected */ ++} tmdlHdmiTxCfgVideoSignalCCIR656; ++ ++#ifdef TMFL_RGB_DDR_12BITS ++/** ++ * \brief Video signals that can be input to video ports in semi-planar CCIR 656 mode ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_VID_B_0_3_G_4_7 = 0x00, /**< Video signal blue 0 to 3 then green 4 to 7 */ ++ TMDL_HDMITX_VID_B_4_7_R_0_3 = 0x01, /**< Video signal blue 4 to 7 then red 0 to 3 */ ++ TMDL_HDMITX_VID_G_0_3_R_4_7 = 0x02, /**< Video signal green 0 to 3 then red 4 to 7 */ ++ TMDL_HDMITX_VID_DDR_NOT_CONNECTED = 0x100 /**< No signal connected */ ++} tmdlHdmiTxCfgVideoSignal_RGB_DDR_12bits; ++ ++/** ++ * \brief Video signals can be mux each others using register 0x27 (MUX_VP_MIX_OUT) ++ * Whatch out that VIP output shall be GBR: green on [23:16], blue on [15:8] and red in [7:0] ++ * this is done by default for all video mode but RGB_DDR_12bits where some extra mux is needed ++ */ ++typedef enum ++{ ++ VIP_MUX_R_B = 0x00, /**< internal vp_r = vp blue */ ++ VIP_MUX_R_G = 0x10, /**< internal vp_r = vp green */ ++ VIP_MUX_R_R = 0x20, /**< internal vp_r = vp red */ ++ VIP_MUX_G_B = 0x00, /**< internal vp_g = vp blue */ ++ VIP_MUX_G_G = 0x04, /**< internal vp_g = vp green */ ++ VIP_MUX_G_R = 0x08, /**< internal vp_g = vp red */ ++ VIP_MUX_B_B = 0x00, /**< internal vp_b = vp blue */ ++ VIP_MUX_B_G = 0x01, /**< internal vp_b = vp green */ ++ VIP_MUX_B_R = 0x02, /**< internal vp_b = vp red */ ++} tmdlHdmiTxCfgVideoSignal_VIP_OUTPUT_MUX; ++#endif ++ ++/* Audio port configuration, bitn = 1 to enable port n, = 0 to disable port n */ ++#define ENABLE_ALL_AUDIO_PORT 0xFF ++/* Audio clock port configuration */ ++#define ENABLE_AUDIO_CLOCK_PORT 1 ++#define DISABLE_AUDIO_CLOCK_PORT 0 ++/* Audio port configuration, bitn = 1 to pulldown port n*/ ++#define DISABLE_ALL_AUDIO_PORT_PULLDOWN 0x00 ++/* Audio clock port pulldown configuration */ ++#define ENABLE_AUDIO_CLOCK_PORT_PULLDOWN 1 ++#define DISABLE_AUDIO_CLOCK_PORT_PULLDOWN 0 ++ ++/** ++ * \brief Structure defining a video mode ++ */ ++typedef struct _tmdlHdmiTxCfgResolution_t { ++ tmdlHdmiTxVidFmt_t resolutionID; ++ UInt16 width; ++ UInt16 height; ++ Bool interlaced; ++ tmdlHdmiTxVfreq_t vfrequency; ++ tmdlHdmiTxPictAspectRatio_t aspectRatio; ++} tmdlHdmiTxCfgResolution_t, *ptmdlHdmiTxCfgResolution_t; ++ ++/** ++ * \brief Structure gathering all configuration parameters ++ */ ++typedef struct ++{ ++ UInt8 commandTaskPriority; ++ UInt8 commandTaskStackSize; ++ UInt8 commandTaskQueueSize; ++ UInt8 hdcpTaskPriority; ++ UInt8 hdcpTaskStackSize; ++ UInt8 i2cAddress; ++ ptmbslHdmiTxSysFunc_t i2cReadFunction; ++ ptmbslHdmiTxSysFunc_t i2cWriteFunction; ++ ptmdlHdmiTxCfgResolution_t pResolutionInfo; ++ UInt8 *pMirrorTableCCIR656; ++ UInt8 *pSwapTableCCIR656; ++ UInt8 *pEnableVideoPortCCIR656; ++ UInt8 *pGroundVideoPortCCIR656; ++ UInt8 *pMirrorTableYUV422; ++ UInt8 *pSwapTableYUV422; ++ UInt8 *pEnableVideoPortYUV422; ++ UInt8 *pGroundVideoPortYUV422; ++ UInt8 *pMirrorTableYUV444; ++ UInt8 *pSwapTableYUV444; ++ UInt8 *pEnableVideoPortYUV444; ++ UInt8 *pGroundVideoPortYUV444; ++ UInt8 *pMirrorTableRGB444; ++ UInt8 *pSwapTableRGB444; ++ UInt8 *pEnableVideoPortRGB444; ++ UInt8 *pGroundVideoPortRGB444; ++#ifdef TMFL_RGB_DDR_12BITS ++ UInt8 *pMirrorTableRGB_DDR_12bits; ++ UInt8 *pSwapTableRGB_DDR_12bits; ++ UInt8 *pNoMux; ++ UInt8 *pMux_RGB_DDR_12bits; ++ UInt8 *pEnableVideoPortRGB_DDR_12bits; ++ UInt8 *pGroundVideoPortRGB_DDR_12bits; ++#endif ++ UInt8 *pEnableAudioPortSPDIF; ++ UInt8 *pGroundAudioPortSPDIF; ++ UInt8 *pEnableAudioClockPortSPDIF; ++ UInt8 *pGroundAudioClockPortSPDIF; ++ UInt8 *pEnableAudioPortI2S; ++ UInt8 *pGroundAudioPortI2S; ++ UInt8 *pEnableAudioPortI2S8C; ++ UInt8 *pGroundAudioPortI2S8C; ++ UInt8 *pEnableAudioClockPortI2S; ++ UInt8 *pGroundAudioClockPortI2S; ++ UInt8 *pEnableAudioPortOBA; ++ UInt8 *pGroundAudioPortOBA; ++ UInt8 *pEnableAudioClockPortOBA; ++ UInt8 *pGroundAudioClockPortOBA; ++ UInt8 *pEnableAudioPortDST; ++ UInt8 *pGroundAudioPortDST; ++ UInt8 *pEnableAudioClockPortDST; ++ UInt8 *pGroundAudioClockPortDST; ++ UInt8 *pEnableAudioPortHBR; ++ UInt8 *pGroundAudioPortHBR; ++ UInt8 *pEnableAudioClockPortHBR; ++ UInt8 *pGroundAudioClockPortHBR; ++ UInt16 keySeed; ++ tmdlHdmiTxTestPattern_t pattern; ++ UInt8 dataEnableSignalAvailable; /* 0 DE is NOT available, 1 DE is there */ ++} tmdlHdmiTxDriverConfigTable_t; ++ ++/*============================================================================*/ ++/* CONSTANTS DECLARATIONS */ ++/*============================================================================*/ ++ ++/* Number of HW units supported by SW driver */ ++#define MAX_UNITS 1 ++ ++#ifdef TMFL_OS_WINDOWS /* OS Windows */ ++extern tmdlHdmiTxCfgVideoSignalCCIR656 videoPortMapping_CCIR656[MAX_UNITS][6]; ++extern tmdlHdmiTxCfgVideoSignal422 videoPortMapping_YUV422[MAX_UNITS][6]; ++extern tmdlHdmiTxCfgVideoSignal444 videoPortMapping_YUV444[MAX_UNITS][6]; ++extern tmdlHdmiTxCfgVideoSignal444 videoPortMapping_RGB444[MAX_UNITS][6]; ++#ifdef TMFL_RGB_DDR_12BITS ++extern tmdlHdmiTxCfgVideoSignal_RGB_DDR_12bits VideoPortMapping_RGB_DDR_12bits[MAX_UNITS][6]; ++extern UInt8 VideoPortMux_RGB_DDR_12bits[MAX_UNITS]; ++extern UInt8 VideoPortNoMux[MAX_UNITS]; ++#endif ++#else /* TMFL_OS_WINDOWS */ ++extern const tmdlHdmiTxCfgVideoSignalCCIR656 videoPortMapping_CCIR656[MAX_UNITS][6]; ++extern const tmdlHdmiTxCfgVideoSignal422 videoPortMapping_YUV422[MAX_UNITS][6]; ++extern const tmdlHdmiTxCfgVideoSignal444 videoPortMapping_YUV444[MAX_UNITS][6]; ++extern const tmdlHdmiTxCfgVideoSignal444 videoPortMapping_RGB444[MAX_UNITS][6]; ++#ifdef TMFL_RGB_DDR_12BITS ++extern const tmdlHdmiTxCfgVideoSignal_RGB_DDR_12bits VideoPortMapping_RGB_DDR_12bits[MAX_UNITS][6]; ++extern const UInt8 VideoPortMux_RGB_DDR_12bits[MAX_UNITS]; ++extern const UInt8 VideoPortNoMux[MAX_UNITS]; ++#endif ++#endif /* TMFL_OS_WINDOWS */ ++ ++/*============================================================================*/ ++/* VARIABLES DECLARATIONS */ ++/*============================================================================*/ ++extern tmdlHdmiTxDriverConfigTable_t driverConfigTableTx[MAX_UNITS]; ++ ++ ++/*============================================================================*/ ++/* FUNCTIONS DECLARATIONS */ ++/*============================================================================*/ ++#ifdef TMFL_CEC_AVAILABLE ++ ++#include "tmdlHdmiCEC_Types.h" ++ ++typedef struct ++{ ++ UInt8 commandTaskPriority; ++ UInt8 commandTaskStackSize; ++ UInt8 commandTaskQueueSize; ++ UInt8 i2cAddress; ++ ptmdlHdmiCecSysFunc_t i2cReadFunction; ++ ptmdlHdmiCecSysFunc_t i2cWriteFunction; ++ tmdlHdmiCecCapabilities_t *pCapabilitiesList; ++} tmdlHdmiCecDriverConfigTable_t; ++ ++tmErrorCode_t tmdlHdmiCecCfgGetConfig ++( ++ tmUnitSelect_t unit, ++ tmdlHdmiCecDriverConfigTable_t *pConfig ++); ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMDLHDMITX_CFG_H */ ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/docs/02_sw_req_an/tmdlHdmiTx_API.zip b/drivers/video/nxp/comps/tmdlHdmiTx/docs/02_sw_req_an/tmdlHdmiTx_API.zip +new file mode 100755 +index 0000000000000000000000000000000000000000..e4eebeb934798ab9e68af4b1e52f105e10827bb9 +GIT binary patch +literal 131083 +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 +z#N(}|pok&!4G93v +z-3=j*pbJ*i%5EJ9Fx{_d3UKc1TDY3FOsUWtedD2kfY1^z)b)NDFE$$`Xf7~X^6m86 +zy4tx8f$A)$#7rcNP|68Rk2OO0#+qHJuJNcudx^0P3ohj@MfTp&{U2GZvO)wH0yqHB +z_?Q00eKoT+u(mU^qc^iK{g?N3I_XXWB@Ad(1e-A;mE2*-pLH0O3`|;N0&&X}EK!h> +zE;z6nwN)sAx@R>0q%oEn21z-FRw3voyD+#ANN%Rabu&lzG%x2xzS)k2-L+|LSLLP? +z#rCmFcl$-xNoVXQ#{0+DXV1-h*Gsiy=LCC;Co1_c$lt3|{3LqWO^60Qjc7?x28X;R +z(x``-e~4nyEyyc%H(n=ZdVt&@bc~E#wM9@r%A_tV;}wuj*q0!=gdmPADJa|;j!b2U +z=2K6MFAK5nKP8Gti5L_ExsCCh#@r>T_(yO75jtf5&K>xKG(u#TFu25+mCT6{k#-*x +zYKSSY;ROh?9~x0!iWwo0P^uG?P_M+3NqI6#nLsiu2{zP_86tsI)XB)MDcq39M2b)f +zSxgBtP>L5RYDAG)NGX|e9CkCkQ;c~Yi9(g`<=0t9(ma2FJFA`V=dY?W|P2%51_ +zNrpJ#2Ui~Hd;_f@;-Lbmm=dYc$QUyv&a>UK5bLxnWMJO|uiWC7d(Twiyg4daGA3P} +zZu~D=&I~b!0#GVL%wsS@z#=mWF=QYy^8GzLWehPDX+%8ec#s8PrXI=$(~vYG1*{9B +z$fN-#|24cs)3uq1N&Mq~cSnDTQmsW7HqC3b8H9=R8(RII;N +zL=lkK9O4fl2a})e=<=hC*$3{KSHXLvu_%-4`wsr3R8Z{5pin|}Q^0}oq()jm=?NLP +z2;VQL)Tw`VFiRV_VtKL^fZJ#V<3~6nCDQnDWt=d;~S}aqmI1oZ`32+hU0;Ms< +zX0ULCE??hYrCrHkgc?uHmCM!Zh^Qs0|19^;c}W%ijx9I3DDCXYF4MVB-DyjDPptH9 +z$S*0(uP-}`cQ$jrD^@*0H>u_2=JfLRsya~L{4-nbWPrdrO1<6Y8qA5CX{jmDQ$Ahm +zPPg&{U7A|OwvxtSvbeEC0v}C!u$S&N$5-Maefd=0rRUFx#gRgub@$i4qJB~$S8knzQ)UOq188L3%K!eFM|5}PGwUm +zicW4aKyT4L*L%f>Q1HjvO^Lj~i|lmLmd29+!JjM!){k6jw9jSn7Y#q_axI-##of=7Aj$`pStafdTmCs?TUq5ZEeR_r~Z>mTJ8Qn +z@fu85eGj3^;$&3?!+KVJ?l_hBCZAoZFAmqP$1?JT`tm-xY~OBSJqGz`pr>r* +z;zU`&E96vPujqcP4Jp(9K$Ev&==8aMU7gF5=T}5a{odFSaPH;5jRJN$W=|<7I*2VD +z3W9sWR +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 +zi_(zHI)%9(RbC@{5~ +z?#w(^mW7XF;FQDe>+Z^k;0z!EJmnHhpHja28w4iTS6sZqN!q0gN6x=CHfzVP(Bg>2 +z$@28=pxuY43z@r^)+ab+u$oLTIFhxua1JSp?OX`?EV=~f`Ufvdv^2^3Bk_~6r#)`k1foum2WVfa= +z?KUmXjoDi}J}Tp!DHX{3D;lqFwnu0>hq+@~)AOQzh4w#}&{D`{r^ou@;caGL!3W9o +zND%3e{G0hMJRFBMMbGG@EOOzZX6>rVtM$FOsI#`6Z$|~#@UfV1h*;(lo5^OtLE7eF +z;3ZMnULv3L=ofgH`SewFCkxUk#LSwkt;k*4XZ$y;LrSj*BA5nhueK)k$+Bp5?=xt? +zH#E(NhL-V)Lg!j}Jn?5^esy<$$a^~xL{Qd3_j(__2kzIJ6t45qf699HAHWO!+7DKl +zpfTW7L4(M@)U~`}_|S^{p->brWmwPQD(P2%fB)k5MRm6&!O!Db@J?N=rFrFD>A$2D +znRTZ#?6~{(i$?MdUG(Dm3bE>2g8vO%h&cGl06Bw8Z$%Sht0P(6QhFd2s4DFO*&=(H`}%|2;ONxIA|Rt6=kE1W>^#769|2i=f^Rjmq@g)*(S{uOkhWZW{c{U +zXYr2DtMk15ZUFjsFZG2QJ#bY(O91*8xKsp6Vxc8&@-J*$i2f(iWJXq1xLg|iHbGat +zHjBHL4yzbM?`w2r|9U>%CL-j4r~^#B&+Ij1*jF=eds1D&D*Z1IDp{Qadqj<$jOL29 +zH1v_CaWc2=bB?RJcYrgqHS(Q)T?#1oB^d}(y9Ps{sgC>sKRE=R*1}Un`DcB`%xV0C +z>Xa;n~Oe_AM^lNXp=&2wPUF-ebeOrnbuQ24Nc^kPCO{ki>azu(GC7s#7J!U_i_Ww}wNH4tyWX1v)iKlSo +z%mxjFMCsAgySg|kHBaW3-oI&t$F8Hf?I<-^nM-#jfIJ~AVJxF%vnltSuzZxDUU_6* +zeRYYMsu7JLXDw6tM7PaV>a!hj8^4|Lm%Okttw@==iS-#*l%%#iE9>ZGvF5gi6Zdm$ +zrD61(UQ8)=e7_`qeP87&vKZjp6X +z{lA#rAnD4`oBCb*Ed4+Q*K+I2Tkhq)5dI6O|0C!6??4^*-{f58{~fLW&xGqgX#GEE +z{Xb~^KWP0wX#M{WwEkb<_`i4S{v9~}pDnxp>8t)3W5mgfdT~p@c#`Gu(17U;{IQwKL0bm#Hen_Z!#kKoY0h{uD5Qcrb1_m +zRs{Q3mo*`Gkx=ByRdKsodQFxX?A&pKxvHJ=o0xjXo=go>c?p!gf&RKoi24zKR;;1v +zccMHP=>`e)DpZEUH15Xs#6%i~b99-vSthNH6jPz!|EK98%O8YiT3DMn +z{d)shR+F>aV1(^{(Xa<@(XpmjmDpGVhX%D_t`hV=W`_;2W@=H?njkHfd%lp+aY!u +zz-Xi@aOFFy|KhMatWpu-=Ju+N@!IWr@-Wr5ZSu8;;P( +z8s`r3=(Qc0xzop6*?4Dp;P4*j4#u=rF4WR?tXS6*-fgmXq1;zGf2jq~=y_T+ZOr;m +zDMe@;RVP!mod?wpTuS};pwzK>Xu?09C7`<`q8NqJ20il+B1TCEvoHQ-42`g`qNo`G +zgLo=UlZF@Zu=GHTDsfJggTZ$R|Ac3&*;5!;QCdIf?4@lterc_=#Z=HovJGOU-ZEq} +z*SY}tvE8AP6S)J}bZQnx#=1$N71Z>Ib5#gY4-To{wF>_8x_^1;43~8GgnFE6wIZn? +z+)?Ks`}h@jbYL;a1&H<{Dh^U=1eDvbPBkvPXs +zXO*ADEa=zx7w^^=-gTlJQm@=N}Kg+F73y!N51wU|8 +zAmfd03X#|ry4g1}H6RVzz_q1jW+Vt^k`x%FL&pj9{p0;r;Q{bS|1 +zAFG*DBB^~g|0wVGuy-nP7PD^ib2zwz +z`Teuw^m*yP_E^suIl-3B}2*S3L! +zN~0l+<;AeWg?ocPaSaZF1vaVtJOU7~b^)ysa(P0N@y*H&j{Vhc*7*aWj)P=0%ieP1%fbB!)pB5dzTaY02|G2he`q3A_ +zeSIvP^+`;WlV*xD?(}I^allOUUwP`i&^dEcqV8jt4M6}KN+)A$eKX?EH#h4E&Yxvo +zY4=kMaBjwfJ=q}l*?HI83*_4p@9CNcb>;AqXZGc!PAW2xsoAIwnX@*J(Rx9kT$weJG2f!R>@MBmZUS7=CZ0*+f_|1N`;YVn +z3zH6*gm#2$(T8IiFoT&M=z*L{SU2k!(~b{>YX{`XU~{hO-Wmtsu1gb^O9Q<>F11ce +z-cE#juo>AyV-W91wn(ym_})Rd$3DQ<^ltaLyvV%3bt$N{u?0cfmKQjNglR2rRIc!_ +zY$%ewiy$cx@(z5<33;d5w$cz4Bv#k87L4E~7J%6o)XUO~(PJ%(+E%2SJ*7vF3Y*TR +zZeA7oix=nbGDRt-C!m@Hpok37ZywCc>;emu-!UeW^Rj+y8b9MOs(Bbm54}Z5TF$u0 +z1D$eXKzGA;woUSq5xJ&zI}2`{Fv3UNPG +z1;3MGu2%AqHyKIhW)?>~(4!MqvsCO&gcwwDw+-X3Te05;A9caDS64;Hq1qUy(_>mB +z2!x?f!?UF+0(Wx{za3e>IR#~a=LQ{Z%n68jb_5^Hb%R{90$b}_594a!^$m?ar8aR2 +zpQDSXd1o{%0A1+hyj*+z{PX7rT-t$xO1jj5n(2(Ly41z94qa7%8A2p_8l`xyCeSv3 +z>5ZZTJT&2chTFfAV$n6j3Ny{?yzlV2CJJLG>-?kNZK`%?9)42~b)up}8)?Q#+j>iv +z3V;E%2LrwM`Ki3T80nn5B74JCF@ +z75>ugc*$sB(#F%r!A0N;kaV^j#$&z)&$N|Sr%;kdeagWlK|Gl-X*o3fR{K`wkyZ_#u|NZyB8=&92CF~D2RU3f? +zsS2c&&kX42HDIJBFtJutmJ(Jk%l=bL5&XCVOZ*GtV=mbSGUdw3*E~m2r?+BviJ}SR +zpt1elDG97_urzK7FisVtjr8EJ=VrhUo>F@ZRm%25Tm+t> +zPwCmHY>YL0`T7p)x?bdNsRCzmblW$mBFVDXi1-61Z8=$0QW{QbqLFxzWdwVDf8=ni +zkr=NTOUc?_p##O0uodR|=H^~obmyTWEEf6!ZhetMNWKuBXNl=c=9TUkGkvl7hJtQd +z2~NiA!WT(*^87EHbKyvCnR3N<@if_i2OkYn$(57=_TFm{HwZsD8YV5Wy}^=bvA
7!Z +z?|Mn(4RQjd?fE=@5%L0m=WHG|`UP~r43bL0&}->!!bBnJVyt;VGv8gHC+`N& +zJAnshsJeFyPWEU=O3!1tb=wRzH*S4l36o?@vJyy;Nl5SCQdObu6`@%HO3A}!wey|yV+iufF|| +zZUjY&C6b*TRv~zd4eI-b=YQgV=_iCq`UnvCkX_N2jIp&28u(0+*f(U>#Xj-R2xQVJ +zvyNemPZ+5ruFmf<#d;jC@IcYnqwH#;JK8cW= +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 +z-eSrHu7V1W@t@OH}+rgMI%V~)%&M7-3YIOP2 +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 +znye^lr(WFLjp55xIW|(FrtwKv8-z%CDJ +z4bM!F|K+enSKVC$>KG7r|4|ObNm~18iSEGE%QG>|I+#FXEle{OhixFiR!o>;qy|?< +zGGY}*`kEG^=FsZd$?pLF9P_iEP0X5>j)Q+#=D_AYXgtaWFCFleefTwAs`=)A(gpGH +z>r(P@44k#fmi^i;Zq1y@AtvPPk-X{?u(ge|5wXoxca__{M4@t5?RXY#Ah%|A8n-j^RN*>s?9j3<0;|VYseePv|?@br0LX}`R(O0^lRwVt$_TC>>RSg{>40!>s2Ro--XJdf6sqmgv=r{QeW#W5a6hnsxK +zACAIKZHA?@b~m82hH^BYK%%pblshhrM#gTX&lA%uelnBt6VrTpG6P+$X;JOq|MutE +zs8N~FtS9Xifi?Td>{z;0dXj}u;*=Qoqbg~IEp=cE09Kxk$B=`23PR8q0GD>QH4#Xr +zW`R&j8@sYdWA-8dE#KX``GPGC;T#BM%*8r_#h>nBH +zi)>o*e9+*OIN)e9s`~Qs|9*p`UFx(cuy`l``7>o$kQ=};`gv0vE-wdc5lhWhy`FDi +zUO`J0qGc^#$GG$xEm4hvV>OTO7r6h{!*5h0w?lu_86^2Q!xTsboI0L3tRr9iuz-P& +zYht-LS9;b`m6_N5JOWh-xj6P*f~o?76=3kT)6f8->%f432NA(_|A0ntaPy#m02K;~ +zG%>-xzcApzKzTcJ)e|G~H&aW_H6rMw^M7!u;yKRbpn9QGq_Le#4+=zasi4BSyc*OV +zC7sH6AJxti|m2ahU|?N07^G(MCIAH}`Yv2s*6%TN^W +z%uD(pZ~B%9!8r!w2c7&uiGNTW#ydHbgHd6b_Aa{gTroV01hPB1tG@gNVb9u9i7<{u +zFg*KGD3(3BL_VZYP1ZHA$PRkf+SdPsy9dX5dmECTtNBnZwcG6^qpQ`RNeTn)`{j(5*pJc`=_VyC9f8yI{y1ZDtNc +ziAM}Z;5M_DyaFz_vc3ghw`XfGPo3@I`kwxN?V;pc&HFgLOHKCUBd=P<~bqiK@pfLL=@UaA=$>+a_%4C;Rl!}(O67R(c(}x(LcHz +zXv{XPP!?~VE$3XzA7&`$>?4}I^Z``_4xZ+fGjq@o$fNv4!Ez1}aX!y#l$~6?Hm1sb +zJH!Kg^ee0Sx_&wQoz4;fV3M{>jw5CP(u(nn>saayXNQ#nV8@hP +zMGGiBiyD-B79cKl&4rz9VQ4wq0+G(jRMfoBEq0BWBRkusFMc+y$UsVNA52nvC*BuG +zZrdvS!TYxT`IWV+$tvD3R` +zGbLUm43a(Nf#uz^{)-KP2w-{k-lD=pEq|U98NMKfrq$ZQmGW!$PX}ME580~D2o==Fc7W5)?52%IFNle8bEE+7GR=seqkVq}0on6aY- +zD`J&*NiH~4FvP+L7DP#my=waEM2I#B+2^=O*AVM4&tNpOL??x{h(iGF~35zSTs>5k6@^CBh{@vXU> +z!8dkszda+Wu$rTvc=dK^$^0m_WcWunwlzv9@nk)&1=6d0I2K8Z2`*l*tF_|;M93Nuii(9`KI!CDFjBaW9i19u%VNOQ +zJ(uQJ(BX&>B}y+~LrQqLo2B%>Pf?T +z5-@gg7IDo7lK`^o<;ALb9%B9~A;bHE%Qk8Va+ii8j0Y-=w*cy{vQ$5$-PW!x`}_R0 +zo+w8Wh3?z&PuEP1#&r2Vq^pAj9k+>2_tjsgb7SFt#7>yjl&tE}Ml5 +z*IAIKf;UB8eCv|4X#=sB%?T*W89AMoE|B#gdy@WwLhUjJrjUg{z`)%Lh$I+ZY(r3u +z+t*L(to!Bo2DOt#xaNt`*SCq))~(jxQCLv6P@O~g!M*;2?;@DpU|7#nEKbdQ}*zUS?Qb|ae) +z(5&rD!G7SKPsW$`)2(MB1LUVpC0WbT;PaYLP|nRX{Y?FY?}fK^o9b7w)?3cSKUI}E +z%s7A3oAGF2*LaoOj7%YKU1YvadRm(x!UL2SvW9Ck+vJ`cb7rZ{{>Kj@!2nW`^qno#tGbE2ZMCm#n4 +z7vbEb7Jv!mYkj^6g3)v)kcr^(I%pE+J@fIDT9OixVa2$TW#saupz1Db5%{j-z3m*{ki*-b*C-KK +z$7(I_}&oEf2m9PS3};i|3Wp +zwfo+em^8q+DoMzpS#uj21c6P6cHKaPv_f5A9mEDtQ-Eo2$z%> +z^wqqBHd{)%vk$$C-9flu61M(ak|sxxF1@VzzFd?Sp~&Ue$t83cU;%1$Ub! +zn5Kmi>C57YKMQ+_UQzL6;3@HBq{Z=MOBlp(naq4!;)y0v@x=~2#4<=C#MWvcZnnfS +zj3UHU++Te*#Iw;X$%QKL`*5P^E1q@n#YznGNmr(YWqfdN)wmk!bJlDcm+z(26DcR1 +z;#tDdjTpB5Hefb|xL4A^ChIZ$A9R&W3oOqj>Ay>ii +zcc4PGCR^ZK1~jz$H(J8dT_*703wDr@i#JL^q;la4b%3qHcK&l2+cDYcGEY4)0J}`s +zU7GM*pu^mP>Eypm&~KV}pQjV7)R6sk%C-g7M^~puN=8}ND}sHgvj&(roCib@{d#yr +zyZE~m-ub>NRerZ`w;jYEjG!}7xxR_gWKHzJJDczYYt$#2++S-TK3e*ALhFX4 +zAD2aWK{|ZrH_;6DY;=-vx#6m5)as)nLs{`UaM!%qIXDz+z~l`6VPJ1q9ssYG*Qec& +zz&WI&PgB!AYNDlYCec04Nr+fjv)7Djl^ +z+FPL*-e!LP551v}6wfX^2ZPQYgDzaBRcVTF2#}Ta_lb#0rHQps4UCE?JSdDrfj9w( +zAOW!~QT>upuL +z_gLXo$CP3C;XfSI=C;I_;ulkgZ#(=yTYsZ4~I|wo9a0Go}sol7BQ)ig1gcI@XcYp9MIs@UDjW?O5#zzA(e1 +zd_|-C_zUW8Y-@?#e|^d4qPJmwpXkv$*nSjn;`;kK*`ZsBF|6R%RBv@XH;qyWzuV}9 +zl(j+kjOplP>JII-U#g`SjI{hbdV6JTfnsoDb~g(b^#4u|9c4>Dm$k}scVwGJDG~aB +zAhF#fkbc#NnRf^SDB(62&~Chzv03$FakufPs}(uuRNBygx4~@OK3&p{<5PEJZPO$P +zHT7IfIY%0|sZ9eiIds3yd%g|t4yX6RAx*gVwsdv0*HiaC$t#}tyWCyvF?oAGwE%Da +zF-*!DKAy-qNmm0pS29pom5JRHjAJK}^E|ZP^6Ob<;*>Iyx=Hn@Cvo7`*AZf}7rJn( +ze}KCsCB@Jv8s5oi=#!vf@4^7X7>gLKpcSu!LypKiDz|EL~_q^>)O=$;g +zk(+>wsxAS=CMp3HQ&bq#tE3s +zY{^p^HV$Y0bOE#FQE6i#Du*xlQS`e0QSLv&dNT7H%&~QCiL?tGi1ucGzXYVxuhE|$ +z3jg~|{k%6n(zI#Y?(uqUa&ZH4$E#w6o2}njpBJF5V5v`0Hi=4E;!H_da)W91SPZDb +zYu7vfS;OFe<3q;Z{(5}^=-RphXD@_KVSg~Z^JRQ%ql8(`n0Fpks$l3eBQCjF_g6AR +zuhb1mGRMx=70D;`QJV-%?Tp5J72w4YOTl^QL9&{Ia8K%_Hl?bZ+GG-u4LZmX$Fiw4 +zV3!JS_se>|)0P9lTX+FMS~~B3elrkGKm|dq-PW&UBq!}OA$+QVw7WIk)9@img#^+Z +zo7=}70v-klNXrl!`ePLdCxBs?VAzFbdXihVYr5#JF&ED8N2)fucJs`7ons@#jY+IU +zsE9|A%A%se#f`zJiIR~f!<0maMGBdS7&&8r%gLDo04kFa((@`&$DY|f?7A;y`3ja% +zZ`B4*{s2k;})-^p#Z51EuuP11IKa!TP95s3GzK@)*9m*qS4< +z$u`rq*XvtCk}7J&-MW=IZ)3B`8?oDXVNwg0zbtRth?rIQJN6C}-|yDDV-L>_n)q5m +zKbtHveEfuc`UrJ&^ia?C`8zz40sNKA8%KBlnb=zXa?`Bz@*i%wzX0@e>fosAem9~F +zd@>(9xVwI`lpo9xY{}_nZZ93vn+&bwLZmWp>-*>=-`5m}o*vxSt1Ywe5ue%x%?)z& +zw-bY7?#C)fB{2%@P4|i4shaUOjvF*V!x3E5hDxgxWqn?&(BZD}LZ~)uM<18eb>^g7Rz#(HZne;BmcmV37WlMlr^bDk0nQy`P1vmS3Ge +zD?#g(-|4kqma0-aAIpKMcfF +z`3}oS0~H4;23ihBkz3G=d5dmB%Ml4bmYpM20+6fX%5r2h9o*vxv9}f@N69=hM@hMB +zo0BZ7LE8hC4A?C|Mx}xZUSGEdWkQhK8iqSa`!kzFfX|fWo_|$Bkk9t9bcG-X-!-m9 +z`0I1CTk+mF2s%1>-Ox*~%ToT)z!RQQ+bikvpX|ufB#DWqz^?wZgh%sn+_?Oe%%@?! +zR@JuF18wi)&}B2GY@HSxkg;ZOvf~b`*88tmJ0#v}La-1P?I3YCBxEkCTScmA-p +zjjB^DrGCp<0%Gd!0C?g^?AG`u-U|+5se@Q^qwp(a`VTW9_TEusnyPqKDnrk(c<_rq +zn?ln<2AJx^3C)lg>b;$pzlo(VScs*L45MfyZhie^gQnPS;Q(YkvpU2(ZPoDYFX;_p9fCkvGJPd=u- +zy_rCzbw!J!`JXh4?ya8rvwMO>=X5`A5-3kQft*z?#}~lQx}lbYEo1pYc||W;X*Gyy +zaqQ5`E}5pZ5KvTPLJqrT`0aZ4H2#WoklTK2dN`LhJ4`i-Yr{@^M;PA9o_xS%TZje) +zzK>Qg^b7-bEqPXHXLkMOVFL%aT?hnX +zYXSbgOSVjp<`c=2B#hX0ak+umhLz5*A!X`Z;@qr})MDvt0;#2;8l_{W>?U~7eG@>y +z>GCRJzeu``k=(P+2KLU_Lo1ZqZRvemO9fzQOhqCR=gLJUVU&ZKhf@j&E4;l701_An +z%vLa!t~?Z=hdf7jtNbfTW))@UdCj?wlsT^NkUOR +zNvFyHL#gXO8?w#eNw}`d``1Cbh-jLLP-^J>x0evj1C5EOfWLF+TVr!8S7RYD)Z9@U +zIr7sC6&um6P1I~D)`l70`oZ3{i88zj`UNu~Hj?jN>DC^naCS88Ao|#CNWZklq6JPA +zY{2r_9EcHF_Zbl}jnv}bVX2W1M-bO2Df+k;P&3K^Maz`@4honet15qv9C=pJ(X7{si0nTOGzvn7ETr;{2tL3N|7{zln|gpTD4Jl1 +zXiLgD{Gs2+mu!V&Se-YG53Sz)U;n65y>dG#sO{Laa<)#aojo%($e?CK0&Ag}Xse@yc0<}y +zYAc0f3^Z^zrE64q-&~ZRKjK>BhOZLanW#7u@XRc<2ZZS?vjDbn0&4}!x&?Aa^eXAu6Kt@A%7erkGs$tE9|z7RN+{_1 +zE+GN6TBGdRfWH&kVM16w9wf_(1LUUiL{^Zq4cHn+6ZD;^W9mGjO~Bd~4>zAZgSpL|2j!k3mO? +zwv9L*WsF;qL>sdu^s79|=e|@;RfHs6Ix7nwj%XAmyrtHvm|&GnvXBt7y-oXLKDa`d +z@LgVBx?k)j&P(&>@ZvytPjJ9ujc(-IqK69N!&xP$AR&Ja0tfl~oPqTB_WC0I0@ZFX +zGNewif=ze*oex|c=I_{M0xM!o1mSXKczy}e5;p`qeAINLiH!nTOV +z`xzAOKj#9(DoO`r5tRwFh|vWr5FNiC$`!TFvzX^kLnjKs?sSkj2}K-VZ(tN$hEG)_ +zGylGb>vh3yj%85EreH|(LpYqzZDh3?OF6iQnB*@HF*Px-2Get6VxLZWGfTr}YfD&q +z#;vp}CI>drhz-spf*0*~Q4v?mvTF)v=y1U%>y`Qt$H#j!8# +z<*9k#z|^04`7VaR;a0$=?rXn&Cn +zQ2(;^^FF%Ge{L15MX?Pgku;$zDr_4_GXgmc8UKHNJMGt-F+KH~mEEJcHFAtVUC2bOU +zMAm@rAh2URsS3Zr>zMO*x|RWA*RF_dsLT3lx5D{C>~hyFxib4X){Ul_MTb>84(a +z5pph{we)Zd`~=u?mghcQbrqWY>9Aeu_MWqtCM)}1Y1eRKuATcwkXaKA_cO<-UB>Lc +z3wA#{_W=h(e!n4cd-jcA4d-%fm?pQ%WQ}}pWB84TT@n$pUu>^V;C)~5|Nr|LqQi_D +z&vF9+@n!)7vHU;OlPbB}8UH`kk`8KHIk~o<^ds@pgNdP*#I`)3pYJa!BHAkvRLFWg)G2i8K +zyhHeyS&dA+`qP9fFnsm2GLZNK#Y +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 +z(zM0T`>r|nozeT!IJz986Op3T9;Sv +z9GY)iyINqL4GMM2GR1@`=Yhd8)Nh%Xbm5ZHiF~#49_|Xxn0MNw` +zC`?AQ!Q=Y84;hbbyZmmtTq4|V!w!2YTEHu(~qWzprNQ*&(EX|i5)9Onwhy-}Y%&z;{L4@<*?9a>H9v_dDVBph-Pr5j=` +zTuanbt`(x|N&G>Rj^%mnuySu$-*@LDW6?}!4t0RJ!rKbK?<)wQ`U=AY +zHm>VYwcyeMP6O(5;b&@l1pz)0YcjBhZWMvuGmEk|>b3vVuirx_(LuB1RtyM2)wJVchHEp7q)2 +zaPnojA3V12+tBI^wJ8dGm9drE>XCKaE5ZM=D{3Edvq%0)xDeNC{d*^S6I}?sm$z+3 +zXl9R%)J_w;6^(0mBeY2Lm-%jGYN+hBic)sMMLK^;_KLJo=?Q5D;9l(qJU0Jl7cuz+O5~$ezAIaN +zP^uIaT)H#`SoPJvqN&&V4}_ciU=W9aMQ9lsMD;D`2olP(Jld%>1!yOQkx&okH^ +z4P=awANr8A*@fXJ7w&mpAHt^i$eS~vo$`tN +zkG_Ra1#IgO!e%*S^#l+-bjGY~QG`ZwCH&QAW& +z<&(G<$`TNy`2GA(zWL*@_4JiC4wy})RS;MGO8tV9@8@o$kpwDbeEzgg>+5XlYC<+) +z=sm3104A<&K<(+wp2mnjuWkLD&1(bKP91_Bu6;nMLULslRc|(j;G$fzH2>ZrWNQp3 +zFavOlsVq>4|2uIre6au1f`#kN<8|z}!)X1l&mj4QDr-5uMpIdg +zCV&R6-TzDpqHqYX+Ib!Y<-%od{{jDrM_?oqvDt4Q>&JyqDbNV+PCSAm2(F{hA{adO +zf5Jd)@*k)!7vY^IOxYUV@u$8HcD3@l^gyO7}rzKAlOzmFX5bD>}ZDw +z@by5hz(_7b%1(#LT(+RTmcMP>d&2KiC0XwDy6($iJ;v`NQ~LN;n7NG?G9<{B +z>k2P%sJRf7e7dJ0+xKs9xDOfS6N?*uoDuMG2`CHgNy{d6~jP;T=GnBK~K{Cc>ua +z09Y9?$8N7+DG0f2uLQl_$v`FpW<8a?l(GT&jy?a+=O`jPi5a+TDNlYB^f?LTorVI( +zSOT&c&Z*DuDD)%MGaIx=;czgJU7X3B4dt98a9kecv?D(f`QP9?LS^&VRusp4pQ9kY +z$#A=wFvWmHB-j6MI1*;zM=QKn9h3ve)_?Wot#mTu?#ZkxBL1(AS*$WtM{iad$|E!R +zoxZG*o^1TDBH*jR%+egrpKs3|;gOObHzWC(sqDc(rdt>%+K%jG_}f2}R|awjVK9-5 +zBg7x+)qkZJPgW_xxVE4_{x@ebM?*R7x3d*5?l%5o{rSJvc{+~^;XwL-EWH2M0@){5 +zHejxmbMOBmYz!rQA6B59xIQWYq1HP;7X>$2hOpTk@s+Co?SDFF847fT5nmlZza1F4JSM*YtN867e$YF+#Rc{1ki%QjVoeB{UUm&{9>=RRZyYS=eCuL9 +z63fJfFhE7kTgQi2sj4w>{8&!Dds9vxzf?}HCn8@fjpc7#cjyi8(#h*|b2j4IQWL0p +zg1fK&^>puiPdICT`kdo{36F6mzHT@TtHr)MvKkx)km1BHn|iJkWfI5qIGe>%N7 +zdRVyF2OOW@M^3Cg4%M+_0n9gM+?%c%Q5NQ9kUe`l`L7Y43^|NjyGL~i1Y^6`*cQR&bgOdXg?~`yJ81Fwl|0-L7_%a +zYxHagoN;;y9^r#v+6iKR?GJxr#P`GB31EbB1*r*|2|Kq!5eo8Uv +z8Y2{}7%}}H!p +zDl^~rnH9EIhwMA~wz$S9apW2b6{&$jg$WYX>s)sblUKN@u|Nc{p0aDg3jCgCIc$@S +znRy=w*zpZF4TKI;2t)hz+jWqsHQKJZTMl1Gg4i9Jp46XfM>d|N31GiWQ-X!;SG3`< +zQB4EE*F*F@*{}CJZH|ivk_`}827pSRA%vy$;^M>*zlj7qKtJXnRO;QdD8V+AYv?5J+jgvy>**GZtg +zw)|JEaiqwtF%tN1E%-|QrHPKjPn*(>tsp^l@j1V%GIgu%6 +zD+j2!rI?XKVw`Q_n5G1B4-aq7P7k!bKu-W_>BmQVeU9Ql{3mMCLK2P@90`kEDTH`q +zEp@%hBg6fmfp8*8*g +z!7R$F34foV;2zDZEeZPr4Z7iRNJ92K@IFpOl4jLwAYz|bf?}4ozp0x%YE)!@_^!}>W4P74oA&0EIVxoMAS4Ej5U{Jzo} +z^jqY?@$NFC5=1vB-+{o}3`LK2PRtDTzFnd|%+t&g%7Rw+yvemlcPp&q@0}Urxi6|l#bo>;gUMZU +zhpAm-{REgU1`95KZdpz|h2C7{&RofgLe!BKML#$GkFupQdHPxVoyJ;bVtR4BJRb%m +zQ~pEqA6|CRkuJ=9WadX#O;H5YR9ux6nR={ +z^sXA8V)-0Y8h-*D?xLRsGo|BI%o!#UmS;^)iJWElbkd;`U`m9GMwYr&D1rt%#YvB` +zqCix*uvpaPorQ9DI?v(qqk4t#SmWy!NMAo}a!FJvhMm7%ZkweT8VWrPm!BDw!}o0b +zrrfR?tn186nARi>=e6Ni-ZjKAyVl`YIv1a5!fZvKn^@U4KJ3eT2DKjE;x7Ehd#dvH +zuTo_E0xX*WLjYW5Qz1gZfJN}CD-%ogSed9Mr1OwO93&cJqHZc3bZ`}962eev#GzHJ +z-~oa7a*~mw9?or@E?Y0EAPkd6>!_V-^7NYL^G^H{x&XZNH-QgTPg{WZNq@!6Ru{vH +z=cfv}N!6Gt<4T8K_0c~@ILoE$`P{Z%VnZcFi*J?AOherXd1iJ06sTh(0qCF%l^b +zEmV%1mdfXhGObI+cR!;FF~!v3V)m_-2^l-Xp#duzF^AM+A~&s6&q@hJ?%Oj4+o1LG +zklhZXGUbUnH_cS{^FY06wV#N$R(PI!NGL@N6eA-!)iYLp +zzyvSLH`pNcE@hHnOx$Js_ST?hfvDY8BN+}qecw*GI{YB%7G-Z{u)vAz1uA?;zJ+-@ +zDn^M#_2$n~L;xzD1L|gQ^&}g0U;8;x1Tpe +zdw;&V0~Vpk=QZ7?Cvt`Lni1h`?erSYrgI-D0Rd>#w`~Ky93JQ(F%k%gV8wk+=P152U;Vy(kPi2zoF-b_?~Vwb;M-yAHx6>F^^vsioe?~N0fQyih^mSk@;0G6 +z?{oLl%aK4v=S%Ui608MVT_1`S^B`-=P);e8k5%|3G1<3|%!9Vqc8jMOrO`8yK)dPx%i*dX1QT+uACFBI<(r7B&~5U758F;h +zyqtOb-8m)Jt!O**oT}F}P*VK~_7I*}z0bw&iu}RHK9S}-0anQuOS5>pOWeI(O6xF7 +z`gZd3H8ogg=VrrQM!UlGgn9K*0@ +zZ?@lkhnDLN*c2`g0n1eCbENWdemDjpIU=0xW +zytH{UV5U{0Y+1HKl`U1Xp};y#$Z@#r{P%l6xiJZKGFQN&IU?SGl&jN#^tf~l%12tc +zihT$_A-vx&=Y-av+o)L;bZK})2Y8F^)BE|vcHF$CXHxf+yi}d;GUDZzAur7{W{qn< +zAU0x-nIzw2>LgTZ{JQT9UEM;i=(M}VNQA353keg}?KsGy4}Np1y9a)%NEX(>S6x6{ +zq6POXTlOWs^WgHnz3r~C;?8+4NKF^TSNq1C-Q9nNe%u&S+rNLil?-!m$)CHj0?(N+ +zh{tE}&_9b4%*iLF$q17Z{C;6^L{+G>S18Jz*z6|>DVfq`*#I(>a2TvT!6 +z*c>zhzd(;*S=&h&ru@WC{?qU-vDqm38ozEtHm*WOEQj^OrBJgvd7m0DcA+a +zjs@Nvx$0ASzmZ$@zNgzA5yMNifnfqwG6V9M^#OjlXO(TLV^Y0*-~i +zT+f||r|*qDe`J{3%c!lod?Z2U>T5*e>-oorx61~_ +zGMIIXO~3OUqkwt42Iy8LrW!b2ya-h4^)r`i2wrzU<8Y%*e4cp-zGA*%glWYm4<0Ea +zH4S`>`mULW@e!klWSjk`j2sr?Y@beDKYc$Y0CN2=CT~D__l(UEn~@?g8TqJnXrY`0 +z_ZD7!&M7ePF}U0V=pK;`wm_TlYo@0R88?GQ2rx+sgWZY_?mAC2?4^heMA7f(c&97s +z)Z9FE_kx6(bxu>pws+Xpv-jn-i0*`n4hGhEtRC)WzBQY=9u1(+R +zf~E}Z?@YhRXG#unrV(&}WejZ(cu7%(ku$2?O5Qh*pTb(q_?28~KT@QB}=Ai|`>8X~t(e!R`I4vHXo|$0K36M%fRO_)_ABt&>19)A)h^v%?dgXQ +zIg}%8K2T~LwtGy`2R?Z=la`^OkSw4f%8g^IyKCk&nsIl#4^iUu7@Rj``Qp(WH?ofkWACx;eu?j}J +zQjFEt2v}Rg`?g9~Y}>lnW*-Dv(~aaf=LT1qfA;jB*F?M*|K72>L-6@d<4tZh(j)=K +zhAu>$$sd8=cERGSe2vrDlnY`U#>{JDXOT9$d`{CjhPLeY+$?_oy{EMI`ioCZlY``z +zOd5Q~W@zWWb|u|E>AFzV_3`-!B+F@}ic-T0u50pc(7j!|F~%!EA9u}>p`Rc(1HNts +z`g4T-KtDuV2aNn6FJm|D*YfO=MShntvTcg`+WHIYGiHCe9YkO+_WXI%&G0515G*Uu +z6#yvn^bT-cd^Co#Zw(x%yAb)0(AVT6XAc~h0}j-fftCgiR1NN_-~o6o|6S6!+^EmRQwPKF#OwGW`{*N`jy*(? +z0tk`(bp-62g8scj3$f4MTm!7$Kf6Fb3dFozGZ`!l6^g_FzEPJtn2+9Y*W#lqGh8{b +z=0x_{)$Lu} +zSc4G-3g?MLxR1vev~ezf{YN+M>Uf=v@Zgmth{(c+GWkS6nvVV`jv}B)C~*lEJop@K +zNbMQdO{K`JZ)d~X<>zUHd|W~Ap0iC8VOVL2sF_}rB@S+}j`jke7cQB#NRx=paUV#? +z*?pz>9Cp$*6`r=1{cGTWjYZ0|zLXvod$&I0ZLJ*YnI%&8Z7BPtb(_@wV!|A|bVjo& +zxf5>AnJHlEVOb&E)TPrIVo{G +zppN0b>yVI;AllV|QdBfUOxoGY?v}66%8W<_qBP^6ptdg?gQX|!^$c=%Mw?^vDhXJT +zRFv-5fWE$SUPK8)RkKlgkQ^y!8Vgb{9K+xF^dfdt3hYBGGpSOz9fXR6=8BVB25H&2 +zCn5&;*VeDUOvsAUwoZ#P+6ejjVO$EKG{M@DRgpR@?5j*qKBs?5yOrhW8R5fw;8~DW +zrGkPTy)~V1lmH^;#|9Q2%n-w8fa!CrNOzFP=kRL72r&Md9aEI|ytVyYC!;9_QdF+CGlb)zZ+bJ@D}8|* +zkY;*Za=`SovCYbE)qn7a1jt0f_l{7aG^Nkkb~8Ft#z8QK?>5OSM)97V(}1Ja?@H7z +z^_7hmaOB21t6y@BBf+`Gm#POVAdLSW!Asj3Cro* +z1vLvcBQdF&GI{B;iR5h-BjdcmsAPfQXy*j?n{24=GiK_&pt-L3rEBJE(&AefRhe@K +zXj0<0Nl47@tJuLpe1WGRP_1CKoJ?a4rZcKSg@1ylC{T-cVb|b)hg%M_K5N~ghKsR6 +zhyM#yCXaSw<&a?FFhzxu_!n11A>$fMU;V=2f-UpyZ9=Z)#Fbj_W5zh|bKtAVV!$3| +zyHF%r57H~n>1%*mEM5R&vQ`lod#l=D9B}piHs2}_ES+0>Eg3ITG<=bRhSW|0P9~i1 +ztY)j#PK9-X^`lOgW#r)Xqrctx+-Bzj{QBV^hGax_SFB$}Th>NRwB=kf*2pjYtO3Ue +zHm-qMQiV66u!^uAK*-ocuFNUp+72X|F+xm8@NkE>J6j~NNHZsAmK&!q{HNbJ(IV_1 +z|Nf3^B7MP1f-3If($L~>&`SQoRD)dKTOogmI@0z1-&|0I7zKv4o96zALenW4sN-Ga +zu}KJUn*AQ+F=8dDP$wvFN@rHhrqR>#wvd7Q@&j8w2J>Lst)-#+@G?<@;}c+rAc|m^ +z8s!MkEnWpdJmLvewd<8@8e-twd=xy#n$YT)!tAHYQ)u-AG4?Gbcx1I295*IyE^Q9M +zG*q`h!;oTX%4m}+XP|-aN*Exw%ICXxGW9rIx3KL}5F6wbG~u)w<(-Sg{M@0XKi9gW +zkI)9nWmAd4DD>`N#IJ3PQkaPE6AS{aUdlw4tvAKfBAGd}idz8e+E1bL#+i1XR +z)`Ms6L9bwSj)4j7%sL5mQ6smSKBec!2D(XGC6Xv=%rWqPUcv^vTmC#|>fI +z+FhcQa6;yW>5 +z+%9hY&6z&F&{?KNq>ewq%J{3e)H>pYi%gy$QQaR0(YO=mGS=>oQLB5KqePo50$QKc905M+*>++EZ4y8MG +zkNVjGa+3NRlIrTnu4V8$1pt3o$r9soelYz52|~E*&V+tS)9T2&sKOe%^CfMn2Fw>S?!O*v-!H->;QDs3^ctQ@(fvKF +z?A960iJ0hbs%jS+%iH}1A-L3I+%MYw1MVxZ0+#)lk1&Echq-nC#C!Fe4Fn4Ti9b>B +zTjc91VXtWS;-2@)9lgL#%=0hTzY=X~o%3{|S;TO6?u$-HxVJpsmek*|`Fi +zvyG?{rF^3C_n=+U_xNKP$*LyKHEr2c(r-c|!DVmG9p8!10+j%}d=#^?2R{v)liAlW +z+ecdNc1_(1m254}iG#&5=nj`_iD6wVPcd!;B` +zJ(P+=0`Y`S$^d4B98kZG#|3YmKj{1T#(&EhYrfz=`%i#Z-GV-`*0U4|Yi2dPwB-h0shtSixOL5g +znrTDJC&5&^>o%gIcn_0v1BTpsuUNcFi#9lT*%XiDlgM-=xp)E-C})9Lpa9QMEn=@v +zJl|LU{4&7d8L&k77LK@VYV7E!1IbnkjcXP-ySYp_*5rs5Myqk@-K2d%exx +zej$HX%WL7jgxtzWS{&?2a>e1_X{Ib(&Zdf4RdqSC;1VELV2_QAO|q|k7Prf18F34q +zFR>uM9%OOm70B-V4#c;v1P6AHJ$Z +z60XFat$VayqG-Io%hfFIn9WFsyi_)njgw))**lFXE*zD~u<{!ftuMFD^89sn-6|^1 +zkHG|>R#Q$r!I!9?^_LyI8_{eIqSIA=2ASCn$I?n6Y_wU7E??ur1ksSgBA +zu}kKOs3LG5d}*31lC)FVNqSZKlyryII_jCtai%c#GU(%H_LB*Gbv)>#yllwj;rn-= +zKB2O$%|)<0LQqA^vbQB-wW&_U2sw^>(Z3go(5{2-rI2D2^BeHVYEuUn?AyBK)}kHO +zSsHc?>fN<&q6b~*Iv&(CeBVq_KG@|*wkze1D>Sv6zpJysyX9xn +zgB*9vQn1n0v^kgTKZUhPeq3P<)Kr!(4GYXURW+>Gbv~{r{^&L5*gozuZ{eRJDtcH! +zRQo119DT0lMiwp*%`aq?6LD?rW>M>!-2$%s(g>?3Xqu+0w3!O%1VV3?2_SA*US?y@ +z{9sUCNHJbG3>J(syaEQV{9FnGt5*ue<#sixCFjvpO@z>qm1-4=H$Ivk(P1>jSl$6w +zP=LVdubcWxaLlkvDTNU9ILn4b0=99rj^NWwn5&w>T~5L17iH~`wD=@vxzWqoLDyu> +z->fzbFqIHBz38H%M{(L4-u*{AVtW@=Ly}&aHI6^JH<`en8{pDOMId$>ye3R|T9?gCfG>;iNqI)*X{JfknBM`g0cNjgk=Cm9mreogHc%9C^rDG?bZ@wLgcaj5tXJGD&M0*5K +z)Qp!$FL+cTE&Lb{l9Il^ySKl^|BSNEeH48EFAVKr%hB8}7!VKu76^#q|CbGOS^nQh +z@G_16u?WfkhXn67rnQxJUz)u)0~U{EBS>bDS~MYqz-n<#k5n#|S&Z*B>?b83k6tPT +zwjPO;Cb%UKc*#y}L%Bc}QX!e%L43FBM9K9Hw$LNeJ3?Wff-6G&P@Pay +zr;SjWNOD*OipI*Qs%r +z*LMI$Xe6O*pR8PD!p)C^0+G6x%!&wMZ>)qGON@T<-#*hpW&o1E_A1k68_LQ^55R{O +ziQkAtEqL4cEv{^Dw5t~=_;@Oimf3<~)Guda4I5Y=8=tI16~} +z59?q6)1}TTD+Y4~rVU1~9LLplaod3pgyw-M3PUX_94B%~X&A4W)r^*vNIb_f;us91 +z0?>iuu+c;1kVQydjypIbC3_F<3psi0k@-uSrr%wxAr)>d*L^`{|j +zM{ZI^Y3U*^mK~J1bBib0>UV~zg(EH&5Pww$@a9%~*LW%Gygog0VvXJ3-d)_%zM}a< +z``igbb+|`_%Y+E`mQO*o-;C;GWCAX_pPoC75C{^TOakkzS|uVxNt47e@k@1TbX>gC +zc0n@0TC5rAZ|!`_$nvQ>kI~}NS%sTMl4?eXean$nh|taSENZ5-B-E$b{tY3N^_HwV +zDd-aImurMWm7)XJfKOXCKG0-__EYU2lzYvCS7>qWHs46s84lvNm+5FD=CLW0I(FT( +zlqieDbsdi3?K^xxX>T$*z_MO>OuaZ{af4+3*F^4liU%wr0I%inrA~>it +z(HEb+9{ub|Qa!H_Eqep%vqR*Fw1b*F(HrhNu!c`5=X7zxFW7fH;E}zwgkNs5+`fg85@om~35Gk14&RxGToK+0=X^IpHtE`?jIBzHI4>I4uy+nG^^R^Z%bV|AXHBe`nAuek&J}&g8uhP0OtI?j3wA+}Q3N15RYNj;)bb +zBDm|U^>wI-N))Ao;%Wowb#wnObD8Rtq0<(94%FKjthCf*7FDl{iK8N{jaI}^JVb2v +zd&E~&ts!%EW|nJJ7c)0Pd;fTRQLVaRS<#23ChSfVzf;z6BeMvxr^thNzBS``qS9Ua +zq$7QBY2jA-vvfGW)gJ>ak*DNAub@}Jx52)N39Epa99m?i=ar9e17u?ix;0_E$I3*! +zPaSvA&*%6o!rLg`sp_EIVoqZD2NO0^M5=6>${Xy)Mvx3dY|z^sBzd?z_m9DA`$^_i +zQ6VHzK&smzm!v=|ZU +zxT{m_G;4HJ51y1p%}L$n3{YxBN=j}R6pXo@{$XG0?) +zv(Ih(6N``t_ffwfl9+VI{A;Uy7}9x@&mpN!5nrGQ>~S1=Q5yas0XGHOdPC^VWzC{Y +z1zPg;U|qDhi=yVsm^+-G1DiT>VN?{e16)Eau;^&~C|^*YaR{;*RBwdBoz!?655c2@ +z_ZhzY9<`>3cQA;IC%MG>!d~u_d7#ZyZepNfS80X^H9&HnVSnD#hK*>OGg%adcDTXb +z-jRZQ4jWBs?n(YMfbj}_BC{F!3CMWEZ+l=Iq^RxHAd`JagkHk2QUQ<0B+9Au;K2I< +z+Yc-P#w!$&y3V8kyP+5!Qv!bdM~6QB1tBI)rqfev#Wdv)u8@tHdj!VX`H|>Le#%GD +zFCZGHQKTgi&*xAelc2^BL*P8{w$bdEV$8cHy!gfgwCpk|9q1L{^{jP&yqT5W!*Bma +zy;_X^U!-qbF@a90WSB#Y8Bm&ahU#*Tz)0{u|)75-3b +zA?iMdA9Z_y#Jf=Bt7veRRW(m~#M{c()Ky55ks~97u8a)m{>%$+e{e!Emy<*uOR&Pg +zIfH$lhYSnKE0ks9Yu&d!gteUi5I*}==<%AD;0&xu-NyLrgF06PQUh4&t$?4DGQ^yJy0C0x?H$(IxK#KwU<1Wn1|6B=VwOPHxP}O)EbT+2(pAh3uqMN;cFNW{LVKc1LvFo7F-@W3`9u| +z)uc=5umdFYN60G!qky`x?_?@%Z<++B(Bq1~%ktC-A7x%gVQ=Pvu$&fLK}@TOE+V$K +zbP`y`Pl~RAAX)E7xgZ`30%J@ +znh-wVaB_+iJLGT5(?Xpw+BL>!E^^?6rY#jdp0_ApSTesEC<8X#7~fLpwEB5vZX|wQ +zFuYwe##rB1BjqZ6|J()rl0C=o!hFRqXzVG5w0yShB$U>!A2@7*QyG8Nx#orOag#@i +zOuHH>8L`lvwnZVaW^jzDWV*Ts +ze$5No(-3n`D>MO+1)Si{XPm~h4R!Nq7hmXsOcYtP*ffQ!oJnZhf~^zth;&w`a#unr +zi4JULQ^~ZVX<6w*loG~4h?`Z1=5)y#=>#CUxwbV|5six +zg&<8eIzEU02xJ}{xzD;&4s)7xr=BPLINuJQGiEl3C5F~g#wt_1uhV_n8I#V#^QXRL +zQ$5nEkDgM8tItI^Y<0XghzI}l`Sl{ske*%=Ov0MUq#^9)Sus@@pxz^-nIW8$2tCOHWr!D*>uD*e)&rdbC%1FZ}+p$6f%cpXNr4sH78C)PpIsM#x#p7`Wn;$t*BNi}k1&-qkPW}sUPKVKnW +zy4JYPa}#&H`{m$Sb*&EHOr80s#A^+MIfv|Pr_Ag*mQMT)zS$FKjAn^+`IYZoIAff3 +ziN!xEmy#}o9hQSk0Qm-oy5h?d2kPe)n&R8%B#MNlJH)ltv=kOb!9DF-0RpAj{Q4N-PazTP= +z`7kj2d!uoDt&Jgn{S`DO*R&U8qScq5@NngT4!WNyI!@P0^#0mp+xXkX+B}*?8o4u?mY!N87Cn%UqT$bN +zBdHP{XUQS^!OcZ@;@;`;Tw^}yIiq{jmmb}$`HJ#6%@8URFN_CL)^QS1))`949n(1K +zN`u+w{N^NZy=yA!Ep%u?J6PTT>#J#Z=I(s;bH}jssZ(_IO~r&emL}`rv_C|O;(X@M +zXjaTAG^``ZNORDB`~!4o%YliW!S@>FLxM2O#pRk>xYfKwt4Tci1xP%6(*h6&SSh)c +z9c|O3mT+6iD>-^^ihCFaCS1+Ucj7`|3b~Vb$#!L&pcrOquWRo|Og=Uqnww +zI0zd4nVK*4LtRh17=|t-LF$G15RPD}STsO$_ZHM-9{F>7-6Yz~T0!;QjM4|$6ti{Z +z$rlP}GWUEvhTWnrvG6+2{C>exAo)afL&1?&R!-XA`4QEB9`4ise*Qs66{_HsP{^*O +zP~Kk=-!aPZtvyrwr(C%35e#{>-ce4d?`g&tv0Mr8da@ +zcEx_o&&T>DL^;b +z9FSuO$a+#-g30*^gCp^e#pt$8n|JGh^S$(&Wm&!FuIj+IN-Bo?J@eG$!pC&T^wovl +zicEd5YWs=`Oij=1n{n3b78uZDp3sPN{jkTx9RIO*TYAI}&|4^$p$!nGh~(5(@2ea? +zsRT(k1OMLqB~@2k^l@t}x_Chqo +z`RI5s7L$DgKccwoO>)QRwb@19HdEY{-eH*d?n^IB>18QGP*Hx^hX;oTD=P5DZ&eRivl}dZK +zRcEV=qOXfbDAQ~NOni%BJwGLZqnZ;-w&RS%VLc+@Zoizi5p3a>>v4U+8Sj|Sh$?~~ +z${F6)LPD35Xd%>>u+BpD3`2%<(4-RvTeDeYO#aQ0cLD)D+EM~JC?hVEt-G;kBvw;h +z;8%b3VXL?-0Em{yzA2pPA?B6q-+x^@8(l)c10VLT&wlLF>P;_~)8gLjj=OKLZ2I)J +zB;;fA^h#mqHp-4opDTbf<8^uB${={|Ucpt{R=-SUD6DLHt*uESI=2x$tsXqB#?ynH +zc6X=OUiYD@o31*Ga8TWMk!V +zL;q2#ZauGtpwN?r#O+Ln;w_fApzSWLVWS=?hZ~gn^Kq*Doqc%j2iklP0zu2Sw)AUe +z891hrDtTV>(Ez;`E0lGtFQG!Q%!T?d|1ZMsAqzMb1^FOdokV$E%qNLn +z&fv8+J!jaKPz=-+M1t}8C)QQ5I+5m;VK{0Z32^h|K~{iGqb6IAwv50l-d)UhZ?RD; +zI+~XjHYdVK3cAb0s$1l!9=LVQh0t|E{6RB7@2wcUj8TraxF}34m +zbUPou$VdD6GiypL;8=}nT)qL%#2U+GVICZ}Cyxm3T)W_rsE(nPkSj{>WBT1&YqQnD +z{GjE|=s$R5cYF9*cxxjZnaF3Ei+Wl+f5ELyMRM(c)K@F0V-1*=D%~imHV<=$jKPu9Ju%GIjrt57t(%iYO0c%231RZBk8bo)ef3w;ig-dUCiprw2g +zuGJ?Gcpo&1^~hs7G7=)FZ$AlTN27a8%+)ANy2c$oW@z2);xAfFSU2S~U>-v+Ccdaj +z(HGSOB+YWb`d0RYYm|gqr&0>kN~Pyh73hP@{ixR;HR)dHaHk(1(BZ*VOteRa +zj8x^`9n}V=|J{wnd|W0cdnA22L>2?pnuTp)$|W+Ws`BPpa+OKkXhjwvQY7Aw7I`5c +z2Zj%jVfJ=Sm6I_-EKS#pfz9Q)iP$Y#nTcI#uN*t#M=ulXHhmh(z|UNgISkh2Buom}}O;7xQ}Z{B833M7q-*_;)fL`Q+_WsTIYD>*mN7T(>J)e~ +z`s;Bh|H+7Ua;Ezk6tX270d~gWc!#^ZgH`C%~FTlTRuoK2vLo +z%jQ0vE$Ir|-v`J3>Ty0{&rqtyV<1Z{-|O`B(AZ^zXP)i)63)%}4vg +z&WD(S+ns49MykqW+LIAp=|F1vuhS~doqy|^$7$y_XF*xhCdgCG%#jAa^;GlzCjD}J +z89A?YLz6r1I;UD2VA#^diP=9FVDv%2j*6ZB3+5MlbnI!Z%+YCmjRq#fj;67umjckR +z--BZv&oOMPlmoz`rJtvYGi8QZ{zGqOLDXvST=%JY^+!gKoWog9ym5I3dxmj~QuE3F +z&w~g^FriQsL-1fZ3u9um1be+MP0>-Yfy~L43WV_cL8*rgMk#V*9As~i=RB;yUTYky +z9s91vk)6m<8Y0G$XJb#$t>W~*`{Cx30bfm@#_x>2r+w0~-8HLd^Li%J@>afml-OI| +zW17~v4zJY6j)1YpL8FPOqS)9ndaJ-YdfKP1pnLKtkh=7~Q(D}uyVBBOT}@Y- +z^{?7fNN}yq(cu%@&wHJk{ljWi>BaGMG(5FAujp%N%ldOcRDv1N7sqBjiOc72Ho^^o +z(HZ-Al_nLOqEvWPq=gLy93>%qm6Pd;4}(^F|Io-cMlaq!2WPBk1}3=!qBNHccAMRs +z`dM%q+5)ieeyGYPI!zT);9Ah6oJ1|+wZ(^BBM0l`$u7TPkU%k%3<;saMl3eFsMEoW +zn~qVaS>o?JuQoD0lgiVVBa@c!{0GhUY~wQb&Emho2A16*khU!-Ofsc;xFE!$0P;-(49GCO&ux)e?b!s9&-a1dfyO$-8vvVMdWu0NTbYev5{U{ +zRUaMzg$3{RSSJAlTf(oORD@Iiljp|*k}3_^UvH2+F)O04&0^k$!BwuyTNR(>yV2#r +zgmt_#ggAuhkz=+`CB~N?s@(4OtW#lpxVQ}7+!f5x>93?j5RQdqDpo{=-X;2Co%2+f +z3)%zyH1AUM^Ccb)OIxHqTfLnYj^{dZ0M{86t?6Gw|MYOe*i8ZR2jpgDc-;`rpdsURw;bS)6HVWx-N}Wd&Y@P*D8B +zk{qEe%8EV%d^FdWITAwq_v-KNPNv`(!&>IkJ74moMRlFQlZlaTzLuTv$nW>pxwnE& +z{lBhdn&^34H1Ch$!iE7!G2 +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 +z~fRKXIq$?^dSh&)awi(Y-BSo7n9=IJPIa +z@Rz{QbRUj2-gBK+&0KXD-ku!L$~-8v$ELhlGicYk2(%BU0rh-VjZdflCm2ZkS96{P`JFT7#uVf^pAKr32|XXARu6ep9BpC`cw1iIgs*` +zk;_XfiF|#3mz0!XV%iQ24CLnK`uh6n>gx9N^ziZV;p5})?CktB{QmyVcKHqbQv!BU +zl>H0Df3#`>1Oz=NAuOQemUWpu;ZPus7V^$xa{TBX=B79Mcs$@s%3~7MDd!==^A&suVC_gd_7pW2e>M@zX?vz{g@cK +z6@_nIYY&j*uEo$oX2;Wk^oX +zx(s40hGWTnF_=@nUO}}HoBVWtJsWjiiZ?AKmMiUA(NxnQ*I`x0eSM=)^Amili23*h +z53^U3S28{tD|q+3BOs+5UsC`G2J0enfW;%F2k9cZE1UjJ8TjO#nW2QquzKy|l@NrYnG +ztp>+Q!rmCnJ++4B@Oz!4jA~RJ7~)c=f&g-u?bE5uFAEN;eai)a338-z=|q{E6}SrG +z5VuKJ9+O3FqjFL#bqeUUG^1~`X-|^LK~$eTZzDd2dXdQp*I{x;)Ak%=T_`egkhhss +zZUd}A<)_jeCJ32WdX7EL7b)F!=2?JuDLIUq+tRr6VwgQ_$2Wk1tKBFQweh2!lX!#! +z;%w)o9T3Y+5`^?ct(*ar;iLhg?TcF8Duiv?X&+yCOb$;4WzcsY=<-*2HV%(Yr=vwn +z9uAMfE2J$rw*EJAKPJ|j+S?0yF*G5>zrK4n&H?PCKO +zbts%E;cAhPMWe~c+Tq+3)EihUkaq{l__Wc!*d=6rTk(p_M9A5M*Z5uJLDRYNwyeFq +zBeBj2kjBO%xpZE4_zhg3JeN5xXry9=i<9I%{5OcUY6j18llcH +zXXy;A8Tw>%{+G@UL9E&*%lGNFnD1q$KTfh}f +ztQPCs1kui3-5q#OjMxeJLS7x9?QAqy8KiBWa6MkC!r|^;O^cEk9nr7U!JLawEtr&X +zQe7BjQvPaiDbhHxv;D!GD^;mfrcq*hUL?vgGgx;Pp=F{III@`yP^HZz>6mq4JnCLV +zE>TA~wekRNUvyMHr` +zILUId$%$uqyQNXCzRSZ_PV#ntQQg`8P_&jsaVN?i{;rDQw)8V+b0@af8Dw +zo8Ahop&E;<(ke~L$~}V)*P-OZ@45wOJsc%EA~L%glv_CHSU$W{jQ4SPCmONlq(jC97QhMCb}ym6n`s==Z-%kI4zOApuk#lZQw9xYhx@BQ5$^&O-GN!^BC4nxce2GWEo%PF0MV) +zgq;2$6~KM+;kNWVCZXyx1D|aN#l;<$IVvP|;A9E=Tp4@G{SAupT_&*_3M~(NF7t=TYBP9ukD=NWoVdqFU?(k2LUsA|W3AR+i +z`#p|2_JmVUuA)P15=gv9Qd_V`qt9r#^c$&&Y{xdj>?+AIDB9`xb$Wtf=;CB^Nf1s) +zT7J(jPC_@bIg+V-Q+Up|0bzVJ63wgc@XcD^#APea__7ATn0Xg^H0LRmpe&B4fsF#F +zpe%InjfO!xBVOBU-zOW9*oi&M5xT%6>*!}1@}1ESC|6vT+HTtSF9X@pgN5kZQTC^e +zG1zoBB`;!k*>~Uc1@7+?E2mNW99?ktFGfjO90)+7qk+e$qagp6+U@D^KEQScn6v#X +zf4jd+1MXy1@SQJ;mU+Z9j`YXLMJGD2&KQl993BC%p`4r6y)NW*7)uLSjg(_2ySI;N#1!>?;bljI!^JXD%(PI4S79?GhU(bB+mmtIOhckdz<(K&leAu4)b +z8t6wNL#HN5BvZ}x5KZ%<fIux#I8OSseagj3W5dB;JYFpHDP4P7XZh6L1M?8(<4j!)J +z>bIa-IzWNJf>_%*K~Bra*pY*Anshpm|>Eq +zj%Lg6h=7aC6*`(GxmnCB=8Uk$?HfZy;+au&`7H&N2vypb{J_c2dd;FjkFMazUTXp> +zI@QIoHeVO{H3^aNl~%tlPMGRi;CRXOEY-`bI>^#D1If>JB8HZ`F&Kyy0#oL@F@ZH? +zO{^6M|E72;9YC#Mk-(2aufox~{OB0|*0SICSp6a7k!bZ)Ar+YgJSa;zd)ptsy_MpG +z#4si>0VS6498S>YFQPMDMJ#itgjb71Vg5JD>3WJ(0uzvT8bEy65%F7BCNY(PK+!z$ +zIJqa;#aHQD_UeyeRU?U5@Md7hiDW=0_YKkL%4RZCA57adJ`cn}4+P3Ams~J+9nj>^ +z{IHO2aGV$jT>O-AbZB>kyCfhRahpBmqf=a9riI@kfAdF9eCREBk`9%aBp_!TSsK?} +zY&+f+kN}vj>S`H_y=B +z+e)1KVSl^e7_za4W_XY*Wf(Rl*E~h+8Z|X>Wc=;+ZM~P6`{91d`DyO^mYqQF`Mhez +z&59-7J<{uWzL~R)RQ)OUKI91dF+;99#iv(5T~Y@~yNEmfIp{WdS;G_@$Nu-Kx_+A? +z8*%4_y8C#hc)h>v^4=D|J7$-R8A&l`Xxi5KHlYhpS* +zoB>M}T>xKDkA07o331O);_`~R<}>;7N< +zGR?*Aa(7Qn>?(D-|0>N +zdcD7L#LVyqndnaM1KdOQDFw$c#Tlkj8^Cx-bI0IPujzP8irQOY$Y)-Bzn@N#TLpk4 +zI>BUmx0uaBKCj5v#0wIT)>0^4bK2IT$ADo)0fIbhiR=r); +z9zTF!J0YEJ*E+zy@ivDdzk!SqJOqA|1-U=kZAfwJkax!d?y!8FUG1i4=voN!urU3GBzg)W2C(x +zVv#qP`c)14*M3=F4g_&aU3o=+w%*jZg1DFNLasZtdDn%I&~gi&1Fg5o=v18R=_z2yV0`N&A-=uvd1Vv7y@%AVt +zKA3+@o`rNUNc6uRs$|Vt(Mq2>YNoP`ME1=Dp^P~vCUd2!mRX=hx~J3j9S(ViEm1su +z3+nQQr=pwrwAG=A?RMeoJJO +z=SsvYUMKo~Gs)4DA9b5hZu?T)K25_p +zdu|e+tWHE43wFj*rf~T7|9b-QMW67Nl9dI&A;MrALosAcC?udsPzKM|bDa +z-2Z#~SkNOT!G^x0CLwx6okXI$k9_Miq3P!OH7Vzn#mbPC-KG=Sb6^kHL5!sb#h(~~ +z|02Y1829+GYmt2gv5l}b=N=wkz&S&*3Fw-OX#hu(M8UUZsvjZWJvZSGNwjDmT|OSR +zdwa{-^>Gi*MTbh(IJ#Dkk^?ScQsewp(;HS&+p?`2r&wwtk60FfwzXSHTEO`FXuy5L +z1AmTCLda)(E0M#w&TcJNmQb)%<_t#>UP9B2UnL-k4z{+{D>6? +zdkHC0T$jDLUssf79(bZUJC@h{vmrkS4sQTY$z@+TdvIW6O*hC8`kF$&7w)u#u-^wa +zG%7GsKReo&VSRb;BjyCRZ)MNaFDXI!2~Eb~C>|5f_Ja5Wcvb|JEdtp$qq&Mtn0#zO +zMP6vu*oQd`QocaG~Ds+gMxF*`NK;a&U(t%IkT6Rd9B!$>kX +zc!vDn+xUOKO>}aEDd0^f(A#-*@BZGpcal?Y>Ub@xd +zl5Y7_TlkmEXn+iJ`U)=*ff7Vy;qnn +zzGf{j*-HMm)KO{AWn-sz--jr+k}CDMgIbkMOY55JMZ;T&6OKv~G8vParR%lgOAH=z +zYwu2hDgHn39i%SQE_UHEBUUbx-+<~foN@bA>eMw$1jxYdL#29`Kzp2Ks*AMY*BR%9 +z3p>sBKsy|l`oE?5Q(V)8v3Q}zlUZXyv@``WKHxTZ5?!ap%b)t`@V0{DxjgXiX_)hm +zwF`SJ(cB(5wirQ*sHC<6<>qD)KO&eM^G!lo^6^ovr}A+^yC!K$%{M|0Z+i4sxqWfi +zBrkOAgBp_9%HV7c$MkSQt0t{V_!uh5$`IDKZ|GlYKJ2vuTyUPKjSbVMP5SOWs;412*bMejjEB3dkEQ3LbOE#QnjMldqo?61fnu`F!r*EgI3o;d2JA +zwCh$b$I-sU_)oo|&owHXJj^|xh~O2@1wiq+d^cXyTIkS~&rd*+v*hpiv)=N&3EHS+ +zM)*KpnlF}J0}x-{oj%i=G$s`YZM!Qd;JpJ3u|9XO`-4&`j5mf1IUaqW+5YK;_gHuM +zxPNt*-s)VmtAv=vA2fP~ex+ls8WCgoX3?b=Ip6Baf7|9{5U{+Hb(9E`>RK-tD1ZI7 +z1e@TLH07~tCJRF3@ACFEU;IYM)2zOr8b0siG0*zU05}p8Fwa6HT!Ss?gs>IdS6sYxKidz*Zf?Ud>2U6FwyK +z_qU={@3%eeGs!sf{ecnBQm#t`ql#i|B_={IZvQhM*vovm)W(xm)K}Q(w5BwX2dKXl +z3fO$H_O%L`ZuH3*r?Pa#_z7!`3cZs1KG1+5n$<=ld#m$O_w&gsb2}?ybf7X@fBDI9 +znbHsRFZcS%9DV^}gaJ*=(W1Gttkf=vNPbvvZ0 +z*1__goi#$dQXfzktg4o0vC7bv%^&9cJ}A6}6C+kGq)GDmi@^)U-Zot`ry9`*fG98f +zMaKE5gtBJF31vT?(;O-_L8NDVzA7-*Rd7mY`IgWagoKlrczvtwzDT0;Xg!e%cY0WG +z`lnmJI!4nRQTiPu%|nt_$?Tcyo5}_TM+;q21#Hr)$W8jO2phS0}>n!d-UtA?J +zmYZ^BnmVsOSPyJ=*DjMV&`Srl66{c99;}51ZT4NNT)bhZ9QU){knNIzzc+);*`T&u +zShv8%rRnE*8v8Mr(a$=;z?y8t$rW2u1UKuuLzUMVQ{8mx +zQgO%{hWyXjn%qP?qtiVsjf;s;w9%*E=QBonlk({PWq +z*V-xXJ=K&Sv8dt9E)fKR-r2K&p@j|}#c^;7qlI2X$fM^lD5MBimxW-(4VA}5>9`?* +zYu_+8LYG)0MT%&@(@*3(IMime=GAes$ik~QqC1TPA8MhVIx8beK?Ff$HujlgNFfXR +zUvkI)ox!4E{XK+)B+F@53*Zm3vJI~-{(}UbA{eF!MOz{q1|mf)T#3l^SKe3$D}^FV +z5;MAAYCsWOVaq};My#r;UQLm(STW!1tY7(ugHY#Q&4BQXl;#gTj1=zRuxv|wzWL33 +zEf@%N$LAm&0*XZib&46k{pAo&)u<(&6e|IZ{@x^!a6BoJ9Vt?KP8HQCH4>2&NuE}} +zqAC$#1kIeEWH^jFtB{d7gp!n+k`7u5KY!I=aOY2)IT*;#I3CuhLyEAg;!9lw(s8Pc +z!YKygf>6;UKSMqUAh~kI!y?oOhS3Da?b0D6xw=_Q&=5$mkWdO$Ui`ivhcFroA-TR2 +z?}!1&&=E+HlYm2ZPh&~nLW3JY1sA5wEv9Jlr#OjgjBCPr>RkHKT*f^xVQpW4l#^aV +zXY5oMrgnzrWuk0dbjOs|F`klU4P1ppsooGs5kgc=dZLb=(@5wAHtZDMEQDEMY5&eq +z%I9AwtR@vKAIbBSNqhrKI$93sZ0> +zDr?62E0so?Y))wFN@z~XUC&RW1fAcvp)c+M6)zd4NBBaz4N$bei4dS2C|FW9z9WR2 +z+ohwg2^kG#A(0xOZeij!imrdB3Q}bR1V+RkB3f3^zQ$oQcXmP(QF~r2D09vXWa^Bc +z2^5VZ-9m>{CXWOQ0|aMgDVmm2yUFo_LFj8dMoG^EbpN55yWLA2#;F*YyEO@N7NV+W +ztlzU?kwe+S{d0n1N`c@-;DsiZYqPXHC8-u{Q8J +z@5UyQah~`~;sqW0WgWoLXVbF+?dNy+i?P|8Seu|Q$=KLk+10@_I=A2BW +zJ4qSXnkry_NVPLT3A#B!(4ko6XhvDon3~|Fic~&XT7+{4JR+gYoAejrFb*}EYG;fx +zxIOh>T{L~wc3G#72Y;9tHbtIhx8HM1Pb{zB^W8NEyzt{Qge6qE2h)Vh(q#SCoOjSy +zr9z;vmTU0#7*n^g4!2_&yufn$sASVCCrVqNU<%drIN@kUub|4Eqy3p(CmB;2RvRWK +z_h?+Omh(KENQ&BMn?xBEed{F1j)c*fHsnp%zd?LYX8!d>B=7^%6#1-43v*Nxa&Cw% +zJH>;2T-1H&@scx>nhjfQn+ju%@_#DxFd#McdsUg#>OZJw5CSW!Cww6VxK5*y)u{zS +zYBesu+aWTm8RV3X8p-(@yk+FynHHoYH#wQ?VhY$Ht|iR8!8kz1Qv)l=8*sFyXdqj1 +z1M6_<3K+kGoRs@nlg~vj@Vip1o3si%jT<*mN8rKmQ+9n_H{*@9R4r1$bk_rW)c=86 +z=04yVJ_n|~<+AE1%bCbDP??TY$R#gxlrmK(e54J2Osj?VqRNA5>lc`&%7=BHobfuX +zFhPhetTjih?^`$nj{1ECncKZUI$Lg=FyDTy@7=|G^eFYpnuOP8s1tGbvzaDFsSfPD +zjk`{K<`0}awgp7@o|E3J#i#>%vLx+A@*KP9p1zMNe_i()$9M8ibeb+dh +zAB@7_{iY6(HHk0JP%n%ieIaiP2k-HUB?Q!!n;{h7gtIayP=mcXi++&r4MON8Ay9nTyt +zQ!5^r*vxnI>&R&NtUUT+Iq5*eGJ=g9c5&_kt5rvBBdx_IdU@qTL41=ou2#H=#$*Op +z?Gt;Vmilr`RUNROZTf-jpW2+b<*n5=m^V9 +zQ0Mgx#=}a)d%XmzHAF2`=mGLUzUZ8nbI17yWTNx*u?iR53&{--KHn$gS3HD +zMr*D+LS?5CS9%+IMw;reCVkpuocD&->Dak0g&9%xzbqWzCNZ0lMqDOhyCsE=Ct&L>-u2HfackloyCyEIp~t#?w(-&`SUhDz%}3H|jRq15}%6|DaxFpi7w +zP_!sPcaGeYchxm~mn`5f1oteELGV;iY`;+rC3>3XPcA)NRpQ9pKb=* +zE&Sb$(u|k)$dA(X9|(#)c1c~v&dVU$Ixj>5G^hkA^^IEi@gSV}KzTM+89PLMPn7cK +zB+V@5_$BC>4Voa|G{ut_DF}xy6Q0&sG00#bIU+7|LxYz#RZSZ!UE*sFDYEy;$@&K+ +z!Q@Q#V^Y#v9kIy**Y5n^GZV=6#z$d{b}*en*n^p$TN4li=<9APa@WP@4(sPlx9wLx +ziX0A~@0e#B6Vn?CjE^qV^9Bc^%zT6 +zY4wm7>+o?NI|{;I4Dd-4BVqWni|J1Pj|ma2CZ;93e}e53G{cWAVkBM;a_XUR-4*$P +zMqz>jyv +zIo89_bKAt~Ta6u_;N+aPh}uu`L%ZgEJroJc@^lXc^5}m|%LxdFX-;!D{Fq1(bOS!2 +zmj{}MO36EjHD^s^4y%)RNPMK{OAna{Lc=8%p&(QHp4o0=Z;8f%`uP4t`729jeB8;j +zjbMC06%j-;m@o=XacOf^t@ayAJ&ZDeP@J#%YCv}eh(JIw4H69NW?vD?5DM;gB{1hI +zr%!t3nABz%QzK|%gd*noMdIL#B|SkDYWU`Zd=+B*D=w$VCBnzU5wa&sk2y_xhnMs$ +zIQJiqItek6&daf99~Izr!_z@raa(*D+wCR6xtywvUZN7vbHKn!i(QGk(a*yzXJ)sU +zDRhu%D29Ch7T^(1`xQ3L^KHb0-^1Hkf4O%PxI=0Huw>f_hz4=KrCcX;Xn{zu!1exN +zH2Y+F@$12RgXTu_6Z!S|N)(}bf4H)+`AiZ6004i!LO!Uz(7&C3`Tmx~hi$ysQ}&wp +zfm5S&>Kozw5)JxJWZ5r1{f#9W`-0vIHAWjL;U}jB+VOdxIoP{xmA@_Az?cFeCREAA +z6CO=*yMSGZz#V+@_lof$OjT0z*H)n1ZVV6~8Ey*4yqEBp2E=;?@_uO8fdBOx@21|l +z9h(kxu3aqIJ-x1KUud?i^!N5DC8y&_x$osZ^R;Kp&f_NVSIPC)f`m7=PsSj)AbMsc +z-q)94O5wMg|L~qu`!6!&n;u`^d=kD9y)J<1DR_G(eg5&jZ-6n;#j1TGp~Il-JX&lb +z`q=f2?HKyShfMe*dxK``2L98xPYP7w-Y0m_H@fXyE}6u_T+$2zOM;yGlwLzv+!q5O +z^c8qym0&u^Ta1Tdaa7|DcRJfx%axaeM|K)!Ovr9mq8jMeoy{M7-@)lid-!EB?)Rhh +zZfyu^mLWL#VY+XYWD-z%fgl8=p*`vfb_b0Go2m^XHTE%nkJMMhd6$dFP=G^@K|kYkiQoPgCJ*EkjH8zh}j8%*bo4nmvj +z%cjQ!7drOs=~$D4-NmYP@AgT<11`B5$8>48V$1Gz{qsh&-TK#tm}|c&gqqQs=P$vA +zx87Helo$>J6zNobhSvzO7eE$Z+!J^^(tO?d8APNL{iXY0&luRc@muCow2x$q?28`_ +zpk#Yy)T!ZWVVK0^{ETIA_v2zUoKvPdzuB;nX>l`0la4ZCUC$e`XQ}t1F%@E)%=95J +za<0WGG-6qHX!}5K{+9WkY5aZ#%Pwg09jOP!Ru7#j#^4P)qp)oC=0Um8)8=x!7pQ7l +z#rmZMlf?49scU8enHH2wWcOiN>&l|Zw~bqbP&x~_nDOqX^bg_Xa?}mWa^1JReaO-V`ts0H_rvr6|RMKLd=yt(&-<@ +zR@Fg`Sej|jqe&W&KG^#Van+^ElNUA(VLRy4_8^)dzS*`!Zqv`^Yc9J +z*RtZq&WY~)3;Q$s^xM`NmDV<-5!}rIk(!9>9E%1nVP+rdYIOS!=~#2^>j9B1ZKFq} +z3zXr=&zlbW>V%&ECO>^XKYjQm@h6J!2f90V|5{wTNXiAcdA5;xNh*!KyUM(xCt$1& +z2~F#3tMWa&)GE3DQkUEHq;at|{EDvD%s=r{Z1^7w(`5j-Ko7lCceQ#BMtbA#%#KWxXCp3cmC`rfwLh9&Qx$sm&OP5si%4v8E)wKRjGE?;oS#x_-dA5H +z-CyKObYoxF?^f=fkJMg==(e^8D@R4?clpO^8b +z2Yq+Z?X{6ujfdMsK0p*DowF`K%*Z<7K +z{408=H-h%tEmM`Y_N{$oXHWUaYM509M>s4l(lc3r|`vt_qZ{BipM)>NcleQO;q>2`Y3K#IZFGCZ#;D@!*X&#O +z&4tfwFK=8f-V`*q2y>Q|GnAIYSuq<_pfxX*o)O=NC3uNRaeH}s@%nf3u?`lq+ +z}N4+J_&CLer%gIRa`vg<|rxDn@ooXU;v +zvIOmX?D*Ssu^WZw4rdjTt*4w%$AH=vN;U$(OjD9rTp*Tik08yN;AW;mYx~F +zZ0EOLqA6he(9b7AAhBpcUjPctADkaFG_OT0jN3B!JtlkkLYWgp#g*2oo`xLZdq<|x +z4^T)6hk6PB`Dmt>z(g{3ayPIvPHm`6Y3RWrL<(E_LO&HR4ReC^x~AUIp2cZ=n|aP2 +zte6jh86G)WnB3DZz~e(@JUJ0|TT~9mL`Y2GT%6WW2~gjX0ZuCge8Ga=n<*|dtQKv^ +zX`pULq)M4}rvOh6IlSrYuE$p#$jZP-0eWAbh&@IkgrohDg5ItLBdk^-fIpdBpcz&o +zPWxTcWeX(|RBy8i7M!!Ir^3uHTcNYDVQknyz5r7kHzB_ +zUNA!xy7z)@P)fNAmJOTZBDG`*X(9jEUQLme)4- +z?9^2qGwtpG=^Ifi3z5NmVXFpvI6w0&hT5q@w&50M#M4o;bG$=J9 +z#js*>f*Khdj8@~pTrHBn0Zpen87BLlJ +zjbhkE;D|Gzm!j-9M$tOE_Bphx-o4~!hk2s#6YRT= +z74Z}oA6V6cMAfNZNs@W!uW2^l_1BMCeK!V$W^%6QxQG$-vh{c1oXR-t327_9qR~^O +zlG38e|6cG<*W&&_7WRd(P{fTl5W=yM=vejpEz&%#-k6UP&paFmUexP+n}zyz3B}^n +z#Mv<0#_I0;?O3b!?m(yDfhDe*+lZTsK`|4N?L6LW*EY2k>(}YoPR{Rad?)?O7cuAY +zWFL|W6v;_Iuyj&5pfl1;8!eeJZkN!mowQ8=Uvb~Nj#JxAQArDLdDApg!qT#R1vIn}UV|o(h_58MV1iSLt-9;><&I&H<*R=o=VDn2{8N$5A +z*KwFg#)x7f=*V)j7vPU8kLNBb8tf10wRq*FWOIBV{V!Z@xv*vA8{lk{1GBE4eetk~ +zC#jaXXS2vpFX_c#*^Tz5^Sz}-ch!!2)9$+P`eGP$vrMw+OMhbEH*GK%uh^s-C}n!W +z!0(tKIO%$h`f>f0V+EaF@Pa6oxP(((vpj(rPCJ$pA!h$*mEjR{{Me=Ny#IM}QNQEO +zmp}oHH;Pu_7P2Iy$Av&x3PqNYlz?o^PD1B`XToOr{dw-aZ5DF0ySb+udr$hor=FI? +z`$u2fD1*)ol%{~#h-fGyt~&O)45nSf3G=!Bnfc;>MOvZ@1YA5JdGK8acl$$&0vAvo}x(mGPDbZxYA*sV~#iN6Kkk{ +z5h+NG6o}ov$UH~6d9`5F_ARY%VuhwFsB=UrikoP$pYtkuK0oQY&qQEsI0sS|m|Rb# +z3VH6g4{N#Xj?&GK-BbPWodBpJ+nW_&{K@7jXnN{K0e_RS@v-L4o$6=InIEyd8*gqI +z6E4Xd&(C7ul}%-bxJRn|am9Rplhi^LJ(6q4#6=X9eEL23o3ww8`J#v-ya#*&7Z$V9 +zQ*fxUg_kIEIrV&~9K=F~DocpB!=2s1=5`D}IPsn{-e7-ENVs_zQjgqqS6$rhD}=Mi +z2%CO;UG$Q&h&DyB+2)I^#;IXp!us`eFy-J#`q0cJ4>iU>Le9CG%QQ8Zj+tK2K0SB- +z&)^>HLS#Fxo>FNP&x)y_2@_6IA_eat_Z`0qL^)H4SUh?34O0j%1(NgTN|#;xb#CeK=OWMze{-u;VrbJ}P>s?1-!{opmpZW!I^WsH +zFT9CdmlNI;Qowm*)+jzSPUTlf_aogvkbBJpW^HY7T1VsyeZh}Q%@jhQvOP~v +z-GKbd*$Bq=AXQ>?SC&u>7SHl9+D}rYG^02Sp}D_x>(WZ8CzX7o_&z0!r+3*=73Hwt4Mn-6RSsUO_Cwq2bi5V}n~AL%IMP@nhj)2%M?}38iw4g$k?OZjEhnrM=GdUOsmQaZz$g~Fz7k?#RuBSE4PB$U;W>i*WAe7Rw +z=_e>bVzlgG>^!Aa`=Bp+ey1-Hha`?kr5exWXcOg2Zl3=w_oWbN^XuNe( +zXMUwJcaC>K1)tthByH%M^5Syv>Bij3ac+%oaaEGAxob1VDBLP@dz7iVu79Y?dI4T@zkGg%h4m|3#GVrFhJ +zGcz+<%$6)>W=2bDF*7rR#pu<0@668J-F@%Qd_VG>$`jS6vQJe;#1oP6MEvBoZYSkN +zv$m5!@uz*Kk46eZF7%BkdQ?5xuKm*3c>vzGt91+qXYXxP1TBOshdb!VZ2#o;^4! +zsVZs8I^05MCtfAYqiT4M_bh@X`uSNyPQegx!x%OoYSevhSzkj1{H +zw<{;6uu`BmjVkhTcF%dsc2BP0h{7Ud^PukmwJ`!o%PFtx97D2;?Mf0-@dIW?sE%Ff +z;Sa0y$zXRLhPCI0N?i71U6X7dtB!3N$*f<(tpT4>5-W}rSzVPz1JuqK +ztJkJ0cb~${m`R*ZL_j-0ALX*Wc)}xe6zcuA-YQI+7i>O;r*GI)Nl%}W{Sg%5(xRn4 +zBbQzYm3ha}5GcK+oTgo8TD5}PRXs)N>5Qod9Y2diWw{q!xiJr=_i$KD2A2v`sx3vm +z^!M(M^DbRN~le=ieg{ +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 +z-c9d<%ZRHKtrm}*&+p*0q+@D +zkUrLi!W$5_zUO&AGGpsIz({&gW@e}2Vdib{wj-AoTjg@LTd(Yw-I7Ozj2Ttz;~rCV +z9+|z=NDsv6y;1uf=RRp2Hsf5iT(O2sVH>t72aLy93G#uP9Dj7;A2B`FwJ=kD$u;87 +zl8?=MRz;U_aC^9Sn?RPgdUho(xm#!tgx8R2%XJD0kY{b +z$^Q0!8W%WFKS%^M@k6vz8`zdxA&1y8;dP)OCya3b9nqFjs}r|Isp}I}`YtFjGIQZI +za6`nJsfDLI631TeJ}==d6{95C=|?I-(AD~Cg!*I&bmGH4-Fla^PK0(-?Sclm-b@fU +zS5FWH9#CF_E^k=mX0P|pa=XAlxyJT(7Ty~UJzmE3{*^MI?!B!S1PuoE +z*Wmaclp=|_*cv%o*x5Si{U5LgfbD&hM0NjzJ%EtOCh}uK{vYfCAJhRK1OoqtI^c3G +zg#P3H|4tnMt^6O<0jr~qD?GTcS6vWR-M!1%>8yx!lg^anrwso4#|;2$uN9aS5Nb`c +zq{z96eb4U^qpF2b)jA|*eLUUssoG)L&$qjb={i@bZcGpNRpioj8G8HF2$k +zwP6KC0IEj*nb~h$&9e#i-!Y#ZgrCSIy-+PdNl#Bkj)||#$JwcK>SYwIM(}YR%%u|N +zm2n-k(jo~v_Jf$D+(t8T1L+8#pVZXC_o5_)OpUiAJzU8bN0j0;XMYc1l7H}vQ`QGz +z3OZJtStwz&X+ndDZwMvtlldjHWqJvfvy5W_0md;N33GCjLd<(HiEQPAEp=v6ELCTK +z1WS&lG$o0qG)IXdF>wfsm<(s=pmVJ&O3{#TT{}HNDC&`g_bzbhkTGE)INKm +zfumPN_S@h}Im|#&T%r$U*H#7{fp@z+aQB%em3&a*0$x*3-z +zmZd)P56%vtODwR??l8(T<@n-IE|+tDlZ@R#Qmo7K=W}>E( +z!5&*bk9#;FQ!W_EaB$ev)NE*{!cZ0)tww`1!60yuY#!V0jQzDW`a2I`=v!9P>Ia(K-r7%v#^;f)Ca=g&kZ_cp6IYK<=?Y>Qzw1Xz +zIG>k5KYtQT4JYIuP^K5DJB;0J!jh(RT-U +z!gTF6=kTu`e$Gz{=aqWeq~-1>m-1+pjks7sz)1Hk5 +z?L3rBv=nXJOp<_cYT-6Osk~CeA1i5p7cSX(amrYJ6fVl|JRpXWk)5uUO#kp7q1_%}AA02;pIHibz-<5bJVkY;A|_rW!olOGvh$NX +zI+DlpoyDL5ig%!c&gbF6$M^wGk)4O2dN`Dpmc*Di6@9*yX>6L%+4I(~S7Ka$n1G>f#3 +zEB+`|{~5%lz|056`cu_bW&nZIecP%JRfn1Qo*-^cjzIZSSij`tHfTpj^dl(BSEaKR +zmi%yA?r`M6dH!UCy*Wn@q>r>aKtrB2ESNPkaR{NMrj9&BjF5iaxXOID>yLRhp6BHgq93^T}ahf+5FEbl)kHX +zU11Zui1TCa-c7KQVbvSnlX;g#*Krm29{c^8Gn-8*>>IJjsA;@Ea>xpl45H*9LL`|1 +zzsIfJj&$&=pbSF{uwx?HCV`-8;tWWh#at!uMh+WE$nH=4<6QL(Vm!ta7xbmYn +z#x@hZDGz-k_R;D(3l=67~|Mjm{BPM;n5gV6+`6@P>V!t17riQDKJx +zC_Z4;mzIs)^L1K)Fmh@ygD6!cHy802*o +z1^RtpS>t4%UTmWY^z0o_S`Cl6h7~(g&58UCe{oHjYBK#`HHBarjf{cp&z9Mwkr4>- +zITUG$bB^%y<>n5+!;oQ@qf22*mLH9V!@U>l+&1Il7Al1D(T6AbL=HXeN%%Ti+1@)6 +za8PIl2m-NhLmZGB8RW=pan?@F;~e2jXuZyF0hpl-^G^omB99-^B)I#kLiM&-bsTIq +z*lVyOwv~;MWa1P_+6U%JbpXi5>(PSr7X5CHZ)w~q!bU$*s?8i*|(J77e0WU8)8xl +zJ;df|I+XLE2Pl>;lW}O%y|AMtY(rldp@~@8p-I+@M5t#1+E2vv_TXOEypRrsi#aTS(-0do+Yd +z3v*tiF^a-a5)+W`wB|Unhs5Zhwf?KF(CHJ3NvOV?L@yVaY;p*!6}HaCQ&2{H-No4t +zj*kYHP{s>c4;vOu&2O1+BrDz087gQgNxEQG%cK|GRm$8MH;3-z4WwTTm|0z@daVjk +zei{!fP>l*lLU?2WUfsmCTacT!dz_+%Y1@$rJymQ7-_$ZW6*%y}4h8ZKI~XuXVW`th6Omh8!!ofIbr()? +z#TD~eWNn<3V$Rl;@Yf&l7rK$%&Zw^sR$G0vJ7Qcs)2-@*96{kg4h6r+=fl|T(S3wI +zN2*r!B@GmplNBIFhUw;^FD~U^yntMPpYkS8GE})61qti!a0t{Y`opd@+2}dmI6rvV +z-Qs0$p07-@2X)s%{WQK>JU;q9+nd9Lj|gk0!`lwWR5lTS({-=M)4u8jG;Av|CN$ou +zic3E;;cE +z5BR_0#pxuH9+VIIx4#C<-zcX4Mltt)Q&;@&jeg#Ta{Q;!ziq$8|CszI)7(F?qPn{J +zzcKx-cd;lRKlvBapYk83e_sB3h9D-`)f@cA3(_c{7lZiNmF?Y1FyRl<7NFBaz +z>wmgN&jaE1qM(4KczKZ0lfy{zsF1~vw>!0^sw>FMj!V)}UYdokOic-x%O3DC&E%rv +ze673c3|2Kym#HhKUcmmfVE$Zm$rPpn(!z7B?I)kPWLq4mu-!sLm}j6T&l^OUBwck# +zj1s!!&CMoO@-zGf=)5A2=SN-msiQ-SY@nSA*7A@~EYGb-9&=tYF8W82Vs24n(42AQ +zt~3ue(^Ey9qblJYquR*pxD}}AP%k6O5tsI@b;%IQt24%Hyi?dvZOw!)$t+^kVA-&F +zyl6kNm2}__dCDKZA2{Vk7>v|v8@d4+08Jg;Fn428Mk+O+2wzVZX!+zR^;cayww5wO=_rf1tQ8yWn8MBdatUxu-X=+&*4^7XT1 +zE_8^|*L9e+D2;W9QID-$7arXon~wy@|)JCu^n#?v}P8hw%7W3;vdwD +zSur(#6)x(vA>qcay#S%W)Lz~EI0XYlug#Jqx^AQuR+j#yO%&!#aM{qcF7CqDA;xe~ +zechZD`6ka%h4Nym-Q)IF7w&Ra=<-@i%V1?e)SJHYp0;>h&ucD1E3aew1q}aK5U#4AA-T|w^2@F|#IClnH14G`Vf!yC_Vr3NPDJ$h!d^76 +zAgEpmpEwd|Yyfh>J-Lk%-rldsz?o(!+Z#-{EBMO&21}4Lh(0`>7Ap(Rcf`&$4a88)E(|m1U*e +z)hA|fGA_{|Wn6#1IJl4geN9Ng!3w#?B0WCQe&Kyxc0|NNO<)9gaa80`lCSxXjY3R&mbODE}|Hd +zi})Fr@@}izQ5ee9oH#bA7%>58PX`*BDfSG=SeyPCcdY?42^QMw*p^>SOB_2h*lu+) +zW5C$&eM>XvpNgaS^lF!W2&EN3^E`$&$@1QrkD+fHRQ-o-4>=vI(W4B@TERjm2AP_oyPj<1${xw?yN0Lgy_c<=*kE>#eE}E>+#DCW8a6&12?VK +znYLM3{NhaWAGQ$bEJP-iGXe9BzI~YDFRO8OHMwwV4|8g;-?=xTDoXV~o^u7uI7FSa +z97(ZD3hz`HL~o_>+MzpSkiV-?zRMJ^i6zB2n-rRyVbiGnEi+25{$T%deokN+h&fBz +zT0}lLyB{*i!O-!ge(KDdXpuz{`-QQ0wKfiDUeEL(OMJCer +zuBFbbrMc8H(uk-b$pGq`V)!`0p4~vLYA$xO9!Z<$!IUaJl$k`$@_TQt-6v$MZ`tiN +zw-_V$hb@$Hy=iLzl)CSCZs$gA=4kBGUuMLjBvy_v-~mxu?mZ~!X|+R{^!OUd<_5Hu +zY0(8q-*~G#P%S);dB<9oJod#59X7wH?4Z7Vi(VC1?EKYk8uk5%0Ce>dN3LP3^%54& +zDiYp;_jOgT1EkV4G#fJDNZK);(ryxTq-~9=7~%JBNCc@niFwo@7lL0btW~VEptA45 +zSULvn9e=V?_l9g|X +zXEOShthi8sL?9ZjI-FHY&Hd%cZnR_LUxn@}) +z6*G!=50YqiSzF2SSeSK3=Eb-u7bzWG5uN8b0B&m-sI4qMw6%Ja&JHZ`e({U=yhc*< +zXr8mFfX$e98T-vkd1fkFe%VC3-^yO2Y-WO~QiQ7#$V3$uZ~MX3ER6ob;E)KU3J*FB +zNb90kE(#4Nvdm4P^=a`uNhoL;B&UcUI+MfG-OQQ>49?RsJ}@BOx?;i{EOyH&Jn~@Q +zKP`wyS{1FSMA&CK?Te4K;yI1tnyh2*rUU%0>VPPlnU1ESiZLafXg;hvXj1*V+vi^4 +z3c-1uiaC`EN@g9bCsA<8+aiR`d>7= +zGw*+@-Gfd+Ew)d{V}Qk+bSLgBt4!^i;sG;%8{~XOI-pCkYV6b#0bHD4=vG8jILx^! +zU&)bg#?BSZ=E8cw#7%I{400+}+7ZqL>f}QgmV7(r>aC4iq2|Htn?zEr!o;}kR6to+ +zOE@Bk{DpOOf7RL#$`cIQ#-=jSQUYu9F= +z^M*YBC6(4Cl|r&nnP&6I-C)EmfZJM}*G<+q7cOu^^sZy$ogJ`vB>|ticr&;?KmMMS +z9WVS&u7L#<|M&zP>4=0W*IvTzCvC`hZ7%5NH?*bVqR&)uFO)EU$B2@aWu%;Nux71t +z1~(!p+L?V6SB7*<3s=nx17%&KeX&>yPZZ$zS(ikR%>W@pW6x_)ExHZmZOvugqiU+a +z)q5f0cwW{$DUVK}*{jBzh^0o}AoT(4%%v2fpJug?bJR&>0rT~uZcJylM+29Xx-9r0 +zE9&Bgn4_l)GyjxsJ2%mVmM^nyUryIH?&;(nDo)NyF+`)BmXX!3t#w3;kv7bOtQva_ +zQi`cfU5qo%{fcgo%-Znh^0JByZewXjNy +zx^R*#vdlPYG0oFb&o92bRCJG;VHI&BuS@oyKHg^AIqYd)Wh;nlO@?xiZMP^HH-}$j +zercQ7j2hfTsORVx3(SpLzFU-KfqN^hO>v%P*l;;kYK{gER77tH9K5MsS-4K^u<_ +zGrI4ousr*12g(=lmbjoq>R5+2nWsh{c9D7;A7*Rq{cU`+Y!i6h-`IAL7Sa8zctha4 +zPC4|c&Mgybsr0Z!~GnD8dG9x&j!h?>BW#945cq8}N@e%R +zw2*U3OF#u3v`Spkd)@uGei9`rtERyb4;XSkVb?j-l<427uJCb>cnYriDwJm +zcBuVb&AqBd|GGWW_dH9YMI`B#jA|9jLbWn-)sctorMv;+-${sNiT1C&Wm1NPY^pLf +z$0s5A103j8G;@}cWpSi(s@0ejMT*yD;rhy|`-cjmhz=R}80r4{vnmw3PQS`udy7i0 +z1=n)ED8*dn@M=&d^J=tZU}D8Gn!eOz_wW$Q1iX6pkiwU``LVo8fiq*kny2{7~OU^6R<9suGdB!&$02FZ!@bnAc? +zN+B1^#ta4aS*7?q^ak(bpE4MkC8oz?@p;eIPc+ySrf&^K+HxIbWTMb&p(D5HX$1#I +zQn4cnM>M0p-deTFs=V8D@}(->T-Ed&B~l>yYeqr(yqNEYj7^SZ>A#h?_SVP3Z?Ddm +zc9c55VTqG@+PGFR{Uv~KiRJH@($>~>8s~jk0>-b@`=S)5deWLz;Qdwxs+vC^o{?A+ +zo$LCo1g>-lDXDXK(H3Wre*L8Iw(SDJ$4xl6T` +zDP-Lw`h)b5L}DroXq#zTUQaA>HWd12=K1!El{aTNaZAgxF8kA^Vv7v6|6E3z=zZ5y +zg(^$uHCpN0Q>$;nD62bP_&aGl%qctgE)L=A{c3goa`{`>%9D%>0IEq9Il0P$R|8ny!*C_Bs)k)19lc6`NeNEsDdTBKiFzqq +z1vho;+=|HroD;ef@g2N@oG>VVM*Y^bT1%~AXc^-G6tp>G`ubCu&gRAuVOb2 +z>*mda$Bmi05>ZCN5Xp`C6My!{b#IF(=aAe_h8Xe5g{Bp3Libyj^8yBy+dmTu(-7sf +zyJ*=feWPhcJ{x>?Yx}popXM?@&LFFWo!Fn1M?K#b*dCPsxkuTYe!1REyhjZ+@BVlg +z4%4D#{&w(M;Dtb5jM?cGM#;e$2jTW{+wm79tp_Tb-*e#CWlWvL9wD10ky@T5T{%6< +z7#P6T)|b7>^0a?!<3#+jw{DqmjD?I=A>-gD)wD$*SG8W=NgLh-Z5{FWTiV#ExYv}B +z4Y7;Q)yMYkw?~rCFAHURD`4PDtk{0hM{4J@jIC2K+Gq$V--IzK6FDmmu+EMzO(C%| +zES-}|E=U2=G%C?17ruf8%?P2A#ZC%*XwbjG{vYv@mx+&9n?2IspU-e|c62dv{;#N; +zkdeKDmGd_PX9GPw=f95!?5l6ut#Y9HPU<-r)pTekbRG=pXbMjKw28!KS~#=7Mbs*w +z_<~s)?~HL-y&0cGwPe9b~G;y`N2yN2cIPR_fu*+9~$=EU$qK_I;_Z4Go6Hldv$KMf^8aWpF_@e@`yD% +zIVdg(H@MM|$s3y;lybY+mckDRbq%FbR+wx}@se~#QdmMaoN1%3`bS6xnYcq4o^{zX +zF`s5&ZR>LIb&M#O{usfK7G5IS1V|~CrlYBzZz=0=tz&oV(Ym4CpqnV>d3DZB92dD$ +z!`JeVjIH#Aa1nCi0nC@5QQiOi5$PEOPuoN&cr|joK4fTPGcMYtgcc<@!+^94WEJ>r +z0Lj~r)m(^H$(R-wnC~|_*%Nl{au60%;+Ahd9pAmT +z1mAA_nFP5XfZXqWhQrTqV5*^;R=Erck$~8J_cxbBjS4nlQ_0h^Ez)XQQa*=v*xx-e +zsvTMeTbmyUo!rA7=(<3@Kjh?!m$_x?9PS6)zOngVh=aju +z%!<^Y+@$-6n_k4FC7-YIXOL0~&&tWBuXi!h__-II6 +za4m95@|XYkU-`paV)p^K58si51PqM*Z~Vvqm)dYKmNfnU)f(sNx*u8tGxYL?b^@1f +ziGglZ?yRMh?z8LyhX?|cbh~y?3UvgoXdC(bz}p>f0l8nJMfB%@7!%Gq>g!$pLq5KO +zUnMn#;V58vfzxyATb282HA^X_?l~#1v+EwoK$FzDnFwejmt>8{C=(ghbf%-8x-aBq +zSpZN0G*@?5V2QSysvB*~D=hqY9W$WDGY(fokd>KoZ~~eY+9<{U$K+C)hO1e7m9RIe +zivx&p_IPdbbmT@!13~ +zRp&q-Ayh&?^;7VOzZBOWZ#W%On%M?p@RrB99b_s%ebPrnOuSGN6-sVdh|Q^21rUYO +zD)TLwg$w=uZsr@M)=i2QRigZ-`1I(=SjA*H4Wr*uNP48yYq;Xv_ltK%bN!k;zkbRj +z%cT>C#W9hZvdK>WEHXA_yQWabBQjBLnBh;}^(B=3ar%7P+siT$GN*f67q8NsG2suN +zJz9IU2o@^oTDKNF2&-$Q265TrSP(4-mSm;TvJCL+kqcPm}1VPRvh4+ +zpX81l0Eu3FqL%V{A%*Qd@_^V$8Ug(>G9cT_`of7d?{n*Lo|fVGu-~Vhpn`xtC8`+u2YAd{ljO-W%q1f%5hX#J6e(v(T~Ea +z9PT)=@h&*HK-cwZ;c`UB`jlUD#q+0(hstO}Q=38?b=NYlJ;{ +zi)`83qjc8CDU+-1SPy}X6tf4DYl{4{vp*j!7XSel%$$qR9pRxI_)xHF@1dK6mB7sV +zj^8Qx!#H7~>1u_4+R_1}bCoXyJ8U_k$vw!>-*c3_=PJKpGzkX@1=?4|9bmAO%CAWf +zsFPIPsgJ)p&Yl807UMKM!qY5F#}4%40i~$5v+#Q991}*=&*Voa26y)J{DYM}IVuoc +zaC$%PV9mAxxBbA!o>n`4unawfrKy#5%on4(j7H0p}RXf+z{!8ilPF8a%*W^JOYN{CyNt%EQtv3*BeYUDI3raEnr_LpR`Ag?+ +zW^h=dQT4{*XctIiuRdH8Mk?CE6JLUV?+z5v)4$-rMI|lW({eR22B# +z(7La3n1qiqb{-hZCt@eFh#dZqXIltlOFX83e_J^2@uDgD5?aL69#Y%UI{s00LGs)Q +z?##nQEksn(2MYm5rS-joQKsN_upG-CX_KcX>MI)MR-iH4Ndhh~A|2Qfa4AbJEMY{k +zm^d_m+Ttt+z?!#7Nn>Se%Jz+&yo$G&wKN2v_ZLi^)=lE=ThO-RrLy*Af-cJ!1_v%? +zY+57pJ02hj=QyhU{S8ijNs9|g9m+7p2Y>*mym)CENid{_>eS4h<`F0y!pWX5vq|`U +zALrB)RpuUi%2$C6HQPymn1^%;_jD!qU*nm{@kyL8RSiGns!_!}dB%9PQfP7;r>)4= +zz`i!K08Ltei=dJLJeK~Nu>z@5eCRlZ2^@0S>8!Rw9C8PGUR+%hrH0Y_NJU(6*3%CA +zkI=aoN5Q>#B_*6k-fbyN^2PUSECJ$e(c3LrvLe4gZ-#Nv6#RM)E2C{Kh&kr0B`Q8V6B;B8I +z0}wmYLY`mIjJR7y=enhI941OuDjUNlRtjr|nB7}!uQW2(MQ|R18xn4$vETX8Oj~Hz +z<3=Q7@sfYDPMGW{^);pFHsdVw;$=p4%Y;eYcj4djusn0=0D^AxL +z<{O3?MJZC};-L+AzrD>|n!5lN4qK&Uc<Zn@c!$$I8C$5VIqSp5bFwB^l;HPdj< +z4kC!2sQNT5!YygAw%CoEmT9p!E!u4Xjg~~By_mU@`X^iR6zc=b*6mGhIULoC*vcN7 +zEhCHOmRx0w#6^3MNbkJDl5xfPI +z7oZ*BCCXJo1R8~SgQeo^f}X$?5+D7}z@EjipT*@7-)e|%Q^iwoZkq*!gbDlvXpw({ +zBSE6ZuR_1}v+C>PF}WMU5H^|i{KkC|4$OIK0;BJIJ}bE@oIYdV=pZJ(g@Fwt9ZQ>T +zmp~axAsmvIi3RdHmZTa9j(#t;|BjPmAX^|=yLBHm5gQBUgK+yk3&yX0jfKvu`zOvw +z`SZ+=;{)Q04D;cXR0Agpgl2*=Swig`9h^&fh +z&2@4Q*(E|k4!wEu2EtbcSPsoTn?X%Qq)8$eTrVu@}+*cK7gqLv?y +z?aM8%Qi2Vhhd`dnB=SD?sjt~5JK^@aQt!2uHSUanXH8a<#;pEY2`N<2%VqOsC!;|A?q~&v +z%V0Lp*0|TSw}xhanlTx^`@nDyS(nddn=GB0QF;Br@$^Z+@fVUyR<9#c>a(w|J@l?Q +zddwgH=})lxB_DWLm^Ae-JS_ef9xfI%|F+?s;Pb(kl7-C|V*x{DX>s~+we+nl$rb3x +z`INu|&)Exz*}jjXP=km$FY@bgdnB*mH8;$6{0k7*ef`9+EaZq#nyPZ2__e9BcfftO +zX~x)s+czn2Vuv0Ex4@yv0rDS!7(xfs%i&TPgMxh*B}k-Ji}rZbP)5Xv>!uSm7{-Ds&Siuy(W#TdtKG=4q?UYqzY%J-0m-;xRX4`FSCZb4?%^1`H +zi7Bt-F|UZ#PbExC({GAAj|&`GRrLs!CIl(2G;&8>42@20BgBrvnOP{XHrs(DvE{+W +z>Nt8G=hYIW%ro9jFC$4AafngNA@34JZvbmqSaOXkE4L#28CvWsytR1bsFF1tU79kQd0?cq8%V +zd^c&otlc +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 +zCx?k%6oY*|C|- +zyJa8uWhYH_Qc;&fmLM%RlvhlSJMK+Z_A=O1W|B#EvTlfoEIZofYIulsO4u)hf*T5E +zZ9{ic0e0X8#a`bDeKHJ|rm*wASS03|TU#PiF8s_iKz6UtidgPT^)3}DO7@%vEeo4n +z0jxaK`;}@2{WslT4{yoCP$=1pB)Lt85= +zU0qWLeLFK+I~!AFC1?<^y&@gSKQCoBa1c*SG>|Yk8ButcFEBu!3SL}HNCEh<7x)VL +zt2}^y^28DN16Rt7!$RX;Z@&4gf-o%4(j)Y;C*^1goL!@MjAIf8VL1lBd$e +z!Ft8Y_yig;=H2d0XV%fVw`Ow*Bfw7%6#-sbA;R=&WATU%s!jSk@?*2w9BO289xb!I +zn(`s5futDKxn7L-xUfJ_3JRLbNz_4Jo+&F>3lE-ei|FxzHx0^eVbJsa+2EL!n+JSv +z1UTKLWt^T%)kKbTu_8%`)L{^le*;i9kta_OzOHNmLC0yn!|bfhr(&*$ekKw&6qAN}en8H^Vz9$Ofu| +zFf4;Je?vOXeRx1N@g@hNd8EEL)VQ1*7#lqj3QkPUu$1AUvwO}8elt|X5wsoS1X%kG +zxXwVk#P?6&=3v@l9xo?!`lF<#xIGDG3s~SgK5&?nmv&nMxD$rmUte(zu;{~?#dv+P +zK@8U?Z>~hM>A5aK@DXieRb;I?zjK51+$L~8VeIpJ2hg|0ftMtRs7P*b=k-epX5B_# +zCZlE)BxM8sGez9-#HUJvR&vv +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 +zdl))wsNGq)ZXPF+FtsCj%0Ox)w +zx?q%8D0$f;&&#?zq@?#@$oVHfqYakyLk^WVe747W!`>t7J-4BJPa)z5A5$AJK11m_ +z4(;sn4Zk56)`z_kCH|RE>lWAgj`qpIs%t#a^ObWu1OV%mW@Cq*m!lOD!pz^9!{Sx+dlUb`M?KLkZb63oGhcC-Csk4sqtwDr>YXkiRzB+cBfyZ +zh1~m)@g$4i9BzC!dV(H2MSn^Mr4xTGk-3(~U=L?u-cm|^tH14AbQi~&k0FSB<@k#r4caS#X*zo9ufK*f&J5ka1x2jH{z_3RsJ5J;A@bQ%=k +z-{$l4+fMCEdN%$jIz7AGy6GZf;h#-_^OEQVMKJ4WP_p9O@!K#pH|2wUvZ~szPcqxW +zqj}*(^pr?{<{NEU(F2#@CRm!+>|0n +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 +z_2Z}e1s|Lm3Ym!K8^uF? +zxspUjPX*UHd`Iu(HRaIti%ql#ryyxF0JW5{EQF{a@fLf8k$I?zdDNB0lc{yY$Sj|S +zDnuSdwtVl$#jG9y +z`!KY#-M4x(!@c%u%@F>t^o^O!mcLzLUvCvs6N=?n`AD}iV?-rZK~`w3;{RhQamy?^cnyopG +zOFak>{U8@NXg&bJ%Nu%b+-=6~m^$R6`ZN&MvVWOLO5Rp&NXo)h%9&#s6dmg9zoT_m4*t*THqTa +z4dR}|b5VL4n@NksWKNmp%h(=Uq^BJiIG0#=9{efS59F2H6P(Ints)nFG2%Bn^CN54 +zed8u(m3fAxw0>RJNKWlsZ?nLXQE264df4ar8a;ao8e_{oED~x)-Y{$s;pIVHZR`m;kCOfJ<^oDP6b-z#aq_XTXw}c4kUO!?(%YN +zqQF1Dt!*id)cW`{Rh5??)-~_46Pk{Y4h+4Azb;UqnLR-C!Q{~M7~F@}<*I)R6@HA5 +zA;uAjF<2+ccSbP>1}_gr475=uQGcS_l*}#y1Maz)c>J$8r99g5Pr&P>sdi4(o!l_+ +z1Wy&)CqFut0Rw67Ot<(W +z?JiN&G9WkUiieQwPQBtf%^@RG<;YDjs>W^Yjw$mqNx;mdD(6$EZSzjqKE1y^Sz@dC +zpUkC~mX2Vyi0(`k+Ajo)J~mi|y@!JOWWOB;{_-^m8_P*N&?f8W0QQe#g|0mIk-6_Q +zx|WRtU2F-^TK0cME^ryAvH~Yv%kb@G@Iqhg7_C+; +zMAcY%U(NwfIa9W$DqT`S7*w@)(M!D;Rmu2TRXi1!E9+(i`e3GURt6Gj8-!B!N!4*5 +z{6$FQ7+wy7;J1!|P$+%-c>45aEa_ob0Qc7 +zZ^4bniK|p;5+iDRsmoT|NQ-}jzC4G*iC-OJ|2eJu#h~9Vy0V7E(i)2`0#1U~SQ5L> +z>LpG1N&k?|Fb%g4?Y&H6JlyLXmW|5_eo`KK{CDb%*a@VdX0C#gg}#t7S91(%@!Bq3 +zg|U?+vvAx`}6uQVa-Os`;h3z +zmqe)}w?>4@uCS!y5fxx2@Mej-f$iD{H>>>CS)5|7Q1 +zOVmTiqiK&d>995F7GFnn84}lgs4D0Oma`J$g-~RYiTg?bwK11S7$FXtJ#^)80aoen +z_YTk!9a_h&K~$TH0dSH(Hlu)Dk(UJ$zCUjD55Z0iMQjZXrHlqEbqGV(ddK&Q;Gh*% +z_i2Cd(I~aS0(-hpo!Vv;enD0l#JFd>KFM`+wLc|o-_|F1Lt22TyhW6y#eYZvu35hd +zMhKiD^4>FEQ@SS?LT+qn3Jq=tTgL<*H0CK_;8U$T8hQ^P-K`mg$VPO8hU#9hd-X8E +zcNtwC)!n*3AegK$zxHI1f9}2`_9HGoVOTDni75JHDbc>LAn{9rENS_vw*^Aor}M+3 +zb<^_jNHNLpyOB +z6WjlI=zE|cZ@bHmJLu$*8nX4A`zJz?9cw_1#P +zD2Wt5^$B|G3fxf&4335TmA`wIB0p8aPuA7j?$m^oiAwyKryp0gRi(Uj%^wNFPO3FI +zRu()0%h254D}A?;|hgHCXo7QHln9r(QTmJbTbJ>fQ1iMK9VHmpPmI +zTouKvPr;y$&Vhu4V&5z8Wd#Jen;byY`xaX@H$h0yF64qXIB&Ltq6hAX+nJH%M+=fO +z5if|s^ir{n2Wv_g2LSS;hkd+1J)5P2%9-s%z|!a`lZ}04=%J}bqM&ey72rM$G^oH% +zVe1Cg9rp%r(S{djIC8n?uP|8skYrKPr=d_5a*D+SKQo&!LD!@Yd_G49J6T4o5rUTY +z!KaV5UR!jFUN3baf~|4Qoc0?RfFl#~p+@g3kSh~9ekB&h+i~4Z*JHxp)|x5ASBKX-U?+>7>Qby85t8 +zQb|*ouY|50S7?P;RFMx5W|l%GPrcK_49M_Mb{A9i8dej!Or?@Ucc8wBS}XvXndbBy;z$z>B%yDzuxF!MS`)O7^Q9nwyE +z496E8Q4qI;e1)RUo8F|Y9TRcI<7&xly6xW9BkE-*+ +z(=OM~FQxvKXRT_&Y(GM`7CqM=LWzB^PDD5Lo4H=HXzosTLIL#HCZ^L3aGYQjp~Z}w +zg?^SePGHPk0$-c6A+bW)*GYo1AOwsBu2FhDk~40~BmI6TDT^5&j<=q!C-BIz$RkGh +zktt@m)&ZQ9c-Tx^=-cjUvkyDKmD}{6(%w9!aErZ*)XHhqoobLJEd@jou-4XyjeCv_ +zP_y-%j@r_SJ!F*A7#ljTFsf%s7}4;;KP1=MzQlc2mTEb&wAZW}IH#FwQx4mdY`Ey5 +z9g$>RzIARYT-sPn4qGV^8h4o6({oo(*PB`zi`Jpz(kwbqC(%ge!i1C@n+5mm)X4s| +zaN{&q&s`xQ*`eSAgM%CbcRpp52LYK!dgy*RE!_C6_ +zb+1%0DQ66419E)InCXmz*SThORiWmKqb-`D@I;|6xLz;&Fgx;qezGWlP$QE(%`UlY +zNzIu!i02otB=aGxtH^v1;Cd6KT{9k&ytfO!^)HSn;Tep^31jTf*OC1ET!1itrJ7fzP;(m~$%Pd=)-P(*3 +z-n1`|keIL37NlIiqAJiE-#cD}&~3Wm>n~Ic1}+KGRl8ctjg33oSJ%E^>^k4uWJ4~* +z)g^G8uN6Usnp3ib3lnLj|DN1)G0-g310E-JqJe<${7n%Sw{djRw=pzUGI`jtYGk$#z=CeY%y_)L=Gx*Y +zz&fgo9RcObbR6{pjgVm$Au=Z(erh7*q)3R&6!4woWmup!`(;dlYnEIbn0f6cY@ +z2o@jMyu}w;oKACfnWBUE?H^;A6DYBF({OVDKN3VB)A7BXTsT&9&!=D|1qw+e(+MKII6__?D=e@`uIHJstY4r`u~2|x*#e;OC?t6}Zg_tBJGJXoLn*s9DM5X5 +zly7<|d)|4L#gS9ox~KqZA)>qOt_3SXL@YoBt*{`1>d@WI5d;#z(7uo5c&Ol>!wq|| +zWq2^Tv+>Pe1VBNTrbkeQJ=j+#k1zTP?ke0O9 +zyx|A!)^BYgbaJaea}`)Tt3(H8%_dh_nU3b=I~mC*N`eUp$LCnM-YeDG +zxCAjF)>;&3@s##zHG=!it_l7r&Mz<`>8x8CIKajrFRKZgGIiy~rAxrpXlm}H_@}7Z +z9dRQkKCZCFq?ec4ip>QR&Z}ZgiuSRywRtBl^B;D7Vr#mR3t%^`>5Er-Metahp<^>{ +z;NxWPDVTSqn0F^1;O|H|k`$tClI}D(AM>2wd?DMIu8V}cDuTPN{O3F|FT*e|N2nrP +ztJ~bzE^&D)eBRIDvxNpSQ0%~i`sn(8B7X1%%$4VGP0wf8j<_JoE$a1r +zO}ERv@eSc$hssWVlUy^Po;d;a?C&O##T^|C8U9wot=j*UME0rEStpTHQ0Gf2uLyOa +zPj}J{>B$w=_$m;GFU~UQ^B!HW&&C|33J|OIsTo-EytruDi*vWek;etuXCa>V-Yy0< +zRrazfwdcckX+%fS){QiD5GG5}VEtU1?Gcw`6q_1rbSF0hyu?wSnH>fDiahFEZR3Sn5OgNUCB2?ry8bhQ*%VLO9(5xcyI4nX#jNQn*H +z1fg9COpfoOuQ$Ysm6j*0)3})UOWG!?Fx5?AI7W}UjBRbRwI2;$G*l-Q{-K#yY}rwr +z=vtEGn7+OY*a})&>en)ARz$Qmnx!ub!E4)=paJKV5Ve806I3A5ZS2p)O@dCP5E0v=W}YS38J6a;I?TQ +zAnFfS@;tH8b4ZWobaj7!bCy3ee4RRbs*;WkBXh;v1qYbZZ&V6So$e2xa?$tb&?{PW +z+PM$aJ#BYEwjfgecHB{I?f{;KgZcL~f#2kb&E+TTm2?wS0brcf(eW9n`iYK7|*@k}MRppJ%$eEQ)HG9yk}Z?94CblS|GK2)IneA*##&q^08bdVg7SuXOgM +z^V5p)$rs<4M>8^lM{|#*FFa33mYM>s_Ojwb^U)>QeOisf9_3JgWWx9EzJ$mAxX1nL +z;a8T7N;9tYj7FlJciXVj1jaMNfTJPpJ$oK*VcD6Yr`vwCiHD*RI;_s4`Csr?UX`Ts+#{Q?G7%q29|cu{6o_2 +z{j$)D2hrOWsq)MI9=R>L}0@w@MwkGS!|dm8H5plI;LD3cH +zsVF<@Z|&G`+yPdUz0%~M4iRYmVoNj?UNu%NXIb0Zl1+eaKl&?zdyijv-`9BvQv|%9 +zTesUNAcJz;9|u>i1km6j^MMk64T*vZmC(N=J1VP0t~Q&FNkOwCP;vgi!foCBC +zdm)hs=Hv`Zqj3fNo=G +zHG`a&YNzJM>)}&^wMcdk-W-NEE?El14?^spKUZ_yiZbav>5|=ET*3&}nc>#4b8VqD}RBtH}!=iTdxnw;$F$1h{WF6KP&XaYW +zpNTP66IDS#M1S40$3mmz^w+CU+!gWYjr@RaYnSg(nQ5M}T(o<{>l#JzI4~zDU7Rzv +zv{&*fuN3S%k$(MGzFFKQ!)iKOCsR|alvAr^Uw<05`VgT#!{rQz6oMj|f9mMIDR*-< +z$lz7(M$TAHKM9GKTy?B^PS)uK|AA}&7(0^a6mh0+%>Sh`uvJ_^9!f@ja`|iaiONRz +zojh#V{8$#@&#_H?2x@QHW+nusg?Is#XXSMQ_Sv_-d~Z=ZkN6*4s_(Z^ebz3IJ4xqe +ziQ1F3Nzul0=a5w;G(d@4BsQ_;ZmH)@br_cLKN&p`ixcJ>q|9n=x?9*(y;M9jsH_p_ +zg0N3iE@g+dVAsEy=FbsEN;lQJ+kF1pP2d80DGmW(==ob>_)mA5k~a4LpiAsP#Zr17 +z(7iHQmHhpI+cD0&TJq7^x4u0L3Q17!ICoY72B+DjJ(9wRY66(+lGx~aYOW9cDnP@ExGOc;(!-l +zXVL&py+zIn&gVPh_a1WPb(tY7s>^M`txZLZ9#*lu8#2sD8(Ck#iyH<^VE&@i2oL`+ +zFL8jMj^w&0>cto6hgIQ%KKFyWIM9-(Pry%s{G$C(Yq<@)(oa4yXzj>C7KX7A~ +z0B3lj>M5W|pB}Y3{UmHQn3`1=?Z~!6;=T}4_q!RjY#6C?dk2Dab6+CvMvA;kK=HYe +z`h~sE}EPHhcL_m +z=tC-RPk{yCC|QQ5mYTYEm{v%bElBBAl}Yl>Vn;K{3KDWC8Frj!TutNz`#&soGk~T3 +zya=Ceb=NhS@Wyn(KL?#B^5vP6F(>Jjh209)L2F}=@m{?}Osoy%97^^0*hQqH9}B7X +zeB2JTdZjkj1e8cfhc_y|X?N +zG`nx%_I^1@^p>0rpN*Sembao)uE+dPZ5}O=5i!&^p-qJu(5v01 +zcfeynPFH>&rIhvxfa@5{)-^ldusZ{?5)bhaar?%#30=e_>R1voqFKk!-zWL-W-d_; +z{5RlkPz-P{VHb=O%R<< +z*JK`@Jb&?C)tZZoesM+L=sgaRH2O^4u5%%O3;Bx)h-wKanXfB7OCCn5#ne_cd1_)ypXth7nCOF{j +zYeqpw(l?_hRb2C=7`ebXJuP-+jKi;Qpmqw410 +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 +z!*;}hgzSV~@AE +z7Q;voicO}bxX07G>3$w2Z{~TnzR +z2=sND3&hR1#wjTVu7-6x8Yh_SWwk*GGwM3)Fk9bGeBi>>k#P^?$%4`1gjz?RK0a7{ +z`qLj7jfNpy$VNX8+JJuCD+6bW5G*94v2V}|#($?a@WhiwP|tkdvm1kY62;uQKC3dr +z(OepI%eecw&)D}`H!kSZ8fwVlgJwKFDst0HOp86w@x^tt@-$rF0t6QmC&MTM=s!wza;$*JGG0q=w2owR}{amQYw& +ze0CvGi*!pJ_sl`it@De>ltgEitO8ZSW7fdTVihIQwwz~7PqL8_tp>AQBf^*_6T +z9ClZO*CN8N1k*}5c?;CG+3#SlWO1hV%_(_kdNc`R7hz7%X1K2#zVGcfyWiemA_R9# +zy1)WgTZ8C)1%hTb=>jDaUkiP~S6W@iqiGX-SO$Ha>>Jp%KqeV?UG`{uYh3})#XQ}i +zyLjukcwf`E59xoQX_@RUfOds?wI5#Bx_)aP;EblqJUA3HdPHYT;vZJGC!=S_15fCN +z2S?13f5}!4T@^0zi~aKd6-J;|x6ol4GZ>oqy_?a +z|E___sF3C$h(JIEi9kU3|BVJ3TUhJqTG;>hEZvF?ZTmD4WT0zjZx|_cXGi6RP~GP) +z<1!fFT2*mBpjpxzAd;~{VLj#S*}rW1NGZKmno)35LB8LZJKP{ +zarxoY6D;q*?#pPJqC<1J`LpSlR;EPY3qjl>SNT>=*_6!Hx5k3GC#dG8i`7B4i1VhaK%@x$S;KCo|=o2@}jsMj^3g7>ca2# +zWHr_o(}W+lv^P8ADouW;wdY}Q0zFLl3JjXQY!`+{49bbF2 +zyT9_oyF5MtdZpdGV-?>j><7vNsH(za> +zc-AY6=-R5EU0SLu>X3Sxc`Zp|VE_K4$_4Vp_4)KD`ZnY8RU~~Xw8t$>JLKY2gO{Z_ +z7bNzZ@<47R_UD4LoL1uOlHdoG=SUi1mm&0*>gse`?k=K<<8sZ{t=ZfY^W%roYsYaT +z@>Nd7{DNFlf!vnF`%IpL_*iSJG0$@#j#9$au{`ANji$xI4M(Whl?v(nFP{Foa8PWn +z^0q&ow1EG9Gt?~IBqxvU9{w(3+_v`T3T@T*u*9jz``8;Q@s*y2l!goS^P+T>JY{&h +z_mj7aU*sLnL;7nxcx#_&Lyg`qiZo*@mYtvJjv@ZFe2@!VcnVJw{$fX)RCh*8o17v% +zMoXF4hT(J*$Xl9&$q^}AT+P<{Cd1G2!+-WL##075_dG{q=R@VU1bkqSB#?Qe{B3-* +zp(0XQwVW=f+OY`#kfy_+Q-#7}_+r^m+36Wy7J0!fQ8hOj1QMxJ9ic=N33PzP@MDEg +z#Yx);0yD>BPZ9-y2-haykrn?c==ntkPufEz@(mgcVf)06Szv!Eh#c6KK@03#EOe4r +zxIgMl7ut3)Ji1l0h#&C-#z~C|F;qOStP*LV6kT7s2r5okMLJg6LUnGq=ucVQ_4Sv8 +ziKOX0xMFJlMUprhtTyi44U3u8sqZEZnxH?@t%w6tif(08npu@VtjT=6dS4GAfFU}pQ>yf?iwi%REQQ(Z;FM)DG| +zA%X$=zfcx+K`W+&NcV2x>@!9NYlZA-z`=dtj3Qh +z)WyQ?S6R*r`}=EMItKBiK@jZpBvbYwtzdP}M{QU4UNgBln?WCNNt!_d$!G7`(;*#3 +zm55XbG(A}*3W@4@Wq<^z(JkwSc@`S|H-+Fly(9>%(oq`)#+L6P9wTRW{zm~`@ +z(uW)IaUfMzkmKdCDAP>Xi~(smcgdYN$^# +zNidy4aRkC5wh1A#6jfTF(D}(&RcQLKE#Lzj6X;Hxmbko6sf?3lbw|s0s3O?l|E!&- +z_^G`-Ra1ZsdF^u)Vii9T1_&%UJk{(sV41Ir+!LXi8LjyqrRcfw6wS02vzF +z_)H_mf>V{IE`2)qL$79unr7gkEM|PczQ%5Pb;}7qVl?eTQ~Fi($W@3jGAxPjL1>W) +zKC(Lt^)MUm-2)q@L1*&|^Nz!L4aM7Hsrf?J+~lG2A!)`AoXVzeaG>QRLBqT_)1J=WE=+5pYs9mO?zdSK_Fpj=W{}Fuq|Mq@ +z!gYaOe#v5+pNhzjDNu<<=SPt-F_!3xS|HNXS7P{;8n{4J9F)cO0AIx0VZ%N!$m~G{ +zhBt7TMqjT{!}v3})3)@;;m1?E{*~@Vk7{HU>2Q}UQBY5+v@dU+4_80!5=2=dJquxrt7r37 +ziez;gL~FD&js#Uy90_mFP%=VbDP;s*rD~I5%47o4g#r_P-YVo$i5DB9se}@)nkuLS +z626Mkmv_UU{*ub;9Yy&i9jB|}O1KF4#g*{!W}HY34Nb*W?f|8x`ZS-SO4@~xrkuNE +zzd@X_9kxuS^c7NBxD8AxPvN4WZ1+w=M^S8Hg|4>$NES?~P+?Dys$8n%Fa`}r5KO69 +z;SBIqZo(hjjs;996rZUFfb^n +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 +zHXWOlNvz +zT6WIu*pFUW2Z62sfIx3xgr&MBzwSMaJ2;zu(76xsc;;RwWmgrIudy<`um0O!I +z$l1uXfDSE$A2&1{0sOY{PB}5IP%$1|YfRc;Mj@&U1xEJvr&)1Lm%iwfx{bK%if2cqpNeh1kY#vY +z*X1S1VfC9QYjs`qJE1QZ>_>ObD-sd@fog+~#5kUArLjpyctu9RnYF_Q|Fb5hvdB)q +zgnEq*`d|*Jl$l(~;JSVj!xftmI^5vYbE(>>ZVe-Zx6;rmEu3lWRr`Dwu{GwwZ)iaf +z76#3X=_5#I6{?utQD<+9^{BO+M|PaCAp;ji_1^D>KylHyD`kT4_@oYsoP?J&f?B>L +zW` +z2Xk*{X=$-0Cy$aS7@Jy6u|X!QJQ8beKa-iMoqUyzgmSV-Gi6Fggu0LO773DKOy(1sOwc39*Y((aTC3xJYOi^3U2_&N;k9w8T#5 +zurHnw!;x>{T`+r!f-cOkrCTh27{Gmx-<%=?LVtCgGvrELw%iDZZV*SCoZ1zS4EKvQ +zYFnUO+g3V{W+i2R2uan6zLLd&EPeD4`|9tSEm?8aX$@E@8-|`c^c;Z9i4THpp2#*{ +z(Zn-!ZCfbadE)dZ7DPBQ)x#UQUxWci7JEG#b1ESQR=vWZD$a4kwz^YnDEQn>HF|u( +zI8SahkYO@F2>-R|APP42!}@v{s13Ij_IDV$_od +zyJ9dwxE$b8AJZ(sC0l99n*9EA0>T*yT!_Zasq$IIE0ahFtrE`fmU9d+Te +zElbU4d0i2XW|~<#Gtuck2wZb8w?Cd<-QT4*FJzU2CCqy29UlVY8F$YDX=eLVbh+s` +z!z}0$tl`RFv?kCh!&5|Oafcew++3YRV+nnMowqq>B`7ZmLWRr~LiGtBn*uCxc1I+t +zN$q_OX>Hxb_vzbDl`gz_EOlZOcnUJMt|;7E&sG!U;jqBXSwM63CJ76wFfHGpo0+B9 +z{@e8G_E)?m8>X!;u*7m|yRE72*67R$?|JZAzwW1i9J>ClsbD&o#!~xJJtIVE=cxVI +zF%D%^h<&g;uJ_8%-E(P$o0oalX;n8wbm(p8TzZAl=%VKsE~vvnFeN|u)=H3`eo;j? +zBz#S-Aj>srl6?P~L#`OxeglI%{+)1m(_fgia-VKJy&gwG>nc$Q8u}zly89l7sESN> +z8owpkGgYEBNNF1-vVBT3$qFc$W4q@N%gdTo|D;+ds&zY7n|XN8mI{(hjEm?W>=EsI +zcFQO?=;TlZnm4<87$|%snV3&|(y@~>wBKej;VDb86J(m{dt~to?N=3+&X^BsbP8OG +zgg`e2H#eb6TkhMhY*)%I#Uy0&M8nw>z?1N;g9dlT8Q){Y +zCMI%mZwp;%<{W}s2vUPvW?6)^qol5cUm1Ciqh}u-o!ZD-C&F06BT4<(%-O>l;7+Et +z)T{~lvHilUR77UZTUyidygCz71so_5>wl1}8(W><*zmFlb!iyUKtG1D1sZptL +z>1@HNVENt?r*$4#p9`M*%LvJPI*~{ +znsccV1CtVZeCxzN>Ct>hVJ{YCwnld>li4h5^Qhi2>C=32_7OkV;^{$^YWsHG|0DdY +z+~wOj)f0`IBFd`Vd9%-%tUd1-4(c|0HRVery|eS<@RO|lDjI8>qJMjGFn8fjd+S|` +zqWq6meKvQ>S?E~am~g9n^SoY}HmE_^?ae_6P}WT(+s_b +z#8{v9jzv1Bwo50R403dgqx}C!MF0KFd*@3nBFSo*e4{&y6StIvUIL#2AEcG%UR8En +zK)Mn%J#iWJQb&e=GggqFv>X>7-5S>)%{MFElt8f`D`KBP8Defcmm +z#qc#rA?V9e$-LH8M%fDMPiK-t?Q|`YdlX4i?vPkgmp6Uc5Ruh9CBSTtfq&L>6B5sP1_ss%>0K!Co7=jJ)fJDzB7My|KeRq-qyjfeeC3UCkZxh|9Q`O#Q*fJ +zFWafol>U0!nrk5gs&fsDU%2x#TmCv4b2h!XfvK^ztgBPTB;cY%{ta4i@R_@sx-M3a +z!wQ=#Kk&B|f9|@%S*rHxOM=p$ +z=Iw3!G~HzeXoSaWj>mqi+O*%fo_b^fXihv;XH``n*|Pqz{_48sUur%v9m29yoRpTf +zG@K?a-ffwnQFgA;D{KXkR$iagaB0b=uaRnXv8vboGt9}k>+4;r8`^gsE{Mv%rLB_f +zb2iq+a^Au3aTWnvTuqY-tBoG1tfpzGH_C5~4W1cYp?Wc{ZF2AqMTT}-m^JU{TUGs# +zcnxC5p^LSV548h4S$68}y6+wHx=NigtIv37RZ2MuU&>cPfd+Qi^Be&v@+PsvhW8FVc&!^XgLS-I(&rcfu0Cf>3_0mRYD- +z@|>AZ2Od)m%8~^!tZ-lJVPW +zzo~D_*yl9A;I|pA#Hqy<(>hh{>b6~-Zy#XA(DkkKG(Hxn{55L1k5sQ)|M>Y!9s*~GgFjQD +z4`lccu9vIl8doo-J&!`RwbXO4mw+a;XK%N1;6b1V7pye26wC%nvg>S~q=6%aRkI<8 +z@KZ?)5`*Rhn+qz92!qoF-k|QwF?17ybCoXImw10V}Mg8U!h$%y$KA?uZ`;1H=Ha(xq`Y7>d{-A6A4QIOLO*1r-M!%E1af +zwxSX$i8f#;f*k;s+{mWlm_1?UED#1bz8e3@K~Prku`%R84*7$lD&4`ui!pK(&UU0T +z)&6rPtSm^;J*M~+IZ9x1$%CU~6pq-PXIH))@G;sk(flx*nisVpM`LbwSCY!~fj034W +zxtd;Q0?K8lih;fbNM!R)(MWrLZ~C}!FALirw1BwZ1Cxgq3a6AO5@*B^?Lz*GjcuXY +z5cFn^I7C7Lz$>)^Qww}IAVP(5;aDsg2&CBHI+Lnjk-8Qb0$RtFTuWYvWEn9i +z6ef%2Df0dTNq{T-iUvsBO3S~G#qOH035}DgaWHMEv>kNrNS_)Z#D5mV1kk}|F&eB`Xs^cF<0SeqM;G%H!b>bYvcv;K +z@iSm7Z5J?j#K~4ciu@ITSU6)eF@=qvXbt9V7R?`5SeN&`Pge%S +zX`tRC+Qv0p{6rfrgYJXVM&f#3UOpi1Rvn$YH9Y*pjdU8D<%$!D?kkO)gxdGuM-G-b +z5$G~4B%0_(rAVywetcMrwxvRN=#G3y-r;bZyzwn2=>A_wV0;ulpkOyJA@-p=-5_x) +z@%V5;`rZiPqB~L`xo?wjaxwc;2tlGN#v_p>$MGWt>&FX0qDxRCkBKE&N<`S +z{GbasA(?Ik<6vTxa}r`Gx?&0v>Tv}dimsm`L>m3x7*e|IHn#NWw8VUiOb8MEA_kJ! +zdJiX2@U;vfJoIDSNS?w&Y~JAZ1@%z35P9^2!$a~zAJ_-#amb7MCJudYh#dX)b{z6U +Z$B3xmOMs0uyfrX_o`51`gm>`P{a?^2+|mF5 + +literal 0 +HcmV?d00001 + +diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/docs/14_user_doc/TRANSMITTER_TDA998X_SW_UM_Devlib.pdf b/drivers/video/nxp/comps/tmdlHdmiTx/docs/14_user_doc/TRANSMITTER_TDA998X_SW_UM_Devlib.pdf +new file mode 100755 +index 0000000000000000000000000000000000000000..510913334135870bdd9370ea2156a3af7e8780a8 +GIT binary patch +literal 610544 +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 +zgT>Lme{937pWXL!MC6}93F?Z;zc0JuIq +zt_Hv0l;gm)9dB^QAVEdn9pFAM{zh+~jPKySOA+tHl@Q+Bs}>p)(R{Xppzfrcpe*m@ +zEo(Y%M@nv`^&QxP}@ahWV;DJ^o@2Sg_(G${s-Xd~-SZ9sH=}Ve^erX4xKkgifLO>hV +zBWg~qrzvftb=HFFiv8d^ccbBDbQIy6MNKZ#@En2G!_}0sPE58lemdpvG}_=&lF~oZ +z-x7gm!@iVot%ekDPb!bA&h&!hOUAs}>Cqx*ua=&oety}verd60AM&I%D1={b_bx1E +z3CHqVTPD*~!*hE2*<8r0CPay>FGjztzmFhdpaa%YdS%-3(U@a{;->qaA;fbztY_ya-ZGkRTieC<$d2G#`a>PPU06x^8& +z_6IclQ+KZ5M)Qo!Y0lpn;L8X^ePN4Od +z_-mGXj}Q!=v?#5e^(!fDX(#Bo7#uY +z*ajs$UZ`jJBGuPu0B4{$@d{}2ia_Y@*%zRYHY^33>cVqClV#?I_#&`Y3 +z`*)&*jUVh1(I`;gz2nj)Dr>ywX<*iDh9+j7bx!Xg4Op+bB8(ve?*vF +zFe5`wKtfDZFVMJ!dijdtsEbZ0$hm;b~lNh&0W;m8e$seJQ2ryBO +z!7Dd#$+EOCQzuByjqK06IgPS*z-cGYMp~ +zDLtp#Q|l*;}kw%zkBh_ +zwb3^kH!5WBLqQZ{DlL+KPjS?8Y8f>NF85W0M9mwoO^*8Xl)0WqXsyshl=#fs#xWSu +z5FDCpCE7HMEf;nPA3m@fOE?TpU%!-}PR3~xOsbzePHe}@X==Dva~Io)Q!)J3C2dLc +zFg*;eAY)$WZzY|b`zDd#bj87pz4Db(&Qw)+?$Gh!y5%i(VHGd0}mb~*Uhsa +z-Mm0bRk+dK=NYLPBFxAUEOr%Z0j>Lb*I`N0e%#=isvU1pAi2tXeoi4xF(Z+Y4O<SWi?DBr_Zif(R9-&v|?9`G*t1#Zv5C +z=G|J+y&PAl70~f23!@<)HH6B%F_i)1s#U`#&QK|HxbBicM_ZsJri$3zWyiF_%u5I}xwo3}8i#1px~vD(^r`vzASb#iAR?{eqFwWyK{_t2qidTKZvbjm_q_Z_A&> +z#<{zB7)7vlzwfrsn}~D+SZ7wVfWUV76Ro}Y=1+maZk#(iJNC8?J4JAZpK9C+M~gBo +z91{dbr`7jb@9b8PxAnsHr{b@!mp=Euaa-c{UbpW4?#HA3^{&CIQJ$=Y?=bgApByZ_ +zj(=m?(o5An%n}hEu|Ht5wzhV3xIZ{JpLcq;I2XX-8$ChZn)~|n#k(uy}doV +zypg6ZIQL|F`@G5R-6`Abs-wf5!os575w63}-S0+Lf?PS5*YZafHyslgH#ax;CnFW) +z6hkYfzU=JVK4bDJ88y`j`I9kT;JLZEmmLdMme%95k9W)P&7+w+`pM0nvOK*1 +z=1;JawzwT;C6~prZTbSbIu(d9fW(Z +zC&VWt_<*cpfKA;f-kwhy8X6nA5O&JWhkLN;YU{O4eom;L4Gs)>SNqO8?V4TQ@Y^Qz +zqrKHI7og><8RfewdyNA72M4Y$ZXF$+uU_V6yvQ(r3ewipO=qql;HUT$8vJICgBf4Do_Nb0%B +zX!E>+NXPt<@+QmXifG8NU +zQv&;ol@j#zQ#MLw=%@eN?!17Jk+B6NK>~zjEI_bq2I%W6Sjqvi!*-lD0l_j4%&^P@ +zWE21RO=eiagBdoG8J4(Ufn_sTU?W*zBUzw0DOq3>SYQ)aV7CUtUV&lL!LSFh!tTNf +zo6ZWG2ia^oek?0&Bpd7rY_K70upw-)A#AXFvcaCf4!ap_7nBl~UxH*Ipf_WOO<;%J +zlN~mJ13Ce+we*|$3m_E3A4*^VPwx;y?|dRkKi|V*1u;XXooq(iJS&VdG#+6Ob*V&c +zbna|eM!w-^jBlxQV$qZ-xyirqiG +zd8nj7(By4gH#OPSy*}E%7(4gzl`{{wol`}{PQ$0DkL#1O(_57k4-QwhhHG*9$Ct@p +zCajQC9BvkWd>%Ia@p(%W0Q+H{@7l-Di!DUik6WFyWerE0Z?e5Lvb5aUYax>Sg7u*N +zLB;l4yQ4+#FRn@oM2mgD;ljD9ZR(leE`7rj50- +z9uIm|Iy!z{mb5J4eWd>7nr5};!<_h63Gv1WeW(r!ajw05eW+LcKKKF5J46caljS9I +zI$EoewTDkj1$A@;RW|s7ZtxBE$I-dlJSd5@1k{W>Fgx;v8HQgh_CD7=uaw6Tx-OIXK|!CzTn=H?BrAPcY213#`{B{&&vhN$ +z^zfc_B*9=g>daakX`(T*N{)<}#0B*3%jpVn%yMPBnarXFF|T$ySi~RjIIfR7a=VXQ +zk_*TQo^4q?s;JB%uT*3U!s#f+=`atvO@dr=H+Lx{uf9|8ZX8~gP2FR<(U$G1(DB$J +zLo;Rv0H=%}?>;ht$ILpu?0C=xTA5qr9b4|6zO{V!Fz(GW@mCbA3h~Ga50-02!AXG& +zrLmiLrOWT#<4`W|mU@9sUW%z%`2O`nDFWF-olo-?qo1pSJF?jH^X#1U9`MEsRhp`o +z;#QP$vflS88jllV+jT0gLzQx&4%TVb)fdu2<3Qk07Y)S2)hsdcXtRvlekd3x++*6+ +zFYBodkWaw{*T5An_+{$hf%AbDfY?}Uxs+%_b~^C6u1h4>(U_TT_S)Q53PL{*j%9(n +zxY(vN5T}ME8;u>a@Yb$fQ1f+}WUqg1V&%#u#Vi3@_f6$m-M|p>B+0pSA-uA1etG5> +z%mVp1;vgP{hM1xYNu^nqWxHtmE_lNww&rSwJUJ6#DPSFx>pAduZn3nO@FPtD#I*}+ +z`X~USKw`KLF3Qg{lBY6~K{&QCYnnSLiQPGPxrB0<=9sgj{u{OG4>D0^pDjJwR*}VO +z=6I>E%*sYQ7k=>(lTVgJlV5e)b#we-B}}7uQ<)-D&S6j{>+|HC-VY?@wM7fuw9Q5Q +zq9`M77O(Uy7F*@%#8HuUUTc@jI8<$XG;1SO7#U{MA0w_J!+iKGzS^(L;Tos~&X+ex^Ro17JMpHf|muAtG=B)eVV?oo-bdYx%kbBSEeh}V@UVu +zF`ID^t7v7hsDIkIg8_Xehda*3(&XG`T)iGzH@Zv5DpgGF*-@^7xO(^D9^S7h +zC3l?ivGjPGXP#9RKhs(ufDBYBh~@6T{7I1Mb^;Yo0&#^r4l9_5;g!9DB2F_Q-D3rI +zK4K{Xw!-4kt}uK;YVp@s65p#MtzpRl-OxA%@*fwcV>gHAPZ0ODY{i(MfXq;|oH&O@ +zumPym+N>>}fSN)zZdF;k|JXBJNhLMq}22IdhMA8>UFYvx}Q$n`yo` +z)hQ7KZtl4?=eQJ`ej=q?98KW7#5upDMt}vr +zuO_BQg`Nz71gCHQN4AS1owki+1hZ{8ju$y-KX+>-HA>lF``aQH__s)*@TpfdTODN4 +z25RDqjkKz%DY9%ycNXe9sA^_%tRoZFhSW5OIOZtmZp-q}29~BPW@nQVi23$rn>b06 +zVj-=y_z2^At~cVnD=rPd6E4(r(^O~*yosyEcIi11o-)#!)(q}Dsi=aQndifTQ%KvZ +zdY{avkNl|V&*>@=xph^KqzI%Xp9fQ;_4yRJ`I@GRl=PafwnM+-G~rSpTXHtJ|6N(1 +z(zX_K<&dy(#Xf0+DEK6K{G; +zJx+?jMhtxPRx$a-rEs=#J;=!k_o@0vlEnmIx&>gf4cG-Kni1tt_B2ijgcs^|4Uy{rTS_Otb|VzHrm$2jP14v%9Er4GrYPp- +zk=Gj%;N8C0rnvJ;pU{9eMGC;9+GW-dtQnoSl-JG~|4eG@tsFof;>FUCe;7V-^&RO|7VCFtRtW3K0}D+9O_@`UPvVTMULFeTM6C +z*IyMLVsyb}uEHpvRjXO|Qw#Hcg`Kq(w7H7&c8%9rhwlJEaV(u2nNzb1ft6V2lL+$U +z0B-Ke$~pS_0P;C653;4IRZqLy6fSN;t{4)^BJ3OlOZTG`JW^6dGag^Otg*U!E8)XR +z|GW9gd&Fs|`t#e386VT_`5f#IR&!KFc}brgyiTu4oy{G&<9_ZXTe%oGxxPQ5J?M^> +z8d3;g^JCEPHD<}uO0TXK#F?p-r!`CU#j`GCLCG^!CY;TSk$?N3$ +zg13iIyk`gBk}_MA%Qvck9?EhgXnHYfKBbdj20G?lws`*hu4M!Ib-`l0(xMA7$+UF5 +z`L*Z6aRX>y6mN-3y5@t+TU)=v2t-sSPE^%wJBqK0>XeRz?H$OCH7nM%LUPdaw~QC>}Ufb +zN|!_J>_N92?l05|VMSc27+_<{&fUA)Fs-s&N%h+GqLZrefZD@W+N)adeLWX#B0i41 +zO%xLwjb@ON<uWKXFy63r@iSbDs>Nw +z|8o{RmN){R!K};7y-TQ};%pOm;>r;ZSnc6`teMv1Q1Q)J)smw^TxS+<&UwqZ&iFZQ +zAwIDye59o#y46d>jtS>cy4U|nPKz!1Pzl30TjSx9E~?X)XDkGU +z`!#kuI@%ZcxQwhLcqEWJOp>2pA3ZdCw5u+nbe+QLX$!reRA?EGwr_IkexpxI;uGE5 +zAtB6Bt|g}Fw4XCt-lAu`m}4X?(CJPmZu*>sr8%=iy0egP6}az_7e~Fg>&z0e6eJzv +zleTM${N2PzZ6e;1EW~Pxs<~&i5)pq;> +zF4*ck4CAy2lgiW$ijBHb>-guRxC0nCQEGB8hw#5xpd6`H0-=?m3~TBa@Xxn2!Y3sx +zKSdYBOD{lW^nT>^0l+2e7Si|TF-zSeT;=9EzEtAuk}D~%qD4h>4Dfc(b+{|3AYSt% +z<*@B613UfHgM3Fs +z*bjYR!p58%{noP@YPp;y?x9+x$EuigTn4DpI%|zlA+^+e_xnCaC3ME=77M$`v`D!` +zjn_X-n)cn-J`b?G8NntITA)}9A3Uf!t)54w5uA!BF>B+>W!ggSfP~OZbX~BT<`R2~ +zq9UGMVmNs7W_Yr%G*dM`FuorbDN~a3@askf-ZMHOGVDdfpXUlKPgYq;gB7XQ8yLW-#;Smd7*gWuUbS +zc2ldcmK}WOZMcb#IsB5G*B5eMV3$|)^cYQ+coX4+Gi!kR*&x@tFs;chuGOpfO4 +zXtqy9XZ!KISFoy^j=>nSXxu=wLA4%b@XY*Si^|}#-eMdGrIIatT(qn>OyBP)&sjX0 +zO0EOT2*Cxp^zDcmLzIwi?^u+4;L!^WE;cgk5$^d|2xE($09uJfzjzX=Ig#XR;VOB( +zpv^$|;!S4qDGEQpMR#NxuU{=G%tUh4lESpyJ5SBIV5G)33J%0Qx20JSQc^D47@(obJ<{_MUTSZpAbvP+Xe6wv +zE?EQI{YH}EGfhOwx#h}n344nCWBd5xs6y6+*+BXDk65h;1rJW;Tq~6TiF|d7&n@f +zMR+Amg#AJ|Hy##Vpd>xMj|N$^hCMOYnpy&1EJJJMcC5VlP&Z$LF|v&x%m~sd+<2!5fGfuGZksS +zAbHb~QedOv@>od6g->ePcj{FyN<0!}ZEKC$_dM +zKgF>2p}&dl|E3gGOVB_c@9vfaURV_*>pk8up!uj64^vzHhEAj#+oQxbTT!NM{DP{9 +zYb-ex<1W>#w#w=jE?!aOM%Xc6(kKF->vIzH{Zld>D^xF4j{|^^H)dLdB2&#>gjWiM +zpH;iNB^PEtW!_F5kswawa$nIf0I4rMfu~FC_S0~&!nb|r0svwlI@R3AR0_ieW1f3g +zdLJ8!MUf#27f*{7<0%c^dhI4nL|GQc2X8WniIjPVQSOWVAv4<`ke8Ur=i*M6XurZ9J3_ +z1d-b=Y4g#l)s2%o5M*`@-V+8^QliVnkqft4FC}fCdpJHg(SJ11dPjRo_$mdGU9H%- +zOVmbo+8de;-yk(P&FdMD{KW8>4ScuL0T9nE7J9NIu^S$+(3SzO>N=u1 +zrnSomhx(F#sZN{HlBd4CqOdie)SQTLbmT}WDC)@o$54OS-VA+EFfHCCY@K3|x!22@ +zm_e*X2Z`B7UZ|-3`1_%V$Nmbjyb%3uHpCqumNyk?r^krqDzN&Uovk%8)*ZIq^ksRcGO(jAnYy;BCSi?iuyF^=2hzT|_VQwo9$^fG +z`ODhxt8QdwUmj`m=)G}WOahE26_%K)D``JJjzMDLl +z4lBil?r`I78ya!zii@QSDL1;e*PafvH{4)4UJJ2LIxcZEwCg08^0gX=q>+y+Z +zFKT#fM(**j17!>4(bH>)kOs_T``1M*6rH+zF=>6OsH|&Mg-_8DB=0?(NVSwD~oLB7kEr4 +z3MiMj-SqYA0=&Ynt0GdojLM6Lb&YDC_g&fG9gNzKf$_^4PXECi-K_^`Fh=LXpTvO1n(# +zlCv)p*qYcz2GZYb4lu|@77^0_2z>rQLIOwC7bP0k;<>h4-VthSYYOR)vt7rzos$#= +zG~4y76YtD_Ic5z#@eVss{@W+6fzZ^=PmWvzK}@HPTto9tXA&yMbN`0+r)RED!~5a! +zYX%_bU!8ylazKu`|KCr*gCU7B=m~frGbCyCw-fNt%-+ejJ*h#st!JbUkcE`?+@l1u +zFha_l*nmuokm4mU3lk#?B^xsftU5SyiPbT$P&Qj%=ihqDA|J(OI +zN%wNVGM^l<%qIsdRmuTNfO33IfI_pdzn=i*faRh8Oa&JUv>NNAo(7usK0~WtnHQGt +z=0#r5P|KVe#B@i?8uEWxV?#Bg|E;_R2qnT#%nUo*DJugd=ozs;p87Y?Ke94EMfpQ( +z^R3#3odbBf+J^O1wGAs9+o@_B5ZkF@4>0(*s%=<6C)GBf)5RW;*~hj9qJGEKHju}h +zt+s)lO8DD%{#NSom&zybcSZ>a3JHsdTo-~A6{(x){k9hXLG%AVVGpEA>3iJ`RM1be +z2Rij{P=CapzhL_{Q`jJ;{P-rvH7E?nOYY8hobS8hTpnpT!6aIweL>mi{Iej}MpqRg75AaPhR`{ec*LwR0@M +zQ(^=~^D_Xj)&Rd0BWU&DNw@+Xe?ozO74Uu&qrb}zWB~;Hx(I^G5+p_f!j1?2-y%XF +z?35woCQyNd(Bd~^WZ)k?`35V)|3=AU9Xg@p&shoLI3-I^zWyF7nU7`lud)O^+x!i{ +z@A*t1`zcw1qWLKRSd{#$#S_PAVTSgjIHAD5kfpy15F`Ks!s4g@qrkw9p#Cp{0<}_q +z%IKWYdFV0J6EgikP++bD%)xR>P@qivDW9ML<1cj{c*g8OJBFMf_!o=tS@qcm +z2U5budK>|R*&xkqP67-VoZm!neBc=}^vqTW@XV?odPMsK!9Rw;Y`+YFZ~Tv2X3Q}4 +z`&qAu)1feQ2jGkuI_*=x;r`KT=?9_k3D6%##0)?P(NDI|ei;=*Mty4_!36rgqy@4w +z1An!8`iH2P1+w1(UD5)XA;y-K1Jae|^f!l|Wk2EA&t-;{>6Fw$1?cx=hWU7l>2ES~ +zX4wQiM*q(USlCZVEfmi0Apjls7y285Gl4nu1phxHU}j^41f;N)0T>GBHxV315Pw5( +zCNhT>5BxI%5SS5CO7Il{6wdD<0RB*O&v+PU-NG*re6?Oc$l~N10w|oHA%OLk`n88S +z6IMbeoFMoY9_H_%0HmY?2rKLOKZXLZ2pRHCe>Y}?)sp-nH^X|y5ko6WPRR5Fh5gDX +zCdm5Z8>66H`zfQK0r9UHb;i-L{IO-^cmIDXEcgNcAZr0wAb&X?F7NUP_)zW+bRA*-UdPV +z1zozI+9~+oSogb%25V&Zrx0x-w&--r{edhbus=8S`dHd6c}v^gy+-$d&_q6f@3{F!|; +z)-&!N+EMb4(Bm5oPFb6?w&}a3{YPYiE-3z#*qm{;(2kpbmQ4Q<4gTcr2kRM!1@&-$ +zga&5>;V-+@5aR`eH9h@r2n6e^`iF#s?MzGvtuH4Au$YKav^Pdf?CaY__u;I~K}`2Fkvla_pbe1)wuQIkd_234;HO +zV-O1fYtjJIa)_V;Vci=3BaZ#a@PX~DgrCmw|D0nWNV{sbuNzA&Q1<;E$9`;=&#Vcc +z9W72c_HzWsCo#SufWrAH0+=rSYP}0O6L~{BlAj>>Gct23()@2k;;Sk9LrQ#Bg?`Ib +zGasLm`Nj|^cYekYSabJpX7`5&CeMWa(BANWgdu0*x&L6T3~SEvr((9VdU4wS{wt~c +zP6WuR2hubc)=CB=yw36t&LiFjU6=h{*iMyDPBHJ%5S@ +zXVeDT4d{dhKeeRH$47=v6c?t&zp1##CnO+4&qn!Y7NgKcM87})OE5A+F5gTC49-sx +zob~@8h;aT5!I`BX^cN&f5d1r>`KBpnH!S}@?yf-X;2(?b&vNP?{Qg%?K@KK;mlY`6 +zeveb&;~c|^Lq$@$9?zyhTu%_2W`;z +zj|f1J9}|MeCoJF342APE1h5}b`eh8xd?uiRPB=mEucZ1!V*evSghdE{W+B9W#y>#Y +zBc71pr-BG#ha7o0VFHXJzsZCj9lBsX6VX9CGyVbr>{uTNa@ysa7{K8C6v02QjhWBH +z3D7c%69oTC4F2P|8rJ;sPZ^{$UK-jM^MnRJkOP>D0kJ?9#NXrq%97vY!jDdLGoNvC +z(4L(Ci~w@t=erz0;rtZA87IejoO*x^JrmipoHfdSY&Cj%_xwLtk;A&5{wX;)Ajs*02ijEtlzJHDw4^?H!^ZJ;;q@ +zkq#zqkv??s8!g2)*;+C7dcTZaNB|Bk5+Eu{vz;8SoeUnSO__@_ez?M0sad&iX0!3x +zY-?wH>tVi>cgu6WBX-rpm5#mI*fMY9AZx&QJh}4$n2VREDKKi!-h1xydC)zl(ed-j +z=Z=KaCDk%pBlDS9?>UW+UoSx2e={(?_xjDQO&G-skxgE{7ZTm5>Xn<@YY$m%r+;)w>YeVh~M%R=5qg0Pp*X2w>d-*y`AERn;V# +z{}Qwh=Zl6@vC-?tY8kS6nakchlx!37GfUkqE!|u4a$cYAmLz+zibp97Wtz}CY@w*k +zEK~8lAll;FYNAW>Ev0^LH*V?K!|fa%?uoXcjjAOR*(d1ec=(!qi6|Q*r5H(Mw2^M` +z+H(UnA@{VXM6bh|F`SPcH*SULp&kfn7a`o0+;pg{+?ss8lt*?&g$Ts_NLdi$(X6(X +z4948!qpALc&8;!3G9=c>8!~sLf*P@na{+HTO1RsaAI&#o?t*vA!FKwH5$!Ux2%hL( +zO4du_Nf^`lmmW7OFyKs3_?txY@O6%l-GB5&U@&P_$-AY@`CyLMemBPPU~_f)VrlQe +zxMQ0%A`qz%`0AqYx!oH*g31H82^4xAvWFhc1N$-!D6&)tn>_)KS`_o|I!&xKmm*w^ +zrt7%3CGVrCewZ`9dTHuP=k|-dTLcy){^uJa{s+qgLtOY=vZ^gQ5#mvr!NL;;WIX9KA@8{XCLoC-q2N-x +zC|RD&MPl83v(%npB}(s&aJ4XlHs74|E$1J+m}K6TM2_2-7)Z1Zh8z)o(+g=LV)@ +z(lF&RbxVF`^*Vp8qEs50G_CjjSUcZ$6);3J)t&51?lowUw#qj$g*DAXyJ +z6JURUsvR~@=nn6m?O-u-cXs%af`7RJmVQL;p|#5cylICr*<|dFe7tFUg&{$o(ZMHc +zAB%dLw_Atsq#K +zk&v`bm7X2BGzII`i!!`t{`WK8>P8cDI|WHf<7VruuIuy`s;?2)MR(9hDkM +zS=nF3{<`zMH2=>;iYb}h_*`(g{?!kvV^n&QS_=H%(LVISUsow(#;@ZJ7JF_;V_BbD +zaoHqatO56iKBHSkr3A{Y7Hy`=BaW*c0d@NgHfVAsCAjIOnLylhH%D3()2NC?yeXok +zCrSM`e9`^%SNPkmlNUQ80C9!09+5w0@H#Xc#=TQ&bdEipYV3SmvU4l&7JOJcooEqx +zaSOEp-*!rFCo=sD99Jq3_hE1=5oY^(J^}eV$F|owvhQ9fE0SxHFq9>w`(7SWB;V+n +zRTfRwtBvSkhP86M+iMzV-4ZmjY_>{S$$Ns@(%~AwgzOjDXmESaFWG +z)Lk69MC)q6@0`L~OR>!_Zow-!yBlWto0T-p;4_p>nh{Q$#WrK9#%s|u&t8oxXvDim4clz6}rDQ<3D7<6PoGi=5f!3zO8TB3l5bJ^Yzy| +zU%-^@4ZKl?c)>nsZAc_~BfLW+a9r5bSe;WuSHZAowH`O7x$O!|uR;(N3n6I)T)Lai +zje&@#wm35{6-#4~$|f +zE-}3N))LKe^Mau6(m9>GtF=v6Uy%kpw}0P&n@A^uwcGtjbWhD>!%I#@nIxfrlJosJ +zbLD;;J0R{;CTb*cui$2%+^MUXnQ-VTE5Z@=8Zlb!wKZ6 +zJkk&`2*#V1M>6RX^U|k|qpqu5d!*y2S|;<}f@H5N{Kma +z{5&FudUrtAjo7;k@xjkueP+H;uJGdK^i~5g_KSQ*dLsEARaHUb3!F^65s^=c!bv3& +zdlom{sOB#=c|MRfWLP)Am-KDp_Uacl1|!?r@M$zR!PB!5*~v$d2=UOfqua}y5Ny48 +zMCy>;XnODBN>8Sl%?DQ8rO&cd%Pi;JwgHH6e4DrcA&5O=`P2XyRs%{n+pb9T}151>KT5le|_5kJdwj{xp +zk;oPC^tjm92jq=yG#9&i!^GyrV!mjivj|6Vm?no`X%7=nw((x0x+5LeyzZh~-ABWB +z@czvt;`Q@B-nS7V`sYS3B>5@p*A(OIj(N_e&dcWqx8LplLYVa?mo=NC@GYJR`zj}4 +ztSVV-bW$t}LYTj6)8Rzdc*WvIne9lHrc7DqzWlO;XLRfR7w>J%lEmafM@LL8paRXKFAGp-}5+C~;3H)rn0JdTzC`|Dg~Xn7--3P#az +zLRZlc!6}K+?YQjMt3VDbyT3wJQ0hjcc*AigG4s;HC75 +z;O4fvNl~H<;W5JW3*PdzHl*+K{n4p1Ch|G9bh)LUO3PPR%P~w_$*o?pryai~#E_@W +zC1Pltz$)oA=gm#&XkPSeiU5%$Nxiho;J&qr!v&)utdCXu@@C-S&NAsi99fP-8@ronlso4<@K`F^I#nor|v478JUuj#^L$PjdFbEY!;Sc +zb;KX&C~CTDMkcIlp21-S+6p9A-Xzc^Hh1L3)%*Zgc4fHDJ=Gcz1VLYV&fju`u3HZ^w(;0X(*(a0Ai$azoQt5|EXov#=Bs3YkI{2^G2C7LQYB5O!hQV8 +z#zgFKt@zN79CHh+_wLvf4YP=`n|)wF7_vYG^U3tmkLDpNWLb#4cucu1^`5fX-l~+^ +zi$0ora$$P```BR+J8U@TrAMOUm~9|Y9H9zWUaL@% +zLBntG4k16cEs%g-GT%JqC%zy}Af8{M>8Bd|p~xDU^1aov4I(Ub+JP +zeVZ>EO$vv_&gF4&dE9%pR`u&&mc|EXA13hHp7WKC?(Jj|QLv+b`B|#qYNc{}d!|E~ +z@@R)mg)omdgTwH6TPC-CUKNJ^{($g?tRVVT$8u#Ut3&Fxm}I;MQN%3S5~WEIv&r;t +zR<#}`99e|iZ*NCyseD9~xToNxw1l&Gu;l+?@cPEClNHK+50We;ReCBv52C@Aga?}I +zjqJSRweAbOjl8?VJ@)_Dd+V?&x2JC$5RpwNARSVhln&{xy+OL9LqNK_r8_pI +zAV{~gq=1xwgrszX(j}e08#tcx^?lCsyw4x+pFghaT-Wj5D`w4F_uTWDnKh$;n@Pw4 +zR;qc)@jYr(VvC4D6?JUD2lFyLYM=sJV-!x%RL#Lw)#&_in5OxPb?S|VlIs0F#22|N +z2>8>*3}7?D0z{#Uy|p->1M=7Y5;7w=BI3_{!e5-Mb#%C?9py1G5A3vTCctptrA(k+ +zw|HhxTuokX%seI1f$ukb55)|H<)f;(OW#wpC+d>M^c|k3ZysPz`57$W-4@#H=M#qV +zkn2dvaynq&6lL%{`x;r1wXi +zzwEDE<{cuX3Z{Si(T~s}m~pMoiDC9C^-#_52X+1dm>`K$6ogBuoX+}WUfCAdtx(~%SKoC +zFdpS?y}}wQDz@UF;!CpH$Kovqs|*TbKKeLMKeE-%-pA9l+`D=}BwFj6vFpg>OxD;C +z$TI(dszewl@f^Q(l%COB%9?rpJ)P~cJL(FFnGV#66hK6@{YoiCkAb8#-nYDLru4hV +zg)X$&XKOsUIbr1>2DwWq8&rwV!h`RQ^m3L%|I<|_r!P8s`IFY?o=#k>M<|F^T#qzG +zY0ElHIOz1<>}Mcyrq2Qg1Hcl>(fdut4dWH2D{4v_zB4a{$?QFB6K5^M!_AEFy +z*kS3O*QO~1xr1YRj_qZ_~;vq%jA@XhHOU5H}t^lA!Ds9GuWjK1-tNB`M +zGj*ZZ=5OU%J1ozGJnfJ+Wyu&j&@oPbS(lrMXxu-7Q}LUM-0^xVT8&HxPkWT`>HWm( +zbMopu(-$J4bM!m~MvjjtA*v&Bjw6x}1}FyJDa5PCB2+r5sb~Za$A|b0K6_M3_Upmf +z$7Ax#qn)RZuMewiKO;IEuC~t|X0dvkUdvVzI-_{~Y6}?6J&LoOlt>2^!`F&nW-g@_ +zUHps=<1m12v}_=pM#s=BJIb$1#*Pmpgrnu7Qr%-~uBl;9wn(!pt^UC!J)@!KL +z=QcXB>Y`wH2tj9lUFzrjEHY%_8Ln{QVfLTYYnDk=Z#~s{@(_vV_%WAsU(JzCJ7vU? +z>pr3gTNG`>4?j)m_`&PnxHM7pvvSp5U6sYh*b*+-+}Lq&DJIUPC~Zona$N(yagzt( +zN_@;vnc97e*)!LmVgHcP)hb003htv$5|rEH{+61JS4vjrp4#Yk+S9{je#qzJve(n& +zLTQ0YQv5~gM7&ldyytTP=obt&yQn1cD1};31XeSOHi$*3oUI(!dL4pYzJMa@l$H4y +zzrVwP!xVcRyIQ6NFpxSgu0J9L(X7F +zT3baYO{gs{9Z9i7(EMT^<-q529v*`fXd=n<%MZ~*WVy!}xg7I{pT0;mJozQUAM_}J +z!RT`!-SD72qm_{&7f3}Th$JwzG_-a0WAV`EO5z^rpo)k4U?Pb$v5Gi`V6pM!G$g@i +zD1vNkyTzWw%|vkMeAb&2zG1H$q~9)UGQM8592Z79ZxP^hSE=Gq8CMtPCCXJhO7n#UM{O&z$-NR&K`@XDUMj%X-j9PNLIiQ4-?QSoBtb~|g3@_gU!bnVCwxS=cIfvB~_bi@c-s +zrJ$&Nr{nupwJ@0QwG_1E<1;yXLt*>1FHqRIbr5~4kbB7Pgjl?9)S3WR4DXj@ZiQJm +zNbqZYiv6h9M#E@wIaT6PL}?N1KkGV$@6okY*{MF{w2gl4E;r$N|ETE;k<@3F0b8HV +zZp7oxEq<7A=rDf%HoHQF8SFKffo1Mqu@pYU?97(LAf2+_hQM^-+77AW`xgS!T6GyN +zIrf2LHWf^yA+dntpf*R*9madIB(yuMJ`=1Mr71_?r|<3&ggQQ4&WA1wo2e!eYOA&o +zceOt~$bVonc{>qTLy2kU08P!KH`5V5N$O=<(R}ykcoW#`ZR6AsroO +zJIY(<+HVU!s@Nf79|s@H_k*1|4+q2{koT^d~Q!)afR!08ec=(!JmWb6< +zy1g(eQ&@5X}1(^F?+j8aJD<+DLzWPy0A; +zHkD@kIR$QrT6o94e&etgnm_>?y(WD4%19jjthgJ|5bN|HVwy^9p?>jW`~@pUN%6>{ +zmti$ULqDyC%L-8kBles}eL%EU&$_3KRgrmCpsLB0MOV;0R;GoP7bN>;2>eeQ9xC~Y +zQ$D`;#XM@gQ)*-^+nr+QB~U{-;H=;|SN`ZKpGiXHx@-k;l!1l&WNnmyUUB=9YoJYw +z3Vdmg`qUvk9sd +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 +zps)l;eqeieFUJl3vd;C;MFm0v +znuq>8eB2YSKC5BwxNB@&)?neh#_(QLIv8ik!hJYMT&1^+*N*^=@biK$UY@d3NGJp2 +zR-x?izF$WG@7h@-vKn?Xg`&WzALn2QSDcrTt^*wIdIPdK`^dK;?fKqOGuoFg-U?FX +zhKz0tW{LE=*O;#x)!QOpIFxjGFQvXK;gsStpCta&o@D(KnXXNAfADDo{53|h{#j~x +zGdn7(9U;2Ei-U5#ooVIP?*8l`U*ap93!)=<;&*F(?L!Ul3}Q~YdsW4rR$?|WWyj=i +zM>p|*urr!obhMp_FbU|fQOt|@lsPVhRM)z#0Q~Zux +zmZV1y9N7w5-}p^HnhZEj_YXE=+4Ulq;riqEdyl2DRTpT7Y*72%_DHthwhH)N5iO#T +zFGTrb9qf?8lV9Hp4*sF|uZZ(5x&CkE`Zf^!&x$Z^w#F>~B+nJGH#4yOr(y)u2&m3s +z=IF)<`KwfikpWOQ1E`(h0Hou;$>5>HtYV{TZT8Z}$oQs`#_e5!|I7({*Xnk9pd1o_ +z9e^%6WVe*wKD>MMn>H +z)q!bPfMOz0ab-6LM`J6fwTTVz=mvNz-R8diClxR7_%6YTIzanfg#Dki|0i0Pw>L7j +zH?w|4`+F)nGN3HfD>DF%xY3Fj*%%rF50ss3Z7q$hZc3W`aVO$#qTkE>dkO!La!Z+< +zft4}y-O~Rx0r21TYmQ|4*tq{A`7g(Rmc)4WjPrIHbz`$vrj9q@p7{mj +z?*DJful!E_%gzqm?l87eBjez>ZT?qD450T-@?Vy_dN#MUvu=L|@Y-z^mD?*1N`Lb2 +zCY=BGqJMAZf2pVS46ro-V*^Pd*n#r_Trgn*s%`u`wEVM51^Z2^TcD}3qrKBhM+F1> +z8@6-)aSP(EX2fq2Zu$OKCWF5#?MT|#TLByCVB=)}(%1ng;`M)~Isk5Humb-9$43zO +zW4>bta0`Zv127H%DaYBkd6-ylNR~Blv^R6rB4c3!5)0mfd!Q8)aM|bfO}U};xv}*t +zM^iG+KVYmKI?7)o-3)p&+U;#JMiwS67H;5P_e(2u6z03DngAK%He|qy{@=Xn|9Qdn +zUl)5j%w4S?Ab&F_^IzM~!NScfW@Bk%uMET&7z0Pk+3cmUl9VX3sF|aKg0a1rjg_s9 +z^$mNunW5H>#`d;0mIjW-WF`id4#q%DAxq#9GjL=bjm3>`M8WTcvU0KBW$OC}vTvq- +z3!j!et37X?=$Hpv@WJmGXoPeIqn9_bRxU52`$Kz8#MoM1mN~pQVYnBh;W^G4V1VAD +zzuR)ccEZL*;>poFc*5Q5^kcQ|`|;(G44(1jy1J5+3)DT$pP*`? +zs_RD2(~4qk2bBuriKe-+*;!q?6gW7C@&InUfKrUp#2|)_&T@tx=^E-T(*3#AR1(r{ +z=>m|Q`{%k<&9F@g!-553xT;PjP+b)hX?N>`M^8?uD*WQdhZemY!W6NLQYtFGbBe4- +zF~pY6gWv|@C1Du3P8uTjlJxRnWaYFG9%0KC=ytf!5S+yr#1{x3s9O5?$%~COz3e$x +zx29^8C|fm^DM1zXiX(?)64iVc3UK(8KqDV@!=x*9stgX!9;{2p60kU$9Rz{lH4|*! +zL>BR^M%vF);tJg&INnpkG(JGP?*p&NUd&M5lXb=lKRx?bVb@wDk~R+x^xJ0-#}BxI +z=Fn3RjZ>4qh`~YPZiZOX-Pu#U2X6KtP%sJ=$3Yi#pfa!yK_%rn5je{u&wvEL$fRgn +zq}8%Ia2AIYu{ajY%T=H;%?@b{5@R%rbuhB0rn-ss3ZA<^bDcz{o;oVmeUGSv&HEI8 +zH=ap-l5s`M{AeL@W!RPvZUB#0+V2Z|q(pLsu|F28eYd6>i*)NWhI%}r&#z4HMW65_ +zL>uJkE@8(iVKr8DtSTl`cr~c)u*wF}YWCMvyhzx*pe60VWzbA;m2Q9&xwc_!z(7?S +z^1KP->k0+c&TEvhY%WZ=Y=5fuIyZpzmJ{jKtm`QIIFUkEKoqbS!1rAhcbiUkYRS`YL?08~ +z*x5^w77h6>sJb$Z?!B!5{KLzLw)OD?UvEqaERMrqx~bzJ7=HfyX9)p|x*VT4V2GD$ +z9pQ+ +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 +zCSPIm2=eIYA=T7cG1rA} +zyPB;hg)^imWE{unadKpgWUW#M62ky48sS6}nMcvkjr_GBQK+rguNw{A9yVX^2I%Qs +zF<_D5DkH1L%NmFug<9`siuGq +zB=J8>rO&`F==!&wV-e}l-pj46f*Kkc-uqnf+(}GDEbZ*3S26&k4OW7h +z>Hu&?5{ViFOQoqac$fpTb#z?jV=|BPo9hRZ&t(fQT?}iU&05;I(Vxf?&;hCnSub<_ +zBt#8m56-RWj%`Yd?~X65wPUR-QVID +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 +z$B3@Vgr_O-0C#7g!q~+LL&au_ +zWiO@pxz(RUT*qX8>X?!Ez8mdQO9*CFXc?fnN+mKayrn2OBxFz1X~SY^9-~tvv^sai +zQ7^1=P`@g-m9{i7Iq80~OAdJB0?t66BLI_Fo#I05R29Aa8-)jbe~|}DF_=uK-MZF_ +z_!(!W?9UW0^FuvGh=a_6Ddt?TIe9kBgdG~QwTd!XU0gj6;=;dDhs9b7U8raY9cY<9 +ztPpw6%^N1Z7T_TX7~Y}$(0tM((~R|5?f%LdzD9})@$d0H5lz2cH0gk%eh``jJkdsY^{GmiZ^FO1%Qkb%fthBSygWvw +z;JqXSGB^;FA8bJ`N^iJITICS`{hmM|qrO9p_-F|SuiX}Cu2|CfI +z6j80Sir0pIcCzD_Juk#4E&9v~%Whapzfb$aH|Pz`Sg|*vt^8&5cY5dm>Xv+Ia$4~k +zQF_%lV3Nc`^Ete9R>4{p{Yl7V6k5&PjZ)W%zCYJUm)xLAW&svSP*pQEK>oVDy$$#! +zI-Tc8h#&}#;sPS)2pwT1S)zOkorFg(s6aV;pYXjMVChzM1{~kFi~w%hrZ)5?MS~}0 +z{JPA1uOU+p4mLPp=}P2Nv85dAhU#J5<2S|@+zB2`sO!n@0^mtZVo#4I5*-_Q-bezzB*=X;ueiTTm?L(WFSdE +z54*Ab0|K8`t4F}vc6eYNml}li`J)|Ku%ySSyS4vh7uof9i0H{V*hl0Sv`krvKVWvttY +zjpNDf>|Zc8Uw7FkaAn?Go`!7Vt!T>}J{ +z1P$))!QF$sMV{_{`sves&Ux>rJI1|(4=^@WtJYdoyVjilIoEFnG<`Fjc3@58)v@Z8 +zU_@FbnZoyW!+Nl7?6jUnR~{%q@WT;eqPoaFqtsEvNFZG*U~YLnLw#a`B72i4NpRuV#%^J|9d{XgeS@dpTqoKd0K# +z9}+mJJBMb@?WN648>yrtxcnRexL99qf8RbR?EdO=rNNS;FJOIBV7dDb!7w(zyu@%6oXMy93lFx=-sK*me?9)xFzIcC2Zap7bj5n#{x +z+?*IC=cT7oS(3-n;hZvj3|a&OPANE=sldHPXw=BdxH0!31BSNyv%&QXVtHxctQa-q +zkc1dPd{%X22bIFjyzfmlxqtx+SRVKBb1Wg!pQu7XH&GGlCN-ip;itx*)*J%gOJ$r9g*vB)Uo(8-`WI64X^KY2`$lnbyvyE!%Kw^h%W +z09460XdajabhItrw<;7m*O3C!iWoJ!_I)L+wT_~EZ8tUTeW=WgsQH*?&R>Ck7{rn7 +z+OZAZ#fOu}tnFLN^a4g4F>?|uF|HG|qff5{D^Av^%T`HG(70X#kSK#0zeiev48)o3 +z`<-tR-awRyz*uj^acISW%Rzf8bz7Aw)OPz-Q81qF`)3y4Zfx{t2s2L)i}scQ|rt_6^Eum +z2U-Gb!8`^~em8k+(BfQ-sv2Jxknjj2?HBb&s3U*Q6o>)yj3Z0K)5?e@7)6uQ%8I_> +zBEpb{ANi1;Za-@R53H`~<0}tGZbFix-X@4~;!Gd65FUYC9UyX=_&gNlMEUS;@`jio +zzt2?S_*Zywjlh#5Mge+M!vd}jLZt&369W#8up?n?N23`Zk87xp`a)A;K^oXa%)9RPJ2zyX;df1Cn%kixpsDewNxv7Y3hHQ?0Fxn)#^KSI%=afZJ=)4fUs +zp66ko#@Ty&3w&yY;$doy31YxQ38Ug!xa<7GQ$Ul&i2NXIWGVhI1$rJLxjx1^V65&& +zP~89>=xW{rCh#BjqN`Xo3y1O1)amo&qa{9jBPZA$4#2^twa+6S0u1iIDFn$ulF!Ws +zZSCzm4@{hTZT`zU2VnL957C)tbD~hOmjQ%P@D?zj|CaxjOU1$Y>`*gkNQH74_vltSGp`209Md+pk?0eD^8S?`zE{h0w{wi>0){S-eQ=%KUj`i1aSDAi +zFCz$k*)~2y(*P=nZ@IF;0m1)&o;rj!i-I%{kVw6_z;pMxJ|YH!*MLNnwEUgEk38<=Vs`@2{sfFZ0fEF8^1fI~P!$=lAz)Xd +zC4hng1SFaY@bh5AUt5J!Nn_m5n4KsBkgIB8QTkKG_gj9jSpCK +zoG>9&9bLjex0z27N`QoGKCdn+VuROP5k2;2%T^;(gOOOx-!%vz`6t+_s0=AGNK><=?GqZ +z|6n?4dsW3o_tW*CKMNdG|2RxUMzr;x4&&1Ik0p?{XIH%0N;Y6flgY`v$`?ja#P~@N +zAckRRl!xY>oxrhyJzJdoY&kuv0!IZZMTI`JG0^dV=KFipzk9@@FG2}~_}RTg5iaYP +zVI9G7h8(}A?f0OHztdZWOJJlAVg7M)U@T1YKb=gcFMrZfsE!5)Uj9TMs6xqgo1FVC;ce+afRGq%m<`y9Pb=XuGN%~8 +zLMdNXdJl-@7FEtiEA3C?FP}5OfW(CU%df$7pvU%_E+ED0^7sJAy)h;;_zG-G^VV)k +zcE+%L4ILBI>~Et+1<)A)W2C+e~F`Yb(QQX$lVk!SbR+AZK^uLwtOEIu(4}L#-9P$QwqGF?w4k +zxfB9uQnZp$cTnIsfL&l*J@=@IqHsh)F|8);#s +zHDBRDefwO(U4vCyqT@$Vs_abBA>8pI6-D!US77?ab#YT!A6tn3u9uAU$zaRbOjUr4iIPx +z^@||FgEB|!6a%nk7SX`8pPWL3WsJ<>H_uS<#QYl7E+vP}89^AN-kPH>reUbCsRuP$ +z;TLNX>w)5l)~S`3I%_MLN*EW0_pfVKf}{GbVta?qtdEKW&XjK=fOPMRc7m;o2uG@# +z#i27tcic+1UrkhLKi|y-d&{Q1d^F&{9wBHLhc)yTQYeX;jzKko-(4|YBT&g}lF)sj +zfdga%*Uh&U6UK~7VT6JORkPnb +z`f4&ZySDa+ykocEDHUeEAl3Cg1L+>E%2P4soP@lsC8HWDbO#582+pXM<_PW%N6E3& +zIwh$7?B;2E-5<*$3&y8552saG6k8tz +zN{**5NiwcC@Y$zvLF%t%-+r|I%Y!Cs1d*$tS +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 +z&xRO3Sht2EtCpp^*@f`TCoG;W3^<2{k+!l +z4BRP-fdhKZSRtz(F7}(#;q{E>dF-r6{-oEVh2thx_&vt8}82S-Se@C$oc(+n2aZ3g=aK}C2 +zGg@*|TB%8Ol9pSs^NPlwLiM&}82Uq|reku5VdVylii2VwpM`v+tuhsJ^a +z@5XSEZp-xWAQpB(@cM^=ji|1sR9I178C4o);)%oHx8XQ?=)Lh*Ibj{` +zTmc__OVDfirmh^2ev-Ia2dTyGO33GrT2{4bzKZIs&zMh5l#A{=6oGF&<|#EA!X9_M +zaOvL>x3o*GD+(u$)5_xP!x38Cvg{X%^0&2lbIav<>^i|IIh$BI +z&fGAHWkF|Y)1oi5q{&%LEZcdQ-d*ar)(Uo>6w0)hZj9!|^v-&KPpwoXtxQf>?xhg+ +zXk;M*Z55>H6N%$FCwGTPYTsSWadZt3n7-3dt~{_?YOG4T#njZQJm~&Xlw%vfMPL$r +zZXab)qd&(!HxD@KSA +zD8(bRe3$RaMrLCG0AIZLwP@6;XqWIXC9bVR&+^l;_b=Vo8~0#g0^(23HK#e}i64I< +z_Jj=5RFi(Sr#^GXt9gR*=brx$Xye~+q`$vZ|3{4iz~uhP7Zw#0myn>Bmljh|R8^Ez +zqhw=I6;V)q{w1LzE%|?;TRbCf0j}`>Lbv$MKK`pS|Id8ffAs&~>K6Y)fB&tN@h2{r +zjqQJl3uXZzw(c5MrU0atjfIQ-zY{Y49V3{Nhvg4OFe?X81?Jx{f`3z(|2hZUzy$vN +z9{#(9k)7?i^bQ+P{RR-ZxPi(*KrJAkED`&E)Vlt;K5j +z{l8xrIXQp|O1xyO&oz9WODFxgFtW0<{{aLB7Df(kHtzq$!U(L4&y)72nzN<35Vy#I +z=HoVXA4uX4w>JId63i6j1;u{?Z5khw8eEmAcH!{;-p +zt&-&PUFoK_HNckC2|dw+^I`V +zM#5iNnM|Jk99{E3w2!WYtvA7e-_0En6l@#*blLxHx%=)0ews8Q(Jy-H2F&KG^}q;s +zTynW<=o3lSzJg(kl!}p57X5Bb5VQM1B>cdNolSi~40NM;|8okZv;}@eI{x*iN+eb* +zQ;jRWt5mT@u~5#@m!c`lR=C*s?e$#-*2}-_N@Kl|2J>fI&J&E8=qS9}Gm>}dZO>;Y +z)Ryl}zSPJTK@#V7^dfW2En87~0Be-rlDHzve_2Ss2Bh0F0 +zLMcWLsKfhma(HrV1j4Cr^_SB+Qbol^kvDH3?g!aiko9L*&1N>#wOv)@+(7Xow@dS!kM{zi#dp~Zo>YyD^pK>Es?>F=1#Ss+&CBW(A2!oIWR#3m +zp?=J;Bec-7eryjN?VLCR_%G~cxc%mQk!+*2wN-7R4$(? +znk4()V(fSUCRFC!I*UPj6Vjq@U0WAbT;C6OJcg*cDDQlaH%CM{5@O$> +zkIR({jo?1ueUvyJ@`yz~FI$%lPM3tS*z4_Z5%5S)b-y5ZcPuL +z`?nw9QyQr8Fd3ai*LDLlJg`~&^>5-EDHOJuRLQ!xzAIPwM^Ket=W-srtO2S8Td$QY +zj)o2u_pO%tn7VwZ%SBBsll>wUgk$r@wvqsrUW@S+);Wa^Ka^DBCqGKEL5`uG??%R8 +z3kPYCK-&1FB!6@Icn)TiEtlR}KMY-{Ra^d`b(czvsC`p8$$OI}$Fsc6_k& +z(^|tK>kbQ1SNR^7u6Q;xh*zWrs94b^--?NUr(0Jah@DVdj`tq3+N)Akzd0zGm0qh) +zZ?DoA$xgg9{d7ShmY3sv2kzv83rSo!*8lW73q4!3-gS6RlrPL@mjSi~KT3$bAr3;^ +z5GVYe3^?-Y&S)N9^xTF17s)MAZ?+;Do?;%cW7x%*8WAeKQ-^KkGx8U9J#e?GJx#ty +z*kk^1TM!M4ytb}P6AmNS7f=;ro=F%UQ3Pq*a`K3bej?y)^rWX%VXXyQA+ax148>Gd +za9Y{dk;O7f=ky;umVb^y{5M8B2iIR{=I-eqH2|fV2hE3j_5CWPR!4&SME)y;ItNc3 +z(^#&aBPgpXB~xlHuKJd^ajy66?0I>b^~J~mR5d*8fY5C50cBZz=oix<;n`35lM1UE +zZ*_)#m#SB8+@0%I8ZgOo51wh9`;K>4j2=Qll*hOe(kCKl?4e{$(J509hgny546Ha#`t;|&qUD~pIJSPTk8n{n<|X&RpU +zG3watZJPQMuaI`Fxa3pLCPOza?Bks0x(s<^c!)#4zs-qATtea4Dj0zXll5qJZm-Xt +z7}-W>h*>ZmHVq{4ehq!~<^z}36c%=xw2YwfbhPygsi5F|R9wvO-c*Q=z7CR5io`3) +z@~XByGQ4G33LZ$DctWLe9Eww;R~U40OSM{Z5i^29)L7A|_r{er1Nk0Wf-*8pFC6+A +zHjPrK{4{*!q1#PFlqX#+zV8=DY8F)$gPpkoIhXC&4pF3X +z*Do>Rr(8=eU`p#B*4Shf3Xm(H%VzeqPFC!Oa7NI=Gv!39`wM$a5s2P}!nJuK(YP4D +z2Mr|dlJ&f^YxsyFFE#ji;ZT?f;ynQ!q15>+6dQ?b$Wo4V?O37!SX_yC5N%%zm4Tu- +zdm$fT(Uc|bmISRth$F9YIMyf-R3WQU@ew)7!C0ol8~TFpc|%3zKM_*D+!(w5l4PE% +zBXZ~r68{@u)d7jIKWhR#^b~QcAp3Ur +zf*Kw3cv1zyef;}QA|IyJ?7j*WsQf@Zrx*?7ZE!ElBb*gpkK+~^$VtzAr4CLmGA(6y +zt_~k2SykVUeI3y7g*K3sVfQ63Ow|k4a@o2n*7MJ{2Ie{!Z-q9geFJo17)xHnFDUk3 +zMHW~`n-DKxmmLxvW8=zEU9g)^SJXXK@V_9^eDHzYUGEU=9UAUf?IG!Nd#FN_{iyd% +zBt1E83EJu5hxue(+B@wH)>M)nite8cMmEWHh^3KhX2{u3aA!yvh$>?hNmNctWwmt< +zN%a%vMa?L<%>h7@UT&=#qjs_mUZ(x)hDf?>QN^hZK0GqhS>Ql=|s<) +zS<$NFhUOrzIM)_0UeSE@5oNyCUEM!$WnL<8-TgXsJXxT*R`>>?{xc0x8~Yt&N7GlN +zv6J^T;xE2Q@kTkQ7sM43|6rtR9*7&HTYigmeh>|5IPDVVx0y77jAFC)CJMtw_~+&M +zI40BF0)(%&CoTL(0;ZwB#hzpOoa8{ZX|M(ECQ(r6>k%13QkE|_el+ub@Q`<9^z@pG +z^)11@r^BK3;EO_(_QF|02S)a=U7u$vMtoeURn +z;N-D?1k^93h&;Kxa~b1E>Gdn{>2WVBb0Fjw_MD%?s3a1|JqU;KwX$F3Z#q`W8W|lY +z&iq`#8oa>Swj;c&r90X7uH0Ytq4TAn3<$cR#?q2sfp)DB%bQiYx$_a3{Rg`Jk1rW= +zF#V^5leY-IPlh(_#|m$RqW!i@?YW^6ngcJ0bIA7VCoFqmk`9JK#@Fz^z}5`G8O)I* +zL1(9V_e50;GGR7+qPG2Xy}4rdE@bYP{Z!8COJY&Sp#Aq_#>Kt=ehFZER&V|r+nkk~ +zg^7!ejGLW@i3?DzSUI1iAZ|`>CiefVTK)Ed{$3=L{katAe=*MgQX~_I{r*!Y{x4N4 +zvOmhZNCJHX8u{1y9h`t@#SIh~K)x>8X}>Q0l)0NZH?Jkhk)0WD +zU&E=c$LVrgQi5BWnQ>@5xtUIZ`Gs(L`eAxw~GL62W(LGPZLVmViu>4~Xd +z9o~vDC4ubk^kzW;rIR*ueZQvxq#&VGG$F{*mbkLEwc{X_c;g=EbPP`(za^nwgF5mZ +z+85U(_Z#Nq=J8iIBI*p4{S4XUw9&~F%`6^n4HL&msZbD1O%3bL1+K{%*twr@jG9zB +zZ#G{Dnwtb;e94M%s=-hxdTRK^VN;o|44(z8n|s8z5!HbguCF?jaqLZOmYJ)5U22?q +z28!N{JUaer59{K|2!?GL3W-ro*#?@8+}ZRdv}qWZi*E)W@BD2_w|}AeB*+fRcN}v0 +z$8g43fLv4vdP>Hfw!m54G#Z*k)XLY>d(a?rnN +z((hwU@Yf|pI;wyYr-QTy9tfch2V>3m2bc69Q_8oh{DOy_Bwy%Qzy7?}WVoa3Ehc+Z +z#CtZt=ZTk!D~tef99$R>J#FgiyEMWYbbQLE{$~SSmn# +z^jAaVs1Hi6AI%vMFJo6&XfI-; +ztmEHtPj{N)G$XvEg;vt=*f)$zHK*$Jc%RoRUMOGa*g=oFr3_d7=}UXK>+5C1!+lB| +z7*wfVUr9XqMz2WDJ(xOMt)=Q~0^_k7L7pB07vT<_Y5HDGkG+pw#e-ijGr@_NYZW^c +zI_Dncn=g%SYG}@`@kTl+)V#4+%rvi$`)5}9^p72@Z^vgoSDImN1|_Z?S#}XD8KJx! +zx8+!C+o@i_&~Ikz3wf2 +zS#;`YN~;oQpzs{dk^}*JUG+yUrPj)M7GkQmU$7q~)1X1BFFHQkNdC*q_pEwfWB6Ga`dLoTd?e!>O(v0WH5*@L;z^fD%njus +zz0iIu8P`>95I*@TTH|Ydw1I&X%6SFp$a;6k$nx7%$FJK*^5h>p1vvSdlK4?2db!`G +zR1cm%sAS9Ui&WJLkSN0O4m$nH{t|k|Hb3{lEM>c-rmM<8hUgW2v+?WV!5@M%(~u~l +zTeR=q=Gqv}GE)=SnEt|$pp2}q1oysXjSl*Zszb>xks)TZx8K5sjneTVKS@d49Pu#0 +z-)9~FyMB7boJwz{9;E;Vd}Y>r-ac*y3xkNC`U+b#dcF6MG-bChZS`CUEhIvxmg-4k +znL+od99Q`zCvvz%ut_`C+*{?LxLC4J6GrEX$f`r}W9k0Dr^P?Z4A9(z5GiTqbd?ez +zFP*CA2I8{?GOV>0H+4cl<`xkP%!Tuu5+iex0@v5e)EAK~zDd70^ZV$bz6aS(%4TB+ +zHiSnK6~W6e8lin^ZgMH#>dJ?xI9l>dT7+TxwtS|!ndo-QxIJ(vjZ(B|(xA&e*iuuk +zv#v|CLR7ZoY;99$qL7oJ5{;a2H&%!iRj2yH5<)3x#Szoy>}?zYuX|-R(5}{CX=KY; +zCUe-HHsws=L1-ZjPD;`*0|i=-llW>W1rDvW`;VczH8o~u9~j@ow;$d*bWbH8NYA0x +zwALW&v@yro#IVZ +zDQf)(bLM}SJH^4p{V!@;29cE=kUQn&cMs>A5T5#zh$v1%nar(qpD2wd4Z;?k1;fYM +zMjCsIrOvYCSKlLTIS-S6B`%i<{xGm!`xOTT#1j4M^^&->wCGO&4Y +zb(+iY^;@(?G-<}jvbQg{5Jv50_dR$x^){=24!D3PB;uN}YjBCoIfLf9w<~|8`Ao#E +zvY<|7lA9B+&MIFsr}skrxp$I4>8VH{X=z_mdbJwXT9dTh!KrMfnpJ)PB`8I+W;e{W +zOwEH%o#*O$yHYW(_7)wp_ShYU$5(J+YC*3ygY;DE3?Zj2jkFVe?K|6tWL@lC7_9z? +znUS~+c;c)Ix8}=3ELyQ&{dA0eFD5Lu^5y8!qkQ17ikY{izL(unb1AaK;5 +z-LtsEY||o6%SY943=UwNeBsF=?xn#g9)QEt%Gm~yq|pr2A#wk({LntO()UnBw4qfH +z*8=spDoqQimS~;U8!h;dP!^f6=`nx_%kPv8LBZWW9-yu+0?q8}dA}p%lO$|>iZl~$ +zFYb7c;<0vF8^0|*jjQ*GVi9_m5g}8?Di8P3U*OEtYxl|XX~0+mvMMN_BY;}HfC3SR +zxHC>Dr%xKv9dp=%RB4j=ClQRraQK`Mnf%)~b|U(z;t|p5Upm}9)XE_^Ct8p+GQQ#P +zi;rQeK|_>;iF2ScGb*)R;(y}rU`)op%(PzW%e{c7=xTNy2-RD8meWBI!R +zMO~n^*}`Kew&+ksAjn&y(WWi3C}d>~LjsEHYWQUG7$k~}Eg}8Mu1>bUjdls&Zmo?r +zSjq@Os9^9Mvp#}PHjoVsGa&STcqQ#`SE5tyZ((Jr5ottsu?t7Qk9J9oe%6vuHyhaO +zc=?D@B_IXUnpx}UYOIi5g0C6rc!l4Vx-xip$xY>58@vJwodz#ee0&;9a`NTVLZus{ +zufckBK-qxI`*ICiaI1f18sQ=;9K$GC2PV6H$Vlbh*U^;=tX4|f8{9qvu6Nq6HIEB= +z%T6z0Tk7Lm7-t&I0v8d|);44XKKsseiOiNQS&cwUXAk`la9W?5?}~R7ehoQa$$??) +z8ee4)@FrHQ;1gLH5o@#r?9bMQd7(Z%oi5}xtk`PKQN(@@0-f`~4ucKUF=e^UA3Cu8 +zBHbKpNRRe4`BcMGJUukr+K3A2RH&MD1V+jgnyH9Sy4gFm0;OQpW7}la!BTYbQw&DS +zMzZqYQHl{};@DFpijX2<*JWL|0Mf2uqb_XOMN>`dU)#=sWNQu=o-UJ*fl=efbc}ZJuLL3N!I*39JCs4h>=EgV8Y?MNMV4#&L +z+HM#^DDT7P4~)>~1Z70r*6KM^;X+(h)^M|opTykJmTW>(0}pZBdyOp{1pS{n{h3E8 +z)_Un6o^u;-=AK}{2_Ep72Fu`KWu`OS0 +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 +zN8IpF8~(qk$5N=EV`kxG{T@93 +zkItr|roSU|23b>E^AFaBiHq&O$j1QMQgQfVaGe6juVMTUWRWY$q=v#k#DR$cpqRmF +zWJnXiRA2nEr(D(CZqw5^WKd8Nkd@tC+jLEnpKoUJlWu1Po-?xu&fUJHc4l2p-B_9j +zs!+?ZgC$KkcW$O;sQrp@XcUMC+Fg7-zw&i^PJ-aEMlaTwx?Bav7}4e$lKzx$VLEHl +zuCg33`m6aE)k>cOX>i#yI4Qt@m?LyviJH-$*Y^&dfa?gSW=`i%G#!=1q{bdl&5khr#(Rq#Pl&CLFwevqf!s(=dsBKPZVY7Jo +zVrg!4n(k~$a6T5rf$_vmUG>8x+f^}d4DIp+`#9-eJg9u=z +zg#t1rhdgiKK2Hr7Kvi8LkHqH)i;^uL&!c+WlChr+EIkAV1$}=8idw2>A*#0iXw?Zf-YE1c8Q6Qd%6XjO!&IAQ7SC(!k7IK9cMF8!_!3xQoo2=fp5~tIPUA<54M9FzQ$5$Vi3J-A +zfjGo6Z?&|SCbkCmh{-TaZ$H>**xKWHB#3?#2Y2#Ug#a0v;oCWqT%w-YEmA1)SQo@H +zKSfp#1FQl4)mFOjLRA&&-F8-s(3(+$I-M1Cm{(_yM6a`-;uLr3 +zEs3C-p7;5Q{;(uZ3^uaBvQT{c;<7*3-r{vDz}rU1peAk3HcMmVq82$uu)Zi+qE4-r +zQ(B&TUqd(9)1|%F|4>|Tp6IoIAHAe7n~|(-K_wm}uQz2)!4?BL2&HUzm~5~UOawI(zM&`;u3lBT1-HJa +zBvMXD1#Zy}$QH_sAJDJpv`ir^xnh*_QYwix$l +zfK?DsKb@yQ*n{K9n;Wr^US+TYse>;j@RUoOUnXkc7?EBqK@?Ne3F;q!&XtH~0ne3L +zu>dImUO<|q3aXU|hoX@5Fu(&VJ#vI>g-;lb00zwM~y{Ai7$vrpo5w3D?08-3N +zE7wCcKN7o(lW6-Ckk{}WESDJYS(o3_*h|DQ*qD@vl_i!#6p_FM^Qrmrsi_-dI^mu3 +za2zV-YLAnOdm@htu0c3J<_mx2G!Q|@H7f0IQ#4E4J1&7zb9W5LLwTl-GSu1FJkUfG +zvnXo>-r#}V;1Jd$e%W`s@`=(LwEK+sRPeGOe4iPTFO(exvw|XMj=hI93X|0HSdx4c +zS+ZKW7VD1}LFDUXD~O0g&3Gf(OLal<*}X`0awRwg6Cj*T_fhU(ezj$00nL}nlZL#_ +z5#r)#EJAH&CUapi6#JL9D7Lxrl-1P&@l7}JeD`R{poU&jsm=ss=gPRtx%UGOfBRr{ +zC@QxVV%!@5#u=yMdKY+bgxp<(3V{mH$iv(#_2SZuiXWrqi-qq@#>s!w41!nD1&WGSxqE)j#(RTLs#9q4Te#n2>8F7QW*Q!)EAO6-Rw9h7l#ROXOZ +zyR0%T0moY_NKin75iS;j=YFImi!PZM+L1Ih5OKru3NI+@5+zC>_rd|>7_JDTKvz&n +z^XnE1Ww{B?_X;$wR>sXkb78z4x5Hpm&qk&s9n&Z(TOR9_?VT-f|%nYD@J +zRr;(tq|nHVx%jEBl*Q}|k!ab7>AB)Fvt)KsW_uEp73+7JchuQuBTcyzef(TKgv>@n +z3x4qs0LNBYe5*=#%#paNA^EyVjw&*i%+#T3ZwAWOo4OS*F#wOwTSRWifo$awbHvVUJO~DZ +zI?36z;MrlR%Cs-r8t(HW+R`+T`X2T9P3V(9y0BwqgkwDI*Ckoz+>utiIQ}joH3{s( +z6fzvR???#gOpxMO+Zk7ZO$>wi3So}{3E%K)NREYyG*YmVi!sfE1;U0P;FqqkeEn0u +zmS5amyj_mVGlgm4T*XLfrGZ;qRcrb4C3c8s%{9gA$bry4VcLSP5c)Q1f5$pq(B^-xX*l*nyglV8O~s!R9P +zL*03%?;_^0)!^V1;^^Br2Ke9+@Ya67IT*?FuQd9L*Hx0xn +zYt0TskX9Nh>&Q5K1UdoxOR>Q}Z{u@-_QOe_t+xd%lafP2TI|$EO8^IYb&}JA?IO(n$h)^Yo&+?*^#Ho<=i9XW_BBw~?ScIyKL7VQ +z-!rd;ngUl^Ig#ZFzH314Dtawx1NLj1F==HKo?L(Os(gq-n?ATT7VpB1V~lnFYR>$d +zc<*Jv?tmG%mFYBX=VQ4@J)xfU8nI1U`w6q+bUU@*O=JIocQ)%9v$-1^1TOU?_ZXdI +z$dFa`w|0PEDrUpEFM#@Z3zEF`$>@n5R;Jl +z_2~W%MjWIddmMflCXy=Z7u6^sPbf|=BRX+hBnq)&92E7(DXUMpS +zEN?k~0gHT_nmD*`;z&p2Pw;_^v`4_%x!a#GQ^Y6YevqIh#d|5$5I#A_cyw;E^KZVG +z*xEzG!D}6|<9`7F?k&KSrA@bonh1ff*@&N|;B&^s&e)A^mx5ZMpYfwINnL|oC6_R1 +zH?v6>IQbC9y!}kLURI3-Amn_YC%|o(BpEYDpcIiT!1mCgAqEz}R_7+&UUP$e!F&q5 +zg7ht}$p(QUZYHFmEcA{=ux`trWVf4;5sEo*R{4yUt1`h@lreP)R-paELtgB +zLiUByo<`xb*;o6uC!X0cYTlC0ZGWg121e_w{Nt{z9`9H4;wudTF97yK9$C20^@3Jo +zTbq+6)=9_qoUpIRRkUjbxky{jF9sm2XKG|D|8zv|$UXSL&SlGTE7e-1b-aNVt3$D( +zVVO|_$|9X8y*sg|gkx;%Njg|#e`gk4GL*E@nMV~G(e{R76?=3xOhUrRoRjsHk_01! +z5;nwS%9KJ-bm^|+{e(-5h^qjn1`NG_BuZ5Dk~>!urQ*A{85!jdC}ePia*{+m&6uTg +zt8y$Jp~2_~F}GW6_$5V!XA}!ft*cQ2k3`H;kunR&A8AYKCo9{>_ySZyOXW=vdD5qpo3#f!VAl?AJF91_tYI>ZoRP*FFs!AEpv?I>19( +z)pZr8vU?4VU%7`fBFI%_*LDig47>|(!px>EA;4`aBYA}q+Lor`N;D9J4FWu~Yh1QYpGkG +z%COMzb+dk1=DN1pT0hNYBx>xa5jJ>Zbn&fw4@ufdhM<0%M{>Gc=pJHbSbloTtY9D< +zyL{Tey_`k%no-vkT5{^-y9$_v{SHc4ab4e@bcJ&BWK#o?^?k9AX)FLbLYL0GAw#7Y +zD$MNjbXEcC-8JBtMV)

c(@gp>Gvx%FXQY+GZq7f$nZ9uB9qY6I66_c3-FOal^Es +z_}ke?w=)1{=b-Duxed?oQTwMqjkxHL9mkf2tuu$NjY+4Hn>GkF&k|Cg4!&Bm`bZNV +zn6G$GxGz7 +zf5E%I2UY#@04Z9tosHzsCqQJOl9eJsm6*wK1ziIMKt9Cxi}LtI44#t>X4|WkoxWi` +ze%vH))Y+9*&X^x&GMtee?SCE+zR_b&$4Uh}yAqZ{?;j6e4Dv}-UX2>*mB=1^hPrE? +zLr4thI-(c|zBe>P44>HwIG2^k`xO~Pq}Hr=?{x`Js3hY{d||ncy+D$&%}SKjN{5*K +z{CyVGtW}li{jZmt%MT}C>}=MeGzHUn`{;li7yh&qXb)%4O^mnpb_hABo|Zona+8iB +zdGH-~askT+rR&1vDRq0&@(`7b4KTV){ZhqjgxAsM(rYo^?exG^3;Q$U5wf3MgNQV7 +zP_!RN#@UnpI#!Wtg>o!0oV +zLIZiDR&igxpb`hOErc8*A-mUC6n67t*;|-m$}PS1J(>R{2n(#2mpJK`%QgiI0vUwZ +z+g(Z7gwp=dAQU^~JvbK@p9QV}2~*gfU5Knmr2hEEs*l4`nZhPw>EJ61NE~3aA4r(| +z1uq3vRO~t5irff#v>zr-F+`L*52zmsM5#w;Pn(n_KY@yR8nO_HW+t4$ViHFhJQ;`9 +zr@M6ddGSo2*Cqi%#3Q6G^fbKqk-MJuxKVOEOqvdM_K<<>da1C`s1xD2#;rbkdJ2(& +z|L!d%#`Mw5dO7(E6MiScyXoobS5VLL2*{Xk&rxU#HOca6{N +z%z1E(wV8CX^81yBh6;6|`DFE!zeC>8n*J8mUSjxBs;e5|JMSi*~rxZ1Nqh&s4z +z_VS@S=r%XH_V&=`KidnF=nO%idlYAx6^|}k^r-5XeEw`UsxNl*tY|iPSaaEi#C!L$ +zmPk&Gz|mgsj=HgODS_K*suFn*N_UD)N3Ga?MTgJ8C1=!W#%s`NrZ6_=)dX>AK7Q@q +z={>kz2P(%TE1X(m1>@oG9L)8|s#>5hnsF(Z(;66jd*7WgTBJC3p!$`c+Nl?|O5KTj +zAcNoBdXR&{U?l|nqK|0Kiu*n@cx=qouxR(P^km-oyghQjE>1TkVF{V73unZEblYvg +z9pS|myGwt7aNd$@XT#C`Kx#nDOt*uvY}$Aj-OEADW$R?iz9Uoh^pf2$thvY7|y +zg|)!+BcoPb_Svy)ZJ)z?EOowcY$z));Zml~djcVoP7XTSy2Mu-^@iq_4%k74!B-<_ +zKzy5td40s8*DdrVW>s4g9r>+XM@ng9-e<@_9a7{ngUIY`7e|*f77NMj8WPFNZy4Ty +zr`J3dL?G}$6^OX;2Ml&VF;Gkt6kXvv-tUh$KmqIf?+5)H5+xSt&3^NzQV*F|MOvy7 +zyp%N549Ha^H?-J9n|7JJTjfbRp-Yx4i(507#t;5;FG6mpYll0efr&MyrOMc_%c-&I +zf<;I0COo_i^0R1zlA&~xhTe1(r~s}PbTJ33{mL%5V)e5l2FXFnS#LWMtnk7Rzl<(f +zk8Vo3a5*-r_ZoXob%0p>7W0PSrCU^50R>L%Dc-2$Ev>d7qc7B1MF@ +zwUHUC5C}?OFr_}2lG06VrF3%r$t52Cd8TNBdq19KQFFe>Bc;-$!06ava8vLBFF*u; +zW#4#6q{pWo8Y_GPeUE}y&&eI;ruRD!a2z(8sOVxm$CESsiNkCbVNcFe*)WnGyp^R^ +z(5Cg?<8@ooA>qj$m$ys5w_%k0eY;;nw-LR0$jL5x@0cmtt|DTy9B7wn*{FN6UK=ne)6)cQ5cZwj +zRtnT&nru_+VRFJvxU*B{Ui7R{XUsHDqVnd +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 +zoJ5Q2GBZMdNiX}cdw6GM5CRCVfzfjq +zEE@I#%r)U04CIynqJ@~%72_F6_)JPIJHRu%vonZF-E?9>NH+~kxGgkf`E2b89J3r@ +zSH$N%WFV~3nlW4F7p8MgXmmJ6ObjR#!0wR~grOdU;fwwqKt~`#R8)M9V)`mof+Drw +zeSCq0%c7Zg0CmflwyEyd@}}EQXX0LVj?0ZVh{oru&4MqwtIzoOBxa3-$S8JG+q2k@ +ztxhhdEm}W%VRaDF`J;KFA1vl<&OzJ +z{sc|mLYj8{g%l3GP9CX>*%!aWoLE9I_l_h +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 +zsA2IoQNleze0&}8V+1 +zz>q;wB~0N(Ql7IW&R`WwsgTOYuneb+_M1#^^U<}>dEzG;qgj@MXI^A1L0?{U-8o=T +z%d~LqN{em;qfc{%ZOZ19IA+cqeez&oyNK``tDJg12k1T!=~m>Db|>A4>TwLK@O$G0 +zDJtnY4WcQd8Mu}E$l0gXBunr_X9M!cIYdO~ytz(rbtU!QXQ>VVAT^#F}9q +zYX%!H%zV#L2!2R9P4@$fM9d_qx!CfA#r6Z1Qeo}OLiXU1AVuJNF +zFfDU+?aMTOWR}T&u9V<7>*UsEmz~8MqJt;$5YXs~I2XY*)OO3~vB1c0 +zXjwF&`9+X8QXicnjt5WkQR^;lcQVLnG1vHF$J$G6b@odW8-X?#4##)MNPd-fik;w +z0W}+tNZ!koOTSvkv^bo~I=CC9;vAKH08?7z-X+knT+|B`yIQf4rW%9WZzGOGlVsUXT2!+UfuLD`{zmw|H>Q2sAQzmG +zJh3}%UN7ceeOK8~YsN2+D2L{(;(B%N9Fc;XM?|M%-w^kMYxrc#r{WDHA}O@Ynva-x(?onNO2f`gG~8gx47c +zW$ov=0MElN=!l#2`!f?W7x?^oCQV1&ec|Yd&0BoV7&uO{sj`7Hgr^)w_!lV-qALXS +zuK{j^p}LXgb?9 +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 +z5i3n)KR=u$*w)Gq}%W2QZSVsy4pUwO)~! +z)g&;@;F47mTI3+@LZB3Du?z^?h9ZUryNfV+?ocVp9RdgN!K^IYFDddO6qLUOFDa@^ +zMq_CPWwmW?U|WK|x{F!yjFXshNu%Do29Ypc)}!pd(8|p2m>Rv{C9w_&6ufraB<-=0^1h4pko&Dz`U-gd!- +zP%YF1+1y(|BvW$9!O&P7QE~rYMZ@ +zHf&jx1l5gbk4Tug{>cSbkiM{Z9iIVNQgtD|zUuz%sfo*!TV>CxU33M>0%1^{{+d#s +zD$>ESz{^%x#3YkT>lalJIW?(drd?@T+$kX|XZbzP$2F%aF-4DDuXw!AY`CUP#57ei +zNGF_76pJ^6T1XZtA28dCsc+(*ORFTa8T8PV6teEW0~B-8$HefmePWq? +z3#f=H{XF*(_;qH+5FwKz$6C)H7kkXOyXb5l61QgK1*WKrLtY5_kgy>t2P9?fm^Or+ +z>Z3VV>($4@@Dz9;O0h3|G`Ny^!W(pSUra-Rk9;V@pmeg%Q{7^n^lUHED%lbF6E^+x +z7beKh5Bl0rcC!V{loH6`lnJ=94Wzp06CDsm$Yi}X^f^q-4%n1 +zAHQEfh_Pjz51wgN@Bj;uX8^|;Ok;Ixd$OoUqZQR-dXtXp62u5ujG3T5BqO=}XFwgU +zePEofc-bV(50G*C_6|xWw8)D?~C|$I)Lo>Zj250 +zsu}^64y+-gi;#z!%*42NGMLX|u!H|ITFGJjhjdaF-O)v;6(t +zah268SqFl9Q(iY4#VJ4|0EDk&6y)mgeZ^ +zg`yca1j?NIAz6~qlP3MnQLsn_f1h;ubE!iI9|z&p6K+C2pB9lX=CM`lSRO2y2u~4! +za?lrj3^-)6{xQxSu +zb4yHc_6(-cZSpggJ$@XYq2M_)L_=2w(g(lg1;p0;KXMUXDM`C^lZ+5!PtPf*HIfCW +z2}Z}S)XM!T(gVct$oRclr2Ha?FAMD~Q6f{nyx?8(o*m|)?7vK-*+rHnyQ`$LWkuWz +zg@3aDS+I~VK`vi|Lyx_aM?JqCc>GacHU{9HCc-o#X3-$^_ +z${i55;X@#&mB3crYT`KyIwyXRmXjMJN`LBBheZS#nz-5IFnMtu? +zkv#J5?Lz!dDCV1y-aXDM!+q!o?<=%NEs;P>*|5xWqekL`%!@`DZTVki?NkdQH0p9U +zAx^aA`SI|aM)HRnKf`PmQegaXm$P1hM2C?xqgl@}5n4%@Llc~WgTFH~a!5?>!$%2% +zSLC>P$UsFY7kOe4N|Pqg@Gz~V8h$(vt(^9em +z%m7mwi7FWRQ~VVt@HCmF)3b}PbIXj=$M);qP0~PfxFndyP`&Cy4q*}$BbyQC1*fXR +zmRwSjAbB5T(Ey3iWzvlq^`=^6y-aYFn8t0?qn$yalprq1PX+-<@4Milslt9pqxiE1 +zvQTfy{_7CJbroh`_nI8%Zg8_g#phO*%q8;Q6skFw$smOb_8}O-IRgce>Savmp(tY9 +zZhkiw4edQ2a0_}bpkt)f3ftZvh#L7R6+pinGK!l9x19@M^RpZ}naAnH>Z)zCWC9@s +zi=f+T9E)SgPNfaBQI6zk351E))x|QExg|aq8mBqr#6H%gSa!+`K=5WDxYIDQ#O#O} +z*M~OZ<;z_!Gx8N_5841!b@v>Yh`15nG}^&CLWBAb(U;N!t9Wz1s7^9d_BGH|jyX9m +zj1`|1;l97>?_@yo7Jsr;8r0$U3a<{wVx>IL6KbMDIOS!>z@2ERIC`eACL6j;o+0V~ +z0jIeJ-M>4vQaeZOViBE}|5K%;5g&Fn&3(3(AUe_WzL!=g;>Tg?Tp8-eivWf48em11 +z?z0Eyh4ph$qxRF`9_9(d$ed`0djUHT9jLqp9-hdt?N^DLgf@>vLqh$sYYbS-sXdQr +zk$9v##r%v44s6(Gd19(uZhvB)&}7OJ6eaCP7NawEK^97fk}2Rt=rjj~B4P(Fr-G~c +zi}ooiRtTo4#nH9I7>c(Y)4iHiEik`Cp#2s-?#!O+ZBH!EXwYZMK5ws23Q1+;4ZD;X>oy$9{UQ57GX +zs$*_N3@%wIKd*lTehME{WX6CD`P#@F<9PYp9;q1wWnFHZx&BsfwnsM7n3oP0Q^zrXWT%s6vDX +z`M4f0kh&@S(PNa$%T&fFGLMixOS=LZHn2Ts?G8YCRz4-(*wW$mm7dZdcBDh>?-Y+( +zF*X%p0cQau*<2)yPWTDcmZL}4|7Lm0K?pX;%|`pf0Ysn09Qb!JM(H@$g4Ts5PsiqV +zdZScXV;gygm2>!UH#;>4IX{eZ`bC7g?pCWMINy$hWpA(u{7Sa4p92RXpphs?^X9PU +zk~YoJr(>*&k{e$|lhW9Hwok1m#}!}pqR0zQcR-+5TkC*UGRIicK&>$oi+NvXi=$U$ +zLSc%DT28P;Xyz*M4gLo2r&CS&<#it6Am@9)75qwJ25_a-1gn+8Ayp&!9T4t5R-;;S +z-GQeXs-;>@Q*+7J7TeO#BA?cg5a9@?@Sq-gjL`H5;cXQGR1BNjh1X8cy7x80z88$t +z{;Gg-r_PvNKz|PFSXKJpkg^*fL*E))#P@QFttW`f>#MPS(yk6VxIHp_lQZ^3638Y$ +zt=J^NSh*>zYIo=Fw#r1B^o5vKtNsErz?c)~+fOk5ev< +z?r|S_fp2pA!c}~}QU@ky!k2W1s$G(vo$M0s+zoJJFvznVfE>~-1L#fKDAp5w5PbVN +zq0eFC;qOS=m{6iRMy?;Q%g{EIxcocGK90!9pC!DZpPpk~29_A@?Q>t^L*>Ez<;JK% +zb(2;@3LmuH9s$*Xu)HgWiUHA1aB&TW-ErCoIA_r5L2|#AD!0O$#2^fWlgSDGlme_zQS@ +zsR}>{|FGPU6I$rKy~qEcZCx}4I|4@;&IOfxb~^cpB9O&Vm7qLVrvScf)j0smySXc} +zy@LVop5AF4h*5wtw5dSi1XghyJ2X6Sd{J=ATHJ~Ur1{5yyvhvmX7!BZ>y10)Z>DpSEYzWI^B +z`6>SnBk=TTy+Ii=ojZbfS57%+JQQKS>C=i}ssn47A9l_!fGx_WfOPXmMHsk#;JtHnC2#;WW%*PG6XDB>SWFmEn{8(w0)W3zFVJ|H62sD~C +zJ{|Kg!;jeBh0%4fE)4tNmb@xu$-0^!k?}TNSEcp~mzsFSQKO$;5a0cm{V&QF>j0u> +z9tKN|r73x<;-kJQK-?2HIWJ}1n;7`T*!XzK!vFY5PUgN)!jXIoHYd09#CyLN@`zi$ +zY86uKo$H=go3&a90lG;8K1e_H#0 +z1C0JD_xSg<{+I0NJLyL!;9&5#N{;_u*+OV0y)_PhQ+L4#v)FeeCd3#*z%d3^9t(;@= +z@NrGr`fzrAe4yp=%+%a4lyHkT+4367%EGQIGKt2+@t(p!J3qg@A)4fVo=U}Q_S26g +zTgTToX^O^kJBRY&_IW?sNlP9ykDbf{}(XRxv8cujvk0@2Xa#&yC=f2ixI&b(^ +zVAX09y66?XXzc7mqtq?fZ;X^3wgGQQFI^TAc=qzxRwY0k=C^6Y1Vtr7j>oH9vN&y#YVrz8&^#c=8sv_x)X= +zcg}ubu){+!IG1N+*v;+peV|(-P5^-e8iEalckwzvA@ogCjnOmQB895mg139X;zz|% +z(2R?g$0}php*+(StI+yyIcipT_bYDTATGc<4v}PkJali@P|`$0b&Qz>-;0exwG|>R +z+<{66cZAdHD2?_t(Lbo75Q5MFQCQqS37413vo9deetuNK=qjZYOg{ejn +z90*U6#CwOR{Zx7e31!eeoPJ;d72#(;L-LZ4Gy{67_d$X +zf|E6a6cuD(oA77c(ox~go?)c23yA7ZpZswVF|&;Q&4W_i_Z$ +zG3Lb9lx`c{K(K`>yq?|@C3mYTAE8?TF8o~v1{1fmCc;B$I3PuiKy9j{7La!2UpUxT9>kDcG=6I&ZHa2};>y>v?f2V3z!Wt#^wU?;l{WWY;<LJS~e&6ZH6H9&c(S`xf=0?0d62;ax@i4f6WXHF&|H+}}(NtRaFbrOws7 +zJTKzZ-_Gy{WDNJ-tQaFa0xJ4xPxTj8yd5UuQFwGeDUMEez}4{bs=#<;3MpQp#27_4 +zW(*;F?NpJfqLk6KX$N4vc(%bcQ|nEz>tu$_Q#x54oUgzL_t0|zomV37ZU)tq=ljrn +zcn+H#gDAjZU@TX#Q=K!0Ydl6o%8u3cB1+LRHX(1m1WRLMmHStO!?CnY>Z-`&9mJbX +zVnK>b!TM{VFbv%hXoi%9DH)fN5-W8=ZmW!=xV4t?TI;?aN`1jc)A% +zhZ@+w*;=WsgN|2&l_JPos?E4ikHS%Ob(_7TW0qn1i!3Rqz(LCmWVN*o{4{dPfXvxY +ziqjV^EOxWXnj?FQQLj@Qx}$}Eu6u|G$OhL(!-IIm>%iM&@iPZ>Ey~6cibL8WVYX$h +z;ZWKJ*Vq_vjZ!hNRRQ67-J)uDR0Mp^cgbR7fBfuaY|!HNw`9sfJxC0F{RpIZvl4^>CJ57e>^C +z9V5S`&ugZRXJ~D+y`-5>uJjrAYthxm;*@bF-f!TSmodUpE~=#7$sXw&UW@OXjCCvR +z-1pvvtdqgE5$Jf9hflZpVLDRwazASQTt<&p&PAao8W31?Zo?(Y6JtS@OZ=P+GL0sb +z6%h=Bc*8?Q{0ORKJ^E31{ilpp@=wp@(lh_@rqW@eT(#xFEDa9-8)7jqJ;#D28>hl= +zy!p)bT(bs>Ng2lhH$bIYW?`Qe+1#A-iXpPQrEmtPdj3dJ5FcKga1=0`tsh!SetapJ +znRX$f=76bM#)zB3sSSR*wqxR0ci{7R<dCTs>FujJXhj$_+e1 +z{fB}|lLZ#T7lh*%`~ejC)PmSUK~!6jZYb?x{;wDz*Gnsa`hO7D0K^t**ZkKMXix%s +zI2F_+X=w1JN(w+haGVOqz8X)pl)XR@Pf*BFNQLujRT5B9t`nJYzh=$N7u1&0NRXLt +zP&Ob4Dmt<@Y)ar$*oNCGy&bVa+XS}`GnL@)NyQw7Bim{~1CzqsidDj<`d)x(phJ=i +zC4s*pz}@5pG3c9SMe8?NguPWP+GtjJ +z=AaJ3Nt4y3?Xd70cfq76E^8Gr2DDH^Zrmr5nzAKn)O0tvvw<4g^KTnZ9mHTU9+as +z69tH+(L=pg>$v$s%A~kF=&MMsML3)GN{cKr>rqFDrPF`!pTY0_vo`jTIq#>8~M|fegX+j$d*c7(#LZ(mBQ6&j8ix0|NISCZgNQl +z83C#!!8x0dI_|KMP{SWNpg3bS_p?w@r3=w}#FqM18eDLp3e?a!HT84}h;cK)EqJss +z*O$zFLAPXZoEPLaW>;R(tu_;rDIV~2Fap%}d$Q`h6hkx6jc1ms<5)7C%baZOa_)JdF^|G4t;CS>I_>%pp04e6R;zD$&P)m& +z_uh4uLs;TK;Ky)ON7@NPs^n%+$!zF-FTW$96`)&=(#$GFeB7y(jGDsEFG}AQJ?#W{ +zJ_Va5W3lx=6EJtht+_z!?_g}aZC=9k+?f0JOT4XTbZ@J{fxisw-b{VZml0Q&c#{f7 +zmxpTkBfRSU-l5ceJiRrK3&bLTPDA~#vW};GO5!=RtV;Yb2|LRgHy%>G7Et%GBWN?v +z%Nk)~aN2m^N-w@QO~ck0AqFW`pR_>|_ +zwH5x+?w24nu;)pLh%;O06;)FAkd@_+@B%>nw)d4X)V*7@LdofKDd12|6dQmVM<@PB +zGzcxg$_LfucMh(Y6oVgAK!O)9Ix5_@Q76T{H|NH~xt*Ii)cJL!H|II|y?YyDr!bYH +zB``mxi|CUkbwQ1*h5DT~R?f%ddsW7seyH=aq86e#u%N0Lp6z_i!qm^a#4n<8I%B$q +zKzyZ_l2v#B_g>M82Qd8UJ-1EwJ1!T4i^5ThLS+;sNwea3W#K(j`ZLzbR+8NovH8QN +zhosU@6(pic7E5(+iEx;vj3FREEE5nPQ|VQgJ=EAvMc00)CH@qY!mGT{#f^yW`aI1Z +z5wkpc@)X#z!oiB(q=7SoPmu~8Uj;W6)Ue}GI=y(wNzfb?;~^_9RlIBS#W0r77?wN9 +z^>(y4u=m2Z^rx)(9Ihx>GzQ4NWod8Sx%|oqzP<}EkZQ(z*%BXm_?Wj?&0L#~SrPwM +z1(8C{f&8&(@1VSR6Am0I;Nj++qplg?N=yPXy%4^ +zJOZ{m6CB`F^v;p?C(OOZMyt|EWCW=Nz`V@4f69jE0c~*=vzx$bX3bHwCOi(z6-vIV +zXM@hSS>6v3F04uWMl;V{3-s_n9@(8k$*)oMT1kP= +z#3gq5@XIJVJ5AJY8ww4S261pB!LOizbNIyCz{B;rco6819vfWu7?_jJal|FYG#l*h +zgjQn9hE}>1O@6Smnf3jwMdvF-)#i_ob8R#VE1$U~k$bEyX32yI+cBl|xE2A$aVQ?m +z=LP!B{N%$xnbf+ceM27GTD%#W4z1KTujv<@uR^sOyvMXku`;hluf|+n{s{1K|Iflz +zMOq5Kfp!r=qU2OPP~9Ov7>oHeh#(d1##{fKDX>3LO&Hi*hgLbYVMSc&@d=gMlE)=0 +z)pd)(J3-D5P3Vi{tXi4*$OCkzvmgZP^2I|McAIp4!1RKeCn +zp5HIi4KPcOS*&-yY-;X0-me?!1=SnUtp_?UqS9gV3@ZM>kviJXoOps@|FwPtH1t59gU +zfrt2L0b@WBPh}qTPp8ZXC2YFIi+Hup&Rc;h;V!9wmCmYveWX&BLZbNdvQHELlj>gm +zo6FboiLz>cRb>f3695`ShPQ)A#gRu%r=9bV4-MvO{0|5q@8zuatl7e}OXdo>SY5sC +z_{833;PS{lcEaC8dsrXoTB^hRm7cqzvPcVcuJlPq +zYyllC#X#%w&3j6bZY?@}KU0_u_tbhG@z!o4i|N!FF$XuNY-xHb7}npPaTPND)HkS> +z^zA>cTS8mZK#%-OY|Q4EwLV(IJg(LcdBrVL(hikE5gRwPEPRl;0tYgkL25(~%A$Y) +z7ustHSqf`oD?1jiPRH+wM^eYZ8};PuSa-(zd|A# +z2H~vBb!DI* +zY!-pZ_tV~{={$2!bE0XxOB14x?jfqeGwVHj<Zszskwp2vGx}umq~+Mwcf7DBJViQZgOy#OBwYzBj&cPw_BJS9t40ToA5lL%<#wYROf)A|$$z=5=PW#4 +z)4<)*|I8qPJWi?Ei7K?p7^at9Z!97^GU-`(_YGa?vV*MllV`qhz* +z*NwO{Fgt{nn!f{p(vyC-w>@1K-KE&3<-}K?c=IghYq%mp$YBbTDEVGUM3S3TpnFSElIvh$VLnyi2G@p +zthq{MTrf3y`iTx1G{^tDrV}U?Sk*OVfZI@_nnI`Z`EAR;0TqKn2$z_jKKNpImmZw( +zSJDv$OZ(^A7@AN0jUU$#5%w4`T#B|oJh1?!-VgQ=;V5cEJMy|^LVWgiet=B8>`ahY +zu#x#r$%xxZbc)wm#qUN-7nd%O_Vo$4xRsMzZ||5`5Y1f0nEZE1cl{?Y9~zZ=q=9|U +z$z8Re?8P!S&NV+%k<%-fuvv+gfx>*+V?fx~oCMI%mWJh9@QaZ-)ImTx`O8Xb+oR{a +z6@aYTm{51dV-QB>?+^TnpIIgjflR!dAl$Rk9*|RP#s=Y4V}6V_aDbfs6p-Pr4pkk6 +zOR>6yL?YLE=7%xPx%G_#hGWX}UVSJtoZIQFa}=_o#XNqqRhv0dI~@RKMo$JAiJU00 +z2irHWLq6lsKR6*CC5Nl)C%NHBqQ!ulTgG|9;IMG!36(!&HYwx4je1QH7}TCk6>e|s +zIWoGQywnGZw +z0<(<49Mb0D^;@!VWDcIfk?P09O-oK;&4NNR2#1TI_vLpozOrH!@PQl+ELwTBUW_$)`F-ffCE@?Qwwhlfk +zPIHVn^A_19Xg(tbd3g0PoczG$!&5XLgm8Rc1w?a1cirX8%QmSftEYS`Q`*boq!f`R +zD|z+AR&@cHCRYTHSvEbpNA!o_1w^rE}UfPB}A=8ynLvcKnEMGcOCxm&y8Y_|Ju +zvPYj^x1c{EP7H8sixiLoP-yIvF{9^KXH)8hWT=IgTJuQaxxs=iZ`>{b6<)NPlPLVa!G&&3_rsI6ldktTst-{2N +zp7lI!Z5*Od9)qAbF1pekG;uu38R@R$2<*+A*$Y%DUq7*7LxN(x`X~h-xOhqgq;oVe +z|KRE6TM}Ri{>?m(2)@}(p)arSq_e%v{IE;K^K3C$uCxv|fX-&%XGcCDBf?oxs*W6p +zCnMLeSe9Pv&k9pTw|$rDz5(X72~08>Pme-t#+CAxwd|K3PFUTpqt#R8Lj+#`a<}%l +z#^toxTgUqNrbji6JigH)2sh@KGG)d^&f@knW?>i-n=%!{P@40+aZc6LdFfK3ZDvYH +zkpxo&>PbO$h!HZr*`d9V2-FfgB}eowiI>N+G}v6@m+hc$aEu^QRReNvfAQmdX;OoY +zx_{cuIL%%d#*-8%bnyrBZ`B!i7tPMRI!LY>9E5TF07(<{RVl4;{9)h>azI +z8d&~QpCPj5x+>`B*FsZvr*KT`4(57Fd>HGH{`UlJN-KZ@yWN%6>45F8#gSa&7bpee +zLvn`fvR(^FZ+AY4fF`6jvba3fp0t`Rcbr(pX_ +zI+=GT@vE@#Oo*BPG5-7sj3Kg!X{TzK!lp-Q0MB)Wzs+>uONxvJd%|2aku35hghj!&m7*%-QE+yl3}x&3O=@N)@dkZ?YqTy +z()0ZJJYiB>utl1o?Fv2&e7F+dF&R*t8Mq32Pcy+9gxLjqmrUN5eczt4Y`k$h)WRm5 +z%>&)Vj(L9RIaeE9z(a4Co7cwy}AsadvxqyjB9t0}d!g{ZR>xza!>)Zc=MWo$hKaVBw}dCT$w1g=fAWcAJEm|#mF$9c&1&FK}GA)mUO7IZJP4irfo6-BU&#l1PDcG1`-htfNOXZtIB&@eD?cZk5CNUVsv0 +zp?dVA=MQ^Y6ve4cFWy}J*s;23QZ?I`)HH;!2{k&y3SiG_Z|o9onW$XX#ZZn3Q-?JpExvuz+B~`LaFu +z^a-YIZ6PpK@Cc!h7C>3o%_FU6*dK&$%cO`He3g2#y1SWkkS}I4A3CoHWo0AWA`7FNlAFYbq=B3wQ}3*pjpWUZMF__!e}s07YWTpUyD^>pV`FqYrU{{r`m1^`RHjb +z?ciK;L)j(eYJ9PW=w!Lge6asvmqR+BmEXHoc95aJc3nEaxje66VgLXajI{W4K)w-P +zveo?nV{+1EK=BuMbHp#Ng;PKsJo|+}O^Q%!EsqxFE0Zu^(^0al1s6z|^Po(4Xp18lOUq+3NX5WroxW#b}@vaEE7=-C^|fC}Z_g{H+II)u&flXd&;m9#PX3`F!|Q>)kf +zF!5SWH^&?ObHxzZr9#n1ks@42>r(V|P-@_7Say;_9`2{v;LAjiMLFuchKFR-X3|A& +z;E0>QJUB#x5~9?+OLfP~v$O^0BB_xBD+zK)?PZQd&&Ci%*fEFRSkv848 +zSOUuL1Y~cHhFH>l^os&9dNDXY*}>(!)px3ro59Val-l%Exir${3UuhKZE|?*W4&}v +zeJKd`QxeoxAXVY2db7fP6s8aGF;r2Xewx5gHIlyRv+2pu2!XSRd#ak1|ITVPHDaY! +zdCH9Q_f0w1QL7fx?uyAYoN6Esvqe1CcCKT(cKYqa72m^>@na>jWpzD^Nm!dz)g +zNAWeU&)TdRGj0(U!Q=4&zr1)-n^mGX9nPbYYzb6c^-zEkix$>AOGCw)O#{9v)lE;# +zr2;#1d#&<>VO|5kQ;%~HlJ|lO7S15~SgD9P9F@kn^*G0ZuUb%y3;J}6!V@J=@$~T+ +zvHB}3oXcA)K#Rf82Q)8Y$Fcpxg +zJ%2?$@H0BMxdtcKwCY_F54j)J^d!`bs1NYc+_U+AjINv+o1JVW&PTcz6F7d$cg*$PLEx-MS_m+qP}2*tTuk +zPQ^AVwrwX>v7J&II2nYy33#?+1LV*K=Uy*L$~ +zMU?^;0DuUf)u~e+QtWtxt=2Z%l$|gbY^sMrGoiEdNA%Ohktq2yCJb=atL@M=gq13l +z>ie2%7Uq0UzWADy+^U-OfvaeJ0^`{zlyE@QsEHktf(|_%jU3HGE}|L}$01v|>I*M4 +zE6CKEbygsa3YLDZljxdIvALTgS#{YOo86=n7;=rb9`9^o5`%}1g6suZoZvFLM3_rPXqAdD>v**{ +zt--#1=H69^xX*_7N!8%sCWuenVA)Uw0Jr0Li?5%GB#wSuXwf-f1OGeN!!sv$Z!lzg +z9n&Mh;_+b3+l7NX_K>`20>Jff%HTI7vNd|roYf&$HXGgHKHrvgx>bzOPU(g}wH~Bp +zk9KVQdk@B%;$*VuIeUd;p4-EB%yp%bwk@?|tJ~!92X>;7*QsDO%8;r11G3+5m)b?B +zVV|rldxMRtK5#wLbq9^Z%o(|hUyoo9UOmtQj%abP`e(z0A5mX91W~)zXO|Te$;lU= +zlv>7aVZF$QYViYZup)MT2Fjd%1;9<3?r;W))GYbSM-=^f`&Q2APy2{I4J$2?65F7; +zR*LY;a>K;ZR{p}}*wq}q>WX^zri(5{D$cBAa-$kR%DYh4R^s<_Eg@zdI#|b38X7dw +z$>eyR=C~HO-Nuz#)*&V%&YTL#aGe|kD>BTk0DG#1#=6O1;qVin+KbDbMD$@~tL=`eBaNBF0{Dolgxa1f(Zf+u2x69BF}#(b$&F!JXn)`d##)zNH-yrkndEY-aeP +z@Ckh0T|)k*#Vl9yQg2I#-8$x~P}a)hWh6#_FQ$p*a_mIS4?}rubqk(5PsZ%BQ;eYa +z_gdMKcT?=Jm{Z0O+}Tt4b>x=I=9UL9@5i=9eTx{(gB`mS`d!1f2lNA_3!c3x2+had +zEHt;XJqK1dmkkuKvyN=^t!ogpf?%a3NWpXMha=4jZ*_rM>&J5=hs~dt%g@2t1DfKt +zoNae@5xP2GL&5yA{P+qpL50XxRpv +zNinyA+cz?j1Q3`cubFaLA4M~+2U45#W&25=(D~x4+OBBz2(V`xJ5F0wVJS#$Vu0~d +zf`K=*wo06YacBp<`e&MIk^ha#^Is!Q|K3ZB()6fEowO)O>y!ak1zdYrf@B@dFKTbZ2 +zB99NvC0$&rt3A3gO$}M@_SGzfW1^j#E3oMfIooVN$dy`%W)x!}5G+stdf2&&7(Hqo +ztUMg+kSfGPtvl@%j1zxEKf +zG#L8^z_zudFbT#qej+9$aj>hVe9L)q*PmV}=KN8C +zC)W@W;iyu1DD-4qzMk}%4>l?P>F2zMLu0%(vOb6O9oY%6 +za9^n8eDjc)z9HQ==iDdb0}-pS*jELg9!oSPn2L~kL%b+4p-S{LjHMyR>wT!oi&3lr +zbWJ!-BOc``e24_eqr@dgCjg$$`ZA=OJoMh}C}<%x^u9TOA96O!1d_@*>XmSlM-_*K +z0$Oa2nH}(r{KV~j)YehXi#`qeop0OtDEjbq9%WktuBDr3{UuR68HlTkwu9Q2$JL>W +z_FNe6vC}&gYeY9I_k_BgoIZ{j#}ZU)ALa&S$1;+??~n~S*(FMG-RwiL{wb&HMjzOu +z;=7wScr)Y~N9k;ZdJG0gyFH&@$^L^=s7CB^Jety3$XPtP5^mp=A9Bg6`fS^Ua_z#% +zG3rM5Rm2JLRbzwxPx&x)r!F0z=P6#VW`I~EIc>8 +z)a_L84X`Hj2fp+-?UX*Z*7DQps?3*pO3vKe-Wyw9m}xXB_@-yiV!=Iyz*tcMivBo!H=#E})Ac2(eBXY}Z6K%>| +zlLqNgST5JCb=D$C-TiV^-IU+n@EcHfb1ZyNAsVJm9Vdg??m5ftkJ63dC3<2*z~ +z2bp2*0%GA{wo+1Pu_*CD8aWe6&JQL6-_0XPGkKZ*+ZoUx8-W9R|`(E5a*{@ +z{+by$YeN%@+qI4GPMRUPD}&M_$&0q8sk4DSSF>2;DYkgf2X3fqxZi#}%b@&^UNH&dZg-y1hr(|Luh3}Mq +z$!ynfw#FlDLLONdsLBOwiZ?>mlBgSr^x3a_GN~m-k=&;}oMR_LqB4j5_%D88F1-C3hICg_}4KOruEI +z%|)-R1qF;n9oOBgdi7#wh3z)AOuX?uI++!_A+=6e1}<*}2k-5BWg|LQz+i!B`q4}c +zHGlHP7I|kt<(BVO@d=k5ZRP7>V5@JGI&dflVLRIIwX5n%2Zucc2!h($}BK$P=!yGGzMZKNMV-Hp8;`vR_MEj{emrbWKFUxQk +zlOPWsDWsTHt61dSP+_h#o;HbTR7*`VI>ZMO7u#1-Q%5!Tj7FGJcpqPI2DtahQ*fdr +zilY%9e?>fTB6q$)yK5f$!Iz!9Q50I_edL)a(JOfji^W0*nJX<(3KC@z_-!fSs%yce +z=qlq+i^Mtgl55WH#fY9%h)YayH~Y{TOosdSGi3w3Hg38{xja^d2Vs*aZX-F1RSSJg +zbb{Ok^J+7hZEO`>qnd3$%&QMz0HS~J-z-LdqVoT_82tq~ps8SNZD!*7pAPWi4$gLr +z%4RN~h`AVF6K-y +zEKW{`?PtKn66Ep9P6nke=#G0BzmO>}bY-(Xu9#3lPzd6kb?|CSMxsbXYQ?~Y6EZTU +z4uq#+LV7<<0lz<;IvSZUmk=o5mxc^1r@@7oI`irx_G%`FBhw1E8z_Vh*^e$A*;L-g +zr7VD(32+4zh=veV;!!O(swszVDBn~CA(UxmgWyUJFyQF&tSYbs8WtFdLRiMOGzB8b +z1Chw)VMmGT=zPIecBy{@S8+E_5wC(y?t*ikDt7SuJAb(us$*b$_x^HoxjzwY;BS~V +z0CL9`=VBt&Buh}b05NA3WEU)dbMMqehmzFq+kILr=|~a +zXqtW50r|_}G@TJv_92d+ytzI5dxt?~Ie+tZMYDqHJ*03nBD>wZe%0IJYd*{cSHdvX +zZh6C47$3ej!;rg?5qa-;ME!SHas*hU%3~n;k4TUJ#%1V_TLW!QsX!KPUIPtTvBU*7 +z55~Ses8%dkT-f6%Fz&MD5dW?{FBJ{(8Z8=hsuqW9%j9p3`a%8;VM=o!-1EBebIMkZ +z@DcTHeVNu%zY?ZnzA0nPhKt|Zt*CxtirSo5JDLIb(wEYsG7oZ7Jo?8aC@bMUxYW&h +zp`u6bhI&bIRWsVK;|#0E-+N(QoKi3k39;pfm$k-DUsTV)awn%x2L&G0v#$Z};zOOG +zo{G%8+`g0C^mcSInTMn +z=?y$WBP8h3y}9z8ijk0oh*4vw;SGle1463oKvY-`LEq8kt6UwwiJ2>c#!+EJOXwzR +zC4J4d3P#*U$UVT3Z;gib9roF2Iikr?xT#NtM#9MpEb20TOdHonzHvnliHkN|2r!b1 +zBC0b-SzMMDb~0@(^umMyiYj9Qry>9SU1Lk8=Aw2EqF#-gxSIfIW!CozKR~`8IMZt` +zo%!xmdKVqOYu=;vzTK;Wjmt^?WVas +z(mQqQy@OE$KzT&J*S!w3S~d&;f3GTVYOqqQ`9=i^0SU$^{-O6TR+N= +zqZ?=+sF80I5Gz3Mk_G(@<7m*8&@6OQRX~2-WdntSQg~s|Oknz +z8Rm-OB?bmmj;S2hTo=XberE|tdP!&uJ6W?|NCmo?Weu<8_DB8s=2Nn?&6FfBunxHt +zp3K4>0f9fr74^vY!xIIHP3{c_uz{%%EDuPLJ +z`sqe~AI@e6=gu*C$ZS?GU{aZe-1%tu4ud+b{(@iCH(f<>Kl$7ie41lqLRbBKm|VBi +z`NMoFmtJ=)@i-VwG?st{HFNMewT5AghB-A1h!8}Wntim5==R=CbUg0yQ1&K2+4=C|Do|?xOH6OFn+|#MMLY@*n|J5A79N95wc2`GGr?^4ZjfQ!?)lc* +z5$XI!`DbT+GvDXtH+LV}T5UWW>t}nr8%y{IZO=hR)>M|0Iv!&TJFAZF?H+Rz>*n|Jj! +zN&dA$`zjabUdgAZu#VpV{W(19l7M&>0&lD*bPzyO7;(l&E%xrzMND?!U&PulA<%!B +zxdrpwQ?yj|>iett7sLS~kAKc36WfmDyID5{M?^%vc4rOc5F)B6^%9f1u3@Ad +z+w#3>CGdGC;LMgovK9Y>k82DgD!BjhS|xhdvxmQWeJ%_DX?t{ +zm{W2G21uX>J;B9f3~eYjK>kM-#yg(pe7|yX*3!=Eta6XVVHK;2-ZDde()f^$0+0^v +zg(vt~S`T2mrPJqpHo-?+0ie)QUA6-{$a*?k*W_DS$X&xPueW@{*4ZJVBR{LyXpee) +zb&{bEX@17u*9pt5RyI0a4EWwK(_p~&Zn(}`q58YkEn4A0nQMpbSovz9{Y_G~X%}eD +z7xhK0?9(7ARxKxbq5VwO?jZ}|Qfs_XBQ|}#WnS`4n>J=g|Dyr?=W&O+bxWM19__X+ +zQZf@-I$T#I6v^F!A8kziXMTKVElAyq6oPP_0fuIhtbh +zFqks|_C=BHhdJ#tMcEo37a>K6Uk<-mLFsJ7Yam$IP8Jg7}hwRf(#J{PeUYY@9X)~@)@J2a}cv*#9%2fA=^ +z58)#JEJ%leUj)y&*gh88?3k4zMB2dU4WgyOVYV<4_?{KV&dB>9u0izSN3qr`MP6C< +ze#XE5R9cLDj+652_Y(1KxFO%__GKa&-3!IGFmPm}Xca6`)0!VE&YXEvRrPQ`t%2?U +zXkmQ)c1}Jf3@}>#XeZ-TkmQhO^@XO$O_@J@-HGCUp>lR=nQCb@@91zM4Vx3%MA&=#UH9vgUrR$YCGN0M;16Tcy#%cZr7B +z1~QhlaXVaJTuHgY_VR$^bDG;DcH=+Yd)34e$V8iH;9)Sw9ac)?7zF#3#iu5)H@CF{ +zuvWzr407%~6wHeYo`=V(27im10t3Rugo{GBSG&|>;m2p1t3Os11^#vYTM(7-V`*_| +z%!!T7SkU8Q%E|}buO>GighFfM5cAc2xA}6F-Lt%q(5BPK7ZHauXUi{RFyGnde1yET +zsH>yN2VtcnAYT3E#QKsS*=I-_N^rWc!_N0^A-*IQ$N{%SY^e$fDE$)Zn$m@IkM}*P +z#c!G=@(gBVMye&tSVQbt7B!w>%mJXxeYZ-kd4NSZRK@TcHYrQPiP1E=}chjg0$m|`X(qBn6QBF{U}UGMf~ +zps^H3VQcet1GbrBt9H=T<$>OBrH%4qB{#-Unx$=Vf~UA&-{AS408{6)B2mpd19f|6 +zd!aClrw)7m5$6U8_sS#Q7Ji@RRZVN7z1ig#vN~Lem*kn(`lI9OM-NfOxHm4QWkjc& +z&8v9*ZBeHH8-}*+y7=QU*h2L_GD@}n!>l*znE{ZEQKv7~%^gl#)6=wDpZcvJ`{O6p +ztc3Q9=b}^ewWL-@1-}XU&ntsIE=M%v)J(NT*II|R`baQRJ7S&g&Y1w`*3u!#`5ky% +zbt-%92dLvkF38^~c>X9^{;A;kd+Q4;Gl1j2Vl38ZpE+!>qkP!+egyMNi>cEp7ZZdR +z3hs6KeAAs@vqY496-qGmM!vFcs*+23J##RZl>S*uqyY^MRDS&!_Q4) +z(f4{ke&Wd2U=h&{)kky7eO(}}ZM*g2*4M3PP4%sE{rA1f_1=Nn_1>>r`vnu&(eoQ6xOh`~ +z-G@ThX&ElXXc!o_egzq{EZEVLIj_GCI?i_3wd(=Dqa*_MC+h3meLJEtc;U8)mcuQ9 +zB|&Ji`(NdzO1|t +zv@w`T>2jV0k(ooUD7_JzhB}~!Z>D!dse88Vl1#f;^pQj+6;r`zx7{ +zv8yt;m5j|_7rw`20N)DqH%+1e(M)Zmw5FKHJ-kJQcS6QV5^G~4eILr_sR?+~8Xil+ +z1Ku*@iE^%2B+pKy=6cv?)r5&~ts{`U@?KCT=6G1E^dKGR5(ga`D#yGB9FV8tE +zE(U@KS(p}9mkQBavw8P7$U+NT1h-2Dy&|10?vNGViuc^ToM6Q)h}vNkRat4Na(04x +z+a9GP2o39`BgvSKMiJOaDrO_}dqMsBW&`pLs=Tl}v4gcT^iD>Wvp-oq$xP_iVNe^bQr7_6jHbw}UWTl|M#iPZAtF7!{IR=B_Vt+v55nPPsXTA}2 +zFOoclEjN7s%WM3c7X%&pr`>d_-xrk4Dg6QjbEKav7w|A`0=8w+DbTW$(VTLd^w4%E +zmXYXZ5cA^~nkgwpa?@63=8wnhkYK=hrEH-_~v5Su^`~=rQ}imNoXf>-d#fRvz2ku&T_(Oe%eJUw`OKx4>o?jwA#h3wdj(KQ +z&v!bfd*cc?22q8##38AEu4xPeCC5*5hLFgqWUnwe>3R^)LU+UN6gB|Zj99OKAQDOa!fbtVZ69Ay&q!o$b@Ra7>k;$ob +zEDi9gBcz(Ock`N#t!hreAepQ1%B1Z#pUJC2op!rca}N_99I?=@{{}xCbfFG;l9Ua^ +zULp0|p1fkCk5`42L5j%5o7u1Cu&WNlxyKL=OpfeMgK{=wnjv}m4vh;`O&bdX0Hc0% +zM2d#Jn-JnNxwXJ(lNCO^v_I+PoWRHP7nxq~2^#ombcff<_oS_?g>6wHlOZ~@iFKn6 +zT8cMK%c@L4{akM~j8hw$qrxvDgr=|(hSkqZM{vgr8wsFM6N!?w%*VyL9}lN+c}e-o +zQ!<3qFkP?$IXvf--`@hhq| +zEft19#_5U=700ujOyamybU3Tb83}`n$0IS=T|bOW=hxKLe$ZhDifZREc|sSnekQy2 +z5V1LVOa#bLg0GLD#2gDV`c#^L2-E+O>VFY1`DlwfdpGjU=eZO-Y6r#y9wYkhLU5Tq})TVi9GN=FMs*VMnW!B8m$4J@XYfjk++5fa8Iic@ +zOn)mZH7;D&5v7syjo2$n=_?=cNdM}Nyw9Ww4<5c{q>!cjK6jiUGC#ZkCI1o|&F|N= +z!q4@b``hBY(I!B +zskaeA6UbrtA?mjo!q?;XjdHIGD(_7(iYpYnRmbPqj3B1{Cb?&fAUg(dpnaEHelIEA +z$daFaY%)t%@=nKNHzcy_L#^kGY8PUFoNXN +zziZcPXm$6`Y@Itv&HQTRMN@4Oe7ie$zFG$Qd_~eP3;wB61gbQ*_KPQTsaJG8TF +zhWVRCs8;hGHV!>tk#VatBDZq|JyH<<3_ea^F5Rs2{%Vi{mTy$3k?4T@@JO1ePUA5= +zr;R)=+~N{s8xwdXnkVzLOnX?j-Q{L@ADA(ZNNE73n)|Cxwd9eE;O;ib8<@MGdAXov`r=z{|7~xY3pDW1!K9Wv<9gDS%6I2}G&II>V9(jp +zV0%ld)95mvTmB9Lhi>Wu$}dI*1!d`pKsk~IyM$$U9_f_sSlduwRRnk!s{u!)XT!Ji +zxF19~_IdISi(S6YDh13E@&_kn{3O)O53WDKB3aaH<9k7Y0OD^C*6wK)-gd;O%Jp(j +z7{mv(ijyLt9~22;lixqI^s*|#S1;y@MC7RQEIgqPZ3%wNW!o+WIte4}D`sG}@lrBf +z^A6~2xPXfA6JpU>D?mV4T$&nwE3z43gTFUD+B`%?8z3sX76p+v+MXD$_{yR{wL>={ +zM`frOXAz1I6T*mA|Jz{*WG&F&fX+3 +zp$Zgpl12d})9(+TA)7o%itHa`(|JBCq3fgzn8}o&bD)!D{*Z@XZqX)94oQ_YVBXqi +z2@5;zmOPnEe+V`&K*jElLZyei*Oqq-GlQ=^K_Ahn-|YhdcH>uQzcSb~X--iN$WiQ( +zl2DSo68?mA{Tr_^wm)cQ|Gby{pBbK6i2mSyed6>p6a9DQXBK8QhEK3CW&kGx7u$ca +zKeMs|IRCOaf7+h`pQvVkVsV-Nz|>pWx|%sNe&V3Hnu(g3IGCC-%9`0*xLOi%u>HIF +zS$)hNml>`Lk?AAfWDS&7`IT8{4xZX;H2=7UDu@m~8^F~5+mBjj&Ju4az~#7teWziI +zR|#!QLJCyt!5gpHixmN8(R)b1!g4&5nG7*W$fkG4OK_V;XxqnP +zNhjLMv}y6NdObT7eG>N(jDX>0dg(fTtR}`6W=i`~R46WyNAn^tN+=2&Px5jXu*k0t +z@RE7w!a#W3wOuQ=PofcpTsVp=f;es)qXla8z$eAt0ZfG)6I;zA3-9@a#UVopD_kRV +zw%`Z)=fL6*5U*?nwHOv&$j||mTLH*8$ +zaw?-@#w>Z{KSv|S0p+(R;B{gcZzIQ+{C+CKAWwcR0xlQxOG-@J!L_^`Wwrum2CE?` +zPiL*^Bd4d+K%RWhe0|kmbZAhrn;L%c +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 +zZ=tx6%MKcb&HJBAHv +z)417uV|H%EcwW?Ih#e$ujBfCo;rJR_LXEi9m={l<2-dL6GP|!~X&8l@dIjG6beQUc +z9!G=sbGLV=5t;)!wA99N;+{B`LzT1w%NKBRD2ALmd>XHf1+EU_a%uqdiT23!g8a~; +zA)mpsN=v?%hM=+zv((LfIsL?4gGoK>J70n6wNvNyj%jciN%)jWdhNp5yOZ8@fjPJj +zA{`GsShs(_^y5?03O1Nm>cg)mn5(f&(t_STi%#Qm#<@Y|z +zv-oBg0c8f7sJt`ag9Wd@`G@XSBQ2J`CQMlx_cXKJ=MlG0-4R6 +zSqgGYMu5yFy@4jZue5$?UH%A>U>e1U_u#&6dNo-R<0gx?h@<(wDWA?R^pXfs%wKvD +z-1Liux}TezC2ck3PH`_bw%>6k +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 +zpYq9y_D0D +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 +zG^>^`;R#I2<#~6|)c`}9q_V +zm2-MESLNZG4xPpG2HU^~4VyiD;k}>}sG6xPn{f$xAAi)nGM{TXh)ihAxPvUaUTM`qE(kCkX|Ouy}HiZT!=37G=9N|GC@rJ!x8Gg +zde`~qkHt(J%>QN@R<3Skvn&n@x<>U&pKn=3{jR^Y!M$A)GBvR^zW@VJj;0a=fhdx+ +zh$fx3e)RS{R`%f*+(O*FTrk|()JZ2ZB_pNo%e8@9S~%R*i)*VA+VG(g7r81>pZ9qY +z-z%*ED8QUzBEd9Pi@`7?Q7I)GI4A~Gl5HaFUD+X##e6vsHZOrdVG?i@4!j=}3zxpw +znY)}yxZm&XvXO|=dMNLbdW|xASh<{%(hKg;tfE%GJt>dLb12Er!5 +zBNR7tA70lrKW#G%jgJ{dx0^E|XDrF`)G7-OWkyYtT7od#g=OoTO*Z<6y7qg=^ESCa +zuP~`|FqL<=396*m#2L?YTQRDXx6?Mhp;e%@TjVI3Oh6 +z0NW2K)e$`=TYAYIW;4cUyHSwAb3ZpOeQGF|Bpd+EfvxQ-*isCcK43*Hw8bq7$%;Vd +z_bD%2M8W8ASyphkI2i9rVk;MpL*)|xk=KyY2ThByFeDU=)=$_sTPx1h&Ew_`cDN*3 +zArvlGKo9IJ7#!OlnJ8*!(z4AH;BjM(N^r>89i0S$pU=aum+t(`(^JOr36eh&VDlYN +zY)CEAe+jwzJa&Mq)=0cRCNoKA0vi3HM;HWznd|zt3v6rPR}c`u)?=6~76_Ci_$I{S +zWsWan9-DEiUHU_$z=vhc$Ss_jQJ4$5EDX)dpU#xz;NQWtcdVnk^QQZekdVGi_aL$n +zk|NQu6%1yzfI|~w`WTzi)|}4ch!CG9bn3 +z{T#+Jl^_)0rJl&A@4DcVPEEkUB^sE?`o$F{nz{NW4!R4x$7g|7Qwg%;TsW{^gUnQl +zqX>Y5fr$}*O5U`cWBm5s(mq;08?CRU4#W!nOZqeS)l-ue9m3@<(%Vz3`bm%M@yT2( +zAJgZFBG{LfX8(nwo}*8&DRG*jOeHC{6I0k&BjJ&c)$f$KS+}&myd#8m!w+O3L!WCA +zwVo_7)DhjlSA~fkP{7Mbu+CAc&xnCSAJ!iMlv6<}0=1GFEJDS7x!C$EB#j5v6^sxx +ziy%*%0SNxIG-(r$9qc_P3(H^94x+D?N-TW|nTE9U789U8C*TxS8Agq7`wvQP|bjz?+DxC_phmhNZT+w5EE-+30hAaY=Z7iUjL&mxXbBr9EeEcCq +zR%X~D)Qlu(SU8M$Sd>bqLvDdnpCtlo)MD&Sq#OIlCCq2RHVs +zE4>(rXFvRK8+%gxQlfNelX@}~O@_Jj;$}pvidlKeY#791wKzNv36 +zBFfeubBJeq$hLp&h@6Bc*&sR?6c}bWjfO1vkJi?%uiV?Lt_OrMugcd>DKA@4c%zX`*VGc8r`YR@)3^g7s>OITc-I-NtodG;2>ziOOYWFO( +zKhN2IL04I|Yu_7pL12ro2#@gwBjP#$0)^(O1Nfu%JVKXK@T22jVJh8Lpw#b47I(^8 +z;~-bCJRWdN`AV7Ql+u+{fKe&YvEVuzdAKZfD5`c}puk9D6J1oiEW{}d4r +z6cQE@p%DTFRx>vSkT5gK8avYp+E^Mfh**Ps(3xACGN_tc3s~Em|Hu39dcwx`h5&P0 +z2O9t(6WbsEcOd_D0DA`^GkpLd3p0bX{@>3`%#0uaMh<57gv@M=e|yUNL&P6D(7!7G +zH;dr +z3h@m|PM>Dy+7+IIFzzqgm?U|h7OW^BPs +z-b|iUc_!$$V;9)FW$W$DcR!-G>w4zYx-?ij!7aC0Z7J5^l)^e3EDyNa3L$~Y;0^azW_qwk2+C47J(GUgH&^5yEJ-!Aa%mm?Tw9%N<}CDI=F=FkZWJ; +z%h8cUji-l)bee&A-TkvC{>$x&>W!TAfpBK0L#7cWxCFiR#@d=h4`>51T^YD&(8^79 +zm8Qpp#l*nCaK#UP(H`9^7h>wXr}R+-Fsu}bt0G&C0h5M=>e|*;g6C*{EMi%Ww|{`= +za#amW>dG5H3A|RUO-CZieLZLzp&+f>B`&X!6-F703Sf&*_izE1==jm{e9^VZrH3%8u4LulPBJ +zfJKwiLyPgk0{X+QeOr6`7*3-)Z`CdpGQL)i$QtQaJwSLX~QhUU|( +zq$CW4Sokacw{{2X{4X4N6d;FOTZduuzbIj1Umi6l(P18`@E;vn46cPu<#+S?ie6T1 +zI$vMUy?>4BzWH7ITuJYRL^Z`0?Z%F>pgkLA$3mFb+*}UErAJ?9@4{6Ssijh6i>un6 +zKqj}{t3B%Qdqp8HZ0pZ&hV4^){#79p*X98&bPj*bi +z)|B$g`t)8(uB3>>B#w|u+mdjphT>{IqNeMFh1N9b*c_Gcgkv13crDW6AIwC>gn(~V +zUvi^LU}}yBoi87V=pn6|T4o5SrofV6<0!X@y<}DSfNEdV?^=3|Vc!ozWxqJsM +z-XmlcGH?EgcUV^>E*MqrakJdD_0|zWn%ulSu}07$is7hbcV9(9g}tc*Cj8)WeSkr4 +z&w=Aw2a{6BK+`IJSIQyD18*j_=v>8en2di8bk>>#8)9#Ym5^MIO`FHbltR2x8M$xZ +z4gp(9%?nSEQeBL#oTPVc3HV+YY92M^fvb6+d>1gbjVa}M#fr*3Aaw#xP-N}H7DAJ< +zD~4-ek_lTTTaaK{=g!vpx`ahuYk3@(r^zu|6x$XfRjHd}h#lCrHp;TZ+N5BQrlp&) +zG_(-%6rY&9MpUag-(4{BuymihyK9Il1$f+({1STgOgSvYVBG-KTl&QC6mbuK&2~FC +z5@O|+tUkj?9Cw@7b0_`nsrL{-3xsT>GkhB^Av+iZGha#8}tb)lv- +z7^ykW)zd!0MSnY|3P-I#%IDEa+Hc2&LH~gb=CdP#dL~ +zf_IQY7QK7KeNpFEn~-2SZ4*!jeVaFP@=WUOICEI%%Fs)g;xd1!hK;M~dh0I{8KdbS +zwYz}T8R7z~ErwdD6j`A6loo8V;lK=|V395z80&HL^!{bF3{9FuNZc#kE2BWM)w~%U +z2u)C!LR$N*dnfG$MOjFkCZ6t~*<jxqyzpfK=v$Vho>nJOc)W_^xa +z-nbW-QXW*xX27b=OyZtl59SovF{U`cz5$-kiZBV)Q1>B)MyG^f;>0m~nxq8dEt>Yd +z&sKNB1ZDfO^7bXYR5vx7n;B-Dy2KAM)bI#eVEX8sLjS;Ez|v^@u^F6b%xbjroe7gW +zz$xP({>ISn;?dfB{A&v%MW!NRQGMY|<%HtZRcvU4Z`17nszsH}7-{>N<5BQcuH$S} +zo;zOB^z&jYL8le^jDCvx&m=)7S$fxskrC@Y^Nbq^Z3%os0kiqpM07C5oKmtlvSB+o +zaxFYlSklMBGfDcp5y!FS#R+>1F`S=rEcE=v9${;&h_zRrj^wWIH@tscPw-XVWJ_V5I +zBH8`VfLL89$+HxRj=iPQuS`!1^qlk#8F*4!!})J`dHlmXEKHhgCrFgZ58oPIo}QlC +zx=xoUwP5|auN@xlL5mT4f~jIU3i3w~h>)eLX-FGTFn7&?UGK6b#dvP*^S!-2vUV<5 +zee$^HnQyYmI4|ASmC;g>OFR42bm;=4eDYe(&0op`3XQ9!lr@?o^ok-A2DjT1Y01? +z(4fjZr>rj!{sNSrI=y5IF(xNA0$O)JwLFPNp_*6(9SLG)n2>|*dsGYyHwKa`V0`Z- +z7BMGxGq!7)xxu@pJCO4ECg56`$lKif4V@iY(4aQw}d1XJK!= +ztGoI9)cKFF$#gq20ug9hvr)ZWi4bzE0!Jg$_eI8ofMLf3pQlC~xR(Js8QCE+xz4xc +zSz3uq9gT{fN^vi4S6=smU$MJKl@t~Ecy+fGhOmfhK*}RTVv;sgXZx< +z>D;(;EPE^Xr-S<$VyR~QD<}>HIGo`_$X5(QgjNH9>T-J57d3t5kaJAh;As9^cFPvi%WOBjQ4qYU(JO +ztM!~l4-x0WD{zx2lqc|=cT<$-DIw!mS>l!=qa7^s6WDm73+O7#3N3gg5uk=_QkJex +zZQ!7{_Hgq5vt)03LBH$@5;s$*VhSvm2Eo-L3*S2}utA43whk(nIE{}i%?@}cd?PX` +z!loxbx57$pw^%|n2Pga1fFJ+=hyRzEptBhXl=PAtsMPHoUw6NJeSO{9+G+z?zpjv& +zpfpCdBUkI{=-AGfy4u>?lPsU$0s3tvEbn+{ot>Rc4{)6u#eR}nMJlK5o@@8i`;rzQ6I7}wyedcX?tk}eF>|zix$K7Oq*Dj8%J(ypS2tqdH +zDcYU--I;VeUY|bWDST`vARtg0-ct!lp>w~xr$4ifN(QwbNdE5+*5EV7o{SXIt;$a6 +zYxqoYO^&Mpma8&XsiFVso-!_X-zgu>K#1*-Q$CuGgD_wh80NDF5#0nU`IZ7|Rcue* +zw{~~!8q4%I|K#zUM^}?<6WiQ*Kh9xO{07-)ww4fPZI4_(F#K2bR!Eq!|NWDlyL&4$ +z$4pXMTH4uTRPA3P%nG%0a_<8%_)>{!{4cVcb}uh4L95KKe#r)Y9Z3>hUEKn9zof5; +z-;TyPT6qlq$cOerQ4;m}z56gEhU0dN$?XdeC_{X!>q=PpM9TRuKmtae6htf&a4~qz +zd|WC*_L6|Dd)$9#-U+hG0zbzR#Pw0SPW~1!NxVlugwj +z##Na1`PBLT4;pfAWTt9n-bXT!a!Gv+;B~@m(9>V#DK6 +zhFyv5gQW+`c1{6J{ +z{oz3odjamR^f-JMdROb39&?hSm&BQ-ueN_Ai^mecapFqfY%gZa7GVJe>Z|g2*Evz5 +zH`KBs-0X;HhQ3KjN!rjs$S@P29Mc0yPZZ*k&$6I?_VD9h4EaxakULOm5VRcd{Y|6w +zb}o*yOXc6a*bX(mP3ljp|I-ur++~|DVgYZQDE77G#4kWM#@fRkGibcaa7dlq=>TE- +z(0yXvtzSaV=Q8=Vz$lv!1}Y!^=VTn)FB$~@8rV9zx~8h{njo!9edw8jHFk_Z6O&Ph +z!0eylODctsJJ0cZW)cG_FLZQtZgf`>;196ILhGCIkaaY46AnZFRf0j-5I1pK7c=ri +zBB!oGAm{$)^k9z)K*#j&vENF_99I1N`o`PbuisK5+2Y3XH7L!~oD%x?x#IVvxqYnv +zkTz#+@OSwyg2Q5q9Aur8pzV^s7QmB#Sm-xycqs{53kxG;N&ZSVD^!2Ywo!*=?HEf9`O_)jfh(*Ee}>eh#If+1-Jj- +zbe;}@`gMy@g-gY?$(UkG6Tv5)mXU8SpZ}(fMEze#4WsxM|B<$MBBpS;9Y_vhHGPEN +zBH}Bd9RUwF#n*;rc>veB4(|1b95GAgd7*&juNy9Wz0xVsbF9RdUk9sY5TErq}N3d3`zG2JV@VdyK +z(ZiMGaSb)~@d@uM608d;8wFo-m=U5M72G5rIJy2ax2mM|NkB4}3VktFRykgg&+`Ds +z2GNV|e+Z-{6N_&xxvRD_{GRSs;hYs~o;tVshG{UNFm_O(b?-@J`^_aR=U<+FW1zfn*?0x8dfqxKTW{qVlbsLvJNt0A +z6Xv4|dui(DVh};yI`#c}C==r^-&4gud|ivQO$WM#0<*BZCm>S)m@7ga1ZxiA#VFNt +z&Op`{2l*9Jd0**MDPCoeobZ2TkU{B{)l~<-(u)ebe%)#I9WM00RiliLkGER!B^iG3k +zQRLJR{VY_uHaRW17qB~n&sZi)=3JfE1fzNm_-Vi{p4+PKWWJ>C*3aaM8}^cl2PV{r +z=9+ObNc&#n-tuGQtWH&Ww6ZJtMF3R>)ifXZic55qYF# +z<`_u6N{Wn60Kcrv%C__^Yzuv@V6Qa)XKLIArT`PJFF?c{_3^#A(%W^B6%XT-?@FsR9LIS`sE?MwF3 +zjf6GqoaMU1&myuA^?nKNcbd@CTs7C2>c!IbAE)9!u5gqVlkh}gE^xPuz_70^Z-VhA +z16e0ll*45fjZZK6N|}gXPj0^S3W8T|CBfjyXbaG=A-+^C#fBktq_*jbXQjx(KVUX# +zh;}^VA`KISsSPD>2wV1LXV28U0ifb_QY(C`^FkhNm_~iJo~AlbWmXA78YxCvj`J*FU0cP*Sb9LTo3jOstN$SIrY)+5@5m-N(!w+8uxQ6y=U +zc*^kSkMe)X{C{VR|JwZjV>JJp{ol>={~5}NPh+q1qQSQSHf`5x|8yV3QTxw5jdpM-iKeiAM4MSx&^>r>Cm +zq&?N?OVoyJAHm(Dqe^!Mn9N(PZ&;U?mqD=Hx)1TR7)U24Cy-*Oi)uf#sUWM(8;+VC +zOGir+)X(K1M{LivTv*nZOuMyu8JZ3B7W4q7@$g0e$yFU1itxEz>%2~m0Ic^-I{@hR +zHAZjncVLnZy}Nn&aEs+Y=CCVq$9LW;y@V +z^)2}$O(3b4EV{u377*{}bJEQW@s|sNngHkEzRvaZmgap!u?EtGzA~7y}xFh^?5nsf6fvbxAPeMl_Q+(!-uv +zZBJi|I+ENovkZi#@gW)ft=#*oAAKvI_sf8na{VN1WaAmFCMzR9;`m?Q|7W%E|6%pJ +zLALtFG8`?V$^M1iv7bq+~Z`{1ODQ3~I$?+Mu}| +z24bxp9gQju3YaCQXeX$i54g)4hHHuy87wa?t$pJ5!J9&yI$*N*sY|I$Q0XY~KDhfJ +ze@wJg@BvE&bX5(pijE1Ndrn(h1*vZD#Bp}oT_7Om%j?)uS=-Fmcf#!=xT@z$XYt-4 +zSkwsdZGcQ*r9B>~z|WC4_SFyhj@1*$PW@_f;&&s9_&=R;On@C<-c$b>ukVNy$J#S8 +z68YU0U7@kV#fJ@Wje4wJ6;=dpwTfLVVC22fVp7jPOWL^7?oDZ|z$gS~b{in$pT+A7 +zkWIc}4R2xLhf%~RdMZB%qHngePYRSuzXvmB5&%RqTgm_E!%E50DllZD)BK)%M5(UL +z1r36Iz0gdX$ROoPD2e196_d}>`K%P(KgBD!m0256< +z;Mw+0MBQv8q@F-s&%A(~cd+PnQYp4{)jfp;{B!+b0BjnS~-PWsR*Yh_hK +zl%?+|qAI|B+f+^sBUch=k!JAyBbhK7)1xpWzer_*#RK0mEZ|XWRq1*Q7vKtdjE~V> +zbT1P`@ss*F(xY2+d7v8%^m3n7}z@lpxR0`upNZ2NO +zJ7^BtQn)@Gv1tbjGOo&#xx0pUCW1F|F1f%?eIC8KpsXS*ui8cqwT}DaR&w7PF`huL +zJ0|nwRb~@8w($6qjI{Myq|E`ArgyK|uc%}pv*_NQ?H%?Ep={kncT44BETwsUfkD{uftym<==+Ry_Ee>I&iLO2St`OrsI??< +zc~VyzONqzG>5|vJpcHRRM>7z6Pxzz%U@b3mYRJp@a24(7uXr5NMU<+QMMs^>$#jww +zSjHbNr&J)`u<^T;)$V=12Jqk%>uU?wYLyj2zkY{v7H2m{Oi)Zwior+F0k7;oOjHAs +z`&b+8Y?BUPEtCWiZ!S}l2j62)3PaGOdG`jcN@i4@7G5&#^t~mhG{Js5` +zIKEzBG?>e_Dx|=mB$5$kOxz~CQWUGw6eu1{ +z7;LFgPP}|SHO9$le|}mgq5DGcPGm#$`F6bX;anj#CnY;XA^fVcjoy(jbF4NQt?=aF +ztwYlG6#ZNdSftxCnvAmy9VGXuZe^P&LnbvdyVyp}{NC?wD(f6|2JQ2!ExQ%l9d008 +zL@%k2ZsnUXM1t!eaga~o7Qs6`g*xpUItP4}Uz3{Wnup~;1^+s*-{XPN6y)rMRYR`o +zc+SGxj7HluTD`#|`er@InJBwp9MVE*z4!F|5oO+ellsp`c7FF)b4K-36?XZxKd(~i +zOk>O~EL-m=JN1mVs(#^2Jsi-+k<&NZRT+MFA4<$SnE{RrNI5!RC2=S&x+cdw-A=~S +z@(U!&Hg*i(u?Q>Ha?QDk8=7H4^Yn+tJ-BSRw>VoHI9e%>C+ge8A0uz4A0&u*j0xli +z4IV`5&a~Od%(@jnXc}jF3%`(6Y0LPvxLA_oJI8j)x5P8$z>`9!4Qv{kwO#IUOa#Q; +z00jjW=G{Eg_-WV0Y4Rw|qs^1Lj2decDXH&@tVaOP#$UAzIG5 +zK78|%8x+^A%DFVab(O$!rV7kr*ZcayBvmtVsAG(`)jO&{g@&|fftdIu-ucjDWpuzT +zk?Oeu!ifmn7|NESiI)G;R{4kQl+WB;6otk4qUbJ0pE|do(FVxaMEtlJY1)m)B +z9lIrwt6zZc``wK@QR=1wpo<9%<|Lxm)k9W$MNK@S;` +z8XresxlEDPLj-pf4CpMtB-Va8IukV`fh11-orsCYUh7H6{Z!Ud{>qqq$8@t#re1`7 +zux^;1)Mt7H5HTn8ZpC3CsA87~yqJ>E=C1elHc-}WYbVQZc7(;Em9fF&!s6x>S-j-YD)qci8NbBEh5r$^gmAO`-!wBS21(Z1fU`SbxorUwmyx!k$)JZ*-f +z(Tn_LYz7mG#~Xp25!D8{e&l?Ah{TdL_yv<~E}hKftf1|j3z)v{39+O2f;n}N%ojY5 +z?N`p3N!TZQk9~)di4pV$)moR%y?8(lSJ7+FlS|+R1i5EUPa2(qXTV6|-0+Va8~*|{ +z5^(1g>aUJw*RF4;ORHIa-&$&So7*j7^T|D^LZyQ~tDO0E)`k^V1*HAKt^dUW@yQ0i +zf@rZriO4vJ>1b*=Wb;aaS55))CNk_p%SHs5VL`7a;XxYdt_E9IWBh@l6iN78EAF=LO^Lwt+x9n5g-wKK7JW;BWSyzYdgiEN=g*Lv~e9 +zH-X07IjO=%^M#Ce_pz;yBE`8wG# +z3pKk!rr-6lo9M%75FC@iVIr_oz#?nuO}*axj{>1D*@N(UFp5SZoFMLyx`ADV@h7tp +z?YGo(zRK*q@}NqQ7L%^I9LJy+of&d@2hUWLUK+AFx?^_kA%ddzqW8%1yq=AzlV$~l +zk1LE40$-}krlK9(lfd0^a7agrqn)yz{Xq}hyfp8Y!WrD_?e|_zxE?hkedqWUv0(K~ +z{$&kfkl)mayyE07XL8O5cXW%`^~MD;(sLRi=UTPX3xOE9%0kdVsfM`f|5&IyEB!bB +zzU+Tf-G3y7)q*Y1o=qKH{Cq=xLE_McL(&OeM(#$h)2DInElk;7x6a>eN7aQV+$7gG +zd;e7TA0~Bkg?Wxkx0LrDKzXkd;zrwl_|LEDo9hP7wGV&?@ie9-ZF`W=+`qQv1BMX2 +zhj4rwN{}pi0K`^Oh;P#d6G7}|##-PeNEdYG54?^LqRIr?nZI)cvoZ2#=78HN$05eB +zo^e(infwa8ylwVB25@sOn2>g^+diFe@*)S)15X%4iQTJ6*M`4+bd&hLVEAnd--6ycQ;w6bxEA_x5gH5p4dMoiufNz@M0wY$2Q`Blm4}# +z`Ztt#nCyN*0?cv#A=$s=9_$}B{tq+muZl(ZXC6iV;ld0DSqK0X?7czAfQ7yQ0|9373q +zZEkJ#^6_yQiu;#>aP(o~h-^_&QMu7ZB?tvT;5J=TFbINjJql#YJ~8h?BFbKXj3F&* +z0tkSAnKC#i6RV%D0!S(Y%c%)7Q=;7$T;%_iyoumF&J&z*oV)#cv%J4)5#Zdqy2Z&y +zSy(y`biheq5qO+7zliySaXE(TO_F|3U6_Q7)M^s275+tEc{sz9oKdo`f2fX*j2sfUQTV%?WlUk!Y}LU^>H2;ceUW&w~1arb9FddeK$=fsXoxoogSz +zO`vtfC3hBOolhqEJ>6O^G&RJz=Q+2b7tvH_Tpmd$3JHJg7b$+Gcu|=L@LRQUv{yfx +zehWBnOdY^c8t)w@vOlVbzVo4CCs7$rf?t$F;04QZW__aj0cN>PDOE{$v4RNtEGdrg +zP=Dw-!iz2`=p`~goR6>)_KA$ugP}MLG_)*Ya1fwtrwTr)!#{kRA%{rx7xaa4eky#E +zn*VOH_DkiZZ0GaS{i^T1l1cXEvE-*F@8ecGS}*b>06_+N2a^_>sJcZ}J0gT#3|Z+! +zyU%rpj39yKLDW*cA)*iK7?Z%wQzwAL<>{2&PawF4-eby()dFXhLS9brvAy)gz^WvO +z$3Sm4aZq_ZuJ7nk|B+ANcW#BU_votZp#9Ixg9}DrWnIN`%5s6UX7QVQF!PyqEQ#Yr +zHP`l}@z_jD7E4MWMhjU$s*%U-{niM9&_IYqEili|)^jgNfo0)SIe*I}p&v77hL@1> +zIn|Ug8RMs25{B?&&LF4g(+yR6AKh?SBcT;LCzMR$17H0LpZZu#9|Q{c1Jm&@f(mfr +zgCOyD*P8Ty7X%G$K{0Ez%bL(;NX=-h@DvA3+zY&>)GbDb?pBuW-U7!>Z{U^1t=382 +zaNLL$=(D@hN?6qDNG4GazJfUC{so9+#_jG#d#_oclLwB8m+inRWbWq^G!$80pXyfH +zK=>N_AnNn_8yTe+otw= +z;<*+TpC`Pq8Knu00Nzh`H-YOU-$E(S^TUp4B>3E?`yp{53jC!~|DL8h(g|FZ;su|3r^-2B7WR0srGA(^WX9&O7A`mA$Y2U5#=cmUrm56JzHadB +z#9lzG$Ya;*`o`ClhCfI>82j+m?8W?bJCCG^#(SMVXESWdk1X5T*Nh<{$Fe$D9y$OS +z{XD{$0VFm|0m10QO%7+jM|t`uFXn%ye}4M(JU1Kz7C`e_3zP`DV3DHAHbONGG! +zNMO&S9&EbeII2jNtyr@1LVrn)jwJ44mVxXu-xu&+>bGPeB4_5l5iD89ukXo~8R3_+ +z-f6_fxOA@eD&jesr{F5`iPe@Bd8rFuMoso#OmRm~q8a+6@ClQaJW#~kf^l@y9b8 +zpqn-@qkm2(9>{G9UhKwaFi65R=1UzprOF02bt5srPTZ}ZLQuRIf@3TP9`J@K_peXW +z5R +z%8sl=G9(P#wv3+d2;$#XdV$jK?PBQa*~fdUBFZond>qTm$a1DnwB(QR^(Fi8N3#K_ +zTv_NMMh}KNNwv`Q5MkJv?H9!mCBdtbGKdsKq}tofQ(kFm)JT_zcrk&EvyV +zHzLyP{+z;LJy9P*iA;Rxp0D}=&@|{~1J$cugk~TwsVC7pkq$T_Q*2-&lqozUPOD4h +z1bRVt3zHg{nY9^NDNrQ@u1zajDQBiTNbbS>YSbq^9?BcCu3)^n=%PI{5`&ZwAZzRs +zGE*#ixuAddIOP>_J~#77Nh%TZA}XN$^&@Tg3Uq;OmqDe~ii`&@K>YWCmx3*LKdZm~HZ!; +zg409hV{@owf*ypJ*?j%pQ%(Fx=6V)J+x +z?#bBUkMly5j^E8zlF@Nd@A&4D%vZy2$aWDs;~zMZ^^6Ld6t4ECBMjWrmtoCFKofog +z<|Cn2W3NPXy@zX=$pmJSjU#V^Yk_GZ%^ovCPNH4A5yn%$8sdd4=|E@1QJJ;QqCbmg +zt@khBMYm3pSdC5z6?nnq><=;+qU2E|5SX+K2?0yMTQeBA^OcHU0Pj4dB!X~tma5Ww +z&*Jv2-@};$sLt +zD-x2b!qVLPYHocA55b$dGDDdE)ff;5fyal^(l34okEthdsVlJ!>m{&72URk@TXxdBH)-mFlw@^yeJ|liKpjd=??IKN>$qfrI48DAV>G-4=4YK{gl?>tpID^VQU`HDY;bzg4HlnV0!=*YqY9$Sd*3 +z-37VC590LtpZ8REc4_<(qMi%c-mMI6=?fFTC>aPfUVMB1Q=i@zpe&pY-^Wx0+1HSW +zfIUv^-w(_X8J08_2jo3Z0VK7QmO{{_^A1Qn&RxmPSN}R$hTEyBI5@st84&R;7Ujvk +z+8|66Kq4w{B<1)DcgyJ9ivUl4QBd$b!=f?IZ4kJ)hL_{F{70gTXzWTqtr5wkbAwKC? +z79b=r+NnZS1lL76dg2EWj*s-y_EF9qm9cdG05kDq%eZF;Wiy=MpQ4c5t4mAYQ8&UL +zO8sJ-qR29_4bWrXMn;X7&_#)&jxS0?b*9K_^d}aC4}^BqY~`*8Kv=6zfkho8^JY;j2C$sX +zGt?Ymax&S6(Kj-SNwvsZEKfh*QMUy-gaoqirdap|DkdwtSiL&B0eDGwbzy^UJ60z2 +zGYiaqLJ&7M)e&&yX)v4pZajfOeqP-x(tUyE%id+5$z!6D%zNy`+Zqqr3ULsz)w5*2 +zlJtGJ(vfm6`auTr54@BslCyK|JBE)J)fq~9%EE3P(_z3E=}pMhpqylR&rB=BupWj_ +zxkc4nuPAfJJfpR@0M6%EbtALPr91HtaZ@ZF0`7=OeFJs8fqu{;OyR*@CV9Tzd*kgk +zG6)!3)zR)*jpp)CpuMN?x~XM3$gdpmat=68?Lm@-7j8Yg7Hr0~B=RT^@j}f5{e)g@ +z`~U9QB6xdx>Q4j%*dkRm5=Z7M};i44XA2|O6O +z1>iV@ZzC%Z8U}SFwOAG7Elml#&yL&06|=*q$`Cjqsca1emC}%J_;0?@|IfG3{`)Vm +zxjFd$%UL+11_v>VJlM~W<3xi*euchg?4T~8!bPk>cCV%Hb!?7tbvY +z`uTBs>*Uh`qYvRDC=K;qJCc!%+3``%#L1)`jfVE$e?IHQpp9u*?7vqTIoMbRZQULC +zsjxiXwFr5%-?-Plx3QZootoM>TWE9lzCG;*X{ckq*Y|b5@yEq`kU>^U;$}6I8hMYO +zWJD(NJtF4jY&;ZWMai(kM>wNe?#x19Gj8j$vwy3TOvD|A)Y!5iw1HV_%jL}W-29ia +z?TU(}NsXbws?sf3_;;;AZ{z5Zreee`3@g)_Dc)WZwtCILN#pKBrci;DUPFBmcF-4K +zKJokahLONIk)zsLf}Q>?XX$yciYD|lLEMo^t$}SJrvUv^xcaJ+Wj5tfQ}lw=v{K5q +zT=#Pm!*t1kvop_D13x*m0#V;KW@5six(dz78f=jxYr@$6!M(B+rp}mp(|m@4xr*=d +z>H*~Kkh=(lW+PyDHyYKMb8YBY(*~^BN{35;>LsqU6JN?0tcYV{CUh8;~h +zvSJ^#Wwcu*XO=UtNyH$3xF_!)RwSa3e?R?(EoA*$n~hl5m%7h+h@uah>p@v} +zPXSaijE9UHWc?s(=dT187qz*+EXjE3{4)km$$u!mw-IUSWSRb9vD*s}yN)K371#Dn +zI;)OTlDn@P$4@&bPJe*L30ItUUS(pB#+@T1@y)`n*b#+;Yx1nk7z2YVWuNo6%nb(3 +zk;${eguEwCv2~DX<1PH7;~5oxJ$*0V +zez?>bP?JOMF}OVZ0C>`D-ZSMwr-Bt6jS)|*p~g=*{S>DDWli4Pt6$7!Zxp{ +zTAs@W9MIH{2VKbXbG5|3sc^BRbm)}oy#f23NNT$O9(D(SMIaZ1N6Xuhs7T$YM=xnrr5Io|UugJ2+vKYxjxCpW+SP4Q-Re +z8MMaKIG^gb1(#0``I9NIW)#6WIL$SOk9zJDdLFWdw18TpAh +z`KYlwhNtxW=BfH2rbsMXux0qgK`T+(Jj1>B`{}D%UU29h}FaU$ni4*T)2xFo{p$zy=G=?!}PU|d;s|>CU|n+ +zbSPZ)RbOTGMHU1q=m!!lD&)>8_bRXa&b2Bm9+fsZ!wuP2y;=s-)4*3^CbMAL7`~O&Bl(42g}#Q8~sSstX$h}eM$d<^CntDh}9=3+>3!sHajEVydFdK{4O~_kM@zi^_aBCY +zQIZmKBEX<#9fXf5HfgXU_6&Eu18#X=BwE$+G&1<4hS{hJV$o)e#jSn^92W-JN)m|+ +z>{c*LO4v!PXE!Qrc9Bt#{r+7H)r*!8w9XO>8y#MO3S6vkl|4pUp`fE6OTORNU1U5G +zoD%eOfs-f98bD0XXV2yPs*0O6Fz84@;^g!ZYZTU;d?ZeZQ)djo$UkCo+piba;6H~+ +zlId^Psfqabs$;#fR2!MfP#VfB-95js2@ZX01h&EA;}WygFb~|J*`~gbl+|OH>&H<5 +zzWZP}2u|i!oc$!P!YP}cIM88E2~C8#{#$t&ErFj2rJ3(XIn@xo$c}O@mHe3q*XD)q +zJI3Ef=E_?}^<9o-V7~$kzwua4C#;OXk_DuQot3_JY3~_`uYiWHVE$ba!c)4T%J}~PjLf3E;{M8DlQpql=Ql4s<3J@5Iw|$vC8J#TVsh> +z>Gg^Uf2f0;o?D&k{D(R+#y`J%iN7^p +z7$DnL`z5n(HbsK$6fsWfME7ub){l4WK=Ph*FmYtFkCJ@ChlSwCmnA#?bZI1y_pW?K(=Za<)!qhrNbt+c(S +z#O!tCXsA_RiD9N_lL%ubJ&3$FBvRaNv-fJZe#QXr0ByjiL>~=?Mt=fJqnv+pjYAn) +zd0HnJ8Qk5^rr8bH6BU9>(p+R}f;-0XSGfNSdH))gC4lSRKhnMn-myLPs7oqjkgVxr +z1iHRZssU!hvW_I;cT9aQEd&;_36^)Xtu<>VEj4Q!D7I90%Dk{F!dGPw+SK(c>G?pY +zQ&OyA3a>n&qb49t7ooBlfD+e+`$HEIiD)!!pRC2~*Y+Ab%_bTA;w?@X-UZ{0ZA5*i +zzhC3sLG!t1zV&6u;P?#KodZ?SbPEvW>5Gq?-cQMCed%SbJ%n$J$|RoJvhNHydh +z?c(by5N|Hl*VVV@>Btxp470>y@hh3-JGiH8)hU3BgsRRfTxm`m^XxNgO0v$V(=4#b +zX1~>3l?<>NQFs~%3#O&jU)cZRh^DvguiS&0^PbHm`Zc39{B~U=2O_Da?POUG(ZNjd +zVL9pWtk(y9`!(8HAwo4N{{2R2*c?xnwi2wK7{Gl7bi2?!-BOLv=*+w9S-Y+q^aPHb +zhPMOOW&Pp<)^37gWMv($DsERBb~(T|?OsN95gJ!s=Aq1FlImXQ+74YLMVQv%$aMkY +z9&KExSMpq2=Ib21epuw9((-J6yEE(fv*97E) +zXxr+liqGUm{jP9lS~kFeh)MS0aucLM%WE&8?`DrmGJA#1-^Q#!_i~?_zV!2r(`Xa4 +z{3wvmgMh5Q>0H6Z-T+)$@&oQ(;Y@`Zdnz@^#Jnlj)Pr68;_cUqgXDM+3dw}Xy=Igjq`Ub3 +zjpv7)pgor6pioDrG3_!}Xb@ia)G9xTx9`*WPNVh|DcpwZB6-#a;j@h`oUgX2hld*v +z1Z`m3c)84!l4E0<+GMO&k;1piD$WR+<+(@~rm +zfsxWXd8n+mlYuI0;!rugTQ7KzC +zt@5D|&Anxzu9K@1KRA@)BvGM2O(kOJKJnj${<878E&?UL4I{^zY$>l8E0{J`&4PqXE@QmT2a*9RS4a<8c(dWZ0-4vf2K(9DQt +zf0b*p(uUut``M|qSiP!JGd>=D;I-I{7QuIV!p&-OeAIM#B9Z8h*&j$4)4}sM8qMky +zN6mWXL!G1oP~QOY1>Tt8=W|PJ+FMzFS@fQas*NqRXlKLrzr^M8;~c?Jf?Xeie4{)&%57M0qn6aCwi! +zF+|Jbh^M|p?+LnRvi+9JW;i{b={ho#tZ#a0vrZ4x%ZH0wbp}V;x~lb;lh&#@&JHAZ +zF46knNCBE-1&!Db7z#phFerD7%(d#`8H|RzA8It`CU!{ux$QK%MxIkh76sBvmL~!}-Vt_9AV}=CaeQ#QY&JTe +zoyh@Rq0osO%q<1v?bA2*Pf@1`QzAtBZgtKhDIf0q( +z%xAW+&%1kyp4y+M_Hj)ReT_>N2V8^Z81IA99jCCI?afSgyJ`H7el)_vh9C{g2C!}w +zeaB1L6a}Dppg#M<0lu^@ebiR4IZt+b_fwm1Ug|N#LO(8V_&ZM0UD0l1bzb);sjlQZ +zi8KjCwkG(<(j!7)oVSU-&f}Z|w(sv>4`$SdRL5{2hWc$xyU&+Bi8X(*Z+ms9Oz)eL +zg?*r%AJLS6x$A#gIpagUgffVBU%vh8JeXu*w#@eILGeR?w{91kruFpYh6J2>fZ3wH +zE)<@{<0f!@>dWJGSWLXMT`F?HLXoVRn-uadD1V+}%8(pc0{RwPbtzE9t +zS$)$>rq=F~utNB&DbrcOC+M9XpSY%9g3gMW!Ch@cKYt_R_1F9uuXGrV7uMoV^pSYA +zuv5yMx=Oa#*MxfU1hLV!LwoKfZcl#8g5N&EDY~3oIk+YTt}x2R^X~roiJeri*sAo< +zd@rj@Xy05XyAjtFrWpeRG?!1s!)HsyNeGi{`u~Pr#AXc$0(DWsni~!c|!^o +z<*CxLS9%{_K1ML8kpGQY-L-n%u%<%Ur`Cn25+UsBP5A_@yg}8jQQrv +zFUPu4`-XmgvV@4uAwG~jvE?GVY~mnRFPqo?yDCf>_0P3@*iE1uK8UFlMHRqyzlP{$ +zAAFLCi$%CT7Suu*Veck~1&eiD)@(`$JRA~7Jb9PR4!3@MXO8%`Zj{^qQ1Q5=j_T*y +z+Jugk2G=`abSw;J%m6H=ZmHI+2-M`WC{%vhHdKCY`y5sbEG9qd8!B^7DD0s`c+6fq +zaww$daj3n4g&X9_JGDbQgg2q|VcgQkutU{E+@G!uhIVH=M)?smIbb!Z;5pyoAt%B! +zjId#7u0PvREbyRc1_+|VBrFksmzK{9V8FB>&jzBaioLl~RyY??rH47uRBB?X%HX3l +zc8Ai87!uULsUQWC>Sj-p^3#6mx$0LgJ$@Tinp}U|C68c->;hyDTuE8nU+zk!j5^Lh +zggu~Es5MQHhep*BK#;Ae<+5@ecuF*2(6B!wW;tb2vK;JoHeqGhT6#vn|J8!{g3@>2 +zIKm{X!&jvhjH2!wkgG;dAsFq39lr^X&nca_TZR%F=t>F%6 +zv#QmquO1vY80JQLEGZ5V1BH$5p{@YAp0%fO6T;cA*SCXgJpI0r;2Jp$S!M;iwX;)5 +z{mmW<{YmYlknWv7HHJlyP}N6ggegj3j23jSZF@iRlf=abXu=*DJ#}U_Q<>F`S63~i +zdhTy1LbUO-zD=8?txn-fo?+8PP5U$Nz9!(}QotsYOhBEqW`mq +z`DN8lvSvhFE#d1oG~+b1Q&J7Mt;N)g@sBADnI>le#G4di9b)8SWSGHky>CbQL04Oc +z!}lwK9!_VjuEIVdf>oy!bYZe^;=d5a1B!yaV}~OqbKfR|Y2HXqx_m9&*^#|v>!HF& +zIG=~4OFexq;1PlC@nUQTxl +zi50mN=yms=M&ptit>Q$K3q8!cq1Y>~uH +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 +zW?PRly|(noF8X0L_Tr*@XolVL3Brt#7^&J +z9uZ#1TXPdW){^X~uAtf;TMLcd*I|kcuNO6;u{bz{4F!kL+wVlP$RbW#_XI?@zjO%( +zvLuY2MetWTjDL?tVWLKF>^}x}r-w&WxB?mAbs|b@B}f2gV;fx>rms5syEyCf?;i=vM*Xq>L%xdR|1Mv}#K`h5`6@hf +z>jl;`cb^AX&xN7MDzO-p$zbSSr#VQi@05mym$5*V;{oIeEla0O@(xI?@1ZyE!5ZLr +z6fWUuHB)w`wCm^z0s`y()WPnmNUw*}lZGlEgbhGqUeczV!8BjA~UM2oirprCQ +zg_bnVv_+uz4C9vk>o@jt!6>%SQX3_db}w2yt}gnI@2`AQ*5TLAl0+SDaNe#@_7DD~ +zoW0h^AX!dW+|D8=%GhRhJ&yuZ+Ktw +zj@7*=oqCsSwOX0vi4B+RiSuTSXhZ{NnS@;M8d2xFm~Ch_uC>mJx*~UgkIbqKlW|d= +z5zLE&9W%{FS&aH~i!0ON4U5yjkJzx}S2+F2#a+hG8a+DyS&31x%q(B>K`&fxD2CGiXCN +znp&2Lg^G9L>U2#T!p*|#rg_;E7>x$V1gg@Q3dY*HqEO?t52VxJIea5Xc3?c3P%F5H +zSq94MAFK|F0%%5=^qrZHr=Y|$H($I87ZI9kJL~@_Xfn`p;l3u;YRc-b7F}%X*A;T=$uV$z$@STuZ_8|CfZ%bI0poa2_P@ap&ibyCK$Fs{9y*E90l#614;KF)VG>3O2C;kFHH6n97?k)#iYN(}% +z63}2Ie($z{CX~MJfozvG`;SGU3b1GGi14l%Tv?dcJ-oi3O8bQqUz`kJ(qg+=Y^|gu +zBx0l8G;&pAiWSWPF~dm?(L9BBKG-|kM|HS2e{oW|@DRldE9hg;p?}pRa1I^!O|%8~ +zF4m-I;OT`E70v}>Nj_`+jL&Yk$ZbEG>_^O*g-<=xC$9w-EJwSo#Lb*H=QgaqVZwzR +zx$nIyv}}COw||io`yI%7SksmO#v_)^cAIJ_LTeE%OJq4oTz!+2wxbOBerMRyV@GP` +zH)ZA76f#Y&b74c`v +zYDE*|%$*G^*~P{5SV8sb`W6YHv~m&J4&8Wfm`D2%MRhE{6tsuevw16?R^;P$TR1LH +zyvzHb#==lx>H3X{Z8-W|D<2m5N|Fb6a0|zZ&S^rht0%~XHhZG0DZqtT46KW8iPWfR +zrl{!{j+_i!Iu5N#bF1YFid1T>OeJAH`ZqTmT(BOVr)@yf^UiXnoX=ty{+tc#R +zvG42t_k4}q)@CA-C-YYCf$pbM(W3;_1sP_JwVZb*17%vodI +zkwQ3HIlyqpcjK(2{hdcC&4r2P>+_x2Y-dlVd0Zahh(PT!RSc%9w|0j;jdqs^1AUVO +zn2ygP0ftd8bjbkmz0^$sBh`x3v^inwMW{|=7-x?|cLQ{M#I9*f&U5Q$`e1Dzg)XYc +z*U(PuIM8Jnmuu3lj(E&$G{WvDq|kFO`F(n|jV-V6D8#~U^U1Q*;+Ba@tu#nVWhb33 +z=QlUYN_sth5^xPI8~{wLh-j8WsONEYNiWi^`G?&}Tl(xLg_aPcp%r(an(b6emFJ*y +zQXOkT%B-Gfr*|Sp-6p*@2beoHrj2<@G>(+52K29J1`c~z23l#R3s>H14H@|{n4@Z=)DQWJ)&!Yj;N$&82k|lV2a?{OMY5)~Dl;%SV<$BRLU+cVYLJ3e`_uN2pXJ +z*_>z;CmFY{%BmV~5>z|9dB-FeO%ZpSXYZ3`1;(mlROd`sjdt!EWy^sh^j_>tDMYy5 +z6vTGm)~9$+rA-GpAw<~MWXuFr>M1>MK|d=6$FkHhw0jl4+$8csvl4PRcTmaG4QGH6jRJn2z +zQsU;@DfFeq6<~XnI%nVJk|3xIllMZ))Y00KbuD)eRH_wE+M#WlsA@5@0LqR2z8hO(_gr3|+0p(|< +zViskC;hB6)jbO}im%?M^Cvz)z_?>vQpmFd*_1&P{z$SOE*pUtgoF4W-6t`ie4sC*B +zb%e{fh11We{m+p~-Qh1jRV$L()J9>5Gbl_sObHNH)2Grm;0!3VW-HRHE@>a?!ZwLA +zRKe3?c?dFL4aE8>vf3KGn-b?`K&StlgKHi?a+)<4nUk-27C4HkvEIE%xCI;lpA79$%eOpcaUaw3#>~WK(InFTY%QFQ*!Q_{a74Rd64sxI!om1wodI!s +zE_8}xVEJt9<~s}nvuZ)!nXXCHXCu!lwpZ)^4xIT9VySrS!IxEBuZ3KrhM{(6kLH@$ +zC^eGZc>AA( +z0CvC}^5`oR#9`Rv&sBz3rQHX|4k)JrX#9>}?B0WD1DCn7(Xi2*f)v!cPRJR)!lR#g=en=uyEr+@B%fy&K7$yyLf$RfrN)f|IgLIbb-lEIYY4Bl)?8hsY3| +zpiR>dmF)aFx|h+S*mO;P5DlaysrQ0sfHiMDLykaHi9-Vpv6nR+P=?7h4w +zy*IF9%$NNJ2;_7lcmr9$+N8(>p-byK(=Fc({yYhpc)+$Pb!ZS;(__diTvP}oMVZ36 +zEhiv8?WycwW`6p5`Rv5yG;i)4K}BPrSozb&M3j3aSljX_|LEo +z%Lle!LIdjb$eU_)UJ)E8X^10eM=`yMna+Yq;JFP^RW#1po`u{x~f9q +zVL41H<@E_+DI}joZQ;7Rwz18HK!i&1hBHiviYQB?s}Y_143K+TONe@M!;%6iT~an= +zW1m5|?2?z?mJv_j3v^NXnnF3)pw)fv*sen;SWI+XYx3$+9<5R{DI&SJ{4&|6cd$~* +zpxWbOO@y5+DKc?8*4!2hrqkA(1^K9Yp4=8jLjmkm2INc*xtkcwcIorE6SQ~vnAgl9 +z89lsjTAT4iUJ_xDwZ_*X>kp5so1hfU24&e?W*JiAwv#GW6+sCNAq2f%Rps`1b$1K@ +zu+s6F!3%+9Aj&l2EngGM5^Sdyjjlc(3x0ag`1@K|e{=fvBq_{^VQC~Cg>Ez{xmM?- +zlTUkXa22tJw^#)QONTBfo&w3!7@Qw39N?%1Et8RT1`rnfalXTRk}?bPfQoC+rQ4mk +zNclmC!qEo1s)MufMLbqyW0d|2bODi76cw^>UeyM30NirjMlSbm5*7kEiZkI=%aM9^ +z%1wbj{jDaZ-!+s0JLol$Q~+s+jnBoIF0@M#Gju#r=V^7W-+%+WD!m&9>pCryXhTtL;fYm;ysPt=uyH0YsT%e|V|l +zLo^TgJaOl%k}iVxh$3}F&>*iYFMWoFcgNo5Xvn@g5*yr8!5c-y9qUCdH=CCB9y^7N +zSZJ6Q62;5L+t8&zil +zxyAgPB_8mD?Z%#bq|Osa7{41Nr4GIK=#E>OaB}7oUvKflUL3bYhh^T^8ksZ}br#DO +zdicQ2?xfPqwRI4EJgP2m$|w+{j%ZDq;vmL2RDLs4XoAt)6tmxr*+T72bXJaU#MwVu +zuH%9%QAic$x_36gMRe|ckhmcA?=vQB^#7DG`CVIBMOM$uQ2+0u!y?vpmUIe+_K?cL +z`iA!0+`p^g{`z1f`t>d(q!cbMFWn!tbAPqP%+5l~2q~1y&P2-!@ePntybgAzF6u<| +zv<%GbOuzCokY8Fx7AAJ4Uw{3ouKOSB*m7|E%eJCJ6>)1thIegz@1Hw*p~hFRk4334 +zz%O6mfM2fpWFeB#06%`cxej06+ZY-o3CS0e&L@9jCW!iW+Y&CHJ-#xzWg#DPxsndV +zZFl{Q@(#z48m7w3zN$#(n2zf0Lc^-{rG>oh@^#Ygeu21`fq>gIe{f1@H3QlG3~G-38)`sF?+S&u6J +zAQtqUg+Yn`4r1;S&?icre=*SaTm&l#)rkGH&(-08>^v!sd|Fkw73YLo6;qz)zFcO>+k5#*)D|XyWCcr9K4$N@;-h_?$zaEAf@!nO +znX&Pz!LVz83?!#IoeJUZ{o^61s5Pu4@6Qk-t*ANiACvf^h-XjDC@sH*)F}g-F!XPh +zvLpF)pH0pdHe5zPAGcOhvAz=@ypgQZA{J{AAP-!sUhE>^GG}g1&Y6BUBQT*OU0D{H +z=U7W?#Pmacsew17c3>IFrP5V8?~oN)jRSBZl>d_d+(3DB|L? +z!#|=KO_{|JP-f-_#0lreL*kR*tduC?MD!)_=$ffR~J)p5WAdgwk&UEy&D#q*M$;E{eVc><>6a%drLByi(S5?N$BiKi!gBw +zJNkZppbP)(fw)*f=Gz11*|t)_X5g0nClG#i{kAEk=%Di4783NwZ#j0t^C5$%Ne0bp +z%!t0nM5+~UM?(q^K9l)j5p8+)Z6>A-E^@l?sJzoQsennL{cgSxNt-Nk*qHiy`jhK} +zqGIt-_Gf?Xw%vF$xu|7(FF&bd7uBy-%Zg)4BAcZB@U2IR*Dpl_K3)C?m|}o{#b4#c +z|1)4Paxnf2Voa*3ThI5Pc(JWKS40`emp3$T#7g-?fz$J7Q&^?n*05XI@+;Pme#F2R +zAKrYpV`6Fvk+f6(XrqPnf<3l@iHqxe$dSXnak2cU+G8YxFSB*wxY|SY$L!%jfyaZp +z)A?m(QtJptv2>mG=TuC(nc`x}tG%rUiz^X&;@P3c+hiT+2UO~DjbLhc(rNf+S9U(c +znHSG3JbcZUUbpA1-r3w&&E5dFz-PAR+uer)7J5OWx53Pt@;Vg_mjn+J>YGo(8=q5e +z;|Se2&Sn!&Oqoq(J9&IM +zy5963j4ycXjPKQXd97*)bbXg>zU(ht73d9c?`FbHM}d}o!--)7fQmd*m+fJtf^UY8 +z3#BZX?~CrO6tDrD5Q)VG>=-EtqT3{^Z77b5pd%3Ei*DS9ltC%LVZ)>dzxNTYB8}HD +zsiPSldAfZDA_?q$)M8TT~ywX4qjT%Bn#!&-oEj9E{KS +zpF4X3(u4F5uVGfiE%el|`f?8@a3pCu`vy)codk}z(I;yDH*maU)?{vddhcRh+YRLA +zw@Ko$#O9)jy$e%B#+Z9E +zs>}gnH^!I1ExwMA)Vmo<{=q}4BKOY8vUI34cXbMdF-nF@eYq2ZHsLfx&+w}>d94}> +zX0E}H6P1UHJlj*TsIM5gnzA)YwG>$&VUUtC0$%Gzpn4`rbg#Gd?U5!qu}i(PaMQtx +zD+yNImf54E77iEPIdFKB0K^;16N}}=JnV{NKPr}+0c3G2%>51L%5&0F(|)!srZj{O+klu +zjQ!BR!cgCjr-(4~?)EbJ{?N5kTf_EcOqwL469Y$2ZCnbvz_H16V7-DuVt#K)ce*V% +zitJ*M*rC+54pJz1FW}3ud1|MKl}fPRbOc}B-NdxO2&N)MeKrRmMy`;KP8VL`VBU!@ +zchO0;ODn4{g~pjeN_4n@e)~IUbyS57_OZkPnd~$IWtJ(oGwE2f5NAqgaiuoeGht0om?|D&wLL9h~(!&WBv&c +zXPHNdadf~rr)Sw&sAdBjWAKbgRNVfo6CT1ZpzZoJIk4|`#DsOvZ+C9n=3`aa?kW(G +z#QU{-6h9tAW6f2O0KS+j{EO0VNZ1l|Qyk%@r-xrTbI{C2n`a8XM8tPk{}^1DN_?2B +zcR6||+Mmv!UoBc_hZqlg_Kb_f+QnQnH0I+EV!iW*)dZELHMY(QnG(y6D+$6?d8*umr|6|WLuan2iQC|pjxQGmGwz@X%QY8n`9}6|TBZaFm9Nm{Va(xn>6}fls +z8&1%QO%ANkZHYp`5owJjS0$cusk|zcuj_)2G|qR6v)Z>57mB{F_M-Pbk>*FvALi7R +zm#Z*j3&bue_{q}TG_6R+QgoNX=*&Z=3*UfV1TeN|dJ-K7l+)sggEN*# +zMXF!Dma|#}X!x< +zD`anS$$?H#+^K&GYxC=e6i3uI+w-5^LYb3cO15w?jz~j?)(udaURi5VvwW6I(k&s! +z^)sb+$Jtf?3J(rYP!TDWA$Q`glI377#9=Y^sYdd*i<)vziYw1Xjt%394qNnq)_CL+ +zOU9q#Gkrvk~?Lt%5)Ej>quLUjC-dBeJRbp +ztB?^CN4qJ`zPn60Z;O&=1>MXZ)2U(3r2UCw{-_4EEWV$jIMqSPqr)YEhr6tDP9*x$ +zCOFL%z1rfC8x3JEX*f`FS7M!oHC9QsLhlQ&XA$bq=Ztt0n2Rd;#7q)m$w_TDp^n6| +zLS$)hcF0$JH6usic`d)?+E1oWHRk(5q1VVm5%=DdX(RIz({A#aY}4DqxJ|`oSj8Kn +z7Yd9XOEWg?R|F9|;C9@{Vc%wJ_eN_TSRujYkx-bhXzSBi+D%j5`F!rZ>YMZ?A3mZI +zKt-X5i!fk`%xHR$q0@QVsI;-zYNR7xM=Jw{GatZBb`TYxHkiAkpap1uVO4Nc8;F!8oyu5ja%VHYpXNxo +zr0Y_H%r^C;kz>Xew~4Lk`6k5%Cs486s{|ghd)WZpu&C?{rtAxA>7a5`<&#n!gY@+- +zuzO~(bzncbq3o>6pkPx`wD1*skLmIqG>@7(a95jLWhJ3)EdgO2*G(K^9)7QPbseiW +zYFb8vQTk2@cw&>j)Udy45;Y#!(t%&5W4pqFNqT;PzpqU4A7XdLe~R7zZHhtMQrFm! +zPTADJ!Gwr~ft^mw(A3z(fryEbflkQU!rD&JMpxgE4rJ(Ls&A+uDo7`2>R>NtXeVTC +zX=80=Xyrh}PA6{VU}$G!ZK3O6NMxjIVQ=_f(h981|9UvnVY;+aaZ8=>`)2%l*xgA> +zvAbx3RzJk@Xg^#VTw8OuTLSn5GGZ9qQ9buzhF)wK|5n4bRwTZT<>!08h92Ec1+!*q>R-2n#rz +z!gU`{Sog+6&7OJJR-Ad%Apc`XRoyB7JvwGXQ-5>%H$I`McIAjxG6075>HTG5wx_WE +zX^4umC9veM-@e#e8CRGwro47Fv7`@<>W~Jn8$f-0bK4Z18t%!()%RN!^BHiT +zInd8RMc=+Je?ZN)b(jwo?P}USAVD)GNQaxxxE;rsx6AOk{c)A3az8xMswWBj@wutd +z1ynNcG8V}IzDe~R3Ff~{PA=JXw$~EUJ9r`#4cUrDjuQc71B}}!~@kd?;QiE +zz|rL@X>okp*HYIv8MhP2`M(C!b!*@SJB2rH$c{?wH&rW(!HayYvtbg>1W@~@U!O|E +zfUU^ewDY}?-#^V*NGn-|i-@OZQ0<*t$S%vnD-CoJLiZ03cqzB4H#MJF6Jeq5ES`Mg +z;4li1Vo+4Hds^r^>}ITyp;*?;9NHQ{A$k{9||i*I>2o(RJ(PCEMC2L4uoY-lR@Ae +zP9Yc%H$v$V;p1YIJ?r%*_p)jmWtGlDnL^MO_!I+zVvk@41SuDAoC+Bqk-(s=J~w*~ +zf?O6w`_{AQ0pBzUce^xZyFp1_)IoxhlFx|ofzINt)i2nI!~-^#8^QcQtQj&uY@S71QC9J>{v +zu5GcV9;7iJ(2n4l_HvSE6ix(ce-wTc&Zhnd;gE6AG!57F6tquFHwcRppM{EmS!`e! +zQ!DMuNThLscd$0+bQ*==V~t%Ax!}D#36vbUc!2Tuey?zfPStz3%PP&a`#nV{IgzWq +zp9xi(fQXv9N>^!mXhh2FEL#O{3iDjDpBfj+Y31YhwD4mhugFkuA!k3?bZeZ!^<_j)6VYXZT?>($;bq_ +zkw6YgmF_iEPADnoz0Qd!#*@f^)2Fg*_^F8kefq;gsAb{cXnlRR1_}(dlFklTdq$TX +z;&bh5i+ZO--nqu>cMLK~gPS}Sb%FQmY1WlhJz*07LN!p#ib5{Kk_z%x+l?A6gZi|K +z*w68BP>E;3aFWYOihUs#gsb^TD9|g9DpCP1va1cCqLF?=&vVa!m`~v7A3souNweGK +zNqnwJWCQY^Go#_cc#=Ug9up>M^!O}y{vaqDSzAKl-DfTW796d9V+_oU56x{5^$aR| +zlD8|?lQ)-Ft#6QOEntbG;h?PfPk)^8>{IotZjCno8Ziw|1gKW_=VO2q^*kBr3&^B^ +zWZs0j4aEY4y9QrEA@ZW= +zo?9Nh09T;=meC)SG~=XAf})H5hgtf9R099hXQCWUtwk%uJVJ^1m#8+;aKryip1t2R_913+YT?b)lC2w^hr#D8Os3gNpo8d=*N7+w*Lp4#R3kXdA +zs-x}?pdNI>_HN!<%0zs{vz9N7LVW9NwU!+Z7c~wIe4Nsi3RrcdSd*6y&=cXV@`M?b +zCmH1J)F%h%l~t(%=q$Y^O!^{;q}^dtz&2ygQferx&S53u0R~1HaADat3%r8&S{YA9 +z!YwtVowpdz*XlDscRUsxir2}xBBv)|>c&(SM{K%BovqIO$iXKT?6Xm)UF#*D0dBLjm!6mJfm9#dFHI$9X~_WZDicZl +zQWm;j0NndEsVC5WExQnt7_P-H?|(t}yD=a*tKep|YfuOj2D$M!VgP7j;mn+#ak7M) +zzX^x9L@&+{=JS|@IXss(SV11PJ%??vHnv$vY%8~c^ws2G|4a-(!k^1}#54=p8UOOU +zaGWi#Z;Yi+mdO-vWu=ss+2V$xLQ_oFCU@V|YY9Ms2FPA*fRb?JH^=TAG_DqM!;0(a +zT)ika!1P8xgSZwUQjh#VUEMTtCM1*M%RC8#+5$%hy%3Ffw>-iPh<)-F +z1X`Hvic$!cv%4I4PMFL*;G4-~K)SNl`&aOGS1Wl^JN$&ce^4uYV4NTtx}9NPc|}s2%{BwIY8IRstj +zEUjwfh8i_KhfM>`{J4<8AjA*8I^R*gF>~iyIjERtDV@}7&f{PJ@rkLzd13%tw4 +zpZ-S_i!pChWl(vJr;?eh=i2rMIBq_E;X{BDF+j~;s#;T~a{|A`KlZ>u)eWz6aeH9M +zfRhJupP#b4SWCXWXYzoAv1Y%*Snpq9tlrTOF#rmQOeSFUv#HF(X!1Q=M>O2!Bzh4t +zO{7l(_@pT+x>rCKXx05InC>%xGiC$P=z`XlD7u(?pK3`vk1Q+`jYnhX!sT#*DPRG2IB{X=)v +zc_6N`vQaP7;5U7`bn{`xphF$@vk5Nf{uR$w&1LwUseSPFCaJm8BaySnK?Y;5P?7oD*|AfuAfK0 +z;|kq>z+xjLh~=!jeJKOP>#D#0CYS0JGpFrv4jH6Sc~YR%M(a0LX+mq;$YF@d6BG!)XhAQ|_U8 +z%QaCp&l&r7$f^MB^9ojD^jsW5uz`;S-JG4_n?V|h07oBy0`jeYyf*;VMaj_}GBL?Az~#{<^cHGP3}toJriySKY%|3x*lLk@ +z(*_xg_?XtantY2yNCZ2I2;m1udeBgFx*1S%bu7X=Qp1>!}-OF2akC +zWgzT<{(rHDeRT*aU?+$8Bfg$L{ZYVYa79DZ3KzuX2wvU;wEVJ8|MEmoN8-OcQ71H5 +z?x4rM*AfRcJ3mv|NoqLCKkNLL3u?cw{3jPQ7Yi5h_z-#zM^cPJoSaM{C?@EeD*|;a +zngJ*N%ts8saK>gO6?CWgrU$GcgoF!Hq7hF-0H_7U1yQlP=Sb0rAmy{P;CBsEJD@+q_72p)7uKH^!4LcgwfuVpW}xWKe_6drkiJabCi+tfD->eu +z-R|AAwcKskjsTZI^k0!NB>E+OCU8Yr#roX?MAFld0Sr`u?I?iYF`Lt09HtNX-ufn2 +zKPLUvX~Ks;i2&;S6<{wc1`htWI_2PZQ`+V=x{D<5{!~yFyz=tj(c8bE<8SjN1nY2c +zaXWuUIMR~`{Ye)>F;lGWQw;|*nGOQ~l+{H7=3bNfFAf7C2l0_75cc~QF@Z$vkOM&= +z4ErCP0ur&mn8ryD`ID@<2>y58{ik3MT8H*bpnDW=+quA~Df1zC$@&2JTSr)Mh0Co8 +z$?bVG9LMhqvS6JD62CR8&VoIuka~?j$rPNVXoOluMFSQ%`Zt|`kfy6#5qreAKc7O$ +zt|I;WU%G|n5p|_)Tx&GSzg35X0skFQF}w!&L7<1zt8(w-BLUfaa)^WO9wIzxOYgAN +z#tFW6990n2H(HitFy*}~LFEofZ>&e;1XtmJ`G0u?lX0>ZFth~MgFGZ?rSpjxaa +z$zh5Ei9MyKHpIXMN0c%A$^ogf079{C2d@BIRVzE50rOHoiy1IKC=8MWdVm|Rapni6 +z(KjW4LZV1m$ORc8B6a^x0#&ZY!G&y#0n?5r^fBxD2t*@#;L~$OZcjd>mfVO;F7rT0 +zS`u7qBo5hOk&08B&HCQJk&DsowV2GVhJ6Oy<V9 +zO(G!P62R5?+gozhbR26JNz2ZhS#5-ss^J5aZx8s~yt9>VS15jYMNCV4NTg#>Pxj-V +zh#+NMSl)q4zrkHoDI~>WJ8khj{Ron~HQoYeUExERpYOhvQkNtag`l0o&c4}l_ExSV +zDTMUd+TY=uMWkW@oEgLe$`QSS=Pb9ZX2N81O!a}JTmZI02xMB!{(d%z5VF_v4>q@Q +zz!ygYen%*3CKb@`TtvJU3n5MSkkn1tExy?;d066zGvzy5Oh^)VT0VD8z(4Q6W3@Z^ +z?vJrXTFwp%vHS;N`+q;c|33-ayd*EhAB63j8zcp_*ccmH%*Oj2pdJ9>C2>3)0Kv=D +zvCi?K=(s9%NDcPgp2?_r;MITNYontR4{^Z<_i*)p`$wy0@8G%kSKg?kFLK=DJOg^b +z^Z&**s@wmXfcnL6LJ<(c#D|GWyrjrZ3)r)-!)Gx&*j8Q;{nPrZT?kgm(AdoaZoD9L +z?cx~~Mb|b_R|r_+eD>j2HZxcE+_^|tl^;md2JZHRWZ#ZmCMZoAZ-1r +zpJ?bj=P)WWRSDi_KtjjWO|FS5e2AYs#i#zuPkQVxV&h$tmGKI9X=OZL!*L}XDnKZ# +zyEw22!l)tqdZAlT`j<-x4#B`**tI&MuGsu>X1UpD8b~7uvGfT6pj42wcaogO*#_FE +ztA4o_0Z@$;a7M<}BXG@jwfBqPv4Nur&y(GYs(@gdO9*#^a1_c6P!YG9b}Z;O=N=OP +zqT#Y{1D2{G#0x@|_An7?cyXt38s9@0AEy|M@xS3A|HSLNpI=Icq<8#>?}2`8`27Fg +z!^OnH#P~m7&aG9qj9OqtdV-YB5XeNz0Pa_6Jz$`{ie0Qp6|$3_Z`D8+muF{MS`={Z +z{pl)R{dg&=P}N&SGn;-y+-}eVd>^_d6k6l-q}Qyii5bRof46@d_SmMfkRW-b>-EXf +zD_NVzV&JxU&8U|4s@Uvti0xpro5S7p@}mDieYinKd0IBp2BU*-c#TvFZ4d|`$8K)& +zz9ZFRyE$F_NkQo6{rF(zME>&X=YiC#%>zuQ%aKA^EngxuCCR>X`bcU3q2IkKK?z26 +zHG9$2;CHE4i1F3sEAvilVK1GuR{S9^=OQ)woy!%}X-s9Odw)Jic_60Z|UF +z5?DMT;jbUw?jvFhEu-z@V#M!PA8QRaWo;4D=DhMlyL!Vc{*yhv6AJeU`s1tlr5f)? +zF}XxyWn#`chnX-@Jj`X3oh1nZL*4Q0M|keTx^^fif;Pb@bvh$%q$Bz|yab=T*rBQw +z97mNQl*g6@4u5~R^@&pH5sw8+UIrcBR*v@%g?GAuM1@8FrmR(@sV-f4&NPl69dYj# +z3ds(IDh%okE7NpU0@;NQnz6T`;TP9?X^_y|g9_9>nx_S3V49?}%!PXK5=|GRLGzso +za=(zEC-KnpP$S`xU!#i_3J?!lL$ds)UlG|?;=lNbzm8Jwr5;VXQ +zu#qM+_v96HmCvAXxbNpT)pL(@3@J!O&p5;Jun&XUZZKTz6q +zFyKp}j=ZAMM~&;o%np00hqRV6w0fy#i?hRFl=02SmBsH?WQl!4J+HjI`5T(f;eEtw +zrrfkUJ@TJA)ydd9ddl*k<`4}e}^48NXdRM3Y#cG-xz+|CeXy? +zFOHM7V6m|TIlVGKPc=+1B^`UoqIe`k*Pe=FSnl9QV%1npJI|Q9-%C!ckLo0~^ij(# +zFEuj#**lDP$ST~Er^G2a5Z#-3VF#U+FC^51i|kRAS@AjLx%g>DPhJJB*W$1ds +z!~1;!weEGRQs3(WG=?c+#HH`VZNwMc5Ei~$Vm%ghF%fk0_#N!QL3A! +zs#;C_;y5{NE`!I;;f$1fF1~icdg9onl@9nThhU+^@{?Bta$h6F_zT9Cz58bP`9rkZ?^P3c%GCF!m)-CyS~M=C3nF}s&HGe4{HYYD$SKsx2`Ljf3Y +zL$`M_Ch{IBscg|ks~8)9V0xy{^SELkurDgiG2nMM`aoYKgs<+P`&tY8XC-atI-4i+ +z{4xG_ZKIhYYg7Z2?-TO;Dccm$Cv%{ShV_h~Z^T4inZai+Il-Yt&GK4G#`WDU*dv0( +zbN3F70n~K#!)IuyZ=xL84BMDKg(5)q8p|jx#_d}=?dYEKkP{3wwfH~SgL^;clkfJ= +zp^gwF>xK0*+?JOU9gNp^N`+2rBDx?@C8eUe5Ukdm9* +zpSAJ2W41HF5i7RS!STC#jP>gv!$J%XxfjgG3JBHKJuIiUzx3}3i+BobZDY=2euHPe +z;Z@lx`@Odo_4U3B|1&(Xz(oJg_Mu=Go&zBd5*@5zH%B3xDgR-)4FZzxiwfCFqb*`0Dx;Y!ZJMHHv0S8bY1A9t+9qY-q# +zJAFlr521{4eV=3``fjR9aj01(>|`R^2l+HDsJ?H-b#GZ(B3#@p=(SH3#J;b5yk3S> +zr~HB-%uOHXMw>x$rV;T5`jw>-gBP3=uB^ZECTnFg_8Zzx%efJ(oYb$?c2!h>EqtXS +zOQjk4IlP_lBb@*$aq-l#34ZZnCt_LGEwc-M*}~Hr7OD_>RkNSt<3&S|!`*Ve5Lnr` +z8Kqz}!7&!z<2Tx!j+QdK&Wa(^)gZKWCcR^;qh#$aoUL3lLs&sW7lT(pVze{H7WV&=b_gFF;K+ +zfD$d#$B2w{eY=9piKUq_1in%!#|h1831{wNA0w_N*paJb!Df3VTS9)dD~cNv +zu@(PuirT3e{>n%;dFA}774Be|6%yEbsA{C|5vGeWP05!Gi({5NT*Epc)EF5V*f?7{ +zz}@U@-vfof>CtTN%;DYp-WUu7?n+1w+SLAI)_GLz2<#+n%ha*cMd3xXrdEH^f0YB+ +zreA8#@1tp@<_7Z-lyr36PGx*7fl+L8^?uDzj}x2!C-Ol8Df`H6DlzUv=%{TB^r$nV +zPcH_WG2gJMrggP`@-72$-gjVh!hVis^lKp|>44!7&4|wt#v`^?zg5`{CHGpARZ&0E +z#^1Yu(~f_4EsoccGBx7EK|21^9;JVU+^y=0f^kos?t)PDkRn*9^k9e)dci8-?^;5T +zfOw&bwo +z0sLZ8^Nbjf@fCY-dWp;eY`3bh3I;Bzh$<%hQM9>(sE4F|5USaRiOu%HI50Pctc9Dn +zSG0G!BZRtOt65Ds{ZNxT)22JS0s(Cq_S(wW-jLWLGjhym{E)%8M8f7Y2{O7zMK9a% +zFp^dmiSD#v^waXIRUmrnb5xCu%B#M&&dZ>UU6=)ErPwmd+s=ZvK>7HaQ=!&~bnI6S +zh7_N#@;?+Jg+1~Sbkwc_tUn_}ZfvBE2i+pOL!BZAqn>Co!=A^(ooX`>+o(y*L~cKL +zT#=z)?jkRtG1sR6ALi?J6t^CtdfE1ME66c{Jotc}YV#PY9~GT_y10*(xUcVSc6>6f +z!w>RfXQr*!xWZy>R9(*p!JYZHgWV(}z^=VzV4-Iio6Y0gc6>-}d)p;~LmkM@$m) +z +zySCdYp75p5QV~X(I_mJ#XQAV~(7ZqtSXk~YA7HQVcHD6?>>Ht$&6Ns5!H%MwpWW(mnLq_;3C&e^ +zFS$-5YX2ccPjY1^(03OLnzNkt;$1v5U@W&k3cK2Tj#-)i%u>+b$7MBT7K3(YQ~4hmLx-RE +zC>zv)ogq=m&xQjNlt}fFZtEf#>fq>03ChmTBUw%ylHr^rq+wO0CAp|#K-&E9Q>2CA +zlREm!YLt_WMir)t0TLTkL8nV%=v{d}yM_5&8fdE%{}rbNv+%U`2qllgAyCg-luFf` +zvh5m+f+g<}+EMX&=j0F-Eu;T|#O3{P&uX|DQPITR%vMk(;+_5(`yT~|rX!T_K)TpV +zY<~(YrG5MvPLXf;;I?0y7bp`Oe}Xpn)8`F{lrSsDK)YtyvORtz>#3AE;1hGEaib?9NF7hhD2F}com(Tc+lwFPLuPB+Kp{4uX%;#)4|g( +zMl|L7I`HbrYdkmX(QjP()LZ(%&*62apev$1uAzrvu?>*&O52(VU7J4g>i_%Vsut_W +z+Nr#4pg^&Tto_eB)w#=5 +z=XI-bq1CqHyu-^B?O4 +zCsh1HWAneF(f-!oCui;o<_xHoptGE1X +z?Ts=^krFXyhZ@q64Rl-CN>fkVM$I$Wlm>liS+2%}BVPyWmZkUgpU3NFCTlWh6(LjS +zA#okOg^^yMU*I5hZgaRiA-McnZ6KpML +zGkwG>=OT<3qfp494XD<{xeo-Y*K?UrlpN>jzXcGCA{;rapm?i57?~|tv=Zwk>>=uT +zceHVYt!lz#e`zTpRNoY*cUu#vZvCnCH}CCfr_1JcgQF*yUg*&tiHS+Pa}8F-C@T6pC^xZ8H|OcxX^$LFY278z +z6M_-@CCY1LCAMvwyk;$qu$Kc2+b6^(91{aG(;l^vXo^dwQA%_%rhOj +z{vO;+wTDG-tyy$LT;szlW3!Mhl=4#IbF_<8GIC&lwXf_K6vpJzsAuGQVmy(R0jo&L +zq!(75t?Wviaav&mVS=F!V2&)`Y@R~by))wO*jQ34iW_D|qfhR5D}J`fsm|pk6H?*m +z!@mMDBH2jANcp}HkE(%^%TZ8;Y7A&-#;O}&x)=>91_15z8`$mVdhi0CG#4=JQS;dM +z?-k~UO#J5iQO^F@8#IvHOQ4Rr$%QI?rVXj&rI66-)iT>-W;tn#fDqG4qmj|-jdq7u +z0xTn`m6%@&va)mJtH6gtqmG16uH0{(s}8H~WmVXmOa*DJ>t}KhB%~X9CFM)>PK#NU +znU{^b$~xIWQt7U^Kp>Of=Njs%Av9NM}T80gYoI4!5ta*xAx<<1Z=Nm*`x+FVSO4 +zZ??pRGiYRmdE@>(+Z9tAG+3;YC+}xdJ-uzq)Q{RnRBKO63&&>^KCV%(GWhB8@=KMkX( +z{o+jP%0sa8#Lz=ECn>Mee!nDnpB>Eb>5m16hVpBNcigBiBwa|#lWy)I43?_{t0GaF +zU}$J|23hyqBtJV0Icp7-xAGVA!w|QAca{6Sb{{iRbP5!{Ud#q9S;Q+XY{ImZe1+!8 +zIrk8`qgMV=TJ1O+h^Qq2i@@-xx*bL5PvSs&MRSEY1rV;M7datq5^4l#>#}b4f0@A- +z0|w*-F`Ut~PbCAd(9F$BKd`XO;(+sl{%s-SEr#OS9|8g_lYj!4ry9qVgt6Gzs~Zdi +zGn5u36~SQOT#La85LPn=frDP!lLMp@V`%?eby-(oH#0j+b1#=w53u1NY_z1gIg8f}D9a00X!rvb-D?&7DcP�ur!R;zEEe=_v^wHTI5DS +zLqwi$>wJ3JM6}Jyo(MkK5B!+Bu)$l@!ykn@SbV$1e>_ARchneKI>b?9c^ +zlbYg7fr-9T#AzCp3WS9=e%o`zI$yPF +zj2Sh%$bWy`HXwQ+g|M3y&g2AHmwKFuuvY*`$_h*e@hWE&!pL{bM)u$1P)0f=DaSkH +z7QPeNDgXEPQ2-;|+8Wl^flD6dm{_sDnKlBf+Tt?J7^yJ`Oq}~2F^5ARp_o{?Ut2<9 +z{VJQfKmN>`_GFqa!84uK@~C~?4JeUO#`x$hwT!YQl^K&&e%_l&pvI|&;d +zGr>qm4HjwryEucOr63`w$mZEpeh#RI{CN~pKgOAZ%d)oL*cXh*DH70*f@V|$MABx{ +zf7|r$1He*(ae+C71V&aAXVgXc +zLEa#X*qg>X0YpoDfvOPB`let6dpvAmbb2g_odxYw<|wInZJ8x&@Q^p!p>|?Nga@IF +zX0L&qr9q&KQ++1C011U*@rzaR(vN@qiRJ=qMXsR+6sr?xKP7~PL>bLUr+6P@Ll7Cq +z!95=fE#P8Mc>-{S&ADRteXc=v?nxz`vh9twfuEIV@;bAxxE34b|OUSqKxl=J#xQ&Krp_o@YMXR))X@!*@C50=xm`n~l{w6x;>{zO!^Txn*)D +zoRg%7W%GMTR*e80rA{05bv0=Dc-$6*VgPZG*cEUQ{G7Mq+>^ENt{$JueaYcFE#Yl# +zZVbe)Nj=05THsPfih>jEEYzmUCgZ2~51EKdR%5nAnfmSh2Sq)d8@?buBTcKElq5!c&5a +zENr8{9(0*~-x(o=TcNM;t?8D9djY-jWiyf!cRupqZt`v}9&J>#JUXmQ{(L=waOOG& +z=!Tmv`^&9gq@(268k-GAt#R02jE$bH2AH#t_&Sye%v_*+IwPc4=teIOLSIHy1<22c +z5yxn)x&aODY^03_50=L34%U!CeJlf=m&Nv!Kfk>QP~4b-gBJT6ZZa$WT7&*7zfx7c +zsnD?X5(Zw6K|R(DT~j5Hx&$WPkrS%3iJI6OzBq4o+Gqz@o{zM*)L*RZ8XsbFRACdE`9_R~qmgwWK +z9oR1(5W-U4rMTjoDV+q;mP$?k@40~t;8q#@&Q0fC +z^WDkaJmxbN-dgFf5iiqbMCkq*kc2ALPIKLD;30e?UBnF*2UD`Gj37hJ+LIamyCS +zg6v~##ulY_?VT>otPoR(%<-ut=F!Y2{*BTANjB?s$+VW75 +z1c!A*!$?lQxG)U-WWmaFATI;;u=f*>*8hbf2{Ynxf&*kwoD-b3ow)LG&R-N%8_gM3 +znVw}TOEee>MJokD-f&b;s>U{3*6yomfq@^B3wX86Z^DpPtb9yggK)h;9?1AtKnp2h +zhOVQBQVJyXryuve)nth%K%(KS!z)Tr&o7 +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 +zd}!kl<@U#52SN+;u@*HZu^8N8fM+Kk=ytL^%N +zDMp**^$HG9zFnc^sbh{8ELg*vHqv}jCrM2j$lpkSq<- +zxbn(S9Q5pG0M#f)%yVav&ZAy;B_P7L+|$uHVK1exu&263=I%wn{aD-0uWMT +zae$S0!qOY}vR`WpvAh?sl1lh_a*3<};bT?1E@Y0(Am(j6#Qk>40Q7W`{Wuu(obTS9 +z0!?glHmdm%G4>QGM2p->6{NONEvtrjhiz6{Tm%LKoxQ*iSAP?g$ +zsKd_fWqzD6w=ax=k(!AhYqZ&R!X|X=^LA +zTWTj-`;Mo^44xC~-E70t8SI@|^UQrxA`*>r0-@CZuFAe(*#y1+HFPSZdy7PIyhTsj7>7NVH6V*=y +zd;NaVNf5A-cCzrDT?8<7RM*XZUxa8{Q-&W8BdkNQqIK3W3kRqv-g2m^8P3#WHUm8U +zZR&|j#$RW#{Fp@=++E!c*810w^yHlQq?D7j$2ztf=5Q}c#o0TYP0e>rCr7;7W8 +z$0ALVlW_csbt1WWR?~00xA+%KwOn;~2c^j73_KIcBeYP7O+R22W@I`tt&Q{=aV!+f +z@BZ-7_xW-j*@=`$Oji4cHK!J#gLsKxot!6I@-r4!zTJJsun|jljkIguS;B$I#9{jP)QRmBv +zCc(j2*-bAtK|FY8D)xd3h2Z3*j$d$c?i=_53B|4 +z*@!P7Vm(NMb$;qwXJ_O@N-5L3!Tbsd&lBTmjz +z7%RM(N{j@7*Nl|VZ*pX^Q0$8H^nU#%%xu_ZOg-zKTD4x>xbjZTX>2ZjZ9U5JC}W|? +z4YQXGJT)50Djwq_hA1cepMGve*NPj!#5fR&RG0LjEU_eJJx7PU8t+JyA*_pjXh=(H +z`c$8e17|*mft@A#?(UaaqUdW+rAoWB6mqT049YTp@Kk0p2|!NWLq$G8SK~<(W|h=w +za;KM7?kEperliIdIBcPu3CK0#NG<3QPP}Il-iBfWmW-Db&=s +z@V^<=7%GY=c`=`Q1k?{oR54%v=&bFYpXdSxw3TSF!|bI$U05Ir263y-RCV=(?AACOld<2894 +znoEMp;inc-il+8@Z>yLFcJ>u@yy<&pblIf+pmW&j2*xr(s_HW}r7rpf?gy>E(Z7j| +z!o^%x@N&V}y)LBOy%CxSJX7cCGgr(2d6!=3X&D!K-=sRSiz}@S1RaL79J|%+^k0lC +zfJzf{BpW8ZmH%l0eS-4aY*|X?3xwPKXd4f5F2b`hI_z5$gjj~I2F|;@nF~Ax +zJ!nK2gt+7;`STqhjot=>|KsoL>-H}@k7cg{*w$#;Kc)kIS3Wd`NVb`&-WndQt!{^M +zv>w-!E6P$Cs5R@_(Y`q3^D}0V+%wXpY-?z@{IR{b`ENC3`|O)Fex)IJtq*C!p$dNS +zkr%isadvjDL5&bFnfLD3d=s+*RG_sUNgF_a7QXP;hP)vRi(%73!|+kJtAi^2>6ZTy +z9>$%%pV%Z9Js7GRn&8l%b8?JTQlIGMr7zI|lgutYAzi+1bUD9NSKe>!VnU(5{gFP?&Xu0o=HN@*lNStiq_DZ1}OXXeRRAje{2pcRJ +z-xU>!O1aEsDe1wgMcm{NbUd2~r)i?IbUb5D2NhD24ONK}IzV~W#g-d%)u{dxd%e;` +z_pvw)doRxU=wv`VV-Nrj3PR!;R;@>2A`RCjb?&T;u%9Jjb^u#MDNnzGQhZi-JQWHI +zJew#vXAv{?s31iel8KNSz4ep?6HBu?W{T@|TrKf!H9A&uNjsXAJq;@F!^v|1$4ean +zN{S+sPj0Ppc^}_T*;%N3*Qii|u<9-EtEddW*U~ieZMyM|->z?!)M5rMHb`j +zkavtZpF&y2zn4z#PoZAgS(@%TpR|tc1*xhAHz;6+iLUU{bx06-(aKAJg3l6$&e{(C7${RL +zHpEcCg#9zUL<$Qpj!{}QPC`~JS^zot-a-{NwWAHV7={sO1W8boZ`vm~940wJ0_lQY +z%@f}oBwRQeQKCcZw4Xj?`ZShYRS%bR?A`8w`p?_L=%{-(Xth*^9mKc0nvHD+2i^f9 +z>$K>V-_yYM1J4qmaC}#0Ih7Jh4#kX +z_w*=adpjAs)+S<~XV7L-9W|&+K`~amt?LO#N{UImYK+&-I4-fS)OMS-1yvuXtf0ZE +zG|+lq>Fd~@ujx}i10^#RTJD$|#_$R4znaF;u(DTp=u~!M*Kf3*Y*J9h=Ca-9fnFGZ +zjMZ6BT3r=FRQIk|jqPDVU|-&?u%-!8xqp9&j<>elV?0&D@y^pcXJzS1R$b-%+z^E^ +z1-xK>80popTaZ}{r}{cQXC3I(uQhmgcPU)f(38gRhV(%!8i@6M|B&E$NBU`d=$%iX +zm)mW5xHdM8`cL#lV6s!ZGEnE)mhn~;(s7^yIHZ$$?$ij5sSZ`ack_dSEKut17L{yc +zLqzFjV2nBCnfQ`(90vfAKVUzU|Dj?Tz?0OE=aLL{$uLES^+ET>`sibt*ECq=$e44@ +z)DU~+6&B#e3c>=u{#TzkhBDI3$-UErxH!_gdap&kLE?=taX2f?{sNLk!3(dj4z^;X^C*zso3KvaE* +zwshYr@)9;shKHaD0Y|Na8pu^54~7MNMP`s5`C9-)o;vlm+CRX3?zj+|W~CG4Z5#17x#rQ5+8{ASmoNY%9 +zCd`}7jhsH}#xOPZ6JW?VNW!s+^Kxvi!&9XCY@KQ@MQILxpj1?CSBS9O8C*WFdEl5> +z>0%uI3}-J4WqgaAkfK1Tt4>< +zs$f7%3v`#q8yO>hI&jfIG(9utir-3XF0JZvZQZ3lj^hF;Y0fQ-O0(C8qBfzA>IP!C +z?!As2LfVh-h^p)9s7@~8e|3=ThN=hCMIt8Z%kBEdxBWO1DyWSB|Kf^BceDnNoL9Bx +zVKoV2AvkoqN|hNS5sgt^L&+Hha*GGS7-wlW&KWWLxv0~`>KO5cCcpWz>a36_z(h}y +zfi#;D++4(EvgCneo*wyG2G2!52~G)GfH_{KuGmhkX0;L{$s_3r)zl^@7_BdmH#uDC +z>~9^Mt!fn>XBDuh-U^mHUZ92l^kqBA +z$r%^~1V%k0u#+UUAjPIZEw-fWUfg6C(>_r(5mB?<7JhX_9swKn6F>`f~OZ& +zX|UdBA+MU-?RahIV(d +z?{f=fPe)efNRBrXDN+jKHGN8H(fg+77yGq{$^4BYN-DTWM(b1AR0xwsu)4C_v~waP +zbqA-wo$DSZ3IKx1Z>+)>bmew#gYRqbk?lh4{`6K~%w-}ZH3zTIo$Hy#EI4GE&1mkM +z4cc})%q7ofxY_p&AZl!xhglz{_<4O^-i&b^;PfacWqe0iM+W1(E$_b=Wdq3;_y}*N +z@I4d5T%YxzAr-x`(@SK4Xqekb2tqj~6wnv{hqSkVu47lWMa|62%*-4^%*@Qp%*>9N +z8DofVK9 +zP5c?<{PRNvbV4b6`a!+jU`vu@agRBfu+|X(U{CMkUhFmtzgDFv_%S9eNOW!^i$guyiu{T+o55 +zI-KIeVUV*NmDUSf*YZn2f{60Lhq#Lu7ffh4`L<~OUy%iY72+Vf$)9Z +zmAiMYnSGS-)V9i@C*vv|^$8n(jc5A`i^Jr5X=RH#*2SfJNF+@smLS#zkL5epL&6A_>pU83JJtNy)S{5Om2KQ2|_H-C(Rq0?`Tf3wXf +z{jY?z%tXJZasll7H*+nc7&j3!pqW3%m^lFU|J$sL3QqRM%BC*bj0z%Rj4GxcE{uOD +zYCiwi4L{reX1E1>*tyvmSXqd;*jN~t*Z|zN!T=)xlyW9w=K8B0 +zaVL9M2LOBSAJ6%-!>G)t;$&#&?C@KCV^2n5<$p8X0OYF}8aV?_QFd{1HFo*y5}k>- +z*#BXWKeGR2kpDY7CL1d&^FODkb?KbguZf|203xe_3Mh$+IJ-abp@F0DTKaaaw?!oI +z5-lM%N@$CrDy2{#IQhR#SxZ)v9UH=aDQG4?KcAeQe*IN9klm%%{LnH~dFS_fb?Ul? +z(cr1-l{ZtJHFROVw28T}qUz|bk9p>+{BfJ~@M~w?+xhK!XoYv5`b>AT+b6#h>0Mbb +z8%%P~G#?>xvg7^vTJ-Sec3hr*_v7iuo4$Hd*;Q9ulI5Oy(q`Am@Bd$5VDt~2!gvx4 +z<~IzQf1Hp#T$m?Wo^rajWs1DREm`6|T0b#G_+E7OGSa*%##L6Nz{ng|pH#(s@-FG( +z8$~sjhM+LBdJy5|klG=VTCeNT>Fl|!rc^e4{n)}Vc&XdOm}u6LD_(u@6RTEFqP9UM +zNH%tgNMc*=3w^kMYjfvtinY&dw(UOWk$QM7;FH*fbGuMA=YcYIKSj@$aOBJ=_Pa}~ +z^Arme`ZameFBtk&ykVyMhj9a&g7P_CCbN{7xKJh!YOx_wm}csa&W0Zm6mTwnZ2k!_ +zJ3fg1{sq)Pm{MO1cZRsBqVDS@AOXvA7A7!1Ui&JB0MXUH>w&;obH&oZI2n+rdgjjd +zt`X{WKicXFT<*C5NG3`lw?$B>tVCuo130Z3*gJwZ$S?t{|x`8LBC}z +z9fuT)+M~rU2Si8n)ZUECZl3;;#$etPIlk-pDi=J~6_>_GeV%1_Cgm(&`6wZwrLP$r2SH+KZg5|d +z5D!vq8yqxiEaexRA}A&}@LD^FY;cWI{UDS?w{~QI+1TUBg17c{j9|1B(v3D)fXPgS +zS+8)r=2|#jmcVb +zqwt2bB40e;ea6=yu(Gq>EogPV4sKh(0;>`I(E_a>|=yAZu2__)0{do)uQE9n&0t!bO +z-dH3P;<$`cxjKnrrEp}-2@l}T;g3KA31G|J86iFmlNK#brAYFSadmpMa5*C=C=$b5%Mf(_Bfd7CyG=~y9AW8j|lpy6y3 +zw-`d*m4BfAY7bXW|BU3GzKV%;Wrc3-kg<7A$~--Il#SRTjtX2tDV#6XT>Zckry)w| +z{CrSBPM%OOO_A;k>ZEi;I>j0yV +zpJ{#qS=ay!!jc&9)}wP+09~Ea>N;v*d}Q=4Mlx`V;K&FNS3{|4<0534#M35{kk%|# +z_IQiRRv2kE&PYIW=;n1NPjH#Cf(#DtK*qJhxCJ7W;kC8c;&QP*Crr0Vii +zetBcpW}0$3CL0a*gWU+NdpU@$C!qx$i-WrMf}rn0e*ZCJRx!fRj@I+n743;&)hQ&5 +z7yrcFO>6`K)h5*Nn3#$88VQVrCsgB!2Gb&E{Jk>i5K;=c2TGcHY@Unk0_KQ8_H0{H +z%Y($+5sycU#}F+R6J_YcGoD`Nuy9;!b$z-Gwi*liGxg9a?a3ot;nikVJRUtmq6Asn +zBhBlGNGD`4{pF)<8r(`Lg7?{2v3xG7QtO18FljO+w8Hj@4`FXOFpYet2Ns|(b7VY> +zk~wx9;r%}0;ZJ!W(gT7e4CLAk*Elj*2Rf1=gm9E_pNBsLnPGOHFOdkpPm1rZ3~)!W +zgf6&!Y3RDDj0LGeEK4fEy*iyPd)d)6u8p3MQG$33E4uNbtMtWTc92}*X?k;{pX2$e +zm1{fP#Cu@Z;9x+HK0RNGfY(h!1to`7$@6KboUCWNobv&wyUJaNLyZ_kn&s8UiYMgL +zV95rk2OP`{M1^1Dviry-PiF+dM+J!TddilKjgy=k+z72$;_<X0rlCacC6% +zcnmfIihltecVHdyCUB>L0d0T5t8Kw_4oT1cA;(Z +zo=Zx{aU{0$qwfxmiirHXizspM40JCugg}XX!M00ytQ}3n0F%qW7^el_0#ULpE_4+P +zTewriL6VCmLG0I_F*Gxd@j7sEENIrTaU_7x8 +zG$3|96|)IUIWJOb0VB|QN`Z9kPG@7uMAPW+JH8C58dDNs+M=RtZLat^#r^6!MQ&E3 +zJYjrJ4D2{q$d%tH*}kw +zxa(whJo&-+)0u&WQ7%noWaQ@!(XBIe} +z3|>+((jH?$4tda|j;sybmm@r7!-#kp9FaoisMYW{x9Ojl&q8uG*FuNlKh|wU!@~R- +zp|7MaP<88K2HoX%1*y|>+UOi4G}*IO-6N-PB#dmi-eX-r{kJ%JKHE7dMSi6!B|#W_ +ztD~JmppIishA-vFc8|5PW+BtEv3A?i?0?H? +z_941Y|5BH&b8m|Mu9hSO#F +zS5^u)b^IP}0V7SApDo!dFZ5pCx5t`zA!ad0V?>5M?lku4F49k5tEfI@EMcfz#%FeP +z(~#{#cG>aFD&e~`Y>?aTE=pM%d7pPz7E>0_82!T9Oi-K3>+!P+Vsl<1l~C8 +zH(%(UU0J~-YhUjes7}GrA$uAe9!*>~7AkY%uhjaLF-ISK()xh#I5kCdoI(;-Rj|E- +znMd@qHF=>`v({R5l-EC&bZHf|t2@g1yVlrhUtgmNeEYGyoj3b0DBKYI66I(O$OKuN +z=EJ>3vv@YN*Ce??(E-#o{@E`=?bfp2phYbwNa?Cp6t=hw7F)va87W5BtI=<(k9eyC +zs-D!X>eCEg{Q}sFs!@sImDf5*DnpfmO2b#JM#szca6+-TB;0XRBDfSuBqfi6m9QgY +zpVvoHPYXrj-`n6UleYHr2au8~Qd{O5b?7THajD}O7Mv6b!c`JJrB-Jj`RJ}IkdD^2 +zLi=C_t7%``Gs$ExIbdN19wKY&PwZKmg8W$7(oOS=yzN;HV$}#{pB-)9%sIy*&Wg4< +zon7gfh?w*HTz^!NQ;UDpQy}D1L1Of)2J6cc?yUTVJ$Snf_yUK%MGg26iV+u|@s>(} +zU0bJr<5HcjyDwQk*<%N8rem^8iACH<>m66yKs6CmPXegGupBRrb-s%jM^qCB~8 +zO1?7Sw?ikZzl?XcM%v4iF+Dmv33L_hPmgH-TJmjawzi3dZX`nCN+tpq!i(17bqlH$ +zR!{k{-XbEA3Ce}H@$&o|&!w-8rFvrbtXgc|G@w#n9{ZyQ`Zh-O!|!}Q@rpF9nAe-% +zW1O*g5ax7@Aoz2eK-2z%%TPgQq@nlzjG>ni->A9VMPSIURekBu#Y)fg`mIVsbSdMGqo?Hzo9B +ztbE^r*GNH;pl|bDqti$3WiB~8UrNt)SoerCCe4vu-N?=Y?hGZGFFy$4=##eepKD2VeN=a{liLUz;%<}GAoug8HFRO +zI{d*3+hYKPsYl7xT5|TMDWN4B?xV)T51<8AjU8w4hk}Ty`?ZEW)HVOj|ao4|w?MST3L0`e?*l +z+eO_;cAIKQvHGx34SEetz%KByW|lrokqx@WHft-Nsft&$lBso0sBm^oRP*x0Cv7-j8E +z{%=J9=*q;^*!2HL>;Ht7{s#yuZ)BzHV#_E;#1269{y>!g_>PVH|G~G+&c@39PuwX+ +zN4AE(PH~;|if~%M!}#HgE%i8v8d8ynq+2++1Qf7RGW|y`&1U$1gwuYO;wxC2bCDW1EIO^sP_5eD`>$M?OBoxT$! +z{t+CT3Hs|Hwxs`u__|%+v;$E+a&)HnE0<58 +z2hyYuE(?!2h&u#NyoU<|s3GzfSOXJqG4(JrOY;cjz3t*|?b=h*&6r5l^wUlVmqQ@- +zStAR@F_cO|PTnPPu%Jpp`qeZx4pZk%ATyL0Y7*!WuHHcY~dhNgBse9=)AdLDNtg4PbyofH)VmDpsaIOeIQM4%O=p* +zeKKfVexU3J0au{xabg2kj|K;VM7V5z0Vher#^JV3sm#pHk7y7RjQs4J!GV1mFBB+` +z7g-Xuvuh!rSoP(!?zj~U(zZpr@j?8+*0?1wVb}=RT+P!cVNY4ICrF_oC>YnO_r|=K +zo^u@{5x(3A%><1+^#aAWI*{K2{k)GTqk#75=P6vGk6%4>vz`I9(Q{FoM^8hRLEIY* +zq7wSxm`C?rYEVeeE;vDlaKl|^j7EiZf`ka4dxU`ug*Qf(wzZged02(1O5M05XJ^AI{tZSBt1fVgUtDgi1!D;M?QY^w#tumu}jQ6Ho@C@VZa +zS1nciPYpjyVjl+^FQamZlF==%%ORni!d^om)&cI$%f4+F>h)EHgJOFCosagYudwl7>c0n;=){_G4t+)2&hoOM}?g61%nnJV3 +zEh8P~$E_U{i4Df~sO`X^CpN$y5R(~QC4vTxLb%+nBP~-Wg0h-XDn5U!APbs;vy&mv +z_Tr(ArNT|G0WVJ*MfWd|Iwl4kCxvBc1RK4aC?p%bF;nQi{r1DV(r(?Vy76I@@GZi8 +zB!kVmc-n4OEIn^WBc#ql@o5cL$MGD;(*oD&01rdQ&k^jrOZ;Jjv^*!UsZ2g(_=R-z +zTe@L(VzSAJGxhLc_Rly{)8z5COz+&nyG;hjOK!=%M&=Hk7?_{L#M8mGu?Q6Nou5P^ +z5O#e5OW8TaTp_^B1MGA<@ZKYoSoRO2pLB?}^P}H8Pv`>O&TWD%!+G=IxzLu3lUv_; +ztmQQJu(*>UPJ{*ALLLk(o!Fw?DaA>bA$|@8+tRIK+60$Dt9h85n4e4v9uiVH$|R9LCqZ5~{X(YJAn{GKWs=^eOwM*+fgt4rfkq{q +ztVe84u!z`3BOgX7)`!Z2V;r6}7!(pfDzTVg$mir=Ufr=EYxovb82CdZ0@m8aE)jNOYQ?^+8W9 +zdC{SsG1ft^B61-y&!WFk<-0S+@!i|kfZ1|=7S^7sf +zY~ut_B+8nt4e1I)7jDud*Az$M*(@ZpqD7itH)~Lig7LBYG*2_Y8wy}EKCqxbZudf +zzD#WeU~hb5R(85t^)*5Q^3@N0O=Jl*ovpbBD+XFaDG(VTH^j|-?97J;+?IrId~H>R +zG;2=Gfd%&D?%+Z*!NL6)&rhx2Yrf`@ehHwzbtXe@G_4-q$)e%O|Nebvk&yCq04sqqIf9OQdwSfbjw>%U-?ld#R@H(6; +zY^l*PcMVS#uz93$0pcFHcSdK9(O(RCN}qc&PHQ{Wcsp)5ML~OS_)I`%bDn$Ge6nA! +z(DUAC1t0!CN5jvIX>Eubr8bm`!^N=vM#A2&dybSa|22l5j%{_)7X=kMnTm%k7Phm4 +zRiWoztjck%#eFI!i-Qgbjr#sQXp`B9bt9+^lYSqy&K*O$^Q)@%`PL{)WPWnz1V?Mo +zUMfp#5L1LWbgr;S39JKWKZ=zBLzwK$(DQO!Qwx=Lf?!W#IV8{Io3ug;5oha~Df@b# +z0?bjTG;=VmL@a$=ue1{_K0wv|GeEX^;k{8Ra{I|X31=*~rBBJ{G=%Cam^B5%_6+yR +z@G>q%bKg$`yCc(}zMiM4I02h)M_zANBYA$W+ank6cdl=1CnJRKC#J9GEj@29J>Fj| +z!DSc?PU#^)9|E6lE?oSt2Hu`N-k}%1rJ*gs>+RN3h8jS(3=2T4qwTeybK<@+6z9QS0e=M$MQnp|?&O +zbUisDmziSE8aX25PoL)lR +zctbRaVx_9!mZI<#s%uu;sWOBj>w5&sT2r)`n +z-q>x!!bS6^#4*uRE>j`>(MCCwNMo0q-%@C*|3eCH21(B>naCF;d?go&AH@ZM&FA@ +zknqC}nMA%2^T7Qu3`Y>InEH+u`=yg2&eC}p^^=kcepBag>`S(1^jyZ@)~6|T{4axW +zqD-Uy2rIkwx}ixXz4AKFt9>(0v(2 +zvHDAw`A(@)wa<4bLm)>Wn +zy_qD7U?u^XpajT(#7hFPKnqd;kG7{T4-LloK6{Hb8M7=^i%YrwSd$C9wWq$zr|fL# +zjfFMosE5F1U#{#^gLa#nAvCOlIAKp;FwhGgf?w>Zmyb-4WM-ijqZk@3!pcA+O)@fJ +zSZvogF{;W7-m6*M#CmG%Qogvy9!7zcU*o;mE#I^wc_+15G^haUpgxYPRSUkunY3c6 +z=_`Qf;BNDeDo;$8K}nJ{Vv&@gh!`Vd)(meVUJTQq#qZtejCfsm#wE>Tqq?)pGo`P) +zY>aB;JC9tICGZcaLOG>~7wFf5U$kbb=<5Wa!*tfQiork4w@-e}lR0F7F(mbxqO{V9 +z4x{NS?WMvPDoMz|L`V|XA%^aKvb@RGUG^fe_2Y2TO6!SVlq9UM6_F$5Vj1pC35+fy*m?ddA2stQreN@PD{czPT?x7z6 +z7oHhW)j+sDe=Dw0(^m;`gF|OkTiGWD?^d|<+I*(5GlasJ>Ty*jA;HdEMnSPKSd_WU +zBiiR}Z6EEWQ&qHfwPzPWNy$A}<6Q2UwD2DtAPS$#zFgY(3;v$lInTu@!lZgv>Ydo) +zOkJ8EFm9BcjIiv_%IiEwv?P^#+26%D$~P+2+@DaBYvuSw-n;1m*?)c^{o6q%t!qpB +z>LEIQl>2_dIGF9zp-k+Iz?AKbzuZz1*EtTC#=r90Fn_l?i&4CZphP+9T)NM2)bV@v +zBy~|<%`@OEdqZBds?`hDg#X2^F>jz5{PS?W$BszXC|w%P8P(SXYDo4rA#p45lTQ5? +z>3auWbAcW$U*mPss-oq#h59_Mqx$m$1OK^ofT$n;6ve5vvUEB^uHUvto9466W4^-! +zy9-FGFC8H;56<^D6-}ICpP=E6r~FE429xH9G2@)kdLqu_YE=X8vX0-Otl9rI`l(pS +zW9p)WgA=qIL*E!VR~s1RQa;vS>0{Zi=U{ARaRcj)>`OW43;raG{59FQHvy<=PuW>q +zt!6O5!HS#z!@)X!Q1`r}oh63rpd?6>I7x~yM2wOnw~>*giR|%+?25A=Y#ih65?GSs +zPl(gMj3sp+?fL}07S{{(o543r)n<+VL$iu2`j>?J-B~}K)i~)FM@s>QvypFat&N0f +z_q&Lzae3h78-$kRf#XrD^0|$K0@C4nxYsH>b8~h%3{vIO{n;ko@-c>VuZX*UCs&dwGIJe%zX_;*=6j +z>z&tC#h$YBxc|JJrf_V28tCf}!i=dCKhcoshsJ({{FRbJ<4=(hNBnoT!7Ig6bh}nQ +zniO`%Ec37tFA#sK-2XSn=diBD&FRhohAGn_PN6Mw3Y`Y}JE8rSllW<88%`m62I$VG +zD5a>CDi`>9RC80)fxl?h-U{HdO9pDep70p#8jA*n5LxWYF>3dB4)PNFe~EKxrTisz?4+6_JlivQ``|8UwEoKrE{k7sSCKeF<7 +zx&BJTz$8Vn09jn!Ij;7AJ3wAwqm=VS-$sg$`;3rey6^oTp7Ces!Ohvxz9;>2Z3r15 +za>KvVzpm{ubFu5U)0UkcPrWbYqsYf$ +zLp@R=)}<+u4s|K}ZmpNU)cLu_bLe3Bahtt{t0%}T?vJd63V^KqK(3w^lixxBy`>uT +zrxPpsyx`3M_Lke+*n=r!CvKuBS`3-bjMp0IQF!_D@`LDk`UKBlEng$?+d|7Ud>JMB +z#@DZ_aX&*|!~tW~U(Wv@E{l6=-JZphlsqe|R3IlcFB!o@tw>3JTqKf{T$*(DD)v&N +zwu$v1LVIWR(WDolR-)^k`|#$5dQNEgr|W6@?2e!RF^HWvT;BOUCqE}9hAW{cN|8uO +zicm*Tkt2U2D@Ybe1{|a`zApW>UgcqYs%-a7@7!OHF5$khM4tCc_}UC4VAu%y>BsL8 +z(uDJ$ZpLZeQiII(jqF=;QF3CkQlgTSl9Z$rwInq;wd*tmAjR3c{M7b0-kXzC=vw<| +z(=^(aWR?(k={q|Jq+FJ*_5W}33jaLp76_HvRix6Sj+Cf%X}(E+b19oI%lRuMo5YWB +zwx3t^FkefyC|%t5RHbTo%#yOqtd(aueEfS*`*XwF-9A4BEy-_4{99D)u8E&qjt9jU +z(TMOQUyq#GQ>&IF+k|2?pg+!>vN7-0X21Y*(GC8GC>NZ~p!~gxWS^A88l`L1V=lSB +zl9Z;z7y_a +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 +z@&vaRRZBtwJw#n*>9-vp#-7ewC6tQ6( +zeR}Z?yi56_+aS|PyRD~u3dAGBy6xe4C3JG-F)Bn0c*Exk{X|&M^XW=)y1f)NuXZWO +zZTp!~Guku6yTs*k)LvsQ1oeQxP#EfMKRRFV0^2-NMLpgGysXOB1bV_h(A9GJ1!=b; +z%r_cc9{&ZY!u?cx^;)gDee9iSNPRFVvR35hh&!D--;g6-X)NEhU>AQvfq?n7V;bcB +zE>oAg7Hr5(w1X!S!$inQ`sE!`tM#wtu|Cf!8rLzJ`j7>PwF$(v(7?5JpCysp6$Swt +z%*QOyx3O?j1XR)u*Bp1<12)tX#i*Oyh0QNn{CIQ4ly%~}4oI~2d;;tw7cm1*o^cmY +z+9TL>7cs&cxL^MES(~T$BEv|v--9LG#38&vbe0zDIziQ!XA=9?fey>NO{_>ha +z^kzL@v)AfkaTM(eTj_DDcVt&SGQnc$?&Ck)J_B((lF^>Aho&xn{czPQ#2-CSe*VLS +zfR9f?U?YQDqJ*<@DV4T+t{axj8u5UIhy8(e|?aiQ^D +zL|_>{{jmZZa{Kg6cg4?4$iHce=v6=5Zz9OA-t01g-6u-5*$wzWm!WHxc&XJOtw&FZ8Lpty3>Iy9Dk8Eq=B{qgTuQ!tvK(cdKH1 +z=)kv}&>iy!>ioZ=jwO!89~em|wHeQ65DnonJ}g>2RlheE1tshf$Q$CVtuU|o@}4#4 +zxSS)e`S6a>Z@s(Vpid?A3l87%3B@o?_;RwOelKw=$x=J|H8%ZrKn;)DAKUc)8b6%Y +zPG8YJ1?UT+6X#_`@${?e;Lh%>8xv!O(&*(DRyAD1GgG@7eN(g26Ie<=G*bBj!_T)j +zW|8PazD7F}WQ{&;P#$QG{qmGgn+PQsYGyZhvc6|%f-n~w*q+DXrVYrQE +zt(%+D6Llqf^JiEc!fTj24^$Q+aB%0-DU*b@122RtY$6ktHdnZ56f)bieceuqa~4>q +zlVei9x}h||T#C3<(U|tVPfBz4W4WE_K}CJa=uv$N49-Oh&Xtt;e2_Z7ogJc2iPt$c +z98oWKVi|j^*NY3(g5rX}{5s~F@Iu!+^!%sNqrmZC%c6TBQ;~8+eW*LcXK@Qb1?&h6 +zus8bxXdzRRRU{R$Vq}99%c1I5n5lqKoP4o)%clMXsY*2D!qUPWW|}Oo6c?C~!u8VS +z-UX}ZIYkhMdRjf+BItNj3DlZGkV501uZD{A=5?Qy6|qsc)%T?$zBs=cCLBhS#aHq(s5=Nwk3l95gsVi||;73>%AmM^0cE7scBou>rSVs1u@6&xeoj +z8!HzgnZ?l|hU`|w=H9hc#18dS+|EZjDqx|ZR}#0_y0rbdBd4!A6_V4fw6!}OPH!3& +zi(HY9`F|LD2O!IWrD1TI)6=$Qx~Fa1wr$(Sv~An&zHQsKZA{xX_s)CYzp?+u?#9N6 +zQ&Bfnr}AWFRphOcg>zA29|0?%TOVx}QidL*G+z@s!Tf-u5NWF{5{Sc}z|64ee`w2f +zTUiE6^2;9|(9=vo*c+WY`YX+mA1y|zEjJA}%^49(a#u4+USCvCL=@QmL`SY0EwDHt +z_xP(h={RgO*MM%KGb4mbP_l9w>S6}{L+zwK9NDiqeZ6l&v4d4V6SDG~gHbkQ0Mv!t +zWBQ*z{$!eqOIZr +zQ`id{ECeDHtiozUB{A3(@Zy;a4wPi}V_^(Rlp+Q*WhoLvjM4z5u%binvLwg7WLJ0T +zdd@2>hJ~KS=4qy*R{TP*kjd&DWNA;`PWZ?Q3z2cP3Bb{g%Y0YX5rLvUeXiD1C!#I$qlv|T@ +z6itsPQp?@4ErY6=XvcB?noe%lp&-Dm?}mmziv3lD@)f^JC&z`2@i>WR{`}Z +z`diRDFvy=HthAoXt{uo;@S-X7tn%`sj7y-E=vJ{_f?`I8pBxJYO+_k5+Id!@Hp$;q +zKA;Bm4`Eroq_LF6Wr{?MrB`YDk>+e1hk&Skxz$yn90VhQl +zJPHfwJ%ZFK7*61Ur>Rq2t{F86NZ}8!K+q;fkVv(%r-p=YbI9SMfmg25^jtv==cBN5 +z3|1e9>oVeB_aq?ve()nvBD#IQw1iFZgGef5$s4LpW +zAA`VQy(CO@&c%tAT%$2u%&`6572cZ-Z7RRpp=dSvBJ)zesm6_k^EX><7=4W +za%#W$dz@p-0d`o`VH0XTW|}6o;zW8E-;6{z^pCFKA8PCu@KJt9jK(F6z}u7(Qk3%; +zJM{d~=Ry(FrwSuw9OCH{*+5GDGX|Otokm{~T^xxZlvAUDHVo%U(pFfsx8qM}L7^ZZ +z$4ub5=ih)vlczNp_-1cYx1hpPBok`QF7v&CO|J0ToY-+@uHKK4V7155e*p#6@?-pq +zl;<0o7m*kT(qF}Ew1I$J3o(D{4dLVLP{wPDJ0eo9sXQe+b7UKXpg6l{zb5qfIJZsl +zZ*fUwD76|dN?+9;sIW--=Ay4PxkN{!6$YsYMRo-FM|u){E;=C`_z>8Eud$%UeZX*9 +zDSYo=C_B95)MRiD`y=B>!wp=4Zz +z1YZt$nk$s}@H$npD_qv^LBtnH +zg_a?OLWD&!_z@=uD%=AWL`mHoM2t&-7loCsr_4ShNKCfhKR|l|ML%;(73*s=Izr@v +z-4M)=J=aaQl*Ul>EjTcdCW!`wrHCOlb~$NW)!(me*`OnzybmJ7RCv=mj?a1K0zK_7 +z-4&s^vIaL5FYvsw7Q84`z8sJs^ZK0nC-HA6U)g$XqSIYY?tW5&m>0ggI&bC$&k +z)WwDlMFWIW6GKhGS!{iVX~m5~_L%6r!hvo3I9+so25Tk8-Pfgesz>q||2#~EXvRb% +zGgl@U#0=vEF)a{|l!Fj4j=qu(iot28iQU+)%#E>*NpoZ7QfV`m9;akS6 +z_Foy;H)o&of%u^;-Z!rF&+HKIkit8z@>9j6A?YS~uwbDQKJ1idCA=s}h$*Mf3dW$$ +zUqYT`oa-D!-?j-88_AAif2iX>({%|5>7Sw@+66?3T}P9y6$&B7_{{ps^M-~2n8WWVd<`J&kN>vOO9>Jv*WueL{$W%;r=@rWW>~>LpnGQs&Ct^5I5;a1VR8ItDHs@mvS8tQYXs<=phU_? +z0%uqCgY=FOBUR$k(!2xp%%Fm&le_EPb(Js6AXS&NW}Wlw%q__wvgHZC$ap4M|G0`O70~t*gQtGqsYtjVtBv*1?2ZeR3=3*w=AmhAp+?e6*k;?il +zsDx+sXITW&98U^=N*!%#vW@O;1!`&<&DcVe-vd)k1@wiTPCasN*hED-+`fRPP*O1tqxUzjxANOn+P_Q1b|-@xuEL +zv-Uq2Wuwy_s|^zRw0yUhv4#J>mI_k;Vm8T?_3Tk8bP;WIsNgsFaWDYz1KBd~uzFx> +zOUQzeKrg2zP5eLG`ffe3Nvs5)(D!m#| +zQ(`!600r0%j1ZRHt2vB^xA^QwEp*7E&l`luHI;1SD#B7`H=B+>aUG!C!4J}!C&yMj +zDNvU&mDM?^`^?lRc;MB~*~D*Z;P9)wu)Yzp`Y3s9gq$_DyNf2kzQ!i9H3z%+UD(GoQeHvBUK3w`mZlSYPhvGc}4Qi +z!^c#C3dZH9Jn7#*NAu4UouNQNnScHdBKwz+PW1Xk|HKT>J?_nyUM*yar&X@O2*aJI4ZBDdWX+5!!kzSI||-6n%MeyZibQ85))_e3D-fxG +zQ$X;)DWHbg)d1+D+`%i$|>fudP}q%yiShCjmm4Z +zs7uH9h2dh$&F=?SC}NL{jY%vl`=cx8h0l#}W9Y!@TW%4Fx+sjh!J!^12POTDbr +zkwhmNE;&^eJd1=p`#x^JmwT!!w6ZE~+WX+em*?HiZ+m}UMC`7+YIYR7j@x#BUfFiP +z-}CZ*U8LB4-Jkvbx{j$H{wxB0$BHJ@Yb$3S7rzZGaVw=7ZZj~uS>#6Fl$yEAnzs365vo-WP#cdzXluf!&sKqBnhoziu^FgyDDGGIW8`=Wcyu*+@G^;CRu*fXc)Ln~L~ +z>$71G`5nrfkf12?Yy!=4YCCSTxEN{Fu%R)lBk@}8rW*R5BqKd&?=eqm6;%f2181?* +z@2P|IO@pPAg?}jl*vppDFCh{?FlWTvsAaed6ytz9ovPD +zwEK}#Rkcd(#mrdTbAu(J&ulU{R}iYQzx|Q-?sHkCZ&ydW{|0OI{A !w+fqkGKSL +zjW4ucwI#tZ`EzH~iD_+T?}fu$d!&brIc(z9y!H$*Co|*di^t~80@YtZ3Ad?7qQ{Mb +zjt-RfuhrX15f=9ix_QfAU15w2Rz!>r=OT}-GJxgs-&Y^AJg+j|5UxHC{p#%8TXSOG +zC;Oj$UCN*&fNE7-L +z^+ET3o`%$q^$aip*HrDV{{ciWPf`5dYt~cH!e8;JA5ss}`{(5<(c*T2)aA@uWxw~H +zH2;G%AJSYjF`)R3ztTmS@DCdz-Jxt`6Z8f}a1P!7Utfz!GX +zIy`5XmMY9%=nKC&TYRlf+xebLY*mY95(N#R-49i#EjcW-hfl&RRwb32u}xCL%8JBU +z>HZXA1@9AP>4kpj7@*R_O}~&1471G#>$?$OQccxw&XE~-4qn`^`T$*1*_Byj)k@3F +zz0(zw)ctD@Nef->iEBrZrP>iv#t>$$-0o6J-b@w{WYYU-?v50t_`A5e*>D*Fnxqr@-HWJ`J#3N^8xD3he>0YgaA%kIqFKHg5aNnz;4q++`wVhul#n)N+#_)un8Ns-^&&AdBs> +z8^x+m-p1%E{{QC?GAljf|E~}-)BopYZD#uaTUL!Et;s1WR-4W5Bb*Bi>e?TY;E-Ta +zv4faWfxFMQ&>Zq&e#_N>FdQIhk^VQQ=o?ujh4gQjk6rU!x>a$ +z`%Nt0@~cR`1-GRvz-2)|pFKUm&Pg-^QKdj5$PPB-57h79xi*XG43HorDV-x8)Gc`@Tq?Hy0qy +zta@r$*2+Fn4jCjOg?5gI>&TQPDAVHvpQjA1?W9%2hJ!Xyep*nB{)5Bdm)NX)z{BY! +zCf5N|i=dxL)E;J*!Azz_SXfTk;mQtb)Kn?~VtgT?T+vCsVelc~G7Jj|vft3}dxpR- +z$-kW(n!-{naD`$=%*A&CokK-aOUS&+k{L9*)ulZ8P=7i}K&f-91Z!9z2-v3p(X!d~ +zZV|pUW(s|0)3;M;8V*9vjT9fptX@j*%zr!(2m8i4^HE7Ks(73>IEhEu}AJT +z6-i8Ej;*k@)WOgQiwOrLCB?Y29k9eh9XKS!=%v##QQp@R8`(Y7aubeV`&d2_>g8mP +z$dDYywzaSiV#j-elIfAnR35M-7vrXSQ5O?O)ngem+NdP+GD$d($d;WF$&Q={%oM~D +zQD-W8}1l^*V!mmZTT%7{XL7vazp*)kj3?t|S( +z>@LEiW`@(0KAI_hrV*f5lEueKT>zpawFK`BKqWEMM +z<(CNwNX8ly#-Vp%rfOi2lM$WeujkNFWVbWdfK1g*cW8?@mQJg1O9pCAB-j$$E*+md +zrNJ(?+#iX-QW2sN86&GMn@VwcDZv=po?9Kzt1O#*@?9CT{ZwNTenhaWD9#vaNn|=y +zX2Fbmu118Kms+C)Q96IXCX!>;Ggp3`^E59m#F8Sv_P}1+@|R`M@hvk?>;xKJ6oi%_ +zKOjcvtNe4nlY@2~6IxG@;~uIWlHgSAff@aKQQ>Y7J1U8=P%ZL-n_&{Fab1l>xD3ri +zbpF(QD~br#0UA0uszzSsFZZk*7Mxzje0*A@AXH!RiUkD(@evCD_)H33;Utl0MB}>s +zK3V7J-4fv=Jx07TiL$+7j_;DReNt-Qg;%M?s9#H`{PY%A?-l=Ye5-KmzqM!3oj5b95` +zLYOj(`D3hTNspr6O1%WO9t{%FA%KOV1qtx$pz55}A-w`pD`+u&S=0B32CF%-x!<1WcC7Y?>g`ed7?M%U +zP2V8ZXZ%;^8Jolva0F;SroDHRM)R>&(4iPQnz$0JkH2vnQwE=Q?&OMO5R5?wWBaT&u3PVv72*yVpCp$wKo8>!& +zlFKFBvt)4-w4Ny6Z`BBeSapSQfGUbZIU@ds=2+8S$?*hKtmS$kB<77TcLc5?x~|pq +zK@x?bqSy#7iNz&nX>pxY^3&QA0b{vaW;zj +zWd_zJBrT~(nciNZpv?iO%jgI;gms?Ipw%%97^q^%3W%FgRA0%X7@BY>n1YPeSiF?nYg;JcC!%z%i|@?L%U`icKT)sakp~8OBwpwBNi&o +zF^)?<^7WReK=vb^coag*<0eEvPCLKM#3rw+wNzeX9NR{5L6HK;Wh^2%Rd-v_-^GC} +zBr82d_k_`_x**R6FK{+rqPZr1PAN!F9+8;#2C5@SfcT!DQ0cE6)d5PT+~euyuz{XSor9l +z64SvzcDqnVq3@#Kqtjp@AQ!{y!UjVDs_2+wbzF#9W0BDf4u{QRPN@qDf$S3?VaIe) +zrns8;;Myb{QKiw@)uvPV=V_-kyQ=yA?EB7y9HvA38aECmNFxl)Fssz29KKY%4o0qo +zlvq2Y#-Z>U-=+uMgO%|(V8dhWcLlJ8@(Clg0=4*z=SQ5sb0QCr@eqRkz=Pb1^^?)- +z(jyC*Z|5UrYx}Vhf+8ckDniSbY$ck4rAFTxrUF6$110mBCk$tn3dULJ>)6{9Un+?0 +z@BE$Od+9xG5+Q1f%GON?ujkueE*Yocm~HRZ$7P?7#}pqy6_}RmtKsI~pOUN@m|r(B +zU(X1%=2>5fpTLFJPlNio4h0R!B7IGBZL-cnpVznPZZC1qw{fK16g4+(e;SB9z2=g}X{Vcr^oyw>`7to3u6 +zYGgH6ivJh5Bgkv3kH=O&r@3ZYbLEKo{0{xm4d(4X;4UkD-KH8^&6O1D^KtY?W0<$P +zAg|TF|AMPESC*;I+bPt4yx`>35Td#U&PB^@AyIG&IE$8CK#iiOdc@l5UpDhSL7qNX +zRcx*ENSLi3-6gEJc7MD!Z+pL-bo&6ag=~M`pM8DK^D4e2w?7}07~Z*f*Epjz9clXK +zY}_4Pqo1#>`M|p<9xI`_C=KG|-BSftyB^u)6jcqqEFO((T5?G)e|NDuwxZ0s%n5JC%xk;GmHMy3qICnJ>k{T^@(C)!|KUm9zaPLp-s#9#F#Hw(7e{!R|w=qz; +zo^(vulT5;W+c&gk)dz&R`2lWw7p(#Ctg+Xb5%z$G$T#!ms#*tjP#@RJ?8Z(7SYeSg)=D1RP!zpvIg0ks +zNg892W70sKd;(QcL8UH0s8nF5)PAYq!qu=L(|( +zZ`gp5Q$3f)8EtTFr{7B6>R%UrdZto`OG_A^2;PO_6{Brb+VW@)cRFtvCnX!_ +znl+J8JXJPSkhyd2)t2p4I34ug#FA=qWhPa5k{tqgtD}u{YP2OgCpe$?>$tbyz3eWw +zKfB=ZqPv)RUI79=5bQ#naNV@jb8B%9rJFYYZUj+=+BTpXr1|Fuj14zwx#k;1L; +z1G{lqWb_tE%xU@gra1_HBCYnA-@0?vMg;o3Xjm~$9fL`4{9%DXzm2%&ZqO@9iu&WG +zjv%_+yO*7ksSCbSM-OtY*dO$=xzFV9RouI}(YYWDC4Cio+Sh(MQS~kQhc1?iATi{X4NY}7aSp4S6 +z_cpn(eNfTO7KHSq)C+3eJ)!amxA=ibo8~+snIeH(&w%+#ANV8=_-dV9S>O3hvz4J$&C8k;&VTSD3&$ +zM5Nlnap&aAY3Cq-dc_|kBa#%Ww?}&IA@jaG5P=lS)f`Kv!2icxp;J=s&|bLN!La%X +zs0vmLWqy)`X_0Y}6I)fN3T{?XQ_@_o{A})#Hu*MUP2%mxXz}ZVdg%pOm-ma(B@bmI +z&R{d^b`m!KSMGufs_v(!s)d7*f(2*zRdg5SrV*+xZ)4Kytb9h~?s_>)(H_dK0IuPq_x9Smt_fO#lza?72(z%ZoqlYLVK1XmtB+bT$M+QHvqT0YhRmJ +z$&-Eobq}7Idwq=c@rtV~`S{OaZ!_kFoD3s>2C>FfxN6}93VDKXm$fE5!w*z5&Ud~=MlN}ktVgG +z*|UmeCB;_waMEG(xmb+Cdv7ScPZsjt8=S3yE-j9h$FBO(a|e!3`R={4+qmYVbv^kl +zjSDjjZ&$+;!}TZPcwuL>=7{Ol%@M80`u1;$+9J|~?Z*cMlI1P-MKcSZ<8Tg<MU38*cWd4vm|Zn~7w#R^Zeyazj?^iky=aj+0?K$B5?)A$G=I +z=xk(!2HM<@L#e!(eZ5mXNR=3E3aPR%B{42hid8XM`7I9DXAZcvWRYp_@V=GqM${5= +z{RV{wpumg!RCpxy&)}5?3#Gy(`E>mLzL6|(a<<=w{MoW*Wyt8x#%Q(DWt)%r&NsUA +zH((9|p}WwOZwwT1yZN%qcC%AcNsJfw#{;|vdb_gN6~@$kGa-IJ2!aF#*L!?6NE{m8 +zM^E1q7|a!h_+m_m(5e|$2d(S6D)2DNu)5xUb#t|wnGA8}5Mn%Tx>x!r1Q!J_D=~|! +zL(QwcLJTT%?o)-F!3V!d`~s{myoZUc_60_qD}`z2%SzLys|%mn!ak2LTk((Ut6)C>H*i1}Q6{>MN5i&aGISUHay| +zU97yae}hzG`g+5!;M +z9|k_T6zS2z7VJ}f%CZ3s7}eR(Q&FYS?CoZo@|-moPCycsNf9N-n3!n9UV?)9to#to +z;_h>W(<)#qYrYwSRuftOZpU$WaqsfWpPyg2(D-7;;b9EhxGA-K-0wOztG1G*aI4$ +z6Kr#c8%gvRFOReM!T)3Amw|zS{{J=d%gFvO+zUMV4UdVA?f)yEGVn|`mj8Y8@I}_- +z6eFj@_7kKhLPx;-pe<;yst!1v9;}Ip>7T!t-&fh}>DVE6+hx&|dAlqc(?!#$msXWa_GO$Rws(_ORx%b^VA^`4`fEpRKHQp3)J}-a0pn` +zPe7@gU>&GdNJ-=snhC)cg&`3unTzbpMJT6hm<>}Y3XTIwDyJE^@7c!1jwi?VF-2%Z +z#4tB0Cf5!L)oB~t9F)pcI0*^r)#S@29Js}}Oj-d-=?CydZAp~KM3cA}A2e{~on+ly +zZ(8{Zo2Rs6)e}0Disa78ir&tTns0=S6E5&Y!Aa#~)st1_LWL2HxfIWe?Fj<7xNB-^$S0PpwKB7N=HS*C5guN=2H&< +z9H#6a_|2;d7gAyMnV*^f*!0iRQ4Kw~GDS$~-fuS2 +zul-{6nb?!`#xvy#s~WjWiP7W%TY~XM)HB2JQdqE!RcuiTKeGXNyP^0+=E-FpiDOj7 +z@3)D5brP)_FiIe=1rO4k1q5a!$Oozb*x)72Nsfec-Lj<#r6LxF<3=VAeLK|e+ +zwcdrwfRh=H;6)PxnSP?|X!KkCM&b)S9-urLdo}A(PbsNgadl(2g=9gN;`ys^1(F-0 +zS8awcQfmyx_784ihkQmuk>^3S|q!&JrDo~Z)~?9EbGsjd;?TFyuknGA9O +zVwo^YMqq8mCW(o-%Ad@9jL)lMpWNR0Ha|*5qO&8B9LzaXVL~n8)vZ(!@-)6k#nSK9 +z%^X-gDmqY?d1)jEtL(UE8pn}HLn3*&V*tQ5z!=|)7stheS*oQe;?s-g$pgyz7{+$9*=yIb6$}-|s!bBA +zpxc|sd8rjLR%6XD7H%q79?X@C9>n0P#OoYRH?2kd3elKhIwjDGPT!eBk^zAW37Y9D +z`Tl0+QZ(9xmx=WhT}l0gd0U&f+4+EFKyk@K2w;;*;$@M=XVE=lQ0>ggQc>VEsxoR+ +znEj~~0j;*Ie=UEjQpB{e)cw_dLeGgTDMnQ7bT~1`-4)}fZG5^J28_A5SIw~bAU40d +zr`_yqFD#=*%jFUl-0>J~gt%Zv9-P=?*6sLGSq0CgWcop(E`6!-!?R8?nkD#2(Ka)T&FNsCEVYrc>=k-?y?Y%b8)dQdJe|$K0_H27Y?DbO;iLnHg>?H|31Tog +zQ~GGkAGNoIcG1kn(s?)-e~AaWxeDnhyVUq34yW^sMsr7J)CPyyp?*>8vDSU_urYP% +zCGSOarg;k$`{?8&6b;d{JJrep-XZ6oQqoiE87#r0?3M?H7L=qv^%2r|*AY28w0yp@|A?h$=Eo`Oo$fjetoop}#w&h1o#D{RFg5<^g>d(iI#=*mzi-L5vPsJnq`We< +z)AZ*obN&>lisnf|+9C@aVD=1No|npMHHoBCaC{aq&b$H8wak+xofas6nH12J>jDu{8ynDcYJ@ +z+Fo(|>IfJ6M5{{9uLihz#3U(^DT-ivN_1++W|l;Ys9!3YS)G_m!4~+MA*6)X8)N+z +zmWt}Y0)2E6$%%(mn4zMHhm^J7LQ!{~eNw+Ms+0;2stgSVO&BbY+zh?OZHGP}C>UdQ +zwq>PRLo+>LINwiD{O53l$PeN-s@%q+lWJk&+`^OmP-)`H$^0M{;v-neiY9{ko=j&A +zxhD1ScouBb+BJ(bh>9kT3STvA>PevTErH5kqV_zgvE0vW3tMC{nmVdzk~amZq@J$P +zWa=O@cc&~voV`xMb>thP{i!DGTeJlnC_ +zKwdD(G)8?vE-Fofs;>mS0`Bn6xXPR=oXng@iOK?1Q-EysXktsl1PM^69`xdw*6&`c +zrU3XzW`D{7Yj+mz>;o06g;G46(U~}s%o;MTE#zu2moMOQw~`kmrAla6J9IBjojxlu +zGNw*WJSzH8Rs>l*P~kyr+>Mj9QXU|Yr)7FFXWr-g%Xh%WOD4)(MuK-NhUBH~Xj +zrwaptRK^AS)a42BAoxeXB3C!gJZN~O$HbHAJ+5OS@Bn*tsx@WCJo*aXrPA_TbCAho +z{*cx-Sk0i&%2}h5hhu@B1!Lth-wLo0FV22nn%#`b@Ixl)htiv;)c!#95l5s#6dU3U +zmQ&l$!{TkOp +zf{YM5(t%JSitCv8%|e@ts+5jqii^};nE6+#`6_)SDPYeKU_IQx%Sb&uEXB&uNpXa~ +zPn^1#w&N*&mvUJd5=#>~OTF3gC2|AO(J~$>VL@7I&h| +zj(|_wTQOAuxuK*Pt$23nFN{lDNm=)g%>jd|O3L+8P3BVV((`@H=_vYOKl)&5xcYx@ +zu6-%X-=-A?y{NmP%ErISuUS^=OuMFqVYAhcyVbDs?uK$ci*qS~bBXhJH^b)0eUw9R +zdH${d8b%rCd}(p6=9Ry&b#>)BoYBR8^aG8WR%%lgXVd>8Z#Crn9~n_n)njf@Za++% +zO_+D8od3&M{=YFkW^q2&b8fvnC!I{;yp7_lXT|8I*%-Mi%NW`$+2uvUJY=2RE6!NE +z_U5N7FI_;^c{>cd{I`>AGM6jBPWCySZ`fyU)NcNhAp%f6a5^->!N6{rSxK8>gV+QT +zi+Eda+Ti^pb+vNs-TkMNz5VEmsbSr;HJvqTMa^bj#?G6YWdm0okIMCe6c9{ZGDo_U +zpDi1hbZe>U*3aC`_1gm=>$4u_hazcBhR+lCLtfi-n`HAl!KMIUQf*@jPUA6g$&dd) +z*+zufY5wP>0<|nM!*A<9rzf{2SS56>!L+ETnd=%?C2c(If16zuUTz3`_W`0%DJrW^lN*RQ25&vg%L;tmhJ*-Qt|Ja@5FyjW}KbyM$*+L5PKb$UhvK;-~4jaM| +zsy&1k*V#@(9{VjY7^+pAAzWZQ4jZj6NoP}p)1fie_~94PYbK=^A-IkyAA9LtetyVw +za-fhBJ$&Zh!HO7RiH5VJJ3;ZyLx4Zvi5yI!figt7!T1SW0d@y%cMFWjL`_)KjA*?I +zuvE=G3_qyUclOr0{6ditCki>QG#(X}jzh3W*h)3DQc5dOH4)l=3Fgt7X-(w@IJogrs_6d6x +z4<`^C+V3?klsB!_<8&wU6lmVkPdDtjL37_2W*ZORq5hd0=2{OvLU5X-Zp??&W4IbC +z`>L`(y69|IsE#`09L$WX1ah?OxecZ99;Uf+O@|H-bGhDjkU@r0fyB9~s(iRcang2P +zN;EDHMZrxomND}jxPdm(aOncR{bt;3{mVA}?b7pY%!zb1!s6Qq^0zeC{|=+H>I)fg1O~2qW@gIU2n_xN{Is2L$d2D`c}^;|+Mpj_#j*8#FH-BcSz~qfI3K%> +zV$dd+j4i(_Cw86WB4^wh@S{pGxlD9}Y}}1{>(XyiJj7ZE|BwB;jzyYMZ?;_h1hlUJ +z+x?~viFXHVx5N0}CO%`O@s8gy=ok$?S-R5X3;OO0ne^z1|4_6x#P>3jJDb`2sH?Vf +z%)a=>Y3VuZO(zvlIdm4`K)@m1&XyyC&%Wj66<%$<`o~_T_(Z-f0!bB+@iN;O5EdHG +zV(7|4sCz<#SQt^`iakLJ2WaQB(@*c7(-R1AEAC~SO1j(?^+t2qGQW;=ENXwYH-1fm +z2{2Wn+z=BK8f*e;5aODSdK)0VWsR7Ag7*qke +z<~6y!b@O`cme({RiT@g_AcZ?@$8*%z=$^y77Omoh%f_$p#4tK7uQ>xs1gG4FNTZyu +zW`d$hIwK7@jX~n9zl!Jo;NGaLso5}1TU8jgcq9#Q^!`1kBkIoTI~;!(ozg+g6obf( +z5a3#*Bm9vm=S1!G*c0Qngd^)FuPf*^%{TW@n*eqQw6LnVpZ@EcicH +zmRG6XMO{<=A6TqyO$XEij?|A7XSMU&Y_y+O1U*S7s?gwM(}u-8Prg%)D-kspGuzbj +zx41Jez9*{K;11-&A^`_%me(XMiG-a^#s$5%(A!is2Vh;>WVJP;^3hSq&CkA?M$g=jGBAZmWi`+YSHZ9Mm&(-P$fYDm)zwvh2>Nup(M*SFHryq4X}Oks_5wR`q}4rdSaok-KI|Yf)&*4TP2J)i*33zc +zJ?(~V|UeikXz_?0`sg$S<&d1mzr!YFIdQ-Tkv~(Nw6UANI;=ZKKob^g; +z-G@w)(GRzv=EcmTmS+26VA@|BXE&Y{l4idnAeXj^lX`QTm8tfYNcJPeebeFr)?VED +zjHB^e7R}E#D^2a}1dn}|#|G8B=1Q7rxtI;e9Ln`8CvkK&^Pk#X8F{Gj0WfKLK|%`x +zZ3UuH2WsPw$?hr$-j%!a5+@q4_ZP0bU*oh0e%z->IaFbW$h&E{x2e~GhvH5j^dO7V +zmpL)FAM_y$vNy6{Tb!FPIiKy*b8UuPd-RUW)1ut{5cCvZq+j>9G&z5FvEX6hWe>5V +zw#$8Z03rQnI16VVzr8W7oW`8LJns!#xPnQ$U~?qaAT$t>2>6XcLFKa$p<#GOUrYI0 +zD5AyE#ERl_w9Xxf(&KhA%|!CC!YGiHi7-hpP5xbDMq{Y|E;dz*>II$B&f7nGH$!_- +z#n`gU*%tSmvxhSJQcuSVTdG)Vk?avy3lS}OVbAY6KgRH+_?`TZ!NYzaqY#m#^`-S) +zZWD}%dh+(reEOFlPO%$^Aqf%$C=&z=b(I0Lo4Hh@^SS{y+#R*Bsb-fc`K1%A;cqIl +z$x^^qtc1Sv2TdcC1d`pxjDWDE6pBN28b +zVF)?EWA*|j!i#eK{h?DOCHQwB{4jvukl6BfK-@5R#rZ2?MHEui;%)i=kt~)fmI}d# +z*SwzZBU6M7`VI@cVi0giAJIc}i*UaS1&Sel{t<3%tg?j`3Nk~~5hjFU1r;OoW%^x~ +zD2Djorw1{uDAK2n!rVg6tj!U@v-mLueiv-cETGswgw3*4Q!BDzhUwFPimkHDkV)Si +z{K7m@t?vzYXPK(o|Bj86iv)rVxk@(@%+CT__cs#Gi&?5cKOYW`g=u9*PcR_rdXa7| +zc$OuyNxvcLFMxid0a9=%Yst(afDy1o_b{}w@SmdQWhi!m?lbs?HL_d(9jqT0^O0>y +z7Av3s4@?LYxGeo7rW7OOe59W~BSeB<9BibK9uZgqX6ir>5hMvcU6`LZtdxNs^8X3y +zMU_iEBj?v|;5wy{Vw8L0+XQoF6h$Qo>!XrSC4s&haPtD7*ogq42n&-`3aKK{cOz~Y +z87M#ciXWvWcH@><(fV%W4h`d8QjzJ1vW`ctLAcn&IN3&y*woa1QFW%32?H$RN;Qlg +z(bBvI0}c@8Ysl^++!B$o{Oj4`=Glpk=$CiFXUFPb?-VpiM?Cg#I>usIM!&(ucc@t5 +zqd)d}E#AF-J?HR#-M8z0USECPj$eIU-%WRaH2b_A6mP%Z{r3L+eYfpKormsI5wz6j +z`tgat`vp9L->-J3%O}{UcX)SnWRd_AB +z7y;P}op)vFmzO1AyLKoGCJ0wS;chKX4GN(7BK-atL%n~YXT-!N6v&aqnXuszUS3D8 +zZPqrELdI>k6wiMmxf~q(Aw3LNrX=9rwe5$9DV@Y(?a!+h58?h_F>`0m{kn?oq(NdjaxNs +z$na#T4;uJOF&#`4bL2BA7iYwTtVu +zHlbP=B`>5$nCvSpHl6lgI!A>c343#y=A`^yIFPq`HSlE5q?`^ySB>;XIh3Y-ykR?^ +zzu1#A-?dj#d56V@_=ebq=tN>c`N4vW5%mZ3j$#uTAi0OQg1HEAMpZHu4RhkCh@(Rs +zDiImKHQ|pw;%m7>h5jlcxXQWX0&W-ZdMV=St*-x}mALn`4-Q}8unMhO@%%yCYpe0Y +z+gWmFg5t^Nxrp4)lJC7Mp~o8Um$mWa)zcqv8^ARs8z_bnqUd{e_zs3HxXjRNC88fE +z%DX_wjw&g5cLctjZ!*}2H;llJR=2JmBHPw9yXI8=xVyW%B)Esc-GWtw{+W`99~+1F8rAJY@|vj=#D!>nkoPtDZBxWr +zpE!hDb85;d89oVHbIWp6@6Z`!wVU6M$2H;8+^0337r(Q}T$iy9>tik`-J16rF_zTu=#J8T=(^f;ry3)6gJ?~KVk7hGDYTmd`>d$ +zhE@=PPv^npx1{qO2Op2R+JsZ@jLG=6BM<#SfPb3WcL#jOZ9(BQHf0TmuXFMvgc*^3 +zhG{tzfHsi~{E0;Y0vrkq>g7T^XieiiI5)~6@-Ffw@*46I@>~ToqEibb^cTyZHnm70 +zU!ku;+txszOrQ239N$ObN6!}K+h=9{g5jH^Z?=g6U5B$rNa`rckvybp`gRYrf;QhU +zATYk6V>VR$zJ}&~$Ni48zZLB#%6AmsO2Xm1C!U6i{cDxw_Toh~r-x!2J(WbC2mbjD +zHRI=_H#Dt-T|)(~TX<7TL-$chwWsXx&Oca&Z~kH)DTPbT_)A8B(>I}=H(rZ%9$Q$; +z4-uBrM@VxRQyAkI!x;T_?%E}#0{rDws)eNvOYO9l1Pv7n8a1~LgtNtcb^Fe0%g29A +zncmR2a#a;bS7~VARY!JvvauaGDsIx@h|oIHADMcboaKJQltl$tgoJPR&MfsOO5B>C;Lw7PYO>GPl8PXCo(5|C-f(TCx|D&Cf3G*P>{F!Au(AaF2q(05ROPXxPOECRYpXso^!_9NKFw)n!5WD1@+9(}48-ip70i_wuy +z>2g?IOO!L$uVe9rWyuy;ki4evqB$1k>u*H@UYD1>Fc+gkoK0VR7^WR@m#0hTZ_D2yeT +zXPPur9fU6;In*ckWN^K#$7X_`_7KGh$vYYt;)}jevQONPeMiP>QFxkDn=FK7CpVVm +zV72&~hH8AI5 +zmug;8xF7a`x6hs!U*Z(2Qx57R(x27p;Qb1TdPighG5%1Jj@zL7Z#YlCwx%6^>bVUF +z1vtfAhBk6hMdToulj`h3SWC|Y!aCN1LfAz#S@}7{?GM67e8!&(GkFa7)IMibnzji0 +z?3Exu2rE=yua2Xcy$I@9<~b^22Y_$G@3w(0!Z)D32e$c6!K1XDej@?T#ro_99**_( +z7Ji-f_iNB}VkY8Kh|Bgd+MIMQ4dd85#-vc%aTQTDR2{!E_{?VCZ1~fruaK=^neacG +zz~bQN8cUaz$L+u|vA%u<2TLG&D3cNU-lo+RfQZeQxl-+H)x@q2)(+jH<=YA!ss+|S +zk;T4d4Ziw3)Zdx2y8EC*N+?I%4e?#ew;tN+l??5u<=X)5srA7I{uhJrQgl4cT7Bkx +z7lnECbr*O&w5XPECG?>tSOvvK|6vAvg9se3-q#9#yx!LuUccVg5dH=Wj=O%du0dfG +z3#G17fXR0nh0&YY0z4Me`3zcJ6PN`JcF%)sZ!8XABShSPOeKXAL5J_67aoF$r}ype +zns*r>7xKe{_pS0pfgi8*g@z}t{OYRa>zBdCF@PmXvPu3f@xgXn)Su(xhS +z*%R=4WX521heB8P^?_be1M`N?RijlbFa-B)yN=d;XCa;d*79pySHwfV1)`BIvk4-U +zE;SLgQVYBlV|?)?L+6or?GY1Srx|mm;9^jZ+Di`u6O* +zd&cC*ub1-OBCh4%x34F^Gw0 +z?qFZDfd@|)%5}O=j8MT(cG2LVX!1eS$#;$fodrw<1fQ=YBnY1`-X%*l(+FQ{ebbE& +zdHF=Rs)O;9Cmd6eR$@3fC{p`GIF%?$I`e=oXw*5x`>Vh0kNicQ5#DntwYtn +zQq{aKq`&IojJR@~UcnZ~FTJmqP;f=pf*lUW-wz}2lUTE)(3d1+J9XOpYzx)?h6K){ +z-fF(ePoP)#i%g8-mR6MtS`YZLtQMCW+R@1$ehJr2Fmg_z^0v?F99&9xo1T-8_)E#(L +z9uSoK-INCo$$W-9!9#2%V?Wg$1GaEORr9Hn%z@2JiSf*X{tTb?jEC9`ojgPZ1zf8%`RRQGFohGs +zw(ni*1gW+z6RK;B$l4LS9~ULmiv8*HPlA9Xr%1|?qf5V%b;#K!*kb_lk`G~{C;wLi +z*R}d%AmXCmK^dePpyDBOmSFTCH-m0-*-j{3pB>7oeJQKOrc!5iv|L7SR;=tGe#)uF +zd`)u#sFLaD!3~LJDu~8SQpk2A0CQ}HV3+nC(rH_~6UgA}M|YcEK9T}K{3FqFIUNo^ +zlHY)lRLkW@nPtn2oYp~fi4((gGm3@IdM%@Z<}5*3NZ`!0@Btv*DQtAIYN+G6o+PJ8{1#-tEF{fp~u+$)}ko&7KP2miO$ +zzw0+kng6o&P2yYc4}7D)wcpC$df%vTE$-Jj|DpVWZ+>{A|KWOTzuEH!|0>MPI>dkZ +z`L7g4tQ_3`N@w&>=f0WA!o%{Hs5fzciRNbiOZ8j-&4jn|FVTNg{9oXo@qZl6!py?) +zFMs^;_8;H;@!?+zUIRhC;olVf)7O80SO4Pr51#&eRs6T|Hz|L6`oH|~uL=D7WL__j +z5x*6VSKV*$P47P^`sRec=zpB>I`(ZIZ@53@&t(6n;or0PpO*UnSKg}?|5#1`df)n= +ztLdMj-<ref+^tbwL%)i4wo8=Av +zNA4T^=LY-xn0e#;!|^8jwf_$%ylMVxd%Ze=P_zt6$H_sg3L{u=d4`P(gTy}u^@>c~I*EX@DMk-+h9_Ot$Ta&NomPx>=) +zb1O$t_3wUGhg#UOU?edEI^;9==;lA7VNa^tzfx9W49T1&<}iY?Rk +zBb|YP7HBSj0^hdhzs2t5S3d)qvr+ +zU0j^g-|l>1Q(T=Nugz*-yUEb&nk!yhf3Y_j*Sjf5C8HvJrj1pw_}*#v!AMdhHssQJqdGB7^O9h3ycb0KWCQ +z0JWOd<4EU{lZ;@%3wUod>w@MYSsP>EJ(efQ;9^&2eVq%91U6p8eRrB{XxaKg`qo1W +z-VC|IL#T05k|c6_#~x3o0#b|pM#2xI4AVQHBU3eIKC^V8=@$uXpRVSEA(0=>8iM1b +zS2E3MUD5oZ42Ccxnaoslh97$Y&TDPSA%Ynv!bS6ylgxx9KRz7j8tzaJ566D-&!%=y +z%l1j3Y14J~sF;Dsg^nv8Y(;4)M9jC0)0W+F(j0$4kjgIjneJH2@hEovB8a1B-0(7P +zEtxBN-w}U_rapqa94LC9LA9k(fAPacgp>mC*Ym4`mPXCt;Fb7No14-<`jE94DH#;| +z|9mc)jdtyQJP_o=`773t10#aPK`A +zO+2fqMmA*IjO@p#m1!&LY-y=BIS%|5gU1@q;Bpx~3_h>^6|KS6#+IMKZM`2m0HTsj +zR#)b3CT8M#z4nmE$Ho9kI;_-SFo~JSoTW*{h;v^-{5cC+&jA1ly|~S;cOOWxG0?1krA*!)~m{WfBy(jsKb2? +zE)1PKvtxk+%Q`<_m=$l#8DFfZn-ecKG|SP5oPV(pT!TdwT#CZ~3yy>mjyMyeI1m(E6=IWXf4m`REL$NRl#TZN(#30U^izxx< +zhvtSGZVhX>_O?-_9X%C{={vLm~xCBjSX|j$y*bJw!@nRPO?>KGE +zSK(c!A~!Azmor${R~%0LjToLAL5UlWp>Q1M-Wtynz*6${Y;L5=8RGzy*S+zR(FDlJ(R4Y|j$=H6j5wKCpju$+pgfli{> +z5=9*wIqOWtN};(U8iqVOEme%G_)o4+XYKJvI7(1HK8U=iAG#}ZX*D;^L-O5Bq9759 +z6a7CM$Ei~2G9;^hFy`=cEi+TpC^AdXoY7H|MntdTmnl9r-S9v@Ov-G&4mU+puQQWi +z&w+}G)|$~#Q6qAiZQQREJea0cbDq))TQ9j*hAsioyQNMA{1k0!~n83r-;S;56OnzSLaWvOp$*IXNQdt7!;;nqRLD^5_?%%bSHVGk3E7W9N +zjMGVz+v7{#3~m^RMB}&#+4`PUA$OT>YmMs`0u!b@^eyiR*H!kjNUPtO+3J$KSg6<| +zsL%j&l1B@3&%V;ZKnX>h?e(=kwHDM(4h-s=NyF)ct4-|D<7Com7-P?^j&Ju +zst0AGkwNL8=hCX!=CHg7GbO}WpZ4sBM3X6R2yObFN26h_L|OV;Y2gT)%$(`F2ZU<8 +zfaUK2oow7N5~)(l9E7P#>Yr7HLFP33qLOt54K5lg*B9mf)AQ;UCB7IciZX(u-Xf#g +zw<_?{CHU5-X&qIJSo2l#S*GeZMB5)e(QAAOt7e(j=(DSETW6>V&emYKaVT +zR*@*V0LhemnqIJX7N55oLzm?Pv2O-rVW_wixc8cSplNj`JCqZ{FZ9xu^#A^Z$yAd6 +zk#&CJ+!t2N4;Le+%+ybs-icSHjIkQZj(p$2AGfsJl>}}1*VY{VOko}h_?d*6R@Pi} +zAik0l2Z!!Z8lDTVB~1}eGj`FIdIN)*mpYkj;q^D`?4qtK7E}`{WUYOTh!`<;&5$pj +z?53jF`XahB_80Zf(1!+1?8N7Ov!oN3NL?<4+s$s#AMCY(YDil2aCO#Dh46d2zLY;y +zRcbihoCWRZ(Sk5( +zMq{&Og4uGpb%I9#R?)xNX*i{;J_cU_9Hpz|gOO-R0ktxA#pu?6TImT=u^MzaKxy1> +zbec~9cIgRXu{QLNH2b;lBo*lb^n!6|W+baLgJbg4DL~RRs*;KfVsYqHQdQdTGth@} +z3u6t7&}DMf=|QA4n9^0k!FPb+7{hXOhulO4u>kZfK&+G^tymCxO>QDhfLbsPKsMpG +zC{4Z;i%KvJKsG*GJs2%FksKsSLn+Ck8*B#%jWY~I7XzS6vuFlG(46OCQ-CCC&U3Lz +z#LCfm00;?PWFTgm>b%c+Uu9U7gGm4g@m&-kVw&pQ{#e6IbR0mgOcW&uj0TV=8P!E2 +zR*fzN;Lfd-F^K7+4G?=@gHA~k3c$`Cm&uCx6!lG}^Y^zKX*<#2Zh$8RC;@;U{hJ8j +zNdj8UyVVXJ%e_?&R>-|gK_`+qi$eE_`z=C)Bz@+Gej;;*MY9s~TZiVE9+Z)Ln}dEL +zc?L`4%>-Hm;79&;0kl$pQUH&t!CbknI>D=wXUXUl(r1=5-V~tMJX?U^guL4TbS9~@ +zY;-2cvsUymsWS(f^tj)q0DdyiB!Hg+6a(NV0eRC9Cj4fhxt2OBM30a>t3*eZI?F^y +zmbB|Y7XU0#f!Y8|WT0ihVH_zXh>#{5utWh$11yn%jsS=8zd31a;(iwZmPkP(fF*K} +zLT;mCFkWt>ZmII2xhh&+EHouHXAW$k4$#PYFmI=(Lqu{T9YBgC_Swa#Cn%%1$o +z`N8@pViKGt5gy<*B)F!;)JJ2~!8){n0apvFe)`XNigb$bP3&kKsAXY@jF4%c&`B-G +zEr^RF5E-GNY1AapiHj-D(WX(#NHpcH?*v`P{ZA +zO7%gGY^+FBsqp?wwqZ8fPfAp|Tz#~ky-KlmqDDczpDRhTKNWK&7y43Xn4wQdX7gvG +zqVpzD|1d{ep4czOPR(gXLLEZQ#%YFXMyv>fGa2-&pWBx@ +zjyhm4RdnEsEU7)pe9^G@7mDi7NlE>pUqX!;U~mjIWQ5&G32-n5?MU-cPbhe^n@+o9 +zAA)yfvPG1ykq5m#Ub1dCbXw-yA<|rQM=Hrf(n=T6JtT?6bTuq0wTQyLFuIK(YtWjPn&n# +zTZCi_5|`9*0-r9KafnFWBX_~GAA;QbF9ZjdWgL+wmPI{`aM*;a)O)4J3A3pubVOY~ +zEPr(5o3P1VG{oVqxGO{7DiCe>JU=4Jh5Gb;S3Dcmrrq5t_>}Q?=M4EhUQn78edjYC-Xx^+J=jW>{(KOM6 +zpS(XwMUT*VWv3M=EJE^Nh0D-O1Nc*dl7G&8cwLRz?qQ;cQ`PRpgyh9!V_=F5Q5l7S +zW{49O`J&uL0t5~c|luk +z%<=UYwZ!q9xa=9)+o&U9dF#5sozFI$iqJSiM&VxmcMQKxn*#+YP +zV7L1&-a|cX5`RAWVjz=Wn$4}P;=N*`$brOC=Oe_ +z&j+A$O?)oq`fkP?6=H^>s5yn%HaRJ5 +zR2skara47UK)>u4Qr74KKmMyPQ>ZkesXyI3Vl0;-B%&dYy9b<(D>6HvkicJjkKpH? +zkvx$+VLabIPytszU$dMOf%`xULLqfMgP#fxK7V`k0JZ=#{Ddet8ebBpcD-S5Ax}Nl +ztmlw?ePCOmTZ0~LJ8i)#AUnWy9ZH=#_OTD1Id0X$DR1b)wQrdG60&^O`&~MqTHm$$ +zp6?iVj7}Ur^IX=93;BEZ+66zDOY}d*=1e^0=5#(m?H^0D_WAXJ*`5e`3clxu;I|T* +zeu@-0^d4V1_68E#ts-B7-E?|0eMKHT7N6IhGXxS6zh5$5Tx*}KpYZx&9rNJ4XmVq- +zxOcqhtL2vg(E!E;$u%$D;seo++6eAc4tr8v=A;Mf#c&znXPH?cURr`;NoA-5w}=7U +z0vZGJfD}Mbp$qEoqe@0cJu{uncHqLA;HrC!N6QuF&3rTdjYhNKjjHb9%I|~ow5FCJ +zmq6Q^lgs54ulkXt`uRGymF-E+la)-0En*GibmFQ8p!?;t>R +zfsn170Ts=SgDxK)6R?;r?wpw}R4|#&7?#_58VX&rY)KB` +zgLm$>Pttc%wD=dfOmD38#O#_X5YkNj)BLA9c?-;dU7cod4rdxh+Pbsgvl5H~4q`eF +z+Ram&ACEr{_HWYbR#S&Gn50EH8N@U4T!3UjDLmDg{BCO@kUm_e6_8hut&kF!@ihph +zfyr4iSYAWwm8IGnIC(urR2E)3k?R8t3i3Mxd&iD>!)c=$gMP6Q0LQ%uUOh+JfdPJ= +zCN7OL%5DLkfwbJ85i8_rT;_*xTLVZ9BB(@dNIHSD;2}S`yV_kf+^R>cl|0$3Lac&k +zIdgKCEb#>LQ}-GNc{b!DN9i>?CzrS8WK^BJGR900lduQ?8W_tQx$e5P@LhDG +zOi*~$RQ@Byqk79L6X_X58etLBM^T|2X7HCgb7V9<*2MXeRM38G84z<#HWQv3lAB--!3shik`n^Y_ez+m5@{EV +zRG9B8?Kn&=1cNZ!I8-ULJoqPJvT?8}$d8#w@4)JOi3-7Iz)JjL{8WI_`p};dmBFdN +zhro#{5elK=A!K|(KvI2@O0Y!aVaRO=2j6*N=+8*8;CaGu%pCV9_7#SOU6M_f$6$ps{Sq+Zy6;i~H +z1gH;$Mu4dHmDMMX1kZ&u2Z9k}NP?#dvqnO3gYoG@mij_7LsA0YVS_yl>w4~kL9c-s +zIpK49LvbT`LVLpDLp+0ffz?mSJz{ViQ +zz=dGbp}k@FA^8#cq50wX!4F{xVF@9x!6P6dz>p!4!I2@5!EPW0fL_2hpa5_gs7nlU +z2%Zhp0j2>7fJZ=^HO@8FwE`dma0Dm^RPe>~!}C4x(*ZgG>wvF^iEoKtiEkP(4)|{; +z2~Z4(wDxHYV$D;Z?t% +z!aF5OXPqrI8Fpkal3?W7)|wBQrzuTyTIczZHpXZWQO%{!u=u_%=E#t%MoS}Bpx3)s +z_sP^7U!M8x-$$(p5gG%{Ygwm^xgdlyU+4*(j}WJbwx+XsrR&su&H#i<}py +z(x?DtR!a>uOA`joa%f}3+foS|#MZCzX7`0^be51^^j*Ajy!_VVM`x+jd@4gOmGb-t +z^Dy;MX}z3PBWGjsBh_#ecy*8NYmUw^Cfl<0VoK2i)p2Q{(caRuq53K!FVkZQui})n +zzIvl{CVedL62X_mB_w{Vs*ox|M&pF4q4_vVrxX(Rt%a?E)Ib +zdlZl0#|NRS5c1W}=&oQFs8Vy +zhq^j&JZ{1`cwLFTICR`AyE1faB#`{nGT1)Q&SevErEzSETnStCiO}HT>o5Lr2~EPl +zqlv~VxDoNYzIpG>0IaQaLxqj+?(t8l0)4t)6i9ErUEd+tGgT$bGtHMQfnUL26AB{N +zBp{qrl5@tebVFkASk77S!=y?dH7D2w?$21Yy}a0aY8D7c#!xz+BW +zK2obC1`qir+3Eh4o1qJTfI&=NZ?erk^VAtkB^10r#>v018%eXfE$e1NC-6Sd-`~vk +zZ`~bfSan~#JAX=M>LlT9*8x$M4(fq4DU~4_kL{L8|;B=N;i-S +zHc4UL`@YwFwh>6%%x<1k{*!;U?Q#13a(1`)mg89H)&`;oEJXoND2(w}ll@(Dp3%WL +zp2_z=5*;aXM)f(j(wHshTJx(7DpCM}xuytG94SgazT_fHu@HE7M>_7>2Iex!T*~R` +z7PHCga2PcnOP6R&;DrgiZU}L?k@VMlIlfA^cx$o)%qak+L$|yVq>LCr^&afhbonYI +zCjHdq6_5VJ2-MVGn;Txs{02ESe4}0jdfIAC6BDHUJujDv7$z{ES}vYZq%fgX%h}uI +zHqK7zV3*y~D(4msv}0A%>RaEO>Gw>Ql-i}pYc41=En_JG2zY|#K@1L=In)kTSrcgu +zJx4NEIG$E8fPLTq&4%e|w%YmXj5k!c49>}+5>1Q(J+6?T@#7o|)lR>k+}SC4+Gnyx +zs=P7okHZ6>jfsiISWrLZ<6VrHAD8;gLkH#qQki +zlP`~mNEpx4Lk8v=bxvOrPU-k(BsHlg?YJ$o<=dxNR%6Ev7%EfprTvB^QRZ3!dUGZaAmtgZAr?`WYMK2-km6g?)HIbKG8n6VUG9GWRnO6hB`J +z^~aV*AV*xGJ7Y;*^4X=t4U?EP=>^8#;>yi#Sa8yaiJ^+EhxJng;F +z8#*vPjxNcgB +z3Yjkp)IV9)&R9^M*sruW&rl_2ohuZZ#8@#v91pLfKKPO|^ +z90oT@!VlL)4&4c6r%e##s?_PXYrF2K@WYd>P1*>FnrntRL*z}Xk{aY`38G5bw94Yi +zv5ej~TzilDSgMcwnwN}sj3DW&18RhCx8Fe^;m(ul*tCj4h6_m&at4L*b5F;1jqIg& +zGAcCl3`EE6I7bZEsR-7iw|`)E}3|Z+QPv$&pnJe%!TYii`kN%vkEYVA7>A+i;vV8SIh^&|B`fQXg^t|d5I~_!IMxIWz*>tvg?Z))l +z?1^#xpzvFY|1bQ1=-j=Wo4p8C-!7U?o(?1_4%zJZyRZ6TmmwIPpA3{u3OXgbM8~6P +z8c6X9#Q4;lW9wLGA3WS)tLNLOYU4f3%N<7Ah-s(HQ!mTdSsN64YiMi5>3BVJ)@u_5 +zS@PlK`EZsK4949nZ14tgB-P(MSr2W<>h*A#QeG4`swNIpD?Yak(ofo({3SGTxtgs! +z?CFrQe%@Y5J4K^;OITYgagvw5yv)-sqa$oftMBURsC{oHW@DjqN2}W|t%q`+5Y-2* +zZsh}!=`Z%tT=P_^N$!}Ln~N+vO6x<@0y|2%4cX-0B=#^ibKL(Pu{x;C86MWDRQj~s +z`#UAVU}kW^&mGgRO!T3b+RJtdS>|1F07mu~O3SXC>by#hO7Yk_%O+y(cPCD_rT(UH +z`y8DGnDr?9pOQ0(%*0E1M;f4;oaZ!aS&NB2!7BriJ5Wfigv-%rzqu4G+$dXSrL2`$ +zSRV@?@g8|pB5KCYxK6#}Pu@5|C#1cfD{f;e^jcN9G!CDcbyt5}xMA+rWKs@$(qsa8 +z6cK^PqMJpfaLB}9PDHSfws^|0{bn~Oo58d-hNmA{(4xuTHOuI +z2ujgpfhfL4oQAPR|Fqx&0J(UPY06)6|KcKIH@U=AvGkB>)hk<=o3Tij&|2z{Fr1pP +zyegcvjAELa5qX)%&l0noA+;Ls%_0-Lcyk5g*v+JN6QXEsNWBa*;lNEWm|WZQ0nQNePruO +z1)z#?O))1j*9GQaF<0KYg3pT^ef6!MLsk$n-p$0D`S{QHbBfM^l_Yk$moXXc;Nz(* +z9Mstk{iwU5+fcEz&R1#qsAYYm2~W1rZZSIwUR-A3h2rt5qcHLs2{%i#tQ^0MHFVW8 +z^`|n|QpNXchcr$~i5oN1N3HF!)pOlJ_*F1f#UGr3PF|Mn@^rS7s)vEz2d#1k<}#jn +zN~M|CG|tCoPncVdpEk2*B(0q|bM!jf1s<+c>pU6GZ-{boCbnqGddD<01^kRgTPkjz +zcHIT)b(9{$e0Sll0_44#_Pf1=KJM4D)r#@SJgqJ$;hMg%7~zIiJa63iVyjf0^VTLi +zEx3`pqaB8j@u$?X9krP3X4El-9|w_^aTp?xD`bDNE?=0t*P6C7>P0Vs|K#`8(!a(Rx7H>_Fln$&RX|ukLK~M*cG9FS +zN1l$DTcK{*4cCuk&cd`T$()51MLhHO#p^TS@y)M6B3l;T&q`L}aA@sM30pQ&VB0V$ +z?}$#_XA1p7MXE1Z&+L#w6gv$U_V8O+Ih25hc;+-y%xlV_`CuW^A0NK0kDY$h`4cl! +z#~QvNdpUdl=gQR7LJ?>7x4ne!n2EaRaODx1 +z_GZ?VpTk@nL|YaPZRay#c*or=TyjxQke!PSgzi5eWi1x&+N$y`^jM-)fyZBui#JMW +zPGmV{%XrsK64~Ut1Q{T)-*=m-Gix`#zAiVhiF`8xM8DgoF|?p$>_f>?+VAO-+PFvb +zLfHtJy+!RHAzwfh?e2PR)~^w2Rkg;Tc&ffygs_GrMW*rt3 +zvrE)h>N#ER4zkD{TcV;F=;`3Ebkbx|^)zB)X=!NzBdo3lnRQLn)mdeAB!{+^OP|qy +zPBqkvE^L&4nthn?tLv(0u7eb5`FLc8oQ=90O|ANrIH2FigN}+=yqw8VG0f#dDc!9J +zbD=%^k!@if`#t-02|Q9AR5I^=k9uvfQ`U7oWvg(gn-(|J53ts63{js{+FR*<;|r+f2S4@aW&kophO!?JgI5ev>Z28}8Me`#Y0P +z7jjRkt{jBxfWCW+7uLv2r_Khj_Ly}Rtn0xI&y=?K>o>5px;k%&=ZDtWRlN&L)5q)?Y_=c+UBS^db2oFu8d1`XMkmuH28z=RCwJ +zGAQPZtRR?^7|5bV+Gua@xjtgUZt8wal{{0iHRhsLk;R%ru`x79Twl}V%o`vw@3fvB +zblv);K|9nV^{b@JnarWG)-}B5h4fe!m{WZG>|=8L#UwgO^qm$2HByQd1Vk{jhO#oJ +zh-enNmKHE|i` +zrr$W&2BM4$*1hc9b(}b)k1aI~@i=&|o}AEgo!25ok@F_aYL%-Gq{EAv2D8!#cxCSj +zcrAosg=96zX4qFny==4fwob}BvW%g7XL(s3aISwCAmwnzq*@x5-`pdB$7Dj$8Xh~^ +z-g(&G`LVrIu)S06F<<)A^WwtyPUDMrd{TzQ$k@hqfkkObcIR#F+{jq@_KyC=1@47I +z{vFTBv&TutZ1uvUwyC$EwYLqskRF>*LvjY6rfI~>rTJY_hJ38@I550R-r%ur=jAvV +zgXqJ{fl+j0zvl_($}r)Fv7iydf;kGLAn6JHs$f?(fGNGE3bxM$pm28L(Z|ckrYh8e +zN3gkk>-NDcg?CfyXxm|w;dpWoL5=r3UyRM71;z!7ICPxJ^f)D4WN$NZ#SInXDPds@`UhCh5v&?}|rV^!fO?6?DJG +zilYe4*zYN5-j;XN>!=B!=o6cr_EGn;2h|(P8H^wYv>lC?^hU}vDNEgGjsbIl*s0j5 +zFHeDaDqOWySXAD(F?o@Ic-K<7pdRUUh1lNQ^s+o6V{~H(<8%$qG`$b-F`QISdCR@( +zZaH%EHnG>gsboGqT+W=kJ|LEf+0qOw`(z{Jhwk3mr&Qs^X4eZm0oLMpg$o8^2mqD3%#p +zRP2=*+msIHe7Q-U^}sgv%;@x@yiD%fSrcrz-_`?I#rJyG(7@l{u20*$OCO`qqr9WM +z*UNVPy+Q)dlO?cvTp{+GuR&?}C(qgYn&S&7!#L7Y*q!Xh21KYL(ps&h^=fhzl1$@= +zX%6yR2TiwQAqFRk=n6~}1nf5;277A}(xnynBAxZ6!83k@*~SjCbCkJh)@#(uFPg@a +zO)7J<$|*F+O*U2JkI4(A>bgyS7<8Cq+HNYFyo~3YRFj`9AWG5YBlFrm)~NB0c}zL( +z*z;&OI-Yk)SXuVmb{!)g9KAc*zR`|sTFZiNf~UnQgue`^59r2}S9hK5f`(UP^mJVB +z4LD(Z{A#e$B@%-9daG!nUJNk=^m`M8hBc<~xcB=v1zG&C#`*rQBpD)|eZ7Uo;dZO> +z>Vt%~mc!d~xS*m#vw& +zyb_qwTIZHOp}R( +z^Lx3SSdBF6~N96#%7y@ILta%^qWa&J%93{Q;d;z8Rs +zt`nM&?1H27v6W)byxTXPmwNtbHuDRdtI(2OZ7V@7lO?W<2pY*2B1%Fd%2nAg)|$Fc +z?hR2!NgAW&NKqH60dUqcel>KRCONA@$xjV0X4eWoNA4n0F4}m8QjR|JnM15{r6s|g +z8EFkOZRf||6&QPm-1VpSBbYUEHaI!+Z%{jE4{jbx=k#hsc*u>F50~e1Y!rzf=M|`4 +zCqHkb>J!piu;o1W@Gm;+KAolFrZl;v%ulg~$P2Lf;9l^m-A-F^IN_<~7v$=(kRAz} +zY7Oz45Ngykv%Bz0t5RfWc#W3Q4lMI6j+P5EXqcB;zy4cl18)C#KlL?iPC2#$&TLEz +z6=wRtRBZXcvIcle*nRI!e2MAoL_J;61eU{eXjzK2>gX3uZlAQJucQ0w*jhMz>3ae< +zDO%pkw@);CY2o>@nL;~-wuL5Up-R@`hd5zc;@MdyGWnOuAuBP6T!<8aUwrLW_iZDm +z`6Gpdan1hfW2Kd13}q%IH1qQoGA!Pm+}FuAjfS3<1MC}#W!E@M9_sK6blN8d+r?A) +z*mT-M`zGZPFA*SZrNvkxA%pT-YiTQxHG@#OL22!a&TBw|3>{6iLm#D4wL$8#gWC?8 +z?ZM}okfz1kq%BXUVFBrsbEBu>HklN|O|Ov27o9u1p_e8Xp^DmFt3#b=&WI|7W1ekC +z!=$PMmLaxnjFzfNma+7trO7!+(6Qp&M;-ISWX*D1hmNxm>g{8*_@)}x>(5R`2g6UO +zEoALSxEG;Kd;>PiAZ+7<+QZuJ$?7nIP`7%H`Z4pn_Bfr-d3K<=3GAz1hM=W0dX^h; +ze#@0*3(x%HwY{=lo8b9u+XVxM)i@lwz3sU6-tr-S83jJ8VVNoqbY~lp`4SvH_M8>o +z3p~(L0R!`m1Ha|*l;(}4(yu-ZIWc)W&86C0u^<*_HbVEMUz0S@CX2mHWo(PAivlj> +z&vO&?ZeOMBhLS3^?2VJ`a~_qGNEknxz%^7$&d_OSq#=|q}1=0 +za)zS=TC+OH6hipj7NSXb)xGKRwYGmM4-s@3CDAQt9b+81*+VIWD;>wYpkOW(ec()Y +zy0G$itG>lnT7%@I< +ziu;fWW;H@|moA-3^+3>vdFuEsR&}JL%1@0TX*bEzZ?MGhsv<~Nvt8YlNQ8b8>nyJL +z>AqC!WOiY<*x8;h;JLfDsQP}6EDQE%vOiMRF;9cdg&8D%_hUUH+ee$vjrq8cAN{86 +zYhRIPg&(h5KOq(6;)4S|olBQ5Kz#LgA^Ol?y8V5{!%f#TTnSdtXSr9_)gkLX!(NSp$@vD3 +z^64`!!O4h4xRQwXxu6RSFA2!&QYEg+uerzUiq72kYZA@RBv`d1TY3DnYDuz65vi9W +zUF^NM#5^~yWK|L@djyn|`!iD6>ShKYfS4L+RW>ywsR!-sPro-#57!v+J0)6gCn?&c +zVE@X03aaf0y{^c4isBbYsplHM)+^#jt>^l6O;>wEb2Nf3RcjxuD*sEGPqXQ}>h|Oy +ziYCq{I!N=a5AJT?SIr?s) +zDapB4qxGC_0oQPz{6&03!E8+2V`z6?r*_^ieQSIHO*+pi*9BUdBj@USqjFG>xRr+{ +zfpCegCV^DR?1Y7_=Ane8p3;S-_)3^4k4U2-+i*vsRA|x`MHHDz6((Vz)9E|@_Ys{N +zr%?QG(5$rAU4nDSuxoVG-~GS7YY!xSCrtCGBy9&ZxK6DsOrbo`_8a?q=0_M1O|Ki7 +zS*8e@Xwq`~hBuoha>2UZDWq2vpzd8|VvS)OYYM_c9e>eMFN;WeEkShgktOvvFmw^P +z*e%Hpbw6 +z?m*=RW;mNZ=Z$T^;+k_2FRMP%(okCfK33<4cBUV)>YaCx_%%F&?+$LC->vx@3G|tA +z3&M|Gc)h;djJGbf;FETca@QVka&r14(C!1_x(OtMCFD8nM~(euhke@bCxOIokDn(G +ztqeiPBj2A%2C@1f#7P%-AEJJnd{*p$e`by=k0h-KyO&Cw} +z+uYs-hR3Q@*Dm!bsAeElj&$fEwxUPaV7-`;GBW8SE1RSV%)l^l5)L_={}+?UVT9;6 +zWdEcAD}!{t*g!3H5+=oD_7}}qdcXj7TIj@I)m@vmH&fxGcn{5M{H6uY7>mQYj?Q^62(LZ4PtmH-jc?iXTFko&{wS2ypTLE2@dyt_J;Kxqu& +z-)Oz&Z*|pNmd3WdR;WhxKUuVT63g_5EkZTISV~w-IC@Ka-IIqC5m`(`Lg!J8IC~O7 +zwk!co4p1Al-|RF;xy$rZjyic4{GDp?EDK(fdUr4E85~_!I=id$ +z36!Q0&d4MG8=4tYBou^V#L}ZqZ+K`P+CVu)zMdXXvrVr|!p6D}H)CO(jq6cKe&4PJ&fmm$DF)aw^Cyo2!?-PO*JRQ}PgMIriVmgdKt6vhBitZ$-GGuGxF +zYdWnl$Wya?+X~4ES@FiQJiOp|a_T9%Ii^TUv`r7r!wUZ?nhKI%qbDY2Qu&DPIiRM^tn!xtTF5-mPov3!XXW&a*Hde{?$l-?=ji#1rnZrC~Hn!AE +zSk!VaI!03gJ#wKOantKqfiRA=`2#p1^_lSo8nU +zo36 +z&m#QiH2z2OhG1|{JbjBpwwrfyg&6G547^KFlj|mpV&s)BGWsX+z!e6+Hmy&sXRGGc +z)JuN6dsS)T>3fO+)YX?Uaq-X0U@%?8jp#7lDA?~4I+?MN$kyx|A;i1lPT{ekbJl6G +zA&m_1Lw}U4<2GVa0-e4JEPK8mFO9PuM^hC4|%R^%l=U|Uc{V|MV5C-4K=~r6F$dOV$y*^M{sonf@OFpTRr~hz=9L7r}3(VSX +zN%|>knCl@kf#c5U#q=F%ZAtwv+P(rRj&9vDhFgL=A-KC+2+$-zAhb-KD&19u2r?V`>RvmIaTM>?ca{frt_Fe +z)%5w6z>6*R`R$Cb-hivFnjq`K3Nt->&S&T{K!+Tc#J_Mu| +zp+I}lRL`6(`(9Pj{J|Lc;u0rDeSiK6|Cgz+u~1fD@KJxj)_HdD)h(@m?0N9Qr$za7 +z7wo#2`n0YC80u1{(3mgXz3ccNqqSYrUptbt+mmSo!To+aHk1zOk738fHN!Nky+Fg9sM22<|1G+otN}avw=6p%bpJK>7py@{`qVlotzQ+{iOc*r +z*ztSX-Rg!Tmua)fn;g(1Wv6 +z)^s7?_-*f*{@XG~0b@weR0U#{`vZqh3LG>tPa@#rF-ea@(0K +zxCL8>5}ar>2Y`Pn7r}RkGTJIdW`vOI1gfh)bi1x;q5gVtYVYN`arCq2W7O01NQ7C> +z9ix61pWk?um9sxa8p7%M5L=`2n|vgcF=q;j!Hr7@ep +zecbwJ-D`CB?@QeVE(Ae1ru|@)>a{mSpWJZC{d?C?+_2MMEN@{?cXAyw3nPtoBDy{2 +z?Fg$t0s1AZ;kn`YVEsdAzoR<*#`zA{qe$BfF5evNx&t}W%Xv(8jzx#~4tqRJeQg|Y +zZojN+inm&r~J08P{;LlXN5wqO?uF#1w +z39v$y3m~Dy$P*V_q-F}%?d*)MdKGk``I*9`3?dAwrgvinLpS0^&Y!xHC`(vF>ba;dA~U32 +zcz)_eoR!5c$Bj2Bd8o@A$?WPfjJVnNgmD2=;p^c9X3hK?-9&8vjz#|^^hNIfMEo0g +zGua;y8I4!F$yNH=qC}=c)<0w`P~Ftbu4rcjgB7se2aFW3li~^HbR5s>h4==jdmdY2 +z0T0@XMGB$=i7oz-z7Z1@ME}2`|7p*Eu2Pb2exQ2O6mq5c4hZP#m#j}lP6$)s9+1co +zu3-SA7&?6f_!}RJD%`nuWk~-;-CcTecYi0b&|PVcd-^iS_OeE1AieTLa5IE+9H9)%mve_CF33P|TShuAJPP4<@A>GY8hCsQ{ +zpjUPrP$DkRE?83!Ar?oEL^%9)Bhk^WcY|keC5a&{kg$oe$M#8P9}#=c>@)#Zcy7ud +zt`RL(XSzB6zSWb;BkSWofBWUCdRkyGxIhP;>K(-;Q^U%4l6?COZrjxDIfr!TlajFL +zpYMP96EUDj3h`g?WiIhM5eLcR^?B&t;*z*l){tB_x^Fg7mT@YbQ%{b4Yh-Bw)VIDq(djY0q4-KY3+}ssGi^{OE(a`!^Cg{F9t1rxv4k(EP +z-%IbjO3Om~_5P2mXB9q%6{O;yNH@ng%ZghE!APGu+#hboqw{j6<5fLoSrCc-J2}6G +zE_=E~1lLZH)c|)pwne1NPOmF6=C1)2$oQSu8mNQ%0>)3ZC4(3?FDDe4(I+AlZ#tqX +zT}O+Fq%VdxIucD$CwTom7bYQ*T6<_t_4&Yv>!MsYGK +z+XweNr+`B0o_ON&dG1V(?- +z6->R~E;eqF`GZ2S9y^f4M6cjk%QrQ5Ki_=mK&Cf%70doYhEVo4k;G*~@mbVUPed=3 +z82L54FG|`+_+%rRBI@qnwTg}lP^12dLf>R_eoz4f4G4fmZY*eq0@Wn0J$+skiu0OZ&3F=yB<)73WfAQMpvX?tmc`$oBZ%e~Mot;xFRi*HB2mBO@5JuOuZ< +z)lsom?3Tj&Q*e9_qtroPGejnks3+{`e$5(a_pe&Awe>1t{|Yg(7S{h-{~0R#cd=Ek +z5-Iy{kRd(mZvC&6oXYM1fKEYgfCuTAeVZGoNP5X*vh?pXrKm2gOXlo6`F|<$$({EU +z|Czdbw$JH9UT=kT}To +z)HQ6!xA+qF7Sf1PnlkpU(5FTJ=_zyF&rzx#C7h`5!u^nQ-geLjC*EWbJ>PlA88Slx +z@jO()kE+4MVny(rf0qzcaa9z*NQvY9hlqo`HsF>d#CQXc`2K&An`YsG$e2=g^nMa= +zNJCe@yb5~9kK3O0f3~)X^~@gB`x|q_4D6)VTo; +zy4y)m4JPPabB7v5sv_@F&{jkx>%&4~^tocsIRJ%2Hp(KCS%-jKdE~Ht&?#P&Mav><$k{|vf +zYudL|Sh+^ohheeOS6Sl#bKoWa?*JFqHda6zw5l&zI?wmH-buE%G?`7= +zBMy}?w|x{qQ4hJg8QtWo;VR&plY;eUbiYn6#3a=i68e<~o_eJcWOa#Hn3jl?oL3kw +zn~o5+kuQ(9Sw&$q`a)CZ$%DZLIS81Gad~`44xNOkd^ulSDA<^D+ +zJro;%@H}o2-g@AIZ6-&ZM)70EH2ttbT6-O92SgQbp$Ni$R=vNM5Ym+^WFTsm3DvDoI##NR5Qj4f+_2rzq +zh+JYyNrgpxO1VJGuZX6gFvs+zC2ywjOPN22(I+UBn9;JJAWI(uH9kup1vNfXpXd)_ +zK#kA-L#5|G@pR_X$4~TRX8p%%d?pZMZz?lA(1UnjDl;+AkT}$WJ~t~iP>F|r>Z=mQ +ze?c@HxdUH{5OcX>$G^x(6e2<<8g5aB5 +zw=CVQV0vb8Os%mX`sz*LZl*`uyIY#C{ +zmT8%|3uXqmNMUv4kEgi`NiOEHYVWTq^$rYWNFUFBUZ>oZmGx|j) +z1?5Yz3L#GuOWXk)1bp0!d3)`!dUkVDv7)65oMVC8A!z+2%BI7@ocm~fbVe6Sx6d?H +zyI48fDmBQdgd(HKdi%nSi~$HqisEW2Kk)MVLY0lX893j`03`c^>4_A@X(ju=(-AR+(S!gU3@t3qC_-ZL=r>M6ADd`uwBMP+i}&3HQ#e#j +zOb1tt@mtfShCO1<0U@SZ1s_mCup=t%r-HE~rj;7}@x6_evQ%k2u`_d;m3PBQbl)O) +z^mogEcBooaZ`K@r>v1o~bcuTJi-&!iyokUJ;g#wEjS&S4eY3?M)&RKi^vpz_ss%p+ +z#<6LpbGkfYHAb(BKOC4&+5(;^KD?E&M-Q)vFUNz+(j?1^D%7Omu}iMzrD$~6k~`_s +zz*qifEANT!Vm!A(Ym{N4HDO221&<5d*Dof*M^3BZFI#2shnu +zBk@lWHxiFayIwP9N8m!jWaWW>!q3 +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 +ztk%D=IRv$<&0GX^7vhc=d_WA+e-_#PxZxb{5# +z^x3HUSEz8CV;NLnCVz;}q(#_Vek&^UcgWLMf~3`>xo(gzhRwO*Ivx{}_h!H`AN;hK +zd$1?7o=)tqr16wdwQCj}f5U;fkYMFYAxOZIK^Z@XdTJt*{16`9HZ5O3qcNIRC6UdS +zG-{)orU+b*!h}WTTbrZ&gYz12`tQ*RXh7YBo@?_n0{3l09pddg +z-&HT>o;9sI!kIP1MdVwSVSoj%OtoTi1T4Q{cZGk%A$7n08SIB?5Vz2;xptuE{6Am; +z=qUsyvN6B3&EJO^tPHc<+Qo)rhBN;7Kpa=_0Y1}I9L@63MeSi=KFKEdG9f6$%j+FQ +zMqh6)93JiEMNL7`-z$9rkA}Fh$RX!kUz_`gCTB!#LvwO60N|XAHE8{FzIB2t8lQj^ +zJFfI7%qU>nJbQbnd_^`+${e|YXfOYGI}joD*pSN)fa +zf-pwxbHx?Oms3r0sx86;)YE|iAt9aj_>RHXcI=uglx|QmQbZnEr@xNQ3Air&0Y_M>z%GlTsvw{V +zDzpUkbs78Rq(0eH1=3J+XTQl3!)$+s-j&6V-lJtv689(h+u=s`=#%;%S?)V{Va25C +zMfDqKs%mP)H?ZrZH6X`y6bu>9@)6zA8m$<^Qo_AsDnXoet7?mZ3kEGoLiPlQJtFl4 +z6YOM{Yd%A5FB3!b{JlA`)(q|tpPJT_O&;&cI;nM{`t=tqf0sU>z>X|$o8}+Nezz7! +zRL}GO*Hk%ASRCkEW0na@yh-+%j?`Syg2`h-jp<>^(1rLpgs +zXvSpzS6NK&9`Glm&dMnx0s7QFUlj=>DAuLxv5oBT$}p)UC!ac*{s9wf*}HZSr+RZi +z9d0t#WK+qBaP#ChpSiLv0NlgDc|;Iysz1%<1?nT-{-)0-wlV)972&s$0&eJ08`tJv +z`-I*P!eZWST4R7__-9qaB8M|)76z-9x|n-+YaQ+V +zyFe7ELcvxPMKIMHwzpw%Bm6ldfA^HzJ3Vi7;>Svd4qD!=>_o}B+gD~wGsuLM7=l6s)eP*anc +zDa>Rr2>&svXah<*iWy^4eQI2NDl-RLA5-%Y0QA`&4O(vHNTdw8h<5>nXU7pP8=D +zxUr)r2m}qLc24P@{sj|AICFBe6jzlw0DrhIn@E$JD$LaQ?`Ggg`0h~R|Au0OK4?48 +zHCCWCRU&y-VqJV65(b)*vvKKBazTx^IrdtcZ`jHo28$n0{*p5E1=y%X-_=wyN-p1%r#^@;;$l>)+=U^p3s*3_YNY$ObURU|f8B6uX#N?(VG&?h!zJMN; +zG1PA;BksDIG0blu`)Q15HANewjBLXTxl2nG@QssDp2%34u3;3Z(BEH$3<1@EKj4R| +zJFW^jLY%btmg1K`<-i*1e;_oLKN(wEdEI=^GQ7K<-7lF?{IkxdCrF{Ik8U%BkkUlU +z-Z!3w$=xfR9tVw=bDqnB*E9&Wm5CZ+YgI0{m35yUSD=!%-=vQu?T%JP8&&@UY$|AM +zzur6Stp)6@UGH*bhbOzWG`>|M=-Tts(0yHumRt}!_oq~5GAfAU*aZdrKBKAU4p*n> +z+Eo-?P~QEkDyVVC8G4iYp-W}Vjgejg0pp8$SL~RZ41Lb;;3@pd`FCpCU6x@QHgA+a8qxpaz#S(K6L6|lIeQ` +zin;>hqrya +zqpwji7eHl^&e~$kcZ2fIP@Kb3D=JPnGAMc@f0TzlJu{+HHn3QPiF#U$8OfPc9#ET9 +zzClvYo+>?;mT(Q)zv>VG}(PhT2ySkzGY{6xgN9*S!6!4?gQMpuHNVkDn_DG`2Nl5NmQ%K;k*E?wG +zR+gfgj#R$rn+IcS-;+(gtZ^zGe{kldxEbf4J?y;$iCcu(zeee2mmBn8L(r>bit +z<0H2C45pYUWU2vQLYe`J{1`p7N2LeTL|}{Hjm9-5Q3GgF2p)aB(A7cDB^NT_OD)d+!*FJ}Qm(kupL? +zh0@>BSkWK2LxwMjq;GB>KGLSp*}P+RC1BeYafRR$qPIr77_L2ceEo$2{CaP2K*C7# +zk48rTH=|+zdXb|4ANLhj-=1~1?*u*Yzj|rMAK4a7_&vvt8*zgWy}j~EMnly_v?a8B +zZ9nn*J_nI9JDym(0-WoPly4Pq_o6N+&ct<9eleiQ9_z5XrlRWZ7kl}g3VP@DTEmH6 +z;D_t-58o2>^i}7t=0rt#M`dc@m29V#-XUpADcHI$U1dMyVTXq@uw7d@7)D`N%V9*w +zy@5vd!ue}NYNkd$8s)X>ey5LgOifKcRhJ_A7Ws~rSVNzE&D5g+dwr@y^>EjL+0ya9%F}}3PrEK9k+a2|CPD9ocAJp +zyMob~El-GVbQ0vvn-P2cYlzN7w6LLUxN{;g$_(DT&!+zzzhhRpC;g^+^k|h$bjFY) +zUSB}%dt9NPCrKp{*=*p!P8X(Afa)%AC*tXUz(ir1`0K7gDlzc{MQSvbKI37V +zzZ?H#euf>@^1k1;)j#I6ppRk*!YNjr)HlggCP#YHCsj +zs#D)0FVy3_Re4?q1@sKLN>FlP=NwDugj80na9w!z_>9gT5#5RywVK(sm)2v{b-Ho6 +zuCp#ic-pb$83-PB-Y0%TV#jF>6fk{i2wq{3x0kS&-(-Bqx{>8ag02gD5$UyGClaO? +zw_wKDiO?FM=B?9RG57>#Y#=TM>#ZhS;n{W!*CW)e^DajIW6Bx;t)dHb2N!iXf;kH? +zN2NYB7^e5FBx~S%Yv?Q!Ea7}c=E@GK|6`vnL4G$4nLexq8EAV@zZ(HHvEDtX#yx3q +zhS9lWiBIIzXyyM0(;lu~Kk#6j3JT=qu}Vp<{X9IMXKJGyB(MGiSKb04lF2lTt?G`v +z@zyA>BRw*(_A=gb-0(@&YyV!%it$yM2zL}22VY=+57tY3?=J_Xyut_s!ffr +z;vm5e?1hbPW&j$u-M5E`-Ic_Dm4G%m>I*wli2$2o()FMGM^4# +zGJzTxD*w5el&qs=lopu#3m6vpnK^RAX#aHb91piMfAYc`yI}{{<&kO2jz6usXQ~#0 +za@OH~*72h&Z-@DyW&Tw6BE-XkMtJSINydA`5k#$8`F3w>eqkgY*Eiwh@t$R=>J6mA +z_wmvx0&3i}5#u2uEqa&D(d@cqJXbY1H98QFW;{4O4#EYoKJdt>V>wS7Cy-LgAp|W +z61*w?g$-Eg&MZ9 +z&uo!Bf>Jywivn|zC8xObP%Dqm=9x_kB_5zRbuE*?5meUGc;2wk`fP>S{J@nz09gJ{ +zTrA~}qIKl0Ke~;tqqxX4PR>`25uHCaiMG<1>IOo#dE>G5um!`*mV^z-T`O8#-S#o= +z)%IOyeCI*6J~OzFykXNfJ9QtzglcBp{CXA)}n< +z%O#xav3#x`jv0Jb;kixbJfOo`rfGm)@U(%5%PCA`Hq3jLO;9J(p@BU$_A1`o{?pk( +zmr3M`J!$Dh!+={EN)&b32EipDgZ^R48ozvEV{Ck$8G}m}yw&00Sys+yrVtgC`g78y +ziiA?|cecV=z?oD%VFI8xFW&$^IjuE}hkeAU$to>UD5CW0HtGQIdm+`8WDaE;ywE4l +ze)MfyH=HnTJB4E=A_NceoTglRCqf-uIYRRCFM^{eQ0Nbl$fVbC!*~vLmvz)VnAC5Y +zUJ>jb8K!#`Zq$+WhJ;#W=SViYaL`h5V!kHA!ac%|f5?`%zei1%sUNo`V?EyO7+;GPK+nGDZn7F$p$hyBkUPs|zfI`z?&R|8fJnOh&$ +zEvt#?w#zFct=u7kLIvE~_HH;NwclG~E#VJ6bu(8N#4F3`a|Er*z|y!WEryu^lpeRQ +zYK=AHrE%+Q!|Il6OY19CoGswLZ42C3u=4VZ0D;c3c20IucRa5|X(c;z{ye9=xpktz +z=U3t!#eM;!1l5ch*Ipd^it#?lxdiYDzUy6r>s^76-cGXZvq*G~O)#WSyBlJiO)DQ2 +zcmm1l=aLY;*5?+!eoY=3s80GiO&J24-L6N_&RHwmuqOscL4N@@g09|#ZWMDDrHS|` +zFK_T|<<>H4RnS;7dy~Lp?MDyYi}Xg7@56;IHW_k3Z?!(W93`B(Pu8*vn=jWat&_5u +zNfj>h6wxD@B5RsIl<_>NKV~S6+ykb~_K$di!3x&16!>&Z9}*hv)T;!YJRBE_kJ$I3(Kd@1?FbyyrKYLKG +zUViJg?Fl-Zu&UdunFwC^85c>EQ{ZwBj=xB1#{}}p=q}*JS>)<6Eoq@>&8qAP;l;T( +zEiEi9V=gaFas_ULx$Lzp5l*|^nuGW}Jk1QF$h1lCMSYqxdYvawC}Di@JX%6pRuNhY +zNhPQa<0VCJz3r}hS4;30=J>9Yl` +z*}14si{b1z)cM(g#>WbvTB})F^L<8%!tUI7quYg;CYIwJMVY_bjb2SF{b{SUtK%IO +zOtn-kuB$tIgNQfV!+*rTdk2vEjm1Pr +z_YR{Ydo^OLtID}}B&%8Jk#kfRIH1m +z?Bkl6MCV519{8yR7q4#I9KgI-d@T+eOqbI)o6(0@9g1aG7egFn81U=abv>Gy0Y)R1 +zkqTjfHVq^Io=7R~3ee=Pn<$DZA*UG-%*(svb$+G?+elx$RYN7I{4M=b_UD +z=DGYuxVpG{2dulD2jXEKA17z{L-7|(NWCL+=J~5=7Ra}}?E3wh!n4XbR0z~*WMa2P +zD|$zcB3jJBk`~KHV8}Ap-bulw?+hJmKJoscoeg#oCCT%sx^g`IN%2PP1j{ul1oLL) +zwH~|wJIxhH7=am;rV);<)qa3=|OXK2F7yK(B +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 +zp_NsI$@H}TU}i(DPIBm=8VW= +z2|89(Fi}KbV~IcBnxn_?ZQB4kR&}jE)e14JD5j~w_O`}zDnl>LJ=lQ@RV3u5)g%l+ +zL}6PNVq|$-JILHsKPLLH<*5QDJ|1u@NljbTp5m~H?+xu{7n@)`f| +zu06*N+(t#5JBU~PJ8zxj9p;XcRQ?1_=7empyDWIB3(T{u^>bMeghu104c1i|UpP3( +zq6U?_2FthyW!;z?Q$2eOh^b(3&_tNwbG7^Ch83wqH3ROYCX~OPw;e +z(lR`@cxvj`B+ni(>SXJf!a!DrPFV9yR-L2{=u-vPTil`)h#5A-ELoArImJ@`)1Hg7 +zP+FE&CIOxUxZuaW6gqfEeABX&{M(SPiuNzzB66Ct`NG~WvYu1qG-8qI@n6#~s2!Y@ +z(ta#!ItO|YoPo#AMNFZ}Zzp8W0pQU>(fWCXa|s#WDT)Tfg6BVoej!qs1QYwkqpM0p +z`#pS8To6+nLFReU04R$7NKp#NN#(Far|vC=e{`4r{C?SWs;M69s4&XTOjIo+J1u6) +zcrk{-5>@NGHu>AMPmXEUPzD~i^04yQr`q={A1qpnO;og4)c*%t?--oP_eBfG#>B}) +z6WbGOV%xTDTN6xd+qP}nwx3u}@aFfw@BMbGx@)hs_wIA5tNO#~?z7jfu$TLkzmQ+? +zYzi1J|7VGIeQ4SgGG0+-Nn^QL?3z2(u}Cj|t=i$>60;uk&}GS>Sub}b_6ofSn&>T$ +zFFY2uNF=Eewq&sAD~vCoTM+f}RURNmMw|W%;{Sd808f7qUZpt|*))Xnz*PFHAx(rR +zeHL8n)JQ|7WlRKWoF>O*AkZ%ehvqA_Dlmp=BCej8hmbo-ExF`(%1N1+xqCPU}&1)Oum#SA!Bj*gIugCe1Tu8$7Mclh7FH +z6ui|_o-iN6M;KQUxymBT@)kZ1%M<29UJ*{7HaFjZG)i%gkx1IV5J`v{Nn1)pQd2#c +znXX*{C0C2Q-_XEeG!a2cK~tTJ_MhW;un7tSR&tQ{Yc0=yFJB=zF!s)p1FR_uL5yg{ +zYR`(&!>^ju%cd*+U|A0VK5NJqydx9TMd^aksufX2DTzd}n)jfTbupou7AQ60|Vs5-i +zdydpId-(>^WMLw!@pNMAsr6spsZAoQ(M>`xcwW(hxrZ);_>!Xj@opsF@^`!P%=_}p +za|VV#cLv!Nh{A%Xkf4=b4SZAM@xaL8<=hj&F5!Q~L{MU&%7`dY)2FwwuhBjw*{`Ze +zZqnO|dBQ)tW(@VAB0)=qa}Vh#)8ay}#Djoc=Yy=e{mn;uWX3Ts>B8HOyZA4*5&MMGnPz{M?tGRG +z?Q}W5v0Z5^{D$5I>ky#u{L8vXlc-S~i=!}dIIcR&GAwb#-+A6ZJ2zWi?w6g|63U&1 +z_zK1?_OOc@?~j)M^3agZ^2=+^BeiELuwo4r80 +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 +ze9Vb#=O=XW +z13mxr9KsZVYgBs7sc=VK{4&Ex%l&jx_&A}e$5@k}Q8)zQFLBT2L6+Thl4npvkDH<7 +zL-zfJ_0j7TfqDbp7J-Gq(EnLRI4VMML(UZ->I`O=k7h26EDw9`#}E#><>xMX1A!J@%t}k-Q%RK2thqU{zj-CX$RVEp7 +z4SmD8d+|Z=C7K+G++Z3VVJ(m7N|Ra~#ab0+Z+F0xIw4i=a7$xa97|f2YB5yCLQ3Oz +zK$5(nnm<6z|I3V&r?ETwjOzgLdVzgLQ_rzH5>y`3k|)E;liZG=ZVSwSO41Ibe*Nyq +z^?hYaz9hX+QYWIy9sDLkn_jD@4+* +zs{C-wpDfFL=EXq<5nhx>bSg0u?SSzYI^|)80wiBpmm96pAR2jSyYM&d#S{NBu|FiIcz0*#GkXm&hnWi>Wlo#ve=k-#~Mz|16+`c}D@^>ANcRKrO#IRz +zuLd=SzUp+xVN1NRgvI^uwZ`A02869iNA%V4i0BIXDNgfG@gr{kiktzf`l9`!rP_CT +znepElJ#xz9jhWH9rwj4s`{G#(y)KGnIE?f!3oG00>GcDB65^HS)Enyo(;n)9^Qzd> +z3v#i1)w~1y;^IiF^2XOgM%ttMq*IstkjAOmW3}hu(uLL%iN`J*C<6&I3VhB-q6lrd +zMZFxE-Y}q{0FW}=Z+WvfKHTzgz@Ixs%xzfr9S#dRbCA9N;D?a*nPz+7BztFf$0nOS +zLC+sp8}|$QLTcVlev-h0=*(YQVJY=V?aC2Aa1shb}<|G`M +zsP-Hg;y7HHaLybI1p{kPNE9gAvn0r5ed#fQ15|=`4UiwwoG)o5dph-fGu9ydN+8-V +z@=Q0XH;lNm1J)qO_gsuF47jsh)_%3PUUX|YdB{xMqV3C=6hi`oU$2UZjn3l!9B3)t=F0ealO8W +zo+IiJ7vVnO@)Uw5oF|^TChpp2Lt+W=PBxqxWGl1;g?R{Wm9YgVmUJJ%I@8Vs8l45U +ztJr{_>?(HThIl4XEOnjhnx82FdyC}#?$F;7%;s`|40M{+-O9v$MtzKJvWOaTiOh}qrqtfS-y@*&Il!udk&G4dk6zw5aiUj-lhC#jl` +ztPfJME{IutSau-@uSC~d{aZ<`vmh_*)nXb?jj!AXL8Sz*M8F%?dByB!Pj3Pba`s_L +zZOiveWv9}2i}&Xq?t15PcXK)3svo$l<~-8SlYKn%){k_LHs*N}0p9|AkEn|ly87hD +zki|y2`bhsXy9cRa>E)lukA5Hvm%Vt8(3bN4slQS|`|;3!9mDWNuN9W1lD}Y^CKMYM +z>yw+p9qY4MJPoJ*tDBX*hh$;5-EPIvG#}T;EJon#X0kA1rY+J4;!I^t4c7?L_%?M+ +zK1N)$Md3kdsT`@%;XydKGPp8_u+D~Z0ch~KXhEN~4kN?(yR)u=Ku@@>mHX3<^FB8p +z@N+Nr=vW?Sy&1dB76-yb3r7QTaxA{ku@KHw?bML5khE0oQqsv}ZYtj&J(ffCcQk^H +zG9YxlAU{A+d%Hfz)y4Kypn^d +z@i}!jkL3^Xv@SsY`5%h|*J&<#LiH;tKuYp_eY)rZGyI2|-Y|OaG(U79KsPzLxbRs`h +z9FBUvbR*}3$iL5ByzvnOO~6%Vb)ibNFZ^ny)$ZpistIa!+R99}wYS)d5M5A=ku(rH +zD`*JZTWMh3?bN7mKC2OSg>=?@l$>ew8lKG6vgKAB2een*ijJDw>Hz6a?rKDiW1b(% +zY92eR?TcpCZAP}&9o6_3<>ws)Wi_`t4b^~R*Uk#eHqaO1Wd=i^{0dn2b}4wC4HJ;; +z3sj)(e3dt*KFOlmRC2e-m0${lcf|x^=OWoN-Mnj#P{D8Rx8x=o9im;JPKP&vOyk;u +zTTRl{&+k=gCt<2x6-e|M7ewZ)3pz*J1&6)nN?Es;GfhqpYlD^ac1<`7(4@6q=YV;R +zG<|?sYz=F)u^L;P!I5U5v +zT7sa*;OvUtG2Z)L3to1A7BAZg;w?*k_8Xm2!0(#zc&d^UBzxZ(o!xu_^Smo?l60a- +zMb`{T-b5OnIdJITUbJ)d*5yxw3Tz>D*)ZBC5}>vZh2ZR7_5Lo|+WG}0f0EBs!NX)Q +z>Uh@t8SzOdQ3XW>F~s`FNwVc;C7&1LQF!sH=doxG;-}-f(f?Pr`=6Q7={s +zy0bf9rB$V#>7eYZo2`JSfCVe>;dnAa=Bua1Ul%JEBm`(TpfMOPwIh%`=eJ-vHxL1G +zUam-)tXYo;ug>XC$=a`_XPssbhh2p{nR?7i0bOlbOlxx2dIqKKp+A%M_+~T1xyzjm-|NPk5}?Mb +zbk~~upbZ-Rq@6Hw)(n21PLnM8ntz;LB%1wWpJ(OkFB&iV5$u$UR2NTGo5dRa3>;Oq +z$l=kWXZuMuPlZNf#1VcELul$2A&oxM&gMSmqluNRhAbe*f-C>3>IS5qDXv+^Wy}Jb +zM)ga?`eHMc9!eDutx1N>e9n??<))L^`(waUtMiK7KHdg}W2qS-)1U)7lMZE9xxAG?2iTaxAs?GL{`ozX*6~*!zSsJbD +z*Pk1fMF_i4hvZba>NH2MN~PqtB`r9Gg0mF4i0>LU`O5Qd4KnfL0b7bH#!$~E^B%K$ +zv*c1uj+R>Dma$4_(uWMT8)U3=8WQth1KI}+R=CLsjs_dL62Y&K-3*`O%^&fk470u$ +zH5S~YZAU;GF*2N&R`iGmCO_T}?~jcQS&0tsv~_9=Z0zcwo+2CRb*Y;0MnVq9;)8jj +z-N<H=i!Nb`Q;1~F_~4}er)^YhUQN%5BaO?~dmFTQhn{X5O|B#MrYT7yU#pGG-`8$U +zbmCaR>ZYxD^0(?1I*A2ehDsLri%M~)PyG!ai@qME8OfG+Ax~Y+JHXtCIE_za`p>g& +z?P|H&hEJb2V{QO{>6&d!oYkYn6T}yaOfv79pLBwiT!PYL+LQDSnNKwDh@WDP-OO`N +z_;)wUxUNw@Sv^aJtBm}Jem?;{gPI$?Wwnipvl9IppuOqJ${KE5MgZ>KYVpIAYt~nU +zt{MAV&DlTK$glQoL$?>Zb9~nrKLtP?@M8i+W@CJPAa|db3r;0s+l~<8>buzyVKV@V +zpfScjqQK`sw_+Npa>s@r@7Eg&(A##^fBx#{b$jK^G?0*qA%MILIvCPkEeSd +zr8l%EsT+K;f93o(IhP%4>DD=C9VPr$J#YZq#+d;Z4!a&u?=fGk=~=mTfIk#&(@w}i +zT3rp8o(tuN&^m_L?@PaJ6fE)i9edKZl2Z(r!gD)rMPeWB*u0(t@vx6g7vr&zHx)74 +zUmZGUlrV=P=%!wc1sw9L1Sgd6iL(Ha+)my(1z2kQM$cU8{wu2J^uJ)pi+sI^qcSh_ +zn#Mw2?FHQcQ?FzruN_0L>VhJ>H0pEzRo&g$nk6!0_77jk!zLP7PmUjg+afX4jGMZb +zjF6!uE{9!LCP)={JGy7~0R&Jgc&j_Q2REX>?RRIvz0niPg{IAG+#mv4l#0v0U%>jW +z=%TYwihgn|Rl6aKd0df?5a^qSVOALF2{*k>@a^|ve=I`}$1#YuZXI#JXriNA=;v=; +zaDa`YIa}zr^PX~$uQUUkGa;I}ru~mIoio90B=}R-U|Ntl=^>7t&!Q)8u8K*Vq=5t@ +z=#$xJ(KPZqC#{(3v&CH13pjlaEcO*2xkhttB_Dr{IBOSuCmk4S=Y8iTz@9f|INE-7 +zur(i?R@pd~2YCZI&3K}QZOs%J$(d1`_3VqG(AF8aSpvtdl$yu&HGvpru8b`Cpw8rG +z1e1^)6ODQW2d>7^wmsLh2*-^(&dCt>8(3%78{L<*VH(JyRr+zZ;~E&Wmf!Wwu*v67 +z99BMKQ2W*}ZrzSbFI{(|*`2Zp}??KHG#1rVf#JEQt(uQk#v)gH~t^&%!I(g8C +z8>*q!RI|=_QVy>);ZhP +z&ePWs*xf>nN0;hpCDaty)B?J?v_XmtzpYzk{UfjoDhW@52&_pw=Z%OG!h+$u4nDX;Cc3Z&O!}1p!mZ5vNWW9ON{*QJBmvf~qOHfAIMrCy&(k3-@a$e# +zy(3$fT}{;kSY9dpbp4J1xJAI@Hh`ZBl>v7-GBX7^L%4~Z+#2Jc3)Ubd^-u=MYe?Bn +zlLOl!x7gB-+`anmf`A;6sk>7@HwnGmWGJS@ZQ*#O<4O)it_^ZGqQV +zN)NY*hWrg~R6eTlZSXx76n@Ik&ai=#L7nZn8_05}{*)mD0PM};ZsmZ|sM=uH_5!1o +ze^BTv7>D=2dSqUg7cQTan<21Cn-@dwAAzv>}vD7xM +z{SbL)OF#*gQq0*7fq}!a7sWn}n{lMmcE=r+Lth6R!qu!}g&fXpD)$}1u3-7TYvQjI +zF?H?pNT?H-PY1E2)_E*wJ{0Z4=%YqztR_#|zS^_ZQ2-Znc52rG1O^u4(<%ZtR9-|9KTJ=0)UZ3RmNHQJ|8)T%}X=g|nZhSoejspQ;#&^^h2kj#$}+ +zx1X(8$c3VxfLN1NeNSt_H0y%ia-8&t++hd)zv_wrGA_+0HR6@iz-kXYL9vDlQ9qxs +zX_pSaj^CxV06D?UVnIA|RVVT;3w +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 +z485 +ztMn}sm+0H|nu)vhz4}4DPPfXo9CS=SrKiePubSncgh# +z0Phg*Fz+aDfo@DR(r|bucqeM5dmHE+-xA-y!=ME_YlsamI@HI3SUqc7uYv|+n +z8ah<@RQZeYP30oBVfZHcB)*A$3*SUX;+yCwd=vdPzKMRv(A&^k$;UU*r|?a*0N+H% +z;G1Y6zKM>-H&GkDiQ4f^)M5Cc;YGz|m~WV`JdJOn6Yx#+yZ9#h48Dd=qD=p-@~mN} +zVW%<$-$cKMZ=&DFH_>V8BK4<=8^1JItnN^EDjMbWe#NUcsDDxXl)ug7OM^07DZ3r3 +z9vZRdxaYLztf#@#MD42Q207lMb<(!W3B1GS;raJ13DLd``uQJbQh-@8q3nT+dS^aWr(HSXf5!#BtD-qF^J%6GuR* +z@;0@vAp*J~0=m=u@1wZo@8LaZ&Of3E<5_W;7dLx%(Lw(=6s-7W-os2jH9bV}{=vb|?cCL(0&U +z;Yst6t={j+Zriju+C0xd&(K8E`g(@THo9%o7J3RjF445bo{64`+H#V#Y1%4nt!D}~ +zH#ILeZ3C{;Ju?$ctMbggyJ=fsVYa7CwsO(5?Vd%RMOqEv(z~0s*R#^IrnRkSUD+yS +z+uXJVHV3wOwt1=(&3nnSN4EWKTcFx=DDkeq9?wx~>q*k4=|eoto|Dx0eP_7&votGR +z&*2F)z3Fc2p8fs;SlFNNtmlGgf&HFKo=bsB!sfeM;1G@PW@~e4#@3c1T05RPsMTp! +zEw!~B)6&pR-S$MHY4uu$);G~G +z3-wWY0mqo`U{B~1I6m~r#7)I$b97A)qDMiDRaoLkIf_|26gU|;gJ?Jh?_YqY8}$g~ +z&Oq|tP|t8Z?y1!0l9#Re0_tCdzJy}gt*@YXpRKRfjQTo?<)y_H`bI5}-n)e2q?~j& +z>09+3o}2n^eV<-SJ?8jdsvpKE-85qdJ>~jw(s1dg^|NG)vlb(QrpOhZ-Ez-Fy@C4Q +zL}R{6@n8h_}(3yi+{oUN`5Ymn@U!bni^>Y;T#j+_TcVNai1BV5N7dcRIzI74eov +zcUNjQEzi3~OY^SxR(dyUMc!>RzcgF=5^uG4k9R+LE=S9!KCRU1yobC;N&6(VGg_{< +z8WG5 Xl+HHsMalJ^|Z1udU)c&WFU>?=*#7J +z_vQIU`0{-=-*}F3@+{`uH%ZT;Xv^~zd8hk|srh|jZ3H*E7xm@(=FkXi+9bL&Pb=~* +zo62#xai0+&470?mGnD#M<@ +zO`4xGG@g8lm!&~tFomi>Wzb5MV!wB#uQ8bF>EWp^uJw%%rUf%NuPJ88Tfx4;oM5iE +zGME<}K@rN8qnWB1d#5r`9jF!>o~8c7!F;mC^$rmXO;Keig2~p=pv|)~INq~4ILWhL +zGm>64_2*Ksh`4ROqF}LSk3P(o>mL^M2gAWAs-Uc7!8rj`R$pG=Xy9mYUT`7RxpSh{ +z1s4aG<8Ab&;406B;99O`gqMPAgByZX!7cu7L8|D!B2l?eyHWxdf;GX#T2XK>_r$lC +z=80pc$am0J$MGYYzJ&U{-*=2_lJ6AFalJO4X6HP`RSwmI9A6{(dV}w>Ho|w^*Wz*c +zRX^1o&pCe=f4Ab=;#z+?&EN)#n@gVA{!D+Ce}I38f0%!iR_r~)e)nwC^85vUhv$-i +zf`792oPR21&mt-?K`l)0KSS%|dH*QNU@O(EV!9LY$Nh7)H2(sBg@1{Eg{MqQ@vru; +z^KbMV^>6ZT_3zNE{@rBN>fh(D^_(QjXZ(k$Pgd&7asO%mS$~7S$$yplc!+GLcrKCV +zjeruccoqdZQMKtxx#Xg_=|RurP^{zydQ<#12Ksn5`?GwFzD9kCuikUUdo++87#Qe7 +zelP}x28IVldk+N)1Fpctz?6VH;0+XNHo8vtHV0+~W|MZAe~GUyP###MMFUF%D+6l+ +z>-|dtmAZ!ARR4dTF#my0n0_UK|Ei%I|KDWXm5Sjxqmt_0K&^_}7HZq6)wpY>P;>8f +z@11sX+DZ38YIW{9$c|AvMU7?k)Xr0*=O#BzZgMwLyX@vOtkLSSj-z*U!HGt}iN=Vt +zj0t;Q6=xYUPB9kjc{|_~lY&#sJvh1Ci<3(y?0K!&^WKL&Zx@_d?#F560maZo>k`J8 +z@ZTM}hbRWOgRaBqIzhd^aHG56tB}n`*G)uQzkqfKvK0v`-2D}4A5m>PbXbrrO4s9G +zjcoJidRo$1NezO=o)K5uDx$T-HxXUEn`~8dz47H_+fGzNb`?n$qE2@b#@2?$c5OpF +z{toI*)TbTFZpSXuz&14WtC5TRK6W_K=r5o`L9XM1#=5>DO(dGq4!H%nXx_$pzZ$t{ +zZpTiSG*i-SL9PaIb=K4MC{Y4%$Xk +z-45*`+TRWxYC}iA8rja%^`sm5(Js+FTO-kBsdw%x(gmVR?a)bSvxTnBUybZ4U2ond +zoAEZa>U5FUZba#HFXi^TlF6Pa-*5eLvS$$uxbt~iY8y&xhxpkcbj_gaFnJx-et*7* +zY<-Dx+M!&cymn~Bon$Xas^7`=Hc>BS9kV;!t@Xt|!F^}_NW@9Qeb +zr`DR1Tmuq0EOU$3j6}?j>(M5ro5g**MieB9h#JA`i+!$;^O)=lh$=*Vb@O~towTnY +zS}oQ9`#M?QZ-{uelTQ-$*-mSkeXAI+eTVb|+2nf3HbHEc=F?7f(N4azQy=VXw?X<> +z`jel^Kx*gYP+Ly>N7r{c1Z;ZRV(TO-amCg;*OMT}9s*!WbVk-B9s{jGj?MD9FRMXq>v(%Qi9WYek6Z7h+@>$AbzfFbGw!6j>SS`Q%uTA1 +zN%auA8B!-t_<(ElIEtTf*@Ad)!}HC1nsEcAjAF%^PdwK#xqlf)dm~4)tYb8%<2bg; +zMLlz}@7Z5+PcW`f)-qoISIRoa@keX)II=g6>^Z5w<0x*%k-c#gXXDr=#n`wqSw9o? +zamcUU)M@yNz`^LAIYKuOn{fAm@aW);j0-r2Hd2=OmGDPFka# +z#YBFw_9O`Ps7m;W$LtIfMWt;ThjWe`r_^`Sna;V8Xfe@pH)@e{6%n1`oEwO$#QMjC +zI!Sv1=N6*vq8>YIM4a+k=-f+mkf=`j>lo1~aZYfa7k+X!3VkQ79nR}SEn*MI^*>RY +zU9<+cItpTYSZ64hxTJG +z+K0JlU*)3xluHx-bp>S|qw%{U@){TM;G(^di}pY+S|eObZpRPTZr%^LXfNcVy^w32 +zl*^jyqWyqtld#Wu;vyfpXb<4pofNByb3kH^BHp!6=(uWyjQ?wl&U-t*|Ihy#;~(i; +znVPNcD5)L}8*R(Hx?AL<@-) +z6D=oNMYNV^15uTvEkxUiYKZm{9VDtFI!1JgsGjJ&d}reqTrU${m&E!lijtxVc}hp3 +zF0yZp@=9Y!=|+@Jlquw`*DRs|qOU1KZjU)-7||%A0wRa7lQKcPFJ&^(R3c5vgG3Rc +zxUictmuLY|1O`#Q%0aaZNm*uzQb%sFR#;lHb$y +z_Vu0~M7@L{{T +zI*J{BM;H`!%yG;^##RlEwjF;JZ&wvzNCEDy3G2n@{Dztb+_aNmO++sp@7@ +z)y<@;o4HWxE|&T%Tb}gqRr0!4(uSmWR>^;FQTo|xsU5Z*x1F|~rPcsEYipu*)poqS=c0erZF&Z)_Ox +z8yhBTt~FOttxs7C6ti`#)v0vA?`?FlPO}!%JOr%IE4{2Ut))tab&mCiN~U#z^+!ry +zYmK!=$+Es@eNTDR+GuT5vi~1jH?(|D{SM(2iVj1|z2G~79|V37_`zx+;Sh5a@?yw; +z0e&%IuK8{7h2X`rgTRl+vyTxDfP9D=h8=!37xs(P!Hnkb@qhbdof;Hftu3E^2gB=>S> +z{$@AfOJ>S$V;uZQ;7RjL!ZOw|7=bTCAN@2cj3zHMUp9LPH^S!qEHRv5-f#tXmqGt2 +z=>HsiDy&@r)`tKw+s_zp{P>=Cjm^XX|iB~;AIGlBqW=4Yz_&4A#Mw1DeV`1kR +z);D|t3zgvC!rd{@zXknl@aKVhf$u>7qFO?l4)ebef1TsjXfeM>d<)AB#pYVVvnoY` +zF^zSUi{|-+|HWuHFC~PgT-ZqirsG*1xD41`y@k8a5&r?B@ih1v;9=m)Y7x(o@2YgSOMf`yF+sy?rwqPBqU{!tP}IjJmGd= +z6|e%>1Z4fO(432>6oKYfI4Z!ujGk`|r=I(4xM)5^colfj{2DLbDLcg)vy +zXx0NSNSu!t*vqj2Nee8rz(NZwv>+$M{Qp9|B{y%ZkyIuoEfYX5Q0~>*C^E9444R0KVwZq_F2LHN5_FgUe`E&=i)>)v4 +zH1Hb*n%~9DMlg?j_X_xnmT$3#1#+(xNa#$`uS&MS!F&!}mgMLlFqLr1fZ@Bvh_a$t9OV>5JekP9Dze;QaRYap#J2G}=t +zV6+_J*|+?Zyiuvkqq4m)ihkj@9 +z`=DPYt49^;Kn1T3$U!gUF9YufK8&}V0N(0Q$g|mD6W+^rpW<1j%w;}RBHMgi*5tLs +z_drY@fg}TX%JLx3FY4{H6KMx9%fB*7Gf`jB{X*&!>L@)4TnS)(^;8T +z1kB4(_Au3fYQ$JIvQpst$d_v1`&dD^R;Tf^)eT`Q`!ym9FrlGf=L;f~=-V1yN +z#&VW-O2+Xj+pkltgbloVH1=eq`I?Wa!n3v-V_eI*W*UTb@KHunhDs9S?_v2>XkLNk +z{{a6V;K#uJA@)2WTehLkVMb*O_zS>i%^elqSFrsjF;m&FP$$-3-bc|s;W<=4j_^g; +zy6VuR7RC{9$_s}#1W4}lCmV1&3K1Zd!tKk4f{aclGgN9M)+d({wXg3a1r*n?u +zsfoM?HcmACm2idn6j>gDdEBOI9G}Kli9ZHwpGstFufxvcu$il>gr6`{)b&z$S4JK% +zb$}n@nJ9@hBGXu9f(E +zI4ZCPgXw({)ES9!O&N1hJ&E$^$xk+V1*u%;q*^5?L(?}<}DA@KLG))V%d +zfyaTH@a$w@0iN9f`KQ1`Dn+R!lgDMLVpM~yqt=;sQl{fwmYHT=r;6aK2t4pN=v&#V +zmMY}+AoTVK;^Y(HQh81}f!W!Qm^^`5I|0uiJ~_+C1ATd>%-sps;7nwMW^ZU70bh={ +z4;S%F#e*(M)tOV}IPQKD|9&cgEEuI&eU*^wC#9V{lAtHw*6bUxW +zpbaxl=V+ze^hY{Zy3F@7TIk&R`3IbdpMPMcSvI|jol-6PM16wS9aU%E^fvH+KwioF +zG4*v+Md;JsnD<3r$Fp|qi=Kz(@A$l_9^fi%!uiqk44;?PF1Y&}JoQV)4i7@!4Hj+! +zH$mTxI4R?~FulXRHJt%J1~`~e&EPpwGZ7mV(0>mR^%0|a19S!>D$-cf^b^eNU%>}) +z_fg#KfoREx1#wp01T4h6Mq*d+I#$2}_L%7ttRNMrjr*`_?C1T7X&rW?ORxs5$Nq3G +zBrjoC(*!%afyaO!0zZPCbHF;_EUZl*VV&KPKi~(3Lsl}8=AB6)H^I8WXX7zn5QBt +zim=z61+)Vr*cr~m{<8pQQtV*WzKEZ9@h)hZD!7)akPz}H8esWhiQ9oyzzQH)Ge62_ +zQp_|L$rh!Yk1bIlhq3j+D{`T?I_$r~IMb?Q9y +zjU!e8zY{&*iMyhTjsV_kP9;=$zRW!>PZPhM<>rSF$sYq>khPR6PYr76GUzOV{+r0S +zzao$BMMcd+1zrvQU9P|sSM-#559Vb*Y~u84S`N!0SnCIVJD-2)gv)m$(5zuh*~Jl_ +zqTsak3s}ZClMbTV|2s}M70A#F$e?$S9ghQXIySup3va-hqP|2=)xgegxo;}IQ>i!+ +z(_HWxs^ctN$~;+U0vQJoF|RrKv$J|nCD +z3XC$E@a4o*Ygx$a9kO^C_;;ZHI-dO*GQEN&7C%=5%kz-`4*K=LXMpQ0&5RwU@Ja`r +zUvlJhco2Ly;9yw03H=r5b4Oks)UN!UN`1_nhWKIL$bB<6^6aZ!kvnt6c@y!l$$XIG +zgyrfd@=VQNEUR$Fc>;MohS!J=g_ye!F;h=6Z|P|6On0wi&DzN)Vv1g_3Hf}tLm^g{ +zb(~F9ud0FXqb^kgc@4GUJ5oQ$&p>_#^3NbY2l+>k7s1-cc#AlB&Be-i47iiuYp&-J +zS@1p9v=t}r^;qLpvA*%&_fz_eh1XCq_-+}nLRJrc>ICY>dwlLDoz;-9M*mT-EH4tj9esXEeUR{f +zGO8Ky{}zn&PnexJbe@%(Ea{DN(C>MS>iv91HsPzXNu1hF;?#B!HTehdLptWYKh9;Z +zAX<8usTNsM@YFTz5Pr?)adS|mlZCnjH8zZA!+3Tv_)314@tb&KG3MoUoccA4=*KwW +z9z#Z`ko=5Kjfg`|}{5*-eXJvs5Dcuru&kKBt>^0{?~25vKpmW4CmJ +z2W&WlpT$#dKBt?$27Wj0UPXWYf*x*#{6F!xj12aSB@1sK0i1^MP6rN^drMwbd*Z1> +zd~!Gbkx%ZXAHzRA@%^wKJ$w#m!|eP7^JwQ;qv$0xz6D7-`nejXm}S6`g2xGE8FFnI +zPCCo@R7H2`Bw~I9JL)~q{1NaS^Gm3Q%v*tWfv{kQ1v@N^fo2oVdi_|U_JiaEB&$`L +zaRZ(;_5m)$dHK6IFMk)OuqSZ7dxg(R6bYnn^h5I_ys;bhpZ#I2KR>JHgP$)DlKE_n +za2Mp6z+PC{$us677+p}MQ=w@MY(4?|Vss;bKj5<`^&g{v&3>@i4a%Rw +zl5ai={1HbHENl@7{}h8Sgdav)9Pkz6IGo>4@%f!b;oxsy>JhxxfeiW+EL?##2d`G# +zE2=zd^Rd7&dYSZ=DR-urb9A9Ehj#ra^Lzxf_kg=!d(0n_@9iXT1Imn +zquL)hpPw}kz+1isn`42)fE!?~Lih?6J_BaK!!H0sT=6;_U=O6Y;Lqzg_dSoV^daUu +zSg`6n$9K(-z{9oB%m=SC-{AmTOL6he#N2}O;1d{^h>bkVaz5r|4fs@87!I9Z@%I6f +zoBgk*VHUO^HXhgvM82m}-klgt6 +zE&d|fANUe54jc(Q2`pnY7#WqTkmLdtMw1u(%fOAm`z6nRH8_E1uRyX4_!OS{IrvoE +ztq0zK1aC1;faEjq!v1i)y&3os?*0w93)W1~84G*{@=qkseW--wEl9?IzlEo=!Jh~2 +z1-=8k2u%n0>)VVn1pB2foUu;VAO_ZfgeDA8hj1#Fm#0X +zo^JUzSr{Vbf_dXe;9B51F$>^xfeP?t;Kml-o$e9-XNlq0z$>`>2UuPuMhCvT@H}){ +zp!1Lz3ncaE)p_to-1!e#T0YAmNLy5%Qw_fGHHbVcWA~s-cIr?x7I)8(&p60Bi +zoa%x2XIv^~`SZ)1aTsY_q7j%u*c~_$Scbc0uvW$r@+Zp+AkPIV5;J&R0ROT?)^x$! +zC#2^yFbive%s<6))6a4DDxP{AJrogs6(fTG4X4D6V5F~$cm}UQXB)h9R8$Z4m3j;w +z6ZxA8J{_Lf3;n$7_&Dsuz`w?5LKd6GA_A|&Z_98OvuWrB`9=1j;U@ZQf%nod +zq7-?ODwi{v#z!F+8S#7I +ztFWxYf)2~arI(l&mF*DndLOd&Q_KRYia~|vpM)Jz3G0A=xiy$Q3BFd;Kxi(4<~KwQ +z#9NL)j_gzCA$JadzjkX3^;4`P>rrh!WM8RIf-iu)33jf5M1Hj+P +z>hw4vRtm#G=xh@i4MYVnu7HLGB6E!I02btKClHO(~yTf^u=GN +zVuQRIhuAimp$a%v;JqryD%Zh}zz-_|G`W`{St~%JVKz$V2N;KSClNl3gPkTX#i4XF +z@Eg>vk3Ggz?BN%{PGf=4*ILpG-mWokr&Pi_IT_enE@|F!w6+-(bMX9k9qv7`LuH+? +z&6_!^a7TuxEuu!qH8UMgaJCv+`~W(|-h+EpJo7Tw=hQ?LGvi`*B)F8_!L)9FYOXO1 +zEiT$uOf(wg6nhq#{Ut3)2Mk*6QLCmwXAbr>Lcr2?A2T1oSH-J%gelz0yrtuiBH8O@4{mn02M500N!Uv&EOVS2|Rw2I@I6Dm5=MCy!7@W@U +znO;Co4YR8tl6^fWZEVmP01Y>Q2Z6(Z3)$@Flrkumv$?yEGxzo41~@sLCa}}IMdld} +z?JzVQFsS7Xy}`&kRiGyhwc^>lzgLXMnbGIzux*~%(?+d@z{=p1F!Ihy)H)tmVoDo> +zGnspvYy*DP0L^>0PrRELf^43wjF>Bsx +zt1pIYe8B9wh~?salXb-qW4V}V=Cz^4U@=%@UtykZ3nOoR08B8*uR`V{fp;CnD2-)! +zn8vR_-_M^xkEX4wkVIYaBOfDf(>V_!dkMlWp+4qUeug)%RFVyuu{!hAmUA475(wl-h5g1oORgPW6-K5@)(X- +zVpcBegjsWe1%RauYHb?n80b;JoYp}|9yBu@^Z~24SxumGn>9n@7;C>-kBlXB3L35% +zOGG-6c?;dXY%mlH`UvO<-cENxKLq|4;AlPew2;K6=C%sOxLn415RJ0r(3fD}YA7_$FF> +z9rRk*vkQ0@oKK;x4Qf?_=snP3qMrbeBImhPKZGv-~kK +zwBv!34*GF_jKKNOA1Om~b6_iA7ieqYj~8l5f7C$3C!tIJs6l={@FYqL8I%RV`5v~F +zf#e8aN8dka{RvpO%J+%k=rz&MzQ^EadpfWRT7fnx4pauC=9;=uxnU4lE8mUqdDy`r%Je4RsfR +zk6GsUvDzMO`7^PgAA8WV1vDhZFw{B+nbAN$Lf}2_>PIr#y%)Y(V9>e(&IGjO$Kiv( +zM}Q4bcRT3v&`=I|3ivztgV9!N(9b~+`sJW?ry?XrLeDtR@Vr2Nux9{!02@KZZ}DfK +zA0f+7`YI6P!uinRYe0Bjf@5Dri@m}3a~kHL?ayw^Tqg%OIf2LwjHqB}6Mm*bRuPvW +zkGgge@N?j7@crBfnzwm +z1E&OJni~x5hGZ#V9h4RV-3oMLNS*`-e0#V-SrBw_lztCP1qZG0kD%Lv?hmXF&H!L9 +zgBGk6RZ+ST^kLW&g3JfNIVfER`YX^Efc1bcf{z|?2I~6SHUr-Qb^!hY$qJy+FTRNu +zUkAMw_Ur8l-*WWVo(`;ny6Cla1*PbbSdO|FeP;|X8S+zsJAlsu +zeGB~&_xsfsSQHx2cSk`d#!(bQ3`9fzIArF6ehiZSSXT$4RuoF3a>GuB%+t`Y7#NGv +zk3b_b?VXS*0?qIY!+!o6rSZ@M&xmT^F9ILY>-aIy9@_i}_hWSn_>d99z&VG~(Ljuj +zfFHOka00aXMT?PrpUp#71;XfpgCLWFQrAYz_J0TFw0E8-tx?I52!h}95$ +zDAA)3N^Qt9@&i9?koJqcWOhZi>e3?qJ_e7}oSL}rZfABIcsh0xYN2$p`E4x6nfKFp +z9QIO#;fOQfk2HMqf(4mhTNq9=gU$|vc4_caQMU_9Pa6z%1>Fu<6WT8Nl4!Sau$xhY +z%pQfgH=GR4pkT+NG=5uWc2R0$|0E6jA+gvSnFsz1Q&(&UryWYif)>zl5!eGb8-4c- +zivI9GL$gC7lCf)10dxgkZ0Z^r%EEp{u3-N}BONg^PC4jFK&=|sA*pOQRxW#@=I06a +zM&@A;WFGcIG-iI7W%jA+XKgjP7j$EDZ!5MN+IkXn6O`5fy#n+eNcI681-ddy*Pzx} +zaB}+Ez&V;}?)2}6Oit8_2ev}#E+0{vA9NZ@KY@lK;LilVBIr^m4S{|I^bp?$LtA@& +z8&KNI(3uHY*L5Tm17{)S)3^`xWJ7Zf+{z*!C) +z4n$A6CQ21J{WF*0zpxw4D>KbbU>r1e4s0;|17?i4szEw{x(k4#pba}7;y5@Bjf`C^ +z)4Z$p7)q;Uex@;#>S%rpWXc+jxa`{u&C`typ}WCZVQ6a<_z9U`nfNsF_F9zgGNroj +zW^_DgP5?hIbiNP!@5)Nkb`F5G*I?T|Q_JaszMKSqDx$8hsby6}TfIRSf}Z%ybUZ;w +zH~s_;H>j_s3?2rj0Ax;r&S{XJfK?SRYRPD;7c{qng@+A>Z1}c>A0b(dOw<_}k<)O@ +z_jh!L#4NL8OkYBIA%D`)&Qp-_z-i*gA-r7xt$6TEPUA6aFnZlM)9lSA!ou00!z;Ov9855Rd0 +zl9vqXjDzv=;}G`OL0^u*hQo*iKa$6oUhBJngYXi@9oQcul?wSxXef=gDx)+W@pBmb +zN(Oa)H{(((kTG~1F|Y%gxBLDNykRV_fxaAuukwH&0XBwYV$g0n=0!SUF9ng{OB%lw +zG_;QG6hyL-X#pGs&I^#tkGAqdaw}>jLuNd12}}l^y +zqQ9N}UK>drMcB1QM1=ycPDfP38^$wMduSeuJg^epTOG7z^pwL$stFh)gyFT=v~LB`96wZ^ovIheEKbm^D= +zTsGQtwj2wq%AuB@SB>U@*d@M5Z4g&&%$lCnK-147>drz2d4Ti{nQgSmnK~YpVK#k+s7S|?+;qfhI^sDUV`1nU@LT_270U;X>GgQ@w2HrqA?IAg +z=qxuV5k(TK44;N%8z9y=x@_W5UjzS&9GHR}XfjMg*jX7-8jl#>j;Ka1(vs65Y2?2E +zKM|5OK|cfj3|PJk^gQsN%G?R;g4vg1uE|X+nd7pKV!RT}Y{i&9i+&aI*R{+wcwV2| +zSPRPspf7QdOvuDF59$`6f?8+(U}QC&G2dt=!gt=tHowyeb{Y**82qr|6B$lsQ}dQ} +zW)t%!d?tPmk{JeF7IazA<;{EAnH9{t^qSuV{5hasGVhO>H}f^U4)jIP=M8Os#iQ#k +zHD9>_zk+!iQ0tkCZ?jy(_idING`}MtGQV@rj5WXJ$c#0=2gzI*N;F@&k#C!?+!#7z +zg`qPCgx)t_xsjKR{?KuQ@)GF%M!!4_`X*>!rU9@#BwGU8nD5>g+cFOOHitfj{B+QM +zt+TK>75pOL#~754qj#l&m(bsVC|v}U;6DV(>S*gc_?w`!95|KX8K0Ae(x#9fjutn; +zOKHGw5o;5uL` +zO7GNIMt%YMOXyq)dIV&?295@Q5$GMDuNn)@S2(n_CJxKvxjbiNfrj7All0888E1?= +z85j%mB*$)^8L@j72o3R#>sGEUaXG{Wp96Hy4-Ua$1N)b^Rd%-yc +zJ?0G@qOdhI>MU{VH@YTL>?>W{zDj))TPAg;g{1HNo=d16NBYhpD~ocIM +z%+Zm$P!Af4|1s#-Q52A6i3C$taOi34XR7`(YxU1r5NppdnrGa(0a>LC8|nKQcbEyO{t}}`+jOf{b&%q +zLY=4^y+I=a3+^D73ejCuQfsI{kI_?9i|SJ|YDEq`K+jWu8cgk}GbK@P^DWcX<+`=z +z=YcJN?SP$uJ%D{%w@ggp!N5_#@xU3t1;8b(TXt*9tAQJUTY)=)`+$dAx9-%1PXbd7 +z+5#8@EC{?GSh-DNhga;UfOUWgZ92c!$!-j60c->82>j;CWyQ@CGo`pkpV#);iG%17m=BfdzG8SEmTD +z6fhoG5m*IS9a!@A=~* +z1>N)*Ig5ZxfvbTVfLnpPx^?K>&N%=)3Oo(G2uua0b?el+ONfABU@Wj8umrGNw{G!e +zLsft^fOUWkfz5zzG?oh`0+WD!fCGUefMYb44^0Hl0L}w00xk!x)mS048Mp(u2Y3*8 +z9C)@{_g39Pmx0%T=?0|$Mgdi~?p?acSYUo&9IzPheqgyI?MYb)SQS_USQ}U$_&m^D +zjSHQ7V*iOF>v?_`75KlREPOch|BQ~#7>>@OlA``?XEx4!+R|AsJ4XH_vd(iZzPbFb +zP?pZ#e~dZ*GzyG}&|1wIc6-eFV6GDXG~V&2@$SFFm_Lniu#|DMZb8$7TY2gqBI}hZ +z59R$QsXIXly*?HCr;dfG$Uk)~O2z((qor5Ue~kawCzf8p|1swHQ&?7CZ6xVce+5Uovl2ir}-X| +z)-C7Z3b&to({Hb@uHUXdw#n`1x#@QOxnr}P7t1DJGuwHyZ0FhflY8Io=XpwGJFlPZ +zyw~ma7npi``Q6KJKQDTJw)4`roa^~lG(KDT0Gtb*A9DIVEMDI~mhgLS>zK=a^Ge< +zUvm3-`G(ofpU-yQCEIz|Z0BQdi84)89GC5U>Fx3rvyIZ+?MNZlo(sq+~iw +zX;!SZAxc{n>op+Z)$|fH*7BaySX)~kqjPeczFUab_dHe9X<`whZ90QvveI{2BDX$2 +zhhwtZMM9tL(U`3EY22XuY9cg06;g+_t*dnD5ge1%QGHyk&yV4le2e7qK=MQ&c`}eZ +z6-fTY-e+KM9oYLU?EOngU6j;AN&Q<()FxQC85VAZg?}m8j*=ZH*@+TCQs_TD&0JyL +z+>Q}3+N-&>SJ`{Yds=&am0Cq1ZPRM)Db^C^X{5jE>#3#dx5Ri6M#{3%tTa7pSyqvNDn@x!38nA(R4G-8@~ZpQ{gh9Y +zR;4MwidXUYE_ZnQTB^J*FPhqhsQ&FygI< +zdRjeAMOAavoQkQ|sx=i?ZB<(;pXN!d&D9lkg<7bq>MFgYuBmHezVkgm&yN8* +zl5$u%sGpVJx|{mrKcfz`npn+fkdB+;E#ik_k;tmgq~X#XvET)`}rw2(1%i#288zAB&G^y_g|((*};{ +z{FBZVxB_Kzb*@2KT#IX2f+z7Li|r(Pnq@n!oz_-4r>)c0D(}4Fykb>wIyfDy2c2$C +zH>;x4-RW*UCel${jr5C* +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 +zm_=x +ztxV;X#GB$z_tHH-Gt(Tzd;X~in5*#DOBFZFw60i?sOJV-8LbGkQr|s7pKNVZ2WKC; +zT-ecUR+f*w*+KHQsq=KwM*~mpE6WYpd~OY@_?~HyoYoZe^*x^Pb=+2G)$tgPX`)A3 +z_EYkzIcJ<_`Kw88$orT_VTe8oYxSmHP!x@{7i}M`st#qvq?aKb}3Tm}034 +zHnv!ya=rpNTkxoGd`a!BC~IPxj4Xhq6xWhHO?safOX-?2@{V*+pExdTc1kHWSmI+P +zDjSMs-W;)2EZ#CrT!gnG*X2VuN{nBYs2x^+(6;g+N~Ki!PxhB2UpVd?FEHQX48b8% +z4#n@e&)~R`xT7hRIFi(lgK@2KpQnW5C^X^K;tJzjzEdm_E+OK_WybYw(v&7-1Xsnu +z#lcMh95o#=z*1GxWkj$}0h7oyr9-QP+P^h_f0RPkqG|~CiTrE?gAvJQ1P%R_izI|3 +zl4S=zF%oA73J~`|{e)+MqL?-x%5TbPWR&g&&;-4K?1u +z4O6E}p-Z03csB5_C9vnDPX{-k*vO<$6*)UCN7@Rd12G%OY{ayI>N`ea)^H*X=X26zHj6ta4E3BUu5Hfsl(X!o4m#WUKfbQaC-{=piM?xA;*%R)VqR%>9~@U +zPUIQfKO(triSp%8jA><>r!`U#G-daMZU@=s6XKK|$8j^M%(n2EMzIKBay~FRfrMRt +zk26KWim>hr)JptJoqRWrOHr$g+$U#bMoiTnt{bJY*a(6u7}WdDkVg(Oxx=0@EnnhE +zQ8tqRkdT1H28on^ix9$rh?0nC-cQEj4PL`ZL@PdXJN8QGMP)E0Z3xkSojfN}$2D35 +z*nR~P5W7X5#Kb}m-W4yZ37i;8J6p(;eb;rs?5>;W0w&)inNi!$?&09^O +zMCi$sGJqf)F3ON}SSWgfajnW>p%TUa+>l)^SCd8Dd(LGagN>+UF1fK$hzx1Nf%-?nhpzs>jTJ08S(H +ztCyEx?(p>rKkQ?Ct5=j=cK)x>KW6Hi8?e +z=6CWrJg-IMzlB9>kiTGtLpB)9nNM(JpWraQU@}9FFqn0p;0iy%nS6rd`WZC(2~PD3 +zW*G{t3WY|AP>n+T_gu{1!dvV6FB%`e&B-<3G(L{C62fXI^r>6GCw)gc+eCOj^;usR +zom3FE!00srA^tnm?zTSN57nCYO~NpsfB<`Vxt+Gw;FGQQya5Xr?|BGe$ns|?ZAO1E +z7t%W5@dS{~uj4KRA;j|4LSq_pwxBFQuZDr(@I}Q1rHM&$F=7=rC5>4d$eE#*k-x#| +zi4OWR#9nU78x!9h|C9+PB)&GM6AE{mS%!Q7%MFPP$*d$aa~vu2D-I(PHMS5Qu*)x= +zIy@N(8|xBD9eW#@M#vPPL{Zns{A)w<9bBaNXo{7B`xy2CAJY!<1Kc2K1(|J_27qgV +zqzC^XcJs$IWseTj$$sGVSIGB2v@M&wh#f(<6q^Cp?>9rPMaMNMD^z(hiUqwgkbb_) +zC>91}90*Zl9EcE3U`=C(_JS?9J5n&k_4%0>88wtw%WAU>Gm@E8uD|1v^@dZ6zdvw+ +z54iReM^V(^81G4$AO3J(xxRQnVW^+&KbUJliM5xHVg7MB`Ytb^1okDkD!2U*W-vLJ +zOKdf+!9km2z$OgZ%sfn6ndeKOf({OfM!Bd)h!qXe!jva*pTWmipYJ5GKDnX8Ulv7; +z(Z$__#QQLbNepOWnQEejH6Y-}1*-hg0DKfOq)SK99Q}&g8pA|<#bP95jAtZl%x6R` +zQQ_c3tlfud*j?D~__^P4EOZYxY%d8dy^@e!Te6}hT*H>Fb`{&Owect4R|KV?m6nz5d3!-CT7Pygwp? +zh0tc^8zgY1F@3c;;SRlNZn3oDesq47-;Zq)b~H#rRACe*n(BAJKqk%m()Gnx6-PF> +z3K@zohsQbK)!Gg8-plt}dQq@KeyQZFj$)R1r8&)g*wgr&!|hiSta|CiLhJYKk#xq% +z^)!szYBf(wA3;KQ$X+RYy=soWz=J>!1r}5fVpN-%6c?8s +zemZ}t{&6A%Kq9jxdNg(7aGPdy|F2O}W)-5H?y@|(JUR*4I?1|krPASK0}{$ta#x5> +z;U)eXF8zS?$K8UgxQyit~*N6qgb7G#f;@mz1 +zXu*@37y5?9)tH8oHpEKl;RX0}5`4$8o~&ePE69H`!}cLtZXiXFPZ+<&Rg;hoqG0c0 +z9S5`d>Z_mafZsZPcLSa`l(zth6!4_FZPz-{#V4|h)ks^6QPzfKN?9j~1p}Qv| +zUm*VIHwSVZr>f6pzcn4$Gw>)5aJkGT5}gjT9J6$ACep9>mK}UrzS2jZOd{;YwF<2w +z+fs65;Pja|?6gX*qT6yO_x;&-Z1q_EKp!)9kYxW^hp73d_CV#9k%-fuiu^9dQNt4PQ^oh^FFWH +zYe%_1x%_Y|Cw%((yKe;=s_^bbC4T8xHNd8#s2zE0?_6(G03Vxrp|b-l#cnNFXNW*Y +zKTr-=+~0SIpECm7@^mgKyf3;4%UI^3j)iWE3>no5zt7^3jhDYr!#G()q4AH!jNHaZ +zrg&Io1bVdTlV@kgbu&iXi@<`7P)%>JDJsUYNkK@y5*h~t$}#$6AOT;AmLy*p9|>?5 +z-nH^^h;nasL4rP+#aaxES0zFGg#5_E&}_~|@(G#Q!{ozoc4W-EHvbnhY0$}vK@y%+ +z*1***3~et^qbMiU96#C@b{bnHa3_1M1Q%}*WlGZ-W`RI{KmDz^^+X^M`i13@0U*>B +z89Q8)LebAREFJo}rrJt4585E>bI*sNY4p20CkGGw@u9uXgdIZOFwq^9i|;3cil=&| +zajQFs&$rw^+BrPp&7x*Mq9h9l;n6QB_i8IpN=2^V%1YX6`lDv8QWx4k%TmRw_38fczC?F#``=z+LeiNEe*yKtoE7A_t +z0jOjfsx2GAh!U}u4EepCD?>{rdIpq6GWj^07}30UTDtCPcu}{7E*1h?N8!%eqMwM +zayXh|8|yX+Sw-Tf{$HoU{w;)o=i}NO%lZ1|ze?qc614IN(SxA!jp6fZDG}b_lx4Cy +z6!YW5*t95VksK>)Q=g}B8ld^I9QSf3vw)wMWN9C*Yq7IseJGI?1r6*=1eLX$G73Bg +zuWfGPkJ&qBnrS{WbrqqvV%QO(xL`=nMft=j2Nw_CpJbbwJSnaIp=j+4h|HJ=W~U0OFKMfZOr$yW-v~TP+g0PfwThBO?~UdLlDmisHdygad?z +zgjF5)){FyP_vZy=>5;7D6`o-n_P1b~QK+54IpU5|YMegU^+~0rcjk1eTCrE{L*;^e +z*M-+1w_5}lRhjD@=TB{|c*$4`bo8t@I*{N8FR1m8~mj6sJR; +z8{djMC>Uz3c7s8YCMfJ8Jp4K>e1jwm8u}9{mbAKFeo2XU=arbER-(?uM#=0hN6eRN +z#|N#m2AxhOx-U(#6SPi#sA)JFHy*d4{uch}4dwe(X*jtxsVJB9Ufd;A4Is6RlbvwR +zBuy9ga_z4sG$Z>*Om%6vSsEAKE +z6F!7=*?KJcD@PVEDSFstT0ov&-y_r`2YJu=f{gsLZk$d}6!sxcfY8cl$w4-~nuq(1 +z&IvBIz8QDT?R1$7$6@5j)lp?qSpg}iR2gn2n&HiP`5@X-zAp!$NWxJGENyVKu&rls +zO@& +z+#3m6kIdIa=3dnc+Ewbod=WN&1=5ETr^HT;;8ZLLm#*PH8zp+0<0V$ +zOeM_(w|whSVbdU$5W`j(uyW&Oz-{3njK+(*h1_LEJ)GJUt~is2V0rm1(04(VN_}pX +zV&Yq!^X<}yNLUo_rji{jmG3qS<$7>c=baDkkLofOU^oBwXZKZi4@e|G_@F+v@~u0A +zVWIk9es0H0%$8OWIlAbnE`Fa~su}+MvJ($3+{#wm;xZ`y*(RL4nBqSo$)wK^`BD$Z +zvK7^(lVZEG!&Dngboml@p@|US)A5Rm5groLhTQdM(k5yL>M?P7U+y#{$7t*VXXoR4_HQG}YzVwXt)(rx42|x12L>PSZe8e>E0<%xpj``` +ztz+|%w>P;7&9_{#uy<3B==zSjs9v~NVxoP7L}gVhUkI_%HaShdV4b#UtlU{SZAxEM +zRICpk*kkxw!D;|34`2&!|2bO(AZYHgJ}*+f2#cgPH>Ug4~*OFx(aZAwbs +zU>1kR78UAlYtg}1)M20gVy&v&9ghRPM=L3SF&BI6KmG-!^3Y?}xij}!!JIznvLf&| +zVpI`^Xxer-cMoW8q|@IbXid976LE=s>lz&0+NV$)GK6oXA0g0>VLGe8 +z9}**5;Ypy>=x1Tkyo)v6W#uzn?~&+na4TIP?ULZgpvSam&UE|;R1M(RUA0f2wiN2s +zTktoduwj1GdASho*shQ)bZMT#A4+rk)<|vHbYm3Z;nV@0f<*25r?oW4nYH6BY(}Q~ +zy@S;q`g!V>J19|t%&0%To};rIFu&H;n0sb(>rrS!g=M+{vwWnLVsNcpULHL|iDhY_ +z_H$&nxijC1{eE@FmB~5_W~fh~dd-qqvO +zr5?%8tjXiKKRjWDt$ZPS{6}}?Uu?kl_JD70!j69)aC9@QK5#6RO^iA|gp{h*;c)%{ +zt+iry<^?o1Q+ZIHv%EJG?<}$%#r5tvpI99cA;DbR;B4qMX$uI>1kaV^i?vw=VBV}e +zr03!Y9PZ!vzBVJBbgRM2UDtUDrjvg~Fz@!b`(0@Z=uk%lRpQm~A8bd~X7w#LC97HE +znK^FWmB%`0f0&W_)4{z9uoV4tmAJ%KTuAk8vdtCSGwBGj)cptB`C|n~!C5*r93Q5e +zu%t&mqPEejskr#TeJ&p6DzGhuaXz+*&FjL-9MwLrG)yDiF7ENf_Ke0mC$$CR{C7J> +z3p%H){b6=e(zdM`R%V(x&qXiDv0oqTTG`jVH<|lA` +zN=U=*n#V%*3NPF5wyi*s5X6@`7$aqzOsdmjMA4}tSq(>tZn9t_JpU)%a*?s97zUFl +zk0MrH8}q5>re!t>7T=q>lGLE=C%Un2E8EN5lYt&X3UUD3KZBFiY=}&TNT-R?63Jr|Zst_wY +z8<_+qPwp<)i?S95Ihzo?y~-SSw}*IQ_5oIb*2^jP&xT8-KTS>!@No>-rrVx}_vFL! +zXiTbb^s|mC^9yxe&ouU_F~sk|GVxF8$u2kE4VrV-U)2pdtp(+--mywWT; +zOu9==1;0K`k+b@K2W>VC`%^_t52m`s^ISVpPjJoMFZDAWO1I0SZn3)KYZr8v)Fs6@4;N0-yJelQ9#uE6QU +zsy`H(@kKsv`qQh3<5gCBD6Ds>-_PRR8Z>Vc{5nUGO6}?r&BTiR9@GXZSK$B +z+>=F9Y@y!8B=w|4DLNJ)%5-0Icp34XbnIJT%ucYkm+-}!WI-)U8$D@q%SDUe^i +zm%yx^{2Bw!+ygYr+?Yg{uP{-tJV_lg)iCOuAZ`-U=)H##sPQlue +zI%N1bIQZ@s@0WOSSB=fupKa4?w-@P6Lwy%R-L_V~Z*=m7M72j^BlNpldhb0O2 +zG<|N3s@1i*M$a-XX#^SDekG51nd9zoQO#N*`d_up9`9>Cb=!|G6y)P~msOc|%+STD +zDjS(Joa~AYQow&$`2YA_UDdk-!|o`&ifkSf^4Dc1Pj|0QvF^IoUn?AU%59+tw7V)g +zz8|$W({|sMaGs)RBjhg`*=P+cpBP)yS*RM!(@$xb8O*SDZSPeOyq6*qYGW+HWz(At?3#JK0`ez{_k_utGhcCo18(h4f7Z3Z?Xp5U)cPR&Gu=JB%AzF4 +zrBHo*jojobV@VRDe#b#KU5Tl+RV8 +zov)ZZ+68GDckTu1?IKqj$P=%x>o8WP%8`Z{|BVi1(kl`0xEOVl-O!%ZhO3QZzY|Vr +zGr`U+sn+P!Z;5q;e-x@!%8LPIv-aefej7pHLln+W59^3Kl!ElrnA% +z8>xJ!{IQEH(aC!!Kdocro*{g%C8~1_Mq&7v@njH@oWcEiw{CJ@sNVI0DXNP&-fc$& +zj+W(*A_aO(o+7mrImxvHCBnBn1y9}nDiu5{fw?b(CKjJ +zk9LKr3vCxenMLO7rb5+OvQ|S(&2X(TO$#uq@9Q2KhBZ|HK(phhvbLoIe>)w2)9#Eq +zpyy>HW+e0Rh@B(ac_M+*hi4epyyK;nkkc$Jc=8>-U5FV~B}k2TaLX9^vlsC}w?Bku +zu+ppMYIO9BJfHm9EX{&;tSIerDPi3WM{;*50sh?Z^;Gu8Eapb!NAA>=C|s|{=^&jV +z*a!2=g`F>t@K|DPxl7{p-Qx6eI~V8evxrE+v25#cW-PGJ=IJW_*?Ggd?Q!=-K81`m +z_V^L{!`JlVxO~rYdYoy1vHUi9%Dk6yvA14=8a<0lwwu>^B^S%=@+x~htqz-&# +zGW8hU?>4lJn2cM>U4?XLFY8_>Iq*cZS5abB+P>~MIvYAW037LiGw*j!?w8|0*mMVNA{OKA^rJhss&_?<5pg`wW*adQ9D~7iHHP?f$-2DcVfIl|Q{eA;6m08ap{Vni$ypL)sZyBET}UadHqc68=ML6Ed?gLN5NF +z|5#X9{wZhX;3Q;YWc*+4e|i6VYaGnXgzW4b|Lp(JOiYAqZ0v-8>A(A58I1o>?2r;p +zPOg8K{EO>v?Z5Qj@_*IhVrBg|4Y{vN_&?P9+k^jwdW`>8?tiD+e^-m~pYA}8kk0)} +zt-s~}r4pn~NT)d=>iyq5|CsVWP4GY4{MXfA4n{&&h?0M)zvurx1pi^;f8G5n@xKoa +zBOwdKh=2Eg)%nZ$w-1o>|79qye;JCGmqFaZ+S$aBLEPHF*+kUD$j;b=LB_<^%-Nif +zg^h)u9|87XIC9SjivMF9zz9Ed&MOwZmP-sX<$@}V-H^x$5;5|6mzIKP5lA`p(XN~H +zOv?pmP8urX`?`YYs*#Yc)JOuOFUvsvRT4;T@%=DH{M}MtuIl@kQ0oErx@T?YMnvHg +z9ofDwx}|CS63VDuOMM2cXqvpEzDRCD4~C>EYIwuj`6U&)c#W?=5oaaLf0>918wF)q +zzUa6K3ZFO87V_B*Sy=ec_dgZ*+uO0oh~J<>>B2EKatr=aYG;l+1C4%AxLSA|vDyfo +zTz2QKV=c_^1mC>K=!!bUOn*4K4SSV$4$)v@7)=@a3h?A%7(L^|9N-XTQf?9hix*`O +zH>G0jUCImDMl2;#zLA92?(jOP1#)Dpwro-UmZ=#HoD2!YN7gp@Qo*GOA#1}wm21>K +zmXEA$Y$b?Y=W!(^SO21~64m|K#>M5<%!zG;vw{?VZoV*9`SZHtNRNl%-ut6(6o&8r +z%deK}FDCwh_5bH+v2n1oGXLk$F%dE|vNCeA{?Fk9Wx{x)i-GU6%g$QOm;qXxeT%N`e9waXr>#M_Kd#vj|@PJDx-k +zvAPnc8xn#a<%FS64H#2Wo@wrRemxl$E)|M9BvVR9>5Ra0u4N6kl0R6Q2$((PGSeZu +zG|-;L=c>1Ke3`Yv>=pP#aNp>J#YR`l_49Lo)e`lc!2M0(t9EDgYy6^a49d5YXnn`t +zyn_i#4M~vO1xJ>*u<{tH6fs;=Gt7!pru~fO5JSdI`epx_JaL-K+p|Z+1h0kYpljYy +z2nt+f*2XI9dDIe545^`d=*#2~yu2a^$K2>Cfyr-rhQ)^ljlZYs01aWy)9|{K;+kej +zVLR2VxA?YTz$u+x%ezlMOgo!c3WmXw+bPT}mJer)zaRV>pN`4a%&*jt;y#}&IzK0k +z*-SgXwN$*GJ}Mzr~Kd;(=} +zhhv=U_yqbcW0SZZPd4I=LC^vl62n2Y?eGM;i+@GTD;W|jB7!SAza$Xd2Z{m-ep+b@D^yHWx{!{_oW +z9gA#H7^#D`(a21)z?xgyK9TL%I7<*>Sj@7O!7DW$K;T_>`UFN(Ghg`G89hg+%NtH( +zkkV_pE?oNija$Bxviq6RC-7HOOD}j9i=Zt@ZhTjk(j!c;dKBkFqZM5Aj69J7dQt^9CpG=AZIu +zk6;_Xn{q5*#(17DDi))gMV7GbdxmGX?CcGJNsLJb2EM@yoaNsRMU!=Z(m1Do3n(wZ +zni_+5{_;-;M8&$KB@r=Usbsz@pbs*=N-}#}uZZfWu`$PMo)E)nHt-pf(aegomt=wz +zpt*9G+PJBpj)^H|5nhsbcY_Dxps@k9Q|^Zx34#t&qTwOrLfu8iQlfl8af6kBGzqtY2Q@m?_`=DG-{XJ;X|o6*@FXc#kKeIfbk1M5XV$egtyV^EN$1YHZ}C9=$%wjpg$Xh=D=DV<#53wP{j +zZhXlH&z34S6&SvsWjXN{9ZeC@vo5f*KjaF-rYu+`pAw2rw4_5sPD;d|0!^ok4`p;? +z@J&XgY##+q_i4r%y>ttghv4uibeJ=v4mk)m&42-8R7m +zHA{az3F+MKJYYknGfF1nOJfxl@Y^zCTi`^Xo|KtT^7PWw*dgvIo@KsMZZgm##p&}6 +zUR&Hmh@KdhU@|ahsyuh)h~tLlkj)w8ruoLo21mF293G(KqLXKjV%WuruaKKo)95Z}Vvd#=Q)y@Pr +zC~X8_O1_*<;TXlQV9rJ>1|V7+za-vNv3b-TDxa)X?&MU!l$izI4Hp>AnZ-poyZCmB +zuFbX(VXAw&Zwl*hayjCL_~x@`*y{(MRCZzgT-oJ~Lseb{EQjY%^H5HAqwpZ-eA@Kz>4x{_<8m3FJi##-HPGPpf{bBuX{u7++3ACZ8haLeKPfy&yn*sf9vF_?3MH?Vkgv{ +z)10d>oSj>3j&ozRjQA3~?(bWEg1=nKC#!oyuabYCQzw7^#{W{E?UDUD`SA=W5I$4v +zchkxL(nsk7hTb>`yNt5=eL~iY&!?Vl +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 +zv$Vz*$<9!{r{x(jdb==OkD7UNksNWdVy0&XE +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 +z+>x&YeKi#XQ~q4f~MhSbDp}>{7U;u +z|H_a#jng@URTY`%I88SsK@>HhCCI7)r4U4HBNoX-M9l@4Fw2s2ZgP%|aGDFgC5L!k +z3JI*xi5FQiBWa&l7-8InRB%tK<~aD8It!8Ikp1?)rpX$Hf!DDhZ@_VA&nfH +zHu0#4?-AQYEdJQ`_B%O2`eB1VA8;+;H^F9njSYd`#-0X(*m?=-NkYtDGr~vP9L5GH +zU>-hf96r2;&$Ynl2|Lv(6LyBKo^jnC&c;e&*FYbE{lw&2(BigCuC5jX+!SM@tTW0c +zN(7O`)qlX(z5inW6ID +zb?#?4kja&*Doo|Lv9W2fIk6@3eX?*%U@5;y2Ce7sRfQ6d%=$`(g*=6_>~w^N4J#{S +zf`uXATR0T5GmnCt;39e;TpLelLGlevA@^xS +zFWlrVEl^$ZWa)soPch=BoA)e%oe +z=#4nB_4iBW%w4r%di$@|XMc=FudE+GVeAi|%KjNGydiPqAM?uqV;3@S?!6h$FT^MZt?2kp +zS+fWgVXE|-As@e^u${TDu!DJ=f02Do-_P#Rf1@8`dJ4ZPv>T2>dto6vOenPv3r50M +z>eF1)-P8Q@_yvXEb3EX9oPErAJh&A-i?`bUWH=cY6EIz7fFp2zS81At%HgGH)5ajK +zz!}omf)FR03EOxkLGs%`*qew*NYY4eB!B4UnYk=7)6@%$hW+Ur;IMmhiDM?y1`JK2 +z#mFmgv7%yNoTIq9it~yI5)`o8Y2fF;wUr_la2dfYLc-!A* +zEvfmMst^LEHq_7fYh=zJ0=XAJT81yq9t*Xr_XbEWLQ|Ox)XZ)b$jwO?pKXhbO_GOfQ=(&+& +zntpogr0v-^_%3(h#GA555C1%y-F9Qu_S%tSK6(D+e-9(8V4eogKq~Jl^N8gZ_>d%t +zBExcok%}Br8A&ACQD{0+;dzQx&eJlI^`H%3<{$|qeQQQ0HKpz%@ +z?e7QMk0YlQC~y_Hacc>>L2@DoTU^XU9bOz~LYNw7g!BO+!5cDI$QopX5+(8C2+P8_ +zN?K`R+CxV|qi;S#Jx(P+qi+HEK3?2jf=UV#5d|p}I4l0d&DUQr~e*)BWmLUJ_96tm_oh9L-yF_ce9)J>_*Lh-h|M@i5=0K_T9ef(4EoxH3&cSgT6~~<4dUj#Ns9U(GBmu +zjh5`0+xe5qMeR*j-#2;fro-8<+i$Exc96%j;8BXGCA>@W@@^~Obf-8rBrBVhV+vMy +zj8zFNI3kJysTt6S2mH2F8ud&X^+=-Uqmd8M$d_r?k&e}z))7%E@X&ul{iMA54e>ah +zy!AwM6w#aYR(+AqUDD!9X4(e*Pu>IN>SlhsCW_B`M1!FPI%!f=L!#g5yvV&pyT&;z0!I$UGXM^1N +ze2_b5EHj7nD0iOb-fkJ)CXkB^pQzkf8Sw5-UI +z!m}I~;T0Fp!x5;N0BBZF6o$tf!lEiMlEPvYF}MpKsnW!d_g9_~5 +zNA6Nhh7=|9()xN(TIX}px>za$h3@V)j~(l_1AI*;b39`5YG +zh>T-|!ZgHz`zEo$xR{?QbT1C3ZxZo6VL~N%q(u}*%0_p*#xlqNfFJ==mLVHR<0mlt=Mn>_%~;w3Yq2 +zC^)dqFe-TrHijil*DHAmNJ+cKb`7#1A(SLpQNarthDqeq>S%XhM;G48=xF3FJ|cCZ +zk(Q##O2pFcQIXmOgEWu|S8yk!k+Kbp&9=xyW+$HZN`!Ca+j($oc-_bq%i+u#2Zi`L&W^Io@3GL$V4Wgra%9u%STR@9*y$Wa@d5uPJ0 +z3`2TFZHw+jx-W+KK;5xU>Yaqp1_^bLaC8p*b+;psg0^pWQAx^9jtfgtX1=xMTe$x2 +z?!rXwI^1vOTXNkR2SnT$9~>W&?$|=4G8EmA7;S +zxEuso>l$N3lD{xBHRKhJ3LsM^?K0G?%Khc&| +z8z=qrnQSHBHTk!9KlyfHym->mY#SPR-}-u0>|e@O*WG>PywxNFnmO<>_g|1pRARSP +zax;4~w}icePOvaC+(eP9sKA1;X#*K_Wg#BnF9+ +zK_W&)k-IrZ#0QDQAW=f_*;qoA>WN}p%$CG!ZK>E5@i7%MBGY11T-R#ZH2kCcu9OUyH34dUuS#JTvdE;{9%2gZKFGsk7dK72}eO9AScRDf?>)64z6ls +zf|(7*r4PTm;Qj(!5clZALnUz(=RG{}9k~i)Xt*2-d03jjBq3+XA05I +zf`4Q_IfKNKl(5WRTGhH(ZZQGl_K@9aG9pl8QduMwEkI37rtP8@qfDE#E`+PA^3{Uk +z5<2xm=6*c+nvC1!^>ALQqypqziJ7nHvwpkc_7|o!&%7ji>(#f+{lS+%dFGqde3xze +zww+tj_2|9p+Ly0B_p{$*zj_S4W8U`Q^zSUWV$9r__r_%1GqZ31)pu`sW2N!Hk5*nk +zxw?8m=_PxYEj_yA4!T~T5@JIatr_2M={ybr!x{QxP`MK?*&WGMUSAO+2v?9vFNF4@ +zeC~A0QmK28^1k8ALGb$5K__v3&?#hd5Q98X+V|Md0u5Q8VfOcAPMUN!Jy)Nh1#ZaF +zu`^r9t;-hh`u6Q-zaqVr!H16}bJFP29OkneJc6W%L@og4vcx0ISG<43eE*2Ox*DF> +zNN42>tl|nD4P#2#xKg22YOUJ+(*1IW)~)pcCfAxZ%t0=R^Alb&(f~%mBO4oObr`;_ +z$Z|yDU65`ut*2w3Vl2ecx3HvwRLL_kF@oGrjX5N=H}@G{$5{hu0CJ1CN=9E=5PV7 +z*u~fY_DUeSO$nMH?c_IM=9J^OW_AYf3QY8Dj8zqfW$rG=VuH`b) +zOm&8Ftz#~l&CQn*y4~S)LP{uOU1c?=q9Vb>PFZm}BaG}~7@5Vo +z9?@8rrm>(?EQ_&I2S>z66>jAAdIJ&7(y-QvX1x+oI+SjORXS1U-dTC|>9iDKk7YKS +zM@`m*n=B>5_+9QpQKCM{Nv8w;rv8lYBY$tEHv`0^F|)5YnYj>Y$$kyrG!(xwWHjlt +z&9=sXJW@J5v?2S$hYz>Vu$x0-7g7NlZdH=u`O}DmT3QlVPCR*SSrn>%g1q7l~0pel5?b6 +zlFPI;+Uwdk`Zq~?UCKb5Sy7zwRz+RDS!K7E;j&p3zscBPd||MLmS1!A +z>EJ4?)0W#bg{cOe%Qplv*KZg>*4v3+*ynr16%2|DxhX)M`j`@>D#)s3H<~vx0`>Rt +zXfX+*c?k1au6R_;k)Tja>Y-%CNijjrWb8ovg~Sh_=!=R6qeXEizTPrQEGA(lB8kex +zjs%}3NSwrGfHrUMqr}KGT}}{+r7F|iX}md&(q7WH%g7VGabHnI@j>CJfWtzgfCYoX +zUb@Uh@KL-=m%j)!K@kj!eQ5<&7+HTYD`|tko;1M~lPG^->MGgLpZw?}67YMHjlKOn +zq%b>pe_IaLq$#8!L7yrlDQqxpaT3UBn6IOsnp6o1^kT`Sn8tmN+wJmrV+mFe4V;^& +zhnv`j@9v+!donagf7X_<>-w7@XcZ7ve&IV6IV4`PYAR}e; +z>ued%4T1U6t@=FMZJyf#-QoAN +z9R7IWKe)4|X1Wbdz)V39tWj|X4b@kCOhu+@sjX_e%H?K?RH~z@FJG29Gnjq#Q5~Xb +z7*QUTtOFzRBWJ7%B2V=WWUpqZ@-Z9*AJuFe<8B1_a5LJ8`VbdJjc77r5rHQ}X%Shd +zR7lhdQB^^-wuu}>RS;Db5;gV^4WqYu$g7c$P6f~jRpbv{SvNH2p<1z+)bHU8K*NhC +zDPn{_I_pU^1^m=vrY#z?SK9#xLb7Wzv7!$XYtE7?P#;IU;gsI0-T!q +z(6X1FTe|EezN`Nq8zyh~-IDAV*|&d&HXfY%z>(h{d+i9s?&g70Y%ln$0Gg4|H!K`(jU5n3*2zJ2J2B*u&dnSGdB8-S)- +z&nlSH<9bTJLg#B-HNollTICwol;B+aU4FKFv#T}O9e#`dlkB=;HuKtnmvF9v0ZJ5Z-8megni&RBB +z118C;zG|}O$`&`xV|HZPEqklI-43QnbRuVI}KXIRP6%MAUic!JDrOm9Jd>U +zZip}P8F%xXjl?y^b!4`RP)d| +z%eJQ8{-H)km*h6|5ScZQ?V_ELdRnxG_+oIzIf0R)^Uy_h^|KG(^QWcr-@3PTW5w?N +z$V*F?J-79HcWqhy)cSMJY(nh1t1rXG*|FI1#_xXh+VM9I6PZl_FB$?nbA!yLSl%!b +zbmOUPhR?`T)!FO<{&sn`D!Fs(n<)c&tZN8W7$o}=$9w!)*O>q}(lN?EGI*JzDR5cv +zYR63fHNhJl3j;R>?-K5EpTTE*CgVXi-Ro`kw0ahKSWnQ_VQx0DX>tWYMP$103q)fF +zy;(O{1MuAh>v+To*5kDRg8hXiXZqkGTb;yz!cvOPOw)KH(8NjCNOOfn%GK0`C&rreS?aF4k~ +zZ4Lcx4f$1J`Gp{KeqhkVOs2YuvAe`5T?dJx2^vJ%8@kFr-~UPW3*`FCpOAshpHgswl!hHT9YLZFDZsr#Vc0W1{{hs+M42;4VIT)MlN@3OWX|z)16@DXn<2?{1DVb5 +zP1|!*#xBz?$f6(tLNaAX0b>_z1qcB2u$3!O66|DgwLMl-U6ZOKr3r9r#H+c<+U8xG +zHaP?LE}J;BpuXywD~=vzA79_LAT@Tn<7dj))|=L!p92>0o$S@@r(h9eCF$)}tE%#@ +zay9OnsE%<7a-qMlTur#jV`;V4HC`R-nkHVS&Qs4S|8N^4V&x^5#x5J` +z)|NGvk5$J;$COejp$ +z+?toVHLr(WBMBvSYveA09OvAcmwt%xqv4w5I?sBg1T-)8eC%kPL1_XY{wMfY~P*Zh`;>+d;3et*!DUlQ7r`#nS( +z1SKz7mO=q!Np2-5@pImqYCEkaC5Emjp0h)(y8Mn6YkdYXbMd5Xvt6|5mT{=fkjq>_aUI~(N7t15Y7UV^js%UZ9 +zs;*59$f#RJ9vWjj7F{S*O7|`z0+}QhcDiJUVmmoN?vqKSlZr%k5s}Cwz^HU>x#41U(~ +zQY+;Kmjn=caFQd32N_Jw5>v=I$$e$>ka-S}T9U2@XiE-3i1al5MFxd~X_Q~kVF-p8 +zHw3K!=@Qr_Lo(Zy3>bB8*#NB;y6rJL6{Fy`ui5j1?q$E2uxIIl<_8-95`Ot`=GiCv +zXW=btzBlDZEBaprn_LTmYM^TgMCOQfgIr5SFj?-9H_JQaZuvvGPZk+DEH9GVa^2~Ozd`Z&yR5$+fqaa;~7xnGU9> +z)}B2xduGjR&2O)n4D(GyzKJ@2tB50;m>${0G)5@$PNZ`ligVP@bFUlsM{!PN?u=^e +z?kYpAT;R&J{r&yopI?6YSe96P>~*dad(Y5$v>MACAg?CQ5~U*PG;xA-jU+`>Nm4|S +ziBgbI%V0vt6#bH+@DdublH<3x!iXM;K(DllbbYHq^Nm_#t|9Ob#ED8?qSOatTqqd0 +zrZnS@md6J?3nt}PPU@d9<<=SEd%yhUCzsyt +zo3Tx7ICj@FvzvK;g|;Ak%ylkUQz9;VvX#70UaSeW^*8CLENE$EQtwljo+h+3A#flA +zKb4&?tkYRQc7urT9o`uz;dtNSesBX4dLRIJII#(QWKonvxl)@3RUx0EFVfcuefsOd +z+p==MOh?MaN|9P6Pu6O!xmLYcFE3K+wadiy((T%Q`B&m=@__uF@(=kFH7lU&k|2nT +zYinpK+-Ry={%(L_}8#RDL(Y#nk~q07~{& +z5P*y#!ir$6NN6pY3q1##XW~@s`&i?|Q+vUdOaeFp;BtcC(uBlJ>klKQEzhiLtZMvb +z&~+5Q8I&FW0tVt~q>3ZFVp?s3>u)Gf?P`sHb_%7mW@aJ`Eixm^9?l^rfRkBvy}PQowAT_lCx$;o{?MpOwLn+tR2%^eOZZGeM! +zCOVH9=`Yb7SmUn>ydhFG6o$8jLN#dd4~jdYJn{#R#l7IPvED;J_{R=UtpmX~1$rob +z_`RW3^yxQ;?!H3W``MFp`_S6KW|n`+&=TG*zY10*_Sd&}OE^HG0#oH=Pm!r&qUV;M +z>bc$?%zcR>m~Lz-U%FFzOA_aTbyyPerA}$1l$1mm&2=Vt13XU&2l_0KZ0;m0`+LOoBlrWb5tdUHnKXjzVE;2_vaqQxQ7l)2K#&O{t=Y0t$=eWre +zj;E2oI8QH3*o2Wq^Z=n817P`t_dfyqU+x$BAC9;roSK0@OUuYd5+R(5y{hneU9zxf +z550Kj=SN@5tQZm6e{TQ%e`V +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 +zc>|rF9|`o5^V&HZoJta{^E&{ +zAW1M_DUzn^Dy&g-$M1*nedbPy1VCn)kyx(VKKG}7MRgT_AW$YLAxTnvP|rn{FJxIh +z6_z_?x*CG$L>lfXgi$3Rs5jN^QVJnuRIo9|=NLq{Ep^3Av#Ey3DDA4ur# +zT%C64SLjUN!_H4=bN#f#e}$j<`JLfN^diKG1?XH4?4n15N0*~W6q|jdu`vpA4gB#= +z));-~1Wj6Q0v-@pn+~auQF@>M}10Eyh&)hx%6_wQFp~n>0^9`i-qwx(f +z2X=!f2x-G;bzp~5&Qsh$CbPZXn}!n~ju*jr{^X&Zx+}VbKd4Wijpj?fvO7>k#=ylt +zD+D>zU!PvQmwCH$aIYF4P;fj6M);sIQYaDV%%LCdeW+HP@X!-?PCR}0qeJ~ad}!2f +zV1W77fd6^cK6u*;FR|svUS}J2efBaxE+6Kh|A3Lkp}$YfLs>R8WRYnylPzeGHcI67 +zxH4>%c+y4uaXUcmf|$4U^xRn0V*3{H7WH=D9riwHpS(|b!Pe|VxGGx+YFSpcGm%ys +zSJE2|bzI;pV!cvtEb`q-Z_{rx9%p;Z=ZxolFFLOauWG-v4my9-1A*h3;sL)MwVbr3 +zIHzpX6xVeoe^FC>xhxBwuDGnBwzzFOTv^<3g!YYXZSbZLbdUT +zH(9`3;r!7#^5GXW!^f62rdlgM77$g#ZF@6ngFoZh;3%jeUXyAR{k~{!6)J5Txm9LC +zq)LE`-|rYv<>2=EtSVYCqDo8T3~&3bN6-|%5pmV*2%mZ?`PU(#gxYk|(CvS?cWlm> +zqMg4Px`}@6jn}J(-eaY7=#y#XQzsl7G6#P_ȁgmR4-I#2iuw2^H3k5n7U)kC&m +z2str3ARBTp5wKk&VY;cd5*t^R{YG~5rR9j1sfNnq*G0Ci-so8>NBL;Ph~Ppgvfi)f#9Gwq~uD*IMiS +zmxM0Ky4t$le?#Dg;B}$f^aqV6oge!5hThlz6#Bb0=zJ1N=H#VYR5)nl#6`Q#-ee1Q +zY&iQKh!9APwIDp$w&}oF36euB6bu#x^bp+GCJcr}h7QYMJ;+tY4VfoEa-1ACF6ZeS +zma~V|?y`XwiO?RlAYs%75&?E$;OPJh?4eV4+q8h371#MAdfBe5Dt~GNUp<$X`DSrwKEV=C +z%cYX*_NPS{n5sYyz9Mwmn40Mkf3ai?t@+6tWd-?VZ}$(iO(`tju&`oi#Y0YMVSKfn +zE0zx4-go7OwQTjV=N_F}KOdx=r1D9GMY-U_mpm6wC;Y31o4dsKNe +z$nI3`46-fCmLR)axje{@smDUBO>GOY#p>b^GgULhLP1r56^lUx`xBq=3G-Qunl%=w +zu_!;-Y+SHIxkA~Z2nr2O4%PT9vj!%>L?pYy*GHAfY7L{LMi90z%3{&fL9^ajBF^9d +zEJJEMiq!J$w;wtu9CzlOc*fU!q`RxDi*}`cw2@|wg>ppuNfsQhDh;ti%Ap`Tpd1LY +zeagNd+pcU6vU`+!f^3_zEy%7?t_reFr8CG{)RqvNug*_#$~FywguWl-yfH0cnGcvn +z)$c3ZqnrW*8L6SvXV;j(uM#VAhG|-yT~;4sLJa|yl@NZs(kkQ@jF+hs;W(=X9HjBM +zSAN)Q+C7n3!+h%EC&hW186m|xC~iUq{gof*mn|7HX`=AkG$DQr3_9(+QPaW~&Oc6Z +znR}z~H+mkns>>6TE>&+(nWfS}g}$kLq_C&>`Dfo!exR_$N}Iw|1sV&KlNwM`b#e#2 +zf^Ok(Juo0kfwZuQHT;wsXcOjl)*o*ZP&!_?Mmj)Jhu~3v`p~;{aWZRr%9qtKyrE5a +zkDiV-+nXrrt;#+4*VLVcyGCyx$in+(?lR>le0 +zOx3|)=8?N3-AH*W&1Cq7FXJue=zg#+!7~L{?P7d!CvkOL2UoTCqM874QRQPGjShd% +zZ+TlB4u0lc`s1mLc +zRmlMmT0LRvEi>v0Cgsl#>;2U~ozon=-8X0CD$)B-v{@;$nmnChl5`%L8^Jt62hxV! +z>>1%r@nfl2x*E(=o{_gH7bwTnJ2k2`=!N#y{qPF+-=E`#&-_oir!SNpsTtx6JqdpO|M)nv>>#p?T|+PsRpM +znv>?FIcZLsljfv3X-=Ax=A=1kPMZI=`N~Oi(wsCW&HoNV@IQgl4Pc*6_7REvfC!{8 +zxdrUXHm;iAPf^83d47MNbLI^n# +zQ=SN^9VC?)rV`^;V%$oSi*_E`JbWdoL;7sAr=vY9*$?(Sq|ZlsA<~PGUJP%qguHDb +zRgiKW*nYHg;b|45%x#`>6{O7V=@@br@OU@t^^H`s(!vmX)uKfL&F71{#U +zijH@jX2eIQrf7j&Knqi}m=Q)IQ93V0%Mkvm6s?fG!(miXPVPw28o8csP0<#6m}T>J +zfWL|2Gbx%9N&F;5GonZ>DOw=oq=hM3%m^b9Q(BXvWe9(DidIPDa2S-nx-CGyHu>d+9qoZ^|~LgFpwAyO0iL +zgwMisJUX1=AH%pikd9**FU{PHF!>pDA%@?F^k}4if%GXz|DMxoM*h`|cbOUfX1Xj7 +z5tobyj+B$hKrJ9ENej5MNe5|%tCy@No#=BW+;s!Z?I!SV#SmlR$rREC#wGK>Zw18f +zB|Ui80&WY0UJG_Jgq#9&E5zktTQN)%T)miHGlW?KZZ}yCejQ}_|3zMSs_mGf7w>$y +zYlS=hc9+ZtstNDBH@AcDI84FCv{zzYU9t@B`rv6V=9Y&Z`-L1-pHLQF(iIS=4f9`3 +z7Gg?0!?~IWDU_2*K$SvDt?-6!c+!KV?1ho`cv`ce%wH_+f?=u-%exNCxdQIzLJG?< +zMgH^@%u5GZn&QJ8e6kXJc+Psr81Oq6dC-kdT9N&6PdDbNH^tv}tOxJD2~+CCx39taO4ry@ +zOe0;JZK-m$59h**kSm%-cmkR#35!avUm +z9-|GZQV2f^T;6(@rtfc=Ha^U#*ABO4FC8AT4MO~@ +zHZ=AjcYJyIWOu>J7I$_>dq?m3&KCE~j_%Hm?xx<>j`p$cl(sf^Uh9gLy*=){mY$aG +zwJptKr*yYAwYjZ5Zj;;F-PGK&rm1_i+p+wgrsB4?yS?!2{Pxz~mS%T;Z&PmzL~d^$ +z*U{~Ez>{uwSw~-cZ+B};&)9SV)!tj?wXEoCYwE6E*wWp@lbSfTe3Dx_yLDN2M^DG{ +z-ccB8_JZNpF5p&OchkDo_7(2j<;z=_wYaCa^E#G79_F+zTiMap)HB9Cw+UXhthLFV +z-_+OM3`x7ER!tsX-_hr;XeZ6jT%UaH62(z-Kt@A_wV(yAg8TPy#7;l=W*XkBc<*Tz?hqamo)Vsh>j`16@JL2lO*pEh@Be^l +zx18{zRB@&_O*|d!DhS;Ky@vNkZ`N2zx6`{pB;=z6pIN$7vsqJ0J|)Q# +z{@>NU^d}H5iGggFOmZ24klF0%0#+p!6Owpc+6(ut*PzqCB>YHia%jrDS@X)vA(SU` +z5@LdLn0^eYoeP2|NQms~>~peIYG0bL{45h|Z0!+Ygf +z@@$~z$n$|-!2d0lyiooM(2L|nK-bGlfNqd`f$o$0fL<%F1Nvh5YQp4e0OyTQj8B0+29+n6)ch$(iO-ln1Nu4huR#CJJVKcH +zcgrEv@>?+?SlJd|Lx`z5XJiC&-s8E)?G&G(jPsyG3sm5nx=4i*sf*PMfNoNkfxTSq +z1beNz9_&ki8=MbUf_;?=vatG9^{YT{Qm+Aevw9uS*Q;LxdMogXbLp=so-p7>8PH>l +zaZr|Wqa4foXP`eYKESd(3-*3QJ`bIT&eQt&q36%5b4dt#RuXt15+g;yS_*kXus8Ab +zl$CK$`Tyh|zNgUhAf;Igrn@AZ3c>hc*C|?nrw;M2Zs~3(E75L8yBF +zy$xg&xq;kFzD@2UkC1-yBzcCsNM0eoCj;aIa)f+FMQYM)T1qF;Iy#FkpbfN}Zlib5 +zd+5V-2i;45LZ7FaJD&tDal+d+)9-)K=P7({`?Rw}!0=uNl4O +z3@?8BTF>oR>badY7)tF5ca82!bS>;^>$usr3qV{4-uZXwj}L=Lr* +z-%}atZ9GlT3uq_3ioVDgt6<%11G}Ex4A*zreQXDNj=c|E$0xXOog;J#YlY{8U%?!a +zEiMwf#cRcT#7Cs@(p|!H((|$_uaZ0E`{myYK1EhS5Ce=dRavB5pfoEFD+6k^`iQz; +zJ)nN7~o;CbHt6~YBkA&^gohY=qGR;OKxEl +zE-iVG>2TTboRUy-CG-yg!>>e4uR7Te@m3Tyg@KwOTaay)efv8&^8R$?5E +zj_ro0A|iPl>*GitN7qEm4@dc`y?jBB#xRhc12K5I9P7)&^jDJc@QfpU9OvUGAIJDO +z!pE^Vj_z?Zjw5><*Rv4U^HQlpT#uuAJQa@UaXgQsc^u2*v3X3MPZO~@2cB?rE*IQ9 +zj$gu)I=H4|jDry4AjIHY_zR2(=~6lH9$vCsh?$qXG~-=$shrl4`Eb7g+(i(k9xjHc +zA;$~_d^3M5#|s(af*ciO!~PWUK>>M;=pbAYJ0*D$n*`S^xXw#H$rdD^g#KVB^C3f|cdRh^ +zb9O`WZKBh$$+zja|K#Osz@oaYwbwa^bND+FVkjCy)DS`lA|b|FO8u{HwLrSZj@y +z@7;T5kl5t*e)qZ0=Xu_}*V$+7wbx#2?X}NlW(1xAp2gEdUPLYYV+EL5rTElX0f~@%1fv~6hG$WXNd0f=qcCp98Rlw< +zaM1&3eG~n^3>`1P0vDj?1?YJJoNvMk7hr`8;={mnUkN9GK`-XTGvGc0?la&%0+0O)J;?=26EDTqjg +zzB^{3ZlHH;1evREtb&&&ytVbg;`3>d_zz>3#Lv+zQ8P9oYC(S1{NXlAB7!VEMs|M;oGhJQ-UI%R+yM(vS +zkC-<`GGQbWMj62z;Kd%#}yONH`igxzuv* +z!wSs13-j(0O=vS?w|rn+A0Cn5ibyI1{XCC^wc)+BpT`rMT?MR&8R4W6c?0_HSQm8b +z3VWW#*nqeIoFSADUc}c#$j&-|#osdUge+qcEAadk +zu2rY_MbK5Kzl8Q`)XM=Dldqz#1y+E54Rr&s3U~u(0$6;;gsnQjM=pfK=f^$V4~YX5 +z&Gm|`ypUe~;fNeT6l?g}XYpJfiENfZ*vi4F4H;!Z91Vo6+z;Q4grk7@@7Zu%RfO|E +zC!&x01+gFT_6z70in;-KbqdpsuXDDp)vzbK!m-*pVU4T}%Vts48TQ^KoUC5qIU~ke}dR$e6`*#VgGA6LLmfST@r~$zOa$k%;Cz<4 +z(Z4*L3-9%q!h3|gbOCE7)RWo36ppayaf?mVKB8Ofxc4LWyyxwREk`he`<}u|#_-)r +zZoN9JfYqsMo=dzq&KnWuv9__6$?@b^v$ +zB7Kto?TIJ}mq6*nK7D=)mqbtFilS$6$>91V-ibejE1Et{`8eOq!xhKAbAdPfmvE`H +zl*)1D)3a|>(2sD2N~C?bCJQr#S@e+bwD2?~<2?T?O%eVm{E;3O{v`aFQiQ(+X%5kvP5^J0rgNx!fIiTdQ4aunf#EO?0ms5PNz~YYdK5ShTtS~} +zsILRJfV+4e1;hb~Kr)aDqyd>g4loCOZlcZy7Vu|+=?;G`G>NDSfI^@IC<6>=k3n4p +z)Dl^C0=s~I5-fwLhk%2^D{Hz<3r%X1f6cI|d_}dXZq0R56GLN^$@^jQ^NgA*(569~CM3UZbK?$E +zbz`rodd(qIIe&f(^?B6y#`R91tJmBD4K&7~Uov>_n#$3>9rxQCGfg|WUaTH9?ZOyC +zxIZyo-!+|P0RK4#v|R?SHRj-c4zR#<8Muc2mmABP5;zK*#0VXk`-Dd&C)g1-X<~qXt0&mHb)xS-hR4yE +zig_oSHUV2eZ{hw(Hf`hW5u}Cv6LlY0TVlv>(5XLM4~G3W2we}}@4v=;_=)+e06r=R +z`-)+AQyWJnY+i<%0qsp2ni3eoJexTtwln{h0CNy8-Ql=~k0Co0--b|)_H$@YiNrmx +z8(59LwM{c{zX^3pq`k2b@exF9FifOv_h`gWHsU9bV*s~aRD`n3)I!*If4DdLJ3;Xymd~yKmAY88*Zu0Z^=P}9G +zK_q4?FdnP3n2w=#)REjUF=it%hwMbzJ-_!;1<^SEz>oNg7rQM+zsEW +zm`B;Y`%rvXvN$HhN@QL<77{~#=l6;19`YmiaZM=<@acR@F6Pd2LX*F7qh&6ei)9}C +zh;?dNi26L67t0@}ERMJd`3t&ZcZuhpoD%=cG=_g#8p}V^OyHkpCi2fQllUi?kMPef +zALE}|KF&We%;2B*08pj(i76RrSDLt^j+z@G*kLF>E9?@`kwSXnk9W-`ab1I +zKahSvPfI_Pen`2}kE9>bGt!TxAJc5OGoI_(unjHEtGyO{f0g#y)C^>8tEPB3~8lzrFW@FdQWkRVl>Q*SPo;9EoJ~4;p1g=EXUX?ZSVycx3+GI~QUm&<9jte5q)MmER>YLqMF3Np!+awRp%RdN-X*e+IRe6KFfi}q-<&E?;d6T?}Hp{r^>vFr?PVMp*c?*3* +z?vOiZi@a6dO5c>X$=j$y?vy*}U*s;ii?+(!xm)h0ZSoFz2mPzOQ{G9Pa*y0Y +z-}$C`PcHVX;A)+{2O{xep`N<_R8IV38p$_luD--}}bj4&~DliT0c#mI^4rCF%Ru8NOEF`?#R1YxR>Cd?5EgkqA6dn&Sw +z`zmsc2P)>0Xxv~tZ|pQ)0Tnb}G`1VBf^ry-8e5GgK&>_&GrEi?LDd@f7#oboK~)$B +zjn&4Zph}J1M!m5IRH1Q)vBcO5YN2tHvBb7? +z9C5T9akLz9v>b7?9C5V#Vi<^}u{c|!+Ej}=g7J%lx@g0%mwBF +z3+s{%MTRAYX@+z|mf@(O&Y&@@GL#!C3{3`yq1xa@*=ksiYm;G%VVhw)T6P+C;p#UG +zf*vv)tShN2t1~c)eTxkC#|c%uA^wR(@z3x@6!(R~eG$!lp~4rRhDSa#?vV%Kkr!#I +z@&))MmHXvUrCcee>F~=Ani0Pf-gzSagZRJFlksCPSl0i?kpx;mtGTapDCWQR6Y@pO +zGTSoGvf#3H%Qh}+U$%7x`(|B?_`di)G`%U_Btg!X5%WrkQbH19Zz)A7Iz*rx|GoI{ +zkrID5{w_uTkNOCcuRg?n1EC6g2(hp-5l9A7fix2Rh_#iOKn{SMx-vg}zW^uz3d8p$ +zVU&e=3_#U5gq1ePQb|N!6#bKVO)G0bPX&Ew0`{V98jv0WYkL*e@MnekbL56GH_Sf| +zSO{o&ncbB=; +zlI-m_>m5VhL363&Af8sDWyoBE@}RlianyU%yxQ#Yp5QHmW{cy5_q5sNIPE=Wu5p|L +z597a#zC+$?W(E`zC3ducrwfbwtC-u^InvT +z%)`9pko|^lvH6%Y!B=cP=}bb)D9Ra-kb+*F&KbT^^Lb~6Z@%t|Gux*(UvbX%RiZrw +zoY$Rsz8do_^sNV-0{XghzHhZ|)VauKG2eAA_QjwqhW@ad&t-{nmU;&*aZbJWpe4~+ +z>AeiP26OCi_OV$^DEpiPoJMIW<1K7XIF +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 +zvmWm`gN{w!^wuTezeVsOFD>O>) +z(d%@9u8@gt(iqtVQOKfz&?>Z1kFZI2i+(7)Bb=l6qiUm8(g#tUQQx7lsDY?A1u5!a +z)QAupbusF9!h=yaWl8vioGw2hJg&4V1Hu!^pz@|rru;(rg;1^xD@O#K^6O|t_)>Ii +z^c3N%(T_$?6FQ?Gi*^cKvCde(D95(MZV)HMel50LoD%!Z*d5{{vEPq9AkK^(i9IR) +zW9&PzH^moXKZr{bUuB;(iOul|@ehdJ_{s58M1TBm<1dPBYJ=J#Zc_g=NfduM>5)l~ +zh$E98o%FbPY*N;wEb;A0vnI_FPmut-)bhWSPGi5<(sTfwKsV4sDVk1Ax28wary0=f +z)eM6=q&cQJsTtLr*IdzD*W5yVR~w~`(qQ#fQmncSjSuCem(I^^e +zl2|EzkrMd#xe~>d;!1i@TqCZ5Op|D#hxqroroi6mG*vmG9ASU&rxSFV&ulXLMWm*V +zDm8VQRhlM^LxXVCtk-PPY|(7fY}f46?9%jW1~o&PgPNn76PnYSbDGPVYp8E(?r24A +zj5a}=q)pMz&}L|}wX?N(+WFc=+Qr&pw54cEwR&x(wnkg8U9GifU0T1k4SnuiDdFpu +z_Ab97_bH2`LYH=fcC)r)ah$djh|zXyd+@Xm)PQ!cc368|dq{f>cPF)@+Vk2g?Duui +z--b1lKNRQe|67=h#Tv{4EH+n9WN9RZ9lP-E*^gPl>|6{asVP1lod?#H^e~GLIS3^Z^6FUSOE!X)bE6YHnz5Ye}nURg{ypQ?=8y>Dnx`h;7ux!@gIcfVtme3O +zNOK(5VbG^g9@p&F?9uGg9ALjijCnm~4ga-i+=r}X#x;k2h3k{_F0Q#)_3zQA=pwGX +z=;G*N`gHV5(JxVcbX9Z}eTD?}#w7kf@=z8<6D>^!Qc2L=LY)R=g1$?FK1!OsG*Nej +zBUyKygVCwFTT9b)clmv$K5A)>K90A~(I+m=*C+FK_MEjv_#*ux^a6eAxNO$W`Z6$C +z5t_-4&;|N54)&bYY@Eom2nzL?{CT7wquF?@j-UkNm4xTR#x6r`fR3!bU*1RQG*P#S +z__)6JgUz){pTq6apr127_lRCh7xtXlCt}x%<`${j^<_)9>J3Y~^i?0ybK+d?*R|w6J4EWV3A(ZQ +zMC^BeEYwb*C&p}Icn%T!v9^ee9s1f2jS;DnKW6@s`6k~t|HwUyA4W&|VJuxjsO|oG +zoTpdcuynV+v7Gd~%N6~ekG0E3)t>+6^S{UU|1wT(*uD`vr`_kT|El)fyVoU!=KXPX +z#4h*ST9*>C)8DJd{a*4B^~8BhjD1$`(c8xJ#y-7g=>dI^(~&xolOyZ%uzub6v*Y@W +zd|Vdyk$inh-@f#$e(Si+67R(ZuP^Gm#^=cRuj+R!y#b!v`rh$%9_~}F>i3mT)*s+< +zA~A`&e5(F1lTkiRe|$V%BXu~}mFMa&mZ$4aaU0HFHmJ*6Hl&-s?4WMZvZE}o>lQCN +z!P|7<))JdVjYEy4Hl@}{+)Z_LN%tHPV=ob>#Y5|`|Y#OKKq=r&!2nW +zgS$SUj`WpL=lJ#5h@0E(PvhkN)bc*`Gt=Diet&lPfB=L*d%t;~@-HYK^cPeJe{qFv +zj4flICGwY6g!%myQQ#{pVzK8MWY}3=5szzC#dLp7MXJBHA|36&1NrMJ<}w*^=dZ8G +z#H_vO)cb@ip)5vt%6j_f}MLd(p-N70dmHE2>bg +zy`sk4U;g72wf>V8b^fl3djHvq2LHK=M*qc%CjXU+X8*N{7XOWkR{yPvy-U=J1Anp> +z-fr(R_7w9ve5dR9_!@7|kn=va(iCsETlY8I#=fy88s`IJo)~jJ(iBUq$FbSZl|`viWMvo0xI)X#DBDIhV1Xv>sD_t=G&5ufnc5oOEv`}mTU<`FA1(V4B8f$!ZdOY +zH|!a<*}v_9gpoPS^_b7c#{4tR#(H_I-?UFG*%fe%%zKv8yyN+2wzp(=AnmqiZ{6;a +zeStY+=Ha+C%2Nq1m94u_`kwB +z{o}gU76O=dYPlZIQ3-DazES`(} +z2cC<(f#)I@@Lc3AelB8}!p}u4Dg0c-az8&8v83~J5zEKvj&_&WJ^J*(86pat3!Ozy +zpR>#va4vIZI9EEWook%y2saQP;(W%r*}2vEymN;$(wXIafpYdZ_d8>d4iO!3rVt*Z +zbi#ScdB)l6jG5Qq>~mgr_B#ihag+wLMYb(F%$bOk;+#dbaLR&3{*(xEk#3eVg`Wfj +zFXrD*j=Q&AOC$2X#8Y%vyO+{D+~;PAUy3felkKMTN#*Ct2{B(grTt2{_<0qTR79Bw +znA)2n3=guXKH2gtz3oQJH<;SIm0Ha0Jw)x?Pw5D0t#lrPkITr%$@q&zLDAzNSqdeU +z?xjwzc?-Wlr&#+?&O{ +z#eKz>^O}nLiwCm0@;izLiU-}oZ7c3|hY=U$j?Joc$L3yj$GfNJ)wokhmY!GYOv}B# +zKy%M^XJ@s#7ce>_oWXge?gDplR%>2OZl^QYU0U3qSD#Vk_7|TiKI5(|z6`6e#e<{C +zU7LGdru^~+T2`04j;$EU87x!QHTQBVS)W(xNnl&VH@cfLs`6@xzYMzUu5#B<`7mlv +zFV}+9Ts%nr#j@YzMPL5*yc#OiBF7nZxO?o%nw~7Znswdd6=8p12aQ$QICh|mkrnuv& +z_o=nyC2Lj&(TrO$Fzdv +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 +z1s6I_D29Jd7(LuY7!OG_B=N(4 +zr1O6}OQ<~KK}HqN+0MwX<5Pm{YRa`C)U-3mMKAkr>*R79clhB`aE4v`UuNjp`q(0f8x)_xKU?Za#1phgO<*w1M3A@?=lI-nc1T!T&)B!$3T!0!Qvkb4?f1xYD9FU5$L +za)c;F;N9Te92?YX8Tq`g%|x%>t4AQWcRynF7S3G@VC^SBm;Qvg3G_$qiC5GN>cA23osz3?tv2+fxm-~Y@o*398&fX%>_z*)eT +zfP8AT>hje)0C3y5jwt$R&R0|5|A`fBy~Morm7Bg%ZBaND;mp_zT1> +zenF%^4Y&b(3LZ)w{%zQobRPa#-UELa@qZQktC0T=d?)ZD2qMky_+O>24Zso-vPc1tO4TJI;>A#;rw95ucd7N +z09*&m1AYbj?+)P4Xct%%oI&^+qxL4FZ62cv)CBNx$agaaJ|$$2 +zk6cSAB!5KiEJ%I}$?w4b2z)s7Cje`KD)1e&VmojZB+mh>V66lQ&$Z=1+3INEFCf_j +ztOTY2OM&G;v{8E$o=D%EXx&eN$PJeM{{*>T2H%c)dJ;kl&`)-oY^iZKLZWXE^~ +zF9SkuX@>pHurmYlg^<^w>QlgVh|JINGa}^&wh0`c9QoGQ7_~PUZSxpapoV9I+T)P#W(<0k +zQGvb+2}SreMEEwu_BM`KX@U8msnRm@+FQ~Z^Xene*~4goz7?lv3+!vBA^AD#?FF9$ +z-U^%ui3|K%=&uG2!NV|M0&=fI^Y6jifzt94=p)w>3dtXlI}4KELh?KCKLQ^P{RzNY +zpbEt5p>7ARg5)`16|9v2;kmXPC|ey3`~@VNfR(@$U@5R1h&F1E!V~G66RrCx5V^t9 +z|DPcD%i!BlZyfkSAUwBVmD4gIc}k8ZMy(fk8e=3F6*-!_8AE_}jCk-eAj(>rVPP}s +zngO|x`rsErrw(VvhC~dw7gj{(V{QJnA +z49Rs!2Ed;N4{K@=FdL`aT#00`q`}fiFX+7Ns^p;sZY&d=GM^{CV)F_~b)zRgSn~+yk5k#JNaF`Fo5M +zMdgS$mTUw6d+4ML-{9x2I5!?dtlq@w5x-8;Y(SjYE%+UrbvGo>;FNd?65It_%E7Nf +z?hC*vuy!2ShHtW#qty3@*7BVNB-OaLJr4`>ff+0b!abUj2$c5)WzdX3E%Fy8UF?4l +z?&+-Z{2wdt*Kl8)&uGnN)NH_gkl)1jLvpu7F$&lQTn}6WOxNYz=x4^Q +zkhFqdkAABH_T$L|zFV~57m%9%WP7L{cl|A>w*{laWsmEgSL1F`TIlAx17Im5^`xwY +zB`06U5m>M?wa+5p^%?^P4P +zpT;+>iQxYTT!UO6FbI-X;A6I_gdfBAvmb-R0X_;A8X?JN6mJ19NFDIKu(n)&w+l?i +zH@~}p_rSscO`VL~=YgL1iU0; +z-nxPPXWqIS_zfA){M^rS89H(3+cwm`9g=AMw-DJK*1uJjz;7o$$~w7{pmqm5 +zSt>2V!Y25?Nv;pJTJ%pX;^gaCotXF8GReZXp)=3QEB4d;%@nOU{d^zCI^s>{Y25Ma +z0^mX*o>r-|klTycxPU%6#CFv0>FXPRPxPMcNw%-Agz;FxSia55zwr4z>gvN9vJY5? +zc0CFIPoRGyAjf)Z6~LL0d +zvxuLJQ5?G9Pc7(A@?Y(7{bG8=0YG4mf!OnBw%h0R$GHRLdb`f&B +zQEG?W*W`Yod+WmJ*MevHr%~4}xmrs5dQWnVUj?59o3}7(Z$oDW*BJEAu+xirS0i%H +zz~)y`*Adiy4v2ZDH3RR*Xnq3vC&8!4D3UyMel6_)w?Gp;X59cD(N4V@jnQYxTu3kn +zZF|8#4x7ushX7wi?qZZ$gg$=&*oSs~7xN_!lKX+b27VgrfD60=J_4382h}eE--m^E +zX-Cd1@Chh&1N=6WS}6Ad#-OKR4eNYRmGnoh($M?{Bv-*>HKyL?Ts5_VnI7$!GlBx2lJnS{L`pq4)Zpw-nOOa;m;%5JNO$1%df57 +zgf-}s$F=#yhia`H;aUS};nHXNVc`>bf4;TfCdy$Q8JQ2JS0hqB4H2}5ipFRLk>z3 +z5EW4Y3Fe5X3<8ExR6s^lOqjD65OV@W#efma3a@&f_KY)k?w$A6|GzuyuJv@eYj<_^ +z?&`1h_jOlypO$}~l0mF8_{#i~6nHk>0Z%$QW`m6Z>kIdeo`JuBdn&=T?|9d78ETes +zXLBwNHHouySMcY7-48X6;9udaKp$)^)QpC;eqeQ>CJ%fT{1;$Tz?MS&1@PB{T@6+O +z)(EUSM3$4*e7(V)-Qeh^f`1PpM8MkqTn(AUaP7x~ZHM{>@Ef_cl(Y|5IA3T3{zX`8 +z0ahI%e}Z~3JfSuQ-vss&2!0H-Y=dY{(jG#zA<$+Q)WET$+tQX$qX_NiLCi*YcUL6s +zv-H@x8p;pset53^2qGMXwcDkmz&!^Sj0d{}Y9e_|xM;c%*+cqN9kv||(O!V<4>7la +ze+8_f6lZ9!4>jo!CkwW{CPhFxny_{|%*a%seHzq%fcnF5)Cp3wrEy>_4b}&021$MC +zDDa4Jac*(hD5&Es8F9}42<ydCkoH8H^W57Alo41vY5s#RfwvU2Aet7u +zw{VZMbXQnw4!&;3QVw&N+tN^91h!O)jMPF+I#?&^TCkd6^T2M0mS+J07ir!~`vdj` +z*buM{&{9R3IZzV=eY*zsne^@r#2F>cYG`u;>_yo2CLEVH*zsUr!ZALCHq{V$G1NDL +zjgm4N{7}e~KF~5n8VxKB_ht1dkbtG#B^^rBNl;g2`#5WZ;Pdz0t{Q>?xiDGc*0Jtg5!NFJ!*KjBuMyx^e08= +z!}*ZyhhaVv1b3$o!_z%;g!p#^INReA2bz;Q*YK=w8NCl}OC9=%DY09lZGEcz$ +z8iV&K#2}iBJ0!qMm-{9atQYd@FzST5goef@pmeY~U>AVR2U`TTG%O}M5^ax&jtfS+ +z!5)Z?i%v$zz@CXtijP4T!CoZ|gVAlU_haHiW6)!;FJi;PqEQ>zPl;r;0D*;j;YcX6 +zGAR=2FL>0qQ1x-4M71Y +z5QU)_l#J3)7FvMvP$AlYq`&2yBki+5MOre__tyks?%Vd<|1@C0mwDtENGb1w;1@9R +zJD|S;`SW~vTUvI~mX@m9$#$gd<|!@Jqoi@v50QP5`05w=_XtO3^_?k@65(svxZoLs>350%e8hD3seo$Dphf9Ve|TL?_77Hq!bel;xsR +zP*#XeL%B_K2Fgm&S<-r&sFo~MlGf*-EEk=JvO;tL%59>HP*#fSNbAZ!Aj16*4O3D2 +ze+!XIaO7p8dLEg}JTg~!WUlhaTqFA_6J6)=xxwRdlgH&2kIQWykvlvhcX>n_ctjd` +zMD771_jyE`ctjrXh&<#GdBh{q42V4D5qZKR@{~v98IMQ{kI3`CKqMa(p^d2GpCa;t +zN8}}s$SWR^*E}L`ctlzOkv1NYw|vIDHC9uZ3(k={Ha5*`sNK*X9y +z#D+)2mPf>nN2Cvrh&>?Uz$4>4EUmlr$kTEViGW~gE2JpzZN|E8dG0gQF +z&Opn^nSe!c+{d9y(n#10b?di5`Pj_T{x+~jLgKSTY +zvOV3C?dkrvJ+aS-_k-At)V1*5a`riR9;EIC@BOPDHOYGPK-Qy&vK~E>^{83aqsOuy +zJ(2b3sjNpYWj%T&>(OgjkKV|7M7S@o6j+iAm>yIQay{6S>Ivs!a^RO_{P{qb!wR|zbOmMtTY-zfOTfMFEL1o`Vyy=6sLVU|&7;l{ +zZxwjwW!?pucTwimfyZ5yveYHcr<#b(hjsO`R+nYo74T?+o)S`{uEG{vPZm;KFIGUC +zYu~l$N^yP4r;a05s)#I~f!ZSK6sawu?#W`^=dln`i>M_eUrMNrq-7~p +zhUBRVssbrfmDI1O6IDg+Kq}NOYA?Csr{T(2jbsh?RU_`YuM_`e*|lWFR%$DWxr4N) +zsT!&VabF{+s66RreXKAJT1@NhoV`CM_SNN7%iI1d;z1w=y5$11fs3F^l|zOeV(qPuh2K> +zJM=yJA&J#OKc`>OZ?Flr!2NK4?26s6JNCqbus8O>et0AvgU90#9Em65c$|c%;OTfK +zPRE%z3+LcDcphGW7vUv%8P3D`coi`>O14PZyJfou>P#&Tb+*hGtI?vg`?)*<6yOdBJLplnXYp%>kY +z=z|q)g)nVL+aZR|pfiw&o=wk2VuF4)lB09!TqIA=rRO3AdLg|Kv1BwBBSm^S89^m7 +zDl3pO8JX3n6TOCBgF4e|>9t6O{)PSpsgjY}jMT_zZAD$kh?S$RWYo5yZe-+sMe1bq +zcB1ZN1oxmGWE5+V1{ul2NRy1_aim3`rcWbn`W$@@>5!4FL%L*iuOK}#!Z(mU8Ra{u +zCmHE`M9m)350N4LgnojI=x6jZWK2f>IWnPN(l3!I{hEG_%t#iPAajxl7RUnk#eGpP +z?1Ej8B_4nWpx$^O9*86)JKT{K$q-LujlHlJvLTt`jciG__#iuyF@C5I$(oVKo@CA# +zcrd60~ogFH#r%|kzs%v*rGNcJs4gGdH0LEa<_m!ZKV6Z6mzl8yOj +zD9OlG$cJQQ0UAa!vk>``>?}gVNrsjnKa!;zkUz=PQWQY4wG53Q8C!`)lC0f??E({k38b@;ZEE-Sp`2zZh +z9B)8jB+r{rIBv$xC;~sj&rl?OiC>~9+=^RKG=7iYqX{JcKck7b19zYp!UGz`5-x~P +z9N~ikiYJ^w9sV26@8RKm|}oZ30sWNbix=D +zltx%%hGsC_FWP1j_E@4>gh3LN&R8?nD1)(OY*8j*lLMN~I5AEri*aFGP&PAw8Gv$_ +zfy_XZOBfc2<`9+zp}9;L6Nct7iA*AzukfqFuV{fnl|mI-sIXIECt5_>wsF1Z~ZP6OmfptJdguQ)HF=6lkRKmKm?r1IR#d@K2>=1ScT2C15i#8Be2cTaF +zvqz(igx!H?6JdA|DkUrrLz~$c!u2hL?JX#Y)}u{n32jTa((~!1^h)|?x|m*1Z=$Q{ +zYI+}i5EQePzDQrDuhX~aM!Jb^CVJU|P3cx_ip}ZycnJ2z0eCbH#6dU=N8uQpfRpi5 +zoQBuojd%;Lz}rbK?ZM{w06v0G;4}C|k~n>&K2{$FSqs5H^C1BgdKunub8r1fXUVs2L4vCIr>OpjQkil?aqd3`!*jN+l0U +zr2vY=f+8t`A}N6)DT5+)0!8W!ilhRHqza0p28z@L6sapHQa4Z}bx@@4ph!JHku*Sy +zG(n5BK#R0Ni*!I|bU|nIKxgzpXL^Fp7=X?gg3cI$&KQHvn1Ifhg3g$M&X|MFSb)y- +z0tK)H1?UY5AOQui0tK)J1+W1HumuIM0|l@L1#kcba0CT#0tIje1?US3&<_;A1r(q^ +zD8K+v09R0efuI0xpaAZm03M(Ko}d6ffC6}d0t^BL@CF4K3<@v=6ksSQfDb6ZFi-$r +z!hIby9JuTUEcOQ$2LN+N0CPtIb4LMlM*~}b1h$R=wvGk11_E2h0b9odTYmz!1_4`x +zfvq9H%~0TG7;rNjxETT5j0A2*0XL(8n-hSW6M>sCz|C0TW*l%c9=MqR+?)j5O#F_U +zy=j|&$<4F$1-hQTM!4Ak+$1@~bJOg<&CT7|4AH#++2sf+$l$+LUAJ&O=VF$9FtT*fPf86{(ZvF>zQy`#_ +z0-0ZrM{lFOO&dt$TbkHpTQKNGu%nS&_Y +zkC{qrenPh(P9l%uKEYc(Y_)y3EUv +zd6_bAw#>_tdD-B>jGArbe75ad4N;p$gz#6~jwqrFWS&U0fk6z>2YDnWypDk1y?VnP +zBqL-CQ93Eq5;l`9>8Ia3Mh9m5=g3kknZ4bCc1rXt!hNz%TGCHphRDq*5X=n(WXlF_ +zP6*E^#4zJ+CbQ8p?j8tLBAq#+D+o +zNv1|LBWIT5mGfRvAfie#HO7#tk(5ASr67@Gu(=XV^}t9H%*dNF0-+$&o)QR4{3XLB +z7T?uquG3D}M1A4!FcgB4P&|r3;V7B>bK(9<^u7xwRI6B3uwP^Q(KnG|v$qF7wG>y} +zew|s8+0{vsDO8bUQlCm_N=3bzLVXN5v;bCr^`TcT;qWXG}LmYl)S$jTOK6 +zH}oh|p#MEA0*vTPfifcX@>HfkfHqS#hZ7z-zwyy9DPB2syyWS+%?k~G`p~{&$olH` +zHS2U;(uS}5dEMe5>xp#(!=}9`OF12I^Ubru9L>eWSrJvoC#Ht +zdqor!L>aBV=wxw_-8tImuxGQpi$lJ}W)sKKmO--zHf1UAD~K5pT$Y)(HmKK>Ax~EC +z2y-s*)wB{Ds1l{ksV_{Z-|f=Z@iQ-a@5OR&f~jgOcCCEcc3DD +zMSJDBSywmpNDSU!PGb$@oQ*v5ugrB@kv5NHSKY +zcN%*!;bnAUQP1Hs)wT~^)Nyug;=h0VGXEmSX>JTxJXScguyv)n-Sgc7gX>c|w+04T +z7Z)jw@MtaBCwqNg@8ucQ4 +z&`H05T{~zKm5wD>Ux^pb+`aPnR(p#FsSir0G^LcFixc`EzSL)4qpM1(-2{yZx9sj+ +z))YP{^$?yKW8)AvR8ujeT7KPv`YQqbJEP_eWAO@FU!4kR-dctt$)IUw`%U5yPi#DbGDM(xo`lcTODs)$Z_ggBrhxeye?I&1c%gW&Oa^ +z6sB)rUC}bt_jF_CzFc#7De}+^jbA4152s(sVLX$$G +z#Z@Q?y9(86wa%xYgt6OR-#q41Fx=g8y?f{@i2}D;Stukl%K45upfS_8R?PG^dUJli +zPx89a#>r-rt8%_>9g;T{4SjOvnfmSM<4Wt&S}C^^XL4&l_}3mOt{EBsD%5?mJ9?3S +zs^E&|ZiV9Rih0*=YL}bNc=>!|QrY6Wj*I%Ony}v?_R^efJ-;?Qxf(6EbWTnCJ+#lZ +z^?lmMPAZo8nQ8v=ffG$8RXZ$h6e*q_7j>>C-F0F_>AvcHi)_!lp*y9ezP;2quwi=p +zy?bTt?;5TsRwZ0r)--IF!@88c1CVCR5-!?3ZO^oAOxxy6+qP}nw!5co+qP}nwyoE* +z_nx!Qi5K_2c=4}_RaKdlS@~tIT8O`@YBdsG)~e;fs|rHsiEmS1sA%l0_Y&PB7JQJy +z29LFG=AGq*iCfMKp5&3|Og&j!?()yeePhm-noU9sUf!0~Fa|`E|xG-AyGvKKH^b;$#eF-)AyKHp~!P$3hf(I8uDHw>R-FD)89L +zSNk}i=17x>=!47=DVf+@e#Vpa5E?9ZajM6wc79vX+u4imTiBmEk3qPQyx=^`CBi=9 +zDos(k+KD)qR)uEZ-jQCCjCcvUJ!R%(x14fa=(Kflnwb;4BhHa9$xUZIBVbcx$adH; +zeKXACWd5Fv{p5Cah?+3zK|%>iDwYxdW->k^%xIyTJg-PvAMt3m=%m@u-lXNWPR-ON +zW)MD&O6y(c;EDDP;bS=Kl1N^o@_w95nk29Nc~c+a +zIp1Z}Lnq0g-Ey_*yo-3x+2VSD1p0K*SiP!C?!#hX;I8%FElRKT&GzgmypQuFW;9^d +z&7<(aIOhJC%6^RtdxZrqKvFbGmlLo0JC+@9Nr9C5G~?TZ@x?gfPoMM8+1~4a{#y;_;gZswbp&DtabQcu*I!*g}Sx-Hj1~!f=3hSPU%~oy& +ztna25z%VJ*CNfe-N&|U!s`7T1u{qc&Cy~$_HRcaz)Os$<@vZL)f@KQAk`yjlW{!G$ +zG3TmuzF|0?<8%w<2>7G3g0^fyvM; +z(X=ZmV^h$L>dtx2X|kr~keo0Hcc14_ZJFJu`9Skciky~EbxY4T*tRxO$_RevWZIKs +z^lWl$bZT5Jd+Rtg<&GtPC|_=V@pfJBdAN`yuTi4a)}Nl~l{SSsI8gg&GPp$1P3ftc +z*AJIIUf4;cxLZ5sqVjl0hd}IsP1Eoce7Y+l0W@TDTunDQ&X#9-o-7NXY#{GuJYG1B +zeAUSGn90^Ywmnd1^UY5;dXkoYGF`6fc|LOVEa1F~bbqc`)oro28sC2NmmEn|Uz1RK +z^_))M&Gnny{GeXGp_IAKfGB@_2pPtFruVL9p7&_c;@N4jB1ovz6}@j^2p?|W$!EbO +zzvi(hS{hqne?BZ%(Tg>BlFhle)he0CE_SRjNf$7UkSLi}@{lx3-KsjV=|-zN&bW_o +zv2lLoH*BDsdvjcaPUk-A-a}K&AHZ6*HVD%*?h$v+yL0FZ=;8`2jUAIsYUPv5Z#TH? +z!N1v&0My6uDYta_xGBX*(amU)Ty<@c-kT}8R&(GlY^}Rj%UE7cN;&m3{y1{kC7I~5 +zuTn`dP-Ekmt@8Xj-Z7oBa&Mi{kcNK9Df~9;OpWrvn^9kU +zR#&-RKsS0ZdwM{{#0;uTNxxLbP%1sZY>W_0L?y8AurJE~7pl@iVRO;AS#$IuOO_AJn(Yho?0S>tZckb5wMl7?|BGpE#(VZu(_sFr5&XE=ncZSGdnlt7!K9w*vFq+yqXsG2y_$!*bWvTA?4b+4oi~l+n&+qiZ)ww)? +zev3?uu-Dmr#K=|$Ud4oRFG%+!i&)dgD3t!Gpo;yJGxQy}32$LTa_(I_{ek359CK~W +zTr|Umdm2g^3^K$oWI`tjwfG#Oi-7WrNYy!9+_mn +z+^1iZ()pXRMrQ+m5f(V#U=e*;TfJ&F5}f +zaJgBD@rjGseW_C?ftV<_%;y#V_Ta*&Fm`HEwtc;%(3Y91)AJGJGY6s@KEb@A0=9>|Wl-f|d6 +z>sy&hZvE{R!b0jQAdyIZPy41Z+jX4#SiU(Erd#1E+k&I%*3#_wx(AA7V*&<@L=zgF +zYsN-&zivHswj^x3`I7X#2+7M`Xu_W3L^*MZF?hi?^ +z3{gl$zufY%Tsy*~U;UOj-Aej06h-hKE3wy+2bmkdD^;p31PXE +z`{eL@#dkJ?x5kCY@>m6psY3*7+})}Ea{kD+FaF$hYAhQEz6x76%JC(l4i^qXOUGaJ +zueH`#_~H7f$+JPQ0*A9rJgmgRQ{M|uM`}5-$JlYqlJY1D>dGu-WqRf7@9kZ>u=iHj +zntg9hJuF&~=;+sig6|_56K-!J5s23n(Pn5|t(AJ{()2}UP6Wjw#OoFW-vUg^HMLdi +zt{$V{Fj_3uTa(kx=F3}j6AoZ{c6|zys}e@b6fKyC(v?)W4#g)s>yxgql3l@m-E$e9 +zT0MqG>N9`&@C5X!roDxM)VI*HwX@OJHvcPYsbc~INyo@ai%Wz1S6&sDUKN*)ndNs< +z$Hk?k{j8v;|DAr982_UE&N2Tt7u{zYMnUn%r-pS3IupLBXARa_<} +z=D!j%9UboP^jDdd7MJ-`>+ka4ni>A){A|Pc*@sV_-?>jc|JCAm&8NP9Xsmy7Of3KQ +zfsuyhfBN&EzWvtonSRrMpIJU_{6qV5{%!YP^v{0%RrksJTl-%!X=pyR(=z{U?qAtY +z{r@2Km&8x0>bUB-|AR8!zbO9(hvt8Ne;WU;{Z0K{{=@aBOaI&AH}!9hPjLT{^&8B; +zyZK*0{Wr9q)ZaY6CH^-0H`j0A|84g>$Morrzxh}h82+LCtNVA`e_{QRM$HJeU{GTEG9VCB4$nyV+(f_{?{tl79 +zAmren7BDum)3>1(Fw?fv=hN4<)YGRH)3-3RGs0zHrKO?yr$CEK%gRL0!otM`1Nmpr +za7sN*bJmiZdwR&QO;A2hOL8@&iyhJ9!NAt{J0g&@=#-S>Go)jQ59PxzE$z356^xfWX&Ton>@qlsin8pkho} +zy)ctkIou6q3PRz0cH6-+8w{>T>4`mDk66inxLosl@mv(u7)U(zV0Bn_H@^YEzT74S +z7x%dveg`;3I?a0<6`oN+R=0Wj;Wf<*a9nPS;$TNgB23`@c4<%1aj-gqB3SOEedOq6 +zt`38{=BBam1hv<<<=p9EN91Kc_Jp;j{uO}zToPqDMD+v{Pm-=-Q?+A +zv-WTm_AaA6(93-mEb2gM(ON&@Df$kp_JaRqun!CBAQIi$07+=L2H@Vb8QGp%BB9&4 +zk$bGQ^Y% +z1YvmuJymx)ciLPsQn|>5@K_7lK|yB~xe3~zf0@h$(}D<)-TjjIm{;9As&Ew0Ks&3O +z_{NVh${q{0KHzDZk&~W;Ej8iiI>-H!J;2pj%^BmoZdQL<=^;7{Yu{1#9jKd0Ho`fZ +zLe>&?o_wMoYaRpFOEny9l=^+Tol?j%W^G`GrnC=;8>9hWE5m@PJ-!XV)E`T4d+|d> +zJA-m!9HBxp@=hnQ0dnWZDjZA$74}DQ6~c!lO``y~5AOdQ+aK70Dubv{z;qA;;O#@c +zg$pAD8kWR3+0IBv&RINt;HX>S3Vt^LvPe@#PJBTLbl_kDz}emaD?saz%{DMq-XY3%ej@$xqD +zN#X*w$ilwN+~<*aroZ$-nImC9aVzw=EP%^S>0$(MPK<>EoWZN6t&7QkVt +z5q||9Oh!PGOoeQ0uV^W66%dG7lR`c$B0GjKG0!iIQsHa@MwDSc%Y3H_b+d@yBw0RZ +z(-rb#!Pys*bScfc%)UkWAxM*Svdjk4VAlak{7eJBJM!cqAe2t=lL!bdl+6UZ)0_2R +z0YR58faF9i)fbf=SEJkE7HF;Xl#F@2LhmnR-&J0W8!pIK*|M>d*xDw~t@$jNBwD??z1`s*4 +zv8zD|^bMe7&Y*5_60TC^6txff9Ly@xDhw-Njvo#b~`kN6j?_jFVZy&Bf&QS)p@wep>6dqNV2atK)iIs +zxc@OfBGkC>5bXQ*`$yrYV&0Cm^iO^2j)%!JSw03R9$vhH6`ec>Jc(IZV-|{i2Vi1-Q2XB;ThEZMd66Fm*cESD@2yyLvdJyg({{>YLXjFhunB3#MD3xvhz=rzZ +z0Ej$v*?0e9#R`)!qunTHb!3rn1Y9t3WaCULnV5z53`q6>R9lLZS=78g?1aDz_yqV* +zqd)}xKi)$>a2 +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 +zK~1O`<-j=-)?Us0 +z5dVnK*rr_uui3!#Rl{`+VT*BL6skhWAXL*=dr8F9jb7sZIF6#-gs8V-;L*NO95dZR +zNhSVuiR<&PTsj}O?@-SPcO_l4?XBn;mbDY~!-jG%nDSgNLK%6}BqVN9TjZpS0SV|t +zQpilh@cMW9HrYn5(Q?Sl5xz>DpjER3>I?97#=wp72^<~ +zjYi|rAziM1zm0AS9)^vQ#Nf=H{l1r3_>5=lslM{!v8`D^6<*_oB$psB^i??NE@Aob1%(PGY6-LE{ +zORhrb$n#43LkB5Zq0-;V;x&*r`^bG)tfqKOOkRdDRCYj$oL`x=oPU@WhX`6w8Tp?- +zZuePBI64}HR-NXvx9d9z>lT+*5!nCKeaU@1IFvXu6}w}0u*ECdn)$nYyCbWz(EB~&EDdARfR{jjI_y>do4p?UA?_p +zuL_;#Y9+=|kkUZhACgmZlVp}oYi(k(8dgM_^Q2nzib|Z`$p=G>Sru#zaHkCpeVia2 +zLjQEMCKyLQne@J?Bzna2tZPqVu_5G1arcq&p5&!F67WGe@wscexBmOcBEl%Fq+6C7 +zjF`99bBLYgvw9=SzE6C5?E8=B8M7h>!hU1%58(9PvmI1y-;>^Z>2KxTkNl15a4CI_ +z$X&ixIIH1PFjg3){ssKcOj9E0UTyBH?(4zaX{WkIf%ckYEt;=pyrD1JpsD~QJ&cdG +zShreBM2jmfjqoenzzMmQF~eGT_f5jhs`HsB4_cI}Bl9%}yLXEg4YQ=`z75HiLU>Io +z&(U^SvttHA1wRobUhw#My9UNJr3$gd1xN4wphKwMd{un&7Z%6$bZ*H)&UV6CbR2%#OEE1xe)K~^E*=vANnZ+(yM +z;?WZ6!6tUBkrlBGNUGxI9R@*Q^2rvI&a1BDm$&4cLfXnXa=Abkx}8y}`k_>j#$AFz +zF6(Os4i@Y#CO5w#C%IJ6HaDj +zL?-P!Woji6GGSX$Q%;&qxpQdKR9xPs;GRgWZzzX_5B&IAfuoET9$xM+Lc63sR=(0y +zW2byHo@R3_)nQhB)%vD`8SS3vJr +z@R5NUf*t)WWKA?_t>97`bT;$6(LVR~%6Ng +zzJBCB$|agiIAEATzOMXN3>#Iwm}7PYO4Ur0IlC0UCu=MF)PbzodM78jlG`THoxgW6 +z;DMKEW=Px6`}n$!rA{Qm9_w_;Vh$8rtZWQ2le&&D2~gls5X)|EKM(U=5EVv!C8c&O +z3^?x>y_RC~%}UnW+$?$uhP#5bxHn=|i)wd+|CapnE9cdyyD5XfeNkaDoQMk;nja{APJ806Tb +z{Oyj=wNt|Y?$ZR0>JH{NKDx{lMvr(y<=7rf)6}8Y)I6EaCcfogk>ms|49}x&o|m(I +zS5BK$XJy0O2wdHmD(Lq +zjs31Op6!!;#a~T|f>cU+i-bJnU>jaqRz(sxBAO?|4r~25g_rEg`QF^S4ve$2?pFYN +z{E)s@kAQIJ`m($o#o88Dy4$CNRjr0u0FR*{r*bw{Rt`_^b&wjA7@UKEN4}xVec46t +ziOrJB=`nJA((#bvn%|prFznxQjdOFhG2LL;u7>$Cb6fzr?(&%Jimfzf`%)H&tp5Jq +z6WL++vBbRvbtsk^_a!wB^Sjr#N=oDFgh=4zBH<~HvC^yi{Fm5+9YE;*#LwB&ESA~^ +z$TWFgNnH7liFphSayD_miJYBbYQ9CF^jFOYZ7V4ZtrS|cau;jPao#WiGR;56hSYZ; +z%B;QiFTdA!Gs;Y%W0bGu$t1xXkiG9Ub=PdIKet(3n7B0!}+*C^wP&Ktr)V__);nq1 +zY2n=HxL*#hw&VS%cidQ;_v{g;wsd>F}cvogoZ(qMX-aSG!zO9-{7l^#2^p$6efi-Sr5?3u8dMXVQ-h$DhC*&X% +zj-jvY%1>m)NM(&`QE;rF#nTHQOh8x3Ar3qe%_|H+pg%qA-MrN7T`KB!J}TJ=rPdw2 +zoIS%*W@SMeg~uQc$KER{??y1SQxZ02j97}5#SeDwY+S8=pVGv6KV6DUI=l2dcW1t+ +zYCTX~JCHtCb-kl((5(5%F;gA~MQT<3BZNv@Mhs_{m1UXjB*wo3UZws&?`ZfGrdUG={ +zxAC52&o?@2XVV^jp#YTw!~(sUq`Cgp +z7>&n{#h3fX;ts++N`~^-VFbmL +zic3cv2<7R<&>7?_P+Mz+emRdjZ$^j+ZiM+(+#nFBduQ0yun-14LZSC=<%zK5mkJ3? +zVXJxQP?IedP3^5K9&NnJpd0X9M*a2343qO>t0*E?GaxL5Ztc|CaI9Hy-2}akh6p83 +z47ZfSfy$FRoOM_4u``^1`Iof01dj1c(l)5h^2ptc$B(Y3-#5i_2AYezhEbkMn`}L@euA{|H^vA +z=h}=f_gCbT;Rv$gMcok#5{j1cb0Q#C;@^Ng-u_(Q%zXy2H8=lf*O#Atfd=&kzj_H^ +z2xF=6-L2Ko2A-~_o%CCY))5jgX+^xFx_@ddosx~yYwz*&z;&WvmH>cTH5JFeXU=?Q +zh2^)I0Bz})>`aeC9tt|1ADK^Ugh+V*rul98;Q6kj!xBd8`aFP{ih|}Q#YHIyPmt*ndV0)Z8|TJT6(VOk956V{xSnZ20?tK8wdPiyW!$*jE%dcUf*Ci +zPQvaIzkVyO9s2Z1un6w+7=;FTipMgK+x1=UbfoJm%W=hJ#l0*Qx~TcmChy+PZqDvB +zu9ul4#pMh<|-*mm-N>K +z|C~ujAa%oiqcl2PN;E>vV?wzLVE>>(K0z|x>h%CwI#@q_P$x}5K_B3j%e!50fMHg7 +zf;WtVl{WS{Zb6l<0B@myR5*5*Ymj*MOBznYOfR3+EE|Okm@w5XfNcO!a9_hQTr9Ls6%V>c6k*+d +zrlY-%OFWnFR#PprD4FX1q&idOS+1GFvsHCg-IO(&i3lXLj +z`cMfI&ZS4^2Z?~STAG+uH2Rs#c-5FMK%ULVJ5_3>O8mJEcEuRQI52MtME_#o+Abo| +z<+4cB=fd|@1M|M$4}VA)0HJ}nOeXu@*t*!b*h=hH&T2J%vwEa5JH(U%@+xqv0;1i5 +z-Zaso$J19e2RbR_^T{jX%dTZnhBg~cFix*qG3jd946O<{@Y8U>a=s!sab$VMd+%p6 +z1tD!IGZKg9_A}f}dhE(#_Ixb73$Y($Gi!TYe)(WURcly^rY2P!RP;s5Nh>B5B^ykj +z>Um^X4d94ye_fsR^OjRi0WQYf4MQ;SQxwHDyz3?MmT0v0cdb*Uz(1M>-N6j(M~p)X +z2gewtA7y+n4$WOv_q`rZ+r3fOo7vpU1eJ_YZgpJQoFtz2bM~VB9(hhL*bOGuK)EH> +zZ9Y^54_B0yqAHaw^sPv)I9eqaR+uV*%=e9cAds*lMt|;IW1Vv?a4>!sb{7^4g +zz0&b?+){AYRP5lQPwEXx#7*s;uEk?m{Gb(^DpA5#6I}P$(4i4Oi1PK7WMk3}3j$R$ +zbAixLLrq#Yf{;;4NhIswl&3?@#s;ZSsGNiz0Pl2aM1$W4%k>UNQ>u?`g^t)Pa2TnE +zrfjiVzX^hMH#ttV7VzIEpLz~>9;L!Pr@^KfBs8(L$!V8`-l#Dr$LRTWn5X05@(wzyKa-K=GRllBVwuqvWK%qs! +zGG}!*6@U~`1;adi*}ymL2mt8U@K)b*4~@RgCBo%5+sFoncvq*WOMDc^dL!@-1V`Ob^i*w=eLDgaRm5R;hg9^>ToGhg_U%|B4m+9Rc=hMZYhY|t0%{liH1a=k +zus2Em_Qg*3Q9+0l8Sn}NW8K@nmoMfgytV8Q@SXLMxqyiT3{`P=E`|Z039dF!{5iNq +z@GakTXGP-JPi-5w@h=9{8fZh--6de+<71WDRGTX#LgzJ}Z+H}(o;ByoO$f|wmzQA? +zOeM0*Y*%k98|(~?{U^e)R5H +zq<$4dY~>7^fb!rJn$=ng%IN)T2C7FC`!gma^{eFf%2 +zCnJqmhkq=9mnSY><%O`1>XBg*@#QwAOhc0GH4*q#rLab|zxs2rGynKGkix$naDBge0I}PPDNt2GMP6LGqt5D8U-wk^|ih#6wU!R +zAL}P1U}t_I>y+Q2C#QoT4GN2tya)C3KHm$%1P +z^yup!gWrn*ZRwIKey%&kWG#P%-?EI0hljkk#1@P76;wAy$UD{ez+J+*KLls +zW#PANuJOZ(SEIOr=*LXo*BBk9r#0bufw5LSAl6UgodvIjB(WtNXZ=$8v6gl&fr>Q; +zy%m+WuGZ@1#cMKZ%va;~xAI?_z51?0yCn*bOKUEPrROe +z9x5=fH(uyPT`>$l+HoT1>J3#VIO>n6R;>>qPVP`)KlX#cEX`FkJl{g$%%2}8sjED6 +z?-&=vKF;Y)>pfv@9k>o}kSD)@s2gYmwJ=N1gVld2&fq}*PU>rqbv8luyyzgFXf&Mncdu;wiwSJQ@jqS4bZmARU +zFaxUer~l=KgB7&ZXz8>LQIH_N%9TnhoUBY3iMM-ce;65y&y6*V0c9@6yqO5qmv5>3 +z$nXO4@I)ZF@c>FdpDT|L@nwYy7pdf=OC3Si$rBYX7vu+W%g{z5qEm|jmWm0F$0WAG +zYj?^k=_tpHD#*b5Ij~bDK0ol{(>v$3fM*KzZKk{Xx_U%pEq=R*{pRp%f*%@BpLKve +zcgbUk*z1?hSXc`0$&Wq-jLl5|baglhSQfU`r5~HoJBEj%S_C9AVm8L#%s&?-YP+>2 +zn{iWt1TXY;n87B?(Pzu2Y(`+MCJ?4`QQIiJm_Fjbs+fA(U6Ia%&D@x#ZIbS(jT`vp +zBxT&HkTo``SNmfn|7_t9AEv^0dYzZGfvkoI9c(r|f?fsxXx +zDF>X}pjMD67w4D$BI2Q#?hu)jv +zJN`EHm6u-AUf-@C*u*ANb*JoB(cLXX5D7lMT0Ou5Qn+;#mLRm+tPIWj?KK=fB$T89 +zFani2S+2a>kG95m6XRXPF|;C4*VrgYRlY4jWedtx6HXn@*12X6?(v@3$n7DP$Px0F +zS3Ki{P&1QNs415nPetEDWu6tz{TJ +zsbbMhdonTrV-TteK1i|h?iy$EB;?&Xn|3vVhQZHoHR@2C>Dp*+RP+R+P3=9HIN%9~ +z&rNJofWzM)craTjBD>6v=mwc>d%_wQb!=wC4I8gq95Y%r#7Fq~dIikAph)-z!m7G3 +zMkf-hS>+vEOvu2Bu{y2a_hcOl+1s5EGpR{Y4Q(Zoufa}iOowrVqKU8un75DyC`FLr +z)8lSoCW;bXIz +zspZ`>7Ha-Ti3fV(4cjxD+vjI$)v#WIGb?#m{l!Eh$MKM}SuShgxQxw-!}3VbF4@Lg +zme|z?)lr*=@1T+9F*JkO^F}-;5rt}bRBdnP|Y$T9~YWD?KRtH0)$rjd#MlK8AFvw +zaDEV$q_twB-#7WL&3Z3XQW!pxP@zEUpL|J}6xbja(+wn@J-0~!y}c^nwkL$xu|qo0 +zp*r9sO98PXN9sV_`bj{dN6(aI&;67n89$v4Wl#7WdM1@Oah)=HQXpb3Q8z5~1WU9S +z+qQNemd55op#WMmxa<K5ndYEs*N{Ucm~H{4UJDwjTz*!*O1gO+gk2-i9u|j +z_SP=cEZ9!kF4}ez6rC5Q7%A;YgaN`$Rat04oWowyCVwGK0#u|?$p*~^+!nA_%w%U% +z2G&mpiz(-eQ&NttiSTrbmt4f>uCUg9Ms6xn*-|VHJ70=;oU*W{ +zww1YAC~Nypx~sOcb&ag>sK&(?AxeT$*`H5!G^>Nyp>pC@0WvqDxD$}eYmsZI3YS^V +z&m*yyB^5Lf$}F*@8vHM9U%1x;2s&IphKDaS98Wy$Huw9JJ)MygxEzq|0fHL7 +z5)J{G9y!#wxtCH42!S{mab~T5#dAhW9KY02p8)o?j^+~8EZit0&*eXlYUzr9sMHXc +z-{BI&SMNO#c&B1Kg)EPe(YC?$Fb?p;(Wj5qe$EIlRsKkP7qHiCgYexOXG!C}Ob6YLM$VNNHL +zSz08^WWtBmpRxDDjYmT}S;w4?_3Polc7~3|z}l))gdc5q9tAv}^ +z5Q?=&#VDhoBc_LsGAgg~`FNF&D{4Nk@|ir7lJ6_`wfH)G-9E)l;?Y`?>05B>gpaVm +z))Z7W#%Is?uBnj!BU0kx{hnlaO4JPOtHCX>_;$rjJ&yfE +zM)9ub*vZjZQ4;OCUB=Zirm{~7L;^%Z0Z&&R;u|HrAR_)%fzT=~6;%M@Jv$<<#f??e +z=g7r-=GkA6i)^iqWPw~%X18RMitHoV{n^wB5|6M)goxe%*FkI|5cwhC&GD*{3^^#t +zY|heQkwN}YGMti@3?V%Vx%`;*G0u4JBkUdcz_oeRyocGY@ZhzPN1B&D7LEauk%3?N +z)_c~8^ZPbcS3R+b+;jih?sZ&Oe89l#z+Voc&gYRj^rm^G<}S(iVd7b%;Q*ptvX}G( +zdxNCZC^veHUgI#VH?l#40U5QoQmoJjK<-|;mmZ`tE1(#DDka6&nl$lc+BwibJMWu~uW&t~Pn~nkeL^0rX<}uHqFg*`OQx{u2FSH=q+KZ@ +z#>GS6iJsivTv9L!)B>#L`b1xXkgG%0Awt*t`h29v-RlOBtYhQ^R3~A45vWh7Z|Kd< +zplFO|Nuq$rvbuu4sCRUiCtM1!Tq<+>g!$ZIX6XJBN$nz8v9PNh`J52r5!+@Wd6i^B +zGg8hfzqsTdRyV(?_#^&&f4RTK-{J4}gSzFRT5^^j)D8Up{=6@!+Z%<$8h3m*tUpzb +zq2=Uh#0QNrRPI-;EPur+Sq;a$gWxqCz#9sQhUp^f)$?0lnm +zSSP0qx*R>_()9y`D9>#BP`!Enz3SsCI6r>6ly=fbsiaYy0Y(jAuf7I(h|h~;kK8_- +zDL7<@U?t>k_wW@)7$uJxkZOtFQ%z0{9rIXJnbW&gV)YO~*NQuz#x>ik +z7T$gL_U-hchppv+g!`-XlY +z^5(c&^?gK~3hp5;N|5)D3`%~lZ7hb}#=d?sPUZV2Jof3?f_lMZ)}o1D5v2U6+%s=x$3w&8?J)mKQNh;1T;;2Ai1lp;*~ +zKd^dW(Z=`x!Kx?mW!5Z!!Y|>ctYtQL9G(~S5`?8%!Qp{aPB+DB2COa|JT#KB0v5wl +z;(0j_^gJ8A_&mxQI<{FeN+Nt0$pt`6&$=~>perLQBP0^Tkq{i)acc8#Ti>1L@g^n4$Tfkx$M?PJGI&%tU=Mb7%1w{ni;NaMv9 +zt;yM&L-KPfbGmbSfwVUQEM1zem!E=8`ip#@9v2x7zRl$LgbDU80M7m7h@cJ&YzV+m +zq=bvHoVR_-%-e3+Hf7drtF~{y_3@+T!u!hcx5&m@mVop+Uo5ZV;T#J_BnIpF;NXp09IIB0ndA07=9HK)HvbEHXQ$$JBH<9M?vx7b?iJWQ{{I`imzA9c +z`?iIZO~-X +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 +zmiHn_-Y4$^`W5+SK))ux4#zj;-@@^bd=!qy +zV>29|{U74K1t_lNJhRX67=*Z7F2)#h2_~4Zgb)_9SSAD`3XfPy#%RQh0b^Z^Fdl|^ +zoSDm8++jo{LRgqL!!QiPaOQzlOIR%>V?r>YD2l~|rC2SC6&AB9!pZ~_La_=(X|W3L +z-+hh{(!F-#t=io>_4oIme*FD+|NZ)#16-bfm>*sK5%81H(g4!FU}T`0P{8fF+f^v; +z`*-RTC`bB(sybAtxZOabvIgnxT9}T(i28Q1AP)Q&1ha}q{1ld>V7B>_8HwL`=+gNc +z{@-{|uK32c-jwsl-=Y!@|8?;<}E>Lc(qmx=8p~DObwT6ba`@ +zxJ1GyB-|k3HnH7n8?s12tq6so&w)OlN0I0YC<=WMMWYYFNBbQVi@pSl+wY=ygh-nL +z5dJelmq6po=)GSPM}Di2wA=433`OsMCVl|x(jTBQR0&I~8nvKy)P+pQju`Y1jiV_v +zhnCP2@C&!m9y&rVVOj=JVN?_qN2OA^R1sB4NhvkeLK&#X)HF3uEmLdMCbdKDQ!fx6 +zwG`zccBL*QfTs8l+a0kO>d%hoP#=q54&`v0#oxQy2|_#1Mnbc=m23*s<|Ll=wX +zI+D--qx6sRKPvx-CU1cizKW@em5S|(6P~?ZIz>yvuyfp_3e(^_S<8(=WegF +za=u^0Vl`L)4cD<9xg~g`h(?up>>v +z1-e3z(xd@qBh&&j=Z=_5%L6L7khcg3rQc +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 +zL!(Tn +zE3`ZvTKCv2TSJ?^Tw@Z+vo*9$_;tv$Gqmd~)GrPlFzJ@Pnru&b=jqUk7LVmn7wIeR +zJO$lmEXRYvzA}h^iQ|XP?wlF@ozFq%Q)f}@LN9Xpf1E7Hb7e52y$P-?Uv+P?E5mzcrd_#^Kh2fz +zlL23dd1pEB^R8kh)R^xoVVx0Hccrb-_&kih7S6$8o4fw6iZty*D} +z4P2=f8`UsRH;qjLc^;&b4HPgDM$JGGtUpf%V3xuDUe071?+sLX0*zg|F1NoiazFwr +zPsM-&{;pj5Xf*60{8G3`divctqdj19(Q+<+6t@Ph#l +z#E%U;WX6q;2OfD6j8g*>o@C?fz;x>Z$e9B;kE +z=!ozrOd*bFPn{{;5yzC6q8y2EPCIm@z{%>+kq)bU70l(?Ua`yIGxV0btUhaRrOV-S +z^h#WekLgvo9{3*g*15)fW4$e|$G*qCT3Lv1s<*>6<(uv8cFp=0dQHwW-!gaVW6yHr +zRMTs-P5Yj3r#|+S#h(2L&z@I%owhvR(_RlgWpO8Ja(3-~=vu&gpKBTTN9M%p^4mu?_1nnoa?D?uP&qanP;PS(X|DwSaIz@E7n|lz6TaH +zmf5?3W%i7^9)Qeeu0v?=BXT-r&yC~++xy(+^x8Ro-{$nRu;O3 +zGHlcCV6N4#2v1tgVh5D8L24^;?qo59GULN#z=<{#=pi<0`X*jf$$cD*^tVd +zhgIi%orh3osM7F>bKQn{G}V)Oa(2zvs;{rwn#^1?KcY17kO54qCm}%{hY(uh1+QWV|Kj>w^!x +zx6DF&VRfZ$5BB{k>%s8c$b{85+#yrokm;0(`y3;I)|}yRuLXONBO%6&;V7@&Tr&9B +zDG&p$*hlTts2fANyF>g$Q3erv&}Dt +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 +zEwIa<0gQ +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

D1m6OnoPfUu^< +z($#FWh)&!QNRu`v?wEd!XxXsrAR;NH`H^> +z&y;goOSE_Tapp#pmrP$lv}yVQXl|OmcqpAD>N9-qGVtL(OZ}zOYo@<8eJkO6lm@7c +z)$mW^oyU3~>z&>(y=nU4$9lPa{v8cwOW;k(@(tGfKTJ#^Gx;mb2U^<&m!}k&6 +z`F*<2Rf3dhO+tOnJ8jEz<cPUXmL!}f!Y4nWI_#87M26^D~cuMgz;*GY3Y$nY}GPW~g=8Ty`e1uHU +zH>T@`bT1#n_%~#i{0j0Z#Gil-)YEllIA%D8+GD-YK2tp&Q+58RAM%@-)nfH!Iz@h6 +z{icXhzol*yUy3*#aa!bJ1?AbR?cWgjc+Yw)QMCT1!kI$qVWWWW7?Y6q@=~ +z^{eFHOXQQ8dbUPHpig%4uSSfr*OHfGD5_plP9v(^;z8OC3WbtFXV?@Mb#nhOrFiw6 +z`kGQsR6$flR2{5GNY>TI=<1Na*FMp +zoIq{Kbarx^L!DeQx#Z#1liN52)iNaZ>d^+r==j1(osJkrZrhfA9Ty+2 +z*MxyyqZf|x!Toip#?q0!`}lrwD~_4$gTsM3NnD3KGWvLelOw_r5#KmDVR8bE*Vf5f +zb$LKSN7De0y(d?FilWV_I)zPrT78;gbC+$G7-f6Q_7+8Gi>-ws^j+JJDMDLqt>O## +z9|tk`&jsT?)$UtDw18+i_TNPOz3DE&d+BU_Pfmp1as1*?5f_H_lriEC{(o6OkN4ka +zczw|xiT2T299rZ5s1<>AC$R2JSa%kzJ1f?m4eQR1bvFv@F6uM3#G@fF8fJ{fW1q7n +z9@oP}wM3^ehWJlpqK9ZH(TBq_erG<j-ym~gmgvl?%l#h%J~&quvfVkBAwTeReDA +z<5#Y+bY$=Euax_AT90?$wTEnN;C^0q|N_B2x-?#>*p%SCT +zwIlS0>`WXmw6$s6R-z_KjGK6M+VdufB&&CYh$}P_`)!`n<&`RU=eY;a^Oy4U#TbD;2(WR|QGWsi#%`>yToj +zRLj!R)#G^2vQgTkZPk+LbFx9InuOM9*xM!>`WCI0s0*oYW$Gf@Z=X}2qdj1Wx`gge +zE7S_=`Eqr+uu{*zE+W)b)PI}$D&41yQeRWQBcjyrs^1k4s10g^7^60-jp9Ldv$~mV +z{=NG5v>U!`f0=f}8oIZAi0*A`G4mg{!~Au9;k)%*;M~u#?WaGNw&#A1Z5MuyZ5Mrx +zZ9nxnw*54Ar&7gBXL*Od3rvB`&F6hOAsJ;wN*>8fL9!f$&zb!}vMeQ?K6MAlW@4}F +z43Z@)e1~^1NS2`R^SGuU*?5J|sP#dzXeH8c@{=;VVltfkq)Zie4JSXy=pJ*xaPpI~ +zTXb$5KKV)6b^I^vm?0VO_`EX-oL3Z_S5%x=G&-;Rh|bGDrc;YGXeA9rw(Z@ZC}*5! +zkW2oD!_mlRp`pl}Yv6MYQDfxi4)c25rwlfqGPEW6LqXA};g={0c$?7#y~oMJdel4C +zs}%BSsv_*dEFQ)aa``#vDn6R-AV#+cXH;p_hN#A<%~9K;c0@HtwNN@3b%Z{bA|0f} +zc?)T6qqHHaJ?aELbJ{_gM^Ju3PqJ39#bJ8~hb#r`>>zG4Q48^>qRvt}A9abaH0rG3 +z9^*dGDM~ZHC5w7kP5l<5GKFFw{w&CHkdd{?gs8P@F3K8wr^)~CYO*rkD_DcJ5 +z`%3#Nd!2o~y`IuW`xg3~iL{Xt=k=tuic+P0yL}fvbIK&mEhyimCs`}l;;_AqLzV(| +z>WEuO#J2X>_ftA#ZzasM@Ba&*1^h*;=|S4r@}>=uc#!t%2OU8Kxs9$VwgI9${O>}E +zEJTq+(L}Mb%pNBcJKe>PTZWuJi*RdUWVp97C`AT}$&;JFrmnCMLhO~64 +zIk!H*QsuW@(%Pn*aAE$LF-Y#EY>8?sg`XnH +zCOeUg>M?k7Su5o6;ohlT?7w=Mki&PUuA^?>#^_?>JG{3h@( +z0=sB*Ny3)3cC@$?E$&oyL5Fy4heorbozW_|71Jozq}d>e(oeNDX8Pyl@Kek^t@*5$;T=9*`b#14P{Y}!b8lzlM0V5WFB +z&ocd)_?s+Io`n1;w?#Z!WF6D5!Q0J~iGRghK>WidI<=clGjA$}g*S8^vS9TvPm;CJ +z|32Y-^K$;Bq4^-MJKZ-P$=Br^F;csBU>h`PH2g=HC(SKrs|}_5V6%<;j?%BdTC({~ +zo(U)ahY8?lijld~r +z>j|{}I_54JGc{=bDf%^qcL2<9B==7I2CclQo#c6E2}MO3RuI3TwV%h9=3)xl1Xf^V +z3c=&~m46I&r$+2Z?bxFrG2>p$nhGBGblN%axc4%h*Y7D;qnAx%LS2T010N;LiY)A(_f?qLu*X +zNwiGj5d+`Fs9XVm3|Irqk~)lJr<&#H(G7T;#n%X>1-!g_>h^CVd{f=Pce5(rM>eW; +ze8;NNJs92Ly9xi3GM#GmvRu6ioTlRqLIwOsjQV}}X5b#QQex&E`;M9S-cI0uVN_zl +zHvxYGY-3a>u)fj=9AH!&*D~zUXC|v=Jgk(PWbrf%!=(nur!8mjRCmO8~N8mC|AkhPHU +z=|?Z1>3~fKG#g>3QTC2o7k9L4;Mv1FeC{P3@cuf;dG#f+w-m#f)XL`2u_8~>I{@1(_JIRHxo?4vRuy`cL9Ldol~ +z6EVW00*ob(ZZ%rlBfWq%2l&y3KWCvcC96JCRKU&9{nk!wft=+9#IlI%o;#_%AY!;3I$y_SKXm?t?~ +zrn6i>Biq!jQ9tQC%=+58&^1DmtY8b;I;@2f9%Z%6zYlv3{{nzl9P?i6Gi~5`4`~AS +zTXAn6R-owwYmpa0Qa&4^DPF`fpni@ +zt>Sjgooq8=3rCV=y=gw}u{|ueR&n3Wn}IQ0*Sa0C70>)2PEFz;IiCFGI0qibwI%}B +z9hCaV^EJ_*3(RDsdrOYLCvp8M!u3mD6L-ne0?rwELQdp7#%@m#I(mhhs&)Vt_nu{$=oL4M&|Hqv}7x{?NJe4$C2_^iz!a +z|BfS&u9O0vOvZ_t?O!*K0rLN6HZxM3TXD_hdwCmB_}3!#xb%$Fx3m!6wSEiyn~c^s +zcrUXq;aX=58d)VpDVNZ}(sL0T(UO#p(%dW7yG4E@^yNlcv +zgLmCV>{WC49z|Jf>Ol(&f@^8lLa!cl73H-ODdhF49wYH4Kl$Kmg?}5c2lyJUGlI`w +z{yy{5*n8@6ny$wgxgOV_dhFiyxbD^CTEI95nn}QBMmj+=-v`_Pomk*5U?V)~1nw~7 +z%xgKt_JOAu>3YljVxR-q!KfxNYVqJ(fz2qr4r~O*!a^tbUC@~TNfTDghggx-7?b6Y +zBw=MFLS6^_4se|w>22&4B-bI4-|g*T&&8L40_X)s0LNliI|@D$XaVK|rvk?S@q|EW +z0YBUSFVs6X*7r#ue#KxyjGJ*+WWtJ6mp}slO;{7O%d!3{U^<=eY0tpUeUMRG1pPL6 +zeio8dj7kys|AAU==G9G%bX|yp<|5kB=P<90MQIhIsT_OESm0ee&)Wd(g3S)-V6Rnc +zz^{~}t!uKK1CSS^^?1};5BUXLbq~YxC3uB?nH~hMK=Ze9{Mk429@%T~y^N;actW{V +zjur0{xL>cwPS5-yx!1zOYrNah8H}HIJ^*WdvhUEG +ztJ~j!x*YSVY+ro>@=a*>_po+?CFX~~x9aB$IVSA030^IN#0AL=%*9N7)^^|t!~#S} +zEl#^UV!wc$I$$N*{ZL1?-^Vx`l$gY>Ok%v%y*^LLDveemZn_Usm1KVOrP +z1E0SGuS!@>v3d^U$?Ybq{5|k5F)z3}X%k`d0ra;~t~K!0Xk`KTO33#D3xQkMrq%#F +z=f`tRj#avkk3+;B=5}#4TZ%E+0f{`V^rP=<(Dw)6!z_%W +zRepkawW#}3;8NK98stl%lMKE9r9P>txA-FT2`x6ryMg=Q;Q{zu +z11y1LCwzDj`~*4ID18XO|O?Yw!@`t5OeKdGperFxW?Lz($Ed1GWk*_0+ +zG)foY=S4&m^Dl${HE=HQ4anC5yMYe_zYn|tEP&=KjFwp7DMsqiMYMYnqjV8bcM&6h +z5i!Y{)hN9K{s-Xq$+qZB#ceght42QaGHUA}*$4h@@NJBi4Dde%Uk#juT1O$D1zZZr +zD7H*?c-EdkL{$UxF>c+Ee+BruoI&vIh_pIrB1)|nP->U40Z9_Zyp_??2u-XG8k0Z4 +ze>wh$6UieI+89k!fTw{+F{jDkSIUTzD;JVXM95{}RIIEI(25tDH&FKyH0MHR1NcLT +zfk|i=yM%TO{1?GjG1?PZ)8=G80&+8U81+0P=g^~fAYTpnm(c6)q4jaF_9RLV!4o$; +z`B3f>D2;?7*X9qEFR$&u+lqm{``O*%eF2-3a +z1Mdf41OHFT-3 +zaiu0e|3|Uyw?76N~c +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 +z#2slaX_X0BcqYhS40!GUjnEpW(Y|0Q?4WOn= +z(*440BX~ia&>T`62ra^cNl7jFOcG=+5w0Ngl5iJYnPS@VZ6X86wWitx&(Z_i7%Go` +zyq1fhzjvu6Kt%ciXfK9%RRa;}HMD;xj6q9b=lf3RV*?%g$b3w`N1oQ`OQo?_VUPS( +zI(7()vxZs@(cn=Sm9|4fl8>0$&{}F^nb0pK@TO`SPl&}*pB`^Y-({&ap^Ag&&7_8zbJSC+5a+gXbxvtO>+V=$EGI)YR`;O40sdk`+TC@y_#=d|IL|u5Jr54tbyX9+ADuH^!|eASNc#$O8Bk>?c^qO$jeNEYUQi9QCUY3M +z#>v|c{i=mF9|8U&<%urhsRXKDLdSqK8c!}#y|62(WD+NBK-bV0h*}KYbxU+{6s`&e +z>kX!F+t9j1jZ}izneswcd0zmxCa~wl5X0+%WnxMud5G#y9Q^(+mrv&(&5O3q5_MtH5!pIA4dj+~)3vc}Rf;HNJ +z?b*WnH#UHF9iP4!X5F;!I$(`v;92$Hxn}gu8?xqdfzjCn{I?38y-J{+&CnhbXh{a7 +z)2l?#M^mu#XA~JiYoYHF7#&_hn=>IA$AgCgwqQBSbP%k_=$yF@=FBJgnbj!pP!4P(4r1M1kPt*AP{hPF;N6{IRMHi01{M_2mqVb#1E{InMy0G4ow +z@CJA;y$=s-ib$LbQI1eN4d`h~*>XO;3Xthf(&4_MFhHaVc9=p^bl{FeAhgf`=4l6^ +zJ&Wm_7AIo53h<%NLy;=K+mP=|qQ2q_5O^F?Sp&=F961n~XoydB=n-34#u +zc7Q#EhLj5Q;Vs@u$Xy0B5z2V+DNkvv16m5{)sUVBSG7QTBv5CddLUE6zXv>w&h06W +zk}1#nLAt&CU17NIst5O7C&9J%AYDmLA(xf6mh#vP(ud36Hiq1B(2MDO?bK`5LGENI +zFNNIme5+_1-a?!2L&^*&*{y}X30e+q6SdNN$b(ux5nh{8W&-S$8V-B`P}tecM77d; +z4qh!c2t5kvUO@K(UDr|tl8FT}XCVdlT%ls9u||%tyw}hR86fr(v_Thg&7tM(pqI1EE +z^q6mOu3^oLi%HnX%F-@r2;pgZ=jv!P(}lKF$t&zlw<*oYI!aoFavlc +zo>B>MAmIq$d>!oJE$p}aOv{TQl8C?tM1uhNF@OU+ml1=Hi+%uI7=Ye?qa}r&&~ig4 +zX)c!xv_ZZPlaEpE5JTJnz2nfkedMaSaP3^Uc1>#@#KTO8A$ee#d0@jO&^x*__6bN+ +zg{ZOI@QOK#$Px91!`0vhYp}V+U8Y&=eB=XfAl7pa~@V +zQ@%B~Wi)+vfxhQQcv^lcolUjCK5c>^jYY5*9T~`X)WXjGHG<7Z7!Vf_hzx^L;v$hx +zSV&+TniLt35RD=e!UDokF8xx`7%ykKj}*1GA~Cs6f}}_tX(DBMM$(jEglR`c5DhY_ +zsE~8|-3FS26dZ#@^qUw+;5BNbA^pZYNfXeoQ9>R@YKoHd8C?6Ipr}}s26PV41wfYp +zT?4c|fE58Evl%sZSs7f0uZ9~=CP#BweiOOxL +zDo;D0UZ@{(M6SpK`JzcE6h)&%Gz-l^`Di&>gEpY;XdgO?%25@%jzsk37qk=5q+cV3 +zqo@G%El{#YB8DD4q3r^tNF-wEF&WV(e*&da{`iITh#a}2lp=wYzF#Aef3pdW?((Bb +zgZ!x8Larmn_Db^WJJ|C_x~3!YJ5al(N9s}Zc%09_%=cS^{D*hO2uHv1>5fJsBt9=b +z4`=@azk(%jTU9|fWa6o;mx4B`um&`MN{N(sJyAYO+a +zqk7bUz6h|OoungTCCU;Ni8dTnB|30alXQZkx8RS2gCM-_=a991O-a8#3YhNHT~ +z5HaLvM9x%6X=6C5NV>pLRnirXYLaenRF`xorBx*+t4Vs2Gj&qB7aUb2z2T@Tk-zfU2J(mu;t?6lBQgXKapDni<`Hq> +z5pm@a8OkFv3=kR4BjUy*GJ;3MokwIOkBG-#Ao9;%`Da8%@rZcxh>YeD@!}Ej<`MA$ +zM8@!l`0^GrmPckBkIWA|GULHwCh++9@%T*Sahb&9@*|IkKaWTNk4PYoNDz-mFd!1b +zBNECZGMPstj7KD#M)a7JR*yD +zL>BXiECEE8@`x3LcS_fXFHykpdo(pLs+Id5c-iBeMo9rie$Tm`7$U +zk4%Xi8TkE9(ry@?mcXxbM3bW*XtFK05&jg!V8EZQwP!EBPo^4wqNWr@ +zP16-M%}~^os;FtEqNZ8jYLey!j-o~L6)jqzXi=V`Mfr*rF^CoPB69{Ls1Q`pd(DDNF#f6_%nV`% +z)89UY^G5oG5WW-12OPz +zQp}|)xS8KLCX;X;z-1}8Yy~$*!Q}wQx0}hOXUr=4J5EdzVx-%k%v?q3c?xd+pRQW~ +z*Ci9`#H0{90?OpIDbs}#PE2OF +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 +zwzi*=#ReRjl%69fA|yO2Fv>Bn0b@#nrgoE +zL(2yR{67gcp!G!W||a9yXHI +z^~s&t_3o*@EromY>C)ELZgJ5%qUx$GsJe8Z?=-|iO3%boY0U6vIc9i>FnXIxt0gz@ +zSK~X7_L*J(W}O^Is#donR<;-5e}Q>d#Hk3$mhPsgzxrWzOjmWT3wFG@-u>;nIM6w? +zOpZOh@@Ty7l#8(=xaa>Z^b{_D=Tbz*+*|iP?D0<6KD{JZPxq=&CG7rAT&r4TksY(# +zp29s**jaIX_@N0lUu^3J5{v&JQLT9M?ekKAiFiza8qbr$bm-MZDQXCa^!2cF?p!!Q +zII*-Lhzp={a)1H&s{=HRcJEbsNcxE!x8!FiAF_rbkP$~y9-nSf`ovCMeGVq!YA0c& +z8|GNdzElu{2PDX4G5p+|+#}E4tD>h{Z{>+&R}}i(`Ob`8SCv3m+ +zO%z3Z0ZRSf>1z-2Dud6UwF~*Am8UPyplUBbIO#5g^z%ynlP4bcac}Q80P5lZzknXI +zPEn)DX8ca_6pmr;trKnTt8|k@@g~fpGBAJ@|nAL-bJQ;yz9c?bhCgvU4Shh@tSA6yUohl`L~ +zgUivP{Aol#OnB>67)+$vRmB4z%dzO43DGoHeIC|~a)AfI&vot0}NX<5LK$z?w1iQ!0g7svcGFHKmx{BmtM&he>Vw{`Ri +zF>KWkPH{I4iy`+@2m6+D)?X8K}`8V1P^;rT!vg38D!cWtqn(6_t(X)OXGu^lwU#EP}4u$J| +zw{j=ex5N7EHss?=DRv6cQd;s9;0N!4Yn`4#l;^o{bBu=@ZGEC7Ul2t(?_=Hu0f9lY3>|7e&(O{S{`O&$fZIjo9^Xxtm?Yn(tIX#QHWN%i*W=8hs +znfBY-Te_sL+@Re>A^$T!U49HFhn>Mk8#ptAF+^hulY1@6m%Ys&5XHA+1|WwOg63OMdw^6f4>ke(#$ouN6%mv1!%UsV=x7%UIXI~u0 +zLaZ`OK6@xVv%4R92PMt&%dd;nYDBL}$&rV*Tu<%`uS>D?BJytqcAAGX>xe*s`|tJAWO!wde;BrL55#cND!AHhj? +z)uiMkTz4>d1$~SVk?ia%uBLT>4)2%KY!}yOtDJ11gKA(&2KrzesSQLo3wgD9S8Ln4 +zwCxvHvQFjL#&K)9+v}kSKpG&obS5(g-PU|EBtPlTxiCkSal7XqMAtq|ensbJE-=Es +zAU7|C78j(17Zu3+SV#qejdBPpG=G%iOiadz7g~FjxAJI+PzO!jz?^&tYBHn(_f6cr +z4+nzdeA@arJ1uIdM}4KV@i%b=c98(pThIRjPjkIc*kuUBvTZ81*0Ri3`c=tgLWQl= +zN9IW$vML)ntI7Lvn~lC%Umj#*>GmUfezsyn+VuUim74saJ}p#u*5%b}yT`|l^{eo6 +zI1PS#4)Lx`uQr!aBTJ`{5sn+BG_zoz%ja?Bm%U3@)@g@bT;l}dRKO{(N$|GMBIEdm +z{`tjh?d=*tb-ItqpOc-x8&`DC1ZO?K5enJIOQvnY(UgA~AsiG|`=~EFiTT7v)%kDy +zu6v-r8$Ri*=TVa2Um4K^CjX|Np?7E~uIsy5rN+1FlC+L@z1 +zX6vv!{~rCvucxbOMz(UJzcx(fFgHvV8$rr3L_tANfCRanOywOLvM^v2PB9PB@DpW> +zIuVzdb{MJ|m0`$c46)jV9zF&xHYP@%UY@>~38g4Ora1_FHBGw^COye33eKjnlQX+8 +zRl9)fKo6(WYPt!3^6Nah?{cy6nG +zto+JKo=^0$46Sqao$kplUx2t53Z}2y6H8-Sb;s+&>c}PO{9wt)Cwg|}LGq)<+02|^ +zqqF*aa;vn1XD@BHozywEW0Pi&(zVoVlj-J9yX3#wT%3wQ@WM+du6xQZn?84TL*TzDR8y0fvc|;?26~0*46ts7mh-f?5+{};21x9UH`sG +z!|HPqkx{BB1qly^>&)vb!7Z@vzFb@8o6-fsYg?=o?4f*|`4K=w13i>!FQ4I80A5bm=wXk(9wP6l`@xI8Vf4 +zMnRPqNNA@)XasK8!$#l)lNop>ipCx%cn;IfkD!{W$;lN-prXR}4R1;#O +zR;D>ByjS`~1W;7Rq%F0wmfTmAnjL`wL>6heDJOAY6JcF7M6TGlde6WrX~?k}*3zq6 +zOFC%bMi;gGh(Yi)ga!ew8<0|Li0z_w71J`+5PT@3ee*FrrBpJ;dN*0wd@(yG +z%5QBl2@#1Z6|-no0>+q);pL5qY}q|MG3*De1gaS}kUu)9`&8^XZy9h#y +zNGFKA2wlsG-UxmrV!Hsh2!72m-lmg04OyZ!dBU)|*&Hc;fS?!CvSoyg-Bi +zxR0pAH3%?JAfk6K`V`VX;%jeqJNyTf5L^h+FcFjl90e5^wg=)7ktAFo(s1uwdKYXV +zQk1LUX}oIylqei27Q%i6GSa{&Od?Vw7KC!dJks=bAP7=07Fa_>1JdXxs8fUo5y1g6 +zDiH`XGD>1TxOBug6Ot1V+=2ZN5mpRW#vT$@5Eoh)NvROb0TWgj7oJLoZUPJ`lB5uh +z2~NzB{h(CPSwdU}2zEqfLL?WAgbSw;TZ}Lsn0ADALTrY-BVEkj+958ia4v#Bqymtr +zNR<6z*OnPj+!5RbLTW??!FprjI?yu1d}E?DL?XV2b~jxI`G<1b#{~C*BhoqaSoQv>wR`neLdO-=ti;I#e^^0j4_&SapkYV0+7R +za1n9hl&KZej+REu5X{-`a{H4`QV)R^NwYsY!eLN%OWPCn4zC;Df%FrhTFje#iC7=< +zhNKs^3Q2Ro<{GX#j6K5Ei2gt)=w^Ut*sY$xi60=e^#iwKu^yR&*gojFL-kg`_ZJW{ +zqRfaDAiM?oQw(g$Wml9RAif2&iPSdWK73Ul{Epz>uP~fj59@@^_v)T4)b8R{4DZY1dZBucsv>-gjDhi}Xav+tlEY<|D+aPTelLD?;~2Z})O +zEV5v@=omM6c%lHDBvO1oW`tqC@^G;u+#Qy0PP6iI%|ETkkm2ED(_|x(*-aSd? +z*4Fw5`%`hvXx=<2r_)Uox6@vaH=nLcE~!c^h{JWe-CaQ2Ba_TSS646ftIN*l>S{i$ +zHhOxd%>Lidivu8br=4q;zKv%r(mQc+FYYgtfch&IY5$oSE78?h+mmF!bZHo8m!Y;H +zLE~W2fAZNns$GI>X7@}Pfj&ir;ABuatZCE3c*P`{xJ-#vuzvdZg|G8J50QRvdkV!q +z|DoQWvPe@02EL?ScRF49o-dmxv51J=(qAq7#~gh-|;ny!NiBx +z(8tQoRTS2zj^X&6EeO6lfrkN$W(kh_PJ{}0=@S+BR>T|p7Lfn<)}W_gABvcu&1tP=2J83;V3&7N`)AF&1+j{>(KhdMcy@LK90fM^%J$~IizkB$!0G-;p+BzB0;uazxqN+#)OIwhUW_~A`#FH;A^vr+(#X%u(*OiVlDQGB8sW7S7wnu@cR{Xf7`%TtbV +zgtCn4?t8$xqdHQ5V +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 +zbR8Qr^XlAGo?!co8aMsb&`= +zY$lsfMiETM`ZQDQihS&FvP#Bxw6NL)9ZtavRJ^})XwqA=u< +zRoHBte@zI;@YoYr?s8|};h0!PWZ5S0Ca^#MvVD6ek0dTiJ16M-)KW6zzyI1XToC-1 +z+ppk~nU*vEqIY=J{H5(0xM5hyz_dBKT_fmYH6_2CFuTa=VQ=}i=F}qJHWF>gM)&Tj +zswMQWbo_{(K5?=4@_P+z7g*PUfkx<$a%4)k5Pq@ +z^TNUEzQ^3Ad}FP+DL&&>1NhtNaPFx70?rAkD~B5_oi-`S7W7WBsS0`K@!%7%<}T&< +zU6ux}9k9h1GBG3~`nT}oCqep4!k3-w;M8;84$ImkAa)c!ni)o)*d78{E-7L_?74L||KH)asN0 +zc1_Qm1JMOF16noj&))uICmR~1>~~ULJ@eV@fQ%+Dhaz#3pXKR$o|FC^gY83H`!v=1 +z^eU0UdGysgE$B+-MC@MGU2R&$gr4D-yp}U`GI?}*pUpAN=cMgz8fLXN8I1iiH2JU= +z238oaNv@yQy3F6c-{a!3%l}L$9rwRcEQ`{cm-G3Bbh_Ag9L_;0SmY-(+7w^R$Ys4 +z+P#{`Wp^od9#j1xXzI+m7Y%s%SQp57z0oqboSKq{yuEJkor41dbry5Gp>Raw^87x| +zzuzicm_qdLHauA!x|&y!^Rz^}M|D +z$xGaPwN}JBde8+ckl)$UNge;GPMerpqQd4Tz~Mag?j*NMT$dZKn;k*VE8G4lEX(>vFPhyO1(SaZ9U$JsT8<_>}M +zeB&Zsn*}{BlHdM2#e>6T>E%~jR^Tzl_UIO$cp3QA+AX>1_@hrw=o$ILgpZkSQ(2!k +z!HxIvK$FN$^f+8{6}%vgaz{uzC@Mo!At@*3cSwLoTLk^>HxC=k;NTg2q) +z!RljfeXITLvEZKsaE?By77+Z)7?22a|#qyQ+K*(y;aDJp11qQZ~m#j{AE$n@#%hYISNCl +z|GZS=^UCbHC=$dfvN%UAhuWbN0ys#-kZ +zAybp=>BtJBLHtdX}1t73AF=MmZ;xU7fOaUcej_E15 +z3k`(o7Fjl8GqbdSKx_@J)V5l3VZps8iq8SdjoWj=y~ie+jKZNJWoyI&eW=;s@7QbV +zBf;`vtMfd~?jp;7>suTxfRcudH;xis0FD01O2>Kw180BRfq~a_4ZDn^=2&`#@`6JK +zTp^Q1B^{y;oE1N~Q24Ic;&BO1YJ1wkw&by>GyhP@CvJ(_^{hHrrhEJneez$-uR*Tj +zvu$iifB*6C&}jute#Rpyt}Y7&c#G~|NP)bD%UgzItIZ?RzQ-VX8a%+t>!){r?>X=y +z_yRNc`<#HOPIS!T%XK6Twkdd5Op9xbMM1q41MTbij|;MTm`BKsTnBk!bo+ +z9Njl6NkEsS+-9Cns#`qt9vM}nsHNl7b4i1#~`Ea9-i0ktN_?9^CB(K=d5 +zI95A*2;R59-_PrR?-F#negtrtx{UluZ$rOem3QYpXKbt5FyTpen@Pm?Cpm_@Vyt=B +zNG-L7O@#>Mn4S~Nn`*EQm@D*o7jUHi@QFBkz)aP}%|&%+U_SYN$YZ`SeR$(P&PK~Q +zaqxNa{7yVM{wc}#y<+9BLeuNO6i~DBP-TY_wuv6+P5|TB>X&K*NJSqsI_a&HwY8{k +z9$3(%j(nXIX=7Z}I5Ir+yLtPzXf3(_3+sF0`+zfmjCSe +zpJV-p{y)qA+5X>^|7Xwto#p>r|3AF^Z=vS?&rtt=BEZ?$n7FzBUraL>J3BMS|AuMy +z^)gZuZ++%=bD+#cAkIZ1iYDH63dr)`P-Cu +z3b*@h`yCjVT$duMhjyq$TntWn8o_zaMqmW)oXvPhH?sKIBWco{2D|cF&)+856FI~B +zYEESv@Qtoo-!Hw*#VcAQk6Bn&Zo@c9uA*V(?ctGIPt$-@50f_;q<0=RBqeEXlqE(paiALzt`a(k!3>dL{Yn +zymvUiCnh0{`&FkAMNT1Og%0UI0k(19^JX%og(%?42A{imIgvHkqsPtp%r2VQ~B&!nkjn=ZjS>3d;#E49LlOZOh +zF1bG4nH1MgqUn?p86pWZ8?r{(+A& +z1za=Q)nwkE!jcEIXm5j!Ytr?se2Vu|y!Zhs``@X)u{bR#us3@EAZlF0jD)PYE2Afh +zS3#ZMDfC-LGI!#eDTm7`t3agJj<6fnB-a#x`h1*OJ!r_f<&OUNo0!uDbVEBjFJRnC3zf6}ukIC33aN#B|X%Kk1Rs)Dpm +zjY!268;;V7GZUL*tweS6Wa_8@u63rjpw0<)lI>VwCNa)LBg +zPl$Qk2;>{kyhR7nxr$DVF>?2%bSLR-O*9pBHCg>Q>Mn-w`-P)hsNF?O+s9YscMqIg +zqMZ$`X#~1}0`+Upx+=dNt+uSPg7v8vKVy7P)1&Q2Pd5wom`0#jfu@kz<90bizRod( +zMidB(9yVnf1*0BI4D?}aM+7~PhZzVx>*35P#o=1c#BDhf^){1Ukn(1^KkvYG6m-R? +z*vP|Stg%i^FW;H3BejNnvqr}wYJSeDW_6=2l>^(;@Dc*B^cAU3#p8r@qK(zea!M|! +zuwD6O#7x9?l<7vORF=4+DsUAT^lP@otUM@VJkZVBpuE|kjlp*sg<#7$M+(1e>YK^p +zO+Qvm^GL0b)`cOgKAk!<56&=_I$>K%_`N_djAhX>}kf|`Xa?h +z-*NuG`xb_PB>bX~R-_tU*v=k{g7v)tqOb2M{v5=0%6GU?AM~323waJ6nKr7eYa0ZH +z@#yPODVAakb$cjrC+V-|Jhb%{FQooIK9B`LcV-Fi-}&&KnpwhAVXAu6?$(uG!Y>k_22k%TThyqvrMPog}b<_ltwCYQl +z4MCP)W=!2z2-&||u;hISfh0k4)y(+`(i^%vFqVJxNktg#=GYqc^%Af*u(n!(8b<}% +zwIxy~EP^QXknKtNts1L}4Lj`jaH#o$SmW|o_Imu5?8qOVSZzkc-A|jna(hsgt0>T$ +zP~6aKC(;Kf?2%M!M}OBp&OXyYUvcS?aR}6ye7<4Ucr_BRVNhK3eH1|T0b0DF)&!G- +zL{n9B0E1+#xybH`T}i=lZlTDWxIe&9SBwQu@vHyPkEQlh7rT8xT@vU)kr;Lpz+*1dP_{<$lCJcH59~nNvR?mnGq4Td8c%*n!IXwusLEzzv>k6)T +zg&7w`>j~TL{}$*M)KM3Grd6iR~^zekfM2UPvW9p}C`)dLnhX +z6ZZX)uMcJvalu`W%tano{t1ExQeSz?gd9LKYR!gZKvnugR5ZZixU_&Yys5v=t +z_}gkZI(rALMeb$sq8PqAftinI*P-`{Z;)o1;P)YduW$&(0~SUf;urS|U%$W;qa5y$ +zJU-0ABiJtWWLqc(+fJBJq^sofA$`1uf@*& +zl<{ta_gT~ZR?+>kF4S4_eH}b0e%I#B{Z&zXewpV(1B>k2ycz_yH7z3G*fRu(_4+dx`zNV+es_4P_mSHeg8_HSCGBXThFmiYGp(%)#l0^iiQ+u*@M +z2h%;jQ=>C+4-xxH6YV05uLik_(vy1CI?=Y}_ITG}`!_W&4_+e(UJ`Y0cZSPah4MCW +zFZcI7-fj3vnon~~ckO_bq`dolG(RW@GeXyEdzq2kW0%VQ*g?2PBR-4ERiOk3KjRZ; +zohri9XKwRZf81M29T5Gyl~gZ`7$NU$%uRy2*meIvNSbvA$d4UA`mu|}9hv+pO@8`MHSqUI@880UxeC-k#0i*DWV~l#pWhF^ysxsK +zVe-ZW3)l_kiVSbSj*P{PLiQAm)s@@@{=J)~pf~}H#qV>FU;65?SN3ujD#c@{a +zE|R-X?g5;9s)p=mFXSNmm+apWH^Jjd!LIPLY)PQ4x!4(2%t-F)F|dOcwO=EYoG>o< +zDh2!zZXgZtP2S`Fz~kV@w4w9~Meqb(f^|d+eGG5wF}&B}Z4KUuzrigf4J6n2FTBWS +zE&MjjYsYHkP5&qSbDqcs*v<2|+6!5FDAIyR>*MFPpBYGwgjV?3{~1Et&l1}57G*0_ +zTP;!B&lxUe|K|=DfBw*xtj5qK^Wl-mY##vd%itK4YIco7xf?b3rlKV;2$`Um6oYOF%J3 +zpd7mzBgVqjT&vohsP5(Ser=AwHkaShcN>zsPTt+aut)nq4$#XsZ3`dGQa*n&EO3O9 +zuKaLRer|v~Z%(TO_Jd?t4w5zD(ZISTw;7MWO_xZ9Rd^7(>VM>CiixmqS@fCwOaS-U +zhp}&t!yfO1CGLm*5AxrABrWVvJ`Q`Dg&Tq_6)D>L+L2n?5BHA*XrlZSLDDMP#*BS* +z2v$m-UN?hlp=}P1SJHo+ZUH?`6ELDkoI>)%I)z#uvTchQL4v?oRCp=YboiGE|nG(p6_5#n6g3D*tv%wg9X}htV0ZML@9^z +zvLvm6);7YHUC(RiBisc)QMZbN(1i~$&i~XcqU~MX=T}~Q|Ncd<-tVbj6#DPu7vIZ& +z;#vDW@r!R8gmZ5fP@d>(ao!a}+fUI*j)Kog@H3A?`zBBy;1aB8XzQossY(~?pi31f +zKM8BH1Z$9qwgc7YkMds?RzN%Yawu-Wy?8oEgQqZB^yGPtlvI(R_`D^0=g5y +zg*;Me&k*i_+xi*4R?(%LD>aM1goYhd{zD?PF9T~T&&8!U6)v(eXvs_MymYZ;V-u)t +zy7bsz!0zY{TOO*;BI!XCA`C@L+VEOMJJct3e%mh3VVvAN(Mz<4_F#RncQJRlSLdSq +z9QYOc5)0e?b^iQ*aQ$N6Hp&$yvy~3g}n1X@u +zOMoH3bJU(ffT0Sl)E*c{q3}Aw6?P!2@<76X9f3b$ABF=vQwLxqMHv60DCz`^Rv1H_ +zftLXPi9H($>_Sn%IE6NfG5!JDD6uPD0(4NU@dLaki3ti5sS7ZP;*2x!btHBpJFq+O +zG+)F!cov +z0e(qCDGNA^`T+}oCuumjfFl%+qyfNDlx=(g9g{eQ+`zGv0~`nZJM?lOaJ<3^lyCeE +z8axBfmbWMhKhi5fFHx|6a%lL$-pY$ +zG3<*ez5iw*o)Jt?Vk`?KB&B2k--`p{s$*6|SIbfOpay<9%4mYk@22 +zI^Zg*0^(L^yodce7kH1tdug8WE^NYl;Qb08pasA+bc1mOC$7YY=tkgLh3jas@eciw +zmH^i)+(1i>!?clZ0{%(i!*nz75xT{A8#h*okI^51k1KqFmKkr+lXNTaDY^~#G~I5z +z2^(_<@EL`hs0R2f@D18b%YhzR0jyJ4Pj?xIa89lSZdLdktukJx=M`?F)xZY28`uau +z2%CBja0lII$j?w8Fb=>zt^w|%2Z6g4Hqk@IYp{9}|4eIvdubhTAN|qTPcPDX;7hat +z_%iTSdWALuUsbrD{serD9yVT~0}2n)qrlhcG2kKK%k&044t!JLTl9qS61`1N0uL*E +zhn@l+p<3fbSZ|5%(KEpJ6@EaQ;L(0a&jLSE_!ru2?4`d_J@6=P0Uo2Rz>n!UrPk%OEpwkM^&|csVv=8_X;73RQ$Hof3?oBnTY +z`nA8?^xysTe{0jX|F^Q~q&};Ye2MRyx%<4|$mRW{Lt6;e(}q|8tZO1HW+v=ef7l=S +zeYDB22h*^Z7hzv*q)plq`Mp|{PK1?Bf%WSTyH)_J<1JT;o!(l``1IdWxlw*@<4?XR +z{EH6<(D^SM3n9ORyDm3cM~m)P<>gXUM(FWt|Pa?lA1zwmS9AK5%Y9* +z%&Ftf16V~w=lrZXLFNz)$`kF#%lAY%^5h6ST0(y5bkFE9MfrI#c6)JZiidN{9c3PJ +z4D^ILRT0Wn-FO0WJ%Oql+ZA#)wA@yg(p0me!AfN%&UVus(@Uomd9>1E*+-ZY{pNW( +zFFYQ3{uPaf=N8@8HaAAA$&b9kCSPl6ZnJqdjwx!JYnNDDj5bhLBn&F48HBD^K!^q7 +zZ0JoaD=zZzGIVK^Gm*3M&ac9eFH=gcw0VLY109t$SC(LDqH8=f_6B=>bhNt>M}2g@ +zt){TZVfSRmIEqX2E~$&4nz1)*iE`VbF3d?ysk4T81zXoX)E8+N(l%1jnx|r_xQrEy +zZIvv`5jloJAw0Hn8%9#(z??EARAf?3c_xbCDQ492Ovj2`;R(tusj+6sbXnhHO0YU? +zHD?GK;5hZ=g(;=Jlz;^58In<{C#|Z6e1F{Ibb7jXmnssNi#5d<2dMXq)Rg%R;tIzc +zs|^9fN24Lz(&DT%h~I9P3%tC+O=WoTRF5h0zT2oQrk>ns&SH-!kvUENoQ~sVPPIR$ +zwR(vIn!HtQ^Nt>KV(VY1wNr=u$}A6e`Zw7X-u!}bj)F0hifs8cB|g~}6khP=&ChJj +z^Tj+Ja*MPW;fskFP31xJ3A*$Yoa;e&EP{|ou&bo +z`cgEC17?F|>PnTrQQJWta1;0quuR#Gl``1G%H +zqO~n#fQ7bNTaJrjoHo@LPV*@!ON^ew= +z%Umk5)}OL=3sT~8qO^4w)jEu79Y(bdqxu@iXmu^p*CKr_($}i=wZy6^dpBQGzR0@z +z&`!P-L~<-zu{HsB&p55f7f#eB)ThVo&MDExqv_2GH)@5zl?taR9Hnrn%3Z4B*Qoe4 +zDxR(4*}k~Mv^E&0FjS&8RvU-=a-23s8>Yh1T0ZX8aoQ-n%W$MNRD~n7!73b%^hksS +zC>M@!n5Monqz%P;9>O7bm*HS-P<>up&zw1UpN2ev{$zR{#*l|G!jT|>=nj4f28lVk8PJfi`4|HoTHAfdpxzLjfvT~ti +z7na9`<#AD<<^tNZ4C)DXgGYl)z$Ublf_fNia==dg>hoJ{GOK9 +zMJ%uH66ekd5?g6BxCA^0TrIZNo5DkLB2Z42O#_btPXjLnZvbxwn>$GkVQ#aZG)-dF57;-mE)&CX;7Eqle+6_Jg +zJ_?osPl7O#AdDnTFbVaORH*<}?rX3C)}Ta5X#c`8CRIBQoYtllnVO80WV|J#PBO|S +zBlRedRSlUx8oUy`+n3i>DRWn)oL$jYSBy3dn5|-=z&NdIy$A|zfP6VCH0LtNeH0j( +z;!a5OPRQ*}sUbpc;xy!B`%0_?Zw8yRMo>3U5-1te6=Vn5Kv+So3s!FxXeH<_(4C+a +zpygPNh|SL3PBAUxnvA6xD>F7^Y|hx75x7H?f=Wb*+d`c>;Uo+XGe_rGg-%l_gnv}H +zN#S)0-3mLqqo;%%pAz!Ql#mCfgxohJq-aXW$SEO%ri7$T32ERmcV}nFht7~y&X5Vt +zkUq|k3};AhXGk|^NKP0R^F#`vT?z*(Ojp=dVJuIq522u)JellfXgnuvwciwX!rq{B +zecUbf1~Y=2y>FAfK|h)Jd|Xfa%(xV9N}@N2x4)pH1sc!KP#`QTIm=x#;j0=n~hnubD_U3kGi`i@rFzaSvCUZoCam?+Mx3Gu+s|*5kiMongv~sJ>dmZP&hEsbD6WCA +z$#fQYf<{j+s$;&Z7;heNJC3Zvq6Ri((y|!ozBUqb%Cb9Sd|`31tW#8{^PP7VQ>Xda +zk=fw`!uk%%`xz+lq4WF`>1_Lgk;HoLFBn(kc{;Y(lP)7hY;gf3C%xT9ktzD*=QWDU +zWKdkxXsH&N`D10er8=+pd^xfqJ+G1MGEn8nCd-lSqHkx5M|`)4#FDb|N*R_`H1H8eMV=?u +zk!PzLw(zIaN1@@2;+U>CZG) +zDjVxA`x?CIXR|~uY +zKxuP7d*qUs?K<(36bx6r9j<*LV40PglbR#5u*+mtdwC=DWkoLOXOG#=Px`W~NDgxh +zq{#d$^6*zx<%|5rzpARLxl^mAR>@HPRn46Tmdhl+tUi}8gPeBie2arMmbQ60c!jdj +zT2)o?TvBUVHIHO#b0wT_yfrotEpt^{C7`N{AE_Bm@-mvMn#U+53(oVYO_lsf6Ph78 +zNM9>N`sd)gDF$H|tqdnN8ApBmiTuU5%x`Hn4Dl`s7y8)y6oT$kSjZ#1Ax)>l>bv0& +zAgwpQPEV1WLXm!$G$t-07u`eG(>pZY_!g;ldW62F6zWTrMvM9`U<)s%N7(!8+)R2~ +zejiS_G^c(N#<4s1)N1)=N<}M$bU$^bLuj$PVZr+r5i4A%RYo +z=wWt=Bl@#+fKG8&omy@&mK$r0b=00tYq8CHjb6rV)EZAEG>>k?2&!p49pqxsU+gyS +zP`|;hK1T%+nGFS84eAq)6Bbb@#%r4>hWe{t +zPOpZ{)ZzHSQEU^v$E +zAbo-Pb>|e$=C_1Xq-dTO$G3p!W7TQ5Cq3%I? +zoj#*~KuQ{0I2^LDv4h9*IG%@5Y~ruES#-ksWs0jry*R8nwS)RZ{n_TNEgf6xTfS~F +zj9SBE>@^Ok_3eXxa!A{5!}(;~EraJ`pYKGG~IN+X{~9W +z=@ru#0oH)YJ{xh~g5c2(h&}oM?JC-c+kvKiA>I-$UM$Y?6C#%Ppto4uw?>Ox(GR}S +z4ruvoiU?dAU=Og12(kv2$Tq}-B2}BHCu;3zuKd-Am?Ul$CGgW7-NaOniv6tLPrygE{V?tHcg| +z80(UW{dgUZ=5<;xTEf>t8hz=BD5xxOak{f?57g!^)PXUZxmP26}(3KJ3l6JXcSdwRbmj|-*QIJ +z(RxE-+hI*|1NxfD&-b#1VL-c2yCXeFWN`f4RLz+`yd#=D4(Ua0C1G5_-|K);)B5yQJ +zfITgNm7GCW)3va?f23!q4kuIrS&+3HA*#)MuLHKY;|&pt^v-25z@iFqw22(Z~{D +zLgaZ(6VX9|GVOV$DD$XAk>XwgOR$I8XX+sps7P}5AJAQbes}XETXeKdJRTX`wMP$! +z<(#>{GsV@vd#X#`k1XN|ZIAwz`YmKhU3*i5xYcc8OOX5@cP#G)Z5NMHu-N5pXA9dM +zb|~y<*wWe47elbslbN^>>XfUXH#w +zxDN(prZ6yJ8j$XauDJTM&Iq}?64|4R?x(BpIL$w~0ladk}IC^WB +z6nAL+4ql1XV$J04oJp4K6fL-WMs%)ya=SWLNZ+16(z%H3}1r~>v`$80{YUu^HFPub!&yT4%}(1u@WgWcY@%4s#V-wGuv$H3Df)-%Cspbh?M`?k8R_mK_#ueXMe9Rd? +zd1ColYa-`QX*%O(uTN40m)98&1;112U0GYXWV2a0za;u5h}NkLBd+!&0N}8SmCy@=*lT5|nDVPm +z9U{WwurFZO!)`z%)tFM(U0A?j!5nju&h$cg$+N2-)kZ>u49sZ75Y&pI;Ir +zwDc=i`_Cn{;o5^Smx5ROJUn{MT6pvec(vGrYn$~pCI7#Ky}>;RI+uxAK$FAkp}kQdmr1b>E0qNK +zd?K0fCXuSLep!=lWI85GEYIy(qHOOxC6|4TU$*{ +zkUr5y74%mjUyq@Da>RkGBNmhz(NssW;bnf*DPz-yyy)O$K2ZB)9jEY;Z{0edPf+-E +zwcQFYvrf^n5{AQpK)CkaY@5Qf5AqNX!w)Q&uBP;+0 +zv>Nj7z^h;z*n?@uW(xib{T95++QW8ae+>Q{IKbIZt%uX?L)$@dmuXH>*jOTlnSAZ7 +zpsvI%urTy?OI&fdNZD%;*(nh%#aS<4xWH4`Qmsg#&Uk>Nwe8#vP@GDBkuO@N!~^%D +zr59X)*Yxu6`Gf=_rN{&rBCnh?lAKyWme@^Qh +zcN}@*|Nf5QlPn)u&&E!DwlR)jB&aZ!PSC|ng2ym(neQ>@!3&t>^m67Fcq_9Ou46WX +z&G1?HJo6^p0Y7B+!TpTi$w21-d~TD)IRVUN2H<+UsJZmxMGLgN#Sg$O4?l*bvbQ>f +zV{Ah%{naWwD46y}irhAIG9Tm>2l}Pc>){n^;y<&J3hVM&@AG>U)`^|?@Az}?v=X*b +zgb!{IkRv`g{3);u?_Hm#)4dGtHx2Ivso{SE2|sLFEaR%y$p0V +z9o)UEvCHaQp;6Y2a7X?8vfbLmy}QYD&jH +z}_}^g)<`Z;k@U^|5{swvSsIG^KYAcc|o1X`f+c{j|eM`7igxm3VF2Q;(kihn|>{ +zfYGOjw{6GpawoMPXO4&03v_T`c)!8&Hb65$BRE}{9;6s{5Um3)c)P)HE*Hx^!O)1z +zSn-SityTn|pc_Y1>_X5xh~C1y;mk*Xm7!e<@@_$wVQl6{e=r>2OrD2lVm!$`juwLu +zxEubVZb1Y$c5_3!I1_GFcI`65BshpDKHK~Bm_ex-R81}O(YilJO@D5U^45_=)q$>u +z5ds5-7Lpc5YP-D*t2k(d+W*DLB-zV?=%<=zl4$3q30`~vOX4l;OIa9s*oOLM%z7l~ +z%vvc7tp?!SO%9j0CuYS_q%u^G#lc6hPyNlv1ru#Yvln@;OkLS@W%{0`d(vB68#9bs +za7blWXNF40Gg{W0(wgEJcMwZ)e*;$zC^FgsF`m&uaL7CpsGwz@LtICAV)caZ22f(1#%$ +zH?$o?@`e~eU5wZ}L*axVOUa1ti^>KNbQJ{R){9=(NUPr*nOYk0k-CyB;<*=nHn4DKf%S8o +z_x1;Gc;>XtRV|<>NB7@&+a)L6kmGnKFQ0VbZL3~79X-&t>GYp{aB?#za5B5(k;PN4 +z{}%BjxMJ=p*LSyh89&$5bK;XfnQ;rwO>Yu^!YEG#n8zD#oX;aji(1uiNWx;>u~}80 +zkXWBE08cdpkLL+rBpN*vSuonPplCRP1^gXkO(g>wxj_93XmD9Y!;+3HoSj>JKA^iRd~uD=^|yPfvN0$ituwy64i%FORq}6`4#z2z5hk +zemMNMP0#HwCp)5&pa|DKfA4hM%TIYCPRXO`%Vu=Fqkz7Vriv-$>&cGq3Ts#K7?DhJ!>8{O$zp9>DKhN>LQ; +zrM$FG>2yXMCr%OPif4%zidTtOB({i~67M+Q5&q#8ozP0#BQ{-O6Om+ee&mekh0zO} +zmJ}B^Z-{Nlyy<%1vBM?Ip)u&;cp)Ns!#+(?{R$_$V<6#nC7rqhHWyJLhqFl9p3PYO +zHjg_|!alNgQ@+PyVS)qjZ-x}^@mfE*7+f$}l5X0cQO(aL+TECfa +zOte%_Jy|$vDyF62v_ovAVLR~{@Od$O8Z{lb@VK?}uiW~?y=On(-dAZ}{l+CTI%SD> +z3+bNU*Pc}LUoKj_YW4in=5!-*$vN+?x#jaKuYT~=yRKTWYJQAW1i!;ud-#LsA2;9e +z&^4F;>RTPyD_D86=>wNO%vea`w&Bo~K{lHOJ;Au#?lXPB>+=C01`{s7)8_&f +z4x%%i4xZ&46z6gdVo!wVzKwoHkv={IK5w6D0-uT*cyQb?iz}uxVJ=uNuN;=QVL4hC +zL>YJBNI>r=5P +zfk8sH$)Mvs>9kGl5v|1@n>#)L|739Kw8ZH>miGcZ6=|A;qyf0gaJEKzxc72BjM8!# +z?Z76wmsIIUDB58fDzQ`3G@J9KV3_w&v?fFh5c1+URIp>t&}_wNG|c0O6!hUHPZteP +z!USWKOpwI-WhMctu-Xs$`^bTV?C{PFm<`|$vU39_3FK-tV~${z@yIIU9wa>|n{!@Q +z#V6z2ePqr@=6qys3^ka2Fn^mBvedyksomDmROnsdH?-+eePnjG44I_A(pP%;>Hz2v0V1Dmh~O4wE?C~a~& +z6(uxEs=KFhb#zInH5@~&#jhjUqmAYC=^f*bBhR6g2iZ4*ox>RmFjpaiSqA@;4VREMx~@z+mwD*ne@qm8bzI8E$8r=T%mM(mM*UHC72K5F5x| +z63K9q--WyNn%0=*S)vDB2+c@#PMh9=o8wQ0bnWjxg_k3?LzendtvM!WJ{S2SXfPkH +zpcYtMro=kd+Y@jA?KgtH1nX1+Dm6`j_=gpWLPf9$N~lqouVUCi>Z(PIK#1H%xJw<3 +zjTup;115X1+(g<#`sfjo%gD3#nqL(C|Lz>IRU(7huBS63iq +za2Rv{STGRCWinbY;0*=?0?%tGk5OMf5sy0<8bB?}7QzKoC@@Msrw2qmprF7YoQ2uV +z1jC!rg9gh~01w$OgKz@iho9QOJ1Q95KV@+EUY3V|pT>W} +z5Azg{@7++GxKJKw5YK+>hJ+;5yF(@eC0LL|l&ZOHf`jrhs|f^`73A!)AC4_{SNn^Y +zosO-3|Mx@l-F6)K$+KP_vm6E`VFSQN;bAXWEOCqF;-R5Wb|3lhdxMaV{ckhL_ +z^_tVq63Dsw#+~8!;Ii7wBT&=w5iyxBes>UhE<RUY%H(q)+7Lb4wkIxyAfq +zVX +zCPj`(o)@_?vZDFs$lA!J2%V!bS;zvQN{F^*Aynz+h{qCd^0Y)!YFd|4I<2W%sij4t +zkwnLntSjs)x+<<|u6eFSF1u?0UT&oGNx*YFV)^U&r}(Y>HhvFp;{$D}CQKJd>3$DR +z?n>+A3+pyPT(rNjdsa1R0?Ex-UncnF>U^zHpcqRF%(SB=a)Q_46!mN}oytS;k%3FKV#@VnHp)PtZCylY&L_rfBmfN8*Dm3-1n|9tPar3Hn> +z-X+pvd86Oa5o&LqEKP2o>z`Xb%m3Z-6`@;;j@A+z3C19>&>qR((GrPkEarWJGrln^ +zBs-i}Q(7|HVWCi#@#yraQC$y=3+iksTq>3-C90%!EjvUBQ_23*)S)3FezUSzm%hKN +zzOC3`%v~nu08@VB{MMA;B#xhhvvUYz5#9?3;82G@-Xux>kSsN__-vBIv8RvJFB)(% +zWkN>s4^IJ{To3Ng5Oi6vl*?@bp0T`LkG8xYS!bSm(`hpe{fJZuavK*uFrD`aQuc(G +z7tB57=u?)rT=BuOtyFkCQOSqlfE=9BJ3AZBA2)B(tQ#Mz{o|B*K8g1iPp-y;M?dh> +zlODJPk|XuxyT_>Wu7Rfk#9@fpeSSL%_^kgd8 +zluRcnn<#h%WQ!&k%E~|x9p0F^K$?CeA$24f6(H%fgcg7QX +zpp3b>27ohwoODcQL-3Q(a0rEZEjnP}bY?ZPmD$GZVXRD9*9#!eTg7|p?Z;n{NU(?8U1I~*SimP8WGJL +zX0szN9GoWwSjdkQ0r`Vfj}a~LBjjZCp2iG35nV~de&95sk$y9VS(cEQp?jdo(6JU| +zRIY{1JXYH{nyqT@l9`ulQ|6hk>?Z9ztff_0OXp%OwSj*cr<`hqEaS>@oXSLlS~(U| +zgRObCIoynzvu$l^9;cCZl12o@m*sg?(Q_cprBOPYOsct9TvysKSJeSfuvQoaF?3rp +zpVUE)%T3Q&azx&_L?RBL&c$>Pj0Dm2;OgL36NgxXC-4yt0`5}odTtL#aY}jLqr{I6 +zrW7oEuAvW7W+IetsC!fwhf5zEs)g!TC;?UvuYfmH(DBVWxT9VguLVbRz&bU{okZ|M +zKOC!sF?hl4_-Ykk9bAet#}znpbVJ?fye4v61QodoH;uC#J1>8!eDChl?GlX%QF +z=whh2Kd!q{aXrzVu(gA(>p@o+P}|Ez60lm?7TD5WXlW@H)UtyPr?|WbHNTA0Q@%YD +zRyj*F*sZr0_4e*{OXAd=U-Pn@76!=i!{LwtYR7ZMYm+f8vP#jszunV`rz*jmvFcA>*5CK$s$#! +z3Ql*n!4Luw6Zvy0RI^c4jYQQzuEm@JMOaL?7K<&dYOebTGR3i#a0OMeeU-`)eQI}| +zM>uWS292nb2&a^8aENTu{5@aoilWgAMe0~qE$<@X^B1~6mDD9_fQ{N+4pWA>Ki~?jNn8;i$-~^85!t$ +zWSNGxBE+J3Xc4lY$IupVBsp3S%$-{7xdi-SH_mpOoR@fPH(?4UCgjXxF?EP|xT$>Q +z=<5gH^sd8yhZzCPf +z=ruE3*ZyLBg +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 +zk7{p`{~09$8*n6bfoa_vUGro1fgfs3UawpZ% +zC$QY}pab6hD2NU}Z5$VgPRM%w@`SnN@05N}ve>iZN|Q@-0<%izM$XM$P`-8S@Luw@tsAqhvJ}PKn_)js<_&b|b| +zi7H*UPF2>*R;kpI%377BlJu5dlBOX|r=X$TZA2MBi6Gzt>NL2F<8lYM?xKPsDz1I6 +zGA4bq5;qo_DI)65fRlyL_1B07#J`p|L2PQPGvl5f|DJeI{8lvk(U0_an-S=3dbO4s +zoAY^HMvefZoQ?HSsxE^vPHvl|wzg*6@pju%L*3FuCa$zo2FUmdPCSi@&kS{i$dIpt +zi)#&PRMp0Hr52@@r5;bMPZ?9v#7AEQ;R+oqcZHmaPC>UU!Rrw)kHA#kEz +z@`msu02gbF$TaErjSz{_7$xvh8OoC>LBMqkQ$ig?#8E4BUCN5U_{2?1pR7B5)6lpm;2&npc=x#thPD7&oj-<9^68dk7c@?83cCZr#2x1^ +z-*tOEI`tXKOU-!TvCGC^9O8Y^lTW_+rdN<5)LV +z8KpZ&i!qDh=N?IDhJKV3WufUuLN=0mLDvfm;|{@(fV-N^1k!<7fxdvj703rV12Y2) +zAUCZK>>*)3^Tb!$)PSjWn2m-xj{v|FFr#dUfB4XLyotl6c-L1z9~H;v{N8ZHlO^ttWz2 +zZd#9_rmPMJZ4J8hsK-faQz_a}4<%DnO{KglORKD#3_?pHqJ#kGf@?#%h)!ZADvoKC +zd?Aaa(>l}IWnE-lW;I%+h6>BGfMeWQr-`S7q@B}a(@Yc3 +zFdQGW^FpKwO+f*_KqU#4QD>>URfDRgs#UeBIvA-YY&a9RL@9C*q|_zCtVe{!O<%+O1~>x&W-a0zupLKHL|ZYuWH5T-zl1 +zwH}Jnyu6nbM5D<7P3xqOGpVwjw8lt2rK?UPI9hRuC9cZQ&hGMc`MUyL!P|se#8-{4 +za-Rv-Sd8 +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 +z2^Afyi&awnv5iQ}`8E{FA=f!FQ}>ow)5cMfh` +zQYb)$>mMpfqX)hu4De+h*bBdFFI3;}maQ+KcQY}gzrfdq>sa9y{UsaWR&P^S@bG%C +zUTi$`LmjX5W@5vSD|GcpCjIQv%f`)CTCN;(Uh_$~KKJ1>o9Zqa*MWCC8)|FDw&UrK +zF`^XjQnROAIkBT-V(#>F`#0nMyboySOuVrFUA%u!`_y1+u6{6NjzcQH3{v@2NaZcy +zR&CUKruQu54$}?``GjSoX`_W&XkKh4=a}bO=K86J{i{vn_2C|{iKGJI`C*a(29gX} +zSlt_U@nN3iJ1~$V!j81+bd}^pjbb}WT1mI+7$VNZ$q}ZVBio^yc8$3f6L=BqCuHc; +zdxDC=46Qttb<RCJ7i +zH+9h^7|zLwFAjVRHSWhf +zj*vSvR +z-Te`If%UHz4+Hmh)CBnOZyx*WzDFO~zYoQZq34Xa7xkv9)$$FrYjgs>vbAS{DP+Mh +z7r-?!UFx_BTwirXo$YngtMmuv53G9=A2b{^eL`C#s)oAWd?&SvT1%OP0A^V!9h9U% +zFe2z$%Es;-rjo`*(j{#K9I3P`#|LtdQk`kVMyC|8!eA!CxwuJHToz#QHPsMKIphlJ +z*<(XcYOD-DW7Do2d_L5QUFhR^&_50GtPBt(?ez%aS&Jc_4jG_TZy5N?^NHxNf@0Lg +zM&~jV-#}sH6SCB>X!2=mufE~`Tv_aY`J+4aOjK7zQ2Eh!A6&I(&#DLZP_tK^H{+_l +zD>fGgwiHb|;t<*uIcyNkyQgpW@_Tmop?DlzyJz9rMTs;x9d*h2Zlh~-3K3t6YxFwe +zDgU}SHJO;{n@jxMH($AuxWV^}x*LhRe7DrCQXi>#pzaxUZOyOi+)qZq!>Kj$niQq` +z56;R!h%TFL{LYeC*2VB-B!n;NmQdffViH9C4&Fg7AUvi1!eOT`h@;sPAhTKe%z#eP7& +zvVZBG2Or#nUgX=W&AoHA6#y-w>)o{4L?Bh@x1haX;T +zG&_KY;G7H{i|2@H6P;(EGK9Vua>@L(%Y4{OntindC&ygTNl`t7bvSB@N;Um=dn+1~ +zpn^QT9uN1q#jTslEz^N}^uG$O{z)YWSI%8pxy>HVDX@XE1y$m@VTJoA3PF}|L!@E`E2};o+Fv> +z$Fnw%Nieoq$A>+x3}D$Tg`3c=(}^9!{k|( +z>Qq#1(8jiAd|sE+%-cs3na294p|08Gv{N)exux9Lv5H%1r+Yzm6D1>{1GrxcsLhH( +zE1e+(wWdP8j)rrhxfHKxNJ|P(A8OOPQXnNwY&TOTl~!!$msk$NXn-CW2Gyu> +z+aU59t#M%pc0IZRcwOq-!0K%&TSkp%9m}=r1i2z$m_fpT3b0(=|{Y+#g6)c!|(HxPtu#|*XVcY +z1GMoM&Rd)-oxgUzY5SwiBwA2M+I55hT%qw6gTZWx0EV;jZWrTbIiqAx^@1lfcPJN& +znR5UTCc7fpxZ4c9;2Djpsj*mPRe6&LFabHRAh11PgciUjJ+;WuLr)>ViH0NPwjZb< +zQ%@Bh)5}QDF!=nm&E~U)3EFQD6MBXLCu|F#%;9csWRgbB4$n9UJT&)lZEvyV>V;F@ +z9K|^puS5RF!WHW<^!Z`57}RXU-2HzzWp>(sYILq%u*^bp`hbh)b6!Ij>Qx?k^q8>la(Bi +zpha&k916KC)*Rz9aSCOVWr7d|&FsqNUvY|m(^ie +z+-fw?kg%191(I2h!DNhk4DK+&nmGN=>ul&LvEj=E57|$E#t=L3aVckpArOg*+mF{~ +z)X-rW0ddRPo!4t;>ye;K&ivgPybNDqH{$w7+NWJjhVWwCHF^F^`mP>HMQe~l&qsu7 +z5Ct=}hBaUfyVgU=v}}`6qY9_&lA-6811;$~x3%aRzRX60wp%4}0dldffBO!LX;B1VGlG +zal%CjLiTW+$HRG8K+vTCr=Q8uRF1ZqqB*V?%-3ulGM9Ge-Rs?y`$aIH@Bpjk&{$B< +zcCp>;Zq~rQ4Aw)Mi36pC#D#{?L5x8^L{!uffZ%E19HfwAD!= +zA>KkgE36iK$*saB(L#_6xky+htQTGp_6bG7(oJq4`$)=Su<%}kmrs%@Ly}L3Eru5U +zWW&k)RKrwm8b3{%mb?gDYPf{ISiD%eIC;I{m;8gm{o=35HHN48ZgDfY&Cttl5VuHM +zl5Y!diGLRMh<_6fh}Aa1FI1D&LbZ6SbZc_0uuXW=_$K$E@EQ0_{GL22d@s6n6pfP^ +zgwf~-^mSUzf*2rTa!iX+htXblYk@~6}WV{0+%kA +zaOvB@e&}vr1*vI23PpnbTGT+C0|0f7fllNUUrzSq9HyLIk!6R&ZtC&^@9PpkiDZ>n +zA!+qlNlR8|BrTqRLofsf$p;6QJ0s<^SxJ!G2A;xz^rf08Od+*~(HRn5N22RUjd5ql +zUhtIWFv_!dz`xEJR&Y5Z3U$?I(Wa+mbOs+*>xb}b@D_do-op3eE&MRF)mTBy7&Sh- +z$hgc%BK$gOd>MR9q$)V(yFy`5cOOC+^#X#h!~gm*fW1%#uvZ^Bh)xpT;dLGPBdyE< +zwDWI6*pCVF7YYlHsrxwIWC_P!jyP;iS|p2s88T?V6^fan64VInWhF$tJV)Jj$=2RW +z)};nvn3t~XncKT;K8j8sL`H8Ckb(XKpn^j$BDwxA$cHMq^g<|a=R+=SC-2o(hTUP7 +zWLw-*-J~DISi+H6;BvN0>59&3e;vHe{GR>2@=o-f#@8~hwYw~Ymv}Hj9S@FRIgoSZprG{R*qoA+bH0XLV=k79=Bmc$+H=`lCYRI7@bg4nT_Qi-nCS&| +zo88C^6j?Oqaq4#-KET +zrhRmkDQ7zPA}|j=IHGI_A3$Jqi5ZSaFCgeSf~8~lIVzAi_`FA~R6m367u`Rg$>qdWT+c6MzEy^?_PmO@Y)|PjNY;3*>wbnls?zm||Y;!}E +z+15TT#O47S+D8T4d4PuYQGN#Q!J!>J#Rs54p@VW;#s!B)PV%=g$nI`LhBn-?rEPof +zz>XeE9rxSX$g# +z+=dlc@vD%}>tT|&Y3f3&YYP!b7t<$&AofmVv+y8x}KG4?X>o#Y6`uta?`Z88y*dd +zj|~1h>WYS6+V?smKGJ!V*Be!~C7{@r7S#}1AiCm}mQO9=3fczBXybJUaY>+>gMWCZw8cu!_0Pi#(()yWgrsgoxL)0eb3 +za>tUEgA8|!M$S~}4p&>BcJ1P>Oisp(*45T0?aIt? +z^#W3~v}BDuB0rUeOv=sN%&WNl^Zd8p6@47bU*k=Nkj+o{s5O3V=d$i~!T&)!>Xi-Cl2Vf++s5;=@ONq7(?;ACe8VC- +z&VTOY{p@@E>aZ4uwb>onHk=pdVfu@<3&FXX?-;2y`XeIoF}x{(KFp7ZQn!dTXH@xjh18rhsquY4mqcq*ETai(5k&#i6ES4UK<`*lh2w^zF~S5o4nkXv*G!6$x?HGS#yiso;UV5zfz +zBu}^hX|AiwIF>7pv0@=Uuo3H3;}X^KV+$94d4azP&{b=zHU6q*SjX;K)7Kcp{&PRn +zd-0=2=SZ(T_oaQf8+`7nI{uBP!TPpZMf{R9ZBfHH(cAG?>PAame%Jl3M-Rgy`$}r} +zcu$HaFIBzY9tWb6C(R$@juvgC@3#D_afo|WPkfmy=WY3IK;?HNE15F(`Ca=QG7WqF +zeaQiTTE~voK1z;G){~QR&b+4mpy^3Fe%qSyvFKxz6bN8Ll9>Ea5~AA?YmGmD*)5y@ +zr+Am9erq?z{s>v{vAOOs>eY1qN`ZRGx9KYdIQyy}7}a~^xD)zy>ktu{oHVTa_5E^F +z;^R~Du9-SAF*!2a%DJYq_PN)S)wf~k6*ou`?!vN_b6ts6-gB@+#K*? +zjK<$?<;VHi?D~@27#P|Lk4#D$o_GDVx$P1X+U50|dQ(!8E27cRzP?&{uR#tG9_e-` +z=JqdbSi**mjblSMEP4^?KD}E* +zYiJFvp*6II*3cSSLu+Uat)VrvhSty;T0?7S4XvRyw1(Eu8ve6E{fmWq>sv{EYghf< +z!C286#dAv0Iz?&OL0ZtQTHhe;2$7MLs4WT72Bl~lf^-<|Xp(VKHmwfQ;gH!Cq$BlZ +z+6U@azWA@ZV^)yX$aK6Cq;(3D$w69Bmh2d$9U(H3TykiTHYiHo8l=Ohq)Em}iH>)J +zbU0+ngLI@;ASXk!<`AgMW&DC^2|C*NJ<|sB|H5<_^FLwQ$@F=q!-F=oY1@W2ZQIbM +zZ5!IOBSglwp-tO1v}xOhHf`I`rfnPAv~5F0M})NBRBa1u!?Y`eAEoH94opX@wuJ?l +zjs@)wyNc&yhtrut+xb0yUD#sSI%eRZ|t9j_#%!=3I+ZEog;{!LMKmKXR_2N(75W +zfHxlH>u4gU$`F@9dNOb+B$b9qNLMh|qM?YVAg*BfVn7}1E(L!A;##^BylNWvE!w5D +zRgmuR!K-C&vi+*0$!jm&`({sW*{&-? +zY@m8#_oa^OYn%^CzunhT_6^nZYMx`4?x}6*;ucmd3(kuRXNR(C9pol)N!8lP+?%o{ +zJxa0?5??t+&sjOy*}bfhzc|+YedEP^16xE +zh_Z=gwUf(A{nu7cs;wxiwT6~Wu_`87#a3NyacS9v;@Uf{>T#FVWmQyJb;!H9s-mu} +z)ViszxULL^t4agawN^E9YORv$NmX@FJ<&g+Z2Y9k;@U<%y+f+(J-MuQqSDvh->sX~ +zxuBw?wt8aqxVkQ*Lij;>h!4N1VC2B+DaEy=*5IM)CQU3ugV2F- +z)m3#?@kFbptad_0ood|JySb^?-8|$Pwbc2i;Frs1fb +zR97>p&MGaNTv1Y{WXj7bYcA*!7Qt$sg2iyQDmZ(!nt)m)9PAFHKja0vG2dSL)uiEN +zQY;fMir2*(fY-!ku`WcHlCEeC{r)O52i +z66M+k?P=`S)FN;V0xJks<>^ra;9W%@GEPv}p8Ual_({iOaB=pXB!g8ocD4f^jwk|qohMnX7+ +z6Lh%1E=xoR7wAY4L%MK_cyJO#0yv2x8FV|*4s?o00o`8o0NqmzfaLXJFgQcRJ)ozH +zAAmnY+zWc9I0gC(aTfGB2m0gC9O^e3gxb+LBGmrM5s96WaKt+jKqop-i=&+*1$28y +zC(vmQFX#*h_F9f?M>o(pjy%xa9X&wzbYS1*=ag7)Zjn!59R3uyGUU +zk;X{SHyeeZZ!xe3HY$ueNH^{@upcujjY`lHj0vEtjLD#<7*ilK)tCy--NsDN_ZhRm +zzu$NibiMH-@RvB>!H(_M&JRgAPneOUnNcQeZYG#$kJ;JG1l`r_20F*gCEd(3uLnKQ +zMBB_8%psr)Ozb4h;pTAAH<~ws9%0@DdZc*^=v!TbvGW_^Dj?l8)b#?q#S!#01reAo +z`$!bm7LTR4^0KkDlv7z;S4Dl1quo5BzeRCG@I2l2Ri=~%r9-7OwRFlJppklDIH?WI$V#gjqCj35-F@34IG@q8I_0jrk +zL$s0FXsuMMw5_7`fF2F;Y1EI{WuX;_qx#r!w0)k^qSx4RG5MsP$JX3&NQWWLxB2cd +z!FaD7$8BagM?z)7%!GvrYdB>j9!~r`$w*30@+bAP^OLtF?@vCF++gRo+t6-%y94b` +zrcg?pt*8A$J5HTx#~p5ENvD-(4YZ1^I%}@A!rEl*Vs2#Gmb5)-$I?!xyV9-ny!3(T +zqtk2BXQwYoUuU=4TdFYPxwba%0z1yAwBs(*>^O6SE$7=BjCZgnXubx-N;c>Ja{v7S +zb+zHui+J5~@`@FKRVtQDUV$PV22PxA%;U}!%QH9*b9WfEGe%$rTbR3}$YT^@2B%@3 +zwWV~-l2Mdp7GkbslNR1Te5E=gVO7l`@(loBhWU3R9swu>y$>VuO(z}YspAL8kN`GAFhS%77L6@b;jcpYFP;8o~4f_OUstAqbI;ys8@ +zLeCn&K)_G{t{J&Ft>=zGJPuF^SPys!uo>_sV29q$=kj;XdMYr^m*)2~Wcu@cnSokg +zKYwXpYG6i|(|^Wy*ncJ~*#|%;aqQG2RHp>e* +z?mwEfFVN4I3f&44gRmau6uAAp0eM+RAa@XQx1xMK>TyHH-Pj)g5VWT#Fx6k0wH7+J +zAV1qbfMFo`i;?aDTES4Hm$zu=9JF&~NP0d)E$DF!^L={(GyLlqX8YG=Z9=>TZCev; +zq7C@aaE*!~PF~@DA#I$2S$Ug0rC4vkrS4 +zVBf4b^zRtjbQpFIj!TyB0{f2&xU)tB>H?`*(~y2Dkj=2l|4snlcy$3Gyj +zIb_@}97i?w_W0j{df&vDk6;+-uLel%Y*S@#G7HK +z%|YLLGibZ7f=0REd~EX11O7dL{UQFlpP|`*_cQG9A7wZUc?FIBdjh_9BE(O>WS{&X +zO9y?H{kG-!A7h^wz&;6IyeR(!Xsju`Hh4Lo{kX}Woi+`BKE-h1y3*+9eUUzfH0Zzy +zr28ZNsmc#fR!-o{tf+u1FgI|PWqSb{*CWu`I?{vuMcGc34j9>bz{pAtxU#%}UIEJ1 +zv!iTzl@7`ehdkz8*4ThMI~nt8Cg#-wq|1@EkbV&9B}i8x?L~TCAT_%e&%;E_!$i!( +zw5(}?OncsC`{2LR13R*FFxPtc)&$mPZ3^_r+KqT^pigr?)?el$-Mn5cgWoMvYaqim +z)YUw1-3l)9jrEs?teqFY?jSVI`ICr0=QX)BP>;4W${qLTBY!01ZbdvM>on}ApuvU^ +z-`dl{w~isLpmA-(xWQ*n@w(K@9;ciGIg8bN;5pHFZP|^!ZNgXtV_#;jm!V%^Mqn}4 +z_8wRt6b#MvVGfnrYesGkuT_f!Gq7F^@ns`D5^2~px0ioNZm*{FOBczjHK`tc+;}Y- +z7qtB)*9cq#=jQeW^v@lXI~?(-Cc9sFjW}!1oyIwpJJ$aJ!)VZ>oAZP8#dGU|^rhwk +zL*raf^ML0YIjZK+9{wnXFB@4`%JoeX!9kx$^=&au;MPn-=A+ +z0xUuLspj;B*O;cY=fX88*#Cd?4o#;7{S%yF31?5FL@rLC@!~$5F_Ur1yOHKQM&hhj +zFMaYES}0e`=QNjGFSl#aa);cZWyqa|rgcUGq&C)Y8j)J55pBe4cNmFAvUZn|Vx(ww +zMykzY|_N;lExl?-{XM_!URP%n(6Awrs +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 +z^xHDLpPL&VM;gR(o{~m1PBje_i +z+Fv<7-(^4T90ayzJ;>{J$I9)1HO6^*-6XL9k4A+$$lP`{ILN(p-6KECd&9?n)8j;5h +zqB)pR}~UreNH5`hp;Z47co;Y3mCKnVou0b<*LC#Cf@?@uytBe&rUFZ +z5;zyqTjYbD+po!^*_pm+54!)o@mC0EH0ERH;?&Vc$YFkEjn*6cZoDE#F2t4k5ck{5 +zX>NX~Vm(!i&%Mbwis1sN}8u0Oo#mW!owk?kS8T$jDy_zn=2Eqlm^sV2H}{qNaWN$>MkwMcWgx}_Nw?d +zZwzMJ%l#(@s)eVjnC>XnM|dYVN4g81(i)~>Soh!b+@;G)V<&ow>gmqC`#PdKyKND* +zg0McYUOBb0ReQ9eRF>2SSJ6A^3Tj${-WWHvs$B4leB-_=nRU}QG)OmasHub;G$7nU +zb(n#ov#9`XnUENSOPGBMjXr6=bH}k(yelWxevgJPJp8Ff_v&?vT?ar?kYhJ4w)Yjs +z0JtY0f&0=)kvzzrzozw#vA-43IPeB?SVrBPYhFiK(?8qGEFQ5~|mrL6(n5F>2PJUXFM& +z3RT#;^}#8U(g!>=Rlij5Nup4?#3(ZxWG@NH|5eX>Stv<6p)<4!`b!-r{{Uz7_b0 +z@KfR@@W;px=TU +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 +zQU!}JP@qB%W$0K+lXFx~Jk9vS;K;4IzVY`=$ +z0aWSwAzszPile=i{Eq7 +z-Ss`q+)_*Ic(`!z>CL1$xTl?ijs41Hc|zgqe$9D%X_9ZCbKLx4 +z=3A88=(RBxCKo?}*N{H>Vxz<_%9QZCqTeesKd4b7tk-xyKzQx%KiQ~xT&ICM{pOh} +z6&siP+|Gp>U$sazkKx~9C)d`?nid{t_tMU8y$|TrJ_HM5l7=lP$)`Rf^g)>wvkqC% +zgWt?5j3K_!11#$#xa5rI_>@CAgaYWrQBBgW0OABZalc;Q?V4G~@5}B7U;QKy?>iK( +z>;Z}kY?nSp>Pom$jTxM44pVgP77-S>nva4kzoM(C?L%Oa~y +z)&f^FBpG@46&AyVKBwc&c7KHX*UDQZv3Cp1`pS6!xDHw0et=Z?o4{j<2n1tEqLS#GQ;LqF=MJoV^TqYC@27_~Ur^*Ocag>C=J&(J;j5&)x~NRxTpY+=gmU_iZ*m@2pF5)`7|QpTh2%-vRl2#c +z>9?^lF)RzKZ=tYxm@jWwqc8CQ3$bwEsxxaZj5c1O<+TiI*V-b@{P_i<(iIZ%{GY{- +z46-?zCwfdW5|U2};oehwr^qj41p|ENrOKX|{2)fd6Sr-Mg9*ki3)G~d#e6?~chkG9 +zM6roQw9pT2FvH +z@#M155-Zo>b`iD4_+ly3ob$m&YOt$q+4$vtYJn!aeA(S&&#K>#q0%)|Kh6nnx85@( +zcR?2w&m+6LI^@`{{EViGTdpgQW6}4uxER_r24I^t)^!?INvpgP`N?$ZNP;fW{*h`)FB +zFapx$?a)9ZQqbjfSh?`u3}lw1C1i*JzwCJ@<+jL*}x{UM#tyWV=3IGZ97M +z*&O_f*%lX9DYsmhX^hj^W$k>fH1S73dxVr?lAdgto95nseYw37o6qksG2JzJwHS`t +z_~aN~m56*v6ISS1?(cFJ%W_9^e7k6|+e0J}W>|ERIl61j@DBV?w%(4C +z7D^7=#W20m!!2ddp3$8ahi>h@g4L;cpA&#~@xj6jf*Tuyo11|BE@k=m_Jge-JN>u) +z{DH9x9U4hWvp1vOu6Se9`SyvoNtzkW*d#nZRiWJyo}vjK!l%j8WDH@hZ<3sH{x;$e +zK4#ble_=E6=~JV=T?cZw(5TE5}=Fz>bwO8{&FTDveKT?`pd+ptM@p>xTh +z^w*TDw{AoaY;!15_5t_={mR!l1vz3rZZc9}%9wT!Of{r*YHjP~G{#uAQ-*c+zn>kH +z^2C3&l5NhcZcevWeQG7Ir0%08!ZcSJ<(uAeR?bk8tRrujX{u7g*J%GbH|ao{F70PuwYyP^?#44BILWrCJlZc7wl1d~19@Uhy@9j}dd`)(tZ!SPS1Pfxi_1OFGVw-?4-OiCzs0IP}5Tt3@BcKI6I!cmA0sk!1P_I6PkvC +z@@J^bQ4fzHiY`T;NhzGJ6rupz`$Jk=xano6=U~IcD^S +zbLBODwW{ex%BgJ`Pe~Ph*9Z3C(QcVtbu6DPoKIm0Do{=t3WF!D5Arn)S@-!@vQl>@ +zC+@Vx_*e)23rdkO5sy#b{FaoyQ@z`s~?Y1KarX+_uG27PFoQ6`F`QD>a?%Ic8Zq-gHuumekRdrIjuA989 +zIUg5SAMR;3wVA}p&oXuD=htJX>Q^{0w#&XqH>zAdzS_@?q9^!0c+A;7$zHMXy-i^*=k_J~8h +z(WG3`j%s+g3KBY1p0>|6moiI-Ry<;&DDcA(?pc*Jjq0WyzPi9&(brqsB(*w151Vc4 +zU565uUk-VoJN@pmhFb$`z0DshC001#$YCaNY<4A)JE(0PrUKLD_(d=)k&5R=n=bw9 +zCZ2W0@8h6%i!IqD5#_Fmgp8dGIX3SNRy6hH$l!+$Kb|wVU0M8#AWD9{UCmo2OLJh) +zr=$D|P^24t_LYXlOe7jM%2aWR41qgJ;@hzq7;z!YmQqzR|2}H%@_p&H^foJ@`ZisQ +zk&TXq2!D=+kxBkasysbo0eGZc%v&KxyV}euT0U+v|AnvC&Sr0qK3hRw@Ze`T`%)pQ +z>EJRnnUFm|x*!Qaj#HuMbB$J>_Oi@J=%h;!7vyWE?%osXQPA6?90Cmp(+1fA@7nN^ +zIkEATvf3OZj_oRV6yHjH>LgF1VW0L_n!CIgT&yN25~TDiwC%t2DY7_jz&ol7(Sm+H +z8oAZl@#!)qn$D3YvQ#-zE76a8<36U6f4Ocgbnz73j_^$Qm}$&uW~yqS)`L*T6z$P( +zei2JkPo8W`99ye%5>I$CBokj$o35&Mq+zJTP-@27a{H+wc6w8m^b#xbb-fP1PXwL9 +zmJ9D@WM!oNSTv@_vhcP4Cg~l?PvAW(gGrB-`g9D%m~=^w%NY8yr_b}RVdR<0xpzD~CH@X_lY?X_KKCTQ$^C-w*)T&0bdZa~d +zdsPqRuHwBlo-RdTmHrLlkv0cVXIIIfptl)nk08m@2>e}t_HWR~%)zSD({yVZg5lL_D>6-y4^YZ$8%WOs +ztpujs0SgiR(sT9W5Bx;;hEY6+g)+4>advSsHMITT(%#4l7K(|Dfq{U5;D2i#9(plL +z8y8b2dNCVA7gG^aV|x=*dKptY^M6!VCMFg>K3J&#FWw_dH(u5XzyK5S!WWXdFk~Q) +zt{WndZb%UIJ=+BCU_)wbVN%Euwb|2vU7`>Gd+(j=k;>=(H&zJjYkKY}%@F1g^KV;& +zFopwEksO$hgXhipm04yoTH8))w6nOeiY)NEFo5&{EX*7q+(+R(hSw<%5>Ed_@7+)K +z4BNa2My#3E1IKhWO19QbY!;QbHw|D6-4pmsMfNxI3cQVDdsEeGW+Bsr}ja)u^5;2}v4 +zsIC&`y@3*ly@v+mRu&k76~m+Yo81SKu7(URW!26Y6v(_b?I=_HcA$_7_ +zWlU@ATi%4pA3EU#Jv;>6v0tB^-;Rb2{_C`+MMx4_KktcPO4s<0*+6-O8y{Unn3+8; +ze3BYeiP#N5K4`z%_@4Q8IQHdAEoRu`!JI6DE*lYkNybOk>ZQmHGy0(5rVq7sD7`13 +zaHa;gOV3Jk=npLG7b&*mfS<9qVY46JO>#-7kuXo64=bwh*p3dhH1NaxNGttF|9AOk +zqA1>Sjs2L7v%?H-wnBdL=cav-2oXvSblL`(KuG}tTY?+_65$SC +za98=XM&K4SfS1BN5Z5M%fXA$BN1Y)F1MCj$&4 +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 +zP=>Z*q>^DCXzK}Xb82lv$!&pAQN8IP< +zFKKU<%s)9Lur8+LtT&GB@bO`}i7U2rV4$Y#bb1YHRrT +zbi-lw!<0PRFAwB_foo?2|VQ6f@b3eVRChEUrk8N%@$Mb(_^U +zw5BHzn0o_HM9aJ+?5627NSt*`XwFRU3|A!-bkrcSg5}@)wR_vf7x^%|e}sp{nZTWtklW<|2*&sE&xo(-$LMs>Ni?og5cNucbE +zaNF3H`9pZyPK0HEUj&VaPR+OTdGpr$VF4JvB +zL>~%5RqZ +zDSZ!{o}Bg3GhWkFL*Or4cqw_I$01!iiF5%2LU{q;g0>YB8tMS?3SltPJ!cdLLnQ1T +z>cA-w9u9W}1tyG(awP?XbX;uny^Y5hZGk`LQxA3EcTzplReK}z5v$F1!0#~|@m7C$ +zJ%S@_1H2fPgNWSby~0PbB;K#Vo3{H4dzpP-^owd>tj}LiSGGorEm*qS6veWqj9O8+ +z+hC%mtm-Xs#iBS9uq~JzIfs#g2B(j1-L}>GFOVN#c-Z?b=;n-DoQKeu;neQgauy!k +zj3d%loJCbPAu{KtVVl#&J-AC*FWO;(mdys<35+4_8&sUcnEz&FROB0LNXi|4c71h0 +zTEYjSW!3{MmNR5jAK{xHH%Fba6>E<|&uGj#Gq5chHL2=JSe$URGP9jEII@c;t@bB8 +z8iSk(SnpuL`G*84orl($i06gT#_Dj#I^J5=kQF65;xiiW(6l3#ZL*}WOn|WM_nX}g +z1$TKu7S?%_m&@Q;NiP^yJz7cBGK&YwPB>}9s3;oKVp5&BnP$sqxNml8hO!bygDW*` +z%gh^rEfu9G;Ch6M8`3<5;7_y?)S=Hq-2QTVV4K%AaKADME*-M!DF9{b8ZBtSis8!9 +zi$fFryb9H;jcj1M##SsFp=nUGthQaku!?KAYS>uSB-c_kSlD{ahoC43WvZ!b1)C`% +zCp>0tn^pDMbfJ#k!v&Es1!i@Nl80%1)qR%ZgZ& +z@s5W*(sVdcfzVa4W`NK%$n4b@&RZ-iZ(PWTRgU5&bSp)9QOqNWA+;Nt$yKgkN03+Y +z@+?~{r;jUs?GL1gg#}PI5aj6$*r=cqE*I%GCD&u9S}f;tJUe9v+}krlnKfw01Rlde +zxb1UmH6W=Q5m6zeHzneAPFu8UhdYS!DC#E^S3!iqcGV;!lRhZOq=Uxnk0sa3Xb1YR +zGxb@|E&uj*(L@e~&VcC7uY&L-0^qPkjVTFL)5{%9aTUs%3(YVWdf94m!FSIBE=HLE +z#!aSx!Ego@8Y|w+VhQQ54XXiE2R1QqG2~$;x#ER7y;wzi2X3{NA&S>}0pU0q2-)O{ +z)nR@;IisewO_{%>W_P!XWaOg0+M{V3i6q0#7A(p1)Z5A~@9f=)17i)ie=!Bovm=}mGaL@{7 +z9V60O*buui(|Tz{BtQg4Beot+G_@!tgNpNH48ikBhgU?%4)4_rEPSmK;=oEu^a-KQ +zYK~7)kSJOrM|4qDhP;cW^zYR@%Su&LRmspe!;>3DlX2P{m3dL;id1K*oE`I)_bJ6@ +zilMH(IM^2Mf&u7Gw@t;uggGi8)HM&p;EJ>nEO%q8>BWJGMp8~=!Q$LwVm88ZIEd^# +z)socexVDZIz#es&?fA019iuSaKRArlW9g}h>{;iSI?egxNx8EB`Q(@xdAp~DPbm9F +zHoYst?MJsk;Q@;ru{n+Ip;@wNHswUkpCYoG)F?irI)Puic#x@LxbmbM@5(NFll*4Z +z=o9+}K*_{I!_iFTi8m420pi9fU+Yza(7E8m0ucE*HXM3zof)T(2>$i9i_3=ah?ghh +z!-;_tav&#gE~$ZlW7jOBMiNKXP{X~l(!-2-VrBX~&9chTrI|X@l#sWpitH28y`+K^ +zSe3DGPy|u;A#m8|+lB9Vk;efGsRW37O9Dqs5nn+Ruy`A2MbmSxoSz&yk#WNZy!qtm +zQb*!Hu>+k67vRno`B}*dky;ht1Nh~CBXHt^ofeA|tTKWOHOO5q^GY%r6=~HYZQ1by +zU2R-w!DF2ttC<%062cYOlruR*wliw?`g$l`Hm8`&5o4o?`~%Up>^DU1ZkE_J`4yW? +zl0<^#iMSKGf}L!F%VUV`AZ=7Ocv`Ls@OWHvgv{4}1{SVg;G4l)i%1r4nj=z_%JZ~# +zDShQ01DUv@UadK&QCJ*$%@O%<7Yl}xwOg}6G^L +zQJ<_3zlts0IGZzLoRmV=1Zl6%madmx&GcqPI)lYZP|XpqLC=qjV4&X7)d+g>3gZHM)_F!4`__T9WeB +zLIveQ|0KT{^`x%$EsFArxem*M-R7*W6{&r9XiNVY3Q{(S9iJ%}xfb52D#>PGZNMkC +zqzy-JtjH|d+Z2eOkL8vXxX7j=kSx!;^IV9KE0+x~x#$u%TPSZ{IK(2h+t+ZnZc$VE +ziv&06s0I)}XDT0*lSXqWi}Py9&rtSz+djgw|KlODD9W}KJKp>o +z^RXuc+f21=P*c7{^oz9U_5Nv5nrURe)*o0S%#s~wpNt~U$;_D5r^|T?{cx+Y!C__F +zh~s^mjmo&iX^u#c86Qbt+8Gt(T#D7!a&O}CkoTRHqk3&EzU%fjp7)Kl9+FsyBEQi; +zTl31bnIi7L!{06j>C_VG7%IrM|9G^3>Z@|IY8& +zRuSO9k7Dz;bjH|n5ofiBuy;KC;VcAo=|>^#`|ozkqxpH?34D5~!{^Q%iHPV;dD=ZZ +zD|kNb;88ZOOEWD;csV?4UL2aYL6Pjn=7u)m|7A_oh+vt|$hLiE+3EKmiz1b8w +zg_17WPIDJybeV^U6O#Mg{mM6z3Id!cc331z!JVlDt@UemyRqnoFLZ_L4i|-QCjm6~ +zJAu3ANhR9x-Xd+r7iW~m7K@I>ZQNMjM!E;UcKGkZxQcB@n&tMM!(I!zvB>t6aEwL~ +zux%eCYlGs@Vv#Dgu|M!vdBC7sVQKN~sqzj#~( +zNDxgB`C!|+H5<^47AE0bcECI$y0SOHs +z^cZ2(7SR&z{WFVRc8-2idY+S2aGsxUVc4d}XyGb%zQfdPb|EZN1KxP(m^jFiKk#8Q +z^2lmbQ$JL75|Zu`K7OB3GaxvB1K5H5UZS8*mD(Er4=83luOZ!3s)~*wZp!fU_j~7x +zI>bL(tfiXEGivkVduTE9G-Y><;p61}`^QVF$!q0e)35$>CjO?Dr`&_nZzO=J*vzZ@ +zsQ2}4nSxKHhjB2W#cf=*w-u&0Ed_TyG4XC=F4VUB{+%e1XnnbtEZJ4t&Fi{CZ3D-! +z_h)o03)%*%wxl(;e)4wfFT873Zl~G9(r5w_36&X`9r}PzlJ#q5oV~SV?9F6=D%drr +znfQkD`9LQNbVoNEpQY`6&iXqN^|99?>+p=vkvPBk#syjL?B=Zv@7&$bU1KM*KUG0# +z?)mPq`zVE)8W~=X2SvwqI`C$wag`-od&}WLWbDp|!^bq4E|nqbHs-O@P2$--RtnB0 +zW3Az2tlj&!x5Lu;1|Lkbmf(j?Zl@m`mB6ST*JG6F355)NJ0g!NsSqSOPNf1A%foO +zy7cspETZ@Dq6#Az=>hdcIgVjb52hU(8e(w??D-R!Rs8O1DpBYfTvCBqja4P2+h;5B +z8XKJ(KBs1G&{0s%_H8)S_*6Q5*VD}F`>knYgakWn^S8nEgtXp+4}aq-1F}H!OWtboPBrW;WtJr?~Bj*NJPln?8mXN=*zjI +zSD$^9L8>XLmqwIP@9lwI7W=Y`u5iTE<-7{Y<4yD-YIxM=pu*xP6E@jbXe6lxVvvZ@ +zukF0{$KYx&?6}RkgV3z6Y1)Ueu&Kj45fj`}?aFWm?u5I6r+)6=G>4bPW1T2BvD*Vu +zpA(-_)`rbyhr`0AQqG+AH`mt%_?ldu%}hU1$M9RMb{sMpx*HA+)x>3ah7WJs=Zy5N +zNUakY&BCtleQ^W9=_4?kyL{j%V)F`u?4f3rEPmNV1J`Ks5O>dXc&r2ZxHwZ7%g +zgS#hRS+Hrk5`8rkGT#TM>QA1xeLV|F@ozQ?=#HD68q{R4YMvII*%9v)&#!METE*E) +zYPV3`Ocd5mnxNZL5OSZr9ZE%Z4L%*8Z$fF+zU5h;W!H+=R$F!T(mzc*JT-ilOG1!1 +zYF%8W(4ASD4>LvwXi=_itl2@AF#w$^rH13U3)0{Fe`n*KY+xi%?Jl;1^_8tUEDkJ< +zthi>we=7Bz*RCNsX<&QlF@1xEdc*nOdw$7*ytc6XhbEj#)qByi2kqhgR9xIsPWrZW +zY*KGMP@&mFO-W^B;qX0yfe+}X!z>e3Eo$zgsdg! +zKB?S3Z>QsR`rVn_{`jO+vW*nmwsBg&sF2r>C2(`0nHtPH=?O$t~+$o(7`xph9o_J1Au@KW@oKLA_q*GM@l&$qxAf +zbz%jK2&2D#ze|h+_l0kz-A0z!Y%jgYd*7x7xxJ+ZS{i=2SlOL6_aeEx8K2E^WKLsH +zM07R|_~^_9pmFuWk+ir0Gap_oi+3l}EeB-SDij +zPs?y9u3|e$`IOJc)9vlOx$OC{(mmyXc%cv%;1CuE^IRdZK2^+TZ +z!COBFq_Sl_s=UI0#h&KkI|vPR?x_uecu_s9tcz}10EKbXEWHFNw-u6MwmRsDKjI?T6;h1 +zl=$=68V5ig_|H3AQJ_%aj06y#P*>rd3vs~FHwnfY;8v}(-{AP@5KPkFY0s&JmX08A +zU7uyRBZv3!{G;0pJM-DP(SR}lUWZNEg8$)?zNNO>VVE{DmW0Ky%NmM!B{9e=oY;Dj +zxZEnSO_QbTUvdROeUpfY>-1IGvEHZkcz#9exGlj4@FDJlyG1uO#qj_;TkxDJraOMT +zqfclgz2w{9s%mE=PK{|F0oROF(V}Y)D!Rn_vcFw``OC!=A*~PwEl~{`98XatB2-7c +z`1i8fpO^X2LC(&#G`4LCiN?SIslh_iO_fZqu&#q`^1R$wBHKvw)=E=RhlG;+te4Sc +zN0%Hyscg)HLkL|q_2}I&dZDQg1WltC3#Sz_Zu-}$6{wbTL{El_c-4kkeM08$dVk2% +z4`)#br10*n=qV!+ZDb7tp)Rjo*-oW>3yH#J@WJjVt>rQAxxTR?tYBPRfuZO;ot6GY +zUxWS3_Ra^NZDGGI7nlwL^~DZM8{h~U2?orcPD{C-=FZ06cU{gg1a8`F8oJ!+Z98BS +zJ;|eyp5MI~k`F0MDht>U>>l*GgH;%5PaBnYvPTGhPXj@H3IOIygNZJc;e_$QGNb+A +z2c3-UpKn+(>UGuTWD3`9kj)OXR^OSGYm&@$*AmZyzD0@}=~vVBHL>qbLY3cl987YP +z5qX`Ntrota{YSL_LT6$v)iiOJc9f(WGc)~8EH^%ZVae<59?-~Pu4cP_Vld2||KQq#!BIEeG=!s(sn%gVmF{A7;5)nA3PIJ~ +zU{`yXrfYSQgmHg)pJ9ad%{LNPm`J=eF55fh4OM9bli9sNgC!I|vsl8cf0n9Qka_&F +z%7rohEs>ZCZSpv=q~Vf68%?8+k{Dk3uZw)Zuj~l0oFR8)f=m6Otu8LWXcb6-^byqv +zd)5#PYY~toQC*u|IYic{*vNe~Zi~eCZ?f>U0UQ16 +z6;mnsARX6ZV(m-$&W=Oz41rwy&Acz^J9EI`hoL;u=^9k1dXD81ilt7ZLHPr0OKP%-< +z0i5RP`STyEak*2vH~@mz&>eA8n^rU_B1{L?;g}OwOj6&?%f&3qJT&w7sYG4O!M0pn +zqedkfybnVY_BuD}27tX}*1#4Vx#^Cz6FZ{(UZoNuNx%>$7?d +zUb)<<4!o*Y4WrZbZllhdy4}wwz9&Eu9e*Xm554=;bT&8`IH)-UIB%Hq3w-KsDv1XK +zkowsWTW30}2J{Pd1COj$Y?%ohmD5DHFI9a*FmXiz1{ej|iXis2UwZp{ +zpAGx(D(@Eon*d(Hfd^_i&1SH4)f()A`B_&6Op!&4fdjsB6TU>ji$L#BE$h!$BP&b&G +zJby1XdD$#A3(ap^F`enJsZC*5(E8il4D|QOQivTYtM%+CK`EbLQ8Xwi1{JoQewxxz +z7S`TX28lL_YAM^Fzd_#eF9( +zX^|wnq|Fe~?hVdovt7z2Wc`Roe6tB8ohR8071Nh&?{?s=vCG5knRvt1TroS`v->de +z>PIIa9u2F+{I(FiAC@e_<%H39Juv|#Q4kM-^Y?Uc;YLUW9q=tUcnAb +z@`)F~xw~S-tC{B&8Z|T1OL_8?VeF^5aJ%-Lk_l3S*W@E${;CTsBnUQnq`mye1)7n- +ze%|38$%dkP?w43X23C<`yZTy>>tDzsm>sY`npj?0m0Dc#^iQgmX$ss@mppBKRFsqy +z1<0?P0be>uo)B-UmIMfXX|dOTty=ijcP?2x1OME)>a3Br(aRJMyhSXPICFj-i{T=X +z*o^Mbo0E1(3d27PZ{#Q4f#o$$~F^dQ0g#?;jd2*1#Xd +z3O0D5)6A%?51N}at>C=0)1@#Tdx$?+SX%rATirZn`M+W28UH6{UJIXD3!j0WiCzaE +zpON8Tot=Y02VV#O|3yb&`mgB!RtH>7jY@PeyKFH^e27=7X&{Ld+R +zVt!HradjXN#&w841pXl6049QKC}Cg-BB%l&0phft4r=yl$YcT})KJ1(!}wu)P(VfyaeD5{Pa9fcs(-V(9ihccYuYdO^M&Q?$QD+P&`8~W +zPtIN-g|(r5Z_BRohr4U2-V(^C#E>1$)}t02=fBtV3*M{==ku*+tVbIjTU`k+aAc6} +z%^ly9F!W|*M0HNfg-?8yB&jCGW&F|o=sp@{+CM_Z<+46WW6FMGg(3B1vz0mT``89| +z2HY*mZdp)3`&EM8AFaFGvN(-iw$fiwSM{sx3+6g&b5v9{yN%Eul=%8Tvza7MQ^0Ro +zdf|UM`)|`UIE@xOAMaR&A1A`8a~?EM8nK8hh(}(>KOU^elG%o4Jk!fI3)600h)v9* +zZXQ+)F8l6RnsTT7O%rm(pjLQka%*|nyCQi@^Lh0n(k1k9q<`RZ0OeS=fb(zXPnl)m +z(gbB06((azJ%GR$?VGH?5seFtF#{u9Pkh~l{6cuNMMN2~Zdpp?sYlDq{8c3rMat&M +zr9=1$qWr-I5ug@$nAs-zXcgw?sKFiKG|kxO+xTaMrSJdTvVTE)=IW~xsYzxSz{|vM +zxle@j-v9HX240^mFOXGM0=7F+<&NZfMDWbyan4|!JH0AG>iXMi&%OB$F(f>Hu>7M1|r6h4Tkcy(C!e%t;u` +zrZne?Yk3jeISo#pqg!%u-j{87&YH6XuTZEd9L|9id_m1Qz*L?(dmk)*B=Mh@5dFtL +zOkDij?+fa=+taC>iwtBp3t81lZVqZXH{|#2{%zfYA_crp=!&ZI$VGuUzK?+09FsE* +z{K$rPQ>5iN$2SsgpHVp4D8w +z#Lb{=Ngf*--RWojNzRrWOzEvTl30GQT0GjqW9c`eLy)vG*+9@AxOuHCWGj#Qx(L|< +zzHKOsWdTm`vncUGs(x6Ve47u3s~sioSTTFh>Ed+f>8Y}>)g +zqLRli(*%fWO|jQGq^m-*=Ud^Zu=ummlc7hEsH2zOZ+%5#F20kG-1;qwAG)cxQXXx>RP3nIVLqb2HgQwoU$N1GC;vl?QGQ@%45 +z^}wam4q-+MLh#2M>+V)`@%d2;C;ZFgyU)A%Y41k`APH) +zxz$B(%_+A>A49ZB)kbq{9>L!}Cu(LD%?s(N&%X@|$xCAEXTWJ7KPaA +z>QFCrXw`q}?WtX!nCJ>otkLT0{O6Tr`0l8uzQJrGH*}W7=^TI^NBQaUe|7Q-EuR^GGU5T?&9F4`uHN1;)a;wtQn4lfCR+3oN;Vc6tpnGD6Z75 +zxdMnXazfy7WRs26u45HIyM}L{cwC*qzl1@3syAvyzui5_IuG7KNEYg$3611iVC0-+A^E$OW2yTdg$pmb5G1jeZVm +zmeHwLH1;TWmoj(jB@K}?2vVaROG^EcEiEMcpnQ{2wXJO+>(t?`zaS>OEJ$0zHB9HK +zUXvk^DXKg`L@vMq+Gv2<#48J+oE6503hhQ%fQf!;YWxbNv3(%<2;a86~HcQ)ihMYUqNzE<@J +zdmJo35#lVw=2gdh@6sHwgL~ynckd4$)Qj=;5A>E4-_^wqrohchc*gat`t_%K1d!g_ +zAq(a+BjdJL|A49@SF#z-#08J_?wRoxN=%eW^tu2jrZgo@=rjDZG}Hhe5p=H?cdmCK +z(ePlO4b(7aavZGwfvOPQUkIybUrY_rNm)g`_#y8`ixzNz`N)0 +z7EH$T{Usls9GCxg#1QFI^NIXW6Tx!N?2IdTK4sA5_4LNRz73Ve1xa~;`iR?JTimRt +z8@}^XI%B=*cTAme`17Sida%Sfb%R^whXH?hb9dBfj#uE5`XXTF6+wV4Dv^0*whoo%lL-9 +zQlG1KIK>BYnK4cl9PHAg5w%|`?Dmro>(qS)gtrjUO2BGAS4+uyM!iDFdRF_4f=8$; +zj?!&%lwSb<6pY}9mYxxEZztegmzG$6QoWUn*Y8oU?mUoYumy{GdC)&s0+$t)$Q5UI +zkh!mOD@g2)9KWj_gWMV+cZLw}?*aAXtsVpoTzt=S_Si-LC~?&v$&BZTEd2TY+i0X{))r+z5%gg*hOqkM&5NgRSwniS^VNXh? +zh^0wq#QH&Y^bPtgT{MZXcsZZt9= +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 +zZ*_jT|GaK=L|9BjG^o{Xm9UN9}4+ +zQtAkuz&0xL+RE?n{*F&~-osq=z9FSqLDNL`jXBi2x=Q=xt{O{st6_zrz6iu8uR09t +ztQtEk-!4%RMs7s-=;>JTD>CC~BA#UD98NEfYLTVcu>%bYQRBQ2fsNgYkcdaio?YyO +zoiZ{)M^?`>sj`TftAjI&Qf#Y^V&E{Wt&NnTegpL&)zrnxN{MuBfsyH4FnfZ+HGLAx +zK_H9T>`iLYnP80a48rXI8i`^iw(gpo +zwuxoZq=sVUrS3Ugw}XBE0M7-}!xF}45N!kR0qhkP`PdC_M0jgJVVVwSpgoTZtHc?{R3nT*sU +zO53ktl6*2`5eN_m?+SWQx)U=7TN%Mf7 +zsglVXv4V_584HnWX4r+XJ|{U|Q9Q~SsEWU90F3b}Y2YN7GgW>JCD)Q$m0ZniEuPwMV0({_k9BuBPi;*tD7F3`)HvU3P={t3fCnh=P_pcAd$b8jUJr~G34q$-I!%9l2j +zED^)v(DA5YpqYtA6W87R&Dx4cTDH3b!`@4Y^0u{9BrBElQoQ!6^v2}>BV(Zj0IB( +z@}}j-^*LknDT#$NgJN1>u`NaaN=(ZWw#_;3MgsFj0>S`^wlr#m61(ue2^1H3laoVq +zFp!mpip&kp%Qbh5<1koK$;4{)R-_@!SHXAamd%UBjAl9x8q;tNUZ8dK_O){C%ulEk +zs%=Z`6~Y=(o!c@i0>HS+J*ym@(lSv=1(l47kF-j+jEc^`BCV1wt#V&d!LF1%h-?bS +zvN=^f-G74LxQ?yQniiZsWzhVA5UZstG5}=#fS?~|F7J^UM{Y;MZUUMK3QM4eMI(2F +zV(OS%8pvCkC&OD$yt3BS|d@D+`{LhjaFX{lZx +zdlIr80x$)eSr8>&nvP;ZXtlDpVNq^vSvcJok*Fju1LN3YLad=ePIvG>F}yc&)n_y> +zNWCcX1aF+wY6nLD}I$W}J5< +zxhcQC#e2PnrnPp7^c%m&@pMv_+Pt<6>2wl^;-$vyYVW@bgi=3$y$V|v0I!jo1(`8| +zF2$+TNQ+BDJ8dkou>V{^^T$IHw|{aBq6you{NXEa3skVSsF0ixpNLbb1Jzj8+_B22 +z7(jb+616!d%dD^_hwDf8GZ&g^vi@x~d~rc(q@o|cp155v2CpK|hZ40Iw)P&=@dvx0 +zsdT5BiN7Cel-hb&@CIrMDY%PTCY7g-_iYQ0negKvxx~V9*1-mO3?qH;6U9fFmz9s7 +z;2AAE$Inrl=gbqW^uQ}t5IcIE$0X#TUG)p( +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 +z7<7Fs)t +z@H)B(5Tu}q7>lvgVI6pZgaJhuRBS^#&Qnag*++Z-eG!ah`*olr7V>X_Rw;#VzI}y2 +z6*GT#L#yr8>CHe?n(e#(T-B{>GCJ<9(dxX9Jl$>jdKiml-CS~)N$fXp3h_x+JO1ub +zpcK1fE3|2x;WOIjxE>n$fFQTvlUGE=!hMYF^VMkh14?|QxVpX$&g8`%Yx3fi6Y;}r +za>ewjk=E2(&{9CF=4SLhvH?D5_xW3y0zYaS^F#hoh;Bw8D>4*7vpEmZqY}^VL#$~) +zn98PU_vaDF6HmLLBbyZvItX35SQtNvlHQVn<=;w?+mzfS@_BA^_hJy^I)qYw`Jh +z1}Qr?$QBOnFUv!0uM)fd19=WRtWf{@qO6o2J3_V2?EJ|hM%ythQ|1+IWg-n*kp3t} +z6?Kov_9UD2d#OpS>-&{zD6`j9G%P&dX0ydF%C%c#O4j%d^WzH{p>L>$9Sf$GWofO4 +z+1X^KSuV|bb%K@dt=x^yxzG6seZeg4K9)TLBY7?L=?YACwOg +zU#&O0FNKG|q{ZWe10cFIcenZuegeL=YT+1SLMLrRL}^(kX4)iD9csx?qK3RdR<_wt +zhJ?O%FyTjAw;t-CIQjw6WZEn`rUyZGOV;#hQ#FYti#`++h)8a^o;z>@T;w>JdYZa= +zF>Cko>RH!jn?{>T8M8+fefXL`^m~RFRPKN)1Y;@tL}{CUTlaxM`hFyRKXl^=E@u$^ +zO4Eae)&UtYi#mYi)cp!B-v0n9$^=20Cj`dD76=VTfczkM2#QF?lqJ`q50hRd%VDTY +zE9Q0L2%^tixp7StJ&nC_#ftbez^7wju@qL@{GG#>MbkCh3lI*oIv9)xxL25CYrAm{ +zF;7DW8dysI6&C4V4DYtvdYl4Ydn;b`T}C^ +zKX0uaovGyu)B{yPdUyXxSF`QBtDrFob=7^vDPZ)4blkU%gGSgJs>Br|&12QKH4vup +zIB@fVY)usi5f2f8^4Af;@&EvFG$V9V1NuYY7A8h&492%eoM9rsI;pBLb?-;X;M5}} +zg)TOc`SLFty8SFJj&^F2Xl>wEQQ1?EdOtM_q4M6OdZne3w`G +zrwiNVOR~&&0HvU&SS&6vVbSxR0wt&Db-N|vP~VYyEXSyh0|n{5*GMek;aewHLIRwu +zQ|c^PI!B!d78aST^F#P30^84v(Y^W-b|i~z8S+xdW}p1&s+Zk!HQl=NF`y(YHd@)}obbXU(+Pj0o(Q}A$y(`={HpqSFV +z55j#3PU-Sy7Hg<_=hJfN$4hnZ-TLPR4O_0;4bi0lRu>%WaXY>h;~A`p?A+Pp`?<;F +zJ)qC9&N=v^97vA%Wjyq9az3M%M;=2R*K^_$og%m*P(>d`=r)}xHgE4gFRlN<*Et4f +z7JX|zwvCQ$+qRu_?2c_a>Daby+qP}{jWu00^RJpax9)t}b=F3$ea`u?vDWje>Qmb} +z*c%QuQ2Z6og^m>_)=L`cyLV^8&pZ&CEa|}-jF(>5D$QUv`B{MV$g$^x?(xIVNYDtv +z1{pDeF1E#BG@rUXn0AL(M)(e$+JcW4vdE)quvW4%Uve@ifmn$Qt9D#!b0-mq0h-pZ +zDn;8)1y3q_?yxwL*3lnoksY?f!mu4dRT=#p|JlytmT2VG_t^O4v&y#BdMfV5t@z?Ex1OKWHefByrH(6>&JqAndszb%laUg#h(YguG)|s>6IGI#JRR5+H +z>%cp@Ox$87T_75@lN50y<}N~)a+s!f=fM>P0WDNmTbE2KCRr>R3hAHFkW5QU#ERky +zlN{A96SK&qL^N{*sjmh0bN?Z!p18KKx9C5aN`tarL64HHJ^Nnw@K?qBtXbnj*lZj= +zjF$0U%i#;@n_Z~9L8H4nGacpD!H>*CxLLX3?3U&uzLggb6|We)vG~!c8*7g@pCs}A +z+#fWxf3v?%1%7$K41KqQKYQaUdZ#2Nv1w79c<9x&Tia&tV$`XvUwjD{Q7hX8RtOHE +zLx)3Wlh{YI9R^Jzrb5zl{HAZ~vZqT-CF_vsV9`gtapk4u%X(G1K$qeiT|d4`z<2hg +zD0d=l1UMZ*mkv^K^q5=T$JPX$unwP%w|i$7RhhN=uHN3r1Ks6p?0)OQ*}K6H2cF +zORw$+_e(QtnG6Ymn8o+h19#VQW)t4UB_WOlhBtK~-q6JX-os9<{J? +z9P;k`)%q0S4aMo(gk^#(cc@*M#a)90Sr^zi;XA{W*n}vveU1nVXOf@Fr*MP7Ro#H& +zux!HS1GQMZ379epgX=;jTxQ;o{PhieyW^!u+KqgQLeoK$`;gEVmU{Is@QE8e&0i&8ofG{oFpI?c_ysmofq=*lP)|l$P&nM) +zFUiP`UA5ZBB$BqK&PYZu7W4H>%+ +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 +zzFX0MQzP_NRm0}^61PQ`*6e{+$93Ezt7)<4*t +zz3da@NYDf~f#*}{8J2&UUm*;s5;dB^v$eCh&E(>;x`%YmprWQjliKX+2KNmARE*JreF(EK-^+Tv;2D;Xz7`Ey+2VJ=DVZCuGaGQf +zEQ7P9_?~=K3LZJg3#0H`%YTg(6Mu(~boc)Kg$`p9YDMy7Ii@l9jdI}&9wElS(n>T{ +zWzJ5N(w^Fmx%ZLw0rU;=2=C9q@&ft^^vK^QfqfQ57G#Wp>VK@s*9Xx8x98|e)3>Qv +z_p^505sS3qQ}sfme#^lg^i_t{Z_YTws0VhZYz*0#{rT(Rx(4-;q8&(mxH-JN$m)%- +z;kgO%rGRi)uny*_Q@=kYx7R)9?-uN1HFFd3yA}K}*W&u34^som{a?~|xHm0W9_3zv +zlvj0b(VnsuNnfvsPdix?A$60WoN>Ecj(m(dW{g5up;17e?=FnjGv!9eGw}lrIe{Sr +z>{`GVXQ)aWfrGgd9rj-_|_ +z&iUK!ogWe)P`?bNr1H9iAk){m$}#4cQlYTVI%fQzPU-aFy-J4ZPB8( +zb+%sLgrH^Dx_7r{^IJvR%Hi6D@0R=Qea^;p^2YP!*GtHa?~BWg*H&yrTI9 +z*7dYgn6{_a(n7C19q6WN*Bq+$8|xJf)o5Op$Y)J#>8DG?E2dz)e$e12_Z*o5)qo`(yvZrC?~UNQ^rbS1%5x=y9+uS7# +zo!qnL7QuN`ll*hxvmj$@pNnikk`rQt5aX_iFPPUo>WRK$+WKr)$iWqYD`bYDd*2<< +zA0~Dz1;}&3wk_CHkwdbNp~qjmz2G^1;pb&Px%?u&r6aLM&H~}JVZyuqmzz+K +zr^tHwU5Gw?SXjJprjEOT=wsNl0jkJVuJUX>joIr6U$;hmkY+uz-UMc^B5BD8E6=pWi|dUo2k0q9oj3%CqCpT<`H6yG)sGCi&H} +zIwssJr0jhC{o?WMjoB^jb@ls}kC1GDo_=unQ?R-n#(P81J<29gBj +z*w+OGG3t!uq4*QkU6f-BQW>a<%Eg;oJ1s`sC|R5u4=EYpS2BVpH6ENQ_nj&?lqz>x +zSxn1kv=?z_z?tpYnJwv0tQYZzv~@AVz!UMd2t~CQEWMFawA_kex2HU(rYdGhX|RKj +zlCC-*1#fSeEfXKvUxwuiER*+2i)h94mm>4RQa+*$)Dk|XCW@42lOmrx3ZIOi^y;wm +zFVrc-#q{%Y_s~TCerDV>o~GtH=bSC6*)xXzFF<2)txLe$^rwjr1 +z%witD+~o;p8grFyNKVYFXhpYT-aG&1R_5N1C*$k#_1sQm*bh3^yQkf-3HK|>6WSMr +zv@Yn&EEO50R;0QG@ka?&i{%Z*Q!`rxu|w{5-Yf6MX|vJ-a)aeuXdPqF(^Rweo`4M* +ze;F4r@Z%b?g5%k&of`lkE;6s;5Detmq|KNurR!`?7$9B8klzw0+@Jl)eXaq^si?lb +z?Vja|@tBDtGA3$@ol+r6_#59*oIqv5X%b$PB}-KvoPV6#nn)y~B*iRNEF`%t +z9b$JKy*Pi}^U`zs;=B6s?VJ0hGwZw3xT-g}ZuPbLqveGcMl=n$_qV!sj@f-IEFE+- +z8Uz0I*sm0|%Ra90oaAVO+en>{=C7QaS~%B +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 +z|G(wm`2P9Np +zI4ZA@{V(?oC}kTk*GqM6r%2$#q@Q`t$JS|k&cug$wsueLN^ONa2x)j3>X_hq$T3Nz +z9RX@7(pOzB<$nLcK!IU4Ng+){P9(9iI7TY>CBq$ +zW`7G4g@U{1#nb7u#>?bmkqGO-hylGErEUZKVP&xS6{k4!EGDmWXAQlP-3aP;6jOo> +zEfv0NMePUUxzr%QHw!XyyN-3=hj7`JX3})0;Pn`3(Cm +zg>)64uP%B!w{o%Xr!l)69llaCo6p0`aQqxOG(NW+^ZtPow0B%UFU3DkYSUkQzXr=T +zfk>26V@N;fi@Y`nbO&P&aixf9P>)rv8^OVxosLh +z6vay5czLByphvFeIl-y~b=^-_Q$)-OiVm{R7Z +zCJ=6~Ia2C8P8=b_f}rqx(jtAK%whR2ypHIUJZEHaXL7ky?&5R1OS{6WC;;U(=5zt( +z#*bIcN6?u=p=Rg~mvrY`Vz-6BlW>G6blWs=>Ii+x_8&tOC1NSf;n4%7d;hv{n*q@f +zi$!X{)YnoT)ED29+Jt^6K20HqXnUJ7CqRO+GklbcfZ5a*(o@{1tVh=anp+peVp~yC +zQj|VIxPu7_U`+tMWD4gvZ6?WOiiI4ZnG`2Thb6+aBaaiE{(wPOa%!2?lkLmEU4S2{ +zi5zS)mB5Nq+gnHqlb@^XNy$h0f$VG)vLJHu+^b9NZCN_y@B6CEGYnQ2ouU%?%W{b{ +z7H2*RW}^w&m^-EbK=O`UoV|chX^6PMB1Ue5`qdU2$cK4F7SW|XHn25a;CgntY{Q88 +z$OYVZIAP#tgrPhAg?**s=SOdMJ_!Vv1%33vi(NF#iPs4C`KLjV9x72R9l +zRy^&a<)02hL@sjTYq5+Hv~Zqa9ROPA5WOb|p@ZTS7(yglpSFXhHQHcE{5J&qJm#Fe +zKYyv%Si9Ca%{PorlHflXF5-&;^$=x>^=?AfC$ +z&fx(@eUe`B>afUxOHHXPSEzlSk5LWQ*1}5O5AgC&76V3v3G_|S%9nk1K(2K)sx9$Km_k>~eFv`6Le79~BsUZE8jwa9x*~-w1hXiG +z=A)ERLI;?6iUdGnNcVtBz8iubhd!tWv%Zglu10>T*`s$atAHjBc}su+)8;uQSHyl6 +z>INY-D#|s6eXMP-4MFHlAQ5wAACwzRQU?ndRwopjG#(r?iCDp2s&3J-cTy~yNG59} +z?FFq{6!mwle`2NN%+Q{7mpi&{jbFs_vrJ_j_#o)FKdb{C4M4eV$*COO`#$oEOuy!g +zP*~gOOTj)_{|b`rJAt4MA@$!kJ;3}j@EfQI|Fhpq(}#&Vw3Xt}jRv-XR#y^m|Dr>D +z9{b31CH`Rn(j9xR72xtp{+u#{R!&N}Eyk{H?N^ULHE77?If*AHg~ZVcP^^0a?T&Ho +z#Y3}qs%wS3`fX(Zs5U}^SK_9IE*r$U>eV+!&`3b%=@Iz>Iwc&qE`l@H5bjLfmk+F@ +z(;N`GE{~$Wjrelt(T#m@LXMf=6{b1HmdLrWEwavX3Rjqj_txM79_Q$zkIpm8N=JF? +z+QO@ph$-Qvn#7%e=|F9G*sBrW3^|jrG%}arA<`E1Fz}LGjpEuM*{igm)r5zUn1byB)ElV39C)_CwXl10wkQMae$aN-7 +zdj_-ZaHWsO7VH~L&}8HuJ~)}|gt(G0A_|m7A +zh1E00FwYCR$51Mu@?Q)HyyiK|x~)yguZN?{6?cQaaYe+b|H*>}`({Cy5Bpx_wbr@r +z^l|6-=io=a`GOuBY|oZ>+_mNpSs$$^+S1H;M{q`*9uDoqKUb&wz2bzLEcx|2 +zY%em7Bgs`0T}V<&BEC>yH_q#vz}SXdSuN_DcS>yumZKHr9^aNQ`hdv+jpdf<9{Dbf +zJMdd5dl;)8$iaDC)Uvq6w?FGy405PU;FYtFV6G2W{Y}5UmkY-9e`h8E>DE) +zU`3~WrA<^Gc>D@QxcV;KYt9G#i5OCV9h6NESySk*MpJ7B^VWbSQB0E8?frvW#Om8= +zJMa^=yO>|NoXwJ$pYlZW(KpAqO|Uk2+bib^mwI0?d@8YXgBdUEx5K{k2LR76!|qJ{ +zRqv8FTz~~`DZ$*!Ww~dA=p)5+?%qxlEKQAOAi`k$PE~I~?~rB69?9Dl#=6D0@;n{pzE8=TasY +ze1zTu@=$mCA$%xo6lm57E^7B}Yn3pb-&`cQWCSLzGx-Atb0Ra_5iwrzi@-h%XtDsu +zT+e9lw`|-{mn(&8J{bUoC%Jd>i<+Sb766d$W<$pj$1v6v>w``jFC{O`3-VTBofAeI +zrRKvd2tA~2@GI2w5_QhuZwG105gVSXs;pw>Pw10RZyZ<+|EC|^cO)JUV0kjUxy`q} +zKOMpXp9M4aNj73K^(B;~%tiTcLac^4)0TxQL&)Whl_K!$9 +z<~KU9tM!3_lSByb=1& +zn{&Itbb4VPB4?%Rby9eiT%J_ILvf#YBQ#ASKPV}CGMW#hMJRq`0tlI&fxU5)oqiDV +zmfW9uv~^h3yAf|~VEZUd8aMarX%vO8H7nqSnUpDgS`Hu#eIAECITZEI2u>96=2(!k +zIYRE2|26{hvcudFm>NX89|tm14L;t!lB1SH(GNw#!)G^LYZG&^zF{6CH%61G +zx76yMzpPdT9zM>JI1wm%{jW^S55TrmgS~}S(JQqTe~+bJyDq-$cXTbEpE?AF107}| +zj+{gM3Q^Au;)~nL;eznSpeV4ghuq?xG19~8&+ZdAm?53T(@irjCz+AgEob43;lh7O +zxt(9pvXesB{ch$hjY*2pX5=H&BJ#%>rlg51ArpI2{NutY +z*qFHySc#I{7j~rop|m8xR3YMBhL*!W%3z-Mu+v2&wHp%IG6%hm +zW}Vjq>9Lo2kh|{8h%XBlW{hsU&*SiRp5?>to`f>MbophwLz7ZwSl8_OfGKp_!2)g(?Pq#kI%)-VIQUrfp-FszY$k? +z##;1U*+D#8A-uR=t=j|90&faQb~}1Q&1tmZs|$*DJL*93^LOT8cRf>YijH=j8wL5q +zUl?}esQNCk0SXXT2pY +z2jdfMx$qtE=mGuwwFS97*%^F2|1y`*h}N0(Mo~VX^CH%c-5KT1wN=mq2kk=F>i_R~ +z@WXip)D!YC>AlN0_qA)<>v=ZQh_@*Y@0Vc)YNIC)&5*MQC^=KZ%DpEYO?m=Ewt>D6xFWT^Op>w#7W=qKv~;(Nk3H*S$>?+tyAlrP{X +z3+qXneL~zPC%qScw&C6J(2!Tu7Z|_f{Dwi3j$-p`iDO??Q3Q51W+- +zdh=PG)q>#S5%#@hb`yh%p3BVacG@POlOcxj7bLG6f4jB +zPV?DMndAG>#-nocS((*>XPu0kVMg{aE6#mN?)5vAN*sWA2#rdBKRsbQiT_vsye%;E-fy5>dajn +zAJTGxQv2sN-sW8Ho9MMf7fI->A0LGZ>Q2|bdCZR#gVrlL5}4CDInV74ocp`P)Irjs +zhFOqiEZN)mhIg^%$IqWebbz7W;xctS;=X>a +zXu6^XD~`)ad|K}#*B|u#>1yF)+-d{$Pa5W#d6%M6yr)J2wTY5J%r)fJ{z3b&%h_g` +zA-JLR$7!ic9O9mS9w9&lG4YQP?lG$+h0Ro~0WL4MRJUdYqQVwse^nYHOQkj5)a9|& +zaWe<*D92ZRCY-OVn3SwO^NGByYH{1B#qu+%##EHS<|$>+4RvGtvd@e7Nr6@qp+R2=zs +zv^8uLs2I_zMw{h+BARUt@`~KDF_EQ(#`!rFkzh!)zf@F8$Y4rUO3d}gmJFDg!BFZ^ +zXd1b}byyG7YdGy&o3U*j&(Wg4W$aCbWg28FvgM1)mT1cggaD6d7TPJ^D6V^`{ak3u +zTl1VO0#!5-8OF&qO-(JSP49CmRZ2AR+O(tme@NU@J6tf7cL+Thrb8k|&nJpsu~iId +z;u)?jCpCgtb~qcJvDg5GnpL94QZ(B(TR1YSCmpD1mQ>}HXf$kn=jF7Q+p}pF6UonIDvyEEJ7JgaDG| +znBq-J;6&JXDf|@HSRwk!XbQX4EbGRd)HT7x*j2~tOhNiBK2OFQsptICX7zV4W4W0) +zG{`V#eYMGPc||1??ue>>{=&GS_ntkKlS5JCycgUBn0W0mk`?lk#w~d>G-w>S~vF+#JPlNnPy)1p8tD>axldgE^%cgZ~E +zTc{|n#^xs~M^;otS!q61Fg2DM(GX!a2>z8_UUzI&s%LBVHV*k?c_SMF9B!^J(Xal; +znY?eGQ7x@0!bv?jvo)bPfkT5Lxnr3Y^FhS{Vj@C6+9XdqzNvc5zCYEG)^rv@bF(gi +zQPZei8GisLyAm^@2@WS(=6TpPmgTg!ovXQ)_+0|l2rQDLM=KQL`z*b3h-@T|f$S3p +z?7aV30Qq~GuF8Q-x#Ms=fsb%3NkxO)wMHa;j^DS*6jk*5?r&9Z`%)(6YagZa)~Rk9 +zns1#dJaH*SKf8gQYB4I|ek{jO1peTtgt?0$Cg}>CbghO~RQq+ZY7!T}Jz0jaLlw3_ +zg=#jflF}q3J@_>WdPLbM7mTKa^%Z@EyLweebGw2r&yWSHhGoX0I!m*QP8?UOIQEmN +zt=w$L)?R;SCdDN^KhzPM`cPE?HqQR?y}gQzsMTXOkg?|7Z0 +zRHYZw1REvd>8~23X$eRfxcsF|i(LqxoOSZBgZ@DKfMQn4Z}#6KdvTzO@(N2HDh{FT +z^|j;J!|C@S7{Av1toV=QX?K5-g4*oL^nzys^^f6|!$mJMfvmh@Q62U${h5UWz+$ +zp1>jAftx=4CH>udE%-sBflt9}Wq4xHet`N;I8v}nL9<6bY+gS=+cpHEC++b#rWaiJ +zEt8~<*&&7bzu>p~UY>0B`JKSwGS~EH&bs(&8ax2j6^7Bk8-7~7kd)41x +zN3x#aYn~@#q*=u{=LIz(x^Vb6|1KeK2N^LAnjJW;6(7QXbD{Lm+>BGEz7%*}R%pQd +z@y9$8U_h{MY3s{n`L^!qEOOIXVGMy@&U=Xu^E&hEQw;Qb3fNbsHwXLH6!6Ia+{3*K +z5Bn+v;v?I8gL_*8^Ew91N3omn@7?H2Y5Shn+1>n{!YNbp3+DG5X8H$au>wV_vox+e +zyjib}9v^~$GXNCQn+@Yhu}A6OuX@%2n+eox0z6|5e8GuwghxurALbdUoVj?jep|gh +zPfE7JVvgBDU62hYr13r!di-Uu<~GN@diIR$ZLf4e(M41fx!{xk7ZPJl@D2Z3vCohJxbE7QUN;BpmfFl=+1n_cmb6{ +z)E5XwxPoUwznWom5L8VRXIHl>C8EZraBM +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 +zei8RV<Y +zb{DN(WRrTI;~8%qL`RfuuB-m8QBnsWg32Re9_Aa$Xa@81Bf_^^^}8$J(fgfZyd+S$ +z@6D6&+NZOJ_y?b0D5%OLhcFEeYU?)mw3Ju$?-1o(6es5WO=ytGk-PRcKC9(v->tMa +zc2R8L@vK981|AXvkwi{Kk5C>8^p?oG;X7Wrs0AoX1Ydbk2ZO*^>bNJiWJh>i|=LV2Ewb(?a%IQpf}7!aEXfC +zC!2WRD0@kih`^9U1Piow314mBlzubv@#+KL3u6=sgVfb>CzTy#-@zo#=m-T5kfm9e +z`&lm!kZX#?`=C>*_i(`?`Lxo_@=7HgQ8-cE4?n +z@@g~E#gWKoGf~_LbQGyz24Hnh7oIX+ +zbw^!Ifm7Oqg +zG%5KnGXjkZ>4y=8(!1u{`hDP0){*Ntej@mu2lssedpb-!FXohBioncPv=6MBH(uA@ +z?j+xoXGbs8ZfJ}(O1t~(SjB3{^;U@DzZ+rf*wo4b`D64O{3>C`hrT4P#6Rfe59 +z!e_;2>!qQh?fI-C>m#E#LAQPEao?mJRFYhiTxPNYra5=N$e~k%Mwsk3huAlj+ryRd +z9L+s!Zr~R$v@4)Cub^(x9erF@1LW!fiPy$mmsiz>Taj0^PQVYqH=w6?2N_0=C>|$G +zbUOIkE4EX7n;4&oj46hRD~&CUZ4JwX(i1Azj_0Egs?5zfv%O=!1eVIu +z%Qec6ms(2Il&MEbdGfd&h{k%KAhTiLb-|E!1a*k)XTx}Y@OjzxZ{{Z4xZh#mfyZrw +zW*i<#PUoZ|BZelCuXmY=zPN~Ql-Y{(j*eGLiSB934r;|H`b1_YG`?1)H;-XvsUdUCSMr(c@`{_l_*45B-Df +z7Aa(vWnqw(I4$}yPL{9MXJ9`Wdiv`TxEu3w81mFxEAX0zj@lF`%5%J7kE2F_PpG7n +zQ`x3=*i_*0z0)M?UC3D=OVMztsNB6AvwW-^vfM;P5>??%IbghUz5#r#r`B`rWOb)j +z&HtLUp0zpR4dL=+VG`@u!~~HkiGnf8Z;Ug9)uvW8ZIa|pl8>%Oy_2oE%2~6buerVX_3U4v3R9%17dR<}i2xn_n`l`1fzwWVPuc&M7kn(QUDf4b-3B*rv +z*}GwRD0?XEXgO898Pnmua7CS-ivorndzY(2X#nrzAb7bDNI4+h4gg_Qm}+pj4EoZhNnH&$m3A@zc~4a0fVL`tm9XW7T9mT`zM%2tJ7 +z<||Y}F+$j#v7Qk`16=Nn;q0+oTj`xk>7%$5Q^#RZd~5$S4X`2aQ2ioKy;g#i-upa`Jn_}ST@3Naa{9Us~fIjGmK<V{C&F +z5a|+dnvyph7g>a`&2U{w_ZyS4>mM=6e8A1|KsP5sFXHdCmZnMN)d?)`F0o8UsXvo6 +zdL>!F;9JXtz|Bn>S-U-s*x7-UcDuVFPz0x0e*=g5lpXGsOd$R`4r(GZ22<;+spH-U +zSph=B%A+#FEL8#^U>3;?I<_edwqb&ml*owa`~{i6ijyFTk!a(X=13}3#*Y+Y<_TGvcXra28at?pxDbZNKjf#JT6 +z5BT;)pr!D+JHI2sm1sY&Mq+eisa_+nfqtF{fXUWdVL2u`NMvtOucqIoi)4q7VK~Aa +zbG^)zqGB=q3{_avD;BWJBT1P?Y{@Lgx(<2APOk+EkiSD-);G03lT@veI2%;Q@W<7Q +zggFgyd(o`~D6^W!zj4wc*-rx+fHhMyY0h5pY)D$74O_DcvD;>|UU|Sy!D1=FJo4Bf +z`cJ3+676bVUVzn&(W`-bL5*j)$$;HX9Y(RW{~fx{Q)%=%SW}nr=H(Pfdfiid8+Oa4 +zot!jM@#K!rwLRYi$6yB|=EodDR^+;9Zs+1D!7xcT^+-;)HBt**4t>O=%Qi|42Y&=T +zPI;ar!oM=Yz`c1bZcb1G<8mH;zw*Pw +zX0=v@$MW77Q$D{X{xC4?u`jaEx}!KCEWpA{5FH!E2!3_RO=Y84J-^7}e8gmP;ul?- +z1>TOAgMkx-1UbDJx=jJyYF;(sAp?rmQ(C8$8k7UhUoNe%1j28#3bEM}Yp=<;-)+I? +z``O)o_zAM~bsidYBRmi52x|CYW~q4Av76>V*J7ypQmt>`(G{Js{hrurHGVl^e=-|i +zL9umAMblnYO7FB(Qz3=C&4~?Uk=iu?1 +z0+!Pg@q_$@|XyOZqXWqX6P>ay);LGFgn +z{z$i&`d@mO^8hfRoou(KB{B)eW1wsT2cb&^JuyUt5esvF^0cj?+Ewaos&7Rt!fv8+ +zP$Hj1UzTS)knD-Bfg9v!j-D_dx>HlAllX_%xBg(aKacyXPoFCNEc;D$EOQ-(qNuhg +zP6{fO!M13`n*yX5T&>8jN@LX97|y*Z3d)hYspLpwA)!;_VcPD?TO`3GDat~0CJd6CWs-~* +zUf=x2#jfBbje+X96`dLBv?w7%U{bKuDvMf}O9e`Cp|HsCD=bo?jGU(Km4r&g%pIAs +z`i~5Q7<5RC{Al7H(JlSRPzJ<;Y+bT_P&99;vGxd3i!sy;e2hZ55=ZfV9)2+X9WNhV +z9&T{@@O=CxQk<%t;>7u*BB#lC92};z93x|#uCca$rpSyRf8sI*yMU7I{Ja`Cy6eFv +zclWjh+STs`^H&(y*)LV#U&8h9$!48QD?2@zOsR(XH8S?D9e6k@7hzS~wto?&_;Y0_ +zO@~vS2vhyvh~X%4)4TOhDRBEjrPJ9t%|+dRkR(+fK!r*d+%sp%ihPd5U~#}Co(8;7 +zJwH>V&u?t}EggC`k7ihN(ION?*U3U)dVEQ@VY3zuVB3}BXika#m@0iUK$jokvJH5ExR +z+NDv({-FKMQ*R<`%bFBK<7cj^n4WB+Zbtaag#Pr#h-vSaNqNTLO_mv(byq3aO)gUO +z3WU8%C5wxNB*HHX@(zOfH?hzzG|x176ycTv;kK_TJNRZV;gS35W(~})8HajNgYvkZ +zCU%*ta;f<|-NKWl!UhIR$eb3_Xg}Hrf$ela0Ea#}P&&dE%79h@7dqcVh&W70)E6Ob +zGK{L%7n1@UFHck%RLAlcV2QB}xB{}%!|h6h?#fkuB!+RVVH%2k +zK*p5@%cHP^+!@x#OG3`(JAdBw^^z+6e5IP&yFtu6>q0k-5t%<*hyNFl!2}!0PQA%x-my6$C;UuB4mwBA8)N69i^5m^v3374 +zr%-G`)ValvauZY +zs4#M?Fzkbw^CqMPN(_Wx(lA}+V+=`>zoap=+&Lp3{#4(=ZX}b)UxIlUKA-A%ONQ`eZ%pw^Qwz$Q2h<(>?l}n +zTvKiwzSOjJw_3RlBvZ+|$?}e#5otbFM<68`rz%q@s-rSf#isUkDi78ILI7vA4x1(m(LnlstNT*SZR+688j=|bu$&ol +z%EpYTkEE)&a7&?K>-}mEs@V!3pE`UBY^MPVmvvzI>_!p7bvdqLaq*AQ{e0`Nr7dY{ +zZvK?ohOWr#*vi{bizwWV)47O^PRK6KQ +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 +z-Ge|H-z~;ce9VTj82eK27&vz?9-Tj1wh&VO +z>?oesAbOusecvVHlJQvbZ;_9A(V*lsvNTG*9p&N&>%f|mCsk(Gd{EyE^-ez_9R`Ro +zdoGx)i=9nP296WH1F~xepe*5>Z87rwV|t_+xJ=E27ia(s;u%))UUX__QD9XGD7HVk +zkJnBLJR-1bsE=2@*L33{BB#$OX*v#p0 +zM9ernup5~tY(?Z$@0(lZ#EJOfL%80!d3lHBa#VwcgEcH0-}`IlZ{JiOZ$}|eTsnxA +z<;7cPbeTVm+#81@2dvaOb{jcz?(_#uC>=Kc3YC~T;z^Xxgpw_$W@Z1m@VNPuB2d@8 +z)Y#B&e0Z?zPjl4l&r((Le5s*rJ$W=n#5$S*`e=i>GzE%D@KRKF5UjibN-)KW>Vh31 +z+bcgJG%{mIUlPS_8Zp}JPl5@@MH3@2G8N=@)4m?O=$RrEsMvGXfb7XH3qv^=eYtvMgMLyo~7gpbGkF +zl*vZSPv5Xj2>63YqW3QJM|BfhcQ`P4u+XN53%e<5&YXYp7X4+wb#F4heW3`IesJfR +zCvg@gQ`ul_zez}Joe<87mJ0{tJh4OgT-fUmyMg5F60VplZxX(`Ywr@iQiK#x9(fH| +zEvtehqASDA;~fv%UG-(gw*ZrcBK1>~M^yYbLNL~VBHdRX8H}dF-Q+R-YTClRx=Nss +zqjPbs`Qz44haIGFJdK01ey4Rd8dPD^l`3r&#n!BM?iRwDX@4QdNpvtei3lRs^F5r$ +zQf_C?d;5}Wv^ZGD8XebXZUVLdB+K)qd0q-{ms1dwDN~s6J`9J|(DSZO(?!G8Q?bh1 +z7(!Y@&VP1l;OWlyp-YMP&K`j-1=%HFskoLpKst%Z%^H*P*8>((v;QK>2jQFGUFEgn +zRKaJ|liBQ9(nE-pvV>M|NNU97kOsW6wa}tR%7PxyXlMd~gYKChm$DBFI=pv1uUk@8 +z=JLCzMx$Vf?KKim+l#jaltz&@M>K0ykL?=-=`t(`dWbT1wpZ-v*ecQ+{o)AT##pjN +zGGeby6=E6!J06sZgt1GBf^s`@(pD2{*hu5S8R|Eky~d1G0IY%I?~y>F2k9=~1sOqb +z^Ripp)~6&edVf@UaVSMhi^QTV0t*Yws(1vc7l;SyEAU&ai??FR@&R0#mkOt8DH5kB +z>^zvg#CCA;SN-But`$JxC%%f`{8E{`nP!#*wF6#8gX!S!{7LKHRd!PXXrmlxM)HfT +zhU>^xkLn%YWnou(v~b;CjHf+&66HeQOo3&M*Lm5*hfNP|<&5AhLPhEmc|ZyewEi8B +zg;kv6JfW%TjI*QB@0K_+yl~tD2IYc4CPM&oM|8vc;gbbeXzuyf@$a41A3JFkq8r$T96$`AmI=rj9QtO)g6eQD2qH3|aZ) +zekLY{YHL)G!4OG02nM73LsIZ{cqC7J2L*fe#C +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 +zxBFr0+ebmYVKg%t8SIc}LFjk!ES=-hd +z3g60wb7s$lW=Jf{iHn}*u;$Es!4hb>f{PhT1DsWGn7XTeymYoC-AtR8M>996KfyC3Uc0uq&=(I}#4cs_L +zB7B? +zAx(p@)UR#Ucp+X5^-B2Dj7NCMW`7pY)A8)(zZ`Z#lV9xJ +zpz3Z2Gg30d9^X>JSg{VV@?8XvV?;E@gkEB*AFoRSVnTOaI$jy(aP^L$yZL= +z1?upsb8*8_%VlARSEAhQ#cwmD^+{juHfW?ZNNlUm4RDSYx2u|OQ{sljImK^ +zBeH4s`)Kkjo%=9oOL@4?cSEc&;=7RkdLbQXW~Z5$tBl@oyTzyeYIR<^y*W6inWVB> +zm09egaG{XY2)O+j)$rXXl~2EcoR{ltT!Qo9Jm#F-=v6(bc`7$XM3|Nr!}3@VxIkQF1u1DG +zw(d0Y0dBuF{=t19`yz>W-vdG28RHn^0AGwN^rd-HNp_z+VM2Z#A|9{7{Etcp&MCE~ +ziNg3|yq+Ab*PXS{x^f*iT)aro2hm0(Fdgg3R1V&))IsL9r>gEP>UH|Q-ru22s7xP* +zcPe|Xx_>5T67@gdqm1sL6tv8=`%X$bc{F8^U`ZFcuK1_Gom*5X-j0g`FC2x5l5zS@LzC-vcMa{|K^Qn?w +zfds0#TH#d1pFExM9!`C%;$fB*bxuXrmF?bQrCC!?w7hl7ua_)!t(ciueXQnTql~(- +z*UJLW)>L{X`|MApycm@-K2WbK{=3W3KIK(sZrD2+7Dg3QaHEUh&V4h*bB!`LKMPgW +z_Zpv(G4kXd?(QZY@2<%pPUZ{B<#>}Cphj;PH_|-0Y#^ou^6%1*ZEzG13h~LgB3_-59z97r_y}@r_H!>U +zvzWNwQBty)^m?l%g!&|!{=7TjGsf5`Z+P69piliASF<4Lw5#=w+=Kx07FpP5%SzeD +zjQ35kZpArd0x#xyzwK&ywVA5Pxub7~L47{lZY1@4xw)}IeLF?MDBS=3TMFU^o&89C +zWh3<2ZLu94wP%@Of{d?{_m~5gWN# +z4HUFzx(zzBa5IqdRrzd%QKOUYM7V*mo&#z#&BY{Df>$gdPk#)(b@# +zHG=2(KSZ+PJx&GKlgY!v3 +zOy^yX86S9)eZ%O|iwf~{g!t&fhrO>#6DIjOr1YsoT_M!#*x)<7RQPsgC(RSish}{| +z@bzeHJ#0&GuL5p^O+K~|6OwL&ErZQ@YbxPHYk6zawrysu=NH=-654Ru%F;Va(b`?L%66bQCJo)r5A0)PP;ji2c3my&Ie(oWp+0jSg6a;Ub4x +zvX$dbPbtLxYd{l>JH*W7X;whRC$d{#HZGu!*mW%d5;6xDssPtQlpE{YfCtbAP(%xU^H1cu`c6AP{FP?#lvS9h#d6Ym> +z@KL228Oao!vTLN2jBq!S`GoZB>`d3AsCjOXyX2SCCN#SvJE8Ost@m#v!2M>a*79`; +z^|Q}NbnKaVOJl?$t1|0E!B()B@XA&7^6bDW?1VKK=g82k`UJj~hrJ;1lT-+=d`%;k +z;RWQ8H&GDZ`OY+az@07}!`2-;*UUJ +zwPOzJ!`W-2gmiRB`gdJeOo{e{7cG{d$o8KF%w;@&M>femDo5)g9eSppl@^x>dh7$E +zgNt)bbog=uDhKzhg6(?2Wr#!2tTjRzW%BW;E5p#jL(rre1{fL!Fm*j~IrHobhO+qi +z^a48Yz0ANjxD5Wv1_Nk^q>b2>*jCZ-@@4F#$1XT+*@T7M=Hc8ChtV-IYx*i8~!(WkaSn9T)U?H@7&!CnxYbj@v%Y +zv)@Fw?sqNjc%`pZNajAgUN05cAD16iJ$fM=bX?b-hNhY0jO3BniL +z22Rey^m9%N=l;(Igef`pw;I79Yx#J%l_79p;CC3Dv>mD8DU-B#{);Bu_tNdQfyB9% +zl26nkJ;IVa*8In-ZpoJdD7X{s8y16$A86P~=;E#U7MOw_yyHGIq2KoRr|B$KIH=_y +zp6!m)W@?Ve9>wBG2qdv2XC#q`C0!E%Gsae+;%o@w4=Ay6c?nP_lMBW$eKIAa~-?1>z_SAw&ey>dUe*}D#& +z4cfcnFZ1`b*?Ch1$5hpCXU_cjTFFjMP$JTZ8ONZG`RSDUI9=$ZcwalvafY +zLpuqFTH|R;!X!U!4b%MD1pil6N +zeCBl^yzlzH3wq>%(cC^4d-`(d)4)neepfPdT8GQ9#_EQ2zVs5DYe`Pr+uzlRwpfj`J{lGVegYp +zwQt+!wPDC+5LsdGi<+NsuKW@6$Vu~bn;jAJ;PQ?rZtnJQN9VzJu869ia48I$a53GW +zg_B0t&Cq7P%i4-qh>;^tF +z#>F<*t5M{M-R;d*B1mD+a~}pi6QdiV6$=vo)lsPPO%G0xJ;cs^Vrs$C?8w8Cbpl(c +zRM3i%T!6}lQ^7atm!PtfhNr_9s~ky?TpsHz}^$^nt(IZc%#zS3qi6^?($AL??JD3w^~Xby_KG?`7=M2^1K}m +zs9biiP9l9kZVvau9X@+=Msh!^uk;!z?|lzp1l^$SH#xn0=KFWMx3$_%N{~avR7-RR +zE$K~O^cL?p&q()l`Ym@LP!5UXS7T&$w)+rr|75Z^cPWK8sQKi6@yMjwA09GN@v)(w +z*N}aqpeL)y47?!qRhFD>VDLVlUZkp+PfeXH;Bta8qUOz7G>jb_QFENo;*4BWXO)dk +z54naYngAtnir5*Tqf#*%WuGgQY5+_gnlbtnrqNG`j&td`Qxv8--blp0>_v?3mBm(_ +zOp{uMmvSG1B_p8EEyb5U?w}Xpl>3Wm3AA74r)QMt*m{1Xeb +z0?(jd1NYcp+QEi(+z0!blO>ch_;wseGsgSJsg;F|#ihA5UDPby6o=JaKya^lI`$k# +zadJj}M)O_t3~#|N&&4R1c?~%Sb?web_hc^i#Y_28*%dA6riPAKDO7q@?NQZx*0>$d +z;F99<&R|Ul@-dv!*d6gxxsrPY$2!`+$A!wgbeCWY8_63mR-|&$n4E?V`faYAl1fXg +z$v>W~l_xLbbC%4>4=SaC%p-+q-1K;gPHNg&!fOQ_+C^?fidZ%Q%SOEA4EKrxybFl* +z1W;hg%)gt$Jn6|e>*q#2t$a%6a40{&&6hE%^_B_G)Ql@?o)6ERe5)TJ^UYl7R2_%0 +zw5S6dJV^?{CF^FdH)rQ}OOwnBv!0X4zFYiELEaR2!?Xa9vl}#qE)C{dYvf&-)#T3IZqI|0*;i>z0cw|k6`QS*Q~da>H-S5H +zU11!bY~QRJnszKV$>X@2ih@2T2VRzxfY#uY0*+Ee?YQ=)6c#h$eez;1bhjU-C0x=d +z3sE+!bE)SUkdN|fe8E>IJ?Mh@9_poX$?)3uscD!ttK&h1F& +zm66D_m1{c+b<2lu(eXw3UUxvLI(6?8y&Ph923GGzZjhc!JN7D70hiKv2Z$aYwRf6d +zKFpvrS*~yUtR!xkB{%8fGb@QQMZHUQC`1h)=5fTij*0l6`Ar=RLr#O@#!qfNYU`jOKfHC(eE96# +zw{ATg?l8Hri!Ph0g{jTqPJZ(%XL4OG5qz5@-$n#Ma^F(&;#wcY_Oqp@J3{ut%4`^K +zBCVsON|OiU+fj;;qo-N=2P%?MnvlgP-xG9=Jz1IQj1^MB`s9WHIGcJG7?Oo%#a? +z9_skJs%B+!h+=8S3zDjyX)X8$?Kvcyg&Telp|oQQJqt4nksorm^abUb70QjF6LTyeGn +z3G+&m?u&2o%;pyz_<4Sjw$zh0(f1Un8` +zE4l>)aFTaQe|WH|R}g0o{|_7i@vlepAkInga6UpT=gl=id@q+(jb_!In+lbaC!Gau +zgcsd&&@z`fYp9;I2NhHNkV9Nz675R!Z+fRvK5z@#rIkVQKJ6WNn#b68YJ}RK%^grg +zcjGUr;ook(`ibVv7>+Yy1Rj0vzYiZ)ZJE7H${&!GP2MeDR}_Ajm7c;JUleVC71H#C +zGI4l}iJabE;vWCFbfDN>oQk*zd_SUF+MJ_#s17&gS4|_$6+vm4!~g^}zNqJ9wwxa29Z`99~kJSOnBB{T9f_mH?8Hg<|{RTSvG8lF4r$z!g@f`8eFJ_vnF00Yp6N5 +zCSM(YsA^pDb@j(J6klR=4a_hsT*h=w$zZl+zt}70iE-Oq_dwW)(i^nfV!!$QT>j>o +z*?YO?cI)LqNWX33{k3xM@ixL6DXRy658)dBO8hDBjq!uylh7~lGkkJa?gsz1@R|9I +z{LSM-=>z(c^Aqe7^^?^v=rgo)*yWp+vq`(oP<%~v2q>>+Dn;UjST7k|U?rRuKftV*+9G$|*q#B!)XIxE_yk8^r +zvIpvzmQH6jqTv{uPLDp+@AylbP;Hp?hO}ANHtF}iYO~HoQfvN8-<9S9U{b4#i;*X) +zN+bo6%ZZu&LJV43@bbrqVnD5J88+lX(7k}(6@?ed*%{*lMsU^O@-E_t?~pHKB5!x5 +z06kOOco5o|}xx#I|Z3uxnH@R +zO+WQN{prq-AE5FvdZP`t7;mC^B=+$xKN$%WbS1epnNT@HH*xn&MB +z69zqY|1d$=$a)OR^d`WEYf&b|2w3jPSSI;j95eR<~IfBHxe6U>v@v$-o?Mwk){DYff)?*j=YNTtn{bskD0LbRBTaS-7`X*SOe5F-R{N=uv0n6s#qadJi*F}B|;U-AF2jRAtAryaK +z+<=CEB2Ji+e^^cklYd;Um%|rLE_nCZ!xwMl8T}0=wX1VaPbfrQJWR>}60{^(XKC9P +zK-QD3860JwN_2q9V{5n7xZb@UYh3L*2L +z5UTR32SG$_8Wj%>lL!1C&4Uarjlgf+kUvK`u7g$e;sh5e +z1)4Y(YeP>CneEqBY4ee11)1%`+<>VQ>Lt_GSbx>{wXXTFLhhEbJG^?X8B%4&-TGMHDrBv-(lWL7G)W}-H +ztPZ$V>68JR@~V!@Jp^BycgDdT@o~e#ZMSBy)?az}{v`W`#+SO;ZMW-o?e*l-79O|1 +z`>f;*&>P9xpS(tYE`4MDkpAErvA^ED*}UbyaeMN5^Z7vkAp8vfjQI@m8~GgmjMFnD +z4>5+yjWMU6>6c)XLK)@IAP^sAbWAUcpLeWDr@~LE-PhJ2Mjs({Y}Te!8?ATDSR-H` +zrgi+iMmYbvHTZ)Z^u`#=gDJxsgBag59$|N{^qU7I_A@#6b0Ol5T+Ut=$#WsYjWF#H +zLOlupT;!WP$8*lYUKkOOCgewv^ev)&&Y`#wJ|995{ef>O=Sva#CJ%8VT)pSTm3SFJ +zyg3{378&#=#q*r}?S?vHPc3n%l4H2CX{fSkxRT_D-m#2t0nBqU$_+JM&69GCJH3WC +zmWH=l&6BP1>9O(Y`tSnt(1KTd`6CJSrKoDAq^d8jhKF6v&FS#SYkcyifa=E2vNn7T +z55Jll?BNjz;3W}NzWA~?)0!JWN7z~B +z`H8UK`wXeuC4S53jZ?V|^NiGyUMW)9o?^H4`w6WBZndp9-J5;0cXQ|U8N@dne|zu= +z$~Q7=`|#=T?Q5kO{`Ce?QhyXM!^}K?5qS)M6#;D0a}Rl$%N&VeB!ol!;<{brI-q6p?HD3CxTDuM{6R>qHbT^i@yk{KrSJ{G-SLvti&3u +z1Pcg>EeJ_k;PnFRl{vh7-4`CsuXyEO;uiGB>OhSC(CW{^S6Lt|0jG}csR|s?`^$?9 +z9I*)$Ars7DBDUZnwtym@e1&uY3vK}sS_jF&^Ou(sC_*Qg!$xdDMmzz9yax+@0TFr! +z$pP`75)d#)BuM%S2?rh=>QBA)D}HFngp{fM>pMt{kX$zB5i!!HPsDFRN|F!39XePf +zV&dunZsXtK8UhW)siMYSh*|#D&)0m2SmaTU!VNc1UyP++0zw+Qdc5?vL94C+>e*jm +zI=TY+s}Lb+2pq8a!W$qY6jT+vsf**2m5-#TtVvNj5+k3|44HH!e+8f*Jrb8N!wZIU +zjS*aOh5Zhz0**BVU4<*s2;D($pKq-oxE|eBx~SiwARVeqn+i^a3@vmxciUPST54c|qLU*kc_i}8O~XK)DTB5=vlW0dQ*{z~iUF97Q=6pI6TOF<^_ +zZMcCc?&|^Nln=qonO?*Q{!GQymtt}1;z2#7C-aq!Pn*3L7rc{EXl>x!8)|Zj5ceGe +zDmmCpL8@hrXI$n;cpZs-D1k`tDGHQ`FU(sGGc*`?;5gq}cQ6aCDQF@~0>unqZ1kzs +zO;w=m82xzY>i|5o1ngB^W&G-?lgKlx#;^e6j@v}w1G|zeNUs +z`jJyFTUo{96-wRpHGF<~yj5}GZCuF|M!nfm^MpXTOm(EQo1lz^lksb=fNz}O)mZlS +z5B?dhcbW2aU3_u3wDpZMdis+6Wj2Bt2?pC}7<@+a;vxO&GqfL>)aiz30E{`n`eu!?YFU&`ieb*yN0Mrx@5C;rHVkk3|!y)A7_U~^Qiit +z2M)Ks$Lb+nBE)a{A1*(Po%NZVYj{n@4x*^M{gF4iaaa@(dzreU-93#3dbf`lQa@pf +z^$Y3~KtnVKcJyIyzTQqlt5=;?rN4WF0uW8K#!Fju4w_Y897$g;Y8e7l$0PfRFi0zf +zAk4=uMo!d`ubTs44h;IWNPF^oP80c6(oD|-$Np6E>~>tvjw|9Y$1SuvlNNlo%le56 +zM)^#YwfZ*m-7&p7UdV2c33YoOlxev=PfA?;@^Ij)qcT!H&pu$>ged_LE@mal8u%0D +zg8^UIKqD(K9(j9dh_k+AfToIf9Q8of6?dni^uq +zMVLq(F(yKcW#Bw&plOE`$v;e_GmRK0mzh7oGHt7fNJ^OO$55n{6iasi;1P6~YO2P* +zXXEo{17lEZkh4zNuaJWK#dSu%+E;!{IcbUa4$6(d{LCscbn@sL(~ZL2>E^`Hp85hx +zHhNvGl1J-a0L}m>2_Z~bDO>Boaed*3U-34?}lgLY72TF#o@9BctXB`=5 +z#wXMkTahM>j~QKGPw28p)v}UM@N^#c2GGwv5Xjq}s~^1c)QuUGN9s(j6Q;uSKX$Dk +zn$cRmUqTed#U+dJer3|(nS$d3(6G1BeGD$0&blIYS@vL6Y34}fDAx2$R53)hw6%GK +zcWQSnI#C?rp%BPj-{vHb_-WkpD(g;yAG$UVl}`~8?$vTvWtzx+{-ksipIHUwotPJj +zj}N!;hN3X2mN((`bxNcenb%_`ZbFhVnrG7Eih|3BTdPENIy_2ruUh|Sjg4iPopKG# +z)*o)T5j$t~j8co1Pe2xAJ3MuBS1DYhu?DfB(vtj#(&zc<>DfhYCBB|=v&pfU1zZ#9X@f5RAEVC +zl66N$Qn4H>2-om;FIL|}UBSXR!DYY6`DDCO1w^s_bde2grbocATCVde+T)=Ywl!_6 +z>S%imN$JTL&zCXmHHdQn8ST5p)dJtOzclO7Lbyv>FMG&wKTo{!oSEYI;e2s28Yy>1 +z4%G=MJ)*bjJcu`n?7-GV+|~E6F;qI;5ZKOpZRGIBJh_bh{Q2(TjXS1d!y?W;adVa+ +zw7hZiVDz*D2fy}uU$!jum!>gBhEv$=xiRXmE8UdBH%nMXfHe6VXx?C!mC4>7MD1C8 +z&6cYZ;UU5~>rXV-6$^WPWxj;*o5zq^?3s7H$oG-!j<|DGq){tNk)oS|yy^aTx~IdY +z72}YBM~zh^7oYy)qWJEfS?sCY_ciOQw6bn@5|T +zSAMmhpw-)IiEkfUuyzdlIJwOup>YJy@a(K#FP$}O*JZxh_Rigo9&u;Fkmb2C8i=3R +z2gtmWUm)ukMe8~2mje_>0(WJ{i+BJzIRV^LT +z_+@7zgt!U=e6T?UL9v}&P;pgi%4$kVV$0HUuzrz%M|pq9v~Bv4X<)B}A=O>O=B)eg +z;qRZDf6dFLYgD<*$fNgtcjh;-PaqB2wFrSu;58f`t6?G%KM9|9Z*E6;QBW<@m}zg? +z`elElTbuc5D6eu=cBe0MAb_?Qk$Z6qb7?59O>S)P!Q-$Dc|I7r3{h%#sniU7y`-Ow +z*5P2rt`i<+C*QHL9)*SM8;7_4m%`=1$f~5SHaTnUpXnDfCp46`*DJ+xgE+}gGz;~m +z8wYOl3(6I>huYX4%0cI#%3gZ`wNeElwXM;NW`XPZpRx)udC!5(+IwiYPKa +zl8$oLrY{V)X>I;=ZV}rE-&xl4h{cl3*x9J3eP15S)>eDe&EZ+7vm-2b%cE@hB|;{qG+gzoI@BLw4{#CN7#S0<=?-=c%CjM`Vd@bP3-+R>7~uw +zILEO5Y4IMeem{PeRH)U0H%@nC&zYCWnST)x?u$~FM5OLQLQmUhGYCwhRY&d)Wv2#w +zlEV|@VRQEn7has6PM6^!(TM{|vG65d4T;9!><%!eWH)uV>3?6)a89S;xw+ejw2u-M +ziije%w$eG2zWBy~{>Ec-eKg~`!diJXxid*y-p!`I+?EADFgjJz+Nc_jwZU&jmW_+cfgQz%KD>|!FH!p=OF_`b9=YCz%1$* +zPe+H1yW&$-C!2}OpHqnA)wkyBtpKzdoQTpwUpSU)=NOP18crI*!grrK1pNwp9A&F! +zON3J;4yr72?Ax~Z*HtPccy#aVylm7_NQb!ll53cyuH>jf3UUbo&a*WC^iPK3L=wBT +z-%P9n7(zO|3znFgZ+2`9BkzDOSSMVPRiIJPdsw!!CITc(Adi?eSEApypTKMjVA^nk +z>J3p{y4%y(*_D^11an^`g?5ELsumVCjVsiKami4BTj=%_n?E^0&eF^{;WpgC-au-u +zfZQrJO)Pw9VEm2BqPdDo9L%z+k`+tM&$|9|lk$En;?pg`@wb`0w$`8atrUaGRrq*z +z@z8P7@j{$iiwHOk;OYz$I;#D#Qc?VKPacDhHHL+ztkE+Qx5d2RACl~_DYKO@QcMd~ +zCgSNDlj%fwE>ZIBStNWul9xBUR*0^TU86LCLh +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 +zGNjK!X9#i_z +zWGcegg4rD{B8E+zl`vFfki;Z}tpFrHiLw+%B#cRzdeC!XB7v>>4d^g8a%RrOV2r^6 +zR$mFcPf=@wG@WCR!VHN~1d0wy7z(!_VY0-C09F?zj{MsW%=;3TVg&Gr=u}{z5HmgA +z#1k$e#*mjgJpgG+!qlP>+WH4L2rO0iFB=$$%M*qmO_P|Yfaum2V<1iijQzF#259|; +z*e(%}l+gLc{DQt7ojQOjGRGeHtEKn_oiRpVjA*n^%_f3NBM`Ho%&cv!%(U%7X;ijE +zi%krfrN1N55#HM7Q@}3K5Q2NBRGHqTA1-$uRTfZAY)Nn;I2Il-5_Lo_z!vZijRi` +z;PBP1b9&^gJ^Vx$MS2Xg0~%eQ2M0R(mbZ53bQ9#y9YgIvYJ1X(p7|#5#T~BbZguTA +zYshXtVN*$J}FG2v2yOTZcj?67R9Up0b4Vd3~ruhBpH +z`7hYwYt4<4n3ymMfM6mbP6dXOAqwFOx=l2j7#uKUI?avh7%eeSfr$z`F9rxr^E>*# +zSi%w$&GY-4W#<^Eu->EC#ISc;2&k~Osgdo1&%favM|Yd(;RCQr8>sh5`0#F-fh2rV`-$~@q|fFg5eW+}|S +zN-0mNfmitaslR4}6DK4rNEq)i|8)ltH9$9a57`E@1^&|q0Q-l8Aqis^RwN+cUjBN= +z}SEPrj( +zA25+gVuHplh>jFf0^Yp;F-R(jZqYK)h&p3oR9d +z-`VHAh-!Gz8qI(R)KHMHEI>e1LY8ZMAp${i933^M8Wqd3gw%$70WQL&QCmu(GQ}9g +zvS?)LGSdsa*?jlKX?4%{v(~KnYy3y=_Ib`Z&w2LVpY!Z<_V@SvcSGAp%I!P;aQ>=m +zmkpnE+gC>xFMVUU-t6$ +zlh3`Fc;pXu-Jv(Xm +zoR#Njs6P3VeJjscd&;BJhs|C!XYCnRZn|>kkZJ3NUir-tUq1f_?T>xwgh%(z-@j_e +z&Vi53EcY*e_u4^6Z`rW3&+lix=a*X!-?#LoeXB=TZ~WtPgO=@{e&UL^Rwpi-aoA0p +zI{IyyF4=)(z?n0Szo~P3b)0?x=HE+a-O}|}#?35p0ys~S}`Xl~fZ}{l7C(O&gu~|@k@#5iKyBF`e_VXI8o!?#G +z_Rr$!vd8AVqifIHUDqF2KWO!y!*{J-*4;6r^T|a6&Rul=j>q=Cf7H^CAL#dmuFG%# +z+d8J5=_MIEHX3uQ8>fn&~d}+js=N@d|_@xiN5T9rF-}<}Xw)#Az$J)Ke{9*aV +z?()^njRzk*Hll8T9@#{`I}VmtCp`6u +znRndywSU{U|F~5*3KdW9p7Pe)w|AX7>*3@BJ;!g0T{O-FKZuMQzbR7XJLlbTs +zL!;-kNS=Kc?O1#ElIO3#^4B-T=e`v;cYfvk8%74r7V(nA^;2h`teIxQ%E4WKHF~g6 +zt4B9Iq3b*+hlzu7{n@6O;X7wd8>`dCKi~Gsu+e5- +zWVNI9y}`MLz}tpi@usb(&We97kGCm40)&H;fB&rwSIrroUikF;_leoQ)Y+wARQ>cb@q9 +z8AmM~KV|mP5#2}L77k3Fy=>09*MDo<&s%%*|6Fj%&a{r1UJ5RcL +z^V4_C>i58h9tqD+-hcfUb{^Ab?_s~(eC@tfhlcF+^G<#Irt^NXe#NWR>z2*zICA&Y +zex1`#T>ej0-zVqwyQxc?%(m?ryXf$To|!-Jnr~0(`u2)9RVRFT&xcoT`C0Y)dv-ta +zRM<87qbo00DZ1^`>yI6z2fXWE?0jm}N9MPWIOE<8%ZAOX7e4UJX9ixe=^I^V9Dn^Q +z^WNR{&MSv>KC!;fZ}yHJ_1Qk%ts$E)U(|2) +z=9Mpg=jzE%&6{%I$m8zOqY?!mBjX&m5p)cFxL3 +z<3-Wzmm}{Se8_C$wl&wR{&Ls2aXpxx@tR$}a`E6}WpLj$?K^4>qzNl`j1!LD^!>9w +z7Kf$=O!4@(hpw4FX~57GZ5yAz<%P4RJvs6>haP6T$DPpAIBBPb;9-VqmT +zl<7fx=#rZ|&-&QMT5rB%%vWD|bluDS$K1K=L!)Qh_b=!Cbl}_})7G!)bL4l|{OsNZ +zPv7^8(HAUwaLHHB`u=HCo>}v+_dGpl$gnRi{@(rr3vRjO+}nle0}r#U!M8a +zJAZV|8{R(P=O6v}h%inbM +zxn{yWe|r7pyZ$g1*H0HMm~}~8-&S1Wto83h|0GrDDDphbJL3QQpGK{-#(z5I{<$p) +zg|%fZt%Wx1iqhJWP;0@pw_TDInY9(QmTnt%Rc>~n6&HJZ+vRy}*IZ=5uBDVjQ^Pk& +z(O}+W#x8tVr_LR^R~qAX`T9c>)h{iU54hp53N?#yr)5LBfKrM{-R-2 +z+VPTB(Hw(81EkqELQ+_t3`u48IfTT|5z>~OH)N@|m6=^js7h-~TP<%(<0GV5 +z>TPA#oFhV7*&G(Kmd$k`^D!8*tkoQsAuIfzW_4lrG!Mbs(%joLNi<{2%lKZZcf5I> +zSX?(n#>01Sx +zPeYa3+#V_gY`!o)>Q>&or>XjG^S-2oCXUAO^q$b}X<9m0(=z1E`83rnXx^)|REKGv +zqxAVIYvtDevX)+2Hhi;I&nwkleJE>bvNO9nZ;rPtNsRHrpyeY=@}kL}ysDGtxXg8* +zo7b1u!QzeBYWfz5v#f}dT_cV{+;5(vP?v1p(;_VkZ>ubqMV{2noa^*;O +ztxuLQ>5XeHQ}ue&mgTLk +z)1*0OY8f{3QP*YB$Vbx3T4}>BY1Q`3l_V{@2T7vG&c=C@M1!UguSROpj3d!AL-Rf- +zL1%7WU(k@TwmdZFI!$V!*(Z}w=4tc#BF-CQOOtrf99xR4)nreS3f+zIk)*o!jhw4Z +z5752)n%c@HSM{iD{U8yIEH*va+WjkANs|kLYMM1;(|F68`K@$I8{;FXGR$ +zv!2mRm(-2p>5(vLjs>;ZGp5?|=KP{ILA3XILra)xT%X2D?0?O=QI`#EIkXkfrVn)* +zb*O$27usrX6U)q3eb?K()=gA%x*f!!x!vs`4$Ylz2XSb8H0^Zzq0Qq68msQ>aRk*B +zZs&0X%}s9SaRk-QZU=FwKbxJNMZFE;NFWZ?R_+UNsFrj)h(q(U+d&-a_hzRt=xq>3 +zfH*XVxi7?_wHCL7I8=AL9mJve!0hxa;B63xIPG>2hiXK(gE+)ww}Ut|H<_K*0K5(2 +z(7fw*5Qpk>w}Ut|XS*H5A^y4@#Gz+fvlBnO4dT$Vx7$G+;+xw+9D06sJBUMdl-X&m +z#oHhbJwLl0#Gz+Vw}UuTL%1EpQ9vB38_ieiNZtlQ6!1K5s=Ew6m;@X_q0nbz5d8%he_k}os +z=Wz|*eLWxX`QGgy4n04c9q>E_o~K%8a9@Z6c%G`>a$kr;?-JY&;?Nq3*#XbBm;rVW +z2k<=A8ik(&;!thsb`Xc^Jhy{5faj^!C(RdluEkuigE;gq!H)-VXdT_{AP&`jW(Pb^ +zf#+!s`2e1$dgtKhfH<_q<8}~-))U#`N)9hTETZ;;JFr&!4Bd8o@Y>>XTb9e>hrkPXZH$t9^d)9 +z9pnS*^9*>N0nan2&-F48&I|bfp2xLoyJp~drnOSHgM0wbGpNtC_z%Z}IDqHzeXU&! +z@H_*aXTWnU*2D3jUjffEsLwOtc?R{lUUv9-f#(_UJOiF*!1D}voHJkOv$&w%F{@H~FwVAlsc&!9fffae+T +zTrY;;95BwIKF@&X8Sp#N0ng)iPF##`he#-@LVs;-4}SC1JC1k4|e~6=Q;2^zQ=Z7hy!>YzjJe6hy!?@ +z1J85dc@Fh?4m^)vY}&N|&vRIBkMCjK7vcb(=fLwEc%B2#b69WBf#*5!JO`fV!1Ek< +zo&(Qw;CT)_R|)F(3V5Ca&-F$bd|{je&-Fp8`vT8%;CT)_kKX`U&VlDS@H~FA?#%Fh8j*T;ik2lFoQTwi5@FT?>nkKb`yK485)ejnSkD}d((@Vo$?7r=9U +zED7iEI11o-{FcP8&*$Cvy`$Ly&n034cAk#{cwPX{z2xfamf1Q@dv1c>(o#0X#2&=lXET&jCCyfaeA9TwfW&@gNT1c>z4v*NAXD$OqKt +z1@OE8o@?WTp96Sa0M85Hc>z2xfaeA9JbssJIR~EW>r1eMIDqHzn^`{xj1S;>+~?rF +zkPqN_0X#2&=lby4&jCCyfam&16MSKu!+N{ER0Uti2k<=Z1G4)9Jl6-ZU? +zthX1y^8$FTjX-b??^oKaWp?_~654!xl)&>6cwRz%UINcc;CTu4xi&xe^#RYd@d@l8 +z4&ZqSJTHOgCDi97@Vtcjyab+?!1EG#9`_M6`%noy*G4a}^ZBX-p2xj-eh%+fanF?5 +z0nba|dHgoneSLhyZ~Wa3;sBoOD}V5XIDqH+%HMr~=Oyqw?ya(G2A-F|^AdPo0?$j} +zdHi#*f#=%r0=^Ij@H~F+?dSD*w*;P-P@k8;b8TMoa{$ldeiFMD;CTr=*G>%Z +zg*brcCGfn2`n&|5m%#H9c&^P_etl4%m%#H9cwPd}OW=9jt7Z2Tcpmr3xgF#KcpmqC +zx-aAdcwPd}wOa;`2XO$;OW=74JTHOgCDi97@Vo?`m%#H9cwRz%UIEW5;CTi0xpooR +zz0xisX!Cqj!1D@tUIEXwdDzbZJgb +zjt4xifaewPyaJwU116jU;sBmkP@h-8^9p!g0naPod6bK_djLGIpgymF=N0f=8&2UI +z(64~!74W##03hMKylVI@z&nw`01w4;? +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 +z^xvw2r-mJhXA9BQ+9S8bLL +zwOPMXo5i6v%ZJ*mUunxc#Npq=$qwT1^>*1o9L{suK^$J6%MRjjo@<*w#NqY1>>v*3 +zx$Gbg=eg`44(GY-AP(obqzNDn=eg`44zJH;2XQ#hWe0IM&t(U3IL{@g0CD(wyX+ti +z=eg`44(GY-AP%q3We0IM&m{o?aX8Oq2XQ#hWe0J1eJ(qQ!+9<{h{Jg<*$Rlm*V|?$JBY)1E<1?Bc`kVnh{NBX +z%MRjjp34s6aGuK!;_&)hb`Xd2T#_abhu7z_gE*Y$vV%CB=dy!1oaeHGIDqG%4;Mfm +zPHi3s=)=j*;{bg)*?AnG4<|d11N7k}9pm``eK^@c9KiDgc%A^yK_5=%@aGcHhm)N@ +zmq;w9`7TfrIR1Q<0M8TPIq1Xbc>a6^`f##?IDqG%4=0Hphy!@8jr1Nb@Er8vbPk9E +zcn>wY&bA5mSzK{>#xn4YjFXRJwt`~{!3p@vXxB&WaYJ)g{=b#TKUx)*Eu7zN~X5hIN +zBf$>x0X)}&6Zk?tfajnOCpj|Dhl*W0hl)vP^Eg!GfSr$XJ$!?m$DxNpu=9NAVa4r$ +z=K?0!K^(wyO^Vhl0R2Yoml58?ox +z2jDsA!%5~2`W4jY0eBvO=b#U#b3i_T=K**Q`f$3+PTqCtn!nP@jW7oP1%vg8Cfv;q-_J;{$jO`f&1veg!;Fp*{zFI2{k-fchNt;q+Jx +zaX@_z`f&1vIDqG%4<}z3AHeez>hlzM4*GB*h58)y;baGKKz*J9&p{tf$Af$T&r{$z +z=)eq+?Vt}AGT=Gr!^sZv0XzqNIQc?8fajnOr==Fi2k;#9;p7YX +z0G@+BoO~f4z;n=tlP}~0cnEc-(dc#(aoOsz~3p;f8Iwp>M|J+M1>xiFd^!zdQf>A|1W?VL2 +zi(vYl^7MUK`MxMJI98kQ>ejeoOg(1w|86m@WAx~@zLzhYv0&k%1+y+`>#ONVU%I#T +zJ>`^f=Z*b*)Afz~(1KZ4b{x8_ky9tmx@6MAIr=l+yT+wUSx-NF@!F;T +EH{2!8L;wH) + +literal 0 +HcmV?d00001 + +diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx.h b/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx.h +new file mode 100755 +index 0000000..d5d34ca +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx.h +@@ -0,0 +1,52 @@ ++/** ++ * Copyright (C) 2007 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmdlHdmiTx.h ++ * ++ * \version $Revision: 1 $ ++ * ++ * \date $Date: 02/08/07 08:32 $ ++ * ++ * \brief devlib driver component API for the TDA998x HDMI Transmitters ++ * ++ * \section refs Reference Documents ++ * HDMI Tx Driver - FRS.doc, ++ * HDMI Tx Driver - tmdlHdmiTx - SCS.doc ++ * ++ * \section info Change Information ++ * ++ * \verbatim ++ ++ $History: tmdlHdmiTx.h $ ++ * ++ * ***************** Version 13 ***************** ++ * User: Demoment Date: 02/08/07 Time: 08:32 ++ * Updated in $/Source/tmdlHdmiTx/inc ++ * initial version ++ * ++ ++ \endverbatim ++ * ++*/ ++ ++#ifndef TMDLHDMITX_H ++#define TMDLHDMITX_H ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++#include "tmNxCompId.h" ++#include "tmdlHdmiTx_Types.h" ++#include "tmdlHdmiTx_Functions.h" ++ ++ ++#endif /* TMDLHDMITX_H */ ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ ++ +diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Functions.h b/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Functions.h +new file mode 100755 +index 0000000..050645d +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Functions.h +@@ -0,0 +1,1806 @@ ++/** ++ * Copyright (C) 2007 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmdlHdmiTx_Functions.h ++ * ++ * \version $Revision: 1 $ ++ * ++ * \date $Date: 02/08/07 8:32 $ ++ * ++ * \brief devlib driver component API for the TDA998x HDMI Transmitters ++ * ++ * \section refs Reference Documents ++ * HDMI Tx Driver - FRS.doc, ++ * HDMI Tx Driver - tmdlHdmiTx - SCS.doc ++ * ++ * \section info Change Information ++ * ++ * \verbatim ++ ++ $History: tmdlHdmiTx_Functions.h $ ++ * ++ * ***************** Version 1 ***************** ++ * User: Demoment Date: 02/08/07 Time: 8:32 ++ * Updated in $/Source/tmdlHdmiTx/inc ++ * initial version ++ * ++ ++ \endverbatim ++ * ++*/ ++ ++#ifndef TMDLHDMITX_FUNCTIONS_H ++#define TMDLHDMITX_FUNCTIONS_H ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#include "tmNxTypes.h" ++#include "tmdlHdmiTx_Types.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*============================================================================*/ ++/* EXTERN FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++ ++/*****************************************************************************/ ++/** ++ \brief Get the software version of the driver. ++ ++ \param pSWVersion Pointer to the version structure. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetSWVersion ++( ++ tmSWVersion_t *pSWVersion ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Get the number of available HDMI transmitters devices in the system. ++ A unit directly represents a physical device. ++ ++ \param pUnitCount Pointer to the number of available units. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetNumberOfUnits ++( ++ UInt32 *pUnitCount ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Get the capabilities of unit 0. Capabilities are stored into a ++ dedicated structure and are directly read from the HW device. ++ ++ \param pCapabilities Pointer to the capabilities structure. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetCapabilities ++( ++ tmdlHdmiTxCapabilities_t *pCapabilities ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Get the capabilities of a specific unit. Capabilities are stored ++ into a dedicated structure and are directly read from the HW ++ device. ++ ++ \param unit Unit to be probed. ++ \param pCapabilities Pointer to the capabilities structure. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetCapabilitiesM ++( ++ tmUnitSelect_t unit, ++ tmdlHdmiTxCapabilities_t *pCapabilities ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Open unit 0 of HdmiTx driver and provides the instance number to ++ the caller. Note that one unit of HdmiTx represents one physical ++ HDMI transmitter and that only one instance per unit can be opened. ++ ++ \param pInstance Pointer to the variable that will receive the instance ++ identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or ++ the transmitter instance is not initialised ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_RESOURCE_OWNED: the resource is already in use ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMDL_ERR_DLHDMITX_INIT_FAILED: the unit instance is already ++ initialised or something wrong happened at lower level. ++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: the unit is not initialized ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMBSL_ERR_HDMI_INIT_FAILED: the unit instance is already ++ initialised ++ - TMBSL_ERR_HDMI_COMPATIBILITY: the driver is not compatiable ++ with the internal device version code ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxOpen ++( ++ tmInstance_t *pInstance ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Open a specific unit of HdmiTx driver and provides the instance ++ number to the caller. Note that one unit of HdmiTx represents one ++ physical HDMI transmitter and that only one instance per unit can be ++ opened. This function switches driver's state machine to ++ "initialized" state. ++ ++ \param pInstance Pointer to the structure that will receive the instance ++ identifier. ++ \param unit Unit number to be opened. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or ++ the transmitter instance is not initialised ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_RESOURCE_OWNED: the resource is already in use ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMDL_ERR_DLHDMITX_INIT_FAILED: the unit instance is already ++ initialised or something wrong happened at lower level. ++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: the unit is not initialized ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMBSL_ERR_HDMI_INIT_FAILED: the unit instance is already ++ initialised ++ - TMBSL_ERR_HDMI_COMPATIBILITY: the driver is not compatiable ++ with the internal device version code ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxOpenM ++( ++ tmInstance_t *pInstance, ++ tmUnitSelect_t unit ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Close an instance of HdmiTx driver. ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxClose ++( ++ tmInstance_t instance ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Set the power state of an instance of the HDMI transmitter. ++ ++ \param instance Instance identifier. ++ \param powerState Power state to set. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetPowerState ++( ++ tmInstance_t instance, ++ tmPowerState_t powerState ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Get the power state of an instance of the HDMI transmitter. ++ ++ \param instance Instance identifier. ++ \param pPowerState Pointer to the power state. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetPowerState ++( ++ tmInstance_t instance, ++ tmPowerState_t *pPowerState ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Set the configuration of instance attributes. This function is ++ required by DVP architecture rules but actually does nothing in this ++ driver ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxInstanceConfig ++( ++ tmInstance_t instance ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Setup the instance with its configuration parameters. This function ++ allows basic instance configuration like enabling HDCP, choosing ++ HDCP encryption mode or enabling HDCP repeater mode. ++ ++ \param instance Instance identifier. ++ \param pSetupInfo Pointer to the structure containing all setup parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxInstanceSetup ++( ++ tmInstance_t instance, ++ tmdlHdmiTxInstanceSetupInfo_t *pSetupInfo ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Get instance setup parameters. ++ ++ \param instance Instance identifier. ++ \param pSetupInfo Pointer to the structure that will receive setup ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetInstanceSetup ++( ++ tmInstance_t instance, ++ tmdlHdmiTxInstanceSetupInfo_t *pSetupInfo ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Make device library handle an incoming interrupt. This function is ++ used by application to tell the device library that the hardware ++ sent an interrupt. ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMITX_FULL: the queue is full ++ ++ ******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxHandleInterrupt ++( ++ tmInstance_t instance ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Register event callbacks. Only one callback is registered through ++ this API. This callback will received the type of event that ++ occured throug a dedicated parameter and will be called as many ++ times as there is pending events. ++ This function is synchronous. ++ This function is ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pCallback Pointer to the callback function that will handle events ++ from the devlib. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxRegisterCallbacks ++( ++ tmInstance_t instance, ++ ptmdlHdmiTxCallback_t pCallback ++); ++ ++/*****************************************************************************/ ++/** ++ \brief This function allows enabling a specific event. By default, all ++ events are disabled, except input lock. ++ ++ \param instance Instance identifier. ++ \param event Event to enable. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxEnableEvent ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEvent_t event ++); ++ ++/*****************************************************************************/ ++/** ++ \brief This function allows disabling a specific event. By default, all ++ events are disabled, except input lock. ++ ++ \param instance Instance identifier. ++ \param event Event to disable. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxDisableEvent ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEvent_t event ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Get specifications of a given video format. Application can use ++ this function to retreives all specifications (frequencies, ++ resolution, etc.) of a given IA/CEA 861-D video format. ++ This function is synchronous. ++ This function is ISR friendly. ++ ++ \param instance Instance identifier. ++ \param resolutionID ID of the resolution to retrieve specs from. ++ \param pResolutionSpecs Pointer to the structure receiving specs. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN: the resolution is unknown ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetVideoFormatSpecs ++( ++ tmInstance_t instance, ++ tmdlHdmiTxVidFmt_t resolutionID, ++ tmdlHdmiTxVidFmtSpecs_t *pResolutionSpecs ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Configures all input and output parameters : format, modes, rates, ++ etc. This is the main configuration function of the driver. Here ++ are transmitted all crucial input and output parameters of the ++ device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param videoInputConfig Configuration of the input video. ++ \param videoOutputConfig Configuration of the output video. ++ \param audioInputConfig Configuration of the input audio. ++ \param sinkType Type of sink connected to the output of the Tx. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetInputOutput ++( ++ tmInstance_t instance, ++ tmdlHdmiTxVideoInConfig_t videoInputConfig, ++ tmdlHdmiTxVideoOutConfig_t videoOutputConfig, ++ tmdlHdmiTxAudioInConfig_t audioInputConfig, ++ tmdlHdmiTxSinkType_t sinkType ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Configures audio input parameters : format, rate, etc. ++ This function is similar to tmdlHdmiTxSetInputOutput except that ++ video is not reconfigured. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param audioInputConfig Configuration of the input audio. ++ \param sinkType Type of sink connected to the output of the Tx. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetAudioInput ++( ++ tmInstance_t instance, ++ tmdlHdmiTxAudioInConfig_t audioInputConfig, ++ tmdlHdmiTxSinkType_t sinkType ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Defines the content of AVI infoframe to be sent by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pAviIfData Pointer to the structure containing AVI infoframe ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetVideoInfoframe ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxAviIfData_t *pAviIfData ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Defines the content of AUD infoframe to be sent by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pAudIfData Pointer to the structure containing AUD infoframe ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetAudioInfoframe ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxAudIfData_t *pAudIfData ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Defines the content of the audio content protection packet to be ++ sent by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pAcpPktData Pointer to the structure containing ACP infoframe ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetACPPacket ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxAcpPktData_t *pAcpPktData ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Defines the content of the General Control packet to be sent by Tx ++ device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pGcpPktData Pointer to the structure containing GCP packet parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetGeneralControlPacket ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxGcpPktData_t *pGcpPktData ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Defines the content of ISRC1 packet to be sent by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pIsrc1PktData Pointer to the structure containing GCP packet parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetISRC1Packet ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxIsrc1PktData_t *pIsrc1PktData ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Defines the content of ISRC2 packet to be sent by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pIsrc2PktData Pointer to the structure containing GCP packet parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetISRC2Packet ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxIsrc2PktData_t *pIsrc2PktData ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Defines the content of MPS infoframe to be sent by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pMpsIfData Pointer to the structure containing MPS infoframe ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetMPSInfoframe ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxMpsIfData_t *pMpsIfData ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Defines the content of SPD infoframe to be sent by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pSpdIfData Pointer to the structure containing SPD infoframe ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetSpdInfoframe ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxSpdIfData_t *pSpdIfData ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Defines the content of VS infoframe to be sent by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pVsIfData Pointer to the structure containing VS infoframe ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetVsInfoframe ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxVsPktData_t *pVsIfData ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Enables/disables NULL packet sending (only used for debug purpose). ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable packet insertion. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxDebugSetNullPacket ++( ++ tmInstance_t instance, ++ Bool enable ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Send one single NULL packet (only used for debug purpose). ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxDebugSetSingleNullPacket ++( ++ tmInstance_t instance ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Set the audio output mute status. This function can be used to mute ++ audio output, without muting video. This can be typically used when ++ reconfiguring the audio HW after a sample rate change. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param muteStatus Mute status (True/False). ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetAudioMute ++( ++ tmInstance_t instance, ++ Bool audioMute ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Reset audio CTS. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxResetAudioCts ++( ++ tmInstance_t instance ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Retrieve EDID Status from driver. ++ This function is synchronous. ++ This function is ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pEdidStatus Pointer to the array that will receive the EDID Status. ++ \param pEdidBlkCount Pointer to the integer that will receive the number of ++ read EDID block. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidStatus ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidStatus_t *pEdidStatus, ++ UInt8 *pEdidBlkCount ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Retrieves audio descriptors from receiver's EDID. This function ++ parses the EDID of Tx device to get the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ ++ \param instance Instance identifier. ++ \param pAudioDescs Pointer to the array that will receive audio ++ descriptors. ++ \param maxAudioDescs Size of the array. ++ \param pWrittenAudioDescs Pointer to the integer that will receive the actual ++ number of written descriptors. ++ \param pAudioFlags Pointer to the byte to receive Audio Capabilities Flags. ++ This byte is filled as such: ++ b7 is the Basic audio bit from CEA Extension Version 3. ++ If this bit is set to 1 this means that the sink handles "Basic audio" i.e. ++ two channel L-PCM audio at sample rates of 32kHz, 44.1kHz, and 48kHz. ++ b6 is the Supports_AI bit from the VSDB ++ This bit set to 1 if the sink supports at least one function that uses ++ information carried by the ACP, ISRC1, or ISRC2 packets. ++ b5-b0 0 ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidAudioCaps ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidAudioDesc_t *pAudioDescs, ++ UInt maxAudioDescs, ++ UInt *pWrittenAudioDescs, ++ UInt8 *pAudioFlags ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Retrieves supported video formats (short descriptors) from ++ receiver's EDID. This function parses the EDID of Rx device to get ++ the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pVideoDesc Pointer to the structure that will receive short ++ video descriptors. ++ \param maxVideoFormats Size of the array. ++ \param pWrittenVideoFormats Pointer to the integer that will receive the actual ++ number of written descriptors. ++ \param pVideoFlags Pointer to the byte to receive Video Capability Flags. ++ b7: underscan supported ++ b6: YCbCr 4:4:4 supported ++ b5: YCbCr 4:2:2 supported ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidVideoCaps ++( ++ tmInstance_t instance, ++ tmdlHdmiTxShortVidDesc_t *pVideoDesc, ++ UInt maxVideoFormats, ++ UInt *pWrittenVideoFormats, ++ UInt8 *pVideoFlags ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Retrieves supported video formats (short descriptors) from ++ receiver's EDID. This function parses the EDID of Rx device to get ++ the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pNativeVideoFormat Pointer to the array that will receive video ++ timing descriptor. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidVideoPreferred ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidVideoTimings_t *pNativeVideoFormat ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Retrieves the sink type from receiver's EDID (HDMI or DVI). This ++ function parses the EDID of Rx device to get the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pSinkType Pointer to the array that will receive sink type. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available ++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMDL_ERR_DLHDMITX_NOT_INITIALIZED: the transmitter is not initialized ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidSinkType ++( ++ tmInstance_t instance, ++ tmdlHdmiTxSinkType_t *pSinkType ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Retrieves source address from receivers's EDID. This ++ function parses the EDID of Rx device to get the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pSourceAddress Pointer to the integer that will receive the EDID source ++ address. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidSourceAddress ++( ++ tmInstance_t instance, ++ UInt16 *pSourceAddress ++); ++ ++ ++ ++/*****************************************************************************/ ++/** ++ \brief Retreives KSV list received by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pKsv Pointer to the array that will receive the KSV list. ++ \param maxKsv Maximum number of KSV that the array can store. ++ \param pWrittenKsv Actual number of KSV written into the array. ++ \param pDepth Connection tree depth. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetKsvList ++( ++ tmInstance_t instance, ++ UInt8 *pKsv, ++ UInt8 maxKsv, ++ UInt8 *pWrittenKsv, ++ UInt8 *pDepth, ++ Bool *pMaxCascExd, ++ Bool *pMaxDevsExd ++); ++#ifdef HDMI_TX_REPEATER_ISR_MODE ++/****************************************************************************** ++ \brief Retreives HDCP depth received by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pDepth Connection tree depth returned with KSV list. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetDepth( ++ tmInstance_t instance, ++ UInt8 *pDepth ++); ++ ++/****************************************************************************** ++ \brief Generate SHA_1 interrupt if not occured. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGeneSHA_1_IT ++( ++ tmInstance_t instance ++); ++#endif /* HDMI_TX_REPEATER_ISR_MODE */ ++/*****************************************************************************/ ++/** ++ \brief Enable/Disable HDCP encryption. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param hdcpEnable HDCP On/Off (true = On, False = Off). ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN: the resolution is unknown ++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetHdcp ++( ++ tmInstance_t instance, ++ Bool hdcpEnable ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Get the driver HDCP state. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pHdcpCheckState Pointer to the integer that will receive the HDCP check state. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetHdcpState ++( ++ tmInstance_t instance, ++ tmdlHdmiTxHdcpCheck_t *pHdcpCheckState ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Check the result of an HDCP encryption attempt, called at ++ intervals (set by timeSinceLastCall) after tmdlHdmiTxSetHdcp(true). ++ This API must be used only in case of No Operating System. if OS, ++ this is manage internally of this device library. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param timeSinceLastCall Time passed in milliseconds since last call, ++ must be shorter than 600 ms. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxHdcpCheck ++( ++ tmInstance_t instance, ++ UInt16 timeSinceLastCall ++); ++ ++/*****************************************************************************/ ++/** ++ \brief This function loads a gamut metadata packet into the HW. HW will ++ actually send it at the beginning of next VS, during the vertical ++ blanking. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable gamut metadata packet insertion. ++ \param pGamutData Pointer to the structure containing gamut metadata ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetGamutPacket ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxGamutData_t *pGamutData ++); ++ ++/*****************************************************************************/ ++/** ++ \brief This function set the extended colorimetry with one of the following ++ extended colorimetries(bits EC2-0): xvYCC601, xvYCC709, sYCC601, ++ AdobeYCC601, AdobeRGB. When the parameter extendedColorimetry is ++ xvYCC601 or xvYCC70, this function calls the API tmdlHdmiTxSetGamutPacket ++ to send Gamut Packet Data that does not exist for all other types of ++ extended colorimetries for which pointer pGamutData can be set to NULL. ++ This function also allows to set YCC Quantization Range (YQ1-0) ++ ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/Disable extended colorimetry. ++ \param extendedColorimetry value of the extended colorimetry (bits EC2 EC1 EC0). ++ \param yccQR YCC quantisation range ++ \param pGamutData Pointer to the structure containing gamut metadata ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong ++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter was out of range ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetExtendedColorimetry ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxExtColorimetry_t extendedColorimetry, ++ tmdlHdmiTxYCCQR_t yccQR, ++ tmdlHdmiTxGamutData_t *pGamutData ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Retrieves supported detailled video descriptors from ++ receiver's EDID. This function parses the EDID of Rx device to get ++ the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pDTDescriptors Pointer to the array that will receive detailled ++ timing descriptors. ++ \param maxDTDesc Size of the array. ++ \param pWrittenDesc Pointer to the integer that will receive the actual ++ number of written descriptors. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidDetailledTimingDescriptors ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors, ++ UInt8 maxDTDesc, ++ UInt8 *pWrittenDTDesc ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Retrieves supported monitor descriptor from receiver's EDID. ++ This function parses the EDID of Rx device to get ++ the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pEdidFirstMD Pointer to the array that will receive the first monitor ++ descriptors. ++ \param pEdidSecondMD Pointer to the array that will receive the second monitor ++ descriptors. ++ \param pEdidOtherMD Pointer to the array that will receive the other monitor ++ descriptors. ++ \param maxOtherMD Size of the array. ++ \param pWrittenOtherMD Pointer to the integer that will receive the actual ++ number of written descriptors. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidMonitorDescriptors ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidFirstMD_t *pEdidFirstMD, ++ tmdlHdmiTxEdidSecondMD_t *pEdidSecondMD, ++ tmdlHdmiTxEdidOtherMD_t *pEdidOtherMD, ++ UInt8 maxOtherMD, ++ UInt8 *pWrittenOtherMD ++); ++ ++/*****************************************************************************/ ++/** ++ \brief Retrieves TV picture ratio from receiver's EDID. ++ This function parses the EDID of Rx device to get ++ the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pEdidTvPictureRatio Pointer to the variable that will receive TV picture ratio ++ value. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidTVPictureRatio ++( ++ tmInstance_t instance, ++ tmdlHdmiTxPictAspectRatio_t *pEdidTvPictureRatio ++); ++ ++/****************************************************************************** ++ \brief This function set the revocation list use for HDCP ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param listPtr Pointer on revocation list provide by application. ++ \param length length of revocation list. ++ ++ \return The call result: ++ - TM_OK: the call was successful, however RX keys have ++ not been checked with provided revocation list ++ because they are not available. ++ - TMDL_DLHDMITX_HDCP_SECURE: the call was successful, RX keys are secure ++ - TMDL_DLHDMITX_HDCP_NOT_SECURE: the call was successful, RX keys are NOT secure ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: we are a repeater ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++ ++******************************************************************************/ ++ ++tmErrorCode_t tmdlHdmiTxSetHDCPRevocationList( ++ tmInstance_t instance, ++ void *listPtr, ++ UInt32 length ++); ++ ++ ++/*****************************************************************************/ ++/** ++ \brief Retreives current HDCP link status. This function is typically used ++ when an "HDCP INACTIVE" event is received to know why HDCP ++ is INACTIVE. ++ ++ \param instance Instance identifier. ++ \param pHdcpStatus Pointer to the enum describing the status. ++ \param pRawStatus Pointer to the byte with the raw error code from HW. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMDL_ERR_DLHDMITX_NOT_INITIALIZED: the transmitter is not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetHdcpFailStatus ++( ++ tmInstance_t instance, ++ tmdlHdmiTxHdcpStatus_t *pHdcpStatus, ++ UInt8 *pRawStatus ++); ++ ++ ++/*****************************************************************************/ ++/** ++ \brief Retrieves latency information from receiver's EDID. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ ++ \param instance Instance identifier. ++ \param pLatency Pointer to the data structure that receive latency ++ information. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidLatencyInfo ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidLatency_t *pLatency ++); ++ ++ ++/****************************************************************************** ++ \brief Retrieves additional data from receiver's EDID VSDB. This function ++ parses the EDID of Rx device to get the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pExtraVsdbData Pointer to the structure of additional VSDB data ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidExtraVsdbData ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidExtraVsdbData_t **pExtraVsdbData ++); ++ ++ ++/****************************************************************************** ++ \brief This function set the B... screen ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful, however RX keys have ++ not been checked with provided revocation list ++ because they are not available. ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ ++ ++******************************************************************************/ ++ ++tmErrorCode_t tmdlHdmiTxSetBScreen( ++ tmInstance_t instance, ++ tmdlHdmiTxTestPattern_t pattern ++); ++ ++/****************************************************************************** ++ \brief This function set the Remove B.... screen ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful, however RX keys have ++ not been checked with provided revocation list ++ because they are not available. ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ ++ ++******************************************************************************/ ++ ++tmErrorCode_t tmdlHdmiTxRemoveBScreen( ++ tmInstance_t instance ++); ++ ++/****************************************************************************** ++ \brief This function Convert DTD to CEA ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pDTDescriptors Pointer on one DTD ++ \return The call result: ++ - CEA code ++ ++ ++******************************************************************************/ ++tmdlHdmiTxVidFmt_t tmdlHdmiTxConvertDTDtoCEA ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors ++); ++ ++ ++/*****************************************************************************/ ++/** ++ \brief Retrieve HPD status from driver. ++ This function is synchronous. ++ This function is ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pHPDStatus Pointer to the variable that will receive the HPD Status. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetHPDStatus ++( ++ tmInstance_t instance, ++ tmdlHdmiTxHotPlug_t * pHPDStatus ++); ++ ++ ++/*****************************************************************************/ ++/** ++ \brief Retrieve RXSense status from driver. ++ This function is synchronous. ++ This function is ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pRXSenseStatus Pointer to the variable that will receive the RXSense Status. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetRXSenseStatus ++( ++ tmInstance_t instance, ++ tmdlHdmiTxRxSense_t * pRXSenseStatus ++); ++ ++ ++/****************************************************************************** ++ \brief Mute or unmute the TMDS outputs. ++ ++ \param instance Instance identifier. ++ \param muteTmdsOut Mute or unmute indication. ++ ++ \return NA. ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxTmdsSetOutputsMute ++( ++ tmInstance_t instance, ++ Bool muteTmdsOut ++); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMDLHDMITX_FUNCTIONS_H */ ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ ++ +diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h b/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h +new file mode 100755 +index 0000000..f090ce2 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h +@@ -0,0 +1,1066 @@ ++/** ++ * Copyright (C) 2007 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmdlHdmiTx_Types.h ++ * ++ * \version $Revision: 1 $ ++ * ++ * \date $Date: 02/08/07 08:32 $ ++ * ++ * \brief devlib driver component API for the TDA998x HDMI Transmitters ++ * ++ * \section refs Reference Documents ++ * HDMI Tx Driver - FRS.doc, ++ * HDMI Tx Driver - tmdlHdmiTx - SCS.doc ++ * ++ * \section info Change Information ++ * ++ * \verbatim ++ ++ $History: tmdlHdmiTx_Types.h $ ++ * ++ * ***************** Version 1 ***************** ++ * User: Demoment Date: 02/08/07 Time: 08:32 ++ * Updated in $/Source/tmdlHdmiTx/inc ++ * initial version ++ ++ \endverbatim ++ * ++*/ ++ ++#ifndef TMDLHDMITX_TYPES_H ++#define TMDLHDMITX_TYPES_H ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++ ++#include "tmNxTypes.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*============================================================================*/ ++/* MACRO DEFINITIONS */ ++/*============================================================================*/ ++ ++/*============================================================================*/ ++/* DEFINES */ ++/*============================================================================*/ ++ ++/**< Error Codes */ ++#define TMDL_ERR_DLHDMITX_BASE CID_DL_HDMITX ++#define TMDL_ERR_DLHDMITX_COMP (TMDL_ERR_DLHDMITX_BASE | TM_ERR_COMP_UNIQUE_START) ++ ++#define TMDL_ERR_DLHDMITX_COMPATIBILITY (TMDL_ERR_DLHDMITX_BASE + TM_ERR_COMPATIBILITY) /**< SW Interface compatibility */ ++#define TMDL_ERR_DLHDMITX_MAJOR_VERSION (TMDL_ERR_DLHDMITX_BASE + TM_ERR_MAJOR_VERSION) /**< SW Major Version error */ ++#define TMDL_ERR_DLHDMITX_COMP_VERSION (TMDL_ERR_DLHDMITX_BASE + TM_ERR_COMP_VERSION) /**< SW component version error */ ++#define TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER (TMDL_ERR_DLHDMITX_BASE + TM_ERR_BAD_UNIT_NUMBER) /**< Invalid device unit number */ ++#define TMDL_ERR_DLHDMITX_BAD_INSTANCE (TMDL_ERR_DLHDMITX_BASE + TM_ERR_BAD_INSTANCE) /**< Bad input instance value */ ++#define TMDL_ERR_DLHDMITX_BAD_HANDLE (TMDL_ERR_DLHDMITX_BASE + TM_ERR_BAD_HANDLE) /**< Bad input handle */ ++#define TMDL_ERR_DLHDMITX_BAD_PARAMETER (TMDL_ERR_DLHDMITX_BASE + TM_ERR_BAD_PARAMETER) /**< Invalid input parameter */ ++#define TMDL_ERR_DLHDMITX_NO_RESOURCES (TMDL_ERR_DLHDMITX_BASE + TM_ERR_NO_RESOURCES) /**< Resource is not available */ ++#define TMDL_ERR_DLHDMITX_RESOURCE_OWNED (TMDL_ERR_DLHDMITX_BASE + TM_ERR_RESOURCE_OWNED) /**< Resource is already in use */ ++#define TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED (TMDL_ERR_DLHDMITX_BASE + TM_ERR_RESOURCE_NOT_OWNED) /**< Caller does not own resource */ ++#define TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS (TMDL_ERR_DLHDMITX_BASE + TM_ERR_INCONSISTENT_PARAMS) /**< Inconsistent input params */ ++#define TMDL_ERR_DLHDMITX_NOT_INITIALIZED (TMDL_ERR_DLHDMITX_BASE + TM_ERR_NOT_INITIALIZED) /**< Component is not initialized */ ++#define TMDL_ERR_DLHDMITX_NOT_SUPPORTED (TMDL_ERR_DLHDMITX_BASE + TM_ERR_NOT_SUPPORTED) /**< Function is not supported */ ++#define TMDL_ERR_DLHDMITX_INIT_FAILED (TMDL_ERR_DLHDMITX_BASE + TM_ERR_INIT_FAILED) /**< Initialization failed */ ++#define TMDL_ERR_DLHDMITX_BUSY (TMDL_ERR_DLHDMITX_BASE + TM_ERR_BUSY) /**< Component is busy */ ++#define TMDL_ERR_DLHDMITX_I2C_READ (TMDL_ERR_DLHDMITX_BASE + TM_ERR_READ) /**< Read error */ ++#define TMDL_ERR_DLHDMITX_I2C_WRITE (TMDL_ERR_DLHDMITX_BASE + TM_ERR_WRITE) /**< Write error */ ++#define TMDL_ERR_DLHDMITX_FULL (TMDL_ERR_DLHDMITX_BASE + TM_ERR_FULL) /**< Queue is full */ ++#define TMDL_ERR_DLHDMITX_NOT_STARTED (TMDL_ERR_DLHDMITX_BASE + TM_ERR_NOT_STARTED) /**< Function is not started */ ++#define TMDL_ERR_DLHDMITX_ALREADY_STARTED (TMDL_ERR_DLHDMITX_BASE + TM_ERR_ALREADY_STARTED) /**< Function is already started */ ++#define TMDL_ERR_DLHDMITX_ASSERTION (TMDL_ERR_DLHDMITX_BASE + TM_ERR_ASSERTION) /**< Assertion failure */ ++#define TMDL_ERR_DLHDMITX_INVALID_STATE (TMDL_ERR_DLHDMITX_BASE + TM_ERR_INVALID_STATE) /**< Invalid state for function */ ++#define TMDL_ERR_DLHDMITX_OPERATION_NOT_PERMITTED (TMDL_ERR_DLHDMITX_BASE + TM_ERR_OPERATION_NOT_PERMITTED) /**< Corresponds to posix EPERM */ ++#define TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN (TMDL_ERR_DLHDMITX_BASE + TM_ERR_BAD_FORMAT) /**< Bad format */ ++ ++#define TMDL_DLHDMITX_HDCP_SECURE (TMDL_ERR_DLHDMITX_COMP + 0x0001) /**< Revocation list is secure */ ++#define TMDL_DLHDMITX_HDCP_NOT_SECURE (TMDL_ERR_DLHDMITX_COMP + 0x0002) /**< Revocation list is NOT secure */ ++ ++ ++/*============================================================================*/ ++/* ENUM OR TYPE DEFINITIONS */ ++/*============================================================================*/ ++ ++/** ++ * \brief Enum listing all events that can be signalled to application ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_HDCP_ACTIVE = 0, /**< HDCP encryption status switched to active */ ++ TMDL_HDMITX_HDCP_INACTIVE = 1, /**< HDCP encryption status switched to inactive */ ++ TMDL_HDMITX_HPD_ACTIVE = 2, /**< Hotplug status switched to active */ ++ TMDL_HDMITX_HPD_INACTIVE = 3, /**< Hotplug status switched to inactive */ ++ TMDL_HDMITX_RX_KEYS_RECEIVED = 4, /**< Receiver(s) key(s) received */ ++ TMDL_HDMITX_RX_DEVICE_ACTIVE = 5, /**< Rx device is connected and active */ ++ TMDL_HDMITX_RX_DEVICE_INACTIVE = 6, /**< Rx device is connected but inactive (standby) */ ++ TMDL_HDMITX_EDID_RECEIVED = 7, /**< EDID has been received */ ++ TMDL_HDMITX_VS_RPT_RECEIVED = 8, /**< VS interrupt has been received */ ++#ifdef HDMI_TX_REPEATER_ISR_MODE ++ TMDL_HDMITX_B_STATUS = 9, /**< TX received BStatus */ ++#endif /* HDMI_TX_REPEATER_ISR_MODE */ ++ TMDL_HDMITX_DEBUG_EVENT_1 = 10 /**< This is a debug event */ ++} tmdlHdmiTxEvent_t; ++ ++/** ++ * \brief Enum listing all available event status ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_EVENT_ENABLED, /**< Event is enabled */ ++ TMDL_HDMITX_EVENT_DISABLED /**< Event is disabled */ ++} tmdlHdmiTxEventStatus_t; ++ ++/** ++ * \brief Callback function pointer type, used to allow driver to callback ++ application when activity status is changing at input. ++ * \param Event Identifier of the source event. ++ */ ++typedef void (*ptmdlHdmiTxCallback_t) (tmdlHdmiTxEvent_t event); ++ ++/** ++ * \brief Enum listing all supported device versions ++ */ ++ typedef enum ++ { ++ TMDL_HDMITX_DEVICE_UNKNOWN, /**< HW device is unknown */ ++ TMDL_HDMITX_DEVICE_TDA9984, /**< HW device is IC TDA9984 */ ++ TMDL_HDMITX_DEVICE_TDA9989, /**< HW device is IC TDA9989 */ ++ TMDL_HDMITX_DEVICE_TDA9981, /**< HW device is IC TDA9981 */ ++ TMDL_HDMITX_DEVICE_TDA9983, /**< HW device is IC TDA9983 */ ++ TMDL_HDMITX_DEVICE_TDA19989, /**< HW device is IC TDA19989 */ ++ TMDL_HDMITX_DEVICE_TDA19988 /**< ok, u got it, it's a TDA19988 */ ++ } tmdlHdmiTxDeviceVersion_t; ++ ++/** ++ * \brief Enum defining the supported HDMI standard version ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_HDMI_VERSION_UNKNOWN, /**< Unknown */ ++ TMDL_HDMITX_HDMI_VERSION_1_1, /**< HDMI 1.1 */ ++ TMDL_HDMITX_HDMI_VERSION_1_2a, /**< HDMI 1.2a */ ++ TMDL_HDMITX_HDMI_VERSION_1_3a /**< HDMI 1.3 */ ++} tmdlHdmiTxHdmiVersion_t; ++ ++/** ++ * \brief Enum listing all color depth (8 bits/color, 10 bits/color, etc.) ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_COLORDEPTH_24 = 0, /**< 8 bits per color */ ++ TMDL_HDMITX_COLORDEPTH_30 = 1, /**< 10 bits per color */ ++ TMDL_HDMITX_COLORDEPTH_36 = 2, /**< 12 bits per color */ ++ TMDL_HDMITX_COLORDEPTH_48 = 3 /**< 16 bits per color */ ++} tmdlHdmiTxColorDepth_t; ++ ++/** ++ * \brief Enum defining the EDID Status ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_EDID_READ = 0, /**< All blocks read OK */ ++ TMDL_HDMITX_EDID_READ_INCOMPLETE = 1, /**< All blocks read OK but buffer too small to return all of them */ ++ TMDL_HDMITX_EDID_ERROR_CHK_BLOCK_0 = 2, /**< Block 0 checksum error */ ++ TMDL_HDMITX_EDID_ERROR_CHK = 3, /**< Block 0 OK, checksum error in one or more other blocks */ ++ TMDL_HDMITX_EDID_NOT_READ = 4, /**< EDID not read */ ++ TMDL_HDMITX_EDID_STATUS_INVALID = 5 /**< Invalid */ ++} tmdlHdmiTxEdidStatus_t; ++ ++/** ++ * \brief Structure defining the supported audio packets ++ */ ++typedef struct ++{ ++ Bool HBR; /**< High Bitrate Audio packet */ ++ Bool DST; /**< Direct Stream Transport audio packet */ ++ Bool oneBitAudio; /**< One Bit Audio sample packet */ ++} tmdlHdmiTxAudioPacket_t; ++ ++/** ++ * \brief Enum listing all possible audio input formats ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_AFMT_SPDIF = 0, /**< SPDIF */ ++ TMDL_HDMITX_AFMT_I2S = 1, /**< I2S */ ++ TMDL_HDMITX_AFMT_OBA = 2, /**< One bit audio / DSD */ ++ TMDL_HDMITX_AFMT_DST = 3, /**< DST */ ++ TMDL_HDMITX_AFMT_HBR = 4 /**< HBR */ ++} tmdlHdmiTxAudioFormat_t; ++ ++/** ++ * \brief Enum listing all possible audio input sample rates ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_AFS_32K = 0, /**< 32kHz */ ++ TMDL_HDMITX_AFS_44K = 1, /**< 44.1kHz */ ++ TMDL_HDMITX_AFS_48K = 2, /**< 48kHz */ ++ TMDL_HDMITX_AFS_88K = 3, /**< 88.2kHz */ ++ TMDL_HDMITX_AFS_96K = 4, /**< 96kHz */ ++ TMDL_HDMITX_AFS_176K = 5, /**< 176.4kHz */ ++ TMDL_HDMITX_AFS_192K = 6 /**< 192kHz */ ++} tmdlHdmiTxAudioRate_t; ++ ++/** ++ * \brief Enum listing all possible audio input sample rates ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_I2SQ_16BITS = 16, /**< 16 bits */ ++ TMDL_HDMITX_I2SQ_32BITS = 32, /**< 32 bits */ ++ TMDL_HDMITX_I2SQ_OTHERS = 0 /**< for SPDIF and DSD */ ++} tmdlHdmiTxAudioI2SQualifier_t; ++ ++/** ++ * \brief Enum listing all possible audio I2S formats ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_I2SFOR_PHILIPS_L = 0, /**< Philips like format */ ++ TMDL_HDMITX_I2SFOR_OTH_L = 2, /**< Other non Philips left justified */ ++ TMDL_HDMITX_I2SFOR_OTH_R = 3, /**< Other non Philips right justified */ ++ TMDL_HDMITX_I2SFOR_INVALID = 4 /**< Invalid format */ ++} tmdlHdmiTxAudioI2SFormat_t; ++ ++/** ++ * \brief Enum listing all possible DST data transfer rates ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_DSTRATE_SINGLE = 0, /**< Single transfer rate */ ++ TMDL_HDMITX_DSTRATE_DOUBLE = 1 /**< Double data rate */ ++} tmdlHdmiTxDstRate_t; ++ ++/** ++ * \brief Structure describing unit capabilities ++ */ ++typedef struct ++{ ++ tmdlHdmiTxDeviceVersion_t deviceVersion; /**< HW device version */ ++ tmdlHdmiTxHdmiVersion_t hdmiVersion; /**< Supported HDMI standard version */ ++ tmdlHdmiTxAudioPacket_t audioPacket; /**< Supported audio packets */ ++ tmdlHdmiTxColorDepth_t colorDepth; /**< Supported color depth */ ++ Bool hdcp; /**< Supported Hdcp encryption (True/False) */ ++ Bool scaler; /**< Supported scaler (True/False) */ ++} tmdlHdmiTxCapabilities_t; ++ ++/** ++ * \brief Structure gathering all instance setup parameters ++ */ ++typedef struct ++{ ++ Bool simplayHd; /**< Enable simplayHD support */ ++ Bool repeaterEnable; /**< Enable repeater mode */ ++ UInt8 *pEdidBuffer; /**< Pointer to raw EDID data */ ++ UInt32 edidBufferSize; /**< Size of buffer for raw EDID data */ ++} tmdlHdmiTxInstanceSetupInfo_t; ++ ++/** ++ * \brief Enum listing all IA/CEA 861-D video formats ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_VFMT_NULL = 0, /**< Not a valid format... */ ++ TMDL_HDMITX_VFMT_NO_CHANGE = 0, /**< ...or no change required */ ++ TMDL_HDMITX_VFMT_MIN = 1, /**< Lowest valid format */ ++ TMDL_HDMITX_VFMT_TV_MIN = 1, /**< Lowest valid TV format */ ++ TMDL_HDMITX_VFMT_01_640x480p_60Hz = 1, /**< Format 01 640 x 480p 60Hz */ ++ TMDL_HDMITX_VFMT_02_720x480p_60Hz = 2, /**< Format 02 720 x 480p 60Hz */ ++ TMDL_HDMITX_VFMT_03_720x480p_60Hz = 3, /**< Format 03 720 x 480p 60Hz */ ++ TMDL_HDMITX_VFMT_04_1280x720p_60Hz = 4, /**< Format 04 1280 x 720p 60Hz */ ++ TMDL_HDMITX_VFMT_05_1920x1080i_60Hz = 5, /**< Format 05 1920 x 1080i 60Hz */ ++ TMDL_HDMITX_VFMT_06_720x480i_60Hz = 6, /**< Format 06 720 x 480i 60Hz */ ++ TMDL_HDMITX_VFMT_07_720x480i_60Hz = 7, /**< Format 07 720 x 480i 60Hz */ ++ TMDL_HDMITX_VFMT_08_720x240p_60Hz = 8, /**< Format 08 720 x 240p 60Hz */ ++ TMDL_HDMITX_VFMT_09_720x240p_60Hz = 9, /**< Format 09 720 x 240p 60Hz */ ++ TMDL_HDMITX_VFMT_10_720x480i_60Hz = 10, /**< Format 10 720 x 480i 60Hz */ ++ TMDL_HDMITX_VFMT_11_720x480i_60Hz = 11, /**< Format 11 720 x 480i 60Hz */ ++ TMDL_HDMITX_VFMT_12_720x240p_60Hz = 12, /**< Format 12 720 x 240p 60Hz */ ++ TMDL_HDMITX_VFMT_13_720x240p_60Hz = 13, /**< Format 13 720 x 240p 60Hz */ ++ TMDL_HDMITX_VFMT_14_1440x480p_60Hz = 14, /**< Format 14 1440 x 480p 60Hz */ ++ TMDL_HDMITX_VFMT_15_1440x480p_60Hz = 15, /**< Format 15 1440 x 480p 60Hz */ ++ TMDL_HDMITX_VFMT_16_1920x1080p_60Hz = 16, /**< Format 16 1920 x 1080p 60Hz */ ++ TMDL_HDMITX_VFMT_17_720x576p_50Hz = 17, /**< Format 17 720 x 576p 50Hz */ ++ TMDL_HDMITX_VFMT_18_720x576p_50Hz = 18, /**< Format 18 720 x 576p 50Hz */ ++ TMDL_HDMITX_VFMT_19_1280x720p_50Hz = 19, /**< Format 19 1280 x 720p 50Hz */ ++ TMDL_HDMITX_VFMT_20_1920x1080i_50Hz = 20, /**< Format 20 1920 x 1080i 50Hz */ ++ TMDL_HDMITX_VFMT_21_720x576i_50Hz = 21, /**< Format 21 720 x 576i 50Hz */ ++ TMDL_HDMITX_VFMT_22_720x576i_50Hz = 22, /**< Format 22 720 x 576i 50Hz */ ++ TMDL_HDMITX_VFMT_23_720x288p_50Hz = 23, /**< Format 23 720 x 288p 50Hz */ ++ TMDL_HDMITX_VFMT_24_720x288p_50Hz = 24, /**< Format 24 720 x 288p 50Hz */ ++ TMDL_HDMITX_VFMT_25_720x576i_50Hz = 25, /**< Format 25 720 x 576i 50Hz */ ++ TMDL_HDMITX_VFMT_26_720x576i_50Hz = 26, /**< Format 26 720 x 576i 50Hz */ ++ TMDL_HDMITX_VFMT_27_720x288p_50Hz = 27, /**< Format 27 720 x 288p 50Hz */ ++ TMDL_HDMITX_VFMT_28_720x288p_50Hz = 28, /**< Format 28 720 x 288p 50Hz */ ++ TMDL_HDMITX_VFMT_29_1440x576p_50Hz = 29, /**< Format 29 1440 x 576p 50Hz */ ++ TMDL_HDMITX_VFMT_30_1440x576p_50Hz = 30, /**< Format 30 1440 x 576p 50Hz */ ++ TMDL_HDMITX_VFMT_31_1920x1080p_50Hz = 31, /**< Format 31 1920 x 1080p 50Hz */ ++ TMDL_HDMITX_VFMT_32_1920x1080p_24Hz = 32, /**< Format 32 1920 x 1080p 24Hz */ ++ TMDL_HDMITX_VFMT_33_1920x1080p_25Hz = 33, /**< Format 33 1920 x 1080p 25Hz */ ++ TMDL_HDMITX_VFMT_34_1920x1080p_30Hz = 34, /**< Format 34 1920 x 1080p 30Hz */ ++ TMDL_HDMITX_VFMT_35_2880x480p_60Hz = 35, /**< Format 35 2880 x 480p 60Hz 4:3 */ ++ TMDL_HDMITX_VFMT_36_2880x480p_60Hz = 36, /**< Format 36 2880 x 480p 60Hz 16:9 */ ++ TMDL_HDMITX_VFMT_37_2880x576p_50Hz = 37, /**< Format 37 2880 x 576p 50Hz 4:3 */ ++ TMDL_HDMITX_VFMT_38_2880x576p_50Hz = 38, /**< Format 38 2880 x 576p 50Hz 16:9 */ ++ ++ TMDL_HDMITX_VFMT_INDEX_60_1280x720p_24Hz = 39,/**< Index of HDMITX_VFMT_60_1280x720p_24Hz */ ++ TMDL_HDMITX_VFMT_60_1280x720p_24Hz = 60, /**< Format 60 1280 x 720p 23.97/24Hz 16:9 */ ++ TMDL_HDMITX_VFMT_61_1280x720p_25Hz = 61, /**< Format 61 1280 x 720p 25Hz 16:9 */ ++ TMDL_HDMITX_VFMT_62_1280x720p_30Hz = 62, /**< Format 60 1280 x 720p 29.97/30Hz 16:9 */ ++ ++ TMDL_HDMITX_VFMT_TV_MAX = 62, /**< Highest valid TV format */ ++ TMDL_HDMITX_VFMT_TV_NO_REG_MIN = 32, /**< Lowest TV format without prefetched table */ ++ TMDL_HDMITX_VFMT_TV_NUM = 42, /**< Number of TV formats & null */ ++ ++ TMDL_HDMITX_VFMT_PC_MIN = 128, /**< Lowest valid PC format */ ++ TMDL_HDMITX_VFMT_PC_640x480p_60Hz = 128, /**< PC format 128 */ ++ TMDL_HDMITX_VFMT_PC_800x600p_60Hz = 129, /**< PC format 129 */ ++ TMDL_HDMITX_VFMT_PC_1152x960p_60Hz = 130, /**< PC format 130 */ ++ TMDL_HDMITX_VFMT_PC_1024x768p_60Hz = 131, /**< PC format 131 */ ++ TMDL_HDMITX_VFMT_PC_1280x768p_60Hz = 132, /**< PC format 132 */ ++ TMDL_HDMITX_VFMT_PC_1280x1024p_60Hz = 133, /**< PC format 133 */ ++ TMDL_HDMITX_VFMT_PC_1360x768p_60Hz = 134, /**< PC format 134 */ ++ TMDL_HDMITX_VFMT_PC_1400x1050p_60Hz = 135, /**< PC format 135 */ ++ TMDL_HDMITX_VFMT_PC_1600x1200p_60Hz = 136, /**< PC format 136 */ ++ TMDL_HDMITX_VFMT_PC_1024x768p_70Hz = 137, /**< PC format 137 */ ++ TMDL_HDMITX_VFMT_PC_640x480p_72Hz = 138, /**< PC format 138 */ ++ TMDL_HDMITX_VFMT_PC_800x600p_72Hz = 139, /**< PC format 139 */ ++ TMDL_HDMITX_VFMT_PC_640x480p_75Hz = 140, /**< PC format 140 */ ++ TMDL_HDMITX_VFMT_PC_1024x768p_75Hz = 141, /**< PC format 141 */ ++ TMDL_HDMITX_VFMT_PC_800x600p_75Hz = 142, /**< PC format 142 */ ++ TMDL_HDMITX_VFMT_PC_1024x864p_75Hz = 143, /**< PC format 143 */ ++ TMDL_HDMITX_VFMT_PC_1280x1024p_75Hz = 144, /**< PC format 144 */ ++ TMDL_HDMITX_VFMT_PC_640x350p_85Hz = 145, /**< PC format 145 */ ++ TMDL_HDMITX_VFMT_PC_640x400p_85Hz = 146, /**< PC format 146 */ ++ TMDL_HDMITX_VFMT_PC_720x400p_85Hz = 147, /**< PC format 147 */ ++ TMDL_HDMITX_VFMT_PC_640x480p_85Hz = 148, /**< PC format 148 */ ++ TMDL_HDMITX_VFMT_PC_800x600p_85Hz = 149, /**< PC format 149 */ ++ TMDL_HDMITX_VFMT_PC_1024x768p_85Hz = 150, /**< PC format 150 */ ++ TMDL_HDMITX_VFMT_PC_1152x864p_85Hz = 151, /**< PC format 151 */ ++ TMDL_HDMITX_VFMT_PC_1280x960p_85Hz = 152, /**< PC format 152 */ ++ TMDL_HDMITX_VFMT_PC_1280x1024p_85Hz = 153, /**< PC format 153 */ ++ TMDL_HDMITX_VFMT_PC_1024x768i_87Hz = 154, /**< PC format 154 */ ++ TMDL_HDMITX_VFMT_PC_MAX = 154, /**< Highest valid PC format */ ++ TMDL_HDMITX_VFMT_PC_NUM = (TMDL_HDMITX_VFMT_PC_MAX-TMDL_HDMITX_VFMT_PC_MIN+1) /**< Number of PC formats */ ++} tmdlHdmiTxVidFmt_t; ++ ++/** ++ * \brief Structure defining the EDID short video descriptor ++ */ ++typedef struct ++{ ++ tmdlHdmiTxVidFmt_t videoFormat; /**< Video format as defined by EIA/CEA 861-D */ ++ Bool nativeVideoFormat; /**< True if format is the preferred video format */ ++} tmdlHdmiTxShortVidDesc_t; ++ ++/** ++ * \brief Enum listing all picture aspect ratio (H:V) (4:3, 16:9) ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_P_ASPECT_RATIO_UNDEFINED = 0, /**< Undefined picture aspect ratio */ ++ TMDL_HDMITX_P_ASPECT_RATIO_6_5 = 1, /**< 6:5 picture aspect ratio (PAR) */ ++ TMDL_HDMITX_P_ASPECT_RATIO_5_4 = 2, /**< 5:4 PAR */ ++ TMDL_HDMITX_P_ASPECT_RATIO_4_3 = 3, /**< 4:3 PAR */ ++ TMDL_HDMITX_P_ASPECT_RATIO_16_10 = 4, /**< 16:10 PAR */ ++ TMDL_HDMITX_P_ASPECT_RATIO_5_3 = 5, /**< 5:3 PAR */ ++ TMDL_HDMITX_P_ASPECT_RATIO_16_9 = 6, /**< 16:9 PAR */ ++ TMDL_HDMITX_P_ASPECT_RATIO_9_5 = 7 /**< 9:5 PAR */ ++} tmdlHdmiTxPictAspectRatio_t; ++ ++/** ++ * \brief Enum listing all vertical frequency ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_VFREQ_24Hz = 0, /**< 24Hz */ ++ TMDL_HDMITX_VFREQ_25Hz = 1, /**< 25Hz */ ++ TMDL_HDMITX_VFREQ_30Hz = 2, /**< 30Hz */ ++ TMDL_HDMITX_VFREQ_50Hz = 3, /**< 50Hz */ ++ TMDL_HDMITX_VFREQ_59Hz = 4, /**< 59.94Hz */ ++ TMDL_HDMITX_VFREQ_60Hz = 5, /**< 60Hz */ ++#ifndef FORMAT_PC ++ TMDL_HDMITX_VFREQ_INVALID = 6, /**< Invalid */ ++ TMDL_HDMITX_VFREQ_NUM = 6 /**< No. of values */ ++#else /* FORMAT_PC */ ++ TMDL_HDMITX_VFREQ_70Hz = 6, /**< 70Hz */ ++ TMDL_HDMITX_VFREQ_72Hz = 7, /**< 72Hz */ ++ TMDL_HDMITX_VFREQ_75Hz = 8, /**< 75Hz */ ++ TMDL_HDMITX_VFREQ_85Hz = 9, /**< 85Hz */ ++ TMDL_HDMITX_VFREQ_87Hz = 10, /**< 87Hz */ ++ TMDL_HDMITX_VFREQ_INVALID = 11, /**< Invalid */ ++ TMDL_HDMITX_VFREQ_NUM = 11 /**< No. of values */ ++#endif /* FORMAT_PC */ ++} tmdlHdmiTxVfreq_t; ++ ++/** ++ * \brief Structure storing specifications of a video resolution ++ */ ++typedef struct ++{ ++ UInt16 width; /**< Width of the frame in pixels */ ++ UInt16 height; /**< Height of the frame in pixels */ ++ Bool interlaced; /**< Interlaced mode (True/False) */ ++ tmdlHdmiTxVfreq_t vfrequency; /**< Vertical frequency in Hz */ ++ tmdlHdmiTxPictAspectRatio_t aspectRatio; /**< Picture aspect ratio (H:V) */ ++} tmdlHdmiTxVidFmtSpecs_t; ++ ++/** ++ * \brief Enum listing all video input modes (CCIR, RGB, etc.) ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_VINMODE_CCIR656 = 0, /**< CCIR656 */ ++ TMDL_HDMITX_VINMODE_RGB444, /**< RGB444 */ ++ TMDL_HDMITX_VINMODE_YUV444, /**< YUV444 */ ++ TMDL_HDMITX_VINMODE_YUV422, /**< YUV422 */ ++#ifdef TMFL_RGB_DDR_12BITS ++ TMDL_HDMITX_VINMODE_RGB_DDR_12BITS, /**< RGB24 bits on a 12 bits bus using double data rate clocking */ ++#endif ++ TMDL_HDMITX_VINMODE_NO_CHANGE , /**< No change */ ++ TMDL_HDMITX_VINMODE_INVALID /**< Invalid */ ++} tmdlHdmiTxVinMode_t; ++ ++/** ++ * \brief Enum listing all possible sync sources ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_SYNCSRC_EMBEDDED = 0, /**< Embedded sync */ ++ TMDL_HDMITX_SYNCSRC_EXT_VREF = 1, /**< External sync Vref, Href, Fref */ ++ TMDL_HDMITX_SYNCSRC_EXT_VS = 2 /**< External sync Vs, Hs */ ++} tmdlHdmiTxSyncSource_t; ++ ++/** ++ * \brief Enum listing all output pixel rate (Single, Double, etc.) ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_PIXRATE_DOUBLE = 0, /**< Double pixel rate */ ++ TMDL_HDMITX_PIXRATE_SINGLE = 1, /**< Single pixel rate */ ++ TMDL_HDMITX_PIXRATE_SINGLE_REPEATED = 2 /**< Single pixel repeated */ ++} tmdlHdmiTxPixRate_t; ++ ++/** ++ * \brief Enum listing the supported transmission formats of 3D video data ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_3D_NONE = 0, /**< 3D video data not present */ ++ TMDL_HDMITX_3D_FRAME_PACKING = 1, /**< 3D video data Frame Packing structure */ ++ TMDL_HDMITX_3D_TOP_AND_BOTTOM = 2, /**< 3D video data Top and Bottom structure */ ++ TMDL_HDMITX_3D_SIDE_BY_SIDE_HALF = 3, /**< 3D video data Side by Side Half structure */ ++ TMDL_HDMITX_3D_INVALID = 4 /**< Invalid */ ++} tmdlHdmiTx3DStructure_t; ++ ++/** ++ * \brief Structure defining the video input configuration ++ */ ++typedef struct ++{ ++ tmdlHdmiTxVidFmt_t format; /**< Video format as defined by EIA/CEA 861-D */ ++ tmdlHdmiTxVinMode_t mode; /**< Video mode (CCIR, RGB, YUV, etc.) */ ++ tmdlHdmiTxSyncSource_t syncSource; /**< Sync source type */ ++ tmdlHdmiTxPixRate_t pixelRate; /**< Pixel rate */ ++ tmdlHdmiTx3DStructure_t structure3D; /**< 3D structure as defined in HDMI1.4a */ ++} tmdlHdmiTxVideoInConfig_t; ++ ++/** ++ * \brief Enum listing all video output modes (YUV, RGB, etc.) ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_VOUTMODE_RGB444 = 0, /**< RGB444 */ ++ TMDL_HDMITX_VOUTMODE_YUV422 = 1, /**< YUV422 */ ++ TMDL_HDMITX_VOUTMODE_YUV444 = 2 /**< YUV444 */ ++} tmdlHdmiTxVoutMode_t; ++ ++/** ++ * \brief Enum defining possible quantization range ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_VQR_DEFAULT = 0, /* Follow HDMI spec. */ ++ TMDL_HDMITX_RGB_FULL = 1, /* Force RGB FULL , DVI only */ ++ TMDL_HDMITX_RGB_LIMITED = 2 /* Force RGB LIMITED , DVI only */ ++} tmdlHdmiTxVQR_t; ++ ++ ++/** ++ * \brief Enum defining possible YCC Quantization Range ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_YQR_LIMITED = 0, /* LIMITED range */ ++ TMDL_HDMITX_YQR_FULL = 1, /* FULL range */ ++ TMDL_HDMITX_YQR_INVALID = 2 /* Invalid range */ ++} tmdlHdmiTxYCCQR_t; ++ ++ ++/** ++ * \brief Structure defining the video output configuration ++ */ ++typedef struct ++{ ++ tmdlHdmiTxVidFmt_t format; /**< Video format as defined by EIA/CEA 861-D */ ++ tmdlHdmiTxVoutMode_t mode; /**< Video mode (CCIR, RGB, YUV, etc.) */ ++ tmdlHdmiTxColorDepth_t colorDepth; /**< Color depth */ ++ tmdlHdmiTxVQR_t dviVqr; /**< VQR applied in DVI mode */ ++} tmdlHdmiTxVideoOutConfig_t; ++ ++ ++typedef enum ++{ ++ TMDL_HDMITX_AUDIO_DATA_PCM = 0, /**< Main data field represents linear PCM samples. */ ++ TMDL_HDMITX_AUDIO_DATA_OTHER = 1, /**< Main data field used for purposes other purposes. */ ++ TMDL_HDMITX_AUDIO_DATA_INVALID = 2 /**< Invalid value */ ++} tmdlHdmiTxAudioData_t; ++ ++ ++typedef enum ++{ ++ TMDL_HDMITX_CSCOPYRIGHT_PROTECTED = 0, /**< Copyright protected */ ++ TMDL_HDMITX_CSCOPYRIGHT_UNPROTECTED = 1, /**< Not copyright protected */ ++ TMDL_HDMITX_CSCOPYRIGHT_INVALID = 2 /**< Invalid value */ ++} tmdlHdmiTxCScopyright_t; ++ ++typedef enum ++{ ++ TMDL_HDMITX_CSFI_PCM_2CHAN_NO_PRE = 0, /**< PCM 2 channels without pre-emphasis or NON Linear PCM */ ++ TMDL_HDMITX_CSFI_PCM_2CHAN_PRE = 1, /**< PCM 2 channels with 50us/15us pre-emphasis */ ++ TMDL_HDMITX_CSFI_PCM_2CHAN_PRE_RSVD1 = 2, /**< PCM Reserved for 2 channels with pre-emphasis */ ++ TMDL_HDMITX_CSFI_PCM_2CHAN_PRE_RSVD2 = 3, /**< PCM Reserved for 2 channels with pre-emphasis */ ++ TMDL_HDMITX_CSFI_INVALID = 4 /**< Invalid value */ ++} tmdlHdmiTxCSformatInfo_t; ++ ++ ++typedef enum ++{ ++ TMDL_HDMITX_CSCLK_LEVEL_II = 0, /**< Level II */ ++ TMDL_HDMITX_CSCLK_LEVEL_I = 1, /**< Level I */ ++ TMDL_HDMITX_CSCLK_LEVEL_III = 2, /**< Level III */ ++ TMDL_HDMITX_CSCLK_NOT_MATCHED = 3, /**< Not matched to sample freq. */ ++ TMDL_HDMITX_CSCLK_INVALID = 4 /**< Invalid */ ++} tmdlHdmiTxCSclkAcc_t; ++ ++ ++typedef enum ++{ ++ TMDL_HDMITX_CSMAX_LENGTH_20 = 0, /**< Max word length is 20 bits */ ++ TMDL_HDMITX_CSMAX_LENGTH_24 = 1, /**< Max word length is 24 bits */ ++ TMDL_HDMITX_CSMAX_INVALID = 2 /**< Invalid value */ ++} tmdlHdmiTxCSmaxWordLength_t; ++ ++ ++ ++typedef enum ++{ ++ TMDL_HDMITX_CSWORD_DEFAULT = 0, /**< Word length is not indicated */ ++ TMDL_HDMITX_CSWORD_20_OF_24 = 1, /**< Sample length is 20 bits out of max 24 possible */ ++ TMDL_HDMITX_CSWORD_16_OF_20 = 1, /**< Sample length is 16 bits out of max 20 possible */ ++ TMDL_HDMITX_CSWORD_22_OF_24 = 2, /**< Sample length is 22 bits out of max 24 possible */ ++ TMDL_HDMITX_CSWORD_18_OF_20 = 2, /**< Sample length is 18 bits out of max 20 possible */ ++ TMDL_HDMITX_CSWORD_RESVD = 3, /**< Reserved - shall not be used */ ++ TMDL_HDMITX_CSWORD_23_OF_24 = 4, /**< Sample length is 23 bits out of max 24 possible */ ++ TMDL_HDMITX_CSWORD_19_OF_20 = 4, /**< Sample length is 19 bits out of max 20 possible */ ++ TMDL_HDMITX_CSWORD_24_OF_24 = 5, /**< Sample length is 24 bits out of max 24 possible */ ++ TMDL_HDMITX_CSWORD_20_OF_20 = 5, /**< Sample length is 20 bits out of max 20 possible */ ++ TMDL_HDMITX_CSWORD_21_OF_24 = 6, /**< Sample length is 21 bits out of max 24 possible */ ++ TMDL_HDMITX_CSWORD_17_OF_20 = 6, /**< Sample length is 17 bits out of max 20 possible */ ++ TMDL_HDMITX_CSWORD_INVALID = 7 /**< Invalid */ ++} tmdlHdmiTxCSwordLength_t; ++ ++ ++typedef enum ++{ ++ TMDL_HDMITX_CSOFREQ_NOT_INDICATED = 0, /**< Not Indicated */ ++ TMDL_HDMITX_CSOFREQ_192k = 1, /**< 192kHz */ ++ TMDL_HDMITX_CSOFREQ_12k = 2, /**< 12kHz */ ++ TMDL_HDMITX_CSOFREQ_176_4k = 3, /**< 176.4kHz */ ++ TMDL_HDMITX_CSOFREQ_RSVD1 = 4, /**< Reserved */ ++ TMDL_HDMITX_CSOFREQ_96k = 5, /**< 96kHz */ ++ TMDL_HDMITX_CSOFREQ_8k = 6, /**< 8kHz */ ++ TMDL_HDMITX_CSOFREQ_88_2k = 7, /**< 88.2kHz */ ++ TMDL_HDMITX_CSOFREQ_16k = 8, /**< 16kHz */ ++ TMDL_HDMITX_CSOFREQ_24k = 9, /**< 24kHz */ ++ TMDL_HDMITX_CSOFREQ_11_025k = 10, /**< 11.025kHz */ ++ TMDL_HDMITX_CSOFREQ_22_05k = 11, /**< 22.05kHz */ ++ TMDL_HDMITX_CSOFREQ_32k = 12, /**< 32kHz */ ++ TMDL_HDMITX_CSOFREQ_48k = 13, /**< 48kHz */ ++ TMDL_HDMITX_CSOFREQ_RSVD2 = 14, /**< Reserved */ ++ TMDL_HDMITX_CSOFREQ_44_1k = 15, /**< 44.1kHz */ ++ TMDL_HDMITX_CSAFS_INVALID = 16 /**< Invalid value */ ++} tmdlHdmiTxCSorigAfs_t; ++ ++ ++ ++typedef struct ++{ ++ tmdlHdmiTxAudioData_t PcmIdentification; ++ tmdlHdmiTxCScopyright_t CopyrightInfo; ++ tmdlHdmiTxCSformatInfo_t FormatInfo; ++ UInt8 categoryCode; ++ tmdlHdmiTxCSclkAcc_t clockAccuracy; ++ tmdlHdmiTxCSmaxWordLength_t maxWordLength; ++ tmdlHdmiTxCSwordLength_t wordLength; ++ tmdlHdmiTxCSorigAfs_t origSampleFreq; ++} tmdlHdmiTxAudioInChannelStatus; ++ ++ ++/** ++ * \brief Structure defining the audio input configuration ++ */ ++typedef struct ++{ ++ tmdlHdmiTxAudioFormat_t format; /**< Audio format (I2S, SPDIF, etc.) */ ++ tmdlHdmiTxAudioRate_t rate; /**< Audio sampling rate */ ++ tmdlHdmiTxAudioI2SFormat_t i2sFormat; /**< I2S format of the audio input */ ++ tmdlHdmiTxAudioI2SQualifier_t i2sQualifier; /**< I2S qualifier of the audio input (8,16,32 bits) */ ++ tmdlHdmiTxDstRate_t dstRate; /**< DST data transfer rate */ ++ UInt8 channelAllocation; /**< Ref to CEA-861D p85 */ ++ tmdlHdmiTxAudioInChannelStatus channelStatus; /**< Ref to IEC 60958-3 */ ++} tmdlHdmiTxAudioInConfig_t; ++ ++/** ++ * \brief Enum listing all the type of sunk ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_SINK_DVI = 0, /**< DVI */ ++ TMDL_HDMITX_SINK_HDMI = 1, /**< HDMI */ ++ TMDL_HDMITX_SINK_EDID = 2 /**< As currently defined in EDID */ ++} tmdlHdmiTxSinkType_t; ++ ++/** ++ * \brief Structure defining the content of a gamut packet ++ */ ++typedef struct ++{ ++ Bool nextField; /**< Gamut relevant for field following packet insertion */ ++ UInt8 GBD_Profile; /**< Profile of the gamut packet : 0 = P0, 1 = P1 */ ++ UInt8 affectedGamutSeqNum; /**< Gamut sequence number of the field that have to be affected by this gamut packet */ ++ Bool noCurrentGBD; /**< Current field not using specific gamut */ ++ UInt8 currentGamutSeqNum; /**< Gamut sequence number of the current field */ ++ UInt8 packetSequence; /**< Sequence of the packet inside a multiple packet gamut */ ++ UInt8 payload[28]; /**< Payload of the gamut packet */ ++} tmdlHdmiTxGamutData_t; ++ ++/** ++ * \brief Type defining the content of a generic packet ++ */ ++typedef UInt8 tmdlHdmiTxGenericPacket[28]; ++ ++/** ++ * \brief Structure defining the content of an ACP packet ++ */ ++typedef struct ++{ ++ UInt8 acpType; ++ UInt8 acpData[28]; ++} tmdlHdmiTxAcpPktData_t; ++ ++/** ++ * \brief Structure defining the content of an AVI infoframe ++ */ ++typedef struct ++{ ++ UInt8 colorIndicator; /**< RGB or YCbCr indicator. See CEA-861-B table 8 for details */ ++ UInt8 activeInfoPresent; /**< Active information present. Indicates if activeFormatAspectRatio field is valid */ ++ UInt8 barInformationDataValid; /**< Bar information data valid */ ++ UInt8 scanInformation; /**< Scan information. See CEA-861-B table 8 for details */ ++ UInt8 colorimetry; /**< Colorimetry. See CEA-861-B table 9 for details */ ++ UInt8 pictureAspectRatio; /**< Picture aspect ratio. See CEA-861-B table 9 for details */ ++ UInt8 activeFormatAspectRatio; /**< Active Format aspect ratio. See CEA-861-B table 10 and Annex H for details */ ++ UInt8 nonUniformPictureScaling; /**< Non-uniform picture scaling. See CEA-861-B table 11 for details */ ++ UInt8 videoFormatIdentificationCode; /**< Video format indentification code. See CEA-861-B section 6.3 for details */ ++ UInt8 pixelRepetitionFactor; /**< Pixel repetition factor. See CEA-861-B table 11 for details */ ++ UInt16 lineNumberEndTopBar; ++ UInt16 lineNumberStartBottomBar; ++ UInt16 lineNumberEndLeftBar; ++ UInt16 lineNumberStartRightBar; ++} tmdlHdmiTxAviIfData_t; ++ ++/** ++ * \brief Structure defining the content of an ACP packet ++ */ ++typedef struct ++{ ++ Bool avMute; ++} tmdlHdmiTxGcpPktData_t; ++ ++/** ++ * \brief Structure defining the content of an AUD infoframe ++ */ ++typedef struct ++{ ++ UInt8 codingType; /**< Coding type (always set to zero) */ ++ UInt8 channelCount; /**< Channel count. See CEA-861-B table 17 for details */ ++ UInt8 samplefrequency; /**< Sample frequency. See CEA-861-B table 18 for details */ ++ UInt8 sampleSize; /**< Sample frequency. See CEA-861-B table 18 for details */ ++ UInt8 channelAllocation; /**< Channel allocation. See CEA-861-B section 6.3.2 for details */ ++ Bool downmixInhibit; /**< Downmix inhibit. See CEA-861-B section 6.3.2 for details */ ++ UInt8 levelShiftValue; /**< level shift value for downmixing. See CEA-861-B section 6.3.2 and table 23 for details */ ++} tmdlHdmiTxAudIfData_t; ++ ++/** ++ * \brief Structure defining the content of an ISRC1 packet ++ */ ++typedef struct ++{ ++ Bool isrcCont; /**< ISRC packet continued in next packet */ ++ Bool isrcValid; /**< Set to one when ISRCStatus and UPC_EAN_ISRC_xx are valid */ ++ UInt8 isrcStatus; /**< ISRC status */ ++ UInt8 UPC_EAN_ISRC[16]; /**< ISRC packet data */ ++} tmdlHdmiTxIsrc1PktData_t; ++ ++/** ++ * \brief Structure defining the content of an ISRC2 packet ++ */ ++typedef struct ++{ ++ UInt8 UPC_EAN_ISRC[16]; /**< ISRC packet data */ ++} tmdlHdmiTxIsrc2PktData_t; ++ ++/** ++ * \brief Structure defining the content of an MPS infoframe ++ */ ++typedef struct ++{ ++ UInt32 bitRate; /**< MPEG bit rate in Hz */ ++ UInt32 frameType; /**< MPEG frame type */ ++ Bool fieldRepeat; /**< 0: new field, 1:repeated field */ ++} tmdlHdmiTxMpsIfData_t; ++ ++/** ++ * \brief Structure defining the content of an SPD infoframe ++ */ ++typedef struct ++{ ++ UInt8 vendorName[8]; /**< Vendor name */ ++ UInt8 productDesc[16]; /**< Product Description */ ++ UInt32 sourceDevInfo; /**< Source Device Info */ ++} tmdlHdmiTxSpdIfData_t; ++ ++ ++/** ++ * \brief Structure defining the content of a VS infoframe packet according to HDMI 1.4a standard ++ */ ++ ++/* HDMI version */ ++#define TMDL_HDMITX_VERSION 0x01 ++ ++/* HDMI video format [3bits] */ ++#define TMDL_HDMITX_VIDEO_FORMAT_SHIFT 5 ++#define TMDL_HDMITX_FORMAT_EXTENDED (0x01 << TMDL_HDMITX_VIDEO_FORMAT_SHIFT) ++#define TMDL_HDMITX_3D (0x02 << TMDL_HDMITX_VIDEO_FORMAT_SHIFT) ++ ++/* IEEE registration identifier (0x000C03) with least significant byte first */ ++#define TMDL_HDMITX_HDMI_IEEE_BYTE0 0x03 ++#define TMDL_HDMITX_HDMI_IEEE_BYTE1 0x0C ++#define TMDL_HDMITX_HDMI_IEEE_BYTE2 0x00 ++ ++/* 3D structure [4bits] */ ++#define TMDL_HDMITX_3D_STRUCTURE_SHIFT 4 ++#define TMDL_HDMITX_FRAME_PACKING (0x00 << TMDL_HDMITX_3D_STRUCTURE_SHIFT) ++#define TMDL_HDMITX_FIELD_ALTERNATIVE (0x01 << TMDL_HDMITX_3D_STRUCTURE_SHIFT) ++#define TMDL_HDMITX_LINE_ALTERNATIVE (0x02 << TMDL_HDMITX_3D_STRUCTURE_SHIFT) ++#define TMDL_HDMITX_SIDE_BY_SIDE_FULL (0x03 << TMDL_HDMITX_3D_STRUCTURE_SHIFT) ++#define TMDL_HDMITX_L_DEPTH (0x04 << TMDL_HDMITX_3D_STRUCTURE_SHIFT) ++#define TMDL_HDMITX_L_DEPTH_GFX (0x05 << TMDL_HDMITX_3D_STRUCTURE_SHIFT) ++#define TMDL_HDMITX_TOP_AND_BOTTOM (0x06 << TMDL_HDMITX_3D_STRUCTURE_SHIFT) ++#define TMDL_HDMITX_SIDE_BY_SIDE_HALF (0x08 << TMDL_HDMITX_3D_STRUCTURE_SHIFT) ++ ++/* 3D EXT Data [4bits] */ ++#define TMDL_HDMITX_3D_EXT_DATA_SHIFT 4 ++#define TMDL_HDMITX_HORIZONTAL_SUB (0x00 << TMDL_HDMITX_3D_EXT_DATA_SHIFT) /* Horizontal sub-sampling */ ++#define TMDL_HDMITX_QUINCUNX_OLOR (0x04 << TMDL_HDMITX_3D_EXT_DATA_SHIFT) /* Odd/Left picture, Odd/Right picture */ ++#define TMDL_HDMITX_QUINCUNX_OLER (0x05 << TMDL_HDMITX_3D_EXT_DATA_SHIFT) /* Odd/Left picture, Even/Right picture */ ++#define TMDL_HDMITX_QUINCUNX_ELOR (0x06 << TMDL_HDMITX_3D_EXT_DATA_SHIFT) /* Even/Left picture, Odd/Right picture */ ++#define TMDL_HDMITX_QUINCUNX_ELER (0x07 << TMDL_HDMITX_3D_EXT_DATA_SHIFT) /* Even/Left picture, Even/Right picture */ ++ ++/* 3D Meta field */ ++#define TMDL_HDMITX_3D_META_TYPE_SHIFT 5 ++#define TMDL_HDMITX_3D_META_PRESENT (0x01 << 3) ++#define TMDL_HDMITX_3D_META_PARALLAX (0x00 << TMDL_HDMITX_3D_META_TYPE_SHIFT) ++ ++#define TMDL_HDMITX_VS_PKT_DATA_LEN 27 ++typedef struct ++{ ++ UInt8 version; ++ /* ++ Packet Byte # 7 6 5 4 3 2 1 0 ++ ++ PB1 24bit IEEE Registration Identifier (0x000C03) ++ PB2 ( least significant byte first ) ++ PB3 ++ PB4 (HDMI_Video_Format ) (0) (0) (0) (0) (0) ++ PB5 (3D_Structure ) +Meta (0) (0) (0) ++ PB6 (3D_Ext_Data ) (0) (0) (0) (0) ++ PB7 (3D_Metadata_type ) (3D_Metadata_Length (= N)) ++ PB8 (3D_Metadata_1 ) ++ ... ... ++ PB [7+N] (3D_Metadata_N ) ++ PB[8+N]~[Nv] (Reserved (0) ) ++ */ ++ UInt8 vsData[TMDL_HDMITX_VS_PKT_DATA_LEN]; ++ ++} tmdlHdmiTxVsPktData_t; ++ ++/** ++ * \brief Structure defining the additional Edid VSDB data according to HDMI 1.4a standard ++ */ ++typedef struct ++{ ++ UInt8 maxTmdsClock; /* maximum supported TMDS clock */ ++ UInt8 cnc0; /* content type Graphics (text) */ ++ UInt8 cnc1; /* content type Photo */ ++ UInt8 cnc2; /* content type Cinema */ ++ UInt8 cnc3; /* content type Game */ ++ UInt8 hdmiVideoPresent; /* additional video format */ ++ UInt8 h3DPresent; /* 3D support by the HDMI Sink */ ++ UInt8 h3DMultiPresent; /* 3D multi strctures present */ ++ UInt8 imageSize; /* additional info for the values in the image size area */ ++ UInt8 hdmi3DLen; /* total length of 3D video formats */ ++ UInt8 hdmiVicLen; /* total length of extended video formats */ ++ UInt8 ext3DData[21]; /* max_len-10, ie: 31-10=21 */ ++} tmdlHdmiTxEdidExtraVsdbData_t; ++ ++/** ++ * \brief Structure defining the Edid audio descriptor ++ */ ++typedef struct ++{ ++ UInt8 format; /* EIA/CEA861 mode */ ++ UInt8 channels; /* number of channels */ ++ UInt8 supportedFreqs; /* bitmask of supported frequencies */ ++ UInt8 supportedRes; /* bitmask of supported resolutions (LPCM only) */ ++ UInt8 maxBitrate; /* Maximum bitrate divided by 8KHz (compressed formats only) */ ++} tmdlHdmiTxEdidAudioDesc_t; ++ ++/** ++ * \brief Structure defining detailed timings of a video format ++ */ ++typedef struct ++{ ++ UInt16 pixelClock; /**< Pixel Clock/10 000 */ ++ UInt16 hActivePixels; /**< Horizontal Active Pixels */ ++ UInt16 hBlankPixels; /**< Horizontal Blanking Pixels */ ++ UInt16 vActiveLines; /**< Vertical Active Lines */ ++ UInt16 vBlankLines; /**< Vertical Blanking Lines */ ++ UInt16 hSyncOffset; /**< Horizontal Sync Offset */ ++ UInt16 hSyncWidth; /**< Horiz. Sync Pulse Width */ ++ UInt16 vSyncOffset; /**< Vertical Sync Offset */ ++ UInt16 vSyncWidth; /**< Vertical Sync Pulse Width */ ++ UInt16 hImageSize; /**< Horizontal Image Size */ ++ UInt16 vImageSize; /**< Vertical Image Size */ ++ UInt16 hBorderPixels; /**< Horizontal Border */ ++ UInt16 vBorderPixels; /**< Vertical Border */ ++ UInt8 flags; /**< Interlace/sync info */ ++} tmdlHdmiTxEdidVideoTimings_t; ++ ++/** size descriptor block of monitor descriptor */ ++#define EDID_MONITOR_DESCRIPTOR_SIZE 13 ++ ++/** ++ * \brief Structure defining the first monitor descriptor ++ */ ++typedef struct ++{ ++ Bool descRecord; /**< True when parameters of struct are available */ ++ UInt8 monitorName[EDID_MONITOR_DESCRIPTOR_SIZE]; /**< Monitor Name */ ++} tmdlHdmiTxEdidFirstMD_t; ++ ++/** ++ * \brief Structure defining the second monitor descriptor ++ */ ++typedef struct ++{ ++ Bool descRecord; /**< True when parameters of struct are available */ ++ UInt8 minVerticalRate; /**< Min vertical rate in Hz */ ++ UInt8 maxVerticalRate; /**< Max vertical rate in Hz */ ++ UInt8 minHorizontalRate; /**< Min horizontal rate in Hz */ ++ UInt8 maxHorizontalRate; /**< Max horizontal rate in Hz */ ++ UInt8 maxSupportedPixelClk; /**< Max suuported pixel clock rate in MHz */ ++} tmdlHdmiTxEdidSecondMD_t; ++ ++/** ++ * \brief Structure defining the other monitor descriptor ++ */ ++typedef struct ++{ ++ Bool descRecord; /**< True when parameters of struct are available */ ++ UInt8 otherDescriptor[EDID_MONITOR_DESCRIPTOR_SIZE]; /**< Other monitor Descriptor */ ++} tmdlHdmiTxEdidOtherMD_t; ++ ++/** ++ * \brief Test pattern types ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_PATTERN_OFF = 0, /**< Insert test pattern */ ++ TMDL_HDMITX_PATTERN_CBAR4 = 1, /**< Insert 4-bar colour bar */ ++ TMDL_HDMITX_PATTERN_CBAR8 = 2, /**< Insert 8-bar colour bar */ ++ TMDL_HDMITX_PATTERN_BLUE = 3, /**< Insert Blue screen */ ++ TMDL_HDMITX_PATTERN_BLACK = 4, /**< Insert Black screen */ ++ TMDL_HDMITX_PATTERN_INVALID = 5 /**< Invalid pattern */ ++} tmdlHdmiTxTestPattern_t; ++ ++/** ++ * \brief Enum listing all hdcp state ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_HDCP_CHECK_NOT_STARTED = 0, /**< Check not started */ ++ TMDL_HDMITX_HDCP_CHECK_IN_PROGRESS = 1, /**< No failures, more to do */ ++ TMDL_HDMITX_HDCP_CHECK_PASS = 2, /**< Final check has passed */ ++ TMDL_HDMITX_HDCP_CHECK_FAIL_FIRST = 3, /**< First check failure code */ ++ TMDL_HDMITX_HDCP_CHECK_FAIL_DRIVER_STATE = 3, /**< Driver not AUTHENTICATED */ ++ TMDL_HDMITX_HDCP_CHECK_FAIL_DEVICE_T0 = 4, /**< A T0 interrupt occurred */ ++ TMDL_HDMITX_HDCP_CHECK_FAIL_DEVICE_RI = 5, /**< Device RI changed */ ++ TMDL_HDMITX_HDCP_CHECK_FAIL_DEVICE_FSM = 6, /**< Device FSM not 10h */ ++ TMDL_HDMITX_HDCP_CHECK_NUM = 7 /**< Number of check results */ ++}tmdlHdmiTxHdcpCheck_t; ++ ++/** ++ * \brief Enum listing all hdcp option flags ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_HDCP_OPTION_FORCE_PJ_IGNORED = 0x01, /* Not set: obey PJ result */ ++ TMDL_HDMITX_HDCP_OPTION_FORCE_SLOW_DDC = 0x02, /* Not set: obey BCAPS setting */ ++ TMDL_HDMITX_HDCP_OPTION_FORCE_NO_1_1 = 0x04, /* Not set: obey BCAPS setting */ ++ TMDL_HDMITX_HDCP_OPTION_FORCE_REPEATER = 0x08, /* Not set: obey BCAPS setting */ ++ TMDL_HDMITX_HDCP_OPTION_FORCE_NO_REPEATER = 0x10, /* Not set: obey BCAPS setting */ ++ TMDL_HDMITX_HDCP_OPTION_FORCE_V_EQU_VBAR = 0x20, /* Not set: obey V=V' result */ ++ TMDL_HDMITX_HDCP_OPTION_FORCE_VSLOW_DDC = 0x40, /* Set: 50kHz DDC */ ++ TMDL_HDMITX_HDCP_OPTION_DEFAULT = 0x00, /* All the above Not Set vals */ ++ TMDL_HDMITX_HDCP_OPTION_MASK = 0x7F, /* Only these bits are allowed */ ++ TMDL_HDMITX_HDCP_OPTION_MASK_BAD = 0x80 /* These bits are not allowed */ ++}tmdlHdmiTxHdcpOptions_t; ++ ++#ifndef NO_HDCP ++/** KSV list sizes */ ++typedef enum ++{ ++ TMDL_HDMITX_KSV_LIST_MAX_DEVICES = 128, ++ TMDL_HDMITX_KSV_BYTES_PER_DEVICE = 5 ++} tmdlHdmiTxHdcpHandleSHA_1; ++ ++/** ++ * \brief Structure defining information about hdcp ++ */ ++typedef struct ++{ ++ tmdlHdmiTxHdcpCheck_t hdcpCheckState; /* Hdcp check state */ ++ UInt8 hdcpErrorState; /* Error State when T0 occured */ ++ Bool bKsvSecure; /* BKSV is secured */ ++ UInt8 hdcpBksv[TMDL_HDMITX_KSV_BYTES_PER_DEVICE]; /* BKSV read from B sink */ ++ UInt8 hdcpKsvList[TMDL_HDMITX_KSV_BYTES_PER_DEVICE * ++ TMDL_HDMITX_KSV_LIST_MAX_DEVICES]; /* KSV list read from B sink during ++ SHA-1 interrupt */ ++ UInt8 hdcpKsvDevices; /* Number of devices read from ++ B sink during SHA-1 interrupt */ ++ UInt8 hdcpDeviceDepth; /* Connection tree depth */ ++ Bool hdcpMaxCascExceeded; ++ Bool hdcpMaxDevsExceeded; ++} tmdlHdmiTxHdcpInfo_t; ++#endif /* NO_HDCP */ ++ ++/** ++ * \brief Enum defining possible HDCP ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_HDCP_OK = 0, ++ TMDL_HDMITX_HDCP_BKSV_RCV_FAIL, /* Source does not receive Sink BKsv */ ++ TMDL_HDMITX_HDCP_BKSV_CHECK_FAIL, /* BKsv does not contain 20 zeros and 20 ones */ ++ TMDL_HDMITX_HDCP_BCAPS_RCV_FAIL, /* Source does not receive Sink Bcaps */ ++ TMDL_HDMITX_HDCP_AKSV_SEND_FAIL, /* Source does not send AKsv */ ++ TMDL_HDMITX_HDCP_R0_RCV_FAIL, /* Source does not receive R'0 */ ++ TMDL_HDMITX_HDCP_R0_CHECK_FAIL, /* R0 = R'0 check fail */ ++ TMDL_HDMITX_HDCP_BKSV_NOT_SECURE, ++ TMDL_HDMITX_HDCP_RI_RCV_FAIL, /* Source does not receive R'i */ ++ TMDL_HDMITX_HDCP_RPT_RI_RCV_FAIL, /* Source does not receive R'i repeater mode */ ++ TMDL_HDMITX_HDCP_RI_CHECK_FAIL, /* RI = R'I check fail */ ++ TMDL_HDMITX_HDCP_RPT_RI_CHECK_FAIL, /* RI = R'I check fail repeater mode */ ++ TMDL_HDMITX_HDCP_RPT_BCAPS_RCV_FAIL, /* Source does not receive Sink Bcaps repeater mode */ ++ TMDL_HDMITX_HDCP_RPT_BCAPS_READY_TIMEOUT, ++ TMDL_HDMITX_HDCP_RPT_V_RCV_FAIL, /* Source does not receive V'*/ ++ TMDL_HDMITX_HDCP_RPT_BSTATUS_RCV_FAIL, /* Source does not receive BSTATUS repeater mode */ ++ TMDL_HDMITX_HDCP_RPT_KSVLIST_RCV_FAIL, /* Source does not receive Ksv list in repeater mode */ ++ TMDL_HDMITX_HDCP_RPT_KSVLIST_NOT_SECURE, ++ TMDL_HDMITX_HDCP_UNKNOWN_STATUS ++ ++}tmdlHdmiTxHdcpStatus_t; ++ ++ ++/** ++ * \brief EDID information about sink latency ++ */ ++typedef struct ++{ ++ Bool latency_available; ++ Bool Ilatency_available; ++ UInt8 Edidvideo_latency; ++ UInt8 Edidaudio_latency; ++ UInt8 EdidIvideo_latency; ++ UInt8 EdidIaudio_latency; ++ ++} tmdlHdmiTxEdidLatency_t; ++ ++ ++/** ++ * \brief Enum defining possible HotPlug status ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_HOTPLUG_INACTIVE = 0, /**< Hotplug inactive */ ++ TMDL_HDMITX_HOTPLUG_ACTIVE = 1, /**< Hotplug active */ ++ TMDL_HDMITX_HOTPLUG_INVALID = 2 /**< Invalid Hotplug */ ++} tmdlHdmiTxHotPlug_t; ++ ++ ++/** ++ * \brief Enum defining possible RxSense status ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_RX_SENSE_INACTIVE = 0, /**< RxSense inactive */ ++ TMDL_HDMITX_RX_SENSE_ACTIVE = 1, /**< RxSense active */ ++ TMDL_HDMITX_RX_SENSE_INVALID = 2 /**< Invalid RxSense */ ++} tmdlHdmiTxRxSense_t; ++ ++ ++/** ++ * \brief Enum listing all the types of extented colorimetries ++ */ ++typedef enum ++{ ++ TMDL_HDMITX_EXT_COLORIMETRY_XVYCC601 = 0, ++ TMDL_HDMITX_EXT_COLORIMETRY_XVYCC709 = 1, ++ TMDL_HDMITX_EXT_COLORIMETRY_SYCC601 = 2, ++ TMDL_HDMITX_EXT_COLORIMETRY_ADOBEYCC601 = 3, ++ TMDL_HDMITX_EXT_COLORIMETRY_ADOBERGB = 4, ++ TMDL_HDMITX_EXT_COLORIMETRY_INVALID = 5 ++} tmdlHdmiTxExtColorimetry_t; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMDLHDMITX_TYPES_H */ ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ ++ +diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx.c b/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx.c +new file mode 100755 +index 0000000..b80b9f2 +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx.c +@@ -0,0 +1,7166 @@ ++/** ++ * Copyright (C) 2006 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmdlHdmiTx.c ++ * ++ * \version Revision: 1 ++ * ++ * \date Date: 10/08/07 10:00 ++ * ++ * \brief devlib driver component API for the TDA998x HDMI Transmitters ++ * ++ * \section refs Reference Documents ++ * HDMI Tx Driver - FRS.doc, ++ * ++ * \section info Change Information ++ * ++ * \verbatim ++ ++ History: tmdlHdmiTx.c ++ * ++ * ***************** Version 1 ***************** ++ * User: J. Lamotte Date: 10/08/07 Time: 10:00 ++ * Updated in $/Source/tmdlHdmiTx/inc ++ * initial version ++ ++ \endverbatim ++ * ++*/ ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++#include "tmdlHdmiTx_IW.h" ++#include "tmdlHdmiTx.h" ++#include "tmdlHdmiTx_local.h" ++#include "tmdlHdmiTx_cfg.h" ++#include "tmbslHdmiTx_funcMapping.h" ++ ++/*============================================================================*/ ++/* TYPES DECLARATIONS */ ++/*============================================================================*/ ++ ++/* Macro to avoid compilation warnings */ ++#ifdef TMFL_OS_WINDOWS ++#define DUMMY_ACCESS(x) x ++#else ++#define DUMMY_ACCESS(x) ++#endif ++ ++/*============================================================================*/ ++/* CONSTANTS DECLARATIONS */ ++/*============================================================================*/ ++ ++ ++ ++/*============================================================================*/ ++/* FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++ ++/* Prototypes of internal functions */ ++/* Task functions */ ++#ifndef TMFL_NO_RTOS ++static void CommandTaskUnit0(void); ++static void HdcpTaskUnit0(void); ++#endif /* TMFL_NO_RTOS */ ++ ++/* Interrupt callback functions */ ++static void dlHdmiTxHandleENCRYPT(tmInstance_t instance); ++static void dlHdmiTxHandleHPD(tmInstance_t instance); ++static void dlHdmiTxHandleT0(tmInstance_t instance); ++static void dlHdmiTxHandleBCAPS(tmInstance_t instance); ++static void dlHdmiTxHandleBSTATUS(tmInstance_t instance); ++static void dlHdmiTxHandleSHA_1(tmInstance_t instance); ++static void dlHdmiTxHandlePJ(tmInstance_t instance); ++static void dlHdmiTxHandleR0(tmInstance_t instance); ++static void dlHdmiTxHandleSW_INT(tmInstance_t instance); ++static void dlHdmiTxHandleRX_SENSE(tmInstance_t instance); ++static void dlHdmiTxHandleEDID_READ(tmInstance_t instance); ++static void dlHdmiTxHandleVS_RPT(tmInstance_t instance); ++ ++/* Devlib internal color bar management functions */ ++#ifndef NO_HDCP ++static void dlHdmiTxCheckColorBar(tmInstance_t instance); ++static void dlHdmiTxCheckHdcpColorBar(tmInstance_t instance); ++#endif ++ ++#ifndef NO_HDCP ++static void dlHdmiTxFindHdcpSeed(tmInstance_t instance); ++#endif /* NO_HDCP */ ++ ++/* Set the state machine of device library */ ++static void dlHdmiTxSetState ++( ++ tmInstance_t instance, ++ tmdlHdmiTxDriverState_t state ++); ++ ++/* Get the event status (enable or disable) in order to known ++ if event should be signaled */ ++static tmdlHdmiTxEventStatus_t dlHdmiTxGetEventStatus ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEvent_t event ++); ++ ++/* Use by tmdlHdmiTxSetInputOutput in scaler mode */ ++static Bool dlHdmiTxGetReflineRefpix ++( ++ tmdlHdmiTxVidFmt_t vinFmt, ++ tmdlHdmiTxVinMode_t vinMode, ++ tmdlHdmiTxVidFmt_t voutFmt, ++ UInt8 syncIn, ++ tmdlHdmiTxPixRate_t pixRate, ++ UInt16 *pRefPix, ++ UInt16 *pRefLine, ++ UInt16 *pScRefPix, ++ UInt16 *pScRefLine, ++ Bool *pbVerified ++); ++ ++/* Use by tmdlHdmiTxSetInputOutput to set AVI infoframe */ ++static tmErrorCode_t dlHdmiTxSetVideoInfoframe ++( ++ tmInstance_t instance, ++ tmdlHdmiTxVidFmt_t voutFmt, ++ tmdlHdmiTxVoutMode_t voutMode ++); ++ ++/* Use to set AVI infoframe with raw data */ ++static tmErrorCode_t dlHdmiTxSetRawVideoInfoframe ++( ++ tmInstance_t instance, ++ tmdlHdmiTxAviIfData_t *pContentVif, ++ Bool enable ++); ++ ++/* Calculate Checksum for info frame */ ++static UInt8 ++dlHdmiTxcalculateCheksumIF ++( ++ tmbslHdmiTxPktRawAvi_t *pData /* Pointer to checksum data */ ++); ++ ++/* IMPORTANT: The 3 functions define below should not be declared in static ++ in order to allow applicative API to call them. Those functions are not ++ in tmdlHdmiTx_Functions.h but are in tmdlHdmiTxCore.def */ ++ ++/* Get the device library state */ ++tmdlHdmiTxDriverState_t dlHdmiTxGetState(tmInstance_t instance); ++ ++/* Set pattern ON (Blue screen or color bar) */ ++tmErrorCode_t dlHdmiTxSetTestPatternOn ++( ++ tmInstance_t instance, ++ tmdlHdmiTxVidFmt_t voutFmt, ++ tmdlHdmiTxVoutMode_t voutMode, ++ tmdlHdmiTxTestPattern_t pattern ++); ++ ++/* Set pattern OFF */ ++tmErrorCode_t dlHdmiTxSetTestPatternOff ++( ++ tmInstance_t instance, ++ tmdlHdmiTxVidFmt_t voutFmt, ++ tmdlHdmiTxVoutMode_t voutMode ++); ++ ++/* Get DTD from BSL */ ++static tmErrorCode_t dlHdmiTxEdidGetDTD ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors, ++ UInt8 maxDTDesc, ++ UInt8 *pWrittenDTDesc ++); ++ ++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_640HAP ++( ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors ++); ++ ++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_720HAP ++( ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors, ++ tmdlHdmiTxPictAspectRatio_t pictureAspectRatio ++); ++ ++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1280HAP ++( ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors ++); ++ ++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1920HAP ++( ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors, ++ Bool formatInterlaced ++); ++ ++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1440HAP ++( ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors, ++ tmdlHdmiTxPictAspectRatio_t pictureAspectRatio, ++ Bool formatInterlaced ++); ++ ++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_2880HAP ++( ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors, ++ tmdlHdmiTxPictAspectRatio_t pictureAspectRatio, ++ Bool formatInterlaced ++); ++ ++static tmdlHdmiTxPictAspectRatio_t dlHdmiTxCalcAspectRatio ( ++ UInt16 HImageSize, ++ UInt16 VImageSize ++); ++ ++#ifndef NO_HDCP ++static void dlHdmiTxCheckHdcpBksv ++( ++ tmInstance_t instance, ++ UInt8 * pHdcpBksvTested, ++ Bool * pbBksvSecure, ++ Bool bBigEndian ++); ++#endif ++ ++/* Calculate table index according to video format value */ ++static tmdlHdmiTxVidFmt_t dlHdmiTxCalcVidFmtIndex(tmdlHdmiTxVidFmt_t vidFmt); ++ ++extern tmErrorCode_t tmbslDebugWriteFakeRegPage( tmUnitSelect_t txUnit ); ++ ++/*============================================================================*/ ++/* VARIABLES DECLARATIONS */ ++/*============================================================================*/ ++ ++tmdlHdmiTxIWSemHandle_t dlHdmiTxItSemaphore[MAX_UNITS]; ++ ++/* Unit configuration structure (device library system configuration) */ ++unitConfig_t unitTableTx[MAX_UNITS] = ++{ ++ { ++ False, ++ False, ++ (tmdlHdmiTxHdcpOptions_t) HDCP_OPT_DEFAULT, ++ False, ++ False, ++ TMDL_HDMITX_DEVICE_UNKNOWN, ++ 0, ++ 0, ++ (tmdlHdmiTxIWTaskHandle_t) 0, ++ (tmdlHdmiTxIWQueueHandle_t) 0, ++ (tmdlHdmiTxIWTaskHandle_t) 0, ++ STATE_NOT_INITIALIZED, ++ (ptmdlHdmiTxCallback_t) 0, ++ {Null, 0,}, ++ } ++}; ++ ++#ifndef TMFL_NO_RTOS ++ ++tmdlHdmiTxIWFuncPtr_t commandTaskTableTx[MAX_UNITS] = { ++ CommandTaskUnit0 ++ }; ++ ++tmdlHdmiTxIWFuncPtr_t hdcpTaskTableTx[MAX_UNITS] = { ++ HdcpTaskUnit0 ++ }; ++ ++#endif /* TMFL_NO_RTOS */ ++ ++tmbslHdmiTxCallbackList_t callbackFuncTableTx; ++ ++/* Device library configuration structure completed by dlHdmiTxGetConfig with ++ informations contained in config file */ ++tmdlHdmiTxDriverConfigTable_t gtmdlHdmiTxDriverConfigTable[MAX_UNITS] = { ++ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, TMDL_HDMITX_PATTERN_OFF,0}, ++}; ++ ++/* Video info (see instanceStatusInfoTx) */ ++tmdlHdmiTxVideoInfo_t videoInfoListTx = { ++ False, ++ {TMDL_HDMITX_VFMT_03_720x480p_60Hz, TMDL_HDMITX_VINMODE_YUV422, TMDL_HDMITX_SYNCSRC_EXT_VS, TMDL_HDMITX_PIXRATE_SINGLE, TMDL_HDMITX_3D_NONE}, ++ {TMDL_HDMITX_VFMT_03_720x480p_60Hz, TMDL_HDMITX_VOUTMODE_YUV422, TMDL_HDMITX_COLORDEPTH_24,TMDL_HDMITX_VQR_DEFAULT} ++}; ++ ++/* Audio info (see instanceStatusInfoTx) */ ++tmdlHdmiTxAudioInfo_t audioInfoListTx = { ++ False, ++ {TMDL_HDMITX_AFMT_SPDIF, TMDL_HDMITX_AFS_48K,TMDL_HDMITX_I2SFOR_PHILIPS_L,TMDL_HDMITX_I2SQ_16BITS,TMDL_HDMITX_DSTRATE_SINGLE,0x00} ++}; ++ ++/* Event state (see instanceStatusInfoTx) */ ++tmdlHdmiTxEventState_t eventStateListTx[EVENT_NB] = { ++ {TMDL_HDMITX_HDCP_ACTIVE, TMDL_HDMITX_EVENT_DISABLED}, ++ {TMDL_HDMITX_HDCP_INACTIVE, TMDL_HDMITX_EVENT_DISABLED}, ++ {TMDL_HDMITX_HPD_ACTIVE, TMDL_HDMITX_EVENT_DISABLED}, ++ {TMDL_HDMITX_HPD_INACTIVE, TMDL_HDMITX_EVENT_DISABLED}, ++ {TMDL_HDMITX_RX_KEYS_RECEIVED, TMDL_HDMITX_EVENT_DISABLED}, ++ {TMDL_HDMITX_RX_DEVICE_ACTIVE, TMDL_HDMITX_EVENT_DISABLED}, ++ {TMDL_HDMITX_RX_DEVICE_INACTIVE, TMDL_HDMITX_EVENT_DISABLED}, ++ {TMDL_HDMITX_EDID_RECEIVED, TMDL_HDMITX_EVENT_DISABLED}, ++ {TMDL_HDMITX_VS_RPT_RECEIVED, TMDL_HDMITX_EVENT_DISABLED} ++#ifdef HDMI_TX_REPEATER_ISR_MODE ++ ,{TMDL_HDMITX_B_STATUS, TMDL_HDMITX_EVENT_DISABLED} ++#endif /* HDMI_TX_REPEATER_ISR_MODE */ ++}; ++ ++/* Color bars state (see instanceStatusInfoTx) */ ++tmdlHdmiTxColBarState_t colorBarStateTx = { ++ False, ++ True, ++ True, ++ False, ++ False, ++ True, ++ False ++}; ++ ++tmdlHdmiTxGamutState_t gamutStateTx = { ++ False, ++ 0, ++ TMDL_HDMITX_EXT_COLORIMETRY_XVYCC601, ++ False, ++ TMDL_HDMITX_YQR_LIMITED ++}; ++ ++ ++/* Instance status (save the actual configuration) */ ++instanceStatus_t instanceStatusInfoTx[MAX_UNITS] = { ++ {(ptmdlHdmiTxVideoInfo_t) &videoInfoListTx, ++ (ptmdlHdmiTxAudioInfo_t) &audioInfoListTx, ++ (ptmdlHdmiTxEventState_t) eventStateListTx, ++ (ptmdlHdmiTxColBarState_t) &colorBarStateTx, ++ (ptmdlHdmiTxGamutState_t) &gamutStateTx } ++}; ++ ++/* HDCP seed table, arranged as pairs of 16-bit integers: lookup value, seed value. ++ * If no table is programmed and if KEY_SEED in config file is null, HDCP will be disabled */ ++#define SEED_TABLE_LEN 10 ++static const UInt16 kSeedTable[SEED_TABLE_LEN][2] = { ++ {0, 0}, ++ {0, 0}, ++ {0, 0}, ++ {0, 0}, ++ {0, 0}, ++ {0, 0}, ++ {0, 0}, ++ {0, 0}, ++ {0, 0}, ++ {0, 0} ++}; ++ ++#ifndef NO_HDCP ++tmdlHdmiTxHdcpInfo_t hdcpInfoListTx[MAX_UNITS]; ++#endif /* NO_HDCP */ ++ ++ ++static Bool gI2CDebugAccessesEnabled = True; /* For debug purpose only, used to manage underlying I2C accessed */ ++ ++#ifdef HDMI_TX_REPEATER_ISR_MODE ++static Bool gIgnoreNextSha1 = False; ++#endif /*HDMI_TX_REPEATER_ISR_MODE*/ ++ ++/*============================================================================*/ ++/* FUNCTIONS */ ++/*============================================================================*/ ++ ++/****************************************************************************** ++ \brief Get the software version of the driver. ++ ++ \param pSWVersion Pointer to the version structure. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetSWVersion ++( ++ tmSWVersion_t *pSWVersion ++) ++{ ++ /* Check if SWVersion pointer is Null */ ++ RETIF(pSWVersion == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Copy SW version */ ++ pSWVersion->compatibilityNr = VERSION_COMPATIBILITY; ++ pSWVersion->majorVersionNr = VERSION_MAJOR; ++ pSWVersion->minorVersionNr = VERSION_MINOR; ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Get the number of available HDMI transmitters devices in the system. ++ A unit directly represents a physical device. ++ ++ \param pUnitCount Pointer to the number of available units. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetNumberOfUnits ++( ++ UInt32 *pUnitCount ++) ++{ ++ /* Check if UnitCount pointer is Null */ ++ RETIF(pUnitCount == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Copy the maximum number of units */ ++ *pUnitCount = MAX_UNITS; ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Get the capabilities of unit 0. Capabilities are stored into a ++ dedicated structure and are directly read from the HW device. ++ ++ \param pCapabilities Pointer to the capabilities structure. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetCapabilities ++( ++ tmdlHdmiTxCapabilities_t *pCapabilities ++) ++{ ++ /* Directly call GetCapabilitiesM function for unit 0 and return the result */ ++ return(tmdlHdmiTxGetCapabilitiesM((tmUnitSelect_t)0, pCapabilities)); ++} ++ ++/****************************************************************************** ++ \brief Get the capabilities of a specific unit. Capabilities are stored ++ into a dedicated structure and are directly read from the HW ++ device. ++ ++ \param unit Unit to be probed. ++ \param pCapabilities Pointer to the capabilities structure. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetCapabilitiesM ++( ++ tmUnitSelect_t unit, ++ tmdlHdmiTxCapabilities_t *pCapabilities ++) ++{ ++ tmErrorCode_t errCode = TM_OK; ++ Bool featureSupported; ++ ++ /* Check if unit number is in range */ ++ RETIF((unit < 0) || (unit >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER) ++ ++ /* Check if Capalities pointer is Null */ ++ RETIF(pCapabilities == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Device version */ ++ pCapabilities->deviceVersion = unitTableTx[unit].deviceVersion ; ++ ++ /* Retrieve the capabilities from the BSL layer */ ++ ++ /* HDCP support */ ++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, ++ HDMITX_FEATURE_HW_HDCP, &featureSupported) ) != TM_OK, errCode) ++ ++ pCapabilities->hdcp = featureSupported; ++ ++ /* Scaler support */ ++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, ++ HDMITX_FEATURE_HW_SCALER, &featureSupported) ) != TM_OK, errCode) ++ ++ pCapabilities->scaler = featureSupported; ++ ++ /* Audio HBR support */ ++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, ++ HDMITX_FEATURE_HW_AUDIO_HBR, &featureSupported) ) != TM_OK, errCode) ++ ++ pCapabilities->audioPacket.HBR = featureSupported; ++ ++ /* Audio OBA support */ ++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, ++ HDMITX_FEATURE_HW_AUDIO_OBA, &featureSupported) ) != TM_OK, errCode) ++ ++ pCapabilities->audioPacket.oneBitAudio = featureSupported; ++ ++ /* Audio DST support */ ++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, ++ HDMITX_FEATURE_HW_AUDIO_DST, &featureSupported) ) != TM_OK, errCode) ++ ++ pCapabilities->audioPacket.DST = featureSupported; ++ ++ /* HDMI version 1.1 support */ ++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, ++ HDMITX_FEATURE_HW_HDMI_1_1, &featureSupported) ) != TM_OK, errCode) ++ ++ if (featureSupported) ++ { ++ pCapabilities->hdmiVersion = TMDL_HDMITX_HDMI_VERSION_1_1; ++ } ++ ++ /* HDMI version 1.2A support */ ++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, ++ HDMITX_FEATURE_HW_HDMI_1_2A, &featureSupported) ) != TM_OK, errCode) ++ ++ if (featureSupported) ++ { ++ pCapabilities->hdmiVersion = TMDL_HDMITX_HDMI_VERSION_1_2a; ++ } ++ ++ /* HDMI version 1.3 support */ ++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, ++ HDMITX_FEATURE_HW_HDMI_1_3A, &featureSupported) ) != TM_OK, errCode) ++ ++ if (featureSupported) ++ { ++ pCapabilities->hdmiVersion = TMDL_HDMITX_HDMI_VERSION_1_3a; ++ } ++ ++ /* Deep Color support */ ++ /* By default */ ++ pCapabilities->colorDepth = TMDL_HDMITX_COLORDEPTH_24; ++ ++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, ++ HDMITX_FEATURE_HW_DEEP_COLOR_30, &featureSupported) ) != TM_OK, errCode) ++ ++ if (featureSupported) ++ { ++ pCapabilities->colorDepth = TMDL_HDMITX_COLORDEPTH_30; ++ } ++ ++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, ++ HDMITX_FEATURE_HW_DEEP_COLOR_36, &featureSupported) ) != TM_OK, errCode) ++ ++ if (featureSupported) ++ { ++ pCapabilities->colorDepth = TMDL_HDMITX_COLORDEPTH_36; ++ } ++ ++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, ++ HDMITX_FEATURE_HW_DEEP_COLOR_48, &featureSupported) ) != TM_OK, errCode) ++ ++ if (featureSupported) ++ { ++ pCapabilities->colorDepth = TMDL_HDMITX_COLORDEPTH_48; ++ } ++ ++ return errCode; ++} ++ ++/****************************************************************************** ++ \brief Open unit 0 of HdmiTx driver and provides the instance number to ++ the caller. Note that one unit of HdmiTx represents one physical ++ HDMI transmitter and that only one instance per unit can be opened. ++ ++ \param pInstance Pointer to the variable that will receive the instance ++ identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or ++ the transmitter instance is not initialised ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_RESOURCE_OWNED: the resource is already in use ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMDL_ERR_DLHDMITX_INIT_FAILED: the unit instance is already ++ initialised or something wrong happened at lower level. ++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: the unit is not initialized ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMBSL_ERR_HDMI_INIT_FAILED: the unit instance is already ++ initialised ++ - TMBSL_ERR_HDMI_COMPATIBILITY: the driver is not compatiable ++ with the internal device version code ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxOpen ++( ++ tmInstance_t *pInstance ++) ++{ ++ /* Directly call OpenM function for unit 0 and return the result */ ++ return(tmdlHdmiTxOpenM(pInstance, (tmUnitSelect_t)0)); ++} ++ ++/****************************************************************************** ++ \brief Open a specific unit of HdmiTx driver and provides the instance ++ number to the caller. Note that one unit of HdmiTx represents one ++ physical HDMI transmitter and that only one instance per unit can be ++ opened. This function switches driver's state machine to ++ "initialized" state. ++ ++ \param pInstance Pointer to the structure that will receive the instance ++ identifier. ++ \param unit Unit number to be opened. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or ++ the transmitter instance is not initialised ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_RESOURCE_OWNED: the resource is already in use ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMDL_ERR_DLHDMITX_INIT_FAILED: the unit instance is already ++ initialised or something wrong happened at lower level. ++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: the unit is not initialized ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMBSL_ERR_HDMI_INIT_FAILED: the unit instance is already ++ initialised ++ - TMBSL_ERR_HDMI_COMPATIBILITY: the driver is not compatiable ++ with the internal device version code ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxOpenM ++( ++ tmInstance_t *pInstance, ++ tmUnitSelect_t unit ++) ++{ ++ tmErrorCode_t errCode; ++ tmErrorCode_t errCodeSem; ++ UInt16 i; ++ UInt8 deviceVersion; ++ Bool featureSupported; ++ ++ /* Check if unit number is in range */ ++ RETIF((unit < 0) || (unit >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER) ++ ++ /* Check if Instance pointer is Null */ ++ RETIF(pInstance == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Create the semaphore to protect variables modified under interruption */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreCreate(&dlHdmiTxItSemaphore[unit]) ) != TM_OK, errCode) ++ ++ /* Take the sempahore */ ++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[unit]) ) != TM_OK, errCodeSem) ++ ++ /* Check if unit is already instanciated */ ++ RETIF_SEM(dlHdmiTxItSemaphore[unit], ++ unitTableTx[unit].opened == True, TMDL_ERR_DLHDMITX_RESOURCE_OWNED) ++ ++ /* Check the state */ ++ RETIF_SEM(dlHdmiTxItSemaphore[unit], ++ dlHdmiTxGetState(unit) != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ /* Instanciate unit and return corresponding instance number */ ++ /* Since HW unit are only instanciable once, instance = unit */ ++ unitTableTx[unit].opened = True; ++ unitTableTx[unit].hdcpEnable = False; ++ unitTableTx[unit].repeaterEnable = False; ++ unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_UNKNOWN; ++ unitTableTx[unit].simplayHd = False; ++ unitTableTx[unit].pCallback = Null; ++ unitTableTx[unit].revocationList.pList = Null; ++ unitTableTx[unit].revocationList.length = 0; ++ ++ /* Recover the configuration of the device library */ ++ RETIF_SEM(dlHdmiTxItSemaphore[unit], ++ dlHdmiTxGetConfig(unit, >mdlHdmiTxDriverConfigTable[unit])!= TM_OK, TMDL_ERR_DLHDMITX_INIT_FAILED) ++ ++#ifndef TMFL_NO_RTOS ++ ++ /* Create message queue associated to this instance/unit */ ++ RETIF_SEM(dlHdmiTxItSemaphore[unit], ++ tmdlHdmiTxIWQueueCreate(gtmdlHdmiTxDriverConfigTable[unit].commandTaskQueueSize, ++ &(unitTableTx[unit].queueHandle)) != TM_OK, TMDL_ERR_DLHDMITX_NO_RESOURCES) ++ ++ /* Create the command task associated to this instance/unit */ ++ RETIF_SEM(dlHdmiTxItSemaphore[unit], ++ tmdlHdmiTxIWTaskCreate(commandTaskTableTx[unit], ++ gtmdlHdmiTxDriverConfigTable[unit].commandTaskPriority, ++ gtmdlHdmiTxDriverConfigTable[unit].commandTaskStackSize, ++ &(unitTableTx[unit].commandTaskHandle)) != TM_OK, TMDL_ERR_DLHDMITX_NO_RESOURCES) ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[unit], ++ tmdlHdmiTxIWTaskStart(unitTableTx[unit].commandTaskHandle) != TM_OK, TMDL_ERR_DLHDMITX_NO_RESOURCES) ++ ++ /* Create the hdcp check task associated to this instance/unit */ ++#ifndef NO_HDCP ++ RETIF_SEM(dlHdmiTxItSemaphore[unit], ++ tmdlHdmiTxIWTaskCreate(hdcpTaskTableTx[unit], ++ gtmdlHdmiTxDriverConfigTable[unit].hdcpTaskPriority, ++ gtmdlHdmiTxDriverConfigTable[unit].hdcpTaskStackSize, ++ &(unitTableTx[unit].hdcpTaskHandle)) != TM_OK, TMDL_ERR_DLHDMITX_NO_RESOURCES) ++#endif /* NO_HDCP */ ++ ++#endif /* TMFL_NO_RTOS */ ++ ++ *pInstance = (tmInstance_t)unit; ++ ++#ifndef NO_HDCP ++ hdcpInfoListTx[unit].bKsvSecure = False; ++ hdcpInfoListTx[unit].hdcpKsvDevices = 0; ++ for(i=0; idisableColorBarOnR0 = False; ++ instanceStatusInfoTx[unit].pColBarState->hdcpColbarChange = False; ++ instanceStatusInfoTx[unit].pColBarState->hdcpEncryptOrT0 = True; ++ instanceStatusInfoTx[unit].pColBarState->hdcpSecureOrT0 = False; ++ instanceStatusInfoTx[unit].pColBarState->inOutFirstSetDone = False; ++ instanceStatusInfoTx[unit].pColBarState->colorBarOn = False; ++ instanceStatusInfoTx[unit].pColBarState->changeColorBarNow = False; ++ ++ instanceStatusInfoTx[unit].pGamutState->gamutOn = False; ++ instanceStatusInfoTx[unit].pGamutState->gamutBufNum = 0; /* use buffer 0 by default */ ++ instanceStatusInfoTx[unit].pGamutState->wideGamutColorSpace = TMDL_HDMITX_EXT_COLORIMETRY_XVYCC601; ++ instanceStatusInfoTx[unit].pGamutState->extColOn = False; ++ instanceStatusInfoTx[unit].pGamutState->yccQR = TMDL_HDMITX_YQR_LIMITED; ++ ++ ++ instanceStatusInfoTx[unit].pAudioInfo->audioMuteState = False; /* Initially audio is not muted */ ++ ++ ++ ++ /* The funcCallback is not the same between BSL, so fill it dynamically */ ++ for(i=0; ivideoInConfig.format, ++ (tmbslHdmiTxPixRate_t)instanceStatusInfoTx[unit].pVideoInfo->videoInConfig.pixelRate); ++ if (errCode != TM_OK) ++ { ++ /* Init failed */ ++ tmbslHdmiTxDeinit(unit); ++ ++ /* Release the sempahore */ ++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[unit]) ) != TM_OK, errCodeSem) ++ ++ return errCode; ++ } ++ else ++ { ++ /* Init passed, continue */ ++ ++ /* Start by forcing the TMDS ouputs off */ ++ errCode = tmbslHdmiTxTmdsSetOutputs(unit, ++ HDMITX_TMDSOUT_FORCED0); ++ RETIF_SEM(dlHdmiTxItSemaphore[unit], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode) ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[unit], ++ (errCode = tmbslHdmiTxHwGetCapabilities(unit, ++ HDMITX_FEATURE_HW_HDCP, &featureSupported) ) != TM_OK, errCode) ++ ++#ifndef NO_HDCP ++ if (featureSupported == True) ++ { ++ dlHdmiTxFindHdcpSeed(unit); ++ } ++#endif /* NO_HDCP */ ++ ++#ifdef TMFL_HDCP_OPTIMIZED_POWER ++ tmbslHdmiTxHdcpPowerDown(unit,True); ++#endif ++ /* Retrieve the hardware device version from the BSL layer */ ++ RETIF_SEM(dlHdmiTxItSemaphore[unit], ++ (errCode = tmbslHdmiTxHwGetVersion(unit,&deviceVersion) ) \ ++ != TM_OK, errCode); ++ ++ /* Store the hardware device version in the global variable */ ++ switch (deviceVersion) ++ { ++ case BSLHDMITX_TDA9984: ++ unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA9984; ++ break; ++ ++ case BSLHDMITX_TDA9989: ++ unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA9989; ++ break; ++ ++ case BSLHDMITX_TDA9981: ++ unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA9981; ++ break; ++ ++ case BSLHDMITX_TDA9983: ++ unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA9983; ++ break; ++ ++ case BSLHDMITX_TDA19989: ++ unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA19989; ++ break; ++ ++ case BSLHDMITX_TDA19988: ++ unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA19988; ++ break; ++ ++ default: ++ unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_UNKNOWN; ++ break; ++ } ++ } ++ ++ ++#ifndef TMFL_NO_RTOS ++ /* Start HDCP check task */ ++ ++#ifndef NO_HDCP ++ RETIF_SEM(dlHdmiTxItSemaphore[unit], ++ tmdlHdmiTxIWTaskStart(unitTableTx[unit].hdcpTaskHandle) != TM_OK, TMDL_ERR_DLHDMITX_NO_RESOURCES) ++#endif /* NO_HDCP */ ++ ++#endif /* TMFL_NO_RTOS */ ++ ++ ++ /* Set the state machine to initialized */ ++ dlHdmiTxSetState(unit, STATE_INITIALIZED); ++ ++ /* Release the sempahore */ ++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[unit]) ) != TM_OK, errCodeSem) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Close an instance of HdmiTx driver. ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxClose ++( ++ tmInstance_t instance ++) ++{ ++ tmErrorCode_t errCode = TM_OK; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check if unit corresponding to instance is opened */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ unitTableTx[instance].opened == False, TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED) ++ ++ /* Close instance */ ++ unitTableTx[instance].opened = False; ++ ++ /* Set the state machine */ ++ dlHdmiTxSetState(instance, STATE_NOT_INITIALIZED); ++ ++ /* Destroy resources allocated for this instance/unit */ ++ ++#ifndef TMFL_NO_RTOS ++ ++#ifndef NO_HDCP ++ tmdlHdmiTxIWTaskDestroy(unitTableTx[instance].hdcpTaskHandle); ++#endif /* NO_HDCP */ ++ ++ tmdlHdmiTxIWTaskDestroy(unitTableTx[instance].commandTaskHandle); ++ tmdlHdmiTxIWQueueDestroy(unitTableTx[instance].queueHandle); ++ ++#endif /* TMFL_NO_RTOS */ ++ ++ /* Reset an instance of an HDMI transmitter */ ++ tmbslHdmiTxDeinit(instance); ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Close the handle to the semaphore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreDestroy(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Set the power state of an instance of the HDMI transmitter. ++ ++ \param instance Instance identifier. ++ \param powerState Power state to set. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetPowerState ++( ++ tmInstance_t instance, ++ tmPowerState_t powerState ++) ++{ ++ tmErrorCode_t errCode; ++ tmbslHdmiTxHotPlug_t hpdStatus; /* HPD status */ ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ if (unitTableTx[instance].deviceVersion == TMDL_HDMITX_DEVICE_TDA9984) ++ { ++ if (powerState == tmPowerSuspend) ++ { ++ return TMDL_ERR_DLHDMITX_NOT_SUPPORTED; ++ } ++ } ++ ++ ++ ++ ++ /* Switch off HDCP */ ++ if ( ((powerState == tmPowerOff) && (unitTableTx[instance].hdcpEnable == True)) ++ || ((powerState == tmPowerStandby) && (unitTableTx[instance].hdcpEnable == True)) ++ || ((powerState == tmPowerSuspend) && (unitTableTx[instance].hdcpEnable == True)) ++ ) ++ { ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ /* Switch off HDCP */ ++ RETIF( (errCode = tmdlHdmiTxSetHdcp(instance, False) ) != TM_OK, errCode) ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ } ++ ++ ++ /* TDA9989, TDA19989 and TDA19988 only */ ++ if ( (unitTableTx[instance].deviceVersion == TMDL_HDMITX_DEVICE_TDA9989) ++ || ++ (unitTableTx[instance].deviceVersion == TMDL_HDMITX_DEVICE_TDA19989) ++ || ++ (unitTableTx[instance].deviceVersion == TMDL_HDMITX_DEVICE_TDA19988)) ++ ++ { ++ if ((powerState != tmPowerOn) && (powerState != tmPowerSuspend)) { ++ dlHdmiTxSetState(instance, STATE_INITIALIZED); ++ } ++ ++ if ((powerState == tmPowerOn) && (unitTableTx[instance].simplayHd == True)) { ++ ++ instanceStatusInfoTx[0].pColBarState->disableColorBarOnR0 = False; ++ instanceStatusInfoTx[0].pColBarState->hdcpColbarChange = False; ++ instanceStatusInfoTx[0].pColBarState->hdcpEncryptOrT0 = True; ++ instanceStatusInfoTx[0].pColBarState->hdcpSecureOrT0 = False; ++ instanceStatusInfoTx[0].pColBarState->inOutFirstSetDone = False; ++ instanceStatusInfoTx[0].pColBarState->colorBarOn = True; ++ instanceStatusInfoTx[0].pColBarState->changeColorBarNow = True; ++ ++ } ++ ++ } ++ ++ /* Set the power state of the transmitter */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPowerSetState(instance, ++ powerState) ) != TM_OK, errCode) ++ ++ /* Get Hot Plug status */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxHotPlugGetStatus(instance, ++ &hpdStatus,False) ) != TM_OK, errCode) ++ ++ if (powerState == tmPowerOn) ++ { ++ if ((hpdStatus == HDMITX_HOTPLUG_ACTIVE) && (dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE)) ++ { ++ /* Yes: Wait for DDC line to settle before reading EDID */ ++ tmbslHdmiTxSysTimerWait(instance, ++ 500); /* ms */ ++ ++ /* Request EDID read */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxEdidRequestBlockData(instance, ++ unitTableTx[instance].pEdidBuffer, (Int)((unitTableTx[instance].edidBufferSize) >> 7), ++ (Int)(unitTableTx[instance].edidBufferSize)) ) != TM_OK, errCode) ++ } ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Get the power state of an instance of the HDMI transmitter. ++ ++ \param instance Instance identifier. ++ \param pPowerState Pointer to the power state. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetPowerState ++( ++ tmInstance_t instance, ++ tmPowerState_t *pPowerState ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if PowerState pointer is Null */ ++ RETIF(pPowerState == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Get the power state of the transmitter */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPowerGetState(instance, ++ pPowerState) ) != TM_OK, errCode) ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Set the configuration of instance attributes. This function is ++ required by DVP architecture rules but actually does nothing in this ++ driver. ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxInstanceConfig ++( ++ tmInstance_t instance ++) ++{ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Setup the instance with its configuration parameters. This function ++ allows basic instance configuration like enabling HDCP, choosing ++ HDCP encryption mode or enabling HDCP repeater mode. ++ ++ \param instance Instance identifier. ++ \param pSetupInfo Pointer to the structure containing all setup parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxInstanceSetup ++( ++ tmInstance_t instance, ++ tmdlHdmiTxInstanceSetupInfo_t *pSetupInfo ++) ++{ ++ tmErrorCode_t errCode; ++#ifndef NO_HDCP ++ UInt16 i; ++#endif ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if SetupInfo pointer is NULL */ ++ RETIF(pSetupInfo == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check if unit corresponding to instance is opened */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ unitTableTx[instance].opened == False, TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED) ++ ++ /* Check the state */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ dlHdmiTxGetState(instance) != STATE_INITIALIZED, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ unitTableTx[instance].repeaterEnable = pSetupInfo->repeaterEnable; ++ unitTableTx[instance].simplayHd = pSetupInfo->simplayHd; ++ unitTableTx[instance].pEdidBuffer = pSetupInfo->pEdidBuffer; ++ unitTableTx[instance].edidBufferSize = pSetupInfo->edidBufferSize; ++ ++#ifndef NO_HDCP ++ /* Reset HDCP DevLib data */ ++ hdcpInfoListTx[instance].hdcpCheckState = TMDL_HDMITX_HDCP_CHECK_NOT_STARTED; ++ hdcpInfoListTx[instance].hdcpErrorState = 0; ++ hdcpInfoListTx[instance].hdcpKsvDevices = 0; ++ hdcpInfoListTx[instance].bKsvSecure = False; ++ for(i=0; i= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if SetupInfo pointer is NULL */ ++ RETIF(pSetupInfo == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check if unit corresponding to instance is opened */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ unitTableTx[instance].opened == False, TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED) ++ ++ pSetupInfo->simplayHd = unitTableTx[instance].simplayHd; ++ pSetupInfo->repeaterEnable = unitTableTx[instance].repeaterEnable; ++ /* JL, TODO */ ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Make device library handle an incoming interrupt. This function is ++ used by application to tell the device library that the hardware ++ sent an interrupt. ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMITX_FULL: the queue is full ++ ++ ******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxHandleInterrupt ++( ++ tmInstance_t instance ++) ++{ ++#ifndef TMFL_NO_RTOS ++ tmErrorCode_t errCode; ++ UInt8 message = 0; ++#else ++ tmErrorCode_t err = TM_OK; ++#endif /* TMFL_NO_RTOS */ ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++#ifndef TMFL_NO_RTOS ++ RETIF( (errCode = tmdlHdmiTxIWQueueSend(unitTableTx[instance].queueHandle, message)) != TM_OK, errCode) ++ ++ /* Disable interrupts for Tx until the callbacks have been done by the command task */ ++ switch(instance) ++ { ++ case INSTANCE_0: ++ tmdlHdmiTxIWDisableInterrupts(TMDL_HDMI_IW_TX_1); ++ break; ++ case INSTANCE_1: ++ tmdlHdmiTxIWDisableInterrupts(TMDL_HDMI_IW_TX_2); ++ break; ++ default: ++ return TMDL_ERR_DLHDMITX_BAD_INSTANCE; ++ } ++#else ++ ++ /* Clear T0 flag before polling for interrupts */ ++ instanceStatusInfoTx[0].pColBarState->hdcpSecureOrT0 = False; ++ ++ if (gI2CDebugAccessesEnabled == True) ++ { ++ ++ err = tmbslHdmiTxHwHandleInterrupt(0); ++ ++ if ((err == TMBSL_ERR_HDMI_I2C_WRITE) || (err == TMBSL_ERR_HDMI_I2C_READ)) ++ { ++ ++ unitTableTx[0].pCallback(TMDL_HDMITX_DEBUG_EVENT_1); ++ } ++ ++ }/* (gI2CDebugAccessesEnabled == True) */ ++ ++ ++#endif /* TMFL_NO_RTOS */ ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Register event callbacks. Only one callback is registered through ++ this API. This callback will received the type of event that ++ occured throug a dedicated parameter and will be called as many ++ times as there is pending events. ++ This function is synchronous. ++ This function is ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pCallback Pointer to the callback function that will handle events ++ from the devlib. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own ++ the resource ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxRegisterCallbacks ++( ++ tmInstance_t instance, ++ ptmdlHdmiTxCallback_t pCallback ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check if unit corresponding to instance is opened */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ unitTableTx[instance].opened == False, TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED) ++ ++ /* Check if instance state is correct */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ dlHdmiTxGetState(instance) != STATE_INITIALIZED, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ /* Store callback pointers */ ++ unitTableTx[instance].pCallback = pCallback; ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief This function allows enabling a specific event. By default, all ++ events are disabled, except input lock. ++ ++ \param instance Instance identifier. ++ \param event Event to enable. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxEnableEvent ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEvent_t event ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if the event exists */ ++ RETIF_BADPARAM(event >= EVENT_NB) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Protect the access to this ressource */ ++ instanceStatusInfoTx[instance].pEventState[event].status = TMDL_HDMITX_EVENT_ENABLED; ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief This function allows disabling a specific event. By default, all ++ events are disabled, except input lock. ++ ++ \param instance Instance identifier. ++ \param event Event to disable. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxDisableEvent ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEvent_t event ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if the event exists */ ++ RETIF_BADPARAM(event >= EVENT_NB) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Protect the access to this ressource */ ++ instanceStatusInfoTx[instance].pEventState[event].status = TMDL_HDMITX_EVENT_DISABLED; ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Get specifications of a given video format. Application can use ++ this function to retreives all specifications (frequencies, ++ resolution, etc.) of a given IA/CEA 861-D video format. ++ This function is synchronous. ++ This function is ISR friendly. ++ ++ \param instance Instance identifier. ++ \param resolutionID ID of the resolution to retrieve specs from. ++ \param pResolutionSpecs Pointer to the structure receiving specs. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN: the resolution is unknown ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetVideoFormatSpecs ++( ++ tmInstance_t instance, ++ tmdlHdmiTxVidFmt_t resolutionID, ++ tmdlHdmiTxVidFmtSpecs_t *pResolutionSpecs ++) ++{ ++ UInt8 i; ++ Bool find = False; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if ResolutionSpecs pointer is Null */ ++ RETIF(pResolutionSpecs == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ for (i = 0; i < RESOLUTION_NB; i++) ++ { ++ if(resolutionID == gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].resolutionID) ++ { ++ find = True; ++ pResolutionSpecs->height = gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].height; ++ pResolutionSpecs->width = gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].width; ++ pResolutionSpecs->interlaced = gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].interlaced; ++ pResolutionSpecs->vfrequency = gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].vfrequency; ++ pResolutionSpecs->aspectRatio = gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].aspectRatio; ++ ++ /* Transformation of 2D-interlaced formats into 3DFP-progressif formats */ ++ if((instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.structure3D == TMDL_HDMITX_3D_FRAME_PACKING) ++ && pResolutionSpecs->interlaced && ((resolutionID == TMDL_HDMITX_VFMT_20_1920x1080i_50Hz) ++ || (resolutionID == TMDL_HDMITX_VFMT_05_1920x1080i_60Hz))) ++ { ++ pResolutionSpecs->interlaced = False; ++ if(pResolutionSpecs->vfrequency == TMDL_HDMITX_VFREQ_50Hz) ++ { ++ pResolutionSpecs->vfrequency = TMDL_HDMITX_VFREQ_25Hz; ++ } ++ else if((pResolutionSpecs->vfrequency == TMDL_HDMITX_VFREQ_60Hz) || (pResolutionSpecs->vfrequency == TMDL_HDMITX_VFREQ_59Hz)) ++ { ++ pResolutionSpecs->vfrequency = TMDL_HDMITX_VFREQ_30Hz; ++ } ++ } ++ ++ break; ++ } ++ } ++ ++ /* Resolution not found in table */ ++ RETIF(find == False, TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Configures all input and output parameters : format, modes, rates, ++ etc. This is the main configuration function of the driver. Here ++ are transmitted all crucial input and output parameters of the ++ device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param videoInputConfig Configuration of the input video. ++ \param videoOutputConfig Configuration of the output video. ++ \param audioInputConfig Configuration of the input audio. ++ \param sinkType Type of sink connected to the output of the Tx. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetInputOutput ++( ++ tmInstance_t instance, ++ tmdlHdmiTxVideoInConfig_t videoInputConfig, ++ tmdlHdmiTxVideoOutConfig_t videoOutputConfig, ++ tmdlHdmiTxAudioInConfig_t audioInputConfig, ++ tmdlHdmiTxSinkType_t sinkType ++) ++{ ++ tmErrorCode_t errCode; ++ UInt8 pixRepeat; /* Pixel repetition */ ++ tmbslHdmiTxVoutDbits_t pathBits; /* Data path bit width */ ++ tmbslHdmiTxPixEdge_t pixelEdge; /* Pixel sampling edge */ ++ tmbslHdmiTxVsMeth_t syncMethod; /* Sync method */ ++ tmbslHdmiTxPixTogl_t toggle; /* Toggling */ ++ UInt8 syncIn; /* Embedded or external */ ++ tmbslHdmiTxPixSubpkt_t spSync; /* Subpacket sync */ ++ tmbslHdmiTxBlnkSrc_t blankit; /* Blanking */ ++ tmbslHdmiTxPixRate_t pixRateSingleDouble; /* HDMITX_PIXRATE_SINGLE */ ++ UInt16 uRefPix; /* REFPIX for output */ ++ UInt16 uRefLine; /* REFLINE for output */ ++ UInt16 uScRefPix=0; /* REFPIX for scaler */ ++ UInt16 uScRefLine=0; /* REFLINE for scaler */ ++ Bool bVerified; /* Scaler setting verified */ ++ tmbslHdmiTxTopSel_t topSel; /* Adjustment for interlaced output */ ++ tmbslHdmiTxHPhases_t phasesH; /* Horizontal phase */ ++ tmbslHdmiTxVsOnce_t once; /* Line/pixel counters sync */ ++ tmbslHdmiTxScaMode_t scalerMode; /* Current scaler mode */ ++ Bool OBASupported; /* OBA supported or not */ ++ Bool DSTSupported; /* DST supported or not */ ++ Bool HBRSupported; /* HBR supporeted or not */ ++ ++ UInt8 *pSwapTable = Null; /* Initialized after (depend on video mode used) */ ++ UInt8 *pMirrorTable = Null; /* Initialized after (depend on video mode used) */ ++#ifdef TMFL_RGB_DDR_12BITS ++ UInt8 *pMux = Null; /* Initialized after (depend on video mode used) */ ++#endif ++ UInt8 *pEnaVideoPortTable = Null; /* Initialized after (depend on video mode used) */ ++ UInt8 *pGndVideoPortTable = Null; /* Initialized after (depend on video mode used) */ ++ tmdlHdmiTxVidFmt_t vinFmtIndex; /* index in table kVfmtToShortFmt_TV */ ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Update the instance status information */ ++ instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.format = videoInputConfig.format; ++ instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.mode = videoInputConfig.mode; ++ instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.syncSource = videoInputConfig.syncSource; ++ instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.pixelRate = videoInputConfig.pixelRate; ++ instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.structure3D = videoInputConfig.structure3D; ++ ++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format = videoOutputConfig.format; ++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode = videoOutputConfig.mode; ++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.colorDepth = videoOutputConfig.colorDepth; ++ ++ /* TODO */ ++ /*instanceStatusInfoTx[instance].pVideoInfo->videoMuteState = */ ++ ++ /* Audio OBA support */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxHwGetCapabilities(instance, ++ HDMITX_FEATURE_HW_AUDIO_OBA, &OBASupported) ) != TM_OK, errCode) ++ ++ /* Audio DST support */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxHwGetCapabilities(instance, ++ HDMITX_FEATURE_HW_AUDIO_DST, &DSTSupported) ) != TM_OK, errCode) ++ ++ /* Audio HBR support */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxHwGetCapabilities(instance, ++ HDMITX_FEATURE_HW_AUDIO_HBR, &HBRSupported) ) != TM_OK, errCode) ++ ++ /* Test if audio input format is supported */ ++ if ( ((audioInputConfig.format == TMDL_HDMITX_AFMT_OBA) && (OBASupported == False)) || ++ ((audioInputConfig.format == TMDL_HDMITX_AFMT_DST) && (DSTSupported == False)) || ++ ((audioInputConfig.format == TMDL_HDMITX_AFMT_HBR) && (HBRSupported == False)) ) ++ { ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TMDL_ERR_DLHDMITX_NOT_SUPPORTED; ++ } ++ ++ instanceStatusInfoTx[instance].pAudioInfo->audioInCfg.format = audioInputConfig.format; ++ instanceStatusInfoTx[instance].pAudioInfo->audioInCfg.i2sFormat = audioInputConfig.i2sFormat; ++ instanceStatusInfoTx[instance].pAudioInfo->audioInCfg.i2sQualifier = audioInputConfig.i2sQualifier; ++ instanceStatusInfoTx[instance].pAudioInfo->audioInCfg.rate = audioInputConfig.rate; ++ instanceStatusInfoTx[instance].pAudioInfo->audioInCfg.channelAllocation = audioInputConfig.channelAllocation; ++ ++ ++ if (sinkType == TMDL_HDMITX_SINK_EDID) ++ { ++ /* Change sink type with the currently defined in EDID */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxEdidGetSinkType(instance, ++ (tmbslHdmiTxSinkType_t *)&sinkType) ) != TM_OK, errCode) ++ } ++ ++ /* forbid format with pixel repetition in DVI */ ++ if (sinkType == TMDL_HDMITX_SINK_DVI) ++ { ++ if(((videoOutputConfig.format >= TMDL_HDMITX_VFMT_06_720x480i_60Hz) && (videoOutputConfig.format <= TMDL_HDMITX_VFMT_15_1440x480p_60Hz)) ++ || ((videoOutputConfig.format >= TMDL_HDMITX_VFMT_21_720x576i_50Hz) && (videoOutputConfig.format <= TMDL_HDMITX_VFMT_30_1440x576p_50Hz)) ++ || ((videoOutputConfig.format >= TMDL_HDMITX_VFMT_35_2880x480p_60Hz)&& (videoOutputConfig.format <= TMDL_HDMITX_VFMT_38_2880x576p_50Hz)) ++ ) ++ { ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TMDL_ERR_DLHDMITX_BAD_PARAMETER; ++ } ++ } ++ ++ /* Set color depth according to output config, transmitter termination is disable */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxSetColorDepth(instance, ++ (tmbslHdmiTxColorDepth)(videoOutputConfig.colorDepth), False) ) != TM_OK, errCode) ++ ++ /* Set the TMDS outputs to a forced state */ ++ errCode = tmbslHdmiTxTmdsSetOutputs(instance, ++ HDMITX_TMDSOUT_FORCED0); ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode) ++ ++ /* Fine-tune the TMDS serializer */ ++ errCode = tmbslHdmiTxTmdsSetSerializer(instance, ++ 4, 8); ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode) ++ ++ /* Set video output configuration */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxVideoOutSetConfig(instance, ++ (tmbslHdmiTxSinkType_t)sinkType, (tmbslHdmiTxVoutMode_t)videoOutputConfig.mode, HDMITX_VOUT_PREFIL_OFF, ++ HDMITX_VOUT_YUV_BLNK_16, HDMITX_VOUT_QRANGE_FS) ) != TM_OK, errCode) ++ ++ /* Set default config */ ++ pixRepeat = HDMITX_PIXREP_DEFAULT; ++ pathBits = HDMITX_VOUT_DBITS_12; ++ pixelEdge = HDMITX_PIXEDGE_CLK_POS; ++ syncMethod = HDMITX_VSMETH_V_H; ++ toggle = HDMITX_PIXTOGL_ENABLE; ++ ++ /* Set sync details */ ++ if (videoInputConfig.syncSource == TMDL_HDMITX_SYNCSRC_EMBEDDED) ++ { ++ /* Embedded sync */ ++ syncIn = EMB; ++ spSync = HDMITX_PIXSUBPKT_SYNC_HEMB; ++ blankit = HDMITX_BLNKSRC_VS_HEMB_VEMB; ++ syncMethod = HDMITX_VSMETH_V_XDE; ++ } ++ else ++ { ++ /* External sync */ ++ syncIn = EXT; ++ ++ ++ if (gtmdlHdmiTxDriverConfigTable[instance].dataEnableSignalAvailable == 1) ++ { ++ /* DE is available */ ++ spSync = HDMITX_PIXSUBPKT_SYNC_DE; ++ } ++ else ++ { ++ /* DE is NOT available */ ++ spSync = HDMITX_PIXSUBPKT_SYNC_HS; ++ } ++ ++ ++ ++ blankit = HDMITX_BLNKSRC_NOT_DE; ++ } ++ ++ ++#ifdef TMFL_RGB_DDR_12BITS ++ /* by default, mux is not used */ ++ pMux = >mdlHdmiTxDriverConfigTable[instance].pNoMux[0]; ++#endif ++ ++ /* Port swap table */ ++ switch(videoInputConfig.mode) ++ { ++ case TMDL_HDMITX_VINMODE_CCIR656: ++ pathBits = HDMITX_VOUT_DBITS_8; ++ pixelEdge = HDMITX_PIXEDGE_CLK_NEG; ++ pSwapTable = gtmdlHdmiTxDriverConfigTable[instance].pSwapTableCCIR656; ++ pMirrorTable = gtmdlHdmiTxDriverConfigTable[instance].pMirrorTableCCIR656; ++#ifdef TMFL_RGB_DDR_12BITS ++ pMux = >mdlHdmiTxDriverConfigTable[instance].pMux_RGB_DDR_12bits[0]; ++#endif ++ pEnaVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pEnableVideoPortCCIR656; ++ pGndVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pGroundVideoPortCCIR656; ++ break; ++ ++ case TMDL_HDMITX_VINMODE_RGB444: ++ pSwapTable = gtmdlHdmiTxDriverConfigTable[instance].pSwapTableRGB444; ++ pMirrorTable = gtmdlHdmiTxDriverConfigTable[instance].pMirrorTableRGB444; ++ pEnaVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pEnableVideoPortRGB444; ++ pGndVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pGroundVideoPortRGB444; ++ break; ++ ++ case TMDL_HDMITX_VINMODE_YUV444: ++ pSwapTable = gtmdlHdmiTxDriverConfigTable[instance].pSwapTableYUV444; ++ pMirrorTable = gtmdlHdmiTxDriverConfigTable[instance].pMirrorTableYUV444; ++ pEnaVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pEnableVideoPortYUV444; ++ pGndVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pGroundVideoPortYUV444; ++ break; ++ ++ case TMDL_HDMITX_VINMODE_YUV422: ++ pSwapTable = gtmdlHdmiTxDriverConfigTable[instance].pSwapTableYUV422; ++ pMirrorTable = gtmdlHdmiTxDriverConfigTable[instance].pMirrorTableYUV422; ++#ifdef TMFL_RGB_DDR_12BITS ++ pMux = >mdlHdmiTxDriverConfigTable[instance].pMux_RGB_DDR_12bits[0]; ++#endif ++ pEnaVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pEnableVideoPortYUV422; ++ pGndVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pGroundVideoPortYUV422; ++ break; ++ ++#ifdef TMFL_RGB_DDR_12BITS ++ case TMDL_HDMITX_VINMODE_RGB_DDR_12BITS: ++ pSwapTable = gtmdlHdmiTxDriverConfigTable[instance].pSwapTableRGB_DDR_12bits; ++ pMirrorTable = gtmdlHdmiTxDriverConfigTable[instance].pMirrorTableRGB_DDR_12bits; ++ pMux = >mdlHdmiTxDriverConfigTable[instance].pMux_RGB_DDR_12bits[0]; ++ pEnaVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pEnableVideoPortRGB_DDR_12bits; ++ pGndVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pGroundVideoPortRGB_DDR_12bits; ++ break; ++#endif ++ default: ++ break; ++ } ++ ++ /* Set the audio and video input port configuration */ ++ errCode = tmbslHdmiTxSetVideoPortConfig(instance, pEnaVideoPortTable, pGndVideoPortTable); ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode); ++ ++#ifdef TMFL_RGB_DDR_12BITS ++ errCode = tmbslHdmiTxVideoInSetMapping(instance, pSwapTable, pMirrorTable, pMux); ++#else ++ errCode = tmbslHdmiTxVideoInSetMapping(instance, pSwapTable, pMirrorTable); ++#endif ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode); ++ ++ /* Set fine image position */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxVideoInSetFine(instance, spSync, HDMITX_PIXTOGL_NO_ACTION) ) != TM_OK, errCode); ++ ++ /* Set input blanking */ ++ errCode = tmbslHdmiTxVideoInSetBlanking(instance, blankit, HDMITX_BLNKCODE_ALL_0); ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode); ++ ++ /* Configure video input options and control the upsampler */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxVideoInSetConfig(instance, ++ (tmbslHdmiTxVinMode_t)videoInputConfig.mode, (tmbslHdmiTxVidFmt_t)videoOutputConfig.format, ++ (tmbslHdmiTx3DStructure_t)videoInputConfig.structure3D, pixelEdge, ++ (tmbslHdmiTxPixRate_t)videoInputConfig.pixelRate, HDMITX_UPSAMPLE_AUTO) ) != TM_OK, errCode); ++ ++ ++ /* Set input ouput - may give NOT_SUPPORTED error */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxVideoSetInOut(instance, (tmbslHdmiTxVidFmt_t)videoInputConfig.format, ++ (tmbslHdmiTx3DStructure_t)videoInputConfig.structure3D, ++ HDMITX_SCAMODE_AUTO, (tmbslHdmiTxVidFmt_t)videoOutputConfig.format, ++ pixRepeat, HDMITX_MATMODE_AUTO, pathBits, (tmbslHdmiTxVQR_t) videoOutputConfig.dviVqr) ) != TM_OK, errCode); ++ ++ ++ /* Only set audio for HDMI, not DVI */ ++ if (sinkType == TMDL_HDMITX_SINK_HDMI) ++ { ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ /* Set audio parameters */ ++ RETIF( (errCode = tmdlHdmiTxSetAudioInput(instance, audioInputConfig, sinkType) ) != TM_OK, errCode) ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ } ++ ++ /* Output fine adjustment */ ++ pixRateSingleDouble = (tmbslHdmiTxPixRate_t)videoInputConfig.pixelRate; ++ if (videoInputConfig.pixelRate == HDMITX_PIXRATE_SINGLE_REPEATED) ++ { ++ pixRateSingleDouble = HDMITX_PIXRATE_SINGLE; ++ } ++ ++ ++ if ((videoInputConfig.structure3D != HDMITX_3D_FRAME_PACKING) && ++ dlHdmiTxGetReflineRefpix(videoInputConfig.format, videoInputConfig.mode, videoOutputConfig.format, ++ syncIn, (tmdlHdmiTxPixRate_t)pixRateSingleDouble, &uRefPix, &uRefLine, ++ &uScRefPix, &uScRefLine, &bVerified) > 0) ++ { ++ /* From 720p50/60 or 1080i50/60 up-scaling to 1080p50/60, when external sync, ++ toggleV, toggleH and toggleX need to be set to 0 */ ++ if (syncIn == EXT) ++ { ++ switch (videoInputConfig.format) ++ { ++ case TMDL_HDMITX_VFMT_04_1280x720p_60Hz: ++ case TMDL_HDMITX_VFMT_19_1280x720p_50Hz: ++ case TMDL_HDMITX_VFMT_05_1920x1080i_60Hz: ++ case TMDL_HDMITX_VFMT_20_1920x1080i_50Hz: ++ if ( (videoOutputConfig.format == TMDL_HDMITX_VFMT_16_1920x1080p_60Hz) ++ || (videoOutputConfig.format == TMDL_HDMITX_VFMT_31_1920x1080p_50Hz) ) ++ { ++ toggle = HDMITX_PIXTOGL_NO_ACTION; ++ } ++ break; ++ default: ++ toggle = HDMITX_PIXTOGL_ENABLE; ++ break; ++ } ++ } ++ ++ /* Combination found in table for scaler: configure input manually */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxVideoInSetSyncManual(instance, ++ (tmbslHdmiTxSyncSource_t)videoInputConfig.syncSource, syncMethod, toggle, toggle, toggle, uRefPix, uRefLine) ) != TM_OK, errCode) ++ } ++ else ++ { ++ /* Not found so assume non-scaler and auto-configure input */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxVideoInSetSyncAuto(instance, ++ (tmbslHdmiTxSyncSource_t)videoInputConfig.syncSource, (tmbslHdmiTxVidFmt_t)videoInputConfig.format, ++ (tmbslHdmiTxVinMode_t)videoInputConfig.mode, (tmbslHdmiTx3DStructure_t)videoInputConfig.structure3D)) != TM_OK, errCode) ++ } ++ ++ /* Only set infoframes for HDMI, not DVI */ ++ if (sinkType == TMDL_HDMITX_SINK_HDMI) ++ { ++ /* Set avi infoframe */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = dlHdmiTxSetVideoInfoframe(instance, videoOutputConfig.format, videoOutputConfig.mode) ) != TM_OK, ++ errCode) ++ } ++ ++ errCode = tmbslHdmiTxScalerGetMode(instance, ++ &scalerMode); ++ ++ /* Ignore scaler TMBSL_ERR_HDMI_NOT_SUPPORTED error */ ++ if ((errCode == TM_OK) && (scalerMode == HDMITX_SCAMODE_ON)) ++ { ++ /* Enable scaler mode */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxScalerInDisable(instance, ++ False) ) != TM_OK, errCode) ++ ++ /* Correction to interlace */ ++ topSel = HDMITX_TOPSEL_INTERNAL; ++ if ((videoOutputConfig.format == TMDL_HDMITX_VFMT_05_1920x1080i_60Hz) ++ || (videoOutputConfig.format == TMDL_HDMITX_VFMT_20_1920x1080i_50Hz)) ++ { ++ /* video input format is range-checked by tmbslHdmiTxVideoSetInOut above */ ++ vinFmtIndex = dlHdmiTxCalcVidFmtIndex(videoInputConfig.format); ++ if ((kVfmtToShortFmt_TV[vinFmtIndex] == TV_480p_60Hz) ++ || (kVfmtToShortFmt_TV[vinFmtIndex] == TV_576p_50Hz)) ++ { ++ /* Correct for 1080i output for p->i conversion only */ ++ topSel = HDMITX_TOPSEL_VRF; ++ } ++ } ++ ++ /* Set scaler field positions */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxScalerSetFieldOrder(instance, ++ HDMITX_INTEXT_NO_CHANGE, HDMITX_INTEXT_NO_CHANGE, topSel, HDMITX_TOPTGL_NO_CHANGE) ) != TM_OK, errCode) ++ ++ /* Scaler fine adjustment */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxScalerSetFine(instance, ++ uScRefPix, uScRefLine) ) != TM_OK, errCode) ++ ++ if ((videoOutputConfig.format == TMDL_HDMITX_VFMT_16_1920x1080p_60Hz) ++ || (videoOutputConfig.format == TMDL_HDMITX_VFMT_31_1920x1080p_50Hz)) ++ { ++ phasesH = HDMITX_H_PHASES_16; ++ } ++ else ++ { ++ phasesH = HDMITX_H_PHASES_15; ++ } ++ ++ /* Set scaler phase */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxScalerSetPhase(instance, ++ phasesH) ) != TM_OK, errCode) ++ ++ /* Set scaler latency */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxScalerSetLatency(instance, ++ 0x22) ) != TM_OK, errCode) ++ ++ /* Set scaler synchronisation option */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxScalerSetSync(instance, ++ syncMethod, HDMITX_VSONCE_EACH_FRAME) ) != TM_OK, errCode) ++ ++ /* With scaler, use Only Once setting for tmbslHdmiTxVideoOutSetSync */ ++ once = HDMITX_VSONCE_ONCE; ++ } ++ else ++ { ++ once = HDMITX_VSONCE_EACH_FRAME; ++ } ++ ++ /* Set video synchronisation */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxVideoOutSetSync(instance, ++ HDMITX_VSSRC_INTERNAL, HDMITX_VSSRC_INTERNAL, HDMITX_VSSRC_INTERNAL, ++ HDMITX_VSTGL_TABLE, once) ) != TM_OK, errCode) ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ instanceStatusInfoTx[instance].pColBarState->inOutFirstSetDone = True; ++ ++ /* Test if pattern is already on */ ++ if (instanceStatusInfoTx[instance].pColBarState->colorBarOn == True) ++ { ++ /* If pattern is On, apply new settings */ ++ instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = True; ++ } ++ ++ return TM_OK; ++} ++ ++/*****************************************************************************/ ++/** ++ \brief Configures audio input parameters : format, rate, etc. ++ This function is similar to tmdlHdmiTxSetInputOutput except that ++ video is not reconfigured. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param audioInputConfig Configuration of the input audio. ++ \param sinkType Type of sink connected to the output of the Tx. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetAudioInput ++( ++ tmInstance_t instance, ++ tmdlHdmiTxAudioInConfig_t audioInputConfig, ++ tmdlHdmiTxSinkType_t sinkType ++) ++{ ++ tmErrorCode_t errCode; ++ tmdlHdmiTxVidFmtSpecs_t resolutionSpecs; /* Used to convert video format to video frequency */ ++ UInt8 layout; /* 0 or 1 */ ++ UInt8 aifChannelCountCode = 0; /* audio info frame channels */ ++ tmbslHdmiTxVfreq_t vOutFreq; /* Vertical output frequency */ ++ tmbslHdmiTxctsRef_t ctsRef; /* CTS ref source */ ++ UInt16 uCtsX; /* CtsX value */ ++ tmbslHdmiTxPktAif_t pktAif; /* Audio infoframe packet */ ++ Bool OBASupported; /* OBA supported or not */ ++ Bool DSTSupported; /* DST supported or not */ ++ Bool HBRSupported; /* HBR supporeted or not */ ++ UInt8 *pEnaAudioPortCfg; ++ UInt8 *pGndAudioPortCfg; ++ UInt8 *pEnaAudioClockPortCfg; ++ UInt8 *pGndAudioClockPortCfg; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the semaphore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Audio OBA support */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxHwGetCapabilities(instance, ++ HDMITX_FEATURE_HW_AUDIO_OBA, &OBASupported) ) != TM_OK, errCode) ++ ++ /* Audio DST support */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxHwGetCapabilities(instance, ++ HDMITX_FEATURE_HW_AUDIO_DST, &DSTSupported) ) != TM_OK, errCode) ++ ++ /* Audio HBR support */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxHwGetCapabilities(instance, ++ HDMITX_FEATURE_HW_AUDIO_HBR, &HBRSupported) ) != TM_OK, errCode) ++ ++ /* Test if audio input format is supported */ ++ if ( ((audioInputConfig.format == TMDL_HDMITX_AFMT_OBA) && (OBASupported == False)) || ++ ((audioInputConfig.format == TMDL_HDMITX_AFMT_DST) && (DSTSupported == False)) || ++ ((audioInputConfig.format == TMDL_HDMITX_AFMT_HBR) && (HBRSupported == False)) ) ++ { ++ /* Release the semaphore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TMDL_ERR_DLHDMITX_NOT_SUPPORTED; ++ } ++ ++ if (sinkType == TMDL_HDMITX_SINK_EDID) ++ { ++ /* Change sink type with the currently defined in EDID */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxEdidGetSinkType(instance, ++ (tmbslHdmiTxSinkType_t *)&sinkType) ) != TM_OK, errCode) ++ } ++ ++ if (sinkType == TMDL_HDMITX_SINK_HDMI) ++ { ++ /* Set audio layout */ ++ layout = 1; ++ if (audioInputConfig.channelAllocation == 0x00) { ++ layout = 0; ++ } ++ aifChannelCountCode = kChanAllocChanNum[audioInputConfig.channelAllocation] - 1; ++ ++ /* Port audio configuration */ ++ switch(audioInputConfig.format) ++ { ++ case TMDL_HDMITX_AFMT_SPDIF: ++ pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortSPDIF; ++ pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortSPDIF; ++ pEnaAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioClockPortSPDIF; ++ pGndAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioClockPortSPDIF; ++ break; ++ ++ case TMDL_HDMITX_AFMT_I2S: ++ pEnaAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioClockPortI2S; ++ pGndAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioClockPortI2S; ++ ++ if(audioInputConfig.channelAllocation >= 1 ) /* For Multi channels */ ++ { ++ pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortI2S8C; ++ pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortI2S8C; ++ } ++ else ++ { ++ pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortI2S; ++ pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortI2S; ++ } ++ break; ++ ++ case TMDL_HDMITX_AFMT_OBA: ++ pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortOBA; ++ pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortOBA; ++ pEnaAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioClockPortOBA; ++ pGndAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioClockPortOBA; ++ break; ++ ++ case TMDL_HDMITX_AFMT_DST: ++ pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortDST; ++ pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortDST; ++ pEnaAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioClockPortDST; ++ pGndAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioClockPortDST; ++ break; ++ ++ case TMDL_HDMITX_AFMT_HBR: ++ pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortHBR; ++ pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortHBR; ++ pEnaAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioClockPortHBR; ++ pGndAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioClockPortHBR; ++ break; ++ ++ default: ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TMDL_ERR_DLHDMITX_BAD_PARAMETER; ++ } ++ ++ errCode = tmbslHdmiTxSetAudioPortConfig(instance, ++ pEnaAudioPortCfg, pGndAudioPortCfg); ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode) ++ ++ errCode = tmbslHdmiTxSetAudioClockPortConfig(instance, ++ pEnaAudioClockPortCfg, pGndAudioClockPortCfg); ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode) ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxAudioInSetConfig(instance, ++ (tmbslHdmiTxaFmt_t)audioInputConfig.format, (tmbslHdmiTxI2sFor_t)audioInputConfig.i2sFormat, ++ audioInputConfig.channelAllocation, HDMITX_CHAN_NO_CHANGE, HDMITX_CLKPOLDSD_NO_CHANGE, HDMITX_SWAPDSD_NO_CHANGE, ++ layout, HDMITX_LATENCY_CURRENT, (tmbslHdmiTxDstRate_t)audioInputConfig.dstRate) ) != TM_OK, errCode) ++ ++ /* Find output vertical frequency from output format */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmdlHdmiTxGetVideoFormatSpecs(instance, instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format, ++ &resolutionSpecs) ) != TM_OK, errCode) ++ vOutFreq = (tmbslHdmiTxVfreq_t)resolutionSpecs.vfrequency; ++ ++ if ((audioInputConfig.format == TMDL_HDMITX_AFMT_SPDIF) ++ || (audioInputConfig.format == TMDL_HDMITX_AFMT_OBA)) ++ { ++ ctsRef = HDMITX_CTSREF_FS64SPDIF; ++ uCtsX = HDMITX_CTSX_64; ++ } ++ else /* I2S */ ++ { ++ ctsRef = HDMITX_CTSREF_ACLK; ++ if (audioInputConfig.i2sQualifier == TMDL_HDMITX_I2SQ_32BITS) ++ { ++ uCtsX = HDMITX_CTSX_64; ++ } ++ else ++ { ++ uCtsX = HDMITX_CTSX_32; ++ } ++ } ++ ++ /* Set the Clock Time Stamp generator in HDMI mode only */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxAudioInSetCts(instance, ++ ctsRef, (tmbslHdmiTxafs_t)audioInputConfig.rate, (tmbslHdmiTxVidFmt_t)instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format, ++ vOutFreq, HDMITX_CTS_AUTO, uCtsX, HDMITX_CTSK_USE_CTSX, HDMITX_CTSMTS_USE_CTSX, ++ (tmbslHdmiTxDstRate_t)audioInputConfig.dstRate) ) != TM_OK, errCode) ++ ++ /* Set Channel Status registers ++ No need to call tmbslTDA9984AudioOutSetChanStatusMapping, since default Byte 2 ++ values of "Do not take into account" are adequate */ ++ ++ ++ if (audioInputConfig.format != TMDL_HDMITX_AFMT_SPDIF) /* channel status automatically copied from SPDIF*/ ++ { ++ ++ if (audioInputConfig.format != TMDL_HDMITX_AFMT_HBR) { ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxAudioOutSetChanStatus(instance, ++ (tmbslHdmiTxAudioData_t)audioInputConfig.channelStatus.PcmIdentification, ++ (tmbslHdmiTxCSformatInfo_t)audioInputConfig.channelStatus.FormatInfo, ++ (tmbslHdmiTxCScopyright_t)audioInputConfig.channelStatus.CopyrightInfo, ++ audioInputConfig.channelStatus.categoryCode, ++ (tmbslHdmiTxafs_t)audioInputConfig.rate, ++ (tmbslHdmiTxCSclkAcc_t)audioInputConfig.channelStatus.clockAccuracy, ++ (tmbslHdmiTxCSmaxWordLength_t)audioInputConfig.channelStatus.maxWordLength, ++ (tmbslHdmiTxCSwordLength_t)audioInputConfig.channelStatus.wordLength, ++ (tmbslHdmiTxCSorigAfs_t)audioInputConfig.channelStatus.origSampleFreq))!= TM_OK, errCode) ++ } ++ else { ++ ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxAudioOutSetChanStatus(instance, ++ (tmbslHdmiTxAudioData_t)audioInputConfig.channelStatus.PcmIdentification, ++ (tmbslHdmiTxCSformatInfo_t)audioInputConfig.channelStatus.FormatInfo, ++ (tmbslHdmiTxCScopyright_t)audioInputConfig.channelStatus.CopyrightInfo, ++ audioInputConfig.channelStatus.categoryCode, ++ HDMITX_AFS_768K, ++ (tmbslHdmiTxCSclkAcc_t)audioInputConfig.channelStatus.clockAccuracy, ++ (tmbslHdmiTxCSmaxWordLength_t)audioInputConfig.channelStatus.maxWordLength, ++ (tmbslHdmiTxCSwordLength_t)audioInputConfig.channelStatus.wordLength, ++ (tmbslHdmiTxCSorigAfs_t)audioInputConfig.channelStatus.origSampleFreq))!= TM_OK, errCode) ++ ++ ++ } ++ ++ } ++ ++ ++ /* Set reset_fifo to 1 */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxAudioOutSetMute(instance, ++ HDMITX_AMUTE_ON) ) != TM_OK, errCode) ++ ++ /* UN Mute audio only if previously not muted */ ++ if (instanceStatusInfoTx[instance].pAudioInfo->audioMuteState == False) { ++ ++ /* Wait for 20 ms */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance],(errCode = tmdlHdmiTxIWWait(20) ) != TM_OK, errCode) ++ /* Set reset_fifo to 0 */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxAudioOutSetMute(instance, ++ HDMITX_AMUTE_OFF) ) != TM_OK, errCode) ++ ++ } ++ ++ ++ /* Set audio infoframe */ ++ pktAif.ChannelCount = aifChannelCountCode; ++ pktAif.CodingType = 0; /* refer to stream header */ ++ pktAif.SampleSize = 0; /* refer to stream header */ ++ pktAif.ChannelAlloc = audioInputConfig.channelAllocation; ++ pktAif.LevelShift = 0; /* 0dB level shift */ ++ pktAif.DownMixInhibit = 0; /* down-mix stereo permitted */ ++ pktAif.SampleFreq = AIF_SF_REFER_TO_STREAM_HEADER; /* refer to stream header */ ++ ++ /* SampleFreq parameter need to be set for OBA and DST audio stream */ ++ if ( (audioInputConfig.format == TMDL_HDMITX_AFMT_OBA) || ++ (audioInputConfig.format == TMDL_HDMITX_AFMT_DST) ) ++ { ++ switch (audioInputConfig.rate) ++ { ++ case TMDL_HDMITX_AFS_32K: ++ pktAif.SampleFreq = AIF_SF_32K; /* see table 18 of CEA-861 */ ++ break; ++ case TMDL_HDMITX_AFS_44K: ++ pktAif.SampleFreq = AIF_SF_44K; ++ break; ++ case TMDL_HDMITX_AFS_48K: ++ pktAif.SampleFreq = AIF_SF_48K; ++ break; ++ case TMDL_HDMITX_AFS_88K: ++ pktAif.SampleFreq = AIF_SF_88K; ++ break; ++ case TMDL_HDMITX_AFS_96K: ++ pktAif.SampleFreq = AIF_SF_96K; ++ break; ++ case TMDL_HDMITX_AFS_176K: ++ pktAif.SampleFreq = AIF_SF_176K; ++ break; ++ case TMDL_HDMITX_AFS_192K: ++ pktAif.SampleFreq = AIF_SF_192K; ++ break; ++ default: ++ pktAif.SampleFreq = AIF_SF_REFER_TO_STREAM_HEADER; /* refer to stream header */ ++ break; ++ } ++ } ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetAudioInfoframe(instance, ++ &pktAif, True) ) != TM_OK, errCode) ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Defines the content of AVI infoframe to be sent by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pAviIfData Pointer to the structure containing AVI infoframe ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetVideoInfoframe ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxAviIfData_t *pAviIfData ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ if (enable == True) ++ { ++ /* Check if AviIfData pointer is Null */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pAviIfData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ errCode = dlHdmiTxSetRawVideoInfoframe(instance, pAviIfData, enable); ++ } ++ else ++ { ++ errCode = dlHdmiTxSetRawVideoInfoframe(instance, Null, enable); ++ } ++ ++ /* Ignore infoframe interlock in DVI mode */ ++ if (errCode == TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ { ++ errCode = TM_OK; ++ } ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], errCode != TM_OK, errCode) ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Defines the content of AUD infoframe to be sent by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pAudIfData Pointer to the structure containing AUD infoframe ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetAudioInfoframe ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxAudIfData_t *pAudIfData ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ if (enable == True) ++ { ++ /* Check if AudIfData pointer is Null */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pAudIfData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetAudioInfoframe(instance, ++ (tmbslHdmiTxPktAif_t *)pAudIfData, enable) ) != TM_OK, errCode) ++ } ++ else ++ { ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetAudioInfoframe(instance, ++ Null, enable) ) != TM_OK, errCode) ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Defines the content of the audio content protection packet to be ++ sent by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pAcpPktData Pointer to the structure containing ACP infoframe ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetACPPacket ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxAcpPktData_t *pAcpPktData ++) ++{ ++ tmErrorCode_t errCode; ++ tmbslHdmiTxPkt_t pkt; ++ UInt8 i; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ if (enable == True) ++ { ++ /* Check if AcpPktData pointer is Null */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pAcpPktData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ switch (pAcpPktData->acpType) ++ { ++ /* Make sure bytes reserved are 0 */ ++ case 0 : /* Generic audio */ ++ for (i=0; i<28; i++) { pkt.dataByte[i] = 0; } ++ break; ++ ++ case 1 : /* IEC 60958 identified audio */ ++ for (i=0; i<28; i++) { pkt.dataByte[i] = 0; } ++ break; ++ ++ case 2 : /* DVD Audio */ ++ for (i=0; i<2; i++) { pkt.dataByte[i] = pAcpPktData->acpData[i]; } ++ for (i=2; i<28; i++) { pkt.dataByte[i] = 0; } ++ break; ++ ++ case 3 : /* SuperAudio CD */ ++ for (i=0; i<17; i++) { pkt.dataByte[i] = pAcpPktData->acpData[i]; } ++ for (i=17; i<28; i++) { pkt.dataByte[i] = 0; } ++ break; ++ ++ default : ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ return TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS; ++ } ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetAcp(instance, ++ &pkt, 28, pAcpPktData->acpType, enable) ) != TM_OK, errCode) ++ } ++ else ++ { ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetAcp(instance, ++ Null, 0, 0, enable) ) != TM_OK, errCode) ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Defines the content of the General Control packet to be sent by Tx ++ device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pGcpPktData Pointer to the structure containing GCP packet parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetGeneralControlPacket ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxGcpPktData_t *pGcpPktData ++) ++{ ++ tmErrorCode_t errCode; ++ tmbslHdmiTxaMute_t aMute; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ if (enable == True) ++ { ++ /* Check if GcpPktData pointer is Null */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pGcpPktData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ if(pGcpPktData->avMute == False) ++ { ++ aMute = HDMITX_AMUTE_OFF; ++ } ++ else ++ { ++ aMute = HDMITX_AMUTE_ON; ++ } ++ ++ /* Set contents of general control packet & enable/disable packet insertion */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetGeneralCntrl(instance, ++ &aMute, enable) ) != TM_OK, errCode) ++ } ++ else ++ { ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetGeneralCntrl(instance, ++ Null, enable) ) != TM_OK, errCode) ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Defines the content of ISRC1 packet to be sent by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pIsrc1PktData Pointer to the structure containing GCP packet parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetISRC1Packet ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxIsrc1PktData_t *pIsrc1PktData ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ if (enable == True) ++ { ++ /* Check if Isrc1PktData pointer is Null */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pIsrc1PktData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetIsrc1(instance, ++ (tmbslHdmiTxPkt_t *)pIsrc1PktData->UPC_EAN_ISRC, 16, pIsrc1PktData->isrcCont, ++ pIsrc1PktData->isrcValid, pIsrc1PktData->isrcStatus, enable) ) != TM_OK, errCode) ++ } ++ else ++ { ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetIsrc1(instance, ++ Null, 0, 0, 0, 0, enable) ) != TM_OK, errCode) ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Defines the content of ISRC2 packet to be sent by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pIsrc2PktData Pointer to the structure containing GCP packet parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetISRC2Packet ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxIsrc2PktData_t *pIsrc2PktData ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ if (enable == True) ++ { ++ /* Check if Isrc1PktData pointer is Null */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pIsrc2PktData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetIsrc2(instance, ++ (tmbslHdmiTxPkt_t *)pIsrc2PktData->UPC_EAN_ISRC, 16, enable) ) != TM_OK, errCode) ++ } ++ else ++ { ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetIsrc2(instance, ++ Null, 0, enable) ) != TM_OK, errCode) ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Defines the content of MPS infoframe to be sent by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pMpsIfData Pointer to the structure containing MPS infoframe ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetMPSInfoframe ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxMpsIfData_t *pMpsIfData ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ if (enable == True) ++ { ++ /* Check if MpsIfData pointer is Null */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pMpsIfData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetMpegInfoframe(instance, ++ (tmbslHdmiTxPktMpeg_t *)pMpsIfData, enable) ) != TM_OK, errCode) ++ } ++ else ++ { ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetMpegInfoframe(instance, ++ Null, enable) ) != TM_OK, errCode) ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Defines the content of SPD infoframe to be sent by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pSpdIfData Pointer to the structure containing SPD infoframe ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetSpdInfoframe ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxSpdIfData_t *pSpdIfData ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ if (enable == True) ++ { ++ /* Check if SpdIfData pointer is Null */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pSpdIfData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetSpdInfoframe(instance, ++ (tmbslHdmiTxPktSpd_t *)pSpdIfData, enable) ) != TM_OK, errCode) ++ } ++ else ++ { ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetSpdInfoframe(instance, ++ Null, enable) ) != TM_OK, errCode) ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Defines the content of VS infoframe to be sent by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable infoframe insertion. ++ \param pVsIfData Pointer to the structure containing VS infoframe ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetVsInfoframe ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxVsPktData_t *pVsIfData ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ if (enable == True) ++ { ++ /* Check if VsIfData pointer is Null */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pVsIfData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetVsInfoframe(instance, ++ (tmbslHdmiTxPkt_t *)pVsIfData->vsData, HDMITX_PKT_DATA_BYTE_CNT-1, pVsIfData->version, enable) ) != TM_OK, errCode) ++ } ++ else ++ { ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetVsInfoframe(instance, ++ Null, 0, pVsIfData->version, enable) ) != TM_OK, errCode) ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Enables/disables NULL packet sending (only used for debug purpose). ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable packet insertion. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxDebugSetNullPacket ++( ++ tmInstance_t instance, ++ Bool enable ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetNullInsert(instance, ++ enable) ) != TM_OK, errCode) ++ ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Send one single NULL packet (only used for debug purpose). ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxDebugSetSingleNullPacket ++( ++ tmInstance_t instance ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSetNullSingle(instance) ) ++ != TM_OK, errCode) ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Set the audio output mute status. This function can be used to mute ++ audio output, without muting video. This can be typically used when ++ reconfiguring the audio HW after a sample rate change. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param muteStatus Mute status (True/False). ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetAudioMute ++( ++ tmInstance_t instance, ++ Bool audioMute ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Mute or Un-mute the audio output */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxAudioOutSetMute(instance, ++ (tmbslHdmiTxaMute_t)audioMute) ) != TM_OK, errCode) ++ ++ /* Store current audio mute status */ ++ instanceStatusInfoTx[instance].pAudioInfo->audioMuteState = audioMute; ++ ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Reset audio CTS. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxResetAudioCts ++( ++ tmInstance_t instance ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Reset the audio Clock Time Stamp generator */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxAudioInResetCts(instance) ++ ) != TM_OK, errCode) ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Retrieve EDID Status from driver. ++ This function is synchronous. ++ This function is ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pEdidStatus Pointer to the array that will receive the EDID Status. ++ \param pEdidBlkCount Pointer to the integer that will receive the number of ++ read EDID block. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidStatus ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidStatus_t *pEdidStatus, ++ UInt8 *pEdidBlkCount ++) ++{ ++ tmErrorCode_t errCode; ++ UInt8 edidStatus; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if EdidStatus and pReadBytesNumber pointers are Null */ ++ RETIF(pEdidStatus == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ RETIF(pEdidBlkCount == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Get the EDID status from BSL driver */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxEdidGetStatus(instance, ++ (UInt8 *)&edidStatus) ) != TM_OK, errCode) ++ ++ if (edidStatus >= TMDL_HDMITX_EDID_STATUS_INVALID) ++ { ++ *pEdidStatus = TMDL_HDMITX_EDID_STATUS_INVALID; ++ } ++ else ++ { ++ *pEdidStatus = (tmdlHdmiTxEdidStatus_t)edidStatus; ++ } ++ ++ if ((*pEdidStatus == TMDL_HDMITX_EDID_READ) || ++ (*pEdidStatus == TMDL_HDMITX_EDID_ERROR_CHK)) ++ { ++ /* Get the read EDID block number from BSL driver */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxEdidGetBlockCount(instance, ++ pEdidBlkCount) ) != TM_OK, errCode) ++ } ++ ++ if (errCode != TM_OK) ++ { ++ /* Error during read EDID, number of read block is 0 */ ++ *pEdidBlkCount = 0; ++ ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ ++ return errCode; ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Retrieves audio descriptors from receiver's EDID. This function ++ parses the EDID of Tx device to get the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ ++ \param instance Instance identifier. ++ \param pAudioDescs Pointer to the array that will receive audio ++ descriptors. ++ \param maxAudioDescs Size of the array. ++ \param pWrittenAudioDescs Pointer to the integer that will receive the actual ++ number of written descriptors. ++ \param pAudioFlags Pointer to the byte to receive Audio Capabilities Flags. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidAudioCaps ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidAudioDesc_t *pAudioDescs, ++ UInt maxAudioDescs, ++ UInt *pWrittenAudioDescs, ++ UInt8 *pAudioFlags ++) ++{ ++ tmErrorCode_t errCode; ++ tmbslHdmiTxEdidSad_t edidSad[HDMI_TX_SAD_MAX_CNT]; ++ UInt i; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if AudioDescs, WrittenAudioDescs and AudioFlags pointers are Null */ ++ RETIF(pAudioDescs == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ RETIF(pWrittenAudioDescs == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ RETIF(pAudioFlags == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check the current state */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ /* Get video capabilities from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxEdidGetAudioCapabilities(instance, ++ edidSad, maxAudioDescs, pWrittenAudioDescs, pAudioFlags) ) != TM_OK, errCode) ++ ++ for (i=0; i<*pWrittenAudioDescs; i++) ++ { ++ pAudioDescs[i].format = (edidSad[i].ModeChans & 0x78) >> 3; /* Bits[6:3]: EIA/CEA861 mode */ ++ pAudioDescs[i].channels = edidSad[i].ModeChans & 0x07; /* Bits[2:0]: channels */ ++ pAudioDescs[i].supportedFreqs = edidSad[i].Freqs; /* Supported frequencies */ ++ ++ if (pAudioDescs[i].format == 1) /* LPCM format */ ++ { ++ pAudioDescs[i].supportedRes = edidSad[i].Byte3 & 0x07; ++ pAudioDescs[i].maxBitrate = 0x00; ++ } ++ else if ( (pAudioDescs[i].format >= 2) && /* Compressed format */ ++ (pAudioDescs[i].format <= 8) ) ++ { ++ pAudioDescs[i].supportedRes = 0x00; ++ pAudioDescs[i].maxBitrate = edidSad[i].Byte3; ++ } ++ else ++ { ++ pAudioDescs[i].supportedRes = 0x00; ++ pAudioDescs[i].maxBitrate = 0x00; ++ } ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Retrieves supported video formats (short descriptors) from ++ receiver's EDID. This function parses the EDID of Rx device to get ++ the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pVideoDesc Pointer to the structure that will receive short ++ video descriptors. ++ \param maxVideoFormats Size of the array. ++ \param pWrittenVideoFormats Pointer to the integer that will receive the actual ++ number of written descriptors. ++ \param pVideoFlags Pointer to the byte to receive Video Capability Flags. ++ b7: underscan supported ++ b6: YCbCr 4:4:4 supported ++ b5: YCbCr 4:2:2 supported ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidVideoCaps ++( ++ tmInstance_t instance, ++ tmdlHdmiTxShortVidDesc_t *pVideoDesc, ++ UInt maxVideoFormats, ++ UInt *pWrittenVideoFormats, ++ UInt8 *pVideoFlags ++) ++{ ++ tmErrorCode_t errCode; ++ UInt8 edidVFmtsBuffer[HDMI_TX_SVD_MAX_CNT]; ++ tmdlHdmiTxEdidVideoTimings_t edidDTDBuffer[NUMBER_DTD_STORED]; ++ UInt8 i; ++ UInt8 writtenDTD = 0; ++ UInt8 dtdCounter = 0; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if Videoformats, WrittenVideoFormats and VideoFlags pointers are Null */ ++ RETIF(pVideoDesc == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ RETIF(pWrittenVideoFormats == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ RETIF(pVideoFlags == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ RETIF(maxVideoFormats == 0, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check the current state */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ /* Get video capabilities from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxEdidGetVideoCapabilities(instance, ++ edidVFmtsBuffer, HDMI_TX_SVD_MAX_CNT, pWrittenVideoFormats, pVideoFlags) ) != TM_OK, errCode) ++ ++ /* Get detailled descriptors from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = dlHdmiTxEdidGetDTD(instance, edidDTDBuffer, NUMBER_DTD_STORED, &writtenDTD) ) != TM_OK, errCode) ++ ++ dtdCounter = 0; ++ if (writtenDTD > 0) ++ { ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Write first DTD in first position of table video desc */ ++ pVideoDesc[0].videoFormat = tmdlHdmiTxConvertDTDtoCEA(instance, &(edidDTDBuffer[dtdCounter])); ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ dtdCounter++; ++ ++ pVideoDesc[0].nativeVideoFormat = False; ++ } ++ ++ /* Start with i = 1 keep the first position for the first DTD */ ++ for (i = dtdCounter; i< maxVideoFormats ; i++) ++ { ++ if ((i < (HDMI_TX_SVD_MAX_CNT + dtdCounter)) && (i < ((*pWrittenVideoFormats) + dtdCounter))) ++ { ++ /* Store SVD */ ++ pVideoDesc[i].videoFormat = (tmdlHdmiTxVidFmt_t)((Int)edidVFmtsBuffer[i - dtdCounter] & 0x7F); ++ /* if bit 7 is true, it means that is a preferred video format */ ++ if ((edidVFmtsBuffer[i - dtdCounter] & 0x80) == 0x80) ++ { ++ pVideoDesc[i].nativeVideoFormat = True; ++ } ++ else ++ { ++ pVideoDesc[i].nativeVideoFormat = False; ++ } ++ } ++ else ++ { ++ if ((dtdCounter < NUMBER_DTD_STORED) && (dtdCounter < writtenDTD)) ++ { ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ /* Store DTD except first DTD */ ++ pVideoDesc[i].videoFormat = tmdlHdmiTxConvertDTDtoCEA(instance, &(edidDTDBuffer[dtdCounter])); ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ dtdCounter++; ++ ++ pVideoDesc[i].nativeVideoFormat = False; ++ } ++ else ++ { ++ /* VGA is always supported */ ++ pVideoDesc[i].videoFormat = TMDL_HDMITX_VFMT_01_640x480p_60Hz; ++ pVideoDesc[i].nativeVideoFormat = False; ++ /* Last format supported exit from loop for */ ++ break; ++ } ++ } ++ } ++ ++ *pWrittenVideoFormats = *pWrittenVideoFormats + dtdCounter + 1; /* + 1 for VGA format */ ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Retrieves supported video formats (short descriptors) from ++ receiver's EDID. This function parses the EDID of Rx device to get ++ the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pNativeVideoFormat Pointer to the array that will receive video ++ timing descriptor. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidVideoPreferred ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidVideoTimings_t *pNativeVideoFormat ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if NativeVideoFormat pointer is Null */ ++ RETIF(pNativeVideoFormat == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check the current state */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ /* Get preferred video format from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxEdidGetVideoPreferred(instance, ++ (tmbslHdmiTxEdidDtd_t *)pNativeVideoFormat) ) != TM_OK, errCode) ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/*****************************************************************************/ ++/** ++ \brief Retrieves supported detailled video descriptors from ++ receiver's EDID. This function parses the EDID of Rx device to get ++ the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pDTDescriptors Pointer to the array that will receive detailled ++ timing descriptors. ++ \param maxDTDesc Size of the array. ++ \param pWrittenDesc Pointer to the integer that will receive the actual ++ number of written descriptors. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidDetailledTimingDescriptors ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors, ++ UInt8 maxDTDesc, ++ UInt8 *pWrittenDTDesc ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if DTDescriptors, WrittenDTDesc pointers are Null */ ++ RETIF(pDTDescriptors == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ RETIF(pWrittenDTDesc == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Get detailled descriptors from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = dlHdmiTxEdidGetDTD(instance, pDTDescriptors, maxDTDesc, pWrittenDTDesc) ) != TM_OK, errCode) ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/*****************************************************************************/ ++/** ++ \brief Retrieves supported monitor descriptor from receiver's EDID. ++ This function parses the EDID of Rx device to get ++ the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pEdidFirstMD Pointer to the array that will receive the first monitor ++ descriptors. ++ \param pEdidSecondMD Pointer to the array that will receive the second monitor ++ descriptors. ++ \param pEdidOtherMD Pointer to the array that will receive the other monitor ++ descriptors. ++ \param maxOtherMD Size of the array. ++ \param pWrittenOtherMD Pointer to the integer that will receive the actual ++ number of written descriptors. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidMonitorDescriptors ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidFirstMD_t *pEdidFirstMD, ++ tmdlHdmiTxEdidSecondMD_t *pEdidSecondMD, ++ tmdlHdmiTxEdidOtherMD_t *pEdidOtherMD, ++ UInt8 maxOtherMD, ++ UInt8 *pWrittenOtherMD ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if DTDescriptors, WrittenDTDesc pointers are Null */ ++ RETIF(pEdidFirstMD == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ RETIF(pEdidSecondMD == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ RETIF(pEdidOtherMD == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check the current state */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ /* Get monitor descriptors from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxEdidGetMonitorDescriptors(instance, ++ (tmbslHdmiTxEdidFirstMD_t *)pEdidFirstMD, (tmbslHdmiTxEdidSecondMD_t *)pEdidSecondMD, ++ (tmbslHdmiTxEdidOtherMD_t *)pEdidOtherMD, maxOtherMD, pWrittenOtherMD) ) != TM_OK, errCode) ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/*****************************************************************************/ ++/** ++ \brief Retrieves TV picture ratio from receiver's EDID. ++ This function parses the EDID of Rx device to get ++ the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pEdidTvPictureRatio Pointer to the array that will receive the TV picture ++ ratio. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidTVPictureRatio ++( ++ tmInstance_t instance, ++ tmdlHdmiTxPictAspectRatio_t *pEdidTvPictureRatio ++) ++{ ++ tmErrorCode_t errCode; ++ tmbslHdmiTxEdidBDParam_t edidBDParam; ++ UInt16 horizontalSize; ++ UInt16 verticalSize; ++ tmbslHdmiTxEdidDtd_t edidDTDBuffer; ++ UInt8 writtenDTD = 0; ++ Bool bDataAvailable = False; /* Data available in EDID for calcul TV picture ratio */ ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if DTDescriptors, WrittenDTDesc pointers are Null */ ++ RETIF(pEdidTvPictureRatio == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check the current state */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ /* Get Basic Display Parameter from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxEdidGetBasicDisplayParam(instance, ++ &edidBDParam) ) != TM_OK, errCode) ++ ++ horizontalSize = (UInt16)edidBDParam.uMaxHorizontalSize; ++ verticalSize = (UInt16)edidBDParam.uMaxVerticalSize; ++ ++ if ((horizontalSize == 0) && (verticalSize == 0)) ++ { ++ /* Get Basic Display Parameter from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxEdidGetDetailedTimingDescriptors ++ (instance, &edidDTDBuffer, 1, &writtenDTD) ) != TM_OK, errCode); ++ ++ if (writtenDTD == 1) ++ { ++ horizontalSize = edidDTDBuffer.uHImageSize; ++ verticalSize = edidDTDBuffer.uVImageSize; ++ bDataAvailable = True; ++ } ++ else ++ { ++ *pEdidTvPictureRatio = TMDL_HDMITX_P_ASPECT_RATIO_UNDEFINED; ++ } ++ } ++ else ++ { ++ bDataAvailable = True; ++ } ++ ++ if (bDataAvailable == True) ++ { ++ *pEdidTvPictureRatio = dlHdmiTxCalcAspectRatio(horizontalSize, verticalSize); ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++ ++ ++} ++ ++/****************************************************************************** ++ \brief Retrieves the sink type from receiver's EDID (HDMI or DVI). This ++ function parses the EDID of Rx device to get the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pSinkType Pointer to the array that will receive sink type. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidSinkType ++( ++ tmInstance_t instance, ++ tmdlHdmiTxSinkType_t *pSinkType ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if SinkType pointer is Null */ ++ RETIF(pSinkType == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check the current state */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ /* Read the source address from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxEdidGetSinkType(instance, ++ (tmbslHdmiTxSinkType_t *)pSinkType) ) != TM_OK, errCode) ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Retrieves source address from receivers's EDID. This ++ function parses the EDID of Rx device to get the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pSourceAddress Pointer to the integer that will receive the EDID source ++ address. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidSourceAddress ++( ++ tmInstance_t instance, ++ UInt16 *pSourceAddress ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if SourceAddress pointer is Null */ ++ RETIF(pSourceAddress == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check the current state */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ /* Read the source address from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxEdidGetSourceAddress(instance, ++ pSourceAddress) ) != TM_OK, errCode) ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Retreives KSV list received by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pKsv Pointer to the array that will receive the KSV list. ++ \param maxKsv Maximum number of KSV that the array can store. ++ \param pWrittenKsv Actual number of KSV written into the array. ++ \param pDepth Connection tree depth returned with KSV list. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetKsvList ++( ++ tmInstance_t instance, ++ UInt8 *pKsv, ++ UInt8 maxKsv, ++ UInt8 *pWrittenKsv, ++ UInt8 *pDepth, ++ Bool *pMaxCascExd, ++ Bool *pMaxDevsExd ++) ++{ ++ tmErrorCode_t errCode; ++#ifndef NO_HDCP ++ UInt16 i,j; ++#endif ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if pDepth, Ksv and WrittenKsv pointers are Null */ ++ RETIF(pKsv == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ RETIF(pWrittenKsv == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ RETIF(pDepth == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ RETIF(pMaxCascExd == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ RETIF(pMaxDevsExd == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Maximum Ksv is HDMITX_KSV_LIST_MAX_DEVICES, 128 devices */ ++ RETIF_BADPARAM(maxKsv > HDMITX_KSV_LIST_MAX_DEVICES) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check the current state */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ /* Make sure that *pWrittenKsv is 0 */ ++ *pWrittenKsv = 0; ++ ++ /* Make sure that *pDepth is 0 */ ++ *pDepth = 0; ++ ++#ifndef NO_HDCP ++ ++ *pMaxCascExd = hdcpInfoListTx[instance].hdcpMaxCascExceeded; ++ *pMaxDevsExd = hdcpInfoListTx[instance].hdcpMaxDevsExceeded; ++ ++ ++ /* Copy the bKsv */ ++ if (maxKsv) { ++ ++ for (j=0; j<5 ;j++) { ++ pKsv[j] = hdcpInfoListTx[instance].hdcpBksv[4-j]; ++ } ++ *pWrittenKsv = *pWrittenKsv + 1; ++ ++ } /* maxKsv */ ++ ++ ++ /* Copy the Ksv list */ ++ for (i=1; i <= hdcpInfoListTx[instance].hdcpKsvDevices; i++) ++ { ++ if (i < maxKsv) ++ { ++ for (j=0; j<5 ;j++) ++ { ++ pKsv[(5*i)+j] = hdcpInfoListTx[instance].hdcpKsvList[(5*(i-1))+j]; ++ } ++ *pWrittenKsv = *pWrittenKsv + 1; ++ } ++ } ++ ++ *pDepth = hdcpInfoListTx[instance].hdcpDeviceDepth; ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++#else ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TMDL_ERR_DLHDMITX_NOT_SUPPORTED; ++#endif /* NO_HDCP */ ++} ++#ifdef HDMI_TX_REPEATER_ISR_MODE ++/****************************************************************************** ++ \brief Retreives HDCP depth received by Tx device. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pDepth Connection tree depth returned with KSV list. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetDepth ++( ++ tmInstance_t instance, ++ UInt8 *pDepth ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if pDepth, is Null */ ++ RETIF(pDepth == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Make sure that *pDepth is 0 */ ++ *pDepth = 0; ++ ++#ifndef NO_HDCP ++ ++ ++ *pDepth = hdcpInfoListTx[instance].hdcpDeviceDepth; ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++#else ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TMDL_ERR_DLHDMITX_NOT_SUPPORTED; ++#endif /* NO_HDCP */ ++} ++ ++/****************************************************************************** ++ \brief Generate SHA_1 interrupt if not occured. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGeneSHA_1_IT ++( ++ tmInstance_t instance ++) ++{ ++ tmErrorCode_t errCode; ++ ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ dlHdmiTxHandleSHA_1(instance); ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++#endif /* HDMI_TX_REPEATER_ISR_MODE */ ++/****************************************************************************** ++ \brief Enable/Disable HDCP encryption. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param hdcpEnable HDCP On/Off (true = On, False = Off). ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN: the resolution is unknown ++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetHdcp ++( ++ tmInstance_t instance, ++ Bool hdcpEnable ++) ++{ ++ tmErrorCode_t errCode; ++#ifndef NO_HDCP ++ tmdlHdmiTxVidFmtSpecs_t resolutionSpecs; ++ tmbslHdmiTxVfreq_t voutFreq; ++ tmbslHdmiTxVidFmt_t voutFmt; ++ tmbslHdmiTxHdcpTxMode_t txMode; ++ tmbslHdmiTxHdcpOptions_t options; ++ UInt8 slaveAddress; ++ UInt16 i; ++#endif ++ tmbslHdmiTxRxSense_t rxSenseStatus; /* Rx Sense status */ ++ tmbslHdmiTxHotPlug_t hpdStatus; /* HPD status */ ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check the current state */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ /* Hdcp is not supported if keySeed is null */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ gtmdlHdmiTxDriverConfigTable[instance].keySeed == HDCP_SEED_NULL, TMDL_ERR_DLHDMITX_NOT_SUPPORTED) ++ ++ /* Read rxSenseStatus and hpdStatus to authorize HDCP only if active */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxRxSenseGetStatus(instance, ++ &rxSenseStatus,False) ) != TM_OK, errCode) ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxHotPlugGetStatus(instance, ++ &hpdStatus,False) ) != TM_OK, errCode) ++ ++#ifndef NO_HDCP ++ if (hdcpEnable == True) /* HDCP ON */ ++ { ++ if ( (rxSenseStatus == HDMITX_RX_SENSE_ACTIVE) && (hpdStatus == HDMITX_HOTPLUG_ACTIVE) ) ++ { ++ ++#ifdef TMFL_HDCP_OPTIMIZED_POWER ++ tmbslHdmiTxHdcpPowerDown(instance,False); ++#endif ++ /* Reset HDCP DevLib data to ensure that new values are used */ ++ hdcpInfoListTx[instance].hdcpCheckState = TMDL_HDMITX_HDCP_CHECK_IN_PROGRESS; ++ hdcpInfoListTx[instance].hdcpErrorState = 0; ++ hdcpInfoListTx[instance].hdcpKsvDevices = 0; ++ hdcpInfoListTx[instance].bKsvSecure = True; ++ for(i=0; ivideoOutConfig.format; ++ ++ /* Find output vertical frequency from output format */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmdlHdmiTxGetVideoFormatSpecs(instance, (tmdlHdmiTxVidFmt_t)voutFmt, &resolutionSpecs) ) != TM_OK, errCode) ++ voutFreq = (tmbslHdmiTxVfreq_t)resolutionSpecs.vfrequency; ++ ++ /* Configure HDCP */ ++ ++ /* HDCP DDC Slave address */ ++ slaveAddress = HDMITX_HDCP_SLAVE_PRIMARY; ++ ++ /* Top level or repeater HDCP mode */ ++ if (unitTableTx[instance].repeaterEnable == True) ++ { ++ txMode = HDMITX_HDCP_TXMODE_REPEATER; ++ } ++ else ++ { ++ txMode = HDMITX_HDCP_TXMODE_TOP_LEVEL; ++ } ++ ++ instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = True; ++ instanceStatusInfoTx[instance].pColBarState->colorBarOn = True; ++ dlHdmiTxCheckColorBar(instance); ++ ++ /* HDCP options */ ++ options = (tmbslHdmiTxHdcpOptions_t)unitTableTx[instance].hdcpOptions; ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxHdcpConfigure(instance, ++ slaveAddress, txMode, options, HDCP_CHECK_INTERVAL_MS, HDCP_NUM_CHECKS) ) != TM_OK, errCode) ++ ++ /* Start HDCP */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxHdcpInit(instance, ++ voutFmt, voutFreq) ) != TM_OK, errCode) ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxHdcpRun(instance) ++ ) != TM_OK, errCode) ++ ++ unitTableTx[instance].hdcpEnable = True; ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return errCode; ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TMDL_ERR_DLHDMITX_INVALID_STATE; ++ } ++ else /* HDCP OFF */ ++ { ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxHdcpStop(instance) ++ ) != TM_OK, errCode) ++ ++ unitTableTx[instance].hdcpEnable = False; ++ ++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_HDCP_INACTIVE) == TMDL_HDMITX_EVENT_ENABLED) ++ { ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ unitTableTx[instance].pCallback(TMDL_HDMITX_HDCP_INACTIVE); ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]); ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode); ++ ++#ifdef TMFL_HDCP_OPTIMIZED_POWER ++ tmbslHdmiTxHdcpPowerDown(instance,True); ++#endif ++ return TM_OK; ++ } ++#else ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TMDL_ERR_DLHDMITX_NOT_SUPPORTED; ++#endif /* NO_HDCP */ ++} ++ ++/****************************************************************************** ++ \brief Get the driver HDCP state. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pHdcpCheckState Pointer to the integer that will receive the HDCP check state. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetHdcpState ++( ++ tmInstance_t instance, ++ tmdlHdmiTxHdcpCheck_t *pHdcpCheckState ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check if HdcpCheckState pointer is Null */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pHdcpCheckState == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++#ifndef NO_HDCP ++ /* Result of tmbslHdmiTxHdcpCheck */ ++ *pHdcpCheckState = hdcpInfoListTx[instance].hdcpCheckState; ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++#else ++ *pHdcpCheckState = TMDL_HDMITX_HDCP_CHECK_NOT_STARTED; ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TMDL_ERR_DLHDMITX_NOT_SUPPORTED; ++#endif /* NO_HDCP */ ++} ++ ++/****************************************************************************** ++ \brief Check the result of an HDCP encryption attempt, called at ++ intervals (set by timeSinceLastCall) after tmdlHdmiTxSetHdcp(true). ++ This API must be used only in case of No Operating System. if OS, ++ this is manage internally of this device library. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param timeSinceLastCall Time passed in milliseconds since last call, ++ must be shorter than 600 ms. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus ++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxHdcpCheck ++( ++ tmInstance_t instance, ++ UInt16 timeSinceLastCall ++) ++{ ++ tmErrorCode_t errCode; ++ Bool featureSupported; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxHwGetCapabilities(instance, ++ HDMITX_FEATURE_HW_HDCP, &featureSupported) ) != TM_OK, errCode) ++ ++#ifndef NO_HDCP ++ dlHdmiTxCheckColorBar(instance); ++ dlHdmiTxCheckHdcpColorBar(instance); ++ ++ if (featureSupported == True) ++ { ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxHdcpCheck(instance, ++ timeSinceLastCall, (tmbslHdmiTxHdcpCheck_t *)&(hdcpInfoListTx[instance].hdcpCheckState)) ) != TM_OK, errCode) ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++#else ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TMDL_ERR_DLHDMITX_NOT_SUPPORTED; ++#endif /* NO_HDCP */ ++} ++ ++/****************************************************************************** ++ \brief This function loads a gamut metadata packet into the HW. HW will ++ actually send it at the beginning of next VS, during the vertical ++ blanking. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/disable gamut metadata packet insertion. ++ \param pGamutData Pointer to the structure containing gamut metadata ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetGamutPacket ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxGamutData_t *pGamutData ++) ++{ ++ tmErrorCode_t errCode; ++ tmbslHdmiTxPktGamut_t pkt; ++ UInt8 i; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check the current state */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ if (enable == True) ++ { ++ /* Check if GamutData pointer is Null */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pGamutData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Fill data */ ++ pkt.HB[0] = 0x0A; ++ ++ pkt.HB[1] = 0x00; ++ pkt.HB[1] = (UInt8)(pkt.HB[1] | ((pGamutData->nextField & 0x01) << 7)); ++ pkt.HB[1] |= (pGamutData->GBD_Profile & 0x07) << 4; ++ pkt.HB[1] |= (pGamutData->affectedGamutSeqNum & 0x0F); ++ ++ pkt.HB[2] = 0x00; ++ pkt.HB[2] = (UInt8)(pkt.HB[2] | ((pGamutData->noCurrentGBD & 0x01) << 7)); ++ pkt.HB[2] |= (pGamutData->packetSequence & 0x03) << 4; ++ pkt.HB[2] |= (pGamutData->currentGamutSeqNum & 0x0F); ++ ++ for(i=0; i<28; i++) ++ { ++ pkt.PB[i] = pGamutData->payload[i]; ++ } ++ ++ /* Store GBD color space */ ++ if ( ((pGamutData->payload[0]) & 0x03) == 2 ) ++ { ++ instanceStatusInfoTx[instance].pGamutState->wideGamutColorSpace = TMDL_HDMITX_EXT_COLORIMETRY_XVYCC709; ++ } ++ else ++ { ++ instanceStatusInfoTx[instance].pGamutState->wideGamutColorSpace = TMDL_HDMITX_EXT_COLORIMETRY_XVYCC601; ++ } ++ ++ /* Fill Gamut metadata packet */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktFillGamut(instance, ++ &pkt, instanceStatusInfoTx[instance].pGamutState->gamutBufNum) ) != TM_OK, errCode) ++ ++ /* Enable Gamut metadata transmission */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSendGamut(instance, ++ instanceStatusInfoTx[instance].pGamutState->gamutBufNum, enable) ) != TM_OK, errCode) ++ ++ /* Use next buffer for next time */ ++ if (instanceStatusInfoTx[instance].pGamutState->gamutBufNum == 0) ++ { ++ instanceStatusInfoTx[instance].pGamutState->gamutBufNum = 1; ++ } ++ else ++ { ++ instanceStatusInfoTx[instance].pGamutState->gamutBufNum = 0; ++ } ++ } ++ else ++ { ++ /* Disable Gamut metadata transmission */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxPktSendGamut(instance, ++ 0, enable) ) != TM_OK, errCode) ++ } ++ ++ /* Store gamut status */ ++ instanceStatusInfoTx[instance].pGamutState->gamutOn = enable; ++ if(enable) instanceStatusInfoTx[instance].pGamutState->extColOn = False; ++ ++ /* Set avi infoframe */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = dlHdmiTxSetVideoInfoframe(instance, ++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format, ++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode) ) != TM_OK, errCode) ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief This function set the extended colorimetry with one of the following ++ extended colorimetries(bits EC2-0): xvYCC601, xvYCC709, sYCC601, ++ AdobeYCC601, AdobeRGB. When the parameter extendedColorimetry is ++ xvYCC601 or xvYCC70, this function calls the API tmdlHdmiTxSetGamutPacket ++ to send Gamut Packet Data that does not exist for all other types of ++ extended colorimetries for which pointer pGamutData can be set to NULL. ++ This function also allows to set YCC Quantization Range (YQ1-0) ++ ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param enable Enable/Disable extended colorimetry. ++ \param extendedColorimetry value of the extended colorimetry (bits EC2 EC1 EC0). ++ \param yccQR YCC quantisation range ++ \param pGamutData Pointer to the structure containing gamut metadata ++ parameters. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong ++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter was out of range ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxSetExtendedColorimetry ++( ++ tmInstance_t instance, ++ Bool enable, ++ tmdlHdmiTxExtColorimetry_t extendedColorimetry, ++ tmdlHdmiTxYCCQR_t yccQR, ++ tmdlHdmiTxGamutData_t *pGamutData ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check if extendedColorimetry & yccQR values are in the correct range */ ++ if(enable) // no need to check them for disable handling ++ { ++ RETIF(extendedColorimetry >= TMDL_HDMITX_EXT_COLORIMETRY_INVALID, TMDL_ERR_DLHDMITX_BAD_PARAMETER) ++ RETIF(yccQR >= TMDL_HDMITX_YQR_INVALID, TMDL_ERR_DLHDMITX_BAD_PARAMETER) ++ } ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check the current state */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ /* Store YCC quantisation range value for later AVI InfoFrame insertion */ ++ if(enable) instanceStatusInfoTx[instance].pGamutState->yccQR = yccQR; ++ ++ /* Extended colorimetries that need to send Gamut Packet Data */ ++ if( ( (enable == True) && ( (extendedColorimetry == TMDL_HDMITX_EXT_COLORIMETRY_XVYCC601) || ++ (extendedColorimetry == TMDL_HDMITX_EXT_COLORIMETRY_XVYCC709) ) ) ++ || ++ ( (enable == False) && (instanceStatusInfoTx[instance].pGamutState->gamutOn == True) ) ) ++ { ++ /* can not have two different types of extended colorimeties enabled in the same time */ ++ if(enable) instanceStatusInfoTx[instance].pGamutState->extColOn = False; ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Call the API that handles Gamut MetaData */ ++ RETIF( (errCode = tmdlHdmiTxSetGamutPacket(instance, enable, pGamutData) ) != TM_OK, errCode) ++ ++ return TM_OK; ++ } ++ ++ /* Extended colorimetries that do not need to send Gamut Packet Data */ ++ if (instanceStatusInfoTx[instance].pGamutState->gamutOn == True) ++ { ++ /* Disable Gamut metadata transmission */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode = tmbslHdmiTxPktSendGamut(instance, 0, False) ) != TM_OK, errCode) ++ ++ instanceStatusInfoTx[instance].pGamutState->gamutOn = False; ++ } ++ ++ /* Store the extended colorimetry that does not need sending Gamut Packet Data */ ++ if(enable) instanceStatusInfoTx[instance].pGamutState->wideGamutColorSpace = extendedColorimetry; ++ instanceStatusInfoTx[instance].pGamutState->extColOn = enable; ++ ++ /* Set avi infoframe */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = dlHdmiTxSetVideoInfoframe(instance, ++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format, ++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode) ) != TM_OK, errCode) ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief This function set the revocation list use for HDCP ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param listPtr Pointer on revocation list provide by application. ++ \param length length of revocation list. ++ ++ \return The call result: ++ - TM_OK: the call was successful, however RX keys have ++ not been checked with provided revocation list ++ because they are not available. ++ - TMDL_DLHDMITX_HDCP_SECURE: the call was successful, RX keys are secure ++ - TMDL_DLHDMITX_HDCP_NOT_SECURE: the call was successful, RX keys are NOT secure ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: we are a repeater ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++ ++tmErrorCode_t tmdlHdmiTxSetHDCPRevocationList( ++ tmInstance_t instance, ++ void *listPtr, ++ UInt32 length ++) ++{ ++ tmErrorCode_t errCode = TM_OK; ++#ifndef NO_HDCP ++ tmErrorCode_t errCodeSem = TM_OK; ++ UInt8 aCounter = 0; ++ UInt8 indexKSVList = 0; ++ UInt8 i; ++ Bool bIsSecure = True; ++#endif ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check parameters */ ++ RETIF((listPtr == Null) || (length == 0), TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++#ifndef NO_HDCP ++ /* --------------------- */ ++ /* Take the semaphore */ ++ /* --------------------- */ ++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem) ++ ++ /* Register revocation list */ ++ unitTableTx[instance].revocationList.pList = (UInt8 *)listPtr; ++ unitTableTx[instance].revocationList.length = length; ++ ++ /* Look if hdcpBksv is filled in */ ++ for (i=0; i= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* --------------------- */ ++ /* Take the semaphore */ ++ /* --------------------- */ ++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem) ++ ++ gtmdlHdmiTxDriverConfigTable[instance].pattern = pattern; ++ ++ /* Set service mode colour bar on/off (also used as HDCP logo pattern) */ ++ (void)dlHdmiTxSetTestPatternOn(instance, instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format, ++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode, ++ gtmdlHdmiTxDriverConfigTable[instance].pattern); ++ ++ /* --------------------------- */ ++ /* Release the sempahore */ ++ /* --------------------------- */ ++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem) ++ ++ return errCode; ++ ++} ++ ++/****************************************************************************** ++ \brief This function set the Remove B.... screen ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ ++ \return The call result: ++ - TM_OK: the call was successful, however RX keys have ++ not been checked with provided revocation list ++ because they are not available. ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ ++ ++******************************************************************************/ ++ ++tmErrorCode_t tmdlHdmiTxRemoveBScreen( ++ tmInstance_t instance ++) ++{ ++ ++ tmErrorCode_t errCodeSem = TM_OK; ++ tmErrorCode_t errCode = TM_OK; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* --------------------- */ ++ /* Take the semaphore */ ++ /* --------------------- */ ++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem) ++ ++ /* Restore last output format and mode */ ++ (void)dlHdmiTxSetTestPatternOff(instance, ++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format, ++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode); ++ ++ /* --------------------------- */ ++ /* Release the sempahore */ ++ /* --------------------------- */ ++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem) ++ ++ return errCode; ++ ++} ++ ++/****************************************************************************** ++ \brief tmdlHdmiTxConvertDTDtoCEA . ++ ++ \param DTDescriptors DTD to convert. ++ ++ \return NA. ++ ++******************************************************************************/ ++tmdlHdmiTxVidFmt_t tmdlHdmiTxConvertDTDtoCEA ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors ++) ++{ ++ ++ tmdlHdmiTxVidFmt_t codeCEA; ++ tmdlHdmiTxPictAspectRatio_t pictureAspectRatio; ++ Bool formatInterlaced; ++ ++ /* --------------------- */ ++ /* Take the semaphore */ ++ /* --------------------- */ ++ tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]); ++ ++ formatInterlaced = False; ++ ++ if ((pDTDescriptors->flags) & 0x80) ++ { ++ formatInterlaced = True; ++ } ++ ++ pictureAspectRatio = dlHdmiTxCalcAspectRatio (pDTDescriptors->hImageSize, pDTDescriptors->vImageSize); ++ ++ switch (pDTDescriptors->hActivePixels) ++ { ++ case 640: ++ codeCEA = dlHdmiTxConvertDTDtoCEA_640HAP(pDTDescriptors); ++ break; ++ ++ case 720: ++ codeCEA = dlHdmiTxConvertDTDtoCEA_720HAP(pDTDescriptors, pictureAspectRatio); ++ break; ++ ++ case 1280: ++ codeCEA = dlHdmiTxConvertDTDtoCEA_1280HAP(pDTDescriptors); ++ break; ++ ++ case 1920: ++ codeCEA = dlHdmiTxConvertDTDtoCEA_1920HAP(pDTDescriptors, formatInterlaced); ++ break; ++ ++ case 1440: ++ codeCEA = dlHdmiTxConvertDTDtoCEA_1440HAP(pDTDescriptors, pictureAspectRatio, formatInterlaced); ++ break; ++ ++ case 2880: ++ codeCEA = dlHdmiTxConvertDTDtoCEA_2880HAP(pDTDescriptors, pictureAspectRatio, formatInterlaced); ++ break; ++ ++ default: ++ /* Not a valid format */ ++ codeCEA = TMDL_HDMITX_VFMT_NULL; ++ break; ++ } ++ ++ /* --------------------------- */ ++ /* Release the sempahore */ ++ /* --------------------------- */ ++ tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ ++ return codeCEA; ++ ++} ++ ++/*============================================================================*/ ++/* INTERNAL FUNCTION */ ++/*============================================================================*/ ++ ++/****************************************************************************** ++ \brief Get the REFPIX and REFLINE for output and scaler ++ for the current settings. ++ ++ \param vinFmt Video input format. ++ \param vinMode Video input mode. ++ \param voutFmt Video output format. ++ \param syncIn Type of synchro (ext or emb). ++ \param pixRate Video pixel rate. ++ \param pRefPix RefPix for output. ++ \param pRefLine RefLine for output. ++ \param pScRefPix RefPix for scaler. ++ \param pScRefLine RefLine for scaler. ++ \param pbVerified Pointer to the boolean that will receive the fact that ++ this scaler setting was verified. ++ ++ \return True (Found) or False (Not found). ++ ++******************************************************************************/ ++static Bool dlHdmiTxGetReflineRefpix ++( ++ tmdlHdmiTxVidFmt_t vinFmt, ++ tmdlHdmiTxVinMode_t vinMode, ++ tmdlHdmiTxVidFmt_t voutFmt, ++ UInt8 syncIn, ++ tmdlHdmiTxPixRate_t pixRate, ++ UInt16 *pRefPix, ++ UInt16 *pRefLine, ++ UInt16 *pScRefPix, ++ UInt16 *pScRefLine, ++ Bool *pbVerified ++) ++{ ++ UInt8 shortVinFmt; ++ UInt8 shortVoutFmt; ++ int i; ++ Bool bFound; ++ tmdlHdmiTxVidFmt_t vinFmtIndex, voutFmtIndex; ++ ++ /* Search for all values to match in table, until table end is reached ++ * when both refPix values are zero */ ++ *pRefPix = 0; ++ *pRefLine = 0; ++ *pScRefPix = 0; ++ *pScRefLine = 0; ++ ++ /* If match is not found in table, we can assume a verified non-scaler ++ * combination */ ++ *pbVerified = 1; ++ bFound = False; ++ ++ if ((voutFmt < TMDL_HDMITX_VFMT_TV_NO_REG_MIN) ++ || ((voutFmt >= HDMITX_VFMT_35_2880x480p_60Hz) && (voutFmt <= HDMITX_VFMT_38_2880x576p_50Hz))) ++ { ++ vinFmtIndex = dlHdmiTxCalcVidFmtIndex(vinFmt); ++ voutFmtIndex = dlHdmiTxCalcVidFmtIndex(voutFmt); ++ shortVinFmt = kVfmtToShortFmt_TV[vinFmtIndex]; ++ shortVoutFmt = kVfmtToShortFmt_TV[voutFmtIndex]; ++ ++ for (i = 0; kRefpixRefline[i].shortVinFmt != TV_INVALID; i++) ++ { ++ if ((kRefpixRefline[i].shortVinFmt == shortVinFmt) ++ && (UNPKMODE(kRefpixRefline[i].modeRateSyncVerf) == vinMode) ++ && (kRefpixRefline[i].shortVoutFmt == shortVoutFmt) ++ && (UNPKRATE(kRefpixRefline[i].modeRateSyncVerf) == pixRate) ++ && (UNPKSYNC(kRefpixRefline[i].modeRateSyncVerf) == syncIn)) ++ { ++ *pRefPix = kRefpixRefline[i].refPix; ++ *pRefLine = kRefpixRefline[i].refLine; ++ *pScRefPix = kRefpixRefline[i].scRefPix; ++ *pScRefLine = kRefpixRefline[i].scRefLine; ++ *pbVerified = UNPKVERF(kRefpixRefline[i].modeRateSyncVerf); ++ bFound = True; ++ break; ++ } ++ } ++ } ++ ++ return bFound; ++} ++ ++/****************************************************************************** ++ \brief Set the video infoframe. ++ ++ \param instance Instance identifier. ++ \param voutFmt Video output format. ++ \param voutMode Video output mode. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++static tmErrorCode_t dlHdmiTxSetVideoInfoframe ++( ++ tmInstance_t instance, ++ tmdlHdmiTxVidFmt_t voutFmt, ++ tmdlHdmiTxVoutMode_t voutMode ++) ++{ ++ tmErrorCode_t errCode; ++ tmdlHdmiTxAviIfData_t contentVif; ++ tmdlHdmiTxVidFmt_t voutFmtIndex; ++ ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ contentVif.colorIndicator = voutMode; /* 3rd api_set_avi_infoframe param */ ++ contentVif.activeInfoPresent = 0; ++ contentVif.barInformationDataValid = 0; ++ contentVif.scanInformation = 0; ++ ++ voutFmtIndex = dlHdmiTxCalcVidFmtIndex(voutFmt); ++ contentVif.pictureAspectRatio = kVfmtToAspect_TV[voutFmtIndex]; ++ ++ contentVif.activeFormatAspectRatio = 8; ++ contentVif.nonUniformPictureScaling = 0; ++ ++#ifdef FORMAT_PC ++ if (voutFmt >= TMDL_HDMITX_VFMT_PC_MIN) ++ { ++ if (voutFmt == TMDL_HDMITX_VFMT_PC_640x480p_60Hz) ++ { ++ contentVif.videoFormatIdentificationCode = (tmbslHdmiTxVidFmt_t)TMDL_HDMITX_VFMT_01_640x480p_60Hz; ++ } ++ else ++ { ++ /* Format PC not Valid in EIA861b */ ++ contentVif.videoFormatIdentificationCode = (tmbslHdmiTxVidFmt_t)TMDL_HDMITX_VFMT_NULL; ++ } ++ } ++ else ++ { ++#endif /* FORMAT_PC */ ++ ++ contentVif.videoFormatIdentificationCode = (tmbslHdmiTxVidFmt_t)voutFmt; ++ ++#ifdef FORMAT_PC ++ } ++#endif /* FORMAT_PC */ ++ ++ ++ if (((voutFmt >= TMDL_HDMITX_VFMT_06_720x480i_60Hz) && (voutFmt <= TMDL_HDMITX_VFMT_09_720x240p_60Hz)) ++ || ((voutFmt >= TMDL_HDMITX_VFMT_21_720x576i_50Hz) && (voutFmt <= TMDL_HDMITX_VFMT_24_720x288p_50Hz))) ++ { ++ /* Force pixel repeat for formats where it's mandatory (Pixel Frequency < 20 Mpix/s)*/ ++ contentVif.pixelRepetitionFactor = 1; ++ } ++ else if((voutFmt == TMDL_HDMITX_VFMT_10_720x480i_60Hz) || (voutFmt == TMDL_HDMITX_VFMT_11_720x480i_60Hz) || ++ (voutFmt == TMDL_HDMITX_VFMT_25_720x576i_50Hz) || (voutFmt == TMDL_HDMITX_VFMT_26_720x576i_50Hz) ) ++ { ++ contentVif.pixelRepetitionFactor = HDMITX_PIXREP_3; // pixel sent 1 or 10 times, here 4 times ++ } ++ else if((voutFmt == TMDL_HDMITX_VFMT_14_1440x480p_60Hz) || (voutFmt == TMDL_HDMITX_VFMT_15_1440x480p_60Hz) || ++ (voutFmt == TMDL_HDMITX_VFMT_29_1440x576p_50Hz) || (voutFmt == TMDL_HDMITX_VFMT_30_1440x576p_50Hz)) ++ { ++ contentVif.pixelRepetitionFactor = HDMITX_PIXREP_1; // pixel sent 1 or 2 times, here 2 times ++ } ++ else if((voutFmt >= TMDL_HDMITX_VFMT_35_2880x480p_60Hz) && (voutFmt <= TMDL_HDMITX_VFMT_38_2880x576p_50Hz)) ++ { ++ contentVif.pixelRepetitionFactor = HDMITX_PIXREP_3; ++ } ++ else /* Default to no repeat for all other formats */ ++ { ++ contentVif.pixelRepetitionFactor = HDMITX_PIXREP_NONE; ++ } ++ ++ if ((instanceStatusInfoTx[instance].pGamutState->gamutOn == True) || ++ (instanceStatusInfoTx[instance].pGamutState->extColOn == True)) ++ { ++ contentVif.colorimetry = (UInt8)TMDL_HDMITX_COLORIMETRY_EXTENDED; ++ } ++ else ++ { ++ switch (voutFmt) ++ { ++ case TMDL_HDMITX_VFMT_04_1280x720p_60Hz: ++ case TMDL_HDMITX_VFMT_05_1920x1080i_60Hz: ++ case TMDL_HDMITX_VFMT_16_1920x1080p_60Hz: ++ case TMDL_HDMITX_VFMT_19_1280x720p_50Hz: ++ case TMDL_HDMITX_VFMT_20_1920x1080i_50Hz: ++ case TMDL_HDMITX_VFMT_31_1920x1080p_50Hz: ++ contentVif.colorimetry = (UInt8)TMDL_HDMITX_COLORIMETRY_ITU709; ++ break; ++ ++ default: ++ contentVif.colorimetry = (UInt8)TMDL_HDMITX_COLORIMETRY_ITU601; ++ break; ++ } ++ } ++ ++ contentVif.lineNumberEndTopBar = 0; ++ contentVif.lineNumberStartBottomBar = 0; ++ contentVif.lineNumberEndLeftBar = 0; ++ contentVif.lineNumberStartRightBar = 0; ++ ++ errCode = dlHdmiTxSetRawVideoInfoframe(instance, &contentVif, True); ++ ++ /* Ignore infoframe interlock in DVI mode */ ++ if (errCode == TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED) ++ { ++ errCode = TM_OK; ++ } ++ ++ return errCode; ++} ++ ++/****************************************************************************** ++ \brief Set the video infoframe. ++ ++ \param instance Instance identifier. ++ \param voutFmt Video output format. ++ \param voutMode Video output mode. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode ++ ++******************************************************************************/ ++static tmErrorCode_t dlHdmiTxSetRawVideoInfoframe ++( ++ tmInstance_t instance, ++ tmdlHdmiTxAviIfData_t *pContentVif, ++ Bool enable ++) ++{ ++ ++ tmErrorCode_t errCode; ++ tmbslHdmiTxPktRawAvi_t PktInfoFrame; ++ UInt8 i; ++ ++ if(pContentVif != Null) ++ { ++ ++ for(i=0; icolorIndicator& 0x03) << 5) | /* Y1-0, B1-0,S1-0 */ ++ ((pContentVif->barInformationDataValid& 0x03) << 2) | ++ (pContentVif->scanInformation & 0x03); ++ if(pContentVif->activeInfoPresent == True) ++ { ++ PktInfoFrame.PB[1] += 0x10; /* A0 bit */ ++ } ++ ++ PktInfoFrame.PB[2] = ((pContentVif->colorimetry & 0x03) << 6) | /* C1-0, M1-0, R3-0 */ ++ ((pContentVif->pictureAspectRatio & 0x03) << 4) | ++ (pContentVif->activeFormatAspectRatio & 0x0F); ++ ++ PktInfoFrame.PB[3] = (pContentVif->nonUniformPictureScaling & 0x03); /* SC1-0 */ /* [HDMI 1.2] */ ++ ++ /* Q1-0 = 00 => RGB Quantization Range depends on video format (CEA-861) */ ++ /* Limited Range for all video formats except PC formats which requires Full Range */ ++ ++ if (pContentVif->colorimetry == TMDL_HDMITX_COLORIMETRY_EXTENDED) ++ { ++ PktInfoFrame.PB[3] = (( ((UInt8)instanceStatusInfoTx[instance].pGamutState->wideGamutColorSpace) & 0x07) <<4) ++ | PktInfoFrame.PB[3]; ++ } ++ ++ /* Bit ITC = 0 => No Content Type ; Bit ITC = 1 => Content Type (see CN1-0) */ ++ /* Today ITC = 0 => No Content Type */ ++ ++ PktInfoFrame.PB[4] = (pContentVif->videoFormatIdentificationCode & 0x7F); /* VIC6-0 */ ++ ++ PktInfoFrame.PB[5] = (pContentVif->pixelRepetitionFactor & 0x0F); /* PR3-0 */ ++ ++ /* CN1-0 => Content Type */ ++ /* Today CN1-0 = 00 => No Data */ ++ ++ /* YQ1-0 => YCC Quantization Range, only managed for those extended colorimetries */ ++ if (pContentVif->colorimetry == TMDL_HDMITX_COLORIMETRY_EXTENDED) ++ { ++ PktInfoFrame.PB[5] |= ( ((UInt8)instanceStatusInfoTx[instance].pGamutState->yccQR) & 0x03) << 6; ++ } ++ PktInfoFrame.PB[6] = (UInt8)(pContentVif->lineNumberEndTopBar & 0x00FF); ++ PktInfoFrame.PB[7] = (UInt8)((pContentVif->lineNumberEndTopBar & 0xFF00) >> 8); ++ PktInfoFrame.PB[8] = (UInt8)(pContentVif->lineNumberStartBottomBar & 0x00FF); ++ PktInfoFrame.PB[9] = (UInt8)((pContentVif->lineNumberStartBottomBar & 0xFF00) >> 8); ++ PktInfoFrame.PB[10] = (UInt8)(pContentVif->lineNumberEndLeftBar & 0x00FF); ++ PktInfoFrame.PB[11] = (UInt8)((pContentVif->lineNumberEndLeftBar & 0xFF00) >> 8); ++ PktInfoFrame.PB[12] = (UInt8)(pContentVif->lineNumberStartRightBar & 0x00FF); ++ PktInfoFrame.PB[13] = (UInt8)((pContentVif->lineNumberStartRightBar & 0xFF00) >> 8); ++ ++ /* Calculate checksum - this is worked out on "Length" bytes of the ++ * packet, the checksum (which we've preset to zero), and the three ++ * header bytes. ++ */ ++ PktInfoFrame.PB[0] = dlHdmiTxcalculateCheksumIF(&PktInfoFrame); ++ ++ errCode = tmbslHdmiTxPktSetRawVideoInfoframe(instance, ++ &PktInfoFrame, enable); ++ } ++ else ++ { ++ errCode = tmbslHdmiTxPktSetVideoInfoframe(instance, ++ Null, enable); ++ } ++ ++ return errCode; ++ ++} ++ ++/*============================================================================*/ ++/* calculateChecksum - returns the byte needed to yield a checksum of zero */ ++/*============================================================================*/ ++static UInt8 ++dlHdmiTxcalculateCheksumIF ++( ++ tmbslHdmiTxPktRawAvi_t *pData /* Pointer to checksum data */ ++) ++{ ++ UInt8 checksum = 0; /* Working checksum calculation */ ++ UInt8 result = 0; /* Value to be returned */ ++ UInt8 numBytes = 0; ++ Int i; ++ ++ if(pData != Null) ++ { ++ ++ numBytes = sizeof(pData->HB); ++ ++ for (i = 0; i < numBytes; i++) ++ { ++ checksum = checksum + pData->HB[i]; ++ } ++ ++ numBytes = sizeof(pData->PB); ++ ++ for (i = 0; i < numBytes; i++) ++ { ++ checksum = checksum + pData->PB[i]; ++ } ++ ++ result = (UInt8)((255 - checksum) + 1); ++ } ++ return result; /* returns 0 in the case of null ptr or 0 bytes */ ++} ++ ++/****************************************************************************** ++ \brief Set colourbar test pattern on with RGB infoframe ++ ++ \param instance Instance identifier. ++ \param voutFmt Video output format. ++ \param voutMode Video output mode. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ ++******************************************************************************/ ++tmErrorCode_t dlHdmiTxSetTestPatternOn ++( ++ tmInstance_t instance, ++ tmdlHdmiTxVidFmt_t voutFmt, ++ tmdlHdmiTxVoutMode_t voutMode, ++ tmdlHdmiTxTestPattern_t pattern ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ RETIF( (errCode = tmbslHdmiTxTestSetPattern(instance, ++ (tmbslHdmiTxTestPattern_t)pattern) ) != TM_OK, errCode) ++ ++ if (pattern > TMDL_HDMITX_PATTERN_CBAR8) ++ { ++ RETIF( (errCode = dlHdmiTxSetVideoInfoframe(instance, voutFmt, voutMode) ) != TM_OK, errCode) ++ } ++ else ++ { ++ /* For TMDL_HDMITX_PATTERN_CBAR8 and TMDL_HDMITX_PATTERN_CBAR4, video mode in infoframe should be RGB */ ++ RETIF( (errCode = dlHdmiTxSetVideoInfoframe(instance, voutFmt, TMDL_HDMITX_VOUTMODE_RGB444) ) != TM_OK, errCode) ++ } ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief Set colourbar test pattern off with previous infoframe ++ ++ \param instance Instance identifier. ++ \param voutFmt Video output format. ++ \param voutMode Video output mode. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus ++ ++******************************************************************************/ ++tmErrorCode_t dlHdmiTxSetTestPatternOff ++( ++ tmInstance_t instance, ++ tmdlHdmiTxVidFmt_t voutFmt, ++ tmdlHdmiTxVoutMode_t voutMode ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ RETIF( (errCode = tmbslHdmiTxTestSetPattern(instance, ++ (tmbslHdmiTxTestPattern_t)TMDL_HDMITX_PATTERN_OFF) ) != TM_OK, errCode) ++ ++ /* Restore video infoframe */ ++ RETIF( (errCode = dlHdmiTxSetVideoInfoframe(instance, voutFmt, voutMode) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} ++ ++/****************************************************************************** ++ \brief HDCP ENCRYPT interrupt callback. ++ ++ \param instance Instance identifier. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxHandleENCRYPT ++( ++ tmInstance_t instance ++) ++{ ++#ifndef NO_HDCP ++ ++ tmbslHdmiTxHdcpHandleENCRYPT(instance); ++ ++ if (instanceStatusInfoTx[instance].pColBarState->disableColorBarOnR0 == False) ++ { ++ instanceStatusInfoTx[instance].pColBarState->hdcpColbarChange = False; ++ instanceStatusInfoTx[instance].pColBarState->hdcpEncryptOrT0 = True; ++ } ++ instanceStatusInfoTx[instance].pColBarState->disableColorBarOnR0 = False; ++#else ++ (void)instance; /* Remove compiler warning */ ++#endif /* NO_HDCP */ ++} ++ ++/****************************************************************************** ++ \brief HPD interrupt callback. ++ ++ \param instance Instance identifier. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxHandleHPD ++( ++ tmInstance_t instance ++) ++{ ++ tmErrorCode_t errCode; ++ tmbslHdmiTxHotPlug_t hpdStatus; /* HPD status */ ++ tmPowerState_t powerState; /* Power state of transmitter */ ++ ++ hpdStatus = HDMITX_HOTPLUG_INVALID; ++ ++ /* Get Hot Plug status */ ++ errCode = tmbslHdmiTxHotPlugGetStatus(instance, ++ &hpdStatus,False); ++ ++ if (errCode != TM_OK) return; ++ ++ /* Get the power state of the transmitter */ ++ errCode = tmbslHdmiTxPowerGetState(instance, ++ &powerState); ++ ++ if (errCode != TM_OK) return; ++ ++ /* Has hot plug changed to Active? */ ++ if (hpdStatus == HDMITX_HOTPLUG_ACTIVE) ++ { ++ /* Set state machine to Plugged */ ++ dlHdmiTxSetState(instance, STATE_PLUGGED); ++ ++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_HPD_ACTIVE) == TMDL_HDMITX_EVENT_ENABLED) ++ { ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ unitTableTx[instance].pCallback(TMDL_HDMITX_HPD_ACTIVE); ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]); ++ } ++ ++ if (powerState == tmPowerOn) ++ { ++ /* Yes: Wait for DDC line to settle before reading EDID */ ++ tmbslHdmiTxSysTimerWait(instance, ++ 500); /* ms */ ++ ++ /* Request EDID read */ ++ errCode = tmbslHdmiTxEdidRequestBlockData(instance, ++ unitTableTx[instance].pEdidBuffer, (Int)((unitTableTx[instance].edidBufferSize) >> 7), ++ (Int)(unitTableTx[instance].edidBufferSize)); ++ ++ if (errCode != TM_OK) return; ++ } ++ } ++ else ++ { ++#ifndef NO_HDCP ++ if (unitTableTx[instance].hdcpEnable == True) ++ { ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ /* Switch off HDCP */ ++ (void)tmdlHdmiTxSetHdcp(instance, False); ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]); ++ } ++#endif /* NO_HDCP */ ++ ++ /* Set state machine to Unplugged */ ++ dlHdmiTxSetState(instance, STATE_UNPLUGGED); ++ ++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_HPD_INACTIVE) == TMDL_HDMITX_EVENT_ENABLED) ++ { ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ unitTableTx[instance].pCallback(TMDL_HDMITX_HPD_INACTIVE); ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]); ++ } ++ } ++} ++ ++/****************************************************************************** ++ \brief T0 interrupt callback. ++ ++ \param instance Instance identifier. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxHandleT0 ++( ++ tmInstance_t instance ++) ++{ ++#ifndef NO_HDCP ++ tmErrorCode_t errCode; ++ ++ errCode = tmbslHdmiTxHdcpHandleT0(instance); ++ ++ if (errCode != TM_OK) return; ++ ++ tmbslHdmiTxHdcpGetT0FailState(instance, ++ &(hdcpInfoListTx[instance].hdcpErrorState)); ++ ++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_HDCP_INACTIVE) == TMDL_HDMITX_EVENT_ENABLED) ++ { ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ unitTableTx[instance].pCallback(TMDL_HDMITX_HDCP_INACTIVE); ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]); ++ } ++ ++ instanceStatusInfoTx[instance].pColBarState->hdcpColbarChange = False; ++ instanceStatusInfoTx[instance].pColBarState->hdcpEncryptOrT0 = True; ++ instanceStatusInfoTx[instance].pColBarState->hdcpSecureOrT0 = True; ++#else ++ (void)instance; ++#endif /* NO_HDCP */ ++} ++ ++/****************************************************************************** ++ \brief BCAPS interrupt callback. ++ ++ \param instance Instance identifier. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxHandleBCAPS ++( ++ tmInstance_t instance ++) ++{ ++#ifndef NO_HDCP ++ Bool bCheckRequired; ++ tmErrorCode_t errCode; ++ ++ /* Handle BCAPS interrupt immediately */ ++ errCode = tmbslHdmiTxHdcpHandleBCAPS(instance); ++ ++ if (errCode != TM_OK) return; ++ ++ /* Wait for TDA9984 to read BKSV from B device */ ++ tmbslHdmiTxSysTimerWait(instance, 10); ++ ++ /* Handle BKSV read */ ++ errCode = tmbslHdmiTxHdcpHandleBKSV(instance, ++ hdcpInfoListTx[instance].hdcpBksv, &bCheckRequired); ++ ++ if (errCode != TM_OK) return; ++ ++ if (bCheckRequired) ++ { ++ /* check HdcpBksv against a revocation list */ ++ dlHdmiTxCheckHdcpBksv (instance, hdcpInfoListTx[instance].hdcpBksv,&(hdcpInfoListTx[instance].bKsvSecure), True); ++ } ++ else ++ { ++ /* Result is always secure if no check required */ ++ hdcpInfoListTx[instance].bKsvSecure = True; ++ } ++ ++ /* Handle BKSV result */ ++ errCode = tmbslHdmiTxHdcpHandleBKSVResult(instance, ++ hdcpInfoListTx[instance].bKsvSecure); ++ ++ if (errCode != TM_OK) return; ++ ++ ++#else ++ (void)instance; ++#endif /* NO_HDCP */ ++} ++ ++/****************************************************************************** ++ \brief BSTATUS interrupt callback. ++ ++ \param instance Instance identifier. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxHandleBSTATUS ++( ++ tmInstance_t instance ++) ++{ ++#ifndef NO_HDCP ++ UInt16 bstatus = 0; ++ ++ tmbslHdmiTxHdcpHandleBSTATUS(instance, ++ &bstatus); ++ ++#ifdef HDMI_TX_REPEATER_ISR_MODE ++ gIgnoreNextSha1 = False; ++#endif /*HDMI_TX_REPEATER_ISR_MODE*/ ++ ++ if (((bstatus & HDMITX_HDCP_BSTATUS_MAX_CASCADE_EXCEEDED) > 0) ++ || ((bstatus & HDMITX_HDCP_BSTATUS_MAX_DEVS_EXCEEDED) > 0)) ++ { ++ ++ hdcpInfoListTx[instance].hdcpDeviceDepth = (UInt8)((bstatus & HDMITX_HDCP_BSTATUS_CASCADE_DEPTH)>>8); ++ ++ /* The KsvList length is limited by the smaller of the list array ++ * length and the number of devices returned in BSTATUS */ ++ hdcpInfoListTx[instance].hdcpKsvDevices = ++ (UInt8)(bstatus & HDMITX_HDCP_BSTATUS_DEVICE_COUNT); ++ ++ if (HDMITX_KSV_LIST_MAX_DEVICES < hdcpInfoListTx[instance].hdcpKsvDevices) ++ { ++ hdcpInfoListTx[instance].hdcpKsvDevices = HDMITX_KSV_LIST_MAX_DEVICES; ++ } ++ ++ if ((bstatus & HDMITX_HDCP_BSTATUS_MAX_CASCADE_EXCEEDED) > 0) ++ { ++ hdcpInfoListTx[instance].hdcpMaxCascExceeded = True; ++ } ++ ++ if ((bstatus & HDMITX_HDCP_BSTATUS_MAX_DEVS_EXCEEDED) > 0) ++ { ++ hdcpInfoListTx[instance].hdcpMaxDevsExceeded = True; ++ } ++ ++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_RX_KEYS_RECEIVED) == TMDL_HDMITX_EVENT_ENABLED) ++ { ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ unitTableTx[instance].pCallback(TMDL_HDMITX_RX_KEYS_RECEIVED); ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]); ++ } ++ } ++ else ++ { ++ ++#ifdef HDMI_TX_REPEATER_ISR_MODE ++ /* Call SHA_1 otherwise this ISR is missed */ ++ hdcpInfoListTx[instance].hdcpDeviceDepth = (UInt8)((bstatus & HDMITX_HDCP_BSTATUS_CASCADE_DEPTH)>>8); ++ ++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_B_STATUS) == TMDL_HDMITX_EVENT_ENABLED) ++ { ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ unitTableTx[instance].pCallback(TMDL_HDMITX_B_STATUS); ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]); ++ } ++ ++ ++#endif /* HDMI_TX_REPEATER_ISR_MODE */ ++ } ++ ++ ++#else ++ (void)instance; ++#endif /* NO_HDCP */ ++} ++ ++/****************************************************************************** ++ \brief SHA_1 interrupt callback. ++ ++ \param instance Instance identifier. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxHandleSHA_1 ++( ++ tmInstance_t instance ++) ++{ ++#ifndef NO_HDCP ++ tmErrorCode_t errCode; ++ UInt8 indexKSVList; ++ ++#ifdef HDMI_TX_REPEATER_ISR_MODE ++ if (gIgnoreNextSha1 == False) ++ { ++ gIgnoreNextSha1 = True; ++#endif /*HDMI_TX_REPEATER_ISR_MODE*/ ++ ++ errCode = tmbslHdmiTxHdcpHandleSHA_1(instance, ++ HDMITX_KSV_LIST_MAX_DEVICES, hdcpInfoListTx[instance].hdcpKsvList, ++ &(hdcpInfoListTx[instance].hdcpKsvDevices),&(hdcpInfoListTx[instance].hdcpDeviceDepth)); ++ if (errCode != TM_OK) return; ++ ++ /* Top level or repeater HDCP mode */ ++ if (unitTableTx[instance].repeaterEnable == False) ++ { ++ /* check HdcpKsvList against revocation list */ ++ ++ indexKSVList = 0; ++ while (( indexKSVList < TMDL_HDMITX_KSV_LIST_MAX_DEVICES ) && ++ ( indexKSVList < hdcpInfoListTx[instance].hdcpKsvDevices ) && ++ (hdcpInfoListTx[instance].bKsvSecure == True) ++ ) ++ { ++ dlHdmiTxCheckHdcpBksv (instance, ++ &(hdcpInfoListTx[instance].hdcpKsvList[indexKSVList * TMDL_HDMITX_KSV_BYTES_PER_DEVICE]), ++ &(hdcpInfoListTx[instance].bKsvSecure), ++ False); ++ indexKSVList++; ++ } ++ } ++ else ++ { ++ hdcpInfoListTx[instance].bKsvSecure = True; ++ } ++ ++ /* Handle SHA_1 result */ ++ errCode = tmbslHdmiTxHdcpHandleSHA_1Result(instance, ++ hdcpInfoListTx[instance].bKsvSecure); ++ ++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_RX_KEYS_RECEIVED) == TMDL_HDMITX_EVENT_ENABLED) ++ { ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ unitTableTx[instance].pCallback(TMDL_HDMITX_RX_KEYS_RECEIVED); ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]); ++ } ++ ++ if (!hdcpInfoListTx[instance].bKsvSecure) ++ { ++ instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = True; ++ instanceStatusInfoTx[instance].pColBarState->colorBarOn = True; ++ dlHdmiTxCheckColorBar(instance); ++ } ++#ifdef HDMI_TX_REPEATER_ISR_MODE ++ } ++#endif /*HDMI_TX_REPEATER_ISR_MODE*/ ++ ++ ++#else ++ (void)instance; ++#endif /* NO_HDCP */ ++} ++ ++/****************************************************************************** ++ \brief PJ interrupt callback. ++ ++ \param instance Instance identifier. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxHandlePJ ++( ++ tmInstance_t instance ++) ++{ ++#ifndef NO_HDCP ++ tmbslHdmiTxHdcpHandlePJ(instance); ++#else ++ (void)instance; ++#endif /* NO_HDCP */ ++} ++ ++/****************************************************************************** ++ \brief R0 interrupt callback. ++ ++ \param instance Instance identifier. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxHandleR0 ++( ++ tmInstance_t instance ++) ++{ ++#ifndef NO_HDCP ++ tmErrorCode_t errCode; ++ tmbslHdmiTxSinkCategory_t category; ++ ++ ++ ++ if (hdcpInfoListTx[instance].bKsvSecure == True) ++ { ++ ++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_HDCP_ACTIVE) == TMDL_HDMITX_EVENT_ENABLED) ++ { ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ unitTableTx[instance].pCallback(TMDL_HDMITX_HDCP_ACTIVE); ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]); ++ } ++ ++ instanceStatusInfoTx[instance].pColBarState->hdcpSecureOrT0 = False; ++ } ++ ++ ++ errCode = tmbslHdmiTxHdcpGetSinkCategory(instance, ++ &category); ++ if (errCode != TM_OK) return; ++ ++ if (category == HDMITX_SINK_CAT_NOT_REPEATER) ++ { ++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_RX_KEYS_RECEIVED) == TMDL_HDMITX_EVENT_ENABLED) ++ { ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ unitTableTx[instance].pCallback(TMDL_HDMITX_RX_KEYS_RECEIVED); ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]); ++ } ++ } ++ ++ instanceStatusInfoTx[instance].pColBarState->disableColorBarOnR0 = True; ++ instanceStatusInfoTx[instance].pColBarState->hdcpColbarChange = True; ++#else ++ (void)instance; ++#endif /* NO_HDCP */ ++} ++ ++/****************************************************************************** ++ \brief SW_INT interrupt callback. ++ ++ \param instance Instance identifier. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxHandleSW_INT ++( ++ tmInstance_t instance ++) ++{ ++ DUMMY_ACCESS(instance); ++} ++ ++/****************************************************************************** ++ \brief RX_SENSE interrupt callback. ++ ++ \param instance Instance identifier. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxHandleRX_SENSE ++( ++ tmInstance_t instance ++) ++{ ++ tmErrorCode_t errCode; ++ tmbslHdmiTxRxSense_t rxSenseStatus; /* Rx Sense status */ ++ tmbslHdmiTxHotPlug_t hpdStatus; /* HPD status */ ++ ++ errCode = tmbslHdmiTxRxSenseGetStatus(instance, ++ &rxSenseStatus,False); ++ ++ if (errCode != TM_OK) return; ++ ++ errCode = tmbslHdmiTxHotPlugGetStatus(instance, ++ &hpdStatus,False); ++ ++ if (errCode != TM_OK) return; ++ ++// if (hpdStatus == HDMITX_HOTPLUG_ACTIVE) ++// { ++ if (rxSenseStatus == HDMITX_RX_SENSE_ACTIVE) ++ { ++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_RX_DEVICE_ACTIVE) == TMDL_HDMITX_EVENT_ENABLED) ++ { ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ unitTableTx[instance].pCallback(TMDL_HDMITX_RX_DEVICE_ACTIVE); ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]); ++ } ++ } ++ else if (rxSenseStatus == HDMITX_RX_SENSE_INACTIVE) ++ { ++ ++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_RX_DEVICE_INACTIVE) == TMDL_HDMITX_EVENT_ENABLED) ++ { ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ unitTableTx[instance].pCallback(TMDL_HDMITX_RX_DEVICE_INACTIVE); ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]); ++ } ++ ++#ifndef NO_HDCP ++ if (unitTableTx[instance].hdcpEnable == True) ++ { ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ /* Switch off HDCP */ ++ (void)tmdlHdmiTxSetHdcp(instance, False); ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]); ++ } ++#endif /* NO_HDCP */ ++ } ++// } ++} ++ ++/****************************************************************************** ++ \brief EDID_READ interrupt callback. ++ ++ \param instance Instance identifier. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxHandleEDID_READ ++( ++ tmInstance_t instance ++) ++{ ++ tmErrorCode_t errCode; ++ UInt8 edidStatus = TMDL_HDMITX_EDID_NOT_READ; ++ ++ /* Get the edid status and read the connected device's EDID */ ++ ++ /* Get Edid status */ ++ errCode = tmbslHdmiTxEdidGetStatus(instance, ++ &edidStatus); ++ ++ if (errCode != TM_OK) ++ { ++ /* Set state machine to Plugged */ ++ dlHdmiTxSetState(instance, STATE_PLUGGED); ++ return; ++ } ++ ++ /* Has hot plug changed to Active? */ ++ if ((edidStatus == TMDL_HDMITX_EDID_READ) || ++ (edidStatus == TMDL_HDMITX_EDID_ERROR_CHK)) ++ { ++ /* Set state machine to EDID available */ ++ dlHdmiTxSetState(instance, STATE_EDID_AVAILABLE); ++ } ++ else ++ { ++ /* Set state machine to Plugged */ ++ dlHdmiTxSetState(instance, STATE_PLUGGED); ++ } ++ ++ ++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_EDID_RECEIVED) == TMDL_HDMITX_EVENT_ENABLED) ++ { ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ unitTableTx[instance].pCallback(TMDL_HDMITX_EDID_RECEIVED); ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]); ++ } ++ ++ ++} ++ ++/****************************************************************************** ++ \brief VS_RPT interrupt callback. ++ ++ \param instance Instance identifier. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxHandleVS_RPT ++( ++ tmInstance_t instance ++) ++{ ++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_VS_RPT_RECEIVED) == TMDL_HDMITX_EVENT_ENABLED) ++ { ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]); ++ unitTableTx[instance].pCallback(TMDL_HDMITX_VS_RPT_RECEIVED); ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]); ++ } ++} ++ ++/****************************************************************************** ++ \brief dlHdmiTxConvertDTDtoCEA_640HAP . ++ ++ \param pDTDescriptors DTD to convert. ++ pictureAspectRatio aspect ratio of DTD ++ formatInterlaced DTD Interlaced or progressif ++ ++ \return NA. ++ ++******************************************************************************/ ++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_640HAP ++( ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors ++) ++{ ++ tmdlHdmiTxVidFmt_t codeCEA; ++ ++ switch (pDTDescriptors->vActiveLines) ++ { ++ case 480: ++ codeCEA = TMDL_HDMITX_VFMT_01_640x480p_60Hz; ++ break; ++ ++ default: ++ /* Not a valid format */ ++ codeCEA = TMDL_HDMITX_VFMT_NULL; ++ break; ++ } ++ ++ return codeCEA; ++ ++} ++ ++/****************************************************************************** ++ \brief dlHdmiTxConvertDTDtoCEA_720HAP . ++ ++ \param pDTDescriptors DTD to convert. ++ pictureAspectRatio aspect ratio of DTD ++ formatInterlaced DTD Interlaced or progressif ++ ++ \return NA. ++ ++******************************************************************************/ ++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_720HAP ++( ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors, ++ tmdlHdmiTxPictAspectRatio_t pictureAspectRatio ++) ++{ ++ tmdlHdmiTxVidFmt_t codeCEA; ++ ++ switch (pDTDescriptors->vActiveLines) ++ { ++ case 480: ++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3) ++ { ++ codeCEA = TMDL_HDMITX_VFMT_02_720x480p_60Hz; ++ } ++ else ++ { ++ codeCEA = TMDL_HDMITX_VFMT_03_720x480p_60Hz; ++ } ++ break; ++ ++ case 576: ++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3) ++ { ++ codeCEA = TMDL_HDMITX_VFMT_17_720x576p_50Hz; ++ } ++ else ++ { ++ codeCEA = TMDL_HDMITX_VFMT_18_720x576p_50Hz; ++ } ++ break; ++ ++ default: ++ /* Not a valid format */ ++ codeCEA = TMDL_HDMITX_VFMT_NULL; ++ break; ++ } ++ ++ return codeCEA; ++ ++} ++/****************************************************************************** ++ \brief dlHdmiTxConvertDTDtoCEA_1280HAP . ++ ++ \param pDTDescriptors DTD to convert. ++ pictureAspectRatio aspect ratio of DTD ++ formatInterlaced DTD Interlaced or progressif ++ ++ \return NA. ++ ++******************************************************************************/ ++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1280HAP ++( ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors ++) ++{ ++ tmdlHdmiTxVidFmt_t codeCEA; ++ ++ switch (pDTDescriptors->vActiveLines) ++ { ++ case 720: ++ switch (pDTDescriptors->hBlankPixels) ++ { ++ case 370: ++ codeCEA = TMDL_HDMITX_VFMT_04_1280x720p_60Hz; ++ break; ++ ++ case 700: ++ codeCEA = TMDL_HDMITX_VFMT_19_1280x720p_50Hz; ++ break; ++ ++ default: ++ /* Not a valid format */ ++ codeCEA = TMDL_HDMITX_VFMT_NULL; ++ break; ++ } ++ break; ++ ++ default: ++ /* Not a valid format */ ++ codeCEA = TMDL_HDMITX_VFMT_NULL; ++ break; ++ } ++ ++ ++ return codeCEA; ++} ++ ++/****************************************************************************** ++ \brief dlHdmiTxConvertDTDtoCEA_1920HAP . ++ ++ \param pDTDescriptors DTD to convert. ++ pictureAspectRatio aspect ratio of DTD ++ formatInterlaced DTD Interlaced or progressif ++ ++ \return NA. ++ ++******************************************************************************/ ++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1920HAP ++( ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors, ++ Bool formatInterlaced ++ ++) ++{ ++ tmdlHdmiTxVidFmt_t codeCEA; ++ ++ switch (pDTDescriptors->hBlankPixels) ++ { ++ case 280: ++ if (formatInterlaced) ++ { ++ codeCEA = TMDL_HDMITX_VFMT_05_1920x1080i_60Hz; ++ } ++ else ++ { ++ if ( pDTDescriptors->pixelClock == 14850 ) ++ { ++ codeCEA = TMDL_HDMITX_VFMT_16_1920x1080p_60Hz; ++ } ++ else ++ { ++ codeCEA = TMDL_HDMITX_VFMT_34_1920x1080p_30Hz; ++ } ++ } ++ break; ++ ++ case 720: ++ if (formatInterlaced) ++ { ++ codeCEA = TMDL_HDMITX_VFMT_20_1920x1080i_50Hz; ++ } ++ else ++ { ++ switch (pDTDescriptors->pixelClock) ++ { ++ case 14850: ++ codeCEA = TMDL_HDMITX_VFMT_31_1920x1080p_50Hz; ++ break; ++ ++ case 7425: ++ codeCEA = TMDL_HDMITX_VFMT_33_1920x1080p_25Hz; ++ break; ++ default: ++ /* Not a valid format */ ++ codeCEA = TMDL_HDMITX_VFMT_NULL; ++ break; ++ } ++ } ++ break; ++ ++ case 830: ++ codeCEA = TMDL_HDMITX_VFMT_32_1920x1080p_24Hz; ++ break; ++ ++ default: ++ /* Not a valid format */ ++ codeCEA = TMDL_HDMITX_VFMT_NULL; ++ break; ++ } ++ ++ ++ return codeCEA; ++} ++ ++/****************************************************************************** ++ \brief dlHdmiTxConvertDTDtoCEA_1440HAP . ++ ++ \param pDTDescriptors DTD to convert. ++ pictureAspectRatio aspect ratio of DTD ++ formatInterlaced DTD Interlaced or progressif ++ ++ \return NA. ++ ++******************************************************************************/ ++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1440HAP ++( ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors, ++ tmdlHdmiTxPictAspectRatio_t pictureAspectRatio, ++ Bool formatInterlaced ++ ++) ++{ ++ tmdlHdmiTxVidFmt_t codeCEA; ++ ++ switch (pDTDescriptors->vActiveLines) ++ { ++ case 240: ++ if (formatInterlaced) ++ { ++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3) ++ { ++ codeCEA = TMDL_HDMITX_VFMT_06_720x480i_60Hz; ++ } ++ else ++ { ++ codeCEA = TMDL_HDMITX_VFMT_07_720x480i_60Hz; ++ } ++ } ++ else ++ { ++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3) ++ { ++ codeCEA = TMDL_HDMITX_VFMT_08_720x240p_60Hz; ++ } ++ else ++ { ++ codeCEA = TMDL_HDMITX_VFMT_09_720x240p_60Hz; ++ } ++ } ++ break; ++ ++ case 288: ++ if (formatInterlaced) ++ { ++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3) ++ { ++ codeCEA = TMDL_HDMITX_VFMT_21_720x576i_50Hz; ++ } ++ else ++ { ++ codeCEA = TMDL_HDMITX_VFMT_22_720x576i_50Hz; ++ } ++ } ++ else ++ { ++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3) ++ { ++ codeCEA = TMDL_HDMITX_VFMT_23_720x288p_50Hz; ++ } ++ else ++ { ++ codeCEA = TMDL_HDMITX_VFMT_24_720x288p_50Hz; ++ } ++ } ++ break; ++ ++ case 480: ++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3) ++ { ++ codeCEA = TMDL_HDMITX_VFMT_14_1440x480p_60Hz; ++ } ++ else ++ { ++ codeCEA = TMDL_HDMITX_VFMT_15_1440x480p_60Hz; ++ } ++ break; ++ ++ case 576: ++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3) ++ { ++ codeCEA = TMDL_HDMITX_VFMT_29_1440x576p_50Hz; ++ } ++ else ++ { ++ codeCEA = TMDL_HDMITX_VFMT_30_1440x576p_50Hz; ++ } ++ break; ++ ++ default: ++ /* Not a valid format */ ++ codeCEA = TMDL_HDMITX_VFMT_NULL; ++ break; ++ } ++ ++ return codeCEA; ++} ++ ++/****************************************************************************** ++ \brief dlHdmiTxConvertDTDtoCEA_2880HAP . ++ ++ \param pDTDescriptors DTD to convert. ++ pictureAspectRatio aspect ratio of DTD ++ formatInterlaced DTD Interlaced or progressif ++ ++ \return NA. ++ ++******************************************************************************/ ++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_2880HAP ++( ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors, ++ tmdlHdmiTxPictAspectRatio_t pictureAspectRatio, ++ Bool formatInterlaced ++) ++{ ++ tmdlHdmiTxVidFmt_t codeCEA; ++ ++ switch (pDTDescriptors->vActiveLines) ++ { ++ case 240: ++ if (formatInterlaced) ++ { ++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3) ++ { ++ codeCEA = TMDL_HDMITX_VFMT_10_720x480i_60Hz; ++ } ++ else ++ { ++ codeCEA = TMDL_HDMITX_VFMT_11_720x480i_60Hz; ++ } ++ } ++ else ++ { ++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3) ++ { ++ codeCEA = TMDL_HDMITX_VFMT_12_720x240p_60Hz; ++ } ++ else ++ { ++ codeCEA = TMDL_HDMITX_VFMT_13_720x240p_60Hz; ++ } ++ } ++ break; ++ ++ case 288: ++ if (formatInterlaced) ++ { ++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3) ++ { ++ codeCEA = TMDL_HDMITX_VFMT_25_720x576i_50Hz; ++ } ++ else ++ { ++ codeCEA = TMDL_HDMITX_VFMT_26_720x576i_50Hz; ++ } ++ } ++ else ++ { ++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3) ++ { ++ codeCEA = TMDL_HDMITX_VFMT_27_720x288p_50Hz; ++ } ++ else ++ { ++ codeCEA = TMDL_HDMITX_VFMT_28_720x288p_50Hz; ++ } ++ } ++ break; ++ ++ default: ++ /* Not a valid format */ ++ codeCEA = TMDL_HDMITX_VFMT_NULL; ++ break; ++ } ++ ++ return codeCEA; ++} ++ ++/****************************************************************************** ++ \brief EdidGetDTD . ++ ++ \param . ++ ++ \return NA. ++ ++******************************************************************************/ ++tmErrorCode_t dlHdmiTxEdidGetDTD ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors, ++ UInt8 maxDTDesc, ++ UInt8 *pWrittenDTDesc ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check the current state */ ++ RETIF( dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ /* Get detailled descriptors from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */ ++ RETIF((errCode = tmbslHdmiTxEdidGetDetailedTimingDescriptors( ++ instance, (tmbslHdmiTxEdidDtd_t *)pDTDescriptors, maxDTDesc, pWrittenDTDesc) ) != TM_OK, errCode); ++ ++ return TM_OK; ++} ++ ++ ++/****************************************************************************** ++ \brief Command processing task, dedicated to unit/instance 0. ++ ++ \param NA. ++ ++ \return NA. ++ ++******************************************************************************/ ++ ++#ifndef TMFL_NO_RTOS ++static void CommandTaskUnit0() ++{ ++ UInt8 command; ++ Bool loop = True; /* Just to avoid compiler warning */ ++ tmErrorCode_t err = TM_OK; ++ ++ while(loop) ++ { ++ tmdlHdmiTxIWQueueReceive(unitTableTx[0].queueHandle, &command); ++ ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[0]); ++ ++ /* Clear T0 flag before polling for interrupts */ ++ instanceStatusInfoTx[0].pColBarState->hdcpSecureOrT0 = False; ++ ++ if (gI2CDebugAccessesEnabled == True) ++ { ++ ++ err = tmbslHdmiTxHwHandleInterrupt(0); ++ ++ if ((err == TMBSL_ERR_HDMI_I2C_WRITE) || (err == TMBSL_ERR_HDMI_I2C_READ)) ++ { ++ ++ unitTableTx[0].pCallback(TMDL_HDMITX_DEBUG_EVENT_1); ++ } ++ ++ }/* (gI2CDebugAccessesEnabled == True) */ ++ ++ /* Enable interrupts for Tx (interrupts are disabled in the HandleInterrupt function) */ ++ tmdlHdmiTxIWEnableInterrupts(TMDL_HDMI_IW_TX_1); ++ ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[0]); ++ }; ++} ++#endif /* TMFL_NO_RTOS */ ++ ++/****************************************************************************** ++ \brief Hdcp check task, dedicated to unit/instance 0. ++ ++ \param NA. ++ ++ \return NA. ++ ++******************************************************************************/ ++#ifndef TMFL_NO_RTOS ++static void HdcpTaskUnit0() ++{ ++ Bool loop = True; /* Just to avoid compiler warning */ ++ Bool featureSupported; ++ ++ tmbslHdmiTxHwGetCapabilities(0, ++ HDMITX_FEATURE_HW_HDCP, &featureSupported); ++ ++#ifndef NO_HDCP ++ while(loop) ++ { ++ (void)tmdlHdmiTxIWWait(35); ++ ++ /* Take the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[0]); ++ ++ if (gI2CDebugAccessesEnabled == True) ++ { ++ ++ dlHdmiTxCheckColorBar(0); ++ dlHdmiTxCheckHdcpColorBar(0); ++ ++ if (featureSupported == True) ++ { ++ tmbslHdmiTxHdcpCheck(0,35, (tmbslHdmiTxHdcpCheck_t *)&(hdcpInfoListTx[0].hdcpCheckState)); ++ } ++ ++ } /* gI2CDebugAccessesEnabled == True*/ ++ ++ /* Release the sempahore */ ++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[0]); ++ }; ++#else ++ (void)loop; ++#endif /* NO_HDCP */ ++} ++#endif /* TMFL_NO_RTOS */ ++ ++#ifndef NO_HDCP ++/****************************************************************************** ++ \brief Check hdcp state to manage color bar. ++ ++ \param instance Instance identifier. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxCheckHdcpColorBar ++( ++ tmInstance_t instance ++) ++{ ++ /* Use HDCP check result to control HDCP colour bars */ ++ if ( (instanceStatusInfoTx[instance].pColBarState->disableColorBarOnR0 == True) ++ && (instanceStatusInfoTx[instance].pColBarState->hdcpColbarChange == True) ++ && (instanceStatusInfoTx[instance].pColBarState->hdcpSecureOrT0 == False) ) ++ { ++ /* Remove test pattern once if Authenticated with no error interrupts */ ++ if (instanceStatusInfoTx[instance].pColBarState->colorBarOn != False) ++ { ++ instanceStatusInfoTx[instance].pColBarState->colorBarOn = False; ++ instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = True; ++ ++ if (unitTableTx[instance].simplayHd == True) { ++ ++ /* Mute or Un-mute the audio output */ ++ tmbslHdmiTxAudioOutSetMute(instance,(tmbslHdmiTxaMute_t)HDMITX_AMUTE_OFF); ++ ++ /* Store current audio mute status */ ++ instanceStatusInfoTx[instance].pAudioInfo->audioMuteState = False; ++ } ++ ++ ++ } ++ /* Reset state flags */ ++ instanceStatusInfoTx[instance].pColBarState->hdcpColbarChange = False; ++ instanceStatusInfoTx[instance].pColBarState->hdcpSecureOrT0 = True; ++ ++#ifdef TMFL_TDA19989 ++ instanceStatusInfoTx[instance].pColBarState->disableColorBarOnR0 = False; ++#endif /* TMFL_TDA19989 */ ++ ++ ++ ++ } ++ ++ if ( (instanceStatusInfoTx[instance].pColBarState->hdcpEncryptOrT0 == True) ++ && (instanceStatusInfoTx[instance].pColBarState->inOutFirstSetDone == True)) ++ { ++ /* Set test pattern once if not Authenticated, to mask HDCP failure */ ++ if (instanceStatusInfoTx[instance].pColBarState->colorBarOn != True) ++ { ++ instanceStatusInfoTx[instance].pColBarState->colorBarOn = True; ++ instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = True; ++ ++ if (unitTableTx[instance].simplayHd == True) { ++ ++ /* Mute or Un-mute the audio output */ ++ tmbslHdmiTxAudioOutSetMute(instance,(tmbslHdmiTxaMute_t)HDMITX_AMUTE_ON); ++ ++ /* Store current audio mute status */ ++ instanceStatusInfoTx[instance].pAudioInfo->audioMuteState = True; ++ } ++ ++ } ++ /* Reset state flag */ ++ instanceStatusInfoTx[instance].pColBarState->hdcpEncryptOrT0 = False; ++ } ++} ++#endif ++ ++#ifndef NO_HDCP ++/****************************************************************************** ++ \brief Show color bars or restore the last video format. ++ ++ \param instance Instance identifier. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxCheckColorBar ++( ++ tmInstance_t instance ++) ++{ ++ if ( (instanceStatusInfoTx[instance].pColBarState->inOutFirstSetDone == True) ++ && (instanceStatusInfoTx[instance].pColBarState->changeColorBarNow == True) ) ++ { ++ instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = False; ++ ++ if (unitTableTx[instance].simplayHd == True) ++ { ++ if (instanceStatusInfoTx[instance].pColBarState->colorBarOn == True) ++ { ++ /* Set service mode colour bar on/off (also used as HDCP logo pattern) */ ++ (void)dlHdmiTxSetTestPatternOn(instance, instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format, ++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode, ++ gtmdlHdmiTxDriverConfigTable[instance].pattern); ++ } ++ else ++ { ++ /* Restore last output format and mode */ ++ (void)dlHdmiTxSetTestPatternOff(instance, ++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format, ++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode); ++ } ++ } ++ } ++} ++#endif ++ ++#ifndef NO_HDCP ++/****************************************************************************** ++ \brief Get hdcp seed. ++ ++ \param instance Instance identifier. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxFindHdcpSeed ++( ++ tmInstance_t instance ++) ++{ ++#if HDCP_SEED_DEFAULT == HDCP_SEED_NULL ++ UInt8 otp[3]; ++#endif ++ ++ /* If no seed is coded in this file then find it somewhere else */ ++#if HDCP_SEED_DEFAULT == HDCP_SEED_NULL ++ /* See if a seed table has been programmed in flash */ ++ if (kSeedTable[0][0] != 0xFFFF) ++ { ++ /* Read OTP LSB at address 0x00 and try to match in flash table */ ++ if ( (tmbslHdmiTxHdcpGetOtp(instance, ++ 0x00, otp)) == TM_OK) ++ { ++ int i; ++ for (i = 0; i < SEED_TABLE_LEN; i++) ++ { ++ if (kSeedTable[i][0] == otp[2]) /* OTP_DATA_LSB */ ++ { ++ /* Found seed! */ ++ gtmdlHdmiTxDriverConfigTable[instance].keySeed = kSeedTable[i][1]; ++ break; ++ } ++ } ++ } ++ } ++#endif /* HDCP_SEED_DEFAULT != HDCP_SEED_NULL */ ++ ++ /* Initialise the TDA9984 HDCP keys */ ++ if (gtmdlHdmiTxDriverConfigTable[instance].keySeed != HDCP_SEED_NULL) ++ { ++ /* Initialise the HDMI Transmitter HDCP keys */ ++ tmbslHdmiTxHdcpDownloadKeys(instance, ++ gtmdlHdmiTxDriverConfigTable[instance].keySeed, HDMITX_HDCP_DECRYPT_ENABLE); ++ } ++} ++#endif /* NO_HDCP */ ++ ++/****************************************************************************** ++ \brief Set the state of the state machine. ++ ++ \param instance Instance identifier. ++ \param state State of the state machine. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxSetState ++( ++ tmInstance_t instance, ++ tmdlHdmiTxDriverState_t state ++) ++{ ++ /* Set the state */ ++ unitTableTx[instance].state = state; ++} ++ ++/****************************************************************************** ++ \brief Get the state of the state machine. ++ ++ \param instance Instance identifier. ++ ++ \return tmdlHdmiTxDriverState_t Current State of the state machine. ++ ++******************************************************************************/ ++tmdlHdmiTxDriverState_t dlHdmiTxGetState ++( ++ tmInstance_t instance ++) ++{ ++ tmdlHdmiTxDriverState_t state; ++ ++ /* Get the state */ ++ state = unitTableTx[instance].state; ++ ++ return (state); ++} ++ ++/****************************************************************************** ++ \brief Get the state of the event (enabled or disabled). ++ ++ \param instance Instance identifier. ++ \param event Event to give the state. ++ ++ \return NA. ++ ++******************************************************************************/ ++static tmdlHdmiTxEventStatus_t dlHdmiTxGetEventStatus ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEvent_t event ++) ++{ ++ tmdlHdmiTxEventStatus_t eventStatus; ++ ++ /* Get the event status */ ++ eventStatus = instanceStatusInfoTx[instance].pEventState[event].status; ++ ++ return (eventStatus); ++} ++ ++/****************************************************************************** ++ \brief Caculation of aspect ratio. ++ ++ \param HImageSize Horizontal image size. ++ \param VImageSize Vertical image size. ++ ++ \return NA. ++ ++******************************************************************************/ ++static tmdlHdmiTxPictAspectRatio_t dlHdmiTxCalcAspectRatio ( ++ UInt16 HImageSize, ++ UInt16 VImageSize ++) ++{ ++ tmdlHdmiTxPictAspectRatio_t pictureAspectRatio; ++ UInt16 calcPictureAspectRatio; ++ ++ /* Define picture Aspect Ratio */ ++ /* 16/9 = 1.77777 so the result approach is 2 */ ++ /* 4/3 = 1.33333 so the result approach is 1 */ ++ /* operation : */ ++ /* ImageSize + (vImageSize/2) */ ++ /* -------------------------- > vImageSize ->True 16/9 False 4/3 */ ++ /* 2 */ ++ ++ calcPictureAspectRatio = ((UInt16)(HImageSize + ((VImageSize)>>1)))>>1; ++ ++ if(calcPictureAspectRatio > VImageSize) ++ { ++ pictureAspectRatio = TMDL_HDMITX_P_ASPECT_RATIO_16_9; ++ } ++ else ++ { ++ pictureAspectRatio = TMDL_HDMITX_P_ASPECT_RATIO_4_3; ++ } ++ ++ return pictureAspectRatio; ++ ++} ++ ++#ifndef NO_HDCP ++/****************************************************************************** ++ \brief dlHdmiTxCheckHdcpBksv . ++ ++ \param pHdcpBksvTested ksv To test. ++ \param pbBksvSecure Test result. ++ \param bBigEndian ksv provide by hardware are in little or big endian. ++ ++ \return NA. ++ ++******************************************************************************/ ++static void dlHdmiTxCheckHdcpBksv ++( ++ tmInstance_t instance, ++ UInt8 * pHdcpBksvTested, ++ Bool * pbBksvSecure, ++ Bool bBigEndian ++) ++{ ++ ++ UInt32 NbInRevocationList; ++ ++ NbInRevocationList = 0; ++ ++ /* CBE: force secure, otherwise we will not look at anything */ ++ *pbBksvSecure = True; ++ ++ if ((unitTableTx[instance].revocationList.pList != Null) && (unitTableTx[instance].revocationList.length > 0)) ++ { ++ while ((*pbBksvSecure == True) && (NbInRevocationList < unitTableTx[instance].revocationList.length)) ++ { ++ if (bBigEndian) ++ { ++ if ((pHdcpBksvTested[0] == unitTableTx[instance].revocationList.pList[NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE]) ++ && ++ (pHdcpBksvTested[1] == unitTableTx[instance].revocationList.pList[1 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)]) ++ && ++ (pHdcpBksvTested[2] == unitTableTx[instance].revocationList.pList[2 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)]) ++ && ++ (pHdcpBksvTested[3] == unitTableTx[instance].revocationList.pList[3 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)]) ++ && ++ (pHdcpBksvTested[4] == unitTableTx[instance].revocationList.pList[4 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)]) ++ ) ++ { ++ *pbBksvSecure = False; ++ } ++ } ++ else ++ { ++ if ((pHdcpBksvTested[4] == unitTableTx[instance].revocationList.pList[NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE]) ++ && ++ (pHdcpBksvTested[3] == unitTableTx[instance].revocationList.pList[1 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)]) ++ && ++ (pHdcpBksvTested[2] == unitTableTx[instance].revocationList.pList[2 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)]) ++ && ++ (pHdcpBksvTested[1] == unitTableTx[instance].revocationList.pList[3 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)]) ++ && ++ (pHdcpBksvTested[0] == unitTableTx[instance].revocationList.pList[4 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)]) ++ ) ++ { ++ *pbBksvSecure = False; ++ } ++ } ++ NbInRevocationList++; ++ } ++ ++ } ++ ++ ++} ++#endif ++ ++/****************************************************************************** ++ \brief dlHdmiTxCalcVidFmtIndex. ++ ++ \param vidFmt video format. ++ ++ \return table index. ++ ++******************************************************************************/ ++static tmdlHdmiTxVidFmt_t dlHdmiTxCalcVidFmtIndex(tmdlHdmiTxVidFmt_t vidFmt) ++{ ++ tmdlHdmiTxVidFmt_t vidFmtIndex = vidFmt; ++ ++ /* Hanlde VIC or table index discontinuity */ ++ if((vidFmt >= TMDL_HDMITX_VFMT_60_1280x720p_24Hz) && (vidFmt <= TMDL_HDMITX_VFMT_62_1280x720p_30Hz)) ++ { ++ vidFmtIndex = (tmdlHdmiTxVidFmt_t)(TMDL_HDMITX_VFMT_INDEX_60_1280x720p_24Hz + (vidFmt - TMDL_HDMITX_VFMT_60_1280x720p_24Hz)); ++ } ++#ifdef FORMAT_PC ++ else if (vidFmt >= TMDL_HDMITX_VFMT_PC_MIN) ++ { ++ vidFmtIndex = (tmdlHdmiTxVidFmt_t)(TMDL_HDMITX_VFMT_TV_NUM + (vidFmt - TMDL_HDMITX_VFMT_PC_MIN)); ++ } ++#endif /* FORMAT_PC */ ++ return(vidFmtIndex); ++} ++ ++ ++tmErrorCode_t tmdlHdmiTxDebugEnableI2CAccesses ( tmInstance_t instance, ++ Bool enableI2C) ++{ ++ tmErrorCode_t errCode = TM_OK; ++ ++ /* Check if instance number is in range */ ++ if( (instance < 0) || (instance >= MAX_UNITS) ) ++ { ++ errCode = TMDL_ERR_DLHDMITX_BAD_INSTANCE; ++ return errCode; ++ } ++ ++ if (enableI2C == True) ++ { ++ errCode = tmbslDebugWriteFakeRegPage(instance); ++ gI2CDebugAccessesEnabled = True; ++ } ++ else ++ { ++ gI2CDebugAccessesEnabled = False; ++ } ++ ++ ++ return errCode; ++ ++} /* tmdlHdmiTxDebugManageI2CAccesses */ ++ ++/*****************************************************************************/ ++/** ++ \brief Retreives current HDCP link status. This function is typically used ++ when an "HDCP INACTIVE" event is received to know why HDCP ++ is INACTIVE. ++ ++ \param instance Instance identifier. ++ \param pHdcpStatus Pointer to the enum describing the status. ++ \param pRawStatus Pointer to the byte with the raw error code from HW. ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong ++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out ++ of range ++ - TMDL_ERR_DLHDMITX_NOT_INITIALIZED: the transmitter is not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetHdcpFailStatus ++( ++ tmInstance_t instance, ++ tmdlHdmiTxHdcpStatus_t *pHdcpStatus, ++ UInt8 *pRawStatus ++) ++{ ++ tmErrorCode_t errCode = TM_OK; ++ ++#ifndef NO_HDCP ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ RETIF(pHdcpStatus == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ RETIF(pRawStatus == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ *pRawStatus = hdcpInfoListTx[instance].hdcpErrorState; ++ ++ switch (hdcpInfoListTx[instance].hdcpErrorState) ++ { ++ ++ case 0: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_OK; ++ break; ++ ++ case 0x02: ++ case 0x03: ++ case 0x04: ++ case 0x05: ++ case 0x06: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_BKSV_RCV_FAIL; ++ break; ++ ++ case 0x08: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_BKSV_CHECK_FAIL; ++ break; ++ ++ case 0x0C: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_BCAPS_RCV_FAIL; ++ break; ++ ++ case 0x0F: ++ case 0x10: ++ case 0x11: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_AKSV_SEND_FAIL; ++ break; ++ ++ case 0x23: ++ case 0x24: ++ case 0x25: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_R0_RCV_FAIL; ++ break; ++ ++ case 0x26: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_R0_CHECK_FAIL; ++ break; ++ ++ case 0x27: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_BKSV_NOT_SECURE; ++ break; ++ ++ case 0x2B: ++ case 0x2C: ++ case 0x2D: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_RI_RCV_FAIL; ++ break; ++ ++ case 0x77: ++ case 0x78: ++ case 0x79: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_RI_RCV_FAIL; ++ break; ++ ++ case 0x2E: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_RI_CHECK_FAIL; ++ break; ++ ++ case 0x7A: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_RI_CHECK_FAIL; ++ break; ++ ++ case 0x66: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_BCAPS_RCV_FAIL; ++ break; ++ ++ case 0x67: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_BCAPS_READY_TIMEOUT; ++ break; ++ ++ case 0x6A: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_V_RCV_FAIL; ++ break; ++ ++ case 0x6C: ++ case 0x6D: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_BSTATUS_RCV_FAIL; ++ break; ++ ++ case 0x6F: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_KSVLIST_RCV_FAIL; ++ break; ++ ++ case 0x74: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_KSVLIST_NOT_SECURE; ++ break; ++ ++ default: ++ *pHdcpStatus = TMDL_HDMITX_HDCP_UNKNOWN_STATUS; ++ break; ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++#else ++ (void)instance; /* Remove compiler warning */ ++#endif /* NO_HDCP */ ++ ++ return errCode; ++} ++ ++ ++tmErrorCode_t tmdlHdmiTxGetEdidLatencyInfo ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidLatency_t *pLatency ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check pointer is Null */ ++ RETIF( pLatency == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check the current state */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxEdidGetLatencyInfo(instance, (tmbslHdmiTxEdidLatency_t *) pLatency) ) != TM_OK, errCode) ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} /* tmdlHdmiTxGetEdidLatencyInfo */ ++ ++/****************************************************************************** ++ \brief Retrieves additional data from receiver's EDID VSDB. This function ++ parses the EDID of Rx device to get the relevant data. ++ This function is synchronous. ++ This function is not ISR friendly. ++ ++ \param instance Instance identifier. ++ \param pExtraVsdbData Pointer to the structure of additional VSDB data ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or ++ out of range ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for ++ the function ++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range ++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number ++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read ++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxGetEdidExtraVsdbData ++( ++ tmInstance_t instance, ++ tmdlHdmiTxEdidExtraVsdbData_t **pExtraVsdbData ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ /* Check pointer is Null */ ++ RETIF(pExtraVsdbData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Check the current state */ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE) ++ ++ RETIF_SEM(dlHdmiTxItSemaphore[instance], ++ (errCode = tmbslHdmiTxEdidGetExtraVsdbData(instance, (tmbslHdmiTxEdidExtraVsdbData_t **)pExtraVsdbData) ) != TM_OK, errCode) ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++} /* tmdlHdmiTxGetEdidExtraVsdbData */ ++ ++ ++tmErrorCode_t tmdlHdmiTxGetHPDStatus ++( ++ tmInstance_t instance, ++ tmdlHdmiTxHotPlug_t * pHPDStatus ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ RETIF( pHPDStatus== Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Get the HPD status from BSL driver */ ++ errCode = tmbslHdmiTxHotPlugGetStatus(instance,(tmbslHdmiTxHotPlug_t *)pHPDStatus,True); ++ ++ if (errCode == TM_OK) { ++ /* do nothing */ ++ } ++ else { ++ *pHPDStatus = TMDL_HDMITX_HOTPLUG_INVALID; ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++ ++} /* tmdlHdmiTxGetHPDStatus */ ++ ++ ++ ++tmErrorCode_t tmdlHdmiTxGetRXSenseStatus ++( ++ tmInstance_t instance, ++ tmdlHdmiTxRxSense_t * pRXSenseStatus ++) ++{ ++ tmErrorCode_t errCode; ++ ++ /* Check if instance number is in range */ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ RETIF( pRXSenseStatus== Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ ++ /* Take the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ /* Get the RXS sense status from BSL driver */ ++ errCode = tmbslHdmiTxRxSenseGetStatus(instance,( tmbslHdmiTxRxSense_t*)pRXSenseStatus,True); ++ ++ if (errCode == TM_OK) { ++ /* do nothing */ ++ } ++ else { ++ *pRXSenseStatus = TMDL_HDMITX_RX_SENSE_INVALID; ++ } ++ ++ /* Release the sempahore */ ++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode) ++ ++ return TM_OK; ++ ++} /* tmdlHdmiTxGetRXSenseStatus */ ++ ++ ++/****************************************************************************** ++ \brief Mute or unmute the TMDS outputs. ++ ++ \param instance Instance identifier. ++ \param muteTmdsOut Mute or unmute indication. ++ ++ \return NA. ++ ++******************************************************************************/ ++tmErrorCode_t tmdlHdmiTxTmdsSetOutputsMute ++( ++ tmInstance_t instance, ++ Bool muteTmdsOut ++) ++{ ++ tmErrorCode_t errCode; ++ tmErrorCode_t errCodeSem; ++ tmbslHdmiTxTmdsOut_t tmdsOut; ++ ++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE) ++ ++ if (muteTmdsOut) ++ tmdsOut = HDMITX_TMDSOUT_FORCED0; // forced 0 outputs ++ else ++ tmdsOut = HDMITX_TMDSOUT_NORMAL; // normal outputs ++ ++ /* Take the sempahore */ ++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem) ++ ++ errCode = tmbslHdmiTxTmdsSetOutputs (instance, tmdsOut); ++ ++ /* Release the sempahore */ ++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem) ++ ++ ++ return errCode; ++} ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.c b/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.c +new file mode 100755 +index 0000000..fc6886d +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.c +@@ -0,0 +1,342 @@ ++/** ++ * Copyright (C) 2006 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmdlHdmiTx_local.c ++ * ++ * \version Revision: 1 ++ * ++ * \date Date: 21/02/08 ++ * ++ * \brief devlib driver component API for the TDA998x HDMI Transmitters ++ * ++ * \section refs Reference Documents ++ * HDMI Tx Driver - FRS.doc, ++ * ++ * \section info Change Information ++ * ++ * \verbatim ++ ++ History: tmdlHdmiTx_local.c ++ * ++ * ***************** Version 1 ***************** ++ * User: G. Burnouf Date: 21/02/08 ++ * Updated in $/Source/tmdlHdmiTx/src ++ * initial version ++ ++ \endverbatim ++ * ++*/ ++ ++/*============================================================================*/ ++/* INCLUDE FILES */ ++/*============================================================================*/ ++#include "tmdlHdmiTx_local.h" ++#include "tmdlHdmiTx_cfg.h" ++#include "tmdlHdmiTx.h" ++ ++/*============================================================================*/ ++/* TYPES DECLARATIONS */ ++/*============================================================================*/ ++ ++typedef struct _dlHdmiTxResolution_t { ++ tmdlHdmiTxVidFmt_t resolutionID; ++ UInt16 width; ++ UInt16 height; ++ Bool interlaced; ++ tmdlHdmiTxVfreq_t vfrequency; ++ tmdlHdmiTxPictAspectRatio_t aspectRatio; ++} dlHdmiTxResolution_t, *pdlHdmiTxResolution_t; ++ ++ ++/*============================================================================*/ ++/* CONSTANTS DECLARATIONS */ ++/*============================================================================*/ ++/* macro for quick error handling */ ++#ifndef RETIF ++#define RETIF(cond, rslt) if ((cond)){return (rslt);} ++#endif ++ ++/*============================================================================*/ ++/* FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++ ++/******************************************************************************/ ++/* DO NOT MODIFY */ ++/******************************************************************************/ ++ ++static void dlHdmiTxGenerateVideoPortTables ++( ++ tmUnitSelect_t unit, ++ tmdlHdmiTxDriverConfigTable_t *pConfig ++); ++ ++ ++/*============================================================================*/ ++/* VARIABLES DECLARATIONS */ ++/*============================================================================*/ ++ ++/** ++ * \brief List of the resolution to be detected by the device library ++ */ ++ ++#ifdef TMFL_OS_WINDOWS /* OS Windows */ ++dlHdmiTxResolution_t resolutionInfoTx[RESOLUTION_NB] = { ++#else /* OS ARM7 */ ++const dlHdmiTxResolution_t resolutionInfoTx[RESOLUTION_NB] = { ++#endif /* endif TMFL_OS_WINDOWS */ ++ /* TV Formats */ ++ /* 60 HZ */ ++ {TMDL_HDMITX_VFMT_01_640x480p_60Hz, 640, 480, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_02_720x480p_60Hz, 720, 480, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_03_720x480p_60Hz, 720, 480, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_04_1280x720p_60Hz, 1280, 720, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_05_1920x1080i_60Hz, 1920, 1080, True, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_06_720x480i_60Hz, 720, 480, True, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_07_720x480i_60Hz, 720, 480, True, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_08_720x240p_60Hz, 720, 240, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_09_720x240p_60Hz, 720, 240, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_10_720x480i_60Hz, 720, 480, True, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_11_720x480i_60Hz, 720, 480, True, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_12_720x240p_60Hz, 720, 240, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_13_720x240p_60Hz, 720, 240, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_14_1440x480p_60Hz, 1440, 480, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_15_1440x480p_60Hz, 1440, 480, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_16_1920x1080p_60Hz, 1920, 1080, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_35_2880x480p_60Hz, 2880, 480, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_36_2880x480p_60Hz, 2880, 480, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ ++ /* 50 HZ */ ++ {TMDL_HDMITX_VFMT_17_720x576p_50Hz, 720, 576, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_18_720x576p_50Hz, 720, 576, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_19_1280x720p_50Hz, 1280, 720, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_20_1920x1080i_50Hz, 1920, 1080, True, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_21_720x576i_50Hz, 720, 576, True, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_22_720x576i_50Hz, 720, 576, True, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_23_720x288p_50Hz, 720, 288, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_24_720x288p_50Hz, 720, 288, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_25_720x576i_50Hz, 720, 576, True, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_26_720x576i_50Hz, 720, 576, True, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_27_720x288p_50Hz, 720, 288, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_28_720x288p_50Hz, 720, 288, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_29_1440x576p_50Hz, 1440, 576, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_30_1440x576p_50Hz, 1440, 576, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_31_1920x1080p_50Hz, 1920, 1080, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_37_2880x576p_50Hz, 2880, 576, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_38_2880x576p_50Hz, 2880, 576, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ ++ /* Low Tv */ ++ {TMDL_HDMITX_VFMT_32_1920x1080p_24Hz, 1920, 1080, False, TMDL_HDMITX_VFREQ_24Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_33_1920x1080p_25Hz, 1920, 1080, False, TMDL_HDMITX_VFREQ_25Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_34_1920x1080p_30Hz, 1920, 1080, False, TMDL_HDMITX_VFREQ_30Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_60_1280x720p_24Hz, 1280, 720, False, TMDL_HDMITX_VFREQ_24Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_61_1280x720p_25Hz, 1280, 720, False, TMDL_HDMITX_VFREQ_25Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_62_1280x720p_30Hz, 1280, 720, False, TMDL_HDMITX_VFREQ_30Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9} ++ ++#ifdef FORMAT_PC ++ /* PC Formats */ ++ /* 60 HZ */ ++ ,{TMDL_HDMITX_VFMT_PC_640x480p_60Hz, 640, 480, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_PC_800x600p_60Hz, 800, 600, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_PC_1152x960p_60Hz, 1152, 960, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_6_5}, ++ {TMDL_HDMITX_VFMT_PC_1024x768p_60Hz, 1024, 768, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_PC_1280x768p_60Hz, 1280, 768, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_5_3}, ++ {TMDL_HDMITX_VFMT_PC_1280x1024p_60Hz, 1280, 1024, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_5_4}, ++ {TMDL_HDMITX_VFMT_PC_1360x768p_60Hz, 1360, 768, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}, ++ {TMDL_HDMITX_VFMT_PC_1400x1050p_60Hz, 1400, 1050, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_PC_1600x1200p_60Hz, 1600, 1200, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ /* 70 HZ */ ++ {TMDL_HDMITX_VFMT_PC_1024x768p_70Hz, 1024, 768, False, TMDL_HDMITX_VFREQ_70Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ /* 72 HZ */ ++ {TMDL_HDMITX_VFMT_PC_640x480p_72Hz, 640, 480, False, TMDL_HDMITX_VFREQ_72Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_PC_800x600p_72Hz, 800, 600, False, TMDL_HDMITX_VFREQ_72Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ /* 75 HZ */ ++ {TMDL_HDMITX_VFMT_PC_640x480p_75Hz, 640, 480, False, TMDL_HDMITX_VFREQ_75Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_PC_1024x768p_75Hz, 1024, 768, False, TMDL_HDMITX_VFREQ_75Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_PC_800x600p_75Hz, 800, 600, False, TMDL_HDMITX_VFREQ_75Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_PC_1024x864p_75Hz, 1024, 864, False, TMDL_HDMITX_VFREQ_75Hz, TMDL_HDMITX_P_ASPECT_RATIO_UNDEFINED}, ++ {TMDL_HDMITX_VFMT_PC_1280x1024p_75Hz, 1280, 1024, False, TMDL_HDMITX_VFREQ_75Hz, TMDL_HDMITX_P_ASPECT_RATIO_5_4}, ++ /* 85 HZ */ ++ {TMDL_HDMITX_VFMT_PC_640x350p_85Hz, 640, 350, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_UNDEFINED}, ++ {TMDL_HDMITX_VFMT_PC_640x400p_85Hz, 640, 400, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_10}, ++ {TMDL_HDMITX_VFMT_PC_720x400p_85Hz, 720, 400, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_9_5}, ++ {TMDL_HDMITX_VFMT_PC_640x480p_85Hz, 640, 480, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_PC_800x600p_85Hz, 800, 600, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_PC_1024x768p_85Hz, 1024, 768, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_PC_1152x864p_85Hz, 1152, 864, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_PC_1280x960p_85Hz, 1280, 960, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}, ++ {TMDL_HDMITX_VFMT_PC_1280x1024p_85Hz, 1280, 1024, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_5_4}, ++ /* 87 HZ */ ++ {TMDL_HDMITX_VFMT_PC_1024x768i_87Hz, 1024, 768, True, TMDL_HDMITX_VFREQ_87Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3} ++#endif /* FORMAT_PC */ ++}; ++ ++ ++/*============================================================================*/ ++/* FUNCTION */ ++/*============================================================================*/ ++ ++/******************************************************************************/ ++/* DO NOT MODIFY */ ++/****************************************************************************** ++ \brief This function allows to the main driver to retrieve its ++ configuration parameters. ++ ++ \param pConfig Pointer to the config structure ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t dlHdmiTxGetConfig ++( ++ tmUnitSelect_t unit, ++ tmdlHdmiTxDriverConfigTable_t *pConfig ++) ++{ ++ /* Check if unit number is in range */ ++ RETIF((unit < 0) || (unit >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER) ++ ++ /* Check if pointer is Null */ ++ RETIF(pConfig == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS) ++ ++ *pConfig = driverConfigTableTx[unit]; ++ ++ /* Done here because of const declaration of tables in ARM7 case */ ++ pConfig->pResolutionInfo = (ptmdlHdmiTxCfgResolution_t)resolutionInfoTx; ++ ++ /* Generate swap and mirror tables in function of video port mapping tables */ ++ dlHdmiTxGenerateVideoPortTables(unit, pConfig); ++ ++ return TM_OK; ++} ++ ++ ++/*============================================================================*/ ++/* INTERNAL FUNCTION */ ++/*============================================================================*/ ++/******************************************************************************/ ++/* DO NOT MODIFY */ ++/******************************************************************************/ ++static void dlHdmiTxGenerateVideoPortTables ++( ++ tmUnitSelect_t unit, ++ tmdlHdmiTxDriverConfigTable_t *pConfig ++) ++{ ++ UInt8 i; ++ ++ for (i=0; i<6; i++) ++ { ++ /* CCIR656 */ ++ if (videoPortMapping_CCIR656[unit][i] != TMDL_HDMITX_VIDCCIR_NOT_CONNECTED) ++ { ++ pConfig->pSwapTableCCIR656[videoPortMapping_CCIR656[unit][i] & 0x07F] = 5-i; ++ pConfig->pMirrorTableCCIR656[videoPortMapping_CCIR656[unit][i] & 0x07F] = (UInt8)(videoPortMapping_CCIR656[unit][i] >> 7); ++ /* Enable port and disable ground port */ ++ if (((5-i) % 2) == 0) ++ { ++ pConfig->pEnableVideoPortCCIR656[i/2] |= 0x0F; ++ pConfig->pGroundVideoPortCCIR656[i/2] = (UInt8)(pConfig->pGroundVideoPortCCIR656[i/2] & 0xF0); ++ } ++ else ++ { ++ pConfig->pEnableVideoPortCCIR656[i/2] = (UInt8)(pConfig->pEnableVideoPortCCIR656[i/2] | 0xF0); ++ pConfig->pGroundVideoPortCCIR656[i/2] &= 0x0F; ++ } ++ } ++ ++ /* YUV422 */ ++ if (videoPortMapping_YUV422[unit][i] != TMDL_HDMITX_VID422_NOT_CONNECTED) ++ { ++ pConfig->pSwapTableYUV422[videoPortMapping_YUV422[unit][i] & 0x07F] = 5-i; ++ pConfig->pMirrorTableYUV422[videoPortMapping_YUV422[unit][i] & 0x07F] = (UInt8)(videoPortMapping_YUV422[unit][i] >> 7); ++ /* Enable port and disable ground port */ ++ if (((5-i) % 2) == 0) ++ { ++ pConfig->pEnableVideoPortYUV422[i/2] |= 0x0F; ++ pConfig->pGroundVideoPortYUV422[i/2] = (UInt8)(pConfig->pGroundVideoPortYUV422[i/2] & 0xF0); ++ } ++ else ++ { ++ pConfig->pEnableVideoPortYUV422[i/2] = (UInt8)(pConfig->pEnableVideoPortYUV422[i/2] | 0xF0); ++ pConfig->pGroundVideoPortYUV422[i/2] &= 0x0F; ++ } ++ } ++ ++ /* YUV444 */ ++ if (videoPortMapping_YUV444[unit][i] != TMDL_HDMITX_VID444_NOT_CONNECTED) ++ { ++ pConfig->pSwapTableYUV444[videoPortMapping_YUV444[unit][i] & 0x07F] = 5-i; ++ pConfig->pMirrorTableYUV444[videoPortMapping_YUV444[unit][i] & 0x07F] = (UInt8)(videoPortMapping_YUV444[unit][i] >> 7); ++ /* Enable port and disable ground port */ ++ if (((5-i) % 2) == 0) ++ { ++ pConfig->pEnableVideoPortYUV444[i/2] |= 0x0F; ++ pConfig->pGroundVideoPortYUV444[i/2] = (UInt8)(pConfig->pGroundVideoPortYUV444[i/2] & 0xF0); ++ } ++ else ++ { ++ pConfig->pEnableVideoPortYUV444[i/2] = (UInt8)(pConfig->pEnableVideoPortYUV444[i/2] | 0xF0); ++ pConfig->pGroundVideoPortYUV444[i/2] &= 0x0F; ++ } ++ } ++ ++ /* RGB444 */ ++ if (videoPortMapping_RGB444[unit][i] != TMDL_HDMITX_VID444_NOT_CONNECTED) ++ { ++ pConfig->pSwapTableRGB444[videoPortMapping_RGB444[unit][i] & 0x07F] = 5-i; ++ pConfig->pMirrorTableRGB444[videoPortMapping_RGB444[unit][i] & 0x07F] = (UInt8)(videoPortMapping_RGB444[unit][i] >> 7); ++ /* Enable port and disable ground port */ ++ if (((5-i) % 2) == 0) ++ { ++ pConfig->pEnableVideoPortRGB444[i/2] |= 0x0F; ++ pConfig->pGroundVideoPortRGB444[i/2] = (UInt8)(pConfig->pGroundVideoPortRGB444[i/2] & 0xF0); ++ } ++ else ++ { ++ pConfig->pEnableVideoPortRGB444[i/2] = (UInt8)(pConfig->pEnableVideoPortRGB444[i/2] | 0xF0); ++ pConfig->pGroundVideoPortRGB444[i/2] &= 0x0F; ++ } ++ } ++ ++ ++#ifdef TMFL_RGB_DDR_12BITS ++ /* RGB DDR 12bits */ ++ if (VideoPortMapping_RGB_DDR_12bits[unit][i] != TMDL_HDMITX_VID_DDR_NOT_CONNECTED) ++ { ++ pConfig->pSwapTableRGB_DDR_12bits[VideoPortMapping_RGB_DDR_12bits[unit][i] & 0x07F] = 5-i; ++ pConfig->pMirrorTableRGB_DDR_12bits[VideoPortMapping_RGB_DDR_12bits[unit][i] & 0x07F] = (UInt8)(VideoPortMapping_RGB_DDR_12bits[unit][i] >> 7); ++ /* Enable port and disable ground port */ ++ if (((5-i) % 2) == 0) ++ { ++ pConfig->pEnableVideoPortRGB_DDR_12bits[i/2] |= 0x0F; ++ pConfig->pGroundVideoPortRGB_DDR_12bits[i/2] = (UInt8)(pConfig->pGroundVideoPortRGB_DDR_12bits[i/2] & 0xF0); ++ } ++ else ++ { ++ pConfig->pEnableVideoPortRGB_DDR_12bits[i/2] = (UInt8)(pConfig->pEnableVideoPortRGB_DDR_12bits[i/2] | 0xF0); ++ pConfig->pGroundVideoPortRGB_DDR_12bits[i/2] &= 0x0F; ++ } ++ } ++#endif ++ } ++ ++#ifdef TMFL_RGB_DDR_12BITS ++ /* VIP internal mux for RGB DDR */ ++ pConfig->pNoMux = (UInt8*)&VideoPortNoMux[unit]; ++ pConfig->pMux_RGB_DDR_12bits = (UInt8*)&VideoPortMux_RGB_DDR_12bits[unit]; ++#endif ++ ++} ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.h b/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.h +new file mode 100755 +index 0000000..ccda7bf +--- /dev/null ++++ b/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.h +@@ -0,0 +1,702 @@ ++/** ++ * Copyright (C) 2006 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * \file tmdlHdmiTx_local.h ++ * ++ * \version $Revision: 1 $ ++ * ++ * \date $Date: 02/08/07 08:32 $ ++ * ++ * \brief devlib driver component API for the TDA998x HDMI Transmitters ++ * ++ * \section refs Reference Documents ++ * HDMI Tx Driver - FRS.doc, ++ * ++ * \section info Change Information ++ * ++ * \verbatim ++ ++ $History: tmdlHdmiTx_local.h $ ++ * ++ * ***************** Version 13 ***************** ++ * User: J. Lamotte Date: 02/08/07 Time: 08:32 ++ * Updated in $/Source/tmdlHdmiTx/inc ++ * initial version ++ * ++ ++ \endverbatim ++ * ++*/ ++ ++#ifndef TMDLHDMITX_LOCAL_H ++#define TMDLHDMITX_LOCAL_H ++ ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++#include ++#endif ++ ++#include "tmdlHdmiTx_IW.h" ++#include "tmNxTypes.h" ++#include "tmdlHdmiTx_Types.h" ++#include "tmdlHdmiTx_cfg.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*============================================================================*/ ++/* MACRO DEFINITIONS */ ++/*============================================================================*/ ++ ++/* Version of the SW driver */ ++#define VERSION_COMPATIBILITY 0 ++#define VERSION_MAJOR 5 ++#define VERSION_MINOR 3 ++ ++/* Invalid HDCP seed */ ++#define HDCP_SEED_NULL 0 ++ ++/* A default seed value may be defined here, or set to HDCP_SEED_NULL. ++ * If HDCP_SEED_NULL, a table of seeds may instead be programmed separately ++ * into flash at the location of kSeedTable, below */ ++#define HDCP_SEED_DEFAULT HDCP_SEED_NULL ++ ++/* Default SHA-1 test handling */ ++#define HDCP_OPT_DEFAULT ( TMDL_HDMITX_HDCP_OPTION_FORCE_PJ_IGNORED \ ++ | TMDL_HDMITX_HDCP_OPTION_FORCE_VSLOW_DDC \ ++ | TMDL_HDMITX_HDCP_OPTION_FORCE_NO_1_1 ) ++ ++/** ++ * A macro to check a condition and if true return a result ++ */ ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++#define RETIF(cond, rslt) if ((cond)){ \ ++ printk(KERN_INFO "%s %d\n",__func__,__LINE__); \ ++ return (rslt);} ++#else ++#define RETIF(cond, rslt) if ((cond)){return (rslt);} ++#endif ++ ++/** ++ * A macro to check a condition and if true return ++ * TMDL_ERR_DLHDMITX_BAD_PARAMETER. ++ * To save code space, it can be compiled out by defining NO_RETIF_BADPARAM on ++ * the compiler command line. ++ */ ++#ifdef NO_RETIF_BADPARAM ++#define RETIF_BADPARAM(cond) ++#else ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++#define RETIF_BADPARAM(cond) if ((cond)){ \ ++ printk(KERN_INFO "%s %d\n",__func__,__LINE__); \ ++ return TMDL_ERR_DLHDMITX_BAD_PARAMETER;} ++#else ++#define RETIF_BADPARAM(cond) if ((cond)){return TMDL_ERR_DLHDMITX_BAD_PARAMETER;} ++#endif ++#endif ++ ++/** ++ * A macro to check a condition and if true, release the semaphore describe by handle and return a result ++ */ ++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER ++#define RETIF_SEM(handle, cond, rslt) if ((cond)){ \ ++ tmdlHdmiTxIWSemaphoreV(handle); \ ++ printk(KERN_INFO "%s %d\n",__func__,__LINE__); \ ++ return (rslt);} ++#else ++#define RETIF_SEM(handle, cond, rslt) if ((cond)){tmdlHdmiTxIWSemaphoreV(handle); return (rslt);} ++#endif ++ ++ /* Resolution supported */ ++#ifndef FORMAT_PC ++#define RESOLUTION_NB 41 ++#else ++#define RESOLUTION_NB 68 ++#endif /* FORMAT_PC */ ++ ++/* Instance number */ ++#define INSTANCE_0 0 ++#define INSTANCE_1 1 ++ ++#ifdef HDMI_TX_REPEATER_ISR_MODE ++/* Number of event */ ++#define EVENT_NB 10 ++#else /* HDMI_TX_REPEATER_ISR_MODE */ ++/* Number of event */ ++#define EVENT_NB 9 ++#endif /* HDMI_TX_REPEATER_ISR_MODE */ ++ ++/* Size of a KSV is five bytes */ ++#define KSV_SIZE 5 ++ ++/* Arbitrary short TV format values */ ++#define TV_INVALID 0 ++#define TV_VGA_60Hz 1 ++#define TV_240p_60Hz 2 ++#define TV_480p_60Hz 3 ++#define TV_480i_60Hz 4 ++#define TV_720p_60Hz 5 ++#define TV_1080p_60Hz 6 ++#define TV_1080i_60Hz 7 ++#define TV_288p_50Hz 8 ++#define TV_576p_50Hz 9 ++#define TV_576i_50Hz 10 ++#define TV_720p_50Hz 11 ++#define TV_1080p_50Hz 12 ++#define TV_1080i_50Hz 13 ++ ++/* Shorthands for vinMode values in tmbslTDA9984.h */ ++#define iINVALID TMDL_HDMITX_VINMODE_INVALID ++#define iCCIR656 TMDL_HDMITX_VINMODE_CCIR656 ++#define iRGB444 TMDL_HDMITX_VINMODE_RGB444 ++#define iYUV444 TMDL_HDMITX_VINMODE_YUV444 ++#define iYUV422 TMDL_HDMITX_VINMODE_YUV422 ++ ++/* Shorthands for input sync */ ++#define EMB 1 ++#define EXT 0 ++ ++/* Shorthands for single/double pixel rate in tmbslTDA9984.h */ ++#define SINGLE TMDL_HDMITX_PIXRATE_SINGLE ++#define DOUBLE TMDL_HDMITX_PIXRATE_DOUBLE ++ ++/* Shorthands for sampling frequency in tmdlHdmiTxSetAudioInput API */ ++#define AIF_SF_REFER_TO_STREAM_HEADER 0 ++#define AIF_SF_32K 1 ++#define AIF_SF_44K 2 ++#define AIF_SF_48K 3 ++#define AIF_SF_88K 4 ++#define AIF_SF_96K 5 ++#define AIF_SF_176K 6 ++#define AIF_SF_192K 7 ++ ++/* HDCP check interval in milliseconds */ ++#define HDCP_CHECK_INTERVAL_MS 2500 ++ ++/* Number of HDCP checks to carry out after HDCP is started */ ++#define HDCP_NUM_CHECKS 5 ++ ++#define TMDL_HDMITX_CHANNELALLOC_LUT_SIZE 32 ++ ++ ++static CONST_DAT UInt8 kChanAllocChanNum[TMDL_HDMITX_CHANNELALLOC_LUT_SIZE] = \ ++{2,3,3,4,3,4,4,5,4,5,5,6,5,6,6,7,6,7,7,8,4,5,5,6,5,6,6,7,6,7,7,8 }; ++ ++ ++/** ++ * Lookup table to convert from EIA/CEA TV video format to ++ * aspect ratio used in video infoframe: ++ * Aspect ratio 1=4:3, 2=16:9 ++ */ ++#ifndef FORMAT_PC ++static CONST_DAT UInt8 kVfmtToAspect_TV[TMDL_HDMITX_VFMT_TV_NUM] = ++#else /* FORMAT_PC */ ++static CONST_DAT UInt8 kVfmtToAspect_TV[TMDL_HDMITX_VFMT_TV_NUM + TMDL_HDMITX_VFMT_PC_NUM] = ++#endif /* FORMAT_PC */ ++{ ++ 0, /* HDMITX_VFMT_NULL */ ++ 1, /* HDMITX_VFMT_01_640x480p_60Hz */ ++ 1, /* HDMITX_VFMT_02_720x480p_60Hz */ ++ 2, /* HDMITX_VFMT_03_720x480p_60Hz */ ++ 2, /* HDMITX_VFMT_04_1280x720p_60Hz */ ++ 2, /* HDMITX_VFMT_05_1920x1080i_60Hz */ ++ 1, /* HDMITX_VFMT_06_720x480i_60Hz */ ++ 2, /* HDMITX_VFMT_07_720x480i_60Hz */ ++ 1, /* HDMITX_VFMT_08_720x240p_60Hz */ ++ 2, /* HDMITX_VFMT_09_720x240p_60Hz */ ++ 1, /* HDMITX_VFMT_10_720x480i_60Hz */ ++ 2, /* HDMITX_VFMT_11_720x480i_60Hz */ ++ 1, /* HDMITX_VFMT_12_720x240p_60Hz */ ++ 2, /* HDMITX_VFMT_13_720x240p_60Hz */ ++ 1, /* HDMITX_VFMT_14_1440x480p_60Hz */ ++ 2, /* HDMITX_VFMT_15_1440x480p_60Hz */ ++ 2, /* HDMITX_VFMT_16_1920x1080p_60Hz */ ++ 1, /* HDMITX_VFMT_17_720x576p_50Hz */ ++ 2, /* HDMITX_VFMT_18_720x576p_50Hz */ ++ 2, /* HDMITX_VFMT_19_1280x720p_50Hz */ ++ 2, /* HDMITX_VFMT_20_1920x1080i_50Hz */ ++ 1, /* HDMITX_VFMT_21_720x576i_50Hz */ ++ 2, /* HDMITX_VFMT_22_720x576i_50Hz */ ++ 1, /* HDMITX_VFMT_23_720x288p_50Hz */ ++ 2, /* HDMITX_VFMT_24_720x288p_50Hz */ ++ 1, /* HDMITX_VFMT_25_720x576i_50Hz */ ++ 2, /* HDMITX_VFMT_26_720x576i_50Hz */ ++ 1, /* HDMITX_VFMT_27_720x288p_50Hz */ ++ 2, /* HDMITX_VFMT_28_720x288p_50Hz */ ++ 1, /* HDMITX_VFMT_29_1440x576p_50Hz */ ++ 2, /* HDMITX_VFMT_30_1440x576p_50Hz */ ++ 2, /* HDMITX_VFMT_31_1920x1080p_50Hz */ ++ 2, /* HDMITX_VFMT_32_1920x1080p_24Hz */ ++ 2, /* HDMITX_VFMT_33_1920x1080p_25Hz */ ++ 2, /* HDMITX_VFMT_34_1920x1080p_30Hz */ ++ ++ 1, /* TMDL_HDMITX_VFMT_35_2880x480p_60Hz */ ++ 2, /* TMDL_HDMITX_VFMT_36_2880x480p_60Hz */ ++ 1, /* TMDL_HDMITX_VFMT_37_2880x576p_50Hz */ ++ 2, /* TMDL_HDMITX_VFMT_38_2880x576p_50Hz */ ++ ++ 2, /* TMDL_HDMITX_VFMT_60_1280x720p_24HZ */ ++ 2, /* TMDL_HDMITX_VFMT_61_1280_720p_25HZ */ ++ 2 /* TMDL_HDMITX_VFMT_62_1280_720p_30HZ */ ++ ++#ifdef FORMAT_PC ++ ,1, /* HDMITX_VFMT_PC_640x480p_60Hz */ ++ 1, /* HDMITX_VFMT_PC_800x600p_60Hz */ ++ 1, /* HDMITX_VFMT_PC_1152x960p_60Hz */ ++ 1, /* HDMITX_VFMT_PC_1024x768p_60Hz */ ++ 1, /* HDMITX_VFMT_PC_1280x768p_60Hz */ ++ 1, /* HDMITX_VFMT_PC_1280x1024p_60Hz */ ++ 1, /* HDMITX_VFMT_PC_1360x768p_60Hz */ ++ 1, /* HDMITX_VFMT_PC_1400x1050p_60Hz */ ++ 1, /* HDMITX_VFMT_PC_1600x1200p_60Hz */ ++ 1, /* HDMITX_VFMT_PC_1024x768p_70Hz */ ++ 1, /* HDMITX_VFMT_PC_640x480p_72Hz */ ++ 1, /* HDMITX_VFMT_PC_800x600p_72Hz */ ++ 1, /* HDMITX_VFMT_PC_640x480p_75Hz */ ++ 1, /* HDMITX_VFMT_PC_1024x768p_75Hz */ ++ 1, /* HDMITX_VFMT_PC_800x600p_75Hz */ ++ 1, /* HDMITX_VFMT_PC_1024x864p_75Hz */ ++ 1, /* HDMITX_VFMT_PC_1280x1024p_75Hz */ ++ 1, /* HDMITX_VFMT_PC_640x350p_85Hz */ ++ 1, /* HDMITX_VFMT_PC_640x400p_85Hz */ ++ 1, /* HDMITX_VFMT_PC_720x400p_85Hz */ ++ 1, /* HDMITX_VFMT_PC_640x480p_85Hz */ ++ 1, /* HDMITX_VFMT_PC_800x600p_85Hz */ ++ 1, /* HDMITX_VFMT_PC_1024x768p_85Hz */ ++ 1, /* HDMITX_VFMT_PC_1152x864p_85Hz */ ++ 1, /* HDMITX_VFMT_PC_1280x960p_85Hz */ ++ 1, /* HDMITX_VFMT_PC_1280x1024p_85Hz */ ++ 1 /* HDMITX_VFMT_PC_1024x768i_87Hz */ ++#endif /* FORMAT_PC */ ++}; ++ ++/** ++ * Lookup table to convert from EIA/CEA TV video format to ++ * the short format of resolution/interlace/frequency ++ */ ++static CONST_DAT UInt8 kVfmtToShortFmt_TV[TMDL_HDMITX_VFMT_TV_NUM] = ++{ ++ TV_INVALID, /* HDMITX_VFMT_NULL */ ++ TV_VGA_60Hz, /* HDMITX_VFMT_01_640x480p_60Hz */ ++ TV_480p_60Hz, /* HDMITX_VFMT_02_720x480p_60Hz */ ++ TV_480p_60Hz, /* HDMITX_VFMT_03_720x480p_60Hz */ ++ TV_720p_60Hz, /* HDMITX_VFMT_04_1280x720p_60Hz */ ++ TV_1080i_60Hz, /* HDMITX_VFMT_05_1920x1080i_60Hz */ ++ TV_480i_60Hz, /* HDMITX_VFMT_06_720x480i_60Hz */ ++ TV_480i_60Hz, /* HDMITX_VFMT_07_720x480i_60Hz */ ++ TV_240p_60Hz, /* HDMITX_VFMT_08_720x240p_60Hz */ ++ TV_240p_60Hz, /* HDMITX_VFMT_09_720x240p_60Hz */ ++ TV_480i_60Hz, /* HDMITX_VFMT_10_720x480i_60Hz */ ++ TV_480i_60Hz, /* HDMITX_VFMT_11_720x480i_60Hz */ ++ TV_240p_60Hz, /* HDMITX_VFMT_12_720x240p_60Hz */ ++ TV_240p_60Hz, /* HDMITX_VFMT_13_720x240p_60Hz */ ++ TV_480p_60Hz, /* HDMITX_VFMT_14_1440x480p_60Hz */ ++ TV_480p_60Hz, /* HDMITX_VFMT_15_1440x480p_60Hz */ ++ TV_1080p_60Hz, /* HDMITX_VFMT_16_1920x1080p_60Hz */ ++ TV_576p_50Hz, /* HDMITX_VFMT_17_720x576p_50Hz */ ++ TV_576p_50Hz, /* HDMITX_VFMT_18_720x576p_50Hz */ ++ TV_720p_50Hz, /* HDMITX_VFMT_19_1280x720p_50Hz */ ++ TV_1080i_50Hz, /* HDMITX_VFMT_20_1920x1080i_50Hz */ ++ TV_576i_50Hz, /* HDMITX_VFMT_21_720x576i_50Hz */ ++ TV_576i_50Hz, /* HDMITX_VFMT_22_720x576i_50Hz */ ++ TV_288p_50Hz, /* HDMITX_VFMT_23_720x288p_50Hz */ ++ TV_288p_50Hz, /* HDMITX_VFMT_24_720x288p_50Hz */ ++ TV_576i_50Hz, /* HDMITX_VFMT_25_720x576i_50Hz */ ++ TV_576i_50Hz, /* HDMITX_VFMT_26_720x576i_50Hz */ ++ TV_288p_50Hz, /* HDMITX_VFMT_27_720x288p_50Hz */ ++ TV_288p_50Hz, /* HDMITX_VFMT_28_720x288p_50Hz */ ++ TV_576p_50Hz, /* HDMITX_VFMT_29_1440x576p_50Hz */ ++ TV_576p_50Hz, /* HDMITX_VFMT_30_1440x576p_50Hz */ ++ TV_1080p_50Hz, /* HDMITX_VFMT_31_1920x1080p_50Hz */ ++ TV_INVALID, /* HDMITX_VFMT_NULL */ ++ TV_INVALID, /* HDMITX_VFMT_NULL */ ++ TV_INVALID, /* HDMITX_VFMT_NULL */ ++ TV_480p_60Hz, /* HDMITX_VFMT_35_2880x480p_60Hz */ ++ TV_480p_60Hz, /* HDMITX_VFMT_36_2880x480p_60Hz */ ++ TV_576p_50Hz, /* HDMITX_VFMT_37_2880x576p_50Hz */ ++ TV_576p_50Hz, /* HDMITX_VFMT_38_2880x576p_50Hz */ ++ TV_INVALID, /* HDMITX_VFMT_NULL */ ++ TV_INVALID, /* HDMITX_VFMT_NULL */ ++ TV_INVALID /* HDMITX_VFMT_NULL */ ++}; ++ ++/** ++ * Macro to pack vinMode(0-5), pixRate(0-1), syncIn(0-1) and bVerified(0-1) ++ * into a byte ++ */ ++#define PKBYTE(mode,rate,sync,verf) (((rate)<<7)|((sync)<<6)|((verf)<<5)|((mode)&0x1F)) ++ ++/** ++ * Macros to unpack vinMode(0-5), pixRate(0-1), syncIn(0-1) and bVerified(0-1) ++ * from a byte ++ */ ++#define UNPKRATE(byte) (((byte)>>7)&1) ++#define UNPKSYNC(byte) (((byte)>>6)&1) ++#define UNPKVERF(byte) (((byte)>>5)&1) ++#define UNPKMODE(byte) ((byte)&0x1F) ++ ++/** ++ * Lookup table to match main video settings and look up sets of ++ * Refpix and Refline values ++ */ ++static CONST_DAT struct ++{ ++ /* Values to match */ ++ UInt8 modeRateSyncVerf; /* Packed vinMode, pixRate, syncIn, bVerified */ ++ UInt8 shortVinFmt; ++ UInt8 shortVoutFmt; ++ /* Values to look up */ ++ UInt16 refPix; /* Output values */ ++ UInt16 refLine; ++ UInt16 scRefPix; /* Scaler values */ ++ UInt16 scRefLine; ++} kRefpixRefline [] = ++{ ++ /*************************************************************/ ++ /** Rows formatted in "Refpix_Refline.xls" and pasted here **/ ++ /** DO NOT DELETE ANY ROWS, to keep all scaler combinations **/ ++ /*************************************************************/ ++ /* mode_____Rate___Sync_Verf shortVinFmt shortVoutFmt refPix refLine scRefPix scRefLine Test ID */ ++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_480i_60Hz, TV_480p_60Hz, 0x08b, 0x024, 0x078, 0x017}, /* VID_F_04 */ ++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_480i_60Hz, TV_720p_60Hz, 0x08b, 0x012, 0x078, 0x017}, /* VID_F_04 */ ++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_480i_60Hz, TV_1080i_60Hz, 0x08b, 0x00e, 0x078, 0x017}, /* VID_F_04 */ ++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_480i_60Hz, TV_1080p_60Hz, 0x08b, 0x021, 0x078, 0x017}, /* */ ++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_480p_60Hz, TV_720p_60Hz, 0x08b, 0x017, 0x078, 0x02c}, /* VID_F_01 */ ++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_480p_60Hz, TV_1080i_60Hz, 0x08b, 0x013, 0x078, 0x02c}, /* VID_F_01 */ ++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_480p_60Hz, TV_1080p_60Hz, 0x08b, 0x027, 0x07A, 0x02c}, /* */ ++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_576i_50Hz, TV_576p_50Hz, 0x091, 0x026, 0x085, 0x018}, /* VID_F_09 */ ++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_576i_50Hz, TV_720p_50Hz, 0x091, 0x013, 0x085, 0x018}, /* VID_F_09 */ ++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_576i_50Hz, TV_1080i_50Hz, 0x091, 0x00f, 0x085, 0x018}, /* VID_F_09 */ ++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_576i_50Hz, TV_1080p_50Hz, 0x091, 0x022, 0x085, 0x018}, /* */ ++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_576p_50Hz, TV_720p_50Hz, 0x091, 0x019, 0x085, 0x02e}, /* VID_F_06 */ ++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_576p_50Hz, TV_1080i_50Hz, 0x091, 0x014, 0x085, 0x02e}, /* VID_F_06 */ ++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_576p_50Hz, TV_1080p_50Hz, 0x091, 0x028, 0x087, 0x02e}, /* */ ++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_480i_60Hz, TV_480p_60Hz, 0x014, 0x20d, 0x359, 0x004}, /* VID_F_04 */ ++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_480i_60Hz, TV_720p_60Hz, 0x014, 0x2cb, 0x359, 0x004}, /* VID_F_04 */ ++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_480i_60Hz, TV_1080i_60Hz, 0x014, 0x44c, 0x359, 0x004}, /* VID_F_04 */ ++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_480i_60Hz, TV_1080p_60Hz, 0x014, 0x436, 0x359, 0x004}, /* */ ++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_480p_60Hz, TV_720p_60Hz, 0x011, 0x2d3, 0x358, 0x007}, /* VID_F_01 */ ++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_480p_60Hz, TV_1080i_60Hz, 0x011, 0x452, 0x358, 0x007}, /* VID_F_01 */ ++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_480p_60Hz, TV_1080p_60Hz, 0x011, 0x43e, 0x358, 0x007}, /* */ ++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_576i_50Hz, TV_576p_50Hz, 0x00d, 0x26b, 0x35f, 0x001}, /* VID_F_09 */ ++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_576i_50Hz, TV_720p_50Hz, 0x00d, 0x2cb, 0x35f, 0x001}, /* VID_F_09 */ ++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_576i_50Hz, TV_1080i_50Hz, 0x00d, 0x44b, 0x35f, 0x001}, /* VID_F_09 */ ++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_576i_50Hz, TV_1080p_50Hz, 0x00d, 0x435, 0x35f, 0x001}, /* */ ++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_576p_50Hz, TV_720p_50Hz, 0x00d, 0x2d1, 0x35f, 0x001}, /* VID_F_06 */ ++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_576p_50Hz, TV_1080i_50Hz, 0x00d, 0x451, 0x35f, 0x001}, /* VID_F_06 */ ++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_576p_50Hz, TV_1080p_50Hz, 0x00d, 0x43d, 0x35f, 0x001}, /* */ ++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_480i_60Hz, TV_480p_60Hz, 0x08b, 0x024, 0x078, 0x017}, /* VID_F_04 */ ++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_480i_60Hz, TV_720p_60Hz, 0x08b, 0x012, 0x078, 0x017}, /* VID_F_04 */ ++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_480i_60Hz, TV_1080i_60Hz, 0x08b, 0x00e, 0x078, 0x017}, /* VID_F_04 */ ++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_480i_60Hz, TV_1080p_60Hz, 0x08b, 0x021, 0x078, 0x017}, /* */ ++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_480p_60Hz, TV_720p_60Hz, 0x08b, 0x017, 0x078, 0x02c}, /* VID_F_01 */ ++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_480p_60Hz, TV_1080i_60Hz, 0x08b, 0x013, 0x078, 0x02c}, /* VID_F_01 */ ++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_480p_60Hz, TV_1080p_60Hz, 0x08b, 0x027, 0x07A, 0x02c}, /* */ ++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_576i_50Hz, TV_576p_50Hz, 0x091, 0x026, 0x085, 0x018}, /* VID_F_09 */ ++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_576i_50Hz, TV_720p_50Hz, 0x091, 0x013, 0x085, 0x018}, /* VID_F_09 */ ++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_576i_50Hz, TV_1080i_50Hz, 0x091, 0x00f, 0x085, 0x018}, /* VID_F_09 */ ++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_576i_50Hz, TV_1080p_50Hz, 0x091, 0x022, 0x085, 0x018}, /* */ ++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_576p_50Hz, TV_720p_50Hz, 0x091, 0x019, 0x085, 0x02e}, /* VID_F_06 */ ++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_576p_50Hz, TV_1080i_50Hz, 0x091, 0x014, 0x085, 0x02e}, /* VID_F_06 */ ++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_576p_50Hz, TV_1080p_50Hz, 0x091, 0x028, 0x087, 0x02e}, /* */ ++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_480i_60Hz, TV_480p_60Hz, 0x014, 0x20d, 0x359, 0x004}, /* VID_F_04 */ ++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_480i_60Hz, TV_720p_60Hz, 0x014, 0x2cb, 0x359, 0x004}, /* VID_F_04 */ ++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_480i_60Hz, TV_1080i_60Hz, 0x014, 0x44c, 0x359, 0x004}, /* VID_F_04 */ ++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_480i_60Hz, TV_1080p_60Hz, 0x014, 0x436, 0x359, 0x004}, /* */ ++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_480p_60Hz, TV_720p_60Hz, 0x011, 0x2d3, 0x358, 0x007}, /* VID_F_01 */ ++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_480p_60Hz, TV_1080i_60Hz, 0x011, 0x452, 0x358, 0x007}, /* VID_F_01 */ ++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_480p_60Hz, TV_1080p_60Hz, 0x011, 0x43e, 0x358, 0x007}, /* */ ++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_576i_50Hz, TV_576p_50Hz, 0x00d, 0x26b, 0x35f, 0x001}, /* VID_F_09 */ ++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_576i_50Hz, TV_720p_50Hz, 0x00d, 0x2cb, 0x35f, 0x001}, /* VID_F_09 */ ++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_576i_50Hz, TV_1080i_50Hz, 0x00d, 0x44b, 0x35f, 0x001}, /* VID_F_09 */ ++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_576i_50Hz, TV_1080p_50Hz, 0x00d, 0x435, 0x35f, 0x001}, /* */ ++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_576p_50Hz, TV_720p_50Hz, 0x00d, 0x2d1, 0x35f, 0x001}, /* VID_F_06 */ ++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_576p_50Hz, TV_1080i_50Hz, 0x00d, 0x451, 0x35f, 0x001}, /* VID_F_06 */ ++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_576p_50Hz, TV_1080p_50Hz, 0x00d, 0x43d, 0x35f, 0x001}, /* */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_480i_60Hz, TV_480p_60Hz, 0x08d, 0x028, 0x078, 0x017}, /* VID_F_04 */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_480i_60Hz, TV_720p_60Hz, 0x08d, 0x014, 0x078, 0x017}, /* VID_F_04 */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_480i_60Hz, TV_1080i_60Hz, 0x08d, 0x010, 0x078, 0x017}, /* VID_F_04 */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_480i_60Hz, TV_1080p_60Hz, 0x08d, 0x021, 0x078, 0x017}, /* */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_480p_60Hz, TV_720p_60Hz, 0x08d, 0x017, 0x078, 0x02c}, /* VID_F_01 */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_480p_60Hz, TV_1080i_60Hz, 0x08d, 0x014, 0x078, 0x02c}, /* VID_F_01 */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_480p_60Hz, TV_1080p_60Hz, 0x08d, 0x027, 0x07C, 0x02c}, /* */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_576i_50Hz, TV_576p_50Hz, 0x093, 0x02a, 0x085, 0x018}, /* VID_F_09 */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_576i_50Hz, TV_720p_50Hz, 0x093, 0x013, 0x085, 0x018}, /* VID_F_09 */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_576i_50Hz, TV_1080i_50Hz, 0x093, 0x00e, 0x085, 0x018}, /* VID_F_09 */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_576i_50Hz, TV_1080p_50Hz, 0x093, 0x022, 0x085, 0x018}, /* */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_576p_50Hz, TV_720p_50Hz, 0x093, 0x019, 0x085, 0x02e}, /* VID_F_06 */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_576p_50Hz, TV_1080i_50Hz, 0x093, 0x014, 0x085, 0x02e}, /* VID_F_06 */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_576p_50Hz, TV_1080p_50Hz, 0x093, 0x028, 0x089, 0x02e}, /* */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_720p_50Hz, TV_1080p_50Hz, 0x2bf, 0x024, 0x105, 0x019}, /* */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_720p_60Hz, TV_1080p_60Hz, 0x175, 0x024, 0x105, 0x019}, /* */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_1080i_50Hz, TV_1080p_50Hz, 0x2d3, 0x023, 0x0c3, 0x014}, /* */ ++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_1080i_60Hz, TV_1080p_60Hz, 0x11b, 0x023, 0x0c3, 0x014}, /* */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_480i_60Hz, TV_480p_60Hz, 0x016, 0x20d, 0x359, 0x004}, /* VID_F_04 */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_480i_60Hz, TV_720p_60Hz, 0x016, 0x2cb, 0x359, 0x004}, /* VID_F_04 */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_480i_60Hz, TV_1080i_60Hz, 0x016, 0x44c, 0x359, 0x004}, /* VID_F_04 */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_480i_60Hz, TV_1080p_60Hz, 0x016, 0x436, 0x359, 0x004}, /* */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_480p_60Hz, TV_720p_60Hz, 0x013, 0x2d3, 0x358, 0x007}, /* VID_F_01 */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_480p_60Hz, TV_1080i_60Hz, 0x013, 0x452, 0x358, 0x007}, /* VID_F_01 */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_480p_60Hz, TV_1080p_60Hz, 0x013, 0x43e, 0x358, 0x007}, /* */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_576i_50Hz, TV_576p_50Hz, 0x00f, 0x26b, 0x35f, 0x001}, /* VID_F_09 */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_576i_50Hz, TV_720p_50Hz, 0x00f, 0x2cb, 0x35f, 0x001}, /* VID_F_09 */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_576i_50Hz, TV_1080i_50Hz, 0x00f, 0x44b, 0x35f, 0x001}, /* VID_F_09 */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_576i_50Hz, TV_1080p_50Hz, 0x00f, 0x435, 0x35f, 0x001}, /* */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_576p_50Hz, TV_720p_50Hz, 0x00f, 0x2d1, 0x35f, 0x001}, /* VID_F_06 */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_576p_50Hz, TV_1080i_50Hz, 0x00f, 0x451, 0x35f, 0x001}, /* VID_F_06 */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_576p_50Hz, TV_1080p_50Hz, 0x00f, 0x43d, 0x35f, 0x001}, /* */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_720p_50Hz, TV_1080p_50Hz, 0x1bb, 0x463, 0x7bb, 0x000}, /* */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_720p_60Hz, TV_1080p_60Hz, 0x071, 0x463, 0x671, 0x000}, /* */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_1080i_50Hz, TV_1080p_50Hz, 0x213, 0x460, 0xa4f, 0x000}, /* */ ++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_1080i_60Hz, TV_1080p_60Hz, 0x05b, 0x460, 0x897, 0x000}, /* */ ++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_480p_60Hz, TV_VGA_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */ ++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */ ++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */ ++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */ ++ {PKBYTE(iINVALID,DOUBLE,EMB, 0), TV_INVALID, TV_INVALID, 0x000, 0x000, 0x000, 0x000} /* EndTable */ ++}; ++ ++ ++/*============================================================================*/ ++/* ENUM OR TYPE DEFINITIONS */ ++/*============================================================================*/ ++/* Enum listing all the type of colorimetry */ ++typedef enum ++{ ++ TMDL_HDMITX_COLORIMETRY_NO_DATA = 0, ++ TMDL_HDMITX_COLORIMETRY_ITU601 = 1, ++ TMDL_HDMITX_COLORIMETRY_ITU709 = 2, ++ TMDL_HDMITX_COLORIMETRY_EXTENDED = 3 ++} tmdlHdmiTxColorimetry_t; ++ ++/* Possible states of the state machine */ ++typedef enum ++{ ++ STATE_NOT_INITIALIZED, /**< Driver is not initialized */ ++ STATE_INITIALIZED, /**< Driver is initialized */ ++ STATE_UNPLUGGED, /**< Receiver device not connected */ ++ STATE_PLUGGED, /**< Receiver device connected, clock lock */ ++ STATE_EDID_AVAILABLE /**< Managed to read receiver's EDID */ ++} tmdlHdmiTxDriverState_t; ++ ++/* revocation list structure */ ++typedef struct ++{ ++ UInt8* pList; ++ UInt32 length; ++} revocationList_t; ++ ++ ++/* unit configuration structure */ ++typedef struct ++{ ++ Bool opened; /**< Is unit instanciated ? */ ++ Bool hdcpEnable; /**< Is HDCP enabled ? */ ++ tmdlHdmiTxHdcpOptions_t hdcpOptions; /**< HDCP options */ ++ Bool repeaterEnable; /**< Is repeater enabled ? */ ++ Bool simplayHd; /**< Enable simplayHD support */ ++ tmdlHdmiTxDeviceVersion_t deviceVersion; /**< Version of the HW device */ ++ UInt8 *pEdidBuffer; /**< Pointer to raw EDID data */ ++ UInt32 edidBufferSize; /**< Size of buffer for raw EDID data */ ++ tmdlHdmiTxIWTaskHandle_t commandTaskHandle; /**< Handle of the command task associated to this unit */ ++ tmdlHdmiTxIWQueueHandle_t queueHandle; /**< Handle of the message queue associated to this unit */ ++ tmdlHdmiTxIWTaskHandle_t hdcpTaskHandle; /**< Handle of the hdcp check task associated to this unit */ ++ tmdlHdmiTxDriverState_t state; /**< Current state of the driver */ ++ ptmdlHdmiTxCallback_t pCallback; /**< Data callback */ ++ revocationList_t revocationList; /**< Revolation List */ ++} unitConfig_t; ++ ++ ++/* Instance status */ ++ ++/* Video information structure */ ++typedef struct _tmdlHdmiTxVideoInfo_t ++{ ++ Bool videoMuteState; /* Video mute state: on/off */ ++ tmdlHdmiTxVideoInConfig_t videoInConfig; /* Video input configuration */ ++ tmdlHdmiTxVideoOutConfig_t videoOutConfig; /* Video output configuration */ ++} tmdlHdmiTxVideoInfo_t, *ptmdlHdmiTxVideoInfo_t; ++ ++/* Audio information structure */ ++typedef struct _tmdlHdmiTxAudioInfo_t ++{ ++ Bool audioMuteState; /* Audio mute state: on/off */ ++ tmdlHdmiTxAudioInConfig_t audioInCfg; /* Audio input configuration */ ++} tmdlHdmiTxAudioInfo_t, *ptmdlHdmiTxAudioInfo_t; ++ ++/* Event state structure */ ++typedef struct _tmdlHdmiTxEventState_t ++{ ++ tmdlHdmiTxEvent_t event; /* Event */ ++ tmdlHdmiTxEventStatus_t status; /* Event status: enabled or disabled */ ++} tmdlHdmiTxEventState_t, *ptmdlHdmiTxEventState_t; ++ ++/* Color bars state structure */ ++typedef struct _tmdlHdmiTxColBarState_t ++{ ++ Bool disableColorBarOnR0; /* To be able to disable colorBar on R0*/ ++ Bool hdcpColbarChange; /* Used to auto-reset colour bars */ ++ Bool hdcpEncryptOrT0; /* True when ENCRYPT or T0 interrupt */ ++ Bool hdcpSecureOrT0; /* True when BKSV secure or T0 */ ++ Bool inOutFirstSetDone; /* API tmdlHdmiTxSetInputOutput call at least one time*/ ++ Bool colorBarOn; ++ Bool changeColorBarNow; ++} tmdlHdmiTxColBarState_t, *ptmdlHdmiTxColBarState_t; ++ ++/* Gamut state structure */ ++typedef struct _tmdlHdmiTxGamutState_t ++{ ++ Bool gamutOn; /* Gamut status : able or disable */ ++ UInt8 gamutBufNum; /* Numero of the buffer used for Gamut metadata (0 or 1) */ ++ tmdlHdmiTxExtColorimetry_t wideGamutColorSpace; /* Store extended colorimetry */ ++ Bool extColOn; /* extended colorimetry status : enabled or disabled */ ++ tmdlHdmiTxYCCQR_t yccQR; /* Store YCC quantisation range */ ++} tmdlHdmiTxGamutState_t, *ptmdlHdmiTxGamutState_t; ++ ++ ++/* instance status structure */ ++typedef struct ++{ ++ ptmdlHdmiTxVideoInfo_t pVideoInfo; /* Video information: current mode and format... */ ++ ptmdlHdmiTxAudioInfo_t pAudioInfo; /* Audio information: current mode and format... */ ++ ptmdlHdmiTxEventState_t pEventState; /* Event state: enabled or disabled */ ++ ptmdlHdmiTxColBarState_t pColBarState; /* Color bars state */ ++ ptmdlHdmiTxGamutState_t pGamutState; /* Gamut state */ ++} instanceStatus_t; ++ ++/*============================================================================*/ ++/* FUNCTION PROTOTYPES */ ++/*============================================================================*/ ++ ++ ++/****************************************************************************** ++ \brief This function allows to the main driver to retrieve its ++ configuration parameters. ++ ++ \param pConfig Pointer to the config structure ++ ++ \return The call result: ++ - TM_OK: the call was successful ++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or ++ the receiver instance is not initialised ++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is ++ inconsistent ++ ++******************************************************************************/ ++tmErrorCode_t dlHdmiTxGetConfig ++( ++ tmUnitSelect_t unit, ++ tmdlHdmiTxDriverConfigTable_t *pConfig ++); ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMDLHDMITX_LOCAL_H */ ++ ++/*============================================================================*/ ++/* END OF FILE */ ++/*============================================================================*/ +diff --git a/drivers/video/nxp/inc/tmFlags.h b/drivers/video/nxp/inc/tmFlags.h +new file mode 100755 +index 0000000..deabca6 +--- /dev/null ++++ b/drivers/video/nxp/inc/tmFlags.h +@@ -0,0 +1,237 @@ ++/* MoReUse 2002-09-13 Continuus Version 2 */ ++/* */ ++/* Changes: made ansi compliant */ ++/*-------------------------------------------------------------------------- */ ++ /* (C) Copyright 2002 Koninklijke Philips Electronics N.V., All Rights Reserved*/ ++ /* */ ++ /* This source code and any compilation or derivative thereof is the sole */ ++ /* property of Philips Corporation and is provided pursuant to a Software */ ++ /* License Agreement. This code is the proprietary information of */ ++ /* Philips Corporation and is confidential in nature. Its use and */ ++ /* dissemination by any party other than Philips Corporation is strictly */ ++ /* limited by the confidential information provisions of the Agreement */ ++ /* referenced above. */ ++ /*------------------------------------------------------------------------- */ ++ /* FILENAME: tmFlags.h */ ++ /* */ ++ /* DESCRIPTION: Platform dependent build flags (typically generated by the */ ++ /* SDE build process if it doesn't already exist). */ ++ /* */ ++ /* DOCUMENT REF: DVP Build Process Specification */ ++ /* */ ++ /* NOTES: This file defines the TMFL_xxx build flags configuration. */ ++ /* It does not include specific component diversity flags that */ ++ /* are defined in the component makefiles (e.g., TMFL_SCOPE */ ++ /* defined in BSL board files) */ ++ /* */ ++ /* This file is based on SDE Version 1.2 generated output. */ ++ /*------------------------------------------------------------------------- */ ++ /* */ ++ #ifndef TM_FLAGS_H ++ #define TM_FLAGS_H ++ ++/* Configurable build flags */ ++/* NOTE: The following flags are configurable (typically generated by SDE */ ++/* based on _TMXXX build environment variables). See individual flags */ ++/* for comments about the settings and consistency requirements. */ ++ ++/* TMFL_BUILD_VERSION: .. as decimal digits. This */ ++/* number is product/release dependent and not standardized as of now. */ ++/*#define TMFL_BUILD_VERSION 00.01.00*/ ++ ++/* RIDE tool does not support . in define value */ ++/* TMFL_BUILD_VERSION is not used to specify neither TDA9975_SW version not TDA9983_SW version */ ++#define TMFL_BUILD_VERSION 00 ++ ++/* TMFL_CPU: CPU type/model numbers: (TMFL_CPU_TYPE_XXX | TMFL_CPU_MODEL_XXX). */ ++/* Example: (TMFL_CPU_TYPE_X86 | TMFL_CPU_MODEL_I486) or (TMFL_CPU_I486) for */ ++/* an x86 i486 CPU. */ ++ #define TMFL_CPU (TMFL_CPU_TYPE_X86 | TMFL_CPU_MODEL_I486) ++ ++/* TMFL_ENDIAN: CPU endianness: */ ++ #define TMFL_ENDIAN (TMFL_ENDIAN_LITTLE) ++ ++/* TMFL_OS: Operating system type/version where the version number should be */ ++/* included if defined: (TMFL_OS_[VVV]). Example: TMFL_OS_PSOS250 */ ++/* indicates that the target OS is pSOS Version 2.50. */ ++ #define TMFL_OS (TMFL_OS_NULLOS) ++ ++/* TMFL_CPU_IS_XXX: These are boolean flags that reflects the CPU type and */ ++/* must be consistent with the TMFL_CPU setting (i.e., if TMFL_CPU = */ ++/* TMFL_CPU_I486, then TMFL_CPU_IS_X86 = 1) and all other TMFL_CPU_IS_XXX */ ++/* flags are 0. */ ++ #define TMFL_CPU_IS_X86 1 ++ #define TMFL_CPU_IS_MIPS 0 ++ #define TMFL_CPU_IS_HP 0 ++ #define TMFL_CPU_IS_TM 0 ++ #define TMFL_CPU_IS_ARM 0 ++ #define TMFL_CPU_IS_REAL 0 ++ ++/* TMFL_OS_IS_XXX: These are boolean flags that reflects the OS type and */ ++/* must be consistent with the TMFL_OS setting (i.e., if TMFL_OS = */ ++/* TMFL_OS_PSOS250, then TMFL_OS_IS_PSOS = 1) and all other TMFL_OS_IS_XXX */ ++/* flags are 0. */ ++ #define TMFL_OS_IS_BTM 0 ++ #define TMFL_OS_IS_CE 0 ++ #define TMFL_OS_IS_NT 0 ++ #define TMFL_OS_IS_PSOS 0 ++ #define TMFL_OS_IS_NULLOS 1 ++ #define TMFL_OS_IS_ECOS 0 ++ #define TMFL_OS_IS_VXWORKS 0 ++ #define TMFL_OS_IS_MTOS 0 ++ ++ ++/* Non-configurable constants */ ++/* NOTE: These values do not change and should not be modified ! */ ++ #define TMFL_CPU_TYPE_MASK 0xffff0000 ++ #define TMFL_CPU_TYPE_X86 0x00010000 ++ #define TMFL_CPU_TYPE_MIPS 0x00020000 ++ #define TMFL_CPU_TYPE_TM 0x00030000 ++ #define TMFL_CPU_TYPE_HP 0x00040000 ++ #define TMFL_CPU_TYPE_ARM 0x00050000 ++ #define TMFL_CPU_TYPE_REAL 0x00060000 ++ #define TMFL_CPU_MODEL_MASK 0x0000ffff ++ #define TMFL_CPU_MODEL_I486 0x00000001 ++ #define TMFL_CPU_MODEL_R3940 0x00000002 ++ #define TMFL_CPU_MODEL_R4300 0x00000003 ++ #define TMFL_CPU_MODEL_TM1100 0x00000004 ++ #define TMFL_CPU_MODEL_TM1300 0x00000005 ++ #define TMFL_CPU_MODEL_TM32 0x00000006 ++ #define TMFL_CPU_MODEL_HP 0x00000007 ++ #define TMFL_CPU_MODEL_R4640 0x00000008 ++ #define TMFL_CPU_MODEL_ARM7 0x00000009 ++ #define TMFL_CPU_MODEL_ARM920T 0x0000000a ++ #define TMFL_CPU_MODEL_ARM940T 0x0000000b ++ #define TMFL_CPU_MODEL_ARM10 0x0000000c ++ #define TMFL_CPU_MODEL_STRONGARM 0x0000000d ++ #define TMFL_CPU_MODEL_RD24120 0x0000000e ++ #define TMFL_CPU_MODEL_ARM926EJS 0x0000000f ++ #define TMFL_CPU_MODEL_ARM946 0x00000010 ++ #define TMFL_CPU_MODEL_R1910 0x00000011 ++ #define TMFL_CPU_MODEL_R4450 0x00000012 ++ #define TMFL_CPU_MODEL_TM3260 0x00000013 ++ #define TMFL_ENDIAN_BIG 1 ++ #define TMFL_ENDIAN_LITTLE 0 ++ #define TMFL_OS_MASK 0xff000000 ++ #define TMFL_OS_VERSION_MASK 0x00ffffff ++ #define TMFL_OS_BTM 0x00000000 ++ #define TMFL_OS_CE 0x01000000 ++ #define TMFL_OS_CE212 0x01020102 ++ #define TMFL_OS_CE300 0x01030000 ++ #define TMFL_OS_NT 0x02000000 ++ #define TMFL_OS_NT4 0x02040000 ++ #define TMFL_OS_PSOS 0x03000000 ++ #define TMFL_OS_PSOS250 0x03020500 ++ #define TMFL_OS_PSOS200 0x03020000 ++ #define TMFL_OS_NULLOS 0x04000000 ++ #define TMFL_OS_ECOS 0x05000000 ++ #define TMFL_OS_VXWORKS 0x06000000 ++ #define TMFL_OS_MTOS 0x07000000 ++ #define TMFL_SCOPE_SP 0 ++ #define TMFL_SCOPE_MP 1 ++ #define TMFL_REL_ASSERT 0x00000002 ++ #define TMFL_REL_DEBUG 0x00000001 ++ #define TMFL_REL_RETAIL 0x00000000 ++ #define TMFL_CPU_I486 0x00010001 ++ #define TMFL_CPU_R3940 0x00020002 ++ #define TMFL_CPU_R4300 0x00020003 ++ #define TMFL_CPU_TM1100 0x00030004 ++ #define TMFL_CPU_TM1300 0x00030005 ++ #define TMFL_CPU_TM32 0x00030006 ++ #define TMFL_CPU_HP 0x00040007 ++ #define TMFL_CPU_R4640 0x00020008 ++ #define TMFL_CPU_ARM7 0x00050009 ++ #define TMFL_CPU_ARM920T 0x0005000a ++ #define TMFL_CPU_ARM940T 0x0005000b ++ #define TMFL_CPU_ARM10 0x0005000c ++ #define TMFL_CPU_STRONGARM 0x0005000d ++ #define TMFL_CPU_RD24120 0x0006000e ++ #define TMFL_CPU_ARM926EJS 0x0005000f ++ #define TMFL_CPU_ARM946 0x00050010 ++ #define TMFL_CPU_R1910 0x00020011 ++ #define TMFL_CPU_R4450 0x00020012 ++ #define TMFL_CPU_TM3260 0x00030013 ++ #define TMFL_MODE_KERNEL 1 ++ #define TMFL_MODE_USER 0 ++ ++/******************************************************************************/ ++/* Components features defines */ ++/******************************************************************************/ ++#ifdef TMFL_TDA19988 ++# ifndef TMFL_TDA19989 ++# define TMFL_TDA19989 ++# endif /* TMFL_TDA19989 */ ++# define TMFL_RGB_DDR_12BITS ++# define TMFL_HDCP_OPTIMIZED_POWER ++#endif /* TMFL_TDA19988 */ ++ ++#ifdef TMFL_TDA19989 ++# ifndef TMFL_TDA9989 ++# define TMFL_TDA9989 ++# define SUPPORT_3D_FP ++# endif /* TMFL_TDA9989 */ ++#endif /* TMFL_TDA19989 */ ++/******************************************************************************/ ++/* Preprocessor checks for invalid settings (if file is manually modified) */ ++/******************************************************************************/ ++/* */ ++ ++/* Check if TMFL_CPU flag changed from its default setting. */ ++#if (TMFL_CPU == (TMFL_CPU_TYPE_MASK | TMFL_CPU_MODEL_MASK)) ++#error ERROR: TMFL_CPU must be set (TMFL_CPU_TYPE_XXX | TMFL_CPU_MODEL_XXX) ! ++#endif ++ ++/* Check if TMFL_ENDIAN flag setting is valid. */ ++#if ((TMFL_ENDIAN != TMFL_ENDIAN_BIG) && (TMFL_ENDIAN != TMFL_ENDIAN_LITTLE)) ++#error ERROR: TMFL_ENDIAN must be set to a valid TMFL_ENDIAN_XXX value ! ++#endif ++ ++/* Check if TMFL_OS flag changed from its default setting. */ ++#if (TMFL_OS == (TMFL_OS_MASK | TMFL_OS_VERSION_MASK)) ++#error ERROR: TMFL_OS must be set to a valid value (TMFL_OS_[]) ! ++#endif ++ ++/* The TMFL_CPU_IS_XXX is a Boolean; one and only one flag can be true (=1). */ ++#if ((TMFL_CPU_IS_X86 + TMFL_CPU_IS_MIPS + TMFL_CPU_IS_TM + TMFL_CPU_IS_HP + TMFL_CPU_IS_ARM + TMFL_CPU_IS_REAL) != 1) ++#error ERROR: One or more TMFL_CPU_IS_XXX values are incorrect or missing ! ++#endif ++ ++/* TMFL_CPU and TMFL_CPU_IS_XXX must be consistent */ ++#if (((TMFL_CPU & TMFL_CPU_TYPE_MASK) == TMFL_CPU_TYPE_X86) && (TMFL_CPU_IS_X86 != 1)) ++#error ERROR: Inconsistent TMFL_CPU and TMFL_CPU_IS_X86 settings ! ++#elif (((TMFL_CPU & TMFL_CPU_TYPE_MASK) == TMFL_CPU_TYPE_MIPS) && (TMFL_CPU_IS_MIPS != 1)) ++#error ERROR: Inconsistent TMFL_CPU and TMFL_CPU_IS_MIPS settings ! ++#elif (((TMFL_CPU & TMFL_CPU_TYPE_MASK) == TMFL_CPU_TYPE_TM) && (TMFL_CPU_IS_TM != 1)) ++#error ERROR: Inconsistent TMFL_CPU and TMFL_CPU_IS_TM settings ! ++#elif (((TMFL_CPU & TMFL_CPU_TYPE_MASK) == TMFL_CPU_TYPE_HP) && (TMFL_CPU_IS_HP != 1)) ++#error ERROR: Inconsistent TMFL_CPU and TMFL_CPU_IS_HP settings ! ++#elif (((TMFL_CPU & TMFL_CPU_TYPE_MASK) == TMFL_CPU_TYPE_ARM) && (TMFL_CPU_IS_ARM != 1)) ++#error ERROR: Inconsistent TMFL_CPU and TMFL_CPU_IS_ARM settings ! ++#elif (((TMFL_CPU & TMFL_CPU_TYPE_MASK) == TMFL_CPU_TYPE_REAL) && (TMFL_CPU_IS_REAL != 1)) ++#error ERROR: Inconsistent TMFL_CPU and TMFL_CPU_IS_REAL settings ! ++#endif /* (((TMFL_CPU & TMFL_CPU_TYPE_MASK) == TMFL_CPU_TYPE_X86) && ... */ ++ ++/* The TMFL_OS_IS_XXX is a Boolean; one and only one flag can be true (=1). */ ++#if ((TMFL_OS_IS_BTM + TMFL_OS_IS_CE + TMFL_OS_IS_NT + TMFL_OS_IS_PSOS + TMFL_OS_IS_NULLOS + TMFL_OS_IS_ECOS + TMFL_OS_IS_VXWORKS + TMFL_OS_IS_MTOS) != 1) ++#error ERROR: One or more TMFL_OS_IS_XXX values are incorrect or missing ! ++#endif ++ ++#if (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_BTM) && (TMFL_OS_IS_BTM != 1)) ++#error ERROR: Inconsistent TMFL_OS and TMFL_OS_IS_BTM settings ! ++#elif (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_CE) && (TMFL_OS_IS_CE != 1)) ++#error ERROR: Inconsistent TMFL_OS and TMFL_OS_IS_CE settings ! ++#elif (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_NT) && (TMFL_OS_IS_NT != 1)) ++#error ERROR: Inconsistent TMFL_OS and TMFL_OS_IS_NT settings ! ++#elif (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_PSOS) && (TMFL_OS_IS_PSOS != 1)) ++#error ERROR: Inconsistent TMFL_OS and TMFL_OS_IS_PSOS settings ! ++#elif (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_NULLOS) && (TMFL_OS_IS_NULLOS != 1)) ++#error ERROR: Inconsistent TMFL_OS and TMFL_OS_IS_NULLOS settings ! ++#elif (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_ECOS) && (TMFL_OS_IS_ECOS != 1)) ++#error ERROR: Inconsistent TMFL_OS and TMFL_OS_IS_ECOS settings ! ++#elif (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_VXWORKS) && (TMFL_OS_IS_VXWORKS != 1)) ++#error ERROR: Inconsistent TMFL_OS and TMFL_OS_IS_VXWORKS settings ! ++#elif (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_MTOS) && (TMFL_OS_IS_MTOS != 1)) ++#error ERROR: Inconsistent TMFL_OS and TMFL_OS_IS_MTOS settings ! ++#endif /* (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_XX) && (TMFL_OS_IS_XX != 1)) */ ++ ++#endif /* TM_FLAGS_H */ +diff --git a/drivers/video/nxp/inc/tmNxCompId.h b/drivers/video/nxp/inc/tmNxCompId.h +new file mode 100755 +index 0000000..2302901 +--- /dev/null ++++ b/drivers/video/nxp/inc/tmNxCompId.h +@@ -0,0 +1,1743 @@ ++/* -------------------------------------------------------------------------- */ ++/* (C) Copyright 2000-2005 Koninklijke Philips Electronics N.V., */ ++/* All rights reserved */ ++/* */ ++/* This source code and any compilation or derivative thereof is the */ ++/* proprietary information of Konlinklijke Philips Electronics N.V. and is */ ++/* Confidential in nature. */ ++/* Under no circumstances is this software to be exposed to or placed under an*/ ++/* Open Source License of any type without the expressed written permission of*/ ++/* Koninklijke Philips Electronics N.V. */ ++/* -------------------------------------------------------------------------- */ ++/* */ ++/* MoReUse - 2005-10-24 Version 118 */ ++/* */ ++/* Added: */ ++/* CID_AACPENC */ ++/* */ ++/* */ ++/* Changed: */ ++/* */ ++/* */ ++/* */ ++/* Removed: */ ++/* */ ++/* */ ++/* */ ++/* General Error Codes Added */ ++/* */ ++/* -------------------------------------------------------------------------- */ ++/* FILE NAME: tmNxCompId.h */ ++/* */ ++/* DESCRIPTION: This header file identifies the standard component */ ++/* identifiers (CIDs) and interface identifiers (IID) for */ ++/* Nexperia platforms. */ ++/* The objective of these identifiers is to enable unique */ ++/* identification of software components and interfaces. */ ++/* In addition, standard status values are also defined to make */ ++/* determination of typical error cases much easier. */ ++/* */ ++/* Functional errors are not real errors in the sense of */ ++/* unexpected behaviour but are part of the normal communication*/ ++/* between a client an a server component. They are linked to */ ++/* an interface, rather than to a component. All implementations*/ ++/* of an interface must have the same behaviour with respect to */ ++/* functional errors. Functional erros are all positive */ ++/* One global functional error is defined: TM_OK 0x00000000 */ ++/* */ ++/* Non-functional errors (all negative numbers) indicate */ ++/* unexpected behaviour. They are linked to concrete component */ ++/* implementations */ ++/* */ ++/* NOTE: The current implementation is different from the prev. */ ++/* component identifier implementation, based on classes, */ ++/* types and layers. However, the new system is backward */ ++/* compatitible with the old implementation. */ ++/* */ ++/* tmNxCompId.h defines a number of general error codes that can*/ ++/* be used by all components. These error codes are concatenated*/ ++/* to the CID or IID value in the local component headerfile of */ ++/* the component that wants to (re-)use this general error code */ ++/* General error codes can be used for both functional and */ ++/* non-functional errors. They should only be used if they */ ++/* semantically fully match (if not, defined a new component or */ ++/* interface specific error code. */ ++/* */ ++/* General Rules: */ ++/* A return value has a length of 32 bits. At the binary level, */ ++/* 1 bit indicates the component or interface flag; 16 bits are */ ++/* used for the actual component id (CID) or interface id (IID) */ ++/* and 12 bits for the return status. */ ++/* The component/interface flag is bit 31. */ ++/* Bits 30--28 are all 0. */ ++/* The component/interface id occupies bits 27--12. */ ++/* The return status occupies bits 11--0. */ ++/* */ ++/* +--------+-----+-------+-----------+ */ ++/* | flag:1 | 0:3 | id:16 | status:12 | */ ++/* +--------+-----+-------+-----------+ */ ++/* */ ++/* Format of interface ids: */ ++/* */ ++/* +-----+-----+--------+-----------+ */ ++/* | 0:1 | 0:3 | iid:16 | status:12 | */ ++/* +-----+-----+--------+-----------+ */ ++/* */ ++/* Format of component ids: */ ++/* */ ++/* +-----+-----+--------+-----------+ */ ++/* | 1:1 | 0:3 | cid:16 | status:12 | */ ++/* +-----+-----+--------+-----------+ */ ++/* */ ++/* At the macro level, we use the prefix "CID_" for component */ ++/* ids (previous version "CID_COMP_") and "IID_" for interface */ ++/* ids. */ ++/* */ ++/* Each component id will be used by only one component; each */ ++/* component will have its own component id. */ ++/* Each interface id will be used by only one interface; each */ ++/* interface will have its own interface id. */ ++/* */ ++/* In order to avoid problems when promoting a UNIQUE interface */ ++/* to a SEPARATE interface, the ranges for CIDs and IIDS must */ ++/* not overlap. */ ++/* */ ++/* Component names and component ids have to be registered */ ++/* together; the same applies for interface names and ids. */ ++/* */ ++/* NOTE about Compatibility */ ++/* In the previous implementation the first four bits were */ ++/* reserved for class, and there were separate fields for */ ++/* type and tag, like this: */ ++/* */ ++/* +---------+--------+-------+---------+-----------+ */ ++/* | class:4 | type:4 | tag:8 | layer:4 | status:12 | */ ++/* +---------+--------+-------+---------+-----------+ */ ++/* */ ++/* The values 0 or 8 are not valid classes, and this fact */ ++/* can be used to distinguish a new-style IID (class == 0), */ ++/* a new-style CID (class == 8), and an old-style CID */ ++/* (otherwise). */ ++/* */ ++/* NOTE about error codes */ ++/* The general error codes use the range 0x001 to 0x7FF. */ ++/* The component specific error codes are defined in the */ ++/* local component header file and can use 0x800 to 0xFFF. */ ++/* TM_OK has the value 0x00000000. */ ++/* The proposed error code ranges (general and specific) are */ ++/* the same for functional and non-functional errors. */ ++/* */ ++/* The previously defined ranges for external customers, */ ++/* assert errors and fatal errors have been dropped. */ ++/* The previously defined range for general errors started */ ++/* at 0x000 instead of 0x001 */ ++/* */ ++/* DOCUMENT REF: Nexperia/MoReUse Naming Conventions */ ++/* */ ++/* -------------------------------------------------------------------------- */ ++ ++#ifndef TMNXCOMPID_H ++#define TMNXCOMPID_H ++ ++/* -------------------------------------------------------------------------- */ ++/* */ ++/* Standard include files: */ ++/* */ ++/* -------------------------------------------------------------------------- */ ++#include "tmNxTypes.h" ++ ++#ifdef __cplusplus ++extern "C" ++{ ++#endif ++ ++/* -------------------------------------------------------------------------- */ ++/* */ ++/* Types and defines: */ ++/* */ ++/* -------------------------------------------------------------------------- */ ++ ++/* -------------------------------------------------------------------------- */ ++/* */ ++/* TM_OK is the 32 bit global status value used by all Nexperia components */ ++/* to indicate successful function/operation status. If a non-zero value is*/ ++/* returned as status, it should use the component ID formats defined. */ ++/* */ ++/* -------------------------------------------------------------------------- */ ++#define TM_OK 0U /* Global success return status */ ++ ++/* -------------------------------------------------------------------------- */ ++/* */ ++/* General Defines */ ++/* */ ++/* -------------------------------------------------------------------------- */ ++#define CID_IID_FLAG_BITSHIFT 31 ++#define CID_ID_BITSHIFT 12 ++#define IID_ID_BITSHIFT 12 ++ ++#define CID_FLAG (0x1U << CID_IID_FLAG_BITSHIFT) ++#define IID_FLAG (0x0U << CID_IID_FLAG_BITSHIFT) ++ ++#define CID_ID(number) ((number) << CID_ID_BITSHIFT) ++#define CID_ID_BITMASK (0x7FFFFU << CID_ID_BITSHIFT) ++ ++#define IID_ID(number) ((number) << IID_ID_BITSHIFT) ++#define IID_ID_BITMASK (0x7FFFFU << IID_ID_BITSHIFT) ++ ++/* -------------------------------------------------------------------------- */ ++/* */ ++/* Definition of the interface IDs */ ++/* */ ++/* -------------------------------------------------------------------------- */ ++#define IID_IENUMUNKNOWN (IID_ID(0x001U) | IID_FLAG) ++#define IID_IBIND (IID_ID(0x002U) | IID_FLAG) ++#define IID_IBINDINFO (IID_ID(0x003U) | IID_FLAG) ++#define IID_IMEM (IID_ID(0x004U) | IID_FLAG) ++#define IID_IUNKNOWN (IID_ID(0x005U) | IID_FLAG) ++#define IID_IIC (IID_ID(0x006U) | IID_FLAG) ++#define IID_ACHAN (IID_ID(0x007U) | IID_FLAG) ++#define IID_AFEAT (IID_ID(0x008U) | IID_FLAG) ++#define IID_AMIX (IID_ID(0x009U) | IID_FLAG) ++#define IID_ANAADEC (IID_ID(0x00aU) | IID_FLAG) ++#define IID_ANAVENC (IID_ID(0x00bU) | IID_FLAG) ++#define IID_ANAVENCRYPT (IID_ID(0x00cU) | IID_FLAG) ++#define IID_ANAVDEC (IID_ID(0x00dU) | IID_FLAG) ++#define IID_BBARDETEXT (IID_ID(0x00eU) | IID_FLAG) ++#define IID_BLEVELDETEXT (IID_ID(0x00fU) | IID_FLAG) ++#define IID_BLEVELMODEXT (IID_ID(0x010U) | IID_FLAG) ++#define IID_BSLSPDI (IID_ID(0x011U) | IID_FLAG) ++#define IID_BSLSPDO (IID_ID(0x012U) | IID_FLAG) ++#define IID_BSL_AI (IID_ID(0x013U) | IID_FLAG) ++#define IID_BSL_AO (IID_ID(0x014U) | IID_FLAG) ++#define IID_BSL_AVI (IID_ID(0X015U) | IID_FLAG) ++#define IID_BSL_AVO (IID_ID(0x016U) | IID_FLAG) ++#define IID_BSL_EEPROM (IID_ID(0X017U) | IID_FLAG) ++#define IID_BSL_IDE (IID_ID(0X018U) | IID_FLAG) ++#define IID_BSL_NANDFLASH (IID_ID(0X019U) | IID_FLAG) ++#define IID_BSL_NORFLASH (IID_ID(0X01aU) | IID_FLAG) ++#define IID_BSL_PARPORT (IID_ID(0X01bU) | IID_FLAG) ++#define IID_BSL_RTC (IID_ID(0X01cU) | IID_FLAG) ++#define IID_COLENH (IID_ID(0x01dU) | IID_FLAG) ++#define IID_COLENHEXT (IID_ID(0x01eU) | IID_FLAG) ++#define IID_CONNMGR (IID_ID(0x01fU) | IID_FLAG) ++#define IID_CRT (IID_ID(0x020U) | IID_FLAG) ++#define IID_CTI (IID_ID(0X021U) | IID_FLAG) ++#define IID_CTIEXT (IID_ID(0X022U) | IID_FLAG) ++#define IID_DIGADEC (IID_ID(0X023U) | IID_FLAG) ++#define IID_DIGVDEC (IID_ID(0X024U) | IID_FLAG) ++#define IID_DMX (IID_ID(0X025U) | IID_FLAG) ++#define IID_DNR (IID_ID(0X026U) | IID_FLAG) ++#define IID_DNREXT (IID_ID(0X027U) | IID_FLAG) ++#define IID_DVBSUBTDEC (IID_ID(0X028U) | IID_FLAG) ++#define IID_FATERR (IID_ID(0X029U) | IID_FLAG) ++#define IID_FREND (IID_ID(0X02aU) | IID_FLAG) ++#define IID_GAMMAEXT (IID_ID(0X02bU) | IID_FLAG) ++#define IID_HISTOMEASEXT (IID_ID(0X02cU) | IID_FLAG) ++#define IID_HISTOMODEXT (IID_ID(0X02dU) | IID_FLAG) ++#define IID_MML (IID_ID(0X02eU) | IID_FLAG) ++#define IID_NOISEESTEXT (IID_ID(0X02fU) | IID_FLAG) ++#define IID_OSAL (IID_ID(0X030U) | IID_FLAG) ++#define IID_PIPSTORE (IID_ID(0X031U) | IID_FLAG) ++#define IID_SCANRATECONV (IID_ID(0X032U) | IID_FLAG) ++#define IID_SCANRATECONVEXT (IID_ID(0X033U) | IID_FLAG) ++#define IID_SHARPENH (IID_ID(0X034U) | IID_FLAG) ++#define IID_SHARPENHEXT (IID_ID(0X035U) | IID_FLAG) ++#define IID_SHARPMEASEXT (IID_ID(0X036U) | IID_FLAG) ++#define IID_SPDIFIN (IID_ID(0X037U) | IID_FLAG) ++#define IID_SPDIFOUT (IID_ID(0X038U) | IID_FLAG) ++#define IID_SPEAKER (IID_ID(0X039U) | IID_FLAG) ++#define IID_STCDEC (IID_ID(0X03aU) | IID_FLAG) ++#define IID_STREAMINJ (IID_ID(0X03bU) | IID_FLAG) ++#define IID_SYNCTAG (IID_ID(0X03cU) | IID_FLAG) ++#define IID_TSSACOM (IID_ID(0X03dU) | IID_FLAG) ++#define IID_TXTDEC (IID_ID(0X03eU) | IID_FLAG) ++#define IID_UTILCRYPT (IID_ID(0X03fU) | IID_FLAG) ++#define IID_UVBWDETEXT (IID_ID(0X040U) | IID_FLAG) ++#define IID_VBIINSERT (IID_ID(0X041U) | IID_FLAG) ++#define IID_VBISLICE (IID_ID(0X042U) | IID_FLAG) ++#define IID_VDCC (IID_ID(0X043U) | IID_FLAG) ++#define IID_VDSTSCAN (IID_ID(0X044U) | IID_FLAG) ++#define IID_VFEAT (IID_ID(0X045U) | IID_FLAG) ++#define IID_VMIX (IID_ID(0X046U) | IID_FLAG) ++#define IID_VSCALEEXT (IID_ID(0X047U) | IID_FLAG) ++#define IID_VSRCPROP (IID_ID(0X048U) | IID_FLAG) ++#define IID_VSRCSCANPROP (IID_ID(0X049U) | IID_FLAG) ++#define IID_GENI2C (IID_ID(0X04aU) | IID_FLAG) ++#define IID_PLFINSTVIN (IID_ID(0X04bU) | IID_FLAG) ++#define IID_PLFINSTAIN (IID_ID(0X04cU) | IID_FLAG) ++#define IID_PLFINSTAOUT (IID_ID(0X04dU) | IID_FLAG) ++#define IID_PLFINSTGFX (IID_ID(0X04eU) | IID_FLAG) ++#define IID_CONNMGRATV (IID_ID(0X04fU) | IID_FLAG) ++#define IID_IAMALIVE (IID_ID(0X050U) | IID_FLAG) ++#define IID_BBARDET (IID_ID(0X051U) | IID_FLAG) ++#define IID_CONTRRESEXT (IID_ID(0X052U) | IID_FLAG) ++#define IID_NOISEMEAS (IID_ID(0X053U) | IID_FLAG) ++#define IID_SHARPMEAS (IID_ID(0X054U) | IID_FLAG) ++#define IID_HISTOMOD (IID_ID(0X055U) | IID_FLAG) ++#define IID_ANTIAGING (IID_ID(0X056U) | IID_FLAG) ++#define IID_AMBIENTLEVEL (IID_ID(0X057U) | IID_FLAG) ++#define IID_HAD_DRV_IIC (IID_ID(0X058U) | IID_FLAG) ++#define IID_HAD_DRV_GPIO (IID_ID(0X059U) | IID_FLAG) ++#define IID_HAD_DRV_CSM (IID_ID(0X05aU) | IID_FLAG) ++#define IID_DRIVERHAL (IID_ID(0X05bU) | IID_FLAG) ++#define IID_MUTISTR (IID_ID(0X05cU) | IID_FLAG) ++#define IID_MUTIVEC (IID_ID(0X05dU) | IID_FLAG) ++#define IID_MUTISTRX (IID_ID(0X05eU) | IID_FLAG) ++#define IID_MUTICMD (IID_ID(0X05fU) | IID_FLAG) ++#define IID_TASK_CONDITION (IID_ID(0X060U) | IID_FLAG) ++#define IID_PACKET_POOL (IID_ID(0X061U) | IID_FLAG) ++#define IID_PACKET_QUEUE (IID_ID(0X062U) | IID_FLAG) ++#define IID_UDSDCD (IID_ID(0X063U) | IID_FLAG) ++#define IID_DCSS_RL (IID_ID(0X064U) | IID_FLAG) ++#define IID_DCSS_DD (IID_ID(0X065U) | IID_FLAG) ++#define IID_DCSS_GD (IID_ID(0X066U) | IID_FLAG) ++#define IID_DCSS_RSC (IID_ID(0X067U) | IID_FLAG) ++#define IID_DCSS_P (IID_ID(0X068U) | IID_FLAG) ++#define IID_DCSS (IID_ID(0X069U) | IID_FLAG) ++#define IID_CC_BURST_CUTTING_AREA (IID_ID(0X06aU) | IID_FLAG) ++#define IID_CC_CONFIGURATION (IID_ID(0X06bU) | IID_FLAG) ++#define IID_CC_CONTROL (IID_ID(0X06cU) | IID_FLAG) ++#define IID_CC_DEBUG (IID_ID(0X06dU) | IID_FLAG) ++#define IID_CC_DECODER (IID_ID(0X06eU) | IID_FLAG) ++#define IID_CC_ENCODER (IID_ID(0X06fU) | IID_FLAG) ++#define IID_CC_HF_PROCESSING (IID_ID(0X070U) | IID_FLAG) ++#define IID_CC_INTERFACE (IID_ID(0X071U) | IID_FLAG) ++#define IID_CC_NATLAB (IID_ID(0X072U) | IID_FLAG) ++#define IID_CC_PIC (IID_ID(0X073U) | IID_FLAG) ++#define IID_CC_WOBBLE (IID_ID(0X074U) | IID_FLAG) ++#define IID_CC_REGISTERMAP (IID_ID(0X075U) | IID_FLAG) ++#define IID_CC_WOBBLE_REG (IID_ID(0X076U) | IID_FLAG) ++#define IID_CC_PIC_REG (IID_ID(0X077U) | IID_FLAG) ++#define IID_CC_NATLAB_REG (IID_ID(0X078U) | IID_FLAG) ++#define IID_CC_INTERFACE_REG (IID_ID(0X079U) | IID_FLAG) ++#define IID_CC_HF_PROCESSING_REG (IID_ID(0X07aU) | IID_FLAG) ++#define IID_CC_ENCODER_REG (IID_ID(0X07bU) | IID_FLAG) ++#define IID_CC_DECODER_REG (IID_ID(0X07cU) | IID_FLAG) ++#define IID_CC_DEBUG_REG (IID_ID(0X07dU) | IID_FLAG) ++#define IID_CC_CONTROL_REG (IID_ID(0X07eU) | IID_FLAG) ++#define IID_CC_CONFIGURATION_REG (IID_ID(0X07fU) | IID_FLAG) ++#define IID_CC_BURST_CUTTING_AREA_REG (IID_ID(0X080U) | IID_FLAG) ++#define IID_CC_PHYSICAL_VALUES (IID_ID(0X081U) | IID_FLAG) ++#define IID_CC_GENERAL_SETTINGS (IID_ID(0X082U) | IID_FLAG) ++#define IID_CC_COEFFICIENTS (IID_ID(0X083U) | IID_FLAG) ++#define IID_REMOTE_CONTROL (IID_ID(0X084U) | IID_FLAG) ++#define IID_TUNER (IID_ID(0X085U) | IID_FLAG) ++#define IID_MUTITST (IID_ID(0X086U) | IID_FLAG) ++#define IID_CHIP_CONTEXT (IID_ID(0X087U) | IID_FLAG) ++#define IID_API (IID_ID(0X088U) | IID_FLAG) ++#define IID_CHANDEC (IID_ID(0X089U) | IID_FLAG) ++#define IID_TUNING (IID_ID(0X08aU) | IID_FLAG) ++#define IID_TUNINGAFC (IID_ID(0X08bU) | IID_FLAG) ++#define IID_TUNINGAFCNTF (IID_ID(0X08cU) | IID_FLAG) ++#define IID_TUNINGCHAN (IID_ID(0X08dU) | IID_FLAG) ++#define IID_TUNINGSEARCHNTF (IID_ID(0X08eU) | IID_FLAG) ++#define IID_ID3EXTR (IID_ID(0X08fU) | IID_FLAG) ++#define IID_ANAAVDEM (IID_ID(0X090U) | IID_FLAG) ++#define IID_ANAAVDEMNTF (IID_ID(0X091U) | IID_FLAG) ++#define IID_CCEXTR (IID_ID(0X092U) | IID_FLAG) ++#define IID_CHANDECDVBC (IID_ID(0X093U) | IID_FLAG) ++#define IID_CHANDECDVBS (IID_ID(0X094U) | IID_FLAG) ++#define IID_CHANDECDVBT (IID_ID(0X095U) | IID_FLAG) ++#define IID_CHANDECNTF (IID_ID(0X096U) | IID_FLAG) ++#define IID_OOB (IID_ID(0X097U) | IID_FLAG) ++#define IID_RFAMP (IID_ID(0X098U) | IID_FLAG) ++#define IID_SIGSTRENGTH (IID_ID(0X099U) | IID_FLAG) ++#define IID_SIGSTRENGTHNTF (IID_ID(0X09aU) | IID_FLAG) ++#define IID_IMAGEDEC (IID_ID(0X09bU) | IID_FLAG) ++#define IID_TUNINGSEARCH (IID_ID(0X09cU) | IID_FLAG) ++#define IID_PINOBJECTS (IID_ID(0X09dU) | IID_FLAG) ++#define IID_URLSRC (IID_ID(0X09eU) | IID_FLAG) ++#define IID_OSDKERNELAPP (IID_ID(0X09fU) | IID_FLAG) ++#define IID_OSDKERNELMEM (IID_ID(0X0a0U) | IID_FLAG) ++#define IID_OSDKERNELOSD (IID_ID(0X0a1U) | IID_FLAG) ++#define IID_OSDKERNELOSDCONTROL (IID_ID(0X0a2U) | IID_FLAG) ++#define IID_RTC (IID_ID(0X0a3U) | IID_FLAG) ++#define IID_FS (IID_ID(0X0a4U) | IID_FLAG) ++#define IID_BE (IID_ID(0X0a5U) | IID_FLAG) ++#define IID_CD_LIB (IID_ID(0X0a6U) | IID_FLAG) ++#define IID_DB (IID_ID(0X0a7U) | IID_FLAG) ++#define IID_AVIN (IID_ID(0X0a8U) | IID_FLAG) ++#define IID_AVOUT (IID_ID(0X0a9U) | IID_FLAG) ++#define IID_INT (IID_ID(0X0aaU) | IID_FLAG) ++#define IID_EVT (IID_ID(0X0abU) | IID_FLAG) ++#define IID_DMA (IID_ID(0X0acU) | IID_FLAG) ++#define IID_CLK (IID_ID(0X0adU) | IID_FLAG) ++#define IID_VMIXBORDERPAINTER (IID_ID(0X0aeU) | IID_FLAG) ++#define IID_CPROCTVFLOW (IID_ID(0X0afU) | IID_FLAG) ++#define IID_VTRANTIAGING (IID_ID(0X0b0U) | IID_FLAG) ++#define IID_VTRFADE (IID_ID(0X0b1U) | IID_FLAG) ++#define IID_VTRSCALE (IID_ID(0X0b2U) | IID_FLAG) ++#define IID_VTRSTROBE (IID_ID(0X0b3U) | IID_FLAG) ++#define IID_HDMIIN (IID_ID(0X0b4U) | IID_FLAG) ++#define IID_ACHANSEL (IID_ID(0X0b5U) | IID_FLAG) ++#define IID_SSP (IID_ID(0X0b6U) | IID_FLAG) ++#define IID_CONNMGR_STILL (IID_ID(0X0b7U) | IID_FLAG) ++#define IID_CONNMGR_AUDIO (IID_ID(0X0b8U) | IID_FLAG) ++#define IID_CONNMGR_MPEG2PS (IID_ID(0X0b9U) | IID_FLAG) ++#define IID_SPI_SD (IID_ID(0X0baU) | IID_FLAG) ++#define IID_DECODERHALCST (IID_ID(0X0bbU) | IID_FLAG) ++#define IID_SOD (IID_ID(0X0bcU) | IID_FLAG) ++#define IID_DCSS_AA (IID_ID(0X0bdU) | IID_FLAG) ++#define IID_DCSS_AVI (IID_ID(0X0beU) | IID_FLAG) ++#define IID_DCSS_BC (IID_ID(0X0bfU) | IID_FLAG) ++#define IID_DCSS_CLUT (IID_ID(0X0c0U) | IID_FLAG) ++#define IID_DCSS_COL (IID_ID(0X0c1U) | IID_FLAG) ++#define IID_DCSS_DFC (IID_ID(0X0c2U) | IID_FLAG) ++#define IID_DCSS_DOC (IID_ID(0X0c3U) | IID_FLAG) ++#define IID_DCSS_GIO (IID_ID(0X0c4U) | IID_FLAG) ++#define IID_DCSS_ISD (IID_ID(0X0c5U) | IID_FLAG) ++#define IID_DCSS_KBI (IID_ID(0X0c6U) | IID_FLAG) ++#define IID_DCSS_OSD (IID_ID(0X0c7U) | IID_FLAG) ++#define IID_DCSS_PIF (IID_ID(0X0c8U) | IID_FLAG) ++#define IID_DCSS_PVI (IID_ID(0X0c9U) | IID_FLAG) ++#define IID_DCSS_SIS (IID_ID(0X0caU) | IID_FLAG) ++#define IID_DCSS_TIG (IID_ID(0X0cbU) | IID_FLAG) ++#define IID_DCSS_USC (IID_ID(0X0ccU) | IID_FLAG) ++#define IID_DCSS_VCR (IID_ID(0X0cdU) | IID_FLAG) ++#define IID_CONNMGR_MP4RTP_PLAYER (IID_ID(0X0ceU) | IID_FLAG) ++#define IID_CONNMGR_AVIMP4_PLAYER (IID_ID(0X0cfU) | IID_FLAG) ++#define IID_VDECANAEXT2 (IID_ID(0X0d0U) | IID_FLAG) ++#define IID_STBCOMMON (IID_ID(0X0d1U) | IID_FLAG) ++#define IID_AVSYNCCTRL (IID_ID(0X0d2U) | IID_FLAG) ++#define IID_PRIVNETSCHEMECONFIG (IID_ID(0X0d3U) | IID_FLAG) ++#define IID_SHAREDVARIABLE (IID_ID(0X0d4U) | IID_FLAG) ++#define IID_NETSCHEMECONFIG (IID_ID(0X0d5U) | IID_FLAG) ++#define IID_AVSYNCTRICK (IID_ID(0X0d6U) | IID_FLAG) ++#define IID_SETINTF (IID_ID(0X0d7U) | IID_FLAG) ++#define IID_URLDMXMONITOR (IID_ID(0X0d8U) | IID_FLAG) ++#define IID_VDECMONITOR (IID_ID(0X0d9U) | IID_FLAG) ++#define IID_STBVIDEOTYPES (IID_ID(0X0daU) | IID_FLAG) ++ ++#define IID_RESERVED (CID_ID(0x7fffU) | CID_FLAG) ++/* ************************************************************************** */ ++/* Interface Id's reserved for external organizations */ ++/* */ ++/* None */ ++/* */ ++/* ************************************************************************** */ ++ ++/* -------------------------------------------------------------------------- */ ++/* */ ++/* Definition of the component IDs */ ++/* */ ++/* -------------------------------------------------------------------------- */ ++#define CID_MPMP1_GRINDER (CID_ID(0x8001U) | CID_FLAG) ++#define CID_MUSB_GRINDER (CID_ID(0x8002U) | CID_FLAG) ++#define CID_UOTGPFL (CID_ID(0x8003U) | CID_FLAG) ++#define CID_CHIPBUILDER_GRINDER (CID_ID(0x8004U) | CID_FLAG) ++ ++#define CID_AANALYZER (CID_ID(0x8009U) | CID_FLAG) ++#define CID_ADEC_AAC4 (CID_ID(0x800aU) | CID_FLAG) ++#define CID_ADEC_ATV (CID_ID(0x800bU) | CID_FLAG) ++#define CID_ADEC_CELP4 (CID_ID(0x800cU) | CID_FLAG) ++#define CID_ADEC_CORE (CID_ID(0x800dU) | CID_FLAG) ++#define CID_ADEC_MP3PRO (CID_ID(0x800eU) | CID_FLAG) ++#define CID_ADEC_PL2 (CID_ID(0x800fU) | CID_FLAG) ++#define CID_ADEC_STB (CID_ID(0x8010U) | CID_FLAG) ++#define CID_ADEEMPH (CID_ID(0x8011U) | CID_FLAG) ++#define CID_AENCAAC4 (CID_ID(0x8012U) | CID_FLAG) ++#define CID_AREND_AO_MUX (CID_ID(0x8013U) | CID_FLAG) ++#define CID_ASP_IIRZ2 (CID_ID(0x8014U) | CID_FLAG) ++#define CID_ASRC (CID_ID(0x8015U) | CID_FLAG) ++#define CID_ASYS_CORE (CID_ID(0x8016U) | CID_FLAG) ++#define CID_ATV_PLF_BASIC (CID_ID(0x8017U) | CID_FLAG) ++#define CID_ATV_STUBS (CID_ID(0x8018U) | CID_FLAG) ++#define CID_AVI_READ_DIVX (CID_ID(0x8019U) | CID_FLAG) ++#define CID_BOOTINFO (CID_ID(0x801aU) | CID_FLAG) ++#define CID_BROWSE_EIS (CID_ID(0x801bU) | CID_FLAG) ++#define CID_BSL_7113 (CID_ID(0x801cU) | CID_FLAG) ++#define CID_BSL_7113QT (CID_ID(0x801dU) | CID_FLAG) ++#define CID_BSL_7114 (CID_ID(0x801eU) | CID_FLAG) ++#define CID_BSL_7118 (CID_ID(0x801fU) | CID_FLAG) ++#define CID_BSL_ANABEL (CID_ID(0x8020U) | CID_FLAG) ++#define CID_BSL_ANABELQT (CID_ID(0x8021U) | CID_FLAG) ++#define CID_BSL_AVIP (CID_ID(0x8022U) | CID_FLAG) ++#define CID_BSL_BOARDS (CID_ID(0x8023U) | CID_FLAG) ++#define CID_BSL_CORE (CID_ID(0x8024U) | CID_FLAG) ++#define CID_BSL_DENC (CID_ID(0x8025U) | CID_FLAG) ++#define CID_BSL_EEPROM_ATMEL (CID_ID(0x8026U) | CID_FLAG) ++#define CID_BSL_IDEXIO (CID_ID(0x8027U) | CID_FLAG) ++#define CID_BSL_NANDSAMSUNG (CID_ID(0x8028U) | CID_FLAG) ++#define CID_BSL_NORINTEL (CID_ID(0x8029U) | CID_FLAG) ++#define CID_BSL_RTCPCF8563 (CID_ID(0x802aU) | CID_FLAG) ++#define CID_BSL_UART_HWAPI (CID_ID(0x802bU) | CID_FLAG) ++#define CID_BSL_UDA1344 (CID_ID(0x802cU) | CID_FLAG) ++#define CID_BT_1500 (CID_ID(0x802dU) | CID_FLAG) ++#define CID_BT_API (CID_ID(0x802eU) | CID_FLAG) ++#define CID_BT_CORE (CID_ID(0x802fU) | CID_FLAG) ++#define CID_BT_CPU (CID_ID(0x8030U) | CID_FLAG) ++#define CID_BT_MIPS (CID_ID(0x8031U) | CID_FLAG) ++#define CID_BT_TRIMEDIA (CID_ID(0x8032U) | CID_FLAG) ++#define CID_BT_V2PCI (CID_ID(0x8033U) | CID_FLAG) ++#define CID_BT_VPCI (CID_ID(0x8034U) | CID_FLAG) ++#define CID_BT_VSTB (CID_ID(0x8035U) | CID_FLAG) ++#define CID_BUFFEREDREAD (CID_ID(0x8036U) | CID_FLAG) ++#define CID_CONN_MGRAUDSYSSTB (CID_ID(0x8037U) | CID_FLAG) ++#define CID_DEMUXMPEGTS_SW (CID_ID(0x8038U) | CID_FLAG) ++#define CID_DIG_ADEC_AUDSYS_STB (CID_ID(0x8039U) | CID_FLAG) ++#define CID_DL_AI (CID_ID(0x803aU) | CID_FLAG) ++#define CID_DL_AICP (CID_ID(0x803bU) | CID_FLAG) ++#define CID_DL_AO (CID_ID(0x803cU) | CID_FLAG) ++#define CID_DL_AVFS (CID_ID(0x803dU) | CID_FLAG) ++#define CID_DL_CLOCK (CID_ID(0x803eU) | CID_FLAG) ++#define CID_DL_DFS (CID_ID(0x803fU) | CID_FLAG) ++#define CID_DL_DISKSCHED (CID_ID(0x8040U) | CID_FLAG) ++#define CID_DL_DMA (CID_ID(0x8041U) | CID_FLAG) ++#define CID_DL_ETH_IP3902 (CID_ID(0x8042U) | CID_FLAG) ++#define CID_DL_GPIO (CID_ID(0x8043U) | CID_FLAG) ++#define CID_DL_I2C (CID_ID(0x8044U) | CID_FLAG) ++#define CID_DL_IDE (CID_ID(0x8045U) | CID_FLAG) ++#define CID_DL_IDESTUB (CID_ID(0x8046U) | CID_FLAG) ++#define CID_DL_IIC (CID_ID(0x8047U) | CID_FLAG) ++#define CID_DL_IR (CID_ID(0x8048U) | CID_FLAG) ++#define CID_DL_MBS (CID_ID(0x8049U) | CID_FLAG) ++#define CID_DL_MBS2 (CID_ID(0x804aU) | CID_FLAG) ++#define CID_DL_NANDFLASH (CID_ID(0x804bU) | CID_FLAG) ++#define CID_DL_NORFLASH (CID_ID(0x804cU) | CID_FLAG) ++#define CID_DL_PCI (CID_ID(0x804dU) | CID_FLAG) ++#define CID_DL_PROCESSOR (CID_ID(0x804eU) | CID_FLAG) ++#define CID_DL_QTNR (CID_ID(0x804fU) | CID_FLAG) ++#define CID_DL_QVCP (CID_ID(0x8050U) | CID_FLAG) ++#define CID_DL_SEM (CID_ID(0x8051U) | CID_FLAG) ++#define CID_DL_SPDI (CID_ID(0x8052U) | CID_FLAG) ++#define CID_DL_SPDO (CID_ID(0x8053U) | CID_FLAG) ++#define CID_DL_TIMER (CID_ID(0x8054U) | CID_FLAG) ++#define CID_DL_TSDMA (CID_ID(0x8055U) | CID_FLAG) ++#define CID_DL_TSIO (CID_ID(0x8056U) | CID_FLAG) ++#define CID_DL_UDMA (CID_ID(0x8057U) | CID_FLAG) ++#define CID_DL_VID_MEAS (CID_ID(0x8058U) | CID_FLAG) ++#define CID_DL_VIP (CID_ID(0x8059U) | CID_FLAG) ++#define CID_DL_VMPG (CID_ID(0x805aU) | CID_FLAG) ++#define CID_DL_XIO (CID_ID(0x805bU) | CID_FLAG) ++#define CID_DRAWTEXT (CID_ID(0x805cU) | CID_FLAG) ++#define CID_DVPDEBUG (CID_ID(0x805dU) | CID_FLAG) ++#define CID_FATALERROR (CID_ID(0x805eU) | CID_FLAG) ++#define CID_FATALERROR_VT (CID_ID(0x805fU) | CID_FLAG) ++#define CID_FREADAVPROP (CID_ID(0x8060U) | CID_FLAG) ++#define CID_FWRITEAVPROP (CID_ID(0x8061U) | CID_FLAG) ++#define CID_HELP (CID_ID(0x8062U) | CID_FLAG) ++#define CID_HTTP_IO_DRIVER (CID_ID(0x8063U) | CID_FLAG) ++#define CID_HW_AICP (CID_ID(0x8064U) | CID_FLAG) ++#define CID_HW_CLOCK (CID_ID(0x8065U) | CID_FLAG) ++#define CID_HW_DMA (CID_ID(0x8066U) | CID_FLAG) ++#define CID_HW_DRAW (CID_ID(0x8067U) | CID_FLAG) ++#define CID_HW_DRAWCOMMON (CID_ID(0x8068U) | CID_FLAG) ++#define CID_HW_DRAWDE (CID_ID(0x8069U) | CID_FLAG) ++#define CID_HW_DRAWREF (CID_ID(0x806aU) | CID_FLAG) ++#define CID_HW_DRAWSHARED (CID_ID(0x806bU) | CID_FLAG) ++#define CID_HW_DRAWTMH (CID_ID(0x806cU) | CID_FLAG) ++#define CID_HW_DRAWTMT (CID_ID(0x806dU) | CID_FLAG) ++#define CID_HW_DRAWTMTH (CID_ID(0x806eU) | CID_FLAG) ++#define CID_HW_DSP (CID_ID(0x806fU) | CID_FLAG) ++#define CID_HW_ETH_IP3902 (CID_ID(0x8070U) | CID_FLAG) ++#define CID_HW_GIC (CID_ID(0x8071U) | CID_FLAG) ++#define CID_HW_GPIO (CID_ID(0x8072U) | CID_FLAG) ++#define CID_HW_I2C (CID_ID(0x8073U) | CID_FLAG) ++#define CID_HW_IIC (CID_ID(0x8074U) | CID_FLAG) ++#define CID_HW_MBS (CID_ID(0x8075U) | CID_FLAG) ++#define CID_HW_MMIARB (CID_ID(0x8076U) | CID_FLAG) ++#define CID_HW_MMIARB1010 (CID_ID(0x8077U) | CID_FLAG) ++#define CID_HW_PCI (CID_ID(0x8078U) | CID_FLAG) ++#define CID_HW_PIC (CID_ID(0x8079U) | CID_FLAG) ++#define CID_HW_SMC (CID_ID(0x807aU) | CID_FLAG) ++#define CID_HW_TSDMA (CID_ID(0x807bU) | CID_FLAG) ++#define CID_HW_UART (CID_ID(0x807cU) | CID_FLAG) ++#define CID_HW_UDMA (CID_ID(0x807dU) | CID_FLAG) ++#define CID_HW_VIP (CID_ID(0x807eU) | CID_FLAG) ++#define CID_HW_VMSP (CID_ID(0x807fU) | CID_FLAG) ++#define CID_HW_XIO (CID_ID(0x8080U) | CID_FLAG) ++#define CID_INFRA_MISC (CID_ID(0x8081U) | CID_FLAG) ++#define CID_INTERRUPT (CID_ID(0x8082U) | CID_FLAG) ++#define CID_IPC_DT (CID_ID(0x8083U) | CID_FLAG) ++#define CID_IPC_READ (CID_ID(0x8084U) | CID_FLAG) ++#define CID_IPC_RPC (CID_ID(0x8085U) | CID_FLAG) ++#define CID_IPC_WRITE (CID_ID(0x8086U) | CID_FLAG) ++#define CID_LIBLOAD_TM (CID_ID(0x8087U) | CID_FLAG) ++#define CID_MEMDBG (CID_ID(0x8088U) | CID_FLAG) ++#define CID_MENU (CID_ID(0x8089U) | CID_FLAG) ++#define CID_MP4READ (CID_ID(0x808aU) | CID_FLAG) ++#define CID_MPEGCOLORBAR (CID_ID(0x808bU) | CID_FLAG) ++#define CID_NETSTACK_FUSION (CID_ID(0x808cU) | CID_FLAG) ++#define CID_NETSTACK_TARGET_TCP (CID_ID(0x808dU) | CID_FLAG) ++#define CID_NETSTACK_UPNP_ALLEGRO (CID_ID(0x808dU) | CID_FLAG) ++#define CID_NETSTACK_UPNP_INTEL (CID_ID(0x808eU) | CID_FLAG) ++#define CID_NETWORKREAD (CID_ID(0x8090U) | CID_FLAG) ++#define CID_NM_COMMON (CID_ID(0x8091U) | CID_FLAG) ++#define CID_NM_DEI (CID_ID(0x8092U) | CID_FLAG) ++#define CID_NM_EST (CID_ID(0x8093U) | CID_FLAG) ++#define CID_NM_QFD (CID_ID(0x8094U) | CID_FLAG) ++#define CID_NM_UPC (CID_ID(0x8095U) | CID_FLAG) ++#define CID_NM_UPC_SPIDER (CID_ID(0x8096U) | CID_FLAG) ++#define CID_OS (CID_ID(0x8097U) | CID_FLAG) ++#define CID_PROBE (CID_ID(0x8098U) | CID_FLAG) ++#define CID_PSIUTIL (CID_ID(0x8099U) | CID_FLAG) ++#define CID_REALNETWORKS_ENGINE (CID_ID(0x809aU) | CID_FLAG) ++#define CID_SCAN_RATE_CONV_VSYS_TV (CID_ID(0x809bU) | CID_FLAG) ++#define CID_SPOSAL (CID_ID(0x809cU) | CID_FLAG) ++#define CID_TIMEDOCTOR (CID_ID(0x809dU) | CID_FLAG) ++#define CID_TSA_CLOCK (CID_ID(0x809eU) | CID_FLAG) ++ ++#define CID_TST_AVETC_SINK (CID_ID(0x80a0U) | CID_FLAG) ++#define CID_TST_DEMUX (CID_ID(0x80a1U) | CID_FLAG) ++#define CID_TST_DEMUX_FOR_MUX (CID_ID(0x80a2U) | CID_FLAG) ++#define CID_TST_SPTS_SINK (CID_ID(0x80a3U) | CID_FLAG) ++#define CID_TTI_UTIL (CID_ID(0x80a4U) | CID_FLAG) ++#define CID_UART (CID_ID(0x80a5U) | CID_FLAG) ++#define CID_UPCONV100MC (CID_ID(0x80a6U) | CID_FLAG) ++#define CID_UTILCPIREC (CID_ID(0x80a7U) | CID_FLAG) ++#define CID_UTILCRYPTRIJNDAEL (CID_ID(0x80a8U) | CID_FLAG) ++#define CID_VATV (CID_ID(0x80a9U) | CID_FLAG) ++#define CID_VATV_TR (CID_ID(0x80aaU) | CID_FLAG) ++#define CID_VBI_INSERT_VSYS_TV (CID_ID(0x80abU) | CID_FLAG) ++#define CID_VCAP_VIP2 (CID_ID(0x80acU) | CID_FLAG) ++#define CID_VDEC_BMP (CID_ID(0x80adU) | CID_FLAG) ++#define CID_VDEC_DIVX (CID_ID(0x80aeU) | CID_FLAG) ++#define CID_VDEC_GIF (CID_ID(0x80afU) | CID_FLAG) ++#define CID_VDEC_JPEG (CID_ID(0x80b0U) | CID_FLAG) ++#define CID_VDEC_JPEG2K (CID_ID(0x80b1U) | CID_FLAG) ++#define CID_VDEC_MP (CID_ID(0x80b2U) | CID_FLAG) ++#define CID_VDECMPEG4 (CID_ID(0x80b3U) | CID_FLAG) ++#define CID_VENC_MPEG4 (CID_ID(0x80b4U) | CID_FLAG) ++#define CID_VENCMJPEG (CID_ID(0x80b5U) | CID_FLAG) ++#define CID_VENCMPEG2 (CID_ID(0x80b6U) | CID_FLAG) ++#define CID_VIDEOUTIL (CID_ID(0x80b7U) | CID_FLAG) ++#define CID_VPACK (CID_ID(0x80b8U) | CID_FLAG) ++#define CID_VPIP_REC_PLAY (CID_ID(0x80b9U) | CID_FLAG) ++#define CID_VPOST_ICP (CID_ID(0x80baU) | CID_FLAG) ++#define CID_VREND_VCP (CID_ID(0x80bbU) | CID_FLAG) ++#define CID_VRENDVO (CID_ID(0x80bcU) | CID_FLAG) ++#define CID_VSCHED (CID_ID(0x80bdU) | CID_FLAG) ++#define CID_VTBLBASE (CID_ID(0x80beU) | CID_FLAG) ++#define CID_VTRANS_MBS2 (CID_ID(0x80bfU) | CID_FLAG) ++#define CID_VTRANS_QTNR (CID_ID(0x80c0U) | CID_FLAG) ++#define CID_VXWORKS_BSP (CID_ID(0x80c1U) | CID_FLAG) ++#define CID_WREAD (CID_ID(0x80c2U) | CID_FLAG) ++#define CID_CONNMGR_ATV (CID_ID(0x80c3U) | CID_FLAG) ++#define CID_DL_VPK (CID_ID(0x80c4U) | CID_FLAG) ++#define CID_VTRANS_VPK (CID_ID(0x80c5U) | CID_FLAG) ++#define CID_DL_VIP2 (CID_ID(0x80c6U) | CID_FLAG) ++#define CID_VX_GEN_UART (CID_ID(0x80c7U) | CID_FLAG) ++#define CID_VX_GPIO (CID_ID(0x80c8U) | CID_FLAG) ++#define CID_VX_GEN_TIMER (CID_ID(0x80c9U) | CID_FLAG) ++#define CID_M4VENC_DIS (CID_ID(0x80caU) | CID_FLAG) ++#define CID_VENC_ANA (CID_ID(0x80cbU) | CID_FLAG) ++#define CID_BSL_VENC_ANA (CID_ID(0x80ccU) | CID_FLAG) ++#define CID_BSL_VENC_ANA_EXT (CID_ID(0x80cdU) | CID_FLAG) ++#define CID_BSL_VENC_ANAVBI_EXT (CID_ID(0x80ceU) | CID_FLAG) ++#define CID_CMDX (CID_ID(0x80cfU) | CID_FLAG) ++#define CID_LL_GPIO (CID_ID(0x80d0U) | CID_FLAG) ++#define CID_LL_KEYPAD (CID_ID(0x80d1U) | CID_FLAG) ++#define CID_LL_TIMER (CID_ID(0x80d2U) | CID_FLAG) ++#define CID_LL_SPI (CID_ID(0x80d3U) | CID_FLAG) ++#define CID_LL_UART (CID_ID(0x80d4U) | CID_FLAG) ++#define CID_LL_I2C (CID_ID(0x80d5U) | CID_FLAG) ++#define CID_LL_TR (CID_ID(0x80d6U) | CID_FLAG) ++#define CID_HW_KEYPAD (CID_ID(0x80d7U) | CID_FLAG) ++#define CID_HW_TIMER (CID_ID(0x80d8U) | CID_FLAG) ++#define CID_HW_SPI (CID_ID(0x80d9U) | CID_FLAG) ++#define CID_HW_VATV_IOSYNC (CID_ID(0x80daU) | CID_FLAG) ++#define CID_DL_VO (CID_ID(0x80dbU) | CID_FLAG) ++#define CID_DL_LVDS (CID_ID(0x80dcU) | CID_FLAG) ++#define CID_HW_DDR2031 (CID_ID(0x80ddU) | CID_FLAG) ++#define CID_BSL_PHY (CID_ID(0x80deU) | CID_FLAG) ++#define CID_ETH_TTCP (CID_ID(0x80dfU) | CID_FLAG) ++#define CID_CDIGADEC_MP3PRO (CID_ID(0x80e0U) | CID_FLAG) ++#define CID_CID3EXTR (CID_ID(0x80e1U) | CID_FLAG) ++#define CID_IMAGEDEC_JPEG (CID_ID(0x80e2U) | CID_FLAG) ++#define CID_CURLSRC_MP3PRO (CID_ID(0x80e3U) | CID_FLAG) ++#define CID_CURLSRC_IMAGEDEC (CID_ID(0x80e4U) | CID_FLAG) ++#define CID_DVP_MAIN (CID_ID(0x80e5U) | CID_FLAG) ++#define CID_TMMAN32 (CID_ID(0x80e6U) | CID_FLAG) ++#define CID_TMMAN_CRT (CID_ID(0x80e7U) | CID_FLAG) ++#define CID_UHS_HAL_PCI (CID_ID(0x80e8U) | CID_FLAG) ++#define CID_UHS_OSAL_VXWORKS (CID_ID(0x80e9U) | CID_FLAG) ++#define CID_UHS_OSAL_PSOS (CID_ID(0x80eaU) | CID_FLAG) ++#define CID_UHS_USBD (CID_ID(0x80ebU) | CID_FLAG) ++#define CID_UHS_RBC (CID_ID(0x80ecU) | CID_FLAG) ++#define CID_UHS_UFI (CID_ID(0x80edU) | CID_FLAG) ++#define CID_UHS_SCSI (CID_ID(0x80eeU) | CID_FLAG) ++#define CID_UHS_PRINTER (CID_ID(0x80efU) | CID_FLAG) ++#define CID_UHS_MOUSE (CID_ID(0x80f0U) | CID_FLAG) ++#define CID_UHS_KEYBOARD (CID_ID(0x80f1U) | CID_FLAG) ++#define CID_UHS_HUB (CID_ID(0x80f2U) | CID_FLAG) ++#define CID_UHS_HCD_1561 (CID_ID(0x80f3U) | CID_FLAG) ++#define CID_CLEANUP (CID_ID(0x80f4U) | CID_FLAG) ++#define CID_ALLOCATOR (CID_ID(0x80f5U) | CID_FLAG) ++#define CID_TCS_CORE_LIBDEV (CID_ID(0x80f6U) | CID_FLAG) ++#define CID_VDI_VDO_ROUTER (CID_ID(0x80f7U) | CID_FLAG) ++#define CID_CONNMGR_ATSC (CID_ID(0x80f8U) | CID_FLAG) ++#define CID_ASPDIF (CID_ID(0x80f9U) | CID_FLAG) ++#define CID_APLL (CID_ID(0x80faU) | CID_FLAG) ++#define CID_ATVPLFINSTVIN (CID_ID(0x80fbU) | CID_FLAG) ++#define CID_ATV_PLF (CID_ID(0x80fcU) | CID_FLAG) ++#define CID_DL_WATCHDOG (CID_ID(0x80fdU) | CID_FLAG) ++#define CID_WMT_NET_READER (CID_ID(0x80feU) | CID_FLAG) ++#define CID_DL_FGPO (CID_ID(0x80ffU) | CID_FLAG) ++#define CID_DL_FGPI (CID_ID(0x8100U) | CID_FLAG) ++#define CID_WMT_DECODER (CID_ID(0x8101U) | CID_FLAG) ++#define CID_HAD_DRV_IIC (CID_ID(0x8102U) | CID_FLAG) ++#define CID_HAD_DRV_GPIO (CID_ID(0x8103U) | CID_FLAG) ++#define CID_HAD_GLOBAL (CID_ID(0x8104U) | CID_FLAG) ++#define CID_HAD_SMM (CID_ID(0x8105U) | CID_FLAG) ++#define CID_HAD_DRV_CSM (CID_ID(0x8106U) | CID_FLAG) ++#define CID_CARACASWDOG (CID_ID(0x8107U) | CID_FLAG) ++#define CID_CARACASADC (CID_ID(0x8108U) | CID_FLAG) ++#define CID_CARACASDMA (CID_ID(0x8109U) | CID_FLAG) ++#define CID_CARACASFLASHCTRL (CID_ID(0x810aU) | CID_FLAG) ++#define CID_CARACASGPTIMER (CID_ID(0x810bU) | CID_FLAG) ++#define CID_CARACASGPIO (CID_ID(0x810cU) | CID_FLAG) ++#define CID_CARACASI2CMO (CID_ID(0x810dU) | CID_FLAG) ++#define CID_CARACASI2CMS (CID_ID(0x810eU) | CID_FLAG) ++#define CID_CARACASRTC (CID_ID(0x810fU) | CID_FLAG) ++#define CID_CARACASSPI (CID_ID(0x8110U) | CID_FLAG) ++#define CID_CARACASTIMER (CID_ID(0x8111U) | CID_FLAG) ++#define CID_CARACASUART (CID_ID(0x8112U) | CID_FLAG) ++#define CID_TSSA40 (CID_ID(0x8113U) | CID_FLAG) ++#define CID_PACKET_POOL (CID_ID(0x8114U) | CID_FLAG) ++#define CID_TSSA15_WRAPPER (CID_ID(0x8115U) | CID_FLAG) ++#define CID_TASK_SYNC (CID_ID(0x8116U) | CID_FLAG) ++#define CID_TASK_CONDITION (CID_ID(0x8117U) | CID_FLAG) ++#define CID_PACKET_QUEUE (CID_ID(0x8118U) | CID_FLAG) ++#define CID_CONNECTION_TOOLKIT (CID_ID(0x8119U) | CID_FLAG) ++#define CID_TSSA16 (CID_ID(0x811aU) | CID_FLAG) ++#define CID_UDSDFU (CID_ID(0x811bU) | CID_FLAG) ++#define CID_BTH (CID_ID(0x811cU) | CID_FLAG) ++#define CID_DCDIP9021 (CID_ID(0x811dU) | CID_FLAG) ++#define CID_DCDIP3501V1X (CID_ID(0x811eU) | CID_FLAG) ++#define CID_ISP1581 (CID_ID(0x811fU) | CID_FLAG) ++#define CID_DCSS_TV (CID_ID(0x8120U) | CID_FLAG) ++#define CID_DCSS_MON (CID_ID(0x8121U) | CID_FLAG) ++#define CID_DCSS_RSC_PC (CID_ID(0x8122U) | CID_FLAG) ++#define CID_DCSS_RSC_INT (CID_ID(0x8123U) | CID_FLAG) ++#define CID_DCSS_RSC_EXT (CID_ID(0x8124U) | CID_FLAG) ++#define CID_DCSS_LIT (CID_ID(0x8125U) | CID_FLAG) ++#define CID_DCSS_LIT_C (CID_ID(0x8126U) | CID_FLAG) ++#define CID_DCSS_45A (CID_ID(0x8127U) | CID_FLAG) ++#define CID_UDSCORE (CID_ID(0x8128U) | CID_FLAG) ++#define CID_HW_AUDIO7135 (CID_ID(0x8129U) | CID_FLAG) ++#define CID_DL_AUDIO3X (CID_ID(0x812aU) | CID_FLAG) ++#define CID_REGACC (CID_ID(0x812bU) | CID_FLAG) ++#define CID_HW_MJPEG (CID_ID(0x812cU) | CID_FLAG) ++#define CID_ISP1582 (CID_ID(0x812dU) | CID_FLAG) ++#define CID_MUTI (CID_ID(0x812eU) | CID_FLAG) ++#define CID_CHANNEL_DECODER_ENCODER (CID_ID(0x812fU) | CID_FLAG) ++#define CID_RESMGR (CID_ID(0x8130U) | CID_FLAG) ++#define CID_WIDGET (CID_ID(0x8131U) | CID_FLAG) ++#define CID_FB (CID_ID(0x8132U) | CID_FLAG) ++#define CID_GFX (CID_ID(0x8133U) | CID_FLAG) ++#define CID_HPS_DISPATCHER (CID_ID(0x8134U) | CID_FLAG) ++#define CID_DL_PLXGPIO (CID_ID(0x8135U) | CID_FLAG) ++#define CID_HW_PLXGPIO (CID_ID(0x8136U) | CID_FLAG) ++#define CID_DL_PLXPHI (CID_ID(0x8137U) | CID_FLAG) ++#define CID_HW_PLXPHI_EVALUATOR (CID_ID(0x8138U) | CID_FLAG) ++#define CID_DL_SCALER (CID_ID(0x8139U) | CID_FLAG) ++#define CID_EFM (CID_ID(0x813aU) | CID_FLAG) ++#define CID_HW_TUNER_FM1236MK3 (CID_ID(0x813bU) | CID_FLAG) ++#define CID_HW_TUNER_FM1216MK3 (CID_ID(0x813cU) | CID_FLAG) ++#define CID_HW_TUNER_FM1216MK2 (CID_ID(0x813dU) | CID_FLAG) ++#define CID_ANALOG_CHANNEL_TABLE (CID_ID(0x813eU) | CID_FLAG) ++#define CID_TUNER_CONTROL (CID_ID(0x813fU) | CID_FLAG) ++#define CID_DL_UIMS (CID_ID(0x8140U) | CID_FLAG) ++#define CID_DL_RCTRANSMITTER (CID_ID(0x8141U) | CID_FLAG) ++#define CID_HW_CST_RCRECEIVER (CID_ID(0x8142U) | CID_FLAG) ++#define CID_HW_CST_RCTRANSMITTER (CID_ID(0x8143U) | CID_FLAG) ++#define CID_DCDIP3506 (CID_ID(0x8144U) | CID_FLAG) ++#define CID_DCDIP3501V2X (CID_ID(0x8145U) | CID_FLAG) ++#define CID_MTV_COORD (CID_ID(0x8146U) | CID_FLAG) ++#define CID_MTV_IMG_ROT_CTRL (CID_ID(0x8147U) | CID_FLAG) ++#define CID_TFE_TRACE (CID_ID(0x8148U) | CID_FLAG) ++#define CID_TMCAL_SERVER (CID_ID(0x8149U) | CID_FLAG) ++#define CID_BOOT_LOADER (CID_ID(0x814aU) | CID_FLAG) ++#define CID_TD_SAVE_DATA (CID_ID(0x814bU) | CID_FLAG) ++#define CID_TFE_TRACE_PROCESS_DATA (CID_ID(0x814cU) | CID_FLAG) ++#define CID_VIDEOCTRL (CID_ID(0x814dU) | CID_FLAG) ++#define CID_BOOT (CID_ID(0x814eU) | CID_FLAG) ++#define CID_EVENT (CID_ID(0x814fU) | CID_FLAG) ++#define CID_USERINPUT (CID_ID(0x8150U) | CID_FLAG) ++#define CID_BSL_TUNER (CID_ID(0x8151U) | CID_FLAG) ++#define CID_P5KIIC (CID_ID(0x8152U) | CID_FLAG) ++#define CID_HW_PMANSECURITY (CID_ID(0x8153U) | CID_FLAG) ++#define CID_DRM_DIVX (CID_ID(0x8154U) | CID_FLAG) ++#define CID_TMHWVIDEODEC7136 (CID_ID(0x8155U) | CID_FLAG) ++#define CID_TMDLVIDEODEC (CID_ID(0x8156U) | CID_FLAG) ++#define CID_OSD_KERNEL (CID_ID(0x8157U) | CID_FLAG) ++#define CID_HW_DCSNETWORK (CID_ID(0x8158U) | CID_FLAG) ++#define CID_DL_RCRECEIVER (CID_ID(0x8159U) | CID_FLAG) ++#define CID_INT (CID_ID(0x815aU) | CID_FLAG) ++#define CID_RTC (CID_ID(0x815bU) | CID_FLAG) ++#define CID_TIMER (CID_ID(0x815cU) | CID_FLAG) ++#define CID_IPC (CID_ID(0x815dU) | CID_FLAG) ++#define CID_P5KTELETEXT (CID_ID(0x815eU) | CID_FLAG) ++#define CID_P5KAUDIOVIDEO (CID_ID(0x815fU) | CID_FLAG) ++#define CID_P5KCONFIG (CID_ID(0x8160U) | CID_FLAG) ++#define CID_HW_CST_TRANSPSTREAMIN (CID_ID(0x8161U) | CID_FLAG) ++#define CID_HOMER_KERNEL (CID_ID(0x8162U) | CID_FLAG) ++#define CID_HOMER_DRIVER (CID_ID(0x8163U) | CID_FLAG) ++#define CID_CD_FILE_SYSTEM (CID_ID(0x8164U) | CID_FLAG) ++#define CID_COBALT_APP (CID_ID(0x8165U) | CID_FLAG) ++#define CID_COBALT_UI (CID_ID(0x8166U) | CID_FLAG) ++#define CID_CD_SERVO (CID_ID(0x8167U) | CID_FLAG) ++#define CID_CD_UTILS (CID_ID(0x8168U) | CID_FLAG) ++#define CID_COBALT_SYSTEM (CID_ID(0x8169U) | CID_FLAG) ++#define CID_CDSLIM (CID_ID(0x816aU) | CID_FLAG) ++#define CID_CD_DATABASE (CID_ID(0x816bU) | CID_FLAG) ++#define CID_CANAVENC (CID_ID(0x816cU) | CID_FLAG) ++#define CID_CANTIAGING (CID_ID(0x816dU) | CID_FLAG) ++#define CID_CAUTOPICTCTRL (CID_ID(0x816eU) | CID_FLAG) ++#define CID_CBBARCTRL (CID_ID(0x816fU) | CID_FLAG) ++#define CID_CBBARDET (CID_ID(0x8170U) | CID_FLAG) ++#define CID_CBBARDETEXT (CID_ID(0x8171U) | CID_FLAG) ++#define CID_CBLEVELDETEXT (CID_ID(0x8172U) | CID_FLAG) ++#define CID_CCOLENH (CID_ID(0x8173U) | CID_FLAG) ++#define CID_CCOLENHEXT (CID_ID(0x8174U) | CID_FLAG) ++#define CID_CCONTRESEXT (CID_ID(0x8175U) | CID_FLAG) ++#define CID_CCTI (CID_ID(0x8176U) | CID_FLAG) ++#define CID_CCTIEXT (CID_ID(0x8177U) | CID_FLAG) ++#define CID_CDNR (CID_ID(0x8178U) | CID_FLAG) ++#define CID_CDNREXT (CID_ID(0x8179U) | CID_FLAG) ++#define CID_CGAMMAEXT (CID_ID(0x817aU) | CID_FLAG) ++#define CID_CHISTOMEASEXT (CID_ID(0x817bU) | CID_FLAG) ++#define CID_CHISTOMOD (CID_ID(0x817cU) | CID_FLAG) ++#define CID_CHISTOMODEXT (CID_ID(0x817dU) | CID_FLAG) ++#define CID_CMBSXRAY (CID_ID(0x817eU) | CID_FLAG) ++#define CID_CNOISE (CID_ID(0x817fU) | CID_FLAG) ++#define CID_CNOISEESTEXT (CID_ID(0x8180U) | CID_FLAG) ++#define CID_CPFSPD (CID_ID(0x8181U) | CID_FLAG) ++#define CID_CQVCPXRAY (CID_ID(0x8182U) | CID_FLAG) ++#define CID_CSCANRATECONV (CID_ID(0x8183U) | CID_FLAG) ++#define CID_CSCANRATECONVEXT (CID_ID(0x8184U) | CID_FLAG) ++#define CID_CSHARPENH (CID_ID(0x8185U) | CID_FLAG) ++#define CID_CSHARPENHEXT (CID_ID(0x8186U) | CID_FLAG) ++#define CID_CSHARPMEAS (CID_ID(0x8187U) | CID_FLAG) ++#define CID_CSHARPMEASEXT (CID_ID(0x8188U) | CID_FLAG) ++#define CID_CSYNCTAG (CID_ID(0x8189U) | CID_FLAG) ++#define CID_CUVBWDETEXT (CID_ID(0x818aU) | CID_FLAG) ++#define CID_CVBISLICE (CID_ID(0x818bU) | CID_FLAG) ++#define CID_CVFEAT (CID_ID(0x818cU) | CID_FLAG) ++#define CID_CVFEAT2 (CID_ID(0x818dU) | CID_FLAG) ++#define CID_CVIPXRAY (CID_ID(0x818eU) | CID_FLAG) ++#define CID_CVIPXRAYDITHER (CID_ID(0x818fU) | CID_FLAG) ++#define CID_CVMIX (CID_ID(0x8190U) | CID_FLAG) ++#define CID_CVTRSCALEEXT (CID_ID(0x8191U) | CID_FLAG) ++#define CID_CVTRANTIAGING (CID_ID(0x8192U) | CID_FLAG) ++#define CID_CVTRFADEVCP (CID_ID(0x8193U) | CID_FLAG) ++#define CID_CVTRSCALEMBSVCP (CID_ID(0x8194U) | CID_FLAG) ++#define CID_CVTRSTROBEMBS (CID_ID(0x8195U) | CID_FLAG) ++#define CID_NM_UTILS (CID_ID(0x8196U) | CID_FLAG) ++#define CID_VSEQSCHEDENGINE (CID_ID(0x8197U) | CID_FLAG) ++#define CID_VCPSCHEDENGINE (CID_ID(0x8198U) | CID_FLAG) ++#define CID_VGENTEST (CID_ID(0x8199U) | CID_FLAG) ++#define CID_VMENU (CID_ID(0x819aU) | CID_FLAG) ++#define CID_VPROCCOMMON (CID_ID(0x819bU) | CID_FLAG) ++#define CID_VPROCTV (CID_ID(0x819cU) | CID_FLAG) ++#define CID_VPROCTV505E (CID_ID(0x819dU) | CID_FLAG) ++#define CID_SCHEDENGINE (CID_ID(0x819eU) | CID_FLAG) ++#define CID_VSLNMCOMMON (CID_ID(0x819fU) | CID_FLAG) ++#define CID_VSLVCAPVIP (CID_ID(0x81a0U) | CID_FLAG) ++#define CID_VSLVCAPVIPVBI (CID_ID(0x81a1U) | CID_FLAG) ++#define CID_VSLVINCONVERT (CID_ID(0x81a2U) | CID_FLAG) ++#define CID_VSLIOSYNC (CID_ID(0x81a3U) | CID_FLAG) ++#define CID_VSLVRENDVCP (CID_ID(0x81a4U) | CID_FLAG) ++#define CID_VSLVRENDVCPVBI (CID_ID(0x81a5U) | CID_FLAG) ++#define CID_VSLSYNCTAG (CID_ID(0x81a6U) | CID_FLAG) ++#define CID_VSLVTRANSMBS (CID_ID(0x81a7U) | CID_FLAG) ++#define CID_VSLVTRANSNM (CID_ID(0x81a8U) | CID_FLAG) ++#define CID_VSLVTRANSQTNR (CID_ID(0x81a9U) | CID_FLAG) ++#define CID_VSLVTRANSSWTNR (CID_ID(0x81aaU) | CID_FLAG) ++#define CID_VTRANSSWTNR (CID_ID(0x81abU) | CID_FLAG) ++#define CID_LL_DMA (CID_ID(0x81acU) | CID_FLAG) ++#define CID_BSL_PNX8550 (CID_ID(0x81adU) | CID_FLAG) ++#define CID_BSL_PNX1500 (CID_ID(0x81aeU) | CID_FLAG) ++#define CID_BSL_NULL (CID_ID(0x81afU) | CID_FLAG) ++#define CID_BSL_PNX2015 (CID_ID(0x81b0U) | CID_FLAG) ++#define CID_HW_SCALER7136 (CID_ID(0x81b1U) | CID_FLAG) ++#define CID_SPI_IP3409 (CID_ID(0x81b2U) | CID_FLAG) ++#define CID_SPI_3409 (CID_ID(0x81b3U) | CID_FLAG) ++#define CID_SPISD_3409 (CID_ID(0x81b4U) | CID_FLAG) ++#define CID_CONNMGRMP4RTPPLAYER (CID_ID(0x81b5U) | CID_FLAG) ++#define CID_DL_NANDFLASH2 (CID_ID(0x81b6U) | CID_FLAG) ++#define CID_HW_HOSTIF (CID_ID(0x81b7U) | CID_FLAG) ++#define CID_LL_HOSTIF (CID_ID(0x81b8U) | CID_FLAG) ++#define CID_LL_MJPEG (CID_ID(0x81b9U) | CID_FLAG) ++#define CID_HW_SENSORIF (CID_ID(0x81baU) | CID_FLAG) ++#define CID_LL_SENSORIF (CID_ID(0x81bbU) | CID_FLAG) ++#define CID_HW_ECSP (CID_ID(0x81bcU) | CID_FLAG) ++#define CID_LL_ECSP (CID_ID(0x81bdU) | CID_FLAG) ++#define CID_HW_DOWNSCALER (CID_ID(0x81beU) | CID_FLAG) ++#define CID_LL_DOWNSCALER (CID_ID(0x81bfU) | CID_FLAG) ++#define CID_HW_UPSCALER (CID_ID(0x81c0U) | CID_FLAG) ++#define CID_LL_UPSCALER (CID_ID(0x81c1U) | CID_FLAG) ++#define CID_HW_JITTEREX (CID_ID(0x81c2U) | CID_FLAG) ++#define CID_LL_JITTEREX (CID_ID(0x81c3U) | CID_FLAG) ++#define CID_HW_NOISERED (CID_ID(0x81c4U) | CID_FLAG) ++#define CID_LL_NOISERED (CID_ID(0x81c5U) | CID_FLAG) ++#define CID_HW_JPEGENCODER (CID_ID(0x81c6U) | CID_FLAG) ++#define CID_LL_JPEGENCODER (CID_ID(0x81c7U) | CID_FLAG) ++#define CID_HW_FLASHLIGHT (CID_ID(0x81c8U) | CID_FLAG) ++#define CID_LL_FLASHLIGHT (CID_ID(0x81c9U) | CID_FLAG) ++#define CID_HW_TVCONVERTER (CID_ID(0x81caU) | CID_FLAG) ++#define CID_LL_TVCONVERTER (CID_ID(0x81cbU) | CID_FLAG) ++#define CID_HW_DVDOMATRIX (CID_ID(0x81ccU) | CID_FLAG) ++#define CID_LL_DVDOMATRIX (CID_ID(0x81cdU) | CID_FLAG) ++#define CID_HW_CLCD (CID_ID(0x81ceU) | CID_FLAG) ++#define CID_LL_CLCD (CID_ID(0x81cfU) | CID_FLAG) ++#define CID_HW_VDE (CID_ID(0x81d0U) | CID_FLAG) ++#define CID_LL_VDE (CID_ID(0x81d1U) | CID_FLAG) ++#define CID_HW_MCSPI (CID_ID(0x81d2U) | CID_FLAG) ++#define CID_LL_MCSPI (CID_ID(0x81d3U) | CID_FLAG) ++#define CID_HW_PWM (CID_ID(0x81d4U) | CID_FLAG) ++#define CID_LL_PWM (CID_ID(0x81d5U) | CID_FLAG) ++#define CID_OSAL_NXM (CID_ID(0x81d6U) | CID_FLAG) ++#define CID_MEMPROF (CID_ID(0x81d7U) | CID_FLAG) ++#define CID_ALCONSTRETCH (CID_ID(0x81d8U) | CID_FLAG) ++#define CID_AUTOFOCUS (CID_ID(0x81d9U) | CID_FLAG) ++#define CID_LL_DVDO2DTL (CID_ID(0x81daU) | CID_FLAG) ++#define CID_HW_DVDO2DTL (CID_ID(0x81dbU) | CID_FLAG) ++#define CID_LL_DTL2DVDO (CID_ID(0x81dcU) | CID_FLAG) ++#define CID_HW_DTL2DVDO (CID_ID(0x81ddU) | CID_FLAG) ++#define CID_LL_COLORMATRIX (CID_ID(0x81deU) | CID_FLAG) ++#define CID_HW_COLORMATRIX (CID_ID(0x81dfU) | CID_FLAG) ++#define CID_UHSPDIFOUT_ASYSATV (CID_ID(0x81e0U) | CID_FLAG) ++#define CID_DL_NANDFLASH1 (CID_ID(0x81e1U) | CID_FLAG) ++#define CID_NANDBOOTFFS (CID_ID(0x81e2U) | CID_FLAG) ++#define CID_CONNMGR_APROCTV (CID_ID(0x81e3U) | CID_FLAG) ++#define CID_CONNMGRSTILLPLAYER (CID_ID(0x81e4U) | CID_FLAG) ++#define CID_CONNMGRAUDIOPLAYER (CID_ID(0x81e5U) | CID_FLAG) ++#define CID_DCDIP9028 (CID_ID(0x81e6U) | CID_FLAG) ++#define CID_CURLSRC_AUDIO (CID_ID(0x81e7U) | CID_FLAG) ++#define CID_CONNMGRAVIMP4PLAYER (CID_ID(0x81e8U) | CID_FLAG) ++#define CID_AUDIOVIDEOSYNC (CID_ID(0x81e9U) | CID_FLAG) ++#define CID_PACKETLIST (CID_ID(0x81eaU) | CID_FLAG) ++#define CID_ASYNCSINK (CID_ID(0x81ebU) | CID_FLAG) ++#define CID_VSYNCSINK (CID_ID(0x81ecU) | CID_FLAG) ++#define CID_XSYNCSINK (CID_ID(0x81edU) | CID_FLAG) ++#define CID_PCIEXP (CID_ID(0x81eeU) | CID_FLAG) ++#define CID_SOD_KERNEL (CID_ID(0x81efU) | CID_FLAG) ++#define CID_SOD_EMULATE (CID_ID(0x81f0U) | CID_FLAG) ++#define CID_SOD_MGR (CID_ID(0x81f1U) | CID_FLAG) ++#define CID_NANDPARTTABLE (CID_ID(0x81f2U) | CID_FLAG) ++#define CID_HW_AUDIO7136 (CID_ID(0x81f3U) | CID_FLAG) ++#define CID_SPI3409 (CID_ID(0x81f4U) | CID_FLAG) ++#define CID_DCSS_MATH (CID_ID(0x81f5U) | CID_FLAG) ++#define CID_DCSS_LIT_CSD (CID_ID(0x81f6U) | CID_FLAG) ++#define CID_DCSS_LIT_M (CID_ID(0x81f7U) | CID_FLAG) ++#define CID_ADT (CID_ID(0x81f8U) | CID_FLAG) ++#define CID_ACS (CID_ID(0x81f9U) | CID_FLAG) ++#define CID_ACB (CID_ID(0x81faU) | CID_FLAG) ++#define CID_ACL (CID_ID(0x81fbU) | CID_FLAG) ++#define CID_AVEPP (CID_ID(0x81fcU) | CID_FLAG) ++#define CID_UDSSIC (CID_ID(0x81fdU) | CID_FLAG) ++#define CID_PROXYI2C (CID_ID(0x81feU) | CID_FLAG) ++#define CID_PL081DMA (CID_ID(0x81feU) | CID_FLAG) ++#define CID_DD_CPIPE (CID_ID(0x81ffU) | CID_FLAG) ++#define CID_DD_MBVP (CID_ID(0x8200U) | CID_FLAG) ++#define CID_CARENDAOUT (CID_ID(0x8201U) | CID_FLAG) ++#define CID_CADIGAIN (CID_ID(0x8202U) | CID_FLAG) ++#define CID_CONNMGR_TV506E (CID_ID(0x8203U) | CID_FLAG) ++#define CID_ASYNCHANDLER (CID_ID(0x8204U) | CID_FLAG) ++#define CID_COMP_M4VENCPSC (CID_ID(0x8205U) | CID_FLAG) ++#define CID_CONNMGRNETSCHEMECONFIG (CID_ID(0x8206U) | CID_FLAG) ++#define CID_CARACASSPIAHB (CID_ID(0x8207U) | CID_FLAG) ++#define CID_COMP_ADECLPCM (CID_ID(0x8208U) | CID_FLAG) ++#define CID_CDIGADEC_MULTISTD (CID_ID(0x8209U) | CID_FLAG) ++#define CID_ADB (CID_ID(0x820aU) | CID_FLAG) ++#define CID_ADR (CID_ID(0x820bU) | CID_FLAG) ++#define CID_AGN (CID_ID(0x820cU) | CID_FLAG) ++#define CID_ANT (CID_ID(0x820dU) | CID_FLAG) ++#define CID_APP (CID_ID(0x820eU) | CID_FLAG) ++#define CID_ASC (CID_ID(0x820fU) | CID_FLAG) ++#define CID_ASM (CID_ID(0x8210U) | CID_FLAG) ++#define CID_ASS (CID_ID(0x8211U) | CID_FLAG) ++#define CID_ATP (CID_ID(0x8212U) | CID_FLAG) ++#define CID_VDEC_MJPEG (CID_ID(0x8213U) | CID_FLAG) ++#define CID_MOV_READ (CID_ID(0x8214U) | CID_FLAG) ++#define CID_EWIFI (CID_ID(0x8215U) | CID_FLAG) ++#define CID_SCR (CID_ID(0x8216U) | CID_FLAG) ++#define CID_AEPP (CID_ID(0x8217U) | CID_FLAG) ++#define CID_VEPP (CID_ID(0x8218U) | CID_FLAG) ++#define CID_MP3ENC (CID_ID(0x8219U) | CID_FLAG) ++#define CID_TDFLOADER (CID_ID(0x821aU) | CID_FLAG) ++#define CID_VIOSYNC (CID_ID(0x821bU) | CID_FLAG) ++#define CID_STBDP (CID_ID(0x821cU) | CID_FLAG) ++#define CID_STBEVENT (CID_ID(0x821dU) | CID_FLAG) ++#define CID_STBFB (CID_ID(0x821eU) | CID_FLAG) ++#define CID_STBDEMUX (CID_ID(0x821fU) | CID_FLAG) ++#define CID_STBFILE (CID_ID(0x8220U) | CID_FLAG) ++#define CID_STBGPIO (CID_ID(0x8221U) | CID_FLAG) ++#define CID_STBI2C (CID_ID(0x8222U) | CID_FLAG) ++#define CID_STBMMIOBUS (CID_ID(0x8223U) | CID_FLAG) ++#define CID_STBPROC (CID_ID(0x8224U) | CID_FLAG) ++#define CID_STBROOT (CID_ID(0x8225U) | CID_FLAG) ++#define CID_STBRPC (CID_ID(0x8226U) | CID_FLAG) ++#define CID_STBRTC (CID_ID(0x8227U) | CID_FLAG) ++#define CID_STBTMLOAD (CID_ID(0x8228U) | CID_FLAG) ++#define CID_STBSTREAMINGSYSTEM (CID_ID(0x8229U) | CID_FLAG) ++#define CID_STBVIDEOSCALER (CID_ID(0x822aU) | CID_FLAG) ++#define CID_STBANALOGBACKEND (CID_ID(0x822bU) | CID_FLAG) ++#define CID_STBVIDEORENDERER (CID_ID(0x822cU) | CID_FLAG) ++#define CID_DRV_MMU (CID_ID(0x822dU) | CID_FLAG) ++#define CID_COMP_AINJECTOR (CID_ID(0x822eU) | CID_FLAG) ++#define CID_VDEC_ANA (CID_ID(0x822fU) | CID_FLAG) ++#define CID_STBAC3AUD (CID_ID(0x8230U) | CID_FLAG) ++#define CID_STBAUDIO (CID_ID(0x8231U) | CID_FLAG) ++#define CID_PHMODARM11WRAPPER (CID_ID(0x8232U) | CID_FLAG) ++#define CID_GPIO_IP4004 (CID_ID(0x8233U) | CID_FLAG) ++#define CID_TMCADIGSPDIFIN (CID_ID(0x8234U) | CID_FLAG) ++#define CID_TMCARENDSPDIFOUT (CID_ID(0x8235U) | CID_FLAG) ++#define CID_TMCPLFINSTAIN (CID_ID(0x8236U) | CID_FLAG) ++#define CID_TMCPLFINSTAOUT (CID_ID(0x8237U) | CID_FLAG) ++#define CID_TMCSPDIFIN (CID_ID(0x8238U) | CID_FLAG) ++#define CID_TMCSPDIFOUT (CID_ID(0x8239U) | CID_FLAG) ++#define CID_BSL_HDMIRX (CID_ID(0x823aU) | CID_FLAG) ++#define CID_AACPENC (CID_ID(0x823bU) | CID_FLAG) ++#define CID_DL_HDMIRX (CID_ID(0x823cU) | CID_FLAG) ++#define CID_APP_HDMIRX (CID_ID(0x823dU) | CID_FLAG) ++#define CID_INFRA_HDMI (CID_ID(0x823eU) | CID_FLAG) ++#define CID_DL_HDMICEC (CID_ID(0x823fU) | CID_FLAG) ++#define CID_BSL_HDMITX (CID_ID(0x8240U) | CID_FLAG) ++#define CID_DL_HDMITX (CID_ID(0x8241U) | CID_FLAG) ++#define CID_APP_HDMITX (CID_ID(0x8242U) | CID_FLAG) ++ ++/*define CID_UART (CID_ID(0x80a5U) | CID_FLAG) already defined*/ ++#define CID_CHIP (CID_ID(0x815bU) | CID_FLAG) ++ ++#define CID_RESERVED (CID_ID(0xff80U) | CID_FLAG) ++/* ************************************************************************** */ ++/* Component Id's reserved for external organizations */ ++/* */ ++/* 0xff80 thru 0xffbf */ ++/* Range of component ID's is reserved for the use of parties outside of */ ++/* Philips that wish to use component ID's privately. */ ++/* If a component is going to be exchanged in the 'PS Ecosystem', then a */ ++/* public component ID should be registered with MoReUse. */ ++/* */ ++/* Range to be used by CE Television Systems */ ++/* 0xffc0 thru 0xffff */ ++/* */ ++/* ************************************************************************** */ ++ ++/* -------------------------------------------------------------------------- */ ++/* */ ++/* Component ID types are defined as unsigned 32 bit integers (UInt32) */ ++/* Interface ID types are defined as unsigned 32 bit integers (UInt32) */ ++/* */ ++/* -------------------------------------------------------------------------- */ ++ ++/* -------------------------------------------------------------------------- */ ++/* */ ++/* Obsolete Component ID values */ ++/* */ ++/* -------------------------------------------------------------------------- */ ++ ++/* -------------------------------------------------------------------------- */ ++/* Component Class definitions (bits 31:28, 4 bits) */ ++/* NOTE: A class of 0x0 must not be defined to ensure that the overall 32 bit */ ++/* component ID/status combination is always non-0 (no TM_OK conflict). */ ++/* -------------------------------------------------------------------------- */ ++#define CID_CLASS_BITSHIFT 28 ++#define CID_CLASS_BITMASK (0xFU << CID_CLASS_BITSHIFT) ++#define CID_GET_CLASS(compId) ((compId & CID_CLASS_BITMASK) >> CID_CLASS_BITSHIFT) ++ ++#define CID_CLASS_NONE (0x1U << CID_CLASS_BITSHIFT) ++#define CID_CLASS_VIDEO (0x2U << CID_CLASS_BITSHIFT) ++#define CID_CLASS_AUDIO (0x3U << CID_CLASS_BITSHIFT) ++#define CID_CLASS_GRAPHICS (0x4U << CID_CLASS_BITSHIFT) ++#define CID_CLASS_BUS (0x5U << CID_CLASS_BITSHIFT) ++#define CID_CLASS_INFRASTR (0x6U << CID_CLASS_BITSHIFT) ++ ++#define CID_CLASS_CUSTOMER (0xFU << CID_CLASS_BITSHIFT) ++ ++/* -------------------------------------------------------------------------- */ ++/* Component Type definitions (bits 27:24, 4 bits) */ ++/* -------------------------------------------------------------------------- */ ++#define CID_TYPE_BITSHIFT 24 ++#define CID_TYPE_BITMASK (0xFU << CID_TYPE_BITSHIFT) ++#define CID_GET_TYPE(compId) ((compId & CID_TYPE_BITMASK) >> CID_TYPE_BITSHIFT) ++ ++#define CID_TYPE_NONE (0x0U << CID_TYPE_BITSHIFT) ++#define CID_TYPE_SOURCE (0x1U << CID_TYPE_BITSHIFT) ++#define CID_TYPE_SINK (0x2U << CID_TYPE_BITSHIFT) ++#define CID_TYPE_ENCODER (0x3U << CID_TYPE_BITSHIFT) ++#define CID_TYPE_DECODER (0x4U << CID_TYPE_BITSHIFT) ++#define CID_TYPE_MUX (0x5U << CID_TYPE_BITSHIFT) ++#define CID_TYPE_DEMUX (0x6U << CID_TYPE_BITSHIFT) ++#define CID_TYPE_DIGITIZER (0x7U << CID_TYPE_BITSHIFT) ++#define CID_TYPE_RENDERER (0x8U << CID_TYPE_BITSHIFT) ++#define CID_TYPE_FILTER (0x9U << CID_TYPE_BITSHIFT) ++#define CID_TYPE_CONTROL (0xAU << CID_TYPE_BITSHIFT) ++#define CID_TYPE_DATABASE (0xBU << CID_TYPE_BITSHIFT) ++#define CID_TYPE_SUBSYSTEM (0xCU << CID_TYPE_BITSHIFT) ++#define CID_TYPE_CUSTOMER (0xFU << CID_TYPE_BITSHIFT) ++ ++/* -------------------------------------------------------------------------- */ ++/* Component Tag definitions (bits 23:16, 8 bits) */ ++/* NOTE: Component tags are defined in groups, dependent on the class and */ ++/* type. */ ++/* -------------------------------------------------------------------------- */ ++#define CID_TAG_BITSHIFT 16 ++#define CID_TAG_BITMASK (0xFFU << CID_TAG_BITSHIFT) ++ ++#define CID_TAG_NONE (0x00U << CID_TAG_BITSHIFT) ++ ++#define CID_TAG_CUSTOMER (0xE0U << CID_TAG_BITSHIFT) ++ ++#define TAG(number) ((number) << CID_TAG_BITSHIFT) ++ ++/* -------------------------------------------------------------------------- */ ++/* General Component Layer definitions (bits 15:12, 4 bits) */ ++/* -------------------------------------------------------------------------- */ ++#define CID_LAYER_BITSHIFT 12 ++#define CID_LAYER_BITMASK (0xF << CID_LAYER_BITSHIFT) ++#define CID_GET_LAYER(compId) ((compId & CID_LAYER_BITMASK) >> CID_LAYER_BITSHIFT) ++ ++#define CID_LAYER_NONE (0x0U << CID_LAYER_BITSHIFT) ++#define CID_LAYER_BTM (0x1U << CID_LAYER_BITSHIFT) ++#define CID_LAYER_HWAPI (0x2U << CID_LAYER_BITSHIFT) ++#define CID_LAYER_BSL (0x3U << CID_LAYER_BITSHIFT) ++#define CID_LAYER_DEVLIB (0x4U << CID_LAYER_BITSHIFT) ++#define CID_LAYER_TMAL (0x5U << CID_LAYER_BITSHIFT) ++#define CID_LAYER_TMOL (0x6U << CID_LAYER_BITSHIFT) ++#define CID_LAYER_TMNL (0xEU << CID_LAYER_BITSHIFT) ++ ++/* -------------------------------------------------------------------------- */ ++/* "new" i.e. after 2002-01-31 layer definitions */ ++/* "New" Component Layers depend on the component type and class */ ++/* So we can have an identical layer value for each type/class combination */ ++/* In order not to break existing code that assumes that layers are unique, */ ++/* we start new layers at 0x7 */ ++/* -------------------------------------------------------------------------- */ ++ ++/*------------------ CTYP_BUS_NOTYPE dependent layer definitions -------------*/ ++#define CID_LAYER_UDS (0x7U << CID_LAYER_BITSHIFT) /* USB Device Stack */ ++#define CID_LAYER_UHS (0x8U << CID_LAYER_BITSHIFT) /* USB Host stack */ ++#define CID_LAYER_UOTG (0x9U << CID_LAYER_BITSHIFT) /* USB OTG stack */ ++ ++#define CID_LAYER_CUSTOMER (0xFU << CID_LAYER_BITSHIFT) /* Customer Defined */ ++ ++/* -------------------------------------------------------------------------- */ ++/* Component Identifier definitions (bits 31:12, 20 bits) */ ++/* NOTE: These DVP platform component identifiers are designed to be unique */ ++/* within the system. The component identifier encompasses the class */ ++/* (CID_CLASS_XXX), type (CID_TYPE_XXX), tag, and layer (CID_LAYER_XXX) */ ++/* fields to form the unique component identifier. This allows any */ ++/* error/progress status value to be identified as to its original */ ++/* source, whether or not the source component s header file is present.*/ ++/* The standard error/progress status definitions should be used */ ++/* whenever possible to ease status interpretation. No layer */ ++/* information is defined at this point; it should be ORed into the API */ ++/* status values defined in the APIs header file. */ ++/* -------------------------------------------------------------------------- */ ++#if (CID_LAYER_NONE != 0) ++#error ERROR: DVP component identifiers require the layer type 'NONE' = 0 ! ++#endif ++ ++/* -------------------------------------------------------------------------- */ ++/* Classless Types/Components (don t fit into other class categories) */ ++/* -------------------------------------------------------------------------- */ ++#define CTYP_NOCLASS_NOTYPE (CID_CLASS_NONE | CID_TYPE_NONE) ++#define CTYP_NOCLASS_SOURCE (CID_CLASS_NONE | CID_TYPE_SOURCE) ++#define CTYP_NOCLASS_SINK (CID_CLASS_NONE | CID_TYPE_SINK) ++#define CTYP_NOCLASS_MUX (CID_CLASS_NONE | CID_TYPE_MUX) ++#define CTYP_NOCLASS_DEMUX (CID_CLASS_NONE | CID_TYPE_DEMUX) ++#define CTYP_NOCLASS_FILTER (CID_CLASS_NONE | CID_TYPE_FILTER) ++#define CTYP_NOCLASS_CONTROL (CID_CLASS_NONE | CID_TYPE_CONTROL) ++#define CTYP_NOCLASS_DATABASE (CID_CLASS_NONE | CID_TYPE_DATABASE) ++#define CTYP_NOCLASS_SUBSYS (CID_CLASS_NONE | CID_TYPE_SUBSYSTEM) ++ ++#define CID_COMP_CLOCK (TAG(0x01U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_DMA (TAG(0x02U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_PIC (TAG(0x03U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_NORFLASH (TAG(0x04U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_NANDFLASH (TAG(0x05U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_GPIO (TAG(0x06U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_SMARTCARD (TAG(0x07U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_UDMA (TAG(0x08U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_DSP (TAG(0x09U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_TIMER (TAG(0x0AU) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_TSDMA (TAG(0x0BU) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_MMIARB (TAG(0x0CU) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_EEPROM (TAG(0x0DU) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_PARPORT (TAG(0x0EU) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_VSS (TAG(0x0FU) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_TSIO (TAG(0x10U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_DBG (TAG(0x11U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_TTE (TAG(0x12U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_AVPROP (TAG(0x13U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_SERIAL_RAM (TAG(0x14U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_SMARTMEDIA (TAG(0x15U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_COMPACT_FLASH (TAG(0x16U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_CI (TAG(0x17U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_INT_ALARM (TAG(0x18U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_TASK_ALARM (TAG(0x19U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_XDMA (TAG(0x1AU) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_ICC (TAG(0x1BU) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_CONNMGR (TAG(0x1CU) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_CONNMGRVSYSTV (TAG(0x1DU) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_VBISLICERVSYSTV (TAG(0x1EU) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_VMIXVSYSTV (TAG(0x1FU) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_NTF (TAG(0x20U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_NTY CID_COMP_NTF /* legacy */ ++#define CID_COMP_FATERR (TAG(0x21U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_DVBTDEMOD (TAG(0x22U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_HYBRIDTUNER (TAG(0x23U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_VLD (TAG(0x24U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_GIC (TAG(0x25U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_WEB (TAG(0x26U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_ANAEPGDB (TAG(0x27U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_HWSEM (TAG(0x28U) | CTYP_NOCLASS_NOTYPE) ++#define CID_COMP_MMON (TAG(0x29U) | CTYP_NOCLASS_NOTYPE) ++ ++#define CID_COMP_FREAD (TAG(0x01U) | CTYP_NOCLASS_SOURCE) ++#define CID_COMP_CDRREAD (TAG(0x02U) | CTYP_NOCLASS_SOURCE) ++#define CID_COMP_VSB (TAG(0x03U) | CTYP_NOCLASS_SOURCE) ++#define CID_COMP_ANALOGTVTUNER (TAG(0x04U) | CTYP_NOCLASS_SOURCE) ++#define CID_COMP_TPINMPEG2 (TAG(0x05U) | CTYP_NOCLASS_SOURCE) ++#define CID_COMP_DREAD (TAG(0x06U) | CTYP_NOCLASS_SOURCE) ++#define CID_COMP_TREAD (TAG(0x07U) | CTYP_NOCLASS_SOURCE) ++#define CID_COMP_RTC (TAG(0x08U) | CTYP_NOCLASS_SOURCE) ++#define CID_COMP_TOUCHC (TAG(0x09U) | CTYP_NOCLASS_SOURCE) ++#define CID_COMP_KEYPAD (TAG(0x0AU) | CTYP_NOCLASS_SOURCE) ++#define CID_COMP_ADC (TAG(0x0BU) | CTYP_NOCLASS_SOURCE) ++#define CID_COMP_READLIST (TAG(0x0CU) | CTYP_NOCLASS_SOURCE) ++#define CID_COMP_FROMDISK (TAG(0x0DU) | CTYP_NOCLASS_SOURCE) ++#define CID_COMP_SOURCE (TAG(0x0EU) | CTYP_NOCLASS_SOURCE) ++ ++#define CID_COMP_FWRITE (TAG(0x01U) | CTYP_NOCLASS_SINK) ++#define CID_COMP_CDWRITE (TAG(0x02U) | CTYP_NOCLASS_SINK) ++#define CID_COMP_CHARLCD (TAG(0x03U) | CTYP_NOCLASS_SINK) ++#define CID_COMP_PWM (TAG(0x04U) | CTYP_NOCLASS_SINK) ++#define CID_COMP_DAC (TAG(0x05U) | CTYP_NOCLASS_SINK) ++#define CID_COMP_TSDMAINJECTOR (TAG(0x06U) | CTYP_NOCLASS_SINK) ++#define CID_COMP_TODISK (TAG(0x07U) | CTYP_NOCLASS_SINK) ++ ++#define CID_COMP_MUXMPEGPS (TAG(0x01U) | CTYP_NOCLASS_MUX) ++#define CID_COMP_MUXMPEG (TAG(0x02U) | CTYP_NOCLASS_MUX) ++ ++#define CID_COMP_DEMUXMPEGTS (TAG(0x01U) | CTYP_NOCLASS_DEMUX) ++#define CID_COMP_DEMUXMPEGPS (TAG(0x02U) | CTYP_NOCLASS_DEMUX) ++#define CID_COMP_DEMUXDV (TAG(0x03U) | CTYP_NOCLASS_DEMUX) ++ ++#define CID_COMP_COPYIO (TAG(0x01U) | CTYP_NOCLASS_FILTER) ++#define CID_COMP_COPYINPLACE (TAG(0x02U) | CTYP_NOCLASS_FILTER) ++#define CID_COMP_UART (TAG(0x03U) | CTYP_NOCLASS_FILTER) ++#define CID_COMP_SSI (TAG(0x04U) | CTYP_NOCLASS_FILTER) ++#define CID_COMP_MODEMV34 (TAG(0x05U) | CTYP_NOCLASS_FILTER) ++#define CID_COMP_MODEMV42 (TAG(0x06U) | CTYP_NOCLASS_FILTER) ++#define CID_COMP_HTMLPARSER (TAG(0x07U) | CTYP_NOCLASS_FILTER) ++#define CID_COMP_VMSP (TAG(0x08U) | CTYP_NOCLASS_FILTER) ++#define CID_COMP_X (TAG(0x09U) | CTYP_NOCLASS_FILTER) ++#define CID_COMP_TXTSUBTDECEBU (TAG(0x0AU) | CTYP_NOCLASS_FILTER) ++#define CID_COMP_CPI (TAG(0x0BU) | CTYP_NOCLASS_FILTER) ++#define CID_COMP_TRICK (TAG(0x0CU) | CTYP_NOCLASS_FILTER) ++#define CID_COMP_FWRITEFREAD (TAG(0x0DU) | CTYP_NOCLASS_FILTER) ++ ++#define CID_COMP_REMCTL5 (TAG(0x01U) | CTYP_NOCLASS_CONTROL) ++#define CID_COMP_INFRARED (TAG(0x02U) | CTYP_NOCLASS_CONTROL) ++ ++#define CID_COMP_PSIP (TAG(0x01U) | CTYP_NOCLASS_DATABASE) ++#define CID_COMP_IDE (TAG(0x02U) | CTYP_NOCLASS_DATABASE) ++#define CID_COMP_DISKSCHED (TAG(0x03U) | CTYP_NOCLASS_DATABASE) ++#define CID_COMP_AVFS (TAG(0x04U) | CTYP_NOCLASS_DATABASE) ++#define CID_COMP_MDB (TAG(0x05U) | CTYP_NOCLASS_DATABASE) ++#define CID_COMP_ATAPI_CMDS (TAG(0x06U) | CTYP_NOCLASS_DATABASE) ++ ++#define CID_COMP_IRDMMPEG (TAG(0x01U) | CTYP_NOCLASS_SUBSYS) ++#define CID_COMP_STORSYS (TAG(0x02U) | CTYP_NOCLASS_SUBSYS) ++#define CID_COMP_PMU (TAG(0x03U) | CTYP_NOCLASS_SUBSYS) ++ ++/* -------------------------------------------------------------------------- */ ++/* Video Class Types/Components (video types handle video/graphics data) */ ++/* -------------------------------------------------------------------------- */ ++#define CTYP_VIDEO_SINK (CID_CLASS_VIDEO | CID_TYPE_SINK) ++#define CTYP_VIDEO_SOURCE (CID_CLASS_VIDEO | CID_TYPE_SOURCE) ++#define CTYP_VIDEO_ENCODER (CID_CLASS_VIDEO | CID_TYPE_ENCODER) ++#define CTYP_VIDEO_DECODER (CID_CLASS_VIDEO | CID_TYPE_DECODER) ++#define CTYP_VIDEO_DIGITIZER (CID_CLASS_VIDEO | CID_TYPE_DIGITIZER) ++#define CTYP_VIDEO_RENDERER (CID_CLASS_VIDEO | CID_TYPE_RENDERER) ++#define CTYP_VIDEO_FILTER (CID_CLASS_VIDEO | CID_TYPE_FILTER) ++#define CTYP_VIDEO_SUBSYS (CID_CLASS_VIDEO | CID_TYPE_SUBSYSTEM) ++ ++#define CID_COMP_LCD (TAG(0x01U) | CTYP_VIDEO_SINK) ++ ++#define CID_COMP_VCAPVI (TAG(0x01U) | CTYP_VIDEO_SOURCE) ++#define CID_COMP_VIP (TAG(0x02U) | CTYP_VIDEO_SOURCE) ++#define CID_COMP_VI (TAG(0x03U) | CTYP_VIDEO_SOURCE) ++#define CID_COMP_VSLICER (TAG(0x04U) | CTYP_VIDEO_SOURCE) ++#define CID_COMP_FBREAD (TAG(0x05U) | CTYP_VIDEO_SOURCE) ++#define CID_COMP_QVI (TAG(0x06U) | CTYP_VIDEO_SOURCE) ++#define CID_COMP_CAMERA (TAG(0x07U) | CTYP_VIDEO_SOURCE) ++#define CID_COMP_CAM_SENSOR (TAG(0x08U) | CTYP_VIDEO_SOURCE) ++ ++#define CID_COMP_VENCM1 (TAG(0x01U) | CTYP_VIDEO_ENCODER) ++#define CID_COMP_VENCM2 (TAG(0x02U) | CTYP_VIDEO_ENCODER) ++#define CID_COMP_VENCMJ (TAG(0x03U) | CTYP_VIDEO_ENCODER) ++#define CID_COMP_VENCH263 (TAG(0x04U) | CTYP_VIDEO_ENCODER) ++#define CID_COMP_VENCH261 (TAG(0x05U) | CTYP_VIDEO_ENCODER) ++#define CID_COMP_M4VENC (TAG(0x06U) | CTYP_VIDEO_ENCODER) ++#define CID_COMP_M4VENCME (TAG(0x07U) | CTYP_VIDEO_ENCODER) ++#define CID_COMP_M4VENCTC (TAG(0x08U) | CTYP_VIDEO_ENCODER) ++#define CID_COMP_M4VENCBSG (TAG(0x09U) | CTYP_VIDEO_ENCODER) ++#define CID_COMP_M4VENCJPEG (TAG(0x0AU) | CTYP_VIDEO_ENCODER) ++ ++#define CID_COMP_VDECM1 (TAG(0x01U) | CTYP_VIDEO_DECODER) ++#define CID_COMP_VDECM2 (TAG(0x02U) | CTYP_VIDEO_DECODER) ++#define CID_COMP_VDECMPEG (TAG(0x03U) | CTYP_VIDEO_DECODER) ++#define CID_COMP_VDECMJ (TAG(0x04U) | CTYP_VIDEO_DECODER) ++#define CID_COMP_VDECSUBPICSVCD (TAG(0x05U) | CTYP_VIDEO_DECODER) ++#define CID_COMP_VDECH263 (TAG(0x06U) | CTYP_VIDEO_DECODER) ++#define CID_COMP_VDECH261 (TAG(0x07U) | CTYP_VIDEO_DECODER) ++#define CID_COMP_VDEC (TAG(0x08U) | CTYP_VIDEO_DECODER) ++#define CID_COMP_VDECSUBPICDVD (TAG(0x09U) | CTYP_VIDEO_DECODER) ++#define CID_COMP_VDECSUBPICBMPDVD (TAG(0x0AU) | CTYP_VIDEO_DECODER) ++#define CID_COMP_VDECSUBPICRENDDVD (TAG(0x0BU) | CTYP_VIDEO_DECODER) ++#define CID_COMP_M4PP (TAG(0x0CU) | CTYP_VIDEO_DECODER) ++#define CID_COMP_M4MC (TAG(0x0DU) | CTYP_VIDEO_DECODER) ++#define CID_COMP_M4CSC (TAG(0x0EU) | CTYP_VIDEO_DECODER) ++#define CID_COMP_VDECTXT (TAG(0x0FU) | CTYP_VIDEO_DECODER) ++#define CID_COMP_VDECDV (TAG(0x10U) | CTYP_VIDEO_DECODER) ++#define CID_COMP_BACKANIM (TAG(0x11U) | CTYP_VIDEO_DECODER) ++ ++#define CID_COMP_VDIG (TAG(0x01U) | CTYP_VIDEO_DIGITIZER) ++#define CID_COMP_VDIGVIRAW (TAG(0x02U) | CTYP_VIDEO_DIGITIZER) ++#define CID_COMP_VDIG_EXT (TAG(0x03U) | CTYP_VIDEO_DIGITIZER) ++#define CID_COMP_VDIG_VBI (TAG(0x04U) | CTYP_VIDEO_DIGITIZER) ++#define CID_COMP_VDIG_EXT_VBI (TAG(0x05U) | CTYP_VIDEO_DIGITIZER) ++ ++#define CID_COMP_VREND (TAG(0x01U) | CTYP_VIDEO_RENDERER) ++#define CID_COMP_HDVO (TAG(0x02U) | CTYP_VIDEO_RENDERER) ++#define CID_COMP_VRENDGFXVO (TAG(0x03U) | CTYP_VIDEO_RENDERER) ++#define CID_COMP_AICP (TAG(0x04U) | CTYP_VIDEO_RENDERER) ++#define CID_COMP_VRENDVORAW (TAG(0x05U) | CTYP_VIDEO_RENDERER) ++#define CID_COMP_VO (TAG(0x06U) | CTYP_VIDEO_RENDERER) ++#define CID_COMP_VRENDVOICP (TAG(0x07U) | CTYP_VIDEO_RENDERER) ++#define CID_COMP_VMIX (TAG(0x08U) | CTYP_VIDEO_RENDERER) ++#define CID_COMP_QVCP (TAG(0x09U) | CTYP_VIDEO_RENDERER) ++#define CID_COMP_VREND_EXT (TAG(0x0AU) | CTYP_VIDEO_RENDERER) ++#define CID_COMP_VENCANA (TAG(0x0BU) | CTYP_VIDEO_RENDERER) ++#define CID_COMP_QVO (TAG(0x0CU) | CTYP_VIDEO_RENDERER) ++ ++#define CID_COMP_MBS (TAG(0x01U) | CTYP_VIDEO_FILTER) ++#define CID_COMP_VTRANS (TAG(0x02U) | CTYP_VIDEO_FILTER) ++#define CID_COMP_QNM (TAG(0x03U) | CTYP_VIDEO_FILTER) ++#define CID_COMP_ICP (TAG(0x04U) | CTYP_VIDEO_FILTER) ++#define CID_COMP_VTRANSNM (TAG(0x05U) | CTYP_VIDEO_FILTER) ++#define CID_COMP_QFD (TAG(0x06U) | CTYP_VIDEO_FILTER) ++#define CID_COMP_VTRANSDVD (TAG(0x07U) | CTYP_VIDEO_FILTER) ++#define CID_COMP_VTRANSCRYSTAL (TAG(0x08U) | CTYP_VIDEO_FILTER) ++#define CID_COMP_VTRANSUD (TAG(0x09U) | CTYP_VIDEO_FILTER) ++/*#define CID_COMP_QTNR (TAG(0x0AU) | CTYP_VIDEO_FILTER) Removed v17: Replaced with CID_VTRANS_QTNR */ ++ ++#define CID_COMP_VSYSMT3 (TAG(0x01U) | CTYP_VIDEO_SUBSYS) ++#define CID_COMP_VSYSSTB (TAG(0x01U) | CTYP_VIDEO_SUBSYS) ++#define CID_COMP_DVDVIDSYS (TAG(0x02U) | CTYP_VIDEO_SUBSYS) ++#define CID_COMP_VDECUD (TAG(0x03U) | CTYP_VIDEO_SUBSYS) ++#define CID_COMP_VIDSYS (TAG(0x04U) | CTYP_VIDEO_SUBSYS) ++#define CID_COMP_VSYSTV (TAG(0x05U) | CTYP_VIDEO_SUBSYS) ++ ++/* -------------------------------------------------------------------------- */ ++/* Audio Class Types/Components (audio types primarily handle audio data) */ ++/* -------------------------------------------------------------------------- */ ++#define CTYP_AUDIO_NOTYPE (CID_CLASS_AUDIO | CID_TYPE_NONE) ++#define CTYP_AUDIO_SINK (CID_CLASS_AUDIO | CID_TYPE_SINK) ++#define CTYP_AUDIO_SOURCE (CID_CLASS_AUDIO | CID_TYPE_SOURCE) ++#define CTYP_AUDIO_ENCODER (CID_CLASS_AUDIO | CID_TYPE_ENCODER) ++#define CTYP_AUDIO_DECODER (CID_CLASS_AUDIO | CID_TYPE_DECODER) ++#define CTYP_AUDIO_DIGITIZER (CID_CLASS_AUDIO | CID_TYPE_DIGITIZER) ++#define CTYP_AUDIO_RENDERER (CID_CLASS_AUDIO | CID_TYPE_RENDERER) ++#define CTYP_AUDIO_FILTER (CID_CLASS_AUDIO | CID_TYPE_FILTER) ++#define CTYP_AUDIO_SUBSYS (CID_CLASS_AUDIO | CID_TYPE_SUBSYSTEM) ++ ++#define CID_COMP_CODEC (TAG(0x01U) | CTYP_AUDIO_NOTYPE) ++ ++#define CID_COMP_SDAC (TAG(0x01U) | CTYP_AUDIO_SINK) ++ ++#define CID_COMP_ADIGAI (TAG(0x01U) | CTYP_AUDIO_DIGITIZER) ++#define CID_COMP_ADIGSPDIF (TAG(0x02U) | CTYP_AUDIO_DIGITIZER) ++ ++#define CID_COMP_ARENDAO (TAG(0x01U) | CTYP_AUDIO_RENDERER) ++#define CID_COMP_ARENDSPDIF (TAG(0x02U) | CTYP_AUDIO_RENDERER) ++ ++#define CID_COMP_NOISESEQ (TAG(0x03U) | CTYP_AUDIO_SOURCE) ++ ++#define CID_COMP_AENCAC3 (TAG(0x01U) | CTYP_AUDIO_ENCODER) ++#define CID_COMP_AENCMPEG1 (TAG(0x02U) | CTYP_AUDIO_ENCODER) ++#define CID_COMP_AENCAAC (TAG(0x03U) | CTYP_AUDIO_ENCODER) ++#define CID_COMP_AENCG723 (TAG(0x04U) | CTYP_AUDIO_ENCODER) ++#define CID_COMP_AENCG728 (TAG(0x05U) | CTYP_AUDIO_ENCODER) ++#define CID_COMP_AENCWMA (TAG(0x06U) | CTYP_AUDIO_ENCODER) ++#define CID_COMP_AVENCMPEG (TAG(0x07U) | CTYP_AUDIO_ENCODER) ++#define CID_COMP_AENCMP3 (TAG(0x08U) | CTYP_AUDIO_ENCODER) ++ ++#define CID_COMP_ADECPROLOGIC (TAG(0x01U) | CTYP_AUDIO_DECODER) ++#define CID_COMP_ADECAC3 (TAG(0x02U) | CTYP_AUDIO_DECODER) ++#define CID_COMP_ADECMPEG1 (TAG(0x03U) | CTYP_AUDIO_DECODER) ++#define CID_COMP_ADECMP3 (TAG(0x04U) | CTYP_AUDIO_DECODER) ++#define CID_COMP_ADECAAC (TAG(0x05U) | CTYP_AUDIO_DECODER) ++#define CID_COMP_ADECG723 (TAG(0x06U) | CTYP_AUDIO_DECODER) ++#define CID_COMP_ADECG728 (TAG(0x07U) | CTYP_AUDIO_DECODER) ++#define CID_COMP_ADECWMA (TAG(0x08U) | CTYP_AUDIO_DECODER) ++#define CID_COMP_ADECTHRU (TAG(0x09U) | CTYP_AUDIO_DECODER) ++#define CID_COMP_ADEC (TAG(0x0AU) | CTYP_AUDIO_DECODER) ++#define CID_COMP_ADECPCM (TAG(0x0BU) | CTYP_AUDIO_DECODER) ++#define CID_COMP_ADECDV (TAG(0x0CU) | CTYP_AUDIO_DECODER) ++#define CID_COMP_ADECDTS (TAG(0x0DU) | CTYP_AUDIO_DECODER) ++ ++#define CID_COMP_ASPLIB (TAG(0x01U) | CTYP_AUDIO_FILTER) ++#define CID_COMP_IIR (TAG(0x02U) | CTYP_AUDIO_FILTER) ++#define CID_COMP_ASPEQ2 (TAG(0x03U) | CTYP_AUDIO_FILTER) ++#define CID_COMP_ASPEQ5 (TAG(0x04U) | CTYP_AUDIO_FILTER) ++#define CID_COMP_ASPBASSREDIR (TAG(0x05U) | CTYP_AUDIO_FILTER) ++#define CID_COMP_ASPLAT2 (TAG(0x06U) | CTYP_AUDIO_FILTER) ++#define CID_COMP_ASPPLUGIN (TAG(0x07U) | CTYP_AUDIO_FILTER) ++#define CID_COMP_AMIXDTV (TAG(0x08U) | CTYP_AUDIO_FILTER) ++#define CID_COMP_AMIXSIMPLE (TAG(0x09U) | CTYP_AUDIO_FILTER) ++#define CID_COMP_AMIXSTB (TAG(0x0AU) | CTYP_AUDIO_FILTER) ++#define CID_COMP_ASPEQ (TAG(0x0BU) | CTYP_AUDIO_FILTER) ++#define CID_COMP_ATESTSIG (TAG(0x0CU) | CTYP_AUDIO_FILTER) ++#define CID_COMP_APROC (TAG(0x0DU) | CTYP_AUDIO_FILTER) ++ ++#define CID_COMP_AUDSUBSYS (TAG(0x01U) | CTYP_AUDIO_SUBSYS) ++#define CID_COMP_AUDSYSSTB (TAG(0x02U) | CTYP_AUDIO_SUBSYS) ++#define CID_COMP_AUDSYSDVD (TAG(0x03U) | CTYP_AUDIO_SUBSYS) ++#define CID_COMP_MMC (TAG(0x04U) | CTYP_AUDIO_SUBSYS) ++#define CID_COMP_COMP_MMC CID_COMP_MMC /* legacy */ ++#define CID_COMP_ASYSATV (TAG(0x05U) | CTYP_AUDIO_SUBSYS) ++ ++/* -------------------------------------------------------------------------- */ ++/* Graphics Class Types/Components */ ++/* -------------------------------------------------------------------------- */ ++#define CTYP_GRAPHICS_RENDERER (CID_CLASS_GRAPHICS | CID_TYPE_SINK) ++ ++#define CID_COMP_WM (TAG(0x01U) | CTYP_GRAPHICS_RENDERER) ++#define CID_COMP_WIDGET (TAG(0x02U) | CTYP_GRAPHICS_RENDERER) ++#define CID_COMP_OM (TAG(0x03U) | CTYP_GRAPHICS_RENDERER) ++#define CID_COMP_HTMLRENDER (TAG(0x04U) | CTYP_GRAPHICS_RENDERER) ++#define CID_COMP_VRENDEIA708 (TAG(0x05U) | CTYP_GRAPHICS_RENDERER) ++#define CID_COMP_VRENDEIA608 (TAG(0x06U) | CTYP_GRAPHICS_RENDERER) ++ ++#define CTYP_GRAPHICS_DRAW (CID_CLASS_GRAPHICS | CID_TYPE_NONE) ++ ++#define CID_COMP_DRAW (TAG(0x10U) | CTYP_GRAPHICS_DRAW) ++#define CID_COMP_DRAW_UT (TAG(0x11U) | CTYP_GRAPHICS_DRAW) ++#define CID_COMP_DRAW_DE (TAG(0x12U) | CTYP_GRAPHICS_DRAW) ++#define CID_COMP_DRAW_REF (TAG(0x13U) | CTYP_GRAPHICS_DRAW) ++#define CID_COMP_DRAW_TMH (TAG(0x14U) | CTYP_GRAPHICS_DRAW) ++#define CID_COMP_DRAW_TMT (TAG(0x15U) | CTYP_GRAPHICS_DRAW) ++#define CID_COMP_DRAW_TMTH (TAG(0x16U) | CTYP_GRAPHICS_DRAW) ++ ++#define CID_COMP_3D (TAG(0x30U) | CTYP_GRAPHICS_DRAW) ++#define CID_COMP_JAWT (TAG(0x31U) | CTYP_GRAPHICS_DRAW) ++#define CID_COMP_JINPUT (TAG(0x32U) | CTYP_GRAPHICS_DRAW) ++#define CID_COMP_LWM (TAG(0x33U) | CTYP_GRAPHICS_DRAW) ++#define CID_COMP_2D (TAG(0x34U) | CTYP_GRAPHICS_DRAW) ++ ++/* -------------------------------------------------------------------------- */ ++/* Bus Class Types/Components (busses connect hardware components together) */ ++/* -------------------------------------------------------------------------- */ ++#define CTYP_BUS_NOTYPE (CID_CLASS_BUS | CID_TYPE_NONE) ++ ++#define CID_COMP_XIO (TAG(0x01U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_IIC (TAG(0x02U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_PCI (TAG(0x03U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_P1394 (TAG(0x04U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_ENET (TAG(0x05U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_ATA (TAG(0x06U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_CAN (TAG(0x07U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_UCGDMA (TAG(0x08U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_I2S (TAG(0x09U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_SPI (TAG(0x0AU) | CTYP_BUS_NOTYPE) ++#define CID_COMP_PCM (TAG(0x0BU) | CTYP_BUS_NOTYPE) ++#define CID_COMP_L3 (TAG(0x0CU) | CTYP_BUS_NOTYPE) ++#define CID_COMP_UDSPFL (TAG(0x0DU) | CTYP_BUS_NOTYPE) ++#define CID_COMP_UDSRSL (TAG(0x0EU) | CTYP_BUS_NOTYPE) ++#define CID_COMP_UDSMSBOT (TAG(0x0FU) | CTYP_BUS_NOTYPE) ++#define CID_COMP_UDSMSCBI (TAG(0x10U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_UDSAUDIO (TAG(0x11U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_UDSHID (TAG(0x12U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_UDSCDC (TAG(0x13U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_UDSPRINTER (TAG(0x14U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_UDSSCSI (TAG(0x15U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_UDSMODEM (TAG(0x16U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_UDSETHERNET (TAG(0x17U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_UHSPFL (TAG(0x18U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_UHSMS (TAG(0x19U) | CTYP_BUS_NOTYPE) ++#define CID_COMP_UHSAUDIO (TAG(0x1AU) | CTYP_BUS_NOTYPE) ++#define CID_COMP_UHSSCSI (TAG(0x1BU) | CTYP_BUS_NOTYPE) ++ ++/* -------------------------------------------------------------------------- */ ++/* Infrastructure Class Types/Components */ ++/* -------------------------------------------------------------------------- */ ++#define CTYP_INFRASTR_NOTYPE (CID_CLASS_INFRASTR | CID_TYPE_NONE) ++#define CTYP_INFRASTR_DATABASE (CID_CLASS_INFRASTR | CID_TYPE_DATABASE) ++ ++#define CID_COMP_OSAL (TAG(0x01U) | CTYP_INFRASTR_NOTYPE) ++#define CID_COMP_MML (TAG(0x02U) | CTYP_INFRASTR_NOTYPE) ++#define CID_COMP_TSSA_DEFAULTS (TAG(0x03U) | CTYP_INFRASTR_NOTYPE) ++#define CID_COMP_RPC (TAG(0x04U) | CTYP_INFRASTR_NOTYPE) ++#define CID_COMP_THI (TAG(0x05U) | CTYP_INFRASTR_NOTYPE) ++#define CID_COMP_REGISTRY (TAG(0x06U) | CTYP_INFRASTR_NOTYPE) ++#define CID_COMP_TMMAN (TAG(0x07U) | CTYP_INFRASTR_NOTYPE) ++#define CID_COMP_LDT (TAG(0x08U) | CTYP_INFRASTR_NOTYPE) ++#define CID_COMP_CPUCONN (TAG(0x09U) | CTYP_INFRASTR_NOTYPE) ++#define CID_COMP_COMMQUE (TAG(0x0AU) | CTYP_INFRASTR_NOTYPE) ++#define CID_COMP_BSLMGR (TAG(0x0BU) | CTYP_INFRASTR_NOTYPE) ++#define CID_COMP_CR (TAG(0x0CU) | CTYP_INFRASTR_NOTYPE) ++#define CID_COMP_NODE (TAG(0x0DU) | CTYP_INFRASTR_NOTYPE) ++#define CID_COMP_COM (TAG(0x0EU) | CTYP_INFRASTR_NOTYPE) ++#define CID_COMP_UTIL (TAG(0x0FU) | CTYP_INFRASTR_NOTYPE) ++#define CID_COMP_SGLIST (TAG(0x10U) | CTYP_INFRASTR_NOTYPE) ++#define CID_COMP_ARITH (TAG(0x11U) | CTYP_INFRASTR_NOTYPE) ++ ++#define CID_COMP_MULTIFS (TAG(0x01U) | CTYP_INFRASTR_DATABASE) ++#define CID_COMP_SFS (TAG(0x02U) | CTYP_INFRASTR_DATABASE) ++ ++/* -------------------------------------------------------------------------- */ ++/* Component Standard Error/Progress Status definitions (bits 11:0, 12 bits) */ ++/* NOTE: These status codes are ORed with the component identifier to create */ ++/* component unique 32 bit status values. The component status values */ ++/* should be defined in the header files where the APIs are defined. */ ++/* -------------------------------------------------------------------------- */ ++#define CID_ERR_BITMASK 0xFFFU ++#define CID_ERR_BITSHIFT 0 ++#define CID_GET_ERROR(compId) ((compId & CID_ERR_BITMASK) >> CID_ERR_BITSHIFT) ++ ++#define TM_ERR_COMPATIBILITY 0x001U /* SW Interface compatibility */ ++#define TM_ERR_MAJOR_VERSION 0x002U /* SW Major Version error */ ++#define TM_ERR_COMP_VERSION 0x003U /* SW component version error */ ++#define TM_ERR_BAD_MODULE_ID 0x004U /* SW - HW module ID error */ ++#define TM_ERR_BAD_UNIT_NUMBER 0x005U /* Invalid device unit number */ ++#define TM_ERR_BAD_INSTANCE 0x006U /* Bad input instance value */ ++#define TM_ERR_BAD_HANDLE 0x007U /* Bad input handle */ ++#define TM_ERR_BAD_INDEX 0x008U /* Bad input index */ ++#define TM_ERR_BAD_PARAMETER 0x009U /* Invalid input parameter */ ++#define TM_ERR_NO_INSTANCES 0x00AU /* No instances available */ ++#define TM_ERR_NO_COMPONENT 0x00BU /* Component is not present */ ++#define TM_ERR_NO_RESOURCES 0x00CU /* Resource is not available */ ++#define TM_ERR_INSTANCE_IN_USE 0x00DU /* Instance is already in use */ ++#define TM_ERR_RESOURCE_OWNED 0x00EU /* Resource is already in use */ ++#define TM_ERR_RESOURCE_NOT_OWNED 0x00FU /* Caller does not own resource */ ++#define TM_ERR_INCONSISTENT_PARAMS 0x010U /* Inconsistent input params */ ++#define TM_ERR_NOT_INITIALIZED 0x011U /* Component is not initialized */ ++#define TM_ERR_NOT_ENABLED 0x012U /* Component is not enabled */ ++#define TM_ERR_NOT_SUPPORTED 0x013U /* Function is not supported */ ++#define TM_ERR_INIT_FAILED 0x014U /* Initialization failed */ ++#define TM_ERR_BUSY 0x015U /* Component is busy */ ++#define TM_ERR_NOT_BUSY 0x016U /* Component is not busy */ ++#define TM_ERR_READ 0x017U /* Read error */ ++#define TM_ERR_WRITE 0x018U /* Write error */ ++#define TM_ERR_ERASE 0x019U /* Erase error */ ++#define TM_ERR_LOCK 0x01AU /* Lock error */ ++#define TM_ERR_UNLOCK 0x01BU /* Unlock error */ ++#define TM_ERR_OUT_OF_MEMORY 0x01CU /* Memory allocation failed */ ++#define TM_ERR_BAD_VIRT_ADDRESS 0x01DU /* Bad virtual address */ ++#define TM_ERR_BAD_PHYS_ADDRESS 0x01EU /* Bad physical address */ ++#define TM_ERR_TIMEOUT 0x01FU /* Timeout error */ ++#define TM_ERR_OVERFLOW 0x020U /* Data overflow/overrun error */ ++#define TM_ERR_FULL 0x021U /* Queue (etc.) is full */ ++#define TM_ERR_EMPTY 0x022U /* Queue (etc.) is empty */ ++#define TM_ERR_NOT_STARTED 0x023U /* Streaming function failed */ ++#define TM_ERR_ALREADY_STARTED 0x024U /* Start function failed */ ++#define TM_ERR_NOT_STOPPED 0x025U /* Non-streaming function failed*/ ++#define TM_ERR_ALREADY_STOPPED 0x026U /* Stop function failed */ ++#define TM_ERR_ALREADY_SETUP 0x027U /* Setup function failed */ ++#define TM_ERR_NULL_PARAMETER 0x028U /* Null input parameter */ ++#define TM_ERR_NULL_DATAINFUNC 0x029U /* Null data input function */ ++#define TM_ERR_NULL_DATAOUTFUNC 0x02AU /* Null data output function */ ++#define TM_ERR_NULL_CONTROLFUNC 0x02BU /* Null control function */ ++#define TM_ERR_NULL_COMPLETIONFUNC 0x02CU /* Null completion function */ ++#define TM_ERR_NULL_PROGRESSFUNC 0x02DU /* Null progress function */ ++#define TM_ERR_NULL_ERRORFUNC 0x02EU /* Null error handler function */ ++#define TM_ERR_NULL_MEMALLOCFUNC 0x02FU /* Null memory alloc function */ ++#define TM_ERR_NULL_MEMFREEFUNC 0x030U /* Null memory free function */ ++#define TM_ERR_NULL_CONFIGFUNC 0x031U /* Null configuration function */ ++#define TM_ERR_NULL_PARENT 0x032U /* Null parent data */ ++#define TM_ERR_NULL_IODESC 0x033U /* Null in/out descriptor */ ++#define TM_ERR_NULL_CTRLDESC 0x034U /* Null control descriptor */ ++#define TM_ERR_UNSUPPORTED_DATACLASS 0x035U /* Unsupported data class */ ++#define TM_ERR_UNSUPPORTED_DATATYPE 0x036U /* Unsupported data type */ ++#define TM_ERR_UNSUPPORTED_DATASUBTYPE 0x037U /* Unsupported data subtype */ ++#define TM_ERR_FORMAT 0x038U /* Invalid/unsupported format */ ++#define TM_ERR_INPUT_DESC_FLAGS 0x039U /* Bad input descriptor flags */ ++#define TM_ERR_OUTPUT_DESC_FLAGS 0x03AU /* Bad output descriptor flags */ ++#define TM_ERR_CAP_REQUIRED 0x03BU /* Capabilities required ??? */ ++#define TM_ERR_BAD_TMALFUNC_TABLE 0x03CU /* Bad TMAL function table */ ++#define TM_ERR_INVALID_CHANNEL_ID 0x03DU /* Invalid channel identifier */ ++#define TM_ERR_INVALID_COMMAND 0x03EU /* Invalid command/request */ ++#define TM_ERR_STREAM_MODE_CONFUSION 0x03FU /* Stream mode config conflict */ ++#define TM_ERR_UNDERRUN 0x040U /* Data underflow/underrun */ ++#define TM_ERR_EMPTY_PACKET_RECVD 0x041U /* Empty data packet received */ ++#define TM_ERR_OTHER_DATAINOUT_ERR 0x042U /* Other data input/output err */ ++#define TM_ERR_STOP_REQUESTED 0x043U /* Stop in progress */ ++#define TM_ERR_ASSERTION 0x049U /* Assertion failure */ ++#define TM_ERR_HIGHWAY_BANDWIDTH 0x04AU /* Highway bandwidth bus error */ ++#define TM_ERR_HW_RESET_FAILED 0x04BU /* Hardware reset failed */ ++#define TM_ERR_BAD_FLAGS 0x04DU /* Bad flags */ ++#define TM_ERR_BAD_PRIORITY 0x04EU /* Bad priority */ ++#define TM_ERR_BAD_REFERENCE_COUNT 0x04FU /* Bad reference count */ ++#define TM_ERR_BAD_SETUP 0x050U /* Bad setup */ ++#define TM_ERR_BAD_STACK_SIZE 0x051U /* Bad stack size */ ++#define TM_ERR_BAD_TEE 0x052U /* Bad tee */ ++#define TM_ERR_IN_PLACE 0x053U /* In place */ ++#define TM_ERR_NOT_CACHE_ALIGNED 0x054U /* Not cache aligned */ ++#define TM_ERR_NO_ROOT_TEE 0x055U /* No root tee */ ++#define TM_ERR_NO_TEE_ALLOWED 0x056U /* No tee allowed */ ++#define TM_ERR_NO_TEE_EMPTY_PACKET 0x057U /* No tee empty packet */ ++#define TM_ERR_NULL_PACKET 0x059U /* Null packet */ ++#define TM_ERR_FORMAT_FREED 0x05AU /* Format freed */ ++#define TM_ERR_FORMAT_INTERNAL 0x05BU /* Format internal */ ++#define TM_ERR_BAD_FORMAT 0x05CU /* Bad format */ ++#define TM_ERR_FORMAT_NEGOTIATE_DATACLASS 0x05DU /* Format negotiate class */ ++#define TM_ERR_FORMAT_NEGOTIATE_DATATYPE 0x05EU /* Format negotiate type */ ++#define TM_ERR_FORMAT_NEGOTIATE_DATASUBTYPE 0x05FU /* Format negotiate subtype */ ++#define TM_ERR_FORMAT_NEGOTIATE_DESCRIPTION 0x060U /* Format negotiate desc */ ++#define TM_ERR_NULL_FORMAT 0x061U /* Null format */ ++#define TM_ERR_FORMAT_REFERENCE_COUNT 0x062U /* Format reference count */ ++#define TM_ERR_FORMAT_NOT_UNIQUE 0x063U /* Format not unique */ ++#define TM_NEW_FORMAT 0x064U /* New format (not an error) */ ++#define TM_ERR_FORMAT_NEGOTIATE_EXTENSION 0x065U /* Format negotiate extension */ ++#define TM_ERR_INVALID_STATE 0x066U /* Invalid state for function */ ++#define TM_ERR_NULL_CONNECTION 0x067U /* No connection to this pin */ ++#define TM_ERR_OPERATION_NOT_PERMITTED 0x068U /* corresponds to posix EPERM */ ++#define TM_ERR_NOT_CLOCKED 0x069U /* Power down - clocked off */ ++ ++ ++#define PH_ERR_COMPATIBILITY 0x001U /* SW Interface compatibility */ ++#define PH_ERR_MAJOR_VERSION 0x002U /* SW Major Version error */ ++#define PH_ERR_COMP_VERSION 0x003U /* SW component version error */ ++#define PH_ERR_BAD_MODULE_ID 0x004U /* SW - HW module ID error */ ++#define PH_ERR_BAD_UNIT_NUMBER 0x005U /* Invalid device unit number */ ++#define PH_ERR_BAD_INSTANCE 0x006U /* Bad input instance value */ ++#define PH_ERR_BAD_HANDLE 0x007U /* Bad input handle */ ++#define PH_ERR_BAD_INDEX 0x008U /* Bad input index */ ++#define PH_ERR_BAD_PARAMETER 0x009U /* Invalid input parameter */ ++#define PH_ERR_NO_INSTANCES 0x00AU /* No instances available */ ++#define PH_ERR_NO_COMPONENT 0x00BU /* Component is not present */ ++#define PH_ERR_NO_RESOURCES 0x00CU /* Resource is not available */ ++#define PH_ERR_INSTANCE_IN_USE 0x00DU /* Instance is already in use */ ++#define PH_ERR_RESOURCE_OWNED 0x00EU /* Resource is already in use */ ++#define PH_ERR_RESOURCE_NOT_OWNED 0x00FU /* Caller does not own resource */ ++#define PH_ERR_INCONSISTENT_PARAMS 0x010U /* Inconsistent input params */ ++#define PH_ERR_NOT_INITIALIZED 0x011U /* Component is not initialized */ ++#define PH_ERR_NOT_ENABLED 0x012U /* Component is not enabled */ ++#define PH_ERR_NOT_SUPPORTED 0x013U /* Function is not supported */ ++#define PH_ERR_INIT_FAILED 0x014U /* Initialization failed */ ++#define PH_ERR_BUSY 0x015U /* Component is busy */ ++#define PH_ERR_NOT_BUSY 0x016U /* Component is not busy */ ++#define PH_ERR_READ 0x017U /* Read error */ ++#define PH_ERR_WRITE 0x018U /* Write error */ ++#define PH_ERR_ERASE 0x019U /* Erase error */ ++#define PH_ERR_LOCK 0x01AU /* Lock error */ ++#define PH_ERR_UNLOCK 0x01BU /* Unlock error */ ++#define PH_ERR_OUT_OF_MEMORY 0x01CU /* Memory allocation failed */ ++#define PH_ERR_BAD_VIRT_ADDRESS 0x01DU /* Bad virtual address */ ++#define PH_ERR_BAD_PHYS_ADDRESS 0x01EU /* Bad physical address */ ++#define PH_ERR_TIMEOUT 0x01FU /* Timeout error */ ++#define PH_ERR_OVERFLOW 0x020U /* Data overflow/overrun error */ ++#define PH_ERR_FULL 0x021U /* Queue (etc.) is full */ ++#define PH_ERR_EMPTY 0x022U /* Queue (etc.) is empty */ ++#define PH_ERR_NOT_STARTED 0x023U /* Streaming function failed */ ++#define PH_ERR_ALREADY_STARTED 0x024U /* Start function failed */ ++#define PH_ERR_NOT_STOPPED 0x025U /* Non-streaming function failed*/ ++#define PH_ERR_ALREADY_STOPPED 0x026U /* Stop function failed */ ++#define PH_ERR_ALREADY_SETUP 0x027U /* Setup function failed */ ++#define PH_ERR_NULL_PARAMETER 0x028U /* Null input parameter */ ++#define PH_ERR_NULL_DATAINFUNC 0x029U /* Null data input function */ ++#define PH_ERR_NULL_DATAOUTFUNC 0x02AU /* Null data output function */ ++#define PH_ERR_NULL_CONTROLFUNC 0x02BU /* Null control function */ ++#define PH_ERR_NULL_COMPLETIONFUNC 0x02CU /* Null completion function */ ++#define PH_ERR_NULL_PROGRESSFUNC 0x02DU /* Null progress function */ ++#define PH_ERR_NULL_ERRORFUNC 0x02EU /* Null error handler function */ ++#define PH_ERR_NULL_MEMALLOCFUNC 0x02FU /* Null memory alloc function */ ++#define PH_ERR_NULL_MEMFREEFUNC 0x030U /* Null memory free function */ ++#define PH_ERR_NULL_CONFIGFUNC 0x031U /* Null configuration function */ ++#define PH_ERR_NULL_PARENT 0x032U /* Null parent data */ ++#define PH_ERR_NULL_IODESC 0x033U /* Null in/out descriptor */ ++#define PH_ERR_NULL_CTRLDESC 0x034U /* Null control descriptor */ ++#define PH_ERR_UNSUPPORTED_DATACLASS 0x035U /* Unsupported data class */ ++#define PH_ERR_UNSUPPORTED_DATATYPE 0x036U /* Unsupported data type */ ++#define PH_ERR_UNSUPPORTED_DATASUBTYPE 0x037U /* Unsupported data subtype */ ++#define PH_ERR_FORMAT 0x038U /* Invalid/unsupported format */ ++#define PH_ERR_INPUT_DESC_FLAGS 0x039U /* Bad input descriptor flags */ ++#define PH_ERR_OUTPUT_DESC_FLAGS 0x03AU /* Bad output descriptor flags */ ++#define PH_ERR_CAP_REQUIRED 0x03BU /* Capabilities required ??? */ ++#define PH_ERR_BAD_TMALFUNC_TABLE 0x03CU /* Bad TMAL function table */ ++#define PH_ERR_INVALID_CHANNEL_ID 0x03DU /* Invalid channel identifier */ ++#define PH_ERR_INVALID_COMMAND 0x03EU /* Invalid command/request */ ++#define PH_ERR_STREAM_MODE_CONFUSION 0x03FU /* Stream mode config conflict */ ++#define PH_ERR_UNDERRUN 0x040U /* Data underflow/underrun */ ++#define PH_ERR_EMPTY_PACKET_RECVD 0x041U /* Empty data packet received */ ++#define PH_ERR_OTHER_DATAINOUT_ERR 0x042U /* Other data input/output err */ ++#define PH_ERR_STOP_REQUESTED 0x043U /* Stop in progress */ ++#define PH_ERR_ASSERTION 0x049U /* Assertion failure */ ++#define PH_ERR_HIGHWAY_BANDWIDTH 0x04AU /* Highway bandwidth bus error */ ++#define PH_ERR_HW_RESET_FAILED 0x04BU /* Hardware reset failed */ ++#define PH_ERR_BAD_FLAGS 0x04DU /* Bad flags */ ++#define PH_ERR_BAD_PRIORITY 0x04EU /* Bad priority */ ++#define PH_ERR_BAD_REFERENCE_COUNT 0x04FU /* Bad reference count */ ++#define PH_ERR_BAD_SETUP 0x050U /* Bad setup */ ++#define PH_ERR_BAD_STACK_SIZE 0x051U /* Bad stack size */ ++#define PH_ERR_BAD_TEE 0x052U /* Bad tee */ ++#define PH_ERR_IN_PLACE 0x053U /* In place */ ++#define PH_ERR_NOT_CACHE_ALIGNED 0x054U /* Not cache aligned */ ++#define PH_ERR_NO_ROOT_TEE 0x055U /* No root tee */ ++#define PH_ERR_NO_TEE_ALLOWED 0x056U /* No tee allowed */ ++#define PH_ERR_NO_TEE_EMPTY_PACKET 0x057U /* No tee empty packet */ ++#define PH_ERR_NULL_PACKET 0x059U /* Null packet */ ++#define PH_ERR_FORMAT_FREED 0x05AU /* Format freed */ ++#define PH_ERR_FORMAT_INTERNAL 0x05BU /* Format internal */ ++#define PH_ERR_BAD_FORMAT 0x05CU /* Bad format */ ++#define PH_ERR_FORMAT_NEGOTIATE_DATACLASS 0x05DU /* Format negotiate class */ ++#define PH_ERR_FORMAT_NEGOTIATE_DATATYPE 0x05EU /* Format negotiate type */ ++#define PH_ERR_FORMAT_NEGOTIATE_DATASUBTYPE 0x05FU /* Format negotiate subtype */ ++#define PH_ERR_FORMAT_NEGOTIATE_DESCRIPTION 0x060U /* Format negotiate desc */ ++#define PH_ERR_NULL_FORMAT 0x061U /* Null format */ ++#define PH_ERR_FORMAT_REFERENCE_COUNT 0x062U /* Format reference count */ ++#define PH_ERR_FORMAT_NOT_UNIQUE 0x063U /* Format not unique */ ++#define PH_NEW_FORMAT 0x064U /* New format (not an error) */ ++#define PH_ERR_FORMAT_NEGOTIATE_EXTENSION 0x065U /* Format negotiate extension */ ++#define PH_ERR_INVALID_STATE 0x066U /* Invalid state for function */ ++#define PH_ERR_NULL_CONNECTION 0x067U /* No connection to this pin */ ++#define PH_ERR_OPERATION_NOT_PERMITTED 0x068U /* corresponds to posix EPERM */ ++#define PH_ERR_NOT_CLOCKED 0x069U /* Power down - clocked off */ ++ ++/* Add new standard error/progress status codes here */ ++ ++#define TM_ERR_COMP_UNIQUE_START 0x800U /* 0x800-0xBFF: Component unique */ ++#define PH_ERR_COMP_UNIQUE_START 0x800U /* 0x800-0xBFF: Component unique */ ++#define TM_ERR_CUSTOMER_START 0xC00U /* 0xC00-0xDFF: Customer defined */ ++#define PH_ERR_CUSTOMER_START 0xC00U /* 0xC00-0xDFF: Customer defined */ ++ ++/* Legacy and withdrawn error codes */ ++#define TM_ERR_FORMAT_NEGOTIATE_SUBCLASS TM_ERR_FORMAT_NEGOTIATE_DATACLASS ++#define TM_ERR_NEW_FORMAT TM_NEW_FORMAT ++#define TM_ERR_PAUSE_PIN_REQUESTED TM_ERR_STOP_REQUESTED ++#define TM_ERR_PIN_ALREADY_STARTED TM_ERR_ALREADY_STARTED ++#define TM_ERR_PIN_ALREADY_STOPPED TM_ERR_ALREADY_STOPPED ++#define TM_ERR_PIN_NOT_STARTED TM_ERR_NOT_STARTED ++#define TM_ERR_PIN_NOT_STOPPED TM_ERR_NOT_STOPPED ++#define TM_ERR_PIN_PAUSED TM_ERR_NOT_STARTED ++ ++/* -------------------------------------------------------------------------- */ ++/* Standard assert error code start offset */ ++/* NOTE: These ranges are FOR LEGACY CODE ONLY and must not be used in new */ ++/* components */ ++/* -------------------------------------------------------------------------- */ ++#define TM_ERR_ASSERT_START 0xE00U /* 0xE00-0xEFF: Assert failures */ ++#define TM_ERR_ASSERT_LAST 0xEFFU /* Last assert error range value */ ++#define CID_IS_ASSERT_ERROR(compId) ((CID_GET_ERROR(compId) >= TM_ERR_ASSERT_START) && (CID_GET_ERROR(compId) <= TM_ERR_ASSERT_LAST)) ++ ++/* -------------------------------------------------------------------------- */ ++/* Standard fatal error code start offset */ ++/* NOTE: These ranges are FOR LEGACY CODE ONLY and must not be used in new */ ++/* components */ ++/* -------------------------------------------------------------------------- */ ++ ++#define TM_ERR_FATAL_START 0xF00U /* 0xF00-0xFFF: Fatal failures */ ++#define TM_ERR_FATAL_LAST 0xFFFU /* Last fatal error range value */ ++#define CID_IS_FATAL_ERROR(compId) ((CID_GET_ERROR(compId) >= TM_ERR_FATAL_START) && (CID_GET_ERROR(compId) <= TM_ERR_FATAL_LAST)) ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* TMNXCOMPID_H ----------------- */ +diff --git a/drivers/video/nxp/inc/tmNxTypes.h b/drivers/video/nxp/inc/tmNxTypes.h +new file mode 100755 +index 0000000..af67f61 +--- /dev/null ++++ b/drivers/video/nxp/inc/tmNxTypes.h +@@ -0,0 +1,366 @@ ++/*==========================================================================*/ ++/* (Copyright (C) 2003 Koninklijke Philips Electronics N.V. */ ++/* All rights reserved. */ ++/* This source code and any compilation or derivative thereof is the */ ++/* proprietary information of Koninklijke Philips Electronics N.V. */ ++/* and is confidential in nature. */ ++/* Under no circumstances is this software to be exposed to or placed */ ++/* under an Open Source License of any type without the expressed */ ++/* written permission of Koninklijke Philips Electronics N.V. */ ++/*==========================================================================*/ ++/* ++ * Copyright (C) 2000,2001 ++ * Koninklijke Philips Electronics N.V. ++ * All Rights Reserved. ++ * ++ * Copyright (C) 2000,2001 TriMedia Technologies, Inc. ++ * All Rights Reserved. ++ * ++ *############################################################ ++ * ++ * Module name : tmNxTypes.h %version: 7 % ++ * ++ * Last Update : %date_modified: Tue Jul 8 18:08:00 2003 % ++ * ++ * Description: TriMedia/MIPS global type definitions. ++ * ++ * Document Ref: DVP Software Coding Guidelines Specification ++ * DVP/MoReUse Naming Conventions specification ++ * DVP Software Versioning Specification ++ * DVP Device Library Architecture Specification ++ * DVP Board Support Library Architecture Specification ++ * DVP Hardware API Architecture Specification ++ * ++ * ++ *############################################################ ++ */ ++ ++#ifndef TMNXTYPES_H ++#define TMNXTYPES_H ++ ++//----------------------------------------------------------------------------- ++// Standard include files: ++//----------------------------------------------------------------------------- ++// ++ ++//----------------------------------------------------------------------------- ++// Project include files: ++//----------------------------------------------------------------------------- ++// ++#include "tmFlags.h" // DVP common build control flags ++ ++#ifdef __cplusplus ++extern "C" ++{ ++#endif ++ ++//----------------------------------------------------------------------------- ++// Types and defines: ++//----------------------------------------------------------------------------- ++// ++ ++/*Under the TCS, may have been included by our client. In ++ order to avoid errors, we take account of this possibility, but in order to ++ support environments where the TCS is not available, we do not include the ++ file by name.*/ ++ ++#ifndef _TMtypes_h ++#define _TMtypes_h ++ ++#define False 0 ++#define True 1 ++ ++#ifdef __cplusplus ++#define Null 0 ++#else ++#define Null ((Void *) 0) ++#endif ++ ++// ++// Standard Types ++// ++typedef signed char Int8; // 8 bit signed integer ++typedef signed short Int16; // 16 bit signed integer ++typedef signed long Int32; // 32 bit signed integer ++typedef unsigned char UInt8; // 8 bit unsigned integer ++typedef unsigned short UInt16; // 16 bit unsigned integer ++typedef unsigned long UInt32; // 32 bit unsigned integer ++typedef float Float; // 32 bit floating point ++typedef unsigned int Bool; // Boolean (True/False) ++typedef char Char; // character, character array ptr ++typedef int Int; // machine-natural integer ++typedef unsigned int UInt; // machine-natural unsigned integer ++typedef char *String; // Null terminated 8 bit char str ++ ++//----------------------------------------------------------------------------- ++// Legacy TM Types/Structures (Not necessarily DVP Coding Guideline compliant) ++// NOTE: For DVP Coding Gudeline compliant code, do not use these types. ++// ++typedef char *Address; // Ready for address-arithmetic ++typedef char const *ConstAddress; ++typedef unsigned char Byte; // Raw byte ++typedef float Float32; // Single-precision float ++typedef double Float64; // Double-precision float ++typedef void *Pointer; // Pointer to anonymous object ++typedef void const *ConstPointer; ++typedef char const *ConstString; ++ ++typedef Int Endian; ++#define BigEndian 0 ++#define LittleEndian 1 ++ ++typedef struct tmVersion ++{ ++ UInt8 majorVersion; ++ UInt8 minorVersion; ++ UInt16 buildVersion; ++} tmVersion_t, *ptmVersion_t; ++#endif /*ndef _TMtypes_h*/ ++ ++/*Define DVP types that are not TCS types.*/ ++/* ++** ===== Updated from SDE2/2.3_Beta/sde_template/inc/tmNxTypes.h ===== ++** ++** NOTE: IBits32/UBits32 types are defined for use with 32 bit bitfields. ++** This is done because ANSI/ISO compliant compilers require bitfields ++** to be of type "int" else a large number of compiler warnings will ++** result. To avoid the risks associated with redefining Int32/UInt32 ++** to type "int" instead of type "long" (which are the same size on 32 ++** bit CPUs) separate 32bit signed/unsigned bitfield types are defined. ++*/ ++typedef signed int IBits32; /* 32 bit signed integer bitfields */ ++typedef unsigned int UBits32; /* 32 bit unsigned integer bitfields */ ++typedef IBits32 *pIBits32; /* 32 bit signed integer bitfield ptr */ ++typedef UBits32 *pUBits32; /* 32 bit unsigned integer bitfield ptr */ ++ ++typedef Int8 *pInt8; // 8 bit signed integer ++typedef Int16 *pInt16; // 16 bit signed integer ++typedef Int32 *pInt32; // 32 bit signed integer ++typedef UInt8 *pUInt8; // 8 bit unsigned integer ++typedef UInt16 *pUInt16; // 16 bit unsigned integer ++typedef UInt32 *pUInt32; // 32 bit unsigned integer ++typedef void Void, *pVoid; // Void (typeless) ++typedef Float *pFloat; // 32 bit floating point ++typedef double Double, *pDouble; // 32/64 bit floating point ++typedef Bool *pBool; // Boolean (True/False) ++typedef Char *pChar; // character, character array ptr ++typedef Int *pInt; // machine-natural integer ++typedef UInt *pUInt; // machine-natural unsigned integer ++typedef String *pString; // Null terminated 8 bit char str, ++ ++/*Assume that 64-bit integers are supported natively by C99 compilers and Visual ++ C version 6.00 and higher. More discrimination in this area may be added ++ here as necessary.*/ ++#if defined __STDC_VERSION__ && __STDC_VERSION__ > 199409L ++/*This can be enabled only when all explicit references to the hi and lo ++ structure members are eliminated from client code.*/ ++#define TMFL_NATIVE_INT64 1 ++typedef signed long long int Int64, *pInt64; // 64-bit integer ++typedef unsigned long long int UInt64, *pUInt64; // 64-bit bitmask ++// #elif defined _MSC_VER && _MSC_VER >= 1200 ++// /*This can be enabled only when all explicit references to the hi and lo ++// structure members are eliminated from client code.*/ ++// #define TMFL_NATIVE_INT64 1 ++// typedef signed __int64 Int64, *pInt64; // 64-bit integer ++// typedef unsigned __int64 UInt64, *pUInt64; // 64-bit bitmask ++#else /*!(defined __STDC_VERSION__ && __STDC_VERSION__ > 199409L)*/ ++#define TMFL_NATIVE_INT64 0 ++typedef ++ struct ++ { ++ /*Get the correct endianness (this has no impact on any other part of ++ the system, but may make memory dumps easier to understand).*/ ++#if TMFL_ENDIAN == TMFL_ENDIAN_BIG ++ Int32 hi; UInt32 lo; ++#else ++ UInt32 lo; Int32 hi; ++#endif ++ } ++ Int64, *pInt64; // 64-bit integer ++typedef ++ struct ++ { ++#if TMFL_ENDIAN == TMFL_ENDIAN_BIG ++ UInt32 hi; UInt32 lo; ++#else ++ UInt32 lo; UInt32 hi; ++#endif ++ } ++ UInt64, *pUInt64; // 64-bit bitmask ++#endif /*defined __STDC_VERSION__ && __STDC_VERSION__ > 199409L*/ ++ ++// Maximum length of device name in all BSP and capability structures ++#define HAL_DEVICE_NAME_LENGTH 16 ++ ++typedef UInt32 tmErrorCode_t; ++typedef UInt32 tmProgressCode_t; ++ ++/* timestamp definition */ ++typedef UInt64 tmTimeStamp_t, *ptmTimeStamp_t; ++ ++//for backwards compatibility with the older tmTimeStamp_t definition ++#define ticks lo ++#define hiTicks hi ++ ++typedef union tmColor3 // 3 byte color structure ++{ ++ UBits32 u32; ++#if (TMFL_ENDIAN == TMFL_ENDIAN_BIG) ++ struct { ++ UBits32 : 8; ++ UBits32 red : 8; ++ UBits32 green : 8; ++ UBits32 blue : 8; ++ } rgb; ++ struct { ++ UBits32 : 8; ++ UBits32 y : 8; ++ UBits32 u : 8; ++ UBits32 v : 8; ++ } yuv; ++ struct { ++ UBits32 : 8; ++ UBits32 u : 8; ++ UBits32 m : 8; ++ UBits32 l : 8; ++ } uml; ++#else ++ struct { ++ UBits32 blue : 8; ++ UBits32 green : 8; ++ UBits32 red : 8; ++ UBits32 : 8; ++ } rgb; ++ struct { ++ UBits32 v : 8; ++ UBits32 u : 8; ++ UBits32 y : 8; ++ UBits32 : 8; ++ } yuv; ++ struct { ++ UBits32 l : 8; ++ UBits32 m : 8; ++ UBits32 u : 8; ++ UBits32 : 8; ++ } uml; ++#endif ++} tmColor3_t, *ptmColor3_t; ++ ++typedef union tmColor4 // 4 byte color structure ++{ ++ UBits32 u32; ++#if (TMFL_ENDIAN == TMFL_ENDIAN_BIG) ++ struct { ++ UBits32 alpha : 8; ++ UBits32 red : 8; ++ UBits32 green : 8; ++ UBits32 blue : 8; ++ } argb; ++ struct { ++ UBits32 alpha : 8; ++ UBits32 y : 8; ++ UBits32 u : 8; ++ UBits32 v : 8; ++ } ayuv; ++ struct { ++ UBits32 alpha : 8; ++ UBits32 u : 8; ++ UBits32 m : 8; ++ UBits32 l : 8; ++ } auml; ++#else ++ struct { ++ UBits32 blue : 8; ++ UBits32 green : 8; ++ UBits32 red : 8; ++ UBits32 alpha : 8; ++ } argb; ++ struct { ++ UBits32 v : 8; ++ UBits32 u : 8; ++ UBits32 y : 8; ++ UBits32 alpha : 8; ++ } ayuv; ++ struct { ++ UBits32 l : 8; ++ UBits32 m : 8; ++ UBits32 u : 8; ++ UBits32 alpha : 8; ++ } auml; ++#endif ++} tmColor4_t, *ptmColor4_t; ++ ++//----------------------------------------------------------------------------- ++// Hardware device power states ++// ++typedef enum tmPowerState ++{ ++ tmPowerOn, // Device powered on (D0 state) ++ tmPowerStandby, // Device power standby (D1 state) ++ tmPowerSuspend, // Device power suspended (D2 state) ++ tmPowerOff // Device powered off (D3 state) ++ ++} tmPowerState_t, *ptmPowerState_t; ++ ++//----------------------------------------------------------------------------- ++// Software Version Structure ++// ++typedef struct tmSWVersion ++{ ++ UInt32 compatibilityNr; // Interface compatibility number ++ UInt32 majorVersionNr; // Interface major version number ++ UInt32 minorVersionNr; // Interface minor version number ++ ++} tmSWVersion_t, *ptmSWVersion_t; ++ ++/*Under the TCS, may have been included by our client. In ++ order to avoid errors, we take account of this possibility, but in order to ++ support environments where the TCS is not available, we do not include the ++ file by name.*/ ++#ifndef _TMBOARDDEF_H_ ++#define _TMBOARDDEF_H_ ++ ++//----------------------------------------------------------------------------- ++// HW Unit Selection ++// ++typedef Int tmUnitSelect_t, *ptmUnitSelect_t; ++ ++#define tmUnitNone (-1) ++#define tmUnit0 0 ++#define tmUnit1 1 ++#define tmUnit2 2 ++#define tmUnit3 3 ++#define tmUnit4 4 ++ ++/*+compatibility*/ ++#define unitSelect_t tmUnitSelect_t ++#define unit0 tmUnit0 ++#define unit1 tmUnit1 ++#define unit2 tmUnit2 ++#define unit3 tmUnit3 ++#define unit4 tmUnit4 ++#define DEVICE_NAME_LENGTH HAL_DEVICE_NAME_LENGTH ++/*-compatibility*/ ++ ++#endif /*ndef _TMBOARDDEF_H_ */ ++ ++//----------------------------------------------------------------------------- ++// Instance handle ++// ++typedef Int tmInstance_t, *ptmInstance_t; ++ ++// Callback function declaration ++typedef Void (*ptmCallback_t) (UInt32 events, Void *pData, UInt32 userData); ++#define tmCallback_t ptmCallback_t /*compatibility*/ ++ ++// Kernel debugging function declaration ++#ifdef TMFL_CFG_INTELCE4100 ++#define KERN_INFO void ++#define printk(fmt, args...) printf(fmt, ## args) ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif //ndef TMNXTYPES_H +diff --git a/drivers/video/nxp/linux_hdmi_release_note.txt b/drivers/video/nxp/linux_hdmi_release_note.txt +new file mode 100755 +index 0000000..d06be0d +--- /dev/null ++++ b/drivers/video/nxp/linux_hdmi_release_note.txt +@@ -0,0 +1,417 @@ ++Release note: ++ ++------------------------------- ++ HDMI Tx modules for TDA998x ++ by ++ NXP Semiconductors BV ++------------------------------- ++ ++--------------------------------- ++ /!\ WARNING /!\ ++If you want to use the HDMI driver from the user space (easier for non-Linux-expert, but needs to have an I2C driver available ++from the user space), PLEASE DON'T USE THE LINUX DELIVERY. USE THE BASIC DELIVERY INSTEAD, and refer to the install_DL.txt note. ++An exemple of application is available in HdmiTx\sde2\comps\tmdlHdmiTx\tst\tmdlHdmiTx_ExampleApplication\src folder. ++--------------------------------- ++ ++The release note gives all necessary detail for installation in Linux ++kernel and application tunning. Installation is Linux typical and does ++not require any HDMI background. A default video and audio setting is ++defined in hdmi_tx_init function. It can be changed at will. ++There is no porting to do, it is already provided in module. And the ++classical HDMI DevLib is embedded in it. But the UserManual is still ++usefull for customers who like to optimise the module according to ++their needs. If so, feedback is welcome. ;) ++Customers who like to drive the module from userland can do it using ++IOCTL. IOCTL maps the classical HDMI API. Using the WAIT_FRAME IOCTL, ++userland can catch HDMI events like Hot Plug Detect, RxSens or EDID. ++ ++So the two main functions the customer needs to take care are : ++- hdmi_tx_init : to setup the default HDMI settings. These settings can be ++ overwritten using the TDA_SET_INPUT_OUTPUT_CMD IOCTL ++- eventCallbackTx : to fetch HDMI events from userland OR add more ++ automatic behavior in the module itself. For example basic EDID check ++ after reading EDID from the sink. ++ ++For customers who like to understand how the HDMI stack works, please ++read the TRANSMITTER_TDA998X_SW_UM_Devlib.pdf user manuel. You learn that: ++1- this module is a 3 levels stack ++2- HDMI core driver API in defined in comps/tmdlHdmiTx/inc ++ ++HDCP is delivered in a proprietary module to avoid GPL license constraints. ++For customer that uses HDCP, don't forget to get additional stuff from NXP ++ ++For OMAP architecture, a DSS plugin is provided. So to activate ++HDMI (switch DSS to HDMI output) just prompt on target: ++echo "3" > /sys/power/vdd2_lock ++echo "1" > /sys/devices/platform/omapdss/display2/enabled ++And desactivate : ++echo "0" > /sys/devices/platform/omapdss/display2/enabled ++ ++------------------------------- ++ ^ ^ ++/!\ CAUTION /!\ ++--- --- ++ ++This release note and it's FAQ below covers every known questions from customers ++up to now. Thank you for reading it carefully. If you modify the driver, we would ++appreciate to gain from your update. So any feedback is welcome. ++ ++------------------------------- ++ ++- Contains : ++ . HdmiTx Linux module ++ . HdmiCec linux module ++ . HDCP linux module (on request only) ++ . test_hdmi/demo_tda test application ++ . TRANSMITTER_TDA998X_SW_UM_Devlib.pdf for HDMI TX API ++ . HDMI_CEC_User_Manual.pdf for HDMI CEC API ++ . this release note ++ ++- Features : ++ . HDMI transmiter ++ . Hot Plug Detection ++ . HDCP (on request only) ++ . Customer Electronics Control (v1.4) ++ . 3D video format, including frame packing ++ ++- Target : ++ . OMAP3430-ZOOMII (http://omappedia.org/wiki/Android_Getting_Started) ++ ++- OS : ++ . Linux Kernel 2.6.29, Android RLS25.12 ++ ++- Directory : ++ . driver/video/hdmi ++ . driver/video/hdcp (only if hdcp is delivered) ++ ++- Compilation tool : ++ . arm-2007q3-51-arm-none-linux-gnueabi-i686-pc-linux-gnu ++ ++------------------------------- ++ ++- Release : ++ * V1.3.0: 2011, 4th May by Vincent Vrignaud ++ . HDMI1565 improved HDCP robustness in show_video function ++ * V1.2: 2010, 22th Oct by Andre Lepine ++ . TDA19988 support ++ * V1.1: 2010, 15th Oct by Andre Lepine ++ . TDA9983 version (only) has been produced in pure Linux style ++ * V1.03: 2010, 26th Augut by Andre Lepine ++ . USER_SET_INPUT_OUPUT ++ . use suspend mode for event catching when DSS HDMI panel is off (hdmi_disable(1)) ++ . prevent IOCTL from updating power mode when used by DSS HDMI panel ++ * V1.02: 2010, 22th Jully by Andre Lepine ++ . SetHdcp with IOCTL ++ * V1.01: 2010, 15th Jully by Andre Lepine ++ . copy_from_user EDID IOCTL ++ . hdcp_onoff rework ++ . SimplayHD feature ++ . kernel i2c_client ++ . start implementing sysfs_attrs : first is resolution ++ * V1.0: 2010, 1st Jully by Andre Lepine ++ . ATC compliancy ++ . BCaps polling during 5s when CCLK is not devided by 2 ++ . It HPD+RxSens rebound (several changes before SW polling) ++ . EDID used for video mode switch (HDMI, DVI) ++ . blue screen before the HDCP authentification is passed ++ . TDA reset when removing Linux module ++ . hdcp_fail_status not used in TDA9981 ++ * V0.964: 2010, 25th may by Andre Lepine ++ . Check incoming REQUEST_ACTIVE_SOURCE is a broadcast ++ * V0.963: 2010, 21th may by Andre Lepine ++ . External HDCP module validation ++ * V0.963: 2010, 18th may by Andre Lepine ++ . External HDCP module validation ++ * V0.962: 2010, 11th may by Andre Lepine ++ . Clean up ++ * V0.961: 2010, 4th may by Andre Lepine ++ . Put image_view_on under compilation flag because it is not suitable for ++ "only hdmi with videoplay" usecase ++ . DEVICE_VENDOR_ID boradcast after logical address retrival ++ . Allow CEC_OPCODE_VENDOR_COMMAND and CEC_OPCODE_DEVICE_VENDOR_ID (not send FEATURE ABORTED) ++ * V0.96: 2010, 16th april by Andre Lepine ++ . Accept HDCP support using the proprietary module nwolc.ko ++ * V0.95: 2010, 23th march by Andre Lepine ++ . Add TDA9981 driver ++ * V0.94: 2010, 19th march by Andre Lepine ++ . Merge TDA19989, TDA9984 and TDA9983 drivers ++ * V0.92: 2010, 11th march by Andre Lepine ++ . Clean-up ++ . DSS pixclock inversion ++ * V0.91: 2010, 18th february by Andre Lepine ++ . porting for TDA9983 ++ * V0.9: 2010, 2nd february by Andre Lepine ++ . Change directory structure ++ . Update NXP DevLib ++ . CEC & HDP event handeling fix ++ * V0.8: 2010, 18 january by Andre Lepine ++ . Pure IRQ (remove IRQ flag for polling with timer) ++ . Merge with last HdmiTx and HdmiCec version ++ . Cec initialization and power state ++ . Check argument of IOCTL and use -EFAULT when inconsistant ++ * V0.7: 2010, 11 january by Andre Lepine ++ . Automatic CEC answering for following opcodes : ++ > GIVE_PHYSICAL_ADDRESS ++ > GET_CEC_VERSION ++ > GIVE_OSD_NAME ++ > GIVE_DEVICE_VENDOR_ID ++ > REQUEST_ACTIVE_SOURCE ++ > GIVE_DEVICE_POWER_STATUS ++ > STANDBY ++ > SET_STREAM_PATH ++ > ROUTING_CHANGE ++ > ABORT_MESSAGE ++ . Automatic logical address negociation ++ . HdmiCec gets EDID physical address and HDMI status from HdmiTx ++ ++------------------------------- ++ ++- Installation : ++ ++ * On host: ++ . mkdir $KERNEL_MODULES ++ . cp nxp-TDA1998X-linux-hdmi-cec-(hdcp)-L###-DL##-BSL##.tar.cvfj $KERNEL_MODULES/. ++ . cd $KERNEL_MODULES ++ . tar xvfj nxp-TDA1998X-linux-hdmi-cec-(hdcp)-L###-DL##-BSL##.tar.cvfj ++ . update LINUX_DIR in hdmi/MakeModules with your kernel directory path ++ . select your TDA target in Makefile : for example TDA_TX := TDA19988 !!! CAUTION, don't forget this !!! ++ . select your platform in Makefile : for example TDA_PLATFORM := ZOOMII ++ . cd hdmi ++ . make -f MakeModules clean (optional for the first time) ++ . make -f MakeModules (then you get hdmitx.ko and hdmicecc.ko modules) ++ . make -f MakeModules uptx (or any download mean that does not use adb) ++ . make -f MakeModules upcec (or any download mean that does not use adb) (19988/89 only) ++ . cd hdcp (for 19988/89 and 9984 only) ++ . update the KEY_SEED value in comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c ++ . make -f MakeModules (then you get nwolc.ko module) ++ . make -f MakeModules up (or any download mean that does not use adb) ++ * Application (optional), better use your own, this one is just a sample ++ . cd test ++ . make clean (optional for the first time) ++ . make ++ . make upload (or any download mean that does not use adb) ++ * On target: ++ . insmod hdmitx.ko verbose=1 (remove verbose to make the module silent) ++ . insmod hdmicec.ko verbose=1 device=4 (remove verbose to make the module silent) ++ . insmod nwolc.ko (only for HDCP) ++ * On TV ++ . connect TV to target ++ ++- Usage : ++ ++ . hdmitx module parameters used with insmod : ++ > verbose: Make the driver verbose ++ > major: The major number of the device mapper ++ . hdmicec module parameters used with insmod : ++ > verbose: Make the driver verbose ++ > major: The major number of the device mapper ++ > device: Device type can be 0:tv, 1:rec 3:tuner 4:mediaplayer, 5:audio ++ > addr: Physical address (until EDID received) ++ . modules handles automaticaly HPD, EDID and following CEC messaging : ++ device connectivity and addressing, routing, standby, OSD name, ++ vendor name features. ++ . tda_demo test application show how to take control of the two modules ++ from userland and catch CEC messages ++ BUT HDMI MODULES CAN RUN WITHOUT IT ++ . HDCP feature is only supported if nwolc module is installed, you can ++ add it or remove it dynamically using insmod nwolc.ko and rmmod nwolk. ++ ++- FAQ : ++ ++ . "Can I modify file tda998x.c ?" ++ YES ! It's only a kind of "application" sample of the core driver below. ++ Feel free to customize it at will ! ++ ++ . "Can I modify files in comps directoty ?" ++ NO ! Core driver bug shall be discussed with NXP otherwise you may break down ++ some patches and introduce regressions ++ ++ . "this->driver.i2c_client not allocated" : ++ 1) Declare your I2C bus usage in arch/arm/mach-omap2/board-zoom2.c as follow : ++ | static struct i2c_board_info __initdata zoom2_i2c_bus3_info[] = { ++ | {I2C_BOARD_INFO(TX_NAME, TDA998X_I2C_SLAVEADDRESS),}, ++ | {I2C_BOARD_INFO(CEC_NAME, TDA99XCEC_I2C_SLAVEADDRESS),}, ++ | }; ++ 2) Check the TDA target in Makefile : for example TDA_TX := TDA9984 ++ ++ . "Video format and plan are strange..." : ++ Check tda.setio.videoout/in in hdmi_tx_init() function of tda998x.c ++ ++ . "The resolution is not the one I want" : ++ Update or create your own omap_video_timings structure and change ++ the video resolution of this->tda.setio.video_out.format in hdmi_tx_init() ++ ++ . "I want 720p@60Hz" : ++ 1- Line 860: Uncomment> /* this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_04_1280x720p_60Hz; */ ++ 2- Line 862: Comment> this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_02_720x480p_60Hz; ++ 3- Line 1051: Replace> video_720x480at60Hz_panel_timings with video_1280x720at60Hz_panel_timings ++ ++ . "RGB colors are swapped, for example I see RBG instead of RGB" : (for TDA9984 and TDA19989 only) ++ Modify the videoPortMapping_RGB444 video port mapping in comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c. ++ ++ . "YUV signals are swapped, for example I see UVY instead of YUV" : (for TDA9984 and TDA19989 only) ++ Modify the videoPortMapping_YUV444/YUV422 video port mapping in comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c. ++ ++ . "I2C or SPDIF audio does not work, signals are swapped" : (for TDA9984 and TDA19989 only) ++ Modify the enableAudioPortI2S/SPDIF audio port mapping in comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c. ++ ++ . "Where can I find all video format definition ?": ++ in hdmi/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h ++ ++ . "Where can I find all audio format definition ?": ++ in hdmi/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h ++ ++ . "Where can I find all HDMI types definition ?": ++ in hdmi/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h ++ ++ . "Where can I find all power management types definition ?": ++ in hdmi/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h ++ ++ . "Where can I find all HDMI Tx API definition ?": ++ in hdmi/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Functions.h ++ ++ . "Where can I find all HDMI CEC types definition ?": ++ in hdmi/comps/tmdlHdmiCec/inc/tmdlHdmiCec_Types.h ++ ++ . "Where can I find all HDMI CEC API definition ?": ++ in hdmi/comps/tmdlHdmiCec/inc/tmdlHdmiCec_Functions.h ++ ++ . "I would like to get debug message": ++ Install the module with debug messages > insmod hdmitx.ko verbose=1 ++ ++ . "I would like to see the EDID of the TV": ++ Install the module with debug messages > insmod hdmitx.ko verbose=1 ++ ++ . "On the TV display some pixel are flickering": ++ Check the OMAP DSS setup and update the dssdev->panel.config parameters ++ ++ . "CEC send Samsung vendor ID": ++ Yes, otherwise you cannot use Samsung devices... replace is by your own ++ ++ . "I don't use OMAP": ++ This module contains an OMAP Display SubSystem plugin that automatically ++ drives video output of OMAP (video input of TDA). If you don't have OMAP ++ remove the ANDROID_DSS (or add your PLATFORM flag in Makefile) and do ++ the video bus configuration at your convience. Anyhow, any other usefull ++ plugin is welcome... So please feedback ;) ++ ++ . "How to install HDMI module ?": ++ See installation chapter above. ++ ++ . "HDCP is not supported": ++ Ask NXP to deliver you the proprietary HDCP module ++ ++ . "HDCP module does not work": ++ Ask NXP to provide you your customer seed number... ++ ++ . "How can I control the HDMI with my apps ?": ++ Use open("/dev/hdmitx") to get access to HdmiTx module. ++ Then use ioctl as described in tda998x_ioctl.h. ++ ++ . "How can I control CEC with my apps ?": ++ Use open("/dev/hdmicec") to get access to HdmiCec module. ++ Then use ioctl as described in tda998x_ioctl.h. ++ ++ . "How can my application get the HDMI event ?": ++ Create a dedicated incoming event thread in your apps and use ioctl WAIT_EVENT ++ ++ . "Is is mandatory to create an incoming event thread in my apps ?": ++ No if you don't care. ++ ++ . "Did I need to create some apps to make HDMI running ?": ++ No, you can modify hdmi_tx_init according to your needs and install the ++ modules in your init.rc. Hdmi will run automatically. ++ ++ . "HDCP device is not authenticated": ++ Check your personnal customer ROMCODE and update accordingly your KEY_SEED value ++ in comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c ++ ++ . "Where can I get the the KEY_SEED value for HDCP": ++ Ask direcly NXP technical software support ++ ++ . "How can I get PC video format like 600x480" ++ Watch out the "features on demand" part of Makefile ++ ++ . "I don't get any interrupt wired nor IRQ on my board" ++ Remove the IRQ flag for timer based polling of interrupt ++ ++ . "I want to use HDCP" ++ 1) Add the nwolc.ko module (or ask it to NXP) ++ 2) Add TDA_HDCP := TMFL_HDCP_SUPPORT flag ++ 3) set your KEY_SEED number in tmdlHdmiTx_Linux_cfg.c file ++ ++ . "HDCP does not work" ++ Ask you key seed to NXP ++ ++ . "got unexpected TMDS activity between EDID reading and SetInputOuput" ++ use USER_SET_INPUT_OUTPUT flag ++ ++ . "I don't want the module to automatically setup TMDS but from userland instead" ++ use USER_SET_INPUT_OUTPUT flag ++ ++ . "I2S audio does not work, N value is not good" ++ Check the audio frequence in hdmi_tx_init or using IOCTL TDA_SET_AUDIO_INPUT_CMD ++ For example, N=6144 at 48KHz, but N=6272 at 44.1Khz ++ ++ . "I2S audio does not work, CTS value is not good" ++ Check the audio I2S format in hdmi_tx_init or using IOCTL TDA_SET_AUDIO_INPUT_CMD ++ CTS is automatically computed by the TDA accordingly to the audio input ++ so accordingly to the upstream settings (like an OMAP ;) ++ For example, I2S 16 bits or 32 bits do not produce the same CTS value ++ ++ . "How can I change the audio settings ?" ++ Put your own settings in setio.audio_in structure. For example : ++ this->tda.setio.audio_in.format = TMDL_HDMITX_AFMT_I2S; ++ this->tda.setio.audio_in.rate = TMDL_HDMITX_AFS_44K; ++ this->tda.setio.audio_in.i2sFormat = TMDL_HDMITX_I2SFOR_PHILIPS_L; ++ this->tda.setio.audio_in.i2sQualifier = TMDL_HDMITX_I2SQ_16BITS; ++ this->tda.setio.audio_in.dstRate = TMDL_HDMITX_DSTRATE_SINGLE; /* not relevant here */ ++ this->tda.setio.audio_in.channelAllocation = 0; /* audio channel allocation L+R (Ref to CEA-861D p85) */ ++ ++ . "When shall I set audio ?" ++ Default (at module startup) is in hdmi_tx_init ++ At will using IOCTL TDA_SET_AUDIO_INPUT_CMD ++ ++- Restriction : ++ ++ . Remove IRQ flag in Makefile for timer based polling ++ . Add ZOOMII_PATCH to reverse clock edge in ZOOMII ++ . add TWL4030_HACK to get keypad handle and inject CEC::USER_CONTROL events ++ . omap_dss_driver might not be supported by kernel, then hdmi_enable ++ and hdmi_disable should be triggered by any other kernel means or ++ replaced by direct call from application using: ++ --> ioctl(my_fd,TDA_IOCTL_SET_POWER,[tmPowerOn|tmPowerStandby]); ++ . HDCP can be switch off dynamically with TDA_IOCTL_SET_HDCP but not hw engine, ++ stop it by removing nwolc.ko module ++ ++- License : ++ ++ . hdmitx and hdmicec modules are free software; you can redistribute ++ it and/or modify it under the terms of the GNU General Public License ++ as published by the Free Software Foundation, using version 2 of the License. ++ These modules are distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ for more details. ++ . nwolc module source code and any compilation or derivative thereof is ++ the proprietary information of NXP N.V. and is confidential in nature. ++ Under no circumstances is this software to be exposed to or placed under ++ an Open Source License of any type without the expressed written permission ++ of NXP N.V. ++ ++- DV : ++ ++ . How to create a DV : ++ -> update tda998xversion.h and set PATCH_LEVEL to 0 ++ -> update linux_hdmi_release_note.txt ++ $>cd driver/video/hdmi ++ $>make -f MakeModules clean ++ $>cd .. ++ $>tar cvfj $DV_FOLDER/linux-hdmi-nxp-modules.vXYZ.tar.cvfj hdmi ++ ++----------------------------------- ++ ++- Feedback : vincent.vrignaud@nxp.com - ++ ++----------------------------------- ++ +diff --git a/drivers/video/nxp/tda998x.c b/drivers/video/nxp/tda998x.c +new file mode 100755 +index 0000000..4b45e41 +--- /dev/null ++++ b/drivers/video/nxp/tda998x.c +@@ -0,0 +1,2307 @@ ++/*****************************************************************************/ ++/* Copyright (c) 2009 NXP Semiconductors BV */ ++/* */ ++/* This program is free software; you can redistribute it and/or modify */ ++/* it under the terms of the GNU General Public License as published by */ ++/* the Free Software Foundation, using version 2 of the License. */ ++/* */ ++/* This program is distributed in the hope that it will be useful, */ ++/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ ++/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ ++/* GNU General Public License for more details. */ ++/* */ ++/* You should have received a copy of the GNU General Public License */ ++/* along with this program; if not, write to the Free Software */ ++/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */ ++/* USA. */ ++/* */ ++/*****************************************************************************/ ++ ++#define _tx_c_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++// #include ++ ++/* HDMI DevLib */ ++#include "tmNxCompId.h" ++#include "tmdlHdmiTx_Types.h" ++#include "tmdlHdmiTx_Functions.h" ++ ++/* local */ ++#include "tda998x_version.h" ++#include "tda998x.h" ++#include "tda998x_ioctl.h" ++ ++#ifdef I2C_DBG ++#include "tmbslHdmiTx_types.h" ++#include "tmbslTDA9989_local.h" ++#endif ++ ++#ifdef ANDROID_DSS ++/* DSS hack */ ++#endif ++ ++/* ++ * ++ * DEFINITION ++ * ---------- ++ * LEVEL 0 ++ * ++ */ ++ ++#define FRAME_PACKING 200 ++#define NO_FP(x) ((x) % FRAME_PACKING) ++#define IS_FP(x) ((x) > FRAME_PACKING) ++#define WITH_FP(x) ((x) + FRAME_PACKING * (this->tda.setio.video_in.structure3D == TMDL_HDMITX_3D_FRAME_PACKING)) ++/* ++ * Global ++ */ ++ ++tda_instance our_instance; ++static struct cdev our_cdev, *this_cdev=&our_cdev; ++#ifdef ANDROID_DSS ++static struct omap_video_timings video_640x480at60Hz_panel_timings = { ++ .x_res = 640, ++ .y_res = 480, ++ .pixel_clock = 25175, ++ .hfp = 16, ++ .hsw = 96, ++ .hbp = 48, ++ .vfp = 10, ++ .vsw = 2, ++ .vbp = 33, ++}; ++static struct omap_video_timings video_640x480at72Hz_panel_timings = { ++ .x_res = 640, ++ .y_res = 480, ++ .pixel_clock = 31500, ++ .hfp = 24, ++ .hsw = 40, ++ .hbp = 128, ++ .vfp = 9, ++ .vsw = 3, ++ .vbp = 28, ++}; ++static struct omap_video_timings video_720x480at60Hz_panel_timings = { ++ .x_res = 720, ++ .y_res = 480, ++ .pixel_clock = 27027, ++ .hfp = 16, ++ .hbp = 60, ++ .hsw = 62, ++ .vfp = 9, ++ .vbp = 30, ++ .vsw = 6, ++}; ++static struct omap_video_timings video_1280x720at50Hz_panel_timings = { ++ .x_res = 1280, ++ .y_res = 720, ++ .pixel_clock = 74250, ++#ifdef ZOOMII_PATCH ++ .hfp = 400, ++ .hbp = 260, ++#else ++ .hfp = 440, ++ .hbp = 220, ++#endif ++ .hsw = 40, ++ .vfp = 5, ++ .vbp = 20, ++ .vsw = 5, ++}; ++static struct omap_video_timings video_1280x720at60Hz_panel_timings = { ++ .x_res = 1280, ++ .y_res = 720, ++ .pixel_clock = 74250, ++#ifdef ZOOMII_PATCH ++ .hfp = 70, ++ .hbp = 260, ++#else ++ .hfp = 110, ++ .hbp = 220, ++#endif ++ .hsw = 40, ++ .vfp = 5, ++ .vbp = 20, ++ .vsw = 5, ++}; ++static struct omap_video_timings video_1920x1080at50Hz_panel_timings = { ++ .x_res = 1920, ++ .y_res = 1080, ++ .pixel_clock = 148500, /* 2640 x 1125 x 50 /2 */ ++#ifdef ZOOMII_PATCH ++ .hfp = 488, ++ .hbp = 188, ++#else ++ .hfp = 528, ++ .hbp = 148, ++#endif ++ .hsw = 44, ++ .vfp = 4, ++ .vbp = 36, ++ .vsw = 5, ++}; ++static struct omap_video_timings video_800x480at60Hz_panel_timings = { ++ /* .x_res = 800 /\* 1280 *\/, */ ++ /* .y_res = 480 /\* 720 *\/, */ ++ /* .pixel_clock = 21800 /\* 21800 23800 25700 *\/, */ ++ .x_res = 800, ++ .y_res = 480, ++ .pixel_clock = 21800, ++ .hfp = 6, ++ .hsw = 1, ++ .hbp = 4, ++ .vfp = 3, ++ .vsw = 1, ++ .vbp = 4, ++}; ++ ++#endif ++ ++/* #define HDCP_TEST 1 */ ++#ifdef HDCP_TEST ++/* TEST */ ++int test = 0; ++#endif ++ ++/* ++ * Module params ++ */ ++ ++static int param_verbose=0,param_major=0,param_minor=0; ++module_param_named(verbose,param_verbose,int,S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(verbose, "Make the driver verbose"); ++module_param_named(major, param_major, int, S_IRUGO); ++MODULE_PARM_DESC(major, "The major number of the device mapper"); ++ ++/* ++ * ++ * TOOLBOX ++ * ------- ++ * LEVEL 1 ++ * ++ * - i2c read/write ++ * - chip Id check ++ * - i2c client info ++ * ++ */ ++ ++/* ++ * Get main and unique I2C Client driver handle ++ */ ++struct i2c_client *GetThisI2cClient(void) ++{ ++ tda_instance *this=&our_instance; ++ return this->driver.i2c_client; ++} ++ ++/* ++ * error handling ++ */ ++char *hdmi_tx_err_string(int err) ++{ ++ switch (err & 0x0FFF) ++ { ++ case TM_ERR_COMPATIBILITY: {return "SW Interface compatibility";break;} ++ case TM_ERR_MAJOR_VERSION: {return "SW Major Version error";break;} ++ case TM_ERR_COMP_VERSION: {return "SW component version error";break;} ++ case TM_ERR_BAD_UNIT_NUMBER: {return "Invalid device unit number";break;} ++ case TM_ERR_BAD_INSTANCE: {return "Bad input instance value ";break;} ++ case TM_ERR_BAD_HANDLE: {return "Bad input handle";break;} ++ case TM_ERR_BAD_PARAMETER: {return "Invalid input parameter";break;} ++ case TM_ERR_NO_RESOURCES: {return "Resource is not available ";break;} ++ case TM_ERR_RESOURCE_OWNED: {return "Resource is already in use";break;} ++ case TM_ERR_RESOURCE_NOT_OWNED: {return "Caller does not own resource";break;} ++ case TM_ERR_INCONSISTENT_PARAMS: {return "Inconsistent input params";break;} ++ case TM_ERR_NOT_INITIALIZED: {return "Component is not initialised";break;} ++ case TM_ERR_NOT_SUPPORTED: {return "Function is not supported";break;} ++ case TM_ERR_INIT_FAILED: {return "Initialization failed";break;} ++ case TM_ERR_BUSY: {return "Component is busy";break;} ++ case TMDL_ERR_DLHDMITX_I2C_READ: {return "Read error";break;} ++ case TMDL_ERR_DLHDMITX_I2C_WRITE: {return "Write error";break;} ++ case TM_ERR_FULL: {return "Queue is full";break;} ++ case TM_ERR_NOT_STARTED: {return "Function is not started";break;} ++ case TM_ERR_ALREADY_STARTED: {return "Function is already starte";break;} ++ case TM_ERR_ASSERTION: {return "Assertion failure";break;} ++ case TM_ERR_INVALID_STATE: {return "Invalid state for function";break;} ++ case TM_ERR_OPERATION_NOT_PERMITTED: {return "Corresponds to posix EPERM";break;} ++ case TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN: {return "Bad format";break;} ++ case TM_OK: {return "OK";break;} ++ default : {printk(KERN_INFO "(err:%x) ",err);return "unknown";break;} ++ } ++} ++ ++static char *tda_spy_event(int event) ++{ ++ switch (event) ++ { ++ case TMDL_HDMITX_HDCP_ACTIVE: {return "HDCP active";break;} ++ case TMDL_HDMITX_HDCP_INACTIVE: {return "HDCP inactive";break;} ++ case TMDL_HDMITX_HPD_ACTIVE: {return "HPD active";break;} ++ case TMDL_HDMITX_HPD_INACTIVE: {return "HPD inactive";break;} ++ case TMDL_HDMITX_RX_KEYS_RECEIVED: {return "Rx keys received";break;} ++ case TMDL_HDMITX_RX_DEVICE_ACTIVE: {return "Rx device active";break;} ++ case TMDL_HDMITX_RX_DEVICE_INACTIVE: {return "Rx device inactive";break;} ++ case TMDL_HDMITX_EDID_RECEIVED: {return "EDID received";break;} ++ case TMDL_HDMITX_VS_RPT_RECEIVED: {return "VS interrupt has been received";break;} ++ /* case TMDL_HDMITX_B_STATUS: {return "TX received BStatus";break;} */ ++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984) ++ case TMDL_HDMITX_DEBUG_EVENT_1: {return "DEBUG_EVENT_1";break;} ++#endif ++ default : {return "Unkonwn event";break;} ++ } ++} ++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984) ++static char *tda_spy_hsdc_fail_status(int fail) ++{ ++ switch (fail) ++ { ++ case TMDL_HDMITX_HDCP_OK: {return "ok";break;} ++ case TMDL_HDMITX_HDCP_BKSV_RCV_FAIL: {return "Source does not receive Sink BKsv ";break;} ++ case TMDL_HDMITX_HDCP_BKSV_CHECK_FAIL: {return "BKsv does not contain 20 zeros and 20 ones";break;} ++ case TMDL_HDMITX_HDCP_BCAPS_RCV_FAIL: {return "Source does not receive Sink Bcaps";break;} ++ case TMDL_HDMITX_HDCP_AKSV_SEND_FAIL: {return "Source does not send AKsv";break;} ++ case TMDL_HDMITX_HDCP_R0_RCV_FAIL: {return "Source does not receive R'0";break;} ++ case TMDL_HDMITX_HDCP_R0_CHECK_FAIL: {return "R0 = R'0 check fail";break;} ++ case TMDL_HDMITX_HDCP_BKSV_NOT_SECURE: {return "bksv not secure";break;} ++ case TMDL_HDMITX_HDCP_RI_RCV_FAIL: {return "Source does not receive R'i";break;} ++ case TMDL_HDMITX_HDCP_RPT_RI_RCV_FAIL: {return "Source does not receive R'i repeater mode";break;} ++ case TMDL_HDMITX_HDCP_RI_CHECK_FAIL: {return "RI = R'I check fail";break;} ++ case TMDL_HDMITX_HDCP_RPT_RI_CHECK_FAIL: {return "RI = R'I check fail repeater mode";break;} ++ case TMDL_HDMITX_HDCP_RPT_BCAPS_RCV_FAIL: {return "Source does not receive Sink Bcaps repeater mode";break;} ++ case TMDL_HDMITX_HDCP_RPT_BCAPS_READY_TIMEOUT: {return "bcaps ready timeout";break;} ++ case TMDL_HDMITX_HDCP_RPT_V_RCV_FAIL: {return "Source does not receive V";break;} ++ case TMDL_HDMITX_HDCP_RPT_BSTATUS_RCV_FAIL: {return "Source does not receive BSTATUS repeater mode";break;} ++ case TMDL_HDMITX_HDCP_RPT_KSVLIST_RCV_FAIL: {return "Source does not receive Ksv list in repeater mode";break;} ++ case TMDL_HDMITX_HDCP_RPT_KSVLIST_NOT_SECURE: {return "ksvlist not secure";break;} ++ default: {return "";break;} ++ } ++} ++ ++static char *tda_spy_hdcp_status(int status) ++{ ++ switch (status) ++ { ++ case TMDL_HDMITX_HDCP_CHECK_NOT_STARTED: {return "Check not started";break;} ++ case TMDL_HDMITX_HDCP_CHECK_IN_PROGRESS: {return "No failures, more to do";break;} ++ case TMDL_HDMITX_HDCP_CHECK_PASS: {return "Final check has passed";break;} ++ case TMDL_HDMITX_HDCP_CHECK_FAIL_FIRST: {return "First check failure code\nDriver not AUTHENTICATED";break;} ++ case TMDL_HDMITX_HDCP_CHECK_FAIL_DEVICE_T0: {return "A T0 interrupt occurred";break;} ++ case TMDL_HDMITX_HDCP_CHECK_FAIL_DEVICE_RI: {return "Device RI changed";break;} ++ case TMDL_HDMITX_HDCP_CHECK_FAIL_DEVICE_FSM: {return "Device FSM not 10h";break;} ++ default : {return "Unknown hdcp status";break;} ++ } ++ ++} ++#endif ++ ++static char *tda_spy_sink(int sink) ++{ ++ switch (sink) ++ { ++ case TMDL_HDMITX_SINK_DVI: {return "DVI";break;} ++ case TMDL_HDMITX_SINK_HDMI: {return "HDMI";break;} ++ case TMDL_HDMITX_SINK_EDID: {return "As currently defined in EDID";break;} ++ default : {return "Unkonwn sink";break;} ++ } ++} ++ ++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984) ++static char *tda_spy_aspect_ratio(int ar) ++{ ++ switch (ar) ++ { ++ case TMDL_HDMITX_P_ASPECT_RATIO_UNDEFINED: {return "Undefined picture aspect rati";break;} ++ case TMDL_HDMITX_P_ASPECT_RATIO_6_5: {return "6:5 picture aspect ratio (PAR";break;} ++ case TMDL_HDMITX_P_ASPECT_RATIO_5_4: {return "5:4 PA";break;} ++ case TMDL_HDMITX_P_ASPECT_RATIO_4_3: {return "4:3 PA";break;} ++ case TMDL_HDMITX_P_ASPECT_RATIO_16_10: {return "16:10 PA";break;} ++ case TMDL_HDMITX_P_ASPECT_RATIO_5_3: {return "5:3 PA";break;} ++ case TMDL_HDMITX_P_ASPECT_RATIO_16_9: {return "16:9 PA";break;} ++ case TMDL_HDMITX_P_ASPECT_RATIO_9_5: {return "9:5 PA";break;} ++ default : {return "Unknown aspect ratio";break;} ++ } ++} ++ ++#if 0 /* no more used */ ++static char *tda_spy_edid_status(int status) ++{ ++ switch (status) ++ { ++ case TMDL_HDMITX_EDID_READ: {return "All blocks read";break;} ++ case TMDL_HDMITX_EDID_READ_INCOMPLETE: {return "All blocks read OK but buffer too small to return all of the";break;} ++ case TMDL_HDMITX_EDID_ERROR_CHK_BLOCK_0: {return "Block 0 checksum erro";break;} ++ case TMDL_HDMITX_EDID_ERROR_CHK: {return "Block 0 OK, checksum error in one or more other block";break;} ++ case TMDL_HDMITX_EDID_NOT_READ: {return "EDID not read";break;} ++ case TMDL_HDMITX_EDID_STATUS_INVALID: {return "Invalid ";break;} ++ default : {return "Unknown edid status";break;} ++ } ++} ++#endif ++ ++static char *tda_spy_vfmt(int fmt) ++{ ++ switch (fmt) ++ { ++ case TMDL_HDMITX_VFMT_NULL: {return "NOT a valid format...";break;} ++ case TMDL_HDMITX_VFMT_01_640x480p_60Hz: {return "vic 01: 640x480p 60Hz";break;} ++ case TMDL_HDMITX_VFMT_02_720x480p_60Hz: {return "vic 02: 720x480p 60Hz";break;} ++ case TMDL_HDMITX_VFMT_03_720x480p_60Hz: {return "vic 03: 720x480p 60Hz";break;} ++ case TMDL_HDMITX_VFMT_04_1280x720p_60Hz: {return "vic 04: 1280x720p 60Hz";break;} ++ case TMDL_HDMITX_VFMT_05_1920x1080i_60Hz: {return "vic 05: 1920x1080i 60Hz";break;} ++ case TMDL_HDMITX_VFMT_06_720x480i_60Hz: {return "vic 06: 720x480i 60Hz";break;} ++ case TMDL_HDMITX_VFMT_07_720x480i_60Hz: {return "vic 07: 720x480i 60Hz";break;} ++ case TMDL_HDMITX_VFMT_08_720x240p_60Hz: {return "vic 08: 720x240p 60Hz";break;} ++ case TMDL_HDMITX_VFMT_09_720x240p_60Hz: {return "vic 09: 720x240p 60Hz";break;} ++ case TMDL_HDMITX_VFMT_10_720x480i_60Hz: {return "vic 10: 720x480i 60Hz";break;} ++ case TMDL_HDMITX_VFMT_11_720x480i_60Hz: {return "vic 11: 720x480i 60Hz";break;} ++ case TMDL_HDMITX_VFMT_12_720x240p_60Hz: {return "vic 12: 720x240p 60Hz";break;} ++ case TMDL_HDMITX_VFMT_13_720x240p_60Hz: {return "vic 13: 720x240p 60Hz";break;} ++ case TMDL_HDMITX_VFMT_14_1440x480p_60Hz: {return "vic 14: 1440x480p 60Hz";break;} ++ case TMDL_HDMITX_VFMT_15_1440x480p_60Hz: {return "vic 15: 1440x480p 60Hz";break;} ++ case TMDL_HDMITX_VFMT_16_1920x1080p_60Hz: {return "vic 16: 1920x1080p 60Hz";break;} ++ case TMDL_HDMITX_VFMT_17_720x576p_50Hz: {return "vic 17: 720x576p 50Hz";break;} ++ case TMDL_HDMITX_VFMT_18_720x576p_50Hz: {return "vic 18: 720x576p 50Hz";break;} ++ case TMDL_HDMITX_VFMT_19_1280x720p_50Hz: {return "vic 19: 1280x720p 50Hz";break;} ++ case TMDL_HDMITX_VFMT_20_1920x1080i_50Hz: {return "vic 20: 1920x1080i 50Hz";break;} ++ case TMDL_HDMITX_VFMT_21_720x576i_50Hz: {return "vic 21: 720x576i 50Hz";break;} ++ case TMDL_HDMITX_VFMT_22_720x576i_50Hz: {return "vic 22: 720x576i 50Hz";break;} ++ case TMDL_HDMITX_VFMT_23_720x288p_50Hz: {return "vic 23: 720x288p 50Hz";break;} ++ case TMDL_HDMITX_VFMT_24_720x288p_50Hz: {return "vic 24: 720x288p 50Hz";break;} ++ case TMDL_HDMITX_VFMT_25_720x576i_50Hz: {return "vic 25: 720x576i 50Hz";break;} ++ case TMDL_HDMITX_VFMT_26_720x576i_50Hz: {return "vic 26: 720x576i 50Hz";break;} ++ case TMDL_HDMITX_VFMT_27_720x288p_50Hz: {return "vic 27: 720x288p 50Hz";break;} ++ case TMDL_HDMITX_VFMT_28_720x288p_50Hz: {return "vic 28: 720x288p 50Hz";break;} ++ case TMDL_HDMITX_VFMT_29_1440x576p_50Hz: {return "vic 29: 1440x576p 50Hz";break;} ++ case TMDL_HDMITX_VFMT_30_1440x576p_50Hz: {return "vic 30: 1440x576p 50Hz";break;} ++ case TMDL_HDMITX_VFMT_31_1920x1080p_50Hz: {return "vic 31: 1920x1080p 50Hz";break;} ++ case TMDL_HDMITX_VFMT_32_1920x1080p_24Hz: {return "vic 32: 1920x1080p 24Hz";break;} ++ case TMDL_HDMITX_VFMT_33_1920x1080p_25Hz: {return "vic 33: 1920x1080p 25Hz";break;} ++ case TMDL_HDMITX_VFMT_34_1920x1080p_30Hz: {return "vic 34: 1920x1080p 30Hz";break;} ++ case TMDL_HDMITX_VFMT_35_2880x480p_60Hz: {return "vic 3: 2880x480p 60Hz";break;} ++ case TMDL_HDMITX_VFMT_36_2880x480p_60Hz: {return "vic 3: 2880x480p 60Hz";break;} ++ case TMDL_HDMITX_VFMT_37_2880x576p_50Hz: {return "vic 3: 2880x576p 50Hz";break;} ++ case TMDL_HDMITX_VFMT_38_2880x576p_50Hz: {return "vic 3: 2880x576p 50Hz";break;} ++ case TMDL_HDMITX_VFMT_60_1280x720p_24Hz: {return "vic 60: 1280x720p 24Hz";break;} ++ case TMDL_HDMITX_VFMT_61_1280x720p_25Hz: {return "vic 61: 1280x720p 25Hz";break;} ++ case TMDL_HDMITX_VFMT_62_1280x720p_30Hz: {return "vic 62: 1280x720p 30Hz";break;} ++ case TMDL_HDMITX_VFMT_PC_800x600p_60Hz: {return "PC 129";break;} ++ case TMDL_HDMITX_VFMT_PC_1152x960p_60Hz: {return "PC 130";break;} ++ case TMDL_HDMITX_VFMT_PC_1024x768p_60Hz: {return "PC 131";break;} ++ case TMDL_HDMITX_VFMT_PC_1280x768p_60Hz: {return "PC 132";break;} ++ case TMDL_HDMITX_VFMT_PC_1280x1024p_60Hz: {return "PC 133";break;} ++ case TMDL_HDMITX_VFMT_PC_1360x768p_60Hz: {return "PC 134";break;} ++ case TMDL_HDMITX_VFMT_PC_1400x1050p_60Hz: {return "PC 135";break;} ++ case TMDL_HDMITX_VFMT_PC_1600x1200p_60Hz: {return "PC 136";break;} ++ case TMDL_HDMITX_VFMT_PC_1024x768p_70Hz: {return "PC 137";break;} ++ case TMDL_HDMITX_VFMT_PC_640x480p_72Hz: {return "PC 138";break;} ++ case TMDL_HDMITX_VFMT_PC_800x600p_72Hz: {return "PC 139";break;} ++ case TMDL_HDMITX_VFMT_PC_640x480p_75Hz: {return "PC 140";break;} ++ case TMDL_HDMITX_VFMT_PC_1024x768p_75Hz: {return "PC 141";break;} ++ case TMDL_HDMITX_VFMT_PC_800x600p_75Hz: {return "PC 142";break;} ++ case TMDL_HDMITX_VFMT_PC_1024x864p_75Hz: {return "PC 143";break;} ++ case TMDL_HDMITX_VFMT_PC_1280x1024p_75Hz: {return "PC 144";break;} ++ case TMDL_HDMITX_VFMT_PC_640x350p_85Hz: {return "PC 145";break;} ++ case TMDL_HDMITX_VFMT_PC_640x400p_85Hz: {return "PC 146";break;} ++ case TMDL_HDMITX_VFMT_PC_720x400p_85Hz: {return "PC 147";break;} ++ case TMDL_HDMITX_VFMT_PC_640x480p_85Hz: {return "PC 148";break;} ++ case TMDL_HDMITX_VFMT_PC_800x600p_85Hz: {return "PC 149";break;} ++ case TMDL_HDMITX_VFMT_PC_1024x768p_85Hz: {return "PC 150";break;} ++ case TMDL_HDMITX_VFMT_PC_1152x864p_85Hz: {return "PC 151";break;} ++ case TMDL_HDMITX_VFMT_PC_1280x960p_85Hz: {return "PC 152";break;} ++ case TMDL_HDMITX_VFMT_PC_1280x1024p_85Hz: {return "PC 153";break;} ++ case TMDL_HDMITX_VFMT_PC_1024x768i_87Hz: {return "PC 154";break;} ++ case FRAME_PACKING + TMDL_HDMITX_VFMT_02_720x480p_60Hz: {return "vic 02: 720x480p 60Hz frame packing";break;} ++ case FRAME_PACKING + TMDL_HDMITX_VFMT_17_720x576p_50Hz: {return "vic 17: 720x576p 50Hz frame packing";break;} ++ case FRAME_PACKING + TMDL_HDMITX_VFMT_60_1280x720p_24Hz: {return "vic 60: 1280x720p 24Hz frame packing";break;} ++ case FRAME_PACKING + TMDL_HDMITX_VFMT_61_1280x720p_25Hz: {return "vic 61: 1280x720p 25Hz frame packing";break;} ++ case FRAME_PACKING + TMDL_HDMITX_VFMT_62_1280x720p_30Hz: {return "vic 62: 1280x720p 30Hz frame packing";break;} ++ case FRAME_PACKING + TMDL_HDMITX_VFMT_19_1280x720p_50Hz: {return "vic 19: 1280x720p 50Hz frame packing";break;} ++ case FRAME_PACKING + TMDL_HDMITX_VFMT_04_1280x720p_60Hz: {return "vic 04: 1280x720p 60Hz frame packing";break;} ++ case FRAME_PACKING + TMDL_HDMITX_VFMT_32_1920x1080p_24Hz: {return "vic 32: 1920x1080p 24Hz frame packing";break;} ++ case FRAME_PACKING + TMDL_HDMITX_VFMT_33_1920x1080p_25Hz: {return "vic 33: 1920x1080p 25Hz frame packing";break;} ++ case FRAME_PACKING + TMDL_HDMITX_VFMT_34_1920x1080p_30Hz: {return "vic 34: 1920x1080p 30Hz frame packing";break;} ++ case FRAME_PACKING + TMDL_HDMITX_VFMT_31_1920x1080p_50Hz: {return "vic 31: 1920x1080p 50Hz frame packing";break;} ++ case FRAME_PACKING + TMDL_HDMITX_VFMT_16_1920x1080p_60Hz: {return "vic 16: 1920x1080p 60Hz frame packing";break;} ++ default : {return "unknown video format";break;} ++ } ++} ++#endif ++ ++static char *tda_spy_audio_fmt(int fmt) ++{ ++ switch (fmt) ++ { ++ case TMDL_HDMITX_AFMT_SPDIF: {return "SPDIF";break;} ++ case TMDL_HDMITX_AFMT_I2S: {return "I2S";break;} ++ case TMDL_HDMITX_AFMT_OBA: {return "OBA";break;} ++ case TMDL_HDMITX_AFMT_DST: {return "DST";break;} ++ case TMDL_HDMITX_AFMT_HBR: {return "HBR";break;} ++ default : {return "Unknown audio format";break;} ++ } ++} ++ ++static char *tda_spy_audio_freq(int freq) ++{ ++ switch (freq) ++ { ++ case TMDL_HDMITX_AFS_32K: {return "32k";break;} ++ case TMDL_HDMITX_AFS_44K: {return "44k";break;} ++ case TMDL_HDMITX_AFS_48K: {return "48k";break;} ++ case TMDL_HDMITX_AFS_88K: {return "88k";break;} ++ case TMDL_HDMITX_AFS_96K: {return "96k";break;} ++ case TMDL_HDMITX_AFS_176K: {return "176k";break;} ++ case TMDL_HDMITX_AFS_192K: {return "192k";break;} ++ default : {return "Unknown audio freq";break;} ++ } ++} ++ ++static char *tda_spy_audio_i2c(int bits) ++{ ++ switch (bits) ++ { ++ case TMDL_HDMITX_I2SQ_16BITS: {return "16 bits";break;} ++ case TMDL_HDMITX_I2SQ_32BITS: {return "32 bits";break;} ++ default : {return "Unknown audio i2c sampling";break;} ++ } ++} ++ ++static char *tda_spy_audio_i2c4(int align) ++{ ++ switch (align) ++ { ++ case TMDL_HDMITX_I2SFOR_PHILIPS_L: {return "Philips Left";break;} ++ case TMDL_HDMITX_I2SFOR_OTH_L: {return "other left";break;} ++ case TMDL_HDMITX_I2SFOR_OTH_R: {return "other right";break;} ++ default : {return "Unknown audio I2C alignement";break;} ++ } ++} ++ ++static void tda_spy_audio(tmdlHdmiTxAudioInConfig_t *audio) ++{ ++ printk(KERN_INFO "hdmitx audio input\n format:%d(%s) rate:%d(%s) i2c_format:%d(%s) i2c_qualif:%d(%s) dst_rate:%d channel:%d\n", \ ++ audio->format, \ ++ tda_spy_audio_fmt(audio->format), \ ++ audio->rate, \ ++ tda_spy_audio_freq(audio->rate), \ ++ audio->i2sFormat, \ ++ tda_spy_audio_i2c4(audio->i2sFormat), \ ++ audio->i2sQualifier, \ ++ tda_spy_audio_i2c(audio->i2sQualifier), \ ++ audio->dstRate, \ ++ audio->channelAllocation); ++ } ++ ++ ++static char *tda_ioctl(int io) ++{ ++ switch (io) ++ { ++ case TDA_VERBOSE_ON_CMD: {return "TDA_VERBOSE_ON_CMD";break;} ++ case TDA_VERBOSE_OFF_CMD: {return "TDA_VERBOSE_OFF_CMD";break;} ++ case TDA_BYEBYE_CMD: {return "TDA_BYEBYE_CMD";break;} ++ case TDA_GET_SW_VERSION_CMD: {return "TDA_GET_SW_VERSION_CMD";break;} ++ case TDA_SET_POWER_CMD: {return "TDA_SET_POWER_CMD";break;} ++ case TDA_GET_POWER_CMD: {return "TDA_GET_POWER_CMD";break;} ++ case TDA_SETUP_CMD: {return "TDA_SETUP_CMD";break;} ++ case TDA_GET_SETUP_CMD: {return "TDA_GET_SETUP_CMD";break;} ++ case TDA_WAIT_EVENT_CMD: {return "TDA_WAIT_EVENT_CMD";break;} ++ case TDA_ENABLE_EVENT_CMD: {return "TDA_ENABLE_EVENT_CMD";break;} ++ case TDA_DISABLE_EVENT_CMD: {return "TDA_DISABLE_EVENT_CMD";break;} ++ case TDA_GET_VIDEO_SPEC_CMD: {return "TDA_GET_VIDEO_SPEC_CMD";break;} ++ case TDA_SET_INPUT_OUTPUT_CMD: {return "TDA_SET_INPUT_OUTPUT_CMD";break;} ++ case TDA_SET_AUDIO_INPUT_CMD: {return "TDA_SET_AUDIO_INPUT_CMD";break;} ++ case TDA_SET_VIDEO_INFOFRAME_CMD: {return "TDA_SET_VIDEO_INFOFRAME_CMD";break;} ++ case TDA_SET_AUDIO_INFOFRAME_CMD: {return "TDA_SET_AUDIO_INFOFRAME_CMD";break;} ++ case TDA_SET_ACP_CMD: {return "TDA_SET_ACP_CMD";break;} ++ case TDA_SET_GCP_CMD: {return "TDA_SET_GCP_CMD";break;} ++ case TDA_SET_ISRC1_CMD: {return "TDA_SET_ISRC1_CMD";break;} ++ case TDA_SET_ISRC2_CMD: {return "TDA_SET_ISRC2_CMD";break;} ++ case TDA_SET_MPS_INFOFRAME_CMD: {return "TDA_SET_MPS_INFOFRAME_CMD";break;} ++ case TDA_SET_SPD_INFOFRAME_CMD: {return "TDA_SET_SPD_INFOFRAME_CMD";break;} ++ case TDA_SET_VS_INFOFRAME_CMD: {return "TDA_SET_VS_INFOFRAME_CMD";break;} ++ case TDA_SET_AUDIO_MUTE_CMD: {return "TDA_SET_AUDIO_MUTE_CMD";break;} ++ case TDA_RESET_AUDIO_CTS_CMD: {return "TDA_RESET_AUDIO_CTS_CMD";break;} ++ case TDA_GET_EDID_STATUS_CMD: {return "TDA_GET_EDID_STATUS_CMD";break;} ++ case TDA_GET_EDID_AUDIO_CAPS_CMD: {return "TDA_GET_EDID_AUDIO_CAPS_CMD";break;} ++ case TDA_GET_EDID_VIDEO_CAPS_CMD: {return "TDA_GET_EDID_VIDEO_CAPS_CMD";break;} ++ case TDA_GET_EDID_VIDEO_PREF_CMD: {return "TDA_GET_EDID_VIDEO_PREF_CMD";break;} ++ case TDA_GET_EDID_SINK_TYPE_CMD: {return "TDA_GET_EDID_SINK_TYPE_CMD";break;} ++ case TDA_GET_EDID_SOURCE_ADDRESS_CMD: {return "TDA_GET_EDID_SOURCE_ADDRESS_CMD";break;} ++ case TDA_SET_GAMMUT_CMD: {return "TDA_SET_GAMMUT_CMD";break;} ++ case TDA_GET_EDID_DTD_CMD: {return "TDA_GET_EDID_DTD_CMD";break;} ++ case TDA_GET_EDID_MD_CMD: {return "TDA_GET_EDID_MD_CMD";break;} ++ case TDA_GET_EDID_TV_ASPECT_RATIO_CMD: {return "TDA_GET_EDID_TV_ASPECT_RATIO_CMD";break;} ++ case TDA_GET_EDID_LATENCY_CMD: {return "TDA_GET_EDID_LATENCY_CMD";break;} ++ case TDA_GET_HPD_STATUS_CMD: {return "TDA_GET_HPD_STATUS_CMD";break;} ++ default : {return "unknown";break;} ++ } ++ ++ ++} ++ ++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984) ++/* ++ * ++ */ ++static int tda_spy(int verbose) ++{ ++ tda_instance *this=&our_instance; ++ int i,err=0; ++ ++ if (!verbose) { ++ return err; ++ } ++ ++ printk(KERN_INFO "\n\n"); ++ this->tda.edid_video_caps.max=EXAMPLE_MAX_SVD; ++ TRY(tmdlHdmiTxGetEdidVideoCaps(this->tda.instance, \ ++ this->tda.edid_video_caps.desc, \ ++ this->tda.edid_video_caps.max, \ ++ &this->tda.edid_video_caps.written, \ ++ &this->tda.edid_video_caps.flags)); ++ printk(KERN_INFO "written:%d\n",this->tda.edid_video_caps.written); ++ printk(KERN_INFO "flags:0X%x\n",this->tda.edid_video_caps.flags); ++ if (this->tda.edid_video_caps.written > this->tda.edid_video_caps.max) { ++ printk(KERN_ERR "get %d video caps but was waiting for %d\n", \ ++ this->tda.edid_video_caps.written, \ ++ this->tda.edid_video_caps.max); ++ this->tda.edid_video_caps.written = this->tda.edid_video_caps.max; ++ } ++ for(i=0; itda.edid_video_caps.written;i++) { ++ printk(KERN_INFO "videoFormat: %s\n",tda_spy_vfmt(this->tda.edid_video_caps.desc[i].videoFormat)); ++ printk(KERN_INFO "nativeVideoFormat:%s\n",(this->tda.edid_video_caps.desc[i].nativeVideoFormat?"yes":"no")); ++ } ++ ++ printk(KERN_INFO "\n\n"); ++ TRY(tmdlHdmiTxGetEdidVideoPreferred(this->tda.instance, \ ++ &this->tda.edid_video_timings)); ++ printk(KERN_INFO "Pixel Clock/10 000:%d\n",this->tda.edid_video_timings.pixelClock); ++ printk(KERN_INFO "Horizontal Active Pixels:%d\n",this->tda.edid_video_timings.hActivePixels); ++ printk(KERN_INFO "Horizontal Blanking Pixels:%d\n",this->tda.edid_video_timings.hBlankPixels); ++ printk(KERN_INFO "Vertical Active Lines:%d\n",this->tda.edid_video_timings.vActiveLines); ++ printk(KERN_INFO "Vertical Blanking Lines:%d\n",this->tda.edid_video_timings.vBlankLines); ++ printk(KERN_INFO "Horizontal Sync Offset:%d\n",this->tda.edid_video_timings.hSyncOffset); ++ printk(KERN_INFO "Horiz. Sync Pulse Width:%d\n",this->tda.edid_video_timings.hSyncWidth); ++ printk(KERN_INFO "Vertical Sync Offset:%d\n",this->tda.edid_video_timings.vSyncOffset); ++ printk(KERN_INFO "Vertical Sync Pulse Width:%d\n",this->tda.edid_video_timings.vSyncWidth); ++ printk(KERN_INFO "Horizontal Image Size:%d\n",this->tda.edid_video_timings.hImageSize); ++ printk(KERN_INFO "Vertical Image Size:%d\n",this->tda.edid_video_timings.vImageSize); ++ printk(KERN_INFO "Horizontal Border:%d\n",this->tda.edid_video_timings.hBorderPixels); ++ printk(KERN_INFO "Vertical Border:%d\n",this->tda.edid_video_timings.vBorderPixels); ++ printk(KERN_INFO "Interlace/sync info:%x\n",this->tda.edid_video_timings.flags); ++ ++ printk(KERN_INFO "\n\n"); ++ TRY(tmdlHdmiTxGetEdidSinkType(this->tda.instance, \ ++ &this->tda.setio.sink)); ++ printk(KERN_INFO "%s\n",tda_spy_sink(this->tda.setio.sink)); ++ printk(KERN_INFO "\n\n"); ++ TRY(tmdlHdmiTxGetEdidSourceAddress(this->tda.instance, \ ++ &this->tda.src_address)); ++ printk(KERN_INFO "%x\n",this->tda.src_address); ++ printk(KERN_INFO "\n\n"); ++ this->tda.edid_dtd.max=EXAMPLE_MAX_SVD; ++ TRY(tmdlHdmiTxGetEdidDetailledTimingDescriptors(this->tda.instance, \ ++ this->tda.edid_dtd.desc, \ ++ this->tda.edid_dtd.max, \ ++ &this->tda.edid_dtd.written)); ++ printk(KERN_INFO "Interlace/sync info:%x\n",this->tda.edid_dtd.desc[i].flags); ++ printk(KERN_INFO "written:%d\n",this->tda.edid_dtd.written); ++ if (this->tda.edid_dtd.written > this->tda.edid_dtd.max) { ++ printk(KERN_ERR "get %d video caps but was waiting for %d\n", \ ++ this->tda.edid_dtd.written, \ ++ this->tda.edid_dtd.max); ++ this->tda.edid_dtd.written = this->tda.edid_dtd.max; ++ } ++ for(i=0; itda.edid_dtd.written;i++) { ++ printk(KERN_INFO "Pixel Clock/10 000:%d\n",this->tda.edid_dtd.desc[i].pixelClock); ++ printk(KERN_INFO "Horizontal Active Pixels:%d\n",this->tda.edid_dtd.desc[i].hActivePixels); ++ printk(KERN_INFO "Horizontal Blanking Pixels:%d\n",this->tda.edid_dtd.desc[i].hBlankPixels); ++ printk(KERN_INFO "Vertical Active Lines:%d\n",this->tda.edid_dtd.desc[i].vActiveLines); ++ printk(KERN_INFO "Vertical Blanking Lines:%d\n",this->tda.edid_dtd.desc[i].vBlankLines); ++ printk(KERN_INFO "Horizontal Sync Offset:%d\n",this->tda.edid_dtd.desc[i].hSyncOffset); ++ printk(KERN_INFO "Horiz. Sync Pulse Width:%d\n",this->tda.edid_dtd.desc[i].hSyncWidth); ++ printk(KERN_INFO "Vertical Sync Offset:%d\n",this->tda.edid_dtd.desc[i].vSyncOffset); ++ printk(KERN_INFO "Vertical Sync Pulse Width:%d\n",this->tda.edid_dtd.desc[i].vSyncWidth); ++ printk(KERN_INFO "Horizontal Image Size:%d\n",this->tda.edid_dtd.desc[i].hImageSize); ++ printk(KERN_INFO "Vertical Image Size:%d\n",this->tda.edid_dtd.desc[i].vImageSize); ++ printk(KERN_INFO "Horizontal Border:%d\n",this->tda.edid_dtd.desc[i].hBorderPixels); ++ printk(KERN_INFO "Vertical Border:%d\n",this->tda.edid_dtd.desc[i].vBorderPixels); ++ } ++ ++ printk(KERN_INFO "\n\n"); ++ this->tda.edid_md.max=EXAMPLE_MAX_SVD; ++ TRY(tmdlHdmiTxGetEdidMonitorDescriptors(this->tda.instance, \ ++ this->tda.edid_md.desc1, \ ++ this->tda.edid_md.desc2, \ ++ this->tda.edid_md.other, \ ++ this->tda.edid_md.max, \ ++ &this->tda.edid_md.written)); ++ printk(KERN_INFO "written:%d\n",this->tda.edid_md.written); ++ if (this->tda.edid_md.written > this->tda.edid_md.max) { ++ printk(KERN_ERR "get %d video caps but was waiting for %d\n", \ ++ this->tda.edid_md.written, \ ++ this->tda.edid_md.max); ++ this->tda.edid_md.written = this->tda.edid_md.max; ++ } ++ for(i=0; itda.edid_md.written;i++) { ++ if (this->tda.edid_md.desc1[i].descRecord) { ++ this->tda.edid_md.desc1[i].monitorName[EDID_MONITOR_DESCRIPTOR_SIZE-1]=0; ++ printk(KERN_INFO "Monitor name:%s\n",this->tda.edid_md.desc1[i].monitorName); ++ } ++ if (this->tda.edid_md.desc1[i].descRecord) { ++ printk(KERN_INFO "Min vertical rate in Hz:%d\n",this->tda.edid_md.desc2[i].minVerticalRate); ++ printk(KERN_INFO "Max vertical rate in Hz:%d\n",this->tda.edid_md.desc2[i].maxVerticalRate); ++ printk(KERN_INFO "Min horizontal rate in Hz:%d\n",this->tda.edid_md.desc2[i].minHorizontalRate); ++ printk(KERN_INFO "Max horizontal rate in Hz:%d\n",this->tda.edid_md.desc2[i].maxHorizontalRate); ++ printk(KERN_INFO "Max supported pixel clock rate in MHz:%d\n",this->tda.edid_md.desc2[i].maxSupportedPixelClk); ++ } ++ } ++ ++ printk(KERN_INFO "\n\n"); ++ TRY(tmdlHdmiTxGetEdidTVPictureRatio(this->tda.instance, \ ++ &this->tda.edid_tv_aspect_ratio)); ++ printk(KERN_INFO "%s\n",tda_spy_aspect_ratio(this->tda.edid_tv_aspect_ratio)); ++ ++ printk(KERN_INFO "\n\n"); ++ TRY(tmdlHdmiTxGetEdidLatencyInfo(this->tda.instance, \ ++ &this->tda.edid_latency)); ++ if (this->tda.edid_latency.latency_available) { ++ printk(KERN_INFO "Edid video:%d\n",this->tda.edid_latency.Edidvideo_latency); ++ printk(KERN_INFO "Edid audio:%d\n",this->tda.edid_latency.Edidaudio_latency); ++ } ++ if (this->tda.edid_latency.Ilatency_available) { ++ printk(KERN_INFO "Edid Ivideo:%d\n",this->tda.edid_latency.EdidIvideo_latency); ++ printk(KERN_INFO "Edid Iaudio:%d\n",this->tda.edid_latency.EdidIaudio_latency); ++ } ++ TRY_DONE: ++ return err; ++} ++#endif ++ ++/* ++ * ++ * PROCESSING ++ * ---------- ++ * LEVEL 2 ++ * ++ * - ++ * ++ */ ++ ++/* ++ * On HDCP ++ */ ++void hdcp_on(tda_instance *this) { ++ ++ int err=0; ++ ++ if (this->tda.hdcp_status != HDCP_IS_NOT_INSTALLED) { /* check HDCP is installed ... */ ++ if (this->tda.hdcp_enable) { /* ... but requested ! */ ++ TRY(tmdlHdmiTxSetHdcp(this->tda.instance,True)); /* switch if on */ ++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984) ++ /* hide video content until HDCP authentification is finished */ ++ if (!this->tda.setup.simplayHd) { ++ TRY(tmdlHdmiTxSetBScreen(this->tda.instance,TMDL_HDMITX_PATTERN_BLUE)); ++ } ++#endif ++ } ++ } ++ TRY_DONE: ++ (void)0; ++} ++ ++/* ++ * Off HDCP ++ */ ++void hdcp_off(tda_instance *this) { ++ ++ int err=0; ++ ++ if (this->tda.hdcp_status != HDCP_IS_NOT_INSTALLED) { /* check HDCP is installed ... */ ++ ++ if (this->tda.hdcp_enable) { /* but no more requested */ ++ TRY(tmdlHdmiTxSetHdcp(this->tda.instance,False)); /* switch if off */ ++ } ++ } ++ TRY_DONE: ++ (void)0; ++} ++ ++/* ++ * Run video ++ */ ++void show_video(tda_instance *this) { ++ ++ int err=0; ++ ++ if (this->tda.rx_device_active) { /* check RxSens */ ++ if (this->tda.hot_plug_detect == TMDL_HDMITX_HOTPLUG_ACTIVE) { /* should be useless, but legacy... */ ++ if (this->tda.power == tmPowerOn) { /* check CEC or DSS didn't switch it off */ ++ if (this->tda.src_address != 0xFFFF) { /* check EDID has been received */ ++ hdcp_off(this); ++ TRY(tmdlHdmiTxSetInputOutput(this->tda.instance, \ ++ this->tda.setio.video_in, \ ++ this->tda.setio.video_out, \ ++ this->tda.setio.audio_in, \ ++ this->tda.setio.sink)); ++ hdcp_on(this); ++ /* ++ Mind that SetInputOutput disable the blue color matrix settings of tmdlHdmiTxSetBScreen ... ++ so put tmdlHdmiTxSetBScreen (or hdcp_on) always after ++ */ ++ } ++ } ++ } ++ } ++ ++ TRY_DONE: ++ (void)0; ++} ++ ++/* ++ * TDA interrupt polling ++ */ ++static void interrupt_polling(struct work_struct *dummy) ++{ ++ tda_instance *this=&our_instance; ++ int err=0; ++ ++ /* Tx part */ ++ TRY(tmdlHdmiTxHandleInterrupt(this->tda.instance)); ++ ++ /* CEC part */ ++ if (this->driver.cec_callback) this->driver.cec_callback(dummy); ++ ++ /* FIX : IT anti debounce */ ++ TRY(tmdlHdmiTxHandleInterrupt(this->tda.instance)); ++ ++ TRY_DONE: ++ ++ /* setup next polling */ ++#ifndef IRQ ++ mod_timer(&this->driver.no_irq_timer,jiffies + ( CHECK_EVERY_XX_MS * HZ / 1000 )); ++#endif ++ ++ (void)0; ++} ++ ++/* ++ * TDA interrupt polling ++ */ ++static void hdcp_check(struct work_struct *dummy) ++{ ++ int err=0; ++ tda_instance *this=&our_instance; ++ tmdlHdmiTxHdcpCheck_t hdcp_status; ++ ++ down(&this->driver.sem); ++ ++ if (this->tda.hdcp_status == HDCP_IS_NOT_INSTALLED) goto TRY_DONE; ++ ++ TRY(tmdlHdmiTxHdcpCheck(this->tda.instance,HDCP_CHECK_EVERY_MS)); ++ TRY(tmdlHdmiTxGetHdcpState(this->tda.instance, &hdcp_status)); ++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984) ++ if (this->tda.hdcp_status != hdcp_status) { ++ LOG(KERN_INFO,"HDCP status:%s\n",tda_spy_hdcp_status(hdcp_status)); ++ this->tda.hdcp_status = hdcp_status; ++ } ++#endif ++#ifdef HDCP_TEST ++ /* TEST */ ++ if (test++>500) { ++ test=0; ++ this->tda.hdcp_enable=1-this->tda.hdcp_enable; ++ printk("TEST hdcp:%d\n",this->tda.hdcp_enable); ++ if (this->tda.rx_device_active) { /* check RxSens */ ++ if (this->tda.hot_plug_detect == TMDL_HDMITX_HOTPLUG_ACTIVE) { /* should be useless, but legacy... */ ++ if (this->tda.power == tmPowerOn) { /* check CEC didn't switch it off */ ++ if (this->tda.src_address != 0xFFFF) { /* check EDID has been received */ ++ hdcp_off(this); ++ hdcp_on(this); ++ } ++ } ++ } ++ } ++ } ++#endif ++ ++ TRY_DONE: ++ ++ /* setup next polling */ ++ mod_timer(&this->driver.hdcp_check,jiffies + ( HDCP_CHECK_EVERY_MS * HZ / 1000 )); ++ ++ up(&this->driver.sem); ++} ++ ++void register_cec_interrupt(cec_callback_t fct) ++{ ++ tda_instance *this=&our_instance; ++ ++ this->driver.cec_callback = fct; ++} ++EXPORT_SYMBOL(register_cec_interrupt); ++ ++void unregister_cec_interrupt(void) ++{ ++ tda_instance *this=&our_instance; ++ ++ this->driver.cec_callback = NULL; ++} ++EXPORT_SYMBOL(unregister_cec_interrupt); ++ ++static DECLARE_WORK(wq_irq, interrupt_polling); ++void polling_timeout(unsigned long arg) ++{ ++ /* derefered because ATOMIC context of timer does not support I2C_transfert */ ++ schedule_work(&wq_irq); ++} ++ ++static DECLARE_WORK(wq_hdcp, hdcp_check); ++void hdcp_check_timeout(unsigned long arg) ++{ ++ /* derefered because ATOMIC context of timer does not support I2C_transfert */ ++ schedule_work(&wq_hdcp); ++} ++ ++#ifdef IRQ ++/* ++ * TDA irq ++ */ ++static irqreturn_t tda_irq(int irq, void *_udc) ++{ ++ ++ /* do it now */ ++ schedule_work(&wq_irq); ++ ++ return IRQ_HANDLED; ++} ++#endif ++ ++/* ++ * TDA callback ++ */ ++static void eventCallbackTx(tmdlHdmiTxEvent_t event) ++{ ++ tda_instance *this=&our_instance; ++ int err=0; ++ unsigned short new_addr; ++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984) ++ tda_hdcp_fail hdcp_fail; ++#endif ++ ++ this->tda.event=event; ++ if (TMDL_HDMITX_HDCP_INACTIVE != event) { ++ printk(KERN_INFO "hdmi %s\n",tda_spy_event(event)); ++ } ++ ++ switch (event) { ++ case TMDL_HDMITX_EDID_RECEIVED: ++ TRY(tmdlHdmiTxGetEdidSourceAddress(this->tda.instance, \ ++ &new_addr)); ++ LOG(KERN_INFO,"phy.@:%x\n",new_addr); ++ /* if (this->tda.src_address == new_addr) { */ ++ /* break; */ ++ /* } */ ++ this->tda.src_address = new_addr; ++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984) ++ tda_spy(this->param.verbose>1); ++#endif ++ /* ++ Customer may add stuff to analyse EDID (see tda_spy()) ++ and select automatically some video/audio settings. ++ By default, let go on with next case and activate ++ default video/audio settings with tmdlHdmiTxSetInputOutput() ++ */ ++ ++ TRY(tmdlHdmiTxGetEdidSinkType(this->tda.instance, \ ++ &this->tda.setio.sink)); ++ if (TMDL_HDMITX_SINK_HDMI != this->tda.setio.sink) { ++ printk(KERN_INFO "/!\\ CAUTION /!\\ sink is not HDMI but %s\n",tda_spy_sink(this->tda.setio.sink)); ++ } ++ ++ msleep(100); ++ /* ++ /!\ WARNING /! \ ++ the core driver does not send any HPD nor RXSENS when HDMI was plugged after at boot time ++ and only EDID_RECEIVED is send, so rx_device_active shall be forced now. ++ Do not skip the next case nor add any break here please ++ */ ++ case TMDL_HDMITX_RX_DEVICE_ACTIVE: /* TV is ready to receive */ ++ this->tda.rx_device_active = 1; ++ show_video(this); ++ break; ++ case TMDL_HDMITX_RX_DEVICE_INACTIVE: /* TV is ignoring the source */ ++ this->tda.rx_device_active = 0; ++ break; ++ case TMDL_HDMITX_HPD_ACTIVE: /* HDMI is so funny u can get RxSens without being plugged !!! */ ++ this->tda.hot_plug_detect = TMDL_HDMITX_HOTPLUG_ACTIVE; ++ show_video(this); ++ break; ++ case TMDL_HDMITX_HPD_INACTIVE: /* unplug */ ++ this->tda.hot_plug_detect = TMDL_HDMITX_HOTPLUG_INACTIVE; ++ this->tda.src_address = 0xFFFF; ++ break; ++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984) ++ case TMDL_HDMITX_HDCP_INACTIVE: /* HDCP drops off */ ++ tmdlHdmiTxGetHdcpFailStatus(this->tda.instance, \ ++ &hdcp_fail, \ ++ &this->tda.hdcp_raw_status); ++ if (this->tda.hdcp_fail != hdcp_fail) { ++ if (this->tda.hdcp_fail) { ++ LOG(KERN_INFO,"%s (%d)\n",tda_spy_hsdc_fail_status(this->tda.hdcp_fail),this->tda.hdcp_raw_status); ++ } ++ this->tda.hdcp_fail = hdcp_fail; ++ tmdlHdmiTxSetBScreen(this->tda.instance,TMDL_HDMITX_PATTERN_BLUE); ++ } ++ break; ++ case TMDL_HDMITX_RX_KEYS_RECEIVED: /* end of HDCP authentification */ ++ if (!this->tda.setup.simplayHd) { ++ tmdlHdmiTxRemoveBScreen(this->tda.instance); ++ } ++ break; ++#endif ++ default: ++ break; ++ } ++ ++ this->driver.poll_done=true; ++ wake_up_interruptible(&this->driver.wait); ++ ++ TRY_DONE: ++ (void)0; ++} ++ ++/* ++ * hdmi Tx init ++ */ ++static int hdmi_tx_init(tda_instance *this) ++{ ++ int err=0; ++ ++ LOG(KERN_INFO,"called\n"); ++ ++ ++ /*Initialize HDMI Transmiter*/ ++ TRY(tmdlHdmiTxOpen(&this->tda.instance)); ++ /* Register the HDMI TX events callbacks */ ++ TRY(tmdlHdmiTxRegisterCallbacks(this->tda.instance,(ptmdlHdmiTxCallback_t)eventCallbackTx)); ++ /* EnableEvent, all by default */ ++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,TMDL_HDMITX_HDCP_ACTIVE)); ++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,TMDL_HDMITX_HDCP_INACTIVE)); ++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,TMDL_HDMITX_HPD_ACTIVE)); ++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,TMDL_HDMITX_HPD_INACTIVE)); ++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,TMDL_HDMITX_RX_KEYS_RECEIVED)); ++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,TMDL_HDMITX_RX_DEVICE_ACTIVE)); ++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,TMDL_HDMITX_RX_DEVICE_INACTIVE)); ++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,TMDL_HDMITX_EDID_RECEIVED)); ++ ++ /* Size of the application EDID buffer */ ++ this->tda.setup.edidBufferSize=EDID_BLOCK_COUNT * EDID_BLOCK_SIZE; ++ /* Buffer to store the application EDID data */ ++ this->tda.setup.pEdidBuffer=this->tda.raw_edid; ++ /* To Enable/disable repeater feature, nor relevant here */ ++ this->tda.setup.repeaterEnable=false; ++ /* To enable/disable simplayHD feature: blue screen when not authenticated */ ++#ifdef SIMPLAYHD ++ this->tda.setup.simplayHd=(this->tda.hdcp_enable?true:false); ++#else ++ this->tda.setup.simplayHd=false; ++#endif ++ ++ /* Provides HDMI TX instance configuration */ ++ TRY(tmdlHdmiTxInstanceSetup(this->tda.instance,&this->tda.setup)); ++ /* Get IC version */ ++ TRY(tmdlHdmiTxGetCapabilities(&this->tda.capabilities)); ++ ++ /* Main settings */ ++ this->tda.setio.video_out.mode = TMDL_HDMITX_VOUTMODE_RGB444; ++ this->tda.setio.video_out.colorDepth = TMDL_HDMITX_COLORDEPTH_24; ++#ifdef TMFL_TDA19989 ++ this->tda.setio.video_out.dviVqr = TMDL_HDMITX_VQR_DEFAULT; /* Use HDMI rules for DVI output */ ++#endif ++ /* this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_31_1920x1080p_50Hz; */ ++ /* this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_PC_640x480p_60Hz; */ ++ /* this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_PC_640x480p_72Hz; */ ++ // this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_04_1280x720p_60Hz; ++ /* this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_19_1280x720p_50Hz; */ ++ this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_02_720x480p_60Hz; ++ ++ this->tda.setio.video_in.mode = TMDL_HDMITX_VINMODE_RGB444; ++ /* this->tda.setio.video_in.mode = TMDL_HDMITX_VINMODE_CCIR656; */ ++ /* this->tda.setio.video_in.mode = TMDL_HDMITX_VINMODE_YUV422; */ ++ this->tda.setio.video_in.format = this->tda.setio.video_out.format; ++ this->tda.setio.video_in.pixelRate = TMDL_HDMITX_PIXRATE_SINGLE; ++ this->tda.setio.video_in.syncSource = TMDL_HDMITX_SYNCSRC_EXT_VS; /* we use HS,VS as synchronisation source */ ++ ++ this->tda.setio.audio_in.format = TMDL_HDMITX_AFMT_I2S; /* audio I2S is coming in */ ++ this->tda.setio.audio_in.rate = TMDL_HDMITX_AFS_48K; /* audio sampling rate */ ++ this->tda.setio.audio_in.i2sFormat = TMDL_HDMITX_I2SFOR_PHILIPS_L; /* I2S format of the audio input */ ++ this->tda.setio.audio_in.i2sQualifier = TMDL_HDMITX_I2SQ_32BITS; /* we use a 32 bits bus */ ++ this->tda.setio.audio_in.dstRate = TMDL_HDMITX_DSTRATE_SINGLE; /* not relevant here */ ++ this->tda.setio.audio_in.channelAllocation = 0; /* audio channel allocation (Ref to CEA-861D p85) */ ++ /* set default channel status */ ++ this->tda.setio.audio_in.channelStatus.PcmIdentification = TMDL_HDMITX_AUDIO_DATA_PCM; ++ this->tda.setio.audio_in.channelStatus.CopyrightInfo = TMDL_HDMITX_CSCOPYRIGHT_PROTECTED; ++ this->tda.setio.audio_in.channelStatus.FormatInfo = TMDL_HDMITX_CSFI_PCM_2CHAN_NO_PRE; ++ this->tda.setio.audio_in.channelStatus.categoryCode = 0x00; ++ this->tda.setio.audio_in.channelStatus.clockAccuracy = TMDL_HDMITX_CSCLK_LEVEL_II; ++ this->tda.setio.audio_in.channelStatus.maxWordLength = TMDL_HDMITX_CSMAX_LENGTH_20; ++ this->tda.setio.audio_in.channelStatus.wordLength = TMDL_HDMITX_CSWORD_DEFAULT; ++ this->tda.setio.audio_in.channelStatus.origSampleFreq = TMDL_HDMITX_CSOFREQ_NOT_INDICATED; ++ ++ ++ this->tda.setio.sink = TMDL_HDMITX_SINK_HDMI; /* skip edid reading */ ++ /* this->tda.src_address = 0x1000; /\* debug *\/ */ ++ this->tda.src_address = NO_PHY_ADDR; /* it's unref */ ++ ++ TRY_DONE: ++ return err; ++} ++ ++void reset_hdmi(int hdcp_module) ++{ ++ tda_instance *this=&our_instance; ++ int err=0; ++ ++ down(&this->driver.sem); ++ ++ /* PATCH because of SetPowerState that calls SetHdcp that has just been removed by nwolc :( */ ++ if (hdcp_module==2) { ++ tmdlHdmiTxSetHdcp(this->tda.instance,0); ++ goto TRY_DONE; ++ } ++ ++ TRY(tmdlHdmiTxSetPowerState(this->tda.instance,tmPowerStandby)); ++ tmdlHdmiTxClose(this->tda.instance); ++ ++ /* reset */ ++ this->tda.hdcp_enable = (hdcp_module?1:0); ++ hdmi_tx_init(this); ++ /* recover previous power state */ ++ TRY(tmdlHdmiTxSetPowerState(this->tda.instance,this->tda.power)); ++ tmdlHdmiTxGetHPDStatus(this->tda.instance,&this->tda.hot_plug_detect); /* check if activ for timer */ ++#ifndef USER_SET_INPUT_OUTPUT ++ show_video(this); ++#endif ++ ++ /* wake up or shut down hdcp checking */ ++ if (hdcp_module) { ++ this->driver.hdcp_check.expires = jiffies + ( HDCP_CHECK_EVERY_MS * HZ / 1000 ); ++ add_timer(&this->driver.hdcp_check); ++ this->tda.hdcp_status = TMDL_HDMITX_HDCP_CHECK_NOT_STARTED; ++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984) ++ tmdlHdmiTxSetBScreen(this->tda.instance,TMDL_HDMITX_PATTERN_BLUE); ++#endif ++ } ++ else { ++ del_timer(&this->driver.hdcp_check); ++ this->tda.hdcp_status = HDCP_IS_NOT_INSTALLED; ++ } ++ ++ TRY_DONE: ++ up(&this->driver.sem); ++} ++EXPORT_SYMBOL(reset_hdmi); ++ ++/* ++ * ++ */ ++short edid_phy_addr(void) ++{ ++ tda_instance *this=&our_instance; ++ ++ return this->tda.src_address; ++} ++EXPORT_SYMBOL(edid_phy_addr); ++ ++/* ++ * ++ */ ++tda_power get_hdmi_status(void) ++{ ++ tda_instance *this=&our_instance; ++ ++ return this->tda.power; ++} ++EXPORT_SYMBOL(get_hdmi_status); ++ ++/* ++ * ++ */ ++tda_power get_hpd_status(void) ++{ ++ tda_instance *this=&our_instance; ++ ++ return (this->tda.hot_plug_detect == TMDL_HDMITX_HOTPLUG_ACTIVE); ++} ++EXPORT_SYMBOL(get_hpd_status); ++ ++/* ++ * ++ */ ++int edid_received(void) ++{ ++ tda_instance *this=&our_instance; ++ ++ return (this->tda.event == TMDL_HDMITX_EDID_RECEIVED); ++} ++EXPORT_SYMBOL(edid_received); ++ ++/* ++ * ++ */ ++int hdmi_enable(void) ++{ ++ tda_instance *this=&our_instance; ++ int err=0; ++ ++ LOG(KERN_INFO,"called\n"); ++ ++ down(&this->driver.sem); ++ ++ this->driver.omap_dss_hdmi_panel = true; ++ ++ this->tda.power = tmPowerOn; ++ TRY(tmdlHdmiTxSetPowerState(this->tda.instance,this->tda.power)); ++ if (err==TM_ERR_NO_RESOURCES) { ++ LOG(KERN_INFO,"Busy...\n"); ++ TRY(tmdlHdmiTxHandleInterrupt(this->tda.instance)); ++ TRY(tmdlHdmiTxHandleInterrupt(this->tda.instance)); ++ TRY(tmdlHdmiTxHandleInterrupt(this->tda.instance)); ++ } ++ tmdlHdmiTxGetHPDStatus(this->tda.instance,&this->tda.hot_plug_detect); ++ show_video(this); ++ ++ TRY_DONE: ++ up(&this->driver.sem); ++ return err; ++} ++EXPORT_SYMBOL(hdmi_enable); ++ ++/* ++ * ++ */ ++int hdmi_disable(int event_tracking) ++{ ++ tda_instance *this=&our_instance; ++ int err=0; ++ ++ LOG(KERN_INFO,"called\n"); ++ ++ down(&this->driver.sem); ++ this->tda.power = (event_tracking?tmPowerSuspend:tmPowerStandby); ++ TRY(tmdlHdmiTxSetPowerState(this->tda.instance,this->tda.power)); ++ ++ TRY_DONE: ++ this->driver.omap_dss_hdmi_panel = false; ++ up(&this->driver.sem); ++ return err; ++} ++EXPORT_SYMBOL(hdmi_disable); ++ ++/* ++ * ++ * ENTRY POINTS ++ * ------------ ++ * LEVEL 3 ++ * ++ * - ++ * ++ */ ++ ++#ifdef ANDROID_DSS ++/* ++ * DSS driver :: probe ++ */ ++static int hdmi_panel_probe(struct omap_dss_device *dssdev) ++{ ++ tda_instance *this=&our_instance; ++ ++ LOG(KERN_INFO," called\n"); ++ ++ /* OMAP_DSS_LCD_IVS = 1<<0, */ ++ /* OMAP_DSS_LCD_IHS = 1<<1, */ ++ /* OMAP_DSS_LCD_IPC = 1<<2, */ ++ /* OMAP_DSS_LCD_IEO = 1<<3, */ ++ /* OMAP_DSS_LCD_RF = 1<<4, */ ++ /* OMAP_DSS_LCD_ONOFF = 1<<5, */ ++ /* OMAP_DSS_LCD_TFT = 1<<20, */ ++ ++ dssdev->panel.config = OMAP_DSS_LCD_ONOFF | OMAP_DSS_LCD_IPC | \ ++ OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS; ++ dssdev->panel.timings = video_1280x720at50Hz_panel_timings; ++ (void)video_1280x720at60Hz_panel_timings; ++ (void)video_720x480at60Hz_panel_timings; ++ (void)video_1280x720at50Hz_panel_timings; ++ (void)video_800x480at60Hz_panel_timings; ++ (void)video_1280x720at50Hz_panel_timings; ++ (void)video_1920x1080at50Hz_panel_timings; ++ (void)video_640x480at72Hz_panel_timings; ++ (void)video_640x480at60Hz_panel_timings; ++ ++ return 0; ++} ++ ++/* ++ * DSS driver :: enable ++ */ ++static void hdmi_panel_remove(struct omap_dss_device *dssdev) ++{ ++} ++ ++/* ++ * DSS driver :: enable ++ */ ++static int hdmi_panel_enable(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ if (dssdev->platform_enable) ++ r = dssdev->platform_enable(dssdev); ++ ++ if (r) ++ goto ERROR0; ++ ++ r = hdmi_enable(); ++ if (r) ++ goto ERROR0; ++ /* wait couple of vsyncs until enabling the LCD */ ++ msleep(50); ++ ++ return 0; ++ ERROR0: ++ return r; ++} ++ ++/* ++ * DSS driver :: disable ++ */ ++static void hdmi_panel_disable(struct omap_dss_device *dssdev) ++{ ++ hdmi_disable(1); /* keep HPD int actif */ ++ ++ /* wait couple of vsyncs until enabling the hdmi */ ++ msleep(50); ++ ++ if (dssdev->platform_disable) ++ dssdev->platform_disable(dssdev); ++} ++ ++/* ++ * DSS driver :: suspend ++ */ ++static int hdmi_panel_suspend(struct omap_dss_device *dssdev) ++{ ++ hdmi_panel_disable(dssdev); ++ return 0; ++} ++ ++/* ++ * DSS driver :: resume ++ */ ++static int hdmi_panel_resume(struct omap_dss_device *dssdev) ++{ ++ return hdmi_panel_enable(dssdev); ++} ++ ++/* ++ * DSS driver (frontend with omapzoom) ++ * ----------------------------------- ++ */ ++static struct omap_dss_driver hdmi_driver = { ++ .probe = hdmi_panel_probe, ++ .remove = hdmi_panel_remove, ++ .enable = hdmi_panel_enable, ++ .disable = hdmi_panel_disable, ++ .suspend = hdmi_panel_suspend, ++ .resume = hdmi_panel_resume, ++ .driver = { ++ .name = "hdmi_panel", ++ .owner = THIS_MODULE, ++ } ++}; ++#endif ++ ++/* ++ * ioctl driver :: opening ++ */ ++ ++static int this_cdev_open(struct inode *pInode, struct file *pFile) ++{ ++ tda_instance *this; ++ int minor=iminor(pInode); ++ ++ if(minor >= MAX_MINOR) { ++ printk(KERN_ERR "hdmitx:%s:only one tda can be open\n",__func__); ++ return -EINVAL; ++ } ++ ++ if ((pFile->private_data != NULL) && (pFile->private_data != &our_instance)) { ++ printk(KERN_ERR "hdmitx:%s:pFile missmatch\n",__func__); ++ } ++ this = pFile->private_data = &our_instance; ++ down(&this->driver.sem); ++ ++ LOG(KERN_INFO,"major:%d minor:%d user:%d\n", imajor(pInode), iminor(pInode), this->driver.user_counter); ++ ++ if ((this->driver.user_counter++) && (this->driver.minor == minor)) { ++ /* init already done */ ++ up(&this->driver.sem); ++ return 0; ++ } ++ this->driver.minor = minor; ++ ++ ++ up(&this->driver.sem); ++ return 0; ++} ++ ++/* ++ * ioctl driver :: ioctl ++ */ ++static int this_cdev_ioctl(struct inode *pInode, struct file *pFile, unsigned int cmd, unsigned long arg) ++{ ++ tda_instance* this = pFile->private_data; ++ int err=0; ++ ++ LOG(KERN_INFO,":%s\n",tda_ioctl(_IOC_NR(cmd))); ++ ++ BUG_ON(this->driver.minor!=iminor(pInode)); ++ if (_IOC_TYPE(cmd) != TDA_IOCTL_BASE) { ++ printk(KERN_INFO "hdmitx:%s:unknown ioctl type: %x\n",__func__,_IOC_TYPE(cmd)); ++ return -ENOIOCTLCMD; ++ } ++ ++ if (_IOC_DIR(cmd) & _IOC_READ) ++ err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)) || !arg; ++ else if (_IOC_DIR(cmd) & _IOC_WRITE) ++ err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)) || !arg; ++ if (err) { ++ printk(KERN_ERR "hdmitx:%s:argument access denied (check address vs value)\n",__func__); ++ printk(KERN_ERR "_IOC_DIR:%d arg:%lx\n",_IOC_DIR(cmd),arg); ++ return -EFAULT; ++ } ++ ++ down(&this->driver.sem); ++ ++ /* Check DevLib consistancy here */ ++ ++ switch ( _IOC_NR(cmd) ) ++ { ++ case TDA_VERBOSE_ON_CMD: ++ { ++ this->param.verbose=1; ++ printk(KERN_INFO "hdmitx:verbose on\n"); ++ break; ++ } ++ ++ case TDA_VERBOSE_OFF_CMD: ++ { ++ printk(KERN_INFO "hdmitx:verbose off\n"); ++ this->param.verbose=0; ++ break; ++ } ++ ++ case TDA_BYEBYE_CMD: ++ { ++ LOG(KERN_INFO,"release event handeling request\n"); ++ this->tda.event=RELEASE; ++ this->driver.poll_done = true; ++ wake_up_interruptible(&this->driver.wait); ++ break; ++ } ++ ++ case TDA_GET_SW_VERSION_CMD: ++ { ++ TRY(tmdlHdmiTxGetSWVersion(&this->tda.version)); ++ BUG_ON(copy_to_user((tda_version*)arg,&this->tda.version,sizeof(tda_version)) != 0); ++ break; ++ } ++ ++ case TDA_SET_POWER_CMD: ++ { ++ if (this->driver.omap_dss_hdmi_panel) { ++ /* DSS uses HDMI panel => do not switch the power through the ioctl, this will be done be DSS */ ++ } ++ else { ++ BUG_ON(copy_from_user(&this->tda.power,(tda_power*)arg,sizeof(tda_power)) != 0); ++ TRY(tmdlHdmiTxSetPowerState(this->tda.instance,this->tda.power)); ++ } ++ break; ++ } ++ ++ case TDA_GET_POWER_CMD: ++ { ++ TRY(tmdlHdmiTxGetPowerState(this->tda.instance, \ ++ &this->tda.power)); ++ BUG_ON(copy_to_user((tda_power*)arg,&this->tda.power,sizeof(tda_power)) != 0); ++ break; ++ } ++ ++ case TDA_SETUP_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.setup,(tda_setup_info*)arg,sizeof(tda_setup_info)) != 0); ++ TRY(tmdlHdmiTxInstanceSetup(this->tda.instance, \ ++ &this->tda.setup)); ++ break; ++ } ++ ++ case TDA_GET_SETUP_CMD: ++ { ++ TRY(tmdlHdmiTxGetInstanceSetup(this->tda.instance, \ ++ &this->tda.setup)); ++ BUG_ON(copy_to_user((tda_setup*)arg,&this->tda.setup,sizeof(tda_setup)) != 0); ++ break; ++ } ++ ++ case TDA_WAIT_EVENT_CMD: ++ { ++ this->driver.poll_done = false; ++ up(&this->driver.sem); ++ if (wait_event_interruptible(this->driver.wait,this->driver.poll_done)) return -ERESTARTSYS; ++ down(&this->driver.sem); ++ BUG_ON(copy_to_user((tda_event*)arg,&this->tda.event,sizeof(tda_event)) != 0); ++ break; ++ } ++ ++ case TDA_ENABLE_EVENT_CMD: ++ { ++ tmdlHdmiTxEvent_t event; ++ BUG_ON(copy_from_user(&event,(tmdlHdmiTxEvent_t*)arg,sizeof(tmdlHdmiTxEvent_t)) != 0); ++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,event)); ++ break; ++ } ++ ++ case TDA_DISABLE_EVENT_CMD: ++ { ++ tmdlHdmiTxEvent_t event; ++ BUG_ON(copy_from_user(&event,(tmdlHdmiTxEvent_t*)arg,sizeof(tmdlHdmiTxEvent_t)) != 0); ++ TRY(tmdlHdmiTxDisableEvent(this->tda.instance,event)); ++ break; ++ } ++ ++ case TDA_GET_VIDEO_SPEC_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.video_fmt,(tda_video_format*)arg,sizeof(tda_video_format)) != 0); ++ TRY(tmdlHdmiTxGetVideoFormatSpecs(this->tda.instance, \ ++ this->tda.video_fmt.id, \ ++ &this->tda.video_fmt.spec)); ++ BUG_ON(copy_to_user((tda_video_format*)arg,&this->tda.video_fmt,sizeof(tda_video_format)) != 0); ++ break; ++ } ++ ++ case TDA_SET_INPUT_OUTPUT_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.setio,(tda_set_in_out*)arg,sizeof(tda_set_in_out)) != 0); ++ ++ /* TRY(tmdlHdmiTxSetInputOutput(this->tda.instance, \ */ ++ /* this->tda.setio.video_in, \ */ ++ /* this->tda.setio.video_out, \ */ ++ /* this->tda.setio.audio_in, \ */ ++ /* this->tda.setio.sink)); */ ++ break; ++ } ++ ++ case TDA_SET_AUDIO_INPUT_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.setio.audio_in,(tda_set_audio_in*)arg,sizeof(tda_set_audio_in)) != 0); ++ TRY(tmdlHdmiTxSetAudioInput(this->tda.instance, \ ++ this->tda.setio.audio_in, \ ++ this->tda.setio.sink)); ++ break; ++ } ++ ++ case TDA_SET_VIDEO_INFOFRAME_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.video_infoframe,(tda_video_infoframe*)arg,sizeof(tda_video_infoframe)) != 0); ++ TRY(tmdlHdmiTxSetVideoInfoframe(this->tda.instance, \ ++ this->tda.video_infoframe.enable, \ ++ &this->tda.video_infoframe.data)); ++ break; ++ } ++ ++ case TDA_SET_AUDIO_INFOFRAME_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.audio_infoframe,(tda_audio_infoframe*)arg,sizeof(tda_audio_infoframe)) != 0); ++ TRY(tmdlHdmiTxSetAudioInfoframe(this->tda.instance, \ ++ this->tda.audio_infoframe.enable, \ ++ &this->tda.audio_infoframe.data)); ++ break; ++ } ++ ++ case TDA_SET_ACP_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.acp,(tda_acp*)arg,sizeof(tda_acp)) != 0); ++ TRY(tmdlHdmiTxSetACPPacket(this->tda.instance, \ ++ this->tda.acp.enable, \ ++ &this->tda.acp.data)); ++ break; ++ } ++ ++ case TDA_SET_GCP_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.gcp,(tda_gcp*)arg,sizeof(tda_gcp)) != 0); ++ TRY(tmdlHdmiTxSetGeneralControlPacket(this->tda.instance, \ ++ this->tda.gcp.enable, \ ++ &this->tda.gcp.data)); ++ break; ++ } ++ ++ case TDA_SET_ISRC1_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.isrc1,(tda_isrc1*)arg,sizeof(tda_isrc1)) != 0); ++ TRY(tmdlHdmiTxSetISRC1Packet(this->tda.instance, \ ++ this->tda.isrc1.enable, \ ++ &this->tda.isrc1.data)); ++ break; ++ } ++ ++ case TDA_SET_MPS_INFOFRAME_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.mps_infoframe,(tda_mps_infoframe*)arg,sizeof(tda_mps_infoframe)) != 0); ++ TRY(tmdlHdmiTxSetMPSInfoframe(this->tda.instance, \ ++ this->tda.mps_infoframe.enable, \ ++ &this->tda.mps_infoframe.data)); ++ break; ++ } ++ ++ case TDA_SET_SPD_INFOFRAME_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.spd_infoframe,(tda_spd_infoframe*)arg,sizeof(tda_spd_infoframe)) != 0); ++ TRY(tmdlHdmiTxSetSpdInfoframe(this->tda.instance, \ ++ this->tda.spd_infoframe.enable, \ ++ &this->tda.spd_infoframe.data)); ++ break; ++ } ++ ++ case TDA_SET_VS_INFOFRAME_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.vs_infoframe,(tda_vs_infoframe*)arg,sizeof(tda_vs_infoframe)) != 0); ++ TRY(tmdlHdmiTxSetVsInfoframe(this->tda.instance, \ ++ this->tda.vs_infoframe.enable, \ ++ &this->tda.vs_infoframe.data)); ++ break; ++ } ++ ++ case TDA_SET_AUDIO_MUTE_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.audio_mute,(bool*)arg,sizeof(bool)) != 0); ++ TRY(tmdlHdmiTxSetAudioMute(this->tda.instance, \ ++ this->tda.audio_mute)); ++ break; ++ } ++ ++ case TDA_RESET_AUDIO_CTS_CMD: ++ { ++ TRY(tmdlHdmiTxResetAudioCts(this->tda.instance)); ++ break; ++ } ++ ++ case TDA_GET_EDID_STATUS_CMD: ++ { ++ TRY(tmdlHdmiTxGetEdidStatus(this->tda.instance, \ ++ &this->tda.edid.status, \ ++ &this->tda.edid.block_count)); ++ BUG_ON(copy_to_user((tda_edid*)arg,&this->tda.edid,sizeof(tda_edid)) != 0); ++ break; ++ } ++ ++ case TDA_GET_EDID_AUDIO_CAPS_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.edid_audio_caps,(tda_edid_audio_caps*)arg,sizeof(tda_edid_audio_caps)) != 0); ++ TRY(tmdlHdmiTxGetEdidAudioCaps(this->tda.instance, \ ++ this->tda.edid_audio_caps.desc, \ ++ this->tda.edid_audio_caps.max, \ ++ &this->tda.edid_audio_caps.written, \ ++ &this->tda.edid_audio_caps.flags)); ++ BUG_ON(copy_to_user((tda_edid_audio_caps*)arg,&this->tda.edid_audio_caps,sizeof(tda_edid_audio_caps)) != 0); ++ break; ++ } ++ ++ case TDA_GET_EDID_VIDEO_CAPS_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.edid_video_caps,(tda_edid_video_caps*)arg,sizeof(tda_edid_video_caps)) != 0); ++ TRY(tmdlHdmiTxGetEdidVideoCaps(this->tda.instance, \ ++ this->tda.edid_video_caps.desc, \ ++ this->tda.edid_video_caps.max, \ ++ &this->tda.edid_video_caps.written, \ ++ &this->tda.edid_video_caps.flags)); ++ BUG_ON(copy_to_user((tda_edid_video_caps*)arg,&this->tda.edid_video_caps,sizeof(tda_edid_video_caps)) != 0); ++ break; ++ } ++ ++ case TDA_GET_EDID_VIDEO_PREF_CMD: ++ { ++ TRY(tmdlHdmiTxGetEdidVideoPreferred(this->tda.instance, \ ++ &this->tda.edid_video_timings)); ++ BUG_ON(copy_to_user((tda_edid_video_timings*)arg,&this->tda.edid_video_timings,sizeof(tda_edid_video_timings)) != 0); ++ break; ++ } ++ ++ case TDA_GET_EDID_SINK_TYPE_CMD: ++ { ++ TRY(tmdlHdmiTxGetEdidSinkType(this->tda.instance, \ ++ &this->tda.setio.sink)); ++ BUG_ON(copy_to_user((tda_sink*)arg,&this->tda.setio.sink,sizeof(tda_sink)) != 0); ++ break; ++ } ++ ++ case TDA_GET_EDID_SOURCE_ADDRESS_CMD: ++ { ++ TRY(tmdlHdmiTxGetEdidSourceAddress(this->tda.instance, \ ++ &this->tda.src_address)); ++ BUG_ON(copy_to_user((unsigned short*)arg,&this->tda.src_address,sizeof(unsigned short)) != 0); ++ break; ++ } ++ ++ case TDA_SET_GAMMUT_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.gammut,(tda_gammut*)arg,sizeof(tda_gammut)) != 0); ++ TRY(tmdlHdmiTxSetGamutPacket(this->tda.instance, \ ++ this->tda.gammut.enable, \ ++ &this->tda.gammut.data)); ++ break; ++ } ++ ++ case TDA_GET_EDID_DTD_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.edid_dtd,(tda_edid_dtd*)arg,sizeof(tda_edid_dtd)) != 0); ++ TRY(tmdlHdmiTxGetEdidDetailledTimingDescriptors(this->tda.instance, \ ++ this->tda.edid_dtd.desc, \ ++ this->tda.edid_dtd.max, \ ++ &this->tda.edid_dtd.written)); ++ BUG_ON(copy_to_user((tda_edid_dtd*)arg,&this->tda.edid_dtd,sizeof(tda_edid_dtd)) != 0); ++ break; ++ } ++ ++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984) ++ case TDA_GET_EDID_MD_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.edid_md,(tda_edid_md*)arg,sizeof(tda_edid_md)) != 0); ++ TRY(tmdlHdmiTxGetEdidMonitorDescriptors(this->tda.instance, \ ++ this->tda.edid_md.desc1, \ ++ this->tda.edid_md.desc2, \ ++ this->tda.edid_md.other, \ ++ this->tda.edid_md.max, \ ++ &this->tda.edid_md.written)); ++ BUG_ON(copy_to_user((tda_edid_md*)arg,&this->tda.edid_md,sizeof(tda_edid_md)) != 0); ++ break; ++ } ++ ++ case TDA_GET_EDID_TV_ASPECT_RATIO_CMD: ++ { ++ TRY(tmdlHdmiTxGetEdidTVPictureRatio(this->tda.instance, \ ++ &this->tda.edid_tv_aspect_ratio)); ++ BUG_ON(copy_to_user((tda_edid_tv_aspect_ratio*)arg,&this->tda.edid_tv_aspect_ratio,sizeof(tda_edid_tv_aspect_ratio)) != 0); ++ break; ++ } ++ ++ case TDA_GET_EDID_LATENCY_CMD: ++ { ++ TRY(tmdlHdmiTxGetEdidLatencyInfo(this->tda.instance, \ ++ &this->tda.edid_latency)); ++ BUG_ON(copy_to_user((tda_edid_latency*)arg,&this->tda.edid_latency,sizeof(tda_edid_latency)) != 0); ++ break; ++ } ++ ++ case TDA_SET_HDCP_CMD: ++ { ++ BUG_ON(copy_from_user(&this->tda.hdcp_enable,(bool*)arg,sizeof(bool)) != 0); ++ break; ++ } ++ ++ case TDA_GET_HPD_STATUS_CMD: ++ { ++ tmdlHdmiTxGetHPDStatus(this->tda.instance,&this->tda.hot_plug_detect); ++ BUG_ON(copy_to_user((tmdlHdmiTxHotPlug_t*)arg,&this->tda.hot_plug_detect,sizeof(tmdlHdmiTxHotPlug_t)) != 0); ++ break; ++ } ++ case TDA_GET_HDCP_STATUS_CMD: ++ { ++ BUG_ON(copy_to_user((tda_edid_latency*)arg,&this->tda.hdcp_status,sizeof(tda_hdcp_status)) != 0); ++ break; ++ } ++#endif ++ ++ default: ++ { ++ /* unrecognized ioctl */ ++ printk(KERN_INFO "hdmitx:%s:unknown ioctl number: %x\n",__func__,cmd); ++ up(&this->driver.sem); ++ return -ENOIOCTLCMD; ++ } ++ } ++ ++ TRY_DONE: ++ up(&this->driver.sem); ++ return err; ++} ++ ++/* ++ * ioctl driver :: releasing ++ */ ++static int this_cdev_release(struct inode *pInode, struct file *pFile) ++{ ++ tda_instance* this = pFile->private_data; ++ int minor = iminor(pInode); ++ ++ LOG(KERN_INFO,"called\n"); ++ ++ if(minor >= MAX_MINOR) { ++ LOG(KERN_ERR,"minor too big!\n"); ++ return -EINVAL; ++ } ++ ++ BUG_ON(this->driver.minor!=iminor(pInode)); ++ down(&this->driver.sem); ++ ++ this->driver.user_counter--; ++ if(this->driver.user_counter == 0) { ++ pFile->private_data = NULL; ++ } ++ else { ++ LOG(KERN_INFO,"Still %d users pending\n",this->driver.user_counter); ++ } ++ ++ up(&this->driver.sem); ++ return 0; ++} ++ ++/* ++ * I2C client :: creation ++ */ ++static int this_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) ++{ ++ tda_instance *this=&our_instance; ++ int err=0; ++ ++ printk(KERN_ERR "i2c probe called.....\n"); ++ ++ LOG(KERN_INFO,"called\n"); ++ ++ /* ++ I2C setup ++ */ ++ if (this->driver.i2c_client) { ++ dev_err(&this->driver.i2c_client->dev, "<%s> HDMI Device already created \n", ++ __func__); ++ return -ENODEV; ++ } ++ ++ this->driver.i2c_client = client; ++ i2c_set_clientdata(client, this); ++ ++ /* I2C ok, then let's startup TDA */ ++ err = hdmi_tx_init(this); ++ if (err) goto i2c_out; ++ this->tda.hdcp_enable = 0; ++ /* Standby the HDMI TX instance : this is mandatory for TDA boot up sequence, do not change it */ ++ this->tda.power = tmPowerStandby; /* power start sequence phase 1, see phase 2 */ ++ tmdlHdmiTxSetPowerState(this->tda.instance,this->tda.power); ++ /* update HPD */ ++ tmdlHdmiTxGetHPDStatus(this->tda.instance,&this->tda.hot_plug_detect); ++ ++#ifdef ANDROID_DSS ++ /* probe DSS */ ++ err = omap_dss_register_driver(&hdmi_driver); ++#endif ++ if (err) goto i2c_tx_out; ++ ++ /* prepare event */ ++ this->driver.poll_done = true; /* currently idle */ ++ init_waitqueue_head(&this->driver.wait); ++ ++#ifdef IRQ ++ if (client->irq > 0) { ++ this->driver.gpio = irq_to_gpio(client->irq); ++ } else { ++ this->driver.gpio = TDA_IRQ_CALIB; ++ } ++ ++ /* FRO calibration */ ++ err=gpio_request(this->driver.gpio, "tda998x calibration"); ++ if (err < 0) { ++ printk(KERN_ERR "hdmitx:%s:cannot use GPIO %d, err:%d\n",__func__, this->driver.gpio,err); ++ goto i2c_out; ++ } ++ /* turn GPIO into IRQ */ ++ gpio_direction_input(this->driver.gpio); ++ msleep(1); ++ ++ err=request_irq(gpio_to_irq(this->driver.gpio), tda_irq, ++ IRQF_TRIGGER_FALLING|IRQF_DISABLED, "TDA IRQ", this); ++ if (err <0) { ++ printk(KERN_ERR "hdmitx:%s:Cannot request irq, err:%d\n",__func__,err); ++ gpio_free(this->driver.gpio); ++ goto i2c_out; ++ } ++#else ++ init_timer(&this->driver.no_irq_timer); ++ this->driver.no_irq_timer.function=polling_timeout; ++ this->driver.no_irq_timer.data=0; ++ this->driver.no_irq_timer.expires = jiffies + HZ; /* start polling in one sec */ ++ add_timer(&this->driver.no_irq_timer); ++#endif ++ ++ /* setup hdcp check timer */ ++ init_timer(&this->driver.hdcp_check); ++ this->driver.hdcp_check.function=hdcp_check_timeout; ++ this->driver.hdcp_check.data=0; ++ ++ tmdlHdmiTxGetSWVersion(&this->tda.version); ++ printk(KERN_INFO "HDMI TX SW Version:%lu.%lu compatibility:%lu\n", \ ++ this->tda.version.majorVersionNr,\ ++ this->tda.version.minorVersionNr,\ ++ this->tda.version.compatibilityNr); ++ return 0; ++ ++ i2c_tx_out: ++ LOG(KERN_INFO,"tmdlHdmiTx closed\n"); ++ /* close DevLib */ ++ err=tmdlHdmiTxClose(this->tda.instance); ++ ++ i2c_out: ++ LOG(KERN_INFO,"this->driver.i2c_client removed\n"); ++ this->driver.i2c_client = NULL; ++ ++ return err; ++} ++ ++/* ++ * I2C client :: destroy ++ */ ++static int this_i2c_remove(struct i2c_client *client) ++{ ++ tda_instance *this=&our_instance; ++ int err=0; ++ ++ LOG(KERN_INFO,"called\n"); ++ ++#ifdef ANDROID_DSS ++ /* unplug DSS */ ++ omap_dss_unregister_driver(&hdmi_driver); ++#endif ++ ++ /* close DevLib */ ++ err=tmdlHdmiTxClose(this->tda.instance); ++ ++ if (!client->adapter) { ++ dev_err(&this->driver.i2c_client->dev, "<%s> No HDMI Device \n", ++ __func__); ++ return -ENODEV; ++ } ++ this->driver.i2c_client = NULL; ++ ++ return err; ++} ++ ++/* ++ * I2C client driver (backend) ++ * ----------------- ++ */ ++static const struct i2c_device_id this_i2c_id[] = { ++ { TX_NAME, 0 }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(i2c, this_i2c_id); ++ ++static struct i2c_driver this_i2c_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = TX_NAME, ++ }, ++ .probe = this_i2c_probe, ++ .remove = this_i2c_remove, ++ .id_table = this_i2c_id, ++}; ++ ++/* ++ * ioctl driver (userland frontend) ++ * ------------ ++ */ ++static struct file_operations this_cdev_fops = { ++ owner: THIS_MODULE, ++ open: this_cdev_open, ++ release: this_cdev_release, ++// ioctl: this_cdev_ioctl, ++}; ++ ++/* ++ * sysfs_attrs ++ * ----------- ++ */ ++ ++static ssize_t reso_show(struct device *dev,struct device_attribute *attr, char *buf) ++{ ++ tda_instance *this=&our_instance; ++ ++ return sprintf(buf,"format video %d ( %s )\n", \ ++ this->tda.setio.video_in.format, \ ++ tda_spy_vfmt(this->tda.setio.video_in.format)); ++} ++ ++static ssize_t reso_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ tda_instance *this=&our_instance; ++ int resolution=0; ++ ++ sscanf(buf,"%d",&resolution); ++ if (resolution != WITH_FP(this->tda.setio.video_in.format)) { ++ LOG(KERN_INFO,"sys_attr new video format\n from %d:( %s )\n to %d:( %s )\n", \ ++ this->tda.setio.video_in.format, \ ++ tda_spy_vfmt(this->tda.setio.video_in.format), \ ++ resolution, \ ++ tda_spy_vfmt(resolution)); ++ this->tda.setio.video_out.format = NO_FP(resolution); ++ this->tda.setio.video_in.format = this->tda.setio.video_out.format; ++ this->tda.setio.video_in.structure3D = (IS_FP(resolution)?TMDL_HDMITX_3D_FRAME_PACKING:TMDL_HDMITX_3D_NONE); ++ ++ if (resolution == 0) { ++ this->tda.power = tmPowerStandby; ++ tmdlHdmiTxSetPowerState(this->tda.instance,this->tda.power); ++ } else { ++ this->tda.power = tmPowerOn; ++ tmdlHdmiTxSetPowerState(this->tda.instance,this->tda.power); ++ show_video(this); ++ } ++ } ++ return 0; ++} ++ ++ ++static ssize_t audio_show(struct device *dev,struct device_attribute *attr, char *buf) ++{ ++ tda_instance *this=&our_instance; ++ printk("Audio Show\n"); ++ ++ tda_spy_audio(&this->tda.setio.audio_in); ++ return sprintf(buf,"audio format %d - %d - %d - %d - %d - %d\n", \ ++ this->tda.setio.audio_in.format, \ ++ this->tda.setio.audio_in.rate, \ ++ this->tda.setio.audio_in.i2sFormat, \ ++ this->tda.setio.audio_in.i2sQualifier, \ ++ this->tda.setio.audio_in.dstRate, \ ++ this->tda.setio.audio_in.channelAllocation); ++} ++ ++static ssize_t audio_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ tda_instance *this=&our_instance; ++ char desc_format[]="%d - %d - %d - %d - %d - %d\n"; ++ tda_audio_in audio; ++ ++ /* ++ Example: ++ ++ adb shell "echo '1 - 1 - 0 - 32 - 0 -' >/sys/hdmitx/audio" ++ ++ with : ++ ++ TMDL_HDMITX_AFMT_I2S, ++ TMDL_HDMITX_AFS_44K, ++ TMDL_HDMITX_I2SFOR_PHILIPS_L, ++ TMDL_HDMITX_I2SQ_32BITS, ++ TMDL_HDMITX_DSTRATE_SINGLE, ++ channel:0 ++ */ ++ ++ memcpy(&audio,&this->tda.setio.audio_in,sizeof(audio)); ++ sscanf(buf,desc_format, \ ++ &audio.format, \ ++ &audio.rate, \ ++ &audio.i2sFormat, \ ++ &audio.i2sQualifier, \ ++ &audio.dstRate, \ ++ &audio.channelAllocation); ++ ++ if (memcmp(&this->tda.setio.audio_in,&audio,sizeof(audio))) { ++ tda_spy_audio(&this->tda.setio.audio_in); ++ memcpy(&this->tda.setio.audio_in,&audio,sizeof(audio)); ++ tmdlHdmiTxSetAudioInput(this->tda.instance, \ ++ this->tda.setio.audio_in, \ ++ this->tda.setio.sink); ++ } ++ return 0; ++} ++ ++#ifdef I2C_DBG ++static ssize_t i2cR_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ /* ++ adb shell "echo '2 1' >/sys/hdmitx/i2cR" ++ ... read page 0x02 address 0x01 ++ */ ++ tda_instance *this=&our_instance; ++ tmHdmiTxobject_t *p; ++ tmErrorCode_t err; ++ unsigned int address; ++ unsigned int value,page; ++ char desc_format[]="%x %x\n"; ++ ++ err = checkUnitSetDis(this->tda.instance, &p); ++ sscanf(buf,desc_format,&page,&address); ++ err = getHwRegister(p, SPA(E_SNONE,page,address), (unsigned char *)&value); ++ printk("i2c read %x @ page:%x address:%x\n",value,page,address); ++ return 0; ++} ++ ++static ssize_t i2cW_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ /* ++ adb shell "echo '2 1 0x03 2' >/sys/hdmitx/i2cW" ++ ... write 0x02 page 0x02 address 0x01 using mask 0x03 ++ */ ++ ++ tda_instance *this=&our_instance; ++ tmHdmiTxobject_t *p; ++ tmErrorCode_t err; ++ unsigned int page,address,mask,value; ++ char desc_format[]="%x %x %x %x\n"; ++ ++ err = checkUnitSetDis(this->tda.instance, &p); ++ sscanf(buf,desc_format,&page,&address,&mask,&value); ++ err = setHwRegisterField(p,SPA(E_SNONE,page,address),mask,value); ++ printk("i2c write %x @ page:%x address:%x mask:%x\n",value,page,address,mask); ++ return 0; ++} ++#endif ++ ++static DEVICE_ATTR(resolution, S_IRUGO|S_IWUSR, reso_show, reso_store); ++static DEVICE_ATTR(audio, S_IRUGO|S_IWUSR, audio_show, audio_store); ++#ifdef I2C_DBG ++static DEVICE_ATTR(i2cW, S_IRUGO|S_IWUSR, NULL, i2cW_store); ++static DEVICE_ATTR(i2cR, S_IRUGO|S_IWUSR, NULL, i2cR_store); ++#endif ++static struct device_attribute *display_sysfs_attrs[] = { ++ &dev_attr_resolution, ++ &dev_attr_audio, ++#ifdef I2C_DBG ++ &dev_attr_i2cW, ++ &dev_attr_i2cR, ++#endif ++ NULL ++}; ++ ++static int comm_init(void) ++{ ++ tda_instance *this=&our_instance; ++ int retval=0; ++ int i=0; ++ struct device_attribute *attr; ++ ++ while ((attr = display_sysfs_attrs[i++]) != NULL) { ++ retval=device_create_file (this->driver.dev,attr); ++ if (retval != 0) { ++ goto out_create_file; ++ } ++ } ++ /* create display sysfs links */ ++ retval = sysfs_create_link(NULL,&(this->driver.dev->kobj),HDMITX_NAME); ++ if (retval != 0) ++ goto out_create_link; ++ return retval; ++ ++ out_create_link: ++ sysfs_remove_link(NULL, HDMITX_NAME); ++ out_create_file: ++ while ((attr = display_sysfs_attrs[i++]) != NULL) { ++ device_remove_file (this->driver.dev,attr); ++ } ++ return retval; ++} ++ ++static void comm_exit(void) ++{ ++ tda_instance *this=&our_instance; ++ int i=0; ++ struct device_attribute *attr; ++ while ((attr = display_sysfs_attrs[i++]) != NULL) { ++ device_remove_file (this->driver.dev,attr); ++ } ++ sysfs_remove_link(NULL, HDMITX_NAME); ++} ++ ++/* ++ * Module :: start up ++ */ ++static int __init tx_init(void) ++{ ++ tda_instance *this=&our_instance; ++ dev_t dev=0; ++ int err=0; ++ ++ /* ++ general device context ++ */ ++ memset(this,0,sizeof(tda_instance)); ++ this->param.verbose = param_verbose; ++ this->param.major = param_major; ++ this->param.minor = param_minor; ++ ++ /* Hello word */ ++ printk(KERN_INFO "%s(%s) %d.%d.%d compiled: %s %s %s\n", HDMITX_NAME, TDA_NAME, ++ TDA_VERSION_MAJOR, ++ TDA_VERSION_MINOR, ++ TDA_VERSION_PATCHLEVEL, ++ __DATE__, __TIME__, TDA_VERSION_EXTRA); ++ if (this->param.verbose) LOG(KERN_INFO,".verbose mode\n"); ++ ++ /* ++ plug I2C (backend : Hw interfacing) ++ */ ++ err = i2c_add_driver(&this_i2c_driver); ++ if (err < 0) { ++ printk(KERN_ERR "Driver registration failed\n"); ++ return -ENODEV; ++ } ++ ++ if (this->driver.i2c_client == NULL) { ++ printk(KERN_ERR "this->driver.i2c_client not allocated\n"); ++ /* unregister i2c */ ++ err = -ENODEV; ++ goto init_out; ++ } ++ ++ /* ++ cdev init (userland frontend) ++ */ ++ ++ /* arbitray range of device numbers */ ++ if (this->param.major) { ++ /* user force major number @ insmod */ ++ dev = MKDEV(this->param.major, this->param.minor); ++ err = register_chrdev_region(dev,MAX_MINOR,HDMITX_NAME); ++ if (err) { ++ printk(KERN_ERR "unable to register %s, dev=%d %s\n",HDMITX_NAME,dev,ERR_TO_STR(err)); ++ goto init_out; ++ } ++ } else { ++ /* fully dynamic major number */ ++ err = alloc_chrdev_region(&dev, this->param.minor, MAX_MINOR,HDMITX_NAME); ++ if (err) { ++ printk(KERN_ERR "unable to alloc chrdev region for %s, dev=%d %s\n",HDMITX_NAME,dev,ERR_TO_STR(err)); ++ goto init_out; ++ } ++ this->param.major = MAJOR(dev); ++ this->param.minor = MINOR(dev); ++ /* create_dev("/dev/hdmitx",dev); */ ++ LOG(KERN_INFO,"/dev/hdmitx created major:%d minor:%d\n",this->param.major, this->param.minor); ++ } ++ ++ cdev_init(this_cdev, &this_cdev_fops); ++ this_cdev->owner = THIS_MODULE; ++ ++ this->driver.class = class_create(THIS_MODULE, HDMITX_NAME); ++ if (IS_ERR(this->driver.class)) { ++ printk(KERN_INFO "Error creating mmap device class.\n"); ++ err =-EIO; ++ goto init_out; ++ } ++ this->driver.dev=device_create(this->driver.class, NULL /* parent */, dev, NULL, HDMITX_NAME); ++ ++ this->driver.devno = dev; ++ err = cdev_add(this_cdev, this->driver.devno, MAX_MINOR); ++ if (err){ ++ printk(KERN_INFO "unable to add device for %s, ipp_driver.devno=%d %s\n",HDMITX_NAME,this->driver.devno,ERR_TO_STR(err)); ++ device_destroy(this->driver.class,this->driver.devno); ++ class_destroy(this->driver.class); ++ unregister_chrdev_region(this->driver.devno, MAX_MINOR); ++ goto init_out; ++ } ++ ++ /* ++ general device context ++ */ ++ sema_init(&this->driver.sem, 1); ++ ++ /* ++ /!\ WARNING /! \ ++ the startup power sequence SHALL BE standby AND THEN suspend (core driver legacy...) ++ this is the only way to get the TDA idle but with active HDP and RxSens interrupt listening ++ */ ++ hdmi_disable(1); /* power start sequence phase 2 */ ++ ++ /* ++ /!\ WARNING /! \ ++ if HDMI is plugged, the core driver will send HDP nor RXSENS event when beeing powered on ! ++ So the Android HDMI service shall start by asking the HDP status using the IOCTL GET_HPD_STATUS ++ */ ++ tmdlHdmiTxGetHPDStatus(this->tda.instance, ++ &this->tda.hot_plug_detect); /* power start sequence phase 3 */ ++ ++ /* sysfs_attrs */ ++ comm_init(); ++ hdmi_enable(); ++ return 0; ++ ++ init_out: ++ i2c_del_driver(&this_i2c_driver); ++ return err; ++} ++ ++/* ++ * Module :: shut down ++ */ ++static void __exit tx_exit(void) ++{ ++ tda_instance *this=&our_instance; ++ ++ LOG(KERN_INFO,"called\n"); ++ ++#ifdef IRQ ++ free_irq(gpio_to_irq(this->driver.gpio), this); ++ gpio_free(this->driver.gpio); ++#else ++ del_timer(&this->driver.no_irq_timer); ++#endif ++ ++ del_timer(&this->driver.hdcp_check); ++ ++ /* sysfs_attrs */ ++ comm_exit(); ++ ++ /* unregister cdevice */ ++ cdev_del(this_cdev); ++ unregister_chrdev_region(this->driver.devno, MAX_MINOR); ++ ++ /* unregister device */ ++ device_destroy(this->driver.class,this->driver.devno); ++ class_destroy(this->driver.class); ++ ++ /* unregister i2c */ ++ i2c_del_driver(&this_i2c_driver); ++} ++ ++ ++/* ++ * Module ++ * ------ ++ */ ++late_initcall(tx_init); ++// module_init(tx_init); ++module_exit(tx_exit); ++ ++/* ++ * Disclamer ++ * --------- ++ */ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Andre Lepine "); ++MODULE_DESCRIPTION(HDMITX_NAME " driver"); +diff --git a/drivers/video/nxp/tda998x.h b/drivers/video/nxp/tda998x.h +new file mode 100755 +index 0000000..3759474 +--- /dev/null ++++ b/drivers/video/nxp/tda998x.h +@@ -0,0 +1,143 @@ ++/*****************************************************************************/ ++/* Copyright (c) 2009 NXP Semiconductors BV */ ++/* */ ++/* This program is free software; you can redistribute it and/or modify */ ++/* it under the terms of the GNU General Public License as published by */ ++/* the Free Software Foundation, using version 2 of the License. */ ++/* */ ++/* This program is distributed in the hope that it will be useful, */ ++/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ ++/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ ++/* GNU General Public License for more details. */ ++/* */ ++/* You should have received a copy of the GNU General Public License */ ++/* along with this program; if not, write to the Free Software */ ++/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */ ++/* USA. */ ++/* */ ++/*****************************************************************************/ ++ ++#ifndef __tx_h__ ++#define __tx_h__ ++ ++#include "tda998x_ioctl.h" ++ ++#define HDMITX_NAME "hdmitx" ++ ++#define POLLING_WQ_NAME "TDA_POLLING" ++#define HDCP_CHECK_EVERY_MS 35 ++#define CHECK_EVERY_XX_MS 200 ++#define OMAP_LCD_GPIO 8 ++ ++#define TDA_MAJOR 234 /* old-style interval of device numbers */ ++#define MAX_MINOR 1 /* 1 minor but 2 access : 1 more for pooling */ ++ ++ ++/* common I2C define with kernel */ ++/* should be the same as arch/arm/mach-omap2/board-zoom2.c */ ++#define TX_NAME "tda998X" ++#define TDA998X_I2C_SLAVEADDRESS 0x70 ++ ++#define TDA_IRQ_CALIB 107 ++ ++#define EDID_BLOCK_COUNT 4 ++#define EDID_BLOCK_SIZE 128 ++#define MAX_EDID_TRIAL 5 ++#define NO_PHY_ADDR 0xFFFF ++ ++#define HDCP_IS_NOT_INSTALLED TMDL_HDMITX_HDCP_CHECK_NUM /* ugly is bad ! */ ++ ++#define LOG(type,fmt,args...) {if (this->param.verbose) {printk(type HDMITX_NAME":%s:" fmt, __func__, ## args);}} ++/* not found the kernel "strerror" one! If someone knows, please replace it */ ++#define ERR_TO_STR(e)((e == -ENODATA)?"ENODATA, no data available":\ ++ (e == -ENOMEM)? "ENOMEM, no memory available":\ ++ (e == -EINVAL)? "EINVAL, invalid argument":\ ++ (e == -EIO)? "EIO, input/output error":\ ++ (e == -ETIMEDOUT)? "ETIMEOUT, timeout has expired":\ ++ (e == -EBUSY)? "EBUSY, device or resource busy":\ ++ (e == -ENOENT)? "ENOENT, no such file or directory":\ ++ (e == -EACCES)? "EACCES, permission denied":\ ++ (e == 0)? "":\ ++ "!UNKNOWN!") ++ ++#define TRY(fct) { \ ++ err=(fct); \ ++ if (err) { \ ++ printk(KERN_ERR "%s returned in %s line %d\n",hdmi_tx_err_string(err),__func__,__LINE__); \ ++ goto TRY_DONE; \ ++ } \ ++ } ++ ++typedef void (*cec_callback_t)(struct work_struct *dummy); ++ ++typedef struct { ++ /* module params */ ++ struct { ++ int verbose; ++ int major; ++ int minor; ++ } param; ++ /* driver */ ++ struct { ++ struct class *class; ++ struct device *dev; ++ int devno; ++ struct i2c_client *i2c_client; ++ struct semaphore sem; ++ int user_counter; ++ int minor; ++ wait_queue_head_t wait; ++ bool poll_done; ++#ifndef IRQ ++ struct timer_list no_irq_timer; ++#endif ++ struct timer_list hdcp_check; ++ cec_callback_t cec_callback; ++ bool omap_dss_hdmi_panel; ++ int gpio; ++ } driver; ++ /* HDMI */ ++ struct { ++ int instance; ++ tda_version version; ++ tda_setup setup; ++ tda_power power; ++ tmdlHdmiTxHotPlug_t hot_plug_detect; ++ bool rx_device_active; ++ tda_video_format video_fmt; ++ tda_set_in_out setio; ++ bool audio_mute; ++ tda_video_infoframe video_infoframe; ++ tda_audio_infoframe audio_infoframe; ++ tda_acp acp; ++ tda_gcp gcp; ++ tda_isrc1 isrc1; ++ tda_isrc2 isrc2; ++ tda_gammut gammut; ++ tda_mps_infoframe mps_infoframe; ++ tda_spd_infoframe spd_infoframe; ++ tda_vs_infoframe vs_infoframe; ++ tda_edid edid; ++ tda_edid_dtd edid_dtd; ++ tda_edid_md edid_md; ++ tda_edid_audio_caps edid_audio_caps; ++ tda_edid_video_caps edid_video_caps; ++ tda_edid_video_timings edid_video_timings; ++ tda_edid_tv_aspect_ratio edid_tv_aspect_ratio; ++#ifdef TMFL_TDA19989 ++ tda_edid_latency edid_latency; ++#endif ++ unsigned short src_address; ++ unsigned char raw_edid[EDID_BLOCK_COUNT*EDID_BLOCK_SIZE]; ++ tda_capabilities capabilities; ++ tda_event event; ++ tda_hdcp_status hdcp_status; ++ bool hdcp_enable; ++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984) ++ tda_hdcp_fail hdcp_fail; ++#endif ++ unsigned char hdcp_raw_status; ++ } tda; ++} tda_instance; ++ ++#endif /* __tx_h__ */ +diff --git a/drivers/video/nxp/tda998x_cec.c b/drivers/video/nxp/tda998x_cec.c +new file mode 100755 +index 0000000..90f3536 +--- /dev/null ++++ b/drivers/video/nxp/tda998x_cec.c +@@ -0,0 +1,2157 @@ ++/*****************************************************************************/ ++/* Copyright (c) 2009 NXP Semiconductors BV */ ++/* */ ++/* This program is free software; you can redistribute it and/or modify */ ++/* it under the terms of the GNU General Public License as published by */ ++/* the Free Software Foundation, using version 2 of the License. */ ++/* */ ++/* This program is distributed in the hope that it will be useful, */ ++/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ ++/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ ++/* GNU General Public License for more details. */ ++/* */ ++/* You should have received a copy of the GNU General Public License */ ++/* along with this program; if not, write to the Free Software */ ++/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */ ++/* USA. */ ++/* */ ++/*****************************************************************************/ ++ ++#define _cec_c_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* HDMI DevLib */ ++#include "tmNxCompId.h" ++#include "tmdlHdmiCEC.h" ++#include "tmdlHdmiCEC_local.h" ++ ++/* local */ ++#include "tda998x_version.h" ++#include "tda998x_cec.h" ++#include "tda998x_ioctl.h" ++ ++#include ++#include ++#include ++#include ++ ++ ++/* ++ * ++ * DEFINITION ++ * ---------- ++ * LEVEL 0 ++ * ++ */ ++ ++/* ++ * Global ++ */ ++ ++MODULE_DEVICE_TABLE(i2c, this_i2c_id); ++static const struct i2c_device_id this_i2c_id[] = { ++ { CEC_NAME, 0 }, ++ { }, ++}; ++cec_instance our_instance; ++static struct cdev our_cdev, *this_cdev=&our_cdev; ++ ++#ifdef TWL4030_HACK ++/* AL : hack to bypass keypad */ ++struct input_dev *gkp_input; ++extern struct input_dev *get_twm4030_input(void); ++#endif ++ ++/* ++ * Dependancies to HdmiTx module ++ */ ++ ++extern void register_cec_interrupt(cec_callback_t fct); ++extern void unregister_cec_interrupt(void); ++extern short edid_phy_addr(void); ++extern int hdmi_enable(void); ++extern int hdmi_disable(int event_tracking); ++extern cec_power get_hdmi_status(void); ++extern cec_power get_hpd_status(void); ++extern int edid_received(void); ++ ++/* ++ * Module params ++ */ ++ ++static int param_verbose=0,param_major=0,param_minor=0,param_device=4,param_addr=0xFFFF; ++module_param_named(verbose,param_verbose,int,S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(verbose, "Make the driver verbose"); ++module_param_named(major, param_major, int, S_IRUGO); ++MODULE_PARM_DESC(major, "The major number of the device mapper"); ++module_param_named(device, param_device, int, S_IRUGO); ++MODULE_PARM_DESC(device, "Device type can be 0:tv, 1:rec 3:tuner 4:mediaplayer, 5:audio"); ++module_param_named(addr, param_addr, int, S_IRUGO); ++MODULE_PARM_DESC(addr, "Physical address (until EDID received)"); ++ ++/* ++ * ++ * TOOLBOX ++ * ------- ++ * LEVEL 1 ++ * ++ * - i2c read/write ++ * - chip Id check ++ * - i2c client info ++ * ++ */ ++ ++ ++/* ++ * Get main and unique I2C Client driver handle ++ */ ++struct i2c_client *GetThisI2cClient(void) ++{ ++ cec_instance *this=&our_instance; ++ return this->driver.i2c_client; ++} ++ ++/* ++ * error handling ++ */ ++static char *hdmi_cec_err_string(int err) ++{ ++ switch (err) ++ { ++ case TMDL_ERR_DLHDMICEC_COMPATIBILITY: {return "SW Interface compatibility";break;} ++ case TMDL_ERR_DLHDMICEC_MAJOR_VERSION: {return "SW Major Version error";break;} ++ case TMDL_ERR_DLHDMICEC_COMP_VERSION: {return "SW component version error";break;} ++ case TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: {return "Invalid device unit number";break;} ++ case TMDL_ERR_DLHDMICEC_BAD_INSTANCE: {return "Bad input instance value ";break;} ++ case TMDL_ERR_DLHDMICEC_BAD_HANDLE: {return "Bad input handle";break;} ++ case TMDL_ERR_DLHDMICEC_BAD_PARAMETER: {return "Invalid input parameter";break;} ++ case TMDL_ERR_DLHDMICEC_NO_RESOURCES: {return "Resource is not available ";break;} ++ case TMDL_ERR_DLHDMICEC_RESOURCE_OWNED: {return "Resource is already in use";break;} ++ case TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: {return "Caller does not own resource";break;} ++ case TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: {return "Inconsistent input params";break;} ++ case TMDL_ERR_DLHDMICEC_NOT_INITIALIZED: {return "Component is not initializ";break;} ++ case TMDL_ERR_DLHDMICEC_NOT_SUPPORTED: {return "Function is not supported";break;} ++ case TMDL_ERR_DLHDMICEC_INIT_FAILED: {return "Initialization failed";break;} ++ case TMDL_ERR_DLHDMICEC_BUSY: {return "Component is busy";break;} ++ case TMDL_ERR_DLHDMICEC_I2C_READ: {return "Read error";break;} ++ case TMDL_ERR_DLHDMICEC_I2C_WRITE: {return "Write error";break;} ++ case TMDL_ERR_DLHDMICEC_FULL: {return "Queue is full";break;} ++ case TMDL_ERR_DLHDMICEC_NOT_STARTED: {return "Function is not started";break;} ++ case TMDL_ERR_DLHDMICEC_ALREADY_STARTED: {return "Function is already starte";break;} ++ case TMDL_ERR_DLHDMICEC_ASSERTION: {return "Assertion failure";break;} ++ case TMDL_ERR_DLHDMICEC_INVALID_STATE: {return "Invalid state for function";break;} ++ case TMDL_ERR_DLHDMICEC_OPERATION_NOT_PERMITTED: {return "Corresponds to posix EPERM";break;} ++ default : {return "Unexpected error";break;} ++ } ++} ++ ++char *cec_opcode(int op) ++{ ++ switch (op) ++ { ++ case CEC_OPCODE_FEATURE_ABORT: {return "CEC_OPCODE_FEATURE_ABORT";break;} ++ case CEC_OPCODE_IMAGE_VIEW_ON: {return "CEC_OPCODE_IMAGE_VIEW_ON";break;} ++ case CEC_OPCODE_TUNER_STEP_INCREMENT: {return "CEC_OPCODE_TUNER_STEP_INCREMENT";break;} ++ case CEC_OPCODE_TUNER_STEP_DECREMENT: {return "CEC_OPCODE_TUNER_STEP_DECREMENT";break;} ++ case CEC_OPCODE_TUNER_DEVICE_STATUS: {return "CEC_OPCODE_TUNER_DEVICE_STATUS";break;} ++ case CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS: {return "CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS";break;} ++ case CEC_OPCODE_RECORD_ON: {return "CEC_OPCODE_RECORD_ON";break;} ++ case CEC_OPCODE_RECORD_STATUS: {return "CEC_OPCODE_RECORD_STATUS";break;} ++ case CEC_OPCODE_RECORD_OFF: {return "CEC_OPCODE_RECORD_OFF";break;} ++ case CEC_OPCODE_TEXT_VIEW_ON: {return "CEC_OPCODE_TEXT_VIEW_ON";break;} ++ case CEC_OPCODE_RECORD_TV_SCREEN: {return "CEC_OPCODE_RECORD_TV_SCREEN";break;} ++ case CEC_OPCODE_GIVE_DECK_STATUS: {return "CEC_OPCODE_GIVE_DECK_STATUS";break;} ++ case CEC_OPCODE_DECK_STATUS: {return "CEC_OPCODE_DECK_STATUS";break;} ++ case CEC_OPCODE_SET_MENU_LANGUAGE: {return "CEC_OPCODE_SET_MENU_LANGUAGE";break;} ++ case CEC_OPCODE_CLEAR_ANALOGUE_TIMER: {return "CEC_OPCODE_CLEAR_ANALOGUE_TIMER";break;} ++ case CEC_OPCODE_SET_ANALOGUE_TIMER: {return "CEC_OPCODE_SET_ANALOGUE_TIMER";break;} ++ case CEC_OPCODE_TIMER_STATUS: {return "CEC_OPCODE_TIMER_STATUS";break;} ++ case CEC_OPCODE_STANDBY: {return "CEC_OPCODE_STANDBY";break;} ++ case CEC_OPCODE_PLAY: {return "CEC_OPCODE_PLAY";break;} ++/* case CEC_OPCODE_DECK_CONTROL: {return "CEC_OPCODE_DECK_CONTROL";break;} */ ++ case CEC_OPCODE_TIMER_CLEARED_STATUS: {return "CEC_OPCODE_TIMER_CLEARED_STATUS";break;} ++ case CEC_OPCODE_USER_CONTROL_PRESSED: {return "CEC_OPCODE_USER_CONTROL_PRESSED";break;} ++ case CEC_OPCODE_USER_CONTROL_RELEASED: {return "CEC_OPCODE_USER_CONTROL_RELEASED";break;} ++ case CEC_OPCODE_GIVE_OSD_NAME: {return "CEC_OPCODE_GIVE_OSD_NAME";break;} ++ case CEC_OPCODE_SET_OSD_NAME: {return "CEC_OPCODE_SET_OSD_NAME";break;} ++ case CEC_OPCODE_SET_OSD_STRING: {return "CEC_OPCODE_SET_OSD_STRING";break;} ++ case CEC_OPCODE_SET_TIMER_PROGRAM_TITLE: {return "CEC_OPCODE_SET_TIMER_PROGRAM_TITLE";break;} ++ case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST: {return "CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST";break;} ++ case CEC_OPCODE_GIVE_AUDIO_STATUS: {return "CEC_OPCODE_GIVE_AUDIO_STATUS";break;} ++ case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE: {return "CEC_OPCODE_SET_SYSTEM_AUDIO_MODE";break;} ++ case CEC_OPCODE_REPORT_AUDIO_STATUS: {return "CEC_OPCODE_REPORT_AUDIO_STATUS";break;} ++ case CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS: {return "CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS";break;} ++ case CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS: {return "CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS";break;} ++ case CEC_OPCODE_ROUTING_CHANGE: {return "CEC_OPCODE_ROUTING_CHANGE";break;} ++ case CEC_OPCODE_ROUTING_INFORMATION: {return "CEC_OPCODE_ROUTING_INFORMATION";break;} ++ case CEC_OPCODE_ACTIVE_SOURCE: {return "CEC_OPCODE_ACTIVE_SOURCE";break;} ++ case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS: {return "CEC_OPCODE_GIVE_PHYSICAL_ADDRESS";break;} ++ case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS: {return "CEC_OPCODE_REPORT_PHYSICAL_ADDRESS";break;} ++ case CEC_OPCODE_REQUEST_ACTIVE_SOURCE: {return "CEC_OPCODE_REQUEST_ACTIVE_SOURCE";break;} ++ case CEC_OPCODE_SET_STREAM_PATH: {return "CEC_OPCODE_SET_STREAM_PATH";break;} ++ case CEC_OPCODE_DEVICE_VENDOR_ID: {return "CEC_OPCODE_DEVICE_VENDOR_ID";break;} ++ case CEC_OPCODE_VENDOR_COMMAND: {return "CEC_OPCODE_VENDOR_COMMAND";break;} ++ case CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN: {return "CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN";break;} ++ case CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP: {return "CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP";break;} ++ case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID: {return "CEC_OPCODE_GIVE_DEVICE_VENDOR_ID";break;} ++ case CEC_OPCODE_MENU_REQUEST: {return "CEC_OPCODE_MENU_REQUEST";break;} ++ case CEC_OPCODE_MENU_STATUS: {return "CEC_OPCODE_MENU_STATUS";break;} ++ case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS: {return "CEC_OPCODE_GIVE_DEVICE_POWER_STATUS";break;} ++ case CEC_OPCODE_REPORT_POWER_STATUS: {return "CEC_OPCODE_REPORT_POWER_STATUS";break;} ++ case CEC_OPCODE_GET_MENU_LANGUAGE: {return "CEC_OPCODE_GET_MENU_LANGUAGE";break;} ++ case CEC_OPCODE_SET_ANALOGUE_SERVICE: {return "CEC_OPCODE_SET_ANALOGUE_SERVICE";break;} ++ case CEC_OPCODE_SET_DIGITAL_SERVICE: {return "CEC_OPCODE_SET_DIGITAL_SERVICE";break;} ++ case CEC_OPCODE_SET_DIGITAL_TIMER: {return "CEC_OPCODE_SET_DIGITAL_TIMER";break;} ++ case CEC_OPCODE_CLEAR_DIGITAL_TIMER: {return "CEC_OPCODE_CLEAR_DIGITAL_TIMER";break;} ++ case CEC_OPCODE_SET_AUDIO_RATE: {return "CEC_OPCODE_SET_AUDIO_RATE";break;} ++ case CEC_OPCODE_INACTIVE_SOURCE: {return "CEC_OPCODE_INACTIVE_SOURCE";break;} ++ case CEC_OPCODE_CEC_VERSION: {return "CEC_OPCODE_CEC_VERSION";break;} ++ case CEC_OPCODE_GET_CEC_VERSION: {return "CEC_OPCODE_GET_CEC_VERSION";break;} ++ case CEC_OPCODE_VENDOR_COMMAND_WITH_ID: {return "CEC_OPCODE_VENDOR_COMMAND_WITH_ID";break;} ++ case CEC_OPCODE_CLEAR_EXTERNAL_TIMER: {return "CEC_OPCODE_CLEAR_EXTERNAL_TIMER";break;} ++ case CEC_OPCODE_SET_EXTERNAL_TIMER: {return "CEC_OPCODE_SET_EXTERNAL_TIMER";break;} ++ case CEC_OPCODE_ABORT_MESSAGE: {return "CEC_OPCODE_ABORT_MESSAGE";break;} ++ default : {return "unknown";break;} ++ } ++} ++ ++ ++static char *cec_ioctl(int io) ++{ ++ switch (io) ++ { ++ case CEC_VERBOSE_ON_CMD: {return "CEC_VERBOSE_ON_CMD";break;} ++ case CEC_VERBOSE_OFF_CMD: {return "CEC_VERBOSE_OFF_CMD";break;} ++ case CEC_BYEBYE_CMD: {return "CEC_BYEBYE_CMD";break;} ++ case CEC_IOCTL_RX_ADDR_CMD: {return "CEC_IOCTL_RX_ADDR_CMD";break;} ++ case CEC_IOCTL_PHY_ADDR_CMD: {return "CEC_IOCTL_PHY_ADDR_CMD";break;} ++ case CEC_IOCTL_WAIT_FRAME_CMD: {return "CEC_IOCTL_WAIT_FRAME_CMD";break;} ++ case CEC_IOCTL_ABORT_MSG_CMD: {return "CEC_IOCTL_ABORT_MSG_CMD";break;} ++ case CEC_IOCTL_ACTIVE_SRC_CMD: {return "CEC_IOCTL_ACTIVE_SRC_CMD";break;} ++ case CEC_IOCTL_VERSION_CMD: {return "CEC_IOCTL_VERSION_CMD";break;} ++ case CEC_IOCTL_CLEAR_ANALOGUE_TIMER_CMD: {return "CEC_IOCTL_CLEAR_ANALOGUE_TIMER_CMD";break;} ++ case CEC_IOCTL_CLEAR_DIGITAL_TIMER_CMD: {return "CEC_IOCTL_CLEAR_DIGITAL_TIMER_CMD";break;} ++ case CEC_IOCTL_CLEAR_EXT_TIMER_WITH_EXT_PLUG_CMD: {return "CEC_IOCTL_CLEAR_EXT_TIMER_WITH_EXT_PLUG_CMD";break;} ++ case CEC_IOCTL_CLEAR_EXT_TIMER_WITH_PHY_ADDR_CMD: {return "CEC_IOCTL_CLEAR_EXT_TIMER_WITH_PHY_ADDR_CMD";break;} ++ case CEC_IOCTL_DECK_CTRL_CMD: {return "CEC_IOCTL_DECK_CTRL_CMD";break;} ++ case CEC_IOCTL_DECK_STATUS_CMD: {return "CEC_IOCTL_DECK_STATUS_CMD";break;} ++ case CEC_IOCTL_DEVICE_VENDOR_ID_CMD: {return "CEC_IOCTL_DEVICE_VENDOR_ID_CMD";break;} ++ case CEC_IOCTL_FEATURE_ABORT_CMD: {return "CEC_IOCTL_FEATURE_ABORT_CMD";break;} ++ case CEC_IOCTL_GET_CEC_VERSION_CMD: {return "CEC_IOCTL_GET_CEC_VERSION_CMD";break;} ++ case CEC_IOCTL_GET_MENU_LANGUAGE_CMD: {return "CEC_IOCTL_GET_MENU_LANGUAGE_CMD";break;} ++ case CEC_IOCTL_GIVE_AUDIO_STATUS_CMD: {return "CEC_IOCTL_GIVE_AUDIO_STATUS_CMD";break;} ++ case CEC_IOCTL_GIVE_DECK_STATUS_CMD: {return "CEC_IOCTL_GIVE_DECK_STATUS_CMD";break;} ++ case CEC_IOCTL_GIVE_DEVICE_POWER_STATUS_CMD: {return "CEC_IOCTL_GIVE_DEVICE_POWER_STATUS_CMD";break;} ++ case CEC_IOCTL_GIVE_DEVICE_VENDOR_ID_CMD: {return "CEC_IOCTL_GIVE_DEVICE_VENDOR_ID_CMD";break;} ++ case CEC_IOCTL_GIVE_OSD_NAME_CMD: {return "CEC_IOCTL_GIVE_OSD_NAME_CMD";break;} ++ case CEC_IOCTL_GIVE_PHY_ADDR_CMD: {return "CEC_IOCTL_GIVE_PHY_ADDR_CMD";break;} ++ case CEC_IOCTL_GIVE_SYS_AUDIO_MODE_STATUS_CMD: {return "CEC_IOCTL_GIVE_SYS_AUDIO_MODE_STATUS_CMD";break;} ++ case CEC_IOCTL_GIVE_TUNER_DEVICE_STATUS_CMD: {return "CEC_IOCTL_GIVE_TUNER_DEVICE_STATUS_CMD";break;} ++ case CEC_IOCTL_IMAGE_VIEW_ON_CMD: {return "CEC_IOCTL_IMAGE_VIEW_ON_CMD";break;} ++ case CEC_IOCTL_INACTIVE_SRC_CMD: {return "CEC_IOCTL_INACTIVE_SRC_CMD";break;} ++ case CEC_IOCTL_MENU_REQUEST_CMD: {return "CEC_IOCTL_MENU_REQUEST_CMD";break;} ++ case CEC_IOCTL_MENU_STATUS_CMD: {return "CEC_IOCTL_MENU_STATUS_CMD";break;} ++ case CEC_IOCTL_PLAY_CMD: {return "CEC_IOCTL_PLAY_CMD";break;} ++ case CEC_IOCTL_POLLING_MSG_CMD: {return "CEC_IOCTL_POLLING_MSG_CMD";break;} ++ case CEC_IOCTL_REC_OFF_CMD: {return "CEC_IOCTL_REC_OFF_CMD";break;} ++ case CEC_IOCTL_REC_ON_ANALOGUE_SERVICE_CMD: {return "CEC_IOCTL_REC_ON_ANALOGUE_SERVICE_CMD";break;} ++ case CEC_IOCTL_REC_ON_DIGITAL_SERVICE_CMD: {return "CEC_IOCTL_REC_ON_DIGITAL_SERVICE_CMD";break;} ++ case CEC_IOCTL_REC_ON_EXT_PHY_ADDR_CMD: {return "CEC_IOCTL_REC_ON_EXT_PHY_ADDR_CMD";break;} ++ case CEC_IOCTL_REC_ON_EXT_PLUG_CMD: {return "CEC_IOCTL_REC_ON_EXT_PLUG_CMD";break;} ++ case CEC_IOCTL_REC_ON_OWN_SRC_CMD: {return "CEC_IOCTL_REC_ON_OWN_SRC_CMD";break;} ++ case CEC_IOCTL_REC_STATUS_CMD: {return "CEC_IOCTL_REC_STATUS_CMD";break;} ++ case CEC_IOCTL_REC_TV_SCREEN_CMD: {return "CEC_IOCTL_REC_TV_SCREEN_CMD";break;} ++ case CEC_IOCTL_REPORT_AUDIO_STATUS_CMD: {return "CEC_IOCTL_REPORT_AUDIO_STATUS_CMD";break;} ++ case CEC_IOCTL_REPORT_PHY_ADDR_CMD: {return "CEC_IOCTL_REPORT_PHY_ADDR_CMD";break;} ++ case CEC_IOCTL_REPORT_POWER_STATUS_CMD: {return "CEC_IOCTL_REPORT_POWER_STATUS_CMD";break;} ++ case CEC_IOCTL_REQUEST_ACTIVE_SRC_CMD: {return "CEC_IOCTL_REQUEST_ACTIVE_SRC_CMD";break;} ++ case CEC_IOCTL_ROUTING_CHANGE_CMD: {return "CEC_IOCTL_ROUTING_CHANGE_CMD";break;} ++ case CEC_IOCTL_ROUTING_INFORMATION_CMD: {return "CEC_IOCTL_ROUTING_INFORMATION_CMD";break;} ++ case CEC_IOCTL_SELECT_ANALOGUE_SERVICE_CMD: {return "CEC_IOCTL_SELECT_ANALOGUE_SERVICE_CMD";break;} ++ case CEC_IOCTL_SELECT_DIGITAL_SERVICE_CMD: {return "CEC_IOCTL_SELECT_DIGITAL_SERVICE_CMD";break;} ++ case CEC_IOCTL_SET_ANALOGUE_TIMER_CMD: {return "CEC_IOCTL_SET_ANALOGUE_TIMER_CMD";break;} ++ case CEC_IOCTL_SET_AUDIO_RATE_CMD: {return "CEC_IOCTL_SET_AUDIO_RATE_CMD";break;} ++ case CEC_IOCTL_SET_DIGITAL_TIMER_CMD: {return "CEC_IOCTL_SET_DIGITAL_TIMER_CMD";break;} ++ case CEC_IOCTL_SET_EXT_TIMER_WITH_EXT_PLUG_CMD: {return "CEC_IOCTL_SET_EXT_TIMER_WITH_EXT_PLUG_CMD";break;} ++ case CEC_IOCTL_SET_EXT_TIMER_WITH_PHY_ADDR_CMD: {return "CEC_IOCTL_SET_EXT_TIMER_WITH_PHY_ADDR_CMD";break;} ++ case CEC_IOCTL_SET_MENU_LANGUAGE_CMD: {return "CEC_IOCTL_SET_MENU_LANGUAGE_CMD";break;} ++ case CEC_IOCTL_SET_OSD_NAME_CMD: {return "CEC_IOCTL_SET_OSD_NAME_CMD";break;} ++ case CEC_IOCTL_SET_OSD_STRING_CMD: {return "CEC_IOCTL_SET_OSD_STRING_CMD";break;} ++ case CEC_IOCTL_SET_STREAM_PATH_CMD: {return "CEC_IOCTL_SET_STREAM_PATH_CMD";break;} ++ case CEC_IOCTL_SET_SYS_AUDIO_MODE_CMD: {return "CEC_IOCTL_SET_SYS_AUDIO_MODE_CMD";break;} ++ case CEC_IOCTL_SET_TIMER_PROGRAM_TITLE_CMD: {return "CEC_IOCTL_SET_TIMER_PROGRAM_TITLE_CMD";break;} ++ case CEC_IOCTL_STANDBY_CMD: {return "CEC_IOCTL_STANDBY_CMD";break;} ++ case CEC_IOCTL_SYS_AUDIO_MODE_REQUEST_CMD: {return "CEC_IOCTL_SYS_AUDIO_MODE_REQUEST_CMD";break;} ++ case CEC_IOCTL_SYS_AUDIO_MODE_STATUS_CMD: {return "CEC_IOCTL_SYS_AUDIO_MODE_STATUS_CMD";break;} ++ case CEC_IOCTL_TEXT_VIEW_ON_CMD: {return "CEC_IOCTL_TEXT_VIEW_ON_CMD";break;} ++ case CEC_IOCTL_TIMER_CLEARED_STATUS_CMD: {return "CEC_IOCTL_TIMER_CLEARED_STATUS_CMD";break;} ++ case CEC_IOCTL_TIMER_STATUS_CMD: {return "CEC_IOCTL_TIMER_STATUS_CMD";break;} ++ case CEC_IOCTL_TUNER_DEVICE_STATUS_ANALOGUE_CMD: {return "CEC_IOCTL_TUNER_DEVICE_STATUS_ANALOGUE_CMD";break;} ++ case CEC_IOCTL_TUNER_DEVICE_STATUS_DIGITAL_CMD: {return "CEC_IOCTL_TUNER_DEVICE_STATUS_DIGITAL_CMD";break;} ++ case CEC_IOCTL_TUNER_STEP_DECREMENT_CMD: {return "CEC_IOCTL_TUNER_STEP_DECREMENT_CMD";break;} ++ case CEC_IOCTL_TUNER_STEP_INCREMENT_CMD: {return "CEC_IOCTL_TUNER_STEP_INCREMENT_CMD";break;} ++ case CEC_IOCTL_USER_CTRL_CMD: {return "CEC_IOCTL_USER_CTRL_CMD";break;} ++ case CEC_IOCTL_USER_CTRL_PLAY_CMD: {return "CEC_IOCTL_USER_CTRL_PLAY_CMD";break;} ++ case CEC_IOCTL_USER_CTRL_SELECT_AUDIOINPUT_CMD: {return "CEC_IOCTL_USER_CTRL_SELECT_AUDIOINPUT_CMD";break;} ++ case CEC_IOCTL_USER_CTRL_SELECT_AVINPUT_CMD: {return "CEC_IOCTL_USER_CTRL_SELECT_AVINPUT_CMD";break;} ++ case CEC_IOCTL_USER_CTRL_SELECT_MEDIA_CMD: {return "CEC_IOCTL_USER_CTRL_SELECT_MEDIA_CMD";break;} ++ case CEC_IOCTL_USER_CTRL_TUNE_CMD: {return "CEC_IOCTL_USER_CTRL_TUNE_CMD";break;} ++ case CEC_IOCTL_USER_CTRL_RELEASED_CMD: {return "CEC_IOCTL_USER_CTRL_RELEASED_CMD";break;} ++ case CEC_IOCTL_VENDOR_COMMAND_CMD: {return "CEC_IOCTL_VENDOR_COMMAND_CMD";break;} ++ case CEC_IOCTL_VENDOR_COMMAND_WITH_ID_CMD: {return "CEC_IOCTL_VENDOR_COMMAND_WITH_ID_CMD";break;} ++ case CEC_IOCTL_VENDOR_REMOTE_BUTTON_DOWN_CMD: {return "CEC_IOCTL_VENDOR_REMOTE_BUTTON_DOWN_CMD";break;} ++ case CEC_IOCTL_VENDOR_REMOTE_BUTTON_UP_CMD: {return "CEC_IOCTL_VENDOR_REMOTE_BUTTON_UP_CMD";break;} ++ case CEC_IOCTL_GET_SW_VERSION_CMD: {return "CEC_IOCTL_GET_SW_VERSION_CMD";break;} ++ case CEC_IOCTL_SET_POWER_STATE_CMD: {return "CEC_IOCTL_SET_POWER_STATE_CMD";break;} ++ case CEC_IOCTL_GET_POWER_STATE_CMD: {return "CEC_IOCTL_GET_POWER_STATE_CMD";break;} ++ case CEC_IOCTL_INSTANCE_CONFIG_CMD: {return "CEC_IOCTL_INSTANCE_CONFIG_CMD";break;} ++ case CEC_IOCTL_INSTANCE_SETUP_CMD: {return "CEC_IOCTL_INSTANCE_SETUP_CMD";break;} ++ case CEC_IOCTL_GET_INSTANCE_SETUP_CMD: {return "CEC_IOCTL_GET_INSTANCE_SETUP_CMD";break;} ++ case CEC_IOCTL_ENABLE_EVENT_CMD: {return "CEC_IOCTL_ENABLE_EVENT_CMD";break;} ++ case CEC_IOCTL_DISABLE_EVENT_CMD: {return "CEC_IOCTL_DISABLE_EVENT_CMD";break;} ++ case CEC_IOCTL_ENABLE_CALIBRATION_CMD: {return "CEC_IOCTL_ENABLE_CALIBRATION_CMD";break;} ++ case CEC_IOCTL_DISABLE_CALIBRATION_CMD: {return "CEC_IOCTL_DISABLE_CALIBRATION_CMD";break;} ++ case CEC_IOCTL_SEND_MSG_CMD: {return "CEC_IOCTL_SEND_MSG_CMD";break;} ++ case CEC_IOCTL_SET_REGISTER_CMD: {return "CEC_IOCTL_SET_REGISTER_CMD";break;} ++ default : {return "unknown";break;} ++ } ++} ++ ++ ++static char *cec_rxstatus(int s) ++{ ++ switch (s) ++ { ++ case CEC_MSG_SUCCESS :{return "success";break;} ++ case CEC_MSG_FAIL_DATA_NOT_ACK :{return "data not ack";break;} ++ case CEC_CSP_OFF_STATE :{return "CSP off";break;} ++ case CEC_BAD_REQ_SERVICE :{return "bad Req";break;} ++ case CEC_MSG_FAIL_UNABLE_TO_ACCESS :{return "CEC line error";break;} ++ case CEC_MSG_FAIL_ARBITRATION_ERROR :{return "arb error";break;} ++ case CEC_MSG_FAIL_BIT_TIMMING_ERROR :{return "bit error";break;} ++ case CEC_MSG_FAIL_DEST_NOT_ACK :{return "destination not ack";break;} ++ default : {return "unknown";break;} ++ } ++} ++ ++ ++static unsigned char get_next_logical_addr(cec_device_type device,unsigned char la) ++{ ++ switch (device) { ++ case CEC_DEVICE_TYPE_TV: ++ switch (la) { ++ case CEC_LOGICAL_ADDRESS_TV: ++ return CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST; ++ default: ++ return CEC_LOGICAL_ADDRESS_TV; ++ } ++ case CEC_DEVICE_TYPE_REC_DEVICE: ++ switch (la) { ++ case CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_1: ++ return CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_2; ++ case CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_2: ++ return CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_3; ++ case CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_3: ++ return CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST; ++ default: ++ return CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_1; ++ } ++ case CEC_DEVICE_TYPE_TUNER: ++ switch (la) { ++ case CEC_LOGICAL_ADDRESS_TUNER_1: ++ return CEC_LOGICAL_ADDRESS_TUNER_2; ++ case CEC_LOGICAL_ADDRESS_TUNER_2: ++ return CEC_LOGICAL_ADDRESS_TUNER_3; ++ case CEC_LOGICAL_ADDRESS_TUNER_3: ++ return CEC_LOGICAL_ADDRESS_TUNER_4; ++ case CEC_LOGICAL_ADDRESS_TUNER_4: ++ return CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST; ++ default: ++ return CEC_LOGICAL_ADDRESS_TUNER_1; ++ } ++ case CEC_DEVICE_TYPE_PLAYBACK_DEVICE: ++ switch (la) { ++ case CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_1: ++ return CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_2; ++ case CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_2: ++ return CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_3; ++ case CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_3: ++ return CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST; ++ default: ++ return CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_1; ++ } ++ case CEC_DEVICE_TYPE_AUDIO_DEVICE: ++ switch (la) { ++ case CEC_LOGICAL_ADDRESS_AUDIO_SYSTEM: ++ return CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST; ++ default: ++ return CEC_LOGICAL_ADDRESS_AUDIO_SYSTEM; ++ } ++ default: ++ return CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST; ++ } ++} ++ ++static int device_type(int type) ++{ ++ printk(KERN_INFO "hdmicec declared as a "); ++ switch (type) { ++ case CEC_DEVICE_TYPE_TV: ++ printk("TV"); ++ break; ++ case CEC_DEVICE_TYPE_REC_DEVICE: ++ printk("record"); ++ break; ++ case CEC_DEVICE_TYPE_TUNER: ++ printk("tuner"); ++ break; ++ case CEC_DEVICE_TYPE_PLAYBACK_DEVICE: ++ printk("playback"); ++ break; ++ case CEC_DEVICE_TYPE_AUDIO_DEVICE: ++ printk("audio"); ++ break; ++ default: ++ printk("default (playback)"); ++ type = CEC_DEVICE_TYPE_PLAYBACK_DEVICE; ++ break; ++ } ++ printk(" device type\n"); ++ return type; ++} ++ ++ ++/* ++ * ++ * PROCESSING ++ * ---------- ++ * LEVEL 2 ++ * ++ */ ++ ++ ++/* ++ * CEC Power On ++ */ ++static void cec_on(cec_instance *this) ++{ ++ int err; ++ struct task_struct *tsk = current; ++ ++ // disable_irq(gpio_to_irq(TDA_IRQ_CALIB)); ++ ++ this->cec.power = tmPowerOn; ++ TRY(tmdlHdmiCecSetPowerState(this->cec.inst,this->cec.power)); ++ ++ /* turn GPIO into calib pulse generator */ ++ gpio_direction_output(TDA_IRQ_CALIB,0); /* output (1 means try-state or high) */ ++ __gpio_set_value(TDA_IRQ_CALIB,1); ++ this->cec.clock = TMDL_HDMICEC_CLOCK_FRO; ++ TRY(tmdlHdmiCecEnableCalibration(this->cec.inst,this->cec.clock)); ++ msleep(10); ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ ++ /* CAUTION : TDA needs a real 10ms pulse */ ++ cpu_relax(); ++ spin_lock_irq(&tsk->sighand->siglock); ++ __gpio_set_value(TDA_IRQ_CALIB,0); ++ __udelay(10000); ++ __gpio_set_value(TDA_IRQ_CALIB,1); ++ spin_unlock_irq(&tsk->sighand->siglock); ++ ++ msleep(10); ++ TRY(tmdlHdmiCecDisableCalibration(this->cec.inst)); ++ ++ /* setup */ ++ TRY(tmdlHdmiCecGetInstanceSetup(this->cec.inst,&this->cec.setup)); ++ this->cec.setup.DeviceLogicalAddress = this->cec.rx_addr; ++ this->cec.clock = TMDL_HDMICEC_CLOCK_FRO; ++ this->cec.setup.cecClockSource = this->cec.clock; ++ TRY(tmdlHdmiCecInstanceSetup(this->cec.inst,&this->cec.setup)); ++ ++ /* turn GPIO into IRQ */ ++ gpio_direction_input(TDA_IRQ_CALIB); ++ // enable_irq(gpio_to_irq(TDA_IRQ_CALIB)); ++ ++ LOG(KERN_INFO,"standby --> on\n"); ++ ++ TRY_DONE: ++ (void)0; ++} ++ ++/* ++ * CEC Power Off ++ */ ++static void cec_standby(cec_instance *this) ++{ ++ int err; ++ ++ this->cec.power = tmPowerStandby; ++ TRY(tmdlHdmiCecSetPowerState(this->cec.inst,this->cec.power)); ++ ++ LOG(KERN_INFO,"on --> standby\n"); ++ ++ TRY_DONE: ++ (void)0; ++} ++ ++/* ++ * CEC interrupt polling ++ */ ++static void cec_interrupt(struct work_struct *dummy) ++{ ++ cec_instance *this=&our_instance; ++ unsigned short new_phy_addr=edid_phy_addr(); ++ int err=0; ++ ++ LOG(KERN_INFO,"%s called\n",__func__); ++ ++ /* switch on/off CEC */ ++ if (!get_hpd_status() && \ ++ (this->cec.power == tmPowerOn)) { ++ this->cec.source_status = CEC_POWER_STATUS_STANDBY; ++/* TRY(tmdlHdmiCecInactiveSource(this->cec.inst, \ */ ++/* this->cec.initiator, \ */ ++/* this->cec.phy_addr)); */ ++ cec_standby(this); ++ } ++ else if (get_hpd_status() && \ ++ (this->cec.power == tmPowerStandby)) { ++ /* send active msg when hdmi has been abled */ ++ cec_on(this); ++ } ++ /* new phy addr means new EDID, mean HPD ! */ ++ else if ((this->cec.phy_addr != new_phy_addr) && \ ++ (this->cec.source_status == CEC_POWER_STATUS_ON)) { ++ LOG(KERN_INFO,"New physical address %02x\n",new_phy_addr); ++ this->cec.phy_addr = new_phy_addr; ++ if (this->cec.phy_addr != 0xFFFF) { ++ this->cec.rx_addr = get_next_logical_addr(this->cec.device_type,CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST); ++ TRY(tmdlHdmiCecPollingMessage(this->cec.inst,this->cec.rx_addr)); ++ } ++ else { ++ this->cec.rx_addr = CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST; ++ } ++ } ++#ifdef GUI_OVER_HDMI ++ else if (edid_received()) { /* Check me */ ++ if (this->cec.source_status == CEC_POWER_STATUS_STANDBY) { ++ /* only for GFX on HDMI, do not use if only video playback on HDMI */ ++ TRY(tmdlHdmiCecImageViewOn(this->cec.inst,this->cec.initiator)); ++ TRY(tmdlHdmiCecHandleInterrupt(this->cec.inst)); ++ msleep(200); ++ TRY(tmdlHdmiCecActiveSource(this->cec.inst,this->cec.phy_addr)); ++ this->cec.source_status = CEC_POWER_STATUS_ON; ++ } ++ } ++#endif ++ ++#if 0 ++ if (this->cec.phy_addr != 0xFFFF) { ++ ++ /* claim source status */ ++ if ((get_hdmi_status() == tmPowerStandby) && \ ++ (this->cec.source_status == CEC_POWER_STATUS_ON)) { ++ /* send inactive msg when hdmi has been disabled */ ++ this->cec.source_status = CEC_POWER_STATUS_STANDBY; ++ TRY(tmdlHdmiCecInactiveSource(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.phy_addr)); ++ } ++ else if ((get_hdmi_status() == tmPowerOn) && \ ++ (this->cec.source_status == CEC_POWER_STATUS_STANDBY)) { ++ /* send active msg when hdmi has been abled */ ++ this->cec.source_status = CEC_POWER_STATUS_ON; ++ TRY(tmdlHdmiCecActiveSource(this->cec.inst, \ ++ this->cec.phy_addr)); ++ } ++/* printk(KERN_INFO "DBG phd_status:%s cec.power:%s\n", \ */ ++/* get_hpd_status()?"Active":"Inactive", \ */ ++/* (this->cec.power==tmPowerOn)?"On":"Standby"); */ ++ } ++#endif ++ ++ /* internal handeling */ ++ TRY(tmdlHdmiCecHandleInterrupt(this->cec.inst)); ++ ++ TRY_DONE: ++ ++ /* setup next tick */ ++ if (!this->driver.deinit_req) { ++ /* setup next polling */ ++#ifndef IRQ ++/* this->driver.timer.expires = jiffies + ( CHECK_EVERY_XX_MS * HZ / 1000 ); */ ++/* add_timer(&this->driver.timer); */ ++ mod_timer(&this->driver.timer,jiffies + ( CHECK_EVERY_XX_MS * HZ / 1000 )); ++#endif ++ } ++ else { ++ this->driver.deinit_req++; ++ wake_up_interruptible(&this->driver.wait); ++ } ++} ++ ++#ifndef IRQ ++static DECLARE_WORK(wq_name, cec_interrupt); ++ ++void polling_timeout(unsigned long arg) ++{ ++ ++#if 0 ++ /* fake frame for equipement-less testing */ ++ ++ cec_instance *this=&our_instance; ++ ++ if (this->driver.timer.data++>1000) { ++ printk(KERN_INFO "Fake Rx message\n"); ++ this->driver.timer.data=0; ++ ++ this->cec.frame.count = 4; ++ this->cec.frame.addr = 4; /* 0-->4 (TV-->MediaPlayer1) */ ++ this->cec.frame.data[0]=0x46; /* opcode: "GiveOsd" */ ++ this->cec.frame.service = CEC_RX_DONE; ++ ++ this->driver.poll_done = true; ++ wake_up_interruptible(&this->driver.wait); ++ } ++#endif ++ ++ /* derefered because ATOMIC context of timer does not support I2C_transfert */ ++ schedule_work(&wq_name); ++ ++} ++#endif ++ ++#ifndef IRQ ++/* ++ * TDA irq ++ */ ++static irqreturn_t tda_irq(int irq, void *_udc) ++{ ++ cec_instance *this=&our_instance; ++ /* printk(KERN_INFO "DBG caught irq:%d\n",irq); */ ++ ++ /* do it now */ ++ mod_timer(&this->driver.timer,jiffies); ++ ++ return IRQ_HANDLED; ++} ++#endif ++ ++#ifdef TWL4030_HACK ++/* ++ * User Control ++ */ ++static void user_control(int key, int press) ++{ ++ input_report_key(gkp_input, key, press); ++ input_sync(gkp_input); ++ msleep(20); ++ input_report_key(gkp_input, key, 0); ++ input_sync(gkp_input); ++} ++#endif ++ ++/* ++ * CEC callback ++ */ ++static void eventCallbackCEC(tmdlHdmiCecEvent_t event, unsigned char *data, unsigned char length) ++{ ++ int err=0; ++ cec_instance *this=&our_instance; ++ int opcode; ++ int initiator,receiver; ++ ++ if (event == TMDL_HDMICEC_CALLBACK_MESSAGE_AVAILABLE) { ++ ++ this->cec.frame.count = length; ++ this->cec.frame.addr = data[1]; /* .AddressByte */ ++ initiator = (this->cec.frame.addr >> 4) & 0x0F; ++ this->cec.initiator = initiator; ++ receiver = this->cec.frame.addr & 0x0F; ++ memcpy(&this->cec.frame.data,&data[2],length-2); /* .DataBytes[], length - siezof(length,addr,ack) */ ++ opcode=this->cec.frame.data[0]; ++ printk(KERN_INFO "hdmicec:Rx:[%x--->%x] %s length:%d addr:%d %02x%02x%02x%02x\n",initiator,receiver,cec_opcode(opcode), \ ++ length,data[1], ++ this->cec.frame.data[0], \ ++ this->cec.frame.data[1], \ ++ this->cec.frame.data[2], \ ++ this->cec.frame.data[3]); ++ this->cec.frame.service = CEC_RX_DONE; ++ ++ msleep(20); ++ ++ /* automatic answering */ ++ switch (opcode) { ++ case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS: ++ TRY(tmdlHdmiCecReportPhysicalAddress(this->cec.inst, \ ++ this->cec.phy_addr, \ ++ this->cec.device_type)); ++ break; ++ case CEC_OPCODE_GET_CEC_VERSION: ++ TRY(tmdlHdmiCecVersion(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.version)); ++ break; ++ case CEC_OPCODE_GIVE_OSD_NAME: ++ TRY(tmdlHdmiCecSetOsdName(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.osd_name.data, \ ++ this->cec.osd_name.length)); ++ break; ++ case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID: ++ TRY(tmdlHdmiCecDeviceVendorID(this->cec.inst, \ ++ this->cec.vendor_id)); ++ break; ++ case CEC_OPCODE_REQUEST_ACTIVE_SOURCE: ++ if (this->cec.source_status == CEC_POWER_STATUS_ON) { ++ if (this->cec.initiator != 0x0F) { ++ if (receiver == 0x0F) { ++ TRY(tmdlHdmiCecActiveSource(this->cec.inst,this->cec.phy_addr)); ++ } ++ } ++ } ++ break; ++ case CEC_OPCODE_ACTIVE_SOURCE: ++ if (this->cec.source_status == CEC_POWER_STATUS_ON) { ++ this->cec.source_status = CEC_POWER_STATUS_STANDBY; ++ hdmi_disable(1); ++ this->cec.power = tmPowerOn; ++ TRY(tmdlHdmiCecSetPowerState(this->cec.inst,this->cec.power)); /* keeps CEC alive */ ++ } ++ break; ++ case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS: ++ TRY(tmdlHdmiCecReportPowerStatus(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.source_status)); ++ break; ++ case CEC_OPCODE_STANDBY: ++ /* mind recording device can only be stopped by appli */ ++ if (this->cec.device_type != CEC_DEVICE_TYPE_REC_DEVICE) { ++ this->cec.source_status = CEC_POWER_STATUS_STANDBY; ++ hdmi_disable(1); ++ this->cec.power = tmPowerOn; ++ TRY(tmdlHdmiCecSetPowerState(this->cec.inst,this->cec.power)); /* keeps CEC alive */ ++ } ++ break; ++ case CEC_OPCODE_ROUTING_INFORMATION: ++ case CEC_OPCODE_SET_STREAM_PATH: ++ /* wake-up if called */ ++ if (this->cec.phy_addr == (((int)this->cec.frame.data[1] << 8) + this->cec.frame.data[2])) { ++ if (this->cec.source_status != CEC_POWER_STATUS_ON) { ++ this->cec.source_status = CEC_POWER_STATUS_ON; ++ hdmi_enable(); ++ } ++ TRY(tmdlHdmiCecActiveSource(this->cec.inst,this->cec.phy_addr)); ++ } ++ break; ++/* case /\* NEW DECK ??? *\/ */ ++ case CEC_OPCODE_ROUTING_CHANGE: ++ /* wake-up if called */ ++ if (this->cec.phy_addr == (((int)this->cec.frame.data[3] << 8) + this->cec.frame.data[4])) { ++ if (this->cec.source_status != CEC_POWER_STATUS_ON) { ++ this->cec.source_status = CEC_POWER_STATUS_ON; ++ hdmi_enable(); ++ } ++ TRY(tmdlHdmiCecActiveSource(this->cec.inst,this->cec.phy_addr)); ++ } ++ break; ++ case CEC_OPCODE_ABORT_MESSAGE: ++ if (this->cec.phy_addr == (((int)this->cec.frame.data[3] << 8) + this->cec.frame.data[4])) { ++ TRY(tmdlHdmiCecFeatureAbort(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.feature_abort.FeatureOpcode, \ ++ this->cec.feature_abort.AbortReason)); ++ } ++ break; ++ case CEC_OPCODE_MENU_REQUEST: ++#ifdef TWL4030_HACK ++ this->cec.menu_status = CEC_MENU_STATE_ACTIVATE; ++ TRY(tmdlHdmiCecMenuStatus(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.menu_status)); ++ break; ++#endif ++ case CEC_OPCODE_USER_CONTROL_PRESSED: ++ switch (this->cec.frame.data[1]) { ++#ifdef TWL4030_HACK /* AL : hack to bypass keypad */ ++ case CEC_REMOTE_BUTTON_SELECT: ++ user_control(353,64); ++ break; ++ case CEC_REMOTE_BUTTON_UP: ++ user_control(103,128); ++ break; ++ case CEC_REMOTE_BUTTON_DOWN: ++ user_control(108,128); ++ break; ++ case CEC_REMOTE_BUTTON_LEFT: ++ user_control(105,128); ++ break; ++ case CEC_REMOTE_BUTTON_RIGHT: ++ user_control(106,128); ++ break; ++ case CEC_REMOTE_BUTTON_EXIT: ++ user_control(14,8); ++ break; ++#endif ++ case CEC_REMOTE_BUTTON_POWER: ++ this->cec.source_status = CEC_POWER_STATUS_ON; ++ hdmi_enable(); ++ break; ++ default: ++ this->cec.feature_abort.FeatureOpcode=opcode; ++ this->cec.feature_abort.AbortReason=CEC_ABORT_INVALID_OPERAND; ++ TRY(tmdlHdmiCecFeatureAbort(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.feature_abort.FeatureOpcode, \ ++ this->cec.feature_abort.AbortReason)); ++ break; ++ } ++ break; ++#ifdef TWL4030_HACK ++ case CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN: ++ user_control(59,8); ++#endif ++ break; ++ case CEC_OPCODE_FEATURE_ABORT: ++ /* stop any state machine transition */ ++ break; ++ case CEC_OPCODE_VENDOR_COMMAND: ++ case CEC_OPCODE_DEVICE_VENDOR_ID: ++ /* hopefully will be handle in userspace */ ++ break; ++ default: ++ if (receiver != 0x0F) { ++ this->cec.feature_abort.FeatureOpcode=opcode; ++ this->cec.feature_abort.AbortReason=CEC_ABORT_UNKNOWN_OPCODE; ++ TRY(tmdlHdmiCecFeatureAbort(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.feature_abort.FeatureOpcode, \ ++ this->cec.feature_abort.AbortReason)); ++ } ++ break; ++ } ++ this->driver.poll_done = true; ++ wake_up_interruptible(&this->driver.wait); ++ } ++ else if (event == TMDL_HDMICEC_CALLBACK_STATUS) { ++ ++ this->cec.frame.count = length; ++ this->cec.frame.addr = data[1]; /* .AddressByte */ ++ initiator = (this->cec.frame.addr >> 4) & 0x0F; ++ receiver = this->cec.frame.addr & 0x0F; ++ memcpy(&this->cec.frame.data,&data[2],length-2); /* .DataBytes[], length - siezof(length,addr) */ ++ opcode=this->cec.frame.data[0]; ++ this->cec.frame.service = CEC_TX_DONE; ++ ++ if (length==POLLING_LENGTH) { ++ if (opcode == CEC_MSG_FAIL_DEST_NOT_ACK) { ++ /* no echo means it's mine ! */ ++ TRY(tmdlHdmiCecSetLogicalAddress(this->cec.inst,this->cec.rx_addr)); ++ TRY(tmdlHdmiCecReportPhysicalAddress(this->cec.inst, \ ++ this->cec.phy_addr, \ ++ this->cec.device_type)); ++ /* DEVICE VENDOR ID sending after logicial address allocation according to spec 1.4 */ ++ TRY(tmdlHdmiCecDeviceVendorID(this->cec.inst, this->cec.vendor_id)); ++ } ++ else if (opcode == CEC_MSG_SUCCESS) { ++ /* try next one */ ++ this->cec.rx_addr=get_next_logical_addr(this->cec.device_type,this->cec.rx_addr); ++ if (this->cec.rx_addr != CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST) { ++ TRY(tmdlHdmiCecPollingMessage(this->cec.inst,this->cec.rx_addr)); ++ } ++ else { ++ /* no more room, keep and claim unregistred */ ++ TRY(tmdlHdmiCecSetLogicalAddress(this->cec.inst,this->cec.rx_addr)); ++ TRY(tmdlHdmiCecReportPhysicalAddress(this->cec.inst, \ ++ this->cec.phy_addr, \ ++ this->cec.device_type)); ++ } ++ } ++ else { ++ printk(KERN_INFO "ACK [%x--->%x] %s\n",initiator,receiver,cec_rxstatus(opcode)); ++ } ++ } ++ else { ++ if (CEC_MSG_SUCCESS != opcode) { ++ printk(KERN_INFO "ACK [%x--->%x] %s\n",initiator,receiver,cec_rxstatus(opcode)); ++ } ++ } ++ ++ this->driver.poll_done = true; ++ wake_up_interruptible(&this->driver.wait); ++ ++ } ++ else { ++ LOG(KERN_ERR,"Oups ! Callback got invalid event %d !\n",event); ++ } ++ ++ TRY_DONE: ++ (void)err; ++} ++ ++/* ++ * DevLib CEC opening ++ */ ++static int hdmi_cec_init(cec_instance *this) ++{ ++ int err=0; ++ ++ /* Real opening */ ++ TRY(tmdlHdmiCecOpen(&this->cec.inst)); ++ ++/* this->cec.vendor_id = 0x006037; /\* NXP (IEEE OUI) *\/ */ ++/* this->cec.vendor_id = 0x0000f0; /\* Samsung *\/ */ ++ this->cec.vendor_id = 0x00e091; /* LGE */ ++ ++/* this->cec.version = CEC_VERSION_1_4; */ ++ this->cec.version = CEC_VERSION_1_3a; ++ this->cec.osd_name.data[0]=0x54; /* TDA19989 by default */ ++ this->cec.osd_name.data[1]=0x44; ++ this->cec.osd_name.data[2]=0x41; ++ this->cec.osd_name.data[3]=0x31; ++ this->cec.osd_name.data[4]=0x39; ++ this->cec.osd_name.data[5]=0x39; ++ this->cec.osd_name.data[6]=0x38; ++ this->cec.osd_name.data[7]=0x39; ++ this->cec.osd_name.length=8; ++ ++ TRY(tmdlHdmiCecRegisterCallbacks(this->cec.inst,eventCallbackCEC)); ++ ++ this->cec.phy_addr = param_addr; ++ this->cec.device_type = device_type(param_device); ++ ++ TRY_DONE: ++ return err; ++} ++ ++ ++/* ++ * ++ * ENTRY POINTS ++ * ------------ ++ * LEVEL 3 ++ * ++ * - ++ * ++ */ ++ ++ ++ ++/* ++ * ioctl driver :: opening ++ */ ++ ++static int this_cdev_open(struct inode *pInode, struct file *pFile) ++{ ++ cec_instance *this; ++ int minor=iminor(pInode); ++ ++ if(minor >= MAX_MINOR) { ++ printk(KERN_ERR "hdmicec:%s:only one cec opening please\n",__func__); ++ return -EINVAL; ++ } ++ ++ if ((pFile->private_data != NULL) && (pFile->private_data != &our_instance)) { ++ printk(KERN_ERR "hdmicec:%s:pFile missmatch\n",__func__); ++ } ++ this = pFile->private_data = &our_instance; ++ down(&this->driver.sem); ++ ++ LOG(KERN_INFO,"major:%d minor:%d user:%d\n", imajor(pInode), iminor(pInode), this->driver.user_counter); ++ ++ if ((this->driver.user_counter++) && (this->driver.minor == minor)) { ++ /* init already done */ ++ up(&this->driver.sem); ++ return 0; ++ } ++ this->driver.minor = minor; ++ ++ ++ up(&this->driver.sem); ++ return 0; ++} ++ ++/* ++ * ioctl driver :: ioctl ++ */ ++static int this_cdev_ioctl(struct inode *pInode, struct file *pFile, unsigned int cmd, unsigned long arg) ++{ ++ cec_instance* this = pFile->private_data; ++ int err=0; ++ ++ LOG(KERN_INFO,":%s\n",cec_ioctl(_IOC_NR(cmd))); ++ ++ BUG_ON(this->driver.minor!=iminor(pInode)); ++ if (_IOC_TYPE(cmd) != CEC_IOCTL_BASE) { ++ printk(KERN_INFO "hdmicec:%s:unknown ioctl type: %x\n",__func__,_IOC_TYPE(cmd)); ++ return -ENOIOCTLCMD; ++ } ++ ++ if (_IOC_DIR(cmd) & _IOC_READ) ++ err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)) || !arg; ++ else if (_IOC_DIR(cmd) & _IOC_WRITE) ++ err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)) || !arg; ++ if (err) { ++ printk(KERN_ERR "hdmicec:%s:argument access denied (check address vs value)\n",__func__); ++ printk(KERN_ERR "_IOC_DIR:%d arg:%lx\n",_IOC_DIR(cmd),arg); ++ return -EFAULT; ++ } ++ ++ down(&this->driver.sem); ++ ++ /* Check DevLib consistancy here */ ++ ++ switch ( _IOC_NR(cmd) ) ++ { ++ case CEC_VERBOSE_ON_CMD: ++ { ++ printk(KERN_INFO "verbose on\n"); ++ this->param.verbose=1; ++ break; ++ } ++ ++ case CEC_VERBOSE_OFF_CMD: ++ { ++ printk(KERN_INFO "verbose off\n"); ++ this->param.verbose=0; ++ break; ++ } ++ ++ case CEC_BYEBYE_CMD: ++ { ++ LOG(KERN_INFO,"callback release request\n"); ++ this->cec.frame.service=CEC_RELEASE; ++ this->driver.poll_done = true; ++ wake_up_interruptible(&this->driver.wait); ++ break; ++ } ++ ++ /* ++ no param ++ */ ++ ++ case CEC_IOCTL_DISABLE_CALIBRATION_CMD: ++ { ++ TRY(tmdlHdmiCecDisableCalibration(this->cec.inst)); ++ break; ++ } ++ ++ case CEC_IOCTL_INSTANCE_CONFIG_CMD: ++ { ++ TRY(tmdlHdmiCecInstanceConfig(this->cec.inst)); ++ break; ++ } ++ ++ case CEC_IOCTL_REQUEST_ACTIVE_SRC_CMD: ++ { ++ TRY(tmdlHdmiCecRequestActiveSource(this->cec.inst)); ++ break; ++ } ++ ++ case CEC_IOCTL_ABORT_MSG_CMD: ++ { ++ TRY(tmdlHdmiCecAbortMessage(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_GET_MENU_LANGUAGE_CMD: ++ { ++ TRY(tmdlHdmiCecGetMenuLanguage(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_GIVE_AUDIO_STATUS_CMD: ++ { ++ TRY(tmdlHdmiCecGiveAudioStatus(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_GIVE_DEVICE_POWER_STATUS_CMD: ++ { ++ TRY(tmdlHdmiCecGiveDevicePowerStatus(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_GIVE_DEVICE_VENDOR_ID_CMD: ++ { ++ TRY(tmdlHdmiCecGiveDeviceVendorID(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_GIVE_OSD_NAME_CMD: ++ { ++ TRY(tmdlHdmiCecGiveOsdName(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_GIVE_PHY_ADDR_CMD: ++ { ++ TRY(tmdlHdmiCecGivePhysicalAddress(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_GIVE_SYS_AUDIO_MODE_STATUS_CMD: ++ { ++ TRY(tmdlHdmiCecGiveSystemAudioModeStatus(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_IMAGE_VIEW_ON_CMD: ++ { ++ TRY(tmdlHdmiCecImageViewOn(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_POLLING_MSG_CMD: ++ { ++ TRY(tmdlHdmiCecPollingMessage(this->cec.inst,this->cec.rx_addr)); ++ break; ++ } ++ ++ case CEC_IOCTL_REC_OFF_CMD: ++ { ++ TRY(tmdlHdmiCecRecordOff(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_REC_ON_OWN_SRC_CMD: ++ { ++ TRY(tmdlHdmiCecRecordOnOwnSource(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_REC_TV_SCREEN_CMD: ++ { ++ TRY(tmdlHdmiCecRecordTvScreen(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_STANDBY_CMD: ++ { ++ TRY(tmdlHdmiCecStandby(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_TEXT_VIEW_ON_CMD: ++ { ++ TRY(tmdlHdmiCecTextViewOn(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_TUNER_STEP_DECREMENT_CMD: ++ { ++ TRY(tmdlHdmiCecTunerStepDecrement(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_TUNER_STEP_INCREMENT_CMD: ++ { ++ TRY(tmdlHdmiCecTunerStepIncrement(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_USER_CTRL_RELEASED_CMD: ++ { ++ TRY(tmdlHdmiCecUserControlReleased(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_VENDOR_REMOTE_BUTTON_UP_CMD: ++ { ++ TRY(tmdlHdmiCecVendorRemoteButtonUp(this->cec.inst,this->cec.initiator)); ++ break; ++ } ++ ++ case CEC_IOCTL_ROUTING_INFORMATION_CMD: ++ { ++ TRY(tmdlHdmiCecRoutingInformation(this->cec.inst,this->cec.phy_addr)); ++ break; ++ } ++ ++ case CEC_IOCTL_SET_STREAM_PATH_CMD: ++ { ++ TRY(tmdlHdmiCecSetStreamPath(this->cec.inst,this->cec.phy_addr)); ++ break; ++ } ++ ++ case CEC_IOCTL_ACTIVE_SRC_CMD: ++ { ++ /* NEW first do a */ ++ /* NEW when switch by DSS and was inactive */ ++ TRY(tmdlHdmiCecActiveSource(this->cec.inst,this->cec.phy_addr)); ++ break; ++ } ++ ++ case CEC_IOCTL_SYS_AUDIO_MODE_REQUEST_CMD: ++ { ++ TRY(tmdlHdmiCecSystemAudioModeRequest(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.phy_addr)); ++ break; ++ } ++ ++ /* ++ 1 param ++ */ ++ ++ case CEC_IOCTL_RX_ADDR_CMD: ++ { ++ /* BUG_ON(copy_from_user(&this->cec.rx_addr,(unsigned char*)arg,sizeof(unsigned char)) != 0); */ ++ this->cec.rx_addr=arg; ++ TRY(tmdlHdmiCecSetLogicalAddress(this->cec.inst,this->cec.rx_addr)); ++ break; ++ } ++ ++ case CEC_IOCTL_PHY_ADDR_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.phy_addr,(unsigned short*)arg,sizeof(unsigned short)) != 0); ++ break; ++ } ++ ++ case CEC_IOCTL_GET_CEC_VERSION_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.version,(cec_version*)arg,sizeof(cec_version)) != 0); ++ TRY(tmdlHdmiCecGetCecVersion(this->cec.inst,this->cec.version)); ++ break; ++ } ++ ++ case CEC_IOCTL_GET_SW_VERSION_CMD: ++ { ++ TRY(tmdlHdmiCecGetSWVersion(&this->cec.sw_version)); ++ BUG_ON(copy_to_user((cec_sw_version*)arg,&this->cec.sw_version,sizeof(cec_sw_version)) != 0); ++ break; ++ } ++ ++ case CEC_IOCTL_SET_POWER_STATE_CMD: ++ { ++ /* NEW : log : please use DSS */ ++ BUG_ON(copy_from_user(&this->cec.power,(cec_power*)arg,sizeof(cec_power)) != 0); ++ TRY(tmdlHdmiCecSetPowerState(this->cec.inst,this->cec.power)); ++ break; ++ } ++ ++ case CEC_IOCTL_GET_POWER_STATE_CMD: ++ { ++ TRY(tmdlHdmiCecGetPowerState(this->cec.inst,&this->cec.power)); ++ BUG_ON(copy_to_user((cec_power*)arg,&this->cec.power,sizeof(cec_power)) != 0); ++ break; ++ } ++ ++ case CEC_IOCTL_INSTANCE_SETUP_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.setup,(cec_setup*)arg,sizeof(cec_setup)) != 0); ++ TRY(tmdlHdmiCecInstanceSetup(this->cec.inst,&this->cec.setup)); ++ break; ++ } ++ ++ case CEC_IOCTL_GET_INSTANCE_SETUP_CMD: ++ { ++ TRY(tmdlHdmiCecGetInstanceSetup(this->cec.inst,&this->cec.setup)); ++ BUG_ON(copy_to_user((cec_setup*)arg,&this->cec.setup,sizeof(cec_setup)) != 0); ++ break; ++ } ++ ++ /* ++ case CEC_IOCTL_ENABLE_EVENT_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.an_event,(cec_event*)arg,sizeof(cec_event)) != 0); ++ TRY(tmdlHdmiCecEnableEvent(this->cec.inst,this->cec.an_event)); ++ break; ++ } ++ ++ case CEC_IOCTL_DISABLE_EVENT_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.an_event,(cec_event*)arg,sizeof(cec_event)) != 0); ++ TRY(tmdlHdmiCecDisableEvent(this->cec.inst,this->cec.an_event)); ++ break; ++ } ++ */ ++ ++ case CEC_IOCTL_SET_MENU_LANGUAGE_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.clock,(cec_string*)arg,sizeof(cec_string)) != 0); ++ TRY(tmdlHdmiCecSetMenuLanguage(this->cec.inst,this->cec.string.data)); ++ break; ++ } ++ ++ case CEC_IOCTL_ENABLE_CALIBRATION_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.clock,(cec_clock*)arg,sizeof(cec_clock)) != 0); ++ TRY(tmdlHdmiCecEnableCalibration(this->cec.inst,this->cec.clock)); ++ break; ++ } ++ ++ /* ++ >1 param ++ */ ++ ++ case CEC_IOCTL_WAIT_FRAME_CMD: ++ { ++ this->cec.frame.service = CEC_WAITING; ++ this->driver.poll_done = false; ++ up(&this->driver.sem); ++ if (wait_event_interruptible(this->driver.wait,this->driver.poll_done)) return -ERESTARTSYS; ++ down(&this->driver.sem); ++ BUG_ON(copy_to_user((cec_frame*)arg,&this->cec.frame,sizeof(cec_frame)) != 0); ++ break; ++ } ++ ++ case CEC_IOCTL_VERSION_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.version,(cec_version*)arg,sizeof(cec_version)) != 0); ++ TRY(tmdlHdmiCecVersion(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.version)); ++ break; ++ } ++ ++ case CEC_IOCTL_CLEAR_ANALOGUE_TIMER_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.analog_timer,(cec_analogue_timer*)arg,sizeof(cec_analogue_timer)) != 0); ++ TRY(tmdlHdmiCecClearAnalogueTimer(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.analog_timer.DayOfMonth, \ ++ this->cec.analog_timer.MonthOfYear, \ ++ this->cec.analog_timer.StartTime, \ ++ &this->cec.analog_timer.Duration, \ ++ this->cec.analog_timer.RecordingSequence, \ ++ this->cec.analog_timer.AnalogueBroadcastType, \ ++ this->cec.analog_timer.AnalogueFrequency, \ ++ this->cec.analog_timer.BroadcastSystem)); ++ break; ++ } ++ ++ case CEC_IOCTL_CLEAR_DIGITAL_TIMER_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.digital_timer,(cec_digital_timer*)arg,sizeof(cec_digital_timer)) != 0); ++ TRY(tmdlHdmiCecClearDigitalTimer(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.digital_timer.DayOfMonth, \ ++ this->cec.digital_timer.MonthOfYear, \ ++ this->cec.digital_timer.StartTime, \ ++ &this->cec.digital_timer.Duration, \ ++ this->cec.digital_timer.RecordingSequence, \ ++ &this->cec.digital_timer.ServiceIdentification)); ++ break; ++ } ++ ++ case CEC_IOCTL_CLEAR_EXT_TIMER_WITH_EXT_PLUG_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.etwep,(cec_ext_timer_with_ext_plug*)arg,sizeof(cec_ext_timer_with_ext_plug)) != 0); ++ TRY(tmdlHdmiCecClearExternalTimerWithExternalPlug(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.etwep.DayOfMonth, \ ++ this->cec.etwep.MonthOfYear, \ ++ this->cec.etwep.StartTime, \ ++ &this->cec.etwep.Duration, \ ++ this->cec.etwep.RecordingSequence, \ ++ this->cec.etwep.ExternalPlug)); ++ break; ++ } ++ ++ case CEC_IOCTL_CLEAR_EXT_TIMER_WITH_PHY_ADDR_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.etwpa,(cec_ext_timer_with_phy_addr*)arg,sizeof(cec_ext_timer_with_phy_addr)) != 0); ++ TRY(tmdlHdmiCecClearExternalTimerWithPhysicalAddress(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.etwpa.DayOfMonth, \ ++ this->cec.etwpa.MonthOfYear, \ ++ this->cec.etwpa.StartTime, \ ++ &this->cec.etwpa.Duration, \ ++ this->cec.etwpa.RecordingSequence, \ ++ this->cec.etwpa.ExternalPhysicalAddress)); ++ break; ++ } ++ ++ case CEC_IOCTL_DECK_CTRL_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.deck_ctrl,(cec_deck_ctrl*)arg,sizeof(cec_deck_ctrl)) != 0); ++ TRY(tmdlHdmiCecDeckControl(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.deck_ctrl)); ++ break; ++ } ++ ++ case CEC_IOCTL_DECK_STATUS_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.deck_status,(cec_deck_status*)arg,sizeof(cec_deck_status)) != 0); ++ TRY(tmdlHdmiCecDeckStatus(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.deck_status)); ++ break; ++ } ++ ++ case CEC_IOCTL_DEVICE_VENDOR_ID_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.vendor_id,(unsigned long*)arg,sizeof(unsigned long)) != 0); ++ TRY(tmdlHdmiCecDeviceVendorID(this->cec.inst, \ ++ this->cec.vendor_id)); ++ break; ++ } ++ ++ case CEC_IOCTL_FEATURE_ABORT_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.feature_abort,(cec_feature_abort*)arg,sizeof(cec_feature_abort)) != 0); ++ TRY(tmdlHdmiCecFeatureAbort(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.feature_abort.FeatureOpcode, \ ++ this->cec.feature_abort.AbortReason)); ++ break; ++ } ++ ++ case CEC_IOCTL_GIVE_DECK_STATUS_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.satus_request,(cec_status_request*)arg,sizeof(cec_status_request)) != 0); ++ TRY(tmdlHdmiCecGiveDeckStatus(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.satus_request)); ++ break; ++ } ++ ++ case CEC_IOCTL_GIVE_TUNER_DEVICE_STATUS_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.satus_request,(cec_status_request*)arg,sizeof(cec_status_request*)) != 0); ++ TRY(tmdlHdmiCecGiveTunerDeviceStatus(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.satus_request)); ++ break; ++ } ++ ++ case CEC_IOCTL_INACTIVE_SRC_CMD: ++ { ++ /* NEW first stand by video */ ++ /* NEW when hdmi_disable and was active */ ++ TRY(tmdlHdmiCecInactiveSource(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.phy_addr)); ++ break; ++ } ++ ++ case CEC_IOCTL_MENU_REQUEST_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.menu_request,(cec_menu_request*)arg,sizeof(cec_menu_request)) != 0); ++ TRY(tmdlHdmiCecMenuRequest(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.menu_request)); ++ break; ++ } ++ ++ case CEC_IOCTL_MENU_STATUS_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.menu_status,(cec_menu_status*)arg,sizeof(cec_menu_status)) != 0); ++ TRY(tmdlHdmiCecMenuStatus(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.menu_status)); ++ break; ++ } ++ ++ case CEC_IOCTL_PLAY_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.play,(cec_play*)arg,sizeof(cec_play)) != 0); ++ TRY(tmdlHdmiCecPlay(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.play)); ++ break; ++ } ++ ++ case CEC_IOCTL_REC_ON_ANALOGUE_SERVICE_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.analog_service,(cec_analogue_service*)arg,sizeof(cec_analogue_service)) != 0); ++ TRY(tmdlHdmiCecRecordOnAnalogueService(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.analog_service.AnalogueBroadcastType, \ ++ this->cec.analog_service.AnalogueFrequency, \ ++ this->cec.analog_service.BroadcastSystem)); ++ break; ++ } ++ ++ case CEC_IOCTL_REC_ON_DIGITAL_SERVICE_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.digital_service,(cec_digital_service*)arg,sizeof(cec_digital_service)) != 0); ++ TRY(tmdlHdmiCecRecordOnDigitalService(this->cec.inst, \ ++ this->cec.initiator, \ ++ &this->cec.digital_service)); ++ break; ++ } ++ ++ case CEC_IOCTL_REC_ON_EXT_PHY_ADDR_CMD: ++ { ++ TRY(tmdlHdmiCecRecordOnExternalPhysicalAddress(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.phy_addr)); ++ break; ++ } ++ ++ case CEC_IOCTL_REC_ON_EXT_PLUG_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.ext_plug,(cec_ext_plug*)arg,sizeof(cec_ext_plug)) != 0); ++ TRY(tmdlHdmiCecRecordOnExternalPlug(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.ext_plug)); ++ break; ++ } ++ ++ case CEC_IOCTL_REC_STATUS_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.rec_status,(cec_rec_status*)arg,sizeof(cec_rec_status)) != 0); ++ TRY(tmdlHdmiCecRecordStatus(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.rec_status)); ++ break; ++ } ++ ++ case CEC_IOCTL_REPORT_AUDIO_STATUS_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.audio_status,(cec_audio_status*)arg,sizeof(cec_audio_status)) != 0); ++ TRY(tmdlHdmiCecReportAudioStatus(this->cec.inst, \ ++ this->cec.initiator, \ ++ &this->cec.audio_status)); ++ break; ++ } ++ ++ case CEC_IOCTL_REPORT_PHY_ADDR_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.device_type,(cec_device_type*)arg,sizeof(cec_device_type)) != 0); ++ TRY(tmdlHdmiCecReportPhysicalAddress(this->cec.inst, \ ++ this->cec.phy_addr, \ ++ this->cec.device_type)); ++ break; ++ } ++ ++ case CEC_IOCTL_REPORT_POWER_STATUS_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.source_status,(cec_power_status*)arg,sizeof(cec_power_status)) != 0); ++ TRY(tmdlHdmiCecReportPowerStatus(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.source_status)); ++ break; ++ } ++ ++ case CEC_IOCTL_SELECT_ANALOGUE_SERVICE_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.analog_service,(cec_analogue_service*)arg,sizeof(cec_analogue_service)) != 0); ++ TRY(tmdlHdmiCecSelectAnalogueService(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.analog_service.AnalogueBroadcastType, \ ++ this->cec.analog_service.AnalogueFrequency, \ ++ this->cec.analog_service.BroadcastSystem)); ++ break; ++ } ++ ++ case CEC_IOCTL_SELECT_DIGITAL_SERVICE_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.digital_service,(cec_digital_service*)arg,sizeof(cec_digital_service)) != 0); ++ TRY(tmdlHdmiCecSelectDigitalService(this->cec.inst, \ ++ this->cec.initiator, \ ++ &this->cec.digital_service)); ++ break; ++ } ++ ++ case CEC_IOCTL_SET_ANALOGUE_TIMER_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.analog_timer,(cec_analogue_timer*)arg,sizeof(cec_analogue_timer)) != 0); ++ TRY(tmdlHdmiCecSetAnalogueTimer(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.analog_timer.DayOfMonth, \ ++ this->cec.analog_timer.MonthOfYear, \ ++ this->cec.analog_timer.StartTime, \ ++ &this->cec.analog_timer.Duration, \ ++ this->cec.analog_timer.RecordingSequence, \ ++ this->cec.analog_timer.AnalogueBroadcastType, \ ++ this->cec.analog_timer.AnalogueFrequency, \ ++ this->cec.analog_timer.BroadcastSystem)); ++ break; ++ } ++ ++ case CEC_IOCTL_SET_AUDIO_RATE_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.audio_rate,(cec_audio_rate*)arg,sizeof(cec_audio_rate)) != 0); ++ TRY(tmdlHdmiCecSetAudioRate(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.audio_rate)); ++ break; ++ } ++ ++ case CEC_IOCTL_SET_DIGITAL_TIMER_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.digital_timer,(cec_digital_timer*)arg,sizeof(cec_digital_timer)) != 0); ++ TRY(tmdlHdmiCecSetDigitalTimer(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.digital_timer.DayOfMonth, \ ++ this->cec.digital_timer.MonthOfYear, \ ++ this->cec.digital_timer.StartTime, \ ++ &this->cec.digital_timer.Duration, \ ++ this->cec.digital_timer.RecordingSequence, \ ++ &this->cec.digital_timer.ServiceIdentification)); ++ break; ++ } ++ ++ case CEC_IOCTL_SET_EXT_TIMER_WITH_EXT_PLUG_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.etwep,(cec_ext_timer_with_ext_plug*)arg,sizeof(cec_ext_timer_with_ext_plug)) != 0); ++ TRY(tmdlHdmiCecSetExternalTimerWithExternalPlug(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.etwep.DayOfMonth, \ ++ this->cec.etwep.MonthOfYear, \ ++ this->cec.etwep.StartTime, \ ++ &this->cec.etwep.Duration, \ ++ this->cec.etwep.RecordingSequence, \ ++ this->cec.etwep.ExternalPlug)); ++ break; ++ } ++ ++ case CEC_IOCTL_SET_EXT_TIMER_WITH_PHY_ADDR_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.etwpa,(cec_ext_timer_with_phy_addr*)arg,sizeof(cec_ext_timer_with_phy_addr)) != 0); ++ TRY(tmdlHdmiCecSetExternalTimerWithPhysicalAddress(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.etwpa.DayOfMonth, \ ++ this->cec.etwpa.MonthOfYear, \ ++ this->cec.etwpa.StartTime, \ ++ &this->cec.etwpa.Duration, \ ++ this->cec.etwpa.RecordingSequence, \ ++ this->cec.etwpa.ExternalPhysicalAddress)); ++ break; ++ } ++ ++ case CEC_IOCTL_SET_SYS_AUDIO_MODE_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.sys_audio_status,(cec_sys_audio_status*)arg,sizeof(cec_sys_audio_status)) != 0); ++ TRY(tmdlHdmiCecSetSystemAudioMode(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.sys_audio_status)); ++ break; ++ } ++ ++ case CEC_IOCTL_SYS_AUDIO_MODE_STATUS_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.sys_audio_status,(cec_sys_audio_status*)arg,sizeof(cec_sys_audio_status)) != 0); ++ TRY(tmdlHdmiCecSystemAudioModeStatus(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.sys_audio_status)); ++ break; ++ } ++ ++ case CEC_IOCTL_TIMER_CLEARED_STATUS_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.timer_cleared_status,(cec_timer_cleared_status*)arg,sizeof(cec_timer_cleared_status)) != 0); ++ TRY(tmdlHdmiCecTimerClearedStatus(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.timer_cleared_status)); ++ break; ++ } ++ ++ case CEC_IOCTL_TIMER_STATUS_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.timer_status,(cec_timer_status*)arg,sizeof(cec_timer_status)) != 0); ++ TRY(tmdlHdmiCecTimerStatus(this->cec.inst, \ ++ this->cec.initiator, \ ++ &this->cec.timer_status)); ++ break; ++ } ++ ++ case CEC_IOCTL_TUNER_DEVICE_STATUS_ANALOGUE_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.tdsa,(cec_tuner_device_status_analogue*)arg,sizeof(cec_tuner_device_status_analogue)) != 0); ++ TRY(tmdlHdmiCecTunerDeviceStatusAnalogue(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.tdsa.RecordingFlag, \ ++ this->cec.tdsa.TunerDisplayInfo, \ ++ this->cec.tdsa.AnalogueBroadcastType, \ ++ this->cec.tdsa.AnalogueFrequency, \ ++ this->cec.tdsa.BroadcastSystem)); ++ break; ++ } ++ ++ case CEC_IOCTL_TUNER_DEVICE_STATUS_DIGITAL_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.tdsd,(cec_tuner_device_status_digital*)arg,sizeof(cec_tuner_device_status_digital)) != 0); ++ TRY(tmdlHdmiCecTunerDeviceStatusDigital(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.tdsd.RecordingFlag, \ ++ this->cec.tdsd.TunerDisplayInfo, \ ++ &this->cec.tdsd.ServiceIdentification)); ++ break; ++ } ++ ++ case CEC_IOCTL_USER_CTRL_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.user_ctrl,(cec_user_ctrl*)arg,sizeof(cec_user_ctrl)) != 0); ++ TRY(tmdlHdmiCecUserControlPressed(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.user_ctrl)); ++ break; ++ } ++ ++ case CEC_IOCTL_USER_CTRL_PLAY_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.play,(cec_play*)arg,sizeof(cec_play)) != 0); ++ TRY(tmdlHdmiCecUserControlPressedPlay(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.play)); ++ break; ++ } ++ ++ case CEC_IOCTL_USER_CTRL_SELECT_AUDIOINPUT_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.select,(unsigned char*)arg,sizeof(unsigned char)) != 0); ++ TRY(tmdlHdmiCecUserControlPressedSelectAudioInput(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.select)); ++ break; ++ } ++ ++ case CEC_IOCTL_USER_CTRL_SELECT_AVINPUT_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.select,(unsigned char*)arg,sizeof(unsigned char)) != 0); ++ TRY(tmdlHdmiCecUserControlPressedSelectAVInput(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.select)); ++ break; ++ } ++ ++ case CEC_IOCTL_USER_CTRL_SELECT_MEDIA_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.select,(unsigned char*)arg,sizeof(unsigned char)) != 0); ++ TRY(tmdlHdmiCecUserControlPressedSelectMedia(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.select)); ++ break; ++ } ++ ++ case CEC_IOCTL_USER_CTRL_TUNE_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.user_ctrl_tune,(cec_user_ctrl_tune*)arg,sizeof(cec_user_ctrl_tune)) != 0); ++ TRY(tmdlHdmiCecUserControlPressedTune(this->cec.inst, \ ++ this->cec.initiator, \ ++ &this->cec.user_ctrl_tune)); ++ break; ++ } ++ ++ case CEC_IOCTL_SET_OSD_NAME_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.osd_name,(cec_string*)arg,sizeof(cec_string)) != 0); ++ TRY(tmdlHdmiCecSetOsdName(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.osd_name.data, \ ++ this->cec.osd_name.length)); ++ break; ++ } ++ ++ case CEC_IOCTL_SET_OSD_STRING_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.osd_string,(cec_osd_string*)arg,sizeof(cec_osd_string)) != 0); ++ TRY(tmdlHdmiCecSetOsdString(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.osd_string.DisplayControl, \ ++ this->cec.osd_string.data, \ ++ this->cec.osd_string.length)); ++ break; ++ } ++ ++ case CEC_IOCTL_SET_TIMER_PROGRAM_TITLE_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.string,(cec_string*)arg,sizeof(cec_string)) != 0); ++ TRY(tmdlHdmiCecSetTimerProgramTitle(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.string.data, \ ++ this->cec.string.length)); ++ break; ++ } ++ ++ case CEC_IOCTL_VENDOR_COMMAND_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.string,(cec_string*)arg,sizeof(cec_string)) != 0); ++ TRY(tmdlHdmiCecVendorCommand(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.string.data, \ ++ this->cec.string.length)); ++ break; ++ } ++ ++ case CEC_IOCTL_VENDOR_REMOTE_BUTTON_DOWN_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.string,(cec_string*)arg,sizeof(cec_string)) != 0); ++ TRY(tmdlHdmiCecVendorRemoteButtonDown(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.string.data, \ ++ this->cec.string.length)); ++ break; ++ } ++ ++ case CEC_IOCTL_VENDOR_COMMAND_WITH_ID_CMD: ++ { ++ BUG_ON(copy_from_user(&this->cec.vcwi,(cec_vendor_command_with_id*)arg,sizeof(cec_vendor_command_with_id)) != 0); ++ TRY(tmdlHdmiCecVendorCommandWithID(this->cec.inst, \ ++ this->cec.initiator, \ ++ this->cec.vcwi.VendorID, \ ++ this->cec.vcwi.cmd.data, \ ++ this->cec.vcwi.cmd.length)); ++ break; ++ } ++ ++ /* case : */ ++ /* { */ ++ /* BUG_ON(copy_from_user(&this->cec.,(*)arg,sizeof()) != 0); */ ++ /* TRY((this->cec.inst, \ */ ++ /* this->cec., \ */ ++ /* &this->cec.)); */ ++ /* break; */ ++ /* } */ ++ ++ default: ++ { ++ /* unrecognized ioctl */ ++ printk(KERN_INFO " unknown ioctl %x\n",cmd); ++ up(&this->driver.sem); ++ return -ENOIOCTLCMD; ++ } ++ } ++ ++ TRY_DONE: ++ up(&this->driver.sem); ++ return err; ++} ++ ++/* ++ * ioctl driver :: releasing ++ */ ++static int this_cdev_release(struct inode *pInode, struct file *pFile) ++{ ++ cec_instance* this = pFile->private_data; ++ int minor = iminor(pInode); ++ ++ LOG(KERN_INFO,"called\n"); ++ ++ if(minor >= MAX_MINOR) { ++ return -EINVAL; ++ } ++ ++ BUG_ON(this->driver.minor!=iminor(pInode)); ++ down(&this->driver.sem); ++ ++ this->driver.user_counter--; ++ if(this->driver.user_counter == 0) { ++ pFile->private_data = NULL; ++ } ++ else { ++ LOG(KERN_INFO,"Still %d user pending\n",this->driver.user_counter); ++ } ++ ++ up(&this->driver.sem); ++ return 0; ++} ++ ++/* ++ * I2C client :: creation ++ */ ++static int __devinit this_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) ++{ ++ cec_instance *this=&our_instance; ++ int err=0; ++ ++ LOG(KERN_INFO,"called\n"); ++ ++ /* ++ I2C setup ++ */ ++ if (this->driver.i2c_client) { ++ dev_err(&this->driver.i2c_client->dev, "<%s> CEC Device already created \n", ++ __func__); ++ return -ENODEV; ++ } ++ ++ this->driver.i2c_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); ++ if (!this->driver.i2c_client) { ++ return -ENOMEM; ++ } ++ memset(this->driver.i2c_client, 0, sizeof(struct i2c_client)); ++ ++ strncpy(this->driver.i2c_client->name, CEC_NAME, I2C_NAME_SIZE); ++ this->driver.i2c_client->addr = TDA99XCEC_I2C_SLAVEADDRESS; ++ this->driver.i2c_client->adapter = client->adapter; ++ ++ i2c_set_clientdata(client, this->driver.i2c_client); ++ ++ tmdlHdmiCecGetSWVersion(&this->cec.sw_version); ++ LOG(KERN_INFO,"HDMI CEC SW Version:%lu.%lu compatibility:%lu\n", \ ++ this->cec.sw_version.majorVersionNr,\ ++ this->cec.sw_version.minorVersionNr,\ ++ this->cec.sw_version.compatibilityNr); ++ ++ /* I2C ok, then let's startup CEC */ ++ ++ /* prepare event */ ++ this->driver.poll_done = true; /* currently idle */ ++ init_waitqueue_head(&this->driver.wait); ++#ifndef IRQ ++ init_timer(&this->driver.timer); /* do it before request_irq */ ++ this->driver.timer.function=polling_timeout; ++ this->driver.timer.data=0; ++ this->driver.timer.expires = jiffies + HZ; /* start polling in one sec */ ++ add_timer(&this->driver.timer); ++#else ++ register_cec_interrupt((cec_callback_t)cec_interrupt); ++#endif ++ ++#ifndef IRQ ++ /* FRO calibration */ ++ err=gpio_request(TDA_IRQ_CALIB,"tda19989 calibration"); ++ if (err < 0) { ++ printk(KERN_ERR "hdmicec:%s:cannot use GPIO 107\n",__func__); ++ goto i2c_out; ++ } ++ /* turn GPIO into IRQ ++ gpio_direction_input(TDA_IRQ_CALIB); ++ msleep(1); ++ if (request_irq(gpio_to_irq(TDA_IRQ_CALIB), \ ++ tda_irq, IRQF_TRIGGER_FALLING|IRQF_DISABLED, "TDA IRQ", NULL)) { ++ printk(KERN_ERR "hdmicec:%s:Cannot request irq, err:%d\n",__func__,err); ++ gpio_free(TDA_IRQ_CALIB); ++ goto i2c_out; ++ } ++ */ ++#endif ++ ++ err = hdmi_cec_init(this); ++ if (err) goto i2c_out; ++ this->cec.rx_addr=CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST; ++ ++ if (get_hpd_status()) { ++ cec_on(this); ++ // disable_irq(gpio_to_irq(TDA_IRQ_CALIB)); ++ cec_interrupt(NULL); /* initiate polling */ ++ // enable_irq(gpio_to_irq(TDA_IRQ_CALIB)); ++ } ++ else { ++ cec_standby(this); ++ } ++ ++ return 0; ++ ++ i2c_out: ++ LOG(KERN_INFO,"HDMICEC eject: this->driver.i2c_client removed\n"); ++ tmdlHdmiCecClose(this->cec.inst); ++ kfree(this->driver.i2c_client); ++ this->driver.i2c_client = NULL; ++ ++ return err; ++} ++ ++/* ++ * I2C client :: destroy ++ */ ++static int this_i2c_remove(struct i2c_client *client) ++{ ++ cec_instance *this=&our_instance; ++ int err=0; ++ ++ LOG(KERN_INFO,"called\n"); ++ ++ err=tmdlHdmiCecClose(this->cec.inst); ++ ++ if (!client->adapter) { ++ dev_err(&this->driver.i2c_client->dev, "<%s> No CEC Device \n", ++ __func__); ++ return -ENODEV; ++ } ++ kfree(this->driver.i2c_client); ++ this->driver.i2c_client = NULL; ++ ++ return err; ++} ++ ++/* ++ * I2C client driver (backend) ++ * ----------------- ++ */ ++static struct i2c_driver this_i2c_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = CEC_NAME, ++ }, ++ .probe = this_i2c_probe, ++ .remove = this_i2c_remove, ++ .id_table = this_i2c_id, ++}; ++ ++/* ++ * ioctl driver (userland frontend) ++ * ------------ ++ */ ++static struct file_operations this_cdev_fops = { ++ owner: THIS_MODULE, ++ open: this_cdev_open, ++ release: this_cdev_release, ++// ioctl: this_cdev_ioctl, ++}; ++ ++/* ++ * Module :: start up ++ */ ++static int __init cec_init(void) ++{ ++ cec_instance *this=&our_instance; ++ dev_t dev=0; ++ int err=0; ++ ++ /* ++ general device context ++ */ ++ memset(this,0,sizeof(cec_instance)); ++ this->param.verbose = param_verbose; ++ this->param.major = param_major; ++ this->param.minor = param_minor; ++ ++ /* Hello word */ ++ printk(KERN_INFO "%s(%s) %d.%d.%d compiled: %s %s %s\n", HDMICEC_NAME, TDA_NAME, TDA_VERSION_MAJOR, ++ TDA_VERSION_MINOR, TDA_VERSION_PATCHLEVEL, __DATE__, __TIME__, TDA_VERSION_EXTRA); ++ if (this->param.verbose) LOG(KERN_INFO,".verbose mode\n"); ++ ++ /* ++ plug I2C (backend : Hw interfacing) ++ */ ++ err = i2c_add_driver(&this_i2c_driver); ++ if (err < 0) { ++ printk(KERN_ERR "Driver registration failed\n"); ++ return -ENODEV; ++ } ++ ++ if (this->driver.i2c_client == NULL) { ++ printk(KERN_ERR "this->driver.i2c_client not allocated\n"); ++ err = -ENODEV; ++ goto init_out; ++ } ++ ++ /* ++ cdev init (userland frontend) ++ */ ++ ++ /* arbitray range of device numbers */ ++ if (this->param.major) { ++ /* user force major number @ insmod */ ++ dev = MKDEV(this->param.major, this->param.minor); ++ err = register_chrdev_region(dev,MAX_MINOR,HDMICEC_NAME); ++ if (err) { ++ printk(KERN_ERR "unable to register %s, dev=%d %s\n",HDMICEC_NAME,dev,ERR_TO_STR(err)); ++ goto init_out; ++ } ++ } else { ++ /* fully dynamic major number */ ++ err = alloc_chrdev_region(&dev, this->param.minor, MAX_MINOR,HDMICEC_NAME); ++ if (err) { ++ printk(KERN_ERR "unable to alloc chrdev region for %s, dev=%d %s\n",HDMICEC_NAME,dev,ERR_TO_STR(err)); ++ goto init_out; ++ } ++ this->param.major = MAJOR(dev); ++ } ++ ++ cdev_init(this_cdev, &this_cdev_fops); ++ this_cdev->owner = THIS_MODULE; ++ ++ this->driver.class = class_create(THIS_MODULE, HDMICEC_NAME); ++ if (IS_ERR(this->driver.class)) { ++ printk(KERN_INFO "Error creating mmap device class.\n"); ++ err =-EIO; ++ goto init_out; ++ } ++ this->driver.dev = device_create(this->driver.class, NULL, dev, NULL, HDMICEC_NAME); ++ ++ this->driver.devno = dev; ++ err = cdev_add(this_cdev, this->driver.devno, MAX_MINOR); ++ if (err){ ++ printk(KERN_INFO "unable to add device for %s, ipp_driver.devno=%d %s\n",HDMICEC_NAME,this->driver.devno,ERR_TO_STR(err)); ++ device_destroy(this->driver.class,this->driver.devno); ++ class_destroy(this->driver.class); ++ unregister_chrdev_region(this->driver.devno, MAX_MINOR); ++ goto init_out; ++ } ++ ++#ifdef TWL4030_HACK ++ /* AL : hack to bypass keypad */ ++ gkp_input = get_twm4030_input(); ++#endif ++ ++ /* ++ general device context ++ */ ++ sema_init(&this->driver.sem, 1); ++ this->driver.deinit_req=0; ++ ++ return 0; ++ ++ init_out: ++ i2c_del_driver(&this_i2c_driver); ++ return err; ++} ++ ++/* ++ * Module :: shut down ++ */ ++static void __exit cec_exit(void) ++{ ++ cec_instance *this=&our_instance; ++ ++ LOG(KERN_INFO,"called\n"); ++ ++#ifndef IRQ ++ // free_irq(gpio_to_irq(TDA_IRQ_CALIB), NULL); ++#endif ++ ++ unregister_cec_interrupt(); ++ this->driver.deinit_req=1; ++#ifndef IRQ ++ if (wait_event_interruptible(this->driver.wait,this->driver.deinit_req>1)) { ++ /* oups... just wait... */ ++ msleep(CHECK_EVERY_XX_MS*20); ++ } ++#endif ++ ++#ifndef IRQ ++ /* release GPIO */ ++ gpio_free(TDA_IRQ_CALIB); ++#endif ++ ++ /* unregister cdevice */ ++ cdev_del(this_cdev); ++ unregister_chrdev_region(this->driver.devno, MAX_MINOR); ++ ++ /* unregister device */ ++ device_destroy(this->driver.class,this->driver.devno); ++ class_destroy(this->driver.class); ++ ++ /* unregister i2c */ ++ i2c_del_driver(&this_i2c_driver); ++ ++} ++ ++ ++/* ++ * Module ++ * ------ ++ */ ++/* late_initcall(cec_init); */ ++module_init(cec_init); ++module_exit(cec_exit); ++ ++/* ++ * Disclamer ++ * --------- ++ */ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Andre Lepine "); ++MODULE_DESCRIPTION(HDMICEC_NAME " driver"); ++ +diff --git a/drivers/video/nxp/tda998x_cec.h b/drivers/video/nxp/tda998x_cec.h +new file mode 100755 +index 0000000..fcc3cfa +--- /dev/null ++++ b/drivers/video/nxp/tda998x_cec.h +@@ -0,0 +1,140 @@ ++/*****************************************************************************/ ++/* Copyright (c) 2009 NXP Semiconductors BV */ ++/* */ ++/* This program is free software; you can redistribute it and/or modify */ ++/* it under the terms of the GNU General Public License as published by */ ++/* the Free Software Foundation, using version 2 of the License. */ ++/* */ ++/* This program is distributed in the hope that it will be useful, */ ++/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ ++/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ ++/* GNU General Public License for more details. */ ++/* */ ++/* You should have received a copy of the GNU General Public License */ ++/* along with this program; if not, write to the Free Software */ ++/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */ ++/* USA. */ ++/* */ ++/*****************************************************************************/ ++ ++#ifndef __cec_h__ ++#define __cec_h__ ++ ++#include "tda998x_ioctl.h" ++ ++#define HDMICEC_NAME "hdmicec" ++ ++#define CEC_MAJOR 234 /* old-style interval of device numbers */ ++#define MAX_MINOR 1 /* 1 minor but 2 access : 1 more for pooling */ ++ ++/* common I2C define with kernel */ ++/* should be the same as arch/arm/mach-omap2/board-zoom2.c */ ++#define CEC_NAME "tda99Xcec" ++#define TDA99XCEC_I2C_SLAVEADDRESS 0x34 ++ ++#define TDA_IRQ_CALIB 107 ++#define POLLING_LENGTH 3 ++ ++#define EDID_BLOCK_COUNT 4 ++#define EDID_BLOCK_SIZE 128 ++ ++#ifdef GPL ++#define CHECK_EVERY_XX_MS 500 /* ms */ ++#else ++#define CHECK_EVERY_XX_MS 10 /* ms */ ++#endif ++ ++#define LOG(type,fmt,args...) {if (this->param.verbose) {printk(type HDMICEC_NAME":%s:" fmt, __func__, ## args);}} ++/* not found the kernel "strerror" one! If someone knows, please replace it */ ++#define ERR_TO_STR(e)((e == -ENODATA)?"ENODATA, no data available":\ ++ (e == -ENOMEM)? "ENOMEM, no memory available":\ ++ (e == -EINVAL)? "EINVAL, invalid argument":\ ++ (e == -EIO)? "EIO, input/output error":\ ++ (e == -ETIMEDOUT)? "ETIMEOUT, timeout has expired":\ ++ (e == -EBUSY)? "EBUSY, device or resource busy":\ ++ (e == -ENOENT)? "ENOENT, no such file or directory":\ ++ (e == -EACCES)? "EACCES, permission denied":\ ++ (e == 0)? "":\ ++ "!UNKNOWN!") ++ ++#define TRY(fct) { \ ++ err=(fct); \ ++ if (err) { \ ++ printk(KERN_ERR "%s? in %s line %d\n",hdmi_cec_err_string(err),__func__,__LINE__); \ ++ goto TRY_DONE; \ ++ } \ ++ } ++ ++typedef void (*cec_callback_t) (struct work_struct *dummy); ++ ++typedef struct { ++ /* module params */ ++ struct { ++ int verbose; ++ int major; ++ int minor; ++ } param; ++ /* driver */ ++ struct { ++ struct class *class; ++ struct device *dev; ++ int devno; ++ struct i2c_client *i2c_client; ++ struct semaphore sem; ++ int user_counter; ++ int minor; ++ wait_queue_head_t wait; ++ bool poll_done; ++ int deinit_req; ++ struct timer_list timer; ++ } driver; ++ /* cec */ ++ struct { ++ int inst; ++ unsigned char rx_addr; ++ unsigned short phy_addr; ++ unsigned char initiator; ++ cec_version version; ++ cec_sw_version sw_version; ++ cec_power power; ++ cec_setup setup; ++ cec_clock clock; ++ cec_analogue_timer analog_timer; ++ cec_digital_timer digital_timer; ++ cec_ext_timer_with_ext_plug etwep; ++ cec_ext_timer_with_phy_addr etwpa; ++ cec_deck_ctrl deck_ctrl; ++ cec_deck_status deck_status; ++ unsigned long vendor_id; ++ cec_feature_abort feature_abort; ++ cec_status_request satus_request; ++ cec_menu_request menu_request; ++ cec_menu_status menu_status; ++ cec_play play; ++ cec_analogue_service analog_service; ++ cec_digital_service digital_service; ++ cec_ext_plug ext_plug; ++ cec_rec_status rec_status; ++ cec_audio_status audio_status; ++ cec_device_type device_type; ++ cec_power_status source_status; ++ cec_audio_rate audio_rate; ++ cec_sys_audio_status sys_audio_status; ++ cec_timer_cleared_status timer_cleared_status; ++ cec_timer_status timer_status; ++ cec_tuner_device_status_analogue tdsa; ++ cec_tuner_device_status_digital tdsd; ++ cec_user_ctrl user_ctrl; ++ unsigned char select; ++ cec_user_ctrl_tune user_ctrl_tune; ++ cec_frame frame; ++ bool byebye; ++ cec_string string; ++ cec_string osd_name; ++ cec_osd_string osd_string; ++ cec_vendor_command_with_id vcwi; ++ } cec; ++} cec_instance; ++ ++#endif /* __cec_h__ */ ++ +diff --git a/drivers/video/nxp/tda998x_ioctl.h b/drivers/video/nxp/tda998x_ioctl.h +new file mode 100755 +index 0000000..cd5b0cd +--- /dev/null ++++ b/drivers/video/nxp/tda998x_ioctl.h +@@ -0,0 +1,1123 @@ ++/** ++ * Copyright (C) 2006 NXP N.V., All Rights Reserved. ++ * This source code and any compilation or derivative thereof is the proprietary ++ * information of NXP N.V. and is confidential in nature. Under no circumstances ++ * is this software to be exposed to or placed under an Open Source License of ++ * any type without the expressed written permission of NXP N.V. ++ * ++ * Version Revision: 1.0 ++ * ++ * Date Date: 27/10/09 ++ * ++ * Brief API for the TDA1998x HDMI Transmitters ++ * ++ **/ ++ ++#include ++ ++#ifndef __tx_ioctl__ ++#define __tx_ioctl__ ++ ++#ifdef __tx_h__ ++ ++#define TRANS_TYPE 1 ++ ++#if TRANS_TYPE ++ ++#define EXAMPLE_MAX_SVD 30 ++ ++/* ++ trans-type ++*/ ++typedef tmSWVersion_t tda_version; ++typedef tmPowerState_t tda_power; ++typedef tmdlHdmiTxInstanceSetupInfo_t tda_setup; ++typedef tmdlHdmiTxCapabilities_t tda_capabilities; ++typedef tmdlHdmiTxVideoOutConfig_t tda_video_out; ++typedef tmdlHdmiTxVideoInConfig_t tda_video_in; ++typedef tmdlHdmiTxSinkType_t tda_sink; ++typedef tmdlHdmiTxAudioInConfig_t tda_audio_in; ++typedef tmdlHdmiTxEdidAudioDesc_t tda_edid_audio_desc; ++typedef tmdlHdmiTxShortVidDesc_t tda_edid_video_desc; ++typedef tmdlHdmiTxEvent_t tda_event; ++typedef tmdlHdmiTxInstanceSetupInfo_t tda_setup_info; ++typedef tmdlHdmiTxEdidVideoTimings_t tda_edid_video_timings; ++typedef tmdlHdmiTxPictAspectRatio_t tda_edid_tv_aspect_ratio; ++typedef tmdlHdmiTxHdcpCheck_t tda_hdcp_status; ++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984) ++typedef tmdlHdmiTxHdcpStatus_t tda_hdcp_fail; ++#endif ++#ifdef TMFL_TDA19989 ++typedef tmdlHdmiTxEdidLatency_t tda_edid_latency; ++#endif ++ ++typedef struct { ++ Bool enable; ++ tmdlHdmiTxGamutData_t data; ++} tda_gammut; ++ ++typedef struct { ++ Bool enable; ++ tmdlHdmiTxVsPktData_t data; ++} tda_vs_infoframe; ++ ++typedef struct { ++ Bool enable; ++ tmdlHdmiTxSpdIfData_t data; ++} tda_spd_infoframe; ++ ++typedef struct { ++ Bool enable; ++ tmdlHdmiTxMpsIfData_t data; ++} tda_mps_infoframe; ++ ++typedef struct { ++ Bool enable; ++ tmdlHdmiTxIsrc1PktData_t data; ++} tda_isrc1; ++ ++typedef struct { ++ Bool enable; ++ tmdlHdmiTxIsrc2PktData_t data; ++} tda_isrc2; ++ ++typedef struct { ++ Bool enable; ++ tmdlHdmiTxAcpPktData_t data; ++} tda_acp; ++ ++typedef struct { ++ Bool enable; ++ tmdlHdmiTxGcpPktData_t data; ++} tda_gcp; ++ ++typedef struct { ++ Bool enable; ++ tmdlHdmiTxAviIfData_t data; ++} tda_video_infoframe; ++ ++typedef struct { ++ Bool enable; ++ tmdlHdmiTxAudIfData_t data; ++} tda_audio_infoframe; ++ ++typedef struct { ++ tmdlHdmiTxVidFmt_t id; ++ tmdlHdmiTxVidFmtSpecs_t spec; ++} tda_video_format; ++ ++typedef struct { ++ tda_video_in video_in; ++ tda_video_out video_out; ++ tda_audio_in audio_in; /* Mind tda_set_audio_in if you change this */ ++ tda_sink sink; /* Mind tda_set_audio_in if you change this */ ++} tda_set_in_out; ++ ++typedef struct { ++ tda_audio_in audio_in; ++ tda_sink sink; ++} tda_set_audio_in; ++ ++typedef struct { ++ tda_edid_audio_desc desc[EXAMPLE_MAX_SVD]; ++ unsigned int max; ++ unsigned int written; ++ unsigned char flags; ++} tda_edid_audio_caps; ++ ++typedef struct { ++ tda_edid_video_desc desc[EXAMPLE_MAX_SVD]; ++ unsigned int max; ++ unsigned int written; ++ unsigned char flags; ++} tda_edid_video_caps; ++ ++typedef struct { ++ tmdlHdmiTxEdidStatus_t status; ++ unsigned char block_count; ++} tda_edid; ++ ++typedef struct { ++ tmdlHdmiTxEdidVideoTimings_t desc[EXAMPLE_MAX_SVD]; ++ unsigned char max; ++ unsigned char written; ++} tda_edid_dtd; ++ ++typedef struct { ++ tmdlHdmiTxEdidFirstMD_t desc1[EXAMPLE_MAX_SVD]; ++ tmdlHdmiTxEdidSecondMD_t desc2[EXAMPLE_MAX_SVD]; ++ tmdlHdmiTxEdidOtherMD_t other[EXAMPLE_MAX_SVD]; ++ unsigned char max; ++ unsigned char written; ++} tda_edid_md; ++ ++#else ++ ++#error do not compiled this ! ++ ++typedef enum ++{ ++ TDA_HDCP_ACTIVE = 0, /**< HDCP encryption status switched to active */ ++ TDA_HDCP_INACTIVE = 1, /**< HDCP encryption status switched to inactive */ ++ TDA_HPD_ACTIVE = 2, /**< Hotplug status switched to active */ ++ TDA_HPD_INACTIVE = 3, /**< Hotplug status switched to inactive */ ++ TDA_RX_KEYS_RECEIVED = 4, /**< Receiver(s) key(s) received */ ++ TDA_RX_DEVICE_ACTIVE = 5, /**< Rx device is connected and active */ ++ TDA_RX_DEVICE_INACTIVE = 6, /**< Rx device is connected but inactive (standby) */ ++ TDA_EDID_RECEIVED = 7, /**< EDID has been received */ ++ TDA_VS_RPT_RECEIVED = 8, /**< VS interrupt has been received */ ++#ifdef HDMI_TX_REPEATER_ISR_MODE ++ TDA_B_STATUS = 9, /**< TX received BStatus */ ++#endif /* HDMI_TX_REPEATER_ISR_MODE */ ++ TDA_DEBUG_EVENT_1 = 10 /**< This is a debug event */ ++} tda_event; ++ ++typedef struct { ++ unsigned char format; /* EIA/CEA861 mode */ ++ unsigned char channels; /* number of channels */ ++ unsigned char supportedFreqs; /* bitmask of supported frequencies */ ++ unsigned char supportedRes; /* bitmask of supported resolutions (LPCM only) */ ++ unsigned char maxBitrate; /* Maximum bitrate divided by 8KHz (compressed formats only) */ ++} tda_edid_audio_desc; ++ ++typedef enum { ++ TDA_EDID_READ = 0, /**< All blocks read OK */ ++ TDA_EDID_READ_INCOMPLETE = 1, /**< All blocks read OK but buffer too small to return all of them */ ++ TDA_EDID_ERROR_CHK_BLOCK_0 = 2, /**< Block 0 checksum error */ ++ TDA_EDID_ERROR_CHK = 3, /**< Block 0 OK, checksum error in one or more other blocks */ ++ TDA_EDID_NOT_READ = 4, /**< EDID not read */ ++ TDA_EDID_STATUS_INVALID = 5 /**< Invalid */ ++} tda_edid_status; ++ ++typedef struct { ++ int HBR; /**< High Bitrate Audio packet */ ++ int DST; /**< Direct Stream Transport audio packet */ ++ int oneBitAudio; /**< One Bit Audio sample packet */ ++} tda_audio_packet; ++ ++typedef enum { ++ TDA_AFMT_SPDIF = 0, /**< SPDIF */ ++ TDA_AFMT_I2S = 1, /**< I2S */ ++ TDA_AFMT_OBA = 2, /**< One bit audio / DSD */ ++ TDA_AFMT_DST = 3, /**< DST */ ++ TDA_AFMT_HBR = 4 /**< HBR */ ++} tda_audio_format; ++ ++typedef enum { ++ TDA_AFS_32K = 0, /**< 32kHz */ ++ TDA_AFS_44K = 1, /**< 44.1kHz */ ++ TDA_AFS_48K = 2, /**< 48kHz */ ++ TDA_AFS_88K = 3, /**< 88.2kHz */ ++ TDA_AFS_96K = 4, /**< 96kHz */ ++ TDA_AFS_176K = 5, /**< 176.4kHz */ ++ TDA_AFS_192K = 6 /**< 192kHz */ ++} tda_audio_rate; ++ ++typedef enum { ++ TDA_I2SQ_16BITS = 16, /**< 16 bits */ ++ TDA_I2SQ_32BITS = 32, /**< 32 bits */ ++ TDA_I2SQ_OTHERS = 0 /**< for SPDIF and DSD */ ++} tda_audio_I2S_qualifier; ++ ++typedef enum { ++ TDA_I2SFOR_PHILIPS_L = 0, /**< Philips like format */ ++ TDA_I2SFOR_OTH_L = 2, /**< Other non Philips left justified */ ++ TDA_I2SFOR_OTH_R = 3, /**< Other non Philips right justified */ ++ TDA_I2SFOR_INVALID = 4 /**< Invalid format */ ++} tda_audio_I2S_format; ++ ++typedef enum { ++ TDA_DSTRATE_SINGLE = 0, /**< Single transfer rate */ ++ TDA_DSTRATE_DOUBLE = 1 /**< Double data rate */ ++} tda_dst_rate; ++ ++typedef struct { ++ int simplayHd; /**< Enable simplayHD support */ ++ int repeaterEnable; /**< Enable repeater mode */ ++ unsigned char *pEdidBuffer; /**< Pointer to raw EDID data */ ++ unsigned long edidBufferSize; /**< Size of buffer for raw EDID data */ ++} tda_instance_setup_info; ++ ++typedef enum { ++ TDA_VFMT_NULL = 0, /**< Not a valid format... */ ++ TDA_VFMT_NO_CHANGE = 0, /**< ...or no change required */ ++ TDA_VFMT_MIN = 1, /**< Lowest valid format */ ++ TDA_VFMT_TV_MIN = 1, /**< Lowest valid TV format */ ++ TDA_VFMT_01_640x480p_60Hz = 1, /**< Format 01 640 x 480p 60Hz */ ++ TDA_VFMT_02_720x480p_60Hz = 2, /**< Format 02 720 x 480p 60Hz */ ++ TDA_VFMT_03_720x480p_60Hz = 3, /**< Format 03 720 x 480p 60Hz */ ++ TDA_VFMT_04_1280x720p_60Hz = 4, /**< Format 04 1280 x 720p 60Hz */ ++ TDA_VFMT_05_1920x1080i_60Hz = 5, /**< Format 05 1920 x 1080i 60Hz */ ++ TDA_VFMT_06_720x480i_60Hz = 6, /**< Format 06 720 x 480i 60Hz */ ++ TDA_VFMT_07_720x480i_60Hz = 7, /**< Format 07 720 x 480i 60Hz */ ++ TDA_VFMT_08_720x240p_60Hz = 8, /**< Format 08 720 x 240p 60Hz */ ++ TDA_VFMT_09_720x240p_60Hz = 9, /**< Format 09 720 x 240p 60Hz */ ++ TDA_VFMT_10_720x480i_60Hz = 10, /**< Format 10 720 x 480i 60Hz */ ++ TDA_VFMT_11_720x480i_60Hz = 11, /**< Format 11 720 x 480i 60Hz */ ++ TDA_VFMT_12_720x240p_60Hz = 12, /**< Format 12 720 x 240p 60Hz */ ++ TDA_VFMT_13_720x240p_60Hz = 13, /**< Format 13 720 x 240p 60Hz */ ++ TDA_VFMT_14_1440x480p_60Hz = 14, /**< Format 14 1440 x 480p 60Hz */ ++ TDA_VFMT_15_1440x480p_60Hz = 15, /**< Format 15 1440 x 480p 60Hz */ ++ TDA_VFMT_16_1920x1080p_60Hz = 16, /**< Format 16 1920 x 1080p 60Hz */ ++ TDA_VFMT_17_720x576p_50Hz = 17, /**< Format 17 720 x 576p 50Hz */ ++ TDA_VFMT_18_720x576p_50Hz = 18, /**< Format 18 720 x 576p 50Hz */ ++ TDA_VFMT_19_1280x720p_50Hz = 19, /**< Format 19 1280 x 720p 50Hz */ ++ TDA_VFMT_20_1920x1080i_50Hz = 20, /**< Format 20 1920 x 1080i 50Hz */ ++ TDA_VFMT_21_720x576i_50Hz = 21, /**< Format 21 720 x 576i 50Hz */ ++ TDA_VFMT_22_720x576i_50Hz = 22, /**< Format 22 720 x 576i 50Hz */ ++ TDA_VFMT_23_720x288p_50Hz = 23, /**< Format 23 720 x 288p 50Hz */ ++ TDA_VFMT_24_720x288p_50Hz = 24, /**< Format 24 720 x 288p 50Hz */ ++ TDA_VFMT_25_720x576i_50Hz = 25, /**< Format 25 720 x 576i 50Hz */ ++ TDA_VFMT_26_720x576i_50Hz = 26, /**< Format 26 720 x 576i 50Hz */ ++ TDA_VFMT_27_720x288p_50Hz = 27, /**< Format 27 720 x 288p 50Hz */ ++ TDA_VFMT_28_720x288p_50Hz = 28, /**< Format 28 720 x 288p 50Hz */ ++ TDA_VFMT_29_1440x576p_50Hz = 29, /**< Format 29 1440 x 576p 50Hz */ ++ TDA_VFMT_30_1440x576p_50Hz = 30, /**< Format 30 1440 x 576p 50Hz */ ++ TDA_VFMT_31_1920x1080p_50Hz = 31, /**< Format 31 1920 x 1080p 50Hz */ ++ TDA_VFMT_32_1920x1080p_24Hz = 32, /**< Format 32 1920 x 1080p 24Hz */ ++ TDA_VFMT_33_1920x1080p_25Hz = 33, /**< Format 33 1920 x 1080p 25Hz */ ++ TDA_VFMT_34_1920x1080p_30Hz = 34, /**< Format 34 1920 x 1080p 30Hz */ ++ TDA_VFMT_TV_MAX = 34, /**< Highest valid TV format */ ++ TDA_VFMT_TV_NO_REG_MIN = 32, /**< Lowest TV format without prefetched table */ ++ TDA_VFMT_TV_NUM = 35, /**< Number of TV formats & null */ ++ TDA_VFMT_PC_MIN = 128, /**< Lowest valid PC format */ ++ TDA_VFMT_PC_640x480p_60Hz = 128, /**< PC format 128 */ ++ TDA_VFMT_PC_800x600p_60Hz = 129, /**< PC format 129 */ ++ TDA_VFMT_PC_1152x960p_60Hz = 130, /**< PC format 130 */ ++ TDA_VFMT_PC_1024x768p_60Hz = 131, /**< PC format 131 */ ++ TDA_VFMT_PC_1280x768p_60Hz = 132, /**< PC format 132 */ ++ TDA_VFMT_PC_1280x1024p_60Hz = 133, /**< PC format 133 */ ++ TDA_VFMT_PC_1360x768p_60Hz = 134, /**< PC format 134 */ ++ TDA_VFMT_PC_1400x1050p_60Hz = 135, /**< PC format 135 */ ++ TDA_VFMT_PC_1600x1200p_60Hz = 136, /**< PC format 136 */ ++ TDA_VFMT_PC_1024x768p_70Hz = 137, /**< PC format 137 */ ++ TDA_VFMT_PC_640x480p_72Hz = 138, /**< PC format 138 */ ++ TDA_VFMT_PC_800x600p_72Hz = 139, /**< PC format 139 */ ++ TDA_VFMT_PC_640x480p_75Hz = 140, /**< PC format 140 */ ++ TDA_VFMT_PC_1024x768p_75Hz = 141, /**< PC format 141 */ ++ TDA_VFMT_PC_800x600p_75Hz = 142, /**< PC format 142 */ ++ TDA_VFMT_PC_1024x864p_75Hz = 143, /**< PC format 143 */ ++ TDA_VFMT_PC_1280x1024p_75Hz = 144, /**< PC format 144 */ ++ TDA_VFMT_PC_640x350p_85Hz = 145, /**< PC format 145 */ ++ TDA_VFMT_PC_640x400p_85Hz = 146, /**< PC format 146 */ ++ TDA_VFMT_PC_720x400p_85Hz = 147, /**< PC format 147 */ ++ TDA_VFMT_PC_640x480p_85Hz = 148, /**< PC format 148 */ ++ TDA_VFMT_PC_800x600p_85Hz = 149, /**< PC format 149 */ ++ TDA_VFMT_PC_1024x768p_85Hz = 150, /**< PC format 150 */ ++ TDA_VFMT_PC_1152x864p_85Hz = 151, /**< PC format 151 */ ++ TDA_VFMT_PC_1280x960p_85Hz = 152, /**< PC format 152 */ ++ TDA_VFMT_PC_1280x1024p_85Hz = 153, /**< PC format 153 */ ++ TDA_VFMT_PC_1024x768i_87Hz = 154, /**< PC format 154 */ ++ TDA_VFMT_PC_MAX = 154, /**< Highest valid PC format */ ++ TDA_VFMT_PC_NUM = (1+154-128) /**< Number of PC formats */ ++} tda_video_fmt_id; ++ ++typedef struct { ++ tda_video_fmt_id videoFormat; /**< Video format as defined by EIA/CEA 861-D */ ++ int nativeVideoFormat; /**< True if format is the preferred video format */ ++} tda_edid_video_desc; ++ ++typedef struct { ++ tda_video_fmt_id videoFormat; /**< Video format as defined by EIA/CEA 861-D */ ++ int nativeVideoFormat; /**< True if format is the preferred video format */ ++} tda_short_video_desc; ++ ++typedef enum { ++ TDA_P_ASPECT_RATIO_UNDEFINED = 0, /**< Undefined picture aspect ratio */ ++ TDA_P_ASPECT_RATIO_6_5 = 1, /**< 6:5 picture aspect ratio (PAR) */ ++ TDA_P_ASPECT_RATIO_5_4 = 2, /**< 5:4 PAR */ ++ TDA_P_ASPECT_RATIO_4_3 = 3, /**< 4:3 PAR */ ++ TDA_P_ASPECT_RATIO_16_10 = 4, /**< 16:10 PAR */ ++ TDA_P_ASPECT_RATIO_5_3 = 5, /**< 5:3 PAR */ ++ TDA_P_ASPECT_RATIO_16_9 = 6, /**< 16:9 PAR */ ++ TDA_P_ASPECT_RATIO_9_5 = 7 /**< 9:5 PAR */ ++} tda_pict_aspect_ratio; ++ ++typedef enum { ++ TDA_VFREQ_24Hz = 0, /**< 24Hz */ ++ TDA_VFREQ_25Hz = 1, /**< 25Hz */ ++ TDA_VFREQ_30Hz = 2, /**< 30Hz */ ++ TDA_VFREQ_50Hz = 3, /**< 50Hz */ ++ TDA_VFREQ_59Hz = 4, /**< 59.94Hz */ ++ TDA_VFREQ_60Hz = 5, /**< 60Hz */ ++ TDA_VFREQ_70Hz = 6, /**< 70Hz */ ++ TDA_VFREQ_72Hz = 7, /**< 72Hz */ ++ TDA_VFREQ_75Hz = 8, /**< 75Hz */ ++ TDA_VFREQ_85Hz = 9, /**< 85Hz */ ++ TDA_VFREQ_87Hz = 10, /**< 87Hz */ ++ TDA_VFREQ_INVALID = 11, /**< Invalid */ ++ TDA_VFREQ_NUM = 11 /**< No. of values */ ++} tda_vfreq; ++ ++typedef struct { ++ unsigned short width; /**< Width of the frame in pixels */ ++ unsigned short height; /**< Height of the frame in pixels */ ++ int interlaced; /**< Interlaced mode (True/False) */ ++ tda_vfreq vfrequency; /**< Vertical frequency in Hz */ ++ tda_pict_aspect_ratio aspectRatio; /**< Picture aspect ratio (H:V) */ ++} tda_video_fmt_specs; ++ ++typedef enum { ++ TDA_VINMODE_CCIR656 = 0, /**< CCIR656 */ ++ TDA_VINMODE_RGB444 = 1, /**< RGB444 */ ++ TDA_VINMODE_YUV444 = 2, /**< YUV444 */ ++ TDA_VINMODE_YUV422 = 3, /**< YUV422 */ ++ TDA_VINMODE_NO_CHANGE = 4, /**< No change */ ++ TDA_VINMODE_INVALID = 5 /**< Invalid */ ++} tda_vinmode; ++ ++typedef enum { ++ TDA_SYNCSRC_EMBEDDED = 0, /**< Embedded sync */ ++ TDA_SYNCSRC_EXT_VREF = 1, /**< External sync Vref, Href, Fref */ ++ TDA_SYNCSRC_EXT_VS = 2 /**< External sync Vs, Hs */ ++} tda_sync_source; ++ ++typedef enum { ++ TDA_PIXRATE_DOUBLE = 0, /**< Double pixel rate */ ++ TDA_PIXRATE_SINGLE = 1, /**< Single pixel rate */ ++ TDA_PIXRATE_SINGLE_REPEATED = 2 /**< Single pixel repeated */ ++} tda_pix_rate; ++ ++typedef struct { ++ tda_video_fmt_id format; /**< Video format as defined by EIA/CEA 861-D */ ++ tda_vinmode mode; /**< Video mode (CCIR, RGB, YUV, etc.) */ ++ tda_sync_source syncSource; /**< Sync source type */ ++ tda_pix_rate pixelRate; /**< Pixel rate */ ++} tda_video_in; ++ ++typedef enum { ++ TDA_VOUTMODE_RGB444 = 0, /**< RGB444 */ ++ TDA_VOUTMODE_YUV422 = 1, /**< YUV422 */ ++ TDA_VOUTMODE_YUV444 = 2 /**< YUV444 */ ++} tda_vout_mode; ++ ++typedef enum { ++ TDA_VQR_DEFAULT = 0, /* Follow HDMI spec. */ ++ TDA_RGB_FULL = 1, /* Force RGB FULL , DVI only */ ++ TDA_RGB_LIMITED = 2 /* Force RGB LIMITED , DVI only */ ++} tda_vqr; ++ ++typedef enum { ++ TDA_COLORDEPTH_24 = 0, /**< 8 bits per color */ ++ TDA_COLORDEPTH_30 = 1, /**< 10 bits per color */ ++ TDA_COLORDEPTH_36 = 2, /**< 12 bits per color */ ++ TDA_COLORDEPTH_48 = 3 /**< 16 bits per color */ ++} tda_color_depth; ++ ++typedef struct { ++ tda_video_fmt_id format; /**< Video format as defined by EIA/CEA 861-D */ ++ tda_vout_mode mode; /**< Video mode (CCIR, RGB, YUV, etc.) */ ++ tda_color_depth colorDepth; /**< Color depth */ ++ tda_vqr dviVqr; /**< VQR applied in DVI mode */ ++} tda_video_out; ++ ++typedef struct { ++ tda_audio_format format; /**< Audio format (I2S, SPDIF, etc.) */ ++ tda_audio_rate rate; /**< Audio sampling rate */ ++ tda_audio_I2S_format i2sFormat; /**< I2S format of the audio input */ ++ tda_audio_I2S_qualifier i2sQualifier; /**< I2S qualifier of the audio input (8,16,32 bits) */ ++ tda_dst_rate dstRate; /**< DST data transfer rate */ ++ unsigned char channelAllocation; /**< Ref to CEA-861D p85 */ ++} tda_audio_in; ++ ++typedef enum { ++ TDA_SINK_DVI = 0, /**< DVI */ ++ TDA_SINK_HDMI = 1, /**< HDMI */ ++ TDA_SINK_EDID = 2 /**< As currently defined in EDID */ ++} tda_sink; ++ ++ typedef enum { ++ TDA_DEVICE_UNKNOWN, /**< HW device is unknown */ ++ TDA_DEVICE_TDA9984, /**< HW device is IC TDA9984 */ ++ TDA_DEVICE_TDA9989, /**< HW device is IC TDA9989 */ ++ TDA_DEVICE_TDA9981, /**< HW device is IC TDA9981 */ ++ TDA_DEVICE_TDA9983, /**< HW device is IC TDA9983 */ ++ TDA_DEVICE_TDA19989 /**< HW device is IC TDA19989 */ ++ } tda_device_version; ++ ++typedef enum { ++ TDA_HDMI_VERSION_UNKNOWN, /**< Unknown */ ++ TDA_HDMI_VERSION_1_1, /**< HDMI 1.1 */ ++ TDA_HDMI_VERSION_1_2a, /**< HDMI 1.2a */ ++ TDA_HDMI_VERSION_1_3a /**< HDMI 1.3 */ ++} tda_hdmi_version; ++ ++typedef struct { ++ int HBR; /**< High Bitrate Audio packet */ ++ int DST; /**< Direct Stream Transport audio packet */ ++ int oneBitAudio; /**< One Bit Audio sample packet */ ++} tda_audio_packet; ++ ++typedef enum { ++ TDA_COLORDEPTH_24 = 0, /**< 8 bits per color */ ++ TDA_COLORDEPTH_30 = 1, /**< 10 bits per color */ ++ TDA_COLORDEPTH_36 = 2, /**< 12 bits per color */ ++ TDA_COLORDEPTH_48 = 3 /**< 16 bits per color */ ++} tda_color_depth; ++ ++typedef struct { ++ tda_device_version deviceVersion; /**< HW device version */ ++ tda_hdmi_version hdmiVersion; /**< Supported HDMI standard version */ ++ tda_audio_packet audioPacket; /**< Supported audio packets */ ++ tda_color_depth colorDepth; /**< Supported color depth */ ++ int hdcp; /**< Supported Hdcp encryption (True/False) */ ++ int scaler; /**< Supported scaler (True/False) */ ++} tda_capabilities; ++ ++typedef struct { ++ unsigned long compatibilityNr; // Interface compatibility number ++ unsigned long majorVersionNr; // Interface major version number ++ unsigned long minorVersionNr; // Interface minor version number ++} tda_version; ++ ++typedef enum ++{ ++ PowerOn, // Device powered on (D0 state) ++ PowerStandby, // Device power standby (D1 state) ++ PowerSuspend, // Device power suspended (D2 state) ++ PowerOff // Device powered off (D3 state) ++} tda_powerXXX; ++ ++typedef struct { ++ unsigned int simplayHd; /**< Enable simplayHD support */ ++ unsigned int repeaterEnable; /**< Enable repeater mode */ ++ unsigned char *pEdidBuffer; /**< Pointer to raw EDID data */ ++ unsigned long edidBufferSize; /**< Size of buffer for raw EDID data */ ++} tda_setup; ++ ++typedef struct { ++ tda_video_fmt_id id; ++ tda_video_fmt_specs spec; ++} tda_video_format; ++ ++typedef struct { ++ tda_video_in video_in; ++ tda_video_out video_out; ++ tda_audio_in audio_in; ++} tda_set_in_out; ++ ++typedef struct { ++ tda_edid_audio_desc desc; ++ unsigned int max; ++ unsigned int written; ++ unsigned char flags; ++} tda_edid_audio_caps; ++ ++typedef struct { ++ tda_edid_video_desc desc; ++ unsigned int max; ++ unsigned int written; ++ unsigned char flags; ++} tda_edid_video_caps; ++ ++typedef struct { ++ tda_edid_status status; ++ unsigned char block_count; ++} tda_edid; ++ ++#endif ++ ++#define TDA_IOCTL_BASE 0x40 ++#define RELEASE 0xFF ++ ++enum { ++ /* driver specific */ ++ TDA_VERBOSE_ON_CMD = 0, ++ TDA_VERBOSE_OFF_CMD, ++ TDA_BYEBYE_CMD, ++ /* HDMI Tx */ ++ TDA_GET_SW_VERSION_CMD, ++ TDA_SET_POWER_CMD, ++ TDA_GET_POWER_CMD, ++ TDA_SETUP_CMD, ++ TDA_GET_SETUP_CMD, ++ TDA_WAIT_EVENT_CMD, ++ TDA_ENABLE_EVENT_CMD, ++ TDA_DISABLE_EVENT_CMD, ++ TDA_GET_VIDEO_SPEC_CMD, ++ TDA_SET_INPUT_OUTPUT_CMD, ++ TDA_SET_AUDIO_INPUT_CMD, ++ TDA_SET_VIDEO_INFOFRAME_CMD, ++ TDA_SET_AUDIO_INFOFRAME_CMD, ++ TDA_SET_ACP_CMD, ++ TDA_SET_GCP_CMD, ++ TDA_SET_ISRC1_CMD, ++ TDA_SET_ISRC2_CMD, ++ TDA_SET_MPS_INFOFRAME_CMD, ++ TDA_SET_SPD_INFOFRAME_CMD, ++ TDA_SET_VS_INFOFRAME_CMD, ++ TDA_SET_AUDIO_MUTE_CMD, ++ TDA_RESET_AUDIO_CTS_CMD, ++ TDA_GET_EDID_STATUS_CMD, ++ TDA_GET_EDID_AUDIO_CAPS_CMD, ++ TDA_GET_EDID_VIDEO_CAPS_CMD, ++ TDA_GET_EDID_VIDEO_PREF_CMD, ++ TDA_GET_EDID_SINK_TYPE_CMD, ++ TDA_GET_EDID_SOURCE_ADDRESS_CMD, ++ TDA_SET_GAMMUT_CMD, ++ TDA_GET_EDID_DTD_CMD, ++ TDA_GET_EDID_MD_CMD, ++ TDA_GET_EDID_TV_ASPECT_RATIO_CMD, ++ TDA_GET_EDID_LATENCY_CMD, ++ TDA_SET_HDCP_CMD, ++ TDA_GET_HDCP_STATUS_CMD, ++ TDA_GET_HPD_STATUS_CMD, ++}; ++ ++ ++/* driver specific */ ++#define TDA_IOCTL_VERBOSE_ON _IO(TDA_IOCTL_BASE, TDA_VERBOSE_ON_CMD) ++#define TDA_IOCTL_VERBOSE_OFF _IO(TDA_IOCTL_BASE, TDA_VERBOSE_OFF_CMD) ++#define TDA_IOCTL_BYEBYE _IO(TDA_IOCTL_BASE, TDA_BYEBYE_CMD) ++/* HDMI Tx */ ++#define TDA_IOCTL_GET_SW_VERSION _IOWR(TDA_IOCTL_BASE, TDA_GET_SW_VERSION_CMD,tda_version) ++#define TDA_IOCTL_SET_POWER _IOWR(TDA_IOCTL_BASE, TDA_SET_POWER_CMD,tda_power) ++#define TDA_IOCTL_GET_POWER _IOWR(TDA_IOCTL_BASE, TDA_GET_POWER_CMD,tda_power) ++#define TDA_IOCTL_SETUP _IOWR(TDA_IOCTL_BASE, TDA_SETUP_CMD,tda_setup_info) ++#define TDA_IOCTL_GET_SETUP _IOWR(TDA_IOCTL_BASE, TDA_GET_SETUP_CMD,tda_setup_info) ++#define TDA_IOCTL_WAIT_EVENT _IOWR(TDA_IOCTL_BASE, TDA_WAIT_EVENT_CMD,tda_event) ++#define TDA_IOCTL_ENABLE_EVENT _IOWR(TDA_IOCTL_BASE, TDA_ENABLE_EVENT_CMD,tda_event) ++#define TDA_IOCTL_DISABLE_EVENT _IOWR(TDA_IOCTL_BASE, TDA_DISABLE_EVENT_CMD,tda_event) ++#define TDA_IOCTL_GET_VIDEO_SPEC _IOWR(TDA_IOCTL_BASE, TDA_GET_VIDEO_SPEC_CMD,tda_video_format) ++#define TDA_IOCTL_SET_INPUT_OUTPUT _IOWR(TDA_IOCTL_BASE, TDA_SET_INPUT_OUTPUT_CMD,tda_set_in_out) ++#define TDA_IOCTL_SET_AUDIO_INPUT _IOWR(TDA_IOCTL_BASE, TDA_SET_AUDIO_INPUT_CMD,tda_audio_in) ++#define TDA_IOCTL_SET_VIDEO_INFOFRAME _IOWR(TDA_IOCTL_BASE, TDA_SET_VIDEO_INFOFRAME_CMD,tda_video_infoframe) ++#define TDA_IOCTL_SET_AUDIO_INFOFRAME _IOWR(TDA_IOCTL_BASE, TDA_SET_AUDIO_INFOFRAME_CMD,tda_audio_infoframe) ++#define TDA_IOCTL_SET_ACP _IOWR(TDA_IOCTL_BASE, TDA_SET_ACP_CMD,tda_acp) ++#define TDA_IOCTL_SET_GCP _IOWR(TDA_IOCTL_BASE, TDA_SET_GCP_CMD,tda_gcp) ++#define TDA_IOCTL_SET_ISRC1 _IOWR(TDA_IOCTL_BASE, TDA_SET_ISRC1_CMD,tda_isrc1) ++#define TDA_IOCTL_SET_ISRC2 _IOWR(TDA_IOCTL_BASE, TDA_SET_ISRC2_CMD,tda_isrc2) ++#define TDA_IOCTL_SET_MPS_INFOFRAME _IOWR(TDA_IOCTL_BASE, TDA_SET_MPS_INFOFRAME_CMD,tda_mps_infoframe) ++#define TDA_IOCTL_SET_SPD_INFOFRAME _IOWR(TDA_IOCTL_BASE, TDA_SET_SPD_INFOFRAME_CMD,tda_spd_infoframe) ++#define TDA_IOCTL_SET_VS_INFOFRAME _IOWR(TDA_IOCTL_BASE, TDA_SET_VS_INFOFRAME_CMD,tda_vs_infoframe) ++#define TDA_IOCTL_SET_AUDIO_MUTE _IOWR(TDA_IOCTL_BASE, TDA_SET_AUDIO_MUTE_CMD,bool) ++#define TDA_IOCTL_RESET_AUDIO_CTS _IO(TDA_IOCTL_BASE, TDA_RESET_AUDIO_CTS_CMD) ++#define TDA_IOCTL_GET_EDID_STATUS _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_STATUS_CMD,tda_edid) ++#define TDA_IOCTL_GET_EDID_AUDIO_CAPS _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_AUDIO_CAPS_CMD,tda_edid_audio_caps) ++#define TDA_IOCTL_GET_EDID_VIDEO_CAPS _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_VIDEO_CAPS_CMD,tda_edid_video_caps) ++#define TDA_IOCTL_GET_EDID_VIDEO_PREF _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_VIDEO_PREF_CMD,tda_edid_video_timings) ++#define TDA_IOCTL_GET_EDID_SINK_TYPE _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_SINK_TYPE_CMD,tda_sink) ++#define TDA_IOCTL_GET_EDID_SOURCE_ADDRESS _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_SOURCE_ADDRESS_CMD,unsigned short) ++#define TDA_IOCTL_SET_GAMMUT _IOWR(TDA_IOCTL_BASE, TDA_SET_GAMMUT_CMD,tda_gammut) ++#define TDA_IOCTL_GET_EDID_DTD _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_DTD_CMD,tda_edid_dtd) ++#define TDA_IOCTL_GET_EDID_MD _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_MD_CMD,tda_edid_md) ++#define TDA_IOCTL_GET_EDID_TV_ASPECT_RATIO _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_TV_ASPECT_RATIO_CMD,tda_edid_tv_aspect_ratio) ++#define TDA_IOCTL_GET_HPD_STATUS _IOWR(TDA_IOCTL_BASE, TDA_GET_HPD_STATUS_CMD, tmdlHdmiTxHotPlug_t) ++#ifdef TMFL_TDA19989 ++#define TDA_IOCTL_GET_EDID_LATENCY _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_LATENCY_CMD,tda_edid_latency) ++#define TDA_IOCTL_SET_HDCP _IOWR(TDA_IOCTL_BASE, TDA_SET_HDCP_CMD,bool) ++#define TDA_IOCTL_GET_HDCP_STATUS _IOWR(TDA_IOCTL_BASE, TDA_GET_HDCP_STATUS_CMD,tda_hdcp_status) ++#endif ++ ++ ++/* --- Full list --- */ ++ ++/* legend: */ ++/* ------- */ ++/* [ ] : not supported */ ++/* [x] : IOCTL */ ++/* [i] : open, init... */ ++ ++/* [x] tmdlHdmiTxGetSWVersion */ ++/* [ ] tmdlHdmiTxGetNumberOfUnits */ ++/* [i] tmdlHdmiTxGetCapabilities */ ++/* [ ] tmdlHdmiTxGetCapabilitiesM */ ++/* [i] tmdlHdmiTxOpen */ ++/* [ ] tmdlHdmiTxOpenM */ ++/* [i] tmdlHdmiTxClose */ ++/* [x] tmdlHdmiTxSetPowerState */ ++/* [x] tmdlHdmiTxGetPowerState */ ++/* [ ] tmdlHdmiTxInstanceConfig */ ++/* [xi] tmdlHdmiTxInstanceSetup */ ++/* [x] tmdlHdmiTxGetInstanceSetup */ ++/* [x] tmdlHdmiTxHandleInterrupt see IOCTL_WAIT_EVENT */ ++/* [i] tmdlHdmiTxRegisterCallbacks */ ++/* [x] tmdlHdmiTxEnableEvent */ ++/* [x] tmdlHdmiTxDisableEvent */ ++/* [x] tmdlHdmiTxGetVideoFormatSpecs */ ++/* [x] tmdlHdmiTxSetInputOutput */ ++/* [x] tmdlHdmiTxSetAudioInput */ ++/* [x] tmdlHdmiTxSetVideoInfoframe */ ++/* [x] tmdlHdmiTxSetAudioInfoframe */ ++/* [x] tmdlHdmiTxSetACPPacket */ ++/* [x] tmdlHdmiTxSetGeneralControlPacket */ ++/* [x] tmdlHdmiTxSetISRC1Packet */ ++/* [x] tmdlHdmiTxSetISRC2Packet */ ++/* [x] tmdlHdmiTxSetMPSInfoframe */ ++/* [x] tmdlHdmiTxSetSpdInfoframe */ ++/* [x] tmdlHdmiTxSetVsInfoframe */ ++/* [ ] tmdlHdmiTxDebugSetNullPacket */ ++/* [ ] tmdlHdmiTxDebugSetSingleNullPacket */ ++/* [x] tmdlHdmiTxSetAudioMute */ ++/* [x] tmdlHdmiTxResetAudioCts */ ++/* [x] tmdlHdmiTxGetEdidStatus */ ++/* [x] tmdlHdmiTxGetEdidAudioCaps */ ++/* [x] tmdlHdmiTxGetEdidVideoCaps */ ++/* [x] tmdlHdmiTxGetEdidVideoPreferred */ ++/* [x] tmdlHdmiTxGetEdidSinkType */ ++/* [x] tmdlHdmiTxGetEdidSourceAddress */ ++/* [ ] tmdlHdmiTxGetKsvList */ ++/* [ ] tmdlHdmiTxGetDepth */ ++/* [ ] tmdlHdmiTxGeneSHA_1_IT */ ++/* [ ] tmdlHdmiTxSetHdcp */ ++/* [ ] tmdlHdmiTxGetHdcpState */ ++/* [ ] tmdlHdmiTxHdcpCheck */ ++/* [x] tmdlHdmiTxSetGamutPacket */ ++/* [x] tmdlHdmiTxGetEdidDetailledTimingDescriptors */ ++/* [x] tmdlHdmiTxGetEdidMonitorDescriptors */ ++/* [x] tmdlHdmiTxGetEdidTVPictureRatio */ ++/* [ ] tmdlHdmiTxSetHDCPRevocationList */ ++/* [ ] tmdlHdmiTxGetHdcpFailStatus */ ++/* [x] tmdlHdmiTxGetEdidLatencyInfo */ ++/* [ ] tmdlHdmiTxSetBScreen */ ++/* [ ] tmdlHdmiTxRemoveBScreen */ ++ ++ ++#endif /* __tx_h__ */ ++#endif /* __tx_ioctl__ */ ++ ++#ifndef __cec_ioctl__ ++#define __cec_ioctl__ ++ ++#ifdef __cec_h__ ++ ++typedef struct { ++ UInt8 DayOfMonth; ++ UInt8 MonthOfYear; ++ UInt16 StartTime; ++ tmdlHdmiCECDuration_t Duration; ++ UInt8 RecordingSequence; ++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType; ++ UInt16 AnalogueFrequency; ++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem; ++} cec_analogue_timer; ++ ++typedef struct { ++ UInt8 DayOfMonth; ++ UInt8 MonthOfYear; ++ UInt16 StartTime; ++ tmdlHdmiCECDuration_t Duration; ++ UInt8 RecordingSequence; ++ tmdlHdmiCECDigitalServiceIdentification_t ServiceIdentification; ++} cec_digital_timer; ++ ++typedef struct { ++ UInt8 DayOfMonth; ++ UInt8 MonthOfYear; ++ UInt16 StartTime; ++ tmdlHdmiCECDuration_t Duration; ++ UInt8 RecordingSequence; ++ tmdlHdmiCECExternalPlug_t ExternalPlug; ++} cec_ext_timer_with_ext_plug; ++ ++typedef struct { ++ UInt8 DayOfMonth; ++ UInt8 MonthOfYear; ++ UInt16 StartTime; ++ tmdlHdmiCECDuration_t Duration; ++ UInt8 RecordingSequence; ++ tmdlHdmiCECExternalPhysicalAddress_t ExternalPhysicalAddress; ++} cec_ext_timer_with_phy_addr; ++ ++typedef struct { ++ tmdlHdmiCECFeatureOpcode_t FeatureOpcode; ++ tmdlHdmiCECAbortReason_t AbortReason; ++} cec_feature_abort; ++ ++typedef struct { ++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType; ++ UInt16 AnalogueFrequency; ++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem; ++} cec_analogue_service; ++ ++typedef struct { ++ UInt16 OriginalAddress; ++ UInt16 NewAddress; ++} cec_routing_change; ++ ++typedef struct { ++ char data[15]; ++ unsigned char length; ++} cec_string; ++ ++typedef struct { ++ tmdlHdmiCECDisplayControl_t DisplayControl; ++ char data[15]; ++ unsigned char length; ++} cec_osd_string; ++ ++typedef struct { ++ tmdlHdmiCECRecordingFlag_t RecordingFlag; ++ tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo; ++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType; ++ UInt16 AnalogueFrequency; ++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem; ++} cec_tuner_device_status_analogue; ++ ++typedef struct { ++ tmdlHdmiCECRecordingFlag_t RecordingFlag; ++ tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo; ++ tmdlHdmiCECDigitalServiceIdentification_t ServiceIdentification; ++} cec_tuner_device_status_digital; ++ ++typedef struct { ++ unsigned long VendorID; ++ cec_string cmd; ++} cec_vendor_command_with_id; ++ ++/* ++ typedef struct { ++ UInt8 *pData; ++ UInt16 lenData; ++ } cec_send_msg; ++*/ ++ ++typedef struct ++{ ++ unsigned char count; ++ unsigned char service; ++ unsigned char addr; ++ unsigned char data[15]; ++} cec_frame; ++/* typedef tmdlHdmiCecFrameFormat_t cec_frame; */ ++ ++typedef tmSWVersion_t cec_sw_version; ++typedef tmPowerState_t cec_power; ++typedef tmdlHdmiCecInstanceSetup_t cec_setup; ++typedef tmdlHdmiCecEvent_t cec_event; ++typedef tmdlHdmiCecClockSource_t cec_clock; ++typedef tmdlHdmiCECSystemAudioStatus_t cec_sys_audio_status; ++typedef tmdlHdmiCECAudioRate_t cec_audio_rate; ++typedef tmdlHdmiCECDigitalServiceIdentification_t cec_digital_service; ++typedef tmdlHdmiCECVersion_t cec_version; ++typedef tmdlHdmiCECDecControlMode_t cec_deck_ctrl; ++typedef tmdlHdmiCECDecInfo_t cec_deck_status; ++typedef tmdlHdmiCECStatusRequest_t cec_status_request; ++typedef tmdlHdmiCECMenuRequestType_t cec_menu_request; ++typedef tmdlHdmiCECMenuState_t cec_menu_status; ++typedef tmdlHdmiCECPlayMode_t cec_play; ++typedef tmdlHdmiCECExternalPlug_t cec_ext_plug; ++typedef tmdlHdmiCECRecordStatusInfo_t cec_rec_status; ++typedef tmdlHdmiCECAudioStatus_t cec_audio_status; ++typedef tmdlHdmiCECPowerStatus_t cec_power_status; ++typedef tmdlHdmiCECTimerClearedStatusData_t cec_timer_cleared_status; ++typedef tmdlHdmiCECTimerStatusData_t cec_timer_status; ++typedef tmdlHdmiCECUserRemoteControlCommand_t cec_user_ctrl; ++typedef tmdlHdmiCECChannelIdentifier_t cec_user_ctrl_tune; ++typedef tmdlHdmiCECDeviceType_t cec_device_type; ++ ++#define CEC_IOCTL_BASE 0x40 ++ ++/* service */ ++enum { ++ CEC_WAITING = 0x80, ++ CEC_RELEASE, ++ CEC_RX_DONE, ++ CEC_TX_DONE ++}; ++ ++enum { ++ /* driver specific */ ++ CEC_VERBOSE_ON_CMD = 0, ++ CEC_VERBOSE_OFF_CMD, ++ CEC_BYEBYE_CMD, ++ ++ /* CEC */ ++ CEC_IOCTL_RX_ADDR_CMD, /* receiver logical address selector */ ++ CEC_IOCTL_PHY_ADDR_CMD, /* physical address selector */ ++ CEC_IOCTL_WAIT_FRAME_CMD, ++ CEC_IOCTL_ABORT_MSG_CMD, ++ CEC_IOCTL_ACTIVE_SRC_CMD, ++ CEC_IOCTL_VERSION_CMD, ++ CEC_IOCTL_CLEAR_ANALOGUE_TIMER_CMD, ++ CEC_IOCTL_CLEAR_DIGITAL_TIMER_CMD, ++ CEC_IOCTL_CLEAR_EXT_TIMER_WITH_EXT_PLUG_CMD, ++ CEC_IOCTL_CLEAR_EXT_TIMER_WITH_PHY_ADDR_CMD, ++ CEC_IOCTL_DECK_CTRL_CMD, ++ CEC_IOCTL_DECK_STATUS_CMD, ++ CEC_IOCTL_DEVICE_VENDOR_ID_CMD, ++ CEC_IOCTL_FEATURE_ABORT_CMD, ++ CEC_IOCTL_GET_CEC_VERSION_CMD, ++ CEC_IOCTL_GET_MENU_LANGUAGE_CMD, ++ CEC_IOCTL_GIVE_AUDIO_STATUS_CMD, ++ CEC_IOCTL_GIVE_DECK_STATUS_CMD, ++ CEC_IOCTL_GIVE_DEVICE_POWER_STATUS_CMD, ++ CEC_IOCTL_GIVE_DEVICE_VENDOR_ID_CMD, ++ CEC_IOCTL_GIVE_OSD_NAME_CMD, ++ CEC_IOCTL_GIVE_PHY_ADDR_CMD, ++ CEC_IOCTL_GIVE_SYS_AUDIO_MODE_STATUS_CMD, ++ CEC_IOCTL_GIVE_TUNER_DEVICE_STATUS_CMD, ++ CEC_IOCTL_IMAGE_VIEW_ON_CMD, ++ CEC_IOCTL_INACTIVE_SRC_CMD, ++ CEC_IOCTL_MENU_REQUEST_CMD, ++ CEC_IOCTL_MENU_STATUS_CMD, ++ CEC_IOCTL_PLAY_CMD, ++ CEC_IOCTL_POLLING_MSG_CMD, ++ CEC_IOCTL_REC_OFF_CMD, ++ CEC_IOCTL_REC_ON_ANALOGUE_SERVICE_CMD, ++ CEC_IOCTL_REC_ON_DIGITAL_SERVICE_CMD, ++ CEC_IOCTL_REC_ON_EXT_PHY_ADDR_CMD, ++ CEC_IOCTL_REC_ON_EXT_PLUG_CMD, ++ CEC_IOCTL_REC_ON_OWN_SRC_CMD, ++ CEC_IOCTL_REC_STATUS_CMD, ++ CEC_IOCTL_REC_TV_SCREEN_CMD, ++ CEC_IOCTL_REPORT_AUDIO_STATUS_CMD, ++ CEC_IOCTL_REPORT_PHY_ADDR_CMD, ++ CEC_IOCTL_REPORT_POWER_STATUS_CMD, ++ CEC_IOCTL_REQUEST_ACTIVE_SRC_CMD, ++ CEC_IOCTL_ROUTING_CHANGE_CMD, ++ CEC_IOCTL_ROUTING_INFORMATION_CMD, ++ CEC_IOCTL_SELECT_ANALOGUE_SERVICE_CMD, ++ CEC_IOCTL_SELECT_DIGITAL_SERVICE_CMD, ++ CEC_IOCTL_SET_ANALOGUE_TIMER_CMD, ++ CEC_IOCTL_SET_AUDIO_RATE_CMD, ++ CEC_IOCTL_SET_DIGITAL_TIMER_CMD, ++ CEC_IOCTL_SET_EXT_TIMER_WITH_EXT_PLUG_CMD, ++ CEC_IOCTL_SET_EXT_TIMER_WITH_PHY_ADDR_CMD, ++ CEC_IOCTL_SET_MENU_LANGUAGE_CMD, ++ CEC_IOCTL_SET_OSD_NAME_CMD, ++ CEC_IOCTL_SET_OSD_STRING_CMD, ++ CEC_IOCTL_SET_STREAM_PATH_CMD, ++ CEC_IOCTL_SET_SYS_AUDIO_MODE_CMD, ++ CEC_IOCTL_SET_TIMER_PROGRAM_TITLE_CMD, ++ CEC_IOCTL_STANDBY_CMD, ++ CEC_IOCTL_SYS_AUDIO_MODE_REQUEST_CMD, ++ CEC_IOCTL_SYS_AUDIO_MODE_STATUS_CMD, ++ CEC_IOCTL_TEXT_VIEW_ON_CMD, ++ CEC_IOCTL_TIMER_CLEARED_STATUS_CMD, ++ CEC_IOCTL_TIMER_STATUS_CMD, ++ CEC_IOCTL_TUNER_DEVICE_STATUS_ANALOGUE_CMD, ++ CEC_IOCTL_TUNER_DEVICE_STATUS_DIGITAL_CMD, ++ CEC_IOCTL_TUNER_STEP_DECREMENT_CMD, ++ CEC_IOCTL_TUNER_STEP_INCREMENT_CMD, ++ CEC_IOCTL_USER_CTRL_CMD, ++ CEC_IOCTL_USER_CTRL_PLAY_CMD, ++ CEC_IOCTL_USER_CTRL_SELECT_AUDIOINPUT_CMD, ++ CEC_IOCTL_USER_CTRL_SELECT_AVINPUT_CMD, ++ CEC_IOCTL_USER_CTRL_SELECT_MEDIA_CMD, ++ CEC_IOCTL_USER_CTRL_TUNE_CMD, ++ CEC_IOCTL_USER_CTRL_RELEASED_CMD, ++ CEC_IOCTL_VENDOR_COMMAND_CMD, ++ CEC_IOCTL_VENDOR_COMMAND_WITH_ID_CMD, ++ CEC_IOCTL_VENDOR_REMOTE_BUTTON_DOWN_CMD, ++ CEC_IOCTL_VENDOR_REMOTE_BUTTON_UP_CMD, ++ CEC_IOCTL_GET_SW_VERSION_CMD, ++ CEC_IOCTL_SET_POWER_STATE_CMD, ++ CEC_IOCTL_GET_POWER_STATE_CMD, ++ CEC_IOCTL_INSTANCE_CONFIG_CMD, ++ CEC_IOCTL_INSTANCE_SETUP_CMD, ++ CEC_IOCTL_GET_INSTANCE_SETUP_CMD, ++ CEC_IOCTL_ENABLE_EVENT_CMD, ++ CEC_IOCTL_DISABLE_EVENT_CMD, ++ CEC_IOCTL_ENABLE_CALIBRATION_CMD, ++ CEC_IOCTL_DISABLE_CALIBRATION_CMD, ++ CEC_IOCTL_SEND_MSG_CMD, ++ CEC_IOCTL_SET_REGISTER_CMD ++}; ++ ++ ++/* driver specific */ ++#define CEC_IOCTL_VERBOSE_ON _IO(CEC_IOCTL_BASE, CEC_VERBOSE_ON_CMD) ++#define CEC_IOCTL_VERBOSE_OFF _IO(CEC_IOCTL_BASE, CEC_VERBOSE_OFF_CMD) ++#define CEC_IOCTL_BYEBYE _IO(CEC_IOCTL_BASE, CEC_BYEBYE_CMD) ++ ++/* CEC */ ++#define CEC_IOCTL_RX_ADDR _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_RX_ADDR_CMD,unsigned char) ++#define CEC_IOCTL_PHY_ADDR _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_PHY_ADDR_CMD,unsigned short) ++#define CEC_IOCTL_WAIT_FRAME _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_WAIT_FRAME_CMD,cec_frame) ++#define CEC_IOCTL_ABORT_MSG _IO(CEC_IOCTL_BASE,CEC_IOCTL_ABORT_MSG_CMD) ++#define CEC_IOCTL_ACTIVE_SRC _IO(CEC_IOCTL_BASE,CEC_IOCTL_ACTIVE_SRC_CMD) ++#define CEC_IOCTL_VERSION _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_VERSION_CMD,cec_version) ++#define CEC_IOCTL_CLEAR_ANALOGUE_TIMER _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_CLEAR_ANALOGUE_TIMER_CMD,cec_analogue_timer) ++#define CEC_IOCTL_CLEAR_DIGITAL_TIMER _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_CLEAR_DIGITAL_TIMER_CMD,cec_digital_timer) ++#define CEC_IOCTL_CLEAR_EXT_TIMER_WITH_EXT_PLUG _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_CLEAR_EXT_TIMER_WITH_EXT_PLUG_CMD,cec_ext_timer_with_ext_plug) ++#define CEC_IOCTL_CLEAR_EXT_TIMER_WITH_PHY_ADDR _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_CLEAR_EXT_TIMER_WITH_PHY_ADDR_CMD,cec_ext_timer_with_phy_addr) ++#define CEC_IOCTL_DECK_CTRL _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_DECK_CTRL_CMD,cec_deck_ctrl) ++#define CEC_IOCTL_DECK_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_DECK_STATUS_CMD,cec_deck_status) ++#define CEC_IOCTL_DEVICE_VENDOR_ID _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_DEVICE_VENDOR_ID_CMD,unsigned long) ++#define CEC_IOCTL_FEATURE_ABORT _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_FEATURE_ABORT_CMD,cec_feature_abort) ++#define CEC_IOCTL_GET_CEC_VERSION _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_GET_CEC_VERSION_CMD,unsigned char) ++#define CEC_IOCTL_GET_MENU_LANGUAGE _IO(CEC_IOCTL_BASE,CEC_IOCTL_GET_MENU_LANGUAGE_CMD) ++#define CEC_IOCTL_GIVE_AUDIO_STATUS _IO(CEC_IOCTL_BASE,CEC_IOCTL_GIVE_AUDIO_STATUS_CMD) ++#define CEC_IOCTL_GIVE_DECK_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_GIVE_DECK_STATUS_CMD,cec_status_request) ++#define CEC_IOCTL_GIVE_DEVICE_POWER_STATUS _IO(CEC_IOCTL_BASE,CEC_IOCTL_GIVE_DEVICE_POWER_STATUS_CMD) ++#define CEC_IOCTL_GIVE_DEVICE_VENDOR_ID _IO(CEC_IOCTL_BASE,CEC_IOCTL_GIVE_DEVICE_VENDOR_ID_CMD) ++#define CEC_IOCTL_GIVE_OSD_NAME _IO(CEC_IOCTL_BASE,CEC_IOCTL_GIVE_OSD_NAME_CMD) ++#define CEC_IOCTL_GIVE_PHY_ADDR _IO(CEC_IOCTL_BASE,CEC_IOCTL_GIVE_PHY_ADDR_CMD) ++#define CEC_IOCTL_GIVE_SYS_AUDIO_MODE_STATUS _IO(CEC_IOCTL_BASE,CEC_IOCTL_GIVE_SYS_AUDIO_MODE_STATUS_CMD) ++#define CEC_IOCTL_GIVE_TUNER_DEVICE_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_GIVE_TUNER_DEVICE_STATUS_CMD,cec_status_request) ++#define CEC_IOCTL_IMAGE_VIEW_ON _IO(CEC_IOCTL_BASE,CEC_IOCTL_IMAGE_VIEW_ON_CMD) ++#define CEC_IOCTL_INACTIVE_SRC _IO(CEC_IOCTL_BASE,CEC_IOCTL_INACTIVE_SRC_CMD) ++#define CEC_IOCTL_MENU_REQUEST _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_MENU_REQUEST_CMD,cec_menu_request) ++#define CEC_IOCTL_MENU_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_MENU_STATUS_CMD,cec_menu_status) ++#define CEC_IOCTL_PLAY _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_PLAY_CMD,cec_play) ++#define CEC_IOCTL_POLLING_MSG _IO(CEC_IOCTL_BASE,CEC_IOCTL_POLLING_MSG_CMD) ++#define CEC_IOCTL_REC_OFF _IO(CEC_IOCTL_BASE,CEC_IOCTL_REC_OFF_CMD) ++#define CEC_IOCTL_REC_ON_ANALOGUE_SERVICE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_REC_ON_ANALOGUE_SERVICE_CMD,cec_analogue_service) ++#define CEC_IOCTL_REC_ON_DIGITAL_SERVICE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_REC_ON_DIGITAL_SERVICE_CMD,cec_digital_service) ++#define CEC_IOCTL_REC_ON_EXT_PHY_ADDR _IO(CEC_IOCTL_BASE,CEC_IOCTL_REC_ON_EXT_PHY_ADDR_CMD) ++#define CEC_IOCTL_REC_ON_EXT_PLUG _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_REC_ON_EXT_PLUG_CMD,cec_ext_plug) ++#define CEC_IOCTL_REC_ON_OWN_SRC _IO(CEC_IOCTL_BASE,CEC_IOCTL_REC_ON_OWN_SRC_CMD) ++#define CEC_IOCTL_REC_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_REC_STATUS_CMD,cec_rec_status) ++#define CEC_IOCTL_REC_TV_SCREEN _IO(CEC_IOCTL_BASE,CEC_IOCTL_REC_TV_SCREEN_CMD) ++#define CEC_IOCTL_REPORT_AUDIO_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_REPORT_AUDIO_STATUS_CMD,cec_audio_status) ++#define CEC_IOCTL_REPORT_PHY_ADDR _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_REPORT_PHY_ADDR_CMD,cec_device_type) ++#define CEC_IOCTL_REPORT_POWER_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_REPORT_POWER_STATUS_CMD,cec_power_status) ++#define CEC_IOCTL_REQUEST_ACTIVE_SRC _IO(CEC_IOCTL_BASE,CEC_IOCTL_REQUEST_ACTIVE_SRC_CMD) ++#define CEC_IOCTL_ROUTING_CHANGE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_ROUTING_CHANGE_CMD,cec_routing_change) ++#define CEC_IOCTL_ROUTING_INFORMATION _IO(CEC_IOCTL_BASE,CEC_IOCTL_ROUTING_INFORMATION_CMD) ++#define CEC_IOCTL_SELECT_ANALOGUE_SERVICE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SELECT_ANALOGUE_SERVICE_CMD,cec_analogue_service) ++#define CEC_IOCTL_SELECT_DIGITAL_SERVICE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SELECT_DIGITAL_SERVICE_CMD,cec_digital_service) ++#define CEC_IOCTL_SET_ANALOGUE_TIMER _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_ANALOGUE_TIMER_CMD,cec_analogue_timer) ++#define CEC_IOCTL_SET_AUDIO_RATE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_AUDIO_RATE_CMD,cec_audio_rate) ++#define CEC_IOCTL_SET_DIGITAL_TIMER _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_DIGITAL_TIMER_CMD,cec_digital_timer) ++#define CEC_IOCTL_SET_EXT_TIMER_WITH_EXT_PLUG _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_EXT_TIMER_WITH_EXT_PLUG_CMD,cec_ext_timer_with_ext_plug) ++#define CEC_IOCTL_SET_EXT_TIMER_WITH_PHY_ADDR _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_EXT_TIMER_WITH_PHY_ADDR_CMD,cec_ext_timer_with_phy_addr) ++#define CEC_IOCTL_SET_MENU_LANGUAGE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_MENU_LANGUAGE_CMD,cec_string) ++#define CEC_IOCTL_SET_OSD_NAME _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_OSD_NAME_CMD,cec_string) ++#define CEC_IOCTL_SET_OSD_STRING _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_OSD_STRING_CMD,cec_osd_string) ++#define CEC_IOCTL_SET_STREAM_PATH _IO(CEC_IOCTL_BASE,CEC_IOCTL_SET_STREAM_PATH_CMD) ++#define CEC_IOCTL_SET_SYS_AUDIO_MODE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_SYS_AUDIO_MODE_CMD,cec_sys_audio_status) ++#define CEC_IOCTL_SET_TIMER_PROGRAM_TITLE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_TIMER_PROGRAM_TITLE_CMD,cec_string) ++#define CEC_IOCTL_STANDBY _IO(CEC_IOCTL_BASE,CEC_IOCTL_STANDBY_CMD) ++#define CEC_IOCTL_SYS_AUDIO_MODE_REQUEST _IO(CEC_IOCTL_BASE,CEC_IOCTL_SYS_AUDIO_MODE_REQUEST_CMD) ++#define CEC_IOCTL_SYS_AUDIO_MODE_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SYS_AUDIO_MODE_STATUS_CMD,cec_sys_audio_status) ++#define CEC_IOCTL_TEXT_VIEW_ON _IO(CEC_IOCTL_BASE,CEC_IOCTL_TEXT_VIEW_ON_CMD) ++#define CEC_IOCTL_TIMER_CLEARED_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_TIMER_CLEARED_STATUS_CMD,cec_timer_cleared_status) ++#define CEC_IOCTL_TIMER_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_TIMER_STATUS_CMD,cec_timer_status) ++#define CEC_IOCTL_TUNER_DEVICE_STATUS_ANALOGUE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_TUNER_DEVICE_STATUS_ANALOGUE_CMD,cec_tuner_device_status_analogue) ++#define CEC_IOCTL_TUNER_DEVICE_STATUS_DIGITAL _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_TUNER_DEVICE_STATUS_DIGITAL_CMD,cec_tuner_device_status_digital) ++#define CEC_IOCTL_TUNER_STEP_DECREMENT _IO(CEC_IOCTL_BASE,CEC_IOCTL_TUNER_STEP_DECREMENT_CMD) ++#define CEC_IOCTL_TUNER_STEP_INCREMENT _IO(CEC_IOCTL_BASE,CEC_IOCTL_TUNER_STEP_INCREMENT_CMD) ++#define CEC_IOCTL_USER_CTRL_PRESSED _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_USER_CTRL_CMD,cec_user_ctrl) ++#define CEC_IOCTL_USER_CTRL_PLAY _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_USER_CTRL_PLAY_CMD,cec_play) ++#define CEC_IOCTL_USER_CTRL_SELECT_AUDIOINPUT _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_USER_CTRL_SELECT_AUDIOINPUT_CMD,unsigned char) ++#define CEC_IOCTL_USER_CTRL_SELECT_AVINPUT _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_USER_CTRL_SELECT_AVINPUT_CMD,unsigned char) ++#define CEC_IOCTL_USER_CTRL_SELECT_MEDIA _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_USER_CTRL_SELECT_MEDIA_CMD,unsigned char) ++#define CEC_IOCTL_USER_CTRL_TUNE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_USER_CTRL_TUNE_CMD,cec_user_ctrl_tune) ++#define CEC_IOCTL_USER_CTRL_RELEASED _IO(CEC_IOCTL_BASE,CEC_IOCTL_USER_CTRL_RELEASED_CMD) ++#define CEC_IOCTL_VENDOR_COMMAND _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_VENDOR_COMMAND_CMD,cec_string) ++#define CEC_IOCTL_VENDOR_COMMAND_WITH_ID _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_VENDOR_COMMAND_WITH_ID_CMD,cec_vendor_command_with_id) ++#define CEC_IOCTL_VENDOR_REMOTE_BUTTON_DOWN _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_VENDOR_REMOTE_BUTTON_DOWN_CMD,cec_string) ++#define CEC_IOCTL_VENDOR_REMOTE_BUTTON_UP _IO(CEC_IOCTL_BASE,CEC_IOCTL_VENDOR_REMOTE_BUTTON_UP_CMD) ++#define CEC_IOCTL_GET_SW_VERSION _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_GET_SW_VERSION_CMD,cec_sw_version) ++#define CEC_IOCTL_SET_POWER_STATE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_POWER_STATE_CMD,cec_power) ++#define CEC_IOCTL_GET_POWER_STATE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_GET_POWER_STATE_CMD,cec_power) ++#define CEC_IOCTL_INSTANCE_CONFIG _IO(CEC_IOCTL_BASE,CEC_IOCTL_INSTANCE_CONFIG_CMD) ++#define CEC_IOCTL_INSTANCE_SETUP _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_INSTANCE_SETUP_CMD,cec_setup) ++#define CEC_IOCTL_GET_INSTANCE_SETUP _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_GET_INSTANCE_SETUP_CMD,cec_setup) ++#define CEC_IOCTL_ENABLE_EVENT _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_ENABLE_EVENT_CMD,cec_event) ++#define CEC_IOCTL_DISABLE_EVENT _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_DISABLE_EVENT_CMD,cec_event) ++#define CEC_IOCTL_ENABLE_CALIBRATION _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_ENABLE_CALIBRATION_CMD,cec_clock) ++#define CEC_IOCTL_DISABLE_CALIBRATION _IO(CEC_IOCTL_BASE,CEC_IOCTL_DISABLE_CALIBRATION_CMD) ++//#define CEC_IOCTL_SEND_MSG _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SEND_MSG_CMD,cec_send_msg) ++ ++/* --- Full list --- */ ++ ++/* legend: */ ++/* ------- */ ++/* [ ] : not supported */ ++/* [x] : IOCTL */ ++/* [i] : open, init... */ ++ ++/* [ ] tmdlHdmiCecAbortMessage */ ++/* [ ] tmdlHdmiCecActiveSource */ ++/* [ ] tmdlHdmiCecVersion */ ++/* [ ] tmdlHdmiCecClearAnalogueTimer */ ++/* [ ] tmdlHdmiCecClearDigitalTimer */ ++/* [ ] tmdlHdmiCecClearExternalTimerWithExternalPlug */ ++/* [ ] tmdlHdmiCecClearExternalTimerWithPhysicalAddress */ ++/* [ ] tmdlHdmiCecDeckControl */ ++/* [ ] tmdlHdmiCecDeckStatus */ ++/* [ ] tmdlHdmiCecDeviceVendorID */ ++/* [ ] tmdlHdmiCecFeatureAbort */ ++/* [ ] tmdlHdmiCecGetCecVersion */ ++/* [ ] tmdlHdmiCecGetMenuLanguage */ ++/* [ ] tmdlHdmiCecGiveAudioStatus */ ++/* [ ] tmdlHdmiCecGiveDeckStatus */ ++/* [ ] tmdlHdmiCecGiveDevicePowerStatus */ ++/* [ ] tmdlHdmiCecGiveDeviceVendorID */ ++/* [ ] tmdlHdmiCecGiveOsdName */ ++/* [ ] tmdlHdmiCecGivePhysicalAddress */ ++/* [ ] tmdlHdmiCecGiveSystemAudioModeStatus */ ++/* [ ] tmdlHdmiCecGiveTunerDeviceStatus */ ++/* [ ] tmdlHdmiCecImageViewOn */ ++/* [ ] tmdlHdmiCecInactiveSource */ ++/* [ ] tmdlHdmiCecMenuRequest */ ++/* [ ] tmdlHdmiCecMenuStatus */ ++/* [ ] tmdlHdmiCecPlay */ ++/* [ ] tmdlHdmiCecPollingMessage */ ++/* [ ] tmdlHdmiCecRecordOff */ ++/* [ ] tmdlHdmiCecRecordOnAnalogueService */ ++/* [ ] tmdlHdmiCecRecordOnDigitalService */ ++/* [ ] tmdlHdmiCecRecordOnExternalPhysicalAddress */ ++/* [ ] tmdlHdmiCecRecordOnExternalPlug */ ++/* [ ] tmdlHdmiCecRecordOnOwnSource */ ++/* [ ] tmdlHdmiCecRecordStatus */ ++/* [ ] tmdlHdmiCecRecordTvScreen */ ++/* [ ] tmdlHdmiCecReportAudioStatus */ ++/* [ ] tmdlHdmiCecReportPhysicalAddress */ ++/* [ ] tmdlHdmiCecReportPowerStatus */ ++/* [ ] tmdlHdmiCecRequestActiveSource */ ++/* [ ] tmdlHdmiCecRoutingChange */ ++/* [ ] tmdlHdmiCecRoutingInformation */ ++/* [ ] tmdlHdmiCecSelectAnalogueService */ ++/* [ ] tmdlHdmiCecSelectDigitalService */ ++/* [ ] tmdlHdmiCecSetAnalogueTimer */ ++/* [ ] tmdlHdmiCecSetAudioRate */ ++/* [ ] tmdlHdmiCecSetDigitalTimer */ ++/* [ ] tmdlHdmiCecSetExternalTimerWithExternalPlug */ ++/* [ ] tmdlHdmiCecSetExternalTimerWithPhysicalAddress */ ++/* [ ] tmdlHdmiCecSetMenuLanguage */ ++/* [ ] tmdlHdmiCecSetOsdName */ ++/* [ ] tmdlHdmiCecSetOsdString */ ++/* [ ] tmdlHdmiCecSetStreamPath */ ++/* [ ] tmdlHdmiCecSetSystemAudioMode */ ++/* [ ] tmdlHdmiCecSetTimerProgramTitle */ ++/* [ ] tmdlHdmiCecStandby */ ++/* [ ] tmdlHdmiCecSystemAudioModeRequest */ ++/* [ ] tmdlHdmiCecSystemAudioModeStatus */ ++/* [ ] tmdlHdmiCecTextViewOn */ ++/* [ ] tmdlHdmiCecTimerClearedStatus */ ++/* [ ] tmdlHdmiCecTimerStatus */ ++/* [ ] tmdlHdmiCecTunerDeviceStatusAnalogue */ ++/* [ ] tmdlHdmiCecTunerDeviceStatusDigital */ ++/* [ ] tmdlHdmiCecTunerStepDecrement */ ++/* [ ] tmdlHdmiCecTunerStepIncrement */ ++/* [ ] tmdlHdmiCecUserControlPressed */ ++/* [ ] tmdlHdmiCecUserControlPressedPlay */ ++/* [ ] tmdlHdmiCecUserControlPressedSelectAudioInput */ ++/* [ ] tmdlHdmiCecUserControlPressedSelectAVInput */ ++/* [ ] tmdlHdmiCecUserControlPressedSelectMedia */ ++/* [ ] tmdlHdmiCecUserControlPressedTune */ ++/* [ ] tmdlHdmiCecUserControlReleased */ ++/* [ ] tmdlHdmiCecVendorCommand */ ++/* [ ] tmdlHdmiCecVendorCommandWithID */ ++/* [ ] tmdlHdmiCecVendorRemoteButtonDown */ ++/* [ ] tmdlHdmiCecVendorRemoteButtonUp */ ++/* [ ] tmdlHdmiCecGetSWVersion */ ++/* [ ] tmdlHdmiCecGetNumberOfUnits */ ++/* [ ] tmdlHdmiCecGetCapabilities */ ++/* [ ] tmdlHdmiCecGetCapabilitiesM */ ++/* [ ] tmdlHdmiCecOpen */ ++/* [ ] tmdlHdmiCecOpenM */ ++/* [ ] tmdlHdmiCecClose */ ++/* [ ] tmdlHdmiCecSetPowerState */ ++/* [ ] tmdlHdmiCecGetPowerState */ ++/* [ ] tmdlHdmiCecInstanceConfig */ ++/* [ ] tmdlHdmiCecInstanceSetup */ ++/* [ ] tmdlHdmiCecGetInstanceSetup */ ++/* [ ] tmdlHdmiCecHandleInterrupt */ ++/* [ ] tmdlHdmiCecRegisterCallbacks */ ++/* [ ] tmdlHdmiCecSetAutoAnswer */ ++/* [ ] tmdlHdmiCecSetLogicalAddress */ ++/* [ ] tmdlHdmiCecEnableEvent */ ++/* [ ] tmdlHdmiCecDisableEvent */ ++/* [ ] tmdlHdmiCecEnableCalibration */ ++/* [ ] tmdlHdmiCecDisableCalibration */ ++/* [ ] tmdlHdmiCecSendMessage */ ++/* [ ] tmdlHdmiCecSetRegister */ ++ ++ ++#endif /* __cec_h__ */ ++#endif /* __cec_ioctl__ */ +diff --git a/drivers/video/nxp/tda998x_version.h b/drivers/video/nxp/tda998x_version.h +new file mode 100755 +index 0000000..11233e0 +--- /dev/null ++++ b/drivers/video/nxp/tda998x_version.h +@@ -0,0 +1,17 @@ ++#ifndef __tda_version__ ++#define __tda_version__ ++ ++/* version */ ++#define TDA_VERSION_MAJOR 1 ++#define TDA_VERSION_MINOR 3 ++#define TDA_VERSION_PATCHLEVEL 0 ++#define TDA_VERSION_EXTRA "-ioctl (2009-10-15)" ++ ++/* TDA TX chip list */ ++#define TDA19989 "tda19989" ++#define TDA19988 "tda19989" ++#define TDA9984 "tda9984" ++#define TDA9983 "tda9983" ++#define TDA9981 "tda9981" ++ ++#endif +diff --git a/drivers/video/nxp/test/Makefile b/drivers/video/nxp/test/Makefile +new file mode 100755 +index 0000000..fd2fcb8 +--- /dev/null ++++ b/drivers/video/nxp/test/Makefile +@@ -0,0 +1,28 @@ ++PACKAGE_NAME=DEMO_TDA ++ ++RULES:=compile ++# ROOT=/home/vadmin/dev/hdmi/omapzoom/nxp-modules ++ROOT=.. ++INC=-I${ROOT} -I${ROOT}/inc -I${ROOT}/comps -I${ROOT}/comps/inc -I${ROOT}/comps/tmdlHdmiTx/inc -I${ROOT}/comps/tmdlHdmiCEC/inc ++ ++EXTRA_CFLAGS += -DFUNC_PTR=" " -DCONST_DAT="const " -DRAM_DAT=" " ++CFLAGS= ${INC} ++# LDFLAGS= -lpthread ++ACC=agcc ++# ACC=arm-none-linux-gnueabi-gcc ++ ++BINARIES=demo_tda ++ ++all: $(RULES) ++ ++clean: ++ @echo "\t-----> $(PACKAGE_NAME):$@" ++ @rm -f $(BINARIES) *.o ++ ++compile: ++ $(ACC) $(CFLAGS) $(LDFLAGS) demo_tda.c -o demo_tda ++ ++upload: ++ adb shell rm demo_tda ++ adb push demo_tda demo_tda ++ adb shell ./demo_tda +diff --git a/drivers/video/nxp/test/demo_tda.c b/drivers/video/nxp/test/demo_tda.c +new file mode 100755 +index 0000000..0365a6c +--- /dev/null ++++ b/drivers/video/nxp/test/demo_tda.c +@@ -0,0 +1,758 @@ ++/* * ++ * Filename: tda_demo.c ++ * ++ * Description: bench and stress of CEC ++ * features for TDA19989 ++ */ ++/* Created: 2009-10-20 ++ * ++ * Author: Andre Lepine ++ * Company: NXP Semiconductors Caen ++ * ++ */ ++#define TDA_DEMO_VERSION "v0.1" ++ ++/* linux */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tmdlHdmiTx_Types.h" ++#include "tmdlHdmiCEC_Types.h" ++#include "tda998x.h" ++#include "tda998x_ioctl.h" ++/* #include "tda998x_cec.h" */ ++ ++ ++/* ++ * ++ * Definitions ++ * ----------- ++ * CHAPTER 0 ++ * ++ */ ++ ++#define USERCHECK(x,y) {if (user_request & (x)) {y;}} ++#define _MY_IOCTL(fd,prefix,io,param) {if (ioctl(fd,prefix##io, param) == -1) {oups("ioctl failed",prefix##io);}} ++#define IO_CEC(io,param) _MY_IOCTL(cec,CEC_IOCTL_,io,param) ++#define IO_TX(io,param) _MY_IOCTL(tx,TDA_IOCTL_,io,param) ++#define IO_RX(io,param) _MY_IOCTL(rx,CEC_IOCTL_,io,param) ++#define CEC_DEV "/dev/hdmicec" ++#define TX_DEV "/dev/hdmitx" ++ ++typedef struct { ++ unsigned char received; ++ unsigned char service; ++ unsigned char addr; ++ unsigned char data[15]; ++} rx_frame; ++ ++unsigned int user_request,user_wait; ++const char cec_name[]=CEC_DEV; ++const char tx_name[]=TX_DEV; ++int rx=0,tx=0,cec=0; ++pthread_t rx_thread; ++unsigned short phy_addr; ++cec_string osd_name = {{78,88,80},3}; /* NXP */ ++tmdlHdmiCECDeviceType_t device_type = CEC_DEVICE_TYPE_PLAYBACK_DEVICE; ++ ++/* ++ * ++ * Internals ++ * --------- ++ * CHAPTER 1 ++ * ++ */ ++ ++char *cec_service(int service) ++{ ++ switch (service) ++ { ++ case CEC_WAITING: {return "waiting";break;} ++ case CEC_RELEASE: {return "release";break;} ++ case CEC_RX_DONE: {return "new message";break;} ++ case CEC_TX_DONE: {return "one message sent";break;} ++ default : {return "unknown";break;} ++ } ++} ++ ++/* ++ * syntax for dumies ++ */ ++void print_usage(char *exename) ++{ ++ printf("Usage: %s [test_numer] [loop]\n",exename); ++ printf("0x001: driver open/close\n"); ++ printf("0x002: ...\n"); ++} ++ ++/* ++ * We did it ! ++ */ ++void my_exit(int signum) { ++ ++ printf("bye\n"); ++ ++ /* ++ .last ioctl for releasing ++ .munmap if needed ++ .free ++ */ ++ ++ if (tx) close(tx); ++ if (cec) { ++ ioctl(cec,CEC_IOCTL_BYEBYE, NULL); ++ close(cec); ++ } ++ if (rx) close(rx); ++ ++ _exit(signum); ++} ++ ++/* ++ * Failure ++ */ ++void oups(char *s,int io) { ++ ++ if (io) { ++ printf("%s (%d)\noups...\n",s,io); ++ } ++ else { ++ } ++ ++ /* ++ .specific ioctl for releasing ++ */ ++ ++ if (tx) close(tx); ++ if (cec) { ++ ioctl(cec,CEC_IOCTL_BYEBYE, NULL); ++ close(cec); ++ } ++ if (rx) close(rx); ++ ++ my_exit(EXIT_FAILURE); ++} ++ ++ ++/* ++ * ++ * Methods ++ * ------- ++ * CHAPTER 2 ++ * ++ */ ++ ++/* ++ do some event control here... ++*/ ++void read_frame(cec_frame *frame) { ++ ++ unsigned char initiator, receiver; ++ int param1,param2,param3; ++ UInt32 vendor_ID; ++ UInt32 vendor_CmdID0, vendor_CmdID1, vendor_CmdID2; ++ char language[3] = {0x65,0x6e,0x67}; /* eng */ ++ tmdlHdmiCECAudioStatus_t audio; ++ tmdlHdmiCecInstanceSetup_t setup; ++ cec_feature_abort fa; ++ int i; ++ ++ printf("CEC module says:%s\n",cec_service(frame->service)); ++ ++ /*Give receive data from CEC bus*/ ++ if (frame->service == CEC_RX_DONE) { ++ ++ //initiator and receiver ++ initiator = (frame->addr >> 4) & 0x0f; ++ receiver = frame->addr & 0x0f; ++ printf("[%x]->[%x] data:%02x%02x%02x%02x...\n", \ ++ initiator, \ ++ receiver, \ ++ frame->data[0], \ ++ frame->data[1], \ ++ frame->data[2], \ ++ frame->data[3]); ++ ++ ++ // Particular case of Polling Message// ++ if (frame->count == 0x03) ++ { ++ } ++ else ++ { ++ switch(frame->data[0]) ++ { ++ // Standby ++ case CEC_OPCODE_STANDBY : ++#ifdef CEC_PW_MGT ++ IO_TX(SET_POWER,tmPowerStandby); ++#endif ++ break; ++ ++ // Set Menu Language ++ case CEC_OPCODE_GET_MENU_LANGUAGE : ++ IO_CEC(SET_MENU_LANGUAGE,language); ++ break; ++ ++ // Set Menu Language ++ case CEC_OPCODE_SET_MENU_LANGUAGE : ++ param1 = frame->data[1]; ++ param2 = frame->data[2]; ++ param3 = frame->data[3]; ++ printf(" \n", param1,param2,param3); ++ break; ++ ++ // Active Source ++ case CEC_OPCODE_ACTIVE_SOURCE : ++ param1 = ((int)frame->data[1] << 8) + frame->data[2]; ++ printf(" \n", param1); ++ break; ++ ++ // Inactive Source ++ case CEC_OPCODE_INACTIVE_SOURCE : ++ param1 = ((int)frame->data[1] << 8) + frame->data[2]; ++ printf(" \n", param1); ++ break; ++ ++ // CEC Version ++ case CEC_OPCODE_CEC_VERSION : ++ param1 = frame->data[1]; ++ printf(" \n", param1); ++ break; ++ ++ // Give OSD Name ++ case CEC_OPCODE_GIVE_OSD_NAME : ++ IO_CEC(SET_OSD_NAME,&osd_name); /* to be check FIXEME */ ++ break; ++ ++ // Give Device vendor_ ID ++ case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID : ++ IO_CEC(DEVICE_VENDOR_ID,0x000800b7); ++ break; ++ ++ // Report Physical Address ++ case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS : ++ param1 = ((int)frame->data[1] << 8) + frame->data[2]; ++ param2 = frame->data[3]; ++ printf(" \n", param1, param2); ++ break; ++ ++ // Device vendor_ ID ++ case CEC_OPCODE_DEVICE_VENDOR_ID : ++ vendor_ID = ((int)frame->data[1] << 16) + \ ++ ((int)frame->data[2] << 8) + \ ++ frame->data[3]; ++ printf(" \n", vendor_ID); ++ break; ++ ++ case CEC_OPCODE_VENDOR_COMMAND_WITH_ID : ++ vendor_ID = ((int)frame->data[1] << 16) + \ ++ ((int)frame->data[2] << 8)+ \ ++ frame->data[3]; ++ vendor_CmdID0 = ((int)frame->data[4] << 24) + \ ++ ((int)frame->data[5] << 16)+ \ ++ ((int)frame->data[6] << 8)+ \ ++ frame->data[7]; ++ vendor_CmdID1 = ((int)frame->data[8] << 24) + \ ++ ((int)frame->data[9] << 16)+ \ ++ ((int)frame->data[10] << 8)+ \ ++ frame->data[11]; ++ vendor_CmdID2 = ((int)frame->data[12] << 16) + \ ++ ((int)frame->data[13] << 8)+ \ ++ frame->data[14]; ++ printf(" \n", vendor_ID, vendor_CmdID0, vendor_CmdID1, vendor_CmdID2); ++ break; ++ ++ // Menu Request ++ case CEC_OPCODE_MENU_REQUEST : ++ param1 = frame->data[1]; ++ printf("

\n", param1); ++ break; ++ ++ // Report Power Status ++ case CEC_OPCODE_REPORT_POWER_STATUS : ++ param1 =frame->data[1]; ++ printf(" \n", param1); ++ break; ++ ++ // Set OSD Name ++ case CEC_OPCODE_SET_OSD_NAME : ++ for(i=1; i <= (frame->count-4); i++) ++ printf("%c", frame->data[i]); ++ printf(" >\n "); ++ break; ++ ++ // Abort Message ++ case CEC_OPCODE_ABORT_MESSAGE : ++ fa.FeatureOpcode=CEC_OPCODE_ABORT_MESSAGE; ++ fa.AbortReason=CEC_ABORT_REFUSED; ++ printf("ABORT_MESSAGE received\n"); ++ IO_CEC(FEATURE_ABORT,&fa); ++ break; ++ ++ // Feature Abort ++ case CEC_OPCODE_FEATURE_ABORT : ++ printf("FEATURE_ABORT"); ++ param1 = frame->data[1]; ++ param2 = frame->data[2]; ++ printf(" \n", param1, param2); ++ break; ++ ++ // Routing Change ++ case CEC_OPCODE_ROUTING_CHANGE : ++ param1 = ((int)frame->data[1] << 8) + frame->data[2]; ++ param2 = frame->data[3]; ++ printf(" \n", param1, param2); ++ break; ++ ++ //Set Stream Path ++ case CEC_OPCODE_SET_STREAM_PATH : ++ param1 = ((int)frame->data[1] << 8) + frame->data[2]; ++ printf(" \n", param1); ++ if (param1 == phy_addr) { ++ /* IO_CEC(ACTIVE_SRC,0); Done my module itself */ ++ } ++ break; ++ ++ //Give Device Power Status ++ case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS : ++ IO_CEC(REPORT_POWER_STATUS,CEC_POWER_STATUS_ON); ++ break; ++ ++ //Give Audio Status ++ case CEC_OPCODE_GIVE_AUDIO_STATUS : ++ audio.audioMuteSatus = CEC_AUDIO_MUTE_OFF; ++ audio.audioVolumeSatus = 15; ++ IO_CEC(REPORT_AUDIO_STATUS,&audio); ++ break; ++ ++ case CEC_OPCODE_PLAY: ++ switch (frame->data[1]) { ++ case CEC_MODE_PLAY_FORWARD: ++ IO_TX(SET_POWER,tmPowerOn); ++ break; ++ case CEC_MODE_PLAY_REVERSE: ++ break; ++ case CEC_MODE_FAST_FORWARD_MIN_SPEED: ++ break; ++ case CEC_MODE_FAST_FORWARD_MEDIUM_SPEED: ++ break; ++ case CEC_MODE_FAST_FORWARD_MAX_SPEED: ++ break; ++ case CEC_MODE_FAST_REVERSE_MIN_SPEED: ++ break; ++ case CEC_MODE_FAST_REVERSE_MEDIUM_SPEED: ++ break; ++ case CEC_MODE_FAST_REVERSE_MAX_SPEED: ++ break; ++ case CEC_MODE_SLOW_FORWARD_MIN_SPEED: ++ break; ++ case CEC_MODE_SLOW_FORWARD_MEDIUM_SPEED: ++ break; ++ case CEC_MODE_SLOW_FORWARD_MAX_SPEED: ++ break; ++ case CEC_MODE_SLOW_REVERSE_MIN_SPEED: ++ break; ++ case CEC_MODE_SLOW_REVERSE_MEDIUM_SPEED: ++ break; ++ case CEC_MODE_SLOW_REVERSE_MAX_SPEED: ++ break; ++ default: ++ fa.FeatureOpcode=frame->data[0]; ++ fa.AbortReason=CEC_ABORT_INVALID_OPERAND; ++ printf("Send feature abort::invalid operand in opcode play\n"); ++ IO_CEC(FEATURE_ABORT,&fa); ++ break; ++ } ++ break; ++ ++ case CEC_OPCODE_USER_CONTROL_PRESSED: ++ switch (frame->data[1]) { ++ case CEC_REMOTE_BUTTON_SELECT: ++ break; ++ case CEC_REMOTE_BUTTON_UP: ++ break; ++ case CEC_REMOTE_BUTTON_DOWN: ++ break; ++ case CEC_REMOTE_BUTTON_LEFT: ++ break; ++ case CEC_REMOTE_BUTTON_RIGHT: ++ break; ++ case CEC_REMOTE_BUTTON_RIGHT_UP: ++ break; ++ case CEC_REMOTE_BUTTON_RIGHT_DOWN: ++ break; ++ case CEC_REMOTE_BUTTON_LEFT_UP: ++ break; ++ case CEC_REMOTE_BUTTON_LEFT_DOWN: ++ break; ++ case CEC_REMOTE_BUTTON_ROOT_MENU: ++ break; ++ case CEC_REMOTE_BUTTON_SETUP_MENU: ++ break; ++ case CEC_REMOTE_BUTTON_CONTENTS_MENU: ++ break; ++ case CEC_REMOTE_BUTTON_FAVORITE_MENU: ++ break; ++ case CEC_REMOTE_BUTTON_EXIT: ++ break; ++ case CEC_REMOTE_BUTTON_NUMBER_0: ++ break; ++ case CEC_REMOTE_BUTTON_NUMBER_1: ++ break; ++ case CEC_REMOTE_BUTTON_NUMBER_2: ++ break; ++ case CEC_REMOTE_BUTTON_NUMBER_3: ++ break; ++ case CEC_REMOTE_BUTTON_NUMBER_4: ++ break; ++ case CEC_REMOTE_BUTTON_NUMBER_5: ++ break; ++ case CEC_REMOTE_BUTTON_NUMBER_6: ++ break; ++ case CEC_REMOTE_BUTTON_NUMBER_7: ++ break; ++ case CEC_REMOTE_BUTTON_NUMBER_8: ++ break; ++ case CEC_REMOTE_BUTTON_NUMBER_9: ++ break; ++ case CEC_REMOTE_BUTTON_DOT: ++ break; ++ case CEC_REMOTE_BUTTON_ENTER: ++ break; ++ case CEC_REMOTE_BUTTON_CLEAR: ++ break; ++ case CEC_REMOTE_BUTTON_NEXT_FAVORITE: ++ break; ++ case CEC_REMOTE_BUTTON_CHANNEL_UP: ++ break; ++ case CEC_REMOTE_BUTTON_CHANNEL_DOWN: ++ break; ++ case CEC_REMOTE_BUTTON_PREVIOUS_CHANNEL: ++ break; ++ case CEC_REMOTE_BUTTON_SOUND_SELECT: ++ break; ++ case CEC_REMOTE_BUTTON_INPUT_SELECT: ++ break; ++ case CEC_REMOTE_BUTTON_DISPLAY_INFORMATION: ++ break; ++ case CEC_REMOTE_BUTTON_HELP: ++ break; ++ case CEC_REMOTE_BUTTON_PAGE_UP: ++ break; ++ case CEC_REMOTE_BUTTON_PAGE_DOWN: ++ break; ++ case CEC_REMOTE_BUTTON_POWER: ++ break; ++ case CEC_REMOTE_BUTTON_VOLUME_UP: ++ break; ++ case CEC_REMOTE_BUTTON_VOLUME_DOWN: ++ break; ++ case CEC_REMOTE_BUTTON_MUTE: ++ break; ++ case CEC_REMOTE_BUTTON_PLAY: ++ break; ++ case CEC_REMOTE_BUTTON_STOP: ++ break; ++ case CEC_REMOTE_BUTTON_PAUSE: ++ break; ++ case CEC_REMOTE_BUTTON_RECORD: ++ break; ++ case CEC_REMOTE_BUTTON_REWIND: ++ break; ++ case CEC_REMOTE_BUTTON_FAST_FORWARD: ++ break; ++ case CEC_REMOTE_BUTTON_EJECT: ++ break; ++ case CEC_REMOTE_BUTTON_FORWARD: ++ break; ++ case CEC_REMOTE_BUTTON_BACKWARD: ++ break; ++ case CEC_REMOTE_BUTTON_STOP_RECORD: ++ break; ++ case CEC_REMOTE_BUTTON_PAUSE_RECORD: ++ break; ++ case CEC_REMOTE_BUTTON_ANGLE: ++ break; ++ case CEC_REMOTE_BUTTON_SUB_PICTURE: ++ break; ++ case CEC_REMOTE_BUTTON_VIDEO_ON_DEMAND: ++ break; ++ case CEC_REMOTE_BUTTON_ELECTRONIC_PROGRAM_GUIDE: ++ break; ++ case CEC_REMOTE_BUTTON_TIMER_PROGRAMMING: ++ break; ++ case CEC_REMOTE_BUTTON_INITIAL_CONFIGURATION: ++ break; ++ case CEC_REMOTE_BUTTON_PLAY_FUNCTION: ++ break; ++ case CEC_REMOTE_BUTTON_PAUSE_PLAY_FUNCTION: ++ break; ++ case CEC_REMOTE_BUTTON_RECORD_FUNCTION: ++ break; ++ case CEC_REMOTE_BUTTON_PAUSE_RECORD_FUNCTION: ++ break; ++ case CEC_REMOTE_BUTTON_STOP_FUNCTION: ++ break; ++ case CEC_REMOTE_BUTTON_MUTE_FUNCTION: ++ break; ++ case CEC_REMOTE_BUTTON_RESTORE_VOLUME_FUNCTION: ++ break; ++ case CEC_REMOTE_BUTTON_TUNE_FUNCTION: ++ break; ++ case CEC_REMOTE_BUTTON_SELECT_MEDIA_FUNCTION: ++ break; ++ case CEC_REMOTE_BUTTON_SELECT_AV_INPUT_FUNCTION: ++ break; ++ case CEC_REMOTE_BUTTON_SELECT_AUDIO_INPUT_FUNCTION: ++ break; ++ case CEC_REMOTE_BUTTON_POWER_TOGGLE_FUNCTION: ++ break; ++ case CEC_REMOTE_BUTTON_POWER_OFF_FUNCTION: ++ break; ++ case CEC_REMOTE_BUTTON_POWER_ON_FUNCTION: ++ break; ++ case CEC_REMOTE_BUTTON_F1_BLUE: ++ break; ++ case CEC_REMOTE_BUTTON_F2_RED: ++ break; ++ case CEC_REMOTE_BUTTON_F3_GREEN: ++ break; ++ case CEC_REMOTE_BUTTON_F4_YELLOW: ++ break; ++ case CEC_REMOTE_BUTTON_F5: ++ break; ++ case CEC_REMOTE_BUTTON_DATA: ++ break; ++ default: ++ fa.FeatureOpcode=frame->data[0]; ++ fa.AbortReason=CEC_ABORT_INVALID_OPERAND; ++ printf("Send feature abort::invalid operand in user control pressed\n"); ++ IO_CEC(FEATURE_ABORT,&fa); ++ break; ++ } ++ break; ++ ++ case CEC_OPCODE_DECK_CONTROL: ++ switch (frame->data[1]) { ++ case CEC_DECK_CONTROL_WIND: /*!< Skip Forward / Wind */ ++ break; ++ case CEC_DECK_CONTROL_REWIND: /*!< Skip Reverse / Rewind */ ++ break; ++ case CEC_DECK_CONTROL_STOP: /*!< Stop */ ++ break; ++ case CEC_DECK_CONTROL_EJECT: /*!< Eject */ ++ break; ++ default: ++ fa.FeatureOpcode=frame->data[0]; ++ fa.AbortReason=CEC_ABORT_INVALID_OPERAND; ++ printf("Send feature abort::invalid operand in deck control\n"); ++ IO_CEC(FEATURE_ABORT,&fa); ++ break; ++ } ++ break; ++ ++ case CEC_OPCODE_DECK_STATUS: ++ switch (frame->data[1]) { ++ case CEC_DECK_INFO_PLAY: /*!< Play */ ++ break; ++ case CEC_DECK_INFO_RECORD: /*!< Record */ ++ break; ++ case CEC_DECK_INFO_PLAY_REVERSE: /*!< Play Reverse */ ++ break; ++ case CEC_DECK_INFO_STILL: /*!< Still */ ++ break; ++ case CEC_DECK_INFO_SLOW: /*!< Slow */ ++ break; ++ case CEC_DECK_INFO_SLOW_REVERSE: /*!< Slow Reverse */ ++ break; ++ case CEC_DECK_INFO_FAST_FORWARD: /*!< Fast Forward */ ++ break; ++ case CEC_DECK_INFO_FAST_REVERSE: /*!< Fast Reverse */ ++ break; ++ case CEC_DECK_INFO_NO_MEDIA: /*!< No Media */ ++ break; ++ case CEC_DECK_INFO_STOP: /*!< Stop */ ++ break; ++ case CEC_DECK_INFO_WIND: /*!< Skip Forward / Wind */ ++ break; ++ case CEC_DECK_INFO_REWIND: /*!< Skip Reverse / Rewind */ ++ break; ++ case CEC_DECK_INFO_ID_SEARCH_FORWARD: /*!< Index Search Forward */ ++ break; ++ case CEC_DECK_INFO_ID_SEARCH_REVERSE: /*!< Index Search Forward */ ++ break; ++ case CEC_DECK_INFO_OTHER_STATUS: /*!< Other Status */ ++ break; ++ default: ++ fa.FeatureOpcode=frame->data[0]; ++ fa.AbortReason=CEC_ABORT_INVALID_OPERAND; ++ printf("Send feature abort::invalid operand in deck status\n"); ++ IO_CEC(FEATURE_ABORT,&fa); ++ break; ++ } ++ break; ++ ++ ++ case CEC_OPCODE_USER_CONTROL_RELEASED: ++ break; ++ ++ default: ++ fa.FeatureOpcode=frame->data[0]; ++ fa.AbortReason=CEC_ABORT_UNKNOWN_OPCODE; ++ printf("Send feature abort::unknown opcode\n"); ++ IO_CEC(FEATURE_ABORT,&fa); ++ break; ++ } ++ } ++ } ++ else if (frame->service == CEC_TX_DONE) { ++ /* ack */ ++ } ++} ++ ++ ++void *rx_main( void *ptr ) { ++ ++ cec_frame frame; ++ memset(&frame,0,sizeof(cec_frame)); ++ ++ printf("%s is alive\n",__func__); ++ ++ /* another cec for event */ ++ if ((rx = open(cec_name, O_RDWR)) == -1) { ++ perror(cec_name); ++ oups("can not open hdmicec driver\n",0); ++ } ++ ++ /* main loop */ ++ while(frame.service!=CEC_RELEASE) { ++ IO_RX(WAIT_FRAME,&frame); ++ read_frame(&frame); ++ } ++ ++ close(rx); ++ pthread_exit(0); ++ ++ return NULL; ++} ++ ++/* ++ * ++ * Bench ++ * --------- ++ * CHAPTER 3 ++ * ++ */ ++ ++/* 0x001: driver open/close */ ++void bench0001(void) { ++ ++ unsigned long /* tda_power */ power; ++ ++ printf("%s\n",__func__); ++ ++ ++ /* ++ * init ++ */ ++ ++ if ((tx = open(tx_name, O_RDWR)) == -1) { ++ perror(tx_name); ++ oups("can not open hdmicec driver (evt mgr)\n",0); ++ } ++ ++ printf("Power on device\n"); ++ power = tmPowerOn; ++ IO_TX(SET_POWER,&power); ++ ++ if ((cec = open(cec_name, O_RDWR)) == -1) { ++ perror(cec_name); ++ oups("can not open hdmicec driver\n",0); ++ } ++ ++ IO_CEC(RX_ADDR,CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_1); ++ IO_CEC(POLLING_MSG,NULL); ++ ++ /* Create independent threads each of which will execute function */ ++ if (pthread_create( &rx_thread, NULL, rx_main, NULL)) { ++ oups("can not create rx_thread\n",0); ++ } ++ ++ /* ++ * idle ++ */ ++ ++ sleep(user_wait); ++ /* IO_CEC(ACTIVE_SRC,0); */ ++ /* IO_CEC(IMAGE_VIEW_ON,0); */ ++ ++ ++ /* ++ * deinit ++ */ ++ ++ /* stop rx_thread */ ++ printf("rx_thread release request\n"); ++ IO_CEC(BYEBYE,0); ++ pthread_join(rx_thread, NULL); ++ ++ /* bye bye */ ++ close(cec); ++ close(tx); ++} ++ ++/* 0x002: ... */ ++void bench0002(void) { ++ ++ printf("%s\n",__func__); ++ ++} ++ ++/* ++ * ++ * Entry point ++ * ----------- ++ * CHAPTER 4 ++ * ++ */ ++ ++int main(int argc, char *argv[]) { ++ ++ printf("tda_demo, %s, %s %s\n",TDA_DEMO_VERSION,__DATE__,__TIME__); ++ printf("any feedback welcome - andre.lepine@nxp.com\n"); ++ ++ user_wait = 3; ++ user_request=0xFFFF; ++ /* Check command line parameters and init framebuffer */ ++ if (argc > 1) user_request = strtol(argv[1],NULL,16); ++ if (argc > 2) user_wait = strtol(argv[2],NULL,16); ++ ++ printf("User request:%x user_wait:%d\n",user_request,user_wait); ++ ++ /* hook up our exit handler */ ++ signal(SIGINT|SIGTERM|SIGKILL|SIGQUIT, my_exit); ++ ++ /* ++ * BENCH ++ */ ++ printf("\nSW raster%s", \ ++ "\n---------\n"); ++ USERCHECK(0x01,bench0001()); ++ USERCHECK(0x02,bench0002()); ++ ++ /* ++ Exit with success ++ */ ++ print_usage(argv[0]); ++ raise(SIGTERM); ++ return 0; ++} +-- +1.7.9.5 + diff --git a/patches/hdmi/0002-Added-DT-binding-to-NXP-driver.patch b/patches/hdmi/0002-Added-DT-binding-to-NXP-driver.patch new file mode 100644 index 00000000..9331f60b --- /dev/null +++ b/patches/hdmi/0002-Added-DT-binding-to-NXP-driver.patch @@ -0,0 +1,38 @@ +From c1e297d7a7be68e95b65a4bfa7cfeec6cdb77d91 Mon Sep 17 00:00:00 2001 +From: Joel A Fernandes +Date: Thu, 15 Nov 2012 16:45:47 -0600 +Subject: [PATCH 2/6] Added DT binding to NXP driver + +Signed-off-by: Joel A Fernandes +--- + drivers/video/nxp/tda998x.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/video/nxp/tda998x.c b/drivers/video/nxp/tda998x.c +index 4b45e41..2864221 100755 +--- a/drivers/video/nxp/tda998x.c ++++ b/drivers/video/nxp/tda998x.c +@@ -1911,6 +1911,12 @@ static int this_i2c_remove(struct i2c_client *client) + * I2C client driver (backend) + * ----------------- + */ ++static const struct of_device_id tda988x_of_match[] = { ++ { .compatible = "nxp,tda988x", }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, tda988x_of_match); ++ + static const struct i2c_device_id this_i2c_id[] = { + { TX_NAME, 0 }, + { }, +@@ -1922,6 +1928,7 @@ static struct i2c_driver this_i2c_driver = { + .driver = { + .owner = THIS_MODULE, + .name = TX_NAME, ++ .of_match_table = tda988x_of_match + }, + .probe = this_i2c_probe, + .remove = this_i2c_remove, +-- +1.7.9.5 + diff --git a/patches/hdmi/0003-da8xx-fb-Add-timings-for-720x480-60.patch b/patches/hdmi/0003-da8xx-fb-Add-timings-for-720x480-60.patch new file mode 100644 index 00000000..be9ae20b --- /dev/null +++ b/patches/hdmi/0003-da8xx-fb-Add-timings-for-720x480-60.patch @@ -0,0 +1,38 @@ +From 3adb8fe9b9d405182986cdee34369c09f66438a0 Mon Sep 17 00:00:00 2001 +From: Joel A Fernandes +Date: Tue, 20 Nov 2012 11:17:33 -0600 +Subject: [PATCH 3/6] da8xx-fb: Add timings for 720x480@60 + +Signed-off-by: Joel A Fernandes +--- + drivers/video/da8xx-fb.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c +index 6d98184..91061e6 100644 +--- a/drivers/video/da8xx-fb.c ++++ b/drivers/video/da8xx-fb.c +@@ -312,6 +312,20 @@ static struct da8xx_panel known_lcd_panels[] = { + .pxl_clk = 30000000, + .invert_pxl_clk = 0, + }, ++ [6] = { ++ /* 1024 x 768 @ 60 Hz Reduced blanking VESA CVT 0.79M3-R */ ++ .name = "nxp-720x480@60", ++ .width = 720, ++ .height = 480, ++ .hfp = 15, ++ .hbp = 59, ++ .hsw = 61, ++ .vfp = 9, ++ .vbp = 30, ++ .vsw = 5, ++ .pxl_clk = 27027000, ++ .invert_pxl_clk = 0, ++ }, + }; + + /* Enable the Raster Engine of the LCD Controller */ +-- +1.7.9.5 + diff --git a/patches/hdmi/0004-video-Kconfig-Makefile-Add-new-Kconfig-for-old-drive.patch b/patches/hdmi/0004-video-Kconfig-Makefile-Add-new-Kconfig-for-old-drive.patch new file mode 100644 index 00000000..9c7cebff --- /dev/null +++ b/patches/hdmi/0004-video-Kconfig-Makefile-Add-new-Kconfig-for-old-drive.patch @@ -0,0 +1,52 @@ +From fc31a189adca594833210cb8cb92b8d847305932 Mon Sep 17 00:00:00 2001 +From: Joel A Fernandes +Date: Tue, 20 Nov 2012 14:14:27 -0600 +Subject: [PATCH 4/6] video/Kconfig+Makefile: Add new Kconfig for old driver + +Signed-off-by: Joel A Fernandes +--- + drivers/video/Kconfig | 2 ++ + drivers/video/Makefile | 2 ++ + drivers/video/nxp/Kconfig | 7 +++++++ + 3 files changed, 11 insertions(+) + create mode 100644 drivers/video/nxp/Kconfig + +diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig +index e7868d8..3dc4ae8 100644 +--- a/drivers/video/Kconfig ++++ b/drivers/video/Kconfig +@@ -2433,6 +2433,8 @@ source "drivers/video/omap2/Kconfig" + source "drivers/video/exynos/Kconfig" + source "drivers/video/backlight/Kconfig" + ++source "drivers/video/nxp/Kconfig" ++ + if VT + source "drivers/video/console/Kconfig" + endif +diff --git a/drivers/video/Makefile b/drivers/video/Makefile +index 0e13296..10e0642 100644 +--- a/drivers/video/Makefile ++++ b/drivers/video/Makefile +@@ -168,3 +168,5 @@ obj-$(CONFIG_FB_VIRTUAL) += vfb.o + + #video output switch sysfs driver + obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o ++ ++obj-$(CONFIG_NXP_TDA998X_OLD) += nxp/ +diff --git a/drivers/video/nxp/Kconfig b/drivers/video/nxp/Kconfig +new file mode 100644 +index 0000000..1315c5f +--- /dev/null ++++ b/drivers/video/nxp/Kconfig +@@ -0,0 +1,7 @@ ++config NXP_TDA998X_OLD ++ tristate "NXP TDA998X HDMI video display driver" ++ select REGMAP_I2C ++ depends on I2C ++ help ++ Say Y here if you want to support NXP's TDA998X HDMI driver ++ To compile this driver as a module, choose M here. +-- +1.7.9.5 + diff --git a/patches/hdmi/0005-am335x-bonelt-dts-Add-DT-node-to-probe-NXP-driver.patch b/patches/hdmi/0005-am335x-bonelt-dts-Add-DT-node-to-probe-NXP-driver.patch new file mode 100644 index 00000000..45e71c4c --- /dev/null +++ b/patches/hdmi/0005-am335x-bonelt-dts-Add-DT-node-to-probe-NXP-driver.patch @@ -0,0 +1,28 @@ +From 0065c3861d78e455876b6e08916d18c17704c71c Mon Sep 17 00:00:00 2001 +From: Joel A Fernandes +Date: Tue, 20 Nov 2012 14:18:08 -0600 +Subject: [PATCH 5/6] am335x-bonelt/dts: Add DT node to probe NXP driver + +Signed-off-by: Joel A Fernandes +--- + arch/arm/boot/dts/am335x-bonelt.dts | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/arm/boot/dts/am335x-bonelt.dts b/arch/arm/boot/dts/am335x-bonelt.dts +index 87257ac..037594d 100644 +--- a/arch/arm/boot/dts/am335x-bonelt.dts ++++ b/arch/arm/boot/dts/am335x-bonelt.dts +@@ -30,3 +30,10 @@ + ti,non-removable; + status = "okay"; + }; ++ ++&i2c0 { ++ tda998X@34 { ++ compatible = "nxp,tda988x"; ++ reg = <0x34>; ++ }; ++}; +-- +1.7.9.5 + diff --git a/patches/hdmi/0006-Add-capebus-override-and-pinmux-for-da8xx-dt.patch b/patches/hdmi/0006-Add-capebus-override-and-pinmux-for-da8xx-dt.patch new file mode 100644 index 00000000..b6354912 --- /dev/null +++ b/patches/hdmi/0006-Add-capebus-override-and-pinmux-for-da8xx-dt.patch @@ -0,0 +1,108 @@ +From 746ac312478efb531dc368d08eeaf496782273ca Mon Sep 17 00:00:00 2001 +From: Joel A Fernandes +Date: Wed, 21 Nov 2012 12:19:29 -0600 +Subject: [PATCH 6/6] Add capebus override and pinmux for da8xx-dt + +Capebus override is left for LT only, rest is kept in common +as there is an HDMI cape as well that could reuse in future. + +Signed-off-by: Joel A Fernandes +--- + arch/arm/boot/dts/am335x-bone-common.dtsi | 48 +++++++++++++++++++++++++++++ + arch/arm/boot/dts/am335x-bonelt.dts | 10 ++++++ + 2 files changed, 58 insertions(+) + +diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi +index 46d5f27..4bd1604 100644 +--- a/arch/arm/boot/dts/am335x-bone-common.dtsi ++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi +@@ -119,6 +119,32 @@ + >; + }; + ++ nxp_hdmi_cape_pins: nxp_hdmi_cape_pins { ++ pinctrl-single,pins = < ++ ++ 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xa4 0x08 /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xa8 0x08 /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xac 0x08 /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xb0 0x08 /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xb4 0x08 /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xb8 0x08 /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xbc 0x08 /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xc0 0x08 /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xc4 0x08 /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xc8 0x08 /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xcc 0x08 /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xd0 0x08 /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xd4 0x08 /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xd8 0x08 /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xdc 0x08 /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */ ++ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */ ++ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */ ++ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */ ++ >; ++ }; ++ + bone_geiger_cape_led_pins: pinmux_bone_geiger_cape_led_pins { + pinctrl-single,pins = < + 0xe4 0x07 /* lcd_hsync.gpio2_23, OUTPUT | MODE7 */ +@@ -267,6 +293,10 @@ + compatible = "bone-generic-cape"; + }; + ++ nxp_hdmi_capebus: cape@6 { ++ compatible = "bone-generic-cape"; ++ }; ++ + /* overrides; no EEPROM (prototyping) */ + // override@3 { + // compatible = "bone-capebus-slot-override"; +@@ -426,6 +456,24 @@ + slots = <&cape_eeprom_0 &cape_eeprom_1 &cape_eeprom_2 &cape_eeprom_3>; + }; + ++/* On-board NXP HDMI Part requires LCDC enabled which is currently ++ only registered using capebus infrastructure */ ++&nxp_hdmi_capebus { ++ board-name = "NXP HDMI on capebus"; ++ version@00A1 { ++ version = "00A1"; ++ dvi { ++ compatible = "da8xx-dt"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&nxp_hdmi_cape_pins>; ++ ++ ti,hwmods = "lcdc"; ++ disp-pll = <135000000>; ++ panel-type = "nxp-720x480@60"; ++ }; ++ }; ++}; ++ + &bone_dvi_cape { + board-name = "BeagleBone DVI-D CAPE"; + +diff --git a/arch/arm/boot/dts/am335x-bonelt.dts b/arch/arm/boot/dts/am335x-bonelt.dts +index 037594d..44814b4 100644 +--- a/arch/arm/boot/dts/am335x-bonelt.dts ++++ b/arch/arm/boot/dts/am335x-bonelt.dts +@@ -37,3 +37,13 @@ + reg = <0x34>; + }; + }; ++ ++&capebus { ++ override@0 { ++ board-name = "NXP HDMI on CapeBus"; ++ compatible = "bone-capebus-slot-override"; ++ slot = <1>; ++ version = "00A1"; ++ manufacturer = "Beagleboardtoys"; ++ }; ++}; +-- +1.7.9.5 + diff --git a/patches/hdmi/0007-nxp-Makefile-Undefine-TDA_CEC-we-don-t-use-CEC-featu.patch b/patches/hdmi/0007-nxp-Makefile-Undefine-TDA_CEC-we-don-t-use-CEC-featu.patch new file mode 100644 index 00000000..784d6a66 --- /dev/null +++ b/patches/hdmi/0007-nxp-Makefile-Undefine-TDA_CEC-we-don-t-use-CEC-featu.patch @@ -0,0 +1,29 @@ +From 1eeaa7d920fe69d50c938e9618c5c1fce9cb6224 Mon Sep 17 00:00:00 2001 +From: Joel A Fernandes +Date: Wed, 21 Nov 2012 13:59:09 -0600 +Subject: [PATCH] nxp:Makefile Undefine TDA_CEC, we don't use CEC features + +CEC code is forced as a module, lets exclude it from build because its +based on a prehistoric kernel and will break our build. + +Signed-off-by: Joel A Fernandes +--- + drivers/video/nxp/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/video/nxp/Makefile b/drivers/video/nxp/Makefile +index f583226..05dc816 100755 +--- a/drivers/video/nxp/Makefile ++++ b/drivers/video/nxp/Makefile +@@ -14,7 +14,7 @@ TDA_PLATFORM := ZOOMII + + #TDA_HDCP := 0 + TDA_HDCP := TMFL_HDCP_SUPPORT +-TDA_CEC := TDA9950 ++#TDA_CEC := TDA9950 + + # add this if INTERRUPT is wired, otherwise polling with timer is used + #EXTRA_CFLAGS += -DIRQ +-- +1.7.9.5 +