#!/bin/sh
#
# This is part of OpenIPC.org project | 2020.08.01
#
# ar0237 imx290 imx307 imx323 imx385 jxf22 ov2718 ov2718_2a sc2235


# SoC detect
chipid=$(ipctool --chip_id)

# MMZ config
mem_start=0x80000000;                             # phy mem start

mem_total=$(awk -F '=' '$1=="totalmem"{print $2}' RS=" " /proc/cmdline | tr -d 'M')
mem_total=${mem_total:=64}

os_mem_size=$(awk -F '=' '$1=="mem"{print $2}' RS=" " /proc/cmdline | tr -d 'M')
os_mem_size=${os_mem_size:=32}

report_error()
{
        echo "******* Error: There's something wrong, please check! *****"
        exit 1
}

insert_mmz()
{
        insmod mmz.ko mmz=anonymous,0,$mmz_start,$mmz_size anony=1 || report_error
}

insert_detect()
{
        cd /lib/modules/4.9.37/hisilicon
        insmod sys_config.ko vi_vpss_online=$b_arg_online sensor=unknown pin_mux_select=0 
        insert_mmz
        insmod hi_media.ko
        insmod hi3518e_base.ko
        insmod hi3518e_sys.ko vi_vpss_online=$b_arg_online sensor=unknown mem_total=$mem_total
        insert_isp
        insmod sensor_i2c.ko
        insmod sensor_spi.ko
        SENSOR=ar0130 insert_sns
        ipcinfo -s
}

remove_detect()
{
        rmmod sensor_spi
        rmmod sensor_i2c
        rmmod hi3518e_isp
        rmmod hi3518e_sys
        rmmod hi3518e_base
        rmmod hi_media
        rmmod mmz
        rmmod sys_config.ko
}

insert_audio()
{
        insmod acodec.ko
        insmod hi3518e_aio.ko
        insmod hi3518e_ai.ko
        insmod hi3518e_ao.ko
        insmod hi3518e_aenc.ko
        insmod hi3518e_adec.ko
        #insmod extdrv/tlv_320aic31.ko 
        echo "insert audio"
}

remove_audio()
{
        rmmod tlv_320aic31.ko
        rmmod hi3518e_adec
        rmmod hi3518e_aenc
        rmmod hi3518e_ao
        rmmod hi3518e_ai
        rmmod hi3518e_aio
        rmmod acodec
        echo "remove audio"
}

remove_sns()
{
        rmmod sensor_spi &> /dev/null
        rmmod sensor_i2c &> /dev/null
}

insert_isp()
{
    case $SENSOR in
        ov9750)
            insmod hi3518e_isp.ko update_pos=1;
            ;;
        *)
            insmod hi3518e_isp.ko update_pos=0 proc_param=1;
            ;;
    esac
}

insert_sns()
{
        case $SENSOR in
                ar0130|9m034)
                        devmem 0x200f0040 32 0x2;                            # I2C0_SCL
                        devmem 0x200f0044 32 0x2;                            # I2C0_SDA
 
                        #cmos pinmux
                        devmem 0x200f007c 32 0x1;                            # VI_DATA13
                        devmem 0x200f0080 32 0x1;                            # VI_DATA10
                        devmem 0x200f0084 32 0x1;                            # VI_DATA12
                        devmem 0x200f0088 32 0x1;                            # VI_DATA11
                        devmem 0x200f008c 32 0x2;                            # VI_VS
                        devmem 0x200f0090 32 0x2;                            # VI_HS
                        devmem 0x200f0094 32 0x1;                            # VI_DATA9

                        devmem 0x2003002c 32 0xc4001;                        # sensor unreset, clk 24MHz, VI 99MHz
                        ;;

		sc1135|sc1145|sc2135)
			devmem 0x200f0040 32 0x2;	# I2C0_SCL
			devmem 0x200f0044 32 0x2;	# I2C0_SDA
			# Cmos pinmux
			devmem 0x200f007c 32 0x1;	# VI_DATA13
			devmem 0x200f0080 32 0x1;	# VI_DATA10
			devmem 0x200f0084 32 0x1;	# VI_DATA12
			devmem 0x200f0088 32 0x1;	# VI_DATA11
			devmem 0x200f008c 32 0x2;	# VI_VS
			devmem 0x200f0090 32 0x2;	# VI_HS
			devmem 0x200f0094 32 0x1;	# VI_DATA9
			devmem 0x2003002c 32 0xb4001;	# clk 27MHz, VI 99MHz
			;;

                sc2235)
                        devmem 0x200f0040 32 0x2;                            # I2C0_SCL
                        devmem 0x200f0044 32 0x2;                            # I2C0_SDA
 
                        #cmos pinmux
                        devmem 0x200f007c 32 0x1;                            # VI_DATA13
                        devmem 0x200f0080 32 0x1;                            # VI_DATA10
                        devmem 0x200f0084 32 0x1;                            # VI_DATA12
                        devmem 0x200f0088 32 0x1;                            # VI_DATA11
                        devmem 0x200f008c 32 0x2;                            # VI_VS
                        devmem 0x200f0090 32 0x2;                            # VI_HS
                        devmem 0x200f0094 32 0x1;                            # VI_DATA9

                        devmem 0x2003002c 32 0xc4001;                        # sensor unreset, clk 24MHz, VI 99MHz
                        ;;
                *)
                        echo "xxxx Invalid sensor type $SENSOR xxxx"
                        report_error;;
        esac
}
insert_ko()
{
        # sys config
        insmod sys_config.ko vi_vpss_online=$b_arg_online sensor=$SENSOR pin_mux_select=0 

        # driver load
        insert_mmz;
        #insmod mmz.ko mmz=anonymous,0,$mmz_start,$mmz_size anony=1 || report_error
        insmod hi_media.ko
        insmod hi3518e_base.ko

        insmod hi3518e_sys.ko vi_vpss_online=$b_arg_online sensor=$SENSOR mem_total=$mem_total
        if [[ $? -ne 0 ]]; then 
                exit;
        fi

        insmod hi3518e_tde.ko
        insmod hi3518e_region.ko
        insmod hi3518e_vgs.ko

        insert_isp;
        insmod hi3518e_viu.ko detect_err_frame=10;
        insmod hi3518e_vpss.ko rfr_frame_comp=1;
        insmod hi3518e_vou.ko
        #insmod hi3518e_vou.ko transparentTransmit=1 #enable transparentTransmit
        #insmod hifb.ko video="hifb:vram0_size:1620"     # default pal

        insmod hi3518e_rc.ko
        insmod hi3518e_venc.ko 
        insmod hi3518e_chnl.ko ChnlLowPower=1
        insmod hi3518e_h264e.ko H264eMiniBufMode=1
        insmod hi3518e_jpege.ko
        insmod hi3518e_ive.ko save_power=0;
#       insmod hi3518e_ive.ko
        insmod sensor_i2c.ko
        insmod pwm.ko
        insmod piris.ko
        insert_sns
        insert_audio

        insmod hi_mipi.ko
        echo "==== Your input Sensor type is $SENSOR ===="
}

remove_ko()
{
        rmmod sys_config.ko
        remove_audio
        remove_sns

        rmmod pwm

        rmmod hi3518e_ive

        rmmod hi3518e_rc
        rmmod hi3518e_jpege
        rmmod hi3518e_h264e
        rmmod hi3518e_chnl
        rmmod hi3518e_venc

        rmmod hifb
        rmmod hi3518e_vou
        rmmod hi3518e_vpss
        rmmod hi3518e_viu
        rmmod hi_mipi

        rmmod hi3518e_vgs
        rmmod hi3518e_region
        rmmod hi3518e_tde

        rmmod piris
        rmmod hi3518e_isp
        rmmod hi3518e_sys
        rmmod hi3518e_base
        rmmod hi_media
        rmmod mmz
}

load_usage()
{
        echo "Usage:  ./load3518e [-option] [sensor_name]"
        echo "options:"
        echo "    -i                       insert modules"
        echo "    -r                       remove modules"
        echo "    -a                       remove modules first, then insert modules"
        echo "    -sensor sensor_name      config sensor type [default: ar0230]"
        echo "    -osmem os_mem_size       config os mem size [unit: M, default: 32]"
        echo "    -total_mem_size          config total mem size [unit: M, default: 64]"
        echo "    -offline                 vi/vpss offline"
        echo "    -h                       help information"
        echo -e "Available sensors: imx222 9m034 ov9752 ar0230 ar0130 ov9712 mn34222"
        echo -e "notes: osmem option can't be used when mmz zone partition is enable\n\n"
        echo -e "for example online:   ./load3518e -a -sensor ar0230 -osmem 32 -total 64\n"
        echo -e "            offline:  ./load3518e -a -sensor ar0230 -osmem 32 -total 64 -offline\n"
}

calc_mmz_info()
{
        mmz_start=`echo "$mem_start $os_mem_size" | 
        awk 'BEGIN { temp = 0; }
        {
                temp = $1/1024/1024 + $2;
        } 
        END { printf("0x%x00000\n", temp); }'`

        mmz_size=`echo "$mem_total $os_mem_size" | 
        awk 'BEGIN { temp = 0; }
        {
                temp = $1 - $2;
        } 
        END { printf("%dM\n", temp); }'`
        echo "mmz_start: $mmz_start, mmz_size: $mmz_size"
}


######################parse arg###################################
b_arg_os_mem=0
b_arg_total_mem=0
b_arg_sensor=0
b_arg_insmod=0
b_arg_remove=0
b_arg_online=1

for arg in $@
do
        if [ $b_arg_total_mem -eq 1 ]; then
                b_arg_total_mem=0;
                mem_total=$arg;

                if [ -z $mem_total ]; then
                        echo "[error] mem_total is null"
                        exit;
                fi
        fi

        if [ $b_arg_os_mem -eq 1 ] ; then
                b_arg_os_mem=0;
                os_mem_size=$arg;

                if [ -z $os_mem_size ]; then
                        echo "[error] os_mem_size is null"
                        exit;
                fi
        fi

        if [ $b_arg_sensor -eq 1 ] ; then
                b_arg_sensor=0
                SENSOR=$arg;
        fi

        case $arg in
                "-i")
                        b_arg_insmod=1;
                        ;;
                "-r")
                        b_arg_remove=1;
                        ;;
                "-a")
                        b_arg_insmod=1;
                        b_arg_remove=1;
                        ;;
                "-h")
                        load_usage;
                        ;;
                "-sensor")
                        b_arg_sensor=1;
                        ;;
                "-osmem")
                        b_arg_os_mem=1;
                        ;;
                "-total")
                        b_arg_total_mem=1;
                        ;;
                "-offline")
                        b_arg_online=0;
                        ;;
        esac
done
#######################parse arg end########################

if [ $os_mem_size -ge $mem_total ] ; then
        echo "[err] os_mem[$os_mem_size], over total_mem[$mem_total]"
        exit;
fi

calc_mmz_info;

#######################Action###############################

if [ $# -lt 1 ]; then
    load_usage;
    exit 0;
fi

# Sensor config
# SENSOR=${SENSOR:=imx307}
#

if [ -n "$SENSOR" ]; then
        logger -s -p daemon.info -t hisilicon "Manualy set SENSOR as ${SENSOR}"
else
        if fw_printenv -n sensor >/dev/null; then
                SENSOR_ENV=$(fw_printenv -n sensor)
                export SENSOR=${SENSOR_ENV}
                logger -s -p daemon.info -t hisilicon "Get data from environment and set SENSOR as ${SENSOR}"
        else
                insert_detect
                SENSOR_DETECT=$(ipcinfo -s)
                export SENSOR=${SENSOR_DETECT:=unknown}
                remove_detect
                logger -s -p daemon.info -t hisilicon "Get data from ipcinfo and set SENSOR as ${SENSOR}"
                fw_setenv sensor $SENSOR && logger -s -p daemon.info -t hisilicon "Write detected ${SENSOR} to U-Boot ENV"
        fi
fi

if [ $b_arg_remove -eq 1 ]; then
        remove_ko;
fi

if [ "$SENSOR" = "unknown" ]; then
        exit 1
else
        if [ $b_arg_insmod -eq 1 ]; then
                cd /lib/modules/4.9.37/hisilicon
                insert_ko;
        fi
fi