diff options
author | Maxime Ripard <mripard@kernel.org> | 2019-10-03 17:38:50 +0300 |
---|---|---|
committer | Maxime Ripard <mripard@kernel.org> | 2019-10-03 17:38:50 +0300 |
commit | 4092de1ba34eb376791809fb366bc15f8a9e0b7c (patch) | |
tree | 6262d4dfcfa7ff9eda8e8d1d0a711711fcae8785 /drivers/gpu/drm/nouveau/dispnv50 | |
parent | a00d17e0a71ae2e4fdaac46e1c12785d3346c3f2 (diff) | |
parent | 54ecb8f7028c5eb3d740bb82b0f1d90f2df63c5c (diff) | |
download | linux-4092de1ba34eb376791809fb366bc15f8a9e0b7c.tar.xz |
Merge drm/drm-next into drm-misc-next
We haven't done any backmerge for a while due to the merge window, and it
starts to become an issue for komeda. Let's bring 5.4-rc1 in.
Signed-off-by: Maxime Ripard <mripard@kernel.org>
Diffstat (limited to 'drivers/gpu/drm/nouveau/dispnv50')
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/atom.h | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/base507c.c | 26 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/base827c.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/base907c.c | 65 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/base917c.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/corec37d.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/disp.c | 68 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/head.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/ovly507e.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/ovly827e.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/ovly907e.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/ovly917e.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/wndw.c | 113 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/wndw.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c | 61 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c | 72 |
16 files changed, 397 insertions, 89 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv50/atom.h b/drivers/gpu/drm/nouveau/dispnv50/atom.h index b5fae5ab3fa8..43df86c38f58 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/atom.h +++ b/drivers/gpu/drm/nouveau/dispnv50/atom.h @@ -185,6 +185,11 @@ struct nv50_wndw_atom { } xlut; struct { + u32 matrix[12]; + bool valid; + } csc; + + struct { u8 mode:2; u8 interval:4; @@ -216,14 +221,23 @@ struct nv50_wndw_atom { u16 y; } point; + struct { + u8 depth; + u8 k1; + u8 src_color:4; + u8 dst_color:4; + } blend; + union nv50_wndw_atom_mask { struct { bool ntfy:1; bool sema:1; bool xlut:1; + bool csc:1; bool image:1; bool scale:1; bool point:1; + bool blend:1; }; u8 mask; } set, clr; diff --git a/drivers/gpu/drm/nouveau/dispnv50/base507c.c b/drivers/gpu/drm/nouveau/dispnv50/base507c.c index d5e295ca2caa..00a85f1e1a4a 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base507c.c +++ b/drivers/gpu/drm/nouveau/dispnv50/base507c.c @@ -25,7 +25,9 @@ #include <nvif/event.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_plane_helper.h> + #include "nouveau_bo.h" void @@ -56,12 +58,21 @@ static void base507c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { u32 *push; - if ((push = evo_wait(&wndw->wndw, 10))) { + if ((push = evo_wait(&wndw->wndw, 13))) { evo_mthd(push, 0x0084, 1); evo_data(push, asyw->image.mode << 8 | asyw->image.interval << 4); evo_mthd(push, 0x00c0, 1); evo_data(push, asyw->image.handle[0]); + if (asyw->image.format == 0xca) { + evo_mthd(push, 0x0110, 2); + evo_data(push, 1); + evo_data(push, 0x6400); + } else { + evo_mthd(push, 0x0110, 2); + evo_data(push, 0); + evo_data(push, 0); + } evo_mthd(push, 0x0800, 5); evo_data(push, asyw->image.offset[0] >> 8); evo_data(push, 0x00000000); @@ -179,9 +190,6 @@ base507c_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, const struct drm_framebuffer *fb = asyw->state.fb; int ret; - if (!fb->format->depth) - return -EINVAL; - ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state, DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, @@ -200,6 +208,14 @@ base507c_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, asyh->base.y = asyw->state.src.y1 >> 16; asyh->base.w = asyw->state.fb->width; asyh->base.h = asyw->state.fb->height; + + /* Some newer formats, esp FP16 ones, don't have a + * "depth". There's nothing that really makes sense there + * either, so just set it to the implicit bit count. + */ + if (!asyh->base.depth) + asyh->base.depth = asyh->base.cpp * 8; + return 0; } @@ -215,6 +231,8 @@ base507c_format[] = { DRM_FORMAT_ABGR2101010, DRM_FORMAT_XBGR8888, DRM_FORMAT_ABGR8888, + DRM_FORMAT_XBGR16161616F, + DRM_FORMAT_ABGR16161616F, 0 }; diff --git a/drivers/gpu/drm/nouveau/dispnv50/base827c.c b/drivers/gpu/drm/nouveau/dispnv50/base827c.c index 73646819a0d6..f4c05949dd62 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base827c.c +++ b/drivers/gpu/drm/nouveau/dispnv50/base827c.c @@ -25,12 +25,21 @@ static void base827c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { u32 *push; - if ((push = evo_wait(&wndw->wndw, 10))) { + if ((push = evo_wait(&wndw->wndw, 13))) { evo_mthd(push, 0x0084, 1); evo_data(push, asyw->image.mode << 8 | asyw->image.interval << 4); evo_mthd(push, 0x00c0, 1); evo_data(push, asyw->image.handle[0]); + if (asyw->image.format == 0xca) { + evo_mthd(push, 0x0110, 2); + evo_data(push, 1); + evo_data(push, 0x6400); + } else { + evo_mthd(push, 0x0110, 2); + evo_data(push, 0); + evo_data(push, 0); + } evo_mthd(push, 0x0800, 5); evo_data(push, asyw->image.offset[0] >> 8); evo_data(push, 0x00000000); diff --git a/drivers/gpu/drm/nouveau/dispnv50/base907c.c b/drivers/gpu/drm/nouveau/dispnv50/base907c.c index 049ce6da321c..5f2de77e0f32 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base907c.c +++ b/drivers/gpu/drm/nouveau/dispnv50/base907c.c @@ -83,6 +83,68 @@ base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) asyw->xlut.i.load = head907d_olut_load; } +static inline u32 +csc_drm_to_base(u64 in) +{ + /* base takes a 19-bit 2's complement value in S3.16 format */ + bool sign = in & BIT_ULL(63); + u32 integer = (in >> 32) & 0x7fffffff; + u32 fraction = in & 0xffffffff; + + if (integer >= 4) { + return (1 << 18) - (sign ? 0 : 1); + } else { + u32 ret = (integer << 16) | (fraction >> 16); + if (sign) + ret = -ret; + return ret & GENMASK(18, 0); + } +} + +void +base907c_csc(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, + const struct drm_color_ctm *ctm) +{ + int i, j; + + for (j = 0; j < 3; j++) { + for (i = 0; i < 4; i++) { + u32 *val = &asyw->csc.matrix[j * 4 + i]; + /* DRM does not support constant offset, while + * HW CSC does. Skip it. */ + if (i == 3) { + *val = 0; + } else { + *val = csc_drm_to_base(ctm->matrix[j * 3 + i]); + } + } + } +} + +static void +base907c_csc_clr(struct nv50_wndw *wndw) +{ + u32 *push; + if ((push = evo_wait(&wndw->wndw, 2))) { + evo_mthd(push, 0x0140, 1); + evo_data(push, 0x00000000); + evo_kick(push, &wndw->wndw); + } +} + +static void +base907c_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +{ + u32 *push, i; + if ((push = evo_wait(&wndw->wndw, 13))) { + evo_mthd(push, 0x0140, 12); + evo_data(push, asyw->csc.matrix[0] | 0x80000000); + for (i = 1; i < 12; i++) + evo_data(push, asyw->csc.matrix[i]); + evo_kick(push, &wndw->wndw); + } +} + const struct nv50_wndw_func base907c = { .acquire = base507c_acquire, @@ -94,6 +156,9 @@ base907c = { .ntfy_clr = base507c_ntfy_clr, .ntfy_wait_begun = base507c_ntfy_wait_begun, .ilut = base907c_ilut, + .csc = base907c_csc, + .csc_set = base907c_csc_set, + .csc_clr = base907c_csc_clr, .olut_core = true, .xlut_set = base907c_xlut_set, .xlut_clr = base907c_xlut_clr, diff --git a/drivers/gpu/drm/nouveau/dispnv50/base917c.c b/drivers/gpu/drm/nouveau/dispnv50/base917c.c index 54d705bb81a5..a1baed4fe0e9 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base917c.c +++ b/drivers/gpu/drm/nouveau/dispnv50/base917c.c @@ -36,6 +36,8 @@ base917c_format[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_XRGB2101010, DRM_FORMAT_ARGB2101010, + DRM_FORMAT_XBGR16161616F, + DRM_FORMAT_ABGR16161616F, 0 }; diff --git a/drivers/gpu/drm/nouveau/dispnv50/corec37d.c b/drivers/gpu/drm/nouveau/dispnv50/corec37d.c index 7860774b65bc..40d9b654ab8c 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/corec37d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/corec37d.c @@ -82,7 +82,7 @@ corec37d_init(struct nv50_core *core) for (i = 0; i < windows; i++) { evo_mthd(push, 0x1000 + (i * 0x080), 3); evo_data(push, i >> 1); - evo_data(push, 0x00000017); + evo_data(push, 0x0000001f); evo_data(push, 0x00000000); evo_mthd(push, 0x1010 + (i * 0x080), 1); evo_data(push, 0x00127fff); diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index d866cadd2ef3..a13924ae1992 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -30,14 +30,14 @@ #include <linux/dma-mapping.h> #include <linux/hdmi.h> -#include <drm/drmP.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_dp_helper.h> +#include <drm/drm_edid.h> #include <drm/drm_fb_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_scdc_helper.h> -#include <drm/drm_edid.h> +#include <drm/drm_vblank.h> #include <nvif/class.h> #include <nvif/cl0002.h> @@ -771,16 +771,20 @@ nv50_msto_atomic_check(struct drm_encoder *encoder, struct nv50_head_atom *asyh = nv50_head_atom(crtc_state); int slots; - /* When restoring duplicated states, we need to make sure that the - * bw remains the same and avoid recalculating it, as the connector's - * bpc may have changed after the state was duplicated - */ - if (!state->duplicated) - asyh->dp.pbn = - drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock, - connector->display_info.bpc * 3); + if (crtc_state->mode_changed || crtc_state->connectors_changed) { + /* + * When restoring duplicated states, we need to make sure that + * the bw remains the same and avoid recalculating it, as the + * connector's bpc may have changed after the state was + * duplicated + */ + if (!state->duplicated) { + const int bpp = connector->display_info.bpc * 3; + const int clock = crtc_state->adjusted_mode.clock; + + asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, bpp); + } - if (drm_atomic_crtc_needs_modeset(crtc_state)) { slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr, mstc->port, asyh->dp.pbn); @@ -1599,7 +1603,8 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe) nv_encoder->aux = aux; } - if ((data = nvbios_dp_table(bios, &ver, &hdr, &cnt, &len)) && + if (nv_connector->type != DCB_CONNECTOR_eDP && + (data = nvbios_dp_table(bios, &ver, &hdr, &cnt, &len)) && ver >= 0x40 && (nvbios_rd08(bios, data + 0x08) & 0x04)) { ret = nv50_mstm_new(nv_encoder, &nv_connector->aux, 16, nv_connector->base.base.id, @@ -1826,8 +1831,11 @@ 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 (old_crtc_state->active && !new_crtc_state->active) + + if (old_crtc_state->active && !new_crtc_state->active) { + pm_runtime_put_noidle(dev->dev); drm_crtc_vblank_off(crtc); + } if (asyh->clr.mask) { nv50_head_flush_clr(head, asyh, atom->flush_disable); @@ -1913,8 +1921,10 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) } if (new_crtc_state->active) { - if (!old_crtc_state->active) + if (!old_crtc_state->active) { drm_crtc_vblank_on(crtc); + pm_runtime_get_noresume(dev->dev); + } if (new_crtc_state->event) drm_crtc_vblank_get(crtc); } @@ -1979,6 +1989,10 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) drm_atomic_helper_cleanup_planes(dev, state); drm_atomic_helper_commit_cleanup_done(state); drm_atomic_state_put(state); + + /* Drop the RPM ref we got from nv50_disp_atomic_commit() */ + pm_runtime_mark_last_busy(dev->dev); + pm_runtime_put_autosuspend(dev->dev); } static void @@ -1993,11 +2007,8 @@ static int nv50_disp_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, bool nonblock) { - struct nouveau_drm *drm = nouveau_drm(dev); struct drm_plane_state *new_plane_state; struct drm_plane *plane; - struct drm_crtc *crtc; - bool active = false; int ret, i; ret = pm_runtime_get_sync(dev->dev); @@ -2034,27 +2045,17 @@ nv50_disp_atomic_commit(struct drm_device *dev, drm_atomic_state_get(state); + /* + * Grab another RPM ref for the commit tail, which will release the + * ref when it's finished + */ + pm_runtime_get_noresume(dev->dev); + if (nonblock) queue_work(system_unbound_wq, &state->commit_work); else nv50_disp_atomic_commit_tail(state); - drm_for_each_crtc(crtc, dev) { - if (crtc->state->active) { - if (!drm->have_disp_power_ref) { - drm->have_disp_power_ref = true; - return 0; - } - active = true; - break; - } - } - - if (!active && drm->have_disp_power_ref) { - pm_runtime_put_autosuspend(dev->dev); - drm->have_disp_power_ref = false; - } - err_cleanup: if (ret) drm_atomic_helper_cleanup_planes(dev, state); @@ -2316,6 +2317,7 @@ nv50_display_create(struct drm_device *dev) disp->disp = &nouveau_display(dev)->disp; dev->mode_config.funcs = &nv50_disp_func; dev->mode_config.quirk_addfb_prefer_xbgr_30bpp = true; + dev->mode_config.normalize_zpos = true; /* small shared memory area we use for notifiers and semaphores */ ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM, diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c index 929d93b1677e..71c23bf1fe25 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head.c @@ -480,7 +480,7 @@ nv50_head_create(struct drm_device *dev, int index) struct nouveau_drm *drm = nouveau_drm(dev); struct nv50_disp *disp = nv50_disp(dev); struct nv50_head *head; - struct nv50_wndw *curs, *wndw; + struct nv50_wndw *base, *ovly, *curs; struct drm_crtc *crtc; int ret; @@ -492,13 +492,13 @@ nv50_head_create(struct drm_device *dev, int index) head->base.index = index; if (disp->disp->object.oclass < GV100_DISP) { - ret = nv50_ovly_new(drm, head->base.index, &wndw); - ret = nv50_base_new(drm, head->base.index, &wndw); + ret = nv50_base_new(drm, head->base.index, &base); + ret = nv50_ovly_new(drm, head->base.index, &ovly); } else { - ret = nv50_wndw_new(drm, DRM_PLANE_TYPE_OVERLAY, - head->base.index * 2 + 1, &wndw); ret = nv50_wndw_new(drm, DRM_PLANE_TYPE_PRIMARY, - head->base.index * 2 + 0, &wndw); + head->base.index * 2 + 0, &base); + ret = nv50_wndw_new(drm, DRM_PLANE_TYPE_OVERLAY, + head->base.index * 2 + 1, &ovly); } if (ret == 0) ret = nv50_curs_new(drm, head->base.index, &curs); @@ -508,10 +508,14 @@ nv50_head_create(struct drm_device *dev, int index) } crtc = &head->base.base; - drm_crtc_init_with_planes(dev, crtc, &wndw->plane, &curs->plane, + drm_crtc_init_with_planes(dev, crtc, &base->plane, &curs->plane, &nv50_head_func, "head-%d", head->base.index); drm_crtc_helper_add(crtc, &nv50_head_help); drm_mode_crtc_set_gamma_size(crtc, 256); + if (disp->disp->object.oclass >= GF110_DISP) + drm_crtc_enable_color_mgmt(crtc, 256, true, 256); + else + drm_crtc_enable_color_mgmt(crtc, 0, false, 256); if (head->func->olut_set) { ret = nv50_lut_init(disp, &drm->client.mmu, &head->olut); diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c index cc417664f823..8ccd96113bad 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c @@ -23,6 +23,7 @@ #include "atom.h" #include <drm/drm_atomic_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_plane_helper.h> #include <nvif/cl507e.h> @@ -160,9 +161,7 @@ ovly507e_format[] = { DRM_FORMAT_YUYV, DRM_FORMAT_UYVY, DRM_FORMAT_XRGB8888, - DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB1555, - DRM_FORMAT_ARGB1555, 0 }; diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c index aaa9fe5a4fc8..2e68fc736fe1 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c @@ -90,11 +90,8 @@ ovly827e_format[] = { DRM_FORMAT_YUYV, DRM_FORMAT_UYVY, DRM_FORMAT_XRGB8888, - DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB1555, - DRM_FORMAT_ARGB1555, DRM_FORMAT_XBGR2101010, - DRM_FORMAT_ABGR2101010, 0 }; diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c index a3ce53046015..9efe5e9d5ce4 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c @@ -61,10 +61,21 @@ ovly907e = { .update = ovly507e_update, }; +static const u32 +ovly907e_format[] = { + DRM_FORMAT_YUYV, + DRM_FORMAT_UYVY, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_XBGR16161616F, + 0 +}; + int ovly907e_new(struct nouveau_drm *drm, int head, s32 oclass, struct nv50_wndw **pwndw) { - return ovly507e_new_(&ovly907e, ovly827e_format, drm, head, oclass, + return ovly507e_new_(&ovly907e, ovly907e_format, drm, head, oclass, 0x00000004 << (head * 4), pwndw); } diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c index 505fa7e78523..e24d6fd23450 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly917e.c @@ -26,13 +26,10 @@ ovly917e_format[] = { DRM_FORMAT_YUYV, DRM_FORMAT_UYVY, DRM_FORMAT_XRGB8888, - DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB1555, - DRM_FORMAT_ARGB1555, DRM_FORMAT_XBGR2101010, - DRM_FORMAT_ABGR2101010, DRM_FORMAT_XRGB2101010, - DRM_FORMAT_ARGB2101010, + DRM_FORMAT_XBGR16161616F, 0 }; diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c index 027a01b97d1c..5193b6257061 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c @@ -26,6 +26,8 @@ #include <nvif/cl0002.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_fourcc.h> + #include "nouveau_bo.h" static void @@ -118,6 +120,7 @@ nv50_wndw_flush_clr(struct nv50_wndw *wndw, u32 *interlock, bool flush, if (clr.sema ) wndw->func-> sema_clr(wndw); if (clr.ntfy ) wndw->func-> ntfy_clr(wndw); if (clr.xlut ) wndw->func-> xlut_clr(wndw); + if (clr.csc ) wndw->func-> csc_clr(wndw); if (clr.image) wndw->func->image_clr(wndw); interlock[wndw->interlock.type] |= wndw->interlock.data; @@ -145,7 +148,9 @@ nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 *interlock, wndw->func->xlut_set(wndw, asyw); } + if (asyw->set.csc ) wndw->func->csc_set (wndw, asyw); if (asyw->set.scale) wndw->func->scale_set(wndw, asyw); + if (asyw->set.blend) wndw->func->blend_set(wndw, asyw); if (asyw->set.point) { if (asyw->set.point = false, asyw->set.mask) interlock[wndw->interlock.type] |= wndw->interlock.data; @@ -202,18 +207,20 @@ static int nv50_wndw_atomic_check_acquire_rgb(struct nv50_wndw_atom *asyw) { switch (asyw->state.fb->format->format) { - case DRM_FORMAT_C8 : asyw->image.format = 0x1e; break; - case DRM_FORMAT_XRGB8888 : - case DRM_FORMAT_ARGB8888 : asyw->image.format = 0xcf; break; - case DRM_FORMAT_RGB565 : asyw->image.format = 0xe8; break; - case DRM_FORMAT_XRGB1555 : - case DRM_FORMAT_ARGB1555 : asyw->image.format = 0xe9; break; - case DRM_FORMAT_XBGR2101010: - case DRM_FORMAT_ABGR2101010: asyw->image.format = 0xd1; break; - case DRM_FORMAT_XBGR8888 : - case DRM_FORMAT_ABGR8888 : asyw->image.format = 0xd5; break; - case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_ARGB2101010: asyw->image.format = 0xdf; break; + case DRM_FORMAT_C8 : asyw->image.format = 0x1e; break; + case DRM_FORMAT_XRGB8888 : + case DRM_FORMAT_ARGB8888 : asyw->image.format = 0xcf; break; + case DRM_FORMAT_RGB565 : asyw->image.format = 0xe8; break; + case DRM_FORMAT_XRGB1555 : + case DRM_FORMAT_ARGB1555 : asyw->image.format = 0xe9; break; + case DRM_FORMAT_XBGR2101010 : + case DRM_FORMAT_ABGR2101010 : asyw->image.format = 0xd1; break; + case DRM_FORMAT_XBGR8888 : + case DRM_FORMAT_ABGR8888 : asyw->image.format = 0xd5; break; + case DRM_FORMAT_XRGB2101010 : + case DRM_FORMAT_ARGB2101010 : asyw->image.format = 0xdf; break; + case DRM_FORMAT_XBGR16161616F: + case DRM_FORMAT_ABGR16161616F: asyw->image.format = 0xca; break; default: return -EINVAL; } @@ -260,7 +267,7 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, bool modeset, asyw->image.pitch[0] = fb->base.pitches[0]; } - if (!(asyh->state.pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC)) + if (!asyh->state.async_flip) asyw->image.interval = 1; else asyw->image.interval = 0; @@ -279,6 +286,28 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, bool modeset, asyw->set.scale = true; } + if (wndw->func->blend_set) { + asyw->blend.depth = 255 - asyw->state.normalized_zpos; + asyw->blend.k1 = asyw->state.alpha >> 8; + switch (asyw->state.pixel_blend_mode) { + case DRM_MODE_BLEND_PREMULTI: + asyw->blend.src_color = 2; /* K1 */ + asyw->blend.dst_color = 7; /* NEG_K1_TIMES_SRC */ + break; + case DRM_MODE_BLEND_COVERAGE: + asyw->blend.src_color = 5; /* K1_TIMES_SRC */ + asyw->blend.dst_color = 7; /* NEG_K1_TIMES_SRC */ + break; + case DRM_MODE_BLEND_PIXEL_NONE: + default: + asyw->blend.src_color = 2; /* K1 */ + asyw->blend.dst_color = 4; /* NEG_K1 */ + break; + } + if (memcmp(&armw->blend, &asyw->blend, sizeof(asyw->blend))) + asyw->set.blend = true; + } + if (wndw->immd) { asyw->point.x = asyw->state.crtc_x; asyw->point.y = asyw->state.crtc_y; @@ -320,7 +349,9 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw, asyh->wndw.olut &= ~BIT(wndw->id); } - if (!ilut && wndw->func->ilut_identity) { + if (!ilut && wndw->func->ilut_identity && + asyw->state.fb->format->format != DRM_FORMAT_XBGR16161616F && + asyw->state.fb->format->format != DRM_FORMAT_ABGR16161616F) { static struct drm_property_blob dummy = {}; ilut = &dummy; } @@ -332,6 +363,8 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw, asyw->xlut.handle = wndw->wndw.vram.handle; asyw->xlut.i.buffer = !asyw->xlut.i.buffer; asyw->set.xlut = true; + } else { + asyw->clr.xlut = armw->xlut.handle != 0; } /* Handle setting base SET_OUTPUT_LUT_LO_ENABLE_USE_CORE_LUT. */ @@ -339,8 +372,18 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw, (!armw->visible || (armw->xlut.handle && !asyw->xlut.handle))) asyw->set.xlut = true; + if (wndw->func->csc && asyh->state.ctm) { + const struct drm_color_ctm *ctm = asyh->state.ctm->data; + wndw->func->csc(wndw, asyw, ctm); + asyw->csc.valid = true; + asyw->set.csc = true; + } else { + asyw->csc.valid = false; + asyw->clr.csc = armw->csc.valid; + } + /* Can't do an immediate flip while changing the LUT. */ - asyh->state.pageflip_flags &= ~DRM_MODE_PAGE_FLIP_ASYNC; + asyh->state.async_flip = false; } static int @@ -408,6 +451,7 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) asyw->clr.ntfy = armw->ntfy.handle != 0; asyw->clr.sema = armw->sema.handle != 0; asyw->clr.xlut = armw->xlut.handle != 0; + asyw->clr.csc = armw->csc.valid; if (wndw->func->image_clr) asyw->clr.image = armw->image.handle[0] != 0; } @@ -499,6 +543,7 @@ nv50_wndw_atomic_duplicate_state(struct drm_plane *plane) asyw->ntfy = armw->ntfy; asyw->ilut = NULL; asyw->xlut = armw->xlut; + asyw->csc = armw->csc; asyw->image = armw->image; asyw->point = armw->point; asyw->clr.mask = 0; @@ -506,6 +551,13 @@ nv50_wndw_atomic_duplicate_state(struct drm_plane *plane) return &asyw->state; } +static int +nv50_wndw_zpos_default(struct drm_plane *plane) +{ + return (plane->type == DRM_PLANE_TYPE_PRIMARY) ? 0 : + (plane->type == DRM_PLANE_TYPE_OVERLAY) ? 1 : 255; +} + static void nv50_wndw_reset(struct drm_plane *plane) { @@ -516,9 +568,10 @@ nv50_wndw_reset(struct drm_plane *plane) if (plane->state) plane->funcs->atomic_destroy_state(plane, plane->state); - plane->state = &asyw->state; - plane->state->plane = plane; - plane->state->rotation = DRM_MODE_ROTATE_0; + + __drm_atomic_helper_plane_reset(plane, &asyw->state); + plane->state->zpos = nv50_wndw_zpos_default(plane); + plane->state->normalized_zpos = nv50_wndw_zpos_default(plane); } static void @@ -613,6 +666,30 @@ nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev, } wndw->notify.func = nv50_wndw_notify; + + if (wndw->func->blend_set) { + ret = drm_plane_create_zpos_property(&wndw->plane, + nv50_wndw_zpos_default(&wndw->plane), 0, 254); + if (ret) + return ret; + + ret = drm_plane_create_alpha_property(&wndw->plane); + if (ret) + return ret; + + ret = drm_plane_create_blend_mode_property(&wndw->plane, + BIT(DRM_MODE_BLEND_PIXEL_NONE) | + BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE)); + if (ret) + return ret; + } else { + ret = drm_plane_create_zpos_immutable_property(&wndw->plane, + nv50_wndw_zpos_default(&wndw->plane)); + if (ret) + return ret; + } + return 0; } diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.h b/drivers/gpu/drm/nouveau/dispnv50/wndw.h index 03f3d8dc235a..c63bd3bdaf06 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.h +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.h @@ -65,6 +65,10 @@ struct nv50_wndw_func { int (*ntfy_wait_begun)(struct nouveau_bo *, u32 offset, struct nvif_device *); void (*ilut)(struct nv50_wndw *, struct nv50_wndw_atom *); + void (*csc)(struct nv50_wndw *, struct nv50_wndw_atom *, + const struct drm_color_ctm *); + void (*csc_set)(struct nv50_wndw *, struct nv50_wndw_atom *); + void (*csc_clr)(struct nv50_wndw *); bool ilut_identity; bool olut_core; void (*xlut_set)(struct nv50_wndw *, struct nv50_wndw_atom *); @@ -72,6 +76,7 @@ struct nv50_wndw_func { void (*image_set)(struct nv50_wndw *, struct nv50_wndw_atom *); void (*image_clr)(struct nv50_wndw *); void (*scale_set)(struct nv50_wndw *, struct nv50_wndw_atom *); + void (*blend_set)(struct nv50_wndw *, struct nv50_wndw_atom *); void (*update)(struct nv50_wndw *, u32 *interlock); }; @@ -81,6 +86,9 @@ extern const struct drm_plane_funcs nv50_wndw; void base507c_ntfy_reset(struct nouveau_bo *, u32); int base507c_ntfy_wait_begun(struct nouveau_bo *, u32, struct nvif_device *); +void base907c_csc(struct nv50_wndw *, struct nv50_wndw_atom *, + const struct drm_color_ctm *); + struct nv50_wimm_func { void (*point)(struct nv50_wndw *, struct nv50_wndw_atom *); @@ -102,8 +110,8 @@ void wndwc37e_sema_set(struct nv50_wndw *, struct nv50_wndw_atom *); void wndwc37e_sema_clr(struct nv50_wndw *); void wndwc37e_ntfy_set(struct nv50_wndw *, struct nv50_wndw_atom *); void wndwc37e_ntfy_clr(struct nv50_wndw *); -void wndwc37e_image_set(struct nv50_wndw *, struct nv50_wndw_atom *); void wndwc37e_image_clr(struct nv50_wndw *); +void wndwc37e_blend_set(struct nv50_wndw *, struct nv50_wndw_atom *); void wndwc37e_update(struct nv50_wndw *, u32 *); int wndwc57e_new(struct nouveau_drm *, enum drm_plane_type, int, s32, diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c index e52a85c83f7a..0f9402162bde 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c @@ -29,6 +29,23 @@ #include <nvif/clc37e.h> static void +wndwc37e_csc_clr(struct nv50_wndw *wndw) +{ +} + +static void +wndwc37e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +{ + u32 *push, i; + if ((push = evo_wait(&wndw->wndw, 13))) { + evo_mthd(push, 0x02bc, 12); + for (i = 0; i < 12; i++) + evo_data(push, asyw->csc.matrix[i]); + evo_kick(push, &wndw->wndw); + } +} + +static void wndwc37e_ilut_clr(struct nv50_wndw *wndw) { u32 *push; @@ -65,6 +82,26 @@ wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) } void +wndwc37e_blend_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +{ + u32 *push; + if ((push = evo_wait(&wndw->wndw, 8))) { + evo_mthd(push, 0x02ec, 7); + evo_data(push, asyw->blend.depth << 4); + evo_data(push, asyw->blend.k1); + evo_data(push, asyw->blend.dst_color << 12 | + asyw->blend.dst_color << 8 | + asyw->blend.src_color << 4 | + asyw->blend.src_color); + evo_data(push, 0xffff0000); + evo_data(push, 0xffff0000); + evo_data(push, 0xffff0000); + evo_data(push, 0xffff0000); + evo_kick(push, &wndw->wndw); + } +} + +void wndwc37e_image_clr(struct nv50_wndw *wndw) { u32 *push; @@ -77,12 +114,12 @@ wndwc37e_image_clr(struct nv50_wndw *wndw) } } -void +static void wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { u32 *push; - if (!(push = evo_wait(&wndw->wndw, 25))) + if (!(push = evo_wait(&wndw->wndw, 17))) return; evo_mthd(push, 0x0308, 1); @@ -90,7 +127,9 @@ wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) evo_mthd(push, 0x0224, 4); evo_data(push, asyw->image.h << 16 | asyw->image.w); evo_data(push, asyw->image.layout << 4 | asyw->image.blockh); - evo_data(push, asyw->image.colorspace << 8 | asyw->image.format); + evo_data(push, asyw->csc.valid << 17 | + asyw->image.colorspace << 8 | + asyw->image.format); evo_data(push, asyw->image.blocks[0] | (asyw->image.pitch[0] >> 6)); evo_mthd(push, 0x0240, 1); evo_data(push, asyw->image.handle[0]); @@ -105,16 +144,6 @@ wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) evo_mthd(push, 0x02a4, 1); evo_data(push, asyw->state.crtc_h << 16 | asyw->state.crtc_w); - - /*XXX: Composition-related stuff. Need to implement properly. */ - evo_mthd(push, 0x02ec, 1); - evo_data(push, (2 - (wndw->id & 1)) << 4); - evo_mthd(push, 0x02f4, 5); - evo_data(push, 0x00000011); - evo_data(push, 0xffff0000); - evo_data(push, 0xffff0000); - evo_data(push, 0xffff0000); - evo_data(push, 0xffff0000); evo_kick(push, &wndw->wndw); } @@ -216,6 +245,8 @@ wndwc37e_format[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_XRGB2101010, DRM_FORMAT_ARGB2101010, + DRM_FORMAT_XBGR16161616F, + DRM_FORMAT_ABGR16161616F, 0 }; @@ -232,8 +263,12 @@ wndwc37e = { .ilut = wndwc37e_ilut, .xlut_set = wndwc37e_ilut_set, .xlut_clr = wndwc37e_ilut_clr, + .csc = base907c_csc, + .csc_set = wndwc37e_csc_set, + .csc_clr = wndwc37e_csc_clr, .image_set = wndwc37e_image_set, .image_clr = wndwc37e_image_clr, + .blend_set = wndwc37e_blend_set, .update = wndwc37e_update, }; diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c index ba89f1a5fcfa..a311c79e5295 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c @@ -29,6 +29,72 @@ #include <nvif/clc37e.h> static void +wndwc57e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +{ + u32 *push; + + if (!(push = evo_wait(&wndw->wndw, 17))) + return; + + evo_mthd(push, 0x0308, 1); + evo_data(push, asyw->image.mode << 4 | asyw->image.interval); + evo_mthd(push, 0x0224, 4); + evo_data(push, asyw->image.h << 16 | asyw->image.w); + evo_data(push, asyw->image.layout << 4 | asyw->image.blockh); + evo_data(push, asyw->image.colorspace << 8 | + asyw->image.format); + evo_data(push, asyw->image.blocks[0] | (asyw->image.pitch[0] >> 6)); + evo_mthd(push, 0x0240, 1); + evo_data(push, asyw->image.handle[0]); + evo_mthd(push, 0x0260, 1); + evo_data(push, asyw->image.offset[0] >> 8); + evo_mthd(push, 0x0290, 1); + evo_data(push, (asyw->state.src_y >> 16) << 16 | + (asyw->state.src_x >> 16)); + evo_mthd(push, 0x0298, 1); + evo_data(push, (asyw->state.src_h >> 16) << 16 | + (asyw->state.src_w >> 16)); + evo_mthd(push, 0x02a4, 1); + evo_data(push, asyw->state.crtc_h << 16 | + asyw->state.crtc_w); + evo_kick(push, &wndw->wndw); +} + +static void +wndwc57e_csc_clr(struct nv50_wndw *wndw) +{ + u32 *push; + if ((push = evo_wait(&wndw->wndw, 13))) { + evo_mthd(push, 0x0400, 12); + evo_data(push, 0x00010000); + evo_data(push, 0x00000000); + evo_data(push, 0x00000000); + evo_data(push, 0x00000000); + evo_data(push, 0x00000000); + evo_data(push, 0x00010000); + evo_data(push, 0x00000000); + evo_data(push, 0x00000000); + evo_data(push, 0x00000000); + evo_data(push, 0x00000000); + evo_data(push, 0x00010000); + evo_data(push, 0x00000000); + evo_kick(push, &wndw->wndw); + } +} + +static void +wndwc57e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +{ + u32 *push, i; + if ((push = evo_wait(&wndw->wndw, 13))) { + evo_mthd(push, 0x0400, 12); + for (i = 0; i < 12; i++) + evo_data(push, asyw->csc.matrix[i]); + evo_kick(push, &wndw->wndw); + } +} + +static void wndwc57e_ilut_clr(struct nv50_wndw *wndw) { u32 *push; @@ -119,8 +185,12 @@ wndwc57e = { .ilut_identity = true, .xlut_set = wndwc57e_ilut_set, .xlut_clr = wndwc57e_ilut_clr, - .image_set = wndwc37e_image_set, + .csc = base907c_csc, + .csc_set = wndwc57e_csc_set, + .csc_clr = wndwc57e_csc_clr, + .image_set = wndwc57e_image_set, .image_clr = wndwc37e_image_clr, + .blend_set = wndwc37e_blend_set, .update = wndwc37e_update, }; |