11f9ea1acSmacallan/* $NetBSD: hcrx_cursor.c,v 1.1 2025/12/22 13:07:11 macallan Exp $ */
21f9ea1acSmacallan/*
31f9ea1acSmacallan * Copyright (c) 2025 Michael Lorenz
41f9ea1acSmacallan * All rights reserved.
51f9ea1acSmacallan *
61f9ea1acSmacallan * Redistribution and use in source and binary forms, with or without
71f9ea1acSmacallan * modification, are permitted provided that the following conditions
81f9ea1acSmacallan * are met:
91f9ea1acSmacallan *
101f9ea1acSmacallan *    - Redistributions of source code must retain the above copyright
111f9ea1acSmacallan *      notice, this list of conditions and the following disclaimer.
121f9ea1acSmacallan *    - Redistributions in binary form must reproduce the above
131f9ea1acSmacallan *      copyright notice, this list of conditions and the following
141f9ea1acSmacallan *      disclaimer in the documentation and/or other materials provided
151f9ea1acSmacallan *      with the distribution.
161f9ea1acSmacallan *
171f9ea1acSmacallan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
181f9ea1acSmacallan * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
191f9ea1acSmacallan * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
201f9ea1acSmacallan * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
211f9ea1acSmacallan * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
221f9ea1acSmacallan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
231f9ea1acSmacallan * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
241f9ea1acSmacallan * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
251f9ea1acSmacallan * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
261f9ea1acSmacallan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
271f9ea1acSmacallan * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
281f9ea1acSmacallan * POSSIBILITY OF SUCH DAMAGE.
291f9ea1acSmacallan *
301f9ea1acSmacallan */
311f9ea1acSmacallan
321f9ea1acSmacallan#include <sys/types.h>
331f9ea1acSmacallan#include <dev/ic/nglereg.h>
341f9ea1acSmacallan#include "ngle.h"
351f9ea1acSmacallan
361f9ea1acSmacallanstatic void HCRXLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src);
371f9ea1acSmacallanstatic void HCRXSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
381f9ea1acSmacallanstatic void HCRXSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
391f9ea1acSmacallan
401f9ea1acSmacallanstatic void
411f9ea1acSmacallanHCRXLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
421f9ea1acSmacallan{
431f9ea1acSmacallan	NGLEPtr pNGLE = NGLEPTR(pScrn);
441f9ea1acSmacallan	uint32_t latch;
451f9ea1acSmacallan	int i;
461f9ea1acSmacallan
471f9ea1acSmacallan	/* image first */
481f9ea1acSmacallan	NGLEWrite4(pNGLE, NGLE_HCRX_CURSOR_ADDR, 0x80);
491f9ea1acSmacallan	for (i = 0; i < 128; i++) {
501f9ea1acSmacallan		memcpy(&latch, src, 4);
511f9ea1acSmacallan		NGLEWrite4(pNGLE, NGLE_HCRX_CURSOR_DATA, latch);
521f9ea1acSmacallan		src += 4;
531f9ea1acSmacallan	}
541f9ea1acSmacallan
551f9ea1acSmacallan	/* and now the mask */
561f9ea1acSmacallan	NGLEWrite4(pNGLE, NGLE_HCRX_CURSOR_ADDR, 0);
571f9ea1acSmacallan	for (i = 0; i < 128; i++) {
581f9ea1acSmacallan		memcpy(&latch, src, 4);
591f9ea1acSmacallan		NGLEWrite4(pNGLE, NGLE_HCRX_CURSOR_DATA, latch);
601f9ea1acSmacallan		src += 4;
611f9ea1acSmacallan	}
621f9ea1acSmacallan}
631f9ea1acSmacallan
641f9ea1acSmacallanvoid
651f9ea1acSmacallanHCRXShowCursor(ScrnInfoPtr pScrn)
661f9ea1acSmacallan{
671f9ea1acSmacallan	NGLEPtr pNGLE = NGLEPTR(pScrn);
681f9ea1acSmacallan
691f9ea1acSmacallan	pNGLE->cursor.enable = 1;
701f9ea1acSmacallan	NGLEWrite4(pNGLE, NGLE_HCRX_CURSOR, pNGLE->creg | HCRX_ENABLE_CURSOR);
711f9ea1acSmacallan}
721f9ea1acSmacallan
731f9ea1acSmacallanvoid
741f9ea1acSmacallanHCRXHideCursor(ScrnInfoPtr pScrn)
751f9ea1acSmacallan{
761f9ea1acSmacallan	NGLEPtr pNGLE = NGLEPTR(pScrn);
771f9ea1acSmacallan
781f9ea1acSmacallan	pNGLE->cursor.enable = 0;
791f9ea1acSmacallan	NGLEWrite4(pNGLE, NGLE_HCRX_CURSOR, pNGLE->creg);
801f9ea1acSmacallan}
811f9ea1acSmacallan
821f9ea1acSmacallanstatic void
831f9ea1acSmacallanHCRXSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
841f9ea1acSmacallan{
851f9ea1acSmacallan	NGLEPtr pNGLE = NGLEPTR(pScrn);
861f9ea1acSmacallan
871f9ea1acSmacallan	if (x < 0)
881f9ea1acSmacallan		x = 0x1000 - x;
891f9ea1acSmacallan	if (y < 0)
901f9ea1acSmacallan		y = 0x1000 - y;
911f9ea1acSmacallan	pNGLE->creg = (x << 16) | y;
921f9ea1acSmacallan	NGLEWrite4(pNGLE, NGLE_HCRX_CURSOR, pNGLE->creg |
931f9ea1acSmacallan	    (pNGLE->cursor.enable ? HCRX_ENABLE_CURSOR : 0));
941f9ea1acSmacallan}
951f9ea1acSmacallan
961f9ea1acSmacallanstatic void
971f9ea1acSmacallanHCRXSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
981f9ea1acSmacallan{
991f9ea1acSmacallan	NGLEPtr pNGLE = NGLEPTR(pScrn);
1001f9ea1acSmacallan	uint8_t stat;
1011f9ea1acSmacallan
1021f9ea1acSmacallan	do {
1031f9ea1acSmacallan		stat = NGLERead1(pNGLE, NGLE_BUSY);
1041f9ea1acSmacallan		if (stat == 0)
1051f9ea1acSmacallan			stat = NGLERead1(pNGLE, NGLE_BUSY);
1061f9ea1acSmacallan	} while (stat != 0);
1071f9ea1acSmacallan
1081f9ea1acSmacallan	NGLEWrite4(pNGLE, NGLE_BAboth,
1091f9ea1acSmacallan	  BA(FractDcd, Otc01, Ots08, Addr24, 0, BINcmap, 0));
1101f9ea1acSmacallan	NGLEWrite4(pNGLE, NGLE_IBO,
1111f9ea1acSmacallan	  IBOvals(RopSrc, 0, BitmapExtent08, 0, DataDynamic, MaskOtc, 0, 0));
1121f9ea1acSmacallan	NGLEWrite4(pNGLE, NGLE_PLANEMASK, 0xffffffff);
1131f9ea1acSmacallan	NGLEWrite4(pNGLE, NGLE_BINC_DST, 0);
1141f9ea1acSmacallan	NGLEWrite4(pNGLE, NGLE_BINC_DATA_R, bg);
1151f9ea1acSmacallan	NGLEWrite4(pNGLE, NGLE_BINC_DATA_R, fg);
1161f9ea1acSmacallan	NGLEWrite4(pNGLE, NGLE_BINC_SRC, 0);
1171f9ea1acSmacallan	NGLEWrite4(pNGLE, NGLE_HCRX_LUTBLT, LBC_ENABLE | LBC_TYPE_CURSOR | 4);
1181f9ea1acSmacallan	pNGLE->hwmode = -1;
1191f9ea1acSmacallan}
1201f9ea1acSmacallan
1211f9ea1acSmacallanBool
1221f9ea1acSmacallanHCRXSetupCursor(ScreenPtr pScreen)
1231f9ea1acSmacallan{
1241f9ea1acSmacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1251f9ea1acSmacallan	NGLEPtr pNGLE = NGLEPTR(pScrn);
1261f9ea1acSmacallan	xf86CursorInfoPtr infoPtr;
1271f9ea1acSmacallan
1281f9ea1acSmacallan	pNGLE->cursor.enable = 0;
1291f9ea1acSmacallan	pNGLE->creg = 0;
1301f9ea1acSmacallan
1311f9ea1acSmacallan	infoPtr = xf86CreateCursorInfoRec();
1321f9ea1acSmacallan	if(!infoPtr) return FALSE;
1331f9ea1acSmacallan
1341f9ea1acSmacallan	pNGLE->CursorInfoRec = infoPtr;
1351f9ea1acSmacallan
1361f9ea1acSmacallan	xf86Msg(X_INFO, "HCRX HW cursor enabled\n");
1371f9ea1acSmacallan
1381f9ea1acSmacallan	infoPtr->MaxWidth = 64;
1391f9ea1acSmacallan	infoPtr->MaxHeight = 64;
1401f9ea1acSmacallan	pNGLE->maskoffset = 8 * 64;
1411f9ea1acSmacallan
1421f9ea1acSmacallan	infoPtr->Flags = HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
1431f9ea1acSmacallan	    HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
1441f9ea1acSmacallan
1451f9ea1acSmacallan	infoPtr->SetCursorColors = HCRXSetCursorColors;
1461f9ea1acSmacallan	infoPtr->SetCursorPosition = HCRXSetCursorPosition;
1471f9ea1acSmacallan	infoPtr->LoadCursorImage = HCRXLoadCursorImage;
1481f9ea1acSmacallan	infoPtr->HideCursor = HCRXHideCursor;
1491f9ea1acSmacallan	infoPtr->ShowCursor = HCRXShowCursor;
1501f9ea1acSmacallan	infoPtr->UseHWCursor = NULL;
1511f9ea1acSmacallan
1521f9ea1acSmacallan	return xf86InitCursor(pScreen, infoPtr);
1531f9ea1acSmacallan}
154