diff options
author | Ondrej Zary <linux@rainbow-software.org> | 2011-05-09 23:39:51 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-05-10 09:31:45 +0200 |
commit | 938a1566b162aa485acd8dea2ebd92d92dfa0a45 (patch) | |
tree | a0aef0566ec4cf2f490191482016220ade365ffa /sound/pci/fm801.c | |
parent | 72587173cc31bb96db63e347b94ad0ef84878cea (diff) | |
download | lwn-938a1566b162aa485acd8dea2ebd92d92dfa0a45.tar.gz lwn-938a1566b162aa485acd8dea2ebd92d92dfa0a45.zip |
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: Ondrej Zary <linux@rainbow-software.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/fm801.c')
-rw-r--r-- | sound/pci/fm801.c | 336 |
1 files changed, 57 insertions, 279 deletions
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index f4dc1c77202b..1db5ead62a98 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -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 |