Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fb716c0b authored by Ondrej Zary's avatar Ondrej Zary Committed by Takashi Iwai
Browse files

snd-fm801: autodetect SF64-PCR (tuner-only) card



When primary AC97 is not found, don't fail with tons of AC97 errors.
Assume that the card is SF64-PCR (tuner-only).
This makes the SF64-PCR radio card work "out of the box".

Also fixes a bug that can cause an oops here:
        if (tea575x_tuner > 0 && (tea575x_tuner & 0x000f) < 4) {
when tea575x_tuner == 16, it passes this check and causes problems
a couple lines below:
        chip->tea.ops = &snd_fm801_tea_ops[(tea575x_tuner & 0x000f) - 1];

Tested with SF64-PCR, but I don't have any of those sound or sound+radio cards
to test if I didn't break anything.

Signed-off-by: default avatarOndrej Zary <linux@rainbow-software.org>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 1233faa8
Loading
Loading
Loading
Loading
+27 −13
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card *
 *    1 = MediaForte 256-PCS
 *    2 = MediaForte 256-PCPR
 *    3 = MediaForte 64-PCR
 *   16 = setup tuner only (this is additional bit), i.e. SF-64-PCR FM card
 *   16 = setup tuner only (this is additional bit), i.e. SF64-PCR FM card
 *  High 16-bits are video (radio) device number + 1
 */
static int tea575x_tuner[SNDRV_CARDS];
@@ -67,7 +67,10 @@ MODULE_PARM_DESC(id, "ID string for the FM801 soundcard.");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable FM801 soundcard.");
module_param_array(tea575x_tuner, int, NULL, 0444);
MODULE_PARM_DESC(tea575x_tuner, "Enable TEA575x tuner.");
MODULE_PARM_DESC(tea575x_tuner, "TEA575x tuner access method (1 = SF256-PCS, 2=SF256-PCPR, 3=SF64-PCR, +16=tuner-only).");

#define TUNER_ONLY		(1<<4)
#define TUNER_TYPE_MASK		(~TUNER_ONLY & 0xFFFF)

/*
 *  Direct registers
@@ -160,7 +163,7 @@ struct fm801 {
	unsigned int multichannel: 1,	/* multichannel support */
		     secondary: 1;	/* secondary codec */
	unsigned char secondary_addr;	/* address of the secondary codec */
	unsigned int tea575x_tuner;	/* tuner flags */
	unsigned int tea575x_tuner;	/* tuner access method & flags */

	unsigned short ply_ctrl; /* playback control */
	unsigned short cap_ctrl; /* capture control */
@@ -1287,7 +1290,7 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume)
{
	unsigned short cmdw;

	if (chip->tea575x_tuner & 0x0010)
	if (chip->tea575x_tuner & TUNER_ONLY)
		goto __ac97_ok;

	/* codec cold reset + AC'97 warm reset */
@@ -1296,10 +1299,12 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume)
	udelay(100);
	outw(0, FM801_REG(chip, CODEC_CTRL));

	if (wait_for_codec(chip, 0, AC97_RESET, msecs_to_jiffies(750)) < 0) {
		snd_printk(KERN_ERR "Primary AC'97 codec not found\n");
		if (! resume)
			return -EIO;
	if (wait_for_codec(chip, 0, AC97_RESET, msecs_to_jiffies(750)) < 0)
		if (!resume) {
			snd_printk(KERN_INFO "Primary AC'97 codec not found, "
					    "assume SF64-PCR (tuner-only)\n");
			chip->tea575x_tuner = 3 | TUNER_ONLY;
			goto __ac97_ok;
		}

	if (chip->multichannel) {
@@ -1414,7 +1419,7 @@ static int __devinit snd_fm801_create(struct snd_card *card,
		return err;
	}
	chip->port = pci_resource_start(pci, 0);
	if ((tea575x_tuner & 0x0010) == 0) {
	if ((tea575x_tuner & TUNER_ONLY) == 0) {
		if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_SHARED,
				"FM801", chip)) {
			snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq);
@@ -1429,6 +1434,14 @@ static int __devinit snd_fm801_create(struct snd_card *card,
		chip->multichannel = 1;

	snd_fm801_chip_init(chip, 0);
	/* init might set tuner access method */
	tea575x_tuner = chip->tea575x_tuner;

	if (chip->irq >= 0 && (tea575x_tuner & TUNER_ONLY)) {
		pci_clear_master(pci);
		free_irq(chip->irq, chip);
		chip->irq = -1;
	}

	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
		snd_fm801_free(chip);
@@ -1438,12 +1451,13 @@ static int __devinit snd_fm801_create(struct snd_card *card,
	snd_card_set_dev(card, &pci->dev);

#ifdef TEA575X_RADIO
	if (tea575x_tuner > 0 && (tea575x_tuner & 0x000f) < 4) {
	if ((tea575x_tuner & TUNER_TYPE_MASK) > 0 &&
	    (tea575x_tuner & TUNER_TYPE_MASK) < 4) {
		chip->tea.dev_nr = tea575x_tuner >> 16;
		chip->tea.card = card;
		chip->tea.freq_fixup = 10700;
		chip->tea.private_data = chip;
		chip->tea.ops = &snd_fm801_tea_ops[(tea575x_tuner & 0x000f) - 1];
		chip->tea.ops = &snd_fm801_tea_ops[(tea575x_tuner & TUNER_TYPE_MASK) - 1];
		snd_tea575x_init(&chip->tea);
	}
#endif
@@ -1483,7 +1497,7 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci,
	sprintf(card->longname, "%s at 0x%lx, irq %i",
		card->shortname, chip->port, chip->irq);

	if (tea575x_tuner[dev] & 0x0010)
	if (chip->tea575x_tuner & TUNER_ONLY)
		goto __fm801_tuner_only;

	if ((err = snd_fm801_pcm(chip, 0, NULL)) < 0) {