summaryrefslogtreecommitdiff
path: root/pm/sleep.d/99video
blob: 29f2f2c6e06c36e54edfa24162d1bc90872c2fc1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
#!/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" ;;
		no-fb) 		   QUIRK_NOFB="true" ;;
		pci-save) 	   QUIRK_PCI_SAVE="true" ;;
	        no-chvt)           QUIRK_NO_CHVT="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

die_if_framebuffer() 
{ 
	[ -d "/sys/class/graphics/fb0" ] || return
	echo "--quirk-no-fb passed, but system is using a framebuffer."
	echo "Aborting."
	exit 1
}


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
}

maybe_chvt()
{
    is_set "$QUIRK_NO_CHVT" && return
    fgconsole |savestate console
    chvt 63
}

maybe_deallocvt()
{
    state_exists console || return 0
    chvt $(restorestate console)
    deallocvt 63
}

# Some tiny helper functions for quirk handling
quirk() { is_set "$1" && [ -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() 
{
	# this is a little mode complicated to handle special-casing mode 3.
	local vbemode=$(restorestate vbemode)
	if [ "$vbemode" = "3" ]; then
		vbe vgamode set $vbemode
	else 
		vbe vbemode set $vbemode
	fi
}

# post the video card
vbe_post() 
{
	local rom="/var/run/video.rom"
	# if we do not have a romfile, do not post with it.
	[ -f "$rom" ] || unset rom
	vbe post $rom
	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; }

# save and restore video card PCI config state
save_pci() 
{
	local pci="/sys/bus/pci/devices"
	for dev in "${pci}"/*; do
		[ -f "${dev}/class" ] || continue
		[ $(cat "${dev}/class") = "0x030000" ] || continue
		[ -f "${dev}/config" ] || continue
		# it is a video card, it has a configuration.  Save it.
		savestate "pci_video_${dev##*/}" <${dev}/config
	done
}

restore_pci() 
{
	local pci="/sys/bus/pci/devices"
	for dev in "${pci}"/*; do
		state_exists "pci_video_${dev##*/}" || continue
		restorestate "pci_video_${dev##*/}" > "${dev}/config"
	done
}

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))
	sysctl -w kernel.acpi_video_flags=$acpi_flag
	
	quirk "${QUIRK_NOFB}" && 		die_if_framebuffer
	quirk "${QUIRK_VBESTATE_RESTORE}" && 	vbe_savestate
	quirk "${QUIRK_VBEMODE_RESTORE}" && 	vbe_savemode
	quirk "${QUIRK_RADEON_OFF}" && 		radeon_off
	quirk "${QUIRK_PCI_SAVE}" && 		pci_save
	quirk "${QUIRK_VGA_MODE_3}" && 		vbe vbemode set 3
	quirk "${QUIRK_DPMS_SUSPEND}" && 	vbe dpms suspend
	save_fbcon
}
resume_video()
{
	# We might need to do one or many of these quirks
	quirk "${QUIRK_PCI_SAVE}" && 		pci_restore
	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) maybe_chvt; suspend_video ;;
	hibernate) maybe_chvt
		if is_set "$HIBERNATE_RESUME_POST_VIDEO"; then
			suspend_video
		fi
		;;
	resume) resume_video; maybe_deallocvt;;
	thaw)
		if is_set "${HIBERNATE_RESUME_POST_VIDEO}"; then
			resume_video
		fi
		maybe_deallocvt
		;;
	help) help ;;
esac