diff options
Diffstat (limited to 'drivers/gpu/drm/vc4/vc4_drv.h')
| -rw-r--r-- | drivers/gpu/drm/vc4/vc4_drv.h | 786 |
1 files changed, 647 insertions, 139 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index df22698d62ee..221d8e01d539 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -1,27 +1,103 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2015 Broadcom - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ - -#include <linux/reservation.h> -#include <drm/drmP.h> +#ifndef _VC4_DRV_H_ +#define _VC4_DRV_H_ + +#include <linux/debugfs.h> +#include <linux/delay.h> +#include <linux/of.h> +#include <linux/refcount.h> +#include <linux/uaccess.h> + +#include <drm/drm_atomic.h> +#include <drm/drm_debugfs.h> +#include <drm/drm_device.h> #include <drm/drm_encoder.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_gem_dma_helper.h> +#include <drm/drm_managed.h> +#include <drm/drm_mm.h> +#include <drm/drm_modeset_lock.h> + +#include <kunit/test-bug.h> + +#include "uapi/drm/vc4_drm.h" + +struct drm_device; +struct drm_gem_object; + +extern const struct drm_driver vc4_drm_driver; +extern const struct drm_driver vc5_drm_driver; + +/* Don't forget to update vc4_bo.c: bo_type_names[] when adding to + * this. + */ +enum vc4_kernel_bo_type { + /* Any kernel allocation (gem_create_object hook) before it + * gets another type set. + */ + VC4_BO_TYPE_KERNEL, + VC4_BO_TYPE_V3D, + VC4_BO_TYPE_V3D_SHADER, + VC4_BO_TYPE_DUMB, + VC4_BO_TYPE_BIN, + VC4_BO_TYPE_RCL, + VC4_BO_TYPE_BCL, + VC4_BO_TYPE_KERNEL_CACHE, + VC4_BO_TYPE_COUNT +}; + +/* Performance monitor object. The perform lifetime is controlled by userspace + * using perfmon related ioctls. A perfmon can be attached to a submit_cl + * request, and when this is the case, HW perf counters will be activated just + * before the submit_cl is submitted to the GPU and disabled when the job is + * done. This way, only events related to a specific job will be counted. + */ +struct vc4_perfmon { + struct vc4_dev *dev; + + /* Tracks the number of users of the perfmon, when this counter reaches + * zero the perfmon is destroyed. + */ + refcount_t refcnt; + + /* Number of counters activated in this perfmon instance + * (should be less than DRM_VC4_MAX_PERF_COUNTERS). + */ + u8 ncounters; + + /* Events counted by the HW perf counters. */ + u8 events[DRM_VC4_MAX_PERF_COUNTERS]; + + /* Storage for counter values. Counters are incremented by the HW + * perf counter values every time the perfmon is attached to a GPU job. + * This way, perfmon users don't have to retrieve the results after + * each job if they want to track events covering several submissions. + * Note that counter values can't be reset, but you can fake a reset by + * destroying the perfmon and creating a new one. + */ + u64 counters[] __counted_by(ncounters); +}; + +enum vc4_gen { + VC4_GEN_4, + VC4_GEN_5, + VC4_GEN_6_C, + VC4_GEN_6_D, +}; struct vc4_dev { - struct drm_device *dev; + struct drm_device base; + struct device *dev; + + enum vc4_gen gen; + + unsigned int irq; - struct vc4_hdmi *hdmi; struct vc4_hvs *hvs; struct vc4_v3d *v3d; - struct vc4_dpi *dpi; - struct vc4_dsi *dsi1; - struct vc4_vec *vec; - - struct drm_fbdev_cma *fbdev; struct vc4_hang_state *hang_state; @@ -46,16 +122,29 @@ struct vc4_dev { struct timer_list time_timer; } bo_cache; - struct vc4_bo_stats { + u32 num_labels; + struct vc4_label { + const char *name; u32 num_allocated; u32 size_allocated; - u32 num_cached; - u32 size_cached; - } bo_stats; + } *bo_labels; - /* Protects bo_cache and the BO stats. */ + /* Protects bo_cache and bo_labels. */ struct mutex bo_lock; + /* Purgeable BO pool. All BOs in this pool can have their memory + * reclaimed if the driver is unable to allocate new BOs. We also + * keep stats related to the purge mechanism here. + */ + struct { + struct list_head list; + unsigned int num; + size_t size; + unsigned int purged_num; + size_t purged_size; + struct mutex lock; + } purgeable; + uint64_t dma_fence_context; /* Sequence number for the last job queued in bin_job_list. @@ -92,10 +181,10 @@ struct vc4_dev { wait_queue_head_t job_wait_queue; struct work_struct job_done_work; - /* List of struct vc4_seqno_cb for callbacks to be made from a - * workqueue when the given seqno is passed. + /* Used to track the active perfmon if any. Access to this field is + * protected by job_lock. */ - struct list_head seqno_cb_list; + struct vc4_perfmon *active_perfmon; /* The memory used for storing binner tile alloc, tile state, * and overflow memory allocations. This is freed when V3D @@ -114,10 +203,20 @@ struct vc4_dev { /* Bitmask of the current bin_alloc used for overflow memory. */ uint32_t bin_alloc_overflow; + /* Incremented when an underrun error happened after an atomic commit. + * This is particularly useful to detect when a specific modeset is too + * demanding in term of memory or HVS bandwidth which is hard to guess + * at atomic check time. + */ + atomic_t underrun; + struct work_struct overflow_mem_work; int power_refcount; + /* Set to true when the load tracker is active. */ + bool load_tracker_enabled; + /* Mutex controlling the power refcount. */ struct mutex power_lock; @@ -126,27 +225,22 @@ struct vc4_dev { struct work_struct reset_work; } hangcheck; - struct semaphore async_modeset; + struct drm_modeset_lock ctm_state_lock; + struct drm_private_obj ctm_manager; + struct drm_private_obj hvs_channels; + struct drm_private_obj load_tracker; + + /* Mutex for binner bo allocation. */ + struct mutex bin_bo_lock; + /* Reference count for our binner bo. */ + struct kref bin_bo_kref; }; -static inline struct vc4_dev * -to_vc4_dev(struct drm_device *dev) -{ - return (struct vc4_dev *)dev->dev_private; -} +#define to_vc4_dev(_dev) \ + container_of_const(_dev, struct vc4_dev, base) struct vc4_bo { - struct drm_gem_cma_object base; - - /* seqno of the last job to render using this BO. */ - uint64_t seqno; - - /* seqno of the last job to use the RCL to write to this BO. - * - * Note that this doesn't include binner overflow memory - * writes. - */ - uint64_t write_seqno; + struct drm_gem_dma_object base; bool t_format; @@ -166,16 +260,24 @@ struct vc4_bo { */ struct vc4_validated_shader_info *validated_shader; - /* normally (resv == &_resv) except for imported bo's */ - struct reservation_object *resv; - struct reservation_object _resv; + /* One of enum vc4_kernel_bo_type, or VC4_BO_TYPE_COUNT + i + * for user-allocated labels. + */ + int label; + + /* Count the number of active users. This is needed to determine + * whether we can move the BO to the purgeable list or not (when the BO + * is used by the GPU or the display engine we can't purge it). + */ + refcount_t usecnt; + + /* Store purgeable/purged state here */ + u32 madv; + struct mutex madv_lock; }; -static inline struct vc4_bo * -to_vc4_bo(struct drm_gem_object *bo) -{ - return (struct vc4_bo *)bo; -} +#define to_vc4_bo(_bo) \ + container_of_const(to_drm_gem_dma_obj(_bo), struct vc4_bo, base) struct vc4_fence { struct dma_fence base; @@ -184,85 +286,394 @@ struct vc4_fence { uint64_t seqno; }; -static inline struct vc4_fence * -to_vc4_fence(struct dma_fence *fence) -{ - return (struct vc4_fence *)fence; -} - -struct vc4_seqno_cb { - struct work_struct work; - uint64_t seqno; - void (*func)(struct vc4_seqno_cb *cb); -}; +#define to_vc4_fence(_fence) \ + container_of_const(_fence, struct vc4_fence, base) struct vc4_v3d { struct vc4_dev *vc4; struct platform_device *pdev; void __iomem *regs; struct clk *clk; + struct debugfs_regset32 regset; }; +#define VC4_NUM_UPM_HANDLES 32 +struct vc4_upm_refcounts { + refcount_t refcount; + + /* Allocation size */ + size_t size; + /* Our allocation in UPM for prefetching. */ + struct drm_mm_node upm; + + /* Pointer back to the HVS structure */ + struct vc4_hvs *hvs; +}; + +#define HVS_NUM_CHANNELS 3 + struct vc4_hvs { + struct vc4_dev *vc4; struct platform_device *pdev; void __iomem *regs; u32 __iomem *dlist; + unsigned int dlist_mem_size; + + struct clk *core_clk; + struct clk *disp_clk; + + unsigned long max_core_rate; /* Memory manager for CRTCs to allocate space in the display * list. Units are dwords. */ struct drm_mm dlist_mm; + /* Memory manager for the LBM memory used by HVS scaling. */ struct drm_mm lbm_mm; + + /* Memory manager for the UPM memory used for prefetching. */ + struct drm_mm upm_mm; + struct ida upm_handles; + struct vc4_upm_refcounts upm_refcounts[VC4_NUM_UPM_HANDLES + 1]; + spinlock_t mm_lock; struct drm_mm_node mitchell_netravali_filter; + + struct debugfs_regset32 regset; + + /* + * Even if HDMI0 on the RPi4 can output modes requiring a pixel + * rate higher than 297MHz, it needs some adjustments in the + * config.txt file to be able to do so and thus won't always be + * available. + */ + bool vc5_hdmi_enable_hdmi_20; + + /* + * 4096x2160@60 requires a core overclock to work, so register + * whether that is sufficient. + */ + bool vc5_hdmi_enable_4096by2160; }; +#define HVS_NUM_CHANNELS 3 +#define HVS_UBM_WORD_SIZE 256 + +struct vc4_hvs_state { + struct drm_private_state base; + unsigned long core_clock_rate; + + struct { + unsigned in_use: 1; + unsigned long fifo_load; + struct drm_crtc_commit *pending_commit; + } fifo_state[HVS_NUM_CHANNELS]; +}; + +#define to_vc4_hvs_state(_state) \ + container_of_const(_state, struct vc4_hvs_state, base) + +struct vc4_hvs_state *vc4_hvs_get_global_state(struct drm_atomic_state *state); +struct vc4_hvs_state *vc4_hvs_get_old_global_state(const struct drm_atomic_state *state); +struct vc4_hvs_state *vc4_hvs_get_new_global_state(const struct drm_atomic_state *state); + struct vc4_plane { struct drm_plane base; }; -static inline struct vc4_plane * -to_vc4_plane(struct drm_plane *plane) -{ - return (struct vc4_plane *)plane; -} +#define to_vc4_plane(_plane) \ + container_of_const(_plane, struct vc4_plane, base) + +enum vc4_scaling_mode { + VC4_SCALING_NONE, + VC4_SCALING_TPZ, + VC4_SCALING_PPF, +}; + +struct vc4_plane_state { + struct drm_plane_state base; + /* System memory copy of the display list for this element, computed + * at atomic_check time. + */ + u32 *dlist; + u32 dlist_size; /* Number of dwords allocated for the display list */ + u32 dlist_count; /* Number of used dwords in the display list. */ + + /* Offset in the dlist to various words, for pageflip or + * cursor updates. + */ + u32 pos0_offset; + u32 pos2_offset; + u32 ptr0_offset[DRM_FORMAT_MAX_PLANES]; + u32 lbm_offset; + + /* Offset where the plane's dlist was last stored in the + * hardware at vc4_crtc_atomic_flush() time. + */ + u32 __iomem *hw_dlist; + + /* Clipped coordinates of the plane on the display. */ + int crtc_x, crtc_y, crtc_w, crtc_h; + /* Clipped area being scanned from in the FB in u16.16 format */ + u32 src_x, src_y; + + u32 src_w[2], src_h[2]; + + /* Scaling selection for the RGB/Y plane and the Cb/Cr planes. */ + enum vc4_scaling_mode x_scaling[2], y_scaling[2]; + bool is_unity; + bool is_yuv; + + /* Our allocation in LBM for temporary storage during scaling. */ + struct drm_mm_node lbm; + + /* The Unified Pre-Fetcher Handle */ + unsigned int upm_handle[DRM_FORMAT_MAX_PLANES]; + + /* Number of lines to pre-fetch */ + unsigned int upm_buffer_lines; + + /* Set when the plane has per-pixel alpha content or does not cover + * the entire screen. This is a hint to the CRTC that it might need + * to enable background color fill. + */ + bool needs_bg_fill; + + /* Mark the dlist as initialized. Useful to avoid initializing it twice + * when async update is not possible. + */ + bool dlist_initialized; + + /* Load of this plane on the HVS block. The load is expressed in HVS + * cycles/sec. + */ + u64 hvs_load; + + /* Memory bandwidth needed for this plane. This is expressed in + * bytes/sec. + */ + u64 membus_load; +}; + +#define to_vc4_plane_state(_state) \ + container_of_const(_state, struct vc4_plane_state, base) enum vc4_encoder_type { VC4_ENCODER_TYPE_NONE, - VC4_ENCODER_TYPE_HDMI, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1, VC4_ENCODER_TYPE_VEC, VC4_ENCODER_TYPE_DSI0, VC4_ENCODER_TYPE_DSI1, VC4_ENCODER_TYPE_SMI, VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_TXP1, }; struct vc4_encoder { struct drm_encoder base; enum vc4_encoder_type type; u32 clock_select; + + void (*pre_crtc_configure)(struct drm_encoder *encoder, struct drm_atomic_state *state); + void (*pre_crtc_enable)(struct drm_encoder *encoder, struct drm_atomic_state *state); + void (*post_crtc_enable)(struct drm_encoder *encoder, struct drm_atomic_state *state); + + void (*post_crtc_disable)(struct drm_encoder *encoder, struct drm_atomic_state *state); + void (*post_crtc_powerdown)(struct drm_encoder *encoder, struct drm_atomic_state *state); +}; + +#define to_vc4_encoder(_encoder) \ + container_of_const(_encoder, struct vc4_encoder, base) + +static inline +struct drm_encoder *vc4_find_encoder_by_type(struct drm_device *drm, + enum vc4_encoder_type type) +{ + struct drm_encoder *encoder; + + drm_for_each_encoder(encoder, drm) { + struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); + + if (vc4_encoder->type == type) + return encoder; + } + + return NULL; +} + +struct vc4_crtc_data { + const char *name; + + const char *debugfs_name; + + /* Bitmask of channels (FIFOs) of the HVS that the output can source from */ + unsigned int hvs_available_channels; + + /* Which output of the HVS this pixelvalve sources from. */ + int hvs_output; +}; + +struct vc4_txp_data { + struct vc4_crtc_data base; + enum vc4_encoder_type encoder_type; + unsigned int high_addr_ptr_reg; + unsigned int has_byte_enable:1; + unsigned int size_minus_one:1; + unsigned int supports_40bit_addresses:1; +}; + +extern const struct vc4_txp_data bcm2835_txp_data; + +struct vc4_pv_data { + struct vc4_crtc_data base; + + /* Depth of the PixelValve FIFO in bytes */ + unsigned int fifo_depth; + + /* Number of pixels output per clock period */ + u8 pixels_per_clock; + + enum vc4_encoder_type encoder_types[4]; +}; + +extern const struct vc4_pv_data bcm2835_pv0_data; +extern const struct vc4_pv_data bcm2835_pv1_data; +extern const struct vc4_pv_data bcm2835_pv2_data; +extern const struct vc4_pv_data bcm2711_pv0_data; +extern const struct vc4_pv_data bcm2711_pv1_data; +extern const struct vc4_pv_data bcm2711_pv2_data; +extern const struct vc4_pv_data bcm2711_pv3_data; +extern const struct vc4_pv_data bcm2711_pv4_data; +extern const struct vc4_pv_data bcm2712_pv0_data; +extern const struct vc4_pv_data bcm2712_pv1_data; + +struct vc4_crtc { + struct drm_crtc base; + struct platform_device *pdev; + const struct vc4_crtc_data *data; + void __iomem *regs; + + /* Timestamp at start of vblank irq - unaffected by lock delays. */ + ktime_t t_vblank; + + u8 lut_r[256]; + u8 lut_g[256]; + u8 lut_b[256]; + + struct drm_pending_vblank_event *event; + + struct debugfs_regset32 regset; + + /** + * @feeds_txp: True if the CRTC feeds our writeback controller. + */ + bool feeds_txp; + + /** + * @irq_lock: Spinlock protecting the resources shared between + * the atomic code and our vblank handler. + */ + spinlock_t irq_lock; + + /** + * @current_dlist: Start offset of the display list currently + * set in the HVS for that CRTC. Protected by @irq_lock, and + * copied in vc4_hvs_update_dlist() for the CRTC interrupt + * handler to have access to that value. + */ + unsigned int current_dlist; + + /** + * @current_hvs_channel: HVS channel currently assigned to the + * CRTC. Protected by @irq_lock, and copied in + * vc4_hvs_atomic_begin() for the CRTC interrupt handler to have + * access to that value. + */ + unsigned int current_hvs_channel; }; -static inline struct vc4_encoder * -to_vc4_encoder(struct drm_encoder *encoder) +#define to_vc4_crtc(_crtc) \ + container_of_const(_crtc, struct vc4_crtc, base) + +static inline const struct vc4_crtc_data * +vc4_crtc_to_vc4_crtc_data(const struct vc4_crtc *crtc) +{ + return crtc->data; +} + +static inline const struct vc4_pv_data * +vc4_crtc_to_vc4_pv_data(const struct vc4_crtc *crtc) { - return container_of(encoder, struct vc4_encoder, base); + const struct vc4_crtc_data *data = vc4_crtc_to_vc4_crtc_data(crtc); + + return container_of_const(data, struct vc4_pv_data, base); } -#define V3D_READ(offset) readl(vc4->v3d->regs + offset) -#define V3D_WRITE(offset, val) writel(val, vc4->v3d->regs + offset) -#define HVS_READ(offset) readl(vc4->hvs->regs + offset) -#define HVS_WRITE(offset, val) writel(val, vc4->hvs->regs + offset) +struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc, + struct drm_crtc_state *state); + +struct vc4_crtc_state { + struct drm_crtc_state base; + /* Dlist area for this CRTC configuration. */ + struct drm_mm_node mm; + bool txp_armed; + unsigned int assigned_channel; + + struct drm_connector_tv_margins margins; + + unsigned long hvs_load; + + /* Transitional state below, only valid during atomic commits */ + bool update_muxing; +}; + +#define VC4_HVS_CHANNEL_DISABLED ((unsigned int)-1) + +#define to_vc4_crtc_state(_state) \ + container_of_const(_state, struct vc4_crtc_state, base) + +#define V3D_READ(offset) \ + ({ \ + kunit_fail_current_test("Accessing a register in a unit test!\n"); \ + readl(vc4->v3d->regs + (offset)); \ + }) + +#define V3D_WRITE(offset, val) \ + do { \ + kunit_fail_current_test("Accessing a register in a unit test!\n"); \ + writel(val, vc4->v3d->regs + (offset)); \ + } while (0) + +#define HVS_READ(offset) \ + ({ \ + kunit_fail_current_test("Accessing a register in a unit test!\n"); \ + readl(hvs->regs + (offset)); \ + }) + +#define HVS_WRITE(offset, val) \ + do { \ + kunit_fail_current_test("Accessing a register in a unit test!\n"); \ + writel(val, hvs->regs + (offset)); \ + } while (0) + +#define HVS_READ6(offset) \ + HVS_READ(hvs->vc4->gen == VC4_GEN_6_C ? SCALER6_ ## offset : SCALER6D_ ## offset) + +#define HVS_WRITE6(offset, val) \ + HVS_WRITE(hvs->vc4->gen == VC4_GEN_6_C ? SCALER6_ ## offset : SCALER6D_ ## offset, val) + +#define VC4_REG32(reg) { .name = #reg, .offset = reg } struct vc4_exec_info { + struct vc4_dev *dev; + /* Sequence number for this bin/render job. */ uint64_t seqno; - /* Latest write_seqno of any BO that binning depends on. */ - uint64_t bin_dep_seqno; - struct dma_fence *fence; /* Last current addresses the hardware was processing when the @@ -276,14 +687,14 @@ struct vc4_exec_info { /* This is the array of BOs that were looked up at the start of exec. * Command validation will use indices into this array. */ - struct drm_gem_cma_object **bo; + struct drm_gem_object **bo; uint32_t bo_count; /* List of BOs that are being written by the RCL. Other than * the binner temporary storage, this is all the BOs written * by the job. */ - struct drm_gem_cma_object *rcl_write_bo[4]; + struct drm_gem_dma_object *rcl_write_bo[4]; uint32_t rcl_write_bo_count; /* Pointers for our position in vc4->job_list */ @@ -302,7 +713,7 @@ struct vc4_exec_info { /* This is the BO where we store the validated command lists, shader * records, and uniforms. */ - struct drm_gem_cma_object *exec_bo; + struct drm_gem_dma_object *exec_bo; /** * This tracks the per-shader-record state (packet 64) that @@ -362,6 +773,30 @@ struct vc4_exec_info { void *uniforms_v; uint32_t uniforms_p; uint32_t uniforms_size; + + /* Pointer to a performance monitor object if the user requested it, + * NULL otherwise. + */ + struct vc4_perfmon *perfmon; + + /* Whether the exec has taken a reference to the binner BO, which should + * happen with a VC4_PACKET_TILE_BINNING_MODE_CONFIG packet. + */ + bool bin_bo_used; +}; + +/* Per-open file private data. Any driver-specific resource that has to be + * released when the DRM file is closed should be placed here. + */ +struct vc4_file { + struct vc4_dev *dev; + + struct { + struct idr idr; + struct mutex lock; + } perfmon; + + bool bin_bo_used; }; static inline struct vc4_exec_info * @@ -429,43 +864,49 @@ struct vc4_validated_shader_info { }; /** - * _wait_for - magic (register) wait macro + * __wait_for - magic wait macro * - * Does the right thing for modeset paths when run under kdgb or similar atomic - * contexts. Note that it's important that we check the condition again after - * having timed out, since the timeout could be due to preemption or similar and - * we've never had a chance to check the condition before the timeout. + * Macro to help avoid open coding check/wait/timeout patterns. Note that it's + * important that we check the condition again after having timed out, since the + * timeout could be due to preemption or similar and we've never had a chance to + * check the condition before the timeout. */ -#define _wait_for(COND, MS, W) ({ \ - unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1; \ - int ret__ = 0; \ - while (!(COND)) { \ - if (time_after(jiffies, timeout__)) { \ - if (!(COND)) \ - ret__ = -ETIMEDOUT; \ +#define __wait_for(OP, COND, US, Wmin, Wmax) ({ \ + const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (US)); \ + long wait__ = (Wmin); /* recommended min for usleep is 10 us */ \ + int ret__; \ + might_sleep(); \ + for (;;) { \ + const bool expired__ = ktime_after(ktime_get_raw(), end__); \ + OP; \ + /* Guarantee COND check prior to timeout */ \ + barrier(); \ + if (COND) { \ + ret__ = 0; \ break; \ } \ - if (W && drm_can_sleep()) { \ - msleep(W); \ - } else { \ - cpu_relax(); \ + if (expired__) { \ + ret__ = -ETIMEDOUT; \ + break; \ } \ + usleep_range(wait__, wait__ * 2); \ + if (wait__ < (Wmax)) \ + wait__ <<= 1; \ } \ ret__; \ }) -#define wait_for(COND, MS) _wait_for(COND, MS, 1) +#define _wait_for(COND, US, Wmin, Wmax) __wait_for(, (COND), (US), (Wmin), \ + (Wmax)) +#define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 10, 1000) /* vc4_bo.c */ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size); -void vc4_free_object(struct drm_gem_object *gem_obj); struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t size, - bool from_cache); -int vc4_dumb_create(struct drm_file *file_priv, - struct drm_device *dev, - struct drm_mode_create_dumb *args); -struct dma_buf *vc4_prime_export(struct drm_device *dev, - struct drm_gem_object *obj, int flags); + bool from_cache, enum vc4_kernel_bo_type type); +int vc4_bo_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args); int vc4_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data, @@ -478,46 +919,76 @@ int vc4_get_tiling_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int vc4_get_hang_state_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -int vc4_mmap(struct file *filp, struct vm_area_struct *vma); -struct reservation_object *vc4_prime_res_obj(struct drm_gem_object *obj); -int vc4_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); -struct drm_gem_object *vc4_prime_import_sg_table(struct drm_device *dev, - struct dma_buf_attachment *attach, - struct sg_table *sgt); -void *vc4_prime_vmap(struct drm_gem_object *obj); -void vc4_bo_cache_init(struct drm_device *dev); -void vc4_bo_cache_destroy(struct drm_device *dev); -int vc4_bo_stats_debugfs(struct seq_file *m, void *arg); +int vc4_label_bo_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int vc4_bo_cache_init(struct drm_device *dev); +int vc4_bo_inc_usecnt(struct vc4_bo *bo); +void vc4_bo_dec_usecnt(struct vc4_bo *bo); +void vc4_bo_add_to_purgeable_pool(struct vc4_bo *bo); +void vc4_bo_remove_from_purgeable_pool(struct vc4_bo *bo); +int vc4_bo_debugfs_init(struct drm_minor *minor); /* vc4_crtc.c */ extern struct platform_driver vc4_crtc_driver; -bool vc4_event_pending(struct drm_crtc *crtc); -int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg); -bool vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, - bool in_vblank_irq, int *vpos, int *hpos, - ktime_t *stime, ktime_t *etime, - const struct drm_display_mode *mode); +int vc4_crtc_disable_at_boot(struct drm_crtc *crtc); +int __vc4_crtc_init(struct drm_device *drm, struct platform_device *pdev, + struct vc4_crtc *vc4_crtc, const struct vc4_crtc_data *data, + struct drm_plane *primary_plane, + const struct drm_crtc_funcs *crtc_funcs, + const struct drm_crtc_helper_funcs *crtc_helper_funcs, + bool feeds_txp); +int vc4_crtc_init(struct drm_device *drm, struct platform_device *pdev, + struct vc4_crtc *vc4_crtc, const struct vc4_crtc_data *data, + const struct drm_crtc_funcs *crtc_funcs, + const struct drm_crtc_helper_funcs *crtc_helper_funcs, + bool feeds_txp); +int vc4_page_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t flags, + struct drm_modeset_acquire_ctx *ctx); +int vc4_crtc_atomic_check(struct drm_crtc *crtc, + struct drm_atomic_state *state); +struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc); +void vc4_crtc_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *state); +void vc4_crtc_reset(struct drm_crtc *crtc); +void vc4_crtc_handle_vblank(struct vc4_crtc *crtc); +void vc4_crtc_send_vblank(struct drm_crtc *crtc); +int vc4_crtc_late_register(struct drm_crtc *crtc); +void vc4_crtc_get_margins(struct drm_crtc_state *state, + unsigned int *left, unsigned int *right, + unsigned int *top, unsigned int *bottom); /* vc4_debugfs.c */ -int vc4_debugfs_init(struct drm_minor *minor); +void vc4_debugfs_init(struct drm_minor *minor); +#ifdef CONFIG_DEBUG_FS +void vc4_debugfs_add_regset32(struct drm_device *drm, + const char *filename, + struct debugfs_regset32 *regset); +#else + +static inline void vc4_debugfs_add_regset32(struct drm_device *drm, + const char *filename, + struct debugfs_regset32 *regset) +{} +#endif /* vc4_drv.c */ void __iomem *vc4_ioremap_regs(struct platform_device *dev, int index); +int vc4_dumb_fixup_args(struct drm_mode_create_dumb *args); /* vc4_dpi.c */ extern struct platform_driver vc4_dpi_driver; -int vc4_dpi_debugfs_regs(struct seq_file *m, void *unused); /* vc4_dsi.c */ extern struct platform_driver vc4_dsi_driver; -int vc4_dsi_debugfs_regs(struct seq_file *m, void *unused); /* vc4_fence.c */ extern const struct dma_fence_ops vc4_fence_ops; /* vc4_gem.c */ -void vc4_gem_init(struct drm_device *dev); -void vc4_gem_destroy(struct drm_device *dev); +int vc4_gem_init(struct drm_device *dev); int vc4_submit_cl_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int vc4_wait_seqno_ioctl(struct drm_device *dev, void *data, @@ -530,36 +1001,51 @@ void vc4_move_job_to_render(struct drm_device *dev, struct vc4_exec_info *exec); int vc4_wait_for_seqno(struct drm_device *dev, uint64_t seqno, uint64_t timeout_ns, bool interruptible); void vc4_job_handle_completed(struct vc4_dev *vc4); -int vc4_queue_seqno_cb(struct drm_device *dev, - struct vc4_seqno_cb *cb, uint64_t seqno, - void (*func)(struct vc4_seqno_cb *cb)); +int vc4_gem_madvise_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); /* vc4_hdmi.c */ extern struct platform_driver vc4_hdmi_driver; -int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused); /* vc4_vec.c */ extern struct platform_driver vc4_vec_driver; -int vc4_vec_debugfs_regs(struct seq_file *m, void *unused); + +/* vc4_txp.c */ +extern struct platform_driver vc4_txp_driver; /* vc4_irq.c */ -irqreturn_t vc4_irq(int irq, void *arg); -void vc4_irq_preinstall(struct drm_device *dev); -int vc4_irq_postinstall(struct drm_device *dev); +void vc4_irq_enable(struct drm_device *dev); +void vc4_irq_disable(struct drm_device *dev); +int vc4_irq_install(struct drm_device *dev, int irq); void vc4_irq_uninstall(struct drm_device *dev); void vc4_irq_reset(struct drm_device *dev); /* vc4_hvs.c */ extern struct platform_driver vc4_hvs_driver; -void vc4_hvs_dump_state(struct drm_device *dev); -int vc4_hvs_debugfs_regs(struct seq_file *m, void *unused); +struct vc4_hvs *__vc4_hvs_alloc(struct vc4_dev *vc4, + void __iomem *regs, + struct platform_device *pdev); +void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int output); +int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output); +u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo); +int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state); +void vc4_hvs_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state); +void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state); +void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state); +void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state); +void vc4_hvs_dump_state(struct vc4_hvs *hvs); +void vc4_hvs_unmask_underrun(struct vc4_hvs *hvs, int channel); +void vc4_hvs_mask_underrun(struct vc4_hvs *hvs, int channel); +int vc4_hvs_debugfs_init(struct drm_minor *minor); /* vc4_kms.c */ int vc4_kms_load(struct drm_device *dev); /* vc4_plane.c */ struct drm_plane *vc4_plane_init(struct drm_device *dev, - enum drm_plane_type type); + enum drm_plane_type type, + uint32_t possible_crtcs); +int vc4_plane_create_additional_planes(struct drm_device *dev); u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist); u32 vc4_plane_dlist_size(const struct drm_plane_state *state); void vc4_plane_async_set_fb(struct drm_plane *plane, @@ -567,9 +1053,13 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, /* vc4_v3d.c */ extern struct platform_driver vc4_v3d_driver; -int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused); -int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused); +extern const struct of_device_id vc4_v3d_dt_match[]; int vc4_v3d_get_bin_slot(struct vc4_dev *vc4); +int vc4_v3d_bin_bo_get(struct vc4_dev *vc4, bool *used); +void vc4_v3d_bin_bo_put(struct vc4_dev *vc4); +int vc4_v3d_pm_get(struct vc4_dev *vc4); +void vc4_v3d_pm_put(struct vc4_dev *vc4); +int vc4_v3d_debugfs_init(struct drm_minor *minor); /* vc4_validate.c */ int @@ -581,16 +1071,34 @@ vc4_validate_bin_cl(struct drm_device *dev, int vc4_validate_shader_recs(struct drm_device *dev, struct vc4_exec_info *exec); -struct drm_gem_cma_object *vc4_use_bo(struct vc4_exec_info *exec, +struct drm_gem_dma_object *vc4_use_bo(struct vc4_exec_info *exec, uint32_t hindex); int vc4_get_rcl(struct drm_device *dev, struct vc4_exec_info *exec); bool vc4_check_tex_size(struct vc4_exec_info *exec, - struct drm_gem_cma_object *fbo, + struct drm_gem_dma_object *fbo, uint32_t offset, uint8_t tiling_format, uint32_t width, uint32_t height, uint8_t cpp); /* vc4_validate_shader.c */ struct vc4_validated_shader_info * -vc4_validate_shader(struct drm_gem_cma_object *shader_obj); +vc4_validate_shader(struct drm_gem_dma_object *shader_obj); + +/* vc4_perfmon.c */ +void vc4_perfmon_get(struct vc4_perfmon *perfmon); +void vc4_perfmon_put(struct vc4_perfmon *perfmon); +void vc4_perfmon_start(struct vc4_dev *vc4, struct vc4_perfmon *perfmon); +void vc4_perfmon_stop(struct vc4_dev *vc4, struct vc4_perfmon *perfmon, + bool capture); +struct vc4_perfmon *vc4_perfmon_find(struct vc4_file *vc4file, int id); +void vc4_perfmon_open_file(struct vc4_file *vc4file); +void vc4_perfmon_close_file(struct vc4_file *vc4file); +int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int vc4_perfmon_destroy_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int vc4_perfmon_get_values_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + +#endif /* _VC4_DRV_H_ */ |
