This is a superset of the current i2c_dp_aux bus functionality and can be used to transfer native AUX in addition to I2C-over-AUX messages. Helpers are provided to read and write the DPCD, either blockwise or byte-wise. Many of the existing helpers for DisplayPort take a copy of a portion of the DPCD and operate on that, without a way to write data back to the DPCD (e.g. for configuration of the link). Subsequent patches will build upon this infrastructure to provide common functionality in a generic way. Signed-off-by: Thierry Reding <treding@xxxxxxxxxx> --- drivers/gpu/drm/drm_dp_helper.c | 50 ++++++++++++++++++++++++ include/drm/drm_dp_helper.h | 85 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 9e978aae8972..6c9276098069 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -346,3 +346,53 @@ int drm_dp_bw_code_to_link_rate(u8 link_bw) } } EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate); + +/** + * drm_dp_dpcd_read() - read a series of bytes from the DPCD + * @aux: DisplayPort AUX channel + * @offset: address of the (first) register to read + * @buffer: buffer to store the register values + * @size: number of bytes in @buffer + * + * Returns the number of bytes transferred on success, or a negative error + * code on failure. + */ +ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset, + void *buffer, size_t size) +{ + struct drm_dp_aux_msg msg; + + memset(&msg, 0, sizeof(msg)); + msg.address = offset; + msg.flags = DRM_DP_AUX_NATIVE_READ; + msg.buffer = buffer; + msg.size = size; + + return aux->transfer(aux, &msg); +} +EXPORT_SYMBOL(drm_dp_dpcd_read); + +/** + * drm_dp_dpcd_write() - write a series of bytes to the DPCD + * @aux: DisplayPort AUX channel + * @offset: address of the (first) register to write + * @buffer: buffer containing the values to write + * @size: number of bytes in @buffer + * + * Returns the number of bytes transferred on success, or a negative error + * code on failure. + */ +ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset, + void *buffer, size_t size) +{ + struct drm_dp_aux_msg msg; + + memset(&msg, 0, sizeof(msg)); + msg.address = offset; + msg.flags = DRM_DP_AUX_NATIVE_WRITE; + msg.buffer = buffer; + msg.size = size; + + return aux->transfer(aux, &msg); +} +EXPORT_SYMBOL(drm_dp_dpcd_write); diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index a92c3754e3bb..e528b2b64cef 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -397,4 +397,89 @@ drm_dp_enhanced_frame_cap(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) (dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP); } +/* + * DisplayPort AUX channel + */ + +/* A message is either a native AUX or I2C-over-AUX transaction */ +#define DRM_DP_AUX_MODE_MASK 0x1 +#define DRM_DP_AUX_NATIVE 0x0 +#define DRM_DP_AUX_I2C 0x1 + +/* + * A message can be a read or write transaction. I2C messages can also be + * part of a larger transaction, in which case the MOT flag can be set. + */ +#define DRM_DP_AUX_WRITE (1 << 30) +#define DRM_DP_AUX_I2C_MOT (1 << 31) + +#define DRM_DP_AUX_NATIVE_READ DRM_DP_AUX_NATIVE +#define DRM_DP_AUX_NATIVE_WRITE (DRM_DP_AUX_WRITE | DRM_DP_AUX_NATIVE) + +#define DRM_DP_AUX_ACK (0 << 0) +#define DRM_DP_AUX_NAK (1 << 0) +#define DRM_DP_AUX_DEFER (2 << 0) +#define DRM_DP_AUX_I2C_NAK (3 << 0) +#define DRM_DP_AUX_I2C_DEFER (4 << 0) + +/** + * struct drm_dp_aux_msg - DisplayPort AUX channel transaction + * @address: address of the (first) register to access + * @flags: contains the type of transaction as well as flags (see above) + * @reply: upon completion, contains the reply type of the transaction + * @buffer: pointer to a transmission or reception buffer + * @size: size of @buffer + */ +struct drm_dp_aux_msg { + unsigned int address; + unsigned long flags; + unsigned long reply; + void *buffer; + size_t size; +}; + +/** + * struct drm_dp_aux - DisplayPort AUX channel + * @transfer: transfers a message representing a single AUX transaction + */ +struct drm_dp_aux { + ssize_t (*transfer)(struct drm_dp_aux *aux, + struct drm_dp_aux_msg *msg); +}; + +ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset, + void *buffer, size_t size); +ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset, + void *buffer, size_t size); + +/** + * drm_dp_dpcd_readb() - read a single byte from the DPCD + * @aux: DisplayPort AUX channel + * @offset: address of the register to read + * @valuep: location where the value of the register will be stored + * + * Returns the number of bytes transferred (1) on success, or a negative + * error code on failure. + */ +static inline ssize_t drm_dp_dpcd_readb(struct drm_dp_aux *aux, + unsigned int offset, u8 *valuep) +{ + return drm_dp_dpcd_read(aux, offset, valuep, 1); +} + +/** + * drm_dp_dpcd_writeb() - write a single byte to the DPCD + * @aux: DisplayPort AUX channel + * @offset: address of the register to write + * @valuep: value to write to the register + * + * Returns the number of bytes transferred (1) on success, or a negative + * error code on failure. + */ +static inline ssize_t drm_dp_dpcd_writeb(struct drm_dp_aux *aux, u8 value, + unsigned int offset) +{ + return drm_dp_dpcd_write(aux, offset, &value, 1); +} + #endif /* _DRM_DP_HELPER_H_ */ -- 1.8.4.2 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel