diff options
Diffstat (limited to 'drivers/media/video/cx88')
-rw-r--r-- | drivers/media/video/cx88/cx88-alsa.c | 10 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-cards.c | 23 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-dvb.c | 214 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-input.c | 4 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-mpeg.c | 3 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88.h | 1 |
6 files changed, 249 insertions, 6 deletions
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 5a67445dd6ed..64b350df78e3 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c | |||
@@ -583,16 +583,18 @@ static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol, | |||
583 | { | 583 | { |
584 | snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); | 584 | snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); |
585 | struct cx88_core *core=chip->core; | 585 | struct cx88_core *core=chip->core; |
586 | int v, b; | 586 | int left, right, v, b; |
587 | int changed = 0; | 587 | int changed = 0; |
588 | u32 old; | 588 | u32 old; |
589 | 589 | ||
590 | b = value->value.integer.value[1] - value->value.integer.value[0]; | 590 | left = value->value.integer.value[0] & 0x3f; |
591 | right = value->value.integer.value[1] & 0x3f; | ||
592 | b = right - left; | ||
591 | if (b < 0) { | 593 | if (b < 0) { |
592 | v = 0x3f - value->value.integer.value[0]; | 594 | v = 0x3f - left; |
593 | b = (-b) | 0x40; | 595 | b = (-b) | 0x40; |
594 | } else { | 596 | } else { |
595 | v = 0x3f - value->value.integer.value[1]; | 597 | v = 0x3f - right; |
596 | } | 598 | } |
597 | /* Do we really know this will always be called with IRQs on? */ | 599 | /* Do we really know this will always be called with IRQs on? */ |
598 | spin_lock_irq(&chip->reg_lock); | 600 | spin_lock_irq(&chip->reg_lock); |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index d844f2aaa01d..eaf0ee7de832 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -1466,6 +1466,18 @@ static const struct cx88_board cx88_boards[] = { | |||
1466 | .audioroute = 8, | 1466 | .audioroute = 8, |
1467 | }, | 1467 | }, |
1468 | }, | 1468 | }, |
1469 | [CX88_BOARD_SAMSUNG_SMT_7020] = { | ||
1470 | .name = "Samsung SMT 7020 DVB-S", | ||
1471 | .tuner_type = TUNER_ABSENT, | ||
1472 | .radio_type = UNSET, | ||
1473 | .tuner_addr = ADDR_UNSET, | ||
1474 | .radio_addr = ADDR_UNSET, | ||
1475 | .input = { { | ||
1476 | .type = CX88_VMUX_DVB, | ||
1477 | .vmux = 0, | ||
1478 | } }, | ||
1479 | .mpeg = CX88_MPEG_DVB, | ||
1480 | }, | ||
1469 | [CX88_BOARD_ADSTECH_PTV_390] = { | 1481 | [CX88_BOARD_ADSTECH_PTV_390] = { |
1470 | .name = "ADS Tech Instant Video PCI", | 1482 | .name = "ADS Tech Instant Video PCI", |
1471 | .tuner_type = TUNER_ABSENT, | 1483 | .tuner_type = TUNER_ABSENT, |
@@ -2355,6 +2367,14 @@ static const struct cx88_subid cx88_subids[] = { | |||
2355 | .subvendor = 0x0070, | 2367 | .subvendor = 0x0070, |
2356 | .subdevice = 0x1404, | 2368 | .subdevice = 0x1404, |
2357 | .card = CX88_BOARD_HAUPPAUGE_HVR3000, | 2369 | .card = CX88_BOARD_HAUPPAUGE_HVR3000, |
2370 | }, { | ||
2371 | .subvendor = 0x18ac, | ||
2372 | .subdevice = 0xdc00, | ||
2373 | .card = CX88_BOARD_SAMSUNG_SMT_7020, | ||
2374 | }, { | ||
2375 | .subvendor = 0x18ac, | ||
2376 | .subdevice = 0xdccd, | ||
2377 | .card = CX88_BOARD_SAMSUNG_SMT_7020, | ||
2358 | },{ | 2378 | },{ |
2359 | .subvendor = 0x1461, | 2379 | .subvendor = 0x1461, |
2360 | .subdevice = 0xc111, /* AverMedia M150-D */ | 2380 | .subdevice = 0xc111, /* AverMedia M150-D */ |
@@ -2633,6 +2653,9 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) | |||
2633 | case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */ | 2653 | case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */ |
2634 | /* known */ | 2654 | /* known */ |
2635 | break; | 2655 | break; |
2656 | case CX88_BOARD_SAMSUNG_SMT_7020: | ||
2657 | cx_set(MO_GP0_IO, 0x008989FF); | ||
2658 | break; | ||
2636 | default: | 2659 | default: |
2637 | warn_printk(core, "warning: unknown hauppauge model #%d\n", | 2660 | warn_printk(core, "warning: unknown hauppauge model #%d\n", |
2638 | tv.model); | 2661 | tv.model); |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index b14296923250..94ab862f0219 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -674,6 +674,194 @@ static int cx8802_alloc_frontends(struct cx8802_dev *dev) | |||
674 | return 0; | 674 | return 0; |
675 | } | 675 | } |
676 | 676 | ||
677 | |||
678 | |||
679 | static u8 samsung_smt_7020_inittab[] = { | ||
680 | 0x01, 0x15, | ||
681 | 0x02, 0x00, | ||
682 | 0x03, 0x00, | ||
683 | 0x04, 0x7D, | ||
684 | 0x05, 0x0F, | ||
685 | 0x06, 0x02, | ||
686 | 0x07, 0x00, | ||
687 | 0x08, 0x60, | ||
688 | |||
689 | 0x0A, 0xC2, | ||
690 | 0x0B, 0x00, | ||
691 | 0x0C, 0x01, | ||
692 | 0x0D, 0x81, | ||
693 | 0x0E, 0x44, | ||
694 | 0x0F, 0x09, | ||
695 | 0x10, 0x3C, | ||
696 | 0x11, 0x84, | ||
697 | 0x12, 0xDA, | ||
698 | 0x13, 0x99, | ||
699 | 0x14, 0x8D, | ||
700 | 0x15, 0xCE, | ||
701 | 0x16, 0xE8, | ||
702 | 0x17, 0x43, | ||
703 | 0x18, 0x1C, | ||
704 | 0x19, 0x1B, | ||
705 | 0x1A, 0x1D, | ||
706 | |||
707 | 0x1C, 0x12, | ||
708 | 0x1D, 0x00, | ||
709 | 0x1E, 0x00, | ||
710 | 0x1F, 0x00, | ||
711 | 0x20, 0x00, | ||
712 | 0x21, 0x00, | ||
713 | 0x22, 0x00, | ||
714 | 0x23, 0x00, | ||
715 | |||
716 | 0x28, 0x02, | ||
717 | 0x29, 0x28, | ||
718 | 0x2A, 0x14, | ||
719 | 0x2B, 0x0F, | ||
720 | 0x2C, 0x09, | ||
721 | 0x2D, 0x05, | ||
722 | |||
723 | 0x31, 0x1F, | ||
724 | 0x32, 0x19, | ||
725 | 0x33, 0xFC, | ||
726 | 0x34, 0x13, | ||
727 | 0xff, 0xff, | ||
728 | }; | ||
729 | |||
730 | |||
731 | static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe, | ||
732 | struct dvb_frontend_parameters *params) | ||
733 | { | ||
734 | struct cx8802_dev *dev = fe->dvb->priv; | ||
735 | u8 buf[4]; | ||
736 | u32 div; | ||
737 | struct i2c_msg msg = { | ||
738 | .addr = 0x61, | ||
739 | .flags = 0, | ||
740 | .buf = buf, | ||
741 | .len = sizeof(buf) }; | ||
742 | |||
743 | div = params->frequency / 125; | ||
744 | |||
745 | buf[0] = (div >> 8) & 0x7f; | ||
746 | buf[1] = div & 0xff; | ||
747 | buf[2] = 0x84; /* 0xC4 */ | ||
748 | buf[3] = 0x00; | ||
749 | |||
750 | if (params->frequency < 1500000) | ||
751 | buf[3] |= 0x10; | ||
752 | |||
753 | if (fe->ops.i2c_gate_ctrl) | ||
754 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
755 | |||
756 | if (i2c_transfer(&dev->core->i2c_adap, &msg, 1) != 1) | ||
757 | return -EIO; | ||
758 | |||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | static int samsung_smt_7020_set_tone(struct dvb_frontend *fe, | ||
763 | fe_sec_tone_mode_t tone) | ||
764 | { | ||
765 | struct cx8802_dev *dev = fe->dvb->priv; | ||
766 | struct cx88_core *core = dev->core; | ||
767 | |||
768 | cx_set(MO_GP0_IO, 0x0800); | ||
769 | |||
770 | switch (tone) { | ||
771 | case SEC_TONE_ON: | ||
772 | cx_set(MO_GP0_IO, 0x08); | ||
773 | break; | ||
774 | case SEC_TONE_OFF: | ||
775 | cx_clear(MO_GP0_IO, 0x08); | ||
776 | break; | ||
777 | default: | ||
778 | return -EINVAL; | ||
779 | } | ||
780 | |||
781 | return 0; | ||
782 | } | ||
783 | |||
784 | static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe, | ||
785 | fe_sec_voltage_t voltage) | ||
786 | { | ||
787 | struct cx8802_dev *dev = fe->dvb->priv; | ||
788 | struct cx88_core *core = dev->core; | ||
789 | |||
790 | u8 data; | ||
791 | struct i2c_msg msg = { | ||
792 | .addr = 8, | ||
793 | .flags = 0, | ||
794 | .buf = &data, | ||
795 | .len = sizeof(data) }; | ||
796 | |||
797 | cx_set(MO_GP0_IO, 0x8000); | ||
798 | |||
799 | switch (voltage) { | ||
800 | case SEC_VOLTAGE_OFF: | ||
801 | break; | ||
802 | case SEC_VOLTAGE_13: | ||
803 | data = ISL6421_EN1 | ISL6421_LLC1; | ||
804 | cx_clear(MO_GP0_IO, 0x80); | ||
805 | break; | ||
806 | case SEC_VOLTAGE_18: | ||
807 | data = ISL6421_EN1 | ISL6421_LLC1 | ISL6421_VSEL1; | ||
808 | cx_clear(MO_GP0_IO, 0x80); | ||
809 | break; | ||
810 | default: | ||
811 | return -EINVAL; | ||
812 | }; | ||
813 | |||
814 | return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO; | ||
815 | } | ||
816 | |||
817 | static int samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend *fe, | ||
818 | u32 srate, u32 ratio) | ||
819 | { | ||
820 | u8 aclk = 0; | ||
821 | u8 bclk = 0; | ||
822 | |||
823 | if (srate < 1500000) { | ||
824 | aclk = 0xb7; | ||
825 | bclk = 0x47; | ||
826 | } else if (srate < 3000000) { | ||
827 | aclk = 0xb7; | ||
828 | bclk = 0x4b; | ||
829 | } else if (srate < 7000000) { | ||
830 | aclk = 0xb7; | ||
831 | bclk = 0x4f; | ||
832 | } else if (srate < 14000000) { | ||
833 | aclk = 0xb7; | ||
834 | bclk = 0x53; | ||
835 | } else if (srate < 30000000) { | ||
836 | aclk = 0xb6; | ||
837 | bclk = 0x53; | ||
838 | } else if (srate < 45000000) { | ||
839 | aclk = 0xb4; | ||
840 | bclk = 0x51; | ||
841 | } | ||
842 | |||
843 | stv0299_writereg(fe, 0x13, aclk); | ||
844 | stv0299_writereg(fe, 0x14, bclk); | ||
845 | stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); | ||
846 | stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); | ||
847 | stv0299_writereg(fe, 0x21, ratio & 0xf0); | ||
848 | |||
849 | return 0; | ||
850 | } | ||
851 | |||
852 | |||
853 | static struct stv0299_config samsung_stv0299_config = { | ||
854 | .demod_address = 0x68, | ||
855 | .inittab = samsung_smt_7020_inittab, | ||
856 | .mclk = 88000000UL, | ||
857 | .invert = 0, | ||
858 | .skip_reinit = 0, | ||
859 | .lock_output = STV0299_LOCKOUTPUT_LK, | ||
860 | .volt13_op0_op1 = STV0299_VOLT13_OP1, | ||
861 | .min_delay_ms = 100, | ||
862 | .set_symbol_rate = samsung_smt_7020_stv0299_set_symbol_rate, | ||
863 | }; | ||
864 | |||
677 | static int dvb_register(struct cx8802_dev *dev) | 865 | static int dvb_register(struct cx8802_dev *dev) |
678 | { | 866 | { |
679 | struct cx88_core *core = dev->core; | 867 | struct cx88_core *core = dev->core; |
@@ -1203,6 +1391,32 @@ static int dvb_register(struct cx8802_dev *dev) | |||
1203 | } | 1391 | } |
1204 | break; | 1392 | break; |
1205 | } | 1393 | } |
1394 | case CX88_BOARD_SAMSUNG_SMT_7020: | ||
1395 | dev->ts_gen_cntrl = 0x08; | ||
1396 | |||
1397 | cx_set(MO_GP0_IO, 0x0101); | ||
1398 | |||
1399 | cx_clear(MO_GP0_IO, 0x01); | ||
1400 | mdelay(100); | ||
1401 | cx_set(MO_GP0_IO, 0x01); | ||
1402 | mdelay(200); | ||
1403 | |||
1404 | fe0->dvb.frontend = dvb_attach(stv0299_attach, | ||
1405 | &samsung_stv0299_config, | ||
1406 | &dev->core->i2c_adap); | ||
1407 | if (fe0->dvb.frontend) { | ||
1408 | fe0->dvb.frontend->ops.tuner_ops.set_params = | ||
1409 | samsung_smt_7020_tuner_set_params; | ||
1410 | fe0->dvb.frontend->tuner_priv = | ||
1411 | &dev->core->i2c_adap; | ||
1412 | fe0->dvb.frontend->ops.set_voltage = | ||
1413 | samsung_smt_7020_set_voltage; | ||
1414 | fe0->dvb.frontend->ops.set_tone = | ||
1415 | samsung_smt_7020_set_tone; | ||
1416 | } | ||
1417 | |||
1418 | break; | ||
1419 | |||
1206 | default: | 1420 | default: |
1207 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", | 1421 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", |
1208 | core->name); | 1422 | core->name); |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index f9fda18b410c..de180d4d5a21 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -192,7 +192,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
192 | struct cx88_IR *ir; | 192 | struct cx88_IR *ir; |
193 | struct input_dev *input_dev; | 193 | struct input_dev *input_dev; |
194 | struct ir_scancode_table *ir_codes = NULL; | 194 | struct ir_scancode_table *ir_codes = NULL; |
195 | int ir_type = IR_TYPE_OTHER; | 195 | u64 ir_type = IR_TYPE_OTHER; |
196 | int err = -ENOMEM; | 196 | int err = -ENOMEM; |
197 | 197 | ||
198 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | 198 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); |
@@ -383,7 +383,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
383 | cx88_ir_start(core, ir); | 383 | cx88_ir_start(core, ir); |
384 | 384 | ||
385 | /* all done */ | 385 | /* all done */ |
386 | err = ir_input_register(ir->input, ir_codes); | 386 | err = ir_input_register(ir->input, ir_codes, NULL); |
387 | if (err) | 387 | if (err) |
388 | goto err_out_stop; | 388 | goto err_out_stop; |
389 | 389 | ||
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index bb5104893411..338af77f7f01 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c | |||
@@ -110,6 +110,9 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
110 | case CX88_BOARD_PCHDTV_HD5500: | 110 | case CX88_BOARD_PCHDTV_HD5500: |
111 | cx_write(TS_SOP_STAT, 1<<13); | 111 | cx_write(TS_SOP_STAT, 1<<13); |
112 | break; | 112 | break; |
113 | case CX88_BOARD_SAMSUNG_SMT_7020: | ||
114 | cx_write(TS_SOP_STAT, 0x00); | ||
115 | break; | ||
113 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | 116 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: |
114 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: | 117 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: |
115 | cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ | 118 | cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index b1499bf604ea..48b6c04fb497 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -239,6 +239,7 @@ extern struct sram_channel cx88_sram_channels[]; | |||
239 | #define CX88_BOARD_WINFAST_DTV1800H 81 | 239 | #define CX88_BOARD_WINFAST_DTV1800H 81 |
240 | #define CX88_BOARD_WINFAST_DTV2000H_J 82 | 240 | #define CX88_BOARD_WINFAST_DTV2000H_J 82 |
241 | #define CX88_BOARD_PROF_7301 83 | 241 | #define CX88_BOARD_PROF_7301 83 |
242 | #define CX88_BOARD_SAMSUNG_SMT_7020 84 | ||
242 | 243 | ||
243 | enum cx88_itype { | 244 | enum cx88_itype { |
244 | CX88_VMUX_COMPOSITE1 = 1, | 245 | CX88_VMUX_COMPOSITE1 = 1, |