//******************************************************************************
//
// Function Name:  VoIP_StopTelephony()
//
// Description:	This function stops full duplex telephony session
//
// Notes:	The full duplex DSP interface is in sharedmem, not vsharedmem.
//		But since its function is closely related to voice processing,
//		we put it here.
//
//******************************************************************************
Boolean VoIP_StopTelephony(void)
{
    int ret;

    Telephony_DumpVPFramesCB=NULL;
    Telephony_FillVPFramesCB=NULL;
    flush_workqueue(intr_workqueue);
    destroy_workqueue(intr_workqueue);

    intr_workqueue = NULL;

#ifdef USE_HR_TIMER
    OSTASK_Sleep( 40 );			// To make sure the timer is not running anymore
    ret = hrtimer_cancel( &hr_timer );
    if (ret) printk("The timer was still in use...\n");

     printk("HR Timer module uninstalling\n");

#else
    gpt_stop(VT_USE_GPT_INDEX);
    gpt_free(VT_USE_GPT_INDEX);
#endif

    return TRUE;
}
//******************************************************************************
//
// Function Name:  VoIP_StopTelephony()
//
// Description:	This function stops full duplex telephony session
//
// Notes:	The full duplex DSP interface is in sharedmem, not vsharedmem.
//		But since its function is closely related to voice processing,
//		we put it here.
//
//******************************************************************************
Boolean VoIP_StopTelephony(void)
{
    int ret;

    Telephony_DumpVPFramesCB=NULL;
    Telephony_FillVPFramesCB=NULL;

/* [email protected] 2011.12.02 start */
/* add patch CSP 476896 for audio loop */
/* review by liubing */
#ifdef USE_WORK_QUEUE_FOR_DL    
	flush_workqueue(intr_workqueue);
    destroy_workqueue(intr_workqueue);

    intr_workqueue = NULL;
#else	
	tasklet_kill(&(voip_task));
#endif	
/* [email protected] 2011.12.02 end */
	

#ifdef USE_HR_TIMER
    OSTASK_Sleep( 40 );			// To make sure the timer is not running anymore
    ret = hrtimer_cancel( &hr_timer );
    if (ret) printk("The timer was still in use...\n");

     printk("HR Timer module uninstalling\n");

#else
    gpt_stop(VT_USE_GPT_INDEX);
    gpt_free(VT_USE_GPT_INDEX);
#endif

    return TRUE;
}
static void bcm_gpt_clkevt_mode(enum clock_event_mode mode,
				struct clock_event_device *dev)
{
	unsigned long flags;

	switch (mode) {
	case CLOCK_EVT_MODE_PERIODIC:
		local_irq_save(flags);
		gc_ce.gmode = GPT_MODE_PERIODIC;
		local_irq_restore(flags);
		gpt_config(config.ce_index, &gc_ce,
				bcm_gpt_interrupt, NULL);
		gpt_start(config.ce_index, -1);
		break;
	case CLOCK_EVT_MODE_SHUTDOWN:
		gpt_stop(config.ce_index);
		break;
	case CLOCK_EVT_MODE_ONESHOT:
		local_irq_save(flags);
		gc_ce.gmode = GPT_MODE_ONESHOT;
		local_irq_restore(flags);
		gpt_config(config.ce_index, &gc_ce,
				bcm_gpt_interrupt, NULL);
		break;
	case CLOCK_EVT_MODE_RESUME:
	case CLOCK_EVT_MODE_UNUSED:
		break;
	}
}
/* ISR/Callback to handle GPT interrupts */
static int gpt_isr(void *dev_id)
{
	struct gpt_test *tt = (struct gpt_test *) dev_id;
	++tt->gpt_count;

	/* Stop the timer if we have interrupted the number of times */
	if (tt->gpt_count >= tt->gpt_num_times) {
		gpt_stop(tt->gpt_index);
		return 0;
	}

	/* If the timer is configured as Oneshot start the timer again here.
	 */
	if (tt->gpt_mode == GPT_MODE_ONESHOT) {
		gpt_start(tt->gpt_index, -1);
	}

	return 0;
}