Skip to content

Commit f43aa58

Browse files
committed
drm/meson: meson_dw_hdmi: add bridge and switch to drm_bridge_funcs
Switch the dw-hdmi driver to drm_bridge_funcs by implementing a new local bridge, connecting it to the dw-hdmi bridge, then implement the atomic_get_input_bus_fmts/atomic_get_output_bus_fmts. Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> Reviewed-by: Jernej Škrabec <jernej.skrabec@siol.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200304104052.17196-8-narmstrong@baylibre.com
1 parent 0fad640 commit f43aa58

File tree

1 file changed

+65
-20
lines changed

1 file changed

+65
-20
lines changed

drivers/gpu/drm/meson/meson_dw_hdmi.c

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <drm/bridge/dw_hdmi.h>
1818
#include <drm/drm_atomic_helper.h>
19+
#include <drm/drm_bridge.h>
1920
#include <drm/drm_device.h>
2021
#include <drm/drm_edid.h>
2122
#include <drm/drm_probe_helper.h>
@@ -135,6 +136,7 @@ struct meson_dw_hdmi_data {
135136

136137
struct meson_dw_hdmi {
137138
struct drm_encoder encoder;
139+
struct drm_bridge bridge;
138140
struct dw_hdmi_plat_data dw_plat_data;
139141
struct meson_drm *priv;
140142
struct device *dev;
@@ -151,6 +153,8 @@ struct meson_dw_hdmi {
151153
};
152154
#define encoder_to_meson_dw_hdmi(x) \
153155
container_of(x, struct meson_dw_hdmi, encoder)
156+
#define bridge_to_meson_dw_hdmi(x) \
157+
container_of(x, struct meson_dw_hdmi, bridge)
154158

155159
static inline int dw_hdmi_is_compatible(struct meson_dw_hdmi *dw_hdmi,
156160
const char *compat)
@@ -368,7 +372,7 @@ static inline void meson_dw_hdmi_phy_reset(struct meson_dw_hdmi *dw_hdmi)
368372
}
369373

370374
static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
371-
struct drm_display_mode *mode)
375+
const struct drm_display_mode *mode)
372376
{
373377
struct meson_drm *priv = dw_hdmi->priv;
374378
int vic = drm_match_cea_mode(mode);
@@ -663,6 +667,10 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
663667

664668
/* Encoder */
665669

670+
static const u32 meson_dw_hdmi_out_bus_fmts[] = {
671+
MEDIA_BUS_FMT_YUV8_1X24,
672+
};
673+
666674
static void meson_venc_hdmi_encoder_destroy(struct drm_encoder *encoder)
667675
{
668676
drm_encoder_cleanup(encoder);
@@ -672,16 +680,43 @@ static const struct drm_encoder_funcs meson_venc_hdmi_encoder_funcs = {
672680
.destroy = meson_venc_hdmi_encoder_destroy,
673681
};
674682

675-
static int meson_venc_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
683+
static u32 *
684+
meson_venc_hdmi_encoder_get_inp_bus_fmts(struct drm_bridge *bridge,
685+
struct drm_bridge_state *bridge_state,
686+
struct drm_crtc_state *crtc_state,
687+
struct drm_connector_state *conn_state,
688+
u32 output_fmt,
689+
unsigned int *num_input_fmts)
690+
{
691+
u32 *input_fmts = NULL;
692+
693+
if (output_fmt == meson_dw_hdmi_out_bus_fmts[0]) {
694+
*num_input_fmts = 1;
695+
input_fmts = kcalloc(*num_input_fmts,
696+
sizeof(*input_fmts),
697+
GFP_KERNEL);
698+
if (!input_fmts)
699+
return NULL;
700+
701+
input_fmts[0] = output_fmt;
702+
} else {
703+
*num_input_fmts = 0;
704+
}
705+
706+
return input_fmts;
707+
}
708+
709+
static int meson_venc_hdmi_encoder_atomic_check(struct drm_bridge *bridge,
710+
struct drm_bridge_state *bridge_state,
676711
struct drm_crtc_state *crtc_state,
677712
struct drm_connector_state *conn_state)
678713
{
679714
return 0;
680715
}
681716

682-
static void meson_venc_hdmi_encoder_disable(struct drm_encoder *encoder)
717+
static void meson_venc_hdmi_encoder_disable(struct drm_bridge *bridge)
683718
{
684-
struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
719+
struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
685720
struct meson_drm *priv = dw_hdmi->priv;
686721

687722
DRM_DEBUG_DRIVER("\n");
@@ -693,9 +728,9 @@ static void meson_venc_hdmi_encoder_disable(struct drm_encoder *encoder)
693728
writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
694729
}
695730

696-
static void meson_venc_hdmi_encoder_enable(struct drm_encoder *encoder)
731+
static void meson_venc_hdmi_encoder_enable(struct drm_bridge *bridge)
697732
{
698-
struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
733+
struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
699734
struct meson_drm *priv = dw_hdmi->priv;
700735

701736
DRM_DEBUG_DRIVER("%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP");
@@ -706,11 +741,11 @@ static void meson_venc_hdmi_encoder_enable(struct drm_encoder *encoder)
706741
writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
707742
}
708743

709-
static void meson_venc_hdmi_encoder_mode_set(struct drm_encoder *encoder,
710-
struct drm_display_mode *mode,
711-
struct drm_display_mode *adjusted_mode)
744+
static void meson_venc_hdmi_encoder_mode_set(struct drm_bridge *bridge,
745+
const struct drm_display_mode *mode,
746+
const struct drm_display_mode *adjusted_mode)
712747
{
713-
struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
748+
struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
714749
struct meson_drm *priv = dw_hdmi->priv;
715750
int vic = drm_match_cea_mode(mode);
716751

@@ -726,12 +761,15 @@ static void meson_venc_hdmi_encoder_mode_set(struct drm_encoder *encoder,
726761
writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
727762
}
728763

729-
static const struct drm_encoder_helper_funcs
730-
meson_venc_hdmi_encoder_helper_funcs = {
731-
.atomic_check = meson_venc_hdmi_encoder_atomic_check,
732-
.disable = meson_venc_hdmi_encoder_disable,
733-
.enable = meson_venc_hdmi_encoder_enable,
734-
.mode_set = meson_venc_hdmi_encoder_mode_set,
764+
static const struct drm_bridge_funcs meson_venc_hdmi_encoder_bridge_funcs = {
765+
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
766+
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
767+
.atomic_get_input_bus_fmts = meson_venc_hdmi_encoder_get_inp_bus_fmts,
768+
.atomic_reset = drm_atomic_helper_bridge_reset,
769+
.atomic_check = meson_venc_hdmi_encoder_atomic_check,
770+
.enable = meson_venc_hdmi_encoder_enable,
771+
.disable = meson_venc_hdmi_encoder_disable,
772+
.mode_set = meson_venc_hdmi_encoder_mode_set,
735773
};
736774

737775
/* DW HDMI Regmap */
@@ -852,6 +890,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
852890
struct drm_device *drm = data;
853891
struct meson_drm *priv = drm->dev_private;
854892
struct dw_hdmi_plat_data *dw_plat_data;
893+
struct drm_bridge *next_bridge;
855894
struct drm_encoder *encoder;
856895
struct resource *res;
857896
int irq;
@@ -953,15 +992,16 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
953992

954993
/* Encoder */
955994

956-
drm_encoder_helper_add(encoder, &meson_venc_hdmi_encoder_helper_funcs);
957-
958995
ret = drm_encoder_init(drm, encoder, &meson_venc_hdmi_encoder_funcs,
959996
DRM_MODE_ENCODER_TMDS, "meson_hdmi");
960997
if (ret) {
961998
dev_err(priv->dev, "Failed to init HDMI encoder\n");
962999
return ret;
9631000
}
9641001

1002+
meson_dw_hdmi->bridge.funcs = &meson_venc_hdmi_encoder_bridge_funcs;
1003+
drm_bridge_attach(encoder, &meson_dw_hdmi->bridge, NULL, 0);
1004+
9651005
encoder->possible_crtcs = BIT(0);
9661006

9671007
DRM_DEBUG_DRIVER("encoder initialized\n");
@@ -984,11 +1024,16 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
9841024

9851025
platform_set_drvdata(pdev, meson_dw_hdmi);
9861026

987-
meson_dw_hdmi->hdmi = dw_hdmi_bind(pdev, encoder,
988-
&meson_dw_hdmi->dw_plat_data);
1027+
meson_dw_hdmi->hdmi = dw_hdmi_probe(pdev,
1028+
&meson_dw_hdmi->dw_plat_data);
9891029
if (IS_ERR(meson_dw_hdmi->hdmi))
9901030
return PTR_ERR(meson_dw_hdmi->hdmi);
9911031

1032+
next_bridge = of_drm_find_bridge(pdev->dev.of_node);
1033+
if (next_bridge)
1034+
drm_bridge_attach(encoder, next_bridge,
1035+
&meson_dw_hdmi->bridge, 0);
1036+
9921037
DRM_DEBUG_DRIVER("HDMI controller initialized\n");
9931038

9941039
return 0;

0 commit comments

Comments
 (0)