diff options
Diffstat (limited to 'ANDROID_3.4.5/sound/soc/wmt/wmt_hwdep.c')
-rwxr-xr-x | ANDROID_3.4.5/sound/soc/wmt/wmt_hwdep.c | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/ANDROID_3.4.5/sound/soc/wmt/wmt_hwdep.c b/ANDROID_3.4.5/sound/soc/wmt/wmt_hwdep.c new file mode 100755 index 00000000..8a6d374e --- /dev/null +++ b/ANDROID_3.4.5/sound/soc/wmt/wmt_hwdep.c @@ -0,0 +1,259 @@ +/*++ + * linux/sound/soc/wmt/wmt_hwdep.c + * WonderMedia I2S audio driver for ALSA + * + * Copyright c 2010 WonderMedia Technologies, Inc. + * + * 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#include <sound/soc.h> +#include <sound/jack.h> + +#include <asm/mach-types.h> +#include <mach/gpio.h> + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/device.h> + +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/soc-dapm.h> +#include <sound/hwdep.h> + +#include <asm/mach-types.h> +#include <mach/hardware.h> + +#include "wmt_hwdep.h" +#include "wmt-pcm.h" + +int WFD_flag = 0; +static int gmode = 2; +static char gstring[3] = "LR"; + +static char gSpdHdm[6] = "BOTH"; +static int gSpHd = 6; + +extern void wmt_i2s_dac0_ctrl(int HDMI_audio_enable); + +static int wmt_hwdep_open(struct snd_hwdep *hw, struct file *file) +{ + if ((file->f_flags & O_RDWR) && (WFD_flag)) { + return -EBUSY; + } + else if (file->f_flags & O_SYNC) { + WFD_flag = 1; + } + return 0; +} + +static int wmt_hwdep_release(struct snd_hwdep *hw, struct file *file) +{ + WFD_flag = 0; + return 0; +} + +static int wmt_hwdep_mmap(struct snd_hwdep *hw, struct file *file, struct vm_area_struct *vma) +{ + vma->vm_flags |= VM_IO | VM_RESERVED; + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + if (remap_pfn_range(vma, vma->vm_start, (vma->vm_pgoff), + vma->vm_end - vma->vm_start, vma->vm_page_prot)) { + printk("*E* remap page range failed: vm_pgoff=0x%x ", (unsigned int)vma->vm_pgoff); + return -EAGAIN; + } + return 0; +} + +static int wmt_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg) +{ + int *value; + WFDStrmInfo_t *info; + struct wmt_soc_vt1603_info vt1603_info; + int ret = 0; + + switch (cmd) { + case WMT_SOC_IOCTL_HDMI: + value = (int __user *)arg; + + if (*value > 1) { + printk("Not supported status for HDMI Audio %d", *value); + return 0; + } + wmt_i2s_dac0_ctrl(*value); + return 0; + + case WMT_SOC_IOCTL_WFD_START: + wmt_pcm_wfd_start(); + return copy_to_user( (void *)arg, (const void __user *) wmt_pcm_wfd_get_buf(), sizeof(unsigned int)); + + case WMT_SOC_IOCTL_GET_STRM: + info = (WFDStrmInfo_t *)wmt_pcm_wfd_get_strm((WFDStrmInfo_t *)arg); + return __put_user((int)info, (unsigned int __user *) arg); + + case WMT_SOC_IOCTL_WFD_STOP: + wmt_pcm_wfd_stop(); + return 0; + + case WMT_SOC_IOCTL_VT1603_RD: + ret = copy_from_user(&vt1603_info, (void __user *)arg, sizeof(vt1603_info)); + + if (ret == 0) { + vt1603_info.reg_value = vt1603_hwdep_ioctl(0, vt1603_info.reg_offset, vt1603_info.reg_value); + printk("<<<%s read reg 0x%x val 0x%x\n", __FUNCTION__, vt1603_info.reg_offset, vt1603_info.reg_value); + ret = copy_to_user((void __user *)arg, &vt1603_info, sizeof(vt1603_info)); + } + return ret; + case WMT_SOC_IOCTL_VT1603_WR: + ret = copy_from_user(&vt1603_info, (void __user *)arg, sizeof(vt1603_info)); + printk("<<<%s write reg 0x%x val 0x%x\n", __FUNCTION__, vt1603_info.reg_offset, vt1603_info.reg_value); + if (ret == 0) + vt1603_hwdep_ioctl(1, vt1603_info.reg_offset, vt1603_info.reg_value); + return ret; + + case WMT_SOC_IOCTL_CH_SEL: + value = (int __user *)arg; + + if (*value > 2) { + printk("Not supported for CH select %d", *value); + return 0; + } + wmt_i2s_ch_sel(*value); + return 0; + + default: + break; + } + + printk("Not supported ioctl for WMT-HWDEP"); + return -ENOIOCTLCMD; +} + +static long wmt_hwdep_write(struct snd_hwdep *hw, const char __user *buf, + long count, loff_t *offset) +{ + char string[3]; + //int mode; + memset(string, 0, sizeof(string)); + copy_from_user(&string, buf, sizeof(string)); + printk("<<<%s %s\n", __FUNCTION__, string); + if (!memcmp(string, "LL", 2)) { + gmode = 0; + } + else if (!memcmp(string, "RR", 2)) { + gmode = 1; + } + else if (!memcmp(string, "LR", 2)) { + gmode = 2; + } + else { + printk("Not supported for CH select"); + return count; + } + + memset(gstring, 0, sizeof(gstring)); + strncpy(gstring, string, sizeof(string)); + wmt_i2s_ch_sel(gmode); + return count; +} + +static long wmt_hwdep_read(struct snd_hwdep *hw, char __user *buf, + long count, loff_t *offset) +{ + int len = 0; + printk("%s string %s --> mode %d\n", __FUNCTION__, gstring, gmode); + len = copy_to_user(buf, gstring, sizeof(gstring)); + + return sizeof(gstring); +} + +static long wmt_hwdep_write_1(struct snd_hwdep *hw, const char __user *buf, + long count, loff_t *offset) +{ + char string[5]; + //int mode; + + copy_from_user(&string, buf, sizeof(string)); + printk("<<<%s %s\n", __FUNCTION__, string); + if (!memcmp(string, "NONE", 4)) { + gSpHd = 3; + } + else if (!memcmp(string, "HDMI", 4)) { + gSpHd = 4; + } + else if (!memcmp(string, "SPDIF", 5)) { + gSpHd = 5; + } + else if (!memcmp(string, "BOTH", 4)) { + gSpHd = 6; + } + else { + printk("Not supported for SPDIF/HDMI switch"); + return count; + } + + memset(gSpdHdm, 0, sizeof(gSpdHdm)); + strncpy(gSpdHdm, string, sizeof(string)); + + wmt_i2s_ch_sel(gSpHd); + return count; +} + + +static long wmt_hwdep_read_1(struct snd_hwdep *hw, char __user *buf, + long count, loff_t *offset) +{ + int len = 0; + printk("%s string %s --> mode %d\n", __FUNCTION__, gSpdHdm, gSpHd); + len = copy_to_user(buf, gSpdHdm, sizeof(gSpdHdm)); + + return sizeof(gstring); +} + +void wmt_soc_hwdep_new(struct snd_soc_codec *codec) +{ + struct snd_hwdep *hwdep; + struct snd_hwdep *hwdep_1; + if (snd_hwdep_new(codec->card->snd_card, "WMT-HWDEP", 0, &hwdep) < 0) { + printk("create WMT-HWDEP_0 fail"); + return; + } + + sprintf(hwdep->name, "WMT-HWDEP %d", 0); + + hwdep->iface = SNDRV_HWDEP_IFACE_WMT; + hwdep->ops.open = wmt_hwdep_open; + hwdep->ops.ioctl = wmt_hwdep_ioctl; + hwdep->ops.release = wmt_hwdep_release; + hwdep->ops.mmap = wmt_hwdep_mmap; + hwdep->ops.write = wmt_hwdep_write; + hwdep->ops.read = wmt_hwdep_read; + + if (snd_hwdep_new(codec->card->snd_card, "WMT-HWDEP", 1, &hwdep_1) < 0) { + printk("create WMT-HWDEP_1 fail"); + return; + } + + sprintf(hwdep_1->name, "WMT-HWDEP %d", 1); + printk("create %s success", hwdep_1->name); + + hwdep_1->iface = SNDRV_HWDEP_IFACE_WMT; + hwdep_1->ops.write = wmt_hwdep_write_1; + hwdep_1->ops.read = wmt_hwdep_read_1; +} + |