drm/vc4: add extcon hdmi connection uevent
[platform/kernel/linux-rpi.git] / drivers / gpu / drm / vc4 / vc4_hdmi.h
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 struct vc4_hdmi;
12 struct vc4_hdmi_register;
13 struct vc4_hdmi_connector_state;
14
15 #ifdef CONFIG_EXTCON
16 struct extcon_dev;
17 #endif
18
19 enum vc4_hdmi_phy_channel {
20         PHY_LANE_0 = 0,
21         PHY_LANE_1,
22         PHY_LANE_2,
23         PHY_LANE_CK,
24 };
25
26 struct vc4_hdmi_variant {
27         /* Encoder Type for that controller */
28         enum vc4_encoder_type encoder_type;
29
30         /* ALSA card name */
31         const char *card_name;
32
33         /* Filename to expose the registers in debugfs */
34         const char *debugfs_name;
35
36         /* Maximum pixel clock supported by the controller (in Hz) */
37         unsigned long long max_pixel_clock;
38
39         /* List of the registers available on that variant */
40         const struct vc4_hdmi_register *registers;
41
42         /* Number of registers on that variant */
43         unsigned int num_registers;
44
45         /* BCM2711 Only.
46          * The variants don't map the lane in the same order in the
47          * PHY, so this is an array mapping the HDMI channel (index)
48          * to the PHY lane (value).
49          */
50         enum vc4_hdmi_phy_channel phy_lane_mapping[4];
51
52         /* The BCM2711 cannot deal with odd horizontal pixel timings */
53         bool unsupported_odd_h_timings;
54
55         /*
56          * The BCM2711 CEC/hotplug IRQ controller is shared between the
57          * two HDMI controllers, and we have a proper irqchip driver for
58          * it.
59          */
60         bool external_irq_controller;
61
62         /* Callback to get the resources (memory region, interrupts,
63          * clocks, etc) for that variant.
64          */
65         int (*init_resources)(struct drm_device *drm,
66                               struct vc4_hdmi *vc4_hdmi);
67
68         /* Callback to reset the HDMI block */
69         void (*reset)(struct vc4_hdmi *vc4_hdmi);
70
71         /* Callback to enable / disable the CSC */
72         void (*csc_setup)(struct vc4_hdmi *vc4_hdmi,
73                           struct drm_connector_state *state,
74                           const struct drm_display_mode *mode);
75
76         /* Callback to configure the video timings in the HDMI block */
77         void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
78                             struct drm_connector_state *state,
79                             const struct drm_display_mode *mode);
80
81         /* Callback to initialize the PHY according to the connector state */
82         void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
83                          struct vc4_hdmi_connector_state *vc4_conn_state);
84
85         /* Callback to disable the PHY */
86         void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
87
88         /* Callback to enable the RNG in the PHY */
89         void (*phy_rng_enable)(struct vc4_hdmi *vc4_hdmi);
90
91         /* Callback to disable the RNG in the PHY */
92         void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi);
93
94         /* Callback to get channel map */
95         u32 (*channel_map)(struct vc4_hdmi *vc4_hdmi, u32 channel_mask);
96
97         /* Enables HDR metadata */
98         bool supports_hdr;
99
100         /* Callback for hardware specific hotplug detect */
101         bool (*hp_detect)(struct vc4_hdmi *vc4_hdmi);
102 };
103
104 /* HDMI audio information */
105 struct vc4_hdmi_audio {
106         struct snd_soc_card card;
107         struct snd_soc_dai_link link;
108         struct snd_soc_dai_link_component cpu;
109         struct snd_soc_dai_link_component codec;
110         struct snd_soc_dai_link_component platform;
111         struct snd_dmaengine_dai_dma_data dma_data;
112         struct hdmi_audio_infoframe infoframe;
113         struct platform_device *codec_pdev;
114         bool streaming;
115 };
116
117 enum vc4_hdmi_output_format {
118         VC4_HDMI_OUTPUT_AUTO,
119         VC4_HDMI_OUTPUT_RGB,
120         VC4_HDMI_OUTPUT_YUV422,
121         VC4_HDMI_OUTPUT_YUV444,
122         VC4_HDMI_OUTPUT_YUV420,
123 };
124
125 /* General HDMI hardware state. */
126 struct vc4_hdmi {
127         struct vc4_hdmi_audio audio;
128
129         struct platform_device *pdev;
130         const struct vc4_hdmi_variant *variant;
131
132         struct vc4_encoder encoder;
133         struct drm_connector connector;
134
135         struct delayed_work scrambling_work;
136
137         struct drm_property *broadcast_rgb_property;
138         struct drm_property *output_format_property;
139
140         struct i2c_adapter *ddc;
141         void __iomem *hdmicore_regs;
142         void __iomem *hd_regs;
143
144         /* VC5 Only */
145         void __iomem *cec_regs;
146         /* VC5 Only */
147         void __iomem *csc_regs;
148         /* VC5 Only */
149         void __iomem *dvp_regs;
150         /* VC5 Only */
151         void __iomem *phy_regs;
152         /* VC5 Only */
153         void __iomem *ram_regs;
154         /* VC5 Only */
155         void __iomem *rm_regs;
156
157         struct gpio_desc *hpd_gpio;
158
159         /*
160          * On some systems (like the RPi4), some modes are in the same
161          * frequency range than the WiFi channels (1440p@60Hz for
162          * example). Should we take evasive actions because that system
163          * has a wifi adapter?
164          */
165         bool disable_wifi_frequencies;
166
167         struct cec_adapter *cec_adap;
168         struct cec_msg cec_rx_msg;
169         bool cec_tx_ok;
170         bool cec_irq_was_rx;
171
172         struct clk *cec_clock;
173         struct clk *pixel_clock;
174         struct clk *hsm_clock;
175         struct clk *audio_clock;
176         struct clk *pixel_bvb_clock;
177
178         struct reset_control *reset;
179
180         struct debugfs_regset32 hdmi_regset;
181         struct debugfs_regset32 hd_regset;
182
183         /**
184          * @hw_lock: Spinlock protecting device register access.
185          */
186         spinlock_t hw_lock;
187
188         /**
189          * @mutex: Mutex protecting the driver access across multiple
190          * frameworks (KMS, ALSA, CEC).
191          */
192         struct mutex mutex;
193
194         /**
195          * @saved_adjusted_mode: Copy of @drm_crtc_state.adjusted_mode
196          * for use by ALSA hooks and interrupt handlers. Protected by @mutex.
197          */
198         struct drm_display_mode saved_adjusted_mode;
199
200         /**
201          * @output_enabled: Is the HDMI controller currently active?
202          * Protected by @mutex.
203          */
204         bool output_enabled;
205
206         /**
207          * @scdc_enabled: Is the HDMI controller currently running with
208          * the scrambler on? Protected by @mutex.
209          */
210         bool scdc_enabled;
211
212         /**
213          * @output_bpc: Copy of @vc4_connector_state.output_bpc for use
214          * outside of KMS hooks. Protected by @mutex.
215          */
216         unsigned int output_bpc;
217
218         /**
219          * @output_format: Copy of @vc4_connector_state.output_format
220          * for use outside of KMS hooks. Protected by @mutex.
221          */
222         enum vc4_hdmi_output_format output_format;
223         /**
224          * @requested_output_format: Copy of @vc4_connector_state.requested_output_format
225          * for use outside of KMS hooks. Protected by @mutex.
226          */
227         enum vc4_hdmi_output_format requested_output_format;
228
229         /**
230          * @broadcast_rgb: Copy of @vc4_connector_state.broadcast_rgb
231          * for use outside of KMS hooks. Protected by @mutex.
232          */
233         int broadcast_rgb;
234
235         /* VC5 debugfs regset */
236         struct debugfs_regset32 cec_regset;
237         struct debugfs_regset32 csc_regset;
238         struct debugfs_regset32 dvp_regset;
239         struct debugfs_regset32 phy_regset;
240         struct debugfs_regset32 ram_regset;
241         struct debugfs_regset32 rm_regset;
242
243 #ifdef CONFIG_EXTCON
244         enum drm_connector_status status;
245         struct extcon_dev *edev;
246 #endif
247 };
248
249 static inline struct vc4_hdmi *
250 connector_to_vc4_hdmi(struct drm_connector *connector)
251 {
252         return container_of(connector, struct vc4_hdmi, connector);
253 }
254
255 static inline struct vc4_hdmi *
256 encoder_to_vc4_hdmi(struct drm_encoder *encoder)
257 {
258         struct vc4_encoder *_encoder = to_vc4_encoder(encoder);
259         return container_of(_encoder, struct vc4_hdmi, encoder);
260 }
261
262 struct vc4_hdmi_connector_state {
263         struct drm_connector_state      base;
264         unsigned long long              pixel_rate;
265         unsigned int                    output_bpc;
266         enum vc4_hdmi_output_format     output_format;
267         enum vc4_hdmi_output_format     requested_output_format;
268         int                             broadcast_rgb;
269 };
270
271 static inline struct vc4_hdmi_connector_state *
272 conn_state_to_vc4_hdmi_conn_state(struct drm_connector_state *conn_state)
273 {
274         return container_of(conn_state, struct vc4_hdmi_connector_state, base);
275 }
276
277 static inline const struct vc4_hdmi_connector_state *
278 const_conn_state_to_vc4_hdmi_conn_state(const struct drm_connector_state *conn_state)
279 {
280         return container_of(conn_state, struct vc4_hdmi_connector_state, base);
281 }
282
283 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
284                        struct vc4_hdmi_connector_state *vc4_conn_state);
285 void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
286 void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
287 void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
288
289 void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
290                        struct vc4_hdmi_connector_state *vc4_conn_state);
291 void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
292 void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
293 void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
294
295 #endif /* _VC4_HDMI_H_ */