From: Hermes Wu <Hermes.wu@xxxxxxxxxx> IT6505 supports audio form I2S to DP audio data sub stream Support audio codec operation include hw_params, audio_startup, audio_shutdown, hook_plugged_cb. In order to prevent pop noise from sink devise, delay audio by after I2S signal is enable by source. Signed-off-by: Hermes Wu <Hermes.wu@xxxxxxxxxx> --- drivers/gpu/drm/bridge/ite-it6505.c | 67 ++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index 88ef76a37fe6accacdd343839ff2569b31b18ceb..9dc58d307dae360ffab5df15e8fe8420d084c764 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -3095,18 +3095,39 @@ static int __maybe_unused it6505_audio_setup_hw_params(struct it6505 *it6505, return 0; } -static void __maybe_unused it6505_audio_shutdown(struct device *dev, void *data) +static void it6505_audio_shutdown(struct device *dev, void *data) { struct it6505 *it6505 = dev_get_drvdata(dev); + cancel_delayed_work_sync(&it6505->delayed_audio); + if (it6505->powered) it6505_disable_audio(it6505); } -static int __maybe_unused it6505_audio_hook_plugged_cb(struct device *dev, - void *data, - hdmi_codec_plugged_cb fn, - struct device *codec_dev) +static int it6505_audio_hw_params(struct device *dev, + void *data, + struct hdmi_codec_daifmt *daifmt, + struct hdmi_codec_params *params) +{ + struct it6505 *it6505 = dev_get_drvdata(dev); + + return it6505_audio_setup_hw_params(it6505, params); +} + +static int it6505_audio_startup(struct device *dev, void *data) +{ + struct it6505 *it6505 = dev_get_drvdata(dev); + + queue_delayed_work(system_wq, &it6505->delayed_audio, + msecs_to_jiffies(180)); + return 0; +} + +static int it6505_audio_hook_plugged_cb(struct device *dev, + void *data, + hdmi_codec_plugged_cb fn, + struct device *codec_dev) { struct it6505 *it6505 = data; @@ -3117,6 +3138,36 @@ static int __maybe_unused it6505_audio_hook_plugged_cb(struct device *dev, return 0; } +static const struct hdmi_codec_ops it6505_audio_codec_ops = { + .hw_params = it6505_audio_hw_params, + .audio_startup = it6505_audio_startup, + .audio_shutdown = it6505_audio_shutdown, + .hook_plugged_cb = it6505_audio_hook_plugged_cb, +}; + +static int it6505_register_audio_driver(struct device *dev) +{ + struct it6505 *it6505 = dev_get_drvdata(dev); + struct hdmi_codec_pdata codec_data = { + .ops = &it6505_audio_codec_ops, + .max_i2s_channels = 8, + .i2s = 1, + .data = it6505, + }; + struct platform_device *pdev; + + pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME, + PLATFORM_DEVID_AUTO, &codec_data, + sizeof(codec_data)); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + + INIT_DELAYED_WORK(&it6505->delayed_audio, it6505_delayed_audio); + DRM_DEV_DEBUG_DRIVER(dev, "bound to %s", HDMI_CODEC_DRV_NAME); + + return 0; +} + static inline struct it6505 *bridge_to_it6505(struct drm_bridge *bridge) { return container_of(bridge, struct it6505, bridge); @@ -3677,6 +3728,12 @@ static int it6505_i2c_probe(struct i2c_client *client) return err; } + err = it6505_register_audio_driver(dev); + if (err < 0) { + dev_err(dev, "Failed to register audio driver: %d", err); + return err; + } + INIT_WORK(&it6505->link_works, it6505_link_training_work); INIT_WORK(&it6505->hdcp_wait_ksv_list, it6505_hdcp_wait_ksv_list); INIT_DELAYED_WORK(&it6505->hdcp_work, it6505_hdcp_work); --- base-commit: fe003bcb69f7bff9ff2b30b659b004dbafe52907 change-id: 20250114-add-audio-codec-8c9d47062a6c Best regards, -- Hermes Wu <Hermes.wu@xxxxxxxxxx>