/* Enable slimbus slave device for RX path */
int wcd9xxx_cfg_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
				unsigned int ch_cnt, unsigned int rate)
{
	u8 i = 0;
	u8  payload_tx_0 = 0, payload_tx_1 = 0, wm_payload = 0;
	u16 grph;
	u32 sph[SLIM_MAX_TX_PORTS] = {0};
	u16 ch_h[SLIM_MAX_TX_PORTS] = {0};
	u16 idx = 0, slave_port_id;
	int ret = 0;
	unsigned short  multi_chan_cfg_reg_addr;

	struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
	struct slim_ch prop;

	pr_debug("%s: ch_cnt[%d] rate[%d]\n", __func__, ch_cnt, rate);
	for (i = 0; i < ch_cnt; i++) {
		idx = (ch_num[i] - BASE_CH_NUM);
		ch_h[i] = tx[idx].ch_h;
		sph[i] = tx[idx].sph;
		slave_port_id = idx ;
		if (slave_port_id > SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS) {
			pr_err("SLIMbus: invalid slave port id: %d",
							slave_port_id);
			ret = -EINVAL;
			goto err;
		}
		/* look for the valid port range and chose the
		 *  payload accordingly
		 */
		if (slave_port_id <=
			SB_PGD_TX_PORT_MULTI_CHANNEL_0_END_PORT_ID) {
			payload_tx_0 = payload_tx_0 | (1 << slave_port_id);
		} else if (slave_port_id <=
				SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID) {
				payload_tx_1 = payload_tx_1 |
				(1 <<
				(slave_port_id -
				SB_PGD_TX_PORT_MULTI_CHANNEL_1_START_PORT_ID));
		} else {
			ret = -EINVAL;
			goto err;
		}
		multi_chan_cfg_reg_addr =
				SB_PGD_TX_PORT_MULTI_CHANNEL_0(slave_port_id);
		/* write to interface device */
		ret = wcd9xxx_interface_reg_write(wcd9xxx,
				multi_chan_cfg_reg_addr,
				payload_tx_0);
		if (ret < 0) {
			pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
								__func__,
						multi_chan_cfg_reg_addr,
						payload_tx_0, ret);
			goto err;
		}
		multi_chan_cfg_reg_addr =
				SB_PGD_TX_PORT_MULTI_CHANNEL_1(slave_port_id);
		/* ports 8,9 */
		ret = wcd9xxx_interface_reg_write(wcd9xxx,
				multi_chan_cfg_reg_addr,
				payload_tx_1);
		if (ret < 0) {
			pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
								__func__,
						multi_chan_cfg_reg_addr,
						payload_tx_1, ret);
			goto err;
		}
		/* configure the slave port for water mark and enable*/
		wm_payload = (SLAVE_PORT_WATER_MARK_VALUE <<
				SLAVE_PORT_WATER_MARK_SHIFT) +
				SLAVE_PORT_ENABLE;
		ret = wcd9xxx_interface_reg_write(wcd9xxx,
				SB_PGD_PORT_CFG_BYTE_ADDR(slave_port_id),
				wm_payload);
		if (ret < 0) {
			pr_err("%s:watermark set failure for port[%d] ret[%d]",
						__func__,
						slave_port_id, ret);
		}
	}

	/* slim_define_ch api */
	prop.prot = SLIM_AUTO_ISO;
	prop.baser = SLIM_RATE_4000HZ;
	prop.dataf = SLIM_CH_DATAF_NOT_DEFINED;
	prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
	prop.ratem = (rate/4000);
	prop.sampleszbits = 16;
	ret = slim_define_ch(wcd9xxx->slim, &prop, ch_h, ch_cnt,
					true, &grph);
	if (ret < 0) {
		pr_err("%s: slim_define_ch failed ret[%d]\n",
					__func__, ret);
		goto err;
	}
	for (i = 0; i < ch_cnt; i++) {
		ret = slim_connect_src(wcd9xxx->slim, sph[i],
							ch_h[i]);
		if (ret < 0) {
			pr_err("%s: slim_connect_src failed ret[%d]\n",
						__func__, ret);
			goto err;
		}
	}
	/* slim_control_ch */
	ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_ACTIVATE,
					true);
	if (ret < 0) {
		pr_err("%s: slim_control_ch failed ret[%d]\n",
				__func__, ret);
		goto err;
	}
	for (i = 0; i < ch_cnt; i++) {
		idx = (ch_num[i] - BASE_CH_NUM);
		tx[idx].grph = grph;
	}
	return 0;
err:
	/* release all acquired handles */
	wcd9xxx_close_slim_sch_tx(wcd9xxx, ch_num, ch_cnt);
	return ret;
}
Пример #2
0
/* Enable slimbus slave device for RX path */
int wcd9xxx_cfg_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
			    unsigned int ch_cnt, unsigned int rate)
{
	u8 i;
	u16 grph;
	u32 sph[SLIM_MAX_RX_PORTS] = {0};
	u16 ch_h[SLIM_MAX_RX_PORTS] = {0};
	u16 slave_port_id;
	u8  payload_rx = 0, wm_payload = 0;
	int ret, idx = 0;
	unsigned short  multi_chan_cfg_reg_addr;
	struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
	struct slim_ch prop;

	/* Configure slave interface device */
	pr_debug("%s: ch_cnt[%d] rate=%d\n", __func__, ch_cnt, rate);

	for (i = 0; i < ch_cnt; i++) {
		idx = (ch_num[i] - BASE_CH_NUM - sh_ch.rx_port_start_offset);
		ch_h[i] = rx[idx].ch_h;
		sph[i] = rx[idx].sph;
		slave_port_id = idx;
		pr_debug("%s: idx %d, ch_h %d, sph %d\n",
			 __func__, idx, ch_h[i], sph[i]);
		if ((slave_port_id > sh_ch.num_rx_slave_port)) {
			pr_err("Slimbus: invalid slave port id: %d",
			       slave_port_id);
			ret = -EINVAL;
			goto err;
		}
		slave_port_id += sh_ch.rx_port_start_offset;
		pr_debug("%s: slave_port_id %d\n", __func__, slave_port_id);
		/* look for the valid port range and chose the
		 * payload accordingly
		 */
		if ((slave_port_id > sh_ch.pgd_tx_port_ch_1_end_port_id) &&
		    (slave_port_id <= sh_ch.port_ch_0_end_port_id)) {
			payload_rx = payload_rx |
				(1 << (slave_port_id -
				      sh_ch.port_ch_0_start_port_id));
		} else {
			ret = -EINVAL;
			goto err;
		}

		multi_chan_cfg_reg_addr =
		    SB_PGD_RX_PORT_MULTI_CHANNEL_0(sh_ch.rx_port_ch_reg_base,
						   idx);
		pr_debug("%s: multi_chan_cfg_reg_addr 0x%x\n", __func__,
			 multi_chan_cfg_reg_addr);

		/* write to interface device */
		ret = wcd9xxx_interface_reg_write(wcd9xxx,
						  multi_chan_cfg_reg_addr,
						  payload_rx);
		if (ret < 0) {
			pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
			       __func__, multi_chan_cfg_reg_addr,
			       payload_rx, ret);
			goto err;
		}
		/* configure the slave port for water mark and enable*/
		wm_payload = (SLAVE_PORT_WATER_MARK_VALUE <<
			      SLAVE_PORT_WATER_MARK_SHIFT) + SLAVE_PORT_ENABLE;
		ret = wcd9xxx_interface_reg_write(
				wcd9xxx,
				SB_PGD_PORT_CFG_BYTE_ADDR(
				    sh_ch.port_rx_cfg_reg_base, idx),
				wm_payload);
		if (ret < 0) {
			pr_err("%s:watermark set failure for port[%d] ret[%d]",
						__func__, slave_port_id, ret);
		}
	}

	/* slim_define_ch api */
	prop.prot = SLIM_AUTO_ISO;
	prop.baser = SLIM_RATE_4000HZ;
	prop.dataf = SLIM_CH_DATAF_NOT_DEFINED;
	prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
	prop.ratem = (rate/4000);
	prop.sampleszbits = 16;

	ret = slim_define_ch(wcd9xxx->slim, &prop, ch_h, ch_cnt, true, &grph);
	if (ret < 0) {
		pr_err("%s: slim_define_ch failed ret[%d]\n",
					__func__, ret);
		goto err;
	}
	for (i = 0; i < ch_cnt; i++) {
		ret = slim_connect_sink(wcd9xxx->slim, &sph[i], 1, ch_h[i]);
		if (ret < 0) {
			pr_err("%s: slim_connect_sink failed ret[%d]\n",
						__func__, ret);
			goto err_close_slim_sch;
		}
	}
	/* slim_control_ch */
	ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_ACTIVATE, true);
	if (ret < 0) {
		pr_err("%s: slim_control_ch failed ret[%d]\n",
				__func__, ret);
		goto err_close_slim_sch;
	}
	for (i = 0; i < ch_cnt; i++) {
		idx = (ch_num[i] - BASE_CH_NUM - sh_ch.rx_port_start_offset);
		rx[idx].grph = grph;
	}
	return 0;

err_close_slim_sch:
	/*  release all acquired handles */
	wcd9xxx_close_slim_sch_rx(wcd9xxx, ch_num, ch_cnt);
err:
	return ret;
}