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

head507d.c (14747B)


      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 "core.h"
     24
     25#include <nvif/push507c.h>
     26
     27#include <nvhw/class/cl507d.h>
     28
     29int
     30head507d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh)
     31{
     32	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
     33	const int i = head->base.index;
     34	int ret;
     35
     36	if ((ret = PUSH_WAIT(push, 2)))
     37		return ret;
     38
     39	PUSH_MTHD(push, NV507D, HEAD_SET_PROCAMP(i),
     40		  NVDEF(NV507D, HEAD_SET_PROCAMP, COLOR_SPACE, RGB) |
     41		  NVDEF(NV507D, HEAD_SET_PROCAMP, CHROMA_LPF, AUTO) |
     42		  NVVAL(NV507D, HEAD_SET_PROCAMP, SAT_COS, asyh->procamp.sat.cos) |
     43		  NVVAL(NV507D, HEAD_SET_PROCAMP, SAT_SINE, asyh->procamp.sat.sin) |
     44		  NVDEF(NV507D, HEAD_SET_PROCAMP, TRANSITION, HARD));
     45	return 0;
     46}
     47
     48int
     49head507d_dither(struct nv50_head *head, struct nv50_head_atom *asyh)
     50{
     51	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
     52	const int i = head->base.index;
     53	int ret;
     54
     55	if ((ret = PUSH_WAIT(push, 2)))
     56		return ret;
     57
     58	PUSH_MTHD(push, NV507D, HEAD_SET_DITHER_CONTROL(i),
     59		  NVVAL(NV507D, HEAD_SET_DITHER_CONTROL, ENABLE, asyh->dither.enable) |
     60		  NVVAL(NV507D, HEAD_SET_DITHER_CONTROL, BITS, asyh->dither.bits) |
     61		  NVVAL(NV507D, HEAD_SET_DITHER_CONTROL, MODE, asyh->dither.mode) |
     62		  NVVAL(NV507D, HEAD_SET_DITHER_CONTROL, PHASE, 0));
     63	return 0;
     64}
     65
     66int
     67head507d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh)
     68{
     69	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
     70	const int i = head->base.index;
     71	u32 bounds = 0;
     72	int ret;
     73
     74	if (asyh->ovly.cpp) {
     75		switch (asyh->ovly.cpp) {
     76		case 4: bounds |= NVDEF(NV507D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, PIXEL_DEPTH, BPP_32); break;
     77		case 2: bounds |= NVDEF(NV507D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, PIXEL_DEPTH, BPP_16); break;
     78		default:
     79			WARN_ON(1);
     80			break;
     81		}
     82		bounds |= NVDEF(NV507D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, USABLE, TRUE);
     83	} else {
     84		bounds |= NVDEF(NV507D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, PIXEL_DEPTH, BPP_16);
     85	}
     86
     87	if ((ret = PUSH_WAIT(push, 2)))
     88		return ret;
     89
     90	PUSH_MTHD(push, NV507D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS(i), bounds);
     91	return 0;
     92}
     93
     94int
     95head507d_base(struct nv50_head *head, struct nv50_head_atom *asyh)
     96{
     97	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
     98	const int i = head->base.index;
     99	u32 bounds = 0;
    100	int ret;
    101
    102	if (asyh->base.cpp) {
    103		switch (asyh->base.cpp) {
    104		case 8: bounds |= NVDEF(NV507D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, PIXEL_DEPTH, BPP_64); break;
    105		case 4: bounds |= NVDEF(NV507D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, PIXEL_DEPTH, BPP_32); break;
    106		case 2: bounds |= NVDEF(NV507D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, PIXEL_DEPTH, BPP_16); break;
    107		case 1: bounds |= NVDEF(NV507D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, PIXEL_DEPTH, BPP_8); break;
    108		default:
    109			WARN_ON(1);
    110			break;
    111		}
    112		bounds |= NVDEF(NV507D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, USABLE, TRUE);
    113	}
    114
    115	if ((ret = PUSH_WAIT(push, 2)))
    116		return ret;
    117
    118	PUSH_MTHD(push, NV507D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS(i), bounds);
    119	return 0;
    120}
    121
    122static int
    123head507d_curs_clr(struct nv50_head *head)
    124{
    125	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
    126	const int i = head->base.index;
    127	int ret;
    128
    129	if ((ret = PUSH_WAIT(push, 2)))
    130		return ret;
    131
    132	PUSH_MTHD(push, NV507D, HEAD_SET_CONTROL_CURSOR(i),
    133		  NVDEF(NV507D, HEAD_SET_CONTROL_CURSOR, ENABLE, DISABLE) |
    134		  NVDEF(NV507D, HEAD_SET_CONTROL_CURSOR, FORMAT, A8R8G8B8) |
    135		  NVDEF(NV507D, HEAD_SET_CONTROL_CURSOR, SIZE, W64_H64));
    136	return 0;
    137}
    138
    139static int
    140head507d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh)
    141{
    142	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
    143	const int i = head->base.index;
    144	int ret;
    145
    146	if ((ret = PUSH_WAIT(push, 3)))
    147		return ret;
    148
    149	PUSH_MTHD(push, NV507D, HEAD_SET_CONTROL_CURSOR(i),
    150		  NVDEF(NV507D, HEAD_SET_CONTROL_CURSOR, ENABLE, ENABLE) |
    151		  NVVAL(NV507D, HEAD_SET_CONTROL_CURSOR, FORMAT, asyh->curs.format) |
    152		  NVVAL(NV507D, HEAD_SET_CONTROL_CURSOR, SIZE, asyh->curs.layout) |
    153		  NVVAL(NV507D, HEAD_SET_CONTROL_CURSOR, HOT_SPOT_X, 0) |
    154		  NVVAL(NV507D, HEAD_SET_CONTROL_CURSOR, HOT_SPOT_Y, 0) |
    155		  NVDEF(NV507D, HEAD_SET_CONTROL_CURSOR, COMPOSITION, ALPHA_BLEND) |
    156		  NVDEF(NV507D, HEAD_SET_CONTROL_CURSOR, SUB_OWNER, NONE),
    157
    158				HEAD_SET_OFFSET_CURSOR(i), asyh->curs.offset >> 8);
    159	return 0;
    160}
    161
    162int
    163head507d_curs_format(struct nv50_head *head, struct nv50_wndw_atom *asyw,
    164		     struct nv50_head_atom *asyh)
    165{
    166	switch (asyw->image.format) {
    167	case 0xcf: asyh->curs.format = NV507D_HEAD_SET_CONTROL_CURSOR_FORMAT_A8R8G8B8; break;
    168	default:
    169		WARN_ON(1);
    170		return -EINVAL;
    171	}
    172	return 0;
    173}
    174
    175int
    176head507d_curs_layout(struct nv50_head *head, struct nv50_wndw_atom *asyw,
    177		     struct nv50_head_atom *asyh)
    178{
    179	switch (asyw->image.w) {
    180	case 32: asyh->curs.layout = NV507D_HEAD_SET_CONTROL_CURSOR_SIZE_W32_H32; break;
    181	case 64: asyh->curs.layout = NV507D_HEAD_SET_CONTROL_CURSOR_SIZE_W64_H64; break;
    182	default:
    183		return -EINVAL;
    184	}
    185	return 0;
    186}
    187
    188int
    189head507d_core_clr(struct nv50_head *head)
    190{
    191	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
    192	const int i = head->base.index;
    193	int ret;
    194
    195	if ((ret = PUSH_WAIT(push, 2)))
    196		return ret;
    197
    198	PUSH_MTHD(push, NV507D, HEAD_SET_CONTEXT_DMA_ISO(i), 0x00000000);
    199	return 0;
    200}
    201
    202static int
    203head507d_core_set(struct nv50_head *head, struct nv50_head_atom *asyh)
    204{
    205	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
    206	const int i = head->base.index;
    207	int ret;
    208
    209	if ((ret = PUSH_WAIT(push, 9)))
    210		return ret;
    211
    212	PUSH_MTHD(push, NV507D, HEAD_SET_OFFSET(i, 0),
    213		  NVVAL(NV507D, HEAD_SET_OFFSET, ORIGIN, asyh->core.offset >> 8));
    214
    215	PUSH_MTHD(push, NV507D, HEAD_SET_SIZE(i),
    216		  NVVAL(NV507D, HEAD_SET_SIZE, WIDTH, asyh->core.w) |
    217		  NVVAL(NV507D, HEAD_SET_SIZE, HEIGHT, asyh->core.h),
    218
    219				HEAD_SET_STORAGE(i),
    220		  NVVAL(NV507D, HEAD_SET_STORAGE, BLOCK_HEIGHT, asyh->core.blockh) |
    221		  NVVAL(NV507D, HEAD_SET_STORAGE, PITCH, asyh->core.pitch >> 8) |
    222		  NVVAL(NV507D, HEAD_SET_STORAGE, PITCH, asyh->core.blocks) |
    223		  NVVAL(NV507D, HEAD_SET_STORAGE, MEMORY_LAYOUT, asyh->core.layout),
    224
    225				HEAD_SET_PARAMS(i),
    226		  NVVAL(NV507D, HEAD_SET_PARAMS, FORMAT, asyh->core.format) |
    227		  NVVAL(NV507D, HEAD_SET_PARAMS, KIND, asyh->core.kind) |
    228		  NVDEF(NV507D, HEAD_SET_PARAMS, PART_STRIDE, PARTSTRIDE_256),
    229
    230				HEAD_SET_CONTEXT_DMA_ISO(i),
    231		  NVVAL(NV507D, HEAD_SET_CONTEXT_DMA_ISO, HANDLE, asyh->core.handle));
    232
    233	PUSH_MTHD(push, NV507D, HEAD_SET_VIEWPORT_POINT_IN(i, 0),
    234		  NVVAL(NV507D, HEAD_SET_VIEWPORT_POINT_IN, X, asyh->core.x) |
    235		  NVVAL(NV507D, HEAD_SET_VIEWPORT_POINT_IN, Y, asyh->core.y));
    236
    237	/* EVO will complain with INVALID_STATE if we have an
    238	 * active cursor and (re)specify HeadSetContextDmaIso
    239	 * without also updating HeadSetOffsetCursor.
    240	 */
    241	asyh->set.curs = asyh->curs.visible;
    242	asyh->set.olut = asyh->olut.handle != 0;
    243	return 0;
    244}
    245
    246void
    247head507d_core_calc(struct nv50_head *head, struct nv50_head_atom *asyh)
    248{
    249	struct nv50_disp *disp = nv50_disp(head->base.base.dev);
    250	if ((asyh->core.visible = (asyh->base.cpp != 0))) {
    251		asyh->core.x = asyh->base.x;
    252		asyh->core.y = asyh->base.y;
    253		asyh->core.w = asyh->base.w;
    254		asyh->core.h = asyh->base.h;
    255	} else
    256	if ((asyh->core.visible = (asyh->ovly.cpp != 0)) ||
    257	    (asyh->core.visible = asyh->curs.visible)) {
    258		/*XXX: We need to either find some way of having the
    259		 *     primary base layer appear black, while still
    260		 *     being able to display the other layers, or we
    261		 *     need to allocate a dummy black surface here.
    262		 */
    263		asyh->core.x = 0;
    264		asyh->core.y = 0;
    265		asyh->core.w = asyh->state.mode.hdisplay;
    266		asyh->core.h = asyh->state.mode.vdisplay;
    267	}
    268	asyh->core.handle = disp->core->chan.vram.handle;
    269	asyh->core.offset = 0;
    270	asyh->core.format = NV507D_HEAD_SET_PARAMS_FORMAT_A8R8G8B8;
    271	asyh->core.kind = NV507D_HEAD_SET_PARAMS_KIND_KIND_PITCH;
    272	asyh->core.layout = NV507D_HEAD_SET_STORAGE_MEMORY_LAYOUT_PITCH;
    273	asyh->core.blockh = NV507D_HEAD_SET_STORAGE_BLOCK_HEIGHT_ONE_GOB;
    274	asyh->core.blocks = 0;
    275	asyh->core.pitch = ALIGN(asyh->core.w, 64) * 4;
    276}
    277
    278static int
    279head507d_olut_clr(struct nv50_head *head)
    280{
    281	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
    282	const int i = head->base.index;
    283	int ret;
    284
    285	if ((ret = PUSH_WAIT(push, 2)))
    286		return ret;
    287
    288	PUSH_MTHD(push, NV507D, HEAD_SET_BASE_LUT_LO(i),
    289		  NVDEF(NV507D, HEAD_SET_BASE_LUT_LO, ENABLE, DISABLE));
    290	return 0;
    291}
    292
    293static int
    294head507d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
    295{
    296	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
    297	const int i = head->base.index;
    298	int ret;
    299
    300	if ((ret = PUSH_WAIT(push, 3)))
    301		return ret;
    302
    303	PUSH_MTHD(push, NV507D, HEAD_SET_BASE_LUT_LO(i),
    304		  NVDEF(NV507D, HEAD_SET_BASE_LUT_LO, ENABLE, ENABLE) |
    305		  NVVAL(NV507D, HEAD_SET_BASE_LUT_LO, MODE, asyh->olut.mode) |
    306		  NVVAL(NV507D, HEAD_SET_BASE_LUT_LO, ORIGIN, 0),
    307
    308				HEAD_SET_BASE_LUT_HI(i),
    309		  NVVAL(NV507D, HEAD_SET_BASE_LUT_HI, ORIGIN, asyh->olut.offset >> 8));
    310	return 0;
    311}
    312
    313static void
    314head507d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem)
    315{
    316	for (; size--; in++, mem += 8) {
    317		writew(drm_color_lut_extract(in->  red, 11) << 3, mem + 0);
    318		writew(drm_color_lut_extract(in->green, 11) << 3, mem + 2);
    319		writew(drm_color_lut_extract(in-> blue, 11) << 3, mem + 4);
    320	}
    321
    322	/* INTERPOLATE modes require a "next" entry to interpolate with,
    323	 * so we replicate the last entry to deal with this for now.
    324	 */
    325	writew(readw(mem - 8), mem + 0);
    326	writew(readw(mem - 6), mem + 2);
    327	writew(readw(mem - 4), mem + 4);
    328}
    329
    330bool
    331head507d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size)
    332{
    333	if (size != 256)
    334		return false;
    335
    336	if (asyh->base.cpp == 1)
    337		asyh->olut.mode = NV507D_HEAD_SET_BASE_LUT_LO_MODE_LORES;
    338	else
    339		asyh->olut.mode = NV507D_HEAD_SET_BASE_LUT_LO_MODE_HIRES;
    340
    341	asyh->olut.load = head507d_olut_load;
    342	return true;
    343}
    344
    345int
    346head507d_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
    347{
    348	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
    349	struct nv50_head_mode *m = &asyh->mode;
    350	const int i = head->base.index;
    351	int ret;
    352
    353	if ((ret = PUSH_WAIT(push, 13)))
    354		return ret;
    355
    356	PUSH_MTHD(push, NV507D, HEAD_SET_PIXEL_CLOCK(i),
    357		  NVVAL(NV507D, HEAD_SET_PIXEL_CLOCK, FREQUENCY, m->clock) |
    358		  NVDEF(NV507D, HEAD_SET_PIXEL_CLOCK, MODE, CLK_CUSTOM) |
    359		  NVDEF(NV507D, HEAD_SET_PIXEL_CLOCK, ADJ1000DIV1001, FALSE) |
    360		  NVDEF(NV507D, HEAD_SET_PIXEL_CLOCK, NOT_DRIVER, FALSE),
    361
    362				HEAD_SET_CONTROL(i),
    363		  NVVAL(NV507D, HEAD_SET_CONTROL, STRUCTURE, m->interlace));
    364
    365	PUSH_MTHD(push, NV507D, HEAD_SET_OVERSCAN_COLOR(i),
    366		  NVVAL(NV507D, HEAD_SET_OVERSCAN_COLOR, RED, 0) |
    367		  NVVAL(NV507D, HEAD_SET_OVERSCAN_COLOR, GRN, 0) |
    368		  NVVAL(NV507D, HEAD_SET_OVERSCAN_COLOR, BLU, 0),
    369
    370				HEAD_SET_RASTER_SIZE(i),
    371		  NVVAL(NV507D, HEAD_SET_RASTER_SIZE, WIDTH, m->h.active) |
    372		  NVVAL(NV507D, HEAD_SET_RASTER_SIZE, HEIGHT, m->v.active),
    373
    374				HEAD_SET_RASTER_SYNC_END(i),
    375		  NVVAL(NV507D, HEAD_SET_RASTER_SYNC_END, X, m->h.synce) |
    376		  NVVAL(NV507D, HEAD_SET_RASTER_SYNC_END, Y, m->v.synce),
    377
    378				HEAD_SET_RASTER_BLANK_END(i),
    379		  NVVAL(NV507D, HEAD_SET_RASTER_BLANK_END, X, m->h.blanke) |
    380		  NVVAL(NV507D, HEAD_SET_RASTER_BLANK_END, Y, m->v.blanke),
    381
    382				HEAD_SET_RASTER_BLANK_START(i),
    383		  NVVAL(NV507D, HEAD_SET_RASTER_BLANK_START, X, m->h.blanks) |
    384		  NVVAL(NV507D, HEAD_SET_RASTER_BLANK_START, Y, m->v.blanks),
    385
    386				HEAD_SET_RASTER_VERT_BLANK2(i),
    387		  NVVAL(NV507D, HEAD_SET_RASTER_VERT_BLANK2, YSTART, m->v.blank2s) |
    388		  NVVAL(NV507D, HEAD_SET_RASTER_VERT_BLANK2, YEND, m->v.blank2e),
    389
    390				HEAD_SET_RASTER_VERT_BLANK_DMI(i),
    391		  NVVAL(NV507D, HEAD_SET_RASTER_VERT_BLANK_DMI, DURATION, m->v.blankus));
    392
    393	PUSH_MTHD(push, NV507D, HEAD_SET_DEFAULT_BASE_COLOR(i),
    394		  NVVAL(NV507D, HEAD_SET_DEFAULT_BASE_COLOR, RED, 0) |
    395		  NVVAL(NV507D, HEAD_SET_DEFAULT_BASE_COLOR, GREEN, 0) |
    396		  NVVAL(NV507D, HEAD_SET_DEFAULT_BASE_COLOR, BLUE, 0));
    397	return 0;
    398}
    399
    400int
    401head507d_view(struct nv50_head *head, struct nv50_head_atom *asyh)
    402{
    403	struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
    404	const int i = head->base.index;
    405	int ret;
    406
    407	if ((ret = PUSH_WAIT(push, 7)))
    408		return ret;
    409
    410	PUSH_MTHD(push, NV507D, HEAD_SET_CONTROL_OUTPUT_SCALER(i),
    411		  NVDEF(NV507D, HEAD_SET_CONTROL_OUTPUT_SCALER, VERTICAL_TAPS, TAPS_1) |
    412		  NVDEF(NV507D, HEAD_SET_CONTROL_OUTPUT_SCALER, HORIZONTAL_TAPS, TAPS_1) |
    413		  NVVAL(NV507D, HEAD_SET_CONTROL_OUTPUT_SCALER, HRESPONSE_BIAS, 0) |
    414		  NVVAL(NV507D, HEAD_SET_CONTROL_OUTPUT_SCALER, VRESPONSE_BIAS, 0));
    415
    416	PUSH_MTHD(push, NV507D, HEAD_SET_VIEWPORT_SIZE_IN(i),
    417		  NVVAL(NV507D, HEAD_SET_VIEWPORT_SIZE_IN, WIDTH, asyh->view.iW) |
    418		  NVVAL(NV507D, HEAD_SET_VIEWPORT_SIZE_IN, HEIGHT, asyh->view.iH));
    419
    420	PUSH_MTHD(push, NV507D, HEAD_SET_VIEWPORT_SIZE_OUT(i),
    421		  NVVAL(NV507D, HEAD_SET_VIEWPORT_SIZE_OUT, WIDTH, asyh->view.oW) |
    422		  NVVAL(NV507D, HEAD_SET_VIEWPORT_SIZE_OUT, HEIGHT, asyh->view.oH),
    423
    424				HEAD_SET_VIEWPORT_SIZE_OUT_MIN(i),
    425		  NVVAL(NV507D, HEAD_SET_VIEWPORT_SIZE_OUT_MIN, WIDTH, asyh->view.oW) |
    426		  NVVAL(NV507D, HEAD_SET_VIEWPORT_SIZE_OUT_MIN, HEIGHT, asyh->view.oH));
    427	return 0;
    428}
    429
    430const struct nv50_head_func
    431head507d = {
    432	.view = head507d_view,
    433	.mode = head507d_mode,
    434	.olut = head507d_olut,
    435	.olut_size = 256,
    436	.olut_set = head507d_olut_set,
    437	.olut_clr = head507d_olut_clr,
    438	.core_calc = head507d_core_calc,
    439	.core_set = head507d_core_set,
    440	.core_clr = head507d_core_clr,
    441	.curs_layout = head507d_curs_layout,
    442	.curs_format = head507d_curs_format,
    443	.curs_set = head507d_curs_set,
    444	.curs_clr = head507d_curs_clr,
    445	.base = head507d_base,
    446	.ovly = head507d_ovly,
    447	.dither = head507d_dither,
    448	.procamp = head507d_procamp,
    449};