/*++
* 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 .
*
* WonderMedia Technologies, Inc.
* 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
--*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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;
}