0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include "wndw.h"
0023 #include "atom.h"
0024
0025 #include <drm/drm_atomic_helper.h>
0026 #include <drm/drm_plane_helper.h>
0027 #include <nouveau_bo.h>
0028
0029 #include <nvif/if0014.h>
0030 #include <nvif/pushc37b.h>
0031
0032 #include <nvhw/class/clc37e.h>
0033
0034 static int
0035 wndwc37e_csc_clr(struct nv50_wndw *wndw)
0036 {
0037 return 0;
0038 }
0039
0040 static int
0041 wndwc37e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
0042 {
0043 struct nvif_push *push = wndw->wndw.push;
0044 int ret;
0045
0046 if ((ret = PUSH_WAIT(push, 13)))
0047 return ret;
0048
0049 PUSH_MTHD(push, NVC37E, SET_CSC_RED2RED, asyw->csc.matrix, 12);
0050 return 0;
0051 }
0052
0053 static int
0054 wndwc37e_ilut_clr(struct nv50_wndw *wndw)
0055 {
0056 struct nvif_push *push = wndw->wndw.push;
0057 int ret;
0058
0059 if ((ret = PUSH_WAIT(push, 2)))
0060 return ret;
0061
0062 PUSH_MTHD(push, NVC37E, SET_CONTEXT_DMA_INPUT_LUT, 0x00000000);
0063 return 0;
0064 }
0065
0066 static int
0067 wndwc37e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
0068 {
0069 struct nvif_push *push = wndw->wndw.push;
0070 int ret;
0071
0072 if ((ret = PUSH_WAIT(push, 4)))
0073 return ret;
0074
0075 PUSH_MTHD(push, NVC37E, SET_CONTROL_INPUT_LUT,
0076 NVVAL(NVC37E, SET_CONTROL_INPUT_LUT, OUTPUT_MODE, asyw->xlut.i.output_mode) |
0077 NVVAL(NVC37E, SET_CONTROL_INPUT_LUT, RANGE, asyw->xlut.i.range) |
0078 NVVAL(NVC37E, SET_CONTROL_INPUT_LUT, SIZE, asyw->xlut.i.size),
0079
0080 SET_OFFSET_INPUT_LUT, asyw->xlut.i.offset >> 8,
0081 SET_CONTEXT_DMA_INPUT_LUT, asyw->xlut.handle);
0082 return 0;
0083 }
0084
0085 static void
0086 wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size)
0087 {
0088 asyw->xlut.i.size = size == 1024 ? NVC37E_SET_CONTROL_INPUT_LUT_SIZE_SIZE_1025 :
0089 NVC37E_SET_CONTROL_INPUT_LUT_SIZE_SIZE_257;
0090 asyw->xlut.i.range = NVC37E_SET_CONTROL_INPUT_LUT_RANGE_UNITY;
0091 asyw->xlut.i.output_mode = NVC37E_SET_CONTROL_INPUT_LUT_OUTPUT_MODE_INTERPOLATE;
0092 asyw->xlut.i.load = head907d_olut_load;
0093 }
0094
0095 int
0096 wndwc37e_blend_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
0097 {
0098 struct nvif_push *push = wndw->wndw.push;
0099 int ret;
0100
0101 if ((ret = PUSH_WAIT(push, 8)))
0102 return ret;
0103
0104 PUSH_MTHD(push, NVC37E, SET_COMPOSITION_CONTROL,
0105 NVDEF(NVC37E, SET_COMPOSITION_CONTROL, COLOR_KEY_SELECT, DISABLE) |
0106 NVVAL(NVC37E, SET_COMPOSITION_CONTROL, DEPTH, asyw->blend.depth),
0107
0108 SET_COMPOSITION_CONSTANT_ALPHA,
0109 NVVAL(NVC37E, SET_COMPOSITION_CONSTANT_ALPHA, K1, asyw->blend.k1) |
0110 NVVAL(NVC37E, SET_COMPOSITION_CONSTANT_ALPHA, K2, 0),
0111
0112 SET_COMPOSITION_FACTOR_SELECT,
0113 NVVAL(NVC37E, SET_COMPOSITION_FACTOR_SELECT, SRC_COLOR_FACTOR_MATCH_SELECT,
0114 asyw->blend.src_color) |
0115 NVVAL(NVC37E, SET_COMPOSITION_FACTOR_SELECT, SRC_COLOR_FACTOR_NO_MATCH_SELECT,
0116 asyw->blend.src_color) |
0117 NVVAL(NVC37E, SET_COMPOSITION_FACTOR_SELECT, DST_COLOR_FACTOR_MATCH_SELECT,
0118 asyw->blend.dst_color) |
0119 NVVAL(NVC37E, SET_COMPOSITION_FACTOR_SELECT, DST_COLOR_FACTOR_NO_MATCH_SELECT,
0120 asyw->blend.dst_color),
0121
0122 SET_KEY_ALPHA,
0123 NVVAL(NVC37E, SET_KEY_ALPHA, MIN, 0x0000) |
0124 NVVAL(NVC37E, SET_KEY_ALPHA, MAX, 0xffff),
0125
0126 SET_KEY_RED_CR,
0127 NVVAL(NVC37E, SET_KEY_RED_CR, MIN, 0x0000) |
0128 NVVAL(NVC37E, SET_KEY_RED_CR, MAX, 0xffff),
0129
0130 SET_KEY_GREEN_Y,
0131 NVVAL(NVC37E, SET_KEY_GREEN_Y, MIN, 0x0000) |
0132 NVVAL(NVC37E, SET_KEY_GREEN_Y, MAX, 0xffff),
0133
0134 SET_KEY_BLUE_CB,
0135 NVVAL(NVC37E, SET_KEY_BLUE_CB, MIN, 0x0000) |
0136 NVVAL(NVC37E, SET_KEY_BLUE_CB, MAX, 0xffff));
0137 return 0;
0138 }
0139
0140 int
0141 wndwc37e_image_clr(struct nv50_wndw *wndw)
0142 {
0143 struct nvif_push *push = wndw->wndw.push;
0144 int ret;
0145
0146 if ((ret = PUSH_WAIT(push, 4)))
0147 return ret;
0148
0149 PUSH_MTHD(push, NVC37E, SET_PRESENT_CONTROL,
0150 NVVAL(NVC37E, SET_PRESENT_CONTROL, MIN_PRESENT_INTERVAL, 0) |
0151 NVDEF(NVC37E, SET_PRESENT_CONTROL, BEGIN_MODE, NON_TEARING));
0152
0153 PUSH_MTHD(push, NVC37E, SET_CONTEXT_DMA_ISO(0), 0x00000000);
0154 return 0;
0155 }
0156
0157 static int
0158 wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
0159 {
0160 struct nvif_push *push = wndw->wndw.push;
0161 int ret;
0162
0163 if ((ret = PUSH_WAIT(push, 17)))
0164 return ret;
0165
0166 PUSH_MTHD(push, NVC37E, SET_PRESENT_CONTROL,
0167 NVVAL(NVC37E, SET_PRESENT_CONTROL, MIN_PRESENT_INTERVAL, asyw->image.interval) |
0168 NVVAL(NVC37E, SET_PRESENT_CONTROL, BEGIN_MODE, asyw->image.mode) |
0169 NVDEF(NVC37E, SET_PRESENT_CONTROL, TIMESTAMP_MODE, DISABLE));
0170
0171 PUSH_MTHD(push, NVC37E, SET_SIZE,
0172 NVVAL(NVC37E, SET_SIZE, WIDTH, asyw->image.w) |
0173 NVVAL(NVC37E, SET_SIZE, HEIGHT, asyw->image.h),
0174
0175 SET_STORAGE,
0176 NVVAL(NVC37E, SET_STORAGE, BLOCK_HEIGHT, asyw->image.blockh) |
0177 NVVAL(NVC37E, SET_STORAGE, MEMORY_LAYOUT, asyw->image.layout),
0178
0179 SET_PARAMS,
0180 NVVAL(NVC37E, SET_PARAMS, FORMAT, asyw->image.format) |
0181 NVVAL(NVC37E, SET_PARAMS, COLOR_SPACE, asyw->image.colorspace) |
0182 NVDEF(NVC37E, SET_PARAMS, INPUT_RANGE, BYPASS) |
0183 NVDEF(NVC37E, SET_PARAMS, UNDERREPLICATE, DISABLE) |
0184 NVDEF(NVC37E, SET_PARAMS, DE_GAMMA, NONE) |
0185 NVVAL(NVC37E, SET_PARAMS, CSC, asyw->csc.valid) |
0186 NVDEF(NVC37E, SET_PARAMS, CLAMP_BEFORE_BLEND, DISABLE) |
0187 NVDEF(NVC37E, SET_PARAMS, SWAP_UV, DISABLE),
0188
0189 SET_PLANAR_STORAGE(0),
0190 NVVAL(NVC37E, SET_PLANAR_STORAGE, PITCH, asyw->image.blocks[0]) |
0191 NVVAL(NVC37E, SET_PLANAR_STORAGE, PITCH, asyw->image.pitch[0] >> 6));
0192
0193 PUSH_MTHD(push, NVC37E, SET_CONTEXT_DMA_ISO(0), asyw->image.handle, 1);
0194 PUSH_MTHD(push, NVC37E, SET_OFFSET(0), asyw->image.offset[0] >> 8);
0195
0196 PUSH_MTHD(push, NVC37E, SET_POINT_IN(0),
0197 NVVAL(NVC37E, SET_POINT_IN, X, asyw->state.src_x >> 16) |
0198 NVVAL(NVC37E, SET_POINT_IN, Y, asyw->state.src_y >> 16));
0199
0200 PUSH_MTHD(push, NVC37E, SET_SIZE_IN,
0201 NVVAL(NVC37E, SET_SIZE_IN, WIDTH, asyw->state.src_w >> 16) |
0202 NVVAL(NVC37E, SET_SIZE_IN, HEIGHT, asyw->state.src_h >> 16));
0203
0204 PUSH_MTHD(push, NVC37E, SET_SIZE_OUT,
0205 NVVAL(NVC37E, SET_SIZE_OUT, WIDTH, asyw->state.crtc_w) |
0206 NVVAL(NVC37E, SET_SIZE_OUT, HEIGHT, asyw->state.crtc_h));
0207 return 0;
0208 }
0209
0210 int
0211 wndwc37e_ntfy_clr(struct nv50_wndw *wndw)
0212 {
0213 struct nvif_push *push = wndw->wndw.push;
0214 int ret;
0215
0216 if ((ret = PUSH_WAIT(push, 2)))
0217 return ret;
0218
0219 PUSH_MTHD(push, NVC37E, SET_CONTEXT_DMA_NOTIFIER, 0x00000000);
0220 return 0;
0221 }
0222
0223 int
0224 wndwc37e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
0225 {
0226 struct nvif_push *push = wndw->wndw.push;
0227 int ret;
0228
0229 if ((ret = PUSH_WAIT(push, 3)))
0230 return ret;
0231
0232 PUSH_MTHD(push, NVC37E, SET_CONTEXT_DMA_NOTIFIER, asyw->ntfy.handle,
0233
0234 SET_NOTIFIER_CONTROL,
0235 NVVAL(NVC37E, SET_NOTIFIER_CONTROL, MODE, asyw->ntfy.awaken) |
0236 NVVAL(NVC37E, SET_NOTIFIER_CONTROL, OFFSET, asyw->ntfy.offset >> 4));
0237 return 0;
0238 }
0239
0240 int
0241 wndwc37e_sema_clr(struct nv50_wndw *wndw)
0242 {
0243 struct nvif_push *push = wndw->wndw.push;
0244 int ret;
0245
0246 if ((ret = PUSH_WAIT(push, 2)))
0247 return ret;
0248
0249 PUSH_MTHD(push, NVC37E, SET_CONTEXT_DMA_SEMAPHORE, 0x00000000);
0250 return 0;
0251 }
0252
0253 int
0254 wndwc37e_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
0255 {
0256 struct nvif_push *push = wndw->wndw.push;
0257 int ret;
0258
0259 if ((ret = PUSH_WAIT(push, 5)))
0260 return ret;
0261
0262 PUSH_MTHD(push, NVC37E, SET_SEMAPHORE_CONTROL, asyw->sema.offset,
0263 SET_SEMAPHORE_ACQUIRE, asyw->sema.acquire,
0264 SET_SEMAPHORE_RELEASE, asyw->sema.release,
0265 SET_CONTEXT_DMA_SEMAPHORE, asyw->sema.handle);
0266 return 0;
0267 }
0268
0269 int
0270 wndwc37e_update(struct nv50_wndw *wndw, u32 *interlock)
0271 {
0272 struct nvif_push *push = wndw->wndw.push;
0273 int ret;
0274
0275 if ((ret = PUSH_WAIT(push, 5)))
0276 return ret;
0277
0278 PUSH_MTHD(push, NVC37E, SET_INTERLOCK_FLAGS, interlock[NV50_DISP_INTERLOCK_CURS] << 1 |
0279 interlock[NV50_DISP_INTERLOCK_CORE],
0280 SET_WINDOW_INTERLOCK_FLAGS, interlock[NV50_DISP_INTERLOCK_WNDW]);
0281
0282 PUSH_MTHD(push, NVC37E, UPDATE, 0x00000001 |
0283 NVVAL(NVC37E, UPDATE, INTERLOCK_WITH_WIN_IMM,
0284 !!(interlock[NV50_DISP_INTERLOCK_WIMM] & wndw->interlock.data)));
0285
0286 return PUSH_KICK(push);
0287 }
0288
0289 void
0290 wndwc37e_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
0291 struct nv50_head_atom *asyh)
0292 {
0293 }
0294
0295 int
0296 wndwc37e_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
0297 struct nv50_head_atom *asyh)
0298 {
0299 return drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
0300 DRM_PLANE_HELPER_NO_SCALING,
0301 DRM_PLANE_HELPER_NO_SCALING,
0302 true, true);
0303 }
0304
0305 static const u32
0306 wndwc37e_format[] = {
0307 DRM_FORMAT_C8,
0308 DRM_FORMAT_YUYV,
0309 DRM_FORMAT_UYVY,
0310 DRM_FORMAT_XRGB8888,
0311 DRM_FORMAT_ARGB8888,
0312 DRM_FORMAT_RGB565,
0313 DRM_FORMAT_XRGB1555,
0314 DRM_FORMAT_ARGB1555,
0315 DRM_FORMAT_XBGR2101010,
0316 DRM_FORMAT_ABGR2101010,
0317 DRM_FORMAT_XBGR8888,
0318 DRM_FORMAT_ABGR8888,
0319 DRM_FORMAT_XRGB2101010,
0320 DRM_FORMAT_ARGB2101010,
0321 DRM_FORMAT_XBGR16161616F,
0322 DRM_FORMAT_ABGR16161616F,
0323 0
0324 };
0325
0326 static const struct nv50_wndw_func
0327 wndwc37e = {
0328 .acquire = wndwc37e_acquire,
0329 .release = wndwc37e_release,
0330 .sema_set = wndwc37e_sema_set,
0331 .sema_clr = wndwc37e_sema_clr,
0332 .ntfy_set = wndwc37e_ntfy_set,
0333 .ntfy_clr = wndwc37e_ntfy_clr,
0334 .ntfy_reset = corec37d_ntfy_init,
0335 .ntfy_wait_begun = base507c_ntfy_wait_begun,
0336 .ilut = wndwc37e_ilut,
0337 .ilut_size = 1024,
0338 .xlut_set = wndwc37e_ilut_set,
0339 .xlut_clr = wndwc37e_ilut_clr,
0340 .csc = base907c_csc,
0341 .csc_set = wndwc37e_csc_set,
0342 .csc_clr = wndwc37e_csc_clr,
0343 .image_set = wndwc37e_image_set,
0344 .image_clr = wndwc37e_image_clr,
0345 .blend_set = wndwc37e_blend_set,
0346 .update = wndwc37e_update,
0347 };
0348
0349 int
0350 wndwc37e_new_(const struct nv50_wndw_func *func, struct nouveau_drm *drm,
0351 enum drm_plane_type type, int index, s32 oclass, u32 heads,
0352 struct nv50_wndw **pwndw)
0353 {
0354 struct nvif_disp_chan_v0 args = {
0355 .id = index,
0356 };
0357 struct nv50_disp *disp = nv50_disp(drm->dev);
0358 struct nv50_wndw *wndw;
0359 int ret;
0360
0361 ret = nv50_wndw_new_(func, drm->dev, type, "wndw", index,
0362 wndwc37e_format, heads, NV50_DISP_INTERLOCK_WNDW,
0363 BIT(index), &wndw);
0364 if (*pwndw = wndw, ret)
0365 return ret;
0366
0367 ret = nv50_dmac_create(&drm->client.device, &disp->disp->object,
0368 &oclass, 0, &args, sizeof(args),
0369 disp->sync->offset, &wndw->wndw);
0370 if (ret) {
0371 NV_ERROR(drm, "qndw%04x allocation failed: %d\n", oclass, ret);
0372 return ret;
0373 }
0374
0375 wndw->ntfy = NV50_DISP_WNDW_NTFY(wndw->id);
0376 wndw->sema = NV50_DISP_WNDW_SEM0(wndw->id);
0377 wndw->data = 0x00000000;
0378 return 0;
0379 }
0380
0381 int
0382 wndwc37e_new(struct nouveau_drm *drm, enum drm_plane_type type, int index,
0383 s32 oclass, struct nv50_wndw **pwndw)
0384 {
0385 return wndwc37e_new_(&wndwc37e, drm, type, index, oclass,
0386 BIT(index >> 1), pwndw);
0387 }