cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

base507c.c (9797B)


      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 "base.h"
     23
     24#include <nvif/cl507c.h>
     25#include <nvif/event.h>
     26#include <nvif/push507c.h>
     27#include <nvif/timer.h>
     28
     29#include <nvhw/class/cl507c.h>
     30
     31#include <drm/drm_atomic_helper.h>
     32#include <drm/drm_fourcc.h>
     33#include <drm/drm_plane_helper.h>
     34
     35#include "nouveau_bo.h"
     36
     37int
     38base507c_update(struct nv50_wndw *wndw, u32 *interlock)
     39{
     40	struct nvif_push *push = wndw->wndw.push;
     41	int ret;
     42
     43	if ((ret = PUSH_WAIT(push, 2)))
     44		return ret;
     45
     46	PUSH_MTHD(push, NV507C, UPDATE, interlock[NV50_DISP_INTERLOCK_CORE]);
     47	return PUSH_KICK(push);
     48}
     49
     50int
     51base507c_image_clr(struct nv50_wndw *wndw)
     52{
     53	struct nvif_push *push = wndw->wndw.push;
     54	int ret;
     55
     56	if ((ret = PUSH_WAIT(push, 4)))
     57		return ret;
     58
     59	PUSH_MTHD(push, NV507C, SET_PRESENT_CONTROL,
     60		  NVDEF(NV507C, SET_PRESENT_CONTROL, BEGIN_MODE, NON_TEARING) |
     61		  NVVAL(NV507C, SET_PRESENT_CONTROL, MIN_PRESENT_INTERVAL, 0));
     62
     63	PUSH_MTHD(push, NV507C, SET_CONTEXT_DMA_ISO, 0x00000000);
     64	return 0;
     65}
     66
     67static int
     68base507c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
     69{
     70	struct nvif_push *push = wndw->wndw.push;
     71	int ret;
     72
     73	if ((ret = PUSH_WAIT(push, 13)))
     74		return ret;
     75
     76	PUSH_MTHD(push, NV507C, SET_PRESENT_CONTROL,
     77		  NVVAL(NV507C, SET_PRESENT_CONTROL, BEGIN_MODE, asyw->image.mode) |
     78		  NVVAL(NV507C, SET_PRESENT_CONTROL, MIN_PRESENT_INTERVAL, asyw->image.interval));
     79
     80	PUSH_MTHD(push, NV507C, SET_CONTEXT_DMA_ISO, asyw->image.handle[0]);
     81
     82	if (asyw->image.format == NV507C_SURFACE_SET_PARAMS_FORMAT_RF16_GF16_BF16_AF16) {
     83		PUSH_MTHD(push, NV507C, SET_PROCESSING,
     84			  NVDEF(NV507C, SET_PROCESSING, USE_GAIN_OFS, ENABLE),
     85
     86					SET_CONVERSION,
     87			  NVVAL(NV507C, SET_CONVERSION, GAIN, 0) |
     88			  NVVAL(NV507C, SET_CONVERSION, OFS, 0x64));
     89	} else {
     90		PUSH_MTHD(push, NV507C, SET_PROCESSING,
     91			  NVDEF(NV507C, SET_PROCESSING, USE_GAIN_OFS, DISABLE),
     92
     93					SET_CONVERSION,
     94			  NVVAL(NV507C, SET_CONVERSION, GAIN, 0) |
     95			  NVVAL(NV507C, SET_CONVERSION, OFS, 0));
     96	}
     97
     98	PUSH_MTHD(push, NV507C, SURFACE_SET_OFFSET(0, 0), asyw->image.offset[0] >> 8);
     99
    100	PUSH_MTHD(push, NV507C, SURFACE_SET_SIZE(0),
    101		  NVVAL(NV507C, SURFACE_SET_SIZE, WIDTH, asyw->image.w) |
    102		  NVVAL(NV507C, SURFACE_SET_SIZE, HEIGHT, asyw->image.h),
    103
    104				SURFACE_SET_STORAGE(0),
    105		  NVVAL(NV507C, SURFACE_SET_STORAGE, MEMORY_LAYOUT, asyw->image.layout) |
    106		  NVVAL(NV507C, SURFACE_SET_STORAGE, PITCH, asyw->image.pitch[0] >> 8) |
    107		  NVVAL(NV507C, SURFACE_SET_STORAGE, PITCH, asyw->image.blocks[0]) |
    108		  NVVAL(NV507C, SURFACE_SET_STORAGE, BLOCK_HEIGHT, asyw->image.blockh),
    109
    110				SURFACE_SET_PARAMS(0),
    111		  NVVAL(NV507C, SURFACE_SET_PARAMS, FORMAT, asyw->image.format) |
    112		  NVDEF(NV507C, SURFACE_SET_PARAMS, SUPER_SAMPLE, X1_AA) |
    113		  NVDEF(NV507C, SURFACE_SET_PARAMS, GAMMA, LINEAR) |
    114		  NVDEF(NV507C, SURFACE_SET_PARAMS, LAYOUT, FRM) |
    115		  NVVAL(NV507C, SURFACE_SET_PARAMS, KIND, asyw->image.kind) |
    116		  NVDEF(NV507C, SURFACE_SET_PARAMS, PART_STRIDE, PARTSTRIDE_256));
    117	return 0;
    118}
    119
    120int
    121base507c_xlut_clr(struct nv50_wndw *wndw)
    122{
    123	struct nvif_push *push = wndw->wndw.push;
    124	int ret;
    125
    126	if ((ret = PUSH_WAIT(push, 2)))
    127		return ret;
    128
    129	PUSH_MTHD(push, NV507C, SET_BASE_LUT_LO,
    130		  NVDEF(NV507C, SET_BASE_LUT_LO, ENABLE, DISABLE));
    131	return 0;
    132}
    133
    134int
    135base507c_xlut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
    136{
    137	struct nvif_push *push = wndw->wndw.push;
    138	int ret;
    139
    140	if ((ret = PUSH_WAIT(push, 2)))
    141		return ret;
    142
    143	PUSH_MTHD(push, NV507C, SET_BASE_LUT_LO,
    144		  NVDEF(NV507C, SET_BASE_LUT_LO, ENABLE, USE_CORE_LUT));
    145	return 0;
    146}
    147
    148int
    149base507c_ntfy_wait_begun(struct nouveau_bo *bo, u32 offset,
    150			 struct nvif_device *device)
    151{
    152	s64 time = nvif_msec(device, 2000ULL,
    153		if (NVBO_TD32(bo, offset, NV_DISP_BASE_NOTIFIER_1, _0, STATUS, ==, BEGUN))
    154			break;
    155		usleep_range(1, 2);
    156	);
    157	return time < 0 ? time : 0;
    158}
    159
    160int
    161base507c_ntfy_clr(struct nv50_wndw *wndw)
    162{
    163	struct nvif_push *push = wndw->wndw.push;
    164	int ret;
    165
    166	if ((ret = PUSH_WAIT(push, 2)))
    167		return ret;
    168
    169	PUSH_MTHD(push, NV507C, SET_CONTEXT_DMA_NOTIFIER, 0x00000000);
    170	return 0;
    171}
    172
    173int
    174base507c_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
    175{
    176	struct nvif_push *push = wndw->wndw.push;
    177	int ret;
    178
    179	if ((ret = PUSH_WAIT(push, 3)))
    180		return ret;
    181
    182	PUSH_MTHD(push, NV507C, SET_NOTIFIER_CONTROL,
    183		  NVVAL(NV507C, SET_NOTIFIER_CONTROL, MODE, asyw->ntfy.awaken) |
    184		  NVVAL(NV507C, SET_NOTIFIER_CONTROL, OFFSET, asyw->ntfy.offset >> 2),
    185
    186				SET_CONTEXT_DMA_NOTIFIER, asyw->ntfy.handle);
    187	return 0;
    188}
    189
    190void
    191base507c_ntfy_reset(struct nouveau_bo *bo, u32 offset)
    192{
    193	NVBO_WR32(bo, offset, NV_DISP_BASE_NOTIFIER_1, _0,
    194			NVDEF(NV_DISP_BASE_NOTIFIER_1, _0, STATUS, NOT_BEGUN));
    195}
    196
    197int
    198base507c_sema_clr(struct nv50_wndw *wndw)
    199{
    200	struct nvif_push *push = wndw->wndw.push;
    201	int ret;
    202
    203	if ((ret = PUSH_WAIT(push, 2)))
    204		return ret;
    205
    206	PUSH_MTHD(push, NV507C, SET_CONTEXT_DMA_SEMAPHORE, 0x00000000);
    207	return 0;
    208}
    209
    210int
    211base507c_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
    212{
    213	struct nvif_push *push = wndw->wndw.push;
    214	int ret;
    215
    216	if ((ret = PUSH_WAIT(push, 5)))
    217		return ret;
    218
    219	PUSH_MTHD(push, NV507C, SET_SEMAPHORE_CONTROL, asyw->sema.offset,
    220				SET_SEMAPHORE_ACQUIRE, asyw->sema.acquire,
    221				SET_SEMAPHORE_RELEASE, asyw->sema.release,
    222				SET_CONTEXT_DMA_SEMAPHORE, asyw->sema.handle);
    223	return 0;
    224}
    225
    226void
    227base507c_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
    228		 struct nv50_head_atom *asyh)
    229{
    230	asyh->base.cpp = 0;
    231}
    232
    233int
    234base507c_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
    235		 struct nv50_head_atom *asyh)
    236{
    237	const struct drm_framebuffer *fb = asyw->state.fb;
    238	int ret;
    239
    240	ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
    241						  DRM_PLANE_HELPER_NO_SCALING,
    242						  DRM_PLANE_HELPER_NO_SCALING,
    243						  false, true);
    244	if (ret)
    245		return ret;
    246
    247	if (!wndw->func->ilut) {
    248		if ((asyh->base.cpp != 1) ^ (fb->format->cpp[0] != 1))
    249			asyh->state.color_mgmt_changed = true;
    250	}
    251
    252	asyh->base.depth = fb->format->depth;
    253	asyh->base.cpp = fb->format->cpp[0];
    254	asyh->base.x = asyw->state.src.x1 >> 16;
    255	asyh->base.y = asyw->state.src.y1 >> 16;
    256	asyh->base.w = asyw->state.fb->width;
    257	asyh->base.h = asyw->state.fb->height;
    258
    259	/* Some newer formats, esp FP16 ones, don't have a
    260	 * "depth". There's nothing that really makes sense there
    261	 * either, so just set it to the implicit bit count.
    262	 */
    263	if (!asyh->base.depth)
    264		asyh->base.depth = asyh->base.cpp * 8;
    265
    266	return 0;
    267}
    268
    269const u32
    270base507c_format[] = {
    271	DRM_FORMAT_C8,
    272	DRM_FORMAT_RGB565,
    273	DRM_FORMAT_XRGB1555,
    274	DRM_FORMAT_ARGB1555,
    275	DRM_FORMAT_XRGB8888,
    276	DRM_FORMAT_ARGB8888,
    277	DRM_FORMAT_XBGR2101010,
    278	DRM_FORMAT_ABGR2101010,
    279	DRM_FORMAT_XBGR8888,
    280	DRM_FORMAT_ABGR8888,
    281	DRM_FORMAT_XBGR16161616F,
    282	DRM_FORMAT_ABGR16161616F,
    283	0
    284};
    285
    286static const struct nv50_wndw_func
    287base507c = {
    288	.acquire = base507c_acquire,
    289	.release = base507c_release,
    290	.sema_set = base507c_sema_set,
    291	.sema_clr = base507c_sema_clr,
    292	.ntfy_reset = base507c_ntfy_reset,
    293	.ntfy_set = base507c_ntfy_set,
    294	.ntfy_clr = base507c_ntfy_clr,
    295	.ntfy_wait_begun = base507c_ntfy_wait_begun,
    296	.olut_core = 1,
    297	.xlut_set = base507c_xlut_set,
    298	.xlut_clr = base507c_xlut_clr,
    299	.image_set = base507c_image_set,
    300	.image_clr = base507c_image_clr,
    301	.update = base507c_update,
    302};
    303
    304int
    305base507c_new_(const struct nv50_wndw_func *func, const u32 *format,
    306	      struct nouveau_drm *drm, int head, s32 oclass, u32 interlock_data,
    307	      struct nv50_wndw **pwndw)
    308{
    309	struct nv50_disp_base_channel_dma_v0 args = {
    310		.head = head,
    311	};
    312	struct nouveau_display *disp = nouveau_display(drm->dev);
    313	struct nv50_disp *disp50 = nv50_disp(drm->dev);
    314	struct nv50_wndw *wndw;
    315	int ret;
    316
    317	ret = nv50_wndw_new_(func, drm->dev, DRM_PLANE_TYPE_PRIMARY,
    318			     "base", head, format, BIT(head),
    319			     NV50_DISP_INTERLOCK_BASE, interlock_data, &wndw);
    320	if (*pwndw = wndw, ret)
    321		return ret;
    322
    323	ret = nv50_dmac_create(&drm->client.device, &disp->disp.object,
    324			       &oclass, head, &args, sizeof(args),
    325			       disp50->sync->offset, &wndw->wndw);
    326	if (ret) {
    327		NV_ERROR(drm, "base%04x allocation failed: %d\n", oclass, ret);
    328		return ret;
    329	}
    330
    331	ret = nvif_notify_ctor(&wndw->wndw.base.user, "kmsBaseNtfy",
    332			       wndw->notify.func, false,
    333			       NV50_DISP_BASE_CHANNEL_DMA_V0_NTFY_UEVENT,
    334			       &(struct nvif_notify_uevent_req) {},
    335			       sizeof(struct nvif_notify_uevent_req),
    336			       sizeof(struct nvif_notify_uevent_rep),
    337			       &wndw->notify);
    338	if (ret)
    339		return ret;
    340
    341	wndw->ntfy = NV50_DISP_BASE_NTFY(wndw->id);
    342	wndw->sema = NV50_DISP_BASE_SEM0(wndw->id);
    343	wndw->data = 0x00000000;
    344	return 0;
    345}
    346
    347int
    348base507c_new(struct nouveau_drm *drm, int head, s32 oclass,
    349	     struct nv50_wndw **pwndw)
    350{
    351	return base507c_new_(&base507c, base507c_format, drm, head, oclass,
    352			     0x00000002 << (head * 8), pwndw);
    353}