mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-23 07:15:57 -04:00
drm/atomic-helper: Add HDMI bridge output bus formats helper
The drm_bridge_funcs atomic_get_output_bus_fmts operation should be the same for likely every HDMI connector bridge, unless such an HDMI connector bridge has some special hardware restrictions that I cannot envision yet. To avoid code duplication and standardize on a set of media bus formats that the HDMI output color formats translate to, add a common helper function that implements this operation to the drm bridge helpers. The function returns a list of output bus formats based on the HDMI bridge's current output bits-per-component, and its bitmask of supported color formats. To guard against future expansion of DRM_OUTPUT_COLOR_FORMAT outgrowing the hweight8 call, add a BUILD_BUG_ON statement where it's used that checks for DRM_OUTPUT_COLOR_FORMAT_COUNT. The justification for not using hweight32 in all cases is that not all ISAs have a popcount instruction, and will benefit from a smaller/faster software implementation that doesn't have to operate across all bits. The justification for not defining an hweight_color depending on the value of DRM_OUTPUT_COLOR_FORMAT_COUNT is that this count enum value is only known at compile time, not at preprocessor time. Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com> Reviewed-by: Daniel Stone <daniel@fooishbar.org> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com> Link: https://patch.msgid.link/20260609-color-format-v17-7-35739b5782cc@collabora.com Signed-off-by: Daniel Stone <daniels@collabora.com>
This commit is contained in:
committed by
Daniel Stone
parent
f5873533bf
commit
3f0f770ccc
@@ -28,6 +28,7 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/dma-fence.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/media-bus-format.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
@@ -4107,3 +4108,83 @@ drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge,
|
||||
return input_fmts;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_bridge_propagate_bus_fmt);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_bridge_get_hdmi_output_bus_fmts - helper implementing
|
||||
* atomic_get_output_bus_fmts for HDMI
|
||||
* @bridge: pointer to &struct drm_bridge
|
||||
* @bridge_state: pointer to the current bridge state
|
||||
* @crtc_state: pointer to the current CRTC state
|
||||
* @conn_state: pointer to the current connector state
|
||||
* @num_output_fmts: pointer to where the number of entries in the returned array
|
||||
* will be stored. Set to 0 if unsuccessful.
|
||||
*
|
||||
* Common implementation for the &drm_bridge_funcs.atomic_get_output_bus_fmts
|
||||
* operation that's applicable to HDMI connectors.
|
||||
*
|
||||
* Returns: a newly allocated array of u32 values of length \*@num_output_fmts,
|
||||
* representing all the MEDIA_BUS_FMTS\_ for the current connector state's
|
||||
* chosen HDMI output bits per compoennt, or %NULL if it fails to allocate one.
|
||||
*/
|
||||
u32 *
|
||||
drm_atomic_helper_bridge_get_hdmi_output_bus_fmts(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state,
|
||||
unsigned int *num_output_fmts)
|
||||
{
|
||||
unsigned int num_fmts = 0;
|
||||
u32 *out_fmts;
|
||||
|
||||
/*
|
||||
* bridge->supported_formats is a bit field of BIT(enum drm_output_color_format)
|
||||
* values. The smallest hweight that is smaller than or equal to
|
||||
* %DRM_OUTPUT_COLOR_FORMAT_COUNT will do for counting set bits here.
|
||||
*/
|
||||
BUILD_BUG_ON(const_true(DRM_OUTPUT_COLOR_FORMAT_COUNT > 8));
|
||||
out_fmts = kmalloc_array(hweight8(bridge->supported_formats),
|
||||
sizeof(u32), GFP_KERNEL);
|
||||
if (!out_fmts) {
|
||||
*num_output_fmts = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (conn_state->hdmi.output_bpc) {
|
||||
case 12:
|
||||
if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444))
|
||||
out_fmts[num_fmts++] = MEDIA_BUS_FMT_RGB121212_1X36;
|
||||
if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
|
||||
out_fmts[num_fmts++] = MEDIA_BUS_FMT_YUV12_1X36;
|
||||
if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
|
||||
out_fmts[num_fmts++] = MEDIA_BUS_FMT_UYVY12_1X24;
|
||||
if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420))
|
||||
out_fmts[num_fmts++] = MEDIA_BUS_FMT_UYYVYY12_0_5X36;
|
||||
break;
|
||||
case 10:
|
||||
if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444))
|
||||
out_fmts[num_fmts++] = MEDIA_BUS_FMT_RGB101010_1X30;
|
||||
if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
|
||||
out_fmts[num_fmts++] = MEDIA_BUS_FMT_YUV10_1X30;
|
||||
if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
|
||||
out_fmts[num_fmts++] = MEDIA_BUS_FMT_UYVY10_1X20;
|
||||
if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420))
|
||||
out_fmts[num_fmts++] = MEDIA_BUS_FMT_UYYVYY10_0_5X30;
|
||||
break;
|
||||
default:
|
||||
if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444))
|
||||
out_fmts[num_fmts++] = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
|
||||
out_fmts[num_fmts++] = MEDIA_BUS_FMT_YUV8_1X24;
|
||||
if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
|
||||
out_fmts[num_fmts++] = MEDIA_BUS_FMT_UYVY8_1X16;
|
||||
if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420))
|
||||
out_fmts[num_fmts++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
|
||||
break;
|
||||
}
|
||||
|
||||
*num_output_fmts = num_fmts;
|
||||
|
||||
return out_fmts;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_bridge_get_hdmi_output_bus_fmts);
|
||||
|
||||
|
||||
@@ -295,4 +295,11 @@ drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge,
|
||||
u32 output_fmt,
|
||||
unsigned int *num_input_fmts);
|
||||
|
||||
u32 *
|
||||
drm_atomic_helper_bridge_get_hdmi_output_bus_fmts(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state,
|
||||
unsigned int *num_output_fmts);
|
||||
|
||||
#endif /* DRM_ATOMIC_HELPER_H_ */
|
||||
|
||||
Reference in New Issue
Block a user