This reverts commit b739bce629.
Conflicts:
	arch/arm/configs/htcleo_defconfig
	arch/arm/mach-msm/Makefile
	arch/arm/mach-msm/board-htcleo.c
		
	
		
			
				
	
	
		
			216 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			216 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* arch/arm/mach-msm/qdsp6/audio_ctrl.c
 | 
						|
 *
 | 
						|
 * Copyright (C) 2009 Google, Inc.
 | 
						|
 * Copyright (C) 2009 HTC Corporation
 | 
						|
 *
 | 
						|
 * This software is licensed under the terms of the GNU General Public
 | 
						|
 * License version 2, as published by the Free Software Foundation, and
 | 
						|
 * may be copied, distributed, and modified under those terms.
 | 
						|
 *
 | 
						|
 * 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.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include <linux/fs.h>
 | 
						|
#include <linux/module.h>
 | 
						|
#include <linux/miscdevice.h>
 | 
						|
#include <linux/uaccess.h>
 | 
						|
#include <linux/msm_audio.h>
 | 
						|
 | 
						|
#include <mach/msm_qdsp6_audio.h>
 | 
						|
#include <mach/htc_acoustic_qsd.h>
 | 
						|
 | 
						|
#define BUFSZ (0)
 | 
						|
 | 
						|
static DEFINE_MUTEX(voice_lock);
 | 
						|
static DEFINE_MUTEX(fm_lock);
 | 
						|
static int voice_started;
 | 
						|
static int fm_started;
 | 
						|
 | 
						|
static struct audio_client *voc_tx_clnt;
 | 
						|
static struct audio_client *voc_rx_clnt;
 | 
						|
static struct audio_client *fm_clnt;
 | 
						|
 | 
						|
static int q6_voice_start(uint32_t rx_acdb_id, uint32_t tx_acdb_id)
 | 
						|
{
 | 
						|
	int rc = 0;
 | 
						|
 | 
						|
	mutex_lock(&voice_lock);
 | 
						|
 | 
						|
	if (voice_started) {
 | 
						|
		pr_err("voice: busy\n");
 | 
						|
		rc = -EBUSY;
 | 
						|
		goto done;
 | 
						|
	}
 | 
						|
 | 
						|
	voc_rx_clnt = q6voice_open(AUDIO_FLAG_WRITE, rx_acdb_id);
 | 
						|
	if (!voc_rx_clnt) {
 | 
						|
		pr_err("voice: open voice rx failed.\n");
 | 
						|
		rc = -ENOMEM;
 | 
						|
		goto done;
 | 
						|
	}
 | 
						|
 | 
						|
	voc_tx_clnt = q6voice_open(AUDIO_FLAG_READ, tx_acdb_id);
 | 
						|
	if (!voc_tx_clnt) {
 | 
						|
		pr_err("voice: open voice tx failed.\n");
 | 
						|
		q6voice_close(voc_rx_clnt);
 | 
						|
		rc = -ENOMEM;
 | 
						|
	}
 | 
						|
 | 
						|
	voice_started = 1;
 | 
						|
done:
 | 
						|
	mutex_unlock(&voice_lock);
 | 
						|
	return rc;
 | 
						|
}
 | 
						|
 | 
						|
static int q6_voice_stop(void)
 | 
						|
{
 | 
						|
	mutex_lock(&voice_lock);
 | 
						|
	if (voice_started) {
 | 
						|
		q6voice_close(voc_tx_clnt);
 | 
						|
		q6voice_close(voc_rx_clnt);
 | 
						|
		voice_started = 0;
 | 
						|
	}
 | 
						|
	mutex_unlock(&voice_lock);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int q6_fm_start(void)
 | 
						|
{
 | 
						|
	int rc = 0;
 | 
						|
 | 
						|
	mutex_lock(&fm_lock);
 | 
						|
 | 
						|
	if (fm_started) {
 | 
						|
		pr_err("fm: busy\n");
 | 
						|
		rc = -EBUSY;
 | 
						|
		goto done;
 | 
						|
	}
 | 
						|
 | 
						|
	fm_clnt = q6fm_open();
 | 
						|
	if (!fm_clnt) {
 | 
						|
		pr_err("fm: open failed.\n");
 | 
						|
		rc = -ENOMEM;
 | 
						|
		goto done;
 | 
						|
	}
 | 
						|
 | 
						|
	fm_started = 1;
 | 
						|
done:
 | 
						|
	mutex_unlock(&fm_lock);
 | 
						|
	return rc;
 | 
						|
}
 | 
						|
 | 
						|
static int q6_fm_stop(void)
 | 
						|
{
 | 
						|
	mutex_lock(&fm_lock);
 | 
						|
	if (fm_started) {
 | 
						|
		q6fm_close(fm_clnt);
 | 
						|
		fm_started = 0;
 | 
						|
	}
 | 
						|
	mutex_unlock(&fm_lock);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int q6_open(struct inode *inode, struct file *file)
 | 
						|
{
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int q6_ioctl(struct inode *inode, struct file *file,
 | 
						|
		    unsigned int cmd, unsigned long arg)
 | 
						|
{
 | 
						|
	int rc;
 | 
						|
	uint32_t n;
 | 
						|
	uint32_t id[2];
 | 
						|
	char filename[64];
 | 
						|
 | 
						|
	switch (cmd) {
 | 
						|
	case AUDIO_SWITCH_DEVICE:
 | 
						|
		rc = copy_from_user(&id, (void *)arg, sizeof(id));
 | 
						|
		if (!rc)
 | 
						|
			rc = q6audio_do_routing(id[0], id[1]);
 | 
						|
		break;
 | 
						|
	case AUDIO_SET_VOLUME:
 | 
						|
		rc = copy_from_user(&n, (void *)arg, sizeof(n));
 | 
						|
		if (!rc)
 | 
						|
			rc = q6audio_set_rx_volume(n);
 | 
						|
		break;
 | 
						|
	case AUDIO_SET_MUTE:
 | 
						|
		rc = copy_from_user(&n, (void *)arg, sizeof(n));
 | 
						|
		if (!rc)
 | 
						|
			rc = q6audio_set_tx_mute(n);
 | 
						|
		break;
 | 
						|
	case AUDIO_UPDATE_ACDB:
 | 
						|
		rc = copy_from_user(&id, (void *)arg, sizeof(id));
 | 
						|
		if (!rc)
 | 
						|
			rc = q6audio_update_acdb(id[0], id[1]);
 | 
						|
		break;
 | 
						|
	case AUDIO_START_VOICE:
 | 
						|
		if (arg == 0) {
 | 
						|
			id[0] = id[1] = 0;
 | 
						|
		} else if (copy_from_user(&id, (void*) arg, sizeof(id))) {
 | 
						|
			pr_info("voice: copy acdb_id from user failed\n");
 | 
						|
			rc = -EFAULT;
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		rc = q6_voice_start(id[0], id[1]);
 | 
						|
		break;
 | 
						|
	case AUDIO_STOP_VOICE:
 | 
						|
		rc = q6_voice_stop();
 | 
						|
		break;
 | 
						|
	case AUDIO_START_FM:
 | 
						|
		rc = q6_fm_start();
 | 
						|
		break;
 | 
						|
	case AUDIO_STOP_FM:
 | 
						|
		rc = q6_fm_stop();
 | 
						|
		break;
 | 
						|
	case AUDIO_REINIT_ACDB:
 | 
						|
		rc = copy_from_user(&filename, (void *)arg, sizeof(filename));
 | 
						|
		if (!rc)
 | 
						|
			rc = q6audio_reinit_acdb(filename);
 | 
						|
		break;
 | 
						|
	case AUDIO_ENABLE_AUXPGA_LOOPBACK: {
 | 
						|
		uint32_t enable;
 | 
						|
		if (copy_from_user(&enable, (void*) arg, sizeof(enable))) {
 | 
						|
			rc = -EFAULT;
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		rc = enable_aux_loopback(enable);
 | 
						|
		break;
 | 
						|
	}
 | 
						|
	default:
 | 
						|
		rc = -EINVAL;
 | 
						|
	}
 | 
						|
 | 
						|
	return rc;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int q6_release(struct inode *inode, struct file *file)
 | 
						|
{
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static struct file_operations q6_dev_fops = {
 | 
						|
	.owner		= THIS_MODULE,
 | 
						|
	.open		= q6_open,
 | 
						|
	.ioctl		= q6_ioctl,
 | 
						|
	.release	= q6_release,
 | 
						|
};
 | 
						|
 | 
						|
struct miscdevice q6_control_device = {
 | 
						|
	.minor	= MISC_DYNAMIC_MINOR,
 | 
						|
	.name	= "msm_audio_ctl",
 | 
						|
	.fops	= &q6_dev_fops,
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
static int __init q6_audio_ctl_init(void) {
 | 
						|
	return misc_register(&q6_control_device);
 | 
						|
}
 | 
						|
 | 
						|
device_initcall(q6_audio_ctl_init);
 |