notro / fbtft

Linux Framebuffer drivers for small TFT LCD display modules. Development has moved to https://git.kernel.org/cgit/linux/kernel/git/gregkh/staging.git/tree/drivers/staging/fbtft?h=staging-testing
1.84k stars 495 forks source link

initialize the screen to black #595

Closed tomsn1978 closed 1 year ago

tomsn1978 commented 1 year ago

Hi I have a monochrome screen and I want to initialize the screen to black when I boot the kernel. Where should I modify the source code

anshulmakkar commented 1 year ago

you can modify the init sequence in fb_ssd1305.c

tomsn1978 commented 1 year ago

I have a single color screen model UC1618, which is similar to UC1701. I wrote a driver after fb_uc1701.c, which displays normally. Now I use qt to draw the screen pattern, where the color 0xFFFFFF means white, The color conversion in the "write_vmem" function also runs when the driver is loaded. When the module is loaded the data in the par->info->screen_buffer is 0x00, so it shows black. I think when initializing, par->info->screen_buffer is initialized to 0xff, which is 0xFF when the memory space is requested

notro commented 1 year ago

I can't see anything in fbtft/driver that should initialize the screen buffer to 0xff. I suggest you turn on debug output to see what is going on.

tomsn1978 commented 1 year ago
static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
{
    //dump_stack();
    u16 *vmem16 = (u16 *)par->info->screen_buffer;
    u8 *buf;
    int x, y, i;
    int ret = 0;

    for (y = 0; y < PAGES; y++) {
        buf = par->txbuf.buf;
        for (x = 0; x < WIDTH; x++) {
            *buf = 0x00;
            for (i = 0; i < 8; i++)
                {
                *buf |= (vmem16[((y * 8 * WIDTH) + (i * WIDTH)) + x]!=0xFFFF ? 1 : 0)<< i;
                }

            buf++;
        }

        gpio_set_value(par->gpio.dc, 1);
        ret = par->fbtftops.write(par, par->txbuf.buf, WIDTH);
        gpio_set_value(par->gpio.dc, 0);
    }

}

"I used 'dump_stack()' to trace the call stack when the kernel loads this module, and found that the 'write_vmem' function was called during kernel startup. I believe that somewhere in the code where it is used, a u16 vmem16 = (u16 )par->info->screen_buffer; was initialized as 0x00. Now I want to initialize it to 0xff."

notro commented 1 year ago

Please post the dump_stack() output.

tomsn1978 commented 1 year ago

[ 2.177186] fbtft_of_value: buswidth = 8 [ 2.181288] fbtft_of_value: debug = 0 [ 2.184990] fbtft_of_value: rotate = 0 [ 2.188779] fbtft_of_value: fps = 40 [ 2.322545] CPU: 0 PID: 1 Comm: swapper Not tainted 4.19.94-gbe5389fd85 #64 [ 2.329577] Hardware name: Generic AM33XX (Flattened Device Tree) [ 2.335770] Backtrace: [ 2.338275] [] (dump_backtrace) from [] (show_stack+0x18/0x1c) [ 2.345949] r7:00000000 r6:0000007f r5:00000000 r4:dbc843e4 [ 2.351713] [] (show_stack) from [] (dump_stack+0x24/0x28) [ 2.359008] [] (dump_stack) from [] (write_vmem+0x14/0xe8) [ 2.366337] [] (write_vmem) from [] (fbtft_update_display+0xd8/0x38c) [ 2.374621] r10:c069524c r9:00000000 r8:0000f000 r7:00000000 r6:0000007f r5:00000000 [ 2.382549] r4:dbc843e4 r3:c0695450 [ 2.386167] [] (fbtft_update_display) from [] (fbtft_register_framebuffer+0x100/0x2a4) [ 2.395932] r10:dbb12000 r9:00000000 r8:dbc84000 r7:dbb12000 r6:dbc84000 r5:00000000 [ 2.403859] r4:dbc843e4 [ 2.406431] [] (fbtft_register_framebuffer) from [] (fbtft_probe_common+0x12c/0x73c) [ 2.416018] r7:dbb12000 r6:dbc843e4 r5:c0d68cd0 r4:db9d6340 [ 2.421773] [] (fbtft_probe_common) from [] (fbtft_driver_probe_spi+0x20/0x24) [ 2.430795] r10:00000000 r9:c0d68d58 r8:00000000 r7:c14ae6e4 r6:c0d68d48 r5:dbb12000 [ 2.438721] r4:00000000 [ 2.441339] [] (fbtft_driver_probe_spi) from [] (spi_drv_probe+0x84/0xa8) [ 2.449931] [] (spi_drv_probe) from [] (really_probe+0x2d4/0x3e8) [ 2.457863] r7:c14ae6e4 r6:00000000 r5:c14ae6e0 r4:dbb12000 [ 2.463618] [] (really_probe) from [] (driver_probe_device+0x68/0x170) [ 2.472121] r10:c0c4a870 r9:c0d7ad80 r8:c0b68afc r7:c0d57e8c r6:dbb12034 r5:c0d68d58 [ 2.480007] r4:dbb12000 [ 2.482638] [] (driver_probe_device) from [] (driver_attach+0x128/0x148) [ 2.491359] r8:c0b68afc r7:c0d57e8c r6:dbb12034 r5:c0d68d58 r4:dbb12000 [ 2.498115] [] (__driver_attach) from [] (bus_for_each_dev+0x7c/0xc8) [ 2.506395] r7:c0d57e8c r6:c051de28 r5:c0d68d58 r4:c0d68d58 [ 2.512149] [] (bus_for_each_dev) from [] (driver_attach+0x24/0x28) [ 2.520208] r6:00000000 r5:dbafd480 r4:c0d68d58 [ 2.524914] [] (driver_attach) from [] (bus_add_driver+0x18c/0x210) [ 2.533024] [] (bus_add_driver) from [] (driver_register+0x94/0x12c) [ 2.541217] r7:00000000 r6:c0d777a8 r5:00000000 r4:c0d68d58 [ 2.546925] [] (driver_register) from [] (spi_register_driver+0x60/0x64) [ 2.555639] r5:c0c3bff8 r4:c0d780e0 [ 2.559260] [] (__spi_register_driver) from [] (fbtft_driver_module_init+0x18/0x38) [ 2.568790] [] (fbtft_driver_module_init) from [] (do_one_initcall+0x68/0x250) [ 2.577874] [] (do_one_initcall) from [] (kernel_init_freeable+0x284/0x330) [ 2.586688] r8:c0b68afc r7:c0c4a850 r6:c0d780e0 r5:00000007 r4:c0c5af68 [ 2.593514] [] (kernel_init_freeable) from [] (kernel_init+0x10/0x110) [ 2.601907] r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c082a350 [ 2.609789] r4:00000000 [ 2.612407] [] (kernel_init) from [] (ret_from_fork+0x14/0x20) [ 2.620029] Exception stack(0xdb897fb0 to 0xdb897ff8) [ 2.625172] 7fa0: 00000000 00000000 00000000 00000000 [ 2.633456] 7fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 2.641736] 7fe0: 00000000 00000000 00000000 00000000 00000013 00000000 [ 2.648398] r5:c082a350 r4:00000000 [ 2.666868] graphics fb0: fb_uc1618t frame buffer, 240x128, 60 KiB video memory, 4 KiB buffer memory, fps=50, spi0.0 at 4 MHz

This is the log at kernel startup time

**[ 21.033722] CPU: 0 PID: 771 Comm: kworker/0:3 Not tainted 4.19.94-gbe5389fd85 #64 [ 21.041402] Hardware name: Generic AM33XX (Flattened Device Tree) [ 21.047590] Workqueue: events fb_deferred_io_work [ 21.052452] Backtrace: [ 21.054968] [] (dump_backtrace) from [] (show_stack+0x18/0x1c) [ 21.062688] r7:00000000 r6:0000007f r5:00000055 r4:dbc843e4 [ 21.068422] [] (show_stack) from [] (dump_stack+0x24/0x28) [ 21.075800] [] (dump_stack) from [] (write_vmem+0x14/0xe8) [ 21.083165] [] (write_vmem) from [] (fbtft_update_display+0xd8/0x38c) [ 21.091479] r10:c069524c r9:0000007f r8:000050a0 r7:00000000 r6:0000007f r5:00000055 [ 21.099375] r4:dbc843e4 r3:c0695450 [ 21.103068] [] (fbtft_update_display) from [] (fbtft_deferred_io+0xe8/0xf0) [ 21.111904] r10:0000007f r9:0000007f r8:000001e0 r7:0000e000 r6:00000055 r5:dbafcec0 [ 21.119798] r4:0000007f [ 21.122487] [] (fbtft_deferred_io) from [] (fb_deferred_io_work+0xb4/0xfc) [ 21.131243] r10:00000000 r9:c0d78234 r8:dbc84000 r7:dbafce80 r6:dbafce84 r5:dbafcec4 [ 21.139137] r4:dbafcec0 [ 21.141786] [] (fb_deferred_io_work) from [] (process_one_work+0x274/0x65c) [ 21.150563] r9:c0d78234 r8:dbf35efc r7:dc407300 r6:c0d1ca34 r5:dbeb2c00 r4:dbc84360 [ 21.158442] [] (process_one_work) from [] (worker_thread+0x60/0x568) [ 21.166671] r10:db8a1e60 r9:00000008 r8:c0d24260 r7:c0d1ca68 r6:dbeb2c14 r5:c0d1ca34 [ 21.174628] r4:dbeb2c00 [ 21.177215] [] (worker_thread) from [] (kthread+0x11c/0x148) [ 21.184745] r10:db8a1e60 r9:00000000 r8:dbeb2c00 r7:dbeb2ab8 r6:dbf34000 r5:dbf09dc0 [ 21.192722] r4:dbeb2a80 [ 21.195307] [] (kthread) from [] (ret_from_fork+0x14/0x20) [ 21.202657] Exception stack(0xdbf35fb0 to 0xdbf35ff8) [ 21.207767] 5fa0: 00000000 00000000 00000000 00000000 [ 21.216083] 5fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 21.224394] 5fe0: 00000000 00000000 00000000 00000000 00000013 00000000 [ 21.231132] r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c015846c [ 21.239025] r4:dbf09dc0

** This is the log that is refreshed normally on the screen

They both call "write_vmem", and the data in par->info->screen_buffer is initialized to 0x00 when the kernel is started, and par->info->screen_buffer data is provided by the application layer when it is displayed normally

notro commented 1 year ago

This is strange, so if I understand you correctly when write_vmem() is called the first time the buffer constains 0xff. And you have checked that the buffer is 0x00 on allocation in fbtft_framebuffer_alloc(). I would have checked the buffer at various points following the call chain to find at which point it changes to 0xff.

tomsn1978 commented 1 year ago

"When write_vmem() is called for the first time, the buffer is constrained to 0x00. I want to initialize this buffer to 0xFF."

notro commented 1 year ago

Oh, ok.

You could use the Set Inverse Display command:

Set DC[0] to force all SEG drivers to output the inverse of the data stored in display memory. This function
has no effect on the existing data stored in display RAM.

Or you could add memset(par->info->screen_buffer, 0xff, par->info->fix.smem_len) in init_display().

tomsn1978 commented 1 year ago

Thank you. I have been looking for the right place to use memset(par->info->screen_buffer, 0xff, par->info->fix.smem_len)

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.