Home | History | Annotate | Line # | Download | only in dev
      1 /*	$NetBSD: j720tp.c,v 1.15 2023/12/20 14:50:02 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2006 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by IWAMOTO Toshihiro and Peter Postma.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 /* Jornada 720 touch-panel driver. */
     33 
     34 #include <sys/cdefs.h>
     35 __KERNEL_RCSID(0, "$NetBSD: j720tp.c,v 1.15 2023/12/20 14:50:02 thorpej Exp $");
     36 
     37 #ifdef _KERNEL_OPT
     38 #include "opt_j720tp.h"
     39 #include "opt_wsdisplay_compat.h"
     40 #endif
     41 
     42 #include <sys/param.h>
     43 #include <sys/systm.h>
     44 #include <sys/device.h>
     45 #include <sys/kernel.h>
     46 #include <sys/ioctl.h>
     47 #include <sys/callout.h>
     48 #include <sys/sysctl.h>
     49 
     50 #include <machine/platid.h>
     51 #include <machine/platid_mask.h>
     52 
     53 #include <arm/sa11x0/sa11x0_var.h>
     54 #include <arm/sa11x0/sa11x0_gpioreg.h>
     55 #include <arm/sa11x0/sa11x0_ppcreg.h>
     56 #include <arm/sa11x0/sa11x0_sspreg.h>
     57 
     58 #include <dev/wscons/wsconsio.h>
     59 #include <dev/wscons/wsmousevar.h>
     60 #include <dev/wscons/wskbdvar.h>
     61 #include <dev/wscons/wsksymvar.h>
     62 #include <dev/wscons/wsksymdef.h>
     63 #include <dev/hpc/hpctpanelvar.h>
     64 
     65 #include <hpcarm/dev/j720sspvar.h>
     66 
     67 #ifdef WSDISPLAY_COMPAT_RAWKBD
     68 #include <dev/hpc/pckbd_encode.h>
     69 #endif
     70 
     71 #define arraysize(ary)	(sizeof(ary) / sizeof(ary[0]))
     72 
     73 #ifdef J720TP_DEBUG
     74 int j720tp_debug = 0;
     75 #define DPRINTF(arg)		if (j720tp_debug) aprint_normal arg
     76 #define DPRINTFN(n, arg)	if (j720tp_debug >= (n)) aprint_normal arg
     77 #else
     78 #define DPRINTF(arg)		/* nothing */
     79 #define DPRINTFN(n, arg)	/* nothing */
     80 #endif
     81 
     82 struct j720tp_softc {
     83 	device_t		sc_dev;
     84 
     85 #define J720TP_WSMOUSE_ENABLED	0x01
     86 #define J720TP_WSKBD_ENABLED	0x02
     87 	int			sc_enabled;
     88 	int			sc_hard_icon;
     89 #ifdef WSDISPLAY_COMPAT_RAWKBD
     90 	int			sc_rawkbd;
     91 #endif
     92 
     93 	struct callout		sc_tpcallout;
     94 	struct j720ssp_softc	*sc_ssp;
     95 
     96 	device_t		sc_wsmousedev;
     97 	device_t		sc_wskbddev;
     98 
     99 	struct tpcalib_softc	sc_tpcalib;
    100 };
    101 
    102 static int	j720tp_match(device_t, cfdata_t, void *);
    103 static void	j720tp_attach(device_t, device_t, void *);
    104 
    105 static int	j720tp_wsmouse_enable(void *);
    106 static int	j720tp_wsmouse_ioctl(void *, u_long, void *, int,
    107 			struct lwp *);
    108 static void	j720tp_wsmouse_disable(void *);
    109 
    110 static int	j720tp_wskbd_enable(void *, int);
    111 static void	j720tp_wskbd_set_leds(void *, int);
    112 static int	j720tp_wskbd_ioctl(void *, u_long, void *, int, struct lwp *);
    113 
    114 static void	j720tp_enable_intr(struct j720tp_softc *);
    115 static void	j720tp_disable_intr(struct j720tp_softc *);
    116 static int	j720tp_intr(void *);
    117 static int	j720tp_get_rawxy(struct j720tp_softc *, int *, int *);
    118 static int	j720tp_get_hard_icon(struct j720tp_softc *, int, int);
    119 static void	j720tp_wsmouse_input(struct j720tp_softc *, int, int);
    120 static void	j720tp_wsmouse_callout(void *);
    121 static void	j720tp_wskbd_input(struct j720tp_softc *, u_int);
    122 static void	j720tp_wskbd_callout(void *);
    123 
    124 const struct wsmouse_accessops j720tp_wsmouse_accessops = {
    125 	j720tp_wsmouse_enable,
    126 	j720tp_wsmouse_ioctl,
    127 	j720tp_wsmouse_disable
    128 };
    129 
    130 static const struct wsmouse_calibcoords j720tp_default_calib = {
    131 	0, 0, 639, 239,
    132 	4,
    133 	{{ 988,  80,   0,   0 },
    134 	 {  88,  84, 639,   0 },
    135 	 { 988, 927,   0, 239 },
    136 	 {  88, 940, 639, 239 }}
    137 };
    138 
    139 const struct wskbd_accessops j720tp_wskbd_accessops = {
    140 	j720tp_wskbd_enable,
    141 	j720tp_wskbd_set_leds,
    142 	j720tp_wskbd_ioctl
    143 };
    144 
    145 #ifndef J720TP_SETTINGS_ICON_KEYSYM
    146 #define J720TP_SETTINGS_ICON_KEYSYM	KS_Home
    147 #endif
    148 #ifndef J720TP_BACKUP_ICON_KEYSYM
    149 #define J720TP_BACKUP_ICON_KEYSYM	KS_Prior
    150 #endif
    151 #ifndef J720TP_DIALUP_ICON_KEYSYM
    152 #define J720TP_DIALUP_ICON_KEYSYM	KS_Next
    153 #endif
    154 #ifndef J720TP_MEDIA_ICON_KEYSYM
    155 #define J720TP_MEDIA_ICON_KEYSYM	KS_End
    156 #endif
    157 
    158 /* Max Y value of the n'th hard icon. */
    159 #define J720TP_HARD_ICON_MAX_Y(n) \
    160 	(((j720tp_hard_icon_bottom - j720tp_hard_icon_top) / 4) * (n)) + \
    161 	j720tp_hard_icon_top
    162 
    163 /* Default raw X/Y values of the hard icon area. */
    164 static int j720tp_hard_icon_left = 70;
    165 static int j720tp_hard_icon_right = 20;
    166 static int j720tp_hard_icon_top = 70;
    167 static int j720tp_hard_icon_bottom = 940;
    168 
    169 /* Maps the icon number to a raw keycode. */
    170 static const int j720tp_wskbd_keys[] = {
    171 	/* Icon 1 */ 199,
    172 	/* Icon 2 */ 201,
    173 	/* Icon 3 */ 209,
    174 	/* Icon 4 */ 207
    175 };
    176 
    177 static const keysym_t j720tp_wskbd_keydesc[] = {
    178 	KS_KEYCODE(199), J720TP_SETTINGS_ICON_KEYSYM,
    179 	KS_KEYCODE(201), J720TP_BACKUP_ICON_KEYSYM,
    180 	KS_KEYCODE(209), J720TP_DIALUP_ICON_KEYSYM,
    181 	KS_KEYCODE(207), J720TP_MEDIA_ICON_KEYSYM
    182 };
    183 
    184 const struct wscons_keydesc j720tp_wskbd_keydesctab[] = {
    185 	{ KB_US, 0,
    186 	  sizeof(j720tp_wskbd_keydesc) / sizeof(keysym_t),
    187 	  j720tp_wskbd_keydesc
    188 	},
    189 	{ 0, 0, 0, 0 }
    190 };
    191 
    192 const struct wskbd_mapdata j720tp_wskbd_keymapdata = {
    193 	j720tp_wskbd_keydesctab, KB_US
    194 };
    195 
    196 CFATTACH_DECL_NEW(j720tp, sizeof(struct j720tp_softc),
    197     j720tp_match, j720tp_attach, NULL, NULL);
    198 
    199 
    200 static int
    201 j720tp_match(device_t parent, cfdata_t cf, void *aux)
    202 {
    203 
    204 	if (!platid_match(&platid, &platid_mask_MACH_HP_JORNADA_7XX))
    205 		return 0;
    206 	if (strcmp(cf->cf_name, "j720tp") != 0)
    207 		return 0;
    208 
    209 	return 1;
    210 }
    211 
    212 static void
    213 j720tp_attach(device_t parent, device_t self, void *aux)
    214 {
    215 	struct j720tp_softc *sc = device_private(self);
    216 	struct wsmousedev_attach_args wsma;
    217 	struct wskbddev_attach_args wska;
    218 
    219 	aprint_normal("\n");
    220 
    221 	sc->sc_dev = self;
    222 	sc->sc_ssp = device_private(parent);
    223 	sc->sc_enabled = 0;
    224 	sc->sc_hard_icon = 0;
    225 #ifdef WSDISPLAY_COMPAT_RAWKBD
    226 	sc->sc_rawkbd = 0;
    227 #endif
    228 
    229 	/* Touch-panel as a pointing device. */
    230 	wsma.accessops = &j720tp_wsmouse_accessops;
    231 	wsma.accesscookie = sc;
    232 
    233 	sc->sc_wsmousedev = config_found(self, &wsma, wsmousedevprint,
    234 	    CFARGS(.iattr = "wsmousedev"));
    235 	if (sc->sc_wsmousedev == NULL)
    236 		return;
    237 
    238 	/* Initialize calibration, set default parameters. */
    239 	tpcalib_init(&sc->sc_tpcalib);
    240 	tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
    241 	    __UNCONST(&j720tp_default_calib), 0, 0);
    242 
    243 	callout_init(&sc->sc_tpcallout, 0);
    244 
    245 	j720tp_wsmouse_disable(sc);
    246 
    247 	/* On-screen "hard icons" as a keyboard device. */
    248 	wska.console = 0;
    249 	wska.keymap = &j720tp_wskbd_keymapdata;
    250 	wska.accessops = &j720tp_wskbd_accessops;
    251 	wska.accesscookie = sc;
    252 
    253 	sc->sc_wskbddev = config_found(self, &wska, wskbddevprint,
    254 	    CFARGS(.iattr = "wskbddev"));
    255 
    256 	/* Setup touch-panel interrupt. */
    257 	sa11x0_intr_establish(0, 9, 1, IPL_TTY, j720tp_intr, sc);
    258 }
    259 
    260 static int
    261 j720tp_wsmouse_enable(void *self)
    262 {
    263 	struct j720tp_softc *sc = self;
    264 	int s;
    265 
    266 	s = spltty();
    267 
    268 	j720tp_enable_intr(sc);
    269 
    270 	sc->sc_enabled |= J720TP_WSMOUSE_ENABLED;
    271 
    272 	splx(s);
    273 	return 0;
    274 }
    275 
    276 static int
    277 j720tp_wsmouse_ioctl(void *self, u_long cmd, void *data, int flag,
    278     struct lwp *l)
    279 {
    280 	struct j720tp_softc *sc = self;
    281 
    282 	return hpc_tpanel_ioctl(&sc->sc_tpcalib, cmd, data, flag, l);
    283 }
    284 
    285 static void
    286 j720tp_wsmouse_disable(void *self)
    287 {
    288 	struct j720tp_softc *sc = self;
    289 	int s;
    290 
    291 	s = spltty();
    292 
    293 	j720tp_disable_intr(sc);
    294 	callout_stop(&sc->sc_tpcallout);
    295 
    296 	sc->sc_enabled &= ~J720TP_WSMOUSE_ENABLED;
    297 
    298 	splx(s);
    299 }
    300 
    301 static int
    302 j720tp_wskbd_enable(void *self, int on)
    303 {
    304 	struct j720tp_softc *sc = self;
    305 	int s;
    306 
    307 	s = spltty();
    308 	sc->sc_enabled |= J720TP_WSKBD_ENABLED;
    309 	splx(s);
    310 
    311 	return 0;
    312 }
    313 
    314 static void
    315 j720tp_wskbd_set_leds(void *self, int leds)
    316 {
    317 	/* nothing to do */
    318 }
    319 
    320 static int
    321 j720tp_wskbd_ioctl(void *self, u_long cmd, void *data, int flag,
    322     struct lwp *l)
    323 {
    324 #ifdef WSDISPLAY_COMPAT_RAWKBD
    325 	struct j720tp_softc *sc = self;
    326 #endif
    327 
    328 	switch (cmd) {
    329 	case WSKBDIO_GTYPE:
    330 		*(int *)data = WSKBD_TYPE_HPC_BTN;
    331 		return 0;
    332 	case WSKBDIO_GETLEDS:
    333 		*(int *)data = 0;
    334 		return 0;
    335 #ifdef WSDISPLAY_COMPAT_RAWKBD
    336 	case WSKBDIO_SETMODE:
    337 		sc->sc_rawkbd = (*(int *)data == WSKBD_RAW);
    338 		return 0;
    339 #endif
    340 	}
    341 
    342 	return EPASSTHROUGH;
    343 }
    344 
    345 /*
    346  * Enable touch-panel interrupt.  Must be called at spltty().
    347  */
    348 static void
    349 j720tp_enable_intr(struct j720tp_softc *sc)
    350 {
    351 	struct j720ssp_softc *ssp = sc->sc_ssp;
    352 	uint32_t er;
    353 
    354 	er = bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER);
    355 	er |= 1 << 9;
    356 	bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER, er);
    357 }
    358 
    359 /*
    360  * Disable touch-panel interrupt.  Must be called at spltty().
    361  */
    362 static void
    363 j720tp_disable_intr(struct j720tp_softc *sc)
    364 {
    365 	struct j720ssp_softc *ssp = sc->sc_ssp;
    366 	uint32_t er;
    367 
    368 	er = bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER);
    369 	er &= ~(1 << 9);
    370 	bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_FER, er);
    371 }
    372 
    373 static int
    374 j720tp_intr(void *arg)
    375 {
    376 	struct j720tp_softc *sc = arg;
    377 	struct j720ssp_softc *ssp = sc->sc_ssp;
    378 	int rawx, rawy;
    379 
    380 	bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_EDR, 1 << 9);
    381 
    382 	if (!(sc->sc_enabled & J720TP_WSMOUSE_ENABLED)) {
    383 		DPRINTF(("j720tp_intr: !sc_enabled\n"));
    384 		return 0;
    385 	}
    386 
    387 	j720tp_disable_intr(sc);
    388 
    389 	if (j720tp_get_rawxy(sc, &rawx, &rawy)) {
    390 		sc->sc_hard_icon = j720tp_get_hard_icon(sc, rawx, rawy);
    391 
    392 		if (sc->sc_hard_icon > 0) {
    393 			j720tp_wskbd_input(sc, WSCONS_EVENT_KEY_DOWN);
    394 			callout_reset(&sc->sc_tpcallout, hz / 32,
    395 			    j720tp_wskbd_callout, sc);
    396 		} else {
    397 			j720tp_wsmouse_input(sc, rawx, rawy);
    398 			callout_reset(&sc->sc_tpcallout, hz / 32,
    399 			    j720tp_wsmouse_callout, sc);
    400 		}
    401 	}
    402 
    403 	return 1;
    404 }
    405 
    406 static int
    407 j720tp_get_rawxy(struct j720tp_softc *sc, int *rawx, int *rawy)
    408 {
    409 	struct j720ssp_softc *ssp = sc->sc_ssp;
    410 	int buf[8], data, i;
    411 
    412 	bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PCR, 0x2000000);
    413 
    414 	/* Send read touch-panel command. */
    415 	if (j720ssp_readwrite(ssp, 1, 0xa0, &data, 100) < 0 || data != 0x11) {
    416 		DPRINTF(("j720tp_get_rawxy: no dummy received\n"));
    417 		goto out;
    418 	}
    419 
    420 	for (i = 0; i < 8; i++) {
    421 		if (j720ssp_readwrite(ssp, 0, 0x11, &data, 100) < 0)
    422 			goto out;
    423 		buf[i] = data;
    424 	}
    425 
    426 	bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PSR, 0x2000000);
    427 
    428 	buf[6] <<= 8;
    429 	buf[7] <<= 8;
    430 	for (i = 0; i < 3; i++) {
    431 		buf[i] |= buf[6] & 0x300;
    432 		buf[6] >>= 2;
    433 		buf[i + 3] |= buf[7] & 0x300;
    434 		buf[7] >>= 2;
    435 	}
    436 
    437 	DPRINTFN(2, ("j720tp_get_rawxy: %d:%d:%d:%d:%d:%d:%d:%d\n",
    438 	    buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]));
    439 
    440 	*rawx = buf[1];
    441 	*rawy = buf[4];
    442 
    443 	return 1;
    444 out:
    445 	bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PSR, 0x2000000);
    446 
    447 	/* reset SSP */
    448 	bus_space_write_4(ssp->sc_iot, ssp->sc_ssph, SASSP_CR0, 0x307);
    449 	delay(100);
    450 	bus_space_write_4(ssp->sc_iot, ssp->sc_ssph, SASSP_CR0, 0x387);
    451 
    452 	DPRINTF(("j720tp_get_rawxy: error %x\n", data));
    453 	return 0;
    454 }
    455 
    456 static int
    457 j720tp_get_hard_icon(struct j720tp_softc *sc, int rawx, int rawy)
    458 {
    459 	int icon = 0;
    460 
    461 	if (!(sc->sc_enabled & J720TP_WSKBD_ENABLED))
    462 		return 0;
    463 	/* Check if the touch was in the hard icons area. */
    464 	if (rawx > j720tp_hard_icon_left)
    465 		return 0;
    466 
    467 	if (rawy < J720TP_HARD_ICON_MAX_Y(1))
    468 		icon = 1;
    469 	else if (rawy < J720TP_HARD_ICON_MAX_Y(2))
    470 		icon = 2;
    471 	else if (rawy < J720TP_HARD_ICON_MAX_Y(3))
    472 		icon = 3;
    473 	else if (rawy < J720TP_HARD_ICON_MAX_Y(4))
    474 		icon = 4;
    475 
    476 	return icon;
    477 }
    478 
    479 static void
    480 j720tp_wsmouse_input(struct j720tp_softc *sc, int rawx, int rawy)
    481 {
    482 	int x, y;
    483 
    484 	tpcalib_trans(&sc->sc_tpcalib, rawx, rawy, &x, &y);
    485 	wsmouse_input(sc->sc_wsmousedev, 1, x, y, 0, 0,
    486 	    WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y);
    487 }
    488 
    489 static void
    490 j720tp_wsmouse_callout(void *arg)
    491 {
    492 	struct j720tp_softc *sc = arg;
    493 	struct j720ssp_softc *ssp = sc->sc_ssp;
    494 	int rawx, rawy, s;
    495 
    496 	s = spltty();
    497 
    498 	if (!(sc->sc_enabled & J720TP_WSMOUSE_ENABLED)) {
    499 		DPRINTF(("j720tp_wsmouse_callout: !sc_enabled\n"));
    500 		splx(s);
    501 		return;
    502 	}
    503 
    504 	if (bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PLR) & (1<<9)) {
    505 		wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0, 0);
    506 		j720tp_enable_intr(sc);
    507 	} else {
    508 		if (j720tp_get_rawxy(sc, &rawx, &rawy))
    509 			j720tp_wsmouse_input(sc, rawx, rawy);
    510 		callout_schedule(&sc->sc_tpcallout, hz / 32);
    511 	}
    512 
    513 	splx(s);
    514 }
    515 
    516 static void
    517 j720tp_wskbd_input(struct j720tp_softc *sc, u_int evtype)
    518 {
    519 	int key = j720tp_wskbd_keys[sc->sc_hard_icon - 1];
    520 
    521 #ifdef WSDISPLAY_COMPAT_RAWKBD
    522 	if (sc->sc_rawkbd) {
    523 		int n;
    524 		u_char data[16];
    525 
    526 		n = pckbd_encode(evtype, key, data);
    527 		wskbd_rawinput(sc->sc_wskbddev, data, n);
    528 	} else
    529 #endif
    530 		wskbd_input(sc->sc_wskbddev, evtype, key);
    531 }
    532 
    533 static void
    534 j720tp_wskbd_callout(void *arg)
    535 {
    536 	struct j720tp_softc *sc = arg;
    537 	struct j720ssp_softc *ssp = sc->sc_ssp;
    538 	int s;
    539 
    540 	s = spltty();
    541 
    542 	if (!sc->sc_enabled) {
    543 		DPRINTF(("j720tp_wskbd_callout: !sc_enabled\n"));
    544 		splx(s);
    545 		return;
    546 	}
    547 
    548 	if (bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PLR) & (1<<9)) {
    549 		j720tp_wskbd_input(sc, WSCONS_EVENT_KEY_UP);
    550 		j720tp_enable_intr(sc);
    551 	} else {
    552 		callout_schedule(&sc->sc_tpcallout, hz / 32);
    553 	}
    554 
    555 	splx(s);
    556 }
    557 
    558 SYSCTL_SETUP(sysctl_j720tp, "sysctl j720tp subtree setup")
    559 {
    560 	const struct sysctlnode *rnode;
    561 	int rc;
    562 
    563 	if ((rc = sysctl_createv(clog, 0, NULL, &rnode,
    564 	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "j720tp",
    565 	    SYSCTL_DESCR("Jornada 720 touch panel controls"),
    566 	    NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0)
    567 		goto err;
    568 
    569 #ifdef J720TP_DEBUG
    570 	if ((rc = sysctl_createv(clog, 0, &rnode, NULL,
    571 	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "debug",
    572 	    SYSCTL_DESCR("Verbosity of debugging messages"),
    573 	    NULL, 0, &j720tp_debug, 0, CTL_CREATE, CTL_EOL)) != 0)
    574 		goto err;
    575 #endif /* J720TP_DEBUG */
    576 
    577 	if ((rc = sysctl_createv(clog, 0, &rnode, &rnode,
    578 	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "hard_icons",
    579 	    SYSCTL_DESCR("Touch panel hard icons controls"),
    580 	    NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
    581 		goto err;
    582 
    583 	if ((rc = sysctl_createv(clog, 0, &rnode, NULL,
    584 	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "left",
    585 	    SYSCTL_DESCR("Raw left X value of the hard icon area"),
    586 	    NULL, 0, &j720tp_hard_icon_left, 0, CTL_CREATE, CTL_EOL)) != 0)
    587 		goto err;
    588 
    589 	if ((rc = sysctl_createv(clog, 0, &rnode, NULL,
    590 	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "right",
    591 	    SYSCTL_DESCR("Raw right X value of the hard icon area"),
    592 	    NULL, 0, &j720tp_hard_icon_right, 0, CTL_CREATE, CTL_EOL)) != 0)
    593 		goto err;
    594 
    595 	if ((rc = sysctl_createv(clog, 0, &rnode, NULL,
    596 	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "top",
    597 	    SYSCTL_DESCR("Raw top Y value of the hard icon area"),
    598 	    NULL, 0, &j720tp_hard_icon_top, 0, CTL_CREATE, CTL_EOL)) != 0)
    599 		goto err;
    600 
    601 	if ((rc = sysctl_createv(clog, 0, &rnode, NULL,
    602 	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "bottom",
    603 	    SYSCTL_DESCR("Raw bottom Y value of the hard icon area"),
    604 	    NULL, 0, &j720tp_hard_icon_bottom, 0, CTL_CREATE, CTL_EOL)) != 0)
    605 		goto err;
    606 
    607 	return;
    608 err:
    609 	aprint_normal("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
    610 }
    611