aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/hardware
diff options
context:
space:
mode:
authorAndreas Eversberg <andreas@eversberg.eu>2008-08-02 16:51:52 -0400
committerKarsten Keil <kkeil@suse.de>2009-01-09 16:44:22 -0500
commit8dd2f36f317569665e454268a2677cfba3e848f1 (patch)
tree62f0d30aa090594648ed21cb9a863e4cc2b4f4fd /drivers/isdn/hardware
parent69e656cc16511719a89d83373c48172d3f39bc5f (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')
-rw-r--r--drivers/isdn/hardware/mISDN/hfc_multi.h3
-rw-r--r--drivers/isdn/hardware/mISDN/hfc_pci.h1
-rw-r--r--drivers/isdn/hardware/mISDN/hfcmulti.c45
-rw-r--r--drivers/isdn/hardware/mISDN/hfcpci.c41
4 files changed, 78 insertions, 12 deletions
diff --git a/drivers/isdn/hardware/mISDN/hfc_multi.h b/drivers/isdn/hardware/mISDN/hfc_multi.h
index 6d74951a1797..4aa6a8b41f50 100644
--- a/drivers/isdn/hardware/mISDN/hfc_multi.h
+++ b/drivers/isdn/hardware/mISDN/hfc_multi.h
@@ -9,6 +9,7 @@
9#define DEBUG_HFCMULTI_MODE 0x00100000 9#define DEBUG_HFCMULTI_MODE 0x00100000
10#define DEBUG_HFCMULTI_MSG 0x00200000 10#define DEBUG_HFCMULTI_MSG 0x00200000
11#define DEBUG_HFCMULTI_STATE 0x00400000 11#define DEBUG_HFCMULTI_STATE 0x00400000
12#define DEBUG_HFCMULTI_FILL 0x00800000
12#define DEBUG_HFCMULTI_SYNC 0x01000000 13#define DEBUG_HFCMULTI_SYNC 0x01000000
13#define DEBUG_HFCMULTI_DTMF 0x02000000 14#define DEBUG_HFCMULTI_DTMF 0x02000000
14#define DEBUG_HFCMULTI_LOCK 0x80000000 15#define DEBUG_HFCMULTI_LOCK 0x80000000
@@ -166,6 +167,8 @@ struct hfc_multi {
166 167
167 u_long chip; /* chip configuration */ 168 u_long chip; /* chip configuration */
168 int masterclk; /* port that provides master clock -1=off */ 169 int masterclk; /* port that provides master clock -1=off */
170 unsigned char silence;/* silence byte */
171 unsigned char silence_data[128];/* silence block */
169 int dtmf; /* flag that dtmf is currently in process */ 172 int dtmf; /* flag that dtmf is currently in process */
170 int Flen; /* F-buffer size */ 173 int Flen; /* F-buffer size */
171 int Zlen; /* Z-buffer size (must be int for calculation)*/ 174 int Zlen; /* Z-buffer size (must be int for calculation)*/
diff --git a/drivers/isdn/hardware/mISDN/hfc_pci.h b/drivers/isdn/hardware/mISDN/hfc_pci.h
index 5783d22a18fe..fd9241ab1802 100644
--- a/drivers/isdn/hardware/mISDN/hfc_pci.h
+++ b/drivers/isdn/hardware/mISDN/hfc_pci.h
@@ -27,6 +27,7 @@
27 */ 27 */
28#define HFCPCI_BTRANS_THRESHOLD 128 28#define HFCPCI_BTRANS_THRESHOLD 128
29#define HFCPCI_BTRANS_MAX 256 29#define HFCPCI_BTRANS_MAX 256
30#define HFCPCI_FILLEMPTY 64
30#define HFCPCI_BTRANS_THRESMASK 0x00 31#define HFCPCI_BTRANS_THRESMASK 0x00
31 32
32/* defines for PCI config */ 33/* defines for PCI config */
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index ff5ec3cbeb77..3fc2e9d95341 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -180,7 +180,6 @@ static int nt_t1_count[] = { 3840, 1920, 960, 480, 240, 120, 60, 30 };
180#define CLKDEL_TE 0x0f /* CLKDEL in TE mode */ 180#define CLKDEL_TE 0x0f /* CLKDEL in TE mode */
181#define CLKDEL_NT 0x6c /* CLKDEL in NT mode 181#define CLKDEL_NT 0x6c /* CLKDEL in NT mode
182 (0x60 MUST be included!) */ 182 (0x60 MUST be included!) */
183static u_char silence = 0xff; /* silence by LAW */
184 183
185#define DIP_4S 0x1 /* DIP Switches for Beronet 1S/2S/4S cards */ 184#define DIP_4S 0x1 /* DIP Switches for Beronet 1S/2S/4S cards */
186#define DIP_8S 0x2 /* DIP Switches for Beronet 8S+ cards */ 185#define DIP_8S 0x2 /* DIP Switches for Beronet 8S+ cards */
@@ -1975,6 +1974,17 @@ next_frame:
1975 return; /* no data */ 1974 return; /* no data */
1976 } 1975 }
1977 1976
1977 /* "fill fifo if empty" feature */
1978 if (bch && test_bit(FLG_FILLEMPTY, &bch->Flags)
1979 && !test_bit(FLG_HDLC, &bch->Flags) && z2 == z1) {
1980 if (debug & DEBUG_HFCMULTI_FILL)
1981 printk(KERN_DEBUG "%s: buffer empty, so we have "
1982 "underrun\n", __func__);
1983 /* fill buffer, to prevent future underrun */
1984 hc->write_fifo(hc, hc->silence_data, poll >> 1);
1985 Zspace -= (poll >> 1);
1986 }
1987
1978 /* if audio data and connected slot */ 1988 /* if audio data and connected slot */
1979 if (bch && (!test_bit(FLG_HDLC, &bch->Flags)) && (!*txpending) 1989 if (bch && (!test_bit(FLG_HDLC, &bch->Flags)) && (!*txpending)
1980 && slot_tx >= 0) { 1990 && slot_tx >= 0) {
@@ -2011,7 +2021,6 @@ next_frame:
2011 __func__, hc->id + 1, ch, Zspace, z1, z2, ii-i, len-i, 2021 __func__, hc->id + 1, ch, Zspace, z1, z2, ii-i, len-i,
2012 temp ? "HDLC":"TRANS"); 2022 temp ? "HDLC":"TRANS");
2013 2023
2014
2015 /* Have to prep the audio data */ 2024 /* Have to prep the audio data */
2016 hc->write_fifo(hc, d, ii - i); 2025 hc->write_fifo(hc, d, ii - i);
2017 *idxp = ii; 2026 *idxp = ii;
@@ -2050,7 +2059,7 @@ next_frame:
2050 * no more data at all. this prevents sending an undefined value. 2059 * no more data at all. this prevents sending an undefined value.
2051 */ 2060 */
2052 if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags)) 2061 if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags))
2053 HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence); 2062 HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence);
2054} 2063}
2055 2064
2056 2065
@@ -2932,7 +2941,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx,
2932 HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); 2941 HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
2933 HFC_wait(hc); 2942 HFC_wait(hc);
2934 /* tx silence */ 2943 /* tx silence */
2935 HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence); 2944 HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence);
2936 HFC_outb(hc, R_SLOT, (((ch / 4) * 8) + 2945 HFC_outb(hc, R_SLOT, (((ch / 4) * 8) +
2937 ((ch % 4) * 4)) << 1); 2946 ((ch % 4) * 4)) << 1);
2938 HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 1)); 2947 HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 1));
@@ -2947,7 +2956,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx,
2947 HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); 2956 HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
2948 HFC_wait(hc); 2957 HFC_wait(hc);
2949 /* tx silence */ 2958 /* tx silence */
2950 HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence); 2959 HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence);
2951 /* enable RX fifo */ 2960 /* enable RX fifo */
2952 HFC_outb(hc, R_FIFO, (ch<<1)|1); 2961 HFC_outb(hc, R_FIFO, (ch<<1)|1);
2953 HFC_wait(hc); 2962 HFC_wait(hc);
@@ -3439,7 +3448,7 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
3439 switch (cq->op) { 3448 switch (cq->op) {
3440 case MISDN_CTRL_GETOP: 3449 case MISDN_CTRL_GETOP:
3441 cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP 3450 cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP
3442 | MISDN_CTRL_RX_OFF; 3451 | MISDN_CTRL_RX_OFF | MISDN_CTRL_FILL_EMPTY;
3443 break; 3452 break;
3444 case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */ 3453 case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */
3445 hc->chan[bch->slot].rx_off = !!cq->p1; 3454 hc->chan[bch->slot].rx_off = !!cq->p1;
@@ -3454,6 +3463,12 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
3454 printk(KERN_DEBUG "%s: RX_OFF request (nr=%d off=%d)\n", 3463 printk(KERN_DEBUG "%s: RX_OFF request (nr=%d off=%d)\n",
3455 __func__, bch->nr, hc->chan[bch->slot].rx_off); 3464 __func__, bch->nr, hc->chan[bch->slot].rx_off);
3456 break; 3465 break;
3466 case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
3467 test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
3468 if (debug & DEBUG_HFCMULTI_MSG)
3469 printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d "
3470 "off=%d)\n", __func__, bch->nr, !!cq->p1);
3471 break;
3457 case MISDN_CTRL_HW_FEATURES: /* fill features structure */ 3472 case MISDN_CTRL_HW_FEATURES: /* fill features structure */
3458 if (debug & DEBUG_HFCMULTI_MSG) 3473 if (debug & DEBUG_HFCMULTI_MSG)
3459 printk(KERN_DEBUG "%s: HW_FEATURE request\n", 3474 printk(KERN_DEBUG "%s: HW_FEATURE request\n",
@@ -3970,6 +3985,7 @@ open_bchannel(struct hfc_multi *hc, struct dchannel *dch,
3970 } 3985 }
3971 if (test_and_set_bit(FLG_OPEN, &bch->Flags)) 3986 if (test_and_set_bit(FLG_OPEN, &bch->Flags))
3972 return -EBUSY; /* b-channel can be only open once */ 3987 return -EBUSY; /* b-channel can be only open once */
3988 test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
3973 bch->ch.protocol = rq->protocol; 3989 bch->ch.protocol = rq->protocol;
3974 hc->chan[ch].rx_off = 0; 3990 hc->chan[ch].rx_off = 0;
3975 rq->ch = &bch->ch; 3991 rq->ch = &bch->ch;
@@ -4806,6 +4822,7 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
4806 struct hfc_multi *hc; 4822 struct hfc_multi *hc;
4807 u_long flags; 4823 u_long flags;
4808 u_char dips = 0, pmj = 0; /* dip settings, port mode Jumpers */ 4824 u_char dips = 0, pmj = 0; /* dip settings, port mode Jumpers */
4825 int i;
4809 4826
4810 if (HFC_cnt >= MAX_CARDS) { 4827 if (HFC_cnt >= MAX_CARDS) {
4811 printk(KERN_ERR "too many cards (max=%d).\n", 4828 printk(KERN_ERR "too many cards (max=%d).\n",
@@ -4839,11 +4856,11 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
4839 hc->id = HFC_cnt; 4856 hc->id = HFC_cnt;
4840 hc->pcm = pcm[HFC_cnt]; 4857 hc->pcm = pcm[HFC_cnt];
4841 hc->io_mode = iomode[HFC_cnt]; 4858 hc->io_mode = iomode[HFC_cnt];
4842 if (dslot[HFC_cnt] < 0) { 4859 if (dslot[HFC_cnt] < 0 && hc->type == 1) {
4843 hc->dslot = 0; 4860 hc->dslot = 0;
4844 printk(KERN_INFO "HFC-E1 card has disabled D-channel, but " 4861 printk(KERN_INFO "HFC-E1 card has disabled D-channel, but "
4845 "31 B-channels\n"); 4862 "31 B-channels\n");
4846 } if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32) { 4863 } if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32 && hc->type == 1) {
4847 hc->dslot = dslot[HFC_cnt]; 4864 hc->dslot = dslot[HFC_cnt];
4848 printk(KERN_INFO "HFC-E1 card has alternating D-channel on " 4865 printk(KERN_INFO "HFC-E1 card has alternating D-channel on "
4849 "time slot %d\n", dslot[HFC_cnt]); 4866 "time slot %d\n", dslot[HFC_cnt]);
@@ -4854,9 +4871,17 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
4854 hc->masterclk = -1; 4871 hc->masterclk = -1;
4855 if (type[HFC_cnt] & 0x100) { 4872 if (type[HFC_cnt] & 0x100) {
4856 test_and_set_bit(HFC_CHIP_ULAW, &hc->chip); 4873 test_and_set_bit(HFC_CHIP_ULAW, &hc->chip);
4857 silence = 0xff; /* ulaw silence */ 4874 hc->silence = 0xff; /* ulaw silence */
4858 } else 4875 } else
4859 silence = 0x2a; /* alaw silence */ 4876 hc->silence = 0x2a; /* alaw silence */
4877 if ((poll >> 1) > sizeof(hc->silence_data)) {
4878 printk(KERN_ERR "HFCMULTI error: silence_data too small, "
4879 "please fix\n");
4880 return -EINVAL;
4881 }
4882 for (i = 0; i < (poll >> 1); i++)
4883 hc->silence_data[i] = hc->silence;
4884
4860 if (!(type[HFC_cnt] & 0x200)) 4885 if (!(type[HFC_cnt] & 0x200))
4861 test_and_set_bit(HFC_CHIP_DTMF, &hc->chip); 4886 test_and_set_bit(HFC_CHIP_DTMF, &hc->chip);
4862 4887
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index cd8302af40eb..80c356e5dbe1 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
754next_t_frame: 784next_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)
1481static int 1511static int
1482channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) 1512channel_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))