Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
26516 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd.
4
* Copyright (c) 2024 Collabora Ltd.
5
*
6
* Author: Algea Cao <[email protected]>
7
* Author: Cristian Ciocaltea <[email protected]>
8
*/
9
#include <linux/completion.h>
10
#include <linux/hdmi.h>
11
#include <linux/export.h>
12
#include <linux/i2c.h>
13
#include <linux/irq.h>
14
#include <linux/module.h>
15
#include <linux/mutex.h>
16
#include <linux/of.h>
17
#include <linux/workqueue.h>
18
19
#include <drm/bridge/dw_hdmi_qp.h>
20
#include <drm/display/drm_hdmi_helper.h>
21
#include <drm/display/drm_hdmi_state_helper.h>
22
#include <drm/drm_atomic.h>
23
#include <drm/drm_atomic_helper.h>
24
#include <drm/drm_bridge.h>
25
#include <drm/drm_connector.h>
26
#include <drm/drm_edid.h>
27
#include <drm/drm_modes.h>
28
29
#include <sound/hdmi-codec.h>
30
31
#include "dw-hdmi-qp.h"
32
33
#define DDC_CI_ADDR 0x37
34
#define DDC_SEGMENT_ADDR 0x30
35
36
#define HDMI14_MAX_TMDSCLK 340000000
37
38
#define SCRAMB_POLL_DELAY_MS 3000
39
40
/*
41
* Unless otherwise noted, entries in this table are 100% optimization.
42
* Values can be obtained from dw_hdmi_qp_compute_n() but that function is
43
* slow so we pre-compute values we expect to see.
44
*
45
* The values for TMDS 25175, 25200, 27000, 54000, 74250 and 148500 kHz are
46
* the recommended N values specified in the Audio chapter of the HDMI
47
* specification.
48
*/
49
static const struct dw_hdmi_audio_tmds_n {
50
unsigned long tmds;
51
unsigned int n_32k;
52
unsigned int n_44k1;
53
unsigned int n_48k;
54
} common_tmds_n_table[] = {
55
{ .tmds = 25175000, .n_32k = 4576, .n_44k1 = 7007, .n_48k = 6864, },
56
{ .tmds = 25200000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, },
57
{ .tmds = 27000000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, },
58
{ .tmds = 28320000, .n_32k = 4096, .n_44k1 = 5586, .n_48k = 6144, },
59
{ .tmds = 30240000, .n_32k = 4096, .n_44k1 = 5642, .n_48k = 6144, },
60
{ .tmds = 31500000, .n_32k = 4096, .n_44k1 = 5600, .n_48k = 6144, },
61
{ .tmds = 32000000, .n_32k = 4096, .n_44k1 = 5733, .n_48k = 6144, },
62
{ .tmds = 33750000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, },
63
{ .tmds = 36000000, .n_32k = 4096, .n_44k1 = 5684, .n_48k = 6144, },
64
{ .tmds = 40000000, .n_32k = 4096, .n_44k1 = 5733, .n_48k = 6144, },
65
{ .tmds = 49500000, .n_32k = 4096, .n_44k1 = 5488, .n_48k = 6144, },
66
{ .tmds = 50000000, .n_32k = 4096, .n_44k1 = 5292, .n_48k = 6144, },
67
{ .tmds = 54000000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, },
68
{ .tmds = 65000000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, },
69
{ .tmds = 68250000, .n_32k = 4096, .n_44k1 = 5376, .n_48k = 6144, },
70
{ .tmds = 71000000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, },
71
{ .tmds = 72000000, .n_32k = 4096, .n_44k1 = 5635, .n_48k = 6144, },
72
{ .tmds = 73250000, .n_32k = 11648, .n_44k1 = 14112, .n_48k = 6144, },
73
{ .tmds = 74250000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, },
74
{ .tmds = 75000000, .n_32k = 4096, .n_44k1 = 5880, .n_48k = 6144, },
75
{ .tmds = 78750000, .n_32k = 4096, .n_44k1 = 5600, .n_48k = 6144, },
76
{ .tmds = 78800000, .n_32k = 4096, .n_44k1 = 5292, .n_48k = 6144, },
77
{ .tmds = 79500000, .n_32k = 4096, .n_44k1 = 4704, .n_48k = 6144, },
78
{ .tmds = 83500000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, },
79
{ .tmds = 85500000, .n_32k = 4096, .n_44k1 = 5488, .n_48k = 6144, },
80
{ .tmds = 88750000, .n_32k = 4096, .n_44k1 = 14112, .n_48k = 6144, },
81
{ .tmds = 97750000, .n_32k = 4096, .n_44k1 = 14112, .n_48k = 6144, },
82
{ .tmds = 101000000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, },
83
{ .tmds = 106500000, .n_32k = 4096, .n_44k1 = 4704, .n_48k = 6144, },
84
{ .tmds = 108000000, .n_32k = 4096, .n_44k1 = 5684, .n_48k = 6144, },
85
{ .tmds = 115500000, .n_32k = 4096, .n_44k1 = 5712, .n_48k = 6144, },
86
{ .tmds = 119000000, .n_32k = 4096, .n_44k1 = 5544, .n_48k = 6144, },
87
{ .tmds = 135000000, .n_32k = 4096, .n_44k1 = 5488, .n_48k = 6144, },
88
{ .tmds = 146250000, .n_32k = 11648, .n_44k1 = 6272, .n_48k = 6144, },
89
{ .tmds = 148500000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, },
90
{ .tmds = 154000000, .n_32k = 4096, .n_44k1 = 5544, .n_48k = 6144, },
91
{ .tmds = 162000000, .n_32k = 4096, .n_44k1 = 5684, .n_48k = 6144, },
92
93
/* For 297 MHz+ HDMI spec have some other rule for setting N */
94
{ .tmds = 297000000, .n_32k = 3073, .n_44k1 = 4704, .n_48k = 5120, },
95
{ .tmds = 594000000, .n_32k = 3073, .n_44k1 = 9408, .n_48k = 10240,},
96
97
/* End of table */
98
{ .tmds = 0, .n_32k = 0, .n_44k1 = 0, .n_48k = 0, },
99
};
100
101
/*
102
* These are the CTS values as recommended in the Audio chapter of the HDMI
103
* specification.
104
*/
105
static const struct dw_hdmi_audio_tmds_cts {
106
unsigned long tmds;
107
unsigned int cts_32k;
108
unsigned int cts_44k1;
109
unsigned int cts_48k;
110
} common_tmds_cts_table[] = {
111
{ .tmds = 25175000, .cts_32k = 28125, .cts_44k1 = 31250, .cts_48k = 28125, },
112
{ .tmds = 25200000, .cts_32k = 25200, .cts_44k1 = 28000, .cts_48k = 25200, },
113
{ .tmds = 27000000, .cts_32k = 27000, .cts_44k1 = 30000, .cts_48k = 27000, },
114
{ .tmds = 54000000, .cts_32k = 54000, .cts_44k1 = 60000, .cts_48k = 54000, },
115
{ .tmds = 74250000, .cts_32k = 74250, .cts_44k1 = 82500, .cts_48k = 74250, },
116
{ .tmds = 148500000, .cts_32k = 148500, .cts_44k1 = 165000, .cts_48k = 148500, },
117
118
/* End of table */
119
{ .tmds = 0, .cts_32k = 0, .cts_44k1 = 0, .cts_48k = 0, },
120
};
121
122
struct dw_hdmi_qp_i2c {
123
struct i2c_adapter adap;
124
125
struct mutex lock; /* used to serialize data transfers */
126
struct completion cmp;
127
u8 stat;
128
129
u8 slave_reg;
130
bool is_regaddr;
131
bool is_segment;
132
};
133
134
struct dw_hdmi_qp {
135
struct drm_bridge bridge;
136
137
struct device *dev;
138
struct dw_hdmi_qp_i2c *i2c;
139
140
struct {
141
const struct dw_hdmi_qp_phy_ops *ops;
142
void *data;
143
} phy;
144
145
struct regmap *regm;
146
147
unsigned long tmds_char_rate;
148
};
149
150
static void dw_hdmi_qp_write(struct dw_hdmi_qp *hdmi, unsigned int val,
151
int offset)
152
{
153
regmap_write(hdmi->regm, offset, val);
154
}
155
156
static unsigned int dw_hdmi_qp_read(struct dw_hdmi_qp *hdmi, int offset)
157
{
158
unsigned int val = 0;
159
160
regmap_read(hdmi->regm, offset, &val);
161
162
return val;
163
}
164
165
static void dw_hdmi_qp_mod(struct dw_hdmi_qp *hdmi, unsigned int data,
166
unsigned int mask, unsigned int reg)
167
{
168
regmap_update_bits(hdmi->regm, reg, mask, data);
169
}
170
171
static struct dw_hdmi_qp *dw_hdmi_qp_from_bridge(struct drm_bridge *bridge)
172
{
173
return container_of(bridge, struct dw_hdmi_qp, bridge);
174
}
175
176
static void dw_hdmi_qp_set_cts_n(struct dw_hdmi_qp *hdmi, unsigned int cts,
177
unsigned int n)
178
{
179
/* Set N */
180
dw_hdmi_qp_mod(hdmi, n, AUDPKT_ACR_N_VALUE, AUDPKT_ACR_CONTROL0);
181
182
/* Set CTS */
183
if (cts)
184
dw_hdmi_qp_mod(hdmi, AUDPKT_ACR_CTS_OVR_EN, AUDPKT_ACR_CTS_OVR_EN_MSK,
185
AUDPKT_ACR_CONTROL1);
186
else
187
dw_hdmi_qp_mod(hdmi, 0, AUDPKT_ACR_CTS_OVR_EN_MSK,
188
AUDPKT_ACR_CONTROL1);
189
190
dw_hdmi_qp_mod(hdmi, AUDPKT_ACR_CTS_OVR_VAL(cts), AUDPKT_ACR_CTS_OVR_VAL_MSK,
191
AUDPKT_ACR_CONTROL1);
192
}
193
194
static int dw_hdmi_qp_match_tmds_n_table(struct dw_hdmi_qp *hdmi,
195
unsigned long pixel_clk,
196
unsigned long freq)
197
{
198
const struct dw_hdmi_audio_tmds_n *tmds_n = NULL;
199
int i;
200
201
for (i = 0; common_tmds_n_table[i].tmds != 0; i++) {
202
if (pixel_clk == common_tmds_n_table[i].tmds) {
203
tmds_n = &common_tmds_n_table[i];
204
break;
205
}
206
}
207
208
if (!tmds_n)
209
return -ENOENT;
210
211
switch (freq) {
212
case 32000:
213
return tmds_n->n_32k;
214
case 44100:
215
case 88200:
216
case 176400:
217
return (freq / 44100) * tmds_n->n_44k1;
218
case 48000:
219
case 96000:
220
case 192000:
221
return (freq / 48000) * tmds_n->n_48k;
222
default:
223
return -ENOENT;
224
}
225
}
226
227
static u32 dw_hdmi_qp_audio_math_diff(unsigned int freq, unsigned int n,
228
unsigned int pixel_clk)
229
{
230
u64 cts = mul_u32_u32(pixel_clk, n);
231
232
return do_div(cts, 128 * freq);
233
}
234
235
static unsigned int dw_hdmi_qp_compute_n(struct dw_hdmi_qp *hdmi,
236
unsigned long pixel_clk,
237
unsigned long freq)
238
{
239
unsigned int min_n = DIV_ROUND_UP((128 * freq), 1500);
240
unsigned int max_n = (128 * freq) / 300;
241
unsigned int ideal_n = (128 * freq) / 1000;
242
unsigned int best_n_distance = ideal_n;
243
unsigned int best_n = 0;
244
u64 best_diff = U64_MAX;
245
int n;
246
247
/* If the ideal N could satisfy the audio math, then just take it */
248
if (dw_hdmi_qp_audio_math_diff(freq, ideal_n, pixel_clk) == 0)
249
return ideal_n;
250
251
for (n = min_n; n <= max_n; n++) {
252
u64 diff = dw_hdmi_qp_audio_math_diff(freq, n, pixel_clk);
253
254
if (diff < best_diff ||
255
(diff == best_diff && abs(n - ideal_n) < best_n_distance)) {
256
best_n = n;
257
best_diff = diff;
258
best_n_distance = abs(best_n - ideal_n);
259
}
260
261
/*
262
* The best N already satisfy the audio math, and also be
263
* the closest value to ideal N, so just cut the loop.
264
*/
265
if (best_diff == 0 && (abs(n - ideal_n) > best_n_distance))
266
break;
267
}
268
269
return best_n;
270
}
271
272
static unsigned int dw_hdmi_qp_find_n(struct dw_hdmi_qp *hdmi, unsigned long pixel_clk,
273
unsigned long sample_rate)
274
{
275
int n = dw_hdmi_qp_match_tmds_n_table(hdmi, pixel_clk, sample_rate);
276
277
if (n > 0)
278
return n;
279
280
dev_warn(hdmi->dev, "Rate %lu missing; compute N dynamically\n",
281
pixel_clk);
282
283
return dw_hdmi_qp_compute_n(hdmi, pixel_clk, sample_rate);
284
}
285
286
static unsigned int dw_hdmi_qp_find_cts(struct dw_hdmi_qp *hdmi, unsigned long pixel_clk,
287
unsigned long sample_rate)
288
{
289
const struct dw_hdmi_audio_tmds_cts *tmds_cts = NULL;
290
int i;
291
292
for (i = 0; common_tmds_cts_table[i].tmds != 0; i++) {
293
if (pixel_clk == common_tmds_cts_table[i].tmds) {
294
tmds_cts = &common_tmds_cts_table[i];
295
break;
296
}
297
}
298
299
if (!tmds_cts)
300
return 0;
301
302
switch (sample_rate) {
303
case 32000:
304
return tmds_cts->cts_32k;
305
case 44100:
306
case 88200:
307
case 176400:
308
return tmds_cts->cts_44k1;
309
case 48000:
310
case 96000:
311
case 192000:
312
return tmds_cts->cts_48k;
313
default:
314
return -ENOENT;
315
}
316
}
317
318
static void dw_hdmi_qp_set_audio_interface(struct dw_hdmi_qp *hdmi,
319
struct hdmi_codec_daifmt *fmt,
320
struct hdmi_codec_params *hparms)
321
{
322
u32 conf0 = 0;
323
324
/* Reset the audio data path of the AVP */
325
dw_hdmi_qp_write(hdmi, AVP_DATAPATH_PACKET_AUDIO_SWINIT_P, GLOBAL_SWRESET_REQUEST);
326
327
/* Disable AUDS, ACR, AUDI */
328
dw_hdmi_qp_mod(hdmi, 0,
329
PKTSCHED_ACR_TX_EN | PKTSCHED_AUDS_TX_EN | PKTSCHED_AUDI_TX_EN,
330
PKTSCHED_PKT_EN);
331
332
/* Clear the audio FIFO */
333
dw_hdmi_qp_write(hdmi, AUDIO_FIFO_CLR_P, AUDIO_INTERFACE_CONTROL0);
334
335
/* Select I2S interface as the audio source */
336
dw_hdmi_qp_mod(hdmi, AUD_IF_I2S, AUD_IF_SEL_MSK, AUDIO_INTERFACE_CONFIG0);
337
338
/* Enable the active i2s lanes */
339
switch (hparms->channels) {
340
case 7 ... 8:
341
conf0 |= I2S_LINES_EN(3);
342
fallthrough;
343
case 5 ... 6:
344
conf0 |= I2S_LINES_EN(2);
345
fallthrough;
346
case 3 ... 4:
347
conf0 |= I2S_LINES_EN(1);
348
fallthrough;
349
default:
350
conf0 |= I2S_LINES_EN(0);
351
break;
352
}
353
354
dw_hdmi_qp_mod(hdmi, conf0, I2S_LINES_EN_MSK, AUDIO_INTERFACE_CONFIG0);
355
356
/*
357
* Enable bpcuv generated internally for L-PCM, or received
358
* from stream for NLPCM/HBR.
359
*/
360
switch (fmt->bit_fmt) {
361
case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
362
conf0 = (hparms->channels == 8) ? AUD_HBR : AUD_ASP;
363
conf0 |= I2S_BPCUV_RCV_EN;
364
break;
365
default:
366
conf0 = AUD_ASP | I2S_BPCUV_RCV_DIS;
367
break;
368
}
369
370
dw_hdmi_qp_mod(hdmi, conf0, I2S_BPCUV_RCV_MSK | AUD_FORMAT_MSK,
371
AUDIO_INTERFACE_CONFIG0);
372
373
/* Enable audio FIFO auto clear when overflow */
374
dw_hdmi_qp_mod(hdmi, AUD_FIFO_INIT_ON_OVF_EN, AUD_FIFO_INIT_ON_OVF_MSK,
375
AUDIO_INTERFACE_CONFIG0);
376
}
377
378
/*
379
* When transmitting IEC60958 linear PCM audio, these registers allow to
380
* configure the channel status information of all the channel status
381
* bits in the IEC60958 frame. For the moment this configuration is only
382
* used when the I2S audio interface, General Purpose Audio (GPA),
383
* or AHB audio DMA (AHBAUDDMA) interface is active
384
* (for S/PDIF interface this information comes from the stream).
385
*/
386
static void dw_hdmi_qp_set_channel_status(struct dw_hdmi_qp *hdmi,
387
u8 *channel_status, bool ref2stream)
388
{
389
/*
390
* AUDPKT_CHSTATUS_OVR0: { RSV, RSV, CS1, CS0 }
391
* AUDPKT_CHSTATUS_OVR1: { CS6, CS5, CS4, CS3 }
392
*
393
* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
394
* CS0: | Mode | d | c | b | a |
395
* CS1: | Category Code |
396
* CS2: | Channel Number | Source Number |
397
* CS3: | Clock Accuracy | Sample Freq |
398
* CS4: | Ori Sample Freq | Word Length |
399
* CS5: | | CGMS-A |
400
* CS6~CS23: Reserved
401
*
402
* a: use of channel status block
403
* b: linear PCM identification: 0 for lpcm, 1 for nlpcm
404
* c: copyright information
405
* d: additional format information
406
*/
407
408
if (ref2stream)
409
channel_status[0] |= IEC958_AES0_NONAUDIO;
410
411
if ((dw_hdmi_qp_read(hdmi, AUDIO_INTERFACE_CONFIG0) & GENMASK(25, 24)) == AUD_HBR) {
412
/* fixup cs for HBR */
413
channel_status[3] = (channel_status[3] & 0xf0) | IEC958_AES3_CON_FS_768000;
414
channel_status[4] = (channel_status[4] & 0x0f) | IEC958_AES4_CON_ORIGFS_NOTID;
415
}
416
417
dw_hdmi_qp_write(hdmi, channel_status[0] | (channel_status[1] << 8),
418
AUDPKT_CHSTATUS_OVR0);
419
420
regmap_bulk_write(hdmi->regm, AUDPKT_CHSTATUS_OVR1, &channel_status[3], 1);
421
422
if (ref2stream)
423
dw_hdmi_qp_mod(hdmi, 0,
424
AUDPKT_PBIT_FORCE_EN_MASK | AUDPKT_CHSTATUS_OVR_EN_MASK,
425
AUDPKT_CONTROL0);
426
else
427
dw_hdmi_qp_mod(hdmi, AUDPKT_PBIT_FORCE_EN | AUDPKT_CHSTATUS_OVR_EN,
428
AUDPKT_PBIT_FORCE_EN_MASK | AUDPKT_CHSTATUS_OVR_EN_MASK,
429
AUDPKT_CONTROL0);
430
}
431
432
static void dw_hdmi_qp_set_sample_rate(struct dw_hdmi_qp *hdmi, unsigned long long tmds_char_rate,
433
unsigned int sample_rate)
434
{
435
unsigned int n, cts;
436
437
n = dw_hdmi_qp_find_n(hdmi, tmds_char_rate, sample_rate);
438
cts = dw_hdmi_qp_find_cts(hdmi, tmds_char_rate, sample_rate);
439
440
dw_hdmi_qp_set_cts_n(hdmi, cts, n);
441
}
442
443
static int dw_hdmi_qp_audio_enable(struct drm_bridge *bridge,
444
struct drm_connector *connector)
445
{
446
struct dw_hdmi_qp *hdmi = dw_hdmi_qp_from_bridge(bridge);
447
448
if (hdmi->tmds_char_rate)
449
dw_hdmi_qp_mod(hdmi, 0, AVP_DATAPATH_PACKET_AUDIO_SWDISABLE, GLOBAL_SWDISABLE);
450
451
return 0;
452
}
453
454
static int dw_hdmi_qp_audio_prepare(struct drm_bridge *bridge,
455
struct drm_connector *connector,
456
struct hdmi_codec_daifmt *fmt,
457
struct hdmi_codec_params *hparms)
458
{
459
struct dw_hdmi_qp *hdmi = dw_hdmi_qp_from_bridge(bridge);
460
bool ref2stream = false;
461
462
if (!hdmi->tmds_char_rate)
463
return -ENODEV;
464
465
if (fmt->bit_clk_provider | fmt->frame_clk_provider) {
466
dev_err(hdmi->dev, "unsupported clock settings\n");
467
return -EINVAL;
468
}
469
470
if (fmt->bit_fmt == SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE)
471
ref2stream = true;
472
473
dw_hdmi_qp_set_audio_interface(hdmi, fmt, hparms);
474
dw_hdmi_qp_set_sample_rate(hdmi, hdmi->tmds_char_rate, hparms->sample_rate);
475
dw_hdmi_qp_set_channel_status(hdmi, hparms->iec.status, ref2stream);
476
drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector, &hparms->cea);
477
478
return 0;
479
}
480
481
static void dw_hdmi_qp_audio_disable_regs(struct dw_hdmi_qp *hdmi)
482
{
483
/*
484
* Keep ACR, AUDI, AUDS packet always on to make SINK device
485
* active for better compatibility and user experience.
486
*
487
* This also fix POP sound on some SINK devices which wakeup
488
* from suspend to active.
489
*/
490
dw_hdmi_qp_mod(hdmi, I2S_BPCUV_RCV_DIS, I2S_BPCUV_RCV_MSK,
491
AUDIO_INTERFACE_CONFIG0);
492
dw_hdmi_qp_mod(hdmi, AUDPKT_PBIT_FORCE_EN | AUDPKT_CHSTATUS_OVR_EN,
493
AUDPKT_PBIT_FORCE_EN_MASK | AUDPKT_CHSTATUS_OVR_EN_MASK,
494
AUDPKT_CONTROL0);
495
496
dw_hdmi_qp_mod(hdmi, AVP_DATAPATH_PACKET_AUDIO_SWDISABLE,
497
AVP_DATAPATH_PACKET_AUDIO_SWDISABLE, GLOBAL_SWDISABLE);
498
}
499
500
static void dw_hdmi_qp_audio_disable(struct drm_bridge *bridge,
501
struct drm_connector *connector)
502
{
503
struct dw_hdmi_qp *hdmi = dw_hdmi_qp_from_bridge(bridge);
504
505
drm_atomic_helper_connector_hdmi_clear_audio_infoframe(connector);
506
507
if (hdmi->tmds_char_rate)
508
dw_hdmi_qp_audio_disable_regs(hdmi);
509
}
510
511
static int dw_hdmi_qp_i2c_read(struct dw_hdmi_qp *hdmi,
512
unsigned char *buf, unsigned int length)
513
{
514
struct dw_hdmi_qp_i2c *i2c = hdmi->i2c;
515
int stat;
516
517
if (!i2c->is_regaddr) {
518
dev_dbg(hdmi->dev, "set read register address to 0\n");
519
i2c->slave_reg = 0x00;
520
i2c->is_regaddr = true;
521
}
522
523
while (length--) {
524
reinit_completion(&i2c->cmp);
525
526
dw_hdmi_qp_mod(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR,
527
I2CM_INTERFACE_CONTROL0);
528
529
if (i2c->is_segment)
530
dw_hdmi_qp_mod(hdmi, I2CM_EXT_READ, I2CM_WR_MASK,
531
I2CM_INTERFACE_CONTROL0);
532
else
533
dw_hdmi_qp_mod(hdmi, I2CM_FM_READ, I2CM_WR_MASK,
534
I2CM_INTERFACE_CONTROL0);
535
536
stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
537
if (!stat) {
538
dev_err(hdmi->dev, "i2c read timed out\n");
539
dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0);
540
return -EAGAIN;
541
}
542
543
/* Check for error condition on the bus */
544
if (i2c->stat & I2CM_NACK_RCVD_IRQ) {
545
dev_err(hdmi->dev, "i2c read error\n");
546
dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0);
547
return -EIO;
548
}
549
550
*buf++ = dw_hdmi_qp_read(hdmi, I2CM_INTERFACE_RDDATA_0_3) & 0xff;
551
dw_hdmi_qp_mod(hdmi, 0, I2CM_WR_MASK, I2CM_INTERFACE_CONTROL0);
552
}
553
554
i2c->is_segment = false;
555
556
return 0;
557
}
558
559
static int dw_hdmi_qp_i2c_write(struct dw_hdmi_qp *hdmi,
560
unsigned char *buf, unsigned int length)
561
{
562
struct dw_hdmi_qp_i2c *i2c = hdmi->i2c;
563
int stat;
564
565
if (!i2c->is_regaddr) {
566
/* Use the first write byte as register address */
567
i2c->slave_reg = buf[0];
568
length--;
569
buf++;
570
i2c->is_regaddr = true;
571
}
572
573
while (length--) {
574
reinit_completion(&i2c->cmp);
575
576
dw_hdmi_qp_write(hdmi, *buf++, I2CM_INTERFACE_WRDATA_0_3);
577
dw_hdmi_qp_mod(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR,
578
I2CM_INTERFACE_CONTROL0);
579
dw_hdmi_qp_mod(hdmi, I2CM_FM_WRITE, I2CM_WR_MASK,
580
I2CM_INTERFACE_CONTROL0);
581
582
stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
583
if (!stat) {
584
dev_err(hdmi->dev, "i2c write time out!\n");
585
dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0);
586
return -EAGAIN;
587
}
588
589
/* Check for error condition on the bus */
590
if (i2c->stat & I2CM_NACK_RCVD_IRQ) {
591
dev_err(hdmi->dev, "i2c write nack!\n");
592
dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0);
593
return -EIO;
594
}
595
596
dw_hdmi_qp_mod(hdmi, 0, I2CM_WR_MASK, I2CM_INTERFACE_CONTROL0);
597
}
598
599
return 0;
600
}
601
602
static int dw_hdmi_qp_i2c_xfer(struct i2c_adapter *adap,
603
struct i2c_msg *msgs, int num)
604
{
605
struct dw_hdmi_qp *hdmi = i2c_get_adapdata(adap);
606
struct dw_hdmi_qp_i2c *i2c = hdmi->i2c;
607
u8 addr = msgs[0].addr;
608
int i, ret = 0;
609
610
if (addr == DDC_CI_ADDR)
611
/*
612
* The internal I2C controller does not support the multi-byte
613
* read and write operations needed for DDC/CI.
614
* FIXME: Blacklist the DDC/CI address until we filter out
615
* unsupported I2C operations.
616
*/
617
return -EOPNOTSUPP;
618
619
for (i = 0; i < num; i++) {
620
if (msgs[i].len == 0) {
621
dev_err(hdmi->dev,
622
"unsupported transfer %d/%d, no data\n",
623
i + 1, num);
624
return -EOPNOTSUPP;
625
}
626
}
627
628
guard(mutex)(&i2c->lock);
629
630
/* Unmute DONE and ERROR interrupts */
631
dw_hdmi_qp_mod(hdmi, I2CM_NACK_RCVD_MASK_N | I2CM_OP_DONE_MASK_N,
632
I2CM_NACK_RCVD_MASK_N | I2CM_OP_DONE_MASK_N,
633
MAINUNIT_1_INT_MASK_N);
634
635
/* Set slave device address taken from the first I2C message */
636
if (addr == DDC_SEGMENT_ADDR && msgs[0].len == 1)
637
addr = DDC_ADDR;
638
639
dw_hdmi_qp_mod(hdmi, addr << 5, I2CM_SLVADDR, I2CM_INTERFACE_CONTROL0);
640
641
/* Set slave device register address on transfer */
642
i2c->is_regaddr = false;
643
644
/* Set segment pointer for I2C extended read mode operation */
645
i2c->is_segment = false;
646
647
for (i = 0; i < num; i++) {
648
if (msgs[i].addr == DDC_SEGMENT_ADDR && msgs[i].len == 1) {
649
i2c->is_segment = true;
650
dw_hdmi_qp_mod(hdmi, DDC_SEGMENT_ADDR, I2CM_SEG_ADDR,
651
I2CM_INTERFACE_CONTROL1);
652
dw_hdmi_qp_mod(hdmi, *msgs[i].buf << 7, I2CM_SEG_PTR,
653
I2CM_INTERFACE_CONTROL1);
654
} else {
655
if (msgs[i].flags & I2C_M_RD)
656
ret = dw_hdmi_qp_i2c_read(hdmi, msgs[i].buf,
657
msgs[i].len);
658
else
659
ret = dw_hdmi_qp_i2c_write(hdmi, msgs[i].buf,
660
msgs[i].len);
661
}
662
if (ret < 0)
663
break;
664
}
665
666
if (!ret)
667
ret = num;
668
669
/* Mute DONE and ERROR interrupts */
670
dw_hdmi_qp_mod(hdmi, 0, I2CM_OP_DONE_MASK_N | I2CM_NACK_RCVD_MASK_N,
671
MAINUNIT_1_INT_MASK_N);
672
673
return ret;
674
}
675
676
static u32 dw_hdmi_qp_i2c_func(struct i2c_adapter *adapter)
677
{
678
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
679
}
680
681
static const struct i2c_algorithm dw_hdmi_qp_algorithm = {
682
.master_xfer = dw_hdmi_qp_i2c_xfer,
683
.functionality = dw_hdmi_qp_i2c_func,
684
};
685
686
static struct i2c_adapter *dw_hdmi_qp_i2c_adapter(struct dw_hdmi_qp *hdmi)
687
{
688
struct dw_hdmi_qp_i2c *i2c;
689
struct i2c_adapter *adap;
690
int ret;
691
692
i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
693
if (!i2c)
694
return ERR_PTR(-ENOMEM);
695
696
mutex_init(&i2c->lock);
697
init_completion(&i2c->cmp);
698
699
adap = &i2c->adap;
700
adap->owner = THIS_MODULE;
701
adap->dev.parent = hdmi->dev;
702
adap->algo = &dw_hdmi_qp_algorithm;
703
strscpy(adap->name, "DesignWare HDMI QP", sizeof(adap->name));
704
705
i2c_set_adapdata(adap, hdmi);
706
707
ret = devm_i2c_add_adapter(hdmi->dev, adap);
708
if (ret) {
709
dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
710
devm_kfree(hdmi->dev, i2c);
711
return ERR_PTR(ret);
712
}
713
714
hdmi->i2c = i2c;
715
dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
716
717
return adap;
718
}
719
720
static int dw_hdmi_qp_config_avi_infoframe(struct dw_hdmi_qp *hdmi,
721
const u8 *buffer, size_t len)
722
{
723
u32 val, i, j;
724
725
if (len != HDMI_INFOFRAME_SIZE(AVI)) {
726
dev_err(hdmi->dev, "failed to configure avi infoframe\n");
727
return -EINVAL;
728
}
729
730
/*
731
* DW HDMI QP IP uses a different byte format from standard AVI info
732
* frames, though generally the bits are in the correct bytes.
733
*/
734
val = buffer[1] << 8 | buffer[2] << 16;
735
dw_hdmi_qp_write(hdmi, val, PKT_AVI_CONTENTS0);
736
737
for (i = 0; i < 4; i++) {
738
for (j = 0; j < 4; j++) {
739
if (i * 4 + j >= 14)
740
break;
741
if (!j)
742
val = buffer[i * 4 + j + 3];
743
val |= buffer[i * 4 + j + 3] << (8 * j);
744
}
745
746
dw_hdmi_qp_write(hdmi, val, PKT_AVI_CONTENTS1 + i * 4);
747
}
748
749
dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_AVI_FIELDRATE, PKTSCHED_PKT_CONFIG1);
750
751
dw_hdmi_qp_mod(hdmi, PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN,
752
PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN, PKTSCHED_PKT_EN);
753
754
return 0;
755
}
756
757
static int dw_hdmi_qp_config_drm_infoframe(struct dw_hdmi_qp *hdmi,
758
const u8 *buffer, size_t len)
759
{
760
u32 val, i;
761
762
if (len != HDMI_INFOFRAME_SIZE(DRM)) {
763
dev_err(hdmi->dev, "failed to configure drm infoframe\n");
764
return -EINVAL;
765
}
766
767
dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_TX_EN, PKTSCHED_PKT_EN);
768
769
val = buffer[1] << 8 | buffer[2] << 16;
770
dw_hdmi_qp_write(hdmi, val, PKT_DRMI_CONTENTS0);
771
772
for (i = 0; i <= buffer[2]; i++) {
773
if (i % 4 == 0)
774
val = buffer[3 + i];
775
val |= buffer[3 + i] << ((i % 4) * 8);
776
777
if ((i % 4 == 3) || i == buffer[2])
778
dw_hdmi_qp_write(hdmi, val,
779
PKT_DRMI_CONTENTS1 + ((i / 4) * 4));
780
}
781
782
dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_FIELDRATE, PKTSCHED_PKT_CONFIG1);
783
dw_hdmi_qp_mod(hdmi, PKTSCHED_DRMI_TX_EN, PKTSCHED_DRMI_TX_EN,
784
PKTSCHED_PKT_EN);
785
786
return 0;
787
}
788
789
/*
790
* Static values documented in the TRM
791
* Different values are only used for debug purposes
792
*/
793
#define DW_HDMI_QP_AUDIO_INFOFRAME_HB1 0x1
794
#define DW_HDMI_QP_AUDIO_INFOFRAME_HB2 0xa
795
796
static int dw_hdmi_qp_config_audio_infoframe(struct dw_hdmi_qp *hdmi,
797
const u8 *buffer, size_t len)
798
{
799
/*
800
* AUDI_CONTENTS0: { RSV, HB2, HB1, RSV }
801
* AUDI_CONTENTS1: { PB3, PB2, PB1, PB0 }
802
* AUDI_CONTENTS2: { PB7, PB6, PB5, PB4 }
803
*
804
* PB0: CheckSum
805
* PB1: | CT3 | CT2 | CT1 | CT0 | F13 | CC2 | CC1 | CC0 |
806
* PB2: | F27 | F26 | F25 | SF2 | SF1 | SF0 | SS1 | SS0 |
807
* PB3: | F37 | F36 | F35 | F34 | F33 | F32 | F31 | F30 |
808
* PB4: | CA7 | CA6 | CA5 | CA4 | CA3 | CA2 | CA1 | CA0 |
809
* PB5: | DM_INH | LSV3 | LSV2 | LSV1 | LSV0 | F52 | F51 | F50 |
810
* PB6~PB10: Reserved
811
*
812
* AUDI_CONTENTS0 default value defined by HDMI specification,
813
* and shall only be changed for debug purposes.
814
*/
815
u32 header_bytes = (DW_HDMI_QP_AUDIO_INFOFRAME_HB1 << 8) |
816
(DW_HDMI_QP_AUDIO_INFOFRAME_HB2 << 16);
817
818
regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS0, &header_bytes, 1);
819
regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS1, &buffer[3], 1);
820
regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS2, &buffer[4], 1);
821
822
/* Enable ACR, AUDI, AMD */
823
dw_hdmi_qp_mod(hdmi,
824
PKTSCHED_ACR_TX_EN | PKTSCHED_AUDI_TX_EN | PKTSCHED_AMD_TX_EN,
825
PKTSCHED_ACR_TX_EN | PKTSCHED_AUDI_TX_EN | PKTSCHED_AMD_TX_EN,
826
PKTSCHED_PKT_EN);
827
828
/* Enable AUDS */
829
dw_hdmi_qp_mod(hdmi, PKTSCHED_AUDS_TX_EN, PKTSCHED_AUDS_TX_EN, PKTSCHED_PKT_EN);
830
831
return 0;
832
}
833
834
static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge,
835
struct drm_atomic_state *state)
836
{
837
struct dw_hdmi_qp *hdmi = bridge->driver_private;
838
struct drm_connector_state *conn_state;
839
struct drm_connector *connector;
840
unsigned int op_mode;
841
842
connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
843
if (WARN_ON(!connector))
844
return;
845
846
conn_state = drm_atomic_get_new_connector_state(state, connector);
847
if (WARN_ON(!conn_state))
848
return;
849
850
if (connector->display_info.is_hdmi) {
851
dev_dbg(hdmi->dev, "%s mode=HDMI rate=%llu\n",
852
__func__, conn_state->hdmi.tmds_char_rate);
853
op_mode = 0;
854
hdmi->tmds_char_rate = conn_state->hdmi.tmds_char_rate;
855
} else {
856
dev_dbg(hdmi->dev, "%s mode=DVI\n", __func__);
857
op_mode = OPMODE_DVI;
858
}
859
860
hdmi->phy.ops->init(hdmi, hdmi->phy.data);
861
862
dw_hdmi_qp_mod(hdmi, HDCP2_BYPASS, HDCP2_BYPASS, HDCP2LOGIC_CONFIG0);
863
dw_hdmi_qp_mod(hdmi, op_mode, OPMODE_DVI, LINK_CONFIG0);
864
865
drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
866
}
867
868
static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge,
869
struct drm_atomic_state *state)
870
{
871
struct dw_hdmi_qp *hdmi = bridge->driver_private;
872
873
hdmi->tmds_char_rate = 0;
874
875
hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
876
}
877
878
static enum drm_connector_status
879
dw_hdmi_qp_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector)
880
{
881
struct dw_hdmi_qp *hdmi = bridge->driver_private;
882
883
return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
884
}
885
886
static const struct drm_edid *
887
dw_hdmi_qp_bridge_edid_read(struct drm_bridge *bridge,
888
struct drm_connector *connector)
889
{
890
struct dw_hdmi_qp *hdmi = bridge->driver_private;
891
const struct drm_edid *drm_edid;
892
893
drm_edid = drm_edid_read_ddc(connector, bridge->ddc);
894
if (!drm_edid)
895
dev_dbg(hdmi->dev, "failed to get edid\n");
896
897
return drm_edid;
898
}
899
900
static enum drm_mode_status
901
dw_hdmi_qp_bridge_tmds_char_rate_valid(const struct drm_bridge *bridge,
902
const struct drm_display_mode *mode,
903
unsigned long long rate)
904
{
905
struct dw_hdmi_qp *hdmi = bridge->driver_private;
906
907
if (rate > HDMI14_MAX_TMDSCLK) {
908
dev_dbg(hdmi->dev, "Unsupported TMDS char rate: %lld\n", rate);
909
return MODE_CLOCK_HIGH;
910
}
911
912
return MODE_OK;
913
}
914
915
static int dw_hdmi_qp_bridge_clear_infoframe(struct drm_bridge *bridge,
916
enum hdmi_infoframe_type type)
917
{
918
struct dw_hdmi_qp *hdmi = bridge->driver_private;
919
920
switch (type) {
921
case HDMI_INFOFRAME_TYPE_AVI:
922
dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN,
923
PKTSCHED_PKT_EN);
924
break;
925
926
case HDMI_INFOFRAME_TYPE_DRM:
927
dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_TX_EN, PKTSCHED_PKT_EN);
928
break;
929
930
case HDMI_INFOFRAME_TYPE_AUDIO:
931
dw_hdmi_qp_mod(hdmi, 0,
932
PKTSCHED_ACR_TX_EN |
933
PKTSCHED_AUDS_TX_EN |
934
PKTSCHED_AUDI_TX_EN,
935
PKTSCHED_PKT_EN);
936
break;
937
default:
938
dev_dbg(hdmi->dev, "Unsupported infoframe type %x\n", type);
939
}
940
941
return 0;
942
}
943
944
static int dw_hdmi_qp_bridge_write_infoframe(struct drm_bridge *bridge,
945
enum hdmi_infoframe_type type,
946
const u8 *buffer, size_t len)
947
{
948
struct dw_hdmi_qp *hdmi = bridge->driver_private;
949
950
dw_hdmi_qp_bridge_clear_infoframe(bridge, type);
951
952
switch (type) {
953
case HDMI_INFOFRAME_TYPE_AVI:
954
return dw_hdmi_qp_config_avi_infoframe(hdmi, buffer, len);
955
956
case HDMI_INFOFRAME_TYPE_DRM:
957
return dw_hdmi_qp_config_drm_infoframe(hdmi, buffer, len);
958
959
case HDMI_INFOFRAME_TYPE_AUDIO:
960
return dw_hdmi_qp_config_audio_infoframe(hdmi, buffer, len);
961
962
default:
963
dev_dbg(hdmi->dev, "Unsupported infoframe type %x\n", type);
964
return 0;
965
}
966
}
967
968
static const struct drm_bridge_funcs dw_hdmi_qp_bridge_funcs = {
969
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
970
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
971
.atomic_reset = drm_atomic_helper_bridge_reset,
972
.atomic_enable = dw_hdmi_qp_bridge_atomic_enable,
973
.atomic_disable = dw_hdmi_qp_bridge_atomic_disable,
974
.detect = dw_hdmi_qp_bridge_detect,
975
.edid_read = dw_hdmi_qp_bridge_edid_read,
976
.hdmi_tmds_char_rate_valid = dw_hdmi_qp_bridge_tmds_char_rate_valid,
977
.hdmi_clear_infoframe = dw_hdmi_qp_bridge_clear_infoframe,
978
.hdmi_write_infoframe = dw_hdmi_qp_bridge_write_infoframe,
979
.hdmi_audio_startup = dw_hdmi_qp_audio_enable,
980
.hdmi_audio_shutdown = dw_hdmi_qp_audio_disable,
981
.hdmi_audio_prepare = dw_hdmi_qp_audio_prepare,
982
};
983
984
static irqreturn_t dw_hdmi_qp_main_hardirq(int irq, void *dev_id)
985
{
986
struct dw_hdmi_qp *hdmi = dev_id;
987
struct dw_hdmi_qp_i2c *i2c = hdmi->i2c;
988
u32 stat;
989
990
stat = dw_hdmi_qp_read(hdmi, MAINUNIT_1_INT_STATUS);
991
992
i2c->stat = stat & (I2CM_OP_DONE_IRQ | I2CM_READ_REQUEST_IRQ |
993
I2CM_NACK_RCVD_IRQ);
994
995
if (i2c->stat) {
996
dw_hdmi_qp_write(hdmi, i2c->stat, MAINUNIT_1_INT_CLEAR);
997
complete(&i2c->cmp);
998
}
999
1000
if (stat)
1001
return IRQ_HANDLED;
1002
1003
return IRQ_NONE;
1004
}
1005
1006
static const struct regmap_config dw_hdmi_qp_regmap_config = {
1007
.reg_bits = 32,
1008
.val_bits = 32,
1009
.reg_stride = 4,
1010
.max_register = EARCRX_1_INT_FORCE,
1011
};
1012
1013
static void dw_hdmi_qp_init_hw(struct dw_hdmi_qp *hdmi)
1014
{
1015
dw_hdmi_qp_write(hdmi, 0, MAINUNIT_0_INT_MASK_N);
1016
dw_hdmi_qp_write(hdmi, 0, MAINUNIT_1_INT_MASK_N);
1017
dw_hdmi_qp_write(hdmi, 428571429, TIMER_BASE_CONFIG0);
1018
1019
/* Software reset */
1020
dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0);
1021
1022
dw_hdmi_qp_write(hdmi, 0x085c085c, I2CM_FM_SCL_CONFIG0);
1023
1024
dw_hdmi_qp_mod(hdmi, 0, I2CM_FM_EN, I2CM_INTERFACE_CONTROL0);
1025
1026
/* Clear DONE and ERROR interrupts */
1027
dw_hdmi_qp_write(hdmi, I2CM_OP_DONE_CLEAR | I2CM_NACK_RCVD_CLEAR,
1028
MAINUNIT_1_INT_CLEAR);
1029
1030
if (hdmi->phy.ops->setup_hpd)
1031
hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data);
1032
}
1033
1034
struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,
1035
struct drm_encoder *encoder,
1036
const struct dw_hdmi_qp_plat_data *plat_data)
1037
{
1038
struct device *dev = &pdev->dev;
1039
struct dw_hdmi_qp *hdmi;
1040
void __iomem *regs;
1041
int ret;
1042
1043
if (!plat_data->phy_ops || !plat_data->phy_ops->init ||
1044
!plat_data->phy_ops->disable || !plat_data->phy_ops->read_hpd) {
1045
dev_err(dev, "Missing platform PHY ops\n");
1046
return ERR_PTR(-ENODEV);
1047
}
1048
1049
hdmi = devm_drm_bridge_alloc(dev, struct dw_hdmi_qp, bridge,
1050
&dw_hdmi_qp_bridge_funcs);
1051
if (IS_ERR(hdmi))
1052
return ERR_CAST(hdmi);
1053
1054
hdmi->dev = dev;
1055
1056
regs = devm_platform_ioremap_resource(pdev, 0);
1057
if (IS_ERR(regs))
1058
return ERR_CAST(regs);
1059
1060
hdmi->regm = devm_regmap_init_mmio(dev, regs, &dw_hdmi_qp_regmap_config);
1061
if (IS_ERR(hdmi->regm)) {
1062
dev_err(dev, "Failed to configure regmap\n");
1063
return ERR_CAST(hdmi->regm);
1064
}
1065
1066
hdmi->phy.ops = plat_data->phy_ops;
1067
hdmi->phy.data = plat_data->phy_data;
1068
1069
dw_hdmi_qp_init_hw(hdmi);
1070
1071
ret = devm_request_threaded_irq(dev, plat_data->main_irq,
1072
dw_hdmi_qp_main_hardirq, NULL,
1073
IRQF_SHARED, dev_name(dev), hdmi);
1074
if (ret)
1075
return ERR_PTR(ret);
1076
1077
hdmi->bridge.driver_private = hdmi;
1078
hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT |
1079
DRM_BRIDGE_OP_EDID |
1080
DRM_BRIDGE_OP_HDMI |
1081
DRM_BRIDGE_OP_HDMI_AUDIO |
1082
DRM_BRIDGE_OP_HPD;
1083
hdmi->bridge.of_node = pdev->dev.of_node;
1084
hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
1085
hdmi->bridge.vendor = "Synopsys";
1086
hdmi->bridge.product = "DW HDMI QP TX";
1087
1088
hdmi->bridge.ddc = dw_hdmi_qp_i2c_adapter(hdmi);
1089
if (IS_ERR(hdmi->bridge.ddc))
1090
return ERR_CAST(hdmi->bridge.ddc);
1091
1092
hdmi->bridge.hdmi_audio_max_i2s_playback_channels = 8;
1093
hdmi->bridge.hdmi_audio_dev = dev;
1094
hdmi->bridge.hdmi_audio_dai_port = 1;
1095
1096
ret = devm_drm_bridge_add(dev, &hdmi->bridge);
1097
if (ret)
1098
return ERR_PTR(ret);
1099
1100
ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL,
1101
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
1102
if (ret)
1103
return ERR_PTR(ret);
1104
1105
return hdmi;
1106
}
1107
EXPORT_SYMBOL_GPL(dw_hdmi_qp_bind);
1108
1109
void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi)
1110
{
1111
dw_hdmi_qp_init_hw(hdmi);
1112
}
1113
EXPORT_SYMBOL_GPL(dw_hdmi_qp_resume);
1114
1115
MODULE_AUTHOR("Algea Cao <[email protected]>");
1116
MODULE_AUTHOR("Cristian Ciocaltea <[email protected]>");
1117
MODULE_DESCRIPTION("DW HDMI QP transmitter library");
1118
MODULE_LICENSE("GPL");
1119
1120