int msm_snddev_request_freq(int *freq, u32 session_id,
			u32 capability, u32 clnt_type)
{
	int i = 0;
	int rc = 0;
	struct msm_snddev_info *info;
	u32 set_freq;
	u32 session_mask = 0;
	u32 clnt_type_mask = 0;

	MM_DBG(": clnt_type 0x%08x\n", clnt_type);

	if ((clnt_type == AUDDEV_CLNT_VOC) && (session_id != 0))
		return -EINVAL;
	if ((clnt_type == AUDDEV_CLNT_DEC)
			&& (session_id >= MAX_DEC_SESSIONS))
		return -EINVAL;
	if ((clnt_type == AUDDEV_CLNT_ENC)
			&& (session_id >= MAX_ENC_SESSIONS))
		return -EINVAL;
	session_mask = ((0x1 << session_id)) << (8 * (clnt_type-1));
	clnt_type_mask = (0xFF << (8 * (clnt_type-1)));
	if (!(*freq == 8000) && !(*freq == 11025) &&
		!(*freq == 12000) && !(*freq == 16000) &&
		!(*freq == 22050) && !(*freq == 24000) &&
		!(*freq == 32000) && !(*freq == 44100) &&
		!(*freq == 48000))
		return -EINVAL;

	for (i = 0; i < audio_dev_ctrl.num_dev; i++) {
		info = audio_dev_ctrl.devs[i];
		if ((info->sessions & session_mask)
			&& (info->capability & capability)) {
			rc = 0;
			if ((info->sessions & ~clnt_type_mask)
				&& ((*freq != 8000) && (*freq != 16000)
					&& (*freq != 48000))) {
				if (clnt_type == AUDDEV_CLNT_ENC) {
					routing_info.enc_freq[session_id].freq
							= 0;
					return -EPERM;
				} else if (clnt_type == AUDDEV_CLNT_DEC) {
					routing_info.dec_freq[session_id].freq
							= 0;
					return -EPERM;
				}
			}
			if (*freq == info->set_sample_rate) {
				rc = info->set_sample_rate;
				continue;
			}
			set_freq = MAX(*freq, info->set_sample_rate);
			if (set_freq == info->set_sample_rate) {
				rc = info->set_sample_rate;
				*freq = info->set_sample_rate;
				continue;
			}

			if (clnt_type == AUDDEV_CLNT_DEC) {
				routing_info.dec_freq[session_id].evt = 1;
				routing_info.dec_freq[session_id].freq
						= set_freq;
			} else if (clnt_type == AUDDEV_CLNT_ENC) {
				routing_info.enc_freq[session_id].evt = 1;
				routing_info.enc_freq[session_id].freq
						= set_freq;
			} else if (capability == SNDDEV_CAP_TX)
				routing_info.voice_tx_sample_rate = set_freq;

			rc = set_freq;
			info->set_sample_rate = set_freq;
			*freq = info->set_sample_rate;

			if (info->opened) {
				broadcast_event(AUDDEV_EVT_FREQ_CHG, i,
							SESSION_IGNORE);
				set_freq = info->dev_ops.set_freq(info,
								set_freq);
				broadcast_event(AUDDEV_EVT_DEV_RDY, i,
							SESSION_IGNORE);
			}
		}
		MM_DBG("info->set_sample_rate = %d\n", info->set_sample_rate);
		MM_DBG("routing_info.enc_freq.freq = %d\n",
					routing_info.enc_freq[session_id].freq);
	}
	return rc;
}
Example #2
0
static void audio_prevent_sleep(struct audio *audio)
{
	MM_DBG("\n"); /* Macro prints the file name and function */
	wake_lock(&audio->wakelock);
	wake_lock(&audio->idlelock);
}
Example #3
0
static int snddev_icodec_open_rx(struct snddev_icodec_state *icodec)
{
	int trc, err;
	int smps_mode = PMAPP_SMPS_MODE_VOTE_PWM;
	struct msm_afe_config afe_config;
	struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;
	struct lpa_codec_config lpa_config;

	wake_lock(&drv->rx_idlelock);

	if ((icodec->data->acdb_id == ACDB_ID_HEADSET_SPKR_MONO) ||
		(icodec->data->acdb_id == ACDB_ID_HEADSET_SPKR_STEREO)) {
		/* Vote PMAPP_SMPS_MODE_VOTE_PFM for headset */
		smps_mode = PMAPP_SMPS_MODE_VOTE_PFM;
		MM_DBG("snddev_icodec_open_rx: PMAPP_SMPS_MODE_VOTE_PFM \n");
	} else
		MM_DBG("snddev_icodec_open_rx: PMAPP_SMPS_MODE_VOTE_PWM \n");

	/* Vote for SMPS mode*/
	err = pmapp_smps_mode_vote(SMPS_AUDIO_PLAYBACK_ID,
				PMAPP_VREG_S4, smps_mode);
	if (err != 0)
		MM_ERR("pmapp_smps_mode_vote error %d\n", err);

	/* enable MI2S RX master block */
	/* enable MI2S RX bit clock */
	trc = clk_set_rate(drv->rx_mclk,
		SNDDEV_ICODEC_CLK_RATE(icodec->sample_rate));
	if (IS_ERR_VALUE(trc))
		goto error_invalid_freq;
	clk_enable(drv->rx_mclk);
	clk_enable(drv->rx_sclk);
	/* clk_set_rate(drv->lpa_codec_clk, 1); */ /* Remove if use pcom */
	clk_enable(drv->lpa_p_clk);
	clk_enable(drv->lpa_codec_clk);
	clk_enable(drv->lpa_core_clk);

	/* Enable LPA sub system
	 */
	drv->lpa = lpa_get();
	if (!drv->lpa)
		goto error_lpa;
	lpa_config.sample_rate = icodec->sample_rate;
	lpa_config.sample_width = 16;
	lpa_config.output_interface = LPA_OUTPUT_INTF_WB_CODEC;
	lpa_config.num_channels = icodec->data->channel_mode;
	lpa_cmd_codec_config(drv->lpa, &lpa_config);

	/* Set audio interconnect reg to LPA */
	audio_interct_codec(AUDIO_INTERCT_LPA);

	/* Set MI2S */
	mi2s_set_codec_output_path((icodec->data->channel_mode == 2 ?
	MI2S_CHAN_STEREO : MI2S_CHAN_MONO_PACKED), WT_16_BIT);

	if (icodec->data->voltage_on)
		icodec->data->voltage_on();

	/* Configure ADIE */
	trc = adie_codec_open(icodec->data->profile, &icodec->adie_path);
	if (IS_ERR_VALUE(trc))
		goto error_adie;
	/* OSR default to 256, can be changed for power optimization
	 * If OSR is to be changed, need clock API for setting the divider
	 */
	adie_codec_setpath(icodec->adie_path, icodec->sample_rate, 256);
	/* Start AFE */
	afe_config.sample_rate = icodec->sample_rate / 1000;
	afe_config.channel_mode = icodec->data->channel_mode;
	afe_config.volume = AFE_VOLUME_UNITY;
	trc = afe_enable(AFE_HW_PATH_CODEC_RX, &afe_config);
	if (IS_ERR_VALUE(trc))
		goto error_afe;
	lpa_cmd_enable_codec(drv->lpa, 1);
	/* Enable ADIE */
	adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_READY);
	adie_codec_proceed_stage(icodec->adie_path,
					ADIE_CODEC_DIGITAL_ANALOG_READY);

	/* Enable power amplifier */
	if (icodec->data->pamp_on)
		icodec->data->pamp_on();

	icodec->enabled = 1;

	wake_unlock(&drv->rx_idlelock);
	return 0;

error_afe:
	adie_codec_close(icodec->adie_path);
	icodec->adie_path = NULL;
error_adie:
	lpa_put(drv->lpa);
error_lpa:
	clk_disable(drv->lpa_p_clk);
	clk_disable(drv->lpa_codec_clk);
	clk_disable(drv->lpa_core_clk);
	clk_disable(drv->rx_sclk);
	clk_disable(drv->rx_mclk);
error_invalid_freq:

	MM_ERR("encounter error\n");

	wake_unlock(&drv->rx_idlelock);
	return -ENODEV;
}
static void qcelp_in_listener(u32 evt_id, union auddev_evt_data *evt_payload,
				void *private_data)
{
	struct audio_in *audio = (struct audio_in *) private_data;
	unsigned long flags;

	MM_DBG("evt_id = 0x%8x\n", evt_id);
	switch (evt_id) {
	case AUDDEV_EVT_DEV_RDY: {
		MM_DBG("AUDDEV_EVT_DEV_RDY\n");
		spin_lock_irqsave(&audio->dev_lock, flags);
		audio->dev_cnt++;
		if (!audio->in_call)
			audio->source |= (0x1 << evt_payload->routing_id);
		spin_unlock_irqrestore(&audio->dev_lock, flags);

		if ((audio->running == 1) && (audio->enabled == 1))
			audqcelp_in_record_config(audio, 1);

		break;
	}
	case AUDDEV_EVT_DEV_RLS: {
		MM_DBG("AUDDEV_EVT_DEV_RLS\n");
		spin_lock_irqsave(&audio->dev_lock, flags);
		audio->dev_cnt--;
		if (!audio->in_call)
			audio->source &= ~(0x1 << evt_payload->routing_id);
		spin_unlock_irqrestore(&audio->dev_lock, flags);

		if ((!audio->running) || (!audio->enabled))
			break;

		/* Turn of as per source */
		if (audio->source)
			audqcelp_in_record_config(audio, 1);
		else
			/* Turn off all */
			audqcelp_in_record_config(audio, 0);

		break;
	}
	case AUDDEV_EVT_VOICE_STATE_CHG: {
		MM_DBG("AUDDEV_EVT_VOICE_STATE_CHG, state = %d\n",
				evt_payload->voice_state);
		audio->voice_state = evt_payload->voice_state;
		if (audio->in_call && audio->running) {
			if (audio->voice_state == VOICE_STATE_INCALL)
				audqcelp_in_record_config(audio, 1);
			else if (audio->voice_state == VOICE_STATE_OFFCALL) {
				audqcelp_in_record_config(audio, 0);
				wake_up(&audio->wait);
			}
		}

		break;
	}
	default:
		MM_ERR("wrong event %d\n", evt_id);
		break;
	}
}
static ssize_t audqcelp_in_read(struct file *file,
				char __user *buf,
				size_t count, loff_t *pos)
{
	struct audio_in *audio = file->private_data;
	unsigned long flags;
	const char __user *start = buf;
	void *data;
	uint32_t index;
	uint32_t size;
	int rc = 0;

	mutex_lock(&audio->read_lock);
	while (count > 0) {
		rc = wait_event_interruptible(
#ifdef CONFIG_SH_AUDIO_DRIVER
			audio->wait, (audio->in_count > 0) || audio->stopped || audio->readbreak
#else
			audio->wait, (audio->in_count > 0) || audio->stopped
#endif /* CONFIG_SH_AUDIO_DRIVER */
			|| (audio->in_call && audio->running &&
				(audio->voice_state == VOICE_STATE_OFFCALL)));
		if (rc < 0)
			break;

#ifdef CONFIG_SH_AUDIO_DRIVER
		if (audio->readbreak) {
			rc = -EPERM;
			audio->readbreak = 0;
			break;
		}
#endif /* CONFIG_SH_AUDIO_DRIVER */

		if (!audio->in_count) {
			if (audio->stopped)  {
				rc = 0;/* End of File */
				break;
			} else if (audio->in_call && audio->running &&
				(audio->voice_state == VOICE_STATE_OFFCALL)) {
				MM_DBG("Not Permitted Voice Terminated\n");
				rc = -EPERM; /* Voice Call stopped */
				break;
			}
		}

		index = audio->in_tail;
		data = (uint8_t *) audio->in[index].data;
		size = audio->in[index].size;
		if (count >= size) {
			if (copy_to_user(buf, data, size)) {
				rc = -EFAULT;
				break;
			}
			spin_lock_irqsave(&audio->dsp_lock, flags);
			if (index != audio->in_tail) {
				/* overrun -- data is
				 * invalid and we need to retry */
				spin_unlock_irqrestore(&audio->dsp_lock, flags);
				continue;
			}
			audio->in[index].size = 0;
			audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
			audio->in_count--;
			spin_unlock_irqrestore(&audio->dsp_lock, flags);
			count -= size;
			buf += size;
		} else {
			MM_ERR("short read\n");
			break;
		}
	}
	mutex_unlock(&audio->read_lock);

	if (buf > start)
		return buf - start;

	return rc;
}
Example #6
0
static int msm_reset_put(struct snd_kcontrol *kcontrol,
                         struct snd_ctl_elem_value *ucontrol)
{
    MM_DBG("Resetting all devices\n");
    return msm_reset_all_device();
}
/* ------------------- device --------------------- */
static long audamrnb_in_ioctl(struct file *file,
                              unsigned int cmd, unsigned long arg)
{
    struct audio_in *audio = file->private_data;
    int rc = 0;

    if (cmd == AUDIO_GET_STATS) {
        struct msm_audio_stats stats;
        stats.byte_count = atomic_read(&audio->in_bytes);
        stats.sample_count = atomic_read(&audio->in_samples);
        if (copy_to_user((void *) arg, &stats, sizeof(stats)))
            return -EFAULT;
        return rc;
    }

    mutex_lock(&audio->lock);
    switch (cmd) {
    case AUDIO_START: {
        uint32_t freq;
        freq = 48000;
        MM_DBG("AUDIO_START\n");
        if (audio->in_call && (audio->voice_state !=
                               VOICE_STATE_INCALL)) {
            rc = -EPERM;
            break;
        }
        rc = msm_snddev_request_freq(&freq, audio->enc_id,
                                     SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
        MM_DBG("sample rate configured %d\n", freq);
        if (rc < 0) {
            MM_DBG(" Sample rate can not be set, return code %d\n",
                   rc);
            msm_snddev_withdraw_freq(audio->enc_id,
                                     SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
            MM_DBG("msm_snddev_withdraw_freq\n");
            break;
        }
        rc = audamrnb_in_enable(audio);
        if (!rc) {
            rc =
                wait_event_interruptible_timeout(audio->wait_enable,
                                                 audio->running != 0, 1*HZ);
            MM_DBG("state %d rc = %d\n", audio->running, rc);

            if (audio->running == 0)
                rc = -ENODEV;
            else
                rc = 0;
        }
        audio->stopped = 0;
        break;
    }
    case AUDIO_STOP: {
        rc = audamrnb_in_disable(audio);
        rc = msm_snddev_withdraw_freq(audio->enc_id,
                                      SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
        MM_DBG("msm_snddev_withdraw_freq\n");
        audio->stopped = 1;
        break;
    }
    case AUDIO_FLUSH: {
        if (audio->stopped) {
            /* Make sure we're stopped and we wake any threads
             * that might be blocked holding the read_lock.
             * While audio->stopped read threads will always
             * exit immediately.
             */
            wake_up(&audio->wait);
            mutex_lock(&audio->read_lock);
            audamrnb_in_flush(audio);
            mutex_unlock(&audio->read_lock);
        }
        break;
    }
    case AUDIO_SET_STREAM_CONFIG: {
        struct msm_audio_stream_config cfg;
        if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
            rc = -EFAULT;
            break;
        }
        /* Allow only single frame */
        if (cfg.buffer_size != (FRAME_SIZE - 8))
            rc = -EINVAL;
        else
            audio->buffer_size = cfg.buffer_size;
        break;
    }
    case AUDIO_GET_STREAM_CONFIG: {
        struct msm_audio_stream_config cfg;
        memset(&cfg, 0, sizeof(cfg));
        cfg.buffer_size = audio->buffer_size;
        cfg.buffer_count = FRAME_NUM;
        if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
            rc = -EFAULT;
        break;
    }
    case AUDIO_GET_AMRNB_ENC_CONFIG_V2: {
        struct msm_audio_amrnb_enc_config_v2 cfg;
        memset(&cfg, 0, sizeof(cfg));
        cfg.dtx_enable = ((audio->dtx_mode == -1) ? 1 : 0);
        cfg.band_mode = audio->used_mode;
        cfg.frame_format = audio->frame_format;
        if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
            rc = -EFAULT;
        break;
    }
    case AUDIO_SET_AMRNB_ENC_CONFIG_V2: {
        struct msm_audio_amrnb_enc_config_v2 cfg;
        if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
            rc = -EFAULT;
            break;
        }
        /* DSP does not support any other than default format */
        if (audio->frame_format != cfg.frame_format) {
            rc = -EINVAL;
            break;
        }
        if (cfg.dtx_enable == 0)
            audio->dtx_mode = 0;
        else if (cfg.dtx_enable == 1)
            audio->dtx_mode = -1;
        else {
            rc = -EINVAL;
            break;
        }
        audio->used_mode = cfg.band_mode;
        break;
    }
    case AUDIO_SET_INCALL: {
        struct msm_voicerec_mode cfg;
        unsigned long flags;
        if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
            rc = -EFAULT;
            break;
        }
        if (cfg.rec_mode != VOC_REC_BOTH &&
                cfg.rec_mode != VOC_REC_UPLINK &&
                cfg.rec_mode != VOC_REC_DOWNLINK) {
            pr_aud_err("invalid rec_mode\n");
            rc = -EINVAL;
            break;
        } else {
            spin_lock_irqsave(&audio->dev_lock, flags);
            if (cfg.rec_mode == VOC_REC_UPLINK)
                audio->source = VOICE_UL_SOURCE_MIX_MASK;
            else if (cfg.rec_mode == VOC_REC_DOWNLINK)
                audio->source = VOICE_DL_SOURCE_MIX_MASK;
            else
                audio->source = VOICE_DL_SOURCE_MIX_MASK |
                                VOICE_UL_SOURCE_MIX_MASK ;
            audio->in_call = 1;
            spin_unlock_irqrestore(&audio->dev_lock, flags);
        }
        break;
    }
    case AUDIO_GET_SESSION_ID: {
        if (copy_to_user((void *) arg, &audio->enc_id,
                         sizeof(unsigned short))) {
            rc = -EFAULT;
        }
        break;
    }
    default:
        rc = -EINVAL;
    }
    mutex_unlock(&audio->lock);
    return rc;
}
Example #8
0
int __msm_adsp_write(struct msm_adsp_module *module, unsigned dsp_queue_addr,
		   void *cmd_buf, size_t cmd_size)
{
	uint32_t ctrl_word;
	uint32_t dsp_q_addr;
	uint32_t dsp_addr;
	uint32_t cmd_id = 0;
	int cnt = 0;
	int ret_status = 0;
	unsigned long flags;
	struct adsp_info *info;

	if (!module || !cmd_buf) {
		MM_AUD_ERR("Called with NULL parameters\n");
		return -EINVAL;
	}
	info = module->info;
	spin_lock_irqsave(&adsp_write_lock, flags);

	if (module->state != ADSP_STATE_ENABLED) {
		spin_unlock_irqrestore(&adsp_write_lock, flags);
		MM_AUD_INFO("module %s not enabled before write\n", module->name);
		return -ENODEV;
	}
	if (adsp_validate_module(module->id)) {
		spin_unlock_irqrestore(&adsp_write_lock, flags);
		MM_AUD_ERR("module id validation failed %s  %d\n",
				module->name, module->id);
		return -ENXIO;
	}
	if (dsp_queue_addr >= QDSP_MAX_NUM_QUEUES) {
		spin_unlock_irqrestore(&adsp_write_lock, flags);
		MM_AUD_ERR("Invalid Queue Index: %d\n", dsp_queue_addr);
		return -ENXIO;
	}
	if (adsp_validate_queue(module->id, dsp_queue_addr, cmd_size)) {
		spin_unlock_irqrestore(&adsp_write_lock, flags);
		return -EINVAL;
	}
	dsp_q_addr = adsp_get_queue_offset(info, dsp_queue_addr);
	dsp_q_addr &= ADSP_RTOS_WRITE_CTRL_WORD_DSP_ADDR_M;

	/* Poll until the ADSP is ready to accept a command.
	 * Wait for 100us, return error if it's not responding.
	 * If this returns an error, we need to disable ALL modules and
	 * then retry.
	 */
	while (((ctrl_word = readl(info->write_ctrl)) &
		ADSP_RTOS_WRITE_CTRL_WORD_READY_M) !=
		ADSP_RTOS_WRITE_CTRL_WORD_READY_V) {
		if (cnt > 50) {
			MM_AUD_ERR("timeout waiting for DSP write ready\n");
			ret_status = -EIO;
			BUG();
			goto fail;
		}
		MM_DBG("waiting for DSP write ready\n");
		udelay(2);
		cnt++;
	}

	/* Set the mutex bits */
	ctrl_word &= ~(ADSP_RTOS_WRITE_CTRL_WORD_MUTEX_M);
	ctrl_word |=  ADSP_RTOS_WRITE_CTRL_WORD_MUTEX_NAVAIL_V;

	/* Clear the command bits */
	ctrl_word &= ~(ADSP_RTOS_WRITE_CTRL_WORD_CMD_M);

	/* Set the queue address bits */
	ctrl_word &= ~(ADSP_RTOS_WRITE_CTRL_WORD_DSP_ADDR_M);
	ctrl_word |= dsp_q_addr;

	writel(ctrl_word, info->write_ctrl);

	/* Generate an interrupt to the DSP.  This notifies the DSP that
	 * we are about to send a command on this particular queue.  The
	 * DSP will in response change its state.
	 */
	writel(1, info->send_irq);

	/* Poll until the adsp responds to the interrupt; this does not
	 * generate an interrupt from the adsp.  This should happen within
	 * 5ms.
	 */
	cnt = 0;
	while ((readl(info->write_ctrl) &
		ADSP_RTOS_WRITE_CTRL_WORD_MUTEX_M) ==
		ADSP_RTOS_WRITE_CTRL_WORD_MUTEX_NAVAIL_V) {
		if (cnt > 2500) {
			MM_AUD_ERR("timeout waiting for adsp ack\n");
			ret_status = -EIO;
			BUG();
			goto fail;
		}
		udelay(2);
		cnt++;
	}

	/* Read the ctrl word */
	ctrl_word = readl(info->write_ctrl);

	if ((ctrl_word & ADSP_RTOS_WRITE_CTRL_WORD_STATUS_M) !=
	    ADSP_RTOS_WRITE_CTRL_WORD_NO_ERR_V) {
		ret_status = -EAGAIN;
		goto fail;
	} else {
		/* No error */
		/* Get the DSP buffer address */
		dsp_addr = (ctrl_word & ADSP_RTOS_WRITE_CTRL_WORD_DSP_ADDR_M) +
			   (uint32_t)MSM_AD5_BASE;

		if (dsp_addr < (uint32_t)(MSM_AD5_BASE + QDSP_RAMC_OFFSET)) {
			uint16_t *buf_ptr = (uint16_t *) cmd_buf;
			uint16_t *dsp_addr16 = (uint16_t *)dsp_addr;
			cmd_size /= sizeof(uint16_t);

			/* Save the command ID */
			cmd_id = (uint32_t) buf_ptr[0];

			/* Copy the command to DSP memory */
			cmd_size++;
			while (--cmd_size)
				*dsp_addr16++ = *buf_ptr++;
		} else {
			uint32_t *buf_ptr = (uint32_t *) cmd_buf;
			uint32_t *dsp_addr32 = (uint32_t *)dsp_addr;
			cmd_size /= sizeof(uint32_t);

			/* Save the command ID */
			cmd_id = buf_ptr[0];

			cmd_size++;
			while (--cmd_size)
				*dsp_addr32++ = *buf_ptr++;
		}

		/* Set the mutex bits */
		ctrl_word &= ~(ADSP_RTOS_WRITE_CTRL_WORD_MUTEX_M);
		ctrl_word |=  ADSP_RTOS_WRITE_CTRL_WORD_MUTEX_NAVAIL_V;

		/* Set the command bits to write done */
		ctrl_word &= ~(ADSP_RTOS_WRITE_CTRL_WORD_CMD_M);
		ctrl_word |= ADSP_RTOS_WRITE_CTRL_WORD_CMD_WRITE_DONE_V;

		/* Set the queue address bits */
		ctrl_word &= ~(ADSP_RTOS_WRITE_CTRL_WORD_DSP_ADDR_M);
		ctrl_word |= dsp_q_addr;

		writel(ctrl_word, info->write_ctrl);

		/* Generate an interrupt to the DSP.  It does not respond with
		 * an interrupt, and we do not need to wait for it to
		 * acknowledge, because it will hold the mutex lock until it's
		 * ready to receive more commands again.
		 */
		writel(1, info->send_irq);

		module->num_commands++;
	} /* Ctrl word status bits were 00, no error in the ctrl word */

fail:
	spin_unlock_irqrestore(&adsp_write_lock, flags);
	return ret_status;
}
/* ------------------- dsp preproc event handler--------------------- */
static void audpreproc_dsp_event(void *data, unsigned id,  void *msg)
{
	struct audio_in *audio = data;

	switch (id) {
	case AUDPREPROC_ERROR_MSG: {
		struct audpreproc_err_msg *err_msg = msg;

		MM_ERR("ERROR_MSG: stream id %d err idx %d\n",
		err_msg->stream_id, err_msg->aud_preproc_err_idx);
		/* Error case */
		wake_up(&audio->wait_enable);
		break;
	}
	case AUDPREPROC_CMD_CFG_DONE_MSG: {
		MM_DBG("CMD_CFG_DONE_MSG \n");
		break;
	}
	case AUDPREPROC_CMD_ENC_CFG_DONE_MSG: {
		struct audpreproc_cmd_enc_cfg_done_msg *enc_cfg_msg = msg;

		MM_DBG("CMD_ENC_CFG_DONE_MSG: stream id %d enc type \
			0x%8x\n", enc_cfg_msg->stream_id,
			enc_cfg_msg->rec_enc_type);
		/* Encoder enable success */
		if (enc_cfg_msg->rec_enc_type & ENCODE_ENABLE) {
			if(audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
				MM_DBG("routing command\n");
				audpreproc_cmd_cfg_routing_mode(audio);
			} else {
				audevrc_in_param_config(audio);
			}
		} else { /* Encoder disable success */
			audio->running = 0;
			if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
				audevrc_in_record_config(audio, 0);
			else
				wake_up(&audio->wait_enable);
		}
		break;
	}
	case AUDPREPROC_CMD_ENC_PARAM_CFG_DONE_MSG: {
		MM_DBG("CMD_ENC_PARAM_CFG_DONE_MSG\n");
		if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
			audevrc_in_mem_config(audio);
		else
			audpcm_config(audio);
		break;
	}
	case AUDPREPROC_CMD_ROUTING_MODE_DONE_MSG: {
		struct audpreproc_cmd_routing_mode_done\
				*routing_cfg_done_msg = msg;
		if (routing_cfg_done_msg->configuration == 0) {
			MM_INFO("routing configuration failed\n");
			audio->running = 0;
		} else
			audevrc_in_param_config(audio);
		break;
	}
	case AUDPREPROC_AFE_CMD_AUDIO_RECORD_CFG_DONE_MSG: {
		MM_DBG("AFE_CMD_AUDIO_RECORD_CFG_DONE_MSG \n");
		wake_up(&audio->wait_enable);
		break;
	}
	default:
		MM_ERR("Unknown Event id %d\n", id);
	}
}
static int snddev_ecodec_open_rx(struct snddev_ecodec_state *ecodec)
{
	int rc = 0;
	struct snddev_ecodec_drv_state *drv = &snddev_ecodec_drv;
	struct msm_afe_config afe_config;
	int ret = 0;

	MM_DBG("snddev_ecodec_open_rx\n");

	if (!drv->tx_active) {
		/* request GPIO */
		rc = aux_pcm_gpios_request();
		if (rc) {
			MM_ERR("GPIO enable failed\n");
			goto done;
		}
		/* config clocks */
		clk_enable(drv->lpa_core_clk);

		/*if long sync is selected in aux PCM interface
		ecodec clock is updated to work with 128KHz,
		if short sync is selected ecodec clock is updated to
		work with 2.048MHz frequency, actual clock output is
		different than the SW configuration by factor of two*/
		if (!(ecodec->data->conf_aux_codec_intf &
			AUX_CODEC_CTL__AUX_CODEC_MODE__I2S_V)) {
			if (ecodec->data->conf_aux_codec_intf &
				AUX_CODEC_CTL__AUX_PCM_MODE__AUX_MASTER_V) {
				MM_DBG("Update ecodec clock to 128 KHz, long "
					"sync in master mode is selected\n");
				ret = clk_set_rate(drv->ecodec_clk, 256000);
				if (ret < 0)
					MM_ERR("Error updating ecodec clock"
							" to 128KHz\n");
			} else if (ecodec->data->conf_aux_codec_intf &
				AUX_CODEC_CTL__AUX_PCM_MODE__PRIM_SLAVE_V) {
				MM_DBG("Update ecodec clock to 2 MHz, short"
					" sync in slave mode is selected\n");
				ret = clk_set_rate(drv->ecodec_clk, 4096000);
				if (ret < 0)
					MM_ERR("Error updating ecodec clock"
							" to 2.048MHz\n");
			} else {
				MM_DBG("Update ecodec clock to 2 MHz, short"
					" sync in master mode is selected\n");
				ret = clk_set_rate(drv->ecodec_clk, 4096000);
				if (ret < 0)
					MM_ERR("Error updating ecodec clock"
							" to 2.048MHz\n");
			}
		}

		/* enable ecodec clk */
		clk_enable(drv->ecodec_clk);

		/* let ADSP confiure AUX PCM regs */
		aux_codec_adsp_codec_ctl_en(ADSP_CTL);

		/* let adsp configure pcm path */
		aux_codec_pcm_path_ctl_en(ADSP_CTL);

		/* choose ADSP_A */
		audio_interct_aux_regsel(AUDIO_ADSP_A);
		audio_interct_tpcm_source(AUDIO_ADSP_A);
		audio_interct_rpcm_source(AUDIO_ADSP_A);

		clk_disable(drv->lpa_core_clk);

		/* send AUX_CODEC_CONFIG to AFE */
		rc = afe_config_aux_codec(ecodec->data->conf_pcm_ctl_val,
				ecodec->data->conf_aux_codec_intf,
				ecodec->data->conf_data_format_padding_val);
		if (IS_ERR_VALUE(rc))
			goto error;
	}
	/* send CODEC CONFIG to AFE */
	afe_config.sample_rate = ecodec->sample_rate / 1000;
	afe_config.channel_mode = ecodec->data->channel_mode;
	afe_config.volume = AFE_VOLUME_UNITY;
	rc = afe_enable(AFE_HW_PATH_AUXPCM_RX, &afe_config);
	if (IS_ERR_VALUE(rc)) {
		if (!drv->tx_active) {
			aux_pcm_gpios_free();
			clk_disable(drv->ecodec_clk);
		}
		goto done;
	}

	ecodec->enabled = 1;
	return 0;

error:
	aux_pcm_gpios_free();
	clk_disable(drv->ecodec_clk);
done:
	return rc;
}
Example #11
0
static int audamrnb_in_open(struct inode *inode, struct file *file)
{
	struct audio_in *audio = &the_audio_amrnb_in;
	int rc;
	int encid;
	int len = 0;
	unsigned long ionflag = 0;
	ion_phys_addr_t addr = 0;
	struct ion_handle *handle = NULL;
	struct ion_client *client = NULL;

	mutex_lock(&audio->lock);
	if (audio->opened) {
		rc = -EBUSY;
		goto done;
	}

	client = msm_ion_client_create(UINT_MAX, "Audio_AMR_In_Client");
	if (IS_ERR_OR_NULL(client)) {
		MM_ERR("Unable to create ION client\n");
		rc = -ENOMEM;
		goto client_create_error;
	}
	audio->client = client;

	handle = ion_alloc(client, DMASZ, SZ_4K,
		ION_HEAP(ION_AUDIO_HEAP_ID),0);
	if (IS_ERR_OR_NULL(handle)) {
		MM_ERR("Unable to create allocate O/P buffers\n");
		rc = -ENOMEM;
		goto buff_alloc_error;
	}
	audio->buff_handle = handle;

	rc = ion_phys(client, handle, &addr, &len);
	if (rc) {
		MM_ERR("O/P buffers:Invalid phy: %x sz: %x\n",
			(unsigned int) addr, (unsigned int) len);
		goto buff_get_phys_error;
	} else {
		MM_INFO("O/P buffers:valid phy: %x sz: %x\n",
			(unsigned int) addr, (unsigned int) len);
	}
	audio->phys = (int32_t)addr;

	rc = ion_handle_get_flags(client, handle, &ionflag);
	if (rc) {
		MM_ERR("could not get flags for the handle\n");
		goto buff_get_flags_error;
	}

	audio->map_v_read = ion_map_kernel(client, handle);
	if (IS_ERR(audio->map_v_read)) {
		MM_ERR("could not map write buffers\n");
		rc = -ENOMEM;
		goto buff_map_error;
	}
	audio->data = audio->map_v_read;
	MM_DBG("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
		audio->phys, (int)audio->data);

	MM_DBG("Memory addr = 0x%8x  phy addr = 0x%8x\n",\
		(int) audio->data, (int) audio->phys);
	if ((file->f_mode & FMODE_WRITE) &&
			(file->f_mode & FMODE_READ)) {
		rc = -EACCES;
		MM_ERR("Non tunnel encoding is not supported\n");
		goto buff_map_error;
	} else if (!(file->f_mode & FMODE_WRITE) &&
					(file->f_mode & FMODE_READ)) {
		audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
		MM_DBG("Opened for tunnel mode encoding\n");
	} else {
		rc = -EACCES;
		goto buff_map_error;
	}


	/* Settings will be re-config at AUDIO_SET_CONFIG,
	 * but at least we need to have initial config
	 */
	audio->buffer_size = (FRAME_SIZE - 8);
	audio->enc_type = ENC_TYPE_AMRNB | audio->mode;
	audio->dtx_mode = -1;
	audio->frame_format = 0;
	audio->used_mode = 7; /* Bit Rate 12.2 kbps MR122 */

	encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
			&audio->queue_ids);
	if (encid < 0) {
		MM_ERR("No free encoder available\n");
		rc = -ENODEV;
		goto aenc_alloc_error;
	}
	audio->enc_id = encid;

	rc = msm_adsp_get(audio->module_name, &audio->audrec,
			   &audrec_amrnb_adsp_ops, audio);

	if (rc) {
		audpreproc_aenc_free(audio->enc_id);
		goto aenc_alloc_error;
	}

	audio->stopped = 0;
	audio->source = 0;

	audamrnb_in_flush(audio);

	audio->device_events = AUDDEV_EVT_DEV_RDY | AUDDEV_EVT_DEV_RLS |
				AUDDEV_EVT_VOICE_STATE_CHG;

	audio->voice_state = msm_get_voice_state();
	rc = auddev_register_evt_listner(audio->device_events,
					AUDDEV_CLNT_ENC, audio->enc_id,
					amrnb_in_listener, (void *) audio);
	if (rc) {
		MM_ERR("failed to register device event listener\n");
		goto evt_error;
	}
	audio->build_id = socinfo_get_build_id();
	MM_DBG("Modem build id = %s\n", audio->build_id);

	file->private_data = audio;
	audio->opened = 1;
	mutex_unlock(&audio->lock);
	return rc;
evt_error:
	msm_adsp_put(audio->audrec);
	audpreproc_aenc_free(audio->enc_id);
	ion_unmap_kernel(client, audio->buff_handle);
aenc_alloc_error:
buff_map_error:
buff_get_phys_error:
buff_get_flags_error:
	ion_free(client, audio->buff_handle);
buff_alloc_error:
	ion_client_destroy(client);
client_create_error:
done:
	mutex_unlock(&audio->lock);
	return rc;
}
/* session id is 32 bit routing mask per device
 * 0-7 for voice clients
 * 8-15 for Decoder clients
 * 16-23 for Encoder clients
 * 24-31 Do not care
 */
void broadcast_event(u32 evt_id, u32 dev_id, u32 session_id)
{
	int clnt_id = 0;
	union auddev_evt_data *evt_payload;
	struct msm_snd_evt_listner *callback;
	struct msm_snddev_info *dev_info = NULL;
	u32 session_mask = 0;
	static int pending_sent;

	MM_DBG(": evt_id = %d\n", evt_id);

	if ((evt_id != AUDDEV_EVT_START_VOICE)
		&& (evt_id != AUDDEV_EVT_END_VOICE)
		&& (evt_id != AUDDEV_EVT_STREAM_VOL_CHG)) {
		dev_info = audio_dev_ctrl_find_dev(dev_id);
		if (IS_ERR(dev_info))
			return;
	}

	if (event.cb != NULL)
		callback = event.cb;
	else
		return;
	mutex_lock(&session_lock);

	evt_payload = kzalloc(sizeof(union auddev_evt_data),
			GFP_KERNEL);

	if (!evt_payload) {
		MM_AUD_ERR("%s: fail to allocate memory\n", __func__);
		return;
	}

	for (; ;) {
		if (!(evt_id & callback->evt_id)) {
			if (callback->cb_next == NULL)
				break;
			else {
				callback = callback->cb_next;
				continue;
			}
		}
		clnt_id = callback->clnt_id;
		memset(evt_payload, 0, sizeof(union auddev_evt_data));

		if ((evt_id == AUDDEV_EVT_START_VOICE)
			|| (evt_id == AUDDEV_EVT_END_VOICE))
			goto skip_check;
		if (callback->clnt_type == AUDDEV_CLNT_AUDIOCAL)
			goto aud_cal;

		session_mask = (0x1 << (clnt_id))
				<< (8 * ((int)callback->clnt_type-1));

		if (evt_id == AUDDEV_EVT_STREAM_VOL_CHG) {
			MM_DBG("AUDDEV_EVT_STREAM_VOL_CHG\n");
			goto volume_strm;
		}

		MM_DBG("dev_info->sessions = %08x\n", dev_info->sessions);

		if ((!session_id && !(dev_info->sessions & session_mask)) ||
			(session_id && ((dev_info->sessions & session_mask) !=
						session_id))) {
			if (callback->cb_next == NULL)
				break;
			else {
				callback = callback->cb_next;
				continue;
			}
		}
		if (evt_id == AUDDEV_EVT_DEV_CHG_VOICE)
			goto voc_events;

volume_strm:
		if (callback->clnt_type == AUDDEV_CLNT_DEC) {
			MM_DBG("AUDDEV_CLNT_DEC\n");
			if (evt_id == AUDDEV_EVT_STREAM_VOL_CHG) {
				MM_DBG("clnt_id = %d, session_id = 0x%8x\n",
					clnt_id, session_id);
				if (session_mask != session_id)
					goto sent_dec;
				else
					evt_payload->session_vol =
						msm_vol_ctl.volume;
			} else if (evt_id == AUDDEV_EVT_FREQ_CHG) {
				if (routing_info.dec_freq[clnt_id].evt) {
					routing_info.dec_freq[clnt_id].evt
							= 0;
					goto sent_dec;
				} else if (routing_info.dec_freq[clnt_id].freq
					== dev_info->set_sample_rate)
					goto sent_dec;
				else {
					evt_payload->freq_info.sample_rate
						= dev_info->set_sample_rate;
					evt_payload->freq_info.dev_type
						= dev_info->capability;
					evt_payload->freq_info.acdb_dev_id
						= dev_info->acdb_id;
				}
			} else
				evt_payload->routing_id = dev_info->copp_id;
			callback->auddev_evt_listener(
					evt_id,
					evt_payload,
					callback->private_data);
sent_dec:
			if (evt_id != AUDDEV_EVT_STREAM_VOL_CHG)
				routing_info.dec_freq[clnt_id].freq
						= dev_info->set_sample_rate;

			if (callback->cb_next == NULL)
				break;
			else {
				callback = callback->cb_next;
				continue;
			}
		}
		if (callback->clnt_type == AUDDEV_CLNT_ENC) {
			MM_DBG("AUDDEV_CLNT_ENC\n");
			if (evt_id == AUDDEV_EVT_FREQ_CHG) {
				if (routing_info.enc_freq[clnt_id].evt) {
					routing_info.enc_freq[clnt_id].evt
							= 0;
					goto sent_enc;
				 } else {
					evt_payload->freq_info.sample_rate
						= dev_info->set_sample_rate;
					evt_payload->freq_info.dev_type
						= dev_info->capability;
					evt_payload->freq_info.acdb_dev_id
						= dev_info->acdb_id;
				}
			} else if (dev_info != NULL)
				evt_payload->routing_id = dev_info->copp_id;
			callback->auddev_evt_listener(
					evt_id,
					evt_payload,
					callback->private_data);
sent_enc:
			if (callback->cb_next == NULL)
					break;
			else {
				callback = callback->cb_next;
				continue;
			}
		}
aud_cal:
		if (callback->clnt_type == AUDDEV_CLNT_AUDIOCAL) {
			MM_DBG("AUDDEV_CLNT_AUDIOCAL\n");
			if (!dev_info->sessions)
				goto sent_aud_cal;
			evt_payload->audcal_info.dev_id = dev_info->copp_id;
			evt_payload->audcal_info.acdb_id =
				dev_info->acdb_id;
			evt_payload->audcal_info.dev_type =
				(dev_info->capability & SNDDEV_CAP_TX) ?
				SNDDEV_CAP_TX : SNDDEV_CAP_RX;
			evt_payload->audcal_info.sample_rate =
				dev_info->set_sample_rate ?
				dev_info->set_sample_rate :
				dev_info->sample_rate;

			callback->auddev_evt_listener(
				evt_id,
				evt_payload,
				callback->private_data);

sent_aud_cal:
			if (callback->cb_next == NULL)
				break;
			else {
				callback = callback->cb_next;
				continue;
			}
		}
skip_check:
voc_events:
		if (callback->clnt_type == AUDDEV_CLNT_VOC) {
			MM_DBG("AUDDEV_CLNT_VOC\n");
			if (evt_id == AUDDEV_EVT_DEV_RLS) {
				if (!pending_sent)
					goto sent_voc;
				else
					pending_sent = 0;
			}
			if (evt_id == AUDDEV_EVT_REL_PENDING)
				pending_sent = 1;

			if (evt_id == AUDDEV_EVT_DEVICE_VOL_MUTE_CHG) {
				if (dev_info->capability & SNDDEV_CAP_TX) {
					evt_payload->voc_vm_info.dev_type =
						SNDDEV_CAP_TX;
					evt_payload->voc_vm_info.acdb_dev_id =
						dev_info->acdb_id;
					evt_payload->
					voc_vm_info.dev_vm_val.mute =
						routing_info.tx_mute;
				} else {
					evt_payload->voc_vm_info.dev_type =
						SNDDEV_CAP_RX;
					evt_payload->voc_vm_info.acdb_dev_id =
						dev_info->acdb_id;
					if (routing_info.rx_mute == 1) /*mute rx*/
						evt_payload->
							voc_vm_info.dev_vm_val.mute =
								routing_info.rx_mute;
					else
						evt_payload->
							voc_vm_info.dev_vm_val.vol =
								routing_info.voice_rx_vol;
				}
			} else if ((evt_id == AUDDEV_EVT_START_VOICE)
					|| (evt_id == AUDDEV_EVT_END_VOICE))
				memset(evt_payload, 0,
					sizeof(union auddev_evt_data));
			else if (evt_id == AUDDEV_EVT_FREQ_CHG) {
				if (routing_info.voice_tx_sample_rate
						!= dev_info->set_sample_rate) {
					routing_info.voice_tx_sample_rate
						= dev_info->set_sample_rate;
					evt_payload->freq_info.sample_rate
						= dev_info->set_sample_rate;
					evt_payload->freq_info.dev_type
						= dev_info->capability;
					evt_payload->freq_info.acdb_dev_id
						= dev_info->acdb_id;
				} else
					goto sent_voc;
			} else {
				evt_payload->voc_devinfo.dev_type =
					(dev_info->capability & SNDDEV_CAP_TX) ?
					SNDDEV_CAP_TX : SNDDEV_CAP_RX;
				evt_payload->voc_devinfo.acdb_dev_id =
					dev_info->acdb_id;
				evt_payload->voc_devinfo.dev_sample =
					dev_info->set_sample_rate ?
					dev_info->set_sample_rate :
					dev_info->sample_rate;
				evt_payload->voc_devinfo.dev_id = dev_id;
				if (dev_info->capability & SNDDEV_CAP_RX)
					evt_payload->voc_devinfo.vol_idx = dev_info->vol_idx;
			}
			callback->auddev_evt_listener(
				evt_id,
				evt_payload,
				callback->private_data);
			if (evt_id == AUDDEV_EVT_DEV_RLS)
				dev_info->sessions &= ~(0xFF);
sent_voc:
			if (callback->cb_next == NULL)
				break;
			else {
				callback = callback->cb_next;
				continue;
			}
		}
	}
	kfree(evt_payload);
	mutex_unlock(&session_lock);
}
static int audio_dev_ctrl_release(struct inode *inode, struct file *file)
{
	MM_DBG("release audio_dev_ctrl\n");
	atomic_dec(&audio_dev_ctrl.opened);
	return 0;
}
static int audio_dev_ctrl_ioctl(struct inode *inode, struct file *file,
	unsigned int cmd, unsigned long arg)
{
	int rc = 0;
	struct audio_dev_ctrl_state *dev_ctrl = file->private_data;

	mutex_lock(&session_lock);
	switch (cmd) {
	case AUDIO_GET_NUM_SND_DEVICE:
		rc = put_user(dev_ctrl->num_dev, (uint32_t __user *) arg);
		break;
	case AUDIO_GET_SND_DEVICES:
		rc = audio_dev_ctrl_get_devices(dev_ctrl, (void __user *) arg);
		break;
	case AUDIO_ENABLE_SND_DEVICE: {
		struct msm_snddev_info *dev_info;
		u32 dev_id;

		if (get_user(dev_id, (u32 __user *) arg)) {
			rc = -EFAULT;
			break;
		}
		dev_info = audio_dev_ctrl_find_dev(dev_id);
		if (IS_ERR(dev_info))
			rc = PTR_ERR(dev_info);
		else {
			rc = dev_info->dev_ops.open(dev_info);
			if (!rc)
				dev_info->opened = 1;
			wake_up(&audio_dev_ctrl.wait);
		}
		break;

	}

	case AUDIO_DISABLE_SND_DEVICE: {
		struct msm_snddev_info *dev_info;
		u32 dev_id;

		if (get_user(dev_id, (u32 __user *) arg)) {
			rc = -EFAULT;
			break;
		}
		dev_info = audio_dev_ctrl_find_dev(dev_id);
		if (IS_ERR(dev_info))
			rc = PTR_ERR(dev_info);
		else {
			rc = dev_info->dev_ops.close(dev_info);
			dev_info->opened = 0;
		}
		break;
	}

	case AUDIO_ROUTE_STREAM: {
		struct msm_audio_route_config route_cfg;
		struct msm_snddev_info *dev_info;

		if (copy_from_user(&route_cfg, (void __user *) arg,
			sizeof(struct msm_audio_route_config))) {
			rc = -EFAULT;
			break;
		}
		MM_DBG("%s: route cfg %d %d type\n", __func__,
		route_cfg.dev_id, route_cfg.stream_type);
		dev_info = audio_dev_ctrl_find_dev(route_cfg.dev_id);
		if (IS_ERR(dev_info)) {
			MM_AUD_ERR("%s: pass invalid dev_id\n", __func__);
			rc = PTR_ERR(dev_info);
			break;
		}

		switch (route_cfg.stream_type) {

		case AUDIO_ROUTE_STREAM_VOICE_RX:
			if (!(dev_info->capability & SNDDEV_CAP_RX) |
			    !(dev_info->capability & SNDDEV_CAP_VOICE)) {
				rc = -EINVAL;
				break;
			}
			dev_ctrl->voice_rx_dev = dev_info;
			break;
		case AUDIO_ROUTE_STREAM_VOICE_TX:
			if (!(dev_info->capability & SNDDEV_CAP_TX) |
			    !(dev_info->capability & SNDDEV_CAP_VOICE)) {
				rc = -EINVAL;
				break;
			}
			dev_ctrl->voice_tx_dev = dev_info;
			break;
		}
		break;
	}

	default:
		rc = -EINVAL;
	}
	mutex_unlock(&session_lock);
	return rc;
}
Example #15
0
static int msm_voice_put(struct snd_kcontrol *kcontrol,
                         struct snd_ctl_elem_value *ucontrol)
{
    int rc = 0;
    uint32_t rx_dev_id;
    uint32_t tx_dev_id;
    struct msm_snddev_info *rx_dev_info;
    struct msm_snddev_info *tx_dev_info;
    int set = ucontrol->value.integer.value[2];
    u32 session_mask;

    if (!set)
        return -EPERM;
    /* Rx Device Routing */
    rx_dev_id = ucontrol->value.integer.value[0];
    rx_dev_info = audio_dev_ctrl_find_dev(rx_dev_id);

    if (IS_ERR(rx_dev_info)) {
        MM_ERR("pass invalid dev_id\n");
        rc = PTR_ERR(rx_dev_info);
        return rc;
    }

    if (!(rx_dev_info->capability & SNDDEV_CAP_RX)) {
        MM_ERR("First Dev is supposed to be RX\n");
        return -EFAULT;
    }

    MM_DBG("route cfg %d STREAM_VOICE_RX type\n",
           rx_dev_id);

    msm_set_voc_route(rx_dev_info, AUDIO_ROUTE_STREAM_VOICE_RX,
                      rx_dev_id);

    session_mask =	0x1 << (8 * ((int)AUDDEV_CLNT_VOC-1));

    broadcast_event(AUDDEV_EVT_DEV_CHG_VOICE, rx_dev_id, session_mask);


    /* Tx Device Routing */
    tx_dev_id = ucontrol->value.integer.value[1];
    tx_dev_info = audio_dev_ctrl_find_dev(tx_dev_id);

    if (IS_ERR(tx_dev_info)) {
        MM_ERR("pass invalid dev_id\n");
        rc = PTR_ERR(tx_dev_info);
        return rc;
    }

    if (!(tx_dev_info->capability & SNDDEV_CAP_TX)) {
        MM_ERR("Second Dev is supposed to be Tx\n");
        return -EFAULT;
    }

    MM_DBG("route cfg %d %d type\n",
           tx_dev_id, AUDIO_ROUTE_STREAM_VOICE_TX);

    msm_set_voc_route(tx_dev_info, AUDIO_ROUTE_STREAM_VOICE_TX,
                      tx_dev_id);

    broadcast_event(AUDDEV_EVT_DEV_CHG_VOICE, tx_dev_id, session_mask);

    if (rx_dev_info->opened)
        broadcast_event(AUDDEV_EVT_DEV_RDY, rx_dev_id,	session_mask);

    if (tx_dev_info->opened)
        broadcast_event(AUDDEV_EVT_DEV_RDY, tx_dev_id, session_mask);

    return rc;
}
/* ------------------- dsp audrec event handler--------------------- */
static void audrec_dsp_event(void *data, unsigned id, size_t len,
			    void (*getevent)(void *ptr, size_t len))
{
	struct audio_in *audio = data;

	switch (id) {
	case AUDREC_CMD_MEM_CFG_DONE_MSG: {
		MM_DBG("CMD_MEM_CFG_DONE MSG DONE\n");
		audio->running = 1;
		if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
			if ((!audio->in_call && (audio->dev_cnt > 0)) ||
				(audio->in_call &&
					(audio->voice_state \
						== VOICE_STATE_INCALL)))
				audevrc_in_record_config(audio, 1);
		} else {
			audpreproc_pcm_send_data(audio, 1);
			wake_up(&audio->wait_enable);
		}
		break;
	}
	case AUDREC_FATAL_ERR_MSG: {
		struct audrec_fatal_err_msg fatal_err_msg;

		getevent(&fatal_err_msg, AUDREC_FATAL_ERR_MSG_LEN);
		MM_ERR("FATAL_ERR_MSG: err id %d\n",
				fatal_err_msg.audrec_err_id);
		/* Error stop the encoder */
		audio->stopped = 1;
		wake_up(&audio->wait);
		if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
			wake_up(&audio->write_wait);
		break;
	}
	case AUDREC_UP_PACKET_READY_MSG: {
		struct audrec_up_pkt_ready_msg pkt_ready_msg;

		getevent(&pkt_ready_msg, AUDREC_UP_PACKET_READY_MSG_LEN);
		MM_DBG("UP_PACKET_READY_MSG: write cnt lsw  %d \
		write cnt msw %d read cnt lsw %d  read cnt msw %d \n",\
		pkt_ready_msg.audrec_packet_write_cnt_lsw, \
		pkt_ready_msg.audrec_packet_write_cnt_msw, \
		pkt_ready_msg.audrec_up_prev_read_cnt_lsw, \
		pkt_ready_msg.audrec_up_prev_read_cnt_msw);

		audevrc_in_get_dsp_frames(audio);
		break;
	}
	case AUDREC_CMD_PCM_BUFFER_PTR_UPDATE_ARM_TO_ENC_MSG: {
		MM_DBG("ptr_update recieved from DSP\n");
		audpreproc_pcm_send_data(audio, 1);
		break;
	}
	case AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG: {
		MM_ERR("AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG");
		audevrc_in_mem_config(audio);
		break;
	}
	case AUDREC_UP_NT_PACKET_READY_MSG: {
		struct audrec_up_nt_packet_ready_msg pkt_ready_msg;

		getevent(&pkt_ready_msg, AUDREC_UP_NT_PACKET_READY_MSG_LEN);
		MM_DBG("UP_NT_PACKET_READY_MSG: write cnt lsw  %d \
		write cnt msw %d read cnt lsw %d  read cnt msw %d \n",\
		pkt_ready_msg.audrec_packetwrite_cnt_lsw, \
		pkt_ready_msg.audrec_packetwrite_cnt_msw, \
		pkt_ready_msg.audrec_upprev_readcount_lsw, \
		pkt_ready_msg.audrec_upprev_readcount_msw);

		audevrc_nt_in_get_dsp_frames(audio);
		break;
	}
	case AUDREC_CMD_EOS_ACK_MSG: {
		MM_DBG("eos ack recieved\n");
		break;
	}
	case AUDREC_CMD_FLUSH_DONE_MSG: {
		audio->wflush = 0;
		audio->rflush = 0;
		audio->flush_ack = 1;
		wake_up(&audio->write_wait);
		MM_DBG("flush ack recieved\n");
		break;
	}
	case ADSP_MESSAGE_ID: {
		MM_DBG("Received ADSP event:module audrectask\n");
		break;
	}
	default:
		MM_ERR("Unknown Event id %d\n", id);
	}
}
Example #17
0
static int msm_route_put(struct snd_kcontrol *kcontrol,
                         struct snd_ctl_elem_value *ucontrol)
{
    int rc = 0;
    int enc_freq = 0;
    int requested_freq = 0;
    struct msm_audio_route_config route_cfg;
    struct msm_snddev_info *dev_info;
    int session_id = ucontrol->value.integer.value[0];
    int set = ucontrol->value.integer.value[2];
    u32 session_mask = 0;
    route_cfg.dev_id = ucontrol->value.integer.value[1];

    if (ucontrol->id.numid == 2)
        route_cfg.stream_type =	AUDIO_ROUTE_STREAM_PLAYBACK;
    else
        route_cfg.stream_type =	AUDIO_ROUTE_STREAM_REC;

    MM_DBG("route cfg %d %d type for popp %d set value %d\n",
           route_cfg.dev_id, route_cfg.stream_type, session_id, set);
    dev_info = audio_dev_ctrl_find_dev(route_cfg.dev_id);

    if (IS_ERR(dev_info)) {
        MM_ERR("pass invalid dev_id\n");
        rc = PTR_ERR(dev_info);
        return rc;
    }
    if (route_cfg.stream_type == AUDIO_ROUTE_STREAM_PLAYBACK) {
        rc = msm_snddev_set_dec(session_id, dev_info->copp_id, set);
        session_mask =
            (0x1 << (session_id) << (8 * ((int)AUDDEV_CLNT_DEC-1)));
        if (!set) {
            if (dev_info->opened) {
                broadcast_event(AUDDEV_EVT_REL_PENDING,
                                route_cfg.dev_id,
                                session_mask);

                broadcast_event(AUDDEV_EVT_DEV_RLS,
                                route_cfg.dev_id,
                                session_mask);
            }
            dev_info->sessions &= ~(session_mask);
        } else {
            dev_info->sessions = dev_info->sessions | session_mask;
            if (dev_info->opened) {
                broadcast_event(AUDDEV_EVT_DEV_RDY,
                                route_cfg.dev_id,
                                session_mask);
                /* Event to notify client for device info */
                broadcast_event(AUDDEV_EVT_DEVICE_INFO,
                                route_cfg.dev_id,
                                session_mask);
            }
        }
    } else {
        rc = msm_snddev_set_enc(session_id, dev_info->copp_id, set);
        session_mask =
            (0x1 << (session_id)) << (8 * ((int)AUDDEV_CLNT_ENC-1));
        if (!set) {
            if (dev_info->opened)
                broadcast_event(AUDDEV_EVT_DEV_RLS,
                                route_cfg.dev_id,
                                session_mask);
            dev_info->sessions &= ~(session_mask);
        } else {
            dev_info->sessions = dev_info->sessions | session_mask;
            enc_freq = msm_snddev_get_enc_freq(session_id);
            requested_freq = enc_freq;
            if (enc_freq > 0) {
                rc = msm_snddev_request_freq(&enc_freq,
                                             session_id,
                                             SNDDEV_CAP_TX,
                                             AUDDEV_CLNT_ENC);
                MM_DBG("sample rate configured %d"
                       "sample rate requested %d\n",
                       enc_freq, requested_freq);
                if ((rc <= 0) || (enc_freq != requested_freq)) {
                    MM_DBG("msm_snddev_withdraw_freq\n");
                    rc = msm_snddev_withdraw_freq
                         (session_id,
                          SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
                    broadcast_event(AUDDEV_EVT_FREQ_CHG,
                                    route_cfg.dev_id,
                                    SESSION_IGNORE);
                }
            }
            if (dev_info->opened) {
                broadcast_event(AUDDEV_EVT_DEV_RDY,
                                route_cfg.dev_id,
                                session_mask);
                /* Event to notify client for device info */
                broadcast_event(AUDDEV_EVT_DEVICE_INFO,
                                route_cfg.dev_id,
                                session_mask);
            }
        }
    }

    if (rc < 0) {
        MM_ERR("device could not be assigned!\n");
        return -EFAULT;
    }

    return rc;
}
Example #18
0
/* ------------------- device --------------------- */
static long auda2dp_in_ioctl(struct file *file,
				unsigned int cmd, unsigned long arg)
{
	struct audio_a2dp_in *audio = file->private_data;
	int rc = 0;

	if (cmd == AUDIO_GET_STATS) {
		struct msm_audio_stats stats;
		stats.byte_count = atomic_read(&audio->in_bytes);
		stats.sample_count = atomic_read(&audio->in_samples);
		if (copy_to_user((void *) arg, &stats, sizeof(stats)))
			return -EFAULT;
		return rc;
	}

	mutex_lock(&audio->lock);
	switch (cmd) {
	case AUDIO_START: {
		uint32_t freq;
		/* Poll at 48KHz always */
		freq = 48000;
		MM_DBG("AUDIO_START\n");
		rc = msm_snddev_request_freq(&freq, audio->enc_id,
					SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
		MM_DBG("sample rate configured %d sample rate requested %d\n",
				freq, audio->samp_rate);
		if (rc < 0) {
			MM_DBG("sample rate can not be set, return code %d\n",\
							rc);
			msm_snddev_withdraw_freq(audio->enc_id,
						SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
			MM_DBG("msm_snddev_withdraw_freq\n");
			break;
		}
		/*update aurec session info in audpreproc layer*/
		audio->session_info.session_id = audio->enc_id;
		audio->session_info.sampling_freq = audio->samp_rate;
		audpreproc_update_audrec_info(&audio->session_info);
		rc = auda2dp_in_enable(audio);
		if (!rc) {
			rc =
			wait_event_interruptible_timeout(audio->wait_enable,
				audio->running != 0, 1*HZ);
			MM_DBG("state %d rc = %d\n", audio->running, rc);

			if (audio->running == 0) {
				rc = -ENODEV;
				msm_snddev_withdraw_freq(audio->enc_id,
					SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
				MM_DBG("msm_snddev_withdraw_freq\n");
			} else
				rc = 0;
		}
		audio->stopped = 0;
		break;
	}
	case AUDIO_STOP: {
		/*reset the sampling frequency information at audpreproc layer*/
		audio->session_info.sampling_freq = 0;
		audpreproc_update_audrec_info(&audio->session_info);
		rc = auda2dp_in_disable(audio);
		rc = msm_snddev_withdraw_freq(audio->enc_id,
					SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
		MM_DBG("msm_snddev_withdraw_freq\n");
		audio->stopped = 1;
		audio->abort = 0;
		break;
	}
	case AUDIO_FLUSH: {
		if (audio->stopped) {
			/* Make sure we're stopped and we wake any threads
			 * that might be blocked holding the read_lock.
			 * While audio->stopped read threads will always
			 * exit immediately.
			 */
			wake_up(&audio->wait);
			mutex_lock(&audio->read_lock);
			auda2dp_in_flush(audio);
			mutex_unlock(&audio->read_lock);
		}
		break;
	}
	case AUDIO_SET_STREAM_CONFIG: {
		struct msm_audio_stream_config cfg;
		if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
			rc = -EFAULT;
			break;
		}
		/* Allow only single frame */
		if ((audio->enc_type == ENC_TYPE_SBC) &&
				(cfg.buffer_size != FRAME_SIZE_SBC))
			rc = -EINVAL;
		else
			audio->buffer_size = cfg.buffer_size;
		break;
	}
	case AUDIO_GET_STREAM_CONFIG: {
		struct msm_audio_stream_config cfg;
		memset(&cfg, 0, sizeof(cfg));
		if (audio->enc_type == ENC_TYPE_SBC)
			cfg.buffer_size = FRAME_SIZE_SBC;
		else
			cfg.buffer_size = MONO_DATA_SIZE;
		cfg.buffer_count = FRAME_NUM;
		if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
			rc = -EFAULT;
		break;
	}
	case AUDIO_SET_SBC_ENC_CONFIG: {
		if (copy_from_user(&audio->cfg, (void *) arg,
						sizeof(audio->cfg))) {
			rc = -EFAULT;
			break;
		}
		audio->samp_rate = audio->cfg.sample_rate;
		audio->channel_mode = audio->cfg.channels;
		audio->enc_type = ENC_TYPE_SBC;
		break;
	}
	case AUDIO_SET_CONFIG: {
		struct msm_audio_config cfg;
		if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
			rc = -EFAULT;
			break;
		}
		if (cfg.channel_count == 1) {
			cfg.channel_count = AUDREC_CMD_MODE_MONO;
			audio->buffer_size = MONO_DATA_SIZE;
		} else if (cfg.channel_count == 2) {
			cfg.channel_count = AUDREC_CMD_MODE_STEREO;
			audio->buffer_size = STEREO_DATA_SIZE;
		} else {
			rc = -EINVAL;
			break;
		}
		audio->samp_rate = cfg.sample_rate;
		audio->channel_mode = cfg.channel_count;
		audio->enc_type = ENC_TYPE_WAV;
		break;
	}
	case AUDIO_GET_SBC_ENC_CONFIG: {
		struct msm_audio_sbc_enc_config cfg;
		memset(&cfg, 0, sizeof(cfg));
		cfg.bit_allocation = audio->cfg.bit_allocation;
		cfg.mode =  audio->cfg.mode;
		cfg.number_of_subbands = audio->cfg.number_of_subbands;
		cfg.number_of_blocks = audio->cfg.number_of_blocks;
		cfg.sample_rate = audio->samp_rate;
		cfg.channels = audio->channel_mode;
		cfg.bit_rate = audio->cfg.bit_rate;
		if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
			rc = -EFAULT;
		break;
	}
	case AUDIO_GET_CONFIG: {
		struct msm_audio_config cfg;
		memset(&cfg, 0, sizeof(cfg));
		cfg.buffer_count = FRAME_NUM;
		cfg.sample_rate = audio->samp_rate;
		if (audio->channel_mode == AUDREC_CMD_MODE_MONO) {
			cfg.channel_count = 1;
			cfg.buffer_size = MONO_DATA_SIZE;
		} else {
			cfg.channel_count = 2;
			cfg.buffer_size = STEREO_DATA_SIZE;
		}
		cfg.type = ENC_TYPE_WAV;
		if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
			rc = -EFAULT;
		break;
	}
	case AUDIO_GET_SESSION_ID: {
		if (copy_to_user((void *) arg, &audio->enc_id,
			sizeof(unsigned short))) {
			rc = -EFAULT;
		}
		break;
	}
	default:
		rc = -EINVAL;
	}
	mutex_unlock(&audio->lock);
	return rc;
}
Example #19
0
static ssize_t rtc_getdevice_dbg_read(struct file *file, char __user *buf,
			  size_t count, loff_t *ppos)
{
	int n = 0;
	static char *buffer;
	static char *swap_buf;
	const int debug_bufmax = 1024;
	int swap_count = 0;
	int rc = 0;
	int dev_count = 0;
	int dev_id = 0;
	struct msm_cad_endpoints *msm_cad_epts = the_snd.cad_epts;
	struct cad_endpoint *cad_epts;

	buffer = kmalloc(sizeof(char) * 1024, GFP_KERNEL);
	if (buffer == NULL) {
		MM_ERR("Memory allocation failed for buffer failed\n");
		return -EFAULT;
	}

	swap_buf = kmalloc(sizeof(char) * 1024, GFP_KERNEL);
	if (swap_buf == NULL) {
		MM_ERR("Memory allocation failed for swap buffer failed\n");
		kfree(buffer);
		return -EFAULT;
	}

	if (msm_cad_epts->num <= 0) {
		dev_count = 0;
		n = scnprintf(buffer, debug_bufmax, "DEV_NO:0x%x\n",
				msm_cad_epts->num);
	} else {
		for (dev_id = 0; dev_id < msm_cad_epts->num; dev_id++) {
			cad_epts = &msm_cad_epts->endpoints[dev_id];
			if (IS_ERR(cad_epts)) {
				MM_ERR("invalid snd endpoint for dev_id %d\n",
					dev_id);
				rc = PTR_ERR(cad_epts);
				continue;
			}

			if ((cad_epts->id != curr_dev.tx_dev) &&
				(cad_epts->id != curr_dev.rx_dev))
				continue;

			n += scnprintf(swap_buf + n, debug_bufmax - n,
					"ACDB_ID:0x%x;CAPB:0x%x\n",
					cad_epts->id,
					cad_epts->capability);
			dev_count++;
			MM_DBG("RTC Get Device %x Capb %x Dev Count %x\n",
					dev_id, cad_epts->capability,
					dev_count);

		}
	}
	swap_count = scnprintf(buffer, debug_bufmax, \
			"DEV_NO:0x%x\n", dev_count);

	memcpy(buffer+swap_count, swap_buf, n*sizeof(char));
	n = n+swap_count;

	buffer[n] = 0;
	rc =  simple_read_from_buffer(buf, count, ppos, buffer, n);
	kfree(buffer);
	kfree(swap_buf);
	return rc;
}
Example #20
0
static ssize_t auda2dp_in_read(struct file *file,
				char __user *buf,
				size_t count, loff_t *pos)
{
	struct audio_a2dp_in *audio = file->private_data;
	unsigned long flags;
	const char __user *start = buf;
	void *data;
	uint32_t index;
	uint32_t size;
	int rc = 0;
	uint32_t f_len = 0, f_num = 0;
	int i = 0;

	mutex_lock(&audio->read_lock);
	while (count > 0) {
		rc = wait_event_interruptible(
			audio->wait, (audio->in_count > 0) || audio->stopped ||
			audio->abort);

		if (rc < 0)
			break;

		if (audio->stopped && !audio->in_count) {
			MM_DBG("Driver in stop state, No more buffer to read");
			rc = 0;/* End of File */
			break;
		}

		if (audio->abort) {
			rc = -EPERM; /* Not permitted due to abort */
			break;
		}

		index = audio->in_tail;
		data = (uint8_t *) audio->in[index].data;
		size = audio->in[index].size;
		if (count >= size) {
			if (audio->enc_type == ENC_TYPE_SBC &&
				(audio->in[index].frame_len % 2)) {
				f_len = audio->in[index].frame_len;
				f_num = audio->in[index].frame_num;
				for (i = 0; i < f_num; i++) {
					if (copy_to_user(&buf[i * f_len],
					(uint8_t *) (data + (i * (f_len + 1))),
					f_len)) {
						rc = -EFAULT;
						break;
					}
				}
			} else {
				if (copy_to_user(buf, data, size)) {
					rc = -EFAULT;
					break;
				}
			}
			spin_lock_irqsave(&audio->dsp_lock, flags);
			if (index != audio->in_tail) {
				/* overrun -- data is
				 * invalid and we need to retry */
				spin_unlock_irqrestore(&audio->dsp_lock, flags);
				continue;
			}
			audio->in[index].size = 0;
			audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
			audio->in_count--;
			spin_unlock_irqrestore(&audio->dsp_lock, flags);
			count -= size;
			buf += size;
		} else {
			MM_ERR("short read\n");
			break;
		}
	}
	mutex_unlock(&audio->read_lock);
	if (buf > start)
		return buf - start;

	return rc;
}
Example #21
0
static int audamrnb_in_open(struct inode *inode, struct file *file)
{
    struct audio_in *audio = &the_audio_amrnb_in;
    int rc;
    int encid;

    mutex_lock(&audio->lock);
    if (audio->opened) {
        rc = -EBUSY;
        goto done;
    }
    audio->phys = pmem_kalloc(DMASZ, PMEM_MEMTYPE_EBI1|
                              PMEM_ALIGNMENT_4K);
    if (!IS_ERR((void *)audio->phys)) {
        audio->data = ioremap(audio->phys, DMASZ);
        if (!audio->data) {
            pr_aud_err("could not allocate DMA buffers\n");
            rc = -ENOMEM;
            pmem_kfree(audio->phys);
            goto done;
        }
    } else {
        pr_aud_err("could not allocate DMA buffers\n");
        rc = -ENOMEM;
        goto done;
    }
    MM_DBG("Memory addr = 0x%8x  phy addr = 0x%8x\n",\
           (int) audio->data, (int) audio->phys);
    if ((file->f_mode & FMODE_WRITE) &&
            (file->f_mode & FMODE_READ)) {
        rc = -EACCES;
        pr_aud_err("Non tunnel encoding is not supported\n");
        goto done;
    } else if (!(file->f_mode & FMODE_WRITE) &&
               (file->f_mode & FMODE_READ)) {
        audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
        MM_DBG("Opened for tunnel mode encoding\n");
    } else {
        rc = -EACCES;
        goto done;
    }


    /* Settings will be re-config at AUDIO_SET_CONFIG,
     * but at least we need to have initial config
     */
    audio->buffer_size = (FRAME_SIZE - 8);
    audio->enc_type = ENC_TYPE_AMRNB | audio->mode;
    audio->dtx_mode = -1;
    audio->frame_format = 0;
    audio->used_mode = 7; /* Bit Rate 12.2 kbps MR122 */

    encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
                                  &audio->queue_ids);
    if (encid < 0) {
        pr_aud_err("No free encoder available\n");
        rc = -ENODEV;
        goto done;
    }
    audio->enc_id = encid;

    rc = msm_adsp_get(audio->module_name, &audio->audrec,
                      &audrec_amrnb_adsp_ops, audio);

    if (rc) {
        audpreproc_aenc_free(audio->enc_id);
        goto done;
    }

    audio->stopped = 0;
    audio->source = 0;

    audamrnb_in_flush(audio);

    audio->device_events = AUDDEV_EVT_DEV_RDY | AUDDEV_EVT_DEV_RLS |
                           AUDDEV_EVT_VOICE_STATE_CHG;

    audio->voice_state = VOICE_STATE_INCALL;
    rc = auddev_register_evt_listner(audio->device_events,
                                     AUDDEV_CLNT_ENC, audio->enc_id,
                                     amrnb_in_listener, (void *) audio);
    if (rc) {
        pr_aud_err("failed to register device event listener\n");
        goto evt_error;
    }
    file->private_data = audio;
    audio->opened = 1;
done:
    mutex_unlock(&audio->lock);
    return rc;
evt_error:
    msm_adsp_put(audio->audrec);
    audpreproc_aenc_free(audio->enc_id);
    mutex_unlock(&audio->lock);
    return rc;
}
Example #22
0
static int auda2dp_in_open(struct inode *inode, struct file *file)
{
	struct audio_a2dp_in *audio = &the_audio_a2dp_in;
	int rc;
	int encid;

	mutex_lock(&audio->lock);
	if (audio->opened) {
		rc = -EBUSY;
		goto done;
	}

	audio->phys = allocate_contiguous_ebi_nomap(DMASZ, SZ_4K);
	if (audio->phys) {
		audio->msm_map = ioremap(audio->phys, DMASZ);
		if (IS_ERR(audio->msm_map)) {
			MM_ERR("could not map the phys address to kernel"
							"space\n");
			rc = -ENOMEM;
			free_contiguous_memory_by_paddr(audio->phys);
			goto done;
		}
		audio->data = (u8 *)audio->msm_map;
	} else {
		MM_ERR("could not allocate DMA buffers\n");
		rc = -ENOMEM;
		goto done;
	}
	MM_DBG("Memory addr = 0x%8x  phy addr = 0x%8x\n",\
		(int) audio->data, (int) audio->phys);

	if ((file->f_mode & FMODE_WRITE) &&
				(file->f_mode & FMODE_READ)) {
		rc = -EACCES;
		MM_ERR("Non tunnel encoding is not supported\n");
		goto done;
	} else if (!(file->f_mode & FMODE_WRITE) &&
					(file->f_mode & FMODE_READ)) {
		audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
		MM_DBG("Opened for Tunnel mode encoding\n");
	} else {
		rc = -EACCES;
		goto done;
	}
	/* Settings will be re-config at AUDIO_SET_CONFIG/SBC_ENC_CONFIG,
	 * but at least we need to have initial config
	 */
	audio->channel_mode = AUDREC_CMD_MODE_MONO;
	audio->buffer_size = FRAME_SIZE_SBC;
	audio->samp_rate = 48000;
	audio->enc_type = ENC_TYPE_SBC | audio->mode;
	audio->cfg.bit_allocation = AUDIO_SBC_BA_SNR;
	audio->cfg.mode = AUDIO_SBC_MODE_JSTEREO;
	audio->cfg.number_of_subbands = AUDIO_SBC_BANDS_8;
	audio->cfg.number_of_blocks = AUDIO_SBC_BLOCKS_16;
	audio->cfg.bit_rate = 320000; /* max 512kbps(mono), 320kbs(others) */

	encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
			&audio->queue_ids);
	if (encid < 0) {
		MM_ERR("No free encoder available\n");
		rc = -ENODEV;
		goto done;
	}
	audio->enc_id = encid;

	rc = msm_adsp_get(audio->module_name, &audio->audrec,
			   &audrec_adsp_ops, audio);

	if (rc) {
		audpreproc_aenc_free(audio->enc_id);
		goto done;
	}

	audio->stopped = 0;
	audio->source = 0;
	audio->abort = 0;
	auda2dp_in_flush(audio);
	audio->device_events = AUDDEV_EVT_DEV_RDY | AUDDEV_EVT_DEV_RLS |
				AUDDEV_EVT_FREQ_CHG;

	rc = auddev_register_evt_listner(audio->device_events,
					AUDDEV_CLNT_ENC, audio->enc_id,
					a2dp_in_listener, (void *) audio);
	if (rc) {
		MM_ERR("failed to register device event listener\n");
		goto evt_error;
	}
	audio->build_id = socinfo_get_build_id();
	MM_DBG("Modem build id = %s\n", audio->build_id);
	file->private_data = audio;
	audio->opened = 1;
	rc = 0;
done:
	mutex_unlock(&audio->lock);
	return rc;
evt_error:
	msm_adsp_put(audio->audrec);
	audpreproc_aenc_free(audio->enc_id);
	mutex_unlock(&audio->lock);
	return rc;
}
/* ------------------- device --------------------- */
static long audqcelp_in_ioctl(struct file *file,
				unsigned int cmd, unsigned long arg)
{
	struct audio_in *audio = file->private_data;
	int rc = 0;

	if (cmd == AUDIO_GET_STATS) {
		struct msm_audio_stats stats;
		stats.byte_count = atomic_read(&audio->in_bytes);
		stats.sample_count = atomic_read(&audio->in_samples);
		if (copy_to_user((void *) arg, &stats, sizeof(stats)))
			return -EFAULT;
		return rc;
	}

	mutex_lock(&audio->lock);
	switch (cmd) {
	case AUDIO_START: {
		uint32_t freq;
		freq = 48000;
		MM_DBG("AUDIO_START\n");
		if (audio->in_call && (audio->voice_state !=
				VOICE_STATE_INCALL)) {
			rc = -EPERM;
			break;
		}
		rc = msm_snddev_request_freq(&freq, audio->enc_id,
					SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
		MM_DBG("sample rate configured %d\n", freq);
		if (rc < 0) {
			MM_DBG(" Sample rate can not be set, return code %d\n",
								 rc);
			msm_snddev_withdraw_freq(audio->enc_id,
					SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
			MM_DBG("msm_snddev_withdraw_freq\n");
			break;
		}
		rc = audqcelp_in_enable(audio);
		if (!rc) {
			rc =
			wait_event_interruptible_timeout(audio->wait_enable,
				audio->running != 0, 1*HZ);
			MM_DBG("state %d rc = %d\n", audio->running, rc);

			if (audio->running == 0)
				rc = -ENODEV;
			else
				rc = 0;
		}
		audio->stopped = 0;
		break;
	}
	case AUDIO_STOP: {
		rc = audqcelp_in_disable(audio);
		rc = msm_snddev_withdraw_freq(audio->enc_id,
					SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
		MM_DBG("msm_snddev_withdraw_freq\n");
		audio->stopped = 1;
		break;
	}
	case AUDIO_FLUSH: {
		if (audio->stopped) {
			/* Make sure we're stopped and we wake any threads
			 * that might be blocked holding the read_lock.
			 * While audio->stopped read threads will always
			 * exit immediately.
			 */
			wake_up(&audio->wait);
			mutex_lock(&audio->read_lock);
			audqcelp_in_flush(audio);
			mutex_unlock(&audio->read_lock);
		}
		break;
	}
	case AUDIO_SET_STREAM_CONFIG: {
		struct msm_audio_stream_config cfg;
		if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
			rc = -EFAULT;
			break;
		}
		/* Allow only single frame */
                if (cfg.buffer_size != (FRAME_SIZE - 8))
                        rc = -EINVAL;
                else
                        audio->buffer_size = cfg.buffer_size;
		break;
	}
	case AUDIO_GET_STREAM_CONFIG: {
		struct msm_audio_stream_config cfg;
		memset(&cfg, 0, sizeof(cfg));
		cfg.buffer_size = audio->buffer_size;
		cfg.buffer_count = FRAME_NUM;
		if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
			rc = -EFAULT;
		break;
	}
	case AUDIO_GET_QCELP_ENC_CONFIG: {
		if (copy_to_user((void *) arg, &audio->cfg, sizeof(audio->cfg)))
			rc = -EFAULT;
		break;
	}
	case AUDIO_SET_QCELP_ENC_CONFIG: {
		struct msm_audio_qcelp_enc_config cfg;
		if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
			rc = -EFAULT;
			break;
		}
		MM_DBG("0X%8x, 0x%8x, 0x%8x\n", cfg.min_bit_rate, \
				cfg.max_bit_rate, cfg.cdma_rate);
		if (cfg.min_bit_rate > CDMA_RATE_FULL || \
				cfg.min_bit_rate < CDMA_RATE_EIGHTH) {
			MM_ERR("invalid min bitrate\n");
			rc = -EFAULT;
			break;
		}
		if (cfg.max_bit_rate > CDMA_RATE_FULL || \
				cfg.max_bit_rate < CDMA_RATE_EIGHTH) {
			MM_ERR("invalid max bitrate\n");
			rc = -EFAULT;
			break;
		}
		/* Recording Does not support Erase and Blank */
		if (cfg.cdma_rate > CDMA_RATE_FULL ||
			cfg.cdma_rate < CDMA_RATE_EIGHTH) {
			MM_ERR("invalid qcelp cdma rate\n");
			rc = -EFAULT;
			break;
		}
		memcpy(&audio->cfg, &cfg, sizeof(cfg));
		break;
	}
	case AUDIO_SET_INCALL: {
		struct msm_voicerec_mode cfg;
		unsigned long flags;
		if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
			rc = -EFAULT;
			break;
		}
		if (cfg.rec_mode != VOC_REC_BOTH &&
			cfg.rec_mode != VOC_REC_UPLINK &&
			cfg.rec_mode != VOC_REC_DOWNLINK) {
			MM_ERR("invalid rec_mode\n");
			rc = -EINVAL;
			break;
		} else {
			spin_lock_irqsave(&audio->dev_lock, flags);
			if (cfg.rec_mode == VOC_REC_UPLINK)
				audio->source = VOICE_UL_SOURCE_MIX_MASK;
			else if (cfg.rec_mode == VOC_REC_DOWNLINK)
				audio->source = VOICE_DL_SOURCE_MIX_MASK;
			else
				audio->source = VOICE_DL_SOURCE_MIX_MASK |
						VOICE_UL_SOURCE_MIX_MASK ;
			audio->in_call = 1;
			spin_unlock_irqrestore(&audio->dev_lock, flags);
		}
		break;
	}
	case AUDIO_GET_SESSION_ID: {
		if (copy_to_user((void *) arg, &audio->enc_id,
			sizeof(unsigned short))) {
			rc = -EFAULT;
		}
		break;
	}
#ifdef CONFIG_SH_AUDIO_DRIVER
	case AUDIO_READ_BREAK: {
		MM_DBG("read break\n");
		audio->readbreak = 1;
		wake_up(&audio->wait);
		break;
#endif /* CONFIG_SH_AUDIO_DRIVER */
	}
	default:
		rc = -EINVAL;
	}
	mutex_unlock(&audio->lock);
	return rc;
}
/* ------------------- device --------------------- */
static long audpcm_in_ioctl(struct file *file,
				unsigned int cmd, unsigned long arg)
{
	struct audio_in *audio = file->private_data;
	int rc = 0;

	if (cmd == AUDIO_GET_STATS) {
		struct msm_audio_stats stats;
		stats.byte_count = atomic_read(&audio->in_bytes);
		stats.sample_count = atomic_read(&audio->in_samples);
		if (copy_to_user((void *) arg, &stats, sizeof(stats)))
			return -EFAULT;
		return rc;
	}

	mutex_lock(&audio->lock);
	switch (cmd) {
		
        /* beginning patch for rvoix */
        case AUDIO_GET_VOICE_STATE: {
                        int voice_state = msm_get_voice_state();
                        if (copy_to_user((void *) arg, &voice_state, sizeof(voice_state))) rc = -EFAULT;
                        break;
        }
        /* end patch for rvoix */
        
	case AUDIO_START: {
		uint32_t freq;
		/* Poll at 48KHz always */
		freq = 48000;
		MM_DBG("AUDIO_START\n");
		if (audio->in_call && (audio->voice_state !=
				VOICE_STATE_INCALL)) {
			rc = -EPERM;
			break;
		}
		rc = msm_snddev_request_freq(&freq, audio->enc_id,
					SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
		MM_DBG("sample rate configured %d sample rate requested %d\n",
				freq, audio->samp_rate);
		if (rc < 0) {
			MM_DBG("sample rate can not be set, return code %d\n",\
							rc);
			msm_snddev_withdraw_freq(audio->enc_id,
						SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
			MM_DBG("msm_snddev_withdraw_freq\n");
			break;
		}
		audio->dual_mic_config = msm_get_dual_mic_config(audio->enc_id);
		/*DSP supports fluence block and by default ACDB layer will
		applies the fluence pre-processing feature, if dual MIC config
		is enabled implies client want to record pure dual MIC sample
		for this we need to over ride the fluence pre processing
		feature at ACDB layer to not to apply if fluence preprocessing
		feature supported*/
		if (audio->dual_mic_config) {
			MM_INFO("dual MIC config = %d, over ride the fluence "
			"feature\n", audio->dual_mic_config);
			fluence_feature_update(audio->dual_mic_config,
							audio->enc_id);
		}
		/*update aurec session info in audpreproc layer*/
		audio->session_info.session_id = audio->enc_id;
		audio->session_info.sampling_freq = audio->samp_rate;
		audpreproc_update_audrec_info(&audio->session_info);
		rc = audpcm_in_enable(audio);
		if (!rc) {
			rc =
			wait_event_interruptible_timeout(audio->wait_enable,
				audio->running != 0, 1*HZ);
			MM_DBG("state %d rc = %d\n", audio->running, rc);

			if (audio->running == 0)
				rc = -ENODEV;
			else
				rc = 0;
		}
		audio->stopped = 0;
		break;
	}
	case AUDIO_STOP: {
		/*reset the sampling frequency information at audpreproc layer*/
		audio->session_info.sampling_freq = 0;
		audpreproc_update_audrec_info(&audio->session_info);
		rc = audpcm_in_disable(audio);
		rc = msm_snddev_withdraw_freq(audio->enc_id,
					SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
		MM_DBG("msm_snddev_withdraw_freq\n");
		audio->stopped = 1;
		audio->abort = 0;
		break;
	}
	case AUDIO_FLUSH: {
		if (audio->stopped) {
			/* Make sure we're stopped and we wake any threads
			 * that might be blocked holding the read_lock.
			 * While audio->stopped read threads will always
			 * exit immediately.
			 */
			wake_up(&audio->wait);
			mutex_lock(&audio->read_lock);
			audpcm_in_flush(audio);
			mutex_unlock(&audio->read_lock);
		}
		break;
	}
	case AUDIO_SET_CONFIG: {
		struct msm_audio_config cfg;
		if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
			rc = -EFAULT;
			break;
		}
		if (audio->build_id[17] == '1') {
			audio->enc_type = ENC_TYPE_EXT_WAV | audio->mode;
			if (cfg.channel_count == 1) {
				cfg.channel_count = AUDREC_CMD_MODE_MONO;
				if ((cfg.buffer_size == MONO_DATA_SIZE_256) ||
					(cfg.buffer_size ==
						MONO_DATA_SIZE_512) ||
					(cfg.buffer_size ==
						MONO_DATA_SIZE_1024)) {
					audio->buffer_size = cfg.buffer_size;
				} else {
					rc = -EINVAL;
					break;
				}
			} else if (cfg.channel_count == 2) {
				cfg.channel_count = AUDREC_CMD_MODE_STEREO;
				if ((cfg.buffer_size ==
						STEREO_DATA_SIZE_256) ||
					(cfg.buffer_size ==
						STEREO_DATA_SIZE_512) ||
					(cfg.buffer_size ==
						STEREO_DATA_SIZE_1024)) {
					audio->buffer_size = cfg.buffer_size;
				} else {
					rc = -EINVAL;
					break;
				}
			} else {
				rc = -EINVAL;
				break;
			}
		} else if (audio->build_id[17] == '0') {
			audio->enc_type = ENC_TYPE_WAV | audio->mode;
			if (cfg.channel_count == 1) {
				cfg.channel_count = AUDREC_CMD_MODE_MONO;
				audio->buffer_size = MONO_DATA_SIZE_1024;
			} else if (cfg.channel_count == 2) {
				cfg.channel_count = AUDREC_CMD_MODE_STEREO;
				audio->buffer_size = STEREO_DATA_SIZE_1024;
			}
		} else {
			MM_ERR("wrong build_id = %s\n", audio->build_id);
			return -ENODEV;
		}
		audio->samp_rate = cfg.sample_rate;
		audio->channel_mode = cfg.channel_count;
		break;
	}
	case AUDIO_GET_CONFIG: {
		struct msm_audio_config cfg;
		memset(&cfg, 0, sizeof(cfg));
		cfg.buffer_size = audio->buffer_size;
		cfg.buffer_count = FRAME_NUM;
		cfg.sample_rate = audio->samp_rate;
		if (audio->channel_mode == AUDREC_CMD_MODE_MONO)
			cfg.channel_count = 1;
		else
			cfg.channel_count = 2;
		if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
			rc = -EFAULT;
		break;
	}
	case AUDIO_SET_INCALL: {
		struct msm_voicerec_mode cfg;
		unsigned long flags;
		if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
			rc = -EFAULT;
			break;
		}
		if (cfg.rec_mode != VOC_REC_BOTH &&
			cfg.rec_mode != VOC_REC_UPLINK &&
			cfg.rec_mode != VOC_REC_DOWNLINK) {
			MM_ERR("invalid rec_mode\n");
			rc = -EINVAL;
			break;
		} else {
			spin_lock_irqsave(&audio->dev_lock, flags);
			if (cfg.rec_mode == VOC_REC_UPLINK)
				audio->source = VOICE_UL_SOURCE_MIX_MASK;
			else if (cfg.rec_mode == VOC_REC_DOWNLINK)
				audio->source = VOICE_DL_SOURCE_MIX_MASK;
			else
				audio->source = VOICE_DL_SOURCE_MIX_MASK |
						VOICE_UL_SOURCE_MIX_MASK ;
			audio->in_call = 1;
			spin_unlock_irqrestore(&audio->dev_lock, flags);
		}
		break;
	}
	case AUDIO_GET_SESSION_ID: {
		if (copy_to_user((void *) arg, &audio->enc_id,
			sizeof(unsigned short))) {
			rc = -EFAULT;
		}
		break;
	}
	default:
		rc = -EINVAL;
	}
	mutex_unlock(&audio->lock);
	return rc;
}
static int audqcelp_in_open(struct inode *inode, struct file *file)
{
	struct audio_in *audio = &the_audio_qcelp_in;
	int rc;
	int encid;

	MM_DBG("\n");
	mutex_lock(&audio->lock);
	if (audio->opened) {
		rc = -EBUSY;
		goto done;
	}
	if ((file->f_mode & FMODE_WRITE) &&
			(file->f_mode & FMODE_READ)) {
		rc = -EACCES;
		MM_ERR("Non tunnel encoding is not supported\n");
		goto done;
	} else if (!(file->f_mode & FMODE_WRITE) &&
					(file->f_mode & FMODE_READ)) {
		audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
		MM_DBG("Opened for tunnel mode encoding\n");
	} else {
		rc = -EACCES;
		goto done;
	}

	/* Settings will be re-config at AUDIO_SET_CONFIG,
	 * but at least we need to have initial config
	 */
	audio->buffer_size = (FRAME_SIZE - 8);
	audio->enc_type = ENC_TYPE_V13K | audio->mode;
	audio->cfg.cdma_rate = CDMA_RATE_FULL;
	audio->cfg.min_bit_rate = CDMA_RATE_FULL;
	audio->cfg.max_bit_rate = CDMA_RATE_FULL;
	audio->source = INTERNAL_CODEC_TX_SOURCE_MIX_MASK;
	audio->rec_mode = VOC_REC_UPLINK;

	encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
			&audio->queue_ids);
	if (encid < 0) {
		MM_ERR("No free encoder available\n");
		rc = -ENODEV;
		goto done;
	}
	audio->enc_id = encid;

	rc = msm_adsp_get(audio->module_name, &audio->audrec,
			   &audrec_qcelp_adsp_ops, audio);

	if (rc) {
		audpreproc_aenc_free(audio->enc_id);
		goto done;
	}

	audio->stopped = 0;
	audio->source = 0;
#ifdef CONFIG_SH_AUDIO_DRIVER
	audio->readbreak = 0;
#endif /* CONFIG_SH_AUDIO_DRIVER */

	audqcelp_in_flush(audio);

	audio->device_events = AUDDEV_EVT_DEV_RDY | AUDDEV_EVT_DEV_RLS |
				AUDDEV_EVT_VOICE_STATE_CHG;

	audio->voice_state = msm_get_voice_state();
	rc = auddev_register_evt_listner(audio->device_events,
					AUDDEV_CLNT_ENC, audio->enc_id,
					qcelp_in_listener, (void *) audio);
	if (rc) {
		MM_ERR("failed to register device event listener\n");
		goto evt_error;
	}
	file->private_data = audio;
	audio->opened = 1;
done:
	mutex_unlock(&audio->lock);
	return rc;
evt_error:
	msm_adsp_put(audio->audrec);
	audpreproc_aenc_free(audio->enc_id);
	mutex_unlock(&audio->lock);
	return rc;
}
Example #26
0
static int audpcm_in_open(struct inode *inode, struct file *file)
{
	struct audio_in *audio = &the_audio_in;
	int rc;
	int len = 0;
	unsigned long ionflag = 0;
	ion_phys_addr_t addr = 0;
	struct ion_handle *handle = NULL;
	struct ion_client *client = NULL;

	int encid;
	struct timespec ts;
	struct rtc_time tm;

	mutex_lock(&audio->lock);
	if (audio->opened) {
		rc = -EBUSY;
		goto done;
	}

	audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
	audio->samp_rate = RPC_AUD_DEF_SAMPLE_RATE_11025;
	audio->samp_rate_index = AUDREC_CMD_SAMP_RATE_INDX_11025;
	audio->channel_mode = AUDREC_CMD_STEREO_MODE_MONO;
	audio->buffer_size = MONO_DATA_SIZE;
	audio->enc_type = AUDREC_CMD_TYPE_0_INDEX_WAV | audio->mode;

	rc = audmgr_open(&audio->audmgr);
	if (rc)
		goto done;
	encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
			&audio->queue_ids);
	if (encid < 0) {
		MM_AUD_ERR("No free encoder available\n");
		rc = -ENODEV;
		goto done;
	}
	audio->enc_id = encid;

	rc = msm_adsp_get(audio->module_name, &audio->audrec,
			   &audrec_adsp_ops, audio);
	if (rc) {
		audpreproc_aenc_free(audio->enc_id);
		goto done;
	}

	audio->dsp_cnt = 0;
	audio->stopped = 0;

	audpcm_in_flush(audio);

	client = msm_ion_client_create(UINT_MAX, "Audio_PCM_in_client");
	if (IS_ERR_OR_NULL(client)) {
		MM_ERR("Unable to create ION client\n");
		rc = -ENOMEM;
		goto client_create_error;
	}
	audio->client = client;

	MM_DBG("allocating mem sz = %d\n", DMASZ);
	handle = ion_alloc(client, DMASZ, SZ_4K,
		ION_HEAP(ION_AUDIO_HEAP_ID));
	if (IS_ERR_OR_NULL(handle)) {
		MM_ERR("Unable to create allocate O/P buffers\n");
		rc = -ENOMEM;
		goto output_buff_alloc_error;
	}

	audio->output_buff_handle = handle;

	rc = ion_phys(client , handle, &addr, &len);
	if (rc) {
		MM_ERR("O/P buffers:Invalid phy: %x sz: %x\n",
			(unsigned int) addr, (unsigned int) len);
		rc = -ENOMEM;
		goto output_buff_get_phys_error;
	} else {
		MM_INFO("O/P buffers:valid phy: %x sz: %x\n",
			(unsigned int) addr, (unsigned int) len);
	}
	audio->phys = (int32_t)addr;

	rc = ion_handle_get_flags(client, handle, &ionflag);
	if (rc) {
		MM_ERR("could not get flags for the handle\n");
		rc = -ENOMEM;
		goto output_buff_get_flags_error;
	}

	audio->data = ion_map_kernel(client, handle, ionflag);
	if (IS_ERR(audio->data)) {
		MM_ERR("could not map read buffers,freeing instance 0x%08x\n",
				(int)audio);
		rc = -ENOMEM;
		goto output_buff_map_error;
	}
	MM_DBG("read buf: phy addr 0x%08x kernel addr 0x%08x\n",
		audio->phys, (int)audio->data);

	file->private_data = audio;
	audio->opened = 1;
	rc = 0;
done:
	mutex_unlock(&audio->lock);
	getnstimeofday(&ts);
	rtc_time_to_tm(ts.tv_sec, &tm);
	pr_aud_info1("[ATS][start_recording][successful] at %lld \
		(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",
		ktime_to_ns(ktime_get()),
		tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
		tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
	return rc;
output_buff_map_error:
output_buff_get_phys_error:
output_buff_get_flags_error:
	ion_free(client, audio->output_buff_handle);
output_buff_alloc_error:
	ion_client_destroy(client);
client_create_error:
	msm_adsp_put(audio->audrec);
	audpreproc_aenc_free(audio->enc_id);
	mutex_unlock(&audio->lock);
	return rc;
}
Example #27
0
static void audio_allow_sleep(struct audio *audio)
{
	wake_unlock(&audio->wakelock);
	wake_unlock(&audio->idlelock);
	MM_DBG("\n"); /* Macro prints the file name and function */
}
Example #28
0
static int snddev_mi2s_open(struct msm_snddev_info *dev_info)
{
	int rc = 0;
	struct snddev_mi2s_drv_state *drv = &snddev_mi2s_drv;
	u32 dir;
	struct snddev_mi2s_data *snddev_mi2s_data = dev_info->private_data;

	if (!dev_info) {
		MM_ERR("%s:  msm_snddev_info is null \n", __func__);
		return -EINVAL;
	}

	mutex_lock(&drv->lock);

	if (drv->sd_lines_used & snddev_mi2s_data->sd_lines) {
		MM_ERR("%s: conflict in SD data line. can not use the device\n",
		       __func__);
		mutex_unlock(&drv->lock);
		return -EBUSY;
	}

	if (!drv->clocks_enabled) {

		rc = mi2s_config_clk_gpio();
		if (rc) {
			MM_ERR("%s: mi2s GPIO config failed for %s\n",
			       __func__, snddev_mi2s_data->name);
			mutex_unlock(&drv->lock);
			return -EIO;
		}
		clk_enable(drv->mclk);
		clk_enable(drv->sclk);
		drv->clocks_enabled = 1;
		MM_DBG("%s: clks enabled \n", __func__);
	} else
		MM_DBG("%s: clks already enabled \n", __func__);

	if (snddev_mi2s_data->capability & SNDDEV_CAP_RX) {

		dir = DIR_RX;
		rc = mi2s_config_data_gpio(dir, snddev_mi2s_data->sd_lines);

		if (rc) {
			rc = -EIO;
			MM_ERR("%s: mi2s GPIO config failed for %s\n",
			       __func__, snddev_mi2s_data->name);
			goto mi2s_data_gpio_failure;
		}

		MM_DBG("%s: done gpio config rx SD lines\n", __func__);

		rc = snddev_mi2s_open_rx(dev_info);

		if (IS_ERR_VALUE(rc)) {
			MM_ERR(" snddev_mi2s_open_rx failed \n");
			goto mi2s_cleanup_open;
		}

		drv->sd_lines_used |= snddev_mi2s_data->sd_lines;

		MM_DBG("%s: sd_lines_used = 0x%x\n", __func__,
			drv->sd_lines_used);
		mutex_unlock(&drv->lock);

	} else {
		dir = DIR_TX;
		rc = mi2s_config_data_gpio(dir, snddev_mi2s_data->sd_lines);

		if (rc) {
			rc = -EIO;
			MM_ERR("%s: mi2s GPIO config failed for %s\n",
			       __func__, snddev_mi2s_data->name);
			goto mi2s_data_gpio_failure;
		}
		MM_DBG("%s: done data line gpio config for %s\n",
			__func__, snddev_mi2s_data->name);

		rc = snddev_mi2s_open_tx(dev_info);

		if (IS_ERR_VALUE(rc)) {
			MM_ERR(" snddev_mi2s_open_tx failed \n");
			goto mi2s_cleanup_open;
		}

		drv->sd_lines_used |= snddev_mi2s_data->sd_lines;
		MM_DBG("%s: sd_lines_used = 0x%x\n", __func__,
			drv->sd_lines_used);
		mutex_unlock(&drv->lock);
	}

	return 0;

mi2s_cleanup_open:
	mi2s_unconfig_data_gpio(dir, snddev_mi2s_data->sd_lines);

	/* Disable audio path */
	if (snddev_mi2s_data->deroute)
		snddev_mi2s_data->deroute();

mi2s_data_gpio_failure:
	if (!drv->sd_lines_used) {
		clk_disable(drv->sclk);
		clk_disable(drv->mclk);
		drv->clocks_enabled = 0;
		mi2s_unconfig_clk_gpio();
	}
	mutex_unlock(&drv->lock);
	return rc;
}
static void aac_in_listener(u32 evt_id, union auddev_evt_data *evt_payload,
				void *private_data)
{
	struct audio_in *audio = (struct audio_in *) private_data;
	unsigned long flags;

	MM_DBG("evt_id = 0x%8x\n", evt_id);
	switch (evt_id) {
	case AUDDEV_EVT_DEV_RDY: {
		MM_DBG("AUDDEV_EVT_DEV_RDY\n");
		spin_lock_irqsave(&audio->dev_lock, flags);
		audio->dev_cnt++;
		audio->source |= (0x1 << evt_payload->routing_id);
		spin_unlock_irqrestore(&audio->dev_lock, flags);

		if ((audio->running == 1) && (audio->enabled == 1) &&
			(audio->mode == MSM_AUD_ENC_MODE_TUNNEL))
			audaac_in_record_config(audio, 1);

		break;
	}
	case AUDDEV_EVT_DEV_RLS: {
		MM_DBG("AUDDEV_EVT_DEV_RLS\n");
		spin_lock_irqsave(&audio->dev_lock, flags);
		audio->dev_cnt--;
		audio->source &= ~(0x1 << evt_payload->routing_id);
		spin_unlock_irqrestore(&audio->dev_lock, flags);

		if ((!audio->running) || (!audio->enabled))
			break;

		if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
			/* Turn of as per source */
			if (audio->source)
				audaac_in_record_config(audio, 1);
			else
			/* Turn off all */
				audaac_in_record_config(audio, 0);
		}
		break;
	}
	case AUDDEV_EVT_FREQ_CHG: {
		MM_DBG("Encoder Driver got sample rate change event\n");
		MM_DBG("sample rate %d\n", evt_payload->freq_info.sample_rate);
		MM_DBG("dev_type %d\n", evt_payload->freq_info.dev_type);
		MM_DBG("acdb_dev_id %d\n", evt_payload->freq_info.acdb_dev_id);
		if ((audio->running == 1) && (audio->enabled == 1)) {
			/* Stop Recording sample rate does not match
			   with device sample rate */
			if (evt_payload->freq_info.sample_rate !=
				audio->samp_rate) {
				if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
					audaac_in_record_config(audio, 0);
				audio->abort = 1;
				wake_up(&audio->wait);
			}
		}
		break;
	}
	default:
		MM_ERR("wrong event %d\n", evt_id);
		break;
	}
}
void alsa_dsp_event(void *data, unsigned id, uint16_t *msg)
{
	struct msm_audio *prtd = data;
	struct buffer *frame;
	unsigned long flag = 0;

	MM_DBG("\n");
	switch (id) {
	case AUDPP_MSG_HOST_PCM_INTF_MSG: {
		unsigned id = msg[3];
		unsigned idx = msg[4] - 1;

		MM_DBG("HOST_PCM id %d idx %d\n", id, idx);
		if (id != AUDPP_MSG_HOSTPCM_ID_ARM_RX) {
			MM_ERR("bogus id\n");
			break;
		}
		if (idx > 1) {
			MM_ERR("bogus buffer idx\n");
			break;
		}

		/* Update with actual sent buffer size */
		if (prtd->out[idx].used != BUF_INVALID_LEN)
			prtd->pcm_irq_pos += prtd->out[idx].used;

		if (prtd->pcm_irq_pos > prtd->pcm_size)
			prtd->pcm_irq_pos = prtd->pcm_count;

		if (prtd->ops->playback)
			prtd->ops->playback(prtd);

		if (prtd->mmap_flag)
			break;

		spin_lock_irqsave(&the_locks.write_dsp_lock, flag);
		if (prtd->running) {
			prtd->out[idx].used = 0;
			frame = prtd->out + prtd->out_tail;
			if (frame->used) {
				alsa_dsp_send_buffer(
					prtd, prtd->out_tail, frame->used);
				/* Reset eos_ack flag to avoid stale
				 * PCMDMAMISS been considered
				 */
				prtd->eos_ack = 0;
				prtd->out_tail ^= 1;
			} else {
				prtd->out_needed++;
			}
			wake_up(&the_locks.write_wait);
		}
		spin_unlock_irqrestore(&the_locks.write_dsp_lock, flag);
		break;
	}
	case AUDPP_MSG_PCMDMAMISSED:
		MM_INFO("PCMDMAMISSED %d\n", msg[0]);
		prtd->eos_ack++;
		MM_DBG("PCMDMAMISSED Count per Buffer %d\n", prtd->eos_ack);
		wake_up(&the_locks.eos_wait);
		break;
	case AUDPP_MSG_CFG_MSG:
		if (msg[0] == AUDPP_MSG_ENA_ENA) {
			MM_DBG("CFG_MSG ENABLE\n");
			prtd->out_needed = 0;
			prtd->running = 1;
			audpp_dsp_set_vol_pan(prtd->session_id, &prtd->vol_pan,
					POPP);
			audpp_route_stream(prtd->session_id,
				msm_snddev_route_dec(prtd->session_id));
			audio_dsp_out_enable(prtd, 1);
		} else if (msg[0] == AUDPP_MSG_ENA_DIS) {
			MM_DBG("CFG_MSG DISABLE\n");
			prtd->running = 0;
		} else {
			MM_DBG("CFG_MSG %d?\n", msg[0]);
		}
		break;
	default:
		MM_DBG("UNKNOWN (%d)\n", id);
	}
}