Message ID | 20240226-dp-live-fmt-v1-4-b78c3f69c9d8@amd.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Setting live video input format for ZynqMP DPSUB | expand |
Hi, On Mon, Feb 26, 2024 at 08:44:45PM -0800, Anatoliy Klymenko wrote: > Add select_output_bus_format to CRTC atomic helpers callbacks. This > callback Will allow CRTC to participate in media bus format negotiation > over connected DRM bridge chain and impose CRTC-specific restrictions. > A good example is CRTC implemented as FPGA soft IP. This kind of CRTC will > most certainly support a single output media bus format, as supporting > multiple runtime options consumes extra FPGA resources. A variety of > options for FPGA are usually achieved by synthesizing IP with different > parameters. > > Incorporate select_output_bus_format callback into the format negotiation > stage to fix the input bus format of the first DRM bridge in the chain. > > Signed-off-by: Anatoliy Klymenko <anatoliy.klymenko@amd.com> > --- > drivers/gpu/drm/drm_bridge.c | 19 +++++++++++++++++-- > include/drm/drm_modeset_helper_vtables.h | 31 +++++++++++++++++++++++++++++++ > 2 files changed, 48 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c > index 521a71c61b16..453ae3d174b4 100644 > --- a/drivers/gpu/drm/drm_bridge.c > +++ b/drivers/gpu/drm/drm_bridge.c > @@ -32,6 +32,7 @@ > #include <drm/drm_edid.h> > #include <drm/drm_encoder.h> > #include <drm/drm_file.h> > +#include <drm/drm_modeset_helper_vtables.h> > #include <drm/drm_of.h> > #include <drm/drm_print.h> > > @@ -879,7 +880,8 @@ static int select_bus_fmt_recursive(struct drm_bridge *first_bridge, > unsigned int i, num_in_bus_fmts = 0; > struct drm_bridge_state *cur_state; > struct drm_bridge *prev_bridge; > - u32 *in_bus_fmts; > + struct drm_crtc *crtc = crtc_state->crtc; > + u32 *in_bus_fmts, in_fmt; > int ret; > > prev_bridge = drm_bridge_get_prev_bridge(cur_bridge); > @@ -933,7 +935,20 @@ static int select_bus_fmt_recursive(struct drm_bridge *first_bridge, > return -ENOMEM; > > if (first_bridge == cur_bridge) { > - cur_state->input_bus_cfg.format = in_bus_fmts[0]; > + in_fmt = in_bus_fmts[0]; > + if (crtc->helper_private && > + crtc->helper_private->select_output_bus_format) { > + in_fmt = crtc->helper_private->select_output_bus_format( > + crtc, > + crtc->state, > + in_bus_fmts, > + num_in_bus_fmts); > + if (!in_fmt) { > + kfree(in_bus_fmts); > + return -ENOTSUPP; > + } > + } > + cur_state->input_bus_cfg.format = in_fmt; I don't think we should start poking at the CRTC internals, but we should rather provide a helper here. > cur_state->output_bus_cfg.format = out_bus_fmt; > kfree(in_bus_fmts); > return 0; > diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h > index 881b03e4dc28..7c21ae1fe3ad 100644 > --- a/include/drm/drm_modeset_helper_vtables.h > +++ b/include/drm/drm_modeset_helper_vtables.h > @@ -489,6 +489,37 @@ struct drm_crtc_helper_funcs { > bool in_vblank_irq, int *vpos, int *hpos, > ktime_t *stime, ktime_t *etime, > const struct drm_display_mode *mode); > + > + /** > + * @select_output_bus_format > + * > + * Called by the first connected DRM bridge to negotiate input media > + * bus format. CRTC is expected to pick preferable media formats from > + * the list supported by the DRM bridge chain. There's nothing restricting it to bridges here. Please rephrase this to remove the bridge mention. The user is typically going to be the encoder, and bridges are just an automagic implementation of an encoder. And generally speaking, I'd really like to have an implementation available before merging this. Maxime
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 521a71c61b16..453ae3d174b4 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -32,6 +32,7 @@ #include <drm/drm_edid.h> #include <drm/drm_encoder.h> #include <drm/drm_file.h> +#include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_of.h> #include <drm/drm_print.h> @@ -879,7 +880,8 @@ static int select_bus_fmt_recursive(struct drm_bridge *first_bridge, unsigned int i, num_in_bus_fmts = 0; struct drm_bridge_state *cur_state; struct drm_bridge *prev_bridge; - u32 *in_bus_fmts; + struct drm_crtc *crtc = crtc_state->crtc; + u32 *in_bus_fmts, in_fmt; int ret; prev_bridge = drm_bridge_get_prev_bridge(cur_bridge); @@ -933,7 +935,20 @@ static int select_bus_fmt_recursive(struct drm_bridge *first_bridge, return -ENOMEM; if (first_bridge == cur_bridge) { - cur_state->input_bus_cfg.format = in_bus_fmts[0]; + in_fmt = in_bus_fmts[0]; + if (crtc->helper_private && + crtc->helper_private->select_output_bus_format) { + in_fmt = crtc->helper_private->select_output_bus_format( + crtc, + crtc->state, + in_bus_fmts, + num_in_bus_fmts); + if (!in_fmt) { + kfree(in_bus_fmts); + return -ENOTSUPP; + } + } + cur_state->input_bus_cfg.format = in_fmt; cur_state->output_bus_cfg.format = out_bus_fmt; kfree(in_bus_fmts); return 0; diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index 881b03e4dc28..7c21ae1fe3ad 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -489,6 +489,37 @@ struct drm_crtc_helper_funcs { bool in_vblank_irq, int *vpos, int *hpos, ktime_t *stime, ktime_t *etime, const struct drm_display_mode *mode); + + /** + * @select_output_bus_format + * + * Called by the first connected DRM bridge to negotiate input media + * bus format. CRTC is expected to pick preferable media formats from + * the list supported by the DRM bridge chain. + * + * This callback is optional. + * + * Parameters: + * + * crtc: + * The CRTC. + * crcs_state: + * New CRTC state. + * supported_fmts: + * List of input bus formats supported by the bridge. + * num_supported_fmts: + * Number of formats in the list. + * + * Returns: + * + * Preferred bus format from the list or 0 if CRTC doesn't support any + * from the provided list. + * + */ + u32 (*select_output_bus_format)(struct drm_crtc *crtc, + struct drm_crtc_state *crtc_state, + const u32 *supported_fmts, + int num_supported_fmts); }; /**
Add select_output_bus_format to CRTC atomic helpers callbacks. This callback Will allow CRTC to participate in media bus format negotiation over connected DRM bridge chain and impose CRTC-specific restrictions. A good example is CRTC implemented as FPGA soft IP. This kind of CRTC will most certainly support a single output media bus format, as supporting multiple runtime options consumes extra FPGA resources. A variety of options for FPGA are usually achieved by synthesizing IP with different parameters. Incorporate select_output_bus_format callback into the format negotiation stage to fix the input bus format of the first DRM bridge in the chain. Signed-off-by: Anatoliy Klymenko <anatoliy.klymenko@amd.com> --- drivers/gpu/drm/drm_bridge.c | 19 +++++++++++++++++-- include/drm/drm_modeset_helper_vtables.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-)