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

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
...@@ -64,7 +64,7 @@ void nvkm_i2c_aux_monitor(struct nvkm_i2c_aux *, bool monitor); ...@@ -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) ...@@ -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) ...@@ -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;
......
...@@ -1147,6 +1147,7 @@ nouveau_connector_aux_xfer(struct drm_dp_aux *obj, struct drm_dp_aux_msg *msg) ...@@ -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) ...@@ -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;
......
...@@ -134,7 +134,7 @@ struct anx9805_aux { ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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;
......
...@@ -51,7 +51,7 @@ nvkm_i2c_aux_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ...@@ -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) ...@@ -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);
} }
......
...@@ -4,7 +4,7 @@ ...@@ -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 *, ...@@ -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 **);
......
...@@ -74,7 +74,7 @@ g94_i2c_aux_init(struct g94_i2c_aux *aux) ...@@ -74,7 +74,7 @@ g94_i2c_aux_init(struct g94_i2c_aux *aux)
static int static int
g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
u8 type, u32 addr, u8 *data, u8 size) u8 type, u32 addr, u8 *data, u8 *size)
{ {
struct g94_i2c_aux *aux = g94_i2c_aux(obj); struct g94_i2c_aux *aux = g94_i2c_aux(obj);
struct nvkm_device *device = aux->base.pad->i2c->subdev.device; struct nvkm_device *device = aux->base.pad->i2c->subdev.device;
...@@ -83,7 +83,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ...@@ -83,7 +83,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
u32 xbuf[4] = {}; u32 xbuf[4] = {};
int ret, i; int ret, i;
AUX_TRACE(&aux->base, "%d: %08x %d", type, addr, size); AUX_TRACE(&aux->base, "%d: %08x %d", type, addr, *size);
ret = g94_i2c_aux_init(aux); ret = g94_i2c_aux_init(aux);
if (ret < 0) if (ret < 0)
...@@ -97,7 +97,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ...@@ -97,7 +97,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
} }
if (!(type & 1)) { if (!(type & 1)) {
memcpy(xbuf, data, size); memcpy(xbuf, data, *size);
for (i = 0; i < 16; i += 4) { for (i = 0; i < 16; i += 4) {
AUX_TRACE(&aux->base, "wr %08x", xbuf[i / 4]); AUX_TRACE(&aux->base, "wr %08x", xbuf[i / 4]);
nvkm_wr32(device, 0x00e4c0 + base + i, xbuf[i / 4]); nvkm_wr32(device, 0x00e4c0 + base + i, xbuf[i / 4]);
...@@ -107,7 +107,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ...@@ -107,7 +107,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
ctrl = nvkm_rd32(device, 0x00e4e4 + base); ctrl = nvkm_rd32(device, 0x00e4e4 + base);
ctrl &= ~0x0001f0ff; ctrl &= ~0x0001f0ff;
ctrl |= type << 12; ctrl |= type << 12;
ctrl |= size - 1; ctrl |= *size - 1;
nvkm_wr32(device, 0x00e4e0 + base, addr); nvkm_wr32(device, 0x00e4e0 + base, addr);
/* (maybe) retry transaction a number of times on failure... */ /* (maybe) retry transaction a number of times on failure... */
...@@ -151,7 +151,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ...@@ -151,7 +151,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
xbuf[i / 4] = nvkm_rd32(device, 0x00e4d0 + base + i); xbuf[i / 4] = nvkm_rd32(device, 0x00e4d0 + base + i);
AUX_TRACE(&aux->base, "rd %08x", xbuf[i / 4]); AUX_TRACE(&aux->base, "rd %08x", xbuf[i / 4]);
} }
memcpy(data, xbuf, size); memcpy(data, xbuf, *size);
} }
out: out:
......
...@@ -74,7 +74,7 @@ gm200_i2c_aux_init(struct gm200_i2c_aux *aux) ...@@ -74,7 +74,7 @@ gm200_i2c_aux_init(struct gm200_i2c_aux *aux)
static int static int
gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
u8 type, u32 addr, u8 *data, u8 size) u8 type, u32 addr, u8 *data, u8 *size)
{ {
struct gm200_i2c_aux *aux = gm200_i2c_aux(obj); struct gm200_i2c_aux *aux = gm200_i2c_aux(obj);
struct nvkm_device *device = aux->base.pad->i2c->subdev.device; struct nvkm_device *device = aux->base.pad->i2c->subdev.device;
...@@ -83,7 +83,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ...@@ -83,7 +83,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
u32 xbuf[4] = {}; u32 xbuf[4] = {};
int ret, i; int ret, i;
AUX_TRACE(&aux->base, "%d: %08x %d", type, addr, size); AUX_TRACE(&aux->base, "%d: %08x %d", type, addr, *size);
ret = gm200_i2c_aux_init(aux); ret = gm200_i2c_aux_init(aux);
if (ret < 0) if (ret < 0)
...@@ -97,7 +97,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ...@@ -97,7 +97,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
} }
if (!(type & 1)) { if (!(type & 1)) {
memcpy(xbuf, data, size); memcpy(xbuf, data, *size);
for (i = 0; i < 16; i += 4) { for (i = 0; i < 16; i += 4) {
AUX_TRACE(&aux->base, "wr %08x", xbuf[i / 4]); AUX_TRACE(&aux->base, "wr %08x", xbuf[i / 4]);
nvkm_wr32(device, 0x00d930 + base + i, xbuf[i / 4]); nvkm_wr32(device, 0x00d930 + base + i, xbuf[i / 4]);
...@@ -107,7 +107,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ...@@ -107,7 +107,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
ctrl = nvkm_rd32(device, 0x00d954 + base); ctrl = nvkm_rd32(device, 0x00d954 + base);
ctrl &= ~0x0001f0ff; ctrl &= ~0x0001f0ff;
ctrl |= type << 12; ctrl |= type << 12;
ctrl |= size - 1; ctrl |= *size - 1;
nvkm_wr32(device, 0x00d950 + base, addr); nvkm_wr32(device, 0x00d950 + base, addr);
/* (maybe) retry transaction a number of times on failure... */ /* (maybe) retry transaction a number of times on failure... */
...@@ -151,7 +151,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ...@@ -151,7 +151,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
xbuf[i / 4] = nvkm_rd32(device, 0x00d940 + base + i); xbuf[i / 4] = nvkm_rd32(device, 0x00d940 + base + i);
AUX_TRACE(&aux->base, "rd %08x", xbuf[i / 4]); AUX_TRACE(&aux->base, "rd %08x", xbuf[i / 4]);
} }
memcpy(data, xbuf, size); memcpy(data, xbuf, *size);
} }
out: out:
......
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