From fd18171105d6f8bab5bcdd86186579bae6ec37ba Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 4 Sep 2017 14:11:22 +0200 Subject: [PATCH] 4.12-stable patches added patches: drm-nouveau-i2c-gf119-add-support-for-address-only-transactions.patch --- ...upport-for-address-only-transactions.patch | 262 ++++++++++++++++++ queue-4.12/series | 1 + 2 files changed, 263 insertions(+) create mode 100644 queue-4.12/drm-nouveau-i2c-gf119-add-support-for-address-only-transactions.patch diff --git a/queue-4.12/drm-nouveau-i2c-gf119-add-support-for-address-only-transactions.patch b/queue-4.12/drm-nouveau-i2c-gf119-add-support-for-address-only-transactions.patch new file mode 100644 index 00000000000..453357b0074 --- /dev/null +++ b/queue-4.12/drm-nouveau-i2c-gf119-add-support-for-address-only-transactions.patch @@ -0,0 +1,262 @@ +From 13a86519202c5d119d83640d6f781f3181205d2c Mon Sep 17 00:00:00 2001 +From: Ben Skeggs +Date: Wed, 19 Jul 2017 16:49:59 +1000 +Subject: drm/nouveau/i2c/gf119-: add support for address-only transactions + +From: Ben Skeggs + +commit 13a86519202c5d119d83640d6f781f3181205d2c upstream. + +Since switching the I2C-over-AUX helpers, there have been regressions on +some display combinations due to us not having support for "address only" +transactions. + +This commits enables support for them for GF119 and newer. + +Earlier GPUs have been reverted to a custom I2C-over-AUX algorithm. + +Signed-off-by: Ben Skeggs +Cc: Ilia Mirkin +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nouveau_connector.c | 2 - + drivers/gpu/drm/nouveau/nv50_display.c | 13 ++++++- + drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c | 4 ++ + drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h | 6 +++ + drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c | 30 +++++++++++------- + drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgf119.c | 35 +++++++++++++++++++++ + drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c | 5 +-- + drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c | 4 +- + 9 files changed, 81 insertions(+), 19 deletions(-) + +--- a/drivers/gpu/drm/nouveau/nouveau_connector.c ++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c +@@ -1155,8 +1155,6 @@ nouveau_connector_aux_xfer(struct drm_dp + return -ENODEV; + if (WARN_ON(msg->size > 16)) + return -E2BIG; +- if (msg->size == 0) +- return msg->size; + + ret = nvkm_i2c_aux_acquire(aux); + if (ret) +--- a/drivers/gpu/drm/nouveau/nv50_display.c ++++ b/drivers/gpu/drm/nouveau/nv50_display.c +@@ -3618,15 +3618,24 @@ nv50_sor_create(struct drm_connector *co + drm_mode_connector_attach_encoder(connector, encoder); + + if (dcbe->type == DCB_OUTPUT_DP) { ++ struct nv50_disp *disp = nv50_disp(encoder->dev); + struct nvkm_i2c_aux *aux = + nvkm_i2c_aux_find(i2c, dcbe->i2c_index); + if (aux) { +- nv_encoder->i2c = &nv_connector->aux.ddc; ++ if (disp->disp->oclass < GF110_DISP) { ++ /* HW has no support for address-only ++ * transactions, so we're required to ++ * use custom I2C-over-AUX code. ++ */ ++ nv_encoder->i2c = &aux->i2c; ++ } else { ++ nv_encoder->i2c = &nv_connector->aux.ddc; ++ } + nv_encoder->aux = aux; + } + + /*TODO: Use DP Info Table to check for support. */ +- if (nv50_disp(encoder->dev)->disp->oclass >= GF110_DISP) { ++ if (disp->disp->oclass >= GF110_DISP) { + ret = nv50_mstm_new(nv_encoder, &nv_connector->aux, 16, + nv_connector->base.base.id, + &nv_encoder->dp.mstm); +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild +@@ -25,6 +25,7 @@ nvkm-y += nvkm/subdev/i2c/bit.o + + nvkm-y += nvkm/subdev/i2c/aux.o + nvkm-y += nvkm/subdev/i2c/auxg94.o ++nvkm-y += nvkm/subdev/i2c/auxgf119.o + nvkm-y += nvkm/subdev/i2c/auxgm200.o + + nvkm-y += nvkm/subdev/i2c/anx9805.o +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c +@@ -117,6 +117,10 @@ int + nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *aux, bool retry, u8 type, + u32 addr, u8 *data, u8 *size) + { ++ if (!*size && !aux->func->address_only) { ++ AUX_ERR(aux, "address-only transaction dropped"); ++ return -ENOSYS; ++ } + return aux->func->xfer(aux, retry, type, addr, data, size); + } + +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h +@@ -3,6 +3,7 @@ + #include "pad.h" + + struct nvkm_i2c_aux_func { ++ bool address_only; + int (*xfer)(struct nvkm_i2c_aux *, bool retry, u8 type, + u32 addr, u8 *data, u8 *size); + int (*lnk_ctl)(struct nvkm_i2c_aux *, int link_nr, int link_bw, +@@ -17,7 +18,12 @@ void nvkm_i2c_aux_del(struct nvkm_i2c_au + int nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *, bool retry, u8 type, + u32 addr, u8 *data, u8 *size); + ++int g94_i2c_aux_new_(const struct nvkm_i2c_aux_func *, 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 g94_i2c_aux_xfer(struct nvkm_i2c_aux *, bool, u8, u32, u8 *, u8 *); ++int gf119_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 **); + + #define AUX_MSG(b,l,f,a...) do { \ +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c +@@ -72,7 +72,7 @@ g94_i2c_aux_init(struct g94_i2c_aux *aux + return 0; + } + +-static int ++int + g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, + u8 type, u32 addr, u8 *data, u8 *size) + { +@@ -105,9 +105,9 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *ob + } + + ctrl = nvkm_rd32(device, 0x00e4e4 + base); +- ctrl &= ~0x0001f0ff; ++ ctrl &= ~0x0001f1ff; + ctrl |= type << 12; +- ctrl |= *size - 1; ++ ctrl |= (*size ? (*size - 1) : 0x00000100); + nvkm_wr32(device, 0x00e4e0 + base, addr); + + /* (maybe) retry transaction a number of times on failure... */ +@@ -160,14 +160,10 @@ out: + return ret < 0 ? ret : (stat & 0x000f0000) >> 16; + } + +-static const struct nvkm_i2c_aux_func +-g94_i2c_aux_func = { +- .xfer = g94_i2c_aux_xfer, +-}; +- + int +-g94_i2c_aux_new(struct nvkm_i2c_pad *pad, int index, u8 drive, +- struct nvkm_i2c_aux **paux) ++g94_i2c_aux_new_(const struct nvkm_i2c_aux_func *func, ++ struct nvkm_i2c_pad *pad, int index, u8 drive, ++ struct nvkm_i2c_aux **paux) + { + struct g94_i2c_aux *aux; + +@@ -175,8 +171,20 @@ g94_i2c_aux_new(struct nvkm_i2c_pad *pad + return -ENOMEM; + *paux = &aux->base; + +- nvkm_i2c_aux_ctor(&g94_i2c_aux_func, pad, index, &aux->base); ++ nvkm_i2c_aux_ctor(func, pad, index, &aux->base); + aux->ch = drive; + aux->base.intr = 1 << aux->ch; + return 0; + } ++ ++static const struct nvkm_i2c_aux_func ++g94_i2c_aux = { ++ .xfer = g94_i2c_aux_xfer, ++}; ++ ++int ++g94_i2c_aux_new(struct nvkm_i2c_pad *pad, int index, u8 drive, ++ struct nvkm_i2c_aux **paux) ++{ ++ return g94_i2c_aux_new_(&g94_i2c_aux, pad, index, drive, paux); ++} +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgf119.c +@@ -0,0 +1,35 @@ ++/* ++ * Copyright 2017 Red Hat Inc. ++ * ++ * 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 "aux.h" ++ ++static const struct nvkm_i2c_aux_func ++gf119_i2c_aux = { ++ .address_only = true, ++ .xfer = g94_i2c_aux_xfer, ++}; ++ ++int ++gf119_i2c_aux_new(struct nvkm_i2c_pad *pad, int index, u8 drive, ++ struct nvkm_i2c_aux **paux) ++{ ++ return g94_i2c_aux_new_(&gf119_i2c_aux, pad, index, drive, paux); ++} +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c +@@ -105,9 +105,9 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux * + } + + ctrl = nvkm_rd32(device, 0x00d954 + base); +- ctrl &= ~0x0001f0ff; ++ ctrl &= ~0x0001f1ff; + ctrl |= type << 12; +- ctrl |= *size - 1; ++ ctrl |= (*size ? (*size - 1) : 0x00000100); + nvkm_wr32(device, 0x00d950 + base, addr); + + /* (maybe) retry transaction a number of times on failure... */ +@@ -162,6 +162,7 @@ out: + + static const struct nvkm_i2c_aux_func + gm200_i2c_aux_func = { ++ .address_only = true, + .xfer = gm200_i2c_aux_xfer, + }; + +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c +@@ -28,7 +28,7 @@ + static const struct nvkm_i2c_pad_func + gf119_i2c_pad_s_func = { + .bus_new_4 = gf119_i2c_bus_new, +- .aux_new_6 = g94_i2c_aux_new, ++ .aux_new_6 = gf119_i2c_aux_new, + .mode = g94_i2c_pad_mode, + }; + +@@ -41,7 +41,7 @@ gf119_i2c_pad_s_new(struct nvkm_i2c *i2c + static const struct nvkm_i2c_pad_func + gf119_i2c_pad_x_func = { + .bus_new_4 = gf119_i2c_bus_new, +- .aux_new_6 = g94_i2c_aux_new, ++ .aux_new_6 = gf119_i2c_aux_new, + }; + + int diff --git a/queue-4.12/series b/queue-4.12/series index fa189c23824..d3347fa3ef4 100644 --- a/queue-4.12/series +++ b/queue-4.12/series @@ -23,3 +23,4 @@ lib-mpi-kunmap-after-finishing-accessing-buffer.patch xfrm-policy-check-policy-direction-value.patch drm-ttm-fix-accounting-error-when-fail-to-get-pages-for-pool.patch nvme-fix-the-definition-of-the-doorbell-buffer-config-support-bit.patch +drm-nouveau-i2c-gf119-add-support-for-address-only-transactions.patch -- 2.47.3