活动介绍

/*clear ACCDET IRQ in accdet register*/ 814 static inline void clear_accdet_interrupt(void) 815 { 816 /*it is safe by using polling to adjust when to clear IRQ_CLR_BIT*/ 817 pmic_pwrap_write(ACCDET_IRQ_STS, ((pmic_pwrap_read(ACCDET_IRQ_STS)) & 0x8000) | (IRQ_CLR_BIT)); 818 ACCDET_DEBUG("[Accdet]clear_accdet_interrupt: ACCDET_IRQ_STS = 0x%x\n", pmic_pwrap_read(ACCDET_IRQ_STS)); 819 } 820 821 static inline void clear_accdet_eint_interrupt(void) 822 { 823 pmic_pwrap_write(ACCDET_IRQ_STS, (((pmic_pwrap_read(ACCDET_IRQ_STS)) & 0x8000) | IRQ_EINT_CLR_BIT)); 824 ACCDET_DEBUG("[Accdet]clear_accdet_eint_interrupt: ACCDET_IRQ_STS = 0x%x\n", pmic_pwrap_read(ACCDET_IRQ_STS)); 825 } 826 827 static inline void check_cable_type(void) 828 { 829 int current_status = 0; 830 int irq_temp = 0; /*for clear IRQ_bit*/ 831 int wait_clear_irq_times = 0; 832 #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION 833 int pin_adc_value = 0; 834 #define PIN_ADC_CHANNEL 5 835 #endif 836 837 current_status = ((pmic_pwrap_read(ACCDET_STATE_RG) & 0xc0) >> 6); /*A=bit1; B=bit0*/ 838 ACCDET_DEBUG("[Accdet]accdet interrupt happen:[%s]current AB = %d\n", 839 accdet_status_string[accdet_status], current_status); 840 841 button_status = 0; 842 pre_status = accdet_status; 843 844 /*ACCDET_DEBUG("[Accdet]check_cable_type: ACCDET_IRQ_STS = 0x%x\n", pmic_pwrap_read(ACCDET_IRQ_STS));*/ 845 IRQ_CLR_FLAG = false; 846 switch (accdet_status) { 847 case PLUG_OUT: 848 #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION 849 pmic_pwrap_write(ACCDET_DEBOUNCE1, cust_headset_settings->debounce1); 850 #endif 851 if (current_status == 0) { 852 #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION 853 /*micbias always on during detected PIN recognition*/ 854 pmic_pwrap_write(ACCDET_PWM_WIDTH, cust_headset_settings->pwm_width); 855 pmic_pwrap_write(ACCDET_PWM_THRESH, cust_headset_settings->pwm_width); 856 ACCDET_DEBUG("[Accdet]PIN recognition micbias always on!\n"); 857 ACCDET_DEBUG("[Accdet]before adc read, pin_adc_value = %d mv!\n", pin_adc_value); 858 msleep(500); 859 current_status = ((pmic_pwrap_read(ACCDET_STATE_RG) & 0xc0) >> 6); /*A=bit1; B=bit0*/ 860 if (current_status == 0 && show_icon_delay != 0) { 861 /*accdet_auxadc_switch(1);switch on when need to use auxadc read voltage*/ 862 pin_adc_value = Accdet_PMIC_IMM_GetOneChannelValue(1); 863 ACCDET_DEBUG("[Accdet]pin_adc_value = %d mv!\n", pin_adc_value); 864 /*accdet_auxadc_switch(0);*/ 865 if (180 > pin_adc_value && pin_adc_value > 90) { /*90mv ilegal headset*/ 866 /*mt_set_gpio_out(GPIO_CAMERA_2_CMRST_PIN, GPIO_OUT_ONE);*/ 867 /*ACCDET_DEBUG("[Accdet]PIN recognition change GPIO_OUT!\n");*/ 868 mutex_lock(&accdet_eint_irq_sync_mutex); 869 if (1 == eint_accdet_sync_flag) { 870 cable_type = HEADSET_NO_MIC; 871 accdet_status = HOOK_SWITCH; 872 cable_pin_recognition = 1; 873 ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", 874 cable_pin_recognition); 875 } else { 876 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 877 } 878 mutex_unlock(&accdet_eint_irq_sync_mutex); 879 } else { 880 mutex_lock(&accdet_eint_irq_sync_mutex); 881 if (1 == eint_accdet_sync_flag) { 882 cable_type = HEADSET_NO_MIC; 883 accdet_status = HOOK_SWITCH; 884 } else { 885 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 886 } 887 mutex_unlock(&accdet_eint_irq_sync_mutex); 888 } 889 } 890 #else 891 mutex_lock(&accdet_eint_irq_sync_mutex); 892 if (1 == eint_accdet_sync_flag) { 893 cable_type = HEADSET_NO_MIC; 894 accdet_status = HOOK_SWITCH; 895 } else { 896 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 897 } 898 mutex_unlock(&accdet_eint_irq_sync_mutex); 899 #endif 900 } else if (current_status == 1) { 901 mutex_lock(&accdet_eint_irq_sync_mutex); 902 if (1 == eint_accdet_sync_flag) { 903 accdet_status = MIC_BIAS; 904 cable_type = HEADSET_MIC; 905 /*AB=11 debounce=30ms*/ 906 pmic_pwrap_write(ACCDET_DEBOUNCE3, cust_headset_settings->debounce3 * 30); 907 } else { 908 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 909 } 910 mutex_unlock(&accdet_eint_irq_sync_mutex); 911 pmic_pwrap_write(ACCDET_DEBOUNCE0, button_press_debounce); 912 /*recover polling set AB 00-01*/ 913 #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION 914 pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width)); 915 pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh)); 916 #endif 917 } else if (current_status == 3) { 918 ACCDET_DEBUG("[Accdet]PLUG_OUT state not change!\n"); 919 #ifdef CONFIG_ACCDET_EINT 920 ACCDET_DEBUG("[Accdet] do not send plug out event in plug out\n"); 921 #else 922 mutex_lock(&accdet_eint_irq_sync_mutex); 923 if (1 == eint_accdet_sync_flag) { 924 accdet_status = PLUG_OUT; 925 cable_type = NO_DEVICE; 926 } else { 927 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 928 } 929 mutex_unlock(&accdet_eint_irq_sync_mutex); 930 #endif 931 } else { 932 ACCDET_DEBUG("[Accdet]PLUG_OUT can't change to this state!\n"); 933 } 934 break; 935 936 case MIC_BIAS: 937 /*solution: resume hook switch debounce time*/ 938 pmic_pwrap_write(ACCDET_DEBOUNCE0, cust_headset_settings->debounce0); 939 940 if (current_status == 0) { 941 mutex_lock(&accdet_eint_irq_sync_mutex); 942 if (1 == eint_accdet_sync_flag) { 943 while ((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) 944 && (wait_clear_irq_times < 3)) { 945 ACCDET_DEBUG("[Accdet]check_cable_type: MIC BIAS clear IRQ on-going1....\n"); 946 wait_clear_irq_times++; 947 msleep(20); 948 } 949 irq_temp = pmic_pwrap_read(ACCDET_IRQ_STS); 950 irq_temp = irq_temp & (~IRQ_CLR_BIT); 951 pmic_pwrap_write(ACCDET_IRQ_STS, irq_temp); 952 IRQ_CLR_FLAG = true; 953 accdet_status = HOOK_SWITCH; 954 } else { 955 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 956 } 957 mutex_unlock(&accdet_eint_irq_sync_mutex); 958 button_status = 1; 959 if (button_status) { 960 mutex_lock(&accdet_eint_irq_sync_mutex); 961 if (1 == eint_accdet_sync_flag) 962 multi_key_detection(current_status); 963 else 964 ACCDET_DEBUG("[Accdet] multi_key_detection: Headset has plugged out\n"); 965 mutex_unlock(&accdet_eint_irq_sync_mutex); 966 /*accdet_auxadc_switch(0);*/ 967 /*recover pwm frequency and duty*/ 968 pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width)); 969 pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh)); 970 } 971 } else if (current_status == 1) { 972 mutex_lock(&accdet_eint_irq_sync_mutex); 973 if (1 == eint_accdet_sync_flag) { 974 accdet_status = MIC_BIAS; 975 cable_type = HEADSET_MIC; 976 ACCDET_DEBUG("[Accdet]MIC_BIAS state not change!\n"); 977 } else { 978 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 979 } 980 mutex_unlock(&accdet_eint_irq_sync_mutex); 981 } else if (current_status == 3) { 982 #if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ 983 ACCDET_DEBUG("[Accdet]do not send plug ou in micbiast\n"); 984 mutex_lock(&accdet_eint_irq_sync_mutex); 985 if (1 == eint_accdet_sync_flag) 986 accdet_status = PLUG_OUT; 987 else 988 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 989 mutex_unlock(&accdet_eint_irq_sync_mutex); 990 #else 991 mutex_lock(&accdet_eint_irq_sync_mutex); 992 if (1 == eint_accdet_sync_flag) { 993 accdet_status = PLUG_OUT; 994 cable_type = NO_DEVICE; 995 } else { 996 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 997 } 998 mutex_unlock(&accdet_eint_irq_sync_mutex); 999 #endif 1000 } else { 1001 ACCDET_DEBUG("[Accdet]MIC_BIAS can't change to this state!\n"); 1002 } 1003 break; 1004 1005 case HOOK_SWITCH: 1006 if (current_status == 0) { 1007 mutex_lock(&accdet_eint_irq_sync_mutex); 1008 if (1 == eint_accdet_sync_flag) { 1009 /*for avoid 01->00 framework of Headset will report press key info for Audio*/ 1010 /*cable_type = HEADSET_NO_MIC;*/ 1011 /*accdet_status = HOOK_SWITCH;*/ 1012 ACCDET_DEBUG("[Accdet]HOOK_SWITCH state not change!\n"); 1013 } else { 1014 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 1015 } 1016 mutex_unlock(&accdet_eint_irq_sync_mutex); 1017 } else if (current_status == 1) { 1018 mutex_lock(&accdet_eint_irq_sync_mutex); 1019 if (1 == eint_accdet_sync_flag) { 1020 multi_key_detection(current_status); 1021 accdet_status = MIC_BIAS; 1022 cable_type = HEADSET_MIC; 1023 } else { 1024 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 1025 } 1026 mutex_unlock(&accdet_eint_irq_sync_mutex); 1027 /*accdet_auxadc_switch(0);*/ 1028 #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION 1029 cable_pin_recognition = 0; 1030 ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", cable_pin_recognition); 1031 pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width)); 1032 pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh)); 1033 #endif 1034 /*solution: reduce hook switch debounce time to 0x400*/ 1035 pmic_pwrap_write(ACCDET_DEBOUNCE0, button_press_debounce); 1036 } else if (current_status == 3) { 1037 1038 #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION 1039 cable_pin_recognition = 0; 1040 ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", cable_pin_recognition); 1041 mutex_lock(&accdet_eint_irq_sync_mutex); 1042 if (1 == eint_accdet_sync_flag) 1043 accdet_status = PLUG_OUT; 1044 else 1045 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 1046 mutex_unlock(&accdet_eint_irq_sync_mutex); 1047 #endif 1048 #if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ 1049 ACCDET_DEBUG("[Accdet] do not send plug out event in hook switch\n"); 1050 mutex_lock(&accdet_eint_irq_sync_mutex); 1051 if (1 == eint_accdet_sync_flag) 1052 accdet_status = PLUG_OUT; 1053 else 1054 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 1055 mutex_unlock(&accdet_eint_irq_sync_mutex); 1056 #else 1057 mutex_lock(&accdet_eint_irq_sync_mutex); 1058 if (1 == eint_accdet_sync_flag) { 1059 accdet_status = PLUG_OUT; 1060 cable_type = NO_DEVICE; 1061 } else { 1062 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 1063 } 1064 mutex_unlock(&accdet_eint_irq_sync_mutex); 1065 #endif 1066 } else { 1067 ACCDET_DEBUG("[Accdet]HOOK_SWITCH can't change to this state!\n"); 1068 } 1069 break; 1070 case STAND_BY: 1071 if (current_status == 3) { 1072 #if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ 1073 ACCDET_DEBUG("[Accdet]accdet do not send plug out event in stand by!\n"); 1074 #else 1075 mutex_lock(&accdet_eint_irq_sync_mutex); 1076 if (1 == eint_accdet_sync_flag) { 1077 accdet_status = PLUG_OUT; 1078 cable_type = NO_DEVICE; 1079 } else { 1080 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 1081 } 1082 mutex_unlock(&accdet_eint_irq_sync_mutex); 1083 #endif 1084 } else { 1085 ACCDET_DEBUG("[Accdet]STAND_BY can't change to this state!\n"); 1086 } 1087 break; 1088 1089 default: 1090 ACCDET_DEBUG("[Accdet]check_cable_type: accdet current status error!\n"); 1091 break; 1092 1093 } 1094 1095 if (!IRQ_CLR_FLAG) { 1096 mutex_lock(&accdet_eint_irq_sync_mutex); 1097 if (1 == eint_accdet_sync_flag) { 1098 while ((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) && (wait_clear_irq_times < 3)) { 1099 ACCDET_DEBUG("[Accdet]check_cable_type: Clear interrupt on-going2....\n"); 1100 wait_clear_irq_times++; 1101 msleep(20); 1102 } 1103 } 1104 irq_temp = pmic_pwrap_read(ACCDET_IRQ_STS); 1105 irq_temp = irq_temp & (~IRQ_CLR_BIT); 1106 pmic_pwrap_write(ACCDET_IRQ_STS, irq_temp); 1107 mutex_unlock(&accdet_eint_irq_sync_mutex); 1108 IRQ_CLR_FLAG = true; 1109 ACCDET_DEBUG("[Accdet]check_cable_type:Clear interrupt:Done[0x%x]!\n", pmic_pwrap_read(ACCDET_IRQ_STS)); 1110 1111 } else { 1112 IRQ_CLR_FLAG = false; 1113 } 1114 1115 ACCDET_DEBUG("[Accdet]cable type:[%s], status switch:[%s]->[%s]\n", 1116 accdet_report_string[cable_type], accdet_status_string[pre_status], 1117 accdet_status_string[accdet_status]); 1118 }

时间: 2025-07-21 09:01:21 浏览: 12
<think>我们正在分析一个耳机检测驱动中的`check_cable_type`函数。该函数负责根据当前状态和读取的寄存器值来确定耳机类型和状态变化。 函数主要逻辑: 1. 读取当前状态寄存器值(ACCDET_STATE_RG),提取A、B两个状态位(current_status) 2. 根据accdet_status(当前记录的状态)和current_status(硬件当前状态)进行状态转移和事件处理 3. 使用互斥锁(accdet_eint_irq_sync_mutex)保护共享变量(如eint_accdet_sync_flag)的访问 4. 在状态转移过程中,可能会调用multi_key_detection进行按键检测,并设置cable_type(耳机类型)和accdet_status(状态) 状态定义: 从代码中可以看出,accdet_status有以下几个状态: PLUG_OUT: 拔出状态 MIC_BIAS: 带麦克风的耳机(四极)插入状态 HOOK_SWITCH: 无麦克风的耳机(三极)插入状态,或按键状态 STAND_BY: 待机状态(代码中处理较少) 另外,cable_type有: HEADSET_NO_MIC: 无麦克风耳机(三极) HEADSET_MIC: 带麦克风耳机(四极) NO_DEVICE: 无设备 关键变量: eint_accdet_sync_flag: 用于同步中断事件,表示耳机插入事件是否有效(防止在拔出过程中处理中断) 函数流程: 1. 获取当前硬件状态current_status(AB两位) 2. 根据当前accdet_status(之前的状态)进行分支处理(switch) 3. 在每个状态分支中,根据current_status的值(0,1,3)进行不同的处理 详细分析每个状态分支: 一、当前状态为PLUG_OUT(拔出状态)时: - 如果current_status为0(AB=00): #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION(支持引脚识别) 设置去抖参数,然后打开麦克风偏置(micbias always on),延迟500ms后再次读取状态。 如果状态仍为0,则进行ADC采样(检测引脚电压): 如果电压在90mv到180mv之间,则认为是非法耳机(可能是三极耳机,但代码中标记为HEADSET_NO_MIC)并设置cable_pin_recognition=1(表示通过引脚识别出的三极耳机) 否则,也设置为三极耳机(HEADSET_NO_MIC)并进入HOOK_SWITCH状态(但没有设置cable_pin_recognition) #else 直接设置为三极耳机(HEADSET_NO_MIC)并进入HOOK_SWITCH状态 #endif - 如果current_status为1(AB=01): 设置为四极耳机(HEADSET_MIC),进入MIC_BIAS状态,并设置去抖参数(debounce3为30倍的设定值,即30ms*30=900ms?) 同时设置按键按下的去抖时间为button_press_debounce(较短) - 如果current_status为3(AB=11): 在PLUG_OUT状态下出现AB=11,可能是未改变状态(即仍然为拔出),但根据配置(如定义了CONFIG_ACCDET_EINT)可能不发送事件,或者设置为PLUG_OUT(无设备) 二、当前状态为MIC_BIAS(四极耳机插入)时: - 恢复去抖时间(debounce0为正常值) - 如果current_status为0(AB=00): 清除中断标志,并设置状态为HOOK_SWITCH(注意:这里在状态转换后,还进行了按键检测(multi_key_detection)) 同时,设置button_status=1,表示有按键事件?然后调用multi_key_detection(注意:这里传递的current_status是0,表示按键释放?) 最后恢复PWM设置。 - 如果current_status为1(AB=01): 状态不变(仍然是MIC_BIAS,四极耳机) - 如果current_status为3(AB=11): 进入PLUG_OUT状态(拔出),设置cable_type为NO_DEVICE。 三、当前状态为HOOK_SWITCH(三极耳机插入)时: - 如果current_status为0(AB=00): 状态不变(还是HOOK_SWITCH),打印日志 - 如果current_status为1(AB=01): 调用multi_key_detection(注意:此时传递的current_status是1,表示按键按下?)然后状态转为MIC_BIAS(四极耳机)?这里似乎有矛盾。 注意:三极耳机只有三个触点(左、右、地),不会出现AB=01(四极耳机才有的状态)。所以这里可能是检测到四极耳机了? 实际上,当三极耳机上按下按键时,会将左右声道短接到麦克风,从而模拟出四极耳机的状态?所以这里可能是按键事件导致状态变化。 因此,这里将状态改为MIC_BIAS(表示按键按下,进入四极耳机模式?)并设置cable_type为HEADSET_MIC(四极)?但三极耳机按下按键时,我们不应该改变耳机类型。 这里可能设计为:当三极耳机按下按键时,我们暂时将其当作四极耳机来处理(因为此时电路连接类似四极耳机),然后通过按键检测来上报按键事件。 在按键释放后,状态会回到HOOK_SWITCH(三极耳机状态)。 另外,这里还做了一些操作:恢复PWM设置,设置去抖时间为button_press_debounce(较短,以便快速响应按键) - 如果current_status为3(AB=11): 进入PLUG_OUT状态(拔出) 四、当前状态为STAND_BY(待机)时: 只有current_status为3(AB=11)时,才进入PLUG_OUT状态。 最后,函数会清除中断标志(如果之前没有清除的话),并打印状态转换日志。 注意:在整个过程中,都使用eint_accdet_sync_flag(在互斥锁保护下)来判断耳机是否在检测过程中被拔出。如果被拔出(eint_accdet_sync_flag为0),则不进行状态转换。 状态转移图(简化): PLUG_OUT -> HOOK_SWITCH (当检测到三极耳机) PLUG_OUT -> MIC_BIAS (当检测到四极耳机) MIC_BIAS -> HOOK_SWITCH (当AB从01变为00,即按键按下?) HOOK_SWITCH -> MIC_BIAS (当AB从00变为01,即按键释放?但实际上代码中在HOOK_SWITCH状态遇到AB=01会转到MIC_BIAS,这可能是按键按下) MIC_BIAS -> PLUG_OUT (当AB=11) HOOK_SWITCH -> PLUG_OUT (当AB=11) 但注意:状态转移中,按键事件会触发状态在HOOK_SWITCH和MIC_BIAS之间转换,而PLUG_OUT是初始和结束状态。 问题:为什么在MIC_BIAS状态下,AB=00会转换到HOOK_SWITCH?而在HOOK_SWITCH状态下,AB=01会转换到MIC_BIAS? 这可能是因为: - 在四极耳机上按下按键时,电路状态会从AB=01(MIC_BIAS)变为AB=00(按键按下,麦克风与地短路,相当于三极耳机的状态?),所以转到HOOK_SWITCH状态(三极状态)并检测按键。 - 而在三极耳机上按下按键时,电路状态会从AB=00(HOOK_SWITCH)变为AB=01(按键按下,左右声道短接到麦克风引脚,模拟四极耳机的麦克风状态),所以转到MIC_BIAS状态(四极状态)并检测按键。 因此,状态转移实际上是根据按键按下/释放引起的电路变化而设计的。 总结: 这个函数通过状态机来管理耳机的插入、拔出和按键事件,结合硬件状态(AB两位)和当前状态,进行状态转移,并在转移过程中上报事件(通过调用send_accdet_status_event和send_key_event,但这两个调用不在这个函数中,而是在状态转移后的其他地方?)。 注意:函数中并没有直接上报事件,而是设置cable_type和accdet_status,事件上报可能在另一个函数(如工作队列函数)中处理。 另外,代码中很多地方使用互斥锁来保护对eint_accdet_sync_flag的访问,这是为了防止在中断服务例程中修改这个标志时发生竞争条件。 最后,函数末尾会清除中断标志(如果之前没有清除的话),确保中断不会被重复触发。 由于代码较长,我们只分析主要逻辑,具体细节可结合注释和调试日志。</think>以下是对耳机检测驱动中状态机与电缆类型识别机制的详细解析: ### 核心状态机设计 ```mermaid stateDiagram-v2 [*] --> PLUG_OUT PLUG_OUT --> HOOK_SWITCH: AB=00 (三极耳机) PLUG_OUT --> MIC_BIAS: AB=01 (四极耳机) HOOK_SWITCH --> MIC_BIAS: AB=01 (按键按下) MIC_BIAS --> HOOK_SWITCH: AB=00 (按键释放) HOOK_SWITCH --> PLUG_OUT: AB=11 (拔出) MIC_BIAS --> PLUG_OUT: AB=11 (拔出) ``` ### 关键处理流程 #### 1. 状态寄存器解析(行837) ```c current_status = (pmic_pwrap_read(ACCDET_STATE_RG) & 0xc0) >> 6; ``` - **AB位含义**: - `00`:三极耳机(无麦克风) - `01`:四极耳机(带麦克风) - `11`:拔出状态 #### 2. 引脚识别机制(CONFIG_ACCDET_PIN_RECOGNIZATION) ```c #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION pin_adc_value = Accdet_PMIC_IMM_GetOneChannelValue(1); // ADC通道1采样 if (180 > pin_adc_value && pin_adc_value > 90) { // 90-180mV范围 cable_type = HEADSET_NO_MIC; // 识别为三极耳机 cable_pin_recognition = 1; // 设置引脚识别标志 } #endif ``` **电压阈值**: - 90-180mV → 三极耳机 - 其他范围 → 四极耳机 #### 3. 状态转移控制 ##### (1) PLUG_OUT → HOOK_SWITCH(三极耳机插入) ```c case PLUG_OUT: if (current_status == 0) { cable_type = HEADSET_NO_MIC; accdet_status = HOOK_SWITCH; } ``` ##### (2) PLUG_OUT → MIC_BIAS(四极耳机插入) ```c else if (current_status == 1) { accdet_status = MIC_BIAS; cable_type = HEADSET_MIC; pmic_pwrap_write(ACCDET_DEBOUNCE3, debounce3*30); // 配置去抖 } ``` ##### (3) MIC_BIAS ↔ HOOK_SWITCH(按键检测) ```c case MIC_BIAS: if (current_status == 0) { // 按键按下 accdet_status = HOOK_SWITCH; multi_key_detection(current_status); // 触发按键检测 } case HOOK_SWITCH: if (current_status == 1) { // 按键释放 accdet_status = MIC_BIAS; multi_key_detection(current_status); } ``` ### 互斥锁保护机制 ```c mutex_lock(&accdet_eint_irq_sync_mutex); if (1 == eint_accdet_sync_flag) { // 检查插拔同步标志 // 执行状态变更操作 } mutex_unlock(&accdet_eint_irq_sync_mutex); ``` **作用**: 1. 防止中断服务程序与工作队列并发访问共享状态 2. 确保在耳机拔出时不处理无效状态转换 3. 避免按键检测过程中的竞态条件 ### 寄存器配置策略 | 寄存器 | 功能说明 | 典型配置位置 | |----------------------|-----------------------------------|-----------------------| | ACCDET_DEBOUNCE0 | 按键释放去抖时间 | 行938, 1035 | | ACCDET_DEBOUNCE3 | 四极耳机插入去抖时间 | 行906 | | ACCDET_PWM_WIDTH | PWM脉冲宽度配置 | 行758, 914 | | ACCDET_PWM_THRESH | PWM电压阈值 | 行759, 915 | ### 异常处理机制 ```c // 中断清除重试机制(行943-948) while ((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) && (wait_clear_irq_times < 3)) { wait_clear_irq_times++; msleep(20); // 20ms重试间隔 } ``` **设计要点**: 1. 最大重试次数3次防止死循环 2. 20ms延时兼顾硬件响应速度和系统性能 3. 配合IRQ_CLR_FLAG确保中断状态同步 ### 调试日志系统 ```c ACCDET_DEBUG("cable type:[%s], status:[%s]->[%s]\n", accdet_report_string[cable_type], accdet_status_string[pre_status], accdet_status_string[accdet_status]); // 行1115 ``` **日志等级**: - 状态转换:INFO级(常规记录) - 异常检测:WARN级(如行932,1001) - 硬件错误:ERROR级(如行802负电压检测)
阅读全文

相关推荐

这几个函数static inline void enable_accdet(u32 state_swctrl) 268 { 269 /*enable ACCDET unit*/ 270 ACCDET_DEBUG("accdet: enable_accdet\n"); 271 /*enable clock*/ 272 pmic_pwrap_write(TOP_CKPDN_CLR, RG_ACCDET_CLK_CLR); 273 pmic_pwrap_write(ACCDET_STATE_SWCTRL, pmic_pwrap_read(ACCDET_STATE_SWCTRL) | state_swctrl); 274 pmic_pwrap_write(ACCDET_CTRL, pmic_pwrap_read(ACCDET_CTRL) | ACCDET_ENABLE); 275 276 } 277 278 static inline void disable_accdet(void) 279 { 280 int irq_temp = 0; 281 282 /*sync with accdet_irq_handler set clear accdet irq bit to avoid set clear accdet irq bit after disable accdet 283 disable accdet irq*/ 284 pmic_pwrap_write(INT_CON_ACCDET_CLR, RG_ACCDET_IRQ_CLR); 285 clear_accdet_interrupt(); 286 udelay(200); 287 mutex_lock(&accdet_eint_irq_sync_mutex); 288 while (pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) { 289 ACCDET_DEBUG("[Accdet]check_cable_type: Clear interrupt on-going....\n"); 290 msleep(20); 291 } 292 irq_temp = pmic_pwrap_read(ACCDET_IRQ_STS); 293 irq_temp = irq_temp & (~IRQ_CLR_BIT); 294 pmic_pwrap_write(ACCDET_IRQ_STS, irq_temp); 295 mutex_unlock(&accdet_eint_irq_sync_mutex); 296 /*disable ACCDET unit*/ 297 ACCDET_DEBUG("accdet: disable_accdet\n"); 298 pre_state_swctrl = pmic_pwrap_read(ACCDET_STATE_SWCTRL); 299 #ifdef CONFIG_ACCDET_EINT 300 pmic_pwrap_write(ACCDET_STATE_SWCTRL, 0); 301 pmic_pwrap_write(ACCDET_CTRL, ACCDET_DISABLE); 302 /*disable clock and Analog control*/ 303 /*mt6331_upmu_set_rg_audmicbias1vref(0x0);*/ 304 pmic_pwrap_write(TOP_CKPDN_SET, RG_ACCDET_CLK_SET); 305 #endif 306 #ifdef CONFIG_ACCDET_EINT_IRQ 307 pmic_pwrap_write(ACCDET_STATE_SWCTRL, ACCDET_EINT_PWM_EN); 308 pmic_pwrap_write(ACCDET_CTRL, pmic_pwrap_read(ACCDET_CTRL) & (~(ACCDET_ENABLE))); 309 /*mt_set_gpio_out(GPIO_CAMERA_2_CMRST_PIN, GPIO_OUT_ZERO);*/ 310 #endif 311 312 } 313 314 #if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ 315 static void disable_micbias(struct timer_list *t) 316 { 317 int ret = 0; 318 319 ret = queue_work(accdet_disable_workqueue, &accdet_disable_work); 320 if (!ret) 321 ACCDET_DEBUG("[Accdet]disable_micbias:accdet_work return:%d!\n", ret); 322 } 323 324 static void disable_micbias_callback(struct work_struct *work) 325 { 326 327 if (cable_type == HEADSET_NO_MIC) { 328 #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION 329 show_icon_delay = 0; 330 cable_pin_recognition = 0; 331 ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", cable_pin_recognition); 332 pmic_pwrap_write(ACCDET_PWM_WIDTH, cust_headset_settings->pwm_width); 333 pmic_pwrap_write(ACCDET_PWM_THRESH, cust_headset_settings->pwm_thresh); 334 #endif 335 /*setting pwm idle;*/ 336 pmic_pwrap_write(ACCDET_STATE_SWCTRL, pmic_pwrap_read(ACCDET_STATE_SWCTRL) & ~ACCDET_SWCTRL_IDLE_EN); 337 #ifdef CONFIG_ACCDET_PIN_SWAP 338 /*accdet_FSA8049_disable(); disable GPIOxxx for PIN swap */ 339 /*ACCDET_DEBUG("[Accdet] FSA8049 disable!\n");*/ 340 #endif 341 disable_accdet(); 342 ACCDET_DEBUG("[Accdet] more than 5s MICBIAS : Disabled\n"); 343 } 344 #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION 345 else if (cable_type == HEADSET_MIC) { 346 pmic_pwrap_write(ACCDET_PWM_WIDTH, cust_headset_settings->pwm_width); 347 pmic_pwrap_write(ACCDET_PWM_THRESH, cust_headset_settings->pwm_thresh); 348 ACCDET_DEBUG("[Accdet]pin recog after 5s recover micbias polling!\n"); 349 } 350 #endif 351 }

解析这个函数:static inline void check_cable_type(void) 828 { 829 int current_status = 0; 830 int irq_temp = 0; /*for clear IRQ_bit*/ 831 int wait_clear_irq_times = 0; 832 #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION 833 int pin_adc_value = 0; 834 #define PIN_ADC_CHANNEL 5 835 #endif 836 837 current_status = ((pmic_pwrap_read(ACCDET_STATE_RG) & 0xc0) >> 6); /*A=bit1; B=bit0*/ 838 ACCDET_DEBUG("[Accdet]accdet interrupt happen:[%s]current AB = %d\n", 839 accdet_status_string[accdet_status], current_status); 840 841 button_status = 0; 842 pre_status = accdet_status; 843 844 /*ACCDET_DEBUG("[Accdet]check_cable_type: ACCDET_IRQ_STS = 0x%x\n", pmic_pwrap_read(ACCDET_IRQ_STS));*/ 845 IRQ_CLR_FLAG = false; 846 switch (accdet_status) { 847 case PLUG_OUT: 848 #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION 849 pmic_pwrap_write(ACCDET_DEBOUNCE1, cust_headset_settings->debounce1); 850 #endif 851 if (current_status == 0) { 852 #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION 853 /*micbias always on during detected PIN recognition*/ 854 pmic_pwrap_write(ACCDET_PWM_WIDTH, cust_headset_settings->pwm_width); 855 pmic_pwrap_write(ACCDET_PWM_THRESH, cust_headset_settings->pwm_width); 856 ACCDET_DEBUG("[Accdet]PIN recognition micbias always on!\n"); 857 ACCDET_DEBUG("[Accdet]before adc read, pin_adc_value = %d mv!\n", pin_adc_value); 858 msleep(500); 859 current_status = ((pmic_pwrap_read(ACCDET_STATE_RG) & 0xc0) >> 6); /*A=bit1; B=bit0*/ 860 if (current_status == 0 && show_icon_delay != 0) { 861 /*accdet_auxadc_switch(1);switch on when need to use auxadc read voltage*/ 862 pin_adc_value = Accdet_PMIC_IMM_GetOneChannelValue(1); 863 ACCDET_DEBUG("[Accdet]pin_adc_value = %d mv!\n", pin_adc_value); 864 /*accdet_auxadc_switch(0);*/ 865 if (180 > pin_adc_value && pin_adc_value > 90) { /*90mv ilegal headset*/ 866 /*mt_set_gpio_out(GPIO_CAMERA_2_CMRST_PIN, GPIO_OUT_ONE);*/ 867 /*ACCDET_DEBUG("[Accdet]PIN recognition change GPIO_OUT!\n");*/ 868 mutex_lock(&accdet_eint_irq_sync_mutex); 869 if (1 == eint_accdet_sync_flag) { 870 cable_type = HEADSET_NO_MIC; 871 accdet_status = HOOK_SWITCH; 872 cable_pin_recognition = 1; 873 ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", 874 cable_pin_recognition); 875 } else { 876 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 877 } 878 mutex_unlock(&accdet_eint_irq_sync_mutex); 879 } else { 880 mutex_lock(&accdet_eint_irq_sync_mutex); 881 if (1 == eint_accdet_sync_flag) { 882 cable_type = HEADSET_NO_MIC; 883 accdet_status = HOOK_SWITCH; 884 } else { 885 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 886 } 887 mutex_unlock(&accdet_eint_irq_sync_mutex); 888 } 889 } 890 #else 891 mutex_lock(&accdet_eint_irq_sync_mutex); 892 if (1 == eint_accdet_sync_flag) { 893 cable_type = HEADSET_NO_MIC; 894 accdet_status = HOOK_SWITCH; 895 } else { 896 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 897 } 898 mutex_unlock(&accdet_eint_irq_sync_mutex); 899 #endif 900 } else if (current_status == 1) { 901 mutex_lock(&accdet_eint_irq_sync_mutex); 902 if (1 == eint_accdet_sync_flag) { 903 accdet_status = MIC_BIAS; 904 cable_type = HEADSET_MIC; 905 /*AB=11 debounce=30ms*/ 906 pmic_pwrap_write(ACCDET_DEBOUNCE3, cust_headset_settings->debounce3 * 30); 907 } else { 908 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 909 } 910 mutex_unlock(&accdet_eint_irq_sync_mutex); 911 pmic_pwrap_write(ACCDET_DEBOUNCE0, button_press_debounce); 912 /*recover polling set AB 00-01*/ 913 #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION 914 pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width)); 915 pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh)); 916 #endif 917 } else if (current_status == 3) { 918 ACCDET_DEBUG("[Accdet]PLUG_OUT state not change!\n"); 919 #ifdef CONFIG_ACCDET_EINT 920 ACCDET_DEBUG("[Accdet] do not send plug out event in plug out\n"); 921 #else 922 mutex_lock(&accdet_eint_irq_sync_mutex); 923 if (1 == eint_accdet_sync_flag) { 924 accdet_status = PLUG_OUT; 925 cable_type = NO_DEVICE; 926 } else { 927 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 928 } 929 mutex_unlock(&accdet_eint_irq_sync_mutex); 930 #endif 931 } else { 932 ACCDET_DEBUG("[Accdet]PLUG_OUT can't change to this state!\n"); 933 } 934 break; 935 936 case MIC_BIAS: 937 /*solution: resume hook switch debounce time*/ 938 pmic_pwrap_write(ACCDET_DEBOUNCE0, cust_headset_settings->debounce0); 939 940 if (current_status == 0) { 941 mutex_lock(&accdet_eint_irq_sync_mutex); 942 if (1 == eint_accdet_sync_flag) { 943 while ((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) 944 && (wait_clear_irq_times < 3)) { 945 ACCDET_DEBUG("[Accdet]check_cable_type: MIC BIAS clear IRQ on-going1....\n"); 946 wait_clear_irq_times++; 947 msleep(20); 948 } 949 irq_temp = pmic_pwrap_read(ACCDET_IRQ_STS); 950 irq_temp = irq_temp & (~IRQ_CLR_BIT); 951 pmic_pwrap_write(ACCDET_IRQ_STS, irq_temp); 952 IRQ_CLR_FLAG = true; 953 accdet_status = HOOK_SWITCH; 954 } else { 955 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 956 } 957 mutex_unlock(&accdet_eint_irq_sync_mutex); 958 button_status = 1; 959 if (button_status) { 960 mutex_lock(&accdet_eint_irq_sync_mutex); 961 if (1 == eint_accdet_sync_flag) 962 multi_key_detection(current_status); 963 else 964 ACCDET_DEBUG("[Accdet] multi_key_detection: Headset has plugged out\n"); 965 mutex_unlock(&accdet_eint_irq_sync_mutex); 966 /*accdet_auxadc_switch(0);*/ 967 /*recover pwm frequency and duty*/ 968 pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width)); 969 pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh)); 970 } 971 } else if (current_status == 1) { 972 mutex_lock(&accdet_eint_irq_sync_mutex); 973 if (1 == eint_accdet_sync_flag) { 974 accdet_status = MIC_BIAS; 975 cable_type = HEADSET_MIC; 976 ACCDET_DEBUG("[Accdet]MIC_BIAS state not change!\n"); 977 } else { 978 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 979 } 980 mutex_unlock(&accdet_eint_irq_sync_mutex); 981 } else if (current_status == 3) { 982 #if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ 983 ACCDET_DEBUG("[Accdet]do not send plug ou in micbiast\n"); 984 mutex_lock(&accdet_eint_irq_sync_mutex); 985 if (1 == eint_accdet_sync_flag) 986 accdet_status = PLUG_OUT; 987 else 988 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 989 mutex_unlock(&accdet_eint_irq_sync_mutex); 990 #else 991 mutex_lock(&accdet_eint_irq_sync_mutex); 992 if (1 == eint_accdet_sync_flag) { 993 accdet_status = PLUG_OUT; 994 cable_type = NO_DEVICE; 995 } else { 996 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 997 } 998 mutex_unlock(&accdet_eint_irq_sync_mutex); 999 #endif 1000 } else { 1001 ACCDET_DEBUG("[Accdet]MIC_BIAS can't change to this state!\n"); 1002 } 1003 break; 1004 1005 case HOOK_SWITCH: 1006 if (current_status == 0) { 1007 mutex_lock(&accdet_eint_irq_sync_mutex); 1008 if (1 == eint_accdet_sync_flag) { 1009 /*for avoid 01->00 framework of Headset will report press key info for Audio*/ 1010 /*cable_type = HEADSET_NO_MIC;*/ 1011 /*accdet_status = HOOK_SWITCH;*/ 1012 ACCDET_DEBUG("[Accdet]HOOK_SWITCH state not change!\n"); 1013 } else { 1014 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 1015 } 1016 mutex_unlock(&accdet_eint_irq_sync_mutex); 1017 } else if (current_status == 1) { 1018 mutex_lock(&accdet_eint_irq_sync_mutex); 1019 if (1 == eint_accdet_sync_flag) { 1020 multi_key_detection(current_status); 1021 accdet_status = MIC_BIAS; 1022 cable_type = HEADSET_MIC; 1023 } else { 1024 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 1025 } 1026 mutex_unlock(&accdet_eint_irq_sync_mutex); 1027 /*accdet_auxadc_switch(0);*/ 1028 #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION 1029 cable_pin_recognition = 0; 1030 ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", cable_pin_recognition); 1031 pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width)); 1032 pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh)); 1033 #endif 1034 /*solution: reduce hook switch debounce time to 0x400*/ 1035 pmic_pwrap_write(ACCDET_DEBOUNCE0, button_press_debounce); 1036 } else if (current_status == 3) { 1037 1038 #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION 1039 cable_pin_recognition = 0; 1040 ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", cable_pin_recognition); 1041 mutex_lock(&accdet_eint_irq_sync_mutex); 1042 if (1 == eint_accdet_sync_flag) 1043 accdet_status = PLUG_OUT; 1044 else 1045 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 1046 mutex_unlock(&accdet_eint_irq_sync_mutex); 1047 #endif 1048 #if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ 1049 ACCDET_DEBUG("[Accdet] do not send plug out event in hook switch\n"); 1050 mutex_lock(&accdet_eint_irq_sync_mutex); 1051 if (1 == eint_accdet_sync_flag) 1052 accdet_status = PLUG_OUT; 1053 else 1054 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 1055 mutex_unlock(&accdet_eint_irq_sync_mutex); 1056 #else 1057 mutex_lock(&accdet_eint_irq_sync_mutex); 1058 if (1 == eint_accdet_sync_flag) { 1059 accdet_status = PLUG_OUT; 1060 cable_type = NO_DEVICE; 1061 } else { 1062 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 1063 } 1064 mutex_unlock(&accdet_eint_irq_sync_mutex); 1065 #endif 1066 } else { 1067 ACCDET_DEBUG("[Accdet]HOOK_SWITCH can't change to this state!\n"); 1068 } 1069 break; 1070 case STAND_BY: 1071 if (current_status == 3) { 1072 #if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ 1073 ACCDET_DEBUG("[Accdet]accdet do not send plug out event in stand by!\n"); 1074 #else 1075 mutex_lock(&accdet_eint_irq_sync_mutex); 1076 if (1 == eint_accdet_sync_flag) { 1077 accdet_status = PLUG_OUT; 1078 cable_type = NO_DEVICE; 1079 } else { 1080 ACCDET_DEBUG("[Accdet] Headset has plugged out\n"); 1081 } 1082 mutex_unlock(&accdet_eint_irq_sync_mutex); 1083 #endif 1084 } else { 1085 ACCDET_DEBUG("[Accdet]STAND_BY can't change to this state!\n"); 1086 } 1087 break; 1088 1089 default: 1090 ACCDET_DEBUG("[Accdet]check_cable_type: accdet current status error!\n"); 1091 break; 1092 1093 } 1094 1095 if (!IRQ_CLR_FLAG) { 1096 mutex_lock(&accdet_eint_irq_sync_mutex); 1097 if (1 == eint_accdet_sync_flag) { 1098 while ((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) && (wait_clear_irq_times < 3)) { 1099 ACCDET_DEBUG("[Accdet]check_cable_type: Clear interrupt on-going2....\n"); 1100 wait_clear_irq_times++; 1101 msleep(20); 1102 } 1103 } 1104 irq_temp = pmic_pwrap_read(ACCDET_IRQ_STS); 1105 irq_temp = irq_temp & (~IRQ_CLR_BIT); 1106 pmic_pwrap_write(ACCDET_IRQ_STS, irq_temp); 1107 mutex_unlock(&accdet_eint_irq_sync_mutex); 1108 IRQ_CLR_FLAG = true; 1109 ACCDET_DEBUG("[Accdet]check_cable_type:Clear interrupt:Done[0x%x]!\n", pmic_pwrap_read(ACCDET_IRQ_STS)); 1110 1111 } else { 1112 IRQ_CLR_FLAG = false; 1113 } 1114 1115 ACCDET_DEBUG("[Accdet]cable type:[%s], status switch:[%s]->[%s]\n", 1116 accdet_report_string[cable_type], accdet_status_string[pre_status], 1117 accdet_status_string[accdet_status]); 1118 }

static void send_accdet_status_event(int cable_type, int status) 664 { 665 switch (cable_type) { 666 case HEADSET_NO_MIC: 667 input_report_switch(kpd_accdet_dev, SW_HEADPHONE_INSERT, status); 668 input_report_switch(kpd_accdet_dev, SW_JACK_PHYSICAL_INSERT, status); 669 input_sync(kpd_accdet_dev); 670 ACCDET_DEBUG("[Accdet]HEADSET_NO_MIC(3-pole) %s\n", status?"PlugIn":"PlugOut"); 671 break; 672 case HEADSET_MIC: 673 input_report_switch(kpd_accdet_dev, SW_HEADPHONE_INSERT, status); 674 input_report_switch(kpd_accdet_dev, SW_MICROPHONE_INSERT, status); 675 input_report_switch(kpd_accdet_dev, SW_JACK_PHYSICAL_INSERT, status); 676 input_sync(kpd_accdet_dev); 677 ACCDET_DEBUG("[Accdet]HEADSET_MIC(4-pole) %s\n", status?"PlugIn":"PlugOut"); 678 break; 679 default: 680 ACCDET_DEBUG("[Accdet]Invalid cableType\n"); 681 } 682 } 683 684 static void send_key_event(int keycode, int flag) 685 { 686 switch (keycode) { 687 case DW_KEY: 688 input_report_key(kpd_accdet_dev, KEY_VOLUMEDOWN, flag); 689 input_sync(kpd_accdet_dev); 690 ACCDET_DEBUG("[accdet]KEY_VOLUMEDOWN %d\n", flag); 691 break; 692 case UP_KEY: 693 input_report_key(kpd_accdet_dev, KEY_VOLUMEUP, flag); 694 input_sync(kpd_accdet_dev); 695 ACCDET_DEBUG("[accdet]KEY_VOLUMEUP %d\n", flag); 696 break; 697 case MD_KEY: 698 input_report_key(kpd_accdet_dev, KEY_PLAYPAUSE, flag); 699 input_sync(kpd_accdet_dev); 700 ACCDET_DEBUG("[accdet]KEY_PLAYPAUSE %d\n", flag); 701 break; 702 case AS_KEY: 703 input_report_key(kpd_accdet_dev, KEY_VOICECOMMAND, flag); 704 input_sync(kpd_accdet_dev); 705 ACCDET_DEBUG("[accdet]KEY_VOICECOMMAND %d\n", flag); 706 break; 707 } 708 } 709 710 static void multi_key_detection(int current_status) 711 { 712 int m_key = 0; 713 int cali_voltage = 0; 714 715 if (0 == current_status) { 716 cali_voltage = Accdet_PMIC_IMM_GetOneChannelValue(1); 717 /*ACCDET_DEBUG("[Accdet]adc cali_voltage1 = %d mv\n", cali_voltage);*/ 718 m_key = cur_key = key_check(cali_voltage); 719 } 720 mdelay(30); 721 #ifdef CONFIG_ACCDET_EINT_IRQ 722 if (((pmic_pwrap_read(ACCDET_IRQ_STS) & EINT_IRQ_STATUS_BIT) != EINT_IRQ_STATUS_BIT) || eint_accdet_sync_flag) { 723 #else /* ifdef CONFIG_ACCDET_EINT */ 724 if (((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) != IRQ_STATUS_BIT) || eint_accdet_sync_flag) { 725 #endif 726 send_key_event(cur_key, !current_status); 727 } else { 728 ACCDET_DEBUG("[Accdet]plug out side effect key press, do not report key = %d\n", cur_key); 729 cur_key = NO_KEY; 730 } 731 if (current_status) 732 cur_key = NO_KEY; 733 } 734 #endif 735 static void accdet_workqueue_func(void) 736 { 737 int ret; 738 739 ret = queue_work(accdet_workqueue, &accdet_work); 740 if (!ret) 741 ACCDET_DEBUG("[Accdet]accdet_work return:%d!\n", ret); 742 } 743 744 int accdet_irq_handler(void) 745 { 746 u64 cur_time = 0; 747 748 cur_time = accdet_get_current_time(); 749 750 #ifdef CONFIG_ACCDET_EINT_IRQ 751 ACCDET_DEBUG("[Accdet accdet_irq_handler]clear_accdet_eint_interrupt: ACCDET_IRQ_STS = 0x%x\n", 752 pmic_pwrap_read(ACCDET_IRQ_STS)); 753 if ((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) 754 && ((pmic_pwrap_read(ACCDET_IRQ_STS) & EINT_IRQ_STATUS_BIT) != EINT_IRQ_STATUS_BIT)) { 755 clear_accdet_interrupt(); 756 if (accdet_status == MIC_BIAS) { 757 /*accdet_auxadc_switch(1);*/ 758 pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width)); 759 pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_width)); 760 } 761 accdet_workqueue_func(); 762 while (((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) 763 && (accdet_timeout_ns(cur_time, ACCDET_TIME_OUT)))) 764 ; 765 } else if ((pmic_pwrap_read(ACCDET_IRQ_STS) & EINT_IRQ_STATUS_BIT) == EINT_IRQ_STATUS_BIT) { 766 if (cur_eint_state == EINT_PIN_PLUG_IN) { 767 if (accdet_eint_type == IRQ_TYPE_LEVEL_HIGH) 768 pmic_pwrap_write(ACCDET_IRQ_STS, pmic_pwrap_read(ACCDET_IRQ_STS) | EINT_IRQ_POL_HIGH); 769 else 770 pmic_pwrap_write(ACCDET_IRQ_STS, pmic_pwrap_read(ACCDET_IRQ_STS) & ~EINT_IRQ_POL_LOW); 771 } else { 772 if (accdet_eint_type == IRQ_TYPE_LEVEL_HIGH) 773 pmic_pwrap_write(ACCDET_IRQ_STS, pmic_pwrap_read(ACCDET_IRQ_STS) & ~EINT_IRQ_POL_LOW); 774 else 775 pmic_pwrap_write(ACCDET_IRQ_STS, pmic_pwrap_read(ACCDET_IRQ_STS) | EINT_IRQ_POL_HIGH); 776 } 777 clear_accdet_eint_interrupt(); 778 while (((pmic_pwrap_read(ACCDET_IRQ_STS) & EINT_IRQ_STATUS_BIT) 779 && (accdet_timeout_ns(cur_time, ACCDET_TIME_OUT)))) 780 ; 781 accdet_eint_func(accdet_irq, NULL); 782 } else { 783 ACCDET_DEBUG("ACCDET IRQ and EINT IRQ don't be triggerred!!\n"); 784 } 785 #else 786 if ((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT)) 787 clear_accdet_interrupt(); 788 if (accdet_status == MIC_BIAS) { 789 /*accdet_auxadc_switch(1);*/ 790 pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width)); 791 pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_width)); 792 } 793 accdet_workqueue_func(); 794 while (((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) 795 && (accdet_timeout_ns(cur_time, ACCDET_TIME_OUT)))) 796 ; 797 #endif 798 #ifdef ACCDET_NEGV_IRQ 799 cur_time = accdet_get_current_time(); 800 if ((pmic_pwrap_read(ACCDET_IRQ_STS) & NEGV_IRQ_STATUS_BIT) == NEGV_IRQ_STATUS_BIT) { 801 ACCDET_DEBUG("[ACCDET NEGV detect]plug in a error Headset\n\r"); 802 pmic_pwrap_write(ACCDET_IRQ_STS, (IRQ_NEGV_CLR_BIT)); 803 while (((pmic_pwrap_read(ACCDET_IRQ_STS) & NEGV_IRQ_STATUS_BIT) 804 && (accdet_timeout_ns(cur_time, ACCDET_TIME_OUT)))) 805 ; 806 pmic_pwrap_write(ACCDET_IRQ_STS, (pmic_pwrap_read(ACCDET_IRQ_STS) & (~IRQ_NEGV_CLR_BIT))); 807 } 808 #endif 809 810 return 1; 811 }

static irqreturn_t accdet_eint_func(int irq, void *data) 500 { 501 int ret = 0; 502 503 ACCDET_DEBUG("[Accdet]Enter accdet_eint_func !!!!!!\n"); 504 if (cur_eint_state == EINT_PIN_PLUG_IN) { 505 /* 506 To trigger EINT when the headset was plugged in 507 We set the polarity back as we initialed. 508 */ 509 #ifndef CONFIG_ACCDET_EINT_IRQ 510 if (accdet_eint_type == IRQ_TYPE_LEVEL_HIGH) 511 irq_set_irq_type(accdet_irq, IRQ_TYPE_LEVEL_HIGH); 512 else 513 irq_set_irq_type(accdet_irq, IRQ_TYPE_LEVEL_LOW); 514 #endif 515 #ifdef CONFIG_ACCDET_EINT_IRQ 516 pmic_pwrap_write(ACCDET_EINT_CTL, pmic_pwrap_read(ACCDET_EINT_CTL) & (~(7 << 4))); 517 /*debounce=256ms*/ 518 pmic_pwrap_write(ACCDET_EINT_CTL, pmic_pwrap_read(ACCDET_EINT_CTL) | EINT_IRQ_DE_IN); 519 pmic_pwrap_write(ACCDET_DEBOUNCE3, cust_headset_settings->debounce3); 520 521 #else 522 gpio_set_debounce(gpiopin, headsetdebounce); 523 #endif 524 525 /* update the eint status */ 526 cur_eint_state = EINT_PIN_PLUG_OUT; 527 } else { 528 /* 529 To trigger EINT when the headset was plugged out 530 We set the opposite polarity to what we initialed. 531 */ 532 #ifndef CONFIG_ACCDET_EINT_IRQ 533 if (accdet_eint_type == IRQ_TYPE_LEVEL_HIGH) 534 irq_set_irq_type(accdet_irq, IRQ_TYPE_LEVEL_LOW); 535 else 536 irq_set_irq_type(accdet_irq, IRQ_TYPE_LEVEL_HIGH); 537 #endif 538 539 #ifdef CONFIG_ACCDET_EINT_IRQ 540 pmic_pwrap_write(ACCDET_EINT_CTL, pmic_pwrap_read(ACCDET_EINT_CTL) & (~(7 << 4))); 541 /*debounce=16ms*/ 542 pmic_pwrap_write(ACCDET_EINT_CTL, pmic_pwrap_read(ACCDET_EINT_CTL) | EINT_IRQ_DE_OUT); 543 #else 544 gpio_set_debounce(gpiopin, accdet_dts_data.accdet_plugout_debounce * 1000); 545 #endif 546 /* update the eint status */ 547 cur_eint_state = EINT_PIN_PLUG_IN; 548 549 mod_timer(&micbias_timer, jiffies + MICBIAS_DISABLE_TIMER); 550 } 551 #ifndef CONFIG_ACCDET_EINT_IRQ 552 disable_irq_nosync(accdet_irq); 553 #endif 554 ACCDET_DEBUG("[Accdet]accdet_eint_func after cur_eint_state=%d\n", cur_eint_state); 555 556 ret = queue_work(accdet_eint_workqueue, &accdet_eint_work); 557 return IRQ_HANDLED; 558 } 559 #ifndef CONFIG_ACCDET_EINT_IRQ 560 static inline int accdet_setup_eint(struct platform_device *accdet_device) 561 { 562 int ret; 563 u32 ints[2] = { 0, 0 }; 564 u32 ints1[2] = { 0, 0 }; 565 struct device_node *node = NULL; 566 struct pinctrl_state *pins_default; 567 568 /*configure to GPIO function, external interrupt */ 569 ACCDET_INFO("[Accdet]accdet_setup_eint\n"); 570 accdet_pinctrl1 = devm_pinctrl_get(&accdet_device->dev); 571 if (IS_ERR(accdet_pinctrl1)) { 572 ret = PTR_ERR(accdet_pinctrl1); 573 dev_err(&accdet_device->dev, "fwq Cannot find accdet accdet_pinctrl1!\n"); 574 return ret; 575 } 576 577 pins_default = pinctrl_lookup_state(accdet_pinctrl1, "default"); 578 if (IS_ERR(pins_default)) { 579 ret = PTR_ERR(pins_default); 580 /*dev_err(&accdet_device->dev, "fwq Cannot find accdet pinctrl default!\n");*/ 581 } 582 583 pins_eint_int = pinctrl_lookup_state(accdet_pinctrl1, "state_eint_as_int"); 584 if (IS_ERR(pins_eint_int)) { 585 ret = PTR_ERR(pins_eint_int); 586 dev_err(&accdet_device->dev, "fwq Cannot find accdet pinctrl state_eint_accdet!\n"); 587 return ret; 588 } 589 pinctrl_select_state(accdet_pinctrl1, pins_eint_int); 590 591 /*node = of_find_matching_node(node, accdet_of_match);*/ 592 node = of_find_matching_node(node, accdet_of_match); 593 if (node) { 594 of_property_read_u32_array(node, "debounce", ints, ARRAY_SIZE(ints)); 595 of_property_read_u32_array(node, "interrupts", ints1, ARRAY_SIZE(ints1)); 596 gpiopin = ints[0]; 597 headsetdebounce = ints[1]; 598 accdet_eint_type = ints1[1]; 599 gpio_set_debounce(gpiopin, headsetdebounce); 600 accdet_irq = irq_of_parse_and_map(node, 0); 601 ret = request_irq(accdet_irq, accdet_eint_func, IRQF_TRIGGER_NONE, "accdet-eint", NULL); 602 if (ret != 0) { 603 ACCDET_ERROR("[Accdet]EINT IRQ LINE NOT AVAILABLE\n"); 604 } else { 605 ACCDET_ERROR("[Accdet]accdet set EINT finished, accdet_irq=%d, headsetdebounce=%d\n", 606 accdet_irq, headsetdebounce); 607 } 608 } else { 609 ACCDET_ERROR("[Accdet]%s can't find compatible node\n", __func__); 610 } 611 return 0; 612 }

大家在看

recommend-type

libssl-1_1-x64.zip

如题,放到软件安装目录bin文件夹下即可。 在anaconda更新包时遇到了这个问题,找了了X64位可以用的,之后成功更新
recommend-type

IEC 61400-25风力发电标准-英文版

IEC61400风电国际标准,分为5个部分,内容包括总则、模型、通信协议、风机构成与控制等。
recommend-type

基于GFFT的LFSR序列生成多项式估计方法

针对线性反馈移位寄存器(LFSR)序列生成多项式的估计问题,提出了一种基于LFSR序列有限域傅里叶变换(GFFT)的估计方法。首先证明了LFSR序列GFFT的非零点与LFSR序列生成多项式的零点之间的对应关系,进而利用该性质实现 LFSR 序列生成多项式的快速估计,并给出了算法在误码环境下的改进方法。仿真实验验证了算法的有效性,并对算法的计算复杂度进行了理论分析。和已有算法相比较,本文提出的算法具有更高的计算效率。
recommend-type

IFIX 4.5 MB1 驱动

 MB1:有两个版本,6.x 和 7.x 版,通过串行口连接所有支持 Modbus 串行通讯协议的设备。主要有 Modicon PLC 和其它控制仪表如:Honeywell UDC,UMC,Moore 的控制仪表等。支持 Mobus RTU 和 ASCII 两种通讯协议。当使用其与其它兼容设备通讯时,注意数据类型会与 Modicon 的数据类型有所差别。7.x 版本支持电话拨号连接和无线电连接。
recommend-type

buliding\horse\pig\rabbit\table\wolf等各种点云数据集pcd文件

这里面包含了很多数据集,有buliding\horse\pig\rabbit\table\wolf等点云pcd文件,感兴趣的可以下载。

最新推荐

recommend-type

【Java使用配置文件连接mysql】

mysql使用druid配置连接mysql
recommend-type

Java课程设计画随机圆(1).pdf

Java课程设计画随机圆(1).pdf
recommend-type

python 一个用py3写的数据库自动备份管理系统.zip

python 一个用py3写的数据库自动备份管理系统
recommend-type

电子商务的应用论文(1).docx

电子商务的应用论文(1).docx
recommend-type

“计算机软件著作权”登记【可编辑范本】(1).doc

“计算机软件著作权”登记【可编辑范本】(1).doc
recommend-type

获取本机IP地址的程序源码分析

从给定文件信息中我们可以提取出的关键知识点是“取本机IP”的实现方法以及与之相关的编程技术和源代码。在当今的信息技术领域中,获取本机IP地址是一项基本技能,广泛应用于网络通信类的软件开发中,下面将详细介绍这一知识点。 首先,获取本机IP地址通常需要依赖于编程语言和操作系统的API。不同的操作系统提供了不同的方法来获取IP地址。在Windows操作系统中,可以通过调用Windows API中的GetAdaptersInfo()或GetAdaptersAddresses()函数来获取网络适配器信息,进而得到IP地址。在类Unix操作系统中,可以通过读取/proc/net或是使用系统命令ifconfig、ip等来获取网络接口信息。 在程序设计过程中,获取本机IP地址的源程序通常会用到网络编程的知识,比如套接字编程(Socket Programming)。网络编程允许程序之间进行通信,套接字则是在网络通信过程中用于发送和接收数据的接口。在许多高级语言中,如Python、Java、C#等,都提供了内置的网络库和类来简化网络编程的工作。 在网络通信类中,IP地址是区分不同网络节点的重要标识,它是由IP协议规定的,用于在网络中唯一标识一个网络接口。IP地址可以是IPv4,也可以是较新的IPv6。IPv4地址由32位二进制数表示,通常分为四部分,每部分由8位构成,并以点分隔,如192.168.1.1。IPv6地址则由128位二进制数表示,其表示方法与IPv4有所不同,以冒号分隔的8组16进制数表示,如2001:0db8:85a3:0000:0000:8a2e:0370:7334。 当编写源代码以获取本机IP地址时,通常涉及到以下几个步骤: 1. 选择合适的编程语言和相关库。 2. 根据目标操作系统的API或系统命令获取网络接口信息。 3. 分析网络接口信息,提取出IP地址。 4. 将提取的IP地址转换成适合程序内部使用的格式。 5. 在程序中提供相应功能,如显示IP地址或用于网络通信。 例如,在Python中,可以使用内置的socket库来获取本机IP地址。一个简单的示例代码如下: ```python import socket # 获取主机名 hostname = socket.gethostname() # 获取本机IP local_ip = socket.gethostbyname(hostname) print("本机IP地址是:", local_ip) ``` 在实际应用中,获取本机IP地址通常是为了实现网络通信功能,例如建立客户端与服务器的连接,或者是在开发涉及到IP地址的其他功能时使用。 关于文件名称“getIP”,这是一个自解释的文件名,明显表示该文件或程序的作用是获取本机的IP地址。从标签“控件 源码 网络通信类 资源”中我们可以看出,这个文件很可能是一个可以嵌入其他软件中的代码片段,用以实现网络通信功能的一部分,具有较高的灵活性和重用性。 综上所述,获取本机IP地址是一个涉及到操作系统API、网络编程以及特定编程语言知识的技能。它不仅需要对编程语言提供的库函数有深入的理解,还要对操作系统的网络配置和IP协议有足够的认识。通过阅读和分析相关的源代码,如“getIP”,可以加深对网络编程实现细节的理解,并能够在实际开发中快速地应用这一技术。
recommend-type

【权威指南】:Win11笔记本上RTX4080驱动的安装与调试秘籍

# 1. Win11笔记本与RTX4080显卡介绍 随着技术的不断发展,笔记本电脑已不再是仅仅满足办公需求的移动设备,而是逐渐成为可以胜任复杂图形处理和游戏任务的强大工具。微软推出的Windows 11操作系统,以其全新的用户界面和改进的系统性能,为用户提供了更为流畅的操作体验。而在硬件方面,NVIDIA的RTX 4080显卡以其卓越的图形处理能力和AI支持,为笔记本电脑带来了前所未有的性能提升。本章节将带您初步了解Windows 11笔记本与NVIDIA RTX 4080显卡的基础信息,为进一步深入探讨它们的优化和调试技巧奠定基础。 ## 1.1 Win11笔记本的优势 Windows
recommend-type

windows环境举例

<think>好的,用户现在想在Windows环境下创建C函数库,需要具体的方法和示例代码。我需要结合之前的回答和用户提供的引用内容来给出合适的指导。 首先回顾之前的回答,用户已经了解了在Linux下创建静态库和动态库的方法,现在需要切换到Windows环境。根据引用[2],Windows下的C标准库和动态链接库的处理与Linux不同,比如使用dlfcn.h在Linux,而Windows可能需要其他方式。另外,引用[1]提到了在Windows下配置gcc环境(MinGW-w64),这可能是一个关键点,因为用户可能需要使用MinGW来编译库。 用户提供的引用[3]提到了使用MSVC编译器,这
recommend-type

QQ自动发送/回复系统源代码开放

根据提供的文件信息,我们可以了解到以下几点关键的知识点: ### 标题:“qqhelp” 1. **项目类型**: 标题“qqhelp”暗示这是一个与QQ相关的帮助工具或项目。QQ是中国流行的即时通讯软件,因此这个标题表明项目可能提供了对QQ客户端功能的辅助或扩展。 2. **用途**: “help”表明此项目的主要目的是提供帮助或解决问题。由于它提到了QQ,并且涉及“autosend/reply”功能,我们可以推测该项目可能用于自动化发送消息回复,或提供某种形式的自动回复机制。 ### 描述:“I put it to my web, but nobody sendmessage to got the source, now I public it. it supply qq,ticq autosend/reply ,full sourcecode use it as you like” 1. **发布情况**: 描述提到该项目原先被放置在某人的网站上,并且没有收到请求源代码的消息。这可能意味着项目不够知名或者需求不高。现在作者决定公开发布,这可能是因为希望项目能够被更多人了解和使用,或是出于开源共享的精神。 2. **功能特性**: 提到的“autosend/reply”表明该项目能够实现自动发送和回复消息。这种功能对于需要进行批量或定时消息沟通的应用场景非常有用,例如客户服务、自动化的营销通知等。 3. **代码可用性**: 作者指出提供了“full sourcecode”,意味着源代码完全开放,用户可以自由使用,无论是查看、学习还是修改,用户都有很大的灵活性。这对于希望学习编程或者有特定需求的开发者来说是一个很大的优势。 ### 标签:“综合系统类” 1. **项目分类**: 标签“综合系统类”表明这个项目可能是一个多功能的集成系统,它可能不仅限于QQ相关的功能,还可能包含了其他类型的综合服务或特性。 2. **技术范畴**: 这个标签可能表明该项目的技术实现比较全面,可能涉及到了多个技术栈或者系统集成的知识点,例如消息处理、网络编程、自动化处理等。 ### 压缩包子文件的文件名称列表: 1. **Unit1.dfm**: 这是一个Delphi或Object Pascal语言的窗体定义文件,用于定义应用程序中的用户界面布局。DFM文件通常用于存储组件的属性和位置信息,使得开发者可以快速地进行用户界面的设计和调整。 2. **qqhelp.dpr**: DPR是Delphi项目文件的扩展名,包含了Delphi项目的核心设置,如程序入口、使用的单元(Units)等。这个文件是编译和构建Delphi项目的起点,它能够帮助开发者了解项目的组织结构和编译指令。 3. **Unit1.pas**: PAS是Delphi或Object Pascal语言的源代码文件。这个文件可能包含了与QQ帮助工具相关的核心逻辑代码,例如处理自动发送和回复消息的算法等。 4. **readme.txt**: 这是一个常见的文本文件,包含项目的基本说明和使用指导,帮助用户了解如何获取、安装、运行和定制该项目。README文件通常是用户与项目首次交互时首先阅读的文件,因此它对于一个开源项目的用户友好度有着重要影响。 通过以上分析,我们可以看出“qqhelp”项目是一个针对QQ通讯工具的自动化消息发送与回复的辅助工具。项目包含完整的源代码,用户可以根据自己的需要进行查看、修改和使用。它可能包含Delphi语言编写的窗体界面和后端逻辑代码,具有一定的综合系统特性。项目作者出于某种原因将其开源,希望能够得到更广泛的使用和反馈。
recommend-type

【7步打造Win11深度学习利器】:Tensorflow-GPU与RTX4080终极优化指南

# 1. 深度学习与Windows 11的融合 在人工智能时代,深度学习已渗透到生活的方方面面,而Windows 11作为最新一代的操作系统,为深度学习提供了一个高效的工作平台。本章节将探讨深度学习技术如何与Windows 11系统融合,以及这一