3128HDMI添加分辨率追踪

1.先从驱动节点入手
/sys/class/display # cd HDMI/
ls
3dmode audioinfo color connect debug enable mode modes monspecs name power property scale subsystem type uevent
找一个特立独行的节点名称
grep -rI "3dmode"
drivers/video/rockchip/hdmi/rockchip-hdmi-sysfs.c:      .get3dmode = hdmi_get_3dmode,
定位到文件
drivers/video/rockchip/display-sys.c
那我们看到
__ATTR(modes, S_IRUGO, display_show_modes, NULL),
cat modes对应的是
display_show_modes 这个函数,看看这个函数为啥没有添加我们显示器的分辨率
这个函数里面有一行代码
    if (dsp->ops->getmodelist(dsp, &modelist)) 
那我们就找到对应的
drivers/video/rockchip/hdmi/rockchip-hdmi-sysfs.c
    .getmodelist = hdmi_get_modelist,


这个函数长这样
static int hdmi_get_modelist(struct rk_display_device *device,
                 struct list_head **modelist)
{
    struct hdmi *hdmi = device->priv_data;

    *modelist = &hdmi->edid.modelist;
    return 0;
}

那这个modelist是个啥东西?我们在kenel下面 grep -rI "modelist",出来的东西挺多,但是别慌,一眼看到正主
drivers/video/rockchip/hdmi/rockchip-hdmi-edid.c:               hdmi_add_vic(vic, &pedid->modelist);
甭管它是谁的,反正给他加的是在这。那么这个函数的真身是?grep -rI "hdmi_add_vic"
drivers/video/rockchip/hdmi/rockchip-hdmi-lcdc.c:int hdmi_add_vic(int vic, struct list_head *head)
找到了也不着急找它,因为我们都知道hdmi最佳分辨率是在dtd块里面的。那么在这个文件里面我们找到hdmi_add_vic的所有调用地方
很快找到hdmi_edid_parse_dtd
有如下代码:
        hdmi_edid_parse_dtd(buf + ddc_offset, vmode);
        hdmi_add_vic(hdmi_videomode_to_vic(vmode), &pedid->modelist);

那么找一下这个函数
hdmi_videomode_to_vic
这个函数长这样
int hdmi_videomode_to_vic(struct fb_videomode *vmode)
{
    struct fb_videomode *mode;
    unsigned int vic = 0;
    int i = 0;

    for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
        mode = (struct fb_videomode *)&(hdmi_mode[i].mode);
        if (vmode->vmode == mode->vmode &&
            vmode->refresh == mode->refresh &&
            vmode->xres == mode->xres &&
            vmode->yres == mode->yres &&
            vmode->left_margin == mode->left_margin &&
            vmode->right_margin == mode->right_margin &&
            vmode->upper_margin == mode->upper_margin &&
            vmode->lower_margin == mode->lower_margin &&
            vmode->hsync_len == mode->hsync_len &&
            vmode->vsync_len == mode->vsync_len) {
            vic = hdmi_mode[i].vic;
            break;
        }
    }
    return vic;
}

而这个hdmi_mode 显然在drivers/video/rockchip/hdmi/rockchip-hdmi-lcdc.c中,那一串长长结构体就是。

我们就伊葫芦画瓢,添加一个自己的结构体。如下
    {
        .mode = {
            .name = "1280x1024p@60Hz",
            .refresh = 60,
            .xres = 1280,
            .yres = 1024,
            .pixclock = 108000000,
            .left_margin = 248,
            .right_margin = 48,
            .upper_margin = 38,
            .lower_margin = 1,
            .hsync_len = 112,
            .vsync_len = 3,
            .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
            .vmode = 0,
            .flag = 0,
        },
        .vic = HDMI_1280X1024P_60HZ,
        .vic_2nd = 0,
        .pixelrepeat = 1,
        .interface = OUT_P888,
    },

那么这个VIC怎么写呢,我们grep一下随便系统自己的,找到drivers/video/rockchip/hdmi/rockchip-hdmi.h
enum hdmi_video_information_code里面添加一个就行了。比如我这里就是HDMI_1280X1024P_60HZ
编译固件,大功告成。如果还有添加不成功的,建议追踪一下modelist 最后你会看到有个地方hdmi_ouputmode_select,它会过滤vic。你手动给他nop掉逻辑就行啦。
这个办法改了以后,可以使显示器自动probe到合适的分辨率,但是观察到framebuffersize和它输出的不合适,因此会花屏。这就是另一个问题了。
本人初接触rk平台,这个自适应HDMI的问题,尚需进一步研究,据我所知,rk在3568以后,基本把hdmi这块完善得完全没有毛病。它找不到的时序配置,它就读edid自己生成一个配置。
简直是插什么屏,就亮什么屏,基本没有调屏的困扰。这点要为国产点赞!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值