From patchwork Thu Sep 9 17:07:21 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: nobled X-Patchwork-Id: 164911 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o89HBAqh026151 for ; Thu, 9 Sep 2010 17:11:48 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 3882B9EF54 for ; Thu, 9 Sep 2010 10:11:10 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-gy0-f177.google.com (mail-gy0-f177.google.com [209.85.160.177]) by gabe.freedesktop.org (Postfix) with ESMTP id 6F6099E76B for ; Thu, 9 Sep 2010 10:08:00 -0700 (PDT) Received: by gyg8 with SMTP id 8so542785gyg.36 for ; Thu, 09 Sep 2010 10:07:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:received:mime-version:sender:received:from:date :x-google-sender-auth:message-id:subject:to:content-type :content-transfer-encoding; bh=p87PmxXnmu2x14U76CNueD4LFkLAr6hth6/jDldkP9Y=; b=BuPhuRhYxOwZ/dolLH7KKlKoyqjff8ZakcUvDp1fwhFtncKzaFgo6f/FvvC/PTXekl sw5ybnhTh0InIEFVzqXt5THoeu9V8meEeP41eJYBCyW7N0dys1i7EwoJkxtA8S9hHDQo 2LZ9Q5Av2EPfyzuRSMhJFwu7q9VCbSE8VMbZI= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=mime-version:sender:from:date:x-google-sender-auth:message-id :subject:to:content-type:content-transfer-encoding; b=kVxQT4KVCoelh5btUHgoA6UYcpbLv0lJjMSj2xkfr5/5ckI70XuYJXuHuUANeD0zIv YnTsEt82ibToCNc0ZrR9InR0vsyQP9D2umkvnR6JZna8cSvANDZbvLTIpMiym18QMyhX PuUc2fI36qphe9hF/9MKAJzyyhJK+jh1r6RFQ= Received: by 10.150.216.2 with SMTP id o2mr377145ybg.420.1284052061127; Thu, 09 Sep 2010 10:07:41 -0700 (PDT) MIME-Version: 1.0 Received: by 10.151.98.12 with HTTP; Thu, 9 Sep 2010 10:07:21 -0700 (PDT) From: nobled Date: Thu, 9 Sep 2010 13:07:21 -0400 X-Google-Sender-Auth: TYofayxUi3rp4tvU4zJTq6nUy5g Message-ID: Subject: [PATCH] libkms/radeon: Add backend To: dri-devel@lists.freedesktop.org X-Mailman-Approved-At: Thu, 09 Sep 2010 10:10:11 -0700 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Thu, 09 Sep 2010 17:11:48 +0000 (UTC) X-MIME-Autoconverted: from base64 to 8bit by demeter1.kernel.org id o89HBAqh026151 diff --git a/libkms/Makefile.am b/libkms/Makefile.am index 2c75878..5c2e63f 100644 --- a/libkms/Makefile.am +++ b/libkms/Makefile.am @@ -26,6 +26,10 @@ if HAVE_NOUVEAU libkms_la_SOURCES += nouveau.c endif +if HAVE_RADEON +libkms_la_SOURCES += radeon.c +endif + libkmsincludedir = ${includedir}/libkms libkmsinclude_HEADERS = libkms.h diff --git a/libkms/internal.h b/libkms/internal.h index 63122d1..51f5e65 100644 --- a/libkms/internal.h +++ b/libkms/internal.h @@ -70,4 +70,6 @@ int intel_create(int fd, struct kms_driver **out); int nouveau_create(int fd, struct kms_driver **out); +int radeon_create(int fd, struct kms_driver **out); + #endif diff --git a/libkms/linux.c b/libkms/linux.c index 02182d3..7449abc 100644 --- a/libkms/linux.c +++ b/libkms/linux.c @@ -111,6 +111,10 @@ linux_from_sysfs(int fd, struct kms_driver **out) else if (!strcmp(name, "nouveau")) ret = nouveau_create(fd, out); #endif +#ifdef HAVE_RADEON + else if (!strcmp(name, "radeon")) + ret = radeon_create(fd, out); +#endif else ret = -ENOSYS; diff --git a/libkms/radeon.c b/libkms/radeon.c new file mode 100644 index 0000000..f5e382a --- /dev/null +++ b/libkms/radeon.c @@ -0,0 +1,242 @@ +/************************************************************************** + * + * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * 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, sub license, 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 (including the + * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ + + +#define HAVE_STDINT_H +#define _FILE_OFFSET_BITS 64 + +#include +#include +#include +#include +#include "internal.h" + +#include +#include +#include "xf86drm.h" + +#include "radeon_drm.h" + + +#define ALIGNMENT 512 + +struct radeon_bo +{ + struct kms_bo base; + unsigned map_count; +}; + +static int +radeon_get_prop(struct kms_driver *kms, unsigned key, unsigned *out) +{ + switch (key) { + case KMS_BO_TYPE: + *out = KMS_BO_TYPE_SCANOUT_X8R8G8B8 | KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8; + break; + default: + return -EINVAL; + } + return 0; +} + +static int +radeon_destroy(struct kms_driver *kms) +{ + free(kms); + return 0; +} + +static int +radeon_bo_create(struct kms_driver *kms, + const unsigned width, const unsigned height, + const enum kms_bo_type type, const unsigned *attr, + struct kms_bo **out) +{ + struct drm_radeon_gem_create arg; + unsigned size, pitch; + struct radeon_bo *bo; + int i, ret; + + for (i = 0; attr[i]; i += 2) { + switch (attr[i]) { + case KMS_WIDTH: + case KMS_HEIGHT: + case KMS_BO_TYPE: + break; + default: + return -EINVAL; + } + } + + switch (type) { + case KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8: + pitch = 4 * 64; + size = 4 * 64 * 64; + break; + case KMS_BO_TYPE_SCANOUT_X8R8G8B8: + pitch = width * 4; + pitch = (pitch + ALIGNMENT - 1) & ~(ALIGNMENT - 1); + size = pitch * height; + break; + default: + return -EINVAL; + } + + bo = calloc(1, sizeof(*bo)); + if (!bo) + return -ENOMEM; + + memset(&arg, 0, sizeof(arg)); + arg.size = size; + arg.alignment = ALIGNMENT; + arg.initial_domain = RADEON_GEM_DOMAIN_CPU; + arg.flags = 0; + arg.handle = 0; + + ret = drmCommandWriteRead(kms->fd, DRM_RADEON_GEM_CREATE, + &arg, sizeof(arg)); + if (ret) + goto err_free; + + bo->base.kms = kms; + bo->base.handle = arg.handle; + bo->base.size = size; + bo->base.pitch = pitch; + bo->base.offset = 0; + bo->map_count = 0; + + *out = &bo->base; + + return 0; + +err_free: + free(bo); + return ret; +} + +static int +radeon_bo_get_prop(struct kms_bo *bo, unsigned key, unsigned *out) +{ + switch (key) { + default: + return -EINVAL; + } +} + +static int +radeon_bo_map(struct kms_bo *_bo, void **out) +{ + struct radeon_bo *bo = (struct radeon_bo *)_bo; + struct drm_radeon_gem_mmap arg; + void *map = NULL; + int ret; + + if (bo->base.ptr) { + bo->map_count++; + *out = bo->base.ptr; + return 0; + } + + memset(&arg, 0, sizeof(arg)); + arg.handle = bo->base.handle; + arg.offset = bo->base.offset; + arg.size = (uint64_t)bo->base.size; + + ret = drmCommandWriteRead(bo->base.kms->fd, DRM_RADEON_GEM_MMAP, + &arg, sizeof(arg)); + if (ret) + return -errno; + + map = mmap(0, arg.size, PROT_READ | PROT_WRITE, MAP_SHARED, + bo->base.kms->fd, arg.addr_ptr); + if (map == MAP_FAILED) + return -errno; + + bo->base.ptr = map; + bo->map_count++; + *out = bo->base.ptr; + + return 0; +} + +static int +radeon_bo_unmap(struct kms_bo *_bo) +{ + struct radeon_bo *bo = (struct radeon_bo *)_bo; + if (--bo->map_count == 0) { + munmap(bo->base.ptr, bo->base.size); + bo->base.ptr = NULL; + } + return 0; +} + +static int +radeon_bo_destroy(struct kms_bo *_bo) +{ + struct radeon_bo *bo = (struct radeon_bo *)_bo; + struct drm_gem_close arg; + int ret; + + if (bo->base.ptr) { + /* XXX Sanity check map_count */ + munmap(bo->base.ptr, bo->base.size); + bo->base.ptr = NULL; + } + + memset(&arg, 0, sizeof(arg)); + arg.handle = bo->base.handle; + + ret = drmIoctl(bo->base.kms->fd, DRM_IOCTL_GEM_CLOSE, &arg); + if (ret) + return -errno; + + free(bo); + return 0; +} + +int +radeon_create(int fd, struct kms_driver **out) +{ + struct kms_driver *kms; + + kms = calloc(1, sizeof(*kms)); + if (!kms) + return -ENOMEM; + + kms->fd = fd; + + kms->bo_create = radeon_bo_create; + kms->bo_map = radeon_bo_map; + kms->bo_unmap = radeon_bo_unmap; + kms->bo_get_prop = radeon_bo_get_prop; + kms->bo_destroy = radeon_bo_destroy; + kms->get_prop = radeon_get_prop; + kms->destroy = radeon_destroy; + *out = kms; + + return 0; +}