diff options
Diffstat (limited to 'sound')
27 files changed, 275 insertions, 658 deletions
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile index c95d8f1..5526b03 100644 --- a/sound/i2c/other/Makefile +++ b/sound/i2c/other/Makefile @@ -8,10 +8,8 @@ snd-ak4117-objs := ak4117.o snd-ak4113-objs := ak4113.o snd-ak4xxx-adda-objs := ak4xxx-adda.o snd-pt2258-objs := pt2258.o -snd-tea575x-tuner-objs := tea575x-tuner.o # Module Dependency obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o -obj-$(CONFIG_SND_TEA575X) += snd-tea575x-tuner.o diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c deleted file mode 100644 index 8a36a1d..0000000 --- a/sound/i2c/other/tea575x-tuner.c +++ /dev/null @@ -1,577 +0,0 @@ -/* - * ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips - * - * Copyright (c) 2004 Jaroslav Kysela <perex@perex.cz> - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <asm/io.h> -#include <linux/delay.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/sched.h> -#include <media/v4l2-device.h> -#include <media/v4l2-dev.h> -#include <media/v4l2-fh.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-event.h> -#include <sound/tea575x-tuner.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); -MODULE_LICENSE("GPL"); - -/* - * definitions - */ - -#define TEA575X_BIT_SEARCH (1<<24) /* 1 = search action, 0 = tuned */ -#define TEA575X_BIT_UPDOWN (1<<23) /* 0 = search down, 1 = search up */ -#define TEA575X_BIT_MONO (1<<22) /* 0 = stereo, 1 = mono */ -#define TEA575X_BIT_BAND_MASK (3<<20) -#define TEA575X_BIT_BAND_FM (0<<20) -#define TEA575X_BIT_BAND_MW (1<<20) -#define TEA575X_BIT_BAND_LW (2<<20) -#define TEA575X_BIT_BAND_SW (3<<20) -#define TEA575X_BIT_PORT_0 (1<<19) /* user bit */ -#define TEA575X_BIT_PORT_1 (1<<18) /* user bit */ -#define TEA575X_BIT_SEARCH_MASK (3<<16) /* search level */ -#define TEA575X_BIT_SEARCH_5_28 (0<<16) /* FM >5uV, AM >28uV */ -#define TEA575X_BIT_SEARCH_10_40 (1<<16) /* FM >10uV, AM > 40uV */ -#define TEA575X_BIT_SEARCH_30_63 (2<<16) /* FM >30uV, AM > 63uV */ -#define TEA575X_BIT_SEARCH_150_1000 (3<<16) /* FM > 150uV, AM > 1000uV */ -#define TEA575X_BIT_DUMMY (1<<15) /* buffer */ -#define TEA575X_BIT_FREQ_MASK 0x7fff - -enum { BAND_FM, BAND_FM_JAPAN, BAND_AM }; - -static const struct v4l2_frequency_band bands[] = { - { - .type = V4L2_TUNER_RADIO, - .index = 0, - .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_FREQ_BANDS, - .rangelow = 87500 * 16, - .rangehigh = 108000 * 16, - .modulation = V4L2_BAND_MODULATION_FM, - }, - { - .type = V4L2_TUNER_RADIO, - .index = 0, - .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_FREQ_BANDS, - .rangelow = 76000 * 16, - .rangehigh = 91000 * 16, - .modulation = V4L2_BAND_MODULATION_FM, - }, - { - .type = V4L2_TUNER_RADIO, - .index = 1, - .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS, - .rangelow = 530 * 16, - .rangehigh = 1710 * 16, - .modulation = V4L2_BAND_MODULATION_AM, - }, -}; - -/* - * lowlevel part - */ - -static void snd_tea575x_write(struct snd_tea575x *tea, unsigned int val) -{ - u16 l; - u8 data; - - if (tea->ops->write_val) - return tea->ops->write_val(tea, val); - - tea->ops->set_direction(tea, 1); - udelay(16); - - for (l = 25; l > 0; l--) { - data = (val >> 24) & TEA575X_DATA; - val <<= 1; /* shift data */ - tea->ops->set_pins(tea, data | TEA575X_WREN); - udelay(2); - tea->ops->set_pins(tea, data | TEA575X_WREN | TEA575X_CLK); - udelay(2); - tea->ops->set_pins(tea, data | TEA575X_WREN); - udelay(2); - } - - if (!tea->mute) - tea->ops->set_pins(tea, 0); -} - -static u32 snd_tea575x_read(struct snd_tea575x *tea) -{ - u16 l, rdata; - u32 data = 0; - - if (tea->ops->read_val) - return tea->ops->read_val(tea); - - tea->ops->set_direction(tea, 0); - tea->ops->set_pins(tea, 0); - udelay(16); - - for (l = 24; l--;) { - tea->ops->set_pins(tea, TEA575X_CLK); - udelay(2); - if (!l) - tea->tuned = tea->ops->get_pins(tea) & TEA575X_MOST ? 0 : 1; - tea->ops->set_pins(tea, 0); - udelay(2); - data <<= 1; /* shift data */ - rdata = tea->ops->get_pins(tea); - if (!l) - tea->stereo = (rdata & TEA575X_MOST) ? 0 : 1; - if (rdata & TEA575X_DATA) - data++; - udelay(2); - } - - if (tea->mute) - tea->ops->set_pins(tea, TEA575X_WREN); - - return data; -} - -static u32 snd_tea575x_val_to_freq(struct snd_tea575x *tea, u32 val) -{ - u32 freq = val & TEA575X_BIT_FREQ_MASK; - - if (freq == 0) - return freq; - - switch (tea->band) { - case BAND_FM: - /* freq *= 12.5 */ - freq *= 125; - freq /= 10; - /* crystal fixup */ - freq -= TEA575X_FMIF; - break; - case BAND_FM_JAPAN: - /* freq *= 12.5 */ - freq *= 125; - freq /= 10; - /* crystal fixup */ - freq += TEA575X_FMIF; - break; - case BAND_AM: - /* crystal fixup */ - freq -= TEA575X_AMIF; - break; - } - - return clamp(freq * 16, bands[tea->band].rangelow, - bands[tea->band].rangehigh); /* from kHz */ -} - -static u32 snd_tea575x_get_freq(struct snd_tea575x *tea) -{ - return snd_tea575x_val_to_freq(tea, snd_tea575x_read(tea)); -} - -void snd_tea575x_set_freq(struct snd_tea575x *tea) -{ - u32 freq = tea->freq / 16; /* to kHz */ - u32 band = 0; - - switch (tea->band) { - case BAND_FM: - band = TEA575X_BIT_BAND_FM; - /* crystal fixup */ - freq += TEA575X_FMIF; - /* freq /= 12.5 */ - freq *= 10; - freq /= 125; - break; - case BAND_FM_JAPAN: - band = TEA575X_BIT_BAND_FM; - /* crystal fixup */ - freq -= TEA575X_FMIF; - /* freq /= 12.5 */ - freq *= 10; - freq /= 125; - break; - case BAND_AM: - band = TEA575X_BIT_BAND_MW; - /* crystal fixup */ - freq += TEA575X_AMIF; - break; - } - - tea->val &= ~(TEA575X_BIT_FREQ_MASK | TEA575X_BIT_BAND_MASK); - tea->val |= band; - tea->val |= freq & TEA575X_BIT_FREQ_MASK; - snd_tea575x_write(tea, tea->val); - tea->freq = snd_tea575x_val_to_freq(tea, tea->val); -} - -/* - * Linux Video interface - */ - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *v) -{ - struct snd_tea575x *tea = video_drvdata(file); - - strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); - strlcpy(v->card, tea->card, sizeof(v->card)); - strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); - strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); - v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; - if (!tea->cannot_read_data) - v->device_caps |= V4L2_CAP_HW_FREQ_SEEK; - v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -static int vidioc_enum_freq_bands(struct file *file, void *priv, - struct v4l2_frequency_band *band) -{ - struct snd_tea575x *tea = video_drvdata(file); - int index; - - if (band->tuner != 0) - return -EINVAL; - - switch (band->index) { - case 0: - if (tea->tea5759) - index = BAND_FM_JAPAN; - else - index = BAND_FM; - break; - case 1: - if (tea->has_am) { - index = BAND_AM; - break; - } - /* Fall through */ - default: - return -EINVAL; - } - - *band = bands[index]; - if (!tea->cannot_read_data) - band->capability |= V4L2_TUNER_CAP_HWSEEK_BOUNDED; - - return 0; -} - -static int vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *v) -{ - struct snd_tea575x *tea = video_drvdata(file); - struct v4l2_frequency_band band_fm = { 0, }; - - if (v->index > 0) - return -EINVAL; - - snd_tea575x_read(tea); - vidioc_enum_freq_bands(file, priv, &band_fm); - - memset(v, 0, sizeof(*v)); - strlcpy(v->name, tea->has_am ? "FM/AM" : "FM", sizeof(v->name)); - v->type = V4L2_TUNER_RADIO; - v->capability = band_fm.capability; - v->rangelow = tea->has_am ? bands[BAND_AM].rangelow : band_fm.rangelow; - v->rangehigh = band_fm.rangehigh; - v->rxsubchans = tea->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; - v->audmode = (tea->val & TEA575X_BIT_MONO) ? - V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO; - v->signal = tea->tuned ? 0xffff : 0; - return 0; -} - -static int vidioc_s_tuner(struct file *file, void *priv, - const struct v4l2_tuner *v) -{ - struct snd_tea575x *tea = video_drvdata(file); - u32 orig_val = tea->val; - - if (v->index) - return -EINVAL; - tea->val &= ~TEA575X_BIT_MONO; - if (v->audmode == V4L2_TUNER_MODE_MONO) - tea->val |= TEA575X_BIT_MONO; - /* Only apply changes if currently tuning FM */ - if (tea->band != BAND_AM && tea->val != orig_val) - snd_tea575x_set_freq(tea); - - return 0; -} - -static int vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct snd_tea575x *tea = video_drvdata(file); - - if (f->tuner != 0) - return -EINVAL; - f->type = V4L2_TUNER_RADIO; - f->frequency = tea->freq; - return 0; -} - -static int vidioc_s_frequency(struct file *file, void *priv, - const struct v4l2_frequency *f) -{ - struct snd_tea575x *tea = video_drvdata(file); - - if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) - return -EINVAL; - - if (tea->has_am && f->frequency < (20000 * 16)) - tea->band = BAND_AM; - else if (tea->tea5759) - tea->band = BAND_FM_JAPAN; - else - tea->band = BAND_FM; - - tea->freq = clamp_t(u32, f->frequency, bands[tea->band].rangelow, - bands[tea->band].rangehigh); - snd_tea575x_set_freq(tea); - return 0; -} - -static int vidioc_s_hw_freq_seek(struct file *file, void *fh, - const struct v4l2_hw_freq_seek *a) -{ - struct snd_tea575x *tea = video_drvdata(file); - unsigned long timeout; - int i, spacing; - - if (tea->cannot_read_data) - return -ENOTTY; - if (a->tuner || a->wrap_around) - return -EINVAL; - - if (file->f_flags & O_NONBLOCK) - return -EWOULDBLOCK; - - if (a->rangelow || a->rangehigh) { - for (i = 0; i < ARRAY_SIZE(bands); i++) { - if ((i == BAND_FM && tea->tea5759) || - (i == BAND_FM_JAPAN && !tea->tea5759) || - (i == BAND_AM && !tea->has_am)) - continue; - if (bands[i].rangelow == a->rangelow && - bands[i].rangehigh == a->rangehigh) - break; - } - if (i == ARRAY_SIZE(bands)) - return -EINVAL; /* No matching band found */ - if (i != tea->band) { - tea->band = i; - tea->freq = clamp(tea->freq, bands[i].rangelow, - bands[i].rangehigh); - snd_tea575x_set_freq(tea); - } - } - - spacing = (tea->band == BAND_AM) ? 5 : 50; /* kHz */ - - /* clear the frequency, HW will fill it in */ - tea->val &= ~TEA575X_BIT_FREQ_MASK; - tea->val |= TEA575X_BIT_SEARCH; - if (a->seek_upward) - tea->val |= TEA575X_BIT_UPDOWN; - else - tea->val &= ~TEA575X_BIT_UPDOWN; - snd_tea575x_write(tea, tea->val); - timeout = jiffies + msecs_to_jiffies(10000); - for (;;) { - if (time_after(jiffies, timeout)) - break; - if (schedule_timeout_interruptible(msecs_to_jiffies(10))) { - /* some signal arrived, stop search */ - tea->val &= ~TEA575X_BIT_SEARCH; - snd_tea575x_set_freq(tea); - return -ERESTARTSYS; - } - if (!(snd_tea575x_read(tea) & TEA575X_BIT_SEARCH)) { - u32 freq; - - /* Found a frequency, wait until it can be read */ - for (i = 0; i < 100; i++) { - msleep(10); - freq = snd_tea575x_get_freq(tea); - if (freq) /* available */ - break; - } - if (freq == 0) /* shouldn't happen */ - break; - /* - * if we moved by less than the spacing, or in the - * wrong direction, continue seeking - */ - if (abs(tea->freq - freq) < 16 * spacing || - (a->seek_upward && freq < tea->freq) || - (!a->seek_upward && freq > tea->freq)) { - snd_tea575x_write(tea, tea->val); - continue; - } - tea->freq = freq; - tea->val &= ~TEA575X_BIT_SEARCH; - return 0; - } - } - tea->val &= ~TEA575X_BIT_SEARCH; - snd_tea575x_set_freq(tea); - return -ENODATA; -} - -static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct snd_tea575x *tea = container_of(ctrl->handler, struct snd_tea575x, ctrl_handler); - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - tea->mute = ctrl->val; - snd_tea575x_set_freq(tea); - return 0; - } - - return -EINVAL; -} - -static const struct v4l2_file_operations tea575x_fops = { - .unlocked_ioctl = video_ioctl2, - .open = v4l2_fh_open, - .release = v4l2_fh_release, - .poll = v4l2_ctrl_poll, -}; - -static const struct v4l2_ioctl_ops tea575x_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek, - .vidioc_enum_freq_bands = vidioc_enum_freq_bands, - .vidioc_log_status = v4l2_ctrl_log_status, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -static const struct video_device tea575x_radio = { - .ioctl_ops = &tea575x_ioctl_ops, - .release = video_device_release_empty, -}; - -static const struct v4l2_ctrl_ops tea575x_ctrl_ops = { - .s_ctrl = tea575x_s_ctrl, -}; - -/* - * initialize all the tea575x chips - */ -int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner) -{ - int retval; - - tea->mute = true; - - /* Not all devices can or know how to read the data back. - Such devices can set cannot_read_data to true. */ - if (!tea->cannot_read_data) { - snd_tea575x_write(tea, 0x55AA); - if (snd_tea575x_read(tea) != 0x55AA) - return -ENODEV; - } - - tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_5_28; - tea->freq = 90500 * 16; /* 90.5Mhz default */ - snd_tea575x_set_freq(tea); - - tea->vd = tea575x_radio; - video_set_drvdata(&tea->vd, tea); - mutex_init(&tea->mutex); - strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name)); - tea->vd.lock = &tea->mutex; - tea->vd.v4l2_dev = tea->v4l2_dev; - tea->fops = tea575x_fops; - tea->fops.owner = owner; - tea->vd.fops = &tea->fops; - set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags); - /* disable hw_freq_seek if we can't use it */ - if (tea->cannot_read_data) - v4l2_disable_ioctl(&tea->vd, VIDIOC_S_HW_FREQ_SEEK); - - if (!tea->cannot_mute) { - tea->vd.ctrl_handler = &tea->ctrl_handler; - v4l2_ctrl_handler_init(&tea->ctrl_handler, 1); - v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops, - V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); - retval = tea->ctrl_handler.error; - if (retval) { - v4l2_err(tea->v4l2_dev, "can't initialize controls\n"); - v4l2_ctrl_handler_free(&tea->ctrl_handler); - return retval; - } - - if (tea->ext_init) { - retval = tea->ext_init(tea); - if (retval) { - v4l2_ctrl_handler_free(&tea->ctrl_handler); - return retval; - } - } - - v4l2_ctrl_handler_setup(&tea->ctrl_handler); - } - - retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->radio_nr); - if (retval) { - v4l2_err(tea->v4l2_dev, "can't register video device!\n"); - v4l2_ctrl_handler_free(tea->vd.ctrl_handler); - return retval; - } - - return 0; -} - -void snd_tea575x_exit(struct snd_tea575x *tea) -{ - video_unregister_device(&tea->vd); - v4l2_ctrl_handler_free(tea->vd.ctrl_handler); -} - -static int __init alsa_tea575x_module_init(void) -{ - return 0; -} - -static void __exit alsa_tea575x_module_exit(void) -{ -} - -module_init(alsa_tea575x_module_init) -module_exit(alsa_tea575x_module_exit) - -EXPORT_SYMBOL(snd_tea575x_init); -EXPORT_SYMBOL(snd_tea575x_exit); -EXPORT_SYMBOL(snd_tea575x_set_freq); diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 103b333..6effe99 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -173,11 +173,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids); #endif /* CONFIG_PNP */ -#ifdef OPTi93X -#define DEV_NAME "opti93x" -#else -#define DEV_NAME "opti92x" -#endif +#define DEV_NAME KBUILD_MODNAME static char * snd_opti9xx_names[] = { "unknown", @@ -1167,7 +1163,7 @@ static int snd_opti9xx_pnp_resume(struct pnp_card_link *pcard) static struct pnp_card_driver opti9xx_pnpc_driver = { .flags = PNP_DRIVER_RES_DISABLE, - .name = "opti9xx", + .name = DEV_NAME, .id_table = snd_opti9xx_pnpids, .probe = snd_opti9xx_pnp_probe, .remove = snd_opti9xx_pnp_remove, diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index fe6fa93..46ed9e8 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -1,10 +1,5 @@ # ALSA PCI drivers -config SND_TEA575X - tristate - depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK - default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK - menuconfig SND_PCI bool "PCI sound devices" depends on PCI @@ -542,7 +537,11 @@ config SND_ES1968_INPUT config SND_ES1968_RADIO bool "Enable TEA5757 radio tuner support for es1968" depends on SND_ES1968 + depends on MEDIA_RADIO_SUPPORT depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_ES1968 + select RADIO_ADAPTERS + select RADIO_TEA575X + help Say Y here to include support for TEA5757 radio tuner integrated on some MediaForte cards (e.g. SF64-PCE2). @@ -562,7 +561,10 @@ config SND_FM801 config SND_FM801_TEA575X_BOOL bool "ForteMedia FM801 + TEA5757 tuner" depends on SND_FM801 + depends on MEDIA_RADIO_SUPPORT depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801 + select RADIO_ADAPTERS + select RADIO_TEA575X help Say Y here to include support for soundcards based on the ForteMedia FM801 chip with a TEA5757 tuner (MediaForte SF256-PCS, SF256-PCP and diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index ca8929b..61262f3 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -1842,7 +1842,7 @@ static int snd_ensoniq_create_gameport(struct ensoniq *ensoniq, int dev) default: if (!request_region(io_port, 8, "ens137x: gameport")) { - printk(KERN_WARNING "ens137x: gameport io port 0x%#x in use\n", + printk(KERN_WARNING "ens137x: gameport io port %#x in use\n", io_port); return -EBUSY; } diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 5e2ec96..b0e3d92 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -113,7 +113,7 @@ #include <sound/initval.h> #ifdef CONFIG_SND_ES1968_RADIO -#include <sound/tea575x-tuner.h> +#include <media/tea575x.h> #endif #define CARD_NAME "ESS Maestro1/2" diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 706c5b6..45bc8a9 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -37,7 +37,7 @@ #include <asm/io.h> #ifdef CONFIG_SND_FM801_TEA575X_BOOL -#include <sound/tea575x-tuner.h> +#include <media/tea575x.h> #endif MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c6c9829..6e61a01 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -555,6 +555,9 @@ struct azx { #ifdef CONFIG_SND_HDA_DSP_LOADER struct azx_dev saved_azx_dev; #endif + + /* secondary power domain for hdmi audio under vga device */ + struct dev_pm_domain hdmi_pm_domain; }; #define CREATE_TRACE_POINTS @@ -1397,8 +1400,9 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) int i, ok; #ifdef CONFIG_PM_RUNTIME - if (chip->pci->dev.power.runtime_status != RPM_ACTIVE) - return IRQ_NONE; + if (chip->driver_caps & AZX_DCAPS_PM_RUNTIME) + if (chip->pci->dev.power.runtime_status != RPM_ACTIVE) + return IRQ_NONE; #endif spin_lock(&chip->reg_lock); @@ -1409,7 +1413,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) } status = azx_readl(chip, INTSTS); - if (status == 0) { + if (status == 0 || status == 0xffffffff) { spin_unlock(&chip->reg_lock); return IRQ_NONE; } @@ -2971,6 +2975,12 @@ static int azx_runtime_suspend(struct device *dev) struct snd_card *card = dev_get_drvdata(dev); struct azx *chip = card->private_data; + if (chip->disabled) + return 0; + + if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME)) + return 0; + /* enable controller wake up event */ azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) | STATESTS_INT_MASK); @@ -2991,6 +3001,12 @@ static int azx_runtime_resume(struct device *dev) struct hda_codec *codec; int status; + if (chip->disabled) + return 0; + + if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME)) + return 0; + if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) hda_display_power(true); @@ -3020,6 +3036,9 @@ static int azx_runtime_idle(struct device *dev) struct snd_card *card = dev_get_drvdata(dev); struct azx *chip = card->private_data; + if (chip->disabled) + return 0; + if (!power_save_controller || !(chip->driver_caps & AZX_DCAPS_PM_RUNTIME)) return -EBUSY; @@ -3102,13 +3121,19 @@ static void azx_vs_set_state(struct pci_dev *pci, "%s: %s via VGA-switcheroo\n", pci_name(chip->pci), disabled ? "Disabling" : "Enabling"); if (disabled) { + pm_runtime_put_sync_suspend(&pci->dev); azx_suspend(&pci->dev); + /* when we get suspended by vga switcheroo we end up in D3cold, + * however we have no ACPI handle, so pci/acpi can't put us there, + * put ourselves there */ + pci->current_state = PCI_D3cold; chip->disabled = true; if (snd_hda_lock_devices(chip->bus)) snd_printk(KERN_WARNING SFX "%s: Cannot lock devices!\n", pci_name(chip->pci)); } else { snd_hda_unlock_devices(chip->bus); + pm_runtime_get_noresume(&pci->dev); chip->disabled = false; azx_resume(&pci->dev); } @@ -3163,6 +3188,9 @@ static int register_vga_switcheroo(struct azx *chip) if (err < 0) return err; chip->vga_switcheroo_registered = 1; + + /* register as an optimus hdmi audio power domain */ + vga_switcheroo_init_domain_pm_optimus_hdmi_audio(&chip->pci->dev, &chip->hdmi_pm_domain); return 0; } #else @@ -3400,6 +3428,7 @@ static struct snd_pci_quirk msi_black_list[] = { SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */ SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */ SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */ + SND_PCI_QUIRK(0x1179, 0xfb44, "Toshiba Satellite C870", 0), /* AMD Hudson */ SND_PCI_QUIRK(0x1849, 0x0888, "ASRock", 0), /* Athlon64 X2 + nvidia */ SND_PCI_QUIRK(0xa0a0, 0x0575, "Aopen MZ915-M", 0), /* ICH6 */ {} @@ -3913,7 +3942,7 @@ static int azx_probe_continue(struct azx *chip) power_down_all_codecs(chip); azx_notifier_register(chip); azx_add_card_list(chip); - if (chip->driver_caps & AZX_DCAPS_PM_RUNTIME) + if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || chip->use_vga_switcheroo) pm_runtime_put_noidle(&pci->dev); return 0; diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index cccaf9c..b524f89 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -169,7 +169,7 @@ static void cs_automute(struct hda_codec *codec) snd_hda_gen_update_outputs(codec); - if (spec->gpio_eapd_hp) { + if (spec->gpio_eapd_hp || spec->gpio_eapd_speaker) { spec->gpio_data = spec->gen.hp_jack_present ? spec->gpio_eapd_hp : spec->gpio_eapd_speaker; snd_hda_codec_write(codec, 0x01, 0, @@ -291,10 +291,11 @@ static int cs_init(struct hda_codec *codec) { struct cs_spec *spec = codec->spec; - /* init_verb sequence for C0/C1/C2 errata*/ - snd_hda_sequence_write(codec, cs_errata_init_verbs); - - snd_hda_sequence_write(codec, cs_coef_init_verbs); + if (spec->vendor_nid == CS420X_VENDOR_NID) { + /* init_verb sequence for C0/C1/C2 errata*/ + snd_hda_sequence_write(codec, cs_errata_init_verbs); + snd_hda_sequence_write(codec, cs_coef_init_verbs); + } snd_hda_gen_init(codec); @@ -307,8 +308,10 @@ static int cs_init(struct hda_codec *codec) spec->gpio_data); } - init_input_coef(codec); - init_digital_coef(codec); + if (spec->vendor_nid == CS420X_VENDOR_NID) { + init_input_coef(codec); + init_digital_coef(codec); + } return 0; } @@ -552,6 +555,76 @@ static int patch_cs420x(struct hda_codec *codec) } /* + * CS4208 support: + * Its layout is no longer compatible with CS4206/CS4207, and the generic + * parser seems working fairly well, except for trivial fixups. + */ +enum { + CS4208_GPIO0, +}; + +static const struct hda_model_fixup cs4208_models[] = { + { .id = CS4208_GPIO0, .name = "gpio0" }, + {} +}; + +static const struct snd_pci_quirk cs4208_fixup_tbl[] = { + /* codec SSID */ + SND_PCI_QUIRK(0x106b, 0x7100, "MacBookPro 6,1", CS4208_GPIO0), + SND_PCI_QUIRK(0x106b, 0x7200, "MacBookPro 6,2", CS4208_GPIO0), + {} /* terminator */ +}; + +static void cs4208_fixup_gpio0(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + struct cs_spec *spec = codec->spec; + spec->gpio_eapd_hp = 0; + spec->gpio_eapd_speaker = 1; + spec->gpio_mask = spec->gpio_dir = + spec->gpio_eapd_hp | spec->gpio_eapd_speaker; + } +} + +static const struct hda_fixup cs4208_fixups[] = { + [CS4208_GPIO0] = { + .type = HDA_FIXUP_FUNC, + .v.func = cs4208_fixup_gpio0, + }, +}; + +static int patch_cs4208(struct hda_codec *codec) +{ + struct cs_spec *spec; + int err; + + spec = cs_alloc_spec(codec, 0); /* no specific w/a */ + if (!spec) + return -ENOMEM; + + spec->gen.automute_hook = cs_automute; + + snd_hda_pick_fixup(codec, cs4208_models, cs4208_fixup_tbl, + cs4208_fixups); + snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); + + err = cs_parse_auto_config(codec); + if (err < 0) + goto error; + + codec->patch_ops = cs_patch_ops; + + snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); + + return 0; + + error: + cs_free(codec); + return err; +} + +/* * Cirrus Logic CS4210 * * 1 DAC => HP(sense) / Speakers, @@ -991,6 +1064,7 @@ static int patch_cs4213(struct hda_codec *codec) static const struct hda_codec_preset snd_hda_preset_cirrus[] = { { .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x }, { .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x }, + { .id = 0x10134208, .name = "CS4208", .patch = patch_cs4208 }, { .id = 0x10134210, .name = "CS4210", .patch = patch_cs4210 }, { .id = 0x10134213, .name = "CS4213", .patch = patch_cs4213 }, {} /* terminator */ @@ -998,6 +1072,7 @@ static const struct hda_codec_preset snd_hda_preset_cirrus[] = { MODULE_ALIAS("snd-hda-codec-id:10134206"); MODULE_ALIAS("snd-hda-codec-id:10134207"); +MODULE_ALIAS("snd-hda-codec-id:10134208"); MODULE_ALIAS("snd-hda-codec-id:10134210"); MODULE_ALIAS("snd-hda-codec-id:10134213"); diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 895a0d3..3d8cd044 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -44,6 +44,8 @@ static bool static_hdmi_pcm; module_param(static_hdmi_pcm, bool, 0644); MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info"); +#define is_haswell(codec) ((codec)->vendor_id == 0x80862807) + struct hdmi_spec_per_cvt { hda_nid_t cvt_nid; int assigned; @@ -67,6 +69,8 @@ struct hdmi_spec_per_pin { struct delayed_work work; struct snd_kcontrol *eld_ctl; int repoll_count; + bool setup; /* the stream has been set up by prepare callback */ + int channels; /* current number of channels */ bool non_pcm; bool chmap_set; /* channel-map override by ALSA API? */ unsigned char chmap[8]; /* ALSA API channel-map */ @@ -551,6 +555,17 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) } } + if (!ca) { + /* if there was no match, select the regular ALSA channel + * allocation with the matching number of channels */ + for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { + if (channels == channel_allocations[i].channels) { + ca = channel_allocations[i].ca_index; + break; + } + } + } + snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf)); snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", ca, channels, buf); @@ -868,18 +883,24 @@ static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, return true; } -static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, - bool non_pcm, - struct snd_pcm_substream *substream) +static void hdmi_setup_audio_infoframe(struct hda_codec *codec, + struct hdmi_spec_per_pin *per_pin, + bool non_pcm) { - struct hdmi_spec *spec = codec->spec; - struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); hda_nid_t pin_nid = per_pin->pin_nid; - int channels = substream->runtime->channels; + int channels = per_pin->channels; struct hdmi_eld *eld; int ca; union audio_infoframe ai; + if (!channels) + return; + + if (is_haswell(codec)) + snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, + AMP_OUT_UNMUTE); + eld = &per_pin->sink_eld; if (!eld->monitor_present) return; @@ -1019,10 +1040,10 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) hdmi_non_intrinsic_event(codec, res); } -static void haswell_verify_pin_D0(struct hda_codec *codec, +static void haswell_verify_D0(struct hda_codec *codec, hda_nid_t cvt_nid, hda_nid_t nid) { - int pwr, lamp, ramp; + int pwr; /* For Haswell, the converter 1/2 may keep in D3 state after bootup, * thus pins could only choose converter 0 for use. Make sure the @@ -1038,25 +1059,6 @@ static void haswell_verify_pin_D0(struct hda_codec *codec, pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT; snd_printd("Haswell HDMI audio: Power for pin 0x%x is now D%d\n", nid, pwr); } - - lamp = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_AMP_GAIN_MUTE, - AC_AMP_GET_LEFT | AC_AMP_GET_OUTPUT); - ramp = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_AMP_GAIN_MUTE, - AC_AMP_GET_RIGHT | AC_AMP_GET_OUTPUT); - if (lamp != ramp) { - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AC_AMP_SET_RIGHT | AC_AMP_SET_OUTPUT | lamp); - - lamp = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_AMP_GAIN_MUTE, - AC_AMP_GET_LEFT | AC_AMP_GET_OUTPUT); - ramp = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_AMP_GAIN_MUTE, - AC_AMP_GET_RIGHT | AC_AMP_GET_OUTPUT); - snd_printd("Haswell HDMI audio: Mute after set on pin 0x%x: [0x%x 0x%x]\n", nid, lamp, ramp); - } } /* @@ -1073,8 +1075,8 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, int pinctl; int new_pinctl = 0; - if (codec->vendor_id == 0x80862807) - haswell_verify_pin_D0(codec, cvt_nid, pin_nid); + if (is_haswell(codec)) + haswell_verify_D0(codec, cvt_nid, pin_nid); if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) { pinctl = snd_hda_codec_read(codec, pin_nid, 0, @@ -1213,7 +1215,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, mux_idx); /* configure unused pins to choose other converters */ - if (codec->vendor_id == 0x80862807) + if (is_haswell(codec)) haswell_config_cvts(codec, pin_idx, mux_idx); snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); @@ -1330,6 +1332,7 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) eld_changed = true; } if (update_eld) { + bool old_eld_valid = pin_eld->eld_valid; pin_eld->eld_valid = eld->eld_valid; eld_changed = pin_eld->eld_size != eld->eld_size || memcmp(pin_eld->eld_buffer, eld->eld_buffer, @@ -1339,6 +1342,14 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) eld->eld_size); pin_eld->eld_size = eld->eld_size; pin_eld->info = eld->info; + + /* Haswell-specific workaround: re-setup when the transcoder is + * changed during the stream playback + */ + if (is_haswell(codec) && + eld->eld_valid && !old_eld_valid && per_pin->setup) + hdmi_setup_audio_infoframe(codec, per_pin, + per_pin->non_pcm); } mutex_unlock(&pin_eld->lock); @@ -1378,7 +1389,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) if (get_defcfg_connect(config) == AC_JACK_PORT_NONE) return 0; - if (codec->vendor_id == 0x80862807) + if (is_haswell(codec)) intel_haswell_fixup_connect_list(codec, pin_nid); pin_idx = spec->num_pins; @@ -1511,14 +1522,17 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, hda_nid_t cvt_nid = hinfo->nid; struct hdmi_spec *spec = codec->spec; int pin_idx = hinfo_to_pin_index(spec, hinfo); - hda_nid_t pin_nid = get_pin(spec, pin_idx)->pin_nid; + struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); + hda_nid_t pin_nid = per_pin->pin_nid; bool non_pcm; non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); + per_pin->channels = substream->runtime->channels; + per_pin->setup = true; hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels); - hdmi_setup_audio_infoframe(codec, pin_idx, non_pcm, substream); + hdmi_setup_audio_infoframe(codec, per_pin, non_pcm); return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); } @@ -1558,6 +1572,9 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, snd_hda_spdif_ctls_unassign(codec, pin_idx); per_pin->chmap_set = false; memset(per_pin->chmap, 0, sizeof(per_pin->chmap)); + + per_pin->setup = false; + per_pin->channels = 0; } return 0; @@ -1693,8 +1710,7 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, per_pin->chmap_set = true; memcpy(per_pin->chmap, chmap, sizeof(chmap)); if (prepared) - hdmi_setup_audio_infoframe(codec, pin_idx, per_pin->non_pcm, - substream); + hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm); return 0; } @@ -1782,6 +1798,9 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) struct snd_pcm_chmap *chmap; struct snd_kcontrol *kctl; int i; + + if (!codec->pcm_info[pin_idx].pcm) + break; err = snd_pcm_add_chmap_ctls(codec->pcm_info[pin_idx].pcm, SNDRV_PCM_STREAM_PLAYBACK, NULL, 0, pin_idx, &chmap); @@ -1979,7 +1998,7 @@ static int patch_generic_hdmi(struct hda_codec *codec) codec->spec = spec; hdmi_array_init(spec, 4); - if (codec->vendor_id == 0x80862807) { + if (is_haswell(codec)) { intel_haswell_enable_all_pins(codec, true); intel_haswell_fixup_enable_dp12(codec); } @@ -1990,7 +2009,7 @@ static int patch_generic_hdmi(struct hda_codec *codec) return -EINVAL; } codec->patch_ops = generic_hdmi_patch_ops; - if (codec->vendor_id == 0x80862807) { + if (is_haswell(codec)) { codec->patch_ops.set_power_state = haswell_set_power_state; codec->dp_mst = true; } diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4a90917..bc07d36 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3443,6 +3443,56 @@ static void alc283_fixup_chromebook(struct hda_codec *codec, } } +/* mute tablet speaker pin (0x14) via dock plugging in addition */ +static void asus_tx300_automute(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + snd_hda_gen_update_outputs(codec); + if (snd_hda_jack_detect(codec, 0x1b)) + spec->gen.mute_bits |= (1ULL << 0x14); +} + +static void alc282_fixup_asus_tx300(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + /* TX300 needs to set up GPIO2 for the speaker amp */ + static const struct hda_verb gpio2_verbs[] = { + { 0x01, AC_VERB_SET_GPIO_MASK, 0x04 }, + { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 }, + { 0x01, AC_VERB_SET_GPIO_DATA, 0x04 }, + {} + }; + static const struct hda_pintbl dock_pins[] = { + { 0x1b, 0x21114000 }, /* dock speaker pin */ + {} + }; + struct snd_kcontrol *kctl; + + switch (action) { + case HDA_FIXUP_ACT_PRE_PROBE: + snd_hda_add_verbs(codec, gpio2_verbs); + snd_hda_apply_pincfgs(codec, dock_pins); + spec->gen.auto_mute_via_amp = 1; + spec->gen.automute_hook = asus_tx300_automute; + snd_hda_jack_detect_enable_callback(codec, 0x1b, + HDA_GEN_HP_EVENT, + snd_hda_gen_hp_automute); + break; + case HDA_FIXUP_ACT_BUILD: + /* this is a bit tricky; give more sane names for the main + * (tablet) speaker and the dock speaker, respectively + */ + kctl = snd_hda_find_mixer_ctl(codec, "Speaker Playback Switch"); + if (kctl) + strcpy(kctl->id.name, "Dock Speaker Playback Switch"); + kctl = snd_hda_find_mixer_ctl(codec, "Bass Speaker Playback Switch"); + if (kctl) + strcpy(kctl->id.name, "Speaker Playback Switch"); + break; + } +} + enum { ALC269_FIXUP_SONY_VAIO, ALC275_FIXUP_SONY_VAIO_GPIO2, @@ -3480,6 +3530,7 @@ enum { ALC269_FIXUP_LIMIT_INT_MIC_BOOST, ALC269VB_FIXUP_ORDISSIMO_EVE2, ALC283_FIXUP_CHROME_BOOK, + ALC282_FIXUP_ASUS_TX300, }; static const struct hda_fixup alc269_fixups[] = { @@ -3735,6 +3786,10 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc283_fixup_chromebook, }, + [ALC282_FIXUP_ASUS_TX300] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc282_fixup_asus_tx300, + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -3784,6 +3839,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK(0x103c, 0x21ed, "HP Falco Chromebook", ALC283_FIXUP_CHROME_BOOK), SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC), @@ -4490,6 +4546,7 @@ static const struct hda_fixup alc662_fixups[] = { static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2), + SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE), SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC), diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 3c511d0..5ae6f04 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -1940,7 +1940,7 @@ static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legac r = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport"); if (!r) { - printk(KERN_WARNING "via82xx: cannot reserve joystick port 0x%#x\n", + printk(KERN_WARNING "via82xx: cannot reserve joystick port %#x\n", JOYSTICK_ADDR); return -EBUSY; } diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 0ecf356..bb53dea 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -649,7 +649,7 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream, dma_params = ssc_p->dma_params[dir]; ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable); - ssc_writel(ssc_p->ssc->regs, IER, dma_params->mask->ssc_error); + ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error); pr_debug("%s enabled SSC_SR=0x%08x\n", dir ? "receive" : "transmit", diff --git a/sound/soc/blackfin/bf6xx-i2s.c b/sound/soc/blackfin/bf6xx-i2s.c index c02405c..5810a06 100644 --- a/sound/soc/blackfin/bf6xx-i2s.c +++ b/sound/soc/blackfin/bf6xx-i2s.c @@ -88,6 +88,7 @@ static int bfin_i2s_hw_params(struct snd_pcm_substream *substream, case SNDRV_PCM_FORMAT_S8: param.spctl |= 0x70; sport->wdsize = 1; + break; case SNDRV_PCM_FORMAT_S16_LE: param.spctl |= 0xf0; sport->wdsize = 2; diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 8af0434..259d1ac 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -349,6 +349,9 @@ static int snd_soc_put_volsw_2r_st(struct snd_kcontrol *kcontrol, val = ucontrol->value.integer.value[0]; val2 = ucontrol->value.integer.value[1]; + if (val >= ARRAY_SIZE(st_table) || val2 >= ARRAY_SIZE(st_table)) + return -EINVAL; + err = snd_soc_update_bits(codec, reg, 0x3f, st_table[val].m); if (err < 0) return err; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 15106c0..b33b45d 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -107,7 +107,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM8782 select SND_SOC_WM8804 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8900 if I2C - select SND_SOC_WM8903 if I2C && GENERIC_HARDIRQS + select SND_SOC_WM8903 if I2C select SND_SOC_WM8904 if I2C select SND_SOC_WM8940 if I2C select SND_SOC_WM8955 if I2C diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index b8ba0ad..80555d7 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -1225,13 +1225,18 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol, struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); struct device *dev = codec->dev; bool apply_fir, apply_iir; - int req, status; + unsigned int req; + int status; dev_dbg(dev, "%s: Enter.\n", __func__); mutex_lock(&drvdata->anc_lock); req = ucontrol->value.integer.value[0]; + if (req >= ARRAY_SIZE(enum_anc_state)) { + status = -EINVAL; + goto cleanup; + } if (req != ANC_APPLY_FIR_IIR && req != ANC_APPLY_FIR && req != ANC_APPLY_IIR) { dev_err(dev, "%s: ERROR: Unsupported status to set '%s'!\n", diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 4d3c8fd..ea141e1 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -125,6 +125,10 @@ static int mc13783_write(struct snd_soc_codec *codec, ret = mc13xxx_reg_write(priv->mc13xxx, reg, value); + /* include errata fix for spi audio problems */ + if (reg == MC13783_AUDIO_CODEC || reg == MC13783_AUDIO_DAC) + ret = mc13xxx_reg_write(priv->mc13xxx, reg, value); + mc13xxx_unlock(priv->mc13xxx); return ret; diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 704e246..b7ab71f 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -198,6 +198,7 @@ config SND_SOC_IMX_SPDIF select SND_SOC_IMX_PCM_DMA select SND_SOC_FSL_SPDIF select SND_SOC_SPDIF + select REGMAP_MMIO help SoC Audio support for i.MX boards with S/PDIF Say Y if you want to add support for SoC audio on an i.MX board with diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index ab17381..d3bf71a 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -335,7 +335,8 @@ static int imx_audmux_probe(struct platform_device *pdev) if (audmux_type == IMX31_AUDMUX) audmux_debugfs_init(); - imx_audmux_parse_dt_defaults(pdev, pdev->dev.of_node); + if (of_id) + imx_audmux_parse_dt_defaults(pdev, pdev->dev.of_node); return 0; } diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index 389cbfa..ca1be1d 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -13,7 +13,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_platform.h> -#include <linux/of_i2c.h> +#include <linux/i2c.h> #include <linux/clk.h> #include <sound/soc.h> @@ -62,7 +62,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) struct device_node *ssi_np, *codec_np; struct platform_device *ssi_pdev; struct i2c_client *codec_dev; - struct imx_sgtl5000_data *data; + struct imx_sgtl5000_data *data = NULL; int int_port, ext_port; int ret; @@ -128,7 +128,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) goto fail; } - data->codec_clk = devm_clk_get(&codec_dev->dev, NULL); + data->codec_clk = clk_get(&codec_dev->dev, NULL); if (IS_ERR(data->codec_clk)) { ret = PTR_ERR(data->codec_clk); goto fail; @@ -172,6 +172,8 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) return 0; fail: + if (data && !IS_ERR(data->codec_clk)) + clk_put(data->codec_clk); if (ssi_np) of_node_put(ssi_np); if (codec_np) @@ -185,6 +187,7 @@ static int imx_sgtl5000_remove(struct platform_device *pdev) struct imx_sgtl5000_data *data = platform_get_drvdata(pdev); snd_soc_unregister_card(&data->card); + clk_put(data->codec_clk); return 0; } diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c index 1d70e27..722afe6 100644 --- a/sound/soc/fsl/imx-wm8962.c +++ b/sound/soc/fsl/imx-wm8962.c @@ -15,7 +15,7 @@ #include <linux/module.h> #include <linux/of_platform.h> -#include <linux/of_i2c.h> +#include <linux/i2c.h> #include <linux/slab.h> #include <linux/clk.h> #include <sound/soc.h> diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 7fce340..0f3d73d 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c @@ -559,7 +559,8 @@ static int kirkwood_i2s_dev_remove(struct platform_device *pdev) #ifdef CONFIG_OF static struct of_device_id mvebu_audio_of_match[] = { - { .compatible = "marvell,mvebu-audio" }, + { .compatible = "marvell,kirkwood-audio" }, + { .compatible = "marvell,dove-audio" }, { } }; MODULE_DEVICE_TABLE(of, mvebu_audio_of_match); diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 9855dfc..2eea184 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -63,7 +63,7 @@ config SND_SOC_SAMSUNG_SMDK_WM8580 config SND_SOC_SAMSUNG_SMDK_WM8994 tristate "SoC I2S Audio support for WM8994 on SMDK" depends on SND_SOC_SAMSUNG - depends on I2C=y && GENERIC_HARDIRQS + depends on I2C=y select MFD_WM8994 select SND_SOC_WM8994 select SND_SAMSUNG_I2S @@ -151,7 +151,7 @@ config SND_SOC_SMARTQ config SND_SOC_GONI_AQUILA_WM8994 tristate "SoC I2S Audio support for AQUILA/GONI - WM8994" depends on SND_SOC_SAMSUNG && (MACH_GONI || MACH_AQUILA) - depends on I2C=y && GENERIC_HARDIRQS + depends on I2C=y select SND_SAMSUNG_I2S select MFD_WM8994 select SND_SOC_WM8994 @@ -177,7 +177,7 @@ config SND_SOC_SMDK_WM8580_PCM config SND_SOC_SMDK_WM8994_PCM tristate "SoC PCM Audio support for WM8994 on SMDK" depends on SND_SOC_SAMSUNG - depends on I2C=y && GENERIC_HARDIRQS + depends on I2C=y select MFD_WM8994 select SND_SOC_WM8994 select SND_SAMSUNG_PCM diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 184d9008..2df2e91 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -157,9 +157,9 @@ static int rsnd_scu_start(struct rsnd_mod *mod, int ret; /* - * SCU will be used if it has RSND_SCU_USB_HPBIF flags + * SCU will be used if it has RSND_SCU_USE_HPBIF flags */ - if (!(flags & RSND_SCU_USB_HPBIF)) { + if (!(flags & RSND_SCU_USE_HPBIF)) { /* it use PIO transter */ dev_dbg(dev, "%s%d is not used\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4d05613..1a38be0 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1380,7 +1380,6 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) return -ENODEV; list_add(&cpu_dai->dapm.list, &card->dapm_list); - snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai); } if (cpu_dai->driver->probe) { diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index 8ca9ecc..122c0c1 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c @@ -158,7 +158,7 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, return -EINVAL; } - return PTR_RET(codec->control_data); + return PTR_ERR_OR_ZERO(codec->control_data); } EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); #else |