drm/dp: Allow registering AUX channels as I2C busses

Implements an I2C-over-AUX I2C adapter on top of the generic drm_dp_aux
infrastructure. It extracts the retry logic from existing drivers, which
should help in porting those drivers to this new helper.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v5:
- move comments partially to to header file
- keep MOT set between I2C messages
- return -EPROTO on short reads

Changes in v4:
- fix typo "bitrate" -> "bit rate"

Changes in v3:
- add back DRM_DEBUG_KMS and DRM_ERROR messages
- embed i2c_adapter within struct drm_dp_aux
- fix typo in comment
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 28ab6f4..b7488c9 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -421,6 +421,7 @@
 
 /**
  * struct drm_dp_aux - DisplayPort AUX channel
+ * @ddc: I2C adapter that can be used for I2C-over-AUX communication
  * @dev: pointer to struct device that is the parent for this AUX channel
  * @transfer: transfers a message representing a single AUX transaction
  *
@@ -435,8 +436,16 @@
  * propagate errors from the .transfer() function, with the exception of
  * the -EBUSY error, which causes a transaction to be retried. On a short,
  * helpers will return -EPROTO to make it simpler to check for failure.
+ *
+ * An AUX channel can also be used to transport I2C messages to a sink. A
+ * typical application of that is to access an EDID that's present in the
+ * sink device. The .transfer() function can also be used to execute such
+ * transactions. The drm_dp_aux_register_i2c_bus() function registers an
+ * I2C adapter that can be passed to drm_probe_ddc(). Upon removal, drivers
+ * should call drm_dp_aux_unregister_i2c_bus() to remove the I2C adapter.
  */
 struct drm_dp_aux {
+	struct i2c_adapter ddc;
 	struct device *dev;
 
 	ssize_t (*transfer)(struct drm_dp_aux *aux,
@@ -497,4 +506,7 @@
 int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link);
 int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link);
 
+int drm_dp_aux_register_i2c_bus(struct drm_dp_aux *aux);
+void drm_dp_aux_unregister_i2c_bus(struct drm_dp_aux *aux);
+
 #endif /* _DRM_DP_HELPER_H_ */