From patchwork Thu Mar 21 02:38:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Annaliese McDermond X-Patchwork-Id: 10862843 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 69DBA18EC for ; Thu, 21 Mar 2019 02:51:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4542829FB6 for ; Thu, 21 Mar 2019 02:51:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3747729FD3; Thu, 21 Mar 2019 02:51:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 8FAFC29FB6 for ; Thu, 21 Mar 2019 02:50:57 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 16B3E86F; Thu, 21 Mar 2019 03:42:33 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 16B3E86F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1553136203; bh=5FVJJpzLXQS1g5qh4BbQTP+abnf8nkvLxylqk0F1uAs=; h=From:To:Date:In-Reply-To:References:Cc:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=jq/dugOfsmoIgCkqg2WWOdQw7zpSmeCmQGQkkmXSMQd2uoqZkV8WqCRM2xgQuKopu 6pjvOmW01fBctiqsC5MYh/gnoyYzFigwWfsAzUoxsqWnCVi+2+uprN3dItQ8TYhvp8 Fksn8RBjSd8YIcLurX8VmQ7oVCEGg5LVz9MRyNo4= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 7DD64F8972B; Thu, 21 Mar 2019 03:39:23 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa1.perex.cz (Postfix, from userid 50401) id BBB40F89720; Thu, 21 Mar 2019 03:39:16 +0100 (CET) Received: from smtp65.ord1c.emailsrvr.com (smtp65.ord1c.emailsrvr.com [108.166.43.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 175F5F8968A for ; Thu, 21 Mar 2019 03:39:12 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 175F5F8968A Received: from smtp17.relay.ord1c.emailsrvr.com (localhost [127.0.0.1]) by smtp17.relay.ord1c.emailsrvr.com (SMTP Server) with ESMTP id 344F2601A4; Wed, 20 Mar 2019 22:39:07 -0400 (EDT) X-SMTPDoctor-Processed: csmtpprox beta Received: from smtp17.relay.ord1c.emailsrvr.com (localhost [127.0.0.1]) by smtp17.relay.ord1c.emailsrvr.com (SMTP Server) with ESMTP id 30F8E60220; Wed, 20 Mar 2019 22:39:07 -0400 (EDT) X-Auth-ID: mcdermj@xenotropic.com Received: by smtp17.relay.ord1c.emailsrvr.com (Authenticated sender: mcdermj-AT-xenotropic.com) with ESMTPSA id 8D097601A4; Wed, 20 Mar 2019 22:39:06 -0400 (EDT) X-Sender-Id: mcdermj@xenotropic.com Received: from commune.xenotropic.com (c-73-96-52-102.hsd1.or.comcast.net [73.96.52.102]) (using TLSv1.2 with cipher DHE-RSA-AES128-GCM-SHA256) by 0.0.0.0:587 (trex/5.7.12); Wed, 20 Mar 2019 22:39:07 -0400 From: Annaliese McDermond To: broonie@kernel.org, alsa-devel@alsa-project.org Date: Wed, 20 Mar 2019 19:38:47 -0700 Message-Id: <20190321023854.16947-5-nh6z@nh6z.net> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190321023854.16947-1-nh6z@nh6z.net> References: <20190321023854.16947-1-nh6z@nh6z.net> MIME-Version: 1.0 Cc: team@nwdigitalradio.com, Annaliese McDermond Subject: [alsa-devel] [PATCH v3 04/11] ASoC: tlv320aic32x4: Model DAC/ADC dividers in CCF X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 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" X-Virus-Scanned: ClamAV using ClamSMTP Model and manage DAC/ADC dividers as components in the Core Clock Framework. This should allow us to do some more complex clock management and power control. Also, some of the on-board chip clocks can be exposed to the outside, and this change will make those clocks easier to consume by other parts of the kernel. Signed-off-by: Annaliese McDermond --- sound/soc/codecs/tlv320aic32x4-clk.c | 90 ++++++++++++++++++++++++++ sound/soc/codecs/tlv320aic32x4.c | 95 ++++++++++++++++------------ sound/soc/codecs/tlv320aic32x4.h | 4 ++ 3 files changed, 148 insertions(+), 41 deletions(-) diff --git a/sound/soc/codecs/tlv320aic32x4-clk.c b/sound/soc/codecs/tlv320aic32x4-clk.c index cded85009c8c..daf14924e324 100644 --- a/sound/soc/codecs/tlv320aic32x4-clk.c +++ b/sound/soc/codecs/tlv320aic32x4-clk.c @@ -289,6 +289,68 @@ static const struct clk_ops aic32x4_codec_clkin_ops = { .get_parent = clk_aic32x4_codec_clkin_get_parent, }; +static int clk_aic32x4_div_prepare(struct clk_hw *hw) +{ + struct clk_aic32x4 *div = to_clk_aic32x4(hw); + + return regmap_update_bits(div->regmap, div->reg, + AIC32X4_DIVEN, AIC32X4_DIVEN); +} + +static void clk_aic32x4_div_unprepare(struct clk_hw *hw) +{ + struct clk_aic32x4 *div = to_clk_aic32x4(hw); + + regmap_update_bits(div->regmap, div->reg, + AIC32X4_DIVEN, 0); +} + +static int clk_aic32x4_div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_aic32x4 *div = to_clk_aic32x4(hw); + u8 divisor; + + divisor = DIV_ROUND_UP(parent_rate, rate); + if (divisor > 128) + return -EINVAL; + + return regmap_update_bits(div->regmap, div->reg, + AIC32X4_DIV_MASK, divisor); +} + +static long clk_aic32x4_div_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long divisor; + + divisor = DIV_ROUND_UP(*parent_rate, rate); + if (divisor > 128) + return -EINVAL; + + return DIV_ROUND_UP(*parent_rate, divisor); +} + +static unsigned long clk_aic32x4_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_aic32x4 *div = to_clk_aic32x4(hw); + + unsigned int val; + + regmap_read(div->regmap, div->reg, &val); + + return DIV_ROUND_UP(parent_rate, val & AIC32X4_DIV_MASK); +} + +static const struct clk_ops aic32x4_div_ops = { + .prepare = clk_aic32x4_div_prepare, + .unprepare = clk_aic32x4_div_unprepare, + .set_rate = clk_aic32x4_div_set_rate, + .round_rate = clk_aic32x4_div_round_rate, + .recalc_rate = clk_aic32x4_div_recalc_rate, +}; + static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = { { .name = "pll", @@ -306,6 +368,34 @@ static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = { .ops = &aic32x4_codec_clkin_ops, .reg = 0, }, + { + .name = "ndac", + .parent_names = (const char * []) { "codec_clkin" }, + .num_parents = 1, + .ops = &aic32x4_div_ops, + .reg = AIC32X4_NDAC, + }, + { + .name = "mdac", + .parent_names = (const char * []) { "ndac" }, + .num_parents = 1, + .ops = &aic32x4_div_ops, + .reg = AIC32X4_MDAC, + }, + { + .name = "nadc", + .parent_names = (const char * []) { "codec_clkin" }, + .num_parents = 1, + .ops = &aic32x4_div_ops, + .reg = AIC32X4_NADC, + }, + { + .name = "madc", + .parent_names = (const char * []) { "nadc" }, + .num_parents = 1, + .ops = &aic32x4_div_ops, + .reg = AIC32X4_MADC, + }, }; static struct clk *aic32x4_register_clk(struct device *dev, diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 5496e4e080f4..0cf942938372 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -52,11 +52,11 @@ struct aic32x4_rate_divs { u32 rate; unsigned long pll_rate; u16 dosr; - u8 ndac; - u8 mdac; + unsigned long ndac_rate; + unsigned long mdac_rate; u8 aosr; - u8 nadc; - u8 madc; + unsigned long nadc_rate; + unsigned long madc_rate; u8 blck_N; u8 r_block; u8 p_block; @@ -309,34 +309,54 @@ static const struct snd_kcontrol_new aic32x4_snd_controls[] = { static const struct aic32x4_rate_divs aic32x4_divs[] = { /* 8k rate */ - { 12000000, 8000, 57120000, 768, 5, 3, 128, 5, 18, 24, 1, 1 }, - { 24000000, 8000, 57120000, 768, 15, 1, 64, 45, 4, 24, 1, 1 }, - { 25000000, 8000, 32620000, 768, 15, 1, 64, 45, 4, 24, 1, 1 }, + { 12000000, 8000, 57120000, 768, 18432000, 6144000, 128, 18432000, + 1024000, 24, 1, 1 }, + { 24000000, 8000, 57120000, 768, 6144000, 6144000, 64, 2048000, + 512000, 24, 1, 1 }, + { 25000000, 8000, 32620000, 768, 6144000, 6144000, 64, 2048000, + 512000, 24, 1, 1 }, /* 11.025k rate */ - { 12000000, 11025, 44217600, 512, 8, 2, 128, 8, 8, 16, 1, 1 }, - { 24000000, 11025, 44217600, 512, 16, 1, 64, 32, 4, 16, 1, 1 }, + { 12000000, 11025, 44217600, 512, 11289600, 5644800, 128, 11289600, + 1411200, 16, 1, 1 }, + { 24000000, 11025, 44217600, 512, 5644800, 5644800, 64, 2822400, + 705600, 16, 1, 1 }, /* 16k rate */ - { 12000000, 16000, 57120000, 384, 5, 3, 128, 5, 9, 12, 1, 1 }, - { 24000000, 16000, 57120000, 384, 15, 1, 64, 18, 5, 12, 1, 1 }, - { 25000000, 16000, 32620000, 384, 15, 1, 64, 18, 5, 12, 1, 1 }, + { 12000000, 16000, 57120000, 384, 18432000, 6144000, 128, 18432000, + 2048000, 12, 1, 1 }, + { 24000000, 16000, 57120000, 384, 6144000, 6144000, 64, 5120000, + 1024000, 12, 1, 1 }, + { 25000000, 16000, 32620000, 384, 6144000, 6144000, 64, 5120000, + 1024000, 12, 1, 1 }, /* 22.05k rate */ - { 12000000, 22050, 44217600, 256, 4, 4, 128, 4, 8, 8, 1, 1 }, - { 24000000, 22050, 44217600, 256, 16, 1, 64, 16, 4, 8, 1, 1 }, - { 25000000, 22050, 19713750, 256, 16, 1, 64, 16, 4, 8, 1, 1 }, + { 12000000, 22050, 44217600, 256, 22579200, 5644800, 128, 22579200, + 2822400, 8, 1, 1 }, + { 24000000, 22050, 44217600, 256, 5644800, 5644800, 64, 5644800, + 1411200, 8, 1, 1 }, + { 25000000, 22050, 19713750, 256, 5644800, 5644800, 64, 5644800, + 1411200, 8, 1, 1 }, /* 32k rate */ - { 12000000, 32000, 14112000, 192, 2, 7, 64, 2, 21, 6, 1, 1 }, - { 24000000, 32000, 14112000, 192, 7, 2, 64, 7, 6, 6, 1, 1 }, + { 12000000, 32000, 14112000, 192, 43008000, 6144000, 64, 43008000, + 2048000, 6, 1, 1 }, + { 24000000, 32000, 14112000, 192, 12288000, 6144000, 64, 12288000, + 2048000, 6, 1, 1 }, /* 44.1k rate */ - { 12000000, 44100, 44217600, 128, 2, 8, 128, 2, 8, 4, 1, 1 }, - { 24000000, 44100, 44217600, 128, 8, 2, 64, 8, 4, 4, 1, 1 }, - { 25000000, 44100, 19713750, 128, 8, 2, 64, 8, 4, 4, 1, 1 }, + { 12000000, 44100, 44217600, 128, 45158400, 5644800, 128, 45158400, + 5644800, 4, 1, 1 }, + { 24000000, 44100, 44217600, 128, 11289600, 5644800, 64, 11289600, + 2822400, 4, 1, 1 }, + { 25000000, 44100, 19713750, 128, 11289600, 5644800, 64, 11289600, + 2822400, 4, 1, 1 }, /* 48k rate */ - { 12000000, 48000, 18432000, 128, 2, 8, 128, 2, 8, 4, 1, 1 }, - { 24000000, 48000, 18432000, 128, 8, 2, 64, 8, 4, 4, 1, 1 }, - { 25000000, 48000, 75626250, 128, 8, 2, 64, 8, 4, 4, 1, 1 }, + { 12000000, 48000, 18432000, 128, 49152000, 6144000, 128, 49152000, + 6144000, 4, 1, 1 }, + { 24000000, 48000, 18432000, 128, 12288000, 6144000, 64, 12288000, + 3072000, 4, 1, 1 }, + { 25000000, 48000, 75626250, 128, 12288000, 6144000, 64, 12288000, + 3072000, 4, 1, 1 }, /* 96k rate */ - { 25000000, 96000, 75626250, 64, 4, 4, 64, 4, 4, 1, 1, 9 }, + { 25000000, 96000, 75626250, 64, 24576000, 6144000, 64, 24576000, + 6144000, 1, 1, 9 }, }; static const struct snd_kcontrol_new hpl_output_mixer_controls[] = { @@ -719,6 +739,10 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component, struct clk_bulk_data clocks[] = { { .id = "pll" }, + { .id = "nadc" }, + { .id = "madc" }, + { .id = "ndac" }, + { .id = "mdac" }, }; i = aic32x4_get_divs(parent_rate, sample_rate); @@ -731,7 +755,11 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component, if (ret) return ret; - clk_set_rate(clocks[0].clk, sample_rate); + clk_set_rate(clocks[0].clk, aic32x4_divs[i].pll_rate); + clk_set_rate(clocks[1].clk, aic32x4_divs[i].nadc_rate); + clk_set_rate(clocks[2].clk, aic32x4_divs[i].madc_rate); + clk_set_rate(clocks[3].clk, aic32x4_divs[i].ndac_rate); + clk_set_rate(clocks[4].clk, aic32x4_divs[i].mdac_rate); aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block); @@ -740,26 +768,10 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component, AIC32X4_BDIVCLK_MASK, AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT); - /* NDAC divider value */ - snd_soc_component_update_bits(component, AIC32X4_NDAC, - AIC32X4_NDAC_MASK, aic32x4_divs[i].ndac); - - /* MDAC divider value */ - snd_soc_component_update_bits(component, AIC32X4_MDAC, - AIC32X4_MDAC_MASK, aic32x4_divs[i].mdac); - /* DOSR MSB & LSB values */ snd_soc_component_write(component, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8); snd_soc_component_write(component, AIC32X4_DOSRLSB, (aic32x4_divs[i].dosr & 0xff)); - /* NADC divider value */ - snd_soc_component_update_bits(component, AIC32X4_NADC, - AIC32X4_NADC_MASK, aic32x4_divs[i].nadc); - - /* MADC divider value */ - snd_soc_component_update_bits(component, AIC32X4_MADC, - AIC32X4_MADC_MASK, aic32x4_divs[i].madc); - /* AOSR value */ snd_soc_component_write(component, AIC32X4_AOSR, aic32x4_divs[i].aosr); @@ -988,6 +1000,7 @@ static int aic32x4_component_probe(struct snd_soc_component *component) struct clk_bulk_data clocks[] = { { .id = "codec_clkin" }, + { .id = "pll" }, }; ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks); diff --git a/sound/soc/codecs/tlv320aic32x4.h b/sound/soc/codecs/tlv320aic32x4.h index e2b65bbba7c2..6ede877b00a0 100644 --- a/sound/soc/codecs/tlv320aic32x4.h +++ b/sound/soc/codecs/tlv320aic32x4.h @@ -206,6 +206,10 @@ int aic32x4_register_clocks(struct device *dev, const char *mclk_name); #define AIC32X4_RMICPGANIN_IN1L_10K 0x10 #define AIC32X4_RMICPGANIN_CM1R_10K 0x40 +/* Common mask and enable for all of the dividers */ +#define AIC32X4_DIVEN BIT(7) +#define AIC32X4_DIV_MASK GENMASK(6, 0) + /* Clock Limits */ #define AIC32X4_MAX_PLL_CLKIN 20000000