[PATCH RFC 14/19] drm/bridge: Add the necessary bits to support bus format negotiation

Neil Armstrong narmstrong at baylibre.com
Thu Aug 22 11:30:24 UTC 2019


On 22/08/2019 12:34, Boris Brezillon wrote:
> On Thu, 22 Aug 2019 12:22:02 +0200
> Neil Armstrong <narmstrong at baylibre.com> wrote:
> 
>> On 22/08/2019 12:09, Boris Brezillon wrote:
>>> On Thu, 22 Aug 2019 11:29:40 +0200
>>> Neil Armstrong <narmstrong at baylibre.com> wrote:
>>>   
>>>>>>> +/**
>>>>>>> + * struct drm_bus_caps - bus capabilities
>>>>>>> + * @supported_fmts: array of MEDIA_BUS_FMT_ formats
>>>>>>> + * @num_supported_fmts: size of the supported_fmts array
>>>>>>> + *
>>>>>>> + * Used by the core to negotiate the bus format at runtime.
>>>>>>> + */
>>>>>>> +struct drm_bus_caps {
>>>>>>> +	const u32 *supported_fmts;
>>>>>>> +	unsigned int num_supported_fmts;
>>>>>>> +};
>>>>>>> +
>>>>>>>  /**
>>>>>>>   * struct drm_bridge_state - Atomic bridge state object
>>>>>>>   * @base: inherit from &drm_private_state
>>>>>>>   * @bridge: the bridge this state refers to
>>>>>>> + * @input_bus_info: input bus information
>>>>>>> + * @output_bus_info: output bus information      
>>>>>>
>>>>>> I would make this an array, to prepare for bridges that will have more
>>>>>> than one input or one output.    
>>>>>
>>>>> Hm, not sure how you'd represent that. I guess you want to support
>>>>> bridges that can activate several inputs+outputs in parallel. Do we
>>>>> even support that right now?
>>>>> Also, how do we link the input to the output in that case? By their
>>>>> position in the array? And we'd need an extra field in bus_caps to
>>>>> point to the corresponding bridge input/output port.
>>>>>
>>>>> I'm glad we can discuss all those problems, but I'd like to focus on
>>>>> what's needed right now, not what could potentially be needed in the
>>>>> future. If we can design things to be more future-proof that's great,
>>>>> but in my experience, trying to solve problems that do not exist yet
>>>>> often leads to complex designs which prove to be wrong when we try to
>>>>> apply them to real situations when they finally occur.    
>>>>
>>>> I had a thought when implementing bus format negotiation for dw-hdmi.
>>>>
>>>> Depending on the output bus-format, we could have different sets of possible
>>>> input drm_bus_caps.
>>>>
>>>> For example, if output is MEDIA_BUS_FMT_RGB888_1X24,
>>>> the input bus formats could only be MEDIA_BUS_FMT_RGB888_1X24 or MEDIA_BUS_FMT_YUV8_1X24.
>>>> Same for MEDIA_BUS_FMT_RGB101010_1X30, MEDIA_BUS_FMT_RGB121212_1X36, MEDIA_BUS_FMT_RGB161616_1X48...
>>>> And the special MEDIA_BUS_FMT_UYYVYY8_0_5X24, where input must be output.  
>>>
>>> Sounds exactly like what Laurent was describing.
>>>   
>>>>
>>>> How could we handle this ? I mean, could we have a fixed
>>>> output drm_bus_caps and be able to dynamically change the input drm_bus_caps ?  
>>>
>>> If all output ends of bridges have fixed formats (meaning that
>>> something sets it to a fixed value, like a DT prop), there's no need
>>> for negotiation at all, since the output of the previous element in
>>> the chain will force input format of the current element.
>>>   
>>>>
>>>> Adding matrix in struct drm_bridge seems over-engineered, no ?  
>>>
>>> Will have to try it to give an answer to that question :).  
>>
>> Another thought, I was thinking about a matrix with an optional callback checking
>> is this particular matrix line is possible, an example :
>>
>> struct drm_bridge_bus_fmt_assoc dw_hdmi_bus_fmt_matrix[] = {
>> 	{ MEDIA_BUS_FMT_RGB888_1X24,
>> 		{MEDIA_BUS_FMT_RGB888_1X24, MEDIA_BUS_FMT_YUV8_1X24, 0},
>> 		{dw_hdmi_bus_fmt_no_yuv420_check, NULL},
>> 	},
>> 	{ MEDIA_BUS_FMT_YUV8_1X24,
>> 		{MEDIA_BUS_FMT_YUV8_1X24, 0},
>> 		{dw_hdmi_bus_fmt_no_yuv420_check,
>> 		 dw_hdmi_bus_fmt_yuv444_check,
>> 		 NULL},
>> 	},
>> 	{ MEDIA_BUS_FMT_RGB101010_1X30,
>> 		{MEDIA_BUS_FMT_RGB101010_1X30, MEDIA_BUS_FMT_YUV10_1X30, 0},
>> 		{dw_hdmi_bus_fmt_no_yuv420_check,
>> 		 dw_hdmi_bus_fmt_rgb_10bit_check,
>> 		 NULL},
>> 	},
>> 	{ MEDIA_BUS_FMT_UYYVYY8_0_5X24,
>> 		{MEDIA_BUS_FMT_UYYVYY8_0_5X24, 0},
>> 		dw_hdmi_bus_fmt_yuv420_check,
>> 	},
>> 	{ MEDIA_BUS_FMT_UYYVYY10_0_5X30,
>> 		{MEDIA_BUS_FMT_UYYVYY8_0_5X24, 0},
>> 		{dw_hdmi_bus_fmt_yuv420_check,
>> 		 dw_hdmi_bus_fmt_yuv420_10bit_check,
>> 		 NULL},
>> 	},
>> };
>>
>> Or with some flags combinations to check on the mode and some on the edid ?
> 
> Okay, so you need to check/reject bus-formats at runtime (the mode is
> not known at attach time). Do you have an idea of what would be checked
> in those hooks?
> 

The output bus format is dependent on the mode (drm_mode_is_420_only() and drm_mode_is_420_also())
and the display info(info->hdmi.scdc.supported, info->bpc and info->color_formats).

dw_hdmi_bus_fmt_yuv420_check would check :
drm_mode_is_420_only(info, mode) || (!info->hdmi.scdc.supported && drm_mode_is_420_also(info, mode))
and if encoder supports the corresponding input mode

dw_hdmi_bus_fmt_no_yuv420_check would be reverse.

dw_hdmi_bus_fmt_yuv444_check would check :
info->color_formats & DRM_COLOR_FORMAT_YCRCB444
and if encoder supports the corresponding input mode

dw_hdmi_bus_fmt_rgb_10bit_check would check:
info->bpc >= 10
and if encoder supports the corresponding input mode

10/12/16 bit selection is best-effort (at least how intel implemented it), this means
we would put the 16/12/10bits bus-formats first and 8bit last.

Same for YUV vs RGB, we should select YUV first if encoder supports it, otherwise RGB.

Neil


More information about the dri-devel mailing list