Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 11 Oct 1997 18:51:50 -0400
From:      john@jwlab.feith.com (John Wehle)
To:        multimedia@freebsd.org
Subject:   Patch to FreeBSD 3.0 AD1848 device driver
Message-ID:  <199710112251.SAA18270@jwlab.FEITH.COM>

next in thread | raw e-mail | index | archive | help
The enclosed patch clears up some of the snaps in the audio
produced by the AD1848 which were caused by overuse of the
autocalibration feature.  The changes are based on the Analog
Devices AD1845 datasheet and Ensoniq sample code.  FYI: the
AD1845 is pin compatible with the AD1846, AD1848, CS4231,
and CS4248.

Changes:

  1) ad1848_output_block and ad1848_start_input activated
     autocalibration (which causes a snap) even though
     according to the documentation it's only necessary
     to do this once and it had already been performed
     by ad1848_init.

  2) ad1848_prepare_for_IO suffered from code duplication
     seemingly due to someone trying to reconcile the code
     with similar code from another port.

  3) ad1848_prepare_for_IO didn't ensure that the ACAL bit
     was cleared prior to disabling the MCE bit.  This could
     cause an autocalibration to occur.

  4) ad1848_halt suffered from code duplication seemingly due
     to someone trying to reconcile the code with similar
     code from another port.

  5) ad1848_halt enabled MCE which according to the documentation
     it isn't necessary to do when disabling DMA, clearing the
     DMA registers, and clearing the INT bit.

  6) The comment in ad1848_init didn't state that clearing the
     MCE bit causes an autocalibration since the ACAL bit was
     set with the indirect registers were loaded.

Note:

  1) The datasheet states the following about changing sample rates:

     "...  Reads will produce "1000 0000 (80h)" until the
     resynchronization is complete.  Poll the Index Register
     until something other than this value is returned."

Sincerely,

John Wehle
------------------8<------------------------8<------------------------
*** sys/i386/isa/sound/ad1848.c.ORIGINAL	Tue Nov 12 20:59:56 1996
--- sys/i386/isa/sound/ad1848.c	Sat Oct 11 15:06:45 1997
***************
*** 813,827 ****
    ad_write (devc, 15, (unsigned char) (cnt & 0xff));
    ad_write (devc, 14, (unsigned char) ((cnt >> 8) & 0xff));
  
!   ad_write (devc, 9, 0x0d);	/*
  				 * Playback enable, single DMA channel mode,
! 				 * auto calibration on.
  				 */
  
!   ad_leave_MCE (devc);		/*
! 				 * Starts the calibration process and
! 				 * enters playback mode after it.
! 				 */
    ad_unmute (devc);
  
    devc->xfer_count = cnt;
--- 813,825 ----
    ad_write (devc, 15, (unsigned char) (cnt & 0xff));
    ad_write (devc, 14, (unsigned char) ((cnt >> 8) & 0xff));
  
!   ad_write (devc, 9, 0x05);	/*
  				 * Playback enable, single DMA channel mode,
! 				 * auto calibration off.
  				 */
  
!   ad_leave_MCE (devc);
! 
    ad_unmute (devc);
  
    devc->xfer_count = cnt;
***************
*** 877,891 ****
    ad_write (devc, count_reg + 1, (unsigned char) (cnt & 0xff));
    ad_write (devc, count_reg, (unsigned char) ((cnt >> 8) & 0xff));
  
!   ad_write (devc, 9, 0x0e);	/*
  				 * Capture enable, single DMA channel mode,
! 				 * auto calibration on.
  				 */
  
!   ad_leave_MCE (devc);		/*
! 				 * Starts the calibration process and
! 				 * enters playback mode after it.
! 				 */
    ad_unmute (devc);
  
    devc->xfer_count = cnt;
--- 875,887 ----
    ad_write (devc, count_reg + 1, (unsigned char) (cnt & 0xff));
    ad_write (devc, count_reg, (unsigned char) ((cnt >> 8) & 0xff));
  
!   ad_write (devc, 9, 0x06);	/*
  				 * Capture enable, single DMA channel mode,
! 				 * auto calibration off.
  				 */
  
!   ad_leave_MCE (devc);
! 
    ad_unmute (devc);
  
    devc->xfer_count = cnt;
***************
*** 906,975 ****
  
    DISABLE_INTR (flags);
    ad_enter_MCE (devc);		/* Enables changes to the format select reg */
    fs = devc->speed_bits | (devc->format_bits << 5);
  
    if (devc->channels > 1)
      fs |= 0x10;
  
    ad_write (devc, 8, fs);
    /*
     * Write to I8 starts resyncronization. Wait until it completes.
     */
    timeout = 10000;
- #ifdef PC98
-   while (timeout > 0 && (INB (devc->base) & 0x80) == 0x80)
- #else
    while (timeout > 0 && INB (devc->base) == 0x80)
- #endif
      timeout--;
  
- #ifdef PC98
-   ad_write (devc, 8, fs);
    /*
!    * Write to I8 starts resyncronization. Wait until it completes.
     */
-   timeout = 10000;
-   while (timeout > 0 && (INB (devc->base) & 0x80) == 0x80)
-     timeout--;
- #endif
  
-   /*
-      * If mode == 2 (CS4231), set I28 also. It's the capture format register.
-    */
    if (devc->mode == 2)
      {
!       ad_write (devc, 28, fs);
  
        /*
!          * Write to I28 starts resyncronization. Wait until it completes.
         */
        timeout = 10000;
- #ifdef PC98
-       while (timeout > 0 && (INB (devc->base) & 0x80) == 0x80)
- #else
        while (timeout > 0 && INB (devc->base) == 0x80)
- #endif
  	timeout--;
- 
      }
  
! #ifdef PC98
!       ad_write (devc, 28, fs);
  
!       /*
!          * Write to I28 starts resyncronization. Wait until it completes.
!        */
!       timeout = 10000;
!       while (timeout > 0 && (INB (devc->base) & 0x80) == 0x80)
! 	timeout--;
! #endif
! 
!   ad_leave_MCE (devc);		/*
! 				 * Starts the calibration process and
! 				 * enters playback mode after it.
! 				 */
    RESTORE_INTR (flags);
    devc->xfer_count = 0;
    return 0;
  }
  
--- 902,947 ----
  
    DISABLE_INTR (flags);
    ad_enter_MCE (devc);		/* Enables changes to the format select reg */
+ 
    fs = devc->speed_bits | (devc->format_bits << 5);
  
    if (devc->channels > 1)
      fs |= 0x10;
  
    ad_write (devc, 8, fs);
+ 
    /*
     * Write to I8 starts resyncronization. Wait until it completes.
     */
+ 
    timeout = 10000;
    while (timeout > 0 && INB (devc->base) == 0x80)
      timeout--;
  
    /*
!    * If mode == 2 (CS4231), set I28 also. It's the capture format register.
     */
  
    if (devc->mode == 2)
      {
!       ad_write (devc, 28, fs & 0x70);
  
        /*
!        * Write to I28 starts resyncronization. Wait until it completes.
         */
+ 
        timeout = 10000;
        while (timeout > 0 && INB (devc->base) == 0x80)
  	timeout--;
      }
  
!   ad_write (devc, 9, ad_read (devc, 9) & 0xc7);
  
!   ad_leave_MCE (devc);
    RESTORE_INTR (flags);
+ 
    devc->xfer_count = 0;
+ 
    return 0;
  }
  
***************
*** 985,1000 ****
    ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
  
    ad_mute (devc);
- #ifdef PC98
-   ad_enter_MCE (devc);
- #endif
-   ad_write (devc, 9, ad_read (devc, 9) & ~0x03);	/* Stop DMA */
- #ifdef PC98
-   ad_leave_MCE (devc);
- #endif
-   OUTB (0, io_Status (devc));	/* Clear interrupt status */
  
!   ad_enter_MCE (devc);
    OUTB (0, io_Status (devc));	/* Clear interrupt status */
    ad_write (devc, 15, 0);	/* Clear DMA counter */
    ad_write (devc, 14, 0);	/* Clear DMA counter */
--- 957,965 ----
    ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
  
    ad_mute (devc);
  
!   ad_write (devc, 9, ad_read (devc, 9) & 0xcc);	/* Stop DMA */
! 
    OUTB (0, io_Status (devc));	/* Clear interrupt status */
    ad_write (devc, 15, 0);	/* Clear DMA counter */
    ad_write (devc, 14, 0);	/* Clear DMA counter */
***************
*** 1005,1016 ****
        ad_write (devc, 31, 0);	/* Clear DMA counter */
      }
  
-   ad_write (devc, 9, ad_read (devc, 9) & ~0x03);	/* Stop DMA */
- 
-   OUTB (0, io_Status (devc));	/* Clear interrupt status */
-   OUTB (0, io_Status (devc));	/* Clear interrupt status */
-   ad_leave_MCE (devc);
- 
    DMAbuf_reset_dma (dev);
  }
  
--- 970,975 ----
***************
*** 1257,1263 ****
        nr_ad1848_devs++;
  
        /*
!          * Toggle the MCE bit. It completes the initialization phase.
         */
  
        ad_enter_MCE (devc);	/* In case the bit was off */
--- 1216,1224 ----
        nr_ad1848_devs++;
  
        /*
!        * Toggle the MCE bit.  This will cause an autocalibration
!        * (since the ACAL bit was set earlier) and completes the
!        * initialization phase.
         */
  
        ad_enter_MCE (devc);	/* In case the bit was off */
-------------------------------------------------------------------------
|   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
|    John Wehle    |     Fax: 1-215-540-5495  |                         |
-------------------------------------------------------------------------




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199710112251.SAA18270>