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);
 |