The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arch/macppc/dev/snapper.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: snapper.c,v 1.44 2022/10/26 20:19:07 kn Exp $ */
    2 /*      $NetBSD: snapper.c,v 1.1 2003/12/27 02:19:34 grant Exp $        */
    3 
    4 /*-
    5  * Copyright (c) 2002 Tsubai Masanari.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 
   30 /*
   31  * Datasheet is available from
   32  * http://focus.ti.com/docs/prod/folders/print/tas3004.html
   33  */
   34 
   35 #include <sys/param.h>
   36 #include <sys/audioio.h>
   37 #include <sys/device.h>
   38 #include <sys/systm.h>
   39 
   40 #include <dev/audio_if.h>
   41 #include <dev/ofw/openfirm.h>
   42 #include <macppc/dev/dbdma.h>
   43 
   44 #include <machine/autoconf.h>
   45 
   46 #include <macppc/dev/i2svar.h>
   47 
   48 #ifdef SNAPPER_DEBUG
   49 # define DPRINTF printf
   50 #else
   51 # define DPRINTF while (0) printf
   52 #endif
   53 
   54 /* XXX */
   55 #define snapper_softc i2s_softc
   56 
   57 /* XXX */
   58 int kiic_write(struct device *, int, int, const void *, int);
   59 int kiic_writereg(struct device *, int, u_int);
   60 
   61 void snapper_init(struct snapper_softc *);
   62 int snapper_match(struct device *, void *, void *);
   63 void snapper_attach(struct device *, struct device *, void *);
   64 void snapper_defer(struct device *);
   65 void snapper_set_volume(struct snapper_softc *, int, int);
   66 void snapper_set_bass(struct snapper_softc *, int);
   67 void snapper_set_treble(struct snapper_softc *, int);
   68 void snapper_set_input(struct snapper_softc *, int);
   69 
   70 int tas3004_write(struct snapper_softc *, u_int, const void *);
   71 int tas3004_init(struct snapper_softc *);
   72 
   73 const struct cfattach snapper_ca = {
   74         sizeof(struct snapper_softc), snapper_match, snapper_attach
   75 };
   76 struct cfdriver snapper_cd = {
   77         NULL, "snapper", DV_DULL
   78 };
   79 
   80 const struct audio_hw_if snapper_hw_if = {
   81         .open = i2s_open,
   82         .close = i2s_close,
   83         .set_params = i2s_set_params,
   84         .round_blocksize = i2s_round_blocksize,
   85         .halt_output = i2s_halt_output,
   86         .halt_input = i2s_halt_input,
   87         .set_port = i2s_set_port,
   88         .get_port = i2s_get_port,
   89         .query_devinfo = i2s_query_devinfo,
   90         .allocm = i2s_allocm,
   91         .round_buffersize = i2s_round_buffersize,
   92         .trigger_output = i2s_trigger_output,
   93         .trigger_input = i2s_trigger_input,
   94 };
   95 
   96 const uint8_t snapper_trebletab[] = {
   97         0x96,   /* -18dB */
   98         0x94,   /* -17dB */
   99         0x92,   /* -16dB */
  100         0x90,   /* -15dB */
  101         0x8e,   /* -14dB */
  102         0x8c,   /* -13dB */
  103         0x8a,   /* -12dB */
  104         0x88,   /* -11dB */
  105         0x86,   /* -10dB */
  106         0x84,   /* -9dB */
  107         0x82,   /* -8dB */
  108         0x80,   /* -7dB */
  109         0x7e,   /* -6dB */
  110         0x7c,   /* -5dB */
  111         0x7a,   /* -4dB */
  112         0x78,   /* -3dB */
  113         0x76,   /* -2dB */
  114         0x74,   /* -1dB */
  115         0x72,   /* 0dB */
  116         0x70,   /* 1dB */
  117         0x6d,   /* 2dB */
  118         0x6b,   /* 3dB */
  119         0x68,   /* 4dB */
  120         0x65,   /* 5dB */
  121         0x62,   /* 6dB */
  122         0x5d,   /* 7dB */
  123         0x59,   /* 8dB */
  124         0x53,   /* 9dB */
  125         0x4d,   /* 10dB */
  126         0x47,   /* 11dB */
  127         0x3f,   /* 12dB */
  128         0x36,   /* 13dB */
  129         0x2c,   /* 14dB */
  130         0x20,   /* 15dB */
  131         0x13,   /* 16dB */
  132         0x04,   /* 17dB */
  133         0x01,   /* 18dB */
  134 };
  135 
  136 const uint8_t snapper_basstab[] = {
  137         0x96,   /* -18dB */
  138         0x94,   /* -17dB */
  139         0x92,   /* -16dB */
  140         0x90,   /* -15dB */
  141         0x8e,   /* -14dB */
  142         0x8c,   /* -13dB */
  143         0x8a,   /* -12dB */
  144         0x88,   /* -11dB */
  145         0x86,   /* -10dB */
  146         0x84,   /* -9dB */
  147         0x82,   /* -8dB */
  148         0x80,   /* -7dB */
  149         0x7e,   /* -6dB */
  150         0x7c,   /* -5dB */
  151         0x7a,   /* -4dB */
  152         0x78,   /* -3dB */
  153         0x76,   /* -2dB */
  154         0x74,   /* -1dB */
  155         0x72,   /* 0dB */
  156         0x6f,   /* 1dB */
  157         0x6d,   /* 2dB */
  158         0x6a,   /* 3dB */
  159         0x67,   /* 4dB */
  160         0x65,   /* 5dB */
  161         0x62,   /* 6dB */
  162         0x5f,   /* 7dB */
  163         0x5b,   /* 8dB */
  164         0x55,   /* 9dB */
  165         0x4f,   /* 10dB */
  166         0x49,   /* 11dB */
  167         0x43,   /* 12dB */
  168         0x3b,   /* 13dB */
  169         0x33,   /* 14dB */
  170         0x29,   /* 15dB */
  171         0x1e,   /* 16dB */
  172         0x11,   /* 17dB */
  173         0x01,   /* 18dB */
  174 };
  175 
  176 struct {
  177         int high, mid, low;
  178 } snapper_volumetab[] = {
  179         { 0x07, 0xF1, 0x7B }, /* 18.0 */
  180         { 0x07, 0x7F, 0xBB }, /* 17.5 */
  181         { 0x07, 0x14, 0x57 }, /* 17.0 */
  182         { 0x06, 0xAE, 0xF6 }, /* 16.5 */
  183         { 0x06, 0x4F, 0x40 }, /* 16.0 */
  184         { 0x05, 0xF4, 0xE5 }, /* 15.5 */
  185         { 0x05, 0x9F, 0x98 }, /* 15.0 */
  186         { 0x05, 0x4F, 0x10 }, /* 14.5 */
  187         { 0x05, 0x03, 0x0A }, /* 14.0 */
  188         { 0x04, 0xBB, 0x44 }, /* 13.5 */
  189         { 0x04, 0x77, 0x83 }, /* 13.0 */
  190         { 0x04, 0x37, 0x8B }, /* 12.5 */
  191         { 0x03, 0xFB, 0x28 }, /* 12.0 */
  192         { 0x03, 0xC2, 0x25 }, /* 11.5 */
  193         { 0x03, 0x8C, 0x53 }, /* 11.0 */
  194         { 0x03, 0x59, 0x83 }, /* 10.5 */
  195         { 0x03, 0x29, 0x8B }, /* 10.0 */
  196         { 0x02, 0xFC, 0x42 }, /* 9.5 */
  197         { 0x02, 0xD1, 0x82 }, /* 9.0 */
  198         { 0x02, 0xA9, 0x25 }, /* 8.5 */
  199         { 0x02, 0x83, 0x0B }, /* 8.0 */
  200         { 0x02, 0x5F, 0x12 }, /* 7.5 */
  201         { 0x02, 0x3D, 0x1D }, /* 7.0 */
  202         { 0x02, 0x1D, 0x0E }, /* 6.5 */
  203         { 0x01, 0xFE, 0xCA }, /* 6.0 */
  204         { 0x01, 0xE2, 0x37 }, /* 5.5 */
  205         { 0x01, 0xC7, 0x3D }, /* 5.0 */
  206         { 0x01, 0xAD, 0xC6 }, /* 4.5 */
  207         { 0x01, 0x95, 0xBC }, /* 4.0 */
  208         { 0x01, 0x7F, 0x09 }, /* 3.5 */
  209         { 0x01, 0x69, 0x9C }, /* 3.0 */
  210         { 0x01, 0x55, 0x62 }, /* 2.5 */
  211         { 0x01, 0x42, 0x49 }, /* 2.0 */
  212         { 0x01, 0x30, 0x42 }, /* 1.5 */
  213         { 0x01, 0x1F, 0x3D }, /* 1.0 */
  214         { 0x01, 0x0F, 0x2B }, /* 0.5 */
  215         { 0x01, 0x00, 0x00 }, /* 0.0 */
  216         { 0x00, 0xF1, 0xAE }, /* -0.5 */
  217         { 0x00, 0xE4, 0x29 }, /* -1.0 */
  218         { 0x00, 0xD7, 0x66 }, /* -1.5 */
  219         { 0x00, 0xCB, 0x59 }, /* -2.0 */
  220         { 0x00, 0xBF, 0xF9 }, /* -2.5 */
  221         { 0x00, 0xB5, 0x3C }, /* -3.0 */
  222         { 0x00, 0xAB, 0x19 }, /* -3.5 */
  223         { 0x00, 0xA1, 0x86 }, /* -4.0 */
  224         { 0x00, 0x98, 0x7D }, /* -4.5 */
  225         { 0x00, 0x8F, 0xF6 }, /* -5.0 */
  226         { 0x00, 0x87, 0xE8 }, /* -5.5 */
  227         { 0x00, 0x80, 0x4E }, /* -6.0 */
  228         { 0x00, 0x79, 0x20 }, /* -6.5 */
  229         { 0x00, 0x72, 0x5A }, /* -7.0 */
  230         { 0x00, 0x6B, 0xF4 }, /* -7.5 */
  231         { 0x00, 0x65, 0xEA }, /* -8.0 */
  232         { 0x00, 0x60, 0x37 }, /* -8.5 */
  233         { 0x00, 0x5A, 0xD5 }, /* -9.0 */
  234         { 0x00, 0x55, 0xC0 }, /* -9.5 */
  235         { 0x00, 0x50, 0xF4 }, /* -10.0 */
  236         { 0x00, 0x4C, 0x6D }, /* -10.5 */
  237         { 0x00, 0x48, 0x27 }, /* -11.0 */
  238         { 0x00, 0x44, 0x1D }, /* -11.5 */
  239         { 0x00, 0x40, 0x4E }, /* -12.0 */
  240         { 0x00, 0x3C, 0xB5 }, /* -12.5 */
  241         { 0x00, 0x39, 0x50 }, /* -13.0 */
  242         { 0x00, 0x36, 0x1B }, /* -13.5 */
  243         { 0x00, 0x33, 0x14 }, /* -14.0 */
  244         { 0x00, 0x30, 0x39 }, /* -14.5 */
  245         { 0x00, 0x2D, 0x86 }, /* -15.0 */
  246         { 0x00, 0x2A, 0xFA }, /* -15.5 */
  247         { 0x00, 0x28, 0x93 }, /* -16.0 */
  248         { 0x00, 0x26, 0x4E }, /* -16.5 */
  249         { 0x00, 0x24, 0x29 }, /* -17.0 */
  250         { 0x00, 0x22, 0x23 }, /* -17.5 */
  251         { 0x00, 0x20, 0x3A }, /* -18.0 */
  252         { 0x00, 0x1E, 0x6D }, /* -18.5 */
  253         { 0x00, 0x1C, 0xB9 }, /* -19.0 */
  254         { 0x00, 0x1B, 0x1E }, /* -19.5 */
  255         { 0x00, 0x19, 0x9A }, /* -20.0 */
  256         { 0x00, 0x18, 0x2B }, /* -20.5 */
  257         { 0x00, 0x16, 0xD1 }, /* -21.0 */
  258         { 0x00, 0x15, 0x8A }, /* -21.5 */
  259         { 0x00, 0x14, 0x56 }, /* -22.0 */
  260         { 0x00, 0x13, 0x33 }, /* -22.5 */
  261         { 0x00, 0x12, 0x20 }, /* -23.0 */
  262         { 0x00, 0x11, 0x1C }, /* -23.5 */
  263         { 0x00, 0x10, 0x27 }, /* -24.0 */
  264         { 0x00, 0x0F, 0x40 }, /* -24.5 */
  265         { 0x00, 0x0E, 0x65 }, /* -25.0 */
  266         { 0x00, 0x0D, 0x97 }, /* -25.5 */
  267         { 0x00, 0x0C, 0xD5 }, /* -26.0 */
  268         { 0x00, 0x0C, 0x1D }, /* -26.5 */
  269         { 0x00, 0x0B, 0x6F }, /* -27.0 */
  270         { 0x00, 0x0A, 0xCC }, /* -27.5 */
  271         { 0x00, 0x0A, 0x31 }, /* -28.0 */
  272         { 0x00, 0x09, 0x9F }, /* -28.5 */
  273         { 0x00, 0x09, 0x15 }, /* -29.0 */
  274         { 0x00, 0x08, 0x93 }, /* -29.5 */
  275         { 0x00, 0x08, 0x18 }, /* -30.0 */
  276         { 0x00, 0x07, 0xA5 }, /* -30.5 */
  277         { 0x00, 0x07, 0x37 }, /* -31.0 */
  278         { 0x00, 0x06, 0xD0 }, /* -31.5 */
  279         { 0x00, 0x06, 0x6E }, /* -32.0 */
  280         { 0x00, 0x06, 0x12 }, /* -32.5 */
  281         { 0x00, 0x05, 0xBB }, /* -33.0 */
  282         { 0x00, 0x05, 0x69 }, /* -33.5 */
  283         { 0x00, 0x05, 0x1C }, /* -34.0 */
  284         { 0x00, 0x04, 0xD2 }, /* -34.5 */
  285         { 0x00, 0x04, 0x8D }, /* -35.0 */
  286         { 0x00, 0x04, 0x4C }, /* -35.5 */
  287         { 0x00, 0x04, 0x0F }, /* -36.0 */
  288         { 0x00, 0x03, 0xD5 }, /* -36.5 */
  289         { 0x00, 0x03, 0x9E }, /* -37.0 */
  290         { 0x00, 0x03, 0x6A }, /* -37.5 */
  291         { 0x00, 0x03, 0x39 }, /* -38.0 */
  292         { 0x00, 0x03, 0x0B }, /* -38.5 */
  293         { 0x00, 0x02, 0xDF }, /* -39.0 */
  294         { 0x00, 0x02, 0xB6 }, /* -39.5 */
  295         { 0x00, 0x02, 0x8F }, /* -40.0 */
  296         { 0x00, 0x02, 0x6B }, /* -40.5 */
  297         { 0x00, 0x02, 0x48 }, /* -41.0 */
  298         { 0x00, 0x02, 0x27 }, /* -41.5 */
  299         { 0x00, 0x02, 0x09 }, /* -42.0 */
  300         { 0x00, 0x01, 0xEB }, /* -42.5 */
  301         { 0x00, 0x01, 0xD0 }, /* -43.0 */
  302         { 0x00, 0x01, 0xB6 }, /* -43.5 */
  303         { 0x00, 0x01, 0x9E }, /* -44.0 */
  304         { 0x00, 0x01, 0x86 }, /* -44.5 */
  305         { 0x00, 0x01, 0x71 }, /* -45.0 */
  306         { 0x00, 0x01, 0x5C }, /* -45.5 */
  307         { 0x00, 0x01, 0x48 }, /* -46.0 */
  308         { 0x00, 0x01, 0x36 }, /* -46.5 */
  309         { 0x00, 0x01, 0x25 }, /* -47.0 */
  310         { 0x00, 0x01, 0x14 }, /* -47.5 */
  311         { 0x00, 0x01, 0x05 }, /* -48.0 */
  312         { 0x00, 0x00, 0xF6 }, /* -48.5 */
  313         { 0x00, 0x00, 0xE9 }, /* -49.0 */
  314         { 0x00, 0x00, 0xDC }, /* -49.5 */
  315         { 0x00, 0x00, 0xCF }, /* -50.0 */
  316         { 0x00, 0x00, 0xC4 }, /* -50.5 */
  317         { 0x00, 0x00, 0xB9 }, /* -51.0 */
  318         { 0x00, 0x00, 0xAE }, /* -51.5 */
  319         { 0x00, 0x00, 0xA5 }, /* -52.0 */
  320         { 0x00, 0x00, 0x9B }, /* -52.5 */
  321         { 0x00, 0x00, 0x93 }, /* -53.0 */
  322         { 0x00, 0x00, 0x8B }, /* -53.5 */
  323         { 0x00, 0x00, 0x83 }, /* -54.0 */
  324         { 0x00, 0x00, 0x7B }, /* -54.5 */
  325         { 0x00, 0x00, 0x75 }, /* -55.0 */
  326         { 0x00, 0x00, 0x6E }, /* -55.5 */
  327         { 0x00, 0x00, 0x68 }, /* -56.0 */
  328         { 0x00, 0x00, 0x62 }, /* -56.5 */
  329         { 0x00, 0x00, 0x0 } /* Mute? */
  330 
  331 };
  332 
  333 /* TAS3004 registers */
  334 #define DEQ_MCR1        0x01    /* Main control register 1 (1byte) */
  335 #define DEQ_DRC         0x02    /* Dynamic range compression (6bytes?) */
  336 #define DEQ_VOLUME      0x04    /* Volume (6bytes) */
  337 #define DEQ_TREBLE      0x05    /* Treble control (1byte) */
  338 #define DEQ_BASS        0x06    /* Bass control (1byte) */
  339 #define DEQ_MIXER_L     0x07    /* Mixer left gain (9bytes) */
  340 #define DEQ_MIXER_R     0x08    /* Mixer right gain (9bytes) */
  341 #define DEQ_LB0         0x0a    /* Left biquad 0 (15bytes) */
  342 #define DEQ_LB1         0x0b    /* Left biquad 1 (15bytes) */
  343 #define DEQ_LB2         0x0c    /* Left biquad 2 (15bytes) */
  344 #define DEQ_LB3         0x0d    /* Left biquad 3 (15bytes) */
  345 #define DEQ_LB4         0x0e    /* Left biquad 4 (15bytes) */
  346 #define DEQ_LB5         0x0f    /* Left biquad 5 (15bytes) */
  347 #define DEQ_LB6         0x10    /* Left biquad 6 (15bytes) */
  348 #define DEQ_RB0         0x13    /* Right biquad 0 (15bytes) */
  349 #define DEQ_RB1         0x14    /* Right biquad 1 (15bytes) */
  350 #define DEQ_RB2         0x15    /* Right biquad 2 (15bytes) */
  351 #define DEQ_RB3         0x16    /* Right biquad 3 (15bytes) */
  352 #define DEQ_RB4         0x17    /* Right biquad 4 (15bytes) */
  353 #define DEQ_RB5         0x18    /* Right biquad 5 (15bytes) */
  354 #define DEQ_RB6         0x19    /* Right biquad 6 (15bytes) */
  355 #define DEQ_LLB         0x21    /* Left loudness biquad (15bytes) */
  356 #define DEQ_RLB         0x22    /* Right loudness biquad (15bytes) */
  357 #define DEQ_LLB_GAIN    0x23    /* Left loudness biquad gain (3bytes) */
  358 #define DEQ_RLB_GAIN    0x24    /* Right loudness biquad gain (3bytes) */
  359 #define DEQ_ACR         0x40    /* Analog control register (1byte) */
  360 #define DEQ_MCR2        0x43    /* Main control register 2 (1byte) */
  361 
  362 #define DEQ_MCR1_FL     0x80    /* Fast load */
  363 #define DEQ_MCR1_SC     0x40    /* SCLK frequency */
  364 #define  DEQ_MCR1_SC_32 0x00    /*  32fs */
  365 #define  DEQ_MCR1_SC_64 0x40    /*  64fs */
  366 #define DEQ_MCR1_SM     0x30    /* Output serial port mode */
  367 #define  DEQ_MCR1_SM_L  0x00    /*  Left justified */
  368 #define  DEQ_MCR1_SM_R  0x10    /*  Right justified */
  369 #define  DEQ_MCR1_SM_I2S 0x20   /*  I2S */
  370 #define DEQ_MCR1_W      0x03    /* Serial port word length */
  371 #define  DEQ_MCR1_W_16  0x00    /*  16 bit */
  372 #define  DEQ_MCR1_W_18  0x01    /*  18 bit */
  373 #define  DEQ_MCR1_W_20  0x02    /*  20 bit */
  374 
  375 #define DEQ_MCR2_DL     0x80    /* Download */
  376 #define DEQ_MCR2_AP     0x02    /* All pass mode */
  377 
  378 #define DEQ_ACR_ADM     0x80    /* ADC output mode */
  379 #define DEQ_ACR_LRB     0x40    /* Select B input */
  380 #define DEQ_ACR_DM      0x0c    /* De-emphasis control */
  381 #define  DEQ_ACR_DM_OFF 0x00    /*  off */
  382 #define  DEQ_ACR_DM_48  0x04    /*  fs = 48kHz */
  383 #define  DEQ_ACR_DM_44  0x08    /*  fs = 44.1kHz */
  384 #define DEQ_ACR_INP     0x02    /* Analog input select */
  385 #define  DEQ_ACR_INP_A  0x00    /*  A */
  386 #define  DEQ_ACR_INP_B  0x02    /*  B */
  387 #define DEQ_ACR_APD     0x01    /* Analog power down */
  388 
  389 struct tas3004_reg {
  390         u_char MCR1[1];
  391         u_char DRC[6];
  392         u_char VOLUME[6];
  393         u_char TREBLE[1];
  394         u_char BASS[1];
  395         u_char MIXER_L[9];
  396         u_char MIXER_R[9];
  397         u_char LB0[15];
  398         u_char LB1[15];
  399         u_char LB2[15];
  400         u_char LB3[15];
  401         u_char LB4[15];
  402         u_char LB5[15];
  403         u_char LB6[15];
  404         u_char RB0[15];
  405         u_char RB1[15];
  406         u_char RB2[15];
  407         u_char RB3[15];
  408         u_char RB4[15];
  409         u_char RB5[15];
  410         u_char RB6[15];
  411         u_char LLB[15];
  412         u_char RLB[15];
  413         u_char LLB_GAIN[3];
  414         u_char RLB_GAIN[3];
  415         u_char ACR[1];
  416         u_char MCR2[1];
  417 };
  418 
  419 int
  420 snapper_match(struct device *parent, void *match, void *aux)
  421 {
  422         struct confargs *ca = aux;
  423         int soundbus, soundchip, soundcodec;
  424         char compat[32];
  425 
  426         if (strcmp(ca->ca_name, "i2s") != 0)
  427                 return (0);
  428 
  429         if ((soundbus = OF_child(ca->ca_node)) == 0 ||
  430             (soundchip = OF_child(soundbus)) == 0)
  431                 return (0);
  432 
  433         bzero(compat, sizeof compat);
  434         OF_getprop(soundchip, "compatible", compat, sizeof compat);
  435 
  436         if (strcmp(compat, "AOAKeylargo") == 0 &&
  437             strcmp(hw_prod, "PowerBook5,4") == 0)
  438                 return (1);
  439         if (strcmp(compat, "snapper") == 0)
  440                 return (1);
  441 
  442         if (OF_getprop(soundchip, "platform-tas-codec-ref",
  443             &soundcodec, sizeof soundcodec) == sizeof soundcodec)
  444                 return (1);
  445 
  446         return (0);
  447 }
  448 
  449 void
  450 snapper_attach(struct device *parent, struct device *self, void *aux)
  451 {
  452         struct snapper_softc *sc = (struct snapper_softc *)self;
  453 
  454         sc->sc_setvolume = snapper_set_volume;
  455         sc->sc_setbass = snapper_set_bass;
  456         sc->sc_settreble = snapper_set_treble;
  457         sc->sc_setinput = snapper_set_input;
  458 
  459         i2s_attach(parent, sc, aux);
  460         config_defer(self, snapper_defer);
  461 }
  462 
  463 void
  464 snapper_defer(struct device *dev)
  465 {
  466         struct snapper_softc *sc = (struct snapper_softc *)dev;
  467         struct device *dv;
  468 
  469         TAILQ_FOREACH(dv, &alldevs, dv_list)
  470                 if (strcmp(dv->dv_cfdata->cf_driver->cd_name, "kiic") == 0 &&
  471                     strcmp(dv->dv_parent->dv_cfdata->cf_driver->cd_name, "macobio") == 0)
  472                         sc->sc_i2c = dv;
  473         if (sc->sc_i2c == NULL) {
  474                 printf("%s: unable to find i2c\n", sc->sc_dev.dv_xname);
  475                 return;
  476         }
  477 
  478         /* XXX If i2c has failed to attach, what should we do? */
  479 
  480         audio_attach_mi(&snapper_hw_if, sc, NULL, &sc->sc_dev);
  481 
  482         /* kiic_setmode(sc->sc_i2c, I2C_STDSUBMODE); */
  483         snapper_init(sc);
  484 }
  485 
  486 void
  487 snapper_set_volume(struct snapper_softc *sc, int left, int right)
  488 {
  489         u_char vol[6];
  490         int nentries = sizeof(snapper_volumetab) / sizeof(snapper_volumetab[0]);
  491         int l, r;
  492 
  493         sc->sc_vol_l = left;
  494         sc->sc_vol_r = right;
  495 
  496         l = nentries - (left * nentries / 256);
  497         r = nentries - (right * nentries / 256);
  498 
  499         DPRINTF(" left %d vol %d %d, right %d vol %d %d\n",
  500                 left, l, nentries,
  501                 right, r, nentries);
  502         if (l >= nentries)
  503                 l = nentries-1;
  504         if (r >= nentries)
  505                 r = nentries-1;
  506 
  507         vol[0] = snapper_volumetab[l].high;
  508         vol[1] = snapper_volumetab[l].mid;
  509         vol[2] = snapper_volumetab[l].low;
  510         vol[3] = snapper_volumetab[r].high;
  511         vol[4] = snapper_volumetab[r].mid;
  512         vol[5] = snapper_volumetab[r].low;
  513 
  514         tas3004_write(sc, DEQ_VOLUME, vol);
  515 }
  516 
  517 void
  518 snapper_set_treble(struct snapper_softc *sc, int value)
  519 {
  520         uint8_t reg;
  521 
  522         if ((value >= 0) && (value <= 255) && (value != sc->sc_treble)) {
  523                 reg = snapper_trebletab[(value >> 3) + 2];
  524                 if (tas3004_write(sc, DEQ_TREBLE, &reg) < 0)
  525                         return;
  526                 sc->sc_treble = value;
  527         }
  528 }
  529 
  530 void
  531 snapper_set_bass(struct snapper_softc *sc, int value)
  532 {
  533         uint8_t reg;
  534 
  535         if ((value >= 0) && (value <= 255) && (value != sc->sc_bass)) {
  536                 reg = snapper_basstab[(value >> 3) + 2];
  537                 if (tas3004_write(sc, DEQ_BASS, &reg) < 0)
  538                         return;
  539                 sc->sc_bass = value;
  540         }
  541 }
  542 
  543 void
  544 snapper_set_input(struct snapper_softc *sc, int mask)
  545 {
  546         uint8_t val = 0;
  547 
  548         switch (mask) {
  549         case    1 << 0: /* microphone */
  550                 val = DEQ_ACR_ADM | DEQ_ACR_LRB | DEQ_ACR_INP_B;
  551                 break;
  552         case    1 << 1: /* line in */
  553                 val = 0;
  554                 break;
  555         }
  556         tas3004_write(sc, DEQ_ACR, &val);
  557 }
  558 
  559 const struct tas3004_reg tas3004_initdata = {
  560         { DEQ_MCR1_SC_64 | DEQ_MCR1_SM_I2S | DEQ_MCR1_W_20 },   /* MCR1 */
  561         { 1, 0, 0, 0, 0, 0 },                                   /* DRC */
  562         { 0x00, 0xd7, 0x66, 0x00, 0xd7, 0x66 },                 /* VOLUME */
  563         { 0x72 },                                               /* TREBLE */
  564         { 0x72 },                                               /* BASS */
  565         { 0x10, 0x00, 0x00, 0, 0, 0, 0, 0, 0 },                 /* MIXER_L */
  566         { 0x10, 0x00, 0x00, 0, 0, 0, 0, 0, 0 },                 /* MIXER_R */
  567         { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },     /* BIQUAD */
  568         { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },     /* BIQUAD */
  569         { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },     /* BIQUAD */
  570         { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },     /* BIQUAD */
  571         { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },     /* BIQUAD */
  572         { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },     /* BIQUAD */
  573         { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },     /* BIQUAD */
  574         { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },     /* BIQUAD */
  575         { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },     /* BIQUAD */
  576         { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },     /* BIQUAD */
  577         { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },     /* BIQUAD */
  578         { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },     /* BIQUAD */
  579         { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },     /* BIQUAD */
  580         { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },     /* BIQUAD */
  581         { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },     /* BIQUAD */
  582         { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },     /* BIQUAD */
  583         { 0, 0, 0 },                                            /* LLB_GAIN */
  584         { 0, 0, 0 },                                            /* RLB_GAIN */
  585         { DEQ_ACR_ADM | DEQ_ACR_LRB | DEQ_ACR_INP_B },          /* ACR */
  586         { 0 }                                                   /* MCR2 */
  587 };
  588 
  589 const char tas3004_regsize[] = {
  590         0,                                      /* 0x00 */
  591         sizeof tas3004_initdata.MCR1,           /* 0x01 */
  592         sizeof tas3004_initdata.DRC,            /* 0x02 */
  593         0,                                      /* 0x03 */
  594         sizeof tas3004_initdata.VOLUME,         /* 0x04 */
  595         sizeof tas3004_initdata.TREBLE,         /* 0x05 */
  596         sizeof tas3004_initdata.BASS,           /* 0x06 */
  597         sizeof tas3004_initdata.MIXER_L,        /* 0x07 */
  598         sizeof tas3004_initdata.MIXER_R,        /* 0x08 */
  599         0,                                      /* 0x09 */
  600         sizeof tas3004_initdata.LB0,            /* 0x0a */
  601         sizeof tas3004_initdata.LB1,            /* 0x0b */
  602         sizeof tas3004_initdata.LB2,            /* 0x0c */
  603         sizeof tas3004_initdata.LB3,            /* 0x0d */
  604         sizeof tas3004_initdata.LB4,            /* 0x0e */
  605         sizeof tas3004_initdata.LB5,            /* 0x0f */
  606         sizeof tas3004_initdata.LB6,            /* 0x10 */
  607         0,                                      /* 0x11 */
  608         0,                                      /* 0x12 */
  609         sizeof tas3004_initdata.RB0,            /* 0x13 */
  610         sizeof tas3004_initdata.RB1,            /* 0x14 */
  611         sizeof tas3004_initdata.RB2,            /* 0x15 */
  612         sizeof tas3004_initdata.RB3,            /* 0x16 */
  613         sizeof tas3004_initdata.RB4,            /* 0x17 */
  614         sizeof tas3004_initdata.RB5,            /* 0x18 */
  615         sizeof tas3004_initdata.RB6,            /* 0x19 */
  616         0,0,0,0, 0,0,
  617         0,                                      /* 0x20 */
  618         sizeof tas3004_initdata.LLB,            /* 0x21 */
  619         sizeof tas3004_initdata.RLB,            /* 0x22 */
  620         sizeof tas3004_initdata.LLB_GAIN,       /* 0x23 */
  621         sizeof tas3004_initdata.RLB_GAIN,       /* 0x24 */
  622         0,0,0,0, 0,0,0,0, 0,0,0,
  623         0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
  624         sizeof tas3004_initdata.ACR,            /* 0x40 */
  625         0,                                      /* 0x41 */
  626         0,                                      /* 0x42 */
  627         sizeof tas3004_initdata.MCR2            /* 0x43 */
  628 };
  629 
  630 #define DEQaddr 0x6a
  631 
  632 int
  633 tas3004_write(struct snapper_softc *sc, u_int reg, const void *data)
  634 {
  635         int size;
  636 
  637         KASSERT(reg < sizeof tas3004_regsize);
  638         size = tas3004_regsize[reg];
  639         KASSERT(size > 0);
  640 
  641         if (kiic_write(sc->sc_i2c, DEQaddr, reg, data, size))
  642                 return (-1);
  643 
  644         return (0);
  645 }
  646 
  647 #define DEQ_WRITE(sc, reg, addr) \
  648         if (tas3004_write(sc, reg, addr)) goto err
  649 
  650 int
  651 tas3004_init(struct snapper_softc *sc)
  652 {
  653         deq_reset(sc);
  654 
  655         DEQ_WRITE(sc, DEQ_LB0, tas3004_initdata.LB0);
  656         DEQ_WRITE(sc, DEQ_LB1, tas3004_initdata.LB1);
  657         DEQ_WRITE(sc, DEQ_LB2, tas3004_initdata.LB2);
  658         DEQ_WRITE(sc, DEQ_LB3, tas3004_initdata.LB3);
  659         DEQ_WRITE(sc, DEQ_LB4, tas3004_initdata.LB4);
  660         DEQ_WRITE(sc, DEQ_LB5, tas3004_initdata.LB5);
  661         DEQ_WRITE(sc, DEQ_LB6, tas3004_initdata.LB6);
  662         DEQ_WRITE(sc, DEQ_RB0, tas3004_initdata.RB0);
  663         DEQ_WRITE(sc, DEQ_RB1, tas3004_initdata.RB1);
  664         DEQ_WRITE(sc, DEQ_RB1, tas3004_initdata.RB1);
  665         DEQ_WRITE(sc, DEQ_RB2, tas3004_initdata.RB2);
  666         DEQ_WRITE(sc, DEQ_RB3, tas3004_initdata.RB3);
  667         DEQ_WRITE(sc, DEQ_RB4, tas3004_initdata.RB4);
  668         DEQ_WRITE(sc, DEQ_RB5, tas3004_initdata.RB5);
  669         DEQ_WRITE(sc, DEQ_RB6, tas3004_initdata.RB6);
  670         DEQ_WRITE(sc, DEQ_MCR1, tas3004_initdata.MCR1);
  671         DEQ_WRITE(sc, DEQ_MCR2, tas3004_initdata.MCR2);
  672         DEQ_WRITE(sc, DEQ_DRC, tas3004_initdata.DRC);
  673         DEQ_WRITE(sc, DEQ_VOLUME, tas3004_initdata.VOLUME);
  674         DEQ_WRITE(sc, DEQ_TREBLE, tas3004_initdata.TREBLE);
  675         DEQ_WRITE(sc, DEQ_BASS, tas3004_initdata.BASS);
  676         DEQ_WRITE(sc, DEQ_MIXER_L, tas3004_initdata.MIXER_L);
  677         DEQ_WRITE(sc, DEQ_MIXER_R, tas3004_initdata.MIXER_R);
  678         DEQ_WRITE(sc, DEQ_LLB, tas3004_initdata.LLB);
  679         DEQ_WRITE(sc, DEQ_RLB, tas3004_initdata.RLB);
  680         DEQ_WRITE(sc, DEQ_LLB_GAIN, tas3004_initdata.LLB_GAIN);
  681         DEQ_WRITE(sc, DEQ_RLB_GAIN, tas3004_initdata.RLB_GAIN);
  682         DEQ_WRITE(sc, DEQ_ACR, tas3004_initdata.ACR);
  683 
  684         return (0);
  685 err:
  686         printf("%s: tas3004_init failed\n", sc->sc_dev.dv_xname);
  687         return (-1);
  688 }
  689 
  690 void
  691 snapper_init(struct snapper_softc *sc)
  692 {
  693 
  694         /* "sample-rates" (44100, 48000) */
  695         i2s_set_rate(sc, 44100);
  696 
  697 #if 1
  698         /* Enable I2C interrupts. */
  699 #define IER 4
  700 #define I2C_INT_DATA 0x01
  701 #define I2C_INT_ADDR 0x02
  702 #define I2C_INT_STOP 0x04
  703         kiic_writereg(sc->sc_i2c, IER,I2C_INT_DATA|I2C_INT_ADDR|I2C_INT_STOP);
  704 #endif
  705 
  706         if (tas3004_init(sc))
  707                 return;
  708 
  709         snapper_set_volume(sc, 190, 190);
  710         snapper_set_treble(sc, 128); /* 0 dB */
  711         snapper_set_bass(sc, 128); /* 0 dB */
  712 
  713         /* Mic in, reflects tas3004_initdata.ACR */
  714         sc->sc_record_source = 1 << 1;
  715         snapper_set_input(sc, sc->sc_record_source);
  716 }

Cache object: eb9a593d492e1e54526457259869d82c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.