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 "wndw.h" 23 #include "atom.h" 24 25 #include <drm/drm_atomic_helper.h> 26 #include <drm/drm_plane_helper.h> 27 #include <nouveau_bo.h> 28 29 #include <nvif/clc37e.h> 30 31 static void 32 wndwc37e_csc_clr(struct nv50_wndw *wndw) 33 { 34 } 35 36 static void 37 wndwc37e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) 38 { 39 u32 *push, i; 40 if ((push = evo_wait(&wndw->wndw, 13))) { 41 evo_mthd(push, 0x02bc, 12); 42 for (i = 0; i < 12; i++) 43 evo_data(push, asyw->csc.matrix[i]); 44 evo_kick(push, &wndw->wndw); 45 } 46 } 47 48 static void 49 wndwc37e_ilut_clr(struct nv50_wndw *wndw) 50 { 51 u32 *push; 52 if ((push = evo_wait(&wndw->wndw, 2))) { 53 evo_mthd(push, 0x02b8, 1); 54 evo_data(push, 0x00000000); 55 evo_kick(push, &wndw->wndw); 56 } 57 } 58 59 static void 60 wndwc37e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) 61 { 62 u32 *push; 63 if ((push = evo_wait(&wndw->wndw, 4))) { 64 evo_mthd(push, 0x02b0, 3); 65 evo_data(push, asyw->xlut.i.output_mode << 8 | 66 asyw->xlut.i.range << 4 | 67 asyw->xlut.i.size); 68 evo_data(push, asyw->xlut.i.offset >> 8); 69 evo_data(push, asyw->xlut.handle); 70 evo_kick(push, &wndw->wndw); 71 } 72 } 73 74 static void 75 wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) 76 { 77 asyw->xlut.i.mode = 2; 78 asyw->xlut.i.size = 0; 79 asyw->xlut.i.range = 0; 80 asyw->xlut.i.output_mode = 1; 81 asyw->xlut.i.load = head907d_olut_load; 82 } 83 84 void 85 wndwc37e_blend_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) 86 { 87 u32 *push; 88 if ((push = evo_wait(&wndw->wndw, 8))) { 89 evo_mthd(push, 0x02ec, 7); 90 evo_data(push, asyw->blend.depth << 4); 91 evo_data(push, asyw->blend.k1); 92 evo_data(push, asyw->blend.dst_color << 12 | 93 asyw->blend.dst_color << 8 | 94 asyw->blend.src_color << 4 | 95 asyw->blend.src_color); 96 evo_data(push, 0xffff0000); 97 evo_data(push, 0xffff0000); 98 evo_data(push, 0xffff0000); 99 evo_data(push, 0xffff0000); 100 evo_kick(push, &wndw->wndw); 101 } 102 } 103 104 void 105 wndwc37e_image_clr(struct nv50_wndw *wndw) 106 { 107 u32 *push; 108 if ((push = evo_wait(&wndw->wndw, 4))) { 109 evo_mthd(push, 0x0308, 1); 110 evo_data(push, 0x00000000); 111 evo_mthd(push, 0x0240, 1); 112 evo_data(push, 0x00000000); 113 evo_kick(push, &wndw->wndw); 114 } 115 } 116 117 static void 118 wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) 119 { 120 u32 *push; 121 122 if (!(push = evo_wait(&wndw->wndw, 17))) 123 return; 124 125 evo_mthd(push, 0x0308, 1); 126 evo_data(push, asyw->image.mode << 4 | asyw->image.interval); 127 evo_mthd(push, 0x0224, 4); 128 evo_data(push, asyw->image.h << 16 | asyw->image.w); 129 evo_data(push, asyw->image.layout << 4 | asyw->image.blockh); 130 evo_data(push, asyw->csc.valid << 17 | 131 asyw->image.colorspace << 8 | 132 asyw->image.format); 133 evo_data(push, asyw->image.blocks[0] | (asyw->image.pitch[0] >> 6)); 134 evo_mthd(push, 0x0240, 1); 135 evo_data(push, asyw->image.handle[0]); 136 evo_mthd(push, 0x0260, 1); 137 evo_data(push, asyw->image.offset[0] >> 8); 138 evo_mthd(push, 0x0290, 1); 139 evo_data(push, (asyw->state.src_y >> 16) << 16 | 140 (asyw->state.src_x >> 16)); 141 evo_mthd(push, 0x0298, 1); 142 evo_data(push, (asyw->state.src_h >> 16) << 16 | 143 (asyw->state.src_w >> 16)); 144 evo_mthd(push, 0x02a4, 1); 145 evo_data(push, asyw->state.crtc_h << 16 | 146 asyw->state.crtc_w); 147 evo_kick(push, &wndw->wndw); 148 } 149 150 void 151 wndwc37e_ntfy_clr(struct nv50_wndw *wndw) 152 { 153 u32 *push; 154 if ((push = evo_wait(&wndw->wndw, 2))) { 155 evo_mthd(push, 0x021c, 1); 156 evo_data(push, 0x00000000); 157 evo_kick(push, &wndw->wndw); 158 } 159 } 160 161 void 162 wndwc37e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) 163 { 164 u32 *push; 165 if ((push = evo_wait(&wndw->wndw, 3))) { 166 evo_mthd(push, 0x021c, 2); 167 evo_data(push, asyw->ntfy.handle); 168 evo_data(push, asyw->ntfy.offset | asyw->ntfy.awaken); 169 evo_kick(push, &wndw->wndw); 170 } 171 } 172 173 void 174 wndwc37e_sema_clr(struct nv50_wndw *wndw) 175 { 176 u32 *push; 177 if ((push = evo_wait(&wndw->wndw, 2))) { 178 evo_mthd(push, 0x0218, 1); 179 evo_data(push, 0x00000000); 180 evo_kick(push, &wndw->wndw); 181 } 182 } 183 184 void 185 wndwc37e_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) 186 { 187 u32 *push; 188 if ((push = evo_wait(&wndw->wndw, 5))) { 189 evo_mthd(push, 0x020c, 4); 190 evo_data(push, asyw->sema.offset); 191 evo_data(push, asyw->sema.acquire); 192 evo_data(push, asyw->sema.release); 193 evo_data(push, asyw->sema.handle); 194 evo_kick(push, &wndw->wndw); 195 } 196 } 197 198 void 199 wndwc37e_update(struct nv50_wndw *wndw, u32 *interlock) 200 { 201 u32 *push; 202 if ((push = evo_wait(&wndw->wndw, 5))) { 203 evo_mthd(push, 0x0370, 2); 204 evo_data(push, interlock[NV50_DISP_INTERLOCK_CURS] << 1 | 205 interlock[NV50_DISP_INTERLOCK_CORE]); 206 evo_data(push, interlock[NV50_DISP_INTERLOCK_WNDW]); 207 evo_mthd(push, 0x0200, 1); 208 if (interlock[NV50_DISP_INTERLOCK_WIMM] & wndw->interlock.data) 209 evo_data(push, 0x00001001); 210 else 211 evo_data(push, 0x00000001); 212 evo_kick(push, &wndw->wndw); 213 } 214 } 215 216 void 217 wndwc37e_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, 218 struct nv50_head_atom *asyh) 219 { 220 } 221 222 int 223 wndwc37e_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, 224 struct nv50_head_atom *asyh) 225 { 226 return drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state, 227 DRM_PLANE_HELPER_NO_SCALING, 228 DRM_PLANE_HELPER_NO_SCALING, 229 true, true); 230 } 231 232 static const u32 233 wndwc37e_format[] = { 234 DRM_FORMAT_C8, 235 DRM_FORMAT_YUYV, 236 DRM_FORMAT_UYVY, 237 DRM_FORMAT_XRGB8888, 238 DRM_FORMAT_ARGB8888, 239 DRM_FORMAT_RGB565, 240 DRM_FORMAT_XRGB1555, 241 DRM_FORMAT_ARGB1555, 242 DRM_FORMAT_XBGR2101010, 243 DRM_FORMAT_ABGR2101010, 244 DRM_FORMAT_XBGR8888, 245 DRM_FORMAT_ABGR8888, 246 DRM_FORMAT_XRGB2101010, 247 DRM_FORMAT_ARGB2101010, 248 DRM_FORMAT_XBGR16161616F, 249 DRM_FORMAT_ABGR16161616F, 250 0 251 }; 252 253 static const struct nv50_wndw_func 254 wndwc37e = { 255 .acquire = wndwc37e_acquire, 256 .release = wndwc37e_release, 257 .sema_set = wndwc37e_sema_set, 258 .sema_clr = wndwc37e_sema_clr, 259 .ntfy_set = wndwc37e_ntfy_set, 260 .ntfy_clr = wndwc37e_ntfy_clr, 261 .ntfy_reset = corec37d_ntfy_init, 262 .ntfy_wait_begun = base507c_ntfy_wait_begun, 263 .ilut = wndwc37e_ilut, 264 .xlut_set = wndwc37e_ilut_set, 265 .xlut_clr = wndwc37e_ilut_clr, 266 .csc = base907c_csc, 267 .csc_set = wndwc37e_csc_set, 268 .csc_clr = wndwc37e_csc_clr, 269 .image_set = wndwc37e_image_set, 270 .image_clr = wndwc37e_image_clr, 271 .blend_set = wndwc37e_blend_set, 272 .update = wndwc37e_update, 273 }; 274 275 int 276 wndwc37e_new_(const struct nv50_wndw_func *func, struct nouveau_drm *drm, 277 enum drm_plane_type type, int index, s32 oclass, u32 heads, 278 struct nv50_wndw **pwndw) 279 { 280 struct nvc37e_window_channel_dma_v0 args = { 281 .pushbuf = 0xb0007e00 | index, 282 .index = index, 283 }; 284 struct nv50_disp *disp = nv50_disp(drm->dev); 285 struct nv50_wndw *wndw; 286 int ret; 287 288 ret = nv50_wndw_new_(func, drm->dev, type, "wndw", index, 289 wndwc37e_format, heads, NV50_DISP_INTERLOCK_WNDW, 290 BIT(index), &wndw); 291 if (*pwndw = wndw, ret) 292 return ret; 293 294 ret = nv50_dmac_create(&drm->client.device, &disp->disp->object, 295 &oclass, 0, &args, sizeof(args), 296 disp->sync->bo.offset, &wndw->wndw); 297 if (ret) { 298 NV_ERROR(drm, "qndw%04x allocation failed: %d\n", oclass, ret); 299 return ret; 300 } 301 302 wndw->ntfy = NV50_DISP_WNDW_NTFY(wndw->id); 303 wndw->sema = NV50_DISP_WNDW_SEM0(wndw->id); 304 wndw->data = 0x00000000; 305 return 0; 306 } 307 308 int 309 wndwc37e_new(struct nouveau_drm *drm, enum drm_plane_type type, int index, 310 s32 oclass, struct nv50_wndw **pwndw) 311 { 312 return wndwc37e_new_(&wndwc37e, drm, type, index, oclass, 313 BIT(index >> 1), pwndw); 314 } 315