예제 #1
0
static ssize_t dsp_write(struct file *file, const char __user *buf,
			 size_t count, loff_t *pos)
{
	char cmd[32];
	unsigned int arg1, arg2;
	int rc = 0;

	if (count >= sizeof(cmd))
		return -EINVAL;
	if (copy_from_user(cmd, buf, count))
		return -EFAULT;
	cmd[count] = 0;

	if ((count > 1) && (cmd[count-1] == '\n'))
		cmd[count-1] = 0;

	if (!strcmp(cmd, "wait-for-crash")) {
		while (!dsp_has_crashed) {
			int res;
			dsp_wait_count++;
			res = wait_event_interruptible(dsp_wait, dsp_has_crashed);
			if (res < 0) {
				dsp_wait_count--;
				return res;
			}
		}
#if defined(CONFIG_MACH_MAHIMAHI)
		/* assert DSP NMI */
		msm_proc_comm(PCOM_CUSTOMER_CMD1, 0, 0);
		msleep(250);
#endif
		
		
		arg1 = SMEM_PC_OEM_FLUSH_ADSP6_CACHE;
		arg2 = 0;
		rc = cust_mproc_comm1(&arg1,&arg2);  
		printk("Send SMEM_PC_OEM_FLUSH_ADSP6_CACHE done rc = %d", rc);
		msleep(250);
			

	} else if (!strcmp(cmd, "boom")) {
		q6audio_dsp_not_responding();
	} else if (!strcmp(cmd, "continue-crash")) {
		dsp_has_crashed = 2;
		wake_up(&dsp_wait);
	} else {
		pr_err("[%s:%s] unknown dsp_debug command: %s\n", __MM_FILE__,
				__func__, cmd);
	}

	return count;
}
예제 #2
0
static ssize_t q6_in_read(struct file *file, char __user *buf,
			  size_t count, loff_t *pos)
{
	struct pcm *pcm = file->private_data;
	struct audio_client *ac;
	struct audio_buffer *ab;
	const char __user *start = buf;
	int xfer;
	int res;

	ac = pcm->ac;
	if (!ac) {
		res = -ENODEV;
		goto fail;
	}
	while (count > 0) {
		ab = ac->buf + ac->cpu_buf;

		if (ab->used)
			if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) {
#ifdef CONFIG_EF12_BOARD
				printk("[SKY AUDIO] Dal timeout! maybe timeout or dsp dead.\n");
#else
				audio_client_dump(ac);
				pr_err("[%s:%s] timeout. dsp dead?\n",
						__MM_FILE__, __func__);
				q6audio_dsp_not_responding();
#endif
			}

		xfer = count;
		if (xfer > ab->size)
			xfer = ab->size;

		if (copy_to_user(buf, ab->data, xfer)) {
			res = -EFAULT;
			goto fail;
		}

		buf += xfer;
		count -= xfer;

		ab->used = 1;
		q6audio_read(ac, ab);
		ac->cpu_buf ^= 1;
	}
fail:
	res = buf - start;
	return res;
}
예제 #3
0
static ssize_t pcm_write(struct file *file, const char __user *buf,
			   size_t count, loff_t *pos)
{
	struct pcm *pcm = file->private_data;
	struct audio_client *ac;
	struct audio_buffer *ab;
	const char __user *start = buf;
	int xfer;

	pr_debug("[%s:%s] count = %d\n", __MM_FILE__, __func__, count);
	if (!pcm->ac)
		pcm_ioctl(file, AUDIO_START, 0);

	ac = pcm->ac;
	if (!ac)
		return -ENODEV;

	while (count > 0) {
		ab = ac->buf + ac->cpu_buf;

		if (ab->used)
			if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) {
				audio_client_dump(ac);
				pr_err("[%s:%s] timeout. dsp dead?\n",
						__MM_FILE__, __func__);
				q6audio_dsp_not_responding();
			}
		pr_debug("[%s:%s] ab->data = %p, cpu_buf = %d", __MM_FILE__,
			__func__, ab->data, ac->cpu_buf);
		xfer = count;
		if (xfer > ab->size)
			xfer = ab->size;

		if (copy_from_user(ab->data, buf, xfer))
			return -EFAULT;

		buf += xfer;
		count -= xfer;

		ab->used = 1;
		ab->actual_size = xfer;
		q6audio_write(ac, ab);
		ac->cpu_buf ^= 1;
	}

	return buf - start;
}
static ssize_t q6_in_read(struct file *file, char __user *buf,
			  size_t count, loff_t *pos)
{
	struct pcm *pcm = file->private_data;
	struct audio_client *ac;
	struct audio_buffer *ab;
	const char __user *start = buf;
	int xfer;
	int res;

	ac = pcm->ac;
	if (!ac) {
		res = -ENODEV;
		goto fail;
	}
	while (count > 0) {
		ab = ac->buf + ac->cpu_buf;

		if (ab->used)
			if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) {
				audio_client_dump(ac);
				pr_err("pcm_read: timeout. dsp dead?\n");
				q6audio_dsp_not_responding();
			}

		xfer = count;
		if (xfer > ab->size)
			xfer = ab->size;

		if (copy_to_user(buf, ab->data, xfer)) {
			res = -EFAULT;
			goto fail;
		}

		buf += xfer;
		count -= xfer;

		ab->used = 1;
		q6audio_read(ac, ab);
		ac->cpu_buf ^= 1;
	}
fail:
	res = buf - start;
	return res;
}
예제 #5
0
파일: q6audio.c 프로젝트: Ma7moud/kernel
static int audio_ioctl(struct audio_client *ac, void *ptr, uint32_t len)
{
    struct adsp_command_hdr *hdr = ptr;
    uint32_t tmp;
    int r;

    hdr->size = len - sizeof(u32);
    hdr->dst = AUDIO_ADDR(ac->session, 0, AUDIO_DOMAIN_DSP);
    hdr->src = AUDIO_ADDR(ac->session, 0, AUDIO_DOMAIN_MODEM);
    hdr->context = ac->session;
    ac->cb_status = -EBUSY;
    r = dal_call(ac->client, AUDIO_OP_CONTROL, 5, ptr, len, &tmp, sizeof(tmp));
    if (r != 4)
        return -EIO;
    if (!wait_event_timeout(ac->wait, (ac->cb_status != -EBUSY), 5*HZ)) {
        dal_trace_dump(ac->client);
        pr_err("audio_ioctl: timeout. dsp dead?\n");
        q6audio_dsp_not_responding();
    }
    return ac->cb_status;
}
예제 #6
0
파일: q6audio.c 프로젝트: Ma7moud/kernel
struct audio_client *q6audio_open_pcm(uint32_t bufsz, uint32_t rate,
                                      uint32_t channels, uint32_t flags, uint32_t acdb_id)
{
    int rc, retry = 5;
    struct audio_client *ac;

    if (q6audio_init())
        return 0;

    ac = audio_client_alloc(bufsz);
    if (!ac)
        return 0;

    ac->flags = flags;

    mutex_lock(&audio_path_lock);

    if (ac->flags & AUDIO_FLAG_WRITE) {
        audio_rx_path_refcount++;
        if (audio_rx_path_refcount == 1) {
            _audio_rx_clk_enable();
#ifdef CONFIG_MSM_QDSP6_CALLREC
            q6_rx_path_enable(0, acdb_id);
            adie_rx_path_enable(acdb_id);
#else
            audio_update_acdb(audio_rx_device_id, acdb_id);
            qdsp6_devchg_notify(ac_control, ADSP_AUDIO_RX_DEVICE, audio_rx_device_id);
            qdsp6_standby(ac_control);
            qdsp6_start(ac_control);
#endif
        }
    } else {
        /* TODO: consider concurrency with voice call */
#ifdef CONFIG_MSM_QDSP6_CALLREC
        if (audio_tx_path_refcount > 0) {
            tx_clk_freq = 8000;
        } else {
            tx_clk_freq = rate;
        }
#else
        tx_clk_freq = rate;
#endif
        audio_tx_path_refcount++;
        if (audio_tx_path_refcount == 1) {
#ifdef CONFIG_MSM_QDSP6_CALLREC
            tx_clk_freq = rate;
#endif
            _audio_tx_clk_enable();
            _audio_tx_path_enable(0, acdb_id);
        }
    }

    for (retry = 5;; retry--) {
        if (ac->flags & AUDIO_FLAG_WRITE)
            rc = audio_out_open(ac, bufsz, rate, channels);
        else
#ifdef CONFIG_MSM_QDSP6_CALLREC
            rc = audio_in_open(ac, bufsz, flags, rate, channels);
#else
            rc = audio_in_open(ac, bufsz, rate, channels);
#endif
        if (rc == 0)
            break;
        if (retry == 0)
            q6audio_dsp_not_responding();
        pr_err("q6audio: open pcm error %d, retrying\n", rc);
        msleep(1);
    }

    if (ac->flags & AUDIO_FLAG_WRITE) {
        if (audio_rx_path_refcount == 1) {
#ifndef CONFIG_MSM_QDSP6_CALLREC
            adie_enable();
            adie_set_path(adie, audio_rx_path_id, ADIE_PATH_RX);
            adie_set_path_freq_plan(adie, ADIE_PATH_RX, 48000);

            adie_proceed_to_stage(adie, ADIE_PATH_RX, ADIE_STAGE_DIGITAL_READY);
            adie_proceed_to_stage(adie, ADIE_PATH_RX, ADIE_STAGE_DIGITAL_ANALOG_READY);

#endif
            audio_rx_analog_enable(1);
        }
    }

    mutex_unlock(&audio_path_lock);

    for (retry = 5;; retry--) {
        rc = audio_command(ac, ADSP_AUDIO_IOCTL_CMD_SESSION_START);
        if (rc == 0)
            break;
        if (retry == 0)
            q6audio_dsp_not_responding();
        pr_err("q6audio: stream start error %d, retrying\n", rc);
    }

    if (!(ac->flags & AUDIO_FLAG_WRITE)) {
        ac->buf[0].used = 1;
        ac->buf[1].used = 1;
        q6audio_read(ac, &ac->buf[0]);
        q6audio_read(ac, &ac->buf[1]);
    }

    audio_prevent_sleep();
    return ac;
}
예제 #7
0
static ssize_t q6_amrnb_in_read(struct file *file, char __user *buf,
			   size_t count, loff_t *pos)
{
	struct audio_client *ac;
	struct audio_buffer *ab;
	const char __user *start = buf;
	struct amrnb *amrnb = file->private_data;
	int xfer = 0;
	int res;

	mutex_lock(&amrnb->lock);
	ac = amrnb->audio_client;
	if (!ac) {
		res = -ENODEV;
		goto fail;
	}
#if 1 
	while (count > xfer) {
		ab = ac->buf + ac->cpu_buf;

		if (ab->used)
			wait_event(ac->wait, (ab->used == 0));

		xfer = ab->actual_size;

		if (copy_to_user(buf, ab->data, xfer)) {
			res = -EFAULT;
			goto fail;
		}

		buf += xfer;
		count -= xfer;

		ab->used = 1;
		q6audio_read(ac, ab);
		ac->cpu_buf ^= 1;
	}
#else
        while (count > 0) {
                ab = ac->buf + ac->cpu_buf;

                if (ab->used)
			 wait_event(ac->wait, (ab->used == 0));
#if 0
                        if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) {
                                audio_client_dump(ac);
                                pr_err("pcm_read: timeout. dsp dead?\n");
                                q6audio_dsp_not_responding();
                        }
#endif
                xfer = count;
                if (xfer > ab->size)
                        xfer = ab->size;

                if (copy_to_user(buf, ab->data, xfer)) {
                        res = -EFAULT;
                        goto fail;
                }

                buf += xfer;
                count -= xfer;

                ab->used = 1;
                q6audio_read(ac, ab);
                ac->cpu_buf ^= 1;
        }
#endif

	res = buf - start;
fail:
	mutex_unlock(&amrnb->lock);

	return res;
}
예제 #8
0
int subsystem_restart(const char *subsys_name)
{
	struct subsys_data *subsys;
	struct task_struct *tsk;
	struct restart_thread_data *data = NULL;

	if (!subsys_name) {
		pr_err("%s: Invalid subsystem name.", __func__);
		return -EINVAL;
	}

	pr_info("Subsystem Restart: Restart sequence requested for  %s\n",
		subsys_name);

	/* List of subsystems is protected by a lock. New subsystems can
	 * still come in.
	 */
	subsys = _find_subsystem(subsys_name);

	if (!subsys) {
		pr_warn("%s: Unregistered subsystem %s!", __func__,
				subsys_name);
		return -EINVAL;
	}
	
//[email protected], 2011-09-20, [MDM BSP] for ULS display	
#ifdef CONFIG_LGE_SDIO_DEBUG_CH	
{
	if (strncmp("external_modem", subsys_name, 14) == 0)
	{
		uls_the_kind_of_subsys = ULS_SUBSYSTEM_MDM;
	}
	else if (strncmp("modem", subsys_name, 5) == 0)
	{
		uls_the_kind_of_subsys = ULS_SUBSYSTEM_MODEM;			
	}
	else if (strncmp("lpass", subsys_name, 5) == 0)
	{
		uls_the_kind_of_subsys = ULS_SUBSYSTEM_LPASS;
	}
	else // this should not be happened.
	{	
		uls_the_kind_of_subsys = ULS_SUBSYSTEM_OTHER;	
		pr_info("%s: Unkown subsystem: Restart sequence requested for  %s\n",
				__func__, subsys_name);
	}
}
#endif
//[email protected], 2011-09-20, [MDM BSP] for ULS display		

	if (restart_level != RESET_SOC) {
		data = kzalloc(sizeof(struct restart_thread_data), GFP_KERNEL);
		if (!data) {
			restart_level = RESET_SOC;
			pr_warn("%s: Failed to alloc restart data. Resetting.",
				__func__);
		} else {
			if (restart_level == RESET_SUBSYS_COUPLED ||
					restart_level == RESET_SUBSYS_MIXED)
				data->coupled = 1;
			else
				data->coupled = 0;

			data->subsys = subsys;
		}
	}

	switch (restart_level) {

	case RESET_SUBSYS_COUPLED:
	case RESET_SUBSYS_MIXED:
	case RESET_SUBSYS_INDEPENDENT:
		dprintk("%s: Restarting %s [level=%d]!\n", __func__,
			subsys_name, restart_level);

		/* Let the kthread handle the actual restarting. Using a
		 * workqueue will not work since all restart requests are
		 * serialized and it prevents the short circuiting of
		 * restart requests for subsystems already in a restart
		 * sequence.
		 */
		tsk = kthread_run(subsystem_restart_thread, data,
				"subsystem_subsystem_restart_thread");
		if (IS_ERR(tsk)) {
		/* [email protected] 2011-06-01
		 * add the error handler */
#if defined(CONFIG_LGE_ERROR_HANDLER)
			msm_set_restart_mode(SUB_UNAB_THD);
#endif
			panic("%s: Unable to create thread to restart %s",
				__func__, subsys->name);
		}

		break;

	case RESET_SOC:
		
#if 0//#ifdef CONFIG_LGE_DEBUG //[email protected] : ramdump for Q6 when Q6 crash or watchdog reset
/* this code need to  start a dspcrashd deamon in init.qcom.rc */
		if (!strncmp("lpass", subsys_name,SUBSYS_NAME_MAX_LENGTH)) 
			q6audio_dsp_not_responding(); 
#endif
		mutex_lock(&subsystem_list_lock);
		list_for_each_entry(subsys, &subsystem_list, list)
			if (subsys->crash_shutdown)
				subsys->crash_shutdown(subsys->name);
		mutex_unlock(&subsystem_list_lock);

		/* [email protected] 2011-06-01
		 * add the error handler */
#if defined(CONFIG_LGE_ERROR_HANDLER)
		msm_set_restart_mode(SUB_RESET_SOC);
#endif
		panic("Resetting the SOC");
		break;

	default:
		/* [email protected] 2011-06-01
		 * add the error handler */
#if defined(CONFIG_LGE_ERROR_HANDLER)
		msm_set_restart_mode(SUB_UNKNOWN);
#endif
		panic("subsys-restart: Unknown restart level!\n");
	break;

	}

	return 0;
}
예제 #9
0
// Jagan-
static ssize_t pcm_write(struct file *file, const char __user *buf,
			   size_t count, loff_t *pos)
{
	struct pcm *pcm = file->private_data;
	struct audio_client *ac;
	struct audio_buffer *ab;
	const char __user *start = buf;
	int xfer;

#if 0
// Jagan+
	if(!task_has_rt_policy(current))
	{
		struct sched_param param = { .sched_priority = 99 };
		printk(KERN_INFO "pcm_write to change to RT tid = %d\n", current->pid);	
	 	 if(sched_setscheduler_nocheck(current, SCHED_FIFO, &param )!=0)
	 	{
	  		printk(KERN_ERR "pcm_write fail to change to RT\n");
	 	}		 
	}
// Jagan-
#endif

	if (!pcm->ac)
		pcm_ioctl(file, AUDIO_START, 0);

	ac = pcm->ac;
	if (!ac)
		return -ENODEV;

	while (count > 0) {
		ab = ac->buf + ac->cpu_buf;

		if (ab->used)
			if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) {
				audio_client_dump(ac);
				pr_err("[%s:%s] timeout. dsp dead?\n",
						__MM_FILE__, __func__);
				q6audio_dsp_not_responding();
			}

		xfer = count;
		if (xfer > ab->size)
			xfer = ab->size;

		if (copy_from_user(ab->data, buf, xfer)) 
			return -EFAULT;

		buf += xfer;
		count -= xfer;

		ab->used = 1;
		ab->actual_size = xfer;
		q6audio_write(ac, ab);
		ac->cpu_buf ^= 1;
	}

	return buf - start;
}

static int pcm_release(struct inode *inode, struct file *file)
{
	struct pcm *pcm = file->private_data;
	if (pcm->ac)
		q6audio_close(pcm->ac);
	kfree(pcm);
	pr_info("[%s:%s] release\n", __MM_FILE__, __func__);
// Jagan+
	if (unlikely(1 == Is_first_boot_flag))
		Is_first_boot_flag = 0;	
// Jagan-
	return 0;
}

static struct file_operations pcm_fops = {
	.owner		= THIS_MODULE,
	.open		= pcm_open,
	.write		= pcm_write,
	.release	= pcm_release,
	.unlocked_ioctl	= pcm_ioctl,
};

struct miscdevice pcm_misc = {
	.minor	= MISC_DYNAMIC_MINOR,
	.name	= "msm_pcm_out",
	.fops	= &pcm_fops,
};

static int __init pcm_init(void) {
	return misc_register(&pcm_misc);
}

device_initcall(pcm_init);