195584Sanholt/* mga_warp.c -- Matrox G200/G400 WARP engine management -*- linux-c -*- 2152909Sanholt * Created: Thu Jan 11 21:29:32 2001 by gareth@valinux.com 3152909Sanholt */ 4139749Simp/*- 595584Sanholt * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 695584Sanholt * All Rights Reserved. 795584Sanholt * 895584Sanholt * Permission is hereby granted, free of charge, to any person obtaining a 995584Sanholt * copy of this software and associated documentation files (the "Software"), 1095584Sanholt * to deal in the Software without restriction, including without limitation 1195584Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1295584Sanholt * and/or sell copies of the Software, and to permit persons to whom the 1395584Sanholt * Software is furnished to do so, subject to the following conditions: 1495584Sanholt * 1595584Sanholt * The above copyright notice and this permission notice (including the next 1695584Sanholt * paragraph) shall be included in all copies or substantial portions of the 1795584Sanholt * Software. 1895584Sanholt * 1995584Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2095584Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2195584Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2295584Sanholt * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 2395584Sanholt * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2495584Sanholt * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2595584Sanholt * OTHER DEALINGS IN THE SOFTWARE. 2695584Sanholt * 2795584Sanholt * Authors: 2895584Sanholt * Gareth Hughes <gareth@valinux.com> 2995584Sanholt */ 3095584Sanholt 31152909Sanholt#include <sys/cdefs.h> 32152909Sanholt__FBSDID("$FreeBSD$"); 33152909Sanholt 3495584Sanholt#include "dev/drm/drmP.h" 35112015Sanholt#include "dev/drm/drm.h" 3695746Sanholt#include "dev/drm/mga_drm.h" 3795584Sanholt#include "dev/drm/mga_drv.h" 3895584Sanholt#include "dev/drm/mga_ucode.h" 3995584Sanholt 40145132Sanholt#define MGA_WARP_CODE_ALIGN 256 /* in bytes */ 4195584Sanholt 4295584Sanholt#define WARP_UCODE_SIZE( which ) \ 4395584Sanholt ((sizeof(which) / MGA_WARP_CODE_ALIGN + 1) * MGA_WARP_CODE_ALIGN) 4495584Sanholt 4595584Sanholt#define WARP_UCODE_INSTALL( which, where ) \ 4695584Sanholtdo { \ 4795584Sanholt DRM_DEBUG( " pcbase = 0x%08lx vcbase = %p\n", pcbase, vcbase );\ 4895584Sanholt dev_priv->warp_pipe_phys[where] = pcbase; \ 4995584Sanholt memcpy( vcbase, which, sizeof(which) ); \ 5095584Sanholt pcbase += WARP_UCODE_SIZE( which ); \ 5195584Sanholt vcbase += WARP_UCODE_SIZE( which ); \ 5295584Sanholt} while (0) 5395584Sanholt 54152909Sanholtstatic const unsigned int mga_warp_g400_microcode_size = 55152909Sanholt (WARP_UCODE_SIZE(warp_g400_tgz) + 56145132Sanholt WARP_UCODE_SIZE(warp_g400_tgza) + 57145132Sanholt WARP_UCODE_SIZE(warp_g400_tgzaf) + 58145132Sanholt WARP_UCODE_SIZE(warp_g400_tgzf) + 59145132Sanholt WARP_UCODE_SIZE(warp_g400_tgzs) + 60145132Sanholt WARP_UCODE_SIZE(warp_g400_tgzsa) + 61145132Sanholt WARP_UCODE_SIZE(warp_g400_tgzsaf) + 62145132Sanholt WARP_UCODE_SIZE(warp_g400_tgzsf) + 63145132Sanholt WARP_UCODE_SIZE(warp_g400_t2gz) + 64145132Sanholt WARP_UCODE_SIZE(warp_g400_t2gza) + 65145132Sanholt WARP_UCODE_SIZE(warp_g400_t2gzaf) + 66145132Sanholt WARP_UCODE_SIZE(warp_g400_t2gzf) + 67145132Sanholt WARP_UCODE_SIZE(warp_g400_t2gzs) + 68145132Sanholt WARP_UCODE_SIZE(warp_g400_t2gzsa) + 69145132Sanholt WARP_UCODE_SIZE(warp_g400_t2gzsaf) + 70145132Sanholt WARP_UCODE_SIZE(warp_g400_t2gzsf)); 7195584Sanholt 72152909Sanholtstatic const unsigned int mga_warp_g200_microcode_size = 73152909Sanholt (WARP_UCODE_SIZE(warp_g200_tgz) + 74145132Sanholt WARP_UCODE_SIZE(warp_g200_tgza) + 75145132Sanholt WARP_UCODE_SIZE(warp_g200_tgzaf) + 76145132Sanholt WARP_UCODE_SIZE(warp_g200_tgzf) + 77145132Sanholt WARP_UCODE_SIZE(warp_g200_tgzs) + 78145132Sanholt WARP_UCODE_SIZE(warp_g200_tgzsa) + 79145132Sanholt WARP_UCODE_SIZE(warp_g200_tgzsaf) + 80145132Sanholt WARP_UCODE_SIZE(warp_g200_tgzsf)); 8195584Sanholt 8295584Sanholt 83152909Sanholtunsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv) 84152909Sanholt{ 85152909Sanholt switch (dev_priv->chipset) { 86152909Sanholt case MGA_CARD_TYPE_G400: 87152909Sanholt case MGA_CARD_TYPE_G550: 88152909Sanholt return PAGE_ALIGN(mga_warp_g400_microcode_size); 89152909Sanholt case MGA_CARD_TYPE_G200: 90152909Sanholt return PAGE_ALIGN(mga_warp_g200_microcode_size); 91152909Sanholt default: 92152909Sanholt DRM_ERROR("Unknown chipset value: 0x%x\n", dev_priv->chipset); 93152909Sanholt return 0; 94152909Sanholt } 9595584Sanholt} 9695584Sanholt 97145132Sanholtstatic int mga_warp_install_g400_microcode(drm_mga_private_t * dev_priv) 9895584Sanholt{ 99207066Srnoland unsigned char *vcbase = dev_priv->warp->virtual; 10095584Sanholt unsigned long pcbase = dev_priv->warp->offset; 10195584Sanholt 102145132Sanholt memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys)); 10395584Sanholt 104145132Sanholt WARP_UCODE_INSTALL(warp_g400_tgz, MGA_WARP_TGZ); 105145132Sanholt WARP_UCODE_INSTALL(warp_g400_tgzf, MGA_WARP_TGZF); 106145132Sanholt WARP_UCODE_INSTALL(warp_g400_tgza, MGA_WARP_TGZA); 107145132Sanholt WARP_UCODE_INSTALL(warp_g400_tgzaf, MGA_WARP_TGZAF); 108145132Sanholt WARP_UCODE_INSTALL(warp_g400_tgzs, MGA_WARP_TGZS); 109145132Sanholt WARP_UCODE_INSTALL(warp_g400_tgzsf, MGA_WARP_TGZSF); 110145132Sanholt WARP_UCODE_INSTALL(warp_g400_tgzsa, MGA_WARP_TGZSA); 111145132Sanholt WARP_UCODE_INSTALL(warp_g400_tgzsaf, MGA_WARP_TGZSAF); 11295584Sanholt 113145132Sanholt WARP_UCODE_INSTALL(warp_g400_t2gz, MGA_WARP_T2GZ); 114145132Sanholt WARP_UCODE_INSTALL(warp_g400_t2gzf, MGA_WARP_T2GZF); 115145132Sanholt WARP_UCODE_INSTALL(warp_g400_t2gza, MGA_WARP_T2GZA); 116145132Sanholt WARP_UCODE_INSTALL(warp_g400_t2gzaf, MGA_WARP_T2GZAF); 117145132Sanholt WARP_UCODE_INSTALL(warp_g400_t2gzs, MGA_WARP_T2GZS); 118145132Sanholt WARP_UCODE_INSTALL(warp_g400_t2gzsf, MGA_WARP_T2GZSF); 119145132Sanholt WARP_UCODE_INSTALL(warp_g400_t2gzsa, MGA_WARP_T2GZSA); 120145132Sanholt WARP_UCODE_INSTALL(warp_g400_t2gzsaf, MGA_WARP_T2GZSAF); 12195584Sanholt 12295584Sanholt return 0; 12395584Sanholt} 12495584Sanholt 125145132Sanholtstatic int mga_warp_install_g200_microcode(drm_mga_private_t * dev_priv) 12695584Sanholt{ 127207066Srnoland unsigned char *vcbase = dev_priv->warp->virtual; 12895584Sanholt unsigned long pcbase = dev_priv->warp->offset; 12995584Sanholt 130145132Sanholt memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys)); 13195584Sanholt 132145132Sanholt WARP_UCODE_INSTALL(warp_g200_tgz, MGA_WARP_TGZ); 133145132Sanholt WARP_UCODE_INSTALL(warp_g200_tgzf, MGA_WARP_TGZF); 134145132Sanholt WARP_UCODE_INSTALL(warp_g200_tgza, MGA_WARP_TGZA); 135145132Sanholt WARP_UCODE_INSTALL(warp_g200_tgzaf, MGA_WARP_TGZAF); 136145132Sanholt WARP_UCODE_INSTALL(warp_g200_tgzs, MGA_WARP_TGZS); 137145132Sanholt WARP_UCODE_INSTALL(warp_g200_tgzsf, MGA_WARP_TGZSF); 138145132Sanholt WARP_UCODE_INSTALL(warp_g200_tgzsa, MGA_WARP_TGZSA); 139145132Sanholt WARP_UCODE_INSTALL(warp_g200_tgzsaf, MGA_WARP_TGZSAF); 14095584Sanholt 14195584Sanholt return 0; 14295584Sanholt} 14395584Sanholt 144145132Sanholtint mga_warp_install_microcode(drm_mga_private_t * dev_priv) 14595584Sanholt{ 146152909Sanholt const unsigned int size = mga_warp_microcode_size(dev_priv); 147152909Sanholt 148152909Sanholt DRM_DEBUG("MGA ucode size = %d bytes\n", size); 149152909Sanholt if (size > dev_priv->warp->size) { 150152909Sanholt DRM_ERROR("microcode too large! (%u > %lu)\n", 151152909Sanholt size, dev_priv->warp->size); 152182080Srnoland return -ENOMEM; 153152909Sanholt } 154152909Sanholt 155145132Sanholt switch (dev_priv->chipset) { 15695584Sanholt case MGA_CARD_TYPE_G400: 157152909Sanholt case MGA_CARD_TYPE_G550: 158145132Sanholt return mga_warp_install_g400_microcode(dev_priv); 15995584Sanholt case MGA_CARD_TYPE_G200: 160145132Sanholt return mga_warp_install_g200_microcode(dev_priv); 16195584Sanholt default: 162182080Srnoland return -EINVAL; 16395584Sanholt } 16495584Sanholt} 16595584Sanholt 16695584Sanholt#define WMISC_EXPECTED (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE) 16795584Sanholt 168145132Sanholtint mga_warp_init(drm_mga_private_t * dev_priv) 16995584Sanholt{ 17095584Sanholt u32 wmisc; 17195584Sanholt 17295584Sanholt /* FIXME: Get rid of these damned magic numbers... 17395584Sanholt */ 174145132Sanholt switch (dev_priv->chipset) { 17595584Sanholt case MGA_CARD_TYPE_G400: 176152909Sanholt case MGA_CARD_TYPE_G550: 177145132Sanholt MGA_WRITE(MGA_WIADDR2, MGA_WMODE_SUSPEND); 178145132Sanholt MGA_WRITE(MGA_WGETMSB, 0x00000E00); 179145132Sanholt MGA_WRITE(MGA_WVRTXSZ, 0x00001807); 180145132Sanholt MGA_WRITE(MGA_WACCEPTSEQ, 0x18000000); 18195584Sanholt break; 18295584Sanholt case MGA_CARD_TYPE_G200: 183145132Sanholt MGA_WRITE(MGA_WIADDR, MGA_WMODE_SUSPEND); 184145132Sanholt MGA_WRITE(MGA_WGETMSB, 0x1606); 185145132Sanholt MGA_WRITE(MGA_WVRTXSZ, 7); 18695584Sanholt break; 18795584Sanholt default: 188182080Srnoland return -EINVAL; 18995584Sanholt } 19095584Sanholt 191145132Sanholt MGA_WRITE(MGA_WMISC, (MGA_WUCODECACHE_ENABLE | 192145132Sanholt MGA_WMASTER_ENABLE | MGA_WCACHEFLUSH_ENABLE)); 193145132Sanholt wmisc = MGA_READ(MGA_WMISC); 194145132Sanholt if (wmisc != WMISC_EXPECTED) { 195145132Sanholt DRM_ERROR("WARP engine config failed! 0x%x != 0x%x\n", 196145132Sanholt wmisc, WMISC_EXPECTED); 197182080Srnoland return -EINVAL; 19895584Sanholt } 19995584Sanholt 20095584Sanholt return 0; 20195584Sanholt} 202