aboutsummaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorFilesLines
2021-06-15drm/amd/display: Always write repeater mode regardless of LTTPRWesley Chalmers1-4/+3
[WHY] SCR for DP2.0 requires that LT be performed with PHY_REPEATER_MODE programmed to 0x55 (Transparent) whenever PHY_REPEATER_CNT is any value other than 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, or 0x01. [HOW] Write Non-Transparent (0xAA) to PHY_REPEATER_MODE when LTTPRs detected and Non-Transparent is requested. Write Transparent in all other cases. Signed-off-by: Wesley Chalmers <[email protected]> Reviewed-by: Jun Lei <[email protected]> Acked-by: Anson Jacob <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-15drm/amd/display: Set LTTPR Transparent Mode after read link capWesley Chalmers1-2/+3
[WHY] SCR for DP 2.0 Spec states that a DPTX shall put LTTPRs into Transparent mode after reading LTTPR Capability registers on HPD. The wording of the SCR is somewhat ambiguous as to whether Transparent mode must be set explicity, or is implicitly set on LTTPR capability read. Explicitly setting Transparent mode after LTTPR capability read should cover all cases. Signed-off-by: Wesley Chalmers <[email protected]> Reviewed-by: Jun Lei <[email protected]> Acked-by: Anson Jacob <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-15drm/amd/display: Read LTTPR caps first on bootupWesley Chalmers3-0/+8
[WHY] SCR for DP 2.0 requires that LTTPR caps be read first on hotplug. For the sake of consistency, this should also be the case on bootup. Signed-off-by: Wesley Chalmers <[email protected]> Reviewed-by: Jun Lei <[email protected]> Acked-by: Anson Jacob <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-15drm/amd/display: Move LTTPR cap read into its own functionWesley Chalmers1-34/+41
[WHY] We want LTTPR capabilities to be readable from more places than just retrieve_link_cap Signed-off-by: Wesley Chalmers <[email protected]> Reviewed-by: Jun Lei <[email protected]> Acked-by: Anson Jacob <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-15drm/amd/display: Read LTTPR caps first on hotplugWesley Chalmers1-32/+33
[WHY] A new SCR for the DP2.0 spec requires that LTTPR caps be the first thing read from DPCD upon hotplug. Signed-off-by: Wesley Chalmers <[email protected]> Reviewed-by: Jun Lei <[email protected]> Acked-by: Anson Jacob <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-15drm/amd/display: move psr dm interface to separate filesRoman Li4-137/+205
[Why] Improve the maintain/read abilities of dm code. [How] Create amdgpu_dm_psr.c/h files. Move psr function from amdgpu_dm.c Signed-off-by: Roman Li <[email protected]> Reviewed-by: Nicholas Kazlauskas <[email protected]> Acked-by: Anson Jacob <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-15drm/amd/display: 3.2.140Aric Cyr1-1/+1
This version brings along following fixed: - LTTPR improvements - Backlight improvements - eDP hotplug detection Signed-off-by: Aric Cyr <[email protected]> Acked-by: Anson Jacob <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-15drm/amd/display: [FW Promotion] Release 0.0.70Anthony Koo1-2/+2
Signed-off-by: Anthony Koo <[email protected]> Acked-by: Anson Jacob <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-15drm/amd/display: Updated variable name.David Galiffi1-6/+6
[Why] Fixed spelling error. [How] Changed "currnet_setting" to "current_setting". Signed-off-by: David Galiffi <[email protected]> Reviewed-by: Wesley Chalmers <[email protected]> Acked-by: Anson Jacob <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-15drm/amd/display: Change swizzle visual confirm reference pipePo-Ting Chen1-5/+5
[Why] To change the swizzle visual confirm reference pipe from top pipe to bottom pipe due to bottom pipe information would be more important for multiple overlay case. Signed-off-by: Po-Ting Chen <[email protected]> Reviewed-by: Anthony Koo <[email protected]> Acked-by: Anson Jacob <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-15drm/amd/display: dp mst detection code refactorWenjing Liu2-96/+70
[why] Move mst start top mgr in dc_link_detect layer. Remove unused same_dpcd variable. Move PEAK_FACTOR_X1000 and LINK_TRAINING_MAX_VERIFY_RETRY to the proper header for defining dc link internal constant. Signed-off-by: Wenjing Liu <[email protected]> Reviewed-by: George Shen <[email protected]> Acked-by: Anson Jacob <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-15drm/amd/display: tune backlight ramping profilesJosip Pavic1-10/+10
[Why & How] Tune backlight ramping profiles for each Vari-Bright level to suit customer preferences Signed-off-by: Josip Pavic <[email protected]> Reviewed-by: Anthony Koo <[email protected]> Acked-by: Anson Jacob <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-15drm/amd/display: add config option for eDP hotplug detectionYi-Ling Chen2-4/+7
[Why] Some custom platforms use eDP hotplug events to notify panel capability changes that should be reported [How] Add a DC config option that unblocks eDP hotplug events Signed-off-by: Yi-Ling Chen <[email protected]> Reviewed-by: Aric Cyr <[email protected]> Acked-by: Anson Jacob <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-15drm/amd/display: add DMUB registers to crash dump diagnostic data.Ashley Thomas11-9/+238
[WHY] Ability to triage DMCUB is improved with availability of certain dmub registers not currently captured in crash dump diagnostic data. [HOW] Add dmub registers to diagnostic data collection. Thanks Nicholas Kazlauskas for awesome input on this! Signed-off-by: Ashley Thomas <[email protected]> Reviewed-by: Nicholas Kazlauskas <[email protected]> Acked-by: Anson Jacob <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-15drm/amd/display: Remove unnecessary blank linesDmytro Laktyushkin1-2/+0
cleanup Signed-off-by: Dmytro Laktyushkin <[email protected]> Reviewed-by: Aric Cyr <[email protected]> Acked-by: Anson Jacob <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-15drm/amdkfd: fix circular locking on get_wave_stateJonathan Kim1-15/+13
get_wave_state acquires the mmap_lock on copy_to_user but so do mmu_notifiers. mmu_notifiers allows dqm locking so do get_wave_state outside the dqm_lock to prevent circular locking. v2: squash in unused variable removal. Signed-off-by: Jonathan Kim <[email protected]> Reviewed-by: Felix Kuehling <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amd/display: Verify Gamma & Degamma LUT sizes in amdgpu_dm_atomic_checkMark Yacoub3-6/+40
For each CRTC state, check the size of Gamma and Degamma LUTs so unexpected and larger sizes wouldn't slip through. TEST: IGT:kms_color::pipe-invalid-gamma-lut-sizes v2: fix assignments in if clauses, Mark's email. Reviewed-by: Harry Wentland <[email protected]> Signed-off-by: Mark Yacoub <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amdgpu: disable DRAM memory training when GECC is enabledHawking Zhang2-13/+35
GECC and G6 mem training are mutually exclusive functionalities. VBIOS/PSP will set the flag (BOOT_CFG_FEATURE_TWO_STAGE_DRAM_TRAINING) in runtime database to indicate whether dram memory training need to be disabled or not. For Navi1x families, two stage mem training is always enabled. Signed-off-by: Hawking Zhang <[email protected]> Reviewed-by: John Clements <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amdgpu: cache psp runtime boot_cfg_bitmask in sw_intHawking Zhang2-0/+9
PSP runtime boot_cfg_bitmask carries various psp bl feature bit mask that can be used by driver. Cache it in sw_init for further usage. Signed-off-by: Hawking Zhang <[email protected]> Reviewed-by: John Clements <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amdgpu: add helper function to query psp runtime db entry (v2)Hawking Zhang1-0/+68
PSP will dump various boot up information into a portion of local frame buffer, called runtime database. The helper function is used for driver to query those shared information. v2: init ret and check !ret to exit loop as soon as found the entry Signed-off-by: Hawking Zhang <[email protected]> Reviewed-by: John Clements <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amdgpu: add psp runtime db structuresHawking Zhang1-0/+54
PSP runtime database is used to share various boot up information with driver. Signed-off-by: Hawking Zhang <[email protected]> Reviewed-by: John Clements <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amdgpu: enable dynamic GECC support (v2)Hawking Zhang1-10/+47
Dynamic GECC allows user to specify GECC enablement status, which will take effect in next boot cycle. v2: initialize boot_cfg to 0xFF Signed-off-by: Hawking Zhang <[email protected]> Reviewed-by: John Clements <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amdgpu: add helper function to query gecc status in boot configHawking Zhang1-0/+23
Query GECC enablement status in boot config Signed-off-by: Hawking Zhang <[email protected]> Reviewed-by: John Clements <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amdgpu: allow different boot configsHawking Zhang1-4/+4
More boot configs need to be supported via BOOTCFG_CMD_SET Signed-off-by: Hawking Zhang <[email protected]> Reviewed-by: John Clements <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amdgpu: update psp gfx i/f to support dynamic GECCHawking Zhang1-4/+9
psp_gfx_uresp_bootcfg is used to inform driver bootcfg settings maintained by tOS Signed-off-by: Hawking Zhang <[email protected]> Reviewed-by: John Clements <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amdkfd: move CoherentHostAccess prop to HSA_CAPABILITYAlex Sierra1-4/+3
CoherentHostAccess flag support has moved from HSA_MEMORYPROPERTY to HSA_CAPABILITY struct. Proper changes have made also at the thunk to support this change. CoherentHostAccess: whether or not device memory can be coherently accessed by the host CPU. Signed-off-by: Alex Sierra <[email protected]> Reviewed-by: Felix Kuehling <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amd/display: add dummy PG callback for beige gobyAurabindo Pillai3-0/+7
[Why&How] PG registers are absent in beige goby, so programming these registers generate call trace. Fix this by adding a dummy function in dcn303 initialization function which prevents writing to non existant registers. Fixes: cd6d421e3d1ad5 ("drm/amd/display: Initial DC support for Beige Goby") Signed-off-by: Aurabindo Pillai <[email protected]> Acked-by: Alex Deucher <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amd/pm: support ss metrics read on yellow_carpSathishkumar S1-0/+34
add support to read smart shift apu and dgpu power share on yellow_carp Signed-off-by: Sathishkumar S <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amd/pm: support ss metrics read on renoirSathishkumar S1-0/+34
add support to read smart shift apu and dgpu power share on renoir. Signed-off-by: Sathishkumar S <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amdkfd: Add memory sync before TLB flush on unmapEric Huang1-3/+20
It is to fix a failure for SDMA updating PTEs. Signed-off-by: Eric Huang <[email protected]> Reviewed-by: Felix Kuehling <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amdgpu: use adev_to_drm macro for consistency (v2)Guchun Chen2-2/+2
Use adev_to_drm() to get to the drm_device pointer. Signed-off-by: Guchun Chen <[email protected]> Reviewed-by: Luben Tuikov <[email protected]> Reviewed-by: Alex Deucher <[email protected]> Reviewed-by: Felix Kuehling <[email protected]> Reviewed-by: Christian König <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amdgpu: reset psp ring wptr during ring_createYuBiao Wang2-0/+2
[Why] psp ring wptr is not initialized properly in ring_create, which would lead to psp failure after several gpu reset. [How] Set ring_wptr to zero in psp_ring_create. Signed-off-by: YuBiao Wang <[email protected]> Reviewed-by: Horace Chen <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amd/pm: Only primary die supports power dataLijo Lazar1-11/+46
On aldebaran, only primary die fetches valid power data. Show power/energy values as 0 on secondary die. Also, power limit should not be set through secondary die. Signed-off-by: Lijo Lazar <[email protected]> Reviewed-by: Hawking Zhang <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amd/pm: correct the power limits reporting on OOB supportedEvan Quan8-35/+95
As OOB(out-of-band) interface may be used to update the power limits. Thus to make sure the power limits reporting of our driver always reflects the correct values, the internal cache must be aligned carefully. V2: add support for out-of-band of other ASICs align cached current power limit with OOB imposed Signed-off-by: Evan Quan <[email protected]> Reviewed-By: Harish Kasiviswanathan <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amd/amdgpu: add instance_number check in amdgpu_discovery_get_ip_versionPeng Ju Zhou2-3/+3
The original code returns IP version of instantce_0 for every IP. This implementation may be correct for most of IPs. However, for certain IP block (VCN for example), it may have 2 instances and both of them have the same hw_id, BUT they have different revision number (0 and 1). In this case, the original amdgpu_discovery_get_ip_version cannot correct reflects the result and returns false information Signed-off-by: Bokun Zhang <[email protected]> Signed-off-by: Peng Ju Zhou <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amd/pm: correct the dpm features disablement for Navi1xEvan Quan1-1/+2
For BACO scenario, PMFW will handle the dpm features disablement and interaction with RLC properly. Driver involvement is unnecessary and error prone. Signed-off-by: Evan Quan <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amd/pm: update the cached dpm feature statusEvan Quan5-13/+50
For some ASICs, the real dpm feature disablement job is handled by PMFW during baco reset and custom pptable loading. Cached dpm feature status need to be updated to pair that. Signed-off-by: Evan Quan <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amdgpu: make audio dev's D-state transition PMFW-awareEvan Quan1-0/+42
To correctly kick into BACO state, the audio dev's D-state transition(D0->D3) needs to be PMFW-aware. So, if the audio dev entered D3 state prior to our driver, we need to bring it back to D0 state and make sure there will be a D-state transition on runpm suspend. Signed-off-by: Evan Quan <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amd/pm: correct the runpm handling for BACO supported ASICEvan Quan4-13/+55
Via the fSMC_MSG_ArmD3 message, PMFW can properly act on the Dstate change. Driver involvement for determining the timing for BACO enter/exit is not needed. Signed-off-by: Evan Quan <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11drm/amd/pm: drop the incomplete fix for Navi14 runpm issueEvan Quan2-29/+2
As the fix by adding PPSMC_MSG_PrepareMp1ForUnload is proved to be incomplete. Another fix(see link below) has been sent out. Link: https://lore.kernel.org/linux-pci/[email protected]/ Signed-off-by: Evan Quan <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-11Merge tag 'exynos-drm-next-for-v5.14' of ↵Dave Airlie12-22/+86
git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next Two cleanups - These patches make Exynos DRM driver to use pm_runtime_resume_and_get() function instead of m_runtime_get_sync() to deal with usage counter. pm_runtime_get_sync() increases the usage counter even when it failed, which could make callers to forget to decrease the usage counter. pm_runtime_resume_and_get() decreases the usage counter regardless of whether it failed or not. Signed-off-by: Dave Airlie <[email protected]> From: Inki Dae <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
2021-06-11Merge tag 'drm-intel-gt-next-2021-06-10' of ↵Dave Airlie108-2723/+1897
git://anongit.freedesktop.org/drm/drm-intel into drm-next UAPI Changes: - Disable mmap ioctl for gen12+ (excl. TGL-LP) - Start enabling HuC loading by default for upcoming Gen12+ platforms (excludes TGL and RKL) Core Changes: - Backmerge of drm-next Driver Changes: - Revert "i915: use io_mapping_map_user" (Eero, Matt A) - Initialize the TTM device and memory managers (Thomas) - Major rework to the GuC submission backend to prepare for enabling on new platforms (Michal Wa., Daniele, Matt B, Rodrigo) - Fix i915_sg_page_sizes to record dma segments rather than physical pages (Thomas) - Locking rework to prep for TTM conversion (Thomas) - Replace IS_GEN and friends with GRAPHICS_VER (Lucas) - Use DEVICE_ATTR_RO macro (Yue) - Static code checker fixes (Zhihao) Signed-off-by: Dave Airlie <[email protected]> From: Joonas Lahtinen <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
2021-06-11Merge branch 'etnaviv/next' of https://git.pengutronix.de/git/lst/linux into ↵Dave Airlie6-43/+82
drm-next - remove redundant NULL checks by various people - fix sparse checker warnings from Marc - expose more GPU ID values to userspace from Christian - add HWDB entry for GPU found on i.MX8MP from Sascha - rework of the linear window calculation to better deal with systems with large regions of reserved RAM Signed-off-by: Dave Airlie <[email protected]> From: Lucas Stach <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
2021-06-11drm/exynos: use pm_runtime_resume_and_get()Inki Dae11-18/+84
Use pm_runtime_resume_and_get() instead of pm_runtime_get_sync() to deal with usage counter. pm_runtime_get_sync() increases the usage counter even when it failed, which makes callers to forget to decrease the usage counter and resulted in reference leak. pm_runtime_resume_and_get() function decreases the usage counter when it failed internally so it can avoid the reference leak. Changelog v1: - Fix an build error reported by kernel test robot of Intel. Signed-off-by: Inki Dae <[email protected]> Reported-by: kernel test robot <[email protected]>
2021-06-11drm/exynos: Use pm_runtime_resume_and_get() to replace open codingTian Tao1-4/+2
use pm_runtime_resume_and_get() to replace pm_runtime_get_sync and pm_runtime_put_noidle to avoid continuing to increase the refcount when pm_runtime_get_sync fails. Signed-off-by: Tian Tao <[email protected]> Reviewed-by: Daniel Vetter <[email protected]> Signed-off-by: Inki Dae <[email protected]>
2021-06-10drm: display: Remove duplicated argument in dcn31Wan Jiabing1-2/+2
Fix the following coccicheck warning: ./drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c: 3539:12-42: duplicated argument to && or || ./drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c: 5677:87-123: duplicated argument to && or || Reviewed-by: Rodrigo Siqueira <[email protected]> Signed-off-by: Wan Jiabing <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-10drm: display: Remove duplicate include in dce110Wan Jiabing1-1/+0
Fix the following checkincludes.pl warning: ./drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c 35 #include "dce110_hw_sequencer.h" 69 #include "dce110_hw_sequencer.h" Reviewed-by: Rodrigo Siqueira <[email protected]> Signed-off-by: Wan Jiabing <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-10drm/amd/display: use ARRAY_SIZE for base60_refresh_ratesJiapeng Chong1-1/+1
Use ARRAY_SIZE instead of dividing sizeof array with sizeof an element. Clean up the following coccicheck warning: ./drivers/gpu/drm/amd/display/dc/core/dc_resource.c:448:47-48: WARNING: Use ARRAY_SIZE. Reported-by: Abaci Robot <[email protected]> Signed-off-by: Jiapeng Chong <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-10drm/amd/display: Fix duplicate included clk_mgr.hJiapeng Chong1-1/+0
Clean up the following includecheck warning: ./drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c: clk_mgr.h is included more than once. No functional change. Reported-by: Abaci Robot <[email protected]> Signed-off-by: Jiapeng Chong <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
2021-06-10drm/amd/pm: Add aldebaran throttler translationGraham Sider1-5/+22
Perform dependent to independent throttle status translation for aldebaran. Signed-off-by: Graham Sider <[email protected]> Reviewed-by: Evan Quan <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>