aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/ttpci/budget-av.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/ttpci/budget-av.c')
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c226
1 files changed, 130 insertions, 96 deletions
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 14e963206b89..6e0f5d307c52 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -59,8 +59,12 @@ struct budget_av {
59 struct dvb_ca_en50221 ca; 59 struct dvb_ca_en50221 ca;
60}; 60};
61 61
62static int enable_ci = 0; 62/* GPIO CI Connections:
63 63 * 0 - Vcc/Reset (Reset is controlled by capacitor)
64 * 1 - Attribute Memory
65 * 2 - Card Enable (Active Low)
66 * 3 - Card Detect
67 */
64 68
65/**************************************************************************** 69/****************************************************************************
66 * INITIALIZATION 70 * INITIALIZATION
@@ -188,22 +192,35 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
188{ 192{
189 struct budget_av *budget_av = (struct budget_av *) ca->data; 193 struct budget_av *budget_av = (struct budget_av *) ca->data;
190 struct saa7146_dev *saa = budget_av->budget.dev; 194 struct saa7146_dev *saa = budget_av->budget.dev;
191 int max = 20; 195 int timeout = 50; // 5 seconds (4.4.6 Ready)
192 196
193 if (slot != 0) 197 if (slot != 0)
194 return -EINVAL; 198 return -EINVAL;
195 199
196 dprintk(1, "ciintf_slot_reset\n"); 200 dprintk(1, "ciintf_slot_reset\n");
197 201
198 /* reset the card */ 202 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
199 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
200 msleep(100);
201 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
202 203
203 while (--max > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d) 204 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
205 msleep(2);
206 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); /* Vcc on */
207 msleep(20); /* 20 ms Vcc settling time */
208
209 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
210
211 /* This should have been based on pin 16 READY of the pcmcia port,
212 * but AFAICS it is not routed to the saa7146 */
213 while (--timeout > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d)
204 msleep(100); 214 msleep(100);
205 215
206 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); 216 if (timeout <= 0)
217 {
218 printk(KERN_ERR "budget-av: cam reset failed (timeout).\n");
219 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
220 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
221 return -ETIMEDOUT;
222 }
223
207 return 0; 224 return 0;
208} 225}
209 226
@@ -240,7 +257,6 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
240{ 257{
241 struct budget_av *budget_av = (struct budget_av *) ca->data; 258 struct budget_av *budget_av = (struct budget_av *) ca->data;
242 struct saa7146_dev *saa = budget_av->budget.dev; 259 struct saa7146_dev *saa = budget_av->budget.dev;
243 int cam = 0;
244 260
245 if (slot != 0) 261 if (slot != 0)
246 return -EINVAL; 262 return -EINVAL;
@@ -248,15 +264,21 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
248 if (!budget_av->slot_status) { 264 if (!budget_av->slot_status) {
249 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); 265 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
250 udelay(1); 266 udelay(1);
251 cam = saa7146_read(saa, PSR) & MASK_06; 267 if (saa7146_read(saa, PSR) & MASK_06)
252 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); 268 {
253 269 printk(KERN_INFO "budget-av: cam inserted\n");
254 if (cam)
255 budget_av->slot_status = 1; 270 budget_av->slot_status = 1;
271 }
272 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
256 } else if (!open) { 273 } else if (!open) {
257 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); 274 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
258 if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT) 275 if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT)
276 {
277 printk(KERN_INFO "budget-av: cam ejected\n");
278 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
279 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
259 budget_av->slot_status = 0; 280 budget_av->slot_status = 0;
281 }
260 } 282 }
261 283
262 if (budget_av->slot_status == 1) 284 if (budget_av->slot_status == 1)
@@ -272,17 +294,11 @@ static int ciintf_init(struct budget_av *budget_av)
272 294
273 memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221)); 295 memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221));
274 296
275 /* setup GPIOs */ 297 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
276 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI); 298 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
277 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); 299 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO);
278 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); 300 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
279 301
280 /* Reset the card */
281 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
282 msleep(50);
283 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
284 msleep(100);
285
286 /* Enable DEBI pins */ 302 /* Enable DEBI pins */
287 saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); 303 saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
288 304
@@ -297,13 +313,14 @@ static int ciintf_init(struct budget_av *budget_av)
297 budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable; 313 budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
298 budget_av->ca.poll_slot_status = ciintf_poll_slot_status; 314 budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
299 budget_av->ca.data = budget_av; 315 budget_av->ca.data = budget_av;
300 if ((result = dvb_ca_en50221_init(budget_av->budget.dvb_adapter, 316
317 if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
301 &budget_av->ca, 0, 1)) != 0) { 318 &budget_av->ca, 0, 1)) != 0) {
302 printk("budget_av: CI interface detected, but initialisation failed.\n"); 319 printk(KERN_ERR "budget-av: ci initialisation failed.\n");
303 goto error; 320 goto error;
304 } 321 }
305 // success! 322
306 printk("ciintf_init: CI interface initialised\n"); 323 printk(KERN_INFO "budget-av: ci interface initialised.\n");
307 budget_av->budget.ci_present = 1; 324 budget_av->budget.ci_present = 1;
308 return 0; 325 return 0;
309 326
@@ -361,8 +378,12 @@ static const u8 saa7113_tab[] = {
361static int saa7113_init(struct budget_av *budget_av) 378static int saa7113_init(struct budget_av *budget_av)
362{ 379{
363 struct budget *budget = &budget_av->budget; 380 struct budget *budget = &budget_av->budget;
381 struct saa7146_dev *saa = budget->dev;
364 const u8 *data = saa7113_tab; 382 const u8 *data = saa7113_tab;
365 383
384 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
385 msleep(200);
386
366 if (i2c_writereg(&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) { 387 if (i2c_writereg(&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) {
367 dprintk(1, "saa7113 not found on KNC card\n"); 388 dprintk(1, "saa7113 not found on KNC card\n");
368 return -ENODEV; 389 return -ENODEV;
@@ -697,75 +718,90 @@ static u8 read_pwm(struct budget_av *budget_av)
697 return pwm; 718 return pwm;
698} 719}
699 720
721#define SUBID_DVBS_KNC1 0x0010
722#define SUBID_DVBS_KNC1_PLUS 0x0011
723#define SUBID_DVBS_TYPHOON 0x4f56
724#define SUBID_DVBS_CINERGY1200 0x1154
725
726#define SUBID_DVBC_KNC1 0x0020
727#define SUBID_DVBC_KNC1_PLUS 0x0021
728#define SUBID_DVBC_CINERGY1200 0x1156
729
730#define SUBID_DVBT_KNC1_PLUS 0x0031
731#define SUBID_DVBT_KNC1 0x0030
732#define SUBID_DVBT_CINERGY1200 0x1157
700 733
701static void frontend_init(struct budget_av *budget_av) 734static void frontend_init(struct budget_av *budget_av)
702{ 735{
703 switch (budget_av->budget.dev->pci->subsystem_device) { 736 struct saa7146_dev * saa = budget_av->budget.dev;
704 case 0x4f56: // Typhoon/KNC1 DVB-S budget (stv0299/Philips SU1278(tsa5059)) 737 struct dvb_frontend * fe = NULL;
705 budget_av->budget.dvb_frontend = 738
706 stv0299_attach(&typhoon_config, &budget_av->budget.i2c_adap); 739 switch (saa->pci->subsystem_device) {
707 if (budget_av->budget.dvb_frontend != NULL) { 740 case SUBID_DVBS_KNC1_PLUS:
741 case SUBID_DVBC_KNC1_PLUS:
742 case SUBID_DVBT_KNC1_PLUS:
743 // Enable / PowerON Frontend
744 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
708 break; 745 break;
709 } 746 }
747
748 switch (saa->pci->subsystem_device) {
749
750 case SUBID_DVBS_KNC1:
751 case SUBID_DVBS_KNC1_PLUS:
752 case SUBID_DVBS_TYPHOON:
753 fe = stv0299_attach(&typhoon_config,
754 &budget_av->budget.i2c_adap);
710 break; 755 break;
711 756
712 case 0x0020: // KNC1 DVB-C budget (tda10021/Philips CU1216(tua6034)) 757 case SUBID_DVBS_CINERGY1200:
713 budget_av->budget.dvb_frontend = 758 fe = stv0299_attach(&cinergy_1200s_config,
714 tda10021_attach(&philips_cu1216_config, 759 &budget_av->budget.i2c_adap);
715 &budget_av->budget.i2c_adap, read_pwm(budget_av));
716 if (budget_av->budget.dvb_frontend != NULL) {
717 break;
718 }
719 break; 760 break;
720 761
721 case 0x0030: // KNC1 DVB-T budget (tda10046/Philips TU1216(tda6651tt)) 762 case SUBID_DVBC_KNC1:
722 budget_av->budget.dvb_frontend = 763 case SUBID_DVBC_KNC1_PLUS:
723 tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap); 764 fe = tda10021_attach(&philips_cu1216_config,
724 if (budget_av->budget.dvb_frontend != NULL) { 765 &budget_av->budget.i2c_adap,
725 break; 766 read_pwm(budget_av));
726 }
727 break; 767 break;
728 768
729 case 0x1154: // TerraTec Cinergy 1200 DVB-S (stv0299/Philips SU1278(tsa5059)) 769 case SUBID_DVBT_KNC1:
730 budget_av->budget.dvb_frontend = 770 case SUBID_DVBT_KNC1_PLUS:
731 stv0299_attach(&cinergy_1200s_config, &budget_av->budget.i2c_adap); 771 fe = tda10046_attach(&philips_tu1216_config,
732 if (budget_av->budget.dvb_frontend != NULL) { 772 &budget_av->budget.i2c_adap);
733 break;
734 }
735 break; 773 break;
736 774
737 case 0x1156: // Terratec Cinergy 1200 DVB-C (tda10021/Philips CU1216(tua6034)) 775 case SUBID_DVBC_CINERGY1200:
738 budget_av->budget.dvb_frontend = 776 fe = tda10021_attach(&philips_cu1216_config,
739 tda10021_attach(&philips_cu1216_config, 777 &budget_av->budget.i2c_adap,
740 &budget_av->budget.i2c_adap, read_pwm(budget_av)); 778 read_pwm(budget_av));
741 if (budget_av->budget.dvb_frontend) {
742 break;
743 }
744 break; 779 break;
745 780
746 case 0x1157: // Terratec Cinergy 1200 DVB-T (tda10046/Philips TU1216(tda6651tt)) 781 case SUBID_DVBT_CINERGY1200:
747 budget_av->budget.dvb_frontend = 782 fe = tda10046_attach(&philips_tu1216_config,
748 tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap); 783 &budget_av->budget.i2c_adap);
749 if (budget_av->budget.dvb_frontend) {
750 break;
751 }
752 break; 784 break;
753 } 785 }
754 786
755 if (budget_av->budget.dvb_frontend == NULL) { 787 if (fe == NULL) {
756 printk("budget_av: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", 788 printk(KERN_ERR "budget-av: A frontend driver was not found "
757 budget_av->budget.dev->pci->vendor, 789 "for device %04x/%04x subsystem %04x/%04x\n",
758 budget_av->budget.dev->pci->device, 790 saa->pci->vendor,
759 budget_av->budget.dev->pci->subsystem_vendor, 791 saa->pci->device,
760 budget_av->budget.dev->pci->subsystem_device); 792 saa->pci->subsystem_vendor,
761 } else { 793 saa->pci->subsystem_device);
762 if (dvb_register_frontend 794 return;
763 (budget_av->budget.dvb_adapter, budget_av->budget.dvb_frontend)) { 795 }
764 printk("budget-av: Frontend registration failed!\n"); 796
765 if (budget_av->budget.dvb_frontend->ops->release) 797 budget_av->budget.dvb_frontend = fe;
766 budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend); 798
767 budget_av->budget.dvb_frontend = NULL; 799 if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
768 } 800 budget_av->budget.dvb_frontend)) {
801 printk(KERN_ERR "budget-av: Frontend registration failed!\n");
802 if (budget_av->budget.dvb_frontend->ops->release)
803 budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend);
804 budget_av->budget.dvb_frontend = NULL;
769 } 805 }
770} 806}
771 807
@@ -822,6 +858,7 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
822 858
823 memset(budget_av, 0, sizeof(struct budget_av)); 859 memset(budget_av, 0, sizeof(struct budget_av));
824 860
861 budget_av->has_saa7113 = 0;
825 budget_av->budget.ci_present = 0; 862 budget_av->budget.ci_present = 0;
826 863
827 dev->ext_priv = budget_av; 864 dev->ext_priv = budget_av;
@@ -836,10 +873,7 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
836 saa7146_write(dev, DD1_INIT, 0x07000600); 873 saa7146_write(dev, DD1_INIT, 0x07000600);
837 saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26); 874 saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
838 875
839 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI); 876 if (saa7113_init(budget_av) == 0) {
840 msleep(500);
841
842 if (0 == saa7113_init(budget_av)) {
843 budget_av->has_saa7113 = 1; 877 budget_av->has_saa7113 = 1;
844 878
845 if (0 != saa7146_vv_init(dev, &vv_data)) { 879 if (0 != saa7146_vv_init(dev, &vv_data)) {
@@ -860,31 +894,26 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
860 894
861 saa7113_setinput(budget_av, 0); 895 saa7113_setinput(budget_av, 0);
862 } else { 896 } else {
863 budget_av->has_saa7113 = 0; 897 ciintf_init(budget_av);
864
865 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
866 } 898 }
867 899
868 /* fixme: find some sane values here... */ 900 /* fixme: find some sane values here... */
869 saa7146_write(dev, PCI_BT_V1, 0x1c00101f); 901 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
870 902
871 mac = budget_av->budget.dvb_adapter->proposed_mac; 903 mac = budget_av->budget.dvb_adapter.proposed_mac;
872 if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) { 904 if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
873 printk("KNC1-%d: Could not read MAC from KNC1 card\n", 905 printk(KERN_ERR "KNC1-%d: Could not read MAC from KNC1 card\n",
874 budget_av->budget.dvb_adapter->num); 906 budget_av->budget.dvb_adapter.num);
875 memset(mac, 0, 6); 907 memset(mac, 0, 6);
876 } else { 908 } else {
877 printk("KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", 909 printk(KERN_INFO "KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
878 budget_av->budget.dvb_adapter->num, 910 budget_av->budget.dvb_adapter.num,
879 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 911 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
880 } 912 }
881 913
882 budget_av->budget.dvb_adapter->priv = budget_av; 914 budget_av->budget.dvb_adapter.priv = budget_av;
883 frontend_init(budget_av); 915 frontend_init(budget_av);
884 916
885 if (enable_ci)
886 ciintf_init(budget_av);
887
888 return 0; 917 return 0;
889} 918}
890 919
@@ -963,14 +992,21 @@ static struct saa7146_extension budget_extension;
963MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S); 992MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
964MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C); 993MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
965MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T); 994MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
995MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
996MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
997MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
966MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S); 998MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
967MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C); 999MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C);
968MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T); 1000MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
969 1001
970static struct pci_device_id pci_tbl[] = { 1002static struct pci_device_id pci_tbl[] = {
971 MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56), 1003 MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
1004 MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
1005 MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
972 MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020), 1006 MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
1007 MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
973 MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030), 1008 MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
1009 MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
974 MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154), 1010 MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154),
975 MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156), 1011 MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),
976 MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157), 1012 MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),
@@ -1010,5 +1046,3 @@ MODULE_LICENSE("GPL");
1010MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others"); 1046MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
1011MODULE_DESCRIPTION("driver for the SAA7146 based so-called " 1047MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1012 "budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)"); 1048 "budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)");
1013module_param_named(enable_ci, enable_ci, int, 0644);
1014MODULE_PARM_DESC(enable_ci, "Turn on/off CI module (default:off).");