Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a6399c3 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soundwire: Add support for 48x2 frame structure"

parents 780c04df 6a39fbf9
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -239,6 +239,43 @@ void swr_port_response(struct swr_master *mstr, u8 tid)
}
EXPORT_SYMBOL(swr_port_response);

/**
 * swr_slvdev_datapath_control - Enables/Disables soundwire slave device
 *                               data path
 * @dev: pointer to soundwire slave device
 * @dev_num: device number of the soundwire slave device
 *
 * Returns error code for failure and 0 for success
 */
int swr_slvdev_datapath_control(struct swr_device *dev, u8 dev_num,
				bool enable)
{
	struct swr_master *master;

	if (!dev)
		return -ENODEV;

	master = dev->master;
	if (!master)
		return -EINVAL;

	if (dev->group_id) {
		/* Broadcast */
		if (master->gr_sid != dev_num) {
			if (!master->gr_sid)
				master->gr_sid = dev_num;
			else
				return 0;
		}
	}

	if (master->slvdev_datapath_control)
		master->slvdev_datapath_control(master, enable);

	return 0;
}
EXPORT_SYMBOL(swr_slvdev_datapath_control);

/**
 * swr_connect_port - enable soundwire slave port(s)
 * @dev: pointer to soundwire slave device
+58 −14
Original line number Diff line number Diff line
@@ -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;
+2 −1
Original line number Diff line number Diff line
/* 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 */
+4 −1
Original line number Diff line number Diff line
/* 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
@@ -151,6 +151,7 @@ struct swr_master {
			  const void *buf, size_t len);
	int (*get_logical_dev_num)(struct swr_master *mstr, u64 dev_id,
				u8 *dev_num);
	void (*slvdev_datapath_control)(struct swr_master *mstr, bool enable);
};

static inline struct swr_master *to_swr_master(struct device *dev)
@@ -304,4 +305,6 @@ extern int swr_device_down(struct swr_device *swr_dev);

extern int swr_reset_device(struct swr_device *swr_dev);

extern int swr_slvdev_datapath_control(struct swr_device *swr_dev, u8 dev_num,
				       bool enable);
#endif /* _LINUX_SOUNDWIRE_H */
+7 −1
Original line number Diff line number Diff line
/*
 * 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
@@ -740,6 +740,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);
@@ -805,6 +808,9 @@ static int wsa881x_spkr_pa_event(struct snd_soc_dapm_widget *w,
			regmap_multi_reg_write(wsa881x->regmap,
					wsa881x_pre_pmu_pa,
					ARRAY_SIZE(wsa881x_pre_pmu_pa));
		swr_slvdev_datapath_control(wsa881x->swr_slave,
					    wsa881x->swr_slave->dev_num,
					    true);
		break;
	case SND_SOC_DAPM_POST_PMU:
		if (WSA881X_IS_2_0(wsa881x->version)) {