Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/27572/?format=api
{ "id": 27572, "url": "http://patchwork.ozlabs.org/api/patches/27572/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20090523231307.17919.5277.stgit@terra/", "project": { "id": 2, "url": "http://patchwork.ozlabs.org/api/projects/2/?format=api", "name": "Linux PPC development", "link_name": "linuxppc-dev", "list_id": "linuxppc-dev.lists.ozlabs.org", "list_email": "linuxppc-dev@lists.ozlabs.org", "web_url": "https://github.com/linuxppc/wiki/wiki", "scm_url": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git", "webscm_url": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/", "list_archive_url": "https://lore.kernel.org/linuxppc-dev/", "list_archive_url_format": "https://lore.kernel.org/linuxppc-dev/{}/", "commit_url_format": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/commit/?id={}" }, "msgid": "<20090523231307.17919.5277.stgit@terra>", "list_archive_url": "https://lore.kernel.org/linuxppc-dev/20090523231307.17919.5277.stgit@terra/", "date": "2009-05-23T23:13:07", "name": "[V2,6/9] Codec for STAC9766 used on the Efika", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": true, "hash": "25a2473fa78757cf6976a2e6aa59fc4827660aaa", "submitter": { "id": 375, "url": "http://patchwork.ozlabs.org/api/people/375/?format=api", "name": "jonsmirl@gmail.com", "email": "jonsmirl@gmail.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20090523231307.17919.5277.stgit@terra/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/27572/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/27572/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org>", "X-Original-To": [ "patchwork-incoming@bilbo.ozlabs.org", "linuxppc-dev@ozlabs.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "patchwork-incoming@ozlabs.org", "linuxppc-dev@ozlabs.org" ], "Received": [ "from ozlabs.org (ozlabs.org [203.10.76.45])\n\t(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))\n\t(Client CN \"mx.ozlabs.org\",\n\tIssuer \"CA Cert Signing Authority\" (verified OK))\n\tby bilbo.ozlabs.org (Postfix) with ESMTPS id 76417B6F35\n\tfor <patchwork-incoming@bilbo.ozlabs.org>;\n\tSun, 24 May 2009 09:23:00 +1000 (EST)", "by ozlabs.org (Postfix)\n\tid 39963DF3DD; Sun, 24 May 2009 09:16:28 +1000 (EST)", "from ozlabs.org (localhost [127.0.0.1])\n\tby ozlabs.org (Postfix) with ESMTP id 354EDDF3DC\n\tfor <patchwork-incoming@ozlabs.org>;\n\tSun, 24 May 2009 09:16:28 +1000 (EST)", "from yx-out-2324.google.com (yx-out-2324.google.com [74.125.44.30])\n\tby ozlabs.org (Postfix) with ESMTP id 23146DE13C\n\tfor <linuxppc-dev@ozlabs.org>; Sun, 24 May 2009 09:13:08 +1000 (EST)", "by yx-out-2324.google.com with SMTP id 8so1216733yxb.39\n\tfor <linuxppc-dev@ozlabs.org>; Sat, 23 May 2009 16:13:08 -0700 (PDT)", "by 10.100.46.17 with SMTP id t17mr9860651ant.50.1243120388335;\n\tSat, 23 May 2009 16:13:08 -0700 (PDT)", "from terra (c-76-109-159-38.hsd1.fl.comcast.net [76.109.159.38])\n\tby mx.google.com with ESMTPS id 8sm11060952agd.37.2009.05.23.16.13.07\n\t(version=TLSv1/SSLv3 cipher=RC4-MD5);\n\tSat, 23 May 2009 16:13:08 -0700 (PDT)", "from localhost ([127.0.0.1] helo=[127.0.1.1])\n\tby terra with esmtp (Exim 4.69) (envelope-from <jonsmirl@gmail.com>)\n\tid 1M80Op-0004hi-Pm; Sat, 23 May 2009 19:13:07 -0400" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; \n\th=domainkey-signature:received:received:received:subject:to:from:date\n\t:message-id:in-reply-to:references:user-agent:mime-version\n\t:content-type:content-transfer-encoding;\n\tbh=hp7t6YG/lRP4eiXMtaA+6zh/Yln8yacQSw745D+gEUY=;\n\tb=fdARZ8FV4XGli5TEPzYfkCugQvMN62314h/M2llpc3rHyERwDBRNfMGr4CteKAjJwQ\n\t116AIPuPPPwqX5642cBbOa/iQ8Ounkpdgikw1Lpfw2nehUWJfu2cY0EOgCrrbyxQG7zp\n\tCP2olu8o3hYf3z2XuK2bsHFrl3Fumhh4N/ncg=", "DomainKey-Signature": "a=rsa-sha1; c=nofws; d=gmail.com; s=gamma;\n\th=subject:to:from:date:message-id:in-reply-to:references:user-agent\n\t:mime-version:content-type:content-transfer-encoding;\n\tb=kxWoYgrjtLRTWLkCo7M+G1NSM6fCAX6wZLIaJbPp//XAa8faHij8k1kersWysdo8tf\n\t4HfbKnh+kGQwObCLbiFHgNzC28VIq+0QVYVDzq34O5WVI0fhYgH0+YJcR3MeyQggfeMZ\n\tkFAtVm87TkZ/YV2ntNeSZ1HA8WwF2j4h3E4/k=", "Subject": "[PATCH V2 6/9] Codec for STAC9766 used on the Efika", "To": "grant.likely@secretlab.ca, linuxppc-dev@ozlabs.org,\n\talsa-devel@alsa-project.org, broonie@sirena.org.uk", "From": "Jon Smirl <jonsmirl@gmail.com>", "Date": "Sat, 23 May 2009 19:13:07 -0400", "Message-ID": "<20090523231307.17919.5277.stgit@terra>", "In-Reply-To": "<20090523231148.17919.46103.stgit@terra>", "References": "<20090523231148.17919.46103.stgit@terra>", "User-Agent": "StGit/0.14.3.366.gf979", "MIME-Version": "1.0", "X-BeenThere": "linuxppc-dev@ozlabs.org", "X-Mailman-Version": "2.1.11", "Precedence": "list", "List-Id": "Linux on PowerPC Developers Mail List <linuxppc-dev.ozlabs.org>", "List-Unsubscribe": "<https://ozlabs.org/mailman/options/linuxppc-dev>,\n\t<mailto:linuxppc-dev-request@ozlabs.org?subject=unsubscribe>", "List-Archive": "<http://ozlabs.org/pipermail/linuxppc-dev>", "List-Post": "<mailto:linuxppc-dev@ozlabs.org>", "List-Help": "<mailto:linuxppc-dev-request@ozlabs.org?subject=help>", "List-Subscribe": "<https://ozlabs.org/mailman/listinfo/linuxppc-dev>,\n\t<mailto:linuxppc-dev-request@ozlabs.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Sender": "linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org", "Errors-To": "linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org" }, "content": "AC97 codec for STAC9766 used on the Efika.\nDatasheet: http://www.idt.com/products/getDoc.cfm?docID=13134007\n\nSigned-off-by: Jon Smirl <jonsmirl@gmail.com>\n---\n 0 files changed, 0 insertions(+), 0 deletions(-)", "diff": "diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig\nindex 7f78b65..cb07d9b 100644\n--- a/sound/soc/codecs/Kconfig\n+++ b/sound/soc/codecs/Kconfig\n@@ -19,6 +19,7 @@ config SND_SOC_ALL_CODECS\n \tselect SND_SOC_CS4270 if I2C\n \tselect SND_SOC_PCM3008\n \tselect SND_SOC_SSM2602 if I2C\n+\tselect SND_SOC_STAC9766 if SND_SOC_AC97_BUS\n \tselect SND_SOC_TLV320AIC23 if I2C\n \tselect SND_SOC_TLV320AIC26 if SPI_MASTER\n \tselect SND_SOC_TLV320AIC3X if I2C\n@@ -93,6 +94,9 @@ config SND_SOC_PCM3008\n config SND_SOC_SSM2602\n \ttristate\n \n+config SND_SOC_STAC9766\n+\ttristate\n+\n config SND_SOC_TLV320AIC23\n \ttristate\n \ndiff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile\nindex 70c55fa..46c007c 100644\n--- a/sound/soc/codecs/Makefile\n+++ b/sound/soc/codecs/Makefile\n@@ -7,6 +7,7 @@ snd-soc-cs4270-objs := cs4270.o\n snd-soc-l3-objs := l3.o\n snd-soc-pcm3008-objs := pcm3008.o\n snd-soc-ssm2602-objs := ssm2602.o\n+snd-soc-stac9766-objs := stac9766.o\n snd-soc-tlv320aic23-objs := tlv320aic23.o\n snd-soc-tlv320aic26-objs := tlv320aic26.o\n snd-soc-tlv320aic3x-objs := tlv320aic3x.o\n@@ -42,6 +43,7 @@ obj-$(CONFIG_SND_SOC_CS4270)\t+= snd-soc-cs4270.o\n obj-$(CONFIG_SND_SOC_L3)\t+= snd-soc-l3.o\n obj-$(CONFIG_SND_SOC_PCM3008)\t+= snd-soc-pcm3008.o\n obj-$(CONFIG_SND_SOC_SSM2602)\t+= snd-soc-ssm2602.o\n+obj-$(CONFIG_SND_SOC_STAC9766)\t+= snd-soc-stac9766.o\n obj-$(CONFIG_SND_SOC_TLV320AIC23)\t+= snd-soc-tlv320aic23.o\n obj-$(CONFIG_SND_SOC_TLV320AIC26)\t+= snd-soc-tlv320aic26.o\n obj-$(CONFIG_SND_SOC_TLV320AIC3X)\t+= snd-soc-tlv320aic3x.o\ndiff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c\nnew file mode 100644\nindex 0000000..7740cd5\n--- /dev/null\n+++ b/sound/soc/codecs/stac9766.c\n@@ -0,0 +1,470 @@\n+/*\n+ * stac9766.c -- ALSA SoC STAC9766 codec support\n+ *\n+ * Copyright 2009 Jon Smirl, Digispeaker\n+ * Author: Jon Smirl <jonsmirl@gmail.com>\n+ *\n+ * This program is free software; you can redistribute it and/or modify it\n+ * under the terms of the GNU General Public License as published by the\n+ * Free Software Foundation; either version 2 of the License, or (at your\n+ * option) any later version.\n+ *\n+ * Features:-\n+ *\n+ * o Support for AC97 Codec, S/PDIF\n+ */\n+\n+#include <linux/init.h>\n+#include <linux/module.h>\n+#include <linux/device.h>\n+#include <sound/core.h>\n+#include <sound/pcm.h>\n+#include <sound/ac97_codec.h>\n+#include <sound/initval.h>\n+#include <sound/pcm_params.h>\n+#include <sound/soc.h>\n+#include <sound/tlv.h>\n+#include <sound/soc-of-simple.h>\n+\n+#include \"stac9766.h\"\n+\n+#define STAC9766_VERSION \"0.10\"\n+\n+/*\n+ * STAC9766 register cache\n+ */\n+static const u16 stac9766_reg[] = {\n+\t0x6A90, 0x8000, 0x8000, 0x8000, /* 6 */\n+\t0x0000, 0x0000, 0x8008, 0x8008, /* e */\n+\t0x8808, 0x8808, 0x8808, 0x8808, /* 16 */\n+\t0x8808, 0x0000, 0x8000, 0x0000, /* 1e */\n+\t0x0000, 0x0000, 0x0000, 0x000f, /* 26 */\n+\t0x0a05, 0x0400, 0xbb80, 0x0000, /* 2e */\n+\t0x0000, 0xbb80, 0x0000, 0x0000, /* 36 */\n+\t0x0000, 0x2000, 0x0000, 0x0100, /* 3e */\n+\t0x0000, 0x0000, 0x0080, 0x0000, /* 46 */\n+\t0x0000, 0x0000, 0x0003, 0xffff, /* 4e */\n+\t0x0000, 0x0000, 0x0000, 0x0000, /* 56 */\n+\t0x4000, 0x0000, 0x0000, 0x0000, /* 5e */\n+\t0x1201, 0xFFFF, 0xFFFF, 0x0000, /* 66 */\n+\t0x0000, 0x0000, 0x0000, 0x0000, /* 6e */\n+\t0x0000, 0x0000, 0x0000, 0x0006, /* 76 */\n+\t0x0000, 0x0000, 0x0000, 0x0000, /* 7e */\n+};\n+\n+static const char *stac9766_record_mux[] = {\"Mic\", \"CD\", \"Video\", \"AUX\", \"Line\", \"Stereo Mix\", \"Mono Mix\", \"Phone\"};\n+static const char *stac9766_mono_mux[] = {\"Mix\", \"Mic\"};\n+static const char *stac9766_mic_mux[] = {\"Mic1\", \"Mic2\"};\n+static const char *stac9766_SPDIF_mux[] = {\"PCM\", \"ADC Record\"};\n+static const char *stac9766_popbypass_mux[] = {\"Normal\", \"Bypass Mixer\"};\n+static const char *stac9766_record_all_mux[] = {\"All analog\", \"Analog plus DAC\"};\n+static const char *stac9766_boost1[] = {\"0dB\", \"10dB\"};\n+static const char *stac9766_boost2[] = {\"0dB\", \"20dB\"};\n+static const char *stac9766_stereo_mic[] = {\"Off\", \"On\"};\n+\n+static const struct soc_enum stac9766_record_enum =\n+\tSOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, stac9766_record_mux);\n+static const struct soc_enum stac9766_mono_enum =\n+\tSOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 9, 2, stac9766_mono_mux);\n+static const struct soc_enum stac9766_mic_enum =\n+\tSOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, stac9766_mic_mux);\n+static const struct soc_enum stac9766_SPDIF_enum =\n+\tSOC_ENUM_SINGLE(AC97_STAC_DA_CONTROL, 1, 2, stac9766_SPDIF_mux);\n+static const struct soc_enum stac9766_popbypass_enum =\n+\tSOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, stac9766_popbypass_mux);\n+static const struct soc_enum stac9766_record_all_enum =\n+\tSOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 12, 2, stac9766_record_all_mux);\n+static const struct soc_enum stac9766_boost1_enum =\n+\tSOC_ENUM_SINGLE(AC97_MIC, 6, 2, stac9766_boost1); /* 0/10dB */\n+static const struct soc_enum stac9766_boost2_enum =\n+\tSOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 2, 2, stac9766_boost2); /* 0/20dB */\n+static const struct soc_enum stac9766_stereo_mic_enum =\n+\tSOC_ENUM_SINGLE(AC97_STAC_STEREO_MIC, 2, 1, stac9766_stereo_mic);\n+\n+static const DECLARE_TLV_DB_LINEAR(master_tlv, -4600, 0);\n+static const DECLARE_TLV_DB_LINEAR(record_tlv, 0, 2250);\n+static const DECLARE_TLV_DB_LINEAR(beep_tlv, -4500, 0);\n+static const DECLARE_TLV_DB_LINEAR(mix_tlv, -3450, 1200);\n+\n+static const struct snd_kcontrol_new stac9766_snd_ac97_controls[] = {\n+\tSOC_DOUBLE_TLV(\"Speaker Volume\", AC97_MASTER, 8, 0, 31, 1, master_tlv),\n+\tSOC_SINGLE(\"Speaker Switch\", AC97_MASTER, 15, 1, 1),\n+\tSOC_DOUBLE_TLV(\"Headphone Volume\", AC97_HEADPHONE, 8, 0, 31, 1, master_tlv),\n+\tSOC_SINGLE(\"Headphone Switch\", AC97_HEADPHONE, 15, 1, 1),\n+\tSOC_SINGLE_TLV(\"Mono Out Volume\", AC97_MASTER_MONO, 0, 31, 1, master_tlv),\n+\tSOC_SINGLE(\"Mono Out Switch\", AC97_MASTER_MONO, 15, 1, 1),\n+\n+\tSOC_DOUBLE_TLV(\"Record Volume\", AC97_REC_GAIN, 8, 0, 15, 0, record_tlv),\n+\tSOC_SINGLE(\"Record Switch\", AC97_REC_GAIN, 15, 1, 1),\n+\n+\n+\tSOC_SINGLE_TLV(\"Beep Volume\", AC97_PC_BEEP, 1, 15, 1, beep_tlv),\n+\tSOC_SINGLE(\"Beep Switch\", AC97_PC_BEEP, 15, 1, 1),\n+\tSOC_SINGLE(\"Beep Frequency\", AC97_PC_BEEP, 5, 127, 1),\n+\tSOC_SINGLE_TLV(\"Phone Volume\", AC97_PHONE, 0, 31, 1, mix_tlv),\n+\tSOC_SINGLE(\"Phone Switch\", AC97_PHONE, 15, 1, 1),\n+\n+\tSOC_ENUM(\"Mic Boost1\", stac9766_boost1_enum),\n+\tSOC_ENUM(\"Mic Boost2\", stac9766_boost2_enum),\n+\tSOC_SINGLE_TLV(\"Mic Volume\", AC97_MIC, 0, 31, 1, mix_tlv),\n+\tSOC_SINGLE(\"Mic Switch\", AC97_MIC, 15, 1, 1),\n+\tSOC_ENUM(\"Stereo Mic\", stac9766_stereo_mic_enum),\n+\n+\tSOC_DOUBLE_TLV(\"Line Volume\", AC97_LINE, 8, 0, 31, 1, mix_tlv),\n+\tSOC_SINGLE(\"Line Switch\", AC97_LINE, 15, 1, 1),\n+\tSOC_DOUBLE_TLV(\"CD Volume\", AC97_CD, 8, 0, 31, 1, mix_tlv),\n+\tSOC_SINGLE(\"CD Switch\", AC97_CD, 15, 1, 1),\n+\tSOC_DOUBLE_TLV(\"AUX Volume\", AC97_AUX, 8, 0, 31, 1, mix_tlv),\n+\tSOC_SINGLE(\"AUX Switch\", AC97_AUX, 15, 1, 1),\n+\tSOC_DOUBLE_TLV(\"Video Volume\", AC97_VIDEO, 8, 0, 31, 1, mix_tlv),\n+\tSOC_SINGLE(\"Video Switch\", AC97_VIDEO, 15, 1, 1),\n+\n+\tSOC_DOUBLE_TLV(\"DAC Volume\", AC97_PCM, 8, 0, 31, 1, mix_tlv),\n+\tSOC_SINGLE(\"DAC Switch\", AC97_PCM, 15, 1, 1),\n+\tSOC_SINGLE(\"Loopback Test Switch\", AC97_GENERAL_PURPOSE, 7, 1, 0),\n+\tSOC_SINGLE(\"3D Volume\", AC97_3D_CONTROL, 3, 2, 1),\n+\tSOC_SINGLE(\"3D Switch\", AC97_GENERAL_PURPOSE, 13, 1, 0),\n+\n+\tSOC_ENUM(\"SPDIF Mux\", stac9766_SPDIF_enum),\n+\tSOC_ENUM(\"Mic1/2 Mux\", stac9766_mic_enum),\n+\tSOC_ENUM(\"Record All Mux\", stac9766_record_all_enum),\n+\tSOC_ENUM(\"Record Mux\", stac9766_record_enum),\n+\tSOC_ENUM(\"Mono Mux\", stac9766_mono_enum),\n+\tSOC_ENUM(\"Pop Bypass Mux\", stac9766_popbypass_enum),\n+};\n+\n+int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg,\n+ unsigned int val)\n+{\n+\tu16 *cache = codec->reg_cache;\n+\n+\tif (reg > AC97_STAC_PAGE0) {\n+\t\tstac9766_ac97_write(codec, AC97_INT_PAGING, 0);\n+\t\tsoc_ac97_ops.write(codec->ac97, reg, val);\n+\t\tstac9766_ac97_write(codec, AC97_INT_PAGING, 1);\n+\t\treturn 0;\n+\t}\n+\tif (reg / 2 > ARRAY_SIZE(stac9766_reg))\n+\t\treturn -EIO;\n+\n+\tsoc_ac97_ops.write(codec->ac97, reg, val);\n+\tcache[reg / 2] = val;\n+\treturn 0;\n+}\n+\n+unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, unsigned int reg)\n+{\n+\tu16 val = 0, *cache = codec->reg_cache;\n+\n+\tif (reg > AC97_STAC_PAGE0) {\n+\t\tstac9766_ac97_write(codec, AC97_INT_PAGING, 0);\n+\t\tval = soc_ac97_ops.read(codec->ac97, reg - AC97_STAC_PAGE0);\n+\t\tstac9766_ac97_write(codec, AC97_INT_PAGING, 1);\n+\t\treturn val;\n+\t}\n+\tif (reg / 2 > ARRAY_SIZE(stac9766_reg))\n+\t\treturn -EIO;\n+\n+\tif (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||\n+\t\treg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 ||\n+\t\treg == AC97_VENDOR_ID2) {\n+\n+\t\tval = soc_ac97_ops.read(codec->ac97, reg);\n+\t\treturn val;\n+\t}\n+\treturn cache[reg / 2];\n+}\n+\n+static int ac97_analog_prepare(struct snd_pcm_substream *substream,\n+ struct snd_soc_dai *dai)\n+{\n+\tstruct snd_soc_codec *codec = dai->codec;\n+\tstruct snd_pcm_runtime *runtime = substream->runtime;\n+\tunsigned short reg, vra;\n+\n+\tvra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS);\n+\n+\tvra |= 0x1; /* enable variable rate audio */\n+\n+\tstac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra);\n+\n+\tif (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)\n+\t\treg = AC97_PCM_FRONT_DAC_RATE;\n+\telse\n+\t\treg = AC97_PCM_LR_ADC_RATE;\n+\n+\treturn stac9766_ac97_write(codec, reg, runtime->rate);\n+}\n+\n+static int ac97_digital_prepare(struct snd_pcm_substream *substream,\n+ struct snd_soc_dai *dai)\n+{\n+\tstruct snd_soc_codec *codec = dai->codec;\n+\tstruct snd_pcm_runtime *runtime = substream->runtime;\n+\tunsigned short reg, vra;\n+\n+\tstac9766_ac97_write(codec, AC97_SPDIF, 0x2002);\n+\n+\tvra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS);\n+\tvra |= 0x5; /* Enable VRA and SPDIF out */\n+\n+\tstac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra);\n+\n+\treg = AC97_PCM_FRONT_DAC_RATE;\n+\n+\treturn stac9766_ac97_write(codec, reg, runtime->rate);\n+}\n+\n+static int ac97_digital_trigger(struct snd_pcm_substream *substream,\n+\t\t\t\t\t\t\t\tint cmd, struct snd_soc_dai *dai)\n+{\n+\tstruct snd_soc_codec *codec = dai->codec;\n+\tunsigned short vra;\n+\n+\tswitch (cmd) {\n+\tcase SNDRV_PCM_TRIGGER_STOP:\n+\t\tvra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS);\n+\t\tvra &= !0x04;\n+\t\tstac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra);\n+\t\tbreak;\n+\t}\n+\treturn 0;\n+}\n+\n+static int stac9766_set_bias_level(struct snd_soc_codec *codec,\n+ enum snd_soc_bias_level level)\n+{\n+\tswitch (level) {\n+\tcase SND_SOC_BIAS_ON: /* full On */\n+\tcase SND_SOC_BIAS_PREPARE: /* partial On */\n+\tcase SND_SOC_BIAS_STANDBY: /* Off, with power */\n+\t\tstac9766_ac97_write(codec, AC97_POWERDOWN, 0x0000);\n+\t\tbreak;\n+\tcase SND_SOC_BIAS_OFF: /* Off, without power */\n+\t\t/* disable everything including AC link */\n+\t\tstac9766_ac97_write(codec, AC97_POWERDOWN, 0xffff);\n+\t\tbreak;\n+\t}\n+\tcodec->bias_level = level;\n+\treturn 0;\n+}\n+\n+int stac9766_reset(struct snd_soc_codec *codec, int try_warm)\n+{\n+\tif (try_warm && soc_ac97_ops.warm_reset) {\n+\t\tsoc_ac97_ops.warm_reset(codec->ac97);\n+\t\tif (stac9766_ac97_read(codec, 0) == stac9766_reg[0])\n+\t\t\treturn 1;\n+\t}\n+\n+\tsoc_ac97_ops.reset(codec->ac97);\n+\tif (soc_ac97_ops.warm_reset)\n+\t\tsoc_ac97_ops.warm_reset(codec->ac97);\n+\tif (stac9766_ac97_read(codec, 0) != stac9766_reg[0])\n+\t\treturn -EIO;\n+\treturn 0;\n+}\n+\n+static int stac9766_codec_suspend(struct platform_device *pdev,\n+ pm_message_t state)\n+{\n+\tstruct snd_soc_device *socdev = platform_get_drvdata(pdev);\n+\tstruct snd_soc_codec *codec = socdev->card->codec;\n+\n+\tstac9766_set_bias_level(codec, SND_SOC_BIAS_OFF);\n+\treturn 0;\n+}\n+\n+static int stac9766_codec_resume(struct platform_device *pdev)\n+{\n+\tstruct snd_soc_device *socdev = platform_get_drvdata(pdev);\n+\tstruct snd_soc_codec *codec = socdev->card->codec;\n+\tu16 id, reset;\n+\n+\treset = 0;\n+\t/* give the codec an AC97 warm reset to start the link */\n+reset:\n+\tif (reset > 5) {\n+\t\tprintk(KERN_ERR \"stac9766 failed to resume\");\n+\t\treturn -EIO;\n+\t}\n+\tcodec->ac97->bus->ops->warm_reset(codec->ac97);\n+\tid = soc_ac97_ops.read(codec->ac97, AC97_VENDOR_ID2);\n+\tif (id != 0x4c13) {\n+\t\tstac9766_reset(codec, 0);\n+\t\treset++;\n+\t\tgoto reset;\n+\t}\n+\tstac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);\n+\n+\tif (codec->suspend_bias_level == SND_SOC_BIAS_ON)\n+\t\tstac9766_set_bias_level(codec, SND_SOC_BIAS_ON);\n+\n+\treturn 0;\n+}\n+\n+static struct snd_soc_dai_ops stac9766_dai_ops_analog =\n+{\n+\t.prepare = ac97_analog_prepare,\n+};\n+\n+static struct snd_soc_dai_ops stac9766_dai_ops_digital =\n+{\n+\t.prepare = ac97_digital_prepare,\n+\t.trigger = ac97_digital_trigger,\n+};\n+\n+struct snd_soc_dai stac9766_dai[] = {\n+{\n+\t.name = \"stac9766 analog\",\n+\t.id = 0,\n+\t.ac97_control = 1,\n+\n+\t/* stream cababilities */\n+\t.playback = {\n+\t\t.stream_name = \"stac9766 analog\",\n+\t\t.channels_min = 1,\n+\t\t.channels_max = 2,\n+\t\t.rates = SNDRV_PCM_RATE_8000_48000,\n+\t\t.formats = SND_SOC_STD_AC97_FMTS,\n+\t},\n+\t.capture = {\n+\t\t.stream_name = \"stac9766 analog\",\n+\t\t.channels_min = 1,\n+\t\t.channels_max = 2,\n+\t\t.rates = SNDRV_PCM_RATE_8000_48000,\n+\t\t.formats = SND_SOC_STD_AC97_FMTS,\n+\t},\n+\t/* alsa ops */\n+\t.ops = &stac9766_dai_ops_analog,\n+},\n+{\n+\t.name = \"stac9766 IEC958\",\n+\t.id = 1,\n+\t.ac97_control = 1,\n+\n+\t/* stream cababilities */\n+\t.playback = {\n+\t\t.stream_name = \"stac9766 IEC958\",\n+\t\t.channels_min = 1,\n+\t\t.channels_max = 2,\n+\t\t.rates = SNDRV_PCM_RATE_32000 | \\\n+\t\t\tSNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,\n+\t\t.formats = SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE,\n+\t},\n+\t/* alsa ops */\n+\t.ops = &stac9766_dai_ops_digital,\n+}};\n+EXPORT_SYMBOL_GPL(stac9766_dai);\n+\n+static int stac9766_codec_probe(struct platform_device *pdev)\n+{\n+\tstruct snd_soc_device *socdev = platform_get_drvdata(pdev);\n+\tstruct snd_soc_codec *codec;\n+\tint ret = 0;\n+\n+\tprintk(KERN_INFO \"STAC9766 SoC Audio Codec %s\\n\", STAC9766_VERSION);\n+\n+\tsocdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);\n+\tif (socdev->card->codec == NULL)\n+\t\treturn -ENOMEM;\n+\tcodec = socdev->card->codec;\n+\tmutex_init(&codec->mutex);\n+\n+\tcodec->reg_cache = kmemdup(stac9766_reg, sizeof(stac9766_reg), GFP_KERNEL);\n+\tif (codec->reg_cache == NULL) {\n+\t\tret = -ENOMEM;\n+\t\tgoto cache_err;\n+\t}\n+\tcodec->reg_cache_size = sizeof(stac9766_reg);\n+\tcodec->reg_cache_step = 2;\n+\n+\tcodec->name = \"STAC9766\";\n+\tcodec->owner = THIS_MODULE;\n+\tcodec->dai = stac9766_dai;\n+\tcodec->num_dai = ARRAY_SIZE(stac9766_dai);\n+\tcodec->write = stac9766_ac97_write;\n+\tcodec->read = stac9766_ac97_read;\n+\tcodec->set_bias_level = stac9766_set_bias_level;\n+\tINIT_LIST_HEAD(&codec->dapm_widgets);\n+\tINIT_LIST_HEAD(&codec->dapm_paths);\n+\n+\tret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);\n+\tif (ret < 0)\n+\t\tgoto codec_err;\n+\n+\t/* register pcms */\n+\tret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);\n+\tif (ret < 0)\n+\t\tgoto pcm_err;\n+\n+\t/* do a cold reset for the controller and then try\n+\t * a warm reset followed by an optional cold reset for codec */\n+\tstac9766_reset(codec, 0);\n+\tret = stac9766_reset(codec, 1);\n+\tif (ret < 0) {\n+\t\tprintk(KERN_ERR \"Failed to reset STAC9766: AC97 link error\\n\");\n+\t\tgoto reset_err;\n+\t}\n+\n+\tstac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);\n+\n+\tsnd_soc_add_controls(codec, stac9766_snd_ac97_controls, ARRAY_SIZE(\n+\t stac9766_snd_ac97_controls));\n+\n+\tret = snd_soc_init_card(socdev);\n+\tif (ret < 0)\n+\t\tgoto reset_err;\n+\treturn 0;\n+\n+reset_err:\n+\tsnd_soc_free_pcms(socdev);\n+pcm_err:\n+\tsnd_soc_free_ac97_codec(codec);\n+codec_err:\n+\tkfree(codec->private_data);\n+cache_err:\n+\tkfree(socdev->card->codec);\n+\tsocdev->card->codec = NULL;\n+\treturn ret;\n+}\n+\n+static int stac9766_codec_remove(struct platform_device *pdev)\n+{\n+\tstruct snd_soc_device *socdev = platform_get_drvdata(pdev);\n+\tstruct snd_soc_codec *codec = socdev->card->codec;\n+\n+\tif (codec == NULL)\n+\t\treturn 0;\n+\n+\tsnd_soc_free_pcms(socdev);\n+\tsnd_soc_free_ac97_codec(codec);\n+\tkfree(codec->reg_cache);\n+\tkfree(codec);\n+\treturn 0;\n+}\n+\n+struct snd_soc_codec_device soc_codec_dev_stac9766 =\n+{\n+\t.probe = stac9766_codec_probe,\n+\t.remove = stac9766_codec_remove,\n+\t.suspend = stac9766_codec_suspend,\n+\t.resume = stac9766_codec_resume,\n+};\n+EXPORT_SYMBOL_GPL(soc_codec_dev_stac9766);\n+\n+static int __init stac9766_modinit(void)\n+{\n+\treturn snd_soc_register_dais(stac9766_dai, ARRAY_SIZE(stac9766_dai));\n+}\n+module_init(stac9766_modinit);\n+\n+static void __exit stac9766_exit(void)\n+{\n+\tsnd_soc_unregister_dais(stac9766_dai, ARRAY_SIZE(stac9766_dai));\n+}\n+module_exit(stac9766_exit);\n+\n+MODULE_DESCRIPTION(\"ASoC stac9766 driver\");\n+MODULE_AUTHOR(\"Jon Smirl <jonsmirl@gmail.com>\");\n+MODULE_LICENSE(\"GPL\");\ndiff --git a/sound/soc/codecs/stac9766.h b/sound/soc/codecs/stac9766.h\nnew file mode 100644\nindex 0000000..65642eb\n--- /dev/null\n+++ b/sound/soc/codecs/stac9766.h\n@@ -0,0 +1,21 @@\n+/*\n+ * stac9766.h -- STAC9766 Soc Audio driver\n+ */\n+\n+#ifndef _STAC9766_H\n+#define _STAC9766_H\n+\n+#define AC97_STAC_PAGE0 0x1000\n+#define AC97_STAC_DA_CONTROL (AC97_STAC_PAGE0 | 0x6A)\n+#define AC97_STAC_ANALOG_SPECIAL (AC97_STAC_PAGE0 | 0x6E)\n+#define AC97_STAC_STEREO_MIC 0x78\n+\n+/* STAC9766 DAI ID's */\n+#define STAC9766_DAI_AC97_ANALOG\t\t0\n+#define STAC9766_DAI_AC97_DIGITAL\t\t1\n+\n+extern struct snd_soc_dai stac9766_dai[];\n+extern struct snd_soc_codec_device soc_codec_dev_stac9766;\n+\n+\n+#endif\n", "prefixes": [ "V2", "6/9" ] }