linux/drivers/gpu/drm/display/drm_dp_dual_mode_helper.c

/*
 * Copyright © 2016 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/export.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/string.h>

#include <drm/display/drm_dp_dual_mode_helper.h>
#include <drm/drm_device.h>
#include <drm/drm_print.h>

/**
 * DOC: dp dual mode helpers
 *
 * Helper functions to deal with DP dual mode (aka. DP++) adaptors.
 *
 * Type 1:
 * Adaptor registers (if any) and the sink DDC bus may be accessed via I2C.
 *
 * Type 2:
 * Adaptor registers and sink DDC bus can be accessed either via I2C or
 * I2C-over-AUX. Source devices may choose to implement either of these
 * access methods.
 */

#define DP_DUAL_MODE_SLAVE_ADDRESS

/**
 * drm_dp_dual_mode_read - Read from the DP dual mode adaptor register(s)
 * @adapter: I2C adapter for the DDC bus
 * @offset: register offset
 * @buffer: buffer for return data
 * @size: size of the buffer
 *
 * Reads @size bytes from the DP dual mode adaptor registers
 * starting at @offset.
 *
 * Returns:
 * 0 on success, negative error code on failure
 */
ssize_t drm_dp_dual_mode_read(struct i2c_adapter *adapter,
			      u8 offset, void *buffer, size_t size)
{}
EXPORT_SYMBOL();

/**
 * drm_dp_dual_mode_write - Write to the DP dual mode adaptor register(s)
 * @adapter: I2C adapter for the DDC bus
 * @offset: register offset
 * @buffer: buffer for write data
 * @size: size of the buffer
 *
 * Writes @size bytes to the DP dual mode adaptor registers
 * starting at @offset.
 *
 * Returns:
 * 0 on success, negative error code on failure
 */
ssize_t drm_dp_dual_mode_write(struct i2c_adapter *adapter,
			       u8 offset, const void *buffer, size_t size)
{}
EXPORT_SYMBOL();

static bool is_hdmi_adaptor(const char hdmi_id[DP_DUAL_MODE_HDMI_ID_LEN])
{}

static bool is_type1_adaptor(uint8_t adaptor_id)
{}

static bool is_type2_adaptor(uint8_t adaptor_id)
{}

static bool is_lspcon_adaptor(const char hdmi_id[DP_DUAL_MODE_HDMI_ID_LEN],
			      const uint8_t adaptor_id)
{}

/**
 * drm_dp_dual_mode_detect - Identify the DP dual mode adaptor
 * @dev: &drm_device to use
 * @adapter: I2C adapter for the DDC bus
 *
 * Attempt to identify the type of the DP dual mode adaptor used.
 *
 * Note that when the answer is @DRM_DP_DUAL_MODE_UNKNOWN it's not
 * certain whether we're dealing with a native HDMI port or
 * a type 1 DVI dual mode adaptor. The driver will have to use
 * some other hardware/driver specific mechanism to make that
 * distinction.
 *
 * Returns:
 * The type of the DP dual mode adaptor used
 */
enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(const struct drm_device *dev,
						   struct i2c_adapter *adapter)
{}
EXPORT_SYMBOL();

/**
 * drm_dp_dual_mode_max_tmds_clock - Max TMDS clock for DP dual mode adaptor
 * @dev: &drm_device to use
 * @type: DP dual mode adaptor type
 * @adapter: I2C adapter for the DDC bus
 *
 * Determine the max TMDS clock the adaptor supports based on the
 * type of the dual mode adaptor and the DP_DUAL_MODE_MAX_TMDS_CLOCK
 * register (on type2 adaptors). As some type 1 adaptors have
 * problems with registers (see comments in drm_dp_dual_mode_detect())
 * we don't read the register on those, instead we simply assume
 * a 165 MHz limit based on the specification.
 *
 * Returns:
 * Maximum supported TMDS clock rate for the DP dual mode adaptor in kHz.
 */
int drm_dp_dual_mode_max_tmds_clock(const struct drm_device *dev, enum drm_dp_dual_mode_type type,
				    struct i2c_adapter *adapter)
{}
EXPORT_SYMBOL();

/**
 * drm_dp_dual_mode_get_tmds_output - Get the state of the TMDS output buffers in the DP dual mode adaptor
 * @dev: &drm_device to use
 * @type: DP dual mode adaptor type
 * @adapter: I2C adapter for the DDC bus
 * @enabled: current state of the TMDS output buffers
 *
 * Get the state of the TMDS output buffers in the adaptor. For
 * type2 adaptors this is queried from the DP_DUAL_MODE_TMDS_OEN
 * register. As some type 1 adaptors have problems with registers
 * (see comments in drm_dp_dual_mode_detect()) we don't read the
 * register on those, instead we simply assume that the buffers
 * are always enabled.
 *
 * Returns:
 * 0 on success, negative error code on failure
 */
int drm_dp_dual_mode_get_tmds_output(const struct drm_device *dev,
				     enum drm_dp_dual_mode_type type, struct i2c_adapter *adapter,
				     bool *enabled)
{}
EXPORT_SYMBOL();

/**
 * drm_dp_dual_mode_set_tmds_output - Enable/disable TMDS output buffers in the DP dual mode adaptor
 * @dev: &drm_device to use
 * @type: DP dual mode adaptor type
 * @adapter: I2C adapter for the DDC bus
 * @enable: enable (as opposed to disable) the TMDS output buffers
 *
 * Set the state of the TMDS output buffers in the adaptor. For
 * type2 this is set via the DP_DUAL_MODE_TMDS_OEN register.
 * Type1 adaptors do not support any register writes.
 *
 * Returns:
 * 0 on success, negative error code on failure
 */
int drm_dp_dual_mode_set_tmds_output(const struct drm_device *dev, enum drm_dp_dual_mode_type type,
				     struct i2c_adapter *adapter, bool enable)
{}
EXPORT_SYMBOL();

/**
 * drm_dp_get_dual_mode_type_name - Get the name of the DP dual mode adaptor type as a string
 * @type: DP dual mode adaptor type
 *
 * Returns:
 * String representation of the DP dual mode adaptor type
 */
const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type)
{}
EXPORT_SYMBOL();

/**
 * drm_lspcon_get_mode: Get LSPCON's current mode of operation by
 * reading offset (0x80, 0x41)
 * @dev: &drm_device to use
 * @adapter: I2C-over-aux adapter
 * @mode: current lspcon mode of operation output variable
 *
 * Returns:
 * 0 on success, sets the current_mode value to appropriate mode
 * -error on failure
 */
int drm_lspcon_get_mode(const struct drm_device *dev, struct i2c_adapter *adapter,
			enum drm_lspcon_mode *mode)
{}
EXPORT_SYMBOL();

/**
 * drm_lspcon_set_mode: Change LSPCON's mode of operation by
 * writing offset (0x80, 0x40)
 * @dev: &drm_device to use
 * @adapter: I2C-over-aux adapter
 * @mode: required mode of operation
 *
 * Returns:
 * 0 on success, -error on failure/timeout
 */
int drm_lspcon_set_mode(const struct drm_device *dev, struct i2c_adapter *adapter,
			enum drm_lspcon_mode mode)
{}
EXPORT_SYMBOL();