diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/firewire/isight.c | 1 | ||||
-rw-r--r-- | sound/pci/asihpi/asihpi.c | 1 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1_main.c | 8 | ||||
-rw-r--r-- | sound/pci/hda/hda_beep.h | 9 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 16 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 46 | ||||
-rw-r--r-- | sound/pci/lola/lola.c | 2 | ||||
-rw-r--r-- | sound/pci/rme9652/hdspm.c | 8 | ||||
-rw-r--r-- | sound/soc/codecs/Kconfig | 3 | ||||
-rw-r--r-- | sound/soc/codecs/twl4030.c | 22 | ||||
-rw-r--r-- | sound/soc/codecs/twl6040.c | 733 | ||||
-rw-r--r-- | sound/soc/codecs/twl6040.h | 119 | ||||
-rw-r--r-- | sound/soc/codecs/wm8991.c | 1 | ||||
-rw-r--r-- | sound/soc/imx/Kconfig | 7 | ||||
-rw-r--r-- | sound/soc/imx/imx-pcm-dma-mx2.c | 2 | ||||
-rw-r--r-- | sound/soc/imx/imx-ssi.c | 2 | ||||
-rw-r--r-- | sound/soc/omap/sdp3430.c | 2 | ||||
-rw-r--r-- | sound/soc/omap/sdp4430.c | 52 | ||||
-rw-r--r-- | sound/soc/omap/zoom2.c | 2 | ||||
-rw-r--r-- | sound/soc/pxa/pxa2xx-pcm.c | 4 | ||||
-rw-r--r-- | sound/soc/soc-cache.c | 3 | ||||
-rw-r--r-- | sound/usb/6fire/firmware.c | 1 | ||||
-rw-r--r-- | sound/usb/6fire/pcm.c | 4 |
23 files changed, 427 insertions, 621 deletions
diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c index 86ee16ca365e..440030818db7 100644 --- a/sound/firewire/isight.c +++ b/sound/firewire/isight.c @@ -209,6 +209,7 @@ static void isight_packet(struct fw_iso_context *context, u32 cycle, isight->packet_index = -1; return; } + fw_iso_context_queue_flush(isight->context); if (++index >= QUEUE_LENGTH) index = 0; diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 2ca6f4f85b41..e3569bdd3b64 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -27,7 +27,6 @@ #include "hpioctl.h" #include <linux/pci.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/jiffies.h> #include <linux/slab.h> diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 5e619a84da06..15f0161ce4a2 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1440,6 +1440,14 @@ static struct snd_emu_chip_details emu_chip_details[] = { .ca0102_chip = 1, .spk71 = 1, .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ + /* EMU0404 PCIe */ + {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40051102, + .driver = "Audigy2", .name = "E-mu 0404 PCIe [MAEM8984]", + .id = "EMU0404", + .emu10k2_chip = 1, + .ca0108_chip = 1, + .spk71 = 1, + .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 PCIe ver_03 */ /* Note that all E-mu cards require kernel 2.6 or newer. */ {.vendor = 0x1102, .device = 0x0008, .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]", diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index f1de1bac042c..55f0647458c7 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h @@ -50,7 +50,12 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable); int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); void snd_hda_detach_beep_device(struct hda_codec *codec); #else -#define snd_hda_attach_beep_device(...) 0 -#define snd_hda_detach_beep_device(...) +static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) +{ + return 0; +} +static inline void snd_hda_detach_beep_device(struct hda_codec *codec) +{ +} #endif #endif diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 43fcfbd32847..d21191dcfe88 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4883,7 +4883,6 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG), SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST), SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG), - SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST), SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V), SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG), SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG), @@ -12600,6 +12599,7 @@ static const struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = { */ enum { PINFIX_FSC_H270, + PINFIX_HP_Z200, }; static const struct alc_fixup alc262_fixups[] = { @@ -12612,9 +12612,17 @@ static const struct alc_fixup alc262_fixups[] = { { } } }, + [PINFIX_HP_Z200] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x16, 0x99130120 }, /* internal speaker */ + { } + } + }, }; static const struct snd_pci_quirk alc262_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200), SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270), {} }; @@ -12731,6 +12739,8 @@ static const struct snd_pci_quirk alc262_cfg_tbl[] = { ALC262_HP_BPC), SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1500, "HP z series", ALC262_HP_BPC), + SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", + ALC262_AUTO), SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1700, "HP xw series", ALC262_HP_BPC), SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL), @@ -13316,9 +13326,8 @@ static void alc268_acer_lc_setup(struct hda_codec *codec) struct alc_spec *spec = codec->spec; spec->autocfg.hp_pins[0] = 0x15; spec->autocfg.speaker_pins[0] = 0x14; - spec->automute_mixer_nid[0] = 0x0f; spec->automute = 1; - spec->automute_mode = ALC_AUTOMUTE_MIXER; + spec->automute_mode = ALC_AUTOMUTE_AMP; spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x12; @@ -13873,7 +13882,6 @@ static const struct snd_pci_quirk alc268_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST), SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO), SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA), - SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER), SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1), {} }; diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 605c99e1e520..f43bb0eaed8b 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -745,12 +745,23 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol, struct via_spec *spec = codec->spec; hda_nid_t nid = kcontrol->private_value; unsigned int pinsel = ucontrol->value.enumerated.item[0]; + unsigned int parm0, parm1; /* Get Independent Mode index of headphone pin widget */ spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel ? 1 : 0; - if (spec->codec_type == VT1718S) + if (spec->codec_type == VT1718S) { snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, pinsel ? 2 : 0); + /* Set correct mute switch for MW3 */ + parm0 = spec->hp_independent_mode ? + AMP_IN_UNMUTE(0) : AMP_IN_MUTE(0); + parm1 = spec->hp_independent_mode ? + AMP_IN_MUTE(1) : AMP_IN_UNMUTE(1); + snd_hda_codec_write(codec, 0x1b, 0, + AC_VERB_SET_AMP_GAIN_MUTE, parm0); + snd_hda_codec_write(codec, 0x1b, 0, + AC_VERB_SET_AMP_GAIN_MUTE, parm1); + } else snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, pinsel); @@ -832,10 +843,13 @@ static int via_hp_build(struct hda_codec *codec) knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; knew->private_value = nid; - knew = via_clone_control(spec, &via_hp_mixer[1]); - if (knew == NULL) - return -ENOMEM; - knew->subdevice = side_mute_channel(spec); + nid = side_mute_channel(spec); + if (nid) { + knew = via_clone_control(spec, &via_hp_mixer[1]); + if (knew == NULL) + return -ENOMEM; + knew->subdevice = nid; + } return 0; } @@ -4280,9 +4294,6 @@ static const struct hda_verb vt1718S_volume_init_verbs[] = { {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, - - /* Setup default input of Front HP to MW9 */ - {0x28, AC_VERB_SET_CONNECT_SEL, 0x1}, /* PW9 PW10 Output enable */ {0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN}, {0x2e, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN}, @@ -4291,10 +4302,10 @@ static const struct hda_verb vt1718S_volume_init_verbs[] = { /* Enable Boost Volume backdoor */ {0x1, 0xf88, 0x8}, /* MW0/1/2/3/4: un-mute index 0 (AOWx), mute index 1 (MW9) */ - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, @@ -4304,8 +4315,6 @@ static const struct hda_verb vt1718S_volume_init_verbs[] = { /* set MUX1 = 2 (AOW4), MUX2 = 1 (AOW3) */ {0x34, AC_VERB_SET_CONNECT_SEL, 0x2}, {0x35, AC_VERB_SET_CONNECT_SEL, 0x1}, - /* Unmute MW4's index 0 */ - {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, { } }; @@ -4453,6 +4462,19 @@ static int vt1718S_auto_create_multi_out_ctls(struct via_spec *spec, if (err < 0) return err; } else if (i == AUTO_SEQ_FRONT) { + /* add control to mixer index 0 */ + err = via_add_control(spec, VIA_CTL_WIDGET_VOL, + "Master Front Playback Volume", + HDA_COMPOSE_AMP_VAL(0x21, 3, 5, + HDA_INPUT)); + if (err < 0) + return err; + err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, + "Master Front Playback Switch", + HDA_COMPOSE_AMP_VAL(0x21, 3, 5, + HDA_INPUT)); + if (err < 0) + return err; /* Front */ sprintf(name, "%s Playback Volume", chname[i]); err = via_add_control( diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c index 34b24286d279..2692e5ae5f2d 100644 --- a/sound/pci/lola/lola.c +++ b/sound/pci/lola/lola.c @@ -445,7 +445,7 @@ static void lola_reset_setups(struct lola *chip) lola_setup_all_analog_gains(chip, PLAY, false); /* output, update */ } -static int lola_parse_tree(struct lola *chip) +static int __devinit lola_parse_tree(struct lola *chip) { unsigned int val; int nid, err; diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 949691a876d3..3f08afc0f0d3 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -521,6 +521,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) /* revisions >= 230 indicate AES32 card */ +#define HDSPM_MADI_OLD_REV 207 #define HDSPM_MADI_REV 210 #define HDSPM_RAYDAT_REV 211 #define HDSPM_AIO_REV 212 @@ -1143,7 +1144,7 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) /* if wordclock has synced freq and wordclock is valid */ if ((status2 & HDSPM_wcLock) != 0 && - (status & HDSPM_SelSyncRef0) == 0) { + (status2 & HDSPM_SelSyncRef0) == 0) { rate_bits = status2 & HDSPM_wcFreqMask; @@ -1639,12 +1640,14 @@ static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi) } } hmidi->pending = 0; + spin_unlock_irqrestore(&hmidi->lock, flags); + spin_lock_irqsave(&hmidi->hdspm->lock, flags); hmidi->hdspm->control_register |= hmidi->ie; hdspm_write(hmidi->hdspm, HDSPM_controlRegister, hmidi->hdspm->control_register); + spin_unlock_irqrestore(&hmidi->hdspm->lock, flags); - spin_unlock_irqrestore (&hmidi->lock, flags); return snd_hdspm_midi_output_write (hmidi); } @@ -6377,6 +6380,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, switch (hdspm->firmware_rev) { case HDSPM_MADI_REV: + case HDSPM_MADI_OLD_REV: hdspm->io_type = MADI; hdspm->card_name = "RME MADI"; hdspm->midiPorts = 3; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 98175a096df2..922f59f9b82d 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -236,10 +236,11 @@ config SND_SOC_TLV320DAC33 tristate config SND_SOC_TWL4030 - select TWL4030_CODEC + select MFD_TWL4030_AUDIO tristate config SND_SOC_TWL6040 + select TWL6040_CORE tristate config SND_SOC_UDA134X diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index bec788b12613..71674bec9604 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -36,7 +36,7 @@ #include <sound/tlv.h> /* Register descriptions are here */ -#include <linux/mfd/twl4030-codec.h> +#include <linux/mfd/twl4030-audio.h> /* Shadow register used by the audio driver */ #define TWL4030_REG_SW_SHADOW 0x4A @@ -251,9 +251,9 @@ static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) return; if (enable) - mode = twl4030_codec_enable_resource(TWL4030_CODEC_RES_POWER); + mode = twl4030_audio_enable_resource(TWL4030_AUDIO_RES_POWER); else - mode = twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER); + mode = twl4030_audio_disable_resource(TWL4030_AUDIO_RES_POWER); if (mode >= 0) { twl4030_write_reg_cache(codec, TWL4030_REG_CODEC_MODE, mode); @@ -297,7 +297,7 @@ static inline void twl4030_reset_registers(struct snd_soc_codec *codec) static void twl4030_init_chip(struct snd_soc_codec *codec) { - struct twl4030_codec_audio_data *pdata = dev_get_platdata(codec->dev); + struct twl4030_codec_data *pdata = dev_get_platdata(codec->dev); struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); u8 reg, byte; int i = 0; @@ -375,13 +375,13 @@ static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable) if (enable) { twl4030->apll_enabled++; if (twl4030->apll_enabled == 1) - status = twl4030_codec_enable_resource( - TWL4030_CODEC_RES_APLL); + status = twl4030_audio_enable_resource( + TWL4030_AUDIO_RES_APLL); } else { twl4030->apll_enabled--; if (!twl4030->apll_enabled) - status = twl4030_codec_disable_resource( - TWL4030_CODEC_RES_APLL); + status = twl4030_audio_disable_resource( + TWL4030_AUDIO_RES_APLL); } if (status >= 0) @@ -732,7 +732,7 @@ static int aif_event(struct snd_soc_dapm_widget *w, static void headset_ramp(struct snd_soc_codec *codec, int ramp) { - struct twl4030_codec_audio_data *pdata = codec->dev->platform_data; + struct twl4030_codec_data *pdata = codec->dev->platform_data; unsigned char hs_gain, hs_pop; struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); /* Base values for ramp delay calculation: 2^19 - 2^26 */ @@ -2260,7 +2260,7 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec) } snd_soc_codec_set_drvdata(codec, twl4030); /* Set the defaults, and power up the codec */ - twl4030->sysclk = twl4030_codec_get_mclk() / 1000; + twl4030->sysclk = twl4030_audio_get_mclk() / 1000; codec->dapm.idle_bias_off = 1; twl4030_init_chip(codec); @@ -2297,7 +2297,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { static int __devinit twl4030_codec_probe(struct platform_device *pdev) { - struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data; + struct twl4030_codec_data *pdata = pdev->dev.platform_data; if (!pdata) { dev_err(&pdev->dev, "platform_data is missing\n"); diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 4c336636d4f5..342c5a3c5270 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -24,11 +24,10 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/pm.h> -#include <linux/i2c.h> -#include <linux/gpio.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/i2c/twl.h> +#include <linux/mfd/twl6040.h> #include <sound/core.h> #include <sound/pcm.h> @@ -77,14 +76,19 @@ struct twl6040_jack_data { /* codec private data */ struct twl6040_data { - int audpwron; - int naudint; + int plug_irq; int codec_powered; int pll; int non_lp; + int pll_power_mode; + int hs_power_mode; + int hs_power_mode_locked; + unsigned int clk_in; unsigned int sysclk; - struct snd_pcm_hw_constraint_list *sysclk_constraints; - struct completion ready; + u16 hs_left_step; + u16 hs_right_step; + u16 hf_left_step; + u16 hf_right_step; struct twl6040_jack_data hs_jack; struct snd_soc_codec *codec; struct workqueue_struct *workqueue; @@ -206,6 +210,32 @@ static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = { TWL6040_REG_DLB, }; +/* set of rates for each pll: low-power and high-performance */ +static unsigned int lp_rates[] = { + 8000, + 11250, + 16000, + 22500, + 32000, + 44100, + 48000, + 88200, + 96000, +}; + +static unsigned int hp_rates[] = { + 8000, + 16000, + 32000, + 48000, + 96000, +}; + +static struct snd_pcm_hw_constraint_list sysclk_constraints[] = { + { .count = ARRAY_SIZE(lp_rates), .list = lp_rates, }, + { .count = ARRAY_SIZE(hp_rates), .list = hp_rates, }, +}; + /* * read twl6040 register cache */ @@ -239,12 +269,13 @@ static inline void twl6040_write_reg_cache(struct snd_soc_codec *codec, static int twl6040_read_reg_volatile(struct snd_soc_codec *codec, unsigned int reg) { + struct twl6040 *twl6040 = codec->control_data; u8 value; if (reg >= TWL6040_CACHEREGNUM) return -EIO; - twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &value, reg); + value = twl6040_reg_read(twl6040, reg); twl6040_write_reg_cache(codec, reg, value); return value; @@ -256,11 +287,13 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec, static int twl6040_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { + struct twl6040 *twl6040 = codec->control_data; + if (reg >= TWL6040_CACHEREGNUM) return -EIO; twl6040_write_reg_cache(codec, reg, value); - return twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, value, reg); + return twl6040_reg_write(twl6040, reg, value); } static void twl6040_init_vio_regs(struct snd_soc_codec *codec) @@ -268,15 +301,21 @@ static void twl6040_init_vio_regs(struct snd_soc_codec *codec) u8 *cache = codec->reg_cache; int reg, i; - /* allow registers to be accessed by i2c */ - twl6040_write(codec, TWL6040_REG_ACCCTL, cache[TWL6040_REG_ACCCTL]); - for (i = 0; i < TWL6040_VIOREGNUM; i++) { reg = twl6040_vio_reg[i]; - /* skip read-only registers (ASICID, ASICREV, STATUS) */ + /* + * skip read-only registers (ASICID, ASICREV, STATUS) + * and registers shared among MFD children + */ switch (reg) { case TWL6040_REG_ASICID: case TWL6040_REG_ASICREV: + case TWL6040_REG_INTID: + case TWL6040_REG_INTMR: + case TWL6040_REG_NCPCTL: + case TWL6040_REG_LDOCTL: + case TWL6040_REG_GPOCTL: + case TWL6040_REG_ACCCTL: case TWL6040_REG_STATUS: continue; default: @@ -293,6 +332,20 @@ static void twl6040_init_vdd_regs(struct snd_soc_codec *codec) for (i = 0; i < TWL6040_VDDREGNUM; i++) { reg = twl6040_vdd_reg[i]; + /* skip vibra and PLL registers */ + switch (reg) { + case TWL6040_REG_VIBCTLL: + case TWL6040_REG_VIBDATL: + case TWL6040_REG_VIBCTLR: + case TWL6040_REG_VIBDATR: + case TWL6040_REG_HPPLLCTL: + case TWL6040_REG_LPPLLCTL: + case TWL6040_REG_LPPLLDIV: + continue; + default: + break; + } + twl6040_write(codec, reg, cache[reg]); } } @@ -317,7 +370,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec, if (headset->ramp == TWL6040_RAMP_UP) { /* ramp step up */ if (val < headset->left_vol) { - val += left_step; + if (val + left_step > headset->left_vol) + val = headset->left_vol; + else + val += left_step; + reg &= ~TWL6040_HSL_VOL_MASK; twl6040_write(codec, TWL6040_REG_HSGAIN, (reg | (~val & TWL6040_HSL_VOL_MASK))); @@ -327,7 +384,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec, } else if (headset->ramp == TWL6040_RAMP_DOWN) { /* ramp step down */ if (val > 0x0) { - val -= left_step; + if ((int)val - (int)left_step < 0) + val = 0; + else + val -= left_step; + reg &= ~TWL6040_HSL_VOL_MASK; twl6040_write(codec, TWL6040_REG_HSGAIN, reg | (~val & TWL6040_HSL_VOL_MASK)); @@ -344,7 +405,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec, if (headset->ramp == TWL6040_RAMP_UP) { /* ramp step up */ if (val < headset->right_vol) { - val += right_step; + if (val + right_step > headset->right_vol) + val = headset->right_vol; + else + val += right_step; + reg &= ~TWL6040_HSR_VOL_MASK; twl6040_write(codec, TWL6040_REG_HSGAIN, (reg | (~val << TWL6040_HSR_VOL_SHIFT))); @@ -354,7 +419,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec, } else if (headset->ramp == TWL6040_RAMP_DOWN) { /* ramp step down */ if (val > 0x0) { - val -= right_step; + if ((int)val - (int)right_step < 0) + val = 0; + else + val -= right_step; + reg &= ~TWL6040_HSR_VOL_MASK; twl6040_write(codec, TWL6040_REG_HSGAIN, reg | (~val << TWL6040_HSR_VOL_SHIFT)); @@ -385,7 +454,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec, if (handsfree->ramp == TWL6040_RAMP_UP) { /* ramp step up */ if (val < handsfree->left_vol) { - val += left_step; + if (val + left_step > handsfree->left_vol) + val = handsfree->left_vol; + else + val += left_step; + reg &= ~TWL6040_HF_VOL_MASK; twl6040_write(codec, TWL6040_REG_HFLGAIN, reg | (0x1D - val)); @@ -395,7 +468,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec, } else if (handsfree->ramp == TWL6040_RAMP_DOWN) { /* ramp step down */ if (val > 0) { - val -= left_step; + if ((int)val - (int)left_step < 0) + val = 0; + else + val -= left_step; + reg &= ~TWL6040_HF_VOL_MASK; twl6040_write(codec, TWL6040_REG_HFLGAIN, reg | (0x1D - val)); @@ -412,7 +489,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec, if (handsfree->ramp == TWL6040_RAMP_UP) { /* ramp step up */ if (val < handsfree->right_vol) { - val += right_step; + if (val + right_step > handsfree->right_vol) + val = handsfree->right_vol; + else + val += right_step; + reg &= ~TWL6040_HF_VOL_MASK; twl6040_write(codec, TWL6040_REG_HFRGAIN, reg | (0x1D - val)); @@ -422,7 +503,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec, } else if (handsfree->ramp == TWL6040_RAMP_DOWN) { /* ramp step down */ if (val > 0) { - val -= right_step; + if ((int)val - (int)right_step < 0) + val = 0; + else + val -= right_step; + reg &= ~TWL6040_HF_VOL_MASK; twl6040_write(codec, TWL6040_REG_HFRGAIN, reg | (0x1D - val)); @@ -451,11 +536,9 @@ static void twl6040_pga_hs_work(struct work_struct *work) /* HS PGA volumes have 4 bits of resolution to ramp */ for (i = 0; i <= 16; i++) { - headset_complete = 1; - if (headset->ramp != TWL6040_RAMP_NONE) - headset_complete = twl6040_hs_ramp_step(codec, - headset->left_step, - headset->right_step); + headset_complete = twl6040_hs_ramp_step(codec, + headset->left_step, + headset->right_step); /* ramp finished ? */ if (headset_complete) @@ -496,11 +579,9 @@ static void twl6040_pga_hf_work(struct work_struct *work) /* HF PGA volumes have 5 bits of resolution to ramp */ for (i = 0; i <= 32; i++) { - handsfree_complete = 1; - if (handsfree->ramp != TWL6040_RAMP_NONE) - handsfree_complete = twl6040_hf_ramp_step(codec, - handsfree->left_step, - handsfree->right_step); + handsfree_complete = twl6040_hf_ramp_step(codec, + handsfree->left_step, + handsfree->right_step); /* ramp finished ? */ if (handsfree_complete) @@ -541,12 +622,16 @@ static int pga_event(struct snd_soc_dapm_widget *w, out = &priv->headset; work = &priv->hs_delayed_work; queue = priv->hs_workqueue; + out->left_step = priv->hs_left_step; + out->right_step = priv->hs_right_step; out->step_delay = 5; /* 5 ms between volume ramp steps */ break; case 4: out = &priv->handsfree; work = &priv->hf_delayed_work; queue = priv->hf_workqueue; + out->left_step = priv->hf_left_step; + out->right_step = priv->hf_right_step; out->step_delay = 5; /* 5 ms between volume ramp steps */ if (SND_SOC_DAPM_EVENT_ON(event)) priv->non_lp++; @@ -579,8 +664,6 @@ static int pga_event(struct snd_soc_dapm_widget *w, if (!delayed_work_pending(work)) { /* use volume ramp for power-down */ - out->left_step = 1; - out->right_step = 1; out->ramp = TWL6040_RAMP_DOWN; INIT_COMPLETION(out->ramp_done); @@ -596,88 +679,6 @@ static int pga_event(struct snd_soc_dapm_widget *w, return 0; } -/* twl6040 codec manual power-up sequence */ -static void twl6040_power_up(struct snd_soc_codec *codec) -{ - u8 ncpctl, ldoctl, lppllctl, accctl; - - ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL); - ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL); - lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL); - accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL); - - /* enable reference system */ - ldoctl |= TWL6040_REFENA; - twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl); - msleep(10); - /* enable internal oscillator */ - ldoctl |= TWL6040_OSCENA; - twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl); - udelay(10); - /* enable high-side ldo */ - ldoctl |= TWL6040_HSLDOENA; - twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl); - udelay(244); - /* enable negative charge pump */ - ncpctl |= TWL6040_NCPENA | TWL6040_NCPOPEN; - twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl); - udelay(488); - /* enable low-side ldo */ - ldoctl |= TWL6040_LSLDOENA; - twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl); - udelay(244); - /* enable low-power pll */ - lppllctl |= TWL6040_LPLLENA; - twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl); - /* reset state machine */ - accctl |= TWL6040_RESETSPLIT; - twl6040_write(codec, TWL6040_REG_ACCCTL, accctl); - mdelay(5); - accctl &= ~TWL6040_RESETSPLIT; - twl6040_write(codec, TWL6040_REG_ACCCTL, accctl); - /* disable internal oscillator */ - ldoctl &= ~TWL6040_OSCENA; - twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl); -} - -/* twl6040 codec manual power-down sequence */ -static void twl6040_power_down(struct snd_soc_codec *codec) -{ - u8 ncpctl, ldoctl, lppllctl, accctl; - - ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL); - ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL); - lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL); - accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL); - - /* enable internal oscillator */ - ldoctl |= TWL6040_OSCENA; - twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl); - udelay(10); - /* disable low-power pll */ - lppllctl &= ~TWL6040_LPLLENA; - twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl); - /* disable low-side ldo */ - ldoctl &= ~TWL6040_LSLDOENA; - twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl); - udelay(244); - /* disable negative charge pump */ - ncpctl &= ~(TWL6040_NCPENA | TWL6040_NCPOPEN); - twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl); - udelay(488); - /* disable high-side ldo */ - ldoctl &= ~TWL6040_HSLDOENA; - twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl); - udelay(244); - /* disable internal oscillator */ - ldoctl &= ~TWL6040_OSCENA; - twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl); - /* disable reference system */ - ldoctl &= ~TWL6040_REFENA; - twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl); - msleep(10); -} - /* set headset dac and driver power mode */ static int headset_power_mode(struct snd_soc_codec *codec, int high_perf) { @@ -713,15 +714,26 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = w->codec; struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); + int ret = 0; - if (SND_SOC_DAPM_EVENT_ON(event)) + if (SND_SOC_DAPM_EVENT_ON(event)) { priv->non_lp++; - else + if (!strcmp(w->name, "Earphone Driver")) { + /* Earphone doesn't support low power mode */ + priv->hs_power_mode_locked = 1; + ret = headset_power_mode(codec, 1); + } + } else { priv->non_lp--; + if (!strcmp(w->name, "Earphone Driver")) { + priv->hs_power_mode_locked = 0; + ret = headset_power_mode(codec, priv->hs_power_mode); + } + } msleep(1); - return 0; + return ret; } static void twl6040_hs_jack_report(struct snd_soc_codec *codec, @@ -766,33 +778,19 @@ static void twl6040_accessory_work(struct work_struct *work) } /* audio interrupt handler */ -static irqreturn_t twl6040_naudint_handler(int irq, void *data) +static irqreturn_t twl6040_audio_handler(int irq, void *data) { struct snd_soc_codec *codec = data; + struct twl6040 *twl6040 = codec->control_data; struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); u8 intid; - twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid, TWL6040_REG_INTID); - - if (intid & TWL6040_THINT) - dev_alert(codec->dev, "die temp over-limit detection\n"); + intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID); if ((intid & TWL6040_PLUGINT) || (intid & TWL6040_UNPLUGINT)) queue_delayed_work(priv->workqueue, &priv->delayed_work, msecs_to_jiffies(200)); - if (intid & TWL6040_HOOKINT) - dev_info(codec->dev, "hook detection\n"); - - if (intid & TWL6040_HFINT) - dev_alert(codec->dev, "hf drivers over current detection\n"); - - if (intid & TWL6040_VIBINT) - dev_alert(codec->dev, "vib drivers over current detection\n"); - - if (intid & TWL6040_READYINT) - complete(&priv->ready); - return IRQ_HANDLED; } @@ -1040,6 +1038,73 @@ static const struct snd_kcontrol_new hfr_mux_controls = static const struct snd_kcontrol_new ep_driver_switch_controls = SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0); +/* Headset power mode */ +static const char *twl6040_power_mode_texts[] = { + "Low-Power", "High-Perfomance", +}; + +static const struct soc_enum twl6040_power_mode_enum = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl6040_power_mode_texts), + twl6040_power_mode_texts); + +static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.enumerated.item[0] = priv->hs_power_mode; + + return 0; +} + +static int twl6040_headset_power_put_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); + int high_perf = ucontrol->value.enumerated.item[0]; + int ret = 0; + + if (!priv->hs_power_mode_locked) + ret = headset_power_mode(codec, high_perf); + + if (!ret) + priv->hs_power_mode = high_perf; + + return ret; +} + +static int twl6040_pll_get_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.enumerated.item[0] = priv->pll_power_mode; + + return 0; +} + +static int twl6040_pll_put_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); + + priv->pll_power_mode = ucontrol->value.enumerated.item[0]; + + return 0; +} + +int twl6040_get_clk_id(struct snd_soc_codec *codec) +{ + struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); + + return priv->pll_power_mode; +} +EXPORT_SYMBOL_GPL(twl6040_get_clk_id); + static const struct snd_kcontrol_new twl6040_snd_controls[] = { /* Capture gains */ SOC_DOUBLE_TLV("Capture Preamplifier Volume", @@ -1058,6 +1123,13 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = { TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv), SOC_SINGLE_TLV("Earphone Playback Volume", TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv), + + SOC_ENUM_EXT("Headset Power Mode", twl6040_power_mode_enum, + twl6040_headset_power_get_enum, + twl6040_headset_power_put_enum), + + SOC_ENUM_EXT("PLL Selection", twl6040_power_mode_enum, + twl6040_pll_get_enum, twl6040_pll_put_enum), }; static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { @@ -1231,36 +1303,11 @@ static int twl6040_add_widgets(struct snd_soc_codec *codec) return 0; } -static int twl6040_power_up_completion(struct snd_soc_codec *codec, - int naudint) -{ - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - int time_left; - u8 intid; - - time_left = wait_for_completion_timeout(&priv->ready, - msecs_to_jiffies(144)); - - if (!time_left) { - twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid, - TWL6040_REG_INTID); - if (!(intid & TWL6040_READYINT)) { - dev_err(codec->dev, "timeout waiting for READYINT\n"); - return -ETIMEDOUT; - } - } - - priv->codec_powered = 1; - - return 0; -} - static int twl6040_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct twl6040 *twl6040 = codec->control_data; struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - int audpwron = priv->audpwron; - int naudint = priv->naudint; int ret; switch (level) { @@ -1272,58 +1319,23 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec, if (priv->codec_powered) break; - if (gpio_is_valid(audpwron)) { - /* use AUDPWRON line */ - gpio_set_value(audpwron, 1); + ret = twl6040_power(twl6040, 1); + if (ret) + return ret; - /* wait for power-up completion */ - ret = twl6040_power_up_completion(codec, naudint); - if (ret) - return ret; - - /* sync registers updated during power-up sequence */ - twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL); - twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL); - twl6040_read_reg_volatile(codec, TWL6040_REG_LPPLLCTL); - } else { - /* use manual power-up sequence */ - twl6040_power_up(codec); - priv->codec_powered = 1; - } + priv->codec_powered = 1; /* initialize vdd/vss registers with reg_cache */ twl6040_init_vdd_regs(codec); /* Set external boost GPO */ twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02); - - /* Set initial minimal gain values */ - twl6040_write(codec, TWL6040_REG_HSGAIN, 0xFF); - twl6040_write(codec, TWL6040_REG_EARCTL, 0x1E); - twl6040_write(codec, TWL6040_REG_HFLGAIN, 0x1D); - twl6040_write(codec, TWL6040_REG_HFRGAIN, 0x1D); break; case SND_SOC_BIAS_OFF: if (!priv->codec_powered) break; - if (gpio_is_valid(audpwron)) { - /* use AUDPWRON line */ - gpio_set_value(audpwron, 0); - - /* power-down sequence latency */ - udelay(500); - - /* sync registers updated during power-down sequence */ - twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL); - twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL); - twl6040_write_reg_cache(codec, TWL6040_REG_LPPLLCTL, - 0x00); - } else { - /* use manual power-down sequence */ - twl6040_power_down(codec); - } - + twl6040_power(twl6040, 0); priv->codec_powered = 0; break; } @@ -1333,27 +1345,6 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec, return 0; } -/* set of rates for each pll: low-power and high-performance */ - -static unsigned int lp_rates[] = { - 88200, - 96000, -}; - -static struct snd_pcm_hw_constraint_list lp_constraints = { - .count = ARRAY_SIZE(lp_rates), - .list = lp_rates, -}; - -static unsigned int hp_rates[] = { - 96000, -}; - -static struct snd_pcm_hw_constraint_list hp_constraints = { - .count = ARRAY_SIZE(hp_rates), - .list = hp_rates, -}; - static int twl6040_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -1363,7 +1354,7 @@ static int twl6040_startup(struct snd_pcm_substream *substream, snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - priv->sysclk_constraints); + &sysclk_constraints[priv->pll_power_mode]); return 0; } @@ -1375,22 +1366,27 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - u8 lppllctl; int rate; - /* nothing to do for high-perf pll, it supports only 48 kHz */ - if (priv->pll == TWL6040_HPPLL_ID) - return 0; - - lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL); - rate = params_rate(params); switch (rate) { case 11250: case 22500: case 44100: case 88200: - lppllctl |= TWL6040_LPLLFIN; + /* These rates are not supported when HPPLL is in use */ + if (unlikely(priv->pll == TWL6040_SYSCLK_SEL_HPPLL)) { + dev_err(codec->dev, "HPPLL does not support rate %d\n", + rate); + return -EINVAL; + } + /* Capture is not supported with 17.64MHz sysclk */ + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + dev_err(codec->dev, + "capture mode is not supported at %dHz\n", + rate); + return -EINVAL; + } priv->sysclk = 17640000; break; case 8000: @@ -1398,7 +1394,6 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream, case 32000: case 48000: case 96000: - lppllctl &= ~TWL6040_LPLLFIN; priv->sysclk = 19200000; break; default: @@ -1406,8 +1401,6 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl); - return 0; } @@ -1416,7 +1409,9 @@ static int twl6040_prepare(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; + struct twl6040 *twl6040 = codec->control_data; struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); + int ret; if (!priv->sysclk) { dev_err(codec->dev, @@ -1424,24 +1419,19 @@ static int twl6040_prepare(struct snd_pcm_substream *substream, return -EINVAL; } - /* - * capture is not supported at 17.64 MHz, - * it's reserved for headset low-power playback scenario - */ - if ((priv->sysclk == 17640000) && - substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - dev_err(codec->dev, - "capture mode is not supported at %dHz\n", - priv->sysclk); - return -EINVAL; - } - if ((priv->sysclk == 17640000) && priv->non_lp) { dev_err(codec->dev, "some enabled paths aren't supported at %dHz\n", priv->sysclk); return -EPERM; } + + ret = twl6040_set_pll(twl6040, priv->pll, priv->clk_in, priv->sysclk); + if (ret) { + dev_err(codec->dev, "Can not set PLL (%d)\n", ret); + return -EPERM; + } + return 0; } @@ -1450,99 +1440,12 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai, { struct snd_soc_codec *codec = codec_dai->codec; struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - u8 hppllctl, lppllctl; - - hppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_HPPLLCTL); - lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL); switch (clk_id) { case TWL6040_SYSCLK_SEL_LPPLL: - switch (freq) { - case 32768: - /* headset dac and driver must be in low-power mode */ - headset_power_mode(codec, 0); - - /* clk32k input requires low-power pll */ - lppllctl |= TWL6040_LPLLENA; - twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl); - mdelay(5); - lppllctl &= ~TWL6040_HPLLSEL; - twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl); - hppllctl &= ~TWL6040_HPLLENA; - twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl); - break; - default: - dev_err(codec->dev, "unknown mclk freq %d\n", freq); - return -EINVAL; - } - - /* lppll divider */ - switch (priv->sysclk) { - case 17640000: - lppllctl |= TWL6040_LPLLFIN; - break; - case 19200000: - lppllctl &= ~TWL6040_LPLLFIN; - break; - default: - /* sysclk not yet configured */ - lppllctl &= ~TWL6040_LPLLFIN; - priv->sysclk = 19200000; - break; - } - - twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl); - - priv->pll = TWL6040_LPPLL_ID; - priv->sysclk_constraints = &lp_constraints; - break; case TWL6040_SYSCLK_SEL_HPPLL: - hppllctl &= ~TWL6040_MCLK_MSK; - - switch (freq) { - case 12000000: - /* mclk input, pll enabled */ - hppllctl |= TWL6040_MCLK_12000KHZ | - TWL6040_HPLLSQRBP | - TWL6040_HPLLENA; - break; - case 19200000: - /* mclk input, pll disabled */ - hppllctl |= TWL6040_MCLK_19200KHZ | - TWL6040_HPLLSQRENA | - TWL6040_HPLLBP; - break; - case 26000000: - /* mclk input, pll enabled */ - hppllctl |= TWL6040_MCLK_26000KHZ | - TWL6040_HPLLSQRBP | - TWL6040_HPLLENA; - break; - case 38400000: - /* clk slicer, pll disabled */ - hppllctl |= TWL6040_MCLK_38400KHZ | - TWL6040_HPLLSQRENA | - TWL6040_HPLLBP; - break; - default: - dev_err(codec->dev, "unknown mclk freq %d\n", freq); - return -EINVAL; - } - - /* headset dac and driver must be in high-performance mode */ - headset_power_mode(codec, 1); - - twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl); - udelay(500); - lppllctl |= TWL6040_HPLLSEL; - twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl); - lppllctl &= ~TWL6040_LPLLENA; - twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl); - - /* high-performance pll can provide only 19.2 MHz */ - priv->pll = TWL6040_HPPLL_ID; - priv->sysclk = 19200000; - priv->sysclk_constraints = &hp_constraints; + priv->pll = clk_id; + priv->clk_in = freq; break; default: dev_err(codec->dev, "unknown clk_id %d\n", clk_id); @@ -1559,15 +1462,27 @@ static struct snd_soc_dai_ops twl6040_dai_ops = { .set_sysclk = twl6040_set_dai_sysclk, }; -static struct snd_soc_dai_driver twl6040_dai = { +static struct snd_soc_dai_driver twl6040_dai[] = { +{ .name = "twl6040-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, - .channels_max = 4, + .channels_max = 2, + .rates = TWL6040_RATES, + .formats = TWL6040_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, .rates = TWL6040_RATES, .formats = TWL6040_FORMATS, }, + .ops = &twl6040_dai_ops, +}, +{ + .name = "twl6040-ul", .capture = { .stream_name = "Capture", .channels_min = 1, @@ -1576,6 +1491,40 @@ static struct snd_soc_dai_driver twl6040_dai = { .formats = TWL6040_FORMATS, }, .ops = &twl6040_dai_ops, +}, +{ + .name = "twl6040-dl1", + .playback = { + .stream_name = "Headset Playback", + .channels_min = 1, + .channels_max = 2, + .rates = TWL6040_RATES, + .formats = TWL6040_FORMATS, + }, + .ops = &twl6040_dai_ops, +}, +{ + .name = "twl6040-dl2", + .playback = { + .stream_name = "Handsfree Playback", + .channels_min = 1, + .channels_max = 2, + .rates = TWL6040_RATES, + .formats = TWL6040_FORMATS, + }, + .ops = &twl6040_dai_ops, +}, +{ + .name = "twl6040-vib", + .playback = { + .stream_name = "Vibra Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .formats = TWL6040_FORMATS, + }, + .ops = &twl6040_dai_ops, +}, }; #ifdef CONFIG_PM @@ -1600,11 +1549,11 @@ static int twl6040_resume(struct snd_soc_codec *codec) static int twl6040_probe(struct snd_soc_codec *codec) { - struct twl4030_codec_data *twl_codec = codec->dev->platform_data; struct twl6040_data *priv; - int audpwron, naudint; + struct twl4030_codec_data *pdata = dev_get_platdata(codec->dev); + struct platform_device *pdev = container_of(codec->dev, + struct platform_device, dev); int ret = 0; - u8 icrev, intmr = TWL6040_ALLINT_MSK; priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); if (priv == NULL) @@ -1612,23 +1561,32 @@ static int twl6040_probe(struct snd_soc_codec *codec) snd_soc_codec_set_drvdata(codec, priv); priv->codec = codec; + codec->control_data = dev_get_drvdata(codec->dev->parent); - twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &icrev, TWL6040_REG_ASICREV); + if (pdata && pdata->hs_left_step && pdata->hs_right_step) { + priv->hs_left_step = pdata->hs_left_step; + priv->hs_right_step = pdata->hs_right_step; + } else { + priv->hs_left_step = 1; + priv->hs_right_step = 1; + } - if (twl_codec && (icrev > 0)) - audpwron = twl_codec->audpwron_gpio; - else - audpwron = -EINVAL; + if (pdata && pdata->hf_left_step && pdata->hf_right_step) { + priv->hf_left_step = pdata->hf_left_step; + priv->hf_right_step = pdata->hf_right_step; + } else { + priv->hf_left_step = 1; + priv->hf_right_step = 1; + } - if (twl_codec) - naudint = twl_codec->naudint_irq; - else - naudint = 0; + priv->plug_irq = platform_get_irq(pdev, 0); + if (priv->plug_irq < 0) { + dev_err(codec->dev, "invalid irq\n"); + ret = -EINVAL; + goto work_err; + } - priv->audpwron = audpwron; - priv->naudint = naudint; priv->workqueue = create_singlethread_workqueue("twl6040-codec"); - if (!priv->workqueue) { ret = -ENOMEM; goto work_err; @@ -1638,56 +1596,33 @@ static int twl6040_probe(struct snd_soc_codec *codec) mutex_init(&priv->mutex); - init_completion(&priv->ready); init_completion(&priv->headset.ramp_done); init_completion(&priv->handsfree.ramp_done); - if (gpio_is_valid(audpwron)) { - ret = gpio_request(audpwron, "audpwron"); - if (ret) - goto gpio1_err; - - ret = gpio_direction_output(audpwron, 0); - if (ret) - goto gpio2_err; - - priv->codec_powered = 0; - - /* enable only codec ready interrupt */ - intmr &= ~(TWL6040_READYMSK | TWL6040_PLUGMSK); - - /* reset interrupt status to allow correct power up sequence */ - twl6040_read_reg_volatile(codec, TWL6040_REG_INTID); - } - twl6040_write(codec, TWL6040_REG_INTMR, intmr); - - if (naudint) { - /* audio interrupt */ - ret = request_threaded_irq(naudint, NULL, - twl6040_naudint_handler, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, - "twl6040_codec", codec); - if (ret) - goto gpio2_err; - } - - /* init vio registers */ - twl6040_init_vio_regs(codec); - priv->hf_workqueue = create_singlethread_workqueue("twl6040-hf"); if (priv->hf_workqueue == NULL) { ret = -ENOMEM; - goto irq_err; + goto hfwq_err; } priv->hs_workqueue = create_singlethread_workqueue("twl6040-hs"); if (priv->hs_workqueue == NULL) { ret = -ENOMEM; - goto wq_err; + goto hswq_err; } INIT_DELAYED_WORK(&priv->hs_delayed_work, twl6040_pga_hs_work); INIT_DELAYED_WORK(&priv->hf_delayed_work, twl6040_pga_hf_work); + ret = request_threaded_irq(priv->plug_irq, NULL, twl6040_audio_handler, + 0, "twl6040_irq_plug", codec); + if (ret) { + dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret); + goto plugirq_err; + } + + /* init vio registers */ + twl6040_init_vio_regs(codec); + /* power on device */ ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); if (ret) @@ -1700,16 +1635,12 @@ static int twl6040_probe(struct snd_soc_codec *codec) return 0; bias_err: + free_irq(priv->plug_irq, codec); +plugirq_err: destroy_workqueue(priv->hs_workqueue); -wq_err: +hswq_err: destroy_workqueue(priv->hf_workqueue); -irq_err: - if (naudint) - free_irq(naudint, codec); -gpio2_err: - if (gpio_is_valid(audpwron)) - gpio_free(audpwron); -gpio1_err: +hfwq_err: destroy_workqueue(priv->workqueue); work_err: kfree(priv); @@ -1719,17 +1650,9 @@ work_err: static int twl6040_remove(struct snd_soc_codec *codec) { struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - int audpwron = priv->audpwron; - int naudint = priv->naudint; twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); - - if (gpio_is_valid(audpwron)) - gpio_free(audpwron); - - if (naudint) - free_irq(naudint, codec); - + free_irq(priv->plug_irq, codec); destroy_workqueue(priv->workqueue); destroy_workqueue(priv->hf_workqueue); destroy_workqueue(priv->hs_workqueue); @@ -1753,8 +1676,8 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = { static int __devinit twl6040_codec_probe(struct platform_device *pdev) { - return snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_twl6040, &twl6040_dai, 1); + return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl6040, + twl6040_dai, ARRAY_SIZE(twl6040_dai)); } static int __devexit twl6040_codec_remove(struct platform_device *pdev) diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h index 23aeed0963e6..d8de67869dd9 100644 --- a/sound/soc/codecs/twl6040.h +++ b/sound/soc/codecs/twl6040.h @@ -22,125 +22,8 @@ #ifndef __TWL6040_H__ #define __TWL6040_H__ -#define TWL6040_REG_ASICID 0x01 -#define TWL6040_REG_ASICREV 0x02 -#define TWL6040_REG_INTID 0x03 -#define TWL6040_REG_INTMR 0x04 -#define TWL6040_REG_NCPCTL 0x05 -#define TWL6040_REG_LDOCTL 0x06 -#define TWL6040_REG_HPPLLCTL 0x07 -#define TWL6040_REG_LPPLLCTL 0x08 -#define TWL6040_REG_LPPLLDIV 0x09 -#define TWL6040_REG_AMICBCTL 0x0A -#define TWL6040_REG_DMICBCTL 0x0B -#define TWL6040_REG_MICLCTL 0x0C -#define TWL6040_REG_MICRCTL 0x0D -#define TWL6040_REG_MICGAIN 0x0E -#define TWL6040_REG_LINEGAIN 0x0F -#define TWL6040_REG_HSLCTL 0x10 -#define TWL6040_REG_HSRCTL 0x11 -#define TWL6040_REG_HSGAIN 0x12 -#define TWL6040_REG_EARCTL 0x13 -#define TWL6040_REG_HFLCTL 0x14 -#define TWL6040_REG_HFLGAIN 0x15 -#define TWL6040_REG_HFRCTL 0x16 -#define TWL6040_REG_HFRGAIN 0x17 -#define TWL6040_REG_VIBCTLL 0x18 -#define TWL6040_REG_VIBDATL 0x19 -#define TWL6040_REG_VIBCTLR 0x1A -#define TWL6040_REG_VIBDATR 0x1B -#define TWL6040_REG_HKCTL1 0x1C -#define TWL6040_REG_HKCTL2 0x1D -#define TWL6040_REG_GPOCTL 0x1E -#define TWL6040_REG_ALB 0x1F -#define TWL6040_REG_DLB 0x20 -#define TWL6040_REG_TRIM1 0x28 -#define TWL6040_REG_TRIM2 0x29 -#define TWL6040_REG_TRIM3 0x2A -#define TWL6040_REG_HSOTRIM 0x2B -#define TWL6040_REG_HFOTRIM 0x2C -#define TWL6040_REG_ACCCTL 0x2D -#define TWL6040_REG_STATUS 0x2E - -#define TWL6040_CACHEREGNUM (TWL6040_REG_STATUS + 1) - -#define TWL6040_VIOREGNUM 18 -#define TWL6040_VDDREGNUM 21 - -/* INTID (0x03) fields */ - -#define TWL6040_THINT 0x01 -#define TWL6040_PLUGINT 0x02 -#define TWL6040_UNPLUGINT 0x04 -#define TWL6040_HOOKINT 0x08 -#define TWL6040_HFINT 0x10 -#define TWL6040_VIBINT 0x20 -#define TWL6040_READYINT 0x40 - -/* INTMR (0x04) fields */ - -#define TWL6040_PLUGMSK 0x02 -#define TWL6040_READYMSK 0x40 -#define TWL6040_ALLINT_MSK 0x7B - -/* NCPCTL (0x05) fields */ - -#define TWL6040_NCPENA 0x01 -#define TWL6040_NCPOPEN 0x40 - -/* LDOCTL (0x06) fields */ - -#define TWL6040_LSLDOENA 0x01 -#define TWL6040_HSLDOENA 0x04 -#define TWL6040_REFENA 0x40 -#define TWL6040_OSCENA 0x80 - -/* HPPLLCTL (0x07) fields */ - -#define TWL6040_HPLLENA 0x01 -#define TWL6040_HPLLRST 0x02 -#define TWL6040_HPLLBP 0x04 -#define TWL6040_HPLLSQRENA 0x08 -#define TWL6040_HPLLSQRBP 0x10 -#define TWL6040_MCLK_12000KHZ (0 << 5) -#define TWL6040_MCLK_19200KHZ (1 << 5) -#define TWL6040_MCLK_26000KHZ (2 << 5) -#define TWL6040_MCLK_38400KHZ (3 << 5) -#define TWL6040_MCLK_MSK 0x60 - -/* LPPLLCTL (0x08) fields */ - -#define TWL6040_LPLLENA 0x01 -#define TWL6040_LPLLRST 0x02 -#define TWL6040_LPLLSEL 0x04 -#define TWL6040_LPLLFIN 0x08 -#define TWL6040_HPLLSEL 0x10 - -/* HSLCTL (0x10) fields */ - -#define TWL6040_HSDACMODEL 0x02 -#define TWL6040_HSDRVMODEL 0x08 - -/* HSRCTL (0x11) fields */ - -#define TWL6040_HSDACMODER 0x02 -#define TWL6040_HSDRVMODER 0x08 - -/* ACCCTL (0x2D) fields */ - -#define TWL6040_RESETSPLIT 0x04 - -#define TWL6040_SYSCLK_SEL_LPPLL 1 -#define TWL6040_SYSCLK_SEL_HPPLL 2 - -#define TWL6040_HPPLL_ID 1 -#define TWL6040_LPPLL_ID 2 - -/* STATUS (0x2E) fields */ - -#define TWL6040_PLUGCOMP 0x02 - void twl6040_hs_jack_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, int report); +int twl6040_get_clk_id(struct snd_soc_codec *codec); #endif /* End of __TWL6040_H__ */ diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 3c2ee1bb73cd..6af23d06870f 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -13,7 +13,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/delay.h> diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index d8f130d39dd9..bb699bb55a50 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -11,9 +11,6 @@ menuconfig SND_IMX_SOC if SND_IMX_SOC -config SND_MXC_SOC_SSI - tristate - config SND_MXC_SOC_FIQ tristate @@ -24,7 +21,6 @@ config SND_MXC_SOC_WM1133_EV1 tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted" depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL select SND_SOC_WM8350 - select SND_MXC_SOC_SSI select SND_MXC_SOC_FIQ help Enable support for audio on the i.MX31ADS with the WM1133-EV1 @@ -34,7 +30,6 @@ config SND_SOC_MX27VIS_AIC32X4 tristate "SoC audio support for Visstrim M10 boards" depends on MACH_IMX27_VISSTRIM_M10 select SND_SOC_TVL320AIC32X4 - select SND_MXC_SOC_SSI select SND_MXC_SOC_MX2 help Say Y if you want to add support for SoC audio on Visstrim SM10 @@ -44,7 +39,6 @@ config SND_SOC_PHYCORE_AC97 tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards" depends on MACH_PCM043 || MACH_PCA100 select SND_SOC_WM9712 - select SND_MXC_SOC_SSI select SND_MXC_SOC_FIQ help Say Y if you want to add support for SoC audio on Phytec phyCORE @@ -57,7 +51,6 @@ config SND_SOC_EUKREA_TLV320 || MACH_EUKREA_MBIMXSD35_BASEBOARD \ || MACH_EUKREA_MBIMXSD51_BASEBOARD select SND_SOC_TLV320AIC23 - select SND_MXC_SOC_SSI select SND_MXC_SOC_FIQ help Enable I2S based access to the TLV320AIC23B codec attached diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c index aab7765f401a..4173b3d87f97 100644 --- a/sound/soc/imx/imx-pcm-dma-mx2.c +++ b/sound/soc/imx/imx-pcm-dma-mx2.c @@ -337,3 +337,5 @@ static void __exit snd_imx_pcm_exit(void) platform_driver_unregister(&imx_pcm_driver); } module_exit(snd_imx_pcm_exit); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:imx-pcm-audio"); diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 5b13feca7537..61fceb09cdb5 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c @@ -774,4 +774,4 @@ module_exit(imx_ssi_exit); MODULE_AUTHOR("Sascha Hauer, <s.hauer@pengutronix.de>"); MODULE_DESCRIPTION("i.MX I2S/ac97 SoC Interface"); MODULE_LICENSE("GPL"); - +MODULE_ALIAS("platform:imx-ssi"); diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c index 3f72d17d1ef0..9f6a758029d1 100644 --- a/sound/soc/omap/sdp3430.c +++ b/sound/soc/omap/sdp3430.c @@ -36,7 +36,7 @@ #include <plat/mcbsp.h> /* Register descriptions for twl4030 codec part */ -#include <linux/mfd/twl4030-codec.h> +#include <linux/mfd/twl4030-audio.h> #include "omap-mcbsp.h" #include "omap-pcm.h" diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c index 189e03900637..b80efb02bfca 100644 --- a/sound/soc/omap/sdp4430.c +++ b/sound/soc/omap/sdp4430.c @@ -21,6 +21,8 @@ #include <linux/clk.h> #include <linux/platform_device.h> +#include <linux/mfd/twl6040.h> + #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> @@ -34,8 +36,6 @@ #include "omap-pcm.h" #include "../codecs/twl6040.h" -static int twl6040_power_mode; - static int sdp4430_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -44,13 +44,13 @@ static int sdp4430_hw_params(struct snd_pcm_substream *substream, int clk_id, freq; int ret; - if (twl6040_power_mode) { - clk_id = TWL6040_SYSCLK_SEL_HPPLL; + clk_id = twl6040_get_clk_id(rtd->codec); + if (clk_id == TWL6040_SYSCLK_SEL_HPPLL) freq = 38400000; - } else { - clk_id = TWL6040_SYSCLK_SEL_LPPLL; + else if (clk_id == TWL6040_SYSCLK_SEL_LPPLL) freq = 32768; - } + else + return -EINVAL; /* set the codec mclk */ ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq, @@ -81,35 +81,6 @@ static struct snd_soc_jack_pin hs_jack_pins[] = { }, }; -static int sdp4430_get_power_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = twl6040_power_mode; - return 0; -} - -static int sdp4430_set_power_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - if (twl6040_power_mode == ucontrol->value.integer.value[0]) - return 0; - - twl6040_power_mode = ucontrol->value.integer.value[0]; - - return 1; -} - -static const char *power_texts[] = {"Low-Power", "High-Performance"}; - -static const struct soc_enum sdp4430_enum[] = { - SOC_ENUM_SINGLE_EXT(2, power_texts), -}; - -static const struct snd_kcontrol_new sdp4430_controls[] = { - SOC_ENUM_EXT("TWL6040 Power Mode", sdp4430_enum[0], - sdp4430_get_power_mode, sdp4430_set_power_mode), -}; - /* SDP4430 machine DAPM */ static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = { SND_SOC_DAPM_MIC("Ext Mic", NULL), @@ -152,12 +123,6 @@ static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_dapm_context *dapm = &codec->dapm; int ret; - /* Add SDP4430 specific controls */ - ret = snd_soc_add_controls(codec, sdp4430_controls, - ARRAY_SIZE(sdp4430_controls)); - if (ret) - return ret; - /* Add SDP4430 specific widgets */ ret = snd_soc_dapm_new_controls(dapm, sdp4430_twl6040_dapm_widgets, ARRAY_SIZE(sdp4430_twl6040_dapm_widgets)); @@ -237,9 +202,6 @@ static int __init sdp4430_soc_init(void) if (ret) goto err; - /* Codec starts in HP mode */ - twl6040_power_mode = 1; - return 0; err: diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c index 01709940a43c..9a2666ffc16c 100644 --- a/sound/soc/omap/zoom2.c +++ b/sound/soc/omap/zoom2.c @@ -32,7 +32,7 @@ #include <plat/mcbsp.h> /* Register descriptions for twl4030 codec part */ -#include <linux/mfd/twl4030-codec.h> +#include <linux/mfd/twl4030-audio.h> #include "omap-mcbsp.h" #include "omap-pcm.h" diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c index 2ce0b2d891d5..fab20a54e863 100644 --- a/sound/soc/pxa/pxa2xx-pcm.c +++ b/sound/soc/pxa/pxa2xx-pcm.c @@ -95,14 +95,14 @@ static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - if (dai->driver->playback.channels_min) { + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) goto out; } - if (dai->driver->capture.channels_min) { + if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); if (ret) diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index c005ceb70c9d..039b9532b270 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -409,9 +409,6 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, codec->bulk_write_raw = snd_soc_hw_bulk_write_raw; switch (control) { - case SND_SOC_CUSTOM: - break; - case SND_SOC_I2C: #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) codec->hw_write = (hw_write_t)i2c_master_send; diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c index a91719d5918b..1e3ae3327dd3 100644 --- a/sound/usb/6fire/firmware.c +++ b/sound/usb/6fire/firmware.c @@ -270,7 +270,6 @@ static int usb6fire_fw_ezusb_upload( data = 0x00; /* resume ezusb cpu */ ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1); if (ret < 0) { - release_firmware(fw); snd_printk(KERN_ERR PREFIX "unable to upload ezusb " "firmware %s: end message.\n", fwname); return ret; diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index b137b25865cc..d144cdb2f159 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c @@ -395,12 +395,12 @@ static int usb6fire_pcm_open(struct snd_pcm_substream *alsa_sub) alsa_rt->hw = pcm_hw; if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (rt->rate >= 0) + if (rt->rate < ARRAY_SIZE(rates)) alsa_rt->hw.rates = rates_alsaid[rt->rate]; alsa_rt->hw.channels_max = OUT_N_CHANNELS; sub = &rt->playback; } else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE) { - if (rt->rate >= 0) + if (rt->rate < ARRAY_SIZE(rates)) alsa_rt->hw.rates = rates_alsaid[rt->rate]; alsa_rt->hw.channels_max = IN_N_CHANNELS; sub = &rt->capture; |