adg.c 12.3 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*
 * Helper routines for R-Car sound ADG.
 *
 *  Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 */
10
#include <linux/clk-provider.h>
11 12 13 14 15 16 17 18
#include "rsnd.h"

#define CLKA	0
#define CLKB	1
#define CLKC	2
#define CLKI	3
#define CLKMAX	4

19 20 21 22 23 24
#define CLKOUT	0
#define CLKOUT1	1
#define CLKOUT2	2
#define CLKOUT3	3
#define CLKOUTMAX 4

25 26
#define BRRx_MASK(x) (0x3FF & x)

27 28 29 30
static struct rsnd_mod_ops adg_ops = {
	.name = "adg",
};

31 32
struct rsnd_adg {
	struct clk *clk[CLKMAX];
33 34
	struct clk *clkout[CLKOUTMAX];
	struct clk_onecell_data onecell;
35
	struct rsnd_mod mod;
36
	u32 flags;
37

38 39
	int rbga_rate_for_441khz; /* RBGA */
	int rbgb_rate_for_48khz;  /* RBGB */
40 41
};

42 43 44
#define LRCLK_ASYNC	(1 << 0)
#define adg_mode_flags(adg)	(adg->flags)

45
#define for_each_rsnd_clk(pos, adg, i)		\
46 47 48 49
	for (i = 0;				\
	     (i < CLKMAX) &&			\
	     ((pos) = adg->clk[i]);		\
	     i++)
50 51 52 53 54
#define for_each_rsnd_clkout(pos, adg, i)	\
	for (i = 0;				\
	     (i < CLKOUTMAX) &&			\
	     ((pos) = adg->clkout[i]);	\
	     i++)
55 56
#define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg)

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
static u32 rsnd_adg_calculate_rbgx(unsigned long div)
{
	int i, ratio;

	if (!div)
		return 0;

	for (i = 3; i >= 0; i--) {
		ratio = 2 << (i * 2);
		if (0 == (div % ratio))
			return (u32)((i << 8) | ((div / ratio) - 1));
	}

	return ~0;
}
72

73
static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io)
74
{
75 76
	struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
	int id = rsnd_mod_id(ssi_mod);
77 78
	int ws = id;

79
	if (rsnd_ssi_is_pin_sharing(io)) {
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
		switch (id) {
		case 1:
		case 2:
			ws = 0;
			break;
		case 4:
			ws = 3;
			break;
		case 8:
			ws = 7;
			break;
		}
	}

	return (0x6 + ws) << 8;
}

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv,
				       struct rsnd_dai_stream *io,
				       unsigned int target_rate,
				       unsigned int *target_val,
				       unsigned int *target_en)
{
	struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
	struct device *dev = rsnd_priv_to_dev(priv);
	int idx, sel, div, step;
	unsigned int val, en;
	unsigned int min, diff;
	unsigned int sel_rate[] = {
		clk_get_rate(adg->clk[CLKA]),	/* 0000: CLKA */
		clk_get_rate(adg->clk[CLKB]),	/* 0001: CLKB */
		clk_get_rate(adg->clk[CLKC]),	/* 0010: CLKC */
		adg->rbga_rate_for_441khz,	/* 0011: RBGA */
		adg->rbgb_rate_for_48khz,	/* 0100: RBGB */
	};

	min = ~0;
	val = 0;
	en = 0;
	for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) {
		idx = 0;
		step = 2;

		if (!sel_rate[sel])
			continue;

		for (div = 2; div <= 98304; div += step) {
			diff = abs(target_rate - sel_rate[sel] / div);
			if (min > diff) {
				val = (sel << 8) | idx;
				min = diff;
				en = 1 << (sel + 1); /* fixme */
			}

			/*
			 * step of 0_0000 / 0_0001 / 0_1101
			 * are out of order
			 */
			if ((idx > 2) && (idx % 2))
				step *= 2;
			if (idx == 0x1c) {
				div += step;
				step *= 2;
			}
			idx++;
		}
	}

	if (min == ~0) {
		dev_err(dev, "no Input clock\n");
		return;
	}

	*target_val = val;
	if (target_en)
		*target_en = en;
}

static void rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv,
				       struct rsnd_dai_stream *io,
				       unsigned int in_rate,
				       unsigned int out_rate,
				       u32 *in, u32 *out, u32 *en)
{
	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
	unsigned int target_rate;
	u32 *target_val;
	u32 _in;
	u32 _out;
	u32 _en;

	/* default = SSI WS */
	_in =
	_out = rsnd_adg_ssi_ws_timing_gen2(io);

	target_rate = 0;
	target_val = NULL;
	_en = 0;
	if (runtime->rate != in_rate) {
		target_rate = out_rate;
		target_val  = &_out;
	} else if (runtime->rate != out_rate) {
		target_rate = in_rate;
		target_val  = &_in;
	}

	if (target_rate)
		__rsnd_adg_get_timesel_ratio(priv, io,
					     target_rate,
					     target_val, &_en);

	if (in)
		*in = _in;
	if (out)
		*out = _out;
	if (en)
		*en = _en;
}

199
int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod,
K
Kuninori Morimoto 已提交
200 201
				 struct rsnd_dai_stream *io)
{
202
	struct rsnd_priv *priv = rsnd_mod_to_priv(cmd_mod);
203 204
	struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
	struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
205
	int id = rsnd_mod_id(cmd_mod);
K
Kuninori Morimoto 已提交
206 207 208
	int shift = (id % 2) ? 16 : 0;
	u32 mask, val;

209 210 211 212
	rsnd_adg_get_timesel_ratio(priv, io,
				   rsnd_src_get_in_rate(priv, io),
				   rsnd_src_get_out_rate(priv, io),
				   NULL, &val, NULL);
K
Kuninori Morimoto 已提交
213 214 215 216

	val  = val	<< shift;
	mask = 0xffff	<< shift;

217
	rsnd_mod_bset(adg_mod, CMDOUT_TIMSEL, mask, val);
K
Kuninori Morimoto 已提交
218 219 220 221

	return 0;
}

222 223 224 225
int rsnd_adg_set_src_timesel_gen2(struct rsnd_mod *src_mod,
				  struct rsnd_dai_stream *io,
				  unsigned int in_rate,
				  unsigned int out_rate)
226
{
227
	struct rsnd_priv *priv = rsnd_mod_to_priv(src_mod);
228 229
	struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
	struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
230 231
	u32 in, out;
	u32 mask, en;
232
	int id = rsnd_mod_id(src_mod);
233 234
	int shift = (id % 2) ? 16 : 0;

235 236
	rsnd_mod_confirm_src(src_mod);

237 238 239
	rsnd_adg_get_timesel_ratio(priv, io,
				   in_rate, out_rate,
				   &in, &out, &en);
240 241 242 243 244 245 246

	in   = in	<< shift;
	out  = out	<< shift;
	mask = 0xffff	<< shift;

	switch (id / 2) {
	case 0:
247 248
		rsnd_mod_bset(adg_mod, SRCIN_TIMSEL0,  mask, in);
		rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL0, mask, out);
249 250
		break;
	case 1:
251 252
		rsnd_mod_bset(adg_mod, SRCIN_TIMSEL1,  mask, in);
		rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL1, mask, out);
253 254
		break;
	case 2:
255 256
		rsnd_mod_bset(adg_mod, SRCIN_TIMSEL2,  mask, in);
		rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL2, mask, out);
257 258
		break;
	case 3:
259 260
		rsnd_mod_bset(adg_mod, SRCIN_TIMSEL3,  mask, in);
		rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL3, mask, out);
261 262
		break;
	case 4:
263 264
		rsnd_mod_bset(adg_mod, SRCIN_TIMSEL4,  mask, in);
		rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL4, mask, out);
265 266 267
		break;
	}

268 269
	if (en)
		rsnd_mod_bset(adg_mod, DIV_EN, en, en);
270

271
	return 0;
272 273
}

274
static void rsnd_adg_set_ssi_clk(struct rsnd_mod *ssi_mod, u32 val)
275
{
276
	struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
277 278
	struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
	struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
279
	int id = rsnd_mod_id(ssi_mod);
280 281 282
	int shift = (id % 4) * 8;
	u32 mask = 0xFF << shift;

283 284
	rsnd_mod_confirm_ssi(ssi_mod);

285
	val = val << shift;
286 287 288 289 290 291

	/*
	 * SSI 8 is not connected to ADG.
	 * it works with SSI 7
	 */
	if (id == 8)
292 293 294 295
		return;

	switch (id / 4) {
	case 0:
296
		rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL0, mask, val);
297 298
		break;
	case 1:
299
		rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL1, mask, val);
300 301
		break;
	case 2:
302
		rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL2, mask, val);
303 304
		break;
	}
305 306
}

307
int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod)
308
{
309
	rsnd_adg_set_ssi_clk(ssi_mod, 0);
310 311 312 313

	return 0;
}

314
int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
315
{
316
	struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
317 318 319
	struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
	struct device *dev = rsnd_priv_to_dev(priv);
	struct clk *clk;
320
	int i;
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
	u32 data;
	int sel_table[] = {
		[CLKA] = 0x1,
		[CLKB] = 0x2,
		[CLKC] = 0x3,
		[CLKI] = 0x0,
	};

	dev_dbg(dev, "request clock = %d\n", rate);

	/*
	 * find suitable clock from
	 * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI.
	 */
	data = 0;
	for_each_rsnd_clk(clk, adg, i) {
		if (rate == clk_get_rate(clk)) {
			data = sel_table[i];
			goto found_clock;
		}
	}

	/*
344
	 * find divided clock from BRGA/BRGB
345
	 */
346
	if (rate  == adg->rbga_rate_for_441khz) {
347 348 349 350
		data = 0x10;
		goto found_clock;
	}

351
	if (rate == adg->rbgb_rate_for_48khz) {
352 353 354 355 356 357 358 359
		data = 0x20;
		goto found_clock;
	}

	return -EIO;

found_clock:

360
	rsnd_adg_set_ssi_clk(ssi_mod, data);
361

362 363 364 365 366 367 368
	if (!(adg_mode_flags(adg) & LRCLK_ASYNC)) {
		struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
		u32 ckr = 0;

		if (0 == (rate % 8000))
			ckr = 0x80000000;

369
		rsnd_mod_bset(adg_mod, BRGCKR, 0x80000000, ckr);
370 371
	}

372
	dev_dbg(dev, "ADG: %s[%d] selects 0x%x for %d\n",
373
		rsnd_mod_name(ssi_mod), rsnd_mod_id(ssi_mod),
374
		data, rate);
375 376 377 378

	return 0;
}

379 380 381 382 383 384 385 386 387 388 389
static void rsnd_adg_get_clkin(struct rsnd_priv *priv,
			       struct rsnd_adg *adg)
{
	struct device *dev = rsnd_priv_to_dev(priv);
	struct clk *clk;
	static const char * const clk_name[] = {
		[CLKA]	= "clk_a",
		[CLKB]	= "clk_b",
		[CLKC]	= "clk_c",
		[CLKI]	= "clk_i",
	};
390
	int i, ret;
391 392 393 394 395 396

	for (i = 0; i < CLKMAX; i++) {
		clk = devm_clk_get(dev, clk_name[i]);
		adg->clk[i] = IS_ERR(clk) ? NULL : clk;
	}

397 398 399 400 401
	for_each_rsnd_clk(clk, adg, i) {
		ret = clk_prepare_enable(clk);
		if (ret < 0)
			dev_warn(dev, "can't use clk %d\n", i);

402
		dev_dbg(dev, "clk %d : %p : %ld\n", i, clk, clk_get_rate(clk));
403
	}
404 405
}

406 407
static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
				struct rsnd_adg *adg)
408 409
{
	struct clk *clk;
410
	struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
411
	struct device *dev = rsnd_priv_to_dev(priv);
412
	struct device_node *np = dev->of_node;
413
	u32 ckr, rbgx, rbga, rbgb;
414
	u32 rate, req_rate = 0, div;
415 416
	uint32_t count = 0;
	unsigned long req_48kHz_rate, req_441kHz_rate;
417
	int i;
418 419 420 421 422 423 424
	const char *parent_clk_name = NULL;
	static const char * const clkout_name[] = {
		[CLKOUT]  = "audio_clkout",
		[CLKOUT1] = "audio_clkout1",
		[CLKOUT2] = "audio_clkout2",
		[CLKOUT3] = "audio_clkout3",
	};
425 426 427 428 429 430 431
	int brg_table[] = {
		[CLKA] = 0x0,
		[CLKB] = 0x1,
		[CLKC] = 0x4,
		[CLKI] = 0x2,
	};

432 433 434 435 436 437 438 439 440 441 442 443 444 445
	of_property_read_u32(np, "#clock-cells", &count);

	/*
	 * ADG supports BRRA/BRRB output only
	 * this means all clkout0/1/2/3 will be same rate
	 */
	of_property_read_u32(np, "clock-frequency", &req_rate);
	req_48kHz_rate = 0;
	req_441kHz_rate = 0;
	if (0 == (req_rate % 44100))
		req_441kHz_rate = req_rate;
	if (0 == (req_rate % 48000))
		req_48kHz_rate = req_rate;

446 447 448 449 450 451 452
	/*
	 * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC
	 * have 44.1kHz or 48kHz base clocks for now.
	 *
	 * SSI itself can divide parent clock by 1/1 - 1/16
	 * see
	 *	rsnd_adg_ssi_clk_try_start()
453
	 *	rsnd_ssi_master_clk_start()
454 455
	 */
	ckr = 0;
456 457 458 459
	rbga = 2; /* default 1/6 */
	rbgb = 2; /* default 1/6 */
	adg->rbga_rate_for_441khz	= 0;
	adg->rbgb_rate_for_48khz	= 0;
460 461 462 463 464 465 466
	for_each_rsnd_clk(clk, adg, i) {
		rate = clk_get_rate(clk);

		if (0 == rate) /* not used */
			continue;

		/* RBGA */
467 468
		if (!adg->rbga_rate_for_441khz && (0 == rate % 44100)) {
			div = 6;
469 470
			if (req_441kHz_rate)
				div = rate / req_441kHz_rate;
471 472 473 474 475
			rbgx = rsnd_adg_calculate_rbgx(div);
			if (BRRx_MASK(rbgx) == rbgx) {
				rbga = rbgx;
				adg->rbga_rate_for_441khz = rate / div;
				ckr |= brg_table[i] << 20;
476 477
				if (req_441kHz_rate)
					parent_clk_name = __clk_get_name(clk);
478
			}
479 480 481
		}

		/* RBGB */
482 483
		if (!adg->rbgb_rate_for_48khz && (0 == rate % 48000)) {
			div = 6;
484 485
			if (req_48kHz_rate)
				div = rate / req_48kHz_rate;
486 487 488 489 490
			rbgx = rsnd_adg_calculate_rbgx(div);
			if (BRRx_MASK(rbgx) == rbgx) {
				rbgb = rbgx;
				adg->rbgb_rate_for_48khz = rate / div;
				ckr |= brg_table[i] << 16;
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
				if (req_48kHz_rate) {
					parent_clk_name = __clk_get_name(clk);
					ckr |= 0x80000000;
				}
			}
		}
	}

	/*
	 * ADG supports BRRA/BRRB output only.
	 * this means all clkout0/1/2/3 will be * same rate
	 */

	/*
	 * for clkout
	 */
	if (!count) {
508
		clk = clk_register_fixed_rate(dev, clkout_name[CLKOUT],
S
Stephen Boyd 已提交
509
					      parent_clk_name, 0, req_rate);
510 511 512 513 514 515 516 517 518 519 520
		if (!IS_ERR(clk)) {
			adg->clkout[CLKOUT] = clk;
			of_clk_add_provider(np, of_clk_src_simple_get, clk);
		}
	}
	/*
	 * for clkout0/1/2/3
	 */
	else {
		for (i = 0; i < CLKOUTMAX; i++) {
			clk = clk_register_fixed_rate(dev, clkout_name[i],
S
Stephen Boyd 已提交
521
						      parent_clk_name, 0,
522 523 524 525 526 527 528 529 530
						      req_rate);
			if (!IS_ERR(clk)) {
				adg->onecell.clks	= adg->clkout;
				adg->onecell.clk_num	= CLKOUTMAX;

				adg->clkout[i] = clk;

				of_clk_add_provider(np, of_clk_src_onecell_get,
						    &adg->onecell);
531
			}
532 533 534
		}
	}

535
	rsnd_mod_bset(adg_mod, BRGCKR, 0x80FF0000, ckr);
536 537 538
	rsnd_mod_write(adg_mod, BRRA,  rbga);
	rsnd_mod_write(adg_mod, BRRB,  rbgb);

539 540
	for_each_rsnd_clkout(clk, adg, i)
		dev_dbg(dev, "clkout %d : %p : %ld\n", i, clk, clk_get_rate(clk));
541
	dev_dbg(dev, "BRGCKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n",
542
		ckr, rbga, rbgb);
543 544
}

545
int rsnd_adg_probe(struct rsnd_priv *priv)
546 547 548
{
	struct rsnd_adg *adg;
	struct device *dev = rsnd_priv_to_dev(priv);
549
	struct device_node *np = dev->of_node;
550 551 552 553 554 555 556

	adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL);
	if (!adg) {
		dev_err(dev, "ADG allocate failed\n");
		return -ENOMEM;
	}

557
	rsnd_mod_init(priv, &adg->mod, &adg_ops,
558
		      NULL, NULL, 0, 0);
559

560
	rsnd_adg_get_clkin(priv, adg);
561
	rsnd_adg_get_clkout(priv, adg);
562

563 564 565
	if (of_get_property(np, "clkout-lr-asynchronous", NULL))
		adg->flags = LRCLK_ASYNC;

566 567 568 569
	priv->adg = adg;

	return 0;
}
570

571
void rsnd_adg_remove(struct rsnd_priv *priv)
572 573 574 575 576 577 578 579 580
{
	struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
	struct clk *clk;
	int i;

	for_each_rsnd_clk(clk, adg, i) {
		clk_disable_unprepare(clk);
	}
}