#!/bin/sh
#
# Copyright 2006-2007 Richard Hughes <richard@hughsie.com>
# Copyright 2007 Peter Jones <pjones@redhat.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.

# Handle video quirks.  If you are having suspend/resume issues,
# troubleshooting using this hook is probably the best place to start.
# If it weren't for video card quirks, suspend/resume on Linux would be 
# a whole lot more stable.

. "${PM_FUNCTIONS}"

for opt in $PM_CMDLINE; do
	case "${opt##--quirk-}" in # just quirks, please
		dpms-on) 	   QUIRK_DPMS_ON="true" ;;
		dpms-suspend) 	   QUIRK_DPMS_SUSPEND="true" ;;
		radeon-off) 	   QUIRK_RADEON_OFF="true" ;;
		reset-brightness)  QUIRK_RESET_BRIGHTNESS="true" ;;
		s3-bios) 	   QUIRK_S3_BIOS="true" ;;
		s3-mode) 	   QUIRK_S3_MODE="true" ;;
		vbe-post) 	   QUIRK_VBE_POST="true" ;;
		vbemode-restore)   QUIRK_VBEMODE_RESTORE="true" ;;
		vbestate-restore)  QUIRK_VBESTATE_RESTORE="true" ;;
		vga-mode3) 	   QUIRK_VGA_MODE_3="true" ;;
		none) 		   QUIRK_NONE="true" ;;
		*) continue ;;
	esac
done


reset_brightness()
{
	for bl in /sys/class/backlight/* ; do
		[ -f "$bl/brightness" ] || continue
		BR="$(cat $bl/brightness)"
		echo 0 > "$bl/brightness"
		echo "$BR" > "$bl/brightness"
	done
}

if command_exists vbetool; then
	vbe() { vbetool "$@"; }
else 
	vbe() { echo "vbetool not installed!" 1>&2; return 1; }
fi

if command_exists radeontool; then
	radeon() { radeontool "$@"; }
else 
	radeon() { echo "radeontool not found" 1>&2; return 1; }
fi

save_fbcon()
{
	local con
	for con in /sys/class/graphics/*/state; do
		[ -f $con ] || continue
		echo 1 >"${con}"
	done
}

resume_fbcon()
{
	local con
	for con in /sys/class/graphics/*/state; do
		[ -f $con ] || continue
		echo 0 >"${con}"
	done
}

# Some tiny helper functions for quirk handling
quirk() { [ "$1" = "true" ] && [ -z $QUIRK_NONE ]; }

# save/restore vbe state
vbe_savestate() { vbe vbestate save |savestate vbestate; }
vbe_restorestate() { restorestate vbestate |vbe vbestate restore; }

# save/restore the vbe mode
vbe_savemode() { vbe vbemode get |savestate vbemode; }
vbe_restoremode() { vbe vbemode get |savestate vbemode; }

# post the video card
vbe_post() { vbe post; sleep 0.1; }

# turn critical bits of radeon cards off/on
radeon_off() { radeon dac off; radeon light off; }
radeon_on() { radeon dac on; radeon light on; }

suspend_video()
{
	# 0=nothing, 1=s3_bios, 2=s3_mode, 3=both
	local acpi_flag=0
	quirk "${QUIRK_S3_BIOS}" && 		acpi_flag=$(($acpi_flag + 1))
	quirk "${QUIRK_S3_MODE}" && 		acpi_flag=$(($acpi_flag + 2))
	[ 0 -ne $acpi_flag ] && sysctl -w kernel.acpi_video_flags=$acpi_flag
	
	quirk "${QUIRK_VBESTATE_RESTORE}" && 	vbe_savestate
	quirk "${QUIRK_VBEMODE_RESTORE}" && 	vbe_savemode
	quirk "${QUIRK_RADEON_OFF}" && 		radeon_off
	quirk "${QUIRK_VGA_MODE_3}" && 		vbe vbemode set 3
	quirk "${QUIRK_DPMS_SUSPEND}" && 	vbe dpms suspend
	save_fbcon # there should be a quirk, but HAL does not pass it.
}
resume_video()
{
	# We might need to do one or many of these quirks
	quirk "${QUIRK_VBE_POST}" && 		vbe_post
	quirk "${QUIRK_VBESTATE_RESTORE}" && 	vbe_restorestate
	quirk "${QUIRK_VBEMODE_RESTORE}" && 	vbe_restoremode
	resume_fbcon 	# also should be handled by a quirk.
	quirk "${QUIRK_RADEON_OFF}" && 		radeon_on
	quirk "${QUIRK_DPMS_ON}" && 		vbe dpms on
	quirk "${QUIRK_RESET_BRIGHTNESS}" && 	reset_brightness
	return 0  # avoid spurious hook exit failure message.
}

help() {
	echo  # first echo makes it look nicer.
	echo "Video quirk handler options:"
	echo
	echo "  --quirk-dpms-on"
	echo "  --quirk-dpms-suspend"
	echo "  --quirk-radeon-off"
	echo "  --quirk-reset-brightness"
	echo "  --quirk-s3-bios"
	echo "  --quirk-s3-mode"
	echo "  --quirk-vbe-post"
	echo "  --quirk-vbemode-restore"
	echo "  --quirk-vbestate-restore"
	echo "  --quirk-vga-mode3"
	echo "  --quirk-none"
}

case "$1" in
	suspend) suspend_video ;;
	hibernate)
		if [ "$HIBERNATE_RESUME_POST_VIDEO" = "yes" ]; then
			suspend_video
		fi
		;;
	resume) resume_video ;;
	thaw)
		if [ "${HIBERNATE_RESUME_POST_VIDEO}" = "yes" ]; then
			resume_video
		fi
		;;
	help) help ;;
esac
