From c04712dc8f47664574d61884a2da3503113d4b4d Mon Sep 17 00:00:00 2001 From: Phani Kumar Uppalapati Date: Wed, 13 Apr 2016 00:53:11 -0700 Subject: [PATCH] soundwire: Add support for 48x2 frame structure Add support for 48x2 frame structure in soundwire so that when slave device data path is not enabled, all control messaging will happen with 48x2 frame. Soundwire slave devices send an explicit request to enable data path which in turn change the frame structure to 48x16. CRs-fixed: 996586 Change-Id: Ia4329ac982eb2a29a2b925897cd87ca9711c30e3 Signed-off-by: Phani Kumar Uppalapati --- drivers/soundwire/swr-wcd-ctrl.c | 72 +++++++++++++++++++++++++------- drivers/soundwire/swr-wcd-ctrl.h | 3 +- sound/soc/codecs/wsa881x.c | 6 +++ 3 files changed, 66 insertions(+), 15 deletions(-) diff --git a/drivers/soundwire/swr-wcd-ctrl.c b/drivers/soundwire/swr-wcd-ctrl.c index 48f647a47676..4a9dcf6fec20 100644 --- a/drivers/soundwire/swr-wcd-ctrl.c +++ b/drivers/soundwire/swr-wcd-ctrl.c @@ -601,6 +601,62 @@ static struct swr_port_info *swrm_get_port(struct swr_master *master, return port; } +static void swrm_slvdev_datapath_control(struct swr_master *master, + bool enable) +{ + u8 bank; + u32 value, n_col; + struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master); + int mask = (SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK | + SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK | + SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_BMSK); + int col_mask = SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK; + u8 active_bank; + + bank = get_inactive_bank_num(swrm); + + dev_dbg(swrm->dev, "%s: enable: %d, slvdev_dp_enable_cnt: %d\n", + __func__, enable, swrm->slvdev_dp_enable_cnt); + + if (enable) { + swrm->slvdev_dp_enable_cnt++; + active_bank = bank ? 0 : 1; + value = swrm->read(swrm->handle, + SWRM_MCP_FRAME_CTRL_BANK_ADDR(active_bank)); + if (((value & col_mask) >> + SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) == + SWR_MAX_COL) + return; + + /* set Row = 48 and col = 16 */ + n_col = SWR_MAX_COL; + } else { + /* + * Do not change to 48x2 if number of channels configured + * as stereo and if disable datapath is called for the + * first slave device + */ + swrm->slvdev_dp_enable_cnt--; + if (swrm->slvdev_dp_enable_cnt > 0) + return; + + /* set Row = 48 and col = 2 */ + n_col = SWR_MIN_COL; + } + + value = swrm->read(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank)); + value &= (~mask); + value |= ((0 << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) | + (n_col << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) | + (0 << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT)); + swrm->write(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); + + dev_dbg(swrm->dev, "%s: regaddr: 0x%x, value: 0x%x\n", __func__, + SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); + + enable_bank_switch(swrm, bank, SWR_MAX_ROW, n_col); +} + static void swrm_apply_port_config(struct swr_master *master) { u32 value; @@ -615,10 +671,6 @@ static void swrm_apply_port_config(struct swr_master *master) u32 val[SWRM_MAX_PORT_REG]; int len = 0; - int mask = (SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK | - SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK | - SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_BMSK); - if (!swrm) { pr_err("%s: Invalid handle to swr controller\n", __func__); @@ -629,15 +681,6 @@ static void swrm_apply_port_config(struct swr_master *master) dev_dbg(swrm->dev, "%s: enter bank: %d master_ports: %d\n", __func__, bank, master->num_port); - /* set Row = 48 and col = 16 */ - value = swrm->read(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank)); - value &= (~mask); - value |= ((0 << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) | - (7 << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) | - (0 << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT)); - swrm->write(swrm->handle, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); - dev_dbg(swrm->dev, "%s: regaddr: 0x%x, value: 0x%x\n", __func__, - SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value); swrm_cmd_fifo_wr_cmd(swrm, 0x01, 0xF, 0x00, SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(bank)); @@ -703,7 +746,6 @@ static void swrm_apply_port_config(struct swr_master *master) } } swrm->bulk_write(swrm->handle, reg, val, len); - enable_bank_switch(swrm, bank, SWR_MAX_ROW, SWR_MAX_COL); } static int swrm_connect_port(struct swr_master *master, @@ -1057,6 +1099,7 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm) u32 value[SWRM_MAX_INIT_REG]; int len = 0; + swrm->slvdev_dp_enable_cnt = 0; /* Clear Rows and Cols */ val = ((row_ctrl << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) | (col_ctrl << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) | @@ -1174,6 +1217,7 @@ static int swrm_probe(struct platform_device *pdev) swrm->master.get_logical_dev_num = swrm_get_logical_dev_num; swrm->master.connect_port = swrm_connect_port; swrm->master.disconnect_port = swrm_disconnect_port; + swrm->master.slvdev_datapath_control = swrm_slvdev_datapath_control; swrm->master.dev.parent = &pdev->dev; swrm->master.dev.of_node = pdev->dev.of_node; swrm->master.num_port = 0; diff --git a/drivers/soundwire/swr-wcd-ctrl.h b/drivers/soundwire/swr-wcd-ctrl.h index b5d477523315..a9248425deea 100755 --- a/drivers/soundwire/swr-wcd-ctrl.h +++ b/drivers/soundwire/swr-wcd-ctrl.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -96,6 +96,7 @@ struct swr_mstr_ctrl { struct platform_device *pdev; int num_rx_chs; u8 num_cfg_devs; + u8 slvdev_dp_enable_cnt; }; #endif /* _SWR_WCD_CTRL_H */ diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index e4fec6d79f29..e0c7a0077869 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -720,6 +720,9 @@ static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w, wsa881x_boost_ctrl(codec, ENABLE); break; case SND_SOC_DAPM_POST_PMD: + swr_slvdev_datapath_control(wsa881x->swr_slave, + wsa881x->swr_slave->dev_num, + false); if (wsa881x->boost_enable) wsa881x_boost_ctrl(codec, DISABLE); wsa881x_resource_acquire(codec, DISABLE); @@ -780,6 +783,9 @@ static int wsa881x_spkr_pa_event(struct snd_soc_dapm_widget *w, regmap_multi_reg_write(wsa881x->regmap, wsa881x_pre_pmu_pa_2_0, ARRAY_SIZE(wsa881x_pre_pmu_pa_2_0)); + swr_slvdev_datapath_control(wsa881x->swr_slave, + wsa881x->swr_slave->dev_num, + true); break; case SND_SOC_DAPM_POST_PMU: if (!wsa881x->comp_enable) {