Cloned display on an external monitor with an iBook 2.2

Abstract

Instructions on making a cloned (mirrored) display appear on the external VGA connector of an 12" iBook.

My setup

Hardware

A 12" iBook 2.2, with an ATI Radeon M7 display device. See cpuinfo, lspci.

Contents of /proc/cpuinfo:

cpu             : 750FX
temperature     : 54-56 C (uncalibrated)
clock           : 900MHz
revision        : 2.3 (pvr 7000 0203)
bogomips        : 1782.57
machine         : PowerBook4,3
motherboard     : PowerBook4,3 MacRISC2 MacRISC Power Macintosh
detected as     : 257 (iBook 2 rev. 2)
pmac flags      : 0000000b
L2 cache        : 512K unified
memory          : 640MB
pmac-generation : NewWorld

Devices on the PCI bus:

00:0b.0 Host bridge: Apple Computer Inc. UniNorth/Pangea AGP
        Flags: bus master, 66Mhz, medium devsel, latency 16
        Capabilities: <available only to root>

00:10.0 VGA compatible controller: ATI Technologies Inc Radeon Mobility M7 LW [Radeon Mobility 7500] (prog-if 00 [VGA])
        Subsystem: ATI Technologies Inc Radeon Mobility M7 LW [Radeon Mobility 7500]
        Flags: bus master, stepping, 66Mhz, medium devsel, latency 255, IRQ 48
        Memory at 98000000 (32-bit, prefetchable) [size=128M]
        I/O ports at 802400 [size=256]
        Memory at 90000000 (32-bit, non-prefetchable) [size=64K]
        Expansion ROM at 90020000 [disabled] [size=128K]
        Capabilities: <available only to root>

10:0b.0 Host bridge: Apple Computer Inc. UniNorth/Pangea PCI
        Flags: bus master, 66Mhz, medium devsel, latency 16

10:17.0 Class ff00: Apple Computer Inc. KeyLargo/Pangea Mac I/O
        Flags: bus master, medium devsel, latency 16
        Memory at 80000000 (32-bit, non-prefetchable) [size=512K]

10:18.0 USB Controller: Apple Computer Inc. KeyLargo/Pangea USB (prog-if 10 [OHCI])
        Flags: bus master, medium devsel, latency 16, IRQ 27
        Memory at 80081000 (32-bit, non-prefetchable) [size=4K]
        Capabilities: <available only to root>

10:19.0 USB Controller: Apple Computer Inc. KeyLargo/Pangea USB (prog-if 10 [OHCI])
        Flags: bus master, medium devsel, latency 16, IRQ 28
        Memory at 80080000 (32-bit, non-prefetchable) [size=4K]
        Capabilities: <available only to root>

20:0b.0 Host bridge: Apple Computer Inc. UniNorth/Pangea Internal PCI
        Flags: bus master, 66Mhz, medium devsel, latency 16

20:0e.0 Class ffff: Apple Computer Inc. UniNorth/Pangea FireWire (rev ff) (prog-if ff)
        !!! Unknown header type 7f

20:0f.0 Ethernet controller: Apple Computer Inc. UniNorth/Pangea GMAC (Sun GEM)
        Flags: bus master, 66Mhz, slow devsel, latency 16, IRQ 41
        Memory at f5200000 (32-bit, non-prefetchable) [size=2M]
        Expansion ROM at f5100000 [disabled] [size=1M]

Software

The iBook runs Debian GNU/Linux, prepackaged kernel kernel-image-2.4.22-powerpc version 2.4.22-1, and Debian's XFree86 version 4.3.0-7. The display manager is gdm 2.4.1.7-1, in case there's some difference in the startup scripts.

Diagnosis

The autogenerated config had a Device section with option UseFBDev set to true. With that, the external display was enlarged and garbled. Google and experimentation showed that commenting out UseFBDev made the external display readable, but the laptop panel seemed to be out of sync.

After some experimentation, I noticed that later X sessions with UseFBDev as true worked, as long as it had once been run without it. This led to the idea of starting X once, on bootup, with a different configuration.

Needed changes

I copied the Device section, renamed it as ati-fix-external-monitor, and removed the UseFBDev line. Then I copied the Screen section, renamed it as fix-external-monitor, and set its Device be ati-fix-external-monitor. See XF86Config-4.

The resulting /etc/X11/XF86Config-4:

Section "InputDevice"
	Identifier	"iBook Keyboard"
	Driver		"keyboard"
	Option		"CoreKeyboard"
	Option		"XkbRules"	"xfree86"
	Option		"XkbModel"	"macintosh"
	Option		"XkbLayout"	"fi+hacks-by-tv(kpenter_altgr)"
EndSection

Section "ServerLayout"
	Identifier	"Default Layout"
	Screen		"Default Screen"
	InputDevice	"iBook Keyboard"
	InputDevice	"Configured Mouse"
EndSection

Section "Device"
	Identifier	"ati-fix-external-monitor"
	Driver		"ati"
	BusID		"PCI:0:16:0"
EndSection

Section "Screen"
	Identifier	"fix-external-monitor"
	Device		"ati-fix-external-monitor"
	Monitor		"Generic Monitor"
	DefaultDepth	24
	SubSection "Display"
		Depth		24
		Modes		"1024x768"
	EndSubSection
EndSection

# XF86Config-4 (XFree86 X server configuration file) generated by dexconf, the
# Debian X Configuration tool, using values from the debconf database.
#
# Edit this file with caution, and see the XF86Config-4 manual page.
# (Type "man XF86Config-4" at the shell prompt.)
#
# This file is automatically updated on xserver-xfree86 package upgrades *only*
# if it has not been modified since the last upgrade of the xserver-xfree86
# package.
#
# If you have edited this file but would like it to be automatically updated
# again, run the following commands as root:
#
#   cp /etc/X11/XF86Config-4 /etc/X11/XF86Config-4.custom
#   md5sum /etc/X11/XF86Config-4 > /var/lib/xfree86/XF86Config-4.md5sum
#   dpkg-reconfigure xserver-xfree86

Section "Files"
	FontPath	"unix/:7100"			# local font server
	# if the local font server has problems, we can fall back on these
	FontPath	"/usr/lib/X11/fonts/Type1"
	FontPath	"/usr/lib/X11/fonts/CID"
	FontPath	"/usr/lib/X11/fonts/Speedo"
	FontPath	"/usr/lib/X11/fonts/misc"
	FontPath	"/usr/lib/X11/fonts/cyrillic"
	FontPath	"/usr/lib/X11/fonts/100dpi"
	FontPath	"/usr/lib/X11/fonts/75dpi"
EndSection

Section "Module"
	Load	"GLcore"
	Load	"bitmap"
	Load	"dbe"
	Load	"ddc"
	#Load	"dri"
	Load	"extmod"
	Load	"freetype"
	Load	"glx"
	Load	"int10"
	Load	"record"
	Load	"speedo"
	Load	"type1"
	Load	"vbe"
EndSection

Section "InputDevice"
	Identifier	"Generic Keyboard"
	Driver		"keyboard"
	Option		"CoreKeyboard"
	Option		"XkbRules"	"xfree86"
	Option		"XkbModel"	"macintosh"
	Option		"XkbLayout"	"fi"
EndSection

Section "InputDevice"
	Identifier	"Configured Mouse"
	Driver		"mouse"
	Option		"CorePointer"
	Option		"Device"		"/dev/input/mice"
	Option		"Protocol"		"ImPS/2"
	Option		"Emulate3Buttons"	"true"
	Option		"ZAxisMapping"		"4 5"
EndSection

Section "Device"
	Identifier	"ATI Technologies, Inc. Radeon Mobility M7 [LW]"
	Driver		"ati"
	BusID		"PCI:0:16:0"
	Option		"UseFBDev"		"true"
EndSection

Section "Monitor"
	Identifier	"Generic Monitor"
	HorizSync	28-50
	VertRefresh	43-75
	Option		"DPMS"
EndSection

Section "Screen"
	Identifier	"Default Screen"
	Device		"ATI Technologies, Inc. Radeon Mobility M7 [LW]"
	Monitor		"Generic Monitor"
	DefaultDepth	24
	SubSection "Display"
		Depth		1
		Modes		"1024x768"
	EndSubSection
	SubSection "Display"
		Depth		4
		Modes		"1024x768"
	EndSubSection
	SubSection "Display"
		Depth		8
		Modes		"1024x768"
	EndSubSection
	SubSection "Display"
		Depth		15
		Modes		"1024x768"
	EndSubSection
	SubSection "Display"
		Depth		16
		Modes		"1024x768"
	EndSubSection
	SubSection "Display"
		Depth		24
		Modes		"1024x768"
	EndSubSection
EndSection

Section "ServerLayout"
	Identifier	"Default Layout"
	Screen		"Default Screen"
	InputDevice	"Generic Keyboard"
	InputDevice	"Configured Mouse"
EndSection

Section "DRI"
	Mode	0666
EndSection

Then I needed a way to start X once with this new Screen definition, to initialize the hardware properly. I noticed that -probeonly didn't have that effect, but I wanted a way that didn't require user interaction, but was still reliable. Timed killing was ugly. I found /usr/bin/X11/xinit /bin/true -- -screen fix-external-monitor did exactly what I wanted.

I copied /etc/init.d/skeleton to /etc/init.d/fix-external-monitor and edited it. See fix-external-monitor.

Contents of /etc/init.d/fix-external-monitor:

#! /bin/sh

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/bin/X11
NAME=fix-external-monitor

# Gracefully exit if the package has been removed.
test -x /usr/bin/X11/xinit || exit 0

set -e

case "$1" in
  start)
	echo -n "Fixing iBook external monitor..."
	xinit /bin/true -- -screen fix-external-monitor
	echo "done."
	;;
  stop|restart|reload|force-reload)
	;;
  *)
	N=/etc/init.d/$NAME
	echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2
	exit 1
	;;
esac

exit 0

The final step was enabling the new init script:

$ sudo update-rc.d fix-external-monitor start 90 2 3 4 5 .

The result

On bootup, X is started, but shuts down automatically. The delay is in the order of a few seconds; for some reason, X is quite slow to start on this hardware. I can't actually tell when the "old X" shuts down and when the "new X" starts, so it just feels like the X startup takes a bit longer.

It seems the external monitor must be connected before X is started, or the trick will not work.