^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Manuel Jander.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Based on the work of:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Vojtech Pavlik
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Raymond Ingles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Should you need to contact me, the author, you can do so either by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Based 90% on Vojtech Pavlik pcigame driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Merged and modified by Manuel Jander, for the OpenVortex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * driver. (email: mjander@embedded.cl).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "au88x0.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/gameport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #if IS_REACHABLE(CONFIG_GAMEPORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define VORTEX_GAME_DWAIT 20 /* 20 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static unsigned char vortex_game_read(struct gameport *gameport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) vortex_t *vortex = gameport_get_port_data(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return hwread(vortex->mmio, VORTEX_GAME_LEGACY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static void vortex_game_trigger(struct gameport *gameport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) vortex_t *vortex = gameport_get_port_data(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) hwwrite(vortex->mmio, VORTEX_GAME_LEGACY, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) vortex_game_cooked_read(struct gameport *gameport, int *axes, int *buttons)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) vortex_t *vortex = gameport_get_port_data(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) *buttons = (~hwread(vortex->mmio, VORTEX_GAME_LEGACY) >> 4) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) axes[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) hwread(vortex->mmio, VORTEX_GAME_AXIS + (i * AXIS_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (axes[i] == AXIS_RANGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) axes[i] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static int vortex_game_open(struct gameport *gameport, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) vortex_t *vortex = gameport_get_port_data(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) case GAMEPORT_MODE_COOKED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) hwwrite(vortex->mmio, VORTEX_CTRL2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) hwread(vortex->mmio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) VORTEX_CTRL2) | CTRL2_GAME_ADCMODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) msleep(VORTEX_GAME_DWAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) case GAMEPORT_MODE_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) hwwrite(vortex->mmio, VORTEX_CTRL2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) hwread(vortex->mmio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) VORTEX_CTRL2) & ~CTRL2_GAME_ADCMODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static int vortex_gameport_register(vortex_t *vortex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct gameport *gp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) vortex->gameport = gp = gameport_allocate_port();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (!gp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) dev_err(vortex->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) "cannot allocate memory for gameport\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) gameport_set_name(gp, "AU88x0 Gameport");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) gameport_set_phys(gp, "pci%s/gameport0", pci_name(vortex->pci_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) gameport_set_dev_parent(gp, &vortex->pci_dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) gp->read = vortex_game_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) gp->trigger = vortex_game_trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) gp->cooked_read = vortex_game_cooked_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) gp->open = vortex_game_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) gameport_set_port_data(gp, vortex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) gp->fuzz = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) gameport_register_port(gp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static void vortex_gameport_unregister(vortex_t * vortex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (vortex->gameport) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) gameport_unregister_port(vortex->gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) vortex->gameport = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static inline int vortex_gameport_register(vortex_t * vortex) { return -ENOSYS; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static inline void vortex_gameport_unregister(vortex_t * vortex) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #endif