示例#1
0
/* ------------------- 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)
			audpcm_in_param_config(audio);
		else { /* Encoder disable success */
			audio->running = 0;
			audpcm_in_record_config(audio, 0);
		}
		break;
	}
	case AUDPREPROC_CMD_ENC_PARAM_CFG_DONE_MSG: {
		MM_DBG("CMD_ENC_PARAM_CFG_DONE_MSG \n");
		audpcm_in_mem_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);
	}
}
示例#2
0
/* ------------------- 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->dev_cnt > 0)
			audpcm_in_record_config(audio, 1);
		break;
	}
	case AUDREC_FATAL_ERR_MSG: {
		struct audrec_fatal_err_msg fatal_err_msg;

		getevent(&fatal_err_msg, AUDREC_FATAL_ERR_MSG_LEN);
		MM_AUD_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);
		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);

		audpcm_in_get_dsp_frames(audio);
		break;
	}
	case ADSP_MESSAGE_ID:
		MM_DBG("audrec: enable/disable done\n");
		break;
	default:
		MM_AUD_ERR("Unknown Event id %d\n", id);
	}
}
示例#3
0
static void pcm_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))
			audpcm_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)
			audpcm_in_record_config(audio, 1);
		else
			/* Turn off all */
			audpcm_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)
                                audpcm_in_record_config(audio, 1);
                        else if (audio->voice_state == VOICE_STATE_OFFCALL) {
                                audpcm_in_record_config(audio, 0);
                                wake_up(&audio->wait);
                        }
                }
                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) {
			/* Stop Recording sample rate does not match
			   with device sample rate */
			if (evt_payload->freq_info.sample_rate !=
				audio->samp_rate) {
				audpcm_in_record_config(audio, 0);
				audio->abort = 1;
				wake_up(&audio->wait);
			}
		}
		break;
	}
	default:
		MM_AUD_ERR("wrong event %d\n", evt_id);
		break;
	}
}
/* ------------------- 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_STOP) {
		unsigned long flags;
		MM_DBG("AUDIO_STOP\n");
		spin_lock_irqsave(&audio->dsp_lock, flags);
		audio->stopped = 1;
		spin_unlock_irqrestore(&audio->dsp_lock, flags);
		wake_up(&audio->wait_voice_incall);
	}

	mutex_lock(&audio->lock);

	switch (cmd) {

	case 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)))
			rc = -EFAULT;
		break;
        }
	case AUDIO_GET_VOICE_STATE: {
		int vstate = audio->voice_state;
		if (copy_to_user((void *) arg, &vstate, sizeof(vstate)))
			rc = -EFAULT;
		break;
        }
        case AUDIO_GET_DEV_DRV_VER: {
                unsigned int vers = DEV_DRV_VER;
                if (copy_to_user((void *) arg, &vers, sizeof(vers)))
                        rc = -EFAULT;
                break;
	}
	case AUDIO_START: {

		uint32_t freq;
		struct timespec ts;	
		/* Poll at 48KHz always */
		freq = 48000;
		MM_DBG("AUDIO_START\n");

		if (audio->in_call && (audio->voice_state != VOICE_STATE_INCALL)) {
			ts = CURRENT_TIME;
			rc = wait_event_interruptible(audio->wait_voice_incall,
				audio->voice_state == VOICE_STATE_INCALL || audio->stopped);
			if(rc < 0 || audio->voice_state != VOICE_STATE_INCALL || audio->stopped) {
				MM_DBG("valid incall state unreacheable\n");
				return -EPERM;
			}
			ts = timespec_sub(CURRENT_TIME,ts);
			MM_DBG("waited %ld.%03ld sec for voice incall state\n", ts.tv_sec, ts.tv_nsec/NSEC_PER_MSEC);
		}

		rc = msm_snddev_request_freq(&freq, audio->enc_id, SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
		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;
		}
		MM_DBG("freq configured for %d\n", freq);

		rc = audpcm_in_enable(audio);
		if (rc == 0) {
			ts = CURRENT_TIME;
			rc = wait_event_interruptible_timeout(audio->wait_enable, audio->running != 0, 3*HZ);
			ts = timespec_sub(CURRENT_TIME,ts);
			MM_DBG("state = %d, rc = %d after %ld.%03ld sec\n", audio->running, rc, 
							ts.tv_sec, ts.tv_nsec/NSEC_PER_MSEC);
			rc = (audio->running == 0) ? -ENODEV : 0;
		} else MM_DBG("failed to enable audpcm\n");

		if (rc == 0 && audio->in_call) {
			rc = audpcm_in_record_config(audio, 1);
			if (rc != 0) MM_ERR("failed to send record config cmd\n");
			else  {
				ts = CURRENT_TIME;
				atomic_set(&audio->rec_conf,0);
				wait_event_interruptible_timeout(audio->wait_rec_cfg,
					atomic_read(&audio->rec_conf) != 0, 3*HZ);
				if (atomic_read(&audio->rec_conf) == 0) {
					MM_DBG("failed to config recording\n");
					rc = -EFAULT;
				} else {
					ts = timespec_sub(CURRENT_TIME,ts);
					MM_DBG("record config success after %ld.%03ld sec\n",
							ts.tv_sec, ts.tv_nsec/NSEC_PER_MSEC);
				}
			}
		}
		audio->stopped = 0;
		break;
	}
	case AUDIO_STOP: {
		rc = audpcm_in_disable(audio);
		if (rc != 0) MM_DBG("failed to stop audio\n");
		rc = msm_snddev_withdraw_freq(audio->enc_id,SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
		break;
	}
	case AUDIO_FLUSH: {
		MM_DBG("AUDIO_FLUSH\n");
		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);
			if (!mutex_trylock(&audio->read_lock)) 
				do {
					msleep(50);
					wake_up(&audio->wait);
				} while (!mutex_trylock(&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 (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;
		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;
                MM_DBG("AUDIO_SET_INCALL\n");
                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;
	}
	if(rc != 0) MM_DBG("returning error %d\n",rc);
	mutex_unlock(&audio->lock);
	return rc;
}