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

Commit 78154f63 authored by Dilip Kota's avatar Dilip Kota Committed by Naveen Kaje
Browse files

slim-msm: Configure push pull protocol on MSM Controller



Configures push pull protocol parameters on
MSM controller. It makes sure to program the
push pull protocol per channel in the framework.
Irresepective of client request, configure to
ISO protocol if channel frequency is multiple
of super frame frequency.

Change-Id: I7f9fc4d7af682d27f617d0220bab2d9b79ade6c8
Signed-off-by: default avatarDilip Kota <dkota@codeaurora.org>
Signed-off-by: default avatarNaveen Kaje <nkaje@codeaurora.org>
Signed-off-by: default avatarVidyakumar Athota <vathota@codeaurora.org>
parent 3ea36b2e
Loading
Loading
Loading
Loading
+70 −9
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/slimbus/slimbus.h>
#include <linux/msm-sps.h>
#include <linux/gcd.h>
#include "slim-msm.h"

int msm_slim_rx_enqueue(struct msm_slim_ctrl *dev, u32 *buf, u8 len)
@@ -188,12 +189,35 @@ msm_slim_sps_mem_free(struct msm_slim_ctrl *dev, struct sps_mem_buffer *mem)
	mem->phys_base = 0;
}

void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pn)
void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 port_b, u8 pn)
{
	struct slim_controller *ctrl;
	struct slim_ch *chan;
	struct msm_slim_pshpull_parm *parm;
	u32 set_cfg = DEF_WATERMARK | DEF_ALIGN | DEF_PACK | ENABLE_PORT;
	writel_relaxed(set_cfg, PGD_PORT(PGD_PORT_CFGn, pn, dev->ver));
	writel_relaxed(DEF_BLKSZ, PGD_PORT(PGD_PORT_BLKn, pn, dev->ver));
	writel_relaxed(DEF_TRANSZ, PGD_PORT(PGD_PORT_TRANn, pn, dev->ver));

	if (!dev) {
		pr_err("%s:Dev node is null\n", __func__);
		return;
	}
	if (pn >= dev->port_nums) {
		pr_err("%s:Invalid port\n", __func__);
		return;
	}
	ctrl = &dev->ctrl;
	chan = ctrl->ports[pn].ch;
	parm = &dev->pipes[pn].psh_pull;
	writel_relaxed(set_cfg, PGD_PORT(PGD_PORT_CFGn, port_b, dev->ver));
	writel_relaxed(DEF_BLKSZ, PGD_PORT(PGD_PORT_BLKn, port_b, dev->ver));
	writel_relaxed(DEF_TRANSZ, PGD_PORT(PGD_PORT_TRANn, port_b, dev->ver));

	if (chan->prot == SLIM_PUSH || chan->prot == SLIM_PULL) {
		set_cfg = 0;
		set_cfg |= ((0xFFFF & parm->num_samples)<<16);
		set_cfg |= (0xFFFF & parm->rpt_period);
		writel_relaxed(set_cfg, PGD_PORT(PGD_PORT_PSHPLLn,
							port_b, dev->ver));
	}
	/* Make sure that port registers are updated before returning */
	mb();
}
@@ -216,15 +240,49 @@ static void msm_slim_disconn_pipe_port(struct msm_slim_ctrl *dev, u8 pn)
	dev->pipes[pn].connected = false;
}

int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn)
static void msm_slim_calc_pshpull_parm(struct msm_slim_ctrl *dev,
					u8 pn, struct slim_ch *prop)
{
	struct msm_slim_endp *endpoint = &dev->pipes[pn];
	struct sps_connect *cfg = &endpoint->config;
	struct msm_slim_pshpull_parm *parm = &endpoint->psh_pull;
	int	chan_freq, round_off, divisor, super_freq;

	super_freq = dev->ctrl.a_framer->superfreq;

	if (prop->baser == SLIM_RATE_4000HZ)
		chan_freq = 4000 * prop->ratem;
	else if (prop->baser == SLIM_RATE_11025HZ)
		chan_freq = 11025 * prop->ratem;
	else
		chan_freq = prop->baser * prop->ratem;

	/*
	 * If channel frequency is multiple of super frame frequency
	 * ISO protocol is suggested
	 */
	if (!(chan_freq % super_freq)) {
		prop->prot = SLIM_HARD_ISO;
		return;
	}
	round_off = DIV_ROUND_UP(chan_freq, super_freq);
	divisor = gcd(round_off * super_freq, chan_freq);
	parm->num_samples = chan_freq/divisor;
	parm->rpt_period = (round_off * super_freq)/divisor;
}

int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn)
{
	struct msm_slim_endp *endpoint;
	struct sps_connect *cfg;
	struct slim_ch *prop;
	u32 stat;
	int ret;

	if (pn >= dev->port_nums)
	if (!dev || pn >= dev->port_nums)
		return -ENODEV;
	endpoint = &dev->pipes[pn];
	cfg = &endpoint->config;
	prop = dev->ctrl.ports[pn].ch;

	endpoint = &dev->pipes[pn];
	ret = sps_get_config(dev->pipes[pn].sps, cfg);
@@ -235,6 +293,9 @@ int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn)
	cfg->options = SPS_O_DESC_DONE | SPS_O_ERROR |
				SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;

	if (prop->prot == SLIM_PUSH || prop->prot ==  SLIM_PULL)
		msm_slim_calc_pshpull_parm(dev, pn, prop);

	if (dev->pipes[pn].connected &&
			dev->ctrl.ports[pn].state == SLIM_P_CFG) {
		return -EISCONN;
@@ -248,7 +309,7 @@ int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn)
			cfg->mode == SPS_MODE_DEST) ||
			(dev->ctrl.ports[pn].flow == SLIM_SINK &&
			 cfg->mode == SPS_MODE_SRC)) {
			msm_hw_set_port(dev, endpoint->port_b);
			msm_hw_set_port(dev, endpoint->port_b, pn);
			return 0;
		}
		msm_slim_disconn_pipe_port(dev, pn);
@@ -283,7 +344,7 @@ int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn)

	if (!ret) {
		dev->pipes[pn].connected = true;
		msm_hw_set_port(dev, endpoint->port_b);
		msm_hw_set_port(dev, endpoint->port_b, pn);
	}
	return ret;
}
+12 −1
Original line number Diff line number Diff line
@@ -197,6 +197,16 @@ struct msm_slim_sps_bam {
	int			irq;
};

/*
 * struct slim_pshpull_parm: Structure to store push pull protocol parameters
 * @num_samples: Number of samples in a period
 * @rpt_period: Repeat period value
 */
struct msm_slim_pshpull_parm {
	int		num_samples;
	int		rpt_period;
};

struct msm_slim_endp {
	struct sps_pipe			*sps;
	struct sps_connect		config;
@@ -204,6 +214,7 @@ struct msm_slim_endp {
	struct sps_mem_buffer		buf;
	bool				connected;
	int				port_b;
	struct msm_slim_pshpull_parm	psh_pull;
};

struct msm_slim_qmi {
@@ -385,7 +396,7 @@ void msm_slim_put_ctrl(struct msm_slim_ctrl *dev);
irqreturn_t msm_slim_port_irq_handler(struct msm_slim_ctrl *dev, u32 pstat);
int msm_slim_init_endpoint(struct msm_slim_ctrl *dev, struct msm_slim_endp *ep);
void msm_slim_free_endpoint(struct msm_slim_endp *ep);
void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pn);
void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pn, u8 port_no);
int msm_alloc_port(struct slim_controller *ctrl, u8 pn);
void msm_dealloc_port(struct slim_controller *ctrl, u8 pn);
int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn);
+13 −5
Original line number Diff line number Diff line
@@ -1364,8 +1364,12 @@ static int disconnect_port_ch(struct slim_controller *ctrl, u32 ph)
	ret = slim_processtxn(ctrl, &txn, false);
	if (ret)
		return ret;
	if (la == SLIM_LA_MANAGER)
	if (la == SLIM_LA_MANAGER) {
		ctrl->ports[pn].state = SLIM_P_UNCFG;
		ctrl->ports[pn].cfg.watermark = 0;
		ctrl->ports[pn].cfg.port_opts = 0;
		ctrl->ports[pn].ch = NULL;
	}
	return 0;
}

@@ -1389,6 +1393,7 @@ int slim_connect_src(struct slim_device *sb, u32 srch, u16 chanh)
	struct slim_ich *slc = &ctrl->chans[chan];
	enum slim_port_flow flow = SLIM_HDL_TO_FLOW(srch);
	u8 la = SLIM_HDL_TO_LA(srch);
	u8 pn = SLIM_HDL_TO_PORT(srch);

	/* manager ports don't have direction when they are allocated */
	if (la != SLIM_LA_MANAGER && flow != SLIM_SRC)
@@ -1397,7 +1402,6 @@ int slim_connect_src(struct slim_device *sb, u32 srch, u16 chanh)
	mutex_lock(&ctrl->sched.m_reconf);

	if (la == SLIM_LA_MANAGER) {
		u8 pn = SLIM_HDL_TO_PORT(srch);
		if (pn >= ctrl->nports ||
			ctrl->ports[pn].state != SLIM_P_UNCFG) {
			ret = -EINVAL;
@@ -1418,7 +1422,7 @@ int slim_connect_src(struct slim_device *sb, u32 srch, u16 chanh)
		ret = -EALREADY;
		goto connect_src_err;
	}

	ctrl->ports[pn].ch = &slc->prop;
	ret = connect_port_ch(ctrl, chan, srch, SLIM_SRC);

	if (!ret)
@@ -1477,8 +1481,10 @@ int slim_connect_sink(struct slim_device *sb, u32 *sinkh, int nsink, u16 chanh)
				(pn >= ctrl->nports ||
				ctrl->ports[pn].state != SLIM_P_UNCFG))
				ret = -EINVAL;
		else
		else {
			ctrl->ports[pn].ch = &slc->prop;
			ret = connect_port_ch(ctrl, chan, sinkh[j], SLIM_SINK);
		}
		if (ret) {
			for (j = j - 1; j >= 0; j--)
				disconnect_port_ch(ctrl, sinkh[j]);
@@ -1671,8 +1677,10 @@ static int slim_remove_ch(struct slim_controller *ctrl, struct slim_ich *slc)
		 * disconnect. It is client's responsibility to call disconnect
		 * on ports owned by the slave device
		 */
		if (la == SLIM_LA_MANAGER)
		if (la == SLIM_LA_MANAGER) {
			ctrl->ports[SLIM_HDL_TO_PORT(ph)].state = SLIM_P_UNCFG;
			ctrl->ports[SLIM_HDL_TO_PORT(ph)].ch = NULL;
		}
	}

	ph = slc->srch;