From 9fb03e63511cc20d413c2896396ba77df3db8411 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 11 Dec 2009 15:13:22 +0100 Subject: drm/radeon/kms: If no placement is supplied fallback to system Do as we did before rework, if no placement is supplied at bo creation time, fallback to allocating bo from system ram. This will fix most of the creation failed issue report we got since the rework get merged. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_object.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 544e18ffaf2..132130fcd99 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -71,6 +71,8 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; if (domain & RADEON_GEM_DOMAIN_CPU) rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; + if (!c) + rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; rbo->placement.num_placement = c; rbo->placement.num_busy_placement = c; } -- cgit From d03d858970a158fa82d9ba0d502bdea0bdb3ad33 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Mon, 14 Dec 2009 21:02:09 +0100 Subject: drm/radeon/kms: Check if bo we got from ttm are radeon object or not If they are not radeon object don't do anythings special for them, this avoid rare oops than can happen in a complex use case. [airlied: additional fixups] Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_object.c | 19 ++++++++++++++++--- drivers/gpu/drm/radeon/radeon_ttm.c | 14 +++++++++++++- 3 files changed, 30 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index c938bb54123..e3c494097f6 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1016,6 +1016,7 @@ extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data); extern void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable); extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable); extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain); +extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo); /* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ struct r100_mc_save { diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 132130fcd99..d9ffe1f56e8 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -56,6 +56,13 @@ static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo) kfree(bo); } +bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo) +{ + if (bo->destroy == &radeon_ttm_bo_destroy) + return true; + return false; +} + void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) { u32 c = 0; @@ -483,14 +490,20 @@ int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, } void radeon_bo_move_notify(struct ttm_buffer_object *bo, - struct ttm_mem_reg *mem) + struct ttm_mem_reg *mem) { - struct radeon_bo *rbo = container_of(bo, struct radeon_bo, tbo); + struct radeon_bo *rbo; + if (!radeon_ttm_bo_is_radeon_bo(bo)) + return; + rbo = container_of(bo, struct radeon_bo, tbo); radeon_bo_check_tiling(rbo, 0, 1); } void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) { - struct radeon_bo *rbo = container_of(bo, struct radeon_bo, tbo); + struct radeon_bo *rbo; + if (!radeon_ttm_bo_is_radeon_bo(bo)) + return; + rbo = container_of(bo, struct radeon_bo, tbo); radeon_bo_check_tiling(rbo, 0, 0); } diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index d2ed896cca0..7bed4122528 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -200,7 +200,19 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, static void radeon_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *placement) { - struct radeon_bo *rbo = container_of(bo, struct radeon_bo, tbo); + struct radeon_bo *rbo; + static u32 placements = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; + + if (!radeon_ttm_bo_is_radeon_bo(bo)) { + placement->fpfn = 0; + placement->lpfn = 0; + placement->placement = &placements; + placement->busy_placement = &placements; + placement->num_placement = 1; + placement->num_busy_placement = 1; + return; + } + rbo = container_of(bo, struct radeon_bo, tbo); switch (bo->mem.mem_type) { case TTM_PL_VRAM: radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); -- cgit From ecabd32a623eaf3e4c853ff73f200c8079028000 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 15 Dec 2009 10:39:48 +1000 Subject: drm/radeon/kms: don't report allocate failure on ERESTARTSYS if we fail with ERESTARTSYS during alloc, we'll get a retry from userspace so don't report it in dmesg. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_gem.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 2944486871b..ee827cc22af 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -66,8 +66,9 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size, } r = radeon_bo_create(rdev, gobj, size, kernel, initial_domain, &robj); if (r) { - DRM_ERROR("Failed to allocate GEM object (%d, %d, %u)\n", - size, initial_domain, alignment); + if (r != -ERESTARTSYS) + DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n", + size, initial_domain, alignment, r); mutex_lock(&rdev->ddev->struct_mutex); drm_gem_object_unreference(gobj); mutex_unlock(&rdev->ddev->struct_mutex); -- cgit From 51f07b7ebce15c1848743a2ba43a0005375d8243 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 16 Dec 2009 13:10:43 +1000 Subject: drm/radeon/gem: don't leak a gem object if reserve fails on get tiling (v2) Not sure it ever happens in practice, spotted during code review. spare brace snuck in Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_gem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index ee827cc22af..60df2d7e7e4 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -351,9 +351,10 @@ int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, rbo = gobj->driver_private; r = radeon_bo_reserve(rbo, false); if (unlikely(r != 0)) - return r; + goto out; radeon_bo_get_tiling_flags(rbo, &args->tiling_flags, &args->pitch); radeon_bo_unreserve(rbo); +out: mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(gobj); mutex_unlock(&dev->struct_mutex); -- cgit From f89551bfe953a144f7d4918ca4c12e11de1e455d Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Tue, 15 Dec 2009 18:23:23 +0100 Subject: drm/radeon/kms: Return to userspace on ERESTARTSYS radeon_object.h wasn't converted to ERESTARTSYS change. No each time we got an ERESTARTSYS we return to userspace (ie we were interrupted by a signal and we let the userspace reschedule the ioctl). Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_object.h | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index f6b69c2c0d0..a02f18011ad 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -59,19 +59,17 @@ static inline unsigned radeon_mem_type_to_domain(u32 mem_type) * * Returns: * -EBUSY: buffer is busy and @no_wait is true - * -ERESTART: A wait for the buffer to become unreserved was interrupted by + * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by * a signal. Release all buffer reservations and return to user-space. */ static inline int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait) { int r; -retry: r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0); if (unlikely(r != 0)) { - if (r == -ERESTART) - goto retry; - dev_err(bo->rdev->dev, "%p reserve failed\n", bo); + if (r != -ERESTARTSYS) + dev_err(bo->rdev->dev, "%p reserve failed\n", bo); return r; } return 0; @@ -125,12 +123,10 @@ static inline int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, { int r; -retry: r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0); if (unlikely(r != 0)) { - if (r == -ERESTART) - goto retry; - dev_err(bo->rdev->dev, "%p reserve failed for wait\n", bo); + if (r != -ERESTARTSYS) + dev_err(bo->rdev->dev, "%p reserve failed for wait\n", bo); return r; } spin_lock(&bo->tbo.lock); @@ -140,8 +136,6 @@ retry: r = ttm_bo_wait(&bo->tbo, true, true, no_wait); spin_unlock(&bo->tbo.lock); ttm_bo_unreserve(&bo->tbo); - if (unlikely(r == -ERESTART)) - goto retry; return r; } -- cgit From 7923c615b811945a9d9f456c92a7a32c34167458 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 15 Dec 2009 17:15:07 -0500 Subject: drm/radeon/kms: make sure mc is initialized before mapping blit bo We need to make sure the the MC is intialized before we map the blit shader object on r6xx+. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600.c | 14 ++++++++------ drivers/gpu/drm/radeon/rv770.c | 14 ++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index f5cf874dc62..e145faac990 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1863,6 +1863,14 @@ int r600_startup(struct radeon_device *rdev) } r600_gpu_init(rdev); + if (!rdev->r600_blit.shader_obj) { + r = r600_blit_init(rdev); + if (r) { + DRM_ERROR("radeon: failed blitter (%d).\n", r); + return r; + } + } + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); if (unlikely(r != 0)) return r; @@ -2038,12 +2046,6 @@ int r600_init(struct radeon_device *rdev) if (r) return r; - r = r600_blit_init(rdev); - if (r) { - DRM_ERROR("radeon: failed blitter (%d).\n", r); - return r; - } - rdev->accel_working = true; r = r600_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 2d124bb5776..f58dc671080 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -892,6 +892,14 @@ static int rv770_startup(struct radeon_device *rdev) } rv770_gpu_init(rdev); + if (!rdev->r600_blit.shader_obj) { + r = r600_blit_init(rdev); + if (r) { + DRM_ERROR("radeon: failed blitter (%d).\n", r); + return r; + } + } + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); if (unlikely(r != 0)) return r; @@ -1051,12 +1059,6 @@ int rv770_init(struct radeon_device *rdev) if (r) return r; - r = r600_blit_init(rdev); - if (r) { - DRM_ERROR("radeon: failed blitter (%d).\n", r); - return r; - } - rdev->accel_working = true; r = rv770_startup(rdev); if (r) { -- cgit From dafc3bd515d6079406986f7748b48adb3c7170f2 Mon Sep 17 00:00:00 2001 From: Christian Koenig Date: Sun, 11 Oct 2009 23:49:13 +0200 Subject: drm/radeon/kms: HDMI support for R600 KMS Adding basic HDMI support for R600 KMS, ported from radeonhd ddx. [airlied:- checkpatch cleanups] Signed-off-by: Christian Koenig Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/Makefile | 2 +- drivers/gpu/drm/radeon/r600.c | 5 + drivers/gpu/drm/radeon/r600_audio.c | 267 ++++++++++++++++ drivers/gpu/drm/radeon/r600_hdmi.c | 506 +++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/r600_reg.h | 74 +++++ drivers/gpu/drm/radeon/radeon.h | 24 ++ drivers/gpu/drm/radeon/radeon_drv.c | 4 + drivers/gpu/drm/radeon/radeon_encoders.c | 16 +- drivers/gpu/drm/radeon/radeon_mode.h | 3 + 9 files changed, 895 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/radeon/r600_audio.c create mode 100644 drivers/gpu/drm/radeon/r600_hdmi.c (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index feb52eee431..b5f5fe75e6a 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile @@ -49,7 +49,7 @@ radeon-y += radeon_device.o radeon_kms.o \ radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \ rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \ r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ - r600_blit_kms.o radeon_pm.o atombios_dp.o + r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o radeon-$(CONFIG_COMPAT) += radeon_ioc32.o diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index e145faac990..5c6058c6ddd 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2067,6 +2067,10 @@ int r600_init(struct radeon_device *rdev) rdev->accel_working = false; } } + + r = r600_audio_init(rdev); + if (r) + return r; /* TODO error handling */ return 0; } @@ -2075,6 +2079,7 @@ void r600_fini(struct radeon_device *rdev) /* Suspend operations */ r600_suspend(rdev); + r600_audio_fini(rdev); r600_blit_fini(rdev); r600_irq_fini(rdev); radeon_irq_kms_fini(rdev); diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c new file mode 100644 index 00000000000..99e2c3891a7 --- /dev/null +++ b/drivers/gpu/drm/radeon/r600_audio.c @@ -0,0 +1,267 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Christian König. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Christian König + */ +#include "drmP.h" +#include "radeon.h" +#include "radeon_reg.h" +#include "atom.h" + +#define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */ + +/* + * check if the chipset is supported + */ +static int r600_audio_chipset_supported(struct radeon_device *rdev) +{ + return rdev->family >= CHIP_R600 + || rdev->family == CHIP_RS600 + || rdev->family == CHIP_RS690 + || rdev->family == CHIP_RS740; +} + +/* + * current number of channels + */ +static int r600_audio_channels(struct radeon_device *rdev) +{ + return (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0x7) + 1; +} + +/* + * current bits per sample + */ +static int r600_audio_bits_per_sample(struct radeon_device *rdev) +{ + uint32_t value = (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0xF0) >> 4; + switch (value) { + case 0x0: return 8; + case 0x1: return 16; + case 0x2: return 20; + case 0x3: return 24; + case 0x4: return 32; + } + + DRM_ERROR("Unknown bits per sample 0x%x using 16 instead.\n", (int)value); + + return 16; +} + +/* + * current sampling rate in HZ + */ +static int r600_audio_rate(struct radeon_device *rdev) +{ + uint32_t value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); + uint32_t result; + + if (value & 0x4000) + result = 44100; + else + result = 48000; + + result *= ((value >> 11) & 0x7) + 1; + result /= ((value >> 8) & 0x7) + 1; + + return result; +} + +/* + * iec 60958 status bits + */ +static uint8_t r600_audio_status_bits(struct radeon_device *rdev) +{ + return RREG32(R600_AUDIO_STATUS_BITS) & 0xff; +} + +/* + * iec 60958 category code + */ +static uint8_t r600_audio_category_code(struct radeon_device *rdev) +{ + return (RREG32(R600_AUDIO_STATUS_BITS) >> 8) & 0xff; +} + +/* + * update all hdmi interfaces with current audio parameters + */ +static void r600_audio_update_hdmi(unsigned long param) +{ + struct radeon_device *rdev = (struct radeon_device *)param; + struct drm_device *dev = rdev->ddev; + + int channels = r600_audio_channels(rdev); + int rate = r600_audio_rate(rdev); + int bps = r600_audio_bits_per_sample(rdev); + uint8_t status_bits = r600_audio_status_bits(rdev); + uint8_t category_code = r600_audio_category_code(rdev); + + struct drm_encoder *encoder; + int changes = 0; + + changes |= channels != rdev->audio_channels; + changes |= rate != rdev->audio_rate; + changes |= bps != rdev->audio_bits_per_sample; + changes |= status_bits != rdev->audio_status_bits; + changes |= category_code != rdev->audio_category_code; + + if (changes) { + rdev->audio_channels = channels; + rdev->audio_rate = rate; + rdev->audio_bits_per_sample = bps; + rdev->audio_status_bits = status_bits; + rdev->audio_category_code = category_code; + } + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + if (changes || r600_hdmi_buffer_status_changed(encoder)) + r600_hdmi_update_audio_settings( + encoder, channels, + rate, bps, status_bits, + category_code); + } + + mod_timer(&rdev->audio_timer, + jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL)); +} + +/* + * initialize the audio vars and register the update timer + */ +int r600_audio_init(struct radeon_device *rdev) +{ + if (!r600_audio_chipset_supported(rdev)) + return 0; + + DRM_INFO("%s audio support", radeon_audio ? "Enabling" : "Disabling"); + WREG32_P(R600_AUDIO_ENABLE, radeon_audio ? 0x81000000 : 0x0, ~0x81000000); + + rdev->audio_channels = -1; + rdev->audio_rate = -1; + rdev->audio_bits_per_sample = -1; + rdev->audio_status_bits = 0; + rdev->audio_category_code = 0; + + setup_timer( + &rdev->audio_timer, + r600_audio_update_hdmi, + (unsigned long)rdev); + + mod_timer(&rdev->audio_timer, jiffies + 1); + + return 0; +} + +/* + * determin how the encoders and audio interface is wired together + */ +int r600_audio_tmds_index(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_encoder *other; + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + return 0; + + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + /* special case check if an TMDS1 is present */ + list_for_each_entry(other, &dev->mode_config.encoder_list, head) { + if (to_radeon_encoder(other)->encoder_id == + ENCODER_OBJECT_ID_INTERNAL_TMDS1) + return 1; + } + return 0; + + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + return 1; + + default: + DRM_ERROR("Unsupported encoder type 0x%02X\n", + radeon_encoder->encoder_id); + return -1; + } +} + +/* + * atach the audio codec to the clock source of the encoder + */ +void r600_audio_set_clock(struct drm_encoder *encoder, int clock) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + int base_rate = 48000; + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + WREG32_P(R600_AUDIO_TIMING, 0, ~0x301); + break; + + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + WREG32_P(R600_AUDIO_TIMING, 0x100, ~0x301); + break; + + default: + DRM_ERROR("Unsupported encoder type 0x%02X\n", + radeon_encoder->encoder_id); + return; + } + + switch (r600_audio_tmds_index(encoder)) { + case 0: + WREG32(R600_AUDIO_PLL1_MUL, base_rate*50); + WREG32(R600_AUDIO_PLL1_DIV, clock*100); + WREG32(R600_AUDIO_CLK_SRCSEL, 0); + break; + + case 1: + WREG32(R600_AUDIO_PLL2_MUL, base_rate*50); + WREG32(R600_AUDIO_PLL2_DIV, clock*100); + WREG32(R600_AUDIO_CLK_SRCSEL, 1); + break; + } +} + +/* + * release the audio timer + * TODO: How to do this correctly on SMP systems? + */ +void r600_audio_fini(struct radeon_device *rdev) +{ + if (!r600_audio_chipset_supported(rdev)) + return; + + WREG32_P(R600_AUDIO_ENABLE, 0x0, ~0x81000000); + + del_timer(&rdev->audio_timer); +} diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c new file mode 100644 index 00000000000..fcc949df0e5 --- /dev/null +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -0,0 +1,506 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Christian König. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Christian König + */ +#include "drmP.h" +#include "radeon_drm.h" +#include "radeon.h" +#include "atom.h" + +/* + * HDMI color format + */ +enum r600_hdmi_color_format { + RGB = 0, + YCC_422 = 1, + YCC_444 = 2 +}; + +/* + * IEC60958 status bits + */ +enum r600_hdmi_iec_status_bits { + AUDIO_STATUS_DIG_ENABLE = 0x01, + AUDIO_STATUS_V = 0x02, + AUDIO_STATUS_VCFG = 0x04, + AUDIO_STATUS_EMPHASIS = 0x08, + AUDIO_STATUS_COPYRIGHT = 0x10, + AUDIO_STATUS_NONAUDIO = 0x20, + AUDIO_STATUS_PROFESSIONAL = 0x40, + AUDIO_STATUS_LEVEL = 0x80 +}; + +struct { + uint32_t Clock; + + int N_32kHz; + int CTS_32kHz; + + int N_44_1kHz; + int CTS_44_1kHz; + + int N_48kHz; + int CTS_48kHz; + +} r600_hdmi_ACR[] = { + /* 32kHz 44.1kHz 48kHz */ + /* Clock N CTS N CTS N CTS */ + { 25174, 4576, 28125, 7007, 31250, 6864, 28125 }, /* 25,20/1.001 MHz */ + { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */ + { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */ + { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */ + { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */ + { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */ + { 74175, 11648, 210937, 17836, 234375, 11648, 140625 }, /* 74.25/1.001 MHz */ + { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ + { 148351, 11648, 421875, 8918, 234375, 5824, 140625 }, /* 148.50/1.001 MHz */ + { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ + { 0, 4096, 0, 6272, 0, 6144, 0 } /* Other */ +}; + +/* + * calculate CTS value if it's not found in the table + */ +static void r600_hdmi_calc_CTS(uint32_t clock, int *CTS, int N, int freq) +{ + if (*CTS == 0) + *CTS = clock*N/(128*freq)*1000; + DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n", + N, *CTS, freq); +} + +/* + * update the N and CTS parameters for a given pixel clock rate + */ +static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset; + int CTS; + int N; + int i; + + for (i = 0; r600_hdmi_ACR[i].Clock != clock && r600_hdmi_ACR[i].Clock != 0; i++); + + CTS = r600_hdmi_ACR[i].CTS_32kHz; + N = r600_hdmi_ACR[i].N_32kHz; + r600_hdmi_calc_CTS(clock, &CTS, N, 32000); + WREG32(offset+R600_HDMI_32kHz_CTS, CTS << 12); + WREG32(offset+R600_HDMI_32kHz_N, N); + + CTS = r600_hdmi_ACR[i].CTS_44_1kHz; + N = r600_hdmi_ACR[i].N_44_1kHz; + r600_hdmi_calc_CTS(clock, &CTS, N, 44100); + WREG32(offset+R600_HDMI_44_1kHz_CTS, CTS << 12); + WREG32(offset+R600_HDMI_44_1kHz_N, N); + + CTS = r600_hdmi_ACR[i].CTS_48kHz; + N = r600_hdmi_ACR[i].N_48kHz; + r600_hdmi_calc_CTS(clock, &CTS, N, 48000); + WREG32(offset+R600_HDMI_48kHz_CTS, CTS << 12); + WREG32(offset+R600_HDMI_48kHz_N, N); +} + +/* + * calculate the crc for a given info frame + */ +static void r600_hdmi_infoframe_checksum(uint8_t packetType, + uint8_t versionNumber, + uint8_t length, + uint8_t *frame) +{ + int i; + frame[0] = packetType + versionNumber + length; + for (i = 1; i <= length; i++) + frame[0] += frame[i]; + frame[0] = 0x100 - frame[0]; +} + +/* + * build a HDMI Video Info Frame + */ +static void r600_hdmi_videoinfoframe( + struct drm_encoder *encoder, + enum r600_hdmi_color_format color_format, + int active_information_present, + uint8_t active_format_aspect_ratio, + uint8_t scan_information, + uint8_t colorimetry, + uint8_t ex_colorimetry, + uint8_t quantization, + int ITC, + uint8_t picture_aspect_ratio, + uint8_t video_format_identification, + uint8_t pixel_repetition, + uint8_t non_uniform_picture_scaling, + uint8_t bar_info_data_valid, + uint16_t top_bar, + uint16_t bottom_bar, + uint16_t left_bar, + uint16_t right_bar +) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset; + + uint8_t frame[14]; + + frame[0x0] = 0; + frame[0x1] = + (scan_information & 0x3) | + ((bar_info_data_valid & 0x3) << 2) | + ((active_information_present & 0x1) << 4) | + ((color_format & 0x3) << 5); + frame[0x2] = + (active_format_aspect_ratio & 0xF) | + ((picture_aspect_ratio & 0x3) << 4) | + ((colorimetry & 0x3) << 6); + frame[0x3] = + (non_uniform_picture_scaling & 0x3) | + ((quantization & 0x3) << 2) | + ((ex_colorimetry & 0x7) << 4) | + ((ITC & 0x1) << 7); + frame[0x4] = (video_format_identification & 0x7F); + frame[0x5] = (pixel_repetition & 0xF); + frame[0x6] = (top_bar & 0xFF); + frame[0x7] = (top_bar >> 8); + frame[0x8] = (bottom_bar & 0xFF); + frame[0x9] = (bottom_bar >> 8); + frame[0xA] = (left_bar & 0xFF); + frame[0xB] = (left_bar >> 8); + frame[0xC] = (right_bar & 0xFF); + frame[0xD] = (right_bar >> 8); + + r600_hdmi_infoframe_checksum(0x82, 0x02, 0x0D, frame); + + WREG32(offset+R600_HDMI_VIDEOINFOFRAME_0, + frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24)); + WREG32(offset+R600_HDMI_VIDEOINFOFRAME_1, + frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x7] << 24)); + WREG32(offset+R600_HDMI_VIDEOINFOFRAME_2, + frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24)); + WREG32(offset+R600_HDMI_VIDEOINFOFRAME_3, + frame[0xC] | (frame[0xD] << 8)); +} + +/* + * build a Audio Info Frame + */ +static void r600_hdmi_audioinfoframe( + struct drm_encoder *encoder, + uint8_t channel_count, + uint8_t coding_type, + uint8_t sample_size, + uint8_t sample_frequency, + uint8_t format, + uint8_t channel_allocation, + uint8_t level_shift, + int downmix_inhibit +) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset; + + uint8_t frame[11]; + + frame[0x0] = 0; + frame[0x1] = (channel_count & 0x7) | ((coding_type & 0xF) << 4); + frame[0x2] = (sample_size & 0x3) | ((sample_frequency & 0x7) << 2); + frame[0x3] = format; + frame[0x4] = channel_allocation; + frame[0x5] = ((level_shift & 0xF) << 3) | ((downmix_inhibit & 0x1) << 7); + frame[0x6] = 0; + frame[0x7] = 0; + frame[0x8] = 0; + frame[0x9] = 0; + frame[0xA] = 0; + + r600_hdmi_infoframe_checksum(0x84, 0x01, 0x0A, frame); + + WREG32(offset+R600_HDMI_AUDIOINFOFRAME_0, + frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24)); + WREG32(offset+R600_HDMI_AUDIOINFOFRAME_1, + frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x8] << 24)); +} + +/* + * test if audio buffer is filled enough to start playing + */ +static int r600_hdmi_is_audio_buffer_filled(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset; + + return (RREG32(offset+R600_HDMI_STATUS) & 0x10) != 0; +} + +/* + * have buffer status changed since last call? + */ +int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + int status, result; + + if (!radeon_encoder->hdmi_offset) + return 0; + + status = r600_hdmi_is_audio_buffer_filled(encoder); + result = radeon_encoder->hdmi_buffer_status != status; + radeon_encoder->hdmi_buffer_status = status; + + return result; +} + +/* + * write the audio workaround status to the hardware + */ +void r600_hdmi_audio_workaround(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t offset = radeon_encoder->hdmi_offset; + + if (!offset) + return; + + if (r600_hdmi_is_audio_buffer_filled(encoder)) { + /* disable audio workaround and start delivering of audio frames */ + WREG32_P(offset+R600_HDMI_CNTL, 0x00000001, ~0x00001001); + + } else if (radeon_encoder->hdmi_audio_workaround) { + /* enable audio workaround and start delivering of audio frames */ + WREG32_P(offset+R600_HDMI_CNTL, 0x00001001, ~0x00001001); + + } else { + /* disable audio workaround and stop delivering of audio frames */ + WREG32_P(offset+R600_HDMI_CNTL, 0x00000000, ~0x00001001); + } +} + + +/* + * update the info frames with the data from the current display mode + */ +void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset; + + if (!offset) + return; + + r600_audio_set_clock(encoder, mode->clock); + + WREG32(offset+R600_HDMI_UNKNOWN_0, 0x1000); + WREG32(offset+R600_HDMI_UNKNOWN_1, 0x0); + WREG32(offset+R600_HDMI_UNKNOWN_2, 0x1000); + + r600_hdmi_update_ACR(encoder, mode->clock); + + WREG32(offset+R600_HDMI_VIDEOCNTL, 0x13); + + WREG32(offset+R600_HDMI_VERSION, 0x202); + + r600_hdmi_videoinfoframe(encoder, RGB, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + /* it's unknown what these bits do excatly, but it's indeed quite usefull for debugging */ + WREG32(offset+R600_HDMI_AUDIO_DEBUG_0, 0x00FFFFFF); + WREG32(offset+R600_HDMI_AUDIO_DEBUG_1, 0x007FFFFF); + WREG32(offset+R600_HDMI_AUDIO_DEBUG_2, 0x00000001); + WREG32(offset+R600_HDMI_AUDIO_DEBUG_3, 0x00000001); + + r600_hdmi_audio_workaround(encoder); + + /* audio packets per line, does anyone know how to calc this ? */ + WREG32_P(offset+R600_HDMI_CNTL, 0x00040000, ~0x001F0000); + + /* update? reset? don't realy know */ + WREG32_P(offset+R600_HDMI_CNTL, 0x14000000, ~0x14000000); +} + +/* + * update settings with current parameters from audio engine + */ +void r600_hdmi_update_audio_settings(struct drm_encoder *encoder, + int channels, + int rate, + int bps, + uint8_t status_bits, + uint8_t category_code) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset; + + uint32_t iec; + + if (!offset) + return; + + DRM_DEBUG("%s with %d channels, %d Hz sampling rate, %d bits per sample,\n", + r600_hdmi_is_audio_buffer_filled(encoder) ? "playing" : "stopped", + channels, rate, bps); + DRM_DEBUG("0x%02X IEC60958 status bits and 0x%02X category code\n", + (int)status_bits, (int)category_code); + + iec = 0; + if (status_bits & AUDIO_STATUS_PROFESSIONAL) + iec |= 1 << 0; + if (status_bits & AUDIO_STATUS_NONAUDIO) + iec |= 1 << 1; + if (status_bits & AUDIO_STATUS_COPYRIGHT) + iec |= 1 << 2; + if (status_bits & AUDIO_STATUS_EMPHASIS) + iec |= 1 << 3; + + iec |= category_code << 8; + + switch (rate) { + case 32000: iec |= 0x3 << 24; break; + case 44100: iec |= 0x0 << 24; break; + case 88200: iec |= 0x8 << 24; break; + case 176400: iec |= 0xc << 24; break; + case 48000: iec |= 0x2 << 24; break; + case 96000: iec |= 0xa << 24; break; + case 192000: iec |= 0xe << 24; break; + } + + WREG32(offset+R600_HDMI_IEC60958_1, iec); + + iec = 0; + switch (bps) { + case 16: iec |= 0x2; break; + case 20: iec |= 0x3; break; + case 24: iec |= 0xb; break; + } + if (status_bits & AUDIO_STATUS_V) + iec |= 0x5 << 16; + + WREG32_P(offset+R600_HDMI_IEC60958_2, iec, ~0x5000f); + + /* 0x021 or 0x031 sets the audio frame length */ + WREG32(offset+R600_HDMI_AUDIOCNTL, 0x31); + r600_hdmi_audioinfoframe(encoder, channels-1, 0, 0, 0, 0, 0, 0, 0); + + r600_hdmi_audio_workaround(encoder); + + /* update? reset? don't realy know */ + WREG32_P(offset+R600_HDMI_CNTL, 0x04000000, ~0x04000000); +} + +/* + * enable/disable the HDMI engine + */ +void r600_hdmi_enable(struct drm_encoder *encoder, int enable) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset; + + if (!offset) + return; + + DRM_DEBUG("%s HDMI interface @ 0x%04X\n", enable ? "Enabling" : "Disabling", offset); + + /* some version of atombios ignore the enable HDMI flag + * so enabling/disabling HDMI was moved here for TMDS1+2 */ + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + WREG32_P(AVIVO_TMDSA_CNTL, enable ? 0x4 : 0x0, ~0x4); + WREG32(offset+R600_HDMI_ENABLE, enable ? 0x101 : 0x0); + break; + + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + WREG32_P(AVIVO_LVTMA_CNTL, enable ? 0x4 : 0x0, ~0x4); + WREG32(offset+R600_HDMI_ENABLE, enable ? 0x105 : 0x0); + break; + + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + /* This part is doubtfull in my opinion */ + WREG32(offset+R600_HDMI_ENABLE, enable ? 0x110 : 0x0); + break; + + default: + DRM_ERROR("unknown HDMI output type\n"); + break; + } +} + +/* + * determin at which register offset the HDMI encoder is + */ +void r600_hdmi_init(struct drm_encoder *encoder) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + radeon_encoder->hdmi_offset = R600_HDMI_TMDS1; + break; + + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + switch (r600_audio_tmds_index(encoder)) { + case 0: + radeon_encoder->hdmi_offset = R600_HDMI_TMDS1; + break; + case 1: + radeon_encoder->hdmi_offset = R600_HDMI_TMDS2; + break; + default: + radeon_encoder->hdmi_offset = 0; + break; + } + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + radeon_encoder->hdmi_offset = R600_HDMI_TMDS2; + break; + + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + radeon_encoder->hdmi_offset = R600_HDMI_DIG; + break; + + default: + radeon_encoder->hdmi_offset = 0; + break; + } + + DRM_DEBUG("using HDMI engine at offset 0x%04X for encoder 0x%x\n", + radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); + + /* TODO: make this configureable */ + radeon_encoder->hdmi_audio_workaround = 0; +} diff --git a/drivers/gpu/drm/radeon/r600_reg.h b/drivers/gpu/drm/radeon/r600_reg.h index e2d1f5f33f7..d0e28ffdeda 100644 --- a/drivers/gpu/drm/radeon/r600_reg.h +++ b/drivers/gpu/drm/radeon/r600_reg.h @@ -110,5 +110,79 @@ #define R600_BIOS_6_SCRATCH 0x173c #define R600_BIOS_7_SCRATCH 0x1740 +/* Audio, these regs were reverse enginered, + * so the chance is high that the naming is wrong + * R6xx+ ??? */ + +/* Audio clocks */ +#define R600_AUDIO_PLL1_MUL 0x0514 +#define R600_AUDIO_PLL1_DIV 0x0518 +#define R600_AUDIO_PLL2_MUL 0x0524 +#define R600_AUDIO_PLL2_DIV 0x0528 +#define R600_AUDIO_CLK_SRCSEL 0x0534 + +/* Audio general */ +#define R600_AUDIO_ENABLE 0x7300 +#define R600_AUDIO_TIMING 0x7344 + +/* Audio params */ +#define R600_AUDIO_VENDOR_ID 0x7380 +#define R600_AUDIO_REVISION_ID 0x7384 +#define R600_AUDIO_ROOT_NODE_COUNT 0x7388 +#define R600_AUDIO_NID1_NODE_COUNT 0x738c +#define R600_AUDIO_NID1_TYPE 0x7390 +#define R600_AUDIO_SUPPORTED_SIZE_RATE 0x7394 +#define R600_AUDIO_SUPPORTED_CODEC 0x7398 +#define R600_AUDIO_SUPPORTED_POWER_STATES 0x739c +#define R600_AUDIO_NID2_CAPS 0x73a0 +#define R600_AUDIO_NID3_CAPS 0x73a4 +#define R600_AUDIO_NID3_PIN_CAPS 0x73a8 + +/* Audio conn list */ +#define R600_AUDIO_CONN_LIST_LEN 0x73ac +#define R600_AUDIO_CONN_LIST 0x73b0 + +/* Audio verbs */ +#define R600_AUDIO_RATE_BPS_CHANNEL 0x73c0 +#define R600_AUDIO_PLAYING 0x73c4 +#define R600_AUDIO_IMPLEMENTATION_ID 0x73c8 +#define R600_AUDIO_CONFIG_DEFAULT 0x73cc +#define R600_AUDIO_PIN_SENSE 0x73d0 +#define R600_AUDIO_PIN_WIDGET_CNTL 0x73d4 +#define R600_AUDIO_STATUS_BITS 0x73d8 + +/* HDMI base register addresses */ +#define R600_HDMI_TMDS1 0x7400 +#define R600_HDMI_TMDS2 0x7700 +#define R600_HDMI_DIG 0x7800 + +/* HDMI registers */ +#define R600_HDMI_ENABLE 0x00 +#define R600_HDMI_STATUS 0x04 +#define R600_HDMI_CNTL 0x08 +#define R600_HDMI_UNKNOWN_0 0x0C +#define R600_HDMI_AUDIOCNTL 0x10 +#define R600_HDMI_VIDEOCNTL 0x14 +#define R600_HDMI_VERSION 0x18 +#define R600_HDMI_UNKNOWN_1 0x28 +#define R600_HDMI_VIDEOINFOFRAME_0 0x54 +#define R600_HDMI_VIDEOINFOFRAME_1 0x58 +#define R600_HDMI_VIDEOINFOFRAME_2 0x5c +#define R600_HDMI_VIDEOINFOFRAME_3 0x60 +#define R600_HDMI_32kHz_CTS 0xac +#define R600_HDMI_32kHz_N 0xb0 +#define R600_HDMI_44_1kHz_CTS 0xb4 +#define R600_HDMI_44_1kHz_N 0xb8 +#define R600_HDMI_48kHz_CTS 0xbc +#define R600_HDMI_48kHz_N 0xc0 +#define R600_HDMI_AUDIOINFOFRAME_0 0xcc +#define R600_HDMI_AUDIOINFOFRAME_1 0xd0 +#define R600_HDMI_IEC60958_1 0xd4 +#define R600_HDMI_IEC60958_2 0xd8 +#define R600_HDMI_UNKNOWN_2 0xdc +#define R600_HDMI_AUDIO_DEBUG_0 0xe0 +#define R600_HDMI_AUDIO_DEBUG_1 0xe4 +#define R600_HDMI_AUDIO_DEBUG_2 0xe8 +#define R600_HDMI_AUDIO_DEBUG_3 0xec #endif diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index e3c494097f6..cd650fd3964 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -89,6 +89,7 @@ extern int radeon_testing; extern int radeon_connector_table; extern int radeon_tv; extern int radeon_new_pll; +extern int radeon_audio; /* * Copy from radeon_drv.h so we don't have to include both and have conflicting @@ -814,6 +815,14 @@ struct radeon_device { struct r600_ih ih; /* r6/700 interrupt ring */ struct workqueue_struct *wq; struct work_struct hotplug_work; + + /* audio stuff */ + struct timer_list audio_timer; + int audio_channels; + int audio_rate; + int audio_bits_per_sample; + uint8_t audio_status_bits; + uint8_t audio_category_code; }; int radeon_device_init(struct radeon_device *rdev, @@ -1147,6 +1156,21 @@ extern void r600_irq_fini(struct radeon_device *rdev); extern void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size); extern int r600_irq_set(struct radeon_device *rdev); +extern int r600_audio_init(struct radeon_device *rdev); +extern int r600_audio_tmds_index(struct drm_encoder *encoder); +extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock); +extern void r600_audio_fini(struct radeon_device *rdev); +extern void r600_hdmi_init(struct drm_encoder *encoder); +extern void r600_hdmi_enable(struct drm_encoder *encoder, int enable); +extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); +extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); +extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder, + int channels, + int rate, + int bps, + uint8_t status_bits, + uint8_t category_code); + #include "radeon_object.h" #endif diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index c5c45e626d7..dbd56ef82f9 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -87,6 +87,7 @@ int radeon_testing = 0; int radeon_connector_table = 0; int radeon_tv = 1; int radeon_new_pll = 1; +int radeon_audio = 1; MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); module_param_named(no_wb, radeon_no_wb, int, 0444); @@ -124,6 +125,9 @@ module_param_named(tv, radeon_tv, int, 0444); MODULE_PARM_DESC(new_pll, "Select new PLL code for AVIVO chips"); module_param_named(new_pll, radeon_new_pll, int, 0444); +MODULE_PARM_DESC(audio, "Audio enable (0 = disable)"); +module_param_named(audio, radeon_audio, int, 0444); + static int radeon_suspend(struct drm_device *dev, pm_message_t state) { drm_radeon_private_t *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index b4f23ec9320..0d1d908e522 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -438,6 +438,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); union lvds_encoder_control args; int index = 0; + int hdmi_detected = 0; uint8_t frev, crev; struct radeon_encoder_atom_dig *dig; struct drm_connector *connector; @@ -458,6 +459,9 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) if (!radeon_connector->con_priv) return; + if (drm_detect_hdmi_monitor(radeon_connector->edid)) + hdmi_detected = 1; + dig_connector = radeon_connector->con_priv; memset(&args, 0, sizeof(args)); @@ -487,7 +491,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) case 1: args.v1.ucMisc = 0; args.v1.ucAction = action; - if (drm_detect_hdmi_monitor(radeon_connector->edid)) + if (hdmi_detected) args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { @@ -512,7 +516,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) if (dig->coherent_mode) args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT; } - if (drm_detect_hdmi_monitor(radeon_connector->edid)) + if (hdmi_detected) args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); args.v2.ucTruncate = 0; @@ -552,7 +556,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) } atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); - + r600_hdmi_enable(encoder, hdmi_detected); } int @@ -893,7 +897,6 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t } atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); - } static void @@ -1162,7 +1165,6 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) } atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); - } static void @@ -1265,6 +1267,8 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, break; } atombios_apply_encoder_quirks(encoder, adjusted_mode); + + r600_hdmi_setmode(encoder, adjusted_mode); } static bool @@ -1510,4 +1514,6 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); break; } + + r600_hdmi_init(encoder); } diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 44d4b652ea1..3dcbe130c42 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -334,6 +334,9 @@ struct radeon_encoder { enum radeon_rmx_type rmx_type; struct drm_display_mode native_mode; void *enc_priv; + int hdmi_offset; + int hdmi_audio_workaround; + int hdmi_buffer_status; }; struct radeon_connector_atom_dig { -- cgit From 6234077d6bad4db25d516743b6723c1b26505341 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 15 Dec 2009 21:46:58 +0100 Subject: drm/radeon/kms: init pm on all chipsets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 2 ++ drivers/gpu/drm/radeon/r300.c | 2 ++ drivers/gpu/drm/radeon/radeon_pm.c | 7 +++++-- drivers/gpu/drm/radeon/rs400.c | 2 ++ 4 files changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 824cc6480a0..44d599aded9 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -3399,6 +3399,8 @@ int r100_init(struct radeon_device *rdev) r100_errata(rdev); /* Initialize clocks */ radeon_get_clock_info(rdev->ddev); + /* Initialize power management */ + radeon_pm_init(rdev); /* Get vram informations */ r100_vram_info(rdev); /* Initialize memory controller (also test AGP) */ diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 83378c39d0e..e47af526fc0 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -1324,6 +1324,8 @@ int r300_init(struct radeon_device *rdev) r300_errata(rdev); /* Initialize clocks */ radeon_get_clock_info(rdev->ddev); + /* Initialize power management */ + radeon_pm_init(rdev); /* Get vram informations */ r300_vram_info(rdev); /* Initialize memory controller (also test AGP) */ diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 34b08d307c8..8bce64cdc32 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -44,8 +44,11 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; struct radeon_device *rdev = dev->dev_private; - seq_printf(m, "engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev)); - seq_printf(m, "memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev)); + seq_printf(m, "default engine clock: %u0 kHz\n", rdev->clock.default_sclk); + seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev)); + seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk); + if (rdev->asic->get_memory_clock) + seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev)); return 0; } diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index c1fcdddb6be..368415df5f3 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -497,6 +497,8 @@ int rs400_init(struct radeon_device *rdev) /* Initialize clocks */ radeon_get_clock_info(rdev->ddev); + /* Initialize power management */ + radeon_pm_init(rdev); /* Get vram informations */ rs400_vram_info(rdev); /* Initialize memory controller (also test AGP) */ -- cgit From 6e7267721fd67d626433ea10c59fc232c6928259 Mon Sep 17 00:00:00 2001 From: Maciej Cencora Date: Tue, 15 Dec 2009 23:13:08 +0100 Subject: drm/radeon/kms: allow for texture tiling This adds the relocations for texture tiling for KMS. Signed-off-by: Maciej Cencora Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r300.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index e47af526fc0..dbb149060b1 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -686,7 +686,15 @@ static int r300_packet0_check(struct radeon_cs_parser *p, r100_cs_dump_packet(p, pkt); return r; } - ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); + + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= R300_TXO_MACRO_TILE; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + tile_flags |= R300_TXO_MICRO_TILE; + + tmp = idx_value + ((u32)reloc->lobj.gpu_offset); + tmp |= tile_flags; + ib[idx] = tmp; track->textures[i].robj = reloc->robj; break; /* Tracked registers */ -- cgit From d785d78bbdb53580b12c40e820af5a3281ce2fc8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 7 Dec 2009 13:16:06 +1000 Subject: drm/radeon/kms: fix r100->r500 CS checker for compressed textures. (v2) This adds support for compressed textures to the r100->r500 CS checker, it lets me run openarena and the demos in mesa fine. Thanks to Maciej Cencora for initial comments. Changes since v1: fix calculations with Maciej formulas Reviewed-by: Maciej Cencora Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 52 ++++++++++++++++++++++++++++++++++--- drivers/gpu/drm/radeon/r100_track.h | 5 ++++ drivers/gpu/drm/radeon/r200.c | 10 +++++-- drivers/gpu/drm/radeon/r300.c | 12 ++++++--- 4 files changed, 70 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 44d599aded9..84e5df766d3 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1374,7 +1374,6 @@ static int r100_packet0_check(struct radeon_cs_parser *p, case RADEON_TXFORMAT_ARGB4444: case RADEON_TXFORMAT_VYUY422: case RADEON_TXFORMAT_YVYU422: - case RADEON_TXFORMAT_DXT1: case RADEON_TXFORMAT_SHADOW16: case RADEON_TXFORMAT_LDUDV655: case RADEON_TXFORMAT_DUDV88: @@ -1382,12 +1381,19 @@ static int r100_packet0_check(struct radeon_cs_parser *p, break; case RADEON_TXFORMAT_ARGB8888: case RADEON_TXFORMAT_RGBA8888: - case RADEON_TXFORMAT_DXT23: - case RADEON_TXFORMAT_DXT45: case RADEON_TXFORMAT_SHADOW32: case RADEON_TXFORMAT_LDUDUV8888: track->textures[i].cpp = 4; break; + case RADEON_TXFORMAT_DXT1: + track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_DXT1; + break; + case RADEON_TXFORMAT_DXT23: + case RADEON_TXFORMAT_DXT45: + track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_DXT35; + break; } track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf); track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf); @@ -2731,6 +2737,7 @@ static inline void r100_cs_track_texture_print(struct r100_cs_track_texture *t) DRM_ERROR("coordinate type %d\n", t->tex_coord_type); DRM_ERROR("width round to power of 2 %d\n", t->roundup_w); DRM_ERROR("height round to power of 2 %d\n", t->roundup_h); + DRM_ERROR("compress format %d\n", t->compress_format); } static int r100_cs_track_cube(struct radeon_device *rdev, @@ -2760,6 +2767,36 @@ static int r100_cs_track_cube(struct radeon_device *rdev, return 0; } +static int r100_track_compress_size(int compress_format, int w, int h) +{ + int block_width, block_height, block_bytes; + int wblocks, hblocks; + int min_wblocks; + int sz; + + block_width = 4; + block_height = 4; + + switch (compress_format) { + case R100_TRACK_COMP_DXT1: + block_bytes = 8; + min_wblocks = 4; + break; + default: + case R100_TRACK_COMP_DXT35: + block_bytes = 16; + min_wblocks = 2; + break; + } + + hblocks = (h + block_height - 1) / block_height; + wblocks = (w + block_width - 1) / block_width; + if (wblocks < min_wblocks) + wblocks = min_wblocks; + sz = wblocks * hblocks * block_bytes; + return sz; +} + static int r100_cs_track_texture_check(struct radeon_device *rdev, struct r100_cs_track *track) { @@ -2797,9 +2834,15 @@ static int r100_cs_track_texture_check(struct radeon_device *rdev, h = h / (1 << i); if (track->textures[u].roundup_h) h = roundup_pow_of_two(h); - size += w * h; + if (track->textures[u].compress_format) { + + size += r100_track_compress_size(track->textures[u].compress_format, w, h); + /* compressed textures are block based */ + } else + size += w * h; } size *= track->textures[u].cpp; + switch (track->textures[u].tex_coord_type) { case 0: break; @@ -2967,6 +3010,7 @@ void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track track->arrays[i].esize = 0x7F; } for (i = 0; i < track->num_texture; i++) { + track->textures[i].compress_format = R100_TRACK_COMP_NONE; track->textures[i].pitch = 16536; track->textures[i].width = 16536; track->textures[i].height = 16536; diff --git a/drivers/gpu/drm/radeon/r100_track.h b/drivers/gpu/drm/radeon/r100_track.h index ca50903dd2b..7188c3778ee 100644 --- a/drivers/gpu/drm/radeon/r100_track.h +++ b/drivers/gpu/drm/radeon/r100_track.h @@ -28,6 +28,10 @@ struct r100_cs_cube_info { unsigned height; }; +#define R100_TRACK_COMP_NONE 0 +#define R100_TRACK_COMP_DXT1 1 +#define R100_TRACK_COMP_DXT35 2 + struct r100_cs_track_texture { struct radeon_bo *robj; struct r100_cs_cube_info cube_info[5]; /* info for 5 non-primary faces */ @@ -44,6 +48,7 @@ struct r100_cs_track_texture { bool enabled; bool roundup_w; bool roundup_h; + unsigned compress_format; }; struct r100_cs_track_limits { diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c index eb740fc3549..20942127c46 100644 --- a/drivers/gpu/drm/radeon/r200.c +++ b/drivers/gpu/drm/radeon/r200.c @@ -401,7 +401,6 @@ int r200_packet0_check(struct radeon_cs_parser *p, case R200_TXFORMAT_Y8: track->textures[i].cpp = 1; break; - case R200_TXFORMAT_DXT1: case R200_TXFORMAT_AI88: case R200_TXFORMAT_ARGB1555: case R200_TXFORMAT_RGB565: @@ -418,9 +417,16 @@ int r200_packet0_check(struct radeon_cs_parser *p, case R200_TXFORMAT_ABGR8888: case R200_TXFORMAT_BGR111110: case R200_TXFORMAT_LDVDU8888: + track->textures[i].cpp = 4; + break; + case R200_TXFORMAT_DXT1: + track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_DXT1; + break; case R200_TXFORMAT_DXT23: case R200_TXFORMAT_DXT45: - track->textures[i].cpp = 4; + track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_DXT1; break; } track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf); diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index dbb149060b1..83490c2b506 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -860,7 +860,6 @@ static int r300_packet0_check(struct radeon_cs_parser *p, case R300_TX_FORMAT_Z6Y5X5: case R300_TX_FORMAT_W4Z4Y4X4: case R300_TX_FORMAT_W1Z5Y5X5: - case R300_TX_FORMAT_DXT1: case R300_TX_FORMAT_D3DMFT_CxV8U8: case R300_TX_FORMAT_B8G8_B8G8: case R300_TX_FORMAT_G8R8_G8B8: @@ -874,8 +873,6 @@ static int r300_packet0_check(struct radeon_cs_parser *p, case 0x17: case R300_TX_FORMAT_FL_I32: case 0x1e: - case R300_TX_FORMAT_DXT3: - case R300_TX_FORMAT_DXT5: track->textures[i].cpp = 4; break; case R300_TX_FORMAT_W16Z16Y16X16: @@ -886,6 +883,15 @@ static int r300_packet0_check(struct radeon_cs_parser *p, case R300_TX_FORMAT_FL_R32G32B32A32: track->textures[i].cpp = 16; break; + case R300_TX_FORMAT_DXT1: + track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_DXT1; + break; + case R300_TX_FORMAT_DXT3: + case R300_TX_FORMAT_DXT5: + track->textures[i].cpp = 1; + track->textures[i].compress_format = R100_TRACK_COMP_DXT35; + break; default: DRM_ERROR("Invalid texture format %u\n", (idx_value & 0x1F)); -- cgit From ed8b67040965e4fe695db333d5914e18ea5f146f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 16 Dec 2009 22:17:09 +0000 Subject: drm: convert drm_ioctl to unlocked_ioctl drm_ioctl is called with the Big Kernel Lock held, which shows up very high in statistics on vfs_ioctl. Moving the lock into the drm_ioctl function itself makes sure we blame the right subsystem and it gets us one step closer to eliminating the locked version of fops->ioctl. Since drm_ioctl does not require the lock itself, we only need to hold it while calling the specific handler. The 32 bit conversion handlers do not interact with any other code, so they don't need the BKL here either and can just call drm_ioctl. As a bonus, this cleans up all the other users of drm_ioctl which now no longer have to find the inode or call lock_kernel. [airlied: squashed the non-driver bits of the second patch in here, this provides the flag for drivers to use to select unlocked ioctls - but doesn't modify any drivers]. Signed-off-by: Arnd Bergmann Cc: David Airlie Cc: dri-devel@lists.sourceforge.net Cc: Frederic Weisbecker Cc: Thomas Gleixner Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_drv.c | 4 ++-- drivers/gpu/drm/radeon/radeon_ioc32.c | 38 +++++++++++------------------------ 2 files changed, 14 insertions(+), 28 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index dbd56ef82f9..8ba3de7994d 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -196,7 +196,7 @@ static struct drm_driver driver_old = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .ioctl = drm_ioctl, + .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, @@ -284,7 +284,7 @@ static struct drm_driver kms_driver = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .ioctl = drm_ioctl, + .unlocked_ioctl = drm_ioctl, .mmap = radeon_mmap, .poll = drm_poll, .fasync = drm_fasync, diff --git a/drivers/gpu/drm/radeon/radeon_ioc32.c b/drivers/gpu/drm/radeon/radeon_ioc32.c index a1bf11de308..48b7cea31e0 100644 --- a/drivers/gpu/drm/radeon/radeon_ioc32.c +++ b/drivers/gpu/drm/radeon/radeon_ioc32.c @@ -92,8 +92,7 @@ static int compat_radeon_cp_init(struct file *file, unsigned int cmd, &init->gart_textures_offset)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init); + return drm_ioctl(file, DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init); } typedef struct drm_radeon_clear32 { @@ -125,8 +124,7 @@ static int compat_radeon_cp_clear(struct file *file, unsigned int cmd, &clr->depth_boxes)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr); + return drm_ioctl(file, DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr); } typedef struct drm_radeon_stipple32 { @@ -149,8 +147,7 @@ static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd, &request->mask)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request); } typedef struct drm_radeon_tex_image32 { @@ -204,8 +201,7 @@ static int compat_radeon_cp_texture(struct file *file, unsigned int cmd, &image->data)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request); } typedef struct drm_radeon_vertex2_32 { @@ -238,8 +234,7 @@ static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd, &request->prim)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request); } typedef struct drm_radeon_cmd_buffer32 { @@ -268,8 +263,7 @@ static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd, &request->boxes)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request); } typedef struct drm_radeon_getparam32 { @@ -293,8 +287,7 @@ static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd, &request->value)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request); } typedef struct drm_radeon_mem_alloc32 { @@ -322,8 +315,7 @@ static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd, &request->region_offset)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_ALLOC, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_RADEON_ALLOC, (unsigned long)request); } typedef struct drm_radeon_irq_emit32 { @@ -345,8 +337,7 @@ static int compat_radeon_irq_emit(struct file *file, unsigned int cmd, &request->irq_seq)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request); } /* The two 64-bit arches where alignof(u64)==4 in 32-bit code */ @@ -372,8 +363,7 @@ static int compat_radeon_cp_setparam(struct file *file, unsigned int cmd, &request->value)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, - DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request); + return drm_ioctl(file, DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request); } #else #define compat_radeon_cp_setparam NULL @@ -413,12 +403,10 @@ long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls)) fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE]; - lock_kernel(); /* XXX for now */ if (fn != NULL) ret = (*fn) (filp, cmd, arg); else - ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); - unlock_kernel(); + ret = drm_ioctl(filp, cmd, arg); return ret; } @@ -431,9 +419,7 @@ long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long if (nr < DRM_COMMAND_BASE) return drm_compat_ioctl(filp, cmd, arg); - lock_kernel(); /* XXX for now */ - ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); - unlock_kernel(); + ret = drm_ioctl(filp, cmd, arg); return ret; } -- cgit From 01136acff8cc8251822fbae77f11e8029049c6f1 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 21 Dec 2009 02:24:47 +0100 Subject: DRM: Rename clamp variable linux/kernel.h has a "clamp" macro, but r300_cmdbuf also uses a variable with the same name. Right now it doesn't seem to include the header, but sooner or later someone will. So better rename the variable now. Signed-off-by: Andi Kleen Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r300_cmdbuf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c index cb2e470f97d..34bffa0e4b7 100644 --- a/drivers/gpu/drm/radeon/r300_cmdbuf.c +++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c @@ -990,7 +990,7 @@ static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv, int sz; int addr; int type; - int clamp; + int isclamp; int stride; RING_LOCALS; @@ -999,10 +999,10 @@ static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv, addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo; type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE); - clamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP); + isclamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP); addr |= (type << 16); - addr |= (clamp << 17); + addr |= (isclamp << 17); stride = type ? 4 : 6; -- cgit From e265f39e1ff026dcc787f1953c048f3de5aefd16 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 19 Dec 2009 08:16:33 +0100 Subject: drivers/gpu: Use kzalloc for allocating only one thing Use kzalloc rather than kcalloc(1,...) The use of the allocated memory that looks like an array is &p->relocs[0], but this should be the same as p->relocs. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ @@ - kcalloc(1, + kzalloc( ...) // Signed-off-by: Julia Lawall Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600_cs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 0d820764f34..44060b92d9e 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -170,7 +170,7 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p, idx, relocs_chunk->length_dw); return -EINVAL; } - *cs_reloc = &p->relocs[0]; + *cs_reloc = p->relocs; (*cs_reloc)->lobj.gpu_offset = (u64)relocs_chunk->kdata[idx + 3] << 32; (*cs_reloc)->lobj.gpu_offset |= relocs_chunk->kdata[idx + 0]; return 0; @@ -717,7 +717,7 @@ static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p) if (p->chunk_relocs_idx == -1) { return 0; } - p->relocs = kcalloc(1, sizeof(struct radeon_cs_reloc), GFP_KERNEL); + p->relocs = kzalloc(sizeof(struct radeon_cs_reloc), GFP_KERNEL); if (p->relocs == NULL) { return -ENOMEM; } -- cgit From 794f3141a194a4f4c28c1d417b071a901f78d9bb Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 20 Dec 2009 16:08:40 +1000 Subject: drm/radeon: fix build on 64-bit with some compilers. drivers/gpu/drm/radeon/radeon_test.c:45: undefined reference to `__udivdi3' Reported-by: Mr. James W. Laferriere Cc: stable@kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c index 391c973ec4d..9f5e2f929da 100644 --- a/drivers/gpu/drm/radeon/radeon_test.c +++ b/drivers/gpu/drm/radeon/radeon_test.c @@ -42,8 +42,8 @@ void radeon_test_moves(struct radeon_device *rdev) /* Number of tests = * (Total GTT - IB pool - writeback page - ring buffer) / test size */ - n = (rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - RADEON_GPU_PAGE_SIZE - - rdev->cp.ring_size) / size; + n = ((u32)(rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - RADEON_GPU_PAGE_SIZE - + rdev->cp.ring_size)) / size; gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL); if (!gtt_obj) { -- cgit From edc664e314d5dadc326cfc15a536fe906d652204 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 17 Dec 2009 11:22:01 -0500 Subject: drm/radeon/kms/atom: fill in proper defines for digital setup Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 0d1d908e522..547fe105e19 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -495,9 +495,9 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { - if (dig->lvds_misc & (1 << 0)) + if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL) args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; - if (dig->lvds_misc & (1 << 1)) + if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB) args.v1.ucMisc |= (1 << 1); } else { if (dig_connector->linkb) @@ -524,18 +524,18 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) args.v2.ucTemporal = 0; args.v2.ucFRC = 0; if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { - if (dig->lvds_misc & (1 << 0)) + if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL) args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; - if (dig->lvds_misc & (1 << 5)) { + if (dig->lvds_misc & ATOM_PANEL_MISC_SPATIAL) { args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; - if (dig->lvds_misc & (1 << 1)) + if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB) args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; } - if (dig->lvds_misc & (1 << 6)) { + if (dig->lvds_misc & ATOM_PANEL_MISC_TEMPORAL) { args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; - if (dig->lvds_misc & (1 << 1)) + if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB) args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; - if (((dig->lvds_misc >> 2) & 0x3) == 2) + if (((dig->lvds_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2) args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; } } else { -- cgit From 310a82c8c5fc431913fe34a17251118e71c2c876 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 17 Dec 2009 01:24:59 -0500 Subject: drm/radeon/kms: fix legacy rmx This makes 640x480 on my R100 work again, both in aspect and centered mode. Signed-off-by: Alex Deucher Tested-by: Dave Airlie Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 2 ++ drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 5 ++--- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 2 ++ 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 547fe105e19..ccba95f83d1 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -233,6 +233,8 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, if (!ASIC_IS_AVIVO(rdev)) { adjusted_mode->hdisplay = mode->hdisplay; adjusted_mode->vdisplay = mode->vdisplay; + adjusted_mode->crtc_hdisplay = mode->hdisplay; + adjusted_mode->crtc_vdisplay = mode->vdisplay; } adjusted_mode->base.id = mode_id; } diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index b82ede98e15..cc27485a07a 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -43,8 +43,7 @@ static void radeon_overscan_setup(struct drm_crtc *crtc, } static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; @@ -1059,7 +1058,7 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc, radeon_set_pll(crtc, adjusted_mode); radeon_overscan_setup(crtc, adjusted_mode); if (radeon_crtc->crtc_id == 0) { - radeon_legacy_rmx_mode_set(crtc, mode, adjusted_mode); + radeon_legacy_rmx_mode_set(crtc, adjusted_mode); } else { if (radeon_crtc->rmx_type != RMX_OFF) { /* FIXME: only first crtc has rmx what should we diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index df00515e81f..981508ff703 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -207,6 +207,8 @@ static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder, *adjusted_mode = *native_mode; adjusted_mode->hdisplay = mode->hdisplay; adjusted_mode->vdisplay = mode->vdisplay; + adjusted_mode->crtc_hdisplay = mode->hdisplay; + adjusted_mode->crtc_vdisplay = mode->vdisplay; adjusted_mode->base.id = mode_id; } -- cgit From d79766fab9975c6414ebab7d2abf017834a48c35 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 17 Dec 2009 19:00:29 -0500 Subject: drm/radeon/kms: set proper default tv standard we were just using 1 before. reported on irc by soreau Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atombios.c | 56 ++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_combios.c | 9 +++-- drivers/gpu/drm/radeon/radeon_connectors.c | 4 +-- drivers/gpu/drm/radeon/radeon_display.c | 2 +- drivers/gpu/drm/radeon/radeon_mode.h | 6 ++++ 5 files changed, 69 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 12a0c760e7f..b5912c26b1d 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1234,6 +1234,61 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, return true; } +enum radeon_tv_std +radeon_atombios_get_tv_info(struct radeon_device *rdev) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, AnalogTV_Info); + uint16_t data_offset; + uint8_t frev, crev; + struct _ATOM_ANALOG_TV_INFO *tv_info; + enum radeon_tv_std tv_std = TV_STD_NTSC; + + atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset); + + tv_info = (struct _ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset); + + switch (tv_info->ucTV_BootUpDefaultStandard) { + case ATOM_TV_NTSC: + tv_std = TV_STD_NTSC; + DRM_INFO("Default TV standard: NTSC\n"); + break; + case ATOM_TV_NTSCJ: + tv_std = TV_STD_NTSC_J; + DRM_INFO("Default TV standard: NTSC-J\n"); + break; + case ATOM_TV_PAL: + tv_std = TV_STD_PAL; + DRM_INFO("Default TV standard: PAL\n"); + break; + case ATOM_TV_PALM: + tv_std = TV_STD_PAL_M; + DRM_INFO("Default TV standard: PAL-M\n"); + break; + case ATOM_TV_PALN: + tv_std = TV_STD_PAL_N; + DRM_INFO("Default TV standard: PAL-N\n"); + break; + case ATOM_TV_PALCN: + tv_std = TV_STD_PAL_CN; + DRM_INFO("Default TV standard: PAL-CN\n"); + break; + case ATOM_TV_PAL60: + tv_std = TV_STD_PAL_60; + DRM_INFO("Default TV standard: PAL-60\n"); + break; + case ATOM_TV_SECAM: + tv_std = TV_STD_SECAM; + DRM_INFO("Default TV standard: SECAM\n"); + break; + default: + tv_std = TV_STD_NTSC; + DRM_INFO("Unknown TV standard; defaulting to NTSC\n"); + break; + } + return tv_std; +} + struct radeon_encoder_tv_dac * radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder) { @@ -1269,6 +1324,7 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder) dac = dac_info->ucDAC2_NTSC_DAC_Adjustment; tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); + tv_dac->tv_std = radeon_atombios_get_tv_info(rdev); } return tv_dac; } diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index c5021a3445d..fd94dbca33a 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -634,11 +634,10 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct return p_dac; } -static enum radeon_tv_std -radeon_combios_get_tv_info(struct radeon_encoder *encoder) +enum radeon_tv_std +radeon_combios_get_tv_info(struct radeon_device *rdev) { - struct drm_device *dev = encoder->base.dev; - struct radeon_device *rdev = dev->dev_private; + struct drm_device *dev = rdev->ddev; uint16_t tv_info; enum radeon_tv_std tv_std = TV_STD_NTSC; @@ -779,7 +778,7 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); found = 1; } - tv_dac->tv_std = radeon_combios_get_tv_info(encoder); + tv_dac->tv_std = radeon_combios_get_tv_info(rdev); } if (!found) { /* then check CRT table */ diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 5eece186e03..8da06e17ff2 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -1171,7 +1171,7 @@ radeon_add_atom_connector(struct drm_device *dev, 1); drm_connector_attach_property(&radeon_connector->base, rdev->mode_info.tv_std_property, - 1); + radeon_atombios_get_tv_info(rdev)); } break; case DRM_MODE_CONNECTOR_LVDS: @@ -1315,7 +1315,7 @@ radeon_add_legacy_connector(struct drm_device *dev, 1); drm_connector_attach_property(&radeon_connector->base, rdev->mode_info.tv_std_property, - 1); + radeon_combios_get_tv_info(rdev)); } break; case DRM_MODE_CONNECTOR_LVDS: diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index a133b833e45..91d72b70abc 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -739,7 +739,7 @@ static struct drm_prop_enum_list radeon_tv_std_enum_list[] = { TV_STD_SECAM, "secam" }, }; -int radeon_modeset_create_props(struct radeon_device *rdev) +static int radeon_modeset_create_props(struct radeon_device *rdev) { int i, sz; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 3dcbe130c42..402369db5ba 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -88,6 +88,7 @@ enum radeon_tv_std { TV_STD_SCART_PAL, TV_STD_SECAM, TV_STD_PAL_CN, + TV_STD_PAL_N, }; /* radeon gpio-based i2c @@ -395,6 +396,11 @@ struct radeon_framebuffer { struct drm_gem_object *obj; }; +extern enum radeon_tv_std +radeon_combios_get_tv_info(struct radeon_device *rdev); +extern enum radeon_tv_std +radeon_atombios_get_tv_info(struct radeon_device *rdev); + extern void radeon_connector_hotplug(struct drm_connector *connector); extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector); extern int radeon_dp_mode_valid_helper(struct radeon_connector *radeon_connector, -- cgit From c31ad97f1886a2ff0f3356dc31d50c57944365da Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 17 Dec 2009 00:00:46 +0100 Subject: drm/radeon/kms: prevent parallel AtomBIOS calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This just adds a mutex around the atombios table execution so we don't call it from two contexts at once. Signed-off-by: Rafał Miłecki Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atom.c | 12 ++++++++++-- drivers/gpu/drm/radeon/atom.h | 1 + drivers/gpu/drm/radeon/radeon_device.c | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index 6578d19dff9..388140a7e65 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -58,6 +58,7 @@ typedef struct { } atom_exec_context; int atom_debug = 0; +static void atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params); void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params); static uint32_t atom_arg_mask[8] = @@ -573,7 +574,7 @@ static void atom_op_calltable(atom_exec_context *ctx, int *ptr, int arg) else SDEBUG(" table: %d\n", idx); if (U16(ctx->ctx->cmd_table + 4 + 2 * idx)) - atom_execute_table(ctx->ctx, idx, ctx->ps + ctx->ps_shift); + atom_execute_table_locked(ctx->ctx, idx, ctx->ps + ctx->ps_shift); } static void atom_op_clear(atom_exec_context *ctx, int *ptr, int arg) @@ -1040,7 +1041,7 @@ static struct { atom_op_shr, ATOM_ARG_MC}, { atom_op_debug, 0},}; -void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) +static void atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params) { int base = CU16(ctx->cmd_table + 4 + 2 * index); int len, ws, ps, ptr; @@ -1092,6 +1093,13 @@ void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) kfree(ectx.ws); } +void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) +{ + mutex_lock(&ctx->mutex); + atom_execute_table_locked(ctx, index, params); + mutex_unlock(&ctx->mutex); +} + static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 }; static void atom_index_iio(struct atom_context *ctx, int base) diff --git a/drivers/gpu/drm/radeon/atom.h b/drivers/gpu/drm/radeon/atom.h index 6671848e5ea..47fd943f6d1 100644 --- a/drivers/gpu/drm/radeon/atom.h +++ b/drivers/gpu/drm/radeon/atom.h @@ -120,6 +120,7 @@ struct card_info { struct atom_context { struct card_info *card; + struct mutex mutex; void *bios; uint32_t cmd_table, data_table; uint16_t *iio; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 02bcdb1240c..99b95ca42a7 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -481,6 +481,7 @@ int radeon_atombios_init(struct radeon_device *rdev) atom_card_info->pll_write = cail_pll_write; rdev->mode_info.atom_context = atom_parse(atom_card_info, rdev->bios); + mutex_init(&rdev->mode_info.atom_context->mutex); radeon_atom_initialize_bios_scratch_regs(rdev->ddev); atom_allocate_fb_scratch(rdev->mode_info.atom_context); return 0; -- cgit From 5ea597f3764880ab3a67fe2246218634a8c12778 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 17 Dec 2009 13:50:09 +0100 Subject: drm/radeon/kms: enable memory clock reading on legacy (V2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit V2: detect IGP cards (which don't have own memory) Signed-off-by: Rafał Miłecki Acked-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_asic.h | 7 ++++--- drivers/gpu/drm/radeon/radeon_clocks.c | 2 +- drivers/gpu/drm/radeon/radeon_device.c | 6 ++++++ 3 files changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 636116bedcb..eb29217bbf1 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -33,6 +33,7 @@ */ uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev); void radeon_legacy_set_engine_clock(struct radeon_device *rdev, uint32_t eng_clock); +uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev); void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable); uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev); @@ -106,7 +107,7 @@ static struct radeon_asic r100_asic = { .copy = &r100_copy_blit, .get_engine_clock = &radeon_legacy_get_engine_clock, .set_engine_clock = &radeon_legacy_set_engine_clock, - .get_memory_clock = NULL, + .get_memory_clock = &radeon_legacy_get_memory_clock, .set_memory_clock = NULL, .set_pcie_lanes = NULL, .set_clock_gating = &radeon_legacy_set_clock_gating, @@ -166,7 +167,7 @@ static struct radeon_asic r300_asic = { .copy = &r100_copy_blit, .get_engine_clock = &radeon_legacy_get_engine_clock, .set_engine_clock = &radeon_legacy_set_engine_clock, - .get_memory_clock = NULL, + .get_memory_clock = &radeon_legacy_get_memory_clock, .set_memory_clock = NULL, .set_pcie_lanes = &rv370_set_pcie_lanes, .set_clock_gating = &radeon_legacy_set_clock_gating, @@ -259,7 +260,7 @@ static struct radeon_asic rs400_asic = { .copy = &r100_copy_blit, .get_engine_clock = &radeon_legacy_get_engine_clock, .set_engine_clock = &radeon_legacy_set_engine_clock, - .get_memory_clock = NULL, + .get_memory_clock = &radeon_legacy_get_memory_clock, .set_memory_clock = NULL, .set_pcie_lanes = NULL, .set_clock_gating = &radeon_legacy_set_clock_gating, diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c index b062109efbe..812f24dbc2a 100644 --- a/drivers/gpu/drm/radeon/radeon_clocks.c +++ b/drivers/gpu/drm/radeon/radeon_clocks.c @@ -62,7 +62,7 @@ uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev) } /* 10 khz */ -static uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev) +uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev) { struct radeon_pll *mpll = &rdev->clock.mpll; uint32_t fb_div, ref_div, post_div, mclk; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 99b95ca42a7..14df3ad64f9 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -391,6 +391,12 @@ int radeon_asic_init(struct radeon_device *rdev) /* FIXME: not supported yet */ return -EINVAL; } + + if (rdev->flags & RADEON_IS_IGP) { + rdev->asic->get_memory_clock = NULL; + rdev->asic->set_memory_clock = NULL; + } + return 0; } -- cgit From 46c64d4bfa01cda7d58c514164f8b127ab6741b7 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Thu, 17 Dec 2009 06:02:28 +0100 Subject: drm/radeon/kms: allow rendering while no colorbuffer is set on r300 Because hardware cannot disable all colorbuffers directly to do depth-only rendering, a user should: - disable reading from a colorbuffer in blending - disable fastfill - set the color channel mask to 0 to prevent writing to a colorbuffer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 4 ++++ drivers/gpu/drm/radeon/r100_track.h | 4 +++- drivers/gpu/drm/radeon/r300.c | 12 ++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 84e5df766d3..71727460968 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -2881,6 +2881,10 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) for (i = 0; i < track->num_cb; i++) { if (track->cb[i].robj == NULL) { + if (!(track->fastfill || track->color_channel_mask || + track->blend_read_enable)) { + continue; + } DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); return -EINVAL; } diff --git a/drivers/gpu/drm/radeon/r100_track.h b/drivers/gpu/drm/radeon/r100_track.h index 7188c3778ee..b27a6999d21 100644 --- a/drivers/gpu/drm/radeon/r100_track.h +++ b/drivers/gpu/drm/radeon/r100_track.h @@ -67,13 +67,15 @@ struct r100_cs_track { unsigned immd_dwords; unsigned num_arrays; unsigned max_indx; + unsigned color_channel_mask; struct r100_cs_track_array arrays[11]; struct r100_cs_track_cb cb[R300_MAX_CB]; struct r100_cs_track_cb zb; struct r100_cs_track_texture textures[R300_TRACK_MAX_TEXTURE]; bool z_enabled; bool separate_cube; - + bool fastfill; + bool blend_read_enable; }; int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track); diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 83490c2b506..6a5d1177afa 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -992,6 +992,18 @@ static int r300_packet0_check(struct radeon_cs_parser *p, } ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); break; + case 0x4e0c: + /* RB3D_COLOR_CHANNEL_MASK */ + track->color_channel_mask = idx_value; + break; + case 0x4d1c: + /* ZB_BW_CNTL */ + track->fastfill = !!(idx_value & (1 << 2)); + break; + case 0x4e04: + /* RB3D_BLENDCNTL */ + track->blend_read_enable = !!(idx_value & (1 << 2)); + break; case 0x4be8: /* valid register only on RV530 */ if (p->rdev->family == CHIP_RV530) -- cgit From 512889f450c1851d9e3628f1894b9b64b0701eac Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Sat, 19 Dec 2009 00:23:00 +0100 Subject: drm/radeon/kms: add 3DC compression support There are 2 formats: ATI1N: 64 bits per 4x4 block, one-channel format ATI2N: 128 bits per 4x4 block, two-channel format Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r300.c | 18 ++++++++++++++++++ drivers/gpu/drm/radeon/r300_reg.h | 1 + 2 files changed, 19 insertions(+) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 6a5d1177afa..3f2cc9e2e8d 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -887,6 +887,14 @@ static int r300_packet0_check(struct radeon_cs_parser *p, track->textures[i].cpp = 1; track->textures[i].compress_format = R100_TRACK_COMP_DXT1; break; + case R300_TX_FORMAT_ATI2N: + if (p->rdev->family < CHIP_R420) { + DRM_ERROR("Invalid texture format %u\n", + (idx_value & 0x1F)); + return -EINVAL; + } + /* The same rules apply as for DXT3/5. */ + /* Pass through. */ case R300_TX_FORMAT_DXT3: case R300_TX_FORMAT_DXT5: track->textures[i].cpp = 1; @@ -951,6 +959,16 @@ static int r300_packet0_check(struct radeon_cs_parser *p, track->textures[i].width_11 = tmp; tmp = ((idx_value >> 16) & 1) << 11; track->textures[i].height_11 = tmp; + + /* ATI1N */ + if (idx_value & (1 << 14)) { + /* The same rules apply as for DXT1. */ + track->textures[i].compress_format = + R100_TRACK_COMP_DXT1; + } + } else if (idx_value & (1 << 14)) { + DRM_ERROR("Forbidden bit TXFORMAT_MSB\n"); + return -EINVAL; } break; case 0x4480: diff --git a/drivers/gpu/drm/radeon/r300_reg.h b/drivers/gpu/drm/radeon/r300_reg.h index 4b7afef35a6..1735a2b6958 100644 --- a/drivers/gpu/drm/radeon/r300_reg.h +++ b/drivers/gpu/drm/radeon/r300_reg.h @@ -900,6 +900,7 @@ # define R300_TX_FORMAT_FL_I32 0x1B # define R300_TX_FORMAT_FL_I32A32 0x1C # define R300_TX_FORMAT_FL_R32G32B32A32 0x1D +# define R300_TX_FORMAT_ATI2N 0x1F /* alpha modes, convenience mostly */ /* if you have alpha, pick constant appropriate to the number of channels (1 for I8, 2 for I8A8, 4 for R8G8B8A8, etc */ -- cgit From d2efdf6d6f425950a61fa5cc3aa22e6718e7f3c8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 22 Dec 2009 10:06:49 -0500 Subject: drm/radeon/kms: add cvt mode if we only have lvds w/h and no edid (v4) This fixes LVDS on some mac laptops without a panel edid. v2 - Set proper mode type flags v3 - Note that this is not neceesarily the exact panel mode, but an approximation based on the cvt formula. For these systems we should ideally read the mode info out of the registers or add a mode table, but this works and is much simpler. v4 - Update comments and debug message. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 8da06e17ff2..20161567dbf 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -208,6 +208,18 @@ static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encode drm_mode_set_name(mode); DRM_DEBUG("Adding native panel mode %s\n", mode->name); + } else if (native_mode->hdisplay != 0 && + native_mode->vdisplay != 0) { + /* mac laptops without an edid */ + /* Note that this is not necessarily the exact panel mode, + * but an approximation based on the cvt formula. For these + * systems we should ideally read the mode info out of the + * registers or add a mode table, but this works and is much + * simpler. + */ + mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false); + mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; + DRM_DEBUG("Adding cvt approximation of native panel mode %s\n", mode->name); } return mode; } -- cgit From 0a0c7596c643239e8d4c3eaaba43b74a96f2411e Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 11 Dec 2009 20:36:19 +0100 Subject: drm/radeon/kms: Avoid crash when trying to cleanup uninitialized structure Add boolean to record if some part of the driver are initialized or not this allow to avoid a crash when trying to cleanup uninitialized structure members. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon.h | 4 +++- drivers/gpu/drm/radeon/radeon_fence.c | 9 ++++++--- drivers/gpu/drm/radeon/radeon_ttm.c | 4 ++++ 3 files changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index cd650fd3964..53b55608102 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -162,6 +162,7 @@ struct radeon_fence_driver { struct list_head created; struct list_head emited; struct list_head signaled; + bool initialized; }; struct radeon_fence { @@ -202,8 +203,9 @@ struct radeon_surface_reg { struct radeon_mman { struct ttm_bo_global_ref bo_global_ref; struct ttm_global_reference mem_global_ref; - bool mem_global_referenced; struct ttm_bo_device bdev; + bool mem_global_referenced; + bool initialized; }; struct radeon_bo { diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index cb4cd97ae39..4cdd8b4f754 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -324,7 +324,7 @@ int radeon_fence_driver_init(struct radeon_device *rdev) write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); r = radeon_scratch_get(rdev, &rdev->fence_drv.scratch_reg); if (r) { - DRM_ERROR("Fence failed to get a scratch register."); + dev_err(rdev->dev, "fence failed to get scratch register\n"); write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); return r; } @@ -335,9 +335,10 @@ int radeon_fence_driver_init(struct radeon_device *rdev) INIT_LIST_HEAD(&rdev->fence_drv.signaled); rdev->fence_drv.count_timeout = 0; init_waitqueue_head(&rdev->fence_drv.queue); + rdev->fence_drv.initialized = true; write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); if (radeon_debugfs_fence_init(rdev)) { - DRM_ERROR("Failed to register debugfs file for fence !\n"); + dev_err(rdev->dev, "fence debugfs file creation failed\n"); } return 0; } @@ -346,11 +347,13 @@ void radeon_fence_driver_fini(struct radeon_device *rdev) { unsigned long irq_flags; + if (!rdev->fence_drv.initialized) + return; wake_up_all(&rdev->fence_drv.queue); write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); radeon_scratch_free(rdev, rdev->fence_drv.scratch_reg); write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); - DRM_INFO("radeon: fence finalized\n"); + rdev->fence_drv.initialized = false; } diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 7bed4122528..a00450743d6 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -494,6 +494,7 @@ int radeon_ttm_init(struct radeon_device *rdev) DRM_ERROR("failed initializing buffer object driver(%d).\n", r); return r; } + rdev->mman.initialized = true; r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, rdev->mc.real_vram_size >> PAGE_SHIFT); if (r) { @@ -541,6 +542,8 @@ void radeon_ttm_fini(struct radeon_device *rdev) { int r; + if (!rdev->mman.initialized) + return; if (rdev->stollen_vga_memory) { r = radeon_bo_reserve(rdev->stollen_vga_memory, false); if (r == 0) { @@ -554,6 +557,7 @@ void radeon_ttm_fini(struct radeon_device *rdev) ttm_bo_device_release(&rdev->mman.bdev); radeon_gart_fini(rdev); radeon_ttm_global_fini(rdev); + rdev->mman.initialized = false; DRM_INFO("radeon: ttm finalized\n"); } -- cgit From 3642133816f9f25065e3ca310f0720574bcdcc52 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 11 Dec 2009 21:18:34 +0100 Subject: drm/radeon/kms: Check module arguments to be valid V2 This patch add a function which check module argument to be valid. On invalid argument it prints a warning and setback the default value. V2: Allow 0 for vram limit & agp mode which are the default value Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_device.c | 73 +++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 14df3ad64f9..7c6848096bc 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -546,9 +546,72 @@ void radeon_agp_disable(struct radeon_device *rdev) } } -/* - * Radeon device. - */ +void radeon_check_arguments(struct radeon_device *rdev) +{ + /* vramlimit must be a power of two */ + switch (radeon_vram_limit) { + case 0: + case 4: + case 8: + case 16: + case 32: + case 64: + case 128: + case 256: + case 512: + case 1024: + case 2048: + case 4096: + break; + default: + dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n", + radeon_vram_limit); + radeon_vram_limit = 0; + break; + } + radeon_vram_limit = radeon_vram_limit << 20; + /* gtt size must be power of two and greater or equal to 32M */ + switch (radeon_gart_size) { + case 4: + case 8: + case 16: + dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n", + radeon_gart_size); + radeon_gart_size = 512; + break; + case 32: + case 64: + case 128: + case 256: + case 512: + case 1024: + case 2048: + case 4096: + break; + default: + dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n", + radeon_gart_size); + radeon_gart_size = 512; + break; + } + rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; + /* AGP mode can only be -1, 1, 2, 4, 8 */ + switch (radeon_agpmode) { + case -1: + case 0: + case 1: + case 2: + case 4: + case 8: + break; + default: + dev_warn(rdev->dev, "invalid AGP mode %d (valid mode: " + "-1, 0, 1, 2, 4, 8)\n", radeon_agpmode); + radeon_agpmode = 0; + break; + } +} + int radeon_device_init(struct radeon_device *rdev, struct drm_device *ddev, struct pci_dev *pdev, @@ -587,9 +650,9 @@ int radeon_device_init(struct radeon_device *rdev, /* Set asic functions */ r = radeon_asic_init(rdev); - if (r) { + if (r) return r; - } + radeon_check_arguments(rdev); if (rdev->flags & RADEON_IS_AGP && radeon_agpmode == -1) { radeon_agp_disable(rdev); -- cgit From f56cd64f5f713a3013c4d980a5695c198d839671 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 18 Dec 2009 11:28:22 -0500 Subject: drm/radeon/kms: never combine LVDS with another encoder When linking multiple encoders to a connector, make sure to not link LVDS with another connector. Some bioses have the same i2c line for LVDS and VGA. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atombios.c | 49 +++++++++++++++----------------- 1 file changed, 23 insertions(+), 26 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index b5912c26b1d..321044bef71 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -745,8 +745,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct else radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, - (1 << - i), + (1 << i), dac), (1 << i)); } @@ -758,32 +757,30 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct if (bios_connectors[j].valid && (i != j)) { if (bios_connectors[i].line_mux == bios_connectors[j].line_mux) { - if (((bios_connectors[i]. - devices & - (ATOM_DEVICE_DFP_SUPPORT)) - && (bios_connectors[j]. - devices & - (ATOM_DEVICE_CRT_SUPPORT))) - || - ((bios_connectors[j]. - devices & - (ATOM_DEVICE_DFP_SUPPORT)) - && (bios_connectors[i]. - devices & - (ATOM_DEVICE_CRT_SUPPORT)))) { - bios_connectors[i]. - devices |= - bios_connectors[j]. - devices; - bios_connectors[i]. - connector_type = - DRM_MODE_CONNECTOR_DVII; - if (bios_connectors[j].devices & - (ATOM_DEVICE_DFP_SUPPORT)) + /* make sure not to combine LVDS */ + if (bios_connectors[i].devices & (ATOM_DEVICE_LCD_SUPPORT)) { + bios_connectors[i].line_mux = 53; + bios_connectors[i].ddc_bus.valid = false; + continue; + } + if (bios_connectors[j].devices & (ATOM_DEVICE_LCD_SUPPORT)) { + bios_connectors[j].line_mux = 53; + bios_connectors[j].ddc_bus.valid = false; + continue; + } + /* combine analog and digital for DVI-I */ + if (((bios_connectors[i].devices & (ATOM_DEVICE_DFP_SUPPORT)) && + (bios_connectors[j].devices & (ATOM_DEVICE_CRT_SUPPORT))) || + ((bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT)) && + (bios_connectors[i].devices & (ATOM_DEVICE_CRT_SUPPORT)))) { + bios_connectors[i].devices |= + bios_connectors[j].devices; + bios_connectors[i].connector_type = + DRM_MODE_CONNECTOR_DVII; + if (bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT)) bios_connectors[i].hpd = bios_connectors[j].hpd; - bios_connectors[j]. - valid = false; + bios_connectors[j].valid = false; } } } -- cgit From 0786201d8cd0730e72b0e087484dd47cc5f58409 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Sat, 19 Dec 2009 12:45:12 -0500 Subject: drm/radeon/kms: add definitions for v4 power tables [airlied: just adding this for completeness to avoid drift between public atombios.h files] Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios.h | 199 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index e83927644de..8e28842080d 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h @@ -4690,6 +4690,205 @@ typedef struct _ATOM_POWERPLAY_INFO_V3 { ATOM_POWERMODE_INFO_V3 asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK]; } ATOM_POWERPLAY_INFO_V3; +/* New PPlib */ +/**************************************************************************/ +typedef struct _ATOM_PPLIB_THERMALCONTROLLER + +{ + UCHAR ucType; // one of ATOM_PP_THERMALCONTROLLER_* + UCHAR ucI2cLine; // as interpreted by DAL I2C + UCHAR ucI2cAddress; + UCHAR ucFanParameters; // Fan Control Parameters. + UCHAR ucFanMinRPM; // Fan Minimum RPM (hundreds) -- for display purposes only. + UCHAR ucFanMaxRPM; // Fan Maximum RPM (hundreds) -- for display purposes only. + UCHAR ucReserved; // ---- + UCHAR ucFlags; // to be defined +} ATOM_PPLIB_THERMALCONTROLLER; + +#define ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f +#define ATOM_PP_FANPARAMETERS_NOFAN 0x80 // No fan is connected to this controller. + +#define ATOM_PP_THERMALCONTROLLER_NONE 0 +#define ATOM_PP_THERMALCONTROLLER_LM63 1 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_ADM1032 2 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_ADM1030 3 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_MUA6649 4 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_LM64 5 +#define ATOM_PP_THERMALCONTROLLER_F75375 6 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_RV6xx 7 +#define ATOM_PP_THERMALCONTROLLER_RV770 8 +#define ATOM_PP_THERMALCONTROLLER_ADT7473 9 + +typedef struct _ATOM_PPLIB_STATE +{ + UCHAR ucNonClockStateIndex; + UCHAR ucClockStateIndices[1]; // variable-sized +} ATOM_PPLIB_STATE; + +//// ATOM_PPLIB_POWERPLAYTABLE::ulPlatformCaps +#define ATOM_PP_PLATFORM_CAP_BACKBIAS 1 +#define ATOM_PP_PLATFORM_CAP_POWERPLAY 2 +#define ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 4 +#define ATOM_PP_PLATFORM_CAP_ASPM_L0s 8 +#define ATOM_PP_PLATFORM_CAP_ASPM_L1 16 +#define ATOM_PP_PLATFORM_CAP_HARDWAREDC 32 +#define ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY 64 +#define ATOM_PP_PLATFORM_CAP_STEPVDDC 128 +#define ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL 256 +#define ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL 512 +#define ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 1024 +#define ATOM_PP_PLATFORM_CAP_HTLINKCONTROL 2048 + +typedef struct _ATOM_PPLIB_POWERPLAYTABLE +{ + ATOM_COMMON_TABLE_HEADER sHeader; + + UCHAR ucDataRevision; + + UCHAR ucNumStates; + UCHAR ucStateEntrySize; + UCHAR ucClockInfoSize; + UCHAR ucNonClockSize; + + // offset from start of this table to array of ucNumStates ATOM_PPLIB_STATE structures + USHORT usStateArrayOffset; + + // offset from start of this table to array of ASIC-specific structures, + // currently ATOM_PPLIB_CLOCK_INFO. + USHORT usClockInfoArrayOffset; + + // offset from start of this table to array of ATOM_PPLIB_NONCLOCK_INFO + USHORT usNonClockInfoArrayOffset; + + USHORT usBackbiasTime; // in microseconds + USHORT usVoltageTime; // in microseconds + USHORT usTableSize; //the size of this structure, or the extended structure + + ULONG ulPlatformCaps; // See ATOM_PPLIB_CAPS_* + + ATOM_PPLIB_THERMALCONTROLLER sThermalController; + + USHORT usBootClockInfoOffset; + USHORT usBootNonClockInfoOffset; + +} ATOM_PPLIB_POWERPLAYTABLE; + +//// ATOM_PPLIB_NONCLOCK_INFO::usClassification +#define ATOM_PPLIB_CLASSIFICATION_UI_MASK 0x0007 +#define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT 0 +#define ATOM_PPLIB_CLASSIFICATION_UI_NONE 0 +#define ATOM_PPLIB_CLASSIFICATION_UI_BATTERY 1 +#define ATOM_PPLIB_CLASSIFICATION_UI_BALANCED 3 +#define ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE 5 +// 2, 4, 6, 7 are reserved + +#define ATOM_PPLIB_CLASSIFICATION_BOOT 0x0008 +#define ATOM_PPLIB_CLASSIFICATION_THERMAL 0x0010 +#define ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE 0x0020 +#define ATOM_PPLIB_CLASSIFICATION_REST 0x0040 +#define ATOM_PPLIB_CLASSIFICATION_FORCED 0x0080 +#define ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE 0x0100 +#define ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE 0x0200 +#define ATOM_PPLIB_CLASSIFICATION_UVDSTATE 0x0400 +#define ATOM_PPLIB_CLASSIFICATION_3DLOW 0x0800 +#define ATOM_PPLIB_CLASSIFICATION_ACPI 0x1000 +// remaining 3 bits are reserved + +//// ATOM_PPLIB_NONCLOCK_INFO::ulCapsAndSettings +#define ATOM_PPLIB_SINGLE_DISPLAY_ONLY 0x00000001 +#define ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK 0x00000002 + +// 0 is 2.5Gb/s, 1 is 5Gb/s +#define ATOM_PPLIB_PCIE_LINK_SPEED_MASK 0x00000004 +#define ATOM_PPLIB_PCIE_LINK_SPEED_SHIFT 2 + +// lanes - 1: 1, 2, 4, 8, 12, 16 permitted by PCIE spec +#define ATOM_PPLIB_PCIE_LINK_WIDTH_MASK 0x000000F8 +#define ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT 3 + +// lookup into reduced refresh-rate table +#define ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK 0x00000F00 +#define ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT 8 + +#define ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED 0 +#define ATOM_PPLIB_LIMITED_REFRESHRATE_50HZ 1 +// 2-15 TBD as needed. + +#define ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING 0x00001000 +#define ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS 0x00002000 +#define ATOM_PPLIB_ENABLE_VARIBRIGHT 0x00008000 + +#define ATOM_PPLIB_DISALLOW_ON_DC 0x00004000 + +// Contained in an array starting at the offset +// in ATOM_PPLIB_POWERPLAYTABLE::usNonClockInfoArrayOffset. +// referenced from ATOM_PPLIB_STATE_INFO::ucNonClockStateIndex +typedef struct _ATOM_PPLIB_NONCLOCK_INFO +{ + USHORT usClassification; + UCHAR ucMinTemperature; + UCHAR ucMaxTemperature; + ULONG ulCapsAndSettings; + UCHAR ucRequiredPower; + UCHAR ucUnused1[3]; +} ATOM_PPLIB_NONCLOCK_INFO; + +// Contained in an array starting at the offset +// in ATOM_PPLIB_POWERPLAYTABLE::usClockInfoArrayOffset. +// referenced from ATOM_PPLIB_STATE::ucClockStateIndices +typedef struct _ATOM_PPLIB_R600_CLOCK_INFO +{ + USHORT usEngineClockLow; + UCHAR ucEngineClockHigh; + + USHORT usMemoryClockLow; + UCHAR ucMemoryClockHigh; + + USHORT usVDDC; + USHORT usUnused1; + USHORT usUnused2; + + ULONG ulFlags; // ATOM_PPLIB_R600_FLAGS_* + +} ATOM_PPLIB_R600_CLOCK_INFO; + +// ulFlags in ATOM_PPLIB_R600_CLOCK_INFO +#define ATOM_PPLIB_R600_FLAGS_PCIEGEN2 1 +#define ATOM_PPLIB_R600_FLAGS_UVDSAFE 2 +#define ATOM_PPLIB_R600_FLAGS_BACKBIASENABLE 4 +#define ATOM_PPLIB_R600_FLAGS_MEMORY_ODT_OFF 8 +#define ATOM_PPLIB_R600_FLAGS_MEMORY_DLL_OFF 16 + +typedef struct _ATOM_PPLIB_RS780_CLOCK_INFO + +{ + USHORT usLowEngineClockLow; // Low Engine clock in MHz (the same way as on the R600). + UCHAR ucLowEngineClockHigh; + USHORT usHighEngineClockLow; // High Engine clock in MHz. + UCHAR ucHighEngineClockHigh; + USHORT usMemoryClockLow; // For now one of the ATOM_PPLIB_RS780_SPMCLK_XXXX constants. + UCHAR ucMemoryClockHigh; // Currentyl unused. + UCHAR ucPadding; // For proper alignment and size. + USHORT usVDDC; // For the 780, use: None, Low, High, Variable + UCHAR ucMaxHTLinkWidth; // From SBIOS - {2, 4, 8, 16} + UCHAR ucMinHTLinkWidth; // From SBIOS - {2, 4, 8, 16}. Effective only if CDLW enabled. Minimum down stream width could be bigger as display BW requriement. + USHORT usHTLinkFreq; // See definition ATOM_PPLIB_RS780_HTLINKFREQ_xxx or in MHz(>=200). + ULONG ulFlags; +} ATOM_PPLIB_RS780_CLOCK_INFO; + +#define ATOM_PPLIB_RS780_VOLTAGE_NONE 0 +#define ATOM_PPLIB_RS780_VOLTAGE_LOW 1 +#define ATOM_PPLIB_RS780_VOLTAGE_HIGH 2 +#define ATOM_PPLIB_RS780_VOLTAGE_VARIABLE 3 + +#define ATOM_PPLIB_RS780_SPMCLK_NONE 0 // We cannot change the side port memory clock, leave it as it is. +#define ATOM_PPLIB_RS780_SPMCLK_LOW 1 +#define ATOM_PPLIB_RS780_SPMCLK_HIGH 2 + +#define ATOM_PPLIB_RS780_HTLINKFREQ_NONE 0 +#define ATOM_PPLIB_RS780_HTLINKFREQ_LOW 1 +#define ATOM_PPLIB_RS780_HTLINKFREQ_HIGH 2 + /**************************************************************************/ /* Following definitions are for compatiblity issue in different SW components. */ -- cgit From b9597a1c6fa6cbc938f14ab6a7fe09047b3a346b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 4 Jan 2010 19:12:02 -0500 Subject: drm/radeon/kms: fallback to default connector table if necessary for combios Some early combios radeon cards don't have a connector table or dac table in the bios, if they do not, fallback to the default tables. Should fix kernel bug 14963. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_display.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 91d72b70abc..1fb2f029d7e 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -329,8 +329,11 @@ static bool radeon_setup_enc_conn(struct drm_device *dev) ret = radeon_get_atom_connector_info_from_object_table(dev); else ret = radeon_get_atom_connector_info_from_supported_devices_table(dev); - } else + } else { ret = radeon_get_legacy_connector_info_from_bios(dev); + if (ret == false) + ret = radeon_get_legacy_connector_info_from_table(dev); + } } else { if (!ASIC_IS_AVIVO(rdev)) ret = radeon_get_legacy_connector_info_from_table(dev); -- cgit From 246263ccc31e4ba2886cca17000bf09ea683eac5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 29 Dec 2009 12:09:17 -0500 Subject: drm/radeon/kms: add primary dac adj values table Look up primary dac adj values from the table if there is no bios or bios dac table to reference. The lookup table may need to be adjusted for certain families. Should fix kernel bug 14945. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_combios.c | 50 +++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index fd94dbca33a..58f342659cc 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -595,6 +595,34 @@ bool radeon_combios_get_clock_info(struct drm_device *dev) return false; } +static const uint32_t default_primarydac_adj[CHIP_LAST] = { + 0x00000808, /* r100 */ + 0x00000808, /* rv100 */ + 0x00000808, /* rs100 */ + 0x00000808, /* rv200 */ + 0x00000808, /* rs200 */ + 0x00000808, /* r200 */ + 0x00000808, /* rv250 */ + 0x00000000, /* rs300 */ + 0x00000808, /* rv280 */ + 0x00000808, /* r300 */ + 0x00000808, /* r350 */ + 0x00000808, /* rv350 */ + 0x00000808, /* rv380 */ + 0x00000808, /* r420 */ + 0x00000808, /* r423 */ + 0x00000808, /* rv410 */ + 0x00000000, /* rs400 */ + 0x00000000, /* rs480 */ +}; + +static void radeon_legacy_get_primary_dac_info_from_table(struct radeon_device *rdev, + struct radeon_encoder_primary_dac *p_dac) +{ + p_dac->ps2_pdac_adj = default_primarydac_adj[rdev->family]; + return; +} + struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct radeon_encoder *encoder) @@ -604,20 +632,20 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct uint16_t dac_info; uint8_t rev, bg, dac; struct radeon_encoder_primary_dac *p_dac = NULL; + int found = 0; - if (rdev->bios == NULL) + p_dac = kzalloc(sizeof(struct radeon_encoder_primary_dac), + GFP_KERNEL); + + if (!p_dac) return NULL; + if (rdev->bios == NULL) + goto out; + /* check CRT table */ dac_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE); if (dac_info) { - p_dac = - kzalloc(sizeof(struct radeon_encoder_primary_dac), - GFP_KERNEL); - - if (!p_dac) - return NULL; - rev = RBIOS8(dac_info) & 0x3; if (rev < 2) { bg = RBIOS8(dac_info + 0x2) & 0xf; @@ -628,9 +656,13 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct dac = RBIOS8(dac_info + 0x3) & 0xf; p_dac->ps2_pdac_adj = (bg << 8) | (dac); } - + found = 1; } +out: + if (!found) /* fallback to defaults */ + radeon_legacy_get_primary_dac_info_from_table(rdev, p_dac); + return p_dac; } -- cgit From 1d3d51b6d2d6fb51c6c30a8c7ed0fd939f6100bf Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 28 Dec 2009 13:45:23 -0500 Subject: drm/radeon/kms: add missing breaks in i2c and ss lookups Should fix fdo bug 25741 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atombios.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 321044bef71..41dd8ebff21 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -114,6 +114,7 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev i2c.i2c_id = gpio->sucI2cId.ucAccess; i2c.valid = true; + break; } } @@ -1026,6 +1027,7 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct ss->delay = ss_info->asSS_Info[i].ucSS_Delay; ss->range = ss_info->asSS_Info[i].ucSS_Range; ss->refdiv = ss_info->asSS_Info[i].ucRecommendedRef_Div; + break; } } } -- cgit From 5eb226132f53d5ec36ce4e7ff9d6b49cceb50f3d Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 6 Jan 2010 17:39:31 +0100 Subject: drm/radeon/kms: fix memory leak Stanse found a memory leak in radeon_master_create. master_priv is not freed/assigned on all paths. Fix that. Signed-off-by: Jiri Slaby Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_cp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 0b2f9c2ad2c..06123ba31d3 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -2145,6 +2145,7 @@ int radeon_master_create(struct drm_device *dev, struct drm_master *master) &master_priv->sarea); if (ret) { DRM_ERROR("SAREA setup failed\n"); + kfree(master_priv); return ret; } master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea); -- cgit From d8a7f79246a447722bd90c2c4ba3ca068b2aa4c0 Mon Sep 17 00:00:00 2001 From: Darren Jenkins Date: Wed, 30 Dec 2009 12:22:55 +1100 Subject: drm/radeon/radeon_connectors.c: add a NULL test before dereference The encoder variable can be NULL in this function so I believe it should be checked before dereference. Coverity CID: 13253 [airlied: extremely unlikely to happen] Signed-off-by: Darren Jenkins Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 20161567dbf..b82ae61d4d1 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -615,7 +615,7 @@ static enum drm_connector_status radeon_vga_detect(struct drm_connector *connect ret = connector_status_connected; } } else { - if (radeon_connector->dac_load_detect) { + if (radeon_connector->dac_load_detect && encoder) { encoder_funcs = encoder->helper_private; ret = encoder_funcs->detect(encoder, connector); } -- cgit From 3655d54af8dd85788c3e5088387469703a0f8f12 Mon Sep 17 00:00:00 2001 From: Darren Jenkins Date: Wed, 30 Dec 2009 12:20:05 +1100 Subject: drm/radeon/radeon_fence.c: move a dereference below the NULL test If a NULL value is possible, the dereference should only occur after the NULL test. Coverity CID: 13334 Signed-off-by: Darren Jenkins Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_fence.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 4cdd8b4f754..8495d4e32e1 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -140,16 +140,15 @@ int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence) bool radeon_fence_signaled(struct radeon_fence *fence) { - struct radeon_device *rdev = fence->rdev; unsigned long irq_flags; bool signaled = false; - if (rdev->gpu_lockup) { + if (!fence) return true; - } - if (fence == NULL) { + + if (fence->rdev->gpu_lockup) return true; - } + write_lock_irqsave(&fence->rdev->fence_drv.lock, irq_flags); signaled = fence->signaled; /* if we are shuting down report all fence as signaled */ -- cgit From 875c186620e017e62b773c93e46af21bb704fe6b Mon Sep 17 00:00:00 2001 From: Darren Jenkins Date: Wed, 30 Dec 2009 12:18:30 +1100 Subject: drm/radeon/radeon_device.c: move a dereference below a NULL test If a NULL value is possible, the dereference should only occur after the NULL test. Coverity CID: 13335 Signed-off-by: Darren Jenkins Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_device.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 7c6848096bc..0c51f8e4661 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -733,16 +733,18 @@ void radeon_device_fini(struct radeon_device *rdev) */ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) { - struct radeon_device *rdev = dev->dev_private; + struct radeon_device *rdev; struct drm_crtc *crtc; int r; - if (dev == NULL || rdev == NULL) { + if (dev == NULL || dev->dev_private == NULL) { return -ENODEV; } if (state.event == PM_EVENT_PRETHAW) { return 0; } + rdev = dev->dev_private; + /* unpin the front buffers */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb); -- cgit From 65aa2f4e8d85b6145ef4834f440a63ab68bd7443 Mon Sep 17 00:00:00 2001 From: Darren Jenkins Date: Wed, 30 Dec 2009 12:16:35 +1100 Subject: gpu/drm/radeon/radeon_irq.c: move a dereference below a NULL test If a NULL value is possible, the dereference should only occur after the NULL test. Coverity CID: 13338 Signed-off-by: Darren Jenkins Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_irq.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c index b79ecc4a7cc..2f349a30019 100644 --- a/drivers/gpu/drm/radeon/radeon_irq.c +++ b/drivers/gpu/drm/radeon/radeon_irq.c @@ -289,16 +289,16 @@ int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_pr drm_radeon_irq_emit_t *emit = data; int result; - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return -EINVAL; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return -EINVAL; + + LOCK_TEST_WITH_RETURN(dev, file_priv); + result = radeon_emit_irq(dev); if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) { -- cgit From 43b19f161c7a9941e3aa7db0e3ee19b93980e3d7 Mon Sep 17 00:00:00 2001 From: Luca Tettamanti Date: Mon, 28 Dec 2009 22:53:05 +0100 Subject: drm/radeon/kms: rs600: use correct mask for SW interrupt The mask happens to be the same, but the IH is reading the status, not the not the control register. Signed-off-by: Luca Tettamanti Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/rs600.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/radeon') diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 4f8ea426057..4245218e954 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -396,7 +396,7 @@ int rs600_irq_process(struct radeon_device *rdev) } while (status || r500_disp_int) { /* SW interrupt */ - if (G_000040_SW_INT_EN(status)) + if (G_000044_SW_INT(status)) radeon_fence_process(rdev); /* Vertical blank interrupts */ if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int)) -- cgit