|
@@ -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
|