1 | /* |
2 | * Copyright 2018 Red Hat Inc. |
3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), |
6 | * to deal in the Software without restriction, including without limitation |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
8 | * and/or sell copies of the Software, and to permit persons to whom the |
9 | * Software is furnished to do so, subject to the following conditions: |
10 | * |
11 | * The above copyright notice and this permission notice shall be included in |
12 | * all copies or substantial portions of the Software. |
13 | * |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
20 | * OTHER DEALINGS IN THE SOFTWARE. |
21 | */ |
22 | #include "ovly.h" |
23 | #include "atom.h" |
24 | |
25 | #include <drm/drm_atomic_helper.h> |
26 | #include <drm/drm_fourcc.h> |
27 | |
28 | #include <nvif/if0014.h> |
29 | #include <nvif/push507c.h> |
30 | |
31 | #include <nvhw/class/cl507e.h> |
32 | |
33 | int |
34 | ovly507e_scale_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) |
35 | { |
36 | struct nvif_push *push = wndw->wndw.push; |
37 | int ret; |
38 | |
39 | if ((ret = PUSH_WAIT(push, 4))) |
40 | return ret; |
41 | |
42 | PUSH_MTHD(push, NV507E, SET_POINT_IN, |
43 | NVVAL(NV507E, SET_POINT_IN, X, asyw->scale.sx) | |
44 | NVVAL(NV507E, SET_POINT_IN, Y, asyw->scale.sy), |
45 | |
46 | SET_SIZE_IN, |
47 | NVVAL(NV507E, SET_SIZE_IN, WIDTH, asyw->scale.sw) | |
48 | NVVAL(NV507E, SET_SIZE_IN, HEIGHT, asyw->scale.sh), |
49 | |
50 | SET_SIZE_OUT, |
51 | NVVAL(NV507E, SET_SIZE_OUT, WIDTH, asyw->scale.dw)); |
52 | return 0; |
53 | } |
54 | |
55 | static int |
56 | ovly507e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) |
57 | { |
58 | struct nvif_push *push = wndw->wndw.push; |
59 | int ret; |
60 | |
61 | if ((ret = PUSH_WAIT(push, 12))) |
62 | return ret; |
63 | |
64 | PUSH_MTHD(push, NV507E, SET_PRESENT_CONTROL, |
65 | NVDEF(NV507E, SET_PRESENT_CONTROL, BEGIN_MODE, ASAP) | |
66 | NVVAL(NV507E, SET_PRESENT_CONTROL, MIN_PRESENT_INTERVAL, asyw->image.interval)); |
67 | |
68 | PUSH_MTHD(push, NV507E, SET_CONTEXT_DMA_ISO, asyw->image.handle[0]); |
69 | |
70 | PUSH_MTHD(push, NV507E, SET_COMPOSITION_CONTROL, |
71 | NVDEF(NV507E, SET_COMPOSITION_CONTROL, MODE, OPAQUE_SUSPEND_BASE)); |
72 | |
73 | PUSH_MTHD(push, NV507E, SURFACE_SET_OFFSET, asyw->image.offset[0] >> 8); |
74 | |
75 | PUSH_MTHD(push, NV507E, SURFACE_SET_SIZE, |
76 | NVVAL(NV507E, SURFACE_SET_SIZE, WIDTH, asyw->image.w) | |
77 | NVVAL(NV507E, SURFACE_SET_SIZE, HEIGHT, asyw->image.h), |
78 | |
79 | SURFACE_SET_STORAGE, |
80 | NVVAL(NV507E, SURFACE_SET_STORAGE, BLOCK_HEIGHT, asyw->image.blockh) | |
81 | NVVAL(NV507E, SURFACE_SET_STORAGE, PITCH, (asyw->image.pitch[0] >> 8)) | |
82 | NVVAL(NV507E, SURFACE_SET_STORAGE, PITCH, asyw->image.blocks[0]) | |
83 | NVVAL(NV507E, SURFACE_SET_STORAGE, MEMORY_LAYOUT, asyw->image.layout), |
84 | |
85 | SURFACE_SET_PARAMS, |
86 | NVVAL(NV507E, SURFACE_SET_PARAMS, FORMAT, asyw->image.format) | |
87 | NVVAL(NV507E, SURFACE_SET_PARAMS, COLOR_SPACE, asyw->image.colorspace) | |
88 | NVVAL(NV507E, SURFACE_SET_PARAMS, KIND, asyw->image.kind) | |
89 | NVDEF(NV507E, SURFACE_SET_PARAMS, PART_STRIDE, PARTSTRIDE_256)); |
90 | return 0; |
91 | } |
92 | |
93 | void |
94 | ovly507e_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, |
95 | struct nv50_head_atom *asyh) |
96 | { |
97 | asyh->ovly.cpp = 0; |
98 | } |
99 | |
100 | int |
101 | ovly507e_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, |
102 | struct nv50_head_atom *asyh) |
103 | { |
104 | const struct drm_framebuffer *fb = asyw->state.fb; |
105 | int ret; |
106 | |
107 | ret = drm_atomic_helper_check_plane_state(plane_state: &asyw->state, crtc_state: &asyh->state, |
108 | DRM_PLANE_NO_SCALING, |
109 | DRM_PLANE_NO_SCALING, |
110 | can_position: true, can_update_disabled: true); |
111 | if (ret) |
112 | return ret; |
113 | |
114 | asyh->ovly.cpp = fb->format->cpp[0]; |
115 | return 0; |
116 | } |
117 | |
118 | #include "nouveau_bo.h" |
119 | |
120 | static const struct nv50_wndw_func |
121 | ovly507e = { |
122 | .acquire = ovly507e_acquire, |
123 | .release = ovly507e_release, |
124 | .ntfy_set = base507c_ntfy_set, |
125 | .ntfy_clr = base507c_ntfy_clr, |
126 | .ntfy_reset = base507c_ntfy_reset, |
127 | .ntfy_wait_begun = base507c_ntfy_wait_begun, |
128 | .image_set = ovly507e_image_set, |
129 | .image_clr = base507c_image_clr, |
130 | .scale_set = ovly507e_scale_set, |
131 | .update = base507c_update, |
132 | }; |
133 | |
134 | static const u32 |
135 | ovly507e_format[] = { |
136 | DRM_FORMAT_YUYV, |
137 | DRM_FORMAT_UYVY, |
138 | DRM_FORMAT_XRGB8888, |
139 | DRM_FORMAT_XRGB1555, |
140 | 0 |
141 | }; |
142 | |
143 | int |
144 | ovly507e_new_(const struct nv50_wndw_func *func, const u32 *format, |
145 | struct nouveau_drm *drm, int head, s32 oclass, u32 interlock_data, |
146 | struct nv50_wndw **pwndw) |
147 | { |
148 | struct nvif_disp_chan_v0 args = { |
149 | .id = head, |
150 | }; |
151 | struct nv50_disp *disp = nv50_disp(dev: drm->dev); |
152 | struct nv50_wndw *wndw; |
153 | int ret; |
154 | |
155 | ret = nv50_wndw_new_(func, drm->dev, DRM_PLANE_TYPE_OVERLAY, |
156 | name: "ovly" , index: head, format, BIT(head), |
157 | NV50_DISP_INTERLOCK_OVLY, interlock_data, |
158 | &wndw); |
159 | if (*pwndw = wndw, ret) |
160 | return ret; |
161 | |
162 | ret = nv50_dmac_create(device: &drm->client.device, disp: &disp->disp->object, |
163 | oclass: &oclass, head: 0, data: &args, size: sizeof(args), |
164 | syncbuf: disp->sync->offset, dmac: &wndw->wndw); |
165 | if (ret) { |
166 | NV_ERROR(drm, "ovly%04x allocation failed: %d\n" , oclass, ret); |
167 | return ret; |
168 | } |
169 | |
170 | wndw->ntfy = NV50_DISP_OVLY_NTFY(wndw->id); |
171 | wndw->sema = NV50_DISP_OVLY_SEM0(wndw->id); |
172 | wndw->data = 0x00000000; |
173 | return 0; |
174 | } |
175 | |
176 | int |
177 | ovly507e_new(struct nouveau_drm *drm, int head, s32 oclass, |
178 | struct nv50_wndw **pwndw) |
179 | { |
180 | return ovly507e_new_(&ovly507e, format: ovly507e_format, drm, head, oclass, |
181 | interlock_data: 0x00000004 << (head * 8), pwndw); |
182 | } |
183 | |