From dce2bc94e0dad155d362b2e294de7a6a5dcf5fc8 Mon Sep 17 00:00:00 2001 From: uch Date: Wed, 12 Jan 2000 14:56:17 +0000 Subject: [PATCH] add UCB1200 sound module ucbsnd (core implementation only) UCB1200 touch panel module moved to ucbtp and sync with vrpiu. --- sys/arch/hpcmips/conf/TX3912 | 12 +- sys/arch/hpcmips/conf/files.hpcmips | 19 +- sys/arch/hpcmips/dev/skbd.c | 18 +- sys/arch/hpcmips/dev/ucb1200.c | 699 ++++---------------------- sys/arch/hpcmips/dev/ucb1200reg.h | 79 ++- sys/arch/hpcmips/dev/ucb1200var.h | 89 +--- sys/arch/hpcmips/dev/ucbsnd.c | 376 ++++++++++++++ sys/arch/hpcmips/dev/ucbtp.c | 732 ++++++++++++++++++++++++++++ sys/arch/hpcmips/tx/tx39.c | 14 +- sys/arch/hpcmips/tx/tx39sib.c | 177 ++++++- sys/arch/hpcmips/tx/tx39sibvar.h | 10 +- sys/arch/hpcmips/tx/tx39var.h | 4 +- sys/arch/hpcmips/tx/txsim.c | 5 +- sys/arch/hpcmips/tx/txsnd.c | 52 ++ sys/arch/hpcmips/tx/txsnd.h | 41 ++ 15 files changed, 1594 insertions(+), 733 deletions(-) create mode 100644 sys/arch/hpcmips/dev/ucbsnd.c create mode 100644 sys/arch/hpcmips/dev/ucbtp.c create mode 100644 sys/arch/hpcmips/tx/txsnd.c create mode 100644 sys/arch/hpcmips/tx/txsnd.h diff --git a/sys/arch/hpcmips/conf/TX3912 b/sys/arch/hpcmips/conf/TX3912 index cb4548e19b08..e84463f71f8c 100644 --- a/sys/arch/hpcmips/conf/TX3912 +++ b/sys/arch/hpcmips/conf/TX3912 @@ -2,7 +2,7 @@ # Distribution kernel (TX3912 based model) kernel config file # -# $NetBSD: TX3912,v 1.6 2000/01/09 07:57:43 shin Exp $ +# $NetBSD: TX3912,v 1.7 2000/01/12 14:56:22 uch Exp $ # include "arch/hpcmips/conf/std.hpcmips" @@ -79,26 +79,28 @@ txcsbus4 at tx39biu? platform PHILIPS_NINO txcsbus5 at tx39biu? platform SHARP_MOBILON txcsbus* at tx39biu? # misc unknown. -# PHILIPS 74ALVC*1624? connected keyboard +# PHILIPS 74ALVC*1624? / TOSHIBA TC5165BFTS buffer chip (keyboard) # tc5165buf* at txcsbus3 iocs 3 iocsbase 0 iocssize 0x100 iocswidth 16 tc5165buf* at txcsbus5 iocs 4 iocsbase 0 iocssize 0x100 iocswidth 16 skbd* at tc5165buf? -# ITE IT8368E PCMCIA buffer chip +# ITE IT8368E PCMCIA / TOSHIBA TC6345AF buffer chip (PCMCIA) # card ... 3:2 (98) # insert/remove ... 5:1/8 (161/168) options IT8368E_LEGACY_MODE # Mobilon HC-4100 requires this it8368e* at txcsbus? regcs 2 regcsbase 0 regcssize 0x20 regcswidth 16 iocs 8 iocsbase 0 iocssize 0x4000000 iocswidth 16 irq1 161 irq2 168 irq3 98 -# PHILIPS UCB1200 modem/audio analog front-end +# PHILIPS UCB1200 / TOSHIBA TC35413F (modem/audio analog front-end) ucb* at tx39sib? slot 0 +ucbtp* at ucb? +ucbsnd* at ucb? # WS console uses SUN or VT100 terminal emulation fb* at tx3912video? wsdisplay* at fb? wskbd* at skbd? mux 1 -wsmouse* at ucb? mux 0 +wsmouse* at ucbtp? mux 0 options WSEMUL_VT100 options WSDISPLAY_DEFAULTSCREENS=4 diff --git a/sys/arch/hpcmips/conf/files.hpcmips b/sys/arch/hpcmips/conf/files.hpcmips index 9a841270f7c9..c57c9797924e 100644 --- a/sys/arch/hpcmips/conf/files.hpcmips +++ b/sys/arch/hpcmips/conf/files.hpcmips @@ -1,4 +1,4 @@ -# $NetBSD: files.hpcmips,v 1.16 2000/01/10 14:08:05 takemura Exp $ +# $NetBSD: files.hpcmips,v 1.17 2000/01/12 14:56:23 uch Exp $ # maxpartitions must be first item in files.${ARCH}. maxpartitions 8 @@ -173,9 +173,11 @@ device txsim { } device txcsbusif {[platform = -1]} device txcomif {[slot = -1]} device txsibif {[slot = -1]} +device ucbif { } attach txsim at mainbus file arch/hpcmips/tx/txsim.c txsim +file arch/hpcmips/tx/txsnd.c txsim device tx39biu: txcsbusif attach tx39biu at txsim @@ -209,11 +211,18 @@ device tx39sib: txsibif attach tx39sib at txsim file arch/hpcmips/tx/tx39sib.c tx39sib -# PHILIPS UCB1200 modem/audio analog front-end -device ucb: wsmousedev -attach ucb at txsibif: tpcalib +# PHILIPS UCB1200 / TOSHIBA TC35413F (modem/audio analog front-end) +device ucb: ucbif +attach ucb at txsibif file arch/hpcmips/dev/ucb1200.c ucb +device ucbtp: wsmousedev +attach ucbtp at ucbif: tpcalib +file arch/hpcmips/dev/ucbtp.c ucbtp + +device ucbsnd +attach ucbsnd at ucbif +file arch/hpcmips/dev/ucbsnd.c ucbsnd device tx39uart: txcomif attach tx39uart at txsim @@ -223,7 +232,7 @@ device txcom attach txcom at txcomif file arch/hpcmips/tx/txcom.c txcom -# ITE 8368E PCMCIA controller +# ITE IT8368E PCMCIA / TOSHIBA TC6345AF buffer chip (PCMCIA) device it8368e: pcmciabus attach it8368e at txcsbus file arch/hpcmips/dev/it8368.c it8368e diff --git a/sys/arch/hpcmips/dev/skbd.c b/sys/arch/hpcmips/dev/skbd.c index 8b106a7a2514..1cca812d860f 100644 --- a/sys/arch/hpcmips/dev/skbd.c +++ b/sys/arch/hpcmips/dev/skbd.c @@ -1,4 +1,4 @@ -/* $NetBSD: skbd.c,v 1.1 1999/12/08 15:49:18 uch Exp $ */ +/* $NetBSD: skbd.c,v 1.2 2000/01/12 14:56:22 uch Exp $ */ /* * Copyright (c) 1999, by UCHIYAMA Yasushi @@ -25,6 +25,8 @@ * SUCH DAMAGE. * */ +#include "opt_tx39xx.h" + #include #include #include @@ -47,6 +49,11 @@ #include #include +#ifdef TX39XX +#include +#include +#endif + struct skbd_softc; struct skbd_chip { @@ -209,7 +216,14 @@ __skbd_input(arg, flag, scancode) struct skbd_chip *sk = arg; int type, key; - type = flag ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP; + if (flag) { +#ifdef TX39XX + tx_sound_click(tx_conf_get_tag()); +#endif + type = WSCONS_EVENT_KEY_DOWN; + } else { + type = WSCONS_EVENT_KEY_UP; + } if ((key = sk->sk_keymap[scancode]) == UNK) { printf("skbd: unknown scan code %#x\n", scancode); diff --git a/sys/arch/hpcmips/dev/ucb1200.c b/sys/arch/hpcmips/dev/ucb1200.c index 17f72e42881c..fd8ee8d9cace 100644 --- a/sys/arch/hpcmips/dev/ucb1200.c +++ b/sys/arch/hpcmips/dev/ucb1200.c @@ -1,4 +1,4 @@ -/* $NetBSD: ucb1200.c,v 1.1 2000/01/08 21:07:04 uch Exp $ */ +/* $NetBSD: ucb1200.c,v 1.2 2000/01/12 14:56:22 uch Exp $ */ /* * Copyright (c) 2000, by UCHIYAMA Yasushi @@ -29,10 +29,8 @@ /* * Device driver for PHILIPS UCB1200 Advanced modem/audio analog front-end */ -#define UCB1200DEBUG - +#undef UCB1200DEBUG #include "opt_tx39_debug.h" -#include "opt_use_poll.h" #include #include @@ -40,17 +38,10 @@ #include #include -#include /* bootinfo */ - -#include -#include #include #include #include -#include - -#include /* debug */ #include #include @@ -61,147 +52,37 @@ int ucb1200_debug = 1; #define DPRINTFN(n, arg) if (ucb1200_debug > (n)) printf arg; #else #define DPRINTF(arg) +#define DPRINTFN(n, arg) #endif +struct ucbchild_state { + int (*cs_busy) __P((void*)); + void *cs_arg; +}; + +struct ucb1200_softc { + struct device sc_dev; + struct device *sc_parent; /* parent (TX39 SIB module) */ + tx_chipset_tag_t sc_tc; + + int sc_snd_rate; /* passed down from SIB module */ + int sc_tel_rate; + + /* inquire child module state */ + struct ucbchild_state sc_child[UCB1200_MODULE_MAX]; +}; + int ucb1200_match __P((struct device*, struct cfdata*, void*)); void ucb1200_attach __P((struct device*, struct device*, void*)); -int ucb1200_idcheck __P((bus_space_tag_t)); +int ucb1200_print __P((void*, const char*)); +int ucb1200_search __P((struct device*, struct cfdata*, void*)); -void ucb1200_dump __P((struct ucb1200_softc*)); -int ucb1200_sibintr __P((void*)); -int ucb1200_poll __P((void*)); - -int ucb1200_adc_async __P((void*)); -int ucb1200_input __P((struct ucb1200_softc*)); - -void ucb1200_intr_ack_sync __P((struct ucb1200_softc*)); -int ucb1200_adc_sync __P((struct ucb1200_softc*, int, int*)); - -int ucb_ts_enable __P((void*)); -int ucb_ts_ioctl __P((void*, u_long, caddr_t, int, struct proc*)); -void ucb_ts_disable __P((void*)); - -/* mra is defined in mra.c */ -int mra_Y_AX1_BX2_C __P((int *y, int ys, int *x1, int x1s, int *x2, int x2s, - int n, int scale, int *a, int *b, int *c)); +void ucb1200_dump __P((struct ucb1200_softc*)); struct cfattach ucb_ca = { sizeof(struct ucb1200_softc), ucb1200_match, ucb1200_attach }; -const struct wsmouse_accessops ucb_ts_accessops = { - ucb_ts_enable, - ucb_ts_ioctl, - ucb_ts_disable, -}; - -/* - * XXX currently no calibration method. this is temporary hack. - */ -#include -#define NSAMPLE 5 - -struct calibration_sample *calibration_sample_lookup __P((void)); -int ucb1200_tp_calibration __P((struct ucb1200_softc*)); - -struct calibration_sample { - int cs_xraw, cs_yraw, cs_x, cs_y; -}; - -struct calibration_sample_table { - platid_t cst_platform; - struct calibration_sample cst_sample[NSAMPLE]; -} calibration_sample_table[] = { - {{{PLATID_WILD, PLATID_MACH_COMPAQ_C_8XX}}, /* uch machine */ - {{ 507, 510, 320, 120 }, - { 898, 757, 40, 40 }, - { 900, 255, 40, 200 }, - { 109, 249, 600, 200 }, - { 110, 753, 600, 40 }}}, - - {{{PLATID_WILD, PLATID_MACH_COMPAQ_C_2010}}, /* uch machine */ - {{ 506, 487, 320, 120 }, - { 880, 250, 40, 40 }, - { 880, 718, 40, 200 }, - { 140, 726, 600, 200 }, - { 137, 250, 600, 40 }}}, - - {{{PLATID_WILD, PLATID_MACH_SHARP_MOBILON_HC4100}}, /* uch machine */ - {{ 497, 501, 320, 120 }, - { 752, 893, 40, 40 }, - { 242, 891, 40, 200 }, - { 241, 115, 600, 200 }, - { 747, 101, 600, 40 }}}, - - {{{PLATID_UNKNOWN, PLATID_UNKNOWN}}, - {{0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}}}, -}; - -struct calibration_sample* -calibration_sample_lookup() -{ - struct calibration_sample_table *tab; - platid_mask_t mask; - - for (tab = calibration_sample_table; - tab->cst_platform.dw.dw1 != PLATID_UNKNOWN; tab++) { - - mask = PLATID_DEREF(&tab->cst_platform); - - if (platid_match(&platid, &mask)) { - return tab->cst_sample; - } - } - - return 0; -} - -int -ucb1200_tp_calibration(sc) - struct ucb1200_softc *sc; -{ -#define SCALE (1024*1024) - struct calibration_sample *cs; - int s, n; - - tx3912video_calibration_pattern(); - - sc->sc_prmxs = bootinfo->fb_width; - sc->sc_prmys = bootinfo->fb_height; - sc->sc_maxx = bootinfo->fb_width - 1; - sc->sc_maxy = bootinfo->fb_height - 1; - - if (!(cs = calibration_sample_lookup())) { - printf(": no calibration data\n"); - return 1; - } - - s = sizeof(struct calibration_sample); - n = NSAMPLE; - - if (mra_Y_AX1_BX2_C(&cs->cs_x, s, &cs->cs_xraw, s, &cs->cs_yraw, s, - n, SCALE, &sc->sc_prmax, &sc->sc_prmbx, - &sc->sc_prmcx) || - mra_Y_AX1_BX2_C(&cs->cs_y, s, &cs->cs_xraw, s, &cs->cs_yraw, s, - n, SCALE, &sc->sc_prmay, - &sc->sc_prmby, &sc->sc_prmcy)) { - printf(": MRA error"); - - return 1; - } else { - DPRINTF((": Ax=%d Bx=%d Cx=%d", - sc->sc_prmax, sc->sc_prmbx, sc->sc_prmcx)); - DPRINTF((" Ay=%d By=%d Cy=%d\n", - sc->sc_prmay, sc->sc_prmby, sc->sc_prmcy)); - } - - return 0; -} - int ucb1200_match(parent, cf, aux) struct device *parent; @@ -209,12 +90,16 @@ ucb1200_match(parent, cf, aux) void *aux; { struct txsib_attach_args *sa = aux; + u_int16_t reg; if (sa->sa_slot != 0) /* UCB1200 must be subframe 0 */ return 0; - - return txsibsf0_reg_read(sa->sa_tc, UCB1200_ID_REG) == UCB1200_ID - ? 1 : 0; + reg = txsibsf0_reg_read(sa->sa_tc, UCB1200_ID_REG); + + if (reg == UCB1200_ID || reg == TC35413F_ID) + return 1; + else + return 0; } void @@ -225,501 +110,80 @@ ucb1200_attach(parent, self, aux) { struct txsib_attach_args *sa = aux; struct ucb1200_softc *sc = (void*)self; - struct wsmousedev_attach_args wsmaa; sc->sc_tc = sa->sa_tc; sc->sc_parent = parent; - - tx_intr_establish(sc->sc_tc, - MAKEINTR(1, TX39_INTRSTATUS1_SIBIRQPOSINT), - IST_EDGE, IPL_TTY, ucb1200_sibintr, sc); + sc->sc_snd_rate = sa->sa_snd_rate; + sc->sc_tel_rate = sa->sa_tel_rate; + + tx39sib_enable1(sc->sc_parent); + tx39sib_enable2(sc->sc_parent); - ucb1200_tp_calibration(sc); #ifdef UCB1200DEBUG ucb1200_dump(sc); #endif - - wsmaa.accessops = &ucb_ts_accessops; - wsmaa.accesscookie = sc; - printf("\n"); - /* - * attach the wsmouse - */ - sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint); + config_search(ucb1200_search, self, ucb1200_print); } int -ucb1200_poll(arg) - void *arg; +ucb1200_search(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; { - struct ucb1200_softc *sc = arg; + struct ucb1200_softc *sc = (void*)parent; + struct ucb1200_attach_args ucba; - if (sc->sm_state != UCBADC_IDLE) { - printf("%s: %s busy\n", sc->sc_dev.dv_xname, - sc->sc_parent->dv_xname); - return POLL_CONT; - } - - if (sc->sc_polling_finish) { - sc->sc_polling_finish = 0; - return POLL_END; - } + ucba.ucba_tc = sc->sc_tc; + ucba.ucba_snd_rate = sc->sc_snd_rate; + ucba.ucba_tel_rate = sc->sc_tel_rate; + ucba.ucba_sib = sc->sc_parent; + ucba.ucba_ucb = parent; - /* execute A-D converter */ - sc->sm_state = UCBADC_ADC_INIT; - ucb1200_adc_async(sc); + if ((*cf->cf_attach->ca_match)(parent, cf, &ucba)) + config_attach(parent, cf, &ucba, ucb1200_print); - return POLL_CONT; + return 0; } -#define REGWRITE(addr, reg, ret) ( \ - sc->sm_addr = (addr), \ - sc->sm_reg = (reg), \ - sc->sm_returnstate = (ret),\ - sc->sm_state = UCBADC_REGWRITE) -#define REGREAD(addr, ret) ( \ - sc->sm_addr = (addr), \ - sc->sm_returnstate = (ret), \ - sc->sm_state = UCBADC_REGREAD) +int +ucb1200_print(aux, pnp) + void *aux; + const char *pnp; +{ + return pnp ? QUIET : UNCONF; +} + +void +ucb1200_state_install(dev, sfun, sarg, sid) + struct device *dev; + int (*sfun) __P((void*)); + void *sarg; + int sid; +{ + struct ucb1200_softc *sc = (void*)dev; + + sc->sc_child[sid].cs_busy = sfun; + sc->sc_child[sid].cs_arg = sarg; +} int -ucb1200_adc_async(arg) - void *arg; +ucb1200_state_idle(dev) + struct device *dev; { - struct ucb1200_softc *sc = arg; - tx_chipset_tag_t tc = sc->sc_tc; - txreg_t reg; - u_int16_t reg16; + struct ucb1200_softc *sc = (void*)dev; + struct ucbchild_state *cs; + int i; - DPRINTFN(9, ("state: %d\n", sc->sm_state)); - - switch (sc->sm_state) { - default: - panic("ucb1200_adc: invalid state %d", sc->sm_state); - /* NOTREACHED */ - break; - - case UCBADC_IDLE: - /* nothing to do */ - break; - - case UCBADC_ADC_INIT: - sc->sc_polling++; - sc->sc_stat = UCBTS_STAT_DRAG; - /* enable heart beat of this state machine */ - sc->sm_ih = tx_intr_establish( - tc, - MAKEINTR(1, TX39_INTRSTATUS1_SIBSF0INT), - IST_EDGE, IPL_TTY, ucb1200_adc_async, sc); - - sc->sm_state = UCBADC_MEASUMENT_INIT; - break; - - case UCBADC_ADC_FINI: - /* disable heart beat of this state machine */ - tx_intr_disestablish(tc, sc->sm_ih); - sc->sm_state = UCBADC_IDLE; - break; - - case UCBADC_MEASUMENT_INIT: - switch (sc->sm_measurement) { - default: - panic("unknown measurement spec."); - /* NOTREACHED */ - break; - case UCBADC_MEASUREMENT_X: - REGWRITE(UCB1200_TSCTRL_REG, - UCB1200_TSCTRL_XPOSITION, - UCBADC_ADC_ENABLE); - break; - case UCBADC_MEASUREMENT_Y: - REGWRITE(UCB1200_TSCTRL_REG, - UCB1200_TSCTRL_YPOSITION, - UCBADC_ADC_ENABLE); - break; - case UCBADC_MEASUREMENT_PRESSURE: - REGWRITE(UCB1200_TSCTRL_REG, - UCB1200_TSCTRL_PRESSURE, - UCBADC_ADC_ENABLE); - break; - } - break; - - case UCBADC_MEASUMENT_FINI: - switch (sc->sm_measurement) { - case UCBADC_MEASUREMENT_X: - sc->sm_measurement = UCBADC_MEASUREMENT_Y; - sc->sm_state = UCBADC_MEASUMENT_INIT; - break; - case UCBADC_MEASUREMENT_Y: - sc->sm_measurement = UCBADC_MEASUREMENT_PRESSURE; - sc->sm_state = UCBADC_MEASUMENT_INIT; - break; - case UCBADC_MEASUREMENT_PRESSURE: - sc->sm_measurement = UCBADC_MEASUREMENT_X; - /* measument complete. pass down to wsmouse_input */ - sc->sm_state = UCBADC_ADC_INPUT; - break; - } - break; - - case UCBADC_ADC_ENABLE: - switch (sc->sm_measurement) { - case UCBADC_MEASUREMENT_PRESSURE: - /* FALLTHROUGH */ - case UCBADC_MEASUREMENT_X: - sc->sm_tmpreg = UCB1200_ADCCTRL_INPUT_SET( - UCB1200_ADCCTRL_ENABLE, - UCB1200_ADCCTRL_INPUT_TSPX); - REGWRITE(UCB1200_ADCCTRL_REG, sc->sm_tmpreg, - UCBADC_ADC_START0); - break; - case UCBADC_MEASUREMENT_Y: - sc->sm_tmpreg = UCB1200_ADCCTRL_INPUT_SET( - UCB1200_ADCCTRL_ENABLE, - UCB1200_ADCCTRL_INPUT_TSPY); - REGWRITE(UCB1200_ADCCTRL_REG, sc->sm_tmpreg, - UCBADC_ADC_START0); - break; - } - break; - - case UCBADC_ADC_START0: - REGWRITE(UCB1200_ADCCTRL_REG, - sc->sm_tmpreg | UCB1200_ADCCTRL_START, - UCBADC_ADC_START1); - break; - - case UCBADC_ADC_START1: - REGWRITE(UCB1200_ADCCTRL_REG, - sc->sm_tmpreg, - UCBADC_ADC_DATAREAD); - sc->sm_retry = 10; - break; - - case UCBADC_ADC_DATAREAD: - REGREAD(UCB1200_ADCDATA_REG, UCBADC_ADC_DATAREAD_WAIT); - break; - - case UCBADC_ADC_DATAREAD_WAIT: - reg16 = TX39_SIBSF0_REGDATA(sc->sm_reg); - if (!(reg16 & UCB1200_ADCDATA_INPROGRESS) && - --sc->sm_retry > 0) { - sc->sm_state = UCBADC_ADC_DATAREAD; - } else { - if (sc->sm_retry <= 0) { - printf("dataread failed\n"); - sc->sm_state = UCBADC_ADC_FINI; - break; - } - - switch (sc->sm_measurement) { - case UCBADC_MEASUREMENT_X: - sc->sc_x = UCB1200_ADCDATA(reg16); - DPRINTFN(9, ("x=%d\n", sc->sc_x)); - break; - case UCBADC_MEASUREMENT_Y: - sc->sc_y = UCB1200_ADCDATA(reg16); - DPRINTFN(9, ("y=%d\n", sc->sc_y)); - break; - case UCBADC_MEASUREMENT_PRESSURE: - sc->sc_p = UCB1200_ADCDATA(reg16); - DPRINTFN(9, ("p=%d\n", sc->sc_p)); - break; - } - - sc->sm_state = UCBADC_ADC_DISABLE; - } - - break; - - case UCBADC_ADC_DISABLE: - REGWRITE(UCB1200_ADCCTRL_REG, 0, UCBADC_ADC_INTRMODE); - - break; - case UCBADC_ADC_INTRMODE: - REGWRITE(UCB1200_TSCTRL_REG, UCB1200_TSCTRL_INTERRUPT, - UCBADC_MEASUMENT_FINI); - break; - - case UCBADC_ADC_INPUT: - if (ucb1200_input(sc) == 0) - sc->sm_state = UCBADC_ADC_FINI; - else - sc->sm_state = UCBADC_INTR_ACK0; - break; - - case UCBADC_INTR_ACK0: - REGREAD(UCB1200_INTSTAT_REG, UCBADC_INTR_ACK1); - break; - - case UCBADC_INTR_ACK1: - REGWRITE(UCB1200_INTSTAT_REG, sc->sm_reg, UCBADC_INTR_ACK2); - break; - - case UCBADC_INTR_ACK2: - sc->sc_polling_finish = 1; - REGWRITE(UCB1200_INTSTAT_REG, 0, UCBADC_ADC_FINI); - break; - - /* - * UCB1200 register access state - */ - case UCBADC_REGREAD: - /* - * In : sc->sm_addr - * Out : sc->sm_reg (with SIBtag) - */ -#define TXSIB_REGREAD_INIT 0 -#define TXSIB_REGREAD_READ 1 - switch (sc->sm_read_state) { - case TXSIB_REGREAD_INIT: - reg = TX39_SIBSF0_REGADDR_SET(0, sc->sm_addr); - tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); - sc->sm_rw_retry = 3; - sc->sm_read_state = TXSIB_REGREAD_READ; - break; - case TXSIB_REGREAD_READ: - reg = tx_conf_read(tc, TX39_SIBSF0STAT_REG); - if ((TX39_SIBSF0_REGADDR(reg) != sc->sm_addr) && - --sc->sm_rw_retry > 0) { - printf("retry!\n"); - break; - } - - if (sc->sm_rw_retry <= 0) { - printf("sf0read: command failed\n"); - sc->sm_state = UCBADC_ADC_FINI; - } else { - sc->sm_reg = reg; - sc->sm_read_state = TXSIB_REGREAD_INIT; - DPRINTFN(9, ("%08x\n", reg)); - if (sc->sm_writing) - sc->sm_state = UCBADC_REGWRITE; - else - sc->sm_state = sc->sm_returnstate; - } - break; - } - break; + cs = sc->sc_child; + for (i = 0; i < UCB1200_MODULE_MAX; i++, cs++) + if (cs->cs_busy) + if ((*cs->cs_busy)(cs->cs_arg)) + return 0; - case UCBADC_REGWRITE: - /* - * In : sc->sm_addr, sc->sm_reg (lower 16bit only) - */ -#define TXSIB_REGWRITE_INIT 0 -#define TXSIB_REGWRITE_WRITE 1 - switch (sc->sm_write_state) { - case TXSIB_REGWRITE_INIT: - sc->sm_writing = 1; - sc->sm_write_state = TXSIB_REGWRITE_WRITE; - sc->sm_state = UCBADC_REGREAD; - - sc->sm_write_val = sc->sm_reg; - break; - case TXSIB_REGWRITE_WRITE: - sc->sm_writing = 0; - sc->sm_write_state = TXSIB_REGWRITE_INIT; - sc->sm_state = sc->sm_returnstate; - - reg = sc->sm_reg; - reg |= TX39_SIBSF0_WRITE; - TX39_SIBSF0_REGDATA_CLR(reg); - reg = TX39_SIBSF0_REGDATA_SET(reg, sc->sm_write_val); - tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); - - break; - } - break; - } - - return 0; -} - -int -ucb1200_input(sc) - struct ucb1200_softc *sc; -{ - static int _x, _y; - int xraw, yraw, pval, x, y; - - xraw = sc->sc_x; - yraw = sc->sc_y; - pval = sc->sc_p; - - x = (sc->sc_prmax * xraw + sc->sc_prmbx*yraw) / SCALE + - sc->sc_prmcx; - y = (sc->sc_prmay * xraw + sc->sc_prmby*yraw) / SCALE + - sc->sc_prmcy; - - if (pval < UCBTS_PRESS_THRESHOLD) { - sc->sc_stat = UCBTS_STAT_RELEASE; - if (sc->sc_polling < UCBTS_TAP_THRESHOLD) { - DPRINTFN(1, ("TAP!\n")); - /* button 0 DOWN */ - wsmouse_input(sc->sc_wsmousedev, 1, 0, 0, 0, 0); - /* button 0 UP */ - wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0); - } else { - wsmouse_input(sc->sc_wsmousedev, 0, _x, _y, 0, - WSMOUSE_INPUT_ABSOLUTE_X | - WSMOUSE_INPUT_ABSOLUTE_Y); - - DPRINTFN(1, ("RELEASE\n")); - } - sc->sc_polling = 0; - - return 1; - } - DPRINTFN(1, ("xraw=%d yraw=%d pressure=%d\n", xraw, yraw, pval)); - - if (x < 0 || x > sc->sc_maxx || y < 0 || y > sc->sc_maxy) - return 0; - - if (sc->sc_polling == 1) - tx3912video_dot(_x = x, _y = y); - else - tx3912video_line(_x, _y, _x = x, _y = y); - - wsmouse_input(sc->sc_wsmousedev, 1, x, y, 0, - WSMOUSE_INPUT_ABSOLUTE_X | - WSMOUSE_INPUT_ABSOLUTE_Y); - - return 0; -} - -int -ucb1200_sibintr(arg) - void *arg; -{ - struct ucb1200_softc *sc = arg; - - sc->sc_stat = UCBTS_STAT_TOUCH; - - /* invoke touch screen polling */ - if (!sc->sc_polling) { - sc->sc_pollh = tx39_poll_establish(sc->sc_tc, 1, IST_EDGE, - ucb1200_poll, sc); - if (!sc->sc_pollh) { - printf("%s: can't poll\n", sc->sc_dev.dv_xname); - } - } - - /* don't acknoledge interrupt until polling finish */ - - return 0; -} - -/* - * sync functions. don't use runtime. - */ - -void -ucb1200_intr_ack_sync(sc) - struct ucb1200_softc *sc; -{ - tx_chipset_tag_t tc = sc->sc_tc; - u_int16_t reg; - - /* clear interrupt */ - reg = txsibsf0_reg_read(tc, UCB1200_INTSTAT_REG); - txsibsf0_reg_write(tc, UCB1200_INTSTAT_REG, reg); - txsibsf0_reg_write(tc, UCB1200_INTSTAT_REG, 0); -} - -int -ucb1200_adc_sync(sc, src, valp) - struct ucb1200_softc *sc; - int src; - int *valp; -{ - tx_chipset_tag_t tc = sc->sc_tc; - u_int16_t reg; - int i = 100; /* retry max */ - - reg = UCB1200_ADCCTRL_ENABLE; - - switch (src) { - case UCBTS_POSX: - txsibsf0_reg_write(tc, UCB1200_TSCTRL_REG, - UCB1200_TSCTRL_XPOSITION); - reg = UCB1200_ADCCTRL_INPUT_SET(reg, - UCB1200_ADCCTRL_INPUT_TSPX); - break; - case UCBTS_POSY: - txsibsf0_reg_write(tc, UCB1200_TSCTRL_REG, - UCB1200_TSCTRL_YPOSITION); - reg = UCB1200_ADCCTRL_INPUT_SET(reg, - UCB1200_ADCCTRL_INPUT_TSPY); - break; - case UCBTS_PRESS: - txsibsf0_reg_write(tc, UCB1200_TSCTRL_REG, - UCB1200_TSCTRL_PRESSURE); - reg = UCB1200_ADCCTRL_INPUT_SET(reg, - UCB1200_ADCCTRL_INPUT_TSPX); - break; - } - /* enable ADC */ - txsibsf0_reg_write(tc, UCB1200_ADCCTRL_REG, reg); - - /* start A-D convert */ - txsibsf0_reg_write(tc, UCB1200_ADCCTRL_REG, - reg | UCB1200_ADCCTRL_START); - txsibsf0_reg_write(tc, UCB1200_ADCCTRL_REG, reg); - - /* inquire converted value */ - do { - reg = txsibsf0_reg_read(tc, UCB1200_ADCDATA_REG); - } while (!(reg & UCB1200_ADCDATA_INPROGRESS) && --i > 0); - - /* disable ADC */ - txsibsf0_reg_write(tc, UCB1200_ADCCTRL_REG, 0); - - /* turn to interrupt mode */ - txsibsf0_reg_write(tc, UCB1200_TSCTRL_REG, - UCB1200_TSCTRL_INTERRUPT); - - if (i == 0) { - printf("ADC not complete.\n"); - return 1; - } else { - *valp = UCB1200_ADCDATA(reg); - } - - return 0; -} - -/* - * access ops. - */ - -int -ucb_ts_enable(v) - void *v; -{ - /* not yet */ - return 0; -} - -void -ucb_ts_disable(v) - void *v; -{ - /* not yet */ -} - -int -ucb_ts_ioctl(v, cmd, data, flag, p) - void *v; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; -{ - /* not yet */ - return 0; + return 1; /* idle state */ } void @@ -748,6 +212,7 @@ ucb1200_dump(sc) u_int16_t reg; int i; + printf("\n\t[UCB1200 register]\n"); for (i = 0; i < 16; i++) { reg = txsibsf0_reg_read(tc, i); printf("%s(%02d) 0x%04x ", regname[i], i, reg); diff --git a/sys/arch/hpcmips/dev/ucb1200reg.h b/sys/arch/hpcmips/dev/ucb1200reg.h index 83f2f2a85cfe..8ea42c050915 100644 --- a/sys/arch/hpcmips/dev/ucb1200reg.h +++ b/sys/arch/hpcmips/dev/ucb1200reg.h @@ -1,4 +1,4 @@ -/* $NetBSD: ucb1200reg.h,v 1.1 2000/01/08 21:07:04 uch Exp $ */ +/* $NetBSD: ucb1200reg.h,v 1.2 2000/01/12 14:56:22 uch Exp $ */ /* * Copyright (c) 2000, by UCHIYAMA Yasushi @@ -48,6 +48,81 @@ #define UCB1200_RESERVED_REG 14 #define UCB1200_NULL_REG 15 /* always returns 0xffff */ +/* + * I/O port data register + */ +#define UCB1200_IO_DATA_SPEAKER 0x100 /* XXX general? */ + +/* + * Telecom control register A + */ +#define UCB1200_TELECOMCTRLA_DIV_MIN 16 +#define UCB1200_TELECOMCTRLA_DIV_MAX 127 +#define UCB1200_TELECOMCTRLA_DIV_SHIFT 0 +#define UCB1200_TELECOMCTRLA_DIV_MASK 0x7f +#define UCB1200_TELECOMCTRLA_DIV(cr) \ + (((cr) >> UCB1200_TELECOMCTRLA_DIV_SHIFT) & \ + UCB1200_TELECOMCTRLA_DIV_MASK) +#define UCB1200_TELECOMCTRLA_DIV_SET(cr, val) \ + ((cr) | (((val) << UCB1200_TELECOMCTRLA_DIV_SHIFT) & \ + (UCB1200_TELECOMCTRLA_DIV_MASK << UCB1200_TELECOMCTRLA_DIV_SHIFT))) + +#define UCB1200_TELECOMCTRLA_LOOP 0x0080 + +/* + * Telecom control register B + */ +#define UCB1200_TELECOMCTRLB_VBF 0x0008 +#define UCB1200_TELECOMCTRLB_CLIPSTATCLR 0x0010 +#define UCB1200_TELECOMCTRLB_ATT 0x0040 +#define UCB1200_TELECOMCTRLB_STS 0x0800 +#define UCB1200_TELECOMCTRLB_MUTE 0x2000 +#define UCB1200_TELECOMCTRLB_INEN 0x4000 +#define UCB1200_TELECOMCTRLB_OUTEN 0x8000 + +/* + * Audio control register A + */ +#define UCB1200_AUDIOCTRLA_DIV_MIN 6 +#define UCB1200_AUDIOCTRLA_DIV_MAX 127 +#define UCB1200_AUDIOCTRLA_DIV_SHIFT 0 +#define UCB1200_AUDIOCTRLA_DIV_MASK 0x7f +#define UCB1200_AUDIOCTRLA_DIV(cr) \ + (((cr) >> UCB1200_AUDIOCTRLA_DIV_SHIFT) & \ + UCB1200_AUDIOCTRLA_DIV_MASK) +#define UCB1200_AUDIOCTRLA_DIV_SET(cr, val) \ + ((cr) | (((val) << UCB1200_AUDIOCTRLA_DIV_SHIFT) & \ + (UCB1200_AUDIOCTRLA_DIV_MASK << UCB1200_AUDIOCTRLA_DIV_SHIFT))) + +#define UCB1200_AUDIOCTRLA_GAIN_SHIFT 7 +#define UCB1200_AUDIOCTRLA_GAIN_MASK 0x1f +#define UCB1200_AUDIOCTRLA_GAIN(cr) \ + (((cr) >> UCB1200_AUDIOCTRLA_GAIN_SHIFT) & \ + UCB1200_AUDIOCTRLA_GAIN_MASK) +#define UCB1200_AUDIOCTRLA_GAIN_SET(cr, val) \ + ((cr) | (((val) << UCB1200_AUDIOCTRLA_GAIN_SHIFT) & \ + (UCB1200_AUDIOCTRLA_GAIN_MASK << UCB1200_AUDIOCTRLA_GAIN_SHIFT))) + +/* + * Audio control register B + */ +#define UCB1200_AUDIOCTRLB_ATT_MIN 0 +#define UCB1200_AUDIOCTRLB_ATT_MAX 0x1f +#define UCB1200_AUDIOCTRLB_ATT_SHIFT 0 +#define UCB1200_AUDIOCTRLB_ATT_MASK 0x1f +#define UCB1200_AUDIOCTRLB_ATT(cr) \ + (((cr) >> UCB1200_AUDIOCTRLB_ATT_SHIFT) & \ + UCB1200_AUDIOCTRLB_ATT_MASK) +#define UCB1200_AUDIOCTRLB_ATT_SET(cr, val) \ + ((cr) | (((val) << UCB1200_AUDIOCTRLB_ATT_SHIFT) & \ + (UCB1200_AUDIOCTRLB_ATT_MASK << UCB1200_AUDIOCTRLB_ATT_SHIFT))) + +#define UCB1200_AUDIOCTRLB_CLIPSTATCLR 0x0040 +#define UCB1200_AUDIOCTRLB_LOOP 0x0100 +#define UCB1200_AUDIOCTRLB_MUTE 0x2000 +#define UCB1200_AUDIOCTRLB_INEN 0x4000 +#define UCB1200_AUDIOCTRLB_OUTEN 0x8000 + /* * Touch screen control register */ @@ -138,3 +213,5 @@ */ /* Version 4, Device 0, Supplier 1 */ #define UCB1200_ID 0x1004 +/* TOSHIBA TC35413F */ +#define TC35413F_ID 0x9712 diff --git a/sys/arch/hpcmips/dev/ucb1200var.h b/sys/arch/hpcmips/dev/ucb1200var.h index 78b53f581fa3..47b79e2fe5c6 100644 --- a/sys/arch/hpcmips/dev/ucb1200var.h +++ b/sys/arch/hpcmips/dev/ucb1200var.h @@ -1,4 +1,4 @@ -/* $NetBSD: ucb1200var.h,v 1.1 2000/01/08 21:07:04 uch Exp $ */ +/* $NetBSD: ucb1200var.h,v 1.2 2000/01/12 14:56:22 uch Exp $ */ /* * Copyright (c) 2000, by UCHIYAMA Yasushi @@ -26,82 +26,19 @@ * */ -enum ucbts_stat { - UCBTS_STAT_DISABLE, - UCBTS_STAT_RELEASE, - UCBTS_STAT_TOUCH, - UCBTS_STAT_DRAG, +struct ucb1200_attach_args { + tx_chipset_tag_t ucba_tc; + int ucba_snd_rate; + int ucba_tel_rate; + struct device *ucba_sib; + struct device *ucba_ucb; }; -#define UCBTS_POSX 1 -#define UCBTS_POSY 2 -#define UCBTS_PRESS 3 +#define UCB1200_TP_MODULE 0 +#define UCB1200_SND_MODULE 1 +#define UCB1200_TEL_MODULE 2 +#define UCB1200_MODULE_MAX 3 -#define UCBTS_PRESS_THRESHOLD 100 -#define UCBTS_TAP_THRESHOLD 5 - -enum ucbadc_state { -/* 0 */ UCBADC_IDLE, -/* 1 */ UCBADC_ADC_INIT, -/* 2 */ UCBADC_ADC_FINI, -/* 3 */ UCBADC_MEASUMENT_INIT, -/* 4 */ UCBADC_MEASUMENT_FINI, -/* 5 */ UCBADC_ADC_ENABLE, -/* 6 */ UCBADC_ADC_START0, -/* 7 */ UCBADC_ADC_START1, -/* 8 */ UCBADC_ADC_DATAREAD, -/* 9 */ UCBADC_ADC_DATAREAD_WAIT, -/*10 */ UCBADC_ADC_DISABLE, -/*11 */ UCBADC_ADC_INTRMODE, -/*12 */ UCBADC_ADC_INPUT, -/*13 */ UCBADC_INTR_ACK0, -/*14 */ UCBADC_INTR_ACK1, -/*15 */ UCBADC_INTR_ACK2, -/*16 */ UCBADC_REGREAD, -/*17 */ UCBADC_REGWRITE -}; - -struct ucb1200_softc { - struct device sc_dev; - struct device *sc_parent; /* parent (TX39 SIB module) */ - tx_chipset_tag_t sc_tc; - - enum ucbts_stat sc_stat; - int sc_polling; - int sc_polling_finish; - void *sc_pollh; - - /* correction parameters */ - int sc_prmax, sc_prmbx, sc_prmcx, sc_prmxs; - int sc_prmay, sc_prmby, sc_prmcy, sc_prmys; - /* limit */ - int sc_maxx, sc_maxy; - - /* measurement value */ - int sc_x, sc_y, sc_p; - - /* SIB frame 0 state machine */ - void *sm_ih; /* TX39 SIB subframe 0 interrupt handler */ - - int sm_addr; /* UCB1200 register address */ - u_int32_t sm_reg; /* UCB1200 register data & TX39 SIB header */ - int sm_tmpreg; - int sm_retry; /* retry counter */ - - enum ucbadc_state sm_state; - int sm_measurement; /* X, Y, Pressure */ -#define UCBADC_MEASUREMENT_X 0 -#define UCBADC_MEASUREMENT_Y 1 -#define UCBADC_MEASUREMENT_PRESSURE 2 - int sm_returnstate; - - int sm_read_state, sm_write_state; - int sm_writing; /* writing state flag */ - u_int32_t sm_write_val; /* temporary buffer */ - - int sm_rw_retry; /* retry counter for r/w */ - - /* wsmouse */ - struct device *sc_wsmousedev; -}; +void ucb1200_state_install __P((struct device*, int (*)__P((void*)), void*, int)); +int ucb1200_state_idle __P((struct device*)); diff --git a/sys/arch/hpcmips/dev/ucbsnd.c b/sys/arch/hpcmips/dev/ucbsnd.c new file mode 100644 index 000000000000..84de58e36ebe --- /dev/null +++ b/sys/arch/hpcmips/dev/ucbsnd.c @@ -0,0 +1,376 @@ +/* $NetBSD: ucbsnd.c,v 1.1 2000/01/12 14:56:21 uch Exp $ */ + +/* + * Copyright (c) 2000, by UCHIYAMA Yasushi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the developer may NOT be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * Device driver for PHILIPS UCB1200 Advanced modem/audio analog front-end + * Audio codec part. + */ +#define UCBSNDDEBUG + +#include "opt_tx39_debug.h" +#include "opt_use_poll.h" + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#ifdef UCBSNDDEBUG +int ucbsnd_debug = 1; +#define DPRINTF(arg) if (ucbsnd_debug) printf arg; +#define DPRINTFN(n, arg) if (ucbsnd_debug > (n)) printf arg; +#else +#define DPRINTF(arg) +#define DPRINTFN(n, arg) +#endif + +enum ucbsnd_state { +/* 0 */ UCBSND_IDLE, +/* 1 */ UCBSND_INIT, +/* 2 */ UCBSND_ENABLE_SAMPLERATE, +/* 3 */ UCBSND_ENABLE_OUTPUTPATH, +/* 5 */ UCBSND_ENABLE_SPEAKER0, +/* 6 */ UCBSND_ENABLE_SPEAKER1, +/* 7 */ UCBSND_TRANSITION_PIO, +/* 8 */ UCBSND_PIO, +/* 9 */ UCBSND_TRANSITION_DISABLE, +/*10 */ UCBSND_DISABLE_OUTPUTPATH, +/*11 */ UCBSND_DISABLE_SPEAKER0, +/*12 */ UCBSND_DISABLE_SPEAKER1, +/*13 */ UCBSND_DISABLE_SIB +}; + +struct ucbsnd_softc { + struct device sc_dev; + struct device *sc_sib; /* parent (TX39 SIB module) */ + struct device *sc_ucb; /* parent (UCB1200 module) */ + tx_chipset_tag_t sc_tc; + + struct tx_sound_tag sc_tag; + + /* + * audio codec state machine + */ + enum ucbsnd_state sa_state; + + int sa_snd_rate; /* passed down from SIB module */ + int sa_tel_rate; + int sa_enabled; + void* sa_sf0ih; + void* sa_sndih; + int sa_retry; + int sa_cnt; /* misc counter */ + +}; + +int ucbsnd_match __P((struct device*, struct cfdata*, void*)); +void ucbsnd_attach __P((struct device*, struct device*, void*)); + +int ucbsnd_exec_output __P((void*)); +int ucbsnd_busy __P((void*)); + +void ucbsnd_sound_init __P((struct ucbsnd_softc*)); +void __ucbsnd_sound_click __P((tx_sound_tag_t)); + +struct cfattach ucbsnd_ca = { + sizeof(struct ucbsnd_softc), ucbsnd_match, ucbsnd_attach +}; + +int +ucbsnd_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + return 1; +} + +void +ucbsnd_attach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct ucb1200_attach_args *ucba = aux; + struct ucbsnd_softc *sc = (void*)self; + tx_chipset_tag_t tc; + + tc = sc->sc_tc = ucba->ucba_tc; + sc->sc_sib = ucba->ucba_sib; + sc->sc_ucb = ucba->ucba_ucb; +#define SOUND_TEST +#ifdef SOUND_TEST + ucbsnd_sound_init(sc); +#endif + sc->sa_snd_rate = ucba->ucba_snd_rate; + sc->sa_tel_rate = ucba->ucba_tel_rate; + +#define KHZ(a) ((a) / 1000), (((a) % 1000)) + printf(": audio %d.%03d kHz telecom %d.%03d kHz", + KHZ((tx39sib_clock(sc->sc_sib) * 2) / + (sc->sa_snd_rate * 64)), + KHZ((tx39sib_clock(sc->sc_sib) * 2) / + (sc->sa_tel_rate * 64))); + + ucb1200_state_install(parent, ucbsnd_busy, self, + UCB1200_SND_MODULE); + + printf("\n"); +} + +int +ucbsnd_busy(arg) + void *arg; +{ + struct ucbsnd_softc *sc = arg; + + return sc->sa_state != UCBSND_IDLE; +} + +int +ucbsnd_exec_output(arg) + void *arg; +{ + struct ucbsnd_softc *sc = arg; + tx_chipset_tag_t tc = sc->sc_tc; + txreg_t reg; + + switch (sc->sa_state) { + default: + panic("ucbsnd_exec_output: invalid state %d", sc->sa_state); + /* NOTREACHED */ + break; + + case UCBSND_IDLE: + /* nothing to do */ + return 0; + + case UCBSND_INIT: + sc->sa_sf0ih = tx_intr_establish( + tc, MAKEINTR(1, TX39_INTRSTATUS1_SIBSF0INT), + IST_EDGE, IPL_TTY, ucbsnd_exec_output, sc); + + sc->sa_state = UCBSND_ENABLE_SAMPLERATE; + return 0; + + case UCBSND_ENABLE_SAMPLERATE: + /* Enable UCB1200 side sample rate */ + reg = TX39_SIBSF0_WRITE; + reg = TX39_SIBSF0_REGADDR_SET(reg, UCB1200_AUDIOCTRLA_REG); + reg = TX39_SIBSF0_REGDATA_SET(reg, sc->sa_snd_rate); + tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); + + sc->sa_state = UCBSND_ENABLE_OUTPUTPATH; + return 0; + + case UCBSND_ENABLE_OUTPUTPATH: + /* Enable UCB1200 side */ + reg = TX39_SIBSF0_WRITE; + reg = TX39_SIBSF0_REGADDR_SET(reg, UCB1200_AUDIOCTRLB_REG); + reg = TX39_SIBSF0_REGDATA_SET(reg, + UCB1200_AUDIOCTRLB_OUTEN); + tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); + + /* Enable SIB side */ + reg = tx_conf_read(tc, TX39_SIBCTRL_REG); + tx_conf_write(tc, TX39_SIBCTRL_REG, + reg | TX39_SIBCTRL_ENSND); + + sc->sa_state = UCBSND_ENABLE_SPEAKER0; + sc->sa_retry = 10; + return 0; + + case UCBSND_ENABLE_SPEAKER0: + /* Speaker on */ + + reg = TX39_SIBSF0_REGADDR_SET(0, UCB1200_IO_DATA_REG); + tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); + + sc->sa_state = UCBSND_ENABLE_SPEAKER1; + return 0; + + case UCBSND_ENABLE_SPEAKER1: + reg = tx_conf_read(tc, TX39_SIBSF0STAT_REG); + if ((TX39_SIBSF0_REGADDR(reg) != UCB1200_IO_DATA_REG) && + --sc->sa_retry > 0) { + + sc->sa_state = UCBSND_ENABLE_SPEAKER0; + return 0; + } + + if (sc->sa_retry <= 0) { + printf("ucbsnd_exec_output: subframe0 busy\n"); + + sc->sa_state = UCBSND_IDLE; + return 0; + } + + reg |= TX39_SIBSF0_WRITE; + reg |= UCB1200_IO_DATA_SPEAKER; + tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); + + sc->sa_state = UCBSND_TRANSITION_PIO; + sc->sa_cnt = 0; + return 0; + + case UCBSND_TRANSITION_PIO: + /* change interrupt source */ + tx_intr_disestablish(tc, sc->sa_sf0ih); + + sc->sa_sndih = tx_intr_establish( + tc, MAKEINTR(1, TX39_INTRSTATUS1_SNDININT), + IST_EDGE, IPL_TTY, ucbsnd_exec_output, sc); + sc->sa_enabled = 1; + + sc->sa_state = UCBSND_PIO; + return 0; + + case UCBSND_PIO: + sc->sa_cnt++; + + if ((sc->sa_cnt % 20) == 0) + tx_conf_write(tc, TX39_SIBSNDHOLD_REG, sc->sa_cnt + 5000); + else + tx_conf_write(tc, TX39_SIBSNDHOLD_REG, 0); + + tx_conf_write(tc, TX39_SIBSF0CTRL_REG, TX39_SIBSF0_SNDVALID); + + if (sc->sa_cnt > 1000) + sc->sa_state = UCBSND_TRANSITION_DISABLE; + + return 0; + + case UCBSND_TRANSITION_DISABLE: + /* change interrupt source */ + sc->sa_enabled = 0; + tx_intr_disestablish(tc, sc->sa_sndih); + sc->sa_sf0ih = tx_intr_establish( + tc, MAKEINTR(1, TX39_INTRSTATUS1_SIBSF0INT), + IST_EDGE, IPL_TTY, ucbsnd_exec_output, sc); + + sc->sa_state = UCBSND_DISABLE_OUTPUTPATH; + return 0; + + case UCBSND_DISABLE_OUTPUTPATH: + /* disable codec output path and mute */ + reg = TX39_SIBSF0_WRITE; + reg = TX39_SIBSF0_REGADDR_SET(reg, UCB1200_AUDIOCTRLB_REG); + reg = TX39_SIBSF0_REGDATA_SET(reg, UCB1200_AUDIOCTRLB_MUTE); + tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); + + sc->sa_state = UCBSND_DISABLE_SPEAKER0; + sc->sa_retry = 10; + return 0; + + case UCBSND_DISABLE_SPEAKER0: + /* Speaker off */ + reg = TX39_SIBSF0_REGADDR_SET(0, UCB1200_IO_DATA_REG); + tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); + + sc->sa_state = UCBSND_DISABLE_SPEAKER1; + return 0; + + case UCBSND_DISABLE_SPEAKER1: + reg = tx_conf_read(tc, TX39_SIBSF0STAT_REG); + if ((TX39_SIBSF0_REGADDR(reg) != UCB1200_IO_DATA_REG) && + --sc->sa_retry > 0) { + + sc->sa_state = UCBSND_DISABLE_SPEAKER0; + return 0; + } + + if (sc->sa_retry <= 0) { + printf("ucbsnd_exec_output: subframe0 busy\n"); + + sc->sa_state = UCBSND_IDLE; + return 0; + } + + reg |= TX39_SIBSF0_WRITE; + reg &= ~UCB1200_IO_DATA_SPEAKER; + tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); + + sc->sa_state = UCBSND_DISABLE_SIB; + return 0; + + case UCBSND_DISABLE_SIB: + /* Disable SIB side */ + reg = tx_conf_read(tc, TX39_SIBCTRL_REG); + reg &= ~TX39_SIBCTRL_ENSND; + tx_conf_write(tc, TX39_SIBCTRL_REG, reg); + + /* end audio disable sequence */ + tx_intr_disestablish(tc, sc->sa_sf0ih); + sc->sa_state = UCBSND_IDLE; + + return 0; + } + + return 0; +} + +/* + * global sound interface. + */ +void +ucbsnd_sound_init(sc) + struct ucbsnd_softc *sc; +{ + tx_sound_tag_t ts = &sc->sc_tag; + tx_chipset_tag_t tc = sc->sc_tc; + + ts->ts_v = sc; + ts->ts_click = __ucbsnd_sound_click; + + tx_conf_register_sound(tc, ts); +} + +void +__ucbsnd_sound_click(arg) + tx_sound_tag_t arg; +{ + struct ucbsnd_softc *sc = (void*)arg; + + if (sc->sa_state == UCBSND_IDLE) { + sc->sa_state = UCBSND_INIT; + ucbsnd_exec_output((void*)sc); + } +} + + diff --git a/sys/arch/hpcmips/dev/ucbtp.c b/sys/arch/hpcmips/dev/ucbtp.c new file mode 100644 index 000000000000..d71cff2cb9bd --- /dev/null +++ b/sys/arch/hpcmips/dev/ucbtp.c @@ -0,0 +1,732 @@ +/* $NetBSD: ucbtp.c,v 1.1 2000/01/12 14:56:21 uch Exp $ */ + +/* + * Copyright (c) 2000, by UCHIYAMA Yasushi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the developer may NOT be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * Device driver for PHILIPS UCB1200 Advanced modem/audio analog front-end + * Touch panel part. + */ +#define UCBTPDEBUG + +#include "opt_tx39_debug.h" +#include "opt_use_poll.h" + +#include +#include +#include + +#include +#include +#include /* bootinfo */ + +#include +#include + +#include + +#include +#include +#include +#include + +#ifdef TX391X +#include /* debug */ +#endif +#include +#include + +#include + +#ifdef UCBTPDEBUG +int ucbtp_debug = 1; +#define DPRINTF(arg) if (ucbtp_debug) printf arg; +#define DPRINTFN(n, arg) if (ucbtp_debug > (n)) printf arg; +#else +#define DPRINTF(arg) +#define DPRINTFN(n, arg) +#endif + +enum ucbts_stat { + UCBTS_STAT_DISABLE, + UCBTS_STAT_RELEASE, + UCBTS_STAT_TOUCH, + UCBTS_STAT_DRAG, +}; + +#define UCBTS_POSX 1 +#define UCBTS_POSY 2 +#define UCBTS_PRESS 3 + +#define UCBTS_PRESS_THRESHOLD 100 +#define UCBTS_TAP_THRESHOLD 5 + +enum ucbadc_state { +/* 0 */ UCBADC_IDLE, +/* 1 */ UCBADC_ADC_INIT, +/* 2 */ UCBADC_ADC_FINI, +/* 3 */ UCBADC_MEASUMENT_INIT, +/* 4 */ UCBADC_MEASUMENT_FINI, +/* 5 */ UCBADC_ADC_ENABLE, +/* 6 */ UCBADC_ADC_START0, +/* 7 */ UCBADC_ADC_START1, +/* 8 */ UCBADC_ADC_DATAREAD, +/* 9 */ UCBADC_ADC_DATAREAD_WAIT, +/*10 */ UCBADC_ADC_DISABLE, +/*11 */ UCBADC_ADC_INTRMODE, +/*12 */ UCBADC_ADC_INPUT, +/*13 */ UCBADC_INTR_ACK0, +/*14 */ UCBADC_INTR_ACK1, +/*15 */ UCBADC_INTR_ACK2, +/*16 */ UCBADC_REGREAD, +/*17 */ UCBADC_REGWRITE +}; + +struct ucbtp_softc { + struct device sc_dev; + struct device *sc_sib; /* parent (TX39 SIB module) */ + struct device *sc_ucb; /* parent (UCB1200 module) */ + tx_chipset_tag_t sc_tc; + + enum ucbts_stat sc_stat; + int sc_polling; + int sc_polling_finish; + void *sc_pollh; + + struct tpcalib_softc sc_tpcalib; + int sc_calibrated; + + /* measurement value */ + int sc_x, sc_y, sc_p; + int sc_ox, sc_oy; + + /* + * touch panel state machine + */ + void *sm_ih; /* TX39 SIB subframe 0 interrupt handler */ + + int sm_addr; /* UCB1200 register address */ + u_int32_t sm_reg; /* UCB1200 register data & TX39 SIB header */ + int sm_tmpreg; + int sm_retry; /* retry counter */ + + enum ucbadc_state sm_state; + int sm_measurement; /* X, Y, Pressure */ +#define UCBADC_MEASUREMENT_X 0 +#define UCBADC_MEASUREMENT_Y 1 +#define UCBADC_MEASUREMENT_PRESSURE 2 + int sm_returnstate; + + int sm_read_state, sm_write_state; + int sm_writing; /* writing state flag */ + u_int32_t sm_write_val; /* temporary buffer */ + + int sm_rw_retry; /* retry counter for r/w */ + + /* wsmouse */ + struct device *sc_wsmousedev; +}; + +int ucbtp_match __P((struct device*, struct cfdata*, void*)); +void ucbtp_attach __P((struct device*, struct device*, void*)); + +int ucbtp_sibintr __P((void*)); +int ucbtp_poll __P((void*)); +int ucbtp_adc_async __P((void*)); +int ucbtp_input __P((struct ucbtp_softc*)); +int ucbtp_busy __P((void*)); + +int ucbtp_enable __P((void*)); +int ucbtp_ioctl __P((void*, u_long, caddr_t, int, struct proc*)); +void ucbtp_disable __P((void*)); + +struct cfattach ucbtp_ca = { + sizeof(struct ucbtp_softc), ucbtp_match, ucbtp_attach +}; + +const struct wsmouse_accessops ucbtp_accessops = { + ucbtp_enable, + ucbtp_ioctl, + ucbtp_disable, +}; + +/* + * XXX currently no calibration method. this is temporary hack. + */ +#include + +struct wsmouse_calibcoords *calibration_sample_lookup __P((void)); +int ucbtp_calibration __P((struct ucbtp_softc*)); + +struct calibration_sample_table { + platid_t cst_platform; + struct wsmouse_calibcoords cst_sample; +} calibration_sample_table[] = { + {{{PLATID_WILD, PLATID_MACH_COMPAQ_C_8XX}}, /* uch machine */ + { 0, 0, 639, 239, 5, + {{ 507, 510, 320, 120 }, + { 898, 757, 40, 40 }, + { 900, 255, 40, 200 }, + { 109, 249, 600, 200 }, + { 110, 753, 600, 40 }}}}, + + {{{PLATID_WILD, PLATID_MACH_COMPAQ_C_2010}}, /* uch machine */ + { 0, 0, 639, 239, 5, + {{ 506, 487, 320, 120 }, + { 880, 250, 40, 40 }, + { 880, 718, 40, 200 }, + { 140, 726, 600, 200 }, + { 137, 250, 600, 40 }}}}, + + {{{PLATID_WILD, PLATID_MACH_SHARP_MOBILON_HC4100}}, /* uch machine */ + { 0, 0, 639, 239, 5, + {{ 497, 501, 320, 120 }, + { 752, 893, 40, 40 }, + { 242, 891, 40, 200 }, + { 241, 115, 600, 200 }, + { 747, 101, 600, 40 }}}}, + + {{{PLATID_UNKNOWN, PLATID_UNKNOWN}}, + { 0, 0, 639, 239, 5, + {{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}}}}, +}; + +struct wsmouse_calibcoords * +calibration_sample_lookup() +{ + struct calibration_sample_table *tab; + platid_mask_t mask; + + for (tab = calibration_sample_table; + tab->cst_platform.dw.dw1 != PLATID_UNKNOWN; tab++) { + + mask = PLATID_DEREF(&tab->cst_platform); + + if (platid_match(&platid, &mask)) { + return &tab->cst_sample; + } + } + + return 0; +} + +int +ucbtp_calibration(sc) + struct ucbtp_softc *sc; +{ + struct wsmouse_calibcoords *cs; +#ifdef TX391X + tx3912video_calibration_pattern(); /* debug */ +#endif + sc->sc_tpcalib.sc_maxx = bootinfo->fb_width - 1; + sc->sc_tpcalib.sc_maxy = bootinfo->fb_height - 1; + sc->sc_tpcalib.sc_minx = 0; + sc->sc_tpcalib.sc_miny = 0; + + tpcalib_init(&sc->sc_tpcalib); + + if (!(cs = calibration_sample_lookup())) { + printf("no calibration data"); + return 1; + } + + sc->sc_calibrated = + tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, + (caddr_t)cs, 0, 0) == 0 ? 1 : 0; + + if (!sc->sc_calibrated) + printf("not "); + printf("calibrated"); + + return 0; +} + +int +ucbtp_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + return 1; +} + +void +ucbtp_attach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct ucb1200_attach_args *ucba = aux; + struct ucbtp_softc *sc = (void*)self; + struct wsmousedev_attach_args wsmaa; + tx_chipset_tag_t tc; + + tc = sc->sc_tc = ucba->ucba_tc; + sc->sc_sib = ucba->ucba_sib; + sc->sc_ucb = ucba->ucba_ucb; + + printf(": "); + /* touch panel interrupt */ + tx_intr_establish(tc, MAKEINTR(1, TX39_INTRSTATUS1_SIBIRQPOSINT), + IST_EDGE, IPL_TTY, ucbtp_sibintr, sc); + + /* attempt to calibrate touch panel */ + ucbtp_calibration(sc); + + printf("\n"); + + wsmaa.accessops = &ucbtp_accessops; + wsmaa.accesscookie = sc; + + ucb1200_state_install(parent, ucbtp_busy, self, UCB1200_TP_MODULE); + + /* + * attach the wsmouse + */ + sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint); +} + +int +ucbtp_busy(arg) + void *arg; +{ + struct ucbtp_softc *sc = arg; + + return sc->sm_state != UCBADC_IDLE; +} + +int +ucbtp_poll(arg) + void *arg; +{ + struct ucbtp_softc *sc = arg; + + if (!ucb1200_state_idle(sc->sc_ucb)) /* subframe0 busy */ + return POLL_CONT; + + if (sc->sc_polling_finish) { + sc->sc_polling_finish = 0; + return POLL_END; + } + + /* execute A-D converter */ + sc->sm_state = UCBADC_ADC_INIT; + ucbtp_adc_async(sc); + + return POLL_CONT; +} + +int +ucbtp_sibintr(arg) + void *arg; +{ + struct ucbtp_softc *sc = arg; + + sc->sc_stat = UCBTS_STAT_TOUCH; + + /* click! */ + tx_sound_click(sc->sc_tc); + + /* invoke touch panel polling */ + if (!sc->sc_polling) { + sc->sc_pollh = tx39_poll_establish(sc->sc_tc, 1, IST_EDGE, + ucbtp_poll, sc); + if (!sc->sc_pollh) { + printf("%s: can't poll\n", sc->sc_dev.dv_xname); + } + } + + /* don't acknoledge interrupt until polling finish */ + + return 0; +} + +#define REGWRITE(addr, reg, ret) ( \ + sc->sm_addr = (addr), \ + sc->sm_reg = (reg), \ + sc->sm_returnstate = (ret),\ + sc->sm_state = UCBADC_REGWRITE) +#define REGREAD(addr, ret) ( \ + sc->sm_addr = (addr), \ + sc->sm_returnstate = (ret), \ + sc->sm_state = UCBADC_REGREAD) + +int +ucbtp_adc_async(arg) + void *arg; +{ + struct ucbtp_softc *sc = arg; + tx_chipset_tag_t tc = sc->sc_tc; + txreg_t reg; + u_int16_t reg16; + + DPRINTFN(9, ("state: %d\n", sc->sm_state)); + + switch (sc->sm_state) { + default: + panic("ucbtp_adc: invalid state %d", sc->sm_state); + /* NOTREACHED */ + break; + + case UCBADC_IDLE: + /* nothing to do */ + break; + + case UCBADC_ADC_INIT: + sc->sc_polling++; + sc->sc_stat = UCBTS_STAT_DRAG; + /* enable heart beat of this state machine */ + sc->sm_ih = tx_intr_establish( + tc, + MAKEINTR(1, TX39_INTRSTATUS1_SIBSF0INT), + IST_EDGE, IPL_TTY, ucbtp_adc_async, sc); + + sc->sm_state = UCBADC_MEASUMENT_INIT; + break; + + case UCBADC_ADC_FINI: + /* disable heart beat of this state machine */ + tx_intr_disestablish(tc, sc->sm_ih); + sc->sm_state = UCBADC_IDLE; + break; + + case UCBADC_MEASUMENT_INIT: + switch (sc->sm_measurement) { + default: + panic("unknown measurement spec."); + /* NOTREACHED */ + break; + case UCBADC_MEASUREMENT_X: + REGWRITE(UCB1200_TSCTRL_REG, + UCB1200_TSCTRL_XPOSITION, + UCBADC_ADC_ENABLE); + break; + case UCBADC_MEASUREMENT_Y: + REGWRITE(UCB1200_TSCTRL_REG, + UCB1200_TSCTRL_YPOSITION, + UCBADC_ADC_ENABLE); + break; + case UCBADC_MEASUREMENT_PRESSURE: + REGWRITE(UCB1200_TSCTRL_REG, + UCB1200_TSCTRL_PRESSURE, + UCBADC_ADC_ENABLE); + break; + } + break; + + case UCBADC_MEASUMENT_FINI: + switch (sc->sm_measurement) { + case UCBADC_MEASUREMENT_X: + sc->sm_measurement = UCBADC_MEASUREMENT_Y; + sc->sm_state = UCBADC_MEASUMENT_INIT; + break; + case UCBADC_MEASUREMENT_Y: + sc->sm_measurement = UCBADC_MEASUREMENT_PRESSURE; + sc->sm_state = UCBADC_MEASUMENT_INIT; + break; + case UCBADC_MEASUREMENT_PRESSURE: + sc->sm_measurement = UCBADC_MEASUREMENT_X; + /* measument complete. pass down to wsmouse_input */ + sc->sm_state = UCBADC_ADC_INPUT; + break; + } + break; + + case UCBADC_ADC_ENABLE: + switch (sc->sm_measurement) { + case UCBADC_MEASUREMENT_PRESSURE: + /* FALLTHROUGH */ + case UCBADC_MEASUREMENT_X: + sc->sm_tmpreg = UCB1200_ADCCTRL_INPUT_SET( + UCB1200_ADCCTRL_ENABLE, + UCB1200_ADCCTRL_INPUT_TSPX); + REGWRITE(UCB1200_ADCCTRL_REG, sc->sm_tmpreg, + UCBADC_ADC_START0); + break; + case UCBADC_MEASUREMENT_Y: + sc->sm_tmpreg = UCB1200_ADCCTRL_INPUT_SET( + UCB1200_ADCCTRL_ENABLE, + UCB1200_ADCCTRL_INPUT_TSPY); + REGWRITE(UCB1200_ADCCTRL_REG, sc->sm_tmpreg, + UCBADC_ADC_START0); + break; + } + break; + + case UCBADC_ADC_START0: + REGWRITE(UCB1200_ADCCTRL_REG, + sc->sm_tmpreg | UCB1200_ADCCTRL_START, + UCBADC_ADC_START1); + break; + + case UCBADC_ADC_START1: + REGWRITE(UCB1200_ADCCTRL_REG, + sc->sm_tmpreg, + UCBADC_ADC_DATAREAD); + sc->sm_retry = 100; + break; + + case UCBADC_ADC_DATAREAD: + REGREAD(UCB1200_ADCDATA_REG, UCBADC_ADC_DATAREAD_WAIT); + break; + + case UCBADC_ADC_DATAREAD_WAIT: + reg16 = TX39_SIBSF0_REGDATA(sc->sm_reg); + if (!(reg16 & UCB1200_ADCDATA_INPROGRESS) && + --sc->sm_retry > 0) { + sc->sm_state = UCBADC_ADC_DATAREAD; + } else { + if (sc->sm_retry <= 0) { + printf("dataread failed\n"); + sc->sm_state = UCBADC_ADC_FINI; + break; + } + + switch (sc->sm_measurement) { + case UCBADC_MEASUREMENT_X: + sc->sc_x = UCB1200_ADCDATA(reg16); + DPRINTFN(9, ("x=%d\n", sc->sc_x)); + break; + case UCBADC_MEASUREMENT_Y: + sc->sc_y = UCB1200_ADCDATA(reg16); + DPRINTFN(9, ("y=%d\n", sc->sc_y)); + break; + case UCBADC_MEASUREMENT_PRESSURE: + sc->sc_p = UCB1200_ADCDATA(reg16); + DPRINTFN(9, ("p=%d\n", sc->sc_p)); + break; + } + + sc->sm_state = UCBADC_ADC_DISABLE; + } + + break; + + case UCBADC_ADC_DISABLE: + REGWRITE(UCB1200_ADCCTRL_REG, 0, UCBADC_ADC_INTRMODE); + + break; + case UCBADC_ADC_INTRMODE: + REGWRITE(UCB1200_TSCTRL_REG, UCB1200_TSCTRL_INTERRUPT, + UCBADC_MEASUMENT_FINI); + break; + + case UCBADC_ADC_INPUT: + if (ucbtp_input(sc) == 0) + sc->sm_state = UCBADC_ADC_FINI; + else + sc->sm_state = UCBADC_INTR_ACK0; + break; + + case UCBADC_INTR_ACK0: + REGREAD(UCB1200_INTSTAT_REG, UCBADC_INTR_ACK1); + break; + + case UCBADC_INTR_ACK1: + REGWRITE(UCB1200_INTSTAT_REG, sc->sm_reg, UCBADC_INTR_ACK2); + break; + + case UCBADC_INTR_ACK2: + sc->sc_polling_finish = 1; + REGWRITE(UCB1200_INTSTAT_REG, 0, UCBADC_ADC_FINI); + break; + + /* + * UCB1200 register access state + */ + case UCBADC_REGREAD: + /* + * In : sc->sm_addr + * Out : sc->sm_reg (with SIBtag) + */ +#define TXSIB_REGREAD_INIT 0 +#define TXSIB_REGREAD_READ 1 + switch (sc->sm_read_state) { + case TXSIB_REGREAD_INIT: + reg = TX39_SIBSF0_REGADDR_SET(0, sc->sm_addr); + tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); + sc->sm_rw_retry = 100; + sc->sm_read_state = TXSIB_REGREAD_READ; + break; + case TXSIB_REGREAD_READ: + reg = tx_conf_read(tc, TX39_SIBSF0STAT_REG); + if ((TX39_SIBSF0_REGADDR(reg) != sc->sm_addr) && + --sc->sm_rw_retry > 0) { + printf("retry!\n"); + break; + } + + if (sc->sm_rw_retry <= 0) { + printf("sf0read: command failed\n"); + sc->sm_state = UCBADC_ADC_FINI; + } else { + sc->sm_reg = reg; + sc->sm_read_state = TXSIB_REGREAD_INIT; + DPRINTFN(9, ("%08x\n", reg)); + if (sc->sm_writing) + sc->sm_state = UCBADC_REGWRITE; + else + sc->sm_state = sc->sm_returnstate; + } + break; + } + break; + + case UCBADC_REGWRITE: + /* + * In : sc->sm_addr, sc->sm_reg (lower 16bit only) + */ +#define TXSIB_REGWRITE_INIT 0 +#define TXSIB_REGWRITE_WRITE 1 + switch (sc->sm_write_state) { + case TXSIB_REGWRITE_INIT: + sc->sm_writing = 1; + sc->sm_write_state = TXSIB_REGWRITE_WRITE; + sc->sm_state = UCBADC_REGREAD; + + sc->sm_write_val = sc->sm_reg; + break; + case TXSIB_REGWRITE_WRITE: + sc->sm_writing = 0; + sc->sm_write_state = TXSIB_REGWRITE_INIT; + sc->sm_state = sc->sm_returnstate; + + reg = sc->sm_reg; + reg |= TX39_SIBSF0_WRITE; + TX39_SIBSF0_REGDATA_CLR(reg); + reg = TX39_SIBSF0_REGDATA_SET(reg, sc->sm_write_val); + tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); + break; + } + break; + } + + return 0; +} + +int +ucbtp_input(sc) + struct ucbtp_softc *sc; +{ + int x, y; + + if (!sc->sc_calibrated) { /* XXX definitely no problem */ + printf("ucbtp_input: no calibration data\n"); + return 1; + } + + tpcalib_trans(&sc->sc_tpcalib, sc->sc_x, sc->sc_y, &x, &y); + DPRINTFN(1, ("x: %d->%d y: %d->%d pressure=%d\n", + sc->sc_x, x, sc->sc_y, y, sc->sc_p)); + + if (sc->sc_p < UCBTS_PRESS_THRESHOLD) { + sc->sc_stat = UCBTS_STAT_RELEASE; + if (sc->sc_polling < UCBTS_TAP_THRESHOLD) { + DPRINTFN(1, ("TAP!\n")); + /* button 0 DOWN */ + wsmouse_input(sc->sc_wsmousedev, 1, 0, 0, 0, 0); + /* button 0 UP */ + wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0); + } else { + wsmouse_input(sc->sc_wsmousedev, 0, + sc->sc_ox, sc->sc_oy, 0, + WSMOUSE_INPUT_ABSOLUTE_X | + WSMOUSE_INPUT_ABSOLUTE_Y); + + DPRINTFN(1, ("RELEASE\n")); + } + sc->sc_polling = 0; + + return 1; + } + +#ifdef TX391X /* debug */ + if (sc->sc_polling == 1) + tx3912video_dot(x, y); + else + tx3912video_line(sc->sc_ox, sc->sc_oy, x, y); + sc->sc_ox = x, sc->sc_oy = y; +#endif + wsmouse_input(sc->sc_wsmousedev, 1, x, y, 0, + WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); + + return 0; +} + +/* + * access ops. + */ + +int +ucbtp_enable(v) + void *v; +{ + /* not yet */ + return 0; +} + +void +ucbtp_disable(v) + void *v; +{ + /* not yet */ +} + +int +ucbtp_ioctl(v, cmd, data, flag, p) + void *v; + u_long cmd; + caddr_t data; + int flag; + struct proc *p; +{ + struct ucbtp_softc *sc = v; + + DPRINTF(("%s(%d): ucbtp_ioctl(%08lx)\n", __FILE__, __LINE__, cmd)); + + switch (cmd) { + case WSMOUSEIO_GTYPE: + *(u_int *)data = WSMOUSE_TYPE_TPANEL; + break; + + case WSMOUSEIO_SRES: + printf("%s(%d): WSMOUSRIO_SRES is not supported", + __FILE__, __LINE__); + break; + + case WSMOUSEIO_SCALIBCOORDS: + case WSMOUSEIO_GCALIBCOORDS: + return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p); + + default: + return (-1); + } + return (0); +} diff --git a/sys/arch/hpcmips/tx/tx39.c b/sys/arch/hpcmips/tx/tx39.c index 1f74b995649e..5ed05c199b9b 100644 --- a/sys/arch/hpcmips/tx/tx39.c +++ b/sys/arch/hpcmips/tx/tx39.c @@ -1,4 +1,4 @@ -/* $NetBSD: tx39.c,v 1.10 2000/01/07 15:19:14 uch Exp $ */ +/* $NetBSD: tx39.c,v 1.11 2000/01/12 14:56:19 uch Exp $ */ /* * Copyright (c) 1999, 2000, by UCHIYAMA Yasushi @@ -373,6 +373,18 @@ tx_conf_register_clock(t, clockt) tx_chipset.tc_clockt = clockt; } +void +tx_conf_register_sound(t, soundt) + tx_chipset_tag_t t; + void *soundt; +{ + if (t != &tx_chipset) { + panic("bogus tx_chipset_tag"); + } + + tx_chipset.tc_soundt = soundt; +} + #ifdef TX39_PREFER_FUNCTION tx_chipset_tag_t tx_conf_get_tag() diff --git a/sys/arch/hpcmips/tx/tx39sib.c b/sys/arch/hpcmips/tx/tx39sib.c index 6f47561d0a18..96079f931d95 100644 --- a/sys/arch/hpcmips/tx/tx39sib.c +++ b/sys/arch/hpcmips/tx/tx39sib.c @@ -1,4 +1,4 @@ -/* $NetBSD: tx39sib.c,v 1.1 2000/01/08 21:07:02 uch Exp $ */ +/* $NetBSD: tx39sib.c,v 1.2 2000/01/12 14:56:19 uch Exp $ */ /* * Copyright (c) 2000, by UCHIYAMA Yasushi @@ -29,7 +29,7 @@ /* * TX39 SIB (Serial Interface Bus) module. */ - +#undef TX39SIBDEBUG #include "opt_tx39_debug.h" #include @@ -58,10 +58,55 @@ void tx39sib_attach __P((struct device*, struct device*, void*)); int tx39sib_print __P((void*, const char*)); int tx39sib_search __P((struct device*, struct cfdata*, void*)); +#define TX39_CLK2X 18432000 +const int sibsclk_divide_table[8] = { + 2, 3, 4, 5, 6, 8, 10, 12 +}; + +struct tx39sib_param { + /* SIB clock rate */ + int sp_clock; +/* + * SIBMCLK = 18.432MHz = (CLK2X /4) + * SIBSCLK = SIBMCLK / sp_clock + * sp_clock start end divide module + * 0 7 8 2 + * 1 6 8 3 + * 2 6 9 4 + * 3 5 9 5 + * 4 5 10 6 + * 5 4 11 8 + * 6 3 12 10 + * 7 2 13 12 + */ + /* sampling rate */ + int sp_snd_rate; /* SNDFSDIV + 1 */ + int sp_tel_rate; /* TELFSDIV + 1 */ +/* + * Fs = (SIBSCLK * 2) / ((FSDIV + 1) * 64 + * FSDIV + 1 sampling rate + * 15 19.2k (1.6% error vs. CD-XA) + * 13 22.154k (0.47% error vs. CD-Audio) + * 22 7.85k (1.8% error vs. 8k) + */ + /* data format 16/8bit */ + int sp_sf0sndmode; + int sp_sf0telmode; +}; + +struct tx39sib_param tx39sib_param_default = { + 0, /* SIBSCLK = 9.216MHz */ + 13, /* audio: CD-Audio */ + 40, /* telecom: 7.2kHz */ + TX39_SIBCTRL_SND16, /* Audio 16bit mono */ + TX39_SIBCTRL_TEL16 /* Telecom 16bit mono */ +}; + struct tx39sib_softc { struct device sc_dev; tx_chipset_tag_t sc_tc; + struct tx39sib_param sc_param; int sc_attached; }; @@ -90,38 +135,122 @@ tx39sib_attach(parent, self, aux) struct txsim_attach_args *ta = aux; struct tx39sib_softc *sc = (void*)self; tx_chipset_tag_t tc; - txreg_t reg; - + sc->sc_tc = tc = ta->ta_tc; + /* set default param */ + sc->sc_param = tx39sib_param_default; +#define MHZ(a) ((a) / 1000000), (((a) % 1000000) / 1000) + printf(": %d.%03d MHz", MHZ(tx39sib_clock(self))); + printf("\n"); #ifdef TX39SIBDEBUG tx39sib_dump(sc); #endif - /* - * Enable subframe0 (UCB1200) - */ - reg = tx_conf_read(tc, TX39_SIBCTRL_REG); - reg |= TX39_SIBCTRL_ENSF0; - tx_conf_write(tc, TX39_SIBCTRL_REG, reg); + /* enable subframe0 */ + tx39sib_enable1(self); + /* enable SIB */ + tx39sib_enable2(self); - /* - * Disable subframe1 (external codec) - */ - reg = tx_conf_read(tc, TX39_SIBCTRL_REG); - reg &= ~TX39_SIBCTRL_ENSF1; - tx_conf_write(tc, TX39_SIBCTRL_REG, reg); - - /* - * Enable SIB module - */ - reg = tx_conf_read(tc, TX39_SIBCTRL_REG); - reg |= TX39_SIBCTRL_ENSIB; - tx_conf_write(tc, TX39_SIBCTRL_REG, reg); +#ifdef TX39SIBDEBUG + tx39sib_dump(sc); +#endif config_search(tx39sib_search, self, tx39sib_print); } +void +tx39sib_enable1(dev) + struct device *dev; +{ + struct tx39sib_softc *sc = (void*)dev; + struct tx39sib_param *param = &sc->sc_param; + tx_chipset_tag_t tc = sc->sc_tc; + + txreg_t reg; + + /* disable SIB */ + tx39sib_disable(dev); + + /* setup */ + reg = 0; + /* SIB clock rate */ + reg = TX39_SIBCTRL_SCLKDIV_SET(reg, param->sp_clock); + /* sampling rate (sound) */ + reg = TX39_SIBCTRL_SNDFSDIV_SET(reg, param->sp_snd_rate - 1); + /* sampling rate (telecom) */ + reg = TX39_SIBCTRL_TELFSDIV_SET(reg, param->sp_tel_rate - 1); + /* data format (8/16bit) */ + reg |= param->sp_sf0sndmode; + reg |= param->sp_sf0telmode; + tx_conf_write(tc, TX39_SIBCTRL_REG, reg); + + /* DMA */ + reg = tx_conf_read(tc, TX39_SIBDMACTRL_REG); + reg &= ~(TX39_SIBDMACTRL_ENDMARXSND | + TX39_SIBDMACTRL_ENDMATXSND | + TX39_SIBDMACTRL_ENDMARXTEL | + TX39_SIBDMACTRL_ENDMATXTEL); + tx_conf_write(tc, TX39_SIBDMACTRL_REG, reg); + + /* + * Enable subframe0 (BETTY) + */ + reg = tx_conf_read(tc, TX39_SIBCTRL_REG); + reg |= TX39_SIBCTRL_ENSF0; + tx_conf_write(tc, TX39_SIBCTRL_REG, reg); +} + +void +tx39sib_enable2(dev) + struct device *dev; +{ + struct tx39sib_softc *sc = (void*)dev; + tx_chipset_tag_t tc = sc->sc_tc; + txreg_t reg; + + reg = tx_conf_read(tc, TX39_SIBCTRL_REG); + reg |= TX39_SIBCTRL_ENSIB; + tx_conf_write(tc, TX39_SIBCTRL_REG, reg); +} + +void +tx39sib_disable(dev) + struct device *dev; +{ + struct tx39sib_softc *sc = (void*)dev; + tx_chipset_tag_t tc = sc->sc_tc; + txreg_t reg; + /* disable codec side */ + /* notyet */ + + /* disable TX39 side */ + reg = tx_conf_read(tc, TX39_SIBCTRL_REG); + reg &= ~(TX39_SIBCTRL_ENTEL | TX39_SIBCTRL_ENSND); + tx_conf_write(tc, TX39_SIBCTRL_REG, reg); + + /* + * Disable subframe0/1 (BETTY/external codec) + */ + reg = tx_conf_read(tc, TX39_SIBCTRL_REG); + reg &= ~TX39_SIBCTRL_ENSF0; + reg &= ~(TX39_SIBCTRL_ENSF1 | TX39_SIBCTRL_SELTELSF1 | + TX39_SIBCTRL_SELSNDSF1); + tx_conf_write(tc, TX39_SIBCTRL_REG, reg); + + /* disable TX39SIB module */ + reg &= ~TX39_SIBCTRL_ENSIB; + tx_conf_write(tc, TX39_SIBCTRL_REG, reg); +} + +int +tx39sib_clock(dev) + struct device *dev; +{ + struct tx39sib_softc *sc = (void*)dev; + + return TX39_CLK2X / sibsclk_divide_table[sc->sc_param.sp_clock]; +} int tx39sib_search(parent, cf, aux) @@ -134,6 +263,8 @@ tx39sib_search(parent, cf, aux) sa.sa_tc = sc->sc_tc; sa.sa_slot = cf->cf_loc[TXSIBIFCF_SLOT]; + sa.sa_snd_rate = sc->sc_param.sp_snd_rate; + sa.sa_tel_rate = sc->sc_param.sp_tel_rate; if (sa.sa_slot == TXSIBIFCF_SLOT_DEFAULT) { printf("tx39sib_search: wildcarded slot, skipping\n"); diff --git a/sys/arch/hpcmips/tx/tx39sibvar.h b/sys/arch/hpcmips/tx/tx39sibvar.h index 75a01e58c04e..ab13d278881a 100644 --- a/sys/arch/hpcmips/tx/tx39sibvar.h +++ b/sys/arch/hpcmips/tx/tx39sibvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: tx39sibvar.h,v 1.1 2000/01/08 21:07:02 uch Exp $ */ +/* $NetBSD: tx39sibvar.h,v 1.2 2000/01/12 14:56:19 uch Exp $ */ /* * Copyright (c) 2000, by UCHIYAMA Yasushi @@ -28,10 +28,18 @@ struct txsib_attach_args { tx_chipset_tag_t sa_tc; + int sa_snd_rate; + int sa_tel_rate; int sa_slot; /* subframe 0 or subframe 1 */ }; +void tx39sib_enable1 __P((struct device*)); +void tx39sib_enable2 __P((struct device*)); +void tx39sib_disable __P((struct device*)); +int tx39sib_clock __P((struct device*)); + /* subframe0 access sync method */ void txsibsf0_reg_write __P((tx_chipset_tag_t, int, u_int16_t)); u_int16_t txsibsf0_reg_read __P((tx_chipset_tag_t, int)); u_int32_t txsibsf0_read __P((tx_chipset_tag_t, int)); + diff --git a/sys/arch/hpcmips/tx/tx39var.h b/sys/arch/hpcmips/tx/tx39var.h index a8012f03854f..041776e019e4 100644 --- a/sys/arch/hpcmips/tx/tx39var.h +++ b/sys/arch/hpcmips/tx/tx39var.h @@ -1,4 +1,4 @@ -/* $NetBSD: tx39var.h,v 1.3 2000/01/03 18:24:05 uch Exp $ */ +/* $NetBSD: tx39var.h,v 1.4 2000/01/12 14:56:19 uch Exp $ */ /* * Copyright (c) 1999, 2000 by UCHIYAMA Yasushi @@ -30,6 +30,7 @@ struct tx_chipset_tag { void *tc_intrt; /* interrupt tag */ void *tc_powert; /* power tag */ void *tc_clockt; /* clock/timer tag */ + void *tc_soundt; /* sound tag */ }; typedef struct tx_chipset_tag* tx_chipset_tag_t; @@ -38,6 +39,7 @@ typedef u_int32_t txreg_t; void tx_conf_register_intr __P((tx_chipset_tag_t, void*)); void tx_conf_register_power __P((tx_chipset_tag_t, void*)); void tx_conf_register_clock __P((tx_chipset_tag_t, void*)); +void tx_conf_register_sound __P((tx_chipset_tag_t, void*)); /* * TX39 Internal Function Register access diff --git a/sys/arch/hpcmips/tx/txsim.c b/sys/arch/hpcmips/tx/txsim.c index cf7b9fabd1b4..4bc7cc2205ec 100644 --- a/sys/arch/hpcmips/tx/txsim.c +++ b/sys/arch/hpcmips/tx/txsim.c @@ -1,4 +1,4 @@ -/* $NetBSD: txsim.c,v 1.1 1999/11/20 19:56:40 uch Exp $ */ +/* $NetBSD: txsim.c,v 1.2 2000/01/12 14:56:20 uch Exp $ */ /* * Copyright (c) 1999, by UCHIYAMA Yasushi @@ -39,6 +39,7 @@ #include #include +#include int txsim_match __P((struct device*, struct cfdata*, void*)); void txsim_attach __P((struct device*, struct device*, void*)); @@ -76,6 +77,8 @@ txsim_attach(parent, self, aux) struct txsim_softc *sc = (void*)self; printf("\n"); + + tx_sound_init(tx_conf_get_tag()); /* * interrupt, clock module is used by other system module. * so attach first. diff --git a/sys/arch/hpcmips/tx/txsnd.c b/sys/arch/hpcmips/tx/txsnd.c new file mode 100644 index 000000000000..20270e09237d --- /dev/null +++ b/sys/arch/hpcmips/tx/txsnd.c @@ -0,0 +1,52 @@ +/* $NetBSD: txsnd.c,v 1.1 2000/01/12 14:56:18 uch Exp $ */ + +/* + * Copyright (c) 2000, by UCHIYAMA Yasushi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the developer may NOT be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include +#include +#include + +#include +#include + +struct tx_sound_tag __tx_sound_default; +void __tx_sound_click __P((tx_sound_tag_t)); + +void +tx_sound_init(tc) + tx_chipset_tag_t tc; +{ + __tx_sound_default.ts_v = NULL; + __tx_sound_default.ts_click = __tx_sound_click; + + tx_conf_register_sound(tc, &__tx_sound_default); +} + +void +__tx_sound_click(arg) + tx_sound_tag_t arg; +{ +} diff --git a/sys/arch/hpcmips/tx/txsnd.h b/sys/arch/hpcmips/tx/txsnd.h new file mode 100644 index 000000000000..d2530ce8e7f7 --- /dev/null +++ b/sys/arch/hpcmips/tx/txsnd.h @@ -0,0 +1,41 @@ +/* $NetBSD: txsnd.h,v 1.1 2000/01/12 14:56:17 uch Exp $ */ + +/* + * Copyright (c) 2000, by UCHIYAMA Yasushi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the developer may NOT be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +typedef struct tx_sound_tag *tx_sound_tag_t; + +struct tx_sound_tag { + void *ts_v; + + void (*ts_click) __P((tx_sound_tag_t)); +}; + +#define tx_sound_click(t) \ + (*((tx_sound_tag_t)(t->tc_soundt))->ts_click) \ + (((tx_sound_tag_t)(t->tc_soundt))->ts_v) + +void tx_sound_init __P((tx_chipset_tag_t));