summaryrefslogtreecommitdiff
path: root/linux-core/nv_drv.c
blob: a6afb0244a6954ef99db2e8bfec3675ca547d0f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/* nv_drv.c -- nv driver -*- linux-c -*-
 * Created: Thu Oct  7 10:38:32 1999 by faith@precisioninsight.com
 *
 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
 * Copyright 2005 Lars Knoll <lars@trolltech.com>
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS AND/OR THEIR 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.
 *
 * Authors:
 *    Rickard E. (Rik) Faith <faith@valinux.com>
 *    Daryll Strauss <daryll@valinux.com>
 *    Gareth Hughes <gareth@valinux.com>
 *    Lars Knoll <lars@trolltech.com>
 */

#include <linux/config.h>
#include "drmP.h"
#include "nv_drv.h"

#include "drm_pciids.h"

static struct pci_device_id pciidlist[] = {
	nv_PCI_IDS
};

static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static struct drm_driver driver = {
	.driver_features = DRIVER_USE_MTRR | DRIVER_USE_AGP,
	.reclaim_buffers = drm_core_reclaim_buffers,
	.get_map_ofs = drm_core_get_map_ofs,
	.get_reg_ofs = drm_core_get_reg_ofs,
	.fops = {
		.owner = THIS_MODULE,
		.open = drm_open,
		.release = drm_release,
		.ioctl = drm_ioctl,
		.mmap = drm_mmap,
		.poll = drm_poll,
		.fasync = drm_fasync,
		},
	.pci_driver = {
		.name = DRIVER_NAME,
		.id_table = pciidlist,
		.probe = probe,
		.remove = __devexit_p(drm_cleanup_pci),
	},
	.name = DRIVER_NAME,
	.desc = DRIVER_DESC,
	.date = DRIVER_DATE,
	.major = DRIVER_MAJOR,
	.minor = DRIVER_MINOR,
	.patchlevel = DRIVER_PATCHLEVEL,
};

static int probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	return drm_get_dev(pdev, ent, &driver);
}


static int __init nv_init(void)
{
	return drm_init(&driver, pciidlist);
}

static void __exit nv_exit(void)
{
	drm_exit(&driver);
}

module_init(nv_init);
module_exit(nv_exit);

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL and additional rights");
dev->dev_private; NV50_DEBUG("\n"); NV_WRITE(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(crtc->index), 0); while(NV_READ(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(crtc->index)) & NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_MASK); crtc->cursor->enabled = false; return 0; } /* Calling update or changing the stored cursor state is left to the higher level ioctl's. */ static int nv50_cursor_show(struct nv50_crtc *crtc) { struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; uint32_t offset = crtc->index * 0x400; NV50_DEBUG("\n"); /* Better not show the cursor when we have none. */ /* TODO: is cursor offset actually set? */ if (!crtc->cursor->block) { DRM_ERROR("No cursor available on crtc %d\n", crtc->index); return -EINVAL; } OUT_MODE(NV50_CRTC0_CURSOR_CTRL + offset, NV50_CRTC0_CURSOR_CTRL_SHOW); return 0; } static int nv50_cursor_hide(struct nv50_crtc *crtc) { struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; uint32_t offset = crtc->index * 0x400; NV50_DEBUG("\n"); OUT_MODE(NV50_CRTC0_CURSOR_CTRL + offset, NV50_CRTC0_CURSOR_CTRL_HIDE); return 0; } static int nv50_cursor_set_pos(struct nv50_crtc *crtc, int x, int y) { struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; NV_WRITE(NV50_HW_CURSOR_POS(crtc->index), ((y & 0xFFFF) << 16) | (x & 0xFFFF)); /* Needed to make the cursor move. */ NV_WRITE(NV50_HW_CURSOR_POS_CTRL(crtc->index), 0); return 0; } static int nv50_cursor_set_offset(struct nv50_crtc *crtc) { struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; NV50_DEBUG("\n"); if (crtc->cursor->block) { OUT_MODE(NV50_CRTC0_CURSOR_OFFSET + crtc->index * 0x400, crtc->cursor->block->start >> 8); } else { OUT_MODE(NV50_CRTC0_CURSOR_OFFSET + crtc->index * 0x400, 0); } return 0; } static int nv50_cursor_set_bo(struct nv50_crtc *crtc, drm_handle_t handle) { struct mem_block *block = NULL; struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; NV50_DEBUG("\n"); block = find_block_by_handle(dev_priv->fb_heap, handle); if (block) { bool first_time = false; if (!crtc->cursor->block) first_time = true; crtc->cursor->block = block; /* set the cursor offset cursor */ if (first_time) { crtc->cursor->set_offset(crtc); if (crtc->cursor->visible) crtc->cursor->show(crtc); } } else { DRM_ERROR("Unable to find cursor bo with handle 0x%X\n", handle); return -EINVAL; } return 0; } int nv50_cursor_create(struct nv50_crtc *crtc) { NV50_DEBUG("\n"); if (!crtc) return -EINVAL; crtc->cursor = kzalloc(sizeof(struct nv50_cursor), GFP_KERNEL); if (!crtc->cursor) return -ENOMEM; /* function pointers */ crtc->cursor->show = nv50_cursor_show; crtc->cursor->hide = nv50_cursor_hide; crtc->cursor->set_pos = nv50_cursor_set_pos; crtc->cursor->set_offset = nv50_cursor_set_offset; crtc->cursor->set_bo = nv50_cursor_set_bo; crtc->cursor->enable = nv50_cursor_enable; crtc->cursor->disable = nv50_cursor_disable; return 0; } int nv50_cursor_destroy(struct nv50_crtc *crtc) { int rval = 0; NV50_DEBUG("\n"); if (!crtc) return -EINVAL; if (crtc->cursor->enabled) { rval = crtc->cursor->disable(crtc); if (rval != 0) return rval; } kfree(crtc->cursor); crtc->cursor = NULL; return 0; }