展訊平臺點屏時要配置兩個時鐘(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,差不多。