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