]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/media/video/cx88/cx88-cards.c
V4L/DVB (7257): cx88: Add xc2028/3028 boards
[linux-2.6-omap-h63xx.git] / drivers / media / video / cx88 / cx88-cards.c
index 254290975cdb62f4327c43a31e5829858b32b3c2..d07286fa21f5257cb52ed12ce3c8b28b3e0d00f3 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "cx88.h"
 #include "tea5767.h"
+#include "tuner-xc2028.h"
 
 static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
 static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
@@ -1401,6 +1402,148 @@ static const struct cx88_board cx88_boards[] = {
                }},
                .mpeg           = CX88_MPEG_DVB,
        },
+       [CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = {
+               .name           = "DViCO FusionHDTV 5 PCI nano",
+               /* xc3008 tuner, digital only for now */
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x000027df, /* Unconfirmed */
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x000027df, /* Unconfirmed */
+                       .audioroute = 1,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x000027df, /* Unconfirmed */
+                       .audioroute = 1,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_PINNACLE_HYBRID_PCTV] = {
+              .name           = "Pinnacle Hybrid PCTV",
+              .tuner_type     = TUNER_XC2028,
+              .tuner_addr     = 0x61,
+              .input          = { {
+                      .type   = CX88_VMUX_TELEVISION,
+                      .vmux   = 0,
+              }, {
+                      .type   = CX88_VMUX_COMPOSITE1,
+                      .vmux   = 1,
+              }, {
+                      .type   = CX88_VMUX_SVIDEO,
+                      .vmux   = 2,
+              } },
+              .radio = {
+                      .type   = CX88_RADIO,
+                      .gpio0  = 0x004ff,
+                      .gpio1  = 0x010ff,
+                      .gpio2  = 0x0ff,
+              },
+       },
+       [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = {
+              .name           = "Winfast TV2000 XP Global",
+              .tuner_type     = TUNER_XC2028,
+              .tuner_addr     = 0x61,
+              .input          = { {
+                      .type   = CX88_VMUX_TELEVISION,
+                      .vmux   = 0,
+                      .gpio0  = 0x0400, /* pin 2:mute = 0 (off?) */
+                      .gpio1  = 0x0000,
+                      .gpio2  = 0x0800, /* pin 19:audio = 0 (tv) */
+
+              }, {
+                      .type   = CX88_VMUX_COMPOSITE1,
+                      .vmux   = 1,
+                      .gpio0  = 0x0400, /* probably?  or 0x0404 to turn mute on */
+                      .gpio1  = 0x0000,
+                      .gpio2  = 0x0808, /* pin 19:audio = 1 (line) */
+
+              }, {
+                      .type   = CX88_VMUX_SVIDEO,
+                      .vmux   = 2,
+              } },
+              .radio = {
+                      .type   = CX88_RADIO,
+                      .gpio0  = 0x004ff,
+                      .gpio1  = 0x010ff,
+                      .gpio2  = 0x0ff,
+              },
+       },
+       [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
+              .name           = "PowerColor Real Angel 330",
+              .tuner_type     = TUNER_XC2028,
+              .tuner_addr     = 0x61,
+              .input          = { {
+                      .type   = CX88_VMUX_TELEVISION,
+                      .vmux   = 0,
+                      .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */
+                      .gpio1 = 0x0000,
+                      .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */
+              }, {
+                      .type   = CX88_VMUX_COMPOSITE1,
+                      .vmux   = 1,
+                      .gpio0 = 0x0400, /* probably?  or 0x0404 to turn mute on */
+                      .gpio1 = 0x0000,
+                      .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */
+              }, {
+                      .type   = CX88_VMUX_SVIDEO,
+                      .vmux   = 2,
+                      .gpio0  = 0x000ff,
+                      .gpio1  = 0x0f37d,
+                      .gpio2  = 0x00019,
+                      .gpio3  = 0x00000,
+              } },
+              .radio = {
+                      .type   = CX88_RADIO,
+                      .gpio0  = 0x000ff,
+                      .gpio1  = 0x0f35d,
+                      .gpio2  = 0x00019,
+                      .gpio3  = 0x00000,
+              },
+       },
+       [CX88_BOARD_GENIATECH_X8000_MT] = {
+               /* Also PowerColor Real Angel 330 and Geniatech X800 OEM */
+              .name           = "Geniatech X8000-MT DVBT",
+              .tuner_type     = TUNER_XC2028,
+              .tuner_addr     = 0x61,
+              .input          = { {
+                      .type   = CX88_VMUX_TELEVISION,
+                      .vmux   = 0,
+                      .gpio0  = 0x00000000,
+                      .gpio1  = 0x00e3e341,
+                      .gpio2  = 0x00000000,
+                      .gpio3  = 0x00000000,
+              }, {
+                      .type   = CX88_VMUX_COMPOSITE1,
+                      .vmux   = 1,
+                      .gpio0  = 0x00000000,
+                      .gpio1  = 0x00e3e361,
+                      .gpio2  = 0x00000000,
+                      .gpio3  = 0x00000000,
+              }, {
+                      .type   = CX88_VMUX_SVIDEO,
+                      .vmux   = 2,
+                      .gpio0  = 0x00000000,
+                      .gpio1  = 0x00e3e361,
+                      .gpio2  = 0x00000000,
+                      .gpio3  = 0x00000000,
+              } },
+              .radio = {
+                      .type   = CX88_RADIO,
+                      .gpio0  = 0x00000000,
+                      .gpio1  = 0x00e3e341,
+                      .gpio2  = 0x00000000,
+                      .gpio3  = 0x00000000,
+              },
+              .mpeg           = CX88_MPEG_DVB,
+       }
 };
 
 /* ------------------------------------------------------------------ */
@@ -1714,7 +1857,27 @@ static const struct cx88_subid cx88_subids[] = {
                .subvendor = 0x11bd,
                .subdevice = 0x0051,
                .card      = CX88_BOARD_PINNACLE_PCTV_HD_800i,
-       },
+       }, {
+               .subvendor = 0x18ac,
+               .subdevice = 0xd530,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO,
+       }, {
+               .subvendor = 0x12ab,
+               .subdevice = 0x1788,
+               .card      = CX88_BOARD_PINNACLE_HYBRID_PCTV,
+       }, {
+               .subvendor = 0x14f1,
+               .subdevice = 0xea3d,
+               .card      = CX88_BOARD_POWERCOLOR_REAL_ANGEL,
+       }, {
+               .subvendor = 0x107d,
+               .subdevice = 0x6f18,
+               .card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
+       }, {
+               .subvendor = 0x14f1,
+               .subdevice = 0x8852,
+               .card      = CX88_BOARD_GENIATECH_X8000_MT,
+       }
 };
 
 /* ----------------------------------------------------------------------- */
@@ -1846,6 +2009,50 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
                CX88_RADIO : 0;
 }
 
+/* ----------------------------------------------------------------------- */
+/* some Geniatech specific stuff                                           */
+
+static int cx88_xc3028_geniatech_tuner_callback(void *priv, int command, int mode)
+{
+       struct i2c_algo_bit_data *i2c_algo = priv;
+       struct cx88_core *core = i2c_algo->data;
+
+       switch (command) {
+       case XC2028_TUNER_RESET:
+               switch (INPUT(core->input).type) {
+               case CX88_RADIO:
+                       cx_write(MO_GP1_IO, 0x101010);
+                       mdelay(50);
+                       cx_write(MO_GP1_IO, 0x101000);
+                       mdelay(50);
+                       cx_write(MO_GP1_IO, 0x101010);
+                       mdelay(50);
+                       return 0;
+               case CX88_VMUX_DVB:
+                       cx_write(MO_GP1_IO, 0x030302);
+                       mdelay(50);
+                       cx_write(MO_GP1_IO, 0x101010);
+                       mdelay(50);
+                       cx_write(MO_GP1_IO, 0x101000);
+                       mdelay(50);
+                       cx_write(MO_GP1_IO, 0x101010);
+                       mdelay(50);
+                       return 0;
+               default:
+                       cx_write(MO_GP1_IO, 0x030301);
+                       mdelay(50);
+                       cx_write(MO_GP1_IO, 0x101010);
+                       mdelay(50);
+                       cx_write(MO_GP1_IO, 0x101000);
+                       mdelay(50);
+                       cx_write(MO_GP1_IO, 0x101010);
+                       mdelay(50);
+                       return 0;
+                }
+       }
+       return -EINVAL;
+}
+
 /* ----------------------------------------------------------------------- */
 /* some DViCO specific stuff                                               */
 
@@ -1880,28 +2087,71 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
        }
 }
 
+static int cx88_xc2028_tuner_callback(void *priv, int command, int arg)
+{
+       struct i2c_algo_bit_data *i2c_algo = priv;
+       struct cx88_core *core = i2c_algo->data;
+
+       /* Board-specific callbacks */
+       switch (core->boardnr) {
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+       case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
+       case CX88_BOARD_GENIATECH_X8000_MT:
+               return cx88_xc3028_geniatech_tuner_callback(priv, command, arg);
+       }
+
+       switch (command) {
+       case XC2028_TUNER_RESET:
+       {
+               switch (INPUT(core->input).type) {
+               case CX88_RADIO:
+                       printk(KERN_INFO "setting GPIO to radio!\n");
+                       cx_write(MO_GP0_IO, 0x4ff);
+                       mdelay(250);
+                       cx_write(MO_GP2_IO, 0xff);
+                       mdelay(250);
+                       cx_write(MO_GP1_IO, 0x101010);
+                       mdelay(250);
+                       cx_write(MO_GP1_IO, 0x101000);
+                       mdelay(250);
+                       cx_write(MO_GP1_IO, 0x101010);
+                       mdelay(250);
+                       return 0;
+               case CX88_VMUX_DVB:     /* Digital TV*/
+               default:                /* Analog TV */
+                       printk(KERN_INFO "setting GPIO to TV!\n");
+                       cx_write(MO_GP1_IO, 0x101010);
+                       mdelay(250);
+                       cx_write(MO_GP1_IO, 0x101000);
+                       mdelay(250);
+                       cx_write(MO_GP1_IO, 0x101010);
+                       mdelay(250);
+                       return 0;
+               }
+       }
+       }
+       return -EINVAL;
+}
+
 /* ----------------------------------------------------------------------- */
 /* Tuner callback function. Currently only needed for the Pinnacle        *
  * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both      *
  * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c)    */
 
-int cx88_tuner_callback(void *priv, int command, int arg)
+static int cx88_xc5000_tuner_callback(void *priv, int command, int arg)
 {
        struct i2c_algo_bit_data *i2c_algo = priv;
        struct cx88_core *core = i2c_algo->data;
 
-       switch(core->boardnr) {
+       switch (core->boardnr) {
        case CX88_BOARD_PINNACLE_PCTV_HD_800i:
-               if(command == 0) { /* This is the reset command from xc5000 */
-                       /* Reset XC5000 tuner via GPIO pin #2 */
-                       cx_set(MO_GP0_IO, 0x00000400);
-                       cx_clear(MO_GP0_IO, 0x00000004);
-                       mdelay(200);
-                       cx_set(MO_GP0_IO, 0x00000004);
-                       mdelay(200);
+               if (command == 0) { /* This is the reset command from xc5000 */
+                       /* Reset XC5000 tuner via SYS_RSTO_pin */
+                       cx_write(MO_SRST_IO, 0);
+                       msleep(10);
+                       cx_write(MO_SRST_IO, 1);
                        return 0;
-               }
-               else {
+               } else {
                        printk(KERN_ERR
                                "xc5000: unknown tuner callback command.\n");
                        return -EINVAL;
@@ -1910,6 +2160,20 @@ int cx88_tuner_callback(void *priv, int command, int arg)
        }
        return 0; /* Should never be here */
 }
+
+int cx88_tuner_callback(void *priv, int command, int arg)
+{
+       struct i2c_algo_bit_data *i2c_algo = priv;
+       struct cx88_core *core = i2c_algo->data;
+
+       switch (core->board.tuner_type) {
+               case TUNER_XC2028:
+                       return cx88_xc2028_tuner_callback(priv, command, arg);
+               case TUNER_XC5000:
+                       return cx88_xc5000_tuner_callback(priv, command, arg);
+       }
+       return -EINVAL;
+}
 EXPORT_SYMBOL(cx88_tuner_callback);
 
 /* ----------------------------------------------------------------------- */
@@ -2064,6 +2328,26 @@ static void cx88_card_setup(struct cx88_core *core)
                cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg);
        }
        }
+
+       if (core->board.tuner_type == TUNER_XC2028) {
+               struct v4l2_priv_tun_config  xc2028_cfg;
+               struct xc2028_ctrl           ctl;
+
+               memset(&xc2028_cfg, 0, sizeof(ctl));
+               memset(&ctl, 0, sizeof(ctl));
+
+               ctl.fname   = XC2028_DEFAULT_FIRMWARE;
+               ctl.max_len = 64;
+               /* FIXME: Those should be device-dependent */
+               ctl.demod = XC3028_FE_OREN538;
+               ctl.mts = 1;
+
+               xc2028_cfg.tuner = TUNER_XC2028;
+               xc2028_cfg.priv  = &ctl;
+
+               cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg);
+       }
+
 }
 
 /* ------------------------------------------------------------------ */
@@ -2198,18 +2482,14 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
        cx88_reset(core);
        cx88_card_setup_pre_i2c(core);
        cx88_i2c_init(core, pci);
+
+       /* load tuner module, if needed */
+       if (TUNER_ABSENT != core->board.tuner_type)
+               request_module("tuner");
+
        cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);
        cx88_card_setup(core);
        cx88_ir_init(core, pci);
 
        return core;
 }
-
-/* ------------------------------------------------------------------ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */