add UCB1200 sound module ucbsnd (core implementation only)

UCB1200 touch panel module moved to ucbtp and sync with vrpiu.
This commit is contained in:
uch 2000-01-12 14:56:17 +00:00
parent e7f230b6d2
commit dce2bc94e0
15 changed files with 1594 additions and 733 deletions

View File

@ -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

View File

@ -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

View File

@ -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 <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
@ -47,6 +49,11 @@
#include <hpcmips/dev/skbdvar.h>
#include <hpcmips/dev/skbdkeymap.h>
#ifdef TX39XX
#include <hpcmips/tx/tx39var.h>
#include <hpcmips/tx/txsnd.h>
#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);

View File

@ -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 <sys/param.h>
#include <sys/systm.h>
@ -40,17 +38,10 @@
#include <machine/bus.h>
#include <machine/intr.h>
#include <machine/bootinfo.h> /* bootinfo */
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsmousevar.h>
#include <hpcmips/tx/tx39var.h>
#include <hpcmips/tx/tx39sibvar.h>
#include <hpcmips/tx/tx39sibreg.h>
#include <hpcmips/tx/tx39icureg.h>
#include <hpcmips/tx/tx3912videovar.h> /* debug */
#include <hpcmips/dev/ucb1200var.h>
#include <hpcmips/dev/ucb1200reg.h>
@ -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 <machine/platid.h>
#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);

View File

@ -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

View File

@ -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*));

View File

@ -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 <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <machine/bus.h>
#include <machine/intr.h>
#include <hpcmips/tx/tx39var.h>
#include <hpcmips/tx/tx39sibvar.h>
#include <hpcmips/tx/tx39sibreg.h>
#include <hpcmips/tx/tx39icureg.h>
#include <hpcmips/tx/txsnd.h>
#include <hpcmips/dev/ucb1200var.h>
#include <hpcmips/dev/ucb1200reg.h>
#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);
}
}

View File

@ -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 <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <machine/bus.h>
#include <machine/intr.h>
#include <machine/bootinfo.h> /* bootinfo */
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsmousevar.h>
#include <hpcmips/dev/tpcalibvar.h>
#include <hpcmips/tx/tx39var.h>
#include <hpcmips/tx/tx39sibvar.h>
#include <hpcmips/tx/tx39sibreg.h>
#include <hpcmips/tx/tx39icureg.h>
#ifdef TX391X
#include <hpcmips/tx/tx3912videovar.h> /* debug */
#endif
#include <hpcmips/dev/ucb1200var.h>
#include <hpcmips/dev/ucb1200reg.h>
#include <hpcmips/tx/txsnd.h>
#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 <machine/platid.h>
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);
}

View File

@ -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()

View File

@ -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 <sys/param.h>
@ -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");

View File

@ -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));

View File

@ -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

View File

@ -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 <machine/autoconf.h>
#include <hpcmips/tx/tx39var.h>
#include <hpcmips/tx/txsnd.h>
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.

View File

@ -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 <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <hpcmips/tx/tx39var.h>
#include <hpcmips/tx/txsnd.h>
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;
{
}

View File

@ -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));