Clean-up/rewrite audio over I^2S support.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3704 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									79b0241756
								
							
						
					
					
						commit
						73560bc8e3
					
				
							
								
								
									
										294
									
								
								hw/omap.c
									
									
									
									
									
								
							
							
						
						
									
										294
									
								
								hw/omap.c
									
									
									
									
									
								
							| @ -997,7 +997,8 @@ static void omap_dma_clk_update(void *opaque, int line, int on) | ||||
|     struct omap_dma_s *s = (struct omap_dma_s *) opaque; | ||||
| 
 | ||||
|     if (on) { | ||||
|         s->delay = ticks_per_sec >> 7; | ||||
|         /* TODO: make a clever calculation */ | ||||
|         s->delay = ticks_per_sec >> 8; | ||||
|         if (s->run_count) | ||||
|             qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay); | ||||
|     } else { | ||||
| @ -4097,8 +4098,11 @@ struct omap_mcbsp_s { | ||||
|     int tx_rate; | ||||
|     int rx_rate; | ||||
|     int tx_req; | ||||
|     int rx_req; | ||||
| 
 | ||||
|     struct i2s_codec_s *codec; | ||||
|     QEMUTimer *source_timer; | ||||
|     QEMUTimer *sink_timer; | ||||
| }; | ||||
| 
 | ||||
| static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s) | ||||
| @ -4134,62 +4138,8 @@ static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s) | ||||
|     qemu_set_irq(s->txirq, irq); | ||||
| } | ||||
| 
 | ||||
| static void omap_mcbsp_req_update(struct omap_mcbsp_s *s) | ||||
| static void omap_mcbsp_rx_newdata(struct omap_mcbsp_s *s) | ||||
| { | ||||
|     int prev = s->tx_req; | ||||
| 
 | ||||
|     s->tx_req = (s->tx_rate || | ||||
|                     (s->spcr[0] & (1 << 12))) &&	/* CLKSTP */ | ||||
|             (s->spcr[1] & (1 << 6)) &&			/* GRST */ | ||||
|             (s->spcr[1] & (1 << 0));			/* XRST */ | ||||
| 
 | ||||
|     if (!s->tx_req && prev) { | ||||
|         s->spcr[1] &= ~(1 << 1);			/* XRDY */ | ||||
|         qemu_irq_lower(s->txdrq); | ||||
|         omap_mcbsp_intr_update(s); | ||||
| 
 | ||||
|         if (s->codec) | ||||
|             s->codec->tx_swallow(s->codec->opaque); | ||||
|     } else if (s->codec && s->tx_req && !prev) { | ||||
|         s->spcr[1] |= 1 << 1;				/* XRDY */ | ||||
|         qemu_irq_raise(s->txdrq); | ||||
|         omap_mcbsp_intr_update(s); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void omap_mcbsp_rate_update(struct omap_mcbsp_s *s) | ||||
| { | ||||
|     int rx_clk = 0, tx_clk = 0; | ||||
|     int cpu_rate = 1500000;	/* XXX */ | ||||
|     if (!s->codec) | ||||
|         return; | ||||
| 
 | ||||
|     if (s->spcr[1] & (1 << 6)) {			/* GRST */ | ||||
|         if (s->spcr[0] & (1 << 0))			/* RRST */ | ||||
|             if ((s->srgr[1] & (1 << 13)) &&		/* CLKSM */ | ||||
|                             (s->pcr & (1 << 8)))	/* CLKRM */ | ||||
|                 if (~s->pcr & (1 << 7))			/* SCLKME */ | ||||
|                     rx_clk = cpu_rate / | ||||
|                             ((s->srgr[0] & 0xff) + 1);	/* CLKGDV */ | ||||
|         if (s->spcr[1] & (1 << 0))			/* XRST */ | ||||
|             if ((s->srgr[1] & (1 << 13)) &&		/* CLKSM */ | ||||
|                             (s->pcr & (1 << 9)))	/* CLKXM */ | ||||
|                 if (~s->pcr & (1 << 7))			/* SCLKME */ | ||||
|                     tx_clk = cpu_rate / | ||||
|                             ((s->srgr[0] & 0xff) + 1);	/* CLKGDV */ | ||||
|     } | ||||
| 
 | ||||
|     s->codec->set_rate(s->codec->opaque, rx_clk, tx_clk); | ||||
| } | ||||
| 
 | ||||
| static void omap_mcbsp_rx_start(struct omap_mcbsp_s *s) | ||||
| { | ||||
|     if (!(s->spcr[0] & 1)) {				/* RRST */ | ||||
|         if (s->codec) | ||||
|             s->codec->in.len = 0; | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if ((s->spcr[0] >> 1) & 1)				/* RRDY */ | ||||
|         s->spcr[0] |= 1 << 2;				/* RFULL */ | ||||
|     s->spcr[0] |= 1 << 1;				/* RRDY */ | ||||
| @ -4197,25 +4147,140 @@ static void omap_mcbsp_rx_start(struct omap_mcbsp_s *s) | ||||
|     omap_mcbsp_intr_update(s); | ||||
| } | ||||
| 
 | ||||
| static void omap_mcbsp_source_tick(void *opaque) | ||||
| { | ||||
|     struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque; | ||||
|     static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 }; | ||||
| 
 | ||||
|     if (!s->rx_rate) | ||||
|         return; | ||||
|     if (s->rx_req) | ||||
|         printf("%s: Rx FIFO overrun\n", __FUNCTION__); | ||||
| 
 | ||||
|     s->rx_req = s->rx_rate << bps[(s->rcr[0] >> 5) & 7]; | ||||
| 
 | ||||
|     omap_mcbsp_rx_newdata(s); | ||||
|     qemu_mod_timer(s->source_timer, qemu_get_clock(vm_clock) + ticks_per_sec); | ||||
| } | ||||
| 
 | ||||
| static void omap_mcbsp_rx_start(struct omap_mcbsp_s *s) | ||||
| { | ||||
|     if (!s->codec || !s->codec->rts) | ||||
|         omap_mcbsp_source_tick(s); | ||||
|     else if (s->codec->in.len) { | ||||
|         s->rx_req = s->codec->in.len; | ||||
|         omap_mcbsp_rx_newdata(s); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void omap_mcbsp_rx_stop(struct omap_mcbsp_s *s) | ||||
| { | ||||
|     qemu_del_timer(s->source_timer); | ||||
| } | ||||
| 
 | ||||
| static void omap_mcbsp_rx_done(struct omap_mcbsp_s *s) | ||||
| { | ||||
|     s->spcr[0] &= ~(1 << 1);				/* RRDY */ | ||||
|     qemu_irq_lower(s->rxdrq); | ||||
|     omap_mcbsp_intr_update(s); | ||||
| } | ||||
| 
 | ||||
| static void omap_mcbsp_tx_newdata(struct omap_mcbsp_s *s) | ||||
| { | ||||
|     s->spcr[1] |= 1 << 1;				/* XRDY */ | ||||
|     qemu_irq_raise(s->txdrq); | ||||
|     omap_mcbsp_intr_update(s); | ||||
| } | ||||
| 
 | ||||
| static void omap_mcbsp_sink_tick(void *opaque) | ||||
| { | ||||
|     struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque; | ||||
|     static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 }; | ||||
| 
 | ||||
|     if (!s->tx_rate) | ||||
|         return; | ||||
|     if (s->tx_req) | ||||
|         printf("%s: Tx FIFO underrun\n", __FUNCTION__); | ||||
| 
 | ||||
|     s->tx_req = s->tx_rate << bps[(s->xcr[0] >> 5) & 7]; | ||||
| 
 | ||||
|     omap_mcbsp_tx_newdata(s); | ||||
|     qemu_mod_timer(s->sink_timer, qemu_get_clock(vm_clock) + ticks_per_sec); | ||||
| } | ||||
| 
 | ||||
| static void omap_mcbsp_tx_start(struct omap_mcbsp_s *s) | ||||
| { | ||||
|     if (s->tx_rate) | ||||
|         return; | ||||
|     s->tx_rate = 1; | ||||
|     omap_mcbsp_req_update(s); | ||||
|     if (!s->codec || !s->codec->cts) | ||||
|         omap_mcbsp_sink_tick(s); | ||||
|     else if (s->codec->out.size) { | ||||
|         s->tx_req = s->codec->out.size; | ||||
|         omap_mcbsp_tx_newdata(s); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void omap_mcbsp_tx_done(struct omap_mcbsp_s *s) | ||||
| { | ||||
|     s->spcr[1] &= ~(1 << 1);				/* XRDY */ | ||||
|     qemu_irq_lower(s->txdrq); | ||||
|     omap_mcbsp_intr_update(s); | ||||
|     if (s->codec && s->codec->cts) | ||||
|         s->codec->tx_swallow(s->codec->opaque); | ||||
| } | ||||
| 
 | ||||
| static void omap_mcbsp_tx_stop(struct omap_mcbsp_s *s) | ||||
| { | ||||
|     s->tx_rate = 0; | ||||
|     omap_mcbsp_req_update(s); | ||||
|     s->tx_req = 0; | ||||
|     omap_mcbsp_tx_done(s); | ||||
|     qemu_del_timer(s->sink_timer); | ||||
| } | ||||
| 
 | ||||
| static void omap_mcbsp_req_update(struct omap_mcbsp_s *s) | ||||
| { | ||||
|     int prev_rx_rate, prev_tx_rate; | ||||
|     int rx_rate = 0, tx_rate = 0; | ||||
|     int cpu_rate = 1500000;	/* XXX */ | ||||
| 
 | ||||
|     /* TODO: check CLKSTP bit */ | ||||
|     if (s->spcr[1] & (1 << 6)) {			/* GRST */ | ||||
|         if (s->spcr[0] & (1 << 0)) {			/* RRST */ | ||||
|             if ((s->srgr[1] & (1 << 13)) &&		/* CLKSM */ | ||||
|                             (s->pcr & (1 << 8))) {	/* CLKRM */ | ||||
|                 if (~s->pcr & (1 << 7))			/* SCLKME */ | ||||
|                     rx_rate = cpu_rate / | ||||
|                             ((s->srgr[0] & 0xff) + 1);	/* CLKGDV */ | ||||
|             } else | ||||
|                 if (s->codec) | ||||
|                     rx_rate = s->codec->rx_rate; | ||||
|         } | ||||
| 
 | ||||
|         if (s->spcr[1] & (1 << 0)) {			/* XRST */ | ||||
|             if ((s->srgr[1] & (1 << 13)) &&		/* CLKSM */ | ||||
|                             (s->pcr & (1 << 9))) {	/* CLKXM */ | ||||
|                 if (~s->pcr & (1 << 7))			/* SCLKME */ | ||||
|                     tx_rate = cpu_rate / | ||||
|                             ((s->srgr[0] & 0xff) + 1);	/* CLKGDV */ | ||||
|             } else | ||||
|                 if (s->codec) | ||||
|                     tx_rate = s->codec->tx_rate; | ||||
|         } | ||||
|     } | ||||
|     prev_tx_rate = s->tx_rate; | ||||
|     prev_rx_rate = s->rx_rate; | ||||
|     s->tx_rate = tx_rate; | ||||
|     s->rx_rate = rx_rate; | ||||
| 
 | ||||
|     if (s->codec) | ||||
|         s->codec->set_rate(s->codec->opaque, rx_rate, tx_rate); | ||||
| 
 | ||||
|     if (!prev_tx_rate && tx_rate) | ||||
|         omap_mcbsp_tx_start(s); | ||||
|     else if (s->tx_rate && !tx_rate) | ||||
|         omap_mcbsp_tx_stop(s); | ||||
| 
 | ||||
|     if (!prev_rx_rate && rx_rate) | ||||
|         omap_mcbsp_rx_start(s); | ||||
|     else if (prev_tx_rate && !tx_rate) | ||||
|         omap_mcbsp_rx_stop(s); | ||||
| } | ||||
| 
 | ||||
| static uint32_t omap_mcbsp_read(void *opaque, target_phys_addr_t addr) | ||||
| @ -4230,17 +4295,19 @@ static uint32_t omap_mcbsp_read(void *opaque, target_phys_addr_t addr) | ||||
|             return 0x0000; | ||||
|         /* Fall through.  */ | ||||
|     case 0x02:	/* DRR1 */ | ||||
|         if (!s->codec) | ||||
|             return 0x0000; | ||||
|         if (s->codec->in.len < 2) { | ||||
|         if (s->rx_req < 2) { | ||||
|             printf("%s: Rx FIFO underrun\n", __FUNCTION__); | ||||
|             omap_mcbsp_rx_stop(s); | ||||
|             omap_mcbsp_rx_done(s); | ||||
|         } else { | ||||
|             s->codec->in.len -= 2; | ||||
|             ret = s->codec->in.fifo[s->codec->in.start ++] << 8; | ||||
|             ret |= s->codec->in.fifo[s->codec->in.start ++]; | ||||
|             if (!s->codec->in.len) | ||||
|                 omap_mcbsp_rx_stop(s); | ||||
|             s->tx_req -= 2; | ||||
|             if (s->codec && s->codec->in.len >= 2) { | ||||
|                 ret = s->codec->in.fifo[s->codec->in.start ++] << 8; | ||||
|                 ret |= s->codec->in.fifo[s->codec->in.start ++]; | ||||
|                 s->codec->in.len -= 2; | ||||
|             } else | ||||
|                 ret = 0x0000; | ||||
|             if (!s->tx_req) | ||||
|                 omap_mcbsp_rx_done(s); | ||||
|             return ret; | ||||
|         } | ||||
|         return 0x0000; | ||||
| @ -4309,7 +4376,7 @@ static uint32_t omap_mcbsp_read(void *opaque, target_phys_addr_t addr) | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static void omap_mcbsp_write(void *opaque, target_phys_addr_t addr, | ||||
| static void omap_mcbsp_writeh(void *opaque, target_phys_addr_t addr, | ||||
|                 uint32_t value) | ||||
| { | ||||
|     struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque; | ||||
| @ -4326,18 +4393,14 @@ static void omap_mcbsp_write(void *opaque, target_phys_addr_t addr, | ||||
|             return; | ||||
|         /* Fall through.  */ | ||||
|     case 0x06:	/* DXR1 */ | ||||
|         if (!s->codec) | ||||
|             return; | ||||
|         if (s->tx_req) { | ||||
|             if (s->codec->out.len > s->codec->out.size - 2) { | ||||
|                 printf("%s: Tx FIFO overrun\n", __FUNCTION__); | ||||
|                 omap_mcbsp_tx_stop(s); | ||||
|             } else { | ||||
|         if (s->tx_req > 1) { | ||||
|             s->tx_req -= 2; | ||||
|             if (s->codec && s->codec->cts) { | ||||
|                 s->codec->out.fifo[s->codec->out.len ++] = (value >> 8) & 0xff; | ||||
|                 s->codec->out.fifo[s->codec->out.len ++] = (value >> 0) & 0xff; | ||||
|                 if (s->codec->out.len >= s->codec->out.size) | ||||
|                     omap_mcbsp_tx_stop(s); | ||||
|             } | ||||
|             if (s->tx_req < 2) | ||||
|                 omap_mcbsp_tx_done(s); | ||||
|         } else | ||||
|             printf("%s: Tx FIFO overrun\n", __FUNCTION__); | ||||
|         return; | ||||
| @ -4346,14 +4409,8 @@ static void omap_mcbsp_write(void *opaque, target_phys_addr_t addr, | ||||
|         s->spcr[1] &= 0x0002; | ||||
|         s->spcr[1] |= 0x03f9 & value; | ||||
|         s->spcr[1] |= 0x0004 & (value << 2);		/* XEMPTY := XRST */ | ||||
|         if (~value & 1) {				/* XRST */ | ||||
|         if (~value & 1)					/* XRST */ | ||||
|             s->spcr[1] &= ~6; | ||||
|             qemu_irq_lower(s->rxdrq); | ||||
|             if (s->codec) | ||||
|                 s->codec->out.len = 0; | ||||
|         } | ||||
|         if (s->codec) | ||||
|             omap_mcbsp_rate_update(s); | ||||
|         omap_mcbsp_req_update(s); | ||||
|         return; | ||||
|     case 0x0a:	/* SPCR1 */ | ||||
| @ -4363,12 +4420,9 @@ static void omap_mcbsp_write(void *opaque, target_phys_addr_t addr, | ||||
|             printf("%s: Digital Loopback mode enable attempt\n", __FUNCTION__); | ||||
|         if (~value & 1) {				/* RRST */ | ||||
|             s->spcr[0] &= ~6; | ||||
|             qemu_irq_lower(s->txdrq); | ||||
|             if (s->codec) | ||||
|                 s->codec->in.len = 0; | ||||
|             s->rx_req = 0; | ||||
|             omap_mcbsp_rx_done(s); | ||||
|         } | ||||
|         if (s->codec) | ||||
|             omap_mcbsp_rate_update(s); | ||||
|         omap_mcbsp_req_update(s); | ||||
|         return; | ||||
| 
 | ||||
| @ -4386,11 +4440,11 @@ static void omap_mcbsp_write(void *opaque, target_phys_addr_t addr, | ||||
|         return; | ||||
|     case 0x14:	/* SRGR2 */ | ||||
|         s->srgr[1] = value & 0xffff; | ||||
|         omap_mcbsp_rate_update(s); | ||||
|         omap_mcbsp_req_update(s); | ||||
|         return; | ||||
|     case 0x16:	/* SRGR1 */ | ||||
|         s->srgr[0] = value & 0xffff; | ||||
|         omap_mcbsp_rate_update(s); | ||||
|         omap_mcbsp_req_update(s); | ||||
|         return; | ||||
|     case 0x18:	/* MCR2 */ | ||||
|         s->mcr[1] = value & 0x03e3; | ||||
| @ -4460,6 +4514,37 @@ static void omap_mcbsp_write(void *opaque, target_phys_addr_t addr, | ||||
|     OMAP_BAD_REG(addr); | ||||
| } | ||||
| 
 | ||||
| static void omap_mcbsp_writew(void *opaque, target_phys_addr_t addr, | ||||
|                 uint32_t value) | ||||
| { | ||||
|     struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque; | ||||
|     int offset = addr & OMAP_MPUI_REG_MASK; | ||||
| 
 | ||||
|     if (offset == 0x04) {				/* DXR */ | ||||
|         if (((s->xcr[0] >> 5) & 7) < 3)			/* XWDLEN1 */ | ||||
|             return; | ||||
|         if (s->tx_req > 3) { | ||||
|             s->tx_req -= 4; | ||||
|             if (s->codec && s->codec->cts) { | ||||
|                 s->codec->out.fifo[s->codec->out.len ++] = | ||||
|                         (value >> 24) & 0xff; | ||||
|                 s->codec->out.fifo[s->codec->out.len ++] = | ||||
|                         (value >> 16) & 0xff; | ||||
|                 s->codec->out.fifo[s->codec->out.len ++] = | ||||
|                         (value >> 8) & 0xff; | ||||
|                 s->codec->out.fifo[s->codec->out.len ++] = | ||||
|                         (value >> 0) & 0xff; | ||||
|             } | ||||
|             if (s->tx_req < 4) | ||||
|                 omap_mcbsp_tx_done(s); | ||||
|         } else | ||||
|             printf("%s: Tx FIFO overrun\n", __FUNCTION__); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     omap_badwidth_write16(opaque, addr, value); | ||||
| } | ||||
| 
 | ||||
| static CPUReadMemoryFunc *omap_mcbsp_readfn[] = { | ||||
|     omap_badwidth_read16, | ||||
|     omap_mcbsp_read, | ||||
| @ -4468,8 +4553,8 @@ static CPUReadMemoryFunc *omap_mcbsp_readfn[] = { | ||||
| 
 | ||||
| static CPUWriteMemoryFunc *omap_mcbsp_writefn[] = { | ||||
|     omap_badwidth_write16, | ||||
|     omap_mcbsp_write, | ||||
|     omap_badwidth_write16, | ||||
|     omap_mcbsp_writeh, | ||||
|     omap_mcbsp_writew, | ||||
| }; | ||||
| 
 | ||||
| static void omap_mcbsp_reset(struct omap_mcbsp_s *s) | ||||
| @ -4484,8 +4569,11 @@ static void omap_mcbsp_reset(struct omap_mcbsp_s *s) | ||||
|     memset(&s->rcer, 0, sizeof(s->rcer)); | ||||
|     memset(&s->xcer, 0, sizeof(s->xcer)); | ||||
|     s->tx_req = 0; | ||||
|     s->rx_req = 0; | ||||
|     s->tx_rate = 0; | ||||
|     s->rx_rate = 0; | ||||
|     qemu_del_timer(s->source_timer); | ||||
|     qemu_del_timer(s->sink_timer); | ||||
| } | ||||
| 
 | ||||
| struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base, | ||||
| @ -4500,6 +4588,8 @@ struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base, | ||||
|     s->rxirq = irq[1]; | ||||
|     s->txdrq = dma[0]; | ||||
|     s->rxdrq = dma[1]; | ||||
|     s->sink_timer = qemu_new_timer(vm_clock, omap_mcbsp_sink_tick, s); | ||||
|     s->source_timer = qemu_new_timer(vm_clock, omap_mcbsp_source_tick, s); | ||||
|     omap_mcbsp_reset(s); | ||||
| 
 | ||||
|     iomemtype = cpu_register_io_memory(0, omap_mcbsp_readfn, | ||||
| @ -4513,14 +4603,20 @@ static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level) | ||||
| { | ||||
|     struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque; | ||||
| 
 | ||||
|     omap_mcbsp_rx_start(s); | ||||
|     if (s->rx_rate) { | ||||
|         s->rx_req = s->codec->in.len; | ||||
|         omap_mcbsp_rx_newdata(s); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void omap_mcbsp_i2s_start(void *opaque, int line, int level) | ||||
| { | ||||
|     struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque; | ||||
| 
 | ||||
|     omap_mcbsp_tx_start(s); | ||||
|     if (s->tx_rate) { | ||||
|         s->tx_req = s->codec->out.size; | ||||
|         omap_mcbsp_tx_newdata(s); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave) | ||||
|  | ||||
| @ -491,6 +491,11 @@ struct i2s_codec_s { | ||||
|     qemu_irq rx_swallow; | ||||
|     qemu_irq tx_start; | ||||
| 
 | ||||
|     int tx_rate; | ||||
|     int cts; | ||||
|     int rx_rate; | ||||
|     int rts; | ||||
| 
 | ||||
|     struct i2s_fifo_s { | ||||
|         uint8_t *fifo; | ||||
|         int len; | ||||
|  | ||||
							
								
								
									
										56
									
								
								hw/tsc210x.c
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								hw/tsc210x.c
									
									
									
									
									
								
							| @ -283,24 +283,13 @@ static void tsc210x_audio_out_cb(struct tsc210x_state_s *s, int free_b) | ||||
|     qemu_irq_raise(s->codec.tx_start); | ||||
| } | ||||
| 
 | ||||
| static void tsc2102_audio_set_format(struct tsc210x_state_s *s) | ||||
| static void tsc2102_audio_rate_update(struct tsc210x_state_s *s) | ||||
| { | ||||
|     int enable; | ||||
|     const struct tsc210x_rate_info_s *rate; | ||||
|     audsettings_t fmt; | ||||
| 
 | ||||
|     if (s->dac_voice[0]) { | ||||
|         tsc210x_out_flush(s, s->codec.out.len); | ||||
|         s->codec.out.size = 0; | ||||
|         AUD_set_active_out(s->dac_voice[0], 0); | ||||
|         AUD_close_out(&s->card, s->dac_voice[0]); | ||||
|         s->dac_voice[0] = 0; | ||||
|     } | ||||
| 
 | ||||
|     enable = | ||||
|             (~s->dac_power & (1 << 15)) &&			/* PWDNC */ | ||||
|             (~s->dac_power & (1 << 10));			/* DAPWDN */ | ||||
|     if (!enable) | ||||
|     s->codec.tx_rate = 0; | ||||
|     s->codec.rx_rate = 0; | ||||
|     if (s->dac_power & (1 << 15))				/* PWDNC */ | ||||
|         return; | ||||
| 
 | ||||
|     for (rate = tsc2102_rates; rate->rate; rate ++) | ||||
| @ -312,16 +301,41 @@ static void tsc2102_audio_set_format(struct tsc210x_state_s *s) | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     s->codec.tx_rate = rate->rate; | ||||
| } | ||||
| 
 | ||||
| static void tsc2102_audio_output_update(struct tsc210x_state_s *s) | ||||
| { | ||||
|     int enable; | ||||
|     audsettings_t fmt; | ||||
| 
 | ||||
|     if (s->dac_voice[0]) { | ||||
|         tsc210x_out_flush(s, s->codec.out.len); | ||||
|         s->codec.out.size = 0; | ||||
|         AUD_set_active_out(s->dac_voice[0], 0); | ||||
|         AUD_close_out(&s->card, s->dac_voice[0]); | ||||
|         s->dac_voice[0] = 0; | ||||
|     } | ||||
|     s->codec.cts = 0; | ||||
| 
 | ||||
|     enable = | ||||
|             (~s->dac_power & (1 << 15)) &&			/* PWDNC */ | ||||
|             (~s->dac_power & (1 << 10));			/* DAPWDN */ | ||||
|     if (!enable || !s->codec.tx_rate) | ||||
|         return; | ||||
| 
 | ||||
|     /* Force our own sampling rate even in slave DAC mode */ | ||||
|     fmt.endianness = 0; | ||||
|     fmt.nchannels = 2; | ||||
|     fmt.freq = rate->rate; | ||||
|     fmt.freq = s->codec.tx_rate; | ||||
|     fmt.fmt = AUD_FMT_S16; | ||||
| 
 | ||||
|     s->dac_voice[0] = AUD_open_out(&s->card, s->dac_voice[0], | ||||
|                     "tsc2102.sink", s, (void *) tsc210x_audio_out_cb, &fmt); | ||||
|     if (s->dac_voice[0]) | ||||
|     if (s->dac_voice[0]) { | ||||
|         s->codec.cts = 1; | ||||
|         AUD_set_active_out(s->dac_voice[0], 1); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg) | ||||
| @ -587,8 +601,9 @@ static void tsc2102_audio_register_write( | ||||
|             fprintf(stderr, "tsc2102_audio_register_write: " | ||||
|                             "wrong value written into Audio 1\n"); | ||||
| #endif | ||||
|         tsc2102_audio_rate_update(s); | ||||
|         if (s->audio) | ||||
|             tsc2102_audio_set_format(s); | ||||
|             tsc2102_audio_output_update(s); | ||||
|         return; | ||||
| 
 | ||||
|     case 0x01: | ||||
| @ -631,8 +646,9 @@ static void tsc2102_audio_register_write( | ||||
|             fprintf(stderr, "tsc2102_audio_register_write: " | ||||
|                             "wrong value written into Power\n"); | ||||
| #endif | ||||
|         tsc2102_audio_rate_update(s); | ||||
|         if (s->audio) | ||||
|             tsc2102_audio_set_format(s); | ||||
|             tsc2102_audio_output_update(s); | ||||
|         return; | ||||
| 
 | ||||
|     case 0x06:	/* Audio Control 3 */ | ||||
| @ -644,7 +660,7 @@ static void tsc2102_audio_register_write( | ||||
|                             "wrong value written into Audio 3\n"); | ||||
| #endif | ||||
|         if (s->audio) | ||||
|             tsc2102_audio_set_format(s); | ||||
|             tsc2102_audio_output_update(s); | ||||
|         return; | ||||
| 
 | ||||
|     case 0x07:	/* LCH_BASS_BOOST_N0 */ | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 balrog
						balrog