forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 958e46acc8e900e8569dd467c1af9b8d2d019394
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,199 @@
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
+ VC4_HDMI_VERTB_VBP));
572
+ u32 vertb_even = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
573
+ VC4_SET_FIELD(mode->crtc_vtotal -
574
+ mode->crtc_vsync_end - interlaced,
575
+ VC4_HDMI_VERTB_VBP));
576
+
577
+ HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
578
+ HDMI_WRITE(HDMI_HORZA,
579
+ (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) |
580
+ (hsync_pos ? VC5_HDMI_HORZA_HPOS : 0) |
581
+ VC4_SET_FIELD(mode->hdisplay * pixel_rep,
582
+ VC5_HDMI_HORZA_HAP) |
583
+ VC4_SET_FIELD((mode->hsync_start -
584
+ mode->hdisplay) * pixel_rep,
585
+ VC5_HDMI_HORZA_HFP));
586
+
587
+ HDMI_WRITE(HDMI_HORZB,
588
+ VC4_SET_FIELD((mode->htotal -
589
+ mode->hsync_end) * pixel_rep,
590
+ VC5_HDMI_HORZB_HBP) |
591
+ VC4_SET_FIELD((mode->hsync_end -
592
+ mode->hsync_start) * pixel_rep,
593
+ VC5_HDMI_HORZB_HSP));
594
+
595
+ HDMI_WRITE(HDMI_VERTA0, verta);
596
+ HDMI_WRITE(HDMI_VERTA1, verta);
597
+
598
+ HDMI_WRITE(HDMI_VERTB0, vertb_even);
599
+ HDMI_WRITE(HDMI_VERTB1, vertb);
600
+
601
+ HDMI_WRITE(HDMI_CLOCK_STOP, 0);
602
+}
603
+
604
+static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
605
+{
606
+ u32 drift;
607
+ int ret;
608
+
609
+ drift = HDMI_READ(HDMI_FIFO_CTL);
610
+ drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
611
+
612
+ HDMI_WRITE(HDMI_FIFO_CTL,
613
+ drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
614
+ HDMI_WRITE(HDMI_FIFO_CTL,
615
+ drift | VC4_HDMI_FIFO_CTL_RECENTER);
616
+ usleep_range(1000, 1100);
617
+ HDMI_WRITE(HDMI_FIFO_CTL,
618
+ drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
619
+ HDMI_WRITE(HDMI_FIFO_CTL,
620
+ drift | VC4_HDMI_FIFO_CTL_RECENTER);
621
+
622
+ ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
623
+ VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
624
+ WARN_ONCE(ret, "Timeout waiting for "
625
+ "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
626
+}
627
+
628
+static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
629
+{
630
+ struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
631
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
632
+ unsigned long pixel_rate, hsm_rate;
633
+ int ret;
634
+
635
+ ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev);
636
+ if (ret < 0) {
637
+ DRM_ERROR("Failed to retain power domain: %d\n", ret);
638
+ return;
639
+ }
640
+
641
+ pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
642
+ ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
643
+ if (ret) {
644
+ DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
645
+ return;
646
+ }
647
+
648
+ ret = clk_prepare_enable(vc4_hdmi->pixel_clock);
649
+ if (ret) {
650
+ DRM_ERROR("Failed to turn on pixel clock: %d\n", ret);
651
+ return;
652
+ }
653
+
701654 /*
702655 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
703656 * be faster than pixel clock, infinitesimally faster, tested in
....@@ -714,46 +667,244 @@
714667 * Additionally, the AXI clock needs to be at least 25% of
715668 * pixel clock, but HSM ends up being the limiting factor.
716669 */
717
- if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100))
670
+ hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
671
+ ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate);
672
+ if (ret) {
673
+ DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
674
+ return;
675
+ }
676
+
677
+ vc4_hdmi_cec_update_clk_div(vc4_hdmi);
678
+
679
+ /*
680
+ * FIXME: When the pixel freq is 594MHz (4k60), this needs to be setup
681
+ * at 300MHz.
682
+ */
683
+ ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock,
684
+ (hsm_rate > VC4_HSM_MID_CLOCK ? 150000000 : 75000000));
685
+ if (ret) {
686
+ DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret);
687
+ clk_disable_unprepare(vc4_hdmi->pixel_clock);
688
+ return;
689
+ }
690
+
691
+ ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock);
692
+ if (ret) {
693
+ DRM_ERROR("Failed to turn on pixel bvb clock: %d\n", ret);
694
+ clk_disable_unprepare(vc4_hdmi->pixel_clock);
695
+ return;
696
+ }
697
+
698
+ if (vc4_hdmi->variant->phy_init)
699
+ vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
700
+
701
+ HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
702
+ HDMI_READ(HDMI_SCHEDULER_CONTROL) |
703
+ VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
704
+ VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
705
+
706
+ if (vc4_hdmi->variant->set_timings)
707
+ vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
708
+}
709
+
710
+static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
711
+{
712
+ struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
713
+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
714
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
715
+
716
+ if (vc4_encoder->hdmi_monitor &&
717
+ drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {
718
+ if (vc4_hdmi->variant->csc_setup)
719
+ vc4_hdmi->variant->csc_setup(vc4_hdmi, true);
720
+
721
+ vc4_encoder->limited_rgb_range = true;
722
+ } else {
723
+ if (vc4_hdmi->variant->csc_setup)
724
+ vc4_hdmi->variant->csc_setup(vc4_hdmi, false);
725
+
726
+ vc4_encoder->limited_rgb_range = false;
727
+ }
728
+
729
+ HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
730
+}
731
+
732
+static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
733
+{
734
+ struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
735
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
736
+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
737
+ bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
738
+ bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
739
+ int ret;
740
+
741
+ HDMI_WRITE(HDMI_VID_CTL,
742
+ VC4_HD_VID_CTL_ENABLE |
743
+ VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
744
+ VC4_HD_VID_CTL_FRAME_COUNTER_RESET |
745
+ (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
746
+ (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
747
+
748
+ HDMI_WRITE(HDMI_VID_CTL,
749
+ HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_BLANKPIX);
750
+
751
+ if (vc4_encoder->hdmi_monitor) {
752
+ HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
753
+ HDMI_READ(HDMI_SCHEDULER_CONTROL) |
754
+ VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
755
+
756
+ ret = wait_for(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
757
+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000);
758
+ WARN_ONCE(ret, "Timeout waiting for "
759
+ "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
760
+ } else {
761
+ HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
762
+ HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
763
+ ~(VC4_HDMI_RAM_PACKET_ENABLE));
764
+ HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
765
+ HDMI_READ(HDMI_SCHEDULER_CONTROL) &
766
+ ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
767
+
768
+ ret = wait_for(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
769
+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000);
770
+ WARN_ONCE(ret, "Timeout waiting for "
771
+ "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
772
+ }
773
+
774
+ if (vc4_encoder->hdmi_monitor) {
775
+ WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
776
+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
777
+ HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
778
+ HDMI_READ(HDMI_SCHEDULER_CONTROL) |
779
+ VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT);
780
+
781
+ HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
782
+ VC4_HDMI_RAM_PACKET_ENABLE);
783
+
784
+ vc4_hdmi_set_infoframes(encoder);
785
+ }
786
+
787
+ vc4_hdmi_recenter_fifo(vc4_hdmi);
788
+}
789
+
790
+static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
791
+{
792
+}
793
+
794
+#define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL
795
+#define WIFI_2_4GHz_CH1_MAX_FREQ 2422000000ULL
796
+
797
+static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
798
+ struct drm_crtc_state *crtc_state,
799
+ struct drm_connector_state *conn_state)
800
+{
801
+ struct drm_display_mode *mode = &crtc_state->adjusted_mode;
802
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
803
+ unsigned long long pixel_rate = mode->clock * 1000;
804
+ unsigned long long tmds_rate;
805
+
806
+ if (vc4_hdmi->variant->unsupported_odd_h_timings &&
807
+ !(mode->flags & DRM_MODE_FLAG_DBLCLK) &&
808
+ ((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
809
+ (mode->hsync_end % 2) || (mode->htotal % 2)))
810
+ return -EINVAL;
811
+
812
+ /*
813
+ * The 1440p@60 pixel rate is in the same range than the first
814
+ * WiFi channel (between 2.4GHz and 2.422GHz with 22MHz
815
+ * bandwidth). Slightly lower the frequency to bring it out of
816
+ * the WiFi range.
817
+ */
818
+ tmds_rate = pixel_rate * 10;
819
+ if (vc4_hdmi->disable_wifi_frequencies &&
820
+ (tmds_rate >= WIFI_2_4GHz_CH1_MIN_FREQ &&
821
+ tmds_rate <= WIFI_2_4GHz_CH1_MAX_FREQ)) {
822
+ mode->clock = 238560;
823
+ pixel_rate = mode->clock * 1000;
824
+ }
825
+
826
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
827
+ pixel_rate = pixel_rate * 2;
828
+
829
+ if (pixel_rate > vc4_hdmi->variant->max_pixel_clock)
830
+ return -EINVAL;
831
+
832
+ return 0;
833
+}
834
+
835
+static enum drm_mode_status
836
+vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
837
+ const struct drm_display_mode *mode)
838
+{
839
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
840
+
841
+ if (vc4_hdmi->variant->unsupported_odd_h_timings &&
842
+ !(mode->flags & DRM_MODE_FLAG_DBLCLK) &&
843
+ ((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
844
+ (mode->hsync_end % 2) || (mode->htotal % 2)))
845
+ return MODE_H_ILLEGAL;
846
+
847
+ if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock)
718848 return MODE_CLOCK_HIGH;
719849
720850 return MODE_OK;
721851 }
722852
723853 static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
854
+ .atomic_check = vc4_hdmi_encoder_atomic_check,
724855 .mode_valid = vc4_hdmi_encoder_mode_valid,
725856 .disable = vc4_hdmi_encoder_disable,
726857 .enable = vc4_hdmi_encoder_enable,
727858 };
728859
729
-/* HDMI audio codec callbacks */
730
-static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
860
+static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
731861 {
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);
862
+ int i;
863
+ u32 channel_map = 0;
864
+
865
+ for (i = 0; i < 8; i++) {
866
+ if (channel_mask & BIT(i))
867
+ channel_map |= i << (3 * i);
868
+ }
869
+ return channel_map;
870
+}
871
+
872
+static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
873
+{
874
+ int i;
875
+ u32 channel_map = 0;
876
+
877
+ for (i = 0; i < 8; i++) {
878
+ if (channel_mask & BIT(i))
879
+ channel_map |= i << (4 * i);
880
+ }
881
+ return channel_map;
882
+}
883
+
884
+/* HDMI audio codec callbacks */
885
+static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
886
+{
887
+ u32 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock);
735888 unsigned long n, m;
736889
737
- rational_best_approximation(hsm_clock, hdmi->audio.samplerate,
890
+ rational_best_approximation(hsm_clock, vc4_hdmi->audio.samplerate,
738891 VC4_HD_MAI_SMP_N_MASK >>
739892 VC4_HD_MAI_SMP_N_SHIFT,
740893 (VC4_HD_MAI_SMP_M_MASK >>
741894 VC4_HD_MAI_SMP_M_SHIFT) + 1,
742895 &n, &m);
743896
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));
897
+ HDMI_WRITE(HDMI_MAI_SMP,
898
+ VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
899
+ VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
747900 }
748901
749
-static void vc4_hdmi_set_n_cts(struct vc4_hdmi *hdmi)
902
+static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
750903 {
751
- struct drm_encoder *encoder = hdmi->encoder;
904
+ struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
752905 struct drm_crtc *crtc = encoder->crtc;
753
- struct drm_device *drm = encoder->dev;
754
- struct vc4_dev *vc4 = to_vc4_dev(drm);
755906 const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
756
- u32 samplerate = hdmi->audio.samplerate;
907
+ u32 samplerate = vc4_hdmi->audio.samplerate;
757908 u32 n, cts;
758909 u64 tmp;
759910
....@@ -762,7 +913,7 @@
762913 do_div(tmp, 128 * samplerate);
763914 cts = tmp;
764915
765
- HDMI_WRITE(VC4_HDMI_CRP_CFG,
916
+ HDMI_WRITE(HDMI_CRP_CFG,
766917 VC4_HDMI_CRP_CFG_EXTERNAL_CTS_EN |
767918 VC4_SET_FIELD(n, VC4_HDMI_CRP_CFG_N));
768919
....@@ -771,8 +922,8 @@
771922 * providing a CTS_1 value. The two CTS values are alternated
772923 * between based on the period fields
773924 */
774
- HDMI_WRITE(VC4_HDMI_CTS_0, cts);
775
- HDMI_WRITE(VC4_HDMI_CTS_1, cts);
925
+ HDMI_WRITE(HDMI_CTS_0, cts);
926
+ HDMI_WRITE(HDMI_CTS_1, cts);
776927 }
777928
778929 static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai)
....@@ -785,26 +936,25 @@
785936 static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
786937 struct snd_soc_dai *dai)
787938 {
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);
939
+ struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
940
+ struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
941
+ struct drm_connector *connector = &vc4_hdmi->connector;
791942 int ret;
792943
793
- if (hdmi->audio.substream && hdmi->audio.substream != substream)
944
+ if (vc4_hdmi->audio.substream && vc4_hdmi->audio.substream != substream)
794945 return -EINVAL;
795946
796
- hdmi->audio.substream = substream;
947
+ vc4_hdmi->audio.substream = substream;
797948
798949 /*
799950 * If the HDMI encoder hasn't probed, or the encoder is
800951 * currently in DVI mode, treat the codec dai as missing.
801952 */
802
- if (!encoder->crtc || !(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
953
+ if (!encoder->crtc || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
803954 VC4_HDMI_RAM_PACKET_ENABLE))
804955 return -ENODEV;
805956
806
- ret = snd_pcm_hw_constraint_eld(substream->runtime,
807
- hdmi->connector->eld);
957
+ ret = snd_pcm_hw_constraint_eld(substream->runtime, connector->eld);
808958 if (ret)
809959 return ret;
810960
....@@ -816,34 +966,33 @@
816966 return 0;
817967 }
818968
819
-static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi)
969
+static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
820970 {
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);
971
+ struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
972
+ struct device *dev = &vc4_hdmi->pdev->dev;
825973 int ret;
826974
975
+ vc4_hdmi->audio.streaming = false;
827976 ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO);
828977 if (ret)
829978 dev_err(dev, "Failed to stop audio infoframe: %d\n", ret);
830979
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);
980
+ HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_RESET);
981
+ HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_ERRORF);
982
+ HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
834983 }
835984
836985 static void vc4_hdmi_audio_shutdown(struct snd_pcm_substream *substream,
837986 struct snd_soc_dai *dai)
838987 {
839
- struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
988
+ struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
840989
841
- if (substream != hdmi->audio.substream)
990
+ if (substream != vc4_hdmi->audio.substream)
842991 return;
843992
844
- vc4_hdmi_audio_reset(hdmi);
993
+ vc4_hdmi_audio_reset(vc4_hdmi);
845994
846
- hdmi->audio.substream = NULL;
995
+ vc4_hdmi->audio.substream = NULL;
847996 }
848997
849998 /* HDMI audio codec callbacks */
....@@ -851,72 +1000,58 @@
8511000 struct snd_pcm_hw_params *params,
8521001 struct snd_soc_dai *dai)
8531002 {
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);
1003
+ struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
1004
+ struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
1005
+ struct device *dev = &vc4_hdmi->pdev->dev;
8591006 u32 audio_packet_config, channel_mask;
860
- u32 channel_map, i;
1007
+ u32 channel_map;
8611008
862
- if (substream != hdmi->audio.substream)
1009
+ if (substream != vc4_hdmi->audio.substream)
8631010 return -EINVAL;
8641011
8651012 dev_dbg(dev, "%s: %u Hz, %d bit, %d channels\n", __func__,
8661013 params_rate(params), params_width(params),
8671014 params_channels(params));
8681015
869
- hdmi->audio.channels = params_channels(params);
870
- hdmi->audio.samplerate = params_rate(params);
1016
+ vc4_hdmi->audio.channels = params_channels(params);
1017
+ vc4_hdmi->audio.samplerate = params_rate(params);
8711018
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);
1019
+ HDMI_WRITE(HDMI_MAI_CTL,
1020
+ VC4_HD_MAI_CTL_RESET |
1021
+ VC4_HD_MAI_CTL_FLUSH |
1022
+ VC4_HD_MAI_CTL_DLATE |
1023
+ VC4_HD_MAI_CTL_ERRORE |
1024
+ VC4_HD_MAI_CTL_ERRORF);
8781025
879
- vc4_hdmi_audio_set_mai_clock(hdmi);
1026
+ vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
8801027
1028
+ /* The B frame identifier should match the value used by alsa-lib (8) */
8811029 audio_packet_config =
8821030 VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT |
8831031 VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS |
884
- VC4_SET_FIELD(0xf, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER);
1032
+ VC4_SET_FIELD(0x8, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER);
8851033
886
- channel_mask = GENMASK(hdmi->audio.channels - 1, 0);
1034
+ channel_mask = GENMASK(vc4_hdmi->audio.channels - 1, 0);
8871035 audio_packet_config |= VC4_SET_FIELD(channel_mask,
8881036 VC4_HDMI_AUDIO_PACKET_CEA_MASK);
8891037
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
- }
1038
+ /* Set the MAI threshold */
1039
+ HDMI_WRITE(HDMI_MAI_THR,
1040
+ VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_PANICHIGH) |
1041
+ VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_PANICLOW) |
1042
+ VC4_SET_FIELD(0x06, VC4_HD_MAI_THR_DREQHIGH) |
1043
+ VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_DREQLOW));
9061044
907
- HDMI_WRITE(VC4_HDMI_MAI_CONFIG,
1045
+ HDMI_WRITE(HDMI_MAI_CONFIG,
9081046 VC4_HDMI_MAI_CONFIG_BIT_REVERSE |
9091047 VC4_SET_FIELD(channel_mask, VC4_HDMI_MAI_CHANNEL_MASK));
9101048
911
- channel_map = 0;
912
- for (i = 0; i < 8; i++) {
913
- if (channel_mask & BIT(i))
914
- channel_map |= i << (3 * i);
915
- }
1049
+ channel_map = vc4_hdmi->variant->channel_map(vc4_hdmi, channel_mask);
1050
+ HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map);
1051
+ HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
1052
+ vc4_hdmi_set_n_cts(vc4_hdmi);
9161053
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);
1054
+ vc4_hdmi_set_audio_infoframe(encoder);
9201055
9211056 return 0;
9221057 }
....@@ -924,30 +1059,33 @@
9241059 static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
9251060 struct snd_soc_dai *dai)
9261061 {
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);
1062
+ struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
9311063
9321064 switch (cmd) {
9331065 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);
1066
+ vc4_hdmi->audio.streaming = true;
1067
+
1068
+ if (vc4_hdmi->variant->phy_rng_enable)
1069
+ vc4_hdmi->variant->phy_rng_enable(vc4_hdmi);
1070
+
1071
+ HDMI_WRITE(HDMI_MAI_CTL,
1072
+ VC4_SET_FIELD(vc4_hdmi->audio.channels,
1073
+ VC4_HD_MAI_CTL_CHNUM) |
1074
+ VC4_HD_MAI_CTL_WHOLSMP |
1075
+ VC4_HD_MAI_CTL_CHALIGN |
1076
+ VC4_HD_MAI_CTL_ENABLE);
9421077 break;
9431078 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);
1079
+ HDMI_WRITE(HDMI_MAI_CTL,
1080
+ VC4_HD_MAI_CTL_DLATE |
1081
+ VC4_HD_MAI_CTL_ERRORE |
1082
+ VC4_HD_MAI_CTL_ERRORF);
1083
+
1084
+ if (vc4_hdmi->variant->phy_rng_disable)
1085
+ vc4_hdmi->variant->phy_rng_disable(vc4_hdmi);
1086
+
1087
+ vc4_hdmi->audio.streaming = false;
1088
+
9511089 break;
9521090 default:
9531091 break;
....@@ -968,10 +1106,11 @@
9681106 struct snd_ctl_elem_info *uinfo)
9691107 {
9701108 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
971
- struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
1109
+ struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
1110
+ struct drm_connector *connector = &vc4_hdmi->connector;
9721111
9731112 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
974
- uinfo->count = sizeof(hdmi->connector->eld);
1113
+ uinfo->count = sizeof(connector->eld);
9751114
9761115 return 0;
9771116 }
....@@ -980,10 +1119,11 @@
9801119 struct snd_ctl_elem_value *ucontrol)
9811120 {
9821121 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
983
- struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
1122
+ struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
1123
+ struct drm_connector *connector = &vc4_hdmi->connector;
9841124
985
- memcpy(ucontrol->value.bytes.data, hdmi->connector->eld,
986
- sizeof(hdmi->connector->eld));
1125
+ memcpy(ucontrol->value.bytes.data, connector->eld,
1126
+ sizeof(connector->eld));
9871127
9881128 return 0;
9891129 }
....@@ -1008,6 +1148,7 @@
10081148 };
10091149
10101150 static const struct snd_soc_component_driver vc4_hdmi_audio_component_drv = {
1151
+ .name = "vc4-hdmi-codec-dai-component",
10111152 .controls = vc4_hdmi_audio_controls,
10121153 .num_controls = ARRAY_SIZE(vc4_hdmi_audio_controls),
10131154 .dapm_widgets = vc4_hdmi_audio_widgets,
....@@ -1048,9 +1189,9 @@
10481189
10491190 static int vc4_hdmi_audio_cpu_dai_probe(struct snd_soc_dai *dai)
10501191 {
1051
- struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
1192
+ struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
10521193
1053
- snd_soc_dai_init_dma_data(dai, &hdmi->audio.dma_data, NULL);
1194
+ snd_soc_dai_init_dma_data(dai, &vc4_hdmi->audio.dma_data, NULL);
10541195
10551196 return 0;
10561197 }
....@@ -1076,18 +1217,26 @@
10761217 .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
10771218 };
10781219
1079
-static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
1220
+static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
10801221 {
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;
1222
+ const struct vc4_hdmi_register *mai_data =
1223
+ &vc4_hdmi->variant->registers[HDMI_MAI_DATA];
1224
+ struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link;
1225
+ struct snd_soc_card *card = &vc4_hdmi->audio.card;
1226
+ struct device *dev = &vc4_hdmi->pdev->dev;
10841227 const __be32 *addr;
1228
+ int index, len;
10851229 int ret;
10861230
1087
- if (!of_find_property(dev->of_node, "dmas", NULL)) {
1231
+ if (!of_find_property(dev->of_node, "dmas", &len) || !len) {
10881232 dev_warn(dev,
1089
- "'dmas' DT property is missing, no HDMI audio\n");
1233
+ "'dmas' DT property is missing or empty, no HDMI audio\n");
10901234 return 0;
1235
+ }
1236
+
1237
+ if (mai_data->reg != VC4_HD) {
1238
+ WARN_ONCE(true, "MAI isn't in the HD block\n");
1239
+ return -EINVAL;
10911240 }
10921241
10931242 /*
....@@ -1097,10 +1246,16 @@
10971246 * for DMA transfers.
10981247 * This VC/MMU should probably be exposed to avoid this kind of hacks.
10991248 */
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;
1249
+ index = of_property_match_string(dev->of_node, "reg-names", "hd");
1250
+ /* Before BCM2711, we don't have a named register range */
1251
+ if (index < 0)
1252
+ index = 1;
1253
+
1254
+ addr = of_get_address(dev->of_node, index, NULL, NULL);
1255
+
1256
+ vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset;
1257
+ vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
1258
+ vc4_hdmi->audio.dma_data.maxburst = 2;
11041259
11051260 ret = devm_snd_dmaengine_pcm_register(dev, &pcm_conf, 0);
11061261 if (ret) {
....@@ -1123,16 +1278,25 @@
11231278 return ret;
11241279 }
11251280
1281
+ dai_link->cpus = &vc4_hdmi->audio.cpu;
1282
+ dai_link->codecs = &vc4_hdmi->audio.codec;
1283
+ dai_link->platforms = &vc4_hdmi->audio.platform;
1284
+
1285
+ dai_link->num_cpus = 1;
1286
+ dai_link->num_codecs = 1;
1287
+ dai_link->num_platforms = 1;
1288
+
11261289 dai_link->name = "MAI";
11271290 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);
1291
+ dai_link->codecs->dai_name = vc4_hdmi_audio_codec_dai_drv.name;
1292
+ dai_link->cpus->dai_name = dev_name(dev);
1293
+ dai_link->codecs->name = dev_name(dev);
1294
+ dai_link->platforms->name = dev_name(dev);
11321295
11331296 card->dai_link = dai_link;
11341297 card->num_links = 1;
1135
- card->name = "vc4-hdmi";
1298
+ card->name = vc4_hdmi->variant->card_name;
1299
+ card->driver_name = "vc4-hdmi";
11361300 card->dev = dev;
11371301 card->owner = THIS_MODULE;
11381302
....@@ -1143,7 +1307,7 @@
11431307 * now stored in card->drvdata and should be retrieved with
11441308 * snd_soc_card_get_drvdata() if needed.
11451309 */
1146
- snd_soc_card_set_drvdata(card, hdmi);
1310
+ snd_soc_card_set_drvdata(card, vc4_hdmi);
11471311 ret = devm_snd_soc_register_card(dev, card);
11481312 if (ret)
11491313 dev_err(dev, "Could not register sound card: %d\n", ret);
....@@ -1155,35 +1319,42 @@
11551319 #ifdef CONFIG_DRM_VC4_HDMI_CEC
11561320 static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
11571321 {
1158
- struct vc4_dev *vc4 = priv;
1159
- struct vc4_hdmi *hdmi = vc4->hdmi;
1322
+ struct vc4_hdmi *vc4_hdmi = priv;
11601323
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,
1324
+ if (vc4_hdmi->cec_irq_was_rx) {
1325
+ if (vc4_hdmi->cec_rx_msg.len)
1326
+ cec_received_msg(vc4_hdmi->cec_adap,
1327
+ &vc4_hdmi->cec_rx_msg);
1328
+ } else if (vc4_hdmi->cec_tx_ok) {
1329
+ cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_OK,
11661330 0, 0, 0, 0);
11671331 } else {
11681332 /*
11691333 * This CEC implementation makes 1 retry, so if we
11701334 * get a NACK, then that means it made 2 attempts.
11711335 */
1172
- cec_transmit_done(hdmi->cec_adap, CEC_TX_STATUS_NACK,
1336
+ cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_NACK,
11731337 0, 2, 0, 0);
11741338 }
11751339 return IRQ_HANDLED;
11761340 }
11771341
1178
-static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1)
1342
+static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
11791343 {
1180
- struct cec_msg *msg = &vc4->hdmi->cec_rx_msg;
1344
+ struct drm_device *dev = vc4_hdmi->connector.dev;
1345
+ struct cec_msg *msg = &vc4_hdmi->cec_rx_msg;
11811346 unsigned int i;
11821347
11831348 msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >>
11841349 VC4_HDMI_CEC_REC_WRD_CNT_SHIFT);
1350
+
1351
+ if (msg->len > 16) {
1352
+ drm_err(dev, "Attempting to read too much data (%d)\n", msg->len);
1353
+ return;
1354
+ }
1355
+
11851356 for (i = 0; i < msg->len; i += 4) {
1186
- u32 val = HDMI_READ(VC4_HDMI_CEC_RX_DATA_1 + i);
1357
+ u32 val = HDMI_READ(HDMI_CEC_RX_DATA_1 + (i >> 2));
11871358
11881359 msg->msg[i] = val & 0xff;
11891360 msg->msg[i + 1] = (val >> 8) & 0xff;
....@@ -1194,38 +1365,37 @@
11941365
11951366 static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
11961367 {
1197
- struct vc4_dev *vc4 = priv;
1198
- struct vc4_hdmi *hdmi = vc4->hdmi;
1199
- u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS);
1368
+ struct vc4_hdmi *vc4_hdmi = priv;
1369
+ u32 stat = HDMI_READ(HDMI_CEC_CPU_STATUS);
12001370 u32 cntrl1, cntrl5;
12011371
12021372 if (!(stat & VC4_HDMI_CPU_CEC))
12031373 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);
1374
+ vc4_hdmi->cec_rx_msg.len = 0;
1375
+ cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1);
1376
+ cntrl5 = HDMI_READ(HDMI_CEC_CNTRL_5);
1377
+ vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
1378
+ if (vc4_hdmi->cec_irq_was_rx) {
1379
+ vc4_cec_read_msg(vc4_hdmi, cntrl1);
12101380 cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
1211
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
1381
+ HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
12121382 cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
12131383 } else {
1214
- hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
1384
+ vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
12151385 cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
12161386 }
1217
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
1218
- HDMI_WRITE(VC4_HDMI_CPU_CLEAR, VC4_HDMI_CPU_CEC);
1387
+ HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
1388
+ HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC);
12191389
12201390 return IRQ_WAKE_THREAD;
12211391 }
12221392
12231393 static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
12241394 {
1225
- struct vc4_dev *vc4 = cec_get_drvdata(adap);
1395
+ struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
12261396 /* clock period in microseconds */
12271397 const u32 usecs = 1000000 / CEC_CLOCK_FREQ;
1228
- u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
1398
+ u32 val = HDMI_READ(HDMI_CEC_CNTRL_5);
12291399
12301400 val &= ~(VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET |
12311401 VC4_HDMI_CEC_CNT_TO_4700_US_MASK |
....@@ -1234,30 +1404,30 @@
12341404 ((4500 / usecs) << VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT);
12351405
12361406 if (enable) {
1237
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val |
1407
+ HDMI_WRITE(HDMI_CEC_CNTRL_5, val |
12381408 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));
1409
+ HDMI_WRITE(HDMI_CEC_CNTRL_5, val);
1410
+ HDMI_WRITE(HDMI_CEC_CNTRL_2,
1411
+ ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) |
1412
+ ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) |
1413
+ ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) |
1414
+ ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) |
1415
+ ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT));
1416
+ HDMI_WRITE(HDMI_CEC_CNTRL_3,
1417
+ ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) |
1418
+ ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) |
1419
+ ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) |
1420
+ ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT));
1421
+ HDMI_WRITE(HDMI_CEC_CNTRL_4,
1422
+ ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) |
1423
+ ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) |
1424
+ ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) |
1425
+ ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT));
12561426
1257
- HDMI_WRITE(VC4_HDMI_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
1427
+ HDMI_WRITE(HDMI_CEC_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
12581428 } else {
1259
- HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
1260
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val |
1429
+ HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
1430
+ HDMI_WRITE(HDMI_CEC_CNTRL_5, val |
12611431 VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET);
12621432 }
12631433 return 0;
....@@ -1265,10 +1435,10 @@
12651435
12661436 static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
12671437 {
1268
- struct vc4_dev *vc4 = cec_get_drvdata(adap);
1438
+ struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
12691439
1270
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1,
1271
- (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
1440
+ HDMI_WRITE(HDMI_CEC_CNTRL_1,
1441
+ (HDMI_READ(HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
12721442 (log_addr & 0xf) << VC4_HDMI_CEC_ADDR_SHIFT);
12731443 return 0;
12741444 }
....@@ -1276,25 +1446,31 @@
12761446 static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
12771447 u32 signal_free_time, struct cec_msg *msg)
12781448 {
1279
- struct vc4_dev *vc4 = cec_get_drvdata(adap);
1449
+ struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
1450
+ struct drm_device *dev = vc4_hdmi->connector.dev;
12801451 u32 val;
12811452 unsigned int i;
12821453
1454
+ if (msg->len > 16) {
1455
+ drm_err(dev, "Attempting to transmit too much data (%d)\n", msg->len);
1456
+ return -ENOMEM;
1457
+ }
1458
+
12831459 for (i = 0; i < msg->len; i += 4)
1284
- HDMI_WRITE(VC4_HDMI_CEC_TX_DATA_1 + i,
1460
+ HDMI_WRITE(HDMI_CEC_TX_DATA_1 + (i >> 2),
12851461 (msg->msg[i]) |
12861462 (msg->msg[i + 1] << 8) |
12871463 (msg->msg[i + 2] << 16) |
12881464 (msg->msg[i + 3] << 24));
12891465
1290
- val = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
1466
+ val = HDMI_READ(HDMI_CEC_CNTRL_1);
12911467 val &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
1292
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val);
1468
+ HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
12931469 val &= ~VC4_HDMI_CEC_MESSAGE_LENGTH_MASK;
12941470 val |= (msg->len - 1) << VC4_HDMI_CEC_MESSAGE_LENGTH_SHIFT;
12951471 val |= VC4_HDMI_CEC_START_XMIT_BEGIN;
12961472
1297
- HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val);
1473
+ HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
12981474 return 0;
12991475 }
13001476
....@@ -1303,49 +1479,296 @@
13031479 .adap_log_addr = vc4_hdmi_cec_adap_log_addr,
13041480 .adap_transmit = vc4_hdmi_cec_adap_transmit,
13051481 };
1482
+
1483
+static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
1484
+{
1485
+ struct cec_connector_info conn_info;
1486
+ struct platform_device *pdev = vc4_hdmi->pdev;
1487
+ u32 value;
1488
+ int ret;
1489
+
1490
+ if (!vc4_hdmi->variant->cec_available)
1491
+ return 0;
1492
+
1493
+ vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
1494
+ vc4_hdmi, "vc4",
1495
+ CEC_CAP_DEFAULTS |
1496
+ CEC_CAP_CONNECTOR_INFO, 1);
1497
+ ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
1498
+ if (ret < 0)
1499
+ return ret;
1500
+
1501
+ cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
1502
+ cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
1503
+
1504
+ HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
1505
+
1506
+ value = HDMI_READ(HDMI_CEC_CNTRL_1);
1507
+ /* Set the logical address to Unregistered */
1508
+ value |= VC4_HDMI_CEC_ADDR_MASK;
1509
+ HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
1510
+
1511
+ vc4_hdmi_cec_update_clk_div(vc4_hdmi);
1512
+
1513
+ ret = devm_request_threaded_irq(&pdev->dev, platform_get_irq(pdev, 0),
1514
+ vc4_cec_irq_handler,
1515
+ vc4_cec_irq_handler_thread, 0,
1516
+ "vc4 hdmi cec", vc4_hdmi);
1517
+ if (ret)
1518
+ goto err_delete_cec_adap;
1519
+
1520
+ ret = cec_register_adapter(vc4_hdmi->cec_adap, &pdev->dev);
1521
+ if (ret < 0)
1522
+ goto err_delete_cec_adap;
1523
+
1524
+ return 0;
1525
+
1526
+err_delete_cec_adap:
1527
+ cec_delete_adapter(vc4_hdmi->cec_adap);
1528
+
1529
+ return ret;
1530
+}
1531
+
1532
+static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi)
1533
+{
1534
+ cec_unregister_adapter(vc4_hdmi->cec_adap);
1535
+}
1536
+#else
1537
+static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
1538
+{
1539
+ return 0;
1540
+}
1541
+
1542
+static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) {};
1543
+
1544
+#endif
1545
+
1546
+static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
1547
+ struct debugfs_regset32 *regset,
1548
+ enum vc4_hdmi_regs reg)
1549
+{
1550
+ const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
1551
+ struct debugfs_reg32 *regs, *new_regs;
1552
+ unsigned int count = 0;
1553
+ unsigned int i;
1554
+
1555
+ regs = kcalloc(variant->num_registers, sizeof(*regs),
1556
+ GFP_KERNEL);
1557
+ if (!regs)
1558
+ return -ENOMEM;
1559
+
1560
+ for (i = 0; i < variant->num_registers; i++) {
1561
+ const struct vc4_hdmi_register *field = &variant->registers[i];
1562
+
1563
+ if (field->reg != reg)
1564
+ continue;
1565
+
1566
+ regs[count].name = field->name;
1567
+ regs[count].offset = field->offset;
1568
+ count++;
1569
+ }
1570
+
1571
+ new_regs = krealloc(regs, count * sizeof(*regs), GFP_KERNEL);
1572
+ if (!new_regs)
1573
+ return -ENOMEM;
1574
+
1575
+ regset->base = __vc4_hdmi_get_field_base(vc4_hdmi, reg);
1576
+ regset->regs = new_regs;
1577
+ regset->nregs = count;
1578
+
1579
+ return 0;
1580
+}
1581
+
1582
+static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
1583
+{
1584
+ struct platform_device *pdev = vc4_hdmi->pdev;
1585
+ struct device *dev = &pdev->dev;
1586
+ int ret;
1587
+
1588
+ vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
1589
+ if (IS_ERR(vc4_hdmi->hdmicore_regs))
1590
+ return PTR_ERR(vc4_hdmi->hdmicore_regs);
1591
+
1592
+ vc4_hdmi->hd_regs = vc4_ioremap_regs(pdev, 1);
1593
+ if (IS_ERR(vc4_hdmi->hd_regs))
1594
+ return PTR_ERR(vc4_hdmi->hd_regs);
1595
+
1596
+ ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD);
1597
+ if (ret)
1598
+ return ret;
1599
+
1600
+ ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI);
1601
+ if (ret)
1602
+ return ret;
1603
+
1604
+ vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel");
1605
+ if (IS_ERR(vc4_hdmi->pixel_clock)) {
1606
+ ret = PTR_ERR(vc4_hdmi->pixel_clock);
1607
+ if (ret != -EPROBE_DEFER)
1608
+ DRM_ERROR("Failed to get pixel clock\n");
1609
+ return ret;
1610
+ }
1611
+
1612
+ vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
1613
+ if (IS_ERR(vc4_hdmi->hsm_clock)) {
1614
+ DRM_ERROR("Failed to get HDMI state machine clock\n");
1615
+ return PTR_ERR(vc4_hdmi->hsm_clock);
1616
+ }
1617
+ vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock;
1618
+
1619
+ return 0;
1620
+}
1621
+
1622
+static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
1623
+{
1624
+ struct platform_device *pdev = vc4_hdmi->pdev;
1625
+ struct device *dev = &pdev->dev;
1626
+ struct resource *res;
1627
+
1628
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi");
1629
+ if (!res)
1630
+ return -ENODEV;
1631
+
1632
+ vc4_hdmi->hdmicore_regs = devm_ioremap(dev, res->start,
1633
+ resource_size(res));
1634
+ if (!vc4_hdmi->hdmicore_regs)
1635
+ return -ENOMEM;
1636
+
1637
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hd");
1638
+ if (!res)
1639
+ return -ENODEV;
1640
+
1641
+ vc4_hdmi->hd_regs = devm_ioremap(dev, res->start, resource_size(res));
1642
+ if (!vc4_hdmi->hd_regs)
1643
+ return -ENOMEM;
1644
+
1645
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cec");
1646
+ if (!res)
1647
+ return -ENODEV;
1648
+
1649
+ vc4_hdmi->cec_regs = devm_ioremap(dev, res->start, resource_size(res));
1650
+ if (!vc4_hdmi->cec_regs)
1651
+ return -ENOMEM;
1652
+
1653
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csc");
1654
+ if (!res)
1655
+ return -ENODEV;
1656
+
1657
+ vc4_hdmi->csc_regs = devm_ioremap(dev, res->start, resource_size(res));
1658
+ if (!vc4_hdmi->csc_regs)
1659
+ return -ENOMEM;
1660
+
1661
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dvp");
1662
+ if (!res)
1663
+ return -ENODEV;
1664
+
1665
+ vc4_hdmi->dvp_regs = devm_ioremap(dev, res->start, resource_size(res));
1666
+ if (!vc4_hdmi->dvp_regs)
1667
+ return -ENOMEM;
1668
+
1669
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
1670
+ if (!res)
1671
+ return -ENODEV;
1672
+
1673
+ vc4_hdmi->phy_regs = devm_ioremap(dev, res->start, resource_size(res));
1674
+ if (!vc4_hdmi->phy_regs)
1675
+ return -ENOMEM;
1676
+
1677
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "packet");
1678
+ if (!res)
1679
+ return -ENODEV;
1680
+
1681
+ vc4_hdmi->ram_regs = devm_ioremap(dev, res->start, resource_size(res));
1682
+ if (!vc4_hdmi->ram_regs)
1683
+ return -ENOMEM;
1684
+
1685
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rm");
1686
+ if (!res)
1687
+ return -ENODEV;
1688
+
1689
+ vc4_hdmi->rm_regs = devm_ioremap(dev, res->start, resource_size(res));
1690
+ if (!vc4_hdmi->rm_regs)
1691
+ return -ENOMEM;
1692
+
1693
+ vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
1694
+ if (IS_ERR(vc4_hdmi->hsm_clock)) {
1695
+ DRM_ERROR("Failed to get HDMI state machine clock\n");
1696
+ return PTR_ERR(vc4_hdmi->hsm_clock);
1697
+ }
1698
+
1699
+ vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb");
1700
+ if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) {
1701
+ DRM_ERROR("Failed to get pixel bvb clock\n");
1702
+ return PTR_ERR(vc4_hdmi->pixel_bvb_clock);
1703
+ }
1704
+
1705
+ vc4_hdmi->audio_clock = devm_clk_get(dev, "audio");
1706
+ if (IS_ERR(vc4_hdmi->audio_clock)) {
1707
+ DRM_ERROR("Failed to get audio clock\n");
1708
+ return PTR_ERR(vc4_hdmi->audio_clock);
1709
+ }
1710
+
1711
+ vc4_hdmi->reset = devm_reset_control_get(dev, NULL);
1712
+ if (IS_ERR(vc4_hdmi->reset)) {
1713
+ DRM_ERROR("Failed to get HDMI reset line\n");
1714
+ return PTR_ERR(vc4_hdmi->reset);
1715
+ }
1716
+
1717
+ return 0;
1718
+}
1719
+
1720
+#ifdef CONFIG_PM
1721
+static int vc4_hdmi_runtime_suspend(struct device *dev)
1722
+{
1723
+ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
1724
+
1725
+ clk_disable_unprepare(vc4_hdmi->hsm_clock);
1726
+
1727
+ return 0;
1728
+}
1729
+
1730
+static int vc4_hdmi_runtime_resume(struct device *dev)
1731
+{
1732
+ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
1733
+ int ret;
1734
+
1735
+ ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
1736
+ if (ret)
1737
+ return ret;
1738
+
1739
+ return 0;
1740
+}
13061741 #endif
13071742
13081743 static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
13091744 {
1745
+ const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
13101746 struct platform_device *pdev = to_platform_device(dev);
13111747 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;
1748
+ struct vc4_hdmi *vc4_hdmi;
1749
+ struct drm_encoder *encoder;
13151750 struct device_node *ddc_node;
13161751 u32 value;
13171752 int ret;
13181753
1319
- hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
1320
- if (!hdmi)
1754
+ vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
1755
+ if (!vc4_hdmi)
13211756 return -ENOMEM;
13221757
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;
1758
+ dev_set_drvdata(dev, vc4_hdmi);
1759
+ encoder = &vc4_hdmi->encoder.base.base;
1760
+ vc4_hdmi->encoder.base.type = variant->encoder_type;
1761
+ vc4_hdmi->encoder.base.pre_crtc_configure = vc4_hdmi_encoder_pre_crtc_configure;
1762
+ vc4_hdmi->encoder.base.pre_crtc_enable = vc4_hdmi_encoder_pre_crtc_enable;
1763
+ vc4_hdmi->encoder.base.post_crtc_enable = vc4_hdmi_encoder_post_crtc_enable;
1764
+ vc4_hdmi->encoder.base.post_crtc_disable = vc4_hdmi_encoder_post_crtc_disable;
1765
+ vc4_hdmi->encoder.base.post_crtc_powerdown = vc4_hdmi_encoder_post_crtc_powerdown;
1766
+ vc4_hdmi->pdev = pdev;
1767
+ vc4_hdmi->variant = variant;
13291768
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
- }
1769
+ ret = variant->init_resources(vc4_hdmi);
1770
+ if (ret)
1771
+ return ret;
13491772
13501773 ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
13511774 if (!ddc_node) {
....@@ -1353,28 +1776,11 @@
13531776 return -ENODEV;
13541777 }
13551778
1356
- hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
1779
+ vc4_hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
13571780 of_node_put(ddc_node);
1358
- if (!hdmi->ddc) {
1781
+ if (!vc4_hdmi->ddc) {
13591782 DRM_DEBUG("Failed to get ddc i2c adapter by node\n");
13601783 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;
13781784 }
13791785
13801786 /* Only use the GPIO HPD pin if present in the DT, otherwise
....@@ -1383,89 +1789,76 @@
13831789 if (of_find_property(dev->of_node, "hpd-gpios", &value)) {
13841790 enum of_gpio_flags hpd_gpio_flags;
13851791
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;
1792
+ vc4_hdmi->hpd_gpio = of_get_named_gpio_flags(dev->of_node,
1793
+ "hpd-gpios", 0,
1794
+ &hpd_gpio_flags);
1795
+ if (vc4_hdmi->hpd_gpio < 0) {
1796
+ ret = vc4_hdmi->hpd_gpio;
1797
+ goto err_put_ddc;
13921798 }
13931799
1394
- hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
1800
+ vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
13951801 }
13961802
1397
- vc4->hdmi = hdmi;
1803
+ vc4_hdmi->disable_wifi_frequencies =
1804
+ of_property_read_bool(dev->of_node, "wifi-2.4ghz-coexistence");
13981805
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);
1806
+ /*
1807
+ * If we boot without any cable connected to the HDMI connector,
1808
+ * the firmware will skip the HSM initialization and leave it
1809
+ * with a rate of 0, resulting in a bus lockup when we're
1810
+ * accessing the registers even if it's enabled.
1811
+ *
1812
+ * Let's put a sensible default at runtime_resume so that we
1813
+ * don't end up in this situation.
1814
+ */
1815
+ ret = clk_set_min_rate(vc4_hdmi->hsm_clock, HSM_MIN_CLOCK_FREQ);
1816
+ if (ret)
1817
+ goto err_put_ddc;
14041818
1405
- HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_ENABLE);
1819
+ if (vc4_hdmi->variant->reset)
1820
+ vc4_hdmi->variant->reset(vc4_hdmi);
1821
+
1822
+ if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") ||
1823
+ of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1")) &&
1824
+ HDMI_READ(HDMI_VID_CTL) & VC4_HD_VID_CTL_ENABLE) {
1825
+ clk_prepare_enable(vc4_hdmi->pixel_clock);
1826
+ clk_prepare_enable(vc4_hdmi->hsm_clock);
1827
+ clk_prepare_enable(vc4_hdmi->pixel_bvb_clock);
14061828 }
1829
+
14071830 pm_runtime_enable(dev);
14081831
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);
1832
+ drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
1833
+ drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
14121834
1413
- hdmi->connector = vc4_hdmi_connector_init(drm, hdmi->encoder);
1414
- if (IS_ERR(hdmi->connector)) {
1415
- ret = PTR_ERR(hdmi->connector);
1835
+ ret = vc4_hdmi_connector_init(drm, vc4_hdmi);
1836
+ if (ret)
14161837 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)
1838
+
1839
+ ret = vc4_hdmi_cec_init(vc4_hdmi);
1840
+ if (ret)
14271841 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
14491842
1450
- ret = vc4_hdmi_audio_init(hdmi);
1843
+ ret = vc4_hdmi_audio_init(vc4_hdmi);
14511844 if (ret)
1452
- goto err_destroy_encoder;
1845
+ goto err_free_cec;
1846
+
1847
+ vc4_debugfs_add_file(drm, variant->debugfs_name,
1848
+ vc4_hdmi_debugfs_regs,
1849
+ vc4_hdmi);
14531850
14541851 return 0;
14551852
1456
-#ifdef CONFIG_DRM_VC4_HDMI_CEC
1457
-err_delete_cec_adap:
1458
- cec_delete_adapter(hdmi->cec_adap);
1853
+err_free_cec:
1854
+ vc4_hdmi_cec_exit(vc4_hdmi);
14591855 err_destroy_conn:
1460
- vc4_hdmi_connector_destroy(hdmi->connector);
1461
-#endif
1856
+ vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
14621857 err_destroy_encoder:
1463
- vc4_hdmi_encoder_destroy(hdmi->encoder);
1464
-err_unprepare_hsm:
1465
- clk_disable_unprepare(hdmi->hsm_clock);
1858
+ drm_encoder_cleanup(encoder);
14661859 pm_runtime_disable(dev);
1467
-err_put_i2c:
1468
- put_device(&hdmi->ddc->dev);
1860
+err_put_ddc:
1861
+ put_device(&vc4_hdmi->ddc->dev);
14691862
14701863 return ret;
14711864 }
....@@ -1473,20 +1866,39 @@
14731866 static void vc4_hdmi_unbind(struct device *dev, struct device *master,
14741867 void *data)
14751868 {
1476
- struct drm_device *drm = dev_get_drvdata(master);
1477
- struct vc4_dev *vc4 = drm->dev_private;
1478
- struct vc4_hdmi *hdmi = vc4->hdmi;
1869
+ struct vc4_hdmi *vc4_hdmi;
14791870
1480
- cec_unregister_adapter(hdmi->cec_adap);
1481
- vc4_hdmi_connector_destroy(hdmi->connector);
1482
- vc4_hdmi_encoder_destroy(hdmi->encoder);
1871
+ /*
1872
+ * ASoC makes it a bit hard to retrieve a pointer to the
1873
+ * vc4_hdmi structure. Registering the card will overwrite our
1874
+ * device drvdata with a pointer to the snd_soc_card structure,
1875
+ * which can then be used to retrieve whatever drvdata we want
1876
+ * to associate.
1877
+ *
1878
+ * However, that doesn't fly in the case where we wouldn't
1879
+ * register an ASoC card (because of an old DT that is missing
1880
+ * the dmas properties for example), then the card isn't
1881
+ * registered and the device drvdata wouldn't be set.
1882
+ *
1883
+ * We can deal with both cases by making sure a snd_soc_card
1884
+ * pointer and a vc4_hdmi structure are pointing to the same
1885
+ * memory address, so we can treat them indistinctly without any
1886
+ * issue.
1887
+ */
1888
+ BUILD_BUG_ON(offsetof(struct vc4_hdmi_audio, card) != 0);
1889
+ BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0);
1890
+ vc4_hdmi = dev_get_drvdata(dev);
14831891
1484
- clk_disable_unprepare(hdmi->hsm_clock);
1892
+ kfree(vc4_hdmi->hdmi_regset.regs);
1893
+ kfree(vc4_hdmi->hd_regset.regs);
1894
+
1895
+ vc4_hdmi_cec_exit(vc4_hdmi);
1896
+ vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
1897
+ drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
1898
+
14851899 pm_runtime_disable(dev);
14861900
1487
- put_device(&hdmi->ddc->dev);
1488
-
1489
- vc4->hdmi = NULL;
1901
+ put_device(&vc4_hdmi->ddc->dev);
14901902 }
14911903
14921904 static const struct component_ops vc4_hdmi_ops = {
....@@ -1505,9 +1917,89 @@
15051917 return 0;
15061918 }
15071919
1920
+static const struct vc4_hdmi_variant bcm2835_variant = {
1921
+ .encoder_type = VC4_ENCODER_TYPE_HDMI0,
1922
+ .debugfs_name = "hdmi_regs",
1923
+ .card_name = "vc4-hdmi",
1924
+ .max_pixel_clock = 162000000,
1925
+ .cec_available = true,
1926
+ .registers = vc4_hdmi_fields,
1927
+ .num_registers = ARRAY_SIZE(vc4_hdmi_fields),
1928
+
1929
+ .init_resources = vc4_hdmi_init_resources,
1930
+ .csc_setup = vc4_hdmi_csc_setup,
1931
+ .reset = vc4_hdmi_reset,
1932
+ .set_timings = vc4_hdmi_set_timings,
1933
+ .phy_init = vc4_hdmi_phy_init,
1934
+ .phy_disable = vc4_hdmi_phy_disable,
1935
+ .phy_rng_enable = vc4_hdmi_phy_rng_enable,
1936
+ .phy_rng_disable = vc4_hdmi_phy_rng_disable,
1937
+ .channel_map = vc4_hdmi_channel_map,
1938
+};
1939
+
1940
+static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = {
1941
+ .encoder_type = VC4_ENCODER_TYPE_HDMI0,
1942
+ .debugfs_name = "hdmi0_regs",
1943
+ .card_name = "vc4-hdmi-0",
1944
+ .max_pixel_clock = HDMI_14_MAX_TMDS_CLK,
1945
+ .registers = vc5_hdmi_hdmi0_fields,
1946
+ .num_registers = ARRAY_SIZE(vc5_hdmi_hdmi0_fields),
1947
+ .phy_lane_mapping = {
1948
+ PHY_LANE_0,
1949
+ PHY_LANE_1,
1950
+ PHY_LANE_2,
1951
+ PHY_LANE_CK,
1952
+ },
1953
+ .unsupported_odd_h_timings = true,
1954
+
1955
+ .init_resources = vc5_hdmi_init_resources,
1956
+ .csc_setup = vc5_hdmi_csc_setup,
1957
+ .reset = vc5_hdmi_reset,
1958
+ .set_timings = vc5_hdmi_set_timings,
1959
+ .phy_init = vc5_hdmi_phy_init,
1960
+ .phy_disable = vc5_hdmi_phy_disable,
1961
+ .phy_rng_enable = vc5_hdmi_phy_rng_enable,
1962
+ .phy_rng_disable = vc5_hdmi_phy_rng_disable,
1963
+ .channel_map = vc5_hdmi_channel_map,
1964
+};
1965
+
1966
+static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = {
1967
+ .encoder_type = VC4_ENCODER_TYPE_HDMI1,
1968
+ .debugfs_name = "hdmi1_regs",
1969
+ .card_name = "vc4-hdmi-1",
1970
+ .max_pixel_clock = HDMI_14_MAX_TMDS_CLK,
1971
+ .registers = vc5_hdmi_hdmi1_fields,
1972
+ .num_registers = ARRAY_SIZE(vc5_hdmi_hdmi1_fields),
1973
+ .phy_lane_mapping = {
1974
+ PHY_LANE_1,
1975
+ PHY_LANE_0,
1976
+ PHY_LANE_CK,
1977
+ PHY_LANE_2,
1978
+ },
1979
+ .unsupported_odd_h_timings = true,
1980
+
1981
+ .init_resources = vc5_hdmi_init_resources,
1982
+ .csc_setup = vc5_hdmi_csc_setup,
1983
+ .reset = vc5_hdmi_reset,
1984
+ .set_timings = vc5_hdmi_set_timings,
1985
+ .phy_init = vc5_hdmi_phy_init,
1986
+ .phy_disable = vc5_hdmi_phy_disable,
1987
+ .phy_rng_enable = vc5_hdmi_phy_rng_enable,
1988
+ .phy_rng_disable = vc5_hdmi_phy_rng_disable,
1989
+ .channel_map = vc5_hdmi_channel_map,
1990
+};
1991
+
15081992 static const struct of_device_id vc4_hdmi_dt_match[] = {
1509
- { .compatible = "brcm,bcm2835-hdmi" },
1993
+ { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
1994
+ { .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant },
1995
+ { .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant },
15101996 {}
1997
+};
1998
+
1999
+static const struct dev_pm_ops vc4_hdmi_pm_ops = {
2000
+ SET_RUNTIME_PM_OPS(vc4_hdmi_runtime_suspend,
2001
+ vc4_hdmi_runtime_resume,
2002
+ NULL)
15112003 };
15122004
15132005 struct platform_driver vc4_hdmi_driver = {
....@@ -1516,5 +2008,6 @@
15162008 .driver = {
15172009 .name = "vc4_hdmi",
15182010 .of_match_table = vc4_hdmi_dt_match,
2011
+ .pm = &vc4_hdmi_pm_ops,
15192012 },
15202013 };