nouveau-y += dispnv50/ovly507e.o
nouveau-y += dispnv50/ovly827e.o
nouveau-y += dispnv50/ovly907e.o
+nouveau-y += dispnv50/ovly917e.o
u8 mode:2;
u8 interval:4;
+ u8 colorspace:2;
u8 format;
u8 kind:7;
u8 layout:1;
u64 offset[6];
} image;
+ struct {
+ u16 sx;
+ u16 sy;
+ u16 sw;
+ u16 sh;
+ u16 dw;
+ u16 dh;
+ } scale;
+
struct {
u16 x;
u16 y;
bool sema:1;
bool xlut:1;
bool image:1;
+ bool scale:1;
bool point:1;
};
u8 mask;
struct nv50_head_atom *);
void base507c_sema_set(struct nv50_wndw *, struct nv50_wndw_atom *);
void base507c_sema_clr(struct nv50_wndw *);
-void base507c_ntfy_reset(struct nouveau_bo *, u32);
void base507c_ntfy_set(struct nv50_wndw *, struct nv50_wndw_atom *);
void base507c_ntfy_clr(struct nv50_wndw *);
-int base507c_ntfy_wait_begun(struct nouveau_bo *, u32, struct nvif_device *);
void base507c_xlut_set(struct nv50_wndw *, struct nv50_wndw_atom *);
void base507c_xlut_clr(struct nv50_wndw *);
void base507c_image_clr(struct nv50_wndw *);
int curs507a_new_(const struct nv50_wimm_func *, struct nouveau_drm *,
int head, s32 oclass, u32 interlock_data,
struct nv50_wndw **);
-extern const struct nv50_wimm_func curs507a;
int curs907a_new(struct nouveau_drm *, int, s32, struct nv50_wndw **);
#define NV50_DISP_BASE_SEM0(c) NV50_DISP_WNDW_SEM0(0 + (c))
#define NV50_DISP_BASE_SEM1(c) NV50_DISP_WNDW_SEM1(0 + (c))
#define NV50_DISP_BASE_NTFY(c) NV50_DISP_WNDW_NTFY(0 + (c))
+#define NV50_DISP_OVLY_SEM0(c) NV50_DISP_WNDW_SEM0(4 + (c))
+#define NV50_DISP_OVLY_SEM1(c) NV50_DISP_WNDW_SEM1(4 + (c))
+#define NV50_DISP_OVLY_NTFY(c) NV50_DISP_WNDW_NTFY(4 + (c))
struct nouveau_bo *sync;
struct mutex mutex;
if (asyh->ovly.cpp) {
switch (asyh->ovly.cpp) {
- case 8: bounds |= 0x00000500; break;
case 4: bounds |= 0x00000300; break;
case 2: bounds |= 0x00000100; break;
default:
break;
}
bounds |= 0x00000001;
+ } else {
+ bounds |= 0x00000100;
}
if ((push = evo_wait(core, 2))) {
break;
}
bounds |= 0x00000001;
+ } else {
+ bounds |= 0x00000100;
}
if ((push = evo_wait(core, 2))) {
#include <nvif/cl507b.h>
-static const struct nv50_wimm_func
-oimm507b = {
-};
-
static int
oimm507b_init_(const struct nv50_wimm_func *func, struct nouveau_drm *drm,
s32 oclass, struct nv50_wndw *wndw)
int
oimm507b_init(struct nouveau_drm *drm, s32 oclass, struct nv50_wndw *wndw)
{
- return oimm507b_init_(&oimm507b, drm, oclass, wndw);
+ return oimm507b_init_(&curs507a, drm, oclass, wndw);
}
int version;
int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **);
} ovlys[] = {
- { GK104_DISP_OVERLAY_CONTROL_DMA, 0, ovly907e_new },
+ { GK104_DISP_OVERLAY_CONTROL_DMA, 0, ovly917e_new },
{ GF110_DISP_OVERLAY_CONTROL_DMA, 0, ovly907e_new },
{ GT214_DISP_OVERLAY_CHANNEL_DMA, 0, ovly827e_new },
{ GT200_DISP_OVERLAY_CHANNEL_DMA, 0, ovly827e_new },
int ovly507e_new_(const struct nv50_wndw_func *, const u32 *format,
struct nouveau_drm *, int head, s32 oclass,
u32 interlock_data, struct nv50_wndw **);
+int ovly507e_acquire(struct nv50_wndw *, struct nv50_wndw_atom *,
+ struct nv50_head_atom *);
+void ovly507e_release(struct nv50_wndw *, struct nv50_wndw_atom *,
+ struct nv50_head_atom *);
+void ovly507e_ntfy_set(struct nv50_wndw *, struct nv50_wndw_atom *);
+void ovly507e_ntfy_clr(struct nv50_wndw *);
+void ovly507e_image_clr(struct nv50_wndw *);
+void ovly507e_scale_set(struct nv50_wndw *, struct nv50_wndw_atom *);
+void ovly507e_update(struct nv50_wndw *, u32 *);
extern const u32 ovly827e_format[];
+void ovly827e_ntfy_reset(struct nouveau_bo *, u32);
+int ovly827e_ntfy_wait_begun(struct nouveau_bo *, u32, struct nvif_device *);
+
+extern const struct nv50_wndw_func ovly907e;
int ovly827e_new(struct nouveau_drm *, int, s32, struct nv50_wndw **);
int ovly907e_new(struct nouveau_drm *, int, s32, struct nv50_wndw **);
+int ovly917e_new(struct nouveau_drm *, int, s32, struct nv50_wndw **);
int nv50_ovly_new(struct nouveau_drm *, int head, struct nv50_wndw **);
#endif
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "ovly.h"
+#include "atom.h"
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
#include <nvif/cl507e.h>
+#include <nvif/event.h>
+
+void
+ovly507e_update(struct nv50_wndw *wndw, u32 *interlock)
+{
+ u32 *push;
+ if ((push = evo_wait(&wndw->wndw, 2))) {
+ evo_mthd(push, 0x0080, 1);
+ evo_data(push, interlock[NV50_DISP_INTERLOCK_CORE]);
+ evo_kick(push, &wndw->wndw);
+ }
+}
+
+void
+ovly507e_scale_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+ u32 *push;
+ if ((push = evo_wait(&wndw->wndw, 4))) {
+ evo_mthd(push, 0x00e0, 3);
+ evo_data(push, asyw->scale.sy << 16 | asyw->scale.sx);
+ evo_data(push, asyw->scale.sh << 16 | asyw->scale.sw);
+ evo_data(push, asyw->scale.dw);
+ evo_kick(push, &wndw->wndw);
+ }
+}
+
+void
+ovly507e_image_clr(struct nv50_wndw *wndw)
+{
+ u32 *push;
+ if ((push = evo_wait(&wndw->wndw, 4))) {
+ evo_mthd(push, 0x0084, 1);
+ evo_data(push, 0x00000000);
+ evo_mthd(push, 0x00c0, 1);
+ evo_data(push, 0x00000000);
+ evo_kick(push, &wndw->wndw);
+ }
+}
+
+static void
+ovly507e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+ u32 *push;
+ if ((push = evo_wait(&wndw->wndw, 12))) {
+ evo_mthd(push, 0x0084, 1);
+ evo_data(push, asyw->image.interval << 4);
+ evo_mthd(push, 0x00c0, 1);
+ evo_data(push, asyw->image.handle[0]);
+ evo_mthd(push, 0x0100, 1);
+ evo_data(push, 0x00000002);
+ evo_mthd(push, 0x0800, 1);
+ evo_data(push, asyw->image.offset[0] >> 8);
+ evo_mthd(push, 0x0808, 3);
+ evo_data(push, asyw->image.h << 16 | asyw->image.w);
+ evo_data(push, asyw->image.layout << 20 |
+ (asyw->image.pitch[0] >> 8) << 8 |
+ asyw->image.blocks[0] << 8 |
+ asyw->image.blockh);
+ evo_data(push, asyw->image.kind << 16 |
+ asyw->image.format << 8 |
+ asyw->image.colorspace);
+ evo_kick(push, &wndw->wndw);
+ }
+}
+
+void
+ovly507e_ntfy_clr(struct nv50_wndw *wndw)
+{
+ u32 *push;
+ if ((push = evo_wait(&wndw->wndw, 2))) {
+ evo_mthd(push, 0x00a4, 1);
+ evo_data(push, 0x00000000);
+ evo_kick(push, &wndw->wndw);
+ }
+}
+
+void
+ovly507e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+ u32 *push;
+ if ((push = evo_wait(&wndw->wndw, 3))) {
+ evo_mthd(push, 0x00a0, 2);
+ evo_data(push, asyw->ntfy.awaken << 30 | asyw->ntfy.offset);
+ evo_data(push, asyw->ntfy.handle);
+ evo_kick(push, &wndw->wndw);
+ }
+}
+
+void
+ovly507e_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
+ struct nv50_head_atom *asyh)
+{
+ asyh->ovly.cpp = 0;
+}
+
+int
+ovly507e_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
+ struct nv50_head_atom *asyh)
+{
+ const struct drm_framebuffer *fb = asyw->state.fb;
+ int ret;
+
+ ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
+ DRM_PLANE_HELPER_NO_SCALING,
+ DRM_PLANE_HELPER_NO_SCALING,
+ true, true);
+ if (ret)
+ return ret;
+
+ asyh->ovly.cpp = fb->format->cpp[0];
+ return 0;
+}
#include "nouveau_bo.h"
static const struct nv50_wndw_func
ovly507e = {
+ .acquire = ovly507e_acquire,
+ .release = ovly507e_release,
+ .ntfy_set = ovly507e_ntfy_set,
+ .ntfy_clr = ovly507e_ntfy_clr,
+ .ntfy_reset = base507c_ntfy_reset,
+ .ntfy_wait_begun = base507c_ntfy_wait_begun,
+ .image_set = ovly507e_image_set,
+ .image_clr = ovly507e_image_clr,
+ .scale_set = ovly507e_scale_set,
+ .update = ovly507e_update,
};
static const u32
ovly507e_format[] = {
+ DRM_FORMAT_YUYV,
+ DRM_FORMAT_UYVY,
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_XRGB1555,
+ DRM_FORMAT_ARGB1555,
0
};
return ret;
}
+ ret = nvif_notify_init(&wndw->wndw.base.user, wndw->notify.func, false,
+ NV50_DISP_OVERLAY_CHANNEL_DMA_V0_NTFY_UEVENT,
+ &(struct nvif_notify_uevent_req) {},
+ sizeof(struct nvif_notify_uevent_req),
+ sizeof(struct nvif_notify_uevent_rep),
+ &wndw->notify);
+ if (ret)
+ return ret;
+
+ wndw->ntfy = NV50_DISP_OVLY_NTFY(wndw->id);
+ wndw->sema = NV50_DISP_OVLY_SEM0(wndw->id);
+ wndw->data = 0x00000000;
return 0;
}
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "ovly.h"
+#include "atom.h"
#include <nouveau_bo.h>
-#include <nvif/cl507e.h>
+static void
+ovly827e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+ u32 *push;
+ if ((push = evo_wait(&wndw->wndw, 12))) {
+ evo_mthd(push, 0x0084, 1);
+ evo_data(push, asyw->image.interval << 4);
+ evo_mthd(push, 0x00c0, 1);
+ evo_data(push, asyw->image.handle[0]);
+ evo_mthd(push, 0x0100, 1);
+ evo_data(push, 0x00000002);
+ evo_mthd(push, 0x0800, 1);
+ evo_data(push, asyw->image.offset[0] >> 8);
+ evo_mthd(push, 0x0808, 3);
+ evo_data(push, asyw->image.h << 16 | asyw->image.w);
+ evo_data(push, asyw->image.layout << 20 |
+ (asyw->image.pitch[0] >> 8) << 8 |
+ asyw->image.blocks[0] << 8 |
+ asyw->image.blockh);
+ evo_data(push, asyw->image.format << 8 |
+ asyw->image.colorspace);
+ evo_kick(push, &wndw->wndw);
+ }
+}
+
+int
+ovly827e_ntfy_wait_begun(struct nouveau_bo *bo, u32 offset,
+ struct nvif_device *device)
+{
+ s64 time = nvif_msec(device, 2000ULL,
+ u32 data = nouveau_bo_rd32(bo, offset / 4 + 3);
+ if ((data & 0xffff0000) == 0xffff0000)
+ break;
+ usleep_range(1, 2);
+ );
+ return time < 0 ? time : 0;
+}
+
+void
+ovly827e_ntfy_reset(struct nouveau_bo *bo, u32 offset)
+{
+ nouveau_bo_wr32(bo, offset / 4 + 0, 0x00000000);
+ nouveau_bo_wr32(bo, offset / 4 + 1, 0x00000000);
+ nouveau_bo_wr32(bo, offset / 4 + 2, 0x00000000);
+ nouveau_bo_wr32(bo, offset / 4 + 3, 0x80000000);
+}
static const struct nv50_wndw_func
ovly827e = {
+ .acquire = ovly507e_acquire,
+ .release = ovly507e_release,
+ .ntfy_set = ovly507e_ntfy_set,
+ .ntfy_clr = ovly507e_ntfy_clr,
+ .ntfy_reset = ovly827e_ntfy_reset,
+ .ntfy_wait_begun = ovly827e_ntfy_wait_begun,
+ .image_set = ovly827e_image_set,
+ .image_clr = ovly507e_image_clr,
+ .scale_set = ovly507e_scale_set,
+ .update = ovly507e_update,
};
const u32
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
};
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "ovly.h"
+#include "atom.h"
-static const struct nv50_wndw_func
+static void
+ovly907e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+ u32 *push;
+ if ((push = evo_wait(&wndw->wndw, 12))) {
+ evo_mthd(push, 0x0084, 1);
+ evo_data(push, asyw->image.interval << 4);
+ evo_mthd(push, 0x00c0, 1);
+ evo_data(push, asyw->image.handle[0]);
+ evo_mthd(push, 0x0100, 1);
+ evo_data(push, 0x00000002);
+ evo_mthd(push, 0x0400, 1);
+ evo_data(push, asyw->image.offset[0] >> 8);
+ evo_mthd(push, 0x0408, 3);
+ evo_data(push, asyw->image.h << 16 | asyw->image.w);
+ evo_data(push, asyw->image.layout << 24 |
+ (asyw->image.pitch[0] >> 8) << 8 |
+ asyw->image.blocks[0] << 8 |
+ asyw->image.blockh);
+ evo_data(push, asyw->image.format << 8 |
+ asyw->image.colorspace);
+ evo_kick(push, &wndw->wndw);
+ }
+}
+
+const struct nv50_wndw_func
ovly907e = {
+ .acquire = ovly507e_acquire,
+ .release = ovly507e_release,
+ .ntfy_set = ovly507e_ntfy_set,
+ .ntfy_clr = ovly507e_ntfy_clr,
+ .ntfy_reset = ovly827e_ntfy_reset,
+ .ntfy_wait_begun = ovly827e_ntfy_wait_begun,
+ .image_set = ovly907e_image_set,
+ .image_clr = ovly507e_image_clr,
+ .scale_set = ovly507e_scale_set,
+ .update = ovly507e_update,
};
int
--- /dev/null
+/*
+ * Copyright 2018 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 "ovly.h"
+
+static const u32
+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,
+ 0
+};
+
+int
+ovly917e_new(struct nouveau_drm *drm, int head, s32 oclass,
+ struct nv50_wndw **pwndw)
+{
+ return ovly507e_new_(&ovly907e, ovly917e_format, drm, head, oclass,
+ 0x00000004 << (head * 4), pwndw);
+}
wndw->func->xlut_set(wndw, asyw);
}
+ if (asyw->set.scale) wndw->func->scale_set(wndw, asyw);
if (asyw->set.point) {
wndw->immd->point(wndw, asyw);
wndw->immd->update(wndw, interlock);
asyw->sema.handle = 0;
}
+static int
+nv50_wndw_atomic_check_acquire_yuv(struct nv50_wndw_atom *asyw)
+{
+ switch (asyw->state.fb->format->format) {
+ case DRM_FORMAT_YUYV: asyw->image.format = 0x28; break;
+ case DRM_FORMAT_UYVY: asyw->image.format = 0x29; break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ asyw->image.colorspace = 1;
+ return 0;
+}
+
static int
nv50_wndw_atomic_check_acquire_rgb(struct nv50_wndw_atom *asyw)
{
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_ARGB2101010: asyw->image.format = 0xdf; break;
default:
- WARN_ON(1);
return -EINVAL;
}
+ asyw->image.colorspace = 0;
return 0;
}
asyw->image.kind = fb->nvbo->kind;
ret = nv50_wndw_atomic_check_acquire_rgb(asyw);
- if (ret)
- return ret;
+ if (ret) {
+ ret = nv50_wndw_atomic_check_acquire_yuv(asyw);
+ if (ret)
+ return ret;
+ }
if (asyw->image.kind) {
asyw->image.layout = 0;
asyw->set.image = wndw->func->image_set != NULL;
}
+ if (wndw->func->scale_set) {
+ asyw->scale.sx = asyw->state.src_x >> 16;
+ asyw->scale.sy = asyw->state.src_y >> 16;
+ asyw->scale.sw = asyw->state.src_w >> 16;
+ asyw->scale.sh = asyw->state.src_h >> 16;
+ asyw->scale.dw = asyw->state.crtc_w;
+ asyw->scale.dh = asyw->state.crtc_h;
+ if (memcmp(&armw->scale, &asyw->scale, sizeof(asyw->scale)))
+ asyw->set.scale = true;
+ }
+
if (wndw->immd) {
asyw->point.x = asyw->state.crtc_x;
asyw->point.y = asyw->state.crtc_y;
void (*xlut_clr)(struct nv50_wndw *);
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 (*update)(struct nv50_wndw *, u32 *interlock);
};
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 *);
+
struct nv50_wimm_func {
void (*point)(struct nv50_wndw *, struct nv50_wndw_atom *);
void (*update)(struct nv50_wndw *, u32 *interlock);
};
+
+extern const struct nv50_wimm_func curs507a;
#endif