3737
3838static struct nouveau_dsm_priv {
3939 bool dsm_detected ;
40+ bool optimus_detected ;
4041 acpi_handle dhandle ;
4142 acpi_handle rom_handle ;
4243} nouveau_dsm_priv ;
4344
45+ #define NOUVEAU_DSM_HAS_MUX 0x1
46+ #define NOUVEAU_DSM_HAS_OPT 0x2
47+
4448static const char nouveau_dsm_muid [] = {
4549 0xA0 , 0xA0 , 0x95 , 0x9D , 0x60 , 0x00 , 0x48 , 0x4D ,
4650 0xB3 , 0x4D , 0x7E , 0x5F , 0xEA , 0x12 , 0x9F , 0xD4 ,
4751};
4852
53+ static const char nouveau_op_dsm_muid [] = {
54+ 0xF8 , 0xD8 , 0x86 , 0xA4 , 0xDA , 0x0B , 0x1B , 0x47 ,
55+ 0xA7 , 0x2B , 0x60 , 0x42 , 0xA6 , 0xB5 , 0xBE , 0xE0 ,
56+ };
57+
58+ static int nouveau_optimus_dsm (acpi_handle handle , int func , int arg , uint32_t * result )
59+ {
60+ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER , NULL };
61+ struct acpi_object_list input ;
62+ union acpi_object params [4 ];
63+ union acpi_object * obj ;
64+ int err ;
65+
66+ input .count = 4 ;
67+ input .pointer = params ;
68+ params [0 ].type = ACPI_TYPE_BUFFER ;
69+ params [0 ].buffer .length = sizeof (nouveau_op_dsm_muid );
70+ params [0 ].buffer .pointer = (char * )nouveau_op_dsm_muid ;
71+ params [1 ].type = ACPI_TYPE_INTEGER ;
72+ params [1 ].integer .value = 0x00000100 ;
73+ params [2 ].type = ACPI_TYPE_INTEGER ;
74+ params [2 ].integer .value = func ;
75+ params [3 ].type = ACPI_TYPE_BUFFER ;
76+ params [3 ].buffer .length = 0 ;
77+
78+ err = acpi_evaluate_object (handle , "_DSM" , & input , & output );
79+ if (err ) {
80+ printk (KERN_INFO "failed to evaluate _DSM: %d\n" , err );
81+ return err ;
82+ }
83+
84+ obj = (union acpi_object * )output .pointer ;
85+
86+ if (obj -> type == ACPI_TYPE_INTEGER )
87+ if (obj -> integer .value == 0x80000002 ) {
88+ return - ENODEV ;
89+ }
90+
91+ if (obj -> type == ACPI_TYPE_BUFFER ) {
92+ if (obj -> buffer .length == 4 && result ) {
93+ * result = 0 ;
94+ * result |= obj -> buffer .pointer [0 ];
95+ * result |= (obj -> buffer .pointer [1 ] << 8 );
96+ * result |= (obj -> buffer .pointer [2 ] << 16 );
97+ * result |= (obj -> buffer .pointer [3 ] << 24 );
98+ }
99+ }
100+
101+ kfree (output .pointer );
102+ return 0 ;
103+ }
104+
49105static int nouveau_dsm (acpi_handle handle , int func , int arg , uint32_t * result )
50106{
51107 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER , NULL };
@@ -151,11 +207,11 @@ static struct vga_switcheroo_handler nouveau_dsm_handler = {
151207 .get_client_id = nouveau_dsm_get_client_id ,
152208};
153209
154- static bool nouveau_dsm_pci_probe (struct pci_dev * pdev )
210+ static int nouveau_dsm_pci_probe (struct pci_dev * pdev )
155211{
156212 acpi_handle dhandle , nvidia_handle ;
157213 acpi_status status ;
158- int ret ;
214+ int ret , retval = 0 ;
159215 uint32_t result ;
160216
161217 dhandle = DEVICE_ACPI_HANDLE (& pdev -> dev );
@@ -169,11 +225,17 @@ static bool nouveau_dsm_pci_probe(struct pci_dev *pdev)
169225
170226 ret = nouveau_dsm (dhandle , NOUVEAU_DSM_SUPPORTED ,
171227 NOUVEAU_DSM_SUPPORTED_FUNCTIONS , & result );
172- if (ret < 0 )
173- return false ;
228+ if (ret == 0 )
229+ retval |= NOUVEAU_DSM_HAS_MUX ;
174230
175- nouveau_dsm_priv .dhandle = dhandle ;
176- return true;
231+ ret = nouveau_optimus_dsm (dhandle , 0 , 0 , & result );
232+ if (ret == 0 )
233+ retval |= NOUVEAU_DSM_HAS_OPT ;
234+
235+ if (retval )
236+ nouveau_dsm_priv .dhandle = dhandle ;
237+
238+ return retval ;
177239}
178240
179241static bool nouveau_dsm_detect (void )
@@ -182,30 +244,42 @@ static bool nouveau_dsm_detect(void)
182244 struct acpi_buffer buffer = {sizeof (acpi_method_name ), acpi_method_name };
183245 struct pci_dev * pdev = NULL ;
184246 int has_dsm = 0 ;
247+ int has_optimus ;
185248 int vga_count = 0 ;
186249 bool guid_valid ;
250+ int retval ;
251+ bool ret = false;
187252
188- /* lookup the GUID */
253+ /* lookup the MXM GUID */
189254 guid_valid = mxm_wmi_supported ();
190- if (!guid_valid )
191- return false;
192255
193- printk ("MXM GUID detected in BIOS\n" );
256+ if (guid_valid )
257+ printk ("MXM: GUID detected in BIOS\n" );
194258
259+ /* now do DSM detection */
195260 while ((pdev = pci_get_class (PCI_CLASS_DISPLAY_VGA << 8 , pdev )) != NULL ) {
196261 vga_count ++ ;
197262
198- has_dsm |= (nouveau_dsm_pci_probe (pdev ) == true);
263+ retval = nouveau_dsm_pci_probe (pdev );
264+ printk ("ret val is %d\n" , retval );
265+ if (retval & NOUVEAU_DSM_HAS_MUX )
266+ has_dsm |= 1 ;
267+ if (retval & NOUVEAU_DSM_HAS_OPT )
268+ has_optimus = 1 ;
199269 }
200270
201- if (vga_count == 2 && has_dsm ) {
271+ if (vga_count == 2 && has_dsm && guid_valid ) {
202272 acpi_get_name (nouveau_dsm_priv .dhandle , ACPI_FULL_PATHNAME , & buffer );
203273 printk (KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n" ,
204274 acpi_method_name );
205275 nouveau_dsm_priv .dsm_detected = true;
206- return true;
276+ ret = true;
207277 }
208- return false;
278+
279+ if (has_optimus == 1 )
280+ nouveau_dsm_priv .optimus_detected = true;
281+
282+ return ret ;
209283}
210284
211285void nouveau_register_dsm_handler (void )
@@ -258,7 +332,7 @@ bool nouveau_acpi_rom_supported(struct pci_dev *pdev)
258332 acpi_status status ;
259333 acpi_handle dhandle , rom_handle ;
260334
261- if (!nouveau_dsm_priv .dsm_detected )
335+ if (!nouveau_dsm_priv .dsm_detected && ! nouveau_dsm_priv . optimus_detected )
262336 return false;
263337
264338 dhandle = DEVICE_ACPI_HANDLE (& pdev -> dev );
0 commit comments