.. | .. |
---|
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 | |
---|