]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - sound/pci/es1968.c
Merge tag 'omap-for-v3.11/fixes-for-merge-window' of git://git.kernel.org/pub/scm...
[karo-tx-linux.git] / sound / pci / es1968.c
index a1f32b5ae0d1b4131a7ba7b9a8d2366bfd959e3d..5e2ec9687731119d80ebc5994b2bdb8fcec06c0d 100644 (file)
@@ -564,6 +564,7 @@ struct es1968 {
 #ifdef CONFIG_SND_ES1968_RADIO
        struct v4l2_device v4l2_dev;
        struct snd_tea575x tea;
+       unsigned int tea575x_tuner;
 #endif
 };
 
@@ -2557,37 +2558,47 @@ static int snd_es1968_input_register(struct es1968 *chip)
                                bits 1=unmask write to given bit */
 #define IO_DIR         8      /* direction register offset from GPIO_DATA
                                bits 0/1=read/write direction */
-/* mask bits for GPIO lines */
-#define STR_DATA       0x0040 /* GPIO6 */
-#define STR_CLK                0x0080 /* GPIO7 */
-#define STR_WREN       0x0100 /* GPIO8 */
-#define STR_MOST       0x0200 /* GPIO9 */
+
+/* GPIO to TEA575x maps */
+struct snd_es1968_tea575x_gpio {
+       u8 data, clk, wren, most;
+       char *name;
+};
+
+static struct snd_es1968_tea575x_gpio snd_es1968_tea575x_gpios[] = {
+       { .data = 6, .clk = 7, .wren = 8, .most = 9, .name = "SF64-PCE2" },
+       { .data = 7, .clk = 8, .wren = 6, .most = 10, .name = "M56VAP" },
+};
+
+#define get_tea575x_gpio(chip) \
+       (&snd_es1968_tea575x_gpios[(chip)->tea575x_tuner])
+
 
 static void snd_es1968_tea575x_set_pins(struct snd_tea575x *tea, u8 pins)
 {
        struct es1968 *chip = tea->private_data;
-       unsigned long io = chip->io_port + GPIO_DATA;
+       struct snd_es1968_tea575x_gpio gpio = *get_tea575x_gpio(chip);
        u16 val = 0;
 
-       val |= (pins & TEA575X_DATA) ? STR_DATA : 0;
-       val |= (pins & TEA575X_CLK)  ? STR_CLK  : 0;
-       val |= (pins & TEA575X_WREN) ? STR_WREN : 0;
+       val |= (pins & TEA575X_DATA) ? (1 << gpio.data) : 0;
+       val |= (pins & TEA575X_CLK)  ? (1 << gpio.clk)  : 0;
+       val |= (pins & TEA575X_WREN) ? (1 << gpio.wren) : 0;
 
-       outw(val, io);
+       outw(val, chip->io_port + GPIO_DATA);
 }
 
 static u8 snd_es1968_tea575x_get_pins(struct snd_tea575x *tea)
 {
        struct es1968 *chip = tea->private_data;
-       unsigned long io = chip->io_port + GPIO_DATA;
-       u16 val = inw(io);
-       u8 ret;
+       struct snd_es1968_tea575x_gpio gpio = *get_tea575x_gpio(chip);
+       u16 val = inw(chip->io_port + GPIO_DATA);
+       u8 ret = 0;
 
-       ret = 0;
-       if (val & STR_DATA)
+       if (val & (1 << gpio.data))
                ret |= TEA575X_DATA;
-       if (val & STR_MOST)
+       if (val & (1 << gpio.most))
                ret |= TEA575X_MOST;
+
        return ret;
 }
 
@@ -2596,13 +2607,18 @@ static void snd_es1968_tea575x_set_direction(struct snd_tea575x *tea, bool outpu
        struct es1968 *chip = tea->private_data;
        unsigned long io = chip->io_port + GPIO_DATA;
        u16 odir = inw(io + IO_DIR);
+       struct snd_es1968_tea575x_gpio gpio = *get_tea575x_gpio(chip);
 
        if (output) {
-               outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK);
-               outw(odir | STR_DATA | STR_CLK | STR_WREN, io + IO_DIR);
+               outw(~((1 << gpio.data) | (1 << gpio.clk) | (1 << gpio.wren)),
+                       io + IO_MASK);
+               outw(odir | (1 << gpio.data) | (1 << gpio.clk) | (1 << gpio.wren),
+                       io + IO_DIR);
        } else {
-               outw(~(STR_CLK | STR_WREN | STR_DATA | STR_MOST), io + IO_MASK);
-               outw((odir & ~(STR_DATA | STR_MOST)) | STR_CLK | STR_WREN, io + IO_DIR);
+               outw(~((1 << gpio.clk) | (1 << gpio.wren) | (1 << gpio.data) | (1 << gpio.most)),
+                       io + IO_MASK);
+               outw((odir & ~((1 << gpio.data) | (1 << gpio.most)))
+                       | (1 << gpio.clk) | (1 << gpio.wren), io + IO_DIR);
        }
 }
 
@@ -2772,6 +2788,9 @@ static int snd_es1968_create(struct snd_card *card,
        snd_card_set_dev(card, &pci->dev);
 
 #ifdef CONFIG_SND_ES1968_RADIO
+       /* don't play with GPIOs on laptops */
+       if (chip->pci->subsystem_vendor != 0x125d)
+               goto no_radio;
        err = v4l2_device_register(&pci->dev, &chip->v4l2_dev);
        if (err < 0) {
                snd_es1968_free(chip);
@@ -2781,10 +2800,18 @@ static int snd_es1968_create(struct snd_card *card,
        chip->tea.private_data = chip;
        chip->tea.radio_nr = radio_nr;
        chip->tea.ops = &snd_es1968_tea_ops;
-       strlcpy(chip->tea.card, "SF64-PCE2", sizeof(chip->tea.card));
        sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci));
-       if (!snd_tea575x_init(&chip->tea, THIS_MODULE))
-               printk(KERN_INFO "es1968: detected TEA575x radio\n");
+       for (i = 0; i < ARRAY_SIZE(snd_es1968_tea575x_gpios); i++) {
+               chip->tea575x_tuner = i;
+               if (!snd_tea575x_init(&chip->tea, THIS_MODULE)) {
+                       snd_printk(KERN_INFO "es1968: detected TEA575x radio type %s\n",
+                                  get_tea575x_gpio(chip)->name);
+                       strlcpy(chip->tea.card, get_tea575x_gpio(chip)->name,
+                               sizeof(chip->tea.card));
+                       break;
+               }
+       }
+no_radio:
 #endif
 
        *chip_ret = chip;
@@ -2909,7 +2936,6 @@ static int snd_es1968_probe(struct pci_dev *pci,
 static void snd_es1968_remove(struct pci_dev *pci)
 {
        snd_card_free(pci_get_drvdata(pci));
-       pci_set_drvdata(pci, NULL);
 }
 
 static struct pci_driver es1968_driver = {