Commit | Line | Data |
---|---|---|
0867b421 AC |
1 | /************************************************************************** |
2 | * Copyright (c) 2007, Intel Corporation. | |
3 | * All Rights Reserved. | |
4 | * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX., USA. | |
5 | * All Rights Reserved. | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify it | |
8 | * under the terms and conditions of the GNU General Public License, | |
9 | * version 2, as published by the Free Software Foundation. | |
10 | * | |
11 | * This program is distributed in the hope it will be useful, but WITHOUT | |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
14 | * more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License along with | |
17 | * this program; if not, write to the Free Software Foundation, Inc., | |
18 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | |
19 | * | |
20 | **************************************************************************/ | |
21 | ||
22 | #include <drm/drmP.h> | |
23 | #include <drm/drm.h> | |
24 | #include "psb_drm.h" | |
25 | #include "psb_drv.h" | |
26 | #include "psb_fb.h" | |
27 | #include "psb_reg.h" | |
28 | #include "psb_intel_reg.h" | |
29 | #include "psb_intel_bios.h" | |
30 | #include <drm/drm_pciids.h> | |
31 | #include "psb_powermgmt.h" | |
32 | #include <linux/cpu.h> | |
33 | #include <linux/notifier.h> | |
34 | #include <linux/spinlock.h> | |
35 | #include <linux/pm_runtime.h> | |
487e873d | 36 | #include <acpi/video.h> |
0867b421 AC |
37 | |
38 | int drm_psb_debug; | |
39 | static int drm_psb_trap_pagefaults; | |
40 | ||
41 | int drm_psb_disable_vsync = 1; | |
42 | int drm_psb_no_fb; | |
0867b421 AC |
43 | int gfxrtdelay = 2 * 1000; |
44 | ||
45 | static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent); | |
46 | ||
47 | MODULE_PARM_DESC(debug, "Enable debug output"); | |
48 | MODULE_PARM_DESC(no_fb, "Disable FBdev"); | |
49 | MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults"); | |
50 | MODULE_PARM_DESC(disable_vsync, "Disable vsync interrupts"); | |
51 | MODULE_PARM_DESC(force_pipeb, "Forces PIPEB to become primary fb"); | |
52 | MODULE_PARM_DESC(ta_mem_size, "TA memory size in kiB"); | |
53 | MODULE_PARM_DESC(ospm, "switch for ospm support"); | |
54 | MODULE_PARM_DESC(rtpm, "Specifies Runtime PM delay for GFX"); | |
55 | MODULE_PARM_DESC(hdmi_edid, "EDID info for HDMI monitor"); | |
56 | module_param_named(debug, drm_psb_debug, int, 0600); | |
57 | module_param_named(no_fb, drm_psb_no_fb, int, 0600); | |
58 | module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600); | |
0867b421 AC |
59 | module_param_named(rtpm, gfxrtdelay, int, 0600); |
60 | ||
61 | ||
62 | static struct pci_device_id pciidlist[] = { | |
63 | { 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8108 }, | |
64 | { 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8109 }, | |
65 | { 0, 0, 0} | |
66 | }; | |
67 | MODULE_DEVICE_TABLE(pci, pciidlist); | |
68 | ||
69 | /* | |
70 | * Standard IOCTLs. | |
71 | */ | |
72 | ||
73 | #define DRM_IOCTL_PSB_KMS_OFF \ | |
74 | DRM_IO(DRM_PSB_KMS_OFF + DRM_COMMAND_BASE) | |
75 | #define DRM_IOCTL_PSB_KMS_ON \ | |
76 | DRM_IO(DRM_PSB_KMS_ON + DRM_COMMAND_BASE) | |
77 | #define DRM_IOCTL_PSB_VT_LEAVE \ | |
78 | DRM_IO(DRM_PSB_VT_LEAVE + DRM_COMMAND_BASE) | |
79 | #define DRM_IOCTL_PSB_VT_ENTER \ | |
80 | DRM_IO(DRM_PSB_VT_ENTER + DRM_COMMAND_BASE) | |
81 | #define DRM_IOCTL_PSB_SIZES \ | |
82 | DRM_IOR(DRM_PSB_SIZES + DRM_COMMAND_BASE, \ | |
83 | struct drm_psb_sizes_arg) | |
84 | #define DRM_IOCTL_PSB_FUSE_REG \ | |
85 | DRM_IOWR(DRM_PSB_FUSE_REG + DRM_COMMAND_BASE, uint32_t) | |
86 | #define DRM_IOCTL_PSB_DC_STATE \ | |
87 | DRM_IOW(DRM_PSB_DC_STATE + DRM_COMMAND_BASE, \ | |
88 | struct drm_psb_dc_state_arg) | |
89 | #define DRM_IOCTL_PSB_ADB \ | |
90 | DRM_IOWR(DRM_PSB_ADB + DRM_COMMAND_BASE, uint32_t) | |
91 | #define DRM_IOCTL_PSB_MODE_OPERATION \ | |
92 | DRM_IOWR(DRM_PSB_MODE_OPERATION + DRM_COMMAND_BASE, \ | |
93 | struct drm_psb_mode_operation_arg) | |
94 | #define DRM_IOCTL_PSB_STOLEN_MEMORY \ | |
95 | DRM_IOWR(DRM_PSB_STOLEN_MEMORY + DRM_COMMAND_BASE, \ | |
96 | struct drm_psb_stolen_memory_arg) | |
97 | #define DRM_IOCTL_PSB_REGISTER_RW \ | |
98 | DRM_IOWR(DRM_PSB_REGISTER_RW + DRM_COMMAND_BASE, \ | |
99 | struct drm_psb_register_rw_arg) | |
100 | #define DRM_IOCTL_PSB_GTT_MAP \ | |
101 | DRM_IOWR(DRM_PSB_GTT_MAP + DRM_COMMAND_BASE, \ | |
102 | struct psb_gtt_mapping_arg) | |
103 | #define DRM_IOCTL_PSB_GTT_UNMAP \ | |
104 | DRM_IOW(DRM_PSB_GTT_UNMAP + DRM_COMMAND_BASE, \ | |
105 | struct psb_gtt_mapping_arg) | |
106 | #define DRM_IOCTL_PSB_GETPAGEADDRS \ | |
107 | DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_GETPAGEADDRS,\ | |
108 | struct drm_psb_getpageaddrs_arg) | |
0867b421 AC |
109 | #define DRM_IOCTL_PSB_UPDATE_GUARD \ |
110 | DRM_IOWR(DRM_PSB_UPDATE_GUARD + DRM_COMMAND_BASE, \ | |
111 | uint32_t) | |
112 | #define DRM_IOCTL_PSB_DPST \ | |
113 | DRM_IOWR(DRM_PSB_DPST + DRM_COMMAND_BASE, \ | |
114 | uint32_t) | |
115 | #define DRM_IOCTL_PSB_GAMMA \ | |
116 | DRM_IOWR(DRM_PSB_GAMMA + DRM_COMMAND_BASE, \ | |
117 | struct drm_psb_dpst_lut_arg) | |
118 | #define DRM_IOCTL_PSB_DPST_BL \ | |
119 | DRM_IOWR(DRM_PSB_DPST_BL + DRM_COMMAND_BASE, \ | |
120 | uint32_t) | |
121 | #define DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID \ | |
122 | DRM_IOWR(DRM_PSB_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \ | |
123 | struct drm_psb_get_pipe_from_crtc_id_arg) | |
124 | ||
125 | /* | |
126 | * TTM execbuf extension. | |
127 | */ | |
487e873d AC |
128 | |
129 | #define DRM_PSB_CMDBUF 0x23 | |
130 | #define DRM_PSB_SCENE_UNREF 0x24 | |
0867b421 AC |
131 | #define DRM_IOCTL_PSB_KMS_OFF DRM_IO(DRM_PSB_KMS_OFF + DRM_COMMAND_BASE) |
132 | #define DRM_IOCTL_PSB_KMS_ON DRM_IO(DRM_PSB_KMS_ON + DRM_COMMAND_BASE) | |
133 | /* | |
134 | * TTM placement user extension. | |
135 | */ | |
136 | ||
137 | #define DRM_PSB_PLACEMENT_OFFSET (DRM_PSB_SCENE_UNREF + 1) | |
138 | ||
139 | #define DRM_PSB_TTM_PL_CREATE (TTM_PL_CREATE + DRM_PSB_PLACEMENT_OFFSET) | |
140 | #define DRM_PSB_TTM_PL_REFERENCE (TTM_PL_REFERENCE + DRM_PSB_PLACEMENT_OFFSET) | |
141 | #define DRM_PSB_TTM_PL_UNREF (TTM_PL_UNREF + DRM_PSB_PLACEMENT_OFFSET) | |
142 | #define DRM_PSB_TTM_PL_SYNCCPU (TTM_PL_SYNCCPU + DRM_PSB_PLACEMENT_OFFSET) | |
143 | #define DRM_PSB_TTM_PL_WAITIDLE (TTM_PL_WAITIDLE + DRM_PSB_PLACEMENT_OFFSET) | |
144 | #define DRM_PSB_TTM_PL_SETSTATUS (TTM_PL_SETSTATUS + DRM_PSB_PLACEMENT_OFFSET) | |
145 | #define DRM_PSB_TTM_PL_CREATE_UB (TTM_PL_CREATE_UB + DRM_PSB_PLACEMENT_OFFSET) | |
146 | ||
147 | /* | |
148 | * TTM fence extension. | |
149 | */ | |
150 | ||
151 | #define DRM_PSB_FENCE_OFFSET (DRM_PSB_TTM_PL_CREATE_UB + 1) | |
152 | #define DRM_PSB_TTM_FENCE_SIGNALED (TTM_FENCE_SIGNALED + DRM_PSB_FENCE_OFFSET) | |
153 | #define DRM_PSB_TTM_FENCE_FINISH (TTM_FENCE_FINISH + DRM_PSB_FENCE_OFFSET) | |
154 | #define DRM_PSB_TTM_FENCE_UNREF (TTM_FENCE_UNREF + DRM_PSB_FENCE_OFFSET) | |
155 | ||
156 | #define DRM_PSB_FLIP (DRM_PSB_TTM_FENCE_UNREF + 1) /*20*/ | |
0867b421 AC |
157 | |
158 | #define DRM_IOCTL_PSB_TTM_PL_CREATE \ | |
159 | DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_CREATE,\ | |
160 | union ttm_pl_create_arg) | |
161 | #define DRM_IOCTL_PSB_TTM_PL_REFERENCE \ | |
162 | DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_REFERENCE,\ | |
163 | union ttm_pl_reference_arg) | |
164 | #define DRM_IOCTL_PSB_TTM_PL_UNREF \ | |
165 | DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_UNREF,\ | |
166 | struct ttm_pl_reference_req) | |
167 | #define DRM_IOCTL_PSB_TTM_PL_SYNCCPU \ | |
168 | DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_SYNCCPU,\ | |
169 | struct ttm_pl_synccpu_arg) | |
170 | #define DRM_IOCTL_PSB_TTM_PL_WAITIDLE \ | |
171 | DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_WAITIDLE,\ | |
172 | struct ttm_pl_waitidle_arg) | |
173 | #define DRM_IOCTL_PSB_TTM_PL_SETSTATUS \ | |
174 | DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_SETSTATUS,\ | |
175 | union ttm_pl_setstatus_arg) | |
176 | #define DRM_IOCTL_PSB_TTM_PL_CREATE_UB \ | |
177 | DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_CREATE_UB,\ | |
178 | union ttm_pl_create_ub_arg) | |
179 | #define DRM_IOCTL_PSB_TTM_FENCE_SIGNALED \ | |
180 | DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_FENCE_SIGNALED, \ | |
181 | union ttm_fence_signaled_arg) | |
182 | #define DRM_IOCTL_PSB_TTM_FENCE_FINISH \ | |
183 | DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_FENCE_FINISH, \ | |
184 | union ttm_fence_finish_arg) | |
185 | #define DRM_IOCTL_PSB_TTM_FENCE_UNREF \ | |
186 | DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_FENCE_UNREF, \ | |
187 | struct ttm_fence_unref_arg) | |
0867b421 AC |
188 | |
189 | static int psb_vt_leave_ioctl(struct drm_device *dev, void *data, | |
190 | struct drm_file *file_priv); | |
191 | static int psb_vt_enter_ioctl(struct drm_device *dev, void *data, | |
192 | struct drm_file *file_priv); | |
193 | static int psb_sizes_ioctl(struct drm_device *dev, void *data, | |
194 | struct drm_file *file_priv); | |
195 | static int psb_dc_state_ioctl(struct drm_device *dev, void * data, | |
196 | struct drm_file *file_priv); | |
197 | static int psb_adb_ioctl(struct drm_device *dev, void *data, | |
198 | struct drm_file *file_priv); | |
199 | static int psb_mode_operation_ioctl(struct drm_device *dev, void *data, | |
200 | struct drm_file *file_priv); | |
201 | static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data, | |
202 | struct drm_file *file_priv); | |
203 | static int psb_register_rw_ioctl(struct drm_device *dev, void *data, | |
204 | struct drm_file *file_priv); | |
205 | static int psb_dpst_ioctl(struct drm_device *dev, void *data, | |
206 | struct drm_file *file_priv); | |
207 | static int psb_gamma_ioctl(struct drm_device *dev, void *data, | |
208 | struct drm_file *file_priv); | |
209 | static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data, | |
210 | struct drm_file *file_priv); | |
211 | ||
212 | #define PSB_IOCTL_DEF(ioctl, func, flags) \ | |
213 | [DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func} | |
214 | ||
215 | static struct drm_ioctl_desc psb_ioctls[] = { | |
216 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_KMS_OFF, psbfb_kms_off_ioctl, | |
217 | DRM_ROOT_ONLY), | |
218 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_KMS_ON, | |
219 | psbfb_kms_on_ioctl, | |
220 | DRM_ROOT_ONLY), | |
221 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_VT_LEAVE, psb_vt_leave_ioctl, | |
222 | DRM_ROOT_ONLY), | |
223 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_VT_ENTER, | |
224 | psb_vt_enter_ioctl, | |
225 | DRM_ROOT_ONLY), | |
226 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_SIZES, psb_sizes_ioctl, DRM_AUTH), | |
227 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_DC_STATE, psb_dc_state_ioctl, DRM_AUTH), | |
228 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_ADB, psb_adb_ioctl, DRM_AUTH), | |
229 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_MODE_OPERATION, psb_mode_operation_ioctl, | |
230 | DRM_AUTH), | |
231 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_STOLEN_MEMORY, psb_stolen_memory_ioctl, | |
232 | DRM_AUTH), | |
233 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_REGISTER_RW, psb_register_rw_ioctl, | |
234 | DRM_AUTH), | |
235 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_GTT_MAP, | |
236 | psb_gtt_map_meminfo_ioctl, | |
237 | DRM_AUTH), | |
238 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_GTT_UNMAP, | |
239 | psb_gtt_unmap_meminfo_ioctl, | |
240 | DRM_AUTH), | |
241 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_GETPAGEADDRS, | |
242 | psb_getpageaddrs_ioctl, | |
243 | DRM_AUTH), | |
244 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST, psb_dpst_ioctl, DRM_AUTH), | |
245 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_GAMMA, psb_gamma_ioctl, DRM_AUTH), | |
246 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH), | |
247 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID, | |
248 | psb_intel_get_pipe_from_crtc_id, 0), | |
0867b421 AC |
249 | |
250 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_CREATE, psb_pl_create_ioctl, | |
251 | DRM_AUTH), | |
252 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_REFERENCE, psb_pl_reference_ioctl, | |
253 | DRM_AUTH), | |
254 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_UNREF, psb_pl_unref_ioctl, | |
255 | DRM_AUTH), | |
256 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_SYNCCPU, psb_pl_synccpu_ioctl, | |
257 | DRM_AUTH), | |
258 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_WAITIDLE, psb_pl_waitidle_ioctl, | |
259 | DRM_AUTH), | |
260 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_SETSTATUS, psb_pl_setstatus_ioctl, | |
261 | DRM_AUTH), | |
262 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_CREATE_UB, psb_pl_ub_create_ioctl, | |
263 | DRM_AUTH), | |
264 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_FENCE_SIGNALED, | |
265 | psb_fence_signaled_ioctl, DRM_AUTH), | |
266 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_FENCE_FINISH, psb_fence_finish_ioctl, | |
267 | DRM_AUTH), | |
268 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_FENCE_UNREF, psb_fence_unref_ioctl, | |
269 | DRM_AUTH), | |
270 | }; | |
271 | ||
272 | static void psb_set_uopt(struct drm_psb_uopt *uopt) | |
273 | { | |
274 | return; | |
275 | } | |
276 | ||
277 | static void psb_lastclose(struct drm_device *dev) | |
278 | { | |
279 | struct drm_psb_private *dev_priv = | |
280 | (struct drm_psb_private *) dev->dev_private; | |
281 | ||
282 | return; | |
283 | ||
284 | if (!dev->dev_private) | |
285 | return; | |
286 | ||
287 | mutex_lock(&dev_priv->cmdbuf_mutex); | |
288 | if (dev_priv->context.buffers) { | |
289 | vfree(dev_priv->context.buffers); | |
290 | dev_priv->context.buffers = NULL; | |
291 | } | |
292 | mutex_unlock(&dev_priv->cmdbuf_mutex); | |
293 | } | |
294 | ||
295 | static void psb_do_takedown(struct drm_device *dev) | |
296 | { | |
297 | struct drm_psb_private *dev_priv = | |
298 | (struct drm_psb_private *) dev->dev_private; | |
299 | struct ttm_bo_device *bdev = &dev_priv->bdev; | |
300 | ||
301 | ||
302 | if (dev_priv->have_mem_mmu) { | |
303 | ttm_bo_clean_mm(bdev, DRM_PSB_MEM_MMU); | |
304 | dev_priv->have_mem_mmu = 0; | |
305 | } | |
306 | ||
307 | if (dev_priv->have_tt) { | |
308 | ttm_bo_clean_mm(bdev, TTM_PL_TT); | |
309 | dev_priv->have_tt = 0; | |
310 | } | |
311 | ||
312 | if (dev_priv->have_camera) { | |
313 | ttm_bo_clean_mm(bdev, TTM_PL_CI); | |
314 | dev_priv->have_camera = 0; | |
315 | } | |
316 | if (dev_priv->have_rar) { | |
317 | ttm_bo_clean_mm(bdev, TTM_PL_RAR); | |
318 | dev_priv->have_rar = 0; | |
319 | } | |
320 | ||
321 | } | |
322 | ||
323 | static void psb_get_core_freq(struct drm_device *dev) | |
324 | { | |
325 | uint32_t clock; | |
326 | struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); | |
327 | struct drm_psb_private *dev_priv = dev->dev_private; | |
328 | ||
329 | /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/ | |
330 | /*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/ | |
331 | ||
332 | pci_write_config_dword(pci_root, 0xD0, 0xD0050300); | |
333 | pci_read_config_dword(pci_root, 0xD4, &clock); | |
334 | pci_dev_put(pci_root); | |
335 | ||
336 | switch (clock & 0x07) { | |
337 | case 0: | |
338 | dev_priv->core_freq = 100; | |
339 | break; | |
340 | case 1: | |
341 | dev_priv->core_freq = 133; | |
342 | break; | |
343 | case 2: | |
344 | dev_priv->core_freq = 150; | |
345 | break; | |
346 | case 3: | |
347 | dev_priv->core_freq = 178; | |
348 | break; | |
349 | case 4: | |
350 | dev_priv->core_freq = 200; | |
351 | break; | |
352 | case 5: | |
353 | case 6: | |
354 | case 7: | |
355 | dev_priv->core_freq = 266; | |
356 | default: | |
357 | dev_priv->core_freq = 0; | |
358 | } | |
359 | } | |
360 | ||
361 | #define FB_REG06 0xD0810600 | |
362 | #define FB_TOPAZ_DISABLE BIT0 | |
363 | #define FB_MIPI_DISABLE BIT11 | |
364 | #define FB_REG09 0xD0810900 | |
365 | #define FB_SKU_MASK (BIT12|BIT13|BIT14) | |
366 | #define FB_SKU_SHIFT 12 | |
367 | #define FB_SKU_100 0 | |
368 | #define FB_SKU_100L 1 | |
369 | #define FB_SKU_83 2 | |
0867b421 AC |
370 | |
371 | bool mid_get_pci_revID(struct drm_psb_private *dev_priv) | |
372 | { | |
373 | uint32_t platform_rev_id = 0; | |
374 | struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); | |
375 | ||
376 | /*get the revison ID, B0:D2:F0;0x08 */ | |
377 | pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id); | |
378 | dev_priv->platform_rev_id = (uint8_t) platform_rev_id; | |
379 | pci_dev_put(pci_gfx_root); | |
380 | PSB_DEBUG_ENTRY("platform_rev_id is %x\n", | |
381 | dev_priv->platform_rev_id); | |
382 | ||
383 | return true; | |
384 | } | |
385 | ||
386 | static int psb_do_init(struct drm_device *dev) | |
387 | { | |
388 | struct drm_psb_private *dev_priv = | |
389 | (struct drm_psb_private *) dev->dev_private; | |
390 | struct ttm_bo_device *bdev = &dev_priv->bdev; | |
391 | struct psb_gtt *pg = dev_priv->pg; | |
392 | ||
393 | uint32_t stolen_gtt; | |
394 | uint32_t tt_start; | |
395 | uint32_t tt_pages; | |
396 | ||
397 | int ret = -ENOMEM; | |
398 | ||
399 | ||
400 | /* | |
401 | * Initialize sequence numbers for the different command | |
402 | * submission mechanisms. | |
403 | */ | |
404 | ||
405 | dev_priv->sequence[PSB_ENGINE_2D] = 0; | |
406 | dev_priv->sequence[PSB_ENGINE_VIDEO] = 0; | |
407 | dev_priv->sequence[LNC_ENGINE_ENCODE] = 0; | |
408 | ||
409 | if (pg->mmu_gatt_start & 0x0FFFFFFF) { | |
410 | DRM_ERROR("Gatt must be 256M aligned. This is a bug.\n"); | |
411 | ret = -EINVAL; | |
412 | goto out_err; | |
413 | } | |
414 | ||
aa19d8e9 | 415 | |
0867b421 AC |
416 | stolen_gtt = (pg->stolen_size >> PAGE_SHIFT) * 4; |
417 | stolen_gtt = (stolen_gtt + PAGE_SIZE - 1) >> PAGE_SHIFT; | |
418 | stolen_gtt = | |
419 | (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages; | |
420 | ||
421 | dev_priv->gatt_free_offset = pg->mmu_gatt_start + | |
422 | (stolen_gtt << PAGE_SHIFT) * 1024; | |
423 | ||
424 | if (1 || drm_debug) { | |
425 | uint32_t core_id = PSB_RSGX32(PSB_CR_CORE_ID); | |
426 | uint32_t core_rev = PSB_RSGX32(PSB_CR_CORE_REVISION); | |
427 | DRM_INFO("SGX core id = 0x%08x\n", core_id); | |
428 | DRM_INFO("SGX core rev major = 0x%02x, minor = 0x%02x\n", | |
429 | (core_rev & _PSB_CC_REVISION_MAJOR_MASK) >> | |
430 | _PSB_CC_REVISION_MAJOR_SHIFT, | |
431 | (core_rev & _PSB_CC_REVISION_MINOR_MASK) >> | |
432 | _PSB_CC_REVISION_MINOR_SHIFT); | |
433 | DRM_INFO | |
434 | ("SGX core rev maintenance = 0x%02x, designer = 0x%02x\n", | |
435 | (core_rev & _PSB_CC_REVISION_MAINTENANCE_MASK) >> | |
436 | _PSB_CC_REVISION_MAINTENANCE_SHIFT, | |
437 | (core_rev & _PSB_CC_REVISION_DESIGNER_MASK) >> | |
438 | _PSB_CC_REVISION_DESIGNER_SHIFT); | |
439 | } | |
440 | ||
aa19d8e9 | 441 | |
0867b421 AC |
442 | spin_lock_init(&dev_priv->irqmask_lock); |
443 | ||
444 | tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ? | |
445 | pg->gatt_pages : PSB_TT_PRIV0_PLIMIT; | |
446 | tt_start = dev_priv->gatt_free_offset - pg->mmu_gatt_start; | |
447 | tt_pages -= tt_start >> PAGE_SHIFT; | |
448 | dev_priv->sizes.ta_mem_size = 0; | |
449 | ||
aa19d8e9 AC |
450 | PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0); |
451 | PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1); | |
452 | PSB_RSGX32(PSB_CR_BIF_BANK1); | |
453 | PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK, | |
454 | PSB_CR_BIF_CTRL); | |
455 | psb_spank(dev_priv); | |
456 | ||
457 | PSB_WSGX32(pg->mmu_gatt_start, PSB_CR_BIF_TWOD_REQ_BASE); | |
0867b421 AC |
458 | |
459 | /* TT region managed by TTM. */ | |
460 | if (!ttm_bo_init_mm(bdev, TTM_PL_TT, | |
461 | pg->gatt_pages - | |
462 | (pg->ci_start >> PAGE_SHIFT) - | |
463 | ((dev_priv->ci_region_size + dev_priv->rar_region_size) | |
464 | >> PAGE_SHIFT))) { | |
465 | ||
466 | dev_priv->have_tt = 1; | |
467 | dev_priv->sizes.tt_size = | |
468 | (tt_pages << PAGE_SHIFT) / (1024 * 1024) / 2; | |
469 | } | |
470 | ||
471 | if (!ttm_bo_init_mm(bdev, | |
472 | DRM_PSB_MEM_MMU, | |
473 | PSB_MEM_TT_START >> PAGE_SHIFT)) { | |
474 | dev_priv->have_mem_mmu = 1; | |
475 | dev_priv->sizes.mmu_size = | |
476 | PSB_MEM_TT_START / (1024*1024); | |
477 | } | |
478 | ||
0867b421 AC |
479 | PSB_DEBUG_INIT("Init MSVDX\n"); |
480 | return 0; | |
481 | out_err: | |
482 | psb_do_takedown(dev); | |
483 | return ret; | |
484 | } | |
485 | ||
486 | static int psb_driver_unload(struct drm_device *dev) | |
487 | { | |
488 | struct drm_psb_private *dev_priv = | |
489 | (struct drm_psb_private *) dev->dev_private; | |
490 | ||
491 | /* Kill vblank etc here */ | |
492 | ||
493 | psb_backlight_exit(); /*writes minimum value to backlight HW reg */ | |
494 | ||
495 | if (drm_psb_no_fb == 0) | |
496 | psb_modeset_cleanup(dev); | |
497 | ||
498 | if (dev_priv) { | |
499 | psb_lid_timer_takedown(dev_priv); | |
500 | ||
501 | psb_do_takedown(dev); | |
502 | ||
503 | ||
504 | if (dev_priv->pf_pd) { | |
505 | psb_mmu_free_pagedir(dev_priv->pf_pd); | |
506 | dev_priv->pf_pd = NULL; | |
507 | } | |
508 | if (dev_priv->mmu) { | |
509 | struct psb_gtt *pg = dev_priv->pg; | |
510 | ||
511 | down_read(&pg->sem); | |
512 | psb_mmu_remove_pfn_sequence( | |
513 | psb_mmu_get_default_pd | |
514 | (dev_priv->mmu), | |
515 | pg->mmu_gatt_start, | |
516 | pg->vram_stolen_size >> PAGE_SHIFT); | |
517 | if (pg->ci_stolen_size != 0) | |
518 | psb_mmu_remove_pfn_sequence( | |
519 | psb_mmu_get_default_pd | |
520 | (dev_priv->mmu), | |
521 | pg->ci_start, | |
522 | pg->ci_stolen_size >> PAGE_SHIFT); | |
523 | if (pg->rar_stolen_size != 0) | |
524 | psb_mmu_remove_pfn_sequence( | |
525 | psb_mmu_get_default_pd | |
526 | (dev_priv->mmu), | |
527 | pg->rar_start, | |
528 | pg->rar_stolen_size >> PAGE_SHIFT); | |
529 | up_read(&pg->sem); | |
530 | psb_mmu_driver_takedown(dev_priv->mmu); | |
531 | dev_priv->mmu = NULL; | |
532 | } | |
533 | psb_gtt_takedown(dev_priv->pg, 1); | |
534 | if (dev_priv->scratch_page) { | |
535 | __free_page(dev_priv->scratch_page); | |
536 | dev_priv->scratch_page = NULL; | |
537 | } | |
538 | if (dev_priv->has_bo_device) { | |
539 | ttm_bo_device_release(&dev_priv->bdev); | |
540 | dev_priv->has_bo_device = 0; | |
541 | } | |
542 | if (dev_priv->has_fence_device) { | |
543 | ttm_fence_device_release(&dev_priv->fdev); | |
544 | dev_priv->has_fence_device = 0; | |
545 | } | |
546 | if (dev_priv->vdc_reg) { | |
547 | iounmap(dev_priv->vdc_reg); | |
548 | dev_priv->vdc_reg = NULL; | |
549 | } | |
550 | if (dev_priv->sgx_reg) { | |
551 | iounmap(dev_priv->sgx_reg); | |
552 | dev_priv->sgx_reg = NULL; | |
553 | } | |
554 | ||
555 | if (dev_priv->tdev) | |
556 | ttm_object_device_release(&dev_priv->tdev); | |
557 | ||
558 | if (dev_priv->has_global) | |
559 | psb_ttm_global_release(dev_priv); | |
560 | ||
561 | kfree(dev_priv); | |
562 | dev->dev_private = NULL; | |
563 | ||
25985edc | 564 | /*destroy VBT data*/ |
487e873d | 565 | psb_intel_destroy_bios(dev); |
0867b421 AC |
566 | } |
567 | ||
568 | ospm_power_uninit(); | |
569 | ||
570 | return 0; | |
571 | } | |
572 | ||
573 | ||
574 | static int psb_driver_load(struct drm_device *dev, unsigned long chipset) | |
575 | { | |
576 | struct drm_psb_private *dev_priv; | |
577 | struct ttm_bo_device *bdev; | |
578 | unsigned long resource_start; | |
579 | struct psb_gtt *pg; | |
580 | unsigned long irqflags; | |
581 | int ret = -ENOMEM; | |
582 | uint32_t tt_pages; | |
583 | ||
0867b421 AC |
584 | dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); |
585 | if (dev_priv == NULL) | |
586 | return -ENOMEM; | |
587 | INIT_LIST_HEAD(&dev_priv->video_ctx); | |
588 | ||
589 | dev_priv->num_pipe = 2; | |
590 | ||
591 | ||
592 | dev_priv->dev = dev; | |
593 | bdev = &dev_priv->bdev; | |
594 | ||
595 | ret = psb_ttm_global_init(dev_priv); | |
596 | if (unlikely(ret != 0)) | |
597 | goto out_err; | |
598 | dev_priv->has_global = 1; | |
599 | ||
600 | dev_priv->tdev = ttm_object_device_init | |
601 | (dev_priv->mem_global_ref.object, PSB_OBJECT_HASH_ORDER); | |
602 | if (unlikely(dev_priv->tdev == NULL)) | |
603 | goto out_err; | |
604 | ||
605 | mutex_init(&dev_priv->temp_mem); | |
606 | mutex_init(&dev_priv->cmdbuf_mutex); | |
607 | mutex_init(&dev_priv->reset_mutex); | |
608 | INIT_LIST_HEAD(&dev_priv->context.validate_list); | |
609 | INIT_LIST_HEAD(&dev_priv->context.kern_validate_list); | |
610 | ||
611 | /* mutex_init(&dev_priv->dsr_mutex); */ | |
612 | ||
613 | spin_lock_init(&dev_priv->reloc_lock); | |
614 | ||
615 | DRM_INIT_WAITQUEUE(&dev_priv->rel_mapped_queue); | |
616 | ||
617 | dev->dev_private = (void *) dev_priv; | |
618 | dev_priv->chipset = chipset; | |
619 | psb_set_uopt(&dev_priv->uopt); | |
620 | ||
621 | PSB_DEBUG_INIT("Mapping MMIO\n"); | |
622 | resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE); | |
623 | ||
624 | dev_priv->vdc_reg = | |
625 | ioremap(resource_start + PSB_VDC_OFFSET, PSB_VDC_SIZE); | |
626 | if (!dev_priv->vdc_reg) | |
627 | goto out_err; | |
628 | ||
629 | dev_priv->sgx_reg = ioremap(resource_start + PSB_SGX_OFFSET, | |
630 | PSB_SGX_SIZE); | |
631 | ||
632 | if (!dev_priv->sgx_reg) | |
633 | goto out_err; | |
634 | ||
635 | psb_get_core_freq(dev); | |
636 | psb_intel_opregion_init(dev); | |
637 | psb_intel_init_bios(dev); | |
638 | ||
639 | PSB_DEBUG_INIT("Init TTM fence and BO driver\n"); | |
640 | ||
641 | /* Init OSPM support */ | |
642 | ospm_power_init(dev); | |
643 | ||
644 | ret = psb_ttm_fence_device_init(&dev_priv->fdev); | |
645 | if (unlikely(ret != 0)) | |
646 | goto out_err; | |
647 | ||
648 | dev_priv->has_fence_device = 1; | |
649 | ret = ttm_bo_device_init(bdev, | |
650 | dev_priv->bo_global_ref.ref.object, | |
651 | &psb_ttm_bo_driver, | |
652 | DRM_PSB_FILE_PAGE_OFFSET, false); | |
653 | if (unlikely(ret != 0)) | |
654 | goto out_err; | |
655 | dev_priv->has_bo_device = 1; | |
656 | ttm_lock_init(&dev_priv->ttm_lock); | |
657 | ||
658 | ret = -ENOMEM; | |
659 | ||
660 | dev_priv->scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO); | |
661 | if (!dev_priv->scratch_page) | |
662 | goto out_err; | |
663 | ||
664 | set_pages_uc(dev_priv->scratch_page, 1); | |
665 | ||
666 | dev_priv->pg = psb_gtt_alloc(dev); | |
667 | if (!dev_priv->pg) | |
668 | goto out_err; | |
669 | ||
670 | ret = psb_gtt_init(dev_priv->pg, 0); | |
671 | if (ret) | |
672 | goto out_err; | |
673 | ||
674 | ret = psb_gtt_mm_init(dev_priv->pg); | |
675 | if (ret) | |
676 | goto out_err; | |
677 | ||
678 | dev_priv->mmu = psb_mmu_driver_init((void *)0, | |
679 | drm_psb_trap_pagefaults, 0, | |
680 | dev_priv); | |
681 | if (!dev_priv->mmu) | |
682 | goto out_err; | |
683 | ||
684 | pg = dev_priv->pg; | |
685 | ||
686 | tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ? | |
687 | (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT; | |
688 | ||
689 | /* CI/RAR use the lower half of TT. */ | |
690 | pg->ci_start = (tt_pages / 2) << PAGE_SHIFT; | |
691 | pg->rar_start = pg->ci_start + pg->ci_stolen_size; | |
692 | ||
693 | ||
694 | /* | |
695 | * Make MSVDX/TOPAZ MMU aware of the CI stolen memory area. | |
696 | */ | |
697 | if (dev_priv->pg->ci_stolen_size != 0) { | |
698 | down_read(&pg->sem); | |
699 | ret = psb_mmu_insert_pfn_sequence(psb_mmu_get_default_pd | |
700 | (dev_priv->mmu), | |
701 | dev_priv->ci_region_start >> PAGE_SHIFT, | |
702 | pg->mmu_gatt_start + pg->ci_start, | |
703 | pg->ci_stolen_size >> PAGE_SHIFT, 0); | |
704 | up_read(&pg->sem); | |
705 | if (ret) | |
706 | goto out_err; | |
707 | } | |
708 | ||
709 | /* | |
710 | * Make MSVDX/TOPAZ MMU aware of the rar stolen memory area. | |
711 | */ | |
712 | if (dev_priv->pg->rar_stolen_size != 0) { | |
713 | down_read(&pg->sem); | |
714 | ret = psb_mmu_insert_pfn_sequence( | |
715 | psb_mmu_get_default_pd(dev_priv->mmu), | |
716 | dev_priv->rar_region_start >> PAGE_SHIFT, | |
717 | pg->mmu_gatt_start + pg->rar_start, | |
718 | pg->rar_stolen_size >> PAGE_SHIFT, 0); | |
719 | up_read(&pg->sem); | |
720 | if (ret) | |
721 | goto out_err; | |
722 | } | |
723 | ||
724 | dev_priv->pf_pd = psb_mmu_alloc_pd(dev_priv->mmu, 1, 0); | |
725 | if (!dev_priv->pf_pd) | |
726 | goto out_err; | |
727 | ||
728 | psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0); | |
729 | psb_mmu_set_pd_context(dev_priv->pf_pd, 1); | |
730 | ||
731 | spin_lock_init(&dev_priv->sequence_lock); | |
732 | ||
733 | PSB_DEBUG_INIT("Begin to init MSVDX/Topaz\n"); | |
734 | ||
735 | ret = psb_do_init(dev); | |
736 | if (ret) | |
737 | return ret; | |
738 | ||
487e873d AC |
739 | /* igd_opregion_init(&dev_priv->opregion_dev); */ |
740 | acpi_video_register(); | |
0867b421 AC |
741 | if (dev_priv->lid_state) |
742 | psb_lid_timer_init(dev_priv); | |
743 | ||
744 | ret = drm_vblank_init(dev, dev_priv->num_pipe); | |
745 | if (ret) | |
746 | goto out_err; | |
747 | ||
748 | /* | |
749 | * Install interrupt handlers prior to powering off SGX or else we will | |
750 | * crash. | |
751 | */ | |
752 | dev_priv->vdc_irq_mask = 0; | |
753 | dev_priv->pipestat[0] = 0; | |
754 | dev_priv->pipestat[1] = 0; | |
755 | dev_priv->pipestat[2] = 0; | |
756 | spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); | |
aa19d8e9 | 757 | PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); |
0867b421 AC |
758 | PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R); |
759 | PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R); | |
760 | spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); | |
761 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | |
762 | drm_irq_install(dev); | |
763 | ||
764 | dev->vblank_disable_allowed = 1; | |
765 | ||
766 | dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ | |
767 | ||
768 | dev->driver->get_vblank_counter = psb_get_vblank_counter; | |
769 | ||
770 | if (drm_psb_no_fb == 0) { | |
771 | psb_modeset_init(dev); | |
772 | psb_fbdev_init(dev); | |
773 | drm_kms_helper_poll_init(dev); | |
774 | } | |
775 | ||
776 | ret = psb_backlight_init(dev); | |
777 | if (ret) | |
778 | return ret; | |
779 | #if 0 | |
780 | /*enable runtime pm at last*/ | |
781 | pm_runtime_enable(&dev->pdev->dev); | |
782 | pm_runtime_set_active(&dev->pdev->dev); | |
783 | #endif | |
784 | /*Intel drm driver load is done, continue doing pvr load*/ | |
785 | DRM_DEBUG("Pvr driver load\n"); | |
786 | ||
787 | /* if (PVRCore_Init() < 0) | |
788 | goto out_err; */ | |
789 | /* if (MRSTLFBInit(dev) < 0) | |
790 | goto out_err;*/ | |
791 | return 0; | |
792 | out_err: | |
793 | psb_driver_unload(dev); | |
794 | return ret; | |
795 | } | |
796 | ||
797 | int psb_driver_device_is_agp(struct drm_device *dev) | |
798 | { | |
799 | return 0; | |
800 | } | |
801 | ||
802 | ||
803 | static int psb_vt_leave_ioctl(struct drm_device *dev, void *data, | |
804 | struct drm_file *file_priv) | |
805 | { | |
806 | struct drm_psb_private *dev_priv = psb_priv(dev); | |
807 | struct ttm_bo_device *bdev = &dev_priv->bdev; | |
808 | struct ttm_mem_type_manager *man; | |
809 | int ret; | |
810 | ||
811 | ret = ttm_vt_lock(&dev_priv->ttm_lock, 1, | |
812 | psb_fpriv(file_priv)->tfile); | |
813 | if (unlikely(ret != 0)) | |
814 | return ret; | |
815 | ||
816 | ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_TT); | |
817 | if (unlikely(ret != 0)) | |
818 | goto out_unlock; | |
819 | ||
820 | man = &bdev->man[TTM_PL_TT]; | |
821 | ||
822 | #if 0 /* What to do with this ? */ | |
823 | if (unlikely(!drm_mm_clean(&man->manager))) | |
824 | DRM_INFO("Warning: GATT was not clean after VT switch.\n"); | |
825 | #endif | |
826 | ||
827 | ttm_bo_swapout_all(&dev_priv->bdev); | |
828 | ||
829 | return 0; | |
830 | out_unlock: | |
831 | (void) ttm_vt_unlock(&dev_priv->ttm_lock); | |
832 | return ret; | |
833 | } | |
834 | ||
835 | static int psb_vt_enter_ioctl(struct drm_device *dev, void *data, | |
836 | struct drm_file *file_priv) | |
837 | { | |
838 | struct drm_psb_private *dev_priv = psb_priv(dev); | |
839 | return ttm_vt_unlock(&dev_priv->ttm_lock); | |
840 | } | |
841 | ||
842 | static int psb_sizes_ioctl(struct drm_device *dev, void *data, | |
843 | struct drm_file *file_priv) | |
844 | { | |
845 | struct drm_psb_private *dev_priv = psb_priv(dev); | |
846 | struct drm_psb_sizes_arg *arg = | |
847 | (struct drm_psb_sizes_arg *) data; | |
848 | ||
849 | *arg = dev_priv->sizes; | |
850 | return 0; | |
851 | } | |
852 | ||
853 | static int psb_dc_state_ioctl(struct drm_device *dev, void * data, | |
854 | struct drm_file *file_priv) | |
855 | { | |
856 | uint32_t flags; | |
857 | uint32_t obj_id; | |
858 | struct drm_mode_object *obj; | |
859 | struct drm_connector *connector; | |
860 | struct drm_crtc *crtc; | |
861 | struct drm_psb_dc_state_arg *arg = | |
862 | (struct drm_psb_dc_state_arg *)data; | |
863 | ||
864 | flags = arg->flags; | |
865 | obj_id = arg->obj_id; | |
866 | ||
867 | if (flags & PSB_DC_CRTC_MASK) { | |
868 | obj = drm_mode_object_find(dev, obj_id, | |
869 | DRM_MODE_OBJECT_CRTC); | |
870 | if (!obj) { | |
871 | DRM_DEBUG("Invalid CRTC object.\n"); | |
872 | return -EINVAL; | |
873 | } | |
874 | ||
875 | crtc = obj_to_crtc(obj); | |
876 | ||
877 | mutex_lock(&dev->mode_config.mutex); | |
878 | if (drm_helper_crtc_in_use(crtc)) { | |
879 | if (flags & PSB_DC_CRTC_SAVE) | |
880 | crtc->funcs->save(crtc); | |
881 | else | |
882 | crtc->funcs->restore(crtc); | |
883 | } | |
884 | mutex_unlock(&dev->mode_config.mutex); | |
885 | ||
886 | return 0; | |
887 | } else if (flags & PSB_DC_OUTPUT_MASK) { | |
888 | obj = drm_mode_object_find(dev, obj_id, | |
889 | DRM_MODE_OBJECT_CONNECTOR); | |
890 | if (!obj) { | |
891 | DRM_DEBUG("Invalid connector id.\n"); | |
892 | return -EINVAL; | |
893 | } | |
894 | ||
895 | connector = obj_to_connector(obj); | |
896 | if (flags & PSB_DC_OUTPUT_SAVE) | |
897 | connector->funcs->save(connector); | |
898 | else | |
899 | connector->funcs->restore(connector); | |
900 | ||
901 | return 0; | |
902 | } | |
903 | ||
904 | DRM_DEBUG("Bad flags 0x%x\n", flags); | |
905 | return -EINVAL; | |
906 | } | |
907 | ||
908 | static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data, | |
909 | struct drm_file *file_priv) | |
910 | { | |
911 | struct drm_psb_private *dev_priv = psb_priv(dev); | |
912 | uint32_t *arg = data; | |
913 | struct backlight_device bd; | |
914 | dev_priv->blc_adj2 = *arg; | |
915 | ||
916 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | |
917 | bd.props.brightness = psb_get_brightness(&bd); | |
918 | psb_set_brightness(&bd); | |
919 | #endif | |
920 | return 0; | |
921 | } | |
922 | ||
923 | static int psb_adb_ioctl(struct drm_device *dev, void *data, | |
924 | struct drm_file *file_priv) | |
925 | { | |
926 | struct drm_psb_private *dev_priv = psb_priv(dev); | |
927 | uint32_t *arg = data; | |
928 | struct backlight_device bd; | |
929 | dev_priv->blc_adj1 = *arg; | |
930 | ||
931 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | |
932 | bd.props.brightness = psb_get_brightness(&bd); | |
933 | psb_set_brightness(&bd); | |
934 | #endif | |
935 | return 0; | |
936 | } | |
937 | ||
938 | /* return the current mode to the dpst module */ | |
939 | static int psb_dpst_ioctl(struct drm_device *dev, void *data, | |
940 | struct drm_file *file_priv) | |
941 | { | |
942 | struct drm_psb_private *dev_priv = psb_priv(dev); | |
943 | uint32_t *arg = data; | |
944 | uint32_t x; | |
945 | uint32_t y; | |
946 | uint32_t reg; | |
947 | ||
948 | if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, | |
949 | OSPM_UHB_ONLY_IF_ON)) | |
950 | return 0; | |
951 | ||
952 | reg = PSB_RVDC32(PIPEASRC); | |
953 | ||
954 | ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); | |
955 | ||
956 | /* horizontal is the left 16 bits */ | |
957 | x = reg >> 16; | |
958 | /* vertical is the right 16 bits */ | |
959 | y = reg & 0x0000ffff; | |
960 | ||
961 | /* the values are the image size minus one */ | |
962 | x++; | |
963 | y++; | |
964 | ||
965 | *arg = (x << 16) | y; | |
966 | ||
967 | return 0; | |
968 | } | |
969 | static int psb_gamma_ioctl(struct drm_device *dev, void *data, | |
970 | struct drm_file *file_priv) | |
971 | { | |
972 | struct drm_psb_dpst_lut_arg *lut_arg = data; | |
973 | struct drm_mode_object *obj; | |
974 | struct drm_crtc *crtc; | |
975 | struct drm_connector *connector; | |
976 | struct psb_intel_crtc *psb_intel_crtc; | |
977 | int i = 0; | |
978 | int32_t obj_id; | |
979 | ||
980 | obj_id = lut_arg->output_id; | |
981 | obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR); | |
982 | if (!obj) { | |
983 | DRM_DEBUG("Invalid Connector object.\n"); | |
984 | return -EINVAL; | |
985 | } | |
986 | ||
987 | connector = obj_to_connector(obj); | |
988 | crtc = connector->encoder->crtc; | |
989 | psb_intel_crtc = to_psb_intel_crtc(crtc); | |
990 | ||
991 | for (i = 0; i < 256; i++) | |
992 | psb_intel_crtc->lut_adj[i] = lut_arg->lut[i]; | |
993 | ||
994 | psb_intel_crtc_load_lut(crtc); | |
995 | ||
996 | return 0; | |
997 | } | |
998 | ||
999 | static int psb_mode_operation_ioctl(struct drm_device *dev, void *data, | |
1000 | struct drm_file *file_priv) | |
1001 | { | |
1002 | uint32_t obj_id; | |
1003 | uint16_t op; | |
1004 | struct drm_mode_modeinfo *umode; | |
1005 | struct drm_display_mode *mode = NULL; | |
1006 | struct drm_psb_mode_operation_arg *arg; | |
1007 | struct drm_mode_object *obj; | |
1008 | struct drm_connector *connector; | |
1009 | struct drm_framebuffer *drm_fb; | |
1010 | struct psb_framebuffer *psb_fb; | |
1011 | struct drm_connector_helper_funcs *connector_funcs; | |
1012 | int ret = 0; | |
1013 | int resp = MODE_OK; | |
1014 | struct drm_psb_private *dev_priv = psb_priv(dev); | |
1015 | ||
1016 | arg = (struct drm_psb_mode_operation_arg *)data; | |
1017 | obj_id = arg->obj_id; | |
1018 | op = arg->operation; | |
1019 | ||
1020 | switch (op) { | |
1021 | case PSB_MODE_OPERATION_SET_DC_BASE: | |
1022 | obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_FB); | |
1023 | if (!obj) { | |
1024 | DRM_ERROR("Invalid FB id %d\n", obj_id); | |
1025 | return -EINVAL; | |
1026 | } | |
1027 | ||
1028 | drm_fb = obj_to_fb(obj); | |
1029 | psb_fb = to_psb_fb(drm_fb); | |
1030 | ||
1031 | if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, | |
1032 | OSPM_UHB_ONLY_IF_ON)) { | |
1033 | REG_WRITE(DSPASURF, psb_fb->offset); | |
1034 | REG_READ(DSPASURF); | |
1035 | ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); | |
1036 | } else { | |
1037 | dev_priv->saveDSPASURF = psb_fb->offset; | |
1038 | } | |
1039 | ||
1040 | return 0; | |
1041 | case PSB_MODE_OPERATION_MODE_VALID: | |
1042 | umode = &arg->mode; | |
1043 | ||
1044 | mutex_lock(&dev->mode_config.mutex); | |
1045 | ||
1046 | obj = drm_mode_object_find(dev, obj_id, | |
1047 | DRM_MODE_OBJECT_CONNECTOR); | |
1048 | if (!obj) { | |
1049 | ret = -EINVAL; | |
1050 | goto mode_op_out; | |
1051 | } | |
1052 | ||
1053 | connector = obj_to_connector(obj); | |
1054 | ||
1055 | mode = drm_mode_create(dev); | |
1056 | if (!mode) { | |
1057 | ret = -ENOMEM; | |
1058 | goto mode_op_out; | |
1059 | } | |
1060 | ||
1061 | /* drm_crtc_convert_umode(mode, umode); */ | |
1062 | { | |
1063 | mode->clock = umode->clock; | |
1064 | mode->hdisplay = umode->hdisplay; | |
1065 | mode->hsync_start = umode->hsync_start; | |
1066 | mode->hsync_end = umode->hsync_end; | |
1067 | mode->htotal = umode->htotal; | |
1068 | mode->hskew = umode->hskew; | |
1069 | mode->vdisplay = umode->vdisplay; | |
1070 | mode->vsync_start = umode->vsync_start; | |
1071 | mode->vsync_end = umode->vsync_end; | |
1072 | mode->vtotal = umode->vtotal; | |
1073 | mode->vscan = umode->vscan; | |
1074 | mode->vrefresh = umode->vrefresh; | |
1075 | mode->flags = umode->flags; | |
1076 | mode->type = umode->type; | |
1077 | strncpy(mode->name, umode->name, DRM_DISPLAY_MODE_LEN); | |
1078 | mode->name[DRM_DISPLAY_MODE_LEN-1] = 0; | |
1079 | } | |
1080 | ||
1081 | connector_funcs = (struct drm_connector_helper_funcs *) | |
1082 | connector->helper_private; | |
1083 | ||
1084 | if (connector_funcs->mode_valid) { | |
1085 | resp = connector_funcs->mode_valid(connector, mode); | |
1086 | arg->data = (void *)resp; | |
1087 | } | |
1088 | ||
1089 | /*do some clean up work*/ | |
1090 | if (mode) | |
1091 | drm_mode_destroy(dev, mode); | |
1092 | mode_op_out: | |
1093 | mutex_unlock(&dev->mode_config.mutex); | |
1094 | return ret; | |
1095 | ||
1096 | default: | |
1097 | DRM_DEBUG("Unsupported psb mode operation"); | |
1098 | return -EOPNOTSUPP; | |
1099 | } | |
1100 | ||
1101 | return 0; | |
1102 | } | |
1103 | ||
1104 | static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data, | |
1105 | struct drm_file *file_priv) | |
1106 | { | |
1107 | struct drm_psb_private *dev_priv = psb_priv(dev); | |
1108 | struct drm_psb_stolen_memory_arg *arg = data; | |
1109 | ||
1110 | arg->base = dev_priv->pg->stolen_base; | |
1111 | arg->size = dev_priv->pg->vram_stolen_size; | |
1112 | ||
1113 | return 0; | |
1114 | } | |
1115 | ||
1116 | static int psb_register_rw_ioctl(struct drm_device *dev, void *data, | |
1117 | struct drm_file *file_priv) | |
1118 | { | |
1119 | struct drm_psb_private *dev_priv = psb_priv(dev); | |
1120 | struct drm_psb_register_rw_arg *arg = data; | |
1121 | UHBUsage usage = | |
1122 | arg->b_force_hw_on ? OSPM_UHB_FORCE_POWER_ON : OSPM_UHB_ONLY_IF_ON; | |
1123 | ||
1124 | if (arg->display_write_mask != 0) { | |
1125 | if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) { | |
1126 | if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS) | |
1127 | PSB_WVDC32(arg->display.pfit_controls, | |
1128 | PFIT_CONTROL); | |
1129 | if (arg->display_write_mask & | |
1130 | REGRWBITS_PFIT_AUTOSCALE_RATIOS) | |
1131 | PSB_WVDC32(arg->display.pfit_autoscale_ratios, | |
1132 | PFIT_AUTO_RATIOS); | |
1133 | if (arg->display_write_mask & | |
1134 | REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS) | |
1135 | PSB_WVDC32( | |
1136 | arg->display.pfit_programmed_scale_ratios, | |
1137 | PFIT_PGM_RATIOS); | |
1138 | if (arg->display_write_mask & REGRWBITS_PIPEASRC) | |
1139 | PSB_WVDC32(arg->display.pipeasrc, | |
1140 | PIPEASRC); | |
1141 | if (arg->display_write_mask & REGRWBITS_PIPEBSRC) | |
1142 | PSB_WVDC32(arg->display.pipebsrc, | |
1143 | PIPEBSRC); | |
1144 | if (arg->display_write_mask & REGRWBITS_VTOTAL_A) | |
1145 | PSB_WVDC32(arg->display.vtotal_a, | |
1146 | VTOTAL_A); | |
1147 | if (arg->display_write_mask & REGRWBITS_VTOTAL_B) | |
1148 | PSB_WVDC32(arg->display.vtotal_b, | |
1149 | VTOTAL_B); | |
1150 | ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); | |
1151 | } else { | |
1152 | if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS) | |
1153 | dev_priv->savePFIT_CONTROL = | |
1154 | arg->display.pfit_controls; | |
1155 | if (arg->display_write_mask & | |
1156 | REGRWBITS_PFIT_AUTOSCALE_RATIOS) | |
1157 | dev_priv->savePFIT_AUTO_RATIOS = | |
1158 | arg->display.pfit_autoscale_ratios; | |
1159 | if (arg->display_write_mask & | |
1160 | REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS) | |
1161 | dev_priv->savePFIT_PGM_RATIOS = | |
1162 | arg->display.pfit_programmed_scale_ratios; | |
1163 | if (arg->display_write_mask & REGRWBITS_PIPEASRC) | |
1164 | dev_priv->savePIPEASRC = arg->display.pipeasrc; | |
1165 | if (arg->display_write_mask & REGRWBITS_PIPEBSRC) | |
1166 | dev_priv->savePIPEBSRC = arg->display.pipebsrc; | |
1167 | if (arg->display_write_mask & REGRWBITS_VTOTAL_A) | |
1168 | dev_priv->saveVTOTAL_A = arg->display.vtotal_a; | |
1169 | if (arg->display_write_mask & REGRWBITS_VTOTAL_B) | |
1170 | dev_priv->saveVTOTAL_B = arg->display.vtotal_b; | |
1171 | } | |
1172 | } | |
1173 | ||
1174 | if (arg->display_read_mask != 0) { | |
1175 | if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) { | |
1176 | if (arg->display_read_mask & | |
1177 | REGRWBITS_PFIT_CONTROLS) | |
1178 | arg->display.pfit_controls = | |
1179 | PSB_RVDC32(PFIT_CONTROL); | |
1180 | if (arg->display_read_mask & | |
1181 | REGRWBITS_PFIT_AUTOSCALE_RATIOS) | |
1182 | arg->display.pfit_autoscale_ratios = | |
1183 | PSB_RVDC32(PFIT_AUTO_RATIOS); | |
1184 | if (arg->display_read_mask & | |
1185 | REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS) | |
1186 | arg->display.pfit_programmed_scale_ratios = | |
1187 | PSB_RVDC32(PFIT_PGM_RATIOS); | |
1188 | if (arg->display_read_mask & REGRWBITS_PIPEASRC) | |
1189 | arg->display.pipeasrc = PSB_RVDC32(PIPEASRC); | |
1190 | if (arg->display_read_mask & REGRWBITS_PIPEBSRC) | |
1191 | arg->display.pipebsrc = PSB_RVDC32(PIPEBSRC); | |
1192 | if (arg->display_read_mask & REGRWBITS_VTOTAL_A) | |
1193 | arg->display.vtotal_a = PSB_RVDC32(VTOTAL_A); | |
1194 | if (arg->display_read_mask & REGRWBITS_VTOTAL_B) | |
1195 | arg->display.vtotal_b = PSB_RVDC32(VTOTAL_B); | |
1196 | ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); | |
1197 | } else { | |
1198 | if (arg->display_read_mask & | |
1199 | REGRWBITS_PFIT_CONTROLS) | |
1200 | arg->display.pfit_controls = | |
1201 | dev_priv->savePFIT_CONTROL; | |
1202 | if (arg->display_read_mask & | |
1203 | REGRWBITS_PFIT_AUTOSCALE_RATIOS) | |
1204 | arg->display.pfit_autoscale_ratios = | |
1205 | dev_priv->savePFIT_AUTO_RATIOS; | |
1206 | if (arg->display_read_mask & | |
1207 | REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS) | |
1208 | arg->display.pfit_programmed_scale_ratios = | |
1209 | dev_priv->savePFIT_PGM_RATIOS; | |
1210 | if (arg->display_read_mask & REGRWBITS_PIPEASRC) | |
1211 | arg->display.pipeasrc = dev_priv->savePIPEASRC; | |
1212 | if (arg->display_read_mask & REGRWBITS_PIPEBSRC) | |
1213 | arg->display.pipebsrc = dev_priv->savePIPEBSRC; | |
1214 | if (arg->display_read_mask & REGRWBITS_VTOTAL_A) | |
1215 | arg->display.vtotal_a = dev_priv->saveVTOTAL_A; | |
1216 | if (arg->display_read_mask & REGRWBITS_VTOTAL_B) | |
1217 | arg->display.vtotal_b = dev_priv->saveVTOTAL_B; | |
1218 | } | |
1219 | } | |
1220 | ||
1221 | if (arg->overlay_write_mask != 0) { | |
1222 | if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) { | |
1223 | if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) { | |
1224 | PSB_WVDC32(arg->overlay.OGAMC5, OV_OGAMC5); | |
1225 | PSB_WVDC32(arg->overlay.OGAMC4, OV_OGAMC4); | |
1226 | PSB_WVDC32(arg->overlay.OGAMC3, OV_OGAMC3); | |
1227 | PSB_WVDC32(arg->overlay.OGAMC2, OV_OGAMC2); | |
1228 | PSB_WVDC32(arg->overlay.OGAMC1, OV_OGAMC1); | |
1229 | PSB_WVDC32(arg->overlay.OGAMC0, OV_OGAMC0); | |
1230 | } | |
1231 | if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) { | |
1232 | PSB_WVDC32(arg->overlay.OGAMC5, OVC_OGAMC5); | |
1233 | PSB_WVDC32(arg->overlay.OGAMC4, OVC_OGAMC4); | |
1234 | PSB_WVDC32(arg->overlay.OGAMC3, OVC_OGAMC3); | |
1235 | PSB_WVDC32(arg->overlay.OGAMC2, OVC_OGAMC2); | |
1236 | PSB_WVDC32(arg->overlay.OGAMC1, OVC_OGAMC1); | |
1237 | PSB_WVDC32(arg->overlay.OGAMC0, OVC_OGAMC0); | |
1238 | } | |
1239 | ||
1240 | if (arg->overlay_write_mask & OV_REGRWBITS_OVADD) { | |
1241 | PSB_WVDC32(arg->overlay.OVADD, OV_OVADD); | |
1242 | ||
1243 | if (arg->overlay.b_wait_vblank) { | |
1244 | /* Wait for 20ms.*/ | |
1245 | unsigned long vblank_timeout = jiffies | |
1246 | + HZ/50; | |
1247 | uint32_t temp; | |
1248 | while (time_before_eq(jiffies, | |
1249 | vblank_timeout)) { | |
1250 | temp = PSB_RVDC32(OV_DOVASTA); | |
1251 | if ((temp & (0x1 << 31)) != 0) | |
1252 | break; | |
1253 | cpu_relax(); | |
1254 | } | |
1255 | } | |
1256 | } | |
1257 | if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD) { | |
1258 | PSB_WVDC32(arg->overlay.OVADD, OVC_OVADD); | |
1259 | if (arg->overlay.b_wait_vblank) { | |
1260 | /* Wait for 20ms.*/ | |
1261 | unsigned long vblank_timeout = | |
1262 | jiffies + HZ/50; | |
1263 | uint32_t temp; | |
1264 | while (time_before_eq(jiffies, | |
1265 | vblank_timeout)) { | |
1266 | temp = PSB_RVDC32(OVC_DOVCSTA); | |
1267 | if ((temp & (0x1 << 31)) != 0) | |
1268 | break; | |
1269 | cpu_relax(); | |
1270 | } | |
1271 | } | |
1272 | } | |
1273 | ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); | |
1274 | } else { | |
1275 | if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) { | |
1276 | dev_priv->saveOV_OGAMC5 = arg->overlay.OGAMC5; | |
1277 | dev_priv->saveOV_OGAMC4 = arg->overlay.OGAMC4; | |
1278 | dev_priv->saveOV_OGAMC3 = arg->overlay.OGAMC3; | |
1279 | dev_priv->saveOV_OGAMC2 = arg->overlay.OGAMC2; | |
1280 | dev_priv->saveOV_OGAMC1 = arg->overlay.OGAMC1; | |
1281 | dev_priv->saveOV_OGAMC0 = arg->overlay.OGAMC0; | |
1282 | } | |
1283 | if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) { | |
1284 | dev_priv->saveOVC_OGAMC5 = arg->overlay.OGAMC5; | |
1285 | dev_priv->saveOVC_OGAMC4 = arg->overlay.OGAMC4; | |
1286 | dev_priv->saveOVC_OGAMC3 = arg->overlay.OGAMC3; | |
1287 | dev_priv->saveOVC_OGAMC2 = arg->overlay.OGAMC2; | |
1288 | dev_priv->saveOVC_OGAMC1 = arg->overlay.OGAMC1; | |
1289 | dev_priv->saveOVC_OGAMC0 = arg->overlay.OGAMC0; | |
1290 | } | |
1291 | if (arg->overlay_write_mask & OV_REGRWBITS_OVADD) | |
1292 | dev_priv->saveOV_OVADD = arg->overlay.OVADD; | |
1293 | if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD) | |
1294 | dev_priv->saveOVC_OVADD = arg->overlay.OVADD; | |
1295 | } | |
1296 | } | |
1297 | ||
1298 | if (arg->overlay_read_mask != 0) { | |
1299 | if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) { | |
1300 | if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) { | |
1301 | arg->overlay.OGAMC5 = PSB_RVDC32(OV_OGAMC5); | |
1302 | arg->overlay.OGAMC4 = PSB_RVDC32(OV_OGAMC4); | |
1303 | arg->overlay.OGAMC3 = PSB_RVDC32(OV_OGAMC3); | |
1304 | arg->overlay.OGAMC2 = PSB_RVDC32(OV_OGAMC2); | |
1305 | arg->overlay.OGAMC1 = PSB_RVDC32(OV_OGAMC1); | |
1306 | arg->overlay.OGAMC0 = PSB_RVDC32(OV_OGAMC0); | |
1307 | } | |
1308 | if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) { | |
1309 | arg->overlay.OGAMC5 = PSB_RVDC32(OVC_OGAMC5); | |
1310 | arg->overlay.OGAMC4 = PSB_RVDC32(OVC_OGAMC4); | |
1311 | arg->overlay.OGAMC3 = PSB_RVDC32(OVC_OGAMC3); | |
1312 | arg->overlay.OGAMC2 = PSB_RVDC32(OVC_OGAMC2); | |
1313 | arg->overlay.OGAMC1 = PSB_RVDC32(OVC_OGAMC1); | |
1314 | arg->overlay.OGAMC0 = PSB_RVDC32(OVC_OGAMC0); | |
1315 | } | |
1316 | if (arg->overlay_read_mask & OV_REGRWBITS_OVADD) | |
1317 | arg->overlay.OVADD = PSB_RVDC32(OV_OVADD); | |
1318 | if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD) | |
1319 | arg->overlay.OVADD = PSB_RVDC32(OVC_OVADD); | |
1320 | ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); | |
1321 | } else { | |
1322 | if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) { | |
1323 | arg->overlay.OGAMC5 = dev_priv->saveOV_OGAMC5; | |
1324 | arg->overlay.OGAMC4 = dev_priv->saveOV_OGAMC4; | |
1325 | arg->overlay.OGAMC3 = dev_priv->saveOV_OGAMC3; | |
1326 | arg->overlay.OGAMC2 = dev_priv->saveOV_OGAMC2; | |
1327 | arg->overlay.OGAMC1 = dev_priv->saveOV_OGAMC1; | |
1328 | arg->overlay.OGAMC0 = dev_priv->saveOV_OGAMC0; | |
1329 | } | |
1330 | if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) { | |
1331 | arg->overlay.OGAMC5 = dev_priv->saveOVC_OGAMC5; | |
1332 | arg->overlay.OGAMC4 = dev_priv->saveOVC_OGAMC4; | |
1333 | arg->overlay.OGAMC3 = dev_priv->saveOVC_OGAMC3; | |
1334 | arg->overlay.OGAMC2 = dev_priv->saveOVC_OGAMC2; | |
1335 | arg->overlay.OGAMC1 = dev_priv->saveOVC_OGAMC1; | |
1336 | arg->overlay.OGAMC0 = dev_priv->saveOVC_OGAMC0; | |
1337 | } | |
1338 | if (arg->overlay_read_mask & OV_REGRWBITS_OVADD) | |
1339 | arg->overlay.OVADD = dev_priv->saveOV_OVADD; | |
1340 | if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD) | |
1341 | arg->overlay.OVADD = dev_priv->saveOVC_OVADD; | |
1342 | } | |
1343 | } | |
1344 | ||
1345 | if (arg->sprite_enable_mask != 0) { | |
1346 | if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) { | |
1347 | PSB_WVDC32(0x1F3E, DSPARB); | |
1348 | PSB_WVDC32(arg->sprite.dspa_control | |
1349 | | PSB_RVDC32(DSPACNTR), DSPACNTR); | |
1350 | PSB_WVDC32(arg->sprite.dspa_key_value, DSPAKEYVAL); | |
1351 | PSB_WVDC32(arg->sprite.dspa_key_mask, DSPAKEYMASK); | |
1352 | PSB_WVDC32(PSB_RVDC32(DSPASURF), DSPASURF); | |
1353 | PSB_RVDC32(DSPASURF); | |
1354 | PSB_WVDC32(arg->sprite.dspc_control, DSPCCNTR); | |
1355 | PSB_WVDC32(arg->sprite.dspc_stride, DSPCSTRIDE); | |
1356 | PSB_WVDC32(arg->sprite.dspc_position, DSPCPOS); | |
1357 | PSB_WVDC32(arg->sprite.dspc_linear_offset, DSPCLINOFF); | |
1358 | PSB_WVDC32(arg->sprite.dspc_size, DSPCSIZE); | |
1359 | PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF); | |
1360 | PSB_RVDC32(DSPCSURF); | |
1361 | ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); | |
1362 | } | |
1363 | } | |
1364 | ||
1365 | if (arg->sprite_disable_mask != 0) { | |
1366 | if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) { | |
1367 | PSB_WVDC32(0x3F3E, DSPARB); | |
1368 | PSB_WVDC32(0x0, DSPCCNTR); | |
1369 | PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF); | |
1370 | PSB_RVDC32(DSPCSURF); | |
1371 | ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); | |
1372 | } | |
1373 | } | |
1374 | ||
1375 | if (arg->subpicture_enable_mask != 0) { | |
1376 | if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) { | |
1377 | uint32_t temp; | |
1378 | if (arg->subpicture_enable_mask & REGRWBITS_DSPACNTR) { | |
1379 | temp = PSB_RVDC32(DSPACNTR); | |
1380 | temp &= ~DISPPLANE_PIXFORMAT_MASK; | |
1381 | temp &= ~DISPPLANE_BOTTOM; | |
1382 | temp |= DISPPLANE_32BPP; | |
1383 | PSB_WVDC32(temp, DSPACNTR); | |
1384 | ||
1385 | temp = PSB_RVDC32(DSPABASE); | |
1386 | PSB_WVDC32(temp, DSPABASE); | |
1387 | PSB_RVDC32(DSPABASE); | |
1388 | temp = PSB_RVDC32(DSPASURF); | |
1389 | PSB_WVDC32(temp, DSPASURF); | |
1390 | PSB_RVDC32(DSPASURF); | |
1391 | } | |
1392 | if (arg->subpicture_enable_mask & REGRWBITS_DSPBCNTR) { | |
1393 | temp = PSB_RVDC32(DSPBCNTR); | |
1394 | temp &= ~DISPPLANE_PIXFORMAT_MASK; | |
1395 | temp &= ~DISPPLANE_BOTTOM; | |
1396 | temp |= DISPPLANE_32BPP; | |
1397 | PSB_WVDC32(temp, DSPBCNTR); | |
1398 | ||
1399 | temp = PSB_RVDC32(DSPBBASE); | |
1400 | PSB_WVDC32(temp, DSPBBASE); | |
1401 | PSB_RVDC32(DSPBBASE); | |
1402 | temp = PSB_RVDC32(DSPBSURF); | |
1403 | PSB_WVDC32(temp, DSPBSURF); | |
1404 | PSB_RVDC32(DSPBSURF); | |
1405 | } | |
1406 | if (arg->subpicture_enable_mask & REGRWBITS_DSPCCNTR) { | |
1407 | temp = PSB_RVDC32(DSPCCNTR); | |
1408 | temp &= ~DISPPLANE_PIXFORMAT_MASK; | |
1409 | temp &= ~DISPPLANE_BOTTOM; | |
1410 | temp |= DISPPLANE_32BPP; | |
1411 | PSB_WVDC32(temp, DSPCCNTR); | |
1412 | ||
1413 | temp = PSB_RVDC32(DSPCBASE); | |
1414 | PSB_WVDC32(temp, DSPCBASE); | |
1415 | PSB_RVDC32(DSPCBASE); | |
1416 | temp = PSB_RVDC32(DSPCSURF); | |
1417 | PSB_WVDC32(temp, DSPCSURF); | |
1418 | PSB_RVDC32(DSPCSURF); | |
1419 | } | |
1420 | ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); | |
1421 | } | |
1422 | } | |
1423 | ||
1424 | if (arg->subpicture_disable_mask != 0) { | |
1425 | if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) { | |
1426 | uint32_t temp; | |
1427 | if (arg->subpicture_disable_mask & REGRWBITS_DSPACNTR) { | |
1428 | temp = PSB_RVDC32(DSPACNTR); | |
1429 | temp &= ~DISPPLANE_PIXFORMAT_MASK; | |
1430 | temp |= DISPPLANE_32BPP_NO_ALPHA; | |
1431 | PSB_WVDC32(temp, DSPACNTR); | |
1432 | ||
1433 | temp = PSB_RVDC32(DSPABASE); | |
1434 | PSB_WVDC32(temp, DSPABASE); | |
1435 | PSB_RVDC32(DSPABASE); | |
1436 | temp = PSB_RVDC32(DSPASURF); | |
1437 | PSB_WVDC32(temp, DSPASURF); | |
1438 | PSB_RVDC32(DSPASURF); | |
1439 | } | |
1440 | if (arg->subpicture_disable_mask & REGRWBITS_DSPBCNTR) { | |
1441 | temp = PSB_RVDC32(DSPBCNTR); | |
1442 | temp &= ~DISPPLANE_PIXFORMAT_MASK; | |
1443 | temp |= DISPPLANE_32BPP_NO_ALPHA; | |
1444 | PSB_WVDC32(temp, DSPBCNTR); | |
1445 | ||
1446 | temp = PSB_RVDC32(DSPBBASE); | |
1447 | PSB_WVDC32(temp, DSPBBASE); | |
1448 | PSB_RVDC32(DSPBBASE); | |
1449 | temp = PSB_RVDC32(DSPBSURF); | |
1450 | PSB_WVDC32(temp, DSPBSURF); | |
1451 | PSB_RVDC32(DSPBSURF); | |
1452 | } | |
1453 | if (arg->subpicture_disable_mask & REGRWBITS_DSPCCNTR) { | |
1454 | temp = PSB_RVDC32(DSPCCNTR); | |
1455 | temp &= ~DISPPLANE_PIXFORMAT_MASK; | |
1456 | temp |= DISPPLANE_32BPP_NO_ALPHA; | |
1457 | PSB_WVDC32(temp, DSPCCNTR); | |
1458 | ||
1459 | temp = PSB_RVDC32(DSPCBASE); | |
1460 | PSB_WVDC32(temp, DSPCBASE); | |
1461 | PSB_RVDC32(DSPCBASE); | |
1462 | temp = PSB_RVDC32(DSPCSURF); | |
1463 | PSB_WVDC32(temp, DSPCSURF); | |
1464 | PSB_RVDC32(DSPCSURF); | |
1465 | } | |
1466 | ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); | |
1467 | } | |
1468 | } | |
1469 | ||
1470 | return 0; | |
1471 | } | |
1472 | ||
1473 | /* always available as we are SIGIO'd */ | |
1474 | static unsigned int psb_poll(struct file *filp, | |
1475 | struct poll_table_struct *wait) | |
1476 | { | |
1477 | return POLLIN | POLLRDNORM; | |
1478 | } | |
1479 | ||
1480 | /* Not sure what we will need yet - in the PVR driver this disappears into | |
1481 | a tangle of abstracted handlers and per process crap */ | |
1482 | ||
1483 | struct psb_priv { | |
1484 | int dummy; | |
1485 | }; | |
1486 | ||
1487 | static int psb_driver_open(struct drm_device *dev, struct drm_file *priv) | |
1488 | { | |
1489 | struct psb_priv *psb = kzalloc(sizeof(struct psb_priv), GFP_KERNEL); | |
1490 | if (psb == NULL) | |
1491 | return -ENOMEM; | |
1492 | priv->driver_priv = psb; | |
1493 | DRM_DEBUG("\n"); | |
1494 | /*return PVRSRVOpen(dev, priv);*/ | |
1495 | return 0; | |
1496 | } | |
1497 | ||
1498 | static void psb_driver_close(struct drm_device *dev, struct drm_file *priv) | |
1499 | { | |
1500 | kfree(priv->driver_priv); | |
1501 | priv->driver_priv = NULL; | |
1502 | } | |
1503 | ||
1504 | static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd, | |
1505 | unsigned long arg) | |
1506 | { | |
1507 | struct drm_file *file_priv = filp->private_data; | |
1508 | struct drm_device *dev = file_priv->minor->dev; | |
1509 | struct drm_psb_private *dev_priv = dev->dev_private; | |
1510 | static unsigned int runtime_allowed; | |
1511 | unsigned int nr = DRM_IOCTL_NR(cmd); | |
1512 | ||
1513 | DRM_DEBUG("cmd = %x, nr = %x\n", cmd, nr); | |
1514 | ||
1515 | if (runtime_allowed == 1 && dev_priv->is_lvds_on) { | |
1516 | runtime_allowed++; | |
1517 | pm_runtime_allow(&dev->pdev->dev); | |
1518 | dev_priv->rpm_enabled = 1; | |
1519 | } | |
1520 | /* | |
1521 | * The driver private ioctls and TTM ioctls should be | |
1522 | * thread-safe. | |
1523 | */ | |
1524 | ||
1525 | if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) | |
1526 | && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) { | |
1527 | struct drm_ioctl_desc *ioctl = | |
1528 | &psb_ioctls[nr - DRM_COMMAND_BASE]; | |
1529 | ||
1530 | if (unlikely(ioctl->cmd != cmd)) { | |
1531 | DRM_ERROR( | |
1532 | "Invalid drm cmnd %d ioctl->cmd %x, cmd %x\n", | |
1533 | nr - DRM_COMMAND_BASE, ioctl->cmd, cmd); | |
1534 | return -EINVAL; | |
1535 | } | |
1536 | ||
1537 | return drm_ioctl(filp, cmd, arg); | |
1538 | } | |
1539 | /* | |
1540 | * Not all old drm ioctls are thread-safe. | |
1541 | */ | |
1542 | ||
1543 | return drm_ioctl(filp, cmd, arg); | |
1544 | } | |
1545 | ||
1546 | ||
1547 | /* When a client dies: | |
1548 | * - Check for and clean up flipped page state | |
1549 | */ | |
1550 | void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv) | |
1551 | { | |
1552 | } | |
1553 | ||
1554 | static void psb_remove(struct pci_dev *pdev) | |
1555 | { | |
1556 | struct drm_device *dev = pci_get_drvdata(pdev); | |
1557 | drm_put_dev(dev); | |
1558 | } | |
1559 | ||
1560 | ||
1561 | static const struct dev_pm_ops psb_pm_ops = { | |
1562 | .runtime_suspend = psb_runtime_suspend, | |
1563 | .runtime_resume = psb_runtime_resume, | |
1564 | .runtime_idle = psb_runtime_idle, | |
1565 | }; | |
1566 | ||
1567 | static struct drm_driver driver = { | |
1568 | .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \ | |
1569 | DRIVER_IRQ_VBL | DRIVER_MODESET, | |
1570 | .load = psb_driver_load, | |
1571 | .unload = psb_driver_unload, | |
1572 | ||
1573 | .ioctls = psb_ioctls, | |
1574 | .num_ioctls = DRM_ARRAY_SIZE(psb_ioctls), | |
1575 | .device_is_agp = psb_driver_device_is_agp, | |
1576 | .irq_preinstall = psb_irq_preinstall, | |
1577 | .irq_postinstall = psb_irq_postinstall, | |
1578 | .irq_uninstall = psb_irq_uninstall, | |
1579 | .irq_handler = psb_irq_handler, | |
1580 | .enable_vblank = psb_enable_vblank, | |
1581 | .disable_vblank = psb_disable_vblank, | |
1582 | .get_vblank_counter = psb_get_vblank_counter, | |
1583 | .firstopen = NULL, | |
1584 | .lastclose = psb_lastclose, | |
1585 | .open = psb_driver_open, | |
1586 | .postclose = psb_driver_close, | |
1587 | #if 0 /* ACFIXME */ | |
1588 | .get_map_ofs = drm_core_get_map_ofs, | |
1589 | .get_reg_ofs = drm_core_get_reg_ofs, | |
1590 | .proc_init = psb_proc_init, | |
1591 | .proc_cleanup = psb_proc_cleanup, | |
1592 | #endif | |
1593 | .preclose = psb_driver_preclose, | |
1594 | .fops = { | |
1595 | .owner = THIS_MODULE, | |
1596 | .open = psb_open, | |
1597 | .release = psb_release, | |
1598 | .unlocked_ioctl = psb_unlocked_ioctl, | |
1599 | .mmap = psb_mmap, | |
1600 | .poll = psb_poll, | |
1601 | .fasync = drm_fasync, | |
1602 | .read = drm_read, | |
1603 | }, | |
0867b421 AC |
1604 | .name = DRIVER_NAME, |
1605 | .desc = DRIVER_DESC, | |
1606 | .date = PSB_DRM_DRIVER_DATE, | |
1607 | .major = PSB_DRM_DRIVER_MAJOR, | |
1608 | .minor = PSB_DRM_DRIVER_MINOR, | |
1609 | .patchlevel = PSB_DRM_DRIVER_PATCHLEVEL | |
1610 | }; | |
1611 | ||
bc54f339 MB |
1612 | static struct pci_driver psb_pci_driver = { |
1613 | .name = DRIVER_NAME, | |
1614 | .id_table = pciidlist, | |
1615 | .resume = ospm_power_resume, | |
1616 | .suspend = ospm_power_suspend, | |
1617 | .probe = psb_probe, | |
1618 | .remove = psb_remove, | |
1619 | #ifdef CONFIG_PM | |
1620 | .driver.pm = &psb_pm_ops, | |
1621 | #endif | |
1622 | }; | |
1623 | ||
0867b421 AC |
1624 | static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
1625 | { | |
1626 | /* MLD Added this from Inaky's patch */ | |
1627 | if (pci_enable_msi(pdev)) | |
1628 | DRM_ERROR("Enable MSI failed!\n"); | |
1629 | return drm_get_pci_dev(pdev, ent, &driver); | |
1630 | } | |
1631 | ||
1632 | static int __init psb_init(void) | |
1633 | { | |
bc54f339 | 1634 | return drm_pci_init(&driver, &psb_pci_driver); |
0867b421 AC |
1635 | } |
1636 | ||
1637 | static void __exit psb_exit(void) | |
1638 | { | |
bc54f339 | 1639 | drm_pci_exit(&driver, &psb_pci_driver); |
0867b421 AC |
1640 | } |
1641 | ||
1642 | late_initcall(psb_init); | |
1643 | module_exit(psb_exit); | |
1644 | ||
1645 | MODULE_AUTHOR(DRIVER_AUTHOR); | |
1646 | MODULE_DESCRIPTION(DRIVER_DESC); | |
1647 | MODULE_LICENSE("GPL"); |