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

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2015 Broadcom
 * Copyright (c) 2014 The Linux Foundation. All rights reserved.
 * Copyright (C) 2013 Red Hat
 * Author: Rob Clark <[email protected]>
 */

/**
 * DOC: VC4 Falcon HDMI module
 *
 * The HDMI core has a state machine and a PHY.  On BCM2835, most of
 * the unit operates off of the HSM clock from CPRMAN.  It also
 * internally uses the PLLH_PIX clock for the PHY.
 *
 * HDMI infoframes are kept within a small packet ram, where each
 * packet can be individually enabled for including in a frame.
 *
 * HDMI audio is implemented entirely within the HDMI IP block.  A
 * register in the HDMI encoder takes SPDIF frames from the DMA engine
 * and transfers them over an internal MAI (multi-channel audio
 * interconnect) bus to the encoder side for insertion into the video
 * blank regions.
 *
 * The driver's HDMI encoder does not yet support power management.
 * The HDMI encoder's power domain and the HSM/pixel clocks are kept
 * continuously running, and only the HDMI logic and packet ram are
 * powered off/on at disable/enable time.
 *
 * The driver does not yet support CEC control, though the HDMI
 * encoder block has CEC support.
 */

#include <drm/display/drm_hdmi_helper.h>
#include <drm/display/drm_hdmi_state_helper.h>
#include <drm/display/drm_scdc_helper.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
#include <linux/clk.h>
#include <linux/component.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/pm_runtime.h>
#include <linux/rational.h>
#include <linux/reset.h>
#include <sound/dmaengine_pcm.h>
#include <sound/hdmi-codec.h>
#include <sound/pcm_drm_eld.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include "media/cec.h"
#include "vc4_drv.h"
#include "vc4_hdmi.h"
#include "vc4_hdmi_regs.h"
#include "vc4_regs.h"

#define VC5_HDMI_HORZA_HFP_SHIFT
#define VC5_HDMI_HORZA_HFP_MASK
#define VC5_HDMI_HORZA_VPOS
#define VC5_HDMI_HORZA_HPOS
#define VC5_HDMI_HORZA_HAP_SHIFT
#define VC5_HDMI_HORZA_HAP_MASK

#define VC5_HDMI_HORZB_HBP_SHIFT
#define VC5_HDMI_HORZB_HBP_MASK
#define VC5_HDMI_HORZB_HSP_SHIFT
#define VC5_HDMI_HORZB_HSP_MASK

#define VC5_HDMI_VERTA_VSP_SHIFT
#define VC5_HDMI_VERTA_VSP_MASK
#define VC5_HDMI_VERTA_VFP_SHIFT
#define VC5_HDMI_VERTA_VFP_MASK
#define VC5_HDMI_VERTA_VAL_SHIFT
#define VC5_HDMI_VERTA_VAL_MASK

#define VC5_HDMI_VERTB_VSPO_SHIFT
#define VC5_HDMI_VERTB_VSPO_MASK

#define VC4_HDMI_MISC_CONTROL_PIXEL_REP_SHIFT
#define VC4_HDMI_MISC_CONTROL_PIXEL_REP_MASK
#define VC5_HDMI_MISC_CONTROL_PIXEL_REP_SHIFT
#define VC5_HDMI_MISC_CONTROL_PIXEL_REP_MASK

#define VC5_HDMI_SCRAMBLER_CTL_ENABLE

#define VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_SHIFT
#define VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_MASK

#define VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_SHIFT
#define VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_MASK

#define VC5_HDMI_GCP_CONFIG_GCP_ENABLE

#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_SHIFT
#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_MASK

#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_0_MASK
#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_0_SET_AVMUTE
#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_0_CLEAR_AVMUTE

#define VC4_HD_M_SW_RST
#define VC4_HD_M_ENABLE

#define HSM_MIN_CLOCK_FREQ
#define CEC_CLOCK_FREQ

#define HDMI_14_MAX_TMDS_CLK

static bool vc4_hdmi_supports_scrambling(struct vc4_hdmi *vc4_hdmi)
{}

static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode,
					   unsigned int bpc,
					   enum hdmi_colorspace fmt)
{}

static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
{}

static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
{}

static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
{}

#ifdef CONFIG_DRM_VC4_HDMI_CEC
static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi)
{}
#else
static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {}
#endif

static int reset_pipe(struct drm_crtc *crtc,
			struct drm_modeset_acquire_ctx *ctx)
{}

static int vc4_hdmi_reset_link(struct drm_connector *connector,
			       struct drm_modeset_acquire_ctx *ctx)
{}

static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi,
				    struct drm_modeset_acquire_ctx *ctx,
				    enum drm_connector_status status)
{}

static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector,
					 struct drm_modeset_acquire_ctx *ctx,
					 bool force)
{}

static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
{}

static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector,
					   struct drm_atomic_state *state)
{}

static void vc4_hdmi_connector_reset(struct drm_connector *connector)
{}

static const struct drm_connector_funcs vc4_hdmi_connector_funcs =;

static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =;

static const struct drm_connector_hdmi_funcs vc4_hdmi_hdmi_connector_funcs;

static int vc4_hdmi_connector_init(struct drm_device *dev,
				   struct vc4_hdmi *vc4_hdmi)
{}

static int vc4_hdmi_stop_packet(struct vc4_hdmi *vc4_hdmi,
				enum hdmi_infoframe_type type,
				bool poll)
{}

static int vc4_hdmi_write_infoframe(struct drm_connector *connector,
				    enum hdmi_infoframe_type type,
				    const u8 *infoframe, size_t len)
{}

#define SCRAMBLING_POLLING_DELAY_MS

static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)
{}

static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder)
{}

static void vc4_hdmi_scrambling_wq(struct work_struct *work)
{}

static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder,
					       struct drm_atomic_state *state)
{}

static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,
						 struct drm_atomic_state *state)
{}

static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
			       struct drm_connector_state *state,
			       const struct drm_display_mode *mode)
{}

/*
 * Matrices for (internal) RGB to RGB output.
 *
 * Matrices are signed 2p13 fixed point, with signed 9p6 offsets
 */
static const u16 vc5_hdmi_csc_full_rgb_to_rgb[2][3][4] =;

/*
 * Conversion between Full Range RGB and YUV using the BT.601 Colorspace
 *
 * Matrices are signed 2p13 fixed point, with signed 9p6 offsets
 */
static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt601[2][3][4] =;

/*
 * Conversion between Full Range RGB and YUV using the BT.709 Colorspace
 *
 * Matrices are signed 2p13 fixed point, with signed 9p6 offsets
 */
static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt709[2][3][4] =;

/*
 * Conversion between Full Range RGB and YUV using the BT.2020 Colorspace
 *
 * Matrices are signed 2p13 fixed point, with signed 9p6 offsets
 */
static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt2020[2][3][4] =;

static void vc5_hdmi_set_csc_coeffs(struct vc4_hdmi *vc4_hdmi,
				    const u16 coeffs[3][4])
{}

static void vc5_hdmi_set_csc_coeffs_swap(struct vc4_hdmi *vc4_hdmi,
					 const u16 coeffs[3][4])
{}

static const u16
(*vc5_hdmi_find_yuv_csc_coeffs(struct vc4_hdmi *vc4_hdmi, u32 colorspace, bool limited))[4]
{}

static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
			       struct drm_connector_state *state,
			       const struct drm_display_mode *mode)
{}

static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
				 struct drm_connector_state *state,
				 const struct drm_display_mode *mode)
{}

static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
				 struct drm_connector_state *state,
				 const struct drm_display_mode *mode)
{}

static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
{}

static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
						struct drm_atomic_state *state)
{}

static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,
					     struct drm_atomic_state *state)
{}

static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
					      struct drm_atomic_state *state)
{}

static void vc4_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder,
					     struct drm_crtc_state *crtc_state,
					     struct drm_connector_state *conn_state)
{}

static enum drm_mode_status
vc4_hdmi_connector_clock_valid(const struct drm_connector *connector,
			       const struct drm_display_mode *mode,
			       unsigned long long clock)
{}

static const struct drm_connector_hdmi_funcs vc4_hdmi_hdmi_connector_funcs =;

#define WIFI_2_4GHz_CH1_MIN_FREQ
#define WIFI_2_4GHz_CH1_MAX_FREQ

static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
					 struct drm_crtc_state *crtc_state,
					 struct drm_connector_state *conn_state)
{}

static enum drm_mode_status
vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
			    const struct drm_display_mode *mode)
{}

static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs =;

static int vc4_hdmi_late_register(struct drm_encoder *encoder)
{}

static const struct drm_encoder_funcs vc4_hdmi_encoder_funcs =;

static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
{}

static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
{}

static bool vc5_hdmi_hp_detect(struct vc4_hdmi *vc4_hdmi)
{}

/* HDMI audio codec callbacks */
static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi,
					 unsigned int samplerate)
{}

static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi, unsigned int samplerate)
{}

static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai)
{}

static bool vc4_hdmi_audio_can_stream(struct vc4_hdmi *vc4_hdmi)
{}

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

static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
{}

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

static int sample_rate_to_mai_fmt(int samplerate)
{}

/* HDMI audio codec callbacks */
static int vc4_hdmi_audio_prepare(struct device *dev, void *data,
				  struct hdmi_codec_daifmt *daifmt,
				  struct hdmi_codec_params *params)
{}

static const struct snd_soc_component_driver vc4_hdmi_audio_cpu_dai_comp =;

static int vc4_hdmi_audio_cpu_dai_probe(struct snd_soc_dai *dai)
{}

static const struct snd_soc_dai_ops vc4_snd_dai_ops =;

static struct snd_soc_dai_driver vc4_hdmi_audio_cpu_dai_drv =;

static const struct snd_dmaengine_pcm_config pcm_conf =;

static int vc4_hdmi_audio_get_eld(struct device *dev, void *data,
				  uint8_t *buf, size_t len)
{}

static const struct hdmi_codec_ops vc4_hdmi_codec_ops =;

static struct hdmi_codec_pdata vc4_hdmi_codec_pdata =;

static void vc4_hdmi_audio_codec_release(void *ptr)
{}

static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
{}

static irqreturn_t vc4_hdmi_hpd_irq_thread(int irq, void *priv)
{}

static int vc4_hdmi_hotplug_init(struct vc4_hdmi *vc4_hdmi)
{}

#ifdef CONFIG_DRM_VC4_HDMI_CEC
static irqreturn_t vc4_cec_irq_handler_rx_thread(int irq, void *priv)
{}

static irqreturn_t vc4_cec_irq_handler_tx_thread(int irq, void *priv)
{}

static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
{}

static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
{}

static irqreturn_t vc4_cec_irq_handler_tx_bare_locked(struct vc4_hdmi *vc4_hdmi)
{}

static irqreturn_t vc4_cec_irq_handler_tx_bare(int irq, void *priv)
{}

static irqreturn_t vc4_cec_irq_handler_rx_bare_locked(struct vc4_hdmi *vc4_hdmi)
{}

static irqreturn_t vc4_cec_irq_handler_rx_bare(int irq, void *priv)
{}

static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
{}

static int vc4_hdmi_cec_enable(struct cec_adapter *adap)
{}

static int vc4_hdmi_cec_disable(struct cec_adapter *adap)
{}

static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
{}

static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
{}

static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
				      u32 signal_free_time, struct cec_msg *msg)
{}

static const struct cec_adap_ops vc4_hdmi_cec_adap_ops =;

static void vc4_hdmi_cec_release(void *ptr)
{}

static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
{}
#else
static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
{
	return 0;
}
#endif

static void vc4_hdmi_free_regset(struct drm_device *drm, void *ptr)
{}

static int vc4_hdmi_build_regset(struct drm_device *drm,
				 struct vc4_hdmi *vc4_hdmi,
				 struct debugfs_regset32 *regset,
				 enum vc4_hdmi_regs reg)
{}

static int vc4_hdmi_init_resources(struct drm_device *drm,
				   struct vc4_hdmi *vc4_hdmi)
{}

static int vc5_hdmi_init_resources(struct drm_device *drm,
				   struct vc4_hdmi *vc4_hdmi)
{}

static int vc4_hdmi_runtime_suspend(struct device *dev)
{}

static int vc4_hdmi_runtime_resume(struct device *dev)
{}

static void vc4_hdmi_put_ddc_device(void *ptr)
{}

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

static const struct component_ops vc4_hdmi_ops =;

static int vc4_hdmi_dev_probe(struct platform_device *pdev)
{}

static void vc4_hdmi_dev_remove(struct platform_device *pdev)
{}

static const struct vc4_hdmi_variant bcm2835_variant =;

static const struct vc4_hdmi_variant bcm2711_hdmi0_variant =;

static const struct vc4_hdmi_variant bcm2711_hdmi1_variant =;

static const struct of_device_id vc4_hdmi_dt_match[] =;

static const struct dev_pm_ops vc4_hdmi_pm_ops =;

struct platform_driver vc4_hdmi_driver =;