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

headc57d.c (8272B)


      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 "head.h"
     23#include "atom.h"
     24#include "core.h"
     25
     26#include <nvif/pushc37b.h>
     27
     28#include <nvhw/class/clc57d.h>
     29
     30static int
     31headc57d_or(struct nv50_head *head, struct nv50_head_atom *asyh)
     32{
     33	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
     34	const int i = head->base.index;
     35	u8 depth;
     36	int ret;
     37
     38	/*XXX: This is a dirty hack until OR depth handling is
     39	 *     improved later for deep colour etc.
     40	 */
     41	switch (asyh->or.depth) {
     42	case 6: depth = 5; break;
     43	case 5: depth = 4; break;
     44	case 2: depth = 1; break;
     45	case 0:	depth = 4; break;
     46	default:
     47		depth = asyh->or.depth;
     48		WARN_ON(1);
     49		break;
     50	}
     51
     52	if ((ret = PUSH_WAIT(push, 2)))
     53		return ret;
     54
     55	PUSH_MTHD(push, NVC57D, HEAD_SET_CONTROL_OUTPUT_RESOURCE(i),
     56		  NVVAL(NVC57D, HEAD_SET_CONTROL_OUTPUT_RESOURCE, CRC_MODE, asyh->or.crc_raster) |
     57		  NVVAL(NVC57D, HEAD_SET_CONTROL_OUTPUT_RESOURCE, HSYNC_POLARITY, asyh->or.nhsync) |
     58		  NVVAL(NVC57D, HEAD_SET_CONTROL_OUTPUT_RESOURCE, VSYNC_POLARITY, asyh->or.nvsync) |
     59		  NVVAL(NVC57D, HEAD_SET_CONTROL_OUTPUT_RESOURCE, PIXEL_DEPTH, depth) |
     60		  NVDEF(NVC57D, HEAD_SET_CONTROL_OUTPUT_RESOURCE, COLOR_SPACE_OVERRIDE, DISABLE) |
     61		  NVDEF(NVC57D, HEAD_SET_CONTROL_OUTPUT_RESOURCE, EXT_PACKET_WIN, NONE));
     62	return 0;
     63}
     64
     65static int
     66headc57d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh)
     67{
     68	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
     69	const int i = head->base.index;
     70	int ret;
     71
     72	if ((ret = PUSH_WAIT(push, 2)))
     73		return ret;
     74
     75	//TODO:
     76	PUSH_MTHD(push, NVC57D, HEAD_SET_PROCAMP(i),
     77		  NVDEF(NVC57D, HEAD_SET_PROCAMP, COLOR_SPACE, RGB) |
     78		  NVDEF(NVC57D, HEAD_SET_PROCAMP, CHROMA_LPF, DISABLE) |
     79		  NVDEF(NVC57D, HEAD_SET_PROCAMP, DYNAMIC_RANGE, VESA));
     80	return 0;
     81}
     82
     83static int
     84headc57d_olut_clr(struct nv50_head *head)
     85{
     86	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
     87	const int i = head->base.index;
     88	int ret;
     89
     90	if ((ret = PUSH_WAIT(push, 2)))
     91		return ret;
     92
     93	PUSH_MTHD(push, NVC57D, HEAD_SET_CONTEXT_DMA_OLUT(i), 0x00000000);
     94	return 0;
     95}
     96
     97static int
     98headc57d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
     99{
    100	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
    101	const int i = head->base.index;
    102	int ret;
    103
    104	if ((ret = PUSH_WAIT(push, 5)))
    105		return ret;
    106
    107	PUSH_MTHD(push, NVC57D, HEAD_SET_OLUT_CONTROL(i),
    108		  NVVAL(NVC57D, HEAD_SET_OLUT_CONTROL, INTERPOLATE, asyh->olut.output_mode) |
    109		  NVDEF(NVC57D, HEAD_SET_OLUT_CONTROL, MIRROR, DISABLE) |
    110		  NVVAL(NVC57D, HEAD_SET_OLUT_CONTROL, MODE, asyh->olut.mode) |
    111		  NVVAL(NVC57D, HEAD_SET_OLUT_CONTROL, SIZE, asyh->olut.size),
    112
    113				HEAD_SET_OLUT_FP_NORM_SCALE(i), 0xffffffff,
    114				HEAD_SET_CONTEXT_DMA_OLUT(i), asyh->olut.handle,
    115				HEAD_SET_OFFSET_OLUT(i), asyh->olut.offset >> 8);
    116	return 0;
    117}
    118
    119static void
    120headc57d_olut_load_8(struct drm_color_lut *in, int size, void __iomem *mem)
    121{
    122	memset_io(mem, 0x00, 0x20); /* VSS header. */
    123	mem += 0x20;
    124
    125	while (size--) {
    126		u16 r = drm_color_lut_extract(in->  red + 0, 16);
    127		u16 g = drm_color_lut_extract(in->green + 0, 16);
    128		u16 b = drm_color_lut_extract(in-> blue + 0, 16);
    129		u16 ri = 0, gi = 0, bi = 0, i;
    130
    131		if (in++, size) {
    132			ri = (drm_color_lut_extract(in->  red, 16) - r) / 4;
    133			gi = (drm_color_lut_extract(in->green, 16) - g) / 4;
    134			bi = (drm_color_lut_extract(in-> blue, 16) - b) / 4;
    135		}
    136
    137		for (i = 0; i < 4; i++, mem += 8) {
    138			writew(r + ri * i, mem + 0);
    139			writew(g + gi * i, mem + 2);
    140			writew(b + bi * i, mem + 4);
    141		}
    142	}
    143
    144	/* INTERPOLATE modes require a "next" entry to interpolate with,
    145	 * so we replicate the last entry to deal with this for now.
    146	 */
    147	writew(readw(mem - 8), mem + 0);
    148	writew(readw(mem - 6), mem + 2);
    149	writew(readw(mem - 4), mem + 4);
    150}
    151
    152static void
    153headc57d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem)
    154{
    155	memset_io(mem, 0x00, 0x20); /* VSS header. */
    156	mem += 0x20;
    157
    158	for (; size--; in++, mem += 0x08) {
    159		writew(drm_color_lut_extract(in->  red, 16), mem + 0);
    160		writew(drm_color_lut_extract(in->green, 16), mem + 2);
    161		writew(drm_color_lut_extract(in-> blue, 16), mem + 4);
    162	}
    163
    164	/* INTERPOLATE modes require a "next" entry to interpolate with,
    165	 * so we replicate the last entry to deal with this for now.
    166	 */
    167	writew(readw(mem - 8), mem + 0);
    168	writew(readw(mem - 6), mem + 2);
    169	writew(readw(mem - 4), mem + 4);
    170}
    171
    172static bool
    173headc57d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size)
    174{
    175	if (size != 0 && size != 256 && size != 1024)
    176		return false;
    177
    178	asyh->olut.mode = NVC57D_HEAD_SET_OLUT_CONTROL_MODE_DIRECT10;
    179	asyh->olut.size = 4 /* VSS header. */ + 1024 + 1 /* Entries. */;
    180	asyh->olut.output_mode = NVC57D_HEAD_SET_OLUT_CONTROL_INTERPOLATE_ENABLE;
    181	if (size == 256)
    182		asyh->olut.load = headc57d_olut_load_8;
    183	else
    184		asyh->olut.load = headc57d_olut_load;
    185	return true;
    186}
    187
    188static int
    189headc57d_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
    190{
    191	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
    192	struct nv50_head_mode *m = &asyh->mode;
    193	const int i = head->base.index;
    194	int ret;
    195
    196	if ((ret = PUSH_WAIT(push, 15)))
    197		return ret;
    198
    199	PUSH_MTHD(push, NVC57D, HEAD_SET_RASTER_SIZE(i),
    200		  NVVAL(NVC57D, HEAD_SET_RASTER_SIZE, WIDTH, m->h.active) |
    201		  NVVAL(NVC57D, HEAD_SET_RASTER_SIZE, HEIGHT, m->v.active),
    202
    203				HEAD_SET_RASTER_SYNC_END(i),
    204		  NVVAL(NVC57D, HEAD_SET_RASTER_SYNC_END, X, m->h.synce) |
    205		  NVVAL(NVC57D, HEAD_SET_RASTER_SYNC_END, Y, m->v.synce),
    206
    207				HEAD_SET_RASTER_BLANK_END(i),
    208		  NVVAL(NVC57D, HEAD_SET_RASTER_BLANK_END, X, m->h.blanke) |
    209		  NVVAL(NVC57D, HEAD_SET_RASTER_BLANK_END, Y, m->v.blanke),
    210
    211				HEAD_SET_RASTER_BLANK_START(i),
    212		  NVVAL(NVC57D, HEAD_SET_RASTER_BLANK_START, X, m->h.blanks) |
    213		  NVVAL(NVC57D, HEAD_SET_RASTER_BLANK_START, Y, m->v.blanks));
    214
    215	//XXX:
    216	PUSH_NVSQ(push, NVC57D, 0x2074 + (i * 0x400), m->v.blank2e << 16 | m->v.blank2s);
    217	PUSH_NVSQ(push, NVC57D, 0x2008 + (i * 0x400), m->interlace);
    218
    219	PUSH_MTHD(push, NVC57D, HEAD_SET_PIXEL_CLOCK_FREQUENCY(i),
    220		  NVVAL(NVC57D, HEAD_SET_PIXEL_CLOCK_FREQUENCY, HERTZ, m->clock * 1000));
    221
    222	PUSH_MTHD(push, NVC57D, HEAD_SET_PIXEL_CLOCK_FREQUENCY_MAX(i),
    223		  NVVAL(NVC57D, HEAD_SET_PIXEL_CLOCK_FREQUENCY_MAX, HERTZ, m->clock * 1000));
    224
    225	/*XXX: HEAD_USAGE_BOUNDS, doesn't belong here. */
    226	PUSH_MTHD(push, NVC57D, HEAD_SET_HEAD_USAGE_BOUNDS(i),
    227		  NVDEF(NVC57D, HEAD_SET_HEAD_USAGE_BOUNDS, CURSOR, USAGE_W256_H256) |
    228		  NVDEF(NVC57D, HEAD_SET_HEAD_USAGE_BOUNDS, OLUT_ALLOWED, TRUE) |
    229		  NVDEF(NVC57D, HEAD_SET_HEAD_USAGE_BOUNDS, OUTPUT_SCALER_TAPS, TAPS_2) |
    230		  NVDEF(NVC57D, HEAD_SET_HEAD_USAGE_BOUNDS, UPSCALING_ALLOWED, TRUE));
    231	return 0;
    232}
    233
    234const struct nv50_head_func
    235headc57d = {
    236	.view = headc37d_view,
    237	.mode = headc57d_mode,
    238	.olut = headc57d_olut,
    239	.ilut_check = head907d_ilut_check,
    240	.olut_identity = true,
    241	.olut_size = 1024,
    242	.olut_set = headc57d_olut_set,
    243	.olut_clr = headc57d_olut_clr,
    244	.curs_layout = head917d_curs_layout,
    245	.curs_format = headc37d_curs_format,
    246	.curs_set = headc37d_curs_set,
    247	.curs_clr = headc37d_curs_clr,
    248	.dither = headc37d_dither,
    249	.procamp = headc57d_procamp,
    250	.or = headc57d_or,
    251	/* TODO: flexible window mappings */
    252	.static_wndw_map = headc37d_static_wndw_map,
    253};