Commit ab2c0672 authored by Dave Airlie's avatar Dave Airlie

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
...@@ -15,7 +15,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ ...@@ -15,7 +15,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
drm-$(CONFIG_COMPAT) += drm_ioc32.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 obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
......
...@@ -28,84 +28,20 @@ ...@@ -28,84 +28,20 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include "intel_dp.h" #include "drm_dp_helper.h"
#include "drmP.h" #include "drmP.h"
/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ /* 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 static int
i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
uint8_t write_byte, uint8_t *read_byte) uint8_t write_byte, uint8_t *read_byte)
{ {
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; 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; int ret;
/* Set up the command byte */ ret = (*algo_data->aux_ch)(adapter, mode,
if (mode & MODE_I2C_READ) write_byte, read_byte);
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);
return 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;
}
}
} }
/* /*
......
...@@ -15,7 +15,6 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ ...@@ -15,7 +15,6 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
intel_lvds.o \ intel_lvds.o \
intel_bios.o \ intel_bios.o \
intel_dp.o \ intel_dp.o \
intel_dp_i2c.o \
intel_hdmi.o \ intel_hdmi.o \
intel_sdvo.o \ intel_sdvo.o \
intel_modes.o \ intel_modes.o \
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include "intel_drv.h" #include "intel_drv.h"
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.h" #include "i915_drv.h"
#include "intel_dp.h" #include "drm_dp_helper.h"
#include "drm_crtc_helper.h" #include "drm_crtc_helper.h"
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#include "intel_drv.h" #include "intel_drv.h"
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.h" #include "i915_drv.h"
#include "intel_dp.h" #include "drm_dp_helper.h"
#define DP_LINK_STATUS_SIZE 6 #define DP_LINK_STATUS_SIZE 6
#define DP_LINK_CHECK_TIMEOUT (10 * 1000) #define DP_LINK_CHECK_TIMEOUT (10 * 1000)
...@@ -382,17 +382,77 @@ intel_dp_aux_native_read(struct intel_output *intel_output, ...@@ -382,17 +382,77 @@ intel_dp_aux_native_read(struct intel_output *intel_output,
} }
static int static int
intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
uint8_t *send, int send_bytes, uint8_t write_byte, uint8_t *read_byte)
uint8_t *recv, int recv_bytes)
{ {
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
struct intel_dp_priv *dp_priv = container_of(adapter, struct intel_dp_priv *dp_priv = container_of(adapter,
struct intel_dp_priv, struct intel_dp_priv,
adapter); adapter);
struct intel_output *intel_output = dp_priv->intel_output; 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;
return intel_dp_aux_ch(intel_output, msg[1] = address >> 8;
send, send_bytes, recv, recv_bytes); 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 = 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 static int
......
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
* OF THIS SOFTWARE. * OF THIS SOFTWARE.
*/ */
#ifndef _INTEL_DP_H_ #ifndef _DRM_DP_HELPER_H_
#define _INTEL_DP_H_ #define _DRM_DP_HELPER_H_
/* From the VESA DisplayPort spec */ /* From the VESA DisplayPort spec */
...@@ -130,15 +130,20 @@ ...@@ -130,15 +130,20 @@
#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0 #define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0
#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6 #define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6
#define MODE_I2C_START 1
#define MODE_I2C_WRITE 2
#define MODE_I2C_READ 4
#define MODE_I2C_STOP 8
struct i2c_algo_dp_aux_data { struct i2c_algo_dp_aux_data {
bool running; bool running;
u16 address; u16 address;
int (*aux_ch) (struct i2c_adapter *adapter, int (*aux_ch) (struct i2c_adapter *adapter,
uint8_t *send, int send_bytes, int mode, uint8_t write_byte,
uint8_t *recv, int recv_bytes); uint8_t *read_byte);
}; };
int int
i2c_dp_aux_add_bus(struct i2c_adapter *adapter); i2c_dp_aux_add_bus(struct i2c_adapter *adapter);
#endif /* _INTEL_DP_H_ */ #endif /* _DRM_DP_HELPER_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment