aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r600_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/r600_cs.c')
-rw-r--r--drivers/gpu/drm/radeon/r600_cs.c131
1 files changed, 112 insertions, 19 deletions
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index 3dab49cb1d4a..f37676d7f217 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -47,18 +47,23 @@ struct r600_cs_track {
47 u32 npipes; 47 u32 npipes;
48 /* value we track */ 48 /* value we track */
49 u32 sq_config; 49 u32 sq_config;
50 u32 log_nsamples;
50 u32 nsamples; 51 u32 nsamples;
51 u32 cb_color_base_last[8]; 52 u32 cb_color_base_last[8];
52 struct radeon_bo *cb_color_bo[8]; 53 struct radeon_bo *cb_color_bo[8];
53 u64 cb_color_bo_mc[8]; 54 u64 cb_color_bo_mc[8];
54 u32 cb_color_bo_offset[8]; 55 u64 cb_color_bo_offset[8];
55 struct radeon_bo *cb_color_frag_bo[8]; /* unused */ 56 struct radeon_bo *cb_color_frag_bo[8];
56 struct radeon_bo *cb_color_tile_bo[8]; /* unused */ 57 u64 cb_color_frag_offset[8];
58 struct radeon_bo *cb_color_tile_bo[8];
59 u64 cb_color_tile_offset[8];
60 u32 cb_color_mask[8];
57 u32 cb_color_info[8]; 61 u32 cb_color_info[8];
58 u32 cb_color_view[8]; 62 u32 cb_color_view[8];
59 u32 cb_color_size_idx[8]; /* unused */ 63 u32 cb_color_size_idx[8]; /* unused */
60 u32 cb_target_mask; 64 u32 cb_target_mask;
61 u32 cb_shader_mask; /* unused */ 65 u32 cb_shader_mask; /* unused */
66 bool is_resolve;
62 u32 cb_color_size[8]; 67 u32 cb_color_size[8];
63 u32 vgt_strmout_en; 68 u32 vgt_strmout_en;
64 u32 vgt_strmout_buffer_en; 69 u32 vgt_strmout_buffer_en;
@@ -311,7 +316,15 @@ static void r600_cs_track_init(struct r600_cs_track *track)
311 track->cb_color_bo[i] = NULL; 316 track->cb_color_bo[i] = NULL;
312 track->cb_color_bo_offset[i] = 0xFFFFFFFF; 317 track->cb_color_bo_offset[i] = 0xFFFFFFFF;
313 track->cb_color_bo_mc[i] = 0xFFFFFFFF; 318 track->cb_color_bo_mc[i] = 0xFFFFFFFF;
314 } 319 track->cb_color_frag_bo[i] = NULL;
320 track->cb_color_frag_offset[i] = 0xFFFFFFFF;
321 track->cb_color_tile_bo[i] = NULL;
322 track->cb_color_tile_offset[i] = 0xFFFFFFFF;
323 track->cb_color_mask[i] = 0xFFFFFFFF;
324 }
325 track->is_resolve = false;
326 track->nsamples = 16;
327 track->log_nsamples = 4;
315 track->cb_target_mask = 0xFFFFFFFF; 328 track->cb_target_mask = 0xFFFFFFFF;
316 track->cb_shader_mask = 0xFFFFFFFF; 329 track->cb_shader_mask = 0xFFFFFFFF;
317 track->cb_dirty = true; 330 track->cb_dirty = true;
@@ -348,11 +361,9 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
348 volatile u32 *ib = p->ib.ptr; 361 volatile u32 *ib = p->ib.ptr;
349 unsigned array_mode; 362 unsigned array_mode;
350 u32 format; 363 u32 format;
364 /* When resolve is used, the second colorbuffer has always 1 sample. */
365 unsigned nsamples = track->is_resolve && i == 1 ? 1 : track->nsamples;
351 366
352 if (G_0280A0_TILE_MODE(track->cb_color_info[i])) {
353 dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n");
354 return -EINVAL;
355 }
356 size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i]; 367 size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i];
357 format = G_0280A0_FORMAT(track->cb_color_info[i]); 368 format = G_0280A0_FORMAT(track->cb_color_info[i]);
358 if (!r600_fmt_is_valid_color(format)) { 369 if (!r600_fmt_is_valid_color(format)) {
@@ -375,7 +386,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
375 array_check.group_size = track->group_size; 386 array_check.group_size = track->group_size;
376 array_check.nbanks = track->nbanks; 387 array_check.nbanks = track->nbanks;
377 array_check.npipes = track->npipes; 388 array_check.npipes = track->npipes;
378 array_check.nsamples = track->nsamples; 389 array_check.nsamples = nsamples;
379 array_check.blocksize = r600_fmt_get_blocksize(format); 390 array_check.blocksize = r600_fmt_get_blocksize(format);
380 if (r600_get_array_mode_alignment(&array_check, 391 if (r600_get_array_mode_alignment(&array_check,
381 &pitch_align, &height_align, &depth_align, &base_align)) { 392 &pitch_align, &height_align, &depth_align, &base_align)) {
@@ -420,7 +431,8 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
420 } 431 }
421 432
422 /* check offset */ 433 /* check offset */
423 tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) * r600_fmt_get_blocksize(format); 434 tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) *
435 r600_fmt_get_blocksize(format) * nsamples;
424 switch (array_mode) { 436 switch (array_mode) {
425 default: 437 default:
426 case V_0280A0_ARRAY_LINEAR_GENERAL: 438 case V_0280A0_ARRAY_LINEAR_GENERAL:
@@ -441,7 +453,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
441 * broken userspace. 453 * broken userspace.
442 */ 454 */
443 } else { 455 } else {
444 dev_warn(p->dev, "%s offset[%d] %d %d %d %lu too big (%d %d) (%d %d %d)\n", 456 dev_warn(p->dev, "%s offset[%d] %d %llu %d %lu too big (%d %d) (%d %d %d)\n",
445 __func__, i, array_mode, 457 __func__, i, array_mode,
446 track->cb_color_bo_offset[i], tmp, 458 track->cb_color_bo_offset[i], tmp,
447 radeon_bo_size(track->cb_color_bo[i]), 459 radeon_bo_size(track->cb_color_bo[i]),
@@ -458,6 +470,51 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
458 tmp = S_028060_PITCH_TILE_MAX((pitch / 8) - 1) | 470 tmp = S_028060_PITCH_TILE_MAX((pitch / 8) - 1) |
459 S_028060_SLICE_TILE_MAX(slice_tile_max - 1); 471 S_028060_SLICE_TILE_MAX(slice_tile_max - 1);
460 ib[track->cb_color_size_idx[i]] = tmp; 472 ib[track->cb_color_size_idx[i]] = tmp;
473
474 /* FMASK/CMASK */
475 switch (G_0280A0_TILE_MODE(track->cb_color_info[i])) {
476 case V_0280A0_TILE_DISABLE:
477 break;
478 case V_0280A0_FRAG_ENABLE:
479 if (track->nsamples > 1) {
480 uint32_t tile_max = G_028100_FMASK_TILE_MAX(track->cb_color_mask[i]);
481 /* the tile size is 8x8, but the size is in units of bits.
482 * for bytes, do just * 8. */
483 uint32_t bytes = track->nsamples * track->log_nsamples * 8 * (tile_max + 1);
484
485 if (bytes + track->cb_color_frag_offset[i] >
486 radeon_bo_size(track->cb_color_frag_bo[i])) {
487 dev_warn(p->dev, "%s FMASK_TILE_MAX too large "
488 "(tile_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n",
489 __func__, tile_max, bytes,
490 track->cb_color_frag_offset[i],
491 radeon_bo_size(track->cb_color_frag_bo[i]));
492 return -EINVAL;
493 }
494 }
495 /* fall through */
496 case V_0280A0_CLEAR_ENABLE:
497 {
498 uint32_t block_max = G_028100_CMASK_BLOCK_MAX(track->cb_color_mask[i]);
499 /* One block = 128x128 pixels, one 8x8 tile has 4 bits..
500 * (128*128) / (8*8) / 2 = 128 bytes per block. */
501 uint32_t bytes = (block_max + 1) * 128;
502
503 if (bytes + track->cb_color_tile_offset[i] >
504 radeon_bo_size(track->cb_color_tile_bo[i])) {
505 dev_warn(p->dev, "%s CMASK_BLOCK_MAX too large "
506 "(block_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n",
507 __func__, block_max, bytes,
508 track->cb_color_tile_offset[i],
509 radeon_bo_size(track->cb_color_tile_bo[i]));
510 return -EINVAL;
511 }
512 break;
513 }
514 default:
515 dev_warn(p->dev, "%s invalid tile mode\n", __func__);
516 return -EINVAL;
517 }
461 return 0; 518 return 0;
462} 519}
463 520
@@ -566,7 +623,7 @@ static int r600_cs_track_validate_db(struct radeon_cs_parser *p)
566 623
567 ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1; 624 ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
568 nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1; 625 nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
569 tmp = ntiles * bpe * 64 * nviews; 626 tmp = ntiles * bpe * 64 * nviews * track->nsamples;
570 if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) { 627 if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
571 dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n", 628 dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n",
572 array_mode, 629 array_mode,
@@ -746,6 +803,12 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
746 */ 803 */
747 if (track->cb_dirty) { 804 if (track->cb_dirty) {
748 tmp = track->cb_target_mask; 805 tmp = track->cb_target_mask;
806
807 /* We must check both colorbuffers for RESOLVE. */
808 if (track->is_resolve) {
809 tmp |= 0xff;
810 }
811
749 for (i = 0; i < 8; i++) { 812 for (i = 0; i < 8; i++) {
750 if ((tmp >> (i * 4)) & 0xF) { 813 if ((tmp >> (i * 4)) & 0xF) {
751 /* at least one component is enabled */ 814 /* at least one component is enabled */
@@ -1231,9 +1294,15 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
1231 break; 1294 break;
1232 case R_028C04_PA_SC_AA_CONFIG: 1295 case R_028C04_PA_SC_AA_CONFIG:
1233 tmp = G_028C04_MSAA_NUM_SAMPLES(radeon_get_ib_value(p, idx)); 1296 tmp = G_028C04_MSAA_NUM_SAMPLES(radeon_get_ib_value(p, idx));
1297 track->log_nsamples = tmp;
1234 track->nsamples = 1 << tmp; 1298 track->nsamples = 1 << tmp;
1235 track->cb_dirty = true; 1299 track->cb_dirty = true;
1236 break; 1300 break;
1301 case R_028808_CB_COLOR_CONTROL:
1302 tmp = G_028808_SPECIAL_OP(radeon_get_ib_value(p, idx));
1303 track->is_resolve = tmp == V_028808_SPECIAL_RESOLVE_BOX;
1304 track->cb_dirty = true;
1305 break;
1237 case R_0280A0_CB_COLOR0_INFO: 1306 case R_0280A0_CB_COLOR0_INFO:
1238 case R_0280A4_CB_COLOR1_INFO: 1307 case R_0280A4_CB_COLOR1_INFO:
1239 case R_0280A8_CB_COLOR2_INFO: 1308 case R_0280A8_CB_COLOR2_INFO:
@@ -1312,16 +1381,21 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
1312 dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg); 1381 dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
1313 return -EINVAL; 1382 return -EINVAL;
1314 } 1383 }
1315 ib[idx] = track->cb_color_base_last[tmp];
1316 track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp]; 1384 track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp];
1385 track->cb_color_frag_offset[tmp] = track->cb_color_bo_offset[tmp];
1386 ib[idx] = track->cb_color_base_last[tmp];
1317 } else { 1387 } else {
1318 r = r600_cs_packet_next_reloc(p, &reloc); 1388 r = r600_cs_packet_next_reloc(p, &reloc);
1319 if (r) { 1389 if (r) {
1320 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); 1390 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
1321 return -EINVAL; 1391 return -EINVAL;
1322 } 1392 }
1323 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1324 track->cb_color_frag_bo[tmp] = reloc->robj; 1393 track->cb_color_frag_bo[tmp] = reloc->robj;
1394 track->cb_color_frag_offset[tmp] = (u64)ib[idx] << 8;
1395 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1396 }
1397 if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
1398 track->cb_dirty = true;
1325 } 1399 }
1326 break; 1400 break;
1327 case R_0280C0_CB_COLOR0_TILE: 1401 case R_0280C0_CB_COLOR0_TILE:
@@ -1338,16 +1412,35 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
1338 dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg); 1412 dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
1339 return -EINVAL; 1413 return -EINVAL;
1340 } 1414 }
1341 ib[idx] = track->cb_color_base_last[tmp];
1342 track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp]; 1415 track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp];
1416 track->cb_color_tile_offset[tmp] = track->cb_color_bo_offset[tmp];
1417 ib[idx] = track->cb_color_base_last[tmp];
1343 } else { 1418 } else {
1344 r = r600_cs_packet_next_reloc(p, &reloc); 1419 r = r600_cs_packet_next_reloc(p, &reloc);
1345 if (r) { 1420 if (r) {
1346 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); 1421 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
1347 return -EINVAL; 1422 return -EINVAL;
1348 } 1423 }
1349 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1350 track->cb_color_tile_bo[tmp] = reloc->robj; 1424 track->cb_color_tile_bo[tmp] = reloc->robj;
1425 track->cb_color_tile_offset[tmp] = (u64)ib[idx] << 8;
1426 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1427 }
1428 if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
1429 track->cb_dirty = true;
1430 }
1431 break;
1432 case R_028100_CB_COLOR0_MASK:
1433 case R_028104_CB_COLOR1_MASK:
1434 case R_028108_CB_COLOR2_MASK:
1435 case R_02810C_CB_COLOR3_MASK:
1436 case R_028110_CB_COLOR4_MASK:
1437 case R_028114_CB_COLOR5_MASK:
1438 case R_028118_CB_COLOR6_MASK:
1439 case R_02811C_CB_COLOR7_MASK:
1440 tmp = (reg - R_028100_CB_COLOR0_MASK) / 4;
1441 track->cb_color_mask[tmp] = radeon_get_ib_value(p, idx);
1442 if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
1443 track->cb_dirty = true;
1351 } 1444 }
1352 break; 1445 break;
1353 case CB_COLOR0_BASE: 1446 case CB_COLOR0_BASE:
@@ -1492,7 +1585,7 @@ unsigned r600_mip_minify(unsigned size, unsigned level)
1492} 1585}
1493 1586
1494static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel, 1587static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel,
1495 unsigned w0, unsigned h0, unsigned d0, unsigned format, 1588 unsigned w0, unsigned h0, unsigned d0, unsigned nsamples, unsigned format,
1496 unsigned block_align, unsigned height_align, unsigned base_align, 1589 unsigned block_align, unsigned height_align, unsigned base_align,
1497 unsigned *l0_size, unsigned *mipmap_size) 1590 unsigned *l0_size, unsigned *mipmap_size)
1498{ 1591{
@@ -1520,7 +1613,7 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel,
1520 1613
1521 depth = r600_mip_minify(d0, i); 1614 depth = r600_mip_minify(d0, i);
1522 1615
1523 size = nbx * nby * blocksize; 1616 size = nbx * nby * blocksize * nsamples;
1524 if (nfaces) 1617 if (nfaces)
1525 size *= nfaces; 1618 size *= nfaces;
1526 else 1619 else
@@ -1672,7 +1765,7 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx,
1672 1765
1673 nfaces = larray - barray + 1; 1766 nfaces = larray - barray + 1;
1674 } 1767 }
1675 r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, format, 1768 r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, array_check.nsamples, format,
1676 pitch_align, height_align, base_align, 1769 pitch_align, height_align, base_align,
1677 &l0_size, &mipmap_size); 1770 &l0_size, &mipmap_size);
1678 /* using get ib will give us the offset into the texture bo */ 1771 /* using get ib will give us the offset into the texture bo */