linux/drivers/gpu/drm/vc4/vc4_crtc.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2015 Broadcom
 */

/**
 * DOC: VC4 CRTC module
 *
 * In VC4, the Pixel Valve is what most closely corresponds to the
 * DRM's concept of a CRTC.  The PV generates video timings from the
 * encoder's clock plus its configuration.  It pulls scaled pixels from
 * the HVS at that timing, and feeds it to the encoder.
 *
 * However, the DRM CRTC also collects the configuration of all the
 * DRM planes attached to it.  As a result, the CRTC is also
 * responsible for writing the display list for the HVS channel that
 * the CRTC will use.
 *
 * The 2835 has 3 different pixel valves.  pv0 in the audio power
 * domain feeds DSI0 or DPI, while pv1 feeds DS1 or SMI.  pv2 in the
 * image domain can feed either HDMI or the SDTV controller.  The
 * pixel valve chooses from the CPRMAN clocks (HSM for HDMI, VEC for
 * SDTV, etc.) according to which output type is chosen in the mux.
 *
 * For power management, the pixel valve's registers are all clocked
 * by the AXI clock, while the timings and FIFOs make use of the
 * output-specific clock.  Since the encoders also directly consume
 * the CPRMAN clocks, and know what timings they need, they are the
 * ones that set the clock.
 */

#include <linux/clk.h>
#include <linux/component.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>

#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_fb_dma_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_drv.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>

#include "vc4_drv.h"
#include "vc4_hdmi.h"
#include "vc4_regs.h"

#define HVS_FIFO_LATENCY_PIX

#define CRTC_WRITE(offset, val)

#define CRTC_READ(offset)

static const struct debugfs_reg32 crtc_regs[] =;

static unsigned int
vc4_crtc_get_cob_allocation(struct vc4_dev *vc4, unsigned int channel)
{}

static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
					  bool in_vblank_irq,
					  int *vpos, int *hpos,
					  ktime_t *stime, ktime_t *etime,
					  const struct drm_display_mode *mode)
{}

static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
{}

static u32 vc4_crtc_get_fifo_full_level_bits(struct vc4_crtc *vc4_crtc,
					     u32 format)
{}

/*
 * Returns the encoder attached to the CRTC.
 *
 * VC4 can only scan out to one encoder at a time, while the DRM core
 * allows drivers to push pixels to more than one encoder from the
 * same CRTC.
 */
struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc,
					 struct drm_crtc_state *state)
{}

static void vc4_crtc_pixelvalve_reset(struct drm_crtc *crtc)
{}

static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encoder,
			       struct drm_atomic_state *state)
{}

static void require_hvs_enabled(struct drm_device *dev)
{}

static int vc4_crtc_disable(struct drm_crtc *crtc,
			    struct drm_encoder *encoder,
			    struct drm_atomic_state *state,
			    unsigned int channel)
{}

int vc4_crtc_disable_at_boot(struct drm_crtc *crtc)
{}

void vc4_crtc_send_vblank(struct drm_crtc *crtc)
{}

static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
				    struct drm_atomic_state *state)
{}

static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
				   struct drm_atomic_state *state)
{}

static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc,
						const struct drm_display_mode *mode)
{}

void vc4_crtc_get_margins(struct drm_crtc_state *state,
			  unsigned int *left, unsigned int *right,
			  unsigned int *top, unsigned int *bottom)
{}

int vc4_crtc_atomic_check(struct drm_crtc *crtc,
			  struct drm_atomic_state *state)
{}

static int vc4_enable_vblank(struct drm_crtc *crtc)
{}

static void vc4_disable_vblank(struct drm_crtc *crtc)
{}

static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
{}

void vc4_crtc_handle_vblank(struct vc4_crtc *crtc)
{}

static irqreturn_t vc4_crtc_irq_handler(int irq, void *data)
{}

struct vc4_async_flip_state {};

/* Called when the V3D execution for the BO being flipped to is done, so that
 * we can actually update the plane's address to point to it.
 */
static void
vc4_async_page_flip_complete(struct vc4_async_flip_state *flip_state)
{}

static void vc4_async_page_flip_seqno_complete(struct vc4_seqno_cb *cb)
{}

static void vc4_async_page_flip_fence_complete(struct dma_fence *fence,
					       struct dma_fence_cb *cb)
{}

static int vc4_async_set_fence_cb(struct drm_device *dev,
				  struct vc4_async_flip_state *flip_state)
{}

static int
vc4_async_page_flip_common(struct drm_crtc *crtc,
			   struct drm_framebuffer *fb,
			   struct drm_pending_vblank_event *event,
			   uint32_t flags)
{}

/* Implements async (non-vblank-synced) page flips.
 *
 * The page flip ioctl needs to return immediately, so we grab the
 * modeset semaphore on the pipe, and queue the address update for
 * when V3D is done with the BO being flipped to.
 */
static int vc4_async_page_flip(struct drm_crtc *crtc,
			       struct drm_framebuffer *fb,
			       struct drm_pending_vblank_event *event,
			       uint32_t flags)
{}

static int vc5_async_page_flip(struct drm_crtc *crtc,
			       struct drm_framebuffer *fb,
			       struct drm_pending_vblank_event *event,
			       uint32_t flags)
{}

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)
{}

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)
{}

int vc4_crtc_late_register(struct drm_crtc *crtc)
{}

static const struct drm_crtc_funcs vc4_crtc_funcs =;

static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs =;

const struct vc4_pv_data bcm2835_pv0_data =;

const struct vc4_pv_data bcm2835_pv1_data =;

const struct vc4_pv_data bcm2835_pv2_data =;

const struct vc4_pv_data bcm2711_pv0_data =;

const struct vc4_pv_data bcm2711_pv1_data =;

const struct vc4_pv_data bcm2711_pv2_data =;

const struct vc4_pv_data bcm2711_pv3_data =;

const struct vc4_pv_data bcm2711_pv4_data =;

static const struct of_device_id vc4_crtc_dt_match[] =;

static void vc4_set_crtc_possible_masks(struct drm_device *drm,
					struct drm_crtc *crtc)
{}

/**
 * __vc4_crtc_init - Initializes a CRTC
 * @drm: DRM Device
 * @pdev: CRTC Platform Device
 * @vc4_crtc: CRTC Object to Initialize
 * @data: Configuration data associated with this CRTC
 * @primary_plane: Primary plane for CRTC
 * @crtc_funcs: Callbacks for the new CRTC
 * @crtc_helper_funcs: Helper Callbacks for the new CRTC
 * @feeds_txp: Is this CRTC connected to the TXP?
 *
 * Initializes our private CRTC structure. This function is mostly
 * relevant for KUnit testing, all other users should use
 * vc4_crtc_init() instead.
 *
 * Returns:
 * 0 on success, a negative error code on failure.
 */
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)
{}

static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
{}

static void vc4_crtc_unbind(struct device *dev, struct device *master,
			    void *data)
{}

static const struct component_ops vc4_crtc_ops =;

static int vc4_crtc_dev_probe(struct platform_device *pdev)
{}

static void vc4_crtc_dev_remove(struct platform_device *pdev)
{}

struct platform_driver vc4_crtc_driver =;