Home | History | Annotate | Line # | Download | only in ic
      1  1.26     isaki /*	$NetBSD: msm6258.c,v 1.26 2019/05/08 13:40:18 isaki Exp $	*/
      2   1.1   minoura 
      3   1.1   minoura /*
      4   1.1   minoura  * Copyright (c) 2001 Tetsuya Isaki. All rights reserved.
      5   1.1   minoura  *
      6   1.1   minoura  * Redistribution and use in source and binary forms, with or without
      7   1.1   minoura  * modification, are permitted provided that the following conditions
      8   1.1   minoura  * are met:
      9   1.1   minoura  * 1. Redistributions of source code must retain the above copyright
     10   1.1   minoura  *    notice, this list of conditions and the following disclaimer.
     11   1.1   minoura  * 2. Redistributions in binary form must reproduce the above copyright
     12   1.1   minoura  *    notice, this list of conditions and the following disclaimer in the
     13   1.1   minoura  *    documentation and/or other materials provided with the distribution.
     14   1.1   minoura  *
     15   1.1   minoura  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16   1.1   minoura  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     17   1.1   minoura  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     18   1.1   minoura  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     19   1.1   minoura  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     20   1.1   minoura  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     21   1.1   minoura  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     22   1.1   minoura  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     23   1.1   minoura  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24   1.1   minoura  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25   1.1   minoura  * SUCH DAMAGE.
     26   1.1   minoura  */
     27   1.1   minoura 
     28   1.1   minoura /*
     29   1.1   minoura  * OKI MSM6258 ADPCM voice synthesizer codec.
     30   1.1   minoura  */
     31   1.5     lukem 
     32   1.5     lukem #include <sys/cdefs.h>
     33  1.26     isaki __KERNEL_RCSID(0, "$NetBSD: msm6258.c,v 1.26 2019/05/08 13:40:18 isaki Exp $");
     34   1.1   minoura 
     35   1.1   minoura #include <sys/systm.h>
     36   1.1   minoura #include <sys/device.h>
     37  1.17  jmcneill #include <sys/kmem.h>
     38   1.1   minoura #include <sys/select.h>
     39   1.1   minoura #include <sys/audioio.h>
     40   1.1   minoura 
     41  1.26     isaki #include <dev/audio/audio_if.h>
     42   1.1   minoura #include <dev/ic/msm6258var.h>
     43   1.1   minoura 
     44  1.15     perry static inline uint8_t	pcm2adpcm_step(struct msm6258_codecvar *, int16_t);
     45  1.15     perry static inline int16_t	adpcm2pcm_step(struct msm6258_codecvar *, uint8_t);
     46   1.1   minoura 
     47  1.12      kent static const int adpcm_estimindex[16] = {
     48   1.9     isaki 	 2,  6,  10,  14,  18,  22,  26,  30,
     49   1.9     isaki 	-2, -6, -10, -14, -18, -22, -26, -30
     50   1.1   minoura };
     51   1.1   minoura 
     52  1.12      kent static const int adpcm_estim[49] = {
     53   1.1   minoura 	 16,  17,  19,  21,  23,  25,  28,  31,  34,  37,
     54   1.1   minoura 	 41,  45,  50,  55,  60,  66,  73,  80,  88,  97,
     55   1.1   minoura 	107, 118, 130, 143, 157, 173, 190, 209, 230, 253,
     56   1.1   minoura 	279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
     57  1.10     isaki 	724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
     58   1.1   minoura };
     59   1.1   minoura 
     60  1.12      kent static const int adpcm_estimstep[16] = {
     61   1.1   minoura 	-1, -1, -1, -1, 2, 4, 6, 8,
     62   1.1   minoura 	-1, -1, -1, -1, 2, 4, 6, 8
     63   1.1   minoura };
     64   1.1   minoura 
     65   1.9     isaki /*
     66   1.9     isaki  * signed 16bit linear PCM -> OkiADPCM
     67   1.9     isaki  */
     68  1.15     perry static inline uint8_t
     69  1.12      kent pcm2adpcm_step(struct msm6258_codecvar *mc, int16_t a)
     70   1.9     isaki {
     71   1.9     isaki 	int estim = (int)mc->mc_estim;
     72   1.9     isaki 	int df;
     73   1.9     isaki 	short dl, c;
     74  1.12      kent 	uint8_t b;
     75  1.12      kent 	uint8_t s;
     76   1.9     isaki 
     77   1.9     isaki 	df = a - mc->mc_amp;
     78   1.9     isaki 	dl = adpcm_estim[estim];
     79   1.9     isaki 	c = (df / 16) * 8 / dl;
     80   1.9     isaki 	if (df < 0) {
     81   1.9     isaki 		b = (unsigned char)(-c) / 2;
     82   1.9     isaki 		s = 0x08;
     83   1.9     isaki 	} else {
     84   1.9     isaki 		b = (unsigned char)(c) / 2;
     85   1.9     isaki 		s = 0;
     86   1.9     isaki 	}
     87   1.9     isaki 	if (b > 7)
     88   1.9     isaki 		b = 7;
     89   1.9     isaki 	s |= b;
     90   1.9     isaki 	mc->mc_amp += (short)(adpcm_estimindex[(int)s] * dl);
     91   1.9     isaki 	estim += adpcm_estimstep[b];
     92   1.9     isaki 	if (estim < 0)
     93   1.9     isaki 		estim = 0;
     94   1.9     isaki 	else if (estim > 48)
     95   1.9     isaki 		estim = 48;
     96   1.9     isaki 
     97   1.9     isaki 	mc->mc_estim = estim;
     98   1.9     isaki 	return s;
     99   1.9     isaki }
    100   1.9     isaki 
    101  1.26     isaki void
    102  1.26     isaki msm6258_internal_to_adpcm(audio_filter_arg_t *arg)
    103  1.12      kent {
    104  1.12      kent 	struct msm6258_codecvar *mc;
    105  1.26     isaki 	const aint_t *src;
    106  1.26     isaki 	uint8_t *dst;
    107  1.26     isaki 	u_int sample_count;
    108  1.26     isaki 	u_int i;
    109  1.26     isaki 
    110  1.26     isaki 	KASSERT((arg->count & 1) == 0);
    111  1.26     isaki 
    112  1.26     isaki 	mc = arg->context;
    113  1.26     isaki 	src = arg->src;
    114  1.26     isaki 	dst = arg->dst;
    115  1.26     isaki 	sample_count = arg->count * arg->srcfmt->channels;
    116  1.26     isaki 	for (i = 0; i < sample_count / 2; i++) {
    117  1.26     isaki 		aint_t s;
    118  1.26     isaki 		uint8_t f;
    119  1.26     isaki 
    120  1.26     isaki 		s = *src++;
    121  1.26     isaki 		s >>= AUDIO_INTERNAL_BITS - 16;
    122  1.26     isaki 		f = pcm2adpcm_step(mc, s);
    123  1.26     isaki 
    124  1.26     isaki 		s = *src++;
    125  1.26     isaki 		s >>= AUDIO_INTERNAL_BITS - 16;
    126  1.26     isaki 		f |= pcm2adpcm_step(mc, s) << 4;
    127  1.26     isaki 
    128  1.26     isaki 		*dst++ = (uint8_t)f;
    129  1.18     isaki 	}
    130   1.9     isaki }
    131   1.1   minoura 
    132   1.1   minoura 
    133   1.9     isaki /*
    134   1.9     isaki  * OkiADPCM -> signed 16bit linear PCM
    135   1.9     isaki  */
    136  1.15     perry static inline int16_t
    137  1.12      kent adpcm2pcm_step(struct msm6258_codecvar *mc, uint8_t b)
    138   1.1   minoura {
    139   1.9     isaki 	int estim = (int)mc->mc_estim;
    140   1.7     isaki 
    141   1.9     isaki 	mc->mc_amp += adpcm_estim[estim] * adpcm_estimindex[b];
    142   1.9     isaki 	estim += adpcm_estimstep[b];
    143   1.7     isaki 
    144   1.7     isaki 	if (estim < 0)
    145   1.7     isaki 		estim = 0;
    146   1.9     isaki 	else if (estim > 48)
    147   1.7     isaki 		estim = 48;
    148   1.9     isaki 
    149   1.9     isaki 	mc->mc_estim = estim;
    150   1.9     isaki 
    151   1.9     isaki 	return mc->mc_amp;
    152   1.1   minoura }
    153   1.1   minoura 
    154  1.26     isaki void
    155  1.26     isaki msm6258_adpcm_to_internal(audio_filter_arg_t *arg)
    156   1.9     isaki {
    157  1.12      kent 	struct msm6258_codecvar *mc;
    158  1.26     isaki 	const uint8_t *src;
    159  1.26     isaki 	aint_t *dst;
    160  1.26     isaki 	u_int sample_count;
    161  1.26     isaki 	u_int i;
    162  1.26     isaki 
    163  1.26     isaki 	KASSERT((arg->count & 1) == 0);
    164  1.26     isaki 
    165  1.26     isaki 	mc = arg->context;
    166  1.26     isaki 	src = arg->src;
    167  1.26     isaki 	dst = arg->dst;
    168  1.26     isaki 	sample_count = arg->count * arg->srcfmt->channels;
    169  1.26     isaki 	for (i = 0; i < sample_count / 2; i++) {
    170  1.26     isaki 		uint8_t a = *src++;
    171  1.26     isaki 		aint_t s;
    172  1.26     isaki 
    173  1.26     isaki 		s = adpcm2pcm_step(mc, a & 0x0f);
    174  1.26     isaki 		s <<= AUDIO_INTERNAL_BITS - 16;
    175  1.26     isaki 		*dst++ = s;
    176  1.26     isaki 
    177  1.26     isaki 		s = adpcm2pcm_step(mc, a >> 4);
    178  1.26     isaki 		s <<= AUDIO_INTERNAL_BITS - 16;
    179  1.26     isaki 		*dst++ = s;
    180  1.18     isaki 	}
    181   1.1   minoura }
    182