Lines Matching +full:audio +full:- +full:bridge

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd.
6 * Author: Algea Cao <algea.cao@rock-chips.com>
19 #include <drm/bridge/dw_hdmi_qp.h>
32 #include <sound/hdmi-codec.h>
34 #include "dw-hdmi-qp.h"
46 * slow so we pre-compute values we expect to see.
49 * the recommended N values specified in the Audio chapter of the HDMI
105 * These are the CTS values as recommended in the Audio chapter of the HDMI
150 struct drm_bridge bridge; member
173 regmap_write(hdmi->regm, offset, val); in dw_hdmi_qp_write()
180 regmap_read(hdmi->regm, offset, &val); in dw_hdmi_qp_read()
188 regmap_update_bits(hdmi->regm, reg, mask, data); in dw_hdmi_qp_mod()
191 static struct dw_hdmi_qp *dw_hdmi_qp_from_bridge(struct drm_bridge *bridge) in dw_hdmi_qp_from_bridge() argument
193 return container_of(bridge, struct dw_hdmi_qp, bridge); in dw_hdmi_qp_from_bridge()
229 return -ENOENT; in dw_hdmi_qp_match_tmds_n_table()
233 return tmds_n->n_32k; in dw_hdmi_qp_match_tmds_n_table()
237 return (freq / 44100) * tmds_n->n_44k1; in dw_hdmi_qp_match_tmds_n_table()
241 return (freq / 48000) * tmds_n->n_48k; in dw_hdmi_qp_match_tmds_n_table()
243 return -ENOENT; in dw_hdmi_qp_match_tmds_n_table()
267 /* If the ideal N could satisfy the audio math, then just take it */ in dw_hdmi_qp_compute_n()
275 (diff == best_diff && abs(n - ideal_n) < best_n_distance)) { in dw_hdmi_qp_compute_n()
278 best_n_distance = abs(best_n - ideal_n); in dw_hdmi_qp_compute_n()
282 * The best N already satisfy the audio math, and also be in dw_hdmi_qp_compute_n()
285 if (best_diff == 0 && (abs(n - ideal_n) > best_n_distance)) in dw_hdmi_qp_compute_n()
300 dev_warn(hdmi->dev, "Rate %lu missing; compute N dynamically\n", in dw_hdmi_qp_find_n()
324 return tmds_cts->cts_32k; in dw_hdmi_qp_find_cts()
328 return tmds_cts->cts_44k1; in dw_hdmi_qp_find_cts()
332 return tmds_cts->cts_48k; in dw_hdmi_qp_find_cts()
334 return -ENOENT; in dw_hdmi_qp_find_cts()
344 /* Reset the audio data path of the AVP */ in dw_hdmi_qp_set_audio_interface()
352 /* Clear the audio FIFO */ in dw_hdmi_qp_set_audio_interface()
355 /* Select I2S interface as the audio source */ in dw_hdmi_qp_set_audio_interface()
359 switch (hparms->channels) { in dw_hdmi_qp_set_audio_interface()
377 * Enable bpcuv generated internally for L-PCM, or received in dw_hdmi_qp_set_audio_interface()
380 switch (fmt->bit_fmt) { in dw_hdmi_qp_set_audio_interface()
382 conf0 = (hparms->channels == 8) ? AUD_HBR : AUD_ASP; in dw_hdmi_qp_set_audio_interface()
393 /* Enable audio FIFO auto clear when overflow */ in dw_hdmi_qp_set_audio_interface()
399 * When transmitting IEC60958 linear PCM audio, these registers allow to
402 * used when the I2S audio interface, General Purpose Audio (GPA),
403 * or AHB audio DMA (AHBAUDDMA) interface is active
419 * CS5: | | CGMS-A | in dw_hdmi_qp_set_channel_status()
440 regmap_bulk_write(hdmi->regm, AUDPKT_CHSTATUS_OVR1, &channel_status[3], 1); in dw_hdmi_qp_set_channel_status()
463 static int dw_hdmi_qp_audio_enable(struct drm_bridge *bridge, in dw_hdmi_qp_audio_enable() argument
466 struct dw_hdmi_qp *hdmi = dw_hdmi_qp_from_bridge(bridge); in dw_hdmi_qp_audio_enable()
468 if (hdmi->tmds_char_rate) in dw_hdmi_qp_audio_enable()
474 static int dw_hdmi_qp_audio_prepare(struct drm_bridge *bridge, in dw_hdmi_qp_audio_prepare() argument
479 struct dw_hdmi_qp *hdmi = dw_hdmi_qp_from_bridge(bridge); in dw_hdmi_qp_audio_prepare()
482 if (!hdmi->tmds_char_rate) in dw_hdmi_qp_audio_prepare()
483 return -ENODEV; in dw_hdmi_qp_audio_prepare()
485 if (fmt->bit_clk_provider | fmt->frame_clk_provider) { in dw_hdmi_qp_audio_prepare()
486 dev_err(hdmi->dev, "unsupported clock settings\n"); in dw_hdmi_qp_audio_prepare()
487 return -EINVAL; in dw_hdmi_qp_audio_prepare()
490 if (fmt->bit_fmt == SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE) in dw_hdmi_qp_audio_prepare()
494 dw_hdmi_qp_set_sample_rate(hdmi, hdmi->tmds_char_rate, hparms->sample_rate); in dw_hdmi_qp_audio_prepare()
495 dw_hdmi_qp_set_channel_status(hdmi, hparms->iec.status, ref2stream); in dw_hdmi_qp_audio_prepare()
496 drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector, &hparms->cea); in dw_hdmi_qp_audio_prepare()
520 static void dw_hdmi_qp_audio_disable(struct drm_bridge *bridge, in dw_hdmi_qp_audio_disable() argument
523 struct dw_hdmi_qp *hdmi = dw_hdmi_qp_from_bridge(bridge); in dw_hdmi_qp_audio_disable()
527 if (hdmi->tmds_char_rate) in dw_hdmi_qp_audio_disable()
534 struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; in dw_hdmi_qp_i2c_read()
537 if (!i2c->is_regaddr) { in dw_hdmi_qp_i2c_read()
538 dev_dbg(hdmi->dev, "set read register address to 0\n"); in dw_hdmi_qp_i2c_read()
539 i2c->slave_reg = 0x00; in dw_hdmi_qp_i2c_read()
540 i2c->is_regaddr = true; in dw_hdmi_qp_i2c_read()
543 while (length--) { in dw_hdmi_qp_i2c_read()
544 reinit_completion(&i2c->cmp); in dw_hdmi_qp_i2c_read()
546 dw_hdmi_qp_mod(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR, in dw_hdmi_qp_i2c_read()
549 if (i2c->is_segment) in dw_hdmi_qp_i2c_read()
556 stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); in dw_hdmi_qp_i2c_read()
558 dev_err(hdmi->dev, "i2c read timed out\n"); in dw_hdmi_qp_i2c_read()
560 return -EAGAIN; in dw_hdmi_qp_i2c_read()
564 if (i2c->stat & I2CM_NACK_RCVD_IRQ) { in dw_hdmi_qp_i2c_read()
565 dev_err(hdmi->dev, "i2c read error\n"); in dw_hdmi_qp_i2c_read()
567 return -EIO; in dw_hdmi_qp_i2c_read()
574 i2c->is_segment = false; in dw_hdmi_qp_i2c_read()
582 struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; in dw_hdmi_qp_i2c_write()
585 if (!i2c->is_regaddr) { in dw_hdmi_qp_i2c_write()
587 i2c->slave_reg = buf[0]; in dw_hdmi_qp_i2c_write()
588 length--; in dw_hdmi_qp_i2c_write()
590 i2c->is_regaddr = true; in dw_hdmi_qp_i2c_write()
593 while (length--) { in dw_hdmi_qp_i2c_write()
594 reinit_completion(&i2c->cmp); in dw_hdmi_qp_i2c_write()
597 dw_hdmi_qp_mod(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR, in dw_hdmi_qp_i2c_write()
602 stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); in dw_hdmi_qp_i2c_write()
604 dev_err(hdmi->dev, "i2c write time out!\n"); in dw_hdmi_qp_i2c_write()
606 return -EAGAIN; in dw_hdmi_qp_i2c_write()
610 if (i2c->stat & I2CM_NACK_RCVD_IRQ) { in dw_hdmi_qp_i2c_write()
611 dev_err(hdmi->dev, "i2c write nack!\n"); in dw_hdmi_qp_i2c_write()
613 return -EIO; in dw_hdmi_qp_i2c_write()
626 struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; in dw_hdmi_qp_i2c_xfer()
632 * The internal I2C controller does not support the multi-byte in dw_hdmi_qp_i2c_xfer()
637 return -EOPNOTSUPP; in dw_hdmi_qp_i2c_xfer()
641 dev_err(hdmi->dev, in dw_hdmi_qp_i2c_xfer()
644 return -EOPNOTSUPP; in dw_hdmi_qp_i2c_xfer()
648 guard(mutex)(&i2c->lock); in dw_hdmi_qp_i2c_xfer()
662 i2c->is_regaddr = false; in dw_hdmi_qp_i2c_xfer()
665 i2c->is_segment = false; in dw_hdmi_qp_i2c_xfer()
669 i2c->is_segment = true; in dw_hdmi_qp_i2c_xfer()
712 i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL); in dw_hdmi_qp_i2c_adapter()
714 return ERR_PTR(-ENOMEM); in dw_hdmi_qp_i2c_adapter()
716 mutex_init(&i2c->lock); in dw_hdmi_qp_i2c_adapter()
717 init_completion(&i2c->cmp); in dw_hdmi_qp_i2c_adapter()
719 adap = &i2c->adap; in dw_hdmi_qp_i2c_adapter()
720 adap->owner = THIS_MODULE; in dw_hdmi_qp_i2c_adapter()
721 adap->dev.parent = hdmi->dev; in dw_hdmi_qp_i2c_adapter()
722 adap->algo = &dw_hdmi_qp_algorithm; in dw_hdmi_qp_i2c_adapter()
723 strscpy(adap->name, "DesignWare HDMI QP", sizeof(adap->name)); in dw_hdmi_qp_i2c_adapter()
727 ret = devm_i2c_add_adapter(hdmi->dev, adap); in dw_hdmi_qp_i2c_adapter()
729 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name); in dw_hdmi_qp_i2c_adapter()
730 devm_kfree(hdmi->dev, i2c); in dw_hdmi_qp_i2c_adapter()
734 hdmi->i2c = i2c; in dw_hdmi_qp_i2c_adapter()
735 dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name); in dw_hdmi_qp_i2c_adapter()
746 dev_err(hdmi->dev, "failed to configure avi infoframe\n"); in dw_hdmi_qp_config_avi_infoframe()
747 return -EINVAL; in dw_hdmi_qp_config_avi_infoframe()
783 dev_err(hdmi->dev, "failed to configure drm infoframe\n"); in dw_hdmi_qp_config_drm_infoframe()
784 return -EINVAL; in dw_hdmi_qp_config_drm_infoframe()
838 regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS0, &header_bytes, 1); in dw_hdmi_qp_config_audio_infoframe()
839 regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS1, &buffer[3], 1); in dw_hdmi_qp_config_audio_infoframe()
840 regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS2, &buffer[4], 1); in dw_hdmi_qp_config_audio_infoframe()
854 static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge, in dw_hdmi_qp_bridge_atomic_enable() argument
857 struct dw_hdmi_qp *hdmi = bridge->driver_private; in dw_hdmi_qp_bridge_atomic_enable()
862 connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); in dw_hdmi_qp_bridge_atomic_enable()
870 if (connector->display_info.is_hdmi) { in dw_hdmi_qp_bridge_atomic_enable()
871 dev_dbg(hdmi->dev, "%s mode=HDMI %s rate=%llu bpc=%u\n", __func__, in dw_hdmi_qp_bridge_atomic_enable()
872 drm_hdmi_connector_get_output_format_name(conn_state->hdmi.output_format), in dw_hdmi_qp_bridge_atomic_enable()
873 conn_state->hdmi.tmds_char_rate, conn_state->hdmi.output_bpc); in dw_hdmi_qp_bridge_atomic_enable()
875 hdmi->tmds_char_rate = conn_state->hdmi.tmds_char_rate; in dw_hdmi_qp_bridge_atomic_enable()
877 dev_dbg(hdmi->dev, "%s mode=DVI\n", __func__); in dw_hdmi_qp_bridge_atomic_enable()
881 hdmi->phy.ops->init(hdmi, hdmi->phy.data); in dw_hdmi_qp_bridge_atomic_enable()
889 static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge, in dw_hdmi_qp_bridge_atomic_disable() argument
892 struct dw_hdmi_qp *hdmi = bridge->driver_private; in dw_hdmi_qp_bridge_atomic_disable()
894 hdmi->tmds_char_rate = 0; in dw_hdmi_qp_bridge_atomic_disable()
896 hdmi->phy.ops->disable(hdmi, hdmi->phy.data); in dw_hdmi_qp_bridge_atomic_disable()
900 dw_hdmi_qp_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector) in dw_hdmi_qp_bridge_detect() argument
902 struct dw_hdmi_qp *hdmi = bridge->driver_private; in dw_hdmi_qp_bridge_detect()
904 return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data); in dw_hdmi_qp_bridge_detect()
908 dw_hdmi_qp_bridge_edid_read(struct drm_bridge *bridge, in dw_hdmi_qp_bridge_edid_read() argument
911 struct dw_hdmi_qp *hdmi = bridge->driver_private; in dw_hdmi_qp_bridge_edid_read()
914 drm_edid = drm_edid_read_ddc(connector, bridge->ddc); in dw_hdmi_qp_bridge_edid_read()
916 dev_dbg(hdmi->dev, "failed to get edid\n"); in dw_hdmi_qp_bridge_edid_read()
922 dw_hdmi_qp_bridge_tmds_char_rate_valid(const struct drm_bridge *bridge, in dw_hdmi_qp_bridge_tmds_char_rate_valid() argument
926 struct dw_hdmi_qp *hdmi = bridge->driver_private; in dw_hdmi_qp_bridge_tmds_char_rate_valid()
929 dev_dbg(hdmi->dev, "Unsupported TMDS char rate: %lld\n", rate); in dw_hdmi_qp_bridge_tmds_char_rate_valid()
936 static int dw_hdmi_qp_bridge_clear_infoframe(struct drm_bridge *bridge, in dw_hdmi_qp_bridge_clear_infoframe() argument
939 struct dw_hdmi_qp *hdmi = bridge->driver_private; in dw_hdmi_qp_bridge_clear_infoframe()
959 dev_dbg(hdmi->dev, "Unsupported infoframe type %x\n", type); in dw_hdmi_qp_bridge_clear_infoframe()
965 static int dw_hdmi_qp_bridge_write_infoframe(struct drm_bridge *bridge, in dw_hdmi_qp_bridge_write_infoframe() argument
969 struct dw_hdmi_qp *hdmi = bridge->driver_private; in dw_hdmi_qp_bridge_write_infoframe()
971 dw_hdmi_qp_bridge_clear_infoframe(bridge, type); in dw_hdmi_qp_bridge_write_infoframe()
984 dev_dbg(hdmi->dev, "Unsupported infoframe type %x\n", type); in dw_hdmi_qp_bridge_write_infoframe()
993 struct dw_hdmi_qp_cec *cec = hdmi->cec; in dw_hdmi_qp_cec_hardirq()
1004 cec->tx_status = CEC_TX_STATUS_ERROR; in dw_hdmi_qp_cec_hardirq()
1005 cec->tx_done = true; in dw_hdmi_qp_cec_hardirq()
1008 cec->tx_status = CEC_TX_STATUS_OK; in dw_hdmi_qp_cec_hardirq()
1009 cec->tx_done = true; in dw_hdmi_qp_cec_hardirq()
1012 cec->tx_status = CEC_TX_STATUS_NACK; in dw_hdmi_qp_cec_hardirq()
1013 cec->tx_done = true; in dw_hdmi_qp_cec_hardirq()
1023 if (len > sizeof(cec->rx_msg.msg)) in dw_hdmi_qp_cec_hardirq()
1024 len = sizeof(cec->rx_msg.msg); in dw_hdmi_qp_cec_hardirq()
1028 cec->rx_msg.msg[i * 4] = val & 0xff; in dw_hdmi_qp_cec_hardirq()
1029 cec->rx_msg.msg[i * 4 + 1] = (val >> 8) & 0xff; in dw_hdmi_qp_cec_hardirq()
1030 cec->rx_msg.msg[i * 4 + 2] = (val >> 16) & 0xff; in dw_hdmi_qp_cec_hardirq()
1031 cec->rx_msg.msg[i * 4 + 3] = (val >> 24) & 0xff; in dw_hdmi_qp_cec_hardirq()
1036 cec->rx_msg.len = len; in dw_hdmi_qp_cec_hardirq()
1037 cec->rx_done = true; in dw_hdmi_qp_cec_hardirq()
1048 struct dw_hdmi_qp_cec *cec = hdmi->cec; in dw_hdmi_qp_cec_thread()
1050 if (cec->tx_done) { in dw_hdmi_qp_cec_thread()
1051 cec->tx_done = false; in dw_hdmi_qp_cec_thread()
1052 drm_connector_hdmi_cec_transmit_attempt_done(cec->connector, in dw_hdmi_qp_cec_thread()
1053 cec->tx_status); in dw_hdmi_qp_cec_thread()
1056 if (cec->rx_done) { in dw_hdmi_qp_cec_thread()
1057 cec->rx_done = false; in dw_hdmi_qp_cec_thread()
1058 drm_connector_hdmi_cec_received_msg(cec->connector, &cec->rx_msg); in dw_hdmi_qp_cec_thread()
1064 static int dw_hdmi_qp_cec_init(struct drm_bridge *bridge, in dw_hdmi_qp_cec_init() argument
1067 struct dw_hdmi_qp *hdmi = dw_hdmi_qp_from_bridge(bridge); in dw_hdmi_qp_cec_init()
1068 struct dw_hdmi_qp_cec *cec = hdmi->cec; in dw_hdmi_qp_cec_init()
1070 cec->connector = connector; in dw_hdmi_qp_cec_init()
1076 return devm_request_threaded_irq(hdmi->dev, cec->irq, in dw_hdmi_qp_cec_init()
1079 dev_name(hdmi->dev), hdmi); in dw_hdmi_qp_cec_init()
1082 static int dw_hdmi_qp_cec_log_addr(struct drm_bridge *bridge, u8 logical_addr) in dw_hdmi_qp_cec_log_addr() argument
1084 struct dw_hdmi_qp *hdmi = dw_hdmi_qp_from_bridge(bridge); in dw_hdmi_qp_cec_log_addr()
1085 struct dw_hdmi_qp_cec *cec = hdmi->cec; in dw_hdmi_qp_cec_log_addr()
1088 cec->addresses = 0; in dw_hdmi_qp_cec_log_addr()
1090 cec->addresses |= BIT(logical_addr) | CEC_ADDR_BROADCAST; in dw_hdmi_qp_cec_log_addr()
1092 dw_hdmi_qp_write(hdmi, cec->addresses, CEC_ADDR); in dw_hdmi_qp_cec_log_addr()
1097 static int dw_hdmi_qp_cec_enable(struct drm_bridge *bridge, bool enable) in dw_hdmi_qp_cec_enable() argument
1099 struct dw_hdmi_qp *hdmi = dw_hdmi_qp_from_bridge(bridge); in dw_hdmi_qp_cec_enable()
1118 dw_hdmi_qp_cec_log_addr(bridge, CEC_LOG_ADDR_INVALID); in dw_hdmi_qp_cec_enable()
1129 static int dw_hdmi_qp_cec_transmit(struct drm_bridge *bridge, u8 attempts, in dw_hdmi_qp_cec_transmit() argument
1132 struct dw_hdmi_qp *hdmi = dw_hdmi_qp_from_bridge(bridge); in dw_hdmi_qp_cec_transmit()
1136 for (i = 0; i < msg->len; i++) { in dw_hdmi_qp_cec_transmit()
1138 val = msg->msg[i]; in dw_hdmi_qp_cec_transmit()
1140 val |= msg->msg[i] << 8; in dw_hdmi_qp_cec_transmit()
1142 val |= msg->msg[i] << 16; in dw_hdmi_qp_cec_transmit()
1144 val |= msg->msg[i] << 24; in dw_hdmi_qp_cec_transmit()
1146 if (i == (msg->len - 1) || (i % 4) == 3) in dw_hdmi_qp_cec_transmit()
1150 dw_hdmi_qp_write(hdmi, msg->len - 1, CEC_TX_COUNT); in dw_hdmi_qp_cec_transmit()
1185 struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; in dw_hdmi_qp_main_hardirq()
1190 i2c->stat = stat & (I2CM_OP_DONE_IRQ | I2CM_READ_REQUEST_IRQ | in dw_hdmi_qp_main_hardirq()
1193 if (i2c->stat) { in dw_hdmi_qp_main_hardirq()
1194 dw_hdmi_qp_write(hdmi, i2c->stat, MAINUNIT_1_INT_CLEAR); in dw_hdmi_qp_main_hardirq()
1195 complete(&i2c->cmp); in dw_hdmi_qp_main_hardirq()
1215 dw_hdmi_qp_write(hdmi, hdmi->ref_clk_rate, TIMER_BASE_CONFIG0); in dw_hdmi_qp_init_hw()
1226 if (hdmi->phy.ops->setup_hpd) in dw_hdmi_qp_init_hw()
1227 hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data); in dw_hdmi_qp_init_hw()
1234 struct device *dev = &pdev->dev; in dw_hdmi_qp_bind()
1239 if (!plat_data->phy_ops || !plat_data->phy_ops->init || in dw_hdmi_qp_bind()
1240 !plat_data->phy_ops->disable || !plat_data->phy_ops->read_hpd) { in dw_hdmi_qp_bind()
1242 return ERR_PTR(-ENODEV); in dw_hdmi_qp_bind()
1245 hdmi = devm_drm_bridge_alloc(dev, struct dw_hdmi_qp, bridge, in dw_hdmi_qp_bind()
1250 hdmi->dev = dev; in dw_hdmi_qp_bind()
1256 hdmi->regm = devm_regmap_init_mmio(dev, regs, &dw_hdmi_qp_regmap_config); in dw_hdmi_qp_bind()
1257 if (IS_ERR(hdmi->regm)) { in dw_hdmi_qp_bind()
1259 return ERR_CAST(hdmi->regm); in dw_hdmi_qp_bind()
1262 hdmi->phy.ops = plat_data->phy_ops; in dw_hdmi_qp_bind()
1263 hdmi->phy.data = plat_data->phy_data; in dw_hdmi_qp_bind()
1265 if (plat_data->ref_clk_rate) { in dw_hdmi_qp_bind()
1266 hdmi->ref_clk_rate = plat_data->ref_clk_rate; in dw_hdmi_qp_bind()
1268 hdmi->ref_clk_rate = 428571429; in dw_hdmi_qp_bind()
1274 ret = devm_request_threaded_irq(dev, plat_data->main_irq, in dw_hdmi_qp_bind()
1280 hdmi->bridge.driver_private = hdmi; in dw_hdmi_qp_bind()
1281 hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT | in dw_hdmi_qp_bind()
1286 hdmi->bridge.of_node = pdev->dev.of_node; in dw_hdmi_qp_bind()
1287 hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA; in dw_hdmi_qp_bind()
1288 hdmi->bridge.vendor = "Synopsys"; in dw_hdmi_qp_bind()
1289 hdmi->bridge.product = "DW HDMI QP TX"; in dw_hdmi_qp_bind()
1291 if (plat_data->supported_formats) in dw_hdmi_qp_bind()
1292 hdmi->bridge.supported_formats = plat_data->supported_formats; in dw_hdmi_qp_bind()
1294 if (plat_data->max_bpc) in dw_hdmi_qp_bind()
1295 hdmi->bridge.max_bpc = plat_data->max_bpc; in dw_hdmi_qp_bind()
1297 hdmi->bridge.ddc = dw_hdmi_qp_i2c_adapter(hdmi); in dw_hdmi_qp_bind()
1298 if (IS_ERR(hdmi->bridge.ddc)) in dw_hdmi_qp_bind()
1299 return ERR_CAST(hdmi->bridge.ddc); in dw_hdmi_qp_bind()
1301 hdmi->bridge.hdmi_audio_max_i2s_playback_channels = 8; in dw_hdmi_qp_bind()
1302 hdmi->bridge.hdmi_audio_dev = dev; in dw_hdmi_qp_bind()
1303 hdmi->bridge.hdmi_audio_dai_port = 1; in dw_hdmi_qp_bind()
1306 if (plat_data->cec_irq) { in dw_hdmi_qp_bind()
1307 hdmi->bridge.ops |= DRM_BRIDGE_OP_HDMI_CEC_ADAPTER; in dw_hdmi_qp_bind()
1308 hdmi->bridge.hdmi_cec_dev = dev; in dw_hdmi_qp_bind()
1309 hdmi->bridge.hdmi_cec_adapter_name = dev_name(dev); in dw_hdmi_qp_bind()
1311 hdmi->cec = devm_kzalloc(hdmi->dev, sizeof(*hdmi->cec), GFP_KERNEL); in dw_hdmi_qp_bind()
1312 if (!hdmi->cec) in dw_hdmi_qp_bind()
1313 return ERR_PTR(-ENOMEM); in dw_hdmi_qp_bind()
1315 hdmi->cec->irq = plat_data->cec_irq; in dw_hdmi_qp_bind()
1321 ret = devm_drm_bridge_add(dev, &hdmi->bridge); in dw_hdmi_qp_bind()
1325 ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL, in dw_hdmi_qp_bind()
1340 MODULE_AUTHOR("Algea Cao <algea.cao@rock-chips.com>");