static ssize_t reset_reason_show(struct device *dev, struct device_attribute *attr, char *buf) { int index; #ifdef CONFIG_BCM_POWEROFF_CHARGING int reset_reason; reset_reason = board_sysconfig(SYSCFG_RESETREASON_SOFT_RESET, SYSCFG_INIT); switch (reset_reason) { case POWER_ON_RESET: index = 0; break; case SOFT_RESET: index = 1; break; case POWEROFF_CHARGING: index = 2; board_sysconfig(SYSCFG_RESETREASON_SOFT_RESET, SYSCFG_ENABLE); break; default: index = 3; break; } sprintf(buf, "%s\n", str_reset_reason[index]); #else /* BCM_POWEROFF_CHARGING */ index = 0; /* Return POWER_ON_RESET always */ #endif /* BCM_POWEROFF_CHARGING */ return strlen(str_reset_reason[index]) + 1; }
// Switch class work to update state of headset static void switch_work(struct work_struct *work) { struct h2w_switch_data *data = container_of(to_delayed_work(work), struct h2w_switch_data, work); int headset_state; if (mic.headset_pd->check_hs_state) { enable_irq(mic.hsirq); mic.headset_pd->check_hs_state(&headset_state); /* Check headset state after the debounce time, * if same exit, as there is no state change */ if (headset_state == mic.headset_state) return; mic.headset_state = headset_state; } switch_set_state(&data->sdev, mic.headset_state); if(mic.headset_state){ if(mic.hsbst){ mic.hsbst = 0; /* Turn on the Rx LDO on headset insertion, this * will only be applicable if headset detect is from GPIO */ if (mic.headset_pd->check_hs_state) writel(AUDIO_RX_LDO_ON(readl(io_p2v(REG_ANACR2))), io_p2v(REG_ANACR2)); board_sysconfig(SYSCFG_AUXMIC, SYSCFG_INIT); enable_irq(mic.hsbirq); } } else { if(!mic.hsbst){ disable_irq(mic.hsbirq); /* Turn off the Rx LDO on headset removal, this will only be * applicable if headset detect is from GPIO */ if (mic.headset_pd->check_hs_state) // [email protected] 2012.05.02 begin // fix bug csp 522980. merge brcm patch { if (!((readl(io_p2v(REG_ANACR2))) & 0x4)) writel(AUDIO_RX_LDO_OFF(readl(io_p2v(REG_ANACR2))), io_p2v(REG_ANACR2)); } // [email protected] 2012.05.02 end board_sysconfig(SYSCFG_AUXMIC, SYSCFG_DISABLE); mic.hsbst = 1; } } }
static void getIMSI_work_func(struct work_struct *work) { SIMLOCK_SIM_DATA_t* simdata = GetSIMData(); if(simdata == NULL) { //printk("%s: IMSI NULL\n", __func__); FactoryMode = DISABLE; } else { //printk("%s: IMSI %s\n", __func__, simdata->imsi_string); FactoryMode = strncmp(simdata->imsi_string, "999999999999999", IMSI_DIGITS) == 0 ? ENABLE : DISABLE; } printk("%s: Factorymode %d\n", __func__, FactoryMode); if(FactoryMode == ENABLE) { if(mic.headset_state) { if(mic.hsbst == ENABLE && mic.headset_state == HEADSET_4_POLE) board_sysconfig(SYSCFG_AUXMIC, SYSCFG_ENABLE); } } }
/*------------------------------------------------------------------------------ Function name : hs_isr Description : interrupt handler Return type : irqreturn_t ------------------------------------------------------------------------------*/ irqreturn_t hs_isr(int irq, void *dev_id) { struct mic_t *p = &mic; int pre_data = -1; int loopcnt = 0; wake_lock_timeout(&p->det_wake_lock, WAKE_LOCK_TIME); p->pluging = ENABLE; sync_use_mic = ENABLE; printk("%s: Before state : %d \n", __func__, p->headset_state); #if 0 /* For remove pop-up noise.*/ if(p->headset_state && (p->keypressing == NONE || p->keypressing == INIT)) { printk("%s: Remove popup noise\n", __func__); board_sysconfig(SYSCFG_HEADSET, SYSCFG_DISABLE); board_sysconfig(SYSCFG_AUXMIC, SYSCFG_DISABLE); } #endif /* debounce headset jack. don't try to determine the type of * headset until the detect state is true for a while. */ while (1) { p->headset_pd->check_hs_state(&(p->headset_state)); if (pre_data == p->headset_state) loopcnt++; else loopcnt = 0; pre_data = p->headset_state; if (loopcnt >= HEADSET_DETECT_REF_COUNT) break; msleep(30); } set_irq_type(p->headset_pd->hsirq, (p->headset_state) ? IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING); determine_state_func(); return IRQ_HANDLED; }
//***************************************************************************** // // Function Name: dsi_teon // // Description: Configure TE Input Pin & Route it to DSI Controller Input // //***************************************************************************** static int dsi_teon ( dsic_panel_t *pPanel ) { Int32 res = 0; board_sysconfig(SYSCFG_LCD, SYSCFG_ENABLE); return ( res ); }
static ssize_t hs_Store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { ssize_t ret = 0; const ptrdiff_t off = attr - hs_Attrs; switch (off) { case ATTR_THRESHOLD: ret += sscanf(buf, "%d\n%d\n%d\n%d\n%d\n%d\n%d\n", \ (int*)(&KEY_3POLE_THRESHOLD), (int*)(&KEY1_THRESHOLD_L), (int*)(&KEY1_THRESHOLD_U),\ (int*)(&KEY2_THRESHOLD_L), (int*)(&KEY2_THRESHOLD_U), (int*)(&KEY3_THRESHOLD_L),\ (int*)(&KEY3_THRESHOLD_U)); queue_work(mic.headset_workqueue, &Write_work); break; case ATTR_TESTON: { int teston = 0; ret += sscanf(buf, "%d\n", &teston); printk("%s: teston %d\n", __func__, teston); TestMode = (teston == 1)? ENABLE : DISABLE; if(TestMode == ENABLE) { if(mic.headset_state == HEADSET_4_POLE) board_sysconfig(SYSCFG_AUXMIC, SYSCFG_ENABLE); } else { if(mic.headset_state == HEADSET_4_POLE) board_sysconfig(SYSCFG_AUXMIC, SYSCFG_ENABLE | SYSCFG_DISABLE); } } break; default : break; } return ret; }
static void type_work_func(struct work_struct *work) { #ifdef REG_DEBUG unsigned long val_anacr2, val_cmc, val_auxen; #endif int adc = auxadc_access(2); if(adc>=KEY_3POLE_THRESHOLD) { if(FactoryMode == DISABLE) board_sysconfig(SYSCFG_AUXMIC, SYSCFG_ENABLE | SYSCFG_DISABLE); if (mic.headset_pd->check_hs_state) board_sysconfig(SYSCFG_HEADSET, SYSCFG_ENABLE); mic.headset_state = HEADSET_4_POLE; printk("%s: 4-pole inserted : ear_adc=%d\n", __func__, adc); } else { board_sysconfig(SYSCFG_AUXMIC, SYSCFG_DISABLE); mic.headset_state = HEADSET_3_POLE; printk("%s: 3-pole inserted : ear_adc=%d\n", __func__, adc); } switch_set_state(&(mic.switch_data.sdev), mic.headset_state); if(FactoryMode == DISABLE) sync_use_mic = DISABLE; #ifdef REG_DEBUG val_anacr2 = readl(io_p2v(REG_ANACR2)); val_cmc = readl(io_p2v(REG_AUXMIC_CMC)); val_auxen = readl(io_p2v(REG_AUXMIC_AUXEN)); printk("%s: REG_ANACR2=%x, REG_AUXMIC_CMC=%x, REG_AUXMIC_AUXEN=%x\n", __func__, val_anacr2, val_cmc, val_auxen); #endif }
// Switch class work to update state of headset static void switch_work(struct work_struct *work) { #ifdef REG_DEBUG unsigned long val_anacr2, val_cmc, val_auxen; val_anacr2 = readl(io_p2v(REG_ANACR2)); val_cmc = readl(io_p2v(REG_AUXMIC_CMC)); val_auxen = readl(io_p2v(REG_AUXMIC_AUXEN)); printk("%s: REG_ANACR2=%x, REG_AUXMIC_CMC=%x, REG_AUXMIC_AUXEN=%x\n", __func__, val_anacr2, val_cmc, val_auxen); #endif if(mic.headset_state) { if(mic.hsbst == DISABLE) { mic.hsbst = ENABLE; board_sysconfig(SYSCFG_AUXMIC, SYSCFG_ENABLE); schedule_delayed_work(&(mic.type_work), TYPE_DETECT_REF_TIME); } } else { if(mic.hsbst == ENABLE) { board_sysconfig(SYSCFG_AUXMIC, SYSCFG_DISABLE); if (mic.headset_pd->check_hs_state) board_sysconfig(SYSCFG_HEADSET, SYSCFG_DISABLE); mic.hsbst = DISABLE; sync_use_mic = DISABLE; switch_set_state(&(mic.switch_data.sdev), mic.headset_state); printk("%s: plugged out\n", __func__); } } }
static void type_work_func(struct work_struct *work) { int adc = 0; if(mic.headset_state) { adc = auxadc_access(2); if(adc >= KEY_3POLE_THRESHOLD) { if(FactoryMode == DISABLE) board_sysconfig(SYSCFG_AUXMIC, SYSCFG_ENABLE | SYSCFG_DISABLE); board_sysconfig(SYSCFG_HEADSET, SYSCFG_ENABLE); mic.headset_state = HEADSET_4_POLE; mic.hsbtime = ktime_get(); ENABLE_IRQ_MICON; printk("%s: 4-pole inserted : ear_adc=%d\n", __func__, adc); } else { if(FactoryMode == DISABLE) board_sysconfig(SYSCFG_AUXMIC, SYSCFG_DISABLE); mic.headset_state = HEADSET_3_POLE; printk("%s: 3-pole inserted : ear_adc=%d\n", __func__, adc); } mic.pluging = DISABLE; if(FactoryMode == DISABLE) sync_use_mic = DISABLE; switch_set_state(&mic.sdev, mic.headset_state); } }
static void determine_state_func(void) { if(mic.headset_state) { board_sysconfig(SYSCFG_HEADSET, SYSCFG_ENABLE); board_sysconfig(SYSCFG_AUXMIC, SYSCFG_ENABLE); cancel_delayed_work(&(mic.type_work)); queue_delayed_work(mic.headset_workqueue, &(mic.type_work), TYPE_DETECT_REF_TIME); } else { board_sysconfig(SYSCFG_HEADSET, SYSCFG_DISABLE); board_sysconfig(SYSCFG_AUXMIC, SYSCFG_DISABLE); DISABLE_IRQ_MICON; mic.pluging = DISABLE; mic.keypressing = INIT; sync_use_mic = DISABLE; switch_set_state(&mic.sdev, mic.headset_state); printk("%s: plugged out\n", __func__); } }
/*------------------------------------------------------------------------------ Function name : hs_buttonisr Description : interrupt handler Return type : irqreturn_t ------------------------------------------------------------------------------*/ irqreturn_t hs_buttonisr(int irq, void *dev_id) { struct mic_t *p = &mic; int val = 0; ktime_t temptime; if(mic.keypressing == INIT) { temptime = ktime_get(); temptime = ktime_sub(temptime, mic.hsbtime); if(temptime.tv.sec >= 1 || temptime.tv.nsec >= KEY_INTERRUPT_REF_TIME) mic.keypressing = NONE; else { printk("%s: Initializing HSB ISR\n", __func__ ); return IRQ_NONE; } } if(p->pluging == ENABLE || p->keypressing != NONE) { printk("%s: Headset pluging OR keypressing\n", __func__ ); return IRQ_NONE; } val = readl(io_p2v(REG_ANACR12)); if(val < KEY_PRESS_THRESHOLD) { printk("%s: False button interrupt\n", __func__ ); return IRQ_NONE; } if (p->headset_state == HEADSET_4_POLE) { p->hsbtime = ktime_get(); board_sysconfig(SYSCFG_AUXMIC, SYSCFG_ENABLE); memset(mic.key_count, 0, sizeof(mic.key_count)); p->keypressing = PRESS; sync_use_mic = ENABLE; cancel_delayed_work(&(mic.input_work)); queue_delayed_work(mic.headset_workqueue, &(p->input_work), KEY_BEFORE_PRESS_REF_TIME); } return IRQ_HANDLED; }
/* 1 : SIM_DUAL_FIRST, 2 : SIM_DUAL_SECOND */ static void getIMSI_work_func(struct work_struct *work) { SIMLOCK_SIM_DATA_t* simdata = GetSIMData(); if(simdata == NULL) { FactoryMode = DISABLE; } else { FactoryMode = strncmp(simdata->imsi_string, TEST_SIM_IMSI, IMSI_DIGITS) == 0 ? ENABLE : DISABLE; } if(FactoryMode == ENABLE) { if(mic.headset_state == HEADSET_4_POLE) board_sysconfig(SYSCFG_AUXMIC, SYSCFG_ENABLE); } }
/* ****************************************************************************** */ void csl_dma_start_transfer(DMA_CHANNEL chanID, DMADRV_LLI_T pLLI) { dmac_t *pdma = (dmac_t *) & dmac; UInt32 assocChan = ASSOC_CHAN_NONE; ASSOC_CHAN_t *pAssocChan = (ASSOC_CHAN_t *) pLLI; #if (defined (_HERA_) || defined (_RHEA_) || defined (_SAMOA_)) chal_dmac_ucode_t ucode; ucode.alloc = dma_ucode_alloc; ucode.coherency = dma_ucode_coherency; ucode.free = dma_ucode_free; #endif if (!pdma->initialized) { /* dprintf(1, "csl_dma: dmac has not been initialized\n"); */ return; } /* Set AHB clock request generated on per-channel basis * This is to ensure Athena enters deep sleep/pedestal mode */ chanArray[chanID].busy = TRUE; board_sysconfig(SYSCFG_CSL_DMA, SYSCFG_DISABLE); #if (defined (_HERA_) || defined (_RHEA_) || defined (_SAMOA_)) chal_dma_prepare_transfer(pdma->handle, chanID, &ucode); chal_dmux_protect(pdma->dmuxHandle); chal_dma_start_transfer(pdma->handle, chanID, &ucode); chal_dmux_unprotect(pdma->dmuxHandle); #else if (pLLI != NULL) { assocChan = pAssocChan->assocChan; } else { assocChan = ASSOC_CHAN_NONE; } chal_dma_start_transfer(pdma->handle, chanID, assocChan); #endif return; }
static int __init hs_probe(struct platform_device *pdev) { int result = 0; mic.hsmajor = 0; mic.headset_state = 0; mic.hsbtime.tv.sec = 0; mic.hsbtime.tv.nsec = 0; mic.headset_pd = NULL; mic.check_count = 0; #ifdef CONFIG_SWITCH result = hs_switchinit(&mic); if (result < 0) return result; #endif result = hs_inputdev(&mic); if (result < 0) goto err; result = register_chrdev(mic.hsmajor, "BrcmHeadset", &hs_fops); if(result < 0) goto err1; else if(result > 0 && (mic.hsmajor == 0)) /* this is for dynamic major */ mic.hsmajor = result; wake_lock_init(&mic.det_wake_lock, WAKE_LOCK_SUSPEND, "sec_jack_det"); INIT_DELAYED_WORK(&(mic.imsi_work), getIMSI_work_func); /* check if platform data is defined for a particular board variant */ if (pdev->dev.platform_data) { mic.headset_pd = pdev->dev.platform_data; KEY_PRESS_THRESHOLD = mic.headset_pd->key_press_threshold; KEY_3POLE_THRESHOLD = mic.headset_pd->key_3pole_threshold; KEY1_THRESHOLD_L = mic.headset_pd->key1_threshold_l; KEY1_THRESHOLD_U = mic.headset_pd->key1_threshold_u; KEY2_THRESHOLD_L = mic.headset_pd->key2_threshold_l; KEY2_THRESHOLD_U = mic.headset_pd->key2_threshold_u; KEY3_THRESHOLD_L = mic.headset_pd->key3_threshold_l; KEY3_THRESHOLD_U = mic.headset_pd->key3_threshold_u; if (mic.headset_pd->hsgpio == NULL) mic.hsirq = mic.headset_pd->hsirq; else { setup_timer(&mic.timer, gpio_jack_timer, (unsigned long)&mic); // timer register. if (gpio_request(mic.headset_pd->hsgpio, "headset detect") < 0) { printk("%s: Could not reserve headset signal GPIO!\n", __func__); goto err2; } gpio_direction_input(mic.headset_pd->hsgpio); bcm_gpio_set_db_val(mic.headset_pd->hsgpio, 0x7); mic.hsirq = gpio_to_irq(mic.headset_pd->hsgpio); } mic.hsbirq = mic.headset_pd->hsbirq; } else { mic.hsirq = platform_get_irq(pdev, 0); mic.hsbirq = platform_get_irq(pdev, 1); } printk("%s: HS irq %d\n", __func__, mic.hsirq); printk("%s: HSB irq %d\n", __func__, mic.hsbirq); result = request_irq(mic.hsbirq, hs_buttonisr, IRQF_NO_SUSPEND, "BrcmHeadsetButton", (void *) NULL); mic.hsbst = DISABLE; if(result < 0) goto err2; result = request_irq(mic.hsirq, hs_isr,(IRQF_DISABLED | IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING | IRQF_NO_SUSPEND), "BrcmHeadset", &mic); if(result < 0) { free_irq(mic.hsbirq, &mic); goto err2; } printk("%s: BrcmHeadset: module inserted >>>> . Major number is = %d\n", __func__, mic.hsmajor); /* Set the ANACR2 bit for mic power down */ board_sysconfig(SYSCFG_AUXMIC, SYSCFG_INIT); board_sysconfig(SYSCFG_HEADSET, SYSCFG_INIT); /*Fix the audio path is wrong when headset already plugged in the device then boot device case.*/ if (mic.headset_pd->hsgpio != NULL) { mic.headset_pd->check_hs_state(&mic.headset_state); printk("%s: headset_state:%d\n", __func__, mic.headset_state); set_irq_type(mic.hsirq, (mic.headset_state) ? IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING); schedule_work(&(mic.switch_data.work)); schedule_delayed_work(&(mic.imsi_work), GET_IMSI_REF_TIME); } return 0; err2: unregister_chrdev(mic.hsmajor,"BrcmHeadset"); if(mic.headset_pd->hsgpio) del_timer_sync(&mic.timer); err1: hs_unreginputdev(&mic); err: hs_unregsysfs(&mic); return result; }
static void input_work_func(struct work_struct *work) { int adc_value = -1; int val = 0; ktime_t temptime; adc_value = auxadc_access(2); val = readl(io_p2v(REG_ANACR12)); // printk("%s: REG_ANACR2=%d, REG_ANACR12=%d\n", __func__,adc_value , val); if(val >= KEY_PRESS_THRESHOLD && adc_value >= KEY1_THRESHOLD_L && adc_value < KEY3_THRESHOLD_U) { temptime = ktime_get(); temptime = ktime_sub(temptime, mic.hsbtime); if(temptime.tv.nsec < VALID_RELEASE_REF_TIME && mic.keypressing == PRESS) { if ( adc_value >= KEY1_THRESHOLD_L && adc_value < KEY1_THRESHOLD_U ) { mic.key_count[0]++; printk ("KEY_BCM_HEADSET_BUTTON \n"); } else if ( adc_value >= KEY2_THRESHOLD_L && adc_value < KEY2_THRESHOLD_U ) { mic.key_count[1]++; printk ("KEY_VOLUMEUP \n"); } else if ( adc_value >= KEY3_THRESHOLD_L && adc_value < KEY3_THRESHOLD_U ) { mic.key_count[2]++; printk ("KEY_VOLUMEDOWN \n"); } } else { if(mic.keypressing == PRESS && (mic.key_count[0] + mic.key_count[1] + mic.key_count[2])) { input_report_key(mic.headset_button_idev, Return_valid_key(mic.key_count), PRESS); input_sync(mic.headset_button_idev); set_button(1); mic.keypressing = RELEASE; } } cancel_delayed_work(&(mic.input_work)); queue_delayed_work(mic.headset_workqueue, &(mic.input_work), KEY_PRESS_REF_TIME); } else { if(mic.keypressing == RELEASE && (mic.key_count[0] + mic.key_count[1] + mic.key_count[2])) { printk ("%s: RELEASE key_count [%d, %d, %d] \n", __func__, mic.key_count[0], mic.key_count[1], mic.key_count[2]); input_report_key(mic.headset_button_idev, Return_valid_key(mic.key_count), RELEASE); input_sync(mic.headset_button_idev); } else { printk("%s: NO PRESS\n", __func__); } if(FactoryMode == DISABLE) { board_sysconfig(SYSCFG_AUXMIC, SYSCFG_ENABLE | SYSCFG_DISABLE); sync_use_mic = DISABLE; } set_button(0); mic.keypressing = NONE; } }
static void input_work_func(struct work_struct *work) { int adc_value = -1; int val = 0; ktime_t temptime; adc_value = auxadc_access(2); val = readl(io_p2v(REG_ANACR12)); // printk("%s: REG_ANACR2=%d, REG_ANACR12=%d\n", __func__,adc_value , val); #ifdef USE_SERVICEMODE if(val >= KEY_PRESS_THRESHOLD && adc_value >= Min_threshold && adc_value < Max_threshold) { #else if(val >= KEY_PRESS_THRESHOLD && adc_value >= KEY1_THRESHOLD_L && adc_value < KEY3_THRESHOLD_U) { #endif temptime = ktime_get(); temptime = ktime_sub(temptime, mic.hsbtime); if(temptime.tv.nsec < VALID_RELEASE_REF_TIME && mic.keypressing == PRESS) { if ( adc_value >= KEY1_THRESHOLD_L && adc_value < KEY1_THRESHOLD_U ) { mic.key_count[0]++; printk ("KEY_BCM_HEADSET_BUTTON \n"); } else if ( adc_value >= KEY2_THRESHOLD_L && adc_value < KEY2_THRESHOLD_U ) { mic.key_count[1]++; printk ("KEY_VOLUMEUP \n"); } else if ( adc_value >= KEY3_THRESHOLD_L && adc_value < KEY3_THRESHOLD_U ) { mic.key_count[2]++; printk ("KEY_VOLUMEDOWN \n"); } } else { if(mic.keypressing == PRESS && (mic.key_count[0] + mic.key_count[1] + mic.key_count[2])) { input_report_key(mic.headset_button_idev, Return_valid_key(mic.key_count), PRESS); input_sync(mic.headset_button_idev); set_button(1); mic.keypressing = RELEASE; } } cancel_delayed_work(&(mic.input_work)); queue_delayed_work(mic.headset_workqueue, &(mic.input_work), KEY_PRESS_REF_TIME); } else { if(mic.keypressing == RELEASE && (mic.key_count[0] + mic.key_count[1] + mic.key_count[2])) { printk ("%s: RELEASE key_count [%d, %d, %d] \n", __func__, mic.key_count[0], mic.key_count[1], mic.key_count[2]); input_report_key(mic.headset_button_idev, Return_valid_key(mic.key_count), RELEASE); input_sync(mic.headset_button_idev); } else { printk("%s: NO PRESS\n", __func__); } if(FactoryMode == DISABLE) { board_sysconfig(SYSCFG_AUXMIC, SYSCFG_ENABLE | SYSCFG_DISABLE); sync_use_mic = DISABLE; } set_button(0); mic.keypressing = NONE; } } /*------------------------------------------------------------------------------ Function name : hs_buttonisr Description : interrupt handler Return type : irqreturn_t ------------------------------------------------------------------------------*/ irqreturn_t hs_buttonisr(int irq, void *dev_id) { struct mic_t *p = &mic; int val = 0; ktime_t temptime; #ifdef USE_SERVICEMODE if(TestMode == ENABLE) { if(p->headset_state == HEADSET_4_POLE) board_sysconfig(SYSCFG_AUXMIC, SYSCFG_ENABLE); return IRQ_NONE; } #endif if(mic.keypressing == INIT) { temptime = ktime_get(); temptime = ktime_sub(temptime, mic.hsbtime); if(temptime.tv.sec >= 1 || temptime.tv.nsec >= KEY_INTERRUPT_REF_TIME) mic.keypressing = NONE; else { printk("%s: Initializing HSB ISR\n", __func__ ); return IRQ_NONE; } } if(p->pluging == ENABLE || p->keypressing != NONE) { printk("%s: Headset pluging OR keypressing\n", __func__ ); return IRQ_NONE; } val = readl(io_p2v(REG_ANACR12)); if(val < KEY_PRESS_THRESHOLD) { printk("%s: False button interrupt\n", __func__ ); return IRQ_NONE; } if (p->headset_state == HEADSET_4_POLE) { p->hsbtime = ktime_get(); board_sysconfig(SYSCFG_AUXMIC, SYSCFG_ENABLE); memset(mic.key_count, 0, sizeof(mic.key_count)); p->keypressing = PRESS; sync_use_mic = ENABLE; cancel_delayed_work(&(mic.input_work)); queue_delayed_work(mic.headset_workqueue, &(p->input_work), KEY_BEFORE_PRESS_REF_TIME); } return IRQ_HANDLED; } /* 1 : SIM_DUAL_FIRST, 2 : SIM_DUAL_SECOND */ static void getIMSI_work_func(struct work_struct *work) { SIMLOCK_SIM_DATA_t* simdata = NULL; int first = DISABLE; int second = DISABLE; simdata = GetSIMData(SIM_DUAL_FIRST); first = ((simdata == NULL) || (strncmp(simdata->imsi_string, TEST_SIM_IMSI, IMSI_DIGITS) != 0)) ? DISABLE : ENABLE; simdata = GetSIMData(SIM_DUAL_SECOND); second = ((simdata == NULL) || (strncmp(simdata->imsi_string, TEST_SIM_IMSI, IMSI_DIGITS) != 0)) ? DISABLE : ENABLE; FactoryMode = (first == ENABLE || second == ENABLE) ? ENABLE : DISABLE; printk("%s: Factorymode %d\n", __func__, FactoryMode); if(FactoryMode == ENABLE) { if(mic.headset_state == HEADSET_4_POLE) board_sysconfig(SYSCFG_AUXMIC, SYSCFG_ENABLE); } }
static int __init hs_probe(struct platform_device *pdev) { int result; mic.hsmajor = 0; mic.headset_state = 0; mic.hsbtime.tv.sec = 0; mic.hsbtime.tv.nsec = 0; mic.headset_pd = NULL; #ifdef CONFIG_SWITCH result = hs_switchinit(&mic); if (result < 0) { return result; } #endif result = hs_inputdev(&mic); if (result < 0) { goto err; } result = register_chrdev(mic.hsmajor, "BrcmHeadset", &hs_fops); if(result < 0) { goto err1; } else if(result > 0 && (mic.hsmajor == 0)) /* this is for dynamic major */ { mic.hsmajor = result; } /* check if platform data is defined for a particular board variant */ if (pdev->dev.platform_data) { mic.headset_pd = pdev->dev.platform_data; if (mic.headset_pd->hsgpio == NULL) { mic.hsirq = mic.headset_pd->hsirq; } else { bcm_gpio_set_db_val(mic.headset_pd->hsgpio, 0x7); if (gpio_request(mic.headset_pd->hsgpio, "headset detect") < 0) { pr_info("Could not reserve headset signal GPIO!\n"); goto err2; } gpio_direction_input(mic.headset_pd->hsgpio); mic.hsirq = gpio_to_irq(mic.headset_pd->hsgpio); } mic.hsbirq = mic.headset_pd->hsbirq; } else { mic.hsirq = platform_get_irq(pdev, 0); mic.hsbirq = platform_get_irq(pdev, 1); } pr_info("HS irq %d\n",mic.hsirq); pr_info("HSB irq %d\n",mic.hsbirq); #if defined(CONFIG_HAS_WAKELOCK) wake_lock_init(&headsetbutton_wake_lock, WAKE_LOCK_SUSPEND, "BrcmHeadsetButton"); #endif result = request_irq(mic.hsbirq, hs_buttonisr, IRQF_NO_SUSPEND, "BrcmHeadsetButton", (void *) NULL); mic.hsbst = 1; /* Disabled */ disable_irq(mic.hsbirq); if(result < 0) { goto err2; } result = request_irq(mic.hsirq, hs_isr,(IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING|IRQF_NO_SUSPEND), "BrcmHeadset", &mic); if(result < 0) { free_irq(mic.hsbirq, &mic); goto err2; } /* Check if the thresholds have been set for a particular board */ if (!mic.headset_pd->keypress_threshold_lp) mic.headset_pd->keypress_threshold_lp = KEYPRESS_THRESHOLD; if (!mic.headset_pd->keypress_threshold_fp) mic.headset_pd->keypress_threshold_fp = KEYPRESS_THRESHOLD; /* Set the ANACR2 bit for mic power down */ board_sysconfig(SYSCFG_HEADSET, SYSCFG_INIT); board_sysconfig(SYSCFG_AUXMIC, SYSCFG_INIT); if (mic.headset_pd->check_hs_state) writel(AUDIO_RX_LDO_OFF(readl(io_p2v(REG_ANACR2))), io_p2v(REG_ANACR2)); /*Fix the audio path is wrong when headset already plugged in the device then boot device case.*/ hs_isr(mic.hsirq,&mic); return 0; err2: unregister_chrdev(mic.hsmajor,"BrcmHeadset"); err1: hs_unreginputdev(&mic); input_free_device(&mic.headset_button_idev); err: hs_unregsysfs(&mic); return result; }
/* ****************************************************************************** */ void csl_dma_process_callback(DMA_Interrupt_t * intStatus) { UInt32 channel, mask, chnl_count; DMA_Interrupt_t localIntStatus; UInt32 flags; DEFINE_SPINLOCK(lock); spin_lock_irqsave(&lock, flags); localIntStatus.errInt = intStatus->errInt; localIntStatus.tcInt = intStatus->tcInt; intStatus->errInt = 0; intStatus->tcInt = 0; spin_unlock_irqrestore(&lock, flags); /* dprintf(1, "csl_dma: csl_dma_process_callback\n"); */ for (channel = 0; channel < TOTAL_DMA_CHANNELS; channel++) { mask = (0x1 << channel); if (chanArray[channel].bUsed == FALSE) continue; #if (defined (_HERA_) || defined (_RHEA_) || defined (_SAMOA_)) if (chanArray[channel].bUsed && chanArray[channel].chanInfo.xferCompleteCb) { chanArray[channel].chanInfo. xferCompleteCb((DMADRV_CALLBACK_STATUS_t) DMADRV_CALLBACK_OK); } #else if (localIntStatus.errInt & mask) { /* dprintf(1, "Eirlys errInt, channel: %d, %d\n", channel, TIMER_GetValue()); */ if (chanArray[channel].bUsed && chanArray[channel].chanInfo.xferCompleteCb) { chanArray[channel].chanInfo. xferCompleteCb((DMADRV_CALLBACK_STATUS_t) DMADRV_CALLBACK_FAIL); spin_lock_irqsave(&lock, flags); if (chanArray[channel].chanInfo.freeChan) { csl_dma_release_channel((DMA_CHANNEL) channel); } spin_unlock_irqrestore(&lock, flags); } } else if (localIntStatus.tcInt & mask) { if (chanArray[channel].bUsed && chanArray[channel].chanInfo.xferCompleteCb) { /* dprintf(1, "Eirlys tcInt, %d, %d, 0x%x\n", channel, */ /* TIMER_GetValue(), chanArray[channel].chanInfo.xferCompleteCb); */ chanArray[channel].chanInfo. xferCompleteCb((DMADRV_CALLBACK_STATUS_t) DMADRV_CALLBACK_OK); spin_lock_irqsave(&lock, flags); chanArray[channel].busy = FALSE; if (chanArray[channel].chanInfo.freeChan) { csl_dma_release_channel((DMA_CHANNEL) channel); } spin_unlock_irqrestore(&lock, flags); } } #endif } for (chnl_count = 0; chnl_count < TOTAL_DMA_CHANNELS; chnl_count++) { if (chanArray[chnl_count].busy == TRUE) { return; } } /* Set AHB clock request generated on per-channel basis * This is to ensure Athena enters deep sleep/pedestal mode*/ board_sysconfig(SYSCFG_CSL_DMA, SYSCFG_ENABLE); return; }
syscfg_reset_reason_t get_ap_boot_mode(void) { return board_sysconfig(SYSCFG_RESETREASON_AP_ONLY_BOOT, SYSCFG_INIT); }
/* Callback called before the device reboots. If the reboot cause is a recovery, this function is going to write the strings "boot-recovery" and "recovery" into the Bootloader Control Block (BCB) so the Android Bootloader can launch the recovery image instead of the boot image. */ static int reboot_notifier_callback( struct notifier_block *nb, unsigned long val, void *v) { struct raw_hd_struct *mmc_hd = NULL; struct bootloader_message *bcb; char *flashblock = NULL; if (mmc_misc_hd == NULL) goto clean_up; else mmc_hd = mmc_misc_hd; if (v == NULL) { board_sysconfig(SYSCFG_RESETREASON_SOFT_RESET, SYSCFG_DISABLE); goto clean_up; } if (!strncmp(v, "recovery", 8)) { int i = 0; dev_t devid; struct block_device *bdev; struct bio bio; struct bio_vec bio_vec; struct completion complete; struct page *page; /* Allocate a buffer to hold a block from 'misc' */ flashblock = kmalloc(mmc_hd->nr_sects * 512, GFP_KERNEL); memset(flashblock, 0, mmc_hd->nr_sects * 512); /* If the allocation fails, return */ if (flashblock == NULL) goto clean_up; /* read the BCB from the misc partition */ /* read the entire block as we'll have to rewrite it hence we need to erase */ devid = MKDEV(mmc_hd->major, mmc_hd->first_minor + mmc_hd->partno); bdev = open_by_devnum(devid, FMODE_READ); if (IS_ERR(bdev)) { printk(KERN_ERR "misc: open device failed with %ld\n", PTR_ERR(bdev)); goto clean_up; } page = virt_to_page(bounce); while (i < mmc_hd->nr_sects) { bio_init(&bio); bio.bi_io_vec = &bio_vec; bio_vec.bv_page = page; bio_vec.bv_offset = 0; bio.bi_vcnt = 1; bio.bi_idx = 0; bio.bi_bdev = bdev; bio.bi_sector = i; if (mmc_hd->nr_sects - i >= 8) { bio_vec.bv_len = PAGE_SIZE; bio.bi_size = PAGE_SIZE; i += 8; } else { bio_vec.bv_len = (mmc_hd->nr_sects - i) * 512; bio.bi_size = (mmc_hd->nr_sects - i) * 512; i = mmc_hd->nr_sects; } init_completion(&complete); bio.bi_private = &complete; bio.bi_end_io = mmc_bio_complete; submit_bio(READ, &bio); wait_for_completion(&complete); /* Copy the read buffer */ memcpy(flashblock + (i * 512), page, bio.bi_size); } blkdev_put(bdev, FMODE_READ); printk(KERN_ERR "misc: Bound to mmc block device '(%d:%d)'\n", mmc_hd->major, mmc_hd->first_minor + mmc_hd->partno); /* BCB is stored at 0-bytes */ bcb = (struct bootloader_message *)&flashblock[0]; /* set bcb.command to "boot-recovery" */ strcpy(bcb->command, "boot-recovery"); /* clean bcb.status */ memset(bcb->status, 0, sizeof(bcb->status)); /* set bcb.recovery to "recovery" */ strcpy(bcb->recovery, "recovery"); /* Write the block back to 'misc' First, erase it */ devid = MKDEV(mmc_hd->major, mmc_hd->first_minor + mmc_hd->partno); bdev = open_by_devnum(devid, FMODE_WRITE); if (IS_ERR(bdev)) { printk(KERN_ERR "misc: open device failed with %ld\n", PTR_ERR(bdev)); goto clean_up; } page = virt_to_page(bounce); i = 0; while (i < mmc_hd->nr_sects) { bio_init(&bio); bio.bi_io_vec = &bio_vec; bio_vec.bv_page = page; bio_vec.bv_offset = 0; bio.bi_vcnt = 1; bio.bi_idx = 0; bio.bi_bdev = bdev; bio.bi_sector = i; if (mmc_hd->nr_sects - i >= 8) { bio_vec.bv_len = PAGE_SIZE; bio.bi_size = PAGE_SIZE; i += 8; } else { bio_vec.bv_len = (mmc_hd->nr_sects - i) * 512; bio.bi_size = (mmc_hd->nr_sects - i) * 512; i = mmc_hd->nr_sects; } init_completion(&complete); bio.bi_private = &complete; bio.bi_end_io = mmc_bio_complete; submit_bio(WRITE, &bio); wait_for_completion(&complete); } blkdev_put(bdev, FMODE_WRITE); /* Then write the block back */ devid = MKDEV(mmc_hd->major, mmc_hd->first_minor + mmc_hd->partno); bdev = open_by_devnum(devid, FMODE_WRITE); if (IS_ERR(bdev)) { printk(KERN_ERR "misc: open device failed with %ld\n", PTR_ERR(bdev)); goto clean_up; } page = virt_to_page(bounce); i = 0; while (i < mmc_hd->nr_sects) { bio_init(&bio); bio.bi_io_vec = &bio_vec; bio_vec.bv_page = page; bio_vec.bv_offset = 0; bio.bi_vcnt = 1; bio.bi_idx = 0; bio.bi_bdev = bdev; bio.bi_sector = i; if (mmc_hd->nr_sects - i >= 8) { /* Copy the BCB block to buffer */ memcpy(bounce, flashblock + (i * 512), PAGE_SIZE); bio_vec.bv_len = PAGE_SIZE; bio.bi_size = PAGE_SIZE; i += 8; } else { /* Copy the BCB block to buffer */ memcpy(bounce, flashblock + (i * 512), (mmc_hd->nr_sects - i) * 512); bio_vec.bv_len = (mmc_hd->nr_sects - i) * 512; bio.bi_size = (mmc_hd->nr_sects - i) * 512; i = mmc_hd->nr_sects; } init_completion(&complete); bio.bi_private = &complete; bio.bi_end_io = mmc_bio_complete; submit_bio(WRITE, &bio); wait_for_completion(&complete); } blkdev_put(bdev, FMODE_WRITE); } if (!strncmp(v, "ap_only", 7)) { board_sysconfig(SYSCFG_RESETREASON_AP_ONLY_BOOT, SYSCFG_DISABLE); } clean_up: if (flashblock != NULL) kfree(flashblock); return NOTIFY_DONE; }
/*------------------------------------------------------------------------------ Function name : hs_buttonisr Description : interrupt handler Return type : irqreturn_t ------------------------------------------------------------------------------*/ irqreturn_t hs_buttonisr(int irq, void *dev_id) { ktime_t r, temp; unsigned int val = 0; #ifdef REG_DEBUG unsigned long val_anacr2, val_cmc, val_auxen; #endif printk ("%s: HS_BUTTONISR (<<<) : status=%d \n", __func__, mic.hsbst); if (mic.hsbst == DISABLE || mic.headset_state != HEADSET_4_POLE) return IRQ_HANDLED; /* Read the ANACR12 register value to check if the interrupt being * serviced by the ISR is spurious */ val = readl(io_p2v(REG_ANACR12)); temp = ktime_get(); r = ktime_sub(temp,mic.hsbtime); if((r.tv.sec > 0) || (r.tv.nsec > REF_TIME)) { mic.hsbtime = temp; } else { printk ("%s: HS_BUTTONISR appeared frequently (r.tv.sec=%d, r.tv.nsec=%d) status=%d \n", __func__, r.tv.sec, r.tv.nsec, mic.hsbst); // return IRQ_HANDLED; } /* If the value read from the ANACR12 register is greater than the * threshold, schedule the workqueue */ printk("%s: REG_ANACR12=%x\n", __func__,val); #ifdef REG_DEBUG val_anacr2 = readl(io_p2v(REG_ANACR2)); val_cmc = readl(io_p2v(REG_AUXMIC_CMC)); val_auxen = readl(io_p2v(REG_AUXMIC_AUXEN)); printk("%s: REG_ANACR2=%x, REG_AUXMIC_CMC=%x, REG_AUXMIC_AUXEN=%x\n", __func__, val_anacr2, val_cmc, val_auxen); #endif if (val >= KEY_PRESS_THRESHOLD) { board_sysconfig(SYSCFG_AUXMIC, SYSCFG_ENABLE); key_resolved = 0; key_count[0] = key_count[1] = key_count[2] = 0; sync_use_mic = ENABLE; schedule_delayed_work(&(mic.input_work), KEY_BEFORE_PRESS_REF_TIME); printk("%s: set_button => PRESS\n", __func__); set_button(PRESS); } else { pr_info("Headset Button press detected for a illegal interrupt\n"); printk("%s: set_button => RELEASE\n", __func__); set_button(RELEASE); } printk ("%s: HS_BUTTONISR (>>>) : status=%d \n", __func__, mic.hsbst); return IRQ_HANDLED; }
static void input_work_func(struct work_struct *work) { int delta = 0; unsigned long val = 0; #ifdef REG_DEBUG unsigned long val_anacr2, val_cmc, val_auxen; #endif static int key_status = RELEASE; int adc_value = auxadc_access(2); printk("%s: input_work adc_value=%d\n", __func__, adc_value); /* If the key_status is 0, send the event for a key press */ if(key_status == RELEASE) { delta = check_delta(mic.hsbtime,mic.hstime); if((mic.headset_state == HEADSET_4_POLE) && (delta == 0)) { if (!key_resolved) { if ( adc_value >= KEY1_THRESHOLD_L && adc_value < KEY1_THRESHOLD_U ) { key_count[0]++; if (key_count[0] >= KEYCOUNT_THRESHOLD) key_resolved = 1; key_type = KEY_BCM_HEADSET_BUTTON; printk ("KEY_BCM_HEADSET_BUTTON \n"); } if ( adc_value >= KEY2_THRESHOLD_L && adc_value < KEY2_THRESHOLD_U ) { key_count[1]++; if (key_count[1] >= KEYCOUNT_THRESHOLD) key_resolved = 1; key_type = KEY_VOLUMEUP; printk ("KEY_VOLUMEUP \n"); } if ( adc_value >= KEY3_THRESHOLD_L && adc_value < KEY3_THRESHOLD_U ) { key_count[2]++; if (key_count[2] >= KEYCOUNT_THRESHOLD) key_resolved = 1; key_type = KEY_VOLUMEDOWN; printk ("KEY_VOLUMEDOWN \n"); } } else input_report_key(mic.headset_button_idev, key_type, PRESS); input_sync(mic.headset_button_idev); printk("%s: set_button => PRESS\n", __func__); set_button(PRESS); printk("%s: button pressed : ear_adc=%d\n", __func__, adc_value); } } /* Check if the value read from ANACR12 is greater than the * threshold. If so, the key is still pressed and schedule the work * queue till the value is less than the threshold */ val = readl(io_p2v(REG_ANACR12)); printk("%s: REG_ANACR12=%x\n", __func__,val); if (val >= KEY_PRESS_THRESHOLD && (adc_value >= KEY1_THRESHOLD_L && adc_value < KEY3_THRESHOLD_U)) { key_status = PRESS; if (!key_resolved) { if ( adc_value >= KEY1_THRESHOLD_L && adc_value < KEY1_THRESHOLD_U ) { key_count[0]++; if (key_count[0] >= KEYCOUNT_THRESHOLD) key_resolved = 1; key_type = KEY_BCM_HEADSET_BUTTON; printk ("KEY_BCM_HEADSET_BUTTON\n"); } if ( adc_value >= KEY2_THRESHOLD_L && adc_value < KEY2_THRESHOLD_U ) { key_count[1]++; if (key_count[1] >= KEYCOUNT_THRESHOLD) key_resolved = 1; key_type = KEY_VOLUMEUP; printk ("KEY_VOLUMEUP\n"); } if ( adc_value >= KEY3_THRESHOLD_L && adc_value < KEY3_THRESHOLD_U ) { key_count[2]++; if (key_count[2] >= KEYCOUNT_THRESHOLD) key_resolved = 1; key_type = KEY_VOLUMEDOWN; printk ("KEY_VOLUMEDOWN\n"); } } else input_report_key(mic.headset_button_idev, key_type, PRESS); schedule_delayed_work(&(mic.input_work), KEY_PRESS_REF_TIME); printk("%s: set_button => PRESS\n", __func__); set_button(PRESS); } /* Once the value read from ANACR12 is less than the threshold, send * the event for a button release */ else { key_status = RELEASE; printk ("%s: key_count [%d, %d, %d] \n", __func__, key_count[0], key_count[1], key_count[2]); if ( key_count[0] >= KEYCOUNT_THRESHOLD ) { printk("SEND/END RELEASE\n"); input_report_key(mic.headset_button_idev, KEY_BCM_HEADSET_BUTTON, RELEASE); input_sync(mic.headset_button_idev); } else if ( key_count[1] >= KEYCOUNT_THRESHOLD ) { printk("VOLUP RELEASE\n"); input_report_key(mic.headset_button_idev, KEY_VOLUMEUP, RELEASE); input_sync(mic.headset_button_idev); } else if ( key_count[2] >= KEYCOUNT_THRESHOLD ) { printk("VOLDOWN RELEASE\n"); input_report_key(mic.headset_button_idev, KEY_VOLUMEDOWN, RELEASE); input_sync(mic.headset_button_idev); } printk("%s: set_button => RELEASE\n", __func__); set_button(RELEASE); key_resolved = 0; key_count[0] = key_count[1] = key_count[2] = 0; if(FactoryMode == DISABLE) { board_sysconfig(SYSCFG_AUXMIC, SYSCFG_ENABLE | SYSCFG_DISABLE); sync_use_mic = DISABLE; } #ifdef REG_DEBUG val_anacr2 = readl(io_p2v(REG_ANACR2)); val_cmc = readl(io_p2v(REG_AUXMIC_CMC)); val_auxen = readl(io_p2v(REG_AUXMIC_AUXEN)); printk("%s: REG_ANACR2=%x, REG_AUXMIC_CMC=%x, REG_AUXMIC_AUXEN=%x\n", __func__, val_anacr2, val_cmc, val_auxen); #endif } }
static int __init hs_probe(struct platform_device *pdev) { int result = 0; mic.pluging = DISABLE; mic.keypressing = INIT; result = hs_switchinit(&mic); if (result < 0) return result; result = hs_inputdev(&mic); if (result < 0) goto err; INIT_DELAYED_WORK(&(mic.imsi_work), getIMSI_work_func); wake_lock_init(&mic.det_wake_lock, WAKE_LOCK_SUSPEND, "brcm_headset_det"); mic.headset_workqueue = create_singlethread_workqueue("brcm_headset_wq"); if (mic.headset_workqueue == NULL) { printk("%s: Failed to create workqueue\n", __func__); goto err1; } /* check if platform data is defined for a particular board variant */ if (pdev->dev.platform_data) { mic.headset_pd = pdev->dev.platform_data; KEY_PRESS_THRESHOLD = mic.headset_pd->key_press_threshold; KEY_3POLE_THRESHOLD = mic.headset_pd->key_3pole_threshold; KEY1_THRESHOLD_L = mic.headset_pd->key1_threshold_l; KEY1_THRESHOLD_U = mic.headset_pd->key1_threshold_u; KEY2_THRESHOLD_L = mic.headset_pd->key2_threshold_l; KEY2_THRESHOLD_U = mic.headset_pd->key2_threshold_u; KEY3_THRESHOLD_L = mic.headset_pd->key3_threshold_l; KEY3_THRESHOLD_U = mic.headset_pd->key3_threshold_u; if (gpio_request(mic.headset_pd->hsgpio, "headset detect") < 0) { printk("%s: Could not reserve headset signal GPIO!\n", __func__); goto err2; } gpio_direction_input(mic.headset_pd->hsgpio); bcm_gpio_set_db_val(mic.headset_pd->hsgpio, 0x7); mic.headset_pd->hsirq = gpio_to_irq(mic.headset_pd->hsgpio); } else { goto err2; } /* Set the ANACR2 bit for mic power down */ board_sysconfig(SYSCFG_AUXMIC, SYSCFG_INIT); board_sysconfig(SYSCFG_HEADSET, SYSCFG_INIT); /*Fix the audio path is wrong when headset already plugged in the device then boot device case.*/ mic.headset_pd->check_hs_state(&mic.headset_state); set_irq_type(mic.headset_pd->hsirq, (mic.headset_state) ? IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING); determine_state_func(); queue_delayed_work(mic.headset_workqueue, &(mic.imsi_work), GET_IMSI_REF_TIME); result = request_threaded_irq(mic.headset_pd->hsbirq, NULL, hs_buttonisr, (IRQF_ONESHOT |IRQF_NO_SUSPEND), "BrcmHeadsetButton", NULL); if(result < 0) goto err2; DISABLE_IRQ_MICON; result = request_threaded_irq(mic.headset_pd->hsirq, NULL, hs_isr, (IRQF_ONESHOT|IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND), "BrcmHeadset", NULL); if(result < 0) { free_irq(mic.headset_pd->hsbirq, &mic); goto err2; } enable_irq_wake(mic.headset_pd->hsirq); set_irq_type(mic.headset_pd->hsirq, (mic.headset_state) ? IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING); return 0; err2: destroy_workqueue(mic.headset_workqueue); err1: input_unregister_device(mic.headset_button_idev); err: switch_dev_unregister(&mic.sdev); return result; }
/**************************************************************************** * * lcd_dev_dirty_rect * * Marks the indicated rows as dirty and arranges for them to be transferred * to the LCD. * ***************************************************************************/ static void lcd_dev_dirty_rect(LCD_dev_info_t * dev, LCD_DirtyRect_t * dirtyRect) { CSL_LCD_RES_T ret; int i; int err = -EINVAL; OSDAL_Dma_Buffer_List *buffer_list, *temp_list; if (unlikely(ap_crashed)) { return; } if(!dev) { pr_info("dev pointer is NULL\n"); return; } if(!dirtyRect) { pr_info("dirtyRect pointer is NULL\n"); return; } if ((dirtyRect->top > dirtyRect->bottom) || ((dirtyRect->bottom - dirtyRect->top) >= dev->height) || (dirtyRect->left > dirtyRect->right) || ((dirtyRect->right - dirtyRect->left) >= dev->width)) { LCD_DEBUG("invalid dirty-rows params - ignoring\n"); LCD_DEBUG("top = %u, bottom = %u, left = %u, right = %u\n", dirtyRect->top, dirtyRect->bottom, dirtyRect->left, dirtyRect->right); return; } down_interruptible(&gDmaSema); #ifdef CONFIG_HAS_WAKELOCK wake_lock(&glcdfb_wake_lock); #endif dev->dirty_rect = *dirtyRect; dev->row_start = dev->dirty_rect.top % dev->height; dev->row_end = dev->dirty_rect.bottom % dev->height; /*If start address is aligned to odd boundary */ if (is_unaligned(dev)) { dev->col_start = dev->dirty_rect.left; dev->col_end = dev->dirty_rect.left; lcd_setup_for_data(dev); lcd_update_column(dev, dev->dirty_rect.left); dev->dirty_rect.left += 1; } /*If length is odd multiple */ if (is_odd_stride(dev) || ((dev->bits_per_pixel == 32) && is_odd_total(dev))) { dev->col_start = dev->dirty_rect.right; dev->col_end = dev->dirty_rect.right; lcd_setup_for_data(dev); lcd_update_column(dev, dev->dirty_rect.right); dev->dirty_rect.right -= 1; } if (is_out_of_bounds(dev) || ((32 != dev->bits_per_pixel) && is_tx_done_16(dev)) || ((32 == dev->bits_per_pixel) && is_tx_done_32(dev))) { /* Dirty columns have been transferred. No further processing required.*/ goto done; } buffer_list = kzalloc((dev->dirty_rect.bottom - dev->dirty_rect.top + 1) * sizeof(OSDAL_Dma_Buffer_List), GFP_KERNEL); if (!buffer_list) { pr_info("Couldn't allocate memory for dma buffer list\n"); goto done; } temp_list = buffer_list; for (i = dev->dirty_rect.top; i <= dev->dirty_rect.bottom; i++) { temp_list->buffers[0].srcAddr = (UInt32)dev->frame_buffer.physPtr + (i * dev->width + dev->dirty_rect.left) * dev->bits_per_pixel / 8; temp_list->buffers[0].destAddr = REG_LCDC_DATR_PADDR; temp_list->buffers[0].length = (dev->dirty_rect.right - dev->dirty_rect.left + 1) * dev->bits_per_pixel / 8; temp_list->buffers[0].bRepeat = 0; temp_list++; } temp_list--; /* Go back to the last list item to set interrupt = 1 */ temp_list->buffers[0].interrupt = 1; req.buff = (void *)buffer_list; req.buffBpp = dev->bits_per_pixel; req.lineLenP = dev->dirty_rect.right - dev->dirty_rect.left + 1; req.lineCount = dev->dirty_rect.bottom - dev->dirty_rect.top + 1; req.timeOut_ms = 100; req.cslLcdCb = lcd_csl_cb; req.cslLcdCbRef = NULL; req.multiLLI = true; dev->col_start = dev->dirty_rect.left; dev->col_end = dev->dirty_rect.right; lcd_setup_for_data(dev); // if(hsm_supported && window_hsm_compatible(dev->dirty_rect)) // CSL_LCDC_PAR_SetSpeed(handle, &timingMem_hs); // else CSL_LCDC_PAR_SetSpeed(handle, &timingMem); /*CP processor is setting IOCR6[19], which it shouldn't be doing. Remove this once the CP team fixes it.*/ if (dev->te_supported) { board_sysconfig(SYSCFG_LCD, SYSCFG_ENABLE); } ret = CSL_LCDC_Update(handle, &req); if (CSL_LCD_OK != ret) { pr_info("CSL_LCDC_Update failed error: %d", ret); goto fail; } err = 0; fail: kfree(buffer_list); done: #ifdef CONFIG_HAS_WAKELOCK wake_unlock(&glcdfb_wake_lock); #endif if (err < 0) up(&gDmaSema); }