int had_process_hot_unplug(struct snd_intelhad *intelhaddata)
{
	int caps, retval = 0;
	enum intel_had_aud_buf_type buf_id;
	struct had_pvt_data *had_stream;
	unsigned long flag_irqs;

	pr_debug("Enter:%s", __func__);

	had_stream = intelhaddata->private_data;
	buf_id = intelhaddata->curr_buf;

	spin_lock_irqsave(&intelhaddata->had_spinlock, flag_irqs);
	if (intelhaddata->drv_status == HAD_DRV_DISCONNECTED) {
		pr_debug("Device already disconnected\n");
		spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);
		return retval;
	} else {
		/* Disable Audio */
		caps = HDMI_AUDIO_BUFFER_DONE;
		retval = had_set_caps(HAD_SET_DISABLE_AUDIO_INT, &caps);
		retval = had_set_caps(HAD_SET_DISABLE_AUDIO, NULL);
		intelhaddata->ops->enable_audio(intelhaddata->stream_info.had_substream, 0);
	}

	intelhaddata->drv_status = HAD_DRV_DISCONNECTED;
	/* Report to above ALSA layer */
	if (intelhaddata->stream_info.had_substream != NULL) {
		spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);
		pr_debug("%s: unlock -> sending pcm_stop -> lock\n", __func__);
		mutex_lock(&had_mutex);
		if (intelhaddata->stream_info.had_substream != NULL)
			snd_pcm_stop(intelhaddata->stream_info.had_substream,
				SNDRV_PCM_STATE_DISCONNECTED);
		mutex_unlock(&had_mutex);
		spin_lock_irqsave(&intelhaddata->had_spinlock, flag_irqs);
	}

	had_stream->stream_type = HAD_INIT;
	spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);
	kfree(intelhaddata->chmap->chmap);
	intelhaddata->chmap->chmap = NULL;
	pr_debug("%s: unlocked -> returned\n", __func__);

	return retval;
}
/**
 * hdmi_audio_suspend - power management suspend function
 *
 *@haddata: pointer to HAD private data
 *@event: pm event for which this method is invoked
 *
 * This function is called by client driver to suspend the
 * hdmi audio.
 */
int hdmi_audio_suspend(void *haddata, hdmi_audio_event_t event)
{
	int caps, retval = 0;
	struct had_pvt_data *had_stream;
	unsigned long flag_irqs;
	struct snd_pcm_substream *substream;
	struct snd_intelhad *intelhaddata = (struct snd_intelhad *)haddata;

	pr_debug("Enter:%s", __func__);

	had_stream = intelhaddata->private_data;
	substream = intelhaddata->stream_info.had_substream;

	if (intelhaddata->dev->power.runtime_status != RPM_SUSPENDED) {
		pr_err("audio stream is active\n");
		return -EAGAIN;
	}


	spin_lock_irqsave(&intelhaddata->had_spinlock, flag_irqs);
	if (intelhaddata->drv_status == HAD_DRV_DISCONNECTED) {
		spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);
		pr_debug("had not connected\n");
		return retval;
	}

	if (intelhaddata->drv_status == HAD_DRV_SUSPENDED) {
		spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);
		pr_debug("had already suspended\n");
		return retval;
	}

	intelhaddata->drv_status = HAD_DRV_SUSPENDED;
	spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);
	/* ToDo: Need to disable UNDERRUN interrupts as well
	   caps = HDMI_AUDIO_UNDERRUN | HDMI_AUDIO_BUFFER_DONE;
	   */
	caps = HDMI_AUDIO_BUFFER_DONE;
	had_set_caps(HAD_SET_DISABLE_AUDIO_INT, &caps);
	had_set_caps(HAD_SET_DISABLE_AUDIO, NULL);
	pr_debug("Exit:%s", __func__);
	return retval;
}
示例#3
0
/**
 * hdmi_audio_remove - removes the alsa card
 *
 *@haddata: pointer to HAD private data
 *
 * This function is called when the hdmi cable is un-plugged. This function
 * free the sound card.
 */
static int __devexit hdmi_audio_remove(struct platform_device *devptr)
{
	struct snd_intelhad *intelhaddata = had_data;
	int caps;

	pr_debug("Enter %s\n", __func__);

	if (!intelhaddata)
		return 0;

	if (intelhaddata->drv_status != HAD_DRV_DISCONNECTED) {
		caps = HDMI_AUDIO_UNDERRUN | HDMI_AUDIO_BUFFER_DONE;
		had_set_caps(HAD_SET_DISABLE_AUDIO_INT, &caps);
		had_set_caps(HAD_SET_DISABLE_AUDIO, NULL);
	}
	kfree(intelhaddata->flat_data);
	snd_card_free(intelhaddata->card);
	kfree(intelhaddata->private_data);
	kfree(intelhaddata);
	return 0;
}
/**
 * hdmi_audio_resume - power management resume function
 *
 *@haddata: pointer to HAD private data
 *
 * This function is called by client driver to resume the
 * hdmi audio.
 */
int hdmi_audio_resume(void *haddata)
{
	int caps, retval = 0;
	struct snd_intelhad *intelhaddata = (struct snd_intelhad *)haddata;
	unsigned long flag_irqs;

	pr_debug("Enter:%s", __func__);

	spin_lock_irqsave(&intelhaddata->had_spinlock, flag_irqs);
	if (intelhaddata->drv_status == HAD_DRV_DISCONNECTED) {
		spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);
		pr_debug("had not connected\n");
		return 0;
	}

	if (HAD_DRV_SUSPENDED != intelhaddata->drv_status) {
		spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);
		pr_err("had is not in suspended state\n");
		return 0;
	}

	if (had_get_hwstate(intelhaddata)) {
		spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);
		pr_err("Failed to resume. Device not accessible\n");
		return -ENODEV;
	}

	intelhaddata->drv_status = HAD_DRV_CONNECTED;
	spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);
	/* ToDo: Need to enable UNDERRUN interrupts as well
	   caps = HDMI_AUDIO_UNDERRUN | HDMI_AUDIO_BUFFER_DONE;
	   */
	caps = HDMI_AUDIO_BUFFER_DONE;
	retval = had_set_caps(HAD_SET_ENABLE_AUDIO_INT, &caps);
	retval = had_set_caps(HAD_SET_ENABLE_AUDIO, NULL);
	pr_debug("Exit:%s", __func__);
	return retval;
}
示例#5
0
/**
* snd_intelhad_pcm_trigger - stream activities are handled here
* @substream:substream for which the stream function is called
* @cmd:the stream commamd thats requested from upper layer
* This function is called whenever an a stream activity is invoked
*/
static int snd_intelhad_pcm_trigger(struct snd_pcm_substream *substream,
					int cmd)
{
	int caps, retval = 0;
	unsigned long flag_irq;
	struct snd_intelhad *intelhaddata;
	struct had_stream_pvt *stream;
	struct had_pvt_data *had_stream;

	intelhaddata = snd_pcm_substream_chip(substream);
	stream = substream->runtime->private_data;
	had_stream = intelhaddata->private_data;

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
		pr_debug("Trigger Start\n");

		/* Disable local INTRs till register prgmng is done */
		if (had_get_hwstate(intelhaddata)) {
			pr_err("_START: HDMI cable plugged-out\n");
			retval = -ENODEV;
			break;
		}
		stream->stream_status = STREAM_RUNNING;

		spin_lock_irqsave(&intelhaddata->had_spinlock, flag_irq);
		had_stream->stream_type = HAD_RUNNING_STREAM;
		spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irq);

		/* Enable Audio */
		/* ToDo: Need to enable UNDERRUN interrupts as well
		   caps = HDMI_AUDIO_UNDERRUN | HDMI_AUDIO_BUFFER_DONE;
		   */
		caps = HDMI_AUDIO_BUFFER_DONE;
		retval = had_set_caps(HAD_SET_ENABLE_AUDIO_INT, &caps);
		retval = had_set_caps(HAD_SET_ENABLE_AUDIO, NULL);
		had_read_modify(AUD_CONFIG, 1, BIT(0));

		pr_debug("Processed _Start\n");

		break;

	case SNDRV_PCM_TRIGGER_STOP:
		pr_debug("Trigger Stop\n");
		spin_lock_irqsave(&intelhaddata->had_spinlock, flag_irq);
		intelhaddata->stream_info.str_id = 0;
		intelhaddata->curr_buf = 0;

		/* Stop reporting BUFFER_DONE/UNDERRUN to above layers*/

		had_stream->stream_type = HAD_INIT;
		spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irq);
		/* Disable Audio */
		/* ToDo: Need to disable UNDERRUN interrupts as well
		   caps = HDMI_AUDIO_UNDERRUN | HDMI_AUDIO_BUFFER_DONE;
		   */
		caps = HDMI_AUDIO_BUFFER_DONE;
		had_set_caps(HAD_SET_DISABLE_AUDIO_INT, &caps);
		had_set_caps(HAD_SET_DISABLE_AUDIO, NULL);
		had_read_modify(AUD_CONFIG, 0, BIT(0));
		/* Reset buffer pointers */
		had_write_register(AUD_HDMI_STATUS, 1);
		had_write_register(AUD_HDMI_STATUS, 0);
		stream->stream_status = STREAM_DROPPED;
		break;

	default:
		retval = -EINVAL;
	}
	return retval;
}