diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-04 03:02:26 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-04 03:02:26 +0300 |
commit | 906dde0f355bd97c080c215811ae7db1137c4af8 (patch) | |
tree | 1e1b4ba58a59c4027f06d86e7430566ee0dcbb15 /drivers/gpu/drm/nouveau/nv50_display.c | |
parent | 69c0067aa3f40d3e52ab78643aecb17d669d3389 (diff) | |
parent | 7846b12fe0b5feab5446d892f41b5140c1419109 (diff) | |
download | linux-906dde0f355bd97c080c215811ae7db1137c4af8.tar.xz |
Merge tag 'drm-for-v4.14' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie:
"This is the main drm pull request for 4.14 merge window.
I'm sending this early, as my continuing journey into fatherhood is
occurring really soon now, I'm going to be mostly useless for the next
couple of weeks, though I may be able to read email, I doubt I'll be
doing much patch applications or git sending. If anything urgent pops
up I've asked Daniel/Jani/Alex/Sean to try and direct stuff towards
you.
Outside drm changes:
Some rcar-du updates that touch the V4L tree, all acks should be in
place. It adds one export to the radix tree code for new i915 use
case. There are some minor AGP cleanups (don't see that too often).
Changes to the vbox driver in staging to avoid breaking compilation.
Summary:
core:
- Atomic helper fixes
- Atomic UAPI fixes
- Add YCBCR 4:2:0 support
- Drop set_busid hook
- Refactor fb_helper locking
- Remove a bunch of internal APIs
- Add a bunch of better default handlers
- Format modifier/blob plane property added
- More internal header refactoring
- Make more internal API names consistent
- Enhanced syncobj APIs (wait/signal/reset/create signalled)
bridge:
- Add Synopsys Designware MIPI DSI host bridge driver
tiny:
- Add Pervasive Displays RePaper displays
- Add support for LEGO MINDSTORMS EV3 LCD
i915:
- Lots of GEN10/CNL support patches
- drm syncobj support
- Skylake+ watermark refactoring
- GVT vGPU 48-bit ppgtt support
- GVT performance improvements
- NOA change ioctl
- CCS (color compression) scanout support
- GPU reset improvements
amdgpu:
- Initial hugepage support
- BO migration logic rework
- Vega10 improvements
- Powerplay fixes
- Stop reprogramming the MC
- Fixes for ACP audio on stoney
- SR-IOV fixes/improvements
- Command submission overhead improvements
amdkfd:
- Non-dGPU upstreaming patches
- Scratch VA ioctl
- Image tiling modes
- Update PM4 headers for new firmware
- Drop all BUG_ONs.
nouveau:
- GP108 modesetting support.
- Disable MSI on big endian.
vmwgfx:
- Add fence fd support.
msm:
- Runtime PM improvements
exynos:
- NV12MT support
- Refactor KMS drivers
imx-drm:
- Lock scanout channel to improve memory bw
- Cleanups
etnaviv:
- GEM object population fixes
tegra:
- Prep work for Tegra186 support
- PRIME mmap support
sunxi:
- HDMI support improvements
- HDMI CEC support
omapdrm:
- HDMI hotplug IRQ support
- Big driver cleanup
- OMAP5 DSI support
rcar-du:
- vblank fixes
- VSP1 updates
arcgpu:
- Minor fixes
stm:
- Add STM32 DSI controller driver
dw_hdmi:
- Add support for Rockchip RK3399
- HDMI CEC support
atmel-hlcdc:
- Add 8-bit color support
vc4:
- Atomic fixes
- New ioctl to attach a label to a buffer object
- HDMI CEC support
- Allow userspace to dictate rendering order on submit ioctl"
* tag 'drm-for-v4.14' of git://people.freedesktop.org/~airlied/linux: (1074 commits)
drm/syncobj: Add a signal ioctl (v3)
drm/syncobj: Add a reset ioctl (v3)
drm/syncobj: Add a syncobj_array_find helper
drm/syncobj: Allow wait for submit and signal behavior (v5)
drm/syncobj: Add a CREATE_SIGNALED flag
drm/syncobj: Add a callback mechanism for replace_fence (v3)
drm/syncobj: add sync obj wait interface. (v8)
i915: Use drm_syncobj_fence_get
drm/syncobj: Add a race-free drm_syncobj_fence_get helper (v2)
drm/syncobj: Rename fence_get to find_fence
drm: kirin: Add mode_valid logic to avoid mode clocks we can't generate
drm/vmwgfx: Bump the version for fence FD support
drm/vmwgfx: Add export fence to file descriptor support
drm/vmwgfx: Add support for imported Fence File Descriptor
drm/vmwgfx: Prepare to support fence fd
drm/vmwgfx: Fix incorrect command header offset at restart
drm/vmwgfx: Support the NOP_ERROR command
drm/vmwgfx: Restart command buffers after errors
drm/vmwgfx: Move irq bottom half processing to threads
drm/vmwgfx: Don't use drm_irq_[un]install
...
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_display.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 157 |
1 files changed, 76 insertions, 81 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 2bc0dc985214..2dbf62a2ac41 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -1055,7 +1055,6 @@ nv50_wndw = { .disable_plane = drm_atomic_helper_disable_plane, .destroy = nv50_wndw_destroy, .reset = nv50_wndw_reset, - .set_property = drm_atomic_helper_plane_set_property, .atomic_duplicate_state = nv50_wndw_atomic_duplicate_state, .atomic_destroy_state = nv50_wndw_atomic_destroy_state, }; @@ -1083,8 +1082,9 @@ nv50_wndw_ctor(const struct nv50_wndw_func *func, struct drm_device *dev, wndw->func = func; wndw->dmac = dmac; - ret = drm_universal_plane_init(dev, &wndw->plane, 0, &nv50_wndw, format, - nformat, type, "%s-%d", name, index); + ret = drm_universal_plane_init(dev, &wndw->plane, 0, &nv50_wndw, + format, nformat, NULL, + type, "%s-%d", name, index); if (ret) return ret; @@ -2103,7 +2103,7 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) NV_ATOMIC(drm, "%s atomic_check %d\n", crtc->name, asyh->state.active); if (asyh->state.active) { - for_each_connector_in_state(asyh->state.state, conn, conns, i) { + for_each_new_connector_in_state(asyh->state.state, conn, conns, i) { if (conns->crtc == crtc) { asyc = nouveau_conn_atom(conns); break; @@ -2204,28 +2204,29 @@ nv50_head_lut_load(struct drm_crtc *crtc) struct nv50_disp *disp = nv50_disp(crtc->dev); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo); + u16 *r, *g, *b; int i; - for (i = 0; i < 256; i++) { - u16 r = nv_crtc->lut.r[i] >> 2; - u16 g = nv_crtc->lut.g[i] >> 2; - u16 b = nv_crtc->lut.b[i] >> 2; + r = crtc->gamma_store; + g = r + crtc->gamma_size; + b = g + crtc->gamma_size; + for (i = 0; i < 256; i++) { if (disp->disp->oclass < GF110_DISP) { - writew(r + 0x0000, lut + (i * 0x08) + 0); - writew(g + 0x0000, lut + (i * 0x08) + 2); - writew(b + 0x0000, lut + (i * 0x08) + 4); + writew((*r++ >> 2) + 0x0000, lut + (i * 0x08) + 0); + writew((*g++ >> 2) + 0x0000, lut + (i * 0x08) + 2); + writew((*b++ >> 2) + 0x0000, lut + (i * 0x08) + 4); } else { - writew(r + 0x6000, lut + (i * 0x20) + 0); - writew(g + 0x6000, lut + (i * 0x20) + 2); - writew(b + 0x6000, lut + (i * 0x20) + 4); + /* 0x6000 interferes with the 14-bit color??? */ + writew((*r++ >> 2) + 0x6000, lut + (i * 0x20) + 0); + writew((*g++ >> 2) + 0x6000, lut + (i * 0x20) + 2); + writew((*b++ >> 2) + 0x6000, lut + (i * 0x20) + 4); } } } static const struct drm_crtc_helper_funcs nv50_head_help = { - .load_lut = nv50_head_lut_load, .atomic_check = nv50_head_atomic_check, }; @@ -2234,15 +2235,6 @@ nv50_head_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t size, struct drm_modeset_acquire_ctx *ctx) { - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - u32 i; - - for (i = 0; i < size; i++) { - nv_crtc->lut.r[i] = r[i]; - nv_crtc->lut.g[i] = g[i]; - nv_crtc->lut.b[i] = b[i]; - } - nv50_head_lut_load(crtc); return 0; } @@ -2325,7 +2317,6 @@ nv50_head_func = { .destroy = nv50_head_destroy, .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, - .set_property = drm_atomic_helper_crtc_set_property, .atomic_duplicate_state = nv50_head_atomic_duplicate_state, .atomic_destroy_state = nv50_head_atomic_destroy_state, }; @@ -2340,19 +2331,13 @@ nv50_head_create(struct drm_device *dev, int index) struct nv50_base *base; struct nv50_curs *curs; struct drm_crtc *crtc; - int ret, i; + int ret; head = kzalloc(sizeof(*head), GFP_KERNEL); if (!head) return -ENOMEM; head->base.index = index; - for (i = 0; i < 256; i++) { - head->base.lut.r[i] = i << 8; - head->base.lut.g[i] = i << 8; - head->base.lut.b[i] = i << 8; - } - ret = nv50_base_new(drm, head, &base); if (ret == 0) ret = nv50_curs_new(drm, head, &curs); @@ -2762,7 +2747,8 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) if (!drm_detect_hdmi_monitor(nv_connector->edid)) return; - ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode); + ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode, + false); if (!ret) { /* We have an AVI InfoFrame, populate it to the display */ args.pwr.avi_infoframe_length @@ -3119,11 +3105,9 @@ nv50_mstc_destroy(struct drm_connector *connector) static const struct drm_connector_funcs nv50_mstc = { - .dpms = drm_atomic_helper_connector_dpms, .reset = nouveau_conn_reset, .detect = nv50_mstc_detect, .fill_modes = drm_helper_probe_single_connector_modes, - .set_property = drm_atomic_helper_connector_set_property, .destroy = nv50_mstc_destroy, .atomic_duplicate_state = nouveau_conn_atomic_duplicate_state, .atomic_destroy_state = nouveau_conn_atomic_destroy_state, @@ -3157,7 +3141,7 @@ nv50_mstc_new(struct nv50_mstm *mstm, struct drm_dp_mst_port *port, mstc->connector.funcs->reset(&mstc->connector); nouveau_conn_attach_properties(&mstc->connector); - for (i = 0; i < ARRAY_SIZE(mstm->msto) && mstm->msto; i++) + for (i = 0; i < ARRAY_SIZE(mstm->msto) && mstm->msto[i]; i++) drm_mode_connector_attach_encoder(&mstc->connector, &mstm->msto[i]->encoder); drm_object_attach_property(&mstc->connector.base, dev->mode_config.path_property, 0); @@ -3913,9 +3897,9 @@ static void nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; - struct drm_crtc_state *crtc_state; + struct drm_crtc_state *new_crtc_state, *old_crtc_state; struct drm_crtc *crtc; - struct drm_plane_state *plane_state; + struct drm_plane_state *new_plane_state; struct drm_plane *plane; struct nouveau_drm *drm = nouveau_drm(dev); struct nv50_disp *disp = nv50_disp(dev); @@ -3934,13 +3918,13 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) mutex_lock(&disp->mutex); /* Disable head(s). */ - for_each_crtc_in_state(state, crtc, crtc_state, i) { - struct nv50_head_atom *asyh = nv50_head_atom(crtc->state); + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + struct nv50_head_atom *asyh = nv50_head_atom(new_crtc_state); struct nv50_head *head = nv50_head(crtc); NV_ATOMIC(drm, "%s: clr %04x (set %04x)\n", crtc->name, asyh->clr.mask, asyh->set.mask); - if (crtc_state->active && !asyh->state.active) + if (old_crtc_state->active && !new_crtc_state->active) drm_crtc_vblank_off(crtc); if (asyh->clr.mask) { @@ -3950,8 +3934,8 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) } /* Disable plane(s). */ - for_each_plane_in_state(state, plane, plane_state, i) { - struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane->state); + for_each_new_plane_in_state(state, plane, new_plane_state, i) { + struct nv50_wndw_atom *asyw = nv50_wndw_atom(new_plane_state); struct nv50_wndw *wndw = nv50_wndw(plane); NV_ATOMIC(drm, "%s: clr %02x (set %02x)\n", plane->name, @@ -4016,8 +4000,8 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) } /* Update head(s). */ - for_each_crtc_in_state(state, crtc, crtc_state, i) { - struct nv50_head_atom *asyh = nv50_head_atom(crtc->state); + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + struct nv50_head_atom *asyh = nv50_head_atom(new_crtc_state); struct nv50_head *head = nv50_head(crtc); NV_ATOMIC(drm, "%s: set %04x (clr %04x)\n", crtc->name, @@ -4028,17 +4012,17 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) interlock_core = 1; } - if (asyh->state.active) { - if (!crtc_state->active) + if (new_crtc_state->active) { + if (!old_crtc_state->active) drm_crtc_vblank_on(crtc); - if (asyh->state.event) + if (new_crtc_state->event) drm_crtc_vblank_get(crtc); } } /* Update plane(s). */ - for_each_plane_in_state(state, plane, plane_state, i) { - struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane->state); + for_each_new_plane_in_state(state, plane, new_plane_state, i) { + struct nv50_wndw_atom *asyw = nv50_wndw_atom(new_plane_state); struct nv50_wndw *wndw = nv50_wndw(plane); NV_ATOMIC(drm, "%s: set %02x (clr %02x)\n", plane->name, @@ -4068,25 +4052,26 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) mutex_unlock(&disp->mutex); /* Wait for HW to signal completion. */ - for_each_plane_in_state(state, plane, plane_state, i) { - struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane->state); + for_each_new_plane_in_state(state, plane, new_plane_state, i) { + struct nv50_wndw_atom *asyw = nv50_wndw_atom(new_plane_state); struct nv50_wndw *wndw = nv50_wndw(plane); int ret = nv50_wndw_wait_armed(wndw, asyw); if (ret) NV_ERROR(drm, "%s: timeout\n", plane->name); } - for_each_crtc_in_state(state, crtc, crtc_state, i) { - if (crtc->state->event) { + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { + if (new_crtc_state->event) { unsigned long flags; /* Get correct count/ts if racing with vblank irq */ - if (crtc->state->active) - drm_accurate_vblank_count(crtc); + if (new_crtc_state->active) + drm_crtc_accurate_vblank_count(crtc); spin_lock_irqsave(&crtc->dev->event_lock, flags); - drm_crtc_send_vblank_event(crtc, crtc->state->event); + drm_crtc_send_vblank_event(crtc, new_crtc_state->event); spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - crtc->state->event = NULL; - if (crtc->state->active) + + new_crtc_state->event = NULL; + if (new_crtc_state->active) drm_crtc_vblank_put(crtc); } } @@ -4111,7 +4096,7 @@ nv50_disp_atomic_commit(struct drm_device *dev, { struct nouveau_drm *drm = nouveau_drm(dev); struct nv50_disp *disp = nv50_disp(dev); - struct drm_plane_state *plane_state; + struct drm_plane_state *old_plane_state; struct drm_plane *plane; struct drm_crtc *crtc; bool active = false; @@ -4134,12 +4119,17 @@ nv50_disp_atomic_commit(struct drm_device *dev, if (!nonblock) { ret = drm_atomic_helper_wait_for_fences(dev, state, true); if (ret) - goto done; + goto err_cleanup; } - for_each_plane_in_state(state, plane, plane_state, i) { - struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane_state); + ret = drm_atomic_helper_swap_state(state, true); + if (ret) + goto err_cleanup; + + for_each_old_plane_in_state(state, plane, old_plane_state, i) { + struct nv50_wndw_atom *asyw = nv50_wndw_atom(old_plane_state); struct nv50_wndw *wndw = nv50_wndw(plane); + if (asyw->set.image) { asyw->ntfy.handle = wndw->dmac->sync.handle; asyw->ntfy.offset = wndw->ntfy; @@ -4150,7 +4140,6 @@ nv50_disp_atomic_commit(struct drm_device *dev, } } - drm_atomic_helper_swap_state(state, true); drm_atomic_state_get(state); if (nonblock) @@ -4162,7 +4151,7 @@ nv50_disp_atomic_commit(struct drm_device *dev, if (crtc->state->enable) { if (!drm->have_disp_power_ref) { drm->have_disp_power_ref = true; - return ret; + return 0; } active = true; break; @@ -4174,6 +4163,9 @@ nv50_disp_atomic_commit(struct drm_device *dev, drm->have_disp_power_ref = false; } +err_cleanup: + if (ret) + drm_atomic_helper_cleanup_planes(dev, state); done: pm_runtime_put_autosuspend(dev->dev); return ret; @@ -4200,18 +4192,19 @@ nv50_disp_outp_atomic_add(struct nv50_atom *atom, struct drm_encoder *encoder) static int nv50_disp_outp_atomic_check_clr(struct nv50_atom *atom, - struct drm_connector *connector) + struct drm_connector_state *old_connector_state) { - struct drm_encoder *encoder = connector->state->best_encoder; - struct drm_crtc_state *crtc_state; + struct drm_encoder *encoder = old_connector_state->best_encoder; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_crtc *crtc; struct nv50_outp_atom *outp; - if (!(crtc = connector->state->crtc)) + if (!(crtc = old_connector_state->crtc)) return 0; - crtc_state = drm_atomic_get_existing_crtc_state(&atom->state, crtc); - if (crtc->state->active && drm_atomic_crtc_needs_modeset(crtc_state)) { + old_crtc_state = drm_atomic_get_old_crtc_state(&atom->state, crtc); + new_crtc_state = drm_atomic_get_new_crtc_state(&atom->state, crtc); + if (old_crtc_state->active && drm_atomic_crtc_needs_modeset(new_crtc_state)) { outp = nv50_disp_outp_atomic_add(atom, encoder); if (IS_ERR(outp)) return PTR_ERR(outp); @@ -4232,15 +4225,15 @@ nv50_disp_outp_atomic_check_set(struct nv50_atom *atom, struct drm_connector_state *connector_state) { struct drm_encoder *encoder = connector_state->best_encoder; - struct drm_crtc_state *crtc_state; + struct drm_crtc_state *new_crtc_state; struct drm_crtc *crtc; struct nv50_outp_atom *outp; if (!(crtc = connector_state->crtc)) return 0; - crtc_state = drm_atomic_get_existing_crtc_state(&atom->state, crtc); - if (crtc_state->active && drm_atomic_crtc_needs_modeset(crtc_state)) { + new_crtc_state = drm_atomic_get_new_crtc_state(&atom->state, crtc); + if (new_crtc_state->active && drm_atomic_crtc_needs_modeset(new_crtc_state)) { outp = nv50_disp_outp_atomic_add(atom, encoder); if (IS_ERR(outp)) return PTR_ERR(outp); @@ -4256,7 +4249,7 @@ static int nv50_disp_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { struct nv50_atom *atom = nv50_atom(state); - struct drm_connector_state *connector_state; + struct drm_connector_state *old_connector_state, *new_connector_state; struct drm_connector *connector; int ret, i; @@ -4264,12 +4257,12 @@ nv50_disp_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) if (ret) return ret; - for_each_connector_in_state(state, connector, connector_state, i) { - ret = nv50_disp_outp_atomic_check_clr(atom, connector); + for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) { + ret = nv50_disp_outp_atomic_check_clr(atom, old_connector_state); if (ret) return ret; - ret = nv50_disp_outp_atomic_check_set(atom, connector_state); + ret = nv50_disp_outp_atomic_check_set(atom, new_connector_state); if (ret) return ret; } @@ -4458,11 +4451,13 @@ nv50_display_create(struct drm_device *dev) /* create crtc objects to represent the hw heads */ if (disp->disp->oclass >= GF110_DISP) - crtcs = nvif_rd32(&device->object, 0x022448); + crtcs = nvif_rd32(&device->object, 0x612004) & 0xf; else - crtcs = 2; + crtcs = 0x3; - for (i = 0; i < crtcs; i++) { + for (i = 0; i < fls(crtcs); i++) { + if (!(crtcs & (1 << i))) + continue; ret = nv50_head_create(dev, i); if (ret) goto out; |