| .. | .. |
|---|
| 21 | 21 | #endif |
|---|
| 22 | 22 | |
|---|
| 23 | 23 | #include <drm/drm_of.h> |
|---|
| 24 | | -#include <drm/drmP.h> |
|---|
| 24 | +#include <drm/drm_drv.h> |
|---|
| 25 | 25 | #include <drm/drm_atomic_helper.h> |
|---|
| 26 | 26 | #include <drm/drm_crtc_helper.h> |
|---|
| 27 | 27 | #include <drm/drm_edid.h> |
|---|
| 28 | +#include <drm/drm_probe_helper.h> |
|---|
| 28 | 29 | |
|---|
| 29 | 30 | #include <sound/hdmi-codec.h> |
|---|
| 30 | 31 | |
|---|
| .. | .. |
|---|
| 439 | 440 | struct switch_dev switchdev; |
|---|
| 440 | 441 | #endif |
|---|
| 441 | 442 | struct rockchip_drm_sub_dev sub_dev; |
|---|
| 442 | | - hdmi_codec_plugged_cb plugged_cb; |
|---|
| 443 | | - struct device *codec_dev; |
|---|
| 444 | | - enum drm_connector_status last_connector_result; |
|---|
| 445 | 443 | }; |
|---|
| 446 | 444 | |
|---|
| 447 | 445 | enum { |
|---|
| .. | .. |
|---|
| 545 | 543 | static inline void hdmi_writeb(struct rk618_hdmi *hdmi, u16 offset, u32 val) |
|---|
| 546 | 544 | { |
|---|
| 547 | 545 | regmap_write(hdmi->regmap, (RK618_HDMI_BASE + ((offset) << 2)), val); |
|---|
| 548 | | -} |
|---|
| 549 | | - |
|---|
| 550 | | -static void handle_plugged_change(struct rk618_hdmi *hdmi, bool plugged) |
|---|
| 551 | | -{ |
|---|
| 552 | | - if (hdmi->plugged_cb && hdmi->codec_dev) |
|---|
| 553 | | - hdmi->plugged_cb(hdmi->codec_dev, plugged); |
|---|
| 554 | | -} |
|---|
| 555 | | - |
|---|
| 556 | | -static int rk618_hdmi_set_plugged_cb(struct rk618_hdmi *hdmi, |
|---|
| 557 | | - hdmi_codec_plugged_cb fn, |
|---|
| 558 | | - struct device *codec_dev) |
|---|
| 559 | | -{ |
|---|
| 560 | | - bool plugged; |
|---|
| 561 | | - |
|---|
| 562 | | - hdmi->plugged_cb = fn; |
|---|
| 563 | | - hdmi->codec_dev = codec_dev; |
|---|
| 564 | | - plugged = hdmi->last_connector_result == connector_status_connected; |
|---|
| 565 | | - handle_plugged_change(hdmi, plugged); |
|---|
| 566 | | - |
|---|
| 567 | | - return 0; |
|---|
| 568 | 546 | } |
|---|
| 569 | 547 | |
|---|
| 570 | 548 | static void rk618_hdmi_set_polarity(struct rk618_hdmi *hdmi, int vic) |
|---|
| .. | .. |
|---|
| 745 | 723 | union hdmi_infoframe frame; |
|---|
| 746 | 724 | int rc; |
|---|
| 747 | 725 | |
|---|
| 748 | | - rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false); |
|---|
| 726 | + rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, &hdmi->connector, mode); |
|---|
| 749 | 727 | |
|---|
| 750 | 728 | if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444) |
|---|
| 751 | 729 | frame.avi.colorspace = HDMI_COLORSPACE_YUV444; |
|---|
| .. | .. |
|---|
| 968 | 946 | { |
|---|
| 969 | 947 | struct rk618_hdmi *hdmi = connector_to_hdmi(connector); |
|---|
| 970 | 948 | bool status; |
|---|
| 971 | | - enum drm_connector_status result; |
|---|
| 972 | 949 | |
|---|
| 973 | 950 | status = rk618_hdmi_hpd_detect(hdmi); |
|---|
| 974 | 951 | #ifdef CONFIG_SWITCH |
|---|
| 975 | 952 | switch_set_state(&hdmi->switchdev, status); |
|---|
| 976 | 953 | #endif |
|---|
| 977 | 954 | |
|---|
| 978 | | - result = status ? connector_status_connected : |
|---|
| 955 | + return status ? connector_status_connected : |
|---|
| 979 | 956 | connector_status_disconnected; |
|---|
| 980 | | - if (result != hdmi->last_connector_result) { |
|---|
| 981 | | - dev_dbg(hdmi->dev, "rk618_hdmi read_hpd result: %d", result); |
|---|
| 982 | | - handle_plugged_change(hdmi, |
|---|
| 983 | | - result == connector_status_connected); |
|---|
| 984 | | - hdmi->last_connector_result = result; |
|---|
| 985 | | - } |
|---|
| 986 | | - |
|---|
| 987 | | - return result; |
|---|
| 988 | 957 | } |
|---|
| 989 | 958 | |
|---|
| 990 | 959 | static int rk618_hdmi_connector_get_modes(struct drm_connector *connector) |
|---|
| .. | .. |
|---|
| 1063 | 1032 | }; |
|---|
| 1064 | 1033 | |
|---|
| 1065 | 1034 | static void rk618_hdmi_bridge_mode_set(struct drm_bridge *bridge, |
|---|
| 1066 | | - struct drm_display_mode *mode, |
|---|
| 1067 | | - struct drm_display_mode *adj_mode) |
|---|
| 1035 | + const struct drm_display_mode *mode, |
|---|
| 1036 | + const struct drm_display_mode *adj_mode) |
|---|
| 1068 | 1037 | { |
|---|
| 1069 | 1038 | struct rk618_hdmi *hdmi = bridge_to_hdmi(bridge); |
|---|
| 1070 | 1039 | |
|---|
| .. | .. |
|---|
| 1097 | 1066 | clk_disable_unprepare(hdmi->clock); |
|---|
| 1098 | 1067 | } |
|---|
| 1099 | 1068 | |
|---|
| 1100 | | -static int rk618_hdmi_bridge_attach(struct drm_bridge *bridge) |
|---|
| 1069 | +static int rk618_hdmi_bridge_attach(struct drm_bridge *bridge, |
|---|
| 1070 | + enum drm_bridge_attach_flags flags) |
|---|
| 1101 | 1071 | { |
|---|
| 1102 | 1072 | struct rk618_hdmi *hdmi = bridge_to_hdmi(bridge); |
|---|
| 1103 | 1073 | struct device *dev = hdmi->dev; |
|---|
| .. | .. |
|---|
| 1137 | 1107 | if (!hdmi->bridge) |
|---|
| 1138 | 1108 | return -EPROBE_DEFER; |
|---|
| 1139 | 1109 | |
|---|
| 1140 | | - ret = drm_bridge_attach(bridge->encoder, hdmi->bridge, bridge); |
|---|
| 1110 | + ret = drm_bridge_attach(bridge->encoder, hdmi->bridge, bridge, 0); |
|---|
| 1141 | 1111 | if (ret) { |
|---|
| 1142 | 1112 | dev_err(dev, "failed to attach bridge\n"); |
|---|
| 1143 | 1113 | return ret; |
|---|
| .. | .. |
|---|
| 1162 | 1132 | .disable = rk618_hdmi_bridge_disable, |
|---|
| 1163 | 1133 | }; |
|---|
| 1164 | 1134 | |
|---|
| 1165 | | -static int rk618_hdmi_audio_config_set(struct rk618_hdmi *hdmi, |
|---|
| 1166 | | - struct hdmi_codec_daifmt *daifmt, |
|---|
| 1167 | | - struct audio_info *audio) |
|---|
| 1135 | +static int |
|---|
| 1136 | +rk618_hdmi_audio_config_set(struct rk618_hdmi *hdmi, struct audio_info *audio) |
|---|
| 1168 | 1137 | { |
|---|
| 1169 | 1138 | int rate, N, channel; |
|---|
| 1170 | 1139 | |
|---|
| .. | .. |
|---|
| 1212 | 1181 | return -ENOENT; |
|---|
| 1213 | 1182 | } |
|---|
| 1214 | 1183 | |
|---|
| 1215 | | - if (daifmt->fmt == HDMI_SPDIF) { |
|---|
| 1216 | | - /* set_audio source SPDIF */ |
|---|
| 1217 | | - hdmi_writeb(hdmi, HDMI_AUDIO_CTRL1, 0x09); |
|---|
| 1218 | | - } else { |
|---|
| 1219 | | - /* set_audio source I2S */ |
|---|
| 1220 | | - hdmi_writeb(hdmi, HDMI_AUDIO_CTRL1, 0x01); |
|---|
| 1221 | | - } |
|---|
| 1184 | + /* set_audio source I2S */ |
|---|
| 1185 | + hdmi_writeb(hdmi, HDMI_AUDIO_CTRL1, 0x01); |
|---|
| 1222 | 1186 | hdmi_writeb(hdmi, AUDIO_SAMPLE_RATE, rate); |
|---|
| 1223 | 1187 | hdmi_writeb(hdmi, AUDIO_I2S_MODE, v_I2S_MODE(I2S_STANDARD) | |
|---|
| 1224 | 1188 | v_I2S_CHANNEL(channel)); |
|---|
| 1225 | 1189 | |
|---|
| 1226 | 1190 | hdmi_writeb(hdmi, AUDIO_I2S_MAP, 0x00); |
|---|
| 1227 | | - hdmi_writeb(hdmi, AUDIO_I2S_SWAPS_SPDIF, rate); |
|---|
| 1191 | + hdmi_writeb(hdmi, AUDIO_I2S_SWAPS_SPDIF, 0); |
|---|
| 1228 | 1192 | |
|---|
| 1229 | 1193 | /* Set N value */ |
|---|
| 1230 | 1194 | hdmi_writeb(hdmi, AUDIO_N_H, (N >> 16) & 0x0F); |
|---|
| .. | .. |
|---|
| 1259 | 1223 | switch (daifmt->fmt) { |
|---|
| 1260 | 1224 | case HDMI_I2S: |
|---|
| 1261 | 1225 | break; |
|---|
| 1262 | | - case HDMI_SPDIF: |
|---|
| 1263 | | - break; |
|---|
| 1264 | 1226 | default: |
|---|
| 1265 | 1227 | dev_err(dev, "%s: Invalid format %d\n", __func__, daifmt->fmt); |
|---|
| 1266 | 1228 | return -EINVAL; |
|---|
| 1267 | 1229 | } |
|---|
| 1268 | 1230 | |
|---|
| 1269 | | - return rk618_hdmi_audio_config_set(hdmi, daifmt, &audio); |
|---|
| 1231 | + return rk618_hdmi_audio_config_set(hdmi, &audio); |
|---|
| 1270 | 1232 | } |
|---|
| 1271 | 1233 | |
|---|
| 1272 | 1234 | static void rk618_hdmi_audio_shutdown(struct device *dev, void *d) |
|---|
| .. | .. |
|---|
| 1274 | 1236 | /* do nothing */ |
|---|
| 1275 | 1237 | } |
|---|
| 1276 | 1238 | |
|---|
| 1277 | | -static int rk618_hdmi_audio_digital_mute(struct device *dev, void *d, bool mute) |
|---|
| 1239 | +static int rk618_hdmi_audio_mute_stream(struct device *dev, void *d, bool mute, int direction) |
|---|
| 1278 | 1240 | { |
|---|
| 1279 | 1241 | struct rk618_hdmi *hdmi = dev_get_drvdata(dev); |
|---|
| 1280 | 1242 | |
|---|
| .. | .. |
|---|
| 1316 | 1278 | return ret; |
|---|
| 1317 | 1279 | } |
|---|
| 1318 | 1280 | |
|---|
| 1319 | | -static int rk618_hdmi_hook_plugged_cb(struct device *dev, void *data, |
|---|
| 1320 | | - hdmi_codec_plugged_cb fn, |
|---|
| 1321 | | - struct device *codec_dev) |
|---|
| 1322 | | -{ |
|---|
| 1323 | | - struct rk618_hdmi *hdmi = dev_get_drvdata(dev); |
|---|
| 1324 | | - |
|---|
| 1325 | | - return rk618_hdmi_set_plugged_cb(hdmi, fn, codec_dev); |
|---|
| 1326 | | -} |
|---|
| 1327 | | - |
|---|
| 1328 | 1281 | static const struct hdmi_codec_ops audio_codec_ops = { |
|---|
| 1329 | 1282 | .hw_params = rk618_hdmi_audio_hw_params, |
|---|
| 1330 | 1283 | .audio_shutdown = rk618_hdmi_audio_shutdown, |
|---|
| 1331 | | - .digital_mute = rk618_hdmi_audio_digital_mute, |
|---|
| 1284 | + .mute_stream = rk618_hdmi_audio_mute_stream, |
|---|
| 1332 | 1285 | .get_eld = rk618_hdmi_audio_get_eld, |
|---|
| 1333 | | - .hook_plugged_cb = rk618_hdmi_hook_plugged_cb, |
|---|
| 1334 | 1286 | }; |
|---|
| 1335 | 1287 | |
|---|
| 1336 | 1288 | static int rk618_hdmi_audio_codec_init(struct rk618_hdmi *hdmi, |
|---|
| 1337 | 1289 | struct device *dev) |
|---|
| 1338 | 1290 | { |
|---|
| 1339 | | - const char *str = "i2s"; |
|---|
| 1340 | | - struct device_node *np = dev->of_node; |
|---|
| 1341 | 1291 | struct hdmi_codec_pdata codec_data = { |
|---|
| 1342 | 1292 | .i2s = 1, |
|---|
| 1343 | | - .spdif = 0, |
|---|
| 1344 | 1293 | .ops = &audio_codec_ops, |
|---|
| 1345 | 1294 | .max_i2s_channels = 8, |
|---|
| 1346 | 1295 | }; |
|---|
| 1347 | | - |
|---|
| 1348 | | - if (of_property_read_string(np, "rockchip,format", &str)) |
|---|
| 1349 | | - dev_warn(dev, "can not get rockchip,format\n"); |
|---|
| 1350 | | - |
|---|
| 1351 | | - if (strstr(str, "spdif")) { |
|---|
| 1352 | | - codec_data.i2s = 0; |
|---|
| 1353 | | - codec_data.spdif = 1; |
|---|
| 1354 | | - } |
|---|
| 1355 | 1296 | |
|---|
| 1356 | 1297 | hdmi->audio_enable = false; |
|---|
| 1357 | 1298 | hdmi->audio_pdev = platform_device_register_data(dev, |
|---|
| .. | .. |
|---|
| 1581 | 1522 | dev_err(dev, "Unable to get HDMI clock\n"); |
|---|
| 1582 | 1523 | return PTR_ERR(hdmi->clock); |
|---|
| 1583 | 1524 | } |
|---|
| 1584 | | - |
|---|
| 1585 | | - /* hpd io pull down */ |
|---|
| 1586 | | - regmap_write(rk618->regmap, RK618_IO_CON0, HDMI_IO_PULL_UP_DISABLE); |
|---|
| 1587 | 1525 | |
|---|
| 1588 | 1526 | rk618_hdmi_pol_init(hdmi, 0); |
|---|
| 1589 | 1527 | rk618_hdmi_reset(hdmi); |
|---|