static void td3116_muxsel(struct bttv *btv, unsigned int input);
static int terratec_active_radio_upgrade(struct bttv *btv);
-static int tea5757_read(struct bttv *btv);
-static int tea5757_write(struct bttv *btv, int value);
+static int tea575x_init(struct bttv *btv);
static void identify_by_eeprom(struct bttv *btv,
unsigned char eeprom_data[256]);
static int pvr_boot(struct bttv *btv);
if (0 == (gpio & 0x20)) {
btv->has_radio = 1;
if (!miro_fmtuner[id]) {
- btv->has_matchbox = 1;
- btv->mbox_we = (1<<6);
- btv->mbox_most = (1<<7);
- btv->mbox_clk = (1<<8);
- btv->mbox_data = (1<<9);
- btv->mbox_mask = (1<<6)|(1<<7)|(1<<8)|(1<<9);
+ btv->has_tea575x = 1;
+ btv->tea_gpio.wren = 6;
+ btv->tea_gpio.most = 7;
+ btv->tea_gpio.clk = 8;
+ btv->tea_gpio.data = 9;
+ tea575x_init(btv);
}
} else {
btv->has_radio = 0;
pr_info("%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
btv->c.nr, id+1, btv->tuner_type,
!btv->has_radio ? "no" :
- (btv->has_matchbox ? "matchbox" : "fmtuner"),
+ (btv->has_tea575x ? "tea575x" : "fmtuner"),
(-1 == msp) ? "no" : "yes");
} else {
/* new cards with microtune tuner */
break;
case BTTV_BOARD_VHX:
btv->has_radio = 1;
- btv->has_matchbox = 1;
- btv->mbox_we = 0x20;
- btv->mbox_most = 0;
- btv->mbox_clk = 0x08;
- btv->mbox_data = 0x10;
- btv->mbox_mask = 0x38;
+ btv->has_tea575x = 1;
+ btv->tea_gpio.wren = 5;
+ btv->tea_gpio.most = 6;
+ btv->tea_gpio.clk = 3;
+ btv->tea_gpio.data = 4;
+ tea575x_init(btv);
break;
case BTTV_BOARD_VOBIS_BOOSTAR:
case BTTV_BOARD_TERRATV:
btv->radio_uses_msp_demodulator = 1;
}
-static int terratec_active_radio_upgrade(struct bttv *btv)
+/* ----------------------------------------------------------------------- */
+
+static void bttv_tea575x_set_pins(struct snd_tea575x *tea, u8 pins)
+{
+ struct bttv *btv = tea->private_data;
+ struct bttv_tea575x_gpio gpio = btv->tea_gpio;
+ u16 val = 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;
+
+ gpio_bits((1 << gpio.data) | (1 << gpio.clk) | (1 << gpio.wren), val);
+ if (btv->mbox_ior) {
+ /* IOW and CSEL active */
+ gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
+ udelay(5);
+ /* all inactive */
+ gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
+ btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
+ }
+}
+
+static u8 bttv_tea575x_get_pins(struct snd_tea575x *tea)
{
- int freq;
+ struct bttv *btv = tea->private_data;
+ struct bttv_tea575x_gpio gpio = btv->tea_gpio;
+ u8 ret = 0;
+ u16 val;
+
+ if (btv->mbox_ior) {
+ /* IOR and CSEL active */
+ gpio_bits(btv->mbox_ior | btv->mbox_csel, 0);
+ udelay(5);
+ }
+ val = gpio_read();
+ if (btv->mbox_ior) {
+ /* all inactive */
+ gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
+ btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
+ }
+
+ if (val & (1 << gpio.data))
+ ret |= TEA575X_DATA;
+ if (val & (1 << gpio.most))
+ ret |= TEA575X_MOST;
+
+ return ret;
+}
+
+static void bttv_tea575x_set_direction(struct snd_tea575x *tea, bool output)
+{
+ struct bttv *btv = tea->private_data;
+ struct bttv_tea575x_gpio gpio = btv->tea_gpio;
+ u32 mask = (1 << gpio.clk) | (1 << gpio.wren) | (1 << gpio.data) |
+ (1 << gpio.most);
+
+ if (output)
+ gpio_inout(mask, (1 << gpio.data) | (1 << gpio.clk) |
+ (1 << gpio.wren));
+ else
+ gpio_inout(mask, (1 << gpio.clk) | (1 << gpio.wren));
+}
+
+static struct snd_tea575x_ops bttv_tea_ops = {
+ .set_pins = bttv_tea575x_set_pins,
+ .get_pins = bttv_tea575x_get_pins,
+ .set_direction = bttv_tea575x_set_direction,
+};
+
+static int tea575x_init(struct bttv *btv)
+{
+ btv->tea.private_data = btv;
+ btv->tea.ops = &bttv_tea_ops;
+ if (!snd_tea575x_hw_init(&btv->tea)) {
+ pr_info("%d: detected TEA575x radio\n", btv->c.nr);
+ btv->tea.mute = false;
+ return 0;
+ }
+ btv->has_tea575x = 0;
+ btv->has_radio = 0;
+
+ return -ENODEV;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int terratec_active_radio_upgrade(struct bttv *btv)
+{
btv->has_radio = 1;
- btv->has_matchbox = 1;
- btv->mbox_we = 0x10;
- btv->mbox_most = 0x20;
- btv->mbox_clk = 0x08;
- btv->mbox_data = 0x04;
- btv->mbox_mask = 0x3c;
+ btv->has_tea575x = 1;
+ btv->tea_gpio.wren = 4;
+ btv->tea_gpio.most = 5;
+ btv->tea_gpio.clk = 3;
+ btv->tea_gpio.data = 2;
btv->mbox_iow = 1 << 8;
btv->mbox_ior = 1 << 9;
btv->mbox_csel = 1 << 10;
- freq=88000/62.5;
- tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */
- if (0x1ed8 == tea5757_read(btv)) {
+ if (!tea575x_init(btv)) {
pr_info("%d: Terratec Active Radio Upgrade found\n", btv->c.nr);
- btv->has_radio = 1;
- btv->has_saa6588 = 1;
- btv->has_matchbox = 1;
- } else {
- btv->has_radio = 0;
- btv->has_matchbox = 0;
+ btv->has_saa6588 = 1;
}
+
return 0;
}
}
}
-
-
-/* ----------------------------------------------------------------------- */
-/* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports */
-/*
- * Copyright (c) 1999 Csaba Halasz <qgehali@uni-miskolc.hu>
- * This code is placed under the terms of the GNU General Public License
- *
- * Brutally hacked by Dan Sheridan <dan.sheridan@contact.org.uk> djs52 8/3/00
- */
-
-static void bus_low(struct bttv *btv, int bit)
-{
- if (btv->mbox_ior) {
- gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
- btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
- udelay(5);
- }
-
- gpio_bits(bit,0);
- udelay(5);
-
- if (btv->mbox_ior) {
- gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
- udelay(5);
- }
-}
-
-static void bus_high(struct bttv *btv, int bit)
-{
- if (btv->mbox_ior) {
- gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
- btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
- udelay(5);
- }
-
- gpio_bits(bit,bit);
- udelay(5);
-
- if (btv->mbox_ior) {
- gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
- udelay(5);
- }
-}
-
-static int bus_in(struct bttv *btv, int bit)
-{
- if (btv->mbox_ior) {
- gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
- btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
- udelay(5);
-
- gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
- udelay(5);
- }
- return gpio_read() & (bit);
-}
-
-/* TEA5757 register bits */
-#define TEA_FREQ 0:14
-#define TEA_BUFFER 15:15
-
-#define TEA_SIGNAL_STRENGTH 16:17
-
-#define TEA_PORT1 18:18
-#define TEA_PORT0 19:19
-
-#define TEA_BAND 20:21
-#define TEA_BAND_FM 0
-#define TEA_BAND_MW 1
-#define TEA_BAND_LW 2
-#define TEA_BAND_SW 3
-
-#define TEA_MONO 22:22
-#define TEA_ALLOW_STEREO 0
-#define TEA_FORCE_MONO 1
-
-#define TEA_SEARCH_DIRECTION 23:23
-#define TEA_SEARCH_DOWN 0
-#define TEA_SEARCH_UP 1
-
-#define TEA_STATUS 24:24
-#define TEA_STATUS_TUNED 0
-#define TEA_STATUS_SEARCHING 1
-
-/* Low-level stuff */
-static int tea5757_read(struct bttv *btv)
-{
- unsigned long timeout;
- int value = 0;
- int i;
-
- /* better safe than sorry */
- gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we);
-
- if (btv->mbox_ior) {
- gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
- btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
- udelay(5);
- }
-
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"tea5757 read");
-
- bus_low(btv,btv->mbox_we);
- bus_low(btv,btv->mbox_clk);
-
- udelay(10);
- timeout= jiffies + msecs_to_jiffies(1000);
-
- /* wait for DATA line to go low; error if it doesn't */
- while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout))
- schedule();
- if (bus_in(btv,btv->mbox_data)) {
- pr_warn("%d: tea5757: read timeout\n", btv->c.nr);
- return -1;
- }
-
- dprintk("%d: tea5757:", btv->c.nr);
- for (i = 0; i < 24; i++) {
- udelay(5);
- bus_high(btv,btv->mbox_clk);
- udelay(5);
- dprintk_cont("%c",
- bus_in(btv, btv->mbox_most) == 0 ? 'T' : '-');
- bus_low(btv,btv->mbox_clk);
- value <<= 1;
- value |= (bus_in(btv,btv->mbox_data) == 0)?0:1; /* MSB first */
- dprintk_cont("%c",
- bus_in(btv, btv->mbox_most) == 0 ? 'S' : 'M');
- }
- dprintk_cont("\n");
- dprintk("%d: tea5757: read 0x%X\n", btv->c.nr, value);
- return value;
-}
-
-static int tea5757_write(struct bttv *btv, int value)
-{
- int i;
- int reg = value;
-
- gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we | btv->mbox_data);
-
- if (btv->mbox_ior) {
- gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
- btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
- udelay(5);
- }
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"tea5757 write");
-
- dprintk("%d: tea5757: write 0x%X\n", btv->c.nr, value);
- bus_low(btv,btv->mbox_clk);
- bus_high(btv,btv->mbox_we);
- for (i = 0; i < 25; i++) {
- if (reg & 0x1000000)
- bus_high(btv,btv->mbox_data);
- else
- bus_low(btv,btv->mbox_data);
- reg <<= 1;
- bus_high(btv,btv->mbox_clk);
- udelay(10);
- bus_low(btv,btv->mbox_clk);
- udelay(10);
- }
- bus_low(btv,btv->mbox_we); /* unmute !!! */
- return 0;
-}
-
-void tea5757_set_freq(struct bttv *btv, unsigned short freq)
-{
- dprintk("tea5757_set_freq %d\n",freq);
- tea5757_write(btv, 5 * freq + 0x358); /* add 10.7MHz (see docs) */
-}
-
/* RemoteVision MX (rv605) muxsel helper [Miguel Freitas]
*
* This is needed because rv605 don't use a normal multiplex, but a crosspoint