linux-stable/include/drm/display/drm_dp_aux_bus.h
Douglas Anderson 3800b17109 drm/dp: Add callbacks to make using DP AUX bus properly easier
As talked about in this patch in the kerneldoc of
of_dp_aux_populate_ep_device() and also in the past in commit
a1e3667a98 ("drm/bridge: ti-sn65dsi86: Promote the AUX channel to
its own sub-dev"), it can be difficult for eDP controller drivers to
know when the panel has finished probing when they're using
of_dp_aux_populate_ep_devices().

The ti-sn65dsi86 driver managed to solve this because it was already
broken up into a bunch of sub-drivers. That means we could solve the
problem there by adding a new sub-driver to get the panel. We could
use the traditional -EPROBE_DEFER retry mechansim to handle the case
where the panel hadn't probed yet.

In parade-ps8640 we didn't really solve this. The code just expects
the panel to be ready right away. While reviewing the code originally
I had managed to convince myself it was fine to just expect the panel
right away, but additional testing has shown that not to be the
case. We could fix parade-ps8640 like we did ti-sn65dsi86 but it's
pretty cumbersome (since we're not already broken into multiple
drivers) and requires a bunch of boilerplate code.

After discussion [1] it seems like the best solution for most people
is:
- Accept that there's always at most one device that will probe as a
  result of the DP AUX bus (it may have sub-devices, but there will be
  one device _directly_ probed).
- When that device finishes probing, we can just have a call back.

This patch implements that idea. We'll now take a callback as an
argument to the populate function. To make this easier to land in
pieces, we'll make wrappers for the old functions. The functions with
the new name (which make it clear that we only have one child) will
take the callback and the functions with the old name will temporarily
wrap.

[1] https://lore.kernel.org/r/CAD=FV=Ur3afHhsXe7a3baWEnD=MFKFeKRbhFU+bt3P67G0MVzQ@mail.gmail.com

Signed-off-by: Douglas Anderson <dianders@chromium.org>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20220510122726.v3.2.I4182ae27e00792842cb86f1433990a0ef9c0a073@changeid
2022-06-02 15:14:16 -07:00

85 lines
2.4 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright 2021 Google Inc.
*
* The DP AUX bus is used for devices that are connected over a DisplayPort
* AUX bus. The devices on the far side of the bus are referred to as
* endpoints in this code.
*/
#ifndef _DP_AUX_BUS_H_
#define _DP_AUX_BUS_H_
#include <linux/device.h>
#include <linux/mod_devicetable.h>
/**
* struct dp_aux_ep_device - Main dev structure for DP AUX endpoints
*
* This is used to instantiate devices that are connected via a DP AUX
* bus. Usually the device is a panel, but conceivable other devices could
* be hooked up there.
*/
struct dp_aux_ep_device {
/** @dev: The normal dev pointer */
struct device dev;
/** @aux: Pointer to the aux bus */
struct drm_dp_aux *aux;
};
struct dp_aux_ep_driver {
int (*probe)(struct dp_aux_ep_device *aux_ep);
void (*remove)(struct dp_aux_ep_device *aux_ep);
void (*shutdown)(struct dp_aux_ep_device *aux_ep);
struct device_driver driver;
};
static inline struct dp_aux_ep_device *to_dp_aux_ep_dev(struct device *dev)
{
return container_of(dev, struct dp_aux_ep_device, dev);
}
static inline struct dp_aux_ep_driver *to_dp_aux_ep_drv(struct device_driver *drv)
{
return container_of(drv, struct dp_aux_ep_driver, driver);
}
int of_dp_aux_populate_bus(struct drm_dp_aux *aux,
int (*done_probing)(struct drm_dp_aux *aux));
void of_dp_aux_depopulate_bus(struct drm_dp_aux *aux);
int devm_of_dp_aux_populate_bus(struct drm_dp_aux *aux,
int (*done_probing)(struct drm_dp_aux *aux));
/* Deprecated versions of the above functions. To be removed when no callers. */
static inline int of_dp_aux_populate_ep_devices(struct drm_dp_aux *aux)
{
int ret;
ret = of_dp_aux_populate_bus(aux, NULL);
/* New API returns -ENODEV for no child case; adapt to old assumption */
return (ret != -ENODEV) ? ret : 0;
}
static inline int devm_of_dp_aux_populate_ep_devices(struct drm_dp_aux *aux)
{
int ret;
ret = devm_of_dp_aux_populate_bus(aux, NULL);
/* New API returns -ENODEV for no child case; adapt to old assumption */
return (ret != -ENODEV) ? ret : 0;
}
static inline void of_dp_aux_depopulate_ep_devices(struct drm_dp_aux *aux)
{
of_dp_aux_depopulate_bus(aux);
}
#define dp_aux_dp_driver_register(aux_ep_drv) \
__dp_aux_dp_driver_register(aux_ep_drv, THIS_MODULE)
int __dp_aux_dp_driver_register(struct dp_aux_ep_driver *aux_ep_drv,
struct module *owner);
void dp_aux_dp_driver_unregister(struct dp_aux_ep_driver *aux_ep_drv);
#endif /* _DP_AUX_BUS_H_ */