162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright 2021 Google Inc.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * The DP AUX bus is used for devices that are connected over a DisplayPort
662306a36Sopenharmony_ci * AUX bus. The devices on the far side of the bus are referred to as
762306a36Sopenharmony_ci * endpoints in this code.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#ifndef _DP_AUX_BUS_H_
1162306a36Sopenharmony_ci#define _DP_AUX_BUS_H_
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/device.h>
1462306a36Sopenharmony_ci#include <linux/mod_devicetable.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/**
1762306a36Sopenharmony_ci * struct dp_aux_ep_device - Main dev structure for DP AUX endpoints
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * This is used to instantiate devices that are connected via a DP AUX
2062306a36Sopenharmony_ci * bus. Usually the device is a panel, but conceivable other devices could
2162306a36Sopenharmony_ci * be hooked up there.
2262306a36Sopenharmony_ci */
2362306a36Sopenharmony_cistruct dp_aux_ep_device {
2462306a36Sopenharmony_ci	/** @dev: The normal dev pointer */
2562306a36Sopenharmony_ci	struct device dev;
2662306a36Sopenharmony_ci	/** @aux: Pointer to the aux bus */
2762306a36Sopenharmony_ci	struct drm_dp_aux *aux;
2862306a36Sopenharmony_ci};
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistruct dp_aux_ep_driver {
3162306a36Sopenharmony_ci	int (*probe)(struct dp_aux_ep_device *aux_ep);
3262306a36Sopenharmony_ci	void (*remove)(struct dp_aux_ep_device *aux_ep);
3362306a36Sopenharmony_ci	void (*shutdown)(struct dp_aux_ep_device *aux_ep);
3462306a36Sopenharmony_ci	struct device_driver driver;
3562306a36Sopenharmony_ci};
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic inline struct dp_aux_ep_device *to_dp_aux_ep_dev(struct device *dev)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	return container_of(dev, struct dp_aux_ep_device, dev);
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistatic inline struct dp_aux_ep_driver *to_dp_aux_ep_drv(struct device_driver *drv)
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	return container_of(drv, struct dp_aux_ep_driver, driver);
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ciint of_dp_aux_populate_bus(struct drm_dp_aux *aux,
4862306a36Sopenharmony_ci			   int (*done_probing)(struct drm_dp_aux *aux));
4962306a36Sopenharmony_civoid of_dp_aux_depopulate_bus(struct drm_dp_aux *aux);
5062306a36Sopenharmony_ciint devm_of_dp_aux_populate_bus(struct drm_dp_aux *aux,
5162306a36Sopenharmony_ci				int (*done_probing)(struct drm_dp_aux *aux));
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci/* Deprecated versions of the above functions. To be removed when no callers. */
5462306a36Sopenharmony_cistatic inline int of_dp_aux_populate_ep_devices(struct drm_dp_aux *aux)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	int ret;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	ret = of_dp_aux_populate_bus(aux, NULL);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	/* New API returns -ENODEV for no child case; adapt to old assumption */
6162306a36Sopenharmony_ci	return (ret != -ENODEV) ? ret : 0;
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistatic inline int devm_of_dp_aux_populate_ep_devices(struct drm_dp_aux *aux)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	int ret;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	ret = devm_of_dp_aux_populate_bus(aux, NULL);
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	/* New API returns -ENODEV for no child case; adapt to old assumption */
7162306a36Sopenharmony_ci	return (ret != -ENODEV) ? ret : 0;
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cistatic inline void of_dp_aux_depopulate_ep_devices(struct drm_dp_aux *aux)
7562306a36Sopenharmony_ci{
7662306a36Sopenharmony_ci	of_dp_aux_depopulate_bus(aux);
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci#define dp_aux_dp_driver_register(aux_ep_drv) \
8062306a36Sopenharmony_ci	__dp_aux_dp_driver_register(aux_ep_drv, THIS_MODULE)
8162306a36Sopenharmony_ciint __dp_aux_dp_driver_register(struct dp_aux_ep_driver *aux_ep_drv,
8262306a36Sopenharmony_ci				struct module *owner);
8362306a36Sopenharmony_civoid dp_aux_dp_driver_unregister(struct dp_aux_ep_driver *aux_ep_drv);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci#endif /* _DP_AUX_BUS_H_ */
86