Update of /cvsroot/alsa/alsa-kernel/Documentation/DocBook
In directory sc8-pr-cvs1:/tmp/cvs-serv5736

Modified Files:
        writing-an-alsa-driver.tmpl 
Log Message:
- added the description of pcm runtime.
- added the section how to put the new driver into alsa tree.



Index: writing-an-alsa-driver.tmpl
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/Documentation/DocBook/writing-an-alsa-driver.tmpl,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- writing-an-alsa-driver.tmpl 19 Mar 2003 16:14:29 -0000      1.7
+++ writing-an-alsa-driver.tmpl 26 Mar 2003 15:17:52 -0000      1.8
@@ -18,8 +18,8 @@
       </affiliation>
      </author>
 
-     <date>Dec. 27, 2002</date>
-     <edition>0.2 (reborn at Christmas)</edition>
+     <date>Mar. 26, 2003</date>
+     <edition>0.3</edition>
 
     <abstract>
       <para>
@@ -30,7 +30,7 @@
 
     <legalnotice>
     <para>
-    Copyright (c) 2002  Takashi Iwai <email>[EMAIL PROTECTED]</email>
+    Copyright (c) 2002, 2003  Takashi Iwai <email>[EMAIL PROTECTED]</email>
     </para>
 
     <para>
@@ -1425,11 +1425,11 @@
     <section id="pci-resource-resource-allocation">
       <title>Resource Allocation</title>
       <para>
-        The allocation of ports and irqs are done via standard kernel
+        The allocation of I/O ports and irqs are done via standard kernel
       functions. Unlike ALSA ver.0.5.x., there are no helpers for
       that. And these resources must be released in the destructor
-      function (see below). Also, on ALSA 0.9.x, you don't need
-      allocate (pseudo-)DMA for PCI like 0.5.x. 
+      function (see below). Also, on ALSA 0.9.x, you don't need to
+      allocate (pseudo-)DMA for PCI like ALSA 0.5.x. 
       </para>
 
       <para>
@@ -1461,7 +1461,7 @@
       since irq 0 is valid. The port address and its resource pointer
       can be initialized as null by
       <function>snd_magic_kcalloc()</function> automatically, so you
-      don't have to take care of it. 
+      don't have to take care of resetting them. 
       </para>
 
       <para>
@@ -2227,79 +2227,157 @@
       </para>
     </section>
 
-    <section id="pcm-interface-operators">
-      <title>Operators</title>
-      <para>
-        OK, now let me explain the detail of each pcm callback
-      (<parameter>ops</parameter>). In general, every callback must
-      return 0 if successful, or a negative number with the error
-      number such as <constant>-EINVAL</constant> at any
-      error. 
-      </para>
-
-      <para>
-        The callback function takes at least the argument with
-        <type>snd_pcm_substream_t</type> pointer. For retrieving the
-        chip record from the given substream instance, you can use the
-        following macro. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  #define chip_t mychip_t
-
-  int xxx() {
-          mychip_t *chip = snd_pcm_substream_chip(substream);
-          ....
-  }
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        It's expanded with a magic-cast, so the cast-error is
-      automatically checked. You should define <type>chip_t</type> at
-      the beginning of the code, since this will be referred in many
-      places of pcm and control interfaces. 
-      </para>
+    <section id="pcm-interface-runtime">
+      <title>Runtime Pointer - The Chest of PCM Information</title>
+       <para>
+         When the PCM substream is opened, a PCM runtime instance is
+       allocated and assigned to the substream. This pointer is
+       accessible via <constant>substream-&gt;runtime</constant>.
+       This runtime pointer holds the various information; it holds
+       the copy of hw_params and sw_params configurations, the buffer
+       pointers, mmap records, spinlocks, etc.  Almost everyhing you
+       need for controlling the PCM can be found there.
+       </para>
 
-      <section id="pcm-interface-operators-open-callback">
-        <title>open callback</title>
-        <para>
+       <para>
+       The definition of runtime instance is found in
+       <filename>&lt;sound/pcm.h&gt;</filename>.  Here is the
+       copy from the file.
           <informalexample>
             <programlisting>
 <![CDATA[
-  static int snd_xxx_open(snd_pcm_substream_t *subs);
+struct _snd_pcm_runtime {
+       /* -- Status -- */
+       snd_pcm_substream_t *trigger_master;
+       snd_timestamp_t trigger_tstamp; /* trigger timestamp */
+       int overrange;
+       snd_pcm_uframes_t avail_max;
+       snd_pcm_uframes_t hw_ptr_base;  /* Position at buffer restart */
+       snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time*/
+
+       /* -- HW params -- */
+       snd_pcm_access_t access;        /* access mode */
+       snd_pcm_format_t format;        /* SNDRV_PCM_FORMAT_* */
+       snd_pcm_subformat_t subformat;  /* subformat */
+       unsigned int rate;              /* rate in Hz */
+       unsigned int channels;          /* channels */
+       snd_pcm_uframes_t period_size;  /* period size */
+       unsigned int periods;           /* periods */
+       snd_pcm_uframes_t buffer_size;  /* buffer size */
+       unsigned int tick_time;         /* tick time */
+       snd_pcm_uframes_t min_align;    /* Min alignment for the format */
+       size_t byte_align;
+       unsigned int frame_bits;
+       unsigned int sample_bits;
+       unsigned int info;
+       unsigned int rate_num;
+       unsigned int rate_den;
+
+       /* -- SW params -- */
+       int tstamp_timespec;            /* use timeval (0) or timespec (1) */
+       snd_pcm_tstamp_t tstamp_mode;   /* mmap timestamp is updated */
+       unsigned int period_step;
+       unsigned int sleep_min;         /* min ticks to sleep */
+       snd_pcm_uframes_t xfer_align;   /* xfer size need to be a multiple */
+       snd_pcm_uframes_t start_threshold;
+       snd_pcm_uframes_t stop_threshold;
+       snd_pcm_uframes_t silence_threshold; /* Silence filling happens when
+                                               noise is nearest than this */
+       snd_pcm_uframes_t silence_size; /* Silence filling size */
+       snd_pcm_uframes_t boundary;     /* pointers wrap point */
+
+       snd_pcm_uframes_t silenced_start;
+       snd_pcm_uframes_t silenced_size;
+
+       snd_pcm_sync_id_t sync;         /* hardware synchronization ID */
+
+       /* -- mmap -- */
+       volatile snd_pcm_mmap_status_t *status;
+       volatile snd_pcm_mmap_control_t *control;
+       atomic_t mmap_count;
+
+       /* -- locking / scheduling -- */
+       spinlock_t lock;
+       wait_queue_head_t sleep;
+       struct timer_list tick_timer;
+       struct fasync_struct *fasync;
+
+       /* -- private section -- */
+       void *private_data;
+       void (*private_free)(snd_pcm_runtime_t *runtime);
+
+       /* -- hardware description -- */
+       snd_pcm_hardware_t hw;
+       snd_pcm_hw_constraints_t hw_constraints;
+
+       /* -- interrupt callbacks -- */
+       void (*transfer_ack_begin)(snd_pcm_substream_t *substream);
+       void (*transfer_ack_end)(snd_pcm_substream_t *substream);
+
+       /* -- timer -- */
+       unsigned int timer_resolution;  /* timer resolution */
+
+       /* -- DMA -- */           
+       unsigned char *dma_area;        /* DMA area */
+       dma_addr_t dma_addr;            /* physical bus address (not accessible from 
main CPU) */
+       size_t dma_bytes;               /* size of DMA area */
+       void *dma_private;              /* private DMA data for the memory allocator */
+
+#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
+       /* -- OSS things -- */
+       snd_pcm_oss_runtime_t oss;
+#endif
+};
 ]]>
             </programlisting>
           </informalexample>
+       </para>
 
-          This is called when a pcm substream is opened.
-        </para>
+       <para>
+         For the operators (callbacks) of each sound driver, most of
+       these records are supposed to be read-only.  Only the PCM
+       middle-layer changes / updates these info.  The excpetions are
+       the hardware description (hw), interrupt callbacks
+       (transfer_ack_xxx), DMA buffer information, and the private
+       data.  Besides, if you use the standard buffer allocation
+       method via <function>snd_pcm_lib_malloc_pages()</function>,
+       you don't need to set the DMA buffer information by yourself.
+       </para>
 
-        <para>
-          At least, here you have to initialize the runtime hardware
-          record. Typically, this is done by like this: 
+       <para>
+       In the sections below, important records are explained.
+       </para>
 
+       <section id="pcm-interface-runtime-hw">
+       <title>Hardware Description</title>
+       <para>
+         The hardware descriptor (<type>snd_pcm_hardware_t</type>)
+       contains the definitions of the fundamental hardware
+       configuration.  Above all, you'll need to define this in
+       <link linkend="pcm-interface-operators-open-callback"><citetitle>
+       the open callback</citetitle></link>.
+       Note that the runtime instance holds the copy of the
+       descriptor, not the pointer to the existing descriptor.  That
+       is, in the open callback, you can modify the copied descriptor
+       (<constant>runtime-&gt;hw</constant>) as you need.  For example, if the maximum
+       number of channels is 1 only on some chip models, you can
+       still use the same hardware descriptor and change the
+       channels_max later:
           <informalexample>
             <programlisting>
 <![CDATA[
-  static int snd_xxx_open(snd_pcm_substream_t *substream)
-  {
-          mychip_t *chip = snd_pcm_substream_chip(substream);
           snd_pcm_runtime_t *runtime = substream->runtime;
-
-          runtime->hw = snd_mychip_playback_hw;
-          return 0;
-  }
+          ...
+          runtime->hw = snd_mychip_playback_hw; // common definition
+          if (chip->model == VERY_OLD_ONE)
+                  runtime->hw.channels_max = 1;
 ]]>
             </programlisting>
           </informalexample>
+       </para>
 
-          where <parameter>snd_mychip_playback_hw</parameter> is the
-          pre-defined hardware record.
-
+       <para>
+         Typically, you'll have a hardware descriptor like below:
           <informalexample>
             <programlisting>
 <![CDATA[
@@ -2326,11 +2404,8 @@
         </para>
 
         <para>
-          The similar struct exists on ALSA 0.5.x driver, so you can
-        guess the values if you already wrote a driver. 
-        </para>
-
-        <para>
+       <itemizedlist>
+       <listitem><para>
           The <structfield>info</structfield> field contains the type and
         capabilities of this pcm. The bit flags are defined in
         <filename>&lt;sound/asound.h&gt;</filename> as
@@ -2366,6 +2441,17 @@
         must handle the corresponding commands. 
         </para>
 
+       <para>
+         When the PCM substreams can be synchronized (typically,
+       synchorinized start/stop of a playback and a capture streams),
+       you can give <constant>SNDRV_PCM_INFO_SYNC_START</constant>,
+       too.  In this case, you'll need to check the linked-list of
+       PCM substreams in the trigger callback.  This will be
+       described in the later section.
+       </para>
+       </listitem>
+
+       <listitem>
         <para>
           <structfield>formats</structfield> field contains the bit-flags
         of supported formats (<constant>SNDRV_PCM_FMTBIT_XXX</constant>).
@@ -2373,38 +2459,181 @@
         bits.  In the example above, the signed 16bit little-endian
         format is specified.
         </para>
+       </listitem>
 
+       <listitem>
         <para>
         <structfield>rates</structfield> field contains the bit-flags of
         supported rates (<constant>SNDRV_PCM_RATE_XXX</constant>).
         When the chip supports continuous rates, pass
         <constant>CONTINUOUS</constant> bit additionally.
-        The pre-defined rate bits are only for typical rates. If your
-        chip supports unconventional rates, you need to add
-        <constant>KNOT</constant> bit and set up the
+        The pre-defined rate bits are provided only for typical
+       rates. If your chip supports unconventional rates, you need to add
+        <constant>KNOT</constant> bit and set up the hardware
         constraint manually (explained later).
         </para>
+       </listitem>
 
-        <para>
-        There have been many changes of terminology between
-        ALSA 0.5.x and 0.9.x.
-        On the ALSA 0.9.x world, <quote>period</quote> means what is
-        known as <quote>fragment</quote> in the OSS.  It's the least
-        size of (a part of) the buffer to generate an interrupt.
+       <listitem>
+       <para>
+       <structfield>rate_min</structfield> and
+       <structfield>rate_max</structfield> define the minimal and
+       maximal sample rate.  This should correspond somehow to
+       <structfield>rates</structfield> bits.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       <structfield>channel_min</structfield> and
+       <structfield>channel_max</structfield> 
+       define, as you might already expected, the minimal and maximal
+       number of channels.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       <structfield>buffer_bytes_max</structfield> defines the
+       maximal buffer size in bytes.  There is no
+       <structfield>buffer_bytes_min</structfield> field, since
+       it can be calculated from the minimal period size and the
+       minimal number of periods.
+       Meanwhile, <structfield>period_bytes_min</structfield> and
+       define the minimal and maximal size of the period in bytes.
+       <structfield>periods_max</structfield> and
+       <structfield>periods_min</structfield> define the maximal and
+       minimal number of periods in the buffer.
         </para>
 
-        <para>
-        Now, taking the new terminology into account, the other fields
-        are self-explanatory (I hope). Please note that here, both 
-        min/max buffer and period sizes are specified in bytes. 
+       <para>
+       The <quote>period</quote> is a term, that corresponds to
+       fragment in the OSS world.  The period defines the size at
+       which the PCM interrupt is generated. This size strongly
+       depends on the hardware. 
+       Generally, the smaller period size will give you more
+       interrupts, that is, more controls. 
+       In the case of capture, this size defines the input latency.
+       On the other hand, the whole buffer size defines the
+       output latency for the playback direction.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       There is also a field <structfield>fifo_size</structfield>.
+       This specifies the size of the hardware FIFO, but it's not
+       used currently in the driver nor in the alsa-lib.  So, you
+       can ignore this field.
+       </para>
+       </listitem>
+       </itemizedlist>
+       </para>
+       </section>
+
+       <section id="pcm-interface-runtime-config">
+       <title>PCM Configurations</title>
+       <para>
+       Ok, let's go back again to the PCM runtime records.
+       The most frequently referred records in the runtime instance are
+       the PCM configurations.
+       The PCM configurations are stored on runtime instance
+       after the application sends <type>hw_params</type> data via
+       alsa-lib.  There are many fields copied from hw_params and
+       sw_params structs.  For example,
+       <structfield>format</structfield> holds the format type
+       chosen by the application.  This field contains the enum value
+       <constant>SNDRV_PCM_FORMAT_XXX</constant>.
+       </para>
+
+       <para>
+       One thing to be noted is that the configured buffer and period
+       sizes are stored in <quote>frames</quote> in the runtime
+        In the ALSA world, 1 frame = channels * samples-size.
+       For conversion between frames and bytes, you can use the
+       helper functions, <function>frames_to_bytes()</function> and
+          <function>bytes_to_frames()</function>. 
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  period_bytes = frames_to_bytes(runtime, runtime->period_size);
+]]>
+            </programlisting>
+          </informalexample>
         </para>
 
-        <para>
-          Some drivers allocate the private instance for each pcm
-          substream. It can be stored in
-          <constant>substream->runtime-&gt;private_data</constant>.
-          Since it's a void pointer, you 
-          should use magic-kmalloc and magic-cast for such an object. 
+       <para>
+       Also, many software parameters (sw_params) are
+       stored in frames, too.  Please check the type of the field.
+       <type>snd_pcm_uframes_t</type> is for the frames as unsigned
+       integer while <type>snd_pcm_sframes_t</type> is for the frames
+       as signed integer.
+       </para>
+       </section>
+
+       <section id="pcm-interface-runtime-dma">
+       <title>DMA Buffer Information</title>
+       <para>
+       The DMA buffer is defined by the following four fields,
+       <structfield>dma_area</structfield>,
+       <structfield>dma_addr</structfield>,
+       <structfield>dma_bytes</structfield> and
+       <structfield>dma_private</structfield>.
+       The <structfield>dma_area</structfield> holds the buffer
+       pointer (the logical address).  You can call
+       <function>memcpy</function> from/to 
+       this pointer.  Meanwhile, <structfield>dma_addr</structfield>
+       holds the physical address of the buffer.  This field is
+       specified only when the buffer is a linear buffer.
+       <structfield>dma_bytes</structfield> holds the size of buffer
+       in bytes.  <structfield>dma_private</structfield> is used for
+       the ALSA DMA allocator.
+       </para>
+
+       <para>
+       If you use a standard ALSA function,
+       <function>snd_pcm_lib_malloc_pages()</function>, for
+       allocating the buffer, these fields are set by the ALSA middle
+       layer, and you should <emphasis>not</emphasis> change them by
+       yourself.  You can read them but not write them.
+       On the other hand, if you want to allocate the buffer by
+       yourself, you'll need to manage it in hw_params callback.
+       At least, <structfield>dma_bytes</structfield> is mandatory.
+       <structfield>dma_area</structfield> is necessary when the
+       buffer is mmapped.  If your driver doesn't support mmap, this
+       field is not necessary.  <structfield>dma_addr</structfield>
+       is also not mandatory.  You can use
+       <structfield>dma_private</structfield> as you like, too.
+       </para>
+       </section>
+
+       <section id="pcm-interface-runtime-status">
+       <title>Running Status</title>
+       <para>
+       The running status can be referred via <constant>runtime-&gt;status</constant>.
+       This is the pointer to <type>snd_pcm_mmap_status_t</type>
+       record.  For example, you can get the current DMA hardware
+       pointer via <constant>runtime-&gt;status-&gt;hw_ptr</constant>.
+       </para>
+
+       <para>
+       The DMA application pointer can be referred via
+       <constant>runtime-&gt;control</constant>, which points
+       <type>snd_pcm_mmap_control_t</type> record.
+       However, accessing directly to this value is not recommended.
+       </para>
+       </section>
+
+       <section id="pcm-interface-runtime-private">
+       <title>Private Data</title> 
+       <para>
+       You can allocate a record for the substream and store it in
+       <constant>runtime-&gt;private_data</constant>.  Usually, this
+       done in
+       <link linkend="pcm-interface-operators-open-callback"><citetitle>
+       the open callback</citetitle></link>.
+        Since it's a void pointer, you should use magic-kmalloc and
+       magic-cast for such an object. 
 
           <informalexample>
             <programlisting>
@@ -2423,8 +2652,110 @@
         </para>
 
         <para>
-          The allocated object must be released in the close callback below.
+          The allocated object must be released in
+       <link linkend="pcm-interface-operators-open-callback"><citetitle>
+       the close callback</citetitle></link>.
         </para>
+       </section>
+
+       <section id="pcm-interface-runtime-intr">
+       <title>Interrupt Callbacks</title>
+       <para>
+       The field <structfield>transfer_ack_begin</structfield> and
+       <structfield>transfer_ack_end</structfield> are called at
+       the beginning and the end of
+       <function>snd_pcm_period_elapsed()</function>, respectively. 
+       </para>
+       </section>
+
+    </section>
+
+    <section id="pcm-interface-operators">
+      <title>Operators</title>
+      <para>
+        OK, now let me explain the detail of each pcm callback
+      (<parameter>ops</parameter>). In general, every callback must
+      return 0 if successful, or a negative number with the error
+      number such as <constant>-EINVAL</constant> at any
+      error. 
+      </para>
+
+      <para>
+        The callback function takes at least the argument with
+        <type>snd_pcm_substream_t</type> pointer. For retrieving the
+        chip record from the given substream instance, you can use the
+        following macro. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  #define chip_t mychip_t
+
+  int xxx() {
+          mychip_t *chip = snd_pcm_substream_chip(substream);
+          ....
+  }
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        It's expanded with a magic-cast, so the cast-error is
+      automatically checked. You should define <type>chip_t</type> at
+      the beginning of the code, since this will be referred in many
+      places of pcm and control interfaces. 
+      </para>
+
+      <section id="pcm-interface-operators-open-callback">
+        <title>open callback</title>
+        <para>
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static int snd_xxx_open(snd_pcm_substream_t *subs);
+]]>
+            </programlisting>
+          </informalexample>
+
+          This is called when a pcm substream is opened.
+        </para>
+
+        <para>
+          At least, here you have to initialize the runtime-&gt;hw
+          record. Typically, this is done by like this: 
+
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static int snd_xxx_open(snd_pcm_substream_t *substream)
+  {
+          mychip_t *chip = snd_pcm_substream_chip(substream);
+          snd_pcm_runtime_t *runtime = substream->runtime;
+
+          runtime->hw = snd_mychip_playback_hw;
+          return 0;
+  }
+]]>
+            </programlisting>
+          </informalexample>
+
+          where <parameter>snd_mychip_playback_hw</parameter> is the
+          pre-defined hardware description.
+       </para>
+
+       <para>
+       You can allocate a private data in this callback, as described
+       in <link linkend="pcm-interface-runtime-private"><citetitle>
+       Private Data</citetitle></link> section.
+       </para>
+
+       <para>
+       If the hardware configuration needs more constraints, set the
+       hardware constraints here, too.
+       See <link linkend="pcm-interface-constraints"><citetitle>
+       Constraints</citetitle></link> for more details.
+       </para>
       </section>
 
       <section id="pcm-interface-operators-close-callback">
@@ -2622,23 +2953,6 @@
         </para>
 
         <para>
-          Note that the period and the buffer sizes are stored in
-          <quote>frames</quote>. In the ALSA world, 1 frame = channels
-          * samples-size. For conversion between frames and bytes, you
-          can use the helper functions,
-          <function>frames_to_bytes()</function> and
-          <function>bytes_to_frames()</function>. 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  period_bytes = frames_to_bytes(runtime, runtime->period_size);
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
           Be careful that this callback will be called many times at
         each set up, too. 
         </para>
@@ -5115,6 +5429,217 @@
     </para>
   </chapter>
 
+
+<!-- ****************************************************** -->
+<!-- How To Put Your Driver  -->
+<!-- ****************************************************** -->
+  <chapter id="how-to-put-your-driver">
+    <title>How To Put Your Driver Into ALSA Tree</title>
+       <section>
+       <title>General</title>
+       <para>
+       So far, you've learned how to write the driver codes.
+       And you might have a question now: how to put my own
+       driver into the ALSA driver tree?
+       Here (finally :) the standard procedure is described briefly.
+       </para>
+
+       <para>
+       Suppose that you'll create a new PCI driver for the card
+       <quote>xyz</quote>.  The card module name would be
+       snd-xyz.  The new driver is usually put into alsa-driver
+       tree.  Then the driver is evaluated, audited and tested
+       by developers and users.  After a certain time, the driver
+       will go to alsa-kernel tree and eventually integrated into
+       Linux 2.5 tree.
+       </para>
+
+       <para>
+       In the following sections, the driver code is supposed
+       to be put into alsa-driver tree.  The two cases are assumed:
+       a driver consisting of a single source file and one consisting
+       of several source files.
+       </para>
+       </section>
+
+       <section>
+       <title>Driver with A Single Source File</title>
+       <para>
+       <orderedlist>
+       <listitem>
+       <para>
+       Modify alsa-driver/pci/Makefile
+       </para>
+
+       <para>
+       Suppose you have a file xyz.c.  Add the following
+       two lines
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  snd-xyz-objs := xyz.o
+  extra-obj-$(CONFIG_SND_XYZ) += snd-xyz.o
+]]>
+        </programlisting>
+      </informalexample>
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       Modify alsa-driver/acore/Makefile
+       </para>
+
+       <para>
+       Here define the dependent modules.
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  obj-$(CONFIG_SND_XYZ) += snd.o ...
+]]>
+        </programlisting>
+      </informalexample>
+
+       If the driver supports PCM, snd-pcm.o,
+       snd-timer.o and snd-page-alloc.o
+       will be needed.
+       </para>
+       <para>
+       For rawmidi, snd-rawmidi.o is needed in addition.
+       The MIDI stuff is also related to the sequencer.
+       You'll need to modify alsa-driver/acore/seq/Makefile.
+       </para>
+
+       <para>
+       For OPL3, snd-hwdep.o is needed, too.
+       It's involved with the sequencer, and as well as rawmidi,
+       you'll need to modify alsa-driver/acore/seq/Makefile
+       and acore/seq/instr/Makefile in addition.
+       Also, a new entry is necessary in
+       alsa-driver/drivers/opl3/Makefile.
+       </para>
+
+       </listitem>
+
+       <listitem>
+       <para>
+       Modify alsa-driver/utils/Modules.dep
+       </para>
+
+       <para>
+       Add the module definition for configure, here.
+       The beginning of the line must be a vertical bar, following
+       the card module name (snd-xyz) and the list of its all 
+       dependent modules.
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  %dir linux/sound/pci
+  |snd-azt3328 snd-pcm snd-mpu401-uart snd-opl3-lib snd-opl3-synth
+  |snd-xyz snd-pcm ...
+]]>
+        </programlisting>
+      </informalexample>
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       Run cvscompile script to re-generate the configure script and
+       build the whole stuff again.
+       </para>
+       </listitem>
+       </orderedlist>
+       </para>
+       </section>
+
+       <section>
+       <title>Drivers with Several Source Files</title>
+       <para>
+       Suppose that the driver snd-xyz have several source files.
+       They are located in the new subdirectory,
+       pci/xyz.
+
+       <orderedlist>
+       <listitem>
+       <para>
+       Add a new directory (xyz) to extra-subdir-y list in alsa-driver/pci/Makefile
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  extra-subdir-y := pdplus vx222 xyz
+]]>
+        </programlisting>
+      </informalexample>
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       Under the directory xyz, create a Makefile
+
+      <example>
+       <title>Sample Makefile for a driver xyz</title>
+        <programlisting>
+<![CDATA[
+  TOPDIR = ../..
+
+  include $(TOPDIR)/toplevel.config
+  include $(TOPDIR)/Makefile.conf
+
+  TOPDIR = $(MAINSRCDIR)
+
+  snd-xyz-objs := xyz.o abc.o def.o
+
+  obj-$(CONFIG_SND_XYZ) += snd-xyz.o
+
+  include $(TOPDIR)/Rules.make
+]]>
+        </programlisting>
+      </example>
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       Modify alsa-driver/acore/Makefile
+       </para>
+
+       <para>
+       This procedure is as same as in the last section.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       Modify alsa-driver/utils/Modules.dep
+       </para>
+
+       <para>
+      <informalexample>
+        <programlisting>
+<![CDATA[
+       %dir linux/sound/pci/xyz
+       |snd-xyz snd-pcm ...
+]]>
+        </programlisting>
+      </informalexample>
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       Run cvscompile script to re-generate the configure script and
+       build the whole stuff again.
+       </para>
+       </listitem>
+       </orderedlist>
+       </para>
+       </section>
+
+  </chapter>
 
 <!-- ****************************************************** -->
 <!-- Useful Functions  -->



-------------------------------------------------------
This SF.net email is sponsored by:
The Definitive IT and Networking Event. Be There!
NetWorld+Interop Las Vegas 2003 -- Register today!
http://ads.sourceforge.net/cgi-bin/redirect.pl?keyn0001en
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog

Reply via email to