Пример #1
0
static int saudio_send_common_cmd(uint32_t dst, uint32_t channel,
				      uint32_t cmd, uint32_t subcmd,int32_t timeout)
{
	int result = 0;
	struct sblock blk = { 0 };
	ADEBUG();
	pr_debug(" dst is %d, channel %d, cmd %x, subcmd %x\n", dst, channel,
		 cmd, subcmd);
	result = sblock_get(dst, channel, (struct sblock *)&blk, timeout);
	if (result >= 0) {
		struct cmd_common *common = (struct cmd_common *)blk.addr;
		int retry = 0;

		common->command = cmd;
		common->sub_cmd = subcmd;
		blk.length = sizeof(struct cmd_common);
		pr_debug(" dst is %d, channel %d, cmd %x, subcmd %x send ok\n",
			 dst, channel, cmd, subcmd);
		while ((result = sblock_send(dst, channel, (struct sblock *)&blk)) == -EBUSY) {
			if (retry++ < 20*1000)
				udelay(100); 
			else {
				printk(KERN_WARNING "%s retry %d timeout\n", __func__, retry);
				break;
			}
		}
	}

	return result;
}
Пример #2
0
static int saudio_data_trigger_process(struct saudio_stream *stream,
					   struct saudio_msg *msg)
{
	int32_t result = 0;
	struct sblock blk = { 0 };
	struct cmd_common *common = NULL;
	struct snd_pcm_runtime *runtime = stream->substream->runtime;
	ADEBUG();

	if (stream->stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
		stream->periods_avail = snd_pcm_playback_avail(runtime) /
		    runtime->period_size;
	} else {
		stream->periods_avail = snd_pcm_capture_avail(runtime) /
		    runtime->period_size;
	}

	pr_debug("saudio.c:stream->periods_avail is %d,block count is %d",
		 stream->periods_avail, sblock_get_free_count(stream->dst,
							      stream->channel));

	stream->periods_tosend = runtime->periods - stream->periods_avail;

	ADEBUG();

	while (stream->periods_tosend) {

		result = sblock_get(stream->dst, stream->channel, &blk, 0);
		if (result) {
			break;
		}
		stream->last_getblk_count++;
		common = (struct cmd_common *)blk.addr;
		blk.length = frames_to_bytes(runtime, runtime->period_size);
		common->command = SAUDIO_DATA_PCM;
		common->sub_cmd = stream->stream_id;
		common->reserved1 =
		    stream->substream->dma_buffer.addr +
		    stream->period * blk.length;

		sblock_send(stream->dst, stream->channel, &blk);

		stream->period++;
		stream->period = stream->period % runtime->periods;
		stream->periods_tosend--;
	}

	pr_debug(":sblock_getblock_count trigger is %d \n",
		 stream->last_getblk_count);

	return result;
}
Пример #3
0
static int saudio_cmd_prepare_process(struct saudio_dev_ctrl *dev_ctrl,
				      struct saudio_msg *msg)
{
	struct sblock blk;
	struct snd_saudio *saudio=NULL;
	int32_t result = 0;
	struct snd_pcm_runtime *runtime =
	    dev_ctrl->stream[msg->stream_id].substream->runtime;
	ADEBUG();
	saudio = dev_ctrl->stream[msg->stream_id].saudio;
	result =
	    sblock_get(dev_ctrl->dst, dev_ctrl->channel, (struct sblock *)&blk,
		       CMD_TIMEOUT);
	if (!result) {
		struct cmd_prepare *prepare = (struct cmd_prepare *)blk.addr;
		prepare->common.command = SAUDIO_CMD_PREPARE;
		prepare->common.sub_cmd=msg->stream_id;
		prepare->rate = runtime->rate;
		prepare->channels = runtime->channels;
		prepare->format = runtime->format;
		prepare->period =
		    frames_to_bytes(runtime, runtime->period_size);
		prepare->periods = runtime->periods;
		blk.length = sizeof(struct cmd_prepare);

		mutex_lock(&dev_ctrl->mutex);

		sblock_send(dev_ctrl->dst, dev_ctrl->channel,
			    (struct sblock *)&blk);
		result =
		    saudio_wait_common_cmd(dev_ctrl->dst, dev_ctrl->channel,
					   SAUDIO_CMD_PREPARE_RET,
					   0,CMD_TIMEOUT);
		if(result) 
		    saudio_snd_card_free(saudio);

		mutex_unlock(&dev_ctrl->mutex);
	}
	pr_debug("saudio_cmd_prepare_process result is %d", result);
	return result;

}
Пример #4
0
static int saudio_send_common_cmd(uint32_t dst, uint32_t channel,
				  uint32_t cmd, uint32_t subcmd,
				  int32_t timeout)
{
	int result = 0;
	struct sblock blk = { 0 };
	ADEBUG();
	pr_debug(" dst is %d, channel %d, cmd %x, subcmd %x\n", dst, channel,
		 cmd, subcmd);
	saudio_clear_cmd( dst,  channel);
	result = sblock_get(dst, channel, (struct sblock *)&blk, timeout);
	if (result >= 0) {
		struct cmd_common *common = (struct cmd_common *)blk.addr;
		common->command = cmd;
		common->sub_cmd = subcmd;
		blk.length = sizeof(struct cmd_common);
		pr_debug(" dst is %d, channel %d, cmd %x, subcmd %x send ok\n",
			 dst, channel, cmd, subcmd);
		result = sblock_send(dst, channel, (struct sblock *)&blk);
	}
	return result;
}
Пример #5
0
static int saudio_data_transfer_process(struct saudio_stream *stream,
					    struct saudio_msg *msg)
{
	struct snd_pcm_runtime *runtime = stream->substream->runtime;
	struct sblock blk = { 0 };
	int32_t result = 0;
	struct cmd_common *common = NULL;

	int32_t elapsed_blks = 0;
	int32_t periods_avail;
	int32_t periods_tosend;
	int32_t cur_blk_count = 0;

	cur_blk_count = sblock_get_free_count(stream->dst, stream->channel);

	elapsed_blks =
	    (cur_blk_count + stream->last_getblk_count - stream->blk_count) -
	    stream->last_elapsed_count;

	if (stream->stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
		periods_avail = snd_pcm_playback_avail(runtime) /
		    runtime->period_size;
	} else {
		periods_avail = snd_pcm_capture_avail(runtime) /
		    runtime->period_size;
	}

	periods_tosend = stream->periods_avail - periods_avail;
	if (periods_tosend > 0) {
		stream->periods_tosend += periods_tosend;
	}

	if (stream->periods_tosend) {
		while (stream->periods_tosend) {
			result =
			    sblock_get(stream->dst, stream->channel, &blk, 0);
			if (result) {
				break;
			}
			stream->last_getblk_count++;
			common = (struct cmd_common *)blk.addr;
			blk.length =
			    frames_to_bytes(runtime, runtime->period_size);
			common->command = SAUDIO_DATA_PCM;
			common->sub_cmd = stream->stream_id;
			common->reserved1 =
			    stream->substream->dma_buffer.addr +
			    stream->period * blk.length;

			sblock_send(stream->dst, stream->channel, &blk);

			stream->periods_tosend--;
			stream->period++;
			stream->period = stream->period % runtime->periods;
		}

	} else {
		pr_debug("saudio.c: saudio no data to send ");
		if (sblock_get_free_count(stream->dst, stream->channel) ==
		    SAUDIO_STREAM_BLOCK_COUNT) {
			pr_debug
			    ("saudio.c: saudio no data to send and  is empty ");
			result =
			    sblock_get(stream->dst, stream->channel, &blk, 0);
			if (result) {
				ETRACE("saudio.c: no data and no blk\n");
			} else {
				stream->last_getblk_count++;
				common = (struct cmd_common *)blk.addr;
				common->command = SAUDIO_DATA_SILENCE;
				common->sub_cmd = stream->stream_id;

				sblock_send(stream->dst, stream->channel, &blk);
				stream->last_elapsed_count++;
				schedule_timeout(msecs_to_jiffies(1));
			}
		}
	}

	while (elapsed_blks) {
		elapsed_blks--;
		stream->hwptr_done++;
		stream->hwptr_done %= runtime->periods;
		snd_pcm_period_elapsed(stream->substream);
		stream->periods_avail++;
		stream->last_elapsed_count++;
	}

	return 0;
}
Пример #6
0
/*Transmit interface*/
static int sprdwl_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct sprdwl_priv *priv = netdev_priv(dev);
	struct sblock blk;
	int ret;
	u8 *addr = NULL;

#ifdef CONFIG_SPRDWL_FW_ZEROCOPY
	if (priv->tx_free < TX_FLOW_LOW) {
		dev_err(&dev->dev, "tx flow control full\n");
		netif_stop_queue(dev);
		priv->ndev->stats.tx_fifo_errors++;
		return NETDEV_TX_BUSY;
	}
#endif
	/*Get a free sblock.*/
	ret = sblock_get(WLAN_CP_ID, WLAN_SBLOCK_CH, &blk, 0);
	if (ret) {
		dev_err(&dev->dev, "Failed to get free sblock (%d)!\n", ret);
		netif_stop_queue(dev);
		priv->ndev->stats.tx_fifo_errors++;
		return NETDEV_TX_BUSY;
	}

	if (blk.length < skb->len) {
		dev_err(&dev->dev, "The size of sblock is so tiny!\n");
		priv->ndev->stats.tx_fifo_errors++;
		sblock_put(WLAN_CP_ID, WLAN_SBLOCK_CH, &blk);
		dev_kfree_skb_any(skb);
		priv->txrcnt = 0;
		return NETDEV_TX_OK;
	}

#ifdef CONFIG_SPRDWL_FW_ZEROCOPY
	addr = blk.addr + SIPC_TRANS_OFFSET;
#else
	addr = blk.addr;
#endif
	priv->tx_free--;
	if (priv->connect_status == SPRDWL_CONNECTED &&
	    priv->cipher_type == SPRDWL_CIPHER_WAPI &&
/*            priv->key_len[GROUP][priv->key_index[GROUP]] != 0 &&*/
	    priv->key_len[PAIRWISE][priv->key_index[PAIRWISE]] != 0 &&
	    (*(u16 *)((u8 *)skb->data + ETH_PKT_TYPE_OFFSET) != 0xb488)) {
		memcpy(((u8 *)addr), skb->data, ETHERNET_HDR_LEN);
		blk.length = wlan_tx_wapi_encryption(priv,
					skb->data,
					(skb->len - ETHERNET_HDR_LEN),
					((u8 *)addr + ETHERNET_HDR_LEN))
					+ ETHERNET_HDR_LEN;
	} else {
		blk.length = skb->len;
		memcpy(((u8 *)addr), skb->data, skb->len);
	}

#ifdef DUMP_TRANSMIT_PACKET
	print_hex_dump(KERN_DEBUG, "transmit packet: ", DUMP_PREFIX_OFFSET,
		       16, 1, skb->data, skb->len, 0);
#endif
	ret = sblock_send(WLAN_CP_ID, WLAN_SBLOCK_CH, &blk);
	if (ret) {
		dev_err(&dev->dev, "Failed to send sblock (%d)!\n", ret);
		sblock_put(WLAN_CP_ID, WLAN_SBLOCK_CH, &blk);
		priv->tx_free++;
		priv->ndev->stats.tx_fifo_errors++;
		if (priv->txrcnt > SETH_RESEND_MAX_NUM)
			netif_stop_queue(dev);
		priv->txrcnt++;
		return NETDEV_TX_BUSY;
	}

	/*Statistics*/
	priv->ndev->stats.tx_bytes += skb->len;
	priv->ndev->stats.tx_packets++;
	dev->trans_start = jiffies;
	priv->txrcnt = 0;

	dev_kfree_skb_any(skb);

	return NETDEV_TX_OK;
}