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/i2c.h>
12 #include <linux/irq.h>
13 #include <linux/module.h>
14 #include <linux/mutex.h>
15 #include <linux/of.h>
16 #include <linux/workqueue.h>
17
18 #include <drm/bridge/dw_hdmi_qp.h>
19 #include <drm/display/drm_hdmi_helper.h>
20 #include <drm/display/drm_hdmi_state_helper.h>
21 #include <drm/drm_atomic.h>
22 #include <drm/drm_atomic_helper.h>
23 #include <drm/drm_bridge.h>
24 #include <drm/drm_connector.h>
25 #include <drm/drm_edid.h>
26 #include <drm/drm_modes.h>
27
28 #include <sound/hdmi-codec.h>
29
30 #include "dw-hdmi-qp.h"
31
32 #define DDC_CI_ADDR 0x37
33 #define DDC_SEGMENT_ADDR 0x30
34
35 #define HDMI14_MAX_TMDSCLK 340000000
36
37 #define SCRAMB_POLL_DELAY_MS 3000
38
39 struct dw_hdmi_qp_i2c {
40 struct i2c_adapter adap;
41
42 struct mutex lock; /* used to serialize data transfers */
43 struct completion cmp;
44 u8 stat;
45
46 u8 slave_reg;
47 bool is_regaddr;
48 bool is_segment;
49 };
50
51 struct dw_hdmi_qp {
52 struct drm_bridge bridge;
53
54 struct device *dev;
55 struct dw_hdmi_qp_i2c *i2c;
56
57 struct {
58 const struct dw_hdmi_qp_phy_ops *ops;
59 void *data;
60 } phy;
61
62 struct regmap *regm;
63 };
64
dw_hdmi_qp_write(struct dw_hdmi_qp * hdmi,unsigned int val,int offset)65 static void dw_hdmi_qp_write(struct dw_hdmi_qp *hdmi, unsigned int val,
66 int offset)
67 {
68 regmap_write(hdmi->regm, offset, val);
69 }
70
dw_hdmi_qp_read(struct dw_hdmi_qp * hdmi,int offset)71 static unsigned int dw_hdmi_qp_read(struct dw_hdmi_qp *hdmi, int offset)
72 {
73 unsigned int val = 0;
74
75 regmap_read(hdmi->regm, offset, &val);
76
77 return val;
78 }
79
dw_hdmi_qp_mod(struct dw_hdmi_qp * hdmi,unsigned int data,unsigned int mask,unsigned int reg)80 static void dw_hdmi_qp_mod(struct dw_hdmi_qp *hdmi, unsigned int data,
81 unsigned int mask, unsigned int reg)
82 {
83 regmap_update_bits(hdmi->regm, reg, mask, data);
84 }
85
dw_hdmi_qp_i2c_read(struct dw_hdmi_qp * hdmi,unsigned char * buf,unsigned int length)86 static int dw_hdmi_qp_i2c_read(struct dw_hdmi_qp *hdmi,
87 unsigned char *buf, unsigned int length)
88 {
89 struct dw_hdmi_qp_i2c *i2c = hdmi->i2c;
90 int stat;
91
92 if (!i2c->is_regaddr) {
93 dev_dbg(hdmi->dev, "set read register address to 0\n");
94 i2c->slave_reg = 0x00;
95 i2c->is_regaddr = true;
96 }
97
98 while (length--) {
99 reinit_completion(&i2c->cmp);
100
101 dw_hdmi_qp_mod(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR,
102 I2CM_INTERFACE_CONTROL0);
103
104 if (i2c->is_segment)
105 dw_hdmi_qp_mod(hdmi, I2CM_EXT_READ, I2CM_WR_MASK,
106 I2CM_INTERFACE_CONTROL0);
107 else
108 dw_hdmi_qp_mod(hdmi, I2CM_FM_READ, I2CM_WR_MASK,
109 I2CM_INTERFACE_CONTROL0);
110
111 stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
112 if (!stat) {
113 dev_err(hdmi->dev, "i2c read timed out\n");
114 dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0);
115 return -EAGAIN;
116 }
117
118 /* Check for error condition on the bus */
119 if (i2c->stat & I2CM_NACK_RCVD_IRQ) {
120 dev_err(hdmi->dev, "i2c read error\n");
121 dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0);
122 return -EIO;
123 }
124
125 *buf++ = dw_hdmi_qp_read(hdmi, I2CM_INTERFACE_RDDATA_0_3) & 0xff;
126 dw_hdmi_qp_mod(hdmi, 0, I2CM_WR_MASK, I2CM_INTERFACE_CONTROL0);
127 }
128
129 i2c->is_segment = false;
130
131 return 0;
132 }
133
dw_hdmi_qp_i2c_write(struct dw_hdmi_qp * hdmi,unsigned char * buf,unsigned int length)134 static int dw_hdmi_qp_i2c_write(struct dw_hdmi_qp *hdmi,
135 unsigned char *buf, unsigned int length)
136 {
137 struct dw_hdmi_qp_i2c *i2c = hdmi->i2c;
138 int stat;
139
140 if (!i2c->is_regaddr) {
141 /* Use the first write byte as register address */
142 i2c->slave_reg = buf[0];
143 length--;
144 buf++;
145 i2c->is_regaddr = true;
146 }
147
148 while (length--) {
149 reinit_completion(&i2c->cmp);
150
151 dw_hdmi_qp_write(hdmi, *buf++, I2CM_INTERFACE_WRDATA_0_3);
152 dw_hdmi_qp_mod(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR,
153 I2CM_INTERFACE_CONTROL0);
154 dw_hdmi_qp_mod(hdmi, I2CM_FM_WRITE, I2CM_WR_MASK,
155 I2CM_INTERFACE_CONTROL0);
156
157 stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
158 if (!stat) {
159 dev_err(hdmi->dev, "i2c write time out!\n");
160 dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0);
161 return -EAGAIN;
162 }
163
164 /* Check for error condition on the bus */
165 if (i2c->stat & I2CM_NACK_RCVD_IRQ) {
166 dev_err(hdmi->dev, "i2c write nack!\n");
167 dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0);
168 return -EIO;
169 }
170
171 dw_hdmi_qp_mod(hdmi, 0, I2CM_WR_MASK, I2CM_INTERFACE_CONTROL0);
172 }
173
174 return 0;
175 }
176
dw_hdmi_qp_i2c_xfer(struct i2c_adapter * adap,struct i2c_msg * msgs,int num)177 static int dw_hdmi_qp_i2c_xfer(struct i2c_adapter *adap,
178 struct i2c_msg *msgs, int num)
179 {
180 struct dw_hdmi_qp *hdmi = i2c_get_adapdata(adap);
181 struct dw_hdmi_qp_i2c *i2c = hdmi->i2c;
182 u8 addr = msgs[0].addr;
183 int i, ret = 0;
184
185 if (addr == DDC_CI_ADDR)
186 /*
187 * The internal I2C controller does not support the multi-byte
188 * read and write operations needed for DDC/CI.
189 * FIXME: Blacklist the DDC/CI address until we filter out
190 * unsupported I2C operations.
191 */
192 return -EOPNOTSUPP;
193
194 for (i = 0; i < num; i++) {
195 if (msgs[i].len == 0) {
196 dev_err(hdmi->dev,
197 "unsupported transfer %d/%d, no data\n",
198 i + 1, num);
199 return -EOPNOTSUPP;
200 }
201 }
202
203 guard(mutex)(&i2c->lock);
204
205 /* Unmute DONE and ERROR interrupts */
206 dw_hdmi_qp_mod(hdmi, I2CM_NACK_RCVD_MASK_N | I2CM_OP_DONE_MASK_N,
207 I2CM_NACK_RCVD_MASK_N | I2CM_OP_DONE_MASK_N,
208 MAINUNIT_1_INT_MASK_N);
209
210 /* Set slave device address taken from the first I2C message */
211 if (addr == DDC_SEGMENT_ADDR && msgs[0].len == 1)
212 addr = DDC_ADDR;
213
214 dw_hdmi_qp_mod(hdmi, addr << 5, I2CM_SLVADDR, I2CM_INTERFACE_CONTROL0);
215
216 /* Set slave device register address on transfer */
217 i2c->is_regaddr = false;
218
219 /* Set segment pointer for I2C extended read mode operation */
220 i2c->is_segment = false;
221
222 for (i = 0; i < num; i++) {
223 if (msgs[i].addr == DDC_SEGMENT_ADDR && msgs[i].len == 1) {
224 i2c->is_segment = true;
225 dw_hdmi_qp_mod(hdmi, DDC_SEGMENT_ADDR, I2CM_SEG_ADDR,
226 I2CM_INTERFACE_CONTROL1);
227 dw_hdmi_qp_mod(hdmi, *msgs[i].buf << 7, I2CM_SEG_PTR,
228 I2CM_INTERFACE_CONTROL1);
229 } else {
230 if (msgs[i].flags & I2C_M_RD)
231 ret = dw_hdmi_qp_i2c_read(hdmi, msgs[i].buf,
232 msgs[i].len);
233 else
234 ret = dw_hdmi_qp_i2c_write(hdmi, msgs[i].buf,
235 msgs[i].len);
236 }
237 if (ret < 0)
238 break;
239 }
240
241 if (!ret)
242 ret = num;
243
244 /* Mute DONE and ERROR interrupts */
245 dw_hdmi_qp_mod(hdmi, 0, I2CM_OP_DONE_MASK_N | I2CM_NACK_RCVD_MASK_N,
246 MAINUNIT_1_INT_MASK_N);
247
248 return ret;
249 }
250
dw_hdmi_qp_i2c_func(struct i2c_adapter * adapter)251 static u32 dw_hdmi_qp_i2c_func(struct i2c_adapter *adapter)
252 {
253 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
254 }
255
256 static const struct i2c_algorithm dw_hdmi_qp_algorithm = {
257 .master_xfer = dw_hdmi_qp_i2c_xfer,
258 .functionality = dw_hdmi_qp_i2c_func,
259 };
260
dw_hdmi_qp_i2c_adapter(struct dw_hdmi_qp * hdmi)261 static struct i2c_adapter *dw_hdmi_qp_i2c_adapter(struct dw_hdmi_qp *hdmi)
262 {
263 struct dw_hdmi_qp_i2c *i2c;
264 struct i2c_adapter *adap;
265 int ret;
266
267 i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
268 if (!i2c)
269 return ERR_PTR(-ENOMEM);
270
271 mutex_init(&i2c->lock);
272 init_completion(&i2c->cmp);
273
274 adap = &i2c->adap;
275 adap->owner = THIS_MODULE;
276 adap->dev.parent = hdmi->dev;
277 adap->algo = &dw_hdmi_qp_algorithm;
278 strscpy(adap->name, "DesignWare HDMI QP", sizeof(adap->name));
279
280 i2c_set_adapdata(adap, hdmi);
281
282 ret = devm_i2c_add_adapter(hdmi->dev, adap);
283 if (ret) {
284 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
285 devm_kfree(hdmi->dev, i2c);
286 return ERR_PTR(ret);
287 }
288
289 hdmi->i2c = i2c;
290 dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
291
292 return adap;
293 }
294
dw_hdmi_qp_config_avi_infoframe(struct dw_hdmi_qp * hdmi,const u8 * buffer,size_t len)295 static int dw_hdmi_qp_config_avi_infoframe(struct dw_hdmi_qp *hdmi,
296 const u8 *buffer, size_t len)
297 {
298 u32 val, i, j;
299
300 if (len != HDMI_INFOFRAME_SIZE(AVI)) {
301 dev_err(hdmi->dev, "failed to configure avi infoframe\n");
302 return -EINVAL;
303 }
304
305 /*
306 * DW HDMI QP IP uses a different byte format from standard AVI info
307 * frames, though generally the bits are in the correct bytes.
308 */
309 val = buffer[1] << 8 | buffer[2] << 16;
310 dw_hdmi_qp_write(hdmi, val, PKT_AVI_CONTENTS0);
311
312 for (i = 0; i < 4; i++) {
313 for (j = 0; j < 4; j++) {
314 if (i * 4 + j >= 14)
315 break;
316 if (!j)
317 val = buffer[i * 4 + j + 3];
318 val |= buffer[i * 4 + j + 3] << (8 * j);
319 }
320
321 dw_hdmi_qp_write(hdmi, val, PKT_AVI_CONTENTS1 + i * 4);
322 }
323
324 dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_AVI_FIELDRATE, PKTSCHED_PKT_CONFIG1);
325
326 dw_hdmi_qp_mod(hdmi, PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN,
327 PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN, PKTSCHED_PKT_EN);
328
329 return 0;
330 }
331
dw_hdmi_qp_config_drm_infoframe(struct dw_hdmi_qp * hdmi,const u8 * buffer,size_t len)332 static int dw_hdmi_qp_config_drm_infoframe(struct dw_hdmi_qp *hdmi,
333 const u8 *buffer, size_t len)
334 {
335 u32 val, i;
336
337 if (len != HDMI_INFOFRAME_SIZE(DRM)) {
338 dev_err(hdmi->dev, "failed to configure drm infoframe\n");
339 return -EINVAL;
340 }
341
342 dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_TX_EN, PKTSCHED_PKT_EN);
343
344 val = buffer[1] << 8 | buffer[2] << 16;
345 dw_hdmi_qp_write(hdmi, val, PKT_DRMI_CONTENTS0);
346
347 for (i = 0; i <= buffer[2]; i++) {
348 if (i % 4 == 0)
349 val = buffer[3 + i];
350 val |= buffer[3 + i] << ((i % 4) * 8);
351
352 if ((i % 4 == 3) || i == buffer[2])
353 dw_hdmi_qp_write(hdmi, val,
354 PKT_DRMI_CONTENTS1 + ((i / 4) * 4));
355 }
356
357 dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_FIELDRATE, PKTSCHED_PKT_CONFIG1);
358 dw_hdmi_qp_mod(hdmi, PKTSCHED_DRMI_TX_EN, PKTSCHED_DRMI_TX_EN,
359 PKTSCHED_PKT_EN);
360
361 return 0;
362 }
363
dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge * bridge,struct drm_bridge_state * old_state)364 static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge,
365 struct drm_bridge_state *old_state)
366 {
367 struct dw_hdmi_qp *hdmi = bridge->driver_private;
368 struct drm_atomic_state *state = old_state->base.state;
369 struct drm_connector_state *conn_state;
370 struct drm_connector *connector;
371 unsigned int op_mode;
372
373 connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
374 if (WARN_ON(!connector))
375 return;
376
377 conn_state = drm_atomic_get_new_connector_state(state, connector);
378 if (WARN_ON(!conn_state))
379 return;
380
381 if (connector->display_info.is_hdmi) {
382 dev_dbg(hdmi->dev, "%s mode=HDMI rate=%llu\n",
383 __func__, conn_state->hdmi.tmds_char_rate);
384 op_mode = 0;
385 } else {
386 dev_dbg(hdmi->dev, "%s mode=DVI\n", __func__);
387 op_mode = OPMODE_DVI;
388 }
389
390 hdmi->phy.ops->init(hdmi, hdmi->phy.data);
391
392 dw_hdmi_qp_mod(hdmi, HDCP2_BYPASS, HDCP2_BYPASS, HDCP2LOGIC_CONFIG0);
393 dw_hdmi_qp_mod(hdmi, op_mode, OPMODE_DVI, LINK_CONFIG0);
394
395 drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
396 }
397
dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge * bridge,struct drm_bridge_state * old_state)398 static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge,
399 struct drm_bridge_state *old_state)
400 {
401 struct dw_hdmi_qp *hdmi = bridge->driver_private;
402
403 hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
404 }
405
406 static enum drm_connector_status
dw_hdmi_qp_bridge_detect(struct drm_bridge * bridge)407 dw_hdmi_qp_bridge_detect(struct drm_bridge *bridge)
408 {
409 struct dw_hdmi_qp *hdmi = bridge->driver_private;
410
411 return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
412 }
413
414 static const struct drm_edid *
dw_hdmi_qp_bridge_edid_read(struct drm_bridge * bridge,struct drm_connector * connector)415 dw_hdmi_qp_bridge_edid_read(struct drm_bridge *bridge,
416 struct drm_connector *connector)
417 {
418 struct dw_hdmi_qp *hdmi = bridge->driver_private;
419 const struct drm_edid *drm_edid;
420
421 drm_edid = drm_edid_read_ddc(connector, bridge->ddc);
422 if (!drm_edid)
423 dev_dbg(hdmi->dev, "failed to get edid\n");
424
425 return drm_edid;
426 }
427
428 static enum drm_mode_status
dw_hdmi_qp_bridge_tmds_char_rate_valid(const struct drm_bridge * bridge,const struct drm_display_mode * mode,unsigned long long rate)429 dw_hdmi_qp_bridge_tmds_char_rate_valid(const struct drm_bridge *bridge,
430 const struct drm_display_mode *mode,
431 unsigned long long rate)
432 {
433 struct dw_hdmi_qp *hdmi = bridge->driver_private;
434
435 if (rate > HDMI14_MAX_TMDSCLK) {
436 dev_dbg(hdmi->dev, "Unsupported TMDS char rate: %lld\n", rate);
437 return MODE_CLOCK_HIGH;
438 }
439
440 return MODE_OK;
441 }
442
dw_hdmi_qp_bridge_clear_infoframe(struct drm_bridge * bridge,enum hdmi_infoframe_type type)443 static int dw_hdmi_qp_bridge_clear_infoframe(struct drm_bridge *bridge,
444 enum hdmi_infoframe_type type)
445 {
446 struct dw_hdmi_qp *hdmi = bridge->driver_private;
447
448 switch (type) {
449 case HDMI_INFOFRAME_TYPE_AVI:
450 dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN,
451 PKTSCHED_PKT_EN);
452 break;
453
454 case HDMI_INFOFRAME_TYPE_DRM:
455 dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_TX_EN, PKTSCHED_PKT_EN);
456 break;
457
458 default:
459 dev_dbg(hdmi->dev, "Unsupported infoframe type %x\n", type);
460 }
461
462 return 0;
463 }
464
dw_hdmi_qp_bridge_write_infoframe(struct drm_bridge * bridge,enum hdmi_infoframe_type type,const u8 * buffer,size_t len)465 static int dw_hdmi_qp_bridge_write_infoframe(struct drm_bridge *bridge,
466 enum hdmi_infoframe_type type,
467 const u8 *buffer, size_t len)
468 {
469 struct dw_hdmi_qp *hdmi = bridge->driver_private;
470
471 dw_hdmi_qp_bridge_clear_infoframe(bridge, type);
472
473 switch (type) {
474 case HDMI_INFOFRAME_TYPE_AVI:
475 return dw_hdmi_qp_config_avi_infoframe(hdmi, buffer, len);
476
477 case HDMI_INFOFRAME_TYPE_DRM:
478 return dw_hdmi_qp_config_drm_infoframe(hdmi, buffer, len);
479
480 default:
481 dev_dbg(hdmi->dev, "Unsupported infoframe type %x\n", type);
482 return 0;
483 }
484 }
485
486 static const struct drm_bridge_funcs dw_hdmi_qp_bridge_funcs = {
487 .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
488 .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
489 .atomic_reset = drm_atomic_helper_bridge_reset,
490 .atomic_enable = dw_hdmi_qp_bridge_atomic_enable,
491 .atomic_disable = dw_hdmi_qp_bridge_atomic_disable,
492 .detect = dw_hdmi_qp_bridge_detect,
493 .edid_read = dw_hdmi_qp_bridge_edid_read,
494 .hdmi_tmds_char_rate_valid = dw_hdmi_qp_bridge_tmds_char_rate_valid,
495 .hdmi_clear_infoframe = dw_hdmi_qp_bridge_clear_infoframe,
496 .hdmi_write_infoframe = dw_hdmi_qp_bridge_write_infoframe,
497 };
498
dw_hdmi_qp_main_hardirq(int irq,void * dev_id)499 static irqreturn_t dw_hdmi_qp_main_hardirq(int irq, void *dev_id)
500 {
501 struct dw_hdmi_qp *hdmi = dev_id;
502 struct dw_hdmi_qp_i2c *i2c = hdmi->i2c;
503 u32 stat;
504
505 stat = dw_hdmi_qp_read(hdmi, MAINUNIT_1_INT_STATUS);
506
507 i2c->stat = stat & (I2CM_OP_DONE_IRQ | I2CM_READ_REQUEST_IRQ |
508 I2CM_NACK_RCVD_IRQ);
509
510 if (i2c->stat) {
511 dw_hdmi_qp_write(hdmi, i2c->stat, MAINUNIT_1_INT_CLEAR);
512 complete(&i2c->cmp);
513 }
514
515 if (stat)
516 return IRQ_HANDLED;
517
518 return IRQ_NONE;
519 }
520
521 static const struct regmap_config dw_hdmi_qp_regmap_config = {
522 .reg_bits = 32,
523 .val_bits = 32,
524 .reg_stride = 4,
525 .max_register = EARCRX_1_INT_FORCE,
526 };
527
dw_hdmi_qp_init_hw(struct dw_hdmi_qp * hdmi)528 static void dw_hdmi_qp_init_hw(struct dw_hdmi_qp *hdmi)
529 {
530 dw_hdmi_qp_write(hdmi, 0, MAINUNIT_0_INT_MASK_N);
531 dw_hdmi_qp_write(hdmi, 0, MAINUNIT_1_INT_MASK_N);
532 dw_hdmi_qp_write(hdmi, 428571429, TIMER_BASE_CONFIG0);
533
534 /* Software reset */
535 dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0);
536
537 dw_hdmi_qp_write(hdmi, 0x085c085c, I2CM_FM_SCL_CONFIG0);
538
539 dw_hdmi_qp_mod(hdmi, 0, I2CM_FM_EN, I2CM_INTERFACE_CONTROL0);
540
541 /* Clear DONE and ERROR interrupts */
542 dw_hdmi_qp_write(hdmi, I2CM_OP_DONE_CLEAR | I2CM_NACK_RCVD_CLEAR,
543 MAINUNIT_1_INT_CLEAR);
544
545 if (hdmi->phy.ops->setup_hpd)
546 hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data);
547 }
548
dw_hdmi_qp_bind(struct platform_device * pdev,struct drm_encoder * encoder,const struct dw_hdmi_qp_plat_data * plat_data)549 struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,
550 struct drm_encoder *encoder,
551 const struct dw_hdmi_qp_plat_data *plat_data)
552 {
553 struct device *dev = &pdev->dev;
554 struct dw_hdmi_qp *hdmi;
555 void __iomem *regs;
556 int ret;
557
558 if (!plat_data->phy_ops || !plat_data->phy_ops->init ||
559 !plat_data->phy_ops->disable || !plat_data->phy_ops->read_hpd) {
560 dev_err(dev, "Missing platform PHY ops\n");
561 return ERR_PTR(-ENODEV);
562 }
563
564 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
565 if (!hdmi)
566 return ERR_PTR(-ENOMEM);
567
568 hdmi->dev = dev;
569
570 regs = devm_platform_ioremap_resource(pdev, 0);
571 if (IS_ERR(regs))
572 return ERR_CAST(regs);
573
574 hdmi->regm = devm_regmap_init_mmio(dev, regs, &dw_hdmi_qp_regmap_config);
575 if (IS_ERR(hdmi->regm)) {
576 dev_err(dev, "Failed to configure regmap\n");
577 return ERR_CAST(hdmi->regm);
578 }
579
580 hdmi->phy.ops = plat_data->phy_ops;
581 hdmi->phy.data = plat_data->phy_data;
582
583 dw_hdmi_qp_init_hw(hdmi);
584
585 ret = devm_request_threaded_irq(dev, plat_data->main_irq,
586 dw_hdmi_qp_main_hardirq, NULL,
587 IRQF_SHARED, dev_name(dev), hdmi);
588 if (ret)
589 return ERR_PTR(ret);
590
591 hdmi->bridge.driver_private = hdmi;
592 hdmi->bridge.funcs = &dw_hdmi_qp_bridge_funcs;
593 hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT |
594 DRM_BRIDGE_OP_EDID |
595 DRM_BRIDGE_OP_HDMI |
596 DRM_BRIDGE_OP_HPD;
597 hdmi->bridge.of_node = pdev->dev.of_node;
598 hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
599 hdmi->bridge.vendor = "Synopsys";
600 hdmi->bridge.product = "DW HDMI QP TX";
601
602 hdmi->bridge.ddc = dw_hdmi_qp_i2c_adapter(hdmi);
603 if (IS_ERR(hdmi->bridge.ddc))
604 return ERR_CAST(hdmi->bridge.ddc);
605
606 ret = devm_drm_bridge_add(dev, &hdmi->bridge);
607 if (ret)
608 return ERR_PTR(ret);
609
610 ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL,
611 DRM_BRIDGE_ATTACH_NO_CONNECTOR);
612 if (ret)
613 return ERR_PTR(ret);
614
615 return hdmi;
616 }
617 EXPORT_SYMBOL_GPL(dw_hdmi_qp_bind);
618
dw_hdmi_qp_resume(struct device * dev,struct dw_hdmi_qp * hdmi)619 void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi)
620 {
621 dw_hdmi_qp_init_hw(hdmi);
622 }
623 EXPORT_SYMBOL_GPL(dw_hdmi_qp_resume);
624
625 MODULE_AUTHOR("Algea Cao <[email protected]>");
626 MODULE_AUTHOR("Cristian Ciocaltea <[email protected]>");
627 MODULE_DESCRIPTION("DW HDMI QP transmitter library");
628 MODULE_LICENSE("GPL");
629