From c5592682d9bc9f73aa93555e0422ecc1eed02c95 Mon Sep 17 00:00:00 2001 From: zyw Date: Fri, 3 Dec 2010 23:28:10 +0800 Subject: [PATCH] update for rk29 fb driver --- arch/arm/mach-rk29/board-rk29sdk.c | 163 +++---------------- drivers/video/display/screen/Kconfig | 2 + drivers/video/display/screen/Makefile | 1 + drivers/video/display/screen/lcd_hsd100pxn.c | 71 ++++++++ drivers/video/display/screen/screen.h | 1 + drivers/video/rk29_fb.c | 145 +++++++++-------- 6 files changed, 180 insertions(+), 203 deletions(-) create mode 100644 drivers/video/display/screen/lcd_hsd100pxn.c diff --git a/arch/arm/mach-rk29/board-rk29sdk.c b/arch/arm/mach-rk29/board-rk29sdk.c index db401bee51c5..608df99963cf 100755 --- a/arch/arm/mach-rk29/board-rk29sdk.c +++ b/arch/arm/mach-rk29/board-rk29sdk.c @@ -111,155 +111,48 @@ static struct rk29_gpio_bank rk29_gpiobankinit[] = { * author: zyw@rock-chips.com *****************************************************************************************/ //#ifdef CONFIG_LCD_TD043MGEA1 -#define LCD_TXD_PIN RK29_PIN0_PA6 // ÂÒÌî,µÃÐÞ¸Ä -#define LCD_CLK_PIN RK29_PIN0_PA7 // ÂÒÌî,µÃÐÞ¸Ä -#define LCD_CS_PIN RK29_PIN0_PB6 // ÂÒÌî,µÃÐÞ¸Ä -#define LCD_TXD_MUX_NAME GPIOE_U1IR_I2C1_NAME -#define LCD_CLK_MUX_NAME NULL -#define LCD_CS_MUX_NAME GPIOH6_IQ_SEL_NAME -#define LCD_TXD_MUX_MODE 0 -#define LCD_CLK_MUX_MODE 0 -#define LCD_CS_MUX_MODE 0 +#define LCD_TXD_PIN INVALID_GPIO +#define LCD_CLK_PIN INVALID_GPIO +#define LCD_CS_PIN INVALID_GPIO +/***************************************************************************************** +* frame buffe devices +* author: zyw@rock-chips.com +*****************************************************************************************/ +#define FB_ID 0 +#define FB_DISPLAY_ON_PIN RK29_PIN6_PD0 +#define FB_LCD_STANDBY_PIN RK29_PIN6_PD1 +#define FB_MCU_FMK_PIN INVALID_GPIO + +#define FB_DISPLAY_ON_VALUE GPIO_HIGH +#define FB_LCD_STANDBY_VALUE GPIO_HIGH + //#endif static int rk29_lcd_io_init(void) { int ret = 0; - -#if 0 - rk29_mux_api_set(LCD_CS_MUX_NAME, LCD_CS_MUX_MODE); - if (LCD_CS_PIN != INVALID_GPIO) { - ret = gpio_request(LCD_CS_PIN, NULL); - if(ret != 0) - { - goto err1; - printk(">>>>>> lcd cs gpio_request err \n "); - } - } - - rk29_mux_api_set(LCD_CLK_MUX_NAME, LCD_CLK_MUX_MODE); - if (LCD_CLK_PIN != INVALID_GPIO) { - ret = gpio_request(LCD_CLK_PIN, NULL); - if(ret != 0) - { - goto err2; - printk(">>>>>> lcd clk gpio_request err \n "); - } - } - - rk29_mux_api_set(LCD_TXD_MUX_NAME, LCD_TXD_MUX_MODE); - if (LCD_TXD_PIN != INVALID_GPIO) { - ret = gpio_request(LCD_TXD_PIN, NULL); - if(ret != 0) - { - goto err3; - printk(">>>>>> lcd txd gpio_request err \n "); - } - } - - return 0; - -err3: - if (LCD_CLK_PIN != INVALID_GPIO) { - gpio_free(LCD_CLK_PIN); - } -err2: - if (LCD_CS_PIN != INVALID_GPIO) { - gpio_free(LCD_CS_PIN); - } -err1: -#endif return ret; } static int rk29_lcd_io_deinit(void) { int ret = 0; -#if 0 - gpio_direction_output(LCD_CLK_PIN, 0); - gpio_set_value(LCD_CLK_PIN, GPIO_HIGH); - gpio_direction_output(LCD_TXD_PIN, 0); - gpio_set_value(LCD_TXD_PIN, GPIO_HIGH); - - gpio_free(LCD_CS_PIN); - rk29_mux_api_mode_resume(LCD_CS_MUX_NAME); - gpio_free(LCD_CLK_PIN); - gpio_free(LCD_TXD_PIN); - rk29_mux_api_mode_resume(LCD_TXD_MUX_NAME); - rk29_mux_api_mode_resume(LCD_CLK_MUX_NAME); -#endif return ret; } struct rk29lcd_info rk29_lcd_info = { - //.txd_pin = LCD_TXD_PIN, - //.clk_pin = LCD_CLK_PIN, - //.cs_pin = LCD_CS_PIN, + .txd_pin = LCD_TXD_PIN, + .clk_pin = LCD_CLK_PIN, + .cs_pin = LCD_CS_PIN, .io_init = rk29_lcd_io_init, .io_deinit = rk29_lcd_io_deinit, }; -/***************************************************************************************** - * frame buffe devices - * author: zyw@rock-chips.com - *****************************************************************************************/ - -#define FB_ID 0 -#define FB_DISPLAY_ON_PIN RK29_PIN0_PB1 // ÂÒÌî,µÃÐÞ¸Ä -#define FB_LCD_STANDBY_PIN INVALID_GPIO -#define FB_MCU_FMK_PIN INVALID_GPIO - -#if 0 -#define FB_DISPLAY_ON_VALUE GPIO_LOW -#define FB_LCD_STANDBY_VALUE 0 - -#define FB_DISPLAY_ON_MUX_NAME GPIOB1_SMCS1_MMC0PCA_NAME -#define FB_DISPLAY_ON_MUX_MODE IOMUXA_GPIO0_B1 - -#define FB_LCD_STANDBY_MUX_NAME NULL -#define FB_LCD_STANDBY_MUX_MODE 1 - -#define FB_MCU_FMK_PIN_MUX_NAME NULL -#define FB_MCU_FMK_MUX_MODE 0 - -#define FB_DATA0_16_MUX_NAME GPIOC_LCDC16BIT_SEL_NAME -#define FB_DATA0_16_MUX_MODE 1 - -#define FB_DATA17_18_MUX_NAME GPIOC_LCDC18BIT_SEL_NAME -#define FB_DATA17_18_MUX_MODE 1 - -#define FB_DATA19_24_MUX_NAME GPIOC_LCDC24BIT_SEL_NAME -#define FB_DATA19_24_MUX_MODE 1 - -#define FB_DEN_MUX_NAME CXGPIO_LCDDEN_SEL_NAME -#define FB_DEN_MUX_MODE 1 - -#define FB_VSYNC_MUX_NAME CXGPIO_LCDVSYNC_SEL_NAME -#define FB_VSYNC_MUX_MODE 1 - -#define FB_MCU_FMK_MUX_NAME NULL -#define FB_MCU_FMK_MUX_MODE 0 -#endif static int rk29_fb_io_init(struct rk29_fb_setting_info *fb_setting) { int ret = 0; -#if 0 - if(fb_setting->data_num <=16) - rk29_mux_api_set(FB_DATA0_16_MUX_NAME, FB_DATA0_16_MUX_MODE); - if(fb_setting->data_num >16 && fb_setting->data_num<=18) - rk29_mux_api_set(FB_DATA17_18_MUX_NAME, FB_DATA17_18_MUX_MODE); - if(fb_setting->data_num >18) - rk29_mux_api_set(FB_DATA19_24_MUX_NAME, FB_DATA19_24_MUX_MODE); - - if(fb_setting->vsync_en) - rk29_mux_api_set(FB_VSYNC_MUX_NAME, FB_VSYNC_MUX_MODE); - - if(fb_setting->den_en) - rk29_mux_api_set(FB_DEN_MUX_NAME, FB_DEN_MUX_MODE); - - if(fb_setting->mcu_fmk_en && FB_MCU_FMK_MUX_NAME && (FB_MCU_FMK_PIN != INVALID_GPIO)) + if(fb_setting->mcu_fmk_en && (FB_MCU_FMK_PIN != INVALID_GPIO)) { - rk29_mux_api_set(FB_MCU_FMK_MUX_NAME, FB_MCU_FMK_MUX_MODE); ret = gpio_request(FB_MCU_FMK_PIN, NULL); if(ret != 0) { @@ -268,10 +161,8 @@ static int rk29_fb_io_init(struct rk29_fb_setting_info *fb_setting) } gpio_direction_input(FB_MCU_FMK_PIN); } - - if(fb_setting->disp_on_en && FB_DISPLAY_ON_MUX_NAME && (FB_DISPLAY_ON_PIN != INVALID_GPIO)) + if(fb_setting->disp_on_en && (FB_DISPLAY_ON_PIN != INVALID_GPIO)) { - rk29_mux_api_set(FB_DISPLAY_ON_MUX_NAME, FB_DISPLAY_ON_MUX_MODE); ret = gpio_request(FB_DISPLAY_ON_PIN, NULL); if(ret != 0) { @@ -280,9 +171,8 @@ static int rk29_fb_io_init(struct rk29_fb_setting_info *fb_setting) } } - if(fb_setting->disp_on_en && FB_LCD_STANDBY_MUX_NAME && (FB_LCD_STANDBY_PIN != INVALID_GPIO)) + if(fb_setting->disp_on_en && (FB_LCD_STANDBY_PIN != INVALID_GPIO)) { - rk29_mux_api_set(FB_LCD_STANDBY_MUX_NAME, FB_LCD_STANDBY_MUX_MODE); ret = gpio_request(FB_LCD_STANDBY_PIN, NULL); if(ret != 0) { @@ -290,17 +180,16 @@ static int rk29_fb_io_init(struct rk29_fb_setting_info *fb_setting) printk(">>>>>> FB_LCD_STANDBY_PIN gpio_request err \n "); } } -#endif return ret; } struct rk29fb_info rk29_fb_info = { .fb_id = FB_ID, - //.disp_on_pin = FB_DISPLAY_ON_PIN, - //.disp_on_value = FB_DISPLAY_ON_VALUE, - //.standby_pin = FB_LCD_STANDBY_PIN, - //.standby_value = FB_LCD_STANDBY_VALUE, - //.mcu_fmk_pin = FB_MCU_FMK_PIN, + .disp_on_pin = FB_DISPLAY_ON_PIN, + .disp_on_value = FB_DISPLAY_ON_VALUE, + .standby_pin = FB_LCD_STANDBY_PIN, + .standby_value = FB_LCD_STANDBY_VALUE, + .mcu_fmk_pin = FB_MCU_FMK_PIN, .lcd_info = &rk29_lcd_info, .io_init = rk29_fb_io_init, }; diff --git a/drivers/video/display/screen/Kconfig b/drivers/video/display/screen/Kconfig index dcf0b3886eae..90e4594fde65 100755 --- a/drivers/video/display/screen/Kconfig +++ b/drivers/video/display/screen/Kconfig @@ -13,6 +13,8 @@ config LCD_HL070VM4AU bool "RGB_HL070VM4AU" config LCD_HSD070IDW1 bool "RGB Hannstar800x480" +config LCD_HSD100PXN + bool "RGB Hannstar HSD100PXN(1024X768)" config LCD_A060SE02 bool "MCU A060SE02" config LCD_S1D13521 diff --git a/drivers/video/display/screen/Makefile b/drivers/video/display/screen/Makefile index 3cf0cc34938e..4944ea197359 100755 --- a/drivers/video/display/screen/Makefile +++ b/drivers/video/display/screen/Makefile @@ -17,5 +17,6 @@ obj-$(CONFIG_LCD_NT35580) += lcd_nt35580.o obj-$(CONFIG_HDMI_ANX7150) += hdmi_anx7150.o obj-$(CONFIG_LCD_HX8357) += lcd_hx8357.o +obj-$(CONFIG_LCD_HSD100PXN) += lcd_hsd100pxn.o diff --git a/drivers/video/display/screen/lcd_hsd100pxn.c b/drivers/video/display/screen/lcd_hsd100pxn.c new file mode 100644 index 000000000000..5bd792e9f846 --- /dev/null +++ b/drivers/video/display/screen/lcd_hsd100pxn.c @@ -0,0 +1,71 @@ +#include +#include +#include "../../rk29_fb.h" +#include +#include +#include +#include "screen.h" + + +/* Base */ +#define OUT_TYPE SCREEN_RGB +#define OUT_FACE OUT_P888 +#define OUT_CLK 65 +#define LCDC_ACLK 150 //29 lcdc axi DMA ƵÂÊ + +/* Timing */ +#define H_PW 10 +#define H_BP 100 +#define H_VD 1024 +#define H_FP 210 + +#define V_PW 10 +#define V_BP 10 +#define V_VD 768 +#define V_FP 18 + +/* Other */ +#define DCLK_POL 0 +#define SWAP_RB 0 + + +void set_lcd_info(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info ) +{ + /* screen type & face */ + screen->type = OUT_TYPE; + screen->face = OUT_FACE; + + /* Screen size */ + screen->x_res = H_VD; + screen->y_res = V_VD; + + /* Timing */ + screen->pixclock = OUT_CLK; + screen->left_margin = H_BP; + screen->right_margin = H_FP; + screen->hsync_len = H_PW; + screen->upper_margin = V_BP; + screen->lower_margin = V_FP; + screen->vsync_len = V_PW; + + /* Pin polarity */ + screen->pin_hsync = 0; + screen->pin_vsync = 0; + screen->pin_den = 0; + screen->pin_dclk = DCLK_POL; + screen->lcdc_aclk = LCDC_ACLK; + + /* Swap rule */ + screen->swap_rb = SWAP_RB; + screen->swap_rg = 0; + screen->swap_gb = 0; + screen->swap_delta = 0; + screen->swap_dumy = 0; + + /* Operation function*/ + screen->init = NULL; + screen->standby = NULL; +} + + + diff --git a/drivers/video/display/screen/screen.h b/drivers/video/display/screen/screen.h index b56e40841cd2..6d15bb498730 100755 --- a/drivers/video/display/screen/screen.h +++ b/drivers/video/display/screen/screen.h @@ -61,6 +61,7 @@ struct rk29fb_screen { u8 pin_vsync; u8 pin_den; u8 pin_dclk; + u8 lcdc_aclk; u8 pin_dispon; /* Swap rule */ diff --git a/drivers/video/rk29_fb.c b/drivers/video/rk29_fb.c index 9cca7b7753e3..5db8bf29bcef 100755 --- a/drivers/video/rk29_fb.c +++ b/drivers/video/rk29_fb.c @@ -53,9 +53,6 @@ #include "./display/screen/screen.h" - -#define CURSOR_BUF_SIZE 256 //rk29 cursor need 256B buf - #if 1 #define fbprintk(msg...) printk(msg); #else @@ -125,7 +122,8 @@ struct rk29fb_inf { struct clk *dclk; //lcdc dclk struct clk *dclk_parent; //lcdc dclk divider frequency source struct clk *dclk_divider; //lcdc demodulator divider frequency - struct clk *clk_share_mem; //lcdc share memory frequency + struct clk *aclk; //lcdc share memory frequency + struct clk *aclk_parent; //lcdc aclk divider frequency source unsigned long dclk_rate; /* lcdc reg base address and backup reg */ @@ -208,7 +206,7 @@ void set_lcd_pin(struct platform_device *pdev, int enable) // set display_on if(display_on != INVALID_GPIO) - { + { gpio_direction_output(display_on, 0); gpio_set_value(display_on, enable ? display_on_pol : !display_on_pol); } @@ -217,6 +215,20 @@ void set_lcd_pin(struct platform_device *pdev, int enable) gpio_direction_output(lcd_standby, 0); gpio_set_value(lcd_standby, enable ? lcd_standby_pol : !lcd_standby_pol); } + + /********* open backlight just for test ***************/ + rk29_mux_api_set(GPIO1B5_PWM0_NAME, 0); + if(0 != gpio_request(RK29_PIN1_PB5, NULL)) + { + gpio_free(RK29_PIN1_PB5); + printk(">>>>>> RK29_PIN1_PB5 gpio_request err \n "); + } + gpio_direction_output(RK29_PIN1_PB5, GPIO_HIGH); + gpio_set_value(RK29_PIN1_PB5, GPIO_HIGH); + gpio_direction_output(RK29_PIN1_PB5, GPIO_HIGH); + printk("P1B5 High \n"); +/************************/ + } int mcu_do_refresh(struct rk29fb_inf *inf) @@ -424,6 +436,9 @@ void load_screen(struct fb_info *info, bool initscreen) u16 x_res = screen->x_res, y_res = screen->y_res; u32 clk_rate = 0; u32 dclk_rate = 0; + u32 aclk_rate = 150000000; + + if(!g_pdev) return -1; fbprintk(">>>>>> %s : %s \n", __FILE__, __FUNCTION__); @@ -487,34 +502,85 @@ void load_screen(struct fb_info *info, bool initscreen) // let above to take effect LcdWrReg(inf, REG_CFG_DONE, 0x01); + inf->clk = clk_get(&g_pdev->dev, "hclk_lcdc"); + if (!inf->clk || IS_ERR(inf->clk)) + { + printk(KERN_ERR "failed to get lcdc_hclk source\n"); + return ; + } + + inf->dclk = clk_get(&g_pdev->dev, "dclk_lcdc"); + if (!inf->dclk || IS_ERR(inf->dclk)) + { + printk(KERN_ERR "failed to get lcd dclock source\n"); + return ; + } + inf->dclk_divider= clk_get(&g_pdev->dev, "dclk_lcdc_div"); + if (!inf->dclk_divider || IS_ERR(inf->dclk_divider)) + { + printk(KERN_ERR "failed to get lcd clock lcdc_divider source \n"); + return ; + } + + if(inf->cur_screen == &inf->lcd_info) { + inf->dclk_parent = clk_get(&g_pdev->dev, "periph_pll"); + } else { + inf->dclk_parent = clk_get(&g_pdev->dev, "codec_pll"); + } + + if (!inf->dclk_parent || IS_ERR(inf->dclk_parent)) + { + printk(KERN_ERR "failed to get lcd dclock parent source\n"); + return ; + } + + inf->aclk = clk_get(&g_pdev->dev, "aclk_lcdc"); + if (!inf->aclk || IS_ERR(inf->aclk)) + { + printk(KERN_ERR "failed to get lcd clock clk_share_mem source \n"); + return ; + } + inf->aclk_parent = clk_get(&g_pdev->dev, "periph_pll"); + if (!inf->dclk_parent || IS_ERR(inf->dclk_parent)) + { + printk(KERN_ERR "failed to get lcd dclock parent source\n"); + return ; + } + // set lcdc clk if(SCREEN_MCU==screen->type) screen->pixclock = 150; //mcu fix to 150 MHz clk_set_parent(inf->dclk_divider, inf->dclk_parent); clk_set_parent(inf->dclk, inf->dclk_divider); + clk_set_parent(inf->aclk, inf->aclk_parent); dclk_rate = screen->pixclock * 1000000; fbprintk(">>>>>> set lcdc dclk need %d HZ, clk_parent = %d hz \n ", screen->pixclock, clk_rate); -#if 0 ret = clk_set_rate(inf->dclk_divider, dclk_rate); - if(ret) { printk(KERN_ERR ">>>>>> set lcdc dclk_divider faild \n "); } + if(screen->lcdc_aclk){ + aclk_rate = screen->lcdc_aclk * 1000000; + } + ret = clk_set_rate(inf->aclk, aclk_rate); + if(ret){ + printk(KERN_ERR ">>>>>> set lcdc dclk_divider faild \n "); + } clk_enable(inf->dclk); clk_enable(inf->clk); - clk_enable(inf->clk_share_mem); -#endif + clk_enable(inf->aclk); // init screen panel if(screen->init && initscreen) { screen->init(); } + } #ifdef CONFIG_CPU_FREQ /* @@ -1246,7 +1312,6 @@ static int win1fb_set_par(struct fb_info *info) struct fb_fix_screeninfo *fix = &info->fix; struct rk29fb_screen *screen = inf->cur_screen; - u8 format = 0; dma_addr_t map_dma; u32 offset=0, addr=0, map_size=0, smem_len=0; @@ -1283,10 +1348,9 @@ static int win1fb_set_par(struct fb_info *info) break; } - smem_len = fix->line_length * var->yres_virtual + CURSOR_BUF_SIZE; //cursor buf also alloc here + smem_len = fix->line_length * var->yres_virtual; //cursor buf also alloc here map_size = PAGE_ALIGN(smem_len); - if (smem_len != fix->smem_len) // buffer need realloc { fbprintk(">>>>>> win1 buffer size is change(%d->%d)! remap memory!\n",fix->smem_len, smem_len); @@ -1316,7 +1380,6 @@ static int win1fb_set_par(struct fb_info *info) addr = fix->smem_start + offset; - LcdMskReg(inf, SYS_CONFIG, m_W1_ENABLE|m_W1_FORMAT, v_W1_ENABLE(1)|v_W1_FORMAT(format)); xpos += (screen->left_margin + screen->hsync_len); @@ -1708,18 +1771,6 @@ static int __init rk29fb_probe (struct platform_device *pdev) } inf->preg = (LCDC_REG*)inf->reg_vir_base; - if(0) - { - struct resource *rtc_mem = NULL; - u32 rtc_reg_vir_base = NULL; - rtc_mem = request_mem_region(RK29_RTC_PHYS, RK29_RTC_SIZE, NULL); - rtc_reg_vir_base = (u32)ioremap(RK29_RTC_PHYS, RK29_RTC_SIZE); - u32 rtc_reg = __raw_readl(rtc_reg_vir_base+0x04); - __raw_writel( rtc_reg | 0x02, rtc_reg_vir_base+0x04 ); - rtc_reg = __raw_readl(rtc_reg_vir_base+0x04); - } - - /* Prepare win1 info */ fbprintk(">> Prepare win1 info \n"); inf->win1fb = framebuffer_alloc(sizeof(struct win1_par), &pdev->dev); @@ -1837,50 +1888,12 @@ static int __init rk29fb_probe (struct platform_device *pdev) /* because after register_framebuffer, the win1fb_check_par and winfb_set_par execute immediately */ fbprintk(">> Init all lcdc and lcd before register_framebuffer \n"); init_lcdc(inf->win1fb); -#if 0 - inf->clk = clk_get(&pdev->dev, "lcdc_hclk"); - if (!inf->clk || IS_ERR(inf->clk)) - { - printk(KERN_ERR "failed to get lcdc_hclk source\n"); - ret = -ENOENT; - goto unregister_win1fb; - } - inf->dclk = clk_get(&pdev->dev, "lcdc"); - if (!inf->dclk || IS_ERR(inf->dclk)) - { - printk(KERN_ERR "failed to get lcd dclock source\n"); - ret = -ENOENT; - goto unregister_win1fb; - } - inf->dclk_parent = clk_get(&pdev->dev, "arm_pll"); - if (!inf->dclk_parent || IS_ERR(inf->dclk_parent)) - { - printk(KERN_ERR "failed to get lcd dclock parent source\n"); - ret = -ENOENT; - goto unregister_win1fb; - } - inf->dclk_divider= clk_get(&pdev->dev, "lcdc_divider"); - if (!inf->dclk_divider || IS_ERR(inf->dclk_divider)) - { - printk(KERN_ERR "failed to get lcd clock lcdc_divider source \n"); - ret = -ENOENT; - goto unregister_win1fb; - } - - inf->clk_share_mem = clk_get(&pdev->dev, "lcdc_share_memory"); - if (!inf->clk_share_mem || IS_ERR(inf->clk_share_mem)) - { - dev_err(&pdev->dev, "failed to get lcd clock clk_share_mem source \n"); - ret = -ENOENT; - goto unregister_win1fb; - } #ifdef CONFIG_CPU_FREQ - inf->freq_transition.notifier_call = rk29fb_freq_transition; - cpufreq_register_notifier(&inf->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); + // inf->freq_transition.notifier_call = rk29fb_freq_transition; + // cpufreq_register_notifier(&inf->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); #endif fbprintk("got clock\n"); -#endif if(mach_info) { @@ -1908,7 +1921,7 @@ static int __init rk29fb_probe (struct platform_device *pdev) mach_info->io_init(&fb_setting); } - //set_lcd_pin(pdev, 1); + set_lcd_pin(pdev, 1); mdelay(10); g_pdev = pdev; inf->mcu_usetimer = 1; -- 2.34.1