2 * Copyright 2008 Jérôme Glisse
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 * Jerome Glisse <glisse@freedesktop.org>
27 #include "radeon_ms.h"
30 #define RADEON_DST_Y_X 0x1438
31 #define RADEON_SRC_Y_X 0x1434
32 #define RADEON_DP_CNTL 0x16c0
33 #define RADEON_DP_GUI_MASTER_CNTL 0x146c
34 #define RADEON_DP_BRUSH_BKGD_CLR 0x1478
35 #define RADEON_DP_BRUSH_FRGD_CLR 0x147c
36 #define RADEON_DP_WRITE_MASK 0x16cc
37 #define RADEON_DST_PITCH_OFFSET 0x142c
38 #define RADEON_SRC_PITCH_OFFSET 0x1428
39 #define RADEON_DST_HEIGHT_WIDTH 0x143c
43 /* for 2D operations */
44 uint32_t dp_gui_master_cntl;
47 struct amd_cmd_bo *dst;
52 struct amd_cmd_bo *src;
58 static int check_blit(struct drm_device *dev, struct amd_cmd *cmd)
60 struct legacy_check *legacy_check;
63 legacy_check = (struct legacy_check *)cmd->driver;
64 /* check that gui master cntl have been set */
65 if (legacy_check->dp_gui_master_cntl == 0xffffffff) {
68 switch ((legacy_check->dp_gui_master_cntl >> 8) & 0xf) {
82 /* check that a destination have been set */
83 if (legacy_check->dst == (void *)-1) {
86 if (legacy_check->dst_pitch == 0xffffffff) {
89 if (legacy_check->dst_x == 0xffffffff) {
92 if (legacy_check->dst_y == 0xffffffff) {
95 if (legacy_check->dst_w == 0xffffffff) {
98 if (legacy_check->dst_h == 0xffffffff) {
101 /* compute start offset of blit */
102 start = legacy_check->dst_pitch * legacy_check->dst_y +
103 legacy_check->dst_x * bpp;
104 /* compute end offset of blit */
105 end = legacy_check->dst_pitch * legacy_check->dst_h +
106 legacy_check->dst_w * bpp;
107 /* FIXME: check that end offset is inside dst bo */
109 /* check that a destination have been set */
110 if (legacy_check->dp_gui_master_cntl & 1) {
111 if (legacy_check->src == (void *)-1) {
114 if (legacy_check->src_pitch == 0xffffffff) {
117 if (legacy_check->src_x == 0xffffffff) {
120 if (legacy_check->src_y == 0xffffffff) {
123 /* compute start offset of blit */
124 start = legacy_check->src_pitch * legacy_check->src_y +
125 legacy_check->src_x * bpp;
126 /* compute end offset of blit */
127 end = legacy_check->src_pitch * legacy_check->dst_h +
128 legacy_check->dst_w * bpp + start;
129 /* FIXME: check that end offset is inside src bo */
134 static int p0_dp_gui_master_cntl(struct drm_device *dev,
138 struct legacy_check *legacy_check;
140 legacy_check = (struct legacy_check *)cmd->driver;
141 legacy_check->dp_gui_master_cntl = cmd->cdw[cdw_id];
142 /* we only accept src data type to be same as dst */
143 if (((legacy_check->dp_gui_master_cntl >> 12) & 0x3) != 3) {
149 static int p0_dst_pitch_offset(struct drm_device *dev,
153 struct legacy_check *legacy_check;
157 legacy_check = (struct legacy_check *)cmd->driver;
158 legacy_check->dst_pitch = ((cmd->cdw[cdw_id] >> 22) & 0xff) << 6;
159 tmp = cmd->cdw[cdw_id] & 0x003fffff;
160 legacy_check->dst = amd_cmd_get_bo(cmd, tmp);
161 if (legacy_check->dst == NULL) {
162 DRM_ERROR("invalid bo (%d) for DST_PITCH_OFFSET register.\n",
166 ret = radeon_ms_bo_get_gpu_addr(dev, &legacy_check->dst->bo->mem, &tmp);
168 DRM_ERROR("failed to get GPU offset for bo 0x%x.\n",
169 legacy_check->dst->handle);
173 DRM_ERROR("bo 0x%x offset doesn't meet alignement 0x%x.\n",
174 legacy_check->dst->handle, tmp);
176 cmd->cdw[cdw_id] &= 0xffc00000;
177 cmd->cdw[cdw_id] |= (tmp >> 10);
181 static int p0_src_pitch_offset(struct drm_device *dev,
185 struct legacy_check *legacy_check;
189 legacy_check = (struct legacy_check *)cmd->driver;
190 legacy_check->src_pitch = ((cmd->cdw[cdw_id] >> 22) & 0xff) << 6;
191 tmp = cmd->cdw[cdw_id] & 0x003fffff;
192 legacy_check->src = amd_cmd_get_bo(cmd, tmp);
193 if (legacy_check->src == NULL) {
194 DRM_ERROR("invalid bo (%d) for SRC_PITCH_OFFSET register.\n",
198 ret = radeon_ms_bo_get_gpu_addr(dev, &legacy_check->src->bo->mem, &tmp);
200 DRM_ERROR("failed to get GPU offset for bo 0x%x.\n",
201 legacy_check->src->handle);
205 DRM_ERROR("bo 0x%x offset doesn't meet alignement 0x%x.\n",
206 legacy_check->src->handle, tmp);
208 cmd->cdw[cdw_id] &= 0xffc00000;
209 cmd->cdw[cdw_id] |= (tmp >> 10);
213 static int p0_dst_y_x(struct drm_device *dev,
217 struct legacy_check *legacy_check;
219 legacy_check = (struct legacy_check *)cmd->driver;
220 legacy_check->dst_x = cmd->cdw[cdw_id] & 0xffff;
221 legacy_check->dst_y = (cmd->cdw[cdw_id] >> 16) & 0xffff;
225 static int p0_src_y_x(struct drm_device *dev,
229 struct legacy_check *legacy_check;
231 legacy_check = (struct legacy_check *)cmd->driver;
232 legacy_check->src_x = cmd->cdw[cdw_id] & 0xffff;
233 legacy_check->src_y = (cmd->cdw[cdw_id] >> 16) & 0xffff;
237 static int p0_dst_h_w(struct drm_device *dev,
241 struct legacy_check *legacy_check;
243 legacy_check = (struct legacy_check *)cmd->driver;
244 legacy_check->dst_w = cmd->cdw[cdw_id] & 0xffff;
245 legacy_check->dst_h = (cmd->cdw[cdw_id] >> 16) & 0xffff;
246 return check_blit(dev, cmd);
249 static int legacy_cmd_check(struct drm_device *dev,
252 struct legacy_check legacy_check;
254 memset(&legacy_check, 0xff, sizeof(struct legacy_check));
255 cmd->driver = &legacy_check;
256 return amd_cmd_check(dev, cmd);
259 int amd_legacy_cmd_module_destroy(struct drm_device *dev)
261 struct drm_radeon_private *dev_priv = dev->dev_private;
263 dev_priv->cmd_module.check = NULL;
264 if (dev_priv->cmd_module.numof_p0_checkers) {
265 drm_free(dev_priv->cmd_module.check_p0,
266 dev_priv->cmd_module.numof_p0_checkers *
267 sizeof(void*), DRM_MEM_DRIVER);
268 dev_priv->cmd_module.numof_p0_checkers = 0;
270 if (dev_priv->cmd_module.numof_p3_checkers) {
271 drm_free(dev_priv->cmd_module.check_p3,
272 dev_priv->cmd_module.numof_p3_checkers *
273 sizeof(void*), DRM_MEM_DRIVER);
274 dev_priv->cmd_module.numof_p3_checkers = 0;
279 int amd_legacy_cmd_module_initialize(struct drm_device *dev)
281 struct drm_radeon_private *dev_priv = dev->dev_private;
282 struct amd_cmd_module *checker = &dev_priv->cmd_module;
286 checker->numof_p0_checkers = 0x5000 >> 2;
287 size = checker->numof_p0_checkers * sizeof(void*);
288 checker->check_p0 = drm_alloc(size, DRM_MEM_DRIVER);
289 if (checker->check_p0 == NULL) {
290 amd_legacy_cmd_module_destroy(dev);
293 /* initialize to -1 */
294 memset(checker->check_p0, 0xff, size);
297 checker->numof_p3_checkers = 20;
298 size = checker->numof_p3_checkers * sizeof(void*);
299 checker->check_p3 = drm_alloc(size, DRM_MEM_DRIVER);
300 if (checker->check_p3 == NULL) {
301 amd_legacy_cmd_module_destroy(dev);
304 /* initialize to -1 */
305 memset(checker->check_p3, 0xff, size);
307 /* initialize packet0 checker */
308 checker->check_p0[RADEON_DST_Y_X >> 2] = p0_dst_y_x;
309 checker->check_p0[RADEON_SRC_Y_X >> 2] = p0_src_y_x;
310 checker->check_p0[RADEON_DST_HEIGHT_WIDTH >> 2] = p0_dst_h_w;
311 checker->check_p0[RADEON_DST_PITCH_OFFSET >> 2] = p0_dst_pitch_offset;
312 checker->check_p0[RADEON_SRC_PITCH_OFFSET >> 2] = p0_src_pitch_offset;
313 checker->check_p0[RADEON_DP_GUI_MASTER_CNTL>>2] = p0_dp_gui_master_cntl;
314 checker->check_p0[RADEON_DP_BRUSH_FRGD_CLR >> 2] = NULL;
315 checker->check_p0[RADEON_DP_WRITE_MASK >> 2] = NULL;
316 checker->check_p0[RADEON_DP_CNTL >> 2] = NULL;
318 checker->check = legacy_cmd_check;