From bd3ee16444d6e35e6f2837521c2508fb05dc436d Mon Sep 17 00:00:00 2001 From: Chris Fries Date: Fri, 8 Oct 2010 13:54:28 -0500 Subject: [PATCH] [ARM] tegra: i2s: Add I2S ioctl for setting bit format Added an ioctl to set the bit format for I2S between "DSP"/"PCM" mode and normal mode (set by board file) Signed-off-by: Iliyan Malchev --- arch/arm/mach-tegra/tegra_i2s_audio.c | 66 +++++++++++++++++++++++++++ include/linux/tegra_audio.h | 7 +++ 2 files changed, 73 insertions(+) diff --git a/arch/arm/mach-tegra/tegra_i2s_audio.c b/arch/arm/mach-tegra/tegra_i2s_audio.c index a70f769b61cf..6f3295d62bf2 100644 --- a/arch/arm/mach-tegra/tegra_i2s_audio.c +++ b/arch/arm/mach-tegra/tegra_i2s_audio.c @@ -126,6 +126,10 @@ struct audio_driver_state { struct miscdevice misc_in; struct miscdevice misc_in_ctl; struct audio_stream in; + + /* Control for whole I2S (Data format, etc.) */ + struct miscdevice misc_ctl; + unsigned int bit_format; }; static inline int buf_size(struct audio_stream *s) @@ -183,6 +187,17 @@ static inline struct audio_driver_state *ads_from_misc_in_ctl( return ads; } +static inline struct audio_driver_state *ads_from_misc_ctl( + struct file *file) +{ + struct miscdevice *m = file->private_data; + struct audio_driver_state *ads = + container_of(m, struct audio_driver_state, + misc_ctl); + BUG_ON(!ads); + return ads; +} + static inline struct audio_driver_state *ads_from_out( struct audio_stream *aos) { @@ -1313,6 +1328,44 @@ static long tegra_audio_out_ioctl(struct file *file, return rc; } +static long tegra_audio_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + int rc = 0; + struct audio_driver_state *ads = ads_from_misc_ctl(file); + unsigned int mode; + + switch (cmd) { + case TEGRA_AUDIO_SET_BIT_FORMAT: + if (copy_from_user(&mode, (const void __user *)arg, + sizeof(mode))) { + rc = -EFAULT; + break; + } + switch(mode) { + case TEGRA_AUDIO_BIT_FORMAT_DEFAULT: + i2s_set_bit_format(ads->i2s_base, ads->pdata->mode); + ads->bit_format = mode; + case TEGRA_AUDIO_BIT_FORMAT_DSP: + i2s_set_bit_format(ads->i2s_base, I2S_BIT_FORMAT_DSP); + ads->bit_format = mode; + break; + default: + pr_err("%s: Invald PCM mode %d", __func__, mode); + rc = -EINVAL; + break; + } + break; + case TEGRA_AUDIO_GET_BIT_FORMAT: + if (copy_to_user((void __user *)arg, &ads->bit_format, + sizeof(mode))) { + rc = -EFAULT; + } + break; + } + return rc; +} + static long tegra_audio_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -1795,6 +1848,13 @@ static const struct file_operations tegra_audio_in_ctl_fops = { .unlocked_ioctl = tegra_audio_in_ioctl, }; +static const struct file_operations tegra_audio_ctl_fops = { + .owner = THIS_MODULE, + .open = tegra_audio_ctl_open, + .release = tegra_audio_ctl_release, + .unlocked_ioctl = tegra_audio_ioctl, +}; + static int init_stream_buffer(struct audio_stream *s, struct tegra_audio_buf_config *cfg, unsigned padding) @@ -2221,6 +2281,12 @@ static int tegra_audio_probe(struct platform_device *pdev) if (rc < 0) return rc; + rc = setup_misc_device(&state->misc_ctl, + &tegra_audio_ctl_fops, + "audio%d_ctl", state->pdev->id); + if (rc < 0) + return rc; + state->using_dma = state->pdata->dma_on; if (!state->using_dma) sound_ops = &pio_sound_ops; diff --git a/include/linux/tegra_audio.h b/include/linux/tegra_audio.h index 07192b28a936..b97b640819a0 100644 --- a/include/linux/tegra_audio.h +++ b/include/linux/tegra_audio.h @@ -72,4 +72,11 @@ struct tegra_audio_out_preload { #define TEGRA_AUDIO_OUT_PRELOAD_FIFO _IOWR(TEGRA_AUDIO_MAGIC, 10, \ struct tegra_audio_out_preload *) +#define TEGRA_AUDIO_BIT_FORMAT_DEFAULT 0 +#define TEGRA_AUDIO_BIT_FORMAT_DSP 1 +#define TEGRA_AUDIO_SET_BIT_FORMAT _IOW(TEGRA_AUDIO_MAGIC, 11, \ + unsigned int *) +#define TEGRA_AUDIO_GET_BIT_FORMAT _IOR(TEGRA_AUDIO_MAGIC, 12, \ + unsigned int *) + #endif/*_CPCAP_AUDIO_H*/ -- 2.34.1