aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAndreas Eversberg <andreas@eversberg.eu>2009-05-22 07:04:49 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-25 03:51:34 -0400
commitbc138ec4ac58bb83e2d9d5c12328d5452294c1f0 (patch)
tree059a02dfee5e813bdf21131aaa7c15085dd7f768 /drivers
parentb5df5a5c3bf0f809d854ad7156ce26b709b533c0 (diff)
mISDN: Hardware acceleration is now possible in conjunction with audio recording
Audio recording requires software audio processing. Both hardware and software processing is simultaniously possible now. Signed-off-by: Andreas Eversberg <andreas@eversberg.eu> Signed-off-by: Karsten Keil <keil@b1-systems.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/isdn/mISDN/dsp.h11
-rw-r--r--drivers/isdn/mISDN/dsp_cmx.c101
-rw-r--r--drivers/isdn/mISDN/dsp_core.c17
3 files changed, 84 insertions, 45 deletions
diff --git a/drivers/isdn/mISDN/dsp.h b/drivers/isdn/mISDN/dsp.h
index 41c6cfdca8c8..564ea3efd5e3 100644
--- a/drivers/isdn/mISDN/dsp.h
+++ b/drivers/isdn/mISDN/dsp.h
@@ -151,6 +151,15 @@ struct dsp_tone {
151 struct timer_list tl; 151 struct timer_list tl;
152}; 152};
153 153
154/***************
155 * echo stuff *
156 ***************/
157
158struct dsp_echo {
159 int software; /* echo is generated by software */
160 int hardware; /* echo is generated by hardware */
161};
162
154/***************** 163/*****************
155 * general stuff * 164 * general stuff *
156 *****************/ 165 *****************/
@@ -161,7 +170,7 @@ struct dsp {
161 struct mISDNchannel *up; 170 struct mISDNchannel *up;
162 unsigned char name[64]; 171 unsigned char name[64];
163 int b_active; 172 int b_active;
164 int echo; /* echo is enabled */ 173 struct dsp_echo echo;
165 int rx_disabled; /* what the user wants */ 174 int rx_disabled; /* what the user wants */
166 int rx_is_off; /* what the card is */ 175 int rx_is_off; /* what the card is */
167 int tx_mix; 176 int tx_mix;
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c
index ac84146326e2..d19b4f6d7d87 100644
--- a/drivers/isdn/mISDN/dsp_cmx.c
+++ b/drivers/isdn/mISDN/dsp_cmx.c
@@ -163,8 +163,9 @@ dsp_cmx_debug(struct dsp *dsp)
163 163
164 printk(KERN_DEBUG "-----Current DSP\n"); 164 printk(KERN_DEBUG "-----Current DSP\n");
165 list_for_each_entry(odsp, &dsp_ilist, list) { 165 list_for_each_entry(odsp, &dsp_ilist, list) {
166 printk(KERN_DEBUG "* %s echo=%d txmix=%d", 166 printk(KERN_DEBUG "* %s hardecho=%d softecho=%d txmix=%d",
167 odsp->name, odsp->echo, odsp->tx_mix); 167 odsp->name, odsp->echo.hardware, odsp->echo.software,
168 odsp->tx_mix);
168 if (odsp->conf) 169 if (odsp->conf)
169 printk(" (Conf %d)", odsp->conf->id); 170 printk(" (Conf %d)", odsp->conf->id);
170 if (dsp == odsp) 171 if (dsp == odsp)
@@ -177,10 +178,12 @@ dsp_cmx_debug(struct dsp *dsp)
177 list_for_each_entry(member, &conf->mlist, list) { 178 list_for_each_entry(member, &conf->mlist, list) {
178 printk(KERN_DEBUG 179 printk(KERN_DEBUG
179 " - member = %s (slot_tx %d, bank_tx %d, " 180 " - member = %s (slot_tx %d, bank_tx %d, "
180 "slot_rx %d, bank_rx %d hfc_conf %d)%s\n", 181 "slot_rx %d, bank_rx %d hfc_conf %d "
182 "tx_data %d rx_is_off %d)%s\n",
181 member->dsp->name, member->dsp->pcm_slot_tx, 183 member->dsp->name, member->dsp->pcm_slot_tx,
182 member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx, 184 member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx,
183 member->dsp->pcm_bank_rx, member->dsp->hfc_conf, 185 member->dsp->pcm_bank_rx, member->dsp->hfc_conf,
186 member->dsp->tx_data, member->dsp->rx_is_off,
184 (member->dsp == dsp) ? " *this*" : ""); 187 (member->dsp == dsp) ? " *this*" : "");
185 } 188 }
186 } 189 }
@@ -385,7 +388,7 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp)
385 int freeunits[8]; 388 int freeunits[8];
386 u_char freeslots[256]; 389 u_char freeslots[256];
387 int same_hfc = -1, same_pcm = -1, current_conf = -1, 390 int same_hfc = -1, same_pcm = -1, current_conf = -1,
388 all_conf = 1; 391 all_conf = 1, tx_data = 0;
389 392
390 /* dsp gets updated (no conf) */ 393 /* dsp gets updated (no conf) */
391 if (!conf) { 394 if (!conf) {
@@ -409,7 +412,7 @@ one_member:
409 /* process hw echo */ 412 /* process hw echo */
410 if (dsp->features.pcm_banks < 1) 413 if (dsp->features.pcm_banks < 1)
411 return; 414 return;
412 if (!dsp->echo) { 415 if (!dsp->echo.software && !dsp->echo.hardware) {
413 /* NO ECHO: remove PCM slot if assigned */ 416 /* NO ECHO: remove PCM slot if assigned */
414 if (dsp->pcm_slot_tx >= 0 || dsp->pcm_slot_rx >= 0) { 417 if (dsp->pcm_slot_tx >= 0 || dsp->pcm_slot_rx >= 0) {
415 if (dsp_debug & DEBUG_DSP_CMX) 418 if (dsp_debug & DEBUG_DSP_CMX)
@@ -427,10 +430,15 @@ one_member:
427 } 430 }
428 return; 431 return;
429 } 432 }
433 /* echo is enabled, find out if we use soft or hardware */
434 dsp->echo.software = dsp->tx_data;
435 dsp->echo.hardware = 0;
430 /* ECHO: already echo */ 436 /* ECHO: already echo */
431 if (dsp->pcm_slot_tx >= 0 && dsp->pcm_slot_rx < 0 && 437 if (dsp->pcm_slot_tx >= 0 && dsp->pcm_slot_rx < 0 &&
432 dsp->pcm_bank_tx == 2 && dsp->pcm_bank_rx == 2) 438 dsp->pcm_bank_tx == 2 && dsp->pcm_bank_rx == 2) {
439 dsp->echo.hardware = 1;
433 return; 440 return;
441 }
434 /* ECHO: if slot already assigned */ 442 /* ECHO: if slot already assigned */
435 if (dsp->pcm_slot_tx >= 0) { 443 if (dsp->pcm_slot_tx >= 0) {
436 dsp->pcm_slot_rx = dsp->pcm_slot_tx; 444 dsp->pcm_slot_rx = dsp->pcm_slot_tx;
@@ -443,6 +451,7 @@ one_member:
443 dsp->pcm_slot_tx); 451 dsp->pcm_slot_tx);
444 dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN, 452 dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN,
445 dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2); 453 dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
454 dsp->echo.hardware = 1;
446 return; 455 return;
447 } 456 }
448 /* ECHO: find slot */ 457 /* ECHO: find slot */
@@ -472,6 +481,7 @@ one_member:
472 "%s no slot available for echo\n", 481 "%s no slot available for echo\n",
473 __func__); 482 __func__);
474 /* no more slots available */ 483 /* no more slots available */
484 dsp->echo.software = 1;
475 return; 485 return;
476 } 486 }
477 /* assign free slot */ 487 /* assign free slot */
@@ -485,6 +495,7 @@ one_member:
485 __func__, dsp->name, dsp->pcm_slot_tx); 495 __func__, dsp->name, dsp->pcm_slot_tx);
486 dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN, 496 dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN,
487 dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2); 497 dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
498 dsp->echo.hardware = 1;
488 return; 499 return;
489 } 500 }
490 501
@@ -554,7 +565,7 @@ conf_software:
554 return; 565 return;
555 } 566 }
556 /* check if member has echo turned on */ 567 /* check if member has echo turned on */
557 if (member->dsp->echo) { 568 if (member->dsp->echo.hardware || member->dsp->echo.software) {
558 if (dsp_debug & DEBUG_DSP_CMX) 569 if (dsp_debug & DEBUG_DSP_CMX)
559 printk(KERN_DEBUG 570 printk(KERN_DEBUG
560 "%s dsp %s cannot form a conf, because " 571 "%s dsp %s cannot form a conf, because "
@@ -592,10 +603,9 @@ conf_software:
592 if (member->dsp->tx_data) { 603 if (member->dsp->tx_data) {
593 if (dsp_debug & DEBUG_DSP_CMX) 604 if (dsp_debug & DEBUG_DSP_CMX)
594 printk(KERN_DEBUG 605 printk(KERN_DEBUG
595 "%s dsp %s cannot form a conf, because " 606 "%s dsp %s tx_data is turned on\n",
596 "tx_data is turned on\n",
597 __func__, member->dsp->name); 607 __func__, member->dsp->name);
598 goto conf_software; 608 tx_data = 1;
599 } 609 }
600 /* check if pipeline exists */ 610 /* check if pipeline exists */
601 if (member->dsp->pipeline.inuse) { 611 if (member->dsp->pipeline.inuse) {
@@ -794,7 +804,7 @@ conf_software:
794 nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx, 804 nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
795 nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx); 805 nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
796 conf->hardware = 1; 806 conf->hardware = 1;
797 conf->software = 0; 807 conf->software = tx_data;
798 return; 808 return;
799 /* if members have one bank (or on the same chip) */ 809 /* if members have one bank (or on the same chip) */
800 } else { 810 } else {
@@ -904,7 +914,7 @@ conf_software:
904 nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx, 914 nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
905 nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx); 915 nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
906 conf->hardware = 1; 916 conf->hardware = 1;
907 conf->software = 0; 917 conf->software = tx_data;
908 return; 918 return;
909 } 919 }
910 } 920 }
@@ -1295,17 +1305,25 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
1295 int r, rr, t, tt, o_r, o_rr; 1305 int r, rr, t, tt, o_r, o_rr;
1296 int preload = 0; 1306 int preload = 0;
1297 struct mISDNhead *hh, *thh; 1307 struct mISDNhead *hh, *thh;
1308 int tx_data_only = 0;
1298 1309
1299 /* don't process if: */ 1310 /* don't process if: */
1300 if (!dsp->b_active) { /* if not active */ 1311 if (!dsp->b_active) { /* if not active */
1301 dsp->last_tx = 0; 1312 dsp->last_tx = 0;
1302 return; 1313 return;
1303 } 1314 }
1304 if (dsp->pcm_slot_tx >= 0 && /* connected to pcm slot */ 1315 if (((dsp->conf && dsp->conf->hardware) || /* hardware conf */
1316 dsp->echo.hardware) && /* OR hardware echo */
1305 dsp->tx_R == dsp->tx_W && /* AND no tx-data */ 1317 dsp->tx_R == dsp->tx_W && /* AND no tx-data */
1306 !(dsp->tone.tone && dsp->tone.software)) { /* AND not soft tones */ 1318 !(dsp->tone.tone && dsp->tone.software)) { /* AND not soft tones */
1307 dsp->last_tx = 0; 1319 if (!dsp->tx_data) { /* no tx_data for user space required */
1308 return; 1320 dsp->last_tx = 0;
1321 return;
1322 }
1323 if (dsp->conf && dsp->conf->software && dsp->conf->hardware)
1324 tx_data_only = 1;
1325 if (dsp->conf->software && dsp->echo.hardware)
1326 tx_data_only = 1;
1309 } 1327 }
1310 1328
1311#ifdef CMX_DEBUG 1329#ifdef CMX_DEBUG
@@ -1388,7 +1406,7 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
1388 /* PROCESS DATA (one member / no conf) */ 1406 /* PROCESS DATA (one member / no conf) */
1389 if (!conf || members <= 1) { 1407 if (!conf || members <= 1) {
1390 /* -> if echo is NOT enabled */ 1408 /* -> if echo is NOT enabled */
1391 if (!dsp->echo) { 1409 if (!dsp->echo.software) {
1392 /* -> send tx-data if available or use 0-volume */ 1410 /* -> send tx-data if available or use 0-volume */
1393 while (r != rr && t != tt) { 1411 while (r != rr && t != tt) {
1394 *d++ = p[t]; /* write tx_buff */ 1412 *d++ = p[t]; /* write tx_buff */
@@ -1438,7 +1456,7 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
1438 o_r = (o_rr - rr + r) & CMX_BUFF_MASK; 1456 o_r = (o_rr - rr + r) & CMX_BUFF_MASK;
1439 /* start rx-pointer at current read position*/ 1457 /* start rx-pointer at current read position*/
1440 /* -> if echo is NOT enabled */ 1458 /* -> if echo is NOT enabled */
1441 if (!dsp->echo) { 1459 if (!dsp->echo.software) {
1442 /* 1460 /*
1443 * -> copy other member's rx-data, 1461 * -> copy other member's rx-data,
1444 * if tx-data is available, mix 1462 * if tx-data is available, mix
@@ -1486,7 +1504,7 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
1486#endif 1504#endif
1487 /* PROCESS DATA (three or more members) */ 1505 /* PROCESS DATA (three or more members) */
1488 /* -> if echo is NOT enabled */ 1506 /* -> if echo is NOT enabled */
1489 if (!dsp->echo) { 1507 if (!dsp->echo.software) {
1490 /* 1508 /*
1491 * -> substract rx-data from conf-data, 1509 * -> substract rx-data from conf-data,
1492 * if tx-data is available, mix 1510 * if tx-data is available, mix
@@ -1550,27 +1568,40 @@ send_packet:
1550 * becuase we want what we send, not what we filtered 1568 * becuase we want what we send, not what we filtered
1551 */ 1569 */
1552 if (dsp->tx_data) { 1570 if (dsp->tx_data) {
1553 /* PREPARE RESULT */ 1571 if (tx_data_only) {
1554 txskb = mI_alloc_skb(len, GFP_ATOMIC); 1572 hh->prim = DL_DATA_REQ;
1555 if (!txskb) { 1573 hh->id = 0;
1556 printk(KERN_ERR 1574 /* queue and trigger */
1557 "FATAL ERROR in mISDN_dsp.o: " 1575 skb_queue_tail(&dsp->sendq, nskb);
1558 "cannot alloc %d bytes\n", len); 1576 schedule_work(&dsp->workq);
1577 /* exit because only tx_data is used */
1578 return;
1559 } else { 1579 } else {
1560 thh = mISDN_HEAD_P(txskb); 1580 txskb = mI_alloc_skb(len, GFP_ATOMIC);
1561 thh->prim = DL_DATA_REQ; 1581 if (!txskb) {
1562 thh->id = 0; 1582 printk(KERN_ERR
1563 memcpy(skb_put(txskb, len), nskb->data+preload, len); 1583 "FATAL ERROR in mISDN_dsp.o: "
1564 /* queue (trigger later) */ 1584 "cannot alloc %d bytes\n", len);
1565 skb_queue_tail(&dsp->sendq, txskb); 1585 } else {
1586 thh = mISDN_HEAD_P(txskb);
1587 thh->prim = DL_DATA_REQ;
1588 thh->id = 0;
1589 memcpy(skb_put(txskb, len), nskb->data+preload,
1590 len);
1591 /* queue (trigger later) */
1592 skb_queue_tail(&dsp->sendq, txskb);
1593 }
1566 } 1594 }
1567 } 1595 }
1596
1597 /* send data only to card, if we don't just calculated tx_data */
1568 /* adjust volume */ 1598 /* adjust volume */
1569 if (dsp->tx_volume) 1599 if (dsp->tx_volume)
1570 dsp_change_volume(nskb, dsp->tx_volume); 1600 dsp_change_volume(nskb, dsp->tx_volume);
1571 /* pipeline */ 1601 /* pipeline */
1572 if (dsp->pipeline.inuse) 1602 if (dsp->pipeline.inuse)
1573 dsp_pipeline_process_tx(&dsp->pipeline, nskb->data, nskb->len); 1603 dsp_pipeline_process_tx(&dsp->pipeline, nskb->data,
1604 nskb->len);
1574 /* crypt */ 1605 /* crypt */
1575 if (dsp->bf_enable) 1606 if (dsp->bf_enable)
1576 dsp_bf_encrypt(dsp, nskb->data, nskb->len); 1607 dsp_bf_encrypt(dsp, nskb->data, nskb->len);
@@ -1891,10 +1922,8 @@ dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb)
1891 1922
1892 /* no conf */ 1923 /* no conf */
1893 if (!dsp->conf) { 1924 if (!dsp->conf) {
1894 /* in case of hardware (echo) */ 1925 /* in case of software echo */
1895 if (dsp->pcm_slot_tx >= 0) 1926 if (dsp->echo.software) {
1896 return;
1897 if (dsp->echo) {
1898 nskb = skb_clone(skb, GFP_ATOMIC); 1927 nskb = skb_clone(skb, GFP_ATOMIC);
1899 if (nskb) { 1928 if (nskb) {
1900 hh = mISDN_HEAD_P(nskb); 1929 hh = mISDN_HEAD_P(nskb);
@@ -1910,7 +1939,7 @@ dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb)
1910 if (dsp->conf->hardware) 1939 if (dsp->conf->hardware)
1911 return; 1940 return;
1912 list_for_each_entry(member, &dsp->conf->mlist, list) { 1941 list_for_each_entry(member, &dsp->conf->mlist, list) {
1913 if (dsp->echo || member->dsp != dsp) { 1942 if (dsp->echo.software || member->dsp != dsp) {
1914 nskb = skb_clone(skb, GFP_ATOMIC); 1943 nskb = skb_clone(skb, GFP_ATOMIC);
1915 if (nskb) { 1944 if (nskb) {
1916 hh = mISDN_HEAD_P(nskb); 1945 hh = mISDN_HEAD_P(nskb);
diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c
index 6b4939854306..a0e0af81eb2e 100644
--- a/drivers/isdn/mISDN/dsp_core.c
+++ b/drivers/isdn/mISDN/dsp_core.c
@@ -203,13 +203,13 @@ dsp_rx_off_member(struct dsp *dsp)
203 else if (dsp->dtmf.software) 203 else if (dsp->dtmf.software)
204 rx_off = 0; 204 rx_off = 0;
205 /* echo in software */ 205 /* echo in software */
206 else if (dsp->echo && dsp->pcm_slot_tx < 0) 206 else if (dsp->echo.software)
207 rx_off = 0; 207 rx_off = 0;
208 /* bridge in software */ 208 /* bridge in software */
209 else if (dsp->conf) { 209 else if (dsp->conf && dsp->conf->software)
210 if (dsp->conf->software) 210 rx_off = 0;
211 rx_off = 0; 211 /* data is not required by user space and not required
212 } 212 * for echo dtmf detection, soft-echo, soft-bridging */
213 213
214 if (rx_off == dsp->rx_is_off) 214 if (rx_off == dsp->rx_is_off)
215 return; 215 return;
@@ -415,7 +415,7 @@ tone_off:
415 dsp_rx_off(dsp); 415 dsp_rx_off(dsp);
416 break; 416 break;
417 case DSP_ECHO_ON: /* enable echo */ 417 case DSP_ECHO_ON: /* enable echo */
418 dsp->echo = 1; /* soft echo */ 418 dsp->echo.software = 1; /* soft echo */
419 if (dsp_debug & DEBUG_DSP_CORE) 419 if (dsp_debug & DEBUG_DSP_CORE)
420 printk(KERN_DEBUG "%s: enable cmx-echo\n", __func__); 420 printk(KERN_DEBUG "%s: enable cmx-echo\n", __func__);
421 dsp_cmx_hardware(dsp->conf, dsp); 421 dsp_cmx_hardware(dsp->conf, dsp);
@@ -424,7 +424,8 @@ tone_off:
424 dsp_cmx_debug(dsp); 424 dsp_cmx_debug(dsp);
425 break; 425 break;
426 case DSP_ECHO_OFF: /* disable echo */ 426 case DSP_ECHO_OFF: /* disable echo */
427 dsp->echo = 0; 427 dsp->echo.software = 0;
428 dsp->echo.hardware = 0;
428 if (dsp_debug & DEBUG_DSP_CORE) 429 if (dsp_debug & DEBUG_DSP_CORE)
429 printk(KERN_DEBUG "%s: disable cmx-echo\n", __func__); 430 printk(KERN_DEBUG "%s: disable cmx-echo\n", __func__);
430 dsp_cmx_hardware(dsp->conf, dsp); 431 dsp_cmx_hardware(dsp->conf, dsp);
@@ -722,7 +723,7 @@ dsp_function(struct mISDNchannel *ch, struct sk_buff *skb)
722 skb->len, (dsp_options&DSP_OPT_ULAW)?1:0); 723 skb->len, (dsp_options&DSP_OPT_ULAW)?1:0);
723 } 724 }
724 /* we need to process receive data if software */ 725 /* we need to process receive data if software */
725 if (dsp->pcm_slot_tx < 0 && dsp->pcm_slot_rx < 0) { 726 if (dsp->conf && dsp->conf->software) {
726 /* process data from card at cmx */ 727 /* process data from card at cmx */
727 dsp_cmx_receive(dsp, skb); 728 dsp_cmx_receive(dsp, skb);
728 } 729 }