mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-08 06:44:35 +08:00
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
This commit is contained in:
commit
507e8e5e5d
@ -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 @@ 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, 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);
|
||||
}
|
||||
|
35
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgf119.c
Normal file
35
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgf119.c
Normal file
@ -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);
|
||||
}
|
@ -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 @@ out:
|
||||
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user