📄 tsc210x.c
字号:
switch (reg) { case 0x00: /* TSC ADC */ return (s->pressure << 15) | ((!s->busy) << 14) | (s->nextfunction << 10) | (s->nextprecision << 8) | s->filter; case 0x01: /* Status / Keypad Control */ if ((s->model & 0xff00) == 0x2100) return (s->pin_func << 14) | ((!s->enabled) << 13) | (s->host_mode << 12) | ((!!s->dav) << 11) | s->dav; else return (s->kb.intr << 15) | ((s->kb.scan || !s->kb.down) << 14) | (s->kb.debounce << 11); case 0x02: /* DAC Control */ if ((s->model & 0xff00) == 0x2300) return s->dac_power & 0x8000; else goto bad_reg; case 0x03: /* Reference */ return s->ref; case 0x04: /* Reset */ return 0xffff; case 0x05: /* Configuration */ return s->timing; case 0x06: /* Secondary configuration */ if ((s->model & 0xff00) == 0x2100) goto bad_reg; return ((!s->dav) << 15) | ((s->kb.mode & 1) << 14) | s->pll[2]; case 0x10: /* Keypad Mask */ if ((s->model & 0xff00) == 0x2100) goto bad_reg; return s->kb.mask; default: bad_reg:#ifdef TSC_VERBOSE fprintf(stderr, "tsc2102_control_register_read: " "no such register: 0x%02x\n", reg);#endif return 0xffff; }}static uint16_t tsc2102_audio_register_read(struct tsc210x_state_s *s, int reg){ int l_ch, r_ch; uint16_t val; switch (reg) { case 0x00: /* Audio Control 1 */ return s->audio_ctrl1; case 0x01: return 0xff00; case 0x02: /* DAC Volume Control */ return s->volume; case 0x03: return 0x8b00; case 0x04: /* Audio Control 2 */ l_ch = 1; r_ch = 1; if (s->softstep && !(s->dac_power & (1 << 10))) { l_ch = (qemu_get_clock(vm_clock) > s->volume_change + TSC_SOFTSTEP_DELAY); r_ch = (qemu_get_clock(vm_clock) > s->volume_change + TSC_SOFTSTEP_DELAY); } return s->audio_ctrl2 | (l_ch << 3) | (r_ch << 2); case 0x05: /* Stereo DAC Power Control */ return 0x2aa0 | s->dac_power | (((s->dac_power & (1 << 10)) && (qemu_get_clock(vm_clock) > s->powerdown + TSC_POWEROFF_DELAY)) << 6); case 0x06: /* Audio Control 3 */ val = s->audio_ctrl3 | 0x0001; s->audio_ctrl3 &= 0xff3f; return val; case 0x07: /* LCH_BASS_BOOST_N0 */ case 0x08: /* LCH_BASS_BOOST_N1 */ case 0x09: /* LCH_BASS_BOOST_N2 */ case 0x0a: /* LCH_BASS_BOOST_N3 */ case 0x0b: /* LCH_BASS_BOOST_N4 */ case 0x0c: /* LCH_BASS_BOOST_N5 */ case 0x0d: /* LCH_BASS_BOOST_D1 */ case 0x0e: /* LCH_BASS_BOOST_D2 */ case 0x0f: /* LCH_BASS_BOOST_D4 */ case 0x10: /* LCH_BASS_BOOST_D5 */ case 0x11: /* RCH_BASS_BOOST_N0 */ case 0x12: /* RCH_BASS_BOOST_N1 */ case 0x13: /* RCH_BASS_BOOST_N2 */ case 0x14: /* RCH_BASS_BOOST_N3 */ case 0x15: /* RCH_BASS_BOOST_N4 */ case 0x16: /* RCH_BASS_BOOST_N5 */ case 0x17: /* RCH_BASS_BOOST_D1 */ case 0x18: /* RCH_BASS_BOOST_D2 */ case 0x19: /* RCH_BASS_BOOST_D4 */ case 0x1a: /* RCH_BASS_BOOST_D5 */ return s->filter_data[reg - 0x07]; case 0x1b: /* PLL Programmability 1 */ return s->pll[0]; case 0x1c: /* PLL Programmability 2 */ return s->pll[1]; case 0x1d: /* Audio Control 4 */ return (!s->softstep) << 14; default:#ifdef TSC_VERBOSE fprintf(stderr, "tsc2102_audio_register_read: " "no such register: 0x%02x\n", reg);#endif return 0xffff; }}static void tsc2102_data_register_write( struct tsc210x_state_s *s, int reg, uint16_t value){ switch (reg) { case 0x00: /* X */ case 0x01: /* Y */ case 0x02: /* Z1 */ case 0x03: /* Z2 */ case 0x05: /* BAT1 */ case 0x06: /* BAT2 */ case 0x07: /* AUX1 */ case 0x08: /* AUX2 */ case 0x09: /* TEMP1 */ case 0x0a: /* TEMP2 */ return; default:#ifdef TSC_VERBOSE fprintf(stderr, "tsc2102_data_register_write: " "no such register: 0x%02x\n", reg);#endif }}static void tsc2102_control_register_write( struct tsc210x_state_s *s, int reg, uint16_t value){ switch (reg) { case 0x00: /* TSC ADC */ s->host_mode = value >> 15; s->enabled = !(value & 0x4000); if (s->busy && !s->enabled) qemu_del_timer(s->timer); s->busy &= s->enabled; s->nextfunction = (value >> 10) & 0xf; s->nextprecision = (value >> 8) & 3; s->filter = value & 0xff; return; case 0x01: /* Status / Keypad Control */ if ((s->model & 0xff00) == 0x2100) s->pin_func = value >> 14; else { s->kb.scan = (value >> 14) & 1; s->kb.debounce = (value >> 11) & 7; if (s->kb.intr && s->kb.scan) { s->kb.intr = 0; qemu_irq_raise(s->kbint); } } return; case 0x02: /* DAC Control */ if ((s->model & 0xff00) == 0x2300) { s->dac_power &= 0x7fff; s->dac_power |= 0x8000 & value; } else goto bad_reg; break; case 0x03: /* Reference */ s->ref = value & 0x1f; return; case 0x04: /* Reset */ if (value == 0xbb00) { if (s->busy) qemu_del_timer(s->timer); tsc210x_reset(s);#ifdef TSC_VERBOSE } else { fprintf(stderr, "tsc2102_control_register_write: " "wrong value written into RESET\n");#endif } return; case 0x05: /* Configuration */ s->timing = value & 0x3f;#ifdef TSC_VERBOSE if (value & ~0x3f) fprintf(stderr, "tsc2102_control_register_write: " "wrong value written into CONFIG\n");#endif return; case 0x06: /* Secondary configuration */ if ((s->model & 0xff00) == 0x2100) goto bad_reg; s->kb.mode = value >> 14; s->pll[2] = value & 0x3ffff; return; case 0x10: /* Keypad Mask */ if ((s->model & 0xff00) == 0x2100) goto bad_reg; s->kb.mask = value; return; default: bad_reg:#ifdef TSC_VERBOSE fprintf(stderr, "tsc2102_control_register_write: " "no such register: 0x%02x\n", reg);#endif }}static void tsc2102_audio_register_write( struct tsc210x_state_s *s, int reg, uint16_t value){ switch (reg) { case 0x00: /* Audio Control 1 */ s->audio_ctrl1 = value & 0x0f3f;#ifdef TSC_VERBOSE if ((value & ~0x0f3f) || ((value & 7) != ((value >> 3) & 7))) fprintf(stderr, "tsc2102_audio_register_write: " "wrong value written into Audio 1\n");#endif tsc2102_audio_rate_update(s); if (s->audio) tsc2102_audio_output_update(s); return; case 0x01:#ifdef TSC_VERBOSE if (value != 0xff00) fprintf(stderr, "tsc2102_audio_register_write: " "wrong value written into reg 0x01\n");#endif return; case 0x02: /* DAC Volume Control */ s->volume = value; s->volume_change = qemu_get_clock(vm_clock); return; case 0x03:#ifdef TSC_VERBOSE if (value != 0x8b00) fprintf(stderr, "tsc2102_audio_register_write: " "wrong value written into reg 0x03\n");#endif return; case 0x04: /* Audio Control 2 */ s->audio_ctrl2 = value & 0xf7f2;#ifdef TSC_VERBOSE if (value & ~0xf7fd) fprintf(stderr, "tsc2102_audio_register_write: " "wrong value written into Audio 2\n");#endif return; case 0x05: /* Stereo DAC Power Control */ if ((value & ~s->dac_power) & (1 << 10)) s->powerdown = qemu_get_clock(vm_clock); s->dac_power = value & 0x9543;#ifdef TSC_VERBOSE if ((value & ~0x9543) != 0x2aa0) fprintf(stderr, "tsc2102_audio_register_write: " "wrong value written into Power\n");#endif tsc2102_audio_rate_update(s); if (s->audio) tsc2102_audio_output_update(s); return; case 0x06: /* Audio Control 3 */ s->audio_ctrl3 &= 0x00c0; s->audio_ctrl3 |= value & 0xf800;#ifdef TSC_VERBOSE if (value & ~0xf8c7) fprintf(stderr, "tsc2102_audio_register_write: " "wrong value written into Audio 3\n");#endif if (s->audio) tsc2102_audio_output_update(s); return; case 0x07: /* LCH_BASS_BOOST_N0 */ case 0x08: /* LCH_BASS_BOOST_N1 */ case 0x09: /* LCH_BASS_BOOST_N2 */ case 0x0a: /* LCH_BASS_BOOST_N3 */ case 0x0b: /* LCH_BASS_BOOST_N4 */ case 0x0c: /* LCH_BASS_BOOST_N5 */ case 0x0d: /* LCH_BASS_BOOST_D1 */ case 0x0e: /* LCH_BASS_BOOST_D2 */ case 0x0f: /* LCH_BASS_BOOST_D4 */ case 0x10: /* LCH_BASS_BOOST_D5 */ case 0x11: /* RCH_BASS_BOOST_N0 */ case 0x12: /* RCH_BASS_BOOST_N1 */ case 0x13: /* RCH_BASS_BOOST_N2 */ case 0x14: /* RCH_BASS_BOOST_N3 */ case 0x15: /* RCH_BASS_BOOST_N4 */ case 0x16: /* RCH_BASS_BOOST_N5 */ case 0x17: /* RCH_BASS_BOOST_D1 */ case 0x18: /* RCH_BASS_BOOST_D2 */ case 0x19: /* RCH_BASS_BOOST_D4 */ case 0x1a: /* RCH_BASS_BOOST_D5 */ s->filter_data[reg - 0x07] = value; return; case 0x1b: /* PLL Programmability 1 */ s->pll[0] = value & 0xfffc;#ifdef TSC_VERBOSE if (value & ~0xfffc) fprintf(stderr, "tsc2102_audio_register_write: " "wrong value written into PLL 1\n");#endif return; case 0x1c: /* PLL Programmability 2 */ s->pll[1] = value & 0xfffc;#ifdef TSC_VERBOSE if (value & ~0xfffc) fprintf(stderr, "tsc2102_audio_register_write: " "wrong value written into PLL 2\n");#endif return; case 0x1d: /* Audio Control 4 */ s->softstep = !(value & 0x4000);#ifdef TSC_VERBOSE if (value & ~0x4000) fprintf(stderr, "tsc2102_audio_register_write: " "wrong value written into Audio 4\n");#endif return; default:#ifdef TSC_VERBOSE fprintf(stderr, "tsc2102_audio_register_write: " "no such register: 0x%02x\n", reg);#endif }}/* This handles most of the chip logic. */static void tsc210x_pin_update(struct tsc210x_state_s *s){ int64_t expires; int pin_state; switch (s->pin_func) { case 0: pin_state = s->pressure; break; case 1: pin_state = !!s->dav; break; case 2: default: pin_state = s->pressure && !s->dav; } if (!s->enabled) pin_state = 0; if (pin_state != s->irq) { s->irq = pin_state; qemu_set_irq(s->pint, !s->irq); } switch (s->nextfunction) { case TSC_MODE_XY_SCAN: case TSC_MODE_XYZ_SCAN: if (!s->pressure) return; break; case TSC_MODE_X: case TSC_MODE_Y: case TSC_MODE_Z: if (!s->pressure) return; /* Fall through */ case TSC_MODE_BAT1: case TSC_MODE_BAT2: case TSC_MODE_AUX: case TSC_MODE_TEMP1: case TSC_MODE_TEMP2: if (s->dav) s->enabled = 0; break; case TSC_MODE_AUX_SCAN: case TSC_MODE_PORT_SCAN: break; case TSC_MODE_NO_SCAN: case TSC_MODE_XX_DRV: case TSC_MODE_YY_DRV: case TSC_MODE_YX_DRV: default: return; } if (!s->enabled || s->busy || s->dav) return; s->busy = 1; s->precision = s->nextprecision; s->function = s->nextfunction; expires = qemu_get_clock(vm_clock) + (ticks_per_sec >> 10); qemu_mod_timer(s->timer, expires);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -