Statistics
| Branch: | Revision:

root / hw / tsc210x.c @ 9a393c6c

History | View | Annotate | Download (27.8 kB)

1 3efda49d balrog
/*
2 7fc42b4b balrog
 * TI TSC2102 (touchscreen/sensors/audio controller) emulator.
3 3efda49d balrog
 *
4 3efda49d balrog
 * Copyright (c) 2006 Andrzej Zaborowski  <balrog@zabor.org>
5 3efda49d balrog
 *
6 3efda49d balrog
 * This program is free software; you can redistribute it and/or
7 3efda49d balrog
 * modify it under the terms of the GNU General Public License as
8 3efda49d balrog
 * published by the Free Software Foundation; either version 2 of
9 3efda49d balrog
 * the License, or (at your option) any later version.
10 3efda49d balrog
 *
11 3efda49d balrog
 * This program is distributed in the hope that it will be useful,
12 3efda49d balrog
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 3efda49d balrog
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 3efda49d balrog
 * GNU General Public License for more details.
15 3efda49d balrog
 *
16 3efda49d balrog
 * You should have received a copy of the GNU General Public License
17 3efda49d balrog
 * along with this program; if not, write to the Free Software
18 3efda49d balrog
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19 3efda49d balrog
 * MA 02111-1307 USA
20 3efda49d balrog
 */
21 3efda49d balrog
22 87ecb68b pbrook
#include "hw.h"
23 87ecb68b pbrook
#include "audio/audio.h"
24 87ecb68b pbrook
#include "qemu-timer.h"
25 87ecb68b pbrook
#include "console.h"
26 87ecb68b pbrook
#include "omap.h"
27 3efda49d balrog
28 3efda49d balrog
#define TSC_DATA_REGISTERS_PAGE                0x0
29 3efda49d balrog
#define TSC_CONTROL_REGISTERS_PAGE        0x1
30 3efda49d balrog
#define TSC_AUDIO_REGISTERS_PAGE        0x2
31 3efda49d balrog
32 3efda49d balrog
#define TSC_VERBOSE
33 3efda49d balrog
34 3efda49d balrog
#define TSC_CUT_RESOLUTION(value, p)        ((value) >> (16 - resolution[p]))
35 3efda49d balrog
36 3efda49d balrog
struct tsc210x_state_s {
37 3efda49d balrog
    qemu_irq pint;
38 3efda49d balrog
    QEMUTimer *timer;
39 d8f699cb balrog
    QEMUSoundCard card;
40 3efda49d balrog
    struct uwire_slave_s chip;
41 d8f699cb balrog
    struct i2s_codec_s codec;
42 d8f699cb balrog
    uint8_t in_fifo[16384];
43 d8f699cb balrog
    uint8_t out_fifo[16384];
44 3efda49d balrog
45 3efda49d balrog
    int x, y;
46 3efda49d balrog
    int pressure;
47 3efda49d balrog
48 3efda49d balrog
    int state, page, offset, irq;
49 3efda49d balrog
    uint16_t command, dav;
50 3efda49d balrog
51 3efda49d balrog
    int busy;
52 3efda49d balrog
    int enabled;
53 3efda49d balrog
    int host_mode;
54 3efda49d balrog
    int function;
55 3efda49d balrog
    int nextfunction;
56 3efda49d balrog
    int precision;
57 3efda49d balrog
    int nextprecision;
58 3efda49d balrog
    int filter;
59 3efda49d balrog
    int pin_func;
60 3efda49d balrog
    int ref;
61 3efda49d balrog
    int timing;
62 3efda49d balrog
    int noise;
63 3efda49d balrog
64 3efda49d balrog
    uint16_t audio_ctrl1;
65 3efda49d balrog
    uint16_t audio_ctrl2;
66 3efda49d balrog
    uint16_t audio_ctrl3;
67 3efda49d balrog
    uint16_t pll[2];
68 3efda49d balrog
    uint16_t volume;
69 3efda49d balrog
    int64_t volume_change;
70 3efda49d balrog
    int softstep;
71 3efda49d balrog
    uint16_t dac_power;
72 3efda49d balrog
    int64_t powerdown;
73 3efda49d balrog
    uint16_t filter_data[0x14];
74 d8f699cb balrog
75 d8f699cb balrog
    const char *name;
76 d8f699cb balrog
    SWVoiceIn *adc_voice[1];
77 d8f699cb balrog
    SWVoiceOut *dac_voice[1];
78 d8f699cb balrog
    int i2s_rx_rate;
79 d8f699cb balrog
    int i2s_tx_rate;
80 d8f699cb balrog
    AudioState *audio;
81 3efda49d balrog
};
82 3efda49d balrog
83 3efda49d balrog
static const int resolution[4] = { 12, 8, 10, 12 };
84 3efda49d balrog
85 3efda49d balrog
#define TSC_MODE_NO_SCAN        0x0
86 3efda49d balrog
#define TSC_MODE_XY_SCAN        0x1
87 3efda49d balrog
#define TSC_MODE_XYZ_SCAN        0x2
88 3efda49d balrog
#define TSC_MODE_X                0x3
89 3efda49d balrog
#define TSC_MODE_Y                0x4
90 3efda49d balrog
#define TSC_MODE_Z                0x5
91 3efda49d balrog
#define TSC_MODE_BAT1                0x6
92 3efda49d balrog
#define TSC_MODE_BAT2                0x7
93 3efda49d balrog
#define TSC_MODE_AUX                0x8
94 3efda49d balrog
#define TSC_MODE_AUX_SCAN        0x9
95 3efda49d balrog
#define TSC_MODE_TEMP1                0xa
96 3efda49d balrog
#define TSC_MODE_PORT_SCAN        0xb
97 3efda49d balrog
#define TSC_MODE_TEMP2                0xc
98 3efda49d balrog
#define TSC_MODE_XX_DRV                0xd
99 3efda49d balrog
#define TSC_MODE_YY_DRV                0xe
100 3efda49d balrog
#define TSC_MODE_YX_DRV                0xf
101 3efda49d balrog
102 3efda49d balrog
static const uint16_t mode_regs[16] = {
103 3efda49d balrog
    0x0000,        /* No scan */
104 3efda49d balrog
    0x0600,        /* X, Y scan */
105 3efda49d balrog
    0x0780,        /* X, Y, Z scan */
106 3efda49d balrog
    0x0400,        /* X */
107 3efda49d balrog
    0x0200,        /* Y */
108 3efda49d balrog
    0x0180,        /* Z */
109 3efda49d balrog
    0x0040,        /* BAT1 */
110 3efda49d balrog
    0x0030,        /* BAT2 */
111 3efda49d balrog
    0x0010,        /* AUX */
112 3efda49d balrog
    0x0010,        /* AUX scan */
113 3efda49d balrog
    0x0004,        /* TEMP1 */
114 3efda49d balrog
    0x0070,        /* Port scan */
115 3efda49d balrog
    0x0002,        /* TEMP2 */
116 3efda49d balrog
    0x0000,        /* X+, X- drivers */
117 3efda49d balrog
    0x0000,        /* Y+, Y- drivers */
118 3efda49d balrog
    0x0000,        /* Y+, X- drivers */
119 3efda49d balrog
};
120 3efda49d balrog
121 3efda49d balrog
/*
122 3efda49d balrog
 * Convert screen coordinates to arbitrary values that the
123 3efda49d balrog
 * touchscreen in my Palm Tungsten E device returns.
124 3efda49d balrog
 * This shouldn't really matter (because the guest system
125 3efda49d balrog
 * should calibrate the touchscreen anyway), but let's
126 3efda49d balrog
 * imitate some real hardware.
127 3efda49d balrog
 */
128 3efda49d balrog
#define X_TRANSFORM(value)                \
129 3efda49d balrog
    ((3850 - ((int) (value) * (3850 - 250) / 32768)) << 4)
130 3efda49d balrog
#define Y_TRANSFORM(value)                \
131 3efda49d balrog
    ((150 + ((int) (value) * (3037 - 150) / 32768)) << 4)
132 3efda49d balrog
#define Z1_TRANSFORM(s)                        \
133 8ef6367e balrog
    ((400 - ((s)->x >> 7) + ((s)->pressure << 10)) << 4)
134 3efda49d balrog
#define Z2_TRANSFORM(s)                        \
135 8ef6367e balrog
    ((4000 + ((s)->y >> 7) - ((s)->pressure << 10)) << 4)
136 8ef6367e balrog
137 3efda49d balrog
#define BAT1_VAL                        0x8660
138 3efda49d balrog
#define BAT2_VAL                        0x0000
139 3efda49d balrog
#define AUX1_VAL                        0x35c0
140 3efda49d balrog
#define AUX2_VAL                        0xffff
141 3efda49d balrog
#define TEMP1_VAL                        0x8c70
142 3efda49d balrog
#define TEMP2_VAL                        0xa5b0
143 3efda49d balrog
144 3efda49d balrog
#define TSC_POWEROFF_DELAY                50
145 3efda49d balrog
#define TSC_SOFTSTEP_DELAY                50
146 3efda49d balrog
147 3efda49d balrog
static void tsc210x_reset(struct tsc210x_state_s *s)
148 3efda49d balrog
{
149 3efda49d balrog
    s->state = 0;
150 3efda49d balrog
    s->pin_func = 2;
151 3efda49d balrog
    s->enabled = 0;
152 3efda49d balrog
    s->busy = 0;
153 3efda49d balrog
    s->nextfunction = 0;
154 3efda49d balrog
    s->ref = 0;
155 3efda49d balrog
    s->timing = 0;
156 3efda49d balrog
    s->irq = 0;
157 3efda49d balrog
    s->dav = 0;
158 3efda49d balrog
159 3efda49d balrog
    s->audio_ctrl1 = 0x0000;
160 3efda49d balrog
    s->audio_ctrl2 = 0x4410;
161 3efda49d balrog
    s->audio_ctrl3 = 0x0000;
162 3efda49d balrog
    s->pll[0] = 0x1004;
163 3efda49d balrog
    s->pll[1] = 0x0000;
164 3efda49d balrog
    s->volume = 0xffff;
165 3efda49d balrog
    s->dac_power = 0x8540;
166 3efda49d balrog
    s->softstep = 1;
167 3efda49d balrog
    s->volume_change = 0;
168 3efda49d balrog
    s->powerdown = 0;
169 3efda49d balrog
    s->filter_data[0x00] = 0x6be3;
170 3efda49d balrog
    s->filter_data[0x01] = 0x9666;
171 3efda49d balrog
    s->filter_data[0x02] = 0x675d;
172 3efda49d balrog
    s->filter_data[0x03] = 0x6be3;
173 3efda49d balrog
    s->filter_data[0x04] = 0x9666;
174 3efda49d balrog
    s->filter_data[0x05] = 0x675d;
175 3efda49d balrog
    s->filter_data[0x06] = 0x7d83;
176 3efda49d balrog
    s->filter_data[0x07] = 0x84ee;
177 3efda49d balrog
    s->filter_data[0x08] = 0x7d83;
178 3efda49d balrog
    s->filter_data[0x09] = 0x84ee;
179 3efda49d balrog
    s->filter_data[0x0a] = 0x6be3;
180 3efda49d balrog
    s->filter_data[0x0b] = 0x9666;
181 3efda49d balrog
    s->filter_data[0x0c] = 0x675d;
182 3efda49d balrog
    s->filter_data[0x0d] = 0x6be3;
183 3efda49d balrog
    s->filter_data[0x0e] = 0x9666;
184 3efda49d balrog
    s->filter_data[0x0f] = 0x675d;
185 3efda49d balrog
    s->filter_data[0x10] = 0x7d83;
186 3efda49d balrog
    s->filter_data[0x11] = 0x84ee;
187 3efda49d balrog
    s->filter_data[0x12] = 0x7d83;
188 3efda49d balrog
    s->filter_data[0x13] = 0x84ee;
189 3efda49d balrog
190 d8f699cb balrog
    s->i2s_tx_rate = 0;
191 d8f699cb balrog
    s->i2s_rx_rate = 0;
192 d8f699cb balrog
193 7fc42b4b balrog
    qemu_set_irq(s->pint, !s->irq);
194 3efda49d balrog
}
195 3efda49d balrog
196 d8f699cb balrog
struct tsc210x_rate_info_s {
197 d8f699cb balrog
    int rate;
198 d8f699cb balrog
    int dsor;
199 d8f699cb balrog
    int fsref;
200 d8f699cb balrog
};
201 d8f699cb balrog
202 d8f699cb balrog
/*  { rate,  dsor,  fsref } */
203 d8f699cb balrog
static const struct tsc210x_rate_info_s tsc2101_rates[] = {
204 d8f699cb balrog
    /* Fsref / 6.0 */
205 d8f699cb balrog
    { 7350,        7,        1 },
206 d8f699cb balrog
    { 8000,        7,        0 },
207 d8f699cb balrog
    /* Fsref / 5.5 */
208 d8f699cb balrog
    { 8018,        6,        1 },
209 d8f699cb balrog
    { 8727,        6,        0 },
210 d8f699cb balrog
    /* Fsref / 5.0 */
211 d8f699cb balrog
    { 8820,        5,        1 },
212 d8f699cb balrog
    { 9600,        5,        0 },
213 d8f699cb balrog
    /* Fsref / 4.0 */
214 d8f699cb balrog
    { 11025,        4,        1 },
215 d8f699cb balrog
    { 12000,        4,        0 },
216 d8f699cb balrog
    /* Fsref / 3.0 */
217 d8f699cb balrog
    { 14700,        3,        1 },
218 d8f699cb balrog
    { 16000,        3,        0 },
219 d8f699cb balrog
    /* Fsref / 2.0 */
220 d8f699cb balrog
    { 22050,        2,        1 },
221 d8f699cb balrog
    { 24000,        2,        0 },
222 d8f699cb balrog
    /* Fsref / 1.5 */
223 d8f699cb balrog
    { 29400,        1,        1 },
224 d8f699cb balrog
    { 32000,        1,        0 },
225 d8f699cb balrog
    /* Fsref */
226 d8f699cb balrog
    { 44100,        0,        1 },
227 d8f699cb balrog
    { 48000,        0,        0 },
228 d8f699cb balrog
229 d8f699cb balrog
    { 0,        0,         0 },
230 d8f699cb balrog
};
231 d8f699cb balrog
232 d8f699cb balrog
/*  { rate,   dsor, fsref }        */
233 d8f699cb balrog
static const struct tsc210x_rate_info_s tsc2102_rates[] = {
234 d8f699cb balrog
    /* Fsref / 6.0 */
235 d8f699cb balrog
    { 7350,        63,        1 },
236 d8f699cb balrog
    { 8000,        63,        0 },
237 d8f699cb balrog
    /* Fsref / 6.0 */
238 d8f699cb balrog
    { 7350,        54,        1 },
239 d8f699cb balrog
    { 8000,        54,        0 },
240 d8f699cb balrog
    /* Fsref / 5.0 */
241 d8f699cb balrog
    { 8820,        45,        1 },
242 d8f699cb balrog
    { 9600,        45,        0 },
243 d8f699cb balrog
    /* Fsref / 4.0 */
244 d8f699cb balrog
    { 11025,        36,        1 },
245 d8f699cb balrog
    { 12000,        36,        0 },
246 d8f699cb balrog
    /* Fsref / 3.0 */
247 d8f699cb balrog
    { 14700,        27,        1 },
248 d8f699cb balrog
    { 16000,        27,        0 },
249 d8f699cb balrog
    /* Fsref / 2.0 */
250 d8f699cb balrog
    { 22050,        18,        1 },
251 d8f699cb balrog
    { 24000,        18,        0 },
252 d8f699cb balrog
    /* Fsref / 1.5 */
253 d8f699cb balrog
    { 29400,        9,        1 },
254 d8f699cb balrog
    { 32000,        9,        0 },
255 d8f699cb balrog
    /* Fsref */
256 d8f699cb balrog
    { 44100,        0,        1 },
257 d8f699cb balrog
    { 48000,        0,        0 },
258 d8f699cb balrog
259 d8f699cb balrog
    { 0,        0,         0 },
260 d8f699cb balrog
};
261 d8f699cb balrog
262 d8f699cb balrog
static inline void tsc210x_out_flush(struct tsc210x_state_s *s, int len)
263 d8f699cb balrog
{
264 d8f699cb balrog
    uint8_t *data = s->codec.out.fifo + s->codec.out.start;
265 d8f699cb balrog
    uint8_t *end = data + len;
266 d8f699cb balrog
267 d8f699cb balrog
    while (data < end)
268 d8f699cb balrog
        data += AUD_write(s->dac_voice[0], data, end - data) ?: (end - data);
269 d8f699cb balrog
270 d8f699cb balrog
    s->codec.out.len -= len;
271 d8f699cb balrog
    if (s->codec.out.len)
272 d8f699cb balrog
        memmove(s->codec.out.fifo, end, s->codec.out.len);
273 d8f699cb balrog
    s->codec.out.start = 0;
274 d8f699cb balrog
}
275 d8f699cb balrog
276 d8f699cb balrog
static void tsc210x_audio_out_cb(struct tsc210x_state_s *s, int free_b)
277 d8f699cb balrog
{
278 d8f699cb balrog
    if (s->codec.out.len >= free_b) {
279 d8f699cb balrog
        tsc210x_out_flush(s, free_b);
280 d8f699cb balrog
        return;
281 d8f699cb balrog
    }
282 d8f699cb balrog
283 d8f699cb balrog
    s->codec.out.size = MIN(free_b, 16384);
284 d8f699cb balrog
    qemu_irq_raise(s->codec.tx_start);
285 d8f699cb balrog
}
286 d8f699cb balrog
287 73560bc8 balrog
static void tsc2102_audio_rate_update(struct tsc210x_state_s *s)
288 d8f699cb balrog
{
289 d8f699cb balrog
    const struct tsc210x_rate_info_s *rate;
290 73560bc8 balrog
291 73560bc8 balrog
    s->codec.tx_rate = 0;
292 73560bc8 balrog
    s->codec.rx_rate = 0;
293 73560bc8 balrog
    if (s->dac_power & (1 << 15))                                /* PWDNC */
294 73560bc8 balrog
        return;
295 73560bc8 balrog
296 73560bc8 balrog
    for (rate = tsc2102_rates; rate->rate; rate ++)
297 73560bc8 balrog
        if (rate->dsor == (s->audio_ctrl1 & 0x3f) &&                /* DACFS */
298 73560bc8 balrog
                        rate->fsref == ((s->audio_ctrl3 >> 13) & 1))/* REFFS */
299 73560bc8 balrog
            break;
300 73560bc8 balrog
    if (!rate->rate) {
301 73560bc8 balrog
        printf("%s: unknown sampling rate configured\n", __FUNCTION__);
302 73560bc8 balrog
        return;
303 73560bc8 balrog
    }
304 73560bc8 balrog
305 73560bc8 balrog
    s->codec.tx_rate = rate->rate;
306 73560bc8 balrog
}
307 73560bc8 balrog
308 73560bc8 balrog
static void tsc2102_audio_output_update(struct tsc210x_state_s *s)
309 73560bc8 balrog
{
310 73560bc8 balrog
    int enable;
311 d8f699cb balrog
    audsettings_t fmt;
312 d8f699cb balrog
313 d8f699cb balrog
    if (s->dac_voice[0]) {
314 d8f699cb balrog
        tsc210x_out_flush(s, s->codec.out.len);
315 d8f699cb balrog
        s->codec.out.size = 0;
316 d8f699cb balrog
        AUD_set_active_out(s->dac_voice[0], 0);
317 d8f699cb balrog
        AUD_close_out(&s->card, s->dac_voice[0]);
318 d8f699cb balrog
        s->dac_voice[0] = 0;
319 d8f699cb balrog
    }
320 73560bc8 balrog
    s->codec.cts = 0;
321 d8f699cb balrog
322 d8f699cb balrog
    enable =
323 d8f699cb balrog
            (~s->dac_power & (1 << 15)) &&                        /* PWDNC */
324 d8f699cb balrog
            (~s->dac_power & (1 << 10));                        /* DAPWDN */
325 73560bc8 balrog
    if (!enable || !s->codec.tx_rate)
326 d8f699cb balrog
        return;
327 d8f699cb balrog
328 d8f699cb balrog
    /* Force our own sampling rate even in slave DAC mode */
329 d8f699cb balrog
    fmt.endianness = 0;
330 d8f699cb balrog
    fmt.nchannels = 2;
331 73560bc8 balrog
    fmt.freq = s->codec.tx_rate;
332 d8f699cb balrog
    fmt.fmt = AUD_FMT_S16;
333 d8f699cb balrog
334 d8f699cb balrog
    s->dac_voice[0] = AUD_open_out(&s->card, s->dac_voice[0],
335 d8f699cb balrog
                    "tsc2102.sink", s, (void *) tsc210x_audio_out_cb, &fmt);
336 73560bc8 balrog
    if (s->dac_voice[0]) {
337 73560bc8 balrog
        s->codec.cts = 1;
338 d8f699cb balrog
        AUD_set_active_out(s->dac_voice[0], 1);
339 73560bc8 balrog
    }
340 d8f699cb balrog
}
341 d8f699cb balrog
342 3efda49d balrog
static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg)
343 3efda49d balrog
{
344 3efda49d balrog
    switch (reg) {
345 3efda49d balrog
    case 0x00:        /* X */
346 3efda49d balrog
        s->dav &= 0xfbff;
347 3efda49d balrog
        return TSC_CUT_RESOLUTION(X_TRANSFORM(s->x), s->precision) +
348 3efda49d balrog
                (s->noise & 3);
349 3efda49d balrog
350 3efda49d balrog
    case 0x01:        /* Y */
351 3efda49d balrog
        s->noise ++;
352 3efda49d balrog
        s->dav &= 0xfdff;
353 3efda49d balrog
        return TSC_CUT_RESOLUTION(Y_TRANSFORM(s->y), s->precision) ^
354 3efda49d balrog
                (s->noise & 3);
355 3efda49d balrog
356 3efda49d balrog
    case 0x02:        /* Z1 */
357 3efda49d balrog
        s->dav &= 0xfeff;
358 3efda49d balrog
        return TSC_CUT_RESOLUTION(Z1_TRANSFORM(s), s->precision) -
359 3efda49d balrog
                (s->noise & 3);
360 3efda49d balrog
361 3efda49d balrog
    case 0x03:        /* Z2 */
362 3efda49d balrog
        s->dav &= 0xff7f;
363 3efda49d balrog
        return TSC_CUT_RESOLUTION(Z2_TRANSFORM(s), s->precision) |
364 3efda49d balrog
                (s->noise & 3);
365 3efda49d balrog
366 3efda49d balrog
    case 0x04:        /* KPData */
367 3efda49d balrog
        return 0xffff;
368 3efda49d balrog
369 3efda49d balrog
    case 0x05:        /* BAT1 */
370 3efda49d balrog
        s->dav &= 0xffbf;
371 8ef6367e balrog
        return TSC_CUT_RESOLUTION(BAT1_VAL, s->precision) +
372 8ef6367e balrog
                (s->noise & 6);
373 3efda49d balrog
374 3efda49d balrog
    case 0x06:        /* BAT2 */
375 3efda49d balrog
        s->dav &= 0xffdf;
376 3efda49d balrog
        return TSC_CUT_RESOLUTION(BAT2_VAL, s->precision);
377 3efda49d balrog
378 3efda49d balrog
    case 0x07:        /* AUX1 */
379 3efda49d balrog
        s->dav &= 0xffef;
380 3efda49d balrog
        return TSC_CUT_RESOLUTION(AUX1_VAL, s->precision);
381 3efda49d balrog
382 3efda49d balrog
    case 0x08:        /* AUX2 */
383 3efda49d balrog
        s->dav &= 0xfff7;
384 3efda49d balrog
        return 0xffff;
385 3efda49d balrog
386 3efda49d balrog
    case 0x09:        /* TEMP1 */
387 3efda49d balrog
        s->dav &= 0xfffb;
388 8ef6367e balrog
        return TSC_CUT_RESOLUTION(TEMP1_VAL, s->precision) -
389 8ef6367e balrog
                (s->noise & 5);
390 3efda49d balrog
391 3efda49d balrog
    case 0x0a:        /* TEMP2 */
392 3efda49d balrog
        s->dav &= 0xfffd;
393 8ef6367e balrog
        return TSC_CUT_RESOLUTION(TEMP2_VAL, s->precision) ^
394 8ef6367e balrog
                (s->noise & 3);
395 3efda49d balrog
396 3efda49d balrog
    case 0x0b:        /* DAC */
397 3efda49d balrog
        s->dav &= 0xfffe;
398 3efda49d balrog
        return 0xffff;
399 3efda49d balrog
400 3efda49d balrog
    default:
401 3efda49d balrog
#ifdef TSC_VERBOSE
402 3efda49d balrog
        fprintf(stderr, "tsc2102_data_register_read: "
403 3efda49d balrog
                        "no such register: 0x%02x\n", reg);
404 3efda49d balrog
#endif
405 3efda49d balrog
        return 0xffff;
406 3efda49d balrog
    }
407 3efda49d balrog
}
408 3efda49d balrog
409 3efda49d balrog
static uint16_t tsc2102_control_register_read(
410 3efda49d balrog
                struct tsc210x_state_s *s, int reg)
411 3efda49d balrog
{
412 3efda49d balrog
    switch (reg) {
413 3efda49d balrog
    case 0x00:        /* TSC ADC */
414 3efda49d balrog
        return (s->pressure << 15) | ((!s->busy) << 14) |
415 3efda49d balrog
                (s->nextfunction << 10) | (s->nextprecision << 8) | s->filter; 
416 3efda49d balrog
417 3efda49d balrog
    case 0x01:        /* Status */
418 3efda49d balrog
        return (s->pin_func << 14) | ((!s->enabled) << 13) |
419 3efda49d balrog
                (s->host_mode << 12) | ((!!s->dav) << 11) | s->dav;
420 3efda49d balrog
421 3efda49d balrog
    case 0x03:        /* Reference */
422 3efda49d balrog
        return s->ref;
423 3efda49d balrog
424 3efda49d balrog
    case 0x04:        /* Reset */
425 3efda49d balrog
        return 0xffff;
426 3efda49d balrog
427 3efda49d balrog
    case 0x05:        /* Configuration */
428 3efda49d balrog
        return s->timing;
429 3efda49d balrog
430 3efda49d balrog
    default:
431 3efda49d balrog
#ifdef TSC_VERBOSE
432 3efda49d balrog
        fprintf(stderr, "tsc2102_control_register_read: "
433 3efda49d balrog
                        "no such register: 0x%02x\n", reg);
434 3efda49d balrog
#endif
435 3efda49d balrog
        return 0xffff;
436 3efda49d balrog
    }
437 3efda49d balrog
}
438 3efda49d balrog
439 3efda49d balrog
static uint16_t tsc2102_audio_register_read(struct tsc210x_state_s *s, int reg)
440 3efda49d balrog
{
441 3efda49d balrog
    int l_ch, r_ch;
442 3efda49d balrog
    uint16_t val;
443 3efda49d balrog
444 3efda49d balrog
    switch (reg) {
445 3efda49d balrog
    case 0x00:        /* Audio Control 1 */
446 3efda49d balrog
        return s->audio_ctrl1;
447 3efda49d balrog
448 3efda49d balrog
    case 0x01:
449 3efda49d balrog
        return 0xff00;
450 3efda49d balrog
451 3efda49d balrog
    case 0x02:        /* DAC Volume Control */
452 3efda49d balrog
        return s->volume;
453 3efda49d balrog
454 3efda49d balrog
    case 0x03:
455 3efda49d balrog
        return 0x8b00;
456 3efda49d balrog
457 3efda49d balrog
    case 0x04:        /* Audio Control 2 */
458 3efda49d balrog
        l_ch = 1;
459 3efda49d balrog
        r_ch = 1;
460 3efda49d balrog
        if (s->softstep && !(s->dac_power & (1 << 10))) {
461 3efda49d balrog
            l_ch = (qemu_get_clock(vm_clock) >
462 3efda49d balrog
                            s->volume_change + TSC_SOFTSTEP_DELAY);
463 3efda49d balrog
            r_ch = (qemu_get_clock(vm_clock) >
464 3efda49d balrog
                            s->volume_change + TSC_SOFTSTEP_DELAY);
465 3efda49d balrog
        }
466 3efda49d balrog
467 3efda49d balrog
        return s->audio_ctrl2 | (l_ch << 3) | (r_ch << 2);
468 3efda49d balrog
469 3efda49d balrog
    case 0x05:        /* Stereo DAC Power Control */
470 3efda49d balrog
        return 0x2aa0 | s->dac_power |
471 3efda49d balrog
                (((s->dac_power & (1 << 10)) &&
472 3efda49d balrog
                  (qemu_get_clock(vm_clock) >
473 3efda49d balrog
                   s->powerdown + TSC_POWEROFF_DELAY)) << 6);
474 3efda49d balrog
475 3efda49d balrog
    case 0x06:        /* Audio Control 3 */
476 3efda49d balrog
        val = s->audio_ctrl3 | 0x0001;
477 3efda49d balrog
        s->audio_ctrl3 &= 0xff3f;
478 3efda49d balrog
        return val;
479 3efda49d balrog
480 3efda49d balrog
    case 0x07:        /* LCH_BASS_BOOST_N0 */
481 3efda49d balrog
    case 0x08:        /* LCH_BASS_BOOST_N1 */
482 3efda49d balrog
    case 0x09:        /* LCH_BASS_BOOST_N2 */
483 3efda49d balrog
    case 0x0a:        /* LCH_BASS_BOOST_N3 */
484 3efda49d balrog
    case 0x0b:        /* LCH_BASS_BOOST_N4 */
485 3efda49d balrog
    case 0x0c:        /* LCH_BASS_BOOST_N5 */
486 3efda49d balrog
    case 0x0d:        /* LCH_BASS_BOOST_D1 */
487 3efda49d balrog
    case 0x0e:        /* LCH_BASS_BOOST_D2 */
488 3efda49d balrog
    case 0x0f:        /* LCH_BASS_BOOST_D4 */
489 3efda49d balrog
    case 0x10:        /* LCH_BASS_BOOST_D5 */
490 3efda49d balrog
    case 0x11:        /* RCH_BASS_BOOST_N0 */
491 3efda49d balrog
    case 0x12:        /* RCH_BASS_BOOST_N1 */
492 3efda49d balrog
    case 0x13:        /* RCH_BASS_BOOST_N2 */
493 3efda49d balrog
    case 0x14:        /* RCH_BASS_BOOST_N3 */
494 3efda49d balrog
    case 0x15:        /* RCH_BASS_BOOST_N4 */
495 3efda49d balrog
    case 0x16:        /* RCH_BASS_BOOST_N5 */
496 3efda49d balrog
    case 0x17:        /* RCH_BASS_BOOST_D1 */
497 3efda49d balrog
    case 0x18:        /* RCH_BASS_BOOST_D2 */
498 3efda49d balrog
    case 0x19:        /* RCH_BASS_BOOST_D4 */
499 3efda49d balrog
    case 0x1a:        /* RCH_BASS_BOOST_D5 */
500 3efda49d balrog
        return s->filter_data[reg - 0x07];
501 3efda49d balrog
502 3efda49d balrog
    case 0x1b:        /* PLL Programmability 1 */
503 3efda49d balrog
        return s->pll[0];
504 3efda49d balrog
505 3efda49d balrog
    case 0x1c:        /* PLL Programmability 2 */
506 3efda49d balrog
        return s->pll[1];
507 3efda49d balrog
508 3efda49d balrog
    case 0x1d:        /* Audio Control 4 */
509 3efda49d balrog
        return (!s->softstep) << 14;
510 3efda49d balrog
511 3efda49d balrog
    default:
512 3efda49d balrog
#ifdef TSC_VERBOSE
513 3efda49d balrog
        fprintf(stderr, "tsc2102_audio_register_read: "
514 3efda49d balrog
                        "no such register: 0x%02x\n", reg);
515 3efda49d balrog
#endif
516 3efda49d balrog
        return 0xffff;
517 3efda49d balrog
    }
518 3efda49d balrog
}
519 3efda49d balrog
520 3efda49d balrog
static void tsc2102_data_register_write(
521 3efda49d balrog
                struct tsc210x_state_s *s, int reg, uint16_t value)
522 3efda49d balrog
{
523 3efda49d balrog
    switch (reg) {
524 3efda49d balrog
    case 0x00:        /* X */
525 3efda49d balrog
    case 0x01:        /* Y */
526 3efda49d balrog
    case 0x02:        /* Z1 */
527 3efda49d balrog
    case 0x03:        /* Z2 */
528 3efda49d balrog
    case 0x05:        /* BAT1 */
529 3efda49d balrog
    case 0x06:        /* BAT2 */
530 3efda49d balrog
    case 0x07:        /* AUX1 */
531 3efda49d balrog
    case 0x08:        /* AUX2 */
532 3efda49d balrog
    case 0x09:        /* TEMP1 */
533 3efda49d balrog
    case 0x0a:        /* TEMP2 */
534 3efda49d balrog
        return;
535 3efda49d balrog
536 3efda49d balrog
    default:
537 3efda49d balrog
#ifdef TSC_VERBOSE
538 3efda49d balrog
        fprintf(stderr, "tsc2102_data_register_write: "
539 3efda49d balrog
                        "no such register: 0x%02x\n", reg);
540 3efda49d balrog
#endif
541 3efda49d balrog
    }
542 3efda49d balrog
}
543 3efda49d balrog
544 3efda49d balrog
static void tsc2102_control_register_write(
545 3efda49d balrog
                struct tsc210x_state_s *s, int reg, uint16_t value)
546 3efda49d balrog
{
547 3efda49d balrog
    switch (reg) {
548 3efda49d balrog
    case 0x00:        /* TSC ADC */
549 3efda49d balrog
        s->host_mode = value >> 15;
550 3efda49d balrog
        s->enabled = !(value & 0x4000);
551 3efda49d balrog
        if (s->busy && !s->enabled)
552 3efda49d balrog
            qemu_del_timer(s->timer);
553 3efda49d balrog
        s->busy &= s->enabled;
554 3efda49d balrog
        s->nextfunction = (value >> 10) & 0xf;
555 3efda49d balrog
        s->nextprecision = (value >> 8) & 3;
556 3efda49d balrog
        s->filter = value & 0xff;
557 3efda49d balrog
        return;
558 3efda49d balrog
559 3efda49d balrog
    case 0x01:        /* Status */
560 3efda49d balrog
        s->pin_func = value >> 14;
561 3efda49d balrog
        return;
562 3efda49d balrog
563 3efda49d balrog
    case 0x03:        /* Reference */
564 3efda49d balrog
        s->ref = value & 0x1f;
565 3efda49d balrog
        return;
566 3efda49d balrog
567 3efda49d balrog
    case 0x04:        /* Reset */
568 3efda49d balrog
        if (value == 0xbb00) {
569 3efda49d balrog
            if (s->busy)
570 3efda49d balrog
                qemu_del_timer(s->timer);
571 3efda49d balrog
            tsc210x_reset(s);
572 3efda49d balrog
#ifdef TSC_VERBOSE
573 3efda49d balrog
        } else {
574 3efda49d balrog
            fprintf(stderr, "tsc2102_control_register_write: "
575 3efda49d balrog
                            "wrong value written into RESET\n");
576 3efda49d balrog
#endif
577 3efda49d balrog
        }
578 3efda49d balrog
        return;
579 3efda49d balrog
580 3efda49d balrog
    case 0x05:        /* Configuration */
581 3efda49d balrog
        s->timing = value & 0x3f;
582 3efda49d balrog
#ifdef TSC_VERBOSE
583 3efda49d balrog
        if (value & ~0x3f)
584 3efda49d balrog
            fprintf(stderr, "tsc2102_control_register_write: "
585 3efda49d balrog
                            "wrong value written into CONFIG\n");
586 3efda49d balrog
#endif
587 3efda49d balrog
        return;
588 3efda49d balrog
589 3efda49d balrog
    default:
590 3efda49d balrog
#ifdef TSC_VERBOSE
591 3efda49d balrog
        fprintf(stderr, "tsc2102_control_register_write: "
592 3efda49d balrog
                        "no such register: 0x%02x\n", reg);
593 3efda49d balrog
#endif
594 3efda49d balrog
    }
595 3efda49d balrog
}
596 3efda49d balrog
597 3efda49d balrog
static void tsc2102_audio_register_write(
598 3efda49d balrog
                struct tsc210x_state_s *s, int reg, uint16_t value)
599 3efda49d balrog
{
600 3efda49d balrog
    switch (reg) {
601 3efda49d balrog
    case 0x00:        /* Audio Control 1 */
602 3efda49d balrog
        s->audio_ctrl1 = value & 0x0f3f;
603 3efda49d balrog
#ifdef TSC_VERBOSE
604 3efda49d balrog
        if ((value & ~0x0f3f) || ((value & 7) != ((value >> 3) & 7)))
605 3efda49d balrog
            fprintf(stderr, "tsc2102_audio_register_write: "
606 3efda49d balrog
                            "wrong value written into Audio 1\n");
607 3efda49d balrog
#endif
608 73560bc8 balrog
        tsc2102_audio_rate_update(s);
609 d8f699cb balrog
        if (s->audio)
610 73560bc8 balrog
            tsc2102_audio_output_update(s);
611 3efda49d balrog
        return;
612 3efda49d balrog
613 3efda49d balrog
    case 0x01:
614 3efda49d balrog
#ifdef TSC_VERBOSE
615 3efda49d balrog
        if (value != 0xff00)
616 3efda49d balrog
            fprintf(stderr, "tsc2102_audio_register_write: "
617 3efda49d balrog
                            "wrong value written into reg 0x01\n");
618 3efda49d balrog
#endif
619 3efda49d balrog
        return;
620 3efda49d balrog
621 3efda49d balrog
    case 0x02:        /* DAC Volume Control */
622 3efda49d balrog
        s->volume = value;
623 3efda49d balrog
        s->volume_change = qemu_get_clock(vm_clock);
624 3efda49d balrog
        return;
625 3efda49d balrog
626 3efda49d balrog
    case 0x03:
627 3efda49d balrog
#ifdef TSC_VERBOSE
628 3efda49d balrog
        if (value != 0x8b00)
629 3efda49d balrog
            fprintf(stderr, "tsc2102_audio_register_write: "
630 3efda49d balrog
                            "wrong value written into reg 0x03\n");
631 3efda49d balrog
#endif
632 3efda49d balrog
        return;
633 3efda49d balrog
634 3efda49d balrog
    case 0x04:        /* Audio Control 2 */
635 3efda49d balrog
        s->audio_ctrl2 = value & 0xf7f2;
636 3efda49d balrog
#ifdef TSC_VERBOSE
637 3efda49d balrog
        if (value & ~0xf7fd)
638 3efda49d balrog
            fprintf(stderr, "tsc2102_audio_register_write: "
639 3efda49d balrog
                            "wrong value written into Audio 2\n");
640 3efda49d balrog
#endif
641 3efda49d balrog
        return;
642 3efda49d balrog
643 3efda49d balrog
    case 0x05:        /* Stereo DAC Power Control */
644 3efda49d balrog
        if ((value & ~s->dac_power) & (1 << 10))
645 3efda49d balrog
            s->powerdown = qemu_get_clock(vm_clock);
646 3efda49d balrog
647 3efda49d balrog
        s->dac_power = value & 0x9543;
648 3efda49d balrog
#ifdef TSC_VERBOSE
649 3efda49d balrog
        if ((value & ~0x9543) != 0x2aa0)
650 3efda49d balrog
            fprintf(stderr, "tsc2102_audio_register_write: "
651 3efda49d balrog
                            "wrong value written into Power\n");
652 3efda49d balrog
#endif
653 73560bc8 balrog
        tsc2102_audio_rate_update(s);
654 d8f699cb balrog
        if (s->audio)
655 73560bc8 balrog
            tsc2102_audio_output_update(s);
656 3efda49d balrog
        return;
657 3efda49d balrog
658 3efda49d balrog
    case 0x06:        /* Audio Control 3 */
659 3efda49d balrog
        s->audio_ctrl3 &= 0x00c0;
660 3efda49d balrog
        s->audio_ctrl3 |= value & 0xf800;
661 3efda49d balrog
#ifdef TSC_VERBOSE
662 3efda49d balrog
        if (value & ~0xf8c7)
663 3efda49d balrog
            fprintf(stderr, "tsc2102_audio_register_write: "
664 3efda49d balrog
                            "wrong value written into Audio 3\n");
665 3efda49d balrog
#endif
666 d8f699cb balrog
        if (s->audio)
667 73560bc8 balrog
            tsc2102_audio_output_update(s);
668 3efda49d balrog
        return;
669 3efda49d balrog
670 3efda49d balrog
    case 0x07:        /* LCH_BASS_BOOST_N0 */
671 3efda49d balrog
    case 0x08:        /* LCH_BASS_BOOST_N1 */
672 3efda49d balrog
    case 0x09:        /* LCH_BASS_BOOST_N2 */
673 3efda49d balrog
    case 0x0a:        /* LCH_BASS_BOOST_N3 */
674 3efda49d balrog
    case 0x0b:        /* LCH_BASS_BOOST_N4 */
675 3efda49d balrog
    case 0x0c:        /* LCH_BASS_BOOST_N5 */
676 3efda49d balrog
    case 0x0d:        /* LCH_BASS_BOOST_D1 */
677 3efda49d balrog
    case 0x0e:        /* LCH_BASS_BOOST_D2 */
678 3efda49d balrog
    case 0x0f:        /* LCH_BASS_BOOST_D4 */
679 3efda49d balrog
    case 0x10:        /* LCH_BASS_BOOST_D5 */
680 3efda49d balrog
    case 0x11:        /* RCH_BASS_BOOST_N0 */
681 3efda49d balrog
    case 0x12:        /* RCH_BASS_BOOST_N1 */
682 3efda49d balrog
    case 0x13:        /* RCH_BASS_BOOST_N2 */
683 3efda49d balrog
    case 0x14:        /* RCH_BASS_BOOST_N3 */
684 3efda49d balrog
    case 0x15:        /* RCH_BASS_BOOST_N4 */
685 3efda49d balrog
    case 0x16:        /* RCH_BASS_BOOST_N5 */
686 3efda49d balrog
    case 0x17:        /* RCH_BASS_BOOST_D1 */
687 3efda49d balrog
    case 0x18:        /* RCH_BASS_BOOST_D2 */
688 3efda49d balrog
    case 0x19:        /* RCH_BASS_BOOST_D4 */
689 3efda49d balrog
    case 0x1a:        /* RCH_BASS_BOOST_D5 */
690 3efda49d balrog
        s->filter_data[reg - 0x07] = value;
691 3efda49d balrog
        return;
692 3efda49d balrog
693 3efda49d balrog
    case 0x1b:        /* PLL Programmability 1 */
694 3efda49d balrog
        s->pll[0] = value & 0xfffc;
695 3efda49d balrog
#ifdef TSC_VERBOSE
696 3efda49d balrog
        if (value & ~0xfffc)
697 3efda49d balrog
            fprintf(stderr, "tsc2102_audio_register_write: "
698 3efda49d balrog
                            "wrong value written into PLL 1\n");
699 3efda49d balrog
#endif
700 3efda49d balrog
        return;
701 3efda49d balrog
702 3efda49d balrog
    case 0x1c:        /* PLL Programmability 2 */
703 3efda49d balrog
        s->pll[1] = value & 0xfffc;
704 3efda49d balrog
#ifdef TSC_VERBOSE
705 3efda49d balrog
        if (value & ~0xfffc)
706 3efda49d balrog
            fprintf(stderr, "tsc2102_audio_register_write: "
707 3efda49d balrog
                            "wrong value written into PLL 2\n");
708 3efda49d balrog
#endif
709 3efda49d balrog
        return;
710 3efda49d balrog
711 3efda49d balrog
    case 0x1d:        /* Audio Control 4 */
712 3efda49d balrog
        s->softstep = !(value & 0x4000);
713 3efda49d balrog
#ifdef TSC_VERBOSE
714 3efda49d balrog
        if (value & ~0x4000)
715 3efda49d balrog
            fprintf(stderr, "tsc2102_audio_register_write: "
716 3efda49d balrog
                            "wrong value written into Audio 4\n");
717 3efda49d balrog
#endif
718 3efda49d balrog
        return;
719 3efda49d balrog
720 3efda49d balrog
    default:
721 3efda49d balrog
#ifdef TSC_VERBOSE
722 3efda49d balrog
        fprintf(stderr, "tsc2102_audio_register_write: "
723 3efda49d balrog
                        "no such register: 0x%02x\n", reg);
724 3efda49d balrog
#endif
725 3efda49d balrog
    }
726 3efda49d balrog
}
727 3efda49d balrog
728 3efda49d balrog
/* This handles most of the chip logic.  */
729 3efda49d balrog
static void tsc210x_pin_update(struct tsc210x_state_s *s)
730 3efda49d balrog
{
731 3efda49d balrog
    int64_t expires;
732 3efda49d balrog
    int pin_state;
733 3efda49d balrog
734 3efda49d balrog
    switch (s->pin_func) {
735 3efda49d balrog
    case 0:
736 3efda49d balrog
        pin_state = s->pressure;
737 3efda49d balrog
        break;
738 3efda49d balrog
    case 1:
739 3efda49d balrog
        pin_state = !!s->dav;
740 3efda49d balrog
        break;
741 3efda49d balrog
    case 2:
742 3efda49d balrog
    default:
743 3efda49d balrog
        pin_state = s->pressure && !s->dav;
744 3efda49d balrog
    }
745 3efda49d balrog
746 3efda49d balrog
    if (!s->enabled)
747 3efda49d balrog
        pin_state = 0;
748 3efda49d balrog
749 3efda49d balrog
    if (pin_state != s->irq) {
750 3efda49d balrog
        s->irq = pin_state;
751 7fc42b4b balrog
        qemu_set_irq(s->pint, !s->irq);
752 3efda49d balrog
    }
753 3efda49d balrog
754 3efda49d balrog
    switch (s->nextfunction) {
755 3efda49d balrog
    case TSC_MODE_XY_SCAN:
756 3efda49d balrog
    case TSC_MODE_XYZ_SCAN:
757 3efda49d balrog
        if (!s->pressure)
758 3efda49d balrog
            return;
759 3efda49d balrog
        break;
760 3efda49d balrog
761 3efda49d balrog
    case TSC_MODE_X:
762 3efda49d balrog
    case TSC_MODE_Y:
763 3efda49d balrog
    case TSC_MODE_Z:
764 3efda49d balrog
        if (!s->pressure)
765 3efda49d balrog
            return;
766 3efda49d balrog
        /* Fall through */
767 3efda49d balrog
    case TSC_MODE_BAT1:
768 3efda49d balrog
    case TSC_MODE_BAT2:
769 3efda49d balrog
    case TSC_MODE_AUX:
770 3efda49d balrog
    case TSC_MODE_TEMP1:
771 3efda49d balrog
    case TSC_MODE_TEMP2:
772 3efda49d balrog
        if (s->dav)
773 3efda49d balrog
            s->enabled = 0;
774 3efda49d balrog
        break;
775 3efda49d balrog
776 3efda49d balrog
    case TSC_MODE_AUX_SCAN:
777 3efda49d balrog
    case TSC_MODE_PORT_SCAN:
778 3efda49d balrog
        break;
779 3efda49d balrog
780 3efda49d balrog
    case TSC_MODE_NO_SCAN:
781 3efda49d balrog
    case TSC_MODE_XX_DRV:
782 3efda49d balrog
    case TSC_MODE_YY_DRV:
783 3efda49d balrog
    case TSC_MODE_YX_DRV:
784 3efda49d balrog
    default:
785 3efda49d balrog
        return;
786 3efda49d balrog
    }
787 3efda49d balrog
788 3efda49d balrog
    if (!s->enabled || s->busy)
789 3efda49d balrog
        return;
790 3efda49d balrog
791 3efda49d balrog
    s->busy = 1;
792 3efda49d balrog
    s->precision = s->nextprecision;
793 3efda49d balrog
    s->function = s->nextfunction;
794 3efda49d balrog
    expires = qemu_get_clock(vm_clock) + (ticks_per_sec >> 10);
795 3efda49d balrog
    qemu_mod_timer(s->timer, expires);
796 3efda49d balrog
}
797 3efda49d balrog
798 3efda49d balrog
static uint16_t tsc210x_read(struct tsc210x_state_s *s)
799 3efda49d balrog
{
800 3efda49d balrog
    uint16_t ret = 0x0000;
801 3efda49d balrog
802 3efda49d balrog
    if (!s->command)
803 3efda49d balrog
        fprintf(stderr, "tsc210x_read: SPI underrun!\n");
804 3efda49d balrog
805 3efda49d balrog
    switch (s->page) {
806 3efda49d balrog
    case TSC_DATA_REGISTERS_PAGE:
807 3efda49d balrog
        ret = tsc2102_data_register_read(s, s->offset);
808 3efda49d balrog
        break;
809 3efda49d balrog
    case TSC_CONTROL_REGISTERS_PAGE:
810 3efda49d balrog
        ret = tsc2102_control_register_read(s, s->offset);
811 3efda49d balrog
        break;
812 3efda49d balrog
    case TSC_AUDIO_REGISTERS_PAGE:
813 3efda49d balrog
        ret = tsc2102_audio_register_read(s, s->offset);
814 3efda49d balrog
        break;
815 3efda49d balrog
    default:
816 3efda49d balrog
        cpu_abort(cpu_single_env, "tsc210x_read: wrong memory page\n");
817 3efda49d balrog
    }
818 3efda49d balrog
819 3efda49d balrog
    tsc210x_pin_update(s);
820 3efda49d balrog
821 3efda49d balrog
    /* Allow sequential reads.  */
822 3efda49d balrog
    s->offset ++;
823 3efda49d balrog
    s->state = 0;
824 3efda49d balrog
    return ret;
825 3efda49d balrog
}
826 3efda49d balrog
827 3efda49d balrog
static void tsc210x_write(struct tsc210x_state_s *s, uint16_t value)
828 3efda49d balrog
{
829 3efda49d balrog
    /*
830 3efda49d balrog
     * This is a two-state state machine for reading
831 3efda49d balrog
     * command and data every second time.
832 3efda49d balrog
     */
833 3efda49d balrog
    if (!s->state) {
834 3efda49d balrog
        s->command = value >> 15;
835 3efda49d balrog
        s->page = (value >> 11) & 0x0f;
836 3efda49d balrog
        s->offset = (value >> 5) & 0x3f;
837 3efda49d balrog
        s->state = 1;
838 3efda49d balrog
    } else {
839 3efda49d balrog
        if (s->command)
840 3efda49d balrog
            fprintf(stderr, "tsc210x_write: SPI overrun!\n");
841 3efda49d balrog
        else
842 3efda49d balrog
            switch (s->page) {
843 3efda49d balrog
            case TSC_DATA_REGISTERS_PAGE:
844 3efda49d balrog
                tsc2102_data_register_write(s, s->offset, value);
845 3efda49d balrog
                break;
846 3efda49d balrog
            case TSC_CONTROL_REGISTERS_PAGE:
847 3efda49d balrog
                tsc2102_control_register_write(s, s->offset, value);
848 3efda49d balrog
                break;
849 3efda49d balrog
            case TSC_AUDIO_REGISTERS_PAGE:
850 3efda49d balrog
                tsc2102_audio_register_write(s, s->offset, value);
851 3efda49d balrog
                break;
852 3efda49d balrog
            default:
853 3efda49d balrog
                cpu_abort(cpu_single_env,
854 3efda49d balrog
                                "tsc210x_write: wrong memory page\n");
855 3efda49d balrog
            }
856 3efda49d balrog
857 3efda49d balrog
        tsc210x_pin_update(s);
858 3efda49d balrog
        s->state = 0;
859 3efda49d balrog
    }
860 3efda49d balrog
}
861 3efda49d balrog
862 3efda49d balrog
static void tsc210x_timer_tick(void *opaque)
863 3efda49d balrog
{
864 3efda49d balrog
    struct tsc210x_state_s *s = opaque;
865 3efda49d balrog
866 3efda49d balrog
    /* Timer ticked -- a set of conversions has been finished.  */
867 3efda49d balrog
868 3efda49d balrog
    if (!s->busy)
869 3efda49d balrog
        return;
870 3efda49d balrog
871 3efda49d balrog
    s->busy = 0;
872 3efda49d balrog
    s->dav |= mode_regs[s->function];
873 3efda49d balrog
    tsc210x_pin_update(s);
874 3efda49d balrog
}
875 3efda49d balrog
876 3efda49d balrog
static void tsc210x_touchscreen_event(void *opaque,
877 3efda49d balrog
                int x, int y, int z, int buttons_state)
878 3efda49d balrog
{
879 3efda49d balrog
    struct tsc210x_state_s *s = opaque;
880 3efda49d balrog
    int p = s->pressure;
881 3efda49d balrog
882 3efda49d balrog
    if (buttons_state) {
883 3efda49d balrog
        s->x = x;
884 3efda49d balrog
        s->y = y;
885 3efda49d balrog
    }
886 3efda49d balrog
    s->pressure = !!buttons_state;
887 3efda49d balrog
888 3efda49d balrog
    /*
889 3efda49d balrog
     * Note: We would get better responsiveness in the guest by
890 3efda49d balrog
     * signaling TS events immediately, but for now we simulate
891 3efda49d balrog
     * the first conversion delay for sake of correctness.
892 3efda49d balrog
     */
893 3efda49d balrog
    if (p != s->pressure)
894 3efda49d balrog
        tsc210x_pin_update(s);
895 3efda49d balrog
}
896 3efda49d balrog
897 d8f699cb balrog
static void tsc210x_i2s_swallow(struct tsc210x_state_s *s)
898 d8f699cb balrog
{
899 d8f699cb balrog
    if (s->dac_voice[0])
900 d8f699cb balrog
        tsc210x_out_flush(s, s->codec.out.len);
901 d8f699cb balrog
    else
902 d8f699cb balrog
        s->codec.out.len = 0;
903 d8f699cb balrog
}
904 d8f699cb balrog
905 d8f699cb balrog
static void tsc210x_i2s_set_rate(struct tsc210x_state_s *s, int in, int out)
906 d8f699cb balrog
{
907 d8f699cb balrog
    s->i2s_tx_rate = out;
908 d8f699cb balrog
    s->i2s_rx_rate = in;
909 d8f699cb balrog
}
910 d8f699cb balrog
911 3efda49d balrog
static void tsc210x_save(QEMUFile *f, void *opaque)
912 3efda49d balrog
{
913 3efda49d balrog
    struct tsc210x_state_s *s = (struct tsc210x_state_s *) opaque;
914 3efda49d balrog
    int64_t now = qemu_get_clock(vm_clock);
915 3efda49d balrog
    int i;
916 3efda49d balrog
917 3efda49d balrog
    qemu_put_be16(f, s->x);
918 3efda49d balrog
    qemu_put_be16(f, s->y);
919 3efda49d balrog
    qemu_put_byte(f, s->pressure);
920 3efda49d balrog
921 3efda49d balrog
    qemu_put_byte(f, s->state);
922 3efda49d balrog
    qemu_put_byte(f, s->page);
923 3efda49d balrog
    qemu_put_byte(f, s->offset);
924 3efda49d balrog
    qemu_put_byte(f, s->command);
925 3efda49d balrog
926 3efda49d balrog
    qemu_put_byte(f, s->irq);
927 3efda49d balrog
    qemu_put_be16s(f, &s->dav);
928 3efda49d balrog
929 3efda49d balrog
    qemu_put_timer(f, s->timer);
930 3efda49d balrog
    qemu_put_byte(f, s->enabled);
931 3efda49d balrog
    qemu_put_byte(f, s->host_mode);
932 3efda49d balrog
    qemu_put_byte(f, s->function);
933 3efda49d balrog
    qemu_put_byte(f, s->nextfunction);
934 3efda49d balrog
    qemu_put_byte(f, s->precision);
935 3efda49d balrog
    qemu_put_byte(f, s->nextprecision);
936 3efda49d balrog
    qemu_put_byte(f, s->filter);
937 3efda49d balrog
    qemu_put_byte(f, s->pin_func);
938 3efda49d balrog
    qemu_put_byte(f, s->ref);
939 3efda49d balrog
    qemu_put_byte(f, s->timing);
940 3efda49d balrog
    qemu_put_be32(f, s->noise);
941 3efda49d balrog
942 3efda49d balrog
    qemu_put_be16s(f, &s->audio_ctrl1);
943 3efda49d balrog
    qemu_put_be16s(f, &s->audio_ctrl2);
944 3efda49d balrog
    qemu_put_be16s(f, &s->audio_ctrl3);
945 3efda49d balrog
    qemu_put_be16s(f, &s->pll[0]);
946 3efda49d balrog
    qemu_put_be16s(f, &s->pll[1]);
947 3efda49d balrog
    qemu_put_be16s(f, &s->volume);
948 3efda49d balrog
    qemu_put_be64(f, (uint64_t) (s->volume_change - now));
949 3efda49d balrog
    qemu_put_be64(f, (uint64_t) (s->powerdown - now));
950 3efda49d balrog
    qemu_put_byte(f, s->softstep);
951 3efda49d balrog
    qemu_put_be16s(f, &s->dac_power);
952 3efda49d balrog
953 3efda49d balrog
    for (i = 0; i < 0x14; i ++)
954 3efda49d balrog
        qemu_put_be16s(f, &s->filter_data[i]);
955 3efda49d balrog
}
956 3efda49d balrog
957 3efda49d balrog
static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
958 3efda49d balrog
{
959 3efda49d balrog
    struct tsc210x_state_s *s = (struct tsc210x_state_s *) opaque;
960 3efda49d balrog
    int64_t now = qemu_get_clock(vm_clock);
961 3efda49d balrog
    int i;
962 3efda49d balrog
963 3efda49d balrog
    s->x = qemu_get_be16(f);
964 3efda49d balrog
    s->y = qemu_get_be16(f);
965 3efda49d balrog
    s->pressure = qemu_get_byte(f);
966 3efda49d balrog
967 3efda49d balrog
    s->state = qemu_get_byte(f);
968 3efda49d balrog
    s->page = qemu_get_byte(f);
969 3efda49d balrog
    s->offset = qemu_get_byte(f);
970 3efda49d balrog
    s->command = qemu_get_byte(f);
971 3efda49d balrog
972 3efda49d balrog
    s->irq = qemu_get_byte(f);
973 3efda49d balrog
    qemu_get_be16s(f, &s->dav);
974 3efda49d balrog
975 3efda49d balrog
    qemu_get_timer(f, s->timer);
976 3efda49d balrog
    s->enabled = qemu_get_byte(f);
977 3efda49d balrog
    s->host_mode = qemu_get_byte(f);
978 3efda49d balrog
    s->function = qemu_get_byte(f);
979 3efda49d balrog
    s->nextfunction = qemu_get_byte(f);
980 3efda49d balrog
    s->precision = qemu_get_byte(f);
981 3efda49d balrog
    s->nextprecision = qemu_get_byte(f);
982 3efda49d balrog
    s->filter = qemu_get_byte(f);
983 3efda49d balrog
    s->pin_func = qemu_get_byte(f);
984 3efda49d balrog
    s->ref = qemu_get_byte(f);
985 3efda49d balrog
    s->timing = qemu_get_byte(f);
986 3efda49d balrog
    s->noise = qemu_get_be32(f);
987 3efda49d balrog
988 3efda49d balrog
    qemu_get_be16s(f, &s->audio_ctrl1);
989 3efda49d balrog
    qemu_get_be16s(f, &s->audio_ctrl2);
990 3efda49d balrog
    qemu_get_be16s(f, &s->audio_ctrl3);
991 3efda49d balrog
    qemu_get_be16s(f, &s->pll[0]);
992 3efda49d balrog
    qemu_get_be16s(f, &s->pll[1]);
993 3efda49d balrog
    qemu_get_be16s(f, &s->volume);
994 3efda49d balrog
    s->volume_change = (int64_t) qemu_get_be64(f) + now;
995 3efda49d balrog
    s->powerdown = (int64_t) qemu_get_be64(f) + now;
996 3efda49d balrog
    s->softstep = qemu_get_byte(f);
997 3efda49d balrog
    qemu_get_be16s(f, &s->dac_power);
998 3efda49d balrog
999 3efda49d balrog
    for (i = 0; i < 0x14; i ++)
1000 3efda49d balrog
        qemu_get_be16s(f, &s->filter_data[i]);
1001 3efda49d balrog
1002 3efda49d balrog
    s->busy = qemu_timer_pending(s->timer);
1003 7fc42b4b balrog
    qemu_set_irq(s->pint, !s->irq);
1004 3efda49d balrog
1005 3efda49d balrog
    return 0;
1006 3efda49d balrog
}
1007 3efda49d balrog
1008 3efda49d balrog
static int tsc2102_iid = 0;
1009 3efda49d balrog
1010 d8f699cb balrog
struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio)
1011 3efda49d balrog
{
1012 3efda49d balrog
    struct tsc210x_state_s *s;
1013 3efda49d balrog
1014 3efda49d balrog
    s = (struct tsc210x_state_s *)
1015 3efda49d balrog
            qemu_mallocz(sizeof(struct tsc210x_state_s));
1016 3efda49d balrog
    memset(s, 0, sizeof(struct tsc210x_state_s));
1017 3efda49d balrog
    s->x = 160;
1018 3efda49d balrog
    s->y = 160;
1019 3efda49d balrog
    s->pressure = 0;
1020 3efda49d balrog
    s->precision = s->nextprecision = 0;
1021 3efda49d balrog
    s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s);
1022 3efda49d balrog
    s->pint = pint;
1023 d8f699cb balrog
    s->name = "tsc2102";
1024 d8f699cb balrog
    s->audio = audio;
1025 3efda49d balrog
1026 3efda49d balrog
    s->chip.opaque = s;
1027 3efda49d balrog
    s->chip.send = (void *) tsc210x_write;
1028 3efda49d balrog
    s->chip.receive = (void *) tsc210x_read;
1029 3efda49d balrog
1030 d8f699cb balrog
    s->codec.opaque = s;
1031 d8f699cb balrog
    s->codec.tx_swallow = (void *) tsc210x_i2s_swallow;
1032 d8f699cb balrog
    s->codec.set_rate = (void *) tsc210x_i2s_set_rate;
1033 d8f699cb balrog
    s->codec.in.fifo = s->in_fifo;
1034 d8f699cb balrog
    s->codec.out.fifo = s->out_fifo;
1035 d8f699cb balrog
1036 3efda49d balrog
    tsc210x_reset(s);
1037 3efda49d balrog
1038 3efda49d balrog
    qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1,
1039 3efda49d balrog
                    "QEMU TSC2102-driven Touchscreen");
1040 3efda49d balrog
1041 d8f699cb balrog
    if (s->audio)
1042 d8f699cb balrog
        AUD_register_card(s->audio, s->name, &s->card);
1043 d8f699cb balrog
1044 3efda49d balrog
    qemu_register_reset((void *) tsc210x_reset, s);
1045 d8f699cb balrog
    register_savevm(s->name, tsc2102_iid ++, 0,
1046 3efda49d balrog
                    tsc210x_save, tsc210x_load, s);
1047 3efda49d balrog
1048 3efda49d balrog
    return &s->chip;
1049 3efda49d balrog
}
1050 d8f699cb balrog
1051 d8f699cb balrog
struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip)
1052 d8f699cb balrog
{
1053 d8f699cb balrog
    struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque;
1054 d8f699cb balrog
1055 d8f699cb balrog
    return &s->codec;
1056 d8f699cb balrog
}