* 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
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "hw.h"
#include "audio/audio.h"
#include "qemu-timer.h"
#include "console.h"
-#include "omap.h"
+#include "omap.h" /* For I2SCodec and uWireSlave */
+#include "devices.h"
#define TSC_DATA_REGISTERS_PAGE 0x0
#define TSC_CONTROL_REGISTERS_PAGE 0x1
#define TSC_CUT_RESOLUTION(value, p) ((value) >> (16 - resolution[p]))
-struct tsc210x_state_s {
+typedef struct {
qemu_irq pint;
qemu_irq kbint;
qemu_irq davint;
QEMUTimer *timer;
QEMUSoundCard card;
- struct uwire_slave_s chip;
- struct i2s_codec_s codec;
+ uWireSlave chip;
+ I2SCodec codec;
uint8_t in_fifo[16384];
uint8_t out_fifo[16384];
uint16_t model;
SWVoiceOut *dac_voice[1];
int i2s_rx_rate;
int i2s_tx_rate;
- AudioState *audio;
int tr[8];
int mode;
int intr;
} kb;
-};
+} TSC210xState;
static const int resolution[4] = { 12, 8, 10, 12 };
#define TSC_POWEROFF_DELAY 50
#define TSC_SOFTSTEP_DELAY 50
-static void tsc210x_reset(struct tsc210x_state_s *s)
+static void tsc210x_reset(TSC210xState *s)
{
s->state = 0;
s->pin_func = 2;
qemu_irq_raise(s->kbint);
}
-struct tsc210x_rate_info_s {
+typedef struct {
int rate;
int dsor;
int fsref;
-};
+} TSC210xRateInfo;
/* { rate, dsor, fsref } */
-static const struct tsc210x_rate_info_s tsc2101_rates[] = {
+static const TSC210xRateInfo tsc2101_rates[] = {
/* Fsref / 6.0 */
{ 7350, 7, 1 },
{ 8000, 7, 0 },
};
/* { rate, dsor, fsref } */
-static const struct tsc210x_rate_info_s tsc2102_rates[] = {
+static const TSC210xRateInfo tsc2102_rates[] = {
/* Fsref / 6.0 */
{ 7350, 63, 1 },
{ 8000, 63, 0 },
{ 0, 0, 0 },
};
-static inline void tsc210x_out_flush(struct tsc210x_state_s *s, int len)
+static inline void tsc210x_out_flush(TSC210xState *s, int len)
{
uint8_t *data = s->codec.out.fifo + s->codec.out.start;
uint8_t *end = data + len;
s->codec.out.start = 0;
}
-static void tsc210x_audio_out_cb(struct tsc210x_state_s *s, int free_b)
+static void tsc210x_audio_out_cb(TSC210xState *s, int free_b)
{
if (s->codec.out.len >= free_b) {
tsc210x_out_flush(s, free_b);
qemu_irq_raise(s->codec.tx_start);
}
-static void tsc2102_audio_rate_update(struct tsc210x_state_s *s)
+static void tsc2102_audio_rate_update(TSC210xState *s)
{
- const struct tsc210x_rate_info_s *rate;
+ const TSC210xRateInfo *rate;
s->codec.tx_rate = 0;
s->codec.rx_rate = 0;
s->codec.tx_rate = rate->rate;
}
-static void tsc2102_audio_output_update(struct tsc210x_state_s *s)
+static void tsc2102_audio_output_update(TSC210xState *s)
{
int enable;
- audsettings_t fmt;
+ struct audsettings 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->dac_voice[0] = NULL;
}
s->codec.cts = 0;
}
}
-static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg)
+static uint16_t tsc2102_data_register_read(TSC210xState *s, int reg)
{
switch (reg) {
case 0x00: /* X */
}
static uint16_t tsc2102_control_register_read(
- struct tsc210x_state_s *s, int reg)
+ TSC210xState *s, int reg)
{
switch (reg) {
case 0x00: /* TSC ADC */
}
}
-static uint16_t tsc2102_audio_register_read(struct tsc210x_state_s *s, int reg)
+static uint16_t tsc2102_audio_register_read(TSC210xState *s, int reg)
{
int l_ch, r_ch;
uint16_t val;
l_ch = 1;
r_ch = 1;
if (s->softstep && !(s->dac_power & (1 << 10))) {
- l_ch = (qemu_get_clock(vm_clock) >
+ l_ch = (qemu_get_clock_ns(vm_clock) >
s->volume_change + TSC_SOFTSTEP_DELAY);
- r_ch = (qemu_get_clock(vm_clock) >
+ r_ch = (qemu_get_clock_ns(vm_clock) >
s->volume_change + TSC_SOFTSTEP_DELAY);
}
case 0x05: /* Stereo DAC Power Control */
return 0x2aa0 | s->dac_power |
(((s->dac_power & (1 << 10)) &&
- (qemu_get_clock(vm_clock) >
+ (qemu_get_clock_ns(vm_clock) >
s->powerdown + TSC_POWEROFF_DELAY)) << 6);
case 0x06: /* Audio Control 3 */
}
static void tsc2102_data_register_write(
- struct tsc210x_state_s *s, int reg, uint16_t value)
+ TSC210xState *s, int reg, uint16_t value)
{
switch (reg) {
case 0x00: /* X */
}
static void tsc2102_control_register_write(
- struct tsc210x_state_s *s, int reg, uint16_t value)
+ TSC210xState *s, int reg, uint16_t value)
{
switch (reg) {
case 0x00: /* TSC ADC */
}
static void tsc2102_audio_register_write(
- struct tsc210x_state_s *s, int reg, uint16_t value)
+ TSC210xState *s, int reg, uint16_t value)
{
switch (reg) {
case 0x00: /* Audio Control 1 */
"wrong value written into Audio 1\n");
#endif
tsc2102_audio_rate_update(s);
- if (s->audio)
- tsc2102_audio_output_update(s);
+ tsc2102_audio_output_update(s);
return;
case 0x01:
case 0x02: /* DAC Volume Control */
s->volume = value;
- s->volume_change = qemu_get_clock(vm_clock);
+ s->volume_change = qemu_get_clock_ns(vm_clock);
return;
case 0x03:
case 0x05: /* Stereo DAC Power Control */
if ((value & ~s->dac_power) & (1 << 10))
- s->powerdown = qemu_get_clock(vm_clock);
+ s->powerdown = qemu_get_clock_ns(vm_clock);
s->dac_power = value & 0x9543;
#ifdef TSC_VERBOSE
"wrong value written into Power\n");
#endif
tsc2102_audio_rate_update(s);
- if (s->audio)
- tsc2102_audio_output_update(s);
+ tsc2102_audio_output_update(s);
return;
case 0x06: /* Audio Control 3 */
fprintf(stderr, "tsc2102_audio_register_write: "
"wrong value written into Audio 3\n");
#endif
- if (s->audio)
- tsc2102_audio_output_update(s);
+ tsc2102_audio_output_update(s);
return;
case 0x07: /* LCH_BASS_BOOST_N0 */
}
/* This handles most of the chip logic. */
-static void tsc210x_pin_update(struct tsc210x_state_s *s)
+static void tsc210x_pin_update(TSC210xState *s)
{
int64_t expires;
int pin_state;
s->busy = 1;
s->precision = s->nextprecision;
s->function = s->nextfunction;
- expires = qemu_get_clock(vm_clock) + (ticks_per_sec >> 10);
+ expires = qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() >> 10);
qemu_mod_timer(s->timer, expires);
}
-static uint16_t tsc210x_read(struct tsc210x_state_s *s)
+static uint16_t tsc210x_read(TSC210xState *s)
{
uint16_t ret = 0x0000;
ret = tsc2102_audio_register_read(s, s->offset);
break;
default:
- cpu_abort(cpu_single_env, "tsc210x_read: wrong memory page\n");
+ hw_error("tsc210x_read: wrong memory page\n");
}
tsc210x_pin_update(s);
return ret;
}
-static void tsc210x_write(struct tsc210x_state_s *s, uint16_t value)
+static void tsc210x_write(TSC210xState *s, uint16_t value)
{
/*
* This is a two-state state machine for reading
tsc2102_audio_register_write(s, s->offset, value);
break;
default:
- cpu_abort(cpu_single_env,
- "tsc210x_write: wrong memory page\n");
+ hw_error("tsc210x_write: wrong memory page\n");
}
tsc210x_pin_update(s);
uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len)
{
- struct tsc210x_state_s *s = opaque;
+ TSC210xState *s = opaque;
uint32_t ret = 0;
if (len != 16)
- cpu_abort(cpu_single_env, "%s: FIXME: bad SPI word width %i\n",
- __FUNCTION__, len);
+ hw_error("%s: FIXME: bad SPI word width %i\n", __FUNCTION__, len);
/* TODO: sequential reads etc - how do we make sure the host doesn't
* unintentionally read out a conversion result from a register while
static void tsc210x_timer_tick(void *opaque)
{
- struct tsc210x_state_s *s = opaque;
+ TSC210xState *s = opaque;
/* Timer ticked -- a set of conversions has been finished. */
static void tsc210x_touchscreen_event(void *opaque,
int x, int y, int z, int buttons_state)
{
- struct tsc210x_state_s *s = opaque;
+ TSC210xState *s = opaque;
int p = s->pressure;
if (buttons_state) {
tsc210x_pin_update(s);
}
-static void tsc210x_i2s_swallow(struct tsc210x_state_s *s)
+static void tsc210x_i2s_swallow(TSC210xState *s)
{
if (s->dac_voice[0])
tsc210x_out_flush(s, s->codec.out.len);
s->codec.out.len = 0;
}
-static void tsc210x_i2s_set_rate(struct tsc210x_state_s *s, int in, int out)
+static void tsc210x_i2s_set_rate(TSC210xState *s, int in, int out)
{
s->i2s_tx_rate = out;
s->i2s_rx_rate = in;
static void tsc210x_save(QEMUFile *f, void *opaque)
{
- struct tsc210x_state_s *s = (struct tsc210x_state_s *) opaque;
- int64_t now = qemu_get_clock(vm_clock);
+ TSC210xState *s = (TSC210xState *) opaque;
+ int64_t now = qemu_get_clock_ns(vm_clock);
int i;
qemu_put_be16(f, s->x);
qemu_put_be16s(f, &s->pll[0]);
qemu_put_be16s(f, &s->pll[1]);
qemu_put_be16s(f, &s->volume);
- qemu_put_be64(f, (uint64_t) (s->volume_change - now));
- qemu_put_be64(f, (uint64_t) (s->powerdown - now));
+ qemu_put_sbe64(f, (s->volume_change - now));
+ qemu_put_sbe64(f, (s->powerdown - now));
qemu_put_byte(f, s->softstep);
qemu_put_be16s(f, &s->dac_power);
static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
{
- struct tsc210x_state_s *s = (struct tsc210x_state_s *) opaque;
- int64_t now = qemu_get_clock(vm_clock);
+ TSC210xState *s = (TSC210xState *) opaque;
+ int64_t now = qemu_get_clock_ns(vm_clock);
int i;
s->x = qemu_get_be16(f);
qemu_get_be16s(f, &s->pll[0]);
qemu_get_be16s(f, &s->pll[1]);
qemu_get_be16s(f, &s->volume);
- s->volume_change = (int64_t) qemu_get_be64(f) + now;
- s->powerdown = (int64_t) qemu_get_be64(f) + now;
+ s->volume_change = qemu_get_sbe64(f) + now;
+ s->powerdown = qemu_get_sbe64(f) + now;
s->softstep = qemu_get_byte(f);
qemu_get_be16s(f, &s->dac_power);
return 0;
}
-static int tsc2102_iid = 0;
-
-struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio)
+uWireSlave *tsc2102_init(qemu_irq pint)
{
- struct tsc210x_state_s *s;
+ TSC210xState *s;
- s = (struct tsc210x_state_s *)
- qemu_mallocz(sizeof(struct tsc210x_state_s));
- memset(s, 0, sizeof(struct tsc210x_state_s));
+ s = (TSC210xState *)
+ g_malloc0(sizeof(TSC210xState));
+ memset(s, 0, sizeof(TSC210xState));
s->x = 160;
s->y = 160;
s->pressure = 0;
s->precision = s->nextprecision = 0;
- s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s);
+ s->timer = qemu_new_timer_ns(vm_clock, tsc210x_timer_tick, s);
s->pint = pint;
s->model = 0x2102;
s->name = "tsc2102";
- s->audio = audio;
s->tr[0] = 0;
s->tr[1] = 1;
qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1,
"QEMU TSC2102-driven Touchscreen");
- if (s->audio)
- AUD_register_card(s->audio, s->name, &s->card);
+ AUD_register_card(s->name, &s->card);
qemu_register_reset((void *) tsc210x_reset, s);
- register_savevm(s->name, tsc2102_iid ++, 0,
+ register_savevm(NULL, s->name, -1, 0,
tsc210x_save, tsc210x_load, s);
return &s->chip;
}
-struct uwire_slave_s *tsc2301_init(qemu_irq penirq, qemu_irq kbirq,
- qemu_irq dav, AudioState *audio)
+uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav)
{
- struct tsc210x_state_s *s;
+ TSC210xState *s;
- s = (struct tsc210x_state_s *)
- qemu_mallocz(sizeof(struct tsc210x_state_s));
- memset(s, 0, sizeof(struct tsc210x_state_s));
+ s = (TSC210xState *)
+ g_malloc0(sizeof(TSC210xState));
+ memset(s, 0, sizeof(TSC210xState));
s->x = 400;
s->y = 240;
s->pressure = 0;
s->precision = s->nextprecision = 0;
- s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s);
+ s->timer = qemu_new_timer_ns(vm_clock, tsc210x_timer_tick, s);
s->pint = penirq;
s->kbint = kbirq;
s->davint = dav;
s->model = 0x2301;
s->name = "tsc2301";
- s->audio = audio;
s->tr[0] = 0;
s->tr[1] = 1;
qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1,
"QEMU TSC2301-driven Touchscreen");
- if (s->audio)
- AUD_register_card(s->audio, s->name, &s->card);
+ AUD_register_card(s->name, &s->card);
qemu_register_reset((void *) tsc210x_reset, s);
- register_savevm(s->name, tsc2102_iid ++, 0,
- tsc210x_save, tsc210x_load, s);
+ register_savevm(NULL, s->name, -1, 0, tsc210x_save, tsc210x_load, s);
return &s->chip;
}
-struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip)
+I2SCodec *tsc210x_codec(uWireSlave *chip)
{
- struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque;
+ TSC210xState *s = (TSC210xState *) chip->opaque;
return &s->codec;
}
* from the touchscreen. Assuming 12-bit precision was used during
* tslib calibration.
*/
-void tsc210x_set_transform(struct uwire_slave_s *chip,
- struct mouse_transform_info_s *info)
+void tsc210x_set_transform(uWireSlave *chip,
+ MouseTransformInfo *info)
{
- struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque;
+ TSC210xState *s = (TSC210xState *) chip->opaque;
#if 0
int64_t ltr[8];
#endif
}
-void tsc210x_key_event(struct uwire_slave_s *chip, int key, int down)
+void tsc210x_key_event(uWireSlave *chip, int key, int down)
{
- struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque;
+ TSC210xState *s = (TSC210xState *) chip->opaque;
if (down)
s->kb.down |= 1 << key;