mpc5200_psc_i2s.c 11.8 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 24 25 26 27
/*
 * Freescale MPC5200 PSC in I2S mode
 * ALSA SoC Digital Audio Interface (DAI) driver
 *
 * Copyright (C) 2008 Secret Lab Technologies Ltd.
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/dma-mapping.h>

#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/soc.h>
#include <sound/soc-of-simple.h>

#include <sysdev/bestcomm/bestcomm.h>
#include <sysdev/bestcomm/gen_bd.h>
#include <asm/mpc52xx_psc.h>

28 29
#include "mpc5200_dma.h"

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
MODULE_DESCRIPTION("Freescale MPC5200 PSC in I2S mode ASoC Driver");
MODULE_LICENSE("GPL");

/**
 * PSC_I2S_RATES: sample rates supported by the I2S
 *
 * This driver currently only supports the PSC running in I2S slave mode,
 * which means the codec determines the sample rate.  Therefore, we tell
 * ALSA that we support all rates and let the codec driver decide what rates
 * are really supported.
 */
#define PSC_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \
			SNDRV_PCM_RATE_CONTINUOUS)

/**
 * PSC_I2S_FORMATS: audio formats supported by the PSC I2S mode
 */
#define PSC_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \
			 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE | \
			 SNDRV_PCM_FMTBIT_S32_BE)

static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
53 54
				 struct snd_pcm_hw_params *params,
				 struct snd_soc_dai *dai)
55 56
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
57
	struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
58 59
	u32 mode;

60
	dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
		" periods=%i buffer_size=%i  buffer_bytes=%i\n",
		__func__, substream, params_period_size(params),
		params_period_bytes(params), params_periods(params),
		params_buffer_size(params), params_buffer_bytes(params));

	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S8:
		mode = MPC52xx_PSC_SICR_SIM_CODEC_8;
		break;
	case SNDRV_PCM_FORMAT_S16_BE:
		mode = MPC52xx_PSC_SICR_SIM_CODEC_16;
		break;
	case SNDRV_PCM_FORMAT_S24_BE:
		mode = MPC52xx_PSC_SICR_SIM_CODEC_24;
		break;
	case SNDRV_PCM_FORMAT_S32_BE:
		mode = MPC52xx_PSC_SICR_SIM_CODEC_32;
		break;
	default:
80
		dev_dbg(psc_dma->dev, "invalid format\n");
81 82
		return -EINVAL;
	}
83
	out_be32(&psc_dma->psc_regs->sicr, psc_dma->sicr | mode);
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106

	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);

	return 0;
}

/**
 * psc_i2s_set_sysclk: set the clock frequency and direction
 *
 * This function is called by the machine driver to tell us what the clock
 * frequency and direction are.
 *
 * Currently, we only support operating as a clock slave (SND_SOC_CLOCK_IN),
 * and we don't care about the frequency.  Return an error if the direction
 * is not SND_SOC_CLOCK_IN.
 *
 * @clk_id: reserved, should be zero
 * @freq: the frequency of the given clock ID, currently ignored
 * @dir: SND_SOC_CLOCK_IN (clock slave) or SND_SOC_CLOCK_OUT (clock master)
 */
static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
			      int clk_id, unsigned int freq, int dir)
{
107 108
	struct psc_dma *psc_dma = cpu_dai->private_data;
	dev_dbg(psc_dma->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n",
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
				cpu_dai, dir);
	return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL;
}

/**
 * psc_i2s_set_fmt: set the serial format.
 *
 * This function is called by the machine driver to tell us what serial
 * format to use.
 *
 * This driver only supports I2S mode.  Return an error if the format is
 * not SND_SOC_DAIFMT_I2S.
 *
 * @format: one of SND_SOC_DAIFMT_xxx
 */
static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
{
126 127
	struct psc_dma *psc_dma = cpu_dai->private_data;
	dev_dbg(psc_dma->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n",
128 129 130 131 132 133 134 135 136 137 138 139 140 141
				cpu_dai, format);
	return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL;
}

/* ---------------------------------------------------------------------
 * ALSA SoC Bindings
 *
 * - Digital Audio Interface (DAI) template
 * - create/destroy dai hooks
 */

/**
 * psc_i2s_dai_template: template CPU Digital Audio Interface
 */
142
static struct snd_soc_dai_ops psc_i2s_dai_ops = {
143
	.startup	= psc_dma_startup,
144
	.hw_params	= psc_i2s_hw_params,
145 146 147
	.hw_free	= psc_dma_hw_free,
	.shutdown	= psc_dma_shutdown,
	.trigger	= psc_dma_trigger,
148 149 150 151
	.set_sysclk	= psc_i2s_set_sysclk,
	.set_fmt	= psc_i2s_set_fmt,
};

152 153 154 155 156 157 158 159 160 161 162 163 164
static struct snd_soc_dai psc_i2s_dai_template = {
	.playback = {
		.channels_min = 2,
		.channels_max = 2,
		.rates = PSC_I2S_RATES,
		.formats = PSC_I2S_FORMATS,
	},
	.capture = {
		.channels_min = 2,
		.channels_max = 2,
		.rates = PSC_I2S_RATES,
		.formats = PSC_I2S_FORMATS,
	},
165
	.ops = &psc_i2s_dai_ops,
166 167 168 169 170 171 172 173 174
};

/* ---------------------------------------------------------------------
 * Sysfs attributes for debugging
 */

static ssize_t psc_i2s_status_show(struct device *dev,
			   struct device_attribute *attr, char *buf)
{
175
	struct psc_dma *psc_dma = dev_get_drvdata(dev);
176 177 178

	return sprintf(buf, "status=%.4x sicr=%.8x rfnum=%i rfstat=0x%.4x "
			"tfnum=%i tfstat=0x%.4x\n",
179 180 181 182 183 184
			in_be16(&psc_dma->psc_regs->sr_csr.status),
			in_be32(&psc_dma->psc_regs->sicr),
			in_be16(&psc_dma->fifo_regs->rfnum) & 0x1ff,
			in_be16(&psc_dma->fifo_regs->rfstat),
			in_be16(&psc_dma->fifo_regs->tfnum) & 0x1ff,
			in_be16(&psc_dma->fifo_regs->tfstat));
185 186
}

187
static int *psc_i2s_get_stat_attr(struct psc_dma *psc_dma, const char *name)
188 189
{
	if (strcmp(name, "playback_underrun") == 0)
190
		return &psc_dma->stats.underrun_count;
191
	if (strcmp(name, "capture_overrun") == 0)
192
		return &psc_dma->stats.overrun_count;
193 194 195 196 197 198 199

	return NULL;
}

static ssize_t psc_i2s_stat_show(struct device *dev,
				 struct device_attribute *attr, char *buf)
{
200
	struct psc_dma *psc_dma = dev_get_drvdata(dev);
201 202
	int *attrib;

203
	attrib = psc_i2s_get_stat_attr(psc_dma, attr->attr.name);
204 205 206 207 208 209 210 211 212 213 214
	if (!attrib)
		return 0;

	return sprintf(buf, "%i\n", *attrib);
}

static ssize_t psc_i2s_stat_store(struct device *dev,
				  struct device_attribute *attr,
				  const char *buf,
				  size_t count)
{
215
	struct psc_dma *psc_dma = dev_get_drvdata(dev);
216 217
	int *attrib;

218
	attrib = psc_i2s_get_stat_attr(psc_dma, attr->attr.name);
219 220 221 222 223 224 225
	if (!attrib)
		return 0;

	*attrib = simple_strtoul(buf, NULL, 0);
	return count;
}

226 227 228 229 230
static DEVICE_ATTR(status, 0644, psc_i2s_status_show, NULL);
static DEVICE_ATTR(playback_underrun, 0644, psc_i2s_stat_show,
			psc_i2s_stat_store);
static DEVICE_ATTR(capture_overrun, 0644, psc_i2s_stat_show,
			psc_i2s_stat_store);
231 232 233 234 235 236 237 238 239 240

/* ---------------------------------------------------------------------
 * OF platform bus binding code:
 * - Probe/remove operations
 * - OF device match table
 */
static int __devinit psc_i2s_of_probe(struct of_device *op,
				      const struct of_device_id *match)
{
	phys_addr_t fifo;
241
	struct psc_dma *psc_dma;
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
	struct resource res;
	int size, psc_id, irq, rc;
	const __be32 *prop;
	void __iomem *regs;

	dev_dbg(&op->dev, "probing psc i2s device\n");

	/* Get the PSC ID */
	prop = of_get_property(op->node, "cell-index", &size);
	if (!prop || size < sizeof *prop)
		return -ENODEV;
	psc_id = be32_to_cpu(*prop);

	/* Fetch the registers and IRQ of the PSC */
	irq = irq_of_parse_and_map(op->node, 0);
	if (of_address_to_resource(op->node, 0, &res)) {
		dev_err(&op->dev, "Missing reg property\n");
		return -ENODEV;
	}
	regs = ioremap(res.start, 1 + res.end - res.start);
	if (!regs) {
		dev_err(&op->dev, "Could not map registers\n");
		return -ENODEV;
	}

	/* Allocate and initialize the driver private data */
268 269
	psc_dma = kzalloc(sizeof *psc_dma, GFP_KERNEL);
	if (!psc_dma) {
270 271 272
		iounmap(regs);
		return -ENOMEM;
	}
273 274 275 276 277 278 279 280
	spin_lock_init(&psc_dma->lock);
	psc_dma->irq = irq;
	psc_dma->psc_regs = regs;
	psc_dma->fifo_regs = regs + sizeof *psc_dma->psc_regs;
	psc_dma->dev = &op->dev;
	psc_dma->playback.psc_dma = psc_dma;
	psc_dma->capture.psc_dma = psc_dma;
	snprintf(psc_dma->name, sizeof psc_dma->name, "PSC%u", psc_id+1);
281 282

	/* Fill out the CPU DAI structure */
283 284 285 286
	memcpy(&psc_dma->dai, &psc_i2s_dai_template, sizeof psc_dma->dai);
	psc_dma->dai.private_data = psc_dma;
	psc_dma->dai.name = psc_dma->name;
	psc_dma->dai.id = psc_id;
287 288 289 290

	/* Find the address of the fifo data registers and setup the
	 * DMA tasks */
	fifo = res.start + offsetof(struct mpc52xx_psc, buffer.buffer_32);
291
	psc_dma->capture.bcom_task =
292
		bcom_psc_gen_bd_rx_init(psc_id, 10, fifo, 512);
293
	psc_dma->playback.bcom_task =
294
		bcom_psc_gen_bd_tx_init(psc_id, 10, fifo);
295 296
	if (!psc_dma->capture.bcom_task ||
	    !psc_dma->playback.bcom_task) {
297 298
		dev_err(&op->dev, "Could not allocate bestcomm tasks\n");
		iounmap(regs);
299
		kfree(psc_dma);
300 301 302 303
		return -ENODEV;
	}

	/* Disable all interrupts and reset the PSC */
304 305 306 307 308
	out_be16(&psc_dma->psc_regs->isr_imr.imr, 0);
	out_8(&psc_dma->psc_regs->command, 3 << 4); /* reset transmitter */
	out_8(&psc_dma->psc_regs->command, 2 << 4); /* reset receiver */
	out_8(&psc_dma->psc_regs->command, 1 << 4); /* reset mode */
	out_8(&psc_dma->psc_regs->command, 4 << 4); /* reset error */
309 310

	/* Configure the serial interface mode; defaulting to CODEC8 mode */
311
	psc_dma->sicr = MPC52xx_PSC_SICR_DTS1 | MPC52xx_PSC_SICR_I2S |
312 313
			MPC52xx_PSC_SICR_CLKPOL;
	if (of_get_property(op->node, "fsl,cellslave", NULL))
314
		psc_dma->sicr |= MPC52xx_PSC_SICR_CELLSLAVE |
315
				 MPC52xx_PSC_SICR_GENCLK;
316 317
	out_be32(&psc_dma->psc_regs->sicr,
		 psc_dma->sicr | MPC52xx_PSC_SICR_SIM_CODEC_8);
318 319 320 321 322 323 324 325 326 327

	/* Check for the codec handle.  If it is not present then we
	 * are done */
	if (!of_get_property(op->node, "codec-handle", NULL))
		return 0;

	/* Set up mode register;
	 * First write: RxRdy (FIFO Alarm) generates rx FIFO irq
	 * Second write: register Normal mode for non loopback
	 */
328 329
	out_8(&psc_dma->psc_regs->mode, 0);
	out_8(&psc_dma->psc_regs->mode, 0);
330 331

	/* Set the TX and RX fifo alarm thresholds */
332 333 334 335
	out_be16(&psc_dma->fifo_regs->rfalarm, 0x100);
	out_8(&psc_dma->fifo_regs->rfcntl, 0x4);
	out_be16(&psc_dma->fifo_regs->tfalarm, 0x100);
	out_8(&psc_dma->fifo_regs->tfcntl, 0x7);
336 337

	/* Lookup the IRQ numbers */
338 339 340 341
	psc_dma->playback.irq =
		bcom_get_task_irq(psc_dma->playback.bcom_task);
	psc_dma->capture.irq =
		bcom_get_task_irq(psc_dma->capture.bcom_task);
342 343

	/* Save what we've done so it can be found again later */
344
	dev_set_drvdata(&op->dev, psc_dma);
345 346

	/* Register the SYSFS files */
347 348 349
	rc = device_create_file(psc_dma->dev, &dev_attr_status);
	rc |= device_create_file(psc_dma->dev, &dev_attr_capture_overrun);
	rc |= device_create_file(psc_dma->dev, &dev_attr_playback_underrun);
350
	if (rc)
351
		dev_info(psc_dma->dev, "error creating sysfs files\n");
352

353
	snd_soc_register_platform(&psc_dma_pcm_soc_platform);
M
Mark Brown 已提交
354

355
	/* Tell the ASoC OF helpers about it */
356 357
	of_snd_soc_register_platform(&psc_dma_pcm_soc_platform, op->node,
				     &psc_dma->dai);
358 359 360 361 362 363

	return 0;
}

static int __devexit psc_i2s_of_remove(struct of_device *op)
{
364
	struct psc_dma *psc_dma = dev_get_drvdata(&op->dev);
365 366 367

	dev_dbg(&op->dev, "psc_i2s_remove()\n");

368
	snd_soc_unregister_platform(&psc_dma_pcm_soc_platform);
M
Mark Brown 已提交
369

370 371
	bcom_gen_bd_rx_release(psc_dma->capture.bcom_task);
	bcom_gen_bd_tx_release(psc_dma->playback.bcom_task);
372

373 374 375
	iounmap(psc_dma->psc_regs);
	iounmap(psc_dma->fifo_regs);
	kfree(psc_dma);
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
	dev_set_drvdata(&op->dev, NULL);

	return 0;
}

/* Match table for of_platform binding */
static struct of_device_id psc_i2s_match[] __devinitdata = {
	{ .compatible = "fsl,mpc5200-psc-i2s", },
	{}
};
MODULE_DEVICE_TABLE(of, psc_i2s_match);

static struct of_platform_driver psc_i2s_driver = {
	.match_table = psc_i2s_match,
	.probe = psc_i2s_of_probe,
	.remove = __devexit_p(psc_i2s_of_remove),
	.driver = {
		.name = "mpc5200-psc-i2s",
		.owner = THIS_MODULE,
	},
};

/* ---------------------------------------------------------------------
 * Module setup and teardown; simply register the of_platform driver
 * for the PSC in I2S mode.
 */
static int __init psc_i2s_init(void)
{
	return of_register_platform_driver(&psc_i2s_driver);
}
module_init(psc_i2s_init);

static void __exit psc_i2s_exit(void)
{
	of_unregister_platform_driver(&psc_i2s_driver);
}
module_exit(psc_i2s_exit);