[PATCH 2/2] drm/radeon: use a fetch function to get the edid

Daniel Vetter daniel at ffwll.ch
Tue Jul 15 09:51:13 PDT 2014


On Tue, Jul 15, 2014 at 5:44 PM, Alex Deucher <alexdeucher at gmail.com> wrote:
> On Tue, Jul 15, 2014 at 11:18 AM, Daniel Vetter <daniel at ffwll.ch> wrote:
>> On Tue, Jul 15, 2014 at 11:08:11AM -0400, Alex Deucher wrote:
>>> We keep a cached version of the edid in radeon_connector which
>>> we use for determining connectedness and when to enable certain
>>> features like hdmi audio, etc.  When the user uses the firmware
>>> interface to override the driver with some other edid the driver's
>>> copy is never updated.  The fetch function will check if there
>>> is a user supplied edid and update the driver's copy if there
>>> is.
>>>
>>> bug:
>>> https://bugs.freedesktop.org/show_bug.cgi?id=80691
>>>
>>> Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
>>
>> [snip]
>>
>>> +struct edid *radeon_connector_edid(struct drm_connector *connector)
>>> +{
>>> +     struct radeon_connector *radeon_connector = to_radeon_connector(connector);
>>> +     struct drm_property_blob *edid_blob = connector->edid_blob_ptr;
>>> +
>>> +     if (radeon_connector->edid) {
>>> +             return radeon_connector->edid;
>>> +     } else if (edid_blob) {
>>> +             struct edid *edid = kmemdup(edid_blob->data, edid_blob->length, GFP_KERNEL);
>>> +             if (edid)
>>> +                     radeon_connector->edid = edid;
>>> +     }
>>> +     return radeon_connector->edid;
>>> +}
>>
>> We have similar issues on intel now that we use the debugfs interface to
>> force certain edids (for validating e.g. 4k or 3d) - our code doesn't see
>> the forced edid. Should we have a helper somewhere or just change
>> drm_get_edid to dtrt here?
>>
>> Adding Thomas who's working on this.
>
> I think the best solution would be to make drm_load_edid_firmware()
> just return the raw user supplied edid, then let the drivers handle it
> internally.  That way the drivers could decide how they want to handle
> it in their detect() or get_modes() callbacks.  The problem is that if
> drm_load_edid_firmware() succeeds, the driver's get_modes() callback
> never gets called.  A less invasive alternative would be to add a a
> get_modes_firmware() callback, e.g.,
>
> diff --git a/drivers/gpu/drm/drm_probe_helper.c
> b/drivers/gpu/drm/drm_probe_helper.c
> index d22676b..ceb246f 100644
> --- a/drivers/gpu/drm/drm_probe_helper.c
> +++ b/drivers/gpu/drm/drm_probe_helper.c
> @@ -127,7 +127,10 @@ static int
> drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
>         }
>
>  #ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE
> -       count = drm_load_edid_firmware(connector);
> +       if (connector_funcs->get_modes_firmware)
> +               count = (*connector_funcs->get_modes_firmware)(connector);
> +       else
> +               count = drm_load_edid_firmware(connector);
>         if (count == 0)
>  #endif
>                 count = (*connector_funcs->get_modes)(connector);
>
> and the driver implementation could mostly just wrap
> drm_load_edid_firmware, e.g.,
>
> +static int radeon_get_modes_firmware(struct drm_connector *connector)
> +{
> +       struct radeon_connector *radeon_connector =
> to_radeon_connector(connector);
> +       struct drm_property_blob *edid_blob;
> +       int ret;
> +
> +       ret = drm_load_edid_firmware(connector);
> +       edid_blob = connector->edid_blob_ptr;
> +       /* update the driver's copy of the */
> +       if (edid_blob) {
> +               struct edid *edid = kmemdup(edid_blob->data,
> edid_blob->length, GFP_KERNEL);
> +               if (edid)
> +                       radeon_connector->edid = edid;
> +       }
> +
> +       return ret;
> +}
>
> The problem is that wouldn't give the driver access to the user
> provided edid at detect() time.

Yeah, we also do a bunch of things in ->detect, so ->detect not
getting called for forced edids is a bit annoying. The other thing is
that edid overriding through debugfs at runtime is done differently
again, and for those the driver's ->detect actually gets called. Well,
if the connector state doesn't get forced.

One idea I've had which is a bit of work is to move all these
detection stuff outside of ->detect and into encoder->mode_fixup
functions (compute_config in i915). If we then add a function to grab
the cached/firmware/overridden edid and use it there it should all
work. And at least on i915 you need to do a full modeset to e.g.
update the audio status anyway.

->detect would then really only be for probing and generating the mode
list while figuring out the actual hw config. And updating driver
private stuff in foo_connector would be done only in ->mode_fixup.

I don't see a good way to make things work as-is, at least if we want
to run ->detect always (since a lot of driver have important code in
there) and make it work with the firmware/debugfs edid forcing and the
connector status forcing (through cmdline or again debugfs).
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch


More information about the dri-devel mailing list