Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/bridge: lontium-lt9611uxc: switch to HDMI audio helpers

While LT9611UXC is a DSI-to-HDMI bridge, it implements all HDMI-related
functions internally, in the firmware, thus it doesn't make sense to
implement DRM_BRIDGE_OP_HDMI. However it is possible to implement
DRM_BRIDGE_OP_HDMI_AUDIO, streamlining HDMI audio plumbing (which
includes plugged notifications and ELD handling).

Implement corresponding callbacks and trigger EDID read /
drm_connector_hdmi_audio_plugged_notify() from the hpd_notify callback.

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Link: https://patch.msgid.link/20250803-lt9611uxc-hdmi-v1-2-cb9ce1793acf@oss.qualcomm.com
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>

+49 -76
+49 -76
drivers/gpu/drm/bridge/lontium-lt9611uxc.c
··· 17 17 #include <linux/wait.h> 18 18 #include <linux/workqueue.h> 19 19 20 - #include <sound/hdmi-codec.h> 21 - 22 20 #include <drm/drm_atomic_helper.h> 23 21 #include <drm/drm_bridge.h> 24 22 #include <drm/drm_edid.h> ··· 24 26 #include <drm/drm_of.h> 25 27 #include <drm/drm_print.h> 26 28 #include <drm/drm_probe_helper.h> 29 + 30 + #include <drm/display/drm_hdmi_audio_helper.h> 27 31 28 32 #define EDID_BLOCK_SIZE 128 29 33 #define EDID_NUM_BLOCKS 2 ··· 48 48 struct device_node *dsi1_node; 49 49 struct mipi_dsi_device *dsi0; 50 50 struct mipi_dsi_device *dsi1; 51 - struct platform_device *audio_pdev; 52 51 53 52 struct gpio_desc *reset_gpio; 54 53 struct gpio_desc *enable_gpio; ··· 428 429 return drm_edid_read_custom(connector, lt9611uxc_get_edid_block, lt9611uxc); 429 430 } 430 431 432 + static void lt9611uxc_bridge_hpd_notify(struct drm_bridge *bridge, 433 + struct drm_connector *connector, 434 + enum drm_connector_status status) 435 + { 436 + const struct drm_edid *drm_edid; 437 + 438 + if (status == connector_status_disconnected) { 439 + drm_connector_hdmi_audio_plugged_notify(connector, false); 440 + drm_edid_connector_update(connector, NULL); 441 + return; 442 + } 443 + 444 + drm_edid = lt9611uxc_bridge_edid_read(bridge, connector); 445 + drm_edid_connector_update(connector, drm_edid); 446 + drm_edid_free(drm_edid); 447 + 448 + if (status == connector_status_connected) 449 + drm_connector_hdmi_audio_plugged_notify(connector, true); 450 + } 451 + 452 + static int lt9611uxc_hdmi_audio_prepare(struct drm_bridge *bridge, 453 + struct drm_connector *connector, 454 + struct hdmi_codec_daifmt *fmt, 455 + struct hdmi_codec_params *hparms) 456 + { 457 + /* 458 + * LT9611UXC will automatically detect rate and sample size, so no need 459 + * to setup anything here. 460 + */ 461 + return 0; 462 + } 463 + 464 + static void lt9611uxc_hdmi_audio_shutdown(struct drm_bridge *bridge, 465 + struct drm_connector *connector) 466 + { 467 + } 468 + 431 469 static const struct drm_bridge_funcs lt9611uxc_bridge_funcs = { 432 470 .attach = lt9611uxc_bridge_attach, 433 471 .mode_valid = lt9611uxc_bridge_mode_valid, 434 472 .mode_set = lt9611uxc_bridge_mode_set, 435 473 .detect = lt9611uxc_bridge_detect, 436 474 .edid_read = lt9611uxc_bridge_edid_read, 475 + .hpd_notify = lt9611uxc_bridge_hpd_notify, 476 + .hdmi_audio_prepare = lt9611uxc_hdmi_audio_prepare, 477 + .hdmi_audio_shutdown = lt9611uxc_hdmi_audio_shutdown, 437 478 }; 438 479 439 480 static int lt9611uxc_parse_dt(struct device *dev, ··· 545 506 lt9611uxc_unlock(lt9611uxc); 546 507 547 508 return ret < 0 ? ret : rev; 548 - } 549 - 550 - static int lt9611uxc_hdmi_hw_params(struct device *dev, void *data, 551 - struct hdmi_codec_daifmt *fmt, 552 - struct hdmi_codec_params *hparms) 553 - { 554 - /* 555 - * LT9611UXC will automatically detect rate and sample size, so no need 556 - * to setup anything here. 557 - */ 558 - return 0; 559 - } 560 - 561 - static void lt9611uxc_audio_shutdown(struct device *dev, void *data) 562 - { 563 - } 564 - 565 - static int lt9611uxc_hdmi_i2s_get_dai_id(struct snd_soc_component *component, 566 - struct device_node *endpoint, 567 - void *data) 568 - { 569 - struct of_endpoint of_ep; 570 - int ret; 571 - 572 - ret = of_graph_parse_endpoint(endpoint, &of_ep); 573 - if (ret < 0) 574 - return ret; 575 - 576 - /* 577 - * HDMI sound should be located as reg = <2> 578 - * Then, it is sound port 0 579 - */ 580 - if (of_ep.port == 2) 581 - return 0; 582 - 583 - return -EINVAL; 584 - } 585 - 586 - static const struct hdmi_codec_ops lt9611uxc_codec_ops = { 587 - .hw_params = lt9611uxc_hdmi_hw_params, 588 - .audio_shutdown = lt9611uxc_audio_shutdown, 589 - .get_dai_id = lt9611uxc_hdmi_i2s_get_dai_id, 590 - }; 591 - 592 - static int lt9611uxc_audio_init(struct device *dev, struct lt9611uxc *lt9611uxc) 593 - { 594 - struct hdmi_codec_pdata codec_data = { 595 - .ops = &lt9611uxc_codec_ops, 596 - .max_i2s_channels = 2, 597 - .i2s = 1, 598 - .data = lt9611uxc, 599 - }; 600 - 601 - lt9611uxc->audio_pdev = 602 - platform_device_register_data(dev, HDMI_CODEC_DRV_NAME, 603 - PLATFORM_DEVID_AUTO, 604 - &codec_data, sizeof(codec_data)); 605 - 606 - return PTR_ERR_OR_ZERO(lt9611uxc->audio_pdev); 607 - } 608 - 609 - static void lt9611uxc_audio_exit(struct lt9611uxc *lt9611uxc) 610 - { 611 - if (lt9611uxc->audio_pdev) { 612 - platform_device_unregister(lt9611uxc->audio_pdev); 613 - lt9611uxc->audio_pdev = NULL; 614 - } 615 509 } 616 510 617 511 #define LT9611UXC_FW_PAGE_SIZE 32 ··· 830 858 i2c_set_clientdata(client, lt9611uxc); 831 859 832 860 lt9611uxc->bridge.of_node = client->dev.of_node; 833 - lt9611uxc->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID; 861 + lt9611uxc->bridge.ops = DRM_BRIDGE_OP_DETECT | 862 + DRM_BRIDGE_OP_EDID | 863 + DRM_BRIDGE_OP_HDMI_AUDIO; 834 864 if (lt9611uxc->hpd_supported) 835 865 lt9611uxc->bridge.ops |= DRM_BRIDGE_OP_HPD; 836 866 lt9611uxc->bridge.type = DRM_MODE_CONNECTOR_HDMIA; 867 + 868 + lt9611uxc->bridge.hdmi_audio_dev = dev; 869 + lt9611uxc->bridge.hdmi_audio_max_i2s_playback_channels = 2; 870 + lt9611uxc->bridge.hdmi_audio_dai_port = 2; 837 871 838 872 drm_bridge_add(&lt9611uxc->bridge); 839 873 ··· 858 880 goto err_remove_bridge; 859 881 } 860 882 } 861 - 862 - ret = lt9611uxc_audio_init(dev, lt9611uxc); 863 - if (ret) 864 - goto err_remove_bridge; 865 883 866 884 return 0; 867 885 ··· 882 908 883 909 free_irq(client->irq, lt9611uxc); 884 910 cancel_work_sync(&lt9611uxc->work); 885 - lt9611uxc_audio_exit(lt9611uxc); 886 911 drm_bridge_remove(&lt9611uxc->bridge); 887 912 888 913 mutex_destroy(&lt9611uxc->ocm_lock);