123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- /* arch/arm/mach-msm/htc_acoustic_qsd.c
- *
- * 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/device.h>
- #include <linux/fs.h>
- #include <linux/module.h>
- #include <linux/miscdevice.h>
- #include <linux/mm.h>
- #include <linux/err.h>
- #include <linux/delay.h>
- #include <linux/kernel.h>
- #include <linux/uaccess.h>
- #include <linux/mutex.h>
- #include <linux/gpio.h>
- #include <mach/msm_smd.h>
- #include <mach/msm_rpcrouter.h>
- #include <mach/msm_iomap.h>
- #include <mach/htc_acoustic_qsd.h>
- #include <mach/msm_qdsp6_audio.h>
- #include "smd_private.h"
- #define ACOUSTIC_IOCTL_MAGIC 'p'
- #define ACOUSTIC_UPDATE_ADIE \
- _IOW(ACOUSTIC_IOCTL_MAGIC, 24, unsigned int)
- #define HTCACOUSTICPROG 0x30100003
- #define HTCACOUSTICVERS 0
- #define ONCRPC_ALLOC_ACOUSTIC_MEM_PROC (1)
- #define ONCRPC_UPDATE_ADIE_PROC (2)
- #define ONCRPC_ENABLE_AUX_PGA_LOOPBACK_PROC (3)
- #define ONCRPC_FORCE_HEADSET_SPEAKER_PROC (4)
- #define HTC_ACOUSTIC_TABLE_SIZE (0x20000)
- #define D(fmt, args...) printk(KERN_INFO "htc-acoustic: "fmt, ##args)
- #define E(fmt, args...) printk(KERN_ERR "htc-acoustic: "fmt, ##args)
- static uint32_t htc_acoustic_vir_addr;
- static struct msm_rpc_endpoint *endpoint;
- static struct mutex api_lock;
- static struct mutex rpc_connect_lock;
- static struct qsd_acoustic_ops *the_ops;
- void acoustic_register_ops(struct qsd_acoustic_ops *ops)
- {
- the_ops = ops;
- }
- static int is_rpc_connect(void)
- {
- mutex_lock(&rpc_connect_lock);
- if (endpoint == NULL) {
- endpoint = msm_rpc_connect(HTCACOUSTICPROG,
- HTCACOUSTICVERS, 0);
- if (IS_ERR(endpoint)) {
- pr_err("%s: init rpc failed! rc = %ld\n",
- __func__, PTR_ERR(endpoint));
- mutex_unlock(&rpc_connect_lock);
- return -1;
- }
- }
- mutex_unlock(&rpc_connect_lock);
- return 0;
- }
- int turn_mic_bias_on(int on)
- {
- D("%s called %d\n", __func__, on);
- if (the_ops->enable_mic_bias)
- the_ops->enable_mic_bias(on);
- return 0;
- }
- EXPORT_SYMBOL(turn_mic_bias_on);
- int force_headset_speaker_on(int enable)
- {
- struct speaker_headset_req {
- struct rpc_request_hdr hdr;
- uint32_t enable;
- } spkr_req;
- D("%s called %d\n", __func__, enable);
- if (is_rpc_connect() == -1)
- return -1;
- spkr_req.enable = cpu_to_be32(enable);
- return msm_rpc_call(endpoint,
- ONCRPC_FORCE_HEADSET_SPEAKER_PROC,
- &spkr_req, sizeof(spkr_req), 5 * HZ);
- }
- EXPORT_SYMBOL(force_headset_speaker_on);
- int enable_aux_loopback(uint32_t enable)
- {
- struct aux_loopback_req {
- struct rpc_request_hdr hdr;
- uint32_t enable;
- } aux_req;
- D("%s called %d\n", __func__, enable);
- if (is_rpc_connect() == -1)
- return -1;
- aux_req.enable = cpu_to_be32(enable);
- return msm_rpc_call(endpoint,
- ONCRPC_ENABLE_AUX_PGA_LOOPBACK_PROC,
- &aux_req, sizeof(aux_req), 5 * HZ);
- }
- EXPORT_SYMBOL(enable_aux_loopback);
- static int acoustic_mmap(struct file *file, struct vm_area_struct *vma)
- {
- unsigned long pgoff;
- int rc = -EINVAL;
- size_t size;
- D("mmap\n");
- mutex_lock(&api_lock);
- size = vma->vm_end - vma->vm_start;
- if (vma->vm_pgoff != 0) {
- E("mmap failed: page offset %lx\n", vma->vm_pgoff);
- goto done;
- }
- if (!htc_acoustic_vir_addr) {
- E("mmap failed: smem region not allocated\n");
- rc = -EIO;
- goto done;
- }
- pgoff = MSM_SHARED_RAM_PHYS +
- (htc_acoustic_vir_addr - (uint32_t)MSM_SHARED_RAM_BASE);
- pgoff = ((pgoff + 4095) & ~4095);
- htc_acoustic_vir_addr = ((htc_acoustic_vir_addr + 4095) & ~4095);
- if (pgoff <= 0) {
- E("pgoff wrong. %ld\n", pgoff);
- goto done;
- }
- if (size <= HTC_ACOUSTIC_TABLE_SIZE) {
- pgoff = pgoff >> PAGE_SHIFT;
- } else {
- E("size > HTC_ACOUSTIC_TABLE_SIZE %d\n", size);
- goto done;
- }
- vma->vm_flags |= VM_IO | VM_RESERVED;
- rc = io_remap_pfn_range(vma, vma->vm_start, pgoff,
- size, vma->vm_page_prot);
- if (rc < 0)
- E("mmap failed: remap error %d\n", rc);
- done: mutex_unlock(&api_lock);
- return rc;
- }
- static int acoustic_open(struct inode *inode, struct file *file)
- {
- int reply_value;
- int rc = -EIO;
- struct set_smem_req {
- struct rpc_request_hdr hdr;
- uint32_t size;
- } req_smem;
- struct set_smem_rep {
- struct rpc_reply_hdr hdr;
- int n;
- } rep_smem;
- D("open\n");
- mutex_lock(&api_lock);
- if (!htc_acoustic_vir_addr) {
- if (is_rpc_connect() == -1)
- goto done;
- req_smem.size = cpu_to_be32(HTC_ACOUSTIC_TABLE_SIZE);
- rc = msm_rpc_call_reply(endpoint,
- ONCRPC_ALLOC_ACOUSTIC_MEM_PROC,
- &req_smem, sizeof(req_smem),
- &rep_smem, sizeof(rep_smem),
- 5 * HZ);
- reply_value = be32_to_cpu(rep_smem.n);
- if (reply_value != 0 || rc < 0) {
- E("open failed: ALLOC_ACOUSTIC_MEM_PROC error %d.\n",
- rc);
- goto done;
- }
- htc_acoustic_vir_addr =
- (uint32_t)smem_alloc(SMEM_ID_VENDOR1,
- HTC_ACOUSTIC_TABLE_SIZE);
- if (!htc_acoustic_vir_addr) {
- E("open failed: smem_alloc error\n");
- goto done;
- }
- }
- rc = 0;
- done:
- mutex_unlock(&api_lock);
- return rc;
- }
- static int acoustic_release(struct inode *inode, struct file *file)
- {
- D("release\n");
- return 0;
- }
- static long acoustic_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
- {
- int rc, reply_value;
- D("ioctl\n");
- mutex_lock(&api_lock);
- switch (cmd) {
- case ACOUSTIC_UPDATE_ADIE: {
- struct update_adie_req {
- struct rpc_request_hdr hdr;
- int id;
- } adie_req;
- struct update_adie_rep {
- struct rpc_reply_hdr hdr;
- int ret;
- } adie_rep;
- D("ioctl: ACOUSTIC_UPDATE_ADIE called %d.\n", current->pid);
- adie_req.id = cpu_to_be32(-1); /* update all codecs */
- rc = msm_rpc_call_reply(endpoint,
- ONCRPC_UPDATE_ADIE_PROC, &adie_req,
- sizeof(adie_req), &adie_rep,
- sizeof(adie_rep), 5 * HZ);
- reply_value = be32_to_cpu(adie_rep.ret);
- if (reply_value != 0 || rc < 0) {
- E("ioctl failed: ONCRPC_UPDATE_ADIE_PROC "\
- "error %d.\n", rc);
- if (rc >= 0)
- rc = -EIO;
- break;
- }
- D("ioctl: ONCRPC_UPDATE_ADIE_PROC success.\n");
- break;
- }
- default:
- E("ioctl: invalid command\n");
- rc = -EINVAL;
- }
- mutex_unlock(&api_lock);
- return rc;
- }
- struct rpc_set_uplink_mute_args {
- int mute;
- };
- static struct file_operations acoustic_fops = {
- .owner = THIS_MODULE,
- .open = acoustic_open,
- .release = acoustic_release,
- .mmap = acoustic_mmap,
- .unlocked_ioctl = acoustic_ioctl,
- };
- static struct miscdevice acoustic_misc = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "htc-acoustic",
- .fops = &acoustic_fops,
- };
- static int __init acoustic_init(void)
- {
- mutex_init(&api_lock);
- mutex_init(&rpc_connect_lock);
- return misc_register(&acoustic_misc);
- }
- static void __exit acoustic_exit(void)
- {
- misc_deregister(&acoustic_misc);
- }
- module_init(acoustic_init);
- module_exit(acoustic_exit);
|