2 * Copyright (C) 2008 Maarten Maathuis.
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #include "nv50_cursor.h"
28 #include "nv50_crtc.h"
29 #include "nv50_display.h"
31 static int nv50_cursor_enable(struct nv50_crtc *crtc)
33 struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
37 NV_WRITE(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(crtc->index), 0x2000);
38 while(NV_READ(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(crtc->index)) & NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_MASK);
40 NV_WRITE(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(crtc->index), NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_ON);
41 while((NV_READ(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(crtc->index)) & NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_MASK)
42 != NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE);
44 crtc->cursor->enabled = true;
49 static int nv50_cursor_disable(struct nv50_crtc *crtc)
51 struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
55 NV_WRITE(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(crtc->index), 0);
56 while(NV_READ(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(crtc->index)) & NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_MASK);
58 crtc->cursor->enabled = false;
63 /* Calling update or changing the stored cursor state is left to the higher level ioctl's. */
64 static int nv50_cursor_show(struct nv50_crtc *crtc)
66 struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
67 uint32_t offset = crtc->index * 0x400;
71 /* Better not show the cursor when we have none. */
72 /* TODO: is cursor offset actually set? */
73 if (!crtc->cursor->block) {
74 DRM_ERROR("No cursor available on crtc %d\n", crtc->index);
78 OUT_MODE(NV50_CRTC0_CURSOR_CTRL + offset, NV50_CRTC0_CURSOR_CTRL_SHOW);
83 static int nv50_cursor_hide(struct nv50_crtc *crtc)
85 struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
86 uint32_t offset = crtc->index * 0x400;
90 OUT_MODE(NV50_CRTC0_CURSOR_CTRL + offset, NV50_CRTC0_CURSOR_CTRL_HIDE);
95 static int nv50_cursor_set_pos(struct nv50_crtc *crtc, int x, int y)
97 struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
99 NV_WRITE(NV50_HW_CURSOR_POS(crtc->index), ((y & 0xFFFF) << 16) | (x & 0xFFFF));
100 /* Needed to make the cursor move. */
101 NV_WRITE(NV50_HW_CURSOR_POS_CTRL(crtc->index), 0);
106 static int nv50_cursor_set_offset(struct nv50_crtc *crtc)
108 struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
112 if (crtc->cursor->block) {
113 OUT_MODE(NV50_CRTC0_CURSOR_OFFSET + crtc->index * 0x400, crtc->cursor->block->start >> 8);
115 OUT_MODE(NV50_CRTC0_CURSOR_OFFSET + crtc->index * 0x400, 0);
121 static int nv50_cursor_set_bo(struct nv50_crtc *crtc, drm_handle_t handle)
123 struct mem_block *block = NULL;
124 struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
128 block = find_block_by_handle(dev_priv->fb_heap, handle);
131 bool first_time = false;
132 if (!crtc->cursor->block)
135 crtc->cursor->block = block;
137 /* set the cursor offset cursor */
139 crtc->cursor->set_offset(crtc);
140 if (crtc->cursor->visible)
141 crtc->cursor->show(crtc);
144 DRM_ERROR("Unable to find cursor bo with handle 0x%X\n", handle);
151 int nv50_cursor_create(struct nv50_crtc *crtc)
158 crtc->cursor = kzalloc(sizeof(struct nv50_cursor), GFP_KERNEL);
162 /* function pointers */
163 crtc->cursor->show = nv50_cursor_show;
164 crtc->cursor->hide = nv50_cursor_hide;
165 crtc->cursor->set_pos = nv50_cursor_set_pos;
166 crtc->cursor->set_offset = nv50_cursor_set_offset;
167 crtc->cursor->set_bo = nv50_cursor_set_bo;
168 crtc->cursor->enable = nv50_cursor_enable;
169 crtc->cursor->disable = nv50_cursor_disable;
174 int nv50_cursor_destroy(struct nv50_crtc *crtc)
183 if (crtc->cursor->enabled) {
184 rval = crtc->cursor->disable(crtc);