diff options
author | Jiang Liu <jiang.liu@linux.intel.com> | 2013-12-19 07:38:22 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-01-05 10:07:15 -0500 |
commit | b072e53b0a27a885d8be3d08c8d8758292762f39 (patch) | |
tree | 177e2c32c572665f4ec1b933599a4f3c13c41de1 /drivers/gpu/drm/nouveau/nouveau_acpi.c | |
parent | 4988d0aeb6843b7070e406f8e6cb095c74e5f136 (diff) |
ACPI / nouveau: replace open-coded _DSM code with helper functions
Use helper functions to simplify _DSM related code in nouveau driver.
After analyzing the ACPI _DSM related code, I changed nouveau_optimus_dsm()
to expect a buffer and nouveau_dsm() to expect an integer only.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_acpi.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_acpi.c | 136 |
1 files changed, 38 insertions, 98 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 3f721e317fef..879a8b474bfe 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c | |||
@@ -78,127 +78,66 @@ static const char nouveau_op_dsm_muid[] = { | |||
78 | 78 | ||
79 | static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result) | 79 | static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result) |
80 | { | 80 | { |
81 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | 81 | int i; |
82 | struct acpi_object_list input; | ||
83 | union acpi_object params[4]; | ||
84 | union acpi_object *obj; | 82 | union acpi_object *obj; |
85 | int i, err; | ||
86 | char args_buff[4]; | 83 | char args_buff[4]; |
84 | union acpi_object argv4 = { | ||
85 | .buffer.type = ACPI_TYPE_BUFFER, | ||
86 | .buffer.length = 4, | ||
87 | .buffer.pointer = args_buff | ||
88 | }; | ||
87 | 89 | ||
88 | input.count = 4; | ||
89 | input.pointer = params; | ||
90 | params[0].type = ACPI_TYPE_BUFFER; | ||
91 | params[0].buffer.length = sizeof(nouveau_op_dsm_muid); | ||
92 | params[0].buffer.pointer = (char *)nouveau_op_dsm_muid; | ||
93 | params[1].type = ACPI_TYPE_INTEGER; | ||
94 | params[1].integer.value = 0x00000100; | ||
95 | params[2].type = ACPI_TYPE_INTEGER; | ||
96 | params[2].integer.value = func; | ||
97 | params[3].type = ACPI_TYPE_BUFFER; | ||
98 | params[3].buffer.length = 4; | ||
99 | /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */ | 90 | /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */ |
100 | for (i = 0; i < 4; i++) | 91 | for (i = 0; i < 4; i++) |
101 | args_buff[i] = (arg >> i * 8) & 0xFF; | 92 | args_buff[i] = (arg >> i * 8) & 0xFF; |
102 | params[3].buffer.pointer = args_buff; | ||
103 | 93 | ||
104 | err = acpi_evaluate_object(handle, "_DSM", &input, &output); | 94 | *result = 0; |
105 | if (err) { | 95 | obj = acpi_evaluate_dsm_typed(handle, nouveau_op_dsm_muid, 0x00000100, |
106 | printk(KERN_INFO "failed to evaluate _DSM: %d\n", err); | 96 | func, &argv4, ACPI_TYPE_BUFFER); |
107 | return err; | 97 | if (!obj) { |
108 | } | 98 | acpi_handle_info(handle, "failed to evaluate _DSM\n"); |
109 | 99 | return AE_ERROR; | |
110 | obj = (union acpi_object *)output.pointer; | 100 | } else { |
111 | 101 | if (obj->buffer.length == 4) { | |
112 | if (obj->type == ACPI_TYPE_INTEGER) | ||
113 | if (obj->integer.value == 0x80000002) { | ||
114 | kfree(output.pointer); | ||
115 | return -ENODEV; | ||
116 | } | ||
117 | |||
118 | if (obj->type == ACPI_TYPE_BUFFER) { | ||
119 | if (obj->buffer.length == 4 && result) { | ||
120 | *result = 0; | ||
121 | *result |= obj->buffer.pointer[0]; | 102 | *result |= obj->buffer.pointer[0]; |
122 | *result |= (obj->buffer.pointer[1] << 8); | 103 | *result |= (obj->buffer.pointer[1] << 8); |
123 | *result |= (obj->buffer.pointer[2] << 16); | 104 | *result |= (obj->buffer.pointer[2] << 16); |
124 | *result |= (obj->buffer.pointer[3] << 24); | 105 | *result |= (obj->buffer.pointer[3] << 24); |
125 | } | 106 | } |
107 | ACPI_FREE(obj); | ||
126 | } | 108 | } |
127 | 109 | ||
128 | kfree(output.pointer); | ||
129 | return 0; | 110 | return 0; |
130 | } | 111 | } |
131 | 112 | ||
132 | static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result) | 113 | static int nouveau_dsm(acpi_handle handle, int func, int arg) |
133 | { | 114 | { |
134 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | 115 | int ret = 0; |
135 | struct acpi_object_list input; | ||
136 | union acpi_object params[4]; | ||
137 | union acpi_object *obj; | 116 | union acpi_object *obj; |
138 | int err; | 117 | union acpi_object argv4 = { |
139 | 118 | .integer.type = ACPI_TYPE_INTEGER, | |
140 | input.count = 4; | 119 | .integer.value = arg, |
141 | input.pointer = params; | 120 | }; |
142 | params[0].type = ACPI_TYPE_BUFFER; | 121 | |
143 | params[0].buffer.length = sizeof(nouveau_dsm_muid); | 122 | obj = acpi_evaluate_dsm_typed(handle, nouveau_dsm_muid, 0x00000102, |
144 | params[0].buffer.pointer = (char *)nouveau_dsm_muid; | 123 | func, &argv4, ACPI_TYPE_INTEGER); |
145 | params[1].type = ACPI_TYPE_INTEGER; | 124 | if (!obj) { |
146 | params[1].integer.value = 0x00000102; | 125 | acpi_handle_info(handle, "failed to evaluate _DSM\n"); |
147 | params[2].type = ACPI_TYPE_INTEGER; | 126 | return AE_ERROR; |
148 | params[2].integer.value = func; | 127 | } else { |
149 | params[3].type = ACPI_TYPE_INTEGER; | 128 | if (obj->integer.value == 0x80000002) |
150 | params[3].integer.value = arg; | 129 | ret = -ENODEV; |
151 | 130 | ACPI_FREE(obj); | |
152 | err = acpi_evaluate_object(handle, "_DSM", &input, &output); | ||
153 | if (err) { | ||
154 | printk(KERN_INFO "failed to evaluate _DSM: %d\n", err); | ||
155 | return err; | ||
156 | } | ||
157 | |||
158 | obj = (union acpi_object *)output.pointer; | ||
159 | |||
160 | if (obj->type == ACPI_TYPE_INTEGER) | ||
161 | if (obj->integer.value == 0x80000002) { | ||
162 | kfree(output.pointer); | ||
163 | return -ENODEV; | ||
164 | } | ||
165 | |||
166 | if (obj->type == ACPI_TYPE_BUFFER) { | ||
167 | if (obj->buffer.length == 4 && result) { | ||
168 | *result = 0; | ||
169 | *result |= obj->buffer.pointer[0]; | ||
170 | *result |= (obj->buffer.pointer[1] << 8); | ||
171 | *result |= (obj->buffer.pointer[2] << 16); | ||
172 | *result |= (obj->buffer.pointer[3] << 24); | ||
173 | } | ||
174 | } | 131 | } |
175 | 132 | ||
176 | kfree(output.pointer); | 133 | return ret; |
177 | return 0; | ||
178 | } | ||
179 | |||
180 | /* Returns 1 if a DSM function is usable and 0 otherwise */ | ||
181 | static int nouveau_test_dsm(acpi_handle test_handle, | ||
182 | int (*dsm_func)(acpi_handle, int, int, uint32_t *), | ||
183 | int sfnc) | ||
184 | { | ||
185 | u32 result = 0; | ||
186 | |||
187 | /* Function 0 returns a Buffer containing available functions. The args | ||
188 | * parameter is ignored for function 0, so just put 0 in it */ | ||
189 | if (dsm_func(test_handle, 0, 0, &result)) | ||
190 | return 0; | ||
191 | |||
192 | /* ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. If | ||
193 | * the n-th bit is enabled, function n is supported */ | ||
194 | return result & 1 && result & (1 << sfnc); | ||
195 | } | 134 | } |
196 | 135 | ||
197 | static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) | 136 | static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) |
198 | { | 137 | { |
199 | mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); | 138 | mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); |
200 | mxm_wmi_call_mxds(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); | 139 | mxm_wmi_call_mxds(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); |
201 | return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id, NULL); | 140 | return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id); |
202 | } | 141 | } |
203 | 142 | ||
204 | static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state) | 143 | static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state) |
@@ -208,7 +147,7 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero | |||
208 | arg = NOUVEAU_DSM_POWER_SPEED; | 147 | arg = NOUVEAU_DSM_POWER_SPEED; |
209 | else | 148 | else |
210 | arg = NOUVEAU_DSM_POWER_STAMINA; | 149 | arg = NOUVEAU_DSM_POWER_STAMINA; |
211 | nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg, NULL); | 150 | nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg); |
212 | return 0; | 151 | return 0; |
213 | } | 152 | } |
214 | 153 | ||
@@ -268,11 +207,12 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) | |||
268 | nouveau_dsm_priv.other_handle = dhandle; | 207 | nouveau_dsm_priv.other_handle = dhandle; |
269 | return false; | 208 | return false; |
270 | } | 209 | } |
271 | if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) | 210 | if (acpi_check_dsm(dhandle, nouveau_dsm_muid, 0x00000102, |
211 | 1 << NOUVEAU_DSM_POWER)) | ||
272 | retval |= NOUVEAU_DSM_HAS_MUX; | 212 | retval |= NOUVEAU_DSM_HAS_MUX; |
273 | 213 | ||
274 | if (nouveau_test_dsm(dhandle, nouveau_optimus_dsm, | 214 | if (acpi_check_dsm(dhandle, nouveau_op_dsm_muid, 0x00000100, |
275 | NOUVEAU_DSM_OPTIMUS_CAPS)) | 215 | 1 << NOUVEAU_DSM_OPTIMUS_CAPS)) |
276 | retval |= NOUVEAU_DSM_HAS_OPT; | 216 | retval |= NOUVEAU_DSM_HAS_OPT; |
277 | 217 | ||
278 | if (retval & NOUVEAU_DSM_HAS_OPT) { | 218 | if (retval & NOUVEAU_DSM_HAS_OPT) { |