Skip to content

Commit 74cfa1e

Browse files
author
Jocelyn Falempe
committed
drm/nouveau/disp: Move tiling functions to dispnv50/tile.h
Refactor, and move the tiling geometry functions to dispnv50/tile.h, so they can be re-used by drm_panic. No functional impact. Signed-off-by: Jocelyn Falempe <[email protected]> Reviewed-by: Lyude Paul <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 0459696 commit 74cfa1e

File tree

2 files changed

+73
-49
lines changed

2 files changed

+73
-49
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/* SPDX-License-Identifier: MIT */
2+
#ifndef __NV50_TILE_H__
3+
#define __NV50_TILE_H__
4+
5+
#include <linux/types.h>
6+
#include <linux/math.h>
7+
8+
/*
9+
* Tiling parameters for NV50+.
10+
* GOB = Group of bytes, the main unit for tiling blocks.
11+
* Tiling blocks are a power of 2 number of GOB.
12+
* All GOBs and blocks have the same width: 64 bytes (so 16 pixels in 32bits).
13+
* tile_mode is the log2 of the number of GOB per block.
14+
*/
15+
16+
#define NV_TILE_GOB_HEIGHT_TESLA 4 /* 4 x 64 bytes = 256 bytes for a GOB on Tesla*/
17+
#define NV_TILE_GOB_HEIGHT 8 /* 8 x 64 bytes = 512 bytes for a GOB on Fermi and later */
18+
#define NV_TILE_GOB_WIDTH_BYTES 64
19+
20+
/* Number of blocks to cover the width of the framebuffer */
21+
static inline u32 nouveau_get_width_in_blocks(u32 stride)
22+
{
23+
return DIV_ROUND_UP(stride, NV_TILE_GOB_WIDTH_BYTES);
24+
}
25+
26+
/* Return the height in pixel of one GOB */
27+
static inline u32 nouveau_get_gob_height(u16 family)
28+
{
29+
if (family == NV_DEVICE_INFO_V0_TESLA)
30+
return NV_TILE_GOB_HEIGHT_TESLA;
31+
else
32+
return NV_TILE_GOB_HEIGHT;
33+
}
34+
35+
/* Number of blocks to cover the heigth of the framebuffer */
36+
static inline u32 nouveau_get_height_in_blocks(u32 height, u32 gobs_in_block, u16 family)
37+
{
38+
return DIV_ROUND_UP(height, nouveau_get_gob_height(family) * gobs_in_block);
39+
}
40+
41+
/* Return the GOB size in bytes */
42+
static inline u32 nouveau_get_gob_size(u16 family)
43+
{
44+
return nouveau_get_gob_height(family) * NV_TILE_GOB_WIDTH_BYTES;
45+
}
46+
47+
/* Return the number of GOB in a block */
48+
static inline int nouveau_get_gobs_in_block(u32 tile_mode, u16 chipset)
49+
{
50+
if (chipset >= 0xc0)
51+
return 1 << (tile_mode >> 4);
52+
return 1 << tile_mode;
53+
}
54+
55+
/* Return true if tile_mode is invalid */
56+
static inline bool nouveau_check_tile_mode(u32 tile_mode, u16 chipset)
57+
{
58+
if (chipset >= 0xc0)
59+
return (tile_mode & 0xfffff0f);
60+
return (tile_mode & 0xfffffff0);
61+
}
62+
63+
#endif

drivers/gpu/drm/nouveau/nouveau_display.c

Lines changed: 10 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include <nvif/if0011.h>
4545
#include <nvif/if0013.h>
4646
#include <dispnv50/crc.h>
47+
#include <dispnv50/tile.h>
4748

4849
int
4950
nouveau_display_vblank_enable(struct drm_crtc *crtc)
@@ -220,69 +221,29 @@ nouveau_validate_decode_mod(struct nouveau_drm *drm,
220221
return 0;
221222
}
222223

223-
static inline uint32_t
224-
nouveau_get_width_in_blocks(uint32_t stride)
225-
{
226-
/* GOBs per block in the x direction is always one, and GOBs are
227-
* 64 bytes wide
228-
*/
229-
static const uint32_t log_block_width = 6;
230-
231-
return (stride + (1 << log_block_width) - 1) >> log_block_width;
232-
}
233-
234-
static inline uint32_t
235-
nouveau_get_height_in_blocks(struct nouveau_drm *drm,
236-
uint32_t height,
237-
uint32_t log_block_height_in_gobs)
238-
{
239-
uint32_t log_gob_height;
240-
uint32_t log_block_height;
241-
242-
BUG_ON(drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA);
243-
244-
if (drm->client.device.info.family < NV_DEVICE_INFO_V0_FERMI)
245-
log_gob_height = 2;
246-
else
247-
log_gob_height = 3;
248-
249-
log_block_height = log_block_height_in_gobs + log_gob_height;
250-
251-
return (height + (1 << log_block_height) - 1) >> log_block_height;
252-
}
253-
254224
static int
255225
nouveau_check_bl_size(struct nouveau_drm *drm, struct nouveau_bo *nvbo,
256226
uint32_t offset, uint32_t stride, uint32_t h,
257227
uint32_t tile_mode)
258228
{
259-
uint32_t gob_size, bw, bh;
229+
uint32_t gob_size, bw, bh, gobs_in_block;
260230
uint64_t bl_size;
261231

262232
BUG_ON(drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA);
263233

264-
if (drm->client.device.info.chipset >= 0xc0) {
265-
if (tile_mode & 0xF)
266-
return -EINVAL;
267-
tile_mode >>= 4;
268-
}
269-
270-
if (tile_mode & 0xFFFFFFF0)
234+
if (nouveau_check_tile_mode(tile_mode, drm->client.device.info.chipset))
271235
return -EINVAL;
272236

273-
if (drm->client.device.info.family < NV_DEVICE_INFO_V0_FERMI)
274-
gob_size = 256;
275-
else
276-
gob_size = 512;
277-
237+
gobs_in_block = nouveau_get_gobs_in_block(tile_mode, drm->client.device.info.chipset);
278238
bw = nouveau_get_width_in_blocks(stride);
279-
bh = nouveau_get_height_in_blocks(drm, h, tile_mode);
239+
bh = nouveau_get_height_in_blocks(h, gobs_in_block, drm->client.device.info.family);
240+
gob_size = nouveau_get_gob_size(drm->client.device.info.family);
280241

281-
bl_size = bw * bh * (1 << tile_mode) * gob_size;
242+
bl_size = bw * bh * gobs_in_block * gob_size;
282243

283-
DRM_DEBUG_KMS("offset=%u stride=%u h=%u tile_mode=0x%02x bw=%u bh=%u gob_size=%u bl_size=%llu size=%zu\n",
284-
offset, stride, h, tile_mode, bw, bh, gob_size, bl_size,
285-
nvbo->bo.base.size);
244+
DRM_DEBUG_KMS("offset=%u stride=%u h=%u gobs_in_block=%u bw=%u bh=%u gob_size=%u bl_size=%llu size=%zu\n",
245+
offset, stride, h, gobs_in_block, bw, bh, gob_size,
246+
bl_size, nvbo->bo.base.size);
286247

287248
if (bl_size + offset > nvbo->bo.base.size)
288249
return -ERANGE;

0 commit comments

Comments
 (0)