Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | DRI Compilation Guide |
2 | ||
3 | VA Linux Systems, Inc. Professional Services - Graphics. | |
4 | ||
5 | 21 April 2001 | |
6 | ||
7 | 1. Preamble | |
8 | ||
9 | 1.1 Copyright | |
10 | ||
11 | Copyright 2000-2001 by VA Linux Systems, Inc. All Rights Reserved. | |
12 | ||
13 | Permission is granted to make and distribute verbatim copies of this document | |
14 | provided the copyright notice and this permission notice are preserved on all | |
15 | copies. | |
16 | ||
17 | 1.2 Trademarks | |
18 | ||
19 | OpenGL is a registered trademark and SGI is a trademark of Silicon Graphics, | |
20 | Inc. Unix is a registered trademark of The Open Group. The `X' device and X | |
21 | Window System are trademarks of The Open Group. XFree86 is a trademark of | |
22 | The XFree86 Project. Linux is a registered trademark of Linus Torvalds. | |
23 | Intel is a registered trademark of Intel Corporation. 3Dlabs, GLINT, and | |
24 | Oxygen are either registered trademarks or trademarks of 3Dlabs Inc. Ltd. | |
25 | 3dfx, Voodoo3, Voodoo4, and Voodoo5 are registered trademarks of 3dfx Inter- | |
26 | active, Incorporated. Matrox is a registered trademark of Matrox Electronic | |
27 | Systems Ltd. ATI Rage and Radeon is a registered trademark of ATI Technolo- | |
28 | gies, Inc. All other trademarks mentioned are the property of their respec- | |
29 | tive owners. | |
30 | ||
31 | 2. Introduction | |
32 | ||
33 | This document describes how to download, compile and install the DRI. The | |
34 | DRI provides 3D graphics hardware acceleration for the XFree86 project. This | |
35 | information is intended for experienced Linux developers. Beginners are | |
36 | probably better off installing precompiled packages. | |
37 | ||
38 | Edits, corrections and updates to this document may be mailed to <brian@tung- | |
39 | stengraphics.com>. | |
40 | ||
41 | Last updated on 13 February 2002 by Brian Paul. | |
42 | ||
43 | 3. Prerequisites | |
44 | ||
45 | You'll need the following: | |
46 | ||
47 | o An installation of XFree86 4.1 or later. The DRI tree has been pruned | |
48 | down to minimize its size. But in order to build the DRI tree you need | |
49 | to have recent X header files, etc. already installed. If you don't | |
50 | have XFree86 4.1 (or later) installed you can probably install it from | |
51 | RPMs (or another package format). Or, you can download XFree86 as | |
52 | sources and compile/install it yourself. | |
53 | ||
54 | o At least 200MB of free disk space. If you compile for debugging (the -g | |
55 | option) then you'll need about 600MB. | |
56 | ||
57 | o GCC compiler and related tools. | |
58 | ||
59 | o ssh (secure shell) if you're a DRI developer and don't want to use | |
60 | anonymous CVS download. | |
61 | ||
62 | o A 2.4.x Linux Kernel. See below for details. | |
63 | ||
64 | o FreeBSD support is not currently being maintained and may not work. | |
65 | ||
66 | The DRI 3D drivers generally work on systems with Intel or AMD CPUs. How- | |
67 | ever, limited support for Alpha and PowerPC support is underway. | |
68 | ||
69 | For 3dfx Voodoo hardware, you'll also need the Glide3 runtime library | |
70 | (libglide3-v3.so for Voodoo3 or libglide3-v5.so for Voodoo4/5). These can be | |
71 | downloaded from the DRI website. You can compile them yourself, but it's | |
72 | often a painful process. | |
73 | ||
74 | For Matrox G200/G400, Intel i810/i830 or ATI Rage128/Radeon hardware, you'll | |
75 | also need AGP support in your Linux kernel, either built-in or as a loadable | |
76 | module. | |
77 | ||
78 | 4. Linux Kernel Preparation | |
79 | ||
80 | Only the Linux 2.4.x kernels are currently supported by the DRI hardware | |
81 | drivers. 2.5.x kernels may work, but aren't tested. | |
82 | ||
83 | Most of the DRI drivers require AGP support and using Intel Pentium III SSE | |
84 | optimizations also requires an up-to-date Linux kernel. Configuring your | |
85 | kernel correctly is very important, as features such as SSE optimizations | |
86 | will be disabled if your kernel does not support them. Thus, if you have a | |
87 | Pentium III processor, you must configure your kernel for the Pentium III | |
88 | processor family. | |
89 | ||
90 | Building a new Linux kernel can be difficult for beginners but there are | |
91 | resources on the Internet to help. This document assumes experience with | |
92 | configuring, building and installing Linux kernels. | |
93 | ||
94 | Linux kernels can be downloaded from www.kernel.org | |
95 | ||
96 | Here are the basic steps for kernel setup. | |
97 | ||
98 | o Download the needed kernel and put it in /usr/src. Create a directory | |
99 | for the source and unpack it. For example: | |
100 | ||
101 | cd /usr/src | |
102 | rm -f linux | |
103 | mkdir linux-2.4.x | |
104 | ln -s linux-2.4.x linux | |
105 | bzcat linux-2.4.x.tar.bz2 | tar xf - | |
106 | ||
107 | It is critical that /usr/src/linux point to your new kernel sources, | |
108 | otherwise the kernel headers will not be used when building the DRI. | |
109 | This will almost certainly cause compilation problems. | |
110 | ||
111 | o Read /usr/src/linux/Documentation/Changes. This file lists the minimum | |
112 | requirements for all software packages required to build the kernel. | |
113 | You must upgrade at least gcc, make, binutils and modutils to at least | |
114 | the versions specified in this file. The other packages may not be | |
115 | needed. If you are upgrading from Linux 2.2.x you must upgrade your | |
116 | modutils package for Linux 2.4.x. | |
117 | ||
118 | o Configure your kernel. You might, for example, use make menuconfig and | |
119 | do the following: | |
120 | ||
121 | o Go to Code maturity level options | |
122 | ||
123 | o Enable Prompt for development and/or incomplete code/drivers | |
124 | ||
125 | o hit ESC to return to the top-level menu | |
126 | ||
127 | o Go to Processor type and features | |
128 | ||
129 | o Select your processor type from Processor Family | |
130 | ||
131 | o hit ESC to return to the top-level menu | |
132 | ||
133 | o Go to Character devices | |
134 | ||
135 | o Disable Direct Rendering Manager (XFree86 DRI support) since we'll | |
136 | use the DRI code from the XFree86/DRI tree and will compile it | |
137 | there. | |
138 | ||
139 | o Go to /dev/agpgart (AGP Support) (EXPERIMENTAL) (NEW) | |
140 | ||
141 | o Hit SPACE twice to build AGP support into the kernel | |
142 | ||
143 | o Enable all chipsets' support for AGP | |
144 | ||
145 | o It's recommended that you turn on MTRRs under Processor type and | |
146 | Features, but not required. | |
147 | ||
148 | o Configure the rest of the kernel as required for your system (i.e. Eth- | |
149 | ernet, SCSI, etc) | |
150 | ||
151 | o Exit, saving your kernel configuration. | |
152 | ||
153 | o Edit your /etc/lilo.conf file. Make sure you have an image entry as | |
154 | follows (or similar): | |
155 | ||
156 | image=/boot/vmlinuz | |
157 | label=linux.2.4.x | |
158 | read-only | |
159 | root=/dev/hda1 | |
160 | ||
161 | The important part is that you have /boot/vmlinuz without a trailing | |
162 | version number. If this is the first entry in your /etc/lilo.conf AND | |
163 | you haven't set a default, then this will be your default kernel. | |
164 | ||
165 | o Compile the new kernel. | |
166 | ||
167 | cd /usr/src/linux-2.4.x | |
168 | make dep | |
169 | make bzImage | |
170 | make modules | |
171 | make modules_install | |
172 | make install | |
173 | ||
174 | Note that last make command will automatically run lilo for you. | |
175 | ||
176 | o Now reboot to use the new kernel. | |
177 | ||
178 | 5. CPU Architectures | |
179 | ||
180 | In general, nothing special has to be done to use the DRI on different CPU | |
181 | architectures. There are, however, a few optimizations that are CPU-depen- | |
182 | dent. Mesa will determine at runtime which CPU-dependent optimizations | |
183 | should be used and enable them where appropriate. | |
184 | ||
185 | 5.1 Intel Pentium III Features | |
186 | ||
187 | The Pentium III SSE instructions are used in optimized vertex transformation | |
188 | functions in the Mesa-based DRI drivers. On Linux, SSE requires a recent | |
189 | kernel (such as 2.4.0-test11 or later) both at compile time and runtime. | |
190 | ||
191 | 5.2 AMD 3DNow! Features | |
192 | ||
193 | AMD's 3DNow! instructions are used in optimized vertex transformation func- | |
194 | tions in the Mesa-based DRI drivers. 3DNow! is supported in most versions of | |
195 | Linux. | |
196 | ||
197 | 5.3 Alpha Features | |
198 | ||
199 | On newer Alpha processors a significant performance increase can be seen with | |
200 | the addition of the -mcpu= option to GCC. This option is dependent on the | |
201 | architecture of the processor. For example, -mcpu=ev6 will build specifi- | |
202 | cally for the EV6 based AXP's, giving both byte and word alignment access to | |
203 | the DRI/Mesa drivers. | |
204 | ||
205 | To enable this optimization edit your xc/config/host.def file and add the | |
206 | line: | |
207 | ||
208 | #define DefaultGcc2AxpOpt -O2 -mcpu=ev6 | |
209 | ||
210 | Additional speed improvements to 3D rendering can be achieved by installing | |
211 | Compaq's Math Libraries (CPML) which can be obtained from http://www.sup- | |
212 | port.compaq.com/alpha-tools/software/index.html | |
213 | ||
214 | Once installed, you can add this line to your host.def to build with the CPML | |
215 | libraries: | |
216 | ||
217 | #define UseCompaqMathLibrary YES | |
218 | ||
219 | The host.def file is explained below. | |
220 | ||
221 | 6. Downloading the XFree86/DRI CVS Sources | |
222 | ||
223 | The DRI project is hosted by SourceForge. The DRI source code, which is a | |
224 | subset of the XFree86 source tree, is kept in a CVS repository there. | |
225 | ||
226 | The DRI CVS sources may be accessed either anonymously or as a registered | |
227 | SourceForge user. It's recommended that you become a registered SourceForge | |
228 | user so that you may submit non-anonymous bug reports and can participate in | |
229 | the mailing lists. | |
230 | ||
231 | 6.1 Anonymous CVS download: | |
232 | ||
233 | 1. Create a directory to store the CVS files: | |
234 | ||
235 | cd ~ | |
236 | mkdir DRI-CVS | |
237 | ||
238 | You could put your CVS directory in a different place but we'll use | |
239 | ~/DRI-CVS/ here. | |
240 | ||
241 | 2. Check out the CVS sources: | |
242 | ||
243 | cd ~/DRI-CVS | |
244 | cvs -d:pserver:anonymous@cvs.dri.sourceforge.net:/cvsroot/dri login | |
245 | (hit ENTER when prompted for a password) | |
246 | cvs -z3 -d:pserver:anonymous@cvs.dri.sourceforge.net:/cvsroot/dri co xc | |
247 | ||
248 | The -z3 flag causes compression to be used in order to reduce the down- | |
249 | load time. | |
250 | ||
251 | 6.2 Registered CVS download: | |
252 | ||
253 | 1. Create a directory to store the CVS files: | |
254 | ||
255 | cd ~ | |
256 | mkdir DRI-CVS | |
257 | ||
258 | You could put your CVS directory in a different place but we'll use | |
259 | ~/DRI-CVS/ here. | |
260 | ||
261 | 2. Set the CVS_RSH environment variable: | |
262 | ||
263 | setenv CVS_RSH ssh // if using csh or tcsh | |
264 | export CVS_RSH=ssh // if using sh or bash | |
265 | ||
266 | 3. Check out the CVS sources: | |
267 | ||
268 | cd ~/DRI-CVS | |
269 | cvs -z3 -d:ext:YOURID@cvs.dri.sourceforge.net:/cvsroot/dri co xc | |
270 | ||
271 | Replace YOURID with your CVS login name. You'll be prompted to enter | |
272 | your sourceforge password. | |
273 | ||
274 | The -z3 flag causes compression to be used in order to reduce the down- | |
275 | load time. | |
276 | ||
277 | 6.3 Updating your CVS sources | |
278 | ||
279 | In the future you'll want to occasionally update your local copy of the DRI | |
280 | source code to get the latest changes. This can be done with: | |
281 | ||
282 | cd ~/DRI-CVS | |
283 | cvs -z3 update -dA xc | |
284 | ||
285 | The -d flag causes any new subdirectories to be created and -A causes most | |
286 | recent trunk sources to be fetched, not branch sources. | |
287 | ||
288 | 7. Mesa | |
289 | ||
290 | Most of the DRI 3D drivers are based on Mesa (the free implementation of the | |
291 | OpenGL API). The relevant files from Mesa are already included in the | |
292 | XFree86/DRI source tree. There is no need to download or install the Mesa | |
293 | source files separately. | |
294 | ||
295 | Sometimes a newer version of Mesa will be available than the version included | |
296 | in XFree86/DRI. Upgrading Mesa within XFree86/DRI is not always straightfor- | |
297 | ward. It can be an error-prone undertaking, especially for beginners, and is | |
298 | not generally recommended. The DRI developers will upgrade Mesa when appro- | |
299 | priate. | |
300 | ||
301 | 8. Compiling the XFree86/DRI tree | |
302 | ||
303 | 8.1 Make a build tree | |
304 | ||
305 | Rather than placing object files and library files right in the source tree, | |
306 | they're instead put into a parallel build tree. The build tree is made with | |
307 | the lndir command: | |
308 | ||
309 | cd ~/DRI-CVS | |
310 | ln -s xc XFree40 | |
311 | mkdir build | |
312 | cd build | |
313 | lndir -silent -ignorelinks ../XFree40 | |
314 | ||
315 | The build tree will be populated with symbolic links which point back into | |
316 | the CVS source tree. | |
317 | ||
318 | Advanced users may have several build trees for compiling and testing with | |
319 | different options. | |
320 | ||
321 | 8.2 Edit the host.def file | |
322 | ||
323 | The ~/DRI-CVS/build/xc/config/cf/host.def file is used to configure the | |
324 | XFree86 build process. You can change it to customize your build options or | |
325 | make adjustments for your particular system configuration | |
326 | ||
327 | The default host.def file will look something like this: | |
328 | ||
329 | #define DefaultCCOptions -Wall | |
330 | (i386) #define DefaultGcc2i386Opt -O2 | |
331 | (Alpha) #define DefaultGcc2AxpOpt -O2 -mcpu=ev6 (or similar) | |
332 | #define LibraryCDebugFlags -O2 | |
333 | #define BuildServersOnly YES | |
334 | #define XF86CardDrivers vga tdfx mga ati i810 | |
335 | #define LinuxDistribution LinuxRedHat | |
336 | #define DefaultCCOptions -ansi GccWarningOptions -pipe | |
337 | #define BuildXF86DRI YES | |
338 | /* Optionally turn these on for debugging */ | |
339 | /* #define GlxBuiltInTdfx YES */ | |
340 | /* #define GlxBuiltInMga YES */ | |
341 | /* #define GlxBuiltInR128 YES */ | |
342 | /* #define GlxBuiltInRadeon YES */ | |
343 | /* #define DoLoadableServer NO */ | |
344 | #define SharedLibFont NO | |
345 | ||
346 | The ProjectRoot variable specifies where the XFree86 files will be installed. | |
347 | We recommend installing the DRI files over your existing XFree86 installation | |
348 | - it's generally safe to do and less error-prone. This policy is different | |
349 | than what we used to recommend. | |
350 | ||
351 | If XFree86 4.x is not installed in /usr/X11R6/ you'll have to add the follow- | |
352 | ing to the host.def file: | |
353 | ||
354 | #define ProjectRoot pathToYourXFree86installation | |
355 | ||
356 | Note the XF86CardDrivers line to be sure your card's driver is listed. | |
357 | ||
358 | If you want to enable 3DNow! optimizations in Mesa and the DRI drivers, you | |
359 | should add the following: | |
360 | ||
361 | #define MesaUse3DNow YES | |
362 | ||
363 | You don't have to be using an AMD processor in order to enable this option. | |
364 | The DRI will look for 3DNow! support and runtime and only enable it if appli- | |
365 | cable. | |
366 | ||
367 | If you want to enable SSE optimizations in Mesa and the DRI drivers, you must | |
368 | upgrade to a Linux 2.4.x kernel. Mesa will verify that SSE is supported by | |
369 | both your processor and your operating system, but to build Mesa inside the | |
370 | DRI you need to have the Linux 2.4.x kernel headers in /usr/src/linux. If | |
371 | you enable SSE optimizations with an earlier version of the Linux kernel in | |
372 | /usr/src/linux, Mesa will not compile. You have been warned. If you do have | |
373 | a 2.4.x kernel, you should add the following: | |
374 | ||
375 | #define MesaUseSSE YES | |
376 | ||
377 | If you want to build the DRM kernel modules as part of the full build pro- | |
378 | cess, add the following: | |
379 | ||
380 | #define BuildXF86DRM YES | |
381 | ||
382 | Otherwise, you'll need to build them separately as described below. | |
383 | ||
384 | 8.3 Compilation | |
385 | ||
386 | To compile the complete DRI tree: | |
387 | ||
388 | cd ~/DRI-CVS/build/xc/ | |
389 | make World >& world.log | |
390 | ||
391 | Or if you want to watch the compilation progress: | |
392 | ||
393 | cd ~/DRI-CVS/build/xc/ | |
394 | make World >& world.log & | |
395 | tail -f world.log | |
396 | ||
397 | With the default compilation flags it's normal to get a lot of warnings dur- | |
398 | ing compilation. | |
399 | ||
400 | Building will take some time so you may want to go check your email or visit | |
401 | slashdot. | |
402 | ||
403 | WARNING: do not use the -j option with make. It's reported that it does not | |
404 | work with XFree86/DRI. | |
405 | ||
406 | 8.4 Check for compilation errors | |
407 | ||
408 | Using your text editor, examine world.log for errors by searching for the | |
409 | pattern ***. | |
410 | ||
411 | After fixing the errors, run make World again. Later, you might just compile | |
412 | parts of the source tree but it's important that the whole tree will build | |
413 | first. | |
414 | ||
415 | If you edited your host.def file to enable automatic building of the DRI ker- | |
416 | nel module(s), verify that they were built: | |
417 | ||
418 | cd ~/DRI-CVS/build/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel | |
419 | ls | |
420 | ||
421 | Otherwise, build them now by running | |
422 | ||
423 | cd ~/DRI-CVS/build/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel | |
424 | make -f Makefile.linux | |
425 | ||
426 | For the 3dfx Voodoo, you should see tdfx.o. For the Matrox G200/G400, you | |
427 | should see mga.o. For the ATI Rage 128, you should see r128.o. For the ATI | |
428 | Radeon, you should see radeon.o. For the Intel i810, you should see i810.o. | |
429 | ||
430 | If the DRI kernel module(s) failed to build you should verify that you're | |
431 | using the right version of the Linux kernel. The most recent kernels are not | |
432 | always supported. | |
433 | ||
434 | If your build machine is running a different version of the kernel than your | |
435 | target machine (i.e. 2.2.x vs. 2.4.x), make will select the wrong kernel | |
436 | source tree. This can be fixed by explicitly setting the value of LINUXDIR. | |
437 | If the path to your kernel source is /usr/src/linux-2.4.x, | |
438 | ||
439 | cd ~/DRI-CVS/build/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel | |
440 | make -f Makefile.linux LINUXDIR=/usr/src/linux-2.4.x | |
441 | ||
442 | or alternatively, edit Makefile.linux to set LINUXDIR before the ifndef LIN- | |
443 | UXDIR line. | |
444 | ||
445 | 8.5 DRI kernel module installation | |
446 | ||
447 | The DRI kernel modules will be in ~/DRI-CVS/build/xc/pro- | |
448 | grams/Xserver/hw/xfree86/os-support/linux/drm/kernel/. | |
449 | ||
450 | To load the appropriate DRM module in your running kernel you can either use | |
451 | ismod and restart your X server or copy the kernel module to /lib/mod- | |
452 | ules/2.4.x/kernel/drivers/char/drm/ then run depmod and restart your X | |
453 | server. | |
454 | ||
455 | Make sure you first unload any older DRI kernel modules that might be already | |
456 | loaded. | |
457 | ||
458 | Note that some DRM modules require that the agpgart module be loaded first. | |
459 | ||
460 | 9. Normal Installation and Configuration | |
461 | ||
462 | Most users will want to install the new X server and use it in place of their | |
463 | old X server. This section explains how to do that. | |
464 | ||
465 | Developers, on the other hand, may just want to test the X server without | |
466 | actually installing it as their default server. If you want to do that, skip | |
467 | to the next section. | |
468 | ||
469 | 9.1 Installation | |
470 | ||
471 | Here are the installation commands: | |
472 | ||
473 | su | |
474 | cd ~/DRI-CVS/build/xc | |
475 | make install | |
476 | ||
477 | 9.2 Update the XF86Config File | |
478 | ||
479 | You may need to edit your XF86Config file to enable the DRI. The config file | |
480 | is usually installed as /etc/X11/XF86Config-4. See the DRI User Guide for | |
481 | details, but basically, you need to load the "glx" and "dri" modules and add | |
482 | a "DRI" section. | |
483 | ||
484 | On the DRI web site, in the resources section, you'll find example XF86Config | |
485 | files for a number of graphics cards. These configuration files also setup | |
486 | DRI options so it's highly recommended that you look at these examples. | |
487 | ||
488 | The XFree86 4.x server can generate a basic configuration file itself. Sim- | |
489 | ply do this: | |
490 | ||
491 | cd /usr/X11R6/bin | |
492 | ./XFree86 -configure | |
493 | ||
494 | A file named /root/XF86Config.new will be created. It should allow you to | |
495 | try your X server but you'll almost certainly have to edit it. For example, | |
496 | you should add HorizSync and VertRefresh options to the Monitor section and | |
497 | Modes options to the Screen section. Also, the ModulePath option in the | |
498 | Files section should be set to /usr/X11R6/lib/modules. | |
499 | ||
500 | 9.3 Start the New X Server | |
501 | ||
502 | The new X server should be ready to use now. Start your X server in your | |
503 | usual manner. Often times the startx command is used: | |
504 | ||
505 | startx | |
506 | ||
507 | 10. Testing the Server Without Installing It | |
508 | ||
509 | As mentioned at the start of section 9, developers may want to simply run the | |
510 | X server without installing it. This can save some time and allow you to | |
511 | keep a number of X servers available for testing. | |
512 | ||
513 | 10.1 Configuration | |
514 | ||
515 | As described in the preceding section, you'll need to create a configuration | |
516 | file for the new server. Put the XF86Config file in your ~/DRI- | |
517 | CVS/build/xc/programs/Xserver directory. | |
518 | ||
519 | Be sure the ModulePath option in your XF86Config file is set correctly. | |
520 | ||
521 | 10.2 A Startup Script | |
522 | ||
523 | A simple shell script can be used to start the X server. Here's an example. | |
524 | ||
525 | #!/bin/sh | |
526 | export DISPLAY=:0 | |
527 | ./XFree86 -xf86config XF86Config & \ | |
528 | sleep 2 | |
529 | fvwm2 & | |
530 | xset b off | |
531 | xmodmap -e "clear mod4" | |
532 | xsetroot -solid "#00306f" | |
533 | xterm -geometry 80x40+0+0 | |
534 | ||
535 | You might name this script start-dri. Put it in your ~/DRI-CVS/build/xc/pro- | |
536 | grams/Xserver directory. | |
537 | ||
538 | To test the server run the script: | |
539 | ||
540 | cd ~/DRI-CVS/build/xc/programs/Xserver | |
541 | ./start-dri | |
542 | ||
543 | For debugging, you may also want to capture the log messages printed by the | |
544 | server in a file. If you're using the C-shell: | |
545 | ||
546 | ./start-dri >& log | |
547 | ||
548 | 11. Where To Go From Here | |
549 | ||
550 | At this point your X server should be up and running with hardware-acceler- | |
551 | ated direct rendering. Please read the DRI User Guide for information about | |
552 | trouble shooting and how to use the DRI-enabled X server for 3D applications. | |
553 | ||
554 | Generated from XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/DRIcomp.sgml,v 1.19 dawes Exp $ |