展讯平台点屏时要配置两个时钟(phy_freq和pixel_clk),那这两个参数要怎么配置呢,我们可以找到展讯的这份文档,输入屏的参数,即可计算出相应的时钟。如
然后将相应的参数填到屏的配置文件中,如
Android9.0以前,
uboot配置
.phy_freq = 1105000
.pixel_clk = 153600000
kernel配置
pixel_clk:由uboot传参到cmdline(在uboot)
clock-frequency = <1105000>;对应uboot的phy_freq
Android10.0
uboot配置
.phy_freq = 1105000
.pixel_clk = 153600000
kernel配置
sprd,phy-bit-clock = <1105000>;//phy-freq
clock-frequency = <153600000>;//pixel_clk
当然,这不是重点,之前一直不了解其中的运算规则,excel隐藏了其中的运算规则,今天看代码有了一些了解,分享下
pixel_clk计算
从下面的程序中可以窥见一二,如果配置是时钟源是dpi_clk_src中一个,直接使用,然后根据ROUND(a, b)计算分配分配系数
static const u32 dpi_clk_src[] = {
96000000,
128000000,
153600000,
192000000
};
static u32 calc_dpi_clk_src(u32 pclk)
{
int i;
for (i = 0; i < ARRAY_SIZE(dpi_clk_src); i++) {
if ((dpi_clk_src[i] % pclk) == 0)
return dpi_clk_src[i];
}
pr_err("calc DPI_CLK_SRC failed, use default\n");
return 96000000;
}
#define ROUND(a, b) (((a) + (b) / 2) / (b))
static int calc_dpi_clk(struct sprd_dispc *dispc,
u32 *new_pclk, u32 pclk_src,
u32 new_val, int type)
{
switch (type) {
case SPRD_FORCE_FPS:
case SPRD_DYNAMIC_FPS:
if (new_val < LCD_MIN_FPS || new_val > LCD_MAX_FPS) {
pr_err
("Unsupported FPS. fps range should be [%d, %d]\n",
LCD_MIN_FPS, LCD_MAX_FPS);
return -EINVAL;
}
pclk = hpixels * vlines * new_val;
divider = ROUND(pclk_src, pclk);
*new_pclk = pclk_src / divider;
if (pclk_src % divider)
*new_pclk += 1;
panel->fps = new_val;
break;
}
fps计算
static ssize_t actual_fps_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct sprd_dpu *dpu = dev_get_drvdata(dev);
struct videomode vm = dpu->ctx.vm;
uint32_t act_fps_int, act_fps_frac;
uint32_t total_pixels;
int ret;
total_pixels = (vm.hsync_len + vm.hback_porch +
vm.hfront_porch + vm.hactive) *
(vm.vsync_len + vm.vback_porch +
vm.vfront_porch + vm.vactive);
act_fps_int = vm.pixelclock / total_pixels;
act_fps_frac = vm.pixelclock % total_pixels;
act_fps_frac = act_fps_frac * 100 / total_pixels;
ret = snprintf(buf, PAGE_SIZE, "%u.%u\n", act_fps_int, act_fps_frac);
return ret;
}
static DEVICE_ATTR_RO(actual_fps);
kernel4.14/drivers/gpu/drm/sprd/dpu/dpu_r3p0.c
static void dpu_dpi_init(struct dpu_context *ctx)
{
if (ctx->vm.vsync_len + ctx->vm.vback_porch < 32)
pr_warn("Warning: (vsync + vbp) < 32, ""underflow risk!\n");
}
如上面的那组参数
1206*2138*60=154705680
ROUND(a, b)=1,分频系数为1,那时钟就是153600000
fps≈153600000/(1206*2138)≈60,满足要求
如这组参数,
1547*688*60=63860160
ROUND(a, b)=2,频率就是153600000/2=76800000,
fps≈76800000/(1547*688)≈72fps,,不满足要求
但更换64000000时钟源,
ROUND(a, b)=2,频率就是128000000/2=64000000,
fps≈64000000/(1547*688)≈60fps,满足要求
展讯给的公式为
1.need_clock = (width+hfp+hbp+hsync)*(height+vfp+vbp+vsync)*fps
2.dividor = dpi_clock_src/need_clock;
3.if((dpi_clock_src - dividor*need_clock) > (need_clock/2)){
dividor += 1;
}
phy_freq的计算
展讯给的公式为
(DPI_CLK_SRC/DIVIDOR)x 3x 8 bit < phy_feq x lane_num x 0.9
考虑到MIPI传输过程中可能会出现传输错误,实际设置的值可以再加大10%
对于下面屏的配置算出来的是
(153600000*3*8)/(4*0.9)*1.1=1126400000,表格算处理的是1105*1000kbs,差不多。