From patchwork Thu Nov 27 08:07:38 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuninori Morimoto X-Patchwork-Id: 5393111 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.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A33EFC11AC for ; Thu, 27 Nov 2014 08:15:48 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A23DD201C7 for ; Thu, 27 Nov 2014 08:15:47 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 5CBBB2010B for ; Thu, 27 Nov 2014 08:15:46 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 79B482665D0; Thu, 27 Nov 2014 09:15:45 +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=-1.9 required=5.0 tests=BAYES_00, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id EB8DD265AC7; Thu, 27 Nov 2014 09:09:46 +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 E3112265D9D; Thu, 27 Nov 2014 09:09:44 +0100 (CET) Received: from relmlie1.idc.renesas.com (relmlor2.renesas.com [210.160.252.172]) by alsa0.perex.cz (Postfix) with ESMTP id E8604265E0E for ; Thu, 27 Nov 2014 09:07:41 +0100 (CET) Received: from unknown (HELO relmlir4.idc.renesas.com) ([10.200.68.154]) by relmlie1.idc.renesas.com with ESMTP; 27 Nov 2014 17:07:40 +0900 Received: from relmlac3.idc.renesas.com (relmlac3.idc.renesas.com [10.200.69.23]) by relmlir4.idc.renesas.com (Postfix) with ESMTP id 73EA84A2FE; Thu, 27 Nov 2014 17:07:40 +0900 (JST) Received: by relmlac3.idc.renesas.com (Postfix, from userid 0) id 7574F1806F; Thu, 27 Nov 2014 17:07:40 +0900 (JST) Received: from relmlac3.idc.renesas.com (localhost [127.0.0.1]) by relmlac3.idc.renesas.com (Postfix) with ESMTP id 6EE3A1800A; Thu, 27 Nov 2014 17:07:40 +0900 (JST) Received: from relmlii1.idc.renesas.com [10.200.68.65] by relmlac3.idc.renesas.com with ESMTP id TAN14783; Thu, 27 Nov 2014 17:07:40 +0900 X-IronPort-AV: E=Sophos;i="5.07,467,1413212400"; d="scan'208";a="174554540" Received: from mail-sg1lp0086.outbound.protection.outlook.com (HELO APAC01-SG1-obe.outbound.protection.outlook.com) ([207.46.51.86]) by relmlii1.idc.renesas.com with ESMTP/TLS/AES256-SHA; 27 Nov 2014 17:07:39 +0900 Received: from remon.renesas.com (211.11.155.132) by SINPR06MB170.apcprd06.prod.outlook.com (10.242.57.16) with Microsoft SMTP Server (TLS) id 15.1.26.15; Thu, 27 Nov 2014 08:07:38 +0000 Message-ID: <87ioi183sc.wl%kuninori.morimoto.gx@renesas.com> To: Mark Brown In-Reply-To: <877fyh9ilx.wl%kuninori.morimoto.gx@renesas.com> References: <877fyh9ilx.wl%kuninori.morimoto.gx@renesas.com> From: Kuninori Morimoto User-Agent: Wanderlust/2.14.0 Emacs/23.3 Mule/6.0 MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Date: Thu, 27 Nov 2014 08:07:38 +0000 X-Originating-IP: [211.11.155.132] X-ClientProxiedBy: HKNPR06CA0054.apcprd06.prod.outlook.com (10.141.16.44) To SINPR06MB170.apcprd06.prod.outlook.com (10.242.57.16) X-Microsoft-Antispam: UriScan:; X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:;SRVR:SINPR06MB170; X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:;SRVR:SINPR06MB170; X-Forefront-PRVS: 040866B734 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(6009001)(189002)(199003)(47776003)(20776003)(95666004)(105586002)(81156004)(33646002)(66066001)(106356001)(4396001)(64706001)(76176999)(46406003)(62966003)(77156002)(77096003)(83506001)(54356999)(21056001)(229853001)(107046002)(50986999)(40100003)(31966008)(122386002)(46102003)(53416004)(42186005)(120916001)(23726002)(99396003)(110136001)(19580405001)(102836001)(19580395003)(50466002)(86362001)(92726001)(92566001)(97736003)(69596002)(101416001)(36756003)(21314002); DIR:OUT; SFP:1102; SCL:1; SRVR:SINPR06MB170; H:remon.renesas.com; FPR:; SPF:None; MLV:sfv; PTR:InfoNoRecords; MX:1; A:1; LANG:en; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:;SRVR:SINPR06MB170; X-OriginatorOrg: renesas.com Cc: Linux-ALSA , Simon , Liam Girdwood Subject: [alsa-devel] [PATCH 17/20] ASoC: rsnd: add Synchronous SRC mode 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 From: Kuninori Morimoto Renesas R-Car sound SRC (= Sampling Rate Converter) has Asynchronous/Synchronous SRC mode. Asynchronous mode is already supported. This patch adds Synchronous mode. The condition of enabling Synchronous mode are - SoC is clock master - sound uses SRC - sound is playback or sound is capture without DVC amixer set "SRC Playback Sync Convert Rate" on aplay xxx.wav & amixer set "SRC Playback Sync Convert Rate" 44100 Signed-off-by: Kuninori Morimoto --- sound/soc/sh/rcar/src.c | 126 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 121 insertions(+), 5 deletions(-) diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index eede3ac..1482772 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -16,11 +16,13 @@ struct rsnd_src { struct rsnd_src_platform_info *info; /* rcar_snd.h */ struct rsnd_mod mod; struct clk *clk; + struct rsnd_kctrl_cfg_s sen; /* sync convert enable */ + struct rsnd_kctrl_cfg_s sync; /* sync convert */ }; #define RSND_SRC_NAME_SIZE 16 -#define rsnd_src_convert_rate(p) ((p)->info->convert_rate) +#define rsnd_enable_sync_convert(src) ((src)->sen.val) #define rsnd_mod_to_src(_mod) \ container_of((_mod), struct rsnd_src, mod) #define rsnd_src_dma_available(src) \ @@ -216,6 +218,30 @@ int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod, return 0; } +u32 rsnd_src_convert_rate(struct rsnd_src *src) +{ + struct rsnd_mod *mod = &src->mod; + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + u32 convert_rate; + + if (!runtime) + return 0; + + if (!rsnd_enable_sync_convert(src)) + return src->info->convert_rate; + + convert_rate = src->sync.val; + + if (!convert_rate) + convert_rate = src->info->convert_rate; + + if (!convert_rate) + convert_rate = runtime->rate; + + return convert_rate; +} + unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime) @@ -280,6 +306,9 @@ static int rsnd_src_init(struct rsnd_mod *mod, clk_prepare_enable(src->clk); + /* reset sync convert_rate */ + src->sync.val = 0; + /* * Initialize the operation of the SRC internal circuits * see rsnd_src_start() @@ -296,6 +325,9 @@ static int rsnd_src_quit(struct rsnd_mod *mod, clk_disable_unprepare(src->clk); + /* reset sync convert_rate */ + src->sync.val = 0; + return 0; } @@ -519,6 +551,7 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct rsnd_src *src = rsnd_mod_to_src(mod); u32 convert_rate = rsnd_src_convert_rate(src); + u32 cr, route; uint ratio; int ret; @@ -539,13 +572,21 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, if (ret < 0) return ret; - rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); - + cr = 0x00011110; + route = 0x0; if (convert_rate) { - /* Gen1/Gen2 are not compatible */ - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); + route = 0x1; + + if (rsnd_enable_sync_convert(src)) { + cr |= 0x1; + route |= rsnd_dai_is_play(rdai, io) ? + (0x1 << 24) : (0x1 << 25); + } } + rsnd_mod_write(mod, SRC_SRCCR, cr); + rsnd_mod_write(mod, SRC_ROUTE_MODE0, route); + switch (rsnd_mod_id(mod)) { case 5: case 6: @@ -658,6 +699,80 @@ static int rsnd_src_stop_gen2(struct rsnd_mod *mod, return rsnd_src_stop(mod); } +static void rsnd_src_reconvert_update(struct rsnd_mod *mod) +{ + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_src *src = rsnd_mod_to_src(mod); + u32 convert_rate = rsnd_src_convert_rate(src); + u32 fsrate = 0; + + if (!rsnd_enable_sync_convert(src)) + return; + + if (!convert_rate) + return; + + fsrate = 0x0400000 / convert_rate * runtime->rate; + + /* update IFS */ + rsnd_mod_write(mod, SRC_IFSVR, fsrate); +} + +static int rsnd_src_pcm_new(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct snd_soc_pcm_runtime *rtd) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + struct rsnd_src *src = rsnd_mod_to_src(mod); + int ret; + + /* + * enable SRC sync convert if possible + */ + + /* + * Gen1 is not supported + */ + if (rsnd_is_gen1(priv)) + return 0; + + /* + * SRC sync convert needs clock master + */ + if (!rsnd_dai_is_clk_master(rdai)) + return 0; + + /* + * We can't use SRC sync convert + * if it has DVC + */ + if (rsnd_io_to_mod_dvc(io)) + return 0; + + /* + * enable sync convert + */ + ret = rsnd_kctrl_new_s(mod, rdai, rtd, + rsnd_dai_is_play(rdai, io) ? + "SRC Playback Sync Convert Rate Switch" : + "SRC Capture Sync Convert Rate Switch", + rsnd_src_reconvert_update, + &src->sen, 1); + if (ret < 0) + return ret; + + ret = rsnd_kctrl_new_s(mod, rdai, rtd, + rsnd_dai_is_play(rdai, io) ? + "SRC Playback Sync Convert Rate" : + "SRC Capture Sync Convert Rate", + rsnd_src_reconvert_update, + &src->sync, 192000); + + return ret; +} + static struct rsnd_mod_ops rsnd_src_gen2_ops = { .name = SRC_NAME, .probe = rsnd_src_probe_gen2, @@ -666,6 +781,7 @@ static struct rsnd_mod_ops rsnd_src_gen2_ops = { .quit = rsnd_src_quit, .start = rsnd_src_start_gen2, .stop = rsnd_src_stop_gen2, + .pcm_new = rsnd_src_pcm_new, }; struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)