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

Commit 1af5c410 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/i2c: modify aux interface to return length actually transferred



Apparently sinks are allows to respond with ACK even if they didn't
fully complete a transaction...  It seems like a missed opportunity
for DEFER to me, but what do I know :)

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 36510add
Loading
Loading
Loading
Loading
+5 −3
Original line number Original line Diff line number Diff line
@@ -64,7 +64,7 @@ void nvkm_i2c_aux_monitor(struct nvkm_i2c_aux *, bool monitor);
int nvkm_i2c_aux_acquire(struct nvkm_i2c_aux *);
int nvkm_i2c_aux_acquire(struct nvkm_i2c_aux *);
void nvkm_i2c_aux_release(struct nvkm_i2c_aux *);
void nvkm_i2c_aux_release(struct nvkm_i2c_aux *);
int nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *, bool retry, u8 type,
int nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *, bool retry, u8 type,
		      u32 addr, u8 *data, u8 size);
		      u32 addr, u8 *data, u8 *size);
int nvkm_i2c_aux_lnk_ctl(struct nvkm_i2c_aux *, int link_nr, int link_bw,
int nvkm_i2c_aux_lnk_ctl(struct nvkm_i2c_aux *, int link_nr, int link_bw,
			 bool enhanced_framing);
			 bool enhanced_framing);


@@ -162,9 +162,11 @@ nvkm_probe_i2c(struct i2c_adapter *adap, u8 addr)
static inline int
static inline int
nvkm_rdaux(struct nvkm_i2c_aux *aux, u32 addr, u8 *data, u8 size)
nvkm_rdaux(struct nvkm_i2c_aux *aux, u32 addr, u8 *data, u8 size)
{
{
	const u8 xfer = size;
	int ret = nvkm_i2c_aux_acquire(aux);
	int ret = nvkm_i2c_aux_acquire(aux);
	if (ret == 0) {
	if (ret == 0) {
		ret = nvkm_i2c_aux_xfer(aux, true, 9, addr, data, size);
		ret = nvkm_i2c_aux_xfer(aux, true, 9, addr, data, &size);
		WARN_ON(!ret && size != xfer);
		nvkm_i2c_aux_release(aux);
		nvkm_i2c_aux_release(aux);
	}
	}
	return ret;
	return ret;
@@ -175,7 +177,7 @@ nvkm_wraux(struct nvkm_i2c_aux *aux, u32 addr, u8 *data, u8 size)
{
{
	int ret = nvkm_i2c_aux_acquire(aux);
	int ret = nvkm_i2c_aux_acquire(aux);
	if (ret == 0) {
	if (ret == 0) {
		ret = nvkm_i2c_aux_xfer(aux, true, 8, addr, data, size);
		ret = nvkm_i2c_aux_xfer(aux, true, 8, addr, data, &size);
		nvkm_i2c_aux_release(aux);
		nvkm_i2c_aux_release(aux);
	}
	}
	return ret;
	return ret;
+3 −2
Original line number Original line Diff line number Diff line
@@ -1147,6 +1147,7 @@ nouveau_connector_aux_xfer(struct drm_dp_aux *obj, struct drm_dp_aux_msg *msg)
		container_of(obj, typeof(*nv_connector), aux);
		container_of(obj, typeof(*nv_connector), aux);
	struct nouveau_encoder *nv_encoder;
	struct nouveau_encoder *nv_encoder;
	struct nvkm_i2c_aux *aux;
	struct nvkm_i2c_aux *aux;
	u8 size = msg->size;
	int ret;
	int ret;


	nv_encoder = find_encoder(&nv_connector->base, DCB_OUTPUT_DP);
	nv_encoder = find_encoder(&nv_connector->base, DCB_OUTPUT_DP);
@@ -1162,11 +1163,11 @@ nouveau_connector_aux_xfer(struct drm_dp_aux *obj, struct drm_dp_aux_msg *msg)
		return ret;
		return ret;


	ret = nvkm_i2c_aux_xfer(aux, false, msg->request, msg->address,
	ret = nvkm_i2c_aux_xfer(aux, false, msg->request, msg->address,
				msg->buffer, msg->size);
				msg->buffer, &size);
	nvkm_i2c_aux_release(aux);
	nvkm_i2c_aux_release(aux);
	if (ret >= 0) {
	if (ret >= 0) {
		msg->reply = ret;
		msg->reply = ret;
		return msg->size;
		return size;
	}
	}


	return ret;
	return ret;
+7 −7
Original line number Original line Diff line number Diff line
@@ -134,7 +134,7 @@ struct anx9805_aux {


static int
static int
anx9805_aux_xfer(struct nvkm_i2c_aux *base, bool retry,
anx9805_aux_xfer(struct nvkm_i2c_aux *base, bool retry,
		 u8 type, u32 addr, u8 *data, u8 size)
		 u8 type, u32 addr, u8 *data, u8 *size)
{
{
	struct anx9805_aux *aux = anx9805_aux(base);
	struct anx9805_aux *aux = anx9805_aux(base);
	struct anx9805_pad *pad = aux->pad;
	struct anx9805_pad *pad = aux->pad;
@@ -143,7 +143,7 @@ anx9805_aux_xfer(struct nvkm_i2c_aux *base, bool retry,
	u8 buf[16] = {};
	u8 buf[16] = {};
	u8 tmp;
	u8 tmp;


	AUX_DBG(&aux->base, "%02x %05x %d", type, addr, size);
	AUX_DBG(&aux->base, "%02x %05x %d", type, addr, *size);


	tmp = nvkm_rdi2cr(adap, pad->addr, 0x07) & ~0x04;
	tmp = nvkm_rdi2cr(adap, pad->addr, 0x07) & ~0x04;
	nvkm_wri2cr(adap, pad->addr, 0x07, tmp | 0x04);
	nvkm_wri2cr(adap, pad->addr, 0x07, tmp | 0x04);
@@ -152,12 +152,12 @@ anx9805_aux_xfer(struct nvkm_i2c_aux *base, bool retry,


	nvkm_wri2cr(adap, aux->addr, 0xe4, 0x80);
	nvkm_wri2cr(adap, aux->addr, 0xe4, 0x80);
	if (!(type & 1)) {
	if (!(type & 1)) {
		memcpy(buf, data, size);
		memcpy(buf, data, *size);
		AUX_DBG(&aux->base, "%16ph", buf);
		AUX_DBG(&aux->base, "%16ph", buf);
		for (i = 0; i < size; i++)
		for (i = 0; i < *size; i++)
			nvkm_wri2cr(adap, aux->addr, 0xf0 + i, buf[i]);
			nvkm_wri2cr(adap, aux->addr, 0xf0 + i, buf[i]);
	}
	}
	nvkm_wri2cr(adap, aux->addr, 0xe5, ((size - 1) << 4) | type);
	nvkm_wri2cr(adap, aux->addr, 0xe5, ((*size - 1) << 4) | type);
	nvkm_wri2cr(adap, aux->addr, 0xe6, (addr & 0x000ff) >>  0);
	nvkm_wri2cr(adap, aux->addr, 0xe6, (addr & 0x000ff) >>  0);
	nvkm_wri2cr(adap, aux->addr, 0xe7, (addr & 0x0ff00) >>  8);
	nvkm_wri2cr(adap, aux->addr, 0xe7, (addr & 0x0ff00) >>  8);
	nvkm_wri2cr(adap, aux->addr, 0xe8, (addr & 0xf0000) >> 16);
	nvkm_wri2cr(adap, aux->addr, 0xe8, (addr & 0xf0000) >> 16);
@@ -176,10 +176,10 @@ anx9805_aux_xfer(struct nvkm_i2c_aux *base, bool retry,
	}
	}


	if (type & 1) {
	if (type & 1) {
		for (i = 0; i < size; i++)
		for (i = 0; i < *size; i++)
			buf[i] = nvkm_rdi2cr(adap, aux->addr, 0xf0 + i);
			buf[i] = nvkm_rdi2cr(adap, aux->addr, 0xf0 + i);
		AUX_DBG(&aux->base, "%16ph", buf);
		AUX_DBG(&aux->base, "%16ph", buf);
		memcpy(data, buf, size);
		memcpy(data, buf, *size);
	}
	}


	ret = 0;
	ret = 0;
+2 −2
Original line number Original line Diff line number Diff line
@@ -51,7 +51,7 @@ nvkm_i2c_aux_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
			if (mcnt || remaining > 16)
			if (mcnt || remaining > 16)
				cmd |= 4; /* MOT */
				cmd |= 4; /* MOT */


			ret = aux->func->xfer(aux, true, cmd, msg->addr, ptr, cnt);
			ret = aux->func->xfer(aux, true, cmd, msg->addr, ptr, &cnt);
			if (ret < 0) {
			if (ret < 0) {
				nvkm_i2c_aux_release(aux);
				nvkm_i2c_aux_release(aux);
				return ret;
				return ret;
@@ -115,7 +115,7 @@ nvkm_i2c_aux_acquire(struct nvkm_i2c_aux *aux)


int
int
nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *aux, bool retry, u8 type,
nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *aux, bool retry, u8 type,
		  u32 addr, u8 *data, u8 size)
		  u32 addr, u8 *data, u8 *size)
{
{
	return aux->func->xfer(aux, retry, type, addr, data, size);
	return aux->func->xfer(aux, retry, type, addr, data, size);
}
}
+2 −2
Original line number Original line Diff line number Diff line
@@ -4,7 +4,7 @@


struct nvkm_i2c_aux_func {
struct nvkm_i2c_aux_func {
	int  (*xfer)(struct nvkm_i2c_aux *, bool retry, u8 type,
	int  (*xfer)(struct nvkm_i2c_aux *, bool retry, u8 type,
		     u32 addr, u8 *data, u8 size);
		     u32 addr, u8 *data, u8 *size);
	int  (*lnk_ctl)(struct nvkm_i2c_aux *, int link_nr, int link_bw,
	int  (*lnk_ctl)(struct nvkm_i2c_aux *, int link_nr, int link_bw,
			bool enhanced_framing);
			bool enhanced_framing);
};
};
@@ -15,7 +15,7 @@ int nvkm_i2c_aux_new_(const struct nvkm_i2c_aux_func *, struct nvkm_i2c_pad *,
		      int id, struct nvkm_i2c_aux **);
		      int id, struct nvkm_i2c_aux **);
void nvkm_i2c_aux_del(struct nvkm_i2c_aux **);
void nvkm_i2c_aux_del(struct nvkm_i2c_aux **);
int nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *, bool retry, u8 type,
int nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *, bool retry, u8 type,
		      u32 addr, u8 *data, u8 size);
		      u32 addr, u8 *data, u8 *size);


int g94_i2c_aux_new(struct nvkm_i2c_pad *, int, u8, struct nvkm_i2c_aux **);
int g94_i2c_aux_new(struct nvkm_i2c_pad *, int, u8, struct nvkm_i2c_aux **);
int gm200_i2c_aux_new(struct nvkm_i2c_pad *, int, u8, struct nvkm_i2c_aux **);
int gm200_i2c_aux_new(struct nvkm_i2c_pad *, int, u8, struct nvkm_i2c_aux **);
Loading