/*
 * Glue audio driver for the SA1110 Assabet board & Philips UDA1341 codec.
 *
 * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License.
 *
 * This is the machine specific part of the Assabet/UDA1341 support.
 * This driver makes use of the UDA1341 and the sa1100-audio modules.
 *
 * History:
 *
 * 2000-05-21	Nicolas Pitre	Initial release.
 *
 * 2001-06-03	Nicolas Pitre	Made this file a separate module, based on
 * 				the former sa1100-uda1341.c driver.
 *
 * 2001-07-17	Nicolas Pitre	Supports 44100Hz and 22050Hz samplerate now.
 *
 * 2001-08-03	Russell King	Fix left/right channel swap.
 *				Attempt to reduce power consumption when idle.
 *
 * 2001-09-23	Russell King	Remove old L3 bus driver.
 *
 * Please note that fiddling too much with MDREFR results in oopses, so we don't
 * touch MDREFR unnecessarily, which means we don't touch it on close.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/errno.h>
#include <linux/sound.h>
#include <linux/soundcard.h>
#include <linux/cpufreq.h>
#include <linux/l3/l3.h>
#include <linux/l3/uda1341.h>

#include <asm/semaphore.h>
#include <asm/uaccess.h>
#include <asm/hardware.h>
#include <asm/dma.h>
#include <asm/arch/assabet.h>

#include "sa1100-audio.h"

/*
 * Define this to fix the power drain on early Assabets
 */
#define FIX_POWER_DRAIN

/*
 * Debugging?
 */
#undef DEBUG


#ifdef DEBUG
#define DPRINTK( x... )  printk( ##x )
#else
#define DPRINTK( x... )
#endif


#define AUDIO_RATE_DEFAULT	44100

/*
 * Mixer (UDA1341) interface
 */

static struct l3_client uda1341;

static int
mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
{
	/*
	 * We only accept mixer (type 'M') ioctls.
	 */
	if (_IOC_TYPE(cmd) != 'M')
		return -EINVAL;

	return l3_command(&uda1341, cmd, (void *)arg);
}

static struct file_operations assabet_mixer_fops = {
	ioctl:		mixer_ioctl,
	owner:		THIS_MODULE
};


/*
 * Audio interface
 */
static long audio_samplerate = AUDIO_RATE_DEFAULT;

/*
 * FIXME: what about SFRM going high when SSP is disabled?
 */
static void assabet_set_samplerate(long val)
{
	struct uda1341_cfg cfg;
	u_int clk_ref, clk_div;

	/* We don't want to mess with clocks when frames are in flight */
	Ser4SSCR0 &= ~SSCR0_SSE;
	/* wait for any frame to complete */
	udelay(125);

	/*
	 * Our clock source is derived from the CPLD on which we don't have
	 * much control unfortunately.  This was intended for a fixed 48000 Hz
	 * samplerate assuming a core clock of 221.2 MHz.  The CPLD appears
	 * to divide the memory clock so there is a ratio of 4608 between
	 * the core clock and the resulting samplerate (obtained by
	 * measurements, the CPLD equations should confirm that).
	 *
	 * Still we can play with the SA1110's clock divisor for the SSP port
	 * to get half the samplerate as well.
	 *
	 * Apparently the clock sent to the SA1110 for the SSP port is further
	 * more divided from the clock sent to the UDA1341 (some people tried
	 * to be too clever in their design, or simply failed to read the
	 * SA1110 manual).  If it was the same clock we would have been able
	 * to support a third samplerate with the UDA1341's 384FS mode.
	 *
	 * At least it would have been a minimum acceptable solution to be
	 * able to set the CPLD divisor by software.  The iPAQ design is
	 * certainly a better example to follow for a new design.
	 */
	clk_ref = cpufreq_get(0) * 1000 / 4608;
	if (val > clk_ref*4/7) {
		audio_samplerate = clk_ref;
		cfg.fs = 256;
		clk_div = SSCR0_SerClkDiv(2);
	} else {
		audio_samplerate = clk_ref/2;
		cfg.fs = 512;
		clk_div = SSCR0_SerClkDiv(4);
	}

	cfg.format = FMT_LSB16;
	l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);

	Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;
}

/*
 * Initialise the Assabet audio driver.
 *
 * Note that we have to be careful with the order that we do things here;
 * there is a D-type flip flop which is clocked from the SFRM line which
 * indicates whether the same is for the left or right channel to the
 * UDA1341.
 *
 * When you disable the SSP (by clearing SSCR0_SSE) it appears that the
 * SFRM signal can float high.  When you re-enable the SSP, you clock the
 * flip flop once, and end up swapping the left and right channels.
 *
 * The ASSABET_BCR_CODEC_RST line will force this flip flop into a known
 * state, but this line resets other devices as well!
 *
 * In addition to the above, it appears that powering down the UDA1341 on
 * early Assabets leaves the UDA_WS actively driving a logic '1' into the
 * chip, wasting power!  (you can tell this by D11 being half-on).  We
 * attempt to correct this by kicking the flip flop on init/open/close.
 * We should probably do this on PM resume as well.
 *
 * (Note the ordering of ASSABET_BCR_AUDIO_ON, SFRM and ASSABET_BCR_CODEC_RST
 * is important).
 */
static void assabet_audio_init(void *dummy)
{
	unsigned long flags;
	unsigned int mdrefr;

	local_irq_save(flags);

	/*
	 * Enable the power for the UDA1341 before driving any signals.
	 * We leave the audio amp (LM4880) disabled for now.
	 */
	ASSABET_BCR_set(ASSABET_BCR_AUDIO_ON);

#ifdef FIX_POWER_DRAIN
	GPSR = GPIO_SSP_SFRM;
	GPCR = GPIO_SSP_SFRM;
#endif

	ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
	ASSABET_BCR_clear(ASSABET_BCR_STEREO_LB);

	/*
	 * Setup the SSP uart.
	 */
	PPAR |= PPAR_SPR;
	Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(2);
	Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;
	GAFR |= GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_CLK;
	GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
	GPDR &= ~(GPIO_SSP_RXD | GPIO_SSP_CLK);
	Ser4SSCR0 |= SSCR0_SSE;

	/*
	 * Only give SFRM to the SSP after it has been enabled.
	 */
	GAFR |= GPIO_SSP_SFRM;

	/*
	 * The assabet board uses the SDRAM clock as the source clock for
	 * audio. This is supplied to the SA11x0 from the CPLD on pin 19.
	 * At 206MHz we need to run the audio clock (SDRAM bank 2)
	 * at half speed. This clock will scale with core frequency so
	 * the audio sample rate will also scale. The CPLD on Assabet
	 * will need to be programmed to match the core frequency.
	 */
	mdrefr = MDREFR;
	if ((mdrefr & (MDREFR_K2DB2 | MDREFR_K2RUN | MDREFR_EAPD |
		       MDREFR_KAPD)) != (MDREFR_K2DB2 | MDREFR_K2RUN)) {
		mdrefr |= MDREFR_K2DB2 | MDREFR_K2RUN;
		mdrefr &= ~(MDREFR_EAPD | MDREFR_KAPD);
		MDREFR = mdrefr;
		(void) MDREFR;
	}
	local_irq_restore(flags);

	/* Wait for the UDA1341 to wake up */
	mdelay(1);

	l3_open(&uda1341);

	assabet_set_samplerate(audio_samplerate);

	/* Enable the audio power */
	ASSABET_BCR_clear(ASSABET_BCR_QMUTE | ASSABET_BCR_SPK_OFF);
}

/*
 * Shutdown the Assabet audio driver.
 *
 * We have to be careful about the SFRM line here for the same reasons
 * described in the initialisation comments above.  This basically means
 * that we must hand the SSP pins back to the GPIO module before disabling
 * the SSP.
 *
 * In addition, to reduce power drain, we toggle the SFRM line once so
 * that the UDA_WS line is at logic 0.
 *
 * We can't clear ASSABET_BCR_CODEC_RST without knowing if the UCB1300 or
 * ADV7171 driver is still active.  If it is, then we still need to play
 * games, so we might as well leave ASSABET_BCR_CODEC_RST set.
 */
static void assabet_audio_shutdown(void *dummy)
{
	ASSABET_BCR_set(ASSABET_BCR_STEREO_LB | ASSABET_BCR_QMUTE |
			ASSABET_BCR_SPK_OFF);

	l3_close(&uda1341);

	GAFR &= ~(GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM);
	Ser4SSCR0 = 0;

#ifdef FIX_POWER_DRAIN
	GPSR = GPIO_SSP_SFRM;
	GPCR = GPIO_SSP_SFRM;
#endif

	/* disable the audio power */
	ASSABET_BCR_clear(ASSABET_BCR_AUDIO_ON);
}

static int assabet_audio_ioctl( struct inode *inode, struct file *file,
				uint cmd, ulong arg)
{
	long val;
	int ret = 0;

	/*
	 * These are platform dependent ioctls which are not handled by the
	 * generic sa1100-audio module.
	 */
	switch (cmd) {
	case SNDCTL_DSP_STEREO:
		ret = get_user(val, (int *) arg);
		if (ret)
			return ret;
		/* the UDA1341 is stereo only */
		ret = (val == 0) ? -EINVAL : 1;
		return put_user(ret, (int *) arg);

	case SNDCTL_DSP_CHANNELS:
	case SOUND_PCM_READ_CHANNELS:
		/* the UDA1341 is stereo only */
		return put_user(2, (long *) arg);

	case SNDCTL_DSP_SPEED:
		ret = get_user(val, (long *) arg);
		if (ret) break;
		assabet_set_samplerate(val);
		/* fall through */

	case SOUND_PCM_READ_RATE:
		return put_user(audio_samplerate, (long *) arg);

	case SNDCTL_DSP_SETFMT:
	case SNDCTL_DSP_GETFMTS:
		/* we can do signed 16-bit only */
		return put_user(AFMT_S16_LE, (long *) arg);

	default:
		/* Maybe this is meant for the mixer (As per OSS Docs) */
		return mixer_ioctl(inode, file, cmd, arg);
	}

	return ret;
}

static audio_stream_t output_stream, input_stream;

static audio_state_t audio_state = {
	output_stream:	&output_stream,
	output_dma:	DMA_Ser4SSPWr,
	output_id:	"Assabet UDA1341 out",
	input_stream:	&input_stream,
	input_dma:	DMA_Ser4SSPRd,
	input_id:	"Assabet UDA1341 in",
	need_tx_for_rx:	1,
	hw_init:	assabet_audio_init,
	hw_shutdown:	assabet_audio_shutdown,
	client_ioctl:	assabet_audio_ioctl,
	sem:		__MUTEX_INITIALIZER(audio_state.sem),
};

static int assabet_audio_open(struct inode *inode, struct file *file)
{
	return sa1100_audio_attach(inode, file, &audio_state);
}

/*
 * Missing fields of this structure will be patched with the call
 * to sa1100_audio_attach().
 */
static struct file_operations assabet_audio_fops = {
	open:		assabet_audio_open,
	owner:		THIS_MODULE
};


static int audio_dev_id, mixer_dev_id;

static int __init assabet_uda1341_init(void)
{
	int ret;

	if (!machine_is_assabet())
		return -ENODEV;

	ret = l3_attach_client(&uda1341, "l3-bit-sa1100-gpio", "uda1341");
	if (ret)
		goto out;

	/* register devices */
	audio_dev_id = register_sound_dsp(&assabet_audio_fops, -1);
	mixer_dev_id = register_sound_mixer(&assabet_mixer_fops, -1);

#ifdef FIX_POWER_DRAIN
	{
		unsigned long flags;
		local_irq_save(flags);
		ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
		GPSR = GPIO_SSP_SFRM;
		GPDR |= GPIO_SSP_SFRM;
		GPCR = GPIO_SSP_SFRM;
		local_irq_restore(flags);
	}
#endif

	printk(KERN_INFO "Assabet UDA1341 audio driver initialized\n");
	return 0;

release_l3:
	l3_detach_client(&uda1341);
out:
	return ret;
}

static void __exit assabet_uda1341_exit(void)
{
	unregister_sound_dsp(audio_dev_id);
	unregister_sound_mixer(mixer_dev_id);
	l3_detach_client(&uda1341);
}

module_init(assabet_uda1341_init);
module_exit(assabet_uda1341_exit);

MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("Glue audio driver for the SA1110 Assabet board & Philips UDA1341 codec.");

EXPORT_NO_SYMBOLS;
