全志D1/D1s芯片:芒果派麻雀点RGB屏填坑

news/2024/11/7 18:49:26/

前言

最近全志推出了D1处理器,搭载平头哥玄铁906 RISC-V的应用处理器。于是准备入手玩一下,买了芒果派做了基于D1s的麻雀板,D1s是D1内封64M DDR的版本,去掉了hdmi输出,号称点屏强芯,点个屏来玩玩。
先晒下小巧精致的麻雀:
在这里插入图片描述

点屏

手上正好有块480*272的rgb屏,可以用这个小板子来点一下。想来rgb屏幕应该很好适配,dts里改几个参数就完事了,不过多次调整怎么也没法让画面正常输出,这个问题应该有不少人遇到。先直入主题说一下如何修复问题吧,后面在详细记录填坑过程。

快速上手体验

我修复的代码patch在这里 https://download.csdn.net/download/qq_34440409/66654101,下载下来后分别到kernel uboot 里打上patch即可。
然后屏幕参数DTS里根据自己的屏参配置下,可以参考我的配置,主要是以下几个参数:

/* part 3 */
lcd_width = <95>; /* 随便写 */
lcd_height = <54>;/* 随便写 */
lcd_x = <480>;
lcd_y = <272>;
lcd_dclk_freq = <9>;
lcd_hbp = <40>;
lcd_ht = <525>;
lcd_hspw = <0>;
lcd_vbp = <8>;
lcd_vt = <288>;
lcd_vspw = <0>;

另外屏幕起来后加载到kernel启动会明显感觉到颜色发生了变化,在kernel 的DTS里找到dmic,并关闭

&dmic {pinctrl-names   = "default","sleep";pinctrl-0       = <&dmic_pins_a>;pinctrl-1       = <&dmic_pins_b>;status = "disable";
};

这个据网友反馈是屏引脚占用导致。

详细填坑过程记录

1.关闭uboot logo显示

为了方便调试我们先针对内核修改,把uboot点屏给他关了。
打开文件 D1\lichee\brandy-2.0\u-boot-2018\configs\sun20iw1p1_defconfig
搜索 CONFIG_DISP2_SUNXI 并注释。重新编译烧录就不会在显示uboot logo了

2.确定屏参

点RGB屏一般就是配一下几个参数的事,这些参数屏手册一般都会给出来,例如我的屏参手册
在这里插入图片描述
从这里可以直接对应到DTS里的几个配置项

lcd_x = <480>;
lcd_y = <272>;
lcd_dclk_freq = <9>;
lcd_hbp = <40>;
lcd_ht = <525>;lcd_vbp = <8>;
lcd_vt = <288>;

还剩下lcd_hspw,lcd_vspw
hspw (HSYNC plus width)行同步脉宽 单位:像素时钟周期
vspw (VSYNC width)垂直同步脉宽 单位:显示一行的时间th
以水平方向为例说一下几个参数的关系:
ht = h显示区域像素 + hbp + hfb + hspw
525 = 480 + 40 + 5 + 0
由此可以确定hspw与vspw 两项的值为0,按经验来说 spw这项一般不需要额外关注。

3.查看LCD显示调试信息

但我照着手册填好后点屏画面总是糊的,调整一番参数多次尝试无果,确定参数应该是没有问题的,那只能翻手册查看调试信息排坑了。
关于D1/D1s芯片资料可以在这里获取https://whycan.com/t_6440.html
查看lcd调试指南,我们可以通过

cat /sys/class/disp/disp/attr/sys

查看显示信息
在这里插入图片描述
DTS里配置的值算出来是60帧没有问题,分辨率也正常,但是实际跑的帧率为322,这差太多了,根据帧率计算公式:
lcd_dclk_freq * 1000000 * num_of_pixel_clk = lcd_ht * lcd_vt * fps
式子里
lcd_dclk_freq单位为Mhz
num_of_pixel_clk = 1 ,因为我们是并行RGB接口,一个时钟发送一个像素
将我们的DTS配置带入以上公式 fps确实应该是60,但实际fps为322,那么我们假设时钟可能不对,反推一下将322fps带入公式算dclk得到
525 * 288 * 322.5 = 48.762M
这个时候我们更改下DTS 按800 * 480的屏参配置

lcd_dclk_freq = <33>;
lcd_hbp = <46>;
lcd_ht = <1055>;
lcd_hspw = <0>;
lcd_vbp = <23>;
lcd_vt = <525>;
lcd_vspw = <0>;

查看显示信息
在这里插入图片描述
根据实际帧率计算dclk
1055 * 525 * 87.7 = 48.574M
由此可以大概能猜到,dclk确实是48M,而dts的对dclk的设置应该是不生效的。

查看下lcd相关的时钟

cat /sys/kernel/debug/clk/clk_summary
cat /sys/kernel/debug/clk/clk_summary | grep tcon

在这里插入图片描述
这里的时钟具体含义与dclk的关系暂时不得而知,可以先留意一下,后面再来对应。

4.通过修改寄存器尝试解决问题

既然猜到了dclk有问题,那么可以去查下寄存器手册找到该值的地址,确定下问题。
最终查到的dclk寄存器描述如下:
在这里插入图片描述
dclk寄存器基地址:
在这里插入图片描述
dclk地址为:0x05461044
用devmem工具读一下寄存器的值 devmem 0x05461044
在这里插入图片描述
根据寄存器的描述:Tdclk = Tsclk/DCLKDIV。 Tsclk是个啥我们也不清楚,但我们可以用已知量先反推计算下:
Tsclk = Tdclk * DCLKDIV = 48 * 6 = 288 Mhz
看到这个数字你想到了什么,前面查看时钟时 tcon-lcd0 的值不就是这个吗。
现在知道了Tsclk = 288M ,要想让我们的dclk为9M,那就得改DCLKDIV为32。

把我们的设备烧录回480 * 272的DTS配置,写寄存器 devmem 0x05461044 32 0xF0000020
写完后立马看到屏幕显示正常了,确定是这个问题无疑。
DTS设置不生效就要去驱动源码里查问题了。

5.梳理屏幕显示驱动

DTS里可知 lcd_driver_name = “default_lcd”
我们可以通过搜索"default_lcd"来找屏驱动文件,找到了drivers/video/fbdev/sunxi/disp2/disp/lcd/default_panel.c,查看文件发现只有上下电时序,初始化序列相关,没有我们需要的,那直接按解析参数来搜索好了。
进入到内核目录,执行 grep -rn "lcd_dclk_freq"
在这里插入图片描述
找到文件drivers/video/fbdev/sunxi/disp2/disp/de/disp_lcd.c
lcd 显示初始化使能主要有这个函数来完成:disp_lcd_fake_enable,梳理出其中主要关注的调用

disp_lcd_fake_enable(...)
{
...//省略若干代码lcd_clk_enable(lcd); //该函数通过调用 lcd_clk_config 来配置lcd相关时钟ret = cal_real_frame_period(lcd); //通过调用do_div(temp, lcd->timings.dclk_rate_set); 设置了 dclk_rate_set
...
}

先来看下 lcd_clk_config 函数,时钟配置的代码在这里:

lcd_clk_config(...)
{
...//省略若干代码disp_al_lcd_get_clk_info(lcd->hwdev_index, &clk_info,&lcdp->panel_info);dclk_rate = lcdp->panel_info.lcd_dclk_freq * 1000000;	/* Mhz -> hz */if (lcdp->panel_info.lcd_if == LCD_IF_DSI) {lcd_rate = dclk_rate * clk_info.dsi_div;pll_rate = lcd_rate * clk_info.lcd_div;} else {lcd_rate = dclk_rate * clk_info.tcon_div;pll_rate = lcd_rate * clk_info.lcd_div;}
...dclk_rate_set = lcd_rate_set / clk_info.tcon_div;if ((pll_rate_set != pll_rate) || (lcd_rate_set != lcd_rate)|| (dclk_rate_set != dclk_rate)) {DE_WRN("disp %d, clk: pll(%ld),clk(%ld),dclk(%ld) dsi_rate(%ld)\n     clk real:pll(%ld),clk(%ld),dclk(%ld) dsi_rate(%ld)\n",lcd->disp, pll_rate, lcd_rate, dclk_rate, dsi_rate,pll_rate_set, lcd_rate_set, dclk_rate_set, dsi_rate_set);}return 0;
}

dclk_rate 就是我们DTS传入的9Mhz参数,通过该值计算得到两个时钟 lcd_rate 与 pll_rate ,根据代码可以得知
pll_rate = lcd_rate = dclk_rate * tcon_div;

pll_rate、 lcd_rate、 dclk_rate 这些都是我们根据DTS得到的值,实际设置值为 pll_rate_set、 lcd_rate_set、dclk_rate_set。这个函数末尾已经加了打印,当计算值与实际设置值不一致时就会打印,查看下启动打印有没有:
在这里插入图片描述
可以看到上面设置没有生效,pll_rate实际是288M,加下打印

	DE_WRN("lyrdebug start\n");if (lcdp->clk_parent) {DE_WRN("lyrdebug set pll_rate_set(%ld)\n",pll_rate);clk_set_rate(lcdp->clk_parent, pll_rate);pll_rate_set = clk_get_rate(lcdp->clk_parent);DE_WRN("lyrdebug get pll_rate_set(%ld)\n",pll_rate_set);}if (clk_info.lcd_div)lcd_rate_set = pll_rate_set / clk_info.lcd_div;elselcd_rate_set = pll_rate_set;DE_WRN("lyrdebug get lcd_rate_set-1-(%ld)\n",lcd_rate_set);clk_set_rate(lcdp->clk_tcon_lcd, lcd_rate_set);lcd_rate_set = clk_get_rate(lcdp->clk_tcon_lcd);DE_WRN("lyrdebug get lcd_rate_set-2-(%ld)\n",lcd_rate_set);DE_WRN("lyrdebug end\n");

查看打印:
在这里插入图片描述
可以得知设置pll_rate这步不生效,那么解决问题就有两个路线了,

  1. 继续追查clk_set_rate(lcdp->clk_parent, pll_rate)为何不生效,至于具体原因那就要去查手册pll_rate相关的属性注意项了
  2. 保持pll_rate为288M,更改DCLK_DIV的值来使得最终给到dclk的值为实际值。

这里我们就懒得再去追查pll_rate设置不生效原因了,我们先假设pll_rate最小值为288M或者他只能设置为288M。
然后找到DCLK_DIV设置的地方,去修改。
通过上面代码分析可以知道pll_rate 与 dclk_rate 的关系:
pll_rate = lcd_rate = dclk_rate * tcon_div
那么这个tcon_div应当就是DCLK_DIV了
tcon_div的值来自函数disp_al_lcd_get_clk_info
搜索这个函数,找到源码:
在这里插入图片描述
可以看到很多结果,哪个才是我们真正使用的源文件呢,这里有个小技巧,通过.o文件来反推,找到了该函数位于文件:
drivers/video/fbdev/sunxi/disp2/disp/de/lowlevel_v2x/disp_al.c
打开文件找到函数disp_al_lcd_get_clk_info

...
static struct lcd_clk_info clk_tbl[] = {{LCD_IF_HV, 6, 1, 1, 0},{LCD_IF_CPU, 12, 1, 1, 0},{LCD_IF_LVDS, 7, 1, 1, 0},
#if defined(DSI_VERSION_40){LCD_IF_DSI, 4, 1, 4, 150000000},
#else{LCD_IF_DSI, 4, 1, 4, 0},
#endif /*endif DSI_VERSION_40*/{LCD_IF_VDPO, 4, 1, 1, 0},
};
...
disp_al_lcd_get_clk_info(...)
{
...for (i = 0; i < sizeof(clk_tbl) / sizeof(struct lcd_clk_info); i++) {if (clk_tbl[i].lcd_if == panel->lcd_if) {tcon_div = clk_tbl[i].tcon_div;lcd_div = clk_tbl[i].lcd_div;dsi_div = clk_tbl[i].dsi_div;dsi_rate = clk_tbl[i].dsi_rate;find = 1;break;}}
...
}

从这里就知道了tcon_div值来自clk_tbl[]中,默认为6,这与我们之前寄存器查看得到值是对得上的。

6.动手修改

上面已经找到了tcon_div值设置的位置,就在这下面添加代码好了

	if(panel->lcd_dclk_freq < 48 && panel->lcd_dclk_freq >= 3){tcon_div = 288/panel->lcd_dclk_freq;}

意思是当DTS中设置的dclk在3到48M之间时自动计算tcon_div的值,要满足tcon_div小于128。

kernel修改完毕后编译测试显示正常,来看下显示调试信息
在这里插入图片描述
可以看到实际帧率与设置帧率完全一致了。

Uboot的修改也是同样的道理,UBoot显示驱动代码路径在D1\lichee\brandy-2.0\u-boot-2018\drivers\video\sunxi\disp2\disp\de\

完成

最后晒一下屏幕显示结果
在这里插入图片描述


http://www.ppmy.cn/news/180429.html

相关文章

k8s节点扩容与缩容

#使用镜像&#xff1a;ikubernetes/myapp:v1 1个master节点2个node节点 [rootmaster ~]# kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME master …

全志V3S Linux 开发过程回记

半年没有碰linux了&#xff0c;一直在玩ESP32&#xff0c;把esp32的人脸识别、语音识别、百度AI识别都摸了个遍 &#xff0c;搞完这些开源出来后&#xff0c;竟然没人喜欢&#xff0c;瞬间就觉得没意思 于是&#xff0c;重新捡起linux开发&#xff0c;我是从全志V3S入门&#x…

荔枝派 zero(全志V3S)-编译及SD烧录

之前买了个荔枝派&#xff0c;全志的A3S芯片。折腾了两天&#xff0c;写一下编译和SD烧录的过程。 目录 1.直接烧录镜像文件 2.uboot编译 3.kernel编译 4.rootfs编译 5.烧录 6.串口登录 1.直接烧录镜像文件 百度到了一堆的资料&#xff0c;下面是网盘链接 链接&#x…

电网电压及中国TN-S系统学习

目前各国的室内电压大体分为两种&#xff1a;100V~130V&#xff0c;220V~240V两个类型。 100V、110V~130V被归类低压&#xff0c;如美国、日本等以及船上的电压&#xff0c;注重安全&#xff1b;220V~240V被称为高压&#xff0c;其中包括中国的220伏及英国的230伏和很多欧洲国…

k8s(三)、kube-router: K8S BGP直通网络CNI方案

前言 上一篇讲到&#xff0c;k8s使用traefik代理集群内部服务&#xff0c;灵活地注入代理配置的方式&#xff0c;提供7层对外服务&#xff08;参考&#xff1a;k8s&#xff08;二&#xff09;、对外服务&#xff09;。在本篇&#xff0c;使用kube-router的cni&#xff0c;实现…

RISC-V (CH32V103)与Cortex-M3内核(CH32F103)单片机中断延时测评

最近在学习RISC-V架构的MCU&#xff0c;特地学习了一下“中断处理机制”&#xff0c;对比之前使用过的Cortex-M3内核单片机&#xff0c;研究它们在中断执行和处理上的差异和效率。 样品选择 CH32V103C8T6和CH32F103C8T6 CH32V103C8T6&#xff0c;沁恒微电子的RSIC-V架构32位…

彩色MT9V034摄像头 Bayer转rgb FPGA实现

彩色MT9V034摄像头 Bayer转rgb FPGA实现 1 图像bayer格式介绍 bayer格式是伊士曼柯达公司科学家Bryce Bayer发明的&#xff0c;Bryce Bayer所发明的拜耳阵列被广泛运用数字图像。Bayer格式是相机内部的原始数据, 一般后缀名为.raw。 对于彩色图像,一般是三原色数据&#xff0c…

AIC, BIC v.s. Crossvalidation

模型选择的方法有许多&#xff0c;例如 AIC, BIC, Crossvalidation, GCV等等。这 些准则的适用条件有哪些&#xff1f;该如何选择不同的准则&#xff1f; AIC, BIC准则 ref&#xff1a;https://methodology.psu.edu/node/504 ref&#xff1a;https://en.wikipedia.org/wiki/B…