bytcr_rt5640.c 25.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 *  byt_cr_dpcm_rt5640.c - ASoc Machine driver for Intel Byt CR platform
 *
 *  Copyright (C) 2014 Intel Corp
 *  Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 of the License.
 *
 *  This program is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  General Public License for more details.
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */

#include <linux/init.h>
#include <linux/module.h>
22
#include <linux/moduleparam.h>
23
#include <linux/platform_device.h>
24
#include <linux/acpi.h>
25
#include <linux/clk.h>
26
#include <linux/device.h>
27
#include <linux/dmi.h>
28
#include <linux/slab.h>
29 30
#include <asm/cpu_device_id.h>
#include <asm/platform_sst_audio.h>
31 32 33
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
34
#include <sound/jack.h>
35
#include "../../codecs/rt5640.h"
36
#include "../atom/sst-atom-controls.h"
37
#include "../common/sst-acpi.h"
38
#include "../common/sst-dsp.h"
39

40 41 42 43
enum {
	BYT_RT5640_DMIC1_MAP,
	BYT_RT5640_DMIC2_MAP,
	BYT_RT5640_IN1_MAP,
44
	BYT_RT5640_IN3_MAP,
45 46
};

47
#define BYT_RT5640_MAP(quirk)	((quirk) &  GENMASK(7, 0))
48
#define BYT_RT5640_DMIC_EN	BIT(16)
49
#define BYT_RT5640_MONO_SPEAKER BIT(17)
50
#define BYT_RT5640_DIFF_MIC     BIT(18) /* defaut is single-ended */
51 52 53
#define BYT_RT5640_SSP2_AIF2    BIT(19) /* default is using AIF1  */
#define BYT_RT5640_SSP0_AIF1    BIT(20)
#define BYT_RT5640_SSP0_AIF2    BIT(21)
54 55 56 57 58 59
#define BYT_RT5640_MCLK_EN	BIT(22)
#define BYT_RT5640_MCLK_25MHZ	BIT(23)

struct byt_rt5640_private {
	struct clk *mclk;
};
60
static bool is_bytcr;
61

62
static unsigned long byt_rt5640_quirk = BYT_RT5640_MCLK_EN;
63
static unsigned int quirk_override;
64
module_param_named(quirk, quirk_override, uint, 0444);
65
MODULE_PARM_DESC(quirk, "Board-specific quirk override");
66

67 68
static void log_quirks(struct device *dev)
{
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
	int map;
	bool has_dmic = false;
	bool has_mclk = false;
	bool has_ssp0 = false;
	bool has_ssp0_aif1 = false;
	bool has_ssp0_aif2 = false;
	bool has_ssp2_aif2 = false;

	map = BYT_RT5640_MAP(byt_rt5640_quirk);
	switch (map) {
	case BYT_RT5640_DMIC1_MAP:
		dev_info(dev, "quirk DMIC1_MAP enabled\n");
		has_dmic = true;
		break;
	case BYT_RT5640_DMIC2_MAP:
		dev_info(dev, "quirk DMIC2_MAP enabled\n");
		has_dmic = true;
		break;
	case BYT_RT5640_IN1_MAP:
		dev_info(dev, "quirk IN1_MAP enabled\n");
		break;
	case BYT_RT5640_IN3_MAP:
		dev_info(dev, "quirk IN3_MAP enabled\n");
		break;
	default:
		dev_err(dev, "quirk map 0x%x is not supported, microphone input will not work\n", map);
		break;
	}
	if (byt_rt5640_quirk & BYT_RT5640_DMIC_EN) {
		if (has_dmic)
			dev_info(dev, "quirk DMIC enabled\n");
		else
			dev_err(dev, "quirk DMIC enabled but no DMIC input set, will be ignored\n");
	}
103
	if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER)
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
		dev_info(dev, "quirk MONO_SPEAKER enabled\n");
	if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) {
		if (!has_dmic)
			dev_info(dev, "quirk DIFF_MIC enabled\n");
		else
			dev_info(dev, "quirk DIFF_MIC enabled but DMIC input selected, will be ignored\n");
	}
	if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {
		dev_info(dev, "quirk SSP0_AIF1 enabled\n");
		has_ssp0 = true;
		has_ssp0_aif1 = true;
	}
	if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) {
		dev_info(dev, "quirk SSP0_AIF2 enabled\n");
		has_ssp0 = true;
		has_ssp0_aif2 = true;
	}
	if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) {
		dev_info(dev, "quirk SSP2_AIF2 enabled\n");
		has_ssp2_aif2 = true;
	}
	if (is_bytcr && !has_ssp0)
		dev_err(dev, "Invalid routing, bytcr detected but no SSP0-based quirk, audio cannot work with SSP2 on bytcr\n");
	if (has_ssp0_aif1 && has_ssp0_aif2)
		dev_err(dev, "Invalid routing, SSP0 cannot be connected to both AIF1 and AIF2\n");
	if (has_ssp0 && has_ssp2_aif2)
		dev_err(dev, "Invalid routing, cannot have both SSP0 and SSP2 connected to codec\n");

	if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
		dev_info(dev, "quirk MCLK_EN enabled\n");
		has_mclk = true;
	}
	if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) {
		if (has_mclk)
			dev_info(dev, "quirk MCLK_25MHZ enabled\n");
		else
			dev_err(dev, "quirk MCLK_25MHZ enabled but quirk MCLK not selected, will be ignored\n");
	}
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
#define BYT_CODEC_DAI1	"rt5640-aif1"
#define BYT_CODEC_DAI2	"rt5640-aif2"

static inline struct snd_soc_dai *byt_get_codec_dai(struct snd_soc_card *card)
{
	struct snd_soc_pcm_runtime *rtd;

	list_for_each_entry(rtd, &card->rtd_list, list) {
		if (!strncmp(rtd->codec_dai->name, BYT_CODEC_DAI1,
			     strlen(BYT_CODEC_DAI1)))
			return rtd->codec_dai;
		if (!strncmp(rtd->codec_dai->name, BYT_CODEC_DAI2,
				strlen(BYT_CODEC_DAI2)))
			return rtd->codec_dai;

	}
	return NULL;
}

static int platform_clock_control(struct snd_soc_dapm_widget *w,
				  struct snd_kcontrol *k, int  event)
{
	struct snd_soc_dapm_context *dapm = w->dapm;
	struct snd_soc_card *card = dapm->card;
	struct snd_soc_dai *codec_dai;
	struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
	int ret;

	codec_dai = byt_get_codec_dai(card);
	if (!codec_dai) {
		dev_err(card->dev,
			"Codec dai not found; Unable to set platform clock\n");
		return -EIO;
	}

	if (SND_SOC_DAPM_EVENT_ON(event)) {
181
		if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
182 183 184
			ret = clk_prepare_enable(priv->mclk);
			if (ret < 0) {
				dev_err(card->dev,
185
					"could not configure MCLK state\n");
186 187 188 189 190 191 192 193 194 195 196 197 198
				return ret;
			}
		}
		ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1,
					     48000 * 512,
					     SND_SOC_CLOCK_IN);
	} else {
		/*
		 * Set codec clock source to internal clock before
		 * turning off the platform clock. Codec needs clock
		 * for Jack detection and button press
		 */
		ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_RCCLK,
199
					     48000 * 512,
200 201
					     SND_SOC_CLOCK_IN);
		if (!ret) {
202
			if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN)
203 204 205 206 207 208 209 210 211 212 213
				clk_disable_unprepare(priv->mclk);
		}
	}

	if (ret < 0) {
		dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
		return ret;
	}

	return 0;
}
214

215
static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {
216 217
	SND_SOC_DAPM_HP("Headphone", NULL),
	SND_SOC_DAPM_MIC("Headset Mic", NULL),
218 219
	SND_SOC_DAPM_MIC("Internal Mic", NULL),
	SND_SOC_DAPM_SPK("Speaker", NULL),
220 221 222 223
	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
			    platform_clock_control, SND_SOC_DAPM_PRE_PMU |
			    SND_SOC_DAPM_POST_PMD),

224 225
};

226
static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
227 228 229 230 231
	{"Headphone", NULL, "Platform Clock"},
	{"Headset Mic", NULL, "Platform Clock"},
	{"Internal Mic", NULL, "Platform Clock"},
	{"Speaker", NULL, "Platform Clock"},

232
	{"Headset Mic", NULL, "MICBIAS1"},
233
	{"IN2P", NULL, "Headset Mic"},
234 235 236 237
	{"Headphone", NULL, "HPOL"},
	{"Headphone", NULL, "HPOR"},
};

238 239 240 241 242 243 244 245 246 247 248 249 250
static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = {
	{"DMIC1", NULL, "Internal Mic"},
};

static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = {
	{"DMIC2", NULL, "Internal Mic"},
};

static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = {
	{"Internal Mic", NULL, "MICBIAS1"},
	{"IN1P", NULL, "Internal Mic"},
};

251 252 253 254 255
static const struct snd_soc_dapm_route byt_rt5640_intmic_in3_map[] = {
	{"Internal Mic", NULL, "MICBIAS1"},
	{"IN3P", NULL, "Internal Mic"},
};

256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif1_map[] = {
	{"ssp2 Tx", NULL, "codec_out0"},
	{"ssp2 Tx", NULL, "codec_out1"},
	{"codec_in0", NULL, "ssp2 Rx"},
	{"codec_in1", NULL, "ssp2 Rx"},

	{"AIF1 Playback", NULL, "ssp2 Tx"},
	{"ssp2 Rx", NULL, "AIF1 Capture"},
};

static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif2_map[] = {
	{"ssp2 Tx", NULL, "codec_out0"},
	{"ssp2 Tx", NULL, "codec_out1"},
	{"codec_in0", NULL, "ssp2 Rx"},
	{"codec_in1", NULL, "ssp2 Rx"},

	{"AIF2 Playback", NULL, "ssp2 Tx"},
	{"ssp2 Rx", NULL, "AIF2 Capture"},
};

276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif1_map[] = {
	{"ssp0 Tx", NULL, "modem_out"},
	{"modem_in", NULL, "ssp0 Rx"},

	{"AIF1 Playback", NULL, "ssp0 Tx"},
	{"ssp0 Rx", NULL, "AIF1 Capture"},
};

static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif2_map[] = {
	{"ssp0 Tx", NULL, "modem_out"},
	{"modem_in", NULL, "ssp0 Rx"},

	{"AIF2 Playback", NULL, "ssp0 Tx"},
	{"ssp0 Rx", NULL, "AIF2 Capture"},
};

292 293 294 295 296 297 298 299 300 301 302 303
static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = {
	{"Speaker", NULL, "SPOLP"},
	{"Speaker", NULL, "SPOLN"},
	{"Speaker", NULL, "SPORP"},
	{"Speaker", NULL, "SPORN"},
};

static const struct snd_soc_dapm_route byt_rt5640_mono_spk_map[] = {
	{"Speaker", NULL, "SPOLP"},
	{"Speaker", NULL, "SPOLN"},
};

304
static const struct snd_kcontrol_new byt_rt5640_controls[] = {
305 306
	SOC_DAPM_PIN_SWITCH("Headphone"),
	SOC_DAPM_PIN_SWITCH("Headset Mic"),
307 308
	SOC_DAPM_PIN_SWITCH("Internal Mic"),
	SOC_DAPM_PIN_SWITCH("Speaker"),
309 310
};

311
static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream,
312 313 314 315 316 317 318 319 320
					struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	int ret;

	ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1,
				     params_rate(params) * 512,
				     SND_SOC_CLOCK_IN);
321

322 323 324 325 326
	if (ret < 0) {
		dev_err(rtd->dev, "can't set codec clock %d\n", ret);
		return ret;
	}

327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
	if (!(byt_rt5640_quirk & BYT_RT5640_MCLK_EN)) {
		/* use bitclock as PLL input */
		if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||
			(byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {

			/* 2x16 bit slots on SSP0 */
			ret = snd_soc_dai_set_pll(codec_dai, 0,
						RT5640_PLL1_S_BCLK1,
						params_rate(params) * 32,
						params_rate(params) * 512);
		} else {
			/* 2x15 bit slots on SSP2 */
			ret = snd_soc_dai_set_pll(codec_dai, 0,
						RT5640_PLL1_S_BCLK1,
						params_rate(params) * 50,
						params_rate(params) * 512);
		}
344
	} else {
345 346 347 348 349 350 351 352 353 354 355
		if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) {
			ret = snd_soc_dai_set_pll(codec_dai, 0,
						RT5640_PLL1_S_MCLK,
						25000000,
						params_rate(params) * 512);
		} else {
			ret = snd_soc_dai_set_pll(codec_dai, 0,
						RT5640_PLL1_S_MCLK,
						19200000,
						params_rate(params) * 512);
		}
356 357
	}

358 359 360 361 362 363 364 365
	if (ret < 0) {
		dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
		return ret;
	}

	return 0;
}

366 367 368 369 370 371 372 373 374 375
static int byt_rt5640_quirk_cb(const struct dmi_system_id *id)
{
	byt_rt5640_quirk = (unsigned long)id->driver_data;
	return 1;
}

static const struct dmi_system_id byt_rt5640_quirk_table[] = {
	{
		.callback = byt_rt5640_quirk_cb,
		.matches = {
376 377
			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
378
		},
379 380
		.driver_data = (void *)(BYT_RT5640_IN1_MAP |
					BYT_RT5640_MCLK_EN),
381 382 383 384
	},
	{
		.callback = byt_rt5640_quirk_cb,
		.matches = {
385 386 387
			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"),
		},
388 389 390 391 392
		.driver_data = (void *)(BYT_RT5640_IN1_MAP |
					BYT_RT5640_MONO_SPEAKER |
					BYT_RT5640_DIFF_MIC |
					BYT_RT5640_SSP0_AIF2 |
					BYT_RT5640_MCLK_EN),
393 394 395 396 397 398
	},
	{
		.callback = byt_rt5640_quirk_cb,
		.matches = {
			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "DellInc."),
			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"),
399
		},
400 401 402
		.driver_data = (void *)(BYT_RT5640_DMIC2_MAP |
					BYT_RT5640_DMIC_EN |
					BYT_RT5640_MCLK_EN),
403
	},
404 405 406
	{
		.callback = byt_rt5640_quirk_cb,
		.matches = {
407 408
			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"),
409
		},
410 411
		.driver_data = (void *)(BYT_RT5640_IN1_MAP |
					BYT_RT5640_MCLK_EN),
412
	},
413 414 415 416 417 418
	{
		.callback = byt_rt5640_quirk_cb,
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
			DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"),
		},
419 420
		.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
					BYT_RT5640_DMIC_EN),
421
	},
422 423 424 425 426 427
	{
		.callback = byt_rt5640_quirk_cb,
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
			DMI_MATCH(DMI_BOARD_NAME, "tPAD"),
		},
428 429 430
		.driver_data = (void *)(BYT_RT5640_IN3_MAP |
					BYT_RT5640_MCLK_EN |
					BYT_RT5640_SSP0_AIF1),
431
	},
432 433 434 435 436 437
	{
		.callback = byt_rt5640_quirk_cb,
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),
		},
438
		.driver_data = (void *)(BYT_RT5640_IN1_MAP |
439 440 441
						 BYT_RT5640_MCLK_EN |
						 BYT_RT5640_SSP0_AIF1),

442 443 444 445 446 447
	},
	{
		.callback = byt_rt5640_quirk_cb,
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
		},
448 449 450
		.driver_data = (void *)(BYT_RT5640_IN3_MAP |
					BYT_RT5640_MCLK_EN |
					BYT_RT5640_SSP0_AIF1),
451 452

	},
453 454 455
	{}
};

456 457 458
static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
{
	struct snd_soc_card *card = runtime->card;
459
	struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
460 461
	struct snd_soc_codec *codec = runtime->codec;
	const struct snd_soc_dapm_route *custom_map;
462
	int num_routes;
463
	int ret;
464 465 466

	card->dapm.idle_bias_off = true;

467 468
	rt5640_sel_asrc_clk_src(codec,
				RT5640_DA_STEREO_FILTER |
469 470 471 472 473
				RT5640_DA_MONO_L_FILTER	|
				RT5640_DA_MONO_R_FILTER	|
				RT5640_AD_STEREO_FILTER	|
				RT5640_AD_MONO_L_FILTER	|
				RT5640_AD_MONO_R_FILTER,
474 475
				RT5640_CLK_SEL_ASRC);

476 477 478 479 480 481 482 483 484 485 486 487
	ret = snd_soc_add_card_controls(card, byt_rt5640_controls,
					ARRAY_SIZE(byt_rt5640_controls));
	if (ret) {
		dev_err(card->dev, "unable to add card controls\n");
		return ret;
	}

	switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
	case BYT_RT5640_IN1_MAP:
		custom_map = byt_rt5640_intmic_in1_map;
		num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map);
		break;
488 489 490 491
	case BYT_RT5640_IN3_MAP:
		custom_map = byt_rt5640_intmic_in3_map;
		num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map);
		break;
492 493 494 495 496 497 498 499 500 501 502 503 504
	case BYT_RT5640_DMIC2_MAP:
		custom_map = byt_rt5640_intmic_dmic2_map;
		num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map);
		break;
	default:
		custom_map = byt_rt5640_intmic_dmic1_map;
		num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map);
	}

	ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
	if (ret)
		return ret;

505 506 507 508
	if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) {
		ret = snd_soc_dapm_add_routes(&card->dapm,
					byt_rt5640_ssp2_aif2_map,
					ARRAY_SIZE(byt_rt5640_ssp2_aif2_map));
509 510 511 512 513 514 515 516
	} else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {
		ret = snd_soc_dapm_add_routes(&card->dapm,
					byt_rt5640_ssp0_aif1_map,
					ARRAY_SIZE(byt_rt5640_ssp0_aif1_map));
	} else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) {
		ret = snd_soc_dapm_add_routes(&card->dapm,
					byt_rt5640_ssp0_aif2_map,
					ARRAY_SIZE(byt_rt5640_ssp0_aif2_map));
517 518 519 520 521 522 523 524
	} else {
		ret = snd_soc_dapm_add_routes(&card->dapm,
					byt_rt5640_ssp2_aif1_map,
					ARRAY_SIZE(byt_rt5640_ssp2_aif1_map));
	}
	if (ret)
		return ret;

525 526 527 528 529 530 531 532 533 534 535 536
	if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {
		ret = snd_soc_dapm_add_routes(&card->dapm,
					byt_rt5640_mono_spk_map,
					ARRAY_SIZE(byt_rt5640_mono_spk_map));
	} else {
		ret = snd_soc_dapm_add_routes(&card->dapm,
					byt_rt5640_stereo_spk_map,
					ARRAY_SIZE(byt_rt5640_stereo_spk_map));
	}
	if (ret)
		return ret;

537 538 539 540 541
	if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) {
		snd_soc_update_bits(codec,  RT5640_IN1_IN2, RT5640_IN_DF1,
				    RT5640_IN_DF1);
	}

542 543 544 545 546 547 548 549 550
	if (byt_rt5640_quirk & BYT_RT5640_DMIC_EN) {
		ret = rt5640_dmic_enable(codec, 0, 0);
		if (ret)
			return ret;
	}

	snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone");
	snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");

551
	if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
		/*
		 * The firmware might enable the clock at
		 * boot (this information may or may not
		 * be reflected in the enable clock register).
		 * To change the rate we must disable the clock
		 * first to cover these cases. Due to common
		 * clock framework restrictions that do not allow
		 * to disable a clock that has not been enabled,
		 * we need to enable the clock first.
		 */
		ret = clk_prepare_enable(priv->mclk);
		if (!ret)
			clk_disable_unprepare(priv->mclk);

		if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ)
			ret = clk_set_rate(priv->mclk, 25000000);
		else
			ret = clk_set_rate(priv->mclk, 19200000);

		if (ret)
			dev_err(card->dev, "unable to set MCLK rate\n");
	}

575 576 577
	return ret;
}

578
static const struct snd_soc_pcm_stream byt_rt5640_dai_params = {
579 580 581 582 583 584 585
	.formats = SNDRV_PCM_FMTBIT_S24_LE,
	.rate_min = 48000,
	.rate_max = 48000,
	.channels_min = 2,
	.channels_max = 2,
};

586
static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd,
587 588 589 590 591 592
			    struct snd_pcm_hw_params *params)
{
	struct snd_interval *rate = hw_param_interval(params,
			SNDRV_PCM_HW_PARAM_RATE);
	struct snd_interval *channels = hw_param_interval(params,
						SNDRV_PCM_HW_PARAM_CHANNELS);
593
	int ret;
594

595
	/* The DSP will covert the FE rate to 48k, stereo */
596 597 598
	rate->min = rate->max = 48000;
	channels->min = channels->max = 2;

599 600 601
	if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||
		(byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {

602
		/* set SSP0 to 16-bit */
603 604 605 606 607 608 609 610 611
		params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);

		/*
		 * Default mode for SSP configuration is TDM 4 slot, override config
		 * with explicit setting to I2S 2ch 16-bit. The word length is set with
		 * dai_set_tdm_slot() since there is no other API exposed
		 */
		ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
					SND_SOC_DAIFMT_I2S     |
612
					SND_SOC_DAIFMT_NB_NF   |
613 614 615 616 617 618
					SND_SOC_DAIFMT_CBS_CFS
			);
		if (ret < 0) {
			dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
			return ret;
		}
619

620 621 622 623 624 625 626
		ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 16);
		if (ret < 0) {
			dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
			return ret;
		}

	} else {
627

628 629 630 631 632 633 634 635 636 637
		/* set SSP2 to 24-bit */
		params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);

		/*
		 * Default mode for SSP configuration is TDM 4 slot, override config
		 * with explicit setting to I2S 2ch 24-bit. The word length is set with
		 * dai_set_tdm_slot() since there is no other API exposed
		 */
		ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
					SND_SOC_DAIFMT_I2S     |
638
					SND_SOC_DAIFMT_NB_NF   |
639 640 641 642 643 644 645 646 647 648 649 650 651
					SND_SOC_DAIFMT_CBS_CFS
			);
		if (ret < 0) {
			dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
			return ret;
		}

		ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
		if (ret < 0) {
			dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
			return ret;
		}
	}
652 653 654
	return 0;
}

655
static int byt_rt5640_aif1_startup(struct snd_pcm_substream *substream)
656
{
657 658
	return snd_pcm_hw_constraint_single(substream->runtime,
			SNDRV_PCM_HW_PARAM_RATE, 48000);
659 660
}

661
static const struct snd_soc_ops byt_rt5640_aif1_ops = {
662
	.startup = byt_rt5640_aif1_startup,
663 664
};

665
static const struct snd_soc_ops byt_rt5640_be_ssp2_ops = {
666
	.hw_params = byt_rt5640_aif1_hw_params,
667 668
};

669
static struct snd_soc_dai_link byt_rt5640_dais[] = {
670 671 672 673 674 675 676
	[MERR_DPCM_AUDIO] = {
		.name = "Baytrail Audio Port",
		.stream_name = "Baytrail Audio",
		.cpu_dai_name = "media-cpu-dai",
		.codec_dai_name = "snd-soc-dummy-dai",
		.codec_name = "snd-soc-dummy",
		.platform_name = "sst-mfld-platform",
677
		.nonatomic = true,
678 679 680
		.dynamic = 1,
		.dpcm_playback = 1,
		.dpcm_capture = 1,
681
		.ops = &byt_rt5640_aif1_ops,
682
	},
683 684 685 686 687 688 689 690 691 692 693 694
	[MERR_DPCM_DEEP_BUFFER] = {
		.name = "Deep-Buffer Audio Port",
		.stream_name = "Deep-Buffer Audio",
		.cpu_dai_name = "deepbuffer-cpu-dai",
		.codec_dai_name = "snd-soc-dummy-dai",
		.codec_name = "snd-soc-dummy",
		.platform_name = "sst-mfld-platform",
		.nonatomic = true,
		.dynamic = 1,
		.dpcm_playback = 1,
		.ops = &byt_rt5640_aif1_ops,
	},
695 696 697 698 699 700 701 702 703 704 705
	[MERR_DPCM_COMPR] = {
		.name = "Baytrail Compressed Port",
		.stream_name = "Baytrail Compress",
		.cpu_dai_name = "compress-cpu-dai",
		.codec_dai_name = "snd-soc-dummy-dai",
		.codec_name = "snd-soc-dummy",
		.platform_name = "sst-mfld-platform",
	},
		/* back ends */
	{
		.name = "SSP2-Codec",
706
		.id = 1,
707
		.cpu_dai_name = "ssp2-port", /* overwritten for ssp0 routing */
708 709
		.platform_name = "sst-mfld-platform",
		.no_pcm = 1,
710
		.codec_dai_name = "rt5640-aif1", /* changed w/ quirk */
711
		.codec_name = "i2c-10EC5640:00", /* overwritten with HID */
712 713
		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
						| SND_SOC_DAIFMT_CBS_CFS,
714
		.be_hw_params_fixup = byt_rt5640_codec_fixup,
715
		.ignore_suspend = 1,
716
		.nonatomic = true,
717 718
		.dpcm_playback = 1,
		.dpcm_capture = 1,
719
		.init = byt_rt5640_init,
720
		.ops = &byt_rt5640_be_ssp2_ops,
721 722 723 724
	},
};

/* SoC card */
725
static struct snd_soc_card byt_rt5640_card = {
726
	.name = "bytcr-rt5640",
A
Axel Lin 已提交
727
	.owner = THIS_MODULE,
728 729 730 731 732 733
	.dai_link = byt_rt5640_dais,
	.num_links = ARRAY_SIZE(byt_rt5640_dais),
	.dapm_widgets = byt_rt5640_widgets,
	.num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets),
	.dapm_routes = byt_rt5640_audio_map,
	.num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map),
734
	.fully_routed = true,
735 736
};

737
static char byt_rt5640_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */
738
static char byt_rt5640_codec_aif_name[12]; /*  = "rt5640-aif[1|2]" */
739
static char byt_rt5640_cpu_dai_name[10]; /*  = "ssp[0|2]-port" */
740

741 742
static bool is_valleyview(void)
{
743
	static const struct x86_cpu_id cpu_ids[] = {
744 745 746 747 748 749 750 751 752
		{ X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */
		{}
	};

	if (!x86_match_cpu(cpu_ids))
		return false;
	return true;
}

753 754 755 756
struct acpi_chan_package {   /* ACPICA seems to require 64 bit integers */
	u64 aif_value;       /* 1: AIF1, 2: AIF2 */
	u64 mclock_value;    /* usually 25MHz (0x17d7940), ignored */
};
757

758
static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
759
{
760
	struct byt_rt5640_private *priv;
761
	struct sst_acpi_mach *mach;
762
	const char *i2c_name = NULL;
763
	int ret_val = 0;
764
	int dai_index;
765
	int i;
766

767
	is_bytcr = false;
768 769 770
	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC);
	if (!priv)
		return -ENOMEM;
771 772

	/* register the soc card */
773
	byt_rt5640_card.dev = &pdev->dev;
774
	mach = byt_rt5640_card.dev->platform_data;
775
	snd_soc_card_set_drvdata(&byt_rt5640_card, priv);
776

777 778 779 780 781 782 783 784 785
	/* fix index of codec dai */
	dai_index = MERR_DPCM_COMPR + 1;
	for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) {
		if (!strcmp(byt_rt5640_dais[i].codec_name, "i2c-10EC5640:00")) {
			dai_index = i;
			break;
		}
	}

786
	/* fixup codec name based on HID */
787
	i2c_name = sst_acpi_find_name_from_hid(mach->id);
788
	if (i2c_name) {
789 790 791 792 793
		snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name),
			"%s%s", "i2c-", i2c_name);

		byt_rt5640_dais[dai_index].codec_name = byt_rt5640_codec_name;
	}
794

795 796 797 798 799 800 801 802
	/*
	 * swap SSP0 if bytcr is detected
	 * (will be overridden if DMI quirk is detected)
	 */
	if (is_valleyview()) {
		struct sst_platform_info *p_info = mach->pdata;
		const struct sst_res_info *res_info = p_info->res_info;

803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848
		if (res_info->acpi_ipc_irq_index == 0)
			is_bytcr = true;
	}

	if (is_bytcr) {
		/*
		 * Baytrail CR platforms may have CHAN package in BIOS, try
		 * to find relevant routing quirk based as done on Windows
		 * platforms. We have to read the information directly from the
		 * BIOS, at this stage the card is not created and the links
		 * with the codec driver/pdata are non-existent
		 */

		struct acpi_chan_package chan_package;

		/* format specified: 2 64-bit integers */
		struct acpi_buffer format = {sizeof("NN"), "NN"};
		struct acpi_buffer state = {0, NULL};
		struct sst_acpi_package_context pkg_ctx;
		bool pkg_found = false;

		state.length = sizeof(chan_package);
		state.pointer = &chan_package;

		pkg_ctx.name = "CHAN";
		pkg_ctx.length = 2;
		pkg_ctx.format = &format;
		pkg_ctx.state = &state;
		pkg_ctx.data_valid = false;

		pkg_found = sst_acpi_find_package_from_hid(mach->id, &pkg_ctx);
		if (pkg_found) {
			if (chan_package.aif_value == 1) {
				dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n");
				byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF1;
			} else  if (chan_package.aif_value == 2) {
				dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n");
				byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
			} else {
				dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n");
				pkg_found = false;
			}
		}

		if (!pkg_found) {
			/* no BIOS indications, assume SSP0-AIF2 connection */
849 850
			byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
		}
851 852 853 854 855 856 857

		/* change defaults for Baytrail-CR capture */
		byt_rt5640_quirk |= BYT_RT5640_IN1_MAP;
		byt_rt5640_quirk |= BYT_RT5640_DIFF_MIC;
	} else {
		byt_rt5640_quirk |= (BYT_RT5640_DMIC1_MAP |
				BYT_RT5640_DMIC_EN);
858 859
	}

860 861
	/* check quirks before creating card */
	dmi_check_system(byt_rt5640_quirk_table);
862
	if (quirk_override) {
863
		dev_info(&pdev->dev, "Overriding quirk 0x%x => 0x%x\n",
864 865 866
			 (unsigned int)byt_rt5640_quirk, quirk_override);
		byt_rt5640_quirk = quirk_override;
	}
867
	log_quirks(&pdev->dev);
868

869 870
	if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) ||
	    (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {
871 872 873 874 875 876 877 878 879 880

		/* fixup codec aif name */
		snprintf(byt_rt5640_codec_aif_name,
			sizeof(byt_rt5640_codec_aif_name),
			"%s", "rt5640-aif2");

		byt_rt5640_dais[dai_index].codec_dai_name =
			byt_rt5640_codec_aif_name;
	}

881 882 883 884 885 886 887 888 889 890 891 892
	if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||
	    (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {

		/* fixup cpu dai name name */
		snprintf(byt_rt5640_cpu_dai_name,
			sizeof(byt_rt5640_cpu_dai_name),
			"%s", "ssp0-port");

		byt_rt5640_dais[dai_index].cpu_dai_name =
			byt_rt5640_cpu_dai_name;
	}

893
	if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
894 895
		priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
		if (IS_ERR(priv->mclk)) {
896 897
			ret_val = PTR_ERR(priv->mclk);

898
			dev_err(&pdev->dev,
899 900 901 902 903 904 905 906 907 908 909
				"Failed to get MCLK from pmc_plt_clk_3: %d\n",
				ret_val);

			/*
			 * Fall back to bit clock usage for -ENOENT (clock not
			 * available likely due to missing dependencies), bail
			 * for all other errors, including -EPROBE_DEFER
			 */
			if (ret_val != -ENOENT)
				return ret_val;
			byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN;
910 911 912
		}
	}

913
	ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card);
914 915

	if (ret_val) {
916 917
		dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
			ret_val);
918 919
		return ret_val;
	}
920
	platform_set_drvdata(pdev, &byt_rt5640_card);
921 922 923
	return ret_val;
}

924
static struct platform_driver snd_byt_rt5640_mc_driver = {
925
	.driver = {
926
		.name = "bytcr_rt5640",
927
	},
928
	.probe = snd_byt_rt5640_mc_probe,
929 930
};

931
module_platform_driver(snd_byt_rt5640_mc_driver);
932 933 934 935

MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver");
MODULE_AUTHOR("Subhransu S. Prusty <subhransu.s.prusty@intel.com>");
MODULE_LICENSE("GPL v2");
936
MODULE_ALIAS("platform:bytcr_rt5640");