MTK平臺pwm模式閃光燈驅動配置

染色體集團備用程式猿發表於2020-12-31
  1. 供電引腳配置:
    除flash torch兩個供電引腳按照常規配置gpio模式外,需另外將ENM pin配置成pwm模式。在dtsi中新增如下程式碼:
flash_light_pwm_pin: flash_light_pwm_pin {
    pins_cmd_dat {
        pinmux = <PINMUX_GPIOxxx__FUNC_PWMx>;
        slew-rate = <1>;
        output-high;
    };
};
  1. 驅動檔案:
    包含pwm標頭檔案:
    #include <mt-plat/mtk_pwm.h>

  2. 閃光燈flash/torch模式下的電流控制:
    (1) flash mode:
    No matter the status of ENM, only when ENF = “1”, Flash mode is in active and the flashing current is equal to IRF * D, D is the duty cycle of PWM signal at ENM pin, the frequency of PWM is largerthan 15KHz
    對應程式碼:

flashlight_pinctrl_set(FLASHLIGHT_PINCTRL_PIN_FLASH, 0);
flashlight_pinctrl_set(FLASHLIGHT_PINCTRL_PIN_PWM_EN, 1);
mt_flashlight_led_set_pwm(0, tempPWM);    //設定pwm佔空比,以實現控制flash電流大小
udelay(500);
flashlight_pinctrl_set(FLASHLIGHT_PINCTRL_PIN_FLASH, 1);

(2) torch mode:
When ENF = “0” and the timer of ENM = “1” is not less than 5ms, Movie/Torch mode will be in active. The LED current should be equal to IRM * D, D is the duty cycle of PWM signal at ENM pin. This PWM signal is sent to ENM pin after the first pulse which “1” level time is more than 5ms. When ENF = “0” and the ENM = “0” is not less than 5ms, the chip will enter into shutdown mode.
對應程式碼:

flashlight_pinctrl_set(FLASHLIGHT_PINCTRL_PIN_FLASH, 0);
flashlight_pinctrl_set(FLASHLIGHT_PINCTRL_PIN_PWM_GPIO, 1);
mdelay(6);
flashlight_pinctrl_set(FLASHLIGHT_PINCTRL_PIN_PWM_EN, 1);
mt_flashlight_led_set_pwm(0, 40);

在flash_tuning_custom.cpp中將torch duty設定為24以上的數值(示例中flash共設定24個duty),用於與flash模式做區分。驅動中檢測到torch的duty時直接呼叫torch的使能邏輯。

  1. mt_flashlight_led_set_pwm的實現:
int mt_flashlight_led_set_pwm(int pwm_num, u32 level)
{
    struct pwm_spec_config pwm_setting;
    memset(&pwm_setting, 0, sizeof(struct pwm_spec_config));
    /*pwm_no is by IC HW design, this value is different by different IC(MTK doc: PWM UserGuide) ——從dws裡面檢視?*/
    pwm_setting.pwm_no = pwm_num;
    /*OLD or FIFO*/
    pwm_setting.mode = PWM_MODE_OLD;
    /*use channel in pmic, or not, default is FALSE*/
    pwm_setting.pmic_pad = 0;
    /*分頻係數*/
    pwm_setting.clk_div = CLK_DIV32;
    /*src clk is by IC HW design, this value is different by different IC(MTK doc: PWM UserGuide) ——未找到查詢對應src的方法*/
    pwm_setting.clk_src = PWM_CLK_OLD_MODE_BLOCK;
    /*FALSE: after the PWM wave send finished, the voltage level of this GPIO is low
       TRUE: after the PWM wave send finished, the voltage level of this GPIO is high*/
    pwm_setting.PWM_MODE_OLD_REGS.IDLE_VALUE = 0;   
    /* FALSE: there is no interval time between 2 complete waveform
        TRUE: interval time between 2 complete waveform, the interval time = DATA_WIDTH*/
    pwm_setting.PWM_MODE_OLD_REGS.GUARD_VALUE = 0;
    /* Guard的長度,old mode下是無效值 */
    pwm_setting.PWM_MODE_OLD_REGS.GDURATION = 0;
    /* waveform numbers. WAVE_NUM= 0 means PWM will send output always, until disable pwm, the waveform will stoped */
    pwm_setting.PWM_MODE_OLD_REGS.WAVE_NUM = 0;
    /* the time of onecomplete waveform, 此處含義是一個完整波形包含100個clk */
    pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH = 100;
    /* the time of high voltage level in one complete waveform, it means duty cycle, 此處含義是一個完整波形中高電平的時長為level個clk */
    pwm_setting.PWM_MODE_OLD_REGS.THRESH = level;
    pwm_set_spec_config(&pwm_setting);
    return 0;
}
  1. 定義pwm使用的level tab:
    static int g_duty_array[FLASHLIGHT_LEVEL_NUM] = {8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100};
    level tab用於根據不同的duty設定不同等級的THRESH, 從而達到實現控制亮度的目的。詳細程式碼實現:
    xxx_enable中,flash模式時:
{
……
    if (g_flash_duty < FLASHLIGHT_LEVEL_NUM)
        tempPWM = g_duty_array[g_flash_duty];
    else
        tempPWM = g_duty_array[LED3201_LEVEL_NUM - 1];
    ……
    mt_flashlight_led_set_pwm(3, tempPWM);
    ……
}

相關文章