Firefly开源社区

标题: firefly-RK3288 Lubuntu 修改分辨率时钟无法正确设置的问题 [打印本页]

作者: Mimosa    时间: 2016-1-27 02:12
标题: firefly-RK3288 Lubuntu 修改分辨率时钟无法正确设置的问题
本帖最后由 Mimosa 于 2016-1-27 02:17 编辑

你好,
我自己有个VGA的显示器,最佳分辨率是1440*900,本来以为直接接上我们的firefly RK3288 在LUbuntu就可以完美工作了,可是发现显示并不完美。这三周泡在firefly的论坛上,也搜索了所有相关分辨率改动的相关文章,都找不到合适的修改方法。因为我想把精力尽快投入到应用开发,这个显示都不对,后续根本没法进行!虽然说多学也有好处,但时间应该在最关键的地方发力。所以,我想请教贵公司的开发人员一些问题,希望尽快解决此问题。
我现在只能确定这么几点:
1. 我使用的是firefly提供得Lubuntu系统,kernel git log最后的版本是:
   commit b8f71a62dc31c36d0c3563d1bc8537931b69b7aa
   Author: Firefly-RK3288 <service@t-firefly.com>
   Date:   Thu Nov 26 14:20:38 2015 +0800

    Kernel->usb:fix usb can not work sometimes
   我接的显示器是VGA得,最佳分辨率是1440*900
2. 根据论坛提示,先使用fbset查看当前设置:
   root@firefly:/home/firefly# fbset
   mode "1920x1080-48"
     # D: 118.807 MHz, H: 54.003 kHz, V: 48.003 Hz
     timings 8417 148 88 36 4 44 5
     geometry 1920 1080 1920 1080 16
     nonstd 4
     rgba 5/11,6/5,5/0,0/0
   endmode
   验证分辨率和颜色位数,时序都不对。于是,我使用fbset修改颜色空间和分辨率
   service lightdm stop
   fbset -a -nonstd 5 -rgba 8/16,8/8,8/0,8/24 -g 1440 900 1440 900 32
   service lightdm start

   nonstd的5对应HAL_PIXEL_FORMAT_BGRA_8888
   // include/linux/rk_fb.h
   enum {

    HAL_PIXEL_FORMAT_RGBA_8888 = 1,

    HAL_PIXEL_FORMAT_RGBX_8888 = 2,

    HAL_PIXEL_FORMAT_RGB_888 = 3,

    HAL_PIXEL_FORMAT_RGB_565 = 4,

    HAL_PIXEL_FORMAT_BGRA_8888 = 5,

    ......
   };
   但是,显示发现还是异常,那只剩下最后的问题,时序问题。(使用fbset修改时序是没有用得,下面会提及)
2. 我的VGA显示器是比较标准的。通过cvt命令可知:
   cvt 1440 900
   # 1440x900 59.89 Hz (CVT 1.30MA) hsync: 55.93 kHz; pclk: 106.50 MHz
   Modeline "1440x900_60.00"  106.50  1440 1528 1672 1904  900 903 909 934 -hsync +vsync
   获得标准的点时钟是: 106.50 MHz。
   然后,我找到drivers/video/rockchip/vga/sda7123_vga.c,sda7123_vga_mode已经添加了1440*900mode了。并且预设的点时钟也106500000也是对的。
   所以,最后其实就剩下timming的设置了。
3. timming是在drivers/clk/rockchip目录处理的。
   //drivers/clk/rockchip/clk-pll.c文件
   static const struct clk_ops clk_pll_ops_3188plus = {
    .recalc_rate = clk_pll_recalc_rate_3188plus,
    .round_rate = clk_pll_round_rate_3188plus,
    .set_rate = clk_pll_set_rate_3188plus,
   };
   为了clk_pll_round_rate_3188plus函数可能找到对应分辨率的时钟,我在rk3188plus_pll_com_table添加了“852000”这个CLKS
   static const struct pll_clk_set rk3188plus_pll_com_table[] = {
    _RK3188PLUS_PLL_SET_CLKS(1250000,   12, 625,    1),
    _RK3188PLUS_PLL_SET_CLKS(1200000,   1,  50, 1),
    _RK3188PLUS_PLL_SET_CLKS(1188000,   2,  99, 1),
    _RK3188PLUS_PLL_SET_CLKS(891000,    8,  594,    2),
    //_RK3188PLUS_PLL_SET_CLKS(852000,    4,  284,    2),  //1440*900,是问别人的,他们公司产品用了这个参数,该VGA分辨率RK3188肯定工作。
    _RK3188PLUS_PLL_SET_CLKS(852000,    1,  71,    2),  //1440*900, 因为(24000*71)/2=852000, 并且852000/106500=8,是整除关系,可以分频
    _RK3188PLUS_PLL_SET_CLKS(768000,    1,  64, 2),
    ......
   }
   但是在函数“clk_pll_set_rate_3188plus”里,继续调用“_pll_clk_set_rate_3188plus”的时候,有写死的部分代码:
    if(!strcmp(__clk_get_name(hw->clk), "clk_cpll")) {
//      cru_writel(0xffff000f, pll->reg + RK3188_PLL_CON(0));
        cru_writel(0xffff0007, pll->reg + RK3188_PLL_CON(0));
        cru_writel(0xffff00c5, pll->reg + RK3188_PLL_CON(1));
    }
    else {
        cru_writel(clk_set->pllcon0, pll->reg + RK3188_PLL_CON(0));
        cru_writel(clk_set->pllcon1, pll->reg + RK3188_PLL_CON(1));
    }
    ....
    if (pll->lock) {
        if(!strcmp(__clk_get_name(hw->clk), "clk_cpll")) {
            cru_writel(0, pll->reg + RK3188_PLL_CON(2));
        }
        spin_unlock_irqrestore(pll->lock, flags);
    }
    这样写死那根本没法设置正确的时钟,于是,我改成如下:
#ifdef USE_BOX
    if(!strcmp(__clk_get_name(hw->clk), "clk_cpll")) {
//      cru_writel(0xffff000f, pll->reg + RK3188_PLL_CON(0));
        cru_writel(0xffff0007, pll->reg + RK3188_PLL_CON(0));
        cru_writel(0xffff00c5, pll->reg + RK3188_PLL_CON(1));
    }
    else {
        cru_writel(clk_set->pllcon0, pll->reg + RK3188_PLL_CON(0));
        cru_writel(clk_set->pllcon1, pll->reg + RK3188_PLL_CON(1));
    }
#else
    cru_writel(clk_set->pllcon0, pll->reg + RK3188_PLL_CON(0));
    cru_writel(clk_set->pllcon1, pll->reg + RK3188_PLL_CON(1));
#endif
    ....
#ifdef USE_BOX
    if (pll->lock) {
        if(!strcmp(__clk_get_name(hw->clk), "clk_cpll")) {
            cru_writel(0, pll->reg + RK3188_PLL_CON(2));
        }
        spin_unlock_irqrestore(pll->lock, flags);
    }
#else
    if (pll->lock)
        spin_unlock_irqrestore(pll->lock, flags);
#endif

   但改后,直接黑屏了...

   还有//drivers/clk/rockchip/clk-ops.c文件
   const struct clk_ops clkops_rate_3288_dclk_lcdc0 = {
    .determine_rate = clk_3288_dclk_lcdc0_determine_rate,
    .set_rate   = clk_3288_dclk_lcdc0_set_rate,
    .round_rate = clk_3288_dclk_lcdc0_round_rate,
    .recalc_rate    = clk_divider_recalc_rate,
   };
   函数clk_3288_dclk_lcdc0_determine_rate也是写死“594*MHZ”相关的时钟。


   最后,想问一下firefly的研发人员,有什么好建议?完善点得话,能不能给个1440*900分辨率的补丁。在这再次表达感谢。

(上面作为邮件也已经发给fn.service@t-firefly.com)
作者: zhansb    时间: 2016-1-27 16:53
不完美,具体是什么现象?
作者: Mimosa    时间: 2016-1-27 21:11
本帖最后由 Mimosa 于 2016-1-28 00:45 编辑

具体就是,可以显示,但是显示的时候字体模糊,拖动时有残影等。下面几张图是我经过命令后拍的
fbset -a -nonstd 5 -rgba 8/16,8/8,8/0,8/24 -g 1440 900 1440 900 32

图片:

第一张图Move下面本来有一行字的,模糊到没有
第二张图图标也是有字的。用鼠标划过去,就恢复不回来了
第三张图,刷新率是有问题的,我想得到60,但因为kernel内部时钟写死,所以不可能获得正确的刷新率

作者: Mimosa    时间: 2016-1-27 21:16
本帖最后由 Mimosa 于 2016-1-28 00:45 编辑

因为就是点时钟设置的问题,是被固定死为“594*MHZ"的。我想请教firefly的技术人员和大家怎么正确的修改这个时钟,论坛上基本都是让你可以改一下这个那个,都是点到为止,基本上没有具体的实现,希望回答的具体些,具体到1440*900这个时钟设置OK,正常显示,再次万分感谢。还有几天快过年了,希望在这几天能解决掉。
作者: Mimosa    时间: 2016-1-28 19:28
zhansb 发表于 2016-1-27 16:53
不完美,具体是什么现象?

@zhansb 能否帮我分析下
作者: Mimosa    时间: 2016-2-19 14:49
@zhansb 继续顶起,没人回答
作者: Mimosa    时间: 2016-2-19 14:51
zhansb 发表于 2016-1-27 16:53
不完美,具体是什么现象?

@zhansb 不知道能不能给点提示?




欢迎光临 Firefly开源社区 (https://dev.t-firefly.com/) Powered by Discuz! X3.1