summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Fries <C.Fries@motorola.com>2010-10-08 13:54:28 -0500
committerIliyan Malchev <malchev@google.com>2010-10-08 15:41:54 -0700
commitbd3ee16444d6e35e6f2837521c2508fb05dc436d (patch)
tree3140f4ce4afbe883d3e0e1dd6d75b44ed2024fb8
parentaee8fd4a24840c8336bba9ad3f992a1083e68897 (diff)
[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 <malchev@google.com>
-rw-r--r--arch/arm/mach-tegra/tegra_i2s_audio.c66
-rw-r--r--include/linux/tegra_audio.h7
2 files changed, 73 insertions, 0 deletions
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*/