Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc138ec4 authored by Andreas Eversberg's avatar Andreas Eversberg Committed by David S. Miller
Browse files

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: default avatarAndreas Eversberg <andreas@eversberg.eu>
Signed-off-by: default avatarKarsten Keil <keil@b1-systems.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b5df5a5c
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -151,6 +151,15 @@ struct dsp_tone {
	struct timer_list tl;
};

/***************
 * echo stuff *
 ***************/

struct dsp_echo {
	int		software; /* echo is generated by software */
	int		hardware; /* echo is generated by hardware */
};

/*****************
 * general stuff *
 *****************/
@@ -161,7 +170,7 @@ struct dsp {
	struct mISDNchannel	*up;
	unsigned char	name[64];
	int		b_active;
	int		echo; /* echo is enabled */
	struct dsp_echo	echo;
	int		rx_disabled; /* what the user wants */
	int		rx_is_off; /* what the card is */
	int		tx_mix;
+65 −36
Original line number Diff line number Diff line
@@ -163,8 +163,9 @@ dsp_cmx_debug(struct dsp *dsp)

	printk(KERN_DEBUG "-----Current DSP\n");
	list_for_each_entry(odsp, &dsp_ilist, list) {
		printk(KERN_DEBUG "* %s echo=%d txmix=%d",
		    odsp->name, odsp->echo, odsp->tx_mix);
		printk(KERN_DEBUG "* %s hardecho=%d softecho=%d txmix=%d",
		    odsp->name, odsp->echo.hardware, odsp->echo.software,
		    odsp->tx_mix);
		if (odsp->conf)
			printk(" (Conf %d)", odsp->conf->id);
		if (dsp == odsp)
@@ -177,10 +178,12 @@ dsp_cmx_debug(struct dsp *dsp)
		list_for_each_entry(member, &conf->mlist, list) {
			printk(KERN_DEBUG
			    "  - member = %s (slot_tx %d, bank_tx %d, "
			    "slot_rx %d, bank_rx %d hfc_conf %d)%s\n",
			    "slot_rx %d, bank_rx %d hfc_conf %d "
			    "tx_data %d rx_is_off %d)%s\n",
			    member->dsp->name, member->dsp->pcm_slot_tx,
			    member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx,
			    member->dsp->pcm_bank_rx, member->dsp->hfc_conf,
			    member->dsp->tx_data, member->dsp->rx_is_off,
			    (member->dsp == dsp) ? " *this*" : "");
		}
	}
@@ -385,7 +388,7 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp)
	int		freeunits[8];
	u_char		freeslots[256];
	int		same_hfc = -1, same_pcm = -1, current_conf = -1,
	    all_conf = 1;
	    all_conf = 1, tx_data = 0;

	/* dsp gets updated (no conf) */
	if (!conf) {
@@ -409,7 +412,7 @@ one_member:
		/* process hw echo */
		if (dsp->features.pcm_banks < 1)
			return;
		if (!dsp->echo) {
		if (!dsp->echo.software && !dsp->echo.hardware) {
			/* NO ECHO: remove PCM slot if assigned */
			if (dsp->pcm_slot_tx >= 0 || dsp->pcm_slot_rx >= 0) {
				if (dsp_debug & DEBUG_DSP_CMX)
@@ -427,10 +430,15 @@ one_member:
			}
			return;
		}
		/* echo is enabled, find out if we use soft or hardware */
		dsp->echo.software = dsp->tx_data;
		dsp->echo.hardware = 0;
		/* ECHO: already echo */
		if (dsp->pcm_slot_tx >= 0 && dsp->pcm_slot_rx < 0 &&
		    dsp->pcm_bank_tx == 2 && dsp->pcm_bank_rx == 2)
		    dsp->pcm_bank_tx == 2 && dsp->pcm_bank_rx == 2) {
			dsp->echo.hardware = 1;
			return;
		}
		/* ECHO: if slot already assigned */
		if (dsp->pcm_slot_tx >= 0) {
			dsp->pcm_slot_rx = dsp->pcm_slot_tx;
@@ -443,6 +451,7 @@ one_member:
				    dsp->pcm_slot_tx);
			dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN,
			    dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
			dsp->echo.hardware = 1;
			return;
		}
		/* ECHO: find slot */
@@ -472,6 +481,7 @@ one_member:
				    "%s no slot available for echo\n",
				    __func__);
			/* no more slots available */
			dsp->echo.software = 1;
			return;
		}
		/* assign free slot */
@@ -485,6 +495,7 @@ one_member:
			    __func__, dsp->name, dsp->pcm_slot_tx);
		dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN,
		    dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
		dsp->echo.hardware = 1;
		return;
	}

@@ -554,7 +565,7 @@ conf_software:
			return;
		}
		/* check if member has echo turned on */
		if (member->dsp->echo) {
		if (member->dsp->echo.hardware || member->dsp->echo.software) {
			if (dsp_debug & DEBUG_DSP_CMX)
				printk(KERN_DEBUG
				    "%s dsp %s cannot form a conf, because "
@@ -592,10 +603,9 @@ conf_software:
		if (member->dsp->tx_data) {
			if (dsp_debug & DEBUG_DSP_CMX)
				printk(KERN_DEBUG
				    "%s dsp %s cannot form a conf, because "
				    "tx_data is turned on\n",
				    "%s dsp %s tx_data is turned on\n",
				    __func__, member->dsp->name);
			goto conf_software;
			tx_data = 1;
		}
		/* check if pipeline exists */
		if (member->dsp->pipeline.inuse) {
@@ -794,7 +804,7 @@ conf_software:
			    nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
			    nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
			conf->hardware = 1;
			conf->software = 0;
			conf->software = tx_data;
			return;
		/* if members have one bank (or on the same chip) */
		} else {
@@ -904,7 +914,7 @@ conf_software:
			    nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
			    nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
			conf->hardware = 1;
			conf->software = 0;
			conf->software = tx_data;
			return;
		}
	}
@@ -1295,18 +1305,26 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
	int r, rr, t, tt, o_r, o_rr;
	int preload = 0;
	struct mISDNhead *hh, *thh;
	int tx_data_only = 0;

	/* don't process if: */
	if (!dsp->b_active) { /* if not active */
		dsp->last_tx = 0;
		return;
	}
	if (dsp->pcm_slot_tx >= 0 && /* connected to pcm slot */
	if (((dsp->conf && dsp->conf->hardware) || /* hardware conf */
	    dsp->echo.hardware) && /* OR hardware echo */
	    dsp->tx_R == dsp->tx_W && /* AND no tx-data */
	    !(dsp->tone.tone && dsp->tone.software)) { /* AND not soft tones */
		if (!dsp->tx_data) { /* no tx_data for user space required */
			dsp->last_tx = 0;
			return;
		}
		if (dsp->conf && dsp->conf->software && dsp->conf->hardware)
			tx_data_only = 1;
		if (dsp->conf->software && dsp->echo.hardware)
			tx_data_only = 1;
	}

#ifdef CMX_DEBUG
	printk(KERN_DEBUG
@@ -1388,7 +1406,7 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
	/* PROCESS DATA (one member / no conf) */
	if (!conf || members <= 1) {
		/* -> if echo is NOT enabled */
		if (!dsp->echo) {
		if (!dsp->echo.software) {
			/* -> send tx-data if available or use 0-volume */
			while (r != rr && t != tt) {
				*d++ = p[t]; /* write tx_buff */
@@ -1438,7 +1456,7 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
		o_r = (o_rr - rr + r) & CMX_BUFF_MASK;
			/* start rx-pointer at current read position*/
		/* -> if echo is NOT enabled */
		if (!dsp->echo) {
		if (!dsp->echo.software) {
			/*
			 * -> copy other member's rx-data,
			 * if tx-data is available, mix
@@ -1486,7 +1504,7 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
#endif
	/* PROCESS DATA (three or more members) */
	/* -> if echo is NOT enabled */
	if (!dsp->echo) {
	if (!dsp->echo.software) {
		/*
		 * -> substract rx-data from conf-data,
		 * if tx-data is available, mix
@@ -1550,7 +1568,15 @@ send_packet:
	 * becuase we want what we send, not what we filtered
	 */
	if (dsp->tx_data) {
		/* PREPARE RESULT */
		if (tx_data_only) {
			hh->prim = DL_DATA_REQ;
			hh->id = 0;
			/* queue and trigger */
			skb_queue_tail(&dsp->sendq, nskb);
			schedule_work(&dsp->workq);
			/* exit because only tx_data is used */
			return;
		} else {
			txskb = mI_alloc_skb(len, GFP_ATOMIC);
			if (!txskb) {
				printk(KERN_ERR
@@ -1560,17 +1586,22 @@ send_packet:
				thh = mISDN_HEAD_P(txskb);
				thh->prim = DL_DATA_REQ;
				thh->id = 0;
			memcpy(skb_put(txskb, len), nskb->data+preload, len);
				memcpy(skb_put(txskb, len), nskb->data+preload,
					len);
				/* queue (trigger later) */
				skb_queue_tail(&dsp->sendq, txskb);
			}
		}
	}

	/* send data only to card, if we don't just calculated tx_data */
	/* adjust volume */
	if (dsp->tx_volume)
		dsp_change_volume(nskb, dsp->tx_volume);
	/* pipeline */
	if (dsp->pipeline.inuse)
		dsp_pipeline_process_tx(&dsp->pipeline, nskb->data, nskb->len);
		dsp_pipeline_process_tx(&dsp->pipeline, nskb->data,
			nskb->len);
	/* crypt */
	if (dsp->bf_enable)
		dsp_bf_encrypt(dsp, nskb->data, nskb->len);
@@ -1891,10 +1922,8 @@ dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb)

	/* no conf */
	if (!dsp->conf) {
		/* in case of hardware (echo) */
		if (dsp->pcm_slot_tx >= 0)
			return;
		if (dsp->echo) {
		/* in case of software echo */
		if (dsp->echo.software) {
			nskb = skb_clone(skb, GFP_ATOMIC);
			if (nskb) {
				hh = mISDN_HEAD_P(nskb);
@@ -1910,7 +1939,7 @@ dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb)
	if (dsp->conf->hardware)
		return;
	list_for_each_entry(member, &dsp->conf->mlist, list) {
		if (dsp->echo || member->dsp != dsp) {
		if (dsp->echo.software || member->dsp != dsp) {
			nskb = skb_clone(skb, GFP_ATOMIC);
			if (nskb) {
				hh = mISDN_HEAD_P(nskb);
+9 −8
Original line number Diff line number Diff line
@@ -203,13 +203,13 @@ dsp_rx_off_member(struct dsp *dsp)
	else if (dsp->dtmf.software)
		rx_off = 0;
	/* echo in software */
	else if (dsp->echo && dsp->pcm_slot_tx < 0)
	else if (dsp->echo.software)
		rx_off = 0;
	/* bridge in software */
	else if (dsp->conf) {
		if (dsp->conf->software)
	else if (dsp->conf && dsp->conf->software)
		rx_off = 0;
	}
	/* data is not required by user space and not required
	 * for echo dtmf detection, soft-echo, soft-bridging */

	if (rx_off == dsp->rx_is_off)
		return;
@@ -415,7 +415,7 @@ tone_off:
		dsp_rx_off(dsp);
		break;
	case DSP_ECHO_ON: /* enable echo */
		dsp->echo = 1; /* soft echo */
		dsp->echo.software = 1; /* soft echo */
		if (dsp_debug & DEBUG_DSP_CORE)
			printk(KERN_DEBUG "%s: enable cmx-echo\n", __func__);
		dsp_cmx_hardware(dsp->conf, dsp);
@@ -424,7 +424,8 @@ tone_off:
			dsp_cmx_debug(dsp);
		break;
	case DSP_ECHO_OFF: /* disable echo */
		dsp->echo = 0;
		dsp->echo.software = 0;
		dsp->echo.hardware = 0;
		if (dsp_debug & DEBUG_DSP_CORE)
			printk(KERN_DEBUG "%s: disable cmx-echo\n", __func__);
		dsp_cmx_hardware(dsp->conf, dsp);
@@ -722,7 +723,7 @@ dsp_function(struct mISDNchannel *ch, struct sk_buff *skb)
				skb->len, (dsp_options&DSP_OPT_ULAW)?1:0);
		}
		/* we need to process receive data if software */
		if (dsp->pcm_slot_tx < 0 && dsp->pcm_slot_rx < 0) {
		if (dsp->conf && dsp->conf->software) {
			/* process data from card at cmx */
			dsp_cmx_receive(dsp, skb);
		}