| .. | .. |
|---|
| 9 | 9 | #include <linux/debugfs.h> |
|---|
| 10 | 10 | #include <linux/hdmi.h> |
|---|
| 11 | 11 | #include <linux/module.h> |
|---|
| 12 | | -#include <linux/of_gpio.h> |
|---|
| 12 | +#include <linux/io.h> |
|---|
| 13 | 13 | #include <linux/platform_device.h> |
|---|
| 14 | 14 | #include <linux/reset.h> |
|---|
| 15 | 15 | |
|---|
| 16 | | -#include <drm/drmP.h> |
|---|
| 17 | 16 | #include <drm/drm_atomic_helper.h> |
|---|
| 18 | | -#include <drm/drm_crtc_helper.h> |
|---|
| 17 | +#include <drm/drm_bridge.h> |
|---|
| 18 | +#include <drm/drm_debugfs.h> |
|---|
| 19 | +#include <drm/drm_drv.h> |
|---|
| 19 | 20 | #include <drm/drm_edid.h> |
|---|
| 21 | +#include <drm/drm_file.h> |
|---|
| 22 | +#include <drm/drm_print.h> |
|---|
| 23 | +#include <drm/drm_probe_helper.h> |
|---|
| 20 | 24 | |
|---|
| 21 | 25 | #include <sound/hdmi-codec.h> |
|---|
| 22 | 26 | |
|---|
| .. | .. |
|---|
| 330 | 334 | * Helper to concatenate infoframe in 32 bits word |
|---|
| 331 | 335 | * |
|---|
| 332 | 336 | * @ptr: pointer on the hdmi internal structure |
|---|
| 333 | | - * @data: infoframe to write |
|---|
| 334 | 337 | * @size: size to write |
|---|
| 335 | 338 | */ |
|---|
| 336 | 339 | static inline unsigned int hdmi_infoframe_subpack(const u8 *ptr, size_t size) |
|---|
| .. | .. |
|---|
| 434 | 437 | |
|---|
| 435 | 438 | DRM_DEBUG_DRIVER("\n"); |
|---|
| 436 | 439 | |
|---|
| 437 | | - ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode, false); |
|---|
| 440 | + ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, |
|---|
| 441 | + hdmi->drm_connector, mode); |
|---|
| 438 | 442 | if (ret < 0) { |
|---|
| 439 | 443 | DRM_ERROR("failed to setup AVI infoframe: %d\n", ret); |
|---|
| 440 | 444 | return ret; |
|---|
| .. | .. |
|---|
| 539 | 543 | return 0; |
|---|
| 540 | 544 | } |
|---|
| 541 | 545 | |
|---|
| 546 | +#define HDMI_TIMEOUT_SWRESET 100 /*milliseconds */ |
|---|
| 547 | + |
|---|
| 542 | 548 | /** |
|---|
| 543 | 549 | * Software reset of the hdmi subsystem |
|---|
| 544 | 550 | * |
|---|
| 545 | 551 | * @hdmi: pointer on the hdmi internal structure |
|---|
| 546 | 552 | * |
|---|
| 547 | 553 | */ |
|---|
| 548 | | -#define HDMI_TIMEOUT_SWRESET 100 /*milliseconds */ |
|---|
| 549 | 554 | static void hdmi_swreset(struct sti_hdmi *hdmi) |
|---|
| 550 | 555 | { |
|---|
| 551 | 556 | u32 val; |
|---|
| .. | .. |
|---|
| 722 | 727 | { "hdmi", hdmi_dbg_show, 0, NULL }, |
|---|
| 723 | 728 | }; |
|---|
| 724 | 729 | |
|---|
| 725 | | -static int hdmi_debugfs_init(struct sti_hdmi *hdmi, struct drm_minor *minor) |
|---|
| 730 | +static void hdmi_debugfs_init(struct sti_hdmi *hdmi, struct drm_minor *minor) |
|---|
| 726 | 731 | { |
|---|
| 727 | 732 | unsigned int i; |
|---|
| 728 | 733 | |
|---|
| 729 | 734 | for (i = 0; i < ARRAY_SIZE(hdmi_debugfs_files); i++) |
|---|
| 730 | 735 | hdmi_debugfs_files[i].data = hdmi; |
|---|
| 731 | 736 | |
|---|
| 732 | | - return drm_debugfs_create_files(hdmi_debugfs_files, |
|---|
| 733 | | - ARRAY_SIZE(hdmi_debugfs_files), |
|---|
| 734 | | - minor->debugfs_root, minor); |
|---|
| 737 | + drm_debugfs_create_files(hdmi_debugfs_files, |
|---|
| 738 | + ARRAY_SIZE(hdmi_debugfs_files), |
|---|
| 739 | + minor->debugfs_root, minor); |
|---|
| 735 | 740 | } |
|---|
| 736 | 741 | |
|---|
| 737 | 742 | static void sti_hdmi_disable(struct drm_bridge *bridge) |
|---|
| .. | .. |
|---|
| 845 | 850 | switch (info->channels) { |
|---|
| 846 | 851 | case 8: |
|---|
| 847 | 852 | audio_cfg |= HDMI_AUD_CFG_CH78_VALID; |
|---|
| 853 | + fallthrough; |
|---|
| 848 | 854 | case 6: |
|---|
| 849 | 855 | audio_cfg |= HDMI_AUD_CFG_CH56_VALID; |
|---|
| 856 | + fallthrough; |
|---|
| 850 | 857 | case 4: |
|---|
| 851 | 858 | audio_cfg |= HDMI_AUD_CFG_CH34_VALID | HDMI_AUD_CFG_8CH; |
|---|
| 859 | + fallthrough; |
|---|
| 852 | 860 | case 2: |
|---|
| 853 | 861 | audio_cfg |= HDMI_AUD_CFG_CH12_VALID; |
|---|
| 854 | 862 | break; |
|---|
| .. | .. |
|---|
| 917 | 925 | } |
|---|
| 918 | 926 | |
|---|
| 919 | 927 | static void sti_hdmi_set_mode(struct drm_bridge *bridge, |
|---|
| 920 | | - struct drm_display_mode *mode, |
|---|
| 921 | | - struct drm_display_mode *adjusted_mode) |
|---|
| 928 | + const struct drm_display_mode *mode, |
|---|
| 929 | + const struct drm_display_mode *adjusted_mode) |
|---|
| 922 | 930 | { |
|---|
| 923 | 931 | struct sti_hdmi *hdmi = bridge->driver_private; |
|---|
| 924 | 932 | int ret; |
|---|
| .. | .. |
|---|
| 926 | 934 | DRM_DEBUG_DRIVER("\n"); |
|---|
| 927 | 935 | |
|---|
| 928 | 936 | /* Copy the drm display mode in the connector local structure */ |
|---|
| 929 | | - memcpy(&hdmi->mode, mode, sizeof(struct drm_display_mode)); |
|---|
| 937 | + drm_mode_copy(&hdmi->mode, mode); |
|---|
| 930 | 938 | |
|---|
| 931 | 939 | /* Update clock framerate according to the selected mode */ |
|---|
| 932 | 940 | ret = clk_set_rate(hdmi->clk_pix, mode->clock * 1000); |
|---|
| .. | .. |
|---|
| 989 | 997 | |
|---|
| 990 | 998 | #define CLK_TOLERANCE_HZ 50 |
|---|
| 991 | 999 | |
|---|
| 992 | | -static int sti_hdmi_connector_mode_valid(struct drm_connector *connector, |
|---|
| 993 | | - struct drm_display_mode *mode) |
|---|
| 1000 | +static enum drm_mode_status |
|---|
| 1001 | +sti_hdmi_connector_mode_valid(struct drm_connector *connector, |
|---|
| 1002 | + struct drm_display_mode *mode) |
|---|
| 994 | 1003 | { |
|---|
| 995 | 1004 | int target = mode->clock * 1000; |
|---|
| 996 | 1005 | int target_min = target - CLK_TOLERANCE_HZ; |
|---|
| .. | .. |
|---|
| 1105 | 1114 | = to_sti_hdmi_connector(connector); |
|---|
| 1106 | 1115 | struct sti_hdmi *hdmi = hdmi_connector->hdmi; |
|---|
| 1107 | 1116 | |
|---|
| 1108 | | - if (hdmi_debugfs_init(hdmi, hdmi->drm_dev->primary)) { |
|---|
| 1109 | | - DRM_ERROR("HDMI debugfs setup failed\n"); |
|---|
| 1110 | | - return -EINVAL; |
|---|
| 1111 | | - } |
|---|
| 1117 | + hdmi_debugfs_init(hdmi, hdmi->drm_dev->primary); |
|---|
| 1112 | 1118 | |
|---|
| 1113 | 1119 | return 0; |
|---|
| 1114 | 1120 | } |
|---|
| .. | .. |
|---|
| 1186 | 1192 | return 0; |
|---|
| 1187 | 1193 | } |
|---|
| 1188 | 1194 | |
|---|
| 1189 | | -static int hdmi_audio_digital_mute(struct device *dev, void *data, bool enable) |
|---|
| 1195 | +static int hdmi_audio_mute(struct device *dev, void *data, |
|---|
| 1196 | + bool enable, int direction) |
|---|
| 1190 | 1197 | { |
|---|
| 1191 | 1198 | struct sti_hdmi *hdmi = dev_get_drvdata(dev); |
|---|
| 1192 | 1199 | |
|---|
| .. | .. |
|---|
| 1214 | 1221 | static const struct hdmi_codec_ops audio_codec_ops = { |
|---|
| 1215 | 1222 | .hw_params = hdmi_audio_hw_params, |
|---|
| 1216 | 1223 | .audio_shutdown = hdmi_audio_shutdown, |
|---|
| 1217 | | - .digital_mute = hdmi_audio_digital_mute, |
|---|
| 1224 | + .mute_stream = hdmi_audio_mute, |
|---|
| 1218 | 1225 | .get_eld = hdmi_audio_get_eld, |
|---|
| 1226 | + .no_capture_mute = 1, |
|---|
| 1219 | 1227 | }; |
|---|
| 1220 | 1228 | |
|---|
| 1221 | 1229 | static int sti_hdmi_register_audio_driver(struct device *dev, |
|---|
| .. | .. |
|---|
| 1249 | 1257 | struct drm_device *drm_dev = data; |
|---|
| 1250 | 1258 | struct drm_encoder *encoder; |
|---|
| 1251 | 1259 | struct sti_hdmi_connector *connector; |
|---|
| 1260 | + struct cec_connector_info conn_info; |
|---|
| 1252 | 1261 | struct drm_connector *drm_connector; |
|---|
| 1253 | 1262 | struct drm_bridge *bridge; |
|---|
| 1254 | 1263 | int err; |
|---|
| .. | .. |
|---|
| 1272 | 1281 | |
|---|
| 1273 | 1282 | bridge->driver_private = hdmi; |
|---|
| 1274 | 1283 | bridge->funcs = &sti_hdmi_bridge_funcs; |
|---|
| 1275 | | - drm_bridge_attach(encoder, bridge, NULL); |
|---|
| 1284 | + drm_bridge_attach(encoder, bridge, NULL, 0); |
|---|
| 1276 | 1285 | |
|---|
| 1277 | 1286 | connector->encoder = encoder; |
|---|
| 1278 | 1287 | |
|---|
| .. | .. |
|---|
| 1280 | 1289 | |
|---|
| 1281 | 1290 | drm_connector->polled = DRM_CONNECTOR_POLL_HPD; |
|---|
| 1282 | 1291 | |
|---|
| 1283 | | - drm_connector_init(drm_dev, drm_connector, |
|---|
| 1284 | | - &sti_hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA); |
|---|
| 1292 | + drm_connector_init_with_ddc(drm_dev, drm_connector, |
|---|
| 1293 | + &sti_hdmi_connector_funcs, |
|---|
| 1294 | + DRM_MODE_CONNECTOR_HDMIA, |
|---|
| 1295 | + hdmi->ddc_adapt); |
|---|
| 1285 | 1296 | drm_connector_helper_add(drm_connector, |
|---|
| 1286 | 1297 | &sti_hdmi_connector_helper_funcs); |
|---|
| 1287 | 1298 | |
|---|
| .. | .. |
|---|
| 1309 | 1320 | goto err_sysfs; |
|---|
| 1310 | 1321 | } |
|---|
| 1311 | 1322 | |
|---|
| 1323 | + cec_fill_conn_info_from_drm(&conn_info, drm_connector); |
|---|
| 1324 | + hdmi->notifier = cec_notifier_conn_register(&hdmi->dev, NULL, |
|---|
| 1325 | + &conn_info); |
|---|
| 1326 | + if (!hdmi->notifier) { |
|---|
| 1327 | + hdmi->drm_connector = NULL; |
|---|
| 1328 | + return -ENOMEM; |
|---|
| 1329 | + } |
|---|
| 1330 | + |
|---|
| 1312 | 1331 | /* Enable default interrupts */ |
|---|
| 1313 | 1332 | hdmi_write(hdmi, HDMI_DEFAULT_INT, HDMI_INT_EN); |
|---|
| 1314 | 1333 | |
|---|
| .. | .. |
|---|
| 1322 | 1341 | static void sti_hdmi_unbind(struct device *dev, |
|---|
| 1323 | 1342 | struct device *master, void *data) |
|---|
| 1324 | 1343 | { |
|---|
| 1344 | + struct sti_hdmi *hdmi = dev_get_drvdata(dev); |
|---|
| 1345 | + |
|---|
| 1346 | + cec_notifier_conn_unregister(hdmi->notifier); |
|---|
| 1325 | 1347 | } |
|---|
| 1326 | 1348 | |
|---|
| 1327 | 1349 | static const struct component_ops sti_hdmi_ops = { |
|---|
| .. | .. |
|---|
| 1371 | 1393 | ret = -ENOMEM; |
|---|
| 1372 | 1394 | goto release_adapter; |
|---|
| 1373 | 1395 | } |
|---|
| 1374 | | - hdmi->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); |
|---|
| 1396 | + hdmi->regs = devm_ioremap(dev, res->start, resource_size(res)); |
|---|
| 1375 | 1397 | if (!hdmi->regs) { |
|---|
| 1376 | 1398 | ret = -ENOMEM; |
|---|
| 1377 | 1399 | goto release_adapter; |
|---|
| .. | .. |
|---|
| 1427 | 1449 | goto release_adapter; |
|---|
| 1428 | 1450 | } |
|---|
| 1429 | 1451 | |
|---|
| 1430 | | - hdmi->notifier = cec_notifier_get(&pdev->dev); |
|---|
| 1431 | | - if (!hdmi->notifier) |
|---|
| 1432 | | - goto release_adapter; |
|---|
| 1433 | | - |
|---|
| 1434 | 1452 | hdmi->reset = devm_reset_control_get(dev, "hdmi"); |
|---|
| 1435 | 1453 | /* Take hdmi out of reset */ |
|---|
| 1436 | 1454 | if (!IS_ERR(hdmi->reset)) |
|---|
| .. | .. |
|---|
| 1450 | 1468 | { |
|---|
| 1451 | 1469 | struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev); |
|---|
| 1452 | 1470 | |
|---|
| 1453 | | - cec_notifier_set_phys_addr(hdmi->notifier, CEC_PHYS_ADDR_INVALID); |
|---|
| 1454 | | - |
|---|
| 1455 | 1471 | i2c_put_adapter(hdmi->ddc_adapt); |
|---|
| 1456 | 1472 | if (hdmi->audio_pdev) |
|---|
| 1457 | 1473 | platform_device_unregister(hdmi->audio_pdev); |
|---|
| 1458 | 1474 | component_del(&pdev->dev, &sti_hdmi_ops); |
|---|
| 1459 | 1475 | |
|---|
| 1460 | | - cec_notifier_put(hdmi->notifier); |
|---|
| 1461 | 1476 | return 0; |
|---|
| 1462 | 1477 | } |
|---|
| 1463 | 1478 | |
|---|