diff options
author | Andreas Eversberg <andreas@eversberg.eu> | 2008-08-02 16:51:52 -0400 |
---|---|---|
committer | Karsten Keil <kkeil@suse.de> | 2009-01-09 16:44:22 -0500 |
commit | 8dd2f36f317569665e454268a2677cfba3e848f1 (patch) | |
tree | 62f0d30aa090594648ed21cb9a863e4cc2b4f4fd /drivers/isdn/hardware/mISDN/hfcpci.c | |
parent | 69e656cc16511719a89d83373c48172d3f39bc5f (diff) |
mISDN: Add feature via MISDN_CTRL_FILL_EMPTY to fill fifo if empty
This prevents underrun of fifo when filled and in case of an underrun it
prevents subsequent underruns due to jitter.
Improve dsp, so buffers are kept filled with a certain delay, so moderate
jitter will not cause underrun all the time -> the audio quality is highly
improved. tones are not interrupted by gaps anymore, except when CPU is
stalling or in high load.
Signed-off-by: Andreas Eversberg <andreas@eversberg.eu>
Signed-off-by: Karsten Keil <kkeil@suse.de>
Diffstat (limited to 'drivers/isdn/hardware/mISDN/hfcpci.c')
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfcpci.c | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index cd8302af40e..80c356e5dbe 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c | |||
@@ -751,6 +751,36 @@ hfcpci_fill_fifo(struct bchannel *bch) | |||
751 | /* fcnt contains available bytes in fifo */ | 751 | /* fcnt contains available bytes in fifo */ |
752 | fcnt = B_FIFO_SIZE - fcnt; | 752 | fcnt = B_FIFO_SIZE - fcnt; |
753 | /* remaining bytes to send (bytes in fifo) */ | 753 | /* remaining bytes to send (bytes in fifo) */ |
754 | |||
755 | /* "fill fifo if empty" feature */ | ||
756 | if (test_bit(FLG_FILLEMPTY, &bch->Flags) && !fcnt) { | ||
757 | /* printk(KERN_DEBUG "%s: buffer empty, so we have " | ||
758 | "underrun\n", __func__); */ | ||
759 | /* fill buffer, to prevent future underrun */ | ||
760 | count = HFCPCI_FILLEMPTY; | ||
761 | new_z1 = le16_to_cpu(*z1t) + count; | ||
762 | /* new buffer Position */ | ||
763 | if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL)) | ||
764 | new_z1 -= B_FIFO_SIZE; /* buffer wrap */ | ||
765 | dst = bdata + (le16_to_cpu(*z1t) - B_SUB_VAL); | ||
766 | maxlen = (B_FIFO_SIZE + B_SUB_VAL) - le16_to_cpu(*z1t); | ||
767 | /* end of fifo */ | ||
768 | if (bch->debug & DEBUG_HW_BFIFO) | ||
769 | printk(KERN_DEBUG "hfcpci_FFt fillempty " | ||
770 | "fcnt(%d) maxl(%d) nz1(%x) dst(%p)\n", | ||
771 | fcnt, maxlen, new_z1, dst); | ||
772 | fcnt += count; | ||
773 | if (maxlen > count) | ||
774 | maxlen = count; /* limit size */ | ||
775 | memset(dst, 0x2a, maxlen); /* first copy */ | ||
776 | count -= maxlen; /* remaining bytes */ | ||
777 | if (count) { | ||
778 | dst = bdata; /* start of buffer */ | ||
779 | memset(dst, 0x2a, count); | ||
780 | } | ||
781 | *z1t = cpu_to_le16(new_z1); /* now send data */ | ||
782 | } | ||
783 | |||
754 | next_t_frame: | 784 | next_t_frame: |
755 | count = bch->tx_skb->len - bch->tx_idx; | 785 | count = bch->tx_skb->len - bch->tx_idx; |
756 | /* maximum fill shall be HFCPCI_BTRANS_MAX */ | 786 | /* maximum fill shall be HFCPCI_BTRANS_MAX */ |
@@ -1481,11 +1511,17 @@ deactivate_bchannel(struct bchannel *bch) | |||
1481 | static int | 1511 | static int |
1482 | channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) | 1512 | channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) |
1483 | { | 1513 | { |
1484 | int ret = 0; | 1514 | int ret = 0; |
1485 | 1515 | ||
1486 | switch (cq->op) { | 1516 | switch (cq->op) { |
1487 | case MISDN_CTRL_GETOP: | 1517 | case MISDN_CTRL_GETOP: |
1488 | cq->op = 0; | 1518 | cq->op = MISDN_CTRL_FILL_EMPTY; |
1519 | break; | ||
1520 | case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */ | ||
1521 | test_and_set_bit(FLG_FILLEMPTY, &bch->Flags); | ||
1522 | if (debug & DEBUG_HW_OPEN) | ||
1523 | printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d " | ||
1524 | "off=%d)\n", __func__, bch->nr, !!cq->p1); | ||
1489 | break; | 1525 | break; |
1490 | default: | 1526 | default: |
1491 | printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op); | 1527 | printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op); |
@@ -1903,6 +1939,7 @@ open_bchannel(struct hfc_pci *hc, struct channel_req *rq) | |||
1903 | bch = &hc->bch[rq->adr.channel - 1]; | 1939 | bch = &hc->bch[rq->adr.channel - 1]; |
1904 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) | 1940 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) |
1905 | return -EBUSY; /* b-channel can be only open once */ | 1941 | return -EBUSY; /* b-channel can be only open once */ |
1942 | test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); | ||
1906 | bch->ch.protocol = rq->protocol; | 1943 | bch->ch.protocol = rq->protocol; |
1907 | rq->ch = &bch->ch; /* TODO: E-channel */ | 1944 | rq->ch = &bch->ch; /* TODO: E-channel */ |
1908 | if (!try_module_get(THIS_MODULE)) | 1945 | if (!try_module_get(THIS_MODULE)) |