diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r600_cs.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r600_cs.c | 232 |
1 files changed, 187 insertions, 45 deletions
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 144c32d37136..c3ea212e0c3c 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c | |||
@@ -25,6 +25,7 @@ | |||
25 | * Alex Deucher | 25 | * Alex Deucher |
26 | * Jerome Glisse | 26 | * Jerome Glisse |
27 | */ | 27 | */ |
28 | #include <linux/kernel.h> | ||
28 | #include "drmP.h" | 29 | #include "drmP.h" |
29 | #include "radeon.h" | 30 | #include "radeon.h" |
30 | #include "r600d.h" | 31 | #include "r600d.h" |
@@ -166,7 +167,7 @@ static void r600_cs_track_init(struct r600_cs_track *track) | |||
166 | static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) | 167 | static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) |
167 | { | 168 | { |
168 | struct r600_cs_track *track = p->track; | 169 | struct r600_cs_track *track = p->track; |
169 | u32 bpe = 0, pitch, slice_tile_max, size, tmp, height; | 170 | u32 bpe = 0, pitch, slice_tile_max, size, tmp, height, pitch_align; |
170 | volatile u32 *ib = p->ib->ptr; | 171 | volatile u32 *ib = p->ib->ptr; |
171 | 172 | ||
172 | if (G_0280A0_TILE_MODE(track->cb_color_info[i])) { | 173 | if (G_0280A0_TILE_MODE(track->cb_color_info[i])) { |
@@ -180,56 +181,57 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) | |||
180 | i, track->cb_color_info[i]); | 181 | i, track->cb_color_info[i]); |
181 | return -EINVAL; | 182 | return -EINVAL; |
182 | } | 183 | } |
183 | pitch = (G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1) << 3; | 184 | /* pitch is the number of 8x8 tiles per row */ |
185 | pitch = G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1; | ||
184 | slice_tile_max = G_028060_SLICE_TILE_MAX(track->cb_color_size[i]) + 1; | 186 | slice_tile_max = G_028060_SLICE_TILE_MAX(track->cb_color_size[i]) + 1; |
185 | if (!pitch) { | 187 | height = size / (pitch * 8 * bpe); |
186 | dev_warn(p->dev, "%s:%d cb pitch (%d) for %d invalid (0x%08X)\n", | ||
187 | __func__, __LINE__, pitch, i, track->cb_color_size[i]); | ||
188 | return -EINVAL; | ||
189 | } | ||
190 | height = size / (pitch * bpe); | ||
191 | if (height > 8192) | 188 | if (height > 8192) |
192 | height = 8192; | 189 | height = 8192; |
190 | if (height > 7) | ||
191 | height &= ~0x7; | ||
193 | switch (G_0280A0_ARRAY_MODE(track->cb_color_info[i])) { | 192 | switch (G_0280A0_ARRAY_MODE(track->cb_color_info[i])) { |
194 | case V_0280A0_ARRAY_LINEAR_GENERAL: | 193 | case V_0280A0_ARRAY_LINEAR_GENERAL: |
194 | /* technically height & 0x7 */ | ||
195 | break; | ||
195 | case V_0280A0_ARRAY_LINEAR_ALIGNED: | 196 | case V_0280A0_ARRAY_LINEAR_ALIGNED: |
196 | if (pitch & 0x3f) { | 197 | pitch_align = max((u32)64, (u32)(track->group_size / bpe)) / 8; |
197 | dev_warn(p->dev, "%s:%d cb pitch (%d x %d = %d) invalid\n", | 198 | if (!IS_ALIGNED(pitch, pitch_align)) { |
198 | __func__, __LINE__, pitch, bpe, pitch * bpe); | 199 | dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n", |
200 | __func__, __LINE__, pitch); | ||
199 | return -EINVAL; | 201 | return -EINVAL; |
200 | } | 202 | } |
201 | if ((pitch * bpe) & (track->group_size - 1)) { | 203 | if (!IS_ALIGNED(height, 8)) { |
202 | dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n", | 204 | dev_warn(p->dev, "%s:%d cb height (%d) invalid\n", |
203 | __func__, __LINE__, pitch); | 205 | __func__, __LINE__, height); |
204 | return -EINVAL; | 206 | return -EINVAL; |
205 | } | 207 | } |
206 | break; | 208 | break; |
207 | case V_0280A0_ARRAY_1D_TILED_THIN1: | 209 | case V_0280A0_ARRAY_1D_TILED_THIN1: |
208 | if ((pitch * 8 * bpe * track->nsamples) & (track->group_size - 1)) { | 210 | pitch_align = max((u32)8, (u32)(track->group_size / (8 * bpe * track->nsamples))) / 8; |
211 | if (!IS_ALIGNED(pitch, pitch_align)) { | ||
209 | dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n", | 212 | dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n", |
210 | __func__, __LINE__, pitch); | 213 | __func__, __LINE__, pitch); |
214 | return -EINVAL; | ||
215 | } | ||
216 | if (!IS_ALIGNED(height, 8)) { | ||
217 | dev_warn(p->dev, "%s:%d cb height (%d) invalid\n", | ||
218 | __func__, __LINE__, height); | ||
211 | return -EINVAL; | 219 | return -EINVAL; |
212 | } | 220 | } |
213 | height &= ~0x7; | ||
214 | if (!height) | ||
215 | height = 8; | ||
216 | break; | 221 | break; |
217 | case V_0280A0_ARRAY_2D_TILED_THIN1: | 222 | case V_0280A0_ARRAY_2D_TILED_THIN1: |
218 | if (pitch & ((8 * track->nbanks) - 1)) { | 223 | pitch_align = max((u32)track->nbanks, |
224 | (u32)(((track->group_size / 8) / (bpe * track->nsamples)) * track->nbanks)); | ||
225 | if (!IS_ALIGNED(pitch, pitch_align)) { | ||
219 | dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n", | 226 | dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n", |
220 | __func__, __LINE__, pitch); | 227 | __func__, __LINE__, pitch); |
221 | return -EINVAL; | 228 | return -EINVAL; |
222 | } | 229 | } |
223 | tmp = pitch * 8 * bpe * track->nsamples; | 230 | if (!IS_ALIGNED((height / 8), track->nbanks)) { |
224 | tmp = tmp / track->nbanks; | 231 | dev_warn(p->dev, "%s:%d cb height (%d) invalid\n", |
225 | if (tmp & (track->group_size - 1)) { | 232 | __func__, __LINE__, height); |
226 | dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n", | ||
227 | __func__, __LINE__, pitch); | ||
228 | return -EINVAL; | 233 | return -EINVAL; |
229 | } | 234 | } |
230 | height &= ~((16 * track->npipes) - 1); | ||
231 | if (!height) | ||
232 | height = 16 * track->npipes; | ||
233 | break; | 235 | break; |
234 | default: | 236 | default: |
235 | dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__, | 237 | dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__, |
@@ -238,16 +240,20 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) | |||
238 | return -EINVAL; | 240 | return -EINVAL; |
239 | } | 241 | } |
240 | /* check offset */ | 242 | /* check offset */ |
241 | tmp = height * pitch; | 243 | tmp = height * pitch * 8 * bpe; |
242 | if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) { | 244 | if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) { |
243 | dev_warn(p->dev, "%s offset[%d] %d to big\n", __func__, i, track->cb_color_bo_offset[i]); | 245 | dev_warn(p->dev, "%s offset[%d] %d too big\n", __func__, i, track->cb_color_bo_offset[i]); |
246 | return -EINVAL; | ||
247 | } | ||
248 | if (!IS_ALIGNED(track->cb_color_bo_offset[i], track->group_size)) { | ||
249 | dev_warn(p->dev, "%s offset[%d] %d not aligned\n", __func__, i, track->cb_color_bo_offset[i]); | ||
244 | return -EINVAL; | 250 | return -EINVAL; |
245 | } | 251 | } |
246 | /* limit max tile */ | 252 | /* limit max tile */ |
247 | tmp = (height * pitch) >> 6; | 253 | tmp = (height * pitch * 8) >> 6; |
248 | if (tmp < slice_tile_max) | 254 | if (tmp < slice_tile_max) |
249 | slice_tile_max = tmp; | 255 | slice_tile_max = tmp; |
250 | tmp = S_028060_PITCH_TILE_MAX((pitch >> 3) - 1) | | 256 | tmp = S_028060_PITCH_TILE_MAX(pitch - 1) | |
251 | S_028060_SLICE_TILE_MAX(slice_tile_max - 1); | 257 | S_028060_SLICE_TILE_MAX(slice_tile_max - 1); |
252 | ib[track->cb_color_size_idx[i]] = tmp; | 258 | ib[track->cb_color_size_idx[i]] = tmp; |
253 | return 0; | 259 | return 0; |
@@ -289,7 +295,7 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) | |||
289 | /* Check depth buffer */ | 295 | /* Check depth buffer */ |
290 | if (G_028800_STENCIL_ENABLE(track->db_depth_control) || | 296 | if (G_028800_STENCIL_ENABLE(track->db_depth_control) || |
291 | G_028800_Z_ENABLE(track->db_depth_control)) { | 297 | G_028800_Z_ENABLE(track->db_depth_control)) { |
292 | u32 nviews, bpe, ntiles; | 298 | u32 nviews, bpe, ntiles, pitch, pitch_align, height, size; |
293 | if (track->db_bo == NULL) { | 299 | if (track->db_bo == NULL) { |
294 | dev_warn(p->dev, "z/stencil with no depth buffer\n"); | 300 | dev_warn(p->dev, "z/stencil with no depth buffer\n"); |
295 | return -EINVAL; | 301 | return -EINVAL; |
@@ -332,6 +338,51 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) | |||
332 | } | 338 | } |
333 | ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF); | 339 | ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF); |
334 | } else { | 340 | } else { |
341 | size = radeon_bo_size(track->db_bo); | ||
342 | pitch = G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1; | ||
343 | height = size / (pitch * 8 * bpe); | ||
344 | height &= ~0x7; | ||
345 | if (!height) | ||
346 | height = 8; | ||
347 | |||
348 | switch (G_028010_ARRAY_MODE(track->db_depth_info)) { | ||
349 | case V_028010_ARRAY_1D_TILED_THIN1: | ||
350 | pitch_align = (max((u32)8, (u32)(track->group_size / (8 * bpe))) / 8); | ||
351 | if (!IS_ALIGNED(pitch, pitch_align)) { | ||
352 | dev_warn(p->dev, "%s:%d db pitch (%d) invalid\n", | ||
353 | __func__, __LINE__, pitch); | ||
354 | return -EINVAL; | ||
355 | } | ||
356 | if (!IS_ALIGNED(height, 8)) { | ||
357 | dev_warn(p->dev, "%s:%d db height (%d) invalid\n", | ||
358 | __func__, __LINE__, height); | ||
359 | return -EINVAL; | ||
360 | } | ||
361 | break; | ||
362 | case V_028010_ARRAY_2D_TILED_THIN1: | ||
363 | pitch_align = max((u32)track->nbanks, | ||
364 | (u32)(((track->group_size / 8) / bpe) * track->nbanks)); | ||
365 | if (!IS_ALIGNED(pitch, pitch_align)) { | ||
366 | dev_warn(p->dev, "%s:%d db pitch (%d) invalid\n", | ||
367 | __func__, __LINE__, pitch); | ||
368 | return -EINVAL; | ||
369 | } | ||
370 | if ((height / 8) & (track->nbanks - 1)) { | ||
371 | dev_warn(p->dev, "%s:%d db height (%d) invalid\n", | ||
372 | __func__, __LINE__, height); | ||
373 | return -EINVAL; | ||
374 | } | ||
375 | break; | ||
376 | default: | ||
377 | dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__, | ||
378 | G_028010_ARRAY_MODE(track->db_depth_info), | ||
379 | track->db_depth_info); | ||
380 | return -EINVAL; | ||
381 | } | ||
382 | if (!IS_ALIGNED(track->db_offset, track->group_size)) { | ||
383 | dev_warn(p->dev, "%s offset[%d] %d not aligned\n", __func__, i, track->db_offset); | ||
384 | return -EINVAL; | ||
385 | } | ||
335 | ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1; | 386 | ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1; |
336 | nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1; | 387 | nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1; |
337 | tmp = ntiles * bpe * 64 * nviews; | 388 | tmp = ntiles * bpe * 64 * nviews; |
@@ -724,7 +775,25 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx | |||
724 | track->db_depth_control = radeon_get_ib_value(p, idx); | 775 | track->db_depth_control = radeon_get_ib_value(p, idx); |
725 | break; | 776 | break; |
726 | case R_028010_DB_DEPTH_INFO: | 777 | case R_028010_DB_DEPTH_INFO: |
727 | track->db_depth_info = radeon_get_ib_value(p, idx); | 778 | if (r600_cs_packet_next_is_pkt3_nop(p)) { |
779 | r = r600_cs_packet_next_reloc(p, &reloc); | ||
780 | if (r) { | ||
781 | dev_warn(p->dev, "bad SET_CONTEXT_REG " | ||
782 | "0x%04X\n", reg); | ||
783 | return -EINVAL; | ||
784 | } | ||
785 | track->db_depth_info = radeon_get_ib_value(p, idx); | ||
786 | ib[idx] &= C_028010_ARRAY_MODE; | ||
787 | track->db_depth_info &= C_028010_ARRAY_MODE; | ||
788 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { | ||
789 | ib[idx] |= S_028010_ARRAY_MODE(V_028010_ARRAY_2D_TILED_THIN1); | ||
790 | track->db_depth_info |= S_028010_ARRAY_MODE(V_028010_ARRAY_2D_TILED_THIN1); | ||
791 | } else { | ||
792 | ib[idx] |= S_028010_ARRAY_MODE(V_028010_ARRAY_1D_TILED_THIN1); | ||
793 | track->db_depth_info |= S_028010_ARRAY_MODE(V_028010_ARRAY_1D_TILED_THIN1); | ||
794 | } | ||
795 | } else | ||
796 | track->db_depth_info = radeon_get_ib_value(p, idx); | ||
728 | break; | 797 | break; |
729 | case R_028004_DB_DEPTH_VIEW: | 798 | case R_028004_DB_DEPTH_VIEW: |
730 | track->db_depth_view = radeon_get_ib_value(p, idx); | 799 | track->db_depth_view = radeon_get_ib_value(p, idx); |
@@ -757,8 +826,25 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx | |||
757 | case R_0280B4_CB_COLOR5_INFO: | 826 | case R_0280B4_CB_COLOR5_INFO: |
758 | case R_0280B8_CB_COLOR6_INFO: | 827 | case R_0280B8_CB_COLOR6_INFO: |
759 | case R_0280BC_CB_COLOR7_INFO: | 828 | case R_0280BC_CB_COLOR7_INFO: |
760 | tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4; | 829 | if (r600_cs_packet_next_is_pkt3_nop(p)) { |
761 | track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); | 830 | r = r600_cs_packet_next_reloc(p, &reloc); |
831 | if (r) { | ||
832 | dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); | ||
833 | return -EINVAL; | ||
834 | } | ||
835 | tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4; | ||
836 | track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); | ||
837 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { | ||
838 | ib[idx] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_2D_TILED_THIN1); | ||
839 | track->cb_color_info[tmp] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_2D_TILED_THIN1); | ||
840 | } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { | ||
841 | ib[idx] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_1D_TILED_THIN1); | ||
842 | track->cb_color_info[tmp] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_1D_TILED_THIN1); | ||
843 | } | ||
844 | } else { | ||
845 | tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4; | ||
846 | track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); | ||
847 | } | ||
762 | break; | 848 | break; |
763 | case R_028060_CB_COLOR0_SIZE: | 849 | case R_028060_CB_COLOR0_SIZE: |
764 | case R_028064_CB_COLOR1_SIZE: | 850 | case R_028064_CB_COLOR1_SIZE: |
@@ -946,8 +1032,9 @@ static inline unsigned minify(unsigned size, unsigned levels) | |||
946 | } | 1032 | } |
947 | 1033 | ||
948 | static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels, | 1034 | static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels, |
949 | unsigned w0, unsigned h0, unsigned d0, unsigned bpe, | 1035 | unsigned w0, unsigned h0, unsigned d0, unsigned bpe, |
950 | unsigned *l0_size, unsigned *mipmap_size) | 1036 | unsigned pitch_align, |
1037 | unsigned *l0_size, unsigned *mipmap_size) | ||
951 | { | 1038 | { |
952 | unsigned offset, i, level, face; | 1039 | unsigned offset, i, level, face; |
953 | unsigned width, height, depth, rowstride, size; | 1040 | unsigned width, height, depth, rowstride, size; |
@@ -960,13 +1047,13 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels | |||
960 | height = minify(h0, i); | 1047 | height = minify(h0, i); |
961 | depth = minify(d0, i); | 1048 | depth = minify(d0, i); |
962 | for(face = 0; face < nfaces; face++) { | 1049 | for(face = 0; face < nfaces; face++) { |
963 | rowstride = ((width * bpe) + 255) & ~255; | 1050 | rowstride = ALIGN((width * bpe), pitch_align); |
964 | size = height * rowstride * depth; | 1051 | size = height * rowstride * depth; |
965 | offset += size; | 1052 | offset += size; |
966 | offset = (offset + 0x1f) & ~0x1f; | 1053 | offset = (offset + 0x1f) & ~0x1f; |
967 | } | 1054 | } |
968 | } | 1055 | } |
969 | *l0_size = (((w0 * bpe) + 255) & ~255) * h0 * d0; | 1056 | *l0_size = ALIGN((w0 * bpe), pitch_align) * h0 * d0; |
970 | *mipmap_size = offset; | 1057 | *mipmap_size = offset; |
971 | if (!blevel) | 1058 | if (!blevel) |
972 | *mipmap_size -= *l0_size; | 1059 | *mipmap_size -= *l0_size; |
@@ -985,16 +1072,23 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels | |||
985 | * the texture and mipmap bo object are big enough to cover this resource. | 1072 | * the texture and mipmap bo object are big enough to cover this resource. |
986 | */ | 1073 | */ |
987 | static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, | 1074 | static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, |
988 | struct radeon_bo *texture, | 1075 | struct radeon_bo *texture, |
989 | struct radeon_bo *mipmap) | 1076 | struct radeon_bo *mipmap, |
1077 | u32 tiling_flags) | ||
990 | { | 1078 | { |
1079 | struct r600_cs_track *track = p->track; | ||
991 | u32 nfaces, nlevels, blevel, w0, h0, d0, bpe = 0; | 1080 | u32 nfaces, nlevels, blevel, w0, h0, d0, bpe = 0; |
992 | u32 word0, word1, l0_size, mipmap_size; | 1081 | u32 word0, word1, l0_size, mipmap_size, pitch, pitch_align; |
993 | 1082 | ||
994 | /* on legacy kernel we don't perform advanced check */ | 1083 | /* on legacy kernel we don't perform advanced check */ |
995 | if (p->rdev == NULL) | 1084 | if (p->rdev == NULL) |
996 | return 0; | 1085 | return 0; |
1086 | |||
997 | word0 = radeon_get_ib_value(p, idx + 0); | 1087 | word0 = radeon_get_ib_value(p, idx + 0); |
1088 | if (tiling_flags & RADEON_TILING_MACRO) | ||
1089 | word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); | ||
1090 | else if (tiling_flags & RADEON_TILING_MICRO) | ||
1091 | word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1); | ||
998 | word1 = radeon_get_ib_value(p, idx + 1); | 1092 | word1 = radeon_get_ib_value(p, idx + 1); |
999 | w0 = G_038000_TEX_WIDTH(word0) + 1; | 1093 | w0 = G_038000_TEX_WIDTH(word0) + 1; |
1000 | h0 = G_038004_TEX_HEIGHT(word1) + 1; | 1094 | h0 = G_038004_TEX_HEIGHT(word1) + 1; |
@@ -1021,11 +1115,55 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i | |||
1021 | __func__, __LINE__, G_038004_DATA_FORMAT(word1)); | 1115 | __func__, __LINE__, G_038004_DATA_FORMAT(word1)); |
1022 | return -EINVAL; | 1116 | return -EINVAL; |
1023 | } | 1117 | } |
1118 | |||
1119 | pitch = G_038000_PITCH(word0) + 1; | ||
1120 | switch (G_038000_TILE_MODE(word0)) { | ||
1121 | case V_038000_ARRAY_LINEAR_GENERAL: | ||
1122 | pitch_align = 1; | ||
1123 | /* XXX check height align */ | ||
1124 | break; | ||
1125 | case V_038000_ARRAY_LINEAR_ALIGNED: | ||
1126 | pitch_align = max((u32)64, (u32)(track->group_size / bpe)) / 8; | ||
1127 | if (!IS_ALIGNED(pitch, pitch_align)) { | ||
1128 | dev_warn(p->dev, "%s:%d tex pitch (%d) invalid\n", | ||
1129 | __func__, __LINE__, pitch); | ||
1130 | return -EINVAL; | ||
1131 | } | ||
1132 | /* XXX check height align */ | ||
1133 | break; | ||
1134 | case V_038000_ARRAY_1D_TILED_THIN1: | ||
1135 | pitch_align = max((u32)8, (u32)(track->group_size / (8 * bpe))) / 8; | ||
1136 | if (!IS_ALIGNED(pitch, pitch_align)) { | ||
1137 | dev_warn(p->dev, "%s:%d tex pitch (%d) invalid\n", | ||
1138 | __func__, __LINE__, pitch); | ||
1139 | return -EINVAL; | ||
1140 | } | ||
1141 | /* XXX check height align */ | ||
1142 | break; | ||
1143 | case V_038000_ARRAY_2D_TILED_THIN1: | ||
1144 | pitch_align = max((u32)track->nbanks, | ||
1145 | (u32)(((track->group_size / 8) / bpe) * track->nbanks)); | ||
1146 | if (!IS_ALIGNED(pitch, pitch_align)) { | ||
1147 | dev_warn(p->dev, "%s:%d tex pitch (%d) invalid\n", | ||
1148 | __func__, __LINE__, pitch); | ||
1149 | return -EINVAL; | ||
1150 | } | ||
1151 | /* XXX check height align */ | ||
1152 | break; | ||
1153 | default: | ||
1154 | dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__, | ||
1155 | G_038000_TILE_MODE(word0), word0); | ||
1156 | return -EINVAL; | ||
1157 | } | ||
1158 | /* XXX check offset align */ | ||
1159 | |||
1024 | word0 = radeon_get_ib_value(p, idx + 4); | 1160 | word0 = radeon_get_ib_value(p, idx + 4); |
1025 | word1 = radeon_get_ib_value(p, idx + 5); | 1161 | word1 = radeon_get_ib_value(p, idx + 5); |
1026 | blevel = G_038010_BASE_LEVEL(word0); | 1162 | blevel = G_038010_BASE_LEVEL(word0); |
1027 | nlevels = G_038014_LAST_LEVEL(word1); | 1163 | nlevels = G_038014_LAST_LEVEL(word1); |
1028 | r600_texture_size(nfaces, blevel, nlevels, w0, h0, d0, bpe, &l0_size, &mipmap_size); | 1164 | r600_texture_size(nfaces, blevel, nlevels, w0, h0, d0, bpe, |
1165 | (pitch_align * bpe), | ||
1166 | &l0_size, &mipmap_size); | ||
1029 | /* using get ib will give us the offset into the texture bo */ | 1167 | /* using get ib will give us the offset into the texture bo */ |
1030 | word0 = radeon_get_ib_value(p, idx + 2); | 1168 | word0 = radeon_get_ib_value(p, idx + 2); |
1031 | if ((l0_size + word0) > radeon_bo_size(texture)) { | 1169 | if ((l0_size + word0) > radeon_bo_size(texture)) { |
@@ -1239,6 +1377,10 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
1239 | return -EINVAL; | 1377 | return -EINVAL; |
1240 | } | 1378 | } |
1241 | ib[idx+1+(i*7)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); | 1379 | ib[idx+1+(i*7)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); |
1380 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) | ||
1381 | ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); | ||
1382 | else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) | ||
1383 | ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1); | ||
1242 | texture = reloc->robj; | 1384 | texture = reloc->robj; |
1243 | /* tex mip base */ | 1385 | /* tex mip base */ |
1244 | r = r600_cs_packet_next_reloc(p, &reloc); | 1386 | r = r600_cs_packet_next_reloc(p, &reloc); |
@@ -1249,7 +1391,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
1249 | ib[idx+1+(i*7)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); | 1391 | ib[idx+1+(i*7)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); |
1250 | mipmap = reloc->robj; | 1392 | mipmap = reloc->robj; |
1251 | r = r600_check_texture_resource(p, idx+(i*7)+1, | 1393 | r = r600_check_texture_resource(p, idx+(i*7)+1, |
1252 | texture, mipmap); | 1394 | texture, mipmap, reloc->lobj.tiling_flags); |
1253 | if (r) | 1395 | if (r) |
1254 | return r; | 1396 | return r; |
1255 | break; | 1397 | break; |