18c2ecf20Sopenharmony_ci#ifndef _VC4_HDMI_H_
28c2ecf20Sopenharmony_ci#define _VC4_HDMI_H_
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <drm/drm_connector.h>
58c2ecf20Sopenharmony_ci#include <media/cec.h>
68c2ecf20Sopenharmony_ci#include <sound/dmaengine_pcm.h>
78c2ecf20Sopenharmony_ci#include <sound/soc.h>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "vc4_drv.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/* VC4 HDMI encoder KMS struct */
128c2ecf20Sopenharmony_cistruct vc4_hdmi_encoder {
138c2ecf20Sopenharmony_ci	struct vc4_encoder base;
148c2ecf20Sopenharmony_ci	bool hdmi_monitor;
158c2ecf20Sopenharmony_ci	bool limited_rgb_range;
168c2ecf20Sopenharmony_ci};
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistatic inline struct vc4_hdmi_encoder *
198c2ecf20Sopenharmony_cito_vc4_hdmi_encoder(struct drm_encoder *encoder)
208c2ecf20Sopenharmony_ci{
218c2ecf20Sopenharmony_ci	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
228c2ecf20Sopenharmony_ci}
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cistruct drm_display_mode;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_cistruct vc4_hdmi;
278c2ecf20Sopenharmony_cistruct vc4_hdmi_register;
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cienum vc4_hdmi_phy_channel {
308c2ecf20Sopenharmony_ci	PHY_LANE_0 = 0,
318c2ecf20Sopenharmony_ci	PHY_LANE_1,
328c2ecf20Sopenharmony_ci	PHY_LANE_2,
338c2ecf20Sopenharmony_ci	PHY_LANE_CK,
348c2ecf20Sopenharmony_ci};
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cistruct vc4_hdmi_variant {
378c2ecf20Sopenharmony_ci	/* Encoder Type for that controller */
388c2ecf20Sopenharmony_ci	enum vc4_encoder_type encoder_type;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	/* ALSA card name */
418c2ecf20Sopenharmony_ci	const char *card_name;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	/* Filename to expose the registers in debugfs */
448c2ecf20Sopenharmony_ci	const char *debugfs_name;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	/* Set to true when the CEC support is available */
478c2ecf20Sopenharmony_ci	bool cec_available;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	/* Maximum pixel clock supported by the controller (in Hz) */
508c2ecf20Sopenharmony_ci	unsigned long long max_pixel_clock;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	/* List of the registers available on that variant */
538c2ecf20Sopenharmony_ci	const struct vc4_hdmi_register *registers;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	/* Number of registers on that variant */
568c2ecf20Sopenharmony_ci	unsigned int num_registers;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	/* BCM2711 Only.
598c2ecf20Sopenharmony_ci	 * The variants don't map the lane in the same order in the
608c2ecf20Sopenharmony_ci	 * PHY, so this is an array mapping the HDMI channel (index)
618c2ecf20Sopenharmony_ci	 * to the PHY lane (value).
628c2ecf20Sopenharmony_ci	 */
638c2ecf20Sopenharmony_ci	enum vc4_hdmi_phy_channel phy_lane_mapping[4];
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	/* The BCM2711 cannot deal with odd horizontal pixel timings */
668c2ecf20Sopenharmony_ci	bool unsupported_odd_h_timings;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	/* Callback to get the resources (memory region, interrupts,
698c2ecf20Sopenharmony_ci	 * clocks, etc) for that variant.
708c2ecf20Sopenharmony_ci	 */
718c2ecf20Sopenharmony_ci	int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	/* Callback to reset the HDMI block */
748c2ecf20Sopenharmony_ci	void (*reset)(struct vc4_hdmi *vc4_hdmi);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	/* Callback to enable / disable the CSC */
778c2ecf20Sopenharmony_ci	void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, bool enable);
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	/* Callback to configure the video timings in the HDMI block */
808c2ecf20Sopenharmony_ci	void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
818c2ecf20Sopenharmony_ci			    struct drm_display_mode *mode);
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	/* Callback to initialize the PHY according to the mode */
848c2ecf20Sopenharmony_ci	void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
858c2ecf20Sopenharmony_ci			 struct drm_display_mode *mode);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	/* Callback to disable the PHY */
888c2ecf20Sopenharmony_ci	void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	/* Callback to enable the RNG in the PHY */
918c2ecf20Sopenharmony_ci	void (*phy_rng_enable)(struct vc4_hdmi *vc4_hdmi);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	/* Callback to disable the RNG in the PHY */
948c2ecf20Sopenharmony_ci	void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi);
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	/* Callback to get channel map */
978c2ecf20Sopenharmony_ci	u32 (*channel_map)(struct vc4_hdmi *vc4_hdmi, u32 channel_mask);
988c2ecf20Sopenharmony_ci};
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci/* HDMI audio information */
1018c2ecf20Sopenharmony_cistruct vc4_hdmi_audio {
1028c2ecf20Sopenharmony_ci	struct snd_soc_card card;
1038c2ecf20Sopenharmony_ci	struct snd_soc_dai_link link;
1048c2ecf20Sopenharmony_ci	struct snd_soc_dai_link_component cpu;
1058c2ecf20Sopenharmony_ci	struct snd_soc_dai_link_component codec;
1068c2ecf20Sopenharmony_ci	struct snd_soc_dai_link_component platform;
1078c2ecf20Sopenharmony_ci	int samplerate;
1088c2ecf20Sopenharmony_ci	int channels;
1098c2ecf20Sopenharmony_ci	struct snd_dmaengine_dai_dma_data dma_data;
1108c2ecf20Sopenharmony_ci	struct snd_pcm_substream *substream;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	bool streaming;
1138c2ecf20Sopenharmony_ci};
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci/* General HDMI hardware state. */
1168c2ecf20Sopenharmony_cistruct vc4_hdmi {
1178c2ecf20Sopenharmony_ci	struct vc4_hdmi_audio audio;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	struct platform_device *pdev;
1208c2ecf20Sopenharmony_ci	const struct vc4_hdmi_variant *variant;
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	struct vc4_hdmi_encoder encoder;
1238c2ecf20Sopenharmony_ci	struct drm_connector connector;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	struct i2c_adapter *ddc;
1268c2ecf20Sopenharmony_ci	void __iomem *hdmicore_regs;
1278c2ecf20Sopenharmony_ci	void __iomem *hd_regs;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	/* VC5 Only */
1308c2ecf20Sopenharmony_ci	void __iomem *cec_regs;
1318c2ecf20Sopenharmony_ci	/* VC5 Only */
1328c2ecf20Sopenharmony_ci	void __iomem *csc_regs;
1338c2ecf20Sopenharmony_ci	/* VC5 Only */
1348c2ecf20Sopenharmony_ci	void __iomem *dvp_regs;
1358c2ecf20Sopenharmony_ci	/* VC5 Only */
1368c2ecf20Sopenharmony_ci	void __iomem *phy_regs;
1378c2ecf20Sopenharmony_ci	/* VC5 Only */
1388c2ecf20Sopenharmony_ci	void __iomem *ram_regs;
1398c2ecf20Sopenharmony_ci	/* VC5 Only */
1408c2ecf20Sopenharmony_ci	void __iomem *rm_regs;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	int hpd_gpio;
1438c2ecf20Sopenharmony_ci	bool hpd_active_low;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	/*
1468c2ecf20Sopenharmony_ci	 * On some systems (like the RPi4), some modes are in the same
1478c2ecf20Sopenharmony_ci	 * frequency range than the WiFi channels (1440p@60Hz for
1488c2ecf20Sopenharmony_ci	 * example). Should we take evasive actions because that system
1498c2ecf20Sopenharmony_ci	 * has a wifi adapter?
1508c2ecf20Sopenharmony_ci	 */
1518c2ecf20Sopenharmony_ci	bool disable_wifi_frequencies;
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	struct cec_adapter *cec_adap;
1548c2ecf20Sopenharmony_ci	struct cec_msg cec_rx_msg;
1558c2ecf20Sopenharmony_ci	bool cec_tx_ok;
1568c2ecf20Sopenharmony_ci	bool cec_irq_was_rx;
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	struct clk *pixel_clock;
1598c2ecf20Sopenharmony_ci	struct clk *hsm_clock;
1608c2ecf20Sopenharmony_ci	struct clk *audio_clock;
1618c2ecf20Sopenharmony_ci	struct clk *pixel_bvb_clock;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	struct reset_control *reset;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	struct debugfs_regset32 hdmi_regset;
1668c2ecf20Sopenharmony_ci	struct debugfs_regset32 hd_regset;
1678c2ecf20Sopenharmony_ci};
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistatic inline struct vc4_hdmi *
1708c2ecf20Sopenharmony_ciconnector_to_vc4_hdmi(struct drm_connector *connector)
1718c2ecf20Sopenharmony_ci{
1728c2ecf20Sopenharmony_ci	return container_of(connector, struct vc4_hdmi, connector);
1738c2ecf20Sopenharmony_ci}
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_cistatic inline struct vc4_hdmi *
1768c2ecf20Sopenharmony_ciencoder_to_vc4_hdmi(struct drm_encoder *encoder)
1778c2ecf20Sopenharmony_ci{
1788c2ecf20Sopenharmony_ci	struct vc4_hdmi_encoder *_encoder = to_vc4_hdmi_encoder(encoder);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	return container_of(_encoder, struct vc4_hdmi, encoder);
1818c2ecf20Sopenharmony_ci}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_civoid vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
1848c2ecf20Sopenharmony_ci		       struct drm_display_mode *mode);
1858c2ecf20Sopenharmony_civoid vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
1868c2ecf20Sopenharmony_civoid vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
1878c2ecf20Sopenharmony_civoid vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_civoid vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
1908c2ecf20Sopenharmony_ci		       struct drm_display_mode *mode);
1918c2ecf20Sopenharmony_civoid vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
1928c2ecf20Sopenharmony_civoid vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
1938c2ecf20Sopenharmony_civoid vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci#endif /* _VC4_HDMI_H_ */
196