/*************************************************************************** * Copyright (c) 2003-2008, Broadcom Corporation * All Rights Reserved * Confidential Property of Broadcom Corporation * * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. * * $brcm_Workfile: $ * $brcm_Revision: $ * $brcm_Date: $ * * Module Description: * * Revision History: * * $brcm_Log: $ * * ***************************************************************************/ #include "bsettop_rfm.h" #include "gist.h" #include "bi2c.h" #include "breg_i2c.h" #include "bstd.h" #include "bos_task_priorities.h" #if (BCHP_CHIP==7552) #include "brfm.h" #endif //#define RFM_USE_INT 1 #ifdef RFM_USE_INT #include "bsettop_gpio.h" #endif BDBG_MODULE(brfm); /* Register software module with debug interface */ #define BRFM_I2C_BUS 2 #define BRFM_I2C_ADDR 0x65 #define BRFM_TASK_STACK_WORDS 256 #if (BCHP_CHIP==7552) #if 1/*janzy@20120731*/ #define RFM_GPIO_NUM BGIO_PinId_eAgpio09 #else #define RFM_GPIO_NUM BGIO_PinId_eAgpio20 #endif #else #define RFM_GPIO_NUM BGIO_PinId_eGpio100 #endif struct brfm { bool inUSE; #if (BCHP_CHIP==7552) BRFM_Handle rfmHandle; #else BI2C_ChannelHandle i2cChannelHandle; BREG_I2C_Handle i2cRegHandle; uint16_t chipAddr; #endif BGIO_Pin_Handle pinHandle; BGIO_PinValue lastValue; b_task_t task_h; #ifdef RFM_USE_INT bgpio_t gpioHandle; b_queue_t queue; b_event_t events[4]; #endif #ifdef ACB612 bool rfm; /* rfm CH3/4 for ACB612 */ #endif unsigned int task_stack[BRFM_TASK_STACK_WORDS]; }; #if (BCHP_CHIP==7552) struct brfm s_rfm = { false, NULL, NULL,BGIO_PinValue_eInvalid, 0}; #else struct brfm s_rfm = { false, NULL, NULL,BRFM_I2C_ADDR,NULL,BGIO_PinValue_eInvalid, 0}; #endif #ifdef RFM_USE_INT static void switch_callback(void *context) { brfm_t p_rfm = (brfm_t)context; b_event_t event; bos_post_event(p_rfm->queue, &event); } #endif #ifndef ACB612 /*************************************************************************** Summary: Thread to monitor RFM switch. Due to how the RF4CE handles GPIO interrupts and to possibly implement debounce logic it is simpler to poll for RFM switch status than make it interrupt driven. ***************************************************************************/ static void rfm_task(void *arg) { brfm_t p_rfm = (brfm_t)arg; #if (BCHP_CHIP==7552) BRFM_OutputChannel chNbr; #else uint8_t data_wr[4]; #endif BERR_Code err; p_rfm->lastValue = 0xFF; /* forces an update */ bos_sleep(1999); /* sleep for 2sec */ while(1) { BGIO_PinValue pinValue; BDBG_MSG(("%s:%d",__FUNCTION__,__LINE__)); #ifdef RFM_USE_INT bos_pend_event(p_rfm->queue, -1); #endif #ifndef ACB612 if (BGIO_Pin_GetValue(p_rfm->pinHandle,&pinValue) == BERR_SUCCESS) #else pinValue = p_rfm->rfm ? BGIO_PinValue_e1 : BGIO_PinValue_e0; #endif { if (pinValue != p_rfm->lastValue) { p_rfm->lastValue = pinValue; BDBG_ERR(("%s:%d, %d BGIO_Pin_GetValue = %d",__FUNCTION__,__LINE__,100,p_rfm->lastValue)); if (p_rfm->lastValue == BGIO_PinValue_e1) { #if (BCHP_CHIP==7552) chNbr = BRFM_OutputChannel_eCh4; #else data_wr[2] = 0x21; /* CH 4 */ #endif } else { #if (BCHP_CHIP==7552) chNbr = BRFM_OutputChannel_eCh3; #else data_wr[2] = 0x1E; /* CH 3 */ #endif } #if (BCHP_CHIP==7552) err = BRFM_SetModulationType(p_rfm->rfmHandle, BRFM_ModulationType_eNtscOpenCable, chNbr); if (err != BERR_SUCCESS) { BDBG_ERR(("%s:%d, BRFM_SetModulationType failed", __FUNCTION__,__LINE__)); } #else data_wr[3] = 0xA0; err = BREG_I2C_WriteNoAddr(p_rfm->i2cRegHandle,p_rfm->chipAddr,&data_wr[2],2); if (err != BERR_SUCCESS) { BDBG_ERR(("%s:%d, BREG_I2C_WriteNoAddr failed = %d(0x%08x)",__FUNCTION__,__LINE__,err,err)); } //data_wr[0] = 0x80; //data_wr[1] = 0x00; bos_sleep(2000); data_wr[3] = 0xA3; err = BREG_I2C_WriteNoAddr(p_rfm->i2cRegHandle,p_rfm->chipAddr,&data_wr[2],2); //err = BREG_I2C_WriteNoAddr(p_rfm->i2cRegHandle,p_rfm->chipAddr,&data_wr[0],4); if (err != BERR_SUCCESS) { BDBG_ERR(("%s:%d, BREG_I2C_WriteNoAddr failed = %d(0x%08x)",__FUNCTION__,__LINE__,err,err)); } #endif } } #ifndef RFM_USE_INT BKNI_Sleep(500); #endif } } #endif /* Summary: Open and allocate RFM resources. Description: On most platforms, the rfm_id is simply an index of the rf modulator. */ brfm_t brfm_open( bobject_t rfm_id /* - index used to identify a particular rfm */ ) { BERR_Code err; #ifndef ACB612 b_task_params task_params; #endif BGIO_PinValue pinValue; #if (BCHP_CHIP==7552) BRFM_Settings rfmSettings; BRFM_OutputChannel chNbr; #else BI2C_ChannelSettings defChnSettings; uint8_t data_wr[4]; #endif brfm_t p_rfm; #ifdef RFM_USE_INT b_event_t event; bgpio_settings gpio_settings; #endif if (s_rfm.inUSE) { return NULL; } p_rfm = &s_rfm; #if (BCHP_CHIP==7552) BRFM_GetDefaultSettings(&rfmSettings, GetCHP()); err = BRFM_Open(&p_rfm->rfmHandle, GetCHP(), GetREG(), GetINT(), &rfmSettings); if (err != BERR_SUCCESS) { BDBG_WRN(("Fail to open RFM module")); return NULL; } #else BI2C_GetChannelDefaultSettings( GetI2C(), BRFM_I2C_BUS, &defChnSettings ); defChnSettings.intMode = true; defChnSettings.clkRate = BI2C_Clk_eClk400Khz; BI2C_OpenChannel( GetI2C(), &(p_rfm->i2cChannelHandle), BRFM_I2C_BUS, &defChnSettings ); BDBG_ASSERT(p_rfm->i2cChannelHandle); BI2C_CreateI2cRegHandle (p_rfm->i2cChannelHandle, &(p_rfm->i2cRegHandle)); BDBG_ASSERT(p_rfm->i2cRegHandle); #endif err = BGIO_Pin_Create(GetGIO(),RFM_GPIO_NUM,&p_rfm->pinHandle); if (err != BERR_SUCCESS) { brfm_close(p_rfm); return NULL; } #if (BCHP_CHIP==7552) chNbr = BRFM_OutputChannel_eCh3; #else /* Configure modulator */ data_wr[0] = 0x90; data_wr[1] = 0x00; data_wr[2] = 0x1E; #endif #ifndef ACB612 if (BGIO_Pin_GetValue(p_rfm->pinHandle,&pinValue) == BERR_SUCCESS) #else pinValue = p_rfm->rfm ? BGIO_PinValue_e1 : BGIO_PinValue_e0; #endif { if (pinValue == BGIO_PinValue_e1) { #if (BCHP_CHIP==7552) chNbr = BRFM_OutputChannel_eCh4; #else data_wr[2] = 0x21; /* CH 4 */ #endif } } #if (BCHP_CHIP==7552) err = BRFM_SetModulationType(p_rfm->rfmHandle, BRFM_ModulationType_eNtscOpenCable, chNbr); if (err != BERR_SUCCESS) { BDBG_WRN(("%s:%d BRFM_SetModulationType failed", __FUNCTION__, __LINE__)); } #else data_wr[3] = 0xA0; err = BREG_I2C_WriteNoAddr(p_rfm->i2cRegHandle,p_rfm->chipAddr,data_wr,4); if (err != BERR_SUCCESS) { brfm_close(p_rfm); return NULL; } #endif #ifdef RFM_USE_INT bos_create_queue(&p_rfm->queue, p_rfm->events, 4); #if (BCHP_CHIP==7552) gpio_settings.type = eGPIO_AStandard; #else gpio_settings.type = eGPIO_Standard; #endif gpio_settings.mode = eGPIO_Input; gpio_settings.intMode = eGPIO_Edge; gpio_settings.user_callback = switch_callback; gpio_settings.user_callback_context =p_rfm; p_rfm->gpioHandle = bgpio_open(RFM_GPIO_NUM, &gpio_settings); #endif p_rfm->inUSE = true; /* ACB612 doesn't have CH3/4 button, but software control, so don't need a task to monitor the GPIO */ #ifndef ACB612 task_params.name = "RFM_TASK"; task_params.priority = RFM_PRIORITY; task_params.stack = p_rfm->task_stack; task_params.stack_size = BRFM_TASK_STACK_WORDS; bos_start_task(&(p_rfm->task_h),&task_params,rfm_task,p_rfm); #endif #ifdef RFM_USE_INT /* set initial RF channel */ bos_post_event(p_rfm->queue, &event); #endif return p_rfm; } /* Summary: Close the rfm. */ void brfm_close( brfm_t rfm /* - handle returned by brfm_open */ ) { BDBG_ASSERT(rfm); if (rfm->pinHandle) BGIO_Pin_Destroy(rfm->pinHandle); #if (BCHP_CHIP==7552) if (rfm->rfmHandle) BRFM_Close(rfm->rfmHandle); #else if (rfm->i2cRegHandle) BI2C_CloseI2cRegHandle(rfm->i2cRegHandle); if (rfm->i2cChannelHandle) BI2C_CloseChannel(rfm->i2cChannelHandle); #endif #ifdef RFM_USE_INT if (rfm->gpioHandle) bgpio_close(rfm->gpioHandle); #endif if (rfm->task_h) bos_stop_task(rfm->task_h); rfm->pinHandle = NULL; #if (BCHP_CHIP==7552) rfm->rfmHandle = NULL; #else rfm->i2cRegHandle = NULL; rfm->i2cChannelHandle = NULL; #endif rfm->task_h = 0; #ifdef RFM_USE_INT rfm->gpioHandle = NULL; bos_delete_queue(&rfm->queue); #endif rfm->inUSE = false; } /* * Summary: * power management for RFM block */ void brfm_standby(brfm_t rfm, bool standby) { if (standby) { BRFM_Standby(rfm->rfmHandle); } else { BRFM_Resume(rfm->rfmHandle); } } void buser_AOV_input_LED(brfm_t rfm, ledStatus_t eLED) { BERR_Code err; static BGIO_Pin_Handle pinLED_R = NULL; static BGIO_Pin_Handle pinLED_G = NULL; pinLED_G = rfm->pinHandle; if(pinLED_R == NULL) { err = BGIO_Pin_Create(GetGIO(),BGIO_PinId_eAgpio04,&pinLED_R); if (err != BERR_SUCCESS) { BDBG_ERR(("BGIO_PinId_eAgpio04 Fail")); return; } BGIO_Pin_SetType(pinLED_R,BGIO_PinType_ePushPull); BGIO_Pin_SetType(pinLED_G,BGIO_PinType_ePushPull); } switch(eLED) { case eLED_Status_R: BGIO_Pin_PushPull_SetValue(pinLED_G,BGIO_PinValue_e0); BGIO_Pin_PushPull_SetValue(pinLED_R,BGIO_PinValue_e1); break; case eLED_Status_G: BGIO_Pin_PushPull_SetValue(pinLED_G,BGIO_PinValue_e1); BGIO_Pin_PushPull_SetValue(pinLED_R,BGIO_PinValue_e0); break; case eLED_Status_OFF: BGIO_Pin_PushPull_SetValue(pinLED_G,BGIO_PinValue_e0); BGIO_Pin_PushPull_SetValue(pinLED_R,BGIO_PinValue_e0); break; case eLED_Status_RG: BGIO_Pin_PushPull_SetValue(pinLED_G,BGIO_PinValue_e1); BGIO_Pin_PushPull_SetValue(pinLED_R,BGIO_PinValue_e1); break; } return; } /* * Summary: * change CH3 or CH4 */ void brfm_set_ch3(brfm_t p_rfm, bool ch) { #ifdef ACB612 BRFM_OutputChannel chNbr; if (!p_rfm) { BDBG_ERR(("%s: Not initialized",__func__)); return; } s_rfm.rfm = ch ? BGIO_PinValue_e1 : BGIO_PinValue_e0; if (p_rfm->rfm != p_rfm->lastValue) { p_rfm->lastValue = p_rfm->rfm; BDBG_ERR(("%s: previous %s",__func__,p_rfm->lastValue ? "CH4" : "CH3")); if (BGIO_PinValue_e1 == p_rfm->rfm) { chNbr = BRFM_OutputChannel_eCh4; } else { chNbr = BRFM_OutputChannel_eCh3; } if (BERR_SUCCESS != BRFM_SetModulationType(p_rfm->rfmHandle, BRFM_ModulationType_eNtscOpenCable, chNbr)) { BDBG_ERR(("%s BRFM_SetModulationType failed", __func__)); } } #endif }