#!/bin/sh
#
# History:
#	2020/06/19 - [Yan Qucheng] created file
#
# Copyright (c) 2020 Ambarella International LP
#
# This file and its contents ("Software") are protected by intellectual
# property rights including, without limitation, U.S. and/or foreign
# copyrights. This Software is also the confidential and proprietary
# information of Ambarella International LP and its licensors. You may not use, reproduce,
# disclose, distribute, modify, or otherwise prepare derivative works of this
# Software or any portion thereof except pursuant to a signed license agreement
# or nondisclosure agreement with Ambarella International LP or its authorized affiliates.
# In the absence of such an agreement, you agree to promptly notify and return
# this Software to Ambarella International LP.
#
# This file includes sample code and is only for internal testing and evaluation.  If you
# distribute this sample code (whether in source, object, or binary code form), it will be
# without any warranty or indemnity protection from Ambarella International LP or its affiliates.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
# MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL AMBARELLA INTERNATIONAL LP OR ITS AFFILIATES BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; COMPUTER FAILURE OR MALFUNCTION; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#

version=$(grep AMBARELLA_CHIP < /proc/ambarella/iav | sed 's/^.*=//g')

help_message(){
	printf "==== HELP ====\n"
	printf "Usage: power_pdev.sh [--all]\n"
	printf "\t--all\t\tdisable all options\n"
	printf "\t--vout\t\tdisable vout\n"
	printf "\t--hevc\t\tdisable hevc\n"
	printf "\t--hdmi\t\tdisable hdmi\n"
	printf "\t--cvbs\t\tdisable cvbs\n"
	printf "\t--gpio\t\treset gpio\n"
	printf "\t--cv\t\tdisable cv\n"
	printf "\t--usb\t\tdisable usb\n"
	printf "\t--sd\t\tdisable sd\n"
	printf "\nNOTE: this script is ONLY for debug purpose.\n"
}

version_check(){
	var=$1
	if [ "$var" != S5L ]&&[ "$var" != S5Lm ]&&[ "$var" != S6LM ]&&[ "$var" != CV2 ]&&[ "$var" != CV22 ]&&[ "$var" != CV25 ]&&[ "$var" != CV25m ]&&[ "$var" != CV28M ]; then
		printf "Could not support version %s\n" "$var"
		return 1
	else
		return 0
	fi
}

disable_vout(){
	if [ "$version" = "S5L" ]||[ "$version" = "S5Lm" ]; then
		printf "==== reset whole vout ====\n"
		devmem 0xec170164 32 0x00200020
		sleep 0.5
		printf "[0xec170164] w: 0x00200020 r: 0x%x\n" "$(devmem 0xec170164)"

		devmem 0xec1701c0 32 0x00200020
		sleep 0.5
		printf "[0xec1701c0] w: 0x00200020 r: 0x%x\n" "$(devmem 0xec1701c0)"
	else
		printf "==== reset whole vout ====\n"
		devmem 0xe0008a00 32 0x80000000
		sleep 0.5
		printf "[0xe0008a00] w: 0x80000000 r: 0x%x\n" "$(devmem 0xe0008a00)"

		printf "==== disable clock for displayA ====\n"
		devmem 0xe0008a04 32 0x0
		sleep 0.5
		printf "[0xe0008a04] w: 0x0 r: 0x%x\n" "$(devmem 0xe0008a04)"

		printf "==== disable clock for displayB ====\n"
		devmem 0xe0008a08 32 0x0
		sleep 0.5
		printf "[0xe0008a08] w: 0x0 r: 0x%x\n" "$(devmem 0xe0008a08)"

		printf "==== disable clock for osd rescaler ====\n"
		devmem 0xe0008a0c 32 0x0
		sleep 0.5
		printf "[0xe0008a0c] w: 0x0 r: 0x%x\n" "$(devmem 0xe0008a0c)"

		printf "==== clock gate for smem ====\n"
		devmem 0xe0008a10 32 0x1
		sleep 0.5
		printf "[0xe0008a10] w: 0x1 r: 0x%x\n" "$(devmem 0xe0008a10)"

		printf "==== clock gate for configuration ====\n"
		devmem 0xe0008a14 32 0x1
		sleep 0.5
		printf "[0xe0008a14] w: 0x1 r: 0x%x\n" "$(devmem 0xe0008a14)"

		printf "==== clock gate for mixer ====\n"
		devmem 0xe0008a18 32 0x1
		sleep 0.5
		printf "[0xe0008a18] w: 0x1 r: 0x%x\n" "$(devmem 0xe0008a18)"
	fi
}

disable_usb(){
	printf "==== power down usb phy ====\n"
	if [ "$version" = "S5L" ]||[ "$version" = "S5Lm" ]; then
		devmem 0xec170050 32 0x00003026
		sleep 0.5
	else
		devmem 0xed080050 32 0x00003026
		sleep 0.5
		printf "[0xed080050] w: 0x00003026 r: 0x%x\n" "$(devmem 0xed080050)"
	fi
}

disable_cvbs(){
	printf "==== disable cvbs ====\n"
	if [ "$version" = "S5L" ]||[ "$version" = "S5Lm" ]; then
		devmem 0xec170688 32 0x40000000
		sleep 0.5

		printf "==== power down adc ====\n"
		devmem 0xec170198 32 0x00000002
		sleep 0.5
	else
		devmem 0xed080688 32 0x40000000
		sleep 0.5
		printf "[0xed080688] w: 0x40000000 r: 0x%x\n" "$(devmem 0xed080688)"

		printf "==== power down adc ====\n"
		devmem 0xed080198 32 0x00000002
		sleep 0.5
		printf "[0xed080198] w: 0x00000002 r: 0x%x\n" "$(devmem 0xed080198)"
	fi
}

disable_cv(){
	if [ "$version" = "S5L" ]||[ "$version" = "S5Lm" ]||[ "$version" = "S6LM" ]; then
		printf "This option not support S5L and S6LM yet\n"
		return 1
	fi
	printf "==== clock gate for vision ====\n"
	devmem 0xed0806e4 32 0x2f130020
	sleep 0.5
	printf "[0xed0806e4] w: 0x2f130020 r: 0x%x\n" "$(devmem 0xed0806e4)"
}

pull_ext_gpio(){
	if [ "$version" = "CV2" ]; then
		devmem 0xec001080 32 0xffffffff
		sleep 0.5
		printf "[0xec001080] w: 0xffffffff r: 0x%x\n" "$(devmem 0xec001080)"

		devmem 0xec001084 32 0xffffffff
		sleep 0.5
		printf "[0xec001084] w: 0xffffffff r: 0x%x\n" "$(devmem 0xec001084)"

		devmem 0xec001088 32 0xffffffff
		sleep 0.5
		printf "[0xec001088] w: 0xffffffff r: 0x%x\n" "$(devmem 0xec001088)"

		devmem 0xec00108C 32 0xffffffff
		sleep 0.5
		printf "[0xec00108C] w: 0xffffffff r: 0x%x\n" "$(devmem 0xec00108C)"

		devmem 0xec001090 32 0xffffffff
		sleep 0.5
		printf "[0xec001090] w: 0xffffffff r: 0x%x\n" "$(devmem 0xec001090)"
	fi

	if [ "$version" = "CV25" ]; then
		devmem 0xe0022014 32 0xffffffff
		sleep 0.5
		printf "[0xe0022014] w: 0xffffffff r: 0x%x\n" "$(devmem 0xe0022014)"

		devmem 0xe0022018 32 0xffffffff
		sleep 0.5
		printf "[0xe0022018] w: 0xffffffff r: 0x%x\n" "$(devmem 0xe0022018)"

		devmem 0xe002201c 32 0xffffffff
		sleep 0.5
		printf "[0xe002201c] w: 0xffffffff r: 0x%x\n" "$(devmem 0xe002201c)"

		devmem 0xe0022020 32 0xffffffff
		sleep 0.5
		printf "[0xe0022020] w: 0xffffffff r: 0x%x\n" "$(devmem 0xe0022020)"
	fi

	if [ "$version" = "CV22" ]; then
		devmem 0xe0022014 32 0xffffffff
		sleep 0.5
		printf "[0xe0022014] w: 0xffffffff r: 0x%x\n" "$(devmem 0xe0022014)"

		devmem 0xe0022018 32 0xffffffff
		sleep 0.5
		printf "[0xe0022018] w: 0xffffffff r: 0x%x\n" "$(devmem 0xe0022018)"

		devmem 0xe002201c 32 0xffffffff
		sleep 0.5
		printf "[0xe002201c] w: 0xffffffff r: 0x%x\n" "$(devmem 0xe002201c)"

		devmem 0xe0022020 32 0xffffffff
		sleep 0.5
		printf "[0xe0022020] w: 0xffffffff r: 0x%x\n" "$(devmem 0xe0022020)"

		devmem 0xe0022024 32 0xffffffff
		sleep 0.5
		printf "[0xe0022024] w: 0xffffffff r: 0x%x\n" "$(devmem 0xe0022024)"
	fi

	if [ "$version" = "S6LM" ]; then
		devmem 0xe0022014 32 0xffffffff
		sleep 0.5
		printf "[0xe0022014] w: 0xffffffff r: 0x%x\n" "$(devmem 0xe0022014)"

		devmem 0xe0022018 32 0xffffffff
		sleep 0.5
		printf "[0xe0022018] w: 0xffffffff r: 0x%x\n" "$(devmem 0xe0022018)"

		devmem 0xe002201c 32 0xffffffff
		sleep 0.5
		printf "[0xe002201c] w: 0xffffffff r: 0x%x\n" "$(devmem 0xe002201c)"
	fi
}

reset_gpio(){
	if [ "$version" = "S5L" ]||[ "$version" = "S5Lm" ]; then
		printf "This option not support S5L yet\n"
		return 1
	fi

	printf "==== make sure GPIOs not driven be pulled up/down externally ====\n"
	pull_ext_gpio

	printf "==== set all GPIO driving strength to 2mA ====\n"
	devmem 0xed080314 32 0x0
	sleep 0.5
	printf "[0xed080314] w: 0x0 r: 0x%x\n" "$(devmem 0xed080314)"

	devmem 0xed080318 32 0x0
	sleep 0.5
	printf "[0xed080318] w: 0x0 r: 0x%x\n" "$(devmem 0xed080318)"

	devmem 0xed08031c 32 0x0
	sleep 0.5
	printf "[0xed08031c] w: 0x0 r: 0x%x\n" "$(devmem 0xed08031c)"

	devmem 0xed080320 32 0x0
	sleep 0.5
	printf "[0xed080320] w: 0x0 r: 0x%x\n" "$(devmem 0xed080320)"

	devmem 0xed080324 32 0x0
	sleep 0.5
	printf "[0xed080324] w: 0x0 r: 0x%x\n" "$(devmem 0xed080324)"

	devmem 0xed080328 32 0x0
	sleep 0.5
	printf "[0xed080328] w: 0x0 r: 0x%x\n" "$(devmem 0xed080328)"

	devmem 0xed08032c 32 0x0
	sleep 0.5
	printf "[0xed08032c] w: 0x0 r: 0x%x\n" "$(devmem 0xed08032c)"

	devmem 0xed080330 32 0x0
	sleep 0.5
	printf "[0xed080330] w: 0x0 r: 0x%x\n" "$(devmem 0xed080330)"

	devmem 0xed080438 32 0x0
	sleep 0.5
	printf "[0xed080438] w: 0x0 r: 0x%x\n" "$(devmem 0xed080438)"

	devmem 0xed08043c 32 0x0
	sleep 0.5
	printf "[0xed08043c] w: 0x0 r: 0x%x\n" "$(devmem 0xed08043c)"

	devmem 0xed080450 32 0x0
	sleep 0.5
	printf "[0xed080450] w: 0x0 r: 0x%x\n" "$(devmem 0xed080450)"

	devmem 0xed080454 32 0x0
	sleep 0.5
	printf "[0xed080454] w: 0x0 r: 0x%x\n" "$(devmem 0xed080454)"
}

disable_comparator_mipi(){
	printf "==== disable N-type comparator in mipi dphy ====\n"
	if [ "$version" = "S5L" ]||[ "$version" = "S5Lm" ]; then
		devmem 0xec17057c 32 0x0401
		sleep 0.5
	else
		devmem 0xed200014 32 0x60141000
		sleep 0.5
		printf "[0xed200014] w: 0x60141000 r: 0x%x\n" "$(devmem 0xed200014)"
	fi
}

disable_hevc(){
	printf "==== RUN AVC disable DSP HEVC STATE REG ====\n"
	if [ "$version" = "S5L" ]||[ "$version" = "S5Lm" ]; then
		devmem 0xec17008c 32 0x37df
		sleep 0.5
		printf "[0xec17008c] w: 0x37df r: 0x%x\n" "$(devmem 0xec17008c)"
	else
		devmem 0xed08008c 32 0xfff3fff
		sleep 0.5
		printf "[0xed08008c] w: 0xfff3fff r: 0x%x\n" "$(devmem 0xed08008c)"
	fi
}

disable_sd(){
	printf "==== powering down the SD PLL ====\n"
	if [ "$version" = "S5L" ]||[ "$version" = "S5Lm" ]; then
		devmem 0xec1704ac 32 0x09001021
		sleep 0.5
		devmem 0xec1704ac 32 0x09001020
		sleep 0.5
	else
		devmem 0xed0804ac 32 0x20
		sleep 0.5
		printf "[0xed0804ac] w: 0x20 r: 0x%x\n" "$(devmem 0xed0804ac)"
	fi
}

disable_video2(){
	printf "==== powering down the Video2  PLL ====\n"
	if [ "$version" = "S5L" ]||[ "$version" = "S5Lm" ]; then
		devmem 0xec1700c0 32 0x01078021
		sleep 0.5
		devmem 0xec1700c0 32 0x01078020
		sleep 0.5
	else
		devmem 0xed0800c0 32 0x20
		sleep 0.5
		printf "[0xed0800c0] w: 0x20 r: 0x%x\n" "$(devmem 0xed0800c0)"
	fi
}

disable_hdmi(){
	printf "==== powering down the HDMI PLL ====\n"
	if [ "$version" = "S5L" ]||[ "$version" = "S5Lm" ]; then
		devmem 0xec170008 32 0x0c
		sleep 0.5
		devmem 0xec170164 32 0x08034021
		sleep 0.5
		devmem 0xec170164 32 0x08034020
		sleep 0.5
	else
		devmem 0xed080164 32 0x20
		sleep 0.5
		printf "[0xed080164] w: 0x20 r: 0x%x\n" "$(devmem 0xed080164)"
	fi
}

hardware_enable(){
	opt_help=0
	opt_all=0
	opt_vout=0
	opt_hdmi=0
	opt_cv=0
	opt_gpio=0
	opt_sd=0
	opt_usb=0
	opt_cvbs=0
	opt_hevc=0

	if [ $# -eq 0 ]; then
		help_message
	fi

	ARGS=$(getopt -l all,vout,hevc,hdmi,cvbs,sd,usb,cv,gpio,help -n 'poweroff_pdev.sh' -- h "$@")
	if [ $? != 0 ]; then
		printf "Getopt failed.\n"
		exit 1
	fi

	eval set -- "${ARGS}"

	while true
	do
		case "$1" in
			--all)
				opt_all=1
				shift
				;;
			--vout)
				opt_vout=1
				shift
				;;
			--hevc)
				opt_hevc=1
				shift
				;;
			--hdmi)
				opt_hdmi=1
				shift
				;;
			--cvbs)
				opt_cvbs=1
				shift
				;;
			--sd)
				opt_sd=1
				shift
				;;
			--usb)
				opt_usb=1
				shift
				;;
			--cv)
				opt_cv=1
				shift
				;;
			--gpio)
				opt_gpio=1
				shift
				;;
			-h|--help)
				opt_help=1
				shift
				;;
			--)
				shift
				break
				;;
			*)
				printf "Invalid args %s\n" "$1"
				exit 1
				;;
		esac
	done

	if [ $opt_help -eq 1 ]; then
		help_message
	elif [ $opt_all -eq 1 ]; then
		disable_vout
		disable_hevc
		disable_usb
		disable_cvbs
		reset_gpio
		disable_comparator_mipi
		disable_sd
		disable_video2
		disable_hdmi
		if [ "$version" != "S5L" ]&&[ "$version" != "S5Lm" ]&&[ "$version" != "S6LM" ]; then
			disable_cv
		fi
	else
		if [ $opt_vout -eq 1 ]; then
			disable_vout
		fi
		if [ $opt_hevc -eq 1 ]; then
			disable_hevc
		fi
		if [ $opt_hdmi -eq 1 ]; then
			disable_hdmi
		fi
		if [ $opt_cvbs -eq 1 ]; then
			disable_cvbs
		fi
		if [ $opt_sd -eq 1 ]; then
			disable_sd
		fi
		if [ $opt_usb -eq 1 ]; then
			disable_usb
		fi
		if [ $opt_cv -eq 1 ]; then
			disable_cv
		fi
		if [ $opt_gpio -eq 1 ]; then
			reset_gpio
		fi
	fi
}

version_check "$version"
if [ $? -eq 0 ]; then
	printf "Current version: %s\n" "$version"
	hardware_enable "$@"
fi
printf "==== Done ====\n"

