diff options
author | Dave Airlie <airlied@redhat.com> | 2014-09-16 06:20:53 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-09-16 06:20:53 +1000 |
commit | 4ac073640a528662a7c072a30e92e70ce00ded33 (patch) | |
tree | 8c5394ff496af5edf31d7124a7fab95756b97a75 /drivers/gpu/drm/nouveau/nv50_display.c | |
parent | 19524f7c59c19854caf5b82d89bc558e38da5790 (diff) | |
parent | cc2a9071458254cb0db6153811734750da0233ea (diff) | |
download | talos-op-linux-4ac073640a528662a7c072a30e92e70ce00ded33.tar.gz talos-op-linux-4ac073640a528662a7c072a30e92e70ce00ded33.zip |
Merge branch 'linux-3.18' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-next
This is the main merge request for Nouveau 3.18, overview:
- various bits of roy's gt21x clock work
- various bits of kepler memory clock work (don't get too excited, there's at least one more major bit left that's busting higher freqs)
- misc fan control improvements
- kepler hdmi infoframe fixes
- dp audio
- l2 cache + cbc improvements
* 'linux-3.18' of git://anongit.freedesktop.org/git/nouveau/linux-2.6: (68 commits)
drm/gt214-/disp: enable dp audio
drm/gt214-/kms: fix hda eld regression
drm/g94-/disp: calculate some dp audio constants
drm/gt214-/kms: perform hda codec setup on displayport too
drm/gk104-/disp: infoframe registers moved yet again on kepler
drm/nouveau/bios: parse older ramcfg/timing data like we do newer ones
drm/nva3/fb/ram: Per-partition regs
drm/nouveau/fb/ram: Support strided regs
drm/nv50/fb/ram: Store the number of partitions in the designated fields
drm/nv50/kms: Set VBLANK time in modeset script
drm/nouveau/bios: Add rammap support for version 1.0
drm/gf100-/pwr/memx: block host and fifo around reclock
drm/nouveau/pwr/memx: fix command ordering around block/unblock
drm/nouveau/pwr/memx: rename fb off/on to block/unblock
drm/nva3/clk: Pause the GPU before reclocking
drm/nouveau/gpio: rename g92 class to g94
drm/gk104-/fb/ram: move fb enable/disable to same place as nvidia
drm/gk104/fb/ram: twiddle some more bits when reclocking
drm/nouveau/bios: parse another large chunk of random memory config data
drm/gk104-/fb/ram: perform certain steps only when bios data differs
...
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_display.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 40 |
1 files changed, 25 insertions, 15 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 03949eaa629f..fdb3e1adea1e 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -1066,7 +1066,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode, u32 vscan = (mode->flags & DRM_MODE_FLAG_DBLSCAN) ? 2 : 1; u32 hactive, hsynce, hbackp, hfrontp, hblanke, hblanks; u32 vactive, vsynce, vbackp, vfrontp, vblanke, vblanks; - u32 vblan2e = 0, vblan2s = 1; + u32 vblan2e = 0, vblan2s = 1, vblankus = 0; u32 *push; int ret; @@ -1083,6 +1083,11 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode, vblanke = vsynce + vbackp; vfrontp = (mode->vsync_start - mode->vdisplay) * vscan / ilace; vblanks = vactive - vfrontp - 1; + /* XXX: Safe underestimate, even "0" works */ + vblankus = (vactive - mode->vdisplay - 2) * hactive; + vblankus *= 1000; + vblankus /= mode->clock; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { vblan2e = vactive + vsynce + vbackp; vblan2s = vblan2e + (mode->vdisplay * vscan / ilace); @@ -1099,14 +1104,14 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode, evo_mthd(push, 0x0804 + (nv_crtc->index * 0x400), 2); evo_data(push, 0x00800000 | mode->clock); evo_data(push, (ilace == 2) ? 2 : 0); - evo_mthd(push, 0x0810 + (nv_crtc->index * 0x400), 6); + evo_mthd(push, 0x0810 + (nv_crtc->index * 0x400), 8); evo_data(push, 0x00000000); evo_data(push, (vactive << 16) | hactive); evo_data(push, ( vsynce << 16) | hsynce); evo_data(push, (vblanke << 16) | hblanke); evo_data(push, (vblanks << 16) | hblanks); evo_data(push, (vblan2e << 16) | vblan2s); - evo_mthd(push, 0x082c + (nv_crtc->index * 0x400), 1); + evo_data(push, vblankus); evo_data(push, 0x00000000); evo_mthd(push, 0x0900 + (nv_crtc->index * 0x400), 2); evo_data(push, 0x00000311); @@ -1651,17 +1656,21 @@ static void nv50_audio_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); struct nouveau_connector *nv_connector; struct nv50_disp *disp = nv50_disp(encoder->dev); - struct { - struct nv50_disp_mthd_v1 base; - struct nv50_disp_sor_hda_eld_v0 eld; + struct __packed { + struct { + struct nv50_disp_mthd_v1 mthd; + struct nv50_disp_sor_hda_eld_v0 eld; + } base; u8 data[sizeof(nv_connector->base.eld)]; } args = { - .base.version = 1, - .base.method = NV50_DISP_MTHD_V1_SOR_HDA_ELD, - .base.hasht = nv_encoder->dcb->hasht, - .base.hashm = nv_encoder->dcb->hashm, + .base.mthd.version = 1, + .base.mthd.method = NV50_DISP_MTHD_V1_SOR_HDA_ELD, + .base.mthd.hasht = nv_encoder->dcb->hasht, + .base.mthd.hashm = (0xf0ff & nv_encoder->dcb->hashm) | + (0x0100 << nv_crtc->index), }; nv_connector = nouveau_encoder_connector_get(nv_encoder); @@ -1671,11 +1680,11 @@ nv50_audio_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) drm_edid_to_eld(&nv_connector->base, nv_connector->edid); memcpy(args.data, nv_connector->base.eld, sizeof(args.data)); - nvif_mthd(disp->disp, 0, &args, sizeof(args)); + nvif_mthd(disp->disp, 0, &args, sizeof(args.base) + args.data[2] * 4); } static void -nv50_audio_disconnect(struct drm_encoder *encoder) +nv50_audio_disconnect(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nv50_disp *disp = nv50_disp(encoder->dev); @@ -1686,7 +1695,8 @@ nv50_audio_disconnect(struct drm_encoder *encoder) .base.version = 1, .base.method = NV50_DISP_MTHD_V1_SOR_HDA_ELD, .base.hasht = nv_encoder->dcb->hasht, - .base.hashm = nv_encoder->dcb->hashm, + .base.hashm = (0xf0ff & nv_encoder->dcb->hashm) | + (0x0100 << nv_crtc->index), }; nvif_mthd(disp->disp, 0, &args, sizeof(args)); @@ -1745,8 +1755,6 @@ nv50_hdmi_disconnect(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc) (0x0100 << nv_crtc->index), }; - nv50_audio_disconnect(encoder); - nvif_mthd(disp->disp, 0, &args, sizeof(args)); } @@ -1855,6 +1863,7 @@ nv50_sor_disconnect(struct drm_encoder *encoder) if (nv_crtc) { nv50_crtc_prepare(&nv_crtc->base); nv50_sor_ctrl(nv_encoder, 1 << nv_crtc->index, 0); + nv50_audio_disconnect(encoder, nv_crtc); nv50_hdmi_disconnect(&nv_encoder->base.base, nv_crtc); } } @@ -1954,6 +1963,7 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, proto = 0x8; else proto = 0x9; + nv50_audio_mode_set(encoder, mode); break; default: BUG_ON(1); |