Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab2c0672 authored by Dave Airlie's avatar Dave Airlie
Browse files

drm/intel: refactor DP i2c support and DP common header to drm helper



Both radeon and nouveau can re-use this code so move it up a level
so they can. However the hw interfaces for aux ch are different
enough that the code to translate from mode, address, bytes
to actual hw interfaces isn't generic, so move that code into the
Intel driver.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 85bb0c37
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \

drm-$(CONFIG_COMPAT) += drm_ioc32.o

drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o
drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_i2c_helper.o

obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o

+5 −69
Original line number Diff line number Diff line
@@ -28,85 +28,21 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/i2c.h>
#include "intel_dp.h"
#include "drm_dp_helper.h"
#include "drmP.h"

/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */

#define MODE_I2C_START	1
#define MODE_I2C_WRITE	2
#define MODE_I2C_READ	4
#define MODE_I2C_STOP	8

static int
i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
			    uint8_t write_byte, uint8_t *read_byte)
{
	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
	uint16_t address = algo_data->address;
	uint8_t msg[5];
	uint8_t reply[2];
	int msg_bytes;
	int reply_bytes;
	int ret;
	
	/* Set up the command byte */
	if (mode & MODE_I2C_READ)
		msg[0] = AUX_I2C_READ << 4;
	else
		msg[0] = AUX_I2C_WRITE << 4;

	if (!(mode & MODE_I2C_STOP))
		msg[0] |= AUX_I2C_MOT << 4;

	msg[1] = address >> 8;
	msg[2] = address;

	switch (mode) {
	case MODE_I2C_WRITE:
		msg[3] = 0;
		msg[4] = write_byte;
		msg_bytes = 5;
		reply_bytes = 1;
		break;
	case MODE_I2C_READ:
		msg[3] = 0;
		msg_bytes = 4;
		reply_bytes = 2;
		break;
	default:
		msg_bytes = 3;
		reply_bytes = 1;
		break;
	}

	for (;;) {
		ret = (*algo_data->aux_ch)(adapter,
					   msg, msg_bytes,
					   reply, reply_bytes);
		if (ret < 0) {
			DRM_DEBUG("aux_ch failed %d\n", ret);
	ret = (*algo_data->aux_ch)(adapter, mode,
				   write_byte, read_byte);
	return ret;
}
		switch (reply[0] & AUX_I2C_REPLY_MASK) {
		case AUX_I2C_REPLY_ACK:
			if (mode == MODE_I2C_READ) {
				*read_byte = reply[1];
			}
			return reply_bytes - 1;
		case AUX_I2C_REPLY_NACK:
			DRM_DEBUG("aux_ch nack\n");
			return -EREMOTEIO;
		case AUX_I2C_REPLY_DEFER:
			DRM_DEBUG("aux_ch defer\n");
			udelay(100);
			break;
		default:
			DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]);
			return -EREMOTEIO;
		}
	}
}

/*
 * I2C over AUX CH
+0 −1
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
	  intel_lvds.o \
	  intel_bios.o \
	  intel_dp.o \
	  intel_dp_i2c.o \
	  intel_hdmi.o \
	  intel_sdvo.o \
	  intel_modes.o \
+1 −1
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@
#include "intel_drv.h"
#include "i915_drm.h"
#include "i915_drv.h"
#include "intel_dp.h"
#include "drm_dp_helper.h"

#include "drm_crtc_helper.h"

+66 −6
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@
#include "intel_drv.h"
#include "i915_drm.h"
#include "i915_drv.h"
#include "intel_dp.h"
#include "drm_dp_helper.h"

#define DP_LINK_STATUS_SIZE	6
#define DP_LINK_CHECK_TIMEOUT	(10 * 1000)
@@ -382,17 +382,77 @@ intel_dp_aux_native_read(struct intel_output *intel_output,
}

static int
intel_dp_i2c_aux_ch(struct i2c_adapter *adapter,
		    uint8_t *send, int send_bytes,
		    uint8_t *recv, int recv_bytes)
intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
		    uint8_t write_byte, uint8_t *read_byte)
{
	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
	struct intel_dp_priv *dp_priv = container_of(adapter,
						     struct intel_dp_priv,
						     adapter);
	struct intel_output *intel_output = dp_priv->intel_output;
	uint16_t address = algo_data->address;
	uint8_t msg[5];
	uint8_t reply[2];
	int msg_bytes;
	int reply_bytes;
	int ret;

	/* Set up the command byte */
	if (mode & MODE_I2C_READ)
		msg[0] = AUX_I2C_READ << 4;
	else
		msg[0] = AUX_I2C_WRITE << 4;

	if (!(mode & MODE_I2C_STOP))
		msg[0] |= AUX_I2C_MOT << 4;

	msg[1] = address >> 8;
	msg[2] = address;

	switch (mode) {
	case MODE_I2C_WRITE:
		msg[3] = 0;
		msg[4] = write_byte;
		msg_bytes = 5;
		reply_bytes = 1;
		break;
	case MODE_I2C_READ:
		msg[3] = 0;
		msg_bytes = 4;
		reply_bytes = 2;
		break;
	default:
		msg_bytes = 3;
		reply_bytes = 1;
		break;
	}

	return intel_dp_aux_ch(intel_output,
			       send, send_bytes, recv, recv_bytes);
	for (;;) {
	  ret = intel_dp_aux_ch(intel_output,
				msg, msg_bytes,
				reply, reply_bytes);
		if (ret < 0) {
			DRM_DEBUG("aux_ch failed %d\n", ret);
			return ret;
		}
		switch (reply[0] & AUX_I2C_REPLY_MASK) {
		case AUX_I2C_REPLY_ACK:
			if (mode == MODE_I2C_READ) {
				*read_byte = reply[1];
			}
			return reply_bytes - 1;
		case AUX_I2C_REPLY_NACK:
			DRM_DEBUG("aux_ch nack\n");
			return -EREMOTEIO;
		case AUX_I2C_REPLY_DEFER:
			DRM_DEBUG("aux_ch defer\n");
			udelay(100);
			break;
		default:
			DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]);
			return -EREMOTEIO;
		}
	}
}

static int
Loading