Commit 507e8e5e authored by Dave Airlie's avatar Dave Airlie

Merge branch 'linux-4.13' of git://github.com/skeggsb/linux into drm-fixes

nouveau regression fixes.

* 'linux-4.13' of git://github.com/skeggsb/linux:
  drm/nouveau/kms: remove call to drm_crtc_vblank_off() during unload/suspend
  drm/nouveau/kms/nv50: update vblank state in response to modeset actions
  drm/nouveau/disp: add tv encoders to output resource mapping
  drm/nouveau/i2c/gf119-: add support for address-only transactions
parents 520eccdf 746c842d
......@@ -1158,8 +1158,6 @@ nouveau_connector_aux_xfer(struct drm_dp_aux *obj, struct drm_dp_aux_msg *msg)
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)
......
......@@ -409,7 +409,6 @@ nouveau_display_fini(struct drm_device *dev, bool suspend)
struct nouveau_display *disp = nouveau_display(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
struct drm_connector *connector;
struct drm_crtc *crtc;
if (!suspend) {
if (drm_drv_uses_atomic_modeset(dev))
......@@ -418,10 +417,6 @@ nouveau_display_fini(struct drm_device *dev, bool suspend)
drm_crtc_force_disable_all(dev);
}
/* Make sure that drm and hw vblank irqs get properly disabled. */
drm_for_each_crtc(crtc, dev)
drm_crtc_vblank_off(crtc);
/* disable flip completion events */
nvif_notify_put(&drm->flip);
......
......@@ -3674,15 +3674,24 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
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);
......@@ -3931,6 +3940,8 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
NV_ATOMIC(drm, "%s: clr %04x (set %04x)\n", crtc->name,
asyh->clr.mask, asyh->set.mask);
if (crtc_state->active && !asyh->state.active)
drm_crtc_vblank_off(crtc);
if (asyh->clr.mask) {
nv50_head_flush_clr(head, asyh, atom->flush_disable);
......@@ -4016,11 +4027,13 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
nv50_head_flush_set(head, asyh);
interlock_core = 1;
}
}
for_each_crtc_in_state(state, crtc, crtc_state, i) {
if (crtc->state->event)
drm_crtc_vblank_get(crtc);
if (asyh->state.active) {
if (!crtc_state->active)
drm_crtc_vblank_on(crtc);
if (asyh->state.event)
drm_crtc_vblank_get(crtc);
}
}
/* Update plane(s). */
......@@ -4067,12 +4080,14 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
if (crtc->state->event) {
unsigned long flags;
/* Get correct count/ts if racing with vblank irq */
drm_accurate_vblank_count(crtc);
if (crtc->state->active)
drm_accurate_vblank_count(crtc);
spin_lock_irqsave(&crtc->dev->event_lock, flags);
drm_crtc_send_vblank_event(crtc, crtc->state->event);
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
crtc->state->event = NULL;
drm_crtc_vblank_put(crtc);
if (crtc->state->active)
drm_crtc_vblank_put(crtc);
}
}
......
......@@ -22,6 +22,7 @@ struct nvkm_ior {
unsigned proto_evo:4;
enum nvkm_ior_proto {
CRT,
TV,
TMDS,
LVDS,
DP,
......
......@@ -62,6 +62,7 @@ nvkm_outp_xlat(struct nvkm_outp *outp, enum nvkm_ior_type *type)
case 0:
switch (outp->info.type) {
case DCB_OUTPUT_ANALOG: *type = DAC; return CRT;
case DCB_OUTPUT_TV : *type = DAC; return TV;
case DCB_OUTPUT_TMDS : *type = SOR; return TMDS;
case DCB_OUTPUT_LVDS : *type = SOR; return LVDS;
case DCB_OUTPUT_DP : *type = SOR; return DP;
......
......@@ -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
......@@ -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);
}
......
......@@ -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_aux **);
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 { \
......
......@@ -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 *obj, bool retry,
}
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 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
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, int index, u8 drive,
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);
}
/*
* 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);
}
......@@ -105,9 +105,9 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
}
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 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
static const struct nvkm_i2c_aux_func
gm200_i2c_aux_func = {
.address_only = true,
.xfer = gm200_i2c_aux_xfer,
};
......
......@@ -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, int id, struct nvkm_i2c_pad **ppad)
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
......
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