11/* SPDX-License-Identifier: MIT */
22
33#include "display.h"
4+ #include "adt.h"
45#include "assert.h"
56#include "dcp.h"
67#include "dcp_iboot.h"
@@ -68,6 +69,84 @@ static void display_choose_color_mode(dcp_color_mode_t *modes, int cnt, dcp_colo
6869 best -> colorimetry , best -> eotf , best -> encoding , best -> bpp );
6970}
7071
72+ static int display_map_fb (uintptr_t iova , void * paddr , size_t size )
73+ {
74+ int ret = dart_map (dcp -> dart_disp , iova , paddr , size );
75+ if (ret < 0 ) {
76+ printf ("display: failed to map fb to dart-disp0\n" );
77+ return -1 ;
78+ }
79+
80+ ret = dart_map (dcp -> dart_dcp , iova , paddr , size );
81+ if (ret < 0 ) {
82+ printf ("display: failed to map fb to dart-dcp\n" );
83+ dart_unmap (dcp -> dart_disp , iova , size );
84+ return -1 ;
85+ }
86+
87+ return 0 ;
88+ }
89+
90+ static uintptr_t display_map_vram (void )
91+ {
92+ int ret = 0 ;
93+ u64 paddr , size ;
94+ int adt_path [4 ];
95+ int node = adt_path_offset_trace (adt , "/vram" , adt_path );
96+
97+ if (node < 0 ) {
98+ printf ("display: '/vram' not found\n" );
99+ return 0 ;
100+ }
101+
102+ int pp = 0 ;
103+ while (adt_path [pp ])
104+ pp ++ ;
105+ adt_path [pp + 1 ] = 0 ;
106+
107+ ret = adt_get_reg (adt , adt_path , "reg" , 0 , & paddr , & size );
108+ if (ret < 0 ) {
109+ printf ("display: failed to read /vram/reg\n" );
110+ return 0 ;
111+ }
112+
113+ if (paddr != cur_boot_args .video .base ) {
114+ printf ("display: vram does not match boot_args.video.base\n" );
115+ return 0 ;
116+ }
117+
118+ s64 iova_disp0 = 0 ;
119+ s64 iova_dcp = 0 ;
120+
121+ iova_dcp = dart_find_iova (dcp -> dart_dcp , iova_dcp , size );
122+ if (iova_dcp < 0 ) {
123+ printf ("display: failed to find IOVA for fb of %06zx bytes (dcp)\n" , size );
124+ return 0 ;
125+ }
126+
127+ // try to map the fb to the same IOVA on disp0
128+ iova_disp0 = dart_find_iova (dcp -> dart_dcp , iova_dcp , size );
129+ if (iova_disp0 < 0 ) {
130+ printf ("display: failed to find IOVA for fb of %06zx bytes (disp0)\n" , size );
131+ return 0 ;
132+ }
133+
134+ // assume this results in the same IOVA, not sure if this is required but matches what iboot
135+ // does on other models.
136+ if (iova_disp0 != iova_dcp ) {
137+ printf ("display: IOVA mismatch for fb between dcp (%08lx) and disp0 (%08lx)\n" ,
138+ (u64 )iova_dcp , (u64 )iova_disp0 );
139+ return 0 ;
140+ }
141+
142+ uintptr_t iova = iova_dcp ;
143+ ret = display_map_fb (iova , (void * )paddr , size );
144+ if (ret < 0 )
145+ return 0 ;
146+
147+ return iova ;
148+ }
149+
71150static int display_start_dcp (void )
72151{
73152 if (iboot )
@@ -81,6 +160,9 @@ static int display_start_dcp(void)
81160
82161 // Find the framebuffer DVA
83162 fb_dva = dart_search (dcp -> dart_disp , (void * )cur_boot_args .video .base );
163+ // framebuffer is not mapped on the M1 Ultra Mac Studio
164+ if (!fb_dva )
165+ fb_dva = display_map_vram ();
84166 if (!fb_dva ) {
85167 printf ("display: failed to find display DVA\n" );
86168 dcp_shutdown (dcp );
0 commit comments