Exemplo n.º 1
0
static int vocpcm_open(struct inode *inode, struct file *file)
{
    struct voc_rpc *voc_rpc = &the_voc_proc;
    struct voc_ctxt *ctxt = voc_minor_to_ctxt(MINOR(inode->i_rdev));
    int rc = 0;

    if (!ctxt) {
        pr_err("unknown voc misc %d\n", MINOR(inode->i_rdev));
        return -ENODEV;
    }

    mutex_lock(&voc_rpc->lock);
    if (voc_rpc->inited == 0) {
        voc_rpc->ept = create_rpc_connect(RPC_SND_PROG, RPC_SND_VERS,
                                          MSM_RPC_UNINTERRUPTIBLE |
                                          MSM_RPC_ENABLE_RECEIVE);
        if (IS_ERR(voc_rpc->ept)) {
            rc = PTR_ERR(voc_rpc->ept);
            voc_rpc->ept = NULL;
            pr_err("vocpcm: failed to connect snd svc\n");
            return rc;
        }

        voc_rpc->task = create_snd_rpc_kthread();
        if (IS_ERR(voc_rpc->task)) {
            rc = PTR_ERR(voc_rpc->task);
            voc_rpc->task = NULL;
            msm_rpc_close(voc_rpc->ept);
            voc_rpc->ept = NULL;
            return rc;
        }
        voc_rpc->inited = 1;
    }
    mutex_unlock(&voc_rpc->lock);

    mutex_lock(&ctxt->lock);
    if (ctxt->opened) {
        pr_err("vocpcm already opened.\n");
        rc = -EBUSY;
        goto err;
    }

    file->private_data = ctxt;
    ctxt->head = 0;
    ctxt->tail = 0;
    ctxt->client = 0;

    memset(ctxt->buf[0].data, 0, sizeof(ctxt->buf[0].data));
    memset(ctxt->buf[1].data, 0, sizeof(ctxt->buf[1].data));
    ctxt->buf[0].index = 0;
    ctxt->buf[1].index = 0;
    ctxt->opened = 1;
    ctxt->count = 0;
    ctxt->s_ptr = 0;
    ctxt->final_input = 0;

err:
    mutex_unlock(&ctxt->lock);
    return rc;
}
Exemplo n.º 2
0
static int msm_fb_lcdc_config(int on)
{
	int rc = 0;
	struct rpc_request_hdr hdr;

	if (on)
		pr_info("lcdc config\n");
	else
		pr_info("lcdc un-config\n");

	lcdc_ep = msm_rpc_connect_compatible(LCDC_API_PROG, LCDC_API_VERS, 0);
	if (IS_ERR(lcdc_ep)) {
		printk(KERN_ERR "%s: msm_rpc_connect failed! rc = %ld\n",
			__func__, PTR_ERR(lcdc_ep));
		return -EINVAL;
	}

	rc = msm_rpc_call(lcdc_ep,
				(on) ? LCDC_CONFIG_PROC : LCDC_UN_CONFIG_PROC,
				&hdr, sizeof(hdr),
				5 * HZ);
	if (rc)
		printk(KERN_ERR
			"%s: msm_rpc_call failed! rc = %d\n", __func__, rc);

	msm_rpc_close(lcdc_ep);
	return rc;
}
Exemplo n.º 3
0
void msm_adsp_put(struct msm_adsp_module *module)
{
	unsigned long flags;

	mutex_lock(&module->lock);
	if (--module->open_count == 0 && module->clk)
		clk_disable(module->clk);
	if (module->ops) {
		pr_info("adsp: closing module %s\n", module->name);

		/* lock to ensure a dsp event cannot be delivered
		 * during or after removal of the ops and driver_data
		 */
		spin_lock_irqsave(&adsp_cmd_lock, flags);
		module->ops = NULL;
		module->driver_data = NULL;
		spin_unlock_irqrestore(&adsp_cmd_lock, flags);

		if (module->state != ADSP_STATE_DISABLED) {
			pr_info("adsp: disabling module %s\n", module->name);
			msm_adsp_disable_locked(module);
		}

		msm_rpc_close(module->rpc_client);
		module->rpc_client = 0;
		if (--adsp_open_count == 0) {
			disable_irq(INT_ADSP);
			allow_suspend();
			pr_info("adsp: disable interrupt\n");
		}
	} else {
		pr_info("adsp: module %s is already closed\n", module->name);
	}
	mutex_unlock(&module->lock);
}
Exemplo n.º 4
0
int __init rpc_clkrgm_sec(uint32_t proc, uint32_t d)
{
	struct msm_rpc_endpoint *mmoc_ep;
	int rc;
	struct mmoc_req {
		struct rpc_request_hdr hdr;
		uint32_t data[1];
	} req;

	printk(KERN_INFO "%s: proc: %02x data: %02x\n", __func__, proc, d);
	mutex_lock(&mmoc_mutex);

	req.data[0] = cpu_to_be32(d);

	mmoc_ep = msm_rpc_connect(0x3000000f, 0, 0);
	if (IS_ERR(mmoc_ep)) {
		printk(KERN_ERR "%s: init rpc failed! error: %ld\n",
				__func__, PTR_ERR(mmoc_ep));
		goto close;
	}
	rc = msm_rpc_call(mmoc_ep, /*proc*/ proc,
			&req, sizeof(req), 5 * HZ);
	if (rc < 0)
		printk(KERN_ERR "%s: rpc call failed! (%d)\n", __func__, rc);

close:
	msm_rpc_close(mmoc_ep);
	mutex_unlock(&mmoc_mutex);
	printk(KERN_INFO "%s: exiting\n", __func__);
	return rc;
}
Exemplo n.º 5
0
static int msm_fb_pm_vid_en(int on)
{
        int rc = 0;
        struct msm_fb_pm_vid_en_req {
                struct rpc_request_hdr hdr;
                uint32_t on;
        } req;
        
        pm_vid_en_ep = msm_rpc_connect(PM_VID_EN_API_PROG,
                                        PM_VID_EN_API_VERS, 0);
        if (IS_ERR(pm_vid_en_ep)) {
                printk(KERN_ERR "%s: msm_rpc_connect failed! rc = %ld\n",
                        __func__, PTR_ERR(pm_vid_en_ep));
                return -EINVAL;
        }

        req.on = cpu_to_be32(on);
        rc = msm_rpc_call(pm_vid_en_ep,
                        PM_VID_EN_CONFIG_PROC,
                        &req, sizeof(req),
                        5 * HZ);
        if (rc)
                printk(KERN_ERR
                        "%s: msm_rpc_call failed! rc = %d\n", __func__, rc);
                
        msm_rpc_close(pm_vid_en_ep);
        return rc;
} 
Exemplo n.º 6
0
int __init rpc_adsprtosatom(uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4)
{
	struct msm_rpc_endpoint *mmoc_ep;
	int rc;
	struct mmoc_req {
		struct rpc_request_hdr hdr;
		uint32_t data[4];
	} req;

	printk(KERN_INFO "%s\n", __func__);
	mutex_lock(&mmoc_mutex);

	req.data[0] = cpu_to_be32(d1);
	req.data[1] = cpu_to_be32(d2);
	req.data[2] = cpu_to_be32(d3);
	req.data[3] = cpu_to_be32(d4);

	mmoc_ep = msm_rpc_connect(0x3000000a, 0, 0);
	if (IS_ERR(mmoc_ep)) {
		printk(KERN_ERR "%s: init rpc failed! error: %ld\n",
				__func__, PTR_ERR(mmoc_ep));
		goto close;
	}
	rc = msm_rpc_call(mmoc_ep, /*proc*/1,
			&req, sizeof(req), 5 * HZ);
	if (rc < 0)
		printk(KERN_ERR "%s: rpc call failed! (%d)\n", __func__, rc);

close:
	msm_rpc_close(mmoc_ep);
	mutex_unlock(&mmoc_mutex);
	printk(KERN_INFO "%s: exiting\n", __func__);
	return rc;
}
Exemplo n.º 7
0
void msm_adsp_put(struct msm_adsp_module *module)
{
    unsigned long flags;

    mutex_lock(&module->lock);
    if (module->ops) {
        MM_INFO("closing module %s\n", module->name);

        /* lock to ensure a dsp event cannot be delivered
         * during or after removal of the ops and driver_data
         */
        spin_lock_irqsave(&adsp_cmd_lock, flags);
        module->ops = NULL;
        module->driver_data = NULL;
        spin_unlock_irqrestore(&adsp_cmd_lock, flags);

        if (module->state != ADSP_STATE_DISABLED) {
            MM_INFO("disabling module %s\n", module->name);
            msm_adsp_disable_locked(module);
        }

        if (module->rpc_client)
            msm_rpc_close(module->rpc_client);
        module->rpc_client = 0;
    } else {
        MM_INFO("module %s is already closed\n", module->name);
    }
    mutex_unlock(&module->lock);
}
Exemplo n.º 8
0
static int elini_gpio_earsense_work_func(void)
{
    int state;
    int gpio_value;

    struct snd_set_hook_param_rep {
        struct rpc_reply_hdr hdr;
        uint32_t get_mode;
    } hkrep;
    struct snd_set_hook_mode_msg {
        struct rpc_request_hdr hdr;
        struct rpc_snd_set_hook_mode_args args;
    } hookmsg;
    int rc;

    struct msm_rpc_endpoint *ept = msm_rpc_connect_compatible(RPC_SND_PROG,
                                   RPC_SND_VERS, 0);
    if (IS_ERR(ept)) {
        rc = PTR_ERR(ept);
        ept = NULL;
        printk(KERN_ERR"failed to connect snd svc, error %d\n", rc);
    }

    hookmsg.args.cb_func = -1;
    hookmsg.args.client_data = 0;


    gpio_value = gpio_get_value(GPIO_EAR_SENSE);
    printk(KERN_INFO"%s: ear sense detected : %s\n", __func__,
           gpio_value?"injected":"ejected");
    if (gpio_value == EAR_EJECT) {
        state = EAR_STATE_EJECT;
        gpio_set_value(GPIO_HS_MIC_BIAS_EN, 0);
        hookmsg.args.mode = cpu_to_be32(0);
    } else {
        state = EAR_STATE_INJECT;
        gpio_set_value(GPIO_HS_MIC_BIAS_EN, 1);
        hookmsg.args.mode = cpu_to_be32(1);
    }
    if(ept) {
        rc = msm_rpc_call_reply(ept,
                                SND_SET_HOOK_MODE_PROC,
                                &hookmsg, sizeof(hookmsg),&hkrep, sizeof(hkrep), 5 * HZ);
        if (rc < 0) {
            printk(KERN_ERR "%s:rpc err because of %d\n", __func__, rc);
        }
    } else {
        printk(KERN_ERR "%s:ext_snd is NULL\n", __func__);
    }
    rc = msm_rpc_close(ept);
    if (rc < 0)
        printk(KERN_ERR"msm_rpc_close failed\n");

    return state;
}
Exemplo n.º 9
0
static int vocpcm_open(struct inode *inode, struct file *file)
{
	struct voc_ctxt *ctxt = voc_minor_to_ctxt(MINOR(inode->i_rdev));

	if (!ctxt) {
		pr_err("voc: unknown voc misc %d\n", MINOR(inode->i_rdev));
		return -ENODEV;
	}

	mutex_lock(&the_voc.lock);
	if (the_voc.task == NULL) {
		if (the_voc.ept == NULL) 
			the_voc.ept = msm_rpc_connect_compatible(RPC_SND_PROG, RPC_SND_VERS,
					MSM_RPC_UNINTERRUPTIBLE | MSM_RPC_ENABLE_RECEIVE);
		if (IS_ERR(the_voc.ept)) {
			the_voc.ept = NULL;
			pr_err("voc: failed to connect voc svc\n");
			mutex_unlock(&the_voc.lock);
			return -ENODEV;
		}
		the_voc.task = kthread_run(voc_rpc_thread, NULL, "voc_rpc_thread");
		if (IS_ERR(the_voc.task)) {
			the_voc.task = NULL;
			if (the_voc.ept) msm_rpc_close(the_voc.ept);
			the_voc.ept = NULL;
			mutex_unlock(&the_voc.lock);
			return -EFAULT;
		}
	}
	mutex_unlock(&the_voc.lock);

	mutex_lock(&ctxt->lock);
	if (ctxt->opened) {
		pr_err("vocpcm already opened.\n");
		mutex_unlock(&ctxt->lock);
		return -EBUSY;
	}

	file->private_data = ctxt;
	ctxt->head = 0;
	ctxt->tail = 0;
	ctxt->client = 0;

	memset(ctxt->buf[0].data, 0, sizeof(ctxt->buf[0].data));
	memset(ctxt->buf[1].data, 0, sizeof(ctxt->buf[1].data));
	ctxt->buf[0].index = 0;
	ctxt->buf[1].index = 0;
	ctxt->opened = 1;
	ctxt->count = 0;
	ctxt->s_ptr = 0;
	ctxt->final_input = 0;

	mutex_unlock(&ctxt->lock);
	return 0;
}
Exemplo n.º 10
0
static void vocpcm_exit(void) 
{
	mutex_lock(&the_voc.lock);
	if(the_voc.ept != NULL) msm_rpc_close(the_voc.ept);
	the_voc.ept = NULL;
	shut_voc(&vocpcm0);
	shut_voc(&vocpcm1);
	shut_voc(&vocpcm2);
	shut_voc(&vocpcm3);

	mutex_unlock(&the_voc.lock);
}
Exemplo n.º 11
0
/*--------------------------------------------------------------------------*
 * Function    : DbgCfgSetErrorAction
 *
 * Description :
 *     Write the ARM9 fatal error auto action setting to NV item #905.
 *
 * Parameters  :
 *
 *     value - the desired error auto action.
 *
 * Return value: integer
 *     Zero     - Successful
 *     Not zero - Fail
 *--------------------------------------------------------------------------*/
int DbgCfgSetErrorAction(int value)
{
    unsigned int tmp_error_fatal_option = 0;
    int ret = -1;

    struct msm_rpc_endpoint *nv_ep;
    error_action_req req;
    error_action_rep rep;

    nv_ep = msm_rpc_connect(NVPROG, NVVERS, 0);

    if (IS_ERR(nv_ep)) 
    {
        printk(KERN_ERR "[dbgcfgtool] %s() LINE:%d, init rpc failed! error: %ld\n", __func__, __LINE__, PTR_ERR(nv_ep));
        return -EINVAL;
    }

    tmp_error_fatal_option = (error_fatal_option & ~ACTION_MASK) |value;

    req.cmd = cpu_to_be32(NV_WRITE_F);
    req.item = cpu_to_be32(NV_ERR_FATAL_OPTIONS_I);
    req.more_data = cpu_to_be32(1);
    req.disc = cpu_to_be32(NV_ERR_FATAL_OPTIONS_I);
    req.data = cpu_to_be32(tmp_error_fatal_option);

    ret = msm_rpc_call_reply (nv_ep,
        ONCRPC_NV_CMD_REMOTE_PROC,
        &req,
        sizeof (req),
        &rep,
        sizeof (rep),
        5 * HZ);

    if (ret < 0)
    {
        printk(KERN_ERR "[dbgcfgtool] %s() LINE:%d, rpc call failed! (%d)\n", __func__, __LINE__, ret);
    }
    else if (be32_to_cpu(rep.retval) != NV_DONE_S)
    {
        printk(KERN_ERR "[dbgcfgtool] %s() LINE:%d,  nv cmd remote result failed! (%d)\n", __func__, __LINE__, rep.retval);
    }
    else
    {
        ret = 0;
        error_fatal_option = tmp_error_fatal_option;  //write success, update local data
        printk(KERN_INFO "[dbgcfgtool] error_fatal_option = 0x%x\n", error_fatal_option);
    }

    msm_rpc_close(nv_ep);
    return ret;
    
}
Exemplo n.º 12
0
static int snd_sys_release(void)
{
	struct snd_sys_ctxt *snd_sys = &the_snd_sys;
	int rc = 0;

	mutex_lock(&snd_sys->lock);
	rc = msm_rpc_close(snd_sys->ept);
	if (rc < 0)
		MM_ERR("msm_rpc_close failed\n");
	snd_sys->ept = NULL;
	mutex_unlock(&snd_sys->lock);
	return rc;
}
Exemplo n.º 13
0
static int snd_release(struct inode *inode, struct file *file)
{
	struct snd_ctxt *snd = file->private_data;
	int rc;

	mutex_lock(&snd->lock);
	rc = msm_rpc_close(snd->ept);
	if (rc < 0)
		MM_ERR("msm_rpc_close failed\n");
	snd->ept = NULL;
	snd->opened = 0;
	mutex_unlock(&snd->lock);
	return 0;
}
Exemplo n.º 14
0
/*--------------------------------------------------------------------------*
 * Function    : DbgCfgSetDetectHWRese
 *
 * Description :
 *     Write the enable HW Reset detection flag to NV item #4399.
 *
 * Parameters  :
 *
 *     value - 0:enable ; 1:disable
 *
 * Return value: integer
 *     Zero     - Successful
 *     Not zero - Fail
 *--------------------------------------------------------------------------*/
int DbgCfgSetDetectHWReset(int value)
{
    int ret = -1;

    struct msm_rpc_endpoint *nv_ep;
    error_action_req req;
    error_action_rep rep;

    nv_ep = msm_rpc_connect(NVPROG, NVVERS, 0);

    if (IS_ERR(nv_ep)) 
    {
        printk(KERN_ERR "[dbgcfgtool] %s() LINE:%d, init rpc failed! error: %ld\n", __func__, __LINE__, PTR_ERR(nv_ep));
        return -EINVAL;
    }

    req.cmd = cpu_to_be32(NV_WRITE_F);
    req.item = cpu_to_be32(NV_DETECT_HW_RESET_I);
    req.more_data = cpu_to_be32(1);
    req.disc = cpu_to_be32(NV_DETECT_HW_RESET_I);
    req.data = cpu_to_be32(value);

    ret = msm_rpc_call_reply (nv_ep,
        ONCRPC_NV_CMD_REMOTE_PROC,
        &req,
        sizeof (req),
        &rep,
        sizeof (rep),
        5 * HZ);

    if (ret < 0)
    {
        printk(KERN_ERR "[dbgcfgtool] %s() LINE:%d, rpc call failed! (%d)\n", __func__, __LINE__, ret);
    }
    else if (be32_to_cpu(rep.retval) != NV_DONE_S)
    {
        printk(KERN_ERR "[dbgcfgtool] %s() LINE:%d,  nv cmd remote result failed! (%d)\n", __func__, __LINE__, rep.retval);
    }
    else
    {
        ret = 0;
        printk(KERN_INFO "[dbgcfgtool] detect_hw_reset = 0x%x\n", value);
    }

    msm_rpc_close(nv_ep);
    return ret;
    
}
Exemplo n.º 15
0
static int snd_open(struct inode *inode, struct file *file)
{
	struct snd_ctxt *snd = &the_snd;
	int rc = 0;

	mutex_lock(&snd->lock);
	if (snd->inited == 0) {
		snd->ept = create_rpc_connect(RPC_SND_PROG, RPC_SND_VERS,
					MSM_RPC_UNINTERRUPTIBLE |
					MSM_RPC_ENABLE_RECEIVE);
		if (IS_ERR(snd->ept)) {
			rc = PTR_ERR(snd->ept);
			snd->ept = NULL;
			pr_err("snd: failed to connect snd svc\n");
			goto err;
		}

		snd->task = create_snd_rpc_kthread();
		if (IS_ERR(snd->task)) {
			rc = PTR_ERR(snd->task);
			snd->task = NULL;
			msm_rpc_close(snd->ept);
			snd->ept = NULL;
			goto err;
		}
		snd->inited = 1;
	}

	if (snd->opened) {
		pr_err("snd already opened.\n");
		rc = -EBUSY;
		goto err;
	}

	file->private_data = snd;
	snd->opened = 1;
err:
	mutex_unlock(&snd->lock);
	return rc;
}
Exemplo n.º 16
0
int msm_snd_rpc_close(void)
{
	int rc = 0;

	if (IS_ERR(snd_ep)) {
		printk(KERN_ERR "%s: snd handle unavailable, rc = %ld\n",
				__func__, PTR_ERR(snd_ep));
		return -EAGAIN;
	}

	rc = msm_rpc_close(snd_ep);
	snd_ep = NULL;

	if (rc < 0) {
		printk(KERN_ERR "%s: close rpc failed! rc = %d\n",
				__func__, rc);
		return -EAGAIN;
	} else
		printk(KERN_INFO "rpc close success\n");

	return rc;
}
Exemplo n.º 17
0
/* rpc call to close connection */
int msm_hsusb_rpc_close(void)
{
	int rc = 0;

	if (IS_ERR(usb_ep)) {
		pr_err("%s: rpc_close failed before call, rc = %ld\n",
			__func__, PTR_ERR(usb_ep));
		return -EAGAIN;
	}

	rc = msm_rpc_close(usb_ep);
	usb_ep = NULL;

	if (rc < 0) {
		pr_err("%s: close rpc failed! rc = %d\n",
			__func__, rc);
		return -EAGAIN;
	} else
		pr_debug("rpc close success\n");

	return rc;
}
/* rpc call to close charging connection */
int msm_chg_rpc_close(void)
{
	int rc = 0;

	if (IS_ERR(chg_ep)) {
		printk(KERN_ERR "%s: rpc_close failed before call, rc = %ld\n",
			__func__, PTR_ERR(chg_ep));
		return -EAGAIN;
	}

	rc = msm_rpc_close(chg_ep);
	chg_ep = NULL;

	if (rc < 0) {
		printk(KERN_ERR "%s: close rpc failed! rc = %d\n",
			__func__, rc);
		return -EAGAIN;
	} else
		printk(KERN_INFO "rpc close success\n");

	return rc;
}
Exemplo n.º 19
0
static void internal_phy_reset(void)
{
	struct msm_rpc_endpoint *usb_ep;
	int rc;
	struct hsusb_phy_start_req {
		struct rpc_request_hdr hdr;
	} req;

	printk(KERN_INFO "msm_hsusb_phy_reset\n");

	usb_ep = msm_rpc_connect(HSUSB_API_PROG, HSUSB_API_VERS, 0);
	if (IS_ERR(usb_ep)) {
		printk(KERN_ERR "%s: init rpc failed! error: %ld\n",
				__func__, PTR_ERR(usb_ep));
		return;
	}
	rc = msm_rpc_call(usb_ep, HSUSB_API_INIT_PHY_PROC,
			&req, sizeof(req), 5 * HZ);
	if (rc < 0)
		printk(KERN_ERR "%s: rpc call failed! (%d)\n", __func__, rc);

	msm_rpc_close(usb_ep);
}
Exemplo n.º 20
0
int __init rpc_tlmm_remote_atom_2(uint32_t proc, uint32_t d1, uint32_t d2)
{
	struct msm_rpc_endpoint *mmoc_ep;
	int rc;
	struct mmoc_req {
		struct rpc_request_hdr hdr;
		uint32_t data[2];
	} req;

	printk(KERN_INFO "%s: proc: %02x\n", __func__, proc);
	mutex_lock(&mmoc_mutex);

	req.data[0] = cpu_to_be32(d1);
	req.data[1] = cpu_to_be32(d2);
	/*req.data[2] = cpu_to_be32(d3);
	req.data[3] = cpu_to_be32(d4);
	req.data[4] = cpu_to_be32(d5);
	req.data[5] = cpu_to_be32(d6);*/

	mmoc_ep = msm_rpc_connect(0x30000066, 0, 0);
	if (IS_ERR(mmoc_ep)) {
		printk(KERN_ERR "%s: init rpc failed! error: %ld\n",
				__func__, PTR_ERR(mmoc_ep));
		goto close;
	}
	rc = msm_rpc_call(mmoc_ep, /*proc*/ proc,
			&req, sizeof(req), 5 * HZ);
	if (rc < 0)
		printk(KERN_ERR "%s: rpc call failed! (%d)\n", __func__, rc);

close:
	msm_rpc_close(mmoc_ep);
	mutex_unlock(&mmoc_mutex);
	printk(KERN_INFO "%s: exiting\n", __func__);
	return rc;
}
Exemplo n.º 21
0
static long snd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	struct snd_set_device_msg dmsg;
	struct snd_set_volume_msg vmsg;
	struct snd_avc_ctl_msg avc_msg;
	struct snd_agc_ctl_msg agc_msg;

	struct msm_snd_device_config dev;
	struct msm_snd_volume_config vol;
	struct snd_ctxt *snd = file->private_data;
	int rc = 0;

	uint32_t avc, agc;

	mutex_lock(&snd->lock);
	switch (cmd) {
	case SND_SET_DEVICE:
		if (copy_from_user(&dev, (void __user *) arg, sizeof(dev))) {
			MM_ERR("set device: invalid pointer\n");
			rc = -EFAULT;
			break;
		}

		dmsg.args.device = cpu_to_be32(dev.device);
		dmsg.args.ear_mute = cpu_to_be32(dev.ear_mute);
		dmsg.args.mic_mute = cpu_to_be32(dev.mic_mute);
		if (check_mute(dev.ear_mute) < 0 ||
				check_mute(dev.mic_mute) < 0) {
			MM_ERR("set device: invalid mute status\n");
			rc = -EINVAL;
			break;
		}
		dmsg.args.cb_func = -1;
		dmsg.args.client_data = 0;

		MM_INFO("snd_set_device %d %d %d\n", dev.device,
				dev.ear_mute, dev.mic_mute);

		rc = msm_rpc_call(snd->ept,
			SND_SET_DEVICE_PROC,
			&dmsg, sizeof(dmsg), 5 * HZ);
		break;

	case SND_SET_VOLUME:
		if (copy_from_user(&vol, (void __user *) arg, sizeof(vol))) {
			MM_ERR("set volume: invalid pointer\n");
			rc = -EFAULT;
			break;
		}

		vmsg.args.device = cpu_to_be32(vol.device);
		vmsg.args.method = cpu_to_be32(vol.method);
#ifdef CONFIG_HUAWEI_KERNEL
		if (vol.method != SND_METHOD_VOICE&&vol.method != SND_METHOD_MIDI) {
#else
		if (vol.method != SND_METHOD_VOICE) {
#endif

			MM_ERR("set volume: invalid method\n");
			rc = -EINVAL;
			break;
		}

		vmsg.args.volume = cpu_to_be32(vol.volume);
		vmsg.args.cb_func = -1;
		vmsg.args.client_data = 0;

		MM_INFO("snd_set_volume %d %d %d\n", vol.device,
				vol.method, vol.volume);

		rc = msm_rpc_call(snd->ept,
			SND_SET_VOLUME_PROC,
			&vmsg, sizeof(vmsg), 5 * HZ);
		break;

	case SND_AVC_CTL:
		if (get_user(avc, (uint32_t __user *) arg)) {
			rc = -EFAULT;
			break;
		} else if ((avc != 1) && (avc != 0)) {
			rc = -EINVAL;
			break;
		}

		avc_msg.args.avc_ctl = cpu_to_be32(avc);
		avc_msg.args.cb_func = -1;
		avc_msg.args.client_data = 0;

		MM_INFO("snd_avc_ctl %d\n", avc);

		rc = msm_rpc_call(snd->ept,
			SND_AVC_CTL_PROC,
			&avc_msg, sizeof(avc_msg), 5 * HZ);
		break;

	case SND_AGC_CTL:
		if (get_user(agc, (uint32_t __user *) arg)) {
			rc = -EFAULT;
			break;
		} else if ((agc != 1) && (agc != 0)) {
			rc = -EINVAL;
			break;
		}
		agc_msg.args.agc_ctl = cpu_to_be32(agc);
		agc_msg.args.cb_func = -1;
		agc_msg.args.client_data = 0;

		MM_INFO("snd_agc_ctl %d\n", agc);

		rc = msm_rpc_call(snd->ept,
			SND_AGC_CTL_PROC,
			&agc_msg, sizeof(agc_msg), 5 * HZ);
		break;

	case SND_GET_NUM_ENDPOINTS:
		if (copy_to_user((void __user *)arg,
				&snd->snd_epts->num, sizeof(unsigned))) {
			MM_ERR("get endpoint: invalid pointer\n");
			rc = -EFAULT;
		}
		break;

	case SND_GET_ENDPOINT:
		rc = get_endpoint(snd, arg);
		break;

	default:
		MM_ERR("unknown command\n");
		rc = -EINVAL;
		break;
	}
	mutex_unlock(&snd->lock);

	return rc;
}

static int snd_release(struct inode *inode, struct file *file)
{
	struct snd_ctxt *snd = file->private_data;
	int rc;

	mutex_lock(&snd->lock);
	rc = msm_rpc_close(snd->ept);
	if (rc < 0)
		MM_ERR("msm_rpc_close failed\n");
	snd->ept = NULL;
	snd->opened = 0;
	mutex_unlock(&snd->lock);
	return 0;
}
static int snd_sys_release(void)
{
	struct snd_sys_ctxt *snd_sys = &the_snd_sys;
	int rc = 0;

	mutex_lock(&snd_sys->lock);
	rc = msm_rpc_close(snd_sys->ept);
	if (rc < 0)
		MM_ERR("msm_rpc_close failed\n");
	snd_sys->ept = NULL;
	mutex_unlock(&snd_sys->lock);
	return rc;
}
static int snd_open(struct inode *inode, struct file *file)
{
	struct snd_ctxt *snd = &the_snd;
	int rc = 0;

	mutex_lock(&snd->lock);
	if (snd->opened == 0) {
		if (snd->ept == NULL) {
			snd->ept = msm_rpc_connect_compatible(RPC_SND_PROG,
					RPC_SND_VERS, 0);
			if (IS_ERR(snd->ept)) {
				rc = PTR_ERR(snd->ept);
				snd->ept = NULL;
				MM_ERR("failed to connect snd svc\n");
				goto err;
			}
		}
		file->private_data = snd;
		snd->opened = 1;
	} else {
		MM_ERR("snd already opened\n");
		rc = -EBUSY;
	}

err:
	mutex_unlock(&snd->lock);
	return rc;
}
static int snd_sys_open(void)
{
	struct snd_sys_ctxt *snd_sys = &the_snd_sys;
	int rc = 0;

	mutex_lock(&snd_sys->lock);
	if (snd_sys->ept == NULL) {
		snd_sys->ept = msm_rpc_connect_compatible(RPC_SND_PROG,
			RPC_SND_VERS, 0);
		if (IS_ERR(snd_sys->ept)) {
			rc = PTR_ERR(snd_sys->ept);
			snd_sys->ept = NULL;
			MM_ERR("failed to connect snd svc\n");
			goto err;
		}
	} else
		MM_DBG("snd already opened\n");

err:
	mutex_unlock(&snd_sys->lock);
	return rc;
}

static struct file_operations snd_fops = {
	.owner		= THIS_MODULE,
	.open		= snd_open,
	.release	= snd_release,
	.unlocked_ioctl	= snd_ioctl,
};

struct miscdevice snd_misc = {
	.minor	= MISC_DYNAMIC_MINOR,
	.name	= "msm_snd",
	.fops	= &snd_fops,
};

static long snd_agc_enable(unsigned long arg)
{
	struct snd_sys_ctxt *snd_sys = &the_snd_sys;
	struct snd_agc_ctl_msg agc_msg;
	int rc = 0;

	if ((arg != 1) && (arg != 0))
		return -EINVAL;

	agc_msg.args.agc_ctl = cpu_to_be32(arg);
	agc_msg.args.cb_func = -1;
	agc_msg.args.client_data = 0;

	MM_DBG("snd_agc_ctl %ld,%d\n", arg, agc_msg.args.agc_ctl);

	rc = msm_rpc_call(snd_sys->ept,
		SND_AGC_CTL_PROC,
		&agc_msg, sizeof(agc_msg), 5 * HZ);
	return rc;
}

static long snd_avc_enable(unsigned long arg)
{
	struct snd_sys_ctxt *snd_sys = &the_snd_sys;
	struct snd_avc_ctl_msg avc_msg;
	int rc = 0;

	if ((arg != 1) && (arg != 0))
		return -EINVAL;

	avc_msg.args.avc_ctl = cpu_to_be32(arg);

	avc_msg.args.cb_func = -1;
	avc_msg.args.client_data = 0;

	MM_DBG("snd_avc_ctl %ld,%d\n", arg, avc_msg.args.avc_ctl);

	rc = msm_rpc_call(snd_sys->ept,
		SND_AVC_CTL_PROC,
		&avc_msg, sizeof(avc_msg), 5 * HZ);
	return rc;
}

static ssize_t snd_agc_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t size)
{
	ssize_t status;
	struct snd_sys_ctxt *snd_sys = &the_snd_sys;
	int rc = 0;

	rc = snd_sys_open();
	if (rc)
		return rc;

	mutex_lock(&snd_sys->lock);

	if (sysfs_streq(buf, "enable"))
		status = snd_agc_enable(1);
	else if (sysfs_streq(buf, "disable"))
		status = snd_agc_enable(0);
	else
		status = -EINVAL;

	mutex_unlock(&snd_sys->lock);
	rc = snd_sys_release();
	if (rc)
		return rc;

	return status ? : size;
}

static ssize_t snd_avc_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t size)
{
	ssize_t status;
	struct snd_sys_ctxt *snd_sys = &the_snd_sys;
	int rc = 0;

	rc = snd_sys_open();
	if (rc)
		return rc;

	mutex_lock(&snd_sys->lock);

	if (sysfs_streq(buf, "enable"))
		status = snd_avc_enable(1);
	else if (sysfs_streq(buf, "disable"))
		status = snd_avc_enable(0);
	else
		status = -EINVAL;

	mutex_unlock(&snd_sys->lock);
	rc = snd_sys_release();
	if (rc)
		return rc;

	return status ? : size;
}