pxa2xx-ac97-lib.c 8.3 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
/*
 * Based on sound/arm/pxa2xx-ac97.c and sound/soc/pxa/pxa2xx-ac97.c
 * which contain:
 *
 * Author:	Nicolas Pitre
 * Created:	Dec 02, 2004
 * Copyright:	MontaVista Software Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/delay.h>

#include <sound/ac97_codec.h>
#include <sound/pxa2xx-lib.h>

#include <asm/irq.h>
24
#include <mach/regs-ac97.h>
25 26 27 28 29 30 31
#include <mach/audio.h>

static DEFINE_MUTEX(car_mutex);
static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
static volatile long gsr_bits;
static struct clk *ac97_clk;
static struct clk *ac97conf_clk;
32
static int reset_gpio;
33

34 35
extern void pxa27x_assert_ac97reset(int reset_gpio, int on);

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
/*
 * Beware PXA27x bugs:
 *
 *   o Slot 12 read from modem space will hang controller.
 *   o CDONE, SDONE interrupt fails after any slot 12 IO.
 *
 * We therefore have an hybrid approach for waiting on SDONE (interrupt or
 * 1 jiffy timeout if interrupt never comes).
 */

unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{
	unsigned short val = -1;
	volatile u32 *reg_addr;

	mutex_lock(&car_mutex);

	/* set up primary or secondary codec space */
54
	if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS)
55 56 57 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
		reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
	else
		reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
	reg_addr += (reg >> 1);

	/* start read access across the ac97 link */
	GSR = GSR_CDONE | GSR_SDONE;
	gsr_bits = 0;
	val = *reg_addr;
	if (reg == AC97_GPIO_STATUS)
		goto out;
	if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 &&
	    !((GSR | gsr_bits) & GSR_SDONE)) {
		printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n",
				__func__, reg, GSR | gsr_bits);
		val = -1;
		goto out;
	}

	/* valid data now */
	GSR = GSR_CDONE | GSR_SDONE;
	gsr_bits = 0;
	val = *reg_addr;
	/* but we've just started another cycle... */
	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);

out:	mutex_unlock(&car_mutex);
	return val;
}
EXPORT_SYMBOL_GPL(pxa2xx_ac97_read);

void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
			unsigned short val)
{
	volatile u32 *reg_addr;

	mutex_lock(&car_mutex);

	/* set up primary or secondary codec space */
94
	if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS)
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
		reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
	else
		reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
	reg_addr += (reg >> 1);

	GSR = GSR_CDONE | GSR_SDONE;
	gsr_bits = 0;
	*reg_addr = val;
	if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 &&
	    !((GSR | gsr_bits) & GSR_CDONE))
		printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n",
				__func__, reg, GSR | gsr_bits);

	mutex_unlock(&car_mutex);
}
EXPORT_SYMBOL_GPL(pxa2xx_ac97_write);

112 113
#ifdef CONFIG_PXA25x
static inline void pxa_ac97_warm_pxa25x(void)
114 115 116
{
	gsr_bits = 0;

117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
	GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN;
	wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
}

static inline void pxa_ac97_cold_pxa25x(void)
{
	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */

	gsr_bits = 0;

	GCR = GCR_COLD_RST;
	GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
	wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
}
#endif

134
#ifdef CONFIG_PXA27x
135 136 137 138
static inline void pxa_ac97_warm_pxa27x(void)
{
	gsr_bits = 0;

139 140
	/* warm reset broken on Bulverde, so manually keep AC97 reset high */
	pxa27x_assert_ac97reset(reset_gpio, 1);
141 142
	udelay(10);
	GCR |= GCR_WARM_RST;
143
	pxa27x_assert_ac97reset(reset_gpio, 0);
144
	udelay(500);
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
}

static inline void pxa_ac97_cold_pxa27x(void)
{
	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */

	gsr_bits = 0;

	/* PXA27x Developers Manual section 13.5.2.2.1 */
	clk_enable(ac97conf_clk);
	udelay(5);
	clk_disable(ac97conf_clk);
	GCR = GCR_COLD_RST;
	udelay(50);
}
161 162
#endif

163 164 165 166
#ifdef CONFIG_PXA3xx
static inline void pxa_ac97_warm_pxa3xx(void)
{
	int timeout = 100;
167

168
	gsr_bits = 0;
169

170 171 172 173
	/* Can't use interrupts */
	GCR |= GCR_WARM_RST;
	while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
		mdelay(1);
174 175
}

176
static inline void pxa_ac97_cold_pxa3xx(void)
177 178 179 180 181 182 183 184 185 186 187 188 189
{
	int timeout = 1000;

	/* Hold CLKBPB for 100us */
	GCR = 0;
	GCR = GCR_CLKBPB;
	udelay(100);
	GCR = 0;

	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */

	gsr_bits = 0;
190

191 192 193 194 195 196
	/* Can't use interrupts on PXA3xx */
	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);

	GCR = GCR_WARM_RST | GCR_COLD_RST;
	while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--)
		mdelay(10);
197 198 199 200 201
}
#endif

bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97)
{
202 203
	unsigned long gsr;

204
#ifdef CONFIG_PXA25x
205
	if (cpu_is_pxa25x())
206 207
		pxa_ac97_warm_pxa25x();
	else
208
#endif
209 210 211 212 213 214 215 216 217 218 219
#ifdef CONFIG_PXA27x
	if (cpu_is_pxa27x())
		pxa_ac97_warm_pxa27x();
	else
#endif
#ifdef CONFIG_PXA3xx
	if (cpu_is_pxa3xx())
		pxa_ac97_warm_pxa3xx();
	else
#endif
		BUG();
220 221
	gsr = GSR | gsr_bits;
	if (!(gsr & (GSR_PCR | GSR_SCR))) {
222
		printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
223
				 __func__, gsr);
224 225 226 227 228 229 230 231 232 233

		return false;
	}

	return true;
}
EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_warm_reset);

bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97)
{
234 235
	unsigned long gsr;

236
#ifdef CONFIG_PXA25x
237
	if (cpu_is_pxa25x())
238 239 240 241 242 243 244 245 246 247 248 249 250 251
		pxa_ac97_cold_pxa25x();
	else
#endif
#ifdef CONFIG_PXA27x
	if (cpu_is_pxa27x())
		pxa_ac97_cold_pxa27x();
	else
#endif
#ifdef CONFIG_PXA3xx
	if (cpu_is_pxa3xx())
		pxa_ac97_cold_pxa3xx();
	else
#endif
		BUG();
252

253 254
	gsr = GSR | gsr_bits;
	if (!(gsr & (GSR_PCR | GSR_SCR))) {
255
		printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
256
				 __func__, gsr);
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285

		return false;
	}

	return true;
}
EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_cold_reset);


void pxa2xx_ac97_finish_reset(struct snd_ac97 *ac97)
{
	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
}
EXPORT_SYMBOL_GPL(pxa2xx_ac97_finish_reset);

static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
{
	long status;

	status = GSR;
	if (status) {
		GSR = status;
		gsr_bits |= status;
		wake_up(&gsr_wq);

		/* Although we don't use those we still need to clear them
		   since they tend to spuriously trigger when MMC is used
		   (hardware bug? go figure)... */
286 287 288 289 290
		if (cpu_is_pxa27x()) {
			MISR = MISR_EOC;
			PISR = PISR_EOC;
			MCSR = MCSR_EOC;
		}
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317

		return IRQ_HANDLED;
	}

	return IRQ_NONE;
}

#ifdef CONFIG_PM
int pxa2xx_ac97_hw_suspend(void)
{
	GCR |= GCR_ACLINK_OFF;
	clk_disable(ac97_clk);
	return 0;
}
EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend);

int pxa2xx_ac97_hw_resume(void)
{
	clk_enable(ac97_clk);
	return 0;
}
EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume);
#endif

int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
{
	int ret;
318
	pxa2xx_audio_ops_t *pdata = dev->dev.platform_data;
319 320 321 322 323 324 325 326 327 328 329 330 331

	if (pdata) {
		switch (pdata->reset_gpio) {
		case 95:
		case 113:
			reset_gpio = pdata->reset_gpio;
			break;
		case 0:
			reset_gpio = 113;
			break;
		case -1:
			break;
		default:
332
			dev_err(&dev->dev, "Invalid reset GPIO %d\n",
333 334 335 336 337 338
				pdata->reset_gpio);
		}
	} else {
		if (cpu_is_pxa27x())
			reset_gpio = 113;
	}
339

340 341
	if (cpu_is_pxa27x()) {
		/* Use GPIO 113 as AC97 Reset on Bulverde */
342
		pxa27x_assert_ac97reset(reset_gpio, 0);
343 344 345 346
		ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
		if (IS_ERR(ac97conf_clk)) {
			ret = PTR_ERR(ac97conf_clk);
			ac97conf_clk = NULL;
347
			goto err_conf;
348
		}
349 350 351 352 353 354
	}

	ac97_clk = clk_get(&dev->dev, "AC97CLK");
	if (IS_ERR(ac97_clk)) {
		ret = PTR_ERR(ac97_clk);
		ac97_clk = NULL;
355
		goto err_clk;
356 357
	}

358 359 360 361
	ret = clk_enable(ac97_clk);
	if (ret)
		goto err_clk2;

Y
Yong Zhang 已提交
362
	ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL);
363 364 365 366
	if (ret < 0)
		goto err_irq;

	return 0;
367 368 369

err_irq:
	GCR |= GCR_ACLINK_OFF;
370 371 372 373
err_clk2:
	clk_put(ac97_clk);
	ac97_clk = NULL;
err_clk:
374 375 376 377
	if (ac97conf_clk) {
		clk_put(ac97conf_clk);
		ac97conf_clk = NULL;
	}
378
err_conf:
379 380 381 382 383 384 385 386
	return ret;
}
EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe);

void pxa2xx_ac97_hw_remove(struct platform_device *dev)
{
	GCR |= GCR_ACLINK_OFF;
	free_irq(IRQ_AC97, NULL);
387 388 389 390
	if (ac97conf_clk) {
		clk_put(ac97conf_clk);
		ac97conf_clk = NULL;
	}
391 392 393 394 395 396 397 398 399 400
	clk_disable(ac97_clk);
	clk_put(ac97_clk);
	ac97_clk = NULL;
}
EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_remove);

MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("Intel/Marvell PXA sound library");
MODULE_LICENSE("GPL");