Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2018 Red Hat Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  */
0022 #include "curs.h"
0023 #include "core.h"
0024 #include "head.h"
0025 
0026 #include <nvif/if0014.h>
0027 #include <nvif/timer.h>
0028 
0029 #include <nvhw/class/cl507a.h>
0030 
0031 #include <drm/drm_atomic_helper.h>
0032 #include <drm/drm_plane_helper.h>
0033 
0034 bool
0035 curs507a_space(struct nv50_wndw *wndw)
0036 {
0037     nvif_msec(&nouveau_drm(wndw->plane.dev)->client.device, 100,
0038         if (NVIF_TV32(&wndw->wimm.base.user, NV507A, FREE, COUNT, >=, 4))
0039             return true;
0040     );
0041 
0042     WARN_ON(1);
0043     return false;
0044 }
0045 
0046 static int
0047 curs507a_update(struct nv50_wndw *wndw, u32 *interlock)
0048 {
0049     struct nvif_object *user = &wndw->wimm.base.user;
0050     int ret = nvif_chan_wait(&wndw->wimm, 1);
0051     if (ret == 0) {
0052         NVIF_WR32(user, NV507A, UPDATE,
0053               NVDEF(NV507A, UPDATE, INTERLOCK_WITH_CORE, DISABLE));
0054     }
0055     return ret;
0056 }
0057 
0058 static int
0059 curs507a_point(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
0060 {
0061     struct nvif_object *user = &wndw->wimm.base.user;
0062     int ret = nvif_chan_wait(&wndw->wimm, 1);
0063     if (ret == 0) {
0064         NVIF_WR32(user, NV507A, SET_CURSOR_HOT_SPOT_POINT_OUT,
0065               NVVAL(NV507A, SET_CURSOR_HOT_SPOT_POINT_OUT, X, asyw->point.x) |
0066               NVVAL(NV507A, SET_CURSOR_HOT_SPOT_POINT_OUT, Y, asyw->point.y));
0067     }
0068     return ret;
0069 }
0070 
0071 const struct nv50_wimm_func
0072 curs507a = {
0073     .point = curs507a_point,
0074     .update = curs507a_update,
0075 };
0076 
0077 static void
0078 curs507a_prepare(struct nv50_wndw *wndw, struct nv50_head_atom *asyh,
0079          struct nv50_wndw_atom *asyw)
0080 {
0081     u32 handle = nv50_disp(wndw->plane.dev)->core->chan.vram.handle;
0082     u32 offset = asyw->image.offset[0];
0083     if (asyh->curs.handle != handle || asyh->curs.offset != offset) {
0084         asyh->curs.handle = handle;
0085         asyh->curs.offset = offset;
0086         asyh->set.curs = asyh->curs.visible;
0087     }
0088 }
0089 
0090 static void
0091 curs507a_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
0092          struct nv50_head_atom *asyh)
0093 {
0094     asyh->curs.visible = false;
0095 }
0096 
0097 static int
0098 curs507a_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
0099          struct nv50_head_atom *asyh)
0100 {
0101     struct nouveau_drm *drm = nouveau_drm(wndw->plane.dev);
0102     struct nv50_head *head = nv50_head(asyw->state.crtc);
0103     int ret;
0104 
0105     ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
0106                           DRM_PLANE_HELPER_NO_SCALING,
0107                           DRM_PLANE_HELPER_NO_SCALING,
0108                           true, true);
0109     asyh->curs.visible = asyw->state.visible;
0110     if (ret || !asyh->curs.visible)
0111         return ret;
0112 
0113     if (asyw->state.crtc_w != asyw->state.crtc_h) {
0114         NV_ATOMIC(drm, "Plane width/height must be equal for cursors\n");
0115         return -EINVAL;
0116     }
0117 
0118     if (asyw->image.w != asyw->state.crtc_w) {
0119         NV_ATOMIC(drm, "Plane width must be equal to fb width for cursors (height can be larger though)\n");
0120         return -EINVAL;
0121     }
0122 
0123     if (asyw->state.src_x || asyw->state.src_y) {
0124         NV_ATOMIC(drm, "Cursor planes do not support framebuffer offsets\n");
0125         return -EINVAL;
0126     }
0127 
0128     ret = head->func->curs_layout(head, asyw, asyh);
0129     if (ret)
0130         return ret;
0131 
0132     return head->func->curs_format(head, asyw, asyh);
0133 }
0134 
0135 static const u32
0136 curs507a_format[] = {
0137     DRM_FORMAT_ARGB8888,
0138     0
0139 };
0140 
0141 static const struct nv50_wndw_func
0142 curs507a_wndw = {
0143     .acquire = curs507a_acquire,
0144     .release = curs507a_release,
0145     .prepare = curs507a_prepare,
0146 };
0147 
0148 int
0149 curs507a_new_(const struct nv50_wimm_func *func, struct nouveau_drm *drm,
0150           int head, s32 oclass, u32 interlock_data,
0151           struct nv50_wndw **pwndw)
0152 {
0153     struct nvif_disp_chan_v0 args = {
0154         .id = head,
0155     };
0156     struct nv50_disp *disp = nv50_disp(drm->dev);
0157     struct nv50_wndw *wndw;
0158     int ret;
0159 
0160     ret = nv50_wndw_new_(&curs507a_wndw, drm->dev, DRM_PLANE_TYPE_CURSOR,
0161                  "curs", head, curs507a_format, BIT(head),
0162                  NV50_DISP_INTERLOCK_CURS, interlock_data, &wndw);
0163     if (*pwndw = wndw, ret)
0164         return ret;
0165 
0166     ret = nvif_object_ctor(&disp->disp->object, "kmsCurs", 0, oclass,
0167                    &args, sizeof(args), &wndw->wimm.base.user);
0168     if (ret) {
0169         NV_ERROR(drm, "curs%04x allocation failed: %d\n", oclass, ret);
0170         return ret;
0171     }
0172 
0173     nvif_object_map(&wndw->wimm.base.user, NULL, 0);
0174     wndw->immd = func;
0175     wndw->ctxdma.parent = NULL;
0176     return 0;
0177 }
0178 
0179 int
0180 curs507a_new(struct nouveau_drm *drm, int head, s32 oclass,
0181          struct nv50_wndw **pwndw)
0182 {
0183     return curs507a_new_(&curs507a, drm, head, oclass,
0184                  0x00000001 << (head * 8), pwndw);
0185 }