Commit d8f699cb32c8c418b65aa6a2c252e097ae4716ae

Authored by balrog
1 parent bfa30a38

Zeroing ITR shouldn't ack irq zero.

Fix PWT & PWL clocks, fix user refcounting for clocks, add 'hsab_ck' and 'usb_w2fc_ck'.
Fix TCMI register addresses.
Implement OMAP McBSP controller and connection to I2S-compatible CODECs.
Add audio support for TSC2102 as an I2S CODEC.
Connect TSC2102 I2S interface to CPU's McBSP1 interface in the Palm Tungsten|E.
Correct '>' instead of '>>' typos.
Implement GPIO PIN_CONTROL register (not in OMAP310 TRM, from OMAP1510).


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3534 c046a42c-6fe2-441c-8c8c-71466251a162
hw/omap.c
... ... @@ -254,7 +254,7 @@ static void omap_inth_write(void *opaque, target_phys_addr_t addr,
254 254  
255 255 switch (offset) {
256 256 case 0x00: /* ITR */
257   - s->irqs &= value;
  257 + s->irqs &= value | 1;
258 258 omap_inth_sir_update(s);
259 259 omap_inth_update(s);
260 260 return;
... ... @@ -992,7 +992,7 @@ static void omap_dma_clk_update(void *opaque, int line, int on)
992 992 struct omap_dma_s *s = (struct omap_dma_s *) opaque;
993 993  
994 994 if (on) {
995   - s->delay = ticks_per_sec >> 5;
  995 + s->delay = ticks_per_sec >> 7;
996 996 if (s->run_count)
997 997 qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay);
998 998 } else {
... ... @@ -1325,8 +1325,10 @@ static void omap_wd_timer_write(void *opaque, target_phys_addr_t addr,
1325 1325 s->mode |= (value >> 15) & 1;
1326 1326 if (s->last_wr == 0xf5) {
1327 1327 if ((value & 0xff) == 0xa0) {
1328   - s->mode = 0;
1329   - omap_clk_put(s->timer.clk);
  1328 + if (s->mode) {
  1329 + s->mode = 0;
  1330 + omap_clk_put(s->timer.clk);
  1331 + }
1330 1332 } else {
1331 1333 /* XXX: on T|E hardware somehow this has no effect,
1332 1334 * on Zire 71 it works as specified. */
... ... @@ -2217,23 +2219,23 @@ static uint32_t omap_tcmi_read(void *opaque, target_phys_addr_t addr)
2217 2219 uint32_t ret;
2218 2220  
2219 2221 switch (offset) {
2220   - case 0xfffecc00: /* IMIF_PRIO */
2221   - case 0xfffecc04: /* EMIFS_PRIO */
2222   - case 0xfffecc08: /* EMIFF_PRIO */
2223   - case 0xfffecc0c: /* EMIFS_CONFIG */
2224   - case 0xfffecc10: /* EMIFS_CS0_CONFIG */
2225   - case 0xfffecc14: /* EMIFS_CS1_CONFIG */
2226   - case 0xfffecc18: /* EMIFS_CS2_CONFIG */
2227   - case 0xfffecc1c: /* EMIFS_CS3_CONFIG */
2228   - case 0xfffecc24: /* EMIFF_MRS */
2229   - case 0xfffecc28: /* TIMEOUT1 */
2230   - case 0xfffecc2c: /* TIMEOUT2 */
2231   - case 0xfffecc30: /* TIMEOUT3 */
2232   - case 0xfffecc3c: /* EMIFF_SDRAM_CONFIG_2 */
2233   - case 0xfffecc40: /* EMIFS_CFG_DYN_WAIT */
  2222 + case 0x00: /* IMIF_PRIO */
  2223 + case 0x04: /* EMIFS_PRIO */
  2224 + case 0x08: /* EMIFF_PRIO */
  2225 + case 0x0c: /* EMIFS_CONFIG */
  2226 + case 0x10: /* EMIFS_CS0_CONFIG */
  2227 + case 0x14: /* EMIFS_CS1_CONFIG */
  2228 + case 0x18: /* EMIFS_CS2_CONFIG */
  2229 + case 0x1c: /* EMIFS_CS3_CONFIG */
  2230 + case 0x24: /* EMIFF_MRS */
  2231 + case 0x28: /* TIMEOUT1 */
  2232 + case 0x2c: /* TIMEOUT2 */
  2233 + case 0x30: /* TIMEOUT3 */
  2234 + case 0x3c: /* EMIFF_SDRAM_CONFIG_2 */
  2235 + case 0x40: /* EMIFS_CFG_DYN_WAIT */
2234 2236 return s->tcmi_regs[offset >> 2];
2235 2237  
2236   - case 0xfffecc20: /* EMIFF_SDRAM_CONFIG */
  2238 + case 0x20: /* EMIFF_SDRAM_CONFIG */
2237 2239 ret = s->tcmi_regs[offset >> 2];
2238 2240 s->tcmi_regs[offset >> 2] &= ~1; /* XXX: Clear SLRF on SDRAM access */
2239 2241 /* XXX: We can try using the VGA_DIRTY flag for this */
... ... @@ -2251,23 +2253,23 @@ static void omap_tcmi_write(void *opaque, target_phys_addr_t addr,
2251 2253 int offset = addr - s->tcmi_base;
2252 2254  
2253 2255 switch (offset) {
2254   - case 0xfffecc00: /* IMIF_PRIO */
2255   - case 0xfffecc04: /* EMIFS_PRIO */
2256   - case 0xfffecc08: /* EMIFF_PRIO */
2257   - case 0xfffecc10: /* EMIFS_CS0_CONFIG */
2258   - case 0xfffecc14: /* EMIFS_CS1_CONFIG */
2259   - case 0xfffecc18: /* EMIFS_CS2_CONFIG */
2260   - case 0xfffecc1c: /* EMIFS_CS3_CONFIG */
2261   - case 0xfffecc20: /* EMIFF_SDRAM_CONFIG */
2262   - case 0xfffecc24: /* EMIFF_MRS */
2263   - case 0xfffecc28: /* TIMEOUT1 */
2264   - case 0xfffecc2c: /* TIMEOUT2 */
2265   - case 0xfffecc30: /* TIMEOUT3 */
2266   - case 0xfffecc3c: /* EMIFF_SDRAM_CONFIG_2 */
2267   - case 0xfffecc40: /* EMIFS_CFG_DYN_WAIT */
  2256 + case 0x00: /* IMIF_PRIO */
  2257 + case 0x04: /* EMIFS_PRIO */
  2258 + case 0x08: /* EMIFF_PRIO */
  2259 + case 0x10: /* EMIFS_CS0_CONFIG */
  2260 + case 0x14: /* EMIFS_CS1_CONFIG */
  2261 + case 0x18: /* EMIFS_CS2_CONFIG */
  2262 + case 0x1c: /* EMIFS_CS3_CONFIG */
  2263 + case 0x20: /* EMIFF_SDRAM_CONFIG */
  2264 + case 0x24: /* EMIFF_MRS */
  2265 + case 0x28: /* TIMEOUT1 */
  2266 + case 0x2c: /* TIMEOUT2 */
  2267 + case 0x30: /* TIMEOUT3 */
  2268 + case 0x3c: /* EMIFF_SDRAM_CONFIG_2 */
  2269 + case 0x40: /* EMIFS_CFG_DYN_WAIT */
2268 2270 s->tcmi_regs[offset >> 2] = value;
2269 2271 break;
2270   - case 0xfffecc0c: /* EMIFS_CONFIG */
  2272 + case 0x0c: /* EMIFS_CONFIG */
2271 2273 s->tcmi_regs[offset >> 2] = (value & 0xf) | (1 << 4);
2272 2274 break;
2273 2275  
... ... @@ -2441,7 +2443,7 @@ static uint32_t omap_clkm_read(void *opaque, target_phys_addr_t addr)
2441 2443 return s->clkm.arm_rstct2;
2442 2444  
2443 2445 case 0x18: /* ARM_SYSST */
2444   - return (s->clkm.clocking_scheme < 11) | s->clkm.cold_start;
  2446 + return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start;
2445 2447  
2446 2448 case 0x1c: /* ARM_CKOUT1 */
2447 2449 return s->clkm.arm_ckout1;
... ... @@ -2720,7 +2722,7 @@ static uint32_t omap_clkdsp_read(void *opaque, target_phys_addr_t addr)
2720 2722 return s->clkm.dsp_rstct2;
2721 2723  
2722 2724 case 0x18: /* DSP_SYSST */
2723   - return (s->clkm.clocking_scheme < 11) | s->clkm.cold_start |
  2725 + return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
2724 2726 (s->env->halted << 6); /* Quite useless... */
2725 2727 }
2726 2728  
... ... @@ -2796,9 +2798,9 @@ static void omap_clkm_reset(struct omap_mpu_state_s *s)
2796 2798 s->clkm.clocking_scheme = 0;
2797 2799 omap_clkm_ckctl_update(s, ~0, 0x3000);
2798 2800 s->clkm.arm_ckctl = 0x3000;
2799   - omap_clkm_idlect1_update(s, s->clkm.arm_idlect1 & 0x0400, 0x0400);
  2801 + omap_clkm_idlect1_update(s, s->clkm.arm_idlect1 ^ 0x0400, 0x0400);
2800 2802 s->clkm.arm_idlect1 = 0x0400;
2801   - omap_clkm_idlect2_update(s, s->clkm.arm_idlect2 & 0x0100, 0x0100);
  2803 + omap_clkm_idlect2_update(s, s->clkm.arm_idlect2 ^ 0x0100, 0x0100);
2802 2804 s->clkm.arm_idlect2 = 0x0100;
2803 2805 s->clkm.arm_ewupct = 0x003f;
2804 2806 s->clkm.arm_rstct1 = 0x0000;
... ... @@ -2822,8 +2824,11 @@ static void omap_clkm_init(target_phys_addr_t mpu_base,
2822 2824  
2823 2825 s->clkm.mpu_base = mpu_base;
2824 2826 s->clkm.dsp_base = dsp_base;
2825   - s->clkm.cold_start = 0x3a;
  2827 + s->clkm.arm_idlect1 = 0x03ff;
  2828 + s->clkm.arm_idlect2 = 0x0100;
  2829 + s->clkm.dsp_idlect1 = 0x0002;
2826 2830 omap_clkm_reset(s);
  2831 + s->clkm.cold_start = 0x3a;
2827 2832  
2828 2833 cpu_register_physical_memory(s->clkm.mpu_base, 0x100, iomemtype[0]);
2829 2834 cpu_register_physical_memory(s->clkm.dsp_base, 0x1000, iomemtype[1]);
... ... @@ -2956,9 +2961,8 @@ static void omap_mpuio_write(void *opaque, target_phys_addr_t addr,
2956 2961  
2957 2962 switch (offset) {
2958 2963 case 0x04: /* OUTPUT_REG */
2959   - diff = s->outputs ^ (value & ~s->dir);
  2964 + diff = (s->outputs ^ value) & ~s->dir;
2960 2965 s->outputs = value;
2961   - value &= ~s->dir;
2962 2966 while ((ln = ffs(diff))) {
2963 2967 ln --;
2964 2968 if (s->handler[ln])
... ... @@ -3120,6 +3124,7 @@ struct omap_gpio_s {
3120 3124 uint16_t edge;
3121 3125 uint16_t mask;
3122 3126 uint16_t ints;
  3127 + uint16_t pins;
3123 3128 };
3124 3129  
3125 3130 static void omap_gpio_set(void *opaque, int line, int level)
... ... @@ -3146,7 +3151,7 @@ static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
3146 3151  
3147 3152 switch (offset) {
3148 3153 case 0x00: /* DATA_INPUT */
3149   - return s->inputs;
  3154 + return s->inputs & s->pins;
3150 3155  
3151 3156 case 0x04: /* DATA_OUTPUT */
3152 3157 return s->outputs;
... ... @@ -3162,6 +3167,10 @@ static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
3162 3167  
3163 3168 case 0x14: /* INTERRUPT_STATUS */
3164 3169 return s->ints;
  3170 +
  3171 + case 0x18: /* PIN_CONTROL (not in OMAP310) */
  3172 + OMAP_BAD_REG(addr);
  3173 + return s->pins;
3165 3174 }
3166 3175  
3167 3176 OMAP_BAD_REG(addr);
... ... @@ -3219,6 +3228,11 @@ static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
3219 3228 qemu_irq_lower(s->irq);
3220 3229 break;
3221 3230  
  3231 + case 0x18: /* PIN_CONTROL (not in OMAP310 TRM) */
  3232 + OMAP_BAD_REG(addr);
  3233 + s->pins = value;
  3234 + break;
  3235 +
3222 3236 default:
3223 3237 OMAP_BAD_REG(addr);
3224 3238 return;
... ... @@ -3246,6 +3260,7 @@ void omap_gpio_reset(struct omap_gpio_s *s)
3246 3260 s->edge = ~0;
3247 3261 s->mask = ~0;
3248 3262 s->ints = 0;
  3263 + s->pins = ~0;
3249 3264 }
3250 3265  
3251 3266 struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
... ... @@ -4058,6 +4073,458 @@ struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
4058 4073 return s;
4059 4074 }
4060 4075  
  4076 +/* Multi-channel Buffered Serial Port interfaces */
  4077 +struct omap_mcbsp_s {
  4078 + target_phys_addr_t base;
  4079 + qemu_irq txirq;
  4080 + qemu_irq rxirq;
  4081 + qemu_irq txdrq;
  4082 + qemu_irq rxdrq;
  4083 +
  4084 + uint16_t spcr[2];
  4085 + uint16_t rcr[2];
  4086 + uint16_t xcr[2];
  4087 + uint16_t srgr[2];
  4088 + uint16_t mcr[2];
  4089 + uint16_t pcr;
  4090 + uint16_t rcer[8];
  4091 + uint16_t xcer[8];
  4092 + int tx_rate;
  4093 + int rx_rate;
  4094 + int tx_req;
  4095 +
  4096 + struct i2s_codec_s *codec;
  4097 +};
  4098 +
  4099 +static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s)
  4100 +{
  4101 + int irq;
  4102 +
  4103 + switch ((s->spcr[0] >> 4) & 3) { /* RINTM */
  4104 + case 0:
  4105 + irq = (s->spcr[0] >> 1) & 1; /* RRDY */
  4106 + break;
  4107 + case 3:
  4108 + irq = (s->spcr[0] >> 3) & 1; /* RSYNCERR */
  4109 + break;
  4110 + default:
  4111 + irq = 0;
  4112 + break;
  4113 + }
  4114 +
  4115 + qemu_set_irq(s->rxirq, irq);
  4116 +
  4117 + switch ((s->spcr[1] >> 4) & 3) { /* XINTM */
  4118 + case 0:
  4119 + irq = (s->spcr[1] >> 1) & 1; /* XRDY */
  4120 + break;
  4121 + case 3:
  4122 + irq = (s->spcr[1] >> 3) & 1; /* XSYNCERR */
  4123 + break;
  4124 + default:
  4125 + irq = 0;
  4126 + break;
  4127 + }
  4128 +
  4129 + qemu_set_irq(s->txirq, irq);
  4130 +}
  4131 +
  4132 +static void omap_mcbsp_req_update(struct omap_mcbsp_s *s)
  4133 +{
  4134 + int prev = s->tx_req;
  4135 +
  4136 + s->tx_req = (s->tx_rate ||
  4137 + (s->spcr[0] & (1 << 12))) && /* CLKSTP */
  4138 + (s->spcr[1] & (1 << 6)) && /* GRST */
  4139 + (s->spcr[1] & (1 << 0)); /* XRST */
  4140 +
  4141 + if (!s->tx_req && prev) {
  4142 + s->spcr[1] &= ~(1 << 1); /* XRDY */
  4143 + qemu_irq_lower(s->txdrq);
  4144 + omap_mcbsp_intr_update(s);
  4145 +
  4146 + if (s->codec)
  4147 + s->codec->tx_swallow(s->codec->opaque);
  4148 + } else if (s->codec && s->tx_req && !prev) {
  4149 + s->spcr[1] |= 1 << 1; /* XRDY */
  4150 + qemu_irq_raise(s->txdrq);
  4151 + omap_mcbsp_intr_update(s);
  4152 + }
  4153 +}
  4154 +
  4155 +static void omap_mcbsp_rate_update(struct omap_mcbsp_s *s)
  4156 +{
  4157 + int rx_clk = 0, tx_clk = 0;
  4158 + int cpu_rate = 1500000; /* XXX */
  4159 + if (!s->codec)
  4160 + return;
  4161 +
  4162 + if (s->spcr[1] & (1 << 6)) { /* GRST */
  4163 + if (s->spcr[0] & (1 << 0)) /* RRST */
  4164 + if ((s->srgr[1] & (1 << 13)) && /* CLKSM */
  4165 + (s->pcr & (1 << 8))) /* CLKRM */
  4166 + if (~s->pcr & (1 << 7)) /* SCLKME */
  4167 + rx_clk = cpu_rate /
  4168 + ((s->srgr[0] & 0xff) + 1); /* CLKGDV */
  4169 + if (s->spcr[1] & (1 << 0)) /* XRST */
  4170 + if ((s->srgr[1] & (1 << 13)) && /* CLKSM */
  4171 + (s->pcr & (1 << 9))) /* CLKXM */
  4172 + if (~s->pcr & (1 << 7)) /* SCLKME */
  4173 + tx_clk = cpu_rate /
  4174 + ((s->srgr[0] & 0xff) + 1); /* CLKGDV */
  4175 + }
  4176 +
  4177 + s->codec->set_rate(s->codec->opaque, rx_clk, tx_clk);
  4178 +}
  4179 +
  4180 +static void omap_mcbsp_rx_start(struct omap_mcbsp_s *s)
  4181 +{
  4182 + if (!(s->spcr[0] & 1)) { /* RRST */
  4183 + if (s->codec)
  4184 + s->codec->in.len = 0;
  4185 + return;
  4186 + }
  4187 +
  4188 + if ((s->spcr[0] >> 1) & 1) /* RRDY */
  4189 + s->spcr[0] |= 1 << 2; /* RFULL */
  4190 + s->spcr[0] |= 1 << 1; /* RRDY */
  4191 + qemu_irq_raise(s->rxdrq);
  4192 + omap_mcbsp_intr_update(s);
  4193 +}
  4194 +
  4195 +static void omap_mcbsp_rx_stop(struct omap_mcbsp_s *s)
  4196 +{
  4197 + s->spcr[0] &= ~(1 << 1); /* RRDY */
  4198 + qemu_irq_lower(s->rxdrq);
  4199 + omap_mcbsp_intr_update(s);
  4200 +}
  4201 +
  4202 +static void omap_mcbsp_tx_start(struct omap_mcbsp_s *s)
  4203 +{
  4204 + if (s->tx_rate)
  4205 + return;
  4206 + s->tx_rate = 1;
  4207 + omap_mcbsp_req_update(s);
  4208 +}
  4209 +
  4210 +static void omap_mcbsp_tx_stop(struct omap_mcbsp_s *s)
  4211 +{
  4212 + s->tx_rate = 0;
  4213 + omap_mcbsp_req_update(s);
  4214 +}
  4215 +
  4216 +static uint32_t omap_mcbsp_read(void *opaque, target_phys_addr_t addr)
  4217 +{
  4218 + struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
  4219 + int offset = addr & OMAP_MPUI_REG_MASK;
  4220 + uint16_t ret;
  4221 +
  4222 + switch (offset) {
  4223 + case 0x00: /* DRR2 */
  4224 + if (((s->rcr[0] >> 5) & 7) < 3) /* RWDLEN1 */
  4225 + return 0x0000;
  4226 + /* Fall through. */
  4227 + case 0x02: /* DRR1 */
  4228 + if (!s->codec)
  4229 + return 0x0000;
  4230 + if (s->codec->in.len < 2) {
  4231 + printf("%s: Rx FIFO underrun\n", __FUNCTION__);
  4232 + omap_mcbsp_rx_stop(s);
  4233 + } else {
  4234 + s->codec->in.len -= 2;
  4235 + ret = s->codec->in.fifo[s->codec->in.start ++] << 8;
  4236 + ret |= s->codec->in.fifo[s->codec->in.start ++];
  4237 + if (!s->codec->in.len)
  4238 + omap_mcbsp_rx_stop(s);
  4239 + return ret;
  4240 + }
  4241 + return 0x0000;
  4242 +
  4243 + case 0x04: /* DXR2 */
  4244 + case 0x06: /* DXR1 */
  4245 + return 0x0000;
  4246 +
  4247 + case 0x08: /* SPCR2 */
  4248 + return s->spcr[1];
  4249 + case 0x0a: /* SPCR1 */
  4250 + return s->spcr[0];
  4251 + case 0x0c: /* RCR2 */
  4252 + return s->rcr[1];
  4253 + case 0x0e: /* RCR1 */
  4254 + return s->rcr[0];
  4255 + case 0x10: /* XCR2 */
  4256 + return s->xcr[1];
  4257 + case 0x12: /* XCR1 */
  4258 + return s->xcr[0];
  4259 + case 0x14: /* SRGR2 */
  4260 + return s->srgr[1];
  4261 + case 0x16: /* SRGR1 */
  4262 + return s->srgr[0];
  4263 + case 0x18: /* MCR2 */
  4264 + return s->mcr[1];
  4265 + case 0x1a: /* MCR1 */
  4266 + return s->mcr[0];
  4267 + case 0x1c: /* RCERA */
  4268 + return s->rcer[0];
  4269 + case 0x1e: /* RCERB */
  4270 + return s->rcer[1];
  4271 + case 0x20: /* XCERA */
  4272 + return s->xcer[0];
  4273 + case 0x22: /* XCERB */
  4274 + return s->xcer[1];
  4275 + case 0x24: /* PCR0 */
  4276 + return s->pcr;
  4277 + case 0x26: /* RCERC */
  4278 + return s->rcer[2];
  4279 + case 0x28: /* RCERD */
  4280 + return s->rcer[3];
  4281 + case 0x2a: /* XCERC */
  4282 + return s->xcer[2];
  4283 + case 0x2c: /* XCERD */
  4284 + return s->xcer[3];
  4285 + case 0x2e: /* RCERE */
  4286 + return s->rcer[4];
  4287 + case 0x30: /* RCERF */
  4288 + return s->rcer[5];
  4289 + case 0x32: /* XCERE */
  4290 + return s->xcer[4];
  4291 + case 0x34: /* XCERF */
  4292 + return s->xcer[5];
  4293 + case 0x36: /* RCERG */
  4294 + return s->rcer[6];
  4295 + case 0x38: /* RCERH */
  4296 + return s->rcer[7];
  4297 + case 0x3a: /* XCERG */
  4298 + return s->xcer[6];
  4299 + case 0x3c: /* XCERH */
  4300 + return s->xcer[7];
  4301 + }
  4302 +
  4303 + OMAP_BAD_REG(addr);
  4304 + return 0;
  4305 +}
  4306 +
  4307 +static void omap_mcbsp_write(void *opaque, target_phys_addr_t addr,
  4308 + uint32_t value)
  4309 +{
  4310 + struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
  4311 + int offset = addr & OMAP_MPUI_REG_MASK;
  4312 +
  4313 + switch (offset) {
  4314 + case 0x00: /* DRR2 */
  4315 + case 0x02: /* DRR1 */
  4316 + OMAP_RO_REG(addr);
  4317 + return;
  4318 +
  4319 + case 0x04: /* DXR2 */
  4320 + if (((s->xcr[0] >> 5) & 7) < 3) /* XWDLEN1 */
  4321 + return;
  4322 + /* Fall through. */
  4323 + case 0x06: /* DXR1 */
  4324 + if (!s->codec)
  4325 + return;
  4326 + if (s->tx_req) {
  4327 + if (s->codec->out.len > s->codec->out.size - 2) {
  4328 + printf("%s: Tx FIFO overrun\n", __FUNCTION__);
  4329 + omap_mcbsp_tx_stop(s);
  4330 + } else {
  4331 + s->codec->out.fifo[s->codec->out.len ++] = (value >> 8) & 0xff;
  4332 + s->codec->out.fifo[s->codec->out.len ++] = (value >> 0) & 0xff;
  4333 + if (s->codec->out.len >= s->codec->out.size)
  4334 + omap_mcbsp_tx_stop(s);
  4335 + }
  4336 + } else
  4337 + printf("%s: Tx FIFO overrun\n", __FUNCTION__);
  4338 + return;
  4339 +
  4340 + case 0x08: /* SPCR2 */
  4341 + s->spcr[1] &= 0x0002;
  4342 + s->spcr[1] |= 0x03f9 & value;
  4343 + s->spcr[1] |= 0x0004 & (value << 2); /* XEMPTY := XRST */
  4344 + if (~value & 1) { /* XRST */
  4345 + s->spcr[1] &= ~6;
  4346 + qemu_irq_lower(s->rxdrq);
  4347 + if (s->codec)
  4348 + s->codec->out.len = 0;
  4349 + }
  4350 + if (s->codec)
  4351 + omap_mcbsp_rate_update(s);
  4352 + omap_mcbsp_req_update(s);
  4353 + return;
  4354 + case 0x0a: /* SPCR1 */
  4355 + s->spcr[0] &= 0x0006;
  4356 + s->spcr[0] |= 0xf8f9 & value;
  4357 + if (value & (1 << 15)) /* DLB */
  4358 + printf("%s: Digital Loopback mode enable attempt\n", __FUNCTION__);
  4359 + if (~value & 1) { /* RRST */
  4360 + s->spcr[0] &= ~6;
  4361 + qemu_irq_lower(s->txdrq);
  4362 + if (s->codec)
  4363 + s->codec->in.len = 0;
  4364 + }
  4365 + if (s->codec)
  4366 + omap_mcbsp_rate_update(s);
  4367 + omap_mcbsp_req_update(s);
  4368 + return;
  4369 +
  4370 + case 0x0c: /* RCR2 */
  4371 + s->rcr[1] = value & 0xffff;
  4372 + return;
  4373 + case 0x0e: /* RCR1 */
  4374 + s->rcr[0] = value & 0x7fe0;
  4375 + return;
  4376 + case 0x10: /* XCR2 */
  4377 + s->xcr[1] = value & 0xffff;
  4378 + return;
  4379 + case 0x12: /* XCR1 */
  4380 + s->xcr[0] = value & 0x7fe0;
  4381 + return;
  4382 + case 0x14: /* SRGR2 */
  4383 + s->srgr[1] = value & 0xffff;
  4384 + omap_mcbsp_rate_update(s);
  4385 + return;
  4386 + case 0x16: /* SRGR1 */
  4387 + s->srgr[0] = value & 0xffff;
  4388 + omap_mcbsp_rate_update(s);
  4389 + return;
  4390 + case 0x18: /* MCR2 */
  4391 + s->mcr[1] = value & 0x03e3;
  4392 + if (value & 3) /* XMCM */
  4393 + printf("%s: Tx channel selection mode enable attempt\n",
  4394 + __FUNCTION__);
  4395 + return;
  4396 + case 0x1a: /* MCR1 */
  4397 + s->mcr[0] = value & 0x03e1;
  4398 + if (value & 1) /* RMCM */
  4399 + printf("%s: Rx channel selection mode enable attempt\n",
  4400 + __FUNCTION__);
  4401 + return;
  4402 + case 0x1c: /* RCERA */
  4403 + s->rcer[0] = value & 0xffff;
  4404 + return;
  4405 + case 0x1e: /* RCERB */
  4406 + s->rcer[1] = value & 0xffff;
  4407 + return;
  4408 + case 0x20: /* XCERA */
  4409 + s->xcer[0] = value & 0xffff;
  4410 + return;
  4411 + case 0x22: /* XCERB */
  4412 + s->xcer[1] = value & 0xffff;
  4413 + return;
  4414 + case 0x24: /* PCR0 */
  4415 + s->pcr = value & 0x7faf;
  4416 + return;
  4417 + case 0x26: /* RCERC */
  4418 + s->rcer[2] = value & 0xffff;
  4419 + return;
  4420 + case 0x28: /* RCERD */
  4421 + s->rcer[3] = value & 0xffff;
  4422 + return;
  4423 + case 0x2a: /* XCERC */
  4424 + s->xcer[2] = value & 0xffff;
  4425 + return;
  4426 + case 0x2c: /* XCERD */
  4427 + s->xcer[3] = value & 0xffff;
  4428 + return;
  4429 + case 0x2e: /* RCERE */
  4430 + s->rcer[4] = value & 0xffff;
  4431 + return;
  4432 + case 0x30: /* RCERF */
  4433 + s->rcer[5] = value & 0xffff;
  4434 + return;
  4435 + case 0x32: /* XCERE */
  4436 + s->xcer[4] = value & 0xffff;
  4437 + return;
  4438 + case 0x34: /* XCERF */
  4439 + s->xcer[5] = value & 0xffff;
  4440 + return;
  4441 + case 0x36: /* RCERG */
  4442 + s->rcer[6] = value & 0xffff;
  4443 + return;
  4444 + case 0x38: /* RCERH */
  4445 + s->rcer[7] = value & 0xffff;
  4446 + return;
  4447 + case 0x3a: /* XCERG */
  4448 + s->xcer[6] = value & 0xffff;
  4449 + return;
  4450 + case 0x3c: /* XCERH */
  4451 + s->xcer[7] = value & 0xffff;
  4452 + return;
  4453 + }
  4454 +
  4455 + OMAP_BAD_REG(addr);
  4456 +}
  4457 +
  4458 +static CPUReadMemoryFunc *omap_mcbsp_readfn[] = {
  4459 + omap_badwidth_read16,
  4460 + omap_mcbsp_read,
  4461 + omap_badwidth_read16,
  4462 +};
  4463 +
  4464 +static CPUWriteMemoryFunc *omap_mcbsp_writefn[] = {
  4465 + omap_badwidth_write16,
  4466 + omap_mcbsp_write,
  4467 + omap_badwidth_write16,
  4468 +};
  4469 +
  4470 +static void omap_mcbsp_reset(struct omap_mcbsp_s *s)
  4471 +{
  4472 + memset(&s->spcr, 0, sizeof(s->spcr));
  4473 + memset(&s->rcr, 0, sizeof(s->rcr));
  4474 + memset(&s->xcr, 0, sizeof(s->xcr));
  4475 + s->srgr[0] = 0x0001;
  4476 + s->srgr[1] = 0x2000;
  4477 + memset(&s->mcr, 0, sizeof(s->mcr));
  4478 + memset(&s->pcr, 0, sizeof(s->pcr));
  4479 + memset(&s->rcer, 0, sizeof(s->rcer));
  4480 + memset(&s->xcer, 0, sizeof(s->xcer));
  4481 + s->tx_req = 0;
  4482 + s->tx_rate = 0;
  4483 + s->rx_rate = 0;
  4484 +}
  4485 +
  4486 +struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base,
  4487 + qemu_irq *irq, qemu_irq *dma, omap_clk clk)
  4488 +{
  4489 + int iomemtype;
  4490 + struct omap_mcbsp_s *s = (struct omap_mcbsp_s *)
  4491 + qemu_mallocz(sizeof(struct omap_mcbsp_s));
  4492 +
  4493 + s->base = base;
  4494 + s->txirq = irq[0];
  4495 + s->rxirq = irq[1];
  4496 + s->txdrq = dma[0];
  4497 + s->rxdrq = dma[1];
  4498 + omap_mcbsp_reset(s);
  4499 +
  4500 + iomemtype = cpu_register_io_memory(0, omap_mcbsp_readfn,
  4501 + omap_mcbsp_writefn, s);
  4502 + cpu_register_physical_memory(s->base, 0x800, iomemtype);
  4503 +
  4504 + return s;
  4505 +}
  4506 +
  4507 +void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
  4508 +{
  4509 + struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
  4510 +
  4511 + omap_mcbsp_rx_start(s);
  4512 +}
  4513 +
  4514 +void omap_mcbsp_i2s_start(void *opaque, int line, int level)
  4515 +{
  4516 + struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
  4517 +
  4518 + omap_mcbsp_tx_start(s);
  4519 +}
  4520 +
  4521 +void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave)
  4522 +{
  4523 + s->codec = slave;
  4524 + slave->rx_swallow = qemu_allocate_irqs(omap_mcbsp_i2s_swallow, s, 1)[0];
  4525 + slave->tx_start = qemu_allocate_irqs(omap_mcbsp_i2s_start, s, 1)[0];
  4526 +}
  4527 +
4061 4528 /* General chip reset */
4062 4529 static void omap_mpu_reset(void *opaque)
4063 4530 {
... ... @@ -4092,6 +4559,9 @@ static void omap_mpu_reset(void *opaque)
4092 4559 omap_pwt_reset(mpu);
4093 4560 omap_i2c_reset(mpu->i2c);
4094 4561 omap_rtc_reset(mpu->rtc);
  4562 + omap_mcbsp_reset(mpu->mcbsp1);
  4563 + omap_mcbsp_reset(mpu->mcbsp2);
  4564 + omap_mcbsp_reset(mpu->mcbsp3);
4095 4565 cpu_reset(mpu->env);
4096 4566 }
4097 4567  
... ... @@ -4254,8 +4724,8 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
4254 4724 s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX],
4255 4725 s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
4256 4726  
4257   - omap_pwl_init(0xfffb5800, s, omap_findclk(s, "clk32-kHz"));
4258   - omap_pwt_init(0xfffb6000, s, omap_findclk(s, "xtal_osc_12m"));
  4727 + omap_pwl_init(0xfffb5800, s, omap_findclk(s, "armxor_ck"));
  4728 + omap_pwt_init(0xfffb6000, s, omap_findclk(s, "armxor_ck"));
4259 4729  
4260 4730 s->i2c = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C],
4261 4731 &s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck"));
... ... @@ -4263,14 +4733,18 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
4263 4733 s->rtc = omap_rtc_init(0xfffb4800, &s->irq[1][OMAP_INT_RTC_TIMER],
4264 4734 omap_findclk(s, "clk32-kHz"));
4265 4735  
  4736 + s->mcbsp1 = omap_mcbsp_init(0xfffb1800, &s->irq[1][OMAP_INT_McBSP1TX],
  4737 + &s->drq[OMAP_DMA_MCBSP1_TX], omap_findclk(s, "dspxor_ck"));
  4738 + s->mcbsp2 = omap_mcbsp_init(0xfffb1000, &s->irq[0][OMAP_INT_310_McBSP2_TX],
  4739 + &s->drq[OMAP_DMA_MCBSP2_TX], omap_findclk(s, "mpuper_ck"));
  4740 + s->mcbsp3 = omap_mcbsp_init(0xfffb7000, &s->irq[1][OMAP_INT_McBSP3TX],
  4741 + &s->drq[OMAP_DMA_MCBSP3_TX], omap_findclk(s, "dspxor_ck"));
  4742 +
4266 4743 /* Register mappings not currenlty implemented:
4267   - * McBSP2 Comm fffb1000 - fffb17ff
4268   - * McBSP1 Audio fffb1800 - fffb1fff (not mapped on OMAP310)
4269 4744 * MCSI2 Comm fffb2000 - fffb27ff (not mapped on OMAP310)
4270 4745 * MCSI1 Bluetooth fffb2800 - fffb2fff (not mapped on OMAP310)
4271 4746 * USB W2FC fffb4000 - fffb47ff
4272 4747 * Camera Interface fffb6800 - fffb6fff
4273   - * McBSP3 fffb7000 - fffb77ff (not mapped on OMAP310)
4274 4748 * USB Host fffba000 - fffba7ff
4275 4749 * FAC fffba800 - fffbafff
4276 4750 * HDQ/1-Wire fffbc000 - fffbc7ff
... ...
hw/omap.h
... ... @@ -479,6 +479,30 @@ struct omap_rtc_s;
479 479 struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
480 480 qemu_irq *irq, omap_clk clk);
481 481  
  482 +struct i2s_codec_s {
  483 + void *opaque;
  484 +
  485 + /* The CPU can call this if it is generating the clock signal on the
  486 + * i2s port. The CODEC can ignore it if it is set up as a clock
  487 + * master and generates its own clock. */
  488 + void (*set_rate)(void *opaque, int in, int out);
  489 +
  490 + void (*tx_swallow)(void *opaque);
  491 + qemu_irq rx_swallow;
  492 + qemu_irq tx_start;
  493 +
  494 + struct i2s_fifo_s {
  495 + uint8_t *fifo;
  496 + int len;
  497 + int start;
  498 + int size;
  499 + } in, out;
  500 +};
  501 +struct omap_mcbsp_s;
  502 +struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base,
  503 + qemu_irq *irq, qemu_irq *dma, omap_clk clk);
  504 +void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave);
  505 +
482 506 /* omap_lcdc.c */
483 507 struct omap_lcd_panel_s;
484 508 void omap_lcdc_reset(struct omap_lcd_panel_s *s);
... ... @@ -536,6 +560,9 @@ struct omap_mpu_state_s {
536 560  
537 561 struct omap_gpio_s *gpio;
538 562  
  563 + struct omap_mcbsp_s *mcbsp1;
  564 + struct omap_mcbsp_s *mcbsp3;
  565 +
539 566 /* MPU public TIPB peripherals */
540 567 struct omap_32khz_timer_s *os_timer;
541 568  
... ... @@ -563,6 +590,8 @@ struct omap_mpu_state_s {
563 590  
564 591 struct omap_rtc_s *rtc;
565 592  
  593 + struct omap_mcbsp_s *mcbsp2;
  594 +
566 595 /* MPU private TIPB peripherals */
567 596 struct omap_intr_handler_s *ih[2];
568 597  
... ... @@ -646,6 +675,7 @@ void omap_badwidth_write32(void *opaque, target_phys_addr_t addr,
646 675 __FUNCTION__, paddr)
647 676  
648 677 # define TCMI_VERBOSE 1
  678 +//# define MEM_VERBOSE 1
649 679  
650 680 # ifdef TCMI_VERBOSE
651 681 # define OMAP_8B_REG(paddr) \
... ... @@ -665,4 +695,97 @@ void omap_badwidth_write32(void *opaque, target_phys_addr_t addr,
665 695  
666 696 # define OMAP_MPUI_REG_MASK 0x000007ff
667 697  
  698 +# ifdef MEM_VERBOSE
  699 +struct io_fn {
  700 + CPUReadMemoryFunc **mem_read;
  701 + CPUWriteMemoryFunc **mem_write;
  702 + void *opaque;
  703 + int in;
  704 +};
  705 +
  706 +static uint32_t io_readb(void *opaque, target_phys_addr_t addr)
  707 +{
  708 + struct io_fn *s = opaque;
  709 + uint32_t ret;
  710 +
  711 + s->in ++;
  712 + ret = s->mem_read[0](s->opaque, addr);
  713 + s->in --;
  714 + if (!s->in)
  715 + fprintf(stderr, "%08x ---> %02x\n", (uint32_t) addr, ret);
  716 + return ret;
  717 +}
  718 +static uint32_t io_readh(void *opaque, target_phys_addr_t addr)
  719 +{
  720 + struct io_fn *s = opaque;
  721 + uint32_t ret;
  722 +
  723 + s->in ++;
  724 + ret = s->mem_read[1](s->opaque, addr);
  725 + s->in --;
  726 + if (!s->in)
  727 + fprintf(stderr, "%08x ---> %04x\n", (uint32_t) addr, ret);
  728 + return ret;
  729 +}
  730 +static uint32_t io_readw(void *opaque, target_phys_addr_t addr)
  731 +{
  732 + struct io_fn *s = opaque;
  733 + uint32_t ret;
  734 +
  735 + s->in ++;
  736 + ret = s->mem_read[2](s->opaque, addr);
  737 + s->in --;
  738 + if (!s->in)
  739 + fprintf(stderr, "%08x ---> %08x\n", (uint32_t) addr, ret);
  740 + return ret;
  741 +}
  742 +static void io_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
  743 +{
  744 + struct io_fn *s = opaque;
  745 +
  746 + if (!s->in)
  747 + fprintf(stderr, "%08x <--- %02x\n", (uint32_t) addr, value);
  748 + s->in ++;
  749 + s->mem_write[0](s->opaque, addr, value);
  750 + s->in --;
  751 +}
  752 +static void io_writeh(void *opaque, target_phys_addr_t addr, uint32_t value)
  753 +{
  754 + struct io_fn *s = opaque;
  755 +
  756 + if (!s->in)
  757 + fprintf(stderr, "%08x <--- %04x\n", (uint32_t) addr, value);
  758 + s->in ++;
  759 + s->mem_write[1](s->opaque, addr, value);
  760 + s->in --;
  761 +}
  762 +static void io_writew(void *opaque, target_phys_addr_t addr, uint32_t value)
  763 +{
  764 + struct io_fn *s = opaque;
  765 +
  766 + if (!s->in)
  767 + fprintf(stderr, "%08x <--- %08x\n", (uint32_t) addr, value);
  768 + s->in ++;
  769 + s->mem_write[2](s->opaque, addr, value);
  770 + s->in --;
  771 +}
  772 +
  773 +static CPUReadMemoryFunc *io_readfn[] = { io_readb, io_readh, io_readw, };
  774 +static CPUWriteMemoryFunc *io_writefn[] = { io_writeb, io_writeh, io_writew, };
  775 +
  776 +inline static int debug_register_io_memory(int io_index,
  777 + CPUReadMemoryFunc **mem_read, CPUWriteMemoryFunc **mem_write,
  778 + void *opaque)
  779 +{
  780 + struct io_fn *s = qemu_malloc(sizeof(struct io_fn));
  781 +
  782 + s->mem_read = mem_read;
  783 + s->mem_write = mem_write;
  784 + s->opaque = opaque;
  785 + s->in = 0;
  786 + return cpu_register_io_memory(io_index, io_readfn, io_writefn, s);
  787 +}
  788 +# define cpu_register_io_memory debug_register_io_memory
  789 +# endif
  790 +
668 791 #endif /* hw_omap_h */
... ...
hw/omap1_clk.c
... ... @@ -307,6 +307,12 @@ static struct clk lbfree_ck = {
307 307 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
308 308 };
309 309  
  310 +static struct clk hsab_ck = {
  311 + .name = "hsab_ck",
  312 + .parent = &tc_ck,
  313 + .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
  314 +};
  315 +
310 316 static struct clk rhea1_ck = {
311 317 .name = "rhea1_ck",
312 318 .parent = &tc_ck,
... ... @@ -359,7 +365,7 @@ static struct clk uart2_ck = {
359 365 static struct clk uart3_1510 = {
360 366 .name = "uart3_ck",
361 367 /* Direct from ULPD, no real parent */
362   - .parent = &armper_ck,/* either armper_ck or dpll4 */
  368 + .parent = &armper_ck, /* either armper_ck or dpll4 */
363 369 .rate = 12000000,
364 370 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
365 371 };
... ... @@ -395,11 +401,12 @@ static struct clk usb_hhc_ck16xx = {
395 401 .flags = CLOCK_IN_OMAP16XX,
396 402 };
397 403  
398   -static struct clk usb_dc_ck = {
399   - .name = "usb_dc_ck",
400   - /* Direct from ULPD, no parent */
  404 +static struct clk usb_w2fc_mclk = {
  405 + .name = "usb_w2fc_mclk",
  406 + .alias = "usb_w2fc_ck",
  407 + .parent = &ck_48m,
401 408 .rate = 48000000,
402   - .flags = CLOCK_IN_OMAP16XX,
  409 + .flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
403 410 };
404 411  
405 412 static struct clk mclk_1510 = {
... ... @@ -539,6 +546,7 @@ static struct clk *onchip_clks[] = {
539 546 &api_ck,
540 547 &lb_ck,
541 548 &lbfree_ck,
  549 + &hsab_ck,
542 550 &rhea1_ck,
543 551 &rhea2_ck,
544 552 &lcd_ck_16xx,
... ... @@ -551,7 +559,6 @@ static struct clk *onchip_clks[] = {
551 559 &uart3_16xx,
552 560 &usb_clk0,
553 561 &usb_hhc_ck1510, &usb_hhc_ck16xx,
554   - &usb_dc_ck,
555 562 &mclk_1510, &mclk_16xx, &mclk_310,
556 563 &bclk_1510, &bclk_16xx, &bclk_310,
557 564 &mmc1_ck,
... ... @@ -560,6 +567,7 @@ static struct clk *onchip_clks[] = {
560 567 &cam_exclk,
561 568 &cam_lclk,
562 569 &clk32k,
  570 + &usb_w2fc_mclk,
563 571 /* Virtual clocks */
564 572 &i2c_fck,
565 573 &i2c_ick,
... ...
hw/palm.c
... ... @@ -78,11 +78,18 @@ static CPUWriteMemoryFunc *static_writefn[] = {
78 78  
79 79 static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
80 80 {
81   - omap_uwire_attach(
82   - cpu->microwire,
83   - tsc2102_init(
84   - omap_gpio_in_get(cpu->gpio)[PALMTE_PINTDAV_GPIO]),
85   - 0);
  81 + struct uwire_slave_s *tsc;
  82 + AudioState *audio = 0;
  83 +
  84 +#ifdef HAS_AUDIO
  85 + audio = AUD_init();
  86 +#endif
  87 +
  88 + tsc = tsc2102_init(omap_gpio_in_get(cpu->gpio)[PALMTE_PINTDAV_GPIO],
  89 + audio);
  90 +
  91 + omap_uwire_attach(cpu->microwire, tsc, 0);
  92 + omap_mcbsp_i2s_attach(cpu->mcbsp1, tsc210x_codec(tsc));
86 93 }
87 94  
88 95 static struct {
... ...
hw/tsc210x.c
... ... @@ -32,7 +32,11 @@
32 32 struct tsc210x_state_s {
33 33 qemu_irq pint;
34 34 QEMUTimer *timer;
  35 + QEMUSoundCard card;
35 36 struct uwire_slave_s chip;
  37 + struct i2s_codec_s codec;
  38 + uint8_t in_fifo[16384];
  39 + uint8_t out_fifo[16384];
36 40  
37 41 int x, y;
38 42 int pressure;
... ... @@ -63,6 +67,13 @@ struct tsc210x_state_s {
63 67 uint16_t dac_power;
64 68 int64_t powerdown;
65 69 uint16_t filter_data[0x14];
  70 +
  71 + const char *name;
  72 + SWVoiceIn *adc_voice[1];
  73 + SWVoiceOut *dac_voice[1];
  74 + int i2s_rx_rate;
  75 + int i2s_tx_rate;
  76 + AudioState *audio;
66 77 };
67 78  
68 79 static const int resolution[4] = { 12, 8, 10, 12 };
... ... @@ -171,9 +182,144 @@ static void tsc210x_reset(struct tsc210x_state_s *s)
171 182 s->filter_data[0x12] = 0x7d83;
172 183 s->filter_data[0x13] = 0x84ee;
173 184  
  185 + s->i2s_tx_rate = 0;
  186 + s->i2s_rx_rate = 0;
  187 +
174 188 qemu_set_irq(s->pint, !s->irq);
175 189 }
176 190  
  191 +struct tsc210x_rate_info_s {
  192 + int rate;
  193 + int dsor;
  194 + int fsref;
  195 +};
  196 +
  197 +/* { rate, dsor, fsref } */
  198 +static const struct tsc210x_rate_info_s tsc2101_rates[] = {
  199 + /* Fsref / 6.0 */
  200 + { 7350, 7, 1 },
  201 + { 8000, 7, 0 },
  202 + /* Fsref / 5.5 */
  203 + { 8018, 6, 1 },
  204 + { 8727, 6, 0 },
  205 + /* Fsref / 5.0 */
  206 + { 8820, 5, 1 },
  207 + { 9600, 5, 0 },
  208 + /* Fsref / 4.0 */
  209 + { 11025, 4, 1 },
  210 + { 12000, 4, 0 },
  211 + /* Fsref / 3.0 */
  212 + { 14700, 3, 1 },
  213 + { 16000, 3, 0 },
  214 + /* Fsref / 2.0 */
  215 + { 22050, 2, 1 },
  216 + { 24000, 2, 0 },
  217 + /* Fsref / 1.5 */
  218 + { 29400, 1, 1 },
  219 + { 32000, 1, 0 },
  220 + /* Fsref */
  221 + { 44100, 0, 1 },
  222 + { 48000, 0, 0 },
  223 +
  224 + { 0, 0, 0 },
  225 +};
  226 +
  227 +/* { rate, dsor, fsref } */
  228 +static const struct tsc210x_rate_info_s tsc2102_rates[] = {
  229 + /* Fsref / 6.0 */
  230 + { 7350, 63, 1 },
  231 + { 8000, 63, 0 },
  232 + /* Fsref / 6.0 */
  233 + { 7350, 54, 1 },
  234 + { 8000, 54, 0 },
  235 + /* Fsref / 5.0 */
  236 + { 8820, 45, 1 },
  237 + { 9600, 45, 0 },
  238 + /* Fsref / 4.0 */
  239 + { 11025, 36, 1 },
  240 + { 12000, 36, 0 },
  241 + /* Fsref / 3.0 */
  242 + { 14700, 27, 1 },
  243 + { 16000, 27, 0 },
  244 + /* Fsref / 2.0 */
  245 + { 22050, 18, 1 },
  246 + { 24000, 18, 0 },
  247 + /* Fsref / 1.5 */
  248 + { 29400, 9, 1 },
  249 + { 32000, 9, 0 },
  250 + /* Fsref */
  251 + { 44100, 0, 1 },
  252 + { 48000, 0, 0 },
  253 +
  254 + { 0, 0, 0 },
  255 +};
  256 +
  257 +static inline void tsc210x_out_flush(struct tsc210x_state_s *s, int len)
  258 +{
  259 + uint8_t *data = s->codec.out.fifo + s->codec.out.start;
  260 + uint8_t *end = data + len;
  261 +
  262 + while (data < end)
  263 + data += AUD_write(s->dac_voice[0], data, end - data) ?: (end - data);
  264 +
  265 + s->codec.out.len -= len;
  266 + if (s->codec.out.len)
  267 + memmove(s->codec.out.fifo, end, s->codec.out.len);
  268 + s->codec.out.start = 0;
  269 +}
  270 +
  271 +static void tsc210x_audio_out_cb(struct tsc210x_state_s *s, int free_b)
  272 +{
  273 + if (s->codec.out.len >= free_b) {
  274 + tsc210x_out_flush(s, free_b);
  275 + return;
  276 + }
  277 +
  278 + s->codec.out.size = MIN(free_b, 16384);
  279 + qemu_irq_raise(s->codec.tx_start);
  280 +}
  281 +
  282 +static void tsc2102_audio_set_format(struct tsc210x_state_s *s)
  283 +{
  284 + int enable;
  285 + const struct tsc210x_rate_info_s *rate;
  286 + audsettings_t fmt;
  287 +
  288 + if (s->dac_voice[0]) {
  289 + tsc210x_out_flush(s, s->codec.out.len);
  290 + s->codec.out.size = 0;
  291 + AUD_set_active_out(s->dac_voice[0], 0);
  292 + AUD_close_out(&s->card, s->dac_voice[0]);
  293 + s->dac_voice[0] = 0;
  294 + }
  295 +
  296 + enable =
  297 + (~s->dac_power & (1 << 15)) && /* PWDNC */
  298 + (~s->dac_power & (1 << 10)); /* DAPWDN */
  299 + if (!enable)
  300 + return;
  301 +
  302 + for (rate = tsc2102_rates; rate->rate; rate ++)
  303 + if (rate->dsor == (s->audio_ctrl1 & 0x3f) && /* DACFS */
  304 + rate->fsref == ((s->audio_ctrl3 >> 13) & 1))/* REFFS */
  305 + break;
  306 + if (!rate->rate) {
  307 + printf("%s: unknown sampling rate configured\n", __FUNCTION__);
  308 + return;
  309 + }
  310 +
  311 + /* Force our own sampling rate even in slave DAC mode */
  312 + fmt.endianness = 0;
  313 + fmt.nchannels = 2;
  314 + fmt.freq = rate->rate;
  315 + fmt.fmt = AUD_FMT_S16;
  316 +
  317 + s->dac_voice[0] = AUD_open_out(&s->card, s->dac_voice[0],
  318 + "tsc2102.sink", s, (void *) tsc210x_audio_out_cb, &fmt);
  319 + if (s->dac_voice[0])
  320 + AUD_set_active_out(s->dac_voice[0], 1);
  321 +}
  322 +
177 323 static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg)
178 324 {
179 325 switch (reg) {
... ... @@ -437,6 +583,8 @@ static void tsc2102_audio_register_write(
437 583 fprintf(stderr, "tsc2102_audio_register_write: "
438 584 "wrong value written into Audio 1\n");
439 585 #endif
  586 + if (s->audio)
  587 + tsc2102_audio_set_format(s);
440 588 return;
441 589  
442 590 case 0x01:
... ... @@ -479,6 +627,8 @@ static void tsc2102_audio_register_write(
479 627 fprintf(stderr, "tsc2102_audio_register_write: "
480 628 "wrong value written into Power\n");
481 629 #endif
  630 + if (s->audio)
  631 + tsc2102_audio_set_format(s);
482 632 return;
483 633  
484 634 case 0x06: /* Audio Control 3 */
... ... @@ -489,6 +639,8 @@ static void tsc2102_audio_register_write(
489 639 fprintf(stderr, "tsc2102_audio_register_write: "
490 640 "wrong value written into Audio 3\n");
491 641 #endif
  642 + if (s->audio)
  643 + tsc2102_audio_set_format(s);
492 644 return;
493 645  
494 646 case 0x07: /* LCH_BASS_BOOST_N0 */
... ... @@ -718,6 +870,20 @@ static void tsc210x_touchscreen_event(void *opaque,
718 870 tsc210x_pin_update(s);
719 871 }
720 872  
  873 +static void tsc210x_i2s_swallow(struct tsc210x_state_s *s)
  874 +{
  875 + if (s->dac_voice[0])
  876 + tsc210x_out_flush(s, s->codec.out.len);
  877 + else
  878 + s->codec.out.len = 0;
  879 +}
  880 +
  881 +static void tsc210x_i2s_set_rate(struct tsc210x_state_s *s, int in, int out)
  882 +{
  883 + s->i2s_tx_rate = out;
  884 + s->i2s_rx_rate = in;
  885 +}
  886 +
721 887 static void tsc210x_save(QEMUFile *f, void *opaque)
722 888 {
723 889 struct tsc210x_state_s *s = (struct tsc210x_state_s *) opaque;
... ... @@ -817,7 +983,7 @@ static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
817 983  
818 984 static int tsc2102_iid = 0;
819 985  
820   -struct uwire_slave_s *tsc2102_init(qemu_irq pint)
  986 +struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio)
821 987 {
822 988 struct tsc210x_state_s *s;
823 989  
... ... @@ -830,19 +996,37 @@ struct uwire_slave_s *tsc2102_init(qemu_irq pint)
830 996 s->precision = s->nextprecision = 0;
831 997 s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s);
832 998 s->pint = pint;
  999 + s->name = "tsc2102";
  1000 + s->audio = audio;
833 1001  
834 1002 s->chip.opaque = s;
835 1003 s->chip.send = (void *) tsc210x_write;
836 1004 s->chip.receive = (void *) tsc210x_read;
837 1005  
  1006 + s->codec.opaque = s;
  1007 + s->codec.tx_swallow = (void *) tsc210x_i2s_swallow;
  1008 + s->codec.set_rate = (void *) tsc210x_i2s_set_rate;
  1009 + s->codec.in.fifo = s->in_fifo;
  1010 + s->codec.out.fifo = s->out_fifo;
  1011 +
838 1012 tsc210x_reset(s);
839 1013  
840 1014 qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1,
841 1015 "QEMU TSC2102-driven Touchscreen");
842 1016  
  1017 + if (s->audio)
  1018 + AUD_register_card(s->audio, s->name, &s->card);
  1019 +
843 1020 qemu_register_reset((void *) tsc210x_reset, s);
844   - register_savevm("tsc2102", tsc2102_iid ++, 0,
  1021 + register_savevm(s->name, tsc2102_iid ++, 0,
845 1022 tsc210x_save, tsc210x_load, s);
846 1023  
847 1024 return &s->chip;
848 1025 }
  1026 +
  1027 +struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip)
  1028 +{
  1029 + struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque;
  1030 +
  1031 + return &s->codec;
  1032 +}
... ...
... ... @@ -1667,7 +1667,8 @@ void qemu_get_ptimer(QEMUFile *f, ptimer_state *s);
1667 1667 #include "hw/omap.h"
1668 1668  
1669 1669 /* tsc210x.c */
1670   -struct uwire_slave_s *tsc2102_init(qemu_irq pint);
  1670 +struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio);
  1671 +struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip);
1671 1672  
1672 1673 /* mcf_uart.c */
1673 1674 uint32_t mcf_uart_read(void *opaque, target_phys_addr_t addr);
... ...