rockchip-linux/kernel

rk3328 TV encoder

strobo5 opened this issue · 3 comments

They say that on the internet that whatever you do or like, you are never the only one. How about enabling the composite video output on a Rock64 with mainline linux? I feel that a lot of work went into rockchip_drm to be part of mainline Linux, and so little is missing for the TV out! The usual trap.

I copied rockchip_drm_tve.c and related code into stable Linux v6.2.8 (as used by PostmarketOS).
See here:
https://github.com/strobo5/linux/compare/v6.2.8...strobo5:linux:rockchip_drm_tve?expand

I get so far that in Linux it looks like the TV encoder is active, and on the oscilloscope I can see the HSYNC pulses and the image signal for each line. This signal changes when I do kmscube, for example, so the pipeline seems to work in general. But I think VSYNC is missing?! The TV does not display an image.

# dmesg | grep tve
[    0.000000] Kernel command line: console=tty0 console=ttyS2,1500000n8 panic=10 coherent_pool=1M video=TV-1:720x576i@50.00 loglevel=7 PMOS_NO_OUTPUT_REDIRECT  pmos_boot_uuid=073d6741-4df0-4ae2-abd6-989ac0733e22 pmos_root_uuid=01dad8dc-81bb-42f6-88d6-484cc07f556a dyndbg="file rockchip_drm_tve.c +p" dynamic_debug.verbose=1
[    0.022357] dyndbg: dyndbg="file rockchip_drm_tve.c +p"
[    0.022380] dyndbg: query 0: "file rockchip_drm_tve.c +p" mod:*
[    0.082827] platform ff373e00.tve: Fixing up cyclic dependency with ff370000.vop
[    0.739012] rockchip-tve ff373e00.tve: failed to get id cell: -2
[    0.739061] rockchip-tve ff373e00.tve: possible_crtc:1
[    0.739106] rockchip-tve ff373e00.tve: rockchip,rk3328-tve tv encoder probe ok
[    0.739122] rockchip-drm display-subsystem: bound ff373e00.tve (ops rockchip_tve_component_ops)
[    0.746811] rockchip-tve ff373e00.tve: encoder mode set:720x576i
[    0.747563] rockchip-tve ff373e00.tve: tve encoder enable
[    0.747574] rockchip-tve ff373e00.tve: cvbs_set_enable
[    0.747588] rockchip-tve ff373e00.tve: dac enable
[    0.747597] rockchip-tve ff373e00.tve: tve set mode:1
[    0.747608] rockchip-tve ff373e00.tve: PAL MODE
[  333.541737] rockchip-tve ff373e00.tve: tve encoder enable
[  333.541761] rockchip-tve ff373e00.tve: cvbs_set_disable
[  333.541783] rockchip-tve ff373e00.tve: dac disable

I have to disable HDMI in the device tree, or it doesn't seem to work at all.

  • does the vertical sync depend on another clock that is not enabled, or only enabled when the HDMI driver loads (but I disabled it in the device tree)?
  • could there be something wrong with the timing settings in rockchip_drm_tve.c:tve_set_mode()?

I also tried building the kernel from this repo but there were errors and I gave up.

I'm out of clues, any help is appreciated. Some logs are attached. Otherwise, let's enjoy together three lines of kmscube as the analog output signal on the analog scope in the image below.

dmesg_nohdmi_tve_debug.log
dri_0_state.log
drm_info.log
modeprint.log
img1

The vertical synchronization is okay now, I can make out the 50 Hz sync pulses on the oscilloscope.

  • The pixel clock ("dclk") was wrong. A clock MUX selects the source of dclk_lcdc between hdmiphy (from a 24 MHz quartz) and dclk_lcdc_src (from either gpll or cpll). I had a copy-pasted statement in my device tree that forced the use of hdmiphy. This was wrong. Now, dclk_lcdc is coming from the CPLL.
  • Disabling HDMI in the device tree was unnecessary. I was mislead because Linux sometimes disables the CRTC (not sure why; its active property reads 0 then). I can enable it with e.g. modetest -M rockchip -s 42@37:720x576i.

But now the rest of the signal is wrong. The colorburst is overlaid with another signal, and the actual image data seems to be out of sync with the 50 Hz.

I'm out of time and ideas again. Maybe based on this information somebody has a clue what the reason might be.

Attached are the output of cat /sys/kernel/debug/clk/clk_summary and four images:

  • horizontal sync @ 50 Hz, but with a shifted image on the second pulse
  • vertical sync with the broken colorburst, and still sometimes with the sync pulse being 2x wider than usual
  • image on an analog black & white TV: vertical stripe on the left (where the colorburst is corrupt?)
  • image on an analog black & white TV: some text being visible on the screen

clk_summary.log
IMG_20231002_213357_mod
IMG_20231002_214456_shrinked
IMG_20231002_213608
IMG_20231002_213610

I had missed the part of drivers/gpu/drm/rockchip/rockchip_drm_vop.c that sets up the interlacing mode. But I can't get that to work properly.

The way I see it, two different "line flag" interrupts are generated when interlacing is enabled, at lines defined by line_flag_num[0] and line_flag_num[1]. Not sure if LINE_FLAG1_INTR is actually being used or not.

Also, on this VOP version (major 3, minor 8), the vblank interrupt used by rockchip-linux is FS_FIELD_INTR instead of FS_INTR. No idea why. The mainline source always uses FS_INTR.

kmscube now renders at 25 FPS, with the enabled interlacing, so the vblank interrupt might be correct (if this is what kmscube syncs on).

The video output now shows something less broken: the kmscube rendering appears stable. But on the oscilloscope I see the vsync pulse + horizontal scans with image information only every 80 ms. Also the stripe on the left edge persists.
IMG_20231008_171427

I updated my branch of mainline v6.2.8 (see original message) before now giving up.

With some debug output I had noticed that in vop_crtc_atomic_enable() there is a check for vdisplay == 288 and that the actual value was twice (576). And also I had seen it being 288 in vop_plane_atomic_check(). So what's the difference? The former was not using the CRTC timings with the crtc_ prefix which are adjusted for interlaced modes. See strobo5/linux@f5db060.

Now it looks more or less okay, just there is a black vertical stripe on the left edge.