Skip to content

Commit 0beba3f

Browse files
committed
drm/bridge: connector: add support for HDMI codec framework
Add necessary glue code to be able to use new HDMI codec framework from the DRM bridge drivers. The drm_bridge implements a limited set of the hdmi_codec_ops interface, with the functions accepting both drm_connector and drm_bridge instead of just a generic void pointer. This framework is integrated with the DRM HDMI Connector framework, but can also be used for DisplayPort connectors. Reviewed-by: Maxime Ripard <[email protected]> Tested-by: Dave Stevenson <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] Signed-off-by: Dmitry Baryshkov <[email protected]>
1 parent baf6166 commit 0beba3f

File tree

3 files changed

+170
-4
lines changed

3 files changed

+170
-4
lines changed

drivers/gpu/drm/display/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ if DRM_DISPLAY_HELPER
1515

1616
config DRM_BRIDGE_CONNECTOR
1717
bool
18+
select DRM_DISPLAY_HDMI_AUDIO_HELPER
1819
select DRM_DISPLAY_HDMI_STATE_HELPER
1920
help
2021
DRM connector implementation terminating DRM bridge chains.

drivers/gpu/drm/display/drm_bridge_connector.c

Lines changed: 95 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <drm/drm_managed.h>
1919
#include <drm/drm_modeset_helper_vtables.h>
2020
#include <drm/drm_probe_helper.h>
21+
#include <drm/display/drm_hdmi_audio_helper.h>
2122
#include <drm/display/drm_hdmi_helper.h>
2223
#include <drm/display/drm_hdmi_state_helper.h>
2324

@@ -387,6 +388,75 @@ static const struct drm_connector_hdmi_funcs drm_bridge_connector_hdmi_funcs = {
387388
.write_infoframe = drm_bridge_connector_write_infoframe,
388389
};
389390

391+
static int drm_bridge_connector_audio_startup(struct drm_connector *connector)
392+
{
393+
struct drm_bridge_connector *bridge_connector =
394+
to_drm_bridge_connector(connector);
395+
struct drm_bridge *bridge;
396+
397+
bridge = bridge_connector->bridge_hdmi;
398+
if (!bridge)
399+
return -EINVAL;
400+
401+
if (!bridge->funcs->hdmi_audio_startup)
402+
return 0;
403+
404+
return bridge->funcs->hdmi_audio_startup(connector, bridge);
405+
}
406+
407+
static int drm_bridge_connector_audio_prepare(struct drm_connector *connector,
408+
struct hdmi_codec_daifmt *fmt,
409+
struct hdmi_codec_params *hparms)
410+
{
411+
struct drm_bridge_connector *bridge_connector =
412+
to_drm_bridge_connector(connector);
413+
struct drm_bridge *bridge;
414+
415+
bridge = bridge_connector->bridge_hdmi;
416+
if (!bridge)
417+
return -EINVAL;
418+
419+
return bridge->funcs->hdmi_audio_prepare(connector, bridge, fmt, hparms);
420+
}
421+
422+
static void drm_bridge_connector_audio_shutdown(struct drm_connector *connector)
423+
{
424+
struct drm_bridge_connector *bridge_connector =
425+
to_drm_bridge_connector(connector);
426+
struct drm_bridge *bridge;
427+
428+
bridge = bridge_connector->bridge_hdmi;
429+
if (!bridge)
430+
return;
431+
432+
bridge->funcs->hdmi_audio_shutdown(connector, bridge);
433+
}
434+
435+
static int drm_bridge_connector_audio_mute_stream(struct drm_connector *connector,
436+
bool enable, int direction)
437+
{
438+
struct drm_bridge_connector *bridge_connector =
439+
to_drm_bridge_connector(connector);
440+
struct drm_bridge *bridge;
441+
442+
bridge = bridge_connector->bridge_hdmi;
443+
if (!bridge)
444+
return -EINVAL;
445+
446+
if (bridge->funcs->hdmi_audio_mute_stream)
447+
return bridge->funcs->hdmi_audio_mute_stream(connector, bridge,
448+
enable, direction);
449+
else
450+
return -ENOTSUPP;
451+
}
452+
453+
static const struct drm_connector_hdmi_audio_funcs drm_bridge_connector_hdmi_audio_funcs = {
454+
.startup = drm_bridge_connector_audio_startup,
455+
.prepare = drm_bridge_connector_audio_prepare,
456+
.shutdown = drm_bridge_connector_audio_shutdown,
457+
.mute_stream = drm_bridge_connector_audio_mute_stream,
458+
};
459+
390460
/* -----------------------------------------------------------------------------
391461
* Bridge Connector Initialisation
392462
*/
@@ -486,7 +556,9 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
486556
if (connector_type == DRM_MODE_CONNECTOR_Unknown)
487557
return ERR_PTR(-EINVAL);
488558

489-
if (bridge_connector->bridge_hdmi)
559+
if (bridge_connector->bridge_hdmi) {
560+
bridge = bridge_connector->bridge_hdmi;
561+
490562
ret = drmm_connector_hdmi_init(drm, connector,
491563
bridge_connector->bridge_hdmi->vendor,
492564
bridge_connector->bridge_hdmi->product,
@@ -495,12 +567,31 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
495567
connector_type, ddc,
496568
supported_formats,
497569
max_bpc);
498-
else
570+
if (ret)
571+
return ERR_PTR(ret);
572+
573+
if (bridge->hdmi_audio_max_i2s_playback_channels ||
574+
bridge->hdmi_audio_spdif_playback) {
575+
if (!bridge->funcs->hdmi_audio_prepare ||
576+
!bridge->funcs->hdmi_audio_shutdown)
577+
return ERR_PTR(-EINVAL);
578+
579+
ret = drm_connector_hdmi_audio_init(connector,
580+
bridge->hdmi_audio_dev,
581+
&drm_bridge_connector_hdmi_audio_funcs,
582+
bridge->hdmi_audio_max_i2s_playback_channels,
583+
bridge->hdmi_audio_spdif_playback,
584+
bridge->hdmi_audio_dai_port);
585+
if (ret)
586+
return ERR_PTR(ret);
587+
}
588+
} else {
499589
ret = drmm_connector_init(drm, connector,
500590
&drm_bridge_connector_funcs,
501591
connector_type, ddc);
502-
if (ret)
503-
return ERR_PTR(ret);
592+
if (ret)
593+
return ERR_PTR(ret);
594+
}
504595

505596
drm_connector_helper_add(connector, &drm_bridge_connector_helper_funcs);
506597

include/drm/drm_bridge.h

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ struct drm_display_info;
4141
struct drm_minor;
4242
struct drm_panel;
4343
struct edid;
44+
struct hdmi_codec_daifmt;
45+
struct hdmi_codec_params;
4446
struct i2c_adapter;
4547

4648
/**
@@ -676,6 +678,57 @@ struct drm_bridge_funcs {
676678
enum hdmi_infoframe_type type,
677679
const u8 *buffer, size_t len);
678680

681+
/**
682+
* @hdmi_audio_startup:
683+
*
684+
* Called when ASoC starts an audio stream setup. The
685+
* @hdmi_audio_startup() is optional.
686+
*
687+
* Returns:
688+
* 0 on success, a negative error code otherwise
689+
*/
690+
int (*hdmi_audio_startup)(struct drm_connector *connector,
691+
struct drm_bridge *bridge);
692+
693+
/**
694+
* @prepare:
695+
* Configures HDMI-encoder for audio stream. Can be called multiple
696+
* times for each setup. Mandatory if HDMI audio is enabled in the
697+
* bridge's configuration.
698+
*
699+
* Returns:
700+
* 0 on success, a negative error code otherwise
701+
*/
702+
int (*hdmi_audio_prepare)(struct drm_connector *connector,
703+
struct drm_bridge *bridge,
704+
struct hdmi_codec_daifmt *fmt,
705+
struct hdmi_codec_params *hparms);
706+
707+
/**
708+
* @hdmi_audio_shutdown:
709+
*
710+
* Shut down the audio stream. Mandatory if HDMI audio is enabled in
711+
* the bridge's configuration.
712+
*
713+
* Returns:
714+
* 0 on success, a negative error code otherwise
715+
*/
716+
void (*hdmi_audio_shutdown)(struct drm_connector *connector,
717+
struct drm_bridge *bridge);
718+
719+
/**
720+
* @hdmi_audio_mute_stream:
721+
*
722+
* Mute/unmute HDMI audio stream. The @hdmi_audio_mute_stream callback
723+
* is optional.
724+
*
725+
* Returns:
726+
* 0 on success, a negative error code otherwise
727+
*/
728+
int (*hdmi_audio_mute_stream)(struct drm_connector *connector,
729+
struct drm_bridge *bridge,
730+
bool enable, int direction);
731+
679732
/**
680733
* @debugfs_init:
681734
*
@@ -859,6 +912,27 @@ struct drm_bridge {
859912
* @DRM_BRIDGE_OP_HDMI is set.
860913
*/
861914
unsigned int max_bpc;
915+
916+
/**
917+
* @hdmi_audio_dev: device to be used as a parent for the HDMI Codec
918+
*/
919+
struct device *hdmi_audio_dev;
920+
921+
/**
922+
* @hdmi_audio_max_i2s_playback_channels: maximum number of playback
923+
* I2S channels for the HDMI codec
924+
*/
925+
int hdmi_audio_max_i2s_playback_channels;
926+
927+
/**
928+
* @hdmi_audio_spdif_playback: set if HDMI codec has S/PDIF playback port
929+
*/
930+
unsigned int hdmi_audio_spdif_playback : 1;
931+
932+
/**
933+
* @hdmi_audio_dai_port: sound DAI port, -1 if it is not enabled
934+
*/
935+
int hdmi_audio_dai_port;
862936
};
863937

864938
static inline struct drm_bridge *

0 commit comments

Comments
 (0)