From patchwork Wed Jun 12 17:13:20 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julia Lemire X-Patchwork-Id: 2711821 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id BCFA2C1459 for ; Wed, 12 Jun 2013 17:31:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8158B20364 for ; Wed, 12 Jun 2013 17:31:55 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 346412036A for ; Wed, 12 Jun 2013 17:31:54 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E4411E5CC4 for ; Wed, 12 Jun 2013 10:31:53 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org X-Greylist: delayed 1064 seconds by postgrey-1.32 at gabe; Wed, 12 Jun 2013 10:31:06 PDT Received: from mtxmxout5.matrox.com (mtxmxout5.matrox.com [138.11.2.95]) by gabe.freedesktop.org (Postfix) with ESMTP id E04C9E5EC8 for ; Wed, 12 Jun 2013 10:31:06 -0700 (PDT) Received: from venus.matrox.com (venus.matrox.com [192.168.1.30]) by mtxmxout5.matrox.com (Postfix) with ESMTP id F41C81C6DA6 for ; Wed, 12 Jun 2013 13:13:35 -0400 (EDT) Received: (from ssmsp@localhost) by venus.matrox.com (8.14.4/8.13.2) id r5CHDZmu007162; Wed, 12 Jun 2013 13:13:35 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by venus.matrox.com (Postfix) with ESMTP id 0A0B3F4DD8; Wed, 12 Jun 2013 13:13:30 -0400 (EDT) X-Virus-MTX-Scanned: by Matrox Virus scanner at venus.matrox.com Received: from matrox.com (dyn-152-165.matrox.com [192.168.152.165]) by venus.matrox.com (Postfix) with ESMTP id E2452F4DD1; Wed, 12 Jun 2013 13:13:20 -0400 (EDT) Message-Id: In-Reply-To: References: From: Julia Lemire Subject: [PATCH 1/1] drm/mgag200: Added resolution and bandwidth limits for various G200e products. To: dri-devel@lists.freedesktop.org Date: Wed, 12 Jun 2013 13:13:20 -0400 (EDT) Cc: Mathieu Larouche X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 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-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This code was ported from the old xorg mga driver. These limits were implemented as a solution to a number of problems that were seen. These problems were linked to the bandwidth limitations of the g200e series. Signed-off-by: Julia Lemire --- drivers/gpu/drm/mgag200/mgag200_drv.h | 41 ++++++++++++------------ drivers/gpu/drm/mgag200/mgag200_main.c | 2 +- drivers/gpu/drm/mgag200/mgag200_mode.c | 55 ++++++++++++++++++++++++++++++-- 3 files changed, 75 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index bf29b2f..710aa29 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -168,37 +168,38 @@ enum mga_type { #define IS_G200_SE(mdev) (mdev->type == G200_SE_A || mdev->type == G200_SE_B) struct mga_device { - struct drm_device *dev; - unsigned long flags; + struct drm_device *dev; + unsigned long flags; - resource_size_t rmmio_base; - resource_size_t rmmio_size; - void __iomem *rmmio; + resource_size_t rmmio_base; + resource_size_t rmmio_size; + void __iomem *rmmio; - drm_local_map_t *framebuffer; + drm_local_map_t *framebuffer; - struct mga_mc mc; - struct mga_mode_info mode_info; + struct mga_mc mc; + struct mga_mode_info mode_info; - struct mga_fbdev *mfbdev; + struct mga_fbdev *mfbdev; - bool suspended; - int num_crtc; - enum mga_type type; - int has_sdram; - struct drm_display_mode mode; + bool suspended; + int num_crtc; + enum mga_type type; + int has_sdram; + struct drm_display_mode mode; - int bpp_shifts[4]; + int bpp_shifts[4]; - int fb_mtrr; + int fb_mtrr; struct { - struct drm_global_reference mem_global_ref; - struct ttm_bo_global_ref bo_global_ref; - struct ttm_bo_device bdev; + struct drm_global_reference mem_global_ref; + struct ttm_bo_global_ref bo_global_ref; + struct ttm_bo_device bdev; } ttm; - u32 reg_1e24; /* SE model number */ + /* SE model number stored in reg 0x1e24 */ + u32 unique_rev_id; }; diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c index 9905923..dafe049 100644 --- a/drivers/gpu/drm/mgag200/mgag200_main.c +++ b/drivers/gpu/drm/mgag200/mgag200_main.c @@ -176,7 +176,7 @@ static int mgag200_device_init(struct drm_device *dev, /* stash G200 SE model number for later use */ if (IS_G200_SE(mdev)) - mdev->reg_1e24 = RREG32(0x1e24); + mdev->unique_rev_id = RREG32(0x1e24); ret = mga_vram_init(mdev); if (ret) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index ee66bad..3cdebe6 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1008,7 +1008,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, if (IS_G200_SE(mdev)) { - if (mdev->reg_1e24 >= 0x02) { + if (mdev->unique_rev_id >= 0x02) { u8 hi_pri_lvl; u32 bpp; u32 mb; @@ -1038,7 +1038,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, WREG8(MGAREG_CRTCEXT_DATA, hi_pri_lvl); } else { WREG8(MGAREG_CRTCEXT_INDEX, 0x06); - if (mdev->reg_1e24 >= 0x01) + if (mdev->unique_rev_id >= 0x01) WREG8(MGAREG_CRTCEXT_DATA, 0x03); else WREG8(MGAREG_CRTCEXT_DATA, 0x04); @@ -1410,6 +1410,24 @@ static int mga_vga_get_modes(struct drm_connector *connector) return ret; } +static uint32_t mga_vga_calculate_mode_bandwidth(struct drm_display_mode * mode, + int bits_per_pixel) +{ + uint64_t active_area, total_area, pixels_per_second; + uint64_t bytes_per_pixel = (bits_per_pixel + 7) / 8; + + if(!mode->htotal || !mode->vtotal || !mode->clock) + return 0; + + active_area = mode->hdisplay * mode->vdisplay; + total_area = mode->htotal * mode->vtotal; + pixels_per_second = active_area * mode->clock * 1000 / total_area; + + return (uint32_t)(pixels_per_second * bytes_per_pixel * 100 / (1024)); +} + +#define MODE_BANDWIDTH MODE_BAD + static int mga_vga_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { @@ -1422,6 +1440,39 @@ static int mga_vga_mode_valid(struct drm_connector *connector, int i = 0; /* FIXME: Add bandwidth and g200se limitations */ + if (IS_G200_SE(mdev)) { + if (mdev->unique_rev_id == 0x01) { + if (mode->hdisplay > 1600) + return MODE_VIRTUAL_X; + if (mode->vdisplay > 1200) + return MODE_VIRTUAL_Y; + if (mga_vga_calculate_mode_bandwidth(mode, bpp) > (24400 * 1024)) + return MODE_BANDWIDTH; + } else if (mdev->unique_rev_id >= 0x02) { + if (mode->hdisplay > 1920) + return MODE_VIRTUAL_X; + if (mode->vdisplay > 1200) + return MODE_VIRTUAL_Y; + if (mga_vga_calculate_mode_bandwidth(mode, bpp) > (30100 * 1024)) + return MODE_BANDWIDTH; + } + } else if (mdev->type == G200_WB) { + if (mode->hdisplay > 1280) + return MODE_VIRTUAL_X; + if (mode->vdisplay > 1024) + return MODE_VIRTUAL_Y; + if (mga_vga_calculate_mode_bandwidth(mode, bpp > (31877 * 1024))) + return MODE_BANDWIDTH; + } else if (mdev->type == G200_EV && + (mga_vga_calculate_mode_bandwidth(mode, bpp) > (32700 * 1024))) { + return MODE_BANDWIDTH; + } else if (mode->type == G200_EH && + (mga_vga_calculate_mode_bandwidth(mode, bpp) > (37500 * 1024))) { + return MODE_BANDWIDTH; + } else if (mode->type == G200_ER && + (mga_vga_calculate_mode_bandwidth(mode, bpp) > (55000 * 1024))) { + return MODE_BANDWIDTH; + } if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 || mode->crtc_hsync_end > 4096 || mode->crtc_htotal > 4096 ||