Lines Matching +full:mt8173 +full:- +full:hdmi
1 // SPDX-License-Identifier: GPL-2.0-only
7 #include <linux/arm-smccc.h>
10 #include <linux/hdmi.h>
24 #include <sound/hdmi-codec.h>
183 static void mtk_hdmi_hw_vid_black(struct mtk_hdmi *hdmi, bool black)
185 regmap_update_bits(hdmi->regs, VIDEO_SOURCE_SEL,
189 static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable)
194 * MT8173 HDMI hardware has an output control bit to enable/disable HDMI
196 * The ARM trusted firmware provides an API for the HDMI driver to set
197 * this control bit to enable HDMI output in supervisor mode.
199 if (hdmi->conf && hdmi->conf->tz_disabled)
200 regmap_update_bits(hdmi->sys_regmap,
201 hdmi->sys_offset + HDMI_SYS_CFG20,
207 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20,
209 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG1C,
213 static void mtk_hdmi_hw_1p4_version_enable(struct mtk_hdmi *hdmi, bool enable)
215 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20,
219 static void mtk_hdmi_hw_aud_mute(struct mtk_hdmi *hdmi)
221 regmap_set_bits(hdmi->regs, GRL_AUDIO_CFG, AUDIO_ZERO);
224 static void mtk_hdmi_hw_aud_unmute(struct mtk_hdmi *hdmi)
226 regmap_clear_bits(hdmi->regs, GRL_AUDIO_CFG, AUDIO_ZERO);
229 static void mtk_hdmi_hw_reset(struct mtk_hdmi *hdmi)
231 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG1C,
233 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG1C,
235 regmap_clear_bits(hdmi->regs, GRL_CFG3, CFG3_CONTROL_PACKET_DELAY);
236 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG1C,
240 static void mtk_hdmi_hw_enable_notice(struct mtk_hdmi *hdmi, bool enable_notice)
242 regmap_update_bits(hdmi->regs, GRL_CFG2, CFG2_NOTICE_EN,
246 static void mtk_hdmi_hw_write_int_mask(struct mtk_hdmi *hdmi, u32 int_mask)
248 regmap_write(hdmi->regs, GRL_INT_MASK, int_mask);
251 static void mtk_hdmi_hw_enable_dvi_mode(struct mtk_hdmi *hdmi, bool enable)
253 regmap_update_bits(hdmi->regs, GRL_CFG1, CFG1_DVI, enable ? CFG1_DVI : 0);
256 static void mtk_hdmi_hw_send_info_frame(struct mtk_hdmi *hdmi, u8 *buffer,
274 dev_dbg(hdmi->dev,
296 dev_err(hdmi->dev, "Unknown infoframe type %d\n", frame_type);
299 regmap_clear_bits(hdmi->regs, ctrl_reg, ctrl_frame_en);
300 regmap_write(hdmi->regs, GRL_INFOFRM_TYPE, frame_type);
301 regmap_write(hdmi->regs, GRL_INFOFRM_VER, frame_ver);
302 regmap_write(hdmi->regs, GRL_INFOFRM_LNG, frame_len);
304 regmap_write(hdmi->regs, GRL_IFM_PORT, checksum);
306 regmap_write(hdmi->regs, GRL_IFM_PORT, frame_data[i]);
308 regmap_set_bits(hdmi->regs, ctrl_reg, ctrl_frame_en);
311 static void mtk_hdmi_hw_send_aud_packet(struct mtk_hdmi *hdmi, bool enable)
313 regmap_update_bits(hdmi->regs, AUDIO_PACKET_OFF,
317 static void mtk_hdmi_hw_config_sys(struct mtk_hdmi *hdmi)
319 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20,
322 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20,
326 static void mtk_hdmi_hw_set_deep_color_mode(struct mtk_hdmi *hdmi)
328 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20,
333 static void mtk_hdmi_hw_send_av_mute(struct mtk_hdmi *hdmi)
335 regmap_clear_bits(hdmi->regs, GRL_CFG4, CTRL_AVMUTE);
337 regmap_set_bits(hdmi->regs, GRL_CFG4, CTRL_AVMUTE);
340 static void mtk_hdmi_hw_send_av_unmute(struct mtk_hdmi *hdmi)
342 regmap_update_bits(hdmi->regs, GRL_CFG4, CFG4_AV_UNMUTE_EN | CFG4_AV_UNMUTE_SET,
345 regmap_update_bits(hdmi->regs, GRL_CFG4, CFG4_AV_UNMUTE_EN | CFG4_AV_UNMUTE_SET,
349 static void mtk_hdmi_hw_ncts_enable(struct mtk_hdmi *hdmi, bool on)
351 regmap_update_bits(hdmi->regs, GRL_CTS_CTRL, CTS_CTRL_SOFT,
355 static void mtk_hdmi_hw_ncts_auto_write_enable(struct mtk_hdmi *hdmi,
358 regmap_update_bits(hdmi->regs, GRL_CTS_CTRL, NCTS_WRI_ANYTIME,
362 static void mtk_hdmi_hw_msic_setting(struct mtk_hdmi *hdmi,
365 regmap_clear_bits(hdmi->regs, GRL_CFG4, CFG4_MHL_MODE);
367 if (mode->flags & DRM_MODE_FLAG_INTERLACE &&
368 mode->clock == 74250 &&
369 mode->vdisplay == 1080)
370 regmap_clear_bits(hdmi->regs, GRL_CFG2, CFG2_MHL_DE_SEL);
372 regmap_set_bits(hdmi->regs, GRL_CFG2, CFG2_MHL_DE_SEL);
375 static void mtk_hdmi_hw_aud_set_channel_swap(struct mtk_hdmi *hdmi,
400 regmap_update_bits(hdmi->regs, GRL_CH_SWAP, 0xff, swap_bit);
403 static void mtk_hdmi_hw_aud_set_bit_num(struct mtk_hdmi *hdmi,
421 regmap_update_bits(hdmi->regs, GRL_AOUT_CFG, AOUT_BNUM_SEL_MASK, val);
424 static void mtk_hdmi_hw_aud_set_i2s_fmt(struct mtk_hdmi *hdmi,
429 regmap_read(hdmi->regs, GRL_CFG0, &val);
453 regmap_write(hdmi->regs, GRL_CFG0, val);
456 static void mtk_hdmi_hw_audio_config(struct mtk_hdmi *hdmi, bool dst)
462 regmap_clear_bits(hdmi->regs, GRL_AOUT_CFG, HIGH_BIT_RATE_PACKET_ALIGN);
469 regmap_update_bits(hdmi->regs, GRL_AUDIO_CFG, mask, val);
472 static void mtk_hdmi_hw_aud_set_i2s_chan_num(struct mtk_hdmi *hdmi,
510 regmap_write(hdmi->regs, GRL_CH_SW0, ch_switch & 0xff);
511 regmap_write(hdmi->regs, GRL_CH_SW1, (ch_switch >> 8) & 0xff);
512 regmap_write(hdmi->regs, GRL_CH_SW2, (ch_switch >> 16) & 0xff);
513 regmap_write(hdmi->regs, GRL_I2S_UV, i2s_uv);
516 static void mtk_hdmi_hw_aud_set_input_type(struct mtk_hdmi *hdmi,
521 regmap_read(hdmi->regs, GRL_CFG1, &val);
529 regmap_write(hdmi->regs, GRL_CFG1, val);
532 static void mtk_hdmi_hw_aud_set_channel_status(struct mtk_hdmi *hdmi,
538 regmap_write(hdmi->regs, GRL_I2S_C_STA0 + i * 4, channel_status[i]);
539 regmap_write(hdmi->regs, GRL_L_STATUS_0 + i * 4, channel_status[i]);
540 regmap_write(hdmi->regs, GRL_R_STATUS_0 + i * 4, channel_status[i]);
543 regmap_write(hdmi->regs, GRL_L_STATUS_0 + i * 4, 0);
544 regmap_write(hdmi->regs, GRL_R_STATUS_0 + i * 4, 0);
548 static void mtk_hdmi_hw_aud_src_reenable(struct mtk_hdmi *hdmi)
552 regmap_read(hdmi->regs, GRL_MIX_CTRL, &val);
555 regmap_write(hdmi->regs, GRL_MIX_CTRL, val);
558 regmap_write(hdmi->regs, GRL_MIX_CTRL, val);
562 static void mtk_hdmi_hw_aud_src_disable(struct mtk_hdmi *hdmi)
566 regmap_read(hdmi->regs, GRL_MIX_CTRL, &val);
568 regmap_write(hdmi->regs, GRL_MIX_CTRL, val);
569 regmap_write(hdmi->regs, GRL_SHIFT_L1, 0x00);
572 static void mtk_hdmi_hw_aud_set_mclk(struct mtk_hdmi *hdmi,
577 regmap_read(hdmi->regs, GRL_CFG5, &val);
600 regmap_write(hdmi->regs, GRL_CFG5, val);
608 /* Recommended N values from HDMI specification, tables 7-1 to 7-3 */
620 * hdmi_recommended_n() - Return N value recommended by HDMI specification
629 for (i = 0; i < ARRAY_SIZE(hdmi_rec_n_table) - 1; i++) {
637 return recommended->n[0];
639 return recommended->n[1];
641 return recommended->n[2];
643 return recommended->n[1] * 2;
645 return recommended->n[2] * 2;
647 return recommended->n[1] * 4;
649 return recommended->n[2] * 4;
685 static void do_hdmi_hw_aud_set_ncts(struct mtk_hdmi *hdmi, unsigned int n,
691 regmap_write(hdmi->regs, GRL_NCTS, 0);
692 regmap_write(hdmi->regs, GRL_NCTS, 0);
693 regmap_write(hdmi->regs, GRL_NCTS, 0);
706 regmap_write(hdmi->regs, GRL_NCTS, val[i]);
709 static void mtk_hdmi_hw_aud_set_ncts(struct mtk_hdmi *hdmi,
717 dev_dbg(hdmi->dev, "%s: sample_rate=%u, clock=%d, cts=%u, n=%u\n",
720 regmap_update_bits(hdmi->regs, DUMMY_304, AUDIO_I2S_NCTS_SEL, AUDIO_I2S_NCTS_SEL_64);
721 do_hdmi_hw_aud_set_ncts(hdmi, n, cts);
794 static int mtk_hdmi_video_change_vpll(struct mtk_hdmi *hdmi, u32 clock)
800 ret = clk_set_rate(hdmi->clk[MTK_HDMI_CLK_HDMI_PLL], clock);
802 dev_err(hdmi->dev, "Failed to set PLL to %u Hz: %d\n", clock,
807 rate = clk_get_rate(hdmi->clk[MTK_HDMI_CLK_HDMI_PLL]);
810 dev_warn(hdmi->dev, "Want PLL %u Hz, got %lu Hz\n", clock,
813 dev_dbg(hdmi->dev, "Want PLL %u Hz, got %lu Hz\n", clock, rate);
815 mtk_hdmi_hw_config_sys(hdmi);
816 mtk_hdmi_hw_set_deep_color_mode(hdmi);
820 static void mtk_hdmi_video_set_display_mode(struct mtk_hdmi *hdmi,
823 mtk_hdmi_hw_reset(hdmi);
824 mtk_hdmi_hw_enable_notice(hdmi, true);
825 mtk_hdmi_hw_write_int_mask(hdmi, 0xff);
826 mtk_hdmi_hw_enable_dvi_mode(hdmi, hdmi->dvi_mode);
827 mtk_hdmi_hw_ncts_auto_write_enable(hdmi, true);
829 mtk_hdmi_hw_msic_setting(hdmi, mode);
833 static void mtk_hdmi_aud_set_input(struct mtk_hdmi *hdmi)
839 mtk_hdmi_hw_aud_set_channel_swap(hdmi, HDMI_AUD_SWAP_LFE_CC);
840 regmap_set_bits(hdmi->regs, GRL_MIX_CTRL, MIX_CTRL_FLAT);
842 if (hdmi->aud_param.aud_input_type == HDMI_AUD_INPUT_SPDIF &&
843 hdmi->aud_param.aud_codec == HDMI_AUDIO_CODING_TYPE_DST) {
844 mtk_hdmi_hw_aud_set_bit_num(hdmi, HDMI_AUDIO_SAMPLE_SIZE_24);
845 } else if (hdmi->aud_param.aud_i2s_fmt == HDMI_I2S_MODE_LJT_24BIT) {
846 hdmi->aud_param.aud_i2s_fmt = HDMI_I2S_MODE_LJT_16BIT;
849 mtk_hdmi_hw_aud_set_i2s_fmt(hdmi, hdmi->aud_param.aud_i2s_fmt);
850 mtk_hdmi_hw_aud_set_bit_num(hdmi, HDMI_AUDIO_SAMPLE_SIZE_24);
852 dst = ((hdmi->aud_param.aud_input_type == HDMI_AUD_INPUT_SPDIF) &&
853 (hdmi->aud_param.aud_codec == HDMI_AUDIO_CODING_TYPE_DST));
854 mtk_hdmi_hw_audio_config(hdmi, dst);
856 if (hdmi->aud_param.aud_input_type == HDMI_AUD_INPUT_SPDIF)
859 chan_type = hdmi->aud_param.aud_input_chan_type;
861 mtk_hdmi_hw_aud_set_i2s_chan_num(hdmi, chan_type, chan_count);
862 mtk_hdmi_hw_aud_set_input_type(hdmi, hdmi->aud_param.aud_input_type);
865 static int mtk_hdmi_aud_set_src(struct mtk_hdmi *hdmi,
868 unsigned int sample_rate = hdmi->aud_param.codec_params.sample_rate;
870 mtk_hdmi_hw_ncts_enable(hdmi, false);
871 mtk_hdmi_hw_aud_src_disable(hdmi);
872 regmap_clear_bits(hdmi->regs, GRL_CFG2, CFG2_ACLK_INV);
874 if (hdmi->aud_param.aud_input_type == HDMI_AUD_INPUT_I2S) {
883 return -EINVAL;
885 mtk_hdmi_hw_aud_set_mclk(hdmi, hdmi->aud_param.aud_mclk);
893 return -EINVAL;
895 mtk_hdmi_hw_aud_set_mclk(hdmi, HDMI_AUD_MCLK_128FS);
898 mtk_hdmi_hw_aud_set_ncts(hdmi, sample_rate, display_mode->clock);
900 mtk_hdmi_hw_aud_src_reenable(hdmi);
904 static int mtk_hdmi_aud_output_config(struct mtk_hdmi *hdmi,
907 mtk_hdmi_hw_aud_mute(hdmi);
908 mtk_hdmi_hw_send_aud_packet(hdmi, false);
910 mtk_hdmi_aud_set_input(hdmi);
911 mtk_hdmi_aud_set_src(hdmi, display_mode);
912 mtk_hdmi_hw_aud_set_channel_status(hdmi,
913 hdmi->aud_param.codec_params.iec.status);
917 mtk_hdmi_hw_ncts_enable(hdmi, true);
918 mtk_hdmi_hw_send_aud_packet(hdmi, true);
919 mtk_hdmi_hw_aud_unmute(hdmi);
923 static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi,
931 hdmi->curr_conn, mode);
933 dev_err(hdmi->dev,
940 dev_err(hdmi->dev, "Failed to pack AVI infoframe: %zd\n", err);
944 mtk_hdmi_hw_send_info_frame(hdmi, buffer, sizeof(buffer));
948 static int mtk_hdmi_setup_spd_infoframe(struct mtk_hdmi *hdmi)
950 struct drm_bridge *bridge = &hdmi->bridge;
955 err = hdmi_spd_infoframe_init(&frame, bridge->vendor, bridge->product);
957 dev_err(hdmi->dev, "Failed to initialize SPD infoframe: %zd\n",
964 dev_err(hdmi->dev, "Failed to pack SDP infoframe: %zd\n", err);
968 mtk_hdmi_hw_send_info_frame(hdmi, buffer, sizeof(buffer));
972 static int mtk_hdmi_setup_audio_infoframe(struct mtk_hdmi *hdmi)
980 dev_err(hdmi->dev, "Failed to setup audio infoframe: %zd\n",
989 hdmi->aud_param.aud_input_chan_type);
993 dev_err(hdmi->dev, "Failed to pack audio infoframe: %zd\n",
998 mtk_hdmi_hw_send_info_frame(hdmi, buffer, sizeof(buffer));
1002 static int mtk_hdmi_setup_vendor_specific_infoframe(struct mtk_hdmi *hdmi,
1010 hdmi->curr_conn, mode);
1012 dev_err(hdmi->dev,
1019 dev_err(hdmi->dev, "Failed to pack vendor infoframe: %zd\n",
1024 mtk_hdmi_hw_send_info_frame(hdmi, buffer, sizeof(buffer));
1028 static void mtk_hdmi_audio_enable(struct mtk_hdmi *hdmi)
1030 mtk_hdmi_hw_send_aud_packet(hdmi, true);
1031 hdmi->audio_enable = true;
1034 static void mtk_hdmi_audio_disable(struct mtk_hdmi *hdmi)
1036 mtk_hdmi_hw_send_aud_packet(hdmi, false);
1037 hdmi->audio_enable = false;
1040 static int mtk_hdmi_output_set_display_mode(struct mtk_hdmi *hdmi,
1045 mtk_hdmi_hw_vid_black(hdmi, true);
1046 mtk_hdmi_hw_aud_mute(hdmi);
1047 mtk_hdmi_hw_send_av_mute(hdmi);
1048 phy_power_off(hdmi->phy);
1050 ret = mtk_hdmi_video_change_vpll(hdmi,
1051 mode->clock * 1000);
1053 dev_err(hdmi->dev, "Failed to set vpll: %d\n", ret);
1056 mtk_hdmi_video_set_display_mode(hdmi, mode);
1058 phy_power_on(hdmi->phy);
1059 mtk_hdmi_aud_output_config(hdmi, mode);
1061 mtk_hdmi_hw_vid_black(hdmi, false);
1062 mtk_hdmi_hw_aud_unmute(hdmi);
1063 mtk_hdmi_hw_send_av_unmute(hdmi);
1075 static int mtk_hdmi_get_all_clk(struct mtk_hdmi *hdmi,
1081 hdmi->clk[i] = of_clk_get_by_name(np,
1083 if (IS_ERR(hdmi->clk[i]))
1084 return PTR_ERR(hdmi->clk[i]);
1089 static int mtk_hdmi_clk_enable_audio(struct mtk_hdmi *hdmi)
1093 ret = clk_prepare_enable(hdmi->clk[MTK_HDMI_CLK_AUD_BCLK]);
1097 ret = clk_prepare_enable(hdmi->clk[MTK_HDMI_CLK_AUD_SPDIF]);
1099 clk_disable_unprepare(hdmi->clk[MTK_HDMI_CLK_AUD_BCLK]);
1106 static void mtk_hdmi_clk_disable_audio(struct mtk_hdmi *hdmi)
1108 clk_disable_unprepare(hdmi->clk[MTK_HDMI_CLK_AUD_BCLK]);
1109 clk_disable_unprepare(hdmi->clk[MTK_HDMI_CLK_AUD_SPDIF]);
1113 mtk_hdmi_update_plugged_status(struct mtk_hdmi *hdmi)
1117 mutex_lock(&hdmi->update_plugged_status_lock);
1118 connected = mtk_cec_hpd_high(hdmi->cec_dev);
1119 if (hdmi->plugged_cb && hdmi->codec_dev)
1120 hdmi->plugged_cb(hdmi->codec_dev, connected);
1121 mutex_unlock(&hdmi->update_plugged_status_lock);
1127 static enum drm_connector_status mtk_hdmi_detect(struct mtk_hdmi *hdmi)
1129 return mtk_hdmi_update_plugged_status(hdmi);
1137 struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
1139 dev_dbg(hdmi->dev, "xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
1140 mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode),
1141 !!(mode->flags & DRM_MODE_FLAG_INTERLACE), mode->clock * 1000);
1143 if (hdmi->conf) {
1144 if (hdmi->conf->cea_modes_only && !drm_match_cea_mode(mode))
1147 if (hdmi->conf->max_mode_clock &&
1148 mode->clock > hdmi->conf->max_mode_clock)
1152 if (mode->clock < 27000)
1154 if (mode->clock > 297000)
1162 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1164 if (hdmi && hdmi->bridge.encoder && hdmi->bridge.encoder->dev) {
1167 status = mtk_hdmi_detect(hdmi);
1168 drm_helper_hpd_irq_event(hdmi->bridge.encoder->dev);
1169 drm_bridge_hpd_notify(&hdmi->bridge, status);
1180 struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
1182 return mtk_hdmi_detect(hdmi);
1188 struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
1191 if (!hdmi->ddc_adpt)
1193 drm_edid = drm_edid_read_ddc(connector, hdmi->ddc_adpt);
1196 * FIXME: This should use !connector->display_info.has_audio (or
1197 * !connector->display_info.is_hdmi) from a path that has read
1202 hdmi->dvi_mode = !drm_detect_monitor_audio(edid);
1212 struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
1218 return -EINVAL;
1221 if (hdmi->next_bridge) {
1222 ret = drm_bridge_attach(encoder, hdmi->next_bridge,
1228 mtk_cec_set_hpd_event(hdmi->cec_dev, mtk_hdmi_hpd_event, hdmi->dev);
1243 struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
1245 if (!hdmi->enabled)
1248 phy_power_off(hdmi->phy);
1249 clk_disable_unprepare(hdmi->clk[MTK_HDMI_CLK_HDMI_PIXEL]);
1250 clk_disable_unprepare(hdmi->clk[MTK_HDMI_CLK_HDMI_PLL]);
1252 hdmi->curr_conn = NULL;
1254 hdmi->enabled = false;
1260 struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
1262 if (!hdmi->powered)
1265 mtk_hdmi_hw_1p4_version_enable(hdmi, true);
1266 mtk_hdmi_hw_make_reg_writable(hdmi, false);
1268 hdmi->powered = false;
1275 struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
1277 dev_dbg(hdmi->dev, "cur info: name:%s, hdisplay:%d\n",
1278 adjusted_mode->name, adjusted_mode->hdisplay);
1279 dev_dbg(hdmi->dev, "hsync_start:%d,hsync_end:%d, htotal:%d",
1280 adjusted_mode->hsync_start, adjusted_mode->hsync_end,
1281 adjusted_mode->htotal);
1282 dev_dbg(hdmi->dev, "hskew:%d, vdisplay:%d\n",
1283 adjusted_mode->hskew, adjusted_mode->vdisplay);
1284 dev_dbg(hdmi->dev, "vsync_start:%d, vsync_end:%d, vtotal:%d",
1285 adjusted_mode->vsync_start, adjusted_mode->vsync_end,
1286 adjusted_mode->vtotal);
1287 dev_dbg(hdmi->dev, "vscan:%d, flag:%d\n",
1288 adjusted_mode->vscan, adjusted_mode->flags);
1290 drm_mode_copy(&hdmi->mode, adjusted_mode);
1296 struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
1298 mtk_hdmi_hw_make_reg_writable(hdmi, true);
1299 mtk_hdmi_hw_1p4_version_enable(hdmi, true);
1301 hdmi->powered = true;
1304 static void mtk_hdmi_send_infoframe(struct mtk_hdmi *hdmi,
1307 mtk_hdmi_setup_audio_infoframe(hdmi);
1308 mtk_hdmi_setup_avi_infoframe(hdmi, mode);
1309 mtk_hdmi_setup_spd_infoframe(hdmi);
1310 if (mode->flags & DRM_MODE_FLAG_3D_MASK)
1311 mtk_hdmi_setup_vendor_specific_infoframe(hdmi, mode);
1317 struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
1320 hdmi->curr_conn = drm_atomic_get_new_connector_for_encoder(state,
1321 bridge->encoder);
1323 mtk_hdmi_output_set_display_mode(hdmi, &hdmi->mode);
1324 clk_prepare_enable(hdmi->clk[MTK_HDMI_CLK_HDMI_PLL]);
1325 clk_prepare_enable(hdmi->clk[MTK_HDMI_CLK_HDMI_PIXEL]);
1326 phy_power_on(hdmi->phy);
1327 mtk_hdmi_send_infoframe(hdmi, &hdmi->mode);
1329 hdmi->enabled = true;
1348 static int mtk_hdmi_get_cec_dev(struct mtk_hdmi *hdmi, struct device *dev, struct device_node *np)
1354 ret = mtk_hdmi_get_all_clk(hdmi, np);
1358 /* The CEC module handles HDMI hotplug detection */
1359 cec_np = of_get_compatible_child(np->parent, "mediatek,mt8173-cec");
1361 return dev_err_probe(dev, -EINVAL, "Failed to find CEC node\n");
1365 dev_err(hdmi->dev, "Waiting for CEC device %pOF\n",
1368 return -EPROBE_DEFER;
1373 * The mediatek,syscon-hdmi property contains a phandle link to the
1377 hdmi->sys_regmap = syscon_regmap_lookup_by_phandle_args(np, "mediatek,syscon-hdmi",
1378 1, &hdmi->sys_offset);
1379 if (IS_ERR(hdmi->sys_regmap))
1380 return dev_err_probe(dev, PTR_ERR(hdmi->sys_regmap),
1383 hdmi->cec_dev = &cec_pdev->dev;
1387 static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
1390 struct device *dev = &pdev->dev;
1391 struct device_node *np = dev->of_node;
1395 ret = mtk_hdmi_get_all_clk(hdmi, np);
1399 hdmi->regs = device_node_to_regmap(dev->of_node);
1400 if (IS_ERR(hdmi->regs))
1401 return PTR_ERR(hdmi->regs);
1405 return -EINVAL;
1407 if (!of_device_is_compatible(remote, "hdmi-connector")) {
1408 hdmi->next_bridge = of_drm_find_bridge(remote);
1409 if (!hdmi->next_bridge) {
1412 return -EPROBE_DEFER;
1416 i2c_np = of_parse_phandle(remote, "ddc-i2c-bus", 0);
1419 return dev_err_probe(dev, -EINVAL, "No ddc-i2c-bus in connector\n");
1421 hdmi->ddc_adpt = of_find_i2c_adapter_by_node(i2c_np);
1423 if (!hdmi->ddc_adpt)
1424 return dev_err_probe(dev, -EINVAL, "Failed to get ddc i2c adapter by node\n");
1426 ret = mtk_hdmi_get_cec_dev(hdmi, dev, np);
1434 * HDMI audio codec callbacks
1437 static int mtk_hdmi_audio_params(struct mtk_hdmi *hdmi,
1442 unsigned int chan = params->cea.channels;
1444 dev_dbg(hdmi->dev, "%s: %u Hz, %d bit, %d channels\n", __func__,
1445 params->sample_rate, params->sample_width, chan);
1447 if (!hdmi->bridge.encoder)
1448 return -ENODEV;
1464 dev_err(hdmi->dev, "channel[%d] not supported!\n", chan);
1465 return -EINVAL;
1468 switch (params->sample_rate) {
1478 dev_err(hdmi->dev, "rate[%d] not supported!\n",
1479 params->sample_rate);
1480 return -EINVAL;
1483 switch (daifmt->fmt) {
1497 dev_err(hdmi->dev, "%s: Invalid DAI format %d\n", __func__,
1498 daifmt->fmt);
1499 return -EINVAL;
1502 memcpy(&hdmi->aud_param, &aud_params, sizeof(aud_params));
1504 dev_dbg(hdmi->dev, "codec:%d, input:%d, channel:%d, fs:%d\n",
1515 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1517 if (!hdmi->audio_enable) {
1518 dev_err(hdmi->dev, "hdmi audio is in disable state!\n");
1519 return -EINVAL;
1522 mtk_hdmi_audio_params(hdmi, daifmt, params);
1523 mtk_hdmi_aud_output_config(hdmi, &hdmi->mode);
1530 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1532 mtk_hdmi_audio_enable(hdmi);
1539 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1541 mtk_hdmi_audio_disable(hdmi);
1548 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1551 mtk_hdmi_hw_aud_mute(hdmi);
1553 mtk_hdmi_hw_aud_unmute(hdmi);
1560 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1562 if (hdmi->enabled)
1563 memcpy(buf, hdmi->curr_conn->eld, min(sizeof(hdmi->curr_conn->eld), len));
1569 static void mtk_hdmi_audio_set_plugged_cb(struct mtk_hdmi *hdmi, hdmi_codec_plugged_cb fn,
1572 mutex_lock(&hdmi->update_plugged_status_lock);
1573 hdmi->plugged_cb = fn;
1574 hdmi->codec_dev = codec_dev;
1575 mutex_unlock(&hdmi->update_plugged_status_lock);
1582 struct mtk_hdmi *hdmi = data;
1584 mtk_hdmi_audio_set_plugged_cb(hdmi, fn, codec_dev);
1585 mtk_hdmi_update_plugged_status(hdmi);
1606 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1607 struct hdmi_audio_param *aud_param = &hdmi->aud_param;
1612 .data = hdmi,
1617 aud_param->aud_codec = HDMI_AUDIO_CODING_TYPE_PCM;
1618 aud_param->aud_sample_size = HDMI_AUDIO_SAMPLE_SIZE_16;
1619 aud_param->aud_input_type = HDMI_AUD_INPUT_I2S;
1620 aud_param->aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT;
1621 aud_param->aud_mclk = HDMI_AUD_MCLK_128FS;
1622 aud_param->aud_input_chan_type = HDMI_AUD_CHAN_TYPE_2_0;
1624 hdmi->audio_pdev = platform_device_register_data(dev,
1629 if (IS_ERR(hdmi->audio_pdev))
1630 return PTR_ERR(hdmi->audio_pdev);
1633 hdmi->audio_pdev);
1642 struct mtk_hdmi *hdmi;
1643 struct device *dev = &pdev->dev;
1646 hdmi = devm_drm_bridge_alloc(dev, struct mtk_hdmi, bridge,
1648 if (IS_ERR(hdmi))
1649 return PTR_ERR(hdmi);
1651 hdmi->dev = dev;
1652 hdmi->conf = of_device_get_match_data(dev);
1654 ret = mtk_hdmi_dt_parse_pdata(hdmi, pdev);
1658 hdmi->phy = devm_phy_get(dev, "hdmi");
1659 if (IS_ERR(hdmi->phy))
1660 return dev_err_probe(dev, PTR_ERR(hdmi->phy),
1661 "Failed to get HDMI PHY\n");
1663 mutex_init(&hdmi->update_plugged_status_lock);
1664 platform_set_drvdata(pdev, hdmi);
1671 hdmi->bridge.of_node = pdev->dev.of_node;
1672 hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID
1674 hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
1675 hdmi->bridge.vendor = "MediaTek";
1676 hdmi->bridge.product = "On-Chip HDMI";
1678 ret = devm_drm_bridge_add(dev, &hdmi->bridge);
1682 ret = mtk_hdmi_clk_enable_audio(hdmi);
1692 struct mtk_hdmi *hdmi = platform_get_drvdata(pdev);
1694 mtk_hdmi_clk_disable_audio(hdmi);
1699 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1701 mtk_hdmi_clk_disable_audio(hdmi);
1708 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1710 return mtk_hdmi_clk_enable_audio(hdmi);
1725 { .compatible = "mediatek,mt2701-hdmi", .data = &mtk_hdmi_conf_mt2701 },
1726 { .compatible = "mediatek,mt8167-hdmi", .data = &mtk_hdmi_conf_mt8167 },
1727 { .compatible = "mediatek,mt8173-hdmi" },
1736 .name = "mediatek-drm-hdmi",
1744 MODULE_DESCRIPTION("MediaTek HDMI Driver");