You are not logged in.

#1 2025-02-19 19:04:33

hockinglee
Member
Registered: 2025-02-19
Posts: 4

i915 driver problems on matebook e 2023

i915 driver crash on huawei matebook e 2023(DRR-W56).
it seems gen11_dsi_set_transcoder_timings divide with zero and cause driver failure.

Here is the log:
[   79.593198] [    T559] i915 0000:00:02.0: [drm:mipi_exec_send_packet [i915]] 
[   79.593279] [    T559] i915 0000:00:02.0: [drm:mipi_exec_delay [i915]] 150000 usecs
[   79.692438] [    T493] i915 0000:00:02.0: [drm:intel_tc_port_update_mode [i915]] Port E/TC#2: TC port mode reset (tbt-alt -> disconnected)
[   79.692524] [     T96] i915 0000:00:02.0: [drm:intel_tc_port_update_mode [i915]] Port D/TC#1: TC port mode reset (tbt-alt -> disconnected)
[   79.743552] [    T559] i915 0000:00:02.0: [drm:mipi_exec_send_packet [i915]] 
[   79.744108] [    T559] i915 0000:00:02.0: [drm:mipi_exec_send_packet [i915]] 
[   79.744612] [    T559] i915 0000:00:02.0: [drm:mipi_exec_delay [i915]] 85000 usecs
[   79.830256] [    T559] i915 0000:00:02.0: [drm:mipi_exec_delay [i915]] 35000 usecs
[   79.866163] [    T559] Oops: divide error: 0000 [#1] PREEMPT SMP NOPTI
[   79.866184] [    T559] CPU: 9 UID: 0 PID: 559 Comm: kworker/9:2 Kdump: loaded Tainted: G        W          6.13.2-arch1-1-w56 #1 87ae4100e3781e7b88a99ea0f2b77e481e624103
[   79.866201] [    T559] Tainted: [W]=WARN
[   79.866204] [    T559] Hardware name: HUAWEI DRR-WXX/DRR-WXX-PCB, BIOS 1.29 10/11/2024
[   79.866209] [    T559] Workqueue: events output_poll_execute
[   79.866228] [    T559] RIP: 0010:gen11_dsi_pre_enable+0x17d5/0x1bb0 [i915]
[   79.866802] [    T559] Code: 01 d0 31 d2 41 f7 f3 31 d2 45 69 db e8 03 00 00 89 c7 b8 40 42 0f 00 f7 ff 31 d2 0f af c6 41 f7 f3 89 c6 8d 80 8f 01 00 00 99 <f7> fe 44 01 e8 66 89 44 24 10 e9 1c fa ff ff 41 8b 81 9c 02 00 00
[   79.866809] [    T559] RSP: 0018:ffffa8b900b47948 EFLAGS: 00010202
[   79.866816] [    T559] RAX: 000000000000018f RBX: ffff8ca29708c618 RCX: 0000000000000018
[   79.866822] [    T559] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 00000000000610ee
[   79.866826] [    T559] RBP: 000000000000038b R08: 0000000000000008 R09: ffff8ca2af76a800
[   79.866831] [    T559] R10: 0000000000000a00 R11: 0000000000000fa0 R12: ffff8ca292d5c000
[   79.866836] [    T559] R13: 0000000000000640 R14: 0000000000000001 R15: ffff8ca2af76a800
[   79.866841] [    T559] FS:  0000000000000000(0000) GS:ffff8ca62f880000(0000) knlGS:0000000000000000
[   79.866847] [    T559] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   79.866852] [    T559] CR2: 00007e7a04002258 CR3: 00000002e2222004 CR4: 0000000000f70ef0
[   79.866858] [    T559] PKRU: 55555554
[   79.866862] [    T559] Call Trace:
[   79.866871] [    T559]  <TASK>
[   79.866878] [    T559]  ? __die_body.cold+0x19/0x27
[   79.866892] [    T559]  ? die+0x2e/0x50
[   79.866902] [    T559]  ? do_trap+0xca/0x110
[   79.866911] [    T559]  ? do_error_trap+0x6a/0x90
[   79.866918] [    T559]  ? gen11_dsi_pre_enable+0x17d5/0x1bb0 [i915 0321ec014254c8464342a113fb35d643c93a38c5]
[   79.867435] [    T559]  ? exc_divide_error+0x38/0x50
[   79.867446] [    T559]  ? gen11_dsi_pre_enable+0x17d5/0x1bb0 [i915 0321ec014254c8464342a113fb35d643c93a38c5]
[   79.867944] [    T559]  ? asm_exc_divide_error+0x1a/0x20
[   79.867960] [    T559]  ? gen11_dsi_pre_enable+0x17d5/0x1bb0 [i915 0321ec014254c8464342a113fb35d643c93a38c5]
[   79.868453] [    T559]  ? gen11_dsi_pre_enable+0x10c9/0x1bb0 [i915 0321ec014254c8464342a113fb35d643c93a38c5]
[   79.868945] [    T559]  intel_encoders_pre_enable+0x91/0xb0 [i915 0321ec014254c8464342a113fb35d643c93a38c5]
[   79.869572] [    T559]  hsw_crtc_enable+0x1b9/0x9b0 [i915 0321ec014254c8464342a113fb35d643c93a38c5]
[   79.870198] [    T559]  intel_enable_crtc+0x10c/0x140 [i915 0321ec014254c8464342a113fb35d643c93a38c5]
[   79.870819] [    T559]  skl_commit_modeset_enables+0x2e1/0x5f0 [i915 0321ec014254c8464342a113fb35d643c93a38c5]
[   79.871436] [    T559]  intel_atomic_commit_tail+0x9cc/0x1540 [i915 0321ec014254c8464342a113fb35d643c93a38c5]
[   79.872057] [    T559]  intel_atomic_commit+0x223/0x270 [i915 0321ec014254c8464342a113fb35d643c93a38c5]
[   79.872348] [    T559]  drm_atomic_commit+0xaf/0xe0
[   79.872351] [    T559]  ? __pfx___drm_printfn_info+0x10/0x10
[   79.872354] [    T559]  drm_client_modeset_commit_atomic+0x203/0x250
[   79.872357] [    T559]  drm_client_modeset_commit_locked+0x5a/0x160
[   79.872359] [    T559]  drm_client_modeset_commit+0x25/0x40
[   79.872361] [    T559]  __drm_fb_helper_restore_fbdev_mode_unlocked+0x85/0xd0
[   79.872364] [    T559]  drm_fb_helper_hotplug_event+0xe6/0x100
[   79.872367] [    T559]  intel_fbdev_client_hotplug+0x82/0xf0 [i915 0321ec014254c8464342a113fb35d643c93a38c5]
[   79.872459] [    T559]  drm_client_dev_hotplug+0x9e/0xf0
[   79.872461] [    T559]  output_poll_execute+0x2ad/0x2d0
[   79.872463] [    T559]  process_one_work+0x17b/0x330
[   79.872467] [    T559]  worker_thread+0x2ce/0x3f0
[   79.872469] [    T559]  ? __pfx_worker_thread+0x10/0x10
[   79.872471] [    T559]  kthread+0xcf/0x100
[   79.872473] [    T559]  ? __pfx_kthread+0x10/0x10
[   79.872474] [    T559]  ret_from_fork+0x31/0x50
[   79.872477] [    T559]  ? __pfx_kthread+0x10/0x10
[   79.872478] [    T559]  ret_from_fork_asm+0x1a/0x30
[   79.872482] [    T559]  </TASK>

test with xe driver, it shows `driver xe failed with error -4`.

[   70.805722] simple-framebuffer simple-framebuffer.0: [drm:drm_file_free] comm="modprobe", pid=2291, dev=0xe200, open_count=1
[   70.805733] simple-framebuffer simple-framebuffer.0: [drm:drm_sysfs_connector_remove] [CONNECTOR:36:Unknown-1] removing connector from sysfs
[   70.805859] xe 0000:00:02.0: vgaarb: deactivate vga console
[   70.806080] xe 0000:00:02.0: [drm] Support for SR-IOV is not available
[   70.806082] xe 0000:00:02.0: [drm] Found alderlake_p (device ID 46aa) display version 13.00 stepping D0
[   70.806084] xe 0000:00:02.0: [drm:xe_pci_probe [xe]] ALDERLAKE_P  46aa:000c dgfx:0 gfx:Xe_LP (12.00) media:Xe_M (12.00) display:yes dma_m_s:39 tc:1 gscfi:0 cscfi:0
[   70.806180] xe 0000:00:02.0: [drm:xe_pci_probe [xe]] Stepping = (G:C0, M:C0, B:**)
[   70.806247] xe 0000:00:02.0: [drm:xe_pci_probe [xe]] SR-IOV support: no (mode: none)
[   70.806328] xe 0000:00:02.0: [drm:intel_pch_type [xe]] Found Alder Lake PCH
[   70.809703] xe 0000:00:02.0: [drm] Using GuC firmware from i915/adlp_guc_70.bin version 70.29.2
[   70.811147] xe 0000:00:02.0: [drm:guc_print_params [xe]] GT0: GuC param[ 0] = 0x002513d7
[   70.811252] xe 0000:00:02.0: [drm:guc_print_params [xe]] GT0: GuC param[ 1] = 0x00000000
[   70.811359] xe 0000:00:02.0: [drm:guc_print_params [xe]] GT0: GuC param[ 2] = 0x00000000
[   70.811414] xe 0000:00:02.0: [drm:guc_print_params [xe]] GT0: GuC param[ 3] = 0x00000003
[   70.811464] xe 0000:00:02.0: [drm:guc_print_params [xe]] GT0: GuC param[ 4] = 0x000006c8
[   70.811509] xe 0000:00:02.0: [drm:guc_print_params [xe]] GT0: GuC param[ 5] = 0x46aa000c
[   70.811556] xe 0000:00:02.0: [drm:guc_print_params [xe]] GT0: GuC param[ 6] = 0x00000000
[   70.811601] xe 0000:00:02.0: [drm:guc_print_params [xe]] GT0: GuC param[ 7] = 0x00000000
[   70.811641] xe 0000:00:02.0: [drm:guc_print_params [xe]] GT0: GuC param[ 8] = 0x00000000
[   70.811681] xe 0000:00:02.0: [drm:guc_print_params [xe]] GT0: GuC param[ 9] = 0x00000000
[   70.811725] xe 0000:00:02.0: [drm:guc_print_params [xe]] GT0: GuC param[10] = 0x00000000
[   70.811807] xe 0000:00:02.0: [drm:guc_print_params [xe]] GT0: GuC param[11] = 0x00000000
[   70.811856] xe 0000:00:02.0: [drm:guc_print_params [xe]] GT0: GuC param[12] = 0x00000000
[   70.811903] xe 0000:00:02.0: [drm:guc_print_params [xe]] GT0: GuC param[13] = 0x00000000
[   70.813469] xe 0000:00:02.0: [drm] Using HuC firmware from i915/tgl_huc.bin version 7.9.3
[   70.813580] xe 0000:00:02.0: [drm:xe_wopcm_init [xe]] WOPCM: 2048K
[   70.813696] xe 0000:00:02.0: [drm:xe_wopcm_init [xe]] Calculated GuC WOPCM [592K, 1420K)
[   70.815056] xe 0000:00:02.0: [drm:__xe_guc_upload.isra.0 [xe]] GT0: load still in progress, timeouts = 0, freq = 850MHz (req 850MHz), status = 0x00000072 [0x39/00]
[   70.815442] xe 0000:00:02.0: [drm:__xe_guc_upload.isra.0 [xe]] GT0: load still in progress, timeouts = 0, freq = 850MHz (req 850MHz), status = 0x00000074 [0x3A/00]
[   70.815815] xe 0000:00:02.0: [drm:__xe_guc_upload.isra.0 [xe]] GT0: load still in progress, timeouts = 0, freq = 850MHz (req 850MHz), status = 0x800005EC [0x76/05]
[   70.838292] xe 0000:00:02.0: [drm:__xe_guc_upload.isra.0 [xe]] GT0: init took 23ms, freq = 850MHz (req = 850MHz), before = 850MHz, status = 0x8002F0EC, timeouts = 0
[   70.838708] xe 0000:00:02.0: [drm:xe_guc_ct_enable [xe]] GT0: GuC CT communication channel enabled
[   70.838800] xe 0000:00:02.0: [drm:xe_guc_ct_enable [xe]] GT0: GuC CT safe-mode enabled
[   70.838884] xe 0000:00:02.0: [drm:xe_gt_topology_init [xe]] GT topology dss mask (geometry): 00000000,00000000,0000001f
[   70.838972] xe 0000:00:02.0: [drm:xe_gt_topology_init [xe]] GT topology dss mask (compute):  00000000,00000000,00000000
[   70.839055] xe 0000:00:02.0: [drm:xe_gt_topology_init [xe]] GT topology EU mask per DSS:     0000ffff
[   70.839137] xe 0000:00:02.0: [drm:xe_gt_topology_init [xe]] GT topology EU type:             simd8
[   70.839217] xe 0000:00:02.0: [drm:xe_gt_topology_init [xe]] GT topology L3 bank mask:        00000000,00000077
[   70.839301] xe 0000:00:02.0: [drm:dss_per_group [xe]] GT0: GuC hwconfig cannot provide dss/slice; using typical fallback values
[   70.839408] xe 0000:00:02.0: [drm:intel_opregion_setup [xe]] graphic opregion physical addr: 0x448ec018
[   70.839553] xe 0000:00:02.0: [drm:intel_opregion_setup [xe]] ACPI OpRegion version 2.1.0
[   70.839665] xe 0000:00:02.0: [drm:intel_opregion_setup [xe]] Public ACPI methods supported
[   70.839765] xe 0000:00:02.0: [drm:intel_opregion_setup [xe]] ASLE supported
[   70.839862] xe 0000:00:02.0: [drm:intel_opregion_setup [xe]] ASLE extension supported
[   70.839967] xe 0000:00:02.0: [drm:intel_opregion_setup [xe]] Found valid VBT in ACPI OpRegion (RVDA)
[   70.840096] xe 0000:00:02.0: [drm:intel_dram_detect [xe]] Num qgv points 4
[   70.840239] xe 0000:00:02.0: [drm:intel_dram_detect [xe]] DRAM channels: 4
[   70.840375] xe 0000:00:02.0: [drm:xe_display_init_noirq [xe]] Watermark level 0 adjustment needed: no
[   70.840530] xe 0000:00:02.0: [drm:icl_get_qgv_points.constprop.0 [xe]] QGV 0: DCLK=2401 tRP=24 tRDPRE=20 tRAS=52 tRCD=24 tRC=76
[   70.840695] xe 0000:00:02.0: [drm:icl_get_qgv_points.constprop.0 [xe]] QGV 1: DCLK=4801 tRP=44 tRDPRE=28 tRAS=104 tRCD=44 tRC=148
[   70.840858] xe 0000:00:02.0: [drm:icl_get_qgv_points.constprop.0 [xe]] QGV 2: DCLK=5201 tRP=48 tRDPRE=28 tRAS=112 tRCD=48 tRC=160
[   70.841030] xe 0000:00:02.0: [drm:icl_get_qgv_points.constprop.0 [xe]] QGV 3: DCLK=5201 tRP=48 tRDPRE=28 tRAS=112 tRCD=48 tRC=160
[   70.841183] xe 0000:00:02.0: [drm:icl_get_qgv_points.constprop.0 [xe]] PSF GV 0: CLK=32 
[   70.841309] xe 0000:00:02.0: [drm:icl_get_qgv_points.constprop.0 [xe]] PSF GV 1: CLK=48 
[   70.841436] xe 0000:00:02.0: [drm:icl_get_qgv_points.constprop.0 [xe]] PSF GV 2: CLK=48 
[   70.841551] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW0 / QGV 0: num_planes=0 deratedbw=16956 peakbw: 38416
[   70.841666] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW0 / QGV 1: num_planes=0 deratedbw=23981 peakbw: 76816
[   70.841780] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW0 / QGV 2: num_planes=0 deratedbw=24772 peakbw: 83216
[   70.841892] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW0 / QGV 3: num_planes=0 deratedbw=24772 peakbw: 83216
[   70.842002] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW0 / PSF GV 0: num_planes=0 bw=34133
[   70.842108] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW0 / PSF GV 1: num_planes=0 bw=51200
[   70.842211] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW0 / PSF GV 2: num_planes=0 bw=51200
[   70.842316] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW1 / QGV 0: num_planes=4 deratedbw=21855 peakbw: 38416
[   70.842431] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW1 / QGV 1: num_planes=4 deratedbw=34500 peakbw: 76816
[   70.842532] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW1 / QGV 2: num_planes=4 deratedbw=36108 peakbw: 83216
[   70.842635] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW1 / QGV 3: num_planes=4 deratedbw=36108 peakbw: 83216
[   70.842738] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW1 / PSF GV 0: num_planes=4 bw=34133
[   70.842841] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW1 / PSF GV 1: num_planes=4 bw=51200
[   70.842944] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW1 / PSF GV 2: num_planes=4 bw=51200
[   70.843047] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW2 / QGV 0: num_planes=0 deratedbw=25544 peakbw: 38416
[   70.843151] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW2 / QGV 1: num_planes=0 deratedbw=38000 peakbw: 76816
[   70.843256] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW2 / QGV 2: num_planes=0 deratedbw=38000 peakbw: 83216
[   70.843367] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW2 / QGV 3: num_planes=0 deratedbw=38000 peakbw: 83216
[   70.843476] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW2 / PSF GV 0: num_planes=0 bw=34133
[   70.843581] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW2 / PSF GV 1: num_planes=0 bw=51200
[   70.843688] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW2 / PSF GV 2: num_planes=0 bw=51200
[   70.843796] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW3 / QGV 0: num_planes=0 deratedbw=27900 peakbw: 38416
[   70.843906] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW3 / QGV 1: num_planes=0 deratedbw=38000 peakbw: 76816
[   70.844017] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW3 / QGV 2: num_planes=0 deratedbw=38000 peakbw: 83216
[   70.844129] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW3 / QGV 3: num_planes=0 deratedbw=38000 peakbw: 83216
[   70.844241] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW3 / PSF GV 0: num_planes=0 bw=34133
[   70.844355] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW3 / PSF GV 1: num_planes=0 bw=51200
[   70.844468] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW3 / PSF GV 2: num_planes=0 bw=51200
[   70.844577] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW4 / QGV 0: num_planes=0 deratedbw=29248 peakbw: 38416
[   70.844680] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW4 / QGV 1: num_planes=0 deratedbw=38000 peakbw: 76816
[   70.844784] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW4 / QGV 2: num_planes=0 deratedbw=38000 peakbw: 83216
[   70.844884] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW4 / QGV 3: num_planes=0 deratedbw=38000 peakbw: 83216
[   70.844984] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW4 / PSF GV 0: num_planes=0 bw=34133
[   70.845081] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW4 / PSF GV 1: num_planes=0 bw=51200
[   70.845177] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW4 / PSF GV 2: num_planes=0 bw=51200
[   70.845278] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW5 / QGV 0: num_planes=0 deratedbw=29972 peakbw: 38416
[   70.845386] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW5 / QGV 1: num_planes=0 deratedbw=38000 peakbw: 76816
[   70.845503] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW5 / QGV 2: num_planes=0 deratedbw=38000 peakbw: 83216
[   70.845586] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW5 / QGV 3: num_planes=0 deratedbw=38000 peakbw: 83216
[   70.845667] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW5 / PSF GV 0: num_planes=0 bw=34133
[   70.845741] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW5 / PSF GV 1: num_planes=0 bw=51200
[   70.845811] xe 0000:00:02.0: [drm:tgl_get_bw_info.isra.0 [xe]] BW5 / PSF GV 2: num_planes=0 bw=51200
[   70.845946] xe 0000:00:02.0: [drm:intel_display_device_info_runtime_init [xe]] rawclk rate: 19200 kHz
[   70.846044] xe 0000:00:02.0: probe with driver xe failed with error -4

GPU works on windows, so it's not a hardware problem.

I'm not familiar with graphics driver or VBT things.
I'm searching around, and I guess the driver read some parameter/config from VBT, and maybe huawei coding some magic thing in it, which cause the driver crash.

I recompile the i915 driver, hard-coding the zero value(line_time_us) to work around with `divide error` issue. The driver didn't crash this time, but the screen tears. remote control with nomachine, the gpu works. so I guess the value of hsync_start/hsync_end/hsync_size/vtotal... is corrupted.

Here is the hardware information. Can anybody help me with this issue?

# lspci -v
00:00.0 Host bridge: Intel Corporation Alder Lake Host and DRAM Controller (rev 06)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IOMMU group 2
	Capabilities: <access denied>
	Kernel driver in use: igen6_edac
	Kernel modules: igen6_edac

00:02.0 VGA compatible controller: Intel Corporation Alder Lake-UP4 GT2 [Iris Xe Graphics] (rev 0c) (prog-if 00 [VGA controller])
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IRQ 255, IOMMU group 1
	Memory at 601d000000 (64-bit, non-prefetchable) [size=16M]
	Memory at 4000000000 (64-bit, prefetchable) [size=256M]
	I/O ports at 1000 [size=64]
	Expansion ROM at 000c0000 [virtual] [disabled] [size=128K]
	Capabilities: <access denied>
	Kernel modules: i915, xe

00:04.0 Signal processing controller: Intel Corporation Alder Lake Innovation Platform Framework Processor Participant (rev 06)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IRQ 16, IOMMU group 3
	Memory at 601e140000 (64-bit, non-prefetchable) [size=128K]
	Capabilities: <access denied>
	Kernel driver in use: proc_thermal_pci
	Kernel modules: processor_thermal_device_pci

00:05.0 Multimedia controller: Intel Corporation Alder Lake Imaging Signal Processor (rev 06)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IRQ 16, IOMMU group 0
	Memory at 601c000000 (64-bit, non-prefetchable) [size=16M]
	Capabilities: <access denied>
	Kernel driver in use: intel-ipu6
	Kernel modules: intel_ipu6

00:06.0 PCI bridge: Intel Corporation 12th Gen Core Processor PCI Express x4 Controller #0 (rev 06) (prog-if 00 [Normal decode])
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IRQ 123, IOMMU group 4
	Bus: primary=00, secondary=01, subordinate=29, sec-latency=0
	I/O behind bridge: [disabled] [16-bit]
	Memory behind bridge: 60000000-6c1fffff [size=194M] [32-bit]
	Prefetchable memory behind bridge: 6000000000-601bffffff [size=448M] [32-bit]
	Capabilities: <access denied>
	Kernel driver in use: pcieport

00:07.0 PCI bridge: Intel Corporation Alder Lake-P Thunderbolt 4 PCI Express Root Port #0 (rev 06) (prog-if 00 [Normal decode])
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IRQ 124, IOMMU group 5
	Bus: primary=00, secondary=2a, subordinate=52, sec-latency=0
	I/O behind bridge: 3000-6fff [size=16K] [16-bit]
	Memory behind bridge: 52000000-5e1fffff [size=194M] [32-bit]
	Prefetchable memory behind bridge: 6020000000-603bffffff [size=448M] [32-bit]
	Capabilities: <access denied>
	Kernel driver in use: pcieport

00:08.0 System peripheral: Intel Corporation 12th Gen Core Processor Gaussian & Neural Accelerator (rev 06)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IRQ 255, IOMMU group 6
	Memory at 601e197000 (64-bit, non-prefetchable) [size=4K]
	Capabilities: <access denied>

00:0d.0 USB controller: Intel Corporation Alder Lake-P Thunderbolt 4 USB Controller (rev 06) (prog-if 30 [XHCI])
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, medium devsel, latency 0, IRQ 125, IOMMU group 7
	Memory at 601e170000 (64-bit, non-prefetchable) [size=64K]
	Capabilities: <access denied>
	Kernel driver in use: xhci_hcd

00:0d.2 USB controller: Intel Corporation Alder Lake-P Thunderbolt 4 NHI #0 (rev 06) (prog-if 40 [USB4 Host Interface])
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IRQ 16, IOMMU group 7
	Memory at 601e100000 (64-bit, non-prefetchable) [size=256K]
	Memory at 601e196000 (64-bit, non-prefetchable) [size=4K]
	Capabilities: <access denied>
	Kernel driver in use: thunderbolt
	Kernel modules: thunderbolt

00:10.0 Serial bus controller: Intel Corporation Alder Lake-P Serial IO I2C Controller #2 (rev 01)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IRQ 18, IOMMU group 8
	Memory at 4017000000 (64-bit, non-prefetchable) [size=4K]
	Capabilities: <access denied>
	Kernel driver in use: intel-lpss
	Kernel modules: intel_lpss_pci

00:10.1 Serial bus controller: Intel Corporation Alder Lake-P Serial IO I2C Controller #3 (rev 01)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IRQ 19, IOMMU group 8
	Memory at 4017001000 (64-bit, non-prefetchable) [size=4K]
	Capabilities: <access denied>
	Kernel driver in use: intel-lpss
	Kernel modules: intel_lpss_pci

00:12.0 Serial controller: Intel Corporation Alder Lake-P Integrated Sensor Hub (rev 01) (prog-if 00 [8250])
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IRQ 26, IOMMU group 9
	Memory at 601e160000 (64-bit, non-prefetchable) [size=64K]
	Capabilities: <access denied>
	Kernel driver in use: intel_ish_ipc
	Kernel modules: intel_ish_ipc

00:12.6 Serial bus controller: Intel Corporation Device 51fb (rev 01)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IRQ 39, IOMMU group 9
	Memory at 4017002000 (64-bit, non-prefetchable) [size=4K]
	Capabilities: <access denied>
	Kernel driver in use: intel-lpss
	Kernel modules: intel_lpss_pci

00:14.0 USB controller: Intel Corporation Alder Lake PCH USB 3.2 xHCI Host Controller (rev 01) (prog-if 30 [XHCI])
	Flags: bus master, medium devsel, latency 0, IRQ 133, IOMMU group 10
	Memory at 5e200000 (64-bit, non-prefetchable) [size=64K]
	Capabilities: <access denied>
	Kernel driver in use: xhci_hcd

00:14.2 RAM memory: Intel Corporation Alder Lake PCH Shared SRAM (rev 01)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IOMMU group 10
	Memory at 601e188000 (64-bit, non-prefetchable) [size=16K]
	Memory at 601e192000 (64-bit, non-prefetchable) [size=4K]
	Capabilities: <access denied>

00:14.3 Network controller: Intel Corporation Alder Lake-P PCH CNVi WiFi (rev 01)
	Subsystem: Intel Corporation Dual Band Wi-Fi 6(802.11ax) AX201 160MHz 2x2 [Harrison Peak]
	Flags: bus master, fast devsel, latency 0, IRQ 16, IOMMU group 11
	Memory at 601e184000 (64-bit, non-prefetchable) [size=16K]
	Capabilities: <access denied>
	Kernel driver in use: iwlwifi
	Kernel modules: iwlwifi

00:15.0 Serial bus controller: Intel Corporation Alder Lake PCH Serial IO I2C Controller #0 (rev 01)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IRQ 27, IOMMU group 12
	Memory at 4017003000 (64-bit, non-prefetchable) [size=4K]
	Capabilities: <access denied>
	Kernel driver in use: intel-lpss
	Kernel modules: intel_lpss_pci

00:15.1 Serial bus controller: Intel Corporation Alder Lake PCH Serial IO I2C Controller #1 (rev 01)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IRQ 40, IOMMU group 12
	Memory at 4017004000 (64-bit, non-prefetchable) [size=4K]
	Capabilities: <access denied>
	Kernel driver in use: intel-lpss
	Kernel modules: intel_lpss_pci

00:16.0 Communication controller: Intel Corporation Alder Lake PCH HECI Controller (rev 01)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IRQ 163, IOMMU group 13
	Memory at 601e18f000 (64-bit, non-prefetchable) [size=4K]
	Capabilities: <access denied>
	Kernel driver in use: mei_me
	Kernel modules: mei_me

00:19.0 Serial bus controller: Intel Corporation Alder Lake-P Serial IO I2C Controller #0 (rev 01)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IRQ 31, IOMMU group 14
	Memory at 4017005000 (64-bit, non-prefetchable) [size=4K]
	Capabilities: <access denied>
	Kernel driver in use: intel-lpss
	Kernel modules: intel_lpss_pci

00:19.1 Serial bus controller: Intel Corporation Alder Lake-P Serial IO I2C Controller #1 (rev 01)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IRQ 32, IOMMU group 14
	Memory at 4017006000 (64-bit, non-prefetchable) [size=4K]
	Capabilities: <access denied>
	Kernel driver in use: intel-lpss
	Kernel modules: intel_lpss_pci

00:1f.0 ISA bridge: Intel Corporation Alder Lake LPC Controller (rev 01)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IOMMU group 15

00:1f.3 Multimedia audio controller: Intel Corporation Alder Lake Smart Sound Technology Audio Controller (rev 01)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: fast devsel, IRQ 16, IOMMU group 15
	Memory at 601e180000 (64-bit, non-prefetchable) [size=16K]
	Memory at 601e000000 (64-bit, non-prefetchable) [size=1M]
	Capabilities: <access denied>
	Kernel modules: snd_hda_intel, snd_soc_avs, snd_sof_pci_intel_tgl

00:1f.4 SMBus: Intel Corporation Alder Lake PCH-P SMBus Host Controller (rev 01)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: medium devsel, IRQ 16, IOMMU group 15
	Memory at 601e18c000 (64-bit, non-prefetchable) [size=256]
	I/O ports at efa0 [size=32]
	Kernel driver in use: i801_smbus
	Kernel modules: i2c_i801

00:1f.5 Serial bus controller: Intel Corporation Alder Lake-P PCH SPI Controller (rev 01)
	Subsystem: Wingtech Group(HongKong)Limited Device 3e65
	Flags: bus master, fast devsel, latency 0, IOMMU group 15
	Memory at 50400000 (32-bit, non-prefetchable) [size=4K]
	Kernel driver in use: intel-spi
	Kernel modules: spi_intel_pci

01:00.0 Non-Volatile memory controller: Sandisk Corp WD Black SN770 / PC SN740 256GB / PC SN560 (DRAM-less) NVMe SSD (rev 01) (prog-if 02 [NVM Express])
	Subsystem: Sandisk Corp WD Black SN770 / PC SN740 256GB / PC SN560 (DRAM-less) NVMe SSD
	Flags: bus master, fast devsel, latency 0, IRQ 16, IOMMU group 16
	Memory at 60000000 (64-bit, non-prefetchable) [size=16K]
	Capabilities: <access denied>
	Kernel driver in use: nvme
	Kernel modules: nvme

Offline

#2 2025-02-20 03:12:40

hockinglee
Member
Registered: 2025-02-19
Posts: 4

Re: i915 driver problems on matebook e 2023

divide error occurs on `line_time_us`, which caculate from htotal/bpp/intel_dsi->lane_count.

static void
gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder,
                                 const struct intel_crtc_state *crtc_state)
{
        struct intel_display *display = to_intel_display(encoder);
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
        const struct drm_display_mode *adjusted_mode =
                &crtc_state->hw.adjusted_mode;
        enum port port;
        enum transcoder dsi_trans;
        /* horizontal timings */
        u16 htotal, hactive, hsync_start, hsync_end, hsync_size;
        u16 hback_porch;
        /* vertical timings */
        u16 vtotal, vactive, vsync_start, vsync_end, vsync_shift;
        int mul = 1, div = 1;
        printk("start..............\n");

        /*
         * Adjust horizontal timings (htotal, hsync_start, hsync_end) to account
         * for slower link speed if DSC is enabled.
         *
         * The compression frequency ratio is the ratio between compressed and
         * non-compressed link speeds, and simplifies down to the ratio between
         * compressed and non-compressed bpp.
         */
        if (crtc_state->dsc.compression_enable) {
                mul = fxp_q4_to_int(crtc_state->dsc.compressed_bpp_x16);
                div = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
        }

        hactive = adjusted_mode->crtc_hdisplay;

        if (is_vid_mode(intel_dsi))
                htotal = DIV_ROUND_UP(adjusted_mode->crtc_htotal * mul, div);
        else
                htotal = DIV_ROUND_UP((hactive + 160) * mul, div);

        hsync_start = DIV_ROUND_UP(adjusted_mode->crtc_hsync_start * mul, div);
        hsync_end = DIV_ROUND_UP(adjusted_mode->crtc_hsync_end * mul, div);
        hsync_size  = hsync_end - hsync_start;
        hback_porch = (adjusted_mode->crtc_htotal -
                       adjusted_mode->crtc_hsync_end);
        vactive = adjusted_mode->crtc_vdisplay;

        if (is_vid_mode(intel_dsi)) {
                vtotal = adjusted_mode->crtc_vtotal;
        } else {
                int bpp, line_time_us, byte_clk_period_ns;

                if (crtc_state->dsc.compression_enable)
                        bpp = fxp_q4_to_int(crtc_state->dsc.compressed_bpp_x16);
                else
                        bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);

                byte_clk_period_ns = 1000000 / afe_clk(encoder, crtc_state);
                line_time_us = (htotal * (bpp / 8) * byte_clk_period_ns) / (1000 * intel_dsi->lane_count);
906c905
<               vtotal = vactive + DIV_ROUND_UP(400, line_time_us);
---
>               vtotal = vactive + DIV_ROUND_UP(400, line_time_us ? line_time_us : 400);

Offline

#3 2025-02-20 03:14:48

hockinglee
Member
Registered: 2025-02-19
Posts: 4

Re: i915 driver problems on matebook e 2023

kernel information:

# uname -a
Linux vbe 6.13.2-arch1-1-w56 #2 SMP PREEMPT_DYNAMIC Wed, 19 Feb 2025 17:34:33 +0000 x86_64 GNU/Linux

Offline

#4 2025-02-20 10:27:21

gromit
Administrator
From: Germany
Registered: 2024-02-10
Posts: 1,542
Website

Re: i915 driver problems on matebook e 2023

Could you try the latest version of the 'linux' package from the repo? It has a newer version which potentially could already fix your issue

Offline

#5 2025-07-13 15:22:43

mio-19
Member
Registered: 2025-05-28
Posts: 9

Re: i915 driver problems on matebook e 2023

I also have driver problem on matebook e 2023

Offline

#6 2025-07-13 20:57:55

loqs
Member
Registered: 2014-03-06
Posts: 19,041

Re: i915 driver problems on matebook e 2023

mio-19 wrote:

I also have driver problem on matebook e 2023

You have not provided any information about why you believe the issue is the same as hockinglee's or basic information such as which driver you have an issue with and what kernel version is in use.

Offline

#7 2025-07-16 09:55:35

mio-19
Member
Registered: 2025-05-28
Posts: 9

Re: i915 driver problems on matebook e 2023

loqs wrote:
mio-19 wrote:

I also have driver problem on matebook e 2023

You have not provided any information about why you believe the issue is the same as hockinglee's or basic information such as which driver you have an issue with and what kernel version is in use.

I believe that the issue is the same because I have the same model of machine. I have multiple linux versions tested on this machine and I currently have 6.15.6 and 6.12.36. I have previously followed archwiki to blacklist i915 and tested xe driver. Both i915 and xe resulted in black screen during initramfs hooks and I was unable to see the prompt to ask me to enter the password of my encrypted rootfs. I will need to find a way to collect log when I can only see the password prompt and access the system with nomodeset flag. Information accessible with nomodeset flag might not be enough to debug the problem

Offline

#8 2025-07-16 11:37:23

seth
Member
From: Won't reply 2 private help req
Registered: 2012-09-03
Posts: 77,693

Re: i915 driver problems on matebook e 2023

Information accessible with nomodeset flag might not be enough to debug the problem

As long as a you're not holding the power button to reboot you can access the journal of the previous ("-1") boot:

sudo journalctl -b -1 | curl -F 'file=@-' 0x0.st

Offline

#9 2025-09-17 11:35:09

mio-19
Member
Registered: 2025-05-28
Posts: 9

Re: i915 driver problems on matebook e 2023

I reinstalled the system with unencrypted rootfs so I can see logs now. I also encountered the divide error


Sep 17 21:31:03 mbe kernel: Oops: divide error: 0000 [#1] SMP NOPTI

Sep 17 21:31:03 mbe kernel: Call Trace:
Sep 17 21:31:03 mbe kernel:  <TASK>
Sep 17 21:31:03 mbe kernel:  hsw_crtc_enable+0x25e/0xde0 [i915 c36f076a77767e83877978921438f4264e5b946e]
Sep 17 21:31:03 mbe kernel:  intel_enable_crtc+0xe3/0x110 [i915 c36f076a77767e83877978921438f4264e5b946e]
Sep 17 21:31:03 mbe kernel:  skl_commit_modeset_enables+0x398/0x680 [i915 c36f076a77767e83877978921438f4264e5b946e]
Sep 17 21:31:03 mbe kernel:  ? intel_shared_dpll_verify_disabled+0x54/0x80 [i915 c36f076a77767e83877978921438f4264e5b946e]
Sep 17 21:31:03 mbe kernel:  intel_atomic_commit_tail+0xd1d/0x1760 [i915 c36f076a77767e83877978921438f4264e5b946e]
Sep 17 21:31:03 mbe kernel:  intel_atomic_commit+0x259/0x290 [i915 c36f076a77767e83877978921438f4264e5b946e]
Sep 17 21:31:03 mbe kernel:  drm_atomic_commit+0xc8/0xf0
Sep 17 21:31:03 mbe kernel:  ? __pfx___drm_printfn_info+0x10/0x10
Sep 17 21:31:03 mbe kernel:  drm_client_modeset_commit_atomic+0x338/0x3c0
Sep 17 21:31:03 mbe kernel:  drm_client_modeset_commit_locked+0x47/0x160
Sep 17 21:31:03 mbe kernel:  drm_client_modeset_commit+0x27/0x50
Sep 17 21:31:03 mbe kernel:  __drm_fb_helper_restore_fbdev_mode_unlocked+0x5d/0xb0
Sep 17 21:31:03 mbe kernel:  drm_fb_helper_set_par+0x38/0x40
Sep 17 21:31:03 mbe kernel:  intel_fbdev_set_par+0x2e/0x70 [i915 c36f076a77767e83877978921438f4264e5b946e]
Sep 17 21:31:03 mbe kernel:  fbcon_init+0x3c5/0x5f0
Sep 17 21:31:03 mbe kernel:  visual_init+0xc0/0x120
Sep 17 21:31:03 mbe kernel:  do_bind_con_driver+0x416/0x4d0
Sep 17 21:31:03 mbe kernel:  do_take_over_console+0x3f1/0x430
Sep 17 21:31:03 mbe kernel:  do_fb_registered+0x136/0x240
Sep 17 21:31:03 mbe kernel:  fbcon_fb_registered+0x2c/0x60
Sep 17 21:31:03 mbe kernel:  register_framebuffer+0x50c/0x550
Sep 17 21:31:03 mbe kernel:  __drm_fb_helper_initial_config_and_unlock+0x4f6/0x6d0
Sep 17 21:31:03 mbe kernel:  drm_fbdev_client_hotplug+0x6c/0xb0
Sep 17 21:31:03 mbe kernel:  drm_client_register+0x6c/0xb0
Sep 17 21:31:03 mbe kernel:  drm_fbdev_client_setup+0xb0/0x180
Sep 17 21:31:03 mbe kernel:  drm_client_setup+0x5b/0xc0
Sep 17 21:31:03 mbe kernel:  intel_display_driver_register+0xc4/0x100 [i915 c36f076a77767e83877978921438f4264e5b946e]
Sep 17 21:31:03 mbe kernel:  ? __pfx___drm_printfn_dbg+0x10/0x10
Sep 17 21:31:03 mbe kernel:  ? intel_display_driver_register+0x3d/0x100 [i915 c36f076a77767e83877978921438f4264e5b946e]
Sep 17 21:31:03 mbe kernel:  i915_driver_probe+0x745/0xc40 [i915 c36f076a77767e83877978921438f4264e5b946e]

Offline

#10 2025-09-17 11:45:16

mio-19
Member
Registered: 2025-05-28
Posts: 9

Re: i915 driver problems on matebook e 2023

on 6.17.0-rc6 still the same error

Sep 17 21:40:53 mbe kernel: Oops: divide error: 0000 [#1] SMP NOPTI

Sep 17 21:40:53 mbe kernel: Tainted: [P]=PROPRIETARY_MODULE, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
Sep 17 21:40:53 mbe kernel: Hardware name: HUAWEI DRR-WXX/DRR-WXX-PCB, BIOS 1.29 10/11/2024
Sep 17 21:40:53 mbe kernel: RIP: 0010:gen11_dsi_pre_enable+0x1a25/0x2d60 [i915]
Sep 17 21:40:53 mbe kernel: Code: 01 d0 31 d2 41 f7 f3 31 d2 45 69 db e8 03 00 00 89 c6 b8 40 42 0f 00 f7 fe 31 d2 0f af c1 41 f7 f3 89 c1 8d>
Sep 17 21:40:53 mbe kernel: RSP: 0018:ffffd3d3406ff0d0 EFLAGS: 00010202
Sep 17 21:40:53 mbe kernel: RAX: 000000000000018f RBX: ffff8ab79d450000 RCX: 0000000000000000
Sep 17 21:40:53 mbe kernel: RDX: 0000000000000000 RSI: 00000000000610ee RDI: 0000000000000a00
Sep 17 21:40:53 mbe kernel: RBP: 000000000000038b R08: 0000000000000008 R09: 0000000000000018
Sep 17 21:40:53 mbe kernel: R10: 0000000000000017 R11: 0000000000000fa0 R12: ffff8ab79edaf800
Sep 17 21:40:53 mbe kernel: R13: 0000000000000640 R14: 0000000000000001 R15: 00000001111bbd3c
Sep 17 21:40:53 mbe kernel: FS:  00007f5177c81880(0000) GS:ffff8abb6047d000(0000) knlGS:0000000000000000
Sep 17 21:40:53 mbe kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
Sep 17 21:40:53 mbe kernel: CR2: 00007fbf83f3f340 CR3: 000000010353d001 CR4: 0000000000f72ef0
Sep 17 21:40:53 mbe kernel: PKRU: 55555554
Sep 17 21:40:53 mbe kernel: Call Trace:
Sep 17 21:40:53 mbe kernel:  <TASK>
Sep 17 21:40:53 mbe kernel:  ? combo_pll_enable+0x72/0x230 [i915 5326ce99fe1800ecff544a85a2029786640a642a]
Sep 17 21:40:53 mbe kernel:  hsw_crtc_enable+0x251/0xcc0 [i915 5326ce99fe1800ecff544a85a2029786640a642a]
Sep 17 21:40:53 mbe kernel:  intel_enable_crtc+0xc0/0x130 [i915 5326ce99fe1800ecff544a85a2029786640a642a]
Sep 17 21:40:53 mbe kernel:  skl_commit_modeset_enables+0x333/0x5f0 [i915 5326ce99fe1800ecff544a85a2029786640a642a]
Sep 17 21:40:53 mbe kernel:  intel_atomic_commit_tail+0xc8c/0x1a20 [i915 5326ce99fe1800ecff544a85a2029786640a642a]
Sep 17 21:40:53 mbe kernel:  intel_atomic_commit+0x238/0x280 [i915 5326ce99fe1800ecff544a85a2029786640a642a]
Sep 17 21:40:53 mbe kernel:  drm_atomic_commit+0xae/0xe0
Sep 17 21:40:53 mbe kernel:  ? __pfx___drm_printfn_info+0x10/0x10
Sep 17 21:40:53 mbe kernel:  drm_client_modeset_commit_atomic.constprop.0+0x1c4/0x200
Sep 17 21:40:53 mbe kernel:  drm_client_modeset_commit_locked+0x55/0x190

Offline

#11 2025-09-17 14:37:25

seth
Member
From: Won't reply 2 private help req
Registered: 2012-09-03
Posts: 77,693

Re: i915 driver problems on matebook e 2023

drm.pages.freedesktop.org/intel-docs/how-to-file-i915-bugs.html

https://elixir.bootlin.com/linux/v6.16/ … dsi.c#L848
https://elixir.bootlin.com/linux/v6.16/ … si.c#L1198

Also post the complete journal (for the errors leading up to this) - I assume there's some bogus response from the panel, but nevertheless the driver should™ not run into a DIV0

Can you attach an external display?

---
x-ref, https://bbs.archlinux.org/viewtopic.php?id=283520

Offline

#12 2026-07-09 12:06:05

Gimondii
Member
Registered: 2026-07-09
Posts: 1

Re: i915 driver problems on matebook e 2023

## Update: divide-by-zero crash fixed, but display still doesn't come up (DSI timing mismatch)

**Hardware:** Huawei MateBook E, Intel Core i7, Alder Lake-P (Iris Xe, device ID 46aa), 16GB RAM, integrated OLED panel (2560x1600) on MIPI-DSI
**Kernel tested:** 7.1.3-arch1 (vanilla, custom-built)

### 1. The crash is a real divide-by-zero, and it's fixable with a one-line patch

In `drivers/gpu/drm/i915/display/icl_dsi.c`, inside the DSI branch of the timing-calculation function:

```c
byte_clk_period_ns = 1000000 / afe_clk(encoder, crtc_state);
line_time_us = (htotal * (bpp / 8) * byte_clk_period_ns) / (1000 * intel_dsi->lane_count);
vtotal = vactive + DIV_ROUND_UP(400, line_time_us);
```

`line_time_us` computes to 0 on this panel/VBT combination, causing a kernel Oops (divide error) during `intel_atomic_commit_tail` → `gen11_dsi_set_transcoder_timings`, which crashes i915 before KMS ever comes up (this is why `nomodeset` "fixes" the black screen — it just avoids loading the crashing modeset path).

**Patch (guards the division, does not fix root cause):**
```c
vtotal = vactive + DIV_ROUND_UP(400, line_time_us ? line_time_us : 1);
```

With this patch, i915 loads without crashing and the driver proceeds. Confirmed on both `linux` and `linux-zen` 7.1.3.

### 2. After the crash fix: driver loads, but DSI timings don't match hardware

Immediately after `intel_display_driver_register`, kernel log shows:

```
i915 0000:00:02.0: [drm] *ERROR* [CRTC:151:pipe A] mismatch in hw.pipe_mode.crtc_htotal (expected 4060, found 2720)
i915 0000:00:02.0: [drm] *ERROR* [CRTC:151:pipe A] mismatch in hw.pipe_mode.crtc_hblank_end (expected 4060, found 2720)
i915 0000:00:02.0: [drm] *ERROR* [CRTC:151:pipe A] mismatch in hw.pipe_mode.crtc_hsync_start (expected 3560, found 594)
i915 0000:00:02.0: [drm] *ERROR* [CRTC:151:pipe A] mismatch in hw.pipe_mode.crtc_hsync_end (expected 3572, found 596)
i915 0000:00:02.0: [drm] *ERROR* [CRTC:151:pipe A] mismatch in hw.pipe_mode.crtc_vtotal (expected 1632, found 2000)
i915 0000:00:02.0: [drm] *ERROR* [CRTC:151:pipe A] mismatch in hw.pipe_mode.crtc_vblank_end (expected 1632, found 2000)
i915 0000:00:02.0: [drm] pipe state doesn't match!
WARNING: drivers/gpu/drm/i915/display/intel_modeset_verify.c:225 at intel_modeset_verify_crtc+0x343/0x570 [i915]
```

Note the panel's native resolution (2560x1600) is read correctly (confirmed via `/sys/class/drm/card1-DSI-1/modes`), so this isn't a resolution-detection problem — it's specifically the sync/blanking timings that are wrong.

With `i915.enable_dsb=0 i915.fastboot=0` on the kernel cmdline, this mismatch becomes a WARN instead of a hang — the system boots fully (WiFi, audio, login all work over SSH), it just never displays anything. Without those params, the same mismatch causes `[drm] *ERROR* [CRTC:151:pipe A] flip_done timed out` and the boot appears to hang (it doesn't — it's just stuck retrying the atomic commit).

### 3. Panel power and backlight *do* work correctly — ruled out as the cause

This panel does NOT use the legacy `BLC_PWM_CTL` register (stays 0x0, irrelevant on this platform). Backlight/panel power on this hardware goes through:
- `PP_CONTROL` at offset `0xc7204` — bit 0 (PANEL_POWER_ON) and bit 1 are set by the driver automatically; bit 2 (`EDP_BLC_ENABLE`) can be set manually via `intel_reg write 0xc7204 0xABCD0007` (0xABCD is the register's unlock key) and takes effect (readback confirms).
- `BXT_BLC_PWM` at `0xc8250`/`0xc8254` — enable bit and duty cycle (`0x00017700`) are already set by the driver at boot, no manual intervention needed.
- DPMS reports `On` on `/sys/class/drm/card1-DSI-1/dpms`.

Despite all of the above confirmed "on", the OLED panel shows nothing — not even a flicker when directly writing to `/dev/tty1`. This confirms the black screen is caused by the invalid DSI transcoder timings preventing the panel from ever receiving a valid video stream, not by power sequencing or backlight.

### 4. Relevant code path (for anyone more familiar with the DSI VBT parsing)

Also worth checking (found via an earlier related thread, https://bbs.archlinux.org/viewtopic.php?id=283520) — `icl_native_gpio_set_value()` in `intel_dsi_vbt.c` handles `MIPI_RESET_1/2`, `MIPI_AVDD_EN_1/2`, `MIPI_BKLT_EN_1/2` GPIO sequencing from VBT MIPI sequences. On a different Huawei MateBook (Tiger Lake), commenting out the `MIPI_RESET_*` case reportedly fixed flickering. I haven't tried modifying this yet — happy to test if someone can point to what specifically to change.

### Summary for anyone hitting this

- The divide-by-zero crash is real and the one-liner above fixes it (happy to submit upstream if useful).
- The remaining black-screen issue is a genuine DSI timing mismatch between what VBT computes and what actually gets programmed into hardware — likely a deeper VBT-parsing bug specific to this panel/Huawei firmware, not something fixable by patching around the crash alone.
- Power/backlight sequencing is confirmed NOT the problem on this specific device.

Happy to provide more logs/dumps/test patches if anyone wants to dig further — I have SSH access to the machine even when the display is black, so live debugging is possible.

Offline

#13 Today 11:16:43

hockinglee
Member
Registered: 2025-02-19
Posts: 4

Re: i915 driver problems on matebook e 2023

Follow-up on my own thread, since I finally got to the bottom of it.

The panel now works completely on this machine: cold boot, suspend-to-RAM (S3) and hibernate (S4), with no module parameters at all. The divide-by-zero we started with is fixed upstream by now; everything below is about what comes *after* it, which is where the black screen actually lives.

If you just want a working panel

It is on the AUR as matebook-e-dsi-dkms:

git clone https://aur.archlinux.org/matebook-e-dsi-dkms.git
cd matebook-e-dsi-dkms
makepkg -si

or with an AUR helper,

yay -S matebook-e-dsi-dkms

It vendors the i915 tree, applies the patches below, and builds the module
through DKMS so it survives kernel updates.  It also ships a pacman hook that
rebuilds the initramfs after DKMS has rebuilt the module -- see the note
further down for why that matters.  Reboot afterwards and check:

modinfo -n i915                    # should be .../updates/dkms/i915.ko.zst
cat /sys/module/i915/srcversion    # should equal modinfo -F srcversion i915

One caveat up front: i915 is an in-tree module, so the package vendors a copy
of it from a specific kernel version and that copy has to stay close to the
kernel you run.  Within one x.y series it is fine; across a series bump it will
usually stop building until the package is updated.

The rest of this post is what was actually wrong, for anyone who wants to know
or has a different variant of the machine.

The panel

MateBook E 2023, DRR-W56. 2560x1600 OLED, dual-link DSI + command mode (TE gated) + DSC 1.1, Alder Lake-P (device 46aa), display version 13. The combination matters: almost every bug below only exists because it is dual link, or because it is command mode, or both. i915 has very little exposure to that combination.

What was actually wrong

Five independent problems, each with its own symptom. Guarding the crash only gets you to the first one.

1. DSC configuration wipes out the dual-link splitter -- black screen

intel_dsc_enable() writes DSS_CTL1 as a whole register, starting from zero, which erases the splitter configuration that configure_dual_link_mode() had just programmed. On top of that it sets JOINER_ENABLE because there are two VDSC engines -- but the joiner (two pipes into one stream) and the splitter (one stream fanned out to two links) are mutually exclusive.

firmware  DSS_CTL1 0x80000500   SPLITTER_ENABLE, buffer depth 1280
i915      DSS_CTL1 0x40000000   JOINER_ENABLE,   buffer depth 0

With the splitter off and the buffer depth at zero the transcoder cannot assemble a frame at all. Jani Nikula's 2024 patch "drm/i915/dsc: don't mess up splitter state in joiner or dsc config" fixed the joiner half of this; its own TODO notes dual-link DSI still needs handling, and that never happened. The patch below adds a SPLITTER_STATE mask and uses read-modify-write for the outputs that own those bits.

2. The panel reset runs too late -- snow

The VBT for this panel puts the reset pulse at the head of MIPI_SEQ_INIT_OTP, as a run of DELAY and GPIO elements before the first packet. i915 executes INIT_OTP from gen11_dsi_pre_enable(), by which point the port and the PHY are already up and the transcoder is configured. MIPI requires the peripheral to leave reset with the lanes in LP-11, so the panel comes out of reset into a link that is already being driven and never syncs -- you get a stable, structured, reddish noise pattern rather than a black screen.

The fix splits just that leading run out of the sequence and executes it right after the DDI buffer is enabled. It only does so when the sequence block is version 3 or newer (per-element sizes are needed to walk the sequence) and only when the leading run actually contains a GPIO element, so a VBT that merely starts with a delay is left exactly as it was. vlv_dsi.c shares the sequence executor and is untouched.

3. Periodic frame update is never restored -- stutter, then a dead panel after any modeset

gen11_dsi_is_periodic_cmd_mode() reads DSI_PERIODIC_FRAME_UPDATE_ENABLE from DSI_TRANS_FUNC_CONF, but that bit lives in DSI_CMD_FRMCTL -- so it always returned false. Meanwhile gen11_dsi_deconfigure_trancoder() clears the bit on teardown and nothing ever sets it again. Once the driver has taken the transcoder down, frames stop for good: icl_dsi_frame_update() only issues a request at the end of a pipe update, and that pipe update waits for a vblank which, in command mode, needs a frame to have been pushed first.

Booting on a panel the firmware left running hides this completely, because the frames were already flowing.

4. The command-mode vtotal heuristic does not fit this panel -- a bar sweeping up the screen

In command mode TRANS_VTOTAL is a DSI transfer parameter rather than a video timing, and i915 derives it from a hardcoded 400us constant. That yields 2000 lines where the firmware programs 1666, and driving the panel at the computed value produces a horizontal interference bar sweeping upwards at the beat frequency between the two rates.

I have no derivation for 1666. The patch keeps whatever the firmware left in the register, as long as it is self-consistent, and falls back to the computed value when the register is cold. This is the weakest part of the series and I would not send it upstream as it stands.

5. The slave link's TE pin buffer does not survive S3 -- picture frozen after resume

This one took the longest. After resume the picture freezes: the panel keeps self-refreshing its last frame, every atomic commit ends in "flip_done timed out", and PIPE_FRMCOUNT stops advancing.

The panel is not at fault. UTIL_PIN_CTL bit 16 is the live level of the utility pin, and measuring it shows TE still pulsing at 59.7 Hz after resume with exactly the same duty cycle as before suspending. DSI_TRANS_FUNC_CONF still reads LINK_READY. Every register i915 knows about matches a working boot, bit for bit. Yet the DSI1_TE interrupt never fires, DSI_INTR_IDENT never latches, and command mode therefore never gets a vblank.

Dumping the display register ranges wholesale and diffing one working boot against six different broken states narrowed it to two registers that i915 has never known about:

0x48400  UTIL_PIN_CTL         known to i915
0x48404  ---                  unknown
0x48408  ---                  unknown, 0xc0000000 at boot, 0 after S3
0x48414  AUD_PIN_BUF_CTL      known, bit 31 = AUD_PIN_BUF_ENABLE

0x48404 and 0x48414 share the low bits 0x177117, so that block is a family of pin buffer controls, and 0xc0000000 has the shape of an enable. This lines up with the comment already in gen11_dsi_config_util_pin(): the utility pin carries the TE of the master link, and for dual link the TE that actually gates the transfer comes from the slave link over a separate GPIO. 0x48408 enables that GPIO's buffer. The firmware programs it, i915 never touches it, and S3 clears it.

Writing that one register by hand takes the panel from 0 to 59.7 frames per second with no modeset and without touching the panel at all -- and the other registers that also differ after resume stay at their wrong values while it works. So it is that register alone.

Two things are needed together, and they are two stages of the same path:

  • UTIL_PIN_CTL's ENABLE | DIRECTION_INPUT -- the TE input pin itself. Upstream skips this for dual link, which is fine as long as the firmware's configuration stays put, but S3 clears it to zero.

  • 0x48408 -- that pin's buffer.

The restore is hooked into gen11_dsi_sync_state() rather than the encoder enable path, because with no compositor running the resume turns into a fastset and gen11_dsi_pre_enable() is never called at all. The value is remembered lazily -- whatever non-zero value is seen gets stored, and it is only written back once it has been lost -- so a platform where the register always reads zero never gets a write. The utility pin is only claimed when its mode field is not UTIL_PIN_MODE_PWM, so machines whose backlight drives PWM through that pin (BXT-style backlight controller 1) are left alone.

The patch

Against i915's display code; built and tested on Arch's linux 7.2.2. Zero module parameters.

diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index a549f1f..5976902 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -868,6 +868,27 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder,
 		if (ret)
 			drm_err(display->drm, "DSI link not ready\n");
 	}
+
+	/*
+	 * Restore periodic frame update if the firmware was using it.
+	 *
+	 * gen11_dsi_deconfigure_trancoder() clears this bit on teardown but
+	 * nothing ever sets it, so once the driver has taken the transcoder
+	 * down the frames stop for good: icl_dsi_frame_update() only issues a
+	 * request at the end of a pipe update, and that pipe update waits for
+	 * a vblank which, in command mode, needs a frame to have been pushed.
+	 *
+	 * Keying this off what the firmware left behind leaves panels that
+	 * are driven from their own TE untouched.
+	 *
+	 * As the firmware does, enable it on DSI0 only, even for dual link.
+	 */
+	if (is_cmd_mode(intel_dsi) && intel_dsi->periodic_cmd_mode) {
+		port = (intel_dsi->ports & BIT(PORT_A)) ? PORT_A : PORT_B;
+
+		intel_de_rmw(display, DSI_CMD_FRMCTL(port), 0,
+			     DSI_PERIODIC_FRAME_UPDATE_ENABLE);
+	}
 }
 
 static void
@@ -978,11 +999,43 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder,
 				       TRANS_HSYNC(display, dsi_trans),
 				       HSYNC_START(hsync_start - 1) | HSYNC_END(hsync_end - 1));
 		}
+	} else if (intel_dsi->cmd_mode_timings.valid) {
+		/*
+		 * Not programmed at all in command mode, so after a
+		 * suspend/resume cycle these read back as zero.  Put the
+		 * firmware values back.
+		 */
+		for_each_dsi_port(port, intel_dsi->ports) {
+			dsi_trans = dsi_port_to_transcoder(port);
+			intel_de_write(display, TRANS_HSYNC(display, dsi_trans),
+				       intel_dsi->cmd_mode_timings.hsync);
+		}
 	}
 
 	/* program TRANS_VTOTAL register */
 	for_each_dsi_port(port, intel_dsi->ports) {
 		dsi_trans = dsi_port_to_transcoder(port);
+		/*
+		 * In command mode TRANS_VTOTAL is a DSI transfer parameter
+		 * rather than a video timing, and the computed value does
+		 * not match what this panel needs: the formula yields 2000
+		 * lines where the firmware programs 1666, and driving the
+		 * panel at the computed value tears the picture - a bar
+		 * sweeping up the screen at the beat frequency between the
+		 * two rates.
+		 *
+		 * There is no known derivation for the firmware's value, so
+		 * keep whatever it left in the register as long as it is
+		 * self-consistent, and only fall back to the computed value
+		 * when the register is cold.
+		 */
+		if (is_cmd_mode(intel_dsi) &&
+		    intel_dsi->cmd_mode_timings.valid) {
+			u32 fw = intel_dsi->cmd_mode_timings.vtotal;
+
+			vtotal = REG_FIELD_GET(VTOTAL_MASK, fw) + 1;
+		}
+
 		/*
 		 * FIXME: Programming this by assuming progressive mode, since
 		 * non-interlaced info from VBT is not saved inside
@@ -1007,6 +1060,12 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder,
 				       TRANS_VSYNC(display, dsi_trans),
 				       VSYNC_START(vsync_start - 1) | VSYNC_END(vsync_end - 1));
 		}
+	} else if (intel_dsi->cmd_mode_timings.valid) {
+		for_each_dsi_port(port, intel_dsi->ports) {
+			dsi_trans = dsi_port_to_transcoder(port);
+			intel_de_write(display, TRANS_VSYNC(display, dsi_trans),
+				       intel_dsi->cmd_mode_timings.vsync);
+		}
 	}
 
 	/*
@@ -1107,6 +1166,67 @@ static void gen11_dsi_setup_timeouts(struct intel_encoder *encoder,
 	}
 }
 
+/*
+ * Undocumented pin buffer control sitting between UTIL_PIN_CTL (0x48400) and
+ * AUD_PIN_BUF_CTL (0x48414); i915 has never known about it.
+ *
+ * util pin carries the TE of the master link, but on a dual link panel the TE
+ * that actually gates the transfer comes from the slave link over a separate
+ * GPIO, and this register enables that pin's buffer.  The firmware programs
+ * it, i915 never touches it, and it does not survive S3.  Once it reads zero
+ * the TE still pulses on the pin -- UTIL_PIN_CTL bit 16 keeps toggling at
+ * 59.7 Hz -- but it never reaches the DSI1_TE interrupt, so command mode
+ * never gets a vblank, every commit times out, and the picture is frozen with
+ * the panel happily self refreshing its last frame.
+ *
+ * Writing this one register by hand takes the panel from 0 to 59.7 frames per
+ * second with no modeset and without touching the panel at all, which is what
+ * pinned it down.
+ */
+#define DSI_PIN_BUF_CTL		_MMIO(0x48408)
+
+/*
+ * Remember whatever non-zero value is found here and put it back when it has
+ * been lost.  Sampling lazily rather than snapshotting at init avoids having
+ * to know when the register first becomes readable, and platforms where it
+ * always reads zero never get a write.
+ */
+static void gen11_dsi_restore_pin_buf_ctl(struct intel_encoder *encoder)
+{
+	struct intel_display *display = to_intel_display(encoder);
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
+	u32 val;
+
+	/*
+	 * Only command mode is known to depend on this; a video mode panel
+	 * does not gate its transfer on TE at all, so leave it alone.
+	 */
+	if (!is_cmd_mode(intel_dsi))
+		return;
+
+	val = intel_de_read(display, DSI_PIN_BUF_CTL);
+
+	if (val) {
+		if (val != intel_dsi->pin_buf_ctl) {
+			drm_dbg_kms(display->drm,
+				    "[ENCODER:%d:%s] DSI_PIN_BUF_CTL is 0x%08x\n",
+				    encoder->base.base.id, encoder->base.name,
+				    val);
+			intel_dsi->pin_buf_ctl = val;
+		}
+		return;
+	}
+
+	if (!intel_dsi->pin_buf_ctl)
+		return;
+
+	drm_info(display->drm,
+		 "[ENCODER:%d:%s] restoring DSI_PIN_BUF_CTL 0x00000000 -> 0x%08x\n",
+		 encoder->base.base.id, encoder->base.name,
+		 intel_dsi->pin_buf_ctl);
+	intel_de_write(display, DSI_PIN_BUF_CTL, intel_dsi->pin_buf_ctl);
+}
+
 static void gen11_dsi_config_util_pin(struct intel_encoder *encoder,
 				      bool enable)
 {
@@ -1119,8 +1239,36 @@ static void gen11_dsi_config_util_pin(struct intel_encoder *encoder,
 	 * for dual link/DSI1 TE is from slave DSI1
 	 * through GPIO.
 	 */
-	if (is_vid_mode(intel_dsi) || (intel_dsi->ports & BIT(PORT_B)))
+	/*
+	 * The comment above says TE comes from the slave DSI1 over a GPIO for
+	 * dual link, so UTIL_PIN is not configured in that case.  On this
+	 * panel that leaves no TE input at all once the driver has taken the
+	 * transcoder down: the transfer is TE gated (CMD_MODE_TE_GATE), so
+	 * without TE the transcoder never pushes a frame, and after a
+	 * suspend/resume cycle the picture freezes.  Whatever the firmware
+	 * set up is gone by then.
+	 *
+	 * Configure it for command mode regardless of the port.
+	 *
+	 * The pin is shared, though: a BXT style backlight drives PWM through
+	 * it when the panel uses controller 1 (intel_backlight.c), and
+	 * assert_can_enable_dc6() warns when it is enabled in PWM mode.  The
+	 * mode field survives a disable, which only clears UTIL_PIN_ENABLE, so
+	 * it is a reliable marker of who owns the pin.  Leave it alone when
+	 * somebody else does.
+	 */
+	if (is_vid_mode(intel_dsi))
+		return;
+
+	if ((intel_de_read(display, UTIL_PIN_CTL) & UTIL_PIN_MODE_MASK) ==
+	    UTIL_PIN_MODE_PWM) {
+		drm_dbg_kms(display->drm,
+			    "utility pin is in PWM mode, not using it for TE\n");
 		return;
+	}
+
+	if (enable)
+		gen11_dsi_restore_pin_buf_ctl(encoder);
 
 	tmp = intel_de_read(display, UTIL_PIN_CTL);
 
@@ -1137,6 +1285,8 @@ static void
 gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder,
 			      const struct intel_crtc_state *crtc_state)
 {
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
+
 	/* step 4a: power up all lanes of the DDI used by DSI */
 	gen11_dsi_power_up_lanes(encoder);
 
@@ -1152,6 +1302,14 @@ gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder,
 	/* enable DDI buffer */
 	gen11_dsi_enable_ddi_buffer(encoder);
 
+	/*
+	 * The lanes are now driven to LP-11 and the transcoder is not yet
+	 * configured, which is where the panel has to leave reset.  INIT_OTP
+	 * itself runs later, with this leading block skipped.
+	 */
+	if (is_cmd_mode(intel_dsi))
+		intel_dsi_vbt_exec_reset_block(intel_dsi);
+
 	gen11_dsi_gate_clocks(encoder);
 
 	gen11_dsi_setup_timings(encoder, crtc_state);
@@ -1195,7 +1353,10 @@ static void gen11_dsi_powerup_panel(struct intel_encoder *encoder)
 				"error setting max return pkt size%d\n", tmp);
 	}
 
-	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_INIT_OTP);
+	if (is_cmd_mode(intel_dsi))
+		intel_dsi_vbt_exec_init_otp(intel_dsi);
+	else
+		intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_INIT_OTP);
 
 	/* ensure all panel commands dispatched before enabling transcoder */
 	wait_for_cmds_dispatched_to_panel(encoder);
@@ -1304,6 +1465,40 @@ static void gen11_dsi_enable(struct intel_atomic_state *state,
 
 	intel_panel_prepare(crtc_state, conn_state);
 
+	/*
+	 * Kick off the first frame.  Periodic frame update is enabled by now,
+	 * but the transcoder only starts pushing once it has been asked for a
+	 * frame at least once, and the driver has no other way to get there:
+	 * icl_dsi_frame_update() runs at the end of a pipe update, and that
+	 * pipe update waits for a vblank which will not arrive until a frame
+	 * has been pushed.
+	 *
+	 * Taking over a panel the firmware left running hides this, since the
+	 * frames were already flowing.  It shows up after a suspend/resume
+	 * cycle, where the picture freezes and only advances by one frame
+	 * every flip_done timeout.
+	 */
+	if (is_cmd_mode(intel_dsi) && intel_dsi->periodic_cmd_mode) {
+		struct intel_display *d = to_intel_display(encoder);
+		enum port p = (intel_dsi->ports & BIT(PORT_A)) ? PORT_A : PORT_B;
+		u32 before = intel_de_read(d, DSI_CMD_FRMCTL(p));
+		int i;
+
+		intel_de_rmw(d, DSI_CMD_FRMCTL(p), 0, DSI_FRAME_UPDATE_REQUEST);
+
+		for (i = 0; i < 50; i++) {
+			if (!(intel_de_read(d, DSI_CMD_FRMCTL(p)) &
+			      DSI_FRAME_UPDATE_REQUEST))
+				break;
+			msleep(1);
+		}
+
+		drm_dbg_kms(d->drm,
+			    "cmd mode: kicked frame update on port %c after %d ms, DSI_CMD_FRMCTL 0x%08x -> 0x%08x\n",
+			    port_name(p), i, before,
+			    intel_de_read(d, DSI_CMD_FRMCTL(p)));
+	}
+
 	intel_crtc_vblank_on(crtc_state);
 }
 
@@ -1544,16 +1739,18 @@ static void gen11_dsi_get_timings(struct intel_encoder *encoder,
 static bool gen11_dsi_is_periodic_cmd_mode(struct intel_dsi *intel_dsi)
 {
 	struct intel_display *display = to_intel_display(&intel_dsi->base);
-	enum transcoder dsi_trans;
+	enum port port;
 	u32 val;
 
-	if (intel_dsi->ports == BIT(PORT_B))
-		dsi_trans = TRANSCODER_DSI_1;
-	else
-		dsi_trans = TRANSCODER_DSI_0;
+	port = (intel_dsi->ports & BIT(PORT_A)) ? PORT_A : PORT_B;
 
-	val = intel_de_read(display, DSI_TRANS_FUNC_CONF(dsi_trans));
-	return (val & DSI_PERIODIC_FRAME_UPDATE_ENABLE);
+	/*
+	 * DSI_PERIODIC_FRAME_UPDATE_ENABLE lives in DSI_CMD_FRMCTL, not in
+	 * DSI_TRANS_FUNC_CONF; reading the latter made this always return
+	 * false.
+	 */
+	val = intel_de_read(display, DSI_CMD_FRMCTL(port));
+	return val & DSI_PERIODIC_FRAME_UPDATE_ENABLE;
 }
 
 static void gen11_dsi_get_cmd_mode_config(struct intel_dsi *intel_dsi,
@@ -1588,8 +1785,50 @@ static void gen11_dsi_get_config(struct intel_encoder *encoder,
 	if (is_cmd_mode(intel_dsi))
 		gen11_dsi_get_cmd_mode_config(intel_dsi, pipe_config);
 
-	if (gen11_dsi_is_periodic_cmd_mode(intel_dsi))
+	if (is_cmd_mode(intel_dsi) && !intel_dsi->cmd_mode_timings.valid) {
+		struct intel_display *display = to_intel_display(encoder);
+		enum transcoder dsi_trans =
+			dsi_port_to_transcoder(ffs(intel_dsi->ports) - 1);
+		u32 vtotal = intel_de_read(display,
+					   TRANS_VTOTAL(display, dsi_trans));
+
+		/*
+		 * Snapshot the transfer timings the firmware left behind, but
+		 * only while they are still there: this runs at takeover, and
+		 * after a suspend/resume cycle the registers have been through
+		 * the driver's own teardown and no longer hold them.
+		 */
+		if (REG_FIELD_GET(VACTIVE_MASK, vtotal) + 1 ==
+		    pipe_config->hw.adjusted_mode.crtc_vdisplay &&
+		    REG_FIELD_GET(VTOTAL_MASK, vtotal) + 1 >
+		    REG_FIELD_GET(VACTIVE_MASK, vtotal) + 1) {
+			intel_dsi->cmd_mode_timings.hsync =
+				intel_de_read(display,
+					      TRANS_HSYNC(display, dsi_trans));
+			intel_dsi->cmd_mode_timings.vsync =
+				intel_de_read(display,
+					      TRANS_VSYNC(display, dsi_trans));
+			intel_dsi->cmd_mode_timings.vtotal = vtotal;
+			intel_dsi->cmd_mode_timings.valid = true;
+
+			drm_dbg_kms(display->drm,
+				    "cmd mode: firmware timings HSYNC 0x%08x VSYNC 0x%08x VTOTAL 0x%08x\n",
+				    intel_dsi->cmd_mode_timings.hsync,
+				    intel_dsi->cmd_mode_timings.vsync,
+				    intel_dsi->cmd_mode_timings.vtotal);
+		}
+	}
+
+	if (gen11_dsi_is_periodic_cmd_mode(intel_dsi)) {
 		pipe_config->mode_flags |= I915_MODE_FLAG_DSI_PERIODIC_CMD_MODE;
+
+		/*
+		 * Remember that the firmware was using periodic frame update,
+		 * so gen11_dsi_configure_transcoder() can put it back after
+		 * the transcoder has been taken down.
+		 */
+		intel_dsi->periodic_cmd_mode = true;
+	}
 }
 
 static void gen11_dsi_sync_state(struct intel_encoder *encoder,
@@ -1599,6 +1838,13 @@ static void gen11_dsi_sync_state(struct intel_encoder *encoder,
 	struct intel_crtc *intel_crtc;
 	enum pipe pipe;
 
+	/*
+	 * Before the crtc_state check: this runs after hardware readout on both
+	 * boot and resume, and unlike the encoder enable hooks it is reached
+	 * even when the resume turns into a fastset.
+	 */
+	gen11_dsi_restore_pin_buf_ctl(encoder);
+
 	if (!crtc_state)
 		return;
 
diff --git a/drivers/gpu/drm/i915/display/intel_dsi.h b/drivers/gpu/drm/i915/display/intel_dsi.h
index 9fcdabb..d19a94b 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi.h
+++ b/drivers/gpu/drm/i915/display/intel_dsi.h
@@ -77,6 +77,31 @@ struct intel_dsi {
 	 */
 	enum mipi_dsi_pixel_format pixel_format;
 
+	/*
+	 * Set at hardware readout when the firmware had periodic frame update
+	 * enabled, so gen11_dsi_configure_transcoder() can restore it.
+	 */
+	bool periodic_cmd_mode;
+
+	/*
+	 * Last non-zero value seen in DSI_PIN_BUF_CTL, remembered so that it
+	 * can be put back after a suspend/resume cycle clears it.
+	 * See gen11_dsi_restore_pin_buf_ctl().
+	 */
+	u32 pin_buf_ctl;
+
+	/*
+	 * The command mode transfer timings the firmware programmed, taken at
+	 * hardware readout while they are still in the registers.  See
+	 * gen11_dsi_set_transcoder_timings().
+	 */
+	struct {
+		bool valid;
+		u32 hsync;
+		u32 vsync;
+		u32 vtotal;
+	} cmd_mode_timings;
+
 	/* NON_BURST_SYNC_PULSE, NON_BURST_SYNC_EVENTS, or BURST_MODE */
 	int video_mode;
 
diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
index fe12041..e6e6a86 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
+++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
@@ -615,11 +615,37 @@ static const char *sequence_name(enum mipi_seq seq_id)
 	return "(unknown)";
 }
 
+/*
+ * The VBT of a command mode panel can put the reset pulse at the head of
+ * INIT_OTP, as a run of DELAY and GPIO elements before the first packet.
+ * i915 executes INIT_OTP from gen11_dsi_pre_enable(), by which point the
+ * port and the PHY are already up and the transcoder is configured - the
+ * panel comes out of reset into a link that is being driven and never
+ * syncs.
+ *
+ * MIPI requires the peripheral to leave reset with the lanes in LP-11, so
+ * the reset block has to run once the DDI buffer is enabled but before the
+ * transcoder is configured.  Split it out of the sequence so it can.
+ */
+enum mipi_seq_part {
+	MIPI_SEQ_PART_ALL = 0,
+	MIPI_SEQ_PART_RESET,	/* the leading DELAY/GPIO run only */
+	MIPI_SEQ_PART_REST,	/* everything after it */
+};
+
+static bool mipi_elem_is_reset_block(u8 operation_byte)
+{
+	return operation_byte == MIPI_SEQ_ELEM_DELAY ||
+	       operation_byte == MIPI_SEQ_ELEM_GPIO;
+}
+
 static void intel_dsi_vbt_exec(struct intel_dsi *intel_dsi,
-			       enum mipi_seq seq_id)
+			       enum mipi_seq seq_id,
+			       enum mipi_seq_part part)
 {
 	struct intel_display *display = to_intel_display(&intel_dsi->base);
 	struct intel_connector *connector = intel_dsi->attached_connector;
+	bool in_reset_block = true;
 	const u8 *data;
 	fn_mipi_elem_exec mipi_elem_exec;
 
@@ -633,8 +659,9 @@ static void intel_dsi_vbt_exec(struct intel_dsi *intel_dsi,
 
 	drm_WARN_ON(display->drm, *data != seq_id);
 
-	drm_dbg_kms(display->drm, "Starting MIPI sequence %d - %s\n",
-		    seq_id, sequence_name(seq_id));
+	if (part != MIPI_SEQ_PART_RESET)
+		drm_dbg_kms(display->drm, "Starting MIPI sequence %d - %s\n",
+			    seq_id, sequence_name(seq_id));
 
 	/* Skip Sequence Byte. */
 	data++;
@@ -656,6 +683,22 @@ static void intel_dsi_vbt_exec(struct intel_dsi *intel_dsi,
 		if (connector->panel.vbt.dsi.seq_version >= 3)
 			operation_size = *data++;
 
+		/*
+		 * The reset block is the run of DELAY/GPIO elements at the
+		 * head of the sequence, up to the first element of any
+		 * other kind.
+		 */
+		if (in_reset_block && !mipi_elem_is_reset_block(operation_byte))
+			in_reset_block = false;
+
+		if (part == MIPI_SEQ_PART_RESET && !in_reset_block)
+			return;
+
+		if (part == MIPI_SEQ_PART_REST && in_reset_block) {
+			data += operation_size;
+			continue;
+		}
+
 		if (mipi_elem_exec) {
 			const u8 *next = data + operation_size;
 
@@ -683,6 +726,66 @@ static void intel_dsi_vbt_exec(struct intel_dsi *intel_dsi,
 	}
 }
 
+/*
+ * Splitting the sequence requires the per element size, which only exists
+ * from sequence block version 3 on. On older VBTs leave INIT_OTP alone:
+ * intel_dsi_vbt_exec_reset_block() does nothing and
+ * intel_dsi_vbt_exec_init_otp() runs the whole sequence in place, which is
+ * what the driver did before.
+ */
+static bool intel_dsi_vbt_can_split(struct intel_dsi *intel_dsi)
+{
+	struct intel_connector *connector = intel_dsi->attached_connector;
+	const u8 *data;
+
+	/* Splitting needs the per element size, added in version 3. */
+	if (connector->panel.vbt.dsi.seq_version < 3)
+		return false;
+
+	data = connector->panel.vbt.dsi.sequence[MIPI_SEQ_INIT_OTP];
+	if (!data)
+		return false;
+
+	data++;		/* sequence byte */
+	data += 4;	/* size of sequence */
+
+	/*
+	 * Only split when the leading run actually contains a GPIO element,
+	 * that is, when there is a panel reset in there to move.  A sequence
+	 * that merely starts with a delay is left exactly as it was.
+	 */
+	while (*data != MIPI_SEQ_ELEM_END) {
+		u8 operation_byte = *data++;
+		u8 operation_size = *data++;
+
+		if (operation_byte == MIPI_SEQ_ELEM_GPIO)
+			return true;
+		if (operation_byte != MIPI_SEQ_ELEM_DELAY)
+			return false;
+
+		data += operation_size;
+	}
+
+	return false;
+}
+
+/* Run only the leading DELAY/GPIO run of INIT_OTP - the panel reset. */
+void intel_dsi_vbt_exec_reset_block(struct intel_dsi *intel_dsi)
+{
+	if (!intel_dsi_vbt_can_split(intel_dsi))
+		return;
+
+	intel_dsi_vbt_exec(intel_dsi, MIPI_SEQ_INIT_OTP, MIPI_SEQ_PART_RESET);
+}
+
+/* Run INIT_OTP with that leading run skipped, if it was run separately. */
+void intel_dsi_vbt_exec_init_otp(struct intel_dsi *intel_dsi)
+{
+	intel_dsi_vbt_exec(intel_dsi, MIPI_SEQ_INIT_OTP,
+			   intel_dsi_vbt_can_split(intel_dsi) ?
+			   MIPI_SEQ_PART_REST : MIPI_SEQ_PART_ALL);
+}
+
 void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi,
 				 enum mipi_seq seq_id)
 {
@@ -691,7 +794,7 @@ void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi,
 	if (seq_id == MIPI_SEQ_BACKLIGHT_ON && intel_dsi->gpio_backlight)
 		gpiod_set_value_cansleep(intel_dsi->gpio_backlight, 1);
 
-	intel_dsi_vbt_exec(intel_dsi, seq_id);
+	intel_dsi_vbt_exec(intel_dsi, seq_id, MIPI_SEQ_PART_ALL);
 
 	if (seq_id == MIPI_SEQ_POWER_OFF && intel_dsi->gpio_panel)
 		gpiod_set_value_cansleep(intel_dsi->gpio_panel, 0);
diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.h b/drivers/gpu/drm/i915/display/intel_dsi_vbt.h
index 3462fcc..5adb979 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.h
+++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.h
@@ -15,6 +15,8 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id);
 void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi, bool panel_is_on);
 void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi,
 				 enum mipi_seq seq_id);
+void intel_dsi_vbt_exec_reset_block(struct intel_dsi *intel_dsi);
+void intel_dsi_vbt_exec_init_otp(struct intel_dsi *intel_dsi);
 void intel_dsi_log_params(struct intel_dsi *intel_dsi);
 
 #endif /* __INTEL_DSI_VBT_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 8f06c3a..dda3203 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -888,7 +888,16 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
 	dss_ctl2_val |= VDSC0_ENABLE;
 	if (vdsc_instances_per_pipe > 1) {
 		dss_ctl2_val |= VDSC1_ENABLE;
-		dss_ctl1_val |= JOINER_ENABLE;
+
+		/*
+		 * JOINER and SPLITTER are mutually exclusive. Dual link DSI
+		 * uses the splitter (one stream fanned out to two links),
+		 * which is not the same thing as the joiner (two pipes fed
+		 * into one stream), so two VDSC engines must not imply the
+		 * joiner here.
+		 */
+		if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
+			dss_ctl1_val |= JOINER_ENABLE;
 	}
 
 	if (vdsc_instances_per_pipe > 2) {
@@ -908,8 +917,31 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
 		if (intel_crtc_is_bigjoiner_primary(crtc_state))
 			dss_ctl1_val |= PRIMARY_BIG_JOINER_ENABLE;
 	}
-	intel_de_write(display, dss_ctl1_reg(crtc, crtc_state->cpu_transcoder), dss_ctl1_val);
-	intel_de_write(display, dss_ctl2_reg(crtc, crtc_state->cpu_transcoder), dss_ctl2_val);
+	/*
+	 * The splitter is programmed before this function runs, by
+	 * configure_dual_link_mode() for dual link DSI and by
+	 * intel_ddi_mso_configure() for eDP MSO, both from the encoder
+	 * pre_enable hook. Writing the whole register here would wipe that
+	 * out, so preserve those bits for the outputs that own them, and
+	 * keep clearing them for everyone else.
+	 */
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) ||
+	    crtc_state->splitter.enable) {
+		intel_de_rmw(display,
+			     dss_ctl1_reg(crtc, crtc_state->cpu_transcoder),
+			     ~(u32)SPLITTER_STATE, dss_ctl1_val);
+		intel_de_rmw(display,
+			     dss_ctl2_reg(crtc, crtc_state->cpu_transcoder),
+			     ~(u32)RIGHT_DL_BUF_TARGET_DEPTH_MASK,
+			     dss_ctl2_val);
+	} else {
+		intel_de_write(display,
+			       dss_ctl1_reg(crtc, crtc_state->cpu_transcoder),
+			       dss_ctl1_val);
+		intel_de_write(display,
+			       dss_ctl2_reg(crtc, crtc_state->cpu_transcoder),
+			       dss_ctl2_val);
+	}
 }
 
 void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state)
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h
index 2b2e3c1..34effaf 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h
@@ -39,6 +39,22 @@
 #define  SPLITTER_CONFIGURATION_MASK		REG_GENMASK(26, 25)
 #define  SPLITTER_CONFIGURATION_2_SEGMENT	REG_FIELD_PREP(SPLITTER_CONFIGURATION_MASK, 0)
 #define  SPLITTER_CONFIGURATION_4_SEGMENT	REG_FIELD_PREP(SPLITTER_CONFIGURATION_MASK, 1)
+/*
+ * The bits in dss_ctl1_reg() that belong to whoever programmed the
+ * splitter rather than to intel_dsc_enable(): configure_dual_link_mode()
+ * owns SPLITTER_ENABLE, DUAL_LINK_MODE_INTERLEAVE, OVERLAP_PIXELS and
+ * LEFT_DL_BUF_TARGET_DEPTH; intel_ddi_mso_configure() owns
+ * SPLITTER_ENABLE, SPLITTER_CONFIGURATION and OVERLAP_PIXELS.
+ *
+ * The first four are listed above under DSS_CTL1 and SPLITTER_CONFIGURATION
+ * under ICL_PIPE_DSS_CTL1; dss_ctl1_reg() picks one register or the other
+ * by display version and the layout of these bits is the same in both.
+ */
+#define  SPLITTER_STATE				(SPLITTER_ENABLE | \
+						 SPLITTER_CONFIGURATION_MASK | \
+						 DUAL_LINK_MODE_INTERLEAVE | \
+						 OVERLAP_PIXELS_MASK | \
+						 LEFT_DL_BUF_TARGET_DEPTH_MASK)
 #define  ULTRA_JOINER_ENABLE			REG_BIT(23)
 #define  PRIMARY_ULTRA_JOINER_ENABLE		REG_BIT(22)
 #define  UNCOMPRESSED_JOINER_PRIMARY		(1 << 21)

Building it by hand

If you would rather not use the AUR package, only the i915 module needs
rebuilding, not the whole kernel:

# matching kernel source for your running kernel
tar xf linux-<version>.tar.xz
cd linux-<version>
zcat /proc/config.gz > .config
echo "-arch1-1" > localversion.10-arch
make olddefconfig
make modules_prepare
cp /usr/lib/modules/$(uname -r)/build/Module.symvers .   # keeps symbol CRCs matching

patch -p1 < ../matebook-e-dsi.diff
make M=drivers/gpu/drm/i915 modules

strip --strip-debug -o /tmp/i915.ko drivers/gpu/drm/i915/i915.ko
sudo zstd -19 -f /tmp/i915.ko \
  -o /usr/lib/modules/$(uname -r)/kernel/drivers/gpu/drm/i915/i915.ko.zst
sudo depmod -a
sudo mkinitcpio -P

Check that it is really the module you loaded, since a stale one behaves exactly like an unpatched kernel:

modinfo -F srcversion i915
cat /sys/module/i915/srcversion

Caveats

  • The vtotal value of 1666 is empirical. I have no derivation for it, and the patch just keeps whatever the firmware programmed.

  • 0x48408 is undocumented. The write is self-limiting -- it only ever restores a value that was observed on the same machine, and only for command mode.

  • Packaged on the AUR as matebook-e-dsi-dkms.

  • Only tested on this one laptop (DRR-W56).

Offline

#14 Today 12:54:43

seth
Member
From: Won't reply 2 private help req
Registered: 2012-09-03
Posts: 77,693

Re: i915 driver problems on matebook e 2023

Is there a pending upstream commit or bug?
Otherwise you'd rather want to document that in the wiki, https://wiki.archlinux.org/index.php?se … l%3ASearch

Offline

Board footer

Powered by FluxBB