This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Testing a display with unusual resolution

Other Parts Discussed in Thread: OMAP3530

 

Hi all,

I would like to test an LCD display with a non-standard resolution which is attached to a Mistral 3530 EVM board.

I use ti-dvsdk_omap3530-evm_4_01_00_09.

Guided by http://processors.wiki.ti.com/index.php/UserGuideDisplayDrivers_PSP_03.00.00.05, I wrote a little program which opens the FB device, reads some values, programs the new frequencies and timing (using ioctl) and writes data into the mmapped FB.

At the first run, I see the previous value (from kernel startup). The display does not change (as far as I can see). At the second run I expect to see get the changed values but I see changes only for xres, yres, but not the timings.

Can someone please explain what is going wrong? Is there a complete example (demo code) to do something similar ?

Thanks in advance, Thomas.

 

PS:

The display is a Evervision 480x272 display with

Pixclock 9MHz

hres 480

h-front porch 2

h back porch 2

h sync 41

vres 272

v front porch 2

v back porch 2

v sync 10

 

This is the test code:



#include <stdio.h>
#include <stddef.h>
#include <fcntl.h>
#include <sys/mman.h>

#include "include/linux/fb.h"


int getFbFixScreeninfo(int fd)
{
    int ret;

    /* Getting fix screen information */
    struct fb_fix_screeninfo fix;
    ret = ioctl(fd, FBIOGET_FSCREENINFO, &fix);
    if(ret < 0) {
        printf("Cannot get fix screen information\n");
        return ret;
    }
    printf("ID = %s\n",fix.id);
    printf("Line length = %d\n",fix.line_length);
    printf("Physical Address = %x\n",fix.smem_start);
    printf("Buffer Length = %d\n",fix.smem_len);
    printf("MMIO Length = %d\n",fix.mmio_len);
    printf("MMIO start = %x\n",fix.mmio_start);
    printf("type = %d\n",fix.type);
    printf("type_aux = %x\n",fix.type_aux);
    printf("visual = %d\n",fix.visual);

    return ret;
}


void printBitfield(struct fb_bitfield bf)
{
    printf("Offset:%d, Length:%d, Msb:%d\n",bf.offset,bf.length,bf.msb_right);
}

int getFbVarScreeninfo(int fd)
{
    int ret;

    /* Getting fix screen information */
    struct fb_var_screeninfo var;
    ret = ioctl(fd, FBIOGET_VSCREENINFO, &var);
    if(ret < 0) {
        printf("Cannot get var screen information\n");
        return ret;
    }
    printf("RES = (%d,%d) VRES = (%d,%d)\n", var.xres, var.yres, var.xres_virtual, var.yres_virtual);
    printf("OFFSET = (%d,%d)\n", var.xoffset, var.yoffset);
    printf("BitsPerPixel = %d\n", var.bits_per_pixel);
    printf("Nonstd: %d\n", var.nonstd);
    printf("Bitfield Red:");
    printBitfield(var.red);
    printf("Bitfield Green:");
    printBitfield(var.green);
    printf("Bitfield Blue:");
    printBitfield(var.blue);
    printf("Activate: %d\n", var.activate);

    printf("Pixclock: %d\n", var.pixclock);
    printf("lp,rp,hs: %d,%d,%d\n", var.left_margin, var.right_margin, var.hsync_len);
    printf("tp,bp,vs: %d,%d,%d\n", var.upper_margin, var.lower_margin, var.vsync_len);
    printf("sync: HorHi:%d,VerHi:%d,Ext:%d,CompHi:%d,BC:%d,oG:%d\n", var.sync&FB_SYNC_HOR_HIGH_ACT?1:0,
            var.sync&FB_SYNC_VERT_HIGH_ACT?1:0, var.sync&FB_SYNC_EXT?1:0, var.sync&FB_SYNC_COMP_HIGH_ACT?1:0,
            var.sync&FB_SYNC_BROADCAST?1:0, var.sync&FB_SYNC_ON_GREEN?1:0 );
    printf("VMode: %d\n", var.vmode);
    printf("Rotate: %d\n", var.rotate);
    return ret;
}

int setFbVarScreeeninfo(int fd, int xres,int yres,int bpp, int pixcl, int lep,int rp,int hs, int up, int lop, int vs, int sync, int rot)
{
    int ret;
    struct fb_var_screeninfo var;

    ret = ioctl(fd, FBIOGET_VSCREENINFO, &var);
    if(ret < 0) {
        printf("Cannot get var screen information\n");
        return ret;
    }

    var.xres = xres;
    var.xres_virtual = xres;
    var.xoffset = 0;
    var.yres = yres;
    var.yres_virtual = yres;
    var.yoffset = 0;
    var.bits_per_pixel = bpp;
    var.pixclock = pixcl;
    var.left_margin = lep;
    var.right_margin = rp;
    var.hsync_len = hs;
    var.upper_margin = up;
    var.lower_margin = lop;
    var.vsync_len = vs;
    var.sync = sync;
    var.rotate = rot;

    ret = ioctl(fd, FBIOPUT_VSCREENINFO, &var);
    if(ret < 0) {
        printf("Cannot put var screen information\n");
        return ret;
    }
    return ret;
}

void mapAndDraw(int fd, int xres,int yres,int bytes)
{
    short * addr = NULL;

    addr = mmap(NULL,xres*yres*bytes,PROT_READ+PROT_WRITE,MAP_SHARED,fd,0);

    if(addr!=0)
    {
        int i;
        for(i=0;i<272;i++)
        {
            int j;
            for(j=0;j<480;j++)
            {
                addr[i*480+j] = ((i&4)^(j&4))?0:0xffff;
            }
        }
    }

    munmap(addr,xres*yres*bytes);
}

int main()
{
    int fd;
    int ret = 0;

    /* Open a graphics Display logical channel in blocking mode */
    fd = open ("/dev/fb0", O_RDWR);
    if (fd == -1) {
        perror("failed to open display device\n");
        return -1;
    }

    if (fd>0 && ret==0)
    {
        ret = getFbFixScreeninfo(fd);
    }

    if (fd>0 && ret==0)
    {
        ret = getFbVarScreeninfo(fd);
    }

    if (fd>0 && ret==0)
    {
        ret = setFbVarScreeeninfo(fd, 480,272,16,111111,2,2,41,2,2,10,0,0);
    }

    if (fd>0 && ret==0)
    {
        mapAndDraw(fd,480,272,2);
    }



    /* Closing of channels */
    close (fd);
}

 

 

  •  

    Hi again,

     

    after failing with the above approach, I found another fragment of the DSS driver documentation, here

     

    http://processors.wiki.ti.com/index.php/OMAP3_DSS2_Architecture

     

    which clearly suggests, to generate a new kernel display driver "panel_XXXX.c". Looking into the directories I even found a driver for a SHARP LQ xxx display which has quite the same timing as our evervision. Hence, I hoped that my work is done by enabling this driver (disabling all others) and the system can only choose the remaining display driver. This failed again and I am still stucked due to incomplete, unclear or missing documentation.

    Here are a couple of questions:

    What does the last sentence (NOTE: Please do not forget to register device for your newly added LCD panel driver in your board specific file.) mean ?

    How do I force the kernel to choose this existing display driver (by kernel parameter, ioctl, sysfs, tools or whatever) ?

    How do the modelines in drivers/video/modedb.c and the display drivers correspond ?  Do I have to specify one ?

    Where do I find consistent documentation of the omap drivers ?  Which documents are uptodate?

     

    Regards, Th.

     

     

     

  • Hi,

    Registering available display panels is done uner the machine-specific code. For the OMAP3 EVM, edit arch/arm/mach-omap2/board-omap3evm.c. Below is what you can find by default:

    static struct omap_dss_device omap3_evm_lcd_device = {
            .name                   = "lcd",
            .driver_name            = "sharp_ls_panel",
            .type                   = OMAP_DISPLAY_TYPE_DPI,
            .phy.dpi.data_lines     = 18,
            .platform_enable        = omap3_evm_enable_lcd,
            .platform_disable       = omap3_evm_disable_lcd,
    };

    static struct omap_dss_device *omap3_evm_dss_devices[] = {

            &omap3_evm_lcd_device,
            &omap3_evm_tv_device,
            &omap3_evm_dvi_device,
    };
     
    static struct omap_dss_board_info omap3_evm_dss_data = {
            .num_devices    = ARRAY_SIZE(omap3_evm_dss_devices),
            .devices        = omap3_evm_dss_devices,
            .default_device = &omap3_evm_lcd_device,
    };
    The "omap3_evm_dss_data" structure is passed to the display driver to register the display panels available. In this case there are 3 of them (LCD,TV,DVI), the LCD being selected by default. For your particular needs, you need to create a "omap_dss_device" with the parameters fitting your display and add this structure to "omap3_evm_dss_devices". You might even set the driver to take this panel by default by having the "default_device" field point to your structure. Note that the "driver_name" field of your structure should be the same as the one you defined in "panel_XXXX.c".
    Let us know how it goes.
  •  

    ok,

     

    now I see a very stable white display. Probably this means, that I have the timing correct.

    root@omap3evm:~/omap3530# fbset

    mode "480x272-60"
        # D: 9.000 MHz, H: 17.143 kHz, V: 59.940 Hz
        geometry 480 272 480 272 16
        timings 111111 2 2 2 2 41 10
        rgba 5/11,6/5,5/0,0/0
    endmode

    root@omap3evm:~/omap3530# cat /sys/devices/platform/omapdss/display0/timings
    9000,480/2/2/41,272/2/2/10

    This looks all quite well.

    But I still do not see any output. What do you suggest as the most direct way to write into the display framebuffer ? Should my above test application with the mmapped /dev/fb0 work ?

    I will also recheck with our HW guys, if the data lines are connected correctly.

    Thx, Th.

     

     

     

     

  •  

    Hi,

    after solving some wiring problems, we finally see pixel-data.

    But there is still a problem: The position of the displayed frame seems to be constantly circling through the address range. When I use the little SW from my first post, I see the checkers pattern that is written into the frame buffer from time to time (for some seconds every 3 minutes)

    Any ideas ?

    Thx, Th.