#!/bin/bash
{
	#////////////////////////////////////
	# DietPi CPU Gov Script
	#
	#////////////////////////////////////
	# Created by Daniel Knight / daniel.knight@dietpi.com / dietpi.com
	#
	#////////////////////////////////////
	#
	# Info:
	# - Runs at boot up /DietPi/dietpi/boot
	# - Sets CPU governor | ondemand | powersave | performance etc
	# - Sets CPU governor user prefs | throttle up percent etc
	#////////////////////////////////////

	#Import DietPi-Globals ---------------------------------------------------------------
	. /DietPi/dietpi/func/dietpi-globals
	G_CHECK_ROOT_USER
	export G_PROGRAM_NAME='DietPi-CPU_set'
	#Import DietPi-Globals ---------------------------------------------------------------

	#Exit path for VM
	if (( $G_HW_MODEL == 20 )); then

		echo -e "\nNotice: CPU Governors are not available for VM.\n"
		exit

	fi

	CPU_GOVERNOR=$(cat /DietPi/dietpi.txt | grep -m1 '^CONFIG_CPU_GOVERNOR=' | sed 's/.*=//')
	CPU_MAX_FREQ=$(cat /DietPi/dietpi.txt | grep -m1 '^CONFIG_CPU_MAX_FREQ=' | sed 's/.*=//')
	CPU_MIN_FREQ=$(cat /DietPi/dietpi.txt | grep -m1 '^CONFIG_CPU_MIN_FREQ=' | sed 's/.*=//')

	Check_GPU_Gov_Available(){

		#Check if target Gov is available on system.
		if (( ! $(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors | grep -ci -m1 "$CPU_GOVERNOR") )); then

			G_DIETPI-NOTIFY 1 "CPU gov: $CPU_GOVERNOR, not supported by kernel"

			if (( $(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors | grep -ci -m1 'ondemand') )); then

				CPU_GOVERNOR='ondemand'

			elif (( $(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors | grep -ci -m1 'interactive') )); then

				CPU_GOVERNOR='interactive'

			else

				CPU_GOVERNOR='performance'

			fi

			G_DIETPI-NOTIFY 2 "Switching to CPU gov: $CPU_GOVERNOR"

			# - Update dietpi.txt
			sed -i "/^CONFIG_CPU_GOVERNOR=/c\CONFIG_CPU_GOVERNOR=$CPU_GOVERNOR" /DietPi/dietpi.txt

		fi

	}

	Apply_CPU_Gov(){

		local input_gov_name=$1
		local input_core_start=$2
		local input_core_end=$3

		#Apply the Gov
		for ((i=$input_core_start; i<$input_core_end; i++))
		do
			echo "$input_gov_name" > /sys/devices/system/cpu/cpu"$i"/cpufreq/scaling_governor
		done

		#Apply CPU max frequency (if set)
		if [[ $CPU_MAX_FREQ =~ ^-?[0-9]+$ ]] &&
			(( $CPU_MAX_FREQ > 0 )); then

			local converted_hz_value=$(( $CPU_MAX_FREQ * 1000 ))

			for ((i=$input_core_start; i<$input_core_end; i++))
			do

				echo "$converted_hz_value" > /sys/devices/system/cpu/cpu"$i"/cpufreq/scaling_max_freq

			done

			G_DIETPI-NOTIFY 2 "Setting CPU max freq: $CPU_MAX_FREQ MHz"

		fi

		#Apply CPU min frequency (if set)
		if [[ $CPU_MIN_FREQ =~ ^-?[0-9]+$ ]] &&
			(( $CPU_MIN_FREQ > 0 )); then

			local converted_hz_value=$(( $CPU_MIN_FREQ * 1000 ))

			for ((i=$input_core_start; i<$input_core_end; i++))
			do

				echo "$converted_hz_value" > /sys/devices/system/cpu/cpu"$i"/cpufreq/scaling_min_freq

			done

			G_DIETPI-NOTIFY 2 "Setting CPU min freq: $CPU_MIN_FREQ MHz"

		fi

		local cpu_throttle_up_percent=$(cat /DietPi/dietpi.txt | grep -m1 '^CONFIG_CPU_USAGE_THROTTLE_UP=' | sed 's/.*=//')

		#Set CPU governor interactive settings
		if [ "$input_gov_name" = interactive ]; then

			#Set hispeed_load, if available on system (eg: XU4 kernel lacks this feature)
			if [ -f /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load ]; then

				G_DIETPI-NOTIFY 2 "Setting go_hispeed_load: $cpu_throttle_up_percent %"
				echo "$cpu_throttle_up_percent" > /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load

			fi

		#Set CPU governor ondemand settings
		elif [ "$input_gov_name" = ondemand ]; then

			local cpu_ondemand_sampling_rate=$(cat /DietPi/dietpi.txt | grep -m1 '^CONFIG_CPU_ONDEMAND_SAMPLE_RATE=' | sed 's/.*=//')
			local cpu_ondemand_sampling_down_factor=$(cat /DietPi/dietpi.txt | grep -m1 '^CONFIG_CPU_ONDEMAND_SAMPLE_DOWNFACTOR=' | sed 's/.*=//')

			G_DIETPI-NOTIFY 2 "Setting up_threshold: $cpu_throttle_up_percent %"
			G_DIETPI-NOTIFY 2 "Setting sampling_rate: $cpu_ondemand_sampling_rate microseconds"
			G_DIETPI-NOTIFY 2 "Setting sampling_down_factor: $cpu_ondemand_sampling_down_factor"

			#Check for different possible locations
			#	All
			if [ -f /sys/devices/system/cpu/cpufreq/ondemand/up_threshold ]; then

				echo "$cpu_throttle_up_percent" > /sys/devices/system/cpu/cpufreq/ondemand/up_threshold
				echo "$cpu_ondemand_sampling_rate" > /sys/devices/system/cpu/cpufreq/ondemand/sampling_rate
				echo "$cpu_ondemand_sampling_down_factor" > /sys/devices/system/cpu/cpufreq/ondemand/sampling_down_factor

			#	XU4 3.x kernel
			else

				#	Apply to all cores
				for ((i=$input_core_start; i<$input_core_end; i++))
				do
					echo "$cpu_throttle_up_percent" > /sys/devices/system/cpu/cpu"$i"/cpufreq/ondemand/up_threshold
					echo "$cpu_ondemand_sampling_rate" > /sys/devices/system/cpu/cpu"$i"/cpufreq/ondemand/sampling_rate
					echo "$cpu_ondemand_sampling_down_factor" > /sys/devices/system/cpu/cpu"$i"/cpufreq/ondemand/sampling_down_factor
				done
			fi

		#Set CPU governor conservative settings
		elif [ "$input_gov_name" = 'conservative' ]; then

			cpu_throttle_up_percent=$(cat /DietPi/dietpi.txt | grep -m1 '^CONFIG_CPU_USAGE_THROTTLE_UP=' | sed 's/.*=//')

			#XU3/4 different path (must apply to each core)
			if (( $G_HW_MODEL == 11 )); then

				for ((i=$input_core_start; i<$input_core_end; i++))
				do

					echo "$cpu_throttle_up_percent" > /sys/devices/system/cpu/cpu"$i"/cpufreq/conservative/up_threshold

				done

			else

				echo "$cpu_throttle_up_percent" > /sys/devices/system/cpu/cpufreq/conservative/up_threshold

			fi

		fi

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Main Loop
	#/////////////////////////////////////////////////////////////////////////////////////
	#-----------------------------------------------------------------------------------
	G_DIETPI-NOTIFY 3 DietPi-Cpu_Set "Applying CPU gov"
	#-----------------------------------------------------------------------------------
	Check_GPU_Gov_Available

	#Apply CPU0 gov to all cores (if required)
	Apply_CPU_Gov "$CPU_GOVERNOR" 0 $G_HW_CPU_CORES

	G_DIETPI-NOTIFY 0 "CPU gov applied: $CPU_GOVERNOR\n"

	#-----------------------------------------------------------------------------------
	exit
	#-----------------------------------------------------------------------------------
}