From patchwork Thu Apr 26 13:20:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vinod Koul X-Patchwork-Id: 10365981 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id A0819601BE for ; Thu, 26 Apr 2018 13:17:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8D7E32834A for ; Thu, 26 Apr 2018 13:17:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 81F8B283D9; Thu, 26 Apr 2018 13:17:25 +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, 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]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 955492834A for ; Thu, 26 Apr 2018 13:17:24 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id C571B26785E; Thu, 26 Apr 2018 15:16:32 +0200 (CEST) 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 4479626782F; Thu, 26 Apr 2018 15:16:30 +0200 (CEST) Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by alsa0.perex.cz (Postfix) with ESMTP id E8932267870 for ; Thu, 26 Apr 2018 15:16:16 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 Apr 2018 06:16:16 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.49,330,1520924400"; d="scan'208";a="51010009" Received: from vkoul-udesk7.iind.intel.com ([10.223.84.143]) by orsmga001.jf.intel.com with ESMTP; 26 Apr 2018 06:16:12 -0700 From: Vinod Koul To: Greg KH Date: Thu, 26 Apr 2018 18:50:08 +0530 Message-Id: <1524748809-21860-13-git-send-email-vkoul@kernel.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1524748809-21860-1-git-send-email-vkoul@kernel.org> References: <1524748809-21860-1-git-send-email-vkoul@kernel.org> Cc: ALSA , tiwai@suse.de, Pierre-Louis Bossart , liam.r.girdwood@linux.intel.com, patches.audio@intel.com, Vinod Koul , broonie@kernel.org Subject: [alsa-devel] [PATCH v6 12/13] soundwire: intel: Add stream initialization 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: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP Add Intel stream init routines which initialize the Physical Data Interface (PDI), Audio Link Hub (ALH) and Audio shim. Also add bank switch routines. Signed-off-by: Hardik T Shah Signed-off-by: Sanyog Kale Signed-off-by: Shreyas NC Signed-off-by: Vinod Koul --- drivers/soundwire/intel.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index a64f87a08cfd..707e435b5da1 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include #include @@ -234,6 +236,149 @@ static int intel_shim_init(struct sdw_intel *sdw) return ret; } +/* + * PDI routines + */ +static void intel_pdi_init(struct sdw_intel *sdw, + struct sdw_cdns_stream_config *config) +{ + void __iomem *shim = sdw->res->shim; + unsigned int link_id = sdw->instance; + int pcm_cap, pdm_cap; + + /* PCM Stream Capability */ + pcm_cap = intel_readw(shim, SDW_SHIM_PCMSCAP(link_id)); + + config->pcm_bd = (pcm_cap & SDW_SHIM_PCMSCAP_BSS) >> + SDW_REG_SHIFT(SDW_SHIM_PCMSCAP_BSS); + config->pcm_in = (pcm_cap & SDW_SHIM_PCMSCAP_ISS) >> + SDW_REG_SHIFT(SDW_SHIM_PCMSCAP_ISS); + config->pcm_out = (pcm_cap & SDW_SHIM_PCMSCAP_OSS) >> + SDW_REG_SHIFT(SDW_SHIM_PCMSCAP_OSS); + + /* PDM Stream Capability */ + pdm_cap = intel_readw(shim, SDW_SHIM_PDMSCAP(link_id)); + + config->pdm_bd = (pdm_cap & SDW_SHIM_PDMSCAP_BSS) >> + SDW_REG_SHIFT(SDW_SHIM_PDMSCAP_BSS); + config->pdm_in = (pdm_cap & SDW_SHIM_PDMSCAP_ISS) >> + SDW_REG_SHIFT(SDW_SHIM_PDMSCAP_ISS); + config->pdm_out = (pdm_cap & SDW_SHIM_PDMSCAP_OSS) >> + SDW_REG_SHIFT(SDW_SHIM_PDMSCAP_OSS); +} + +static int +intel_pdi_get_ch_cap(struct sdw_intel *sdw, unsigned int pdi_num, bool pcm) +{ + void __iomem *shim = sdw->res->shim; + unsigned int link_id = sdw->instance; + int count; + + if (pcm) { + count = intel_readw(shim, SDW_SHIM_PCMSYCHC(link_id, pdi_num)); + } else { + count = intel_readw(shim, SDW_SHIM_PDMSCAP(link_id)); + count = ((count & SDW_SHIM_PDMSCAP_CPSS) >> + SDW_REG_SHIFT(SDW_SHIM_PDMSCAP_CPSS)); + } + + /* zero based values for channel count in register */ + count++; + + return count; +} + +static int intel_pdi_get_ch_update(struct sdw_intel *sdw, + struct sdw_cdns_pdi *pdi, + unsigned int num_pdi, + unsigned int *num_ch, bool pcm) +{ + int i, ch_count = 0; + + for (i = 0; i < num_pdi; i++) { + pdi->ch_count = intel_pdi_get_ch_cap(sdw, pdi->num, pcm); + ch_count += pdi->ch_count; + pdi++; + } + + *num_ch = ch_count; + return 0; +} + +static int intel_pdi_stream_ch_update(struct sdw_intel *sdw, + struct sdw_cdns_streams *stream, bool pcm) +{ + intel_pdi_get_ch_update(sdw, stream->bd, stream->num_bd, + &stream->num_ch_bd, pcm); + + intel_pdi_get_ch_update(sdw, stream->in, stream->num_in, + &stream->num_ch_in, pcm); + + intel_pdi_get_ch_update(sdw, stream->out, stream->num_out, + &stream->num_ch_out, pcm); + + return 0; +} + +static int intel_pdi_ch_update(struct sdw_intel *sdw) +{ + /* First update PCM streams followed by PDM streams */ + intel_pdi_stream_ch_update(sdw, &sdw->cdns.pcm, true); + intel_pdi_stream_ch_update(sdw, &sdw->cdns.pdm, false); + + return 0; +} + +static void +intel_pdi_shim_configure(struct sdw_intel *sdw, struct sdw_cdns_pdi *pdi) +{ + void __iomem *shim = sdw->res->shim; + unsigned int link_id = sdw->instance; + int pdi_conf = 0; + + pdi->intel_alh_id = (link_id * 16) + pdi->num + 5; + + /* + * Program stream parameters to stream SHIM register + * This is applicable for PCM stream only. + */ + if (pdi->type != SDW_STREAM_PCM) + return; + + if (pdi->dir == SDW_DATA_DIR_RX) + pdi_conf |= SDW_SHIM_PCMSYCM_DIR; + else + pdi_conf &= ~(SDW_SHIM_PCMSYCM_DIR); + + pdi_conf |= (pdi->intel_alh_id << + SDW_REG_SHIFT(SDW_SHIM_PCMSYCM_STREAM)); + pdi_conf |= (pdi->l_ch_num << SDW_REG_SHIFT(SDW_SHIM_PCMSYCM_LCHN)); + pdi_conf |= (pdi->h_ch_num << SDW_REG_SHIFT(SDW_SHIM_PCMSYCM_HCHN)); + + intel_writew(shim, SDW_SHIM_PCMSYCHM(link_id, pdi->num), pdi_conf); +} + +static void +intel_pdi_alh_configure(struct sdw_intel *sdw, struct sdw_cdns_pdi *pdi) +{ + void __iomem *alh = sdw->res->alh; + unsigned int link_id = sdw->instance; + unsigned int conf; + + pdi->intel_alh_id = (link_id * 16) + pdi->num + 5; + + /* Program Stream config ALH register */ + conf = intel_readl(alh, SDW_ALH_STRMZCFG(pdi->intel_alh_id)); + + conf |= (SDW_ALH_STRMZCFG_DMAT_VAL << + SDW_REG_SHIFT(SDW_ALH_STRMZCFG_DMAT)); + + conf |= ((pdi->ch_count - 1) << + SDW_REG_SHIFT(SDW_ALH_STRMZCFG_CHN)); + + intel_writel(alh, SDW_ALH_STRMZCFG(pdi->intel_alh_id), conf); +} + static int intel_prop_read(struct sdw_bus *bus) { /* Initialize with default handler to read all DisCo properties */ @@ -265,6 +410,7 @@ static struct sdw_master_ops sdw_intel_ops = { */ static int intel_probe(struct platform_device *pdev) { + struct sdw_cdns_stream_config config; struct sdw_intel *sdw; int ret; @@ -287,6 +433,9 @@ static int intel_probe(struct platform_device *pdev) sdw_intel_ops.read_prop = intel_prop_read; sdw->cdns.bus.ops = &sdw_intel_ops; + sdw_intel_ops.read_prop = intel_prop_read; + sdw->cdns.bus.ops = &sdw_intel_ops; + platform_set_drvdata(pdev, sdw); ret = sdw_add_bus_master(&sdw->cdns.bus); @@ -304,9 +453,15 @@ static int intel_probe(struct platform_device *pdev) goto err_init; ret = sdw_cdns_enable_interrupt(&sdw->cdns); + + /* Read the PDI config and initialize cadence PDI */ + intel_pdi_init(sdw, &config); + ret = sdw_cdns_pdi_init(&sdw->cdns, config); if (ret) goto err_init; + intel_pdi_ch_update(sdw); + /* Acquire IRQ */ ret = request_threaded_irq(sdw->res->irq, sdw_cdns_irq, sdw_cdns_thread, IRQF_SHARED, KBUILD_MODNAME,