Commit c488eef8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
  ALSA: hda - Make jack-plug notification selectable
  ALSA: ctxfi - Add PM support
  sound: seq_midi_event: fix decoding of (N)RPN events
  ALSA: hda - Add digital-mic support to ALC262 auto model
  ALSA: hda - Fix check of input source type for realtek codecs
  ALSA: hda - Add quirk for Sony VAIO Z21MN
  ALSA: hda - Get back Input Source for ALC262 toshiba-s06 model
  ALSA: hda - Fix unsigned comparison in patch_sigmatel.c
  ALSA: via82xx: add option to disable 500ms delay in snd_via82xx_codec_wait
  sound: fix check for return value in snd_pcm_hw_refine
  ALSA: ctxfi - Allow unknown PCI SSIDs
  ASoC: Blackfin: update the bf5xx_i2s_resume parameters
  ASoC: Blackfin: keep better track of SPORT configuration state
parents cf9c1b92 3f67f669
......@@ -320,7 +320,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
snd_mask_max(&params->masks[SNDRV_PCM_HW_PARAM_CHANNELS])) {
changed = substream->ops->ioctl(substream,
SNDRV_PCM_IOCTL1_FIFO_SIZE, params);
if (params < 0)
if (changed < 0)
return changed;
}
}
......
......@@ -504,10 +504,10 @@ static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf,
if (dev->nostat && count < 12)
return -ENOMEM;
cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f);
bytes[0] = ev->data.control.param & 0x007f;
bytes[1] = (ev->data.control.param & 0x3f80) >> 7;
bytes[2] = ev->data.control.value & 0x007f;
bytes[3] = (ev->data.control.value & 0x3f80) >> 7;
bytes[0] = (ev->data.control.param & 0x3f80) >> 7;
bytes[1] = ev->data.control.param & 0x007f;
bytes[2] = (ev->data.control.value & 0x3f80) >> 7;
bytes[3] = ev->data.control.value & 0x007f;
if (cmd != dev->lastcmd && !dev->nostat) {
if (count < 9)
return -ENOMEM;
......
......@@ -46,8 +46,6 @@ static struct snd_pci_quirk __devinitdata subsys_20k1_list[] = {
SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0031, "SB073x", CTSB073X),
SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_CREATIVE, 0xf000, 0x6000,
"UAA", CTUAA),
SND_PCI_QUIRK_VENDOR(PCI_VENDOR_ID_CREATIVE,
"Unknown", CT20K1_UNKNOWN),
{ } /* terminator */
};
......@@ -67,13 +65,16 @@ static struct snd_pci_quirk __devinitdata subsys_20k2_list[] = {
};
static const char *ct_subsys_name[NUM_CTCARDS] = {
/* 20k1 models */
[CTSB055X] = "SB055x",
[CTSB073X] = "SB073x",
[CTSB0760] = "SB076x",
[CTUAA] = "UAA",
[CT20K1_UNKNOWN] = "Unknown",
/* 20k2 models */
[CTSB0760] = "SB076x",
[CTHENDRIX] = "Hendrix",
[CTSB0880] = "SB0880",
[CT20K2_UNKNOWN] = "Unknown",
};
static struct {
......@@ -260,13 +261,8 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
int device = apcm->substream->pcm->device;
unsigned int pitch;
if (NULL != apcm->src) {
/* Prepared pcm playback */
return 0;
}
/* first release old resources */
atc->pcm_release_resources(atc, apcm);
atc_pcm_release_resources(atc, apcm);
/* Get SRC resource */
desc.multi = apcm->substream->runtime->channels;
......@@ -660,10 +656,7 @@ static int atc_pcm_capture_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
unsigned int pitch;
int mix_base = 0, imp_base = 0;
if (NULL != apcm->src) {
/* Prepared pcm capture */
return 0;
}
atc_pcm_release_resources(atc, apcm);
/* Get needed resources. */
err = atc_pcm_capture_get_resources(atc, apcm);
......@@ -866,7 +859,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
unsigned int rate = apcm->substream->runtime->rate;
unsigned int status;
int err;
int err = 0;
unsigned char iec958_con_fs;
switch (rate) {
......@@ -907,8 +900,7 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
int err;
int i;
if (NULL != apcm->src)
return 0;
atc_pcm_release_resources(atc, apcm);
/* Configure SPDIFOO and PLL to passthrough mode;
* determine pll_rate. */
......@@ -1115,32 +1107,20 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)
return err;
}
static int ct_atc_destroy(struct ct_atc *atc)
static int atc_release_resources(struct ct_atc *atc)
{
struct daio_mgr *daio_mgr;
struct dao *dao;
struct dai *dai;
struct daio *daio;
struct sum_mgr *sum_mgr;
struct src_mgr *src_mgr;
struct srcimp_mgr *srcimp_mgr;
struct srcimp *srcimp;
struct ct_mixer *mixer;
int i = 0;
if (NULL == atc)
return 0;
if (atc->timer) {
ct_timer_free(atc->timer);
atc->timer = NULL;
}
/* Stop hardware and disable all interrupts */
if (NULL != atc->hw)
((struct hw *)atc->hw)->card_stop(atc->hw);
/* Destroy internal mixer objects */
int i;
struct daio_mgr *daio_mgr = NULL;
struct dao *dao = NULL;
struct dai *dai = NULL;
struct daio *daio = NULL;
struct sum_mgr *sum_mgr = NULL;
struct src_mgr *src_mgr = NULL;
struct srcimp_mgr *srcimp_mgr = NULL;
struct srcimp *srcimp = NULL;
struct ct_mixer *mixer = NULL;
/* disconnect internal mixer objects */
if (NULL != atc->mixer) {
mixer = atc->mixer;
mixer->set_input_left(mixer, MIX_LINE_IN, NULL);
......@@ -1149,7 +1129,6 @@ static int ct_atc_destroy(struct ct_atc *atc)
mixer->set_input_right(mixer, MIX_MIC_IN, NULL);
mixer->set_input_left(mixer, MIX_SPDIF_IN, NULL);
mixer->set_input_right(mixer, MIX_SPDIF_IN, NULL);
ct_mixer_destroy(atc->mixer);
}
if (NULL != atc->daios) {
......@@ -1167,6 +1146,7 @@ static int ct_atc_destroy(struct ct_atc *atc)
daio_mgr->put_daio(daio_mgr, daio);
}
kfree(atc->daios);
atc->daios = NULL;
}
if (NULL != atc->pcm) {
......@@ -1175,6 +1155,7 @@ static int ct_atc_destroy(struct ct_atc *atc)
sum_mgr->put_sum(sum_mgr, atc->pcm[i]);
kfree(atc->pcm);
atc->pcm = NULL;
}
if (NULL != atc->srcs) {
......@@ -1183,6 +1164,7 @@ static int ct_atc_destroy(struct ct_atc *atc)
src_mgr->put_src(src_mgr, atc->srcs[i]);
kfree(atc->srcs);
atc->srcs = NULL;
}
if (NULL != atc->srcimps) {
......@@ -1193,8 +1175,30 @@ static int ct_atc_destroy(struct ct_atc *atc)
srcimp_mgr->put_srcimp(srcimp_mgr, atc->srcimps[i]);
}
kfree(atc->srcimps);
atc->srcimps = NULL;
}
return 0;
}
static int ct_atc_destroy(struct ct_atc *atc)
{
int i = 0;
if (NULL == atc)
return 0;
if (atc->timer) {
ct_timer_free(atc->timer);
atc->timer = NULL;
}
atc_release_resources(atc);
/* Destroy internal mixer objects */
if (NULL != atc->mixer)
ct_mixer_destroy(atc->mixer);
for (i = 0; i < NUM_RSCTYP; i++) {
if ((NULL != rsc_mgr_funcs[i].destroy) &&
(NULL != atc->rsc_mgrs[i]))
......@@ -1240,9 +1244,21 @@ static int __devinit atc_identify_card(struct ct_atc *atc)
return -ENOENT;
}
p = snd_pci_quirk_lookup(atc->pci, list);
if (!p)
return -ENOENT;
atc->model = p->value;
if (p) {
if (p->value < 0) {
printk(KERN_ERR "ctxfi: "
"Device %04x:%04x is black-listed\n",
atc->pci->subsystem_vendor,
atc->pci->subsystem_device);
return -ENOENT;
}
atc->model = p->value;
} else {
if (atc->chip_type == ATC20K1)
atc->model = CT20K1_UNKNOWN;
else
atc->model = CT20K2_UNKNOWN;
}
atc->model_name = ct_subsys_name[atc->model];
snd_printd("ctxfi: chip %s model %s (%04x:%04x) is found\n",
atc->chip_name, atc->model_name,
......@@ -1310,7 +1326,7 @@ static int __devinit atc_create_hw_devs(struct ct_atc *atc)
return 0;
}
static int __devinit atc_get_resources(struct ct_atc *atc)
static int atc_get_resources(struct ct_atc *atc)
{
struct daio_desc da_desc = {0};
struct daio_mgr *daio_mgr;
......@@ -1407,16 +1423,10 @@ static int __devinit atc_get_resources(struct ct_atc *atc)
atc->n_pcm++;
}
err = ct_mixer_create(atc, (struct ct_mixer **)&atc->mixer);
if (err) {
printk(KERN_ERR "ctxfi: Failed to create mixer obj!!!\n");
return err;
}
return 0;
}
static void __devinit
static void
atc_connect_dai(struct src_mgr *src_mgr, struct dai *dai,
struct src **srcs, struct srcimp **srcimps)
{
......@@ -1455,7 +1465,7 @@ atc_connect_dai(struct src_mgr *src_mgr, struct dai *dai,
src_mgr->commit_write(src_mgr); /* Synchronously enable SRCs */
}
static void __devinit atc_connect_resources(struct ct_atc *atc)
static void atc_connect_resources(struct ct_atc *atc)
{
struct dai *dai;
struct dao *dao;
......@@ -1501,6 +1511,84 @@ static void __devinit atc_connect_resources(struct ct_atc *atc)
}
}
#ifdef CONFIG_PM
static int atc_suspend(struct ct_atc *atc, pm_message_t state)
{
int i;
struct hw *hw = atc->hw;
snd_power_change_state(atc->card, SNDRV_CTL_POWER_D3hot);
for (i = FRONT; i < NUM_PCMS; i++) {
if (!atc->pcms[i])
continue;
snd_pcm_suspend_all(atc->pcms[i]);
}
atc_release_resources(atc);
hw->suspend(hw, state);
return 0;
}
static int atc_hw_resume(struct ct_atc *atc)
{
struct hw *hw = atc->hw;
struct card_conf info = {0};
/* Re-initialize card hardware. */
info.rsr = atc->rsr;
info.msr = atc->msr;
info.vm_pgt_phys = atc_get_ptp_phys(atc, 0);
return hw->resume(hw, &info);
}
static int atc_resources_resume(struct ct_atc *atc)
{
struct ct_mixer *mixer;
int err = 0;
/* Get resources */
err = atc_get_resources(atc);
if (err < 0) {
atc_release_resources(atc);
return err;
}
/* Build topology */
atc_connect_resources(atc);
mixer = atc->mixer;
mixer->resume(mixer);
return 0;
}
static int atc_resume(struct ct_atc *atc)
{
int err = 0;
/* Do hardware resume. */
err = atc_hw_resume(atc);
if (err < 0) {
printk(KERN_ERR "ctxfi: pci_enable_device failed, "
"disabling device\n");
snd_card_disconnect(atc->card);
return err;
}
err = atc_resources_resume(atc);
if (err < 0)
return err;
snd_power_change_state(atc->card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif
static struct ct_atc atc_preset __devinitdata = {
.map_audio_buffer = ct_map_audio_buffer,
.unmap_audio_buffer = ct_unmap_audio_buffer,
......@@ -1529,6 +1617,10 @@ static struct ct_atc atc_preset __devinitdata = {
.spdif_out_set_status = atc_spdif_out_set_status,
.spdif_out_passthru = atc_spdif_out_passthru,
.have_digit_io_switch = atc_have_digit_io_switch,
#ifdef CONFIG_PM
.suspend = atc_suspend,
.resume = atc_resume,
#endif
};
/**
......@@ -1587,6 +1679,12 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
if (err < 0)
goto error1;
err = ct_mixer_create(atc, (struct ct_mixer **)&atc->mixer);
if (err) {
printk(KERN_ERR "ctxfi: Failed to create mixer obj!!!\n");
goto error1;
}
/* Get resources */
err = atc_get_resources(atc);
if (err < 0)
......
......@@ -136,6 +136,13 @@ struct ct_atc {
unsigned char n_pcm;
struct ct_timer *timer;
#ifdef CONFIG_PM
int (*suspend)(struct ct_atc *atc, pm_message_t state);
int (*resume)(struct ct_atc *atc);
#define NUM_PCMS (NUM_CTALSADEVS - 1)
struct snd_pcm *pcms[NUM_PCMS];
#endif
};
......
......@@ -30,13 +30,16 @@ enum CHIPTYP {
enum CTCARDS {
/* 20k1 models */
CTSB055X,
CT20K1_MODEL_FIRST = CTSB055X,
CTSB073X,
CTUAA,
CT20K1_UNKNOWN,
/* 20k2 models */
CTSB0760,
CT20K2_MODEL_FIRST = CTSB0760,
CTHENDRIX,
CTSB0880,
CT20K2_UNKNOWN,
NUM_CTCARDS /* This should always be the last */
};
......@@ -61,6 +64,10 @@ struct hw {
int (*card_init)(struct hw *hw, struct card_conf *info);
int (*card_stop)(struct hw *hw);
int (*pll_init)(struct hw *hw, unsigned int rsr);
#ifdef CONFIG_PM
int (*suspend)(struct hw *hw, pm_message_t state);
int (*resume)(struct hw *hw, struct card_conf *info);
#endif
int (*is_adc_source_selected)(struct hw *hw, enum ADCSRC source);
int (*select_adc_source)(struct hw *hw, enum ADCSRC source);
int (*have_digit_io_switch)(struct hw *hw);
......
......@@ -1911,9 +1911,17 @@ static int hw_card_start(struct hw *hw)
goto error1;
}
err = pci_request_regions(pci, "XFi");
if (err < 0)
goto error1;
if (!hw->io_base) {
err = pci_request_regions(pci, "XFi");
if (err < 0)
goto error1;
if (hw->model == CTUAA)
hw->io_base = pci_resource_start(pci, 5);
else
hw->io_base = pci_resource_start(pci, 0);
}
/* Switch to X-Fi mode from UAA mode if neeeded */
if (hw->model == CTUAA) {
......@@ -1921,18 +1929,17 @@ static int hw_card_start(struct hw *hw)
if (err)
goto error2;
hw->io_base = pci_resource_start(pci, 5);
} else {
hw->io_base = pci_resource_start(pci, 0);
}
err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED,
"ctxfi", hw);
if (err < 0) {
printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq);
goto error2;
if (hw->irq < 0) {
err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED,
"ctxfi", hw);
if (err < 0) {
printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq);
goto error2;
}
hw->irq = pci->irq;
}
hw->irq = pci->irq;
pci_set_master(pci);
......@@ -1948,6 +1955,15 @@ error1:
static int hw_card_stop(struct hw *hw)
{
unsigned int data;
/* disable transport bus master and queueing of request */
hw_write_20kx(hw, TRNCTL, 0x00);
/* disable pll */
data = hw_read_20kx(hw, PLLCTL);
hw_write_20kx(hw, PLLCTL, (data & (~(0x0F<<12))));
/* TODO: Disable interrupt and so on... */
if (hw->irq >= 0)
synchronize_irq(hw->irq);
......@@ -1987,11 +2003,9 @@ static int hw_card_init(struct hw *hw, struct card_conf *info)
struct trn_conf trn_info = {0};
/* Get PCI io port base address and do Hendrix switch if needed. */
if (!hw->io_base) {
err = hw_card_start(hw);
if (err)
return err;
}
err = hw_card_start(hw);
if (err)
return err;
/* PLL init */
err = hw_pll_init(hw, info->rsr);
......@@ -2064,6 +2078,37 @@ static int hw_card_init(struct hw *hw, struct card_conf *info)
return 0;
}
#ifdef CONFIG_PM
static int hw_suspend(struct hw *hw, pm_message_t state)
{
struct pci_dev *pci = hw->pci;
hw_card_stop(hw);
if (hw->model == CTUAA) {
/* Switch to UAA config space. */
pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x0);
}
pci_disable_device(pci);
pci_save_state(pci);
pci_set_power_state(pci, pci_choose_state(pci, state));
return 0;
}
static int hw_resume(struct hw *hw, struct card_conf *info)
{
struct pci_dev *pci = hw->pci;
pci_set_power_state(pci, PCI_D0);
pci_restore_state(pci);
/* Re-initialize card hardware. */
return hw_card_init(hw, info);
}
#endif
static u32 hw_read_20kx(struct hw *hw, u32 reg)
{
u32 value;
......@@ -2128,6 +2173,10 @@ static struct hw ct20k1_preset __devinitdata = {
.is_adc_source_selected = hw_is_adc_input_selected,
.select_adc_source = hw_adc_input_select,
.have_digit_io_switch = hw_have_digit_io_switch,
#ifdef CONFIG_PM
.suspend = hw_suspend,
.resume = hw_resume,
#endif
.src_rsc_get_ctrl_blk = src_get_rsc_ctrl_blk,
.src_rsc_put_ctrl_blk = src_put_rsc_ctrl_blk,
......
......@@ -1860,16 +1860,18 @@ static int hw_card_start(struct hw *hw)
goto error1;
}
err = pci_request_regions(pci, "XFi");
if (err < 0)
goto error1;
if (!hw->io_base) {
err = pci_request_regions(pci, "XFi");
if (err < 0)
goto error1;
hw->io_base = pci_resource_start(hw->pci, 2);
hw->mem_base = (unsigned long)ioremap(hw->io_base,
hw->io_base = pci_resource_start(hw->pci, 2);
hw->mem_base = (unsigned long)ioremap(hw->io_base,
pci_resource_len(hw->pci, 2));
if (NULL == (void *)hw->mem_base) {
err = -ENOENT;
goto error2;
if (NULL == (void *)hw->mem_base) {
err = -ENOENT;
goto error2;
}
}
/* Switch to 20k2 mode from UAA mode. */
......@@ -1901,6 +1903,15 @@ error1:
static int hw_card_stop(struct hw *hw)
{
unsigned int data;
/* disable transport bus master and queueing of request */
hw_write_20kx(hw, TRANSPORT_CTL, 0x00);
/* disable pll */
data = hw_read_20kx(hw, PLL_ENB);
hw_write_20kx(hw, PLL_ENB, (data & (~0x07)));
/* TODO: Disable interrupt and so on... */
return 0;
}
......@@ -1939,11 +1950,9 @@ static int hw_card_init(struct hw *hw, struct card_conf *info)
/* Get PCI io port/memory base address and
* do 20kx core switch if needed. */
if (!hw->io_base) {
err = hw_card_start(hw);
if (err)
return err;
}
err = hw_card_start(hw);
if (err)
return err;
/* PLL init */
err = hw_pll_init(hw, info->rsr);
......@@ -2006,6 +2015,32 @@ static int hw_card_init(struct hw *hw, struct card_conf *info)
return 0;
}
#ifdef CONFIG_PM
static int hw_suspend(struct hw *hw, pm_message_t state)
{
struct pci_dev *pci = hw->pci;
hw_card_stop(hw);
pci_disable_device(pci);
pci_save_state(pci);
pci_set_power_state(pci, pci_choose_state(pci, state));
return 0;
}
static int hw_resume(struct hw *hw, struct card_conf *info)
{
struct pci_dev *pci = hw->pci;
pci_set_power_state(pci, PCI_D0);
pci_restore_state(pci);
/* Re-initialize card hardware. */
return hw_card_init(hw, info);
}
#endif