Skip to content

Commit 047b8e2

Browse files
committed
Merge tag 'drm-misc-next-2017-06-19_0' of git://anongit.freedesktop.org/git/drm-misc into drm-next
UAPI Changes: - vc4: Add get/set tiling format ioctls (Eric) Driver Changes: - vc4: Add tiling T-format support for scanout (Eric) - vc4: Use atomic helpers in commit (Boris) Cc: Boris Brezillon <[email protected]> Cc: Eric Anholt <[email protected]> * tag 'drm-misc-next-2017-06-19_0' of git://anongit.freedesktop.org/git/drm-misc: drm/vc4: Mimic drm_atomic_helper_commit() behavior drm/vc4: Add get/set tiling ioctls. drm/vc4: Add T-format scanout support.
2 parents 296923e + 34c8ea4 commit 047b8e2

File tree

8 files changed

+227
-32
lines changed

8 files changed

+227
-32
lines changed

drivers/gpu/drm/vc4/vc4_bo.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ void vc4_free_object(struct drm_gem_object *gem_bo)
343343
bo->validated_shader = NULL;
344344
}
345345

346+
bo->t_format = false;
346347
bo->free_time = jiffies;
347348
list_add(&bo->size_head, cache_list);
348349
list_add(&bo->unref_head, &vc4->bo_cache.time_list);
@@ -568,6 +569,88 @@ vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data,
568569
return ret;
569570
}
570571

572+
/**
573+
* vc4_set_tiling_ioctl() - Sets the tiling modifier for a BO.
574+
* @dev: DRM device
575+
* @data: ioctl argument
576+
* @file_priv: DRM file for this fd
577+
*
578+
* The tiling state of the BO decides the default modifier of an fb if
579+
* no specific modifier was set by userspace, and the return value of
580+
* vc4_get_tiling_ioctl() (so that userspace can treat a BO it
581+
* received from dmabuf as the same tiling format as the producer
582+
* used).
583+
*/
584+
int vc4_set_tiling_ioctl(struct drm_device *dev, void *data,
585+
struct drm_file *file_priv)
586+
{
587+
struct drm_vc4_set_tiling *args = data;
588+
struct drm_gem_object *gem_obj;
589+
struct vc4_bo *bo;
590+
bool t_format;
591+
592+
if (args->flags != 0)
593+
return -EINVAL;
594+
595+
switch (args->modifier) {
596+
case DRM_FORMAT_MOD_NONE:
597+
t_format = false;
598+
break;
599+
case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
600+
t_format = true;
601+
break;
602+
default:
603+
return -EINVAL;
604+
}
605+
606+
gem_obj = drm_gem_object_lookup(file_priv, args->handle);
607+
if (!gem_obj) {
608+
DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
609+
return -ENOENT;
610+
}
611+
bo = to_vc4_bo(gem_obj);
612+
bo->t_format = t_format;
613+
614+
drm_gem_object_unreference_unlocked(gem_obj);
615+
616+
return 0;
617+
}
618+
619+
/**
620+
* vc4_get_tiling_ioctl() - Gets the tiling modifier for a BO.
621+
* @dev: DRM device
622+
* @data: ioctl argument
623+
* @file_priv: DRM file for this fd
624+
*
625+
* Returns the tiling modifier for a BO as set by vc4_set_tiling_ioctl().
626+
*/
627+
int vc4_get_tiling_ioctl(struct drm_device *dev, void *data,
628+
struct drm_file *file_priv)
629+
{
630+
struct drm_vc4_get_tiling *args = data;
631+
struct drm_gem_object *gem_obj;
632+
struct vc4_bo *bo;
633+
634+
if (args->flags != 0 || args->modifier != 0)
635+
return -EINVAL;
636+
637+
gem_obj = drm_gem_object_lookup(file_priv, args->handle);
638+
if (!gem_obj) {
639+
DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
640+
return -ENOENT;
641+
}
642+
bo = to_vc4_bo(gem_obj);
643+
644+
if (bo->t_format)
645+
args->modifier = DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED;
646+
else
647+
args->modifier = DRM_FORMAT_MOD_NONE;
648+
649+
drm_gem_object_unreference_unlocked(gem_obj);
650+
651+
return 0;
652+
}
653+
571654
void vc4_bo_cache_init(struct drm_device *dev)
572655
{
573656
struct vc4_dev *vc4 = to_vc4_dev(dev);

drivers/gpu/drm/vc4/vc4_drv.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ static const struct drm_ioctl_desc vc4_drm_ioctls[] = {
138138
DRM_IOCTL_DEF_DRV(VC4_GET_HANG_STATE, vc4_get_hang_state_ioctl,
139139
DRM_ROOT_ONLY),
140140
DRM_IOCTL_DEF_DRV(VC4_GET_PARAM, vc4_get_param_ioctl, DRM_RENDER_ALLOW),
141+
DRM_IOCTL_DEF_DRV(VC4_SET_TILING, vc4_set_tiling_ioctl, DRM_RENDER_ALLOW),
142+
DRM_IOCTL_DEF_DRV(VC4_GET_TILING, vc4_get_tiling_ioctl, DRM_RENDER_ALLOW),
141143
};
142144

143145
static struct drm_driver vc4_drm_driver = {

drivers/gpu/drm/vc4/vc4_drv.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ struct vc4_bo {
148148
*/
149149
uint64_t write_seqno;
150150

151+
bool t_format;
152+
151153
/* List entry for the BO's position in either
152154
* vc4_exec_info->unref_list or vc4_dev->bo_cache.time_list
153155
*/
@@ -470,6 +472,10 @@ int vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data,
470472
struct drm_file *file_priv);
471473
int vc4_mmap_bo_ioctl(struct drm_device *dev, void *data,
472474
struct drm_file *file_priv);
475+
int vc4_set_tiling_ioctl(struct drm_device *dev, void *data,
476+
struct drm_file *file_priv);
477+
int vc4_get_tiling_ioctl(struct drm_device *dev, void *data,
478+
struct drm_file *file_priv);
473479
int vc4_get_hang_state_ioctl(struct drm_device *dev, void *data,
474480
struct drm_file *file_priv);
475481
int vc4_mmap(struct file *filp, struct vm_area_struct *vma);

drivers/gpu/drm/vc4/vc4_kms.c

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ vc4_atomic_complete_commit(struct vc4_commit *c)
4242
struct drm_device *dev = state->dev;
4343
struct vc4_dev *vc4 = to_vc4_dev(dev);
4444

45+
drm_atomic_helper_wait_for_fences(dev, state, false);
46+
47+
drm_atomic_helper_wait_for_dependencies(state);
48+
4549
drm_atomic_helper_commit_modeset_disables(dev, state);
4650

4751
drm_atomic_helper_commit_planes(dev, state, 0);
@@ -57,10 +61,14 @@ vc4_atomic_complete_commit(struct vc4_commit *c)
5761
*/
5862
state->legacy_cursor_update = false;
5963

64+
drm_atomic_helper_commit_hw_done(state);
65+
6066
drm_atomic_helper_wait_for_vblanks(dev, state);
6167

6268
drm_atomic_helper_cleanup_planes(dev, state);
6369

70+
drm_atomic_helper_commit_cleanup_done(state);
71+
6472
drm_atomic_state_put(state);
6573

6674
up(&vc4->async_modeset);
@@ -117,32 +125,10 @@ static int vc4_atomic_commit(struct drm_device *dev,
117125
if (!c)
118126
return -ENOMEM;
119127

120-
/* Make sure that any outstanding modesets have finished. */
121-
if (nonblock) {
122-
struct drm_crtc *crtc;
123-
struct drm_crtc_state *crtc_state;
124-
unsigned long flags;
125-
bool busy = false;
126-
127-
/*
128-
* If there's an undispatched event to send then we're
129-
* obviously still busy. If there isn't, then we can
130-
* unconditionally wait for the semaphore because it
131-
* shouldn't be contended (for long).
132-
*
133-
* This is to prevent a race where queuing a new flip
134-
* from userspace immediately on receipt of an event
135-
* beats our clean-up and returns EBUSY.
136-
*/
137-
spin_lock_irqsave(&dev->event_lock, flags);
138-
for_each_crtc_in_state(state, crtc, crtc_state, i)
139-
busy |= vc4_event_pending(crtc);
140-
spin_unlock_irqrestore(&dev->event_lock, flags);
141-
if (busy) {
142-
kfree(c);
143-
return -EBUSY;
144-
}
145-
}
128+
ret = drm_atomic_helper_setup_commit(state, nonblock);
129+
if (ret)
130+
return ret;
131+
146132
ret = down_interruptible(&vc4->async_modeset);
147133
if (ret) {
148134
kfree(c);
@@ -202,11 +188,50 @@ static int vc4_atomic_commit(struct drm_device *dev,
202188
return 0;
203189
}
204190

191+
static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev,
192+
struct drm_file *file_priv,
193+
const struct drm_mode_fb_cmd2 *mode_cmd)
194+
{
195+
struct drm_mode_fb_cmd2 mode_cmd_local;
196+
197+
/* If the user didn't specify a modifier, use the
198+
* vc4_set_tiling_ioctl() state for the BO.
199+
*/
200+
if (!(mode_cmd->flags & DRM_MODE_FB_MODIFIERS)) {
201+
struct drm_gem_object *gem_obj;
202+
struct vc4_bo *bo;
203+
204+
gem_obj = drm_gem_object_lookup(file_priv,
205+
mode_cmd->handles[0]);
206+
if (!gem_obj) {
207+
DRM_ERROR("Failed to look up GEM BO %d\n",
208+
mode_cmd->handles[0]);
209+
return ERR_PTR(-ENOENT);
210+
}
211+
bo = to_vc4_bo(gem_obj);
212+
213+
mode_cmd_local = *mode_cmd;
214+
215+
if (bo->t_format) {
216+
mode_cmd_local.modifier[0] =
217+
DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED;
218+
} else {
219+
mode_cmd_local.modifier[0] = DRM_FORMAT_MOD_NONE;
220+
}
221+
222+
drm_gem_object_unreference_unlocked(gem_obj);
223+
224+
mode_cmd = &mode_cmd_local;
225+
}
226+
227+
return drm_fb_cma_create(dev, file_priv, mode_cmd);
228+
}
229+
205230
static const struct drm_mode_config_funcs vc4_mode_funcs = {
206231
.output_poll_changed = vc4_output_poll_changed,
207232
.atomic_check = drm_atomic_helper_check,
208233
.atomic_commit = vc4_atomic_commit,
209-
.fb_create = drm_fb_cma_create,
234+
.fb_create = vc4_fb_create,
210235
};
211236

212237
int vc4_kms_load(struct drm_device *dev)

drivers/gpu/drm/vc4/vc4_plane.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -500,8 +500,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
500500
u32 ctl0_offset = vc4_state->dlist_count;
501501
const struct hvs_format *format = vc4_get_hvs_format(fb->format->format);
502502
int num_planes = drm_format_num_planes(format->drm);
503-
u32 scl0, scl1;
504-
u32 lbm_size;
503+
u32 scl0, scl1, pitch0;
504+
u32 lbm_size, tiling;
505505
unsigned long irqflags;
506506
int ret, i;
507507

@@ -542,11 +542,31 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
542542
scl1 = vc4_get_scl_field(state, 0);
543543
}
544544

545+
switch (fb->modifier) {
546+
case DRM_FORMAT_MOD_LINEAR:
547+
tiling = SCALER_CTL0_TILING_LINEAR;
548+
pitch0 = VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH);
549+
break;
550+
case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
551+
tiling = SCALER_CTL0_TILING_256B_OR_T;
552+
553+
pitch0 = (VC4_SET_FIELD(0, SCALER_PITCH0_TILE_Y_OFFSET),
554+
VC4_SET_FIELD(0, SCALER_PITCH0_TILE_WIDTH_L),
555+
VC4_SET_FIELD((vc4_state->src_w[0] + 31) >> 5,
556+
SCALER_PITCH0_TILE_WIDTH_R));
557+
break;
558+
default:
559+
DRM_DEBUG_KMS("Unsupported FB tiling flag 0x%16llx",
560+
(long long)fb->modifier);
561+
return -EINVAL;
562+
}
563+
545564
/* Control word */
546565
vc4_dlist_write(vc4_state,
547566
SCALER_CTL0_VALID |
548567
(format->pixel_order << SCALER_CTL0_ORDER_SHIFT) |
549568
(format->hvs << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
569+
VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) |
550570
(vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) |
551571
VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) |
552572
VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1));
@@ -600,8 +620,11 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
600620
for (i = 0; i < num_planes; i++)
601621
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
602622

603-
/* Pitch word 0/1/2 */
604-
for (i = 0; i < num_planes; i++) {
623+
/* Pitch word 0 */
624+
vc4_dlist_write(vc4_state, pitch0);
625+
626+
/* Pitch word 1/2 */
627+
for (i = 1; i < num_planes; i++) {
605628
vc4_dlist_write(vc4_state,
606629
VC4_SET_FIELD(fb->pitches[i], SCALER_SRC_PITCH));
607630
}

drivers/gpu/drm/vc4/vc4_regs.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,13 @@ enum hvs_pixel_format {
709709
#define SCALER_CTL0_SIZE_MASK VC4_MASK(29, 24)
710710
#define SCALER_CTL0_SIZE_SHIFT 24
711711

712+
#define SCALER_CTL0_TILING_MASK VC4_MASK(21, 20)
713+
#define SCALER_CTL0_TILING_SHIFT 20
714+
#define SCALER_CTL0_TILING_LINEAR 0
715+
#define SCALER_CTL0_TILING_64B 1
716+
#define SCALER_CTL0_TILING_128B 2
717+
#define SCALER_CTL0_TILING_256B_OR_T 3
718+
712719
#define SCALER_CTL0_HFLIP BIT(16)
713720
#define SCALER_CTL0_VFLIP BIT(15)
714721

@@ -838,7 +845,19 @@ enum hvs_pixel_format {
838845
#define SCALER_PPF_KERNEL_OFFSET_SHIFT 0
839846
#define SCALER_PPF_KERNEL_UNCACHED BIT(31)
840847

848+
/* PITCH0/1/2 fields for raster. */
841849
#define SCALER_SRC_PITCH_MASK VC4_MASK(15, 0)
842850
#define SCALER_SRC_PITCH_SHIFT 0
843851

852+
/* PITCH0 fields for T-tiled. */
853+
#define SCALER_PITCH0_TILE_WIDTH_L_MASK VC4_MASK(22, 16)
854+
#define SCALER_PITCH0_TILE_WIDTH_L_SHIFT 16
855+
#define SCALER_PITCH0_TILE_LINE_DIR BIT(15)
856+
#define SCALER_PITCH0_TILE_INITIAL_LINE_DIR BIT(14)
857+
/* Y offset within a tile. */
858+
#define SCALER_PITCH0_TILE_Y_OFFSET_MASK VC4_MASK(13, 7)
859+
#define SCALER_PITCH0_TILE_Y_OFFSET_SHIFT 7
860+
#define SCALER_PITCH0_TILE_WIDTH_R_MASK VC4_MASK(6, 0)
861+
#define SCALER_PITCH0_TILE_WIDTH_R_SHIFT 0
862+
844863
#endif /* VC4_REGS_H */

include/uapi/drm/drm_fourcc.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ extern "C" {
182182
#define DRM_FORMAT_MOD_VENDOR_SAMSUNG 0x04
183183
#define DRM_FORMAT_MOD_VENDOR_QCOM 0x05
184184
#define DRM_FORMAT_MOD_VENDOR_VIVANTE 0x06
185+
#define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07
185186
/* add more to the end as needed */
186187

187188
#define fourcc_mod_code(vendor, val) \
@@ -306,7 +307,6 @@ extern "C" {
306307
*/
307308
#define DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED fourcc_mod_code(VIVANTE, 4)
308309

309-
310310
/* NVIDIA Tegra frame buffer modifiers */
311311

312312
/*
@@ -351,6 +351,27 @@ extern "C" {
351351
*/
352352
#define NV_FORMAT_MOD_TEGRA_16BX2_BLOCK(v) fourcc_mod_tegra_code(2, v)
353353

354+
/*
355+
* Broadcom VC4 "T" format
356+
*
357+
* This is the primary layout that the V3D GPU can texture from (it
358+
* can't do linear). The T format has:
359+
*
360+
* - 64b utiles of pixels in a raster-order grid according to cpp. It's 4x4
361+
* pixels at 32 bit depth.
362+
*
363+
* - 1k subtiles made of a 4x4 raster-order grid of 64b utiles (so usually
364+
* 16x16 pixels).
365+
*
366+
* - 4k tiles made of a 2x2 grid of 1k subtiles (so usually 32x32 pixels). On
367+
* even 4k tile rows, they're arranged as (BL, TL, TR, BR), and on odd rows
368+
* they're (TR, BR, BL, TL), where bottom left is start of memory.
369+
*
370+
* - an image made of 4k tiles in rows either left-to-right (even rows of 4k
371+
* tiles) or right-to-left (odd rows of 4k tiles).
372+
*/
373+
#define DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED fourcc_mod_code(BROADCOM, 1)
374+
354375
#if defined(__cplusplus)
355376
}
356377
#endif

0 commit comments

Comments
 (0)