Lines Matching +full:i2c +full:- +full:hdmi
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>
10 #include <linux/hdmi.h>
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.
46 * the recommended N values specified in the Audio chapter of the HDMI
93 /* For 297 MHz+ HDMI spec have some other rule for setting N */
102 * These are the CTS values as recommended in the Audio chapter of the HDMI
138 struct dw_hdmi_qp_i2c *i2c; member
150 static void dw_hdmi_qp_write(struct dw_hdmi_qp *hdmi, unsigned int val, in dw_hdmi_qp_write() argument
153 regmap_write(hdmi->regm, offset, val); in dw_hdmi_qp_write()
156 static unsigned int dw_hdmi_qp_read(struct dw_hdmi_qp *hdmi, int offset) in dw_hdmi_qp_read() argument
160 regmap_read(hdmi->regm, offset, &val); in dw_hdmi_qp_read()
165 static void dw_hdmi_qp_mod(struct dw_hdmi_qp *hdmi, unsigned int data, in dw_hdmi_qp_mod() argument
168 regmap_update_bits(hdmi->regm, reg, mask, data); in dw_hdmi_qp_mod()
176 static void dw_hdmi_qp_set_cts_n(struct dw_hdmi_qp *hdmi, unsigned int cts, in dw_hdmi_qp_set_cts_n() argument
180 dw_hdmi_qp_mod(hdmi, n, AUDPKT_ACR_N_VALUE, AUDPKT_ACR_CONTROL0); in dw_hdmi_qp_set_cts_n()
184 dw_hdmi_qp_mod(hdmi, AUDPKT_ACR_CTS_OVR_EN, AUDPKT_ACR_CTS_OVR_EN_MSK, in dw_hdmi_qp_set_cts_n()
187 dw_hdmi_qp_mod(hdmi, 0, AUDPKT_ACR_CTS_OVR_EN_MSK, in dw_hdmi_qp_set_cts_n()
190 dw_hdmi_qp_mod(hdmi, AUDPKT_ACR_CTS_OVR_VAL(cts), AUDPKT_ACR_CTS_OVR_VAL_MSK, in dw_hdmi_qp_set_cts_n()
194 static int dw_hdmi_qp_match_tmds_n_table(struct dw_hdmi_qp *hdmi, in dw_hdmi_qp_match_tmds_n_table() argument
209 return -ENOENT; in dw_hdmi_qp_match_tmds_n_table()
213 return tmds_n->n_32k; in dw_hdmi_qp_match_tmds_n_table()
217 return (freq / 44100) * tmds_n->n_44k1; in dw_hdmi_qp_match_tmds_n_table()
221 return (freq / 48000) * tmds_n->n_48k; in dw_hdmi_qp_match_tmds_n_table()
223 return -ENOENT; in dw_hdmi_qp_match_tmds_n_table()
235 static unsigned int dw_hdmi_qp_compute_n(struct dw_hdmi_qp *hdmi, in dw_hdmi_qp_compute_n() argument
255 (diff == best_diff && abs(n - ideal_n) < best_n_distance)) { in dw_hdmi_qp_compute_n()
258 best_n_distance = abs(best_n - ideal_n); in dw_hdmi_qp_compute_n()
265 if (best_diff == 0 && (abs(n - ideal_n) > best_n_distance)) in dw_hdmi_qp_compute_n()
272 static unsigned int dw_hdmi_qp_find_n(struct dw_hdmi_qp *hdmi, unsigned long pixel_clk, in dw_hdmi_qp_find_n() argument
275 int n = dw_hdmi_qp_match_tmds_n_table(hdmi, pixel_clk, sample_rate); in dw_hdmi_qp_find_n()
280 dev_warn(hdmi->dev, "Rate %lu missing; compute N dynamically\n", in dw_hdmi_qp_find_n()
283 return dw_hdmi_qp_compute_n(hdmi, pixel_clk, sample_rate); in dw_hdmi_qp_find_n()
286 static unsigned int dw_hdmi_qp_find_cts(struct dw_hdmi_qp *hdmi, unsigned long pixel_clk, in dw_hdmi_qp_find_cts() argument
304 return tmds_cts->cts_32k; in dw_hdmi_qp_find_cts()
308 return tmds_cts->cts_44k1; in dw_hdmi_qp_find_cts()
312 return tmds_cts->cts_48k; in dw_hdmi_qp_find_cts()
314 return -ENOENT; in dw_hdmi_qp_find_cts()
318 static void dw_hdmi_qp_set_audio_interface(struct dw_hdmi_qp *hdmi, in dw_hdmi_qp_set_audio_interface() argument
325 dw_hdmi_qp_write(hdmi, AVP_DATAPATH_PACKET_AUDIO_SWINIT_P, GLOBAL_SWRESET_REQUEST); in dw_hdmi_qp_set_audio_interface()
328 dw_hdmi_qp_mod(hdmi, 0, in dw_hdmi_qp_set_audio_interface()
333 dw_hdmi_qp_write(hdmi, AUDIO_FIFO_CLR_P, AUDIO_INTERFACE_CONTROL0); in dw_hdmi_qp_set_audio_interface()
336 dw_hdmi_qp_mod(hdmi, AUD_IF_I2S, AUD_IF_SEL_MSK, AUDIO_INTERFACE_CONFIG0); in dw_hdmi_qp_set_audio_interface()
339 switch (hparms->channels) { in dw_hdmi_qp_set_audio_interface()
354 dw_hdmi_qp_mod(hdmi, conf0, I2S_LINES_EN_MSK, AUDIO_INTERFACE_CONFIG0); in dw_hdmi_qp_set_audio_interface()
357 * Enable bpcuv generated internally for L-PCM, or received in dw_hdmi_qp_set_audio_interface()
360 switch (fmt->bit_fmt) { in dw_hdmi_qp_set_audio_interface()
362 conf0 = (hparms->channels == 8) ? AUD_HBR : AUD_ASP; in dw_hdmi_qp_set_audio_interface()
370 dw_hdmi_qp_mod(hdmi, conf0, I2S_BPCUV_RCV_MSK | AUD_FORMAT_MSK, in dw_hdmi_qp_set_audio_interface()
374 dw_hdmi_qp_mod(hdmi, AUD_FIFO_INIT_ON_OVF_EN, AUD_FIFO_INIT_ON_OVF_MSK, in dw_hdmi_qp_set_audio_interface()
386 static void dw_hdmi_qp_set_channel_status(struct dw_hdmi_qp *hdmi, in dw_hdmi_qp_set_channel_status() argument
399 * CS5: | | CGMS-A | in dw_hdmi_qp_set_channel_status()
411 if ((dw_hdmi_qp_read(hdmi, AUDIO_INTERFACE_CONFIG0) & GENMASK(25, 24)) == AUD_HBR) { in dw_hdmi_qp_set_channel_status()
417 dw_hdmi_qp_write(hdmi, channel_status[0] | (channel_status[1] << 8), in dw_hdmi_qp_set_channel_status()
420 regmap_bulk_write(hdmi->regm, AUDPKT_CHSTATUS_OVR1, &channel_status[3], 1); in dw_hdmi_qp_set_channel_status()
423 dw_hdmi_qp_mod(hdmi, 0, in dw_hdmi_qp_set_channel_status()
427 dw_hdmi_qp_mod(hdmi, AUDPKT_PBIT_FORCE_EN | AUDPKT_CHSTATUS_OVR_EN, in dw_hdmi_qp_set_channel_status()
432 static void dw_hdmi_qp_set_sample_rate(struct dw_hdmi_qp *hdmi, unsigned long long tmds_char_rate, in dw_hdmi_qp_set_sample_rate() argument
437 n = dw_hdmi_qp_find_n(hdmi, tmds_char_rate, sample_rate); in dw_hdmi_qp_set_sample_rate()
438 cts = dw_hdmi_qp_find_cts(hdmi, tmds_char_rate, sample_rate); in dw_hdmi_qp_set_sample_rate()
440 dw_hdmi_qp_set_cts_n(hdmi, cts, n); in dw_hdmi_qp_set_sample_rate()
446 struct dw_hdmi_qp *hdmi = dw_hdmi_qp_from_bridge(bridge); in dw_hdmi_qp_audio_enable() local
448 if (hdmi->tmds_char_rate) in dw_hdmi_qp_audio_enable()
449 dw_hdmi_qp_mod(hdmi, 0, AVP_DATAPATH_PACKET_AUDIO_SWDISABLE, GLOBAL_SWDISABLE); in dw_hdmi_qp_audio_enable()
459 struct dw_hdmi_qp *hdmi = dw_hdmi_qp_from_bridge(bridge); in dw_hdmi_qp_audio_prepare() local
462 if (!hdmi->tmds_char_rate) in dw_hdmi_qp_audio_prepare()
463 return -ENODEV; in dw_hdmi_qp_audio_prepare()
465 if (fmt->bit_clk_provider | fmt->frame_clk_provider) { in dw_hdmi_qp_audio_prepare()
466 dev_err(hdmi->dev, "unsupported clock settings\n"); in dw_hdmi_qp_audio_prepare()
467 return -EINVAL; in dw_hdmi_qp_audio_prepare()
470 if (fmt->bit_fmt == SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE) in dw_hdmi_qp_audio_prepare()
473 dw_hdmi_qp_set_audio_interface(hdmi, fmt, hparms); in dw_hdmi_qp_audio_prepare()
474 dw_hdmi_qp_set_sample_rate(hdmi, hdmi->tmds_char_rate, hparms->sample_rate); in dw_hdmi_qp_audio_prepare()
475 dw_hdmi_qp_set_channel_status(hdmi, hparms->iec.status, ref2stream); in dw_hdmi_qp_audio_prepare()
476 drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector, &hparms->cea); in dw_hdmi_qp_audio_prepare()
481 static void dw_hdmi_qp_audio_disable_regs(struct dw_hdmi_qp *hdmi) in dw_hdmi_qp_audio_disable_regs() argument
490 dw_hdmi_qp_mod(hdmi, I2S_BPCUV_RCV_DIS, I2S_BPCUV_RCV_MSK, in dw_hdmi_qp_audio_disable_regs()
492 dw_hdmi_qp_mod(hdmi, AUDPKT_PBIT_FORCE_EN | AUDPKT_CHSTATUS_OVR_EN, in dw_hdmi_qp_audio_disable_regs()
496 dw_hdmi_qp_mod(hdmi, AVP_DATAPATH_PACKET_AUDIO_SWDISABLE, in dw_hdmi_qp_audio_disable_regs()
503 struct dw_hdmi_qp *hdmi = dw_hdmi_qp_from_bridge(bridge); in dw_hdmi_qp_audio_disable() local
507 if (hdmi->tmds_char_rate) in dw_hdmi_qp_audio_disable()
508 dw_hdmi_qp_audio_disable_regs(hdmi); in dw_hdmi_qp_audio_disable()
511 static int dw_hdmi_qp_i2c_read(struct dw_hdmi_qp *hdmi, in dw_hdmi_qp_i2c_read() argument
514 struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; in dw_hdmi_qp_i2c_read() local
517 if (!i2c->is_regaddr) { in dw_hdmi_qp_i2c_read()
518 dev_dbg(hdmi->dev, "set read register address to 0\n"); in dw_hdmi_qp_i2c_read()
519 i2c->slave_reg = 0x00; in dw_hdmi_qp_i2c_read()
520 i2c->is_regaddr = true; in dw_hdmi_qp_i2c_read()
523 while (length--) { in dw_hdmi_qp_i2c_read()
524 reinit_completion(&i2c->cmp); in dw_hdmi_qp_i2c_read()
526 dw_hdmi_qp_mod(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR, in dw_hdmi_qp_i2c_read()
529 if (i2c->is_segment) in dw_hdmi_qp_i2c_read()
530 dw_hdmi_qp_mod(hdmi, I2CM_EXT_READ, I2CM_WR_MASK, in dw_hdmi_qp_i2c_read()
533 dw_hdmi_qp_mod(hdmi, I2CM_FM_READ, I2CM_WR_MASK, in dw_hdmi_qp_i2c_read()
536 stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); in dw_hdmi_qp_i2c_read()
538 dev_err(hdmi->dev, "i2c read timed out\n"); in dw_hdmi_qp_i2c_read()
539 dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0); in dw_hdmi_qp_i2c_read()
540 return -EAGAIN; in dw_hdmi_qp_i2c_read()
544 if (i2c->stat & I2CM_NACK_RCVD_IRQ) { in dw_hdmi_qp_i2c_read()
545 dev_err(hdmi->dev, "i2c read error\n"); in dw_hdmi_qp_i2c_read()
546 dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0); in dw_hdmi_qp_i2c_read()
547 return -EIO; in dw_hdmi_qp_i2c_read()
550 *buf++ = dw_hdmi_qp_read(hdmi, I2CM_INTERFACE_RDDATA_0_3) & 0xff; in dw_hdmi_qp_i2c_read()
551 dw_hdmi_qp_mod(hdmi, 0, I2CM_WR_MASK, I2CM_INTERFACE_CONTROL0); in dw_hdmi_qp_i2c_read()
554 i2c->is_segment = false; in dw_hdmi_qp_i2c_read()
559 static int dw_hdmi_qp_i2c_write(struct dw_hdmi_qp *hdmi, in dw_hdmi_qp_i2c_write() argument
562 struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; in dw_hdmi_qp_i2c_write() local
565 if (!i2c->is_regaddr) { in dw_hdmi_qp_i2c_write()
567 i2c->slave_reg = buf[0]; in dw_hdmi_qp_i2c_write()
568 length--; in dw_hdmi_qp_i2c_write()
570 i2c->is_regaddr = true; in dw_hdmi_qp_i2c_write()
573 while (length--) { in dw_hdmi_qp_i2c_write()
574 reinit_completion(&i2c->cmp); in dw_hdmi_qp_i2c_write()
576 dw_hdmi_qp_write(hdmi, *buf++, I2CM_INTERFACE_WRDATA_0_3); in dw_hdmi_qp_i2c_write()
577 dw_hdmi_qp_mod(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR, in dw_hdmi_qp_i2c_write()
579 dw_hdmi_qp_mod(hdmi, I2CM_FM_WRITE, I2CM_WR_MASK, in dw_hdmi_qp_i2c_write()
582 stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); in dw_hdmi_qp_i2c_write()
584 dev_err(hdmi->dev, "i2c write time out!\n"); in dw_hdmi_qp_i2c_write()
585 dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0); in dw_hdmi_qp_i2c_write()
586 return -EAGAIN; in dw_hdmi_qp_i2c_write()
590 if (i2c->stat & I2CM_NACK_RCVD_IRQ) { in dw_hdmi_qp_i2c_write()
591 dev_err(hdmi->dev, "i2c write nack!\n"); in dw_hdmi_qp_i2c_write()
592 dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0); in dw_hdmi_qp_i2c_write()
593 return -EIO; in dw_hdmi_qp_i2c_write()
596 dw_hdmi_qp_mod(hdmi, 0, I2CM_WR_MASK, I2CM_INTERFACE_CONTROL0); in dw_hdmi_qp_i2c_write()
605 struct dw_hdmi_qp *hdmi = i2c_get_adapdata(adap); in dw_hdmi_qp_i2c_xfer() local
606 struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; in dw_hdmi_qp_i2c_xfer() local
612 * The internal I2C controller does not support the multi-byte in dw_hdmi_qp_i2c_xfer()
615 * unsupported I2C operations. in dw_hdmi_qp_i2c_xfer()
617 return -EOPNOTSUPP; in dw_hdmi_qp_i2c_xfer()
621 dev_err(hdmi->dev, in dw_hdmi_qp_i2c_xfer()
624 return -EOPNOTSUPP; in dw_hdmi_qp_i2c_xfer()
628 guard(mutex)(&i2c->lock); in dw_hdmi_qp_i2c_xfer()
631 dw_hdmi_qp_mod(hdmi, I2CM_NACK_RCVD_MASK_N | I2CM_OP_DONE_MASK_N, in dw_hdmi_qp_i2c_xfer()
635 /* Set slave device address taken from the first I2C message */ in dw_hdmi_qp_i2c_xfer()
639 dw_hdmi_qp_mod(hdmi, addr << 5, I2CM_SLVADDR, I2CM_INTERFACE_CONTROL0); in dw_hdmi_qp_i2c_xfer()
642 i2c->is_regaddr = false; in dw_hdmi_qp_i2c_xfer()
644 /* Set segment pointer for I2C extended read mode operation */ in dw_hdmi_qp_i2c_xfer()
645 i2c->is_segment = false; in dw_hdmi_qp_i2c_xfer()
649 i2c->is_segment = true; in dw_hdmi_qp_i2c_xfer()
650 dw_hdmi_qp_mod(hdmi, DDC_SEGMENT_ADDR, I2CM_SEG_ADDR, in dw_hdmi_qp_i2c_xfer()
652 dw_hdmi_qp_mod(hdmi, *msgs[i].buf << 7, I2CM_SEG_PTR, in dw_hdmi_qp_i2c_xfer()
656 ret = dw_hdmi_qp_i2c_read(hdmi, msgs[i].buf, in dw_hdmi_qp_i2c_xfer()
659 ret = dw_hdmi_qp_i2c_write(hdmi, msgs[i].buf, in dw_hdmi_qp_i2c_xfer()
670 dw_hdmi_qp_mod(hdmi, 0, I2CM_OP_DONE_MASK_N | I2CM_NACK_RCVD_MASK_N, in dw_hdmi_qp_i2c_xfer()
686 static struct i2c_adapter *dw_hdmi_qp_i2c_adapter(struct dw_hdmi_qp *hdmi) in dw_hdmi_qp_i2c_adapter() argument
688 struct dw_hdmi_qp_i2c *i2c; in dw_hdmi_qp_i2c_adapter() local
692 i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL); in dw_hdmi_qp_i2c_adapter()
693 if (!i2c) in dw_hdmi_qp_i2c_adapter()
694 return ERR_PTR(-ENOMEM); in dw_hdmi_qp_i2c_adapter()
696 mutex_init(&i2c->lock); in dw_hdmi_qp_i2c_adapter()
697 init_completion(&i2c->cmp); in dw_hdmi_qp_i2c_adapter()
699 adap = &i2c->adap; in dw_hdmi_qp_i2c_adapter()
700 adap->owner = THIS_MODULE; in dw_hdmi_qp_i2c_adapter()
701 adap->dev.parent = hdmi->dev; in dw_hdmi_qp_i2c_adapter()
702 adap->algo = &dw_hdmi_qp_algorithm; in dw_hdmi_qp_i2c_adapter()
703 strscpy(adap->name, "DesignWare HDMI QP", sizeof(adap->name)); in dw_hdmi_qp_i2c_adapter()
705 i2c_set_adapdata(adap, hdmi); in dw_hdmi_qp_i2c_adapter()
707 ret = devm_i2c_add_adapter(hdmi->dev, adap); in dw_hdmi_qp_i2c_adapter()
709 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name); in dw_hdmi_qp_i2c_adapter()
710 devm_kfree(hdmi->dev, i2c); in dw_hdmi_qp_i2c_adapter()
714 hdmi->i2c = i2c; in dw_hdmi_qp_i2c_adapter()
715 dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name); in dw_hdmi_qp_i2c_adapter()
720 static int dw_hdmi_qp_config_avi_infoframe(struct dw_hdmi_qp *hdmi, in dw_hdmi_qp_config_avi_infoframe() argument
726 dev_err(hdmi->dev, "failed to configure avi infoframe\n"); in dw_hdmi_qp_config_avi_infoframe()
727 return -EINVAL; in dw_hdmi_qp_config_avi_infoframe()
731 * DW HDMI QP IP uses a different byte format from standard AVI info in dw_hdmi_qp_config_avi_infoframe()
735 dw_hdmi_qp_write(hdmi, val, PKT_AVI_CONTENTS0); in dw_hdmi_qp_config_avi_infoframe()
746 dw_hdmi_qp_write(hdmi, val, PKT_AVI_CONTENTS1 + i * 4); in dw_hdmi_qp_config_avi_infoframe()
749 dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_AVI_FIELDRATE, PKTSCHED_PKT_CONFIG1); in dw_hdmi_qp_config_avi_infoframe()
751 dw_hdmi_qp_mod(hdmi, PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN, in dw_hdmi_qp_config_avi_infoframe()
757 static int dw_hdmi_qp_config_drm_infoframe(struct dw_hdmi_qp *hdmi, in dw_hdmi_qp_config_drm_infoframe() argument
763 dev_err(hdmi->dev, "failed to configure drm infoframe\n"); in dw_hdmi_qp_config_drm_infoframe()
764 return -EINVAL; in dw_hdmi_qp_config_drm_infoframe()
767 dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_TX_EN, PKTSCHED_PKT_EN); in dw_hdmi_qp_config_drm_infoframe()
770 dw_hdmi_qp_write(hdmi, val, PKT_DRMI_CONTENTS0); in dw_hdmi_qp_config_drm_infoframe()
778 dw_hdmi_qp_write(hdmi, val, in dw_hdmi_qp_config_drm_infoframe()
782 dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_FIELDRATE, PKTSCHED_PKT_CONFIG1); in dw_hdmi_qp_config_drm_infoframe()
783 dw_hdmi_qp_mod(hdmi, PKTSCHED_DRMI_TX_EN, PKTSCHED_DRMI_TX_EN, in dw_hdmi_qp_config_drm_infoframe()
796 static int dw_hdmi_qp_config_audio_infoframe(struct dw_hdmi_qp *hdmi, in dw_hdmi_qp_config_audio_infoframe() argument
812 * AUDI_CONTENTS0 default value defined by HDMI specification, in dw_hdmi_qp_config_audio_infoframe()
818 regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS0, &header_bytes, 1); in dw_hdmi_qp_config_audio_infoframe()
819 regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS1, &buffer[3], 1); in dw_hdmi_qp_config_audio_infoframe()
820 regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS2, &buffer[4], 1); in dw_hdmi_qp_config_audio_infoframe()
823 dw_hdmi_qp_mod(hdmi, in dw_hdmi_qp_config_audio_infoframe()
829 dw_hdmi_qp_mod(hdmi, PKTSCHED_AUDS_TX_EN, PKTSCHED_AUDS_TX_EN, PKTSCHED_PKT_EN); in dw_hdmi_qp_config_audio_infoframe()
837 struct dw_hdmi_qp *hdmi = bridge->driver_private; in dw_hdmi_qp_bridge_atomic_enable() local
842 connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); in dw_hdmi_qp_bridge_atomic_enable()
850 if (connector->display_info.is_hdmi) { in dw_hdmi_qp_bridge_atomic_enable()
851 dev_dbg(hdmi->dev, "%s mode=HDMI rate=%llu\n", in dw_hdmi_qp_bridge_atomic_enable()
852 __func__, conn_state->hdmi.tmds_char_rate); in dw_hdmi_qp_bridge_atomic_enable()
854 hdmi->tmds_char_rate = conn_state->hdmi.tmds_char_rate; in dw_hdmi_qp_bridge_atomic_enable()
856 dev_dbg(hdmi->dev, "%s mode=DVI\n", __func__); in dw_hdmi_qp_bridge_atomic_enable()
860 hdmi->phy.ops->init(hdmi, hdmi->phy.data); in dw_hdmi_qp_bridge_atomic_enable()
862 dw_hdmi_qp_mod(hdmi, HDCP2_BYPASS, HDCP2_BYPASS, HDCP2LOGIC_CONFIG0); in dw_hdmi_qp_bridge_atomic_enable()
863 dw_hdmi_qp_mod(hdmi, op_mode, OPMODE_DVI, LINK_CONFIG0); in dw_hdmi_qp_bridge_atomic_enable()
871 struct dw_hdmi_qp *hdmi = bridge->driver_private; in dw_hdmi_qp_bridge_atomic_disable() local
873 hdmi->tmds_char_rate = 0; in dw_hdmi_qp_bridge_atomic_disable()
875 hdmi->phy.ops->disable(hdmi, hdmi->phy.data); in dw_hdmi_qp_bridge_atomic_disable()
881 struct dw_hdmi_qp *hdmi = bridge->driver_private; in dw_hdmi_qp_bridge_detect() local
883 return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data); in dw_hdmi_qp_bridge_detect()
890 struct dw_hdmi_qp *hdmi = bridge->driver_private; in dw_hdmi_qp_bridge_edid_read() local
893 drm_edid = drm_edid_read_ddc(connector, bridge->ddc); in dw_hdmi_qp_bridge_edid_read()
895 dev_dbg(hdmi->dev, "failed to get edid\n"); in dw_hdmi_qp_bridge_edid_read()
905 struct dw_hdmi_qp *hdmi = bridge->driver_private; in dw_hdmi_qp_bridge_tmds_char_rate_valid() local
908 dev_dbg(hdmi->dev, "Unsupported TMDS char rate: %lld\n", rate); in dw_hdmi_qp_bridge_tmds_char_rate_valid()
918 struct dw_hdmi_qp *hdmi = bridge->driver_private; in dw_hdmi_qp_bridge_clear_infoframe() local
922 dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN, in dw_hdmi_qp_bridge_clear_infoframe()
927 dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_TX_EN, PKTSCHED_PKT_EN); in dw_hdmi_qp_bridge_clear_infoframe()
931 dw_hdmi_qp_mod(hdmi, 0, in dw_hdmi_qp_bridge_clear_infoframe()
938 dev_dbg(hdmi->dev, "Unsupported infoframe type %x\n", type); in dw_hdmi_qp_bridge_clear_infoframe()
948 struct dw_hdmi_qp *hdmi = bridge->driver_private; in dw_hdmi_qp_bridge_write_infoframe() local
954 return dw_hdmi_qp_config_avi_infoframe(hdmi, buffer, len); in dw_hdmi_qp_bridge_write_infoframe()
957 return dw_hdmi_qp_config_drm_infoframe(hdmi, buffer, len); in dw_hdmi_qp_bridge_write_infoframe()
960 return dw_hdmi_qp_config_audio_infoframe(hdmi, buffer, len); in dw_hdmi_qp_bridge_write_infoframe()
963 dev_dbg(hdmi->dev, "Unsupported infoframe type %x\n", type); in dw_hdmi_qp_bridge_write_infoframe()
986 struct dw_hdmi_qp *hdmi = dev_id; in dw_hdmi_qp_main_hardirq() local
987 struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; in dw_hdmi_qp_main_hardirq() local
990 stat = dw_hdmi_qp_read(hdmi, MAINUNIT_1_INT_STATUS); in dw_hdmi_qp_main_hardirq()
992 i2c->stat = stat & (I2CM_OP_DONE_IRQ | I2CM_READ_REQUEST_IRQ | in dw_hdmi_qp_main_hardirq()
995 if (i2c->stat) { in dw_hdmi_qp_main_hardirq()
996 dw_hdmi_qp_write(hdmi, i2c->stat, MAINUNIT_1_INT_CLEAR); in dw_hdmi_qp_main_hardirq()
997 complete(&i2c->cmp); in dw_hdmi_qp_main_hardirq()
1013 static void dw_hdmi_qp_init_hw(struct dw_hdmi_qp *hdmi) in dw_hdmi_qp_init_hw() argument
1015 dw_hdmi_qp_write(hdmi, 0, MAINUNIT_0_INT_MASK_N); in dw_hdmi_qp_init_hw()
1016 dw_hdmi_qp_write(hdmi, 0, MAINUNIT_1_INT_MASK_N); in dw_hdmi_qp_init_hw()
1017 dw_hdmi_qp_write(hdmi, 428571429, TIMER_BASE_CONFIG0); in dw_hdmi_qp_init_hw()
1020 dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0); in dw_hdmi_qp_init_hw()
1022 dw_hdmi_qp_write(hdmi, 0x085c085c, I2CM_FM_SCL_CONFIG0); in dw_hdmi_qp_init_hw()
1024 dw_hdmi_qp_mod(hdmi, 0, I2CM_FM_EN, I2CM_INTERFACE_CONTROL0); in dw_hdmi_qp_init_hw()
1027 dw_hdmi_qp_write(hdmi, I2CM_OP_DONE_CLEAR | I2CM_NACK_RCVD_CLEAR, in dw_hdmi_qp_init_hw()
1030 if (hdmi->phy.ops->setup_hpd) in dw_hdmi_qp_init_hw()
1031 hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data); in dw_hdmi_qp_init_hw()
1038 struct device *dev = &pdev->dev; in dw_hdmi_qp_bind()
1039 struct dw_hdmi_qp *hdmi; in dw_hdmi_qp_bind() local
1043 if (!plat_data->phy_ops || !plat_data->phy_ops->init || in dw_hdmi_qp_bind()
1044 !plat_data->phy_ops->disable || !plat_data->phy_ops->read_hpd) { in dw_hdmi_qp_bind()
1046 return ERR_PTR(-ENODEV); in dw_hdmi_qp_bind()
1049 hdmi = devm_drm_bridge_alloc(dev, struct dw_hdmi_qp, bridge, in dw_hdmi_qp_bind()
1051 if (IS_ERR(hdmi)) in dw_hdmi_qp_bind()
1052 return ERR_CAST(hdmi); in dw_hdmi_qp_bind()
1054 hdmi->dev = dev; in dw_hdmi_qp_bind()
1060 hdmi->regm = devm_regmap_init_mmio(dev, regs, &dw_hdmi_qp_regmap_config); in dw_hdmi_qp_bind()
1061 if (IS_ERR(hdmi->regm)) { in dw_hdmi_qp_bind()
1063 return ERR_CAST(hdmi->regm); in dw_hdmi_qp_bind()
1066 hdmi->phy.ops = plat_data->phy_ops; in dw_hdmi_qp_bind()
1067 hdmi->phy.data = plat_data->phy_data; in dw_hdmi_qp_bind()
1069 dw_hdmi_qp_init_hw(hdmi); in dw_hdmi_qp_bind()
1071 ret = devm_request_threaded_irq(dev, plat_data->main_irq, in dw_hdmi_qp_bind()
1073 IRQF_SHARED, dev_name(dev), hdmi); in dw_hdmi_qp_bind()
1077 hdmi->bridge.driver_private = hdmi; in dw_hdmi_qp_bind()
1078 hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT | in dw_hdmi_qp_bind()
1083 hdmi->bridge.of_node = pdev->dev.of_node; in dw_hdmi_qp_bind()
1084 hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA; in dw_hdmi_qp_bind()
1085 hdmi->bridge.vendor = "Synopsys"; in dw_hdmi_qp_bind()
1086 hdmi->bridge.product = "DW HDMI QP TX"; in dw_hdmi_qp_bind()
1088 hdmi->bridge.ddc = dw_hdmi_qp_i2c_adapter(hdmi); in dw_hdmi_qp_bind()
1089 if (IS_ERR(hdmi->bridge.ddc)) in dw_hdmi_qp_bind()
1090 return ERR_CAST(hdmi->bridge.ddc); in dw_hdmi_qp_bind()
1092 hdmi->bridge.hdmi_audio_max_i2s_playback_channels = 8; in dw_hdmi_qp_bind()
1093 hdmi->bridge.hdmi_audio_dev = dev; in dw_hdmi_qp_bind()
1094 hdmi->bridge.hdmi_audio_dai_port = 1; in dw_hdmi_qp_bind()
1096 ret = devm_drm_bridge_add(dev, &hdmi->bridge); in dw_hdmi_qp_bind()
1100 ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL, in dw_hdmi_qp_bind()
1105 return hdmi; in dw_hdmi_qp_bind()
1109 void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi) in dw_hdmi_qp_resume() argument
1111 dw_hdmi_qp_init_hw(hdmi); in dw_hdmi_qp_resume()
1115 MODULE_AUTHOR("Algea Cao <algea.cao@rock-chips.com>");
1117 MODULE_DESCRIPTION("DW HDMI QP transmitter library");