From 28ac67add5c6134ee7227a2352361e2de5b06ed7 Mon Sep 17 00:00:00 2001 From: Marcin Juszkiewicz Date: Mon, 27 Nov 2006 16:59:23 +0000 Subject: libexif: added 0.6.13 --- packages/libexif/libexif_0.6.13.bb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 packages/libexif/libexif_0.6.13.bb diff --git a/packages/libexif/libexif_0.6.13.bb b/packages/libexif/libexif_0.6.13.bb new file mode 100644 index 0000000000..9f3136798f --- /dev/null +++ b/packages/libexif/libexif_0.6.13.bb @@ -0,0 +1,18 @@ +DESCRIPTION = "Library to read the extended image information (EXIF) from JPEG pictures" +HOMEPAGE = "http://sourceforge.net/projects/libexif" +SECTION = "libs" +LICENSE = "LGPL" + +SRC_URI = "${SOURCEFORGE_MIRROR}/libexif/libexif-${PV}.tar.bz2" + +inherit autotools pkgconfig + +do_stage() { + oe_libinstall -a -so -C libexif libexif ${STAGING_LIBDIR} + + install -d ${STAGING_INCDIR}/libexif + for X in exif-byte-order.h exif-data.h exif-format.h exif-loader.h exif-tag.h exif-content.h exif-entry.h exif-ifd.h exif-utils.h exif-log.h exif-mnote-data.h _stdint.h + do + install -m 0644 ${S}/libexif/$X ${STAGING_INCDIR}/libexif/$X + done +} -- cgit v1.2.3 From 3b8845fae2df131cc5528009ab2e96e86560ccee Mon Sep 17 00:00:00 2001 From: Matthias Hentges Date: Mon, 27 Nov 2006 19:35:58 +0000 Subject: initscripts: - Reformat some echo lines to be more readable on QVGA - echo RETURNCODE after fsck run - raise RETURNCODE for a FUBAR FS to -gt3 --- packages/initscripts/initscripts-1.0/checkroot.sh | 14 +++++++++----- packages/initscripts/initscripts_1.0.bb | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/initscripts/initscripts-1.0/checkroot.sh b/packages/initscripts/initscripts-1.0/checkroot.sh index df3035371b..44db23707e 100755 --- a/packages/initscripts/initscripts-1.0/checkroot.sh +++ b/packages/initscripts/initscripts-1.0/checkroot.sh @@ -148,7 +148,10 @@ else # 2 or larger. A return code of 1 indicates that filesystem # errors were corrected but that the boot may proceed. # - if test "$?" -gt 1 + + echo "RETURNCODE: [$RTC]" + + if test "$RTC" -gt 3 then # Since this script is run very early in the boot-process, it should be safe to assume that the @@ -159,13 +162,14 @@ else # Surprise! Re-directing from a HERE document (as in # "cat << EOF") won't work, because the root is read-only. echo - echo "fsck failed. Please repair manually and reboot. Please note" - echo "that the root filesystem is currently mounted read-only. To" - echo "remount it read-write:" + echo "fsck failed. Please repair manually and reboot. " + echo "Please note that the root filesystem is currently " + echo "mounted read-only. To remount it read-write:" echo echo " # mount -n -o remount,rw /" echo - echo "CONTROL-D will exit from this shell and REBOOT the system." + echo "CONTROL-D will exit from this shell" + echo "and REBOOT the system." echo # Start a single user shell on the console /sbin/sulogin $CONSOLE diff --git a/packages/initscripts/initscripts_1.0.bb b/packages/initscripts/initscripts_1.0.bb index 306629732a..39662eb31a 100644 --- a/packages/initscripts/initscripts_1.0.bb +++ b/packages/initscripts/initscripts_1.0.bb @@ -5,7 +5,7 @@ DEPENDS = "makedevs" DEPENDS_openzaurus = "makedevs virtual/kernel" RDEPENDS = "makedevs" LICENSE = "GPL" -PR = "r82" +PR = "r83" SRC_URI = "file://halt \ file://ramdisk \ -- cgit v1.2.3 From 28fa247ca598fad3ce28eeb342b529ee990221ff Mon Sep 17 00:00:00 2001 From: Marcin Juszkiewicz Date: Mon, 27 Nov 2006 20:00:21 +0000 Subject: bash: added 3.2 with upstream patches: 001 -> 005 --- packages/bash/bash-3.2/.mtn2git_empty | 0 packages/bash/bash-3.2/001-005.patch | 312 ++++++++++++++++++++++++++++++++++ packages/bash/bash_3.2.bb | 28 +++ 3 files changed, 340 insertions(+) create mode 100644 packages/bash/bash-3.2/.mtn2git_empty create mode 100644 packages/bash/bash-3.2/001-005.patch create mode 100644 packages/bash/bash_3.2.bb diff --git a/packages/bash/bash-3.2/.mtn2git_empty b/packages/bash/bash-3.2/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/bash/bash-3.2/001-005.patch b/packages/bash/bash-3.2/001-005.patch new file mode 100644 index 0000000000..541d71385f --- /dev/null +++ b/packages/bash/bash-3.2/001-005.patch @@ -0,0 +1,312 @@ + +Collected upstream patches: 001 -> 005 + +Index: bash-3.2/parse.y +=================================================================== +--- bash-3.2.orig/parse.y 2006-11-27 20:09:18.000000000 +0100 ++++ bash-3.2/parse.y 2006-11-27 20:10:10.000000000 +0100 +@@ -1029,6 +1029,7 @@ + #define PST_CMDTOKEN 0x1000 /* command token OK - unused */ + #define PST_COMPASSIGN 0x2000 /* parsing x=(...) compound assignment */ + #define PST_ASSIGNOK 0x4000 /* assignment statement ok in this context */ ++#define PST_REGEXP 0x8000 /* parsing an ERE/BRE as a single word */ + + /* Initial size to allocate for tokens, and the + amount to grow them by. */ +@@ -2591,6 +2592,9 @@ + return (character); + } + ++ if (parser_state & PST_REGEXP) ++ goto tokword; ++ + /* Shell meta-characters. */ + if MBTEST(shellmeta (character) && ((parser_state & PST_DBLPAREN) == 0)) + { +@@ -2698,6 +2702,7 @@ + if MBTEST(character == '-' && (last_read_token == LESS_AND || last_read_token == GREATER_AND)) + return (character); + ++tokword: + /* Okay, if we got this far, we have to read a word. Read one, + and then check it against the known ones. */ + result = read_token_word (character); +@@ -2735,7 +2740,7 @@ + /* itrace("parse_matched_pair: open = %c close = %c", open, close); */ + count = 1; + pass_next_character = backq_backslash = was_dollar = in_comment = 0; +- check_comment = (flags & P_COMMAND) && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0; ++ check_comment = (flags & P_COMMAND) && qc != '`' && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0; + + /* RFLAGS is the set of flags we want to pass to recursive calls. */ + rflags = (qc == '"') ? P_DQUOTE : (flags & P_DQUOTE); +@@ -3202,8 +3207,11 @@ + if (tok == WORD && test_binop (yylval.word->word)) + op = yylval.word; + #if defined (COND_REGEXP) +- else if (tok == WORD && STREQ (yylval.word->word,"=~")) +- op = yylval.word; ++ else if (tok == WORD && STREQ (yylval.word->word, "=~")) ++ { ++ op = yylval.word; ++ parser_state |= PST_REGEXP; ++ } + #endif + else if (tok == '<' || tok == '>') + op = make_word_from_token (tok); /* ( */ +@@ -3234,6 +3242,7 @@ + + /* rhs */ + tok = read_token (READ); ++ parser_state &= ~PST_REGEXP; + if (tok == WORD) + { + tright = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL); +@@ -3419,9 +3428,34 @@ + goto next_character; + } + ++#ifdef COND_REGEXP ++ /* When parsing a regexp as a single word inside a conditional command, ++ we need to special-case characters special to both the shell and ++ regular expressions. Right now, that is only '(' and '|'. */ /*)*/ ++ if MBTEST((parser_state & PST_REGEXP) && (character == '(' || character == '|')) /*)*/ ++ { ++ if (character == '|') ++ goto got_character; ++ ++ push_delimiter (dstack, character); ++ ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0); ++ pop_delimiter (dstack); ++ if (ttok == &matched_pair_error) ++ return -1; /* Bail immediately. */ ++ RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2, ++ token_buffer_size, TOKEN_DEFAULT_GROW_SIZE); ++ token[token_index++] = character; ++ strcpy (token + token_index, ttok); ++ token_index += ttoklen; ++ FREE (ttok); ++ dollar_present = all_digit_token = 0; ++ goto next_character; ++ } ++#endif /* COND_REGEXP */ ++ + #ifdef EXTENDED_GLOB + /* Parse a ksh-style extended pattern matching specification. */ +- if (extended_glob && PATTERN_CHAR (character)) ++ if MBTEST(extended_glob && PATTERN_CHAR (character)) + { + peek_char = shell_getc (1); + if MBTEST(peek_char == '(') /* ) */ +Index: bash-3.2/patchlevel.h +=================================================================== +--- bash-3.2.orig/patchlevel.h 2006-11-27 20:09:18.000000000 +0100 ++++ bash-3.2/patchlevel.h 2006-11-27 20:11:06.000000000 +0100 +@@ -25,6 +25,6 @@ + regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh + looks for to find the patch level (for the sccs version string). */ + +-#define PATCHLEVEL 0 ++#define PATCHLEVEL 5 + + #endif /* _PATCHLEVEL_H_ */ +Index: bash-3.2/po/ru.po +=================================================================== +--- bash-3.2.orig/po/ru.po 2006-11-27 20:09:18.000000000 +0100 ++++ bash-3.2/po/ru.po 2006-11-27 20:10:00.000000000 +0100 +@@ -12,7 +12,7 @@ + "Last-Translator: Evgeniy Dushistov \n" + "Language-Team: Russian \n" + "MIME-Version: 1.0\n" +-"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Type: text/plain; charset=KOI8-R\n" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +Index: bash-3.2/subst.c +=================================================================== +--- bash-3.2.orig/subst.c 2006-11-27 20:09:18.000000000 +0100 ++++ bash-3.2/subst.c 2006-11-27 20:10:26.000000000 +0100 +@@ -5707,6 +5707,11 @@ + vtype &= ~VT_STARSUB; + + mflags = 0; ++ if (patsub && *patsub == '/') ++ { ++ mflags |= MATCH_GLOBREP; ++ patsub++; ++ } + + /* Malloc this because expand_string_if_necessary or one of the expansion + functions in its call chain may free it on a substitution error. */ +@@ -5741,13 +5746,12 @@ + } + + /* ksh93 doesn't allow the match specifier to be a part of the expanded +- pattern. This is an extension. */ ++ pattern. This is an extension. Make sure we don't anchor the pattern ++ at the beginning or end of the string if we're doing global replacement, ++ though. */ + p = pat; +- if (pat && pat[0] == '/') +- { +- mflags |= MATCH_GLOBREP|MATCH_ANY; +- p++; +- } ++ if (mflags & MATCH_GLOBREP) ++ mflags |= MATCH_ANY; + else if (pat && pat[0] == '#') + { + mflags |= MATCH_BEG; +Index: bash-3.2/tests/new-exp.right +=================================================================== +--- bash-3.2.orig/tests/new-exp.right 2006-11-27 20:09:18.000000000 +0100 ++++ bash-3.2/tests/new-exp.right 2006-11-27 20:10:29.000000000 +0100 +@@ -430,7 +430,7 @@ + Case06---1---A B C::--- + Case07---3---A:B:C--- + Case08---3---A:B:C--- +-./new-exp.tests: line 506: /${$(($#-1))}: bad substitution ++./new-exp.tests: line 506: ${$(($#-1))}: bad substitution + argv[1] = + argv[2] = + argv[3] = +Index: bash-3.2/builtins/printf.def +=================================================================== +--- bash-3.2.orig/builtins/printf.def 2006-11-27 20:09:18.000000000 +0100 ++++ bash-3.2/builtins/printf.def 2006-11-27 20:11:05.000000000 +0100 +@@ -49,6 +49,12 @@ + # define INT_MIN (-2147483647-1) + #endif + ++#if defined (PREFER_STDARG) ++# include ++#else ++# include ++#endif ++ + #include + #include + +@@ -151,6 +157,10 @@ + #define SKIP1 "#'-+ 0" + #define LENMODS "hjlLtz" + ++#ifndef HAVE_ASPRINTF ++extern int asprintf __P((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3))); ++#endif ++ + static void printf_erange __P((char *)); + static int printstr __P((char *, char *, int, int, int)); + static int tescape __P((char *, char *, int *)); +Index: bash-3.2/lib/sh/snprintf.c +=================================================================== +--- bash-3.2.orig/lib/sh/snprintf.c 2006-11-27 20:09:18.000000000 +0100 ++++ bash-3.2/lib/sh/snprintf.c 2006-11-27 20:11:06.000000000 +0100 +@@ -471,6 +471,8 @@ + 10^x ~= r + * log_10(200) = 2; + * log_10(250) = 2; ++ * ++ * NOTE: do not call this with r == 0 -- an infinite loop results. + */ + static int + log_10(r) +@@ -576,8 +578,11 @@ + { + integral_part[0] = '0'; + integral_part[1] = '\0'; +- fraction_part[0] = '0'; +- fraction_part[1] = '\0'; ++ /* The fractional part has to take the precision into account */ ++ for (ch = 0; ch < precision-1; ch++) ++ fraction_part[ch] = '0'; ++ fraction_part[ch] = '0'; ++ fraction_part[ch+1] = '\0'; + if (fract) + *fract = fraction_part; + return integral_part; +@@ -805,6 +810,7 @@ + PUT_CHAR(*tmp, p); + tmp++; + } ++ + PAD_LEFT(p); + } + +@@ -972,11 +978,21 @@ + if ((p->flags & PF_THOUSANDS) && grouping && (t = groupnum (tmp))) + tmp = t; + ++ if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0) ++ { ++ /* smash the trailing zeros unless altform */ ++ for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--) ++ tmp2[i] = '\0'; ++ if (tmp2[0] == '\0') ++ p->precision = 0; ++ } ++ + /* calculate the padding. 1 for the dot */ + p->width = p->width - + ((d > 0. && p->justify == RIGHT) ? 1:0) - + ((p->flags & PF_SPACE) ? 1:0) - +- strlen(tmp) - p->precision - 1; ++ strlen(tmp) - p->precision - ++ ((p->precision != 0 || (p->flags & PF_ALTFORM)) ? 1 : 0); /* radix char */ + PAD_RIGHT(p); + PUT_PLUS(d, p, 0.); + PUT_SPACE(d, p, 0.); +@@ -991,11 +1007,6 @@ + if (p->precision != 0 || (p->flags & PF_ALTFORM)) + PUT_CHAR(decpoint, p); /* put the '.' */ + +- if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0) +- /* smash the trailing zeros unless altform */ +- for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--) +- tmp2[i] = '\0'; +- + for (; *tmp2; tmp2++) + PUT_CHAR(*tmp2, p); /* the fraction */ + +@@ -1011,14 +1022,19 @@ + char *tmp, *tmp2; + int j, i; + +- if (chkinfnan(p, d, 1) || chkinfnan(p, d, 2)) ++ if (d != 0 && (chkinfnan(p, d, 1) || chkinfnan(p, d, 2))) + return; /* already printed nan or inf */ + + GETLOCALEDATA(decpoint, thoussep, grouping); + DEF_PREC(p); +- j = log_10(d); +- d = d / pow_10(j); /* get the Mantissa */ +- d = ROUND(d, p); ++ if (d == 0.) ++ j = 0; ++ else ++ { ++ j = log_10(d); ++ d = d / pow_10(j); /* get the Mantissa */ ++ d = ROUND(d, p); ++ } + tmp = dtoa(d, p->precision, &tmp2); + + /* 1 for unit, 1 for the '.', 1 for 'e|E', +@@ -1076,6 +1092,7 @@ + PUT_CHAR(*tmp, p); + tmp++; + } ++ + PAD_LEFT(p); + } + #endif +@@ -1358,7 +1375,7 @@ + STAR_ARGS(data); + DEF_PREC(data); + d = GETDOUBLE(data); +- i = log_10(d); ++ i = (d != 0.) ? log_10(d) : -1; + /* + * for '%g|%G' ANSI: use f if exponent + * is in the range or [-4,p] exclusively diff --git a/packages/bash/bash_3.2.bb b/packages/bash/bash_3.2.bb new file mode 100644 index 0000000000..e3d6b0560c --- /dev/null +++ b/packages/bash/bash_3.2.bb @@ -0,0 +1,28 @@ +DESCRIPTION = "An sh-compatible command language interpreter." +HOMEPAGE = "http://cnswww.cns.cwru.edu/~chet/bash/bashtop.html" +DEPENDS = "ncurses" +SECTION = "base/shell" +LICENSE = "GPL" + +SRC_URI = "${GNU_MIRROR}/bash/bash-${PV}.tar.gz \ + file://001-005.patch;patch=1" + +inherit autotools gettext + +PARALLEL_MAKE = "" + +bindir = "/bin" +sbindir = "/sbin" + +EXTRA_OECONF = "--with-ncurses" +export CC_FOR_BUILD = "${BUILD_CC}" + +do_configure () { + gnu-configize + oe_runconf +} + +pkg_postinst () { + grep -q "bin/bash" ${sysconfdir}/shells || echo /bin/bash >> ${sysconfdir}/shells + grep -q "bin/sh" ${sysconfdir}/shells || echo /bin/sh >> ${sysconfdir}/shells +} -- cgit v1.2.3 From 98c24fd9863bbcd80db9c43602d0e72d901e810e Mon Sep 17 00:00:00 2001 From: Matthias Hentges Date: Mon, 27 Nov 2006 20:29:10 +0000 Subject: linux: Update 2.6.17 to latest asoc * untested in .dev * --- .../asoc-v0.12.4_2.6.17.patch | 31713 +++++++++++++++++++ packages/linux/linux-openzaurus_2.6.17.bb | 7 +- 2 files changed, 31716 insertions(+), 4 deletions(-) create mode 100644 packages/linux/linux-openzaurus-2.6.17/asoc-v0.12.4_2.6.17.patch diff --git a/packages/linux/linux-openzaurus-2.6.17/asoc-v0.12.4_2.6.17.patch b/packages/linux/linux-openzaurus-2.6.17/asoc-v0.12.4_2.6.17.patch new file mode 100644 index 0000000000..7fa3822bba --- /dev/null +++ b/packages/linux/linux-openzaurus-2.6.17/asoc-v0.12.4_2.6.17.patch @@ -0,0 +1,31713 @@ +Index: linux-2.6-pxa-new/Documentation/sound/alsa/soc/DAI.txt +=================================================================== +--- /dev/null ++++ linux-2.6-pxa-new/Documentation/sound/alsa/soc/DAI.txt +@@ -0,0 +1,546 @@ ++ASoC currently supports the three main Digital Audio Interfaces (DAI) found on ++SoC controllers and portable audio CODECS today, namely AC97, I2S and PCM. ++ ++ ++AC97 ++==== ++ ++ AC97 is a five wire interface commonly found on many PC sound cards. It is ++now also popular in many portable devices. This DAI has a reset line and time ++multiplexes its data on its SDATA_OUT (playback) and SDATA_IN (capture) lines. ++The bit clock (BCLK) is always driven by the CODEC (usually 12.288MHz) and the ++frame (FRAME) (usually 48kHz) is always driven by the controller. Each AC97 ++frame is 21uS long and is divided into 13 time slots. ++ ++The AC97 specification can be found at :- ++http://www.intel.com/design/chipsets/audio/ac97_r23.pdf ++ ++ ++I2S ++=== ++ ++ I2S is a common 4 wire DAI used in HiFi, STB and portable devices. The Tx and ++Rx lines are used for audio transmision, whilst the bit clock (BCLK) and ++left/right clock (LRC) synchronise the link. I2S is flexible in that either the ++controller or CODEC can drive (master) the BCLK and LRC clock lines. Bit clock ++usually varies depending on the sample rate and the master system clock ++(SYSCLK). LRCLK is the same as the sample rate. A few devices support separate ++ADC and DAC LRCLK's, this allows for similtanious capture and playback at ++different sample rates. ++ ++I2S has several different operating modes:- ++ ++ o I2S - MSB is transmitted on the falling edge of the first BCLK after LRC ++ transition. ++ ++ o Left Justified - MSB is transmitted on transition of LRC. ++ ++ o Right Justified - MSB is transmitted sample size BCLK's before LRC ++ transition. ++ ++PCM ++=== ++ ++PCM is another 4 wire interface, very similar to I2S, that can support a more ++flexible protocol. It has bit clock (BCLK) and sync (SYNC) lines that are used ++to synchronise the link whilst the Tx and Rx lines are used to transmit and ++receive the audio data. Bit clock usually varies depending on sample rate ++whilst sync runs at the sample rate. PCM also supports Time Division ++Multiplexing (TDM) in that several devices can use the bus similtaniuosly (This ++is sometimes referred to as network mode). ++ ++Common PCM operating modes:- ++ ++ o Mode A - MSB is transmitted on falling edge of first BCLK after FRAME/SYNC. ++ ++ o Mode B - MSB is transmitted on rising edge of FRAME/SYNC. ++ ++ ++ASoC DAI Configuration ++====================== ++ ++Every CODEC DAI and SoC DAI must have their capabilities defined in order to ++be configured together at runtime when the audio and clocking parameters are ++known. This is achieved by creating an array of struct snd_soc_hw_mode in the ++the CODEC and SoC interface drivers. Each element in the array describes a DAI ++mode and each mode is usually based upon the DAI system clock to sample rate ++ratio (FS). ++ ++i.e. 48k sample rate @ 256 FS = sytem clock of 12.288 MHz ++ 48000 * 256 = 12288000 ++ ++The CPU and Codec DAI modes are then ANDed together at runtime to determine the ++rutime DAI configuration for both the Codec and CPU. ++ ++When creating a new codec or SoC DAI it's probably best to start of with a few ++sample rates first and then test your interface. ++ ++struct snd_soc_dai_mode is defined (in soc.h) as:- ++ ++/* SoC DAI mode */ ++struct snd_soc_dai_mode { ++ u16 fmt; /* SND_SOC_DAIFMT_* */ ++ u16 tdm; /* SND_SOC_HWTDM_* */ ++ u64 pcmfmt; /* SNDRV_PCM_FMTBIT_* */ ++ u16 pcmrate; /* SND_SOC_HWRATE_* */ ++ u16 pcmdir:2; /* SND_SOC_HWDIR_* */ ++ u16 flags:8; /* hw flags */ ++ u16 fs; /* mclk to rate divider */ ++ u64 bfs; /* mclk to bclk dividers */ ++ unsigned long priv; /* private mode data */ ++}; ++ ++fmt: ++---- ++This field defines the DAI mode hardware format (e.g. I2S settings) and ++supports the following settings:- ++ ++ 1) hardware DAI formats ++ ++#define SND_SOC_DAIFMT_I2S (1 << 0) /* I2S mode */ ++#define SND_SOC_DAIFMT_RIGHT_J (1 << 1) /* Right justified mode */ ++#define SND_SOC_DAIFMT_LEFT_J (1 << 2) /* Left Justified mode */ ++#define SND_SOC_DAIFMT_DSP_A (1 << 3) /* L data msb after FRM */ ++#define SND_SOC_DAIFMT_DSP_B (1 << 4) /* L data msb during FRM */ ++#define SND_SOC_DAIFMT_AC97 (1 << 5) /* AC97 */ ++ ++ 2) hw DAI signal inversions ++ ++#define SND_SOC_DAIFMT_NB_NF (1 << 8) /* normal bit clock + frame */ ++#define SND_SOC_DAIFMT_NB_IF (1 << 9) /* normal bclk + inv frm */ ++#define SND_SOC_DAIFMT_IB_NF (1 << 10) /* invert bclk + nor frm */ ++#define SND_SOC_DAIFMT_IB_IF (1 << 11) /* invert bclk + frm */ ++ ++ 3) hw clock masters ++ This is wrt the codec, the inverse is true for the interface ++ i.e. if the codec is clk and frm master then the interface is ++ clk and frame slave. ++ ++#define SND_SOC_DAIFMT_CBM_CFM (1 << 12) /* codec clk & frm master */ ++#define SND_SOC_DAIFMT_CBS_CFM (1 << 13) /* codec clk slave & frm master */ ++#define SND_SOC_DAIFMT_CBM_CFS (1 << 14) /* codec clk master & frame slave */ ++#define SND_SOC_DAIFMT_CBS_CFS (1 << 15) /* codec clk & frm slave */ ++ ++At least one option from each section must be selected. Multiple selections are ++also supported e.g. ++ ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_RIGHT_J | \ ++ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_IB_NF | \ ++ SND_SOC_DAIFMT_IB_IF ++ ++ ++tdm: ++------ ++This field defines the Time Division Multiplexing left and right word ++positions for the DAI mode if applicable. Set to SND_SOC_DAITDM_LRDW(0,0) for ++no TDM. ++ ++ ++pcmfmt: ++--------- ++The hardware PCM format. This describes the PCM formats supported by the DAI ++mode e.g. ++ ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \ ++ SNDRV_PCM_FORMAT_S24_3LE ++ ++pcmrate: ++---------- ++The PCM sample rates supported by the DAI mode. e.g. ++ ++ .pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ ++ SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ ++ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 ++ ++ ++pcmdir: ++--------- ++The stream directions supported by this mode. e.g. playback and capture ++ ++ ++flags: ++-------- ++The DAI hardware flags supported by the mode. ++ ++/* use bfs mclk divider mode (BCLK = MCLK / x) */ ++#define SND_SOC_DAI_BFS_DIV 0x1 ++/* use bfs rate mulitplier (BCLK = RATE * x)*/ ++#define SND_SOC_DAI_BFS_RATE 0x2 ++/* use bfs rcw multiplier (BCLK = RATE * CHN * WORD SIZE) */ ++#define SND_SOC_DAI_BFS_RCW 0x4 ++/* capture and playback can use different clocks */ ++#define SND_SOC_DAI_ASYNC 0x8 ++ ++NOTE: Bitclock division and mulitiplication modes can be safely matched by the ++core logic. ++ ++ ++fs: ++----- ++The FS supported by this DAI mode FS is the ratio between the system clock and ++the sample rate. See above ++ ++bfs: ++------ ++BFS is the ratio of BCLK to MCLK or the ratio of BCLK to sample rate (this ++depends on the codec or CPU DAI). ++ ++The BFS supported by the DAI mode. This can either be the ratio between the ++bitclock (BCLK) and the sample rate OR the ratio between the system clock and ++the sample rate. Depends on the flags above. ++ ++priv: ++----- ++private codec mode data. ++ ++ ++ ++Examples ++======== ++ ++Note that Codec DAI and CPU DAI examples are interchangeable in these examples ++as long as the bus master is reversed. i.e. ++ ++ SND_SOC_DAIFMT_CBM_CFM would become SND_SOC_DAIFMT_CBS_CFS ++ and vice versa. ++ ++This applies to all SND_SOC_DAIFMT_CB*_CF*. ++ ++Example 1 ++--------- ++ ++Simple codec that only runs at 8k & 48k @ 256FS in master mode, can generate a ++BCLK of either MCLK/2 or MCLK/4. ++ ++ /* codec master */ ++ { ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE, ++ .pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000, ++ .pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE, ++ .flags = SND_SOC_DAI_BFS_DIV, ++ .fs = 256, ++ .bfs = SND_SOC_FSBD(2) | SND_SOC_FSBD(4), ++ } ++ ++ ++Example 2 ++--------- ++Simple codec that only runs at 8k & 48k @ 256FS in master mode, can generate a ++BCLK of either Rate * 32 or Rate * 64. ++ ++ /* codec master */ ++ { ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE, ++ .pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000, ++ .pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE, ++ .flags = SND_SOC_DAI_BFS_RATE, ++ .fs = 256, ++ .bfs = 32, ++ }, ++ { ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE, ++ .pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000, ++ .pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE, ++ .flags = SND_SOC_DAI_BFS_RATE, ++ .fs = 256, ++ .bfs = 64, ++ }, ++ ++ ++Example 3 ++--------- ++Codec that runs at 8k & 48k @ 256FS in master mode, can generate a BCLK that ++is a multiple of Rate * channels * word size. (RCW) i.e. ++ ++ BCLK = 8000 * 2 * 16 (8k, stereo, 16bit) ++ = 256kHz ++ ++This codecs supports a RCW multiple of 1,2 ++ ++ { ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE, ++ .pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000, ++ .pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE, ++ .flags = SND_SOC_DAI_BFS_RCW, ++ .fs = 256, ++ .bfs = SND_SOC_FSBW(1) | SND_SOC_FSBW(2), ++ } ++ ++ ++Example 4 ++--------- ++Codec that only runs at 8k & 48k @ 256FS in master mode, can generate a ++BCLK of either Rate * 32 or Rate * 64. Codec can also run in slave mode as long ++as BCLK is rate * 32 or rate * 64. ++ ++ /* codec master */ ++ { ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE, ++ .pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000, ++ .pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE, ++ .flags = SND_SOC_DAI_BFS_RATE, ++ .fs = 256, ++ .bfs = 32, ++ }, ++ { ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE, ++ .pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000, ++ .pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE, ++ .flags = SND_SOC_DAI_BFS_RATE, ++ .fs = 256, ++ .bfs = 64, ++ }, ++ ++ /* codec slave */ ++ { ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE, ++ .pcmdir = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000, ++ .pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE, ++ .flags = SND_SOC_DAI_BFS_RATE, ++ .fs = SND_SOC_FS_ALL, ++ .bfs = 32, ++ }, ++ { ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE, ++ .pcmdir = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000, ++ .pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE, ++ .flags = SND_SOC_DAI_BFS_RATE, ++ .fs = SND_SOC_FS_ALL, ++ .bfs = 64, ++ }, ++ ++ ++Example 5 ++--------- ++Codec that only runs at 8k, 16k, 32k, 48k, 96k @ 128FS, 192FS & 256FS in master ++mode and can generate a BCLK of MCLK / (1,2,4,8,16). Codec can also run in slave ++mode as and does not care about FS or BCLK (as long as there is enough bandwidth). ++ ++ #define CODEC_FSB \ ++ (SND_SOC_FSBD(1) | SND_SOC_FSBD(2) | SND_SOC_FSBD(4) | \ ++ SND_SOC_FSBD(8) | SND_SOC_FSBD(16)) ++ ++ #define CODEC_RATES \ ++ (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 |\ ++ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) ++ ++ /* codec master @ 128, 192 & 256 FS */ ++ { ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE, ++ .pcmrate = CODEC_RATES, ++ .pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE, ++ .flags = SND_SOC_DAI_BFS_DIV, ++ .fs = 128, ++ .bfs = CODEC_FSB, ++ }, ++ ++ { ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE, ++ .pcmrate = CODEC_RATES, ++ .pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE, ++ .flags = SND_SOC_DAI_BFS_DIV, ++ .fs = 192, ++ .bfs = CODEC_FSB ++ }, ++ ++ { ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE, ++ .pcmrate = CODEC_RATES, ++ .pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE, ++ .flags = SND_SOC_DAI_BFS_DIV, ++ .fs = 256, ++ .bfs = CODEC_FSB, ++ }, ++ ++ /* codec slave */ ++ { ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE, ++ .pcmrate = CODEC_RATES, ++ .pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE, ++ .fs = SND_SOC_FS_ALL, ++ .bfs = SND_SOC_FSB_ALL, ++ }, ++ ++ ++Example 6 ++--------- ++Codec that only runs at 8k, 44.1k, 48k @ different FS in master mode (for use ++with a fixed MCLK) and can generate a BCLK of MCLK / (1,2,4,8,16). ++Codec can also run in slave mode as and does not care about FS or BCLK (as long ++as there is enough bandwidth). Codec can support 16, 24 and 32 bit PCM sample ++sizes. ++ ++ #define CODEC_FSB \ ++ (SND_SOC_FSBD(1) | SND_SOC_FSBD(2) | SND_SOC_FSBD(4) | \ ++ SND_SOC_FSBD(8) | SND_SOC_FSBD(16)) ++ ++ #define CODEC_PCM_FORMATS \ ++ (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \ ++ SNDRV_PCM_FORMAT_S24_3LE | SNDRV_PCM_FORMAT_S24_LE | SNDRV_PCM_FORMAT_S32_LE) ++ ++ /* codec master */ ++ { ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE, ++ .pcmrate = SNDRV_PCM_RATE_8000, ++ .pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE, ++ .flags = SND_SOC_DAI_BFS_DIV, ++ .fs = 1536, ++ .bfs = CODEC_FSB, ++ }, ++ ++ { ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE, ++ .pcmrate = SNDRV_PCM_RATE_44100, ++ .pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE, ++ .flags = SND_SOC_DAI_BFS_DIV, ++ .fs = 272, ++ .bfs = CODEC_FSB, ++ }, ++ ++ { ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE, ++ .pcmrate = SNDRV_PCM_RATE_48000, ++ .pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE, ++ .flags = SND_SOC_DAI_BFS_DIV, ++ .fs = 256, ++ .bfs = CODEC_FSB, ++ }, ++ ++ /* codec slave */ ++ { ++ .fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, ++ .pcmfmt = SNDRV_PCM_FORMAT_S16_LE, ++ .pcmrate = CODEC_RATES, ++ .pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE, ++ .fs = SND_SOC_FS_ALL, ++ .bfs = SND_SOC_FSB_ALL, ++ }, ++ ++ ++Example 7 ++--------- ++AC97 Codec that does not support VRA (i.e only runs at 48k). ++ ++ #define AC97_DIR \ ++ (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE) ++ ++ #define AC97_PCM_FORMATS \ ++ (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S18_3LE | \ ++ SNDRV_PCM_FORMAT_S20_3LE) ++ ++ /* AC97 with no VRA */ ++ { ++ .pcmfmt = AC97_PCM_FORMATS, ++ .pcmrate = SNDRV_PCM_RATE_48000, ++ } ++ ++ ++Example 8 ++--------- ++ ++CPU DAI that supports 8k - 48k @ 256FS and BCLK = MCLK / 4 in master mode. ++Slave mode (CPU DAI is FRAME master) supports 8k - 96k at any FS as long as ++BCLK = 64 * rate. (Intel XScale I2S controller). ++ ++ #define PXA_I2S_DAIFMT \ ++ (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF) ++ ++ #define PXA_I2S_DIR \ ++ (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE) ++ ++ #define PXA_I2S_RATES \ ++ (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ ++ SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ ++ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) ++ ++ /* priv is divider */ ++ static struct snd_soc_dai_mode pxa2xx_i2s_modes[] = { ++ /* pxa2xx I2S frame and clock master modes */ ++ { ++ .fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, ++ .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, ++ .pcmrate = SNDRV_PCM_RATE_8000, ++ .pcmdir = PXA_I2S_DIR, ++ .flags = SND_SOC_DAI_BFS_DIV, ++ .fs = 256, ++ .bfs = SND_SOC_FSBD(4), ++ .priv = 0x48, ++ }, ++ { ++ .fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, ++ .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, ++ .pcmrate = SNDRV_PCM_RATE_11025, ++ .pcmdir = PXA_I2S_DIR, ++ .flags = SND_SOC_DAI_BFS_DIV, ++ .fs = 256, ++ .bfs = SND_SOC_FSBD(4), ++ .priv = 0x34, ++ }, ++ { ++ .fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, ++ .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, ++ .pcmrate = SNDRV_PCM_RATE_16000, ++ .pcmdir = PXA_I2S_DIR, ++ .flags = SND_SOC_DAI_BFS_DIV, ++ .fs = 256, ++ .bfs = SND_SOC_FSBD(4), ++ .priv = 0x24, ++ }, ++ { ++ .fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, ++ .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, ++ .pcmrate = SNDRV_PCM_RATE_22050, ++ .pcmdir = PXA_I2S_DIR, ++ .flags = SND_SOC_DAI_BFS_DIV, ++ .fs = 256, ++ .bfs = SND_SOC_FSBD(4), ++ .priv = 0x1a, ++ }, ++ { ++ .fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, ++ .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, ++ .pcmrate = SNDRV_PCM_RATE_44100, ++ .pcmdir = PXA_I2S_DIR, ++ .flags = SND_SOC_DAI_BFS_DIV, ++ .fs = 256, ++ .bfs = SND_SOC_FSBD(4), ++ .priv = 0xd, ++ }, ++ { ++ .fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, ++ .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, ++ .pcmrate = SNDRV_PCM_RATE_48000, ++ .pcmdir = PXA_I2S_DIR, ++ .flags = SND_SOC_DAI_BFS_DIV, ++ .fs = 256, ++ .bfs = SND_SOC_FSBD(4), ++ .priv = 0xc, ++ }, ++ ++ /* pxa2xx I2S frame master and clock slave mode */ ++ { ++ .fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBM_CFS, ++ .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, ++ .pcmrate = PXA_I2S_RATES, ++ .pcmdir = PXA_I2S_DIR, ++ .fs = SND_SOC_FS_ALL, ++ .flags = SND_SOC_DAI_BFS_RATE, ++ .bfs = 64, ++ .priv = 0x48, ++ }, ++}; +Index: linux-2.6-pxa-new/Documentation/sound/alsa/soc/clocking.txt +=================================================================== +--- /dev/null ++++ linux-2.6-pxa-new/Documentation/sound/alsa/soc/clocking.txt +@@ -0,0 +1,314 @@ ++Audio Clocking ++============== ++ ++This text describes the audio clocking terms in ASoC and digital audio in ++general. Note: Audio clocking can be complex ! ++ ++ ++Master Clock ++------------ ++ ++Every audio subsystem is driven by a master clock (sometimes refered to as MCLK ++or SYSCLK). This audio master clock can be derived from a number of sources ++(e.g. crystal, PLL, CPU clock) and is responsible for producing the correct ++audio playback and capture sample rates. ++ ++Some master clocks (e.g. PLL's and CPU based clocks) are configuarble in that ++their speed can be altered by software (depending on the system use and to save ++power). Other master clocks are fixed at at set frequency (i.e. crystals). ++ ++ ++DAI Clocks ++---------- ++The Digital Audio Interface is usually driven by a Bit Clock (often referred to ++as BCLK). This clock is used to drive the digital audio data across the link ++between the codec and CPU. ++ ++The DAI also has a frame clock to signal the start of each audio frame. This ++clock is sometimes referred to as LRC (left right clock) or FRAME. This clock ++runs at exactly the sample rate (LRC = Rate). ++ ++Bit Clock can be generated as follows:- ++ ++BCLK = MCLK / x ++ ++ or ++ ++BCLK = LRC * x ++ ++ or ++ ++BCLK = LRC * Channels * Word Size ++ ++This relationship depends on the codec or SoC CPU in particular. ASoC can quite ++easily match BCLK generated by division (SND_SOC_DAI_BFS_DIV) with BCLK by ++multiplication (SND_SOC_DAI_BFS_RATE) or BCLK generated by ++Rate * Channels * Word size (RCW or SND_SOC_DAI_BFS_RCW). ++ ++ ++ASoC Clocking ++------------- ++ ++The ASoC core determines the clocking for each particular configuration at ++runtime. This is to allow for dynamic audio clocking wereby the audio clock is ++variable and depends on the system state or device usage scenario. i.e. a voice ++call requires slower clocks (and hence less power) than MP3 playback. ++ ++ASoC will call the config_sysclock() function for the target machine during the ++audio parameters configuration. The function is responsible for then clocking ++the machine audio subsytem and returning the audio clock speed to the core. ++This function should also call the codec and cpu DAI clock_config() functions ++to configure their respective internal clocking if required. ++ ++ ++ASoC Clocking Control Flow ++-------------------------- ++ ++The ASoC core will call the machine drivers config_sysclock() when most of the ++DAI capabilities are known. The machine driver is then responsible for calling ++the codec and/or CPU DAI drivers with the selected capabilities and the current ++MCLK. Note that the machine driver is also resonsible for setting the MCLK (and ++enabling it). ++ ++ (1) Match Codec and CPU DAI capabilities. At this point we have ++ matched the majority of the DAI fields and now need to make sure this ++ mode is currently clockable. ++ ++ (2) machine->config_sysclk() is now called with the matched DAI FS, sample ++ rate and BCLK master. This function then gets/sets the current audio ++ clock (depening on usage) and calls the codec and CPUI DAI drivers with ++ the FS, rate, BCLK master and MCLK. ++ ++ (3) Codec/CPU DAI config_sysclock(). This function checks that the FS, rate, ++ BCLK master and MCLK are acceptable for the codec or CPU DAI. It also ++ sets the DAI internal state to work with said clocks. ++ ++The config_sysclk() functions for CPU, codec and machine should return the MCLK ++on success and 0 on failure. ++ ++ ++Examples (b = BCLK, l = LRC) ++============================ ++ ++Example 1 ++--------- ++ ++Simple codec that only runs at 48k @ 256FS in master mode. ++ ++CPU only runs as slave DAI, however it generates a variable MCLK. ++ ++ -------- --------- ++ | | <----mclk--- | | ++ | Codec |b -----------> | CPU | ++ | |l -----------> | | ++ | | | | ++ -------- --------- ++ ++The codec driver has the following config_sysclock() ++ ++ static unsigned int config_sysclk(struct snd_soc_codec_dai *dai, ++ struct snd_soc_clock_info *info, unsigned int clk) ++ { ++ /* make sure clock is 256 * rate */ ++ if(info->rate << 8 == clk) { ++ dai->mclk = clk; ++ return clk; ++ } ++ ++ return 0; ++ } ++ ++The CPU I2S DAI driver has the following config_sysclk() ++ ++ static unsigned int config_sysclk(struct snd_soc_codec_dai *dai, ++ struct snd_soc_clock_info *info, unsigned int clk) ++ { ++ /* can we support this clk */ ++ if(set_audio_clk(clk) < 0) ++ return -EINVAL; ++ ++ dai->mclk = clk; ++ return dai->clk; ++ } ++ ++The machine driver config_sysclk() in this example is as follows:- ++ ++ unsigned int machine_config_sysclk(struct snd_soc_pcm_runtime *rtd, ++ struct snd_soc_clock_info *info) ++ { ++ int clk = info->rate * info->fs; ++ ++ /* check that CPU can deliver clock */ ++ if(rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info, clk) < 0) ++ return -EINVAL; ++ ++ /* can codec work with this clock */ ++ return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, clk); ++ } ++ ++ ++Example 2 ++--------- ++ ++Codec that can master at 8k and 48k at various FS (and hence supports a fixed ++set of input MCLK's) and can also be slave at various FS . ++ ++The CPU can master at 8k and 48k @256 FS and can be slave at any FS. ++ ++MCLK is a 12.288MHz crystal on this machine. ++ ++ -------- --------- ++ | | <---xtal---> | | ++ | Codec |b <----------> | CPU | ++ | |l <----------> | | ++ | | | | ++ -------- --------- ++ ++ ++The codec driver has the following config_sysclock() ++ ++ /* supported input clocks */ ++ const static int hifi_clks[] = {11289600, 12000000, 12288000, ++ 16934400, 18432000}; ++ ++ static unsigned int config_hsysclk(struct snd_soc_codec_dai *dai, ++ struct snd_soc_clock_info *info, unsigned int clk) ++ { ++ int i; ++ ++ /* is clk supported */ ++ for(i = 0; i < ARRAY_SIZE(hifi_clks); i++) { ++ if(clk == hifi_clks[i]) { ++ dai->mclk = clk; ++ return clk; ++ } ++ } ++ ++ /* this clk is not supported */ ++ return 0; ++ } ++ ++The CPU I2S DAI driver has the following config_sysclk() ++ ++ static unsigned int config_sysclk(struct snd_soc_codec_dai *dai, ++ struct snd_soc_clock_info *info, unsigned int clk) ++ { ++ /* are we master or slave */ ++ if (info->bclk_master & ++ (SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS)) { ++ ++ /* we can only master @ 256FS */ ++ if(info->rate << 8 == clk) { ++ dai->mclk = clk; ++ return dai->mclk; ++ } ++ } else { ++ /* slave we can run at any FS */ ++ dai->mclk = clk; ++ return dai->mclk; ++ } ++ ++ /* not supported */ ++ return dai->clk; ++ } ++ ++The machine driver config_sysclk() in this example is as follows:- ++ ++ unsigned int machine_config_sysclk(struct snd_soc_pcm_runtime *rtd, ++ struct snd_soc_clock_info *info) ++ { ++ int clk = 12288000; /* 12.288MHz */ ++ ++ /* who's driving the link */ ++ if (info->bclk_master & ++ (SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS)) { ++ /* codec master */ ++ ++ /* check that CPU can work with clock */ ++ if(rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info, clk) < 0) ++ return -EINVAL; ++ ++ /* can codec work with this clock */ ++ return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, clk); ++ } else { ++ /* cpu master */ ++ ++ /* check that codec can work with clock */ ++ if(rtd->codec_dai->config_sysclk(rtd->codec_dai, info, clk) < 0) ++ return -EINVAL; ++ ++ /* can CPU work with this clock */ ++ return rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info, clk); ++ } ++ } ++ ++ ++ ++Example 3 ++--------- ++ ++Codec that masters at 8k ... 48k @256 FS. Codec can also be slave and ++doesn't care about FS. The codec has an internal PLL and dividers to generate ++the necessary internal clocks (for 256FS). ++ ++CPU can only be slave and doesn't care about FS. ++ ++MCLK is a non controllable 13MHz clock from the CPU. ++ ++ ++ -------- --------- ++ | | <----mclk--- | | ++ | Codec |b <----------> | CPU | ++ | |l <----------> | | ++ | | | | ++ -------- --------- ++ ++The codec driver has the following config_sysclock() ++ ++ /* valid PCM clock dividers * 2 */ ++ static int pcm_divs[] = {2, 6, 11, 4, 8, 12, 16}; ++ ++ static unsigned int config_vsysclk(struct snd_soc_codec_dai *dai, ++ struct snd_soc_clock_info *info, unsigned int clk) ++ { ++ int i, j, best_clk = info->fs * info->rate; ++ ++ /* can we run at this clk without the PLL ? */ ++ for (i = 0; i < ARRAY_SIZE(pcm_divs); i++) { ++ if ((best_clk >> 1) * pcm_divs[i] == clk) { ++ dai->pll_in = 0; ++ dai->clk_div = pcm_divs[i]; ++ dai->mclk = best_clk; ++ return dai->mclk; ++ } ++ } ++ ++ /* now check for PLL support */ ++ for (i = 0; i < ARRAY_SIZE(pll_div); i++) { ++ if (pll_div[i].pll_in == clk) { ++ for (j = 0; j < ARRAY_SIZE(pcm_divs); j++) { ++ if (pll_div[i].pll_out == pcm_divs[j] * (best_clk >> 1)) { ++ dai->pll_in = clk; ++ dai->pll_out = pll_div[i].pll_out; ++ dai->clk_div = pcm_divs[j]; ++ dai->mclk = best_clk; ++ return dai->mclk; ++ } ++ } ++ } ++ } ++ ++ /* this clk is not supported */ ++ return 0; ++ } ++ ++ ++The CPU I2S DAI driver has the does not need a config_sysclk() as it can slave ++at any FS. ++ ++ unsigned int config_sysclk(struct snd_soc_pcm_runtime *rtd, ++ struct snd_soc_clock_info *info) ++ { ++ /* codec has pll that generates mclk from 13MHz xtal */ ++ return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, 13000000); ++ } +Index: linux-2.6-pxa-new/Documentation/sound/alsa/soc/codec.txt +=================================================================== +--- /dev/null ++++ linux-2.6-pxa-new/Documentation/sound/alsa/soc/codec.txt +@@ -0,0 +1,232 @@ ++ASoC Codec Driver ++================= ++ ++The codec driver is generic and hardware independent code that configures the ++codec to provide audio capture and playback. It should contain no code that is ++specific to the target platform or machine. All platform and machine specific ++code should be added to the platform and machine drivers respectively. ++ ++Each codec driver must provide the following features:- ++ ++ 1) Digital audio interface (DAI) description ++ 2) Digital audio interface configuration ++ 3) PCM's description ++ 4) Codec control IO - using I2C, 3 Wire(SPI) or both API's ++ 5) Mixers and audio controls ++ 6) Sysclk configuration ++ 7) Codec audio operations ++ ++Optionally, codec drivers can also provide:- ++ ++ 8) DAPM description. ++ 9) DAPM event handler. ++10) DAC Digital mute control. ++ ++It's probably best to use this guide in conjuction with the existing codec ++driver code in sound/soc/codecs/ ++ ++ASoC Codec driver breakdown ++=========================== ++ ++1 - Digital Audio Interface (DAI) description ++--------------------------------------------- ++The DAI is a digital audio data transfer link between the codec and host SoC ++CPU. It typically has data transfer capabilities in both directions ++(playback and capture) and can run at a variety of different speeds. ++Supported interfaces currently include AC97, I2S and generic PCM style links. ++Please read DAI.txt for implementation information. ++ ++ ++2 - Digital Audio Interface (DAI) configuration ++----------------------------------------------- ++DAI configuration is handled by the codec_pcm_prepare function and is ++responsible for configuring and starting the DAI on the codec. This can be ++called multiple times and is atomic. It can access the runtime parameters. ++ ++This usually consists of a large function with numerous switch statements to ++set up each configuration option. These options are set by the core at runtime. ++ ++ ++3 - Codec PCM's ++--------------- ++Each codec must have it's PCM's defined. This defines the number of channels, ++stream names, callbacks and codec name. It is also used to register the DAI ++with the ASoC core. The PCM structure also associates the DAI capabilities with ++the ALSA PCM. ++ ++e.g. ++ ++static struct snd_soc_pcm_codec wm8731_pcm_client = { ++ .name = "WM8731", ++ .playback = { ++ .stream_name = "Playback", ++ .channels_min = 1, ++ .channels_max = 2, ++ }, ++ .capture = { ++ .stream_name = "Capture", ++ .channels_min = 1, ++ .channels_max = 2, ++ }, ++ .config_sysclk = wm8731_config_sysclk, ++ .ops = { ++ .prepare = wm8731_pcm_prepare, ++ }, ++ .caps = { ++ .num_modes = ARRAY_SIZE(wm8731_hwfmt), ++ .modes = &wm8731_hwfmt[0], ++ }, ++}; ++ ++ ++4 - Codec control IO ++-------------------- ++The codec can ususally be controlled via an I2C or SPI style interface (AC97 ++combines control with data in the DAI). The codec drivers will have to provide ++functions to read and write the codec registers along with supplying a register ++cache:- ++ ++ /* IO control data and register cache */ ++ void *control_data; /* codec control (i2c/3wire) data */ ++ void *reg_cache; ++ ++Codec read/write should do any data formatting and call the hardware read write ++below to perform the IO. These functions are called by the core and alsa when ++performing DAPM or changing the mixer:- ++ ++ unsigned int (*read)(struct snd_soc_codec *, unsigned int); ++ int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); ++ ++Codec hardware IO functions - usually points to either the I2C, SPI or AC97 ++read/write:- ++ ++ hw_write_t hw_write; ++ hw_read_t hw_read; ++ ++ ++5 - Mixers and audio controls ++----------------------------- ++All the codec mixers and audio controls can be defined using the convenience ++macros defined in soc.h. ++ ++ #define SOC_SINGLE(xname, reg, shift, mask, invert) ++ ++Defines a single control as follows:- ++ ++ xname = Control name e.g. "Playback Volume" ++ reg = codec register ++ shift = control bit(s) offset in register ++ mask = control bit size(s) e.g. mask of 7 = 3 bits ++ invert = the control is inverted ++ ++Other macros include:- ++ ++ #define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) ++ ++A stereo control ++ ++ #define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert) ++ ++A stereo control spanning 2 registers ++ ++ #define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts) ++ ++Defines an single enumerated control as follows:- ++ ++ xreg = register ++ xshift = control bit(s) offset in register ++ xmask = control bit(s) size ++ xtexts = pointer to array of strings that describe each setting ++ ++ #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) ++ ++Defines a stereo enumerated control ++ ++ ++6 - System clock configuration. ++------------------------------- ++The system clock that drives the audio subsystem can change depending on sample ++rate and the system power state. i.e. ++ ++o Higher sample rates sometimes need a higher system clock. ++o Low system power states can sometimes limit the available clocks. ++ ++This function is a callback that the machine driver can call to set and ++determine if the clock and sample rate combination is supported by the codec at ++the present time (and system state). ++ ++NOTE: If the codec has a PLL then it has a lot more flexability wrt clock and ++sample rate combinations. ++ ++Your config_sysclock function should return the MCLK if it's a valid ++combination for your codec else 0; ++ ++Please read clocking.txt now. ++ ++ ++7 - Codec Audio Operations ++-------------------------- ++The codec driver also supports the following alsa operations:- ++ ++/* SoC audio ops */ ++struct snd_soc_ops { ++ int (*startup)(snd_pcm_substream_t *); ++ void (*shutdown)(snd_pcm_substream_t *); ++ int (*hw_params)(snd_pcm_substream_t *, snd_pcm_hw_params_t *); ++ int (*hw_free)(snd_pcm_substream_t *); ++ int (*prepare)(snd_pcm_substream_t *); ++}; ++ ++Please refer to the alsa driver PCM documentation for details. ++http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm ++ ++ ++8 - DAPM description. ++--------------------- ++The Dynamic Audio Power Management description describes the codec's power ++components, their relationships and registers to the ASoC core. Please read ++dapm.txt for details of building the description. ++ ++Please also see the examples in other codec drivers. ++ ++ ++9 - DAPM event handler ++---------------------- ++This function is a callback that handles codec domain PM calls and system ++domain PM calls (e.g. suspend and resume). It's used to put the codec to sleep ++when not in use. ++ ++Power states:- ++ ++ SNDRV_CTL_POWER_D0: /* full On */ ++ /* vref/mid, clk and osc on, active */ ++ ++ SNDRV_CTL_POWER_D1: /* partial On */ ++ SNDRV_CTL_POWER_D2: /* partial On */ ++ ++ SNDRV_CTL_POWER_D3hot: /* Off, with power */ ++ /* everything off except vref/vmid, inactive */ ++ ++ SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */ ++ ++ ++10 - Codec DAC digital mute control. ++------------------------------------ ++Most codecs have a digital mute before the DAC's that can be used to minimise ++any system noise. The mute stops any digital data from entering the DAC. ++ ++A callback can be created that is called by the core for each codec DAI when the ++mute is applied or freed. ++ ++i.e. ++ ++static int wm8974_mute(struct snd_soc_codec *codec, ++ struct snd_soc_codec_dai *dai, int mute) ++{ ++ u16 mute_reg = wm8974_read_reg_cache(codec, WM8974_DAC) & 0xffbf; ++ if(mute) ++ wm8974_write(codec, WM8974_DAC, mute_reg | 0x40); ++ else ++ wm8974_write(codec, WM8974_DAC, mute_reg); ++ return 0; ++} +Index: linux-2.6-pxa-new/Documentation/sound/alsa/soc/dapm.txt +=================================================================== +--- /dev/null ++++ linux-2.6-pxa-new/Documentation/sound/alsa/soc/dapm.txt +@@ -0,0 +1,297 @@ ++Dynamic Audio Power Management for Portable Devices ++=================================================== ++ ++1. Description ++============== ++ ++Dynamic Audio Power Management (DAPM) is designed to allow portable Linux devices ++to use the minimum amount of power within the audio subsystem at all times. It ++is independent of other kernel PM and as such, can easily co-exist with the ++other PM systems. ++ ++DAPM is also completely transparent to all user space applications as all power ++switching is done within the ASoC core. No code changes or recompiling are ++required for user space applications. DAPM makes power switching descisions based ++upon any audio stream (capture/playback) activity and audio mixer settings ++within the device. ++ ++DAPM spans the whole machine. It covers power control within the entire audio ++subsystem, this includes internal codec power blocks and machine level power ++systems. ++ ++There are 4 power domains within DAPM ++ ++ 1. Codec domain - VREF, VMID (core codec and audio power) ++ Usually controlled at codec probe/remove and suspend/resume, although ++ can be set at stream time if power is not needed for sidetone, etc. ++ ++ 2. Platform/Machine domain - physically connected inputs and outputs ++ Is platform/machine and user action specific, is configured by the ++ machine driver and responds to asynchronous events e.g when HP ++ are inserted ++ ++ 3. Path domain - audio susbsystem signal paths ++ Automatically set when mixer and mux settings are changed by the user. ++ e.g. alsamixer, amixer. ++ ++ 4. Stream domain - DAC's and ADC's. ++ Enabled and disabled when stream playback/capture is started and ++ stopped respectively. e.g. aplay, arecord. ++ ++All DAPM power switching descisons are made automatically by consulting an audio ++routing map of the whole machine. This map is specific to each machine and ++consists of the interconnections between every audio component (including ++internal codec components). All audio components that effect power are called ++widgets hereafter. ++ ++ ++2. DAPM Widgets ++=============== ++ ++Audio DAPM widgets fall into a number of types:- ++ ++ o Mixer - Mixes several analog signals into a single analog signal. ++ o Mux - An analog switch that outputs only 1 of it's inputs. ++ o PGA - A programmable gain amplifier or attenuation widget. ++ o ADC - Analog to Digital Converter ++ o DAC - Digital to Analog Converter ++ o Switch - An analog switch ++ o Input - A codec input pin ++ o Output - A codec output pin ++ o Headphone - Headphone (and optional Jack) ++ o Mic - Mic (and optional Jack) ++ o Line - Line Input/Output (and optional Jack) ++ o Speaker - Speaker ++ o Pre - Special PRE widget (exec before all others) ++ o Post - Special POST widget (exec after all others) ++ ++(Widgets are defined in include/sound/soc-dapm.h) ++ ++Widgets are usually added in the codec driver and the machine driver. There are ++convience macros defined in soc-dapm.h that can be used to quickly build a ++list of widgets of the codecs and machines DAPM widgets. ++ ++Most widgets have a name, register, shift and invert. Some widgets have extra ++parameters for stream name and kcontrols. ++ ++ ++2.1 Stream Domain Widgets ++------------------------- ++ ++Stream Widgets relate to the stream power domain and only consist of ADC's ++(analog to digital converters) and DAC's (digital to analog converters). ++ ++Stream widgets have the following format:- ++ ++SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert), ++ ++NOTE: the stream name must match the corresponding stream name in your codecs ++snd_soc_codec_dai. ++ ++e.g. stream widgets for HiFi playback and capture ++ ++SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1), ++SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1), ++ ++ ++2.2 Path Domain Widgets ++----------------------- ++ ++Path domain widgets have a ability to control or effect the audio signal or ++audio paths within the audio subsystem. They have the following form:- ++ ++SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls) ++ ++Any widget kcontrols can be set using the controls and num_controls members. ++ ++e.g. Mixer widget (the kcontrols are declared first) ++ ++/* Output Mixer */ ++static const snd_kcontrol_new_t wm8731_output_mixer_controls[] = { ++SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0), ++SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0), ++SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0), ++}; ++ ++SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls, ++ ARRAY_SIZE(wm8731_output_mixer_controls)), ++ ++ ++2.3 Platform/Machine domain Widgets ++----------------------------------- ++ ++Machine widgets are different from codec widgets in that they don't have a ++codec register bit associated with them. A machine widget is assigned to each ++machine audio component (non codec) that can be independently powered. e.g. ++ ++ o Speaker Amp ++ o Microphone Bias ++ o Jack connectors ++ ++A machine widget can have an optional call back. ++ ++e.g. Jack connector widget for an external Mic that enables Mic Bias ++when the Mic is inserted:- ++ ++static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event) ++{ ++ if(SND_SOC_DAPM_EVENT_ON(event)) ++ set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_MIC_BIAS); ++ else ++ reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_MIC_BIAS); ++ ++ return 0; ++} ++ ++SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias), ++ ++ ++2.4 Codec Domain ++---------------- ++ ++The Codec power domain has no widgets and is handled by the codecs DAPM event ++handler. This handler is called when the codec powerstate is changed wrt to any ++stream event or by kernel PM events. ++ ++ ++2.5 Virtual Widgets ++------------------- ++ ++Sometimes widgets exist in the codec or machine audio map that don't have any ++corresponding register bit for power control. In this case it's necessary to ++create a virtual widget - a widget with no control bits e.g. ++ ++SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0), ++ ++This can be used to merge to signal paths together in software. ++ ++After all the widgets have been defined, they can then be added to the DAPM ++subsystem individually with a call to snd_soc_dapm_new_control(). ++ ++ ++3. Codec Widget Interconnections ++================================ ++ ++Widgets are connected to each other within the codec and machine by audio ++paths (called interconnections). Each interconnection must be defined in order ++to create a map of all audio paths between widgets. ++This is easiest with a diagram of the codec (and schematic of the machine audio ++system), as it requires joining widgets together via their audio signal paths. ++ ++i.e. from the WM8731 codec's output mixer (wm8731.c) ++ ++The WM8731 output mixer has 3 inputs (sources) ++ ++ 1. Line Bypass Input ++ 2. DAC (HiFi playback) ++ 3. Mic Sidetone Input ++ ++Each input in this example has a kcontrol associated with it (defined in example ++above) and is connected to the output mixer via it's kcontrol name. We can now ++connect the destination widget (wrt audio signal) with it's source widgets. ++ ++ /* output mixer */ ++ {"Output Mixer", "Line Bypass Switch", "Line Input"}, ++ {"Output Mixer", "HiFi Playback Switch", "DAC"}, ++ {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"}, ++ ++So we have :- ++ ++ Destination Widget <=== Path Name <=== Source Widget ++ ++Or:- ++ ++ Sink, Path, Source ++ ++Or :- ++ ++ "Output Mixer" is connected to the "DAC" via the "HiFi Playback Switch". ++ ++When there is no path name connecting widgets (e.g. a direct connection) we ++pass NULL for the path name. ++ ++Interconnections are created with a call to:- ++ ++snd_soc_dapm_connect_input(codec, sink, path, source); ++ ++Finally, snd_soc_dapm_new_widgets(codec) must be called after all widgets and ++interconnections have been registered with the core. This causes the core to ++scan the codec and machine so that the internal DAPM state matches the ++physical state of the machine. ++ ++ ++3.1 Machine Widget Interconnections ++----------------------------------- ++Machine widget interconnections are created in the same way as codec ones and ++directly connect the codec pins to machine level widgets. ++ ++e.g. connects the speaker out codec pins to the internal speaker. ++ ++ /* ext speaker connected to codec pins LOUT2, ROUT2 */ ++ {"Ext Spk", NULL , "ROUT2"}, ++ {"Ext Spk", NULL , "LOUT2"}, ++ ++This allows the DAPM to power on and off pins that are connected (and in use) ++and pins that are NC respectively. ++ ++ ++4 Endpoint Widgets ++=================== ++An endpoint is a start or end point (widget) of an audio signal within the ++machine and includes the codec. e.g. ++ ++ o Headphone Jack ++ o Internal Speaker ++ o Internal Mic ++ o Mic Jack ++ o Codec Pins ++ ++When a codec pin is NC it can be marked as not used with a call to ++ ++snd_soc_dapm_set_endpoint(codec, "Widget Name", 0); ++ ++The last argument is 0 for inactive and 1 for active. This way the pin and its ++input widget will never be powered up and consume power. ++ ++This also applies to machine widgets. e.g. if a headphone is connected to a ++jack then the jack can be marked active. If the headphone is removed, then ++the headphone jack can be marked inactive. ++ ++ ++5 DAPM Widget Events ++==================== ++ ++Some widgets can register their interest with the DAPM core in PM events. ++e.g. A Speaker with an amplifier registers a widget so the amplifier can be ++powered only when the spk is in use. ++ ++/* turn speaker amplifier on/off depending on use */ ++static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event) ++{ ++ if (SND_SOC_DAPM_EVENT_ON(event)) ++ set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON); ++ else ++ reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON); ++ ++ return 0; ++} ++ ++/* corgi machine dapm widgets */ ++static const struct snd_soc_dapm_widget wm8731_dapm_widgets = ++ SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event); ++ ++Please see soc-dapm.h for all other widgets that support events. ++ ++ ++5.1 Event types ++--------------- ++ ++The following event types are supported by event widgets. ++ ++/* dapm event types */ ++#define SND_SOC_DAPM_PRE_PMU 0x1 /* before widget power up */ ++#define SND_SOC_DAPM_POST_PMU 0x2 /* after widget power up */ ++#define SND_SOC_DAPM_PRE_PMD 0x4 /* before widget power down */ ++#define SND_SOC_DAPM_POST_PMD 0x8 /* after widget power down */ ++#define SND_SOC_DAPM_PRE_REG 0x10 /* before audio path setup */ ++#define SND_SOC_DAPM_POST_REG 0x20 /* after audio path setup */ +Index: linux-2.6-pxa-new/Documentation/sound/alsa/soc/machine.txt +=================================================================== +--- /dev/null ++++ linux-2.6-pxa-new/Documentation/sound/alsa/soc/machine.txt +@@ -0,0 +1,114 @@ ++ASoC Machine Driver ++=================== ++ ++The ASoC machine (or board) driver is the code that glues together the platform ++and codec drivers. ++ ++The machine driver can contain codec and platform specific code. It registers ++the audio subsystem with the kernel as a platform device and is represented by ++the following struct:- ++ ++/* SoC machine */ ++struct snd_soc_machine { ++ char *name; ++ ++ int (*probe)(struct platform_device *pdev); ++ int (*remove)(struct platform_device *pdev); ++ ++ /* the pre and post PM functions are used to do any PM work before and ++ * after the codec and DAI's do any PM work. */ ++ int (*suspend_pre)(struct platform_device *pdev, pm_message_t state); ++ int (*suspend_post)(struct platform_device *pdev, pm_message_t state); ++ int (*resume_pre)(struct platform_device *pdev); ++ int (*resume_post)(struct platform_device *pdev); ++ ++ /* machine stream operations */ ++ struct snd_soc_ops *ops; ++ ++ /* CPU <--> Codec DAI links */ ++ struct snd_soc_dai_link *dai_link; ++ int num_links; ++}; ++ ++probe()/remove() ++---------------- ++probe/remove are optional. Do any machine specific probe here. ++ ++ ++suspend()/resume() ++------------------ ++The machine driver has pre and post versions of suspend and resume to t