forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-11 04dd17822334871b23ea2862f7798fb0e0007777
kernel/drivers/gpu/drm/vc4/vc4_hdmi.c
....@@ -1,20 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2015 Broadcom
34 * Copyright (c) 2014 The Linux Foundation. All rights reserved.
45 * Copyright (C) 2013 Red Hat
56 * Author: Rob Clark <robdclark@gmail.com>
6
- *
7
- * This program is free software; you can redistribute it and/or modify it
8
- * under the terms of the GNU General Public License version 2 as published by
9
- * the Free Software Foundation.
10
- *
11
- * This program is distributed in the hope that it will be useful, but WITHOUT
12
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14
- * more details.
15
- *
16
- * You should have received a copy of the GNU General Public License along with
17
- * this program. If not, see <http://www.gnu.org/licenses/>.
187 */
198
209 /**
....@@ -43,8 +32,9 @@
4332 */
4433
4534 #include <drm/drm_atomic_helper.h>
46
-#include <drm/drm_crtc_helper.h>
4735 #include <drm/drm_edid.h>
36
+#include <drm/drm_probe_helper.h>
37
+#include <drm/drm_simple_kms_helper.h>
4838 #include <linux/clk.h>
4939 #include <linux/component.h>
5040 #include <linux/i2c.h>
....@@ -53,206 +43,141 @@
5343 #include <linux/of_platform.h>
5444 #include <linux/pm_runtime.h>
5545 #include <linux/rational.h>
46
+#include <linux/reset.h>
5647 #include <sound/dmaengine_pcm.h>
5748 #include <sound/pcm_drm_eld.h>
5849 #include <sound/pcm_params.h>
5950 #include <sound/soc.h>
6051 #include "media/cec.h"
6152 #include "vc4_drv.h"
53
+#include "vc4_hdmi.h"
54
+#include "vc4_hdmi_regs.h"
6255 #include "vc4_regs.h"
6356
64
-#define HSM_CLOCK_FREQ 163682864
57
+#define VC5_HDMI_HORZA_HFP_SHIFT 16
58
+#define VC5_HDMI_HORZA_HFP_MASK VC4_MASK(28, 16)
59
+#define VC5_HDMI_HORZA_VPOS BIT(15)
60
+#define VC5_HDMI_HORZA_HPOS BIT(14)
61
+#define VC5_HDMI_HORZA_HAP_SHIFT 0
62
+#define VC5_HDMI_HORZA_HAP_MASK VC4_MASK(13, 0)
63
+
64
+#define VC5_HDMI_HORZB_HBP_SHIFT 16
65
+#define VC5_HDMI_HORZB_HBP_MASK VC4_MASK(26, 16)
66
+#define VC5_HDMI_HORZB_HSP_SHIFT 0
67
+#define VC5_HDMI_HORZB_HSP_MASK VC4_MASK(10, 0)
68
+
69
+#define VC5_HDMI_VERTA_VSP_SHIFT 24
70
+#define VC5_HDMI_VERTA_VSP_MASK VC4_MASK(28, 24)
71
+#define VC5_HDMI_VERTA_VFP_SHIFT 16
72
+#define VC5_HDMI_VERTA_VFP_MASK VC4_MASK(22, 16)
73
+#define VC5_HDMI_VERTA_VAL_SHIFT 0
74
+#define VC5_HDMI_VERTA_VAL_MASK VC4_MASK(12, 0)
75
+
76
+#define VC5_HDMI_VERTB_VSPO_SHIFT 16
77
+#define VC5_HDMI_VERTB_VSPO_MASK VC4_MASK(29, 16)
78
+
79
+# define VC4_HD_M_SW_RST BIT(2)
80
+# define VC4_HD_M_ENABLE BIT(0)
81
+
82
+#define HSM_MIN_CLOCK_FREQ 120000000
6583 #define CEC_CLOCK_FREQ 40000
66
-#define CEC_CLOCK_DIV (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ)
84
+#define VC4_HSM_MID_CLOCK 149985000
6785
68
-/* HDMI audio information */
69
-struct vc4_hdmi_audio {
70
- struct snd_soc_card card;
71
- struct snd_soc_dai_link link;
72
- int samplerate;
73
- int channels;
74
- struct snd_dmaengine_dai_dma_data dma_data;
75
- struct snd_pcm_substream *substream;
76
-};
86
+#define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000)
7787
78
-/* General HDMI hardware state. */
79
-struct vc4_hdmi {
80
- struct platform_device *pdev;
81
-
82
- struct drm_encoder *encoder;
83
- struct drm_connector *connector;
84
-
85
- struct vc4_hdmi_audio audio;
86
-
87
- struct i2c_adapter *ddc;
88
- void __iomem *hdmicore_regs;
89
- void __iomem *hd_regs;
90
- int hpd_gpio;
91
- bool hpd_active_low;
92
-
93
- struct cec_adapter *cec_adap;
94
- struct cec_msg cec_rx_msg;
95
- bool cec_tx_ok;
96
- bool cec_irq_was_rx;
97
-
98
- struct clk *pixel_clock;
99
- struct clk *hsm_clock;
100
-};
101
-
102
-#define HDMI_READ(offset) readl(vc4->hdmi->hdmicore_regs + offset)
103
-#define HDMI_WRITE(offset, val) writel(val, vc4->hdmi->hdmicore_regs + offset)
104
-#define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
105
-#define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
106
-
107
-/* VC4 HDMI encoder KMS struct */
108
-struct vc4_hdmi_encoder {
109
- struct vc4_encoder base;
110
- bool hdmi_monitor;
111
- bool limited_rgb_range;
112
- bool rgb_range_selectable;
113
-};
114
-
115
-static inline struct vc4_hdmi_encoder *
116
-to_vc4_hdmi_encoder(struct drm_encoder *encoder)
117
-{
118
- return container_of(encoder, struct vc4_hdmi_encoder, base.base);
119
-}
120
-
121
-/* VC4 HDMI connector KMS struct */
122
-struct vc4_hdmi_connector {
123
- struct drm_connector base;
124
-
125
- /* Since the connector is attached to just the one encoder,
126
- * this is the reference to it so we can do the best_encoder()
127
- * hook.
128
- */
129
- struct drm_encoder *encoder;
130
-};
131
-
132
-static inline struct vc4_hdmi_connector *
133
-to_vc4_hdmi_connector(struct drm_connector *connector)
134
-{
135
- return container_of(connector, struct vc4_hdmi_connector, base);
136
-}
137
-
138
-#define HDMI_REG(reg) { reg, #reg }
139
-static const struct {
140
- u32 reg;
141
- const char *name;
142
-} hdmi_regs[] = {
143
- HDMI_REG(VC4_HDMI_CORE_REV),
144
- HDMI_REG(VC4_HDMI_SW_RESET_CONTROL),
145
- HDMI_REG(VC4_HDMI_HOTPLUG_INT),
146
- HDMI_REG(VC4_HDMI_HOTPLUG),
147
- HDMI_REG(VC4_HDMI_MAI_CHANNEL_MAP),
148
- HDMI_REG(VC4_HDMI_MAI_CONFIG),
149
- HDMI_REG(VC4_HDMI_MAI_FORMAT),
150
- HDMI_REG(VC4_HDMI_AUDIO_PACKET_CONFIG),
151
- HDMI_REG(VC4_HDMI_RAM_PACKET_CONFIG),
152
- HDMI_REG(VC4_HDMI_HORZA),
153
- HDMI_REG(VC4_HDMI_HORZB),
154
- HDMI_REG(VC4_HDMI_FIFO_CTL),
155
- HDMI_REG(VC4_HDMI_SCHEDULER_CONTROL),
156
- HDMI_REG(VC4_HDMI_VERTA0),
157
- HDMI_REG(VC4_HDMI_VERTA1),
158
- HDMI_REG(VC4_HDMI_VERTB0),
159
- HDMI_REG(VC4_HDMI_VERTB1),
160
- HDMI_REG(VC4_HDMI_TX_PHY_RESET_CTL),
161
- HDMI_REG(VC4_HDMI_TX_PHY_CTL0),
162
-
163
- HDMI_REG(VC4_HDMI_CEC_CNTRL_1),
164
- HDMI_REG(VC4_HDMI_CEC_CNTRL_2),
165
- HDMI_REG(VC4_HDMI_CEC_CNTRL_3),
166
- HDMI_REG(VC4_HDMI_CEC_CNTRL_4),
167
- HDMI_REG(VC4_HDMI_CEC_CNTRL_5),
168
- HDMI_REG(VC4_HDMI_CPU_STATUS),
169
- HDMI_REG(VC4_HDMI_CPU_MASK_STATUS),
170
-
171
- HDMI_REG(VC4_HDMI_CEC_RX_DATA_1),
172
- HDMI_REG(VC4_HDMI_CEC_RX_DATA_2),
173
- HDMI_REG(VC4_HDMI_CEC_RX_DATA_3),
174
- HDMI_REG(VC4_HDMI_CEC_RX_DATA_4),
175
- HDMI_REG(VC4_HDMI_CEC_TX_DATA_1),
176
- HDMI_REG(VC4_HDMI_CEC_TX_DATA_2),
177
- HDMI_REG(VC4_HDMI_CEC_TX_DATA_3),
178
- HDMI_REG(VC4_HDMI_CEC_TX_DATA_4),
179
-};
180
-
181
-static const struct {
182
- u32 reg;
183
- const char *name;
184
-} hd_regs[] = {
185
- HDMI_REG(VC4_HD_M_CTL),
186
- HDMI_REG(VC4_HD_MAI_CTL),
187
- HDMI_REG(VC4_HD_MAI_THR),
188
- HDMI_REG(VC4_HD_MAI_FMT),
189
- HDMI_REG(VC4_HD_MAI_SMP),
190
- HDMI_REG(VC4_HD_VID_CTL),
191
- HDMI_REG(VC4_HD_CSC_CTL),
192
- HDMI_REG(VC4_HD_FRAME_COUNT),
193
-};
194
-
195
-#ifdef CONFIG_DEBUG_FS
196
-int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
88
+static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
19789 {
19890 struct drm_info_node *node = (struct drm_info_node *)m->private;
199
- struct drm_device *dev = node->minor->dev;
200
- struct vc4_dev *vc4 = to_vc4_dev(dev);
201
- int i;
91
+ struct vc4_hdmi *vc4_hdmi = node->info_ent->data;
92
+ struct drm_printer p = drm_seq_file_printer(m);
20293
203
- for (i = 0; i < ARRAY_SIZE(hdmi_regs); i++) {
204
- seq_printf(m, "%s (0x%04x): 0x%08x\n",
205
- hdmi_regs[i].name, hdmi_regs[i].reg,
206
- HDMI_READ(hdmi_regs[i].reg));
207
- }
208
-
209
- for (i = 0; i < ARRAY_SIZE(hd_regs); i++) {
210
- seq_printf(m, "%s (0x%04x): 0x%08x\n",
211
- hd_regs[i].name, hd_regs[i].reg,
212
- HD_READ(hd_regs[i].reg));
213
- }
94
+ drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
95
+ drm_print_regset32(&p, &vc4_hdmi->hd_regset);
21496
21597 return 0;
21698 }
217
-#endif /* CONFIG_DEBUG_FS */
21899
219
-static void vc4_hdmi_dump_regs(struct drm_device *dev)
100
+static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
220101 {
221
- struct vc4_dev *vc4 = to_vc4_dev(dev);
222
- int i;
102
+ HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
103
+ udelay(1);
104
+ HDMI_WRITE(HDMI_M_CTL, 0);
223105
224
- for (i = 0; i < ARRAY_SIZE(hdmi_regs); i++) {
225
- DRM_INFO("0x%04x (%s): 0x%08x\n",
226
- hdmi_regs[i].reg, hdmi_regs[i].name,
227
- HDMI_READ(hdmi_regs[i].reg));
228
- }
229
- for (i = 0; i < ARRAY_SIZE(hd_regs); i++) {
230
- DRM_INFO("0x%04x (%s): 0x%08x\n",
231
- hd_regs[i].reg, hd_regs[i].name,
232
- HD_READ(hd_regs[i].reg));
233
- }
106
+ HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
107
+
108
+ HDMI_WRITE(HDMI_SW_RESET_CONTROL,
109
+ VC4_HDMI_SW_RESET_HDMI |
110
+ VC4_HDMI_SW_RESET_FORMAT_DETECT);
111
+
112
+ HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
234113 }
114
+
115
+static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
116
+{
117
+ reset_control_reset(vc4_hdmi->reset);
118
+
119
+ HDMI_WRITE(HDMI_DVP_CTL, 0);
120
+
121
+ HDMI_WRITE(HDMI_CLOCK_STOP,
122
+ HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL);
123
+}
124
+
125
+#ifdef CONFIG_DRM_VC4_HDMI_CEC
126
+static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi)
127
+{
128
+ u16 clk_cnt;
129
+ u32 value;
130
+
131
+ value = HDMI_READ(HDMI_CEC_CNTRL_1);
132
+ value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
133
+
134
+ /*
135
+ * Set the clock divider: the hsm_clock rate and this divider
136
+ * setting will give a 40 kHz CEC clock.
137
+ */
138
+ clk_cnt = clk_get_rate(vc4_hdmi->hsm_clock) / CEC_CLOCK_FREQ;
139
+ value |= clk_cnt << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT;
140
+ HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
141
+}
142
+#else
143
+static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {}
144
+#endif
235145
236146 static enum drm_connector_status
237147 vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
238148 {
239
- struct drm_device *dev = connector->dev;
240
- struct vc4_dev *vc4 = to_vc4_dev(dev);
149
+ struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
150
+ bool connected = false;
241151
242
- if (vc4->hdmi->hpd_gpio) {
243
- if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio) ^
244
- vc4->hdmi->hpd_active_low)
245
- return connector_status_connected;
246
- cec_phys_addr_invalidate(vc4->hdmi->cec_adap);
247
- return connector_status_disconnected;
152
+ WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev));
153
+
154
+ if (vc4_hdmi->hpd_gpio) {
155
+ if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^
156
+ vc4_hdmi->hpd_active_low)
157
+ connected = true;
158
+ } else if (drm_probe_ddc(vc4_hdmi->ddc)) {
159
+ connected = true;
160
+ } else if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) {
161
+ connected = true;
248162 }
249163
250
- if (drm_probe_ddc(vc4->hdmi->ddc))
251
- return connector_status_connected;
164
+ if (connected) {
165
+ if (connector->status != connector_status_connected) {
166
+ struct edid *edid = drm_get_edid(connector, vc4_hdmi->ddc);
252167
253
- if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
168
+ if (edid) {
169
+ cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid);
170
+ vc4_hdmi->encoder.hdmi_monitor = drm_detect_hdmi_monitor(edid);
171
+ kfree(edid);
172
+ }
173
+ }
174
+
175
+ pm_runtime_put(&vc4_hdmi->pdev->dev);
254176 return connector_status_connected;
255
- cec_phys_addr_invalidate(vc4->hdmi->cec_adap);
177
+ }
178
+
179
+ cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
180
+ pm_runtime_put(&vc4_hdmi->pdev->dev);
256181 return connector_status_disconnected;
257182 }
258183
....@@ -264,26 +189,17 @@
264189
265190 static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
266191 {
267
- struct vc4_hdmi_connector *vc4_connector =
268
- to_vc4_hdmi_connector(connector);
269
- struct drm_encoder *encoder = vc4_connector->encoder;
270
- struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
271
- struct drm_device *dev = connector->dev;
272
- struct vc4_dev *vc4 = to_vc4_dev(dev);
192
+ struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
193
+ struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder;
273194 int ret = 0;
274195 struct edid *edid;
275196
276
- edid = drm_get_edid(connector, vc4->hdmi->ddc);
277
- cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
197
+ edid = drm_get_edid(connector, vc4_hdmi->ddc);
198
+ cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid);
278199 if (!edid)
279200 return -ENODEV;
280201
281202 vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
282
-
283
- if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
284
- vc4_encoder->rgb_range_selectable =
285
- drm_rgb_quant_range_selectable(edid);
286
- }
287203
288204 drm_connector_update_edid_property(connector, edid);
289205 ret = drm_add_edid_modes(connector, edid);
....@@ -292,11 +208,19 @@
292208 return ret;
293209 }
294210
211
+static void vc4_hdmi_connector_reset(struct drm_connector *connector)
212
+{
213
+ drm_atomic_helper_connector_reset(connector);
214
+
215
+ if (connector->state)
216
+ drm_atomic_helper_connector_tv_reset(connector);
217
+}
218
+
295219 static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
296220 .detect = vc4_hdmi_connector_detect,
297221 .fill_modes = drm_helper_probe_single_connector_modes,
298222 .destroy = vc4_hdmi_connector_destroy,
299
- .reset = drm_atomic_helper_connector_reset,
223
+ .reset = vc4_hdmi_connector_reset,
300224 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
301225 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
302226 };
....@@ -305,23 +229,25 @@
305229 .get_modes = vc4_hdmi_connector_get_modes,
306230 };
307231
308
-static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
309
- struct drm_encoder *encoder)
232
+static int vc4_hdmi_connector_init(struct drm_device *dev,
233
+ struct vc4_hdmi *vc4_hdmi)
310234 {
311
- struct drm_connector *connector;
312
- struct vc4_hdmi_connector *hdmi_connector;
235
+ struct drm_connector *connector = &vc4_hdmi->connector;
236
+ struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
237
+ int ret;
313238
314
- hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector),
315
- GFP_KERNEL);
316
- if (!hdmi_connector)
317
- return ERR_PTR(-ENOMEM);
318
- connector = &hdmi_connector->base;
319
-
320
- hdmi_connector->encoder = encoder;
321
-
322
- drm_connector_init(dev, connector, &vc4_hdmi_connector_funcs,
323
- DRM_MODE_CONNECTOR_HDMIA);
239
+ drm_connector_init_with_ddc(dev, connector,
240
+ &vc4_hdmi_connector_funcs,
241
+ DRM_MODE_CONNECTOR_HDMIA,
242
+ vc4_hdmi->ddc);
324243 drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
244
+
245
+ /* Create and attach TV margin props to this connector. */
246
+ ret = drm_mode_create_tv_margin_properties(dev);
247
+ if (ret)
248
+ return ret;
249
+
250
+ drm_connector_attach_tv_margin_properties(connector);
325251
326252 connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
327253 DRM_CONNECTOR_POLL_DISCONNECT);
....@@ -331,44 +257,37 @@
331257
332258 drm_connector_attach_encoder(connector, encoder);
333259
334
- return connector;
260
+ return 0;
335261 }
336
-
337
-static void vc4_hdmi_encoder_destroy(struct drm_encoder *encoder)
338
-{
339
- drm_encoder_cleanup(encoder);
340
-}
341
-
342
-static const struct drm_encoder_funcs vc4_hdmi_encoder_funcs = {
343
- .destroy = vc4_hdmi_encoder_destroy,
344
-};
345262
346263 static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
347264 enum hdmi_infoframe_type type)
348265 {
349
- struct drm_device *dev = encoder->dev;
350
- struct vc4_dev *vc4 = to_vc4_dev(dev);
266
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
351267 u32 packet_id = type - 0x80;
352268
353
- HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
354
- HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
269
+ HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
270
+ HDMI_READ(HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
355271
356
- return wait_for(!(HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
272
+ return wait_for(!(HDMI_READ(HDMI_RAM_PACKET_STATUS) &
357273 BIT(packet_id)), 100);
358274 }
359275
360276 static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
361277 union hdmi_infoframe *frame)
362278 {
363
- struct drm_device *dev = encoder->dev;
364
- struct vc4_dev *vc4 = to_vc4_dev(dev);
279
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
365280 u32 packet_id = frame->any.type - 0x80;
366
- u32 packet_reg = VC4_HDMI_RAM_PACKET(packet_id);
281
+ const struct vc4_hdmi_register *ram_packet_start =
282
+ &vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START];
283
+ u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id;
284
+ void __iomem *base = __vc4_hdmi_get_field_base(vc4_hdmi,
285
+ ram_packet_start->reg);
367286 uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
368287 ssize_t len, i;
369288 int ret;
370289
371
- WARN_ONCE(!(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
290
+ WARN_ONCE(!(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
372291 VC4_HDMI_RAM_PACKET_ENABLE),
373292 "Packet RAM has to be on to store the packet.");
374293
....@@ -383,23 +302,23 @@
383302 }
384303
385304 for (i = 0; i < len; i += 7) {
386
- HDMI_WRITE(packet_reg,
387
- buffer[i + 0] << 0 |
388
- buffer[i + 1] << 8 |
389
- buffer[i + 2] << 16);
305
+ writel(buffer[i + 0] << 0 |
306
+ buffer[i + 1] << 8 |
307
+ buffer[i + 2] << 16,
308
+ base + packet_reg);
390309 packet_reg += 4;
391310
392
- HDMI_WRITE(packet_reg,
393
- buffer[i + 3] << 0 |
394
- buffer[i + 4] << 8 |
395
- buffer[i + 5] << 16 |
396
- buffer[i + 6] << 24);
311
+ writel(buffer[i + 3] << 0 |
312
+ buffer[i + 4] << 8 |
313
+ buffer[i + 5] << 16 |
314
+ buffer[i + 6] << 24,
315
+ base + packet_reg);
397316 packet_reg += 4;
398317 }
399318
400
- HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
401
- HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
402
- ret = wait_for((HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
319
+ HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
320
+ HDMI_READ(HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
321
+ ret = wait_for((HDMI_READ(HDMI_RAM_PACKET_STATUS) &
403322 BIT(packet_id)), 100);
404323 if (ret)
405324 DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret);
....@@ -407,24 +326,29 @@
407326
408327 static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
409328 {
329
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
410330 struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
331
+ struct drm_connector *connector = &vc4_hdmi->connector;
332
+ struct drm_connector_state *cstate = connector->state;
411333 struct drm_crtc *crtc = encoder->crtc;
412334 const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
413335 union hdmi_infoframe frame;
414336 int ret;
415337
416
- ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
338
+ ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
339
+ connector, mode);
417340 if (ret < 0) {
418341 DRM_ERROR("couldn't fill AVI infoframe\n");
419342 return;
420343 }
421344
422
- drm_hdmi_avi_infoframe_quant_range(&frame.avi, mode,
345
+ drm_hdmi_avi_infoframe_quant_range(&frame.avi,
346
+ connector, mode,
423347 vc4_encoder->limited_rgb_range ?
424348 HDMI_QUANTIZATION_RANGE_LIMITED :
425
- HDMI_QUANTIZATION_RANGE_FULL,
426
- vc4_encoder->rgb_range_selectable,
427
- false);
349
+ HDMI_QUANTIZATION_RANGE_FULL);
350
+
351
+ drm_hdmi_avi_infoframe_bars(&frame.avi, cstate);
428352
429353 vc4_hdmi_write_infoframe(encoder, &frame);
430354 }
....@@ -447,9 +371,7 @@
447371
448372 static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
449373 {
450
- struct drm_device *drm = encoder->dev;
451
- struct vc4_dev *vc4 = drm->dev_private;
452
- struct vc4_hdmi *hdmi = vc4->hdmi;
374
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
453375 union hdmi_infoframe frame;
454376 int ret;
455377
....@@ -458,143 +380,69 @@
458380 frame.audio.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
459381 frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
460382 frame.audio.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
461
- frame.audio.channels = hdmi->audio.channels;
383
+ frame.audio.channels = vc4_hdmi->audio.channels;
462384
463385 vc4_hdmi_write_infoframe(encoder, &frame);
464386 }
465387
466388 static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
467389 {
390
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
391
+
468392 vc4_hdmi_set_avi_infoframe(encoder);
469393 vc4_hdmi_set_spd_infoframe(encoder);
394
+ /*
395
+ * If audio was streaming, then we need to reenabled the audio
396
+ * infoframe here during encoder_enable.
397
+ */
398
+ if (vc4_hdmi->audio.streaming)
399
+ vc4_hdmi_set_audio_infoframe(encoder);
470400 }
471401
472
-static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
402
+static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
473403 {
474
- struct drm_device *dev = encoder->dev;
475
- struct vc4_dev *vc4 = to_vc4_dev(dev);
476
- struct vc4_hdmi *hdmi = vc4->hdmi;
404
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
405
+
406
+ HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
407
+
408
+ HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) |
409
+ VC4_HD_VID_CTL_CLRRGB | VC4_HD_VID_CTL_CLRSYNC);
410
+
411
+ HDMI_WRITE(HDMI_VID_CTL,
412
+ HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX);
413
+}
414
+
415
+static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
416
+{
417
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
477418 int ret;
478419
479
- HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
420
+ if (vc4_hdmi->variant->phy_disable)
421
+ vc4_hdmi->variant->phy_disable(vc4_hdmi);
480422
481
- HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
482
- HD_WRITE(VC4_HD_VID_CTL,
483
- HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
423
+ HDMI_WRITE(HDMI_VID_CTL,
424
+ HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
484425
485
- clk_disable_unprepare(hdmi->pixel_clock);
426
+ clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock);
427
+ clk_disable_unprepare(vc4_hdmi->pixel_clock);
486428
487
- ret = pm_runtime_put(&hdmi->pdev->dev);
429
+ ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
488430 if (ret < 0)
489431 DRM_ERROR("Failed to release power domain: %d\n", ret);
490432 }
491433
492
-static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
434
+static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
493435 {
494
- struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
495
- struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
496
- struct drm_device *dev = encoder->dev;
497
- struct vc4_dev *vc4 = to_vc4_dev(dev);
498
- struct vc4_hdmi *hdmi = vc4->hdmi;
499
- bool debug_dump_regs = false;
500
- bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
501
- bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
502
- bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
503
- u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
504
- u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
505
- VC4_HDMI_VERTA_VSP) |
506
- VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
507
- VC4_HDMI_VERTA_VFP) |
508
- VC4_SET_FIELD(mode->crtc_vdisplay, VC4_HDMI_VERTA_VAL));
509
- u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
510
- VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
511
- VC4_HDMI_VERTB_VBP));
512
- u32 vertb_even = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
513
- VC4_SET_FIELD(mode->crtc_vtotal -
514
- mode->crtc_vsync_end -
515
- interlaced,
516
- VC4_HDMI_VERTB_VBP));
436
+}
437
+
438
+static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
439
+{
517440 u32 csc_ctl;
518
- int ret;
519
-
520
- ret = pm_runtime_get_sync(&hdmi->pdev->dev);
521
- if (ret < 0) {
522
- DRM_ERROR("Failed to retain power domain: %d\n", ret);
523
- return;
524
- }
525
-
526
- ret = clk_set_rate(hdmi->pixel_clock,
527
- mode->clock * 1000 *
528
- ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
529
- if (ret) {
530
- DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
531
- return;
532
- }
533
-
534
- ret = clk_prepare_enable(hdmi->pixel_clock);
535
- if (ret) {
536
- DRM_ERROR("Failed to turn on pixel clock: %d\n", ret);
537
- return;
538
- }
539
-
540
- HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL,
541
- VC4_HDMI_SW_RESET_HDMI |
542
- VC4_HDMI_SW_RESET_FORMAT_DETECT);
543
-
544
- HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL, 0);
545
-
546
- /* PHY should be in reset, like
547
- * vc4_hdmi_encoder_disable() does.
548
- */
549
- HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
550
-
551
- HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0);
552
-
553
- if (debug_dump_regs) {
554
- DRM_INFO("HDMI regs before:\n");
555
- vc4_hdmi_dump_regs(dev);
556
- }
557
-
558
- HD_WRITE(VC4_HD_VID_CTL, 0);
559
-
560
- HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
561
- HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
562
- VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
563
- VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
564
-
565
- HDMI_WRITE(VC4_HDMI_HORZA,
566
- (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
567
- (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
568
- VC4_SET_FIELD(mode->hdisplay * pixel_rep,
569
- VC4_HDMI_HORZA_HAP));
570
-
571
- HDMI_WRITE(VC4_HDMI_HORZB,
572
- VC4_SET_FIELD((mode->htotal -
573
- mode->hsync_end) * pixel_rep,
574
- VC4_HDMI_HORZB_HBP) |
575
- VC4_SET_FIELD((mode->hsync_end -
576
- mode->hsync_start) * pixel_rep,
577
- VC4_HDMI_HORZB_HSP) |
578
- VC4_SET_FIELD((mode->hsync_start -
579
- mode->hdisplay) * pixel_rep,
580
- VC4_HDMI_HORZB_HFP));
581
-
582
- HDMI_WRITE(VC4_HDMI_VERTA0, verta);
583
- HDMI_WRITE(VC4_HDMI_VERTA1, verta);
584
-
585
- HDMI_WRITE(VC4_HDMI_VERTB0, vertb_even);
586
- HDMI_WRITE(VC4_HDMI_VERTB1, vertb);
587
-
588
- HD_WRITE(VC4_HD_VID_CTL,
589
- (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
590
- (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
591441
592442 csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
593443 VC4_HD_CSC_CTL_ORDER);
594444
595
- if (vc4_encoder->hdmi_monitor &&
596
- drm_default_rgb_quant_range(mode) ==
597
- HDMI_QUANTIZATION_RANGE_LIMITED) {
445
+ if (enable) {
598446 /* CEA VICs other than #1 requre limited range RGB
599447 * output unless overridden by an AVI infoframe.
600448 * Apply a colorspace conversion to squash 0-255 down
....@@ -610,94 +458,200 @@
610458 csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
611459 VC4_HD_CSC_CTL_MODE);
612460
613
- HD_WRITE(VC4_HD_CSC_12_11, (0x000 << 16) | 0x000);
614
- HD_WRITE(VC4_HD_CSC_14_13, (0x100 << 16) | 0x6e0);
615
- HD_WRITE(VC4_HD_CSC_22_21, (0x6e0 << 16) | 0x000);
616
- HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000);
617
- HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0);
618
- HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000);
619
- vc4_encoder->limited_rgb_range = true;
620
- } else {
621
- vc4_encoder->limited_rgb_range = false;
461
+ HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
462
+ HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
463
+ HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
464
+ HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
465
+ HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
466
+ HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
622467 }
623468
624469 /* The RGB order applies even when CSC is disabled. */
625
- HD_WRITE(VC4_HD_CSC_CTL, csc_ctl);
626
-
627
- HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
628
-
629
- if (debug_dump_regs) {
630
- DRM_INFO("HDMI regs after:\n");
631
- vc4_hdmi_dump_regs(dev);
632
- }
633
-
634
- HD_WRITE(VC4_HD_VID_CTL,
635
- HD_READ(VC4_HD_VID_CTL) |
636
- VC4_HD_VID_CTL_ENABLE |
637
- VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
638
- VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
639
-
640
- if (vc4_encoder->hdmi_monitor) {
641
- HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
642
- HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
643
- VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
644
-
645
- ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
646
- VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000);
647
- WARN_ONCE(ret, "Timeout waiting for "
648
- "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
649
- } else {
650
- HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
651
- HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
652
- ~(VC4_HDMI_RAM_PACKET_ENABLE));
653
- HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
654
- HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
655
- ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
656
-
657
- ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
658
- VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000);
659
- WARN_ONCE(ret, "Timeout waiting for "
660
- "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
661
- }
662
-
663
- if (vc4_encoder->hdmi_monitor) {
664
- u32 drift;
665
-
666
- WARN_ON(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
667
- VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
668
- HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
669
- HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
670
- VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT);
671
-
672
- HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
673
- VC4_HDMI_RAM_PACKET_ENABLE);
674
-
675
- vc4_hdmi_set_infoframes(encoder);
676
-
677
- drift = HDMI_READ(VC4_HDMI_FIFO_CTL);
678
- drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
679
-
680
- HDMI_WRITE(VC4_HDMI_FIFO_CTL,
681
- drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
682
- HDMI_WRITE(VC4_HDMI_FIFO_CTL,
683
- drift | VC4_HDMI_FIFO_CTL_RECENTER);
684
- usleep_range(1000, 1100);
685
- HDMI_WRITE(VC4_HDMI_FIFO_CTL,
686
- drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
687
- HDMI_WRITE(VC4_HDMI_FIFO_CTL,
688
- drift | VC4_HDMI_FIFO_CTL_RECENTER);
689
-
690
- ret = wait_for(HDMI_READ(VC4_HDMI_FIFO_CTL) &
691
- VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
692
- WARN_ONCE(ret, "Timeout waiting for "
693
- "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
694
- }
470
+ HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
695471 }
696472
697
-static enum drm_mode_status
698
-vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc,
699
- const struct drm_display_mode *mode)
473
+static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
700474 {
475
+ u32 csc_ctl;
476
+
477
+ csc_ctl = 0x07; /* RGB_CONVERT_MODE = custom matrix, || USE_RGB_TO_YCBCR */
478
+
479
+ if (enable) {
480
+ /* CEA VICs other than #1 requre limited range RGB
481
+ * output unless overridden by an AVI infoframe.
482
+ * Apply a colorspace conversion to squash 0-255 down
483
+ * to 16-235. The matrix here is:
484
+ *
485
+ * [ 0.8594 0 0 16]
486
+ * [ 0 0.8594 0 16]
487
+ * [ 0 0 0.8594 16]
488
+ * [ 0 0 0 1]
489
+ * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
490
+ */
491
+ HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x1b80);
492
+ HDMI_WRITE(HDMI_CSC_14_13, (0x0400 << 16) | 0x0000);
493
+ HDMI_WRITE(HDMI_CSC_22_21, (0x1b80 << 16) | 0x0000);
494
+ HDMI_WRITE(HDMI_CSC_24_23, (0x0400 << 16) | 0x0000);
495
+ HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
496
+ HDMI_WRITE(HDMI_CSC_34_33, (0x0400 << 16) | 0x1b80);
497
+ } else {
498
+ /* Still use the matrix for full range, but make it unity.
499
+ * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
500
+ */
501
+ HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x2000);
502
+ HDMI_WRITE(HDMI_CSC_14_13, (0x0000 << 16) | 0x0000);
503
+ HDMI_WRITE(HDMI_CSC_22_21, (0x2000 << 16) | 0x0000);
504
+ HDMI_WRITE(HDMI_CSC_24_23, (0x0000 << 16) | 0x0000);
505
+ HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
506
+ HDMI_WRITE(HDMI_CSC_34_33, (0x0000 << 16) | 0x2000);
507
+ }
508
+
509
+ HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
510
+}
511
+
512
+static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
513
+ struct drm_display_mode *mode)
514
+{
515
+ bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
516
+ bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
517
+ bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
518
+ u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
519
+ u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
520
+ VC4_HDMI_VERTA_VSP) |
521
+ VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
522
+ VC4_HDMI_VERTA_VFP) |
523
+ VC4_SET_FIELD(mode->crtc_vdisplay, VC4_HDMI_VERTA_VAL));
524
+ u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
525
+ VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end +
526
+ interlaced,
527
+ VC4_HDMI_VERTB_VBP));
528
+ u32 vertb_even = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
529
+ VC4_SET_FIELD(mode->crtc_vtotal -
530
+ mode->crtc_vsync_end,
531
+ VC4_HDMI_VERTB_VBP));
532
+
533
+ HDMI_WRITE(HDMI_HORZA,
534
+ (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
535
+ (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
536
+ VC4_SET_FIELD(mode->hdisplay * pixel_rep,
537
+ VC4_HDMI_HORZA_HAP));
538
+
539
+ HDMI_WRITE(HDMI_HORZB,
540
+ VC4_SET_FIELD((mode->htotal -
541
+ mode->hsync_end) * pixel_rep,
542
+ VC4_HDMI_HORZB_HBP) |
543
+ VC4_SET_FIELD((mode->hsync_end -
544
+ mode->hsync_start) * pixel_rep,
545
+ VC4_HDMI_HORZB_HSP) |
546
+ VC4_SET_FIELD((mode->hsync_start -
547
+ mode->hdisplay) * pixel_rep,
548
+ VC4_HDMI_HORZB_HFP));
549
+
550
+ HDMI_WRITE(HDMI_VERTA0, verta);
551
+ HDMI_WRITE(HDMI_VERTA1, verta);
552
+
553
+ HDMI_WRITE(HDMI_VERTB0, vertb_even);
554
+ HDMI_WRITE(HDMI_VERTB1, vertb);
555
+}
556
+static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
557
+ struct drm_display_mode *mode)
558
+{
559
+ bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
560
+ bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
561
+ bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
562
+ u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
563
+ u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
564
+ VC5_HDMI_VERTA_VSP) |
565
+ VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
566
+ VC5_HDMI_VERTA_VFP) |
567
+ VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL));
568
+ u32 vertb = (VC4_SET_FIELD(mode->htotal >> (2 - pixel_rep),
569
+ VC5_HDMI_VERTB_VSPO) |
570
+ VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end +
571
+ interlaced,
572
+ VC4_HDMI_VERTB_VBP));
573
+ u32 vertb_even = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
574
+ VC4_SET_FIELD(mode->crtc_vtotal -
575
+ mode->crtc_vsync_end,
576
+ VC4_HDMI_VERTB_VBP));
577
+
578
+ HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
579
+ HDMI_WRITE(HDMI_HORZA,
580
+ (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) |
581
+ (hsync_pos ? VC5_HDMI_HORZA_HPOS : 0) |
582
+ VC4_SET_FIELD(mode->hdisplay * pixel_rep,
583
+ VC5_HDMI_HORZA_HAP) |
584
+ VC4_SET_FIELD((mode->hsync_start -
585
+ mode->hdisplay) * pixel_rep,
586
+ VC5_HDMI_HORZA_HFP));
587
+
588
+ HDMI_WRITE(HDMI_HORZB,
589
+ VC4_SET_FIELD((mode->htotal -
590
+ mode->hsync_end) * pixel_rep,
591
+ VC5_HDMI_HORZB_HBP) |
592
+ VC4_SET_FIELD((mode->hsync_end -
593
+ mode->hsync_start) * pixel_rep,
594
+ VC5_HDMI_HORZB_HSP));
595
+
596
+ HDMI_WRITE(HDMI_VERTA0, verta);
597
+ HDMI_WRITE(HDMI_VERTA1, verta);
598
+
599
+ HDMI_WRITE(HDMI_VERTB0, vertb_even);
600
+ HDMI_WRITE(HDMI_VERTB1, vertb);
601
+
602
+ HDMI_WRITE(HDMI_CLOCK_STOP, 0);
603
+}
604
+
605
+static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
606
+{
607
+ u32 drift;
608
+ int ret;
609
+
610
+ drift = HDMI_READ(HDMI_FIFO_CTL);
611
+ drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
612
+
613
+ HDMI_WRITE(HDMI_FIFO_CTL,
614
+ drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
615
+ HDMI_WRITE(HDMI_FIFO_CTL,
616
+ drift | VC4_HDMI_FIFO_CTL_RECENTER);
617
+ usleep_range(1000, 1100);
618
+ HDMI_WRITE(HDMI_FIFO_CTL,
619
+ drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
620
+ HDMI_WRITE(HDMI_FIFO_CTL,
621
+ drift | VC4_HDMI_FIFO_CTL_RECENTER);
622
+
623
+ ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
624
+ VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
625
+ WARN_ONCE(ret, "Timeout waiting for "
626
+ "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
627
+}
628
+
629
+static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
630
+{
631
+ struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
632
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
633
+ unsigned long pixel_rate, hsm_rate;
634
+ int ret;
635
+
636
+ ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev);
637
+ if (ret < 0) {
638
+ DRM_ERROR("Failed to retain power domain: %d\n", ret);
639
+ return;
640
+ }
641
+
642
+ pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
643
+ ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
644
+ if (ret) {
645
+ DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
646
+ return;
647
+ }
648
+
649
+ ret = clk_prepare_enable(vc4_hdmi->pixel_clock);
650
+ if (ret) {
651
+ DRM_ERROR("Failed to turn on pixel clock: %d\n", ret);
652
+ return;
653
+ }
654
+
701655 /*
702656 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
703657 * be faster than pixel clock, infinitesimally faster, tested in
....@@ -714,46 +668,244 @@
714668 * Additionally, the AXI clock needs to be at least 25% of
715669 * pixel clock, but HSM ends up being the limiting factor.
716670 */
717
- if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100))
671
+ hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
672
+ ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate);
673
+ if (ret) {
674
+ DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
675
+ return;
676
+ }
677
+
678
+ vc4_hdmi_cec_update_clk_div(vc4_hdmi);
679
+
680
+ /*
681
+ * FIXME: When the pixel freq is 594MHz (4k60), this needs to be setup
682
+ * at 300MHz.
683
+ */
684
+ ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock,
685
+ (hsm_rate > VC4_HSM_MID_CLOCK ? 150000000 : 75000000));
686
+ if (ret) {
687
+ DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret);
688
+ clk_disable_unprepare(vc4_hdmi->pixel_clock);
689
+ return;
690
+ }
691
+
692
+ ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock);
693
+ if (ret) {
694
+ DRM_ERROR("Failed to turn on pixel bvb clock: %d\n", ret);
695
+ clk_disable_unprepare(vc4_hdmi->pixel_clock);
696
+ return;
697
+ }
698
+
699
+ if (vc4_hdmi->variant->phy_init)
700
+ vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
701
+
702
+ HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
703
+ HDMI_READ(HDMI_SCHEDULER_CONTROL) |
704
+ VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
705
+ VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
706
+
707
+ if (vc4_hdmi->variant->set_timings)
708
+ vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
709
+}
710
+
711
+static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
712
+{
713
+ struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
714
+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
715
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
716
+
717
+ if (vc4_encoder->hdmi_monitor &&
718
+ drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {
719
+ if (vc4_hdmi->variant->csc_setup)
720
+ vc4_hdmi->variant->csc_setup(vc4_hdmi, true);
721
+
722
+ vc4_encoder->limited_rgb_range = true;
723
+ } else {
724
+ if (vc4_hdmi->variant->csc_setup)
725
+ vc4_hdmi->variant->csc_setup(vc4_hdmi, false);
726
+
727
+ vc4_encoder->limited_rgb_range = false;
728
+ }
729
+
730
+ HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
731
+}
732
+
733
+static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
734
+{
735
+ struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
736
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
737
+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
738
+ bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
739
+ bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
740
+ int ret;
741
+
742
+ HDMI_WRITE(HDMI_VID_CTL,
743
+ VC4_HD_VID_CTL_ENABLE |
744
+ VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
745
+ VC4_HD_VID_CTL_FRAME_COUNTER_RESET |
746
+ (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
747
+ (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
748
+
749
+ HDMI_WRITE(HDMI_VID_CTL,
750
+ HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_BLANKPIX);
751
+
752
+ if (vc4_encoder->hdmi_monitor) {
753
+ HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
754
+ HDMI_READ(HDMI_SCHEDULER_CONTROL) |
755
+ VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
756
+
757
+ ret = wait_for(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
758
+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000);
759
+ WARN_ONCE(ret, "Timeout waiting for "
760
+ "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
761
+ } else {
762
+ HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
763
+ HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
764
+ ~(VC4_HDMI_RAM_PACKET_ENABLE));
765
+ HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
766
+ HDMI_READ(HDMI_SCHEDULER_CONTROL) &
767
+ ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
768
+
769
+ ret = wait_for(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
770
+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000);
771
+ WARN_ONCE(ret, "Timeout waiting for "
772
+ "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
773
+ }
774
+
775
+ if (vc4_encoder->hdmi_monitor) {
776
+ WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
777
+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
778
+ HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
779
+ HDMI_READ(HDMI_SCHEDULER_CONTROL) |
780
+ VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT);
781
+
782
+ HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
783
+ VC4_HDMI_RAM_PACKET_ENABLE);
784
+
785
+ vc4_hdmi_set_infoframes(encoder);
786
+ }
787
+
788
+ vc4_hdmi_recenter_fifo(vc4_hdmi);
789
+}
790
+
791
+static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
792
+{
793
+}
794
+
795
+#define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL
796
+#define WIFI_2_4GHz_CH1_MAX_FREQ 2422000000ULL
797
+
798
+static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
799
+ struct drm_crtc_state *crtc_state,
800
+ struct drm_connector_state *conn_state)
801
+{
802
+ struct drm_display_mode *mode = &crtc_state->adjusted_mode;
803
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
804
+ unsigned long long pixel_rate = mode->clock * 1000;
805
+ unsigned long long tmds_rate;
806
+
807
+ if (vc4_hdmi->variant->unsupported_odd_h_timings &&
808
+ !(mode->flags & DRM_MODE_FLAG_DBLCLK) &&
809
+ ((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
810
+ (mode->hsync_end % 2) || (mode->htotal % 2)))
811
+ return -EINVAL;
812
+
813
+ /*
814
+ * The 1440p@60 pixel rate is in the same range than the first
815
+ * WiFi channel (between 2.4GHz and 2.422GHz with 22MHz
816
+ * bandwidth). Slightly lower the frequency to bring it out of
817
+ * the WiFi range.
818
+ */
819
+ tmds_rate = pixel_rate * 10;
820
+ if (vc4_hdmi->disable_wifi_frequencies &&
821
+ (tmds_rate >= WIFI_2_4GHz_CH1_MIN_FREQ &&
822
+ tmds_rate <= WIFI_2_4GHz_CH1_MAX_FREQ)) {
823
+ mode->clock = 238560;
824
+ pixel_rate = mode->clock * 1000;
825
+ }
826
+
827
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
828
+ pixel_rate = pixel_rate * 2;
829
+
830
+ if (pixel_rate > vc4_hdmi->variant->max_pixel_clock)
831
+ return -EINVAL;
832
+
833
+ return 0;
834
+}
835
+
836
+static enum drm_mode_status
837
+vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
838
+ const struct drm_display_mode *mode)
839
+{
840
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
841
+
842
+ if (vc4_hdmi->variant->unsupported_odd_h_timings &&
843
+ !(mode->flags & DRM_MODE_FLAG_DBLCLK) &&
844
+ ((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
845
+ (mode->hsync_end % 2) || (mode->htotal % 2)))
846
+ return MODE_H_ILLEGAL;
847
+
848
+ if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock)
718849 return MODE_CLOCK_HIGH;
719850
720851 return MODE_OK;
721852 }
722853
723854 static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
855
+ .atomic_check = vc4_hdmi_encoder_atomic_check,
724856 .mode_valid = vc4_hdmi_encoder_mode_valid,
725857 .disable = vc4_hdmi_encoder_disable,
726858 .enable = vc4_hdmi_encoder_enable,
727859 };
728860
729
-/* HDMI audio codec callbacks */
730
-static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
861
+static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
731862 {
732
- struct drm_device *drm = hdmi->encoder->dev;
733
- struct vc4_dev *vc4 = to_vc4_dev(drm);
734
- u32 hsm_clock = clk_get_rate(hdmi->hsm_clock);
863
+ int i;
864
+ u32 channel_map = 0;
865
+
866
+ for (i = 0; i < 8; i++) {
867
+ if (channel_mask & BIT(i))
868
+ channel_map |= i << (3 * i);
869
+ }
870
+ return channel_map;
871
+}
872
+
873
+static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
874
+{
875
+ int i;
876
+ u32 channel_map = 0;
877
+
878
+ for (i = 0; i < 8; i++) {
879
+ if (channel_mask & BIT(i))
880
+ channel_map |= i << (4 * i);
881
+ }
882
+ return channel_map;
883
+}
884
+
885
+/* HDMI audio codec callbacks */
886
+static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
887
+{
888
+ u32 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock);
735889 unsigned long n, m;
736890
737
- rational_best_approximation(hsm_clock, hdmi->audio.samplerate,
891
+ rational_best_approximation(hsm_clock, vc4_hdmi->audio.samplerate,
738892 VC4_HD_MAI_SMP_N_MASK >>
739893 VC4_HD_MAI_SMP_N_SHIFT,
740894 (VC4_HD_MAI_SMP_M_MASK >>
741895 VC4_HD_MAI_SMP_M_SHIFT) + 1,
742896 &n, &m);
743897
744
- HD_WRITE(VC4_HD_MAI_SMP,
745
- VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
746
- VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
898
+ HDMI_WRITE(HDMI_MAI_SMP,
899
+ VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
900
+ VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
747901 }
748902
749
-static void vc4_hdmi_set_n_cts(struct vc4_hdmi *hdmi)
903
+static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
750904 {
751
- struct drm_encoder *encoder = hdmi->encoder;
905
+ struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
752906 struct drm_crtc *crtc = encoder->crtc;
753
- struct drm_device *drm = encoder->dev;
754
- struct vc4_dev *vc4 = to_vc4_dev(drm);
755907 const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
756
- u32 samplerate = hdmi->audio.samplerate;
908
+ u32 samplerate = vc4_hdmi->audio.samplerate;
757909 u32 n, cts;
758910 u64 tmp;
759911
....@@ -762,7 +914,7 @@
762914 do_div(tmp, 128 * samplerate);
763915 cts = tmp;
764916
765
- HDMI_WRITE(VC4_HDMI_CRP_CFG,
917
+ HDMI_WRITE(HDMI_CRP_CFG,
766918 VC4_HDMI_CRP_CFG_EXTERNAL_CTS_EN |
767919 VC4_SET_FIELD(n, VC4_HDMI_CRP_CFG_N));
768920
....@@ -771,8 +923,8 @@
771923 * providing a CTS_1 value. The two CTS values are alternated
772924 * between based on the period fields
773925 */
774
- HDMI_WRITE(VC4_HDMI_CTS_0, cts);
775
- HDMI_WRITE(VC4_HDMI_CTS_1, cts);
926
+ HDMI_WRITE(HDMI_CTS_0, cts);
927
+ HDMI_WRITE(HDMI_CTS_1, cts);
776928 }
777929
778930 static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai)
....@@ -785,26 +937,25 @@
785937 static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
786938 struct snd_soc_dai *dai)
787939 {
788
- struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
789
- struct drm_encoder *encoder = hdmi->encoder;
790
- struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
940
+ struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
941
+ struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
942
+ struct drm_connector *connector = &vc4_hdmi->connector;
791943 int ret;
792944
793
- if (hdmi->audio.substream && hdmi->audio.substream != substream)
945
+ if (vc4_hdmi->audio.substream && vc4_hdmi->audio.substream != substream)
794946 return -EINVAL;
795947
796
- hdmi->audio.substream = substream;
948
+ vc4_hdmi->audio.substream = substream;
797949
798950 /*
799951 * If the HDMI encoder hasn't probed, or the encoder is
800952 * currently in DVI mode, treat the codec dai as missing.
801953 */
802
- if (!encoder->crtc || !(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
954
+ if (!encoder->crtc || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
803955 VC4_HDMI_RAM_PACKET_ENABLE))
804956 return -ENODEV;
805957
806
- ret = snd_pcm_hw_constraint_eld(substream->runtime,
807
- hdmi->connector->eld);
958
+ ret = snd_pcm_hw_constraint_eld(substream->runtime, connector->eld);
808959 if (ret)
809960 return ret;
810961
....@@ -816,34 +967,33 @@
816967 return 0;
817968 }
818969
819
-static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi)
970
+static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
820971 {
821
- struct drm_encoder *encoder = hdmi->encoder;
822
- struct drm_device *drm = encoder->dev;
823
- struct device *dev = &hdmi->pdev->dev;
824
- struct vc4_dev *vc4 = to_vc4_dev(drm);
972
+ struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
973
+ struct device *dev = &vc4_hdmi->pdev->dev;
825974 int ret;
826975
976
+ vc4_hdmi->audio.streaming = false;
827977 ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO);
828978 if (ret)
829979 dev_err(dev, "Failed to stop audio infoframe: %d\n", ret);
830980
831
- HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_RESET);
832
- HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_ERRORF);
833
- HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
981
+ HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_RESET);
982
+ HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_ERRORF);
983
+ HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
834984 }
835985
836986 static void vc4_hdmi_audio_shutdown(struct snd_pcm_substream *substream,
837987 struct snd_soc_dai *dai)
838988 {
839
- struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
989
+ struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
840990
841
- if (substream != hdmi->audio.substream)
991
+ if (substream != vc4_hdmi->audio.substream)
842992 return;
843993
844
- vc4_hdmi_audio_reset(hdmi);
994
+ vc4_hdmi_audio_reset(vc4_hdmi);
845995
846
- hdmi->audio.substream = NULL;
996
+ vc4_hdmi->audio.substream = NULL;
847997 }
848998
849999 /* HDMI audio codec callbacks */
....@@ -851,72 +1001,58 @@
8511001 struct snd_pcm_hw_params *params,
8521002 struct snd_soc_dai *dai)
8531003 {
854
- struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
855
- struct drm_encoder *encoder = hdmi->encoder;
856
- struct drm_device *drm = encoder->dev;
857
- struct device *dev = &hdmi->pdev->dev;
858
- struct vc4_dev *vc4 = to_vc4_dev(drm);
1004
+ struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
1005
+ struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
1006
+ struct device *dev = &vc4_hdmi->pdev->dev;
8591007 u32 audio_packet_config, channel_mask;
860
- u32 channel_map, i;
1008
+ u32 channel_map;
8611009
862
- if (substream != hdmi->audio.substream)
1010
+ if (substream != vc4_hdmi->audio.substream)
8631011 return -EINVAL;
8641012
8651013 dev_dbg(dev, "%s: %u Hz, %d bit, %d channels\n", __func__,
8661014 params_rate(params), params_width(params),
8671015 params_channels(params));
8681016
869
- hdmi->audio.channels = params_channels(params);
870
- hdmi->audio.samplerate = params_rate(params);
1017
+ vc4_hdmi->audio.channels = params_channels(params);
1018
+ vc4_hdmi->audio.samplerate = params_rate(params);
8711019
872
- HD_WRITE(VC4_HD_MAI_CTL,
873
- VC4_HD_MAI_CTL_RESET |
874
- VC4_HD_MAI_CTL_FLUSH |
875
- VC4_HD_MAI_CTL_DLATE |
876
- VC4_HD_MAI_CTL_ERRORE |
877
- VC4_HD_MAI_CTL_ERRORF);
1020
+ HDMI_WRITE(HDMI_MAI_CTL,
1021
+ VC4_HD_MAI_CTL_RESET |
1022
+ VC4_HD_MAI_CTL_FLUSH |
1023
+ VC4_HD_MAI_CTL_DLATE |
1024
+ VC4_HD_MAI_CTL_ERRORE |
1025
+ VC4_HD_MAI_CTL_ERRORF);
8781026
879
- vc4_hdmi_audio_set_mai_clock(hdmi);
1027
+ vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
8801028
1029
+ /* The B frame identifier should match the value used by alsa-lib (8) */
8811030 audio_packet_config =
8821031 VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT |
8831032 VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS |
884
- VC4_SET_FIELD(0xf, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER);
1033
+ VC4_SET_FIELD(0x8, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER);
8851034
886
- channel_mask = GENMASK(hdmi->audio.channels - 1, 0);
1035
+ channel_mask = GENMASK(vc4_hdmi->audio.channels - 1, 0);
8871036 audio_packet_config |= VC4_SET_FIELD(channel_mask,
8881037 VC4_HDMI_AUDIO_PACKET_CEA_MASK);
8891038
890
- /* Set the MAI threshold. This logic mimics the firmware's. */
891
- if (hdmi->audio.samplerate > 96000) {
892
- HD_WRITE(VC4_HD_MAI_THR,
893
- VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
894
- VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
895
- } else if (hdmi->audio.samplerate > 48000) {
896
- HD_WRITE(VC4_HD_MAI_THR,
897
- VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
898
- VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
899
- } else {
900
- HD_WRITE(VC4_HD_MAI_THR,
901
- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) |
902
- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) |
903
- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) |
904
- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW));
905
- }
1039
+ /* Set the MAI threshold */
1040
+ HDMI_WRITE(HDMI_MAI_THR,
1041
+ VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_PANICHIGH) |
1042
+ VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_PANICLOW) |
1043
+ VC4_SET_FIELD(0x06, VC4_HD_MAI_THR_DREQHIGH) |
1044
+ VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_DREQLOW));
9061045
907
- HDMI_WRITE(VC4_HDMI_MAI_CONFIG,
1046
+ HDMI_WRITE(HDMI_MAI_CONFIG,
9081047 VC4_HDMI_MAI_CONFIG_BIT_REVERSE |
9091048 VC4_SET_FIELD(channel_mask, VC4_HDMI_MAI_CHANNEL_MASK));
9101049
911
- channel_map = 0;
912
- for (i = 0; i < 8; i++) {
913
- if (channel_mask & BIT(i))
914
- channel_map |= i << (3 * i);
915
- }
1050
+ channel_map = vc4_hdmi->variant->channel_map(vc4_hdmi, channel_mask);
1051
+ HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map);
1052
+ HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
1053
+ vc4_hdmi_set_n_cts(vc4_hdmi);
9161054
917
- HDMI_WRITE(VC4_HDMI_MAI_CHANNEL_MAP, channel_map);
918
- HDMI_WRITE(VC4_HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
919
- vc4_hdmi_set_n_cts(hdmi);
1055
+ vc4_hdmi_set_audio_infoframe(encoder);
9201056
9211057 return 0;
9221058 }
....@@ -924,30 +1060,33 @@
9241060 static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
9251061 struct snd_soc_dai *dai)
9261062 {
927
- struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
928
- struct drm_encoder *encoder = hdmi->encoder;
929
- struct drm_device *drm = encoder->dev;
930
- struct vc4_dev *vc4 = to_vc4_dev(drm);
1063
+ struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
9311064
9321065 switch (cmd) {
9331066 case SNDRV_PCM_TRIGGER_START:
934
- vc4_hdmi_set_audio_infoframe(encoder);
935
- HDMI_WRITE(VC4_HDMI_TX_PHY_CTL0,
936
- HDMI_READ(VC4_HDMI_TX_PHY_CTL0) &
937
- ~VC4_HDMI_TX_PHY_RNG_PWRDN);
938
- HD_WRITE(VC4_HD_MAI_CTL,
939
- VC4_SET_FIELD(hdmi->audio.channels,
940
- VC4_HD_MAI_CTL_CHNUM) |
941
- VC4_HD_MAI_CTL_ENABLE);
1067
+ vc4_hdmi->audio.streaming = true;
1068
+
1069
+ if (vc4_hdmi->variant->phy_rng_enable)
1070
+ vc4_hdmi->variant->phy_rng_enable(vc4_hdmi);
1071
+
1072
+ HDMI_WRITE(HDMI_MAI_CTL,
1073
+ VC4_SET_FIELD(vc4_hdmi->audio.channels,
1074
+ VC4_HD_MAI_CTL_CHNUM) |
1075
+ VC4_HD_MAI_CTL_WHOLSMP |
1076
+ VC4_HD_MAI_CTL_CHALIGN |
1077
+ VC4_HD_MAI_CTL_ENABLE);
9421078 break;
9431079 case SNDRV_PCM_TRIGGER_STOP:
944
- HD_WRITE(VC4_HD_MAI_CTL,
945
- VC4_HD_MAI_CTL_DLATE |
946
- VC4_HD_MAI_CTL_ERRORE |
947
- VC4_HD_MAI_CTL_ERRORF);
948
- HDMI_WRITE(VC4_HDMI_TX_PHY_CTL0,
949
- HDMI_READ(VC4_HDMI_TX_PHY_CTL0) |
950
- VC4_HDMI_TX_PHY_RNG_PWRDN);
1080
+ HDMI_WRITE(HDMI_MAI_CTL,
1081
+ VC4_HD_MAI_CTL_DLATE |
1082
+ VC4_HD_MAI_CTL_ERRORE |
1083
+ VC4_HD_MAI_CTL_ERRORF);
1084
+
1085
+ if (vc4_hdmi->variant->phy_rng_disable)
1086
+ vc4_hdmi->variant->phy_rng_disable(vc4_hdmi);
1087
+
1088
+ vc4_hdmi->audio.streaming = false;
1089
+
9511090 break;
9521091 default:
9531092 break;
....@@ -968,10 +1107,11 @@
9681107 struct snd_ctl_elem_info *uinfo)
9691108 {
9701109 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
971
- struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
1110
+ struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
1111
+ struct drm_connector *connector = &vc4_hdmi->connector;
9721112
9731113 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
974
- uinfo->count = sizeof(hdmi->connector->eld);
1114
+ uinfo->count = sizeof(connector->eld);
9751115
9761116 return 0;
9771117 }
....@@ -980,10 +1120,11 @@
9801120 struct snd_ctl_elem_value *ucontrol)
9811121 {
9821122 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
983
- struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
1123
+ struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
1124
+ struct drm_connector *connector = &vc4_hdmi->connector;
9841125
985
- memcpy(ucontrol->value.bytes.data, hdmi->connector->eld,
986
- sizeof(hdmi->connector->eld));
1126
+ memcpy(ucontrol->value.bytes.data, connector->eld,
1127
+ sizeof(connector->eld));
9871128
9881129 return 0;
9891130 }
....@@ -1008,6 +1149,7 @@
10081149 };
10091150
10101151 static const struct snd_soc_component_driver vc4_hdmi_audio_component_drv = {
1152
+ .name = "vc4-hdmi-codec-dai-component",
10111153 .controls = vc4_hdmi_audio_controls,
10121154 .num_controls = ARRAY_SIZE(vc4_hdmi_audio_controls),
10131155 .dapm_widgets = vc4_hdmi_audio_widgets,
....@@ -1048,9 +1190,9 @@
10481190
10491191 static int vc4_hdmi_audio_cpu_dai_probe(struct snd_soc_dai *dai)
10501192 {
1051
- struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
1193
+ struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
10521194
1053
- snd_soc_dai_init_dma_data(dai, &hdmi->audio.dma_data, NULL);
1195
+ snd_soc_dai_init_dma_data(dai, &vc4_hdmi->audio.dma_data, NULL);
10541196
10551197 return 0;
10561198 }
....@@ -1076,18 +1218,26 @@
10761218 .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
10771219 };
10781220
1079
-static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
1221
+static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
10801222 {
1081
- struct snd_soc_dai_link *dai_link = &hdmi->audio.link;
1082
- struct snd_soc_card *card = &hdmi->audio.card;
1083
- struct device *dev = &hdmi->pdev->dev;
1223
+ const struct vc4_hdmi_register *mai_data =
1224
+ &vc4_hdmi->variant->registers[HDMI_MAI_DATA];
1225
+ struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link;
1226
+ struct snd_soc_card *card = &vc4_hdmi->audio.card;
1227
+ struct device *dev = &vc4_hdmi->pdev->dev;
10841228 const __be32 *addr;
1229
+ int index, len;
10851230 int ret;
10861231
1087
- if (!of_find_property(dev->of_node, "dmas", NULL)) {
1232
+ if (!of_find_property(dev->of_node, "dmas", &len) || !len) {
10881233 dev_warn(dev,
1089
- "'dmas' DT property is missing, no HDMI audio\n");
1234
+ "'dmas' DT property is missing or empty, no HDMI audio\n");
10901235 return 0;
1236
+ }
1237
+
1238
+ if (mai_data->reg != VC4_HD) {
1239
+ WARN_ONCE(true, "MAI isn't in the HD block\n");
1240
+ return -EINVAL;
10911241 }
10921242
10931243 /*
....@@ -1097,10 +1247,16 @@
10971247 * for DMA transfers.
10981248 * This VC/MMU should probably be exposed to avoid this kind of hacks.
10991249 */
1100
- addr = of_get_address(dev->of_node, 1, NULL, NULL);
1101
- hdmi->audio.dma_data.addr = be32_to_cpup(addr) + VC4_HD_MAI_DATA;
1102
- hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
1103
- hdmi->audio.dma_data.maxburst = 2;
1250
+ index = of_property_match_string(dev->of_node, "reg-names", "hd");
1251
+ /* Before BCM2711, we don't have a named register range */
1252
+ if (index < 0)
1253
+ index = 1;
1254
+
1255
+ addr = of_get_address(dev->of_node, index, NULL, NULL);
1256
+
1257
+ vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset;
1258
+ vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
1259
+ vc4_hdmi->audio.dma_data.maxburst = 2;
11041260
11051261 ret = devm_snd_dmaengine_pcm_register(dev, &pcm_conf, 0);
11061262 if (ret) {
....@@ -1123,16 +1279,25 @@
11231279 return ret;
11241280 }
11251281
1282
+ dai_link->cpus = &vc4_hdmi->audio.cpu;
1283
+ dai_link->codecs = &vc4_hdmi->audio.codec;
1284
+ dai_link->platforms = &vc4_hdmi->audio.platform;
1285
+
1286
+ dai_link->num_cpus = 1;
1287
+ dai_link->num_codecs = 1;
1288
+ dai_link->num_platforms = 1;
1289
+
11261290 dai_link->name = "MAI";
11271291 dai_link->stream_name = "MAI PCM";
1128
- dai_link->codec_dai_name = vc4_hdmi_audio_codec_dai_drv.name;
1129
- dai_link->cpu_dai_name = dev_name(dev);
1130
- dai_link->codec_name = dev_name(dev);
1131
- dai_link->platform_name = dev_name(dev);
1292
+ dai_link->codecs->dai_name = vc4_hdmi_audio_codec_dai_drv.name;
1293
+ dai_link->cpus->dai_name = dev_name(dev);
1294
+ dai_link->codecs->name = dev_name(dev);
1295
+ dai_link->platforms->name = dev_name(dev);
11321296
11331297 card->dai_link = dai_link;
11341298 card->num_links = 1;
1135
- card->name = "vc4-hdmi";
1299
+ card->name = vc4_hdmi->variant->card_name;
1300
+ card->driver_name = "vc4-hdmi";
11361301 card->dev = dev;
11371302 card->owner = THIS_MODULE;
11381303
....@@ -1143,7 +1308,7 @@
11431308 * now stored in card->drvdata and should be retrieved with
11441309 * snd_soc_card_get_drvdata() if needed.
11451310 */
1146
- snd_soc_card_set_drvdata(card, hdmi);
1311
+ snd_soc_card_set_drvdata(card, vc4_hdmi);
11471312 ret = devm_snd_soc_register_card(dev, card);
11481313 if (ret)
11491314 dev_err(dev, "Could not register sound card: %d\n", ret);
....@@ -1155,35 +1320,42 @@
11551320 #ifdef CONFIG_DRM_VC4_HDMI_CEC
11561321 static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
11571322 {
1158
- struct vc4_dev *vc4 = priv;
1159
- struct vc4_hdmi *hdmi = vc4->hdmi;
1323
+ struct vc4_hdmi *vc4_hdmi = priv;
11601324
1161
- if (hdmi->cec_irq_was_rx) {
1162
- if (hdmi->cec_rx_msg.len)
1163
- cec_received_msg(hdmi->cec_adap, &hdmi->cec_rx_msg);
1164
- } else if (hdmi->cec_tx_ok) {
1165
- cec_transmit_done(hdmi->cec_adap, CEC_TX_STATUS_OK,
1325
+ if (vc4_hdmi->cec_irq_was_rx) {
1326
+ if (vc4_hdmi->cec_rx_msg.len)
1327
+ cec_received_msg(vc4_hdmi->cec_adap,
1328
+ &vc4_hdmi->cec_rx_msg);
1329
+ } else if (vc4_hdmi->cec_tx_ok) {
1330
+ cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_OK,
11661331 0, 0, 0, 0);
11671332 } else {
11681333 /*
11691334 * This CEC implementation makes 1 retry, so if we
11701335 * get a NACK, then that means it made 2 attempts.
11711336 */
1172
- cec_transmit_done(hdmi->cec_adap, CEC_TX_STATUS_NACK,
1337
+ cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_NACK,
11731338 0, 2, 0, 0);
11741339 }
11751340 return IRQ_HANDLED;
11761341 }
11771342
1178
-static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1)
1343
+static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
11791344 {
1180
- struct cec_msg *msg = &vc4->hdmi->cec_rx_msg;
1345
+ struct drm_device *dev = vc4_hdmi->connector.dev;
1346
+ struct cec_msg *msg = &vc4_hdmi->cec_rx_msg;
11811347 unsigned int i;
11821348
11831349 msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >>
11841350 VC4_HDMI_CEC_REC_WRD_CNT_SHIFT);
1351
+
1352
+ if (msg->len > 16) {
1353
+ drm_err(dev, "Attempting to read too much data (%d)\n", msg->len);
1354
+ return;
1355
+ }
1356
+
11851357 for (i = 0; i < msg->len; i += 4) {
1186
- u32 val = HDMI_READ(VC4_HDMI_CEC_RX_DATA_1 + i);
1358
+ u32 val = HDMI_READ(HDMI_CEC_RX_DATA_1 + (i >> 2));
11871359
11881360 msg->msg[i] = val & 0xff;
11891361 msg->msg[i + 1] = (val >> 8) & 0xff;
....@@ -1194,38 +1366,37 @@
11941366
11951367 static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
11961368 {
1197
- struct vc4_dev *vc4 = priv;
1198
- struct vc4_hdmi *hdmi = vc4->hdmi;
1199
- u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS);
1369
+ struct vc4_hdmi *vc4_hdmi = priv;
1370
+ u32 stat = HDMI_READ(HDMI_CEC_CPU_STATUS);
12001371 u32 cntrl1, cntrl5;
12011372
12021373 if (!(stat & VC4_HDMI_CPU_CEC))
12031374 return IRQ_NONE;
1204
- hdmi->cec_rx_msg.len = 0;
1205
- cntrl1 = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
1206
- cntrl5 = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
1207
- hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
1208
- if (hdmi->cec_irq_was_rx) {
1209
- vc4_cec_read_msg(vc4, cntrl1);
1375
+ vc4_hdmi->cec_rx_msg.len = 0;
1376
+ cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1);
1377
+ cntrl5 = HDMI_READ(HDMI_CEC_CNTRL_5);
1378
+ vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
1379
+ if (vc4_hdmi->cec_irq_was_rx) {
1380
+ vc4_cec_read_msg(vc4_hdmi, cntrl1);
12101381 cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
1211
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
1382
+ HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
12121383 cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
12131384 } else {
1214
- hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
1385
+ vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
12151386 cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
12161387 }
1217
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
1218
- HDMI_WRITE(VC4_HDMI_CPU_CLEAR, VC4_HDMI_CPU_CEC);
1388
+ HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
1389
+ HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC);
12191390
12201391 return IRQ_WAKE_THREAD;
12211392 }
12221393
12231394 static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
12241395 {
1225
- struct vc4_dev *vc4 = cec_get_drvdata(adap);
1396
+ struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
12261397 /* clock period in microseconds */
12271398 const u32 usecs = 1000000 / CEC_CLOCK_FREQ;
1228
- u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
1399
+ u32 val = HDMI_READ(HDMI_CEC_CNTRL_5);
12291400
12301401 val &= ~(VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET |
12311402 VC4_HDMI_CEC_CNT_TO_4700_US_MASK |
....@@ -1234,30 +1405,30 @@
12341405 ((4500 / usecs) << VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT);
12351406
12361407 if (enable) {
1237
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val |
1408
+ HDMI_WRITE(HDMI_CEC_CNTRL_5, val |
12381409 VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET);
1239
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val);
1240
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_2,
1241
- ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) |
1242
- ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) |
1243
- ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) |
1244
- ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) |
1245
- ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT));
1246
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_3,
1247
- ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) |
1248
- ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) |
1249
- ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) |
1250
- ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT));
1251
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_4,
1252
- ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) |
1253
- ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) |
1254
- ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) |
1255
- ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT));
1410
+ HDMI_WRITE(HDMI_CEC_CNTRL_5, val);
1411
+ HDMI_WRITE(HDMI_CEC_CNTRL_2,
1412
+ ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) |
1413
+ ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) |
1414
+ ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) |
1415
+ ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) |
1416
+ ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT));
1417
+ HDMI_WRITE(HDMI_CEC_CNTRL_3,
1418
+ ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) |
1419
+ ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) |
1420
+ ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) |
1421
+ ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT));
1422
+ HDMI_WRITE(HDMI_CEC_CNTRL_4,
1423
+ ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) |
1424
+ ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) |
1425
+ ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) |
1426
+ ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT));
12561427
1257
- HDMI_WRITE(VC4_HDMI_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
1428
+ HDMI_WRITE(HDMI_CEC_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
12581429 } else {
1259
- HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
1260
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val |
1430
+ HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
1431
+ HDMI_WRITE(HDMI_CEC_CNTRL_5, val |
12611432 VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET);
12621433 }
12631434 return 0;
....@@ -1265,10 +1436,10 @@
12651436
12661437 static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
12671438 {
1268
- struct vc4_dev *vc4 = cec_get_drvdata(adap);
1439
+ struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
12691440
1270
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1,
1271
- (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
1441
+ HDMI_WRITE(HDMI_CEC_CNTRL_1,
1442
+ (HDMI_READ(HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
12721443 (log_addr & 0xf) << VC4_HDMI_CEC_ADDR_SHIFT);
12731444 return 0;
12741445 }
....@@ -1276,25 +1447,31 @@
12761447 static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
12771448 u32 signal_free_time, struct cec_msg *msg)
12781449 {
1279
- struct vc4_dev *vc4 = cec_get_drvdata(adap);
1450
+ struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
1451
+ struct drm_device *dev = vc4_hdmi->connector.dev;
12801452 u32 val;
12811453 unsigned int i;
12821454
1455
+ if (msg->len > 16) {
1456
+ drm_err(dev, "Attempting to transmit too much data (%d)\n", msg->len);
1457
+ return -ENOMEM;
1458
+ }
1459
+
12831460 for (i = 0; i < msg->len; i += 4)
1284
- HDMI_WRITE(VC4_HDMI_CEC_TX_DATA_1 + i,
1461
+ HDMI_WRITE(HDMI_CEC_TX_DATA_1 + (i >> 2),
12851462 (msg->msg[i]) |
12861463 (msg->msg[i + 1] << 8) |
12871464 (msg->msg[i + 2] << 16) |
12881465 (msg->msg[i + 3] << 24));
12891466
1290
- val = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
1467
+ val = HDMI_READ(HDMI_CEC_CNTRL_1);
12911468 val &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
1292
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val);
1469
+ HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
12931470 val &= ~VC4_HDMI_CEC_MESSAGE_LENGTH_MASK;
12941471 val |= (msg->len - 1) << VC4_HDMI_CEC_MESSAGE_LENGTH_SHIFT;
12951472 val |= VC4_HDMI_CEC_START_XMIT_BEGIN;
12961473
1297
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val);
1474
+ HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
12981475 return 0;
12991476 }
13001477
....@@ -1303,49 +1480,297 @@
13031480 .adap_log_addr = vc4_hdmi_cec_adap_log_addr,
13041481 .adap_transmit = vc4_hdmi_cec_adap_transmit,
13051482 };
1483
+
1484
+static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
1485
+{
1486
+ struct cec_connector_info conn_info;
1487
+ struct platform_device *pdev = vc4_hdmi->pdev;
1488
+ u32 value;
1489
+ int ret;
1490
+
1491
+ if (!vc4_hdmi->variant->cec_available)
1492
+ return 0;
1493
+
1494
+ vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
1495
+ vc4_hdmi,
1496
+ vc4_hdmi->variant->card_name,
1497
+ CEC_CAP_DEFAULTS |
1498
+ CEC_CAP_CONNECTOR_INFO, 1);
1499
+ ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
1500
+ if (ret < 0)
1501
+ return ret;
1502
+
1503
+ cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
1504
+ cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
1505
+
1506
+ HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
1507
+
1508
+ value = HDMI_READ(HDMI_CEC_CNTRL_1);
1509
+ /* Set the logical address to Unregistered */
1510
+ value |= VC4_HDMI_CEC_ADDR_MASK;
1511
+ HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
1512
+
1513
+ vc4_hdmi_cec_update_clk_div(vc4_hdmi);
1514
+
1515
+ ret = devm_request_threaded_irq(&pdev->dev, platform_get_irq(pdev, 0),
1516
+ vc4_cec_irq_handler,
1517
+ vc4_cec_irq_handler_thread, 0,
1518
+ "vc4 hdmi cec", vc4_hdmi);
1519
+ if (ret)
1520
+ goto err_delete_cec_adap;
1521
+
1522
+ ret = cec_register_adapter(vc4_hdmi->cec_adap, &pdev->dev);
1523
+ if (ret < 0)
1524
+ goto err_delete_cec_adap;
1525
+
1526
+ return 0;
1527
+
1528
+err_delete_cec_adap:
1529
+ cec_delete_adapter(vc4_hdmi->cec_adap);
1530
+
1531
+ return ret;
1532
+}
1533
+
1534
+static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi)
1535
+{
1536
+ cec_unregister_adapter(vc4_hdmi->cec_adap);
1537
+}
1538
+#else
1539
+static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
1540
+{
1541
+ return 0;
1542
+}
1543
+
1544
+static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) {};
1545
+
1546
+#endif
1547
+
1548
+static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
1549
+ struct debugfs_regset32 *regset,
1550
+ enum vc4_hdmi_regs reg)
1551
+{
1552
+ const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
1553
+ struct debugfs_reg32 *regs, *new_regs;
1554
+ unsigned int count = 0;
1555
+ unsigned int i;
1556
+
1557
+ regs = kcalloc(variant->num_registers, sizeof(*regs),
1558
+ GFP_KERNEL);
1559
+ if (!regs)
1560
+ return -ENOMEM;
1561
+
1562
+ for (i = 0; i < variant->num_registers; i++) {
1563
+ const struct vc4_hdmi_register *field = &variant->registers[i];
1564
+
1565
+ if (field->reg != reg)
1566
+ continue;
1567
+
1568
+ regs[count].name = field->name;
1569
+ regs[count].offset = field->offset;
1570
+ count++;
1571
+ }
1572
+
1573
+ new_regs = krealloc(regs, count * sizeof(*regs), GFP_KERNEL);
1574
+ if (!new_regs)
1575
+ return -ENOMEM;
1576
+
1577
+ regset->base = __vc4_hdmi_get_field_base(vc4_hdmi, reg);
1578
+ regset->regs = new_regs;
1579
+ regset->nregs = count;
1580
+
1581
+ return 0;
1582
+}
1583
+
1584
+static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
1585
+{
1586
+ struct platform_device *pdev = vc4_hdmi->pdev;
1587
+ struct device *dev = &pdev->dev;
1588
+ int ret;
1589
+
1590
+ vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
1591
+ if (IS_ERR(vc4_hdmi->hdmicore_regs))
1592
+ return PTR_ERR(vc4_hdmi->hdmicore_regs);
1593
+
1594
+ vc4_hdmi->hd_regs = vc4_ioremap_regs(pdev, 1);
1595
+ if (IS_ERR(vc4_hdmi->hd_regs))
1596
+ return PTR_ERR(vc4_hdmi->hd_regs);
1597
+
1598
+ ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD);
1599
+ if (ret)
1600
+ return ret;
1601
+
1602
+ ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI);
1603
+ if (ret)
1604
+ return ret;
1605
+
1606
+ vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel");
1607
+ if (IS_ERR(vc4_hdmi->pixel_clock)) {
1608
+ ret = PTR_ERR(vc4_hdmi->pixel_clock);
1609
+ if (ret != -EPROBE_DEFER)
1610
+ DRM_ERROR("Failed to get pixel clock\n");
1611
+ return ret;
1612
+ }
1613
+
1614
+ vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
1615
+ if (IS_ERR(vc4_hdmi->hsm_clock)) {
1616
+ DRM_ERROR("Failed to get HDMI state machine clock\n");
1617
+ return PTR_ERR(vc4_hdmi->hsm_clock);
1618
+ }
1619
+ vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock;
1620
+
1621
+ return 0;
1622
+}
1623
+
1624
+static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
1625
+{
1626
+ struct platform_device *pdev = vc4_hdmi->pdev;
1627
+ struct device *dev = &pdev->dev;
1628
+ struct resource *res;
1629
+
1630
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi");
1631
+ if (!res)
1632
+ return -ENODEV;
1633
+
1634
+ vc4_hdmi->hdmicore_regs = devm_ioremap(dev, res->start,
1635
+ resource_size(res));
1636
+ if (!vc4_hdmi->hdmicore_regs)
1637
+ return -ENOMEM;
1638
+
1639
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hd");
1640
+ if (!res)
1641
+ return -ENODEV;
1642
+
1643
+ vc4_hdmi->hd_regs = devm_ioremap(dev, res->start, resource_size(res));
1644
+ if (!vc4_hdmi->hd_regs)
1645
+ return -ENOMEM;
1646
+
1647
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cec");
1648
+ if (!res)
1649
+ return -ENODEV;
1650
+
1651
+ vc4_hdmi->cec_regs = devm_ioremap(dev, res->start, resource_size(res));
1652
+ if (!vc4_hdmi->cec_regs)
1653
+ return -ENOMEM;
1654
+
1655
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csc");
1656
+ if (!res)
1657
+ return -ENODEV;
1658
+
1659
+ vc4_hdmi->csc_regs = devm_ioremap(dev, res->start, resource_size(res));
1660
+ if (!vc4_hdmi->csc_regs)
1661
+ return -ENOMEM;
1662
+
1663
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dvp");
1664
+ if (!res)
1665
+ return -ENODEV;
1666
+
1667
+ vc4_hdmi->dvp_regs = devm_ioremap(dev, res->start, resource_size(res));
1668
+ if (!vc4_hdmi->dvp_regs)
1669
+ return -ENOMEM;
1670
+
1671
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
1672
+ if (!res)
1673
+ return -ENODEV;
1674
+
1675
+ vc4_hdmi->phy_regs = devm_ioremap(dev, res->start, resource_size(res));
1676
+ if (!vc4_hdmi->phy_regs)
1677
+ return -ENOMEM;
1678
+
1679
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "packet");
1680
+ if (!res)
1681
+ return -ENODEV;
1682
+
1683
+ vc4_hdmi->ram_regs = devm_ioremap(dev, res->start, resource_size(res));
1684
+ if (!vc4_hdmi->ram_regs)
1685
+ return -ENOMEM;
1686
+
1687
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rm");
1688
+ if (!res)
1689
+ return -ENODEV;
1690
+
1691
+ vc4_hdmi->rm_regs = devm_ioremap(dev, res->start, resource_size(res));
1692
+ if (!vc4_hdmi->rm_regs)
1693
+ return -ENOMEM;
1694
+
1695
+ vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
1696
+ if (IS_ERR(vc4_hdmi->hsm_clock)) {
1697
+ DRM_ERROR("Failed to get HDMI state machine clock\n");
1698
+ return PTR_ERR(vc4_hdmi->hsm_clock);
1699
+ }
1700
+
1701
+ vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb");
1702
+ if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) {
1703
+ DRM_ERROR("Failed to get pixel bvb clock\n");
1704
+ return PTR_ERR(vc4_hdmi->pixel_bvb_clock);
1705
+ }
1706
+
1707
+ vc4_hdmi->audio_clock = devm_clk_get(dev, "audio");
1708
+ if (IS_ERR(vc4_hdmi->audio_clock)) {
1709
+ DRM_ERROR("Failed to get audio clock\n");
1710
+ return PTR_ERR(vc4_hdmi->audio_clock);
1711
+ }
1712
+
1713
+ vc4_hdmi->reset = devm_reset_control_get(dev, NULL);
1714
+ if (IS_ERR(vc4_hdmi->reset)) {
1715
+ DRM_ERROR("Failed to get HDMI reset line\n");
1716
+ return PTR_ERR(vc4_hdmi->reset);
1717
+ }
1718
+
1719
+ return 0;
1720
+}
1721
+
1722
+#ifdef CONFIG_PM
1723
+static int vc4_hdmi_runtime_suspend(struct device *dev)
1724
+{
1725
+ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
1726
+
1727
+ clk_disable_unprepare(vc4_hdmi->hsm_clock);
1728
+
1729
+ return 0;
1730
+}
1731
+
1732
+static int vc4_hdmi_runtime_resume(struct device *dev)
1733
+{
1734
+ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
1735
+ int ret;
1736
+
1737
+ ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
1738
+ if (ret)
1739
+ return ret;
1740
+
1741
+ return 0;
1742
+}
13061743 #endif
13071744
13081745 static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
13091746 {
1747
+ const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
13101748 struct platform_device *pdev = to_platform_device(dev);
13111749 struct drm_device *drm = dev_get_drvdata(master);
1312
- struct vc4_dev *vc4 = drm->dev_private;
1313
- struct vc4_hdmi *hdmi;
1314
- struct vc4_hdmi_encoder *vc4_hdmi_encoder;
1750
+ struct vc4_hdmi *vc4_hdmi;
1751
+ struct drm_encoder *encoder;
13151752 struct device_node *ddc_node;
13161753 u32 value;
13171754 int ret;
13181755
1319
- hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
1320
- if (!hdmi)
1756
+ vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
1757
+ if (!vc4_hdmi)
13211758 return -ENOMEM;
13221759
1323
- vc4_hdmi_encoder = devm_kzalloc(dev, sizeof(*vc4_hdmi_encoder),
1324
- GFP_KERNEL);
1325
- if (!vc4_hdmi_encoder)
1326
- return -ENOMEM;
1327
- vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI;
1328
- hdmi->encoder = &vc4_hdmi_encoder->base.base;
1760
+ dev_set_drvdata(dev, vc4_hdmi);
1761
+ encoder = &vc4_hdmi->encoder.base.base;
1762
+ vc4_hdmi->encoder.base.type = variant->encoder_type;
1763
+ vc4_hdmi->encoder.base.pre_crtc_configure = vc4_hdmi_encoder_pre_crtc_configure;
1764
+ vc4_hdmi->encoder.base.pre_crtc_enable = vc4_hdmi_encoder_pre_crtc_enable;
1765
+ vc4_hdmi->encoder.base.post_crtc_enable = vc4_hdmi_encoder_post_crtc_enable;
1766
+ vc4_hdmi->encoder.base.post_crtc_disable = vc4_hdmi_encoder_post_crtc_disable;
1767
+ vc4_hdmi->encoder.base.post_crtc_powerdown = vc4_hdmi_encoder_post_crtc_powerdown;
1768
+ vc4_hdmi->pdev = pdev;
1769
+ vc4_hdmi->variant = variant;
13291770
1330
- hdmi->pdev = pdev;
1331
- hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
1332
- if (IS_ERR(hdmi->hdmicore_regs))
1333
- return PTR_ERR(hdmi->hdmicore_regs);
1334
-
1335
- hdmi->hd_regs = vc4_ioremap_regs(pdev, 1);
1336
- if (IS_ERR(hdmi->hd_regs))
1337
- return PTR_ERR(hdmi->hd_regs);
1338
-
1339
- hdmi->pixel_clock = devm_clk_get(dev, "pixel");
1340
- if (IS_ERR(hdmi->pixel_clock)) {
1341
- DRM_ERROR("Failed to get pixel clock\n");
1342
- return PTR_ERR(hdmi->pixel_clock);
1343
- }
1344
- hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
1345
- if (IS_ERR(hdmi->hsm_clock)) {
1346
- DRM_ERROR("Failed to get HDMI state machine clock\n");
1347
- return PTR_ERR(hdmi->hsm_clock);
1348
- }
1771
+ ret = variant->init_resources(vc4_hdmi);
1772
+ if (ret)
1773
+ return ret;
13491774
13501775 ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
13511776 if (!ddc_node) {
....@@ -1353,28 +1778,11 @@
13531778 return -ENODEV;
13541779 }
13551780
1356
- hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
1781
+ vc4_hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
13571782 of_node_put(ddc_node);
1358
- if (!hdmi->ddc) {
1783
+ if (!vc4_hdmi->ddc) {
13591784 DRM_DEBUG("Failed to get ddc i2c adapter by node\n");
13601785 return -EPROBE_DEFER;
1361
- }
1362
-
1363
- /* This is the rate that is set by the firmware. The number
1364
- * needs to be a bit higher than the pixel clock rate
1365
- * (generally 148.5Mhz).
1366
- */
1367
- ret = clk_set_rate(hdmi->hsm_clock, HSM_CLOCK_FREQ);
1368
- if (ret) {
1369
- DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
1370
- goto err_put_i2c;
1371
- }
1372
-
1373
- ret = clk_prepare_enable(hdmi->hsm_clock);
1374
- if (ret) {
1375
- DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
1376
- ret);
1377
- goto err_put_i2c;
13781786 }
13791787
13801788 /* Only use the GPIO HPD pin if present in the DT, otherwise
....@@ -1383,89 +1791,76 @@
13831791 if (of_find_property(dev->of_node, "hpd-gpios", &value)) {
13841792 enum of_gpio_flags hpd_gpio_flags;
13851793
1386
- hdmi->hpd_gpio = of_get_named_gpio_flags(dev->of_node,
1387
- "hpd-gpios", 0,
1388
- &hpd_gpio_flags);
1389
- if (hdmi->hpd_gpio < 0) {
1390
- ret = hdmi->hpd_gpio;
1391
- goto err_unprepare_hsm;
1794
+ vc4_hdmi->hpd_gpio = of_get_named_gpio_flags(dev->of_node,
1795
+ "hpd-gpios", 0,
1796
+ &hpd_gpio_flags);
1797
+ if (vc4_hdmi->hpd_gpio < 0) {
1798
+ ret = vc4_hdmi->hpd_gpio;
1799
+ goto err_put_ddc;
13921800 }
13931801
1394
- hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
1802
+ vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
13951803 }
13961804
1397
- vc4->hdmi = hdmi;
1805
+ vc4_hdmi->disable_wifi_frequencies =
1806
+ of_property_read_bool(dev->of_node, "wifi-2.4ghz-coexistence");
13981807
1399
- /* HDMI core must be enabled. */
1400
- if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) {
1401
- HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST);
1402
- udelay(1);
1403
- HD_WRITE(VC4_HD_M_CTL, 0);
1808
+ /*
1809
+ * If we boot without any cable connected to the HDMI connector,
1810
+ * the firmware will skip the HSM initialization and leave it
1811
+ * with a rate of 0, resulting in a bus lockup when we're
1812
+ * accessing the registers even if it's enabled.
1813
+ *
1814
+ * Let's put a sensible default at runtime_resume so that we
1815
+ * don't end up in this situation.
1816
+ */
1817
+ ret = clk_set_min_rate(vc4_hdmi->hsm_clock, HSM_MIN_CLOCK_FREQ);
1818
+ if (ret)
1819
+ goto err_put_ddc;
14041820
1405
- HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_ENABLE);
1821
+ if (vc4_hdmi->variant->reset)
1822
+ vc4_hdmi->variant->reset(vc4_hdmi);
1823
+
1824
+ if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") ||
1825
+ of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1")) &&
1826
+ HDMI_READ(HDMI_VID_CTL) & VC4_HD_VID_CTL_ENABLE) {
1827
+ clk_prepare_enable(vc4_hdmi->pixel_clock);
1828
+ clk_prepare_enable(vc4_hdmi->hsm_clock);
1829
+ clk_prepare_enable(vc4_hdmi->pixel_bvb_clock);
14061830 }
1831
+
14071832 pm_runtime_enable(dev);
14081833
1409
- drm_encoder_init(drm, hdmi->encoder, &vc4_hdmi_encoder_funcs,
1410
- DRM_MODE_ENCODER_TMDS, NULL);
1411
- drm_encoder_helper_add(hdmi->encoder, &vc4_hdmi_encoder_helper_funcs);
1834
+ drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
1835
+ drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
14121836
1413
- hdmi->connector = vc4_hdmi_connector_init(drm, hdmi->encoder);
1414
- if (IS_ERR(hdmi->connector)) {
1415
- ret = PTR_ERR(hdmi->connector);
1837
+ ret = vc4_hdmi_connector_init(drm, vc4_hdmi);
1838
+ if (ret)
14161839 goto err_destroy_encoder;
1417
- }
1418
-#ifdef CONFIG_DRM_VC4_HDMI_CEC
1419
- hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
1420
- vc4, "vc4",
1421
- CEC_CAP_TRANSMIT |
1422
- CEC_CAP_LOG_ADDRS |
1423
- CEC_CAP_PASSTHROUGH |
1424
- CEC_CAP_RC, 1);
1425
- ret = PTR_ERR_OR_ZERO(hdmi->cec_adap);
1426
- if (ret < 0)
1840
+
1841
+ ret = vc4_hdmi_cec_init(vc4_hdmi);
1842
+ if (ret)
14271843 goto err_destroy_conn;
1428
- HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
1429
- value = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
1430
- value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
1431
- /*
1432
- * Set the logical address to Unregistered and set the clock
1433
- * divider: the hsm_clock rate and this divider setting will
1434
- * give a 40 kHz CEC clock.
1435
- */
1436
- value |= VC4_HDMI_CEC_ADDR_MASK |
1437
- (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
1438
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, value);
1439
- ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
1440
- vc4_cec_irq_handler,
1441
- vc4_cec_irq_handler_thread, 0,
1442
- "vc4 hdmi cec", vc4);
1443
- if (ret)
1444
- goto err_delete_cec_adap;
1445
- ret = cec_register_adapter(hdmi->cec_adap, dev);
1446
- if (ret < 0)
1447
- goto err_delete_cec_adap;
1448
-#endif
14491844
1450
- ret = vc4_hdmi_audio_init(hdmi);
1845
+ ret = vc4_hdmi_audio_init(vc4_hdmi);
14511846 if (ret)
1452
- goto err_destroy_encoder;
1847
+ goto err_free_cec;
1848
+
1849
+ vc4_debugfs_add_file(drm, variant->debugfs_name,
1850
+ vc4_hdmi_debugfs_regs,
1851
+ vc4_hdmi);
14531852
14541853 return 0;
14551854
1456
-#ifdef CONFIG_DRM_VC4_HDMI_CEC
1457
-err_delete_cec_adap:
1458
- cec_delete_adapter(hdmi->cec_adap);
1855
+err_free_cec:
1856
+ vc4_hdmi_cec_exit(vc4_hdmi);
14591857 err_destroy_conn:
1460
- vc4_hdmi_connector_destroy(hdmi->connector);
1461
-#endif
1858
+ vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
14621859 err_destroy_encoder:
1463
- vc4_hdmi_encoder_destroy(hdmi->encoder);
1464
-err_unprepare_hsm:
1465
- clk_disable_unprepare(hdmi->hsm_clock);
1860
+ drm_encoder_cleanup(encoder);
14661861 pm_runtime_disable(dev);
1467
-err_put_i2c:
1468
- put_device(&hdmi->ddc->dev);
1862
+err_put_ddc:
1863
+ put_device(&vc4_hdmi->ddc->dev);
14691864
14701865 return ret;
14711866 }
....@@ -1473,20 +1868,39 @@
14731868 static void vc4_hdmi_unbind(struct device *dev, struct device *master,
14741869 void *data)
14751870 {
1476
- struct drm_device *drm = dev_get_drvdata(master);
1477
- struct vc4_dev *vc4 = drm->dev_private;
1478
- struct vc4_hdmi *hdmi = vc4->hdmi;
1871
+ struct vc4_hdmi *vc4_hdmi;
14791872
1480
- cec_unregister_adapter(hdmi->cec_adap);
1481
- vc4_hdmi_connector_destroy(hdmi->connector);
1482
- vc4_hdmi_encoder_destroy(hdmi->encoder);
1873
+ /*
1874
+ * ASoC makes it a bit hard to retrieve a pointer to the
1875
+ * vc4_hdmi structure. Registering the card will overwrite our
1876
+ * device drvdata with a pointer to the snd_soc_card structure,
1877
+ * which can then be used to retrieve whatever drvdata we want
1878
+ * to associate.
1879
+ *
1880
+ * However, that doesn't fly in the case where we wouldn't
1881
+ * register an ASoC card (because of an old DT that is missing
1882
+ * the dmas properties for example), then the card isn't
1883
+ * registered and the device drvdata wouldn't be set.
1884
+ *
1885
+ * We can deal with both cases by making sure a snd_soc_card
1886
+ * pointer and a vc4_hdmi structure are pointing to the same
1887
+ * memory address, so we can treat them indistinctly without any
1888
+ * issue.
1889
+ */
1890
+ BUILD_BUG_ON(offsetof(struct vc4_hdmi_audio, card) != 0);
1891
+ BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0);
1892
+ vc4_hdmi = dev_get_drvdata(dev);
14831893
1484
- clk_disable_unprepare(hdmi->hsm_clock);
1894
+ kfree(vc4_hdmi->hdmi_regset.regs);
1895
+ kfree(vc4_hdmi->hd_regset.regs);
1896
+
1897
+ vc4_hdmi_cec_exit(vc4_hdmi);
1898
+ vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
1899
+ drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
1900
+
14851901 pm_runtime_disable(dev);
14861902
1487
- put_device(&hdmi->ddc->dev);
1488
-
1489
- vc4->hdmi = NULL;
1903
+ put_device(&vc4_hdmi->ddc->dev);
14901904 }
14911905
14921906 static const struct component_ops vc4_hdmi_ops = {
....@@ -1505,9 +1919,89 @@
15051919 return 0;
15061920 }
15071921
1922
+static const struct vc4_hdmi_variant bcm2835_variant = {
1923
+ .encoder_type = VC4_ENCODER_TYPE_HDMI0,
1924
+ .debugfs_name = "hdmi_regs",
1925
+ .card_name = "vc4-hdmi",
1926
+ .max_pixel_clock = 162000000,
1927
+ .cec_available = true,
1928
+ .registers = vc4_hdmi_fields,
1929
+ .num_registers = ARRAY_SIZE(vc4_hdmi_fields),
1930
+
1931
+ .init_resources = vc4_hdmi_init_resources,
1932
+ .csc_setup = vc4_hdmi_csc_setup,
1933
+ .reset = vc4_hdmi_reset,
1934
+ .set_timings = vc4_hdmi_set_timings,
1935
+ .phy_init = vc4_hdmi_phy_init,
1936
+ .phy_disable = vc4_hdmi_phy_disable,
1937
+ .phy_rng_enable = vc4_hdmi_phy_rng_enable,
1938
+ .phy_rng_disable = vc4_hdmi_phy_rng_disable,
1939
+ .channel_map = vc4_hdmi_channel_map,
1940
+};
1941
+
1942
+static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = {
1943
+ .encoder_type = VC4_ENCODER_TYPE_HDMI0,
1944
+ .debugfs_name = "hdmi0_regs",
1945
+ .card_name = "vc4-hdmi-0",
1946
+ .max_pixel_clock = HDMI_14_MAX_TMDS_CLK,
1947
+ .registers = vc5_hdmi_hdmi0_fields,
1948
+ .num_registers = ARRAY_SIZE(vc5_hdmi_hdmi0_fields),
1949
+ .phy_lane_mapping = {
1950
+ PHY_LANE_0,
1951
+ PHY_LANE_1,
1952
+ PHY_LANE_2,
1953
+ PHY_LANE_CK,
1954
+ },
1955
+ .unsupported_odd_h_timings = true,
1956
+
1957
+ .init_resources = vc5_hdmi_init_resources,
1958
+ .csc_setup = vc5_hdmi_csc_setup,
1959
+ .reset = vc5_hdmi_reset,
1960
+ .set_timings = vc5_hdmi_set_timings,
1961
+ .phy_init = vc5_hdmi_phy_init,
1962
+ .phy_disable = vc5_hdmi_phy_disable,
1963
+ .phy_rng_enable = vc5_hdmi_phy_rng_enable,
1964
+ .phy_rng_disable = vc5_hdmi_phy_rng_disable,
1965
+ .channel_map = vc5_hdmi_channel_map,
1966
+};
1967
+
1968
+static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = {
1969
+ .encoder_type = VC4_ENCODER_TYPE_HDMI1,
1970
+ .debugfs_name = "hdmi1_regs",
1971
+ .card_name = "vc4-hdmi-1",
1972
+ .max_pixel_clock = HDMI_14_MAX_TMDS_CLK,
1973
+ .registers = vc5_hdmi_hdmi1_fields,
1974
+ .num_registers = ARRAY_SIZE(vc5_hdmi_hdmi1_fields),
1975
+ .phy_lane_mapping = {
1976
+ PHY_LANE_1,
1977
+ PHY_LANE_0,
1978
+ PHY_LANE_CK,
1979
+ PHY_LANE_2,
1980
+ },
1981
+ .unsupported_odd_h_timings = true,
1982
+
1983
+ .init_resources = vc5_hdmi_init_resources,
1984
+ .csc_setup = vc5_hdmi_csc_setup,
1985
+ .reset = vc5_hdmi_reset,
1986
+ .set_timings = vc5_hdmi_set_timings,
1987
+ .phy_init = vc5_hdmi_phy_init,
1988
+ .phy_disable = vc5_hdmi_phy_disable,
1989
+ .phy_rng_enable = vc5_hdmi_phy_rng_enable,
1990
+ .phy_rng_disable = vc5_hdmi_phy_rng_disable,
1991
+ .channel_map = vc5_hdmi_channel_map,
1992
+};
1993
+
15081994 static const struct of_device_id vc4_hdmi_dt_match[] = {
1509
- { .compatible = "brcm,bcm2835-hdmi" },
1995
+ { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
1996
+ { .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant },
1997
+ { .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant },
15101998 {}
1999
+};
2000
+
2001
+static const struct dev_pm_ops vc4_hdmi_pm_ops = {
2002
+ SET_RUNTIME_PM_OPS(vc4_hdmi_runtime_suspend,
2003
+ vc4_hdmi_runtime_resume,
2004
+ NULL)
15112005 };
15122006
15132007 struct platform_driver vc4_hdmi_driver = {
....@@ -1516,5 +2010,6 @@
15162010 .driver = {
15172011 .name = "vc4_hdmi",
15182012 .of_match_table = vc4_hdmi_dt_match,
2013
+ .pm = &vc4_hdmi_pm_ops,
15192014 },
15202015 };