Linux Audio

Check our new training course

Loading...
v6.2
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// Socionext UniPhier AIO ALSA common driver.
   4//
   5// Copyright (c) 2016-2018 Socionext Inc.
   6
   7#include <linux/bitfield.h>
   8#include <linux/errno.h>
   9#include <linux/kernel.h>
  10#include <linux/module.h>
  11#include <sound/core.h>
  12#include <sound/pcm.h>
  13#include <sound/pcm_params.h>
  14#include <sound/soc.h>
  15
  16#include "aio.h"
  17#include "aio-reg.h"
  18
  19static u64 rb_cnt(u64 wr, u64 rd, u64 len)
  20{
  21	if (rd <= wr)
  22		return wr - rd;
  23	else
  24		return len - (rd - wr);
  25}
  26
  27static u64 rb_cnt_to_end(u64 wr, u64 rd, u64 len)
  28{
  29	if (rd <= wr)
  30		return wr - rd;
  31	else
  32		return len - rd;
  33}
  34
  35static u64 rb_space(u64 wr, u64 rd, u64 len)
  36{
  37	if (rd <= wr)
  38		return len - (wr - rd) - 8;
  39	else
  40		return rd - wr - 8;
  41}
  42
  43static u64 rb_space_to_end(u64 wr, u64 rd, u64 len)
  44{
  45	if (rd > wr)
  46		return rd - wr - 8;
  47	else if (rd > 0)
  48		return len - wr;
  49	else
  50		return len - wr - 8;
  51}
  52
  53u64 aio_rb_cnt(struct uniphier_aio_sub *sub)
  54{
  55	return rb_cnt(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
  56}
  57
  58u64 aio_rbt_cnt_to_end(struct uniphier_aio_sub *sub)
  59{
  60	return rb_cnt_to_end(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
  61}
  62
  63u64 aio_rb_space(struct uniphier_aio_sub *sub)
  64{
  65	return rb_space(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
  66}
  67
  68u64 aio_rb_space_to_end(struct uniphier_aio_sub *sub)
  69{
  70	return rb_space_to_end(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
  71}
  72
  73/**
  74 * aio_iecout_set_enable - setup IEC output via SoC glue
  75 * @chip: the AIO chip pointer
  76 * @enable: false to stop the output, true to start
  77 *
  78 * Set enabled or disabled S/PDIF signal output to out of SoC via AOnIEC pins.
  79 * This function need to call at driver startup.
  80 *
  81 * The regmap of SoC glue is specified by 'socionext,syscon' optional property
  82 * of DT. This function has no effect if no property.
  83 */
  84void aio_iecout_set_enable(struct uniphier_aio_chip *chip, bool enable)
  85{
  86	struct regmap *r = chip->regmap_sg;
  87
  88	if (!r)
  89		return;
  90
  91	regmap_write(r, SG_AOUTEN, (enable) ? ~0 : 0);
  92}
  93
  94/**
  95 * aio_chip_set_pll - set frequency to audio PLL
  96 * @chip: the AIO chip pointer
  97 * @pll_id: PLL
  98 * @freq: frequency in Hz, 0 is ignored
  99 *
 100 * Sets frequency of audio PLL. This function can be called anytime,
 101 * but it takes time till PLL is locked.
 102 *
 103 * Return: Zero if successful, otherwise a negative value on error.
 104 */
 105int aio_chip_set_pll(struct uniphier_aio_chip *chip, int pll_id,
 106		     unsigned int freq)
 107{
 108	struct device *dev = &chip->pdev->dev;
 109	struct regmap *r = chip->regmap;
 110	int shift;
 111	u32 v;
 112
 113	/* Not change */
 114	if (freq == 0)
 115		return 0;
 116
 117	switch (pll_id) {
 118	case AUD_PLL_A1:
 119		shift = 0;
 120		break;
 121	case AUD_PLL_F1:
 122		shift = 1;
 123		break;
 124	case AUD_PLL_A2:
 125		shift = 2;
 126		break;
 127	case AUD_PLL_F2:
 128		shift = 3;
 129		break;
 130	default:
 131		dev_err(dev, "PLL(%d) not supported\n", pll_id);
 132		return -EINVAL;
 133	}
 134
 135	switch (freq) {
 136	case 36864000:
 137		v = A2APLLCTR1_APLLX_36MHZ;
 138		break;
 139	case 33868800:
 140		v = A2APLLCTR1_APLLX_33MHZ;
 141		break;
 142	default:
 143		dev_err(dev, "PLL frequency not supported(%d)\n", freq);
 144		return -EINVAL;
 145	}
 146	chip->plls[pll_id].freq = freq;
 147
 148	regmap_update_bits(r, A2APLLCTR1, A2APLLCTR1_APLLX_MASK << shift,
 149			   v << shift);
 150
 151	return 0;
 152}
 153
 154/**
 155 * aio_chip_init - initialize AIO whole settings
 156 * @chip: the AIO chip pointer
 157 *
 158 * Sets AIO fixed and whole device settings to AIO.
 159 * This function need to call once at driver startup.
 160 *
 161 * The register area that is changed by this function is shared by all
 162 * modules of AIO. But there is not race condition since this function
 163 * has always set the same initialize values.
 164 */
 165void aio_chip_init(struct uniphier_aio_chip *chip)
 166{
 167	struct regmap *r = chip->regmap;
 168
 169	regmap_update_bits(r, A2APLLCTR0,
 170			   A2APLLCTR0_APLLXPOW_MASK,
 171			   A2APLLCTR0_APLLXPOW_PWON);
 172
 173	regmap_update_bits(r, A2EXMCLKSEL0,
 174			   A2EXMCLKSEL0_EXMCLK_MASK,
 175			   A2EXMCLKSEL0_EXMCLK_OUTPUT);
 176
 177	regmap_update_bits(r, A2AIOINPUTSEL, A2AIOINPUTSEL_RXSEL_MASK,
 178			   A2AIOINPUTSEL_RXSEL_PCMI1_HDMIRX1 |
 179			   A2AIOINPUTSEL_RXSEL_PCMI2_SIF |
 180			   A2AIOINPUTSEL_RXSEL_PCMI3_EVEA |
 181			   A2AIOINPUTSEL_RXSEL_IECI1_HDMIRX1);
 182
 183	if (chip->chip_spec->addr_ext)
 184		regmap_update_bits(r, CDA2D_TEST, CDA2D_TEST_DDR_MODE_MASK,
 185				   CDA2D_TEST_DDR_MODE_EXTON0);
 186	else
 187		regmap_update_bits(r, CDA2D_TEST, CDA2D_TEST_DDR_MODE_MASK,
 188				   CDA2D_TEST_DDR_MODE_EXTOFF1);
 189}
 190
 191/**
 192 * aio_init - initialize AIO substream
 193 * @sub: the AIO substream pointer
 194 *
 195 * Sets fixed settings of each AIO substreams.
 196 * This function need to call once at substream startup.
 197 *
 198 * Return: Zero if successful, otherwise a negative value on error.
 199 */
 200int aio_init(struct uniphier_aio_sub *sub)
 201{
 202	struct device *dev = &sub->aio->chip->pdev->dev;
 203	struct regmap *r = sub->aio->chip->regmap;
 204
 205	regmap_write(r, A2RBNMAPCTR0(sub->swm->rb.hw),
 206		     MAPCTR0_EN | sub->swm->rb.map);
 207	regmap_write(r, A2CHNMAPCTR0(sub->swm->ch.hw),
 208		     MAPCTR0_EN | sub->swm->ch.map);
 209
 210	switch (sub->swm->type) {
 211	case PORT_TYPE_I2S:
 212	case PORT_TYPE_SPDIF:
 213	case PORT_TYPE_EVE:
 214		if (sub->swm->dir == PORT_DIR_INPUT) {
 215			regmap_write(r, A2IIFNMAPCTR0(sub->swm->iif.hw),
 216				     MAPCTR0_EN | sub->swm->iif.map);
 217			regmap_write(r, A2IPORTNMAPCTR0(sub->swm->iport.hw),
 218				     MAPCTR0_EN | sub->swm->iport.map);
 219		} else {
 220			regmap_write(r, A2OIFNMAPCTR0(sub->swm->oif.hw),
 221				     MAPCTR0_EN | sub->swm->oif.map);
 222			regmap_write(r, A2OPORTNMAPCTR0(sub->swm->oport.hw),
 223				     MAPCTR0_EN | sub->swm->oport.map);
 224		}
 225		break;
 226	case PORT_TYPE_CONV:
 227		regmap_write(r, A2OIFNMAPCTR0(sub->swm->oif.hw),
 228			     MAPCTR0_EN | sub->swm->oif.map);
 229		regmap_write(r, A2OPORTNMAPCTR0(sub->swm->oport.hw),
 230			     MAPCTR0_EN | sub->swm->oport.map);
 231		regmap_write(r, A2CHNMAPCTR0(sub->swm->och.hw),
 232			     MAPCTR0_EN | sub->swm->och.map);
 233		regmap_write(r, A2IIFNMAPCTR0(sub->swm->iif.hw),
 234			     MAPCTR0_EN | sub->swm->iif.map);
 235		break;
 236	default:
 237		dev_err(dev, "Unknown port type %d.\n", sub->swm->type);
 238		return -EINVAL;
 239	}
 240
 241	return 0;
 242}
 243
 244/**
 245 * aio_port_reset - reset AIO port block
 246 * @sub: the AIO substream pointer
 247 *
 248 * Resets the digital signal input/output port block of AIO.
 249 */
 250void aio_port_reset(struct uniphier_aio_sub *sub)
 251{
 252	struct regmap *r = sub->aio->chip->regmap;
 253
 254	if (sub->swm->dir == PORT_DIR_OUTPUT) {
 255		regmap_write(r, AOUTRSTCTR0, BIT(sub->swm->oport.map));
 256		regmap_write(r, AOUTRSTCTR1, BIT(sub->swm->oport.map));
 257	} else {
 258		regmap_update_bits(r, IPORTMXRSTCTR(sub->swm->iport.map),
 259				   IPORTMXRSTCTR_RSTPI_MASK,
 260				   IPORTMXRSTCTR_RSTPI_RESET);
 261		regmap_update_bits(r, IPORTMXRSTCTR(sub->swm->iport.map),
 262				   IPORTMXRSTCTR_RSTPI_MASK,
 263				   IPORTMXRSTCTR_RSTPI_RELEASE);
 264	}
 265}
 266
 267/**
 268 * aio_port_set_ch - set channels of LPCM
 269 * @sub: the AIO substream pointer, PCM substream only
 270 *
 271 * Set suitable slot selecting to input/output port block of AIO.
 272 *
 273 * This function may return error if non-PCM substream.
 274 *
 275 * Return: Zero if successful, otherwise a negative value on error.
 276 */
 277static int aio_port_set_ch(struct uniphier_aio_sub *sub)
 278{
 279	struct regmap *r = sub->aio->chip->regmap;
 280	static const u32 slotsel_2ch[] = {
 281		0, 0, 0, 0, 0,
 282	};
 283	static const u32 slotsel_multi[] = {
 284		OPORTMXTYSLOTCTR_SLOTSEL_SLOT0,
 285		OPORTMXTYSLOTCTR_SLOTSEL_SLOT1,
 286		OPORTMXTYSLOTCTR_SLOTSEL_SLOT2,
 287		OPORTMXTYSLOTCTR_SLOTSEL_SLOT3,
 288		OPORTMXTYSLOTCTR_SLOTSEL_SLOT4,
 289	};
 290	u32 mode;
 291	const u32 *slotsel;
 292	int i;
 293
 294	switch (params_channels(&sub->params)) {
 295	case 8:
 296	case 6:
 297		mode = OPORTMXTYSLOTCTR_MODE;
 298		slotsel = slotsel_multi;
 299		break;
 300	case 2:
 301		mode = 0;
 302		slotsel = slotsel_2ch;
 303		break;
 304	default:
 305		return -EINVAL;
 306	}
 307
 308	for (i = 0; i < AUD_MAX_SLOTSEL; i++) {
 309		regmap_update_bits(r, OPORTMXTYSLOTCTR(sub->swm->oport.map, i),
 310				   OPORTMXTYSLOTCTR_MODE, mode);
 311		regmap_update_bits(r, OPORTMXTYSLOTCTR(sub->swm->oport.map, i),
 312				   OPORTMXTYSLOTCTR_SLOTSEL_MASK, slotsel[i]);
 313	}
 314
 315	return 0;
 316}
 317
 318/**
 319 * aio_port_set_rate - set sampling rate of LPCM
 320 * @sub: the AIO substream pointer, PCM substream only
 321 * @rate: Sampling rate in Hz.
 322 *
 323 * Set suitable I2S format settings to input/output port block of AIO.
 324 * Parameter is specified by hw_params().
 325 *
 326 * This function may return error if non-PCM substream.
 327 *
 328 * Return: Zero if successful, otherwise a negative value on error.
 329 */
 330static int aio_port_set_rate(struct uniphier_aio_sub *sub, int rate)
 331{
 332	struct regmap *r = sub->aio->chip->regmap;
 333	struct device *dev = &sub->aio->chip->pdev->dev;
 334	u32 v;
 335
 336	if (sub->swm->dir == PORT_DIR_OUTPUT) {
 337		switch (rate) {
 338		case 8000:
 339			v = OPORTMXCTR1_FSSEL_8;
 340			break;
 341		case 11025:
 342			v = OPORTMXCTR1_FSSEL_11_025;
 343			break;
 344		case 12000:
 345			v = OPORTMXCTR1_FSSEL_12;
 346			break;
 347		case 16000:
 348			v = OPORTMXCTR1_FSSEL_16;
 349			break;
 350		case 22050:
 351			v = OPORTMXCTR1_FSSEL_22_05;
 352			break;
 353		case 24000:
 354			v = OPORTMXCTR1_FSSEL_24;
 355			break;
 356		case 32000:
 357			v = OPORTMXCTR1_FSSEL_32;
 358			break;
 359		case 44100:
 360			v = OPORTMXCTR1_FSSEL_44_1;
 361			break;
 362		case 48000:
 363			v = OPORTMXCTR1_FSSEL_48;
 364			break;
 365		case 88200:
 366			v = OPORTMXCTR1_FSSEL_88_2;
 367			break;
 368		case 96000:
 369			v = OPORTMXCTR1_FSSEL_96;
 370			break;
 371		case 176400:
 372			v = OPORTMXCTR1_FSSEL_176_4;
 373			break;
 374		case 192000:
 375			v = OPORTMXCTR1_FSSEL_192;
 376			break;
 377		default:
 378			dev_err(dev, "Rate not supported(%d)\n", rate);
 379			return -EINVAL;
 380		}
 381
 382		regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map),
 383				   OPORTMXCTR1_FSSEL_MASK, v);
 384	} else {
 385		switch (rate) {
 386		case 8000:
 387			v = IPORTMXCTR1_FSSEL_8;
 388			break;
 389		case 11025:
 390			v = IPORTMXCTR1_FSSEL_11_025;
 391			break;
 392		case 12000:
 393			v = IPORTMXCTR1_FSSEL_12;
 394			break;
 395		case 16000:
 396			v = IPORTMXCTR1_FSSEL_16;
 397			break;
 398		case 22050:
 399			v = IPORTMXCTR1_FSSEL_22_05;
 400			break;
 401		case 24000:
 402			v = IPORTMXCTR1_FSSEL_24;
 403			break;
 404		case 32000:
 405			v = IPORTMXCTR1_FSSEL_32;
 406			break;
 407		case 44100:
 408			v = IPORTMXCTR1_FSSEL_44_1;
 409			break;
 410		case 48000:
 411			v = IPORTMXCTR1_FSSEL_48;
 412			break;
 413		case 88200:
 414			v = IPORTMXCTR1_FSSEL_88_2;
 415			break;
 416		case 96000:
 417			v = IPORTMXCTR1_FSSEL_96;
 418			break;
 419		case 176400:
 420			v = IPORTMXCTR1_FSSEL_176_4;
 421			break;
 422		case 192000:
 423			v = IPORTMXCTR1_FSSEL_192;
 424			break;
 425		default:
 426			dev_err(dev, "Rate not supported(%d)\n", rate);
 427			return -EINVAL;
 428		}
 429
 430		regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
 431				   IPORTMXCTR1_FSSEL_MASK, v);
 432	}
 433
 434	return 0;
 435}
 436
 437/**
 438 * aio_port_set_fmt - set format of I2S data
 439 * @sub: the AIO substream pointer, PCM substream only
 440 * This parameter has no effect if substream is I2S or PCM.
 441 *
 442 * Set suitable I2S format settings to input/output port block of AIO.
 443 * Parameter is specified by set_fmt().
 444 *
 445 * This function may return error if non-PCM substream.
 446 *
 447 * Return: Zero if successful, otherwise a negative value on error.
 448 */
 449static int aio_port_set_fmt(struct uniphier_aio_sub *sub)
 450{
 451	struct regmap *r = sub->aio->chip->regmap;
 452	struct device *dev = &sub->aio->chip->pdev->dev;
 453	u32 v;
 454
 455	if (sub->swm->dir == PORT_DIR_OUTPUT) {
 456		switch (sub->aio->fmt) {
 457		case SND_SOC_DAIFMT_LEFT_J:
 458			v = OPORTMXCTR1_I2SLRSEL_LEFT;
 459			break;
 460		case SND_SOC_DAIFMT_RIGHT_J:
 461			v = OPORTMXCTR1_I2SLRSEL_RIGHT;
 462			break;
 463		case SND_SOC_DAIFMT_I2S:
 464			v = OPORTMXCTR1_I2SLRSEL_I2S;
 465			break;
 466		default:
 467			dev_err(dev, "Format is not supported(%d)\n",
 468				sub->aio->fmt);
 469			return -EINVAL;
 470		}
 471
 472		v |= OPORTMXCTR1_OUTBITSEL_24;
 473		regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map),
 474				   OPORTMXCTR1_I2SLRSEL_MASK |
 475				   OPORTMXCTR1_OUTBITSEL_MASK, v);
 476	} else {
 477		switch (sub->aio->fmt) {
 478		case SND_SOC_DAIFMT_LEFT_J:
 479			v = IPORTMXCTR1_LRSEL_LEFT;
 480			break;
 481		case SND_SOC_DAIFMT_RIGHT_J:
 482			v = IPORTMXCTR1_LRSEL_RIGHT;
 483			break;
 484		case SND_SOC_DAIFMT_I2S:
 485			v = IPORTMXCTR1_LRSEL_I2S;
 486			break;
 487		default:
 488			dev_err(dev, "Format is not supported(%d)\n",
 489				sub->aio->fmt);
 490			return -EINVAL;
 491		}
 492
 493		v |= IPORTMXCTR1_OUTBITSEL_24 |
 494			IPORTMXCTR1_CHSEL_ALL;
 495		regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
 496				   IPORTMXCTR1_LRSEL_MASK |
 497				   IPORTMXCTR1_OUTBITSEL_MASK |
 498				   IPORTMXCTR1_CHSEL_MASK, v);
 499	}
 500
 501	return 0;
 502}
 503
 504/**
 505 * aio_port_set_clk - set clock and divider of AIO port block
 506 * @sub: the AIO substream pointer
 507 *
 508 * Set suitable PLL clock divider and relational settings to
 509 * input/output port block of AIO. Parameters are specified by
 510 * set_sysclk() and set_pll().
 511 *
 512 * Return: Zero if successful, otherwise a negative value on error.
 513 */
 514static int aio_port_set_clk(struct uniphier_aio_sub *sub)
 515{
 516	struct uniphier_aio_chip *chip = sub->aio->chip;
 517	struct device *dev = &sub->aio->chip->pdev->dev;
 518	struct regmap *r = sub->aio->chip->regmap;
 519	static const u32 v_pll[] = {
 520		OPORTMXCTR2_ACLKSEL_A1, OPORTMXCTR2_ACLKSEL_F1,
 521		OPORTMXCTR2_ACLKSEL_A2, OPORTMXCTR2_ACLKSEL_F2,
 522		OPORTMXCTR2_ACLKSEL_A2PLL,
 523		OPORTMXCTR2_ACLKSEL_RX1,
 524	};
 525	static const u32 v_div[] = {
 526		OPORTMXCTR2_DACCKSEL_1_2, OPORTMXCTR2_DACCKSEL_1_3,
 527		OPORTMXCTR2_DACCKSEL_1_1, OPORTMXCTR2_DACCKSEL_2_3,
 528	};
 529	u32 v;
 530
 531	if (sub->swm->dir == PORT_DIR_OUTPUT) {
 532		if (sub->swm->type == PORT_TYPE_I2S) {
 533			if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) {
 534				dev_err(dev, "PLL(%d) is invalid\n",
 535					sub->aio->pll_out);
 536				return -EINVAL;
 537			}
 538			if (sub->aio->plldiv >= ARRAY_SIZE(v_div)) {
 539				dev_err(dev, "PLL divider(%d) is invalid\n",
 540					sub->aio->plldiv);
 541				return -EINVAL;
 542			}
 543
 544			v = v_pll[sub->aio->pll_out] |
 545				OPORTMXCTR2_MSSEL_MASTER |
 546				v_div[sub->aio->plldiv];
 547
 548			switch (chip->plls[sub->aio->pll_out].freq) {
 549			case 0:
 550			case 36864000:
 551			case 33868800:
 552				v |= OPORTMXCTR2_EXTLSIFSSEL_36;
 553				break;
 554			default:
 555				v |= OPORTMXCTR2_EXTLSIFSSEL_24;
 556				break;
 557			}
 558		} else if (sub->swm->type == PORT_TYPE_EVE) {
 559			v = OPORTMXCTR2_ACLKSEL_A2PLL |
 560				OPORTMXCTR2_MSSEL_MASTER |
 561				OPORTMXCTR2_EXTLSIFSSEL_36 |
 562				OPORTMXCTR2_DACCKSEL_1_2;
 563		} else if (sub->swm->type == PORT_TYPE_SPDIF) {
 564			if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) {
 565				dev_err(dev, "PLL(%d) is invalid\n",
 566					sub->aio->pll_out);
 567				return -EINVAL;
 568			}
 569			v = v_pll[sub->aio->pll_out] |
 570				OPORTMXCTR2_MSSEL_MASTER |
 571				OPORTMXCTR2_DACCKSEL_1_2;
 572
 573			switch (chip->plls[sub->aio->pll_out].freq) {
 574			case 0:
 575			case 36864000:
 576			case 33868800:
 577				v |= OPORTMXCTR2_EXTLSIFSSEL_36;
 578				break;
 579			default:
 580				v |= OPORTMXCTR2_EXTLSIFSSEL_24;
 581				break;
 582			}
 583		} else {
 584			v = OPORTMXCTR2_ACLKSEL_A1 |
 585				OPORTMXCTR2_MSSEL_MASTER |
 586				OPORTMXCTR2_EXTLSIFSSEL_36 |
 587				OPORTMXCTR2_DACCKSEL_1_2;
 588		}
 589		regmap_write(r, OPORTMXCTR2(sub->swm->oport.map), v);
 590	} else {
 591		v = IPORTMXCTR2_ACLKSEL_A1 |
 592			IPORTMXCTR2_MSSEL_SLAVE |
 593			IPORTMXCTR2_EXTLSIFSSEL_36 |
 594			IPORTMXCTR2_DACCKSEL_1_2;
 595		regmap_write(r, IPORTMXCTR2(sub->swm->iport.map), v);
 596	}
 597
 598	return 0;
 599}
 600
 601/**
 602 * aio_port_set_param - set parameters of AIO port block
 603 * @sub: the AIO substream pointer
 604 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM.
 605 * This parameter has no effect if substream is I2S or PCM.
 606 * @params: hardware parameters of ALSA
 607 *
 608 * Set suitable setting to input/output port block of AIO to process the
 609 * specified in params.
 610 *
 611 * Return: Zero if successful, otherwise a negative value on error.
 612 */
 613int aio_port_set_param(struct uniphier_aio_sub *sub, int pass_through,
 614		       const struct snd_pcm_hw_params *params)
 615{
 616	struct regmap *r = sub->aio->chip->regmap;
 617	unsigned int rate;
 618	u32 v;
 619	int ret;
 620
 621	if (!pass_through) {
 622		if (sub->swm->type == PORT_TYPE_EVE ||
 623		    sub->swm->type == PORT_TYPE_CONV) {
 624			rate = 48000;
 625		} else {
 626			rate = params_rate(params);
 627		}
 628
 629		ret = aio_port_set_ch(sub);
 630		if (ret)
 631			return ret;
 632
 633		ret = aio_port_set_rate(sub, rate);
 634		if (ret)
 635			return ret;
 636
 637		ret = aio_port_set_fmt(sub);
 638		if (ret)
 639			return ret;
 640	}
 641
 642	ret = aio_port_set_clk(sub);
 643	if (ret)
 644		return ret;
 645
 646	if (sub->swm->dir == PORT_DIR_OUTPUT) {
 647		if (pass_through)
 648			v = OPORTMXCTR3_SRCSEL_STREAM |
 649				OPORTMXCTR3_VALID_STREAM;
 650		else
 651			v = OPORTMXCTR3_SRCSEL_PCM |
 652				OPORTMXCTR3_VALID_PCM;
 653
 654		v |= OPORTMXCTR3_IECTHUR_IECOUT |
 655			OPORTMXCTR3_PMSEL_PAUSE |
 656			OPORTMXCTR3_PMSW_MUTE_OFF;
 657		regmap_write(r, OPORTMXCTR3(sub->swm->oport.map), v);
 658	} else {
 659		regmap_write(r, IPORTMXACLKSEL0EX(sub->swm->iport.map),
 660			     IPORTMXACLKSEL0EX_ACLKSEL0EX_INTERNAL);
 661		regmap_write(r, IPORTMXEXNOE(sub->swm->iport.map),
 662			     IPORTMXEXNOE_PCMINOE_INPUT);
 663	}
 664
 665	return 0;
 666}
 667
 668/**
 669 * aio_port_set_enable - start or stop of AIO port block
 670 * @sub: the AIO substream pointer
 671 * @enable: zero to stop the block, otherwise to start
 672 *
 673 * Start or stop the signal input/output port block of AIO.
 674 */
 675void aio_port_set_enable(struct uniphier_aio_sub *sub, int enable)
 676{
 677	struct regmap *r = sub->aio->chip->regmap;
 678
 679	if (sub->swm->dir == PORT_DIR_OUTPUT) {
 680		regmap_write(r, OPORTMXPATH(sub->swm->oport.map),
 681			     sub->swm->oif.map);
 682
 683		regmap_update_bits(r, OPORTMXMASK(sub->swm->oport.map),
 684				   OPORTMXMASK_IUDXMSK_MASK |
 685				   OPORTMXMASK_IUXCKMSK_MASK |
 686				   OPORTMXMASK_DXMSK_MASK |
 687				   OPORTMXMASK_XCKMSK_MASK,
 688				   OPORTMXMASK_IUDXMSK_OFF |
 689				   OPORTMXMASK_IUXCKMSK_OFF |
 690				   OPORTMXMASK_DXMSK_OFF |
 691				   OPORTMXMASK_XCKMSK_OFF);
 692
 693		if (enable)
 694			regmap_write(r, AOUTENCTR0, BIT(sub->swm->oport.map));
 695		else
 696			regmap_write(r, AOUTENCTR1, BIT(sub->swm->oport.map));
 697	} else {
 698		regmap_update_bits(r, IPORTMXMASK(sub->swm->iport.map),
 699				   IPORTMXMASK_IUXCKMSK_MASK |
 700				   IPORTMXMASK_XCKMSK_MASK,
 701				   IPORTMXMASK_IUXCKMSK_OFF |
 702				   IPORTMXMASK_XCKMSK_OFF);
 703
 704		if (enable)
 705			regmap_update_bits(r,
 706					   IPORTMXCTR2(sub->swm->iport.map),
 707					   IPORTMXCTR2_REQEN_MASK,
 708					   IPORTMXCTR2_REQEN_ENABLE);
 709		else
 710			regmap_update_bits(r,
 711					   IPORTMXCTR2(sub->swm->iport.map),
 712					   IPORTMXCTR2_REQEN_MASK,
 713					   IPORTMXCTR2_REQEN_DISABLE);
 714	}
 715}
 716
 717/**
 718 * aio_port_get_volume - get volume of AIO port block
 719 * @sub: the AIO substream pointer
 720 *
 721 * Return: current volume, range is 0x0000 - 0xffff
 722 */
 723int aio_port_get_volume(struct uniphier_aio_sub *sub)
 724{
 725	struct regmap *r = sub->aio->chip->regmap;
 726	u32 v;
 727
 728	regmap_read(r, OPORTMXTYVOLGAINSTATUS(sub->swm->oport.map, 0), &v);
 729
 730	return FIELD_GET(OPORTMXTYVOLGAINSTATUS_CUR_MASK, v);
 731}
 732
 733/**
 734 * aio_port_set_volume - set volume of AIO port block
 735 * @sub: the AIO substream pointer
 736 * @vol: target volume, range is 0x0000 - 0xffff.
 737 *
 738 * Change digital volume and perfome fade-out/fade-in effect for specified
 739 * output slot of port. Gained PCM value can calculate as the following:
 740 *   Gained = Original * vol / 0x4000
 741 */
 742void aio_port_set_volume(struct uniphier_aio_sub *sub, int vol)
 743{
 744	struct regmap *r = sub->aio->chip->regmap;
 745	int oport_map = sub->swm->oport.map;
 746	int cur, diff, slope = 0, fs;
 747
 748	if (sub->swm->dir == PORT_DIR_INPUT)
 749		return;
 750
 751	cur = aio_port_get_volume(sub);
 752	diff = abs(vol - cur);
 753	fs = params_rate(&sub->params);
 754	if (fs)
 755		slope = diff / AUD_VOL_FADE_TIME * 1000 / fs;
 756	slope = max(1, slope);
 757
 758	regmap_update_bits(r, OPORTMXTYVOLPARA1(oport_map, 0),
 759			   OPORTMXTYVOLPARA1_SLOPEU_MASK, slope << 16);
 760	regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
 761			   OPORTMXTYVOLPARA2_TARGET_MASK, vol);
 762
 763	if (cur < vol)
 764		regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
 765				   OPORTMXTYVOLPARA2_FADE_MASK,
 766				   OPORTMXTYVOLPARA2_FADE_FADEIN);
 767	else
 768		regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
 769				   OPORTMXTYVOLPARA2_FADE_MASK,
 770				   OPORTMXTYVOLPARA2_FADE_FADEOUT);
 771
 772	regmap_write(r, AOUTFADECTR0, BIT(oport_map));
 773}
 774
 775/**
 776 * aio_if_set_param - set parameters of AIO DMA I/F block
 777 * @sub: the AIO substream pointer
 778 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM.
 779 * This parameter has no effect if substream is I2S or PCM.
 780 *
 781 * Set suitable setting to DMA interface block of AIO to process the
 782 * specified in settings.
 783 *
 784 * Return: Zero if successful, otherwise a negative value on error.
 785 */
 786int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through)
 787{
 788	struct regmap *r = sub->aio->chip->regmap;
 789	u32 memfmt, v;
 790
 791	if (sub->swm->dir == PORT_DIR_OUTPUT) {
 792		if (pass_through) {
 793			v = PBOUTMXCTR0_ENDIAN_0123 |
 794				PBOUTMXCTR0_MEMFMT_STREAM;
 795		} else {
 796			switch (params_channels(&sub->params)) {
 797			case 2:
 798				memfmt = PBOUTMXCTR0_MEMFMT_2CH;
 799				break;
 800			case 6:
 801				memfmt = PBOUTMXCTR0_MEMFMT_6CH;
 802				break;
 803			case 8:
 804				memfmt = PBOUTMXCTR0_MEMFMT_8CH;
 805				break;
 806			default:
 807				return -EINVAL;
 808			}
 809			v = PBOUTMXCTR0_ENDIAN_3210 | memfmt;
 810		}
 811
 812		regmap_write(r, PBOUTMXCTR0(sub->swm->oif.map), v);
 813		regmap_write(r, PBOUTMXCTR1(sub->swm->oif.map), 0);
 814	} else {
 815		regmap_write(r, PBINMXCTR(sub->swm->iif.map),
 816			     PBINMXCTR_NCONNECT_CONNECT |
 817			     PBINMXCTR_INOUTSEL_IN |
 818			     (sub->swm->iport.map << PBINMXCTR_PBINSEL_SHIFT) |
 819			     PBINMXCTR_ENDIAN_3210 |
 820			     PBINMXCTR_MEMFMT_D0);
 821	}
 822
 823	return 0;
 824}
 825
 826/**
 827 * aio_oport_set_stream_type - set parameters of AIO playback port block
 828 * @sub: the AIO substream pointer
 829 * @pc: Pc type of IEC61937
 830 *
 831 * Set special setting to output port block of AIO to output the stream
 832 * via S/PDIF.
 833 *
 834 * Return: Zero if successful, otherwise a negative value on error.
 835 */
 836int aio_oport_set_stream_type(struct uniphier_aio_sub *sub,
 837			      enum IEC61937_PC pc)
 838{
 839	struct regmap *r = sub->aio->chip->regmap;
 840	u32 repet = 0, pause = OPORTMXPAUDAT_PAUSEPC_CMN;
 
 841
 842	switch (pc) {
 843	case IEC61937_PC_AC3:
 844		repet = OPORTMXREPET_STRLENGTH_AC3 |
 845			OPORTMXREPET_PMLENGTH_AC3;
 846		pause |= OPORTMXPAUDAT_PAUSEPD_AC3;
 847		break;
 848	case IEC61937_PC_MPA:
 849		repet = OPORTMXREPET_STRLENGTH_MPA |
 850			OPORTMXREPET_PMLENGTH_MPA;
 851		pause |= OPORTMXPAUDAT_PAUSEPD_MPA;
 852		break;
 853	case IEC61937_PC_MP3:
 854		repet = OPORTMXREPET_STRLENGTH_MP3 |
 855			OPORTMXREPET_PMLENGTH_MP3;
 856		pause |= OPORTMXPAUDAT_PAUSEPD_MP3;
 857		break;
 858	case IEC61937_PC_DTS1:
 859		repet = OPORTMXREPET_STRLENGTH_DTS1 |
 860			OPORTMXREPET_PMLENGTH_DTS1;
 861		pause |= OPORTMXPAUDAT_PAUSEPD_DTS1;
 862		break;
 863	case IEC61937_PC_DTS2:
 864		repet = OPORTMXREPET_STRLENGTH_DTS2 |
 865			OPORTMXREPET_PMLENGTH_DTS2;
 866		pause |= OPORTMXPAUDAT_PAUSEPD_DTS2;
 867		break;
 868	case IEC61937_PC_DTS3:
 869		repet = OPORTMXREPET_STRLENGTH_DTS3 |
 870			OPORTMXREPET_PMLENGTH_DTS3;
 871		pause |= OPORTMXPAUDAT_PAUSEPD_DTS3;
 872		break;
 873	case IEC61937_PC_AAC:
 874		repet = OPORTMXREPET_STRLENGTH_AAC |
 875			OPORTMXREPET_PMLENGTH_AAC;
 876		pause |= OPORTMXPAUDAT_PAUSEPD_AAC;
 877		break;
 878	case IEC61937_PC_PAUSE:
 879		/* Do nothing */
 880		break;
 881	}
 882
 883	regmap_write(r, OPORTMXREPET(sub->swm->oport.map), repet);
 884	regmap_write(r, OPORTMXPAUDAT(sub->swm->oport.map), pause);
 
 
 
 
 
 885
 886	return 0;
 887}
 888
 889/**
 890 * aio_src_reset - reset AIO SRC block
 891 * @sub: the AIO substream pointer
 892 *
 893 * Resets the digital signal input/output port with sampling rate converter
 894 * block of AIO.
 895 * This function has no effect if substream is not supported rate converter.
 896 */
 897void aio_src_reset(struct uniphier_aio_sub *sub)
 898{
 899	struct regmap *r = sub->aio->chip->regmap;
 900
 901	if (sub->swm->dir != PORT_DIR_OUTPUT)
 902		return;
 903
 904	regmap_write(r, AOUTSRCRSTCTR0, BIT(sub->swm->oport.map));
 905	regmap_write(r, AOUTSRCRSTCTR1, BIT(sub->swm->oport.map));
 906}
 907
 908/**
 909 * aio_src_set_param - set parameters of AIO SRC block
 910 * @sub: the AIO substream pointer
 911 * @params: hardware parameters of ALSA
 912 *
 913 * Set suitable setting to input/output port with sampling rate converter
 914 * block of AIO to process the specified in params.
 915 * This function has no effect if substream is not supported rate converter.
 916 *
 917 * Return: Zero if successful, otherwise a negative value on error.
 918 */
 919int aio_src_set_param(struct uniphier_aio_sub *sub,
 920		      const struct snd_pcm_hw_params *params)
 921{
 922	struct regmap *r = sub->aio->chip->regmap;
 923	u32 v;
 
 924
 925	if (sub->swm->dir != PORT_DIR_OUTPUT)
 926		return 0;
 927
 928	regmap_write(r, OPORTMXSRC1CTR(sub->swm->oport.map),
 929		     OPORTMXSRC1CTR_THMODE_SRC |
 930		     OPORTMXSRC1CTR_SRCPATH_CALC |
 931		     OPORTMXSRC1CTR_SYNC_ASYNC |
 932		     OPORTMXSRC1CTR_FSIIPSEL_INNER |
 933		     OPORTMXSRC1CTR_FSISEL_ACLK);
 
 
 934
 935	switch (params_rate(params)) {
 936	default:
 937	case 48000:
 938		v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
 939			OPORTMXRATE_I_MCKSEL_36 |
 940			OPORTMXRATE_I_FSSEL_48;
 941		break;
 942	case 44100:
 943		v = OPORTMXRATE_I_ACLKSEL_APLLA2 |
 944			OPORTMXRATE_I_MCKSEL_33 |
 945			OPORTMXRATE_I_FSSEL_44_1;
 946		break;
 947	case 32000:
 948		v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
 949			OPORTMXRATE_I_MCKSEL_36 |
 950			OPORTMXRATE_I_FSSEL_32;
 951		break;
 952	}
 953
 954	regmap_write(r, OPORTMXRATE_I(sub->swm->oport.map),
 
 955		     v | OPORTMXRATE_I_ACLKSRC_APLL |
 956		     OPORTMXRATE_I_LRCKSTP_STOP);
 957	regmap_update_bits(r, OPORTMXRATE_I(sub->swm->oport.map),
 
 
 
 958			   OPORTMXRATE_I_LRCKSTP_MASK,
 959			   OPORTMXRATE_I_LRCKSTP_START);
 
 
 960
 961	return 0;
 962}
 963
 964int aio_srcif_set_param(struct uniphier_aio_sub *sub)
 965{
 966	struct regmap *r = sub->aio->chip->regmap;
 967
 968	regmap_write(r, PBINMXCTR(sub->swm->iif.map),
 969		     PBINMXCTR_NCONNECT_CONNECT |
 970		     PBINMXCTR_INOUTSEL_OUT |
 971		     (sub->swm->oport.map << PBINMXCTR_PBINSEL_SHIFT) |
 972		     PBINMXCTR_ENDIAN_3210 |
 973		     PBINMXCTR_MEMFMT_D0);
 974
 975	return 0;
 976}
 977
 978int aio_srcch_set_param(struct uniphier_aio_sub *sub)
 979{
 980	struct regmap *r = sub->aio->chip->regmap;
 981
 982	regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->och.map),
 983		     CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
 984
 985	regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->och.map),
 986		     CDA2D_CHMXAMODE_ENDIAN_3210 |
 987		     CDA2D_CHMXAMODE_AUPDT_FIX |
 988		     CDA2D_CHMXAMODE_TYPE_NORMAL);
 989
 990	regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->och.map),
 991		     CDA2D_CHMXAMODE_ENDIAN_3210 |
 992		     CDA2D_CHMXAMODE_AUPDT_INC |
 993		     CDA2D_CHMXAMODE_TYPE_RING |
 994		     (sub->swm->och.map << CDA2D_CHMXAMODE_RSSEL_SHIFT));
 995
 996	return 0;
 997}
 998
 999void aio_srcch_set_enable(struct uniphier_aio_sub *sub, int enable)
1000{
1001	struct regmap *r = sub->aio->chip->regmap;
1002	u32 v;
1003
1004	if (enable)
1005		v = CDA2D_STRT0_STOP_START;
1006	else
1007		v = CDA2D_STRT0_STOP_STOP;
1008
1009	regmap_write(r, CDA2D_STRT0,
1010		     v | BIT(sub->swm->och.map));
1011}
1012
1013int aiodma_ch_set_param(struct uniphier_aio_sub *sub)
1014{
1015	struct regmap *r = sub->aio->chip->regmap;
1016	u32 v;
1017
1018	regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->ch.map),
1019		     CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
1020
1021	v = CDA2D_CHMXAMODE_ENDIAN_3210 |
1022		CDA2D_CHMXAMODE_AUPDT_INC |
1023		CDA2D_CHMXAMODE_TYPE_NORMAL |
1024		(sub->swm->rb.map << CDA2D_CHMXAMODE_RSSEL_SHIFT);
1025	if (sub->swm->dir == PORT_DIR_OUTPUT)
1026		regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->ch.map), v);
1027	else
1028		regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->ch.map), v);
1029
1030	return 0;
1031}
1032
1033void aiodma_ch_set_enable(struct uniphier_aio_sub *sub, int enable)
1034{
1035	struct regmap *r = sub->aio->chip->regmap;
1036
1037	if (enable) {
1038		regmap_write(r, CDA2D_STRT0,
1039			     CDA2D_STRT0_STOP_START | BIT(sub->swm->ch.map));
1040
1041		regmap_update_bits(r, INTRBIM(0),
1042				   BIT(sub->swm->rb.map),
1043				   BIT(sub->swm->rb.map));
1044	} else {
1045		regmap_write(r, CDA2D_STRT0,
1046			     CDA2D_STRT0_STOP_STOP | BIT(sub->swm->ch.map));
1047
1048		regmap_update_bits(r, INTRBIM(0),
1049				   BIT(sub->swm->rb.map),
1050				   0);
1051	}
1052}
1053
1054static u64 aiodma_rb_get_rp(struct uniphier_aio_sub *sub)
1055{
1056	struct regmap *r = sub->aio->chip->regmap;
1057	u32 pos_u, pos_l;
1058	int i;
1059
1060	regmap_write(r, CDA2D_RDPTRLOAD,
1061		     CDA2D_RDPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
1062	/* Wait for setup */
1063	for (i = 0; i < 6; i++)
1064		regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
1065
1066	regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
1067	regmap_read(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), &pos_u);
1068	pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
1069
1070	return ((u64)pos_u << 32) | pos_l;
1071}
1072
1073static void aiodma_rb_set_rp(struct uniphier_aio_sub *sub, u64 pos)
1074{
1075	struct regmap *r = sub->aio->chip->regmap;
1076	u32 tmp;
1077	int i;
1078
1079	regmap_write(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), (u32)pos);
1080	regmap_write(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), (u32)(pos >> 32));
1081	regmap_write(r, CDA2D_RDPTRLOAD, BIT(sub->swm->rb.map));
1082	/* Wait for setup */
1083	for (i = 0; i < 6; i++)
1084		regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &tmp);
1085}
1086
1087static u64 aiodma_rb_get_wp(struct uniphier_aio_sub *sub)
1088{
1089	struct regmap *r = sub->aio->chip->regmap;
1090	u32 pos_u, pos_l;
1091	int i;
1092
1093	regmap_write(r, CDA2D_WRPTRLOAD,
1094		     CDA2D_WRPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
1095	/* Wait for setup */
1096	for (i = 0; i < 6; i++)
1097		regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
1098
1099	regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
1100	regmap_read(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map), &pos_u);
1101	pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
1102
1103	return ((u64)pos_u << 32) | pos_l;
1104}
1105
1106static void aiodma_rb_set_wp(struct uniphier_aio_sub *sub, u64 pos)
1107{
1108	struct regmap *r = sub->aio->chip->regmap;
1109	u32 tmp;
1110	int i;
1111
1112	regmap_write(r, CDA2D_RBMXWRPTR(sub->swm->rb.map),
1113		     lower_32_bits(pos));
1114	regmap_write(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map),
1115		     upper_32_bits(pos));
1116	regmap_write(r, CDA2D_WRPTRLOAD, BIT(sub->swm->rb.map));
1117	/* Wait for setup */
1118	for (i = 0; i < 6; i++)
1119		regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &tmp);
1120}
1121
1122int aiodma_rb_set_threshold(struct uniphier_aio_sub *sub, u64 size, u32 th)
1123{
1124	struct regmap *r = sub->aio->chip->regmap;
1125
1126	if (size <= th)
1127		return -EINVAL;
1128
1129	regmap_write(r, CDA2D_RBMXBTH(sub->swm->rb.map), th);
1130	regmap_write(r, CDA2D_RBMXRTH(sub->swm->rb.map), th);
1131
1132	return 0;
1133}
1134
1135int aiodma_rb_set_buffer(struct uniphier_aio_sub *sub, u64 start, u64 end,
1136			 int period)
1137{
1138	struct regmap *r = sub->aio->chip->regmap;
1139	u64 size = end - start;
1140	int ret;
1141
1142	if (end < start || period < 0)
1143		return -EINVAL;
1144
1145	regmap_write(r, CDA2D_RBMXCNFG(sub->swm->rb.map), 0);
1146	regmap_write(r, CDA2D_RBMXBGNADRS(sub->swm->rb.map),
1147		     lower_32_bits(start));
1148	regmap_write(r, CDA2D_RBMXBGNADRSU(sub->swm->rb.map),
1149		     upper_32_bits(start));
1150	regmap_write(r, CDA2D_RBMXENDADRS(sub->swm->rb.map),
1151		     lower_32_bits(end));
1152	regmap_write(r, CDA2D_RBMXENDADRSU(sub->swm->rb.map),
1153		     upper_32_bits(end));
1154
1155	regmap_write(r, CDA2D_RBADRSLOAD, BIT(sub->swm->rb.map));
1156
1157	ret = aiodma_rb_set_threshold(sub, size, 2 * period);
1158	if (ret)
1159		return ret;
1160
1161	if (sub->swm->dir == PORT_DIR_OUTPUT) {
1162		aiodma_rb_set_rp(sub, start);
1163		aiodma_rb_set_wp(sub, end - period);
1164
1165		regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1166				   CDA2D_RBMXIX_SPACE,
1167				   CDA2D_RBMXIX_SPACE);
1168	} else {
1169		aiodma_rb_set_rp(sub, end - period);
1170		aiodma_rb_set_wp(sub, start);
1171
1172		regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1173				   CDA2D_RBMXIX_REMAIN,
1174				   CDA2D_RBMXIX_REMAIN);
1175	}
1176
1177	sub->threshold = 2 * period;
1178	sub->rd_offs = 0;
1179	sub->wr_offs = 0;
1180	sub->rd_org = 0;
1181	sub->wr_org = 0;
1182	sub->rd_total = 0;
1183	sub->wr_total = 0;
1184
1185	return 0;
1186}
1187
1188void aiodma_rb_sync(struct uniphier_aio_sub *sub, u64 start, u64 size,
1189		    int period)
1190{
1191	if (sub->swm->dir == PORT_DIR_OUTPUT) {
1192		sub->rd_offs = aiodma_rb_get_rp(sub) - start;
1193
1194		if (sub->use_mmap) {
1195			sub->threshold = 2 * period;
1196			aiodma_rb_set_threshold(sub, size, 2 * period);
1197
1198			sub->wr_offs = sub->rd_offs - period;
1199			if (sub->rd_offs < period)
1200				sub->wr_offs += size;
1201		}
1202		aiodma_rb_set_wp(sub, sub->wr_offs + start);
1203	} else {
1204		sub->wr_offs = aiodma_rb_get_wp(sub) - start;
1205
1206		if (sub->use_mmap) {
1207			sub->threshold = 2 * period;
1208			aiodma_rb_set_threshold(sub, size, 2 * period);
1209
1210			sub->rd_offs = sub->wr_offs - period;
1211			if (sub->wr_offs < period)
1212				sub->rd_offs += size;
1213		}
1214		aiodma_rb_set_rp(sub, sub->rd_offs + start);
1215	}
1216
1217	sub->rd_total += sub->rd_offs - sub->rd_org;
1218	if (sub->rd_offs < sub->rd_org)
1219		sub->rd_total += size;
1220	sub->wr_total += sub->wr_offs - sub->wr_org;
1221	if (sub->wr_offs < sub->wr_org)
1222		sub->wr_total += size;
1223
1224	sub->rd_org = sub->rd_offs;
1225	sub->wr_org = sub->wr_offs;
1226}
1227
1228bool aiodma_rb_is_irq(struct uniphier_aio_sub *sub)
1229{
1230	struct regmap *r = sub->aio->chip->regmap;
1231	u32 ir;
1232
1233	regmap_read(r, CDA2D_RBMXIR(sub->swm->rb.map), &ir);
1234
1235	if (sub->swm->dir == PORT_DIR_OUTPUT)
1236		return !!(ir & CDA2D_RBMXIX_SPACE);
1237	else
1238		return !!(ir & CDA2D_RBMXIX_REMAIN);
1239}
1240
1241void aiodma_rb_clear_irq(struct uniphier_aio_sub *sub)
1242{
1243	struct regmap *r = sub->aio->chip->regmap;
1244
1245	if (sub->swm->dir == PORT_DIR_OUTPUT)
1246		regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1247			     CDA2D_RBMXIX_SPACE);
1248	else
1249		regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1250			     CDA2D_RBMXIX_REMAIN);
1251}
v6.13.7
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// Socionext UniPhier AIO ALSA common driver.
   4//
   5// Copyright (c) 2016-2018 Socionext Inc.
   6
   7#include <linux/bitfield.h>
   8#include <linux/errno.h>
   9#include <linux/kernel.h>
  10#include <linux/module.h>
  11#include <sound/core.h>
  12#include <sound/pcm.h>
  13#include <sound/pcm_params.h>
  14#include <sound/soc.h>
  15
  16#include "aio.h"
  17#include "aio-reg.h"
  18
  19static u64 rb_cnt(u64 wr, u64 rd, u64 len)
  20{
  21	if (rd <= wr)
  22		return wr - rd;
  23	else
  24		return len - (rd - wr);
  25}
  26
  27static u64 rb_cnt_to_end(u64 wr, u64 rd, u64 len)
  28{
  29	if (rd <= wr)
  30		return wr - rd;
  31	else
  32		return len - rd;
  33}
  34
  35static u64 rb_space(u64 wr, u64 rd, u64 len)
  36{
  37	if (rd <= wr)
  38		return len - (wr - rd) - 8;
  39	else
  40		return rd - wr - 8;
  41}
  42
  43static u64 rb_space_to_end(u64 wr, u64 rd, u64 len)
  44{
  45	if (rd > wr)
  46		return rd - wr - 8;
  47	else if (rd > 0)
  48		return len - wr;
  49	else
  50		return len - wr - 8;
  51}
  52
  53u64 aio_rb_cnt(struct uniphier_aio_sub *sub)
  54{
  55	return rb_cnt(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
  56}
  57
  58u64 aio_rbt_cnt_to_end(struct uniphier_aio_sub *sub)
  59{
  60	return rb_cnt_to_end(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
  61}
  62
  63u64 aio_rb_space(struct uniphier_aio_sub *sub)
  64{
  65	return rb_space(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
  66}
  67
  68u64 aio_rb_space_to_end(struct uniphier_aio_sub *sub)
  69{
  70	return rb_space_to_end(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
  71}
  72
  73/**
  74 * aio_iecout_set_enable - setup IEC output via SoC glue
  75 * @chip: the AIO chip pointer
  76 * @enable: false to stop the output, true to start
  77 *
  78 * Set enabled or disabled S/PDIF signal output to out of SoC via AOnIEC pins.
  79 * This function need to call at driver startup.
  80 *
  81 * The regmap of SoC glue is specified by 'socionext,syscon' optional property
  82 * of DT. This function has no effect if no property.
  83 */
  84void aio_iecout_set_enable(struct uniphier_aio_chip *chip, bool enable)
  85{
  86	struct regmap *r = chip->regmap_sg;
  87
  88	if (!r)
  89		return;
  90
  91	regmap_write(r, SG_AOUTEN, (enable) ? ~0 : 0);
  92}
  93
  94/**
  95 * aio_chip_set_pll - set frequency to audio PLL
  96 * @chip: the AIO chip pointer
  97 * @pll_id: PLL
  98 * @freq: frequency in Hz, 0 is ignored
  99 *
 100 * Sets frequency of audio PLL. This function can be called anytime,
 101 * but it takes time till PLL is locked.
 102 *
 103 * Return: Zero if successful, otherwise a negative value on error.
 104 */
 105int aio_chip_set_pll(struct uniphier_aio_chip *chip, int pll_id,
 106		     unsigned int freq)
 107{
 108	struct device *dev = &chip->pdev->dev;
 109	struct regmap *r = chip->regmap;
 110	int shift;
 111	u32 v;
 112
 113	/* Not change */
 114	if (freq == 0)
 115		return 0;
 116
 117	switch (pll_id) {
 118	case AUD_PLL_A1:
 119		shift = 0;
 120		break;
 121	case AUD_PLL_F1:
 122		shift = 1;
 123		break;
 124	case AUD_PLL_A2:
 125		shift = 2;
 126		break;
 127	case AUD_PLL_F2:
 128		shift = 3;
 129		break;
 130	default:
 131		dev_err(dev, "PLL(%d) not supported\n", pll_id);
 132		return -EINVAL;
 133	}
 134
 135	switch (freq) {
 136	case 36864000:
 137		v = A2APLLCTR1_APLLX_36MHZ;
 138		break;
 139	case 33868800:
 140		v = A2APLLCTR1_APLLX_33MHZ;
 141		break;
 142	default:
 143		dev_err(dev, "PLL frequency not supported(%d)\n", freq);
 144		return -EINVAL;
 145	}
 146	chip->plls[pll_id].freq = freq;
 147
 148	regmap_update_bits(r, A2APLLCTR1, A2APLLCTR1_APLLX_MASK << shift,
 149			   v << shift);
 150
 151	return 0;
 152}
 153
 154/**
 155 * aio_chip_init - initialize AIO whole settings
 156 * @chip: the AIO chip pointer
 157 *
 158 * Sets AIO fixed and whole device settings to AIO.
 159 * This function need to call once at driver startup.
 160 *
 161 * The register area that is changed by this function is shared by all
 162 * modules of AIO. But there is not race condition since this function
 163 * has always set the same initialize values.
 164 */
 165void aio_chip_init(struct uniphier_aio_chip *chip)
 166{
 167	struct regmap *r = chip->regmap;
 168
 169	regmap_update_bits(r, A2APLLCTR0,
 170			   A2APLLCTR0_APLLXPOW_MASK,
 171			   A2APLLCTR0_APLLXPOW_PWON);
 172
 173	regmap_update_bits(r, A2EXMCLKSEL0,
 174			   A2EXMCLKSEL0_EXMCLK_MASK,
 175			   A2EXMCLKSEL0_EXMCLK_OUTPUT);
 176
 177	regmap_update_bits(r, A2AIOINPUTSEL, A2AIOINPUTSEL_RXSEL_MASK,
 178			   A2AIOINPUTSEL_RXSEL_PCMI1_HDMIRX1 |
 179			   A2AIOINPUTSEL_RXSEL_PCMI2_SIF |
 180			   A2AIOINPUTSEL_RXSEL_PCMI3_EVEA |
 181			   A2AIOINPUTSEL_RXSEL_IECI1_HDMIRX1);
 182
 183	if (chip->chip_spec->addr_ext)
 184		regmap_update_bits(r, CDA2D_TEST, CDA2D_TEST_DDR_MODE_MASK,
 185				   CDA2D_TEST_DDR_MODE_EXTON0);
 186	else
 187		regmap_update_bits(r, CDA2D_TEST, CDA2D_TEST_DDR_MODE_MASK,
 188				   CDA2D_TEST_DDR_MODE_EXTOFF1);
 189}
 190
 191/**
 192 * aio_init - initialize AIO substream
 193 * @sub: the AIO substream pointer
 194 *
 195 * Sets fixed settings of each AIO substreams.
 196 * This function need to call once at substream startup.
 197 *
 198 * Return: Zero if successful, otherwise a negative value on error.
 199 */
 200int aio_init(struct uniphier_aio_sub *sub)
 201{
 202	struct device *dev = &sub->aio->chip->pdev->dev;
 203	struct regmap *r = sub->aio->chip->regmap;
 204
 205	regmap_write(r, A2RBNMAPCTR0(sub->swm->rb.hw),
 206		     MAPCTR0_EN | sub->swm->rb.map);
 207	regmap_write(r, A2CHNMAPCTR0(sub->swm->ch.hw),
 208		     MAPCTR0_EN | sub->swm->ch.map);
 209
 210	switch (sub->swm->type) {
 211	case PORT_TYPE_I2S:
 212	case PORT_TYPE_SPDIF:
 213	case PORT_TYPE_EVE:
 214		if (sub->swm->dir == PORT_DIR_INPUT) {
 215			regmap_write(r, A2IIFNMAPCTR0(sub->swm->iif.hw),
 216				     MAPCTR0_EN | sub->swm->iif.map);
 217			regmap_write(r, A2IPORTNMAPCTR0(sub->swm->iport.hw),
 218				     MAPCTR0_EN | sub->swm->iport.map);
 219		} else {
 220			regmap_write(r, A2OIFNMAPCTR0(sub->swm->oif.hw),
 221				     MAPCTR0_EN | sub->swm->oif.map);
 222			regmap_write(r, A2OPORTNMAPCTR0(sub->swm->oport.hw),
 223				     MAPCTR0_EN | sub->swm->oport.map);
 224		}
 225		break;
 226	case PORT_TYPE_CONV:
 227		regmap_write(r, A2OIFNMAPCTR0(sub->swm->oif.hw),
 228			     MAPCTR0_EN | sub->swm->oif.map);
 229		regmap_write(r, A2OPORTNMAPCTR0(sub->swm->oport.hw),
 230			     MAPCTR0_EN | sub->swm->oport.map);
 231		regmap_write(r, A2CHNMAPCTR0(sub->swm->och.hw),
 232			     MAPCTR0_EN | sub->swm->och.map);
 233		regmap_write(r, A2IIFNMAPCTR0(sub->swm->iif.hw),
 234			     MAPCTR0_EN | sub->swm->iif.map);
 235		break;
 236	default:
 237		dev_err(dev, "Unknown port type %d.\n", sub->swm->type);
 238		return -EINVAL;
 239	}
 240
 241	return 0;
 242}
 243
 244/**
 245 * aio_port_reset - reset AIO port block
 246 * @sub: the AIO substream pointer
 247 *
 248 * Resets the digital signal input/output port block of AIO.
 249 */
 250void aio_port_reset(struct uniphier_aio_sub *sub)
 251{
 252	struct regmap *r = sub->aio->chip->regmap;
 253
 254	if (sub->swm->dir == PORT_DIR_OUTPUT) {
 255		regmap_write(r, AOUTRSTCTR0, BIT(sub->swm->oport.map));
 256		regmap_write(r, AOUTRSTCTR1, BIT(sub->swm->oport.map));
 257	} else {
 258		regmap_update_bits(r, IPORTMXRSTCTR(sub->swm->iport.map),
 259				   IPORTMXRSTCTR_RSTPI_MASK,
 260				   IPORTMXRSTCTR_RSTPI_RESET);
 261		regmap_update_bits(r, IPORTMXRSTCTR(sub->swm->iport.map),
 262				   IPORTMXRSTCTR_RSTPI_MASK,
 263				   IPORTMXRSTCTR_RSTPI_RELEASE);
 264	}
 265}
 266
 267/**
 268 * aio_port_set_ch - set channels of LPCM
 269 * @sub: the AIO substream pointer, PCM substream only
 270 *
 271 * Set suitable slot selecting to input/output port block of AIO.
 272 *
 273 * This function may return error if non-PCM substream.
 274 *
 275 * Return: Zero if successful, otherwise a negative value on error.
 276 */
 277static int aio_port_set_ch(struct uniphier_aio_sub *sub)
 278{
 279	struct regmap *r = sub->aio->chip->regmap;
 280	static const u32 slotsel_2ch[] = {
 281		0, 0, 0, 0, 0,
 282	};
 283	static const u32 slotsel_multi[] = {
 284		OPORTMXTYSLOTCTR_SLOTSEL_SLOT0,
 285		OPORTMXTYSLOTCTR_SLOTSEL_SLOT1,
 286		OPORTMXTYSLOTCTR_SLOTSEL_SLOT2,
 287		OPORTMXTYSLOTCTR_SLOTSEL_SLOT3,
 288		OPORTMXTYSLOTCTR_SLOTSEL_SLOT4,
 289	};
 290	u32 mode;
 291	const u32 *slotsel;
 292	int i;
 293
 294	switch (params_channels(&sub->params)) {
 295	case 8:
 296	case 6:
 297		mode = OPORTMXTYSLOTCTR_MODE;
 298		slotsel = slotsel_multi;
 299		break;
 300	case 2:
 301		mode = 0;
 302		slotsel = slotsel_2ch;
 303		break;
 304	default:
 305		return -EINVAL;
 306	}
 307
 308	for (i = 0; i < AUD_MAX_SLOTSEL; i++) {
 309		regmap_update_bits(r, OPORTMXTYSLOTCTR(sub->swm->oport.map, i),
 310				   OPORTMXTYSLOTCTR_MODE, mode);
 311		regmap_update_bits(r, OPORTMXTYSLOTCTR(sub->swm->oport.map, i),
 312				   OPORTMXTYSLOTCTR_SLOTSEL_MASK, slotsel[i]);
 313	}
 314
 315	return 0;
 316}
 317
 318/**
 319 * aio_port_set_rate - set sampling rate of LPCM
 320 * @sub: the AIO substream pointer, PCM substream only
 321 * @rate: Sampling rate in Hz.
 322 *
 323 * Set suitable I2S format settings to input/output port block of AIO.
 324 * Parameter is specified by hw_params().
 325 *
 326 * This function may return error if non-PCM substream.
 327 *
 328 * Return: Zero if successful, otherwise a negative value on error.
 329 */
 330static int aio_port_set_rate(struct uniphier_aio_sub *sub, int rate)
 331{
 332	struct regmap *r = sub->aio->chip->regmap;
 333	struct device *dev = &sub->aio->chip->pdev->dev;
 334	u32 v;
 335
 336	if (sub->swm->dir == PORT_DIR_OUTPUT) {
 337		switch (rate) {
 338		case 8000:
 339			v = OPORTMXCTR1_FSSEL_8;
 340			break;
 341		case 11025:
 342			v = OPORTMXCTR1_FSSEL_11_025;
 343			break;
 344		case 12000:
 345			v = OPORTMXCTR1_FSSEL_12;
 346			break;
 347		case 16000:
 348			v = OPORTMXCTR1_FSSEL_16;
 349			break;
 350		case 22050:
 351			v = OPORTMXCTR1_FSSEL_22_05;
 352			break;
 353		case 24000:
 354			v = OPORTMXCTR1_FSSEL_24;
 355			break;
 356		case 32000:
 357			v = OPORTMXCTR1_FSSEL_32;
 358			break;
 359		case 44100:
 360			v = OPORTMXCTR1_FSSEL_44_1;
 361			break;
 362		case 48000:
 363			v = OPORTMXCTR1_FSSEL_48;
 364			break;
 365		case 88200:
 366			v = OPORTMXCTR1_FSSEL_88_2;
 367			break;
 368		case 96000:
 369			v = OPORTMXCTR1_FSSEL_96;
 370			break;
 371		case 176400:
 372			v = OPORTMXCTR1_FSSEL_176_4;
 373			break;
 374		case 192000:
 375			v = OPORTMXCTR1_FSSEL_192;
 376			break;
 377		default:
 378			dev_err(dev, "Rate not supported(%d)\n", rate);
 379			return -EINVAL;
 380		}
 381
 382		regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map),
 383				   OPORTMXCTR1_FSSEL_MASK, v);
 384	} else {
 385		switch (rate) {
 386		case 8000:
 387			v = IPORTMXCTR1_FSSEL_8;
 388			break;
 389		case 11025:
 390			v = IPORTMXCTR1_FSSEL_11_025;
 391			break;
 392		case 12000:
 393			v = IPORTMXCTR1_FSSEL_12;
 394			break;
 395		case 16000:
 396			v = IPORTMXCTR1_FSSEL_16;
 397			break;
 398		case 22050:
 399			v = IPORTMXCTR1_FSSEL_22_05;
 400			break;
 401		case 24000:
 402			v = IPORTMXCTR1_FSSEL_24;
 403			break;
 404		case 32000:
 405			v = IPORTMXCTR1_FSSEL_32;
 406			break;
 407		case 44100:
 408			v = IPORTMXCTR1_FSSEL_44_1;
 409			break;
 410		case 48000:
 411			v = IPORTMXCTR1_FSSEL_48;
 412			break;
 413		case 88200:
 414			v = IPORTMXCTR1_FSSEL_88_2;
 415			break;
 416		case 96000:
 417			v = IPORTMXCTR1_FSSEL_96;
 418			break;
 419		case 176400:
 420			v = IPORTMXCTR1_FSSEL_176_4;
 421			break;
 422		case 192000:
 423			v = IPORTMXCTR1_FSSEL_192;
 424			break;
 425		default:
 426			dev_err(dev, "Rate not supported(%d)\n", rate);
 427			return -EINVAL;
 428		}
 429
 430		regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
 431				   IPORTMXCTR1_FSSEL_MASK, v);
 432	}
 433
 434	return 0;
 435}
 436
 437/**
 438 * aio_port_set_fmt - set format of I2S data
 439 * @sub: the AIO substream pointer, PCM substream only
 440 * This parameter has no effect if substream is I2S or PCM.
 441 *
 442 * Set suitable I2S format settings to input/output port block of AIO.
 443 * Parameter is specified by set_fmt().
 444 *
 445 * This function may return error if non-PCM substream.
 446 *
 447 * Return: Zero if successful, otherwise a negative value on error.
 448 */
 449static int aio_port_set_fmt(struct uniphier_aio_sub *sub)
 450{
 451	struct regmap *r = sub->aio->chip->regmap;
 452	struct device *dev = &sub->aio->chip->pdev->dev;
 453	u32 v;
 454
 455	if (sub->swm->dir == PORT_DIR_OUTPUT) {
 456		switch (sub->aio->fmt) {
 457		case SND_SOC_DAIFMT_LEFT_J:
 458			v = OPORTMXCTR1_I2SLRSEL_LEFT;
 459			break;
 460		case SND_SOC_DAIFMT_RIGHT_J:
 461			v = OPORTMXCTR1_I2SLRSEL_RIGHT;
 462			break;
 463		case SND_SOC_DAIFMT_I2S:
 464			v = OPORTMXCTR1_I2SLRSEL_I2S;
 465			break;
 466		default:
 467			dev_err(dev, "Format is not supported(%d)\n",
 468				sub->aio->fmt);
 469			return -EINVAL;
 470		}
 471
 472		v |= OPORTMXCTR1_OUTBITSEL_24;
 473		regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map),
 474				   OPORTMXCTR1_I2SLRSEL_MASK |
 475				   OPORTMXCTR1_OUTBITSEL_MASK, v);
 476	} else {
 477		switch (sub->aio->fmt) {
 478		case SND_SOC_DAIFMT_LEFT_J:
 479			v = IPORTMXCTR1_LRSEL_LEFT;
 480			break;
 481		case SND_SOC_DAIFMT_RIGHT_J:
 482			v = IPORTMXCTR1_LRSEL_RIGHT;
 483			break;
 484		case SND_SOC_DAIFMT_I2S:
 485			v = IPORTMXCTR1_LRSEL_I2S;
 486			break;
 487		default:
 488			dev_err(dev, "Format is not supported(%d)\n",
 489				sub->aio->fmt);
 490			return -EINVAL;
 491		}
 492
 493		v |= IPORTMXCTR1_OUTBITSEL_24 |
 494			IPORTMXCTR1_CHSEL_ALL;
 495		regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
 496				   IPORTMXCTR1_LRSEL_MASK |
 497				   IPORTMXCTR1_OUTBITSEL_MASK |
 498				   IPORTMXCTR1_CHSEL_MASK, v);
 499	}
 500
 501	return 0;
 502}
 503
 504/**
 505 * aio_port_set_clk - set clock and divider of AIO port block
 506 * @sub: the AIO substream pointer
 507 *
 508 * Set suitable PLL clock divider and relational settings to
 509 * input/output port block of AIO. Parameters are specified by
 510 * set_sysclk() and set_pll().
 511 *
 512 * Return: Zero if successful, otherwise a negative value on error.
 513 */
 514static int aio_port_set_clk(struct uniphier_aio_sub *sub)
 515{
 516	struct uniphier_aio_chip *chip = sub->aio->chip;
 517	struct device *dev = &sub->aio->chip->pdev->dev;
 518	struct regmap *r = sub->aio->chip->regmap;
 519	static const u32 v_pll[] = {
 520		OPORTMXCTR2_ACLKSEL_A1, OPORTMXCTR2_ACLKSEL_F1,
 521		OPORTMXCTR2_ACLKSEL_A2, OPORTMXCTR2_ACLKSEL_F2,
 522		OPORTMXCTR2_ACLKSEL_A2PLL,
 523		OPORTMXCTR2_ACLKSEL_RX1,
 524	};
 525	static const u32 v_div[] = {
 526		OPORTMXCTR2_DACCKSEL_1_2, OPORTMXCTR2_DACCKSEL_1_3,
 527		OPORTMXCTR2_DACCKSEL_1_1, OPORTMXCTR2_DACCKSEL_2_3,
 528	};
 529	u32 v;
 530
 531	if (sub->swm->dir == PORT_DIR_OUTPUT) {
 532		if (sub->swm->type == PORT_TYPE_I2S) {
 533			if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) {
 534				dev_err(dev, "PLL(%d) is invalid\n",
 535					sub->aio->pll_out);
 536				return -EINVAL;
 537			}
 538			if (sub->aio->plldiv >= ARRAY_SIZE(v_div)) {
 539				dev_err(dev, "PLL divider(%d) is invalid\n",
 540					sub->aio->plldiv);
 541				return -EINVAL;
 542			}
 543
 544			v = v_pll[sub->aio->pll_out] |
 545				OPORTMXCTR2_MSSEL_MASTER |
 546				v_div[sub->aio->plldiv];
 547
 548			switch (chip->plls[sub->aio->pll_out].freq) {
 549			case 0:
 550			case 36864000:
 551			case 33868800:
 552				v |= OPORTMXCTR2_EXTLSIFSSEL_36;
 553				break;
 554			default:
 555				v |= OPORTMXCTR2_EXTLSIFSSEL_24;
 556				break;
 557			}
 558		} else if (sub->swm->type == PORT_TYPE_EVE) {
 559			v = OPORTMXCTR2_ACLKSEL_A2PLL |
 560				OPORTMXCTR2_MSSEL_MASTER |
 561				OPORTMXCTR2_EXTLSIFSSEL_36 |
 562				OPORTMXCTR2_DACCKSEL_1_2;
 563		} else if (sub->swm->type == PORT_TYPE_SPDIF) {
 564			if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) {
 565				dev_err(dev, "PLL(%d) is invalid\n",
 566					sub->aio->pll_out);
 567				return -EINVAL;
 568			}
 569			v = v_pll[sub->aio->pll_out] |
 570				OPORTMXCTR2_MSSEL_MASTER |
 571				OPORTMXCTR2_DACCKSEL_1_2;
 572
 573			switch (chip->plls[sub->aio->pll_out].freq) {
 574			case 0:
 575			case 36864000:
 576			case 33868800:
 577				v |= OPORTMXCTR2_EXTLSIFSSEL_36;
 578				break;
 579			default:
 580				v |= OPORTMXCTR2_EXTLSIFSSEL_24;
 581				break;
 582			}
 583		} else {
 584			v = OPORTMXCTR2_ACLKSEL_A1 |
 585				OPORTMXCTR2_MSSEL_MASTER |
 586				OPORTMXCTR2_EXTLSIFSSEL_36 |
 587				OPORTMXCTR2_DACCKSEL_1_2;
 588		}
 589		regmap_write(r, OPORTMXCTR2(sub->swm->oport.map), v);
 590	} else {
 591		v = IPORTMXCTR2_ACLKSEL_A1 |
 592			IPORTMXCTR2_MSSEL_SLAVE |
 593			IPORTMXCTR2_EXTLSIFSSEL_36 |
 594			IPORTMXCTR2_DACCKSEL_1_2;
 595		regmap_write(r, IPORTMXCTR2(sub->swm->iport.map), v);
 596	}
 597
 598	return 0;
 599}
 600
 601/**
 602 * aio_port_set_param - set parameters of AIO port block
 603 * @sub: the AIO substream pointer
 604 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM.
 605 * This parameter has no effect if substream is I2S or PCM.
 606 * @params: hardware parameters of ALSA
 607 *
 608 * Set suitable setting to input/output port block of AIO to process the
 609 * specified in params.
 610 *
 611 * Return: Zero if successful, otherwise a negative value on error.
 612 */
 613int aio_port_set_param(struct uniphier_aio_sub *sub, int pass_through,
 614		       const struct snd_pcm_hw_params *params)
 615{
 616	struct regmap *r = sub->aio->chip->regmap;
 617	unsigned int rate;
 618	u32 v;
 619	int ret;
 620
 621	if (!pass_through) {
 622		if (sub->swm->type == PORT_TYPE_EVE ||
 623		    sub->swm->type == PORT_TYPE_CONV) {
 624			rate = 48000;
 625		} else {
 626			rate = params_rate(params);
 627		}
 628
 629		ret = aio_port_set_ch(sub);
 630		if (ret)
 631			return ret;
 632
 633		ret = aio_port_set_rate(sub, rate);
 634		if (ret)
 635			return ret;
 636
 637		ret = aio_port_set_fmt(sub);
 638		if (ret)
 639			return ret;
 640	}
 641
 642	ret = aio_port_set_clk(sub);
 643	if (ret)
 644		return ret;
 645
 646	if (sub->swm->dir == PORT_DIR_OUTPUT) {
 647		if (pass_through)
 648			v = OPORTMXCTR3_SRCSEL_STREAM |
 649				OPORTMXCTR3_VALID_STREAM;
 650		else
 651			v = OPORTMXCTR3_SRCSEL_PCM |
 652				OPORTMXCTR3_VALID_PCM;
 653
 654		v |= OPORTMXCTR3_IECTHUR_IECOUT |
 655			OPORTMXCTR3_PMSEL_PAUSE |
 656			OPORTMXCTR3_PMSW_MUTE_OFF;
 657		regmap_write(r, OPORTMXCTR3(sub->swm->oport.map), v);
 658	} else {
 659		regmap_write(r, IPORTMXACLKSEL0EX(sub->swm->iport.map),
 660			     IPORTMXACLKSEL0EX_ACLKSEL0EX_INTERNAL);
 661		regmap_write(r, IPORTMXEXNOE(sub->swm->iport.map),
 662			     IPORTMXEXNOE_PCMINOE_INPUT);
 663	}
 664
 665	return 0;
 666}
 667
 668/**
 669 * aio_port_set_enable - start or stop of AIO port block
 670 * @sub: the AIO substream pointer
 671 * @enable: zero to stop the block, otherwise to start
 672 *
 673 * Start or stop the signal input/output port block of AIO.
 674 */
 675void aio_port_set_enable(struct uniphier_aio_sub *sub, int enable)
 676{
 677	struct regmap *r = sub->aio->chip->regmap;
 678
 679	if (sub->swm->dir == PORT_DIR_OUTPUT) {
 680		regmap_write(r, OPORTMXPATH(sub->swm->oport.map),
 681			     sub->swm->oif.map);
 682
 683		regmap_update_bits(r, OPORTMXMASK(sub->swm->oport.map),
 684				   OPORTMXMASK_IUDXMSK_MASK |
 685				   OPORTMXMASK_IUXCKMSK_MASK |
 686				   OPORTMXMASK_DXMSK_MASK |
 687				   OPORTMXMASK_XCKMSK_MASK,
 688				   OPORTMXMASK_IUDXMSK_OFF |
 689				   OPORTMXMASK_IUXCKMSK_OFF |
 690				   OPORTMXMASK_DXMSK_OFF |
 691				   OPORTMXMASK_XCKMSK_OFF);
 692
 693		if (enable)
 694			regmap_write(r, AOUTENCTR0, BIT(sub->swm->oport.map));
 695		else
 696			regmap_write(r, AOUTENCTR1, BIT(sub->swm->oport.map));
 697	} else {
 698		regmap_update_bits(r, IPORTMXMASK(sub->swm->iport.map),
 699				   IPORTMXMASK_IUXCKMSK_MASK |
 700				   IPORTMXMASK_XCKMSK_MASK,
 701				   IPORTMXMASK_IUXCKMSK_OFF |
 702				   IPORTMXMASK_XCKMSK_OFF);
 703
 704		if (enable)
 705			regmap_update_bits(r,
 706					   IPORTMXCTR2(sub->swm->iport.map),
 707					   IPORTMXCTR2_REQEN_MASK,
 708					   IPORTMXCTR2_REQEN_ENABLE);
 709		else
 710			regmap_update_bits(r,
 711					   IPORTMXCTR2(sub->swm->iport.map),
 712					   IPORTMXCTR2_REQEN_MASK,
 713					   IPORTMXCTR2_REQEN_DISABLE);
 714	}
 715}
 716
 717/**
 718 * aio_port_get_volume - get volume of AIO port block
 719 * @sub: the AIO substream pointer
 720 *
 721 * Return: current volume, range is 0x0000 - 0xffff
 722 */
 723int aio_port_get_volume(struct uniphier_aio_sub *sub)
 724{
 725	struct regmap *r = sub->aio->chip->regmap;
 726	u32 v;
 727
 728	regmap_read(r, OPORTMXTYVOLGAINSTATUS(sub->swm->oport.map, 0), &v);
 729
 730	return FIELD_GET(OPORTMXTYVOLGAINSTATUS_CUR_MASK, v);
 731}
 732
 733/**
 734 * aio_port_set_volume - set volume of AIO port block
 735 * @sub: the AIO substream pointer
 736 * @vol: target volume, range is 0x0000 - 0xffff.
 737 *
 738 * Change digital volume and perfome fade-out/fade-in effect for specified
 739 * output slot of port. Gained PCM value can calculate as the following:
 740 *   Gained = Original * vol / 0x4000
 741 */
 742void aio_port_set_volume(struct uniphier_aio_sub *sub, int vol)
 743{
 744	struct regmap *r = sub->aio->chip->regmap;
 745	int oport_map = sub->swm->oport.map;
 746	int cur, diff, slope = 0, fs;
 747
 748	if (sub->swm->dir == PORT_DIR_INPUT)
 749		return;
 750
 751	cur = aio_port_get_volume(sub);
 752	diff = abs(vol - cur);
 753	fs = params_rate(&sub->params);
 754	if (fs)
 755		slope = diff / AUD_VOL_FADE_TIME * 1000 / fs;
 756	slope = max(1, slope);
 757
 758	regmap_update_bits(r, OPORTMXTYVOLPARA1(oport_map, 0),
 759			   OPORTMXTYVOLPARA1_SLOPEU_MASK, slope << 16);
 760	regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
 761			   OPORTMXTYVOLPARA2_TARGET_MASK, vol);
 762
 763	if (cur < vol)
 764		regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
 765				   OPORTMXTYVOLPARA2_FADE_MASK,
 766				   OPORTMXTYVOLPARA2_FADE_FADEIN);
 767	else
 768		regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
 769				   OPORTMXTYVOLPARA2_FADE_MASK,
 770				   OPORTMXTYVOLPARA2_FADE_FADEOUT);
 771
 772	regmap_write(r, AOUTFADECTR0, BIT(oport_map));
 773}
 774
 775/**
 776 * aio_if_set_param - set parameters of AIO DMA I/F block
 777 * @sub: the AIO substream pointer
 778 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM.
 779 * This parameter has no effect if substream is I2S or PCM.
 780 *
 781 * Set suitable setting to DMA interface block of AIO to process the
 782 * specified in settings.
 783 *
 784 * Return: Zero if successful, otherwise a negative value on error.
 785 */
 786int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through)
 787{
 788	struct regmap *r = sub->aio->chip->regmap;
 789	u32 memfmt, v;
 790
 791	if (sub->swm->dir == PORT_DIR_OUTPUT) {
 792		if (pass_through) {
 793			v = PBOUTMXCTR0_ENDIAN_0123 |
 794				PBOUTMXCTR0_MEMFMT_STREAM;
 795		} else {
 796			switch (params_channels(&sub->params)) {
 797			case 2:
 798				memfmt = PBOUTMXCTR0_MEMFMT_2CH;
 799				break;
 800			case 6:
 801				memfmt = PBOUTMXCTR0_MEMFMT_6CH;
 802				break;
 803			case 8:
 804				memfmt = PBOUTMXCTR0_MEMFMT_8CH;
 805				break;
 806			default:
 807				return -EINVAL;
 808			}
 809			v = PBOUTMXCTR0_ENDIAN_3210 | memfmt;
 810		}
 811
 812		regmap_write(r, PBOUTMXCTR0(sub->swm->oif.map), v);
 813		regmap_write(r, PBOUTMXCTR1(sub->swm->oif.map), 0);
 814	} else {
 815		regmap_write(r, PBINMXCTR(sub->swm->iif.map),
 816			     PBINMXCTR_NCONNECT_CONNECT |
 817			     PBINMXCTR_INOUTSEL_IN |
 818			     (sub->swm->iport.map << PBINMXCTR_PBINSEL_SHIFT) |
 819			     PBINMXCTR_ENDIAN_3210 |
 820			     PBINMXCTR_MEMFMT_D0);
 821	}
 822
 823	return 0;
 824}
 825
 826/**
 827 * aio_oport_set_stream_type - set parameters of AIO playback port block
 828 * @sub: the AIO substream pointer
 829 * @pc: Pc type of IEC61937
 830 *
 831 * Set special setting to output port block of AIO to output the stream
 832 * via S/PDIF.
 833 *
 834 * Return: Zero if successful, otherwise a negative value on error.
 835 */
 836int aio_oport_set_stream_type(struct uniphier_aio_sub *sub,
 837			      enum IEC61937_PC pc)
 838{
 839	struct regmap *r = sub->aio->chip->regmap;
 840	u32 repet = 0, pause = OPORTMXPAUDAT_PAUSEPC_CMN;
 841	int ret;
 842
 843	switch (pc) {
 844	case IEC61937_PC_AC3:
 845		repet = OPORTMXREPET_STRLENGTH_AC3 |
 846			OPORTMXREPET_PMLENGTH_AC3;
 847		pause |= OPORTMXPAUDAT_PAUSEPD_AC3;
 848		break;
 849	case IEC61937_PC_MPA:
 850		repet = OPORTMXREPET_STRLENGTH_MPA |
 851			OPORTMXREPET_PMLENGTH_MPA;
 852		pause |= OPORTMXPAUDAT_PAUSEPD_MPA;
 853		break;
 854	case IEC61937_PC_MP3:
 855		repet = OPORTMXREPET_STRLENGTH_MP3 |
 856			OPORTMXREPET_PMLENGTH_MP3;
 857		pause |= OPORTMXPAUDAT_PAUSEPD_MP3;
 858		break;
 859	case IEC61937_PC_DTS1:
 860		repet = OPORTMXREPET_STRLENGTH_DTS1 |
 861			OPORTMXREPET_PMLENGTH_DTS1;
 862		pause |= OPORTMXPAUDAT_PAUSEPD_DTS1;
 863		break;
 864	case IEC61937_PC_DTS2:
 865		repet = OPORTMXREPET_STRLENGTH_DTS2 |
 866			OPORTMXREPET_PMLENGTH_DTS2;
 867		pause |= OPORTMXPAUDAT_PAUSEPD_DTS2;
 868		break;
 869	case IEC61937_PC_DTS3:
 870		repet = OPORTMXREPET_STRLENGTH_DTS3 |
 871			OPORTMXREPET_PMLENGTH_DTS3;
 872		pause |= OPORTMXPAUDAT_PAUSEPD_DTS3;
 873		break;
 874	case IEC61937_PC_AAC:
 875		repet = OPORTMXREPET_STRLENGTH_AAC |
 876			OPORTMXREPET_PMLENGTH_AAC;
 877		pause |= OPORTMXPAUDAT_PAUSEPD_AAC;
 878		break;
 879	case IEC61937_PC_PAUSE:
 880		/* Do nothing */
 881		break;
 882	}
 883
 884	ret = regmap_write(r, OPORTMXREPET(sub->swm->oport.map), repet);
 885	if (ret)
 886		return ret;
 887	
 888	ret = regmap_write(r, OPORTMXPAUDAT(sub->swm->oport.map), pause);
 889	if (ret)
 890		return ret;
 891
 892	return 0;
 893}
 894
 895/**
 896 * aio_src_reset - reset AIO SRC block
 897 * @sub: the AIO substream pointer
 898 *
 899 * Resets the digital signal input/output port with sampling rate converter
 900 * block of AIO.
 901 * This function has no effect if substream is not supported rate converter.
 902 */
 903void aio_src_reset(struct uniphier_aio_sub *sub)
 904{
 905	struct regmap *r = sub->aio->chip->regmap;
 906
 907	if (sub->swm->dir != PORT_DIR_OUTPUT)
 908		return;
 909
 910	regmap_write(r, AOUTSRCRSTCTR0, BIT(sub->swm->oport.map));
 911	regmap_write(r, AOUTSRCRSTCTR1, BIT(sub->swm->oport.map));
 912}
 913
 914/**
 915 * aio_src_set_param - set parameters of AIO SRC block
 916 * @sub: the AIO substream pointer
 917 * @params: hardware parameters of ALSA
 918 *
 919 * Set suitable setting to input/output port with sampling rate converter
 920 * block of AIO to process the specified in params.
 921 * This function has no effect if substream is not supported rate converter.
 922 *
 923 * Return: Zero if successful, otherwise a negative value on error.
 924 */
 925int aio_src_set_param(struct uniphier_aio_sub *sub,
 926		      const struct snd_pcm_hw_params *params)
 927{
 928	struct regmap *r = sub->aio->chip->regmap;
 929	u32 v;
 930	int ret;
 931
 932	if (sub->swm->dir != PORT_DIR_OUTPUT)
 933		return 0;
 934
 935	ret = regmap_write(r, OPORTMXSRC1CTR(sub->swm->oport.map),
 936		     OPORTMXSRC1CTR_THMODE_SRC |
 937		     OPORTMXSRC1CTR_SRCPATH_CALC |
 938		     OPORTMXSRC1CTR_SYNC_ASYNC |
 939		     OPORTMXSRC1CTR_FSIIPSEL_INNER |
 940		     OPORTMXSRC1CTR_FSISEL_ACLK);
 941	if (ret)
 942		return ret;
 943
 944	switch (params_rate(params)) {
 945	default:
 946	case 48000:
 947		v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
 948			OPORTMXRATE_I_MCKSEL_36 |
 949			OPORTMXRATE_I_FSSEL_48;
 950		break;
 951	case 44100:
 952		v = OPORTMXRATE_I_ACLKSEL_APLLA2 |
 953			OPORTMXRATE_I_MCKSEL_33 |
 954			OPORTMXRATE_I_FSSEL_44_1;
 955		break;
 956	case 32000:
 957		v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
 958			OPORTMXRATE_I_MCKSEL_36 |
 959			OPORTMXRATE_I_FSSEL_32;
 960		break;
 961	}
 962
 963
 964	ret = regmap_write(r, OPORTMXRATE_I(sub->swm->oport.map),
 965		     v | OPORTMXRATE_I_ACLKSRC_APLL |
 966		     OPORTMXRATE_I_LRCKSTP_STOP);
 967	if (ret)
 968		return ret;
 969
 970	ret = regmap_update_bits(r, OPORTMXRATE_I(sub->swm->oport.map),
 971			   OPORTMXRATE_I_LRCKSTP_MASK,
 972			   OPORTMXRATE_I_LRCKSTP_START);
 973	if (ret)
 974		return ret;
 975
 976	return 0;
 977}
 978
 979int aio_srcif_set_param(struct uniphier_aio_sub *sub)
 980{
 981	struct regmap *r = sub->aio->chip->regmap;
 982
 983	regmap_write(r, PBINMXCTR(sub->swm->iif.map),
 984		     PBINMXCTR_NCONNECT_CONNECT |
 985		     PBINMXCTR_INOUTSEL_OUT |
 986		     (sub->swm->oport.map << PBINMXCTR_PBINSEL_SHIFT) |
 987		     PBINMXCTR_ENDIAN_3210 |
 988		     PBINMXCTR_MEMFMT_D0);
 989
 990	return 0;
 991}
 992
 993int aio_srcch_set_param(struct uniphier_aio_sub *sub)
 994{
 995	struct regmap *r = sub->aio->chip->regmap;
 996
 997	regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->och.map),
 998		     CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
 999
1000	regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->och.map),
1001		     CDA2D_CHMXAMODE_ENDIAN_3210 |
1002		     CDA2D_CHMXAMODE_AUPDT_FIX |
1003		     CDA2D_CHMXAMODE_TYPE_NORMAL);
1004
1005	regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->och.map),
1006		     CDA2D_CHMXAMODE_ENDIAN_3210 |
1007		     CDA2D_CHMXAMODE_AUPDT_INC |
1008		     CDA2D_CHMXAMODE_TYPE_RING |
1009		     (sub->swm->och.map << CDA2D_CHMXAMODE_RSSEL_SHIFT));
1010
1011	return 0;
1012}
1013
1014void aio_srcch_set_enable(struct uniphier_aio_sub *sub, int enable)
1015{
1016	struct regmap *r = sub->aio->chip->regmap;
1017	u32 v;
1018
1019	if (enable)
1020		v = CDA2D_STRT0_STOP_START;
1021	else
1022		v = CDA2D_STRT0_STOP_STOP;
1023
1024	regmap_write(r, CDA2D_STRT0,
1025		     v | BIT(sub->swm->och.map));
1026}
1027
1028int aiodma_ch_set_param(struct uniphier_aio_sub *sub)
1029{
1030	struct regmap *r = sub->aio->chip->regmap;
1031	u32 v;
1032
1033	regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->ch.map),
1034		     CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
1035
1036	v = CDA2D_CHMXAMODE_ENDIAN_3210 |
1037		CDA2D_CHMXAMODE_AUPDT_INC |
1038		CDA2D_CHMXAMODE_TYPE_NORMAL |
1039		(sub->swm->rb.map << CDA2D_CHMXAMODE_RSSEL_SHIFT);
1040	if (sub->swm->dir == PORT_DIR_OUTPUT)
1041		regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->ch.map), v);
1042	else
1043		regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->ch.map), v);
1044
1045	return 0;
1046}
1047
1048void aiodma_ch_set_enable(struct uniphier_aio_sub *sub, int enable)
1049{
1050	struct regmap *r = sub->aio->chip->regmap;
1051
1052	if (enable) {
1053		regmap_write(r, CDA2D_STRT0,
1054			     CDA2D_STRT0_STOP_START | BIT(sub->swm->ch.map));
1055
1056		regmap_update_bits(r, INTRBIM(0),
1057				   BIT(sub->swm->rb.map),
1058				   BIT(sub->swm->rb.map));
1059	} else {
1060		regmap_write(r, CDA2D_STRT0,
1061			     CDA2D_STRT0_STOP_STOP | BIT(sub->swm->ch.map));
1062
1063		regmap_update_bits(r, INTRBIM(0),
1064				   BIT(sub->swm->rb.map),
1065				   0);
1066	}
1067}
1068
1069static u64 aiodma_rb_get_rp(struct uniphier_aio_sub *sub)
1070{
1071	struct regmap *r = sub->aio->chip->regmap;
1072	u32 pos_u, pos_l;
1073	int i;
1074
1075	regmap_write(r, CDA2D_RDPTRLOAD,
1076		     CDA2D_RDPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
1077	/* Wait for setup */
1078	for (i = 0; i < 6; i++)
1079		regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
1080
1081	regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
1082	regmap_read(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), &pos_u);
1083	pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
1084
1085	return ((u64)pos_u << 32) | pos_l;
1086}
1087
1088static void aiodma_rb_set_rp(struct uniphier_aio_sub *sub, u64 pos)
1089{
1090	struct regmap *r = sub->aio->chip->regmap;
1091	u32 tmp;
1092	int i;
1093
1094	regmap_write(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), (u32)pos);
1095	regmap_write(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), (u32)(pos >> 32));
1096	regmap_write(r, CDA2D_RDPTRLOAD, BIT(sub->swm->rb.map));
1097	/* Wait for setup */
1098	for (i = 0; i < 6; i++)
1099		regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &tmp);
1100}
1101
1102static u64 aiodma_rb_get_wp(struct uniphier_aio_sub *sub)
1103{
1104	struct regmap *r = sub->aio->chip->regmap;
1105	u32 pos_u, pos_l;
1106	int i;
1107
1108	regmap_write(r, CDA2D_WRPTRLOAD,
1109		     CDA2D_WRPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
1110	/* Wait for setup */
1111	for (i = 0; i < 6; i++)
1112		regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
1113
1114	regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
1115	regmap_read(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map), &pos_u);
1116	pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
1117
1118	return ((u64)pos_u << 32) | pos_l;
1119}
1120
1121static void aiodma_rb_set_wp(struct uniphier_aio_sub *sub, u64 pos)
1122{
1123	struct regmap *r = sub->aio->chip->regmap;
1124	u32 tmp;
1125	int i;
1126
1127	regmap_write(r, CDA2D_RBMXWRPTR(sub->swm->rb.map),
1128		     lower_32_bits(pos));
1129	regmap_write(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map),
1130		     upper_32_bits(pos));
1131	regmap_write(r, CDA2D_WRPTRLOAD, BIT(sub->swm->rb.map));
1132	/* Wait for setup */
1133	for (i = 0; i < 6; i++)
1134		regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &tmp);
1135}
1136
1137int aiodma_rb_set_threshold(struct uniphier_aio_sub *sub, u64 size, u32 th)
1138{
1139	struct regmap *r = sub->aio->chip->regmap;
1140
1141	if (size <= th)
1142		return -EINVAL;
1143
1144	regmap_write(r, CDA2D_RBMXBTH(sub->swm->rb.map), th);
1145	regmap_write(r, CDA2D_RBMXRTH(sub->swm->rb.map), th);
1146
1147	return 0;
1148}
1149
1150int aiodma_rb_set_buffer(struct uniphier_aio_sub *sub, u64 start, u64 end,
1151			 int period)
1152{
1153	struct regmap *r = sub->aio->chip->regmap;
1154	u64 size = end - start;
1155	int ret;
1156
1157	if (end < start || period < 0)
1158		return -EINVAL;
1159
1160	regmap_write(r, CDA2D_RBMXCNFG(sub->swm->rb.map), 0);
1161	regmap_write(r, CDA2D_RBMXBGNADRS(sub->swm->rb.map),
1162		     lower_32_bits(start));
1163	regmap_write(r, CDA2D_RBMXBGNADRSU(sub->swm->rb.map),
1164		     upper_32_bits(start));
1165	regmap_write(r, CDA2D_RBMXENDADRS(sub->swm->rb.map),
1166		     lower_32_bits(end));
1167	regmap_write(r, CDA2D_RBMXENDADRSU(sub->swm->rb.map),
1168		     upper_32_bits(end));
1169
1170	regmap_write(r, CDA2D_RBADRSLOAD, BIT(sub->swm->rb.map));
1171
1172	ret = aiodma_rb_set_threshold(sub, size, 2 * period);
1173	if (ret)
1174		return ret;
1175
1176	if (sub->swm->dir == PORT_DIR_OUTPUT) {
1177		aiodma_rb_set_rp(sub, start);
1178		aiodma_rb_set_wp(sub, end - period);
1179
1180		regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1181				   CDA2D_RBMXIX_SPACE,
1182				   CDA2D_RBMXIX_SPACE);
1183	} else {
1184		aiodma_rb_set_rp(sub, end - period);
1185		aiodma_rb_set_wp(sub, start);
1186
1187		regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1188				   CDA2D_RBMXIX_REMAIN,
1189				   CDA2D_RBMXIX_REMAIN);
1190	}
1191
1192	sub->threshold = 2 * period;
1193	sub->rd_offs = 0;
1194	sub->wr_offs = 0;
1195	sub->rd_org = 0;
1196	sub->wr_org = 0;
1197	sub->rd_total = 0;
1198	sub->wr_total = 0;
1199
1200	return 0;
1201}
1202
1203void aiodma_rb_sync(struct uniphier_aio_sub *sub, u64 start, u64 size,
1204		    int period)
1205{
1206	if (sub->swm->dir == PORT_DIR_OUTPUT) {
1207		sub->rd_offs = aiodma_rb_get_rp(sub) - start;
1208
1209		if (sub->use_mmap) {
1210			sub->threshold = 2 * period;
1211			aiodma_rb_set_threshold(sub, size, 2 * period);
1212
1213			sub->wr_offs = sub->rd_offs - period;
1214			if (sub->rd_offs < period)
1215				sub->wr_offs += size;
1216		}
1217		aiodma_rb_set_wp(sub, sub->wr_offs + start);
1218	} else {
1219		sub->wr_offs = aiodma_rb_get_wp(sub) - start;
1220
1221		if (sub->use_mmap) {
1222			sub->threshold = 2 * period;
1223			aiodma_rb_set_threshold(sub, size, 2 * period);
1224
1225			sub->rd_offs = sub->wr_offs - period;
1226			if (sub->wr_offs < period)
1227				sub->rd_offs += size;
1228		}
1229		aiodma_rb_set_rp(sub, sub->rd_offs + start);
1230	}
1231
1232	sub->rd_total += sub->rd_offs - sub->rd_org;
1233	if (sub->rd_offs < sub->rd_org)
1234		sub->rd_total += size;
1235	sub->wr_total += sub->wr_offs - sub->wr_org;
1236	if (sub->wr_offs < sub->wr_org)
1237		sub->wr_total += size;
1238
1239	sub->rd_org = sub->rd_offs;
1240	sub->wr_org = sub->wr_offs;
1241}
1242
1243bool aiodma_rb_is_irq(struct uniphier_aio_sub *sub)
1244{
1245	struct regmap *r = sub->aio->chip->regmap;
1246	u32 ir;
1247
1248	regmap_read(r, CDA2D_RBMXIR(sub->swm->rb.map), &ir);
1249
1250	if (sub->swm->dir == PORT_DIR_OUTPUT)
1251		return !!(ir & CDA2D_RBMXIX_SPACE);
1252	else
1253		return !!(ir & CDA2D_RBMXIX_REMAIN);
1254}
1255
1256void aiodma_rb_clear_irq(struct uniphier_aio_sub *sub)
1257{
1258	struct regmap *r = sub->aio->chip->regmap;
1259
1260	if (sub->swm->dir == PORT_DIR_OUTPUT)
1261		regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1262			     CDA2D_RBMXIX_SPACE);
1263	else
1264		regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1265			     CDA2D_RBMXIX_REMAIN);
1266}