1080p60 video refresh of DSI output can 't reach 60HZ

Hi:
We are currently debuging the DSI output of our custom tx1 board. The dts is as follows.

dsi {
			compatible = "nvidia,tegra210-dsi";
			reg = <0x0 0x54300000 0x0 0x40000 0x0 0x54400000 0x0 0x40000>;
			clocks = <0x41 0x30 0x41 0x93 0x41 0x52 0x41 0x94 0x41 0xf6 0x41 0xb1>;
			clock-names = "dsi", "dsia_lp", "dsib", "dsib_lp", "pll_p_out3", "clk72mhz";
			resets = <0x41 0x30 0x41 0x52>;
			reset-names = "dsia", "dsib";
			pad-controllers = <0x5b 0xf 0x5b 0x10 0x5b 0x11 0x5b 0x12>;
			pad-names = "dsia", "dsib", "dsic", "dsid";
			status = "okay";
			nvidia,dsi-controller-vs = <0x1>;

			panel-dsi-1080p-p2382 {
				status = "okay";
				compatible = "dsi,1080p";
				nvidia,dsi-instance = <0x0>;
				nvidia,dsi-n-data-lanes = <0x4>;
				nvidia,dsi-pixel-format = <0x3>;
				nvidia,dsi-refresh-rate = <0x3c>;
				nvidia,dsi-video-data-type = <0x0>;
				nvidia,dsi-video-clock-mode = <0x0>;
				nvidia,dsi-video-burst-mode = <0x1>;
				nvidia,dsi-virtual-channel = <0x0>;
				nvidia,dsi-panel-reset = <0x1>;
				nvidia,dsi-power-saving-suspend = <0x1>;
				nvidia,dsi-ulpm-not-support = <0x1>;
				nvidia,dsi-init-cmd = <0x0 0x5 0x11 0x0 0x0 0x3 0x5 0x1 0x14 0x0 0x5 0x29 0x0 0x0 0x1 0x14>;
				nvidia,dsi-n-init-cmd = <0x5>;
				nvidia,dsi-suspend-cmd = <0x0 0x5 0x28 0x0 0x0 0x0 0x5 0x10 0x0 0x0 0x1 0x50>;
				nvidia,dsi-n-suspend-cmd = <0x3>;
				nvidia,dsi-dpd-pads = <0x4 0x8>;
				nvidia,panel-rst-gpio = <0x7b 0xaa 0x0>;
				nvidia,panel-bl-pwm-gpio = <0x7b 0xa8 0x0>;

				disp-default-out {
					nvidia,out-type = <0x2>;
					nvidia,out-width = <0x780>;
					nvidia,out-height = <0x438>;
					nvidia,out-flags = <0x0>;
					nvidia,out-xres = <0x780>;
					nvidia,out-yres = <0x438>;
				};

				display-timings {
				  1920x1080-p60 {
						clock-frequency = <0x8D9EE20>;//148500000
						hactive = <0x780>;
						vactive = <0x438>;
						hfront-porch = <0x58>;
						hback-porch = <0x94>;
						hsync-len = <0x2c>;
						vfront-porch = <0x4>;
						vback-porch = <0x24>;
						vsync-len = <0x5>;
						nvidia,h-ref-to-sync = <0x1>;
						nvidia,v-ref-to-sync = <0x1>;
					};
                                 };
                           };

we are using a ADV7535 connected on the DSI-0 output which is to achieve the function of dsi transfer to hdmi.
The DSI output is works and I can get video image from the hdmi output of ADV7535.

First problem: We set the video format of DSI output is 1080P60, but video refresh of DSI output can’t reach 60HZ, the pixel clock can’t reach 148500000.
I check the code of kernel and get the reason which leads to pixel clock not 148500000 but 148333326. the reason is the code as follows, this code can be find in the file of dsi.c

static void tegra_dsi_set_dsi_clk(struct tegra_dc *dc,
			struct tegra_dc_dsi_data *dsi, u32 clk)
{
	u32 rm;
	u32 pclk_khz;

	/* Round up to MHz */
	rm = clk % 1000;
	if (rm != 0)
	   clk -= rm;
        
        /* refer to source code */

}

I wonder how to aviod this problem.

Second problem: I modify the dts to set video format of DSI output to 1080P60 and 1080P30 and 1080P25, The DSI output all can works and I can get video image.
but I modify the dts to set video format of DSI output to 1080P50, I can’t get the video image. I wonder how to get the 1080P50 image from DSI.

1920x1080-p50 {
						clock-frequency = <0x8D9EE20>;//148500000
						hactive = <0x780>;
						vactive = <0x438>;
						hfront-porch = <0x210>;
						hback-porch = <0x94>;
						hsync-len = <0x2c>;
						vfront-porch = <0x4>;
						vback-porch = <0x24>;
						vsync-len = <0x5>;
						nvidia,h-ref-to-sync = <0x1>;
						nvidia,v-ref-to-sync = <0x1>;
					};

					1920x1080-p30 {
						clock-frequency = <0x46CF710>;//74250000
						hactive = <0x780>;
						vactive = <0x438>;
						hfront-porch = <0x58>;
						hback-porch = <0x94>;
						hsync-len = <0x2c>;
						vfront-porch = <0x4>;
						vback-porch = <0x24>;
						vsync-len = <0x5>;
						nvidia,h-ref-to-sync = <0x1>;
						nvidia,v-ref-to-sync = <0x1>;
					};
					1920x1080-p25 {
						clock-frequency = <0x46CF710>;//74250000
						hactive = <0x780>;
						vactive = <0x438>;
						hfront-porch = <0x210>;
						hback-porch = <0x94>;
						hsync-len = <0x2c>;
						vfront-porch = <0x4>;
						vback-porch = <0x24>;
						vsync-len = <0x5>;
						nvidia,h-ref-to-sync = <0x1>;
						nvidia,v-ref-to-sync = <0x1>;
					};

Third problem: how to modify the dts to get the 1080I50 image from DSI.

thanks!

Hi meyan,

Why do you say that you cannot get 1920x1080@60 in question 1 and says it works well in quesiont 2? Is it a non-60 result?

Also, 148500000 looks not like a 50fps one.

Please try this

1920x1080-32 {
                            clock-frequency = <162000000>;
                            hactive = <1920>;
                            vactive = <1080>;
                            hfront-porch = <88>;
                            hback-porch = <148>;
                            hsync-len = <44>;
                            vfront-porch = <4>;
                            vback-porch = <36>;
                            vsync-len = <5>;
                            nvidia,h-ref-to-sync = <1>;
                            nvidia,v-ref-to-sync = <1>;
              };

hi
the result is not 60HZ,it is 59.93HZ.

I try this

display-timings {
					1920x1080-32 {
						clock-frequency = <162000000>;
						hactive = <1920>;
						vactive = <1080>;
						hfront-porch = <88>;
						hback-porch = <148>;
						hsync-len = <44>;
						vfront-porch = <4>;
						vback-porch = <36>;
						vsync-len = <5>;
						nvidia,h-ref-to-sync = <1>;
						nvidia,v-ref-to-sync = <1>;
					};
				};

but the result also can’t reach 60HZ and pixel clock also is 148333000 not 148500000.

the boot message as follows, we can see that the nominal-pclk have come up to 162022000.

[    0.195471] platform tegradc.0: domain=ffffffc0fa13d618 allocates as[0]=ffffffc0fa054248
[    0.196048] platform tegradc.0: IOVA linear map 0x00000000c6000000(2a000000)
[    0.474227] tegradc tegradc.0: DT parsed successfully
[    0.474277] tegradc tegradc.0: Display dc.ffffff8000980000 registered with id=0
[    0.474835] tegradc tegradc.0: DSI: HS clock rate is 445500
[    0.475934] tegradc tegradc.0: probed
[    2.601200] tegradc tegradc.0: fb registered
[    2.614518] tegradc tegradc.0: nominal-pclk:162022000 parent:162021093 div:1.0 pclk:162021093 160401780~176603980
[    9.144893] tegradc tegradc.0: nominal-pclk:3333000 parent:9998950 div:3.0 pclk:3332983 3299670~3632970
[   12.587449] tegradc tegradc.0: nominal-pclk:3333000 parent:9998950 div:3.0 pclk:3332983 3299670~3632970

we get the dc->mode.pclk through debug message which we put in the code as follows.

static inline unsigned long tegra_dc_clk_get_rate(struct tegra_dc *dc)
{
    printk(" %s at %d %d \n", __func__, __LINE__, dc->mode.pclk);
#if defined(CONFIG_TEGRA_NVDISPLAY)
	if (!tegra_platform_is_silicon() || !tegra_bpmp_running())
#else
	if (!tegra_platform_is_silicon())
#endif
		return dc->mode.pclk;

	return clk_get_rate(dc->clk);
}

the print message is:

[   12.454283]  tegra_dc_clk_get_rate at 418 148333000

we can get th pixel clock is 148333000 not 148500000.

Hi meyan,

One more question, how do you know that current fps is 59.93? Are you using xrandr?

Do you have 1080p HDMI? Could you try it directly without using DSI as output and see what is the pclk calculation result in tegradc?

hi!
We use the pixel clock to calculate the refresh of video. We have both hdmi output and dsi output on our tx1 board.Hdmi output have no problem. the pixel clock can reach 148500000.

Now I have another serious problem about our dsi output. I set the format of dsi output is 1080P60. The problem is that when i click the mouse on the desktop, the dsi output will occur flash screen which you can see it in the attachment of follows. I shoot video obout this problem, there are two screenin in the video, left screen is the output of dsi which have flash screen; right screen is our debug sereen.

We have put our debug message in the function of tegra_dc_irq which is in the file of dc.c.

static irqreturn_t tegra_dc_irq(int irq, void *ptr)
{
	ktime_t timestamp = ktime_get();
	struct tegra_dc *dc = ptr;
	unsigned long status;
	unsigned long underflow_mask;
	u32 val;
	int need_disable = 0;

#ifndef CONFIG_TEGRA_NVDISPLAY
	if (tegra_platform_is_fpga())
		return IRQ_NONE;
#endif
	mutex_lock(&dc->lock);
	if (!tegra_dc_is_powered(dc)) {
		mutex_unlock(&dc->lock);
		return IRQ_HANDLED;
	}

	tegra_dc_get(dc);

	if (!dc->enabled || !nvhost_module_powered_ext(dc->ndev)) {
		dev_dbg(&dc->ndev->dev, "IRQ when DC not powered!\n");
		status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
		tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
		tegra_dc_put(dc);
		mutex_unlock(&dc->lock);
		return IRQ_HANDLED;
	}

	/* clear all status flags except underflow, save those for the worker */
	status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
	tegra_dc_writel(dc, status & ~ALL_UF_INT(), DC_CMD_INT_STATUS);
	val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
	tegra_dc_writel(dc, val & ~ALL_UF_INT(), DC_CMD_INT_MASK);
    
	/*
	 * Overlays can get thier internal state corrupted during and underflow
	 * condition.  The only way to fix this state is to reset the DC.
	 * if we get 4 consecutive frames with underflows, assume we're
	 * hosed and reset.
	 */
	underflow_mask = status & ALL_UF_INT();

	/* Check underflow */
	if (underflow_mask) {
		dc->underflow_mask |= underflow_mask;
		schedule_delayed_work(&dc->underflow_work,
			msecs_to_jiffies(1));

        printk(" ++++$$$++ %s at %d run here +$$$++ \n", __func__, __LINE__);

	}

	if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE ||
		dc->out->flags & TEGRA_DC_OUT_NVSR_MODE)
		tegra_dc_one_shot_irq(dc, status, timestamp);
	else
		tegra_dc_continuous_irq(dc, status, timestamp);

	if (dc->nvsr)
		tegra_dc_nvsr_irq(dc->nvsr, status);

We find when the flash screen occured ,there are debug messages also occure on our debug screen at the same time.
According to the debug message we guess that there is are underflow occure when i click the mouse.
I wonder how to solve the flash csreen problem.
I would appreciate any help.

thanks!

Hi meyan,

For underflow, please try to use jetson_clock.sh to raise the emc clock.

Could you trace why mode->pclk in tegra_dc_program_mode is that value?

Your nominal-pclk looks different from device tree and I would like to know why. My dts does not have this problem since we are using different mode.

Hi WayneWWW!
I use command as follows and now there are no underflow interupt occure. The output of dsi looks well.thank you.

sudo ${HOME}/jetson_clocks.sh
sudo ${HOME}/jetson_clocks.sh --show

and the show message is as follows.

SOC family:tegra210  Machine:jetson_tx1
Online CPUs: 0-3
CPU Cluster Switching: Disabled
cpu0: Gonvernor=interactive MinFreq=1734000 MaxFreq=1734000 CurrentFreq=1734000
cpu1: Gonvernor=interactive MinFreq=1734000 MaxFreq=1734000 CurrentFreq=1734000
cpu2: Gonvernor=interactive MinFreq=1734000 MaxFreq=1734000 CurrentFreq=1734000
cpu3: Gonvernor=interactive MinFreq=1734000 MaxFreq=1734000 CurrentFreq=1734000
GPU MinFreq=998400000 MaxFreq=998400000 CurrentFreq=998400000
EMC MinFreq=12750000 MaxFreq=1600000000 CurrentFreq=<b>1600000000</b> FreqOverride=1
Can't access Fan!

Hi meyan,

Do you find why your nominal-pclk looks different from device tree?

Hi WayneWWW!
I am sorry for my later reply.
Do you mean the nominal-pclk (162022000) different from the clock-frequency(162000000) of device tree?

Hi WayneWWW!
I am sorry for my later reply.
Do you mean the nominal-pclk (162022000) different from the clock-frequency(162000000) of device tree?

Yes, it should be a value directly from device tree.

Hi WayneWWW!
I trace the mode->pclk in tegra_dc_program_mode just now.
I find mode->pclk is modify in the function of _tegra_dc_set_mode which is called by tegra_dc_set_fb_mode. I put my debug message in this function and find 162022000 appears. The mode->pclk will be processd by this function.

int _tegra_dc_set_mode(struct tegra_dc *dc,
				const struct tegra_dc_mode *mode)
{
	struct tegra_dc_mode new_mode = *mode;
	int yuv_flag = new_mode.vmode & FB_VMODE_YUV_MASK;

	if (yuv_flag == (FB_VMODE_Y420      | FB_VMODE_Y24) ||
	    yuv_flag == (FB_VMODE_Y420_ONLY | FB_VMODE_Y24)) {
		new_mode.h_back_porch /= 2;
		new_mode.h_front_porch /= 2;
		new_mode.h_sync_width /= 2;
		new_mode.h_active /= 2;
		new_mode.pclk /= 2;
	} else if (yuv_flag == (FB_VMODE_Y420 | FB_VMODE_Y30)) {
		new_mode.h_back_porch = (new_mode.h_back_porch * 5) / 8;
		new_mode.h_front_porch = (new_mode.h_front_porch * 5) / 8;
		new_mode.h_sync_width = (new_mode.h_sync_width * 5) / 8;
		new_mode.h_active = (new_mode.h_active * 5) / 8;
		new_mode.pclk = (new_mode.pclk / 8) * 5;
	}

	if (memcmp(&dc->mode, &new_mode, sizeof(dc->mode)) == 0) {
		/* mode is unchanged, just return */
		return 0;
	}

	memcpy(&dc->mode, &new_mode, sizeof(dc->mode));
	dc->mode_dirty = true;

	if (dc->out->type == TEGRA_DC_OUT_RGB)
		panel_sync_rate = tegra_dc_calc_refresh(&new_mode);
	else if (dc->out->type == TEGRA_DC_OUT_DSI)
		panel_sync_rate = dc->out->dsi->rated_refresh_rate * 1000;

	if (dc->out->type == TEGRA_DC_OUT_FAKE_DSIA ||
		dc->out->type == TEGRA_DC_OUT_FAKE_DSIB ||
		dc->out->type == TEGRA_DC_OUT_FAKE_DSI_GANGED) {
		tegra_dsi_init_clock_param(dc);
	}

	/* Update cached mode */
	memcpy(&dc->cached_mode, &dc->mode, sizeof(dc->mode));

	print_mode(dc, &new_mode, __func__);
	dc->frametime_ns = calc_frametime_ns(&new_mode);

    printk(" $$$@@@@@+$$$++ %s at %d %d +$$$++@@@@@@$$$ \n", __func__, __LINE__, new_mode.pclk);

	return 0;
}

I find the value of mode->pclk is calculated by the code as follows which is in the function of tegra_dc_set_fb_mode.

mode.pclk = PICOS2KHZ(fbmode->pixclock) * 1000;

Then mode.pclk become 162022000.

If i modify the clock-frequency = <148500000> in the dts ,there is no different between mode->pclk and nominal-pclk.

I believe the calculation in DSI would cause little difference between the desired value and the real one.

Why do you need a value that is so precise? I believe 59.93HZ. and 60Hz should not influence that much.

hi
I modify the code as follow and now the pixel clock is ok,and get the correct 1080P60 image. Our DSI output will connect to a hdmi_sdi transfer which need a precise pixel clock to recognize the format of image and prodect the corresponding vsync and fsync.

static void tegra_dsi_set_dsi_clk(struct tegra_dc *dc,
			struct tegra_dc_dsi_data *dsi, u32 clk)
{
	u32 rm;
	u32 pclk_khz;

	/* Round up to MHz */
	//rm = clk % 1000;
	//if (rm != 0)
	   //clk -= rm;
        
        /* refer to source code */

}

Hi meyan,

For 1080p50 video, could you try to modify the clock-frequency to 127000000?

Hi meyan,

I would like to know if any converter would hit this error. Why should it needs a precise pclk output? What would happen if not precise?