示例#1
0
// Modified by somesoo 20100730 for removing green block effect
int8	tunerbb_drv_fc8050_multi_set_channel(int32 freq_num, uint8 subch_cnt, uint8 subch_id[ ], uint8 op_mode[ ])
{
	int8 res = BBM_OK;
	int32 freq = 0;
	uint8 dmb_cnt=0;
	int i;
	fc8050_service_type svcType = FC8050_SERVICE_MAX;
	unsigned short mask;
		
	// Added by somesoo 20100730 for removing green block effect
	fc8050_isr_control(0);
	
	for(i=0;i<subch_cnt;i++)
	{
		serviceType[i] = op_mode[i];

		if(FC8050_ENSQUERY != op_mode[i])
			tunerbb_drv_fc8050_stop();
		else
			svcType = FC8050_ENSQUERY;
	}
	
	tunerbb_drv_fc8050_control_fic(0);
	/* Change freq_num(channel num) to frequency */
	freq = tunerbb_drv_convert_chnum_to_freq(freq_num);

	if(freq == 0)
	{
		return FC8050_RESULT_ERROR;
	}

	res = BBM_TUNER_SET_FREQ(0, freq);
		
	if(res)
	{
		return FC8050_RESULT_ERROR;
	}
	
	if(svcType == FC8050_ENSQUERY)
	{
		if(BBM_SCAN_STATUS(0))
		{
			return FC8050_RESULT_ERROR;
		}
	}
		
	BBM_WORD_READ(NULL, BBM_BUF_ENABLE, &mask);
	mask &= 0x100;
	
	for(i=0;i<subch_cnt;i++)
	{
		switch(serviceType[i])
		{
			case FC8050_DAB:
				mask |= (1<<DAB_SVC_ID);
				BBM_AUDIO_SELECT(0, subch_id[i],DAB_SVC_ID);
#ifdef STREAM_TS_UPLOAD
				fc8050_demux_select_channel(subch_id[i], DAB_SVC_ID);
#else
				g_chinfo[subch_id[i]]=DAB_SVC_ID;
#endif
				break;
			case FC8050_DMB:
			case FC8050_VISUAL:
				mask |= (1<<(DMB_SVC_ID+dmb_cnt));	//LGE_BROADCAST_I
				if(dmb_cnt<2)
				{
					BBM_VIDEO_SELECT(0, subch_id[i], DMB_SVC_ID+dmb_cnt, dmb_cnt);
#ifdef STREAM_TS_UPLOAD
					fc8050_demux_select_video(subch_id[i], DMB_SVC_ID+dmb_cnt);
#else
					g_chinfo[subch_id[i]]=dmb_cnt;
#endif
					dmb_cnt++;
				}
				else
					res=BBM_NOK;
				break;
			case FC8050_DATA:
				mask |= (1<<DAT_SVC_ID);
				BBM_DATA_SELECT(0, subch_id[i], DAT_SVC_ID);
#ifdef STREAM_TS_UPLOAD
				fc8050_demux_select_channel(subch_id[i], DAT_SVC_ID);
#else
				g_chinfo[subch_id[i]]=DAT_SVC_ID;
#endif
				break;
			case FC8050_ENSQUERY:
				tunerbb_drv_fc8050_control_fic(1);
				res = BBM_OK;
				break;
			default:
				res = BBM_NOK;
				break;
		}
	}
	BBM_WORD_WRITE(NULL, BBM_BUF_ENABLE, mask);
	tot_subch_cnt = subch_cnt;

	// Added by somesoo 20100730 for removing green block effect
	if(svcType != FC8050_ENSQUERY)
		fc8050_isr_control(1);
	
	if(res)
		return FC8050_RESULT_ERROR;
	else
		return FC8050_RESULT_SUCCESS;
}
示例#2
0
/*--------------------------------------------------------------------------
int8 tunerbb_drv_fc8050_get_bbinfo(tdmb_status_rsp_type* dmb_bb_info)
    (1)   Getting the RF/BB Information 
    (2)   Return Value
           Sucess : 1
           Fail : 0 or negative interger (If there is error code)
    (3)   Argument
            tdmb_status_rsp_type* dmb_bb_info (IN/OUT)
           typedef struct tdmb_status_rsp_status
           {
                 uint32 dab_ok;
                 uint32 msc_ber;
                 uint32 sync_lock;
                 uint32 afc_ok;
                 uint32 cir;
                 uint32 fic_ber;
                 uint32 tp_lock;
                 uint32 sch_ber;
                 uint32 tp_err_cnt;
                 uint32 va_ber;
                 byte   srv_state_flag;
           };

           These paramters are dependent on Information supplied by Device.
---------------------------------------------------------------------------- */
int8	tunerbb_drv_fc8050_get_ber(struct broadcast_tdmb_sig_info *dmb_bb_info)
{
	uint8 sync_status;
	uint32 tp_err_cnt=0;

	fc8050_isr_control(0);

	tunerbb_drv_fc8050_check_overrun(serviceType[0]);

	dmb_bb_info->msc_ber=tunerbb_drv_fc8050_get_viterbi_ber();

	sync_status=tunerbb_drv_fc8050_get_sync_status();
	dmb_bb_info->sync_lock = ((sync_status & 0x10) ? 1 : 0);
	dmb_bb_info->cir = ((sync_status & 0x08) ? 1 : 0);
	dmb_bb_info->afc_ok = (((sync_status & 0x06)==0x06) ? 1 : 0);	
	
	if(dmb_bb_info->cir && dmb_bb_info->sync_lock)
	{
		dmb_bb_info->sch_ber = 1;
		// dab_ok : channel impulse response
		dmb_bb_info->dab_ok 	= 1;	
	}
	else
	{
		dmb_bb_info->sch_ber = 0;
		// dab_ok : channel impulse response
		dmb_bb_info->dab_ok 	= 0;	
	}
	
	if(serviceType[0] == FC8050_DMB || serviceType[0] == FC8050_VISUAL)
	{
		tp_err_cnt=tunerbb_drv_fc8050_rserror_count();
		if((dmb_bb_info->sync_lock == 0) || (tp_total_cnt == 0))
		{
			dmb_bb_info->tp_err_cnt = 0;
			dmb_bb_info->tp_lock = 0;
		}
		else if(tp_err_cnt == 0)
		{
			dmb_bb_info->tp_err_cnt = 0;
			dmb_bb_info->tp_lock = 1;
		}
		else //if(bb_info.tp_err_cnt > 0)
		{
			dmb_bb_info->tp_err_cnt = (uint32)((tp_err_cnt *1000)/(3*tp_total_cnt));
			dmb_bb_info->tp_lock = 0;
		}

		// initialize information		
		tp_total_cnt = 0;
	}
	else
	{
		dmb_bb_info->tp_err_cnt =0;
		dmb_bb_info->tp_lock	=0;
	}

	dmb_bb_info->fic_ber=0;
	dmb_bb_info->va_ber=tunerbb_drv_fc8050_get_rs_ber();
	dmb_bb_info->srv_state_flag=0;

	fc8050_isr_control(1);
	
	return FC8050_RESULT_SUCCESS;
}
/*--------------------------------------------------------------------------
int8 tunerbb_drv_fc8050_get_bbinfo(tdmb_status_rsp_type* dmb_bb_info)
    (1)   Getting the RF/BB Information 
    (2)   Return Value
           Sucess : 1
           Fail : 0 or negative interger (If there is error code)
    (3)   Argument
            tdmb_status_rsp_type* dmb_bb_info (IN/OUT)
           typedef struct tdmb_status_rsp_status
           {
                 uint32 dab_ok;
                 uint32 msc_ber;
                 uint32 sync_lock;
                 uint32 afc_ok;
                 uint32 cir;
                 uint32 fic_ber;
                 uint32 tp_lock;
                 uint32 sch_ber;
                 uint32 tp_err_cnt;
                 uint32 va_ber;
                 byte   srv_state_flag;
           };

           These paramters are dependent on Information supplied by Device.
---------------------------------------------------------------------------- */
int8	tunerbb_drv_fc8050_get_ber(struct broadcast_tdmb_sig_info *dmb_bb_info)
{
	uint8 sync_status;
	uint32 tp_err_cnt=0;

	uint16 nframe = 0;	

	fc8050_isr_control(0);

	tunerbb_drv_fc8050_check_overrun(serviceType[0]);

	dmb_bb_info->msc_ber = tunerbb_drv_fc8050_get_viterbi_ber();

	sync_status = tunerbb_drv_fc8050_get_sync_status();
	dmb_bb_info->sync_lock = ((sync_status & 0x10) ? 1 : 0);
	dmb_bb_info->cir = ((sync_status & 0x08) ? 1 : 0);
	dmb_bb_info->afc_ok = (((sync_status & 0x06)==0x06) ? 1 : 0);	
	
	if(dmb_bb_info->cir && dmb_bb_info->sync_lock)
	{
		dmb_bb_info->sch_ber = 1;
		// dab_ok : channel impulse response
		dmb_bb_info->dab_ok 	= 1;	
	}
	else
	{
		dmb_bb_info->sch_ber = 0;
		// dab_ok : channel impulse response
		dmb_bb_info->dab_ok 	= 0;	
	}
	
	if(serviceType[0] == FC8050_DMB || serviceType[0] == FC8050_VISUAL)
	{
		tp_err_cnt = tunerbb_drv_fc8050_rserror_count(&nframe); //실시간 frame수 체크
		
		if((dmb_bb_info->sync_lock == 0) || (tp_total_cnt == 0))
		{
			dmb_bb_info->tp_err_cnt = 0;
			dmb_bb_info->tp_lock = 0;
		}
		else if(tp_err_cnt == 0)
		{
			dmb_bb_info->tp_err_cnt = 0;
			dmb_bb_info->tp_lock = 1;
		}
		else //if(bb_info.tp_err_cnt > 0)
		{
			dmb_bb_info->tp_err_cnt = (uint32)((tp_err_cnt *1000)/(3*tp_total_cnt));
			dmb_bb_info->tp_lock = 0;
		}

		// initialize information		
		tp_total_cnt = 0;
	}
	else
	{
		dmb_bb_info->tp_err_cnt = 0;
		dmb_bb_info->tp_lock	= 0;
	}

	dmb_bb_info->fic_ber = 0;
	dmb_bb_info->va_ber = tunerbb_drv_fc8050_get_rs_ber();

	if(dmb_bb_info->msc_ber < 6000)
	{
		dmb_bb_info->antenna_level = 4;
	}
	else if(dmb_bb_info->msc_ber >= 6000 && dmb_bb_info->msc_ber < 8000)
	{
		dmb_bb_info->antenna_level = 3;
	}
	else if(dmb_bb_info->msc_ber >= 8000 && dmb_bb_info->msc_ber < 9000)
	{
		dmb_bb_info->antenna_level = 2;
	}
	else if(dmb_bb_info->msc_ber >= 9000 && dmb_bb_info->msc_ber < 12000)
	{
		dmb_bb_info->antenna_level = 1;
	}
	else if(dmb_bb_info->msc_ber >= 12000)
	{
		dmb_bb_info->antenna_level = 0;
	}

	//antenna level이 0이면 약전계이므로 5분종료를 위해 dab_ok를 0으로 만듬. 
	if(dmb_bb_info->antenna_level == 0)
	{
		dmb_bb_info->dab_ok = 0; 
	}
	fc8050_isr_control(1);
	
	return FC8050_RESULT_SUCCESS;
}
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;
}
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);
		return FALSE;
	}

	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 ignore #########\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 tdmb_configure_gpios(void)
{
	int rc = OK;
	int err_count = 0;

	rc = gpio_request(DMB_RESET_N, "DMB_RESET_N");
	if (rc < 0) {
		err_count++;
		printk("%s:Failed GPIO DMB_RESET_N request!!!\n",__func__);
	}

	rc = gpio_request(DMB_EN, "DMB_EN");
	if (rc < 0) {
		err_count++;
		printk("%s:Failed GPIO DMB_EN request!!!\n",__func__);
	}

	rc = gpio_request(DMB_INT_N, "DMB_INT_N");
	if (rc < 0) {
		err_count++;
		printk("%s:Failed GPIO DMB_INT_N request!!!\n",__func__);
	}

	gpio_direction_output(DMB_RESET_N, 0);
	gpio_direction_output(DMB_EN, 0);
	gpio_direction_input(DMB_INT_N);

	if(err_count > 0) rc = -EINVAL;

	return rc;
}