Commit graph

326 commits

Author SHA1 Message Date
Zhao Yakui aa0261f230 drm/i915: Don't change the blank/sync width when calculating scaled modes
Also, use the border instead of border minus one.

At the same time, make sure the horizontal border and hsync are even for
the LVDS that works in dual-channel mode. So both horizontal border and hsync
start are also changed to be even, even for the LVDS in single-channel mode.

https://bugs.freedesktop.org/show_bug.cgi?id=20951

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-22 19:35:08 -07:00
Zhao Yakui 3fbe18d65d drm/i915: Add support for changing LVDS panel fitting using an output property.
Previously the driver would always scale the chosen video mode to fill the
panel.  This adds 1:1 and maintain-aspect-ratio scaling modes.

v2: the drm_calloc/drm_free is replaced by kzalloc/kfree based
on Eric's suggestion.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-22 19:31:05 -07:00
Jesse Barnes 9e06dd39f2 drm/i915: correct suspend/resume ordering
We need to save register state *after* idling GEM, clearing the ring,
and uninstalling the IRQ handler, or we might end up saving bogus
fence regs, for one.  Our restore ordering should already be correct,
since we do GEM, ring and IRQ init after restoring the last register
state, which prevents us from clobbering things.

I put this together to potentially address a bug, but I haven't heard
back if it fixes it yet.  However I think it stands on its own, so I'm
sending it in.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-22 18:54:04 -07:00
Eric Anholt be9f1c4f73 Merge commit 'keithp/drm-intel-next' into drm-intel-next 2009-06-21 22:33:15 -07:00
Dave Airlie 95934f939c drm/i915: enable GEM on PAE.
In theory now that the AGP subsystem is using struct page, we should
have on problems enabling GEM on PAE systems.

Signed-off-by: Dave Airlie <airlied@redhat.com>
2009-06-19 10:29:20 +10:00
Keith Packard fb0f8fbf97 drm/i915: Generate 2MHz clock for display port aux channel I/O. Retry I/O.
The display port aux channel clock is taken from the hrawclk value, which is
provided to the chip as the FSB frequency (as far as I can determine). The
strapping values for that are available in the CLKCFG register, now used to
select an appropriate divider to generate a 2MHz clock.

In addition, the DisplayPort spec requires that each aux channel I/O be
retried 'at least 3 times' in case the sink is idle when the first request
comes in.

Signed-off-by: Keith Packard <keithp@keithp.com>
2009-06-18 15:54:14 -07:00
Keith Packard a5b3da543d drm/i915: Clarify error returns from display port aux channel I/O
Use distinct error return values for each kind of aux channel I/O failure.

Signed-off-by: Keith Packard <keithp@keithp.com>
2009-06-18 15:54:12 -07:00
Keith Packard b11248df4c drm/i915: Add CLKCFG register definition
The CLKCFG register holds information about the GMCH plls and input clock
values.

Signed-off-by: Keith Packard <keithp@keithp.com>
2009-06-18 15:54:11 -07:00
Keith Packard e4b366996b drm/i915: Split array of DAC limits into separate structures.
The array of DAC limits was only ever referenced with #defined constant
offsets, and keeping those #define values in sync with the array itself was a
nuisance. This will make future changes to the set of DAC limits less
error-prone.

Signed-off-by: Keith Packard <keithp@keithp.com>
2009-06-18 15:54:10 -07:00
Keith Packard c8110e52b7 drm/i915: Use hotplug callback to retrain DP link
When a DP monitor is plugged back in, it needs to be retrained if it was
active before.

Signed-off-by: Keith Packard <keithp@keithp.com>
2009-06-18 15:54:08 -07:00
Keith Packard a4fc5ed698 drm/i915: Add Display Port support
Signed-off-by: Keith Packard <keithp@keithp.com>
2009-06-18 15:54:07 -07:00
Keith Packard c31c4ba343 drm/i915: add per-output hotplug callback for KMS
This allows each output to deal with plug/unplug events as needed.

Signed-off-by: Keith Packard <keithp@keithp.com>
2009-06-18 15:54:06 -07:00
Keith Packard 308cd3a2e5 drm/i915: Clean up SDVO i2c handling
Eliminate the copy of i2c_bus in sdvo_priv.
Eliminate local copies of i2c_bus and ddcbus.
Eliminate unused settings of slave_addr.

Signed-off-by: Keith Packard <keithp@keithp.com>
2009-06-18 15:54:04 -07:00
Keith Packard f9c10a9b96 drm/i915: Change I2C api to pass around i2c_adapters
The existing API passed around intel_i2c_chan pointers, which are dependent
on the i2c bit-banging algo. This precluded the driver from using outputs
which use a different algo. Switching to the more general i2c_adpater allows
the driver to support non bit-banging DDC.

This also required moving the slave address into the output private
structures.

Signed-off-by: Keith Packard <keithp@keithp.com>
2009-06-18 15:53:57 -07:00
Keith Packard b99e228d35 drm/i915: check for CONFIG_PNP before using pnp function
Signed-off-by: Keith Packard <keithp@keithp.com>
2009-06-18 14:59:11 -07:00
Keith Packard 98acd46f35 drm/i915: Apple DMI info has inconsistent SYS_VENDOR information
Some machines say 'Apple Inc.' while others say 'Apple Computer, Inc'.
Switch the test to just look for 'Apple' instead.

Signed-off-by: Keith Packard <keithp@keithp.com>
2009-06-18 14:59:10 -07:00
Keith Packard aa93d632c4 drm/i915: Require digital monitor on HDMI ports for detect
HDMI and DVI both require DDC/EDID on monitors, so use
that to know when a monitor is connected as the hot-plug
pins are shared with SDVO and DisplayPort

Signed-off-by: Keith Packard <keithp@keithp.com>
2009-06-18 14:59:01 -07:00
Eric Anholt 9a298b2acd drm: Remove memory debugging infrastructure.
It hasn't been used in ages, and having the user tell your how much
memory is being freed at free time is a recipe for disaster even if it
was ever used.

Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-18 13:00:33 -07:00
Chris Wilson 52dc7d32b8 drm/i915: Clear fence register on tiling stride change.
The fence register value also depends upon the stride of the object, so we
need to clear the fence if that is changed as well.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
[anholt: Added 8xx and 965 paths, and renamed the confusing
i915_gem_object_tiling_ok function to i915_gem_object_fence_offset_ok]
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-18 12:40:50 -07:00
Chris Wilson 8c4b8c3f34 drm/i915: Install fence register for tiled scanout on i915
With the work by Jesse Barnes to eliminate allocation of fences during
execbuffer, it becomes possible to write to the scan-out buffer with it
never acquiring a fence (simply by only ever writing to the object using
tiled GPU commands and never writing to it via the GTT). So for pre-i965
chipsets which require fenced access for tiled scan-out buffers, we need
to obtain a fence register.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-18 11:47:04 -07:00
Chris Wilson d78b47b9a5 drm/i915: detach/attach get/put pages symmetry
After performing an operation over the page list for a buffer retrieved by
i915_gem_object_get_pages() the pages need to be returned with
i915_gem_object_put_pages(). This was not being observed for the phys
objects which were thus leaking references to their backing pages.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
CC: Dave Airlie <airlied@gmail.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-17 15:26:24 -07:00
Ben Gamari 76cff81ad1 drm/i915: A few debugfs formatting fixes
Signed-Off-By: Ben Gamari <bgamari.foss@gmail.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-17 14:32:20 -07:00
Ben Gamari 049b77cb2a drm/i915: Warn when inteldrmfb fails to restore its framebuffer config
While sifting through the inteldrmfb code trying to solve #22040 I found that
the fb restore path doesn't check the return value of
drm_crtc_helper_set_config(), which seems to have all sorts of potential
failure modes. We should warn someone if one of these is triggered.

Signed-Off-By: Ben Gamari <bgamari.foss@gmail.com>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
[anholt: hand-applied, failures are mine]
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-17 14:22:47 -07:00
Dave Airlie 4410f39109 fbdev: add support for handoff from firmware to hw framebuffers
With KMS we have ran into an issue where we really want the KMS fb driver
to be the one running the console, so panics etc can be shown by switching
out of X etc.

However with vesafb/efifb built-in, we end up with those on fb0 and the
KMS fb driver on fb1, driving the same piece of hw, so this adds an fb
info flag to denote a firmware fbdev, and adds a new aperture base/size
range which can be compared when the hw drivers are installed to see if
there is a conflict with a firmware driver, and if there is the firmware
driver is unregistered and the hw driver takes over.

It uses new aperture_base/size members instead of comparing on the fix
smem_start/length, as smem_start/length might for example only cover the
first 1MB of the PCI aperture, and we could allocate the kms fb from 8MB
into the aperture, thus they would never overlap.

[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Dave Airlie <airlied@redhat.com>
Acked-by: Peter Jones <pjones@redhat.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Krzysztof Helt <krzysztof.h1@poczta.fm>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-06-16 19:48:00 -07:00
Linus Torvalds 6b702462cb Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (50 commits)
  drm: include kernel list header file in hashtab header
  drm: Export hash table functionality.
  drm: Split out the mm declarations in a separate header. Add atomic operations.
  drm/radeon: add support for RV790.
  drm/radeon: add rv740 drm support.
  drm_calloc_large: check right size, check integer overflow, use GFP_ZERO
  drm: Eliminate magic I2C frobbing when reading EDID
  drm/i915: duplicate desired mode for use by fbcon.
  drm/via: vfree() no need checking before calling it
  drm: Replace DRM_DEBUG with DRM_DEBUG_DRIVER in i915 driver
  drm: Replace DRM_DEBUG with DRM_DEBUG_MODE in drm_mode
  drm/i915: Replace DRM_DEBUG with DRM_DEBUG_KMS in intel_sdvo
  drm/i915: replace DRM_DEBUG with DRM_DEBUG_KMS in intel_lvds
  drm: add separate drm debugging levels
  radeon: remove _DRM_DRIVER from the preadded sarea map
  drm: don't associate _DRM_DRIVER maps with a master
  drm: simplify kcalloc() call to kzalloc().
  intelfb: fix spelling of "CLOCK"
  drm: fix LOCK_TEST_WITH_RETURN macro
  drm/i915: Hook connector to encoder during load detection (fixes tv/vga detect)
  ...
2009-06-12 18:09:18 -07:00
Dave Airlie 7ff145593d drm/i915: duplicate desired mode for use by fbcon.
duplicate the mode into fbcon storage, so when we free modes later
we don't just lose this.

Signed-off-by: Dave Airlie <airlied@redhat.com>
2009-06-12 15:00:01 +10:00
yakui_zhao be25ed9c5c drm: Replace DRM_DEBUG with DRM_DEBUG_DRIVER in i915 driver
Replace the DRM_DEBUG with the DRM_DEBUG_DRIVER to print the debug info
in i915 driver.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2009-06-12 14:59:58 +10:00
yakui_zhao 342dc382c4 drm/i915: Replace DRM_DEBUG with DRM_DEBUG_KMS in intel_sdvo
Use the DRM_DEBUG_KMS/DEBUG_LOG_KMS to print the debug info for
SDVO device.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2009-06-11 18:40:44 +10:00
yakui_zhao 7fb85bfb54 drm/i915: replace DRM_DEBUG with DRM_DEBUG_KMS in intel_lvds
Use the DRM_DEBUG_KMS macro definition to print the debug info for
the LVDS.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2009-06-11 18:40:36 +10:00
Pavel Roskin 1bcbf39488 intelfb: fix spelling of "CLOCK"
Signed-off-by: Pavel Roskin <proski@gnu.org>
Cc: Eric Anholt <eric@anholt.net>
Cc: Dave Airlie <airlied@linux.ie>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2009-06-11 16:10:29 +10:00
Keith Packard 03d6069912 drm/i915: Hook connector to encoder during load detection (fixes tv/vga detect)
With the DRM-driven DPMS code, encoders are considered idle unless a
connector is hooked to them, so mode setting is skipped. This makes load
detection fail as none of the hardware is enabled.

Signed-off-by: Keith Packard <keithp@keithp.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-09 15:20:55 -07:00
Chris Wilson 2939e1f533 drm/i915: NOMEM->NOSPC
To differentiate between encountering an out-of-memory error with running
out of space in the aperture, use ENOSPC for the later.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-09 14:51:39 -07:00
Chris Wilson 21d509e339 drm/i915: use I915_GEM_GPU_DOMAINS
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-09 14:51:18 -07:00
Chris Wilson b1ce786cb8 drm/i915: no need to hold mutex for object lookup
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-09 14:41:37 -07:00
Chris Wilson 1f803ee5ce drm/i915: Call drm_vblank_post_modeset() on error paths.
Ensure that the drm_vblank_pre_modeset() is always balanced by
drm_vblank_post_modeset() within intel_crtc_mode_set().

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-09 14:41:26 -07:00
Chris Wilson 5f26a2c7ad drm/i915: OR in the COMMAND read domain for the batch buffer.
The batch buffer may be shared with another read buffer, so we should not
ignore any previously set domains, but just or in the command domain (and
check that the buffer is not writable).

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-09 13:54:05 -07:00
Chris Wilson 83d6079515 drm/i915: Sanity check execbuffer arguments before touching state.
By sending a broken execbuffer (its length was not suitably aligned) I
triggered an operation upon a freed object. The invalid alignment was
discovered after updating the write_domain on the object but before the
object was placed on the active queue. So during the unwind process
following the error, the now freed object attempts to flush its
non-existent, but outstanding, GPU writes causing this use-after-free.

[drm:i915_dispatch_gem_execbuffer] *ERROR* alignment
[drm:i915_gem_execbuffer] *ERROR* dispatch failed -22
WARNING: at lib/kref.c:43 warn_slowpath_null+0x10/0x15()
Modules linked in:
Pid: 4552, comm: lt-csi-drm Not tainted 2.6.30-rc6 #423
Call Trace:
 [<c0119ef3>] warn_slowpath_fmt+0x57/0x6d
 [<c014de24>] ? get_pageblock_migratetype+0x18/0x1e
 [<c014e8fd>] ? free_hot_page+0xa/0xc
 [<c014e915>] ? __free_pages+0x16/0x1f
 [<c0153ebf>] ? shmem_truncate_range+0x63e/0x656
 [<c015fb2f>] ? slob_page_alloc+0x146/0x1c8
 [<c0119f19>] warn_slowpath_null+0x10/0x15
 [<c01f55f2>] kref_get+0x1b/0x21
 [<c02605db>] i915_gem_object_move_to_active+0x1f/0x56
 [<c0261302>] i915_add_request+0x156/0x19a
 [<c026136e>] i915_gem_object_flush_gpu_write_domain+0x28/0x3f
 [<c0261eca>] i915_gem_object_unbind+0x4a/0x124
 [<c0261fd7>] i915_gem_free_object+0x33/0x9b
 [<c0250d6b>] drm_gem_object_free+0x28/0x4a
 [<c0250d43>] ? drm_gem_object_free+0x0/0x4a
 [<c01f55ce>] kref_put+0x38/0x41
 [<c0250cbf>] drm_gem_object_unreference+0x11/0x13
 [<c0250d06>] drm_gem_object_handle_unreference+0x1e/0x21
 [<c0250d13>] drm_gem_object_release_handle+0xa/0xe
 [<c01f3e6b>] idr_for_each+0x5f/0x98
 [<c0250d09>] ? drm_gem_object_release_handle+0x0/0xe
 [<c0250daf>] drm_gem_release+0x22/0x34
 [<c025046f>] drm_release+0x1e8/0x3c4
 [<c0162d25>] __fput+0xaf/0x146
 [<c0162dce>] fput+0x12/0x14
 [<c01605ef>] filp_close+0x48/0x52
 [<c011b182>] put_files_struct+0x57/0x9b
 [<c011b1e4>] exit_files+0x1e/0x20
 [<c011c6b6>] do_exit+0x16d/0x511
 [<c03704ab>] ? __schedule+0x3d4/0x3e5
 [<c0103f0d>] ? handle_irq+0xd/0x69
 [<c011caa7>] do_group_exit+0x4d/0x73
 [<c011cae0>] sys_exit_group+0x13/0x17
 [<c010268c>] sysenter_do_call+0x12/0x2b

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-09 13:52:57 -07:00
Michael Cousin fa0864b26b drm/i915: Skip lvds with Aopen i945GTt-VFA
Signed-off-by: Michael Cousin <mika.cousin@gmail.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-09 11:56:12 -07:00
Zhenyu Wang 036a4a7d92 drm/i915: handle interrupt on new chipset
Update interrupt handling methods for IGDNG with new registers
for display and graphics interrupt functions. As we won't use
irq-based vblank sync in dri2, so display interrupt on new chip
will be used for hotplug only in future.

Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-09 11:15:27 -07:00
Jesse Barnes d765898970 drm/i915: enable MCHBAR if needed
Using the new PNP resource checking code, this patch allows the i915
driver to allocate MCHBAR space if needed and use the BAR to determine
current memory settings.

[apw@canonical.com: moved to the new generic PNP resource interface]
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Andy Whitcroft <apw@canonical.com>
Signed-off-by: Eric Anholt <eric@anholt.net>

failure to update-index after git-am --reject to hand-apply

Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-09 11:15:07 -07:00
Jesse Barnes b66d18ddb1 drm/i915: avoid non-atomic sysrq execution
The sysrq functions are executed in hardirq context, so we shouldn't be
calling sleeping functions from them, like mutex_locks or memory
allocations.

Fix up the i915 sysrq handler to avoid this.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-05 14:22:33 +00:00
Jesse Barnes 42c2798b35 drm/i915: apply G45 vblank count code to all G4x chips and fix max_frame_count
All G4x and newer chips use the new style frame count register, with a
full 32 bit frame count.  Update the code to reflect this.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-05 14:22:31 +00:00
Jarod Wilson 70aa96ca2d drm/i915: add ignore lvds quirk info for AOpen Mini PC
Fix a FIXME in the intel LVDS bring-up code, adding the appropriate
blacklist entry for the AOpen Mini PC, courtesy of a dmidecode
dump from Florian Demmer.

Signed-off-by: Jarod Wilson <jarod@redhat.com>
CC: Florian Demmer <florian@demmer.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-05 14:22:30 +00:00
yakui_zhao 714605e4a0 drm/i915: Initialize the SDVO device based on the sdvo info parsed from VBT
http://bugs.freedesktop.org/show_bug.cgi?id=20429

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
[anholt: Massive cleanup of the slave addr function]
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-05 14:22:19 +00:00
yakui_zhao 9b9d172d06 drm/i915: parse VBT general definition block to get the SDVO device info
The general definition block contains the child device tables, which include
the SDVO device info. For example: device slave address, device dvo port,
device type.

We will get the info of SDVO device by parsing the general definition blocks.
Only when a valid slave address is found, it is regarded as the SDVO device.
And the info of DVO port and slave address is recorded.

http://bugs.freedesktop.org/show_bug.cgi?id=20429

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-05 14:13:05 +00:00
yakui_zhao 59a036cfbd drm/i915: Add the structure of child_device_config in video BIOS tables.
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-05 14:13:02 +00:00
Keith Packard 040d87f15a drm/i915: Add Display Port register defines
This adds the register definitions for the display port enable register
along with those for the GMCH and Link M/N ratios required to drive display
port outputs.

Signed-off-by: Keith Packard <keithp@keithp.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-05 14:12:59 +00:00
Keith Packard 2245fda810 drm/i915: Don't trim cursor addresses to 11 bits
We can safely assume that cursor addresses will not extend beyond the
addressable screen dimensions; setting the additional bits is harmless in
any case.

Signed-off-by: Keith Packard <keithp@keithp.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-05 13:09:04 +00:00
Ma Ling cb66c692d1 drm/i915: Set correct TV detection voltage level override values
We detect TV connect status by setting DAC voltage level override
values as 0.7 voltage for DAC_A/B/C. The corresponding 2-bits shold be 0x2,
In order correctly to set last bit as 0, at first we must clean it.

It fixed freedesktop.org bug #21204

Signed-off-by: Ma Ling <ling.ma@intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-05 12:53:26 +00:00
Zhenyu Wang 541998a18b drm/i915: Add LVDS support for IGDNG
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
2009-06-05 11:35:49 +00:00