int tdmb_fc8050_power_off(void)
{
	if ( fc8050_ctrl_info.TdmbPowerOnState == TRUE )
	{
		tdmb_fc8050_interrupt_lock();
		fc8050_ctrl_info.TdmbPowerOnState = FALSE;
		gpio_set_value(DMB_RESET_N, 0);
		gpio_set_value(DMB_EN, 0);
		//gpio_direction_output(DMB_INT_N, false);   
		gpio_set_value(DMB_INT_N, 0);		

#ifdef ANTENNA_SWITCHING
        gpio_set_value_cansleep(DMB_ANT_SEL_P_EAR, 1);
        gpio_set_value_cansleep(DMB_ANT_SEL_N_INNER, 0);  
#endif  /* ANTENNA_SWITCHING */

		wake_unlock(&fc8050_ctrl_info.wake_lock);

#ifdef PM_QOS		/* QoS release */
		if(pm_qos_request_active(&fc8050_ctrl_info.pm_req_list)) {
			pm_qos_update_request(&fc8050_ctrl_info.pm_req_list, PM_QOS_DEFAULT_VALUE);	
		}	
#endif
	}
	else
	{
		printk("tdmb_fc8050_power_on the power already turn off \n");
	}	

	printk("tdmb_fc8050_power_off completed \n");
	
	return TRUE;
}
Beispiel #2
0
int tdmb_fc8050_power_off(void)
{
	if ( fc8050_ctrl_info.TdmbPowerOnState == TRUE )
	{
		
		tdmb_fc8050_interrupt_lock();

		if(xo_handle_tdmb != NULL) {
		    msm_xo_mode_vote(xo_handle_tdmb, MSM_XO_MODE_OFF);
		}

		fc8050_ctrl_info.TdmbPowerOnState = FALSE;

		gpio_set_value(DMB_RESET_N, 0);
		gpio_set_value(DMB_EN, 0);

		wake_unlock(&fc8050_ctrl_info.wake_lock);

/*		if(pm_qos_request_active(&fc8050_ctrl_info.pm_req_list)) {
			pm_qos_update_request(&fc8050_ctrl_info.pm_req_list, PM_QOS_DEFAULT_VALUE);	
		}*/
	}
	else
	{
		printk("tdmb_fc8050_power_on the power already turn off \n");
	}	

	printk("tdmb_fc8050_power_off completed \n");
	return TRUE;
}
Beispiel #3
0
static int broadcast_tdmb_fc8050_probe(struct spi_device *spi)
{
	int rc;

	fc8050_ctrl_info.TdmbPowerOnState = FALSE;
	
	fc8050_ctrl_info.spi_ptr 				= spi;
	fc8050_ctrl_info.spi_ptr->mode 			= SPI_MODE_0;
	fc8050_ctrl_info.spi_ptr->bits_per_word 	= 8;
	fc8050_ctrl_info.spi_ptr->max_speed_hz 	= (24000*1000);
	rc = spi_setup(spi);
	printk("broadcast_tdmb_fc8050_probe spi_setup=%d\n", rc);
	BBM_HOSTIF_SELECT(NULL, 1);

    xo_handle_tdmb = msm_xo_get(MSM_XO_TCXO_A2, id);
	if(IS_ERR(xo_handle_tdmb)) {
		pr_err("Failed to get MSM_XO_TCXO_A2 handle for TDMB (%ld)\n", PTR_ERR(xo_handle_tdmb));
		return FALSE;
	}

#ifdef FEATURE_DMB_USE_WORKQUEUE
	INIT_WORK(&fc8050_ctrl_info.spi_work, broacast_tdmb_spi_work);
	fc8050_ctrl_info.spi_wq = create_singlethread_workqueue("tdmb_spi_wq");
	if(fc8050_ctrl_info.spi_wq == NULL){
		printk("Failed to setup tdmb spi workqueue \n");
		return -ENOMEM;
	}
#endif

	tdmb_configure_gpios( );

#ifdef FEATURE_DMB_USE_WORKQUEUE
	rc = request_irq(spi->irq, broadcast_tdmb_spi_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, 
	                   spi->dev.driver->name, &fc8050_ctrl_info);
#else
	rc = request_threaded_irq(spi->irq, NULL, broadcast_tdmb_spi_event_handler, IRQF_DISABLED | IRQF_TRIGGER_FALLING,
	                   spi->dev.driver->name, &fc8050_ctrl_info);
#endif
	printk("broadcast_tdmb_fc8050_probe request_irq=%d\n", rc);

	tdmb_fc8050_interrupt_lock();

	mutex_init(&fc8050_ctrl_info.mutex);

	wake_lock_init(&fc8050_ctrl_info.wake_lock,  WAKE_LOCK_SUSPEND, dev_name(&spi->dev));
	
	spin_lock_init(&fc8050_ctrl_info.spin_lock);

//	pm_qos_add_request(&fc8050_ctrl_info.pm_req_list, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
	
	printk("broadcast_fc8050_probe End\n");

	return rc;
}
int tdmb_fc8050_power_off(void)
{
	if ( fc8050_ctrl_info.TdmbPowerOnState == TRUE )
	{
		tdmb_fc8050_interrupt_lock();

#ifdef FEATURE_DMB_USE_XO
		if(fc8050_ctrl_info.clk != NULL) {
			clk_disable_unprepare(fc8050_ctrl_info.clk);
		}
#endif

		fc8050_ctrl_info.TdmbPowerOnState = FALSE;

		gpio_set_value(DMB_RESET_N, 0);
		gpio_set_value(DMB_EN, 0);

		wake_unlock(&fc8050_ctrl_info.wake_lock);

//		gpio_set_value(PM8058_GPIO_PM_TO_SYS(DMB_ANT_SEL_P-1), 1);	// for ESD TEST
//		gpio_set_value(PM8058_GPIO_PM_TO_SYS(DMB_ANT_SEL_N-1), 0);

#ifdef FEATURE_DMB_USE_BUS_SCALE
		msm_bus_scale_client_update_request(fc8050_ctrl_info.bus_scale_client_id, 0); /* expensive call, index:0 is the <84 512 0 0> entry */
#endif
#ifdef FEATURE_DMB_USE_PM_QOS
		if(pm_qos_request_active(&fc8050_ctrl_info.pm_req_list)) {
			pm_qos_update_request(&fc8050_ctrl_info.pm_req_list, PM_QOS_DEFAULT_VALUE);
		}
#endif
	}
	else
	{
		printk("tdmb_fc8050_power_on the power already turn off \n");
	}

	printk("tdmb_fc8050_power_off completed \n");
	return TRUE;
}
int tdmb_fc8050_spi_write_read(uint8* tx_data, int tx_length, uint8 *rx_data, int rx_length)
{
	int rc;

	struct spi_transfer	t = {
			.tx_buf		= tx_data,
			.rx_buf		= rx_data,
			.len		= tx_length+rx_length,
		};

	struct spi_message	m;	

	if (fc8050_ctrl_info.spi_ptr == NULL)
	{
		printk("tdmb_fc8050_spi_write_read error txdata=0x%x, length=%d\n", (unsigned int)tx_data, tx_length+rx_length);
	}

	mutex_lock(&fc8050_ctrl_info.mutex);

	spi_message_init(&m);
	spi_message_add_tail(&t, &m);
	rc = spi_sync(fc8050_ctrl_info.spi_ptr, &m);

	if ( rc < 0 )
	{
		printk("tdmb_fc8050_spi_read_burst result(%d), actual_len=%d\n",rc, m.actual_length);
	}

	mutex_unlock(&fc8050_ctrl_info.mutex);

	return TRUE;
}

#ifdef FEATURE_DMB_USE_WORKQUEUE
static irqreturn_t broadcast_tdmb_spi_isr(int irq, void *handle)
{
	struct tdmb_fc8050_ctrl_blk* fc8050_info_p;
	unsigned long flag;

	fc8050_info_p = (struct tdmb_fc8050_ctrl_blk *)handle;	
	if ( fc8050_info_p && fc8050_info_p->TdmbPowerOnState )
	{
		if (fc8050_info_p->spi_irq_status)
		{			
			printk("######### spi read function is so late skip #########\n");			
			return IRQ_HANDLED;
		}		
//		printk("***** broadcast_tdmb_spi_isr coming *******\n");

		spin_lock_irqsave(&fc8050_info_p->spin_lock, flag);
		queue_work(fc8050_info_p->spi_wq, &fc8050_info_p->spi_work);
		spin_unlock_irqrestore(&fc8050_info_p->spin_lock, flag);    
	}
	else
	{
		printk("broadcast_tdmb_spi_isr is called, but device is off state\n");
	}

	return IRQ_HANDLED; 
}

static void broacast_tdmb_spi_work(struct work_struct *tdmb_work)
{
	struct tdmb_fc8050_ctrl_blk *pTdmbWorkData;

	pTdmbWorkData = container_of(tdmb_work, struct tdmb_fc8050_ctrl_blk, spi_work);
	if ( pTdmbWorkData )
	{
		fc8050_isr_control(0);
		pTdmbWorkData->spi_irq_status = TRUE;
		broadcast_drv_if_isr();
		pTdmbWorkData->spi_irq_status = FALSE;
		fc8050_isr_control(1);
	}
	else
	{
		printk("~~~~~~~broadcast_tdmb_spi_work call but pTdmbworkData is NULL ~~~~~~~\n");
	}
}
#else
static irqreturn_t broadcast_tdmb_spi_event_handler(int irq, void *handle)
{	
	struct tdmb_fc8050_ctrl_blk* fc8050_info_p;

	fc8050_info_p = (struct tdmb_fc8050_ctrl_blk *)handle;	
	if ( fc8050_info_p && fc8050_info_p->TdmbPowerOnState )
	{
		if (fc8050_info_p->spi_irq_status)
		{			
			printk("######### spi read function is so late skip #########\n");			
			return IRQ_HANDLED;
		}		

		fc8050_isr_control(0);
		fc8050_info_p->spi_irq_status = TRUE;
		broadcast_drv_if_isr();
		fc8050_info_p->spi_irq_status = FALSE;
		fc8050_isr_control(1);
	}
	else
	{
		printk("broadcast_tdmb_spi_isr is called, but device is off state\n");
	}

	return IRQ_HANDLED;
} 
#endif


static int broadcast_tdmb_fc8050_probe(struct spi_device *spi)
{
	int rc;

#ifdef ANTENNA_SWITCHING
	struct pm_gpio GPIO11_CFG = {
				.direction      = PM_GPIO_DIR_OUT,
				.pull           = PM_GPIO_PULL_NO,
				.function       = PM_GPIO_FUNC_NORMAL,
				.vin_sel        = 2,
				.inv_int_pol    = 0,	
				};
	struct pm_gpio GPIO12_CFG = {
				.direction      = PM_GPIO_DIR_OUT,
				.pull           = PM_GPIO_PULL_NO,
				.function       = PM_GPIO_FUNC_NORMAL,
				.vin_sel        = 2,
				.inv_int_pol    = 0,			
				};	
#endif  /* ANTENNA_SWITCHING */

	fc8050_ctrl_info.TdmbPowerOnState = FALSE;
	
	fc8050_ctrl_info.spi_ptr 				= spi;
	fc8050_ctrl_info.spi_ptr->mode 			= SPI_MODE_0;
	fc8050_ctrl_info.spi_ptr->bits_per_word 	= 8;
	fc8050_ctrl_info.spi_ptr->max_speed_hz 	= ( 24000*1000 );
	rc = spi_setup(spi);

	printk("broadcast_tdmb_fc8050_probe spi_setup=%d\n", rc);

	BBM_HOSTIF_SELECT(NULL, 1);

#ifdef FEATURE_DMB_USE_WORKQUEUE
	INIT_WORK(&fc8050_ctrl_info.spi_work, broacast_tdmb_spi_work);
	fc8050_ctrl_info.spi_wq = create_singlethread_workqueue("tdmb_spi_wq");
	if(fc8050_ctrl_info.spi_wq == NULL){
		printk("Failed to setup tdmb spi workqueue \n");

		return -ENOMEM;
	}
#endif

	gpio_request(DMB_RESET_N, "DMB_RESET_N");
	gpio_request(DMB_EN, "DMB_EN");
	gpio_request(DMB_INT_N, "DMB_INT_N");
	//gpio_direction_output(DMB_RESET_N, false);      
	//gpio_direction_output(DMB_EN, false);               
	//gpio_direction_output(DMB_INT_N, false);           

#ifdef ANTENNA_SWITCHING
	pm8xxx_gpio_config(DMB_ANT_SEL_P_EAR, &GPIO11_CFG);
	pm8xxx_gpio_config(DMB_ANT_SEL_N_INNER, &GPIO12_CFG);

	gpio_set_value_cansleep(DMB_ANT_SEL_P_EAR, 1);
	gpio_set_value_cansleep(DMB_ANT_SEL_N_INNER, 0);
#endif  /* ANTENNA_SWITCHING */

#ifdef FEATURE_DMB_USE_WORKQUEUE
	rc = request_irq(spi->irq, broadcast_tdmb_spi_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, 
	                   spi->dev.driver->name, &fc8050_ctrl_info);
#else
	rc = request_threaded_irq(spi->irq, NULL, broadcast_tdmb_spi_event_handler, IRQF_DISABLED | IRQF_TRIGGER_FALLING,
	                      spi->dev.driver->name, &fc8050_ctrl_info);
#endif
	printk("broadcast_tdmb_fc8050_probe request_irq=%d\n", rc);


	tdmb_fc8050_interrupt_lock();

	mutex_init(&fc8050_ctrl_info.mutex);

	wake_lock_init(&fc8050_ctrl_info.wake_lock,  WAKE_LOCK_SUSPEND, dev_name(&spi->dev));		
	spin_lock_init(&fc8050_ctrl_info.spin_lock);

#ifdef PM_QOS
	pm_qos_add_request(&fc8050_ctrl_info.pm_req_list, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
#endif  /* PM_QOS */

	printk("broadcast_fc8050_probe End\n");

	return rc;
}

static int broadcast_tdmb_fc8050_remove(struct spi_device *spi)
{
	printk("broadcast_tdmb_fc8050_remove \n");

#ifdef FEATURE_DMB_USE_WORKQUEUE
	if (fc8050_ctrl_info.spi_wq)
	{
		flush_workqueue(fc8050_ctrl_info.spi_wq);
		destroy_workqueue(fc8050_ctrl_info.spi_wq);
	}
#endif
	free_irq(spi->irq, &fc8050_ctrl_info);

	mutex_destroy(&fc8050_ctrl_info.mutex);

	wake_lock_destroy(&fc8050_ctrl_info.wake_lock);

#ifdef PM_QOS
	pm_qos_remove_request(&fc8050_ctrl_info.pm_req_list);
#endif  /* PM_QOS */

	memset((unsigned char*)&fc8050_ctrl_info, 0x0, sizeof(struct tdmb_fc8050_ctrl_blk));

	return 0;
}

static int broadcast_tdmb_fc8050_suspend(struct spi_device *spi, pm_message_t mesg)
{
	printk("broadcast_tdmb_fc8050_suspend \n");
	return 0;
}
static int broadcast_tdmb_fc8050_probe(struct spi_device *spi)
{
	int rc;

	if(spi == NULL)
	{
		printk("broadcast_fc8050_probe spi is NULL, so spi can not be set\n");
		return -1;
	}

	fc8050_ctrl_info.TdmbPowerOnState = FALSE;
	fc8050_ctrl_info.spi_ptr 				= spi;
	fc8050_ctrl_info.spi_ptr->mode 			= SPI_MODE_0;
	fc8050_ctrl_info.spi_ptr->bits_per_word 	= 8;
	fc8050_ctrl_info.spi_ptr->max_speed_hz 	= (15000*1000);

#ifdef FEATURE_DMB_USE_BUS_SCALE
	fc8050_ctrl_info.pdev = to_platform_device(&spi->dev);
	fc8050_ctrl_info.bus_scale_pdata = msm_bus_cl_get_pdata(fc8050_ctrl_info.pdev);
	fc8050_ctrl_info.bus_scale_client_id = msm_bus_scale_register_client(fc8050_ctrl_info.bus_scale_pdata);
#endif

	// Once I have a spi_device structure I can do a transfer anytime

	rc = spi_setup(spi);
	printk("broadcast_tdmb_fc8050_probe spi_setup=%d\n", rc);
	BBM_HOSTIF_SELECT(NULL, 1);

#ifdef FEATURE_DMB_USE_XO
	fc8050_ctrl_info.clk = clk_get(&fc8050_ctrl_info.spi_ptr->dev, "xo");
	if (IS_ERR(fc8050_ctrl_info.clk)) {
		rc = PTR_ERR(fc8050_ctrl_info.clk);
		dev_err(&fc8050_ctrl_info.spi_ptr->dev, "could not get clock\n");
		return rc;
	}

	/* We enable/disable the clock only to assure it works */
	rc = clk_prepare_enable(fc8050_ctrl_info.clk);
	if (rc) {
		dev_err(&fc8050_ctrl_info.spi_ptr->dev, "could not enable clock\n");
		return rc;
	}
	clk_disable_unprepare(fc8050_ctrl_info.clk);
#endif

#ifdef FEATURE_DMB_USE_WORKQUEUE
	INIT_WORK(&fc8050_ctrl_info.spi_work, broacast_tdmb_spi_work);
	fc8050_ctrl_info.spi_wq = create_singlethread_workqueue("tdmb_spi_wq");
	if(fc8050_ctrl_info.spi_wq == NULL){
		printk("Failed to setup tdmb spi workqueue \n");
		return -ENOMEM;
	}
#endif

	tdmb_configure_gpios();

#ifdef FEATURE_DMB_USE_WORKQUEUE
	rc = request_irq(spi->irq, broadcast_tdmb_spi_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, 
	                   spi->dev.driver->name, &fc8050_ctrl_info);
#else
	rc = request_threaded_irq(spi->irq, NULL, broadcast_tdmb_spi_event_handler, IRQF_ONESHOT | IRQF_DISABLED | IRQF_TRIGGER_FALLING,
	                   spi->dev.driver->name, &fc8050_ctrl_info);
#endif
	printk("broadcast_tdmb_fc8050_probe request_irq=%d\n", rc);

	tdmb_fc8050_interrupt_lock();

	mutex_init(&fc8050_ctrl_info.mutex);

	wake_lock_init(&fc8050_ctrl_info.wake_lock,  WAKE_LOCK_SUSPEND, dev_name(&spi->dev));

	spin_lock_init(&fc8050_ctrl_info.spin_lock);

#ifdef FEATURE_DMB_USE_PM_QOS
	pm_qos_add_request(&fc8050_ctrl_info.pm_req_list, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
#endif
	printk("broadcast_fc8050_probe End\n");

	return rc;
}