/*
* Audio support for PS3
* Copyright (C) 2007 Sony Computer Entertainment Inc.
* All rights reserved.
* Copyright 2006, 2007 Sony Corporation
*
* 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 Licence.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <sound/driver.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/asound.h>
#include <sound/memalloc.h>
#include <sound/pcm_params.h>
#include <sound/control.h>
#include <linux/dmapool.h>
#include <linux/dma-mapping.h>
#include <asm/firmware.h>
#include <asm/dma.h>
#include <asm/lv1call.h>
#include <asm/ps3.h>
#include <asm/ps3av.h>
#include "snd_ps3_reg.h"
#include "snd_ps3.h"
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("PS3 sound driver");
MODULE_AUTHOR("Sony Computer Entertainment Inc.");
/* module entries */
static int __init snd_ps3_init(void);
static void __exit snd_ps3_exit(void);
/* ALSA snd driver ops */
static int snd_ps3_pcm_open(struct snd_pcm_substream *substream);
static int snd_ps3_pcm_close(struct snd_pcm_substream *substream);
static int snd_ps3_pcm_prepare(struct snd_pcm_substream *substream);
static int snd_ps3_pcm_trigger(struct snd_pcm_substream *substream,
int cmd);
static snd_pcm_uframes_t snd_ps3_pcm_pointer(struct snd_pcm_substream
*substream);
static int snd_ps3_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params);
static int snd_ps3_pcm_hw_free(struct snd_pcm_substream *substream);
/* ps3_system_bus_driver entries */
static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev);
static int snd_ps3_driver_remove(struct ps3_system_bus_device *dev);
/* address setup */
static int snd_ps3_map_mmio(void);
static void snd_ps3_unmap_mmio(void);
static int snd_ps3_allocate_irq(void);
static void snd_ps3_free_irq(void);
static void snd_ps3_audio_set_base_addr(uint64_t ioaddr_start);
/* interrupt handler */
static irqreturn_t snd_ps3_interrupt(int irq, void *dev_id);
/* set sampling rate/format */
static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream);
/* take effect parameter change */
static int snd_ps3_change_avsetting(struct snd_ps3_card_info *card);
/* initialize avsetting and take it effect */
static int snd_ps3_init_avsetting(struct snd_ps3_card_info *card);
/* setup dma */
static int snd_ps3_program_dma(struct snd_ps3_card_info *card,
enum snd_ps3_dma_filltype filltype);
static void snd_ps3_wait_for_dma_stop(struct snd_ps3_card_info *card);
static dma_addr_t v_to_bus(struct snd_ps3_card_info *, void *vaddr, int ch);
module_init(snd_ps3_init);
module_exit(snd_ps3_exit);
/*
* global
*/
static struct snd_ps3_card_info the_card;
static int snd_ps3_start_delay = CONFIG_SND_PS3_DEFAULT_START_DELAY;
module_param_named(start_delay, snd_ps3_start_delay, uint, 0644);
MODULE_PARM_DESC(start_delay, "time to insert silent data in milisec");
static int index = SNDRV_DEFAULT_IDX1;
static char *id = SNDRV_DEFAULT_STR1;
module_param(index, int, 0444);
MODULE_PARM_DESC(index, "Index value for PS3 soundchip.");
module_param(id, charp, 0444);
MODULE_PARM_DESC(id, "ID string for PS3 soundchip.");
/*
* PS3 audio register access
*/
static inline u32 read_reg(unsigned int reg)
{
return in_be32(the_card.mapped_mmio_vaddr + reg);
}
static inline void write_reg(unsigned int reg, u32 val)
{
out_be32(the_card.mapped_mmio_vaddr + reg, val);
}
static inline void update_reg(unsigned int reg, u32 or_val)
{
u32 newval = read_reg(reg) |