Commit 938a1566 authored by Ondrej Zary's avatar Ondrej Zary Committed by Takashi Iwai

ALSA: fm801: convert TEA575x support to new interface

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: default avatarOndrej Zary <linux@rainbow-software.org>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 72587173
...@@ -717,308 +717,86 @@ static int __devinit snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pc ...@@ -717,308 +717,86 @@ static int __devinit snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pc
#ifdef TEA575X_RADIO #ifdef TEA575X_RADIO
/* 256PCS GPIO numbers */ /* GPIO to TEA575x maps */
#define TEA_256PCS_DATA 1 struct snd_fm801_tea575x_gpio {
#define TEA_256PCS_WRITE_ENABLE 2 /* inverted */ u8 data, clk, wren, most;
#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);
}
/* and reset the write enable bit */ static struct snd_fm801_tea575x_gpio snd_fm801_tea575x_gpios[] = {
reg |= FM801_GPIO_GP(TEA_256PCS_WRITE_ENABLE) | { .data = 1, .clk = 3, .wren = 2, .most = 0 }, /* SF256-PCS */
FM801_GPIO_GP(TEA_256PCS_DATA); { .data = 1, .clk = 0, .wren = 2, .most = 3 }, /* SF256-PCP */
outw(reg, FM801_REG(chip, GPIO_CTRL)); { .data = 2, .clk = 0, .wren = 1, .most = 3 }, /* SF64-PCR */
spin_unlock_irq(&chip->reg_lock); };
}
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; struct fm801 *chip = tea->private_data;
unsigned short reg; unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL));
unsigned int val = 0; struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1];
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 */
static void snd_fm801_tea575x_256pcpr_write(struct snd_tea575x *tea, unsigned int val) reg &= ~(FM801_GPIO_GP(gpio.data) |
{ FM801_GPIO_GP(gpio.clk) |
struct fm801 *chip = tea->private_data; FM801_GPIO_GP(gpio.wren));
unsigned short reg;
int i = 25;
spin_lock_irq(&chip->reg_lock); reg |= (pins & TEA575X_DATA) ? FM801_GPIO_GP(gpio.data) : 0;
reg = inw(FM801_REG(chip, GPIO_CTRL)); reg |= (pins & TEA575X_CLK) ? FM801_GPIO_GP(gpio.clk) : 0;
/* use GPIO lines and set write enable bit */ /* WRITE_ENABLE is inverted */
reg |= FM801_GPIO_GS(TEA_256PCPR_DATA) | reg |= (pins & TEA575X_WREN) ? 0 : FM801_GPIO_GP(gpio.wren);
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);
}
/* 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)); 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; struct fm801 *chip = tea->private_data;
unsigned short reg; unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL));
unsigned int val = 0; struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1];
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);
return val; return (reg & FM801_GPIO_GP(gpio.data)) ? TEA575X_DATA : 0 |
(reg & FM801_GPIO_GP(gpio.most)) ? TEA575X_MOST : 0;
} }
/* 64PCR GPIO numbers */ static void snd_fm801_tea575x_set_direction(struct snd_tea575x *tea, bool output)
#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)
{ {
struct fm801 *chip = tea->private_data; struct fm801 *chip = tea->private_data;
unsigned short reg; unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL));
int i = 25; 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 */ /* use GPIO lines and set write enable bit */
reg |= FM801_GPIO_GS(TEA_64PCR_DATA) | reg |= FM801_GPIO_GS(gpio.data) |
FM801_GPIO_GS(TEA_64PCR_WRITE_ENABLE) | FM801_GPIO_GS(gpio.wren) |
FM801_GPIO_GS(TEA_64PCR_BUS_CLOCK); FM801_GPIO_GS(gpio.clk) |
/* all of lines are in the write direction */ FM801_GPIO_GS(gpio.most);
/* clear data and clock lines */ if (output) {
reg &= ~(FM801_GPIO_GD(TEA_64PCR_DATA) | /* all of lines are in the write direction */
FM801_GPIO_GD(TEA_64PCR_WRITE_ENABLE) | /* clear data and clock lines */
FM801_GPIO_GD(TEA_64PCR_BUS_CLOCK) | reg &= ~(FM801_GPIO_GD(gpio.data) |
FM801_GPIO_GP(TEA_64PCR_DATA) | FM801_GPIO_GD(gpio.wren) |
FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK) | FM801_GPIO_GD(gpio.clk) |
FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE)); FM801_GPIO_GP(gpio.data) |
outw(reg, FM801_REG(chip, GPIO_CTRL)); FM801_GPIO_GP(gpio.clk) |
udelay(1); FM801_GPIO_GP(gpio.wren));
} else {
while (i--) { /* use GPIO lines, set data direction to input */
if (val & (1 << i)) reg |= FM801_GPIO_GD(gpio.data) |
reg |= FM801_GPIO_GP(TEA_64PCR_DATA); FM801_GPIO_GD(gpio.most) |
else FM801_GPIO_GP(gpio.data) |
reg &= ~FM801_GPIO_GP(TEA_64PCR_DATA); FM801_GPIO_GP(gpio.most) |
outw(reg, FM801_REG(chip, GPIO_CTRL)); FM801_GPIO_GP(gpio.wren);
udelay(1); /* all of lines are in the write direction, except data */
reg |= FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK); /* clear data, write enable and clock lines */
outw(reg, FM801_REG(chip, GPIO_CTRL)); reg &= ~(FM801_GPIO_GD(gpio.wren) |
reg &= ~FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK); FM801_GPIO_GD(gpio.clk) |
outw(reg, FM801_REG(chip, GPIO_CTRL)); FM801_GPIO_GP(gpio.clk));
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;
} }
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)); 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] = { static struct snd_tea575x_ops snd_fm801_tea_ops = {
{ .set_pins = snd_fm801_tea575x_set_pins,
/* 1 = MediaForte 256-PCS */ .get_pins = snd_fm801_tea575x_get_pins,
.write = snd_fm801_tea575x_256pcs_write, .set_direction = snd_fm801_tea575x_set_direction,
.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,
}
}; };
#endif #endif
...@@ -1456,7 +1234,7 @@ static int __devinit snd_fm801_create(struct snd_card *card, ...@@ -1456,7 +1234,7 @@ static int __devinit snd_fm801_create(struct snd_card *card,
chip->tea.card = card; chip->tea.card = card;
chip->tea.freq_fixup = 10700; chip->tea.freq_fixup = 10700;
chip->tea.private_data = chip; 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); snd_tea575x_init(&chip->tea);
} }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment