From 0fd039053c5d6d1311da097ba23a127f84513006 Mon Sep 17 00:00:00 2001 From: Mirko Vogt Date: Tue, 18 Aug 2009 17:37:39 +0200 Subject: [PATCH] purge out OSS stuff as it's obsolete, does not compile and isn't worth the time fixing it --- .../files-2.6.27/sound/oss/ac97_codec.c | 1206 ------- .../xburst/files-2.6.27/sound/oss/ak4642en.c | 712 ---- .../xburst/files-2.6.27/sound/oss/jz_ac97.c | 2252 ------------- .../xburst/files-2.6.27/sound/oss/jz_i2s.c | 2908 ----------------- .../sound/oss/jz_pcm_tlv320aic1106_dma.c | 1839 ----------- .../xburst/files-2.6.27/sound/oss/jzcodec.c | 443 --- .../xburst/files-2.6.27/sound/oss/jzdlv.c | 644 ---- .../xburst/files-2.6.27/sound/oss/jzdlv.h | 21 - .../patches-2.6.27/001-ingenic-patchset.patch | 107 - 9 files changed, 10132 deletions(-) delete mode 100755 target/linux/xburst/files-2.6.27/sound/oss/ac97_codec.c delete mode 100755 target/linux/xburst/files-2.6.27/sound/oss/ak4642en.c delete mode 100755 target/linux/xburst/files-2.6.27/sound/oss/jz_ac97.c delete mode 100755 target/linux/xburst/files-2.6.27/sound/oss/jz_i2s.c delete mode 100644 target/linux/xburst/files-2.6.27/sound/oss/jz_pcm_tlv320aic1106_dma.c delete mode 100755 target/linux/xburst/files-2.6.27/sound/oss/jzcodec.c delete mode 100755 target/linux/xburst/files-2.6.27/sound/oss/jzdlv.c delete mode 100755 target/linux/xburst/files-2.6.27/sound/oss/jzdlv.h diff --git a/target/linux/xburst/files-2.6.27/sound/oss/ac97_codec.c b/target/linux/xburst/files-2.6.27/sound/oss/ac97_codec.c deleted file mode 100755 index b63839e8f..000000000 --- a/target/linux/xburst/files-2.6.27/sound/oss/ac97_codec.c +++ /dev/null @@ -1,1206 +0,0 @@ -/* - * ac97_codec.c: Generic AC97 mixer/modem module - * - * Derived from ac97 mixer in maestro and trident driver. - * - * Copyright 2000 Silicon Integrated System Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ************************************************************************** - * - * The Intel Audio Codec '97 specification is available at the Intel - * audio homepage: http://developer.intel.com/ial/scalableplatforms/audio/ - * - * The specification itself is currently available at: - * ftp://download.intel.com/ial/scalableplatforms/ac97r22.pdf - * - ************************************************************************** - * - * History - * May 02, 2003 Liam Girdwood - * Removed non existant WM9700 - * Added support for WM9705, WM9708, WM9709, WM9710, WM9711 - * WM9712 and WM9717 - * Mar 28, 2002 Randolph Bentson - * corrections to support WM9707 in ViewPad 1000 - * v0.4 Mar 15 2000 Ollie Lho - * dual codecs support verified with 4 channels output - * v0.3 Feb 22 2000 Ollie Lho - * bug fix for record mask setting - * v0.2 Feb 10 2000 Ollie Lho - * add ac97_read_proc for /proc/driver/{vendor}/ac97 - * v0.1 Jan 14 2000 Ollie Lho - * Isolated from trident.c to support multiple ac97 codec - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CODEC_ID_BUFSZ 14 - -static int ac97_read_mixer(struct ac97_codec *codec, int oss_channel); -static void ac97_write_mixer(struct ac97_codec *codec, int oss_channel, - unsigned int left, unsigned int right); -static void ac97_set_mixer(struct ac97_codec *codec, unsigned int oss_mixer, unsigned int val ); -static int ac97_recmask_io(struct ac97_codec *codec, int rw, int mask); -static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned long arg); - -static int ac97_init_mixer(struct ac97_codec *codec); - -static int wolfson_init03(struct ac97_codec * codec); -static int wolfson_init04(struct ac97_codec * codec); -static int wolfson_init05(struct ac97_codec * codec); -static int wolfson_init11(struct ac97_codec * codec); -static int wolfson_init13(struct ac97_codec * codec); -static int tritech_init(struct ac97_codec * codec); -static int tritech_maestro_init(struct ac97_codec * codec); -static int sigmatel_9708_init(struct ac97_codec *codec); -static int sigmatel_9721_init(struct ac97_codec *codec); -static int sigmatel_9744_init(struct ac97_codec *codec); -static int ad1886_init(struct ac97_codec *codec); -static int eapd_control(struct ac97_codec *codec, int); -static int crystal_digital_control(struct ac97_codec *codec, int slots, int rate, int mode); -static int cmedia_init(struct ac97_codec * codec); -static int cmedia_digital_control(struct ac97_codec *codec, int slots, int rate, int mode); -static int generic_digital_control(struct ac97_codec *codec, int slots, int rate, int mode); - - -/* - * AC97 operations. - * - * If you are adding a codec then you should be able to use - * eapd_ops - any codec that supports EAPD amp control (most) - * null_ops - any ancient codec that supports nothing - * - * The three functions are - * init - used for non AC97 standard initialisation - * amplifier - used to do amplifier control (1=on 0=off) - * digital - switch to digital modes (0 = analog) - * - * Not all codecs support all features, not all drivers use all the - * operations yet - */ - -static struct ac97_ops null_ops = { NULL, NULL, NULL }; -static struct ac97_ops default_ops = { NULL, eapd_control, NULL }; -static struct ac97_ops default_digital_ops = { NULL, eapd_control, generic_digital_control}; -static struct ac97_ops wolfson_ops03 = { wolfson_init03, NULL, NULL }; -static struct ac97_ops wolfson_ops04 = { wolfson_init04, NULL, NULL }; -static struct ac97_ops wolfson_ops05 = { wolfson_init05, NULL, NULL }; -static struct ac97_ops wolfson_ops11 = { wolfson_init11, NULL, NULL }; -static struct ac97_ops wolfson_ops13 = { wolfson_init13, NULL, NULL }; -static struct ac97_ops tritech_ops = { tritech_init, NULL, NULL }; -static struct ac97_ops tritech_m_ops = { tritech_maestro_init, NULL, NULL }; -static struct ac97_ops sigmatel_9708_ops = { sigmatel_9708_init, NULL, NULL }; -static struct ac97_ops sigmatel_9721_ops = { sigmatel_9721_init, NULL, NULL }; -static struct ac97_ops sigmatel_9744_ops = { sigmatel_9744_init, NULL, NULL }; -static struct ac97_ops crystal_digital_ops = { NULL, eapd_control, crystal_digital_control }; -static struct ac97_ops ad1886_ops = { ad1886_init, eapd_control, NULL }; -static struct ac97_ops cmedia_ops = { NULL, eapd_control, NULL}; -static struct ac97_ops cmedia_digital_ops = { cmedia_init, eapd_control, cmedia_digital_control}; - -/* sorted by vendor/device id */ -static const struct { - u32 id; - char *name; - struct ac97_ops *ops; - int flags; -} ac97_codec_ids[] = { - {0x41445303, "Analog Devices AD1819", &null_ops}, - {0x41445340, "Analog Devices AD1881", &null_ops}, - {0x41445348, "Analog Devices AD1881A", &null_ops}, - {0x41445360, "Analog Devices AD1885", &default_ops}, - {0x41445361, "Analog Devices AD1886", &ad1886_ops}, - {0x41445370, "Analog Devices AD1981", &null_ops}, - {0x41445372, "Analog Devices AD1981A", &null_ops}, - {0x41445374, "Analog Devices AD1981B", &null_ops}, - {0x41445460, "Analog Devices AD1885", &default_ops}, - {0x41445461, "Analog Devices AD1886", &ad1886_ops}, - {0x414B4D00, "Asahi Kasei AK4540", &null_ops}, - {0x414B4D01, "Asahi Kasei AK4542", &null_ops}, - {0x414B4D02, "Asahi Kasei AK4543", &null_ops}, - {0x414C4326, "ALC100P", &null_ops}, - {0x414C4710, "ALC200/200P", &null_ops}, - {0x414C4720, "ALC650", &default_digital_ops}, - {0x434D4941, "CMedia", &cmedia_ops, AC97_NO_PCM_VOLUME }, - {0x434D4942, "CMedia", &cmedia_ops, AC97_NO_PCM_VOLUME }, - {0x434D4961, "CMedia", &cmedia_digital_ops, AC97_NO_PCM_VOLUME }, - {0x43525900, "Cirrus Logic CS4297", &default_ops}, - {0x43525903, "Cirrus Logic CS4297", &default_ops}, - {0x43525913, "Cirrus Logic CS4297A rev A", &default_ops}, - {0x43525914, "Cirrus Logic CS4297A rev B", &default_ops}, - {0x43525923, "Cirrus Logic CS4298", &null_ops}, - {0x4352592B, "Cirrus Logic CS4294", &null_ops}, - {0x4352592D, "Cirrus Logic CS4294", &null_ops}, - {0x43525931, "Cirrus Logic CS4299 rev A", &crystal_digital_ops}, - {0x43525933, "Cirrus Logic CS4299 rev C", &crystal_digital_ops}, - {0x43525934, "Cirrus Logic CS4299 rev D", &crystal_digital_ops}, - {0x43585430, "CXT48", &default_ops, AC97_DELUDED_MODEM }, - {0x43585442, "CXT66", &default_ops, AC97_DELUDED_MODEM }, - {0x44543031, "Diamond Technology DT0893", &default_ops}, - {0x45838308, "ESS Allegro ES1988", &null_ops}, - {0x49434511, "ICE1232", &null_ops}, /* I hope --jk */ - {0x4e534331, "National Semiconductor LM4549", &null_ops}, - {0x53494c22, "Silicon Laboratory Si3036", &null_ops}, - {0x53494c23, "Silicon Laboratory Si3038", &null_ops}, - {0x545200FF, "TriTech TR?????", &tritech_m_ops}, - {0x54524102, "TriTech TR28022", &null_ops}, - {0x54524103, "TriTech TR28023", &null_ops}, - {0x54524106, "TriTech TR28026", &null_ops}, - {0x54524108, "TriTech TR28028", &tritech_ops}, - {0x54524123, "TriTech TR A5", &null_ops}, - {0x574D4C03, "Wolfson WM9703/07/08/17", &wolfson_ops03}, - {0x574D4C04, "Wolfson WM9704M/WM9704Q", &wolfson_ops04}, - {0x574D4C05, "Wolfson WM9705/WM9710", &wolfson_ops05}, - {0x574D4C09, "Wolfson WM9709", &null_ops}, - {0x574D4C12, "Wolfson WM9711/9712", &wolfson_ops11}, - {0x574D4C13, "Wolfson WM9713", &wolfson_ops13, AC97_DEFAULT_POWER_OFF}, - {0x83847600, "SigmaTel STAC????", &null_ops}, - {0x83847604, "SigmaTel STAC9701/3/4/5", &null_ops}, - {0x83847605, "SigmaTel STAC9704", &null_ops}, - {0x83847608, "SigmaTel STAC9708", &sigmatel_9708_ops}, - {0x83847609, "SigmaTel STAC9721/23", &sigmatel_9721_ops}, - {0x83847644, "SigmaTel STAC9744/45", &sigmatel_9744_ops}, - {0x83847652, "SigmaTel STAC9752/53", &default_ops}, - {0x83847656, "SigmaTel STAC9756/57", &sigmatel_9744_ops}, - {0x83847666, "SigmaTel STAC9750T", &sigmatel_9744_ops}, - {0x83847684, "SigmaTel STAC9783/84?", &null_ops}, - {0x57454301, "Winbond 83971D", &null_ops}, -}; - -/* this table has default mixer values for all OSS mixers. */ -static struct mixer_defaults { - int mixer; - unsigned int value; -} mixer_defaults[SOUND_MIXER_NRDEVICES] = { - /* all values 0 -> 100 in bytes */ - {SOUND_MIXER_VOLUME, 0x4343}, - {SOUND_MIXER_BASS, 0x4343}, - {SOUND_MIXER_TREBLE, 0x4343}, - {SOUND_MIXER_PCM, 0x4343}, - {SOUND_MIXER_SPEAKER, 0x4343}, - {SOUND_MIXER_LINE, 0x4343}, - {SOUND_MIXER_MIC, 0x0000}, - {SOUND_MIXER_CD, 0x4343}, - {SOUND_MIXER_ALTPCM, 0x4343}, - {SOUND_MIXER_IGAIN, 0x4343}, - {SOUND_MIXER_LINE1, 0x4343}, - {SOUND_MIXER_PHONEIN, 0x4343}, - {SOUND_MIXER_PHONEOUT, 0x4343}, - {SOUND_MIXER_VIDEO, 0x4343}, - {-1,0} -}; - -/* table to scale scale from OSS mixer value to AC97 mixer register value */ -static struct ac97_mixer_hw { - unsigned char offset; - int scale; -} ac97_hw[SOUND_MIXER_NRDEVICES]= { - [SOUND_MIXER_VOLUME] = {AC97_MASTER_VOL_STEREO,64}, - [SOUND_MIXER_BASS] = {AC97_MASTER_TONE, 16}, - [SOUND_MIXER_TREBLE] = {AC97_MASTER_TONE, 16}, - [SOUND_MIXER_PCM] = {AC97_PCMOUT_VOL, 32}, - [SOUND_MIXER_SPEAKER] = {AC97_PCBEEP_VOL, 16}, - [SOUND_MIXER_LINE] = {AC97_LINEIN_VOL, 32}, - [SOUND_MIXER_MIC] = {AC97_MIC_VOL, 32}, - [SOUND_MIXER_CD] = {AC97_CD_VOL, 32}, - [SOUND_MIXER_ALTPCM] = {AC97_HEADPHONE_VOL, 64}, - [SOUND_MIXER_IGAIN] = {AC97_RECORD_GAIN, 16}, - [SOUND_MIXER_LINE1] = {AC97_AUX_VOL, 32}, - [SOUND_MIXER_PHONEIN] = {AC97_PHONE_VOL, 32}, - [SOUND_MIXER_PHONEOUT] = {AC97_MASTER_VOL_MONO, 64}, - [SOUND_MIXER_VIDEO] = {AC97_VIDEO_VOL, 32}, -}; - -/* the following tables allow us to go from OSS <-> ac97 quickly. */ -enum ac97_recsettings { - AC97_REC_MIC=0, - AC97_REC_CD, - AC97_REC_VIDEO, - AC97_REC_AUX, - AC97_REC_LINE, - AC97_REC_STEREO, /* combination of all enabled outputs.. */ - AC97_REC_MONO, /*.. or the mono equivalent */ - AC97_REC_PHONE -}; - -static const unsigned int ac97_rm2oss[] = { - [AC97_REC_MIC] = SOUND_MIXER_MIC, - [AC97_REC_CD] = SOUND_MIXER_CD, - [AC97_REC_VIDEO] = SOUND_MIXER_VIDEO, - [AC97_REC_AUX] = SOUND_MIXER_LINE1, - [AC97_REC_LINE] = SOUND_MIXER_LINE, - [AC97_REC_STEREO]= SOUND_MIXER_IGAIN, - [AC97_REC_PHONE] = SOUND_MIXER_PHONEIN -}; - -/* indexed by bit position */ -static const unsigned int ac97_oss_rm[] = { - [SOUND_MIXER_MIC] = AC97_REC_MIC, - [SOUND_MIXER_CD] = AC97_REC_CD, - [SOUND_MIXER_VIDEO] = AC97_REC_VIDEO, - [SOUND_MIXER_LINE1] = AC97_REC_AUX, - [SOUND_MIXER_LINE] = AC97_REC_LINE, - [SOUND_MIXER_IGAIN] = AC97_REC_STEREO, - [SOUND_MIXER_PHONEIN] = AC97_REC_PHONE -}; - -static LIST_HEAD(codecs); -static LIST_HEAD(codec_drivers); -static DEFINE_MUTEX(codec_mutex); - -/* reads the given OSS mixer from the ac97 the caller must have insured that the ac97 knows - about that given mixer, and should be holding a spinlock for the card */ -static int ac97_read_mixer(struct ac97_codec *codec, int oss_channel) -{ - u16 val; - int ret = 0; - int scale; - struct ac97_mixer_hw *mh = &ac97_hw[oss_channel]; - - val = codec->codec_read(codec , mh->offset); - - if (val & AC97_MUTE) { - ret = 0; - } else if (AC97_STEREO_MASK & (1 << oss_channel)) { - /* nice stereo mixers .. */ - int left,right; - - left = (val >> 8) & 0x7f; - right = val & 0x7f; - - if (oss_channel == SOUND_MIXER_IGAIN) { - right = (right * 100) / mh->scale; - left = (left * 100) / mh->scale; - } else { - /* these may have 5 or 6 bit resolution */ - if(oss_channel == SOUND_MIXER_VOLUME || oss_channel == SOUND_MIXER_ALTPCM) - scale = (1 << codec->bit_resolution); - else - scale = mh->scale; - - right = 100 - ((right * 100) / scale); - left = 100 - ((left * 100) / scale); - } - ret = left | (right << 8); - } else if (oss_channel == SOUND_MIXER_SPEAKER) { - ret = 100 - ((((val & 0x1e)>>1) * 100) / mh->scale); - } else if (oss_channel == SOUND_MIXER_PHONEIN) { - ret = 100 - (((val & 0x1f) * 100) / mh->scale); - } else if (oss_channel == SOUND_MIXER_PHONEOUT) { - scale = (1 << codec->bit_resolution); - ret = 100 - (((val & 0x1f) * 100) / scale); - } else if (oss_channel == SOUND_MIXER_MIC) { - ret = 100 - (((val & 0x1f) * 100) / mh->scale); - /* the low bit is optional in the tone sliders and masking - it lets us avoid the 0xf 'bypass'.. */ - } else if (oss_channel == SOUND_MIXER_BASS) { - ret = 100 - ((((val >> 8) & 0xe) * 100) / mh->scale); - } else if (oss_channel == SOUND_MIXER_TREBLE) { - ret = 100 - (((val & 0xe) * 100) / mh->scale); - } - -#ifdef DEBUG - printk("ac97_codec: read OSS mixer %2d (%s ac97 register 0x%02x), " - "0x%04x -> 0x%04x\n", - oss_channel, codec->id ? "Secondary" : "Primary", - mh->offset, val, ret); -#endif - - return ret; -} - -/* write the OSS encoded volume to the given OSS encoded mixer, again caller's job to - make sure all is well in arg land, call with spinlock held */ -static void ac97_write_mixer(struct ac97_codec *codec, int oss_channel, - unsigned int left, unsigned int right) -{ - u16 val = 0; - int scale; - struct ac97_mixer_hw *mh = &ac97_hw[oss_channel]; - -#ifdef DEBUG - printk("ac97_codec: wrote OSS mixer %2d (%s ac97 register 0x%02x), " - "left vol:%2d, right vol:%2d:", - oss_channel, codec->id ? "Secondary" : "Primary", - mh->offset, left, right); -#endif - - if (AC97_STEREO_MASK & (1 << oss_channel)) { - /* stereo mixers */ - if (left == 0 && right == 0) { - val = AC97_MUTE; - } else { - if (oss_channel == SOUND_MIXER_IGAIN) { - right = (right * mh->scale) / 100; - left = (left * mh->scale) / 100; - if (right >= mh->scale) - right = mh->scale-1; - if (left >= mh->scale) - left = mh->scale-1; - } else { - /* these may have 5 or 6 bit resolution */ - if (oss_channel == SOUND_MIXER_VOLUME || - oss_channel == SOUND_MIXER_ALTPCM) - scale = (1 << codec->bit_resolution); - else - scale = mh->scale; - - right = ((100 - right) * scale) / 100; - left = ((100 - left) * scale) / 100; - if (right >= scale) - right = scale-1; - if (left >= scale) - left = scale-1; - } - val = (left << 8) | right; - } - } else if (oss_channel == SOUND_MIXER_BASS) { - val = codec->codec_read(codec , mh->offset) & ~0x0f00; - left = ((100 - left) * mh->scale) / 100; - if (left >= mh->scale) - left = mh->scale-1; - val |= (left << 8) & 0x0e00; - } else if (oss_channel == SOUND_MIXER_TREBLE) { - val = codec->codec_read(codec , mh->offset) & ~0x000f; - left = ((100 - left) * mh->scale) / 100; - if (left >= mh->scale) - left = mh->scale-1; - val |= left & 0x000e; - } else if(left == 0) { - val = AC97_MUTE; - } else if (oss_channel == SOUND_MIXER_SPEAKER) { - left = ((100 - left) * mh->scale) / 100; - if (left >= mh->scale) - left = mh->scale-1; - val = left << 1; - } else if (oss_channel == SOUND_MIXER_PHONEIN) { - left = ((100 - left) * mh->scale) / 100; - if (left >= mh->scale) - left = mh->scale-1; - val = left; - } else if (oss_channel == SOUND_MIXER_PHONEOUT) { - scale = (1 << codec->bit_resolution); - left = ((100 - left) * scale) / 100; - if (left >= mh->scale) - left = mh->scale-1; - val = left; - } else if (oss_channel == SOUND_MIXER_MIC) { - val = codec->codec_read(codec , mh->offset) & ~0x801f; - left = ((100 - left) * mh->scale) / 100; - if (left >= mh->scale) - left = mh->scale-1; - val |= left; - /* the low bit is optional in the tone sliders and masking - it lets us avoid the 0xf 'bypass'.. */ - } -#ifdef DEBUG - printk(" 0x%04x", val); -#endif - - codec->codec_write(codec, mh->offset, val); - -#ifdef DEBUG - val = codec->codec_read(codec, mh->offset); - printk(" -> 0x%04x\n", val); -#endif -} - -/* a thin wrapper for write_mixer */ -static void ac97_set_mixer(struct ac97_codec *codec, unsigned int oss_mixer, unsigned int val ) -{ - unsigned int left,right; - - /* cleanse input a little */ - right = ((val >> 8) & 0xff) ; - left = (val & 0xff) ; - - if (right > 100) right = 100; - if (left > 100) left = 100; - - codec->mixer_state[oss_mixer] = (right << 8) | left; - codec->write_mixer(codec, oss_mixer, left, right); -} - -/* read or write the recmask, the ac97 can really have left and right recording - inputs independantly set, but OSS doesn't seem to want us to express that to - the user. the caller guarantees that we have a supported bit set, and they - must be holding the card's spinlock */ -static int ac97_recmask_io(struct ac97_codec *codec, int rw, int mask) -{ - unsigned int val; - - if (rw) { - /* read it from the card */ - val = codec->codec_read(codec, AC97_RECORD_SELECT); -#ifdef DEBUG - printk("ac97_codec: ac97 recmask to set to 0x%04x\n", val); -#endif - return (1 << ac97_rm2oss[val & 0x07]); - } - - /* else, write the first set in the mask as the - output */ - /* clear out current set value first (AC97 supports only 1 input!) */ - val = (1 << ac97_rm2oss[codec->codec_read(codec, AC97_RECORD_SELECT) & 0x07]); - if (mask != val) - mask &= ~val; - - val = ffs(mask); - val = ac97_oss_rm[val-1]; - val |= val << 8; /* set both channels */ - -#ifdef DEBUG - printk("ac97_codec: setting ac97 recmask to 0x%04x\n", val); -#endif - - codec->codec_write(codec, AC97_RECORD_SELECT, val); - - return 0; -}; - -static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned long arg) -{ - int i, val = 0; - - if (cmd == SOUND_MIXER_INFO) { - mixer_info info; - memset(&info, 0, sizeof(info)); - strlcpy(info.id, codec->name, sizeof(info.id)); - strlcpy(info.name, codec->name, sizeof(info.name)); - info.modify_counter = codec->modcnt; - if (copy_to_user((void __user *)arg, &info, sizeof(info))) - return -EFAULT; - return 0; - } - if (cmd == SOUND_OLD_MIXER_INFO) { - _old_mixer_info info; - memset(&info, 0, sizeof(info)); - strlcpy(info.id, codec->name, sizeof(info.id)); - strlcpy(info.name, codec->name, sizeof(info.name)); - if (copy_to_user((void __user *)arg, &info, sizeof(info))) - return -EFAULT; - return 0; - } - - if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int)) - return -EINVAL; - - if (cmd == OSS_GETVERSION) - return put_user(SOUND_VERSION, (int __user *)arg); - - if (_SIOC_DIR(cmd) == _SIOC_READ) { - switch (_IOC_NR(cmd)) { - case SOUND_MIXER_RECSRC: /* give them the current record source */ - if (!codec->recmask_io) { - val = 0; - } else { - val = codec->recmask_io(codec, 1, 0); - } - break; - - case SOUND_MIXER_DEVMASK: /* give them the supported mixers */ - val = codec->supported_mixers; - break; - - case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */ - val = codec->record_sources; - break; - - case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */ - val = codec->stereo_mixers; - break; - - case SOUND_MIXER_CAPS: - val = SOUND_CAP_EXCL_INPUT; - break; - - default: /* read a specific mixer */ - i = _IOC_NR(cmd); - - if (!supported_mixer(codec, i)) - return -EINVAL; - - /* do we ever want to touch the hardware? */ - /* val = codec->read_mixer(codec, i); */ - val = codec->mixer_state[i]; - break; - } - return put_user(val, (int __user *)arg); - } - - if (_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) { - codec->modcnt++; - if (get_user(val, (int __user *)arg)) - return -EFAULT; - - switch (_IOC_NR(cmd)) { - case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ - if (!codec->recmask_io) return -EINVAL; - if (!val) return 0; - if (!(val &= codec->record_sources)) return -EINVAL; - - codec->recmask_io(codec, 0, val); - - return 0; - default: /* write a specific mixer */ - i = _IOC_NR(cmd); - - if (!supported_mixer(codec, i)) - return -EINVAL; - - ac97_set_mixer(codec, i, val); - - return 0; - } - } - return -EINVAL; -} - -/** - * codec_id - Turn id1/id2 into a PnP string - * @id1: Vendor ID1 - * @id2: Vendor ID2 - * @buf: CODEC_ID_BUFSZ byte buffer - * - * Fills buf with a zero terminated PnP ident string for the id1/id2 - * pair. For convenience the return is the passed in buffer pointer. - */ - -static char *codec_id(u16 id1, u16 id2, char *buf) -{ - if(id1&0x8080) { - snprintf(buf, CODEC_ID_BUFSZ, "0x%04x:0x%04x", id1, id2); - } else { - buf[0] = (id1 >> 8); - buf[1] = (id1 & 0xFF); - buf[2] = (id2 >> 8); - snprintf(buf+3, CODEC_ID_BUFSZ - 3, "%d", id2&0xFF); - } - return buf; -} - -/** - * ac97_check_modem - Check if the Codec is a modem - * @codec: codec to check - * - * Return true if the device is an AC97 1.0 or AC97 2.0 modem - */ - -static int ac97_check_modem(struct ac97_codec *codec) -{ - /* Check for an AC97 1.0 soft modem (ID1) */ - if(codec->codec_read(codec, AC97_RESET) & 2) - return 1; - /* Check for an AC97 2.x soft modem */ - codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0L); - if(codec->codec_read(codec, AC97_EXTENDED_MODEM_ID) & 1) - return 1; - return 0; -} - - -/** - * ac97_alloc_codec - Allocate an AC97 codec - * - * Returns a new AC97 codec structure. AC97 codecs may become - * refcounted soon so this interface is needed. Returns with - * one reference taken. - */ - -struct ac97_codec *ac97_alloc_codec(void) -{ - struct ac97_codec *codec = kzalloc(sizeof(struct ac97_codec), GFP_KERNEL); - if(!codec) - return NULL; - - spin_lock_init(&codec->lock); - INIT_LIST_HEAD(&codec->list); - return codec; -} - -EXPORT_SYMBOL(ac97_alloc_codec); - -/** - * ac97_release_codec - Release an AC97 codec - * @codec: codec to release - * - * Release an allocated AC97 codec. This will be refcounted in - * time but for the moment is trivial. Calls the unregister - * handler if the codec is now defunct. - */ - -void ac97_release_codec(struct ac97_codec *codec) -{ - /* Remove from the list first, we don't want to be - "rediscovered" */ - mutex_lock(&codec_mutex); - list_del(&codec->list); - mutex_unlock(&codec_mutex); - /* - * The driver needs to deal with internal - * locking to avoid accidents here. - */ - if(codec->driver) - codec->driver->remove(codec, codec->driver); - kfree(codec); -} - -EXPORT_SYMBOL(ac97_release_codec); - -/** - * ac97_probe_codec - Initialize and setup AC97-compatible codec - * @codec: (in/out) Kernel info for a single AC97 codec - * - * Reset the AC97 codec, then initialize the mixer and - * the rest of the @codec structure. - * - * The codec_read and codec_write fields of @codec are - * required to be setup and working when this function - * is called. All other fields are set by this function. - * - * codec_wait field of @codec can optionally be provided - * when calling this function. If codec_wait is not %NULL, - * this function will call codec_wait any time it is - * necessary to wait for the audio chip to reach the - * codec-ready state. If codec_wait is %NULL, then - * the default behavior is to call schedule_timeout. - * Currently codec_wait is used to wait for AC97 codec - * reset to complete. - * - * Some codecs will power down when a register reset is - * performed. We now check for such codecs. - * - * Returns 1 (true) on success, or 0 (false) on failure. - */ - -int ac97_probe_codec(struct ac97_codec *codec) -{ - u16 id1, id2; - u16 audio; - int i; - char cidbuf[CODEC_ID_BUFSZ]; - u16 f; - struct list_head *l; - struct ac97_driver *d; - - /* wait for codec-ready state */ - if (codec->codec_wait) - codec->codec_wait(codec); - else - udelay(10); - - /* will the codec power down if register reset ? */ - id1 = codec->codec_read(codec, AC97_VENDOR_ID1); - id2 = codec->codec_read(codec, AC97_VENDOR_ID2); - codec->name = NULL; - codec->codec_ops = &null_ops; - for (i = 0; i < ARRAY_SIZE(ac97_codec_ids); i++) { - if (ac97_codec_ids[i].id == ((id1 << 16) | id2)) { - codec->type = ac97_codec_ids[i].id; - codec->name = ac97_codec_ids[i].name; - codec->codec_ops = ac97_codec_ids[i].ops; - codec->flags = ac97_codec_ids[i].flags; - break; - } - } - - codec->model = (id1 << 16) | id2; - if ((codec->flags & AC97_DEFAULT_POWER_OFF) == 0) { - /* reset codec and wait for the ready bit before we continue */ - codec->codec_write(codec, AC97_RESET, 0L); - if (codec->codec_wait) - codec->codec_wait(codec); - else - udelay(10); - } - - /* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should - * be read zero. - * - * FIXME: is the following comment outdated? -jgarzik - * Probing of AC97 in this way is not reliable, it is not even SAFE !! - */ - if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) { - printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n", - (codec->id & 0x2) ? (codec->id&1 ? "4th" : "Tertiary") - : (codec->id&1 ? "Secondary": "Primary")); - return 0; - } - - /* probe for Modem Codec */ - codec->modem = ac97_check_modem(codec); - - /* enable SPDIF */ - f = codec->codec_read(codec, AC97_EXTENDED_STATUS); - if((codec->codec_ops == &null_ops) && (f & 4)) - codec->codec_ops = &default_digital_ops; - - /* A device which thinks its a modem but isnt */ - if(codec->flags & AC97_DELUDED_MODEM) - codec->modem = 0; - - if (codec->name == NULL) - codec->name = "Unknown"; - printk(KERN_INFO "ac97_codec: AC97 %s codec, id: %s (%s)\n", - codec->modem ? "Modem" : (audio ? "Audio" : ""), - codec_id(id1, id2, cidbuf), codec->name); - - if(!ac97_init_mixer(codec)) - return 0; - - /* - * Attach last so the caller can override the mixer - * callbacks. - */ - - mutex_lock(&codec_mutex); - list_add(&codec->list, &codecs); - - list_for_each(l, &codec_drivers) { - d = list_entry(l, struct ac97_driver, list); - if ((codec->model ^ d->codec_id) & d->codec_mask) - continue; - if(d->probe(codec, d) == 0) - { - codec->driver = d; - break; - } - } - - mutex_unlock(&codec_mutex); - return 1; -} - -static int ac97_init_mixer(struct ac97_codec *codec) -{ - u16 cap; - int i; - - cap = codec->codec_read(codec, AC97_RESET); - - /* mixer masks */ - codec->supported_mixers = AC97_SUPPORTED_MASK; - codec->stereo_mixers = AC97_STEREO_MASK; - codec->record_sources = AC97_RECORD_MASK; - if (!(cap & 0x04)) - codec->supported_mixers &= ~(SOUND_MASK_BASS|SOUND_MASK_TREBLE); - if (!(cap & 0x10)) - codec->supported_mixers &= ~SOUND_MASK_ALTPCM; - - - /* detect bit resolution */ - codec->codec_write(codec, AC97_MASTER_VOL_STEREO, 0x2020); - if(codec->codec_read(codec, AC97_MASTER_VOL_STEREO) == 0x2020) - codec->bit_resolution = 6; - else - codec->bit_resolution = 5; - - /* generic OSS to AC97 wrapper */ - codec->read_mixer = ac97_read_mixer; - codec->write_mixer = ac97_write_mixer; - codec->recmask_io = ac97_recmask_io; - codec->mixer_ioctl = ac97_mixer_ioctl; - - /* initialize mixer channel volumes */ - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { - struct mixer_defaults *md = &mixer_defaults[i]; - if (md->mixer == -1) - break; - if (!supported_mixer(codec, md->mixer)) - continue; - ac97_set_mixer(codec, md->mixer, md->value); - } - - /* codec specific initialization for 4-6 channel output or secondary codec stuff */ - if (codec->codec_ops->init != NULL) { - codec->codec_ops->init(codec); - } - - /* - * Volume is MUTE only on this device. We have to initialise - * it but its useless beyond that. - */ - if(codec->flags & AC97_NO_PCM_VOLUME) - { - codec->supported_mixers &= ~SOUND_MASK_PCM; - printk(KERN_WARNING "AC97 codec does not have proper volume support.\n"); - } - return 1; -} - -#define AC97_SIGMATEL_ANALOG 0x6c /* Analog Special */ -#define AC97_SIGMATEL_DAC2INVERT 0x6e -#define AC97_SIGMATEL_BIAS1 0x70 -#define AC97_SIGMATEL_BIAS2 0x72 -#define AC97_SIGMATEL_MULTICHN 0x74 /* Multi-Channel programming */ -#define AC97_SIGMATEL_CIC1 0x76 -#define AC97_SIGMATEL_CIC2 0x78 - - -static int sigmatel_9708_init(struct ac97_codec * codec) -{ - u16 codec72, codec6c; - - codec72 = codec->codec_read(codec, AC97_SIGMATEL_BIAS2) & 0x8000; - codec6c = codec->codec_read(codec, AC97_SIGMATEL_ANALOG); - - if ((codec72==0) && (codec6c==0)) { - codec->codec_write(codec, AC97_SIGMATEL_CIC1, 0xabba); - codec->codec_write(codec, AC97_SIGMATEL_CIC2, 0x1000); - codec->codec_write(codec, AC97_SIGMATEL_BIAS1, 0xabba); - codec->codec_write(codec, AC97_SIGMATEL_BIAS2, 0x0007); - } else if ((codec72==0x8000) && (codec6c==0)) { - codec->codec_write(codec, AC97_SIGMATEL_CIC1, 0xabba); - codec->codec_write(codec, AC97_SIGMATEL_CIC2, 0x1001); - codec->codec_write(codec, AC97_SIGMATEL_DAC2INVERT, 0x0008); - } else if ((codec72==0x8000) && (codec6c==0x0080)) { - /* nothing */ - } - codec->codec_write(codec, AC97_SIGMATEL_MULTICHN, 0x0000); - return 0; -} - - -static int sigmatel_9721_init(struct ac97_codec * codec) -{ - /* Only set up secondary codec */ - if (codec->id == 0) - return 0; - - codec->codec_write(codec, AC97_SURROUND_MASTER, 0L); - - /* initialize SigmaTel STAC9721/23 as secondary codec, decoding AC link - sloc 3,4 = 0x01, slot 7,8 = 0x00, */ - codec->codec_write(codec, AC97_SIGMATEL_MULTICHN, 0x00); - - /* we don't have the crystal when we are on an AMR card, so use - BIT_CLK as our clock source. Write the magic word ABBA and read - back to enable register 0x78 */ - codec->codec_write(codec, AC97_SIGMATEL_CIC1, 0xabba); - codec->codec_read(codec, AC97_SIGMATEL_CIC1); - - /* sync all the clocks*/ - codec->codec_write(codec, AC97_SIGMATEL_CIC2, 0x3802); - - return 0; -} - - -static int sigmatel_9744_init(struct ac97_codec * codec) -{ - // patch for SigmaTel - codec->codec_write(codec, AC97_SIGMATEL_CIC1, 0xabba); - codec->codec_write(codec, AC97_SIGMATEL_CIC2, 0x0000); // is this correct? --jk - codec->codec_write(codec, AC97_SIGMATEL_BIAS1, 0xabba); - codec->codec_write(codec, AC97_SIGMATEL_BIAS2, 0x0002); - codec->codec_write(codec, AC97_SIGMATEL_MULTICHN, 0x0000); - return 0; -} - -static int cmedia_init(struct ac97_codec *codec) -{ - /* Initialise the CMedia 9739 */ - /* - We could set various options here - Register 0x20 bit 0x100 sets mic as center bass - Also do multi_channel_ctrl &=~0x3000 |=0x1000 - - For now we set up the GPIO and PC beep - */ - - u16 v; - - /* MIC */ - codec->codec_write(codec, 0x64, 0x3000); - v = codec->codec_read(codec, 0x64); - v &= ~0x8000; - codec->codec_write(codec, 0x64, v); - codec->codec_write(codec, 0x70, 0x0100); - codec->codec_write(codec, 0x72, 0x0020); - return 0; -} - -#define AC97_WM97XX_FMIXER_VOL 0x72 -#define AC97_WM97XX_RMIXER_VOL 0x74 -#define AC97_WM97XX_TEST 0x5a -#define AC97_WM9704_RPCM_VOL 0x70 -#define AC97_WM9711_OUT3VOL 0x16 - -static int wolfson_init03(struct ac97_codec * codec) -{ - /* this is known to work for the ViewSonic ViewPad 1000 */ - codec->codec_write(codec, AC97_WM97XX_FMIXER_VOL, 0x0808); - codec->codec_write(codec, AC97_GENERAL_PURPOSE, 0x8000); - return 0; -} - -static int wolfson_init04(struct ac97_codec * codec) -{ - codec->codec_write(codec, AC97_WM97XX_FMIXER_VOL, 0x0808); - codec->codec_write(codec, AC97_WM97XX_RMIXER_VOL, 0x0808); - - // patch for DVD noise - codec->codec_write(codec, AC97_WM97XX_TEST, 0x0200); - - // init vol as PCM vol - codec->codec_write(codec, AC97_WM9704_RPCM_VOL, - codec->codec_read(codec, AC97_PCMOUT_VOL)); - - /* set rear surround volume */ - codec->codec_write(codec, AC97_SURROUND_MASTER, 0x0000); - return 0; -} - -/* WM9705, WM9710 */ -static int wolfson_init05(struct ac97_codec * codec) -{ - /* set front mixer volume */ - codec->codec_write(codec, AC97_WM97XX_FMIXER_VOL, 0x0808); - return 0; -} - -/* WM9711, WM9712 */ -static int wolfson_init11(struct ac97_codec * codec) -{ - /* stop pop's during suspend/resume */ - codec->codec_write(codec, AC97_WM97XX_TEST, - codec->codec_read(codec, AC97_WM97XX_TEST) & 0xffbf); - - /* set out3 volume */ - codec->codec_write(codec, AC97_WM9711_OUT3VOL, 0x0808); - return 0; -} - -/* WM9713 */ -static int wolfson_init13(struct ac97_codec * codec) -{ - codec->codec_write(codec, AC97_RECORD_GAIN, 0x00a0); - codec->codec_write(codec, AC97_POWER_CONTROL, 0x0000); - codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0xDA00); - codec->codec_write(codec, AC97_EXTEND_MODEM_STAT, 0x3810); - codec->codec_write(codec, AC97_PHONE_VOL, 0x0808); - codec->codec_write(codec, AC97_PCBEEP_VOL, 0x0808); - - return 0; -} - -static int tritech_init(struct ac97_codec * codec) -{ - codec->codec_write(codec, 0x26, 0x0300); - codec->codec_write(codec, 0x26, 0x0000); - codec->codec_write(codec, AC97_SURROUND_MASTER, 0x0000); - codec->codec_write(codec, AC97_RESERVED_3A, 0x0000); - return 0; -} - - -/* copied from drivers/sound/maestro.c */ -static int tritech_maestro_init(struct ac97_codec * codec) -{ - /* no idea what this does */ - codec->codec_write(codec, 0x2A, 0x0001); - codec->codec_write(codec, 0x2C, 0x0000); - codec->codec_write(codec, 0x2C, 0XFFFF); - return 0; -} - - - -/* - * Presario700 workaround - * for Jack Sense/SPDIF Register mis-setting causing - * no audible output - * by Santiago Nullo 04/05/2002 - */ - -#define AC97_AD1886_JACK_SENSE 0x72 - -static int ad1886_init(struct ac97_codec * codec) -{ - /* from AD1886 Specs */ - codec->codec_write(codec, AC97_AD1886_JACK_SENSE, 0x0010); - return 0; -} - - - - -/* - * This is basically standard AC97. It should work as a default for - * almost all modern codecs. Note that some cards wire EAPD *backwards* - * That side of it is up to the card driver not us to cope with. - * - */ - -static int eapd_control(struct ac97_codec * codec, int on) -{ - if(on) - codec->codec_write(codec, AC97_POWER_CONTROL, - codec->codec_read(codec, AC97_POWER_CONTROL)|0x8000); - else - codec->codec_write(codec, AC97_POWER_CONTROL, - codec->codec_read(codec, AC97_POWER_CONTROL)&~0x8000); - return 0; -} - -static int generic_digital_control(struct ac97_codec *codec, int slots, int rate, int mode) -{ - u16 reg; - - reg = codec->codec_read(codec, AC97_SPDIF_CONTROL); - - switch(rate) - { - /* Off by default */ - default: - case 0: - reg = codec->codec_read(codec, AC97_EXTENDED_STATUS); - codec->codec_write(codec, AC97_EXTENDED_STATUS, (reg & ~AC97_EA_SPDIF)); - if(rate == 0) - return 0; - return -EINVAL; - case 1: - reg = (reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_48K; - break; - case 2: - reg = (reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_44K; - break; - case 3: - reg = (reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_32K; - break; - } - - reg &= ~AC97_SC_CC_MASK; - reg |= (mode & AUDIO_CCMASK) << 6; - - if(mode & AUDIO_DIGITAL) - reg |= 2; - if(mode & AUDIO_PRO) - reg |= 1; - if(mode & AUDIO_DRS) - reg |= 0x4000; - - codec->codec_write(codec, AC97_SPDIF_CONTROL, reg); - - reg = codec->codec_read(codec, AC97_EXTENDED_STATUS); - reg &= (AC97_EA_SLOT_MASK); - reg |= AC97_EA_VRA | AC97_EA_SPDIF | slots; - codec->codec_write(codec, AC97_EXTENDED_STATUS, reg); - - reg = codec->codec_read(codec, AC97_EXTENDED_STATUS); - if(!(reg & 0x0400)) - { - codec->codec_write(codec, AC97_EXTENDED_STATUS, reg & ~ AC97_EA_SPDIF); - return -EINVAL; - } - return 0; -} - -/* - * Crystal digital audio control (CS4299) - */ - -static int crystal_digital_control(struct ac97_codec *codec, int slots, int rate, int mode) -{ - u16 cv; - - if(mode & AUDIO_DIGITAL) - return -EINVAL; - - switch(rate) - { - case 0: cv = 0x0; break; /* SPEN off */ - case 48000: cv = 0x8004; break; /* 48KHz digital */ - case 44100: cv = 0x8104; break; /* 44.1KHz digital */ - case 32768: /* 32Khz */ - default: - return -EINVAL; - } - codec->codec_write(codec, 0x68, cv); - return 0; -} - -/* - * CMedia digital audio control - * Needs more work. - */ - -static int cmedia_digital_control(struct ac97_codec *codec, int slots, int rate, int mode) -{ - u16 cv; - - if(mode & AUDIO_DIGITAL) - return -EINVAL; - - switch(rate) - { - case 0: cv = 0x0001; break; /* SPEN off */ - case 48000: cv = 0x0009; break; /* 48KHz digital */ - default: - return -EINVAL; - } - codec->codec_write(codec, 0x2A, 0x05c4); - codec->codec_write(codec, 0x6C, cv); - - /* Switch on mix to surround */ - cv = codec->codec_read(codec, 0x64); - cv &= ~0x0200; - if(mode) - cv |= 0x0200; - codec->codec_write(codec, 0x64, cv); - return 0; -} - - -/* copied from drivers/sound/maestro.c */ -#if 0 /* there has been 1 person on the planet with a pt101 that we - know of. If they care, they can put this back in :) */ -static int pt101_init(struct ac97_codec * codec) -{ - printk(KERN_INFO "ac97_codec: PT101 Codec detected, initializing but _not_ installing mixer device.\n"); - /* who knows.. */ - codec->codec_write(codec, 0x2A, 0x0001); - codec->codec_write(codec, 0x2C, 0x0000); - codec->codec_write(codec, 0x2C, 0xFFFF); - codec->codec_write(codec, 0x10, 0x9F1F); - codec->codec_write(codec, 0x12, 0x0808); - codec->codec_write(codec, 0x14, 0x9F1F); - codec->codec_write(codec, 0x16, 0x9F1F); - codec->codec_write(codec, 0x18, 0x0404); - codec->codec_write(codec, 0x1A, 0x0000); - codec->codec_write(codec, 0x1C, 0x0000); - codec->codec_write(codec, 0x02, 0x0404); - codec->codec_write(codec, 0x04, 0x0808); - codec->codec_write(codec, 0x0C, 0x801F); - codec->codec_write(codec, 0x0E, 0x801F); - return 0; -} -#endif - - -EXPORT_SYMBOL(ac97_probe_codec); - -MODULE_LICENSE("GPL"); - diff --git a/target/linux/xburst/files-2.6.27/sound/oss/ak4642en.c b/target/linux/xburst/files-2.6.27/sound/oss/ak4642en.c deleted file mode 100755 index 092f7f0dc..000000000 --- a/target/linux/xburst/files-2.6.27/sound/oss/ak4642en.c +++ /dev/null @@ -1,712 +0,0 @@ -/* - * linux/sound/oss/ak4642en.c - * - * AKM ak4642en codec chip driver to I2S interface - * - * Copyright (c) 2005-2007 Ingenic Semiconductor Inc. - * Author: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Because the normal application of AUDIO devices are focused on Little_endian, - * then we only perform the little endian data format in driver. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sound_config.h" - -extern mixer_info info; -extern _old_mixer_info old_info; -extern int abnormal_data_count; - -extern void (*clear_codec_mode)(void); -extern void (*set_codec_gpio_pin)(void); -extern void (*each_time_init_codec)(void); -extern void (*set_codec_record)(void); -extern void (*set_codec_replay)(void); -extern void (*clear_codec_record)(void); -extern void (*clear_codec_replay)(void); -extern void (*set_codec_speed)(int range); -extern void (*codec_mixer_old_info_id_name)(void); -extern void (*codec_mixer_info_id_name)(void); -extern void (*set_codec_volume)(int val); -extern void (*set_codec_mic)(int val); -extern void (*i2s_resume_codec)(void); -extern void (*i2s_suspend_codec)(int wr,int rd); -extern void (*set_replay_hp_or_speaker)(void); - -#define I2S_PDN 68 -#define JACK_PLUG_PIN 83 -#define JACK_PLUG_IRQ (IRQ_GPIO_0 + JACK_PLUG_PIN) - -static int jack_plug_level, old_level; -static unsigned int i2c_addr = 0x26; //AK4642EN device address at I2C bus -static unsigned int i2c_clk = 100000;//AK4642EN 400kHz max,but 100kHz here -static unsigned int spk_hp = 0; -static int codec_volume; - -void set_ak4642en_gpio_pin(void); -void each_time_init_ak4642en(void); -void set_ak4642en_replay(void); -void set_ak4642en_record(void); -void turn_on_ak4642en(void); -void turn_off_ak4642en(void); -void set_ak4642en_speed(int rate); -void reset_ak4642en(void); -void ak4642en_mixer_old_info_id_name(void); -void ak4642en_mixer_info_id_name(void); -void set_ak4642en_bass(int val); -void set_ak4642en_volume(int val); -void set_ak4642en_mic(int val); -void resume_ak4642en(void); -void suspend_ak4642en(int wr,int rd); - -static void write_reg(u8 reg, u8 val) -{ - i2c_open(); - i2c_setclk(i2c_clk); - i2c_write((i2c_addr >> 1), &val, reg, 1); - i2c_close(); -} - -#if 0 -static u8 read_reg(u8 reg) -{ - u8 val; - i2c_open(); - i2c_setclk(i2c_clk); - i2c_read((i2c_addr >> 1), &val, reg, 1); - i2c_close(); - return val; -} - -static u16 i2s_codec_read(u8 reg) -{ - u16 value; - value = read_reg(reg); - return value; -} -#endif - -static void i2s_codec_write(u8 reg, u16 data) -{ - u8 val = data & 0xff; - write_reg(reg, val); -} - -void set_ak4642en_gpio_pin(void) -{ - //set AIC pin to I2S slave mode,only GPIO70,71,77,78 - __gpio_as_output(68); - __gpio_clear_pin(68); - __gpio_as_output(69); - __gpio_clear_pin(69); - __gpio_as_output(70); - __gpio_clear_pin(70); - __gpio_as_input(71); - __gpio_clear_pin(71); - __gpio_as_input(77); - __gpio_clear_pin(77); - __gpio_as_input(78); - __gpio_clear_pin(78); - REG_GPIO_GPALR(2) &= 0xC3FF0CFF; - REG_GPIO_GPALR(2) |= 0x14005000; - //set SCC clock initialization - REG_SCC1_CR(SCC1_BASE) = 0x00000000; - udelay(2); - REG_SCC1_CR(SCC1_BASE) |= 1 << 31; - udelay(2); - - __gpio_as_output(I2S_PDN); - __gpio_set_pin(I2S_PDN); - udelay(5); - __gpio_clear_pin(I2S_PDN); - ndelay(300);//>150ns - __gpio_set_pin(I2S_PDN); - mdelay(1); - //set PLL Master mode - i2s_codec_write(0x01, 0x0008);//master - i2s_codec_write(0x04, 0x006b);//ref:12MHz;BITCLK:64fs;I2S compli - i2s_codec_write(0x05, 0x000b);//sync:48KHz; - i2s_codec_write(0x00, 0x0040);//PMVCM - i2s_codec_write(0x01, 0x0009);//master,PLL enable - mdelay(40); - jack_plug_level = 10; - old_level = 100; - spk_hp = 0; - __gpio_disable_pull(JACK_PLUG_PIN); - udelay(10); - __gpio_as_input(JACK_PLUG_PIN); - jack_plug_level = __gpio_get_pin(JACK_PLUG_PIN); - //i suppose jack_plug_lvel is 1 indicate with HPO - if (jack_plug_level > 1 || jack_plug_level <0) - printk("Audio ak4642en codec Jack plug level is wrong!\n"); - if (jack_plug_level) - __gpio_as_irq_fall_edge(JACK_PLUG_PIN); - else - __gpio_as_irq_rise_edge(JACK_PLUG_PIN); -} - -void clear_ak4642en_mode(void) -{ - spk_hp = 0; - i2s_codec_write(0x01, 0x0008);//master,PLL disable - //free_irq(JACK_PLUG_IRQ, i2s_controller); - __gpio_clear_pin(I2S_PDN); - udelay(2); - REG_SCC1_CR(SCC1_BASE) &= 0 << 31; - udelay(2); -} - -void set_ak4642en_replay(void) -{ - //for poll - /*jack_plug_level is H for SPK,is L for HP*/ - jack_plug_level = __gpio_get_pin(JACK_PLUG_PIN); - if(old_level == jack_plug_level) - return; - old_level = jack_plug_level; - if(spk_hp == 1) - { - if(jack_plug_level == 1) - { - //now HeadPhone output,so clear SPK - i2s_codec_write(0x02, 0x0020); - i2s_codec_write(0x02, 0x0000); - i2s_codec_write(0x00, 0x0040); - } - else - { - //now Speaker output,so clear HP - i2s_codec_write(0x01, 0x0039); - i2s_codec_write(0x01, 0x0009); - i2s_codec_write(0x00, 0x0040); - i2s_codec_write(0x0e, 0x0000); - i2s_codec_write(0x0f, 0x0008); - } - } - spk_hp = 1; - if(jack_plug_level == 1) - { - //for HeadPhone output - i2s_codec_write(0x00, 0x0060); // - i2s_codec_write(0x0f, 0x0009); //5-10 - - i2s_codec_write(0x00, 0x0064); // - i2s_codec_write(0x09, 0x0091);// volume control 0dB - i2s_codec_write(0x0c, 0x0091);// 0dB(right) - //eq off - i2s_codec_write(0x11, 0x0000);//5-10 - i2s_codec_write(0x01, 0x0039); // - - i2s_codec_write(0x01, 0x0079); // - } - else - { - //for Speaker output - i2s_codec_write(0x00, 0x0040); - i2s_codec_write(0x02, 0x0020); - - i2s_codec_write(0x03, 0x0018);//5-10 - i2s_codec_write(0x06, 0x003c); - - i2s_codec_write(0x08, 0x00A1);//5-10 - - i2s_codec_write(0x0b, 0x0040); //5-10 - - i2s_codec_write(0x07, 0x002d); //5-10 - i2s_codec_write(0x09, 0x0091); - i2s_codec_write(0x0c, 0x0091); - //HP volume output value - - i2s_codec_write(0x0a, codec_volume);//5-10 - i2s_codec_write(0x0d, codec_volume);//5-10 - - i2s_codec_write(0x00, 0x0074); - i2s_codec_write(0x02, 0x00a0); - } -} - -void set_ak4642en_record(void) -{ - abnormal_data_count = 0; - i2s_codec_write(0x02, 0x0004); - i2s_codec_write(0x03, 0x0038);// recording volume add - i2s_codec_write(0x06, 0x0000);//for ALC short waiting time - i2s_codec_write(0x08, 0x00e1); - i2s_codec_write(0x0b, 0x0000); - i2s_codec_write(0x07, 0x0021); // ALC on - - i2s_codec_write(0x10, 0x0000);//0x0001 - //i2s_codec_write(0x10, 0x0001);//0x0001 - i2s_codec_write(0x01, 0x0039); //for open pop noise - i2s_codec_write(0x01, 0x0079); - i2s_codec_write(0x00, 0x0065); - mdelay(300); -} - -void clear_ak4642en_replay(void) -{ - //for poll - old_level = 100; - spk_hp = 0; - if(jack_plug_level == 1) - { - //for HeadPhone output - i2s_codec_write(0x01, 0x0039); // for close pop noise - mdelay(300); - i2s_codec_write(0x01, 0x0009); //PLL on I2S - i2s_codec_write(0x07, 0x0001); - i2s_codec_write(0x11, 0x0000); - i2s_codec_write(0x00, 0x0040); - i2s_codec_write(0x0f, 0x0008); // for open pop noise - } - else - { - //for Speaker output - i2s_codec_write(0x02, 0x0020); - i2s_codec_write(0x07, 0x0001); - i2s_codec_write(0x11, 0x0000); - i2s_codec_write(0x02, 0x0000); - i2s_codec_write(0x00, 0x0040); // for close pop noise - } -} - -void clear_ak4642en_record(void) -{ - //for Mic input(Stereo) - i2s_codec_write(0x02, 0x0001); - i2s_codec_write(0x07, 0x0001); - i2s_codec_write(0x11, 0x0000); -} - -void each_time_init_ak4642en(void) -{ - __i2s_disable(); - __i2s_as_slave(); - __i2s_set_sample_size(16); -} - -void set_ak4642en_speed(int rate) -{ - //codec work at frequency - unsigned short speed = 0; - unsigned short val = 0; - switch (rate) - { - case 8000: - speed = 0x00; - if(jack_plug_level == 1) //speaker - { - i2s_codec_write(0x16, 0x0000); - i2s_codec_write(0x17, 0x0000); - i2s_codec_write(0x18, 0x0000); - i2s_codec_write(0x19, 0x0000); - i2s_codec_write(0x1A, 0x0000); - i2s_codec_write(0x1B, 0x0000); - i2s_codec_write(0x1C, 0x0027);//800hz - i2s_codec_write(0x1D, 0x0018); - i2s_codec_write(0x1E, 0x00b2); - i2s_codec_write(0x1F, 0x002f); - i2s_codec_write(0x11, 0x0010); //eq on - } - break; - case 12000: - speed = 0x01; - if(jack_plug_level == 1) - { - i2s_codec_write(0x16, 0x0000); - i2s_codec_write(0x17, 0x0000); - i2s_codec_write(0x18, 0x0000); - i2s_codec_write(0x19, 0x0000); - i2s_codec_write(0x1A, 0x0000); - i2s_codec_write(0x1B, 0x0000); - i2s_codec_write(0x1C, 0x0064); - i2s_codec_write(0x1D, 0x001a); - i2s_codec_write(0x1E, 0x0038); - i2s_codec_write(0x1F, 0x002b); - i2s_codec_write(0x11, 0x0010); //eq on - } - break; - case 16000: - speed = 0x02; - if(jack_plug_level == 1) - { - i2s_codec_write(0x16, 0x00af); - i2s_codec_write(0x17, 0x0020); - i2s_codec_write(0x18, 0x0043); - i2s_codec_write(0x19, 0x001a); - i2s_codec_write(0x1A, 0x00af); - i2s_codec_write(0x1B, 0x0020); - i2s_codec_write(0x1C, 0x00a0); - i2s_codec_write(0x1D, 0x001b); - i2s_codec_write(0x1E, 0x00c0); - i2s_codec_write(0x1F, 0x0028); - i2s_codec_write(0x11, 0x0018); //eq on - } - break; - case 24000: - speed = 0x03; - if(jack_plug_level == 1) - { - i2s_codec_write(0x16, 0x0086); - i2s_codec_write(0x17, 0x0015); - i2s_codec_write(0x18, 0x005d); - i2s_codec_write(0x19, 0x0006); - i2s_codec_write(0x1A, 0x0086); - i2s_codec_write(0x1B, 0x0015); - i2s_codec_write(0x1C, 0x00f5); - i2s_codec_write(0x1D, 0x001c); - i2s_codec_write(0x1E, 0x0016); - i2s_codec_write(0x1F, 0x0026); - i2s_codec_write(0x11, 0x0018); //eq on - } - break; - case 7350: - speed = 0x04; - if(jack_plug_level == 1) - { - i2s_codec_write(0x16, 0x0000); - i2s_codec_write(0x17, 0x0000); - i2s_codec_write(0x18, 0x0000); - i2s_codec_write(0x19, 0x0000); - i2s_codec_write(0x1A, 0x0000); - i2s_codec_write(0x1B, 0x0000); - i2s_codec_write(0x1C, 0x0027); - i2s_codec_write(0x1D, 0x0018); - i2s_codec_write(0x1E, 0x00b2); - i2s_codec_write(0x1F, 0x002f); - i2s_codec_write(0x11, 0x0010); //eq on - } - break; - case 11025: - speed = 0x05; - if(jack_plug_level == 1) - { - i2s_codec_write(0x16, 0x0059); - i2s_codec_write(0x17, 0x000d); - i2s_codec_write(0x18, 0x00cb); - i2s_codec_write(0x19, 0x0037); - i2s_codec_write(0x1A, 0x0059); - i2s_codec_write(0x1B, 0x000d); - i2s_codec_write(0x1C, 0x0046); - i2s_codec_write(0x1D, 0x001e); - i2s_codec_write(0x1E, 0x0074); - i2s_codec_write(0x1F, 0x0023); - i2s_codec_write(0x11, 0x0018); //eq on - } - break; - case 14700: - speed = 0x06; - if(jack_plug_level == 1) - { - i2s_codec_write(0x16, 0x0000); - i2s_codec_write(0x17, 0x0000); - i2s_codec_write(0x18, 0x0000); - i2s_codec_write(0x19, 0x0000); - i2s_codec_write(0x1A, 0x0000); - i2s_codec_write(0x1B, 0x0000); - i2s_codec_write(0x1C, 0x004a); - i2s_codec_write(0x1D, 0x001b); - i2s_codec_write(0x1E, 0x006c); - i2s_codec_write(0x1F, 0x0029); - i2s_codec_write(0x11, 0x0010); //eq on - } - break; - case 22050: - speed = 0x07; - if(jack_plug_level == 1) - { - i2s_codec_write(0x16, 0x002d); - i2s_codec_write(0x17, 0x0017); - i2s_codec_write(0x18, 0x0050); - i2s_codec_write(0x19, 0x0009); - i2s_codec_write(0x1A, 0x002d); - i2s_codec_write(0x1B, 0x0017); - i2s_codec_write(0x1C, 0x00d7); - i2s_codec_write(0x1D, 0x001c); - i2s_codec_write(0x1E, 0x0093); - i2s_codec_write(0x1F, 0x0026); - i2s_codec_write(0x11, 0x0018); //eq on - } - break; - case 32000: - speed = 0x0a; - if(jack_plug_level == 1) - { - i2s_codec_write(0x16, 0x0012); - i2s_codec_write(0x17, 0x0011); - i2s_codec_write(0x18, 0x006e); - i2s_codec_write(0x19, 0x003e); - i2s_codec_write(0x1A, 0x0012); - i2s_codec_write(0x1B, 0x0011); - i2s_codec_write(0x1C, 0x00aa); - i2s_codec_write(0x1D, 0x001d); - i2s_codec_write(0x1E, 0x00ab); - i2s_codec_write(0x1F, 0x0024); - i2s_codec_write(0x11, 0x0018); //eq on - } - break; - case 48000: - speed = 0x0b; - if(jack_plug_level == 1) - { - i2s_codec_write(0x16, 0x0082); - i2s_codec_write(0x17, 0x000c); - i2s_codec_write(0x18, 0x004b); - i2s_codec_write(0x19, 0x0036); - i2s_codec_write(0x1A, 0x0082); - i2s_codec_write(0x1B, 0x000c); - i2s_codec_write(0x1C, 0x0068); - i2s_codec_write(0x1D, 0x001e); - i2s_codec_write(0x1E, 0x0030); - i2s_codec_write(0x1F, 0x0023); - i2s_codec_write(0x11, 0x0018); //eq on - } - break; - case 29400: - speed = 0x0e; - if(jack_plug_level == 1) - { - i2s_codec_write(0x16, 0x003d); - i2s_codec_write(0x17, 0x0012); - i2s_codec_write(0x18, 0x0083); - i2s_codec_write(0x19, 0x0000); - i2s_codec_write(0x1A, 0x003d); - i2s_codec_write(0x1B, 0x0012); - i2s_codec_write(0x1C, 0x0079); - i2s_codec_write(0x1D, 0x001d); - i2s_codec_write(0x1E, 0x000d); - i2s_codec_write(0x1F, 0x0025); - i2s_codec_write(0x11, 0x0018); //eq on - } - break; - case 44100: - speed = 0x0f; - if(jack_plug_level == 1) - { - i2s_codec_write(0x16, 0x0059); - i2s_codec_write(0x17, 0x000d); - i2s_codec_write(0x18, 0x00cb); - i2s_codec_write(0x19, 0x0037); - i2s_codec_write(0x1A, 0x0059); - i2s_codec_write(0x1B, 0x000d); - i2s_codec_write(0x1C, 0x0046); - i2s_codec_write(0x1D, 0x001e); - i2s_codec_write(0x1E, 0x0074); - i2s_codec_write(0x1F, 0x0023); - i2s_codec_write(0x11, 0x0018); //eq on - } - break; - default: - break; - } - val = speed & 0x08; - val = val << 2; - speed = speed & 0x07; - val = val | speed; - i2s_codec_write(0x05, val); -} - -void ak4642en_mixer_old_info_id_name(void) -{ - strncpy(info.id, "AK4642EN", sizeof(info.id)); - strncpy(info.name,"AKM AK4642en codec", sizeof(info.name)); -} - -void ak4642en_mixer_info_id_name(void) -{ - strncpy(old_info.id, "AK4642EN", sizeof(old_info.id)); - strncpy(old_info.name,"AKM AK4642en codec", sizeof(old_info.name)); -} - -void set_ak4642en_volume(int val) -{ - if ( val == 0 ) - codec_volume = 255; - else if ( val > 1 && val <= 10) - codec_volume = 92; - else if ( val > 10 && val <= 20 ) - codec_volume = 67; - else if ( val > 20 && val <= 30 ) - codec_volume = 50; - else if ( val > 30 && val <= 40 ) - codec_volume = 40; - else if ( val > 40 && val <= 50 ) - codec_volume = 30; - else if ( val > 50 && val <= 60 ) - codec_volume = 22; - else if ( val > 60&& val <= 70 ) - codec_volume = 15; - else if ( val > 70 && val <= 80 ) - codec_volume = 8; - else if ( val > 80 && val <= 90 ) - codec_volume = 4; - else if ( val > 90 && val <= 100 ) - codec_volume = 2; - - i2s_codec_write(0x0a, codec_volume); - i2s_codec_write(0x0d, codec_volume); -} - -void set_ak4642en_mic(int val) -{ - int mic_gain; - mic_gain = 241 * val /100; - i2s_codec_write(0x09, mic_gain); - i2s_codec_write(0x0c, mic_gain); -} - -void resume_ak4642en(void) -{ - __gpio_as_output(17); - __gpio_set_pin(17); //enable ak4642 - __gpio_as_output(68); - __gpio_clear_pin(68); - __gpio_as_output(69); - __gpio_clear_pin(69); - __gpio_as_output(70); - __gpio_clear_pin(70); - __gpio_as_input(71); - __gpio_clear_pin(71); - __gpio_as_input(77); - __gpio_clear_pin(77); - __gpio_as_input(78); - __gpio_clear_pin(78); - REG_GPIO_GPALR(2) &= 0xC3FF0CFF; - REG_GPIO_GPALR(2) |= 0x14005000; - //set SCC clock initialization - REG_SCC1_CR(SCC1_BASE) = 0x00000000; - udelay(2); - REG_SCC1_CR(SCC1_BASE) |= 1 << 31; - udelay(2); - __gpio_as_output(I2S_PDN); - __gpio_set_pin(I2S_PDN); - udelay(5); - __gpio_clear_pin(I2S_PDN); - ndelay(300);//>150ns - __gpio_set_pin(I2S_PDN); - mdelay(1); - //set PLL Master mode - i2s_codec_write(0x01, 0x0008);//master - i2s_codec_write(0x04, 0x006b);//ref:12MHz;BITCLK:64fs;I2S compli - i2s_codec_write(0x05, 0x000b);//sync:48KHz; - i2s_codec_write(0x00, 0x0040);//PMVCM - i2s_codec_write(0x01, 0x0009);//master,PLL enable - jack_plug_level = 10; - old_level = 100; - spk_hp = 0; - __gpio_as_input(JACK_PLUG_PIN); - jack_plug_level = __gpio_get_pin(JACK_PLUG_PIN); - //i suppose jack_plug_lvel is 1 indicate with HPO - if(jack_plug_level > 1 || jack_plug_level <0) - printk("Audio ak4642en codec Jack plug level is wrong!\n"); - if(jack_plug_level) - __gpio_as_irq_fall_edge(JACK_PLUG_PIN); - else - __gpio_as_irq_rise_edge(JACK_PLUG_PIN); - - i2s_codec_write(0x00, 0x0065); //for resume power - i2s_codec_write(0x01, 0x0039); //for open pop noise - i2s_codec_write(0x01, 0x0079); - i2s_codec_write(0x0a, codec_volume); - i2s_codec_write(0x0d, codec_volume); -} - -void suspend_ak4642en(int wr,int rd) -{ - if(wr) //playing - { - if(jack_plug_level == 0) - { - i2s_codec_write(0x01, 0x0039); // for close pop noise - mdelay(500); - i2s_codec_write(0x01, 0x0009); //PLL on I2S - i2s_codec_write(0x07, 0x0001); - i2s_codec_write(0x11, 0x0000); - i2s_codec_write(0x00, 0x0040); - i2s_codec_write(0x0f, 0x0008); // for open pop noise - - } - else - { - //for Speaker output - i2s_codec_write(0x02, 0x0020); - i2s_codec_write(0x07, 0x0001); - i2s_codec_write(0x11, 0x0000); - i2s_codec_write(0x02, 0x0000); - i2s_codec_write(0x00, 0x0040); // for close pop noise - } - } - - if(rd) // recording - { - i2s_codec_write(0x02, 0x0001); // 5-11 a1 - i2s_codec_write(0x07, 0x0001); - i2s_codec_write(0x11, 0x0000); - mdelay(300); - } - __gpio_as_output(17); - __gpio_clear_pin(17);//disable ak4642 - __i2s_disable(); -} - -static int __init init_ak4642en(void) -{ - set_codec_gpio_pin = set_ak4642en_gpio_pin; - each_time_init_codec = each_time_init_ak4642en; - clear_codec_mode = clear_ak4642en_mode; - - set_codec_record = set_ak4642en_record; - set_codec_replay = set_ak4642en_replay; - set_replay_hp_or_speaker = set_ak4642en_replay; - - set_codec_speed = set_ak4642en_speed; - clear_codec_record = clear_ak4642en_record; - clear_codec_replay = clear_ak4642en_replay; - - codec_mixer_old_info_id_name = ak4642en_mixer_old_info_id_name; - codec_mixer_info_id_name = ak4642en_mixer_info_id_name; - - set_codec_volume = set_ak4642en_volume; - - set_codec_mic = set_ak4642en_mic; - - i2s_resume_codec = resume_ak4642en; - i2s_suspend_codec = suspend_ak4642en; - printk("---> ak4642en initialization!\n"); - return 0; -} - -static void __exit cleanup_ak4642en(void) -{ - spk_hp = 0; - i2s_codec_write(0x01, 0x0008);//master,PLL disable - //free_irq(JACK_PLUG_IRQ, i2s_controller); - __gpio_clear_pin(I2S_PDN); - udelay(2); - REG_SCC1_CR(SCC1_BASE) &= 0 << 31; - udelay(2); -} - -module_init(init_ak4642en); -module_exit(cleanup_ak4642en); diff --git a/target/linux/xburst/files-2.6.27/sound/oss/jz_ac97.c b/target/linux/xburst/files-2.6.27/sound/oss/jz_ac97.c deleted file mode 100755 index 698a003f1..000000000 --- a/target/linux/xburst/files-2.6.27/sound/oss/jz_ac97.c +++ /dev/null @@ -1,2252 +0,0 @@ -/* - * linux/drivers/sound/jz_ac97.c - * - * Jz On-Chip AC97 audio driver. - * - * Copyright (C) 2005 - 2007, Ingenic Semiconductor Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Because the normal application of AUDIO devices are focused on Little_endian, - * then we only perform the little endian data format in driver. - * - */ - -#define __NO_VERSION__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#include "sound_config.h" - -#define DMA_ID_AC97_TX DMA_ID_AIC_TX -#define DMA_ID_AC97_RX DMA_ID_AIC_RX - -/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */ -#define NR_AC97 2 - -#define STANDARD_SPEED 48000 -#define MAX_RETRY 100 - -static unsigned int k_8000[] = { - 0, 42, 85, 128, 170, 213, -}; - -static unsigned int reload_8000[] = { - 1, 0, 0, 0, 0, 0, -}; - -static unsigned int k_11025[] = { - 0, 58, 117, 176, 234, 37, 96, 154, - 213, 16, 74, 133, 192, 250, 53, 112, - 170, 229, 32, 90, 149, 208, 10, 69, - 128, 186, 245, 48, 106, 165, 224, 26, - 85, 144, 202, 5, 64, 122, 181, 240, - 42, 101, 160, 218, 21, 80, 138, 197, -}; - -static unsigned int reload_11025[] = { - 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, - 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, - 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, -}; - -static unsigned int k_16000[] = { - 0, 85, 170, -}; - -static unsigned int reload_16000[] = { - 1, 0, 0, -}; - -static unsigned int k_22050[] = { - 0, 117, 234, 96, 213, 74, 192, 53, - 170, 32, 149, 10, 128, 245, 106, 224, - 85, 202, 64, 181, 42, 160, 21, 138, -}; - -static unsigned int reload_22050[] = { - 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, -}; - -static unsigned int k_24000[] = { - 0, 128, -}; - -static unsigned int reload_24000[] = { - 1, 0, -}; - -static unsigned int k_32000[] = { - 0, 170, 85, -}; - -static unsigned int reload_32000[] = { - 1, 0, 1, -}; - -static unsigned int k_44100[] = { - 0, 234, 213, 192, 170, 149, 128, 106, - 85, 64, 42, 21, -}; - -static unsigned int reload_44100[] = { - 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -}; - -static unsigned int k_48000[] = { - 0, -}; - -static unsigned int reload_48000[] = { - 1, -}; - - -static unsigned int f_scale_counts[8] = { - 6, 48, 3, 24, 2, 3, 12, 1, -}; - -static int jz_audio_rate; -static char jz_audio_format; -static char jz_audio_channels; -static int jz_audio_k; /* rate expand multiple */ -static int jz_audio_q; /* rate expand compensate */ -static int jz_audio_count; /* total count of voice data */ -static int last_jz_audio_count; - -static int jz_audio_fragments;//unused fragment amount -static int jz_audio_fragstotal; -static int jz_audio_fragsize; -static int jz_audio_dma_tran_count;//bytes count of one DMA transfer - -static unsigned int f_scale_count; -static unsigned int *f_scale_array; -static unsigned int *f_scale_reload; -static unsigned int f_scale_idx; - -static void (*old_mksound)(unsigned int hz, unsigned int ticks); -extern void (*kd_mksound)(unsigned int hz, unsigned int ticks); -extern void jz_set_dma_block_size(int dmanr, int nbyte); -extern void jz_set_dma_dest_width(int dmanr, int nbit); -extern void jz_set_dma_src_width(int dmanr, int nbit); - -static void jz_update_filler(int bits, int channels); - -static void Init_In_Out_queue(int fragstotal,int fragsize); -static void Free_In_Out_queue(int fragstotal,int fragsize); - -static irqreturn_t -jz_ac97_replay_dma_irq(int irqnr, void *dev_id); -static irqreturn_t -jz_ac97_record_dma_irq(int irqnr, void *dev_id); - -static void -(*replay_filler)(unsigned long src_start, int count, int id); -static int -(*record_filler)(unsigned long dst_start, int count, int id); - -static struct file_operations jz_ac97_audio_fops; - -DECLARE_WAIT_QUEUE_HEAD (rx_wait_queue); -DECLARE_WAIT_QUEUE_HEAD (tx_wait_queue); - -struct jz_ac97_controller_info -{ - int io_base; - int dma1; /* play */ - int dma2; /* record */ - - char *name; - - int dev_audio; - struct ac97_codec *ac97_codec[NR_AC97]; - - unsigned short ac97_features; - - int opened1; - int opened2; - - unsigned char *tmp1; /* tmp buffer for sample conversions */ - unsigned char *tmp2; - - spinlock_t lock; - spinlock_t ioctllock; - wait_queue_head_t dac_wait; - wait_queue_head_t adc_wait; - - int nextIn; // byte index to next-in to DMA buffer - int nextOut; // byte index to next-out from DMA buffer - int count; // current byte count in DMA buffer - int finish; // current transfered byte count in DMA buffer - unsigned total_bytes; // total bytes written or read - unsigned blocks; - unsigned error; // over/underrun - - /* We use two devices, because we can do simultaneous play and record. - This keeps track of which device is being used for what purpose; - these are the actual device numbers. */ - int dev_for_play; - int dev_for_record; - - int playing; - int recording; - int patched; - unsigned long rec_buf_size; - unsigned long playback_buf_size; - -#ifdef CONFIG_PM - struct pm_dev *pm; -#endif -}; - -static struct jz_ac97_controller_info *ac97_controller = NULL; - -static int jz_readAC97Reg(struct ac97_codec *dev, u8 reg); -static int jz_writeAC97Reg(struct ac97_codec *dev, u8 reg, u16 data); -static u16 ac97_codec_read(struct ac97_codec *codec, u8 reg); -static void ac97_codec_write(struct ac97_codec *codec, u8 reg, u16 data); - -#define QUEUE_MAX 2 - -typedef struct buffer_queue_s { - int count; - int *id; - spinlock_t lock; -} buffer_queue_t; - -static unsigned long *out_dma_buf = NULL; -static unsigned long *out_dma_pbuf = NULL; -static unsigned long *out_dma_buf_data_count = NULL; -static unsigned long *in_dma_buf = NULL; -static unsigned long *in_dma_pbuf = NULL; -static unsigned long *in_dma_buf_data_count = NULL; - -static buffer_queue_t out_empty_queue; -static buffer_queue_t out_full_queue; -static buffer_queue_t out_busy_queue; - -static buffer_queue_t in_empty_queue; -static buffer_queue_t in_full_queue; -static buffer_queue_t in_busy_queue; - -static int first_record_call = 0; - -static inline int get_buffer_id(struct buffer_queue_s *q) -{ - int r, i; - unsigned long flags; - spin_lock_irqsave(&q->lock, flags); - if (q->count == 0) { - spin_unlock_irqrestore(&q->lock, flags); - return -1; - } - r = *(q->id + 0); - for (i=0;i < q->count-1;i++) - *(q->id + i) = *(q->id + (i+1)); - q->count --; - spin_unlock_irqrestore(&q->lock, flags); - return r; -} - -static inline void put_buffer_id(struct buffer_queue_s *q, int id) -{ - unsigned long flags; - spin_lock_irqsave(&q->lock, flags); - *(q->id + q->count) = id; - q->count ++; - spin_unlock_irqrestore(&q->lock, flags); -} - -static inline int elements_in_queue(struct buffer_queue_s *q) -{ - int r; - unsigned long flags; - spin_lock_irqsave(&q->lock, flags); - r = q->count; - spin_unlock_irqrestore(&q->lock, flags); - return r; -} - -/**************************************************************************** - * Architecture related routines - ****************************************************************************/ -static inline -void audio_start_dma(int chan, void *dev_id, unsigned long phyaddr,int count, int mode) -{ - unsigned long flags; - struct jz_ac97_controller_info * controller = - (struct jz_ac97_controller_info *) dev_id; - //for DSP_GETOPTR - spin_lock_irqsave(&controller->ioctllock, flags); - jz_audio_dma_tran_count = count; - spin_unlock_irqrestore(&controller->ioctllock, flags); - - flags = claim_dma_lock(); - disable_dma(chan); - clear_dma_ff(chan); - set_dma_mode(chan, mode); - set_dma_addr(chan, phyaddr); - if (count == 0) { - count++; - printk(KERN_DEBUG "%s: JzSOC DMA controller can't set dma count zero!\n", - __FUNCTION__); - } - set_dma_count(chan, count); - enable_dma(chan); - release_dma_lock(flags); -} - -static irqreturn_t -jz_ac97_record_dma_irq (int irq, void *dev_id) -{ - struct jz_ac97_controller_info * controller = - (struct jz_ac97_controller_info *) dev_id; - int dma = controller->dma2; - int id1, id2; - unsigned long flags; - - disable_dma(dma); - if (__dmac_channel_address_error_detected(dma)) { - printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); - __dmac_channel_clear_address_error(dma); - } - if (__dmac_channel_transmit_end_detected(dma)) { - __dmac_channel_clear_transmit_end(dma); - - //for DSP_GETIPTR - spin_lock_irqsave(&controller->ioctllock, flags); - controller->total_bytes += jz_audio_dma_tran_count; - controller->blocks ++; - spin_unlock_irqrestore(&controller->ioctllock, flags); - - id1 = get_buffer_id(&in_busy_queue); - put_buffer_id(&in_full_queue, id1); - wake_up(&rx_wait_queue); - wake_up(&controller->adc_wait); - if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { - put_buffer_id(&in_busy_queue, id2); - - *(in_dma_buf_data_count + id2) = *(in_dma_buf_data_count + id1); - audio_start_dma(dma,dev_id, - *(in_dma_pbuf + id2), - *(in_dma_buf_data_count + id2), - DMA_MODE_READ); - } else { - in_busy_queue.count = 0; - } - } - return IRQ_HANDLED; -} - -static irqreturn_t -jz_ac97_replay_dma_irq (int irq, void *dev_id) -{ - struct jz_ac97_controller_info * controller = - (struct jz_ac97_controller_info *) dev_id; - int dma = controller->dma1, id; - unsigned long flags; - - disable_dma(dma); - if (__dmac_channel_address_error_detected(dma)) { - printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); - __dmac_channel_clear_address_error(dma); - } - if (__dmac_channel_transmit_end_detected(dma)) { - __dmac_channel_clear_transmit_end(dma); - //for DSP_GETOPTR - spin_lock_irqsave(&controller->ioctllock, flags); - controller->total_bytes += jz_audio_dma_tran_count; - controller->blocks ++; - spin_unlock_irqrestore(&controller->ioctllock, flags); - if ((id = get_buffer_id(&out_busy_queue)) < 0) { - printk(KERN_DEBUG "Strange DMA finish interrupt for AC97 module\n"); - } - - put_buffer_id(&out_empty_queue, id); - if ((id = get_buffer_id(&out_full_queue)) >= 0) { - put_buffer_id(&out_busy_queue, id); - if(*(out_dma_buf_data_count + id) > 0) { - audio_start_dma(dma, dev_id, *(out_dma_pbuf + id), - *(out_dma_buf_data_count + id), - DMA_MODE_WRITE); - } - } else { - out_busy_queue.count = 0; - } - if (elements_in_queue(&out_empty_queue) > 0) { - wake_up(&tx_wait_queue); - wake_up(&controller->dac_wait); - } - } - return IRQ_HANDLED; -} - -/* - * Initialize the onchip AC97 controller - */ -static void jz_ac97_initHw(struct jz_ac97_controller_info *controller) -{ - __ac97_disable(); - __ac97_reset(); - __ac97_enable(); - - __ac97_cold_reset_codec(); - /* wait for a long time to let ac97 controller reset completely, - * otherwise, registers except ACFR will be clear by reset, can't be - * set correctly. - */ - udelay(160); - - __ac97_disable_record(); - __ac97_disable_replay(); - __ac97_disable_loopback(); - - /* Check the trigger threshold reset value to detect version */ - if (((REG_AIC_FR & AIC_FR_TFTH_MASK) >> AIC_FR_TFTH_BIT) == 8) { - printk("JzAC97: patched controller detected.\n"); - controller->patched = 1; - } else { - printk("JzAC97: standard controller detected.\n"); - controller->patched = 0; - } - - /* Set FIFO data size. Which shows valid data bits. - * - */ - __ac97_set_oass(8); - __ac97_set_iass(8); - - __ac97_set_xs_stereo(); - __ac97_set_rs_stereo(); -} - -/* - * Initialize all of in(out)_empty_queue value - */ -static void Init_In_Out_queue(int fragstotal,int fragsize) -{ - int i; - if(out_dma_buf || in_dma_buf) - return; - in_empty_queue.count = fragstotal; - out_empty_queue.count = fragstotal; - - out_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - if (!out_dma_buf) - goto all_mem_err; - out_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - if (!out_dma_pbuf) - goto all_mem_err; - out_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - if (!out_dma_buf_data_count) - goto all_mem_err; - in_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - if (!in_dma_buf) - goto all_mem_err; - in_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - if (!in_dma_pbuf) - goto all_mem_err; - in_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - if (!in_dma_buf_data_count) - goto all_mem_err; - in_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!in_empty_queue.id) - goto all_mem_err; - in_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!in_full_queue.id) - goto all_mem_err; - in_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!in_busy_queue.id) - goto all_mem_err; - out_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!out_empty_queue.id) - goto all_mem_err; - out_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!out_full_queue.id) - goto all_mem_err; - out_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!out_busy_queue.id) - goto all_mem_err; - - for (i=0;i < fragstotal;i++) { - *(in_empty_queue.id + i) = i; - *(out_empty_queue.id + i) = i; - } - - in_full_queue.count = 0; - in_busy_queue.count = 0; - out_busy_queue.count = 0; - out_full_queue.count = 0; - /*alloc DMA buffer*/ - for (i = 0; i < jz_audio_fragstotal; i++) { - *(out_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); - if (*(out_dma_buf + i) == 0) { - printk(" can't allocate required DMA(OUT) buffers.\n"); - goto mem_failed_out; - } - *(out_dma_pbuf + i) = virt_to_phys((void *)(*(out_dma_buf + i))); - } - - for (i = 0; i < jz_audio_fragstotal; i++) { - *(in_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); - if (*(in_dma_buf + i) == 0) { - printk(" can't allocate required DMA(IN) buffers.\n"); - goto mem_failed_in; - } - *(in_dma_pbuf + i) = virt_to_phys((void *)(*(in_dma_buf + i))); - dma_cache_wback_inv(*(in_dma_buf + i), 4096*8);//fragsize - *(in_dma_buf + i) = KSEG1ADDR(*(in_dma_buf + i)); - } - return ; - - all_mem_err: - printk("error:allocate memory occur error!\n"); - return ; - -mem_failed_out: - - for (i = 0; i < jz_audio_fragstotal; i++) { - if(*(out_dma_buf + i)) - free_pages(*(out_dma_buf + i), get_order(fragsize)); - } - return ; - -mem_failed_in: - - for (i = 0; i < jz_audio_fragstotal; i++) { - if(*(in_dma_buf + i)) - free_pages(*(in_dma_buf + i), get_order(fragsize)); - } - return ; - -} -static void Free_In_Out_queue(int fragstotal,int fragsize) -{ - int i; - if(out_dma_buf != NULL) - { - for (i = 0; i < jz_audio_fragstotal; i++) - { - if(*(out_dma_buf + i)) - free_pages(*(out_dma_buf + i), get_order(fragsize)); - *(out_dma_buf + i) = 0; - } - kfree(out_dma_buf); - out_dma_buf = NULL; - } - if(out_dma_pbuf) - { - kfree(out_dma_pbuf); - out_dma_pbuf = NULL; - } - if(out_dma_buf_data_count) - { - kfree(out_dma_buf_data_count); - out_dma_buf_data_count = NULL; - } - if(in_dma_buf) - { - for (i = 0; i < jz_audio_fragstotal; i++) - { - if(*(in_dma_buf + i)) - free_pages(*(in_dma_buf + i), get_order(fragsize)); - *(in_dma_buf + i) = 0; - } - kfree(in_dma_buf); - in_dma_buf = NULL; - } - if(in_dma_pbuf) - { - kfree(in_dma_pbuf); - in_dma_pbuf = NULL; - } - if(in_dma_buf_data_count) - { - kfree(in_dma_buf_data_count); - in_dma_buf_data_count = NULL; - } - if(in_empty_queue.id) - { - kfree(in_empty_queue.id); - in_empty_queue.id = NULL; - } - if(in_full_queue.id) - { - kfree(in_full_queue.id); - in_full_queue.id = NULL; - } - if(in_busy_queue.id) - { - kfree(in_busy_queue.id); - in_busy_queue.id = NULL; - } - if(out_empty_queue.id) - { - kfree(out_empty_queue.id); - out_empty_queue.id = NULL; - } - if(out_full_queue.id) - { - kfree(out_full_queue.id); - out_full_queue.id = NULL; - } - if(out_busy_queue.id) - { - kfree(out_busy_queue.id); - out_busy_queue.id = NULL; - } - - in_empty_queue.count = fragstotal; - out_empty_queue.count = fragstotal; - in_full_queue.count = 0; - in_busy_queue.count = 0; - out_busy_queue.count = 0; - out_full_queue.count = 0; - return ; -} - -/* - * Reset everything - */ -static void -jz_ac97_full_reset(struct jz_ac97_controller_info *controller) -{ - jz_ac97_initHw(controller); -} - - -static void -jz_ac97_mksound(unsigned int hz, unsigned int ticks) -{ -// printk("BEEP - %d %d!\n", hz, ticks); -} - -static int jz_audio_set_speed(int dev, int rate) -{ - /* 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999 ? */ - u32 dacp; - struct ac97_codec *codec=ac97_controller->ac97_codec[0]; - - if (rate > 48000) - rate = 48000; - if (rate < 8000) - rate = 8000; - - - /* Power down the DAC */ - dacp=ac97_codec_read(codec, AC97_POWER_CONTROL); - ac97_codec_write(codec, AC97_POWER_CONTROL, dacp|0x0200); - /* Load the rate; only 48Khz playback available, read always zero */ - if ((ac97_controller->patched) && (ac97_controller->ac97_features & 1)) - ac97_codec_write(codec, AC97_PCM_FRONT_DAC_RATE, rate); - else - ac97_codec_write(codec, AC97_PCM_FRONT_DAC_RATE, 48000); - - /* Power it back up */ - ac97_codec_write(codec, AC97_POWER_CONTROL, dacp); - - jz_audio_rate = rate; - jz_audio_k = STANDARD_SPEED / rate; - if (rate * jz_audio_k != STANDARD_SPEED) - jz_audio_q = rate / ((STANDARD_SPEED / jz_audio_k) - rate ); - else - jz_audio_q = 0x1fffffff; /* a very big value, don't compensate */ - - switch (rate) { - case 8000: - f_scale_count = f_scale_counts[0]; - f_scale_array = k_8000; - f_scale_reload = reload_8000; - break; - case 11025: - f_scale_count = f_scale_counts[1]; - f_scale_array = k_11025; - f_scale_reload = reload_11025; - break; - case 16000: - f_scale_count = f_scale_counts[2]; - f_scale_array = k_16000; - f_scale_reload = reload_16000; - break; - case 22050: - f_scale_count = f_scale_counts[3]; - f_scale_array = k_22050; - f_scale_reload = reload_22050; - break; - case 24000: - f_scale_count = f_scale_counts[4]; - f_scale_array = k_24000; - f_scale_reload = reload_24000; - break; - case 32000: - f_scale_count = f_scale_counts[5]; - f_scale_array = k_32000; - f_scale_reload = reload_32000; - break; - case 44100: - f_scale_count = f_scale_counts[6]; - f_scale_array = k_44100; - f_scale_reload = reload_44100; - break; - case 48000: - f_scale_count = f_scale_counts[7]; - f_scale_array = k_48000; - f_scale_reload = reload_48000; - break; - } - f_scale_idx = 0; - - return jz_audio_rate; -} - -static int record_fill_1x8_u(unsigned long dst_start, int count, int id) -{ - int cnt = 0; - unsigned char data; - volatile unsigned char *s = (unsigned char *)(*(in_dma_buf + id)); - volatile unsigned char *dp = (unsigned char *)dst_start; - - while (count > 0) { - count -= 2; /* count in dword */ - if ((jz_audio_count++ % jz_audio_k) == 0) { - cnt++; - data = *(s++); - *(dp ++) = data + 0x80; - s++; /* skip the other channel */ - } else { - s += 2; /* skip the redundancy */ - } - if (jz_audio_count - last_jz_audio_count >= jz_audio_q) { - jz_audio_count++; - last_jz_audio_count = jz_audio_count; - count -= 2; - s += 2; - } - } - return cnt; -} - -static int record_fill_2x8_u(unsigned long dst_start, int count, int id) -{ - int cnt = 0; - unsigned char d1, d2; - volatile unsigned char *s = (unsigned char *)(*(in_dma_buf + id)); - volatile unsigned char *dp = (unsigned char *)dst_start; - - while (count > 0) { - count -= 2; - if ((jz_audio_count++ % jz_audio_k) == 0) { - cnt += 2; - d1 = *(s++); - *(dp ++) = d1 + 0x80; - d2 = *(s++); - *(dp ++) = d2 + 0x80; - } else { - s += 2; /* skip the redundancy */ - } - if (jz_audio_count - last_jz_audio_count >= jz_audio_q * 2) { - jz_audio_count += 2; - last_jz_audio_count = jz_audio_count; - count -= 2; - s += 2; - } - } - return cnt; -} - -static int record_fill_1x16_s(unsigned long dst_start, int count, int id) -{ - int cnt = 0; - unsigned short d1; - unsigned short *s = (unsigned short *)(*(in_dma_buf + id)); - unsigned short *dp = (unsigned short *)dst_start; - - while (count > 0) { - count -= 2; /* count in dword */ - if ((jz_audio_count++ % jz_audio_k) == 0) { - cnt += 2; /* count in byte */ - d1 = *(s++); - *(dp ++) = d1; - s++; /* skip the other channel */ - } else { - s += 2; /* skip the redundancy */ - } - if (jz_audio_count - last_jz_audio_count >= jz_audio_q * 2) { - jz_audio_count += 2; - last_jz_audio_count = jz_audio_count; - count -= 2; - s += 2; - } - } - return cnt; -} - -static int record_fill_2x16_s(unsigned long dst_start, int count, int id) -{ - int cnt = 0; - unsigned short d1, d2; - unsigned short *s = (unsigned short *)(*(in_dma_buf + id)); - unsigned short *dp = (unsigned short *)dst_start; - - while (count > 0) { - count -= 2; /* count in dword */ - if ((jz_audio_count++ % jz_audio_k) == 0) { - cnt += 4; /* count in byte */ - d1 = *(s++); - *(dp ++) = d1; - d2 = *(s++); - *(dp ++) = d2; - } else - s += 2; /* skip the redundancy */ - - if (jz_audio_count - last_jz_audio_count >= jz_audio_q * 4) { - jz_audio_count += 4; - last_jz_audio_count = jz_audio_count; - count -= 2; - s += 2; - } - } - return cnt; -} - - -static void replay_fill_1x8_u(unsigned long src_start, int count, int id) -{ - int i, cnt = 0; - unsigned char data; - unsigned char *s = (unsigned char *)src_start; - unsigned char *dp = (unsigned char *)(*(out_dma_buf + id)); - - while (count > 0) { - count--; - jz_audio_count++; - cnt += jz_audio_k; - data = *(s++) - 0x80; - for (i=0;i 0) { - count -= 2; - jz_audio_count += 2; - cnt += 2 * jz_audio_k; - d1 = *(s++) - 0x80; - d2 = *(s++) - 0x80; - for (i=0;i= jz_audio_q * 2) { - cnt += 2 * jz_audio_k; - last_jz_audio_count = jz_audio_count; - for (i=0;i= 0) { - if (f_scale_reload[f_scale_idx]) { - d1 = d2; - d2 = *s++; - if (!count) - break; - count -= 2; - } - d = d1 + (((d2 - d1) * f_scale_array[f_scale_idx]) >> 8); - *dp++ = d; - *dp++ = d; - cnt += 4; - f_scale_idx ++; - if (f_scale_idx >= f_scale_count) - f_scale_idx = 0; - } - *(out_dma_buf_data_count + id) = cnt; -} - -static void replay_fill_2x16_s(unsigned long src_start, int count, int id) -{ - int cnt = 0; - static short d11, d12, d21, d22, d1, d2; - short *s = (short *)src_start; - short *dp = (short *)(*(out_dma_buf + id)); - - d12 = *s++; - d22 = *s++; - count -= 4; - while (count >= 0) { - register unsigned int kvalue; - kvalue = f_scale_array[f_scale_idx]; - if (f_scale_reload[f_scale_idx]) { - d11 = d12; - d12 = *s++; - d21 = d22; - d22 = *s++; - if (!count) - break; - count -= 4; - } - d1 = d11 + (((d12 - d11)*kvalue) >> 8); - d2 = d21 + (((d22 - d21)*kvalue) >> 8); - *dp++ = d1; - *dp++ = d2; - cnt += 4; - f_scale_idx ++; - if (f_scale_idx >= f_scale_count) - f_scale_idx = 0; - } - *(out_dma_buf_data_count + id) = cnt; -} - -static unsigned int jz_audio_set_format(int dev, unsigned int fmt) -{ - switch (fmt) { - case AFMT_U8: - case AFMT_S16_LE: - jz_audio_format = fmt; - jz_update_filler(fmt, jz_audio_channels); - case AFMT_QUERY: - break; - } - return jz_audio_format; -} - -static short jz_audio_set_channels(int dev, short channels) -{ - switch (channels) { - case 1: - __ac97_set_xs_stereo(); // always stereo when recording - __ac97_set_rs_stereo(); // always stereo when recording - jz_audio_channels = channels; - jz_update_filler(jz_audio_format, jz_audio_channels); - break; - case 2: - __ac97_set_xs_stereo(); - __ac97_set_rs_stereo(); - jz_audio_channels = channels; - jz_update_filler(jz_audio_format, jz_audio_channels); - break; - case 0: - break; - } - return jz_audio_channels; -} - - -static void jz_audio_reset(void) -{ - __ac97_disable_replay(); - __ac97_disable_receive_dma(); - __ac97_disable_record(); - __ac97_disable_transmit_dma(); -} - -static int jz_audio_release(struct inode *inode, struct file *file); -static int jz_audio_open(struct inode *inode, struct file *file); -static int jz_audio_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); -static unsigned int jz_audio_poll(struct file *file, - struct poll_table_struct *wait); -static ssize_t jz_audio_write(struct file *file, const char *buffer, - size_t count, loff_t *ppos); -static ssize_t jz_audio_read(struct file *file, char *buffer, - size_t count, loff_t *ppos); - -/* static struct file_operations jz_ac97_audio_fops */ -static struct file_operations jz_ac97_audio_fops = -{ - owner: THIS_MODULE, - open: jz_audio_open, - release: jz_audio_release, - write: jz_audio_write, - read: jz_audio_read, - poll: jz_audio_poll, - ioctl: jz_audio_ioctl -}; - -/* Read / Write AC97 codec registers */ -static inline int jz_out_command_ready(void) -{ - int t2 = 1000; - int done = 0; - - while (! done && t2-- > 0) { - if (REG32(AC97_ACSR) & AIC_ACSR_CADT) { - REG32(AC97_ACSR) &= ~AIC_ACSR_CADT; - done = 1; - } - else - udelay (1); - } - return done; -} - -static inline int jz_in_status_ready(void) -{ - int t2 = 1000; - int done = 0; - - while (! done && t2-- > 0) { - if (REG32(AC97_ACSR) & AIC_ACSR_SADR) { - REG32(AC97_ACSR) &= ~AIC_ACSR_SADR; - done = 1; - } - else { - if (REG32(AC97_ACSR) & AIC_ACSR_RSTO) { - REG32(AC97_ACSR) &= ~AIC_ACSR_RSTO; - printk(KERN_DEBUG "%s: RSTO receive status timeout.\n", - __FUNCTION__); - done = 0; - break; - } - udelay (1); - } - } - return done; -} - -static int jz_readAC97Reg (struct ac97_codec *dev, u8 reg) -{ - u16 value; - - if (reg < 128) { - u8 ret_reg; - __ac97_out_rcmd_addr(reg);//output read addr - if (jz_out_command_ready())//judge if send completely? - while (jz_in_status_ready()) {//judge if receive completely? - ret_reg = __ac97_in_status_addr();//slot1:send addr - value = __ac97_in_data(); - if (ret_reg == reg) - return value; - else { -// printk(KERN_DEBUG "%s: index (0x%02x)->(0x%02x) 0x%x\n", __FUNCTION__, reg, ret_reg, value); - return -EINVAL; - } - } - } - value = __ac97_in_data(); - printk (KERN_DEBUG "timeout while reading AC97 codec (0x%x)\n", reg); - return -EINVAL; -} - -static u16 ac97_codec_read(struct ac97_codec *codec, u8 reg) -{ - int res = jz_readAC97Reg(codec, reg); - int count = 0; - while (res == -EINVAL) { - udelay(1000); - __ac97_warm_reset_codec(); - udelay(1000); - res = jz_readAC97Reg(codec, reg); - count ++; - if (count > MAX_RETRY){ - printk(KERN_WARNING"After try %d when read AC97 codec 0x%x, can't success, give up operate!!\n", - MAX_RETRY, reg); - break; - } - } - return (u16)res; -} - -static int jz_writeAC97Reg (struct ac97_codec *dev, u8 reg, u16 value) -{ - //unsigned long flags; - int done = 0; - - //save_and_cli(flags); - - __ac97_out_wcmd_addr(reg); - __ac97_out_data(value); - if (jz_out_command_ready()) - done = 1; - else - printk (KERN_DEBUG "Tiemout AC97 codec write (0x%X<==0x%X)\n", reg, value); - //restore_flags(flags); - return done; -} -static void ac97_codec_write(struct ac97_codec *codec, u8 reg, u16 data) -{ - int done = jz_writeAC97Reg(codec, reg, data); - int count = 0; - while (done == 0) { - count ++; - udelay (2000); - __ac97_warm_reset_codec(); - udelay(2000); - done = jz_writeAC97Reg(codec, reg, data); - if ( count > MAX_RETRY ){ - printk (KERN_DEBUG " After try %d when write AC97 codec (0x%x), can't sucess, give up!! \n", - MAX_RETRY, reg); - break; - } - } -} - -/* OSS /dev/mixer file operation methods */ - -static int jz_ac97_open_mixdev(struct inode *inode, struct file *file) -{ - int i; - int minor = MINOR(inode->i_rdev); - struct jz_ac97_controller_info *controller = ac97_controller; - - for (i = 0; i < NR_AC97; i++) - if (controller->ac97_codec[i] != NULL && - controller->ac97_codec[i]->dev_mixer == minor) - goto match; - - if (!controller) - return -ENODEV; - - match: - file->private_data = controller->ac97_codec[i]; - - return 0; -} - -static int jz_ac97_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct ac97_codec *codec = (struct ac97_codec *)file->private_data; - - return codec->mixer_ioctl(codec, cmd, arg); -} - -static loff_t jz_ac97_llseek(struct file *file, loff_t offset, int origin) -{ - return -ESPIPE; -} - -static /*const*/ struct file_operations jz_ac97_mixer_fops = { - owner: THIS_MODULE, - llseek: jz_ac97_llseek, - ioctl: jz_ac97_ioctl_mixdev, - open: jz_ac97_open_mixdev, -}; - -/* AC97 codec initialisation. */ -static int __init jz_ac97_codec_init(struct jz_ac97_controller_info *controller) -{ - int num_ac97 = 0; - int ready_2nd = 0; - struct ac97_codec *codec; - unsigned short eid; - int i = 0; - - if (__ac97_codec_is_low_power_mode()) { - printk(KERN_DEBUG "AC97 codec is low power mode, warm reset ...\n"); - __ac97_warm_reset_codec(); - udelay(10); - } - i = 0; - while (!__ac97_codec_is_ready()) { - i++; - if ( i > 100 ) { - printk(KERN_WARNING "AC97 codec not ready, failed init ..\n"); - return -ENODEV; - } - udelay(10); - } - i = 0; - - /* Reset the mixer. */ - for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { - if ((codec = kmalloc(sizeof(struct ac97_codec), - GFP_KERNEL)) == NULL) - return -ENOMEM; - memset(codec, 0, sizeof(struct ac97_codec)); - - /* initialize some basic codec information, - other fields will be filled - in ac97_probe_codec */ - codec->private_data = controller; - codec->id = num_ac97; - - codec->codec_read = ac97_codec_read; - codec->codec_write = ac97_codec_write; - - if (ac97_probe_codec(codec) == 0) - break; - - eid = ac97_codec_read(codec, AC97_EXTENDED_ID); - if (eid == 0xFFFF) { - printk(KERN_WARNING "Jz AC97: no codec attached?\n"); - kfree(codec); - break; - } - - controller->ac97_features = eid; - - if (!(eid & 0x0001)) - printk(KERN_WARNING "AC97 codec: only 48Khz playback available.\n"); - else { - printk(KERN_WARNING "AC97 codec: supports variable sample rate.\n"); - /* Enable HPEN: UCB1400 only */ - ac97_codec_write(codec, 0x6a, - ac97_codec_read(codec, 0x6a) | 0x40); - - /* Enable variable rate mode */ - ac97_codec_write(codec, AC97_EXTENDED_STATUS, 9); - ac97_codec_write(codec, - AC97_EXTENDED_STATUS, - ac97_codec_read(codec, AC97_EXTENDED_STATUS) | 0xE800); - /* power up everything, modify this - when implementing power saving */ - ac97_codec_write(codec, - AC97_POWER_CONTROL, - ac97_codec_read(codec, AC97_POWER_CONTROL) & ~0x7f00); - /* wait for analog ready */ - for (i=10; i && ((ac97_codec_read(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--) { -// current->state = TASK_UNINTERRUPTIBLE; -// schedule_timeout(HZ/20); - } - - if (!(ac97_codec_read(codec, AC97_EXTENDED_STATUS) & 1)) { - printk(KERN_WARNING "Jz AC97: Codec refused to allow VRA, using 48Khz only.\n"); - controller->ac97_features &= ~1; - } - } - - if ((codec->dev_mixer = - register_sound_mixer(&jz_ac97_mixer_fops, -1)) < 0) { - printk(KERN_ERR "Jz AC97: couldn't register mixer!\n"); - kfree(codec); - break; - } - - controller->ac97_codec[num_ac97] = codec; - - /* if there is no secondary codec at all, don't probe any more */ - if (!ready_2nd) - return num_ac97+1; - } - return num_ac97; -} - -static void jz_update_filler(int format, int channels) -{ -#define TYPE(fmt,ch) (((fmt)<<3) | ((ch)&7)) /* up to 8 chans supported. */ - - - switch (TYPE(format, channels)) { - default: - - case TYPE(AFMT_U8, 1): - if ((ac97_controller->patched) && - (ac97_controller->ac97_features & 1)) { - __aic_enable_mono2stereo(); - __aic_enable_unsignadj(); - jz_set_dma_block_size(ac97_controller->dma1, 16); - jz_set_dma_block_size(ac97_controller->dma2, 16); - } else { - __aic_disable_mono2stereo(); - __aic_disable_unsignadj(); - jz_set_dma_block_size(ac97_controller->dma1, 4); - jz_set_dma_block_size(ac97_controller->dma2, 4); - } - replay_filler = replay_fill_1x8_u; - record_filler = record_fill_1x8_u; - __ac97_set_oass(8); - __ac97_set_iass(8); - jz_set_dma_dest_width(ac97_controller->dma1, 8); - jz_set_dma_src_width(ac97_controller->dma2, 8); - break; - case TYPE(AFMT_U8, 2): - if ((ac97_controller->patched) && - (ac97_controller->ac97_features & 1)) { - __aic_enable_mono2stereo(); - __aic_enable_unsignadj(); - jz_set_dma_block_size(ac97_controller->dma1, 16); - jz_set_dma_block_size(ac97_controller->dma2, 16); - } else { - __aic_disable_mono2stereo(); - __aic_disable_unsignadj(); - jz_set_dma_block_size(ac97_controller->dma1, 4); - jz_set_dma_block_size(ac97_controller->dma2, 4); - } - replay_filler = replay_fill_2x8_u; - record_filler = record_fill_2x8_u; - __ac97_set_oass(8); - __ac97_set_iass(8); - jz_set_dma_dest_width(ac97_controller->dma1, 8); - jz_set_dma_src_width(ac97_controller->dma2, 8); - break; - case TYPE(AFMT_S16_LE, 1): - if ((ac97_controller->patched) && - (ac97_controller->ac97_features & 1)) { - __aic_enable_mono2stereo(); - jz_set_dma_block_size(ac97_controller->dma1, 16); - jz_set_dma_block_size(ac97_controller->dma2, 16); - } else { - __aic_disable_mono2stereo(); - jz_set_dma_block_size(ac97_controller->dma1, 4); - jz_set_dma_block_size(ac97_controller->dma2, 4); - } - __aic_disable_unsignadj(); - replay_filler = replay_fill_1x16_s; - record_filler = record_fill_1x16_s; - __ac97_set_oass(16); - __ac97_set_iass(16); - - jz_set_dma_dest_width(ac97_controller->dma1, 16); - jz_set_dma_src_width(ac97_controller->dma2, 16); - - break; - - case TYPE(AFMT_S16_LE, 2): - if ((ac97_controller->patched) && - (ac97_controller->ac97_features & 1)) { - jz_set_dma_block_size(ac97_controller->dma1, 16); - jz_set_dma_block_size(ac97_controller->dma2, 16); - } else { - jz_set_dma_block_size(ac97_controller->dma1, 4); - jz_set_dma_block_size(ac97_controller->dma2, 4); - } - __aic_disable_mono2stereo(); - __aic_disable_unsignadj(); - replay_filler = replay_fill_2x16_s; - record_filler = record_fill_2x16_s; - __ac97_set_oass(16); - __ac97_set_iass(16); - jz_set_dma_dest_width(ac97_controller->dma1, 16); - jz_set_dma_src_width(ac97_controller->dma2, 16); - break; - } -} - -#ifdef CONFIG_PROC_FS - -extern struct proc_dir_entry *proc_jz_root; - -static int jz_ac97_init_proc(struct jz_ac97_controller_info *controller) -{ - if (!create_proc_read_entry ("ac97", 0, proc_jz_root, - ac97_read_proc, controller->ac97_codec[0])) - return -EIO; - - return 0; -} - -static void jz_ac97_cleanup_proc(struct jz_ac97_controller_info *controller) -{ -} - -#endif - -static void __init attach_jz_ac97(struct jz_ac97_controller_info *controller) -{ - char *name; - int adev; - - name = controller->name; - jz_ac97_initHw(controller); - - /* register /dev/audio ? */ - adev = register_sound_dsp(&jz_ac97_audio_fops, -1); - if (adev < 0) - goto audio_failed; - - /* initialize AC97 codec and register /dev/mixer */ - if (jz_ac97_codec_init(controller) <= 0) - goto mixer_failed; - -#ifdef CONFIG_PROC_FS - if (jz_ac97_init_proc(controller) < 0) { - printk(KERN_ERR "%s: can't create AC97 proc filesystem.\n", name); - goto proc_failed; - } -#endif - - controller->tmp1 = (void *)__get_free_pages(GFP_KERNEL, 8);//4 - if (!controller->tmp1) { - printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); - goto tmp1_failed; - } - - controller->tmp2 = (void *)__get_free_pages(GFP_KERNEL, 8);//4 - if (!controller->tmp2) { - printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); - goto tmp2_failed; - } - - if ((controller->dma1 = jz_request_dma(DMA_ID_AC97_TX, "audio dac", - jz_ac97_replay_dma_irq, - IRQF_DISABLED, controller)) < 0) { - printk(KERN_ERR "%s: can't reqeust DMA DAC channel.\n", name); - goto dma1_failed; - } - if ((controller->dma2 = jz_request_dma(DMA_ID_AC97_RX, "audio adc", - jz_ac97_record_dma_irq, - IRQF_DISABLED, controller)) < 0) { - printk(KERN_ERR "%s: can't reqeust DMA ADC channel.\n", name); - goto dma2_failed; - } - - printk("Jz On-Chip AC97 controller registered (DAC: DMA%d/IRQ%d, ADC: DMA%d/IRQ%d)\n", - controller->dma1, get_dma_done_irq(controller->dma1), - controller->dma2, get_dma_done_irq(controller->dma2)); - - old_mksound = kd_mksound; /* see vt.c */ - kd_mksound = jz_ac97_mksound; - controller->dev_audio = adev; - return; - - dma2_failed: - jz_free_dma(controller->dma1); - dma1_failed: - free_pages((unsigned long)controller->tmp2, 8);//4 - tmp2_failed: - free_pages((unsigned long)controller->tmp1, 8);//4 - tmp1_failed: -#ifdef CONFIG_PROC_FS - jz_ac97_cleanup_proc(controller); -#endif - proc_failed: - /* unregister mixer dev */ - mixer_failed: - unregister_sound_dsp(adev); - audio_failed: - return; -} - -static int __init probe_jz_ac97(struct jz_ac97_controller_info **controller) -{ - if ((*controller = kmalloc(sizeof(struct jz_ac97_controller_info), - GFP_KERNEL)) == NULL) { - printk(KERN_ERR "Jz AC97 Controller: out of memory.\n"); - return -ENOMEM; - } - memset( *controller, 0, sizeof(struct jz_ac97_controller_info) ); - (*controller)->name = "Jz AC97 controller"; - (*controller)->opened1 = 0; - (*controller)->opened2 = 0; - - init_waitqueue_head(&(*controller)->adc_wait); - init_waitqueue_head(&(*controller)->dac_wait); - spin_lock_init(&(*controller)->lock); - init_waitqueue_head(&rx_wait_queue); - init_waitqueue_head(&tx_wait_queue); - - return 0; -} - -static void __exit unload_jz_ac97(struct jz_ac97_controller_info *controller) -{ - int adev = controller->dev_audio; - - jz_ac97_full_reset (controller); - - controller->dev_audio = -1; - - if (old_mksound) - kd_mksound = old_mksound; /* Our driver support bell for kb, see vt.c */ - -#ifdef CONFIG_PROC_FS - jz_ac97_cleanup_proc(controller); -#endif - - jz_free_dma(controller->dma1); - jz_free_dma(controller->dma2); - - free_pages((unsigned long)controller->tmp1, 8);//4 - free_pages((unsigned long)controller->tmp2, 8);//4 - - if (adev >= 0) { - //unregister_sound_mixer(audio_devs[adev]->mixer_dev); - unregister_sound_dsp(controller->dev_audio); - } -} - -#ifdef CONFIG_PM - -static int reserve_mastervol, reserve_micvol; -static int reserve_power1, reserve_power2; -static int reserve_power3, reserve_power4; -static int reserve_power5, reserve_power6; - -static int jz_ac97_suspend(struct jz_ac97_controller_info *controller, int state) -{ - struct ac97_codec *codec = controller->ac97_codec[0]; - - /* save codec states */ - reserve_mastervol = ac97_codec_read(codec, 0x0002); - reserve_micvol = ac97_codec_read(codec, 0x000e); - - reserve_power1 = ac97_codec_read(codec, 0x0026); - reserve_power2 = ac97_codec_read(codec, 0x006c); - reserve_power3 = ac97_codec_read(codec, 0x005c); - reserve_power4 = ac97_codec_read(codec, 0x0064); - reserve_power5 = ac97_codec_read(codec, 0x0066); - reserve_power6 = ac97_codec_read(codec, 0x006a); - - /* put codec into power-saving mode */ - ac97_codec_write(codec, 0x5c, 0xffff); - ac97_codec_write(codec, 0x64, 0x0000); - ac97_codec_write(codec, 0x66, 0x0000); - ac97_codec_write(codec, 0x6a, 0x0000); - - ac97_codec_write(codec, 0x6c, 0x0030); - ac97_codec_write(codec, 0x26, 0x3b00); - - ac97_save_state(codec); - __ac97_disable(); - - return 0; -} - -static int jz_ac97_resume(struct jz_ac97_controller_info *controller) -{ - struct ac97_codec *codec = controller->ac97_codec[0]; - - jz_ac97_full_reset(controller); - ac97_probe_codec(codec); - ac97_restore_state(codec); - - ac97_codec_write(codec, 0x0026, reserve_power1); - ac97_codec_write(codec, 0x006c, reserve_power2); - ac97_codec_write(codec, 0x005c, reserve_power3); - ac97_codec_write(codec, 0x0064, reserve_power4); - ac97_codec_write(codec, 0x0066, reserve_power5); - ac97_codec_write(codec, 0x006a, reserve_power6); - - ac97_codec_write(codec, 0x0002, reserve_mastervol); - ac97_codec_write(codec, 0x000e, reserve_micvol); - - /* Enable variable rate mode */ - ac97_codec_write(codec, AC97_EXTENDED_STATUS, 9); - ac97_codec_write(codec, - AC97_EXTENDED_STATUS, - ac97_codec_read(codec, AC97_EXTENDED_STATUS) | 0xE800); - - return 0; -} - -static int jz_ac97_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -{ - int ret; - struct jz_ac97_controller_info *controller = pm_dev->data; - - if (!controller) return -EINVAL; - - switch (req) { - case PM_SUSPEND: - ret = jz_ac97_suspend(controller, (int)data); - break; - - case PM_RESUME: - ret = jz_ac97_resume(controller); - break; - default: - ret = -EINVAL; - break; - } - return ret; -} -#endif /* CONFIG_PM */ - -static int __init init_jz_ac97(void) -{ - int errno; - - if ((errno = probe_jz_ac97(&ac97_controller)) < 0) - return errno; - attach_jz_ac97(ac97_controller); - - out_empty_queue.id = NULL; - out_full_queue.id = NULL; - out_busy_queue.id = NULL; - - in_empty_queue.id = NULL; - in_full_queue.id = NULL; - in_busy_queue.id = NULL; - -#ifdef CONFIG_PM - ac97_controller->pm = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, - jz_ac97_pm_callback); - if (ac97_controller->pm) - ac97_controller->pm->data = ac97_controller; -#endif - - return 0; -} - -static void __exit cleanup_jz_ac97(void) -{ - unload_jz_ac97(ac97_controller); -} - -module_init(init_jz_ac97); -module_exit(cleanup_jz_ac97); - - -static int drain_adc(struct jz_ac97_controller_info *ctrl, int nonblock) -{ - DECLARE_WAITQUEUE(wait, current); - unsigned long flags; - int count; - unsigned tmo; - - add_wait_queue(&ctrl->adc_wait, &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - spin_lock_irqsave(&ctrl->lock, flags); - count = get_dma_residue(ctrl->dma2); - spin_unlock_irqrestore(&ctrl->lock, flags); - if (count <= 0) - break; - - if (signal_pending(current)) - break; - if (nonblock) { - remove_wait_queue(&ctrl->adc_wait, &wait); - current->state = TASK_RUNNING; - return -EBUSY; - } - tmo = (PAGE_SIZE * HZ) / STANDARD_SPEED; - tmo *= jz_audio_k * (jz_audio_format == AFMT_S16_LE) ? 2 : 4; - tmo /= jz_audio_channels; - } - remove_wait_queue(&ctrl->adc_wait, &wait); - current->state = TASK_RUNNING; - if (signal_pending(current)) - return -ERESTARTSYS; - return 0; -} - -static int drain_dac(struct jz_ac97_controller_info *ctrl, int nonblock) -{ - DECLARE_WAITQUEUE(wait, current); - unsigned long flags; - int count; - unsigned tmo; - - add_wait_queue(&(ctrl->dac_wait), &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - spin_lock_irqsave(&ctrl->lock, flags); - count = get_dma_residue(ctrl->dma1); - spin_unlock_irqrestore(&ctrl->lock, flags); - if (count <= 0 && elements_in_queue(&out_full_queue) <= 0) - break; - if (signal_pending(current)) - break; - if (nonblock) { - remove_wait_queue(&ctrl->dac_wait, &wait); - current->state = TASK_RUNNING; - return -EBUSY; - } - tmo = (PAGE_SIZE * HZ) / STANDARD_SPEED; - tmo *= jz_audio_k * (jz_audio_format == AFMT_S16_LE) ? 2 : 4; - tmo /= jz_audio_channels; - } - remove_wait_queue(&ctrl->dac_wait, &wait); - current->state = TASK_RUNNING; - if (signal_pending(current)) - return -ERESTARTSYS; - return 0; -} - -/* - * Audio operation routines implementation - */ -static int jz_audio_release(struct inode *inode, struct file *file) -{ - struct jz_ac97_controller_info *controller = - (struct jz_ac97_controller_info *) file->private_data; - unsigned long flags; - - if (file->f_mode & FMODE_WRITE) { - controller->opened1 = 0; - drain_dac(controller, file->f_flags & O_NONBLOCK); - disable_dma(controller->dma1); - set_dma_count(controller->dma1, 0); - __ac97_disable_transmit_dma(); - __ac97_disable_replay(); - - spin_lock_irqsave(&controller->ioctllock, flags); - controller->total_bytes = 0; - controller->count = 0; - controller->finish = 0; - jz_audio_dma_tran_count = 0; - controller->blocks = 0; - controller->nextOut = 0; - spin_unlock_irqrestore(&controller->ioctllock, flags); - - } - if (file->f_mode & FMODE_READ) { - controller->opened2 = 0; - first_record_call = 1; - drain_adc(controller, file->f_flags & O_NONBLOCK); - disable_dma(controller->dma2); - set_dma_count(controller->dma2, 0); - __ac97_disable_receive_dma(); - __ac97_disable_record(); - spin_lock_irqsave(&controller->ioctllock, flags); - controller->total_bytes = 0; - jz_audio_dma_tran_count = 0; - controller->count = 0; - controller->finish = 0; - controller->blocks = 0; - controller->nextIn = 0; - spin_unlock_irqrestore(&controller->ioctllock, flags); - - } - Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); - return 0; -} - -static int jz_audio_open(struct inode *inode, struct file *file) -{ - struct jz_ac97_controller_info *controller= ac97_controller; - - if (controller == NULL) - return -ENODEV; - - if (file->f_mode & FMODE_WRITE) { - if (controller->opened1 == 1) - return -EBUSY; - controller->opened1 = 1; - //for ioctl - controller->total_bytes = 0; - jz_audio_dma_tran_count = 0; - controller->count = 0; - controller->finish = 0; - controller->blocks = 0; - controller->nextOut = 0; - jz_audio_set_channels(controller->dev_audio, 1); - jz_audio_set_format(controller->dev_audio, AFMT_U8); - jz_audio_set_speed(controller->dev_audio, 8000); - } - - if (file->f_mode & FMODE_READ) { - if (controller->opened2 == 1) - return -EBUSY; - controller->opened2 = 1; - first_record_call = 1; - printk(KERN_DEBUG "You'd better apply 48000Hz 16-bit Stereo for record.\n"); - //for ioctl - controller->total_bytes = 0; - jz_audio_dma_tran_count = 0; - controller->count = 0; - controller->finish = 0; - controller->blocks = 0; - controller->nextIn = 0; - jz_audio_set_channels(controller->dev_audio, 2); - jz_audio_set_format(controller->dev_audio, AFMT_S16_LE); - jz_audio_set_speed(controller->dev_audio, 48000); - } - - last_jz_audio_count = jz_audio_count = 0; - file->private_data = controller; - - jz_audio_fragsize = 8 * PAGE_SIZE; - jz_audio_fragstotal = 4; - Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); - return 0; -} - -static int jz_audio_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct jz_ac97_controller_info *controller = - (struct jz_ac97_controller_info *) file->private_data; - int val=0,fullc,busyc,unfinish; - unsigned int flags; - count_info cinfo; - - switch (cmd) - { - case OSS_GETVERSION: - return put_user(SOUND_VERSION, (int *)arg); - - case SNDCTL_DSP_RESET: - jz_audio_reset(); - return 0; - - case SNDCTL_DSP_SYNC: - if (file->f_mode & FMODE_WRITE) - return drain_dac(controller, file->f_flags & O_NONBLOCK); - return 0; - - case SNDCTL_DSP_SPEED: /* set smaple rate */ - { - if (get_user(val, (int *)arg)) - return -EFAULT; - if (val >= 0) - jz_audio_set_speed(controller->dev_audio, val); - return put_user(val, (int *)arg); - } - - case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ - if (get_user(val, (int *)arg)) - return -EFAULT; - jz_audio_set_channels(controller->dev_audio, val ? 2 : 1); - return 0; - - case SNDCTL_DSP_GETBLKSIZE: - //return put_user(4*PAGE_SIZE, (int *)arg); - return put_user(jz_audio_fragsize , (int *)arg); - - case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/ - return put_user(AFMT_U8 | AFMT_S16_LE, (int *)arg); - - case SNDCTL_DSP_SETFMT: /* Select sample format */ - if (get_user(val, (int *)arg)) - return -EFAULT; - - if (val != AFMT_QUERY) { - jz_audio_set_format(controller->dev_audio,val); - } else { - if (file->f_mode & FMODE_READ) - val = (jz_audio_format == 16) ? - AFMT_S16_LE : AFMT_U8; - else - val = (jz_audio_format == 16) ? - AFMT_S16_LE : AFMT_U8; - } - return put_user(val, (int *)arg); - - case SNDCTL_DSP_CHANNELS: - if (get_user(val, (int *)arg)) - return -EFAULT; - jz_audio_set_channels(controller->dev_audio, val); - return put_user(val, (int *)arg); - - case SNDCTL_DSP_POST: - /* FIXME: the same as RESET ?? */ - return 0; - - case SNDCTL_DSP_SUBDIVIDE: - return 0; - - case SNDCTL_DSP_SETFRAGMENT: - if(out_dma_buf || in_dma_buf) - return -EBUSY; - get_user(val, (long *) arg); - jz_audio_fragsize = 1 << (val & 0xFFFF);//16 least bits - - if (jz_audio_fragsize < 4 * PAGE_SIZE) - jz_audio_fragsize = 4 * PAGE_SIZE; - if (jz_audio_fragsize > (16 * PAGE_SIZE)) //16 PAGE_SIZE - jz_audio_fragsize = 16 * PAGE_SIZE; - jz_audio_fragstotal = (val >> 16) & 0x7FFF; - if (jz_audio_fragstotal < 2) - jz_audio_fragstotal = 2; - if (jz_audio_fragstotal > 32) - jz_audio_fragstotal = 32; - - Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); - return 0; - - case SNDCTL_DSP_GETCAPS: - return put_user(DSP_CAP_REALTIME|DSP_CAP_BATCH, (int *)arg); - - case SNDCTL_DSP_NONBLOCK: - file->f_flags |= O_NONBLOCK; - return 0; - - case SNDCTL_DSP_SETDUPLEX: - return -EINVAL; - - case SNDCTL_DSP_GETOSPACE: - { - audio_buf_info abinfo; - int i, bytes = 0; - - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - //unused fragment amount - spin_lock_irqsave(&controller->ioctllock, flags); - jz_audio_fragments = elements_in_queue(&out_empty_queue); - for (i = 0; i < jz_audio_fragments; i++) - bytes += jz_audio_fragsize; - bytes /= jz_audio_k; - spin_unlock_irqrestore(&controller->ioctllock, flags); - //bytes /= jz_audio_b; - abinfo.fragments = jz_audio_fragments; - abinfo.fragstotal = jz_audio_fragstotal; - abinfo.fragsize = jz_audio_fragsize; - abinfo.bytes = bytes; - return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; - } - - case SNDCTL_DSP_GETISPACE: - { - audio_buf_info abinfo; - int i, bytes = 0; - - if (!(file->f_mode & FMODE_READ)) - return -EINVAL; - //unused fragment amount - jz_audio_fragments = elements_in_queue(&in_empty_queue); - for (i = 0; i < jz_audio_fragments; i++) - bytes += jz_audio_fragsize; - - abinfo.fragments = jz_audio_fragments; - abinfo.fragstotal = jz_audio_fragstotal; - abinfo.fragsize = jz_audio_fragsize; - abinfo.bytes = bytes; - return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; - } - case SNDCTL_DSP_GETTRIGGER: - val = 0; - if (file->f_mode & FMODE_READ && in_dma_buf) //record is at working - val |= PCM_ENABLE_INPUT; - if (file->f_mode & FMODE_WRITE && out_dma_buf) //playback is at working - val |= PCM_ENABLE_OUTPUT; - return put_user(val, (int *)arg); - - case SNDCTL_DSP_SETTRIGGER: - if (get_user(val, (int *)arg)) - return -EFAULT; - /*if (file->f_mode & FMODE_READ) { - if (val & PCM_ENABLE_INPUT) { - if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) - return ret; - start_adc(state); - } else - stop_adc(state); - } - if (file->f_mode & FMODE_WRITE) { - if (val & PCM_ENABLE_OUTPUT) { - if (!dmabuf->ready && (ret = prog_dmabuf(state, 0))) - return ret; - start_dac(state); - } else - stop_dac(state); - }*/ - return 0; - - case SNDCTL_DSP_GETIPTR: - if (!(file->f_mode & FMODE_READ)) - return -EINVAL; - - spin_lock_irqsave(&controller->ioctllock, flags); - //controller->total_bytes += get_dma_residue(controller->dma2); - cinfo.bytes = controller->total_bytes; - cinfo.blocks = controller->blocks; - cinfo.ptr = controller->nextIn; - controller->blocks = 0; - spin_unlock_irqrestore(&controller->ioctllock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); - - case SNDCTL_DSP_GETOPTR: - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - - spin_lock_irqsave(&controller->ioctllock, flags); - //controller->total_bytes += get_dma_residue(controller->dma1); - cinfo.bytes = controller->total_bytes; - cinfo.blocks = controller->blocks; - cinfo.ptr = controller->nextOut; - controller->blocks = 0; - spin_unlock_irqrestore(&controller->ioctllock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); - - case SNDCTL_DSP_GETODELAY: - { - int id, i; - - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - spin_lock_irqsave(&controller->ioctllock, flags); - unfinish = 0; - fullc = elements_in_queue(&out_full_queue); - busyc = elements_in_queue(&out_busy_queue); - - for(i = 0;i < fullc ;i ++) - { - id = *(out_full_queue.id + i); - unfinish += *(out_dma_buf_data_count + id); - } - for(i = 0;i < busyc ;i ++) - { - id = *(out_busy_queue.id + i); - unfinish += get_dma_residue(controller->dma1); - } - spin_unlock_irqrestore(&controller->ioctllock, flags); - unfinish /= jz_audio_k;//jz_audio_k is jz_audio_b - return put_user(val, (int *)arg); - } - case SOUND_PCM_READ_RATE: - return put_user(jz_audio_rate, (int *)arg); - case SOUND_PCM_READ_CHANNELS: - return put_user(jz_audio_channels, (int *)arg); - case SOUND_PCM_READ_BITS: - return put_user((jz_audio_format & (AFMT_S8 | AFMT_U8)) ? 8 : 16, (int *)arg); - case SNDCTL_DSP_MAPINBUF: - case SNDCTL_DSP_MAPOUTBUF: - case SNDCTL_DSP_SETSYNCRO: - case SOUND_PCM_WRITE_FILTER: - case SOUND_PCM_READ_FILTER: - return -EINVAL; - } - return -EINVAL; -} - -static unsigned int jz_audio_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct jz_ac97_controller_info *controller = - (struct jz_ac97_controller_info *) file->private_data; - unsigned long flags; - unsigned int mask = 0; - - if (file->f_mode & FMODE_WRITE) { - if (elements_in_queue(&out_empty_queue) > 0) - return POLLOUT | POLLWRNORM; - poll_wait(file, &controller->dac_wait, wait); - } - if (file->f_mode & FMODE_READ) { - if (elements_in_queue(&in_full_queue) > 0) - return POLLIN | POLLRDNORM; - poll_wait(file, &controller->adc_wait, wait); - } - spin_lock_irqsave(&controller->lock, flags); - if (file->f_mode & FMODE_WRITE) { - if (elements_in_queue(&out_empty_queue) > 0) - mask |= POLLOUT | POLLWRNORM; - } - else if (file->f_mode & FMODE_READ) { - if (elements_in_queue(&in_full_queue) > 0) - mask |= POLLIN | POLLRDNORM; - } - spin_unlock_irqrestore(&controller->lock, flags); - return mask; -} - -static ssize_t jz_audio_read(struct file *file, char *buffer, - size_t count, loff_t *ppos) -{ - struct jz_ac97_controller_info *controller = - (struct jz_ac97_controller_info *) file->private_data; - int id, ret = 0, left_count, copy_count, cnt = 0; - unsigned long flags; - - if (count < 0) - return -EINVAL; - - spin_lock_irqsave(&controller->ioctllock, flags); - controller->nextIn = 0; - spin_unlock_irqrestore(&controller->ioctllock, flags); - Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); - - if (count < 2*PAGE_SIZE / jz_audio_k) { - copy_count = count * 16 / (jz_audio_channels * jz_audio_format); - } else - copy_count = ((2*PAGE_SIZE / jz_audio_k + 3) / 4) * 4; - left_count = count; - - if (first_record_call) { - first_record_call = 0; - if ((id = get_buffer_id(&in_empty_queue)) >= 0) { - put_buffer_id(&in_busy_queue, id); - *(in_dma_buf_data_count + id) = copy_count * (jz_audio_format/8); - __ac97_enable_receive_dma(); - __ac97_enable_record(); - audio_start_dma(controller->dma2,file->private_data, - *(in_dma_pbuf + id), - *(in_dma_buf_data_count + id), - DMA_MODE_READ); - interruptible_sleep_on(&rx_wait_queue); - } else - BUG(); - } - - while (left_count > 0) { - if (elements_in_queue(&in_full_queue) <= 0) { - if (file->f_flags & O_NONBLOCK) - return ret ? ret : -EAGAIN; - else - interruptible_sleep_on(&rx_wait_queue); - } - if (signal_pending(current)) - return ret ? ret: -ERESTARTSYS; - - if ((id = get_buffer_id(&in_full_queue)) >= 0) { - cnt = record_filler((unsigned long)controller->tmp2+ret, copy_count, id); - put_buffer_id(&in_empty_queue, id); - } else - BUG(); - - if (elements_in_queue(&in_busy_queue) == 0) { - if ((id=get_buffer_id(&in_empty_queue)) >= 0) { - put_buffer_id(&in_busy_queue, id); - *(in_dma_buf_data_count + id) = copy_count * (jz_audio_format/8); - __ac97_enable_receive_dma(); - __ac97_enable_record(); - audio_start_dma(controller->dma2,file->private_data, - *(in_dma_pbuf + id), - *(in_dma_buf_data_count + id), - DMA_MODE_READ); - } - } - - if (ret + cnt > count) - cnt = count - ret; - - if (copy_to_user(buffer+ret, controller->tmp2+ret, cnt)) - return ret ? ret : -EFAULT; - - ret += cnt; - spin_lock_irqsave(&controller->ioctllock, flags); - controller->nextIn += ret; - spin_unlock_irqrestore(&controller->ioctllock, flags); - left_count -= cnt; - } - if (ret != count) - printk(KERN_DEBUG "%s: count=%d ret=%d jz_audio_count=%d\n", - __FUNCTION__, count, ret, jz_audio_count); - return ret; -} - -static ssize_t jz_audio_write(struct file *file, const char *buffer, - size_t count, loff_t *ppos) -{ - struct jz_ac97_controller_info *controller = - (struct jz_ac97_controller_info *) file->private_data; - int id, ret = 0, left_count, copy_count; - unsigned int flags; - - if (count <= 0) - return -EINVAL; - - spin_lock_irqsave(&controller->ioctllock, flags); - controller->nextOut = 0; - spin_unlock_irqrestore(&controller->ioctllock, flags); - Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); - - /* The data buffer size of the user space is always a PAGE_SIZE - * scale, so the process can be simplified. - */ - - if ((ac97_controller->patched) && (ac97_controller->ac97_features & 1)) - copy_count = count; - else { - if (count < 2*PAGE_SIZE / jz_audio_k) - copy_count = count; - else - copy_count = ((2*PAGE_SIZE / jz_audio_k + 3) / 4) * 4; - } - left_count = count; - - if (!(ac97_controller->patched) || !(ac97_controller->ac97_features & 1)) { - if (copy_from_user(controller->tmp1, buffer, count)) { - printk(KERN_DEBUG "%s: copy_from_user failed.\n", __FUNCTION__); - return ret ? ret : -EFAULT; - } - } - - while (left_count > 0) { - if (elements_in_queue(&out_empty_queue) == 0) { - if (file->f_flags & O_NONBLOCK) - return ret; - else - interruptible_sleep_on(&tx_wait_queue); - } - - if (signal_pending(current)) - return ret ? ret : -ERESTARTSYS; - - /* the end fragment size in this write */ - if (ret + copy_count > count) - copy_count = count - ret; - - if ((id = get_buffer_id(&out_empty_queue)) >= 0) { - if ((ac97_controller->patched) && - (ac97_controller->ac97_features & 1)) { - if (copy_from_user((char *)(*(out_dma_buf + id)), buffer+ret, copy_count)) { - printk(KERN_DEBUG "%s: copy_from_user failed.\n", __FUNCTION__); - return ret ? ret : -EFAULT; - } - *(out_dma_buf_data_count + id) = copy_count; - } else - replay_filler( - (unsigned long)controller->tmp1 + ret, - copy_count, id); - //when 0,kernel will panic - if(*(out_dma_buf_data_count + id) > 0) { - put_buffer_id(&out_full_queue, id); - dma_cache_wback_inv(*(out_dma_buf + id), *(out_dma_buf_data_count + id)); - } else {//when 0,i need refill in empty queue - put_buffer_id(&out_empty_queue, id); - } - } else - BUG(); - left_count = left_count - copy_count; - ret += copy_count; - - spin_lock_irqsave(&controller->ioctllock, flags); - controller->nextOut += ret; - spin_unlock_irqrestore(&controller->ioctllock, flags); - - if (elements_in_queue(&out_busy_queue) == 0) { - if ((id=get_buffer_id(&out_full_queue)) >= 0) { - put_buffer_id(&out_busy_queue, id); - - __ac97_enable_transmit_dma(); - __ac97_enable_replay(); - if(*(out_dma_buf_data_count + id) > 0) { - audio_start_dma(controller->dma1,file->private_data, - *(out_dma_pbuf + id), - *(out_dma_buf_data_count + id), - DMA_MODE_WRITE); - } - } - } - } - - if (ret != count) - printk(KERN_DEBUG "%s: count=%d ret=%d jz_audio_count=%d\n", - __FUNCTION__, count, ret, jz_audio_count); - return ret; -} - -/* this function for the other codec function */ -struct ac97_codec * find_ac97_codec(void) -{ - if ( ac97_controller ) - return ac97_controller->ac97_codec[0]; - return 0; - -} - diff --git a/target/linux/xburst/files-2.6.27/sound/oss/jz_i2s.c b/target/linux/xburst/files-2.6.27/sound/oss/jz_i2s.c deleted file mode 100755 index dcd3e939c..000000000 --- a/target/linux/xburst/files-2.6.27/sound/oss/jz_i2s.c +++ /dev/null @@ -1,2908 +0,0 @@ -/* - * linux/drivers/sound/Jz_i2s.c - * - * JzSOC On-Chip I2S audio driver. - * - * Copyright (C) 2005 by Junzheng Corp. - * Modified by cjfeng on Aug 9,2007,and not any bug on Jz4730 using - * dma channel 4&3,noah is tested. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Because the normal application of AUDIO devices are focused on Little_endian, - * then we only perform the little endian data format in driver. - * - */ - -#include -#include -#include -//#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sound_config.h" - -#if defined(CONFIG_I2S_DLV) -#include "jzdlv.h" -#endif - -#define DPRINTK(args...) printk(args) -#define DMA_ID_I2S_TX DMA_ID_AIC_TX -#define DMA_ID_I2S_RX DMA_ID_AIC_RX -#define NR_I2S 2 -#define JZCODEC_RW_BUFFER_SIZE 5 -#define JZCODEC_RW_BUFFER_TOTAL 4 - -#define USE_NONE 1 -#define USE_MIC 2 -#define USE_LINEIN 3 - -typedef struct hpvol_shift_s -{ - int hpvol; - int shift; -} hpvol_shift_t; - -mixer_info info; -_old_mixer_info old_info; -int codec_volue_shift; -hpvol_shift_t hpvol_shift_table[72]; -int abnormal_data_count; -unsigned long i2s_clk; - -void (*set_codec_mode)(void) = NULL; -void (*clear_codec_mode)(void) = NULL; -void (*set_codec_gpio_pin)(void) = NULL; -void (*each_time_init_codec)(void) = NULL; -int (*set_codec_startup_param)(void) = NULL; -void (*set_codec_volume_table)(void) = NULL; -void (*set_codec_record)(int mode) = NULL; -void (*set_codec_replay)(void) = NULL; -void (*set_codec_replay_record)(int mode) = NULL; -void (*turn_on_codec)(void) = NULL; -void (*turn_off_codec)(void) = NULL; -void (*set_codec_speed)(int rate) = NULL; -void (*reset_codec)(void) = NULL; -void (*codec_mixer_old_info_id_name)(void) = NULL; -void (*codec_mixer_info_id_name)(void) = NULL; -void (*set_codec_bass)(int val) = NULL; -void (*set_codec_volume)(int val) = NULL; -void (*set_codec_mic)(int val) = NULL; -void (*set_codec_line)(int val) = NULL; -void (*i2s_resume_codec)(void) = NULL; -void (*i2s_suspend_codec)(int wr,int rd) = NULL; -void (*init_codec_pin)(void) = NULL; -void (*set_codec_some_func)(void) = NULL; -void (*clear_codec_record)(void) = NULL; -void (*clear_codec_replay)(void) = NULL; -void (*set_replay_hp_or_speaker)(void) = NULL; -void (*set_codec_direct_mode)(void) = NULL; -void (*clear_codec_direct_mode)(void) = NULL; -void (*set_codec_linein2hp)(void) = NULL; -void (*clear_codec_linein2hp)(void) = NULL; - -static int jz_audio_rate; -static int jz_audio_format; -static int jz_audio_volume; -static int jz_audio_channels; -static int jz_audio_b; /* bits expand multiple */ -static int jz_audio_fragments; /* unused fragment amount */ -static int jz_audio_fragstotal; -static int jz_audio_fragsize; -static int jz_audio_speed; - -static int codec_bass_gain; -static int audio_mix_modcnt; -static int jz_audio_dma_tran_count; /* bytes count of one DMA transfer */ -#if defined(CONFIG_I2S_DLV) -int jz_mic_only = 1; -static int jz_codec_config = 0; -static unsigned long ramp_up_start; -static unsigned long ramp_up_end; -static unsigned long gain_up_start; -static unsigned long gain_up_end; -static unsigned long ramp_down_start; -static unsigned long ramp_down_end; -static unsigned long gain_down_start; -static unsigned long gain_down_end; -#endif - -static int codec_mic_gain; -static int pop_dma_flag; -static int last_dma_buffer_id; -static int drain_flag; -static int use_mic_line_flag; - -static void (*old_mksound)(unsigned int hz, unsigned int ticks); -extern void (*kd_mksound)(unsigned int hz, unsigned int ticks); -static void jz_update_filler(int bits, int channels); - -static int Init_In_Out_queue(int fragstotal,int fragsize); -static int Free_In_Out_queue(int fragstotal,int fragsize); -static irqreturn_t jz_i2s_replay_dma_irq(int irqnr, void *ref); -static irqreturn_t jz_i2s_record_dma_irq(int irqnr, void *ref); -static void (*replay_filler)(signed long src_start, int count, int id); -static int (*record_filler)(unsigned long dst_start, int count, int id); -#if defined(CONFIG_I2S_ICODEC) -static void write_mute_to_dma_buffer(signed long l_sample, signed long r_sample); -#endif -static void jz_audio_reset(void); -static struct file_operations jz_i2s_audio_fops; - -static DECLARE_WAIT_QUEUE_HEAD (rx_wait_queue); -static DECLARE_WAIT_QUEUE_HEAD (tx_wait_queue); -static DECLARE_WAIT_QUEUE_HEAD (drain_wait_queue); -static DECLARE_WAIT_QUEUE_HEAD (pop_wait_queue); - -struct jz_i2s_controller_info -{ - int io_base; - int dma1; /* for play */ - int dma2; /* for record */ - char *name; - int dev_audio; - struct i2s_codec *i2s_codec[NR_I2S]; - int opened1; - int opened2; - unsigned char *tmp1; /* tmp buffer for sample conversions */ - unsigned char *tmp2; - spinlock_t lock; - spinlock_t ioctllock; - - wait_queue_head_t dac_wait; - wait_queue_head_t adc_wait; - int nextIn; /* byte index to next-in to DMA buffer */ - int nextOut; /* byte index to next-out from DMA buffer */ - int count; /* current byte count in DMA buffer */ - int finish; /* current transfered byte count in DMA buffer */ - unsigned total_bytes; /* total bytes written or read */ - unsigned blocks; - unsigned error; /* over/underrun */ -#ifdef CONFIG_PM - struct pm_dev *pm; -#endif -}; - - -static struct jz_i2s_controller_info *i2s_controller = NULL; -struct i2s_codec -{ - /* I2S controller connected with */ - void *private_data; - char *name; - int id; - int dev_mixer; - /* controller specific lower leverl i2s accessing routines */ - u16 (*codec_read) (u8 reg); /* the function accessing Codec REGs */ - void (*codec_write) (u8 reg, u16 val); - /* Wait for codec-ready */ - void (*codec_wait) (struct i2s_codec *codec); - /* OSS mixer masks */ - int modcnt; - int supported_mixers; - int stereo_mixers; - int record_sources; - int bit_resolution; - /* OSS mixer interface */ - int (*read_mixer) (struct i2s_codec *codec, int oss_channel); - void (*write_mixer)(struct i2s_codec *codec, int oss_channel, - unsigned int left, unsigned int right); - int (*recmask_io) (struct i2s_codec *codec, int rw, int mask); - int (*mixer_ioctl)(struct i2s_codec *codec, unsigned int cmd, unsigned long arg); - /* saved OSS mixer states */ - unsigned int mixer_state[SOUND_MIXER_NRDEVICES]; -}; - - -typedef struct buffer_queue_s -{ - int count; - int *id; - int lock; -} buffer_queue_t; - -typedef struct left_right_sample_s -{ - signed long left; - signed long right; -} left_right_sample_t; - -static unsigned long pop_turn_onoff_buf; -static unsigned long pop_turn_onoff_pbuf; - -static unsigned long *out_dma_buf = NULL; -static unsigned long *out_dma_pbuf = NULL; -static unsigned long *out_dma_buf_data_count = NULL; -static unsigned long *in_dma_buf = NULL; -static unsigned long *in_dma_pbuf = NULL; -static unsigned long *in_dma_buf_data_count = NULL; - -static buffer_queue_t out_empty_queue; -static buffer_queue_t out_full_queue; -static buffer_queue_t out_busy_queue; -static buffer_queue_t in_empty_queue; -static buffer_queue_t in_full_queue; -static buffer_queue_t in_busy_queue; -static int first_record_call = 0; - -static left_right_sample_t save_last_samples[64]; - -static inline int get_buffer_id(struct buffer_queue_s *q) -{ - int r; - unsigned long flags; - int i; - - spin_lock_irqsave(&q->lock, flags); - if (q->count == 0) { - spin_unlock_irqrestore(&q->lock, flags); - return -1; - } - r = *(q->id + 0); - for (i=0;i < q->count-1;i++) - *(q->id + i) = *(q->id + (i+1)); - q->count --; - spin_unlock_irqrestore(&q->lock, flags); - - return r; -} - -static inline void put_buffer_id(struct buffer_queue_s *q, int id) -{ - unsigned long flags; - - spin_lock_irqsave(&q->lock, flags); - *(q->id + q->count) = id; - q->count ++; - spin_unlock_irqrestore(&q->lock, flags); -} - -static inline int elements_in_queue(struct buffer_queue_s *q) -{ - int r; - unsigned long flags; - - spin_lock_irqsave(&q->lock, flags); - r = q->count; - spin_unlock_irqrestore(&q->lock, flags); - - return r; -} - -static inline void audio_start_dma(int chan, void *dev_id, unsigned long phyaddr,int count, int mode) -{ - unsigned long flags; - struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; - - spin_lock_irqsave(&controller->ioctllock, flags); - jz_audio_dma_tran_count = count / jz_audio_b; - spin_unlock_irqrestore(&controller->ioctllock, flags); - flags = claim_dma_lock(); - disable_dma(chan); - clear_dma_ff(chan); -#if 1 - jz_set_oss_dma(chan, mode, jz_audio_format); -#else - set_dma_mode(chan, mode); -#endif - set_dma_addr(chan, phyaddr); - if (count == 0) { - count++; - printk("JzSOC DMA controller can't set dma 0 count!\n"); - } - set_dma_count(chan, count); - enable_dma(chan); - release_dma_lock(flags); -} - -static irqreturn_t jz_i2s_record_dma_irq (int irq, void *dev_id) -{ - int id1, id2; - unsigned long flags; - struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; - int dma = controller->dma2; - - disable_dma(dma); - if (__dmac_channel_address_error_detected(dma)) { - printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); - __dmac_channel_clear_address_error(dma); - } - if (__dmac_channel_transmit_end_detected(dma)) { - __dmac_channel_clear_transmit_end(dma); - - if(drain_flag == 1) - wake_up(&drain_wait_queue); - /* for DSP_GETIPTR */ - spin_lock_irqsave(&controller->ioctllock, flags); - controller->total_bytes += jz_audio_dma_tran_count; - controller->blocks ++; - spin_unlock_irqrestore(&controller->ioctllock, flags); - id1 = get_buffer_id(&in_busy_queue); - put_buffer_id(&in_full_queue, id1); - - wake_up(&rx_wait_queue); - wake_up(&controller->adc_wait); - if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { - put_buffer_id(&in_busy_queue, id2); - *(in_dma_buf_data_count + id2) = *(in_dma_buf_data_count + id1); - dma_cache_wback_inv(*(in_dma_buf + id2), *(in_dma_buf_data_count + id2)); - audio_start_dma(dma,dev_id, - *(in_dma_pbuf + id2), - *(in_dma_buf_data_count + id2), - DMA_MODE_READ); - } else - in_busy_queue.count = 0; - } - - return IRQ_HANDLED; -} - -static irqreturn_t jz_i2s_replay_dma_irq (int irq, void *dev_id) -{ - int id; - unsigned long flags; - struct jz_i2s_controller_info * controller = (struct jz_i2s_controller_info *) dev_id; - int dma = controller->dma1; - - disable_dma(dma); - if (__dmac_channel_address_error_detected(dma)) { - printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); - __dmac_channel_clear_address_error(dma); - } - if (__dmac_channel_transmit_end_detected(dma)) { - __dmac_channel_clear_transmit_end(dma); - - if(pop_dma_flag == 1) { - pop_dma_flag = 0; - wake_up(&pop_wait_queue); - } else { - if(drain_flag == 1) { - /* Is replay dma buffer over ? */ - if(elements_in_queue(&out_full_queue) <= 0) { - drain_flag = 0; - wake_up(&drain_wait_queue); - } - } - - /* for DSP_GETOPTR */ - spin_lock_irqsave(&controller->ioctllock, flags); - controller->total_bytes += jz_audio_dma_tran_count; - controller->blocks ++; - spin_unlock_irqrestore(&controller->ioctllock, flags); - if ((id = get_buffer_id(&out_busy_queue)) < 0) - printk(KERN_DEBUG "Strange DMA finish interrupt for I2S module\n"); - put_buffer_id(&out_empty_queue, id); - if ((id = get_buffer_id(&out_full_queue)) >= 0) { - put_buffer_id(&out_busy_queue, id); - if(*(out_dma_buf_data_count + id) > 0) { - audio_start_dma(dma, dev_id, *(out_dma_pbuf + id), - *(out_dma_buf_data_count + id), - DMA_MODE_WRITE); - last_dma_buffer_id = id; - } - } else - out_busy_queue.count = 0; - - if (elements_in_queue(&out_empty_queue) > 0) { - wake_up(&tx_wait_queue); - wake_up(&controller->dac_wait); - } - } - } - - return IRQ_HANDLED; -} - -static void jz_i2s_initHw(int set) -{ -#if defined(CONFIG_MIPS_JZ_URANUS) - i2s_clk = 48000000; -#else - i2s_clk = __cpm_get_i2sclk(); -#endif - __i2s_disable(); - if(set) - __i2s_reset(); - schedule_timeout(5); - if(each_time_init_codec) - each_time_init_codec(); - __i2s_disable_record(); - __i2s_disable_replay(); - __i2s_disable_loopback(); - __i2s_set_transmit_trigger(4); - __i2s_set_receive_trigger(3); -} - -static int Init_In_Out_queue(int fragstotal,int fragsize) -{ - int i; - - /* recording */ - in_empty_queue.count = fragstotal; - in_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - if (!in_dma_buf) - goto all_mem_err; - in_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - if (!in_dma_pbuf) - goto all_mem_err; - in_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - if (!in_dma_buf_data_count) - goto all_mem_err; - in_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!in_empty_queue.id) - goto all_mem_err; - in_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!in_full_queue.id) - goto all_mem_err; - in_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!in_busy_queue.id) - goto all_mem_err; - - for (i=0;i < fragstotal;i++) - *(in_empty_queue.id + i) = i; - in_full_queue.count = 0; - in_busy_queue.count = 0; - - for (i = 0; i < fragstotal; i++) { - *(in_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); - if (*(in_dma_buf + i) == 0) - goto mem_failed_in; - *(in_dma_pbuf + i) = virt_to_phys((void *)(*(in_dma_buf + i))); - dma_cache_wback_inv(*(in_dma_buf + i), fragsize); - } - - /* playing */ - out_empty_queue.count = fragstotal; - out_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - if (!out_dma_buf) - goto all_mem_err; - out_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - if (!out_dma_pbuf) - goto all_mem_err; - out_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - - if (!out_dma_buf_data_count) - goto all_mem_err; - out_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!out_empty_queue.id) - goto all_mem_err; - out_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!out_full_queue.id) - goto all_mem_err; - out_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!out_busy_queue.id) - goto all_mem_err; - for (i=0;i < fragstotal;i++) - *(out_empty_queue.id + i) = i; - - out_busy_queue.count = 0; - out_full_queue.count = 0; - /* alloc DMA buffer */ - for (i = 0; i < fragstotal; i++) { - *(out_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); - if (*(out_dma_buf + i) == 0) { - printk(" can't allocate required DMA(OUT) buffers.\n"); - goto mem_failed_out; - } - *(out_dma_pbuf + i) = virt_to_phys((void *)(*(out_dma_buf + i))); - } - - return 1; -all_mem_err: - printk("error:allocate memory occur error 1!\n"); - return 0; -mem_failed_out: - printk("error:allocate memory occur error 2!\n"); - for (i = 0; i < fragstotal; i++) { - if(*(out_dma_buf + i)) - free_pages(*(out_dma_buf + i), get_order(fragsize)); - } - - return 0; -mem_failed_in: - printk("error:allocate memory occur error 3!\n"); - for (i = 0; i < fragstotal; i++) { - if(*(in_dma_buf + i)) - free_pages(*(in_dma_buf + i), get_order(fragsize)); - } - return 0; -} - -static int Free_In_Out_queue(int fragstotal,int fragsize) -{ - int i; - /* playing */ - if(out_dma_buf != NULL) { - for (i = 0; i < fragstotal; i++) { - if(*(out_dma_buf + i)) - free_pages(*(out_dma_buf + i), get_order(fragsize)); - *(out_dma_buf + i) = 0; - } - kfree(out_dma_buf); - out_dma_buf = NULL; - } - if(out_dma_pbuf) { - kfree(out_dma_pbuf); - out_dma_pbuf = NULL; - } - if(out_dma_buf_data_count) { - kfree(out_dma_buf_data_count); - out_dma_buf_data_count = NULL; - } - if(out_empty_queue.id) { - kfree(out_empty_queue.id); - out_empty_queue.id = NULL; - } - if(out_full_queue.id) { - kfree(out_full_queue.id); - out_full_queue.id = NULL; - } - if(out_busy_queue.id) { - kfree(out_busy_queue.id); - out_busy_queue.id = NULL; - } - out_empty_queue.count = fragstotal; - out_busy_queue.count = 0; - out_full_queue.count = 0; - - /* recording */ - if(in_dma_buf) { - for (i = 0; i < fragstotal; i++) { - if(*(in_dma_buf + i)) { - dma_cache_wback_inv(*(in_dma_buf + i), fragsize); - free_pages(*(in_dma_buf + i), get_order(fragsize)); - } - *(in_dma_buf + i) = 0; - } - kfree(in_dma_buf); - in_dma_buf = NULL; - } - if(in_dma_pbuf) { - kfree(in_dma_pbuf); - in_dma_pbuf = NULL; - } - if(in_dma_buf_data_count) { - kfree(in_dma_buf_data_count); - in_dma_buf_data_count = NULL; - } - if(in_empty_queue.id) { - kfree(in_empty_queue.id); - in_empty_queue.id = NULL; - } - if(in_full_queue.id) { - kfree(in_full_queue.id); - in_full_queue.id = NULL; - } - if(in_busy_queue.id) { - kfree(in_busy_queue.id); - in_busy_queue.id = NULL; - } - - in_empty_queue.count = fragstotal; - in_full_queue.count = 0; - in_busy_queue.count = 0; - - return 1; -} - -static void jz_i2s_full_reset(struct jz_i2s_controller_info *controller) -{ - jz_i2s_initHw(0); -} - -static int jz_audio_set_speed(int dev, int rate) -{ - /* 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999 ? */ - jz_audio_speed = rate; -#if defined(CONFIG_I2S_DLV) - if (rate > 96000) - rate = 96000; -#else - if (rate > 48000) - rate = 48000; -#endif - if (rate < 8000) - rate = 8000; - jz_audio_rate = rate; - - if(set_codec_speed) - set_codec_speed(rate); - - return jz_audio_rate; -} - - -static int record_fill_1x8_u(unsigned long dst_start, int count, int id) -{ - int cnt = 0; - unsigned long data; - volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); - volatile unsigned char *dp = (unsigned char*)dst_start; - - while (count > 0) { - count -= 2; /* count in dword */ - cnt++; - data = *(s++); - *(dp ++) = ((data << 16) >> 24) + 0x80; - s++; /* skip the other channel */ - } - - return cnt; -} - - -static int record_fill_2x8_u(unsigned long dst_start, int count, int id) -{ - int cnt = 0; - unsigned long d1, d2; - volatile unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); - volatile unsigned char *dp = (unsigned char*)dst_start; - - while (count > 0) { - count -= 2; - cnt += 2; - d1 = *(s++); - *(dp ++) = ((d1 << 16) >> 24) + 0x80; - d2 = *(s++); - *(dp ++) = ((d2 << 16) >> 24) + 0x80; - } - - return cnt; -} - - -static int record_fill_1x16_s(unsigned long dst_start, int count, int id) -{ - int cnt = 0; - unsigned long d1; - unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); - unsigned short *dp = (unsigned short *)dst_start; - - while (count > 0) { - count -= 2; /* count in dword */ - cnt += 2; /* count in byte */ - d1 = *(s++); - *(dp ++) = (d1 << 16) >> 16; - s++; /* skip the other channel */ - } - - return cnt; -} - - -static int record_fill_2x16_s(unsigned long dst_start, int count, int id) -{ - int cnt = 0; - unsigned long d1, d2; - unsigned long *s = (unsigned long*)(*(in_dma_buf + id)); - unsigned short *dp = (unsigned short *)dst_start; - while (count > 0) { - count -= 2; /* count in dword */ - cnt += 4; /* count in byte */ - d1 = *(s++); - d2 = *(s++); - if(abnormal_data_count > 0) { - d1 = d2 = 0; - abnormal_data_count --; - } - *(dp ++) = (d1 << 16) >> 16; - *(dp ++) = (d2 << 16) >> 16; - } - - return cnt; -} - -static void replay_fill_1x8_u(signed long src_start, int count, int id) -{ - int cnt = 0; - unsigned char data; - unsigned long ddata; - volatile unsigned char *s = (unsigned char *)src_start; - volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); - - while (count > 0) { - count--; - cnt += 1; - data = *(s++) - 0x80; - ddata = (unsigned long) data << 8; - *(dp ++) = ddata; - *(dp ++) = ddata; - - /* save last left and right */ - if(count == 1) { - save_last_samples[id].left = ddata; - save_last_samples[id].right = ddata; - } - } - cnt = cnt * 2 * jz_audio_b; - *(out_dma_buf_data_count + id) = cnt; -} - - -static void replay_fill_2x8_u(signed long src_start, int count, int id) -{ - int cnt = 0; - unsigned char d1; - unsigned long dd1; - volatile unsigned char *s = (unsigned char *)src_start; - volatile unsigned long *dp = (unsigned long*)(*(out_dma_buf + id)); - - while (count > 0) { - count -= 1; - cnt += 1 ; - d1 = *(s++) - 0x80; - dd1 = (unsigned long) d1 << 8; - *(dp ++) = dd1; - /* save last left */ - if(count == 2) - save_last_samples[id].left = dd1; - /* save last right */ - if(count == 1) - save_last_samples[id].right = dd1; - } - cnt *= jz_audio_b; - *(out_dma_buf_data_count + id) = cnt; -} - - -static void replay_fill_1x16_s(signed long src_start, int count, int id) -{ - int cnt = 0; - signed short d1; - signed long l1; - volatile signed short *s = (signed short *)src_start; - volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); - - while (count > 0) { - count -= 2; - cnt += 2 ; - d1 = *(s++); - l1 = (signed long)d1; -#if defined(CONFIG_I2S_ICODEC) - l1 >>= codec_volue_shift; -#endif - *(dp ++) = l1; - *(dp ++) = l1; - - /* save last left and right */ - if(count == 1) { - save_last_samples[id].left = l1; - save_last_samples[id].right = l1; - } - } - cnt = cnt * 2 * jz_audio_b; - *(out_dma_buf_data_count + id) = cnt; -} - -static void replay_fill_2x16_s(signed long src_start, int count, int id) -{ - int cnt = 0; - signed short d1; - signed long l1; - volatile signed short *s = (signed short *)src_start; - volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); -#if defined(CONFIG_I2S_ICODEC) - int mute_cnt = 0; - signed long tmp1,tmp2; - volatile signed long *before_dp; - int sam_rate = jz_audio_rate / 20; - - tmp1 = tmp2 = 0; - while (count > 0) { - count -= 2; - cnt += 2; - d1 = *(s++); - - l1 = (signed long)d1; - l1 >>= codec_volue_shift; - - if(l1 == 0) { - mute_cnt ++; - if(mute_cnt >= sam_rate) { - before_dp = dp - 10; - *(before_dp) = (signed long)1; - before_dp = dp - 11; - *(before_dp) = (signed long)1; - mute_cnt = 0; - } - } else - mute_cnt = 0; - - *(dp ++) = l1; - - tmp1 = tmp2; - tmp2 = l1; - } - - /* save last left */ - save_last_samples[id].left = tmp1; - /* save last right */ - save_last_samples[id].right = tmp2; -#endif -#if defined(CONFIG_I2S_DLV) - while (count > 0) { - count -= 2; - cnt += 2; - d1 = *(s++); - - l1 = (signed long)d1; - - *(dp ++) = l1; - } -#endif - cnt *= jz_audio_b; - *(out_dma_buf_data_count + id) = cnt; -} - -static void replay_fill_2x18_s(unsigned long src_start, int count, int id) -{ - int cnt = 0; - signed long d1; - signed long l1; - volatile signed long *s = (signed long *)src_start; - volatile signed long *dp = (signed long*)(*(out_dma_buf + id)); - while (count > 0) { - count -= 4; - cnt += 4; - d1 = *(s++); - l1 = (signed long)d1; - *(dp ++) = l1; - } - - cnt *= jz_audio_b; - *(out_dma_buf_data_count + id) = cnt; -} - -static unsigned int jz_audio_set_format(int dev, unsigned int fmt) -{ - switch (fmt) { - case AFMT_U8: - __i2s_set_oss_sample_size(8); - __i2s_set_iss_sample_size(8); - jz_audio_format = fmt; - jz_update_filler(jz_audio_format,jz_audio_channels); - break; - case AFMT_S16_LE: -#if defined(CONFIG_I2S_DLV) - /* DAC path and ADC path */ - write_codec_file(2, 0x00); - //write_codec_file(2, 0x60); -#endif - jz_audio_format = fmt; - jz_update_filler(jz_audio_format,jz_audio_channels); - __i2s_set_oss_sample_size(16); - __i2s_set_iss_sample_size(16); - break; - case 18: - __i2s_set_oss_sample_size(18); - jz_audio_format = fmt; - jz_update_filler(jz_audio_format,jz_audio_channels); - break; - case AFMT_QUERY: - break; - } - - return jz_audio_format; -} - - -static short jz_audio_set_channels(int dev, short channels) -{ - switch (channels) { - case 1: - if(set_codec_some_func) - set_codec_some_func(); - jz_audio_channels = channels; - jz_update_filler(jz_audio_format, jz_audio_channels); -#if defined(CONFIG_I2S_DLV) - write_codec_file_bit(1, 1, 6);//CR1.MONO->1 for Mono -#endif - break; - case 2: - jz_audio_channels = channels; - jz_update_filler(jz_audio_format, jz_audio_channels); -#if defined(CONFIG_I2S_DLV) - write_codec_file_bit(1, 0, 6);//CR1.MONO->0 for Stereo -#endif - break; - case 0: - break; - } - - return jz_audio_channels; -} - -static void init_codec(void) -{ - /* inititalize internal I2S codec */ - if(init_codec_pin) - init_codec_pin(); - -#if defined(CONFIG_I2S_ICDC) - /* initialize AIC but not reset it */ - jz_i2s_initHw(0); -#endif - if(reset_codec) - reset_codec(); -} - -static void jz_audio_reset(void) -{ - __i2s_disable_replay(); - __i2s_disable_receive_dma(); - __i2s_disable_record(); - __i2s_disable_transmit_dma(); -#if defined(CONFIG_I2S_DLV) - REG_AIC_I2SCR = 0x10; -#endif - init_codec(); -} - -static int jz_audio_release(struct inode *inode, struct file *file); -static int jz_audio_open(struct inode *inode, struct file *file); -static int jz_audio_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg); -static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait); -static ssize_t jz_audio_write(struct file *file, const char *buffer,size_t count, loff_t *ppos); -static ssize_t jz_audio_read(struct file *file, char *buffer,size_t count, loff_t *ppos); - -/* static struct file_operations jz_i2s_audio_fops */ -static struct file_operations jz_i2s_audio_fops = -{ - owner: THIS_MODULE, - open: jz_audio_open, - release: jz_audio_release, - write: jz_audio_write, - read: jz_audio_read, - poll: jz_audio_poll, - ioctl: jz_audio_ioctl -}; - -static int jz_i2s_open_mixdev(struct inode *inode, struct file *file) -{ - int i; - int minor = MINOR(inode->i_rdev); - struct jz_i2s_controller_info *controller = i2s_controller; - - for (i = 0; i < NR_I2S; i++) - if (controller->i2s_codec[i] != NULL && controller->i2s_codec[i]->dev_mixer == minor) - goto match; - - if (!controller) - return -ENODEV; -match: - file->private_data = controller->i2s_codec[i]; - - return 0; -} - -static int jz_i2s_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct i2s_codec *codec = (struct i2s_codec *)file->private_data; - return codec->mixer_ioctl(codec, cmd, arg); -} - -static loff_t jz_i2s_llseek(struct file *file, loff_t offset, int origin) -{ - return -ESPIPE; -} - -static struct file_operations jz_i2s_mixer_fops = -{ - owner: THIS_MODULE, - llseek: jz_i2s_llseek, - ioctl: jz_i2s_ioctl_mixdev, - open: jz_i2s_open_mixdev, -}; - -static int i2s_mixer_ioctl(struct i2s_codec *codec, unsigned int cmd, unsigned long arg) -{ - int ret; - long val = 0; - switch (cmd) { - case SOUND_MIXER_INFO: - - if(codec_mixer_info_id_name) - codec_mixer_info_id_name(); - info.modify_counter = audio_mix_modcnt; - - return copy_to_user((void *)arg, &info, sizeof(info)); - case SOUND_OLD_MIXER_INFO: - - if(codec_mixer_old_info_id_name) - codec_mixer_old_info_id_name(); - - return copy_to_user((void *)arg, &old_info, sizeof(info)); - case SOUND_MIXER_READ_STEREODEVS: - - return put_user(0, (long *) arg); - case SOUND_MIXER_READ_CAPS: - - val = SOUND_CAP_EXCL_INPUT; - return put_user(val, (long *) arg); - case SOUND_MIXER_READ_DEVMASK: - break; - case SOUND_MIXER_READ_RECMASK: - break; - case SOUND_MIXER_READ_RECSRC: - break; - case SOUND_MIXER_WRITE_SPEAKER: - - ret = get_user(val, (long *) arg); - if (ret) - return ret; - val = val & 0xff; - if(val < 0) - val = 0; - if(val > 100) - val = 100; - switch(val) { - case 100: - if(set_codec_direct_mode) - set_codec_direct_mode(); - break; - case 0: - if(clear_codec_direct_mode) - clear_codec_direct_mode(); - break; - } - break; - case SOUND_MIXER_WRITE_BASS: - - ret = get_user(val, (long *) arg); - if (ret) - return ret; - - val = val & 0xff; - if(val < 0) - val = 0; - if(val > 100) - val = 100; - codec_bass_gain = val; - if(set_codec_bass) - set_codec_bass(val); - - return 0; - case SOUND_MIXER_READ_BASS: - - val = codec_bass_gain; - ret = val << 8; - val = val | ret; - - return put_user(val, (long *) arg); - case SOUND_MIXER_WRITE_VOLUME: - ret = get_user(val, (long *) arg); - if (ret) - return ret; - val = val & 0xff; - if(val < 0) - val = 0; - if(val > 100) - val = 100; - - jz_audio_volume = val; - if(set_codec_volume) - set_codec_volume(val); - - return 0; - case SOUND_MIXER_READ_VOLUME: - - val = jz_audio_volume; - ret = val << 8; - val = val | ret; - - return put_user(val, (long *) arg); - - case SOUND_MIXER_WRITE_MIC: - - ret = get_user(val, (long *) arg); - if (ret) - return ret; - - val = val & 0xff; - if(val < 0) - val = 0; - if(val > 100) - val = 100; - codec_mic_gain = val; - use_mic_line_flag = USE_MIC; - if(set_codec_mic) - set_codec_mic(val); - - return 0; - case SOUND_MIXER_READ_MIC: - - val = codec_mic_gain; - ret = val << 8; - val = val | ret; - - return put_user(val, (long *) arg); - - case SOUND_MIXER_WRITE_LINE: - - ret = get_user(val, (long *) arg); - if (ret) - return ret; - - val = val & 0xff; - if(val < 0) - val = 0; - if(val > 100) - val = 100; - use_mic_line_flag = USE_LINEIN; - codec_mic_gain = val; - if(set_codec_line) - set_codec_line(val); - - return 0; - case SOUND_MIXER_READ_LINE: - - val = codec_mic_gain; - ret = val << 8; - val = val | ret; - - return put_user(val, (long *) arg); - default: - return -ENOSYS; - } - audio_mix_modcnt ++; - return 0; -} - - -int i2s_probe_codec(struct i2s_codec *codec) -{ - /* generic OSS to I2S wrapper */ - codec->mixer_ioctl = i2s_mixer_ioctl; - return 1; -} - - -/* I2S codec initialisation. */ -static int __init jz_i2s_codec_init(struct jz_i2s_controller_info *controller) -{ - int num_i2s = 0; - struct i2s_codec *codec; - - for (num_i2s = 0; num_i2s < NR_I2S; num_i2s++) { - if ((codec = kmalloc(sizeof(struct i2s_codec),GFP_KERNEL)) == NULL) - return -ENOMEM; - memset(codec, 0, sizeof(struct i2s_codec)); - codec->private_data = controller; - codec->id = num_i2s; - - if (i2s_probe_codec(codec) == 0) - break; - if ((codec->dev_mixer = register_sound_mixer(&jz_i2s_mixer_fops, -1)) < 0) { - printk(KERN_ERR "Jz I2S: couldn't register mixer!\n"); - kfree(codec); - break; - } - controller->i2s_codec[num_i2s] = codec; - } - return num_i2s; -} - - -static void jz_update_filler(int format, int channels) -{ -#define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3)) - - switch (TYPE(format, channels)) - { - - case TYPE(AFMT_U8, 1): - jz_audio_b = 4; /* 4bytes * 8bits =32bits */ - replay_filler = replay_fill_1x8_u; - record_filler = record_fill_1x8_u; - break; - case TYPE(AFMT_U8, 2): - jz_audio_b = 4; - replay_filler = replay_fill_2x8_u; - record_filler = record_fill_2x8_u; - break; - case TYPE(AFMT_S16_LE, 1): - jz_audio_b = 2; /* 2bytes * 16bits =32bits */ - replay_filler = replay_fill_1x16_s; - record_filler = record_fill_1x16_s; - break; - case TYPE(AFMT_S16_LE, 2): - jz_audio_b = 2; - replay_filler = replay_fill_2x16_s; - record_filler = record_fill_2x16_s; - break; - case TYPE(18, 2): - jz_audio_b = 1; - replay_filler = replay_fill_2x18_s; - record_filler = record_fill_2x16_s; - break; - default: - ; - } -} - - -#ifdef CONFIG_PROC_FS -extern struct proc_dir_entry *proc_jz_root; -int i2s_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - return 0; -} - -static int jz_i2s_init_proc(struct jz_i2s_controller_info *controller) -{ - if (!create_proc_read_entry ("i2s", 0, proc_jz_root, i2s_read_proc, controller->i2s_codec[0])) - return -EIO; - return 0; -} - -static void jz_i2s_cleanup_proc(struct jz_i2s_controller_info *controller) -{ -} -#endif - -static void __init attach_jz_i2s(struct jz_i2s_controller_info *controller) -{ - char *name; - int adev; /* No of Audio device. */ - - name = controller->name; - /* initialize AIC controller and reset it */ - jz_i2s_initHw(1); - adev = register_sound_dsp(&jz_i2s_audio_fops, -1); - if (adev < 0) - goto audio_failed; - /* initialize I2S codec and register /dev/mixer */ - if (jz_i2s_codec_init(controller) <= 0) - goto mixer_failed; - -#ifdef CONFIG_PROC_FS - if (jz_i2s_init_proc(controller) < 0) { - printk(KERN_ERR "%s: can't create I2S proc filesystem.\n", name); - goto proc_failed; - } -#endif - - controller->tmp1 = (void *)__get_free_pages(GFP_KERNEL, 8); - if (!controller->tmp1) { - printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); - goto tmp1_failed; - } - controller->tmp2 = (void *)__get_free_pages(GFP_KERNEL, 8); - if (!controller->tmp2) { - printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); - goto tmp2_failed; - } - if ((controller->dma2 = jz_request_dma(DMA_ID_I2S_RX, "audio adc", jz_i2s_record_dma_irq, IRQF_DISABLED, controller)) < 0) { - printk(KERN_ERR "%s: can't reqeust DMA ADC channel.\n", name); - goto dma2_failed; - } - if ((controller->dma1 = jz_request_dma(DMA_ID_I2S_TX, "audio dac", jz_i2s_replay_dma_irq, IRQF_DISABLED, controller)) < 0) { - printk(KERN_ERR "%s: can't reqeust DMA DAC channel.\n", name); - goto dma1_failed; - } - printk("JzSOC On-Chip I2S controller registered (DAC: DMA(play):%d/IRQ%d,\n ADC: DMA(record):%d/IRQ%d)\n", controller->dma1, get_dma_done_irq(controller->dma1), controller->dma2, get_dma_done_irq(controller->dma2)); - - controller->dev_audio = adev; - pop_turn_onoff_buf = __get_free_pages(GFP_KERNEL | GFP_DMA, 8); - if(!pop_turn_onoff_buf) - printk("pop_turn_onoff_buf alloc is wrong!\n"); - pop_turn_onoff_pbuf = virt_to_phys((void *)pop_turn_onoff_buf); - - return; -dma2_failed: - jz_free_dma(controller->dma1); -dma1_failed: - free_pages((unsigned long)controller->tmp2, 8); -tmp2_failed: - free_pages((unsigned long)controller->tmp1, 8); -tmp1_failed: - -#ifdef CONFIG_PROC_FS - jz_i2s_cleanup_proc(controller); -#endif -proc_failed: - /* unregister mixer dev */ -mixer_failed: - unregister_sound_dsp(adev); -audio_failed: - return; -} - -static int __init probe_jz_i2s(struct jz_i2s_controller_info **controller) -{ - if ((*controller = kmalloc(sizeof(struct jz_i2s_controller_info), - GFP_KERNEL)) == NULL) { - printk(KERN_ERR "Jz I2S Controller: out of memory.\n"); - return -ENOMEM; - } - (*controller)->name = "Jz I2S controller"; - (*controller)->opened1 = 0; - (*controller)->opened2 = 0; - init_waitqueue_head(&(*controller)->adc_wait); - init_waitqueue_head(&(*controller)->dac_wait); - spin_lock_init(&(*controller)->lock); - init_waitqueue_head(&rx_wait_queue); - init_waitqueue_head(&tx_wait_queue); - init_waitqueue_head(&pop_wait_queue); - init_waitqueue_head(&drain_wait_queue); - - return 0; -} - -static void __exit unload_jz_i2s(struct jz_i2s_controller_info *controller) -{ - int adev = controller->dev_audio; - - jz_i2s_full_reset(controller); - controller->dev_audio = -1; - if (old_mksound) - kd_mksound = old_mksound;/* Our driver support bell for kb, see vt.c */ - -#ifdef CONFIG_PROC_FS - jz_i2s_cleanup_proc(controller); -#endif - - jz_free_dma(controller->dma1); - jz_free_dma(controller->dma2); - free_pages((unsigned long)controller->tmp1, 8); - free_pages((unsigned long)controller->tmp2, 8); - free_pages((unsigned long)pop_turn_onoff_buf, 8); - - if (adev >= 0) { - /* unregister_sound_mixer(audio_devs[adev]->mixer_dev); */ - unregister_sound_dsp(controller->dev_audio); - } -} - -#ifdef CONFIG_PM -static int jz_i2s_suspend(struct jz_i2s_controller_info *controller, int state) -{ - if(i2s_suspend_codec) - i2s_suspend_codec(controller->opened1,controller->opened2); - printk("Aic and codec are suspended!\n"); - return 0; -} - -static int jz_i2s_resume(struct jz_i2s_controller_info *controller) -{ - if(i2s_resume_codec) - i2s_resume_codec(); - -#if defined(CONFIG_I2S_AK4642EN) - jz_i2s_initHw(0); - jz_audio_reset(); - __i2s_enable(); - jz_audio_set_speed(controller->dev_audio,jz_audio_speed); - /* playing */ - if(controller->opened1) { - if(set_codec_replay) - set_codec_replay(); - int dma = controller->dma1; - int id; - unsigned long flags; - disable_dma(dma); - if(__dmac_channel_address_error_detected(dma)) { - printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); - __dmac_channel_clear_address_error(dma); - } - if(__dmac_channel_transmit_end_detected(dma)) - __dmac_channel_clear_transmit_end(dma); - - /* for DSP_GETOPTR */ - spin_lock_irqsave(&controller->ioctllock, flags); - controller->total_bytes += jz_audio_dma_tran_count; - controller->blocks ++; - spin_unlock_irqrestore(&controller->ioctllock, flags); - while((id = get_buffer_id(&out_busy_queue)) >= 0) - put_buffer_id(&out_empty_queue, id); - - out_busy_queue.count=0; - if((id = get_buffer_id(&out_full_queue)) >= 0) { - put_buffer_id(&out_empty_queue, id); - } - if (elements_in_queue(&out_empty_queue) > 0) { - wake_up(&tx_wait_queue); - wake_up(&controller->dac_wait); - } else - printk("pm out_empty_queue empty"); - } - - /* recording */ - if(controller->opened2) { - if(set_codec_record) - set_codec_record(use_mic_line_flag); - int dma = controller->dma2; - int id1, id2; - unsigned long flags; - disable_dma(dma); - if (__dmac_channel_address_error_detected(dma)) { - printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); - __dmac_channel_clear_address_error(dma); - } - if (__dmac_channel_transmit_end_detected(dma)) { - __dmac_channel_clear_transmit_end(dma); - } - /* for DSP_GETIPTR */ - spin_lock_irqsave(&controller->ioctllock, flags); - controller->total_bytes += jz_audio_dma_tran_count; - controller->blocks ++; - spin_unlock_irqrestore(&controller->ioctllock, flags); - id1 = get_buffer_id(&in_busy_queue); - put_buffer_id(&in_full_queue, id1); - wake_up(&rx_wait_queue); - wake_up(&controller->adc_wait); - if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { - put_buffer_id(&in_full_queue, id2); - } - in_busy_queue.count = 0; - } -#endif - - return 0; -} - -static int jz_i2s_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -{ - int ret; - struct jz_i2s_controller_info *controller = pm_dev->data; - - if (!controller) return -EINVAL; - - switch (req) { - case PM_SUSPEND: - ret = jz_i2s_suspend(controller, (int)data); - break; - case PM_RESUME: - ret = jz_i2s_resume(controller); - break; - default: - ret = -EINVAL; - break; - } - return ret; -} -#endif /* CONFIG_PM */ - -#if defined(CONFIG_I2S_DLV) -static irqreturn_t aic_codec_irq(int irq, void *dev_id) -{ - u8 file_9 = read_codec_file(9); - u8 file_8 = read_codec_file(8); - - //printk("--- 8:0x%x 9:0x%x ---\n",file_8,file_9); - if ((file_9 & 0x1f) == 0x10) { - - write_codec_file(8, 0x3f); - write_codec_file_bit(5, 1, 6);//SB_OUT->1 - mdelay(300); - while ((read_codec_file(9) & 0x4) != 0x4); - while ((read_codec_file(9) & 0x10) == 0x10) { - write_codec_file(9, 0x10); - } - write_codec_file_bit(5, 0, 6);//SB_OUT->0 - mdelay(300); - while ((read_codec_file(9) & 0x8) != 0x8); - write_codec_file(9, file_9); - write_codec_file(8, file_8); - - return IRQ_HANDLED; - } - - if (file_9 & 0x8) - ramp_up_end = jiffies; - else if (file_9 & 0x4) - ramp_down_end = jiffies; - else if (file_9 & 0x2) - gain_up_end = jiffies; - else if (file_9 & 0x1) - gain_down_end = jiffies; - - write_codec_file(9, file_9); - if (file_9 & 0xf) - wake_up(&pop_wait_queue); - while (REG_ICDC_RGDATA & 0x100); - - return IRQ_HANDLED; -} -#endif - -static int __init init_jz_i2s(void) -{ - int errno; -#if defined(CONFIG_I2S_DLV) - int retval; - ramp_up_start = 0; - ramp_up_end = 0; - gain_up_start = 0; - gain_up_end = 0; - ramp_down_start = 0; - ramp_down_end = 0; - gain_down_start = 0; - gain_down_end = 0; -#endif - use_mic_line_flag = USE_NONE; - abnormal_data_count = 0; - if(set_codec_mode) - set_codec_mode(); - - drain_flag = 0; - if ((errno = probe_jz_i2s(&i2s_controller)) < 0) - return errno; - if(set_codec_gpio_pin) - set_codec_gpio_pin(); - - attach_jz_i2s(i2s_controller); - if(set_codec_startup_param) - set_codec_startup_param(); - if(set_codec_volume_table) - set_codec_volume_table(); - -#if defined(CONFIG_I2S_DLV) - jz_codec_config = 0; - retval = request_irq(IRQ_AIC, aic_codec_irq, IRQF_DISABLED, "aic_codec_irq", NULL); - if (retval) { - printk("Could not get aic codec irq %d\n", IRQ_AIC); - return retval; - } -#endif - - out_empty_queue.id = NULL; - out_full_queue.id = NULL; - out_busy_queue.id = NULL; - in_empty_queue.id = NULL; - in_full_queue.id = NULL; - in_busy_queue.id = NULL; - - jz_audio_fragsize = JZCODEC_RW_BUFFER_SIZE * PAGE_SIZE; - jz_audio_fragstotal = JZCODEC_RW_BUFFER_TOTAL ; - Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); - -#ifdef CONFIG_PM - i2s_controller->pm = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, - jz_i2s_pm_callback); - if (i2s_controller->pm) - i2s_controller->pm->data = i2s_controller; -#endif -#if defined(CONFIG_I2S_DLV) - __cpm_start_idct(); - __cpm_start_db(); - __cpm_start_me(); - __cpm_start_mc(); - __cpm_start_ipu(); -#endif - printk("JZ I2S OSS audio driver initialized\n"); - - return 0; -} - -static void __exit cleanup_jz_i2s(void) -{ -#ifdef CONFIG_PM - /* pm_unregister(i2s_controller->pm); */ -#endif -#if defined(CONFIG_I2S_DLV) - free_irq(IRQ_AIC, NULL); -#endif - unload_jz_i2s(i2s_controller); - Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); - if(clear_codec_mode) - clear_codec_mode(); -} - -module_init(init_jz_i2s); -module_exit(cleanup_jz_i2s); - -#if defined(CONFIG_SOC_JZ4730) -static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -{ - DECLARE_WAITQUEUE(wait, current); - unsigned long flags; - int count,con; - - if(elements_in_queue(&in_busy_queue) > 0) { - if (nonblock) - return -EBUSY; - drain_flag = 1; - sleep_on(&drain_wait_queue); - drain_flag = 0; - } else { - add_wait_queue(&ctrl->adc_wait, &wait); - for (con = 0; con < 1000; con ++) { - udelay(1); - set_current_state(TASK_INTERRUPTIBLE); - spin_lock_irqsave(&ctrl->lock, flags); - count = get_dma_residue(ctrl->dma2); - spin_unlock_irqrestore(&ctrl->lock, flags); - if (count <= 0) - break; - if (nonblock) { - remove_wait_queue(&ctrl->adc_wait, &wait); - current->state = TASK_RUNNING; - return -EBUSY; - } - } - remove_wait_queue(&ctrl->adc_wait, &wait); - current->state = TASK_RUNNING; - } - return 0; -} - -static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -{ - DECLARE_WAITQUEUE(wait, current); - unsigned long flags; - int count; - - if(elements_in_queue(&out_full_queue) > 0) { - if (nonblock) - return -EBUSY; - - drain_flag = 1; - sleep_on(&drain_wait_queue); - drain_flag = 0; - } else { - add_wait_queue(&(ctrl->dac_wait), &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if(elements_in_queue(&out_full_queue) <= 0) { - spin_lock_irqsave(&ctrl->lock, flags); - count = get_dma_residue(ctrl->dma1); - spin_unlock_irqrestore(&ctrl->lock, flags); - if(count <= 0) - break; - } - if (nonblock) { - remove_wait_queue(&ctrl->dac_wait, &wait); - current->state = TASK_RUNNING; - return -EBUSY; - } - } - remove_wait_queue(&ctrl->dac_wait, &wait); - current->state = TASK_RUNNING; - } - - return 0; -} -#endif - -#if defined(CONFIG_SOC_JZ4740) -#define MAXDELAY 50000 -static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -{ - int count,ele,i=0; - int tfl; - - for (;;) { - if(!nonblock) {//blocked - if ( i < MAXDELAY ) { - udelay(10); - i++; - } else - break; - - ele = elements_in_queue(&out_full_queue); - if(ele <= 0) { - udelay(10); - spin_lock(&ctrl->lock); - count = get_dma_residue(ctrl->dma1); - spin_unlock(&ctrl->lock); - if (count <= 0) - break; - } - } else {//non-blocked - mdelay(100); - ele = elements_in_queue(&out_full_queue); - - if(ele <= 0) { - mdelay(100); - - spin_lock(&ctrl->lock); - count = get_dma_residue(ctrl->dma1); - spin_unlock(&ctrl->lock); - if (count <= 0) - break; - } - } - } - - /* wait for TX fifo */ - while (1) { - tfl = __aic_get_transmit_resident(); - if (tfl == 0) - break; - udelay(2); - } - - return 0; -} - -static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -{ - int count,i=0; - - for (;;) { - if ( i < MAXDELAY ) - { - udelay(10); - i++; - } - else - break; - spin_lock(&ctrl->lock); - count = get_dma_residue(ctrl->dma2); - spin_unlock(&ctrl->lock); - if (count <= 0) - break; - - if (nonblock) { - return -EBUSY; - } - } - - return 0; -} -#endif - -#if defined(CONFIG_SOC_JZ4750) -#define MAXDELAY 50000 -static int drain_adc(struct jz_i2s_controller_info *ctrl, int nonblock) -{ - //DECLARE_WAITQUEUE(wait, current); - unsigned long flags; - int count,i=0; - - //add_wait_queue(&ctrl->adc_wait, &wait); - for (;;) { - if (i < MAXDELAY) { - udelay(10); - i++; - } else - break; - //set_current_state(TASK_INTERRUPTIBLE); - spin_lock_irqsave(&ctrl->lock, flags); - //spin_lock(&ctrl->lock); - count = get_dma_residue(ctrl->dma2); - spin_unlock_irqrestore(&ctrl->lock, flags); - //spin_unlock(&ctrl->lock); - if (count <= 0) - break; - - /*if (signal_pending(current)) - break;*/ - if (nonblock) { - //remove_wait_queue(&ctrl->adc_wait, &wait); - //current->state = TASK_RUNNING; - return -EBUSY; - } - } - //remove_wait_queue(&ctrl->adc_wait, &wait); - //current->state = TASK_RUNNING; - /*if (signal_pending(current)) - return -ERESTARTSYS;*/ - return 0; -} -static int drain_dac(struct jz_i2s_controller_info *ctrl, int nonblock) -{ - unsigned long flags; - int count,ele,busyele,emptyele,i=0; - - for (;;) { - if(!nonblock) {//blocked - if (i < MAXDELAY) { - udelay(10); - i++; - } else - break; - - ele = elements_in_queue(&out_full_queue); - if(ele <= 0) { - udelay(200); - - busyele = elements_in_queue(&out_busy_queue); - emptyele = elements_in_queue(&out_empty_queue); - if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { - spin_lock_irqsave(&ctrl->lock, flags); - count = get_dma_residue(ctrl->dma1); - spin_unlock_irqrestore(&ctrl->lock, flags); - if (count <= 0) - break; - } - } - } else {//non-blocked - //mdelay(100); - ele = elements_in_queue(&out_full_queue); - - if(ele <= 0) { - //mdelay(100); - busyele = elements_in_queue(&out_busy_queue); - emptyele = elements_in_queue(&out_empty_queue); - - if (busyele <= 0 && emptyele >= jz_audio_fragstotal) { - spin_lock_irqsave(&ctrl->lock, flags); - count = get_dma_residue(ctrl->dma1); - spin_unlock_irqrestore(&ctrl->lock, flags); - if (count <= 0) - break; - } - } - } - } - - return 0; -} -#endif - -static int jz_audio_release(struct inode *inode, struct file *file) -{ - unsigned long flags; -#if defined(CONFIG_I2S_DLV) - unsigned long tfl; -#endif - struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; -#if defined(CONFIG_I2S_DLV) - jz_codec_config = 0; -#endif - if (controller == NULL) - return -ENODEV; - - pop_dma_flag = 0; - - if (controller->opened1 == 1 && controller->opened2 == 1) { - controller->opened1 = 0; - __i2s_enable_transmit_dma(); - __i2s_enable_replay(); - drain_dac(controller, file->f_flags & O_NONBLOCK); -#if defined(CONFIG_I2S_DLV) - /* wait for fifo empty */ - write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 - gain_down_start = jiffies; - sleep_on(&pop_wait_queue); - //gain_down_end = jiffies; - /*while (1) { - tfl = REG_AIC_SR & 0x00003f00; - if (tfl == 0) { - udelay(500); - break; - } - mdelay(2); - }*/ - mdelay(100); -#endif - disable_dma(controller->dma1); - set_dma_count(controller->dma1, 0); - __i2s_disable_transmit_dma(); - __i2s_disable_replay(); - -#if defined(CONFIG_I2S_ICODEC) - if(clear_codec_replay) - clear_codec_replay(); -#endif - spin_lock_irqsave(&controller->ioctllock, flags); - controller->total_bytes = 0; - controller->count = 0; - controller->finish = 0; - jz_audio_dma_tran_count = 0; - controller->blocks = 0; - controller->nextOut = 0; - spin_unlock_irqrestore(&controller->ioctllock, flags); - - controller->opened2 = 0; - first_record_call = 1; - __i2s_enable_receive_dma(); - __i2s_enable_record(); - drain_adc(controller, file->f_flags & O_NONBLOCK); - disable_dma(controller->dma2); - set_dma_count(controller->dma2, 0); - __i2s_disable_receive_dma(); - __i2s_disable_record(); -#if defined(CONFIG_I2S_ICODEC) - if(clear_codec_record) - clear_codec_record(); -#endif - spin_lock_irqsave(&controller->ioctllock, flags); - controller->total_bytes = 0; - jz_audio_dma_tran_count = 0; - controller->count = 0; - controller->finish = 0; - controller->blocks = 0; - controller->nextIn = 0; - spin_unlock_irqrestore(&controller->ioctllock, flags); -#if defined(CONFIG_I2S_DLV) - write_codec_file_bit(5, 1, 6);//SB_OUT->1 - ramp_down_start = jiffies; - sleep_on(&pop_wait_queue); - //ramp_down_end = jiffies; - if (use_mic_line_flag == USE_LINEIN) { - unset_record_line_input_audio_with_audio_data_replay(); - //printk("3 use_mic_line_flag=%d\n",use_mic_line_flag); - } - if (use_mic_line_flag == USE_MIC) { - unset_record_mic_input_audio_with_audio_data_replay(); - //printk("4 use_mic_line_flag=%d\n",use_mic_line_flag); - } - -#if 0 - unset_record_playing_audio_mixed_with_mic_input_audio(); -#endif -#endif - __i2s_disable(); - if(turn_off_codec) - turn_off_codec(); - abnormal_data_count = 0; - } else if (controller->opened1 == 1) { - //controller->opened1 = 0; - __i2s_enable_transmit_dma(); - __i2s_enable_replay(); - drain_dac(controller, file->f_flags & O_NONBLOCK); - /* add some mute to anti-pop */ -#if defined(CONFIG_I2S_ICODEC) - //write_mute_to_dma_buffer(save_last_samples[last_dma_buffer_id].left,save_last_samples[last_dma_buffer_id].right); -#endif -#if defined(CONFIG_I2S_DLV) - write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 - gain_down_start = jiffies; - sleep_on(&pop_wait_queue); - //gain_down_end = jiffies; - while (1) { - tfl = REG_AIC_SR & 0x00003f00; - if (tfl == 0) { - udelay(500); - break; - } - mdelay(2); - } -#endif - disable_dma(controller->dma1); - set_dma_count(controller->dma1, 0); - __i2s_disable_transmit_dma(); - __i2s_disable_replay(); -#if defined(CONFIG_I2S_ICODEC) - if(clear_codec_replay) - clear_codec_replay(); -#endif - __aic_flush_fifo(); - - spin_lock_irqsave(&controller->ioctllock, flags); - controller->total_bytes = 0; - controller->count = 0; - controller->finish = 0; - jz_audio_dma_tran_count = 0; - controller->blocks = 0; - controller->nextOut = 0; - spin_unlock_irqrestore(&controller->ioctllock, flags); -#if defined(CONFIG_I2S_DLV) - write_codec_file_bit(5, 1, 6);//SB_OUT->1 - ramp_down_start = jiffies; - sleep_on(&pop_wait_queue); - //ramp_down_end = jiffies; - unset_audio_data_replay(); -#endif - __i2s_disable(); -#if defined(CONFIG_I2S_ICODEC) - if(turn_off_codec) - turn_off_codec(); -#endif - } else if (controller->opened2 == 1) { - controller->opened2 = 0; - first_record_call = 1; - __i2s_enable_receive_dma(); - __i2s_enable_record(); - drain_adc(controller, file->f_flags & O_NONBLOCK); - disable_dma(controller->dma2); - set_dma_count(controller->dma2, 0); - __i2s_disable_receive_dma(); - __i2s_disable_record(); -#if defined(CONFIG_I2S_ICODEC) - if(clear_codec_record) - clear_codec_record(); -#endif - spin_lock_irqsave(&controller->ioctllock, flags); - controller->total_bytes = 0; - jz_audio_dma_tran_count = 0; - controller->count = 0; - controller->finish = 0; - controller->blocks = 0; - controller->nextIn = 0; - spin_unlock_irqrestore(&controller->ioctllock, flags); -#if defined(CONFIG_I2S_DLV) -#if 0 - /* unset Record MIC input audio with direct playback */ - unset_record_mic_input_audio_with_direct_playback(); -#endif -#if 1 - /* unset Record MIC input audio without playback */ - unset_record_mic_input_audio_without_playback(); -#endif -#if 0 - /* tested */ - /* unset Record LINE input audio without playback */ - unset_record_line_input_audio_without_playback(); -#endif -#endif - __i2s_disable(); -#if defined(CONFIG_I2S_ICODEC) - if(turn_off_codec) - turn_off_codec(); -#endif - abnormal_data_count = 0; - } - -#if defined(CONFIG_I2S_DLV) - write_codec_file(9, 0xff); - write_codec_file(8, 0x3f); -/* __cpm_stop_idct(); - __cpm_stop_db(); - __cpm_stop_me(); - __cpm_stop_mc(); - __cpm_stop_ipu();*/ -#endif - - if (controller->opened1 == 1 && controller->opened2 == 1) { - controller->opened1 = 0; - controller->opened2 = 0; - //print_pop_duration(); - //__dmac_disable_module(0); - } else if ( controller->opened1 == 1 ) { - controller->opened1 = 0; - //print_pop_duration(); - } else if ( controller->opened2 == 1 ) { - controller->opened2 = 0; - } - - return 0; -} - -static int jz_audio_open(struct inode *inode, struct file *file) -{ - int i; - struct jz_i2s_controller_info *controller = i2s_controller; -#if defined(CONFIG_I2S_DLV) - jz_codec_config = 0; -#endif - if (controller == NULL) - return -ENODEV; - - mdelay(2); -#if defined(CONFIG_I2S_DLV) - REG_DMAC_DMACKE(0) = 0x3f; -#endif - pop_dma_flag = 0; - if (controller->opened1 == 1 || controller->opened2 == 1 ) { - printk("\naudio is busy!\n"); - return -EBUSY; - } - - if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { - if (controller->opened1 == 1) - return -EBUSY; - controller->opened1 = 1; - /* for ioctl */ - controller->total_bytes = 0; - jz_audio_dma_tran_count = 0; - controller->count = 0; - controller->finish = 0; - controller->blocks = 0; - controller->nextOut = 0; - - for(i=0;i < 64;i++) { - save_last_samples[i].left = 0; - save_last_samples[i].right = 0; - } - - out_empty_queue.count = jz_audio_fragstotal; - for (i=0;i < jz_audio_fragstotal;i++) - *(out_empty_queue.id + i) = i; - out_busy_queue.count = 0; - out_full_queue.count = 0; - last_dma_buffer_id = 0; - - if (controller->opened2 == 1) - return -EBUSY; - - controller->opened2 = 1; - first_record_call = 1; - /* for ioctl */ - controller->total_bytes = 0; - jz_audio_dma_tran_count = 0; - controller->count = 0; - controller->finish = 0; - controller->blocks = 0; - controller->nextIn = 0; - - in_empty_queue.count = jz_audio_fragstotal; - for (i=0;i < jz_audio_fragstotal;i++) - *(in_empty_queue.id + i) = i; - - in_full_queue.count = 0; - in_busy_queue.count = 0; - } else if (file->f_mode & FMODE_WRITE) { - if (controller->opened1 == 1) - return -EBUSY; - - controller->opened1 = 1; - /* for ioctl */ - controller->total_bytes = 0; - jz_audio_dma_tran_count = 0; - controller->count = 0; - controller->finish = 0; - controller->blocks = 0; - controller->nextOut = 0; - - for(i=0;i < 64;i++) { - save_last_samples[i].left = 0; - save_last_samples[i].right = 0; - } - - out_empty_queue.count = jz_audio_fragstotal; - for (i=0;i < jz_audio_fragstotal;i++) - *(out_empty_queue.id + i) = i; - out_busy_queue.count = 0; - out_full_queue.count = 0; - last_dma_buffer_id = 0; - } else if (file->f_mode & FMODE_READ) { - if (controller->opened2 == 1) - return -EBUSY; - - controller->opened2 = 1; - first_record_call = 1; - /* for ioctl */ - controller->total_bytes = 0; - jz_audio_dma_tran_count = 0; - controller->count = 0; - controller->finish = 0; - controller->blocks = 0; - controller->nextIn = 0; - - in_empty_queue.count = jz_audio_fragstotal; - for (i=0;i < jz_audio_fragstotal;i++) - *(in_empty_queue.id + i) = i; - - in_full_queue.count = 0; - in_busy_queue.count = 0; - } - - file->private_data = controller; - jz_audio_reset(); - REG_AIC_FR |= (1 << 6); - if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { -#if defined(CONFIG_I2S_ICODEC) - if (set_codec_replay_record) - set_codec_replay_record(use_mic_line_flag); -#endif -#if defined(CONFIG_I2S_DLV) - if (use_mic_line_flag == USE_NONE) { - printk("you select mic or line recording please.or use mic recording!\n"); - use_mic_line_flag = USE_MIC; - } - if (use_mic_line_flag == USE_LINEIN) { - /* Record LINE input audio with Audio data replay (full duplex for linein) */ - /* codec_test_line */ - set_record_line_input_audio_with_audio_data_replay(); - - } - if (use_mic_line_flag == USE_MIC) { - /* Record MIC input audio with Audio data replay (full duplex) */ - /* codec_test_mic */ - set_record_mic_input_audio_with_audio_data_replay(); - } -#if 0 - /* Record playing audio mixed with MIC input audio */ - set_record_playing_audio_mixed_with_mic_input_audio(); -#endif - -#endif - } else if (file->f_mode & FMODE_WRITE) { -#if defined(CONFIG_I2S_ICODEC) - if(set_codec_replay) - set_codec_replay(); -#endif -#if defined(CONFIG_I2S_DLV) - //mdelay(10); - /* Audio data replay */ - set_audio_data_replay(); -#endif - } else if (file->f_mode & FMODE_READ) { -#if defined(CONFIG_I2S_ICODEC) - abnormal_data_count = 0; - if(set_codec_record) - set_codec_record(use_mic_line_flag); -#endif -#if defined(CONFIG_I2S_DLV) -#if 0 - /* Record MIC input audio with direct playback */ - set_record_mic_input_audio_with_direct_playback(); -#endif - -#if 1 - /* set Record MIC input audio without playback */ - set_record_mic_input_audio_without_playback(); -#endif -#if 0 - /* tested */ - /* set Record LINE input audio without playback */ - set_record_line_input_audio_without_playback(); -#endif - mdelay(1); -#endif - } - -#if defined(CONFIG_I2S_DLV) - __aic_reset(); - - mdelay(10); - REG_AIC_I2SCR = 0x10; - mdelay(20); - __aic_flush_fifo(); -#endif - - __i2s_enable(); - -#if defined(CONFIG_I2S_DLV) - ndelay(100); - - if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { -#if defined(CONFIG_I2S_DLV) - //set SB_ADC or SB_DAC - __dmac_enable_module(0); - write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 - ramp_up_start = jiffies; - sleep_on(&pop_wait_queue); - //ramp_up_end = jiffies; -#endif - } else if (file->f_mode & FMODE_WRITE) { -#if defined(CONFIG_I2S_DLV) - write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 - ramp_up_start = jiffies; - /*while (!(REG_RTC_RCR & RTC_RCR_WRDY)); - REG_RTC_RCR = 0x1; - while (!(REG_RTC_RCR & RTC_RCR_WRDY)); - REG_RTC_RGR = 1;*/ - sleep_on(&pop_wait_queue); - //ramp_up_end = jiffies; - write_codec_file_bit(5, 1, 4);//SB_ADC->1 -#endif - } else if (file->f_mode & FMODE_READ) { -#if defined(CONFIG_I2S_DLV) - if (jz_mic_only) - write_codec_file_bit(5, 1, 7);//SB_DAC->1 - else - write_codec_file_bit(5, 0, 7);//SB_DAC->0 - mdelay(500); -#endif - } -#endif - return 0; -} - - -static int jz_audio_ioctl(struct inode *inode, struct file *file, -unsigned int cmd, unsigned long arg) -{ - int val,fullc,busyc,unfinish,newfragstotal,newfragsize; - struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; - count_info cinfo; - audio_buf_info abinfo; - int id, i; - - val = 0; - switch (cmd) { - case OSS_GETVERSION: - return put_user(SOUND_VERSION, (int *)arg); - case SNDCTL_DSP_RESET: -#if 0 - jz_audio_reset(); - __i2s_disable_replay(); - __i2s_disable_receive_dma(); - __i2s_disable_record(); - __i2s_disable_transmit_dma(); -#endif - return 0; - case SNDCTL_DSP_SYNC: - if (file->f_mode & FMODE_WRITE) - return drain_dac(controller, file->f_flags & O_NONBLOCK); - return 0; - case SNDCTL_DSP_SPEED: - /* set smaple rate */ - if (get_user(val, (int *)arg)) - return -EFAULT; - if (val >= 0) - jz_audio_set_speed(controller->dev_audio, val); - - return put_user(val, (int *)arg); - case SNDCTL_DSP_STEREO: - /* set stereo or mono channel */ - if (get_user(val, (int *)arg)) - return -EFAULT; - jz_audio_set_channels(controller->dev_audio, val ? 2 : 1); - - return 0; - case SNDCTL_DSP_GETBLKSIZE: - //return put_user(jz_audio_fragsize / jz_audio_b, (int *)arg); - return put_user(jz_audio_fragsize, (int *)arg); - case SNDCTL_DSP_GETFMTS: - /* Returns a mask of supported sample format*/ - return put_user(AFMT_U8 | AFMT_S16_LE, (int *)arg); - case SNDCTL_DSP_SETFMT: - /* Select sample format */ - if (get_user(val, (int *)arg)) - return -EFAULT; - if (val != AFMT_QUERY) - jz_audio_set_format(controller->dev_audio,val); - else { - if (file->f_mode & FMODE_READ) - val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; - else - val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; - } - - return put_user(val, (int *)arg); - case SNDCTL_DSP_CHANNELS: - if (get_user(val, (int *)arg)) - return -EFAULT; - jz_audio_set_channels(controller->dev_audio, val); - - return put_user(val, (int *)arg); - case SNDCTL_DSP_POST: - /* FIXME: the same as RESET ?? */ - return 0; - case SNDCTL_DSP_SUBDIVIDE: - return 0; - case SNDCTL_DSP_SETFRAGMENT: - get_user(val, (long *) arg); - newfragsize = 1 << (val & 0xFFFF); - if (newfragsize < 4 * PAGE_SIZE) - newfragsize = 4 * PAGE_SIZE; - if (newfragsize > (16 * PAGE_SIZE)) - newfragsize = 16 * PAGE_SIZE; - - newfragstotal = (val >> 16) & 0x7FFF; - if (newfragstotal < 2) - newfragstotal = 2; - if (newfragstotal > 32) - newfragstotal = 32; - if((jz_audio_fragstotal == newfragstotal) && (jz_audio_fragsize == newfragsize)) - return 0; - Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); - mdelay(500); - jz_audio_fragstotal = newfragstotal; - jz_audio_fragsize = newfragsize; - - Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); - mdelay(10); - - return 0; - case SNDCTL_DSP_GETCAPS: - return put_user(DSP_CAP_REALTIME|DSP_CAP_BATCH, (int *)arg); - case SNDCTL_DSP_NONBLOCK: - file->f_flags |= O_NONBLOCK; - return 0; - case SNDCTL_DSP_SETDUPLEX: - return -EINVAL; - case SNDCTL_DSP_GETOSPACE: - { - int i; - unsigned long bytes = 0; - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - - //spin_lock_irqsave(&controller->ioctllock, flags); - spin_lock(&controller->ioctllock); - jz_audio_fragments = elements_in_queue(&out_empty_queue); - for (i = 0; i < jz_audio_fragments; i++) - bytes += jz_audio_fragsize; - - if (jz_audio_channels == 2) - bytes /= jz_audio_b; - else if (jz_audio_channels == 1) - bytes /= 4; - else - printk("SNDCTL_DSP_GETOSPACE : channels is wrong 1!\n"); - - //spin_unlock_irqrestore(&controller->ioctllock, flags); - spin_unlock(&controller->ioctllock); - /* unused fragment amount */ - abinfo.fragments = jz_audio_fragments; - /* amount of fragments */ - abinfo.fragstotal = jz_audio_fragstotal; - /* fragment size in bytes */ - if (jz_audio_channels == 2) - abinfo.fragsize = jz_audio_fragsize / jz_audio_b; - else if (jz_audio_channels == 1) - abinfo.fragsize = jz_audio_fragsize / 4; - else - printk("SNDCTL_DSP_GETOSPACE : channels is wrong 2!\n"); - - /* write size count without blocking in bytes */ - abinfo.bytes = (int)bytes; - - return copy_to_user((void *)arg, &abinfo, - sizeof(abinfo)) ? -EFAULT : 0; - } - case SNDCTL_DSP_GETISPACE: - { - int i; - unsigned long bytes = 0; - if (!(file->f_mode & FMODE_READ)) - return -EINVAL; - jz_audio_fragments = elements_in_queue(&in_empty_queue); - for (i = 0; i < jz_audio_fragments; i++) - bytes += jz_audio_fragsize; - - if (jz_audio_channels == 2) - bytes /= jz_audio_b; - else if (jz_audio_channels == 1) - bytes /= 4; - else - printk("SNDCTL_DSP_GETISPACE : channels is wrong 1!\n"); - - abinfo.fragments = jz_audio_fragments; - abinfo.fragstotal = jz_audio_fragstotal; - - if (jz_audio_channels == 2) - abinfo.fragsize = jz_audio_fragsize / jz_audio_b; - else if (jz_audio_channels == 1) - abinfo.fragsize = jz_audio_fragsize / 4; - else - printk("SNDCTL_DSP_GETISPACE : channels is wrong 2!\n"); - - abinfo.bytes = (int)bytes; - - return copy_to_user((void *)arg, &abinfo, - sizeof(abinfo)) ? -EFAULT : 0; - } - case SNDCTL_DSP_GETTRIGGER: - val = 0; - if (file->f_mode & FMODE_READ && in_dma_buf) - val |= PCM_ENABLE_INPUT; - if (file->f_mode & FMODE_WRITE && out_dma_buf) - val |= PCM_ENABLE_OUTPUT; - - return put_user(val, (int *)arg); - case SNDCTL_DSP_SETTRIGGER: - if (get_user(val, (int *)arg)) - return -EFAULT; - return 0; - case SNDCTL_DSP_GETIPTR: - if (!(file->f_mode & FMODE_READ)) - return -EINVAL; - - //spin_lock_irqsave(&controller->ioctllock, flags); - spin_lock(&controller->ioctllock); - cinfo.bytes = controller->total_bytes; - cinfo.blocks = controller->blocks; - cinfo.ptr = controller->nextIn; - controller->blocks = 0; - //spin_unlock_irqrestore(&controller->ioctllock, flags); - spin_unlock(&controller->ioctllock); - - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); - case SNDCTL_DSP_GETOPTR: - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - - //spin_lock_irqsave(&controller->ioctllock, flags); - spin_lock(&controller->ioctllock); - cinfo.bytes = controller->total_bytes; - cinfo.blocks = controller->blocks; - cinfo.ptr = controller->nextOut; - controller->blocks = 0; - //spin_unlock_irqrestore(&controller->ioctllock, flags); - spin_unlock(&controller->ioctllock); - - return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); - case SNDCTL_DSP_GETODELAY: - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - - //spin_lock_irqsave(&controller->ioctllock, flags); - spin_lock(&controller->ioctllock); - unfinish = 0; - fullc = elements_in_queue(&out_full_queue); - busyc = elements_in_queue(&out_busy_queue); - for(i = 0;i < fullc ;i ++) { - id = *(out_full_queue.id + i); - unfinish += *(out_dma_buf_data_count + id); - } - for(i = 0;i < busyc ;i ++) { - id = *(out_busy_queue.id + i); - unfinish += get_dma_residue(controller->dma1); - } - //spin_unlock_irqrestore(&controller->ioctllock, flags); - spin_unlock(&controller->ioctllock); - - if (jz_audio_channels == 2) - unfinish /= jz_audio_b; - else if (jz_audio_channels == 1) - unfinish /= 4; - else - printk("SNDCTL_DSP_GETODELAY : channels is wrong !\n"); - - return put_user(unfinish, (int *) arg); - case SOUND_PCM_READ_RATE: - return put_user(jz_audio_rate, (int *)arg); - case SOUND_PCM_READ_CHANNELS: - return put_user(jz_audio_channels, (int *)arg); - case SOUND_PCM_READ_BITS: - return put_user((jz_audio_format & (AFMT_S8 | AFMT_U8)) ? 8 : 16, (int *)arg); - case SNDCTL_DSP_MAPINBUF: - case SNDCTL_DSP_MAPOUTBUF: - case SNDCTL_DSP_SETSYNCRO: - case SOUND_PCM_WRITE_FILTER: - case SOUND_PCM_READ_FILTER: - return -EINVAL; - } - return -EINVAL; -} - - -static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait) -{ - struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; - unsigned int mask = 0; - - if (file->f_mode & FMODE_WRITE) { - if (elements_in_queue(&out_empty_queue) > 0) - return POLLOUT | POLLWRNORM; - - poll_wait(file, &controller->dac_wait, wait); - } - - if (file->f_mode & FMODE_READ) { - if (elements_in_queue(&in_full_queue) > 0) - return POLLIN | POLLRDNORM; - - poll_wait(file, &controller->adc_wait, wait); - } - - //spin_lock_irqsave(&controller->lock, flags); - spin_lock(&controller->lock); - if (file->f_mode & FMODE_WRITE) { - if (elements_in_queue(&out_empty_queue) > 0) - mask |= POLLOUT | POLLWRNORM; - } else if (file->f_mode & FMODE_READ) { - if (elements_in_queue(&in_full_queue) > 0) - mask |= POLLIN | POLLRDNORM; - } - //spin_unlock_irqrestore(&controller->lock, flags); - spin_unlock(&controller->lock); - - return mask; -} - -static ssize_t jz_audio_read(struct file *file, char *buffer, size_t count, loff_t *ppos) -{ - struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; - int id, ret = 0, left_count, copy_count, cnt = 0; - - if (count < 0) - return -EINVAL; - - __i2s_enable_receive_dma(); - __i2s_enable_record(); - - //spin_lock_irqsave(&controller->ioctllock, flags); - spin_lock(&controller->ioctllock); - controller->nextIn = 0; - //spin_unlock_irqrestore(&controller->ioctllock, flags); - spin_unlock(&controller->ioctllock); - - copy_count = jz_audio_fragsize / 4; - - left_count = count; - if (first_record_call) { - first_record_call = 0; - audio_read_back_first: - if ((id = get_buffer_id(&in_empty_queue)) >= 0) { - put_buffer_id(&in_busy_queue, id); - spin_lock(&controller->lock); - *(in_dma_buf_data_count + id) = copy_count * 4; - - spin_unlock(&controller->lock); - __i2s_enable_receive_dma(); - __i2s_enable_record(); - dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); - audio_start_dma(controller->dma2,file->private_data, - *(in_dma_pbuf + id), - *(in_dma_buf_data_count + id), - DMA_MODE_READ); - sleep_on(&rx_wait_queue); - } else - goto audio_read_back_first; - } - - while (left_count > 0) { - audio_read_back_second: - if (elements_in_queue(&in_full_queue) <= 0) { - if (file->f_flags & O_NONBLOCK) - return ret ? ret : -EAGAIN; - else - sleep_on(&rx_wait_queue); - } - - if ((id = get_buffer_id(&in_full_queue)) >= 0) { - spin_lock(&controller->lock); - cnt = record_filler((unsigned long)controller->tmp2+ret, copy_count, id); - spin_unlock(&controller->lock); - put_buffer_id(&in_empty_queue, id); - } else - goto audio_read_back_second; - - if (elements_in_queue(&in_busy_queue) == 0) { - if ((id=get_buffer_id(&in_empty_queue)) >= 0) { - put_buffer_id(&in_busy_queue, id); - spin_lock(&controller->lock); - *(in_dma_buf_data_count + id) = copy_count * 4; - spin_unlock(&controller->lock); - - dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); - audio_start_dma(controller->dma2,file->private_data, - *(in_dma_pbuf + id), - *(in_dma_buf_data_count + id), - DMA_MODE_READ); - } - } - if (ret + cnt > count) { - spin_lock(&controller->lock); - cnt = count - ret; - spin_unlock(&controller->lock); - } - if (copy_to_user(buffer+ret, controller->tmp2+ret, cnt)) - return ret ? ret : -EFAULT; - - spin_lock(&controller->lock); - ret += cnt; - spin_unlock(&controller->lock); - - //spin_lock_irqsave(&controller->ioctllock, flags); - spin_lock(&controller->ioctllock); - controller->nextIn += ret; - //spin_unlock_irqrestore(&controller->ioctllock, flags); - spin_unlock(&controller->ioctllock); - - spin_lock(&controller->lock); - left_count -= cnt; - spin_unlock(&controller->lock); - } - return ret; -} - -static ssize_t jz_audio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) -{ - int id, ret = 0, left_count, copy_count = 0; - struct jz_i2s_controller_info *controller = (struct jz_i2s_controller_info *) file->private_data; - - if (count <= 0) - return -EINVAL; - - if(set_replay_hp_or_speaker) - set_replay_hp_or_speaker(); - - __i2s_enable_transmit_dma(); - __i2s_enable_replay(); - - //spin_lock_irqsave(&controller->ioctllock, flags); - spin_lock(&controller->ioctllock); - controller->nextOut = 0; - //spin_unlock_irqrestore(&controller->ioctllock, flags); - spin_unlock(&controller->ioctllock); - if (jz_audio_channels == 2) - copy_count = jz_audio_fragsize / jz_audio_b; - else if(jz_audio_channels == 1) - copy_count = jz_audio_fragsize / 4; - left_count = count; - if (copy_from_user(controller->tmp1, buffer, count)) { - printk("copy_from_user failed:%d",ret); - return ret ? ret : -EFAULT; - } - - while (left_count > 0) { - audio_write_back: - if (file->f_flags & O_NONBLOCK) - udelay(2); - if (elements_in_queue(&out_empty_queue) == 0) { - if (file->f_flags & O_NONBLOCK) - return ret; - else - sleep_on(&tx_wait_queue); - } - /* the end fragment size in this write */ - if (ret + copy_count > count) - copy_count = count - ret; - if ((id = get_buffer_id(&out_empty_queue)) >= 0) { - replay_filler((signed long)controller->tmp1 + ret, copy_count, id); - if(*(out_dma_buf_data_count + id) > 0) { - put_buffer_id(&out_full_queue, id); - dma_cache_wback_inv(*(out_dma_buf + id), *(out_dma_buf_data_count + id)); - } else - put_buffer_id(&out_empty_queue, id); - } else - goto audio_write_back; - - left_count = left_count - copy_count; - ret += copy_count; - - //spin_lock_irqsave(&controller->ioctllock, flags); - spin_lock(&controller->ioctllock); - controller->nextOut += ret; - //spin_unlock_irqrestore(&controller->ioctllock, flags); - spin_unlock(&controller->ioctllock); - - if (elements_in_queue(&out_busy_queue) == 0) { - if ((id=get_buffer_id(&out_full_queue)) >= 0) { - put_buffer_id(&out_busy_queue, id); - if(*(out_dma_buf_data_count + id) > 0) { - audio_start_dma(controller->dma1, - file->private_data, - *(out_dma_pbuf + id), - *(out_dma_buf_data_count + id), - DMA_MODE_WRITE); - last_dma_buffer_id = id; -#if defined(CONFIG_I2S_DLV) - if (jz_codec_config == 0) { - write_codec_file_bit(1, 0, 5); - gain_up_start = jiffies; - sleep_on(&pop_wait_queue); - //gain_up_end = jiffies; - jz_codec_config = 1; - //SB_ADC->1 - //write_codec_file_bit(5, 1, 4); - //while(1); - } -#endif - } - } - } - } - - return ret; -} - -#if defined(CONFIG_I2S_ICODEC) -static void write_mute_to_dma_buffer(signed long l_sample, signed long r_sample) -{ - int i,step_len; - unsigned long *pop_buf = (unsigned long*)pop_turn_onoff_buf; - unsigned int sample_oss = (REG_AIC_CR & 0x00380000) >> 19; - unsigned long l_sample_count,r_sample_count,sample_count; - struct jz_i2s_controller_info *controller = i2s_controller; - signed int left_sam=0,right_sam=0,l_val,r_val; - - switch (sample_oss) { - case 0x0: - break; - case 0x1: - left_sam = (signed int)l_sample; - right_sam = (signed int)r_sample; - break; - case 0x2: - break; - case 0x3: - break; - case 0x4: - break; - } - - if(left_sam == 0 && right_sam == 0) - return; - - switch (sample_oss) { - case 0x0: - break; - case 0x1: - step_len = jz_audio_speed / 10 * 3; - step_len = step_len / 2; - step_len = 0x7fff / step_len + 1; - - l_sample_count = 0; - l_val = left_sam; - - while(1) { - if(l_val > 0) { - if(l_val >= step_len) { - l_val -= step_len; - l_sample_count ++; - } else - break; - } - - if(l_val < 0) { - if(l_val <= -step_len) { - l_val += step_len; - l_sample_count ++; - } else - break; - } - - if(l_val == 0) - break; - } - - r_sample_count = 0; - r_val = right_sam; - while(1) { - if(r_val > 0) { - if(r_val >= step_len) { - r_val -= step_len; - r_sample_count ++; - } else - break; - } - - if(r_val < 0) { - if(r_val <= -step_len) { - r_val += step_len; - r_sample_count ++; - } else - break; - } - - if(r_val == 0) - break; - } - /* fill up */ - if(l_sample_count > r_sample_count) - sample_count = l_sample_count; - else - sample_count = r_sample_count; - - l_val = left_sam; - r_val = right_sam; - for(i=0;i <= sample_count;i++) { - - *pop_buf = (unsigned long)l_val; - pop_buf ++; - - if(l_val > step_len) - l_val -= step_len; - else if(l_val < -step_len) - l_val += step_len; - else if(l_val >= -step_len && l_val <= step_len) - l_val = 0; - - *pop_buf = (unsigned long)r_val; - pop_buf ++; - if(r_val > step_len) - r_val -= step_len; - else if(r_val < -step_len) - r_val += step_len; - else if(r_val >= -step_len && r_val <= step_len) - r_val = 0; - } - - *pop_buf = 0; - pop_buf ++; - *pop_buf = 0; - - pop_buf ++; - sample_count += 2; - dma_cache_wback_inv(pop_turn_onoff_buf, sample_count*8); - - pop_dma_flag = 1; - audio_start_dma(controller->dma1,controller,pop_turn_onoff_pbuf,sample_count*8,DMA_MODE_WRITE); - sleep_on(&pop_wait_queue); - pop_dma_flag = 0; - break; - case 0x2: - break; - case 0x3: - break; - case 0x4: - break; - } -} -#endif diff --git a/target/linux/xburst/files-2.6.27/sound/oss/jz_pcm_tlv320aic1106_dma.c b/target/linux/xburst/files-2.6.27/sound/oss/jz_pcm_tlv320aic1106_dma.c deleted file mode 100644 index 1a1f4cfad..000000000 --- a/target/linux/xburst/files-2.6.27/sound/oss/jz_pcm_tlv320aic1106_dma.c +++ /dev/null @@ -1,1839 +0,0 @@ -/* - * linux/drivers/sound/jz_pcm_tlv320aic1106.c - * - * JzSOC On-Chip PCM audio driver. - * - * Copyright (C) 2005 by Ingenic Corp. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Because the normal application of AUDIO devices are focused on Little_endian, - * then we only perform the little endian data format in driver. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sound_config.h" - -#define NR_PCM 2 -#define MAXDELAY 50000 -#define JZCODEC_RW_BUFFER_SIZE 4 -#define JZCODEC_RW_BUFFER_TOTAL 3 -#define JZCODEC_USER_BUFFER 6 - -#define MODE_is_8 0 // 1 is 8 bits, and 0 is 16 bits - -static int jz_audio_rate; -static char jz_audio_format; -static char jz_audio_volume; -static char jz_audio_channels; -static int jz_audio_fragments;//unused fragment amount -static int jz_audio_fragstotal; -static int jz_audio_fragsize; -static int jz_audio_speed; -static int jz_audio_dma_tran_count;//bytes count of one DMA transfer - -static void jz_update_filler(int bits, int channels); -static int Init_In_Out_queue(int fragstotal,int fragsize); -static int Free_In_Out_queue(int fragstotal,int fragsize); -static irqreturn_t jz_pcm_irq(int irqnr, void *ref); -static irqreturn_t jz_pcm_replay_dma_irq(int irqnr, void *ref); -static irqreturn_t jz_pcm_record_dma_irq(int irqnr, void *ref); -static void (*replay_filler)(unsigned long src_start, int count, int id); -static int (*record_filler)(unsigned long dst_start, int count, int id); -static void dump_pcmc_reg(void); - -static struct file_operations jz_pcm_audio_fops; -static DECLARE_WAIT_QUEUE_HEAD (rx_wait_queue); -static DECLARE_WAIT_QUEUE_HEAD (tx_wait_queue); - -struct jz_pcm_controller_info { - int io_base; - int dma1; /* play */ - int dma2; /* record */ - char *name; - int dev_audio; - struct pcm_codec *pcm_codec[NR_PCM]; - int opened1; - int opened2; - unsigned char *tmp1; /* tmp buffer for sample conversions */ - unsigned char *tmp2; - spinlock_t lock; - spinlock_t ioctllock; - - wait_queue_head_t dac_wait; - wait_queue_head_t adc_wait; - int nextIn; // byte index to next-in to DMA buffer - int nextOut; // byte index to next-out from DMA buffer - int count; // current byte count in DMA buffer - int finish; // current transfered byte count in DMA buffer - unsigned long total_bytes; // total bytes written or read - unsigned long blocks; - unsigned long error; // over/underrun -}; -static struct jz_pcm_controller_info *pcm_controller = NULL; - -struct pcm_codec { - /* PCM controller connected with */ - void *private_data; - char *name; - int id; - int dev_mixer; - /* controller specific lower leverl pcm accessing routines */ - u16 (*codec_read) (u8 reg);//the function accessing Codec REGs - void (*codec_write) (u8 reg, u16 val); - /* Wait for codec-ready. Ok to sleep here. */ - void (*codec_wait) (struct pcm_codec *codec); - /* OSS mixer masks */ - int modcnt; - int supported_mixers; - int stereo_mixers; - int record_sources; - int bit_resolution; - /* OSS mixer interface */ - int (*read_mixer) (struct pcm_codec *codec, int oss_channel); - void (*write_mixer)(struct pcm_codec *codec, int oss_channel, - unsigned int left, unsigned int right); - int (*recmask_io) (struct pcm_codec *codec, int rw, int mask); - int (*mixer_ioctl)(struct pcm_codec *codec, unsigned int cmd, unsigned long arg); - /* saved OSS mixer states */ - unsigned int mixer_state[SOUND_MIXER_NRDEVICES]; -}; - -typedef struct buffer_queue_s { - int count; - int *id; - int lock; -} buffer_queue_t; - -static unsigned long *out_dma_buf = NULL; -static unsigned long *out_dma_pbuf = NULL; -static unsigned long *out_dma_buf_data_count = NULL; -static unsigned long *in_dma_buf = NULL; -static unsigned long *in_dma_pbuf = NULL; -static unsigned long *in_dma_buf_data_count = NULL; - -static buffer_queue_t out_empty_queue; -static buffer_queue_t out_full_queue; -static buffer_queue_t out_busy_queue; -static buffer_queue_t in_empty_queue; -static buffer_queue_t in_full_queue; -static buffer_queue_t in_busy_queue; -static int first_record_call = 0; - -static inline int get_buffer_id(struct buffer_queue_s *q) -{ - int r, i; - unsigned long flags; - - spin_lock_irqsave(&q->lock, flags); - if (q->count == 0) { - spin_unlock_irqrestore(&q->lock, flags); - return -1; - } - r = *(q->id + 0); - for (i=0;i < q->count-1;i++) - *(q->id + i) = *(q->id + (i+1)); - q->count --; - spin_unlock_irqrestore(&q->lock, flags); - - return r; -} - -static inline void put_buffer_id(struct buffer_queue_s *q, int id) -{ - unsigned long flags; - - spin_lock_irqsave(&q->lock, flags); - *(q->id + q->count) = id; - q->count ++; - spin_unlock_irqrestore(&q->lock, flags); -} - -static inline int elements_in_queue(struct buffer_queue_s *q) -{ - int r; - unsigned long flags; - - spin_lock_irqsave(&q->lock, flags); - r = q->count; - spin_unlock_irqrestore(&q->lock, flags); - - return r; -} - -static inline void audio_start_dma(int chan, void *dev_id, unsigned long phyaddr,int count, int mode) -{ - unsigned long flags; - struct jz_pcm_controller_info * controller = (struct jz_pcm_controller_info *) dev_id; - - //for DSP_GETOPTR - //spin_lock_irqsave(&controller->ioctllock, flags); - spin_lock(&controller->ioctllock); - jz_audio_dma_tran_count = count; - //spin_unlock_irqrestore(&controller->ioctllock, flags); - spin_unlock(&controller->ioctllock); - flags = claim_dma_lock(); - __dmac_disable_module(0);//!!!!!!!!! - disable_dma(chan); - clear_dma_ff(chan); - set_dma_mode(chan, mode); -#if MODE_is_8 - __dmac_channel_set_src_port_width(chan, 8); - __dmac_channel_set_dest_port_width(chan, 8); - __dmac_channel_set_transfer_unit_8bit(chan); -#else - __dmac_channel_set_src_port_width(chan, 16); - __dmac_channel_set_dest_port_width(chan, 16); - __dmac_channel_set_transfer_unit_16bit(chan); -#endif - - set_dma_addr(chan, phyaddr); - if (count == 0) { - count++; - printk("JzSOC DMA controller can't set dma 0 count!\n"); - } - - set_dma_count(chan, count); - enable_dma(chan); - __dmac_enable_module(0); - release_dma_lock(flags); -#if 0 - //for DSP_GETOPTR on FPGA - struct jz_dma_chan *tmpchan = &jz_dma_table[1]; - - spin_lock(&controller->ioctllock); - jz_audio_dma_tran_count = count; - spin_unlock(&controller->ioctllock); - flags = claim_dma_lock(); - disable_dma(chan); - clear_dma_ff(chan); - set_dma_mode(chan, mode); -#if MODE_is_8 - __dmac_channel_set_src_port_width(chan, 8); - __dmac_channel_set_dest_port_width(chan, 8); - __dmac_channel_set_transfer_unit_8bit(chan); -#else - __dmac_channel_set_src_port_width(chan, 16); - __dmac_channel_set_dest_port_width(chan, 16); - __dmac_channel_set_transfer_unit_16bit(chan); -#endif - set_dma_addr(chan, phyaddr); - if (count == 0) { - count++; - printk("JzSOC DMA controller can't set dma 0 count!\n"); - } - set_dma_count(chan, count); - enable_dma(chan); - release_dma_lock(flags); -#if 0 - __pcm_enable_tfs_intr(); - __pcm_enable_tur_intr(); - __pcm_enable_rfs_intr(); - __pcm_enable_ror_intr(); -#endif -#endif -} - -static irqreturn_t jz_pcm_record_dma_irq(int irq, void *dev_id) -{ - int id1, id2; - struct jz_pcm_controller_info * controller = (struct jz_pcm_controller_info *) dev_id; - int dma = controller->dma2; - - disable_dma(dma); - if (__dmac_channel_address_error_detected(dma)) { - printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); - __dmac_channel_clear_address_error(dma); - } - if (__dmac_channel_transmit_end_detected(dma)) { - __dmac_channel_clear_transmit_end(dma); - //for DSP_GETIPTR - spin_lock(&controller->ioctllock); - controller->total_bytes += jz_audio_dma_tran_count; - controller->blocks ++; - spin_unlock(&controller->ioctllock); - id1 = get_buffer_id(&in_busy_queue); - put_buffer_id(&in_full_queue, id1); - - wake_up(&rx_wait_queue); - wake_up(&controller->adc_wait); - if ((id2 = get_buffer_id(&in_empty_queue)) >= 0) { - put_buffer_id(&in_busy_queue, id2); - *(in_dma_buf_data_count + id2) = *(in_dma_buf_data_count + id1); - - dma_cache_wback_inv(*(in_dma_buf + id2), *(in_dma_buf_data_count + id2)); - audio_start_dma(dma,dev_id, - *(in_dma_pbuf + id2), - *(in_dma_buf_data_count + id2), - DMA_MODE_READ); - } else - in_busy_queue.count = 0; - } - - return IRQ_HANDLED; -} - -static irqreturn_t jz_pcm_irq(int irq, void *dev_id) -{ - struct jz_pcm_controller_info * controller = (struct jz_pcm_controller_info *) dev_id; - printk("pcm interrupt REG_PCM_INTS : 0x%08x\n",REG_PCM_INTS); - - return IRQ_HANDLED; -} - -static irqreturn_t jz_pcm_replay_dma_irq(int irq, void *dev_id) -{ - int id; - unsigned long flags; - struct jz_pcm_controller_info * controller = (struct jz_pcm_controller_info *) dev_id; - int dma = controller->dma1; - - disable_dma(dma); - if (__dmac_channel_address_error_detected(dma)) { - printk(KERN_DEBUG "%s: DMAC address error.\n", __FUNCTION__); - __dmac_channel_clear_address_error(dma); - } - if (__dmac_channel_transmit_end_detected(dma)) { - __dmac_channel_clear_transmit_end(dma); - //for DSP_GETOPTR - spin_lock_irqsave(&controller->ioctllock, flags); - controller->total_bytes += jz_audio_dma_tran_count; - controller->blocks ++; - spin_unlock_irqrestore(&controller->ioctllock, flags); - if ((id = get_buffer_id(&out_busy_queue)) < 0) - printk(KERN_DEBUG "Strange DMA finish interrupt for PCM module\n"); - put_buffer_id(&out_empty_queue, id); - if ((id = get_buffer_id(&out_full_queue)) >= 0) { - put_buffer_id(&out_busy_queue, id); //very busy - if(*(out_dma_buf_data_count + id) > 0) { - audio_start_dma(dma, dev_id, *(out_dma_pbuf + id), - *(out_dma_buf_data_count + id), - DMA_MODE_WRITE); - } - } else - out_busy_queue.count = 0; - - if (elements_in_queue(&out_empty_queue) > 0) { - wake_up(&tx_wait_queue); - wake_up(&controller->dac_wait); - } - } - - return IRQ_HANDLED; -} - -static int Init_In_Out_queue(int fragstotal,int fragsize) -{ - int i; - // recording - in_empty_queue.count = fragstotal; - in_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - if (!in_dma_buf) - goto all_mem_err; - in_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - if (!in_dma_pbuf) - goto all_mem_err; - in_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - if (!in_dma_buf_data_count) - goto all_mem_err; - in_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!in_empty_queue.id) - goto all_mem_err; - in_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!in_full_queue.id) - goto all_mem_err; - in_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!in_busy_queue.id) - goto all_mem_err; - - for (i=0;i < fragstotal;i++) - *(in_empty_queue.id + i) = i; - in_full_queue.count = 0; - in_busy_queue.count = 0; - - for (i = 0; i < fragstotal; i++) { - *(in_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); - if (*(in_dma_buf + i) == 0) - goto mem_failed_in; - *(in_dma_pbuf + i) = virt_to_phys((void *)(*(in_dma_buf + i))); - dma_cache_wback_inv(*(in_dma_buf + i), fragsize); - } - - //playing - out_empty_queue.count = fragstotal; - out_dma_buf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - if (!out_dma_buf) - goto all_mem_err; - out_dma_pbuf = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - if (!out_dma_pbuf) - goto all_mem_err; - out_dma_buf_data_count = (unsigned long *)kmalloc(sizeof(unsigned long) * fragstotal, GFP_KERNEL); - - if (!out_dma_buf_data_count) - goto all_mem_err; - out_empty_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!out_empty_queue.id) - goto all_mem_err; - out_full_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!out_full_queue.id) - goto all_mem_err; - out_busy_queue.id = (int *)kmalloc(sizeof(int) * fragstotal, GFP_KERNEL); - if (!out_busy_queue.id) - goto all_mem_err; - for (i=0;i < fragstotal;i++) - *(out_empty_queue.id + i) = i; - - out_busy_queue.count = 0; - out_full_queue.count = 0; - /*alloc DMA buffer*/ - for (i = 0; i < fragstotal; i++) { - *(out_dma_buf + i) = __get_free_pages(GFP_KERNEL | GFP_DMA, get_order(fragsize)); - if (*(out_dma_buf + i) == 0) { - printk(" can't allocate required DMA(OUT) buffers.\n"); - goto mem_failed_out; - } - *(out_dma_pbuf + i) = virt_to_phys((void *)(*(out_dma_buf + i))); - } - - return 1; -all_mem_err: - printk("error:allocate memory occur error 1!\n"); - return 0; -mem_failed_out: - printk("error:allocate memory occur error 2!\n"); - for (i = 0; i < fragstotal; i++) { - if(*(out_dma_buf + i)) - free_pages(*(out_dma_buf + i), get_order(fragsize)); - } - - return 0; -mem_failed_in: - printk("error:allocate memory occur error 3!\n"); - for (i = 0; i < fragstotal; i++) { - if(*(in_dma_buf + i)) - free_pages(*(in_dma_buf + i), get_order(fragsize)); - } - return 0; -} - -static int Free_In_Out_queue(int fragstotal,int fragsize) -{ - int i; - //playing - if(out_dma_buf != NULL) { - for (i = 0; i < fragstotal; i++) { - if(*(out_dma_buf + i)) - free_pages(*(out_dma_buf + i), get_order(fragsize)); - *(out_dma_buf + i) = 0; //release page error - } - kfree(out_dma_buf); - out_dma_buf = NULL; - } - if(out_dma_pbuf) { - kfree(out_dma_pbuf); - out_dma_pbuf = NULL; - } - if(out_dma_buf_data_count) { - kfree(out_dma_buf_data_count); - out_dma_buf_data_count = NULL; - } - if(out_empty_queue.id) { - kfree(out_empty_queue.id); - out_empty_queue.id = NULL; - } - if(out_full_queue.id) { - kfree(out_full_queue.id); - out_full_queue.id = NULL; - } - if(out_busy_queue.id) { - kfree(out_busy_queue.id); - out_busy_queue.id = NULL; - } - out_empty_queue.count = fragstotal; - out_busy_queue.count = 0; - out_full_queue.count = 0; - - // recording - if(in_dma_buf) { - for (i = 0; i < fragstotal; i++) { - if(*(in_dma_buf + i)) { - dma_cache_wback_inv(*(in_dma_buf + i), fragsize); - free_pages(*(in_dma_buf + i), get_order(fragsize)); - } - *(in_dma_buf + i) = 0; //release page error - } - kfree(in_dma_buf); - in_dma_buf = NULL; - } - if(in_dma_pbuf) { - kfree(in_dma_pbuf); - in_dma_pbuf = NULL; - } - if(in_dma_buf_data_count) { - kfree(in_dma_buf_data_count); - in_dma_buf_data_count = NULL; - } - if(in_empty_queue.id) { - kfree(in_empty_queue.id); - in_empty_queue.id = NULL; - } - if(in_full_queue.id) { - kfree(in_full_queue.id); - in_full_queue.id = NULL; - } - if(in_busy_queue.id) { - kfree(in_busy_queue.id); - in_busy_queue.id = NULL; - } - - in_empty_queue.count = fragstotal; - in_full_queue.count = 0; - in_busy_queue.count = 0; - - return 1; -} - -static int jz_audio_set_speed(int dev, int rate) -{ - /* 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000 */ - long codec_speed; - long speed = 0; - - jz_audio_speed = rate; - if (rate > 48000) - rate = 48000; - if (rate < 8000) - rate = 8000; - jz_audio_rate = rate; - - /*switch (rate) { - case 8000: - speed = 0; - break; - case 11025: - speed = 1; - break; - case 12000: - speed = 2; - break; - case 16000: - speed = 3; - break; - case 22050: - speed = 4; - break; - case 24000: - speed = 5; - break; - case 32000: - speed = 6; - break; - case 44100: - speed = 7; - break; - case 48000: - speed = 8; - break; - default: - break; - } - printk("set PCMIN or PCMOUT speed.\n"); - __pcm_set_clk_rate(speed); - __pcm_set_sync_rate(256);*/ - - return jz_audio_rate; -} - - -static int record_fill_1x8_u(unsigned long dst_start, int count, int id) -{ - int cnt = 0; - volatile unsigned char *s = (unsigned char*)(*(in_dma_buf + id)); - volatile unsigned char *dp = (unsigned char*)dst_start; - - while (count > 0) { - *dp = *s; - dp ++; - s++; - count --; - cnt ++; - } - - return cnt; -} - -static int record_fill_2x8_u(unsigned long dst_start, int count, int id) -{ - int cnt = 0; - volatile unsigned char *s = (unsigned char*)(*(in_dma_buf + id)); - volatile unsigned char *dp = (unsigned char*)dst_start; - -#if 1 - while (count > 0) { - *dp = *s; - s ++; - dp ++; - count --; - cnt ++; - } -#else - while (count > 0) { - *dp = *s; - s += 2; //skip right sample - dp ++; - count -= 2; - cnt ++; - } -#endif - return cnt; -} - -static int record_fill_1x16_s(unsigned long dst_start, int count, int id) -{ - int cnt = 0; - unsigned short d1; - unsigned short *s = (unsigned short*)(*(in_dma_buf + id)); - unsigned short *dp = (unsigned short *)dst_start; - - while (count > 0) { - *dp = *s; - s ++; - dp ++; - count -= 2; - cnt += 2; - } - - return cnt; -} - -static int record_fill_2x16_s(unsigned long dst_start, int count, int id) -{ - int cnt = 0; - unsigned short *s = (unsigned short*)(*(in_dma_buf + id)); - unsigned short *dp = (unsigned short *)dst_start; - -#if 1 - while (count > 0) { - *dp = *s; - s ++; - dp ++; - count -= 2; - cnt += 2; - } -#else - while (count > 0) { - *dp = *s; - s += 2; //skip right sample - dp ++; - count -= 4; - cnt += 2;/* count in byte */ - } -#endif - - return cnt; -} - -static void replay_fill_1x8_u(unsigned long src_start, int count, int id) -{ -#if 0 - volatile unsigned char *s = (unsigned char *)src_start; - volatile unsigned char *dp = (unsigned char *)(*(out_dma_buf + id)); - - *(out_dma_buf_data_count + id) = count; - while (count > 0) { - *dp = *s; - dp ++; - s ++; - count --; - } -#else - volatile u8 *s = (u8 *)src_start; - volatile u8 *dp = (u8 *)(*(out_dma_buf + id)); - - *(out_dma_buf_data_count + id) = count; - while (count > 0) { - *dp = *s; - dp ++; - s ++; - count --; - } -#endif -} - -static void replay_fill_2x8_u(unsigned long src_start, int count, int id) -{ - volatile unsigned char *s = (unsigned char *)src_start; - volatile unsigned char *dp = (unsigned char *)(*(out_dma_buf + id)); - -#if 1 - *(out_dma_buf_data_count + id) = count; - while (count > 0) { - *dp = *s; - dp ++; - s ++; - count --; - } -#else - while (count > 0) { - *dp = *s; - s += 2; //skip right sample - dp ++; - count -= 2; - cnt ++; - } - *(out_dma_buf_data_count + id) = cnt; -#endif -} - - -static void replay_fill_1x16_s(unsigned long src_start, int count, int id) -{ - int cnt = 0; - unsigned short d1, l1; - signed short sam_to; - volatile unsigned short *s = (unsigned short *)src_start; - volatile unsigned short *dp = (unsigned short*)(*(out_dma_buf + id)); - - while (count > 0) { - d1 = *s; - - sam_to = (signed short)d1; - if (sam_to >= 0) { - sam_to = 0xfff * sam_to / 0x7fff; - } else { - sam_to = 0 - sam_to; - sam_to = 0xfff * sam_to / 0x7fff; - sam_to = 0 - sam_to; - } - d1 = (unsigned short)sam_to; - d1 = d1 << 3; - l1 = d1 | jz_audio_volume; - - *dp = l1; - s ++; - dp ++; - count -= 2; - cnt += 2 ; - } - *(out_dma_buf_data_count + id) = cnt; -} - -static void replay_fill_2x16_s(unsigned long src_start, int count, int id) -{ - int cnt = 0; - unsigned short d1, l1; - volatile unsigned short *s = (unsigned short *)src_start; - volatile unsigned short *dp = (unsigned short*)(*(out_dma_buf + id)); - -#if 1 - while (count > 0) { - d1 = *s; - l1 = (d1 & 0xfff8) | jz_audio_volume; - *dp = l1; - s ++; - dp ++; - count -= 2; - cnt += 2 ; - } - *(out_dma_buf_data_count + id) = cnt; -#else - while (count > 0) { - d1 = *s; - l1 = (d1 & 0xfff8) | jz_audio_volume; - *dp = l1; - s += 2; //skip right sample - dp ++; - count -= 4; - cnt += 2; - } - *(out_dma_buf_data_count + id) = cnt; -#endif -} - -static unsigned int jz_audio_set_format(int dev, unsigned int fmt) -{ - switch (fmt) { - case AFMT_U8: - case AFMT_S16_LE: - jz_audio_format = fmt; - jz_update_filler(jz_audio_format, jz_audio_channels); - case AFMT_QUERY: - break; - } - - return jz_audio_format; -} - -static short jz_audio_set_channels(int dev, short channels) -{ - switch (channels) { - case 1: - case 2: - jz_audio_channels = channels; - jz_update_filler(jz_audio_format, jz_audio_channels); - break; - default: - printk("channel number is wrong. %d\n",__LINE__); - } - - return jz_audio_channels; -} - -static void init_codec(void) -{ - printk("set PCM codec RESET pin on LOW, while MCLK occur.\n"); - printk("set LINSEL on LOW(8bits) or HIGH(13bits+3bits for PCMOUT gain).\n"); -} - -static void jz_audio_reset(void) -{ - __pcm_flush_fifo(); - __pcm_disable_txfifo(); - __pcm_disable_rxfifo(); - __pcm_set_transmit_trigger(7); - __pcm_set_receive_trigger(7); - __pcm_omsb_next_sync(); - __pcm_imsb_next_sync(); -#if MODE_is_8 - __pcm_set_iss(8);//8bits decided by LINSEL - __pcm_set_oss(8);//8bits decided by LINSEL -#else - __pcm_set_iss(16);//16bits decided by LINSEL - __pcm_set_oss(16); -#endif - __pcm_disable_tfs_intr(); - __pcm_disable_tur_intr(); - __pcm_disable_rfs_intr(); - __pcm_disable_ror_intr(); - - __pcm_disable_receive_dma(); - __pcm_disable_transmit_dma(); - - //init_codec(); -} - -static int jz_audio_release(struct inode *inode, struct file *file); -static int jz_audio_open(struct inode *inode, struct file *file); -static int jz_audio_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg); -static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait); -static ssize_t jz_audio_write(struct file *file, const char *buffer,size_t count, loff_t *ppos); -static ssize_t jz_audio_read(struct file *file, char *buffer,size_t count, loff_t *ppos); - -/* static struct file_operations jz_pcm_audio_fops */ -static struct file_operations jz_pcm_audio_fops = -{ - owner: THIS_MODULE, - open: jz_audio_open, - release: jz_audio_release, - write: jz_audio_write, - read: jz_audio_read, - poll: jz_audio_poll, - ioctl: jz_audio_ioctl -}; - -static int jz_pcm_open_mixdev(struct inode *inode, struct file *file) -{ - int i; - int minor = MINOR(inode->i_rdev); - struct jz_pcm_controller_info *controller = pcm_controller; - - for (i = 0; i < NR_PCM; i++) - if (controller->pcm_codec[i] != NULL && controller->pcm_codec[i]->dev_mixer == minor) - goto match; - - if (!controller) - return -ENODEV; -match: - file->private_data = controller->pcm_codec[i]; - - return 0; -} - -static int jz_pcm_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct pcm_codec *codec = (struct pcm_codec *)file->private_data; - return codec->mixer_ioctl(codec, cmd, arg); -} - -static loff_t jz_pcm_llseek(struct file *file, loff_t offset, int origin) -{ - return -ESPIPE; -} - -static struct file_operations jz_pcm_mixer_fops = -{ - owner: THIS_MODULE, - llseek: jz_pcm_llseek, - ioctl: jz_pcm_ioctl_mixdev, - open: jz_pcm_open_mixdev, -}; - -static int pcm_mixer_ioctl(struct pcm_codec *codec, unsigned int cmd, unsigned long arg) -{ - int ret; - long val = 0; - - switch (cmd) { - case SOUND_MIXER_READ_STEREODEVS: - return put_user(0, (long *) arg); - case SOUND_MIXER_READ_CAPS: - val = SOUND_CAP_EXCL_INPUT; - return put_user(val, (long *) arg); - case SOUND_MIXER_READ_DEVMASK: - break; - case SOUND_MIXER_READ_RECMASK: - break; - case SOUND_MIXER_READ_RECSRC: - break; - case SOUND_MIXER_WRITE_VOLUME: - ret = get_user(val, (long *) arg); - if (ret) - return ret; - val = val & 0xff; - if(val < 0) - val = 0; - if(val > 100) - val = 100; - if (val == 100) { - dump_pcmc_reg(); - return 100; - } - val = val / 10; - switch (val) { - case 0: - case 1: - jz_audio_volume = 7; - break; - case 2: - jz_audio_volume = 6; - break; - case 3: - jz_audio_volume = 5; - break; - case 4: - jz_audio_volume = 4; - break; - case 5: - jz_audio_volume = 3; - break; - case 6: - jz_audio_volume = 2; - break; - case 7: - case 8: - jz_audio_volume = 1; - break; - case 9: - case 10: - jz_audio_volume = 0; - break; - } - return 0; - case SOUND_MIXER_READ_VOLUME: - val = jz_audio_volume; - ret = val << 8; - val = val | ret; - return put_user(val, (long *) arg); - case SOUND_MIXER_WRITE_MIC: - printk("Can not justify Mic gain to the PCM codec.!\n"); - return -ENOSYS; - - case SOUND_MIXER_READ_MIC: - printk("Can not justify Mic gain to the PCM codec.!\n"); - return -ENOSYS; - default: - return -ENOSYS; - } - - return 0; -} - - -int pcm_probe_codec(struct pcm_codec *codec) -{ - /* generic OSS to PCM wrapper */ - codec->mixer_ioctl = pcm_mixer_ioctl; - return 1; -} - -/* PCM codec initialisation. */ -static int __init jz_pcm_codec_init(struct jz_pcm_controller_info *controller) -{ - int num_pcm = 0; - struct pcm_codec *codec; - - for (num_pcm = 0; num_pcm < NR_PCM; num_pcm++) { - if ((codec = kmalloc(sizeof(struct pcm_codec),GFP_KERNEL)) == NULL) - return -ENOMEM; - memset(codec, 0, sizeof(struct pcm_codec)); - codec->private_data = controller; - codec->id = num_pcm; - - if (pcm_probe_codec(codec) == 0) - break; - if ((codec->dev_mixer = register_sound_mixer(&jz_pcm_mixer_fops, -1)) < 0) { - printk(KERN_ERR "Jz PCM: couldn't register mixer!\n"); - kfree(codec); - break; - } - controller->pcm_codec[num_pcm] = codec; - } - - return num_pcm; -} - -static void jz_update_filler(int format, int channels) -{ -#define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3)) - - switch (TYPE(format, channels)) { - default: - case TYPE(AFMT_U8, 1): - replay_filler = replay_fill_1x8_u; - record_filler = record_fill_1x8_u; - break; - case TYPE(AFMT_U8, 2): - /*replay_filler = replay_fill_2x8_u; - record_filler = record_fill_2x8_u;*/ - printk("channel is 2. Line:%d\n",__LINE__); - break; - case TYPE(AFMT_S16_LE, 1): - replay_filler = replay_fill_1x16_s; - record_filler = record_fill_1x16_s; - break; - case TYPE(AFMT_S16_LE, 2): - /*replay_filler = replay_fill_2x16_s; - record_filler = record_fill_2x16_s;*/ - printk("channel is 2. Line:%d\n",__LINE__); - break; - } -} - -static void __init attach_jz_pcm(struct jz_pcm_controller_info *controller) -{ - char *name; - int adev;//No of Audio device. - int err; - - name = controller->name; - /* register /dev/audio */ - adev = register_sound_dsp(&jz_pcm_audio_fops, -1); - if (adev < 0) - goto audio_failed; - /* initialize PCM codec and register /dev/mixer */ - if (jz_pcm_codec_init(controller) <= 0) - goto mixer_failed; - - controller->tmp1 = (void *)__get_free_pages(GFP_KERNEL, JZCODEC_USER_BUFFER); - if (!controller->tmp1) { - printk(KERN_ERR "%s: can't allocate tmp buffers.\n", controller->name); - goto tmp1_failed; - } - printk("DMA_ID_PCM_TX=0x%08x DMA_ID_PCM_RX=0x%08x\n",DMA_ID_PCM_TX ,DMA_ID_PCM_RX); - if ((controller->dma1 = jz_request_dma(DMA_ID_PCM_TX, "audio dac", jz_pcm_replay_dma_irq, IRQF_DISABLED, controller)) < 0) { - printk(KERN_ERR "%s: can't reqeust DMA DAC channel.\n", name); - goto dma1_failed; - } - if ((controller->dma2 = jz_request_dma(DMA_ID_PCM_RX, "audio adc", jz_pcm_record_dma_irq, IRQF_DISABLED, controller)) < 0) { - printk(KERN_ERR "%s: can't reqeust DMA ADC channel.\n", name); - goto dma2_failed; - } - printk("JzSOC On-Chip PCM controller registered (DAC: DMA(play):%d/IRQ%d,\n ADC: DMA(record):%d/IRQ%d)\n", controller->dma1, get_dma_done_irq(controller->dma1), controller->dma2, get_dma_done_irq(controller->dma2)); - - err = request_irq(IRQ_PCM, jz_pcm_irq, IRQF_DISABLED, "pcm irq", controller); - if (err < 0) - printk("can't allocate pcm irq.\n"); - controller->dev_audio = adev; - - return; -dma2_failed: - jz_free_dma(controller->dma2); -dma1_failed: - jz_free_dma(controller->dma1); -tmp1_failed: - free_pages((unsigned long)controller->tmp1, JZCODEC_USER_BUFFER); - -mixer_failed: - unregister_sound_dsp(adev); -audio_failed: - return; -} - - -static int __init probe_jz_pcm(struct jz_pcm_controller_info **controller) -{ - if ((*controller = kmalloc(sizeof(struct jz_pcm_controller_info), - GFP_KERNEL)) == NULL) { - printk(KERN_ERR "Jz PCM Controller: out of memory.\n"); - return -ENOMEM; - } - - (*controller)->name = "Jz PCM controller"; - (*controller)->opened1 = 0; - (*controller)->opened2 = 0; - init_waitqueue_head(&(*controller)->adc_wait); - init_waitqueue_head(&(*controller)->dac_wait); - spin_lock_init(&(*controller)->lock); - init_waitqueue_head(&rx_wait_queue); - init_waitqueue_head(&tx_wait_queue); - - return 0; -} - -static void __exit unload_jz_pcm(struct jz_pcm_controller_info *controller) -{ - int adev = controller->dev_audio; - - __pcm_reset(); - schedule_timeout(5); - __pcm_disable(); - __pcm_clk_disable(); - __pcm_flush_fifo(); - - controller->dev_audio = -1; - jz_free_dma(controller->dma1); - jz_free_dma(controller->dma2); - free_pages((unsigned long)controller->tmp1, JZCODEC_USER_BUFFER); - - if (adev >= 0) - unregister_sound_dsp(controller->dev_audio); -} - -static int __init init_jz_pcm(void) -{ - int errno; - /* 24M OSC ---> CPCCR.ECS ---> PCMCDR.PCMS ---> cpm_pcm_sysclk(X) */ - long X = 12000000; //in Hz /* 6.144 MHz <= X <= 264.192 MHz */ - -#if 0 - /* pcm_sys_clk is from PLL divsion */ - REG_CPM_PCMCDR = 0x8000001b; - REG_CPM_CPCCR |= 0x00400000; -#endif - /* pcm_sys_clk is from external clock */ - /* reset codec GPF4 */ - __gpio_as_output(32 * 5 + 4); - __gpio_set_pin(32 * 5 + 4); - mdelay(1); - - __pcm_reset(); - schedule_timeout(5); - __pcm_clk_disable(); - - /* set CPM to output cpm-pcm-sysclk ,assume cpm-pcm-sysclk is X Hz */ - /* PCMCLK must be 2048000 Hz, it is 256 mutil of PCMSYNC */ - //__pcm_set_clk_rate(X, 2048000); - __pcm_set_clk_rate(X, 2000000); - /* PCMSYNC must be 8000 Hz. 2048000 / 256 = 8000 */ - __pcm_set_sync_rate(2048000, 8000); - //__pcm_set_sync_rate(2000000, 8000); - __pcm_set_sync_len(0); - - __pcm_flush_fifo(); - __pcm_disable_txfifo(); - __pcm_disable_rxfifo(); - __pcm_set_transmit_trigger(7); - __pcm_set_receive_trigger(7); - __pcm_omsb_next_sync(); - __pcm_imsb_next_sync(); - -#if MODE_is_8 - __pcm_set_iss(8);//8bits decided by LINSEL - __pcm_set_oss(8); -#else - __pcm_set_iss(16);//16bits decided by LINSEL - __pcm_set_oss(16); -#endif - __pcm_set_valid_slot(1); - - __pcm_disable_tfs_intr(); - __pcm_disable_tur_intr(); - __pcm_disable_rfs_intr(); - __pcm_disable_ror_intr(); - - __pcm_disable_receive_dma(); - __pcm_disable_transmit_dma(); - - __pcm_last_sample(); - __pcm_as_master(); - - __pcm_enable(); - __pcm_clk_enable(); - - if ((errno = probe_jz_pcm(&pcm_controller)) < 0) - return errno; - attach_jz_pcm(pcm_controller); - - out_empty_queue.id = NULL; - out_full_queue.id = NULL; - out_busy_queue.id = NULL; - in_empty_queue.id = NULL; - in_full_queue.id = NULL; - in_busy_queue.id = NULL; - - jz_audio_fragsize = JZCODEC_RW_BUFFER_SIZE * PAGE_SIZE; - jz_audio_fragstotal = JZCODEC_RW_BUFFER_TOTAL ; - Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); - - __gpio_clear_pin(32 * 5 + 4); - udelay(100); - - __gpio_set_pin(32 * 5 + 4); - dump_pcmc_reg(); - - return 0; -} - - -static void __exit cleanup_jz_pcm(void) -{ - unload_jz_pcm(pcm_controller); - Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); -} - -module_init(init_jz_pcm); -module_exit(cleanup_jz_pcm); - -static int drain_adc(struct jz_pcm_controller_info *ctrl, int nonblock) -{ - unsigned long flags; - int count, i=0; - - for (;;) { - if ( i < MAXDELAY ) { - udelay(10); - i++; - } else - break; - - spin_lock_irqsave(&ctrl->lock, flags); - count = get_dma_residue(ctrl->dma2); - spin_unlock_irqrestore(&ctrl->lock, flags); - if (count <= 0) - break; - - if (nonblock) - return -EBUSY; - } - - return 0; -} -static int drain_dac(struct jz_pcm_controller_info *ctrl, int nonblock) -{ - unsigned long flags; - int count, ele, i=0; - - for (;;) { - if(!nonblock) {//blocked - if ( i < MAXDELAY ) { - udelay(10); - i++; - } else - break; - - ele = elements_in_queue(&out_full_queue); - if(ele <= 0) { - udelay(10); - spin_lock_irqsave(&ctrl->lock, flags); - count = get_dma_residue(ctrl->dma1); - spin_unlock_irqrestore(&ctrl->lock, flags); - if (count <= 0) - break; - } - } else {//non-blocked - mdelay(100); - ele = elements_in_queue(&out_full_queue); - - if(ele <= 0) { - mdelay(100); - - spin_lock_irqsave(&ctrl->lock, flags); - count = get_dma_residue(ctrl->dma1); - spin_unlock_irqrestore(&ctrl->lock, flags); - if (count <= 0) - break; - } - } - } - - return 0; -} - -static int jz_audio_release(struct inode *inode, struct file *file) -{ - struct jz_pcm_controller_info *controller = (struct jz_pcm_controller_info *) file->private_data; - - if (controller == NULL) - return -ENODEV; - - if ( controller->opened1 == 1 ) { - __pcm_enable_transmit_dma(); - __pcm_enable_txfifo(); - drain_dac(controller, file->f_flags & O_NONBLOCK); - disable_dma(controller->dma1); - set_dma_count(controller->dma1, 0); - - __pcm_disable_transmit_dma(); - __pcm_disable_txfifo(); - - spin_lock(&controller->ioctllock); - controller->total_bytes = 0; - controller->count = 0; - controller->finish = 0; - jz_audio_dma_tran_count = 0; - controller->blocks = 0; - controller->nextOut = 0; - spin_unlock(&controller->ioctllock); - //__pcm_disable(); - controller->opened1 = 0; - } - - if ( controller->opened2 == 1 ) { - first_record_call = 1; - __pcm_enable_receive_dma(); - __pcm_enable_rxfifo(); - drain_adc(controller, file->f_flags & O_NONBLOCK); - disable_dma(controller->dma2); - set_dma_count(controller->dma2, 0); - __pcm_disable_receive_dma(); - __pcm_disable_rxfifo(); - - spin_lock(&controller->ioctllock); - controller->total_bytes = 0; - jz_audio_dma_tran_count = 0; - controller->count = 0; - controller->finish = 0; - controller->blocks = 0; - controller->nextIn = 0; - spin_unlock(&controller->ioctllock); - //__pcm_disable(); - controller->opened2 = 0; - } - __pcm_disable_tfs_intr(); - __pcm_disable_tur_intr(); - __pcm_disable_rfs_intr(); - __pcm_disable_ror_intr(); - - return 0; -} - -static int jz_audio_open(struct inode *inode, struct file *file) -{ - int i; - struct jz_pcm_controller_info *controller = pcm_controller; - - if (controller == NULL) - return -ENODEV; - - if (controller->opened1 == 1 || controller->opened2 == 1 ) { - printk("\naudio is busy!\n"); - return -EBUSY; - } - REG_DMAC_DMACKE(0) = 0x3f; - REG_DMAC_DMACKE(1) = 0x3f; - if (file->f_mode & FMODE_WRITE) { - if (controller->opened1 == 1) - return -EBUSY; - controller->opened1 = 1; - //for ioctl - controller->total_bytes = 0; - jz_audio_dma_tran_count = 0; - controller->count = 0; - controller->finish = 0; - controller->blocks = 0; - controller->nextOut = 0; - - out_empty_queue.count = jz_audio_fragstotal; - for (i=0;i < jz_audio_fragstotal;i++) - *(out_empty_queue.id + i) = i; - out_busy_queue.count = 0; - out_full_queue.count = 0; - /* set PCMOUT params */ - } - - if (file->f_mode & FMODE_READ) { - if (controller->opened2 == 1) - return -EBUSY; - controller->opened2 = 1; - first_record_call = 1; - //for ioctl - controller->total_bytes = 0; - jz_audio_dma_tran_count = 0; - controller->count = 0; - controller->finish = 0; - controller->blocks = 0; - controller->nextIn = 0; - in_empty_queue.count = jz_audio_fragstotal; - for (i=0;i < jz_audio_fragstotal;i++) - *(in_empty_queue.id + i) = i; - in_full_queue.count = 0; - in_busy_queue.count = 0; - /* set PCMIN params */ - } - - file->private_data = controller; - jz_audio_reset(); - __pcm_enable(); - - return 0; -} - -static int jz_audio_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int val,fullc,busyc,unfinish,newfragstotal,newfragsize; - unsigned int flags; - audio_buf_info abinfo; - int i, bytes, id; - count_info cinfo; - struct jz_pcm_controller_info *controller = (struct jz_pcm_controller_info *) file->private_data; - - val = 0; - bytes = 0; - switch (cmd) { - case OSS_GETVERSION: - return put_user(SOUND_VERSION, (int *)arg); - case SNDCTL_DSP_RESET: - return 0; - case SNDCTL_DSP_SYNC: - if (file->f_mode & FMODE_WRITE) - drain_dac(controller, file->f_flags & O_NONBLOCK); - return 0; - case SNDCTL_DSP_SPEED: - { - if (get_user(val, (int *)arg)) - return -EFAULT; - /* set smaple rate */ - if (val >= 0) - jz_audio_set_speed(controller->dev_audio, val); - return put_user(val, (int *)arg); - } - case SNDCTL_DSP_STEREO: - /* set stereo or mono channel */ - if (get_user(val, (int *)arg)) - return -EFAULT; - - jz_audio_set_channels(controller->dev_audio, val ? 2 : 1); - return 0; - - case SNDCTL_DSP_GETBLKSIZE: - //return put_user(4*PAGE_SIZE, (int *)arg); - return put_user(jz_audio_fragsize , (int *)arg); - case SNDCTL_DSP_GETFMTS: - /* Returns a mask of supported sample format*/ - return put_user(AFMT_U8 | AFMT_S16_LE, (int *)arg); - - case SNDCTL_DSP_SETFMT: - { - if (get_user(val, (int *)arg)) - return -EFAULT; - /* Select sample format */ - if (val != AFMT_QUERY) - jz_audio_set_format(controller->dev_audio,val); - else - if (file->f_mode & FMODE_READ) - val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; - else - val = (jz_audio_format == 16) ? AFMT_S16_LE : AFMT_U8; - return put_user(val, (int *)arg); - } - - case SNDCTL_DSP_CHANNELS: - if (get_user(val, (int *)arg)) - return -EFAULT; - printk("%s:%s:%d\n",__FILE__,__FUNCTION__,__LINE__); - jz_audio_set_channels(controller->dev_audio, val); - return put_user(val, (int *)arg); - - case SNDCTL_DSP_POST: - /* FIXME: the same as RESET ?? */ - return 0; - - case SNDCTL_DSP_SUBDIVIDE: - return 0; - - case SNDCTL_DSP_SETFRAGMENT: - get_user(val, (long *) arg); - newfragsize = 1 << (val & 0xFFFF);//16 least bits - - if (newfragsize < 4 * PAGE_SIZE) - newfragsize = 4 * PAGE_SIZE; - if (newfragsize > (16 * PAGE_SIZE)) //16 PAGE_SIZE - newfragsize = 16 * PAGE_SIZE; - - newfragstotal = (val >> 16) & 0x7FFF; - if (newfragstotal < 2) - newfragstotal = 2; - if (newfragstotal > 32) - newfragstotal = 32; - if((jz_audio_fragstotal == newfragstotal) && (jz_audio_fragsize == newfragsize)) - return 0; - Free_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); - mdelay(500); - jz_audio_fragstotal = newfragstotal; - jz_audio_fragsize = newfragsize; - - Init_In_Out_queue(jz_audio_fragstotal,jz_audio_fragsize); - mdelay(10); - - return 0; - case SNDCTL_DSP_GETCAPS: - return put_user(DSP_CAP_REALTIME|DSP_CAP_BATCH, (int *)arg); - case SNDCTL_DSP_NONBLOCK: - file->f_flags |= O_NONBLOCK; - return 0; - case SNDCTL_DSP_SETDUPLEX: - return -EINVAL; - case SNDCTL_DSP_GETOSPACE: - { - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - //unused fragment amount - spin_lock_irqsave(&controller->ioctllock, flags); - jz_audio_fragments = elements_in_queue(&out_empty_queue); - for (i = 0; i < jz_audio_fragments; i++) - bytes += jz_audio_fragsize; - - spin_unlock_irqrestore(&controller->ioctllock, flags); - abinfo.fragments = jz_audio_fragments; - abinfo.fragstotal = jz_audio_fragstotal; - abinfo.fragsize = jz_audio_fragsize; - abinfo.bytes = bytes; - return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; - } - case SNDCTL_DSP_GETISPACE: - if (!(file->f_mode & FMODE_READ)) - return -EINVAL; - bytes = 0; - //unused fragment amount - jz_audio_fragments = elements_in_queue(&in_empty_queue); - for (i = 0; i < jz_audio_fragments; i++) - bytes += jz_audio_fragsize; - - abinfo.fragments = jz_audio_fragments; - abinfo.fragstotal = jz_audio_fragstotal; - abinfo.fragsize = jz_audio_fragsize; - abinfo.bytes = bytes; - return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; - case SNDCTL_DSP_GETTRIGGER: - val = 0; - if (file->f_mode & FMODE_READ && in_dma_buf) - val |= PCM_ENABLE_INPUT; - if (file->f_mode & FMODE_WRITE && out_dma_buf) - val |= PCM_ENABLE_OUTPUT; - return put_user(val, (int *)arg); - - case SNDCTL_DSP_SETTRIGGER: - if (get_user(val, (int *)arg)) - return -EFAULT; - return 0; - case SNDCTL_DSP_GETIPTR: - if (!(file->f_mode & FMODE_READ)) - return -EINVAL; - - spin_lock_irqsave(&controller->ioctllock, flags); - cinfo.bytes = controller->total_bytes; - cinfo.blocks = controller->blocks; - cinfo.ptr = controller->nextIn; - controller->blocks = 0; - spin_unlock_irqrestore(&controller->ioctllock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); - case SNDCTL_DSP_GETOPTR: - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - spin_lock_irqsave(&controller->ioctllock, flags); - cinfo.bytes = controller->total_bytes; - cinfo.blocks = controller->blocks; - cinfo.ptr = controller->nextOut; - controller->blocks = 0; - spin_unlock_irqrestore(&controller->ioctllock, flags); - return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); - case SNDCTL_DSP_GETODELAY: - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - spin_lock_irqsave(&controller->ioctllock, flags); - unfinish = 0; - fullc = elements_in_queue(&out_full_queue); - busyc = elements_in_queue(&out_busy_queue); - for(i = 0;i < fullc ;i ++) { - id = *(out_full_queue.id + i); - unfinish += *(out_dma_buf_data_count + id); - } - for(i = 0;i < busyc ;i ++) { - id = *(out_busy_queue.id + i); - unfinish += get_dma_residue(controller->dma1); - } - spin_unlock_irqrestore(&controller->ioctllock, flags); - return put_user(unfinish, (int *) arg); - case SOUND_PCM_READ_RATE: - return put_user(jz_audio_rate, (int *)arg); - case SOUND_PCM_READ_CHANNELS: - return put_user(jz_audio_channels, (int *)arg); - case SOUND_PCM_READ_BITS: - return put_user((jz_audio_format & (AFMT_S8 | AFMT_U8)) ? 8 : 16, (int *)arg); - case SNDCTL_DSP_MAPINBUF: - case SNDCTL_DSP_MAPOUTBUF: - case SNDCTL_DSP_SETSYNCRO: - case SOUND_PCM_WRITE_FILTER: - case SOUND_PCM_READ_FILTER: - return -EINVAL; - } - return -EINVAL; -} - -static unsigned int jz_audio_poll(struct file *file,struct poll_table_struct *wait) -{ - unsigned long flags; - unsigned int mask = 0; - struct jz_pcm_controller_info *controller = (struct jz_pcm_controller_info *) file->private_data; - - if (file->f_mode & FMODE_WRITE) { - if (elements_in_queue(&out_empty_queue) > 0) - return POLLOUT | POLLWRNORM; - poll_wait(file, &controller->dac_wait, wait); - } - - if (file->f_mode & FMODE_READ) { - if (elements_in_queue(&in_full_queue) > 0) - return POLLIN | POLLRDNORM; - poll_wait(file, &controller->adc_wait, wait); - } - - spin_lock_irqsave(&controller->lock, flags); - if (file->f_mode & FMODE_WRITE) { - if (elements_in_queue(&out_empty_queue) > 0) - mask |= POLLOUT | POLLWRNORM; - } else if (file->f_mode & FMODE_READ) { - if (elements_in_queue(&in_full_queue) > 0) - mask |= POLLIN | POLLRDNORM; - } - spin_unlock_irqrestore(&controller->lock, flags); - - return mask; -} - -static ssize_t jz_audio_read(struct file *file, char *buffer, size_t count, loff_t *ppos) -{ - int id, ret = 0, left_count, copy_count, cnt = 0; - struct jz_pcm_controller_info *controller = (struct jz_pcm_controller_info *) file->private_data; - - if (count < 0) - return -EINVAL; - - __pcm_enable_receive_dma(); - __pcm_enable_rxfifo(); - - spin_lock(&controller->ioctllock); - controller->nextIn = 0; - spin_unlock(&controller->ioctllock); - - spin_lock(&controller->lock); - -#if 0 - if (count < 2 * PAGE_SIZE ) - copy_count = count * 16 / (jz_audio_channels * jz_audio_format); - else - copy_count = 2 * PAGE_SIZE ; -#else - if (count <= jz_audio_fragsize) - copy_count = count; - else - copy_count = jz_audio_fragsize; -#endif - - left_count = count; - spin_unlock(&controller->lock); - - if (first_record_call) { - first_record_call = 0; -audio_read_back_first: - if ((id = get_buffer_id(&in_empty_queue)) >= 0) { - put_buffer_id(&in_busy_queue, id); - - spin_lock(&controller->lock); - *(in_dma_buf_data_count + id) = copy_count; - spin_unlock(&controller->lock); - - dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); - audio_start_dma(controller->dma2,file->private_data, - *(in_dma_pbuf + id), - *(in_dma_buf_data_count + id), - DMA_MODE_READ); - - sleep_on(&rx_wait_queue); - } else - goto audio_read_back_first; - } - - while (left_count > 0) { -audio_read_back_second: - if (elements_in_queue(&in_full_queue) <= 0) { - if (file->f_flags & O_NONBLOCK) - return ret ? ret : -EAGAIN; - else - sleep_on(&rx_wait_queue); - } - - if ((id = get_buffer_id(&in_full_queue)) >= 0) { - spin_lock(&controller->lock); - cnt = record_filler((unsigned long)controller->tmp1+ret, copy_count, id); - spin_unlock(&controller->lock); - put_buffer_id(&in_empty_queue, id); - } else - goto audio_read_back_second; - - if (elements_in_queue(&in_busy_queue) == 0) { - if ((id=get_buffer_id(&in_empty_queue)) >= 0) { - put_buffer_id(&in_busy_queue, id); - spin_lock(&controller->lock); - *(in_dma_buf_data_count + id) = copy_count; - spin_unlock(&controller->lock); - - dma_cache_wback_inv(*(in_dma_buf + id), *(in_dma_buf_data_count + id)); - audio_start_dma(controller->dma2,file->private_data, - *(in_dma_pbuf + id), - *(in_dma_buf_data_count + id), - DMA_MODE_READ); - } - } - if (ret + cnt > count) { - spin_lock(&controller->lock); - cnt = count - ret; - spin_unlock(&controller->lock); - } - if (copy_to_user(buffer+ret, controller->tmp1+ret, cnt)) - return ret ? ret : -EFAULT; - spin_lock(&controller->lock); - ret += cnt; - spin_unlock(&controller->lock); - - spin_lock(&controller->ioctllock); - controller->nextIn += ret; - spin_unlock(&controller->ioctllock); - - spin_lock(&controller->lock); - left_count -= cnt; - spin_unlock(&controller->lock); - } - - return ret; -} - -static ssize_t jz_audio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) -{ - int id, ret, left_count, copy_count; - unsigned int flags; - struct jz_pcm_controller_info *controller = (struct jz_pcm_controller_info *) file->private_data; - - if (count <= 0) - return -EINVAL; - - __pcm_enable_transmit_dma(); - __pcm_enable_txfifo(); - - spin_lock_irqsave(&controller->ioctllock, flags); - controller->nextOut = 0; - spin_unlock_irqrestore(&controller->ioctllock, flags); - -#if 0 - if (count < 2 * PAGE_SIZE ) - copy_count = count; - else - copy_count = 2 * PAGE_SIZE; -#else - if (count <= jz_audio_fragsize) - copy_count = count; - else - copy_count = jz_audio_fragsize; -#endif - - left_count = count; - ret = 0; - - if (copy_from_user(controller->tmp1, buffer, count)) { - printk("copy_from_user failed:%d",ret); - return ret ? ret : -EFAULT; - } - - while (left_count > 0) { -audio_write_back: - if (elements_in_queue(&out_empty_queue) == 0) { - // all are full - if (file->f_flags & O_NONBLOCK) - return ret; - else - sleep_on(&tx_wait_queue); - } - /* the end fragment size in this write */ - if (ret + copy_count > count) - copy_count = count - ret; - if ((id = get_buffer_id(&out_empty_queue)) >= 0) { - replay_filler((unsigned long)controller->tmp1 + ret, copy_count, id); - if(*(out_dma_buf_data_count + id) > 0) { - put_buffer_id(&out_full_queue, id); //busy in - dma_cache_wback_inv(*(out_dma_buf + id), *(out_dma_buf_data_count + id)); - } else - put_buffer_id(&out_empty_queue, id); //spare - } else - goto audio_write_back; - - left_count = left_count - copy_count; - ret += copy_count;//all is in byte - - spin_lock(&controller->ioctllock); - controller->nextOut += ret; - spin_unlock(&controller->ioctllock); - - if (elements_in_queue(&out_busy_queue) == 0) { - if ((id=get_buffer_id(&out_full_queue)) >= 0) { - put_buffer_id(&out_busy_queue, id); - - if(*(out_dma_buf_data_count + id) > 0) { - audio_start_dma(controller->dma1, - file->private_data, - *(out_dma_pbuf + id), - *(out_dma_buf_data_count + id), - DMA_MODE_WRITE); - - } - } - } - } - - return ret; -} - -static void dump_pcmc_reg(void) -{ - printk("REG_DMAC_DMACKE(0) : 0x%08x\n",REG_DMAC_DMACKE(0)); - printk("REG_DMAC_DMACKE(1) : 0x%08x\n",REG_DMAC_DMACKE(1)); - printk("REG_CPM_CLKGR=0x%08x\n",REG_CPM_CLKGR); - printk("REG_CPM_CPCCR : 0x%08x\n",REG_CPM_CPCCR); - printk("REG_CPM_PCMCDR : 0x%08x\n",REG_CPM_PCMCDR); - printk("REG_PCM_CLT : 0x%08x\n",REG_PCM_CTL); - printk("REG_PCM_CFG : 0x%08x\n",REG_PCM_CFG); - printk("REG_PCM_INTC : 0x%08x\n",REG_PCM_INTC); - printk("REG_PCM_INTS : 0x%08x\n",REG_PCM_INTS); - printk("REG_PCM_DIV : 0x%08x\n",REG_PCM_DIV); -} diff --git a/target/linux/xburst/files-2.6.27/sound/oss/jzcodec.c b/target/linux/xburst/files-2.6.27/sound/oss/jzcodec.c deleted file mode 100755 index 0af65804b..000000000 --- a/target/linux/xburst/files-2.6.27/sound/oss/jzcodec.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - * linux/drivers/sound/jzcodec.c - * - * JzSOC internal audio driver. - * - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sound_config.h" - -#define USE_NONE 1 -#define USE_MIC 2 -#define USE_LINEIN 3 - -typedef struct hpvol_shift_s -{ - int hpvol; - int shift; -} hpvol_shift_t; - -extern mixer_info info; -extern _old_mixer_info old_info; -extern int codec_volue_shift; -extern hpvol_shift_t hpvol_shift_table[72]; -extern int abnormal_data_count; - -extern void (*set_codec_mode)(void); -extern void (*each_time_init_codec)(void); -extern int (*set_codec_startup_param)(void); -extern void (*set_codec_volume_table)(void); -extern void (*set_codec_record)(int mode); -extern void (*set_codec_replay)(void); -extern void (*set_codec_replay_record)(int mode); -extern void (*turn_on_codec)(void); -extern void (*turn_off_codec)(void); -extern void (*set_codec_speed)(int rate); -extern void (*reset_codec)(void); -extern void (*codec_mixer_old_info_id_name)(void); -extern void (*codec_mixer_info_id_name)(void); -extern void (*set_codec_bass)(int val); -extern void (*set_codec_volume)(int val); -extern void (*set_codec_mic)(int val); -extern void (*set_codec_line)(int val); -extern void (*i2s_resume_codec)(void); -extern void (*i2s_suspend_codec)(void); -extern void (*set_codec_direct_mode)(void); -extern void (*clear_codec_direct_mode)(void); - -static int jzcodec_reg[2]; - -void set_jzcodec_mode(void); -void each_time_init_jzcodec(void); -int set_jzcodec_startup_param(void); -void set_jzcodec_volume_table(void); -void set_jzcodec_replay(void); -void set_jzcodec_record(int mode); -void turn_on_jzcodec(void); -void turn_off_jzcodec(void); -void set_jzcodec_speed(int rate); -void reset_jzcodec(void); -void jzcodec_mixer_old_info_id_name(void); -void jzcodec_mixer_info_id_name(void); -void set_jzcodec_bass(int val); -void set_jzcodec_volume(int val); -void set_jzcodec_mic(int val); -void set_jzcodec_line(int val); -void in_codec_app1(void); -void in_codec_app12(void); -void HP_turn_on(void); -void HP_turn_off(void); -void resume_jzcodec(void); -void suspend_jzcodec(void); -void set_jzcodec_replay_record(int mode); - -void set_jzcodec_mode(void) -{ - __i2s_internal_codec(); - __i2s_as_slave(); - __i2s_select_i2s(); - __aic_select_i2s(); - - REG_ICDC_CDCCR1 = 0x001b2303; - schedule_timeout(1); - REG_ICDC_CDCCR1 = 0x001b2302; -} - -void each_time_init_jzcodec(void) -{ - __i2s_disable(); - __i2s_as_slave(); - __i2s_set_oss_sample_size(16); - __i2s_set_iss_sample_size(16); -} - -int set_jzcodec_startup_param(void) -{ - REG_ICDC_CDCCR1 = 0x001b2300; - schedule_timeout(50); - REG_ICDC_CDCCR1 = 0x00033300; - schedule_timeout(5); - REG_ICDC_CDCCR1 = 0x17026300; - - return 1; -} -void set_jzcodec_volume_table(void) -{ - int errno,hpvol_step,sample_shift; - - codec_volue_shift = 0; - hpvol_step = 3; - sample_shift = 0; - for(errno = 0;errno < 72;errno++) { - hpvol_shift_table[errno].hpvol = hpvol_step; - hpvol_shift_table[errno].shift = sample_shift; - hpvol_step --; - if(hpvol_step <= 0) { - hpvol_step = 3; - sample_shift ++; - } - } -} - -void set_jzcodec_replay(void) -{ - in_codec_app1(); -} - -void set_jzcodec_record(int mode) -{ - switch (mode) { - case USE_NONE: - case USE_MIC: - in_codec_app12(); - abnormal_data_count = 0; - break; - case USE_LINEIN: - REG_ICDC_CDCCR1 = 0x27022000;//for linein - mdelay(300); - break; - } -} - -void set_jzcodec_replay_record(int mode) -{ - long val = 0; - REG_ICDC_CDCCR1 = 0x00037302; - mdelay(2); - REG_ICDC_CDCCR1 = 0x03006000; - mdelay(2); - - switch (mode) { - case USE_NONE: - case USE_MIC: - REG_ICDC_CDCCR1 = 0x17022000;//for mic - break; - case USE_LINEIN: - REG_ICDC_CDCCR1 = 0x27022000;//for linein - break; - } - - val = REG_ICDC_CDCCR2; - val &= 0x0000ff00; - val |= 0x00170030; - REG_ICDC_CDCCR2 = val; -} - -void turn_on_jzcodec(void) -{ - HP_turn_on(); -} - -void set_jzcodec_direct_mode(void) -{ - long val = 0; - REG_ICDC_CDCCR1 = 0x14000000; - val &= 0x0000ff00; - val |= 0x001f0033; - REG_ICDC_CDCCR2 = val; - mdelay(300); -} - -void clear_jzcodec_direct_mode(void) -{ - HP_turn_off(); -} - -void turn_off_jzcodec(void) -{ - HP_turn_off(); -} - -void set_jzcodec_speed(int rate) -{ - long codec_speed,speed = 0; - switch (rate) { - case 8000: - speed = 0; - break; - case 11025: - speed = 1; - break; - case 12000: - speed = 2; - break; - case 16000: - speed = 3; - break; - case 22050: - speed = 4; - break; - case 24000: - speed = 5; - break; - case 32000: - speed = 6; - break; - case 44100: - speed = 7; - break; - case 48000: - speed = 8; - break; - default: - break; - } - - codec_speed = REG_ICDC_CDCCR2; - codec_speed |= 0x00000f00; - - speed = speed << 8; - speed |= 0xfffff0ff; - codec_speed &= speed; - REG_ICDC_CDCCR2 = codec_speed; -} - -void reset_jzcodec(void) -{ - REG_ICDC_CDCCR1 |= 1; - mdelay(1); - REG_ICDC_CDCCR1 &= 0xfffffffe; -} - -void jzcodec_mixer_old_info_id_name(void) -{ - strncpy(info.id, "JZCODEC", sizeof(info.id)); - strncpy(info.name,"Jz internal codec", sizeof(info.name)); -} - -void jzcodec_mixer_info_id_name(void) -{ - strncpy(old_info.id, "JZCODEC", sizeof(old_info.id)); - strncpy(old_info.name,"Jz internal codec", sizeof(old_info.name)); -} - -void set_jzcodec_bass(int val) -{ - int bass_gain = 0; - if(val < 25) - bass_gain = 0; - if(val >= 25 && val < 50) - bass_gain = 1; - if(val >= 50 && val < 75) - bass_gain = 2; - if(val >= 75 && val <= 100 ) - bass_gain = 3; - - REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x3 << 4)) | (bass_gain << 4)); -} - -void set_jzcodec_volume(int val) -{ - unsigned int sample_oss; - int index,shift_max,vol_scale,vol_step,codec_volume; - shift_max = 0; - sample_oss = (REG_AIC_CR & 0x00380000) >> 19; - - switch(sample_oss) - { - case 0x0: - shift_max = 4; /* 8 bits */ - break; - case 0x1: - shift_max = 10; /* 16 bits */ - break; - case 0x2: - shift_max = 12; /* 18 bits */ - break; - case 0x3: - shift_max = 15; /* 20 bits */ - break; - case 0x4: - shift_max = 19; /* 24 bits */ - break; - } - - vol_scale = 3 * (shift_max + 1); - vol_step = 100 / vol_scale; - - for(index = 0;index <= 100;index += vol_step) - if( val <= index ) - break; - - if(index == 0) - index = vol_step; - index = index / vol_step; - if(index > vol_scale) - index = vol_scale; - - index = vol_scale - index; - codec_volume = hpvol_shift_table[index].hpvol; - codec_volue_shift = hpvol_shift_table[index].shift; - codec_volume = 3; - REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x3)) | codec_volume); -} - -void set_jzcodec_mic(int val) -{ - long mic_gain; - - mic_gain = 31 * val /100; - REG_ICDC_CDCCR2 = (REG_ICDC_CDCCR2 | (0x3 << 4)); - REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x1f << 16)) | (mic_gain << 16)); -} - -void set_jzcodec_line(int val) -{ - long line_gain; - - line_gain = 31 * val /100; - REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x1f << 16)) | (line_gain << 16)); -} - -void HP_turn_on(void) -{ - long val = 0; - /* simple and slow anti-pop */ - REG_ICDC_CDCCR1 = 0x00037302; - mdelay(2); - REG_ICDC_CDCCR1 = 0x03006000; - mdelay(2); - REG_ICDC_CDCCR1 = 0x03002000; - - val = REG_ICDC_CDCCR2; - val &= 0x0000ff00; - val |= 0x001f0033; - REG_ICDC_CDCCR2 = val; -} - -void HP_turn_off(void) -{ - mdelay(20); - REG_ICDC_CDCCR1 = 0x00033300; -} - -void in_codec_app1(void) -{ - /* test is OK */ - HP_turn_on(); -} - -void in_codec_app12(void) -{ - REG_ICDC_CDCCR1 = 0x14024300; - mdelay(300); -} - -void resume_jzcodec(void) -{ - REG_ICDC_CDCCR2 = 0x00170800; - mdelay(2); - REG_ICDC_CDCCR1 = 0x001f2102; - mdelay(5); - REG_ICDC_CDCCR1 = 0x00033302; - mdelay(550); - REG_ICDC_CDCCR1 = 0x00033300; - REG_ICDC_CDCCR1 = jzcodec_reg[0]; - REG_ICDC_CDCCR2 = jzcodec_reg[1]; -} - -void suspend_jzcodec(void) -{ - - jzcodec_reg[0] = REG_ICDC_CDCCR1; - jzcodec_reg[1] = REG_ICDC_CDCCR2; - - REG_ICDC_CDCCR1 = 0x001b2302; - mdelay(1); - REG_ICDC_CDCCR1 = 0x001b2102; -} - -static int __init init_jzcodec(void) -{ - set_codec_mode = set_jzcodec_mode; - each_time_init_codec = each_time_init_jzcodec; - - set_codec_startup_param = set_jzcodec_startup_param; - set_codec_volume_table = set_jzcodec_volume_table; - set_codec_record = set_jzcodec_record; - set_codec_replay = set_jzcodec_replay; - set_codec_replay_record = set_jzcodec_replay_record; - turn_on_codec = turn_on_jzcodec; - turn_off_codec = turn_off_jzcodec; - set_codec_speed = set_jzcodec_speed; - reset_codec = reset_jzcodec; - codec_mixer_old_info_id_name = jzcodec_mixer_old_info_id_name; - codec_mixer_info_id_name = jzcodec_mixer_info_id_name; - set_codec_bass = set_jzcodec_bass; - set_codec_volume = set_jzcodec_volume; - set_codec_mic = set_jzcodec_mic; - set_codec_line = set_jzcodec_line; - i2s_resume_codec = resume_jzcodec; - i2s_suspend_codec = suspend_jzcodec; - set_codec_direct_mode = set_jzcodec_direct_mode; - clear_codec_direct_mode = clear_jzcodec_direct_mode; - - return 0; -} - - -static void __exit cleanup_jzcodec(void) -{ - REG_ICDC_CDCCR1 = 0x001b2302; - -} - -module_init(init_jzcodec); -module_exit(cleanup_jzcodec); diff --git a/target/linux/xburst/files-2.6.27/sound/oss/jzdlv.c b/target/linux/xburst/files-2.6.27/sound/oss/jzdlv.c deleted file mode 100755 index 8f8f2ba1f..000000000 --- a/target/linux/xburst/files-2.6.27/sound/oss/jzdlv.c +++ /dev/null @@ -1,644 +0,0 @@ -/* - * linux/drivers/sound/jzcodec.c - * - * JzSOC internal audio driver. - * - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sound_config.h" -#include "jzdlv.h" - -#define USE_NONE 1 -#define USE_MIC 2 -#define USE_LINEIN 3 - -extern mixer_info info; -extern _old_mixer_info old_info; -extern int codec_volue_shift; - -extern void (*set_codec_mode)(void); -extern void (*each_time_init_codec)(void); -extern int (*set_codec_startup_param)(void); -extern void (*set_codec_record)(void); -extern void (*set_codec_replay)(void); -extern void (*set_codec_replay_record)(void); -extern void (*turn_on_codec)(void); -extern void (*turn_off_codec)(void); -extern void (*set_codec_speed)(int rate); -extern void (*reset_codec)(void); -extern void (*codec_mixer_old_info_id_name)(void); -extern void (*codec_mixer_info_id_name)(void); -extern void (*set_codec_bass)(int val); -extern void (*set_codec_volume)(int val); -extern void (*set_codec_mic)(int val); -extern void (*set_codec_line)(int val); -extern void (*i2s_resume_codec)(void); -extern void (*i2s_suspend_codec)(void); -extern void (*set_codec_direct_mode)(void); -extern void (*clear_codec_direct_mode)(void); - - -void set_dlv_mode(void); -void each_time_init_jzcodec(void); -int set_dlv_startup_param(void); -void set_dlvjzcodec_volume_table(void); -void set_dlv_replay(void); -void set_dlv_record(void); -void set_dlv_speed(int rate); -void reset_dlv(void); -void jzcodec_mixer_old_info_id_name(void); -void jzcodec_mixer_info_id_name(void); -void set_dlv_volume(int val); -void set_dlv_mic(int val); - -extern int jz_mic_only; -int read_codec_file(int addr) -{ - while (__icdc_rgwr_ready()); - __icdc_set_addr(addr); - mdelay(1); - return(__icdc_get_value()); -} - -#if 0 -void printk_codec_files(void) -{ - int cnt; - - printk("\n"); - - printk("REG_CPM_I2SCDR=0x%08x\n",REG_CPM_I2SCDR); - printk("REG_CPM_CLKGR=0x%08x\n",REG_CPM_CLKGR); - printk("REG_CPM_CPCCR=0x%08x\n",REG_CPM_CPCCR); - printk("REG_AIC_FR=0x%08x\n",REG_AIC_FR); - printk("REG_AIC_CR=0x%08x\n",REG_AIC_CR); - printk("REG_AIC_I2SCR=0x%08x\n",REG_AIC_I2SCR); - printk("REG_AIC_SR=0x%08x\n",REG_AIC_SR); - printk("REG_ICDC_RGDATA=0x%08x\n",REG_ICDC_RGDATA); - - for (cnt = 0; cnt <= 27 ; cnt++) { - printk(" ( %d : 0x%x ) ",cnt ,read_codec_file(cnt)); - } - printk("\n"); -} -#endif - -void write_codec_file(int addr, int val) -{ - while (__icdc_rgwr_ready()); - __icdc_set_addr(addr); - __icdc_set_cmd(val); /* write */ - mdelay(1); - __icdc_set_rgwr(); - mdelay(1); -} - -int write_codec_file_bit(int addr, int bitval, int mask_bit) -{ - int val; - while (__icdc_rgwr_ready()); - __icdc_set_addr(addr); - mdelay(1); - val = __icdc_get_value(); /* read */ - - while (__icdc_rgwr_ready()); - __icdc_set_addr(addr); - val &= ~(1 << mask_bit); - if (bitval == 1) - val |= 1 << mask_bit; - - __icdc_set_cmd(val); /* write */ - mdelay(1); - __icdc_set_rgwr(); - mdelay(1); - - while (__icdc_rgwr_ready()); - __icdc_set_addr(addr); - val = __icdc_get_value(); /* read */ - - if (((val >> mask_bit) & bitval) == bitval) - return 1; - else - return 0; -} -void set_dlv_mode(void) -{ - /*REG_CPM_CPCCR &= ~(1 << 31); - REG_CPM_CPCCR &= ~(1 << 30);*/ - write_codec_file(0, 0xf); - - REG_AIC_I2SCR = 0x10; - __i2s_internal_codec(); - __i2s_as_slave(); - __i2s_select_i2s(); - __aic_select_i2s(); - __aic_reset(); - mdelay(10); - REG_AIC_I2SCR = 0x10; - mdelay(20); - - /* power on DLV */ - write_codec_file(9, 0xff); - write_codec_file(8, 0x3f); - mdelay(10); -} -void reset_dlv_codec(void) -{ - /* reset DLV codec. from hibernate mode to sleep mode */ - write_codec_file(0, 0xf); - write_codec_file_bit(6, 0, 0); - write_codec_file_bit(6, 0, 1); - mdelay(200); - //write_codec_file(0, 0xf); - write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0 - write_codec_file_bit(5, 0, 4);//PMR1.SB_ADC->0 - mdelay(10);//wait for stability -} - -void each_time_init_dlv(void) -{ - __i2s_disable(); - __i2s_as_slave(); - __aic_internal_codec(); - __i2s_set_oss_sample_size(16); - __i2s_set_iss_sample_size(16); -} - -int set_dlv_startup_param(void) -{ - __i2s_disable_transmit_intr(); - __i2s_disable_receive_intr(); - - return 1; -} -/* set Audio data replay */ -void set_audio_data_replay(void) -{ - /* DAC path */ - write_codec_file(9, 0xff); - //write_codec_file(8, 0x30); - write_codec_file(8, 0x20); - mdelay(10); - write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 - write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 - write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 - - write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 - write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 - - write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 - //mdelay(100); - //write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 - write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 - //mdelay(300); -} - -#if 1 /* mask warning */ -/* set Record MIC input audio without playback */ -void set_record_mic_input_audio_without_playback(void) -{ - /* ADC path for MIC IN */ - jz_mic_only = 1; - write_codec_file(9, 0xff); - write_codec_file(8, 0x3f); - write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 - mdelay(10); - write_codec_file_bit(1, 1, 2); - //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 - - write_codec_file(22, 0x40);//mic 1 - write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 - write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 - write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 - - write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 - write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 - //write_codec_file_bit(6, 1, 3);// gain set - - write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 - mdelay(100); - write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 - write_codec_file(1, 0x4); -} -#endif - -#if 1 /* mask warning */ -/* unset Record MIC input audio without playback */ -void unset_record_mic_input_audio_without_playback(void) -{ - /* ADC path for MIC IN */ - jz_mic_only = 0; - write_codec_file_bit(5, 1, 4);//SB_ADC->1 - write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 - write_codec_file(22, 0xc0);//CR3.SB_MIC1 - write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 - write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 - write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 - write_codec_file_bit(6, 1, 1);//SB->1 -} -#endif - -#if 0 /* mask warning */ -/* set Record LINE input audio without playback */ -void set_record_line_input_audio_without_playback(void) -{ - /* ADC path for LINE IN */ - jz_mic_only = 1; - write_codec_file(9, 0xff); - write_codec_file(8, 0x3f); - mdelay(10); - write_codec_file(22, 0xf6);//line in 1 - write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 - write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1 - write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 - write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 - - write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 - write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 - mdelay(10); - write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 - mdelay(100); - write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 - write_codec_file(1, 0x4); -} -#endif - -#if 0 /* mask warning */ -/* unset Record LINE input audio without playback */ -void unset_record_line_input_audio_without_playback(void) -{ - /* ADC path for LINE IN */ - write_codec_file_bit(5, 1, 4);//SB_ADC->1 - write_codec_file_bit(5, 1, 3);//ONR1.SB_LIN->1 - - write_codec_file(22, 0xc0);//CR3.SB_MIC1 - write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 - write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 - write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 - write_codec_file_bit(6, 1, 1);//SB->1 -} -#endif - -#if 0 /* mask warning */ -/* set Playback LINE input audio direct only */ -void set_playback_line_input_audio_direct_only(void) -{ - jz_audio_reset();//or init_codec() - REG_AIC_I2SCR = 0x10; - write_codec_file(9, 0xff); - write_codec_file(8, 0x3f); - mdelay(10); - write_codec_file(22, 0xf6);//line in 1 - write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 - mdelay(10); - write_codec_file_bit(1, 1, 2);//CR1.HP_BYPASS->1 - write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 - write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 - write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 - write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 - - write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 - mdelay(100); - write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 - //write_codec_file_bit(5, 1, 7);//PMR1.SB_DAC->1 - //write_codec_file_bit(5, 1, 4);//PMR1.SB_ADC->1 -} -#endif - -#if 0 /* mask warning */ -/* unset Playback LINE input audio direct only */ -void unset_playback_line_input_audio_direct_only(void) -{ - write_codec_file_bit(6, 0, 3);//GIM->0 - write_codec_file_bit(1, 0, 2);//PMR1.BYPASS->0 - write_codec_file_bit(5, 1, 3);//PMR1.SB_LINE->1 - write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 - mdelay(100); - write_codec_file_bit(5, 1, 5);//PMR1.SB_MIX->1 - write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 - write_codec_file_bit(6, 1, 1);//SB->1 -} -#endif - -#if 0 /* mask warning */ -/* set Record MIC input audio with direct playback */ -void set_record_mic_input_audio_with_direct_playback(void) -{ - write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 - jz_mic_only = 0; - write_codec_file(9, 0xff); - write_codec_file(8, 0x3f); - mdelay(10); - - write_codec_file(22, 0x60);//mic 1 - write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 - write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 - write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 - write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 - write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 - - write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 - write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0 - write_codec_file_bit(6, 1, 3);// gain set - - write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 - mdelay(100); - write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0 - //write_codec_file(1, 0x4); -} -#endif - -#if 0 /* mask warning */ -/* unset Record MIC input audio with direct playback */ -void unset_record_mic_input_audio_with_direct_playback(void) -{ - /* ADC path for MIC IN */ - jz_mic_only = 0; - write_codec_file_bit(5, 1, 4);//SB_ADC->1 - write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 - write_codec_file(22, 0xc0);//CR3.SB_MIC1 - write_codec_file_bit(5, 1, 6);//PMR1.SB_OUT->1 - write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 - write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 - write_codec_file_bit(6, 1, 1);//SB->1 -} -#endif - -#if 0 /* mask warning */ -/* set Record playing audio mixed with MIC input audio */ -void set_record_playing_audio_mixed_with_mic_input_audio(void) -{ - write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 - write_codec_file(9, 0xff); - //write_codec_file(8, 0x30); - write_codec_file(8, 0x20); - mdelay(10); - - write_codec_file(22, 0x63);//mic 1 - - write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 - write_codec_file_bit(6, 1, 3);// gain set - - write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 - write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 - write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 - write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 - write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 - write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 - write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 - write_codec_file_bit(5, 0, 4);//PMR1.SB_MIX->0 -} -#endif - -#if 0 /* mask warning */ -/* unset Record playing audio mixed with MIC input audio */ -void unset_record_playing_audio_mixed_with_mic_input_audio(void) -{ - /* ADC path */ - write_codec_file_bit(5, 1, 4);//SB_ADC->1 - write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 - //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 - write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 - //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 - //write_codec_file_bit(5, 1, 6);//SB_OUT->1 - write_codec_file_bit(5, 1, 7);//SB_DAC->1 - write_codec_file_bit(5, 1, 5);//SB_MIX->1 - write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 - write_codec_file_bit(6, 1, 1);//SB->1 -} -#endif - -#if 1 /* mask warning */ -/* set Record MIC input audio with Audio data replay (full duplex) */ -void set_record_mic_input_audio_with_audio_data_replay(void) -{ - write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 - write_codec_file(9, 0xff); - //write_codec_file(8, 0x30); - write_codec_file(8, 0x20); - write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 - write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1 - write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 - - write_codec_file_bit(22, 0, 7);//CR3.SB_MIC->0 - write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0 - - write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 - write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -} -#endif - -#if 1 /* mask warning */ -/* unset Record MIC input audio with Audio data replay (full duplex) */ -void unset_record_mic_input_audio_with_audio_data_replay(void) -{ - /* ADC path */ - write_codec_file_bit(5, 1, 4);//SB_ADC->1 - write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 - //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 - write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 - write_codec_file_bit(5, 1, 7);//SB_DAC->1 - write_codec_file_bit(5, 1, 5);//SB_MIX->1 - write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 - write_codec_file_bit(6, 1, 1);//SB->1 -} -#endif - -#if 1 /* mask warning */ -/* set Record LINE input audio with Audio data replay (full duplex for linein) */ -void set_record_line_input_audio_with_audio_data_replay(void) -{ - write_codec_file(9, 0xff); - //write_codec_file(8, 0x30); - write_codec_file(8, 0x20); - write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0 - write_codec_file_bit(5, 0, 3);//PMR1.SB_LIN->0 - write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1 - write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 - //write_codec_file_bit(22, 1, 7);//CR3.SB_MIC->1 - write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1 - write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 - - - //jz_mic_only = 1; - write_codec_file(22, 0xc6);//line in 1 - write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0 - write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0 - write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0 -} -#endif - -#if 1 /* mask warning */ -/* unset Record LINE input audio with Audio data replay (full duplex for linein) */ -void unset_record_line_input_audio_with_audio_data_replay(void) -{ - /* ADC path */ - write_codec_file_bit(5, 1, 4);//SB_ADC->1 - write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1 - //write_codec_file_bit(1, 1, 6);//CR1.MONO->1 - write_codec_file(22, 0xc0);//CR3.SB_MIC1->1 - write_codec_file_bit(5, 1, 7);//SB_DAC->1 - write_codec_file_bit(5, 1, 5);//SB_MIX->1 - write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 - write_codec_file_bit(6, 1, 1);//SB->1 -} -#endif - -#if 1 -/* unset Audio data replay */ -void unset_audio_data_replay(void) -{ - //write_codec_file_bit(1, 1, 5);//DAC_MUTE->1 - //mdelay(800); - //write_codec_file_bit(5, 1, 6);//SB_OUT->1 - //mdelay(800); - write_codec_file_bit(5, 1, 7);//SB_DAC->1 - write_codec_file_bit(5, 1, 4);//SB_MIX->1 - write_codec_file_bit(6, 1, 0);//SB_SLEEP->1 - write_codec_file_bit(6, 1, 1);//SB->1 -} -#endif - -void set_dlv_replay(void) -{ - set_audio_data_replay(); -} - -void set_dlv_speed(int rate) -{ - int speed = 0, val; - speed = 0; - switch (rate) { - case 8000: - speed = 10; - break; - case 9600: - speed = 9; - break; - case 11025: - speed = 8; - break; - case 12000: - speed = 7; - break; - case 16000: - speed = 6; - break; - case 22050: - speed = 5; - break; - case 24000: - speed = 4; - break; - case 32000: - speed = 3; - break; - case 44100: - speed = 2; - break; - case 48000: - speed = 1; - break; - case 96000: - speed = 0; - break; - default: - break; - } - - val = read_codec_file(4); - val = (speed << 4) | speed; - write_codec_file(4, val); -} - -void reset_jzcodec(void) -{ - -} - -void dlv_mixer_old_info_id_name(void) -{ - strncpy(info.id, "JZDLV", sizeof(info.id)); - strncpy(info.name,"Jz internal codec dlv on jz4750", sizeof(info.name)); -} - -void dlv_mixer_info_id_name(void) -{ - strncpy(old_info.id, "JZDLV", sizeof(old_info.id)); - strncpy(old_info.name,"Jz internal codec dlv on jz4750", sizeof(old_info.name)); -} - -void set_dlv_mic(int val) -{ - int cur_vol ; - /* set gain */ - //write_codec_file_bit(6, 1, 3);//GIM - cur_vol = 31 * val / 100; - cur_vol |= cur_vol << 4; - write_codec_file(19, cur_vol);//GIL,GIR -} - -void set_dlv_line(int val) -{ - int cur_vol; - /* set gain */ - cur_vol = 31 * val / 100; - cur_vol &= 0x1f; - write_codec_file(11, cur_vol);//GO1L - write_codec_file(12, cur_vol);//GO1R -} - -void set_dlv_volume(int val) -{ - unsigned long cur_vol; - cur_vol = 31 * (100 - val) / 100; - write_codec_file(17, cur_vol | 0xc0); - write_codec_file(18, cur_vol); -} - -static int __init init_dlv(void) -{ - set_codec_mode = set_dlv_mode; - each_time_init_codec = each_time_init_dlv; - reset_codec = reset_dlv_codec; - set_codec_startup_param = set_dlv_startup_param; - - set_codec_replay = set_dlv_replay; - - set_codec_speed = set_dlv_speed; - - codec_mixer_old_info_id_name = dlv_mixer_old_info_id_name; - codec_mixer_info_id_name = dlv_mixer_info_id_name; - - set_codec_volume = set_dlv_volume; - set_codec_mic = set_dlv_mic; - set_codec_line = set_dlv_line; - - return 0; -} - - -static void __exit cleanup_dlv(void) -{ - -} - -module_init(init_dlv); -module_exit(cleanup_dlv); diff --git a/target/linux/xburst/files-2.6.27/sound/oss/jzdlv.h b/target/linux/xburst/files-2.6.27/sound/oss/jzdlv.h deleted file mode 100755 index d36156378..000000000 --- a/target/linux/xburst/files-2.6.27/sound/oss/jzdlv.h +++ /dev/null @@ -1,21 +0,0 @@ -/* header file for dlv */ -void write_codec_file(int addr, int val); -int read_codec_file(int addr); -void printk_codec_files(void); -int write_codec_file_bit(int addr, int bitval, int mask_bit); -void set_audio_data_replay(void); -void unset_audio_data_replay(void); -void set_record_mic_input_audio_without_playback(void); -void unset_record_mic_input_audio_without_playback(void); -void set_record_line_input_audio_without_playback(void); -void unset_record_line_input_audio_without_playback(void); -void set_playback_line_input_audio_direct_only(void); -void unset_playback_line_input_audio_direct_only(void); -void set_record_mic_input_audio_with_direct_playback(void); -void unset_record_mic_input_audio_with_direct_playback(void); -void set_record_playing_audio_mixed_with_mic_input_audio(void); -void unset_record_playing_audio_mixed_with_mic_input_audio(void); -void set_record_mic_input_audio_with_audio_data_replay(void); -void unset_record_mic_input_audio_with_audio_data_replay(void); -void set_record_line_input_audio_with_audio_data_replay(void); -void unset_record_line_input_audio_with_audio_data_replay(void); diff --git a/target/linux/xburst/patches-2.6.27/001-ingenic-patchset.patch b/target/linux/xburst/patches-2.6.27/001-ingenic-patchset.patch index ba220c112..81e6f8516 100644 --- a/target/linux/xburst/patches-2.6.27/001-ingenic-patchset.patch +++ b/target/linux/xburst/patches-2.6.27/001-ingenic-patchset.patch @@ -5777,113 +5777,6 @@ diff -ru linux-2.6/sound/core/pcm_native.c /plain/src/qi/linux-2.6.27.git.svn/so } static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params, -diff -ru linux-2.6/sound/oss/Kconfig /plain/src/qi/linux-2.6.27.git.svn/sound/oss/Kconfig ---- linux-2.6/sound/oss/Kconfig 2009-08-17 23:58:04.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/sound/oss/Kconfig 2009-08-12 10:39:09.000000000 +0200 -@@ -5,6 +5,75 @@ - # - # Prompt user for primary drivers. - -+config OSS_OBSOLETE -+ bool "Obsolete OSS drivers" -+ depends on SOUND_PRIME -+ help -+ This option enables support for obsolete OSS drivers that -+ are scheduled for removal in the near future. -+ -+ Please contact Adrian Bunk if you had to -+ say Y here because your hardware is not properly supported -+ by ALSA. -+ -+ If unsure, say N. -+ -+config SOUND_JZ_AC97 -+ bool "Jz On-Chip AC97 driver" -+ depends on OSS_OBSOLETE -+ help -+ Say Y here if you have want to select the on-chip AC97 driver -+ on Jz4730/Jz4740/Jz5730. -+ -+config SOUND_JZ_I2S -+ bool "Jz On-Chip I2S driver" -+ depends on OSS_OBSOLETE -+ help -+ Say Y here if you have want to select the on-chip I2S driver -+ on Jz4730/Jz4740/Jz5730. -+ -+config SOUND_JZ_PCM -+ bool "Jz On-Chip PCM driver" -+ depends on SOC_JZ4750 -+ help -+ Say Y here if you have want to select the on-chip PCM driver -+ on Jz4750. -+ -+choice -+ prompt "I2S codec type" -+ depends on SOUND_JZ_I2S -+ -+config I2S_AK4642EN -+ bool "AK4642EN" -+ depends on SOC_JZ4730 -+ help -+ Answer Y if you have an external AK4642EN codec. -+ -+config I2S_ICODEC -+ bool "Internal On-Chip codec" -+ depends on SOC_JZ4740 -+ help -+ Answer Y if you have an internal I2S codec. -+ -+config I2S_DLV -+ bool "Internal On-Chip codec on Jz4750 or Jz4750d" -+ depends on SOC_JZ4750 || SOC_JZ4750D -+ help -+ Answer Y if you have an internal I2S codec on Jz4750 or Jz4750d. -+ -+endchoice -+ -+choice -+ prompt "PCM codec type" -+ depends on SOUND_JZ_PCM -+ -+config PCM_TLV320AIC1106 -+ bool "TLV320AIC1106" -+ help -+ Answer Y if you have an TI tlv320aic 1106 codec. -+ -+endchoice -+ - config SOUND_BCM_CS4297A - tristate "Crystal Sound CS4297a (for Swarm)" - depends on SIBYTE_SWARM -diff -ru linux-2.6/sound/oss/Makefile /plain/src/qi/linux-2.6.27.git.svn/sound/oss/Makefile ---- linux-2.6/sound/oss/Makefile 2009-08-17 23:58:04.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/sound/oss/Makefile 2009-08-12 10:39:09.000000000 +0200 -@@ -9,6 +9,12 @@ - - # Please leave it as is, cause the link order is significant ! - -+obj-$(CONFIG_SOUND_JZ_AC97) += jz_ac97.o ac97_codec.o -+obj-$(CONFIG_I2S_AK4642EN) += ak4642en.o -+obj-$(CONFIG_I2S_ICODEC) += jzcodec.o jz_i2s.o -+obj-$(CONFIG_I2S_DLV) += jzdlv.o jz_i2s.o -+obj-$(CONFIG_SOUND_JZ_PCM) += jz_pcm_tlv320aic1106_dma.o -+ - obj-$(CONFIG_SOUND_SH_DAC_AUDIO) += sh_dac_audio.o - obj-$(CONFIG_SOUND_HAL2) += hal2.o - obj-$(CONFIG_SOUND_AEDSP16) += aedsp16.o -diff -ru linux-2.6/sound/oss/os.h /plain/src/qi/linux-2.6.27.git.svn/sound/oss/os.h ---- linux-2.6/sound/oss/os.h 2009-08-17 23:57:37.000000000 +0200 -+++ /plain/src/qi/linux-2.6.27.git.svn/sound/oss/os.h 2009-08-12 10:39:09.000000000 +0200 -@@ -9,7 +9,7 @@ - #ifdef __KERNEL__ - #include - #include --#include -+//#include - #include - #include - #include diff -ru linux-2.6/sound/soc/codecs/Kconfig /plain/src/qi/linux-2.6.27.git.svn/sound/soc/codecs/Kconfig --- linux-2.6/sound/soc/codecs/Kconfig 2009-08-17 23:58:04.000000000 +0200 +++ /plain/src/qi/linux-2.6.27.git.svn/sound/soc/codecs/Kconfig 2009-08-12 10:39:09.000000000 +0200