⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tsc210x.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * TI TSC2102 (touchscreen/sensors/audio controller) emulator. * TI TSC2301 (touchscreen/sensors/keypad). * * Copyright (c) 2006 Andrzej Zaborowski  <balrog@zabor.org> * Copyright (C) 2008 Nokia Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include "hw.h"#include "audio/audio.h"#include "qemu-timer.h"#include "console.h"#include "omap.h"	/* For struct i2s_codec_s and struct uwire_slave_s */#define TSC_DATA_REGISTERS_PAGE		0x0#define TSC_CONTROL_REGISTERS_PAGE	0x1#define TSC_AUDIO_REGISTERS_PAGE	0x2#define TSC_VERBOSE#define TSC_CUT_RESOLUTION(value, p)	((value) >> (16 - resolution[p]))struct tsc210x_state_s {    qemu_irq pint;    qemu_irq kbint;    qemu_irq davint;    QEMUTimer *timer;    QEMUSoundCard card;    struct uwire_slave_s chip;    struct i2s_codec_s codec;    uint8_t in_fifo[16384];    uint8_t out_fifo[16384];    uint16_t model;    int x, y;    int pressure;    int state, page, offset, irq;    uint16_t command, dav;    int busy;    int enabled;    int host_mode;    int function;    int nextfunction;    int precision;    int nextprecision;    int filter;    int pin_func;    int ref;    int timing;    int noise;    uint16_t audio_ctrl1;    uint16_t audio_ctrl2;    uint16_t audio_ctrl3;    uint16_t pll[3];    uint16_t volume;    int64_t volume_change;    int softstep;    uint16_t dac_power;    int64_t powerdown;    uint16_t filter_data[0x14];    const char *name;    SWVoiceIn *adc_voice[1];    SWVoiceOut *dac_voice[1];    int i2s_rx_rate;    int i2s_tx_rate;    AudioState *audio;    int tr[8];    struct {        uint16_t down;        uint16_t mask;        int scan;        int debounce;        int mode;        int intr;    } kb;};static const int resolution[4] = { 12, 8, 10, 12 };#define TSC_MODE_NO_SCAN	0x0#define TSC_MODE_XY_SCAN	0x1#define TSC_MODE_XYZ_SCAN	0x2#define TSC_MODE_X		0x3#define TSC_MODE_Y		0x4#define TSC_MODE_Z		0x5#define TSC_MODE_BAT1		0x6#define TSC_MODE_BAT2		0x7#define TSC_MODE_AUX		0x8#define TSC_MODE_AUX_SCAN	0x9#define TSC_MODE_TEMP1		0xa#define TSC_MODE_PORT_SCAN	0xb#define TSC_MODE_TEMP2		0xc#define TSC_MODE_XX_DRV		0xd#define TSC_MODE_YY_DRV		0xe#define TSC_MODE_YX_DRV		0xfstatic const uint16_t mode_regs[16] = {    0x0000,	/* No scan */    0x0600,	/* X, Y scan */    0x0780,	/* X, Y, Z scan */    0x0400,	/* X */    0x0200,	/* Y */    0x0180,	/* Z */    0x0040,	/* BAT1 */    0x0030,	/* BAT2 */    0x0010,	/* AUX */    0x0010,	/* AUX scan */    0x0004,	/* TEMP1 */    0x0070,	/* Port scan */    0x0002,	/* TEMP2 */    0x0000,	/* X+, X- drivers */    0x0000,	/* Y+, Y- drivers */    0x0000,	/* Y+, X- drivers */};#define X_TRANSFORM(s)			\    ((s->y * s->tr[0] - s->x * s->tr[1]) / s->tr[2] + s->tr[3])#define Y_TRANSFORM(s)			\    ((s->y * s->tr[4] - s->x * s->tr[5]) / s->tr[6] + s->tr[7])#define Z1_TRANSFORM(s)			\    ((400 - ((s)->x >> 7) + ((s)->pressure << 10)) << 4)#define Z2_TRANSFORM(s)			\    ((4000 + ((s)->y >> 7) - ((s)->pressure << 10)) << 4)#define BAT1_VAL			0x8660#define BAT2_VAL			0x0000#define AUX1_VAL			0x35c0#define AUX2_VAL			0xffff#define TEMP1_VAL			0x8c70#define TEMP2_VAL			0xa5b0#define TSC_POWEROFF_DELAY		50#define TSC_SOFTSTEP_DELAY		50static void tsc210x_reset(struct tsc210x_state_s *s){    s->state = 0;    s->pin_func = 2;    s->enabled = 0;    s->busy = 0;    s->nextfunction = 0;    s->ref = 0;    s->timing = 0;    s->irq = 0;    s->dav = 0;    s->audio_ctrl1 = 0x0000;    s->audio_ctrl2 = 0x4410;    s->audio_ctrl3 = 0x0000;    s->pll[0] = 0x1004;    s->pll[1] = 0x0000;    s->pll[2] = 0x1fff;    s->volume = 0xffff;    s->dac_power = 0x8540;    s->softstep = 1;    s->volume_change = 0;    s->powerdown = 0;    s->filter_data[0x00] = 0x6be3;    s->filter_data[0x01] = 0x9666;    s->filter_data[0x02] = 0x675d;    s->filter_data[0x03] = 0x6be3;    s->filter_data[0x04] = 0x9666;    s->filter_data[0x05] = 0x675d;    s->filter_data[0x06] = 0x7d83;    s->filter_data[0x07] = 0x84ee;    s->filter_data[0x08] = 0x7d83;    s->filter_data[0x09] = 0x84ee;    s->filter_data[0x0a] = 0x6be3;    s->filter_data[0x0b] = 0x9666;    s->filter_data[0x0c] = 0x675d;    s->filter_data[0x0d] = 0x6be3;    s->filter_data[0x0e] = 0x9666;    s->filter_data[0x0f] = 0x675d;    s->filter_data[0x10] = 0x7d83;    s->filter_data[0x11] = 0x84ee;    s->filter_data[0x12] = 0x7d83;    s->filter_data[0x13] = 0x84ee;    s->i2s_tx_rate = 0;    s->i2s_rx_rate = 0;    s->kb.scan = 1;    s->kb.debounce = 0;    s->kb.mask = 0x0000;    s->kb.mode = 3;    s->kb.intr = 0;    qemu_set_irq(s->pint, !s->irq);    qemu_set_irq(s->davint, !s->dav);    qemu_irq_raise(s->kbint);}struct tsc210x_rate_info_s {    int rate;    int dsor;    int fsref;};/*  { rate,  dsor,  fsref } */static const struct tsc210x_rate_info_s tsc2101_rates[] = {    /* Fsref / 6.0 */    { 7350,	7,	1 },    { 8000,	7,	0 },    /* Fsref / 5.5 */    { 8018,	6,	1 },    { 8727,	6,	0 },    /* Fsref / 5.0 */    { 8820,	5,	1 },    { 9600,	5,	0 },    /* Fsref / 4.0 */    { 11025,	4,	1 },    { 12000,	4,	0 },    /* Fsref / 3.0 */    { 14700,	3,	1 },    { 16000,	3,	0 },    /* Fsref / 2.0 */    { 22050,	2,	1 },    { 24000,	2,	0 },    /* Fsref / 1.5 */    { 29400,	1,	1 },    { 32000,	1,	0 },    /* Fsref */    { 44100,	0,	1 },    { 48000,	0,	0 },    { 0,	0, 	0 },};/*  { rate,   dsor, fsref }	*/static const struct tsc210x_rate_info_s tsc2102_rates[] = {    /* Fsref / 6.0 */    { 7350,	63,	1 },    { 8000,	63,	0 },    /* Fsref / 6.0 */    { 7350,	54,	1 },    { 8000,	54,	0 },    /* Fsref / 5.0 */    { 8820,	45,	1 },    { 9600,	45,	0 },    /* Fsref / 4.0 */    { 11025,	36,	1 },    { 12000,	36,	0 },    /* Fsref / 3.0 */    { 14700,	27,	1 },    { 16000,	27,	0 },    /* Fsref / 2.0 */    { 22050,	18,	1 },    { 24000,	18,	0 },    /* Fsref / 1.5 */    { 29400,	9,	1 },    { 32000,	9,	0 },    /* Fsref */    { 44100,	0,	1 },    { 48000,	0,	0 },    { 0,	0, 	0 },};static inline void tsc210x_out_flush(struct tsc210x_state_s *s, int len){    uint8_t *data = s->codec.out.fifo + s->codec.out.start;    uint8_t *end = data + len;    while (data < end)        data += AUD_write(s->dac_voice[0], data, end - data) ?: (end - data);    s->codec.out.len -= len;    if (s->codec.out.len)        memmove(s->codec.out.fifo, end, s->codec.out.len);    s->codec.out.start = 0;}static void tsc210x_audio_out_cb(struct tsc210x_state_s *s, int free_b){    if (s->codec.out.len >= free_b) {        tsc210x_out_flush(s, free_b);        return;    }    s->codec.out.size = MIN(free_b, 16384);    qemu_irq_raise(s->codec.tx_start);}static void tsc2102_audio_rate_update(struct tsc210x_state_s *s){    const struct tsc210x_rate_info_s *rate;    s->codec.tx_rate = 0;    s->codec.rx_rate = 0;    if (s->dac_power & (1 << 15))				/* PWDNC */        return;    for (rate = tsc2102_rates; rate->rate; rate ++)        if (rate->dsor == (s->audio_ctrl1 & 0x3f) &&		/* DACFS */                        rate->fsref == ((s->audio_ctrl3 >> 13) & 1))/* REFFS */            break;    if (!rate->rate) {        printf("%s: unknown sampling rate configured\n", __FUNCTION__);        return;    }    s->codec.tx_rate = rate->rate;}static void tsc2102_audio_output_update(struct tsc210x_state_s *s){    int enable;    audsettings_t fmt;    if (s->dac_voice[0]) {        tsc210x_out_flush(s, s->codec.out.len);        s->codec.out.size = 0;        AUD_set_active_out(s->dac_voice[0], 0);        AUD_close_out(&s->card, s->dac_voice[0]);        s->dac_voice[0] = 0;    }    s->codec.cts = 0;    enable =            (~s->dac_power & (1 << 15)) &&			/* PWDNC */            (~s->dac_power & (1 << 10));			/* DAPWDN */    if (!enable || !s->codec.tx_rate)        return;    /* Force our own sampling rate even in slave DAC mode */    fmt.endianness = 0;    fmt.nchannels = 2;    fmt.freq = s->codec.tx_rate;    fmt.fmt = AUD_FMT_S16;    s->dac_voice[0] = AUD_open_out(&s->card, s->dac_voice[0],                    "tsc2102.sink", s, (void *) tsc210x_audio_out_cb, &fmt);    if (s->dac_voice[0]) {        s->codec.cts = 1;        AUD_set_active_out(s->dac_voice[0], 1);    }}static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg){    switch (reg) {    case 0x00:	/* X */        s->dav &= 0xfbff;        return TSC_CUT_RESOLUTION(X_TRANSFORM(s), s->precision) +                (s->noise & 3);    case 0x01:	/* Y */        s->noise ++;        s->dav &= 0xfdff;        return TSC_CUT_RESOLUTION(Y_TRANSFORM(s), s->precision) ^                (s->noise & 3);    case 0x02:	/* Z1 */        s->dav &= 0xfeff;        return TSC_CUT_RESOLUTION(Z1_TRANSFORM(s), s->precision) -                (s->noise & 3);    case 0x03:	/* Z2 */        s->dav &= 0xff7f;        return TSC_CUT_RESOLUTION(Z2_TRANSFORM(s), s->precision) |                (s->noise & 3);    case 0x04:	/* KPData */        if ((s->model & 0xff00) == 0x2300) {            if (s->kb.intr && (s->kb.mode & 2)) {                s->kb.intr = 0;                qemu_irq_raise(s->kbint);            }            return s->kb.down;        }        return 0xffff;    case 0x05:	/* BAT1 */        s->dav &= 0xffbf;        return TSC_CUT_RESOLUTION(BAT1_VAL, s->precision) +                (s->noise & 6);    case 0x06:	/* BAT2 */        s->dav &= 0xffdf;        return TSC_CUT_RESOLUTION(BAT2_VAL, s->precision);    case 0x07:	/* AUX1 */        s->dav &= 0xffef;        return TSC_CUT_RESOLUTION(AUX1_VAL, s->precision);    case 0x08:	/* AUX2 */        s->dav &= 0xfff7;        return 0xffff;    case 0x09:	/* TEMP1 */        s->dav &= 0xfffb;        return TSC_CUT_RESOLUTION(TEMP1_VAL, s->precision) -                (s->noise & 5);    case 0x0a:	/* TEMP2 */        s->dav &= 0xfffd;        return TSC_CUT_RESOLUTION(TEMP2_VAL, s->precision) ^                (s->noise & 3);    case 0x0b:	/* DAC */        s->dav &= 0xfffe;        return 0xffff;    default:#ifdef TSC_VERBOSE        fprintf(stderr, "tsc2102_data_register_read: "                        "no such register: 0x%02x\n", reg);#endif        return 0xffff;    }}static uint16_t tsc2102_control_register_read(                struct tsc210x_state_s *s, int reg){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -