ALSA: fm801: convert TEA575x support to new interface
authorOndrej Zary <linux@rainbow-software.org>
Mon, 9 May 2011 21:39:51 +0000 (23:39 +0200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 10 May 2011 07:31:45 +0000 (09:31 +0200)
Use common functions to access TEA575x tuner - remove original read/write
functions and provide new pin manipulation functions instead.

Also convert the original triple implementation to a simple GPIO pin map.

Tested with SF256-PCP and SF64-PCR (added the GPIO pin for MO/ST signal
for them).
SF256-PCS untested (pin for MO/ST signal is a guess).

Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/fm801.c

index f4dc1c77202b2c4c819e68f80d27f36d8f4934c1..1db5ead62a9824c147b071193a1787815e9c5343 100644 (file)
@@ -717,308 +717,86 @@ static int __devinit snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pc
 
 #ifdef TEA575X_RADIO
 
-/* 256PCS GPIO numbers */
-#define TEA_256PCS_DATA                        1
-#define TEA_256PCS_WRITE_ENABLE                2       /* inverted */
-#define TEA_256PCS_BUS_CLOCK           3
-
-static void snd_fm801_tea575x_256pcs_write(struct snd_tea575x *tea, unsigned int val)
-{
-       struct fm801 *chip = tea->private_data;
-       unsigned short reg;
-       int i = 25;
-
-       spin_lock_irq(&chip->reg_lock);
-       reg = inw(FM801_REG(chip, GPIO_CTRL));
-       /* use GPIO lines and set write enable bit */
-       reg |= FM801_GPIO_GS(TEA_256PCS_DATA) |
-              FM801_GPIO_GS(TEA_256PCS_WRITE_ENABLE) |
-              FM801_GPIO_GS(TEA_256PCS_BUS_CLOCK);
-       /* all of lines are in the write direction */
-       /* clear data and clock lines */
-       reg &= ~(FM801_GPIO_GD(TEA_256PCS_DATA) |
-                FM801_GPIO_GD(TEA_256PCS_WRITE_ENABLE) |
-                FM801_GPIO_GD(TEA_256PCS_BUS_CLOCK) |
-                FM801_GPIO_GP(TEA_256PCS_DATA) |
-                FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK) |
-                FM801_GPIO_GP(TEA_256PCS_WRITE_ENABLE));
-       outw(reg, FM801_REG(chip, GPIO_CTRL));
-       udelay(1);
-
-       while (i--) {
-               if (val & (1 << i))
-                       reg |= FM801_GPIO_GP(TEA_256PCS_DATA);
-               else
-                       reg &= ~FM801_GPIO_GP(TEA_256PCS_DATA);
-               outw(reg, FM801_REG(chip, GPIO_CTRL));
-               udelay(1);
-               reg |= FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK);
-               outw(reg, FM801_REG(chip, GPIO_CTRL));
-               reg &= ~FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK);
-               outw(reg, FM801_REG(chip, GPIO_CTRL));
-               udelay(1);
-       }
+/* GPIO to TEA575x maps */
+struct snd_fm801_tea575x_gpio {
+       u8 data, clk, wren, most;
+};
 
-       /* and reset the write enable bit */
-       reg |= FM801_GPIO_GP(TEA_256PCS_WRITE_ENABLE) |
-              FM801_GPIO_GP(TEA_256PCS_DATA);
-       outw(reg, FM801_REG(chip, GPIO_CTRL));
-       spin_unlock_irq(&chip->reg_lock);
-}
+static struct snd_fm801_tea575x_gpio snd_fm801_tea575x_gpios[] = {
+       { .data = 1, .clk = 3, .wren = 2, .most = 0 },  /* SF256-PCS */
+       { .data = 1, .clk = 0, .wren = 2, .most = 3 },  /* SF256-PCP */
+       { .data = 2, .clk = 0, .wren = 1, .most = 3 },  /* SF64-PCR */
+};
 
-static unsigned int snd_fm801_tea575x_256pcs_read(struct snd_tea575x *tea)
+static void snd_fm801_tea575x_set_pins(struct snd_tea575x *tea, u8 pins)
 {
        struct fm801 *chip = tea->private_data;
-       unsigned short reg;
-       unsigned int val = 0;
-       int i;
-       
-       spin_lock_irq(&chip->reg_lock);
-       reg = inw(FM801_REG(chip, GPIO_CTRL));
-       /* use GPIO lines, set data direction to input */
-       reg |= FM801_GPIO_GS(TEA_256PCS_DATA) |
-              FM801_GPIO_GS(TEA_256PCS_WRITE_ENABLE) |
-              FM801_GPIO_GS(TEA_256PCS_BUS_CLOCK) |
-              FM801_GPIO_GD(TEA_256PCS_DATA) |
-              FM801_GPIO_GP(TEA_256PCS_DATA) |
-              FM801_GPIO_GP(TEA_256PCS_WRITE_ENABLE);
-       /* all of lines are in the write direction, except data */
-       /* clear data, write enable and clock lines */
-       reg &= ~(FM801_GPIO_GD(TEA_256PCS_WRITE_ENABLE) |
-                FM801_GPIO_GD(TEA_256PCS_BUS_CLOCK) |
-                FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK));
-
-       for (i = 0; i < 24; i++) {
-               reg &= ~FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK);
-               outw(reg, FM801_REG(chip, GPIO_CTRL));
-               udelay(1);
-               reg |= FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK);
-               outw(reg, FM801_REG(chip, GPIO_CTRL));
-               udelay(1);
-               val <<= 1;
-               if (inw(FM801_REG(chip, GPIO_CTRL)) & FM801_GPIO_GP(TEA_256PCS_DATA))
-                       val |= 1;
-       }
-
-       spin_unlock_irq(&chip->reg_lock);
-
-       return val;
-}
-
-/* 256PCPR GPIO numbers */
-#define TEA_256PCPR_BUS_CLOCK          0
-#define TEA_256PCPR_DATA               1
-#define TEA_256PCPR_WRITE_ENABLE       2       /* inverted */
+       unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL));
+       struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1];
 
-static void snd_fm801_tea575x_256pcpr_write(struct snd_tea575x *tea, unsigned int val)
-{
-       struct fm801 *chip = tea->private_data;
-       unsigned short reg;
-       int i = 25;
+       reg &= ~(FM801_GPIO_GP(gpio.data) |
+                FM801_GPIO_GP(gpio.clk) |
+                FM801_GPIO_GP(gpio.wren));
 
-       spin_lock_irq(&chip->reg_lock);
-       reg = inw(FM801_REG(chip, GPIO_CTRL));
-       /* use GPIO lines and set write enable bit */
-       reg |= FM801_GPIO_GS(TEA_256PCPR_DATA) |
-              FM801_GPIO_GS(TEA_256PCPR_WRITE_ENABLE) |
-              FM801_GPIO_GS(TEA_256PCPR_BUS_CLOCK);
-       /* all of lines are in the write direction */
-       /* clear data and clock lines */
-       reg &= ~(FM801_GPIO_GD(TEA_256PCPR_DATA) |
-                FM801_GPIO_GD(TEA_256PCPR_WRITE_ENABLE) |
-                FM801_GPIO_GD(TEA_256PCPR_BUS_CLOCK) |
-                FM801_GPIO_GP(TEA_256PCPR_DATA) |
-                FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK) |
-                FM801_GPIO_GP(TEA_256PCPR_WRITE_ENABLE));
-       outw(reg, FM801_REG(chip, GPIO_CTRL));
-       udelay(1);
-
-       while (i--) {
-               if (val & (1 << i))
-                       reg |= FM801_GPIO_GP(TEA_256PCPR_DATA);
-               else
-                       reg &= ~FM801_GPIO_GP(TEA_256PCPR_DATA);
-               outw(reg, FM801_REG(chip, GPIO_CTRL));
-               udelay(1);
-               reg |= FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK);
-               outw(reg, FM801_REG(chip, GPIO_CTRL));
-               reg &= ~FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK);
-               outw(reg, FM801_REG(chip, GPIO_CTRL));
-               udelay(1);
-       }
+       reg |= (pins & TEA575X_DATA) ? FM801_GPIO_GP(gpio.data) : 0;
+       reg |= (pins & TEA575X_CLK)  ? FM801_GPIO_GP(gpio.clk) : 0;
+       /* WRITE_ENABLE is inverted */
+       reg |= (pins & TEA575X_WREN) ? 0 : FM801_GPIO_GP(gpio.wren);
 
-       /* and reset the write enable bit */
-       reg |= FM801_GPIO_GP(TEA_256PCPR_WRITE_ENABLE) |
-              FM801_GPIO_GP(TEA_256PCPR_DATA);
        outw(reg, FM801_REG(chip, GPIO_CTRL));
-       spin_unlock_irq(&chip->reg_lock);
 }
 
-static unsigned int snd_fm801_tea575x_256pcpr_read(struct snd_tea575x *tea)
+static u8 snd_fm801_tea575x_get_pins(struct snd_tea575x *tea)
 {
        struct fm801 *chip = tea->private_data;
-       unsigned short reg;
-       unsigned int val = 0;
-       int i;
-       
-       spin_lock_irq(&chip->reg_lock);
-       reg = inw(FM801_REG(chip, GPIO_CTRL));
-       /* use GPIO lines, set data direction to input */
-       reg |= FM801_GPIO_GS(TEA_256PCPR_DATA) |
-              FM801_GPIO_GS(TEA_256PCPR_WRITE_ENABLE) |
-              FM801_GPIO_GS(TEA_256PCPR_BUS_CLOCK) |
-              FM801_GPIO_GD(TEA_256PCPR_DATA) |
-              FM801_GPIO_GP(TEA_256PCPR_DATA) |
-              FM801_GPIO_GP(TEA_256PCPR_WRITE_ENABLE);
-       /* all of lines are in the write direction, except data */
-       /* clear data, write enable and clock lines */
-       reg &= ~(FM801_GPIO_GD(TEA_256PCPR_WRITE_ENABLE) |
-                FM801_GPIO_GD(TEA_256PCPR_BUS_CLOCK) |
-                FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK));
-
-       for (i = 0; i < 24; i++) {
-               reg &= ~FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK);
-               outw(reg, FM801_REG(chip, GPIO_CTRL));
-               udelay(1);
-               reg |= FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK);
-               outw(reg, FM801_REG(chip, GPIO_CTRL));
-               udelay(1);
-               val <<= 1;
-               if (inw(FM801_REG(chip, GPIO_CTRL)) & FM801_GPIO_GP(TEA_256PCPR_DATA))
-                       val |= 1;
-       }
-
-       spin_unlock_irq(&chip->reg_lock);
+       unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL));
+       struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1];
 
-       return val;
+       return  (reg & FM801_GPIO_GP(gpio.data)) ? TEA575X_DATA : 0 |
+               (reg & FM801_GPIO_GP(gpio.most)) ? TEA575X_MOST : 0;
 }
 
-/* 64PCR GPIO numbers */
-#define TEA_64PCR_BUS_CLOCK            0
-#define TEA_64PCR_WRITE_ENABLE         1       /* inverted */
-#define TEA_64PCR_DATA                 2
-
-static void snd_fm801_tea575x_64pcr_write(struct snd_tea575x *tea, unsigned int val)
+static void snd_fm801_tea575x_set_direction(struct snd_tea575x *tea, bool output)
 {
        struct fm801 *chip = tea->private_data;
-       unsigned short reg;
-       int i = 25;
+       unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL));
+       struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1];
 
-       spin_lock_irq(&chip->reg_lock);
-       reg = inw(FM801_REG(chip, GPIO_CTRL));
        /* use GPIO lines and set write enable bit */
-       reg |= FM801_GPIO_GS(TEA_64PCR_DATA) |
-              FM801_GPIO_GS(TEA_64PCR_WRITE_ENABLE) |
-              FM801_GPIO_GS(TEA_64PCR_BUS_CLOCK);
-       /* all of lines are in the write direction */
-       /* clear data and clock lines */
-       reg &= ~(FM801_GPIO_GD(TEA_64PCR_DATA) |
-                FM801_GPIO_GD(TEA_64PCR_WRITE_ENABLE) |
-                FM801_GPIO_GD(TEA_64PCR_BUS_CLOCK) |
-                FM801_GPIO_GP(TEA_64PCR_DATA) |
-                FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK) |
-                FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE));
-       outw(reg, FM801_REG(chip, GPIO_CTRL));
-       udelay(1);
-
-       while (i--) {
-               if (val & (1 << i))
-                       reg |= FM801_GPIO_GP(TEA_64PCR_DATA);
-               else
-                       reg &= ~FM801_GPIO_GP(TEA_64PCR_DATA);
-               outw(reg, FM801_REG(chip, GPIO_CTRL));
-               udelay(1);
-               reg |= FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK);
-               outw(reg, FM801_REG(chip, GPIO_CTRL));
-               reg &= ~FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK);
-               outw(reg, FM801_REG(chip, GPIO_CTRL));
-               udelay(1);
-       }
-
-       /* and reset the write enable bit */
-       reg |= FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE) |
-              FM801_GPIO_GP(TEA_64PCR_DATA);
-       outw(reg, FM801_REG(chip, GPIO_CTRL));
-       spin_unlock_irq(&chip->reg_lock);
-}
-
-static unsigned int snd_fm801_tea575x_64pcr_read(struct snd_tea575x *tea)
-{
-       struct fm801 *chip = tea->private_data;
-       unsigned short reg;
-       unsigned int val = 0;
-       int i;
-       
-       spin_lock_irq(&chip->reg_lock);
-       reg = inw(FM801_REG(chip, GPIO_CTRL));
-       /* use GPIO lines, set data direction to input */
-       reg |= FM801_GPIO_GS(TEA_64PCR_DATA) |
-              FM801_GPIO_GS(TEA_64PCR_WRITE_ENABLE) |
-              FM801_GPIO_GS(TEA_64PCR_BUS_CLOCK) |
-              FM801_GPIO_GD(TEA_64PCR_DATA) |
-              FM801_GPIO_GP(TEA_64PCR_DATA) |
-              FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE);
-       /* all of lines are in the write direction, except data */
-       /* clear data, write enable and clock lines */
-       reg &= ~(FM801_GPIO_GD(TEA_64PCR_WRITE_ENABLE) |
-                FM801_GPIO_GD(TEA_64PCR_BUS_CLOCK) |
-                FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK));
-
-       for (i = 0; i < 24; i++) {
-               reg &= ~FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK);
-               outw(reg, FM801_REG(chip, GPIO_CTRL));
-               udelay(1);
-               reg |= FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK);
-               outw(reg, FM801_REG(chip, GPIO_CTRL));
-               udelay(1);
-               val <<= 1;
-               if (inw(FM801_REG(chip, GPIO_CTRL)) & FM801_GPIO_GP(TEA_64PCR_DATA))
-                       val |= 1;
+       reg |= FM801_GPIO_GS(gpio.data) |
+              FM801_GPIO_GS(gpio.wren) |
+              FM801_GPIO_GS(gpio.clk) |
+              FM801_GPIO_GS(gpio.most);
+       if (output) {
+               /* all of lines are in the write direction */
+               /* clear data and clock lines */
+               reg &= ~(FM801_GPIO_GD(gpio.data) |
+                        FM801_GPIO_GD(gpio.wren) |
+                        FM801_GPIO_GD(gpio.clk) |
+                        FM801_GPIO_GP(gpio.data) |
+                        FM801_GPIO_GP(gpio.clk) |
+                        FM801_GPIO_GP(gpio.wren));
+       } else {
+               /* use GPIO lines, set data direction to input */
+               reg |= FM801_GPIO_GD(gpio.data) |
+                      FM801_GPIO_GD(gpio.most) |
+                      FM801_GPIO_GP(gpio.data) |
+                      FM801_GPIO_GP(gpio.most) |
+                      FM801_GPIO_GP(gpio.wren);
+               /* all of lines are in the write direction, except data */
+               /* clear data, write enable and clock lines */
+               reg &= ~(FM801_GPIO_GD(gpio.wren) |
+                        FM801_GPIO_GD(gpio.clk) |
+                        FM801_GPIO_GP(gpio.clk));
        }
 
-       spin_unlock_irq(&chip->reg_lock);
-
-       return val;
-}
-
-static void snd_fm801_tea575x_64pcr_mute(struct snd_tea575x *tea,
-                                         unsigned int mute)
-{
-       struct fm801 *chip = tea->private_data;
-       unsigned short reg;
-
-       spin_lock_irq(&chip->reg_lock);
-
-       reg = inw(FM801_REG(chip, GPIO_CTRL));
-       if (mute)
-               /* 0xf800 (mute) */
-               reg &= ~FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE);
-       else
-               /* 0xf802 (unmute) */
-               reg |= FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE);
        outw(reg, FM801_REG(chip, GPIO_CTRL));
-       udelay(1);
-
-       spin_unlock_irq(&chip->reg_lock);
 }
 
-static struct snd_tea575x_ops snd_fm801_tea_ops[3] = {
-       {
-               /* 1 = MediaForte 256-PCS */
-               .write = snd_fm801_tea575x_256pcs_write,
-               .read = snd_fm801_tea575x_256pcs_read,
-       },
-       {
-               /* 2 = MediaForte 256-PCPR */
-               .write = snd_fm801_tea575x_256pcpr_write,
-               .read = snd_fm801_tea575x_256pcpr_read,
-       },
-       {
-               /* 3 = MediaForte 64-PCR */
-               .write = snd_fm801_tea575x_64pcr_write,
-               .read = snd_fm801_tea575x_64pcr_read,
-               .mute = snd_fm801_tea575x_64pcr_mute,
-       }
+static struct snd_tea575x_ops snd_fm801_tea_ops = {
+       .set_pins = snd_fm801_tea575x_set_pins,
+       .get_pins = snd_fm801_tea575x_get_pins,
+       .set_direction = snd_fm801_tea575x_set_direction,
 };
 #endif
 
@@ -1456,7 +1234,7 @@ static int __devinit snd_fm801_create(struct snd_card *card,
                chip->tea.card = card;
                chip->tea.freq_fixup = 10700;
                chip->tea.private_data = chip;
-               chip->tea.ops = &snd_fm801_tea_ops[(tea575x_tuner & TUNER_TYPE_MASK) - 1];
+               chip->tea.ops = &snd_fm801_tea_ops;
                snd_tea575x_init(&chip->tea);
        }
 #endif