| .. | .. |
|---|
| 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; |
|---|
| .. | .. |
|---|
| 1105 | 1113 | = to_sti_hdmi_connector(connector); |
|---|
| 1106 | 1114 | struct sti_hdmi *hdmi = hdmi_connector->hdmi; |
|---|
| 1107 | 1115 | |
|---|
| 1108 | | - if (hdmi_debugfs_init(hdmi, hdmi->drm_dev->primary)) { |
|---|
| 1109 | | - DRM_ERROR("HDMI debugfs setup failed\n"); |
|---|
| 1110 | | - return -EINVAL; |
|---|
| 1111 | | - } |
|---|
| 1116 | + hdmi_debugfs_init(hdmi, hdmi->drm_dev->primary); |
|---|
| 1112 | 1117 | |
|---|
| 1113 | 1118 | return 0; |
|---|
| 1114 | 1119 | } |
|---|
| .. | .. |
|---|
| 1186 | 1191 | return 0; |
|---|
| 1187 | 1192 | } |
|---|
| 1188 | 1193 | |
|---|
| 1189 | | -static int hdmi_audio_digital_mute(struct device *dev, void *data, bool enable) |
|---|
| 1194 | +static int hdmi_audio_mute(struct device *dev, void *data, |
|---|
| 1195 | + bool enable, int direction) |
|---|
| 1190 | 1196 | { |
|---|
| 1191 | 1197 | struct sti_hdmi *hdmi = dev_get_drvdata(dev); |
|---|
| 1192 | 1198 | |
|---|
| .. | .. |
|---|
| 1214 | 1220 | static const struct hdmi_codec_ops audio_codec_ops = { |
|---|
| 1215 | 1221 | .hw_params = hdmi_audio_hw_params, |
|---|
| 1216 | 1222 | .audio_shutdown = hdmi_audio_shutdown, |
|---|
| 1217 | | - .digital_mute = hdmi_audio_digital_mute, |
|---|
| 1223 | + .mute_stream = hdmi_audio_mute, |
|---|
| 1218 | 1224 | .get_eld = hdmi_audio_get_eld, |
|---|
| 1225 | + .no_capture_mute = 1, |
|---|
| 1219 | 1226 | }; |
|---|
| 1220 | 1227 | |
|---|
| 1221 | 1228 | static int sti_hdmi_register_audio_driver(struct device *dev, |
|---|
| .. | .. |
|---|
| 1249 | 1256 | struct drm_device *drm_dev = data; |
|---|
| 1250 | 1257 | struct drm_encoder *encoder; |
|---|
| 1251 | 1258 | struct sti_hdmi_connector *connector; |
|---|
| 1259 | + struct cec_connector_info conn_info; |
|---|
| 1252 | 1260 | struct drm_connector *drm_connector; |
|---|
| 1253 | 1261 | struct drm_bridge *bridge; |
|---|
| 1254 | 1262 | int err; |
|---|
| .. | .. |
|---|
| 1272 | 1280 | |
|---|
| 1273 | 1281 | bridge->driver_private = hdmi; |
|---|
| 1274 | 1282 | bridge->funcs = &sti_hdmi_bridge_funcs; |
|---|
| 1275 | | - drm_bridge_attach(encoder, bridge, NULL); |
|---|
| 1283 | + drm_bridge_attach(encoder, bridge, NULL, 0); |
|---|
| 1276 | 1284 | |
|---|
| 1277 | 1285 | connector->encoder = encoder; |
|---|
| 1278 | 1286 | |
|---|
| .. | .. |
|---|
| 1280 | 1288 | |
|---|
| 1281 | 1289 | drm_connector->polled = DRM_CONNECTOR_POLL_HPD; |
|---|
| 1282 | 1290 | |
|---|
| 1283 | | - drm_connector_init(drm_dev, drm_connector, |
|---|
| 1284 | | - &sti_hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA); |
|---|
| 1291 | + drm_connector_init_with_ddc(drm_dev, drm_connector, |
|---|
| 1292 | + &sti_hdmi_connector_funcs, |
|---|
| 1293 | + DRM_MODE_CONNECTOR_HDMIA, |
|---|
| 1294 | + hdmi->ddc_adapt); |
|---|
| 1285 | 1295 | drm_connector_helper_add(drm_connector, |
|---|
| 1286 | 1296 | &sti_hdmi_connector_helper_funcs); |
|---|
| 1287 | 1297 | |
|---|
| .. | .. |
|---|
| 1309 | 1319 | goto err_sysfs; |
|---|
| 1310 | 1320 | } |
|---|
| 1311 | 1321 | |
|---|
| 1322 | + cec_fill_conn_info_from_drm(&conn_info, drm_connector); |
|---|
| 1323 | + hdmi->notifier = cec_notifier_conn_register(&hdmi->dev, NULL, |
|---|
| 1324 | + &conn_info); |
|---|
| 1325 | + if (!hdmi->notifier) { |
|---|
| 1326 | + hdmi->drm_connector = NULL; |
|---|
| 1327 | + return -ENOMEM; |
|---|
| 1328 | + } |
|---|
| 1329 | + |
|---|
| 1312 | 1330 | /* Enable default interrupts */ |
|---|
| 1313 | 1331 | hdmi_write(hdmi, HDMI_DEFAULT_INT, HDMI_INT_EN); |
|---|
| 1314 | 1332 | |
|---|
| .. | .. |
|---|
| 1322 | 1340 | static void sti_hdmi_unbind(struct device *dev, |
|---|
| 1323 | 1341 | struct device *master, void *data) |
|---|
| 1324 | 1342 | { |
|---|
| 1343 | + struct sti_hdmi *hdmi = dev_get_drvdata(dev); |
|---|
| 1344 | + |
|---|
| 1345 | + cec_notifier_conn_unregister(hdmi->notifier); |
|---|
| 1325 | 1346 | } |
|---|
| 1326 | 1347 | |
|---|
| 1327 | 1348 | static const struct component_ops sti_hdmi_ops = { |
|---|
| .. | .. |
|---|
| 1371 | 1392 | ret = -ENOMEM; |
|---|
| 1372 | 1393 | goto release_adapter; |
|---|
| 1373 | 1394 | } |
|---|
| 1374 | | - hdmi->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); |
|---|
| 1395 | + hdmi->regs = devm_ioremap(dev, res->start, resource_size(res)); |
|---|
| 1375 | 1396 | if (!hdmi->regs) { |
|---|
| 1376 | 1397 | ret = -ENOMEM; |
|---|
| 1377 | 1398 | goto release_adapter; |
|---|
| .. | .. |
|---|
| 1427 | 1448 | goto release_adapter; |
|---|
| 1428 | 1449 | } |
|---|
| 1429 | 1450 | |
|---|
| 1430 | | - hdmi->notifier = cec_notifier_get(&pdev->dev); |
|---|
| 1431 | | - if (!hdmi->notifier) |
|---|
| 1432 | | - goto release_adapter; |
|---|
| 1433 | | - |
|---|
| 1434 | 1451 | hdmi->reset = devm_reset_control_get(dev, "hdmi"); |
|---|
| 1435 | 1452 | /* Take hdmi out of reset */ |
|---|
| 1436 | 1453 | if (!IS_ERR(hdmi->reset)) |
|---|
| .. | .. |
|---|
| 1450 | 1467 | { |
|---|
| 1451 | 1468 | struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev); |
|---|
| 1452 | 1469 | |
|---|
| 1453 | | - cec_notifier_set_phys_addr(hdmi->notifier, CEC_PHYS_ADDR_INVALID); |
|---|
| 1454 | | - |
|---|
| 1455 | 1470 | i2c_put_adapter(hdmi->ddc_adapt); |
|---|
| 1456 | 1471 | if (hdmi->audio_pdev) |
|---|
| 1457 | 1472 | platform_device_unregister(hdmi->audio_pdev); |
|---|
| 1458 | 1473 | component_del(&pdev->dev, &sti_hdmi_ops); |
|---|
| 1459 | 1474 | |
|---|
| 1460 | | - cec_notifier_put(hdmi->notifier); |
|---|
| 1461 | 1475 | return 0; |
|---|
| 1462 | 1476 | } |
|---|
| 1463 | 1477 | |
|---|