1#ifndef _VC4_HDMI_H_
2#define _VC4_HDMI_H_
3
4#include <drm/drm_connector.h>
5#include <media/cec.h>
6#include <sound/dmaengine_pcm.h>
7#include <sound/soc.h>
8
9#include "vc4_drv.h"
10
11/* VC4 HDMI encoder KMS struct */
12struct vc4_hdmi_encoder {
13	struct vc4_encoder base;
14	bool hdmi_monitor;
15	bool limited_rgb_range;
16};
17
18static inline struct vc4_hdmi_encoder *
19to_vc4_hdmi_encoder(struct drm_encoder *encoder)
20{
21	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
22}
23
24struct drm_display_mode;
25
26struct vc4_hdmi;
27struct vc4_hdmi_register;
28
29enum vc4_hdmi_phy_channel {
30	PHY_LANE_0 = 0,
31	PHY_LANE_1,
32	PHY_LANE_2,
33	PHY_LANE_CK,
34};
35
36struct vc4_hdmi_variant {
37	/* Encoder Type for that controller */
38	enum vc4_encoder_type encoder_type;
39
40	/* ALSA card name */
41	const char *card_name;
42
43	/* Filename to expose the registers in debugfs */
44	const char *debugfs_name;
45
46	/* Set to true when the CEC support is available */
47	bool cec_available;
48
49	/* Maximum pixel clock supported by the controller (in Hz) */
50	unsigned long long max_pixel_clock;
51
52	/* List of the registers available on that variant */
53	const struct vc4_hdmi_register *registers;
54
55	/* Number of registers on that variant */
56	unsigned int num_registers;
57
58	/* BCM2711 Only.
59	 * The variants don't map the lane in the same order in the
60	 * PHY, so this is an array mapping the HDMI channel (index)
61	 * to the PHY lane (value).
62	 */
63	enum vc4_hdmi_phy_channel phy_lane_mapping[4];
64
65	/* The BCM2711 cannot deal with odd horizontal pixel timings */
66	bool unsupported_odd_h_timings;
67
68	/* Callback to get the resources (memory region, interrupts,
69	 * clocks, etc) for that variant.
70	 */
71	int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
72
73	/* Callback to reset the HDMI block */
74	void (*reset)(struct vc4_hdmi *vc4_hdmi);
75
76	/* Callback to enable / disable the CSC */
77	void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, bool enable);
78
79	/* Callback to configure the video timings in the HDMI block */
80	void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
81			    struct drm_display_mode *mode);
82
83	/* Callback to initialize the PHY according to the mode */
84	void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
85			 struct drm_display_mode *mode);
86
87	/* Callback to disable the PHY */
88	void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
89
90	/* Callback to enable the RNG in the PHY */
91	void (*phy_rng_enable)(struct vc4_hdmi *vc4_hdmi);
92
93	/* Callback to disable the RNG in the PHY */
94	void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi);
95
96	/* Callback to get channel map */
97	u32 (*channel_map)(struct vc4_hdmi *vc4_hdmi, u32 channel_mask);
98};
99
100/* HDMI audio information */
101struct vc4_hdmi_audio {
102	struct snd_soc_card card;
103	struct snd_soc_dai_link link;
104	struct snd_soc_dai_link_component cpu;
105	struct snd_soc_dai_link_component codec;
106	struct snd_soc_dai_link_component platform;
107	int samplerate;
108	int channels;
109	struct snd_dmaengine_dai_dma_data dma_data;
110	struct snd_pcm_substream *substream;
111
112	bool streaming;
113};
114
115/* General HDMI hardware state. */
116struct vc4_hdmi {
117	struct vc4_hdmi_audio audio;
118
119	struct platform_device *pdev;
120	const struct vc4_hdmi_variant *variant;
121
122	struct vc4_hdmi_encoder encoder;
123	struct drm_connector connector;
124
125	struct i2c_adapter *ddc;
126	void __iomem *hdmicore_regs;
127	void __iomem *hd_regs;
128
129	/* VC5 Only */
130	void __iomem *cec_regs;
131	/* VC5 Only */
132	void __iomem *csc_regs;
133	/* VC5 Only */
134	void __iomem *dvp_regs;
135	/* VC5 Only */
136	void __iomem *phy_regs;
137	/* VC5 Only */
138	void __iomem *ram_regs;
139	/* VC5 Only */
140	void __iomem *rm_regs;
141
142	int hpd_gpio;
143	bool hpd_active_low;
144
145	/*
146	 * On some systems (like the RPi4), some modes are in the same
147	 * frequency range than the WiFi channels (1440p@60Hz for
148	 * example). Should we take evasive actions because that system
149	 * has a wifi adapter?
150	 */
151	bool disable_wifi_frequencies;
152
153	struct cec_adapter *cec_adap;
154	struct cec_msg cec_rx_msg;
155	bool cec_tx_ok;
156	bool cec_irq_was_rx;
157
158	struct clk *pixel_clock;
159	struct clk *hsm_clock;
160	struct clk *audio_clock;
161	struct clk *pixel_bvb_clock;
162
163	struct reset_control *reset;
164
165	struct debugfs_regset32 hdmi_regset;
166	struct debugfs_regset32 hd_regset;
167};
168
169static inline struct vc4_hdmi *
170connector_to_vc4_hdmi(struct drm_connector *connector)
171{
172	return container_of(connector, struct vc4_hdmi, connector);
173}
174
175static inline struct vc4_hdmi *
176encoder_to_vc4_hdmi(struct drm_encoder *encoder)
177{
178	struct vc4_hdmi_encoder *_encoder = to_vc4_hdmi_encoder(encoder);
179
180	return container_of(_encoder, struct vc4_hdmi, encoder);
181}
182
183void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
184		       struct drm_display_mode *mode);
185void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
186void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
187void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
188
189void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
190		       struct drm_display_mode *mode);
191void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
192void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
193void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
194
195#endif /* _VC4_HDMI_H_ */
196