intel_hdmi_audio.c 49.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 *   intel_hdmi_audio.c - Intel HDMI audio driver
 *
 *  Copyright (C) 2016 Intel Corp
 *  Authors:	Sailaja Bandarupalli <sailaja.bandarupalli@intel.com>
 *		Ramesh Babu K V	<ramesh.babu@intel.com>
 *		Vaibhav Agarwal <vaibhav.agarwal@intel.com>
 *		Jerome Anand <jerome.anand@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.
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * ALSA driver for Intel HDMI audio
 */

24
#include <linux/types.h>
25 26 27 28
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/module.h>
29
#include <linux/interrupt.h>
30
#include <linux/pm_runtime.h>
31
#include <linux/dma-mapping.h>
32 33
#include <asm/cacheflush.h>
#include <sound/core.h>
34 35
#include <sound/asoundef.h>
#include <sound/pcm.h>
36 37 38
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/control.h>
39
#include <drm/drm_edid.h>
40
#include <drm/intel_lpe_audio.h>
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
#include "intel_hdmi_audio.h"

/*standard module options for ALSA. This module supports only one card*/
static int hdmi_card_index = SNDRV_DEFAULT_IDX1;
static char *hdmi_card_id = SNDRV_DEFAULT_STR1;

module_param_named(index, hdmi_card_index, int, 0444);
MODULE_PARM_DESC(index,
		"Index value for INTEL Intel HDMI Audio controller.");
module_param_named(id, hdmi_card_id, charp, 0444);
MODULE_PARM_DESC(id,
		"ID string for INTEL Intel HDMI Audio controller.");

/*
 * ELD SA bits in the CEA Speaker Allocation data block
 */
T
Takashi Iwai 已提交
57
static const int eld_speaker_allocation_bits[] = {
58 59 60 61 62 63 64 65 66 67 68 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 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
	[0] = FL | FR,
	[1] = LFE,
	[2] = FC,
	[3] = RL | RR,
	[4] = RC,
	[5] = FLC | FRC,
	[6] = RLC | RRC,
	/* the following are not defined in ELD yet */
	[7] = 0,
};

/*
 * This is an ordered list!
 *
 * The preceding ones have better chances to be selected by
 * hdmi_channel_allocation().
 */
static struct cea_channel_speaker_allocation channel_allocations[] = {
/*                        channel:   7     6    5    4    3     2    1    0  */
{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
				/* 2.1 */
{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
				/* Dolby Surround */
{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
				/* surround40 */
{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
				/* surround41 */
{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
				/* surround50 */
{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
				/* surround51 */
{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
				/* 6.1 */
{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
				/* surround71 */
{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },

{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
};

T
Takashi Iwai 已提交
120
static const struct channel_map_table map_tables[] = {
121 122 123 124 125 126 127 128 129 130 131 132
	{ SNDRV_CHMAP_FL,       0x00,   FL },
	{ SNDRV_CHMAP_FR,       0x01,   FR },
	{ SNDRV_CHMAP_RL,       0x04,   RL },
	{ SNDRV_CHMAP_RR,       0x05,   RR },
	{ SNDRV_CHMAP_LFE,      0x02,   LFE },
	{ SNDRV_CHMAP_FC,       0x03,   FC },
	{ SNDRV_CHMAP_RLC,      0x06,   RLC },
	{ SNDRV_CHMAP_RRC,      0x07,   RRC },
	{} /* terminator */
};

/* hardware capability structure */
133
static const struct snd_pcm_hardware had_pcm_hardware = {
134 135 136 137 138
	.info =	(SNDRV_PCM_INFO_INTERLEAVED |
		SNDRV_PCM_INFO_DOUBLE |
		SNDRV_PCM_INFO_MMAP|
		SNDRV_PCM_INFO_MMAP_VALID |
		SNDRV_PCM_INFO_BATCH),
139
	.formats = SNDRV_PCM_FMTBIT_S24,
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
	.rates = SNDRV_PCM_RATE_32000 |
		SNDRV_PCM_RATE_44100 |
		SNDRV_PCM_RATE_48000 |
		SNDRV_PCM_RATE_88200 |
		SNDRV_PCM_RATE_96000 |
		SNDRV_PCM_RATE_176400 |
		SNDRV_PCM_RATE_192000,
	.rate_min = HAD_MIN_RATE,
	.rate_max = HAD_MAX_RATE,
	.channels_min = HAD_MIN_CHANNEL,
	.channels_max = HAD_MAX_CHANNEL,
	.buffer_bytes_max = HAD_MAX_BUFFER,
	.period_bytes_min = HAD_MIN_PERIOD_BYTES,
	.period_bytes_max = HAD_MAX_PERIOD_BYTES,
	.periods_min = HAD_MIN_PERIODS,
	.periods_max = HAD_MAX_PERIODS,
	.fifo_size = HAD_FIFO_SIZE,
};

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
/* Get the active PCM substream;
 * Call had_substream_put() for unreferecing.
 * Don't call this inside had_spinlock, as it takes by itself
 */
static struct snd_pcm_substream *
had_substream_get(struct snd_intelhad *intelhaddata)
{
	struct snd_pcm_substream *substream;
	unsigned long flags;

	spin_lock_irqsave(&intelhaddata->had_spinlock, flags);
	substream = intelhaddata->stream_info.substream;
	if (substream)
		intelhaddata->stream_info.substream_refcount++;
	spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags);
	return substream;
}

/* Unref the active PCM substream;
 * Don't call this inside had_spinlock, as it takes by itself
 */
static void had_substream_put(struct snd_intelhad *intelhaddata)
{
	unsigned long flags;

	spin_lock_irqsave(&intelhaddata->had_spinlock, flags);
	intelhaddata->stream_info.substream_refcount--;
	spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags);
}

189
/* Register access functions */
190
static void had_read_register(struct snd_intelhad *ctx, u32 reg, u32 *val)
191
{
192
	*val = ioread32(ctx->mmio_start + ctx->had_config_offset + reg);
193 194
}

195
static void had_write_register(struct snd_intelhad *ctx, u32 reg, u32 val)
196
{
197
	iowrite32(val, ctx->mmio_start + ctx->had_config_offset + reg);
198 199
}

200
/*
201 202
 * enable / disable audio configuration
 *
203
 * The normal read/modify should not directly be used on VLV2 for
204
 * updating AUD_CONFIG register.
205 206 207 208 209 210 211 212 213 214
 * This is because:
 * Bit6 of AUD_CONFIG register is writeonly due to a silicon bug on VLV2
 * HDMI IP. As a result a read-modify of AUD_CONFIG regiter will always
 * clear bit6. AUD_CONFIG[6:4] represents the "channels" field of the
 * register. This field should be 1xy binary for configuration with 6 or
 * more channels. Read-modify of AUD_CONFIG (Eg. for enabling audio)
 * causes the "channels" field to be updated as 0xy binary resulting in
 * bad audio. The fix is to always write the AUD_CONFIG[6:4] with
 * appropriate value when doing read-modify of AUD_CONFIG register.
 */
215 216 217
static void had_enable_audio(struct snd_pcm_substream *substream,
			     struct snd_intelhad *intelhaddata,
			     bool enable)
218
{
219
	union aud_cfg cfg_val = {.regval = 0};
220 221
	u8 channels;
	u32 mask, val;
222 223 224 225 226

	/*
	 * If substream is NULL, there is no active stream.
	 * In this case just set channels to 2
	 */
227
	channels = substream ? substream->runtime->channels : 2;
228
	dev_dbg(intelhaddata->dev, "enable %d, ch=%d\n", enable, channels);
229

230
	cfg_val.regx.num_ch = channels - 2;
231
	if (enable)
232
		cfg_val.regx.aud_en = 1;
233
	mask = AUD_CONFIG_CH_MASK | 1;
234

235 236 237 238
	had_read_register(intelhaddata, AUD_CONFIG, &val);
	val &= ~mask;
	val |= cfg_val.regval;
	had_write_register(intelhaddata, AUD_CONFIG, val);
239 240
}

241 242
/* forcibly ACKs to both BUFFER_DONE and BUFFER_UNDERRUN interrupts */
static void had_ack_irqs(struct snd_intelhad *ctx)
243 244 245
{
	u32 status_reg;

246 247 248 249
	had_read_register(ctx, AUD_HDMI_STATUS, &status_reg);
	status_reg |= HDMI_AUDIO_BUFFER_DONE | HDMI_AUDIO_UNDERRUN;
	had_write_register(ctx, AUD_HDMI_STATUS, status_reg);
	had_read_register(ctx, AUD_HDMI_STATUS, &status_reg);
250 251
}

252 253
/* Reset buffer pointers */
static void had_reset_audio(struct snd_intelhad *intelhaddata)
254
{
255 256
	had_write_register(intelhaddata, AUD_HDMI_STATUS, 1);
	had_write_register(intelhaddata, AUD_HDMI_STATUS, 0);
257 258
}

T
Takashi Iwai 已提交
259
/*
260 261 262 263 264 265
 * initialize audio channel status registers
 * This function is called in the prepare callback
 */
static int had_prog_status_reg(struct snd_pcm_substream *substream,
			struct snd_intelhad *intelhaddata)
{
266 267 268
	union aud_cfg cfg_val = {.regval = 0};
	union aud_ch_status_0 ch_stat0 = {.regval = 0};
	union aud_ch_status_1 ch_stat1 = {.regval = 0};
269 270
	int format;

271
	ch_stat0.regx.lpcm_id = (intelhaddata->aes_bits &
T
Takashi Iwai 已提交
272
					  IEC958_AES0_NONAUDIO) >> 1;
273
	ch_stat0.regx.clk_acc = (intelhaddata->aes_bits &
T
Takashi Iwai 已提交
274
					  IEC958_AES3_CON_CLOCK) >> 4;
275
	cfg_val.regx.val_bit = ch_stat0.regx.lpcm_id;
276 277 278

	switch (substream->runtime->rate) {
	case AUD_SAMPLE_RATE_32:
279
		ch_stat0.regx.samp_freq = CH_STATUS_MAP_32KHZ;
280 281 282
		break;

	case AUD_SAMPLE_RATE_44_1:
283
		ch_stat0.regx.samp_freq = CH_STATUS_MAP_44KHZ;
284 285
		break;
	case AUD_SAMPLE_RATE_48:
286
		ch_stat0.regx.samp_freq = CH_STATUS_MAP_48KHZ;
287 288
		break;
	case AUD_SAMPLE_RATE_88_2:
289
		ch_stat0.regx.samp_freq = CH_STATUS_MAP_88KHZ;
290 291
		break;
	case AUD_SAMPLE_RATE_96:
292
		ch_stat0.regx.samp_freq = CH_STATUS_MAP_96KHZ;
293 294
		break;
	case AUD_SAMPLE_RATE_176_4:
295
		ch_stat0.regx.samp_freq = CH_STATUS_MAP_176KHZ;
296 297
		break;
	case AUD_SAMPLE_RATE_192:
298
		ch_stat0.regx.samp_freq = CH_STATUS_MAP_192KHZ;
299 300 301 302 303 304
		break;

	default:
		/* control should never come here */
		return -EINVAL;
	}
T
Takashi Iwai 已提交
305

306
	had_write_register(intelhaddata,
307
			   AUD_CH_STATUS_0, ch_stat0.regval);
308 309 310 311

	format = substream->runtime->format;

	if (format == SNDRV_PCM_FORMAT_S16_LE) {
312 313
		ch_stat1.regx.max_wrd_len = MAX_SMPL_WIDTH_20;
		ch_stat1.regx.wrd_len = SMPL_WIDTH_16BITS;
314
	} else if (format == SNDRV_PCM_FORMAT_S24_LE) {
315 316
		ch_stat1.regx.max_wrd_len = MAX_SMPL_WIDTH_24;
		ch_stat1.regx.wrd_len = SMPL_WIDTH_24BITS;
317
	} else {
318 319
		ch_stat1.regx.max_wrd_len = 0;
		ch_stat1.regx.wrd_len = 0;
320
	}
T
Takashi Iwai 已提交
321

322
	had_write_register(intelhaddata,
323
			   AUD_CH_STATUS_1, ch_stat1.regval);
324 325 326
	return 0;
}

327
/*
328 329 330 331
 * function to initialize audio
 * registers and buffer confgiuration registers
 * This function is called in the prepare callback
 */
332 333
static int had_init_audio_ctrl(struct snd_pcm_substream *substream,
			       struct snd_intelhad *intelhaddata)
334
{
335 336
	union aud_cfg cfg_val = {.regval = 0};
	union aud_buf_config buf_cfg = {.regval = 0};
337 338 339 340
	u8 channels;

	had_prog_status_reg(substream, intelhaddata);

341 342 343 344
	buf_cfg.regx.audio_fifo_watermark = FIFO_THRESHOLD;
	buf_cfg.regx.dma_fifo_watermark = DMA_FIFO_THRESHOLD;
	buf_cfg.regx.aud_delay = 0;
	had_write_register(intelhaddata, AUD_BUF_CONFIG, buf_cfg.regval);
345 346

	channels = substream->runtime->channels;
347
	cfg_val.regx.num_ch = channels - 2;
348
	if (channels <= 2)
349
		cfg_val.regx.layout = LAYOUT0;
350
	else
351
		cfg_val.regx.layout = LAYOUT1;
352

353
	cfg_val.regx.val_bit = 1;
354 355 356 357 358 359 360

	/* fix up the DP bits */
	if (intelhaddata->dp_output) {
		cfg_val.regx.dp_modei = 1;
		cfg_val.regx.set = 1;
	}

361
	had_write_register(intelhaddata, AUD_CONFIG, cfg_val.regval);
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
	return 0;
}

/*
 * Compute derived values in channel_allocations[].
 */
static void init_channel_allocations(void)
{
	int i, j;
	struct cea_channel_speaker_allocation *p;

	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
		p = channel_allocations + i;
		p->channels = 0;
		p->spk_mask = 0;
		for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
			if (p->speakers[j]) {
				p->channels++;
				p->spk_mask |= p->speakers[j];
			}
	}
}

/*
 * The transformation takes two steps:
 *
 *      eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
 *            spk_mask => (channel_allocations[])         => ai->CA
 *
 * TODO: it could select the wrong CA from multiple candidates.
 */
393 394
static int had_channel_allocation(struct snd_intelhad *intelhaddata,
				  int channels)
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
{
	int i;
	int ca = 0;
	int spk_mask = 0;

	/*
	 * CA defaults to 0 for basic stereo audio
	 */
	if (channels <= 2)
		return 0;

	/*
	 * expand ELD's speaker allocation mask
	 *
	 * ELD tells the speaker mask in a compact(paired) form,
	 * expand ELD's notions to match the ones used by Audio InfoFrame.
	 */

	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
414
		if (intelhaddata->eld[DRM_ELD_SPEAKER] & (1 << i))
415 416 417 418 419 420 421 422 423 424 425 426 427
			spk_mask |= eld_speaker_allocation_bits[i];
	}

	/* search for the first working match in the CA table */
	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
		if (channels == channel_allocations[i].channels &&
		(spk_mask & channel_allocations[i].spk_mask) ==
				channel_allocations[i].spk_mask) {
			ca = channel_allocations[i].ca_index;
			break;
		}
	}

428
	dev_dbg(intelhaddata->dev, "select CA 0x%x for %d\n", ca, channels);
429 430 431 432 433 434 435

	return ca;
}

/* from speaker bit mask to ALSA API channel position */
static int spk_to_chmap(int spk)
{
T
Takashi Iwai 已提交
436
	const struct channel_map_table *t = map_tables;
437 438 439 440 441 442 443 444

	for (; t->map; t++) {
		if (t->spk_mask == spk)
			return t->map;
	}
	return 0;
}

445
static void had_build_channel_allocation_map(struct snd_intelhad *intelhaddata)
446
{
T
Takashi Iwai 已提交
447
	int i, c;
448 449 450 451 452 453
	int spk_mask = 0;
	struct snd_pcm_chmap_elem *chmap;
	u8 eld_high, eld_high_mask = 0xF0;
	u8 high_msb;

	chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
T
Takashi Iwai 已提交
454
	if (!chmap) {
455 456 457 458
		intelhaddata->chmap->chmap = NULL;
		return;
	}

459 460
	dev_dbg(intelhaddata->dev, "eld speaker = %x\n",
		intelhaddata->eld[DRM_ELD_SPEAKER]);
461 462 463 464 465 466 467 468 469 470

	/* WA: Fix the max channel supported to 8 */

	/*
	 * Sink may support more than 8 channels, if eld_high has more than
	 * one bit set. SOC supports max 8 channels.
	 * Refer eld_speaker_allocation_bits, for sink speaker allocation
	 */

	/* if 0x2F < eld < 0x4F fall back to 0x2f, else fall back to 0x4F */
471
	eld_high = intelhaddata->eld[DRM_ELD_SPEAKER] & eld_high_mask;
472 473 474 475 476 477
	if ((eld_high & (eld_high-1)) && (eld_high > 0x1F)) {
		/* eld_high & (eld_high-1): if more than 1 bit set */
		/* 0x1F: 7 channels */
		for (i = 1; i < 4; i++) {
			high_msb = eld_high & (0x80 >> i);
			if (high_msb) {
478
				intelhaddata->eld[DRM_ELD_SPEAKER] &=
479 480 481 482 483 484 485
					high_msb | 0xF;
				break;
			}
		}
	}

	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
486
		if (intelhaddata->eld[DRM_ELD_SPEAKER] & (1 << i))
487 488 489 490 491 492 493 494
			spk_mask |= eld_speaker_allocation_bits[i];
	}

	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
		if (spk_mask == channel_allocations[i].spk_mask) {
			for (c = 0; c < channel_allocations[i].channels; c++) {
				chmap->map[c] = spk_to_chmap(
					channel_allocations[i].speakers[
T
Takashi Iwai 已提交
495
						(MAX_SPEAKERS - 1) - c]);
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
			}
			chmap->channels = channel_allocations[i].channels;
			intelhaddata->chmap->chmap = chmap;
			break;
		}
	}
	if (i >= ARRAY_SIZE(channel_allocations)) {
		intelhaddata->chmap->chmap = NULL;
		kfree(chmap);
	}
}

/*
 * ALSA API channel-map control callbacks
 */
static int had_chmap_ctl_info(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_info *uinfo)
{
	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
	struct snd_intelhad *intelhaddata = info->private_data;

517
	if (!intelhaddata->connected)
518 519 520 521 522 523 524 525 526 527 528 529 530
		return -ENODEV;
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = HAD_MAX_CHANNEL;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = SNDRV_CHMAP_LAST;
	return 0;
}

static int had_chmap_ctl_get(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
	struct snd_intelhad *intelhaddata = info->private_data;
T
Takashi Iwai 已提交
531
	int i;
532 533
	const struct snd_pcm_chmap_elem *chmap;

534
	if (!intelhaddata->connected)
535
		return -ENODEV;
536 537 538 539

	mutex_lock(&intelhaddata->mutex);
	if (!intelhaddata->chmap->chmap) {
		mutex_unlock(&intelhaddata->mutex);
540
		return -ENODATA;
541 542
	}

543
	chmap = intelhaddata->chmap->chmap;
544
	for (i = 0; i < chmap->channels; i++)
545
		ucontrol->value.integer.value[i] = chmap->map[i];
546
	mutex_unlock(&intelhaddata->mutex);
547 548 549 550 551 552 553

	return 0;
}

static int had_register_chmap_ctls(struct snd_intelhad *intelhaddata,
						struct snd_pcm *pcm)
{
T
Takashi Iwai 已提交
554
	int err;
555 556 557 558 559 560 561 562

	err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
			NULL, 0, (unsigned long)intelhaddata,
			&intelhaddata->chmap);
	if (err < 0)
		return err;

	intelhaddata->chmap->private_data = intelhaddata;
563 564
	intelhaddata->chmap->kctl->info = had_chmap_ctl_info;
	intelhaddata->chmap->kctl->get = had_chmap_ctl_get;
565 566 567 568
	intelhaddata->chmap->chmap = NULL;
	return 0;
}

569
/*
T
Takashi Iwai 已提交
570
 * Initialize Data Island Packets registers
571 572
 * This function is called in the prepare callback
 */
573 574
static void had_prog_dip(struct snd_pcm_substream *substream,
			 struct snd_intelhad *intelhaddata)
575 576
{
	int i;
577 578 579
	union aud_ctrl_st ctrl_state = {.regval = 0};
	union aud_info_frame2 frame2 = {.regval = 0};
	union aud_info_frame3 frame3 = {.regval = 0};
580
	u8 checksum = 0;
581
	u32 info_frame;
582
	int channels;
583
	int ca;
584 585 586

	channels = substream->runtime->channels;

587
	had_write_register(intelhaddata, AUD_CNTL_ST, ctrl_state.regval);
588

589
	ca = had_channel_allocation(intelhaddata, channels);
590 591
	if (intelhaddata->dp_output) {
		info_frame = DP_INFO_FRAME_WORD1;
592
		frame2.regval = (substream->runtime->channels - 1) | (ca << 24);
593 594
	} else {
		info_frame = HDMI_INFO_FRAME_WORD1;
595
		frame2.regx.chnl_cnt = substream->runtime->channels - 1;
596
		frame3.regx.chnl_alloc = ca;
597

T
Takashi Iwai 已提交
598
		/* Calculte the byte wide checksum for all valid DIP words */
599
		for (i = 0; i < BYTES_PER_WORD; i++)
600
			checksum += (info_frame >> (i * 8)) & 0xff;
601
		for (i = 0; i < BYTES_PER_WORD; i++)
602
			checksum += (frame2.regval >> (i * 8)) & 0xff;
603
		for (i = 0; i < BYTES_PER_WORD; i++)
604
			checksum += (frame3.regval >> (i * 8)) & 0xff;
605

606
		frame2.regx.chksum = -(checksum);
607
	}
608

T
Takashi Iwai 已提交
609
	had_write_register(intelhaddata, AUD_HDMIW_INFOFR, info_frame);
610 611
	had_write_register(intelhaddata, AUD_HDMIW_INFOFR, frame2.regval);
	had_write_register(intelhaddata, AUD_HDMIW_INFOFR, frame3.regval);
612 613 614

	/* program remaining DIP words with zero */
	for (i = 0; i < HAD_MAX_DIP_WORDS-VALID_DIP_WORDS; i++)
T
Takashi Iwai 已提交
615
		had_write_register(intelhaddata, AUD_HDMIW_INFOFR, 0x0);
616

617 618 619
	ctrl_state.regx.dip_freq = 1;
	ctrl_state.regx.dip_en_sta = 1;
	had_write_register(intelhaddata, AUD_CNTL_ST, ctrl_state.regval);
620 621
}

622 623 624 625
static int had_calculate_maud_value(u32 aud_samp_freq, u32 link_rate)
{
	u32 maud_val;

T
Takashi Iwai 已提交
626
	/* Select maud according to DP 1.2 spec */
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700
	if (link_rate == DP_2_7_GHZ) {
		switch (aud_samp_freq) {
		case AUD_SAMPLE_RATE_32:
			maud_val = AUD_SAMPLE_RATE_32_DP_2_7_MAUD_VAL;
			break;

		case AUD_SAMPLE_RATE_44_1:
			maud_val = AUD_SAMPLE_RATE_44_1_DP_2_7_MAUD_VAL;
			break;

		case AUD_SAMPLE_RATE_48:
			maud_val = AUD_SAMPLE_RATE_48_DP_2_7_MAUD_VAL;
			break;

		case AUD_SAMPLE_RATE_88_2:
			maud_val = AUD_SAMPLE_RATE_88_2_DP_2_7_MAUD_VAL;
			break;

		case AUD_SAMPLE_RATE_96:
			maud_val = AUD_SAMPLE_RATE_96_DP_2_7_MAUD_VAL;
			break;

		case AUD_SAMPLE_RATE_176_4:
			maud_val = AUD_SAMPLE_RATE_176_4_DP_2_7_MAUD_VAL;
			break;

		case HAD_MAX_RATE:
			maud_val = HAD_MAX_RATE_DP_2_7_MAUD_VAL;
			break;

		default:
			maud_val = -EINVAL;
			break;
		}
	} else if (link_rate == DP_1_62_GHZ) {
		switch (aud_samp_freq) {
		case AUD_SAMPLE_RATE_32:
			maud_val = AUD_SAMPLE_RATE_32_DP_1_62_MAUD_VAL;
			break;

		case AUD_SAMPLE_RATE_44_1:
			maud_val = AUD_SAMPLE_RATE_44_1_DP_1_62_MAUD_VAL;
			break;

		case AUD_SAMPLE_RATE_48:
			maud_val = AUD_SAMPLE_RATE_48_DP_1_62_MAUD_VAL;
			break;

		case AUD_SAMPLE_RATE_88_2:
			maud_val = AUD_SAMPLE_RATE_88_2_DP_1_62_MAUD_VAL;
			break;

		case AUD_SAMPLE_RATE_96:
			maud_val = AUD_SAMPLE_RATE_96_DP_1_62_MAUD_VAL;
			break;

		case AUD_SAMPLE_RATE_176_4:
			maud_val = AUD_SAMPLE_RATE_176_4_DP_1_62_MAUD_VAL;
			break;

		case HAD_MAX_RATE:
			maud_val = HAD_MAX_RATE_DP_1_62_MAUD_VAL;
			break;

		default:
			maud_val = -EINVAL;
			break;
		}
	} else
		maud_val = -EINVAL;

	return maud_val;
}

701
/*
T
Takashi Iwai 已提交
702
 * Program HDMI audio CTS value
703 704 705
 *
 * @aud_samp_freq: sampling frequency of audio data
 * @tmds: sampling frequency of the display data
706
 * @link_rate: DP link rate
707
 * @n_param: N value, depends on aud_samp_freq
708
 * @intelhaddata: substream private data
709 710 711
 *
 * Program CTS register based on the audio and display sampling frequency
 */
712 713
static void had_prog_cts(u32 aud_samp_freq, u32 tmds, u32 link_rate,
			 u32 n_param, struct snd_intelhad *intelhaddata)
714 715 716 717
{
	u32 cts_val;
	u64 dividend, divisor;

718 719 720 721 722 723 724 725 726
	if (intelhaddata->dp_output) {
		/* Substitute cts_val with Maud according to DP 1.2 spec*/
		cts_val = had_calculate_maud_value(aud_samp_freq, link_rate);
	} else {
		/* Calculate CTS according to HDMI 1.3a spec*/
		dividend = (u64)tmds * n_param*1000;
		divisor = 128 * aud_samp_freq;
		cts_val = div64_u64(dividend, divisor);
	}
727
	dev_dbg(intelhaddata->dev, "TMDS value=%d, N value=%d, CTS Value=%d\n",
728
		 tmds, n_param, cts_val);
729
	had_write_register(intelhaddata, AUD_HDMI_CTS, (BIT(24) | cts_val));
730 731 732 733
}

static int had_calculate_n_value(u32 aud_samp_freq)
{
T
Takashi Iwai 已提交
734
	int n_val;
735 736 737 738 739

	/* Select N according to HDMI 1.3a spec*/
	switch (aud_samp_freq) {
	case AUD_SAMPLE_RATE_32:
		n_val = 4096;
T
Takashi Iwai 已提交
740
		break;
741 742 743

	case AUD_SAMPLE_RATE_44_1:
		n_val = 6272;
T
Takashi Iwai 已提交
744
		break;
745 746 747

	case AUD_SAMPLE_RATE_48:
		n_val = 6144;
T
Takashi Iwai 已提交
748
		break;
749 750 751

	case AUD_SAMPLE_RATE_88_2:
		n_val = 12544;
T
Takashi Iwai 已提交
752
		break;
753 754 755

	case AUD_SAMPLE_RATE_96:
		n_val = 12288;
T
Takashi Iwai 已提交
756
		break;
757 758 759

	case AUD_SAMPLE_RATE_176_4:
		n_val = 25088;
T
Takashi Iwai 已提交
760
		break;
761 762 763

	case HAD_MAX_RATE:
		n_val = 24576;
T
Takashi Iwai 已提交
764
		break;
765 766 767

	default:
		n_val = -EINVAL;
T
Takashi Iwai 已提交
768
		break;
769 770 771 772
	}
	return n_val;
}

773
/*
T
Takashi Iwai 已提交
774
 * Program HDMI audio N value
775 776 777
 *
 * @aud_samp_freq: sampling frequency of audio data
 * @n_param: N value, depends on aud_samp_freq
778
 * @intelhaddata: substream private data
779 780 781 782
 *
 * This function is called in the prepare callback.
 * It programs based on the audio and display sampling frequency
 */
783 784
static int had_prog_n(u32 aud_samp_freq, u32 *n_param,
		      struct snd_intelhad *intelhaddata)
785
{
T
Takashi Iwai 已提交
786
	int n_val;
787

788 789 790 791 792 793 794 795 796 797 798 799
	if (intelhaddata->dp_output) {
		/*
		 * According to DP specs, Maud and Naud values hold
		 * a relationship, which is stated as:
		 * Maud/Naud = 512 * fs / f_LS_Clk
		 * where, fs is the sampling frequency of the audio stream
		 * and Naud is 32768 for Async clock.
		 */

		n_val = DP_NAUD_VAL;
	} else
		n_val =	had_calculate_n_value(aud_samp_freq);
800 801 802 803

	if (n_val < 0)
		return n_val;

804
	had_write_register(intelhaddata, AUD_N_ENABLE, (BIT(24) | n_val));
805 806 807 808
	*n_param = n_val;
	return 0;
}

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 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977
/*
 * PCM ring buffer handling
 *
 * The hardware provides a ring buffer with the fixed 4 buffer descriptors
 * (BDs).  The driver maps these 4 BDs onto the PCM ring buffer.  The mapping
 * moves at each period elapsed.  The below illustrates how it works:
 *
 * At time=0
 *  PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1|
 *  BD  | 0 | 1 | 2 | 3 |
 *
 * At time=1 (period elapsed)
 *  PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1|
 *  BD      | 1 | 2 | 3 | 0 |
 *
 * At time=2 (second period elapsed)
 *  PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1|
 *  BD          | 2 | 3 | 0 | 1 |
 *
 * The bd_head field points to the index of the BD to be read.  It's also the
 * position to be filled at next.  The pcm_head and the pcm_filled fields
 * point to the indices of the current position and of the next position to
 * be filled, respectively.  For PCM buffer there are both _head and _filled
 * because they may be difference when nperiods > 4.  For example, in the
 * example above at t=1, bd_head=1 and pcm_head=1 while pcm_filled=5:
 *
 * pcm_head (=1) --v               v-- pcm_filled (=5)
 *       PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1|
 *       BD      | 1 | 2 | 3 | 0 |
 *  bd_head (=1) --^               ^-- next to fill (= bd_head)
 *
 * For nperiods < 4, the remaining BDs out of 4 are marked as invalid, so that
 * the hardware skips those BDs in the loop.
 */

#define AUD_BUF_ADDR(x)		(AUD_BUF_A_ADDR + (x) * HAD_REG_WIDTH)
#define AUD_BUF_LEN(x)		(AUD_BUF_A_LENGTH + (x) * HAD_REG_WIDTH)

/* Set up a buffer descriptor at the "filled" position */
static void had_prog_bd(struct snd_pcm_substream *substream,
			struct snd_intelhad *intelhaddata)
{
	int idx = intelhaddata->bd_head;
	int ofs = intelhaddata->pcmbuf_filled * intelhaddata->period_bytes;
	u32 addr = substream->runtime->dma_addr + ofs;

	addr |= AUD_BUF_VALID | AUD_BUF_INTR_EN;
	had_write_register(intelhaddata, AUD_BUF_ADDR(idx), addr);
	had_write_register(intelhaddata, AUD_BUF_LEN(idx),
			   intelhaddata->period_bytes);

	/* advance the indices to the next */
	intelhaddata->bd_head++;
	intelhaddata->bd_head %= intelhaddata->num_bds;
	intelhaddata->pcmbuf_filled++;
	intelhaddata->pcmbuf_filled %= substream->runtime->periods;
}

/* invalidate a buffer descriptor with the given index */
static void had_invalidate_bd(struct snd_intelhad *intelhaddata,
			      int idx)
{
	had_write_register(intelhaddata, AUD_BUF_ADDR(idx), 0);
	had_write_register(intelhaddata, AUD_BUF_LEN(idx), 0);
}

/* Initial programming of ring buffer */
static void had_init_ringbuf(struct snd_pcm_substream *substream,
			     struct snd_intelhad *intelhaddata)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	int i, num_periods;

	num_periods = runtime->periods;
	intelhaddata->num_bds = min(num_periods, HAD_NUM_OF_RING_BUFS);
	intelhaddata->period_bytes =
		frames_to_bytes(runtime, runtime->period_size);
	WARN_ON(intelhaddata->period_bytes & 0x3f);

	intelhaddata->bd_head = 0;
	intelhaddata->pcmbuf_head = 0;
	intelhaddata->pcmbuf_filled = 0;

	for (i = 0; i < HAD_NUM_OF_RING_BUFS; i++) {
		if (i < num_periods)
			had_prog_bd(substream, intelhaddata);
		else /* invalidate the rest */
			had_invalidate_bd(intelhaddata, i);
	}

	intelhaddata->bd_head = 0; /* reset at head again before starting */
}

/* process a bd, advance to the next */
static void had_advance_ringbuf(struct snd_pcm_substream *substream,
				struct snd_intelhad *intelhaddata)
{
	int num_periods = substream->runtime->periods;

	/* reprogram the next buffer */
	had_prog_bd(substream, intelhaddata);

	/* proceed to next */
	intelhaddata->pcmbuf_head++;
	intelhaddata->pcmbuf_head %= num_periods;
}

/* process the current BD(s);
 * returns the current PCM buffer byte position, or -EPIPE for underrun.
 */
static int had_process_ringbuf(struct snd_pcm_substream *substream,
			       struct snd_intelhad *intelhaddata)
{
	int len, processed;
	unsigned long flags;

	processed = 0;
	spin_lock_irqsave(&intelhaddata->had_spinlock, flags);
	for (;;) {
		/* get the remaining bytes on the buffer */
		had_read_register(intelhaddata,
				  AUD_BUF_LEN(intelhaddata->bd_head),
				  &len);
		if (len < 0 || len > intelhaddata->period_bytes) {
			dev_dbg(intelhaddata->dev, "Invalid buf length %d\n",
				len);
			len = -EPIPE;
			goto out;
		}

		if (len > 0) /* OK, this is the current buffer */
			break;

		/* len=0 => already empty, check the next buffer */
		if (++processed >= intelhaddata->num_bds) {
			len = -EPIPE; /* all empty? - report underrun */
			goto out;
		}
		had_advance_ringbuf(substream, intelhaddata);
	}

	len = intelhaddata->period_bytes - len;
	len += intelhaddata->period_bytes * intelhaddata->pcmbuf_head;
 out:
	spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags);
	return len;
}

/* called from irq handler */
static void had_process_buffer_done(struct snd_intelhad *intelhaddata)
{
	struct snd_pcm_substream *substream;

	if (!intelhaddata->connected)
		return; /* disconnected? - bail out */

	substream = had_substream_get(intelhaddata);
	if (!substream)
		return; /* no stream? - bail out */

	/* process or stop the stream */
	if (had_process_ringbuf(substream, intelhaddata) < 0)
		snd_pcm_stop_xrun(substream);
	else
		snd_pcm_period_elapsed(substream);

	had_substream_put(intelhaddata);
}

978 979
#define MAX_CNT			0xFF

980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
/*
 * The interrupt status 'sticky' bits might not be cleared by
 * setting '1' to that bit once...
 */
static void wait_clear_underrun_bit(struct snd_intelhad *intelhaddata)
{
	int i;
	u32 val;

	for (i = 0; i < MAX_CNT; i++) {
		/* clear bit30, 31 AUD_HDMI_STATUS */
		had_read_register(intelhaddata, AUD_HDMI_STATUS, &val);
		if (!(val & AUD_CONFIG_MASK_UNDERRUN))
			return;
		had_write_register(intelhaddata, AUD_HDMI_STATUS, val);
	}
	dev_err(intelhaddata->dev, "Unable to clear UNDERRUN bits\n");
}

/* called from irq handler */
static void had_process_buffer_underrun(struct snd_intelhad *intelhaddata)
1001
{
1002
	struct snd_pcm_substream *substream;
1003 1004

	/* Handle Underrun interrupt within Audio Unit */
1005
	had_write_register(intelhaddata, AUD_CONFIG, 0);
1006
	/* Reset buffer pointers */
1007
	had_reset_audio(intelhaddata);
1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019

	wait_clear_underrun_bit(intelhaddata);

	if (!intelhaddata->connected)
		return; /* disconnected? - bail out */

	/* Report UNDERRUN error to above layers */
	substream = had_substream_get(intelhaddata);
	if (substream) {
		snd_pcm_stop_xrun(substream);
		had_substream_put(intelhaddata);
	}
1020 1021
}

T
Takashi Iwai 已提交
1022
/*
T
Takashi Iwai 已提交
1023
 * ALSA PCM open callback
1024
 */
1025
static int had_pcm_open(struct snd_pcm_substream *substream)
1026 1027 1028 1029 1030 1031 1032 1033
{
	struct snd_intelhad *intelhaddata;
	struct snd_pcm_runtime *runtime;
	int retval;

	intelhaddata = snd_pcm_substream_chip(substream);
	runtime = substream->runtime;

T
Takashi Iwai 已提交
1034
	pm_runtime_get_sync(intelhaddata->dev);
1035

1036
	if (!intelhaddata->connected) {
1037 1038
		dev_dbg(intelhaddata->dev, "%s: HDMI cable plugged-out\n",
			__func__);
1039
		retval = -ENODEV;
1040
		goto error;
1041 1042 1043
	}

	/* set the runtime hw parameter with local snd_pcm_hardware struct */
1044
	runtime->hw = had_pcm_hardware;
1045 1046 1047 1048

	retval = snd_pcm_hw_constraint_integer(runtime,
			 SNDRV_PCM_HW_PARAM_PERIODS);
	if (retval < 0)
1049
		goto error;
1050 1051 1052 1053 1054 1055

	/* Make sure, that the period size is always aligned
	 * 64byte boundary
	 */
	retval = snd_pcm_hw_constraint_step(substream->runtime, 0,
			SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64);
1056
	if (retval < 0)
1057
		goto error;
1058

1059
	/* expose PCM substream */
1060 1061 1062 1063 1064
	spin_lock_irq(&intelhaddata->had_spinlock);
	intelhaddata->stream_info.substream = substream;
	intelhaddata->stream_info.substream_refcount++;
	spin_unlock_irq(&intelhaddata->had_spinlock);

1065
	return retval;
1066
 error:
1067 1068 1069 1070
	pm_runtime_put(intelhaddata->dev);
	return retval;
}

T
Takashi Iwai 已提交
1071
/*
T
Takashi Iwai 已提交
1072
 * ALSA PCM close callback
1073
 */
1074
static int had_pcm_close(struct snd_pcm_substream *substream)
1075 1076 1077 1078 1079
{
	struct snd_intelhad *intelhaddata;

	intelhaddata = snd_pcm_substream_chip(substream);

1080
	/* unreference and sync with the pending PCM accesses */
1081 1082 1083 1084 1085 1086 1087 1088 1089
	spin_lock_irq(&intelhaddata->had_spinlock);
	intelhaddata->stream_info.substream = NULL;
	intelhaddata->stream_info.substream_refcount--;
	while (intelhaddata->stream_info.substream_refcount > 0) {
		spin_unlock_irq(&intelhaddata->had_spinlock);
		cpu_relax();
		spin_lock_irq(&intelhaddata->had_spinlock);
	}
	spin_unlock_irq(&intelhaddata->had_spinlock);
1090 1091 1092 1093 1094

	pm_runtime_put(intelhaddata->dev);
	return 0;
}

T
Takashi Iwai 已提交
1095
/*
T
Takashi Iwai 已提交
1096
 * ALSA PCM hw_params callback
1097
 */
1098 1099
static int had_pcm_hw_params(struct snd_pcm_substream *substream,
			     struct snd_pcm_hw_params *hw_params)
1100
{
1101
	struct snd_intelhad *intelhaddata;
1102 1103 1104
	unsigned long addr;
	int pages, buf_size, retval;

1105
	intelhaddata = snd_pcm_substream_chip(substream);
1106 1107 1108 1109
	buf_size = params_buffer_bytes(hw_params);
	retval = snd_pcm_lib_malloc_pages(substream, buf_size);
	if (retval < 0)
		return retval;
1110 1111
	dev_dbg(intelhaddata->dev, "%s:allocated memory = %d\n",
		__func__, buf_size);
1112 1113 1114 1115 1116
	/* mark the pages as uncached region */
	addr = (unsigned long) substream->runtime->dma_area;
	pages = (substream->runtime->dma_bytes + PAGE_SIZE - 1) / PAGE_SIZE;
	retval = set_memory_uc(addr, pages);
	if (retval) {
1117 1118
		dev_err(intelhaddata->dev, "set_memory_uc failed.Error:%d\n",
			retval);
1119 1120 1121 1122 1123 1124 1125
		return retval;
	}
	memset(substream->runtime->dma_area, 0, buf_size);

	return retval;
}

T
Takashi Iwai 已提交
1126
/*
T
Takashi Iwai 已提交
1127
 * ALSA PCM hw_free callback
1128
 */
1129
static int had_pcm_hw_free(struct snd_pcm_substream *substream)
1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144
{
	unsigned long addr;
	u32 pages;

	/* mark back the pages as cached/writeback region before the free */
	if (substream->runtime->dma_area != NULL) {
		addr = (unsigned long) substream->runtime->dma_area;
		pages = (substream->runtime->dma_bytes + PAGE_SIZE - 1) /
								PAGE_SIZE;
		set_memory_wb(addr, pages);
		return snd_pcm_lib_free_pages(substream);
	}
	return 0;
}

T
Takashi Iwai 已提交
1145
/*
T
Takashi Iwai 已提交
1146
 * ALSA PCM trigger callback
1147
 */
1148
static int had_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
1149
{
1150
	int retval = 0;
1151 1152 1153 1154 1155 1156
	struct snd_intelhad *intelhaddata;

	intelhaddata = snd_pcm_substream_chip(substream);

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
T
Takashi Iwai 已提交
1157 1158
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
	case SNDRV_PCM_TRIGGER_RESUME:
1159
		/* Disable local INTRs till register prgmng is done */
1160
		if (!intelhaddata->connected) {
1161 1162
			dev_dbg(intelhaddata->dev,
				"_START: HDMI cable plugged-out\n");
1163 1164 1165 1166
			retval = -ENODEV;
			break;
		}

1167
		intelhaddata->stream_info.running = true;
1168 1169

		/* Enable Audio */
1170
		had_ack_irqs(intelhaddata); /* FIXME: do we need this? */
1171
		had_enable_audio(substream, intelhaddata, true);
1172 1173 1174
		break;

	case SNDRV_PCM_TRIGGER_STOP:
T
Takashi Iwai 已提交
1175 1176
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
	case SNDRV_PCM_TRIGGER_SUSPEND:
1177
		spin_lock(&intelhaddata->had_spinlock);
1178

1179
		/* Stop reporting BUFFER_DONE/UNDERRUN to above layers */
1180

1181
		intelhaddata->stream_info.running = false;
1182
		spin_unlock(&intelhaddata->had_spinlock);
1183
		/* Disable Audio */
1184
		had_enable_audio(substream, intelhaddata, false);
1185
		/* Reset buffer pointers */
1186
		had_reset_audio(intelhaddata);
1187 1188 1189 1190 1191 1192 1193 1194
		break;

	default:
		retval = -EINVAL;
	}
	return retval;
}

T
Takashi Iwai 已提交
1195
/*
T
Takashi Iwai 已提交
1196
 * ALSA PCM prepare callback
1197
 */
1198
static int had_pcm_prepare(struct snd_pcm_substream *substream)
1199 1200 1201
{
	int retval;
	u32 disp_samp_freq, n_param;
1202
	u32 link_rate = 0;
1203 1204 1205 1206 1207 1208
	struct snd_intelhad *intelhaddata;
	struct snd_pcm_runtime *runtime;

	intelhaddata = snd_pcm_substream_chip(substream);
	runtime = substream->runtime;

1209
	if (!intelhaddata->connected) {
1210 1211
		dev_dbg(intelhaddata->dev, "%s: HDMI cable plugged-out\n",
			__func__);
1212 1213 1214 1215
		retval = -ENODEV;
		goto prep_end;
	}

1216
	dev_dbg(intelhaddata->dev, "period_size=%d\n",
1217
		(int)frames_to_bytes(runtime, runtime->period_size));
1218 1219 1220 1221 1222
	dev_dbg(intelhaddata->dev, "periods=%d\n", runtime->periods);
	dev_dbg(intelhaddata->dev, "buffer_size=%d\n",
		(int)snd_pcm_lib_buffer_bytes(substream));
	dev_dbg(intelhaddata->dev, "rate=%d\n", runtime->rate);
	dev_dbg(intelhaddata->dev, "channels=%d\n", runtime->channels);
1223 1224

	/* Get N value in KHz */
1225
	disp_samp_freq = intelhaddata->tmds_clock_speed;
1226

1227
	retval = had_prog_n(substream->runtime->rate, &n_param, intelhaddata);
1228
	if (retval) {
1229 1230
		dev_err(intelhaddata->dev,
			"programming N value failed %#x\n", retval);
1231 1232
		goto prep_end;
	}
1233 1234

	if (intelhaddata->dp_output)
1235
		link_rate = intelhaddata->link_rate;
1236

1237 1238
	had_prog_cts(substream->runtime->rate, disp_samp_freq, link_rate,
		     n_param, intelhaddata);
1239

1240
	had_prog_dip(substream, intelhaddata);
1241

1242
	retval = had_init_audio_ctrl(substream, intelhaddata);
1243 1244

	/* Prog buffer address */
1245
	had_init_ringbuf(substream, intelhaddata);
1246 1247 1248 1249 1250 1251

	/*
	 * Program channel mapping in following order:
	 * FL, FR, C, LFE, RL, RR
	 */

1252
	had_write_register(intelhaddata, AUD_BUF_CH_SWAP, SWAP_LFE_CENTER);
1253 1254 1255 1256 1257

prep_end:
	return retval;
}

T
Takashi Iwai 已提交
1258
/*
T
Takashi Iwai 已提交
1259
 * ALSA PCM pointer callback
1260
 */
1261
static snd_pcm_uframes_t had_pcm_pointer(struct snd_pcm_substream *substream)
1262 1263
{
	struct snd_intelhad *intelhaddata;
1264
	int len;
1265 1266 1267

	intelhaddata = snd_pcm_substream_chip(substream);

1268
	if (!intelhaddata->connected)
T
Takashi Iwai 已提交
1269 1270
		return SNDRV_PCM_POS_XRUN;

1271 1272 1273 1274
	len = had_process_ringbuf(substream, intelhaddata);
	if (len < 0)
		return SNDRV_PCM_POS_XRUN;
	return bytes_to_frames(substream->runtime, len);
1275 1276
}

T
Takashi Iwai 已提交
1277
/*
T
Takashi Iwai 已提交
1278
 * ALSA PCM mmap callback
1279
 */
1280 1281
static int had_pcm_mmap(struct snd_pcm_substream *substream,
			struct vm_area_struct *vma)
1282 1283 1284 1285 1286 1287 1288
{
	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
	return remap_pfn_range(vma, vma->vm_start,
			substream->dma_buffer.addr >> PAGE_SHIFT,
			vma->vm_end - vma->vm_start, vma->vm_page_prot);
}

1289 1290 1291
/*
 * ALSA PCM ops
 */
1292 1293 1294
static const struct snd_pcm_ops had_pcm_ops = {
	.open =		had_pcm_open,
	.close =	had_pcm_close,
1295
	.ioctl =	snd_pcm_lib_ioctl,
1296 1297 1298 1299 1300 1301
	.hw_params =	had_pcm_hw_params,
	.hw_free =	had_pcm_hw_free,
	.prepare =	had_pcm_prepare,
	.trigger =	had_pcm_trigger,
	.pointer =	had_pcm_pointer,
	.mmap =		had_pcm_mmap,
1302 1303
};

1304
/* process mode change of the running stream; called in mutex */
1305
static int had_process_mode_change(struct snd_intelhad *intelhaddata)
1306
{
1307
	struct snd_pcm_substream *substream;
1308 1309
	int retval = 0;
	u32 disp_samp_freq, n_param;
1310
	u32 link_rate = 0;
1311

1312 1313
	substream = had_substream_get(intelhaddata);
	if (!substream)
1314
		return 0;
1315 1316

	/* Disable Audio */
1317
	had_enable_audio(substream, intelhaddata, false);
1318 1319

	/* Update CTS value */
1320
	disp_samp_freq = intelhaddata->tmds_clock_speed;
1321

1322
	retval = had_prog_n(substream->runtime->rate, &n_param, intelhaddata);
1323
	if (retval) {
1324 1325
		dev_err(intelhaddata->dev,
			"programming N value failed %#x\n", retval);
1326 1327
		goto out;
	}
1328 1329

	if (intelhaddata->dp_output)
1330
		link_rate = intelhaddata->link_rate;
1331

1332 1333
	had_prog_cts(substream->runtime->rate, disp_samp_freq, link_rate,
		     n_param, intelhaddata);
1334 1335

	/* Enable Audio */
1336
	had_enable_audio(substream, intelhaddata, true);
1337 1338

out:
1339
	had_substream_put(intelhaddata);
1340 1341 1342
	return retval;
}

1343
/* process hot plug, called from wq with mutex locked */
1344
static void had_process_hot_plug(struct snd_intelhad *intelhaddata)
1345 1346 1347
{
	struct snd_pcm_substream *substream;

1348
	spin_lock_irq(&intelhaddata->had_spinlock);
1349
	if (intelhaddata->connected) {
1350
		dev_dbg(intelhaddata->dev, "Device already connected\n");
1351
		spin_unlock_irq(&intelhaddata->had_spinlock);
1352
		return;
1353
	}
1354

1355
	intelhaddata->connected = true;
1356 1357
	dev_dbg(intelhaddata->dev,
		"%s @ %d:DEBUG PLUG/UNPLUG : HAD_DRV_CONNECTED\n",
1358
			__func__, __LINE__);
1359
	spin_unlock_irq(&intelhaddata->had_spinlock);
1360 1361

	/* Safety check */
1362
	substream = had_substream_get(intelhaddata);
1363
	if (substream) {
1364 1365
		dev_dbg(intelhaddata->dev,
			"Force to stop the active stream by disconnection\n");
1366 1367
		/* Set runtime->state to hw_params done */
		snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
1368
		had_substream_put(intelhaddata);
1369 1370 1371 1372 1373
	}

	had_build_channel_allocation_map(intelhaddata);
}

1374
/* process hot unplug, called from wq with mutex locked */
1375
static void had_process_hot_unplug(struct snd_intelhad *intelhaddata)
1376
{
1377
	struct snd_pcm_substream *substream;
1378

1379 1380
	substream = had_substream_get(intelhaddata);

1381
	spin_lock_irq(&intelhaddata->had_spinlock);
1382

1383
	if (!intelhaddata->connected) {
1384
		dev_dbg(intelhaddata->dev, "Device already disconnected\n");
1385
		spin_unlock_irq(&intelhaddata->had_spinlock);
1386
		goto out;
1387 1388 1389

	}

1390
	/* Disable Audio */
1391
	had_enable_audio(substream, intelhaddata, false);
1392

1393
	intelhaddata->connected = false;
1394 1395
	dev_dbg(intelhaddata->dev,
		"%s @ %d:DEBUG PLUG/UNPLUG : HAD_DRV_DISCONNECTED\n",
1396
			__func__, __LINE__);
1397
	spin_unlock_irq(&intelhaddata->had_spinlock);
1398 1399

	/* Report to above ALSA layer */
1400 1401
	if (substream)
		snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
1402

1403 1404 1405
 out:
	if (substream)
		had_substream_put(intelhaddata);
1406 1407 1408 1409
	kfree(intelhaddata->chmap->chmap);
	intelhaddata->chmap->chmap = NULL;
}

1410 1411 1412
/*
 * ALSA iec958 and ELD controls
 */
1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426

static int had_iec958_info(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_info *uinfo)
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
	uinfo->count = 1;
	return 0;
}

static int had_iec958_get(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	struct snd_intelhad *intelhaddata = snd_kcontrol_chip(kcontrol);

1427
	mutex_lock(&intelhaddata->mutex);
1428 1429 1430 1431 1432 1433
	ucontrol->value.iec958.status[0] = (intelhaddata->aes_bits >> 0) & 0xff;
	ucontrol->value.iec958.status[1] = (intelhaddata->aes_bits >> 8) & 0xff;
	ucontrol->value.iec958.status[2] =
					(intelhaddata->aes_bits >> 16) & 0xff;
	ucontrol->value.iec958.status[3] =
					(intelhaddata->aes_bits >> 24) & 0xff;
1434
	mutex_unlock(&intelhaddata->mutex);
1435 1436
	return 0;
}
1437

1438 1439 1440 1441 1442 1443 1444 1445 1446
static int had_iec958_mask_get(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	ucontrol->value.iec958.status[0] = 0xff;
	ucontrol->value.iec958.status[1] = 0xff;
	ucontrol->value.iec958.status[2] = 0xff;
	ucontrol->value.iec958.status[3] = 0xff;
	return 0;
}
1447

1448 1449 1450 1451 1452
static int had_iec958_put(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	unsigned int val;
	struct snd_intelhad *intelhaddata = snd_kcontrol_chip(kcontrol);
1453
	int changed = 0;
1454 1455 1456 1457 1458

	val = (ucontrol->value.iec958.status[0] << 0) |
		(ucontrol->value.iec958.status[1] << 8) |
		(ucontrol->value.iec958.status[2] << 16) |
		(ucontrol->value.iec958.status[3] << 24);
1459
	mutex_lock(&intelhaddata->mutex);
1460 1461
	if (intelhaddata->aes_bits != val) {
		intelhaddata->aes_bits = val;
1462
		changed = 1;
1463
	}
1464 1465
	mutex_unlock(&intelhaddata->mutex);
	return changed;
1466 1467
}

1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486
static int had_ctl_eld_info(struct snd_kcontrol *kcontrol,
			    struct snd_ctl_elem_info *uinfo)
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
	uinfo->count = HDMI_MAX_ELD_BYTES;
	return 0;
}

static int had_ctl_eld_get(struct snd_kcontrol *kcontrol,
			   struct snd_ctl_elem_value *ucontrol)
{
	struct snd_intelhad *intelhaddata = snd_kcontrol_chip(kcontrol);

	mutex_lock(&intelhaddata->mutex);
	memcpy(ucontrol->value.bytes.data, intelhaddata->eld,
	       HDMI_MAX_ELD_BYTES);
	mutex_unlock(&intelhaddata->mutex);
	return 0;
}
1487

1488
static const struct snd_kcontrol_new had_controls[] = {
1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510
	{
		.access = SNDRV_CTL_ELEM_ACCESS_READ,
		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
		.info = had_iec958_info, /* shared */
		.get = had_iec958_mask_get,
	},
	{
		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
		.info = had_iec958_info,
		.get = had_iec958_get,
		.put = had_iec958_put,
	},
	{
		.access = (SNDRV_CTL_ELEM_ACCESS_READ |
			   SNDRV_CTL_ELEM_ACCESS_VOLATILE),
		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
		.name = "ELD",
		.info = had_ctl_eld_info,
		.get = had_ctl_eld_get,
	},
1511 1512
};

1513 1514 1515
/*
 * audio interrupt handler
 */
1516 1517 1518 1519 1520
static irqreturn_t display_pipe_interrupt_handler(int irq, void *dev_id)
{
	struct snd_intelhad *ctx = dev_id;
	u32 audio_stat, audio_reg;

T
Takashi Iwai 已提交
1521
	audio_reg = AUD_HDMI_STATUS;
1522
	had_read_register(ctx, audio_reg, &audio_stat);
1523 1524

	if (audio_stat & HDMI_AUDIO_UNDERRUN) {
1525
		had_write_register(ctx, audio_reg, HDMI_AUDIO_UNDERRUN);
1526 1527 1528 1529
		had_process_buffer_underrun(ctx);
	}

	if (audio_stat & HDMI_AUDIO_BUFFER_DONE) {
1530
		had_write_register(ctx, audio_reg, HDMI_AUDIO_BUFFER_DONE);
1531 1532 1533 1534 1535 1536
		had_process_buffer_done(ctx);
	}

	return IRQ_HANDLED;
}

1537 1538 1539
/*
 * monitor plug/unplug notification from i915; just kick off the work
 */
1540 1541 1542 1543
static void notify_audio_lpe(struct platform_device *pdev)
{
	struct snd_intelhad *ctx = platform_get_drvdata(pdev);

1544 1545
	schedule_work(&ctx->hdmi_audio_wq);
}
1546

1547
/* the work to handle monitor hot plug/unplug */
1548 1549 1550 1551 1552
static void had_audio_wq(struct work_struct *work)
{
	struct snd_intelhad *ctx =
		container_of(work, struct snd_intelhad, hdmi_audio_wq);
	struct intel_hdmi_lpe_audio_pdata *pdata = ctx->dev->platform_data;
1553

T
Takashi Iwai 已提交
1554
	pm_runtime_get_sync(ctx->dev);
1555
	mutex_lock(&ctx->mutex);
1556 1557 1558
	if (!pdata->hdmi_connected) {
		dev_dbg(ctx->dev, "%s: Event: HAD_NOTIFY_HOT_UNPLUG\n",
			__func__);
1559
		memset(ctx->eld, 0, sizeof(ctx->eld)); /* clear the old ELD */
1560
		had_process_hot_unplug(ctx);
1561 1562 1563
	} else {
		struct intel_hdmi_lpe_audio_eld *eld = &pdata->eld;

1564 1565 1566
		dev_dbg(ctx->dev, "%s: HAD_NOTIFY_ELD : port = %d, tmds = %d\n",
			__func__, eld->port_id,	pdata->tmds_clock_speed);

1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577
		switch (eld->pipe_id) {
		case 0:
			ctx->had_config_offset = AUDIO_HDMI_CONFIG_A;
			break;
		case 1:
			ctx->had_config_offset = AUDIO_HDMI_CONFIG_B;
			break;
		case 2:
			ctx->had_config_offset = AUDIO_HDMI_CONFIG_C;
			break;
		default:
1578
			dev_dbg(ctx->dev, "Invalid pipe %d\n",
1579 1580 1581 1582
				eld->pipe_id);
			break;
		}

1583
		memcpy(ctx->eld, eld->eld_data, sizeof(ctx->eld));
1584

1585 1586 1587
		ctx->dp_output = pdata->dp_output;
		ctx->tmds_clock_speed = pdata->tmds_clock_speed;
		ctx->link_rate = pdata->link_rate;
1588

1589
		had_process_hot_plug(ctx);
1590

1591
		/* Process mode change if stream is active */
1592
		had_process_mode_change(ctx);
1593
	}
1594
	mutex_unlock(&ctx->mutex);
T
Takashi Iwai 已提交
1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632
	pm_runtime_put(ctx->dev);
}

/*
 * PM callbacks
 */

static int hdmi_lpe_audio_runtime_suspend(struct device *dev)
{
	struct snd_intelhad *ctx = dev_get_drvdata(dev);
	struct snd_pcm_substream *substream;

	substream = had_substream_get(ctx);
	if (substream) {
		snd_pcm_suspend(substream);
		had_substream_put(ctx);
	}

	return 0;
}

static int hdmi_lpe_audio_suspend(struct device *dev)
{
	struct snd_intelhad *ctx = dev_get_drvdata(dev);
	int err;

	err = hdmi_lpe_audio_runtime_suspend(dev);
	if (!err)
		snd_power_change_state(ctx->card, SNDRV_CTL_POWER_D3hot);
	return err;
}

static int hdmi_lpe_audio_resume(struct device *dev)
{
	struct snd_intelhad *ctx = dev_get_drvdata(dev);

	snd_power_change_state(ctx->card, SNDRV_CTL_POWER_D0);
	return 0;
1633 1634 1635 1636 1637 1638 1639
}

/* release resources */
static void hdmi_lpe_audio_free(struct snd_card *card)
{
	struct snd_intelhad *ctx = card->private_data;

1640 1641
	cancel_work_sync(&ctx->hdmi_audio_wq);

1642 1643 1644 1645 1646 1647
	if (ctx->mmio_start)
		iounmap(ctx->mmio_start);
	if (ctx->irq >= 0)
		free_irq(ctx->irq, ctx);
}

1648
/*
1649
 * hdmi_lpe_audio_probe - start bridge with i915
1650
 *
1651
 * This function is called when the i915 driver creates the
T
Takashi Iwai 已提交
1652
 * hdmi-lpe-audio platform device.
1653
 */
1654
static int hdmi_lpe_audio_probe(struct platform_device *pdev)
1655 1656
{
	struct snd_card *card;
1657 1658 1659 1660 1661
	struct snd_intelhad *ctx;
	struct snd_pcm *pcm;
	struct intel_hdmi_lpe_audio_pdata *pdata;
	int irq;
	struct resource *res_mmio;
1662
	int i, ret;
1663 1664 1665 1666 1667 1668

	pdata = pdev->dev.platform_data;
	if (!pdata) {
		dev_err(&pdev->dev, "%s: quit: pdata not allocated by i915!!\n", __func__);
		return -EINVAL;
	}
1669

1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681
	/* get resources */
	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		dev_err(&pdev->dev, "Could not get irq resource\n");
		return -ENODEV;
	}

	res_mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res_mmio) {
		dev_err(&pdev->dev, "Could not get IO_MEM resources\n");
		return -ENXIO;
	}
1682

1683
	/* create a card instance with ALSA framework */
1684 1685 1686 1687 1688 1689 1690
	ret = snd_card_new(&pdev->dev, hdmi_card_index, hdmi_card_id,
			   THIS_MODULE, sizeof(*ctx), &card);
	if (ret)
		return ret;

	ctx = card->private_data;
	spin_lock_init(&ctx->had_spinlock);
1691
	mutex_init(&ctx->mutex);
1692
	ctx->connected = false;
1693 1694 1695 1696
	ctx->dev = &pdev->dev;
	ctx->card = card;
	ctx->aes_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
	strcpy(card->driver, INTEL_HAD);
1697 1698
	strcpy(card->shortname, "Intel HDMI/DP LPE Audio");
	strcpy(card->longname, "Intel HDMI/DP LPE Audio");
1699 1700 1701

	ctx->irq = -1;
	ctx->tmds_clock_speed = DIS_SAMPLE_RATE_148_5;
1702
	INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq);
1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721

	card->private_free = hdmi_lpe_audio_free;

	/* assume pipe A as default */
	ctx->had_config_offset = AUDIO_HDMI_CONFIG_A;

	platform_set_drvdata(pdev, ctx);

	dev_dbg(&pdev->dev, "%s: mmio_start = 0x%x, mmio_end = 0x%x\n",
		__func__, (unsigned int)res_mmio->start,
		(unsigned int)res_mmio->end);

	ctx->mmio_start = ioremap_nocache(res_mmio->start,
					  (size_t)(resource_size(res_mmio)));
	if (!ctx->mmio_start) {
		dev_err(&pdev->dev, "Could not get ioremap\n");
		ret = -EACCES;
		goto err;
	}
1722

1723 1724 1725 1726 1727 1728 1729
	/* setup interrupt handler */
	ret = request_irq(irq, display_pipe_interrupt_handler, 0,
			  pdev->name, ctx);
	if (ret < 0) {
		dev_err(&pdev->dev, "request_irq failed\n");
		goto err;
	}
1730

1731 1732 1733 1734 1735
	ctx->irq = irq;

	ret = snd_pcm_new(card, INTEL_HAD, PCM_INDEX, MAX_PB_STREAMS,
			  MAX_CAP_STREAMS, &pcm);
	if (ret)
1736 1737 1738
		goto err;

	/* setup private data which can be retrieved when required */
1739
	pcm->private_data = ctx;
1740 1741
	pcm->info_flags = 0;
	strncpy(pcm->name, card->shortname, strlen(card->shortname));
1742
	/* setup the ops for playabck */
1743
	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &had_pcm_ops);
1744 1745 1746 1747 1748

	/* only 32bit addressable */
	dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
	dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));

1749 1750
	/* allocate dma pages;
	 * try to allocate 600k buffer as default which is large enough
1751
	 */
1752
	snd_pcm_lib_preallocate_pages_for_all(pcm,
1753
			SNDRV_DMA_TYPE_DEV, NULL,
1754
			HAD_DEFAULT_BUFFER, HAD_MAX_BUFFER);
1755

1756 1757 1758 1759 1760 1761
	/* create controls */
	for (i = 0; i < ARRAY_SIZE(had_controls); i++) {
		ret = snd_ctl_add(card, snd_ctl_new1(&had_controls[i], ctx));
		if (ret < 0)
			goto err;
	}
1762 1763 1764 1765

	init_channel_allocations();

	/* Register channel map controls */
1766 1767
	ret = had_register_chmap_ctls(ctx, pcm);
	if (ret < 0)
1768 1769
		goto err;

1770 1771
	ret = snd_card_register(card);
	if (ret)
1772 1773
		goto err;

1774
	spin_lock_irq(&pdata->lpe_audio_slock);
1775
	pdata->notify_audio_lpe = notify_audio_lpe;
1776
	pdata->notify_pending = false;
1777
	spin_unlock_irq(&pdata->lpe_audio_slock);
1778 1779 1780 1781

	pm_runtime_set_active(&pdev->dev);
	pm_runtime_enable(&pdev->dev);

1782
	dev_dbg(&pdev->dev, "%s: handle pending notification\n", __func__);
1783
	schedule_work(&ctx->hdmi_audio_wq);
1784

1785
	return 0;
1786

1787 1788
err:
	snd_card_free(card);
1789
	return ret;
1790 1791
}

1792
/*
1793
 * hdmi_lpe_audio_remove - stop bridge with i915
1794
 *
T
Takashi Iwai 已提交
1795
 * This function is called when the platform device is destroyed.
1796
 */
1797
static int hdmi_lpe_audio_remove(struct platform_device *pdev)
1798
{
1799
	struct snd_intelhad *ctx = platform_get_drvdata(pdev);
1800

1801
	snd_card_free(ctx->card);
1802 1803 1804
	return 0;
}

T
Takashi Iwai 已提交
1805 1806 1807 1808 1809
static const struct dev_pm_ops hdmi_lpe_audio_pm = {
	SET_SYSTEM_SLEEP_PM_OPS(hdmi_lpe_audio_suspend, hdmi_lpe_audio_resume)
	SET_RUNTIME_PM_OPS(hdmi_lpe_audio_runtime_suspend, NULL, NULL)
};

1810 1811 1812
static struct platform_driver hdmi_lpe_audio_driver = {
	.driver		= {
		.name  = "hdmi-lpe-audio",
T
Takashi Iwai 已提交
1813
		.pm = &hdmi_lpe_audio_pm,
1814 1815 1816 1817 1818 1819 1820 1821
	},
	.probe          = hdmi_lpe_audio_probe,
	.remove		= hdmi_lpe_audio_remove,
};

module_platform_driver(hdmi_lpe_audio_driver);
MODULE_ALIAS("platform:hdmi_lpe_audio");

1822 1823 1824 1825 1826 1827 1828
MODULE_AUTHOR("Sailaja Bandarupalli <sailaja.bandarupalli@intel.com>");
MODULE_AUTHOR("Ramesh Babu K V <ramesh.babu@intel.com>");
MODULE_AUTHOR("Vaibhav Agarwal <vaibhav.agarwal@intel.com>");
MODULE_AUTHOR("Jerome Anand <jerome.anand@intel.com>");
MODULE_DESCRIPTION("Intel HDMI Audio driver");
MODULE_LICENSE("GPL v2");
MODULE_SUPPORTED_DEVICE("{Intel,Intel_HAD}");