[PATCH v2 2/3] drm/mgag200: Add BMC output
Jocelyn Falempe
jfalempe at redhat.com
Tue Jun 11 14:40:18 UTC 2024
On 10/06/2024 16:06, Thomas Zimmermann wrote:
> The BMC output can be viewed via the BMC's web interface or a
> similar client. Represent it as virtual encoder and connector.
> It's attached to the same CRTC as the VGA connector.
>
> The connector's status depends on the physical connector's status.
> The BMC is only connected if the physical connector is not. This
> is necessary to support userspace clients that can only handle a
> single output per CRTC.
>
> The BMC is a server feature. Add a BMC output for all server chips,
> but not the desktop models.
Thanks, I think it makes thing clearer for userspace, even if it's not
perfect yet. It also allows to have bigger resolution when no vga
monitor are connected.
Reviewed-by: Jocelyn Falempe <jfalempe at redhat.com>
>
> Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de>
> ---
> drivers/gpu/drm/mgag200/mgag200_bmc.c | 107 ++++++++++++++++++++++
> drivers/gpu/drm/mgag200/mgag200_drv.h | 10 ++
> drivers/gpu/drm/mgag200/mgag200_g200eh.c | 4 +
> drivers/gpu/drm/mgag200/mgag200_g200eh3.c | 4 +
> drivers/gpu/drm/mgag200/mgag200_g200er.c | 4 +
> drivers/gpu/drm/mgag200/mgag200_g200ev.c | 4 +
> drivers/gpu/drm/mgag200/mgag200_g200ew3.c | 4 +
> drivers/gpu/drm/mgag200/mgag200_g200se.c | 4 +
> drivers/gpu/drm/mgag200/mgag200_g200wb.c | 4 +
> 9 files changed, 145 insertions(+)
>
> diff --git a/drivers/gpu/drm/mgag200/mgag200_bmc.c b/drivers/gpu/drm/mgag200/mgag200_bmc.c
> index 2ba2e3c5086a5..23ef85aa7e378 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_bmc.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_bmc.c
> @@ -2,8 +2,18 @@
>
> #include <linux/delay.h>
>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_edid.h>
> +#include <drm/drm_managed.h>
> +#include <drm/drm_probe_helper.h>
> +
> #include "mgag200_drv.h"
>
> +static struct mgag200_bmc_connector *to_mgag200_bmc_connector(struct drm_connector *connector)
> +{
> + return container_of(connector, struct mgag200_bmc_connector, base);
> +}
> +
> void mgag200_bmc_disable_vidrst(struct mga_device *mdev)
> {
> u8 tmp;
> @@ -97,3 +107,100 @@ void mgag200_bmc_enable_vidrst(struct mga_device *mdev)
> tmp &= ~0x10;
> WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
> }
> +
> +static const struct drm_encoder_funcs mgag200_bmc_encoder_funcs = {
> + .destroy = drm_encoder_cleanup,
> +};
> +
> +static int mgag200_bmc_connector_helper_detect_ctx(struct drm_connector *connector,
> + struct drm_modeset_acquire_ctx *ctx,
> + bool force)
> +{
> + struct mgag200_bmc_connector *bmc_connector = to_mgag200_bmc_connector(connector);
> + struct drm_connector *physical_connector = bmc_connector->physical_connector;
> +
> + /*
> + * Most user-space compositors cannot handle more than one connected
> + * connector per CRTC. Hence, we only mark the BMC as connected if the
> + * physical connector is disconnected. If the physical connector's status
> + * is connected or unknown, the BMC remains disconnected. This has no
> + * effect on the output of the BMC.
> + *
> + * FIXME: Remove this logic once user-space compositors can handle more
> + * than one connector per CRTC. The BMC should always be connected.
> + */
> +
> + if (physical_connector && physical_connector->status == connector_status_disconnected)
> + return connector_status_connected;
> +
> + return connector_status_disconnected;
> +}
> +
> +static int mgag200_bmc_connector_helper_get_modes(struct drm_connector *connector)
> +{
> + struct drm_device *dev = connector->dev;
> + struct mga_device *mdev = to_mga_device(dev);
> + const struct mgag200_device_info *minfo = mdev->info;
> +
> + return drm_add_modes_noedid(connector, minfo->max_hdisplay, minfo->max_vdisplay);
> +}
> +
> +static const struct drm_connector_helper_funcs mgag200_bmc_connector_helper_funcs = {
> + .get_modes = mgag200_bmc_connector_helper_get_modes,
> + .detect_ctx = mgag200_bmc_connector_helper_detect_ctx,
> +};
> +
> +static const struct drm_connector_funcs mgag200_bmc_connector_funcs = {
> + .reset = drm_atomic_helper_connector_reset,
> + .fill_modes = drm_helper_probe_single_connector_modes,
> + .destroy = drm_connector_cleanup,
> + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int mgag200_bmc_connector_init(struct drm_device *dev,
> + struct mgag200_bmc_connector *bmc_connector,
> + struct drm_connector *physical_connector)
> +{
> + struct drm_connector *connector = &bmc_connector->base;
> + int ret;
> +
> + ret = drm_connector_init(dev, connector, &mgag200_bmc_connector_funcs,
> + DRM_MODE_CONNECTOR_VIRTUAL);
> + if (ret)
> + return ret;
> + drm_connector_helper_add(connector, &mgag200_bmc_connector_helper_funcs);
> +
> + bmc_connector->physical_connector = physical_connector;
> +
> + return 0;
> +}
> +
> +int mgag200_bmc_output_init(struct mga_device *mdev, struct drm_connector *physical_connector)
> +{
> + struct drm_device *dev = &mdev->base;
> + struct drm_crtc *crtc = &mdev->crtc;
> + struct drm_encoder *encoder;
> + struct mgag200_bmc_connector *bmc_connector;
> + struct drm_connector *connector;
> + int ret;
> +
> + encoder = &mdev->output.bmc.encoder;
> + ret = drm_encoder_init(dev, encoder, &mgag200_bmc_encoder_funcs,
> + DRM_MODE_ENCODER_VIRTUAL, NULL);
> + if (ret)
> + return ret;
> + encoder->possible_crtcs = drm_crtc_mask(crtc);
> +
> + bmc_connector = &mdev->output.bmc.bmc_connector;
> + ret = mgag200_bmc_connector_init(dev, bmc_connector, physical_connector);
> + if (ret)
> + return ret;
> + connector = &bmc_connector->base;
> +
> + ret = drm_connector_attach_encoder(connector, encoder);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
> index db89fddc26dcb..7f7dfbd0f0134 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_drv.h
> +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
> @@ -186,6 +186,11 @@ static inline struct mgag200_crtc_state *to_mgag200_crtc_state(struct drm_crtc_s
> return container_of(base, struct mgag200_crtc_state, base);
> }
>
> +struct mgag200_bmc_connector {
> + struct drm_connector base;
> + struct drm_connector *physical_connector;
> +};
> +
> enum mga_type {
> G200_PCI,
> G200_AGP,
> @@ -288,6 +293,10 @@ struct mga_device {
> struct drm_encoder encoder;
> struct drm_connector connector;
> } vga;
> + struct {
> + struct drm_encoder encoder;
> + struct mgag200_bmc_connector bmc_connector;
> + } bmc;
> } output;
> };
>
> @@ -433,5 +442,6 @@ int mgag200_vga_output_init(struct mga_device *mdev);
> /* mgag200_bmc.c */
> void mgag200_bmc_disable_vidrst(struct mga_device *mdev);
> void mgag200_bmc_enable_vidrst(struct mga_device *mdev);
> +int mgag200_bmc_output_init(struct mga_device *mdev, struct drm_connector *physical_connector);
>
> #endif /* __MGAG200_DRV_H__ */
> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
> index df00b25efb895..6f31c5249f0b1 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c
> @@ -218,6 +218,10 @@ static int mgag200_g200eh_pipeline_init(struct mga_device *mdev)
> if (ret)
> return ret;
>
> + ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
> + if (ret)
> + return ret;
> +
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
> index be42b1291e357..5befe8da4beb2 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c
> @@ -122,6 +122,10 @@ static int mgag200_g200eh3_pipeline_init(struct mga_device *mdev)
> if (ret)
> return ret;
>
> + ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
> + if (ret)
> + return ret;
> +
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mgag200/mgag200_g200er.c
> index 6f2c07af38c4f..55c275180cde2 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_g200er.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c
> @@ -261,6 +261,10 @@ static int mgag200_g200er_pipeline_init(struct mga_device *mdev)
> if (ret)
> return ret;
>
> + ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
> + if (ret)
> + return ret;
> +
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
> index 908d04d4c862c..2466126140db6 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c
> @@ -262,6 +262,10 @@ static int mgag200_g200ev_pipeline_init(struct mga_device *mdev)
> if (ret)
> return ret;
>
> + ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
> + if (ret)
> + return ret;
> +
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
> index 8b69af543e2be..a52e60609c3de 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c
> @@ -131,6 +131,10 @@ static int mgag200_g200ew3_pipeline_init(struct mga_device *mdev)
> if (ret)
> return ret;
>
> + ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
> + if (ret)
> + return ret;
> +
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c
> index 6d7fbdf62b97a..212770acdd477 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_g200se.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c
> @@ -393,6 +393,10 @@ static int mgag200_g200se_pipeline_init(struct mga_device *mdev)
> if (ret)
> return ret;
>
> + ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
> + if (ret)
> + return ret;
> +
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
> index 564d1f3ecc108..cb6daa0426fbc 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c
> @@ -265,6 +265,10 @@ static int mgag200_g200wb_pipeline_init(struct mga_device *mdev)
> if (ret)
> return ret;
>
> + ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
> + if (ret)
> + return ret;
> +
> return 0;
> }
>
More information about the dri-devel
mailing list