| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (c) 2014 MediaTek Inc. |
|---|
| 3 | 4 | * Author: Jie Qiu <jie.qiu@mediatek.com> |
|---|
| 4 | | - * |
|---|
| 5 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 6 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 7 | | - * published by the Free Software Foundation. |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 10 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 11 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 12 | | - * GNU General Public License for more details. |
|---|
| 13 | 5 | */ |
|---|
| 14 | | -#include <drm/drmP.h> |
|---|
| 15 | | -#include <drm/drm_atomic_helper.h> |
|---|
| 16 | | -#include <drm/drm_crtc.h> |
|---|
| 17 | | -#include <drm/drm_crtc_helper.h> |
|---|
| 18 | | -#include <drm/drm_edid.h> |
|---|
| 6 | + |
|---|
| 19 | 7 | #include <linux/arm-smccc.h> |
|---|
| 20 | 8 | #include <linux/clk.h> |
|---|
| 21 | 9 | #include <linux/delay.h> |
|---|
| .. | .. |
|---|
| 24 | 12 | #include <linux/io.h> |
|---|
| 25 | 13 | #include <linux/kernel.h> |
|---|
| 26 | 14 | #include <linux/mfd/syscon.h> |
|---|
| 15 | +#include <linux/module.h> |
|---|
| 16 | +#include <linux/mutex.h> |
|---|
| 27 | 17 | #include <linux/of_platform.h> |
|---|
| 28 | 18 | #include <linux/of.h> |
|---|
| 29 | 19 | #include <linux/of_gpio.h> |
|---|
| .. | .. |
|---|
| 31 | 21 | #include <linux/phy/phy.h> |
|---|
| 32 | 22 | #include <linux/platform_device.h> |
|---|
| 33 | 23 | #include <linux/regmap.h> |
|---|
| 24 | + |
|---|
| 34 | 25 | #include <sound/hdmi-codec.h> |
|---|
| 26 | + |
|---|
| 27 | +#include <drm/drm_atomic_helper.h> |
|---|
| 28 | +#include <drm/drm_bridge.h> |
|---|
| 29 | +#include <drm/drm_crtc.h> |
|---|
| 30 | +#include <drm/drm_edid.h> |
|---|
| 31 | +#include <drm/drm_print.h> |
|---|
| 32 | +#include <drm/drm_probe_helper.h> |
|---|
| 33 | + |
|---|
| 35 | 34 | #include "mtk_cec.h" |
|---|
| 36 | 35 | #include "mtk_hdmi.h" |
|---|
| 37 | 36 | #include "mtk_hdmi_regs.h" |
|---|
| .. | .. |
|---|
| 147 | 146 | struct hdmi_codec_params codec_params; |
|---|
| 148 | 147 | }; |
|---|
| 149 | 148 | |
|---|
| 149 | +struct mtk_hdmi_conf { |
|---|
| 150 | + bool tz_disabled; |
|---|
| 151 | +}; |
|---|
| 152 | + |
|---|
| 150 | 153 | struct mtk_hdmi { |
|---|
| 151 | 154 | struct drm_bridge bridge; |
|---|
| 152 | 155 | struct drm_bridge *next_bridge; |
|---|
| 153 | 156 | struct drm_connector conn; |
|---|
| 154 | 157 | struct device *dev; |
|---|
| 158 | + const struct mtk_hdmi_conf *conf; |
|---|
| 155 | 159 | struct phy *phy; |
|---|
| 156 | 160 | struct device *cec_dev; |
|---|
| 157 | 161 | struct i2c_adapter *ddc_adpt; |
|---|
| .. | .. |
|---|
| 172 | 176 | bool audio_enable; |
|---|
| 173 | 177 | bool powered; |
|---|
| 174 | 178 | bool enabled; |
|---|
| 179 | + hdmi_codec_plugged_cb plugged_cb; |
|---|
| 180 | + struct device *codec_dev; |
|---|
| 181 | + struct mutex update_plugged_status_lock; |
|---|
| 175 | 182 | }; |
|---|
| 176 | 183 | |
|---|
| 177 | 184 | static inline struct mtk_hdmi *hdmi_ctx_from_bridge(struct drm_bridge *b) |
|---|
| .. | .. |
|---|
| 240 | 247 | * The ARM trusted firmware provides an API for the HDMI driver to set |
|---|
| 241 | 248 | * this control bit to enable HDMI output in supervisor mode. |
|---|
| 242 | 249 | */ |
|---|
| 243 | | - arm_smccc_smc(MTK_SIP_SET_AUTHORIZED_SECURE_REG, 0x14000904, 0x80000000, |
|---|
| 244 | | - 0, 0, 0, 0, 0, &res); |
|---|
| 250 | + if (hdmi->conf && hdmi->conf->tz_disabled) |
|---|
| 251 | + regmap_update_bits(hdmi->sys_regmap, |
|---|
| 252 | + hdmi->sys_offset + HDMI_SYS_CFG20, |
|---|
| 253 | + 0x80008005, enable ? 0x80000005 : 0x8000); |
|---|
| 254 | + else |
|---|
| 255 | + arm_smccc_smc(MTK_SIP_SET_AUTHORIZED_SECURE_REG, 0x14000904, |
|---|
| 256 | + 0x80000000, 0, 0, 0, 0, 0, &res); |
|---|
| 245 | 257 | |
|---|
| 246 | 258 | regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20, |
|---|
| 247 | 259 | HDMI_PCLK_FREE_RUN, enable ? HDMI_PCLK_FREE_RUN : 0); |
|---|
| .. | .. |
|---|
| 304 | 316 | u8 checksum; |
|---|
| 305 | 317 | int ctrl_frame_en = 0; |
|---|
| 306 | 318 | |
|---|
| 307 | | - frame_type = *buffer; |
|---|
| 308 | | - buffer += 1; |
|---|
| 309 | | - frame_ver = *buffer; |
|---|
| 310 | | - buffer += 1; |
|---|
| 311 | | - frame_len = *buffer; |
|---|
| 312 | | - buffer += 1; |
|---|
| 313 | | - checksum = *buffer; |
|---|
| 314 | | - buffer += 1; |
|---|
| 319 | + frame_type = *buffer++; |
|---|
| 320 | + frame_ver = *buffer++; |
|---|
| 321 | + frame_len = *buffer++; |
|---|
| 322 | + checksum = *buffer++; |
|---|
| 315 | 323 | frame_data = buffer; |
|---|
| 316 | 324 | |
|---|
| 317 | 325 | dev_dbg(hdmi->dev, |
|---|
| .. | .. |
|---|
| 335 | 343 | ctrl_frame_en = VS_EN; |
|---|
| 336 | 344 | ctrl_reg = GRL_ACP_ISRC_CTRL; |
|---|
| 337 | 345 | break; |
|---|
| 346 | + default: |
|---|
| 347 | + dev_err(hdmi->dev, "Unknown infoframe type %d\n", frame_type); |
|---|
| 348 | + return; |
|---|
| 338 | 349 | } |
|---|
| 339 | 350 | mtk_hdmi_clear_bits(hdmi, ctrl_reg, ctrl_frame_en); |
|---|
| 340 | 351 | mtk_hdmi_write(hdmi, GRL_INFOFRM_TYPE, frame_type); |
|---|
| .. | .. |
|---|
| 972 | 983 | struct drm_display_mode *mode) |
|---|
| 973 | 984 | { |
|---|
| 974 | 985 | struct hdmi_avi_infoframe frame; |
|---|
| 975 | | - u8 buffer[17]; |
|---|
| 986 | + u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; |
|---|
| 976 | 987 | ssize_t err; |
|---|
| 977 | 988 | |
|---|
| 978 | | - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); |
|---|
| 989 | + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, |
|---|
| 990 | + &hdmi->conn, mode); |
|---|
| 979 | 991 | if (err < 0) { |
|---|
| 980 | 992 | dev_err(hdmi->dev, |
|---|
| 981 | 993 | "Failed to get AVI infoframe from mode: %zd\n", err); |
|---|
| .. | .. |
|---|
| 997 | 1009 | const char *product) |
|---|
| 998 | 1010 | { |
|---|
| 999 | 1011 | struct hdmi_spd_infoframe frame; |
|---|
| 1000 | | - u8 buffer[29]; |
|---|
| 1012 | + u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_SPD_INFOFRAME_SIZE]; |
|---|
| 1001 | 1013 | ssize_t err; |
|---|
| 1002 | 1014 | |
|---|
| 1003 | 1015 | err = hdmi_spd_infoframe_init(&frame, vendor, product); |
|---|
| .. | .. |
|---|
| 1020 | 1032 | static int mtk_hdmi_setup_audio_infoframe(struct mtk_hdmi *hdmi) |
|---|
| 1021 | 1033 | { |
|---|
| 1022 | 1034 | struct hdmi_audio_infoframe frame; |
|---|
| 1023 | | - u8 buffer[14]; |
|---|
| 1035 | + u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE]; |
|---|
| 1024 | 1036 | ssize_t err; |
|---|
| 1025 | 1037 | |
|---|
| 1026 | 1038 | err = hdmi_audio_infoframe_init(&frame); |
|---|
| .. | .. |
|---|
| 1187 | 1199 | clk_disable_unprepare(hdmi->clk[MTK_HDMI_CLK_AUD_SPDIF]); |
|---|
| 1188 | 1200 | } |
|---|
| 1189 | 1201 | |
|---|
| 1202 | +static enum drm_connector_status |
|---|
| 1203 | +mtk_hdmi_update_plugged_status(struct mtk_hdmi *hdmi) |
|---|
| 1204 | +{ |
|---|
| 1205 | + bool connected; |
|---|
| 1206 | + |
|---|
| 1207 | + mutex_lock(&hdmi->update_plugged_status_lock); |
|---|
| 1208 | + connected = mtk_cec_hpd_high(hdmi->cec_dev); |
|---|
| 1209 | + if (hdmi->plugged_cb && hdmi->codec_dev) |
|---|
| 1210 | + hdmi->plugged_cb(hdmi->codec_dev, connected); |
|---|
| 1211 | + mutex_unlock(&hdmi->update_plugged_status_lock); |
|---|
| 1212 | + |
|---|
| 1213 | + return connected ? |
|---|
| 1214 | + connector_status_connected : connector_status_disconnected; |
|---|
| 1215 | +} |
|---|
| 1216 | + |
|---|
| 1190 | 1217 | static enum drm_connector_status hdmi_conn_detect(struct drm_connector *conn, |
|---|
| 1191 | 1218 | bool force) |
|---|
| 1192 | 1219 | { |
|---|
| 1193 | 1220 | struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn); |
|---|
| 1194 | | - |
|---|
| 1195 | | - return mtk_cec_hpd_high(hdmi->cec_dev) ? |
|---|
| 1196 | | - connector_status_connected : connector_status_disconnected; |
|---|
| 1221 | + return mtk_hdmi_update_plugged_status(hdmi); |
|---|
| 1197 | 1222 | } |
|---|
| 1198 | 1223 | |
|---|
| 1199 | 1224 | static void hdmi_conn_destroy(struct drm_connector *conn) |
|---|
| .. | .. |
|---|
| 1231 | 1256 | struct drm_display_mode *mode) |
|---|
| 1232 | 1257 | { |
|---|
| 1233 | 1258 | struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn); |
|---|
| 1259 | + struct drm_bridge *next_bridge; |
|---|
| 1234 | 1260 | |
|---|
| 1235 | 1261 | dev_dbg(hdmi->dev, "xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n", |
|---|
| 1236 | | - mode->hdisplay, mode->vdisplay, mode->vrefresh, |
|---|
| 1262 | + mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), |
|---|
| 1237 | 1263 | !!(mode->flags & DRM_MODE_FLAG_INTERLACE), mode->clock * 1000); |
|---|
| 1238 | 1264 | |
|---|
| 1239 | | - if (hdmi->bridge.next) { |
|---|
| 1265 | + next_bridge = drm_bridge_get_next_bridge(&hdmi->bridge); |
|---|
| 1266 | + if (next_bridge) { |
|---|
| 1240 | 1267 | struct drm_display_mode adjusted_mode; |
|---|
| 1241 | 1268 | |
|---|
| 1242 | 1269 | drm_mode_copy(&adjusted_mode, mode); |
|---|
| 1243 | | - if (!drm_bridge_mode_fixup(hdmi->bridge.next, mode, |
|---|
| 1244 | | - &adjusted_mode)) |
|---|
| 1270 | + if (!drm_bridge_chain_mode_fixup(next_bridge, mode, |
|---|
| 1271 | + &adjusted_mode)) |
|---|
| 1245 | 1272 | return MODE_BAD; |
|---|
| 1246 | 1273 | } |
|---|
| 1247 | 1274 | |
|---|
| .. | .. |
|---|
| 1288 | 1315 | * Bridge callbacks |
|---|
| 1289 | 1316 | */ |
|---|
| 1290 | 1317 | |
|---|
| 1291 | | -static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge) |
|---|
| 1318 | +static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge, |
|---|
| 1319 | + enum drm_bridge_attach_flags flags) |
|---|
| 1292 | 1320 | { |
|---|
| 1293 | 1321 | struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); |
|---|
| 1294 | 1322 | int ret; |
|---|
| 1295 | 1323 | |
|---|
| 1296 | | - ret = drm_connector_init(bridge->encoder->dev, &hdmi->conn, |
|---|
| 1297 | | - &mtk_hdmi_connector_funcs, |
|---|
| 1298 | | - DRM_MODE_CONNECTOR_HDMIA); |
|---|
| 1324 | + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { |
|---|
| 1325 | + DRM_ERROR("Fix bridge driver to make connector optional!"); |
|---|
| 1326 | + return -EINVAL; |
|---|
| 1327 | + } |
|---|
| 1328 | + |
|---|
| 1329 | + ret = drm_connector_init_with_ddc(bridge->encoder->dev, &hdmi->conn, |
|---|
| 1330 | + &mtk_hdmi_connector_funcs, |
|---|
| 1331 | + DRM_MODE_CONNECTOR_HDMIA, |
|---|
| 1332 | + hdmi->ddc_adpt); |
|---|
| 1299 | 1333 | if (ret) { |
|---|
| 1300 | 1334 | dev_err(hdmi->dev, "Failed to initialize connector: %d\n", ret); |
|---|
| 1301 | 1335 | return ret; |
|---|
| .. | .. |
|---|
| 1316 | 1350 | |
|---|
| 1317 | 1351 | if (hdmi->next_bridge) { |
|---|
| 1318 | 1352 | ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge, |
|---|
| 1319 | | - bridge); |
|---|
| 1353 | + bridge, flags); |
|---|
| 1320 | 1354 | if (ret) { |
|---|
| 1321 | 1355 | dev_err(hdmi->dev, |
|---|
| 1322 | 1356 | "Failed to attach external bridge: %d\n", ret); |
|---|
| .. | .. |
|---|
| 1364 | 1398 | } |
|---|
| 1365 | 1399 | |
|---|
| 1366 | 1400 | static void mtk_hdmi_bridge_mode_set(struct drm_bridge *bridge, |
|---|
| 1367 | | - struct drm_display_mode *mode, |
|---|
| 1368 | | - struct drm_display_mode *adjusted_mode) |
|---|
| 1401 | + const struct drm_display_mode *mode, |
|---|
| 1402 | + const struct drm_display_mode *adjusted_mode) |
|---|
| 1369 | 1403 | { |
|---|
| 1370 | 1404 | struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); |
|---|
| 1371 | 1405 | |
|---|
| .. | .. |
|---|
| 1441 | 1475 | |
|---|
| 1442 | 1476 | ret = mtk_hdmi_get_all_clk(hdmi, np); |
|---|
| 1443 | 1477 | if (ret) { |
|---|
| 1444 | | - dev_err(dev, "Failed to get clocks: %d\n", ret); |
|---|
| 1478 | + if (ret != -EPROBE_DEFER) |
|---|
| 1479 | + dev_err(dev, "Failed to get clocks: %d\n", ret); |
|---|
| 1480 | + |
|---|
| 1445 | 1481 | return ret; |
|---|
| 1446 | 1482 | } |
|---|
| 1447 | 1483 | |
|---|
| .. | .. |
|---|
| 1586 | 1622 | hdmi_params.aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT; |
|---|
| 1587 | 1623 | hdmi_params.aud_mclk = HDMI_AUD_MCLK_128FS; |
|---|
| 1588 | 1624 | break; |
|---|
| 1625 | + case HDMI_SPDIF: |
|---|
| 1626 | + hdmi_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM; |
|---|
| 1627 | + hdmi_params.aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16; |
|---|
| 1628 | + hdmi_params.aud_input_type = HDMI_AUD_INPUT_SPDIF; |
|---|
| 1629 | + break; |
|---|
| 1589 | 1630 | default: |
|---|
| 1590 | 1631 | dev_err(hdmi->dev, "%s: Invalid DAI format %d\n", __func__, |
|---|
| 1591 | 1632 | daifmt->fmt); |
|---|
| .. | .. |
|---|
| 1604 | 1645 | { |
|---|
| 1605 | 1646 | struct mtk_hdmi *hdmi = dev_get_drvdata(dev); |
|---|
| 1606 | 1647 | |
|---|
| 1607 | | - dev_dbg(dev, "%s\n", __func__); |
|---|
| 1608 | | - |
|---|
| 1609 | 1648 | mtk_hdmi_audio_enable(hdmi); |
|---|
| 1610 | 1649 | |
|---|
| 1611 | 1650 | return 0; |
|---|
| .. | .. |
|---|
| 1615 | 1654 | { |
|---|
| 1616 | 1655 | struct mtk_hdmi *hdmi = dev_get_drvdata(dev); |
|---|
| 1617 | 1656 | |
|---|
| 1618 | | - dev_dbg(dev, "%s\n", __func__); |
|---|
| 1619 | | - |
|---|
| 1620 | 1657 | mtk_hdmi_audio_disable(hdmi); |
|---|
| 1621 | 1658 | } |
|---|
| 1622 | 1659 | |
|---|
| 1623 | 1660 | static int |
|---|
| 1624 | | -mtk_hdmi_audio_digital_mute(struct device *dev, void *data, bool enable) |
|---|
| 1661 | +mtk_hdmi_audio_mute(struct device *dev, void *data, |
|---|
| 1662 | + bool enable, int direction) |
|---|
| 1625 | 1663 | { |
|---|
| 1626 | 1664 | struct mtk_hdmi *hdmi = dev_get_drvdata(dev); |
|---|
| 1627 | | - |
|---|
| 1628 | | - dev_dbg(dev, "%s(%d)\n", __func__, enable); |
|---|
| 1629 | 1665 | |
|---|
| 1630 | 1666 | if (enable) |
|---|
| 1631 | 1667 | mtk_hdmi_hw_aud_mute(hdmi); |
|---|
| .. | .. |
|---|
| 1639 | 1675 | { |
|---|
| 1640 | 1676 | struct mtk_hdmi *hdmi = dev_get_drvdata(dev); |
|---|
| 1641 | 1677 | |
|---|
| 1642 | | - dev_dbg(dev, "%s\n", __func__); |
|---|
| 1643 | | - |
|---|
| 1644 | 1678 | memcpy(buf, hdmi->conn.eld, min(sizeof(hdmi->conn.eld), len)); |
|---|
| 1679 | + |
|---|
| 1680 | + return 0; |
|---|
| 1681 | +} |
|---|
| 1682 | + |
|---|
| 1683 | +static int mtk_hdmi_audio_hook_plugged_cb(struct device *dev, void *data, |
|---|
| 1684 | + hdmi_codec_plugged_cb fn, |
|---|
| 1685 | + struct device *codec_dev) |
|---|
| 1686 | +{ |
|---|
| 1687 | + struct mtk_hdmi *hdmi = data; |
|---|
| 1688 | + |
|---|
| 1689 | + mutex_lock(&hdmi->update_plugged_status_lock); |
|---|
| 1690 | + hdmi->plugged_cb = fn; |
|---|
| 1691 | + hdmi->codec_dev = codec_dev; |
|---|
| 1692 | + mutex_unlock(&hdmi->update_plugged_status_lock); |
|---|
| 1693 | + |
|---|
| 1694 | + mtk_hdmi_update_plugged_status(hdmi); |
|---|
| 1645 | 1695 | |
|---|
| 1646 | 1696 | return 0; |
|---|
| 1647 | 1697 | } |
|---|
| .. | .. |
|---|
| 1650 | 1700 | .hw_params = mtk_hdmi_audio_hw_params, |
|---|
| 1651 | 1701 | .audio_startup = mtk_hdmi_audio_startup, |
|---|
| 1652 | 1702 | .audio_shutdown = mtk_hdmi_audio_shutdown, |
|---|
| 1653 | | - .digital_mute = mtk_hdmi_audio_digital_mute, |
|---|
| 1703 | + .mute_stream = mtk_hdmi_audio_mute, |
|---|
| 1654 | 1704 | .get_eld = mtk_hdmi_audio_get_eld, |
|---|
| 1705 | + .hook_plugged_cb = mtk_hdmi_audio_hook_plugged_cb, |
|---|
| 1706 | + .no_capture_mute = 1, |
|---|
| 1655 | 1707 | }; |
|---|
| 1656 | 1708 | |
|---|
| 1657 | | -static void mtk_hdmi_register_audio_driver(struct device *dev) |
|---|
| 1709 | +static int mtk_hdmi_register_audio_driver(struct device *dev) |
|---|
| 1658 | 1710 | { |
|---|
| 1711 | + struct mtk_hdmi *hdmi = dev_get_drvdata(dev); |
|---|
| 1659 | 1712 | struct hdmi_codec_pdata codec_data = { |
|---|
| 1660 | 1713 | .ops = &mtk_hdmi_audio_codec_ops, |
|---|
| 1661 | 1714 | .max_i2s_channels = 2, |
|---|
| 1662 | 1715 | .i2s = 1, |
|---|
| 1716 | + .data = hdmi, |
|---|
| 1663 | 1717 | }; |
|---|
| 1664 | 1718 | struct platform_device *pdev; |
|---|
| 1665 | 1719 | |
|---|
| .. | .. |
|---|
| 1667 | 1721 | PLATFORM_DEVID_AUTO, &codec_data, |
|---|
| 1668 | 1722 | sizeof(codec_data)); |
|---|
| 1669 | 1723 | if (IS_ERR(pdev)) |
|---|
| 1670 | | - return; |
|---|
| 1724 | + return PTR_ERR(pdev); |
|---|
| 1671 | 1725 | |
|---|
| 1672 | 1726 | DRM_INFO("%s driver bound to HDMI\n", HDMI_CODEC_DRV_NAME); |
|---|
| 1727 | + return 0; |
|---|
| 1673 | 1728 | } |
|---|
| 1674 | 1729 | |
|---|
| 1675 | 1730 | static int mtk_drm_hdmi_probe(struct platform_device *pdev) |
|---|
| .. | .. |
|---|
| 1683 | 1738 | return -ENOMEM; |
|---|
| 1684 | 1739 | |
|---|
| 1685 | 1740 | hdmi->dev = dev; |
|---|
| 1741 | + hdmi->conf = of_device_get_match_data(dev); |
|---|
| 1686 | 1742 | |
|---|
| 1687 | 1743 | ret = mtk_hdmi_dt_parse_pdata(hdmi, pdev); |
|---|
| 1688 | 1744 | if (ret) |
|---|
| .. | .. |
|---|
| 1695 | 1751 | return ret; |
|---|
| 1696 | 1752 | } |
|---|
| 1697 | 1753 | |
|---|
| 1754 | + mutex_init(&hdmi->update_plugged_status_lock); |
|---|
| 1698 | 1755 | platform_set_drvdata(pdev, hdmi); |
|---|
| 1699 | 1756 | |
|---|
| 1700 | 1757 | ret = mtk_hdmi_output_init(hdmi); |
|---|
| .. | .. |
|---|
| 1703 | 1760 | return ret; |
|---|
| 1704 | 1761 | } |
|---|
| 1705 | 1762 | |
|---|
| 1706 | | - mtk_hdmi_register_audio_driver(dev); |
|---|
| 1763 | + ret = mtk_hdmi_register_audio_driver(dev); |
|---|
| 1764 | + if (ret) { |
|---|
| 1765 | + dev_err(dev, "Failed to register audio driver: %d\n", ret); |
|---|
| 1766 | + return ret; |
|---|
| 1767 | + } |
|---|
| 1707 | 1768 | |
|---|
| 1708 | 1769 | hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs; |
|---|
| 1709 | 1770 | hdmi->bridge.of_node = pdev->dev.of_node; |
|---|
| .. | .. |
|---|
| 1715 | 1776 | goto err_bridge_remove; |
|---|
| 1716 | 1777 | } |
|---|
| 1717 | 1778 | |
|---|
| 1718 | | - dev_dbg(dev, "mediatek hdmi probe success\n"); |
|---|
| 1719 | 1779 | return 0; |
|---|
| 1720 | 1780 | |
|---|
| 1721 | 1781 | err_bridge_remove: |
|---|
| .. | .. |
|---|
| 1738 | 1798 | struct mtk_hdmi *hdmi = dev_get_drvdata(dev); |
|---|
| 1739 | 1799 | |
|---|
| 1740 | 1800 | mtk_hdmi_clk_disable_audio(hdmi); |
|---|
| 1741 | | - dev_dbg(dev, "hdmi suspend success!\n"); |
|---|
| 1801 | + |
|---|
| 1742 | 1802 | return 0; |
|---|
| 1743 | 1803 | } |
|---|
| 1744 | 1804 | |
|---|
| .. | .. |
|---|
| 1753 | 1813 | return ret; |
|---|
| 1754 | 1814 | } |
|---|
| 1755 | 1815 | |
|---|
| 1756 | | - dev_dbg(dev, "hdmi resume success!\n"); |
|---|
| 1757 | 1816 | return 0; |
|---|
| 1758 | 1817 | } |
|---|
| 1759 | 1818 | #endif |
|---|
| 1760 | 1819 | static SIMPLE_DEV_PM_OPS(mtk_hdmi_pm_ops, |
|---|
| 1761 | 1820 | mtk_hdmi_suspend, mtk_hdmi_resume); |
|---|
| 1762 | 1821 | |
|---|
| 1822 | +static const struct mtk_hdmi_conf mtk_hdmi_conf_mt2701 = { |
|---|
| 1823 | + .tz_disabled = true, |
|---|
| 1824 | +}; |
|---|
| 1825 | + |
|---|
| 1763 | 1826 | static const struct of_device_id mtk_drm_hdmi_of_ids[] = { |
|---|
| 1764 | | - { .compatible = "mediatek,mt8173-hdmi", }, |
|---|
| 1827 | + { .compatible = "mediatek,mt2701-hdmi", |
|---|
| 1828 | + .data = &mtk_hdmi_conf_mt2701, |
|---|
| 1829 | + }, |
|---|
| 1830 | + { .compatible = "mediatek,mt8173-hdmi", |
|---|
| 1831 | + }, |
|---|
| 1765 | 1832 | {} |
|---|
| 1766 | 1833 | }; |
|---|
| 1767 | 1834 | |
|---|
| .. | .. |
|---|
| 1776 | 1843 | }; |
|---|
| 1777 | 1844 | |
|---|
| 1778 | 1845 | static struct platform_driver * const mtk_hdmi_drivers[] = { |
|---|
| 1779 | | - &mtk_hdmi_phy_driver, |
|---|
| 1780 | 1846 | &mtk_hdmi_ddc_driver, |
|---|
| 1781 | 1847 | &mtk_cec_driver, |
|---|
| 1782 | 1848 | &mtk_hdmi_driver, |
|---|