From patchwork Tue Dec 15 11:29:49 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Charles Keepax X-Patchwork-Id: 7853901 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 88C44BEEE1 for ; Tue, 15 Dec 2015 11:32:43 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 84731202EC for ; Tue, 15 Dec 2015 11:32:42 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 2A39C20272 for ; Tue, 15 Dec 2015 11:32:41 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 29370265876; Tue, 15 Dec 2015 12:32:37 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id EEF4E264F52; Tue, 15 Dec 2015 12:30:11 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 9D1B5264F53; Tue, 15 Dec 2015 12:30:10 +0100 (CET) Received: from mx0a-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by alsa0.perex.cz (Postfix) with ESMTP id 5227F261AD0 for ; Tue, 15 Dec 2015 12:29:55 +0100 (CET) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.15.0.59/8.15.0.59) with SMTP id tBFBPgOp005717; Tue, 15 Dec 2015 05:29:54 -0600 Authentication-Results: ppops.net; spf=none smtp.mail=ckeepax@opensource.wolfsonmicro.com Received: from mail1.cirrus.com (mail1.cirrus.com [141.131.3.20]) by mx0a-001ae601.pphosted.com with ESMTP id 1ysqu7aqed-4; Tue, 15 Dec 2015 05:29:54 -0600 Received: from EX12.ad.cirrus.com (unknown [172.19.9.182]) by mail1.cirrus.com (Postfix) with ESMTP id 079B834043; Tue, 15 Dec 2015 05:30:19 -0600 (CST) Received: from imbe.wolfsonmicro.main (172.20.9.178) by EX12.ad.cirrus.com (172.19.9.182) with Microsoft SMTP Server id 14.3.248.2; Tue, 15 Dec 2015 11:29:50 +0000 Received: from algalon.wolfsonmicro.main ([172.22.20.24]) by imbe.wolfsonmicro.main (8.14.4/8.14.4) with ESMTP id tBFBTmLK025048; Tue, 15 Dec 2015 11:29:50 GMT From: Charles Keepax To: Date: Tue, 15 Dec 2015 11:29:49 +0000 Message-ID: <1450178989-8749-9-git-send-email-ckeepax@opensource.wolfsonmicro.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1450178989-8749-1-git-send-email-ckeepax@opensource.wolfsonmicro.com> References: <1450178989-8749-1-git-send-email-ckeepax@opensource.wolfsonmicro.com> MIME-Version: 1.0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 spamscore=0 suspectscore=3 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1507310007 definitions=main-1512150183 Cc: alsa-devel@alsa-project.org, vinod.koul@intel.com, patches@opensource.wolfsonmicro.com, lgirdwood@gmail.com, tiwai@suse.com Subject: [alsa-devel] [PATCH v3 8/8] ASoC: wm_adsp: Pull data through compressed read X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP Data is read in blocks of up to one fragment is size from the circular buffer on the DSP and is re-packed to remove the padding byte that exists in the DSP memory map. Signed-off-by: Charles Keepax --- sound/soc/codecs/wm5110.c | 1 + sound/soc/codecs/wm_adsp.c | 138 +++++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/wm_adsp.h | 2 + 3 files changed, 141 insertions(+) diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index c6c176e..9ed864b 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -2297,6 +2297,7 @@ static struct snd_compr_ops wm5110_compr_ops = { .get_caps = wm_adsp_compr_get_caps, .trigger = wm_adsp_compr_trigger, .pointer = wm_adsp_compr_pointer, + .copy = wm_adsp_compr_copy, }; static struct snd_soc_platform_driver wm5110_compr_platform = { diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 9d68ba5..fbcd4ce 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -293,6 +293,7 @@ struct wm_adsp_compr { struct snd_compr_stream *stream; struct snd_compressed_buffer size; + u32 *raw_buf; unsigned int copied_total; }; @@ -2382,6 +2383,7 @@ int wm_adsp_compr_free(struct snd_compr_stream *stream) dsp->compr = NULL; + kfree(compr->raw_buf); kfree(compr); mutex_unlock(&dsp->pwr_lock); @@ -2449,6 +2451,7 @@ int wm_adsp_compr_set_params(struct snd_compr_stream *stream, struct snd_compr_params *params) { struct wm_adsp_compr *compr = stream->runtime->private_data; + unsigned int size; int ret; ret = wm_adsp_compr_check_params(stream, params); @@ -2460,6 +2463,11 @@ int wm_adsp_compr_set_params(struct snd_compr_stream *stream, adsp_dbg(compr->dsp, "fragment_size=%d fragments=%d\n", compr->size.fragment_size, compr->size.fragments); + size = wm_adsp_compr_frag_words(compr) * sizeof(*compr->raw_buf); + compr->raw_buf = kmalloc(size, GFP_DMA | GFP_KERNEL); + if (!compr->raw_buf) + return -ENOMEM; + return 0; } EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params); @@ -2793,6 +2801,7 @@ static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf) int wm_adsp_compr_handle_irq(struct wm_adsp *dsp) { struct wm_adsp_compr_buf *buf = dsp->buffer; + struct wm_adsp_compr *compr = dsp->compr; int ret = 0; mutex_lock(&dsp->pwr_lock); @@ -2829,6 +2838,9 @@ int wm_adsp_compr_handle_irq(struct wm_adsp *dsp) goto out; } + if (compr->stream) + snd_compr_fragment_elapsed(compr->stream); + out: mutex_unlock(&dsp->pwr_lock); @@ -2903,4 +2915,130 @@ out: } EXPORT_SYMBOL_GPL(wm_adsp_compr_pointer); +static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target) +{ + struct wm_adsp_compr_buf *buf = compr->buf; + u8 *pack_in = (u8 *)compr->raw_buf; + u8 *pack_out = (u8 *)compr->raw_buf; + unsigned int adsp_addr; + int mem_type, nwords, max_read; + int i, j, ret; + + /* Calculate read parameters */ + for (i = 0; i < wm_adsp_fw[buf->dsp->fw].caps->num_regions; ++i) + if (buf->read_index < buf->regions[i].cumulative_size) + break; + + if (i == wm_adsp_fw[buf->dsp->fw].caps->num_regions) + return -EINVAL; + + mem_type = buf->regions[i].mem_type; + adsp_addr = buf->regions[i].base_addr + + (buf->read_index - buf->regions[i].offset); + + max_read = wm_adsp_compr_frag_words(compr); + nwords = buf->regions[i].cumulative_size - buf->read_index; + + if (nwords > target) + nwords = target; + if (nwords > buf->avail) + nwords = buf->avail; + if (nwords > max_read) + nwords = max_read; + if (!nwords) + return 0; + + /* Read data from DSP */ + ret = wm_adsp_read_data_block(buf->dsp, mem_type, adsp_addr, + nwords, compr->raw_buf); + if (ret < 0) + return ret; + + /* Remove the padding bytes from the data read from the DSP */ + for (i = 0; i < nwords; i++) { + for (j = 0; j < WM_ADSP_DATA_WORD_SIZE; j++) + *pack_out++ = *pack_in++; + + pack_in += sizeof(*(compr->raw_buf)) - WM_ADSP_DATA_WORD_SIZE; + } + + /* update read index to account for words read */ + buf->read_index += nwords; + if (buf->read_index == wm_adsp_buffer_size(buf)) + buf->read_index = 0; + + ret = wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(next_read_index), + buf->read_index); + if (ret < 0) + return ret; + + /* update avail to account for words read */ + buf->avail -= nwords; + + return nwords; +} + +static int wm_adsp_compr_read(struct wm_adsp_compr *compr, + char __user *buf, size_t count) +{ + struct wm_adsp *dsp = compr->dsp; + int ntotal = 0; + int nwords, nbytes; + + adsp_dbg(dsp, "Requested read of %zu bytes\n", count); + + if (!compr->buf) + return -ENXIO; + + if (compr->buf->error) + return -EIO; + + count /= WM_ADSP_DATA_WORD_SIZE; + + do { + nwords = wm_adsp_buffer_capture_block(compr, count); + if (nwords < 0) { + adsp_err(dsp, "Failed to capture block: %d\n", nwords); + return nwords; + } + + nbytes = nwords * WM_ADSP_DATA_WORD_SIZE; + + adsp_dbg(dsp, "Read %d bytes\n", nbytes); + + if (copy_to_user(buf + ntotal, compr->raw_buf, nbytes)) { + adsp_err(dsp, "Failed to copy data to user: %d, %d\n", + ntotal, nbytes); + return -EFAULT; + } + + count -= nwords; + ntotal += nbytes; + } while (nwords > 0 && count > 0); + + compr->copied_total += ntotal; + + return ntotal; +} + +int wm_adsp_compr_copy(struct snd_compr_stream *stream, char __user *buf, + size_t count) +{ + struct wm_adsp_compr *compr = stream->runtime->private_data; + struct wm_adsp *dsp = compr->dsp; + int ret; + + mutex_lock(&dsp->pwr_lock); + + if (stream->direction == SND_COMPRESS_CAPTURE) + ret = wm_adsp_compr_read(compr, buf, count); + else + ret = -ENOTSUPP; + + mutex_unlock(&dsp->pwr_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(wm_adsp_compr_copy); + MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 522fa1a..1a928ec 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -115,5 +115,7 @@ extern int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd); extern int wm_adsp_compr_handle_irq(struct wm_adsp *dsp); extern int wm_adsp_compr_pointer(struct snd_compr_stream *stream, struct snd_compr_tstamp *tstamp); +extern int wm_adsp_compr_copy(struct snd_compr_stream *stream, + char __user *buf, size_t count); #endif