Lines Matching +full:ddc +full:- +full:i2c +full:- +full:bus
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>
12 #include <linux/i2c.h>
29 #include <sound/hdmi-codec.h>
31 #include "dw-hdmi-qp.h"
43 * slow so we pre-compute values we expect to see.
138 struct dw_hdmi_qp_i2c *i2c;
153 regmap_write(hdmi->regm, offset, val);
160 regmap_read(hdmi->regm, offset, &val);
168 regmap_update_bits(hdmi->regm, reg, mask, data);
209 return -ENOENT;
213 return tmds_n->n_32k;
217 return (freq / 44100) * tmds_n->n_44k1;
221 return (freq / 48000) * tmds_n->n_48k;
223 return -ENOENT;
255 (diff == best_diff && abs(n - ideal_n) < best_n_distance)) {
258 best_n_distance = abs(best_n - ideal_n);
265 if (best_diff == 0 && (abs(n - ideal_n) > best_n_distance))
280 dev_warn(hdmi->dev, "Rate %lu missing; compute N dynamically\n",
304 return tmds_cts->cts_32k;
308 return tmds_cts->cts_44k1;
312 return tmds_cts->cts_48k;
314 return -ENOENT;
339 switch (hparms->channels) {
357 * Enable bpcuv generated internally for L-PCM, or received
360 switch (fmt->bit_fmt) {
362 conf0 = (hparms->channels == 8) ? AUD_HBR : AUD_ASP;
399 * CS5: | | CGMS-A |
420 regmap_bulk_write(hdmi->regm, AUDPKT_CHSTATUS_OVR1, &channel_status[3], 1);
448 if (hdmi->tmds_char_rate)
462 if (!hdmi->tmds_char_rate)
463 return -ENODEV;
465 if (fmt->bit_clk_provider | fmt->frame_clk_provider) {
466 dev_err(hdmi->dev, "unsupported clock settings\n");
467 return -EINVAL;
470 if (fmt->bit_fmt == SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE)
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);
507 if (hdmi->tmds_char_rate)
514 struct dw_hdmi_qp_i2c *i2c = hdmi->i2c;
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;
523 while (length--) {
524 reinit_completion(&i2c->cmp);
526 dw_hdmi_qp_mod(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR,
529 if (i2c->is_segment)
536 stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
538 dev_err(hdmi->dev, "i2c read timed out\n");
540 return -EAGAIN;
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");
547 return -EIO;
554 i2c->is_segment = false;
562 struct dw_hdmi_qp_i2c *i2c = hdmi->i2c;
565 if (!i2c->is_regaddr) {
567 i2c->slave_reg = buf[0];
568 length--;
570 i2c->is_regaddr = true;
573 while (length--) {
574 reinit_completion(&i2c->cmp);
577 dw_hdmi_qp_mod(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR,
582 stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
584 dev_err(hdmi->dev, "i2c write time out!\n");
586 return -EAGAIN;
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");
593 return -EIO;
606 struct dw_hdmi_qp_i2c *i2c = hdmi->i2c;
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.
617 return -EOPNOTSUPP;
621 dev_err(hdmi->dev,
624 return -EOPNOTSUPP;
628 guard(mutex)(&i2c->lock);
635 /* Set slave device address taken from the first I2C message */
642 i2c->is_regaddr = false;
644 /* Set segment pointer for I2C extended read mode operation */
645 i2c->is_segment = false;
649 i2c->is_segment = true;
688 struct dw_hdmi_qp_i2c *i2c;
692 i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
693 if (!i2c)
694 return ERR_PTR(-ENOMEM);
696 mutex_init(&i2c->lock);
697 init_completion(&i2c->cmp);
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));
707 ret = devm_i2c_add_adapter(hdmi->dev, adap);
709 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
710 devm_kfree(hdmi->dev, i2c);
714 hdmi->i2c = i2c;
715 dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
726 dev_err(hdmi->dev, "failed to configure avi infoframe\n");
727 return -EINVAL;
763 dev_err(hdmi->dev, "failed to configure drm infoframe\n");
764 return -EINVAL;
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);
837 struct dw_hdmi_qp *hdmi = bridge->driver_private;
842 connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
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);
854 hdmi->tmds_char_rate = conn_state->hdmi.tmds_char_rate;
856 dev_dbg(hdmi->dev, "%s mode=DVI\n", __func__);
860 hdmi->phy.ops->init(hdmi, hdmi->phy.data);
871 struct dw_hdmi_qp *hdmi = bridge->driver_private;
873 hdmi->tmds_char_rate = 0;
875 hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
881 struct dw_hdmi_qp *hdmi = bridge->driver_private;
883 return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
890 struct dw_hdmi_qp *hdmi = bridge->driver_private;
893 drm_edid = drm_edid_read_ddc(connector, bridge->ddc);
895 dev_dbg(hdmi->dev, "failed to get edid\n");
905 struct dw_hdmi_qp *hdmi = bridge->driver_private;
908 dev_dbg(hdmi->dev, "Unsupported TMDS char rate: %lld\n", rate);
918 struct dw_hdmi_qp *hdmi = bridge->driver_private;
938 dev_dbg(hdmi->dev, "Unsupported infoframe type %x\n", type);
948 struct dw_hdmi_qp *hdmi = bridge->driver_private;
963 dev_dbg(hdmi->dev, "Unsupported infoframe type %x\n", type);
987 struct dw_hdmi_qp_i2c *i2c = hdmi->i2c;
992 i2c->stat = stat & (I2CM_OP_DONE_IRQ | I2CM_READ_REQUEST_IRQ |
995 if (i2c->stat) {
996 dw_hdmi_qp_write(hdmi, i2c->stat, MAINUNIT_1_INT_CLEAR);
997 complete(&i2c->cmp);
1030 if (hdmi->phy.ops->setup_hpd)
1031 hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data);
1038 struct device *dev = &pdev->dev;
1043 if (!plat_data->phy_ops || !plat_data->phy_ops->init ||
1044 !plat_data->phy_ops->disable || !plat_data->phy_ops->read_hpd) {
1046 return ERR_PTR(-ENODEV);
1054 hdmi->dev = dev;
1060 hdmi->regm = devm_regmap_init_mmio(dev, regs, &dw_hdmi_qp_regmap_config);
1061 if (IS_ERR(hdmi->regm)) {
1063 return ERR_CAST(hdmi->regm);
1066 hdmi->phy.ops = plat_data->phy_ops;
1067 hdmi->phy.data = plat_data->phy_data;
1071 ret = devm_request_threaded_irq(dev, plat_data->main_irq,
1077 hdmi->bridge.driver_private = hdmi;
1078 hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT |
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";
1088 hdmi->bridge.ddc = dw_hdmi_qp_i2c_adapter(hdmi);
1089 if (IS_ERR(hdmi->bridge.ddc))
1090 return ERR_CAST(hdmi->bridge.ddc);
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;
1096 ret = devm_drm_bridge_add(dev, &hdmi->bridge);
1100 ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL,
1115 MODULE_AUTHOR("Algea Cao <algea.cao@rock-chips.com>");