Home | History | Annotate | Line # | Download | only in ic
msm6258.c revision 1.24.4.1
      1  1.24.4.1  christos /*	$NetBSD: msm6258.c,v 1.24.4.1 2019/06/10 22:07:10 christos 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.24.4.1  christos __KERNEL_RCSID(0, "$NetBSD: msm6258.c,v 1.24.4.1 2019/06/10 22:07:10 christos 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.24.4.1  christos #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.24.4.1  christos void
    102  1.24.4.1  christos msm6258_internal_to_adpcm(audio_filter_arg_t *arg)
    103      1.12      kent {
    104      1.12      kent 	struct msm6258_codecvar *mc;
    105  1.24.4.1  christos 	const aint_t *src;
    106  1.24.4.1  christos 	uint8_t *dst;
    107  1.24.4.1  christos 	u_int sample_count;
    108  1.24.4.1  christos 	u_int i;
    109  1.24.4.1  christos 
    110  1.24.4.1  christos 	KASSERT((arg->count & 1) == 0);
    111  1.24.4.1  christos 
    112  1.24.4.1  christos 	mc = arg->context;
    113  1.24.4.1  christos 	src = arg->src;
    114  1.24.4.1  christos 	dst = arg->dst;
    115  1.24.4.1  christos 	sample_count = arg->count * arg->srcfmt->channels;
    116  1.24.4.1  christos 	for (i = 0; i < sample_count / 2; i++) {
    117  1.24.4.1  christos 		aint_t s;
    118  1.24.4.1  christos 		uint8_t f;
    119  1.24.4.1  christos 
    120  1.24.4.1  christos 		s = *src++;
    121  1.24.4.1  christos 		s >>= AUDIO_INTERNAL_BITS - 16;
    122  1.24.4.1  christos 		f = pcm2adpcm_step(mc, s);
    123  1.24.4.1  christos 
    124  1.24.4.1  christos 		s = *src++;
    125  1.24.4.1  christos 		s >>= AUDIO_INTERNAL_BITS - 16;
    126  1.24.4.1  christos 		f |= pcm2adpcm_step(mc, s) << 4;
    127       1.1   minoura 
    128  1.24.4.1  christos 		*dst++ = (uint8_t)f;
    129      1.18     isaki 	}
    130       1.1   minoura }
    131       1.1   minoura 
    132  1.24.4.1  christos 
    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.24.4.1  christos void
    155  1.24.4.1  christos msm6258_adpcm_to_internal(audio_filter_arg_t *arg)
    156       1.9     isaki {
    157      1.12      kent 	struct msm6258_codecvar *mc;
    158  1.24.4.1  christos 	const uint8_t *src;
    159  1.24.4.1  christos 	aint_t *dst;
    160  1.24.4.1  christos 	u_int sample_count;
    161  1.24.4.1  christos 	u_int i;
    162  1.24.4.1  christos 
    163  1.24.4.1  christos 	KASSERT((arg->count & 1) == 0);
    164  1.24.4.1  christos 
    165  1.24.4.1  christos 	mc = arg->context;
    166  1.24.4.1  christos 	src = arg->src;
    167  1.24.4.1  christos 	dst = arg->dst;
    168  1.24.4.1  christos 	sample_count = arg->count * arg->srcfmt->channels;
    169  1.24.4.1  christos 	for (i = 0; i < sample_count / 2; i++) {
    170  1.24.4.1  christos 		uint8_t a = *src++;
    171  1.24.4.1  christos 		aint_t s;
    172  1.24.4.1  christos 
    173  1.24.4.1  christos 		s = adpcm2pcm_step(mc, a & 0x0f);
    174  1.24.4.1  christos 		s <<= AUDIO_INTERNAL_BITS - 16;
    175  1.24.4.1  christos 		*dst++ = s;
    176  1.24.4.1  christos 
    177  1.24.4.1  christos 		s = adpcm2pcm_step(mc, a >> 4);
    178  1.24.4.1  christos 		s <<= AUDIO_INTERNAL_BITS - 16;
    179  1.24.4.1  christos 		*dst++ = s;
    180      1.18     isaki 	}
    181       1.1   minoura }
    182