mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-10-29 23:28:52 +01:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
16
drivers/gpu/drm/mgag200/Kconfig
Normal file
16
drivers/gpu/drm/mgag200/Kconfig
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
config DRM_MGAG200
|
||||
tristate "Kernel modesetting driver for MGA G200 server engines"
|
||||
depends on DRM && PCI
|
||||
select FB_SYS_FILLRECT
|
||||
select FB_SYS_COPYAREA
|
||||
select FB_SYS_IMAGEBLIT
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_KMS_FB_HELPER
|
||||
select DRM_TTM
|
||||
help
|
||||
This is a KMS driver for the MGA G200 server chips, it
|
||||
does not support the original MGA G200 or any of the desktop
|
||||
chips. It requires 0.3.0 of the modesetting userspace driver,
|
||||
and a version of mga driver that will fail on KMS enabled
|
||||
devices.
|
||||
|
||||
5
drivers/gpu/drm/mgag200/Makefile
Normal file
5
drivers/gpu/drm/mgag200/Makefile
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
ccflags-y := -Iinclude/drm
|
||||
mgag200-y := mgag200_main.o mgag200_mode.o mgag200_cursor.o \
|
||||
mgag200_drv.o mgag200_fb.o mgag200_i2c.o mgag200_ttm.o
|
||||
|
||||
obj-$(CONFIG_DRM_MGAG200) += mgag200.o
|
||||
277
drivers/gpu/drm/mgag200/mgag200_cursor.c
Normal file
277
drivers/gpu/drm/mgag200/mgag200_cursor.c
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
* Copyright 2013 Matrox Graphics
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License version 2. See the file COPYING in the main
|
||||
* directory of this archive for more details.
|
||||
*
|
||||
* Author: Christopher Harvey <charvey@matrox.com>
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include "mgag200_drv.h"
|
||||
|
||||
static bool warn_transparent = true;
|
||||
static bool warn_palette = true;
|
||||
|
||||
/*
|
||||
Hide the cursor off screen. We can't disable the cursor hardware because it
|
||||
takes too long to re-activate and causes momentary corruption
|
||||
*/
|
||||
static void mga_hide_cursor(struct mga_device *mdev)
|
||||
{
|
||||
WREG8(MGA_CURPOSXL, 0);
|
||||
WREG8(MGA_CURPOSXH, 0);
|
||||
if (mdev->cursor.pixels_1->pin_count)
|
||||
mgag200_bo_unpin(mdev->cursor.pixels_1);
|
||||
if (mdev->cursor.pixels_2->pin_count)
|
||||
mgag200_bo_unpin(mdev->cursor.pixels_2);
|
||||
}
|
||||
|
||||
int mga_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
struct drm_file *file_priv,
|
||||
uint32_t handle,
|
||||
uint32_t width,
|
||||
uint32_t height)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct mga_device *mdev = (struct mga_device *)dev->dev_private;
|
||||
struct mgag200_bo *pixels_1 = mdev->cursor.pixels_1;
|
||||
struct mgag200_bo *pixels_2 = mdev->cursor.pixels_2;
|
||||
struct mgag200_bo *pixels_current = mdev->cursor.pixels_current;
|
||||
struct mgag200_bo *pixels_prev = mdev->cursor.pixels_prev;
|
||||
struct drm_gem_object *obj;
|
||||
struct mgag200_bo *bo = NULL;
|
||||
int ret = 0;
|
||||
unsigned int i, row, col;
|
||||
uint32_t colour_set[16];
|
||||
uint32_t *next_space = &colour_set[0];
|
||||
uint32_t *palette_iter;
|
||||
uint32_t this_colour;
|
||||
bool found = false;
|
||||
int colour_count = 0;
|
||||
u64 gpu_addr;
|
||||
u8 reg_index;
|
||||
u8 this_row[48];
|
||||
|
||||
if (!pixels_1 || !pixels_2) {
|
||||
WREG8(MGA_CURPOSXL, 0);
|
||||
WREG8(MGA_CURPOSXH, 0);
|
||||
return -ENOTSUPP; /* Didn't allocate space for cursors */
|
||||
}
|
||||
|
||||
if ((width != 64 || height != 64) && handle) {
|
||||
WREG8(MGA_CURPOSXL, 0);
|
||||
WREG8(MGA_CURPOSXH, 0);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
BUG_ON(pixels_1 != pixels_current && pixels_1 != pixels_prev);
|
||||
BUG_ON(pixels_2 != pixels_current && pixels_2 != pixels_prev);
|
||||
BUG_ON(pixels_current == pixels_prev);
|
||||
|
||||
ret = mgag200_bo_reserve(pixels_1, true);
|
||||
if (ret) {
|
||||
WREG8(MGA_CURPOSXL, 0);
|
||||
WREG8(MGA_CURPOSXH, 0);
|
||||
return ret;
|
||||
}
|
||||
ret = mgag200_bo_reserve(pixels_2, true);
|
||||
if (ret) {
|
||||
WREG8(MGA_CURPOSXL, 0);
|
||||
WREG8(MGA_CURPOSXH, 0);
|
||||
mgag200_bo_unreserve(pixels_1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!handle) {
|
||||
mga_hide_cursor(mdev);
|
||||
ret = 0;
|
||||
goto out1;
|
||||
}
|
||||
|
||||
/* Move cursor buffers into VRAM if they aren't already */
|
||||
if (!pixels_1->pin_count) {
|
||||
ret = mgag200_bo_pin(pixels_1, TTM_PL_FLAG_VRAM,
|
||||
&mdev->cursor.pixels_1_gpu_addr);
|
||||
if (ret)
|
||||
goto out1;
|
||||
}
|
||||
if (!pixels_2->pin_count) {
|
||||
ret = mgag200_bo_pin(pixels_2, TTM_PL_FLAG_VRAM,
|
||||
&mdev->cursor.pixels_2_gpu_addr);
|
||||
if (ret) {
|
||||
mgag200_bo_unpin(pixels_1);
|
||||
goto out1;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
obj = drm_gem_object_lookup(dev, file_priv, handle);
|
||||
if (!obj) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
ret = -ENOENT;
|
||||
goto out1;
|
||||
}
|
||||
drm_gem_object_unreference(obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
bo = gem_to_mga_bo(obj);
|
||||
ret = mgag200_bo_reserve(bo, true);
|
||||
if (ret) {
|
||||
dev_err(&dev->pdev->dev, "failed to reserve user bo\n");
|
||||
goto out1;
|
||||
}
|
||||
if (!bo->kmap.virtual) {
|
||||
ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
|
||||
if (ret) {
|
||||
dev_err(&dev->pdev->dev, "failed to kmap user buffer updates\n");
|
||||
goto out2;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&colour_set[0], 0, sizeof(uint32_t)*16);
|
||||
/* width*height*4 = 16384 */
|
||||
for (i = 0; i < 16384; i += 4) {
|
||||
this_colour = ioread32(bo->kmap.virtual + i);
|
||||
/* No transparency */
|
||||
if (this_colour>>24 != 0xff &&
|
||||
this_colour>>24 != 0x0) {
|
||||
if (warn_transparent) {
|
||||
dev_info(&dev->pdev->dev, "Video card doesn't support cursors with partial transparency.\n");
|
||||
dev_info(&dev->pdev->dev, "Not enabling hardware cursor.\n");
|
||||
warn_transparent = false; /* Only tell the user once. */
|
||||
}
|
||||
ret = -EINVAL;
|
||||
goto out3;
|
||||
}
|
||||
/* Don't need to store transparent pixels as colours */
|
||||
if (this_colour>>24 == 0x0)
|
||||
continue;
|
||||
found = false;
|
||||
for (palette_iter = &colour_set[0]; palette_iter != next_space; palette_iter++) {
|
||||
if (*palette_iter == this_colour) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
continue;
|
||||
/* We only support 4bit paletted cursors */
|
||||
if (colour_count >= 16) {
|
||||
if (warn_palette) {
|
||||
dev_info(&dev->pdev->dev, "Video card only supports cursors with up to 16 colours.\n");
|
||||
dev_info(&dev->pdev->dev, "Not enabling hardware cursor.\n");
|
||||
warn_palette = false; /* Only tell the user once. */
|
||||
}
|
||||
ret = -EINVAL;
|
||||
goto out3;
|
||||
}
|
||||
*next_space = this_colour;
|
||||
next_space++;
|
||||
colour_count++;
|
||||
}
|
||||
|
||||
/* Program colours from cursor icon into palette */
|
||||
for (i = 0; i < colour_count; i++) {
|
||||
if (i <= 2)
|
||||
reg_index = 0x8 + i*0x4;
|
||||
else
|
||||
reg_index = 0x60 + i*0x3;
|
||||
WREG_DAC(reg_index, colour_set[i] & 0xff);
|
||||
WREG_DAC(reg_index+1, colour_set[i]>>8 & 0xff);
|
||||
WREG_DAC(reg_index+2, colour_set[i]>>16 & 0xff);
|
||||
BUG_ON((colour_set[i]>>24 & 0xff) != 0xff);
|
||||
}
|
||||
|
||||
/* Map up-coming buffer to write colour indices */
|
||||
if (!pixels_prev->kmap.virtual) {
|
||||
ret = ttm_bo_kmap(&pixels_prev->bo, 0,
|
||||
pixels_prev->bo.num_pages,
|
||||
&pixels_prev->kmap);
|
||||
if (ret) {
|
||||
dev_err(&dev->pdev->dev, "failed to kmap cursor updates\n");
|
||||
goto out3;
|
||||
}
|
||||
}
|
||||
|
||||
/* now write colour indices into hardware cursor buffer */
|
||||
for (row = 0; row < 64; row++) {
|
||||
memset(&this_row[0], 0, 48);
|
||||
for (col = 0; col < 64; col++) {
|
||||
this_colour = ioread32(bo->kmap.virtual + 4*(col + 64*row));
|
||||
/* write transparent pixels */
|
||||
if (this_colour>>24 == 0x0) {
|
||||
this_row[47 - col/8] |= 0x80>>(col%8);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* write colour index here */
|
||||
for (i = 0; i < colour_count; i++) {
|
||||
if (colour_set[i] == this_colour) {
|
||||
if (col % 2)
|
||||
this_row[col/2] |= i<<4;
|
||||
else
|
||||
this_row[col/2] |= i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy_toio(pixels_prev->kmap.virtual + row*48, &this_row[0], 48);
|
||||
}
|
||||
|
||||
/* Program gpu address of cursor buffer */
|
||||
if (pixels_prev == pixels_1)
|
||||
gpu_addr = mdev->cursor.pixels_1_gpu_addr;
|
||||
else
|
||||
gpu_addr = mdev->cursor.pixels_2_gpu_addr;
|
||||
WREG_DAC(MGA1064_CURSOR_BASE_ADR_LOW, (u8)((gpu_addr>>10) & 0xff));
|
||||
WREG_DAC(MGA1064_CURSOR_BASE_ADR_HI, (u8)((gpu_addr>>18) & 0x3f));
|
||||
|
||||
/* Adjust cursor control register to turn on the cursor */
|
||||
WREG_DAC(MGA1064_CURSOR_CTL, 4); /* 16-colour palletized cursor mode */
|
||||
|
||||
/* Now swap internal buffer pointers */
|
||||
if (mdev->cursor.pixels_1 == mdev->cursor.pixels_prev) {
|
||||
mdev->cursor.pixels_prev = mdev->cursor.pixels_2;
|
||||
mdev->cursor.pixels_current = mdev->cursor.pixels_1;
|
||||
} else if (mdev->cursor.pixels_1 == mdev->cursor.pixels_current) {
|
||||
mdev->cursor.pixels_prev = mdev->cursor.pixels_1;
|
||||
mdev->cursor.pixels_current = mdev->cursor.pixels_2;
|
||||
} else {
|
||||
BUG();
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
ttm_bo_kunmap(&pixels_prev->kmap);
|
||||
out3:
|
||||
ttm_bo_kunmap(&bo->kmap);
|
||||
out2:
|
||||
mgag200_bo_unreserve(bo);
|
||||
out1:
|
||||
if (ret)
|
||||
mga_hide_cursor(mdev);
|
||||
mgag200_bo_unreserve(pixels_1);
|
||||
mgag200_bo_unreserve(pixels_2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mga_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
|
||||
{
|
||||
struct mga_device *mdev = (struct mga_device *)crtc->dev->dev_private;
|
||||
/* Our origin is at (64,64) */
|
||||
x += 64;
|
||||
y += 64;
|
||||
|
||||
BUG_ON(x <= 0);
|
||||
BUG_ON(y <= 0);
|
||||
BUG_ON(x & ~0xffff);
|
||||
BUG_ON(y & ~0xffff);
|
||||
|
||||
WREG8(MGA_CURPOSXL, x & 0xff);
|
||||
WREG8(MGA_CURPOSXH, (x>>8) & 0xff);
|
||||
|
||||
WREG8(MGA_CURPOSYL, y & 0xff);
|
||||
WREG8(MGA_CURPOSYH, (y>>8) & 0xff);
|
||||
return 0;
|
||||
}
|
||||
138
drivers/gpu/drm/mgag200/mgag200_drv.c
Normal file
138
drivers/gpu/drm/mgag200/mgag200_drv.c
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright 2012 Red Hat
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License version 2. See the file COPYING in the main
|
||||
* directory of this archive for more details.
|
||||
*
|
||||
* Authors: Matthew Garrett
|
||||
* Dave Airlie
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/console.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include "mgag200_drv.h"
|
||||
|
||||
#include <drm/drm_pciids.h>
|
||||
|
||||
/*
|
||||
* This is the generic driver code. This binds the driver to the drm core,
|
||||
* which then performs further device association and calls our graphics init
|
||||
* functions
|
||||
*/
|
||||
int mgag200_modeset = -1;
|
||||
|
||||
MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
|
||||
module_param_named(modeset, mgag200_modeset, int, 0400);
|
||||
|
||||
static struct drm_driver driver;
|
||||
|
||||
static const struct pci_device_id pciidlist[] = {
|
||||
{ PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_A },
|
||||
{ PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B },
|
||||
{ PCI_VENDOR_ID_MATROX, 0x530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EV },
|
||||
{ PCI_VENDOR_ID_MATROX, 0x532, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_WB },
|
||||
{ PCI_VENDOR_ID_MATROX, 0x533, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EH },
|
||||
{ PCI_VENDOR_ID_MATROX, 0x534, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_ER },
|
||||
{0,}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, pciidlist);
|
||||
|
||||
static void mgag200_kick_out_firmware_fb(struct pci_dev *pdev)
|
||||
{
|
||||
struct apertures_struct *ap;
|
||||
bool primary = false;
|
||||
|
||||
ap = alloc_apertures(1);
|
||||
if (!ap)
|
||||
return;
|
||||
|
||||
ap->ranges[0].base = pci_resource_start(pdev, 0);
|
||||
ap->ranges[0].size = pci_resource_len(pdev, 0);
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
|
||||
#endif
|
||||
remove_conflicting_framebuffers(ap, "mgag200drmfb", primary);
|
||||
kfree(ap);
|
||||
}
|
||||
|
||||
|
||||
static int mga_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
mgag200_kick_out_firmware_fb(pdev);
|
||||
|
||||
return drm_get_pci_dev(pdev, ent, &driver);
|
||||
}
|
||||
|
||||
static void mga_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
|
||||
drm_put_dev(dev);
|
||||
}
|
||||
|
||||
static const struct file_operations mgag200_driver_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.unlocked_ioctl = drm_ioctl,
|
||||
.mmap = mgag200_mmap,
|
||||
.poll = drm_poll,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = drm_compat_ioctl,
|
||||
#endif
|
||||
.read = drm_read,
|
||||
};
|
||||
|
||||
static struct drm_driver driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET,
|
||||
.load = mgag200_driver_load,
|
||||
.unload = mgag200_driver_unload,
|
||||
.set_busid = drm_pci_set_busid,
|
||||
.fops = &mgag200_driver_fops,
|
||||
.name = DRIVER_NAME,
|
||||
.desc = DRIVER_DESC,
|
||||
.date = DRIVER_DATE,
|
||||
.major = DRIVER_MAJOR,
|
||||
.minor = DRIVER_MINOR,
|
||||
.patchlevel = DRIVER_PATCHLEVEL,
|
||||
|
||||
.gem_free_object = mgag200_gem_free_object,
|
||||
.dumb_create = mgag200_dumb_create,
|
||||
.dumb_map_offset = mgag200_dumb_mmap_offset,
|
||||
.dumb_destroy = drm_gem_dumb_destroy,
|
||||
};
|
||||
|
||||
static struct pci_driver mgag200_pci_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = pciidlist,
|
||||
.probe = mga_pci_probe,
|
||||
.remove = mga_pci_remove,
|
||||
};
|
||||
|
||||
static int __init mgag200_init(void)
|
||||
{
|
||||
#ifdef CONFIG_VGA_CONSOLE
|
||||
if (vgacon_text_force() && mgag200_modeset == -1)
|
||||
return -EINVAL;
|
||||
#endif
|
||||
|
||||
if (mgag200_modeset == 0)
|
||||
return -EINVAL;
|
||||
return drm_pci_init(&driver, &mgag200_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit mgag200_exit(void)
|
||||
{
|
||||
drm_pci_exit(&driver, &mgag200_pci_driver);
|
||||
}
|
||||
|
||||
module_init(mgag200_init);
|
||||
module_exit(mgag200_exit);
|
||||
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_LICENSE("GPL");
|
||||
310
drivers/gpu/drm/mgag200/mgag200_drv.h
Normal file
310
drivers/gpu/drm/mgag200/mgag200_drv.h
Normal file
|
|
@ -0,0 +1,310 @@
|
|||
/*
|
||||
* Copyright 2010 Matt Turner.
|
||||
* Copyright 2012 Red Hat
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License version 2. See the file COPYING in the main
|
||||
* directory of this archive for more details.
|
||||
*
|
||||
* Authors: Matthew Garrett
|
||||
* Matt Turner
|
||||
* Dave Airlie
|
||||
*/
|
||||
#ifndef __MGAG200_DRV_H__
|
||||
#define __MGAG200_DRV_H__
|
||||
|
||||
#include <video/vga.h>
|
||||
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/ttm/ttm_bo_api.h>
|
||||
#include <drm/ttm/ttm_bo_driver.h>
|
||||
#include <drm/ttm/ttm_placement.h>
|
||||
#include <drm/ttm/ttm_memory.h>
|
||||
#include <drm/ttm/ttm_module.h>
|
||||
|
||||
#include <drm/drm_gem.h>
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
|
||||
#include "mgag200_reg.h"
|
||||
|
||||
#define DRIVER_AUTHOR "Matthew Garrett"
|
||||
|
||||
#define DRIVER_NAME "mgag200"
|
||||
#define DRIVER_DESC "MGA G200 SE"
|
||||
#define DRIVER_DATE "20110418"
|
||||
|
||||
#define DRIVER_MAJOR 1
|
||||
#define DRIVER_MINOR 0
|
||||
#define DRIVER_PATCHLEVEL 0
|
||||
|
||||
#define MGAG200FB_CONN_LIMIT 1
|
||||
|
||||
#define RREG8(reg) ioread8(((void __iomem *)mdev->rmmio) + (reg))
|
||||
#define WREG8(reg, v) iowrite8(v, ((void __iomem *)mdev->rmmio) + (reg))
|
||||
#define RREG32(reg) ioread32(((void __iomem *)mdev->rmmio) + (reg))
|
||||
#define WREG32(reg, v) iowrite32(v, ((void __iomem *)mdev->rmmio) + (reg))
|
||||
|
||||
#define ATTR_INDEX 0x1fc0
|
||||
#define ATTR_DATA 0x1fc1
|
||||
|
||||
#define WREG_ATTR(reg, v) \
|
||||
do { \
|
||||
RREG8(0x1fda); \
|
||||
WREG8(ATTR_INDEX, reg); \
|
||||
WREG8(ATTR_DATA, v); \
|
||||
} while (0) \
|
||||
|
||||
#define WREG_SEQ(reg, v) \
|
||||
do { \
|
||||
WREG8(MGAREG_SEQ_INDEX, reg); \
|
||||
WREG8(MGAREG_SEQ_DATA, v); \
|
||||
} while (0) \
|
||||
|
||||
#define WREG_CRT(reg, v) \
|
||||
do { \
|
||||
WREG8(MGAREG_CRTC_INDEX, reg); \
|
||||
WREG8(MGAREG_CRTC_DATA, v); \
|
||||
} while (0) \
|
||||
|
||||
|
||||
#define WREG_ECRT(reg, v) \
|
||||
do { \
|
||||
WREG8(MGAREG_CRTCEXT_INDEX, reg); \
|
||||
WREG8(MGAREG_CRTCEXT_DATA, v); \
|
||||
} while (0) \
|
||||
|
||||
#define GFX_INDEX 0x1fce
|
||||
#define GFX_DATA 0x1fcf
|
||||
|
||||
#define WREG_GFX(reg, v) \
|
||||
do { \
|
||||
WREG8(GFX_INDEX, reg); \
|
||||
WREG8(GFX_DATA, v); \
|
||||
} while (0) \
|
||||
|
||||
#define DAC_INDEX 0x3c00
|
||||
#define DAC_DATA 0x3c0a
|
||||
|
||||
#define WREG_DAC(reg, v) \
|
||||
do { \
|
||||
WREG8(DAC_INDEX, reg); \
|
||||
WREG8(DAC_DATA, v); \
|
||||
} while (0) \
|
||||
|
||||
#define MGA_MISC_OUT 0x1fc2
|
||||
#define MGA_MISC_IN 0x1fcc
|
||||
|
||||
#define MGAG200_MAX_FB_HEIGHT 4096
|
||||
#define MGAG200_MAX_FB_WIDTH 4096
|
||||
|
||||
#define MATROX_DPMS_CLEARED (-1)
|
||||
|
||||
#define to_mga_crtc(x) container_of(x, struct mga_crtc, base)
|
||||
#define to_mga_encoder(x) container_of(x, struct mga_encoder, base)
|
||||
#define to_mga_connector(x) container_of(x, struct mga_connector, base)
|
||||
#define to_mga_framebuffer(x) container_of(x, struct mga_framebuffer, base)
|
||||
|
||||
struct mga_framebuffer {
|
||||
struct drm_framebuffer base;
|
||||
struct drm_gem_object *obj;
|
||||
};
|
||||
|
||||
struct mga_fbdev {
|
||||
struct drm_fb_helper helper;
|
||||
struct mga_framebuffer mfb;
|
||||
void *sysram;
|
||||
int size;
|
||||
struct ttm_bo_kmap_obj mapping;
|
||||
int x1, y1, x2, y2; /* dirty rect */
|
||||
spinlock_t dirty_lock;
|
||||
};
|
||||
|
||||
struct mga_crtc {
|
||||
struct drm_crtc base;
|
||||
u8 lut_r[256], lut_g[256], lut_b[256];
|
||||
int last_dpms;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
struct mga_mode_info {
|
||||
bool mode_config_initialized;
|
||||
struct mga_crtc *crtc;
|
||||
};
|
||||
|
||||
struct mga_encoder {
|
||||
struct drm_encoder base;
|
||||
int last_dpms;
|
||||
};
|
||||
|
||||
|
||||
struct mga_i2c_chan {
|
||||
struct i2c_adapter adapter;
|
||||
struct drm_device *dev;
|
||||
struct i2c_algo_bit_data bit;
|
||||
int data, clock;
|
||||
};
|
||||
|
||||
struct mga_connector {
|
||||
struct drm_connector base;
|
||||
struct mga_i2c_chan *i2c;
|
||||
};
|
||||
|
||||
struct mga_cursor {
|
||||
/*
|
||||
We have to have 2 buffers for the cursor to avoid occasional
|
||||
corruption while switching cursor icons.
|
||||
If either of these is NULL, then don't do hardware cursors, and
|
||||
fall back to software.
|
||||
*/
|
||||
struct mgag200_bo *pixels_1;
|
||||
struct mgag200_bo *pixels_2;
|
||||
u64 pixels_1_gpu_addr, pixels_2_gpu_addr;
|
||||
/* The currently displayed icon, this points to one of pixels_1, or pixels_2 */
|
||||
struct mgag200_bo *pixels_current;
|
||||
/* The previously displayed icon */
|
||||
struct mgag200_bo *pixels_prev;
|
||||
};
|
||||
|
||||
struct mga_mc {
|
||||
resource_size_t vram_size;
|
||||
resource_size_t vram_base;
|
||||
resource_size_t vram_window;
|
||||
};
|
||||
|
||||
enum mga_type {
|
||||
G200_SE_A,
|
||||
G200_SE_B,
|
||||
G200_WB,
|
||||
G200_EV,
|
||||
G200_EH,
|
||||
G200_ER,
|
||||
};
|
||||
|
||||
#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;
|
||||
|
||||
resource_size_t rmmio_base;
|
||||
resource_size_t rmmio_size;
|
||||
void __iomem *rmmio;
|
||||
|
||||
struct mga_mc mc;
|
||||
struct mga_mode_info mode_info;
|
||||
|
||||
struct mga_fbdev *mfbdev;
|
||||
struct mga_cursor cursor;
|
||||
|
||||
bool suspended;
|
||||
int num_crtc;
|
||||
enum mga_type type;
|
||||
int has_sdram;
|
||||
struct drm_display_mode mode;
|
||||
|
||||
int bpp_shifts[4];
|
||||
|
||||
int fb_mtrr;
|
||||
|
||||
struct {
|
||||
struct drm_global_reference mem_global_ref;
|
||||
struct ttm_bo_global_ref bo_global_ref;
|
||||
struct ttm_bo_device bdev;
|
||||
} ttm;
|
||||
|
||||
/* SE model number stored in reg 0x1e24 */
|
||||
u32 unique_rev_id;
|
||||
};
|
||||
|
||||
|
||||
struct mgag200_bo {
|
||||
struct ttm_buffer_object bo;
|
||||
struct ttm_placement placement;
|
||||
struct ttm_bo_kmap_obj kmap;
|
||||
struct drm_gem_object gem;
|
||||
struct ttm_place placements[3];
|
||||
int pin_count;
|
||||
};
|
||||
#define gem_to_mga_bo(gobj) container_of((gobj), struct mgag200_bo, gem)
|
||||
|
||||
static inline struct mgag200_bo *
|
||||
mgag200_bo(struct ttm_buffer_object *bo)
|
||||
{
|
||||
return container_of(bo, struct mgag200_bo, bo);
|
||||
}
|
||||
/* mgag200_crtc.c */
|
||||
void mga_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
|
||||
u16 blue, int regno);
|
||||
void mga_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
|
||||
u16 *blue, int regno);
|
||||
|
||||
/* mgag200_mode.c */
|
||||
int mgag200_modeset_init(struct mga_device *mdev);
|
||||
void mgag200_modeset_fini(struct mga_device *mdev);
|
||||
|
||||
/* mgag200_fb.c */
|
||||
int mgag200_fbdev_init(struct mga_device *mdev);
|
||||
void mgag200_fbdev_fini(struct mga_device *mdev);
|
||||
|
||||
/* mgag200_main.c */
|
||||
int mgag200_framebuffer_init(struct drm_device *dev,
|
||||
struct mga_framebuffer *mfb,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj);
|
||||
|
||||
|
||||
int mgag200_driver_load(struct drm_device *dev, unsigned long flags);
|
||||
int mgag200_driver_unload(struct drm_device *dev);
|
||||
int mgag200_gem_create(struct drm_device *dev,
|
||||
u32 size, bool iskernel,
|
||||
struct drm_gem_object **obj);
|
||||
int mgag200_dumb_create(struct drm_file *file,
|
||||
struct drm_device *dev,
|
||||
struct drm_mode_create_dumb *args);
|
||||
void mgag200_gem_free_object(struct drm_gem_object *obj);
|
||||
int
|
||||
mgag200_dumb_mmap_offset(struct drm_file *file,
|
||||
struct drm_device *dev,
|
||||
uint32_t handle,
|
||||
uint64_t *offset);
|
||||
/* mgag200_i2c.c */
|
||||
struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev);
|
||||
void mgag200_i2c_destroy(struct mga_i2c_chan *i2c);
|
||||
|
||||
#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
|
||||
void mgag200_ttm_placement(struct mgag200_bo *bo, int domain);
|
||||
|
||||
static inline int mgag200_bo_reserve(struct mgag200_bo *bo, bool no_wait)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, NULL);
|
||||
if (ret) {
|
||||
if (ret != -ERESTARTSYS && ret != -EBUSY)
|
||||
DRM_ERROR("reserve failed %p\n", bo);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mgag200_bo_unreserve(struct mgag200_bo *bo)
|
||||
{
|
||||
ttm_bo_unreserve(&bo->bo);
|
||||
}
|
||||
|
||||
int mgag200_bo_create(struct drm_device *dev, int size, int align,
|
||||
uint32_t flags, struct mgag200_bo **pastbo);
|
||||
int mgag200_mm_init(struct mga_device *mdev);
|
||||
void mgag200_mm_fini(struct mga_device *mdev);
|
||||
int mgag200_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||
int mgag200_bo_pin(struct mgag200_bo *bo, u32 pl_flag, u64 *gpu_addr);
|
||||
int mgag200_bo_unpin(struct mgag200_bo *bo);
|
||||
int mgag200_bo_push_sysram(struct mgag200_bo *bo);
|
||||
/* mgag200_cursor.c */
|
||||
int mga_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
|
||||
uint32_t handle, uint32_t width, uint32_t height);
|
||||
int mga_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
|
||||
|
||||
#endif /* __MGAG200_DRV_H__ */
|
||||
322
drivers/gpu/drm/mgag200/mgag200_fb.c
Normal file
322
drivers/gpu/drm/mgag200/mgag200_fb.c
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
/*
|
||||
* Copyright 2010 Matt Turner.
|
||||
* Copyright 2012 Red Hat
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License version 2. See the file COPYING in the main
|
||||
* directory of this archive for more details.
|
||||
*
|
||||
* Authors: Matthew Garrett
|
||||
* Matt Turner
|
||||
* Dave Airlie
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
|
||||
#include <linux/fb.h>
|
||||
|
||||
#include "mgag200_drv.h"
|
||||
|
||||
static void mga_dirty_update(struct mga_fbdev *mfbdev,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
int i;
|
||||
struct drm_gem_object *obj;
|
||||
struct mgag200_bo *bo;
|
||||
int src_offset, dst_offset;
|
||||
int bpp = (mfbdev->mfb.base.bits_per_pixel + 7)/8;
|
||||
int ret = -EBUSY;
|
||||
bool unmap = false;
|
||||
bool store_for_later = false;
|
||||
int x2, y2;
|
||||
unsigned long flags;
|
||||
|
||||
obj = mfbdev->mfb.obj;
|
||||
bo = gem_to_mga_bo(obj);
|
||||
|
||||
/*
|
||||
* try and reserve the BO, if we fail with busy
|
||||
* then the BO is being moved and we should
|
||||
* store up the damage until later.
|
||||
*/
|
||||
if (drm_can_sleep())
|
||||
ret = mgag200_bo_reserve(bo, true);
|
||||
if (ret) {
|
||||
if (ret != -EBUSY)
|
||||
return;
|
||||
|
||||
store_for_later = true;
|
||||
}
|
||||
|
||||
x2 = x + width - 1;
|
||||
y2 = y + height - 1;
|
||||
spin_lock_irqsave(&mfbdev->dirty_lock, flags);
|
||||
|
||||
if (mfbdev->y1 < y)
|
||||
y = mfbdev->y1;
|
||||
if (mfbdev->y2 > y2)
|
||||
y2 = mfbdev->y2;
|
||||
if (mfbdev->x1 < x)
|
||||
x = mfbdev->x1;
|
||||
if (mfbdev->x2 > x2)
|
||||
x2 = mfbdev->x2;
|
||||
|
||||
if (store_for_later) {
|
||||
mfbdev->x1 = x;
|
||||
mfbdev->x2 = x2;
|
||||
mfbdev->y1 = y;
|
||||
mfbdev->y2 = y2;
|
||||
spin_unlock_irqrestore(&mfbdev->dirty_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
mfbdev->x1 = mfbdev->y1 = INT_MAX;
|
||||
mfbdev->x2 = mfbdev->y2 = 0;
|
||||
spin_unlock_irqrestore(&mfbdev->dirty_lock, flags);
|
||||
|
||||
if (!bo->kmap.virtual) {
|
||||
ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to kmap fb updates\n");
|
||||
mgag200_bo_unreserve(bo);
|
||||
return;
|
||||
}
|
||||
unmap = true;
|
||||
}
|
||||
for (i = y; i <= y2; i++) {
|
||||
/* assume equal stride for now */
|
||||
src_offset = dst_offset = i * mfbdev->mfb.base.pitches[0] + (x * bpp);
|
||||
memcpy_toio(bo->kmap.virtual + src_offset, mfbdev->sysram + src_offset, (x2 - x + 1) * bpp);
|
||||
|
||||
}
|
||||
if (unmap)
|
||||
ttm_bo_kunmap(&bo->kmap);
|
||||
|
||||
mgag200_bo_unreserve(bo);
|
||||
}
|
||||
|
||||
static void mga_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect)
|
||||
{
|
||||
struct mga_fbdev *mfbdev = info->par;
|
||||
sys_fillrect(info, rect);
|
||||
mga_dirty_update(mfbdev, rect->dx, rect->dy, rect->width,
|
||||
rect->height);
|
||||
}
|
||||
|
||||
static void mga_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area)
|
||||
{
|
||||
struct mga_fbdev *mfbdev = info->par;
|
||||
sys_copyarea(info, area);
|
||||
mga_dirty_update(mfbdev, area->dx, area->dy, area->width,
|
||||
area->height);
|
||||
}
|
||||
|
||||
static void mga_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image)
|
||||
{
|
||||
struct mga_fbdev *mfbdev = info->par;
|
||||
sys_imageblit(info, image);
|
||||
mga_dirty_update(mfbdev, image->dx, image->dy, image->width,
|
||||
image->height);
|
||||
}
|
||||
|
||||
|
||||
static struct fb_ops mgag200fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
.fb_set_par = drm_fb_helper_set_par,
|
||||
.fb_fillrect = mga_fillrect,
|
||||
.fb_copyarea = mga_copyarea,
|
||||
.fb_imageblit = mga_imageblit,
|
||||
.fb_pan_display = drm_fb_helper_pan_display,
|
||||
.fb_blank = drm_fb_helper_blank,
|
||||
.fb_setcmap = drm_fb_helper_setcmap,
|
||||
};
|
||||
|
||||
static int mgag200fb_create_object(struct mga_fbdev *afbdev,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object **gobj_p)
|
||||
{
|
||||
struct drm_device *dev = afbdev->helper.dev;
|
||||
u32 size;
|
||||
struct drm_gem_object *gobj;
|
||||
int ret = 0;
|
||||
|
||||
size = mode_cmd->pitches[0] * mode_cmd->height;
|
||||
ret = mgag200_gem_create(dev, size, true, &gobj);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*gobj_p = gobj;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mgag200fb_create(struct drm_fb_helper *helper,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct mga_fbdev *mfbdev =
|
||||
container_of(helper, struct mga_fbdev, helper);
|
||||
struct drm_device *dev = mfbdev->helper.dev;
|
||||
struct drm_mode_fb_cmd2 mode_cmd;
|
||||
struct mga_device *mdev = dev->dev_private;
|
||||
struct fb_info *info;
|
||||
struct drm_framebuffer *fb;
|
||||
struct drm_gem_object *gobj = NULL;
|
||||
struct device *device = &dev->pdev->dev;
|
||||
struct mgag200_bo *bo;
|
||||
int ret;
|
||||
void *sysram;
|
||||
int size;
|
||||
|
||||
mode_cmd.width = sizes->surface_width;
|
||||
mode_cmd.height = sizes->surface_height;
|
||||
mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8);
|
||||
|
||||
mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
|
||||
sizes->surface_depth);
|
||||
size = mode_cmd.pitches[0] * mode_cmd.height;
|
||||
|
||||
ret = mgag200fb_create_object(mfbdev, &mode_cmd, &gobj);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create fbcon backing object %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
bo = gem_to_mga_bo(gobj);
|
||||
|
||||
sysram = vmalloc(size);
|
||||
if (!sysram)
|
||||
return -ENOMEM;
|
||||
|
||||
info = framebuffer_alloc(0, device);
|
||||
if (info == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
info->par = mfbdev;
|
||||
|
||||
ret = mgag200_framebuffer_init(dev, &mfbdev->mfb, &mode_cmd, gobj);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mfbdev->sysram = sysram;
|
||||
mfbdev->size = size;
|
||||
|
||||
fb = &mfbdev->mfb.base;
|
||||
|
||||
/* setup helper */
|
||||
mfbdev->helper.fb = fb;
|
||||
mfbdev->helper.fbdev = info;
|
||||
|
||||
ret = fb_alloc_cmap(&info->cmap, 256, 0);
|
||||
if (ret) {
|
||||
DRM_ERROR("%s: can't allocate color map\n", info->fix.id);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
strcpy(info->fix.id, "mgadrmfb");
|
||||
|
||||
info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
|
||||
info->fbops = &mgag200fb_ops;
|
||||
|
||||
/* setup aperture base/size for vesafb takeover */
|
||||
info->apertures = alloc_apertures(1);
|
||||
if (!info->apertures) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
info->apertures->ranges[0].base = mdev->dev->mode_config.fb_base;
|
||||
info->apertures->ranges[0].size = mdev->mc.vram_size;
|
||||
|
||||
drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
|
||||
drm_fb_helper_fill_var(info, &mfbdev->helper, sizes->fb_width,
|
||||
sizes->fb_height);
|
||||
|
||||
info->screen_base = sysram;
|
||||
info->screen_size = size;
|
||||
info->pixmap.flags = FB_PIXMAP_SYSTEM;
|
||||
|
||||
DRM_DEBUG_KMS("allocated %dx%d\n",
|
||||
fb->width, fb->height);
|
||||
return 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mga_fbdev_destroy(struct drm_device *dev,
|
||||
struct mga_fbdev *mfbdev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct mga_framebuffer *mfb = &mfbdev->mfb;
|
||||
|
||||
if (mfbdev->helper.fbdev) {
|
||||
info = mfbdev->helper.fbdev;
|
||||
|
||||
unregister_framebuffer(info);
|
||||
if (info->cmap.len)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
|
||||
if (mfb->obj) {
|
||||
drm_gem_object_unreference_unlocked(mfb->obj);
|
||||
mfb->obj = NULL;
|
||||
}
|
||||
drm_fb_helper_fini(&mfbdev->helper);
|
||||
vfree(mfbdev->sysram);
|
||||
drm_framebuffer_unregister_private(&mfb->base);
|
||||
drm_framebuffer_cleanup(&mfb->base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_fb_helper_funcs mga_fb_helper_funcs = {
|
||||
.gamma_set = mga_crtc_fb_gamma_set,
|
||||
.gamma_get = mga_crtc_fb_gamma_get,
|
||||
.fb_probe = mgag200fb_create,
|
||||
};
|
||||
|
||||
int mgag200_fbdev_init(struct mga_device *mdev)
|
||||
{
|
||||
struct mga_fbdev *mfbdev;
|
||||
int ret;
|
||||
int bpp_sel = 32;
|
||||
|
||||
/* prefer 16bpp on low end gpus with limited VRAM */
|
||||
if (IS_G200_SE(mdev) && mdev->mc.vram_size < (2048*1024))
|
||||
bpp_sel = 16;
|
||||
|
||||
mfbdev = devm_kzalloc(mdev->dev->dev, sizeof(struct mga_fbdev), GFP_KERNEL);
|
||||
if (!mfbdev)
|
||||
return -ENOMEM;
|
||||
|
||||
mdev->mfbdev = mfbdev;
|
||||
spin_lock_init(&mfbdev->dirty_lock);
|
||||
|
||||
drm_fb_helper_prepare(mdev->dev, &mfbdev->helper, &mga_fb_helper_funcs);
|
||||
|
||||
ret = drm_fb_helper_init(mdev->dev, &mfbdev->helper,
|
||||
mdev->num_crtc, MGAG200FB_CONN_LIMIT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_fb_helper_single_add_all_connectors(&mfbdev->helper);
|
||||
|
||||
/* disable all the possible outputs/crtcs before entering KMS mode */
|
||||
drm_helper_disable_unused_functions(mdev->dev);
|
||||
|
||||
drm_fb_helper_initial_config(&mfbdev->helper, bpp_sel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mgag200_fbdev_fini(struct mga_device *mdev)
|
||||
{
|
||||
if (!mdev->mfbdev)
|
||||
return;
|
||||
|
||||
mga_fbdev_destroy(mdev->dev, mdev->mfbdev);
|
||||
}
|
||||
156
drivers/gpu/drm/mgag200/mgag200_i2c.c
Normal file
156
drivers/gpu/drm/mgag200/mgag200_i2c.c
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Copyright 2012 Red Hat Inc.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Authors: Dave Airlie <airlied@redhat.com>
|
||||
*/
|
||||
#include <linux/export.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include "mgag200_drv.h"
|
||||
|
||||
static int mga_i2c_read_gpio(struct mga_device *mdev)
|
||||
{
|
||||
WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
|
||||
return RREG8(DAC_DATA);
|
||||
}
|
||||
|
||||
static void mga_i2c_set_gpio(struct mga_device *mdev, int mask, int val)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL);
|
||||
tmp = (RREG8(DAC_DATA) & mask) | val;
|
||||
WREG_DAC(MGA1064_GEN_IO_CTL, tmp);
|
||||
WREG_DAC(MGA1064_GEN_IO_DATA, 0);
|
||||
}
|
||||
|
||||
static inline void mga_i2c_set(struct mga_device *mdev, int mask, int state)
|
||||
{
|
||||
if (state)
|
||||
state = 0;
|
||||
else
|
||||
state = mask;
|
||||
mga_i2c_set_gpio(mdev, ~mask, state);
|
||||
}
|
||||
|
||||
static void mga_gpio_setsda(void *data, int state)
|
||||
{
|
||||
struct mga_i2c_chan *i2c = data;
|
||||
struct mga_device *mdev = i2c->dev->dev_private;
|
||||
mga_i2c_set(mdev, i2c->data, state);
|
||||
}
|
||||
|
||||
static void mga_gpio_setscl(void *data, int state)
|
||||
{
|
||||
struct mga_i2c_chan *i2c = data;
|
||||
struct mga_device *mdev = i2c->dev->dev_private;
|
||||
mga_i2c_set(mdev, i2c->clock, state);
|
||||
}
|
||||
|
||||
static int mga_gpio_getsda(void *data)
|
||||
{
|
||||
struct mga_i2c_chan *i2c = data;
|
||||
struct mga_device *mdev = i2c->dev->dev_private;
|
||||
return (mga_i2c_read_gpio(mdev) & i2c->data) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int mga_gpio_getscl(void *data)
|
||||
{
|
||||
struct mga_i2c_chan *i2c = data;
|
||||
struct mga_device *mdev = i2c->dev->dev_private;
|
||||
return (mga_i2c_read_gpio(mdev) & i2c->clock) ? 1 : 0;
|
||||
}
|
||||
|
||||
struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev)
|
||||
{
|
||||
struct mga_device *mdev = dev->dev_private;
|
||||
struct mga_i2c_chan *i2c;
|
||||
int ret;
|
||||
int data, clock;
|
||||
|
||||
WREG_DAC(MGA1064_GEN_IO_CTL2, 1);
|
||||
WREG_DAC(MGA1064_GEN_IO_DATA, 0xff);
|
||||
WREG_DAC(MGA1064_GEN_IO_CTL, 0);
|
||||
|
||||
switch (mdev->type) {
|
||||
case G200_SE_A:
|
||||
case G200_SE_B:
|
||||
case G200_EV:
|
||||
case G200_WB:
|
||||
data = 1;
|
||||
clock = 2;
|
||||
break;
|
||||
case G200_EH:
|
||||
case G200_ER:
|
||||
data = 2;
|
||||
clock = 1;
|
||||
break;
|
||||
default:
|
||||
data = 2;
|
||||
clock = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
i2c = kzalloc(sizeof(struct mga_i2c_chan), GFP_KERNEL);
|
||||
if (!i2c)
|
||||
return NULL;
|
||||
|
||||
i2c->data = data;
|
||||
i2c->clock = clock;
|
||||
i2c->adapter.owner = THIS_MODULE;
|
||||
i2c->adapter.class = I2C_CLASS_DDC;
|
||||
i2c->adapter.dev.parent = &dev->pdev->dev;
|
||||
i2c->dev = dev;
|
||||
i2c_set_adapdata(&i2c->adapter, i2c);
|
||||
snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), "mga i2c");
|
||||
|
||||
i2c->adapter.algo_data = &i2c->bit;
|
||||
|
||||
i2c->bit.udelay = 10;
|
||||
i2c->bit.timeout = 2;
|
||||
i2c->bit.data = i2c;
|
||||
i2c->bit.setsda = mga_gpio_setsda;
|
||||
i2c->bit.setscl = mga_gpio_setscl;
|
||||
i2c->bit.getsda = mga_gpio_getsda;
|
||||
i2c->bit.getscl = mga_gpio_getscl;
|
||||
|
||||
ret = i2c_bit_add_bus(&i2c->adapter);
|
||||
if (ret) {
|
||||
kfree(i2c);
|
||||
i2c = NULL;
|
||||
}
|
||||
return i2c;
|
||||
}
|
||||
|
||||
void mgag200_i2c_destroy(struct mga_i2c_chan *i2c)
|
||||
{
|
||||
if (!i2c)
|
||||
return;
|
||||
i2c_del_adapter(&i2c->adapter);
|
||||
kfree(i2c);
|
||||
}
|
||||
|
||||
367
drivers/gpu/drm/mgag200/mgag200_main.c
Normal file
367
drivers/gpu/drm/mgag200/mgag200_main.c
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
/*
|
||||
* Copyright 2010 Matt Turner.
|
||||
* Copyright 2012 Red Hat
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License version 2. See the file COPYING in the main
|
||||
* directory of this archive for more details.
|
||||
*
|
||||
* Authors: Matthew Garrett
|
||||
* Matt Turner
|
||||
* Dave Airlie
|
||||
*/
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include "mgag200_drv.h"
|
||||
|
||||
static void mga_user_framebuffer_destroy(struct drm_framebuffer *fb)
|
||||
{
|
||||
struct mga_framebuffer *mga_fb = to_mga_framebuffer(fb);
|
||||
if (mga_fb->obj)
|
||||
drm_gem_object_unreference_unlocked(mga_fb->obj);
|
||||
drm_framebuffer_cleanup(fb);
|
||||
kfree(fb);
|
||||
}
|
||||
|
||||
static const struct drm_framebuffer_funcs mga_fb_funcs = {
|
||||
.destroy = mga_user_framebuffer_destroy,
|
||||
};
|
||||
|
||||
int mgag200_framebuffer_init(struct drm_device *dev,
|
||||
struct mga_framebuffer *gfb,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj)
|
||||
{
|
||||
int ret;
|
||||
|
||||
drm_helper_mode_fill_fb_struct(&gfb->base, mode_cmd);
|
||||
gfb->obj = obj;
|
||||
ret = drm_framebuffer_init(dev, &gfb->base, &mga_fb_funcs);
|
||||
if (ret) {
|
||||
DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct drm_framebuffer *
|
||||
mgag200_user_framebuffer_create(struct drm_device *dev,
|
||||
struct drm_file *filp,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
struct mga_framebuffer *mga_fb;
|
||||
int ret;
|
||||
|
||||
obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);
|
||||
if (obj == NULL)
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
mga_fb = kzalloc(sizeof(*mga_fb), GFP_KERNEL);
|
||||
if (!mga_fb) {
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
ret = mgag200_framebuffer_init(dev, mga_fb, mode_cmd, obj);
|
||||
if (ret) {
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
kfree(mga_fb);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
return &mga_fb->base;
|
||||
}
|
||||
|
||||
static const struct drm_mode_config_funcs mga_mode_funcs = {
|
||||
.fb_create = mgag200_user_framebuffer_create,
|
||||
};
|
||||
|
||||
static int mga_probe_vram(struct mga_device *mdev, void __iomem *mem)
|
||||
{
|
||||
int offset;
|
||||
int orig;
|
||||
int test1, test2;
|
||||
int orig1, orig2;
|
||||
|
||||
/* Probe */
|
||||
orig = ioread16(mem);
|
||||
iowrite16(0, mem);
|
||||
|
||||
for (offset = 0x100000; offset < mdev->mc.vram_window; offset += 0x4000) {
|
||||
orig1 = ioread8(mem + offset);
|
||||
orig2 = ioread8(mem + offset + 0x100);
|
||||
|
||||
iowrite16(0xaa55, mem + offset);
|
||||
iowrite16(0xaa55, mem + offset + 0x100);
|
||||
|
||||
test1 = ioread16(mem + offset);
|
||||
test2 = ioread16(mem);
|
||||
|
||||
iowrite16(orig1, mem + offset);
|
||||
iowrite16(orig2, mem + offset + 0x100);
|
||||
|
||||
if (test1 != 0xaa55) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (test2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
iowrite16(orig, mem);
|
||||
return offset - 65536;
|
||||
}
|
||||
|
||||
/* Map the framebuffer from the card and configure the core */
|
||||
static int mga_vram_init(struct mga_device *mdev)
|
||||
{
|
||||
void __iomem *mem;
|
||||
struct apertures_struct *aper = alloc_apertures(1);
|
||||
if (!aper)
|
||||
return -ENOMEM;
|
||||
|
||||
/* BAR 0 is VRAM */
|
||||
mdev->mc.vram_base = pci_resource_start(mdev->dev->pdev, 0);
|
||||
mdev->mc.vram_window = pci_resource_len(mdev->dev->pdev, 0);
|
||||
|
||||
aper->ranges[0].base = mdev->mc.vram_base;
|
||||
aper->ranges[0].size = mdev->mc.vram_window;
|
||||
|
||||
remove_conflicting_framebuffers(aper, "mgafb", true);
|
||||
kfree(aper);
|
||||
|
||||
if (!devm_request_mem_region(mdev->dev->dev, mdev->mc.vram_base, mdev->mc.vram_window,
|
||||
"mgadrmfb_vram")) {
|
||||
DRM_ERROR("can't reserve VRAM\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
mem = pci_iomap(mdev->dev->pdev, 0, 0);
|
||||
|
||||
mdev->mc.vram_size = mga_probe_vram(mdev, mem);
|
||||
|
||||
pci_iounmap(mdev->dev->pdev, mem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mgag200_device_init(struct drm_device *dev,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct mga_device *mdev = dev->dev_private;
|
||||
int ret, option;
|
||||
|
||||
mdev->type = flags;
|
||||
|
||||
/* Hardcode the number of CRTCs to 1 */
|
||||
mdev->num_crtc = 1;
|
||||
|
||||
pci_read_config_dword(dev->pdev, PCI_MGA_OPTION, &option);
|
||||
mdev->has_sdram = !(option & (1 << 14));
|
||||
|
||||
/* BAR 0 is the framebuffer, BAR 1 contains registers */
|
||||
mdev->rmmio_base = pci_resource_start(mdev->dev->pdev, 1);
|
||||
mdev->rmmio_size = pci_resource_len(mdev->dev->pdev, 1);
|
||||
|
||||
if (!devm_request_mem_region(mdev->dev->dev, mdev->rmmio_base, mdev->rmmio_size,
|
||||
"mgadrmfb_mmio")) {
|
||||
DRM_ERROR("can't reserve mmio registers\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mdev->rmmio = pcim_iomap(dev->pdev, 1, 0);
|
||||
if (mdev->rmmio == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* stash G200 SE model number for later use */
|
||||
if (IS_G200_SE(mdev))
|
||||
mdev->unique_rev_id = RREG32(0x1e24);
|
||||
|
||||
ret = mga_vram_init(mdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mdev->bpp_shifts[0] = 0;
|
||||
mdev->bpp_shifts[1] = 1;
|
||||
mdev->bpp_shifts[2] = 0;
|
||||
mdev->bpp_shifts[3] = 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions here will be called by the core once it's bound the driver to
|
||||
* a PCI device
|
||||
*/
|
||||
|
||||
|
||||
int mgag200_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
{
|
||||
struct mga_device *mdev;
|
||||
int r;
|
||||
|
||||
mdev = devm_kzalloc(dev->dev, sizeof(struct mga_device), GFP_KERNEL);
|
||||
if (mdev == NULL)
|
||||
return -ENOMEM;
|
||||
dev->dev_private = (void *)mdev;
|
||||
mdev->dev = dev;
|
||||
|
||||
r = mgag200_device_init(dev, flags);
|
||||
if (r) {
|
||||
dev_err(&dev->pdev->dev, "Fatal error during GPU init: %d\n", r);
|
||||
return r;
|
||||
}
|
||||
r = mgag200_mm_init(mdev);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
drm_mode_config_init(dev);
|
||||
dev->mode_config.funcs = (void *)&mga_mode_funcs;
|
||||
if (IS_G200_SE(mdev) && mdev->mc.vram_size < (2048*1024))
|
||||
dev->mode_config.preferred_depth = 16;
|
||||
else
|
||||
dev->mode_config.preferred_depth = 24;
|
||||
dev->mode_config.prefer_shadow = 1;
|
||||
|
||||
r = mgag200_modeset_init(mdev);
|
||||
if (r) {
|
||||
dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Make small buffers to store a hardware cursor (double buffered icon updates) */
|
||||
mgag200_bo_create(dev, roundup(48*64, PAGE_SIZE), 0, 0,
|
||||
&mdev->cursor.pixels_1);
|
||||
mgag200_bo_create(dev, roundup(48*64, PAGE_SIZE), 0, 0,
|
||||
&mdev->cursor.pixels_2);
|
||||
if (!mdev->cursor.pixels_2 || !mdev->cursor.pixels_1)
|
||||
goto cursor_nospace;
|
||||
mdev->cursor.pixels_current = mdev->cursor.pixels_1;
|
||||
mdev->cursor.pixels_prev = mdev->cursor.pixels_2;
|
||||
goto cursor_done;
|
||||
cursor_nospace:
|
||||
mdev->cursor.pixels_1 = NULL;
|
||||
mdev->cursor.pixels_2 = NULL;
|
||||
dev_warn(&dev->pdev->dev, "Could not allocate space for cursors. Not doing hardware cursors.\n");
|
||||
cursor_done:
|
||||
|
||||
out:
|
||||
if (r)
|
||||
mgag200_driver_unload(dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
int mgag200_driver_unload(struct drm_device *dev)
|
||||
{
|
||||
struct mga_device *mdev = dev->dev_private;
|
||||
|
||||
if (mdev == NULL)
|
||||
return 0;
|
||||
mgag200_modeset_fini(mdev);
|
||||
mgag200_fbdev_fini(mdev);
|
||||
drm_mode_config_cleanup(dev);
|
||||
mgag200_mm_fini(mdev);
|
||||
dev->dev_private = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mgag200_gem_create(struct drm_device *dev,
|
||||
u32 size, bool iskernel,
|
||||
struct drm_gem_object **obj)
|
||||
{
|
||||
struct mgag200_bo *astbo;
|
||||
int ret;
|
||||
|
||||
*obj = NULL;
|
||||
|
||||
size = roundup(size, PAGE_SIZE);
|
||||
if (size == 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = mgag200_bo_create(dev, size, 0, 0, &astbo);
|
||||
if (ret) {
|
||||
if (ret != -ERESTARTSYS)
|
||||
DRM_ERROR("failed to allocate GEM object\n");
|
||||
return ret;
|
||||
}
|
||||
*obj = &astbo->gem;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mgag200_dumb_create(struct drm_file *file,
|
||||
struct drm_device *dev,
|
||||
struct drm_mode_create_dumb *args)
|
||||
{
|
||||
int ret;
|
||||
struct drm_gem_object *gobj;
|
||||
u32 handle;
|
||||
|
||||
args->pitch = args->width * ((args->bpp + 7) / 8);
|
||||
args->size = args->pitch * args->height;
|
||||
|
||||
ret = mgag200_gem_create(dev, args->size, false,
|
||||
&gobj);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = drm_gem_handle_create(file, gobj, &handle);
|
||||
drm_gem_object_unreference_unlocked(gobj);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
args->handle = handle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mgag200_bo_unref(struct mgag200_bo **bo)
|
||||
{
|
||||
struct ttm_buffer_object *tbo;
|
||||
|
||||
if ((*bo) == NULL)
|
||||
return;
|
||||
|
||||
tbo = &((*bo)->bo);
|
||||
ttm_bo_unref(&tbo);
|
||||
*bo = NULL;
|
||||
}
|
||||
|
||||
void mgag200_gem_free_object(struct drm_gem_object *obj)
|
||||
{
|
||||
struct mgag200_bo *mgag200_bo = gem_to_mga_bo(obj);
|
||||
|
||||
mgag200_bo_unref(&mgag200_bo);
|
||||
}
|
||||
|
||||
|
||||
static inline u64 mgag200_bo_mmap_offset(struct mgag200_bo *bo)
|
||||
{
|
||||
return drm_vma_node_offset_addr(&bo->bo.vma_node);
|
||||
}
|
||||
|
||||
int
|
||||
mgag200_dumb_mmap_offset(struct drm_file *file,
|
||||
struct drm_device *dev,
|
||||
uint32_t handle,
|
||||
uint64_t *offset)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
int ret;
|
||||
struct mgag200_bo *bo;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
obj = drm_gem_object_lookup(dev, file, handle);
|
||||
if (obj == NULL) {
|
||||
ret = -ENOENT;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
bo = gem_to_mga_bo(obj);
|
||||
*offset = mgag200_bo_mmap_offset(bo);
|
||||
|
||||
drm_gem_object_unreference(obj);
|
||||
ret = 0;
|
||||
out_unlock:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
|
||||
}
|
||||
1654
drivers/gpu/drm/mgag200/mgag200_mode.c
Normal file
1654
drivers/gpu/drm/mgag200/mgag200_mode.c
Normal file
File diff suppressed because it is too large
Load diff
665
drivers/gpu/drm/mgag200/mgag200_reg.h
Normal file
665
drivers/gpu/drm/mgag200/mgag200_reg.h
Normal file
|
|
@ -0,0 +1,665 @@
|
|||
/*
|
||||
* MGA Millennium (MGA2064W) functions
|
||||
* MGA Mystique (MGA1064SG) functions
|
||||
*
|
||||
* Copyright 1996 The XFree86 Project, Inc.
|
||||
*
|
||||
* Authors
|
||||
* Dirk Hohndel
|
||||
* hohndel@XFree86.Org
|
||||
* David Dawes
|
||||
* dawes@XFree86.Org
|
||||
* Contributors:
|
||||
* Guy DESBIEF, Aix-en-provence, France
|
||||
* g.desbief@aix.pacwan.net
|
||||
* MGA1064SG Mystique register file
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _MGA_REG_H_
|
||||
#define _MGA_REG_H_
|
||||
|
||||
#define MGAREG_DWGCTL 0x1c00
|
||||
#define MGAREG_MACCESS 0x1c04
|
||||
/* the following is a mystique only register */
|
||||
#define MGAREG_MCTLWTST 0x1c08
|
||||
#define MGAREG_ZORG 0x1c0c
|
||||
|
||||
#define MGAREG_PAT0 0x1c10
|
||||
#define MGAREG_PAT1 0x1c14
|
||||
#define MGAREG_PLNWT 0x1c1c
|
||||
|
||||
#define MGAREG_BCOL 0x1c20
|
||||
#define MGAREG_FCOL 0x1c24
|
||||
|
||||
#define MGAREG_SRC0 0x1c30
|
||||
#define MGAREG_SRC1 0x1c34
|
||||
#define MGAREG_SRC2 0x1c38
|
||||
#define MGAREG_SRC3 0x1c3c
|
||||
|
||||
#define MGAREG_XYSTRT 0x1c40
|
||||
#define MGAREG_XYEND 0x1c44
|
||||
|
||||
#define MGAREG_SHIFT 0x1c50
|
||||
/* the following is a mystique only register */
|
||||
#define MGAREG_DMAPAD 0x1c54
|
||||
#define MGAREG_SGN 0x1c58
|
||||
#define MGAREG_LEN 0x1c5c
|
||||
|
||||
#define MGAREG_AR0 0x1c60
|
||||
#define MGAREG_AR1 0x1c64
|
||||
#define MGAREG_AR2 0x1c68
|
||||
#define MGAREG_AR3 0x1c6c
|
||||
#define MGAREG_AR4 0x1c70
|
||||
#define MGAREG_AR5 0x1c74
|
||||
#define MGAREG_AR6 0x1c78
|
||||
|
||||
#define MGAREG_CXBNDRY 0x1c80
|
||||
#define MGAREG_FXBNDRY 0x1c84
|
||||
#define MGAREG_YDSTLEN 0x1c88
|
||||
#define MGAREG_PITCH 0x1c8c
|
||||
|
||||
#define MGAREG_YDST 0x1c90
|
||||
#define MGAREG_YDSTORG 0x1c94
|
||||
#define MGAREG_YTOP 0x1c98
|
||||
#define MGAREG_YBOT 0x1c9c
|
||||
|
||||
#define MGAREG_CXLEFT 0x1ca0
|
||||
#define MGAREG_CXRIGHT 0x1ca4
|
||||
#define MGAREG_FXLEFT 0x1ca8
|
||||
#define MGAREG_FXRIGHT 0x1cac
|
||||
|
||||
#define MGAREG_XDST 0x1cb0
|
||||
|
||||
#define MGAREG_DR0 0x1cc0
|
||||
#define MGAREG_DR1 0x1cc4
|
||||
#define MGAREG_DR2 0x1cc8
|
||||
#define MGAREG_DR3 0x1ccc
|
||||
|
||||
#define MGAREG_DR4 0x1cd0
|
||||
#define MGAREG_DR5 0x1cd4
|
||||
#define MGAREG_DR6 0x1cd8
|
||||
#define MGAREG_DR7 0x1cdc
|
||||
|
||||
#define MGAREG_DR8 0x1ce0
|
||||
#define MGAREG_DR9 0x1ce4
|
||||
#define MGAREG_DR10 0x1ce8
|
||||
#define MGAREG_DR11 0x1cec
|
||||
|
||||
#define MGAREG_DR12 0x1cf0
|
||||
#define MGAREG_DR13 0x1cf4
|
||||
#define MGAREG_DR14 0x1cf8
|
||||
#define MGAREG_DR15 0x1cfc
|
||||
|
||||
#define MGAREG_SRCORG 0x2cb4
|
||||
#define MGAREG_DSTORG 0x2cb8
|
||||
|
||||
/* add or or this to one of the previous "power registers" to start
|
||||
the drawing engine */
|
||||
|
||||
#define MGAREG_EXEC 0x0100
|
||||
|
||||
#define MGAREG_FIFOSTATUS 0x1e10
|
||||
#define MGAREG_Status 0x1e14
|
||||
#define MGAREG_CACHEFLUSH 0x1fff
|
||||
#define MGAREG_ICLEAR 0x1e18
|
||||
#define MGAREG_IEN 0x1e1c
|
||||
|
||||
#define MGAREG_VCOUNT 0x1e20
|
||||
|
||||
#define MGAREG_Reset 0x1e40
|
||||
|
||||
#define MGAREG_OPMODE 0x1e54
|
||||
|
||||
/* Warp Registers */
|
||||
#define MGAREG_WIADDR 0x1dc0
|
||||
#define MGAREG_WIADDR2 0x1dd8
|
||||
#define MGAREG_WGETMSB 0x1dc8
|
||||
#define MGAREG_WVRTXSZ 0x1dcc
|
||||
#define MGAREG_WACCEPTSEQ 0x1dd4
|
||||
#define MGAREG_WMISC 0x1e70
|
||||
|
||||
#define MGAREG_MEMCTL 0x2e08
|
||||
|
||||
/* OPMODE register additives */
|
||||
|
||||
#define MGAOPM_DMA_GENERAL (0x00 << 2)
|
||||
#define MGAOPM_DMA_BLIT (0x01 << 2)
|
||||
#define MGAOPM_DMA_VECTOR (0x10 << 2)
|
||||
|
||||
/* MACCESS register additives */
|
||||
#define MGAMAC_PW8 0x00
|
||||
#define MGAMAC_PW16 0x01
|
||||
#define MGAMAC_PW24 0x03 /* not a typo */
|
||||
#define MGAMAC_PW32 0x02 /* not a typo */
|
||||
#define MGAMAC_BYPASS332 0x10000000
|
||||
#define MGAMAC_NODITHER 0x40000000
|
||||
#define MGAMAC_DIT555 0x80000000
|
||||
|
||||
/* DWGCTL register additives */
|
||||
|
||||
/* Lines */
|
||||
|
||||
#define MGADWG_LINE_OPEN 0x00
|
||||
#define MGADWG_AUTOLINE_OPEN 0x01
|
||||
#define MGADWG_LINE_CLOSE 0x02
|
||||
#define MGADWG_AUTOLINE_CLOSE 0x03
|
||||
|
||||
/* Trapezoids */
|
||||
#define MGADWG_TRAP 0x04
|
||||
#define MGADWG_TEXTURE_TRAP 0x06
|
||||
|
||||
/* BitBlts */
|
||||
|
||||
#define MGADWG_BITBLT 0x08
|
||||
#define MGADWG_FBITBLT 0x0c
|
||||
#define MGADWG_ILOAD 0x09
|
||||
#define MGADWG_ILOAD_SCALE 0x0d
|
||||
#define MGADWG_ILOAD_FILTER 0x0f
|
||||
#define MGADWG_ILOAD_HIQH 0x07
|
||||
#define MGADWG_ILOAD_HIQHV 0x0e
|
||||
#define MGADWG_IDUMP 0x0a
|
||||
|
||||
/* atype access to WRAM */
|
||||
|
||||
#define MGADWG_RPL ( 0x00 << 4 )
|
||||
#define MGADWG_RSTR ( 0x01 << 4 )
|
||||
#define MGADWG_ZI ( 0x03 << 4 )
|
||||
#define MGADWG_BLK ( 0x04 << 4 )
|
||||
#define MGADWG_I ( 0x07 << 4 )
|
||||
|
||||
/* specifies whether bit blits are linear or xy */
|
||||
#define MGADWG_LINEAR ( 0x01 << 7 )
|
||||
|
||||
/* z drawing mode. use MGADWG_NOZCMP for always */
|
||||
|
||||
#define MGADWG_NOZCMP ( 0x00 << 8 )
|
||||
#define MGADWG_ZE ( 0x02 << 8 )
|
||||
#define MGADWG_ZNE ( 0x03 << 8 )
|
||||
#define MGADWG_ZLT ( 0x04 << 8 )
|
||||
#define MGADWG_ZLTE ( 0x05 << 8 )
|
||||
#define MGADWG_GT ( 0x06 << 8 )
|
||||
#define MGADWG_GTE ( 0x07 << 8 )
|
||||
|
||||
/* use this to force colour expansion circuitry to do its stuff */
|
||||
|
||||
#define MGADWG_SOLID ( 0x01 << 11 )
|
||||
|
||||
/* ar register at zero */
|
||||
|
||||
#define MGADWG_ARZERO ( 0x01 << 12 )
|
||||
|
||||
#define MGADWG_SGNZERO ( 0x01 << 13 )
|
||||
|
||||
#define MGADWG_SHIFTZERO ( 0x01 << 14 )
|
||||
|
||||
/* See table on 4-43 for bop ALU operations */
|
||||
|
||||
/* See table on 4-44 for translucidity masks */
|
||||
|
||||
#define MGADWG_BMONOLEF ( 0x00 << 25 )
|
||||
#define MGADWG_BMONOWF ( 0x04 << 25 )
|
||||
#define MGADWG_BPLAN ( 0x01 << 25 )
|
||||
|
||||
/* note that if bfcol is specified and you're doing a bitblt, it causes
|
||||
a fbitblt to be performed, so check that you obey the fbitblt rules */
|
||||
|
||||
#define MGADWG_BFCOL ( 0x02 << 25 )
|
||||
#define MGADWG_BUYUV ( 0x0e << 25 )
|
||||
#define MGADWG_BU32BGR ( 0x03 << 25 )
|
||||
#define MGADWG_BU32RGB ( 0x07 << 25 )
|
||||
#define MGADWG_BU24BGR ( 0x0b << 25 )
|
||||
#define MGADWG_BU24RGB ( 0x0f << 25 )
|
||||
|
||||
#define MGADWG_PATTERN ( 0x01 << 29 )
|
||||
#define MGADWG_TRANSC ( 0x01 << 30 )
|
||||
#define MGAREG_MISC_WRITE 0x3c2
|
||||
#define MGAREG_MISC_READ 0x3cc
|
||||
#define MGAREG_MEM_MISC_WRITE 0x1fc2
|
||||
#define MGAREG_MEM_MISC_READ 0x1fcc
|
||||
|
||||
#define MGAREG_MISC_IOADSEL (0x1 << 0)
|
||||
#define MGAREG_MISC_RAMMAPEN (0x1 << 1)
|
||||
#define MGAREG_MISC_CLK_SEL_VGA25 (0x0 << 2)
|
||||
#define MGAREG_MISC_CLK_SEL_VGA28 (0x1 << 2)
|
||||
#define MGAREG_MISC_CLK_SEL_MGA_PIX (0x2 << 2)
|
||||
#define MGAREG_MISC_CLK_SEL_MGA_MSK (0x3 << 2)
|
||||
#define MGAREG_MISC_VIDEO_DIS (0x1 << 4)
|
||||
#define MGAREG_MISC_HIGH_PG_SEL (0x1 << 5)
|
||||
|
||||
/* MMIO VGA registers */
|
||||
#define MGAREG_SEQ_INDEX 0x1fc4
|
||||
#define MGAREG_SEQ_DATA 0x1fc5
|
||||
#define MGAREG_CRTC_INDEX 0x1fd4
|
||||
#define MGAREG_CRTC_DATA 0x1fd5
|
||||
#define MGAREG_CRTCEXT_INDEX 0x1fde
|
||||
#define MGAREG_CRTCEXT_DATA 0x1fdf
|
||||
|
||||
/* Cursor X and Y position */
|
||||
#define MGA_CURPOSXL 0x3c0c
|
||||
#define MGA_CURPOSXH 0x3c0d
|
||||
#define MGA_CURPOSYL 0x3c0e
|
||||
#define MGA_CURPOSYH 0x3c0f
|
||||
|
||||
/* MGA bits for registers PCI_OPTION_REG */
|
||||
#define MGA1064_OPT_SYS_CLK_PCI ( 0x00 << 0 )
|
||||
#define MGA1064_OPT_SYS_CLK_PLL ( 0x01 << 0 )
|
||||
#define MGA1064_OPT_SYS_CLK_EXT ( 0x02 << 0 )
|
||||
#define MGA1064_OPT_SYS_CLK_MSK ( 0x03 << 0 )
|
||||
|
||||
#define MGA1064_OPT_SYS_CLK_DIS ( 0x01 << 2 )
|
||||
#define MGA1064_OPT_G_CLK_DIV_1 ( 0x01 << 3 )
|
||||
#define MGA1064_OPT_M_CLK_DIV_1 ( 0x01 << 4 )
|
||||
|
||||
#define MGA1064_OPT_SYS_PLL_PDN ( 0x01 << 5 )
|
||||
#define MGA1064_OPT_VGA_ION ( 0x01 << 8 )
|
||||
|
||||
/* MGA registers in PCI config space */
|
||||
#define PCI_MGA_INDEX 0x44
|
||||
#define PCI_MGA_DATA 0x48
|
||||
#define PCI_MGA_OPTION 0x40
|
||||
#define PCI_MGA_OPTION2 0x50
|
||||
#define PCI_MGA_OPTION3 0x54
|
||||
|
||||
#define RAMDAC_OFFSET 0x3c00
|
||||
|
||||
/* TVP3026 direct registers */
|
||||
|
||||
#define TVP3026_INDEX 0x00
|
||||
#define TVP3026_WADR_PAL 0x00
|
||||
#define TVP3026_COL_PAL 0x01
|
||||
#define TVP3026_PIX_RD_MSK 0x02
|
||||
#define TVP3026_RADR_PAL 0x03
|
||||
#define TVP3026_CUR_COL_ADDR 0x04
|
||||
#define TVP3026_CUR_COL_DATA 0x05
|
||||
#define TVP3026_DATA 0x0a
|
||||
#define TVP3026_CUR_RAM 0x0b
|
||||
#define TVP3026_CUR_XLOW 0x0c
|
||||
#define TVP3026_CUR_XHI 0x0d
|
||||
#define TVP3026_CUR_YLOW 0x0e
|
||||
#define TVP3026_CUR_YHI 0x0f
|
||||
|
||||
/* TVP3026 indirect registers */
|
||||
|
||||
#define TVP3026_SILICON_REV 0x01
|
||||
#define TVP3026_CURSOR_CTL 0x06
|
||||
#define TVP3026_LATCH_CTL 0x0f
|
||||
#define TVP3026_TRUE_COLOR_CTL 0x18
|
||||
#define TVP3026_MUX_CTL 0x19
|
||||
#define TVP3026_CLK_SEL 0x1a
|
||||
#define TVP3026_PAL_PAGE 0x1c
|
||||
#define TVP3026_GEN_CTL 0x1d
|
||||
#define TVP3026_MISC_CTL 0x1e
|
||||
#define TVP3026_GEN_IO_CTL 0x2a
|
||||
#define TVP3026_GEN_IO_DATA 0x2b
|
||||
#define TVP3026_PLL_ADDR 0x2c
|
||||
#define TVP3026_PIX_CLK_DATA 0x2d
|
||||
#define TVP3026_MEM_CLK_DATA 0x2e
|
||||
#define TVP3026_LOAD_CLK_DATA 0x2f
|
||||
#define TVP3026_KEY_RED_LOW 0x32
|
||||
#define TVP3026_KEY_RED_HI 0x33
|
||||
#define TVP3026_KEY_GREEN_LOW 0x34
|
||||
#define TVP3026_KEY_GREEN_HI 0x35
|
||||
#define TVP3026_KEY_BLUE_LOW 0x36
|
||||
#define TVP3026_KEY_BLUE_HI 0x37
|
||||
#define TVP3026_KEY_CTL 0x38
|
||||
#define TVP3026_MCLK_CTL 0x39
|
||||
#define TVP3026_SENSE_TEST 0x3a
|
||||
#define TVP3026_TEST_DATA 0x3b
|
||||
#define TVP3026_CRC_LSB 0x3c
|
||||
#define TVP3026_CRC_MSB 0x3d
|
||||
#define TVP3026_CRC_CTL 0x3e
|
||||
#define TVP3026_ID 0x3f
|
||||
#define TVP3026_RESET 0xff
|
||||
|
||||
|
||||
/* MGA1064 DAC Register file */
|
||||
/* MGA1064 direct registers */
|
||||
|
||||
#define MGA1064_INDEX 0x00
|
||||
#define MGA1064_WADR_PAL 0x00
|
||||
#define MGA1064_SPAREREG 0x00
|
||||
#define MGA1064_COL_PAL 0x01
|
||||
#define MGA1064_PIX_RD_MSK 0x02
|
||||
#define MGA1064_RADR_PAL 0x03
|
||||
#define MGA1064_DATA 0x0a
|
||||
|
||||
#define MGA1064_CUR_XLOW 0x0c
|
||||
#define MGA1064_CUR_XHI 0x0d
|
||||
#define MGA1064_CUR_YLOW 0x0e
|
||||
#define MGA1064_CUR_YHI 0x0f
|
||||
|
||||
/* MGA1064 indirect registers */
|
||||
#define MGA1064_DVI_PIPE_CTL 0x03
|
||||
#define MGA1064_CURSOR_BASE_ADR_LOW 0x04
|
||||
#define MGA1064_CURSOR_BASE_ADR_HI 0x05
|
||||
#define MGA1064_CURSOR_CTL 0x06
|
||||
#define MGA1064_CURSOR_COL0_RED 0x08
|
||||
#define MGA1064_CURSOR_COL0_GREEN 0x09
|
||||
#define MGA1064_CURSOR_COL0_BLUE 0x0a
|
||||
|
||||
#define MGA1064_CURSOR_COL1_RED 0x0c
|
||||
#define MGA1064_CURSOR_COL1_GREEN 0x0d
|
||||
#define MGA1064_CURSOR_COL1_BLUE 0x0e
|
||||
|
||||
#define MGA1064_CURSOR_COL2_RED 0x010
|
||||
#define MGA1064_CURSOR_COL2_GREEN 0x011
|
||||
#define MGA1064_CURSOR_COL2_BLUE 0x012
|
||||
|
||||
#define MGA1064_VREF_CTL 0x018
|
||||
|
||||
#define MGA1064_MUL_CTL 0x19
|
||||
#define MGA1064_MUL_CTL_8bits 0x0
|
||||
#define MGA1064_MUL_CTL_15bits 0x01
|
||||
#define MGA1064_MUL_CTL_16bits 0x02
|
||||
#define MGA1064_MUL_CTL_24bits 0x03
|
||||
#define MGA1064_MUL_CTL_32bits 0x04
|
||||
#define MGA1064_MUL_CTL_2G8V16bits 0x05
|
||||
#define MGA1064_MUL_CTL_G16V16bits 0x06
|
||||
#define MGA1064_MUL_CTL_32_24bits 0x07
|
||||
|
||||
#define MGA1064_PIX_CLK_CTL 0x1a
|
||||
#define MGA1064_PIX_CLK_CTL_CLK_DIS ( 0x01 << 2 )
|
||||
#define MGA1064_PIX_CLK_CTL_CLK_POW_DOWN ( 0x01 << 3 )
|
||||
#define MGA1064_PIX_CLK_CTL_SEL_PCI ( 0x00 << 0 )
|
||||
#define MGA1064_PIX_CLK_CTL_SEL_PLL ( 0x01 << 0 )
|
||||
#define MGA1064_PIX_CLK_CTL_SEL_EXT ( 0x02 << 0 )
|
||||
#define MGA1064_PIX_CLK_CTL_SEL_MSK ( 0x03 << 0 )
|
||||
|
||||
#define MGA1064_GEN_CTL 0x1d
|
||||
#define MGA1064_GEN_CTL_SYNC_ON_GREEN_DIS (0x01 << 5)
|
||||
#define MGA1064_MISC_CTL 0x1e
|
||||
#define MGA1064_MISC_CTL_DAC_EN ( 0x01 << 0 )
|
||||
#define MGA1064_MISC_CTL_VGA ( 0x01 << 1 )
|
||||
#define MGA1064_MISC_CTL_DIS_CON ( 0x03 << 1 )
|
||||
#define MGA1064_MISC_CTL_MAFC ( 0x02 << 1 )
|
||||
#define MGA1064_MISC_CTL_VGA8 ( 0x01 << 3 )
|
||||
#define MGA1064_MISC_CTL_DAC_RAM_CS ( 0x01 << 4 )
|
||||
|
||||
#define MGA1064_GEN_IO_CTL2 0x29
|
||||
#define MGA1064_GEN_IO_CTL 0x2a
|
||||
#define MGA1064_GEN_IO_DATA 0x2b
|
||||
#define MGA1064_SYS_PLL_M 0x2c
|
||||
#define MGA1064_SYS_PLL_N 0x2d
|
||||
#define MGA1064_SYS_PLL_P 0x2e
|
||||
#define MGA1064_SYS_PLL_STAT 0x2f
|
||||
|
||||
#define MGA1064_REMHEADCTL 0x30
|
||||
#define MGA1064_REMHEADCTL_CLKDIS ( 0x01 << 0 )
|
||||
#define MGA1064_REMHEADCTL_CLKSL_OFF ( 0x00 << 1 )
|
||||
#define MGA1064_REMHEADCTL_CLKSL_PLL ( 0x01 << 1 )
|
||||
#define MGA1064_REMHEADCTL_CLKSL_PCI ( 0x02 << 1 )
|
||||
#define MGA1064_REMHEADCTL_CLKSL_MSK ( 0x03 << 1 )
|
||||
|
||||
#define MGA1064_REMHEADCTL2 0x31
|
||||
|
||||
#define MGA1064_ZOOM_CTL 0x38
|
||||
#define MGA1064_SENSE_TST 0x3a
|
||||
|
||||
#define MGA1064_CRC_LSB 0x3c
|
||||
#define MGA1064_CRC_MSB 0x3d
|
||||
#define MGA1064_CRC_CTL 0x3e
|
||||
#define MGA1064_COL_KEY_MSK_LSB 0x40
|
||||
#define MGA1064_COL_KEY_MSK_MSB 0x41
|
||||
#define MGA1064_COL_KEY_LSB 0x42
|
||||
#define MGA1064_COL_KEY_MSB 0x43
|
||||
#define MGA1064_PIX_PLLA_M 0x44
|
||||
#define MGA1064_PIX_PLLA_N 0x45
|
||||
#define MGA1064_PIX_PLLA_P 0x46
|
||||
#define MGA1064_PIX_PLLB_M 0x48
|
||||
#define MGA1064_PIX_PLLB_N 0x49
|
||||
#define MGA1064_PIX_PLLB_P 0x4a
|
||||
#define MGA1064_PIX_PLLC_M 0x4c
|
||||
#define MGA1064_PIX_PLLC_N 0x4d
|
||||
#define MGA1064_PIX_PLLC_P 0x4e
|
||||
|
||||
#define MGA1064_PIX_PLL_STAT 0x4f
|
||||
|
||||
/*Added for G450 dual head*/
|
||||
|
||||
#define MGA1064_VID_PLL_STAT 0x8c
|
||||
#define MGA1064_VID_PLL_P 0x8D
|
||||
#define MGA1064_VID_PLL_M 0x8E
|
||||
#define MGA1064_VID_PLL_N 0x8F
|
||||
|
||||
/* Modified PLL for G200 Winbond (G200WB) */
|
||||
#define MGA1064_WB_PIX_PLLC_M 0xb7
|
||||
#define MGA1064_WB_PIX_PLLC_N 0xb6
|
||||
#define MGA1064_WB_PIX_PLLC_P 0xb8
|
||||
|
||||
/* Modified PLL for G200 Maxim (G200EV) */
|
||||
#define MGA1064_EV_PIX_PLLC_M 0xb6
|
||||
#define MGA1064_EV_PIX_PLLC_N 0xb7
|
||||
#define MGA1064_EV_PIX_PLLC_P 0xb8
|
||||
|
||||
/* Modified PLL for G200 EH */
|
||||
#define MGA1064_EH_PIX_PLLC_M 0xb6
|
||||
#define MGA1064_EH_PIX_PLLC_N 0xb7
|
||||
#define MGA1064_EH_PIX_PLLC_P 0xb8
|
||||
|
||||
/* Modified PLL for G200 Maxim (G200ER) */
|
||||
#define MGA1064_ER_PIX_PLLC_M 0xb7
|
||||
#define MGA1064_ER_PIX_PLLC_N 0xb6
|
||||
#define MGA1064_ER_PIX_PLLC_P 0xb8
|
||||
|
||||
#define MGA1064_DISP_CTL 0x8a
|
||||
#define MGA1064_DISP_CTL_DAC1OUTSEL_MASK 0x01
|
||||
#define MGA1064_DISP_CTL_DAC1OUTSEL_DIS 0x00
|
||||
#define MGA1064_DISP_CTL_DAC1OUTSEL_EN 0x01
|
||||
#define MGA1064_DISP_CTL_DAC2OUTSEL_MASK (0x03 << 2)
|
||||
#define MGA1064_DISP_CTL_DAC2OUTSEL_DIS 0x00
|
||||
#define MGA1064_DISP_CTL_DAC2OUTSEL_CRTC1 (0x01 << 2)
|
||||
#define MGA1064_DISP_CTL_DAC2OUTSEL_CRTC2 (0x02 << 2)
|
||||
#define MGA1064_DISP_CTL_DAC2OUTSEL_TVE (0x03 << 2)
|
||||
#define MGA1064_DISP_CTL_PANOUTSEL_MASK (0x03 << 5)
|
||||
#define MGA1064_DISP_CTL_PANOUTSEL_DIS 0x00
|
||||
#define MGA1064_DISP_CTL_PANOUTSEL_CRTC1 (0x01 << 5)
|
||||
#define MGA1064_DISP_CTL_PANOUTSEL_CRTC2RGB (0x02 << 5)
|
||||
#define MGA1064_DISP_CTL_PANOUTSEL_CRTC2656 (0x03 << 5)
|
||||
|
||||
#define MGA1064_SYNC_CTL 0x8b
|
||||
|
||||
#define MGA1064_PWR_CTL 0xa0
|
||||
#define MGA1064_PWR_CTL_DAC2_EN (0x01 << 0)
|
||||
#define MGA1064_PWR_CTL_VID_PLL_EN (0x01 << 1)
|
||||
#define MGA1064_PWR_CTL_PANEL_EN (0x01 << 2)
|
||||
#define MGA1064_PWR_CTL_RFIFO_EN (0x01 << 3)
|
||||
#define MGA1064_PWR_CTL_CFIFO_EN (0x01 << 4)
|
||||
|
||||
#define MGA1064_PAN_CTL 0xa2
|
||||
|
||||
/* Using crtc2 */
|
||||
#define MGAREG2_C2CTL 0x10
|
||||
#define MGAREG2_C2HPARAM 0x14
|
||||
#define MGAREG2_C2HSYNC 0x18
|
||||
#define MGAREG2_C2VPARAM 0x1c
|
||||
#define MGAREG2_C2VSYNC 0x20
|
||||
#define MGAREG2_C2STARTADD0 0x28
|
||||
|
||||
#define MGAREG2_C2OFFSET 0x40
|
||||
#define MGAREG2_C2DATACTL 0x4c
|
||||
|
||||
#define MGAREG_C2CTL 0x3c10
|
||||
#define MGAREG_C2CTL_C2_EN 0x01
|
||||
|
||||
#define MGAREG_C2_HIPRILVL_M (0x07 << 4)
|
||||
#define MGAREG_C2_MAXHIPRI_M (0x07 << 8)
|
||||
|
||||
#define MGAREG_C2CTL_PIXCLKSEL_MASK (0x03 << 1)
|
||||
#define MGAREG_C2CTL_PIXCLKSELH_MASK (0x01 << 14)
|
||||
#define MGAREG_C2CTL_PIXCLKSEL_PCICLK 0x00
|
||||
#define MGAREG_C2CTL_PIXCLKSEL_VDOCLK (0x01 << 1)
|
||||
#define MGAREG_C2CTL_PIXCLKSEL_PIXELPLL (0x02 << 1)
|
||||
#define MGAREG_C2CTL_PIXCLKSEL_VIDEOPLL (0x03 << 1)
|
||||
#define MGAREG_C2CTL_PIXCLKSEL_VDCLK (0x01 << 14)
|
||||
|
||||
#define MGAREG_C2CTL_PIXCLKSEL_CRISTAL (0x01 << 1) | (0x01 << 14)
|
||||
#define MGAREG_C2CTL_PIXCLKSEL_SYSTEMPLL (0x02 << 1) | (0x01 << 14)
|
||||
|
||||
#define MGAREG_C2CTL_PIXCLKDIS_MASK (0x01 << 3)
|
||||
#define MGAREG_C2CTL_PIXCLKDIS_DISABLE (0x01 << 3)
|
||||
|
||||
#define MGAREG_C2CTL_CRTCDACSEL_MASK (0x01 << 20)
|
||||
#define MGAREG_C2CTL_CRTCDACSEL_CRTC1 0x00
|
||||
#define MGAREG_C2CTL_CRTCDACSEL_CRTC2 (0x01 << 20)
|
||||
|
||||
#define MGAREG_C2HPARAM 0x3c14
|
||||
#define MGAREG_C2HSYNC 0x3c18
|
||||
#define MGAREG_C2VPARAM 0x3c1c
|
||||
#define MGAREG_C2VSYNC 0x3c20
|
||||
#define MGAREG_C2STARTADD0 0x3c28
|
||||
|
||||
#define MGAREG_C2OFFSET 0x3c40
|
||||
#define MGAREG_C2DATACTL 0x3c4c
|
||||
|
||||
/* video register */
|
||||
|
||||
#define MGAREG_BESA1C3ORG 0x3d60
|
||||
#define MGAREG_BESA1CORG 0x3d10
|
||||
#define MGAREG_BESA1ORG 0x3d00
|
||||
#define MGAREG_BESCTL 0x3d20
|
||||
#define MGAREG_BESGLOBCTL 0x3dc0
|
||||
#define MGAREG_BESHCOORD 0x3d28
|
||||
#define MGAREG_BESHISCAL 0x3d30
|
||||
#define MGAREG_BESHSRCEND 0x3d3c
|
||||
#define MGAREG_BESHSRCLST 0x3d50
|
||||
#define MGAREG_BESHSRCST 0x3d38
|
||||
#define MGAREG_BESLUMACTL 0x3d40
|
||||
#define MGAREG_BESPITCH 0x3d24
|
||||
#define MGAREG_BESV1SRCLST 0x3d54
|
||||
#define MGAREG_BESV1WGHT 0x3d48
|
||||
#define MGAREG_BESVCOORD 0x3d2c
|
||||
#define MGAREG_BESVISCAL 0x3d34
|
||||
|
||||
/* texture engine registers */
|
||||
|
||||
#define MGAREG_TMR0 0x2c00
|
||||
#define MGAREG_TMR1 0x2c04
|
||||
#define MGAREG_TMR2 0x2c08
|
||||
#define MGAREG_TMR3 0x2c0c
|
||||
#define MGAREG_TMR4 0x2c10
|
||||
#define MGAREG_TMR5 0x2c14
|
||||
#define MGAREG_TMR6 0x2c18
|
||||
#define MGAREG_TMR7 0x2c1c
|
||||
#define MGAREG_TMR8 0x2c20
|
||||
#define MGAREG_TEXORG 0x2c24
|
||||
#define MGAREG_TEXWIDTH 0x2c28
|
||||
#define MGAREG_TEXHEIGHT 0x2c2c
|
||||
#define MGAREG_TEXCTL 0x2c30
|
||||
# define MGA_TW4 (0x00000000)
|
||||
# define MGA_TW8 (0x00000001)
|
||||
# define MGA_TW15 (0x00000002)
|
||||
# define MGA_TW16 (0x00000003)
|
||||
# define MGA_TW12 (0x00000004)
|
||||
# define MGA_TW32 (0x00000006)
|
||||
# define MGA_TW8A (0x00000007)
|
||||
# define MGA_TW8AL (0x00000008)
|
||||
# define MGA_TW422 (0x0000000A)
|
||||
# define MGA_TW422UYVY (0x0000000B)
|
||||
# define MGA_PITCHLIN (0x00000100)
|
||||
# define MGA_NOPERSPECTIVE (0x00200000)
|
||||
# define MGA_TAKEY (0x02000000)
|
||||
# define MGA_TAMASK (0x04000000)
|
||||
# define MGA_CLAMPUV (0x18000000)
|
||||
# define MGA_TEXMODULATE (0x20000000)
|
||||
#define MGAREG_TEXCTL2 0x2c3c
|
||||
# define MGA_G400_TC2_MAGIC (0x00008000)
|
||||
# define MGA_TC2_DECALBLEND (0x00000001)
|
||||
# define MGA_TC2_IDECAL (0x00000002)
|
||||
# define MGA_TC2_DECALDIS (0x00000004)
|
||||
# define MGA_TC2_CKSTRANSDIS (0x00000010)
|
||||
# define MGA_TC2_BORDEREN (0x00000020)
|
||||
# define MGA_TC2_SPECEN (0x00000040)
|
||||
# define MGA_TC2_DUALTEX (0x00000080)
|
||||
# define MGA_TC2_TABLEFOG (0x00000100)
|
||||
# define MGA_TC2_BUMPMAP (0x00000200)
|
||||
# define MGA_TC2_SELECT_TMU1 (0x80000000)
|
||||
#define MGAREG_TEXTRANS 0x2c34
|
||||
#define MGAREG_TEXTRANSHIGH 0x2c38
|
||||
#define MGAREG_TEXFILTER 0x2c58
|
||||
# define MGA_MIN_NRST (0x00000000)
|
||||
# define MGA_MIN_BILIN (0x00000002)
|
||||
# define MGA_MIN_ANISO (0x0000000D)
|
||||
# define MGA_MAG_NRST (0x00000000)
|
||||
# define MGA_MAG_BILIN (0x00000020)
|
||||
# define MGA_FILTERALPHA (0x00100000)
|
||||
#define MGAREG_ALPHASTART 0x2c70
|
||||
#define MGAREG_ALPHAXINC 0x2c74
|
||||
#define MGAREG_ALPHAYINC 0x2c78
|
||||
#define MGAREG_ALPHACTRL 0x2c7c
|
||||
# define MGA_SRC_ZERO (0x00000000)
|
||||
# define MGA_SRC_ONE (0x00000001)
|
||||
# define MGA_SRC_DST_COLOR (0x00000002)
|
||||
# define MGA_SRC_ONE_MINUS_DST_COLOR (0x00000003)
|
||||
# define MGA_SRC_ALPHA (0x00000004)
|
||||
# define MGA_SRC_ONE_MINUS_SRC_ALPHA (0x00000005)
|
||||
# define MGA_SRC_DST_ALPHA (0x00000006)
|
||||
# define MGA_SRC_ONE_MINUS_DST_ALPHA (0x00000007)
|
||||
# define MGA_SRC_SRC_ALPHA_SATURATE (0x00000008)
|
||||
# define MGA_SRC_BLEND_MASK (0x0000000f)
|
||||
# define MGA_DST_ZERO (0x00000000)
|
||||
# define MGA_DST_ONE (0x00000010)
|
||||
# define MGA_DST_SRC_COLOR (0x00000020)
|
||||
# define MGA_DST_ONE_MINUS_SRC_COLOR (0x00000030)
|
||||
# define MGA_DST_SRC_ALPHA (0x00000040)
|
||||
# define MGA_DST_ONE_MINUS_SRC_ALPHA (0x00000050)
|
||||
# define MGA_DST_DST_ALPHA (0x00000060)
|
||||
# define MGA_DST_ONE_MINUS_DST_ALPHA (0x00000070)
|
||||
# define MGA_DST_BLEND_MASK (0x00000070)
|
||||
# define MGA_ALPHACHANNEL (0x00000100)
|
||||
# define MGA_VIDEOALPHA (0x00000200)
|
||||
# define MGA_DIFFUSEDALPHA (0x01000000)
|
||||
# define MGA_MODULATEDALPHA (0x02000000)
|
||||
#define MGAREG_TDUALSTAGE0 (0x2CF8)
|
||||
#define MGAREG_TDUALSTAGE1 (0x2CFC)
|
||||
# define MGA_TDS_COLOR_ARG2_DIFFUSE (0x00000000)
|
||||
# define MGA_TDS_COLOR_ARG2_SPECULAR (0x00000001)
|
||||
# define MGA_TDS_COLOR_ARG2_FCOL (0x00000002)
|
||||
# define MGA_TDS_COLOR_ARG2_PREVSTAGE (0x00000003)
|
||||
# define MGA_TDS_COLOR_ALPHA_DIFFUSE (0x00000000)
|
||||
# define MGA_TDS_COLOR_ALPHA_FCOL (0x00000004)
|
||||
# define MGA_TDS_COLOR_ALPHA_CURRTEX (0x00000008)
|
||||
# define MGA_TDS_COLOR_ALPHA_PREVTEX (0x0000000c)
|
||||
# define MGA_TDS_COLOR_ALPHA_PREVSTAGE (0x00000010)
|
||||
# define MGA_TDS_COLOR_ARG1_REPLICATEALPHA (0x00000020)
|
||||
# define MGA_TDS_COLOR_ARG1_INV (0x00000040)
|
||||
# define MGA_TDS_COLOR_ARG2_REPLICATEALPHA (0x00000080)
|
||||
# define MGA_TDS_COLOR_ARG2_INV (0x00000100)
|
||||
# define MGA_TDS_COLOR_ALPHA1INV (0x00000200)
|
||||
# define MGA_TDS_COLOR_ALPHA2INV (0x00000400)
|
||||
# define MGA_TDS_COLOR_ARG1MUL_ALPHA1 (0x00000800)
|
||||
# define MGA_TDS_COLOR_ARG2MUL_ALPHA2 (0x00001000)
|
||||
# define MGA_TDS_COLOR_ARG1ADD_MULOUT (0x00002000)
|
||||
# define MGA_TDS_COLOR_ARG2ADD_MULOUT (0x00004000)
|
||||
# define MGA_TDS_COLOR_MODBRIGHT_2X (0x00008000)
|
||||
# define MGA_TDS_COLOR_MODBRIGHT_4X (0x00010000)
|
||||
# define MGA_TDS_COLOR_ADD_SUB (0x00000000)
|
||||
# define MGA_TDS_COLOR_ADD_ADD (0x00020000)
|
||||
# define MGA_TDS_COLOR_ADD2X (0x00040000)
|
||||
# define MGA_TDS_COLOR_ADDBIAS (0x00080000)
|
||||
# define MGA_TDS_COLOR_BLEND (0x00100000)
|
||||
# define MGA_TDS_COLOR_SEL_ARG1 (0x00000000)
|
||||
# define MGA_TDS_COLOR_SEL_ARG2 (0x00200000)
|
||||
# define MGA_TDS_COLOR_SEL_ADD (0x00400000)
|
||||
# define MGA_TDS_COLOR_SEL_MUL (0x00600000)
|
||||
# define MGA_TDS_ALPHA_ARG1_INV (0x00800000)
|
||||
# define MGA_TDS_ALPHA_ARG2_DIFFUSE (0x00000000)
|
||||
# define MGA_TDS_ALPHA_ARG2_FCOL (0x01000000)
|
||||
# define MGA_TDS_ALPHA_ARG2_PREVTEX (0x02000000)
|
||||
# define MGA_TDS_ALPHA_ARG2_PREVSTAGE (0x03000000)
|
||||
# define MGA_TDS_ALPHA_ARG2_INV (0x04000000)
|
||||
# define MGA_TDS_ALPHA_ADD (0x08000000)
|
||||
# define MGA_TDS_ALPHA_ADDBIAS (0x10000000)
|
||||
# define MGA_TDS_ALPHA_ADD2X (0x20000000)
|
||||
# define MGA_TDS_ALPHA_SEL_ARG1 (0x00000000)
|
||||
# define MGA_TDS_ALPHA_SEL_ARG2 (0x40000000)
|
||||
# define MGA_TDS_ALPHA_SEL_ADD (0x80000000)
|
||||
# define MGA_TDS_ALPHA_SEL_MUL (0xc0000000)
|
||||
|
||||
#define MGAREG_DWGSYNC 0x2c4c
|
||||
|
||||
#define MGAREG_AGP_PLL 0x1e4c
|
||||
#define MGA_AGP2XPLL_ENABLE 0x1
|
||||
#define MGA_AGP2XPLL_DISABLE 0x0
|
||||
|
||||
#endif
|
||||
436
drivers/gpu/drm/mgag200/mgag200_ttm.c
Normal file
436
drivers/gpu/drm/mgag200/mgag200_ttm.c
Normal file
|
|
@ -0,0 +1,436 @@
|
|||
/*
|
||||
* Copyright 2012 Red Hat Inc.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Authors: Dave Airlie <airlied@redhat.com>
|
||||
*/
|
||||
#include <drm/drmP.h>
|
||||
#include "mgag200_drv.h"
|
||||
#include <ttm/ttm_page_alloc.h>
|
||||
|
||||
static inline struct mga_device *
|
||||
mgag200_bdev(struct ttm_bo_device *bd)
|
||||
{
|
||||
return container_of(bd, struct mga_device, ttm.bdev);
|
||||
}
|
||||
|
||||
static int
|
||||
mgag200_ttm_mem_global_init(struct drm_global_reference *ref)
|
||||
{
|
||||
return ttm_mem_global_init(ref->object);
|
||||
}
|
||||
|
||||
static void
|
||||
mgag200_ttm_mem_global_release(struct drm_global_reference *ref)
|
||||
{
|
||||
ttm_mem_global_release(ref->object);
|
||||
}
|
||||
|
||||
static int mgag200_ttm_global_init(struct mga_device *ast)
|
||||
{
|
||||
struct drm_global_reference *global_ref;
|
||||
int r;
|
||||
|
||||
global_ref = &ast->ttm.mem_global_ref;
|
||||
global_ref->global_type = DRM_GLOBAL_TTM_MEM;
|
||||
global_ref->size = sizeof(struct ttm_mem_global);
|
||||
global_ref->init = &mgag200_ttm_mem_global_init;
|
||||
global_ref->release = &mgag200_ttm_mem_global_release;
|
||||
r = drm_global_item_ref(global_ref);
|
||||
if (r != 0) {
|
||||
DRM_ERROR("Failed setting up TTM memory accounting "
|
||||
"subsystem.\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
ast->ttm.bo_global_ref.mem_glob =
|
||||
ast->ttm.mem_global_ref.object;
|
||||
global_ref = &ast->ttm.bo_global_ref.ref;
|
||||
global_ref->global_type = DRM_GLOBAL_TTM_BO;
|
||||
global_ref->size = sizeof(struct ttm_bo_global);
|
||||
global_ref->init = &ttm_bo_global_init;
|
||||
global_ref->release = &ttm_bo_global_release;
|
||||
r = drm_global_item_ref(global_ref);
|
||||
if (r != 0) {
|
||||
DRM_ERROR("Failed setting up TTM BO subsystem.\n");
|
||||
drm_global_item_unref(&ast->ttm.mem_global_ref);
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mgag200_ttm_global_release(struct mga_device *ast)
|
||||
{
|
||||
if (ast->ttm.mem_global_ref.release == NULL)
|
||||
return;
|
||||
|
||||
drm_global_item_unref(&ast->ttm.bo_global_ref.ref);
|
||||
drm_global_item_unref(&ast->ttm.mem_global_ref);
|
||||
ast->ttm.mem_global_ref.release = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void mgag200_bo_ttm_destroy(struct ttm_buffer_object *tbo)
|
||||
{
|
||||
struct mgag200_bo *bo;
|
||||
|
||||
bo = container_of(tbo, struct mgag200_bo, bo);
|
||||
|
||||
drm_gem_object_release(&bo->gem);
|
||||
kfree(bo);
|
||||
}
|
||||
|
||||
static bool mgag200_ttm_bo_is_mgag200_bo(struct ttm_buffer_object *bo)
|
||||
{
|
||||
if (bo->destroy == &mgag200_bo_ttm_destroy)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
mgag200_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
|
||||
struct ttm_mem_type_manager *man)
|
||||
{
|
||||
switch (type) {
|
||||
case TTM_PL_SYSTEM:
|
||||
man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
|
||||
man->available_caching = TTM_PL_MASK_CACHING;
|
||||
man->default_caching = TTM_PL_FLAG_CACHED;
|
||||
break;
|
||||
case TTM_PL_VRAM:
|
||||
man->func = &ttm_bo_manager_func;
|
||||
man->flags = TTM_MEMTYPE_FLAG_FIXED |
|
||||
TTM_MEMTYPE_FLAG_MAPPABLE;
|
||||
man->available_caching = TTM_PL_FLAG_UNCACHED |
|
||||
TTM_PL_FLAG_WC;
|
||||
man->default_caching = TTM_PL_FLAG_WC;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mgag200_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
|
||||
{
|
||||
struct mgag200_bo *mgabo = mgag200_bo(bo);
|
||||
|
||||
if (!mgag200_ttm_bo_is_mgag200_bo(bo))
|
||||
return;
|
||||
|
||||
mgag200_ttm_placement(mgabo, TTM_PL_FLAG_SYSTEM);
|
||||
*pl = mgabo->placement;
|
||||
}
|
||||
|
||||
static int mgag200_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)
|
||||
{
|
||||
struct mgag200_bo *mgabo = mgag200_bo(bo);
|
||||
|
||||
return drm_vma_node_verify_access(&mgabo->gem.vma_node, filp);
|
||||
}
|
||||
|
||||
static int mgag200_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
|
||||
struct ttm_mem_reg *mem)
|
||||
{
|
||||
struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
|
||||
struct mga_device *mdev = mgag200_bdev(bdev);
|
||||
|
||||
mem->bus.addr = NULL;
|
||||
mem->bus.offset = 0;
|
||||
mem->bus.size = mem->num_pages << PAGE_SHIFT;
|
||||
mem->bus.base = 0;
|
||||
mem->bus.is_iomem = false;
|
||||
if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
|
||||
return -EINVAL;
|
||||
switch (mem->mem_type) {
|
||||
case TTM_PL_SYSTEM:
|
||||
/* system memory */
|
||||
return 0;
|
||||
case TTM_PL_VRAM:
|
||||
mem->bus.offset = mem->start << PAGE_SHIFT;
|
||||
mem->bus.base = pci_resource_start(mdev->dev->pdev, 0);
|
||||
mem->bus.is_iomem = true;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mgag200_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
|
||||
{
|
||||
}
|
||||
|
||||
static int mgag200_bo_move(struct ttm_buffer_object *bo,
|
||||
bool evict, bool interruptible,
|
||||
bool no_wait_gpu,
|
||||
struct ttm_mem_reg *new_mem)
|
||||
{
|
||||
int r;
|
||||
r = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static void mgag200_ttm_backend_destroy(struct ttm_tt *tt)
|
||||
{
|
||||
ttm_tt_fini(tt);
|
||||
kfree(tt);
|
||||
}
|
||||
|
||||
static struct ttm_backend_func mgag200_tt_backend_func = {
|
||||
.destroy = &mgag200_ttm_backend_destroy,
|
||||
};
|
||||
|
||||
|
||||
static struct ttm_tt *mgag200_ttm_tt_create(struct ttm_bo_device *bdev,
|
||||
unsigned long size, uint32_t page_flags,
|
||||
struct page *dummy_read_page)
|
||||
{
|
||||
struct ttm_tt *tt;
|
||||
|
||||
tt = kzalloc(sizeof(struct ttm_tt), GFP_KERNEL);
|
||||
if (tt == NULL)
|
||||
return NULL;
|
||||
tt->func = &mgag200_tt_backend_func;
|
||||
if (ttm_tt_init(tt, bdev, size, page_flags, dummy_read_page)) {
|
||||
kfree(tt);
|
||||
return NULL;
|
||||
}
|
||||
return tt;
|
||||
}
|
||||
|
||||
static int mgag200_ttm_tt_populate(struct ttm_tt *ttm)
|
||||
{
|
||||
return ttm_pool_populate(ttm);
|
||||
}
|
||||
|
||||
static void mgag200_ttm_tt_unpopulate(struct ttm_tt *ttm)
|
||||
{
|
||||
ttm_pool_unpopulate(ttm);
|
||||
}
|
||||
|
||||
struct ttm_bo_driver mgag200_bo_driver = {
|
||||
.ttm_tt_create = mgag200_ttm_tt_create,
|
||||
.ttm_tt_populate = mgag200_ttm_tt_populate,
|
||||
.ttm_tt_unpopulate = mgag200_ttm_tt_unpopulate,
|
||||
.init_mem_type = mgag200_bo_init_mem_type,
|
||||
.evict_flags = mgag200_bo_evict_flags,
|
||||
.move = mgag200_bo_move,
|
||||
.verify_access = mgag200_bo_verify_access,
|
||||
.io_mem_reserve = &mgag200_ttm_io_mem_reserve,
|
||||
.io_mem_free = &mgag200_ttm_io_mem_free,
|
||||
};
|
||||
|
||||
int mgag200_mm_init(struct mga_device *mdev)
|
||||
{
|
||||
int ret;
|
||||
struct drm_device *dev = mdev->dev;
|
||||
struct ttm_bo_device *bdev = &mdev->ttm.bdev;
|
||||
|
||||
ret = mgag200_ttm_global_init(mdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ttm_bo_device_init(&mdev->ttm.bdev,
|
||||
mdev->ttm.bo_global_ref.ref.object,
|
||||
&mgag200_bo_driver,
|
||||
dev->anon_inode->i_mapping,
|
||||
DRM_FILE_PAGE_OFFSET,
|
||||
true);
|
||||
if (ret) {
|
||||
DRM_ERROR("Error initialising bo driver; %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM, mdev->mc.vram_size >> PAGE_SHIFT);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mdev->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
|
||||
pci_resource_len(dev->pdev, 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mgag200_mm_fini(struct mga_device *mdev)
|
||||
{
|
||||
ttm_bo_device_release(&mdev->ttm.bdev);
|
||||
|
||||
mgag200_ttm_global_release(mdev);
|
||||
|
||||
arch_phys_wc_del(mdev->fb_mtrr);
|
||||
mdev->fb_mtrr = 0;
|
||||
}
|
||||
|
||||
void mgag200_ttm_placement(struct mgag200_bo *bo, int domain)
|
||||
{
|
||||
u32 c = 0;
|
||||
unsigned i;
|
||||
|
||||
bo->placement.placement = bo->placements;
|
||||
bo->placement.busy_placement = bo->placements;
|
||||
if (domain & TTM_PL_FLAG_VRAM)
|
||||
bo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
|
||||
if (domain & TTM_PL_FLAG_SYSTEM)
|
||||
bo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
|
||||
if (!c)
|
||||
bo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
|
||||
bo->placement.num_placement = c;
|
||||
bo->placement.num_busy_placement = c;
|
||||
for (i = 0; i < c; ++i) {
|
||||
bo->placements[i].fpfn = 0;
|
||||
bo->placements[i].lpfn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int mgag200_bo_create(struct drm_device *dev, int size, int align,
|
||||
uint32_t flags, struct mgag200_bo **pmgabo)
|
||||
{
|
||||
struct mga_device *mdev = dev->dev_private;
|
||||
struct mgag200_bo *mgabo;
|
||||
size_t acc_size;
|
||||
int ret;
|
||||
|
||||
mgabo = kzalloc(sizeof(struct mgag200_bo), GFP_KERNEL);
|
||||
if (!mgabo)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = drm_gem_object_init(dev, &mgabo->gem, size);
|
||||
if (ret) {
|
||||
kfree(mgabo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mgabo->bo.bdev = &mdev->ttm.bdev;
|
||||
|
||||
mgag200_ttm_placement(mgabo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
|
||||
|
||||
acc_size = ttm_bo_dma_acc_size(&mdev->ttm.bdev, size,
|
||||
sizeof(struct mgag200_bo));
|
||||
|
||||
ret = ttm_bo_init(&mdev->ttm.bdev, &mgabo->bo, size,
|
||||
ttm_bo_type_device, &mgabo->placement,
|
||||
align >> PAGE_SHIFT, false, NULL, acc_size,
|
||||
NULL, NULL, mgag200_bo_ttm_destroy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*pmgabo = mgabo;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u64 mgag200_bo_gpu_offset(struct mgag200_bo *bo)
|
||||
{
|
||||
return bo->bo.offset;
|
||||
}
|
||||
|
||||
int mgag200_bo_pin(struct mgag200_bo *bo, u32 pl_flag, u64 *gpu_addr)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
if (bo->pin_count) {
|
||||
bo->pin_count++;
|
||||
if (gpu_addr)
|
||||
*gpu_addr = mgag200_bo_gpu_offset(bo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mgag200_ttm_placement(bo, pl_flag);
|
||||
for (i = 0; i < bo->placement.num_placement; i++)
|
||||
bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
|
||||
ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
bo->pin_count = 1;
|
||||
if (gpu_addr)
|
||||
*gpu_addr = mgag200_bo_gpu_offset(bo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mgag200_bo_unpin(struct mgag200_bo *bo)
|
||||
{
|
||||
int i, ret;
|
||||
if (!bo->pin_count) {
|
||||
DRM_ERROR("unpin bad %p\n", bo);
|
||||
return 0;
|
||||
}
|
||||
bo->pin_count--;
|
||||
if (bo->pin_count)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < bo->placement.num_placement ; i++)
|
||||
bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
|
||||
ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mgag200_bo_push_sysram(struct mgag200_bo *bo)
|
||||
{
|
||||
int i, ret;
|
||||
if (!bo->pin_count) {
|
||||
DRM_ERROR("unpin bad %p\n", bo);
|
||||
return 0;
|
||||
}
|
||||
bo->pin_count--;
|
||||
if (bo->pin_count)
|
||||
return 0;
|
||||
|
||||
if (bo->kmap.virtual)
|
||||
ttm_bo_kunmap(&bo->kmap);
|
||||
|
||||
mgag200_ttm_placement(bo, TTM_PL_FLAG_SYSTEM);
|
||||
for (i = 0; i < bo->placement.num_placement ; i++)
|
||||
bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
|
||||
|
||||
ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
|
||||
if (ret) {
|
||||
DRM_ERROR("pushing to VRAM failed\n");
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mgag200_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_file *file_priv;
|
||||
struct mga_device *mdev;
|
||||
|
||||
if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
|
||||
return -EINVAL;
|
||||
|
||||
file_priv = filp->private_data;
|
||||
mdev = file_priv->minor->dev->dev_private;
|
||||
return ttm_bo_mmap(filp, vma, &mdev->ttm.bdev);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue