aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx23885
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-09 22:50:49 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-09 22:50:49 -0500
commit3e7468313758913c5e4d372f35b271b96bad1298 (patch)
treeeb612d252a9e2349a1173451cd779beebd18a33e /drivers/media/video/cx23885
parent6825fbc4cb219f2c98bb7d157915d797cf5cb823 (diff)
parente97f4677961f68e29bd906022ebf60a6df7f530a (diff)
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (345 commits) V4L/DVB (13542): ir-keytable: Allow dynamic table change V4L/DVB (13541): atbm8830: replace 64-bit division and floating point usage V4L/DVB (13540): ir-common: Cleanup get key evdev code V4L/DVB (13539): ir-common: add __func__ for debug messages V4L/DVB (13538): ir-common: Use a dynamic keycode table V4L/DVB (13537): ir: Prepare the code for dynamic keycode table allocation V4L/DVB (13536): em28xx: Use the full RC5 code on HVR-950 Remote Controller V4L/DVB (13535): ir-common: Add a hauppauge new table with the complete RC5 code V4L/DVB (13534): ir-common: Remove some unused fields/structs V4L/DVB (13533): ir: use dynamic tables, instead of static ones V4L/DVB (13532): ir-common: Add infrastructure to use a dynamic keycode table V4L/DVB (13531): ir-common: rename the debug routine to allow exporting it V4L/DVB (13458): go7007: subdev conversion V4L/DVB (13457): s2250: subdev conversion V4L/DVB (13456): s2250: Change module structure V4L/DVB (13528): em28xx: add support for em2800 VC211A card em28xx: don't reduce scale to half size for em2800 em28xx: don't load audio modules when AC97 is mis-detected em28xx: em2800 chips support max width of 640 V4L/DVB (13523): dvb-bt8xx: fix compile warning ... Fix up trivial conflicts due to spelling fixes from the trivial tree in Documentation/video4linux/gspca.txt drivers/media/video/cx18/cx18-mailbox.h
Diffstat (limited to 'drivers/media/video/cx23885')
-rw-r--r--drivers/media/video/cx23885/Kconfig2
-rw-r--r--drivers/media/video/cx23885/Makefile3
-rw-r--r--drivers/media/video/cx23885/cx23885-417.c10
-rw-r--r--drivers/media/video/cx23885/cx23885-cards.c155
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c115
-rw-r--r--drivers/media/video/cx23885/cx23885-dvb.c158
-rw-r--r--drivers/media/video/cx23885/cx23885-f300.c177
-rw-r--r--drivers/media/video/cx23885/cx23885-f300.h2
-rw-r--r--drivers/media/video/cx23885/cx23885-input.c427
-rw-r--r--drivers/media/video/cx23885/cx23885-input.h30
-rw-r--r--drivers/media/video/cx23885/cx23885-ioctl.c208
-rw-r--r--drivers/media/video/cx23885/cx23885-ioctl.h39
-rw-r--r--drivers/media/video/cx23885/cx23885-ir.c101
-rw-r--r--drivers/media/video/cx23885/cx23885-ir.h31
-rw-r--r--drivers/media/video/cx23885/cx23885-reg.h5
-rw-r--r--drivers/media/video/cx23885/cx23885-video.c44
-rw-r--r--drivers/media/video/cx23885/cx23885.h31
-rw-r--r--drivers/media/video/cx23885/cx23888-ir.c1239
-rw-r--r--drivers/media/video/cx23885/cx23888-ir.h28
19 files changed, 2705 insertions, 100 deletions
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
index fd3fc3e3198a..bcdda9a9aa96 100644
--- a/drivers/media/video/cx23885/Kconfig
+++ b/drivers/media/video/cx23885/Kconfig
@@ -18,7 +18,9 @@ config VIDEO_CX23885
18 select DVB_TDA10048 if !DVB_FE_CUSTOMISE 18 select DVB_TDA10048 if !DVB_FE_CUSTOMISE
19 select DVB_LNBP21 if !DVB_FE_CUSTOMISE 19 select DVB_LNBP21 if !DVB_FE_CUSTOMISE
20 select DVB_STV6110 if !DVB_FE_CUSTOMISE 20 select DVB_STV6110 if !DVB_FE_CUSTOMISE
21 select DVB_CX24116 if !DVB_FE_CUSTOMISE
21 select DVB_STV0900 if !DVB_FE_CUSTOMISE 22 select DVB_STV0900 if !DVB_FE_CUSTOMISE
23 select DVB_DS3000 if !DVB_FE_CUSTOMISE
22 select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE 24 select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
23 select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE 25 select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
24 select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE 26 select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile
index ab8ea35c9bfb..5787ae243631 100644
--- a/drivers/media/video/cx23885/Makefile
+++ b/drivers/media/video/cx23885/Makefile
@@ -1,6 +1,7 @@
1cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ 1cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \
2 cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \ 2 cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \
3 netup-init.o cimax2.o netup-eeprom.o 3 cx23885-ioctl.o cx23885-ir.o cx23885-input.o cx23888-ir.o \
4 netup-init.o cimax2.o netup-eeprom.o cx23885-f300.o
4 5
5obj-$(CONFIG_VIDEO_CX23885) += cx23885.o 6obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
6 7
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c
index 6c3b51ce3372..0eed852c61e9 100644
--- a/drivers/media/video/cx23885/cx23885-417.c
+++ b/drivers/media/video/cx23885/cx23885-417.c
@@ -37,6 +37,7 @@
37#include <media/cx2341x.h> 37#include <media/cx2341x.h>
38 38
39#include "cx23885.h" 39#include "cx23885.h"
40#include "cx23885-ioctl.h"
40 41
41#define CX23885_FIRM_IMAGE_SIZE 376836 42#define CX23885_FIRM_IMAGE_SIZE 376836
42#define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw" 43#define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
@@ -318,7 +319,7 @@ static int mc417_wait_ready(struct cx23885_dev *dev)
318 } 319 }
319} 320}
320 321
321static int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value) 322int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value)
322{ 323{
323 u32 regval; 324 u32 regval;
324 325
@@ -382,7 +383,7 @@ static int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value)
382 return mc417_wait_ready(dev); 383 return mc417_wait_ready(dev);
383} 384}
384 385
385static int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value) 386int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value)
386{ 387{
387 int retval; 388 int retval;
388 u32 regval; 389 u32 regval;
@@ -1724,6 +1725,11 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
1724 .vidioc_log_status = vidioc_log_status, 1725 .vidioc_log_status = vidioc_log_status,
1725 .vidioc_querymenu = vidioc_querymenu, 1726 .vidioc_querymenu = vidioc_querymenu,
1726 .vidioc_queryctrl = vidioc_queryctrl, 1727 .vidioc_queryctrl = vidioc_queryctrl,
1728 .vidioc_g_chip_ident = cx23885_g_chip_ident,
1729#ifdef CONFIG_VIDEO_ADV_DEBUG
1730 .vidioc_g_register = cx23885_g_register,
1731 .vidioc_s_register = cx23885_s_register,
1732#endif
1727}; 1733};
1728 1734
1729static struct video_device cx23885_mpeg_template = { 1735static struct video_device cx23885_mpeg_template = {
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
index bfdf79f1033c..1ec48169277d 100644
--- a/drivers/media/video/cx23885/cx23885-cards.c
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -28,6 +28,7 @@
28#include "cx23885.h" 28#include "cx23885.h"
29#include "tuner-xc2028.h" 29#include "tuner-xc2028.h"
30#include "netup-init.h" 30#include "netup-init.h"
31#include "cx23888-ir.h"
31 32
32/* ------------------------------------------------------------------ */ 33/* ------------------------------------------------------------------ */
33/* board config info */ 34/* board config info */
@@ -199,11 +200,61 @@ struct cx23885_board cx23885_boards[] = {
199 }, 200 },
200 [CX23885_BOARD_MYGICA_X8506] = { 201 [CX23885_BOARD_MYGICA_X8506] = {
201 .name = "Mygica X8506 DMB-TH", 202 .name = "Mygica X8506 DMB-TH",
203 .tuner_type = TUNER_XC5000,
204 .tuner_addr = 0x61,
205 .porta = CX23885_ANALOG_VIDEO,
202 .portb = CX23885_MPEG_DVB, 206 .portb = CX23885_MPEG_DVB,
207 .input = {
208 {
209 .type = CX23885_VMUX_TELEVISION,
210 .vmux = CX25840_COMPOSITE2,
211 },
212 {
213 .type = CX23885_VMUX_COMPOSITE1,
214 .vmux = CX25840_COMPOSITE8,
215 },
216 {
217 .type = CX23885_VMUX_SVIDEO,
218 .vmux = CX25840_SVIDEO_LUMA3 |
219 CX25840_SVIDEO_CHROMA4,
220 },
221 {
222 .type = CX23885_VMUX_COMPONENT,
223 .vmux = CX25840_COMPONENT_ON |
224 CX25840_VIN1_CH1 |
225 CX25840_VIN6_CH2 |
226 CX25840_VIN7_CH3,
227 },
228 },
203 }, 229 },
204 [CX23885_BOARD_MAGICPRO_PROHDTVE2] = { 230 [CX23885_BOARD_MAGICPRO_PROHDTVE2] = {
205 .name = "Magic-Pro ProHDTV Extreme 2", 231 .name = "Magic-Pro ProHDTV Extreme 2",
232 .tuner_type = TUNER_XC5000,
233 .tuner_addr = 0x61,
234 .porta = CX23885_ANALOG_VIDEO,
206 .portb = CX23885_MPEG_DVB, 235 .portb = CX23885_MPEG_DVB,
236 .input = {
237 {
238 .type = CX23885_VMUX_TELEVISION,
239 .vmux = CX25840_COMPOSITE2,
240 },
241 {
242 .type = CX23885_VMUX_COMPOSITE1,
243 .vmux = CX25840_COMPOSITE8,
244 },
245 {
246 .type = CX23885_VMUX_SVIDEO,
247 .vmux = CX25840_SVIDEO_LUMA3 |
248 CX25840_SVIDEO_CHROMA4,
249 },
250 {
251 .type = CX23885_VMUX_COMPONENT,
252 .vmux = CX25840_COMPONENT_ON |
253 CX25840_VIN1_CH1 |
254 CX25840_VIN6_CH2 |
255 CX25840_VIN7_CH3,
256 },
257 },
207 }, 258 },
208 [CX23885_BOARD_HAUPPAUGE_HVR1850] = { 259 [CX23885_BOARD_HAUPPAUGE_HVR1850] = {
209 .name = "Hauppauge WinTV-HVR1850", 260 .name = "Hauppauge WinTV-HVR1850",
@@ -214,6 +265,15 @@ struct cx23885_board cx23885_boards[] = {
214 .name = "Compro VideoMate E800", 265 .name = "Compro VideoMate E800",
215 .portc = CX23885_MPEG_DVB, 266 .portc = CX23885_MPEG_DVB,
216 }, 267 },
268 [CX23885_BOARD_HAUPPAUGE_HVR1290] = {
269 .name = "Hauppauge WinTV-HVR1290",
270 .portc = CX23885_MPEG_DVB,
271 },
272 [CX23885_BOARD_MYGICA_X8558PRO] = {
273 .name = "Mygica X8558 PRO DMB-TH",
274 .portb = CX23885_MPEG_DVB,
275 .portc = CX23885_MPEG_DVB,
276 },
217}; 277};
218const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); 278const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
219 279
@@ -349,6 +409,14 @@ struct cx23885_subid cx23885_subids[] = {
349 .subvendor = 0x1858, 409 .subvendor = 0x1858,
350 .subdevice = 0xe800, 410 .subdevice = 0xe800,
351 .card = CX23885_BOARD_COMPRO_VIDEOMATE_E800, 411 .card = CX23885_BOARD_COMPRO_VIDEOMATE_E800,
412 }, {
413 .subvendor = 0x0070,
414 .subdevice = 0x8551,
415 .card = CX23885_BOARD_HAUPPAUGE_HVR1290,
416 }, {
417 .subvendor = 0x14f1,
418 .subdevice = 0x8578,
419 .card = CX23885_BOARD_MYGICA_X8558PRO,
352 }, 420 },
353}; 421};
354const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); 422const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -509,9 +577,13 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
509 * DVB-T and MPEG2 HW Encoder */ 577 * DVB-T and MPEG2 HW Encoder */
510 break; 578 break;
511 case 85021: 579 case 85021:
512 /* WinTV-HVR1850 (PCIe, OEM, RCA in, IR, FM, 580 /* WinTV-HVR1850 (PCIe, Retail, 3.5mm in, IR, FM,
513 Dual channel ATSC and MPEG2 HW Encoder */ 581 Dual channel ATSC and MPEG2 HW Encoder */
514 break; 582 break;
583 case 85721:
584 /* WinTV-HVR1290 (PCIe, OEM, RCA in, IR,
585 Dual channel ATSC and Basic analog */
586 break;
515 default: 587 default:
516 printk(KERN_WARNING "%s: warning: " 588 printk(KERN_WARNING "%s: warning: "
517 "unknown hauppauge model #%d\n", 589 "unknown hauppauge model #%d\n",
@@ -710,10 +782,14 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
710 cx_set(GP0_IO, 0x00040004); 782 cx_set(GP0_IO, 0x00040004);
711 break; 783 break;
712 case CX23885_BOARD_TBS_6920: 784 case CX23885_BOARD_TBS_6920:
713 case CX23885_BOARD_TEVII_S470:
714 cx_write(MC417_CTL, 0x00000036); 785 cx_write(MC417_CTL, 0x00000036);
715 cx_write(MC417_OEN, 0x00001000); 786 cx_write(MC417_OEN, 0x00001000);
716 cx_write(MC417_RWD, 0x00001800); 787 cx_set(MC417_RWD, 0x00000002);
788 mdelay(200);
789 cx_clear(MC417_RWD, 0x00000800);
790 mdelay(200);
791 cx_set(MC417_RWD, 0x00000800);
792 mdelay(200);
717 break; 793 break;
718 case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: 794 case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
719 /* GPIO-0 INTA from CiMax1 795 /* GPIO-0 INTA from CiMax1
@@ -758,15 +834,26 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
758 break; 834 break;
759 case CX23885_BOARD_MYGICA_X8506: 835 case CX23885_BOARD_MYGICA_X8506:
760 case CX23885_BOARD_MAGICPRO_PROHDTVE2: 836 case CX23885_BOARD_MAGICPRO_PROHDTVE2:
837 /* GPIO-0 (0)Analog / (1)Digital TV */
761 /* GPIO-1 reset XC5000 */ 838 /* GPIO-1 reset XC5000 */
762 /* GPIO-2 reset LGS8GL5 / LGS8G75 */ 839 /* GPIO-2 reset LGS8GL5 / LGS8G75 */
763 cx_set(GP0_IO, 0x00060000); 840 cx23885_gpio_enable(dev, GPIO_0 | GPIO_1 | GPIO_2, 1);
764 cx_clear(GP0_IO, 0x00000006); 841 cx23885_gpio_clear(dev, GPIO_1 | GPIO_2);
765 mdelay(100); 842 mdelay(100);
766 cx_set(GP0_IO, 0x00060006); 843 cx23885_gpio_set(dev, GPIO_0 | GPIO_1 | GPIO_2);
844 mdelay(100);
845 break;
846 case CX23885_BOARD_MYGICA_X8558PRO:
847 /* GPIO-0 reset first ATBM8830 */
848 /* GPIO-1 reset second ATBM8830 */
849 cx23885_gpio_enable(dev, GPIO_0 | GPIO_1, 1);
850 cx23885_gpio_clear(dev, GPIO_0 | GPIO_1);
851 mdelay(100);
852 cx23885_gpio_set(dev, GPIO_0 | GPIO_1);
767 mdelay(100); 853 mdelay(100);
768 break; 854 break;
769 case CX23885_BOARD_HAUPPAUGE_HVR1850: 855 case CX23885_BOARD_HAUPPAUGE_HVR1850:
856 case CX23885_BOARD_HAUPPAUGE_HVR1290:
770 /* GPIO-0 656_CLK */ 857 /* GPIO-0 656_CLK */
771 /* GPIO-1 656_D0 */ 858 /* GPIO-1 656_D0 */
772 /* GPIO-2 Wake# */ 859 /* GPIO-2 Wake# */
@@ -801,6 +888,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
801 888
802int cx23885_ir_init(struct cx23885_dev *dev) 889int cx23885_ir_init(struct cx23885_dev *dev)
803{ 890{
891 int ret = 0;
804 switch (dev->board) { 892 switch (dev->board) {
805 case CX23885_BOARD_HAUPPAUGE_HVR1250: 893 case CX23885_BOARD_HAUPPAUGE_HVR1250:
806 case CX23885_BOARD_HAUPPAUGE_HVR1500: 894 case CX23885_BOARD_HAUPPAUGE_HVR1500:
@@ -812,15 +900,46 @@ int cx23885_ir_init(struct cx23885_dev *dev)
812 case CX23885_BOARD_HAUPPAUGE_HVR1275: 900 case CX23885_BOARD_HAUPPAUGE_HVR1275:
813 case CX23885_BOARD_HAUPPAUGE_HVR1255: 901 case CX23885_BOARD_HAUPPAUGE_HVR1255:
814 case CX23885_BOARD_HAUPPAUGE_HVR1210: 902 case CX23885_BOARD_HAUPPAUGE_HVR1210:
815 case CX23885_BOARD_HAUPPAUGE_HVR1850:
816 /* FIXME: Implement me */ 903 /* FIXME: Implement me */
817 break; 904 break;
905 case CX23885_BOARD_HAUPPAUGE_HVR1850:
906 case CX23885_BOARD_HAUPPAUGE_HVR1290:
907 ret = cx23888_ir_probe(dev);
908 if (ret)
909 break;
910 dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR);
911 dev->pci_irqmask |= PCI_MSK_IR;
912 break;
818 case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: 913 case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
819 request_module("ir-kbd-i2c"); 914 request_module("ir-kbd-i2c");
820 break; 915 break;
821 } 916 }
822 917
823 return 0; 918 return ret;
919}
920
921void cx23885_ir_fini(struct cx23885_dev *dev)
922{
923 switch (dev->board) {
924 case CX23885_BOARD_HAUPPAUGE_HVR1850:
925 case CX23885_BOARD_HAUPPAUGE_HVR1290:
926 dev->pci_irqmask &= ~PCI_MSK_IR;
927 cx_clear(PCI_INT_MSK, PCI_MSK_IR);
928 cx23888_ir_remove(dev);
929 dev->sd_ir = NULL;
930 break;
931 }
932}
933
934void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
935{
936 switch (dev->board) {
937 case CX23885_BOARD_HAUPPAUGE_HVR1850:
938 case CX23885_BOARD_HAUPPAUGE_HVR1290:
939 if (dev->sd_ir && (dev->pci_irqmask & PCI_MSK_IR))
940 cx_set(PCI_INT_MSK, PCI_MSK_IR);
941 break;
942 }
824} 943}
825 944
826void cx23885_card_setup(struct cx23885_dev *dev) 945void cx23885_card_setup(struct cx23885_dev *dev)
@@ -853,6 +972,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
853 case CX23885_BOARD_HAUPPAUGE_HVR1255: 972 case CX23885_BOARD_HAUPPAUGE_HVR1255:
854 case CX23885_BOARD_HAUPPAUGE_HVR1210: 973 case CX23885_BOARD_HAUPPAUGE_HVR1210:
855 case CX23885_BOARD_HAUPPAUGE_HVR1850: 974 case CX23885_BOARD_HAUPPAUGE_HVR1850:
975 case CX23885_BOARD_HAUPPAUGE_HVR1290:
856 if (dev->i2c_bus[0].i2c_rc == 0) 976 if (dev->i2c_bus[0].i2c_rc == 0)
857 hauppauge_eeprom(dev, eeprom+0xc0); 977 hauppauge_eeprom(dev, eeprom+0xc0);
858 break; 978 break;
@@ -886,8 +1006,12 @@ void cx23885_card_setup(struct cx23885_dev *dev)
886 ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ 1006 ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
887 ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; 1007 ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
888 break; 1008 break;
889 case CX23885_BOARD_TEVII_S470:
890 case CX23885_BOARD_TBS_6920: 1009 case CX23885_BOARD_TBS_6920:
1010 ts1->gen_ctrl_val = 0x4; /* Parallel */
1011 ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
1012 ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
1013 break;
1014 case CX23885_BOARD_TEVII_S470:
891 case CX23885_BOARD_DVBWORLD_2005: 1015 case CX23885_BOARD_DVBWORLD_2005:
892 ts1->gen_ctrl_val = 0x5; /* Parallel */ 1016 ts1->gen_ctrl_val = 0x5; /* Parallel */
893 ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ 1017 ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
@@ -907,6 +1031,14 @@ void cx23885_card_setup(struct cx23885_dev *dev)
907 ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ 1031 ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
908 ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; 1032 ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
909 break; 1033 break;
1034 case CX23885_BOARD_MYGICA_X8558PRO:
1035 ts1->gen_ctrl_val = 0x5; /* Parallel */
1036 ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
1037 ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
1038 ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
1039 ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
1040 ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
1041 break;
910 case CX23885_BOARD_HAUPPAUGE_HVR1250: 1042 case CX23885_BOARD_HAUPPAUGE_HVR1250:
911 case CX23885_BOARD_HAUPPAUGE_HVR1500: 1043 case CX23885_BOARD_HAUPPAUGE_HVR1500:
912 case CX23885_BOARD_HAUPPAUGE_HVR1500Q: 1044 case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
@@ -922,6 +1054,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
922 case CX23885_BOARD_HAUPPAUGE_HVR1210: 1054 case CX23885_BOARD_HAUPPAUGE_HVR1210:
923 case CX23885_BOARD_HAUPPAUGE_HVR1850: 1055 case CX23885_BOARD_HAUPPAUGE_HVR1850:
924 case CX23885_BOARD_COMPRO_VIDEOMATE_E800: 1056 case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
1057 case CX23885_BOARD_HAUPPAUGE_HVR1290:
925 default: 1058 default:
926 ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ 1059 ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
927 ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ 1060 ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
@@ -939,6 +1072,10 @@ void cx23885_card_setup(struct cx23885_dev *dev)
939 case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: 1072 case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
940 case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: 1073 case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
941 case CX23885_BOARD_COMPRO_VIDEOMATE_E800: 1074 case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
1075 case CX23885_BOARD_HAUPPAUGE_HVR1850:
1076 case CX23885_BOARD_MYGICA_X8506:
1077 case CX23885_BOARD_MAGICPRO_PROHDTVE2:
1078 case CX23885_BOARD_HAUPPAUGE_HVR1290:
942 dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, 1079 dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
943 &dev->i2c_bus[2].i2c_adap, 1080 &dev->i2c_bus[2].i2c_adap,
944 "cx25840", "cx25840", 0x88 >> 1, NULL); 1081 "cx25840", "cx25840", 0x88 >> 1, NULL);
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index fa2d350e20fd..04b12d27bc13 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -32,6 +32,9 @@
32 32
33#include "cx23885.h" 33#include "cx23885.h"
34#include "cimax2.h" 34#include "cimax2.h"
35#include "cx23888-ir.h"
36#include "cx23885-ir.h"
37#include "cx23885-input.h"
35 38
36MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); 39MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
37MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); 40MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
@@ -753,6 +756,23 @@ static void cx23885_dev_checkrevision(struct cx23885_dev *dev)
753 __func__, dev->hwrevision); 756 __func__, dev->hwrevision);
754} 757}
755 758
759/* Find the first v4l2_subdev member of the group id in hw */
760struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw)
761{
762 struct v4l2_subdev *result = NULL;
763 struct v4l2_subdev *sd;
764
765 spin_lock(&dev->v4l2_dev.lock);
766 v4l2_device_for_each_subdev(sd, &dev->v4l2_dev) {
767 if (sd->grp_id == hw) {
768 result = sd;
769 break;
770 }
771 }
772 spin_unlock(&dev->v4l2_dev.lock);
773 return result;
774}
775
756static int cx23885_dev_setup(struct cx23885_dev *dev) 776static int cx23885_dev_setup(struct cx23885_dev *dev)
757{ 777{
758 int i; 778 int i;
@@ -899,7 +919,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
899 cx23885_i2c_register(&dev->i2c_bus[1]); 919 cx23885_i2c_register(&dev->i2c_bus[1]);
900 cx23885_i2c_register(&dev->i2c_bus[2]); 920 cx23885_i2c_register(&dev->i2c_bus[2]);
901 cx23885_card_setup(dev); 921 cx23885_card_setup(dev);
902 call_all(dev, tuner, s_standby); 922 call_all(dev, core, s_power, 0);
903 cx23885_ir_init(dev); 923 cx23885_ir_init(dev);
904 924
905 if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) { 925 if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) {
@@ -1637,6 +1657,7 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1637 u32 ts1_status, ts1_mask; 1657 u32 ts1_status, ts1_mask;
1638 u32 ts2_status, ts2_mask; 1658 u32 ts2_status, ts2_mask;
1639 int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0; 1659 int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0;
1660 bool ir_handled = false;
1640 1661
1641 pci_status = cx_read(PCI_INT_STAT); 1662 pci_status = cx_read(PCI_INT_STAT);
1642 pci_mask = cx_read(PCI_INT_MSK); 1663 pci_mask = cx_read(PCI_INT_MSK);
@@ -1662,18 +1683,12 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1662 dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n", 1683 dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n",
1663 ts2_status, ts2_mask, ts2_count); 1684 ts2_status, ts2_mask, ts2_count);
1664 1685
1665 if ((pci_status & PCI_MSK_RISC_RD) || 1686 if (pci_status & (PCI_MSK_RISC_RD | PCI_MSK_RISC_WR |
1666 (pci_status & PCI_MSK_RISC_WR) || 1687 PCI_MSK_AL_RD | PCI_MSK_AL_WR | PCI_MSK_APB_DMA |
1667 (pci_status & PCI_MSK_AL_RD) || 1688 PCI_MSK_VID_C | PCI_MSK_VID_B | PCI_MSK_VID_A |
1668 (pci_status & PCI_MSK_AL_WR) || 1689 PCI_MSK_AUD_INT | PCI_MSK_AUD_EXT |
1669 (pci_status & PCI_MSK_APB_DMA) || 1690 PCI_MSK_GPIO0 | PCI_MSK_GPIO1 |
1670 (pci_status & PCI_MSK_VID_C) || 1691 PCI_MSK_IR)) {
1671 (pci_status & PCI_MSK_VID_B) ||
1672 (pci_status & PCI_MSK_VID_A) ||
1673 (pci_status & PCI_MSK_AUD_INT) ||
1674 (pci_status & PCI_MSK_AUD_EXT) ||
1675 (pci_status & PCI_MSK_GPIO0) ||
1676 (pci_status & PCI_MSK_GPIO1)) {
1677 1692
1678 if (pci_status & PCI_MSK_RISC_RD) 1693 if (pci_status & PCI_MSK_RISC_RD)
1679 dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n", 1694 dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n",
@@ -1722,6 +1737,10 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1722 if (pci_status & PCI_MSK_GPIO1) 1737 if (pci_status & PCI_MSK_GPIO1)
1723 dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n", 1738 dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n",
1724 PCI_MSK_GPIO1); 1739 PCI_MSK_GPIO1);
1740
1741 if (pci_status & PCI_MSK_IR)
1742 dprintk(7, " (PCI_MSK_IR 0x%08x)\n",
1743 PCI_MSK_IR);
1725 } 1744 }
1726 1745
1727 if (cx23885_boards[dev->board].cimax > 0 && 1746 if (cx23885_boards[dev->board].cimax > 0 &&
@@ -1752,12 +1771,48 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1752 if (vida_status) 1771 if (vida_status)
1753 handled += cx23885_video_irq(dev, vida_status); 1772 handled += cx23885_video_irq(dev, vida_status);
1754 1773
1774 if (pci_status & PCI_MSK_IR) {
1775 v4l2_subdev_call(dev->sd_ir, ir, interrupt_service_routine,
1776 pci_status, &ir_handled);
1777 if (ir_handled)
1778 handled++;
1779 }
1780
1755 if (handled) 1781 if (handled)
1756 cx_write(PCI_INT_STAT, pci_status); 1782 cx_write(PCI_INT_STAT, pci_status);
1757out: 1783out:
1758 return IRQ_RETVAL(handled); 1784 return IRQ_RETVAL(handled);
1759} 1785}
1760 1786
1787static void cx23885_v4l2_dev_notify(struct v4l2_subdev *sd,
1788 unsigned int notification, void *arg)
1789{
1790 struct cx23885_dev *dev;
1791
1792 if (sd == NULL)
1793 return;
1794
1795 dev = to_cx23885(sd->v4l2_dev);
1796
1797 switch (notification) {
1798 case V4L2_SUBDEV_IR_RX_NOTIFY: /* Called in an IRQ context */
1799 if (sd == dev->sd_ir)
1800 cx23885_ir_rx_v4l2_dev_notify(sd, *(u32 *)arg);
1801 break;
1802 case V4L2_SUBDEV_IR_TX_NOTIFY: /* Called in an IRQ context */
1803 if (sd == dev->sd_ir)
1804 cx23885_ir_tx_v4l2_dev_notify(sd, *(u32 *)arg);
1805 break;
1806 }
1807}
1808
1809static void cx23885_v4l2_dev_notify_init(struct cx23885_dev *dev)
1810{
1811 INIT_WORK(&dev->ir_rx_work, cx23885_ir_rx_work_handler);
1812 INIT_WORK(&dev->ir_tx_work, cx23885_ir_tx_work_handler);
1813 dev->v4l2_dev.notify = cx23885_v4l2_dev_notify;
1814}
1815
1761static inline int encoder_on_portb(struct cx23885_dev *dev) 1816static inline int encoder_on_portb(struct cx23885_dev *dev)
1762{ 1817{
1763 return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER; 1818 return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER;
@@ -1816,6 +1871,26 @@ void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask)
1816 printk(KERN_INFO "%s: Unsupported\n", dev->name); 1871 printk(KERN_INFO "%s: Unsupported\n", dev->name);
1817} 1872}
1818 1873
1874u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask)
1875{
1876 if (mask & 0x00000007)
1877 return (cx_read(GP0_IO) >> 8) & mask & 0x7;
1878
1879 if (mask & 0x0007fff8) {
1880 if (encoder_on_portb(dev) || encoder_on_portc(dev))
1881 printk(KERN_ERR
1882 "%s: Reading GPIO moving on encoder ports\n",
1883 dev->name);
1884 return (cx_read(MC417_RWD) & ((mask & 0x7fff8) >> 3)) << 3;
1885 }
1886
1887 /* TODO: 23-19 */
1888 if (mask & 0x00f80000)
1889 printk(KERN_INFO "%s: Unsupported\n", dev->name);
1890
1891 return 0;
1892}
1893
1819void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput) 1894void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput)
1820{ 1895{
1821 if ((mask & 0x00000007) && asoutput) 1896 if ((mask & 0x00000007) && asoutput)
@@ -1854,6 +1929,9 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
1854 if (err < 0) 1929 if (err < 0)
1855 goto fail_free; 1930 goto fail_free;
1856 1931
1932 /* Prepare to handle notifications from subdevices */
1933 cx23885_v4l2_dev_notify_init(dev);
1934
1857 /* pci init */ 1935 /* pci init */
1858 dev->pci = pci_dev; 1936 dev->pci = pci_dev;
1859 if (pci_enable_device(pci_dev)) { 1937 if (pci_enable_device(pci_dev)) {
@@ -1896,6 +1974,14 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
1896 break; 1974 break;
1897 } 1975 }
1898 1976
1977 /*
1978 * The CX2388[58] IR controller can start firing interrupts when
1979 * enabled, so these have to take place after the cx23885_irq() handler
1980 * is hooked up by the call to request_irq() above.
1981 */
1982 cx23885_ir_pci_int_enable(dev);
1983 cx23885_input_init(dev);
1984
1899 return 0; 1985 return 0;
1900 1986
1901fail_irq: 1987fail_irq:
@@ -1912,6 +1998,9 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev)
1912 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); 1998 struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
1913 struct cx23885_dev *dev = to_cx23885(v4l2_dev); 1999 struct cx23885_dev *dev = to_cx23885(v4l2_dev);
1914 2000
2001 cx23885_input_fini(dev);
2002 cx23885_ir_fini(dev);
2003
1915 cx23885_shutdown(dev); 2004 cx23885_shutdown(dev);
1916 2005
1917 pci_disable_device(pci_dev); 2006 pci_disable_device(pci_dev);
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
index 16c6a921f40b..e45d2df08138 100644
--- a/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/drivers/media/video/cx23885/cx23885-dvb.c
@@ -38,6 +38,7 @@
38#include "tda18271.h" 38#include "tda18271.h"
39#include "lgdt330x.h" 39#include "lgdt330x.h"
40#include "xc5000.h" 40#include "xc5000.h"
41#include "max2165.h"
41#include "tda10048.h" 42#include "tda10048.h"
42#include "tuner-xc2028.h" 43#include "tuner-xc2028.h"
43#include "tuner-simple.h" 44#include "tuner-simple.h"
@@ -54,6 +55,9 @@
54#include "netup-eeprom.h" 55#include "netup-eeprom.h"
55#include "netup-init.h" 56#include "netup-init.h"
56#include "lgdt3305.h" 57#include "lgdt3305.h"
58#include "atbm8830.h"
59#include "ds3000.h"
60#include "cx23885-f300.h"
57 61
58static unsigned int debug; 62static unsigned int debug;
59 63
@@ -400,6 +404,7 @@ static struct stv0900_reg stv0900_ts_regs[] = {
400 404
401static struct stv0900_config netup_stv0900_config = { 405static struct stv0900_config netup_stv0900_config = {
402 .demod_address = 0x68, 406 .demod_address = 0x68,
407 .demod_mode = 1, /* dual */
403 .xtal = 8000000, 408 .xtal = 8000000,
404 .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ 409 .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
405 .diseqc_mode = 2,/* 2/3 PWM */ 410 .diseqc_mode = 2,/* 2/3 PWM */
@@ -414,34 +419,22 @@ static struct stv6110_config netup_stv6110_tunerconfig_a = {
414 .i2c_address = 0x60, 419 .i2c_address = 0x60,
415 .mclk = 16000000, 420 .mclk = 16000000,
416 .clk_div = 1, 421 .clk_div = 1,
422 .gain = 8, /* +16 dB - maximum gain */
417}; 423};
418 424
419static struct stv6110_config netup_stv6110_tunerconfig_b = { 425static struct stv6110_config netup_stv6110_tunerconfig_b = {
420 .i2c_address = 0x63, 426 .i2c_address = 0x63,
421 .mclk = 16000000, 427 .mclk = 16000000,
422 .clk_div = 1, 428 .clk_div = 1,
429 .gain = 8, /* +16 dB - maximum gain */
423}; 430};
424 431
425static int tbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
426{
427 struct cx23885_tsport *port = fe->dvb->priv;
428 struct cx23885_dev *dev = port->dev;
429
430 if (voltage == SEC_VOLTAGE_18)
431 cx_write(MC417_RWD, 0x00001e00);/* GPIO-13 high */
432 else if (voltage == SEC_VOLTAGE_13)
433 cx_write(MC417_RWD, 0x00001a00);/* GPIO-13 low */
434 else
435 cx_write(MC417_RWD, 0x00001800);/* GPIO-12 low */
436 return 0;
437}
438
439static struct cx24116_config tbs_cx24116_config = { 432static struct cx24116_config tbs_cx24116_config = {
440 .demod_address = 0x05, 433 .demod_address = 0x55,
441}; 434};
442 435
443static struct cx24116_config tevii_cx24116_config = { 436static struct ds3000_config tevii_ds3000_config = {
444 .demod_address = 0x55, 437 .demod_address = 0x68,
445}; 438};
446 439
447static struct cx24116_config dvbworld_cx24116_config = { 440static struct cx24116_config dvbworld_cx24116_config = {
@@ -486,11 +479,40 @@ static int cx23885_dvb_set_frontend(struct dvb_frontend *fe,
486 break; 479 break;
487 } 480 }
488 break; 481 break;
482 case CX23885_BOARD_MYGICA_X8506:
483 case CX23885_BOARD_MAGICPRO_PROHDTVE2:
484 /* Select Digital TV */
485 cx23885_gpio_set(dev, GPIO_0);
486 break;
489 } 487 }
490 return (port->set_frontend_save) ? 488 return 0;
491 port->set_frontend_save(fe, param) : -ENODEV;
492} 489}
493 490
491static int cx23885_dvb_fe_ioctl_override(struct dvb_frontend *fe,
492 unsigned int cmd, void *parg,
493 unsigned int stage)
494{
495 int err = 0;
496
497 switch (stage) {
498 case DVB_FE_IOCTL_PRE:
499
500 switch (cmd) {
501 case FE_SET_FRONTEND:
502 err = cx23885_dvb_set_frontend(fe,
503 (struct dvb_frontend_parameters *) parg);
504 break;
505 }
506 break;
507
508 case DVB_FE_IOCTL_POST:
509 /* no post-ioctl handling required */
510 break;
511 }
512 return err;
513};
514
515
494static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = { 516static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = {
495 .prod = LGS8GXX_PROD_LGS8G75, 517 .prod = LGS8GXX_PROD_LGS8G75,
496 .demod_address = 0x19, 518 .demod_address = 0x19,
@@ -511,6 +533,38 @@ static struct xc5000_config magicpro_prohdtve2_xc5000_config = {
511 .if_khz = 6500, 533 .if_khz = 6500,
512}; 534};
513 535
536static struct atbm8830_config mygica_x8558pro_atbm8830_cfg1 = {
537 .prod = ATBM8830_PROD_8830,
538 .demod_address = 0x44,
539 .serial_ts = 0,
540 .ts_sampling_edge = 1,
541 .ts_clk_gated = 0,
542 .osc_clk_freq = 30400, /* in kHz */
543 .if_freq = 0, /* zero IF */
544 .zif_swap_iq = 1,
545};
546
547static struct max2165_config mygic_x8558pro_max2165_cfg1 = {
548 .i2c_address = 0x60,
549 .osc_clk = 20
550};
551
552static struct atbm8830_config mygica_x8558pro_atbm8830_cfg2 = {
553 .prod = ATBM8830_PROD_8830,
554 .demod_address = 0x44,
555 .serial_ts = 1,
556 .ts_sampling_edge = 1,
557 .ts_clk_gated = 0,
558 .osc_clk_freq = 30400, /* in kHz */
559 .if_freq = 0, /* zero IF */
560 .zif_swap_iq = 1,
561};
562
563static struct max2165_config mygic_x8558pro_max2165_cfg2 = {
564 .i2c_address = 0x60,
565 .osc_clk = 20
566};
567
514static int dvb_register(struct cx23885_tsport *port) 568static int dvb_register(struct cx23885_tsport *port)
515{ 569{
516 struct cx23885_dev *dev = port->dev; 570 struct cx23885_dev *dev = port->dev;
@@ -550,12 +604,6 @@ static int dvb_register(struct cx23885_tsport *port)
550 0x60, &dev->i2c_bus[1].i2c_adap, 604 0x60, &dev->i2c_bus[1].i2c_adap,
551 &hauppauge_hvr127x_config); 605 &hauppauge_hvr127x_config);
552 } 606 }
553
554 /* FIXME: temporary hack */
555 /* define bridge override to set_frontend */
556 port->set_frontend_save = fe0->dvb.frontend->ops.set_frontend;
557 fe0->dvb.frontend->ops.set_frontend = cx23885_dvb_set_frontend;
558
559 break; 607 break;
560 case CX23885_BOARD_HAUPPAUGE_HVR1255: 608 case CX23885_BOARD_HAUPPAUGE_HVR1255:
561 i2c_bus = &dev->i2c_bus[0]; 609 i2c_bus = &dev->i2c_bus[0];
@@ -772,23 +820,23 @@ static int dvb_register(struct cx23885_tsport *port)
772 } 820 }
773 break; 821 break;
774 case CX23885_BOARD_TBS_6920: 822 case CX23885_BOARD_TBS_6920:
775 i2c_bus = &dev->i2c_bus[0]; 823 i2c_bus = &dev->i2c_bus[1];
776 824
777 fe0->dvb.frontend = dvb_attach(cx24116_attach, 825 fe0->dvb.frontend = dvb_attach(cx24116_attach,
778 &tbs_cx24116_config, 826 &tbs_cx24116_config,
779 &i2c_bus->i2c_adap); 827 &i2c_bus->i2c_adap);
780 if (fe0->dvb.frontend != NULL) 828 if (fe0->dvb.frontend != NULL)
781 fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage; 829 fe0->dvb.frontend->ops.set_voltage = f300_set_voltage;
782 830
783 break; 831 break;
784 case CX23885_BOARD_TEVII_S470: 832 case CX23885_BOARD_TEVII_S470:
785 i2c_bus = &dev->i2c_bus[1]; 833 i2c_bus = &dev->i2c_bus[1];
786 834
787 fe0->dvb.frontend = dvb_attach(cx24116_attach, 835 fe0->dvb.frontend = dvb_attach(ds3000_attach,
788 &tevii_cx24116_config, 836 &tevii_ds3000_config,
789 &i2c_bus->i2c_adap); 837 &i2c_bus->i2c_adap);
790 if (fe0->dvb.frontend != NULL) 838 if (fe0->dvb.frontend != NULL)
791 fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage; 839 fe0->dvb.frontend->ops.set_voltage = f300_set_voltage;
792 840
793 break; 841 break;
794 case CX23885_BOARD_DVBWORLD_2005: 842 case CX23885_BOARD_DVBWORLD_2005:
@@ -814,8 +862,8 @@ static int dvb_register(struct cx23885_tsport *port)
814 if (!dvb_attach(lnbh24_attach, 862 if (!dvb_attach(lnbh24_attach,
815 fe0->dvb.frontend, 863 fe0->dvb.frontend,
816 &i2c_bus->i2c_adap, 864 &i2c_bus->i2c_adap,
817 LNBH24_PCL, 865 LNBH24_PCL | LNBH24_TTX,
818 LNBH24_TTX, 0x09)) 866 LNBH24_TEN, 0x09))
819 printk(KERN_ERR 867 printk(KERN_ERR
820 "No LNBH24 found!\n"); 868 "No LNBH24 found!\n");
821 869
@@ -835,8 +883,8 @@ static int dvb_register(struct cx23885_tsport *port)
835 if (!dvb_attach(lnbh24_attach, 883 if (!dvb_attach(lnbh24_attach,
836 fe0->dvb.frontend, 884 fe0->dvb.frontend,
837 &i2c_bus->i2c_adap, 885 &i2c_bus->i2c_adap,
838 LNBH24_PCL, 886 LNBH24_PCL | LNBH24_TTX,
839 LNBH24_TTX, 0x0a)) 887 LNBH24_TEN, 0x0a))
840 printk(KERN_ERR 888 printk(KERN_ERR
841 "No LNBH24 found!\n"); 889 "No LNBH24 found!\n");
842 890
@@ -872,6 +920,7 @@ static int dvb_register(struct cx23885_tsport *port)
872 } 920 }
873 break; 921 break;
874 case CX23885_BOARD_HAUPPAUGE_HVR1850: 922 case CX23885_BOARD_HAUPPAUGE_HVR1850:
923 case CX23885_BOARD_HAUPPAUGE_HVR1290:
875 i2c_bus = &dev->i2c_bus[0]; 924 i2c_bus = &dev->i2c_bus[0];
876 fe0->dvb.frontend = dvb_attach(s5h1411_attach, 925 fe0->dvb.frontend = dvb_attach(s5h1411_attach,
877 &hcw_s5h1411_config, 926 &hcw_s5h1411_config,
@@ -881,6 +930,36 @@ static int dvb_register(struct cx23885_tsport *port)
881 0x60, &dev->i2c_bus[0].i2c_adap, 930 0x60, &dev->i2c_bus[0].i2c_adap,
882 &hauppauge_tda18271_config); 931 &hauppauge_tda18271_config);
883 break; 932 break;
933 case CX23885_BOARD_MYGICA_X8558PRO:
934 switch (port->nr) {
935 /* port B */
936 case 1:
937 i2c_bus = &dev->i2c_bus[0];
938 fe0->dvb.frontend = dvb_attach(atbm8830_attach,
939 &mygica_x8558pro_atbm8830_cfg1,
940 &i2c_bus->i2c_adap);
941 if (fe0->dvb.frontend != NULL) {
942 dvb_attach(max2165_attach,
943 fe0->dvb.frontend,
944 &i2c_bus->i2c_adap,
945 &mygic_x8558pro_max2165_cfg1);
946 }
947 break;
948 /* port C */
949 case 2:
950 i2c_bus = &dev->i2c_bus[1];
951 fe0->dvb.frontend = dvb_attach(atbm8830_attach,
952 &mygica_x8558pro_atbm8830_cfg2,
953 &i2c_bus->i2c_adap);
954 if (fe0->dvb.frontend != NULL) {
955 dvb_attach(max2165_attach,
956 fe0->dvb.frontend,
957 &i2c_bus->i2c_adap,
958 &mygic_x8558pro_max2165_cfg2);
959 }
960 break;
961 }
962 break;
884 963
885 default: 964 default:
886 printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " 965 printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
@@ -897,14 +976,15 @@ static int dvb_register(struct cx23885_tsport *port)
897 fe0->dvb.frontend->callback = cx23885_tuner_callback; 976 fe0->dvb.frontend->callback = cx23885_tuner_callback;
898 977
899 /* Put the analog decoder in standby to keep it quiet */ 978 /* Put the analog decoder in standby to keep it quiet */
900 call_all(dev, tuner, s_standby); 979 call_all(dev, core, s_power, 0);
901 980
902 if (fe0->dvb.frontend->ops.analog_ops.standby) 981 if (fe0->dvb.frontend->ops.analog_ops.standby)
903 fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend); 982 fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend);
904 983
905 /* register everything */ 984 /* register everything */
906 ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, 985 ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
907 &dev->pci->dev, adapter_nr, 0); 986 &dev->pci->dev, adapter_nr, 0,
987 cx23885_dvb_fe_ioctl_override);
908 988
909 /* init CI & MAC */ 989 /* init CI & MAC */
910 switch (dev->board) { 990 switch (dev->board) {
diff --git a/drivers/media/video/cx23885/cx23885-f300.c b/drivers/media/video/cx23885/cx23885-f300.c
new file mode 100644
index 000000000000..93998f220986
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-f300.c
@@ -0,0 +1,177 @@
1/*
2 * Driver for Silicon Labs C8051F300 microcontroller.
3 *
4 * It is used for LNB power control in TeVii S470,
5 * TBS 6920 PCIe DVB-S2 cards.
6 *
7 * Microcontroller connected to cx23885 GPIO pins:
8 * GPIO0 - data - P0.3 F300
9 * GPIO1 - reset - P0.2 F300
10 * GPIO2 - clk - P0.1 F300
11 * GPIO3 - busy - P0.0 F300
12 *
13 * Copyright (C) 2009 Igor M. Liplianin <liplianin@me.by>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 *
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 */
30
31#include "cx23885.h"
32
33#define F300_DATA GPIO_0
34#define F300_RESET GPIO_1
35#define F300_CLK GPIO_2
36#define F300_BUSY GPIO_3
37
38static void f300_set_line(struct cx23885_dev *dev, u32 line, u8 lvl)
39{
40 cx23885_gpio_enable(dev, line, 1);
41 if (lvl == 1)
42 cx23885_gpio_set(dev, line);
43 else
44 cx23885_gpio_clear(dev, line);
45}
46
47static u8 f300_get_line(struct cx23885_dev *dev, u32 line)
48{
49 cx23885_gpio_enable(dev, line, 0);
50
51 return cx23885_gpio_get(dev, line);
52}
53
54static void f300_send_byte(struct cx23885_dev *dev, u8 dta)
55{
56 u8 i;
57
58 for (i = 0; i < 8; i++) {
59 f300_set_line(dev, F300_CLK, 0);
60 udelay(30);
61 f300_set_line(dev, F300_DATA, (dta & 0x80) >> 7);/* msb first */
62 udelay(30);
63 dta <<= 1;
64 f300_set_line(dev, F300_CLK, 1);
65 udelay(30);
66 }
67}
68
69static u8 f300_get_byte(struct cx23885_dev *dev)
70{
71 u8 i, dta = 0;
72
73 for (i = 0; i < 8; i++) {
74 f300_set_line(dev, F300_CLK, 0);
75 udelay(30);
76 dta <<= 1;
77 f300_set_line(dev, F300_CLK, 1);
78 udelay(30);
79 dta |= f300_get_line(dev, F300_DATA);/* msb first */
80
81 }
82
83 return dta;
84}
85
86static u8 f300_xfer(struct dvb_frontend *fe, u8 *buf)
87{
88 struct cx23885_tsport *port = fe->dvb->priv;
89 struct cx23885_dev *dev = port->dev;
90 u8 i, temp, ret = 0;
91
92 temp = buf[0];
93 for (i = 0; i < buf[0]; i++)
94 temp += buf[i + 1];
95 temp = (~temp + 1);/* get check sum */
96 buf[1 + buf[0]] = temp;
97
98 f300_set_line(dev, F300_RESET, 1);
99 f300_set_line(dev, F300_CLK, 1);
100 udelay(30);
101 f300_set_line(dev, F300_DATA, 1);
102 msleep(1);
103
104 /* question: */
105 f300_set_line(dev, F300_RESET, 0);/* begin to send data */
106 msleep(1);
107
108 f300_send_byte(dev, 0xe0);/* the slave address is 0xe0, write */
109 msleep(1);
110
111 temp = buf[0];
112 temp += 2;
113 for (i = 0; i < temp; i++)
114 f300_send_byte(dev, buf[i]);
115
116 f300_set_line(dev, F300_RESET, 1);/* sent data over */
117 f300_set_line(dev, F300_DATA, 1);
118
119 /* answer: */
120 temp = 0;
121 for (i = 0; ((i < 8) & (temp == 0)); i++) {
122 msleep(1);
123 if (f300_get_line(dev, F300_BUSY) == 0)
124 temp = 1;
125 }
126
127 if (i > 7) {
128 printk(KERN_ERR "%s: timeout, the slave no response\n",
129 __func__);
130 ret = 1; /* timeout, the slave no response */
131 } else { /* the slave not busy, prepare for getting data */
132 f300_set_line(dev, F300_RESET, 0);/*ready...*/
133 msleep(1);
134 f300_send_byte(dev, 0xe1);/* 0xe1 is Read */
135 msleep(1);
136 temp = f300_get_byte(dev);/*get the data length */
137 if (temp > 14)
138 temp = 14;
139
140 for (i = 0; i < (temp + 1); i++)
141 f300_get_byte(dev);/* get data to empty buffer */
142
143 f300_set_line(dev, F300_RESET, 1);/* received data over */
144 f300_set_line(dev, F300_DATA, 1);
145 }
146
147 return ret;
148}
149
150int f300_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
151{
152 u8 buf[16];
153
154 buf[0] = 0x05;
155 buf[1] = 0x38;/* write port */
156 buf[2] = 0x01;/* A port, lnb power */
157
158 switch (voltage) {
159 case SEC_VOLTAGE_13:
160 buf[3] = 0x01;/* power on */
161 buf[4] = 0x02;/* B port, H/V */
162 buf[5] = 0x00;/*13V v*/
163 break;
164 case SEC_VOLTAGE_18:
165 buf[3] = 0x01;
166 buf[4] = 0x02;
167 buf[5] = 0x01;/* 18V h*/
168 break;
169 case SEC_VOLTAGE_OFF:
170 buf[3] = 0x00;/* power off */
171 buf[4] = 0x00;
172 buf[5] = 0x00;
173 break;
174 }
175
176 return f300_xfer(fe, buf);
177}
diff --git a/drivers/media/video/cx23885/cx23885-f300.h b/drivers/media/video/cx23885/cx23885-f300.h
new file mode 100644
index 000000000000..e73344c94963
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-f300.h
@@ -0,0 +1,2 @@
1extern int f300_set_voltage(struct dvb_frontend *fe,
2 fe_sec_voltage_t voltage);
diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c
new file mode 100644
index 000000000000..469e083dd5f8
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-input.c
@@ -0,0 +1,427 @@
1/*
2 * Driver for the Conexant CX23885/7/8 PCIe bridge
3 *
4 * Infrared remote control input device
5 *
6 * Most of this file is
7 *
8 * Copyright (C) 2009 Andy Walls <awalls@radix.net>
9 *
10 * However, the cx23885_input_{init,fini} functions contained herein are
11 * derived from Linux kernel files linux/media/video/.../...-input.c marked as:
12 *
13 * Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
14 * Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
15 * Markus Rechberger <mrechberger@gmail.com>
16 * Mauro Carvalho Chehab <mchehab@infradead.org>
17 * Sascha Sommer <saschasommer@freenet.de>
18 * Copyright (C) 2004, 2005 Chris Pascoe
19 * Copyright (C) 2003, 2004 Gerd Knorr
20 * Copyright (C) 2003 Pavel Machek
21 *
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * as published by the Free Software Foundation; either version 2
25 * of the License, or (at your option) any later version.
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
35 * 02110-1301, USA.
36 */
37
38#include <linux/input.h>
39#include <media/ir-common.h>
40#include <media/v4l2-subdev.h>
41
42#include "cx23885.h"
43
44#define RC5_BITS 14
45#define RC5_HALF_BITS (2*RC5_BITS)
46#define RC5_HALF_BITS_MASK ((1 << RC5_HALF_BITS) - 1)
47
48#define RC5_START_BITS_NORMAL 0x3 /* Command range 0 - 63 */
49#define RC5_START_BITS_EXTENDED 0x2 /* Command range 64 - 127 */
50
51#define RC5_EXTENDED_COMMAND_OFFSET 64
52
53static inline unsigned int rc5_command(u32 rc5_baseband)
54{
55 return RC5_INSTR(rc5_baseband) +
56 ((RC5_START(rc5_baseband) == RC5_START_BITS_EXTENDED)
57 ? RC5_EXTENDED_COMMAND_OFFSET : 0);
58}
59
60static void cx23885_input_process_raw_rc5(struct cx23885_dev *dev)
61{
62 struct card_ir *ir_input = dev->ir_input;
63 unsigned int code, command;
64 u32 rc5;
65
66 /* Ignore codes that are too short to be valid RC-5 */
67 if (ir_input->last_bit < (RC5_HALF_BITS - 1))
68 return;
69
70 /* The library has the manchester coding backwards; XOR to adapt. */
71 code = (ir_input->code & RC5_HALF_BITS_MASK) ^ RC5_HALF_BITS_MASK;
72 rc5 = ir_rc5_decode(code);
73
74 switch (RC5_START(rc5)) {
75 case RC5_START_BITS_NORMAL:
76 break;
77 case RC5_START_BITS_EXTENDED:
78 /* Don't allow if the remote only emits standard commands */
79 if (ir_input->start == RC5_START_BITS_NORMAL)
80 return;
81 break;
82 default:
83 return;
84 }
85
86 if (ir_input->addr != RC5_ADDR(rc5))
87 return;
88
89 /* Don't generate a keypress for RC-5 auto-repeated keypresses */
90 command = rc5_command(rc5);
91 if (RC5_TOGGLE(rc5) != RC5_TOGGLE(ir_input->last_rc5) ||
92 command != rc5_command(ir_input->last_rc5) ||
93 /* Catch T == 0, CMD == 0 (e.g. '0') as first keypress after init */
94 RC5_START(ir_input->last_rc5) == 0) {
95 /* This keypress is differnet: not an auto repeat */
96 ir_input_nokey(ir_input->dev, &ir_input->ir);
97 ir_input_keydown(ir_input->dev, &ir_input->ir, command);
98 }
99 ir_input->last_rc5 = rc5;
100
101 /* Schedule when we should do the key up event: ir_input_nokey() */
102 mod_timer(&ir_input->timer_keyup,
103 jiffies + msecs_to_jiffies(ir_input->rc5_key_timeout));
104}
105
106static void cx23885_input_next_pulse_width_rc5(struct cx23885_dev *dev,
107 u32 ns_pulse)
108{
109 const int rc5_quarterbit_ns = 444444; /* 32 cycles/36 kHz/2 = 444 us */
110 struct card_ir *ir_input = dev->ir_input;
111 int i, level, quarterbits, halfbits;
112
113 if (!ir_input->active) {
114 ir_input->active = 1;
115 /* assume an initial space that we may not detect or measure */
116 ir_input->code = 0;
117 ir_input->last_bit = 0;
118 }
119
120 if (ns_pulse == V4L2_SUBDEV_IR_PULSE_RX_SEQ_END) {
121 ir_input->last_bit++; /* Account for the final space */
122 ir_input->active = 0;
123 cx23885_input_process_raw_rc5(dev);
124 return;
125 }
126
127 level = (ns_pulse & V4L2_SUBDEV_IR_PULSE_LEVEL_MASK) ? 1 : 0;
128
129 /* Skip any leading space to sync to the start bit */
130 if (ir_input->last_bit == 0 && level == 0)
131 return;
132
133 /*
134 * With valid RC-5 we can get up to two consecutive half-bits in a
135 * single pulse measurment. Experiments have shown that the duration
136 * of a half-bit can vary. Make sure we always end up with an even
137 * number of quarter bits at the same level (mark or space).
138 */
139 ns_pulse &= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
140 quarterbits = ns_pulse / rc5_quarterbit_ns;
141 if (quarterbits & 1)
142 quarterbits++;
143 halfbits = quarterbits / 2;
144
145 for (i = 0; i < halfbits; i++) {
146 ir_input->last_bit++;
147 ir_input->code |= (level << ir_input->last_bit);
148
149 if (ir_input->last_bit >= RC5_HALF_BITS-1) {
150 ir_input->active = 0;
151 cx23885_input_process_raw_rc5(dev);
152 /*
153 * If level is 1, a leading mark is invalid for RC5.
154 * If level is 0, we scan past extra intial space.
155 * Either way we don't want to reactivate collecting
156 * marks or spaces here with any left over half-bits.
157 */
158 break;
159 }
160 }
161}
162
163static void cx23885_input_process_pulse_widths_rc5(struct cx23885_dev *dev,
164 bool add_eom)
165{
166 struct card_ir *ir_input = dev->ir_input;
167 struct ir_input_state *ir_input_state = &ir_input->ir;
168
169 u32 ns_pulse[RC5_HALF_BITS+1];
170 ssize_t num = 0;
171 int count, i;
172
173 do {
174 v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ns_pulse,
175 sizeof(ns_pulse), &num);
176
177 count = num / sizeof(u32);
178
179 /* Append an end of Rx seq, if the caller requested */
180 if (add_eom && count < ARRAY_SIZE(ns_pulse)) {
181 ns_pulse[count] = V4L2_SUBDEV_IR_PULSE_RX_SEQ_END;
182 count++;
183 }
184
185 /* Just drain the Rx FIFO, if we're called, but not RC-5 */
186 if (ir_input_state->ir_type != IR_TYPE_RC5)
187 continue;
188
189 for (i = 0; i < count; i++)
190 cx23885_input_next_pulse_width_rc5(dev, ns_pulse[i]);
191 } while (num != 0);
192}
193
194void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
195{
196 struct v4l2_subdev_ir_parameters params;
197 int overrun, data_available;
198
199 if (dev->sd_ir == NULL || events == 0)
200 return;
201
202 switch (dev->board) {
203 case CX23885_BOARD_HAUPPAUGE_HVR1850:
204 case CX23885_BOARD_HAUPPAUGE_HVR1290:
205 /*
206 * The only board we handle right now. However other boards
207 * using the CX2388x integrated IR controller should be similar
208 */
209 break;
210 default:
211 return;
212 }
213
214 overrun = events & (V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN |
215 V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN);
216
217 data_available = events & (V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED |
218 V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ);
219
220 if (overrun) {
221 /* If there was a FIFO overrun, stop the device */
222 v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
223 params.enable = false;
224 /* Mitigate race with cx23885_input_ir_stop() */
225 params.shutdown = atomic_read(&dev->ir_input_stopping);
226 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
227 }
228
229 if (data_available)
230 cx23885_input_process_pulse_widths_rc5(dev, overrun);
231
232 if (overrun) {
233 /* If there was a FIFO overrun, clear & restart the device */
234 params.enable = true;
235 /* Mitigate race with cx23885_input_ir_stop() */
236 params.shutdown = atomic_read(&dev->ir_input_stopping);
237 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
238 }
239}
240
241static void cx23885_input_ir_start(struct cx23885_dev *dev)
242{
243 struct card_ir *ir_input = dev->ir_input;
244 struct ir_input_state *ir_input_state = &ir_input->ir;
245 struct v4l2_subdev_ir_parameters params;
246
247 if (dev->sd_ir == NULL)
248 return;
249
250 atomic_set(&dev->ir_input_stopping, 0);
251
252 /* keyup timer set up, if needed */
253 switch (dev->board) {
254 case CX23885_BOARD_HAUPPAUGE_HVR1850:
255 case CX23885_BOARD_HAUPPAUGE_HVR1290:
256 setup_timer(&ir_input->timer_keyup,
257 ir_rc5_timer_keyup, /* Not actually RC-5 specific */
258 (unsigned long) ir_input);
259 if (ir_input_state->ir_type == IR_TYPE_RC5) {
260 /*
261 * RC-5 repeats a held key every
262 * 64 bits * (2 * 32/36000) sec/bit = 113.778 ms
263 */
264 ir_input->rc5_key_timeout = 115;
265 }
266 break;
267 }
268
269 v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
270 switch (dev->board) {
271 case CX23885_BOARD_HAUPPAUGE_HVR1850:
272 case CX23885_BOARD_HAUPPAUGE_HVR1290:
273 /*
274 * The IR controller on this board only returns pulse widths.
275 * Any other mode setting will fail to set up the device.
276 */
277 params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
278 params.enable = true;
279 params.interrupt_enable = true;
280 params.shutdown = false;
281
282 /* Setup for baseband compatible with both RC-5 and RC-6A */
283 params.modulation = false;
284 /* RC-5: 2,222,222 ns = 1/36 kHz * 32 cycles * 2 marks * 1.25*/
285 /* RC-6A: 3,333,333 ns = 1/36 kHz * 16 cycles * 6 marks * 1.25*/
286 params.max_pulse_width = 3333333; /* ns */
287 /* RC-5: 666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */
288 /* RC-6A: 333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */
289 params.noise_filter_min_width = 333333; /* ns */
290 /*
291 * This board has inverted receive sense:
292 * mark is received as low logic level;
293 * falling edges are detected as rising edges; etc.
294 */
295 params.invert = true;
296 break;
297 }
298 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
299}
300
301static void cx23885_input_ir_stop(struct cx23885_dev *dev)
302{
303 struct card_ir *ir_input = dev->ir_input;
304 struct v4l2_subdev_ir_parameters params;
305
306 if (dev->sd_ir == NULL)
307 return;
308
309 /*
310 * Stop the sd_ir subdevice from generating notifications and
311 * scheduling work.
312 * It is shutdown this way in order to mitigate a race with
313 * cx23885_input_rx_work_handler() in the overrun case, which could
314 * re-enable the subdevice.
315 */
316 atomic_set(&dev->ir_input_stopping, 1);
317 v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
318 while (params.shutdown == false) {
319 params.enable = false;
320 params.interrupt_enable = false;
321 params.shutdown = true;
322 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
323 v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
324 }
325
326 flush_scheduled_work();
327
328 switch (dev->board) {
329 case CX23885_BOARD_HAUPPAUGE_HVR1850:
330 case CX23885_BOARD_HAUPPAUGE_HVR1290:
331 del_timer_sync(&ir_input->timer_keyup);
332 break;
333 }
334}
335
336int cx23885_input_init(struct cx23885_dev *dev)
337{
338 struct card_ir *ir;
339 struct input_dev *input_dev;
340 struct ir_scancode_table *ir_codes = NULL;
341 int ir_type, ir_addr, ir_start;
342 int ret;
343
344 /*
345 * If the IR device (hardware registers, chip, GPIO lines, etc.) isn't
346 * encapsulated in a v4l2_subdev, then I'm not going to deal with it.
347 */
348 if (dev->sd_ir == NULL)
349 return -ENODEV;
350
351 switch (dev->board) {
352 case CX23885_BOARD_HAUPPAUGE_HVR1850:
353 case CX23885_BOARD_HAUPPAUGE_HVR1290:
354 /* Parameters for the grey Hauppauge remote for the HVR-1850 */
355 ir_codes = &ir_codes_hauppauge_new_table;
356 ir_type = IR_TYPE_RC5;
357 ir_addr = 0x1e; /* RC-5 system bits emitted by the remote */
358 ir_start = RC5_START_BITS_NORMAL; /* A basic RC-5 remote */
359 break;
360 }
361 if (ir_codes == NULL)
362 return -ENODEV;
363
364 ir = kzalloc(sizeof(*ir), GFP_KERNEL);
365 input_dev = input_allocate_device();
366 if (!ir || !input_dev) {
367 ret = -ENOMEM;
368 goto err_out_free;
369 }
370
371 ir->dev = input_dev;
372 ir->addr = ir_addr;
373 ir->start = ir_start;
374
375 /* init input device */
376 snprintf(ir->name, sizeof(ir->name), "cx23885 IR (%s)",
377 cx23885_boards[dev->board].name);
378 snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci));
379
380 ret = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
381 if (ret < 0)
382 goto err_out_free;
383
384 input_dev->name = ir->name;
385 input_dev->phys = ir->phys;
386 input_dev->id.bustype = BUS_PCI;
387 input_dev->id.version = 1;
388 if (dev->pci->subsystem_vendor) {
389 input_dev->id.vendor = dev->pci->subsystem_vendor;
390 input_dev->id.product = dev->pci->subsystem_device;
391 } else {
392 input_dev->id.vendor = dev->pci->vendor;
393 input_dev->id.product = dev->pci->device;
394 }
395 input_dev->dev.parent = &dev->pci->dev;
396
397 dev->ir_input = ir;
398 cx23885_input_ir_start(dev);
399
400 ret = input_register_device(ir->dev);
401 if (ret)
402 goto err_out_stop;
403
404 return 0;
405
406err_out_stop:
407 cx23885_input_ir_stop(dev);
408 dev->ir_input = NULL;
409err_out_free:
410 ir_input_free(input_dev);
411 input_free_device(input_dev);
412 kfree(ir);
413 return ret;
414}
415
416void cx23885_input_fini(struct cx23885_dev *dev)
417{
418 /* Always stop the IR hardware from generating interrupts */
419 cx23885_input_ir_stop(dev);
420
421 if (dev->ir_input == NULL)
422 return;
423 ir_input_free(dev->ir_input->dev);
424 input_unregister_device(dev->ir_input->dev);
425 kfree(dev->ir_input);
426 dev->ir_input = NULL;
427}
diff --git a/drivers/media/video/cx23885/cx23885-input.h b/drivers/media/video/cx23885/cx23885-input.h
new file mode 100644
index 000000000000..3572cb1ecfc2
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-input.h
@@ -0,0 +1,30 @@
1/*
2 * Driver for the Conexant CX23885/7/8 PCIe bridge
3 *
4 * Infrared remote control input device
5 *
6 * Copyright (C) 2009 Andy Walls <awalls@radix.net>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 * 02110-1301, USA.
22 */
23
24#ifndef _CX23885_INPUT_H_
25#define _CX23885_INPUT_H_
26int cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events);
27
28int cx23885_input_init(struct cx23885_dev *dev);
29void cx23885_input_fini(struct cx23885_dev *dev);
30#endif
diff --git a/drivers/media/video/cx23885/cx23885-ioctl.c b/drivers/media/video/cx23885/cx23885-ioctl.c
new file mode 100644
index 000000000000..dfb4627fb340
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-ioctl.c
@@ -0,0 +1,208 @@
1/*
2 * Driver for the Conexant CX23885/7/8 PCIe bridge
3 *
4 * Various common ioctl() support functions
5 *
6 * Copyright (c) 2009 Andy Walls <awalls@radix.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 *
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include "cx23885.h"
25#include <media/v4l2-chip-ident.h>
26
27int cx23885_g_chip_ident(struct file *file, void *fh,
28 struct v4l2_dbg_chip_ident *chip)
29{
30 struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
31 int err = 0;
32 u8 rev;
33
34 chip->ident = V4L2_IDENT_NONE;
35 chip->revision = 0;
36 switch (chip->match.type) {
37 case V4L2_CHIP_MATCH_HOST:
38 switch (chip->match.addr) {
39 case 0:
40 rev = cx_read(RDR_CFG2) & 0xff;
41 switch (dev->pci->device) {
42 case 0x8852:
43 /* rev 0x04 could be '885 or '888. Pick '888. */
44 if (rev == 0x04)
45 chip->ident = V4L2_IDENT_CX23888;
46 else
47 chip->ident = V4L2_IDENT_CX23885;
48 break;
49 case 0x8880:
50 if (rev == 0x0e || rev == 0x0f)
51 chip->ident = V4L2_IDENT_CX23887;
52 else
53 chip->ident = V4L2_IDENT_CX23888;
54 break;
55 default:
56 chip->ident = V4L2_IDENT_UNKNOWN;
57 break;
58 }
59 chip->revision = (dev->pci->device << 16) | (rev << 8) |
60 (dev->hwrevision & 0xff);
61 break;
62 case 1:
63 if (dev->v4l_device != NULL) {
64 chip->ident = V4L2_IDENT_CX23417;
65 chip->revision = 0;
66 }
67 break;
68 case 2:
69 /*
70 * The integrated IR controller on the CX23888 is
71 * host chip 2. It may not be used/initialized or sd_ir
72 * may be pointing at the cx25840 subdevice for the
73 * IR controller on the CX23885. Thus we find it
74 * without using the dev->sd_ir pointer.
75 */
76 call_hw(dev, CX23885_HW_888_IR, core, g_chip_ident,
77 chip);
78 break;
79 default:
80 err = -EINVAL; /* per V4L2 spec */
81 break;
82 }
83 break;
84 case V4L2_CHIP_MATCH_I2C_DRIVER:
85 /* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */
86 call_all(dev, core, g_chip_ident, chip);
87 break;
88 case V4L2_CHIP_MATCH_I2C_ADDR:
89 /*
90 * We could return V4L2_IDENT_UNKNOWN, but we don't do the work
91 * to look if a chip is at the address with no driver. That's a
92 * dangerous thing to do with EEPROMs anyway.
93 */
94 call_all(dev, core, g_chip_ident, chip);
95 break;
96 default:
97 err = -EINVAL;
98 break;
99 }
100 return err;
101}
102
103#ifdef CONFIG_VIDEO_ADV_DEBUG
104static int cx23885_g_host_register(struct cx23885_dev *dev,
105 struct v4l2_dbg_register *reg)
106{
107 if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0))
108 return -EINVAL;
109
110 reg->size = 4;
111 reg->val = cx_read(reg->reg);
112 return 0;
113}
114
115static int cx23417_g_register(struct cx23885_dev *dev,
116 struct v4l2_dbg_register *reg)
117{
118 u32 value;
119
120 if (dev->v4l_device == NULL)
121 return -EINVAL;
122
123 if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000)
124 return -EINVAL;
125
126 if (mc417_register_read(dev, (u16) reg->reg, &value))
127 return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */
128
129 reg->size = 4;
130 reg->val = value;
131 return 0;
132}
133
134int cx23885_g_register(struct file *file, void *fh,
135 struct v4l2_dbg_register *reg)
136{
137 struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
138
139 if (!capable(CAP_SYS_ADMIN))
140 return -EPERM;
141
142 if (reg->match.type == V4L2_CHIP_MATCH_HOST) {
143 switch (reg->match.addr) {
144 case 0:
145 return cx23885_g_host_register(dev, reg);
146 case 1:
147 return cx23417_g_register(dev, reg);
148 default:
149 break;
150 }
151 }
152
153 /* FIXME - any error returns should not be ignored */
154 call_all(dev, core, g_register, reg);
155 return 0;
156}
157
158static int cx23885_s_host_register(struct cx23885_dev *dev,
159 struct v4l2_dbg_register *reg)
160{
161 if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0))
162 return -EINVAL;
163
164 reg->size = 4;
165 cx_write(reg->reg, reg->val);
166 return 0;
167}
168
169static int cx23417_s_register(struct cx23885_dev *dev,
170 struct v4l2_dbg_register *reg)
171{
172 if (dev->v4l_device == NULL)
173 return -EINVAL;
174
175 if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000)
176 return -EINVAL;
177
178 if (mc417_register_write(dev, (u16) reg->reg, (u32) reg->val))
179 return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */
180
181 reg->size = 4;
182 return 0;
183}
184
185int cx23885_s_register(struct file *file, void *fh,
186 struct v4l2_dbg_register *reg)
187{
188 struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
189
190 if (!capable(CAP_SYS_ADMIN))
191 return -EPERM;
192
193 if (reg->match.type == V4L2_CHIP_MATCH_HOST) {
194 switch (reg->match.addr) {
195 case 0:
196 return cx23885_s_host_register(dev, reg);
197 case 1:
198 return cx23417_s_register(dev, reg);
199 default:
200 break;
201 }
202 }
203
204 /* FIXME - any error returns should not be ignored */
205 call_all(dev, core, s_register, reg);
206 return 0;
207}
208#endif
diff --git a/drivers/media/video/cx23885/cx23885-ioctl.h b/drivers/media/video/cx23885/cx23885-ioctl.h
new file mode 100644
index 000000000000..80b0f4923c6a
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-ioctl.h
@@ -0,0 +1,39 @@
1/*
2 * Driver for the Conexant CX23885/7/8 PCIe bridge
3 *
4 * Various common ioctl() support functions
5 *
6 * Copyright (c) 2009 Andy Walls <awalls@radix.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 *
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#ifndef _CX23885_IOCTL_H_
25#define _CX23885_IOCTL_H_
26
27int cx23885_g_chip_ident(struct file *file, void *fh,
28 struct v4l2_dbg_chip_ident *chip);
29
30#ifdef CONFIG_VIDEO_ADV_DEBUG
31int cx23885_g_register(struct file *file, void *fh,
32 struct v4l2_dbg_register *reg);
33
34
35int cx23885_s_register(struct file *file, void *fh,
36 struct v4l2_dbg_register *reg);
37
38#endif
39#endif
diff --git a/drivers/media/video/cx23885/cx23885-ir.c b/drivers/media/video/cx23885/cx23885-ir.c
new file mode 100644
index 000000000000..6ae982cc9856
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-ir.c
@@ -0,0 +1,101 @@
1/*
2 * Driver for the Conexant CX23885/7/8 PCIe bridge
3 *
4 * Infrared device support routines - non-input, non-vl42_subdev routines
5 *
6 * Copyright (C) 2009 Andy Walls <awalls@radix.net>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 * 02110-1301, USA.
22 */
23
24#include <media/v4l2-device.h>
25
26#include "cx23885.h"
27#include "cx23885-input.h"
28
29#define CX23885_IR_RX_FIFO_SERVICE_REQ 0
30#define CX23885_IR_RX_END_OF_RX_DETECTED 1
31#define CX23885_IR_RX_HW_FIFO_OVERRUN 2
32#define CX23885_IR_RX_SW_FIFO_OVERRUN 3
33
34#define CX23885_IR_TX_FIFO_SERVICE_REQ 0
35
36
37void cx23885_ir_rx_work_handler(struct work_struct *work)
38{
39 struct cx23885_dev *dev =
40 container_of(work, struct cx23885_dev, ir_rx_work);
41 u32 events = 0;
42 unsigned long *notifications = &dev->ir_rx_notifications;
43
44 if (test_and_clear_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications))
45 events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN;
46 if (test_and_clear_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications))
47 events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN;
48 if (test_and_clear_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications))
49 events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED;
50 if (test_and_clear_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications))
51 events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
52
53 if (events == 0)
54 return;
55
56 if (dev->ir_input)
57 cx23885_input_rx_work_handler(dev, events);
58}
59
60void cx23885_ir_tx_work_handler(struct work_struct *work)
61{
62 struct cx23885_dev *dev =
63 container_of(work, struct cx23885_dev, ir_tx_work);
64 u32 events = 0;
65 unsigned long *notifications = &dev->ir_tx_notifications;
66
67 if (test_and_clear_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications))
68 events |= V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ;
69
70 if (events == 0)
71 return;
72
73}
74
75/* Called in an IRQ context */
76void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
77{
78 struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev);
79 unsigned long *notifications = &dev->ir_rx_notifications;
80
81 if (events & V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ)
82 set_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications);
83 if (events & V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED)
84 set_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications);
85 if (events & V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN)
86 set_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications);
87 if (events & V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN)
88 set_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications);
89 schedule_work(&dev->ir_rx_work);
90}
91
92/* Called in an IRQ context */
93void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
94{
95 struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev);
96 unsigned long *notifications = &dev->ir_tx_notifications;
97
98 if (events & V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ)
99 set_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications);
100 schedule_work(&dev->ir_tx_work);
101}
diff --git a/drivers/media/video/cx23885/cx23885-ir.h b/drivers/media/video/cx23885/cx23885-ir.h
new file mode 100644
index 000000000000..9b8a6d5d1ef6
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-ir.h
@@ -0,0 +1,31 @@
1/*
2 * Driver for the Conexant CX23885/7/8 PCIe bridge
3 *
4 * Infrared device support routines - non-input, non-vl42_subdev routines
5 *
6 * Copyright (C) 2009 Andy Walls <awalls@radix.net>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 * 02110-1301, USA.
22 */
23
24#ifndef _CX23885_IR_H_
25#define _CX23885_IR_H_
26void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events);
27void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events);
28
29void cx23885_ir_rx_work_handler(struct work_struct *work);
30void cx23885_ir_tx_work_handler(struct work_struct *work);
31#endif
diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h
index eafbe5226bae..c0bc9a068954 100644
--- a/drivers/media/video/cx23885/cx23885-reg.h
+++ b/drivers/media/video/cx23885/cx23885-reg.h
@@ -212,8 +212,9 @@ Channel manager Data Structure entry = 20 DWORD
212 212
213#define DEV_CNTRL2 0x00040000 213#define DEV_CNTRL2 0x00040000
214 214
215#define PCI_MSK_GPIO1 (1 << 24) 215#define PCI_MSK_IR (1 << 28)
216#define PCI_MSK_GPIO0 (1 << 23) 216#define PCI_MSK_GPIO1 (1 << 24)
217#define PCI_MSK_GPIO0 (1 << 23)
217#define PCI_MSK_APB_DMA (1 << 12) 218#define PCI_MSK_APB_DMA (1 << 12)
218#define PCI_MSK_AL_WR (1 << 11) 219#define PCI_MSK_AL_WR (1 << 11)
219#define PCI_MSK_AL_RD (1 << 10) 220#define PCI_MSK_AL_RD (1 << 10)
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index 654cc253cd50..8b372b4f0de2 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -35,6 +35,7 @@
35#include "cx23885.h" 35#include "cx23885.h"
36#include <media/v4l2-common.h> 36#include <media/v4l2-common.h>
37#include <media/v4l2-ioctl.h> 37#include <media/v4l2-ioctl.h>
38#include "cx23885-ioctl.h"
38 39
39MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards"); 40MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards");
40MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); 41MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
@@ -401,6 +402,13 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
401 INPUT(input)->gpio2, INPUT(input)->gpio3); 402 INPUT(input)->gpio2, INPUT(input)->gpio3);
402 dev->input = input; 403 dev->input = input;
403 404
405 if (dev->board == CX23885_BOARD_MYGICA_X8506 ||
406 dev->board == CX23885_BOARD_MAGICPRO_PROHDTVE2) {
407 /* Select Analog TV */
408 if (INPUT(input)->type == CX23885_VMUX_TELEVISION)
409 cx23885_gpio_clear(dev, GPIO_0);
410 }
411
404 /* Tell the internal A/V decoder */ 412 /* Tell the internal A/V decoder */
405 v4l2_subdev_call(dev->sd_cx25840, video, s_routing, 413 v4l2_subdev_call(dev->sd_cx25840, video, s_routing,
406 INPUT(input)->vmux, 0, 0); 414 INPUT(input)->vmux, 0, 0);
@@ -1144,6 +1152,7 @@ static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
1144 [CX23885_VMUX_COMPOSITE3] = "Composite3", 1152 [CX23885_VMUX_COMPOSITE3] = "Composite3",
1145 [CX23885_VMUX_COMPOSITE4] = "Composite4", 1153 [CX23885_VMUX_COMPOSITE4] = "Composite4",
1146 [CX23885_VMUX_SVIDEO] = "S-Video", 1154 [CX23885_VMUX_SVIDEO] = "S-Video",
1155 [CX23885_VMUX_COMPONENT] = "Component",
1147 [CX23885_VMUX_TELEVISION] = "Television", 1156 [CX23885_VMUX_TELEVISION] = "Television",
1148 [CX23885_VMUX_CABLE] = "Cable TV", 1157 [CX23885_VMUX_CABLE] = "Cable TV",
1149 [CX23885_VMUX_DVB] = "DVB", 1158 [CX23885_VMUX_DVB] = "DVB",
@@ -1312,34 +1321,6 @@ static int vidioc_s_frequency(struct file *file, void *priv,
1312 cx23885_set_freq(dev, f); 1321 cx23885_set_freq(dev, f);
1313} 1322}
1314 1323
1315#ifdef CONFIG_VIDEO_ADV_DEBUG
1316static int vidioc_g_register(struct file *file, void *fh,
1317 struct v4l2_dbg_register *reg)
1318{
1319 struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
1320
1321 if (!v4l2_chip_match_host(&reg->match))
1322 return -EINVAL;
1323
1324 call_all(dev, core, g_register, reg);
1325
1326 return 0;
1327}
1328
1329static int vidioc_s_register(struct file *file, void *fh,
1330 struct v4l2_dbg_register *reg)
1331{
1332 struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
1333
1334 if (!v4l2_chip_match_host(&reg->match))
1335 return -EINVAL;
1336
1337 call_all(dev, core, s_register, reg);
1338
1339 return 0;
1340}
1341#endif
1342
1343/* ----------------------------------------------------------- */ 1324/* ----------------------------------------------------------- */
1344 1325
1345static void cx23885_vid_timeout(unsigned long data) 1326static void cx23885_vid_timeout(unsigned long data)
@@ -1449,9 +1430,10 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
1449 .vidioc_s_tuner = vidioc_s_tuner, 1430 .vidioc_s_tuner = vidioc_s_tuner,
1450 .vidioc_g_frequency = vidioc_g_frequency, 1431 .vidioc_g_frequency = vidioc_g_frequency,
1451 .vidioc_s_frequency = vidioc_s_frequency, 1432 .vidioc_s_frequency = vidioc_s_frequency,
1433 .vidioc_g_chip_ident = cx23885_g_chip_ident,
1452#ifdef CONFIG_VIDEO_ADV_DEBUG 1434#ifdef CONFIG_VIDEO_ADV_DEBUG
1453 .vidioc_g_register = vidioc_g_register, 1435 .vidioc_g_register = cx23885_g_register,
1454 .vidioc_s_register = vidioc_s_register, 1436 .vidioc_s_register = cx23885_s_register,
1455#endif 1437#endif
1456}; 1438};
1457 1439
@@ -1529,9 +1511,11 @@ int cx23885_video_register(struct cx23885_dev *dev)
1529 if (sd) { 1511 if (sd) {
1530 struct tuner_setup tun_setup; 1512 struct tuner_setup tun_setup;
1531 1513
1514 memset(&tun_setup, 0, sizeof(tun_setup));
1532 tun_setup.mode_mask = T_ANALOG_TV; 1515 tun_setup.mode_mask = T_ANALOG_TV;
1533 tun_setup.type = dev->tuner_type; 1516 tun_setup.type = dev->tuner_type;
1534 tun_setup.addr = v4l2_i2c_subdev_addr(sd); 1517 tun_setup.addr = v4l2_i2c_subdev_addr(sd);
1518 tun_setup.tuner_callback = cx23885_tuner_callback;
1535 1519
1536 v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup); 1520 v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup);
1537 } 1521 }
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
index cc7a165561ff..fa744764dc8b 100644
--- a/drivers/media/video/cx23885/cx23885.h
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -79,6 +79,8 @@
79#define CX23885_BOARD_MAGICPRO_PROHDTVE2 23 79#define CX23885_BOARD_MAGICPRO_PROHDTVE2 23
80#define CX23885_BOARD_HAUPPAUGE_HVR1850 24 80#define CX23885_BOARD_HAUPPAUGE_HVR1850 24
81#define CX23885_BOARD_COMPRO_VIDEOMATE_E800 25 81#define CX23885_BOARD_COMPRO_VIDEOMATE_E800 25
82#define CX23885_BOARD_HAUPPAUGE_HVR1290 26
83#define CX23885_BOARD_MYGICA_X8558PRO 27
82 84
83#define GPIO_0 0x00000001 85#define GPIO_0 0x00000001
84#define GPIO_1 0x00000002 86#define GPIO_1 0x00000002
@@ -157,6 +159,7 @@ enum cx23885_itype {
157 CX23885_VMUX_COMPOSITE3, 159 CX23885_VMUX_COMPOSITE3,
158 CX23885_VMUX_COMPOSITE4, 160 CX23885_VMUX_COMPOSITE4,
159 CX23885_VMUX_SVIDEO, 161 CX23885_VMUX_SVIDEO,
162 CX23885_VMUX_COMPONENT,
160 CX23885_VMUX_TELEVISION, 163 CX23885_VMUX_TELEVISION,
161 CX23885_VMUX_CABLE, 164 CX23885_VMUX_CABLE,
162 CX23885_VMUX_DVB, 165 CX23885_VMUX_DVB,
@@ -297,10 +300,6 @@ struct cx23885_tsport {
297 /* Allow a single tsport to have multiple frontends */ 300 /* Allow a single tsport to have multiple frontends */
298 u32 num_frontends; 301 u32 num_frontends;
299 void *port_priv; 302 void *port_priv;
300
301 /* FIXME: temporary hack */
302 int (*set_frontend_save) (struct dvb_frontend *,
303 struct dvb_frontend_parameters *);
304}; 303};
305 304
306struct cx23885_dev { 305struct cx23885_dev {
@@ -356,6 +355,16 @@ struct cx23885_dev {
356 unsigned int has_radio; 355 unsigned int has_radio;
357 struct v4l2_subdev *sd_cx25840; 356 struct v4l2_subdev *sd_cx25840;
358 357
358 /* Infrared */
359 struct v4l2_subdev *sd_ir;
360 struct work_struct ir_rx_work;
361 unsigned long ir_rx_notifications;
362 struct work_struct ir_tx_work;
363 unsigned long ir_tx_notifications;
364
365 struct card_ir *ir_input;
366 atomic_t ir_input_stopping;
367
359 /* V4l */ 368 /* V4l */
360 u32 freq; 369 u32 freq;
361 struct video_device *video_dev; 370 struct video_device *video_dev;
@@ -383,6 +392,13 @@ static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev)
383#define call_all(dev, o, f, args...) \ 392#define call_all(dev, o, f, args...) \
384 v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) 393 v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args)
385 394
395#define CX23885_HW_888_IR (1 << 0)
396
397#define call_hw(dev, grpid, o, f, args...) \
398 v4l2_device_call_all(&dev->v4l2_dev, grpid, o, f, ##args)
399
400extern struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw);
401
386extern struct list_head cx23885_devlist; 402extern struct list_head cx23885_devlist;
387 403
388#define SRAM_CH01 0 /* Video A */ 404#define SRAM_CH01 0 /* Video A */
@@ -455,6 +471,7 @@ extern void cx23885_wakeup(struct cx23885_tsport *port,
455 471
456extern void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask); 472extern void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask);
457extern void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask); 473extern void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask);
474extern u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask);
458extern void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, 475extern void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask,
459 int asoutput); 476 int asoutput);
460 477
@@ -471,6 +488,8 @@ extern int cx23885_tuner_callback(void *priv, int component,
471 int command, int arg); 488 int command, int arg);
472extern void cx23885_card_list(struct cx23885_dev *dev); 489extern void cx23885_card_list(struct cx23885_dev *dev);
473extern int cx23885_ir_init(struct cx23885_dev *dev); 490extern int cx23885_ir_init(struct cx23885_dev *dev);
491extern void cx23885_ir_pci_int_enable(struct cx23885_dev *dev);
492extern void cx23885_ir_fini(struct cx23885_dev *dev);
474extern void cx23885_gpio_setup(struct cx23885_dev *dev); 493extern void cx23885_gpio_setup(struct cx23885_dev *dev);
475extern void cx23885_card_setup(struct cx23885_dev *dev); 494extern void cx23885_card_setup(struct cx23885_dev *dev);
476extern void cx23885_card_setup_pre_i2c(struct cx23885_dev *dev); 495extern void cx23885_card_setup_pre_i2c(struct cx23885_dev *dev);
@@ -515,6 +534,10 @@ extern void cx23885_417_check_encoder(struct cx23885_dev *dev);
515extern void cx23885_mc417_init(struct cx23885_dev *dev); 534extern void cx23885_mc417_init(struct cx23885_dev *dev);
516extern int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value); 535extern int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value);
517extern int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value); 536extern int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value);
537extern int mc417_register_read(struct cx23885_dev *dev,
538 u16 address, u32 *value);
539extern int mc417_register_write(struct cx23885_dev *dev,
540 u16 address, u32 value);
518extern void mc417_gpio_set(struct cx23885_dev *dev, u32 mask); 541extern void mc417_gpio_set(struct cx23885_dev *dev, u32 mask);
519extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask); 542extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask);
520extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput); 543extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput);
diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c
new file mode 100644
index 000000000000..3ccc8afeccf3
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23888-ir.c
@@ -0,0 +1,1239 @@
1/*
2 * Driver for the Conexant CX23885/7/8 PCIe bridge
3 *
4 * CX23888 Integrated Consumer Infrared Controller
5 *
6 * Copyright (C) 2009 Andy Walls <awalls@radix.net>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 * 02110-1301, USA.
22 */
23
24#include <linux/kfifo.h>
25
26#include <media/v4l2-device.h>
27#include <media/v4l2-chip-ident.h>
28
29#include "cx23885.h"
30
31static unsigned int ir_888_debug;
32module_param(ir_888_debug, int, 0644);
33MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]");
34
35#define CX23888_IR_REG_BASE 0x170000
36/*
37 * These CX23888 register offsets have a straightforward one to one mapping
38 * to the CX23885 register offsets of 0x200 through 0x218
39 */
40#define CX23888_IR_CNTRL_REG 0x170000
41#define CNTRL_WIN_3_3 0x00000000
42#define CNTRL_WIN_4_3 0x00000001
43#define CNTRL_WIN_3_4 0x00000002
44#define CNTRL_WIN_4_4 0x00000003
45#define CNTRL_WIN 0x00000003
46#define CNTRL_EDG_NONE 0x00000000
47#define CNTRL_EDG_FALL 0x00000004
48#define CNTRL_EDG_RISE 0x00000008
49#define CNTRL_EDG_BOTH 0x0000000C
50#define CNTRL_EDG 0x0000000C
51#define CNTRL_DMD 0x00000010
52#define CNTRL_MOD 0x00000020
53#define CNTRL_RFE 0x00000040
54#define CNTRL_TFE 0x00000080
55#define CNTRL_RXE 0x00000100
56#define CNTRL_TXE 0x00000200
57#define CNTRL_RIC 0x00000400
58#define CNTRL_TIC 0x00000800
59#define CNTRL_CPL 0x00001000
60#define CNTRL_LBM 0x00002000
61#define CNTRL_R 0x00004000
62
63#define CX23888_IR_TXCLK_REG 0x170004
64#define TXCLK_TCD 0x0000FFFF
65
66#define CX23888_IR_RXCLK_REG 0x170008
67#define RXCLK_RCD 0x0000FFFF
68
69#define CX23888_IR_CDUTY_REG 0x17000C
70#define CDUTY_CDC 0x0000000F
71
72#define CX23888_IR_STATS_REG 0x170010
73#define STATS_RTO 0x00000001
74#define STATS_ROR 0x00000002
75#define STATS_RBY 0x00000004
76#define STATS_TBY 0x00000008
77#define STATS_RSR 0x00000010
78#define STATS_TSR 0x00000020
79
80#define CX23888_IR_IRQEN_REG 0x170014
81#define IRQEN_RTE 0x00000001
82#define IRQEN_ROE 0x00000002
83#define IRQEN_RSE 0x00000010
84#define IRQEN_TSE 0x00000020
85
86#define CX23888_IR_FILTR_REG 0x170018
87#define FILTR_LPF 0x0000FFFF
88
89/* This register doesn't follow the pattern; it's 0x23C on a CX23885 */
90#define CX23888_IR_FIFO_REG 0x170040
91#define FIFO_RXTX 0x0000FFFF
92#define FIFO_RXTX_LVL 0x00010000
93#define FIFO_RXTX_RTO 0x0001FFFF
94#define FIFO_RX_NDV 0x00020000
95#define FIFO_RX_DEPTH 8
96#define FIFO_TX_DEPTH 8
97
98/* CX23888 unique registers */
99#define CX23888_IR_SEEDP_REG 0x17001C
100#define CX23888_IR_TIMOL_REG 0x170020
101#define CX23888_IR_WAKE0_REG 0x170024
102#define CX23888_IR_WAKE1_REG 0x170028
103#define CX23888_IR_WAKE2_REG 0x17002C
104#define CX23888_IR_MASK0_REG 0x170030
105#define CX23888_IR_MASK1_REG 0x170034
106#define CX23888_IR_MAKS2_REG 0x170038
107#define CX23888_IR_DPIPG_REG 0x17003C
108#define CX23888_IR_LEARN_REG 0x170044
109
110#define CX23888_VIDCLK_FREQ 108000000 /* 108 MHz, BT.656 */
111#define CX23888_IR_REFCLK_FREQ (CX23888_VIDCLK_FREQ / 2)
112
113#define CX23888_IR_RX_KFIFO_SIZE (512 * sizeof(u32))
114#define CX23888_IR_TX_KFIFO_SIZE (512 * sizeof(u32))
115
116struct cx23888_ir_state {
117 struct v4l2_subdev sd;
118 struct cx23885_dev *dev;
119 u32 id;
120 u32 rev;
121
122 struct v4l2_subdev_ir_parameters rx_params;
123 struct mutex rx_params_lock;
124 atomic_t rxclk_divider;
125 atomic_t rx_invert;
126
127 struct kfifo *rx_kfifo;
128 spinlock_t rx_kfifo_lock;
129
130 struct v4l2_subdev_ir_parameters tx_params;
131 struct mutex tx_params_lock;
132 atomic_t txclk_divider;
133
134 struct kfifo *tx_kfifo;
135 spinlock_t tx_kfifo_lock;
136};
137
138static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd)
139{
140 return v4l2_get_subdevdata(sd);
141}
142
143/*
144 * IR register block read and write functions
145 */
146static
147inline int cx23888_ir_write4(struct cx23885_dev *dev, u32 addr, u32 value)
148{
149 cx_write(addr, value);
150 return 0;
151}
152
153static inline u32 cx23888_ir_read4(struct cx23885_dev *dev, u32 addr)
154{
155 return cx_read(addr);
156}
157
158static inline int cx23888_ir_and_or4(struct cx23885_dev *dev, u32 addr,
159 u32 and_mask, u32 or_value)
160{
161 cx_andor(addr, ~and_mask, or_value);
162 return 0;
163}
164
165/*
166 * Rx and Tx Clock Divider register computations
167 *
168 * Note the largest clock divider value of 0xffff corresponds to:
169 * (0xffff + 1) * 1000 / 108/2 MHz = 1,213,629.629... ns
170 * which fits in 21 bits, so we'll use unsigned int for time arguments.
171 */
172static inline u16 count_to_clock_divider(unsigned int d)
173{
174 if (d > RXCLK_RCD + 1)
175 d = RXCLK_RCD;
176 else if (d < 2)
177 d = 1;
178 else
179 d--;
180 return (u16) d;
181}
182
183static inline u16 ns_to_clock_divider(unsigned int ns)
184{
185 return count_to_clock_divider(
186 DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ / 1000000 * ns, 1000));
187}
188
189static inline unsigned int clock_divider_to_ns(unsigned int divider)
190{
191 /* Period of the Rx or Tx clock in ns */
192 return DIV_ROUND_CLOSEST((divider + 1) * 1000,
193 CX23888_IR_REFCLK_FREQ / 1000000);
194}
195
196static inline u16 carrier_freq_to_clock_divider(unsigned int freq)
197{
198 return count_to_clock_divider(
199 DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, freq * 16));
200}
201
202static inline unsigned int clock_divider_to_carrier_freq(unsigned int divider)
203{
204 return DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, (divider + 1) * 16);
205}
206
207static inline u16 freq_to_clock_divider(unsigned int freq,
208 unsigned int rollovers)
209{
210 return count_to_clock_divider(
211 DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, freq * rollovers));
212}
213
214static inline unsigned int clock_divider_to_freq(unsigned int divider,
215 unsigned int rollovers)
216{
217 return DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ,
218 (divider + 1) * rollovers);
219}
220
221/*
222 * Low Pass Filter register calculations
223 *
224 * Note the largest count value of 0xffff corresponds to:
225 * 0xffff * 1000 / 108/2 MHz = 1,213,611.11... ns
226 * which fits in 21 bits, so we'll use unsigned int for time arguments.
227 */
228static inline u16 count_to_lpf_count(unsigned int d)
229{
230 if (d > FILTR_LPF)
231 d = FILTR_LPF;
232 else if (d < 4)
233 d = 0;
234 return (u16) d;
235}
236
237static inline u16 ns_to_lpf_count(unsigned int ns)
238{
239 return count_to_lpf_count(
240 DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ / 1000000 * ns, 1000));
241}
242
243static inline unsigned int lpf_count_to_ns(unsigned int count)
244{
245 /* Duration of the Low Pass Filter rejection window in ns */
246 return DIV_ROUND_CLOSEST(count * 1000,
247 CX23888_IR_REFCLK_FREQ / 1000000);
248}
249
250static inline unsigned int lpf_count_to_us(unsigned int count)
251{
252 /* Duration of the Low Pass Filter rejection window in us */
253 return DIV_ROUND_CLOSEST(count, CX23888_IR_REFCLK_FREQ / 1000000);
254}
255
256/*
257 * FIFO register pulse width count compuations
258 */
259static u32 clock_divider_to_resolution(u16 divider)
260{
261 /*
262 * Resolution is the duration of 1 tick of the readable portion of
263 * of the pulse width counter as read from the FIFO. The two lsb's are
264 * not readable, hence the << 2. This function returns ns.
265 */
266 return DIV_ROUND_CLOSEST((1 << 2) * ((u32) divider + 1) * 1000,
267 CX23888_IR_REFCLK_FREQ / 1000000);
268}
269
270static u64 pulse_width_count_to_ns(u16 count, u16 divider)
271{
272 u64 n;
273 u32 rem;
274
275 /*
276 * The 2 lsb's of the pulse width timer count are not readable, hence
277 * the (count << 2) | 0x3
278 */
279 n = (((u64) count << 2) | 0x3) * (divider + 1) * 1000; /* millicycles */
280 rem = do_div(n, CX23888_IR_REFCLK_FREQ / 1000000); /* / MHz => ns */
281 if (rem >= CX23888_IR_REFCLK_FREQ / 1000000 / 2)
282 n++;
283 return n;
284}
285
286static unsigned int pulse_width_count_to_us(u16 count, u16 divider)
287{
288 u64 n;
289 u32 rem;
290
291 /*
292 * The 2 lsb's of the pulse width timer count are not readable, hence
293 * the (count << 2) | 0x3
294 */
295 n = (((u64) count << 2) | 0x3) * (divider + 1); /* cycles */
296 rem = do_div(n, CX23888_IR_REFCLK_FREQ / 1000000); /* / MHz => us */
297 if (rem >= CX23888_IR_REFCLK_FREQ / 1000000 / 2)
298 n++;
299 return (unsigned int) n;
300}
301
302/*
303 * Pulse Clocks computations: Combined Pulse Width Count & Rx Clock Counts
304 *
305 * The total pulse clock count is an 18 bit pulse width timer count as the most
306 * significant part and (up to) 16 bit clock divider count as a modulus.
307 * When the Rx clock divider ticks down to 0, it increments the 18 bit pulse
308 * width timer count's least significant bit.
309 */
310static u64 ns_to_pulse_clocks(u32 ns)
311{
312 u64 clocks;
313 u32 rem;
314 clocks = CX23888_IR_REFCLK_FREQ / 1000000 * (u64) ns; /* millicycles */
315 rem = do_div(clocks, 1000); /* /1000 = cycles */
316 if (rem >= 1000 / 2)
317 clocks++;
318 return clocks;
319}
320
321static u16 pulse_clocks_to_clock_divider(u64 count)
322{
323 u32 rem;
324
325 rem = do_div(count, (FIFO_RXTX << 2) | 0x3);
326
327 /* net result needs to be rounded down and decremented by 1 */
328 if (count > RXCLK_RCD + 1)
329 count = RXCLK_RCD;
330 else if (count < 2)
331 count = 1;
332 else
333 count--;
334 return (u16) count;
335}
336
337/*
338 * IR Control Register helpers
339 */
340enum tx_fifo_watermark {
341 TX_FIFO_HALF_EMPTY = 0,
342 TX_FIFO_EMPTY = CNTRL_TIC,
343};
344
345enum rx_fifo_watermark {
346 RX_FIFO_HALF_FULL = 0,
347 RX_FIFO_NOT_EMPTY = CNTRL_RIC,
348};
349
350static inline void control_tx_irq_watermark(struct cx23885_dev *dev,
351 enum tx_fifo_watermark level)
352{
353 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_TIC, level);
354}
355
356static inline void control_rx_irq_watermark(struct cx23885_dev *dev,
357 enum rx_fifo_watermark level)
358{
359 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_RIC, level);
360}
361
362static inline void control_tx_enable(struct cx23885_dev *dev, bool enable)
363{
364 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~(CNTRL_TXE | CNTRL_TFE),
365 enable ? (CNTRL_TXE | CNTRL_TFE) : 0);
366}
367
368static inline void control_rx_enable(struct cx23885_dev *dev, bool enable)
369{
370 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~(CNTRL_RXE | CNTRL_RFE),
371 enable ? (CNTRL_RXE | CNTRL_RFE) : 0);
372}
373
374static inline void control_tx_modulation_enable(struct cx23885_dev *dev,
375 bool enable)
376{
377 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_MOD,
378 enable ? CNTRL_MOD : 0);
379}
380
381static inline void control_rx_demodulation_enable(struct cx23885_dev *dev,
382 bool enable)
383{
384 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_DMD,
385 enable ? CNTRL_DMD : 0);
386}
387
388static inline void control_rx_s_edge_detection(struct cx23885_dev *dev,
389 u32 edge_types)
390{
391 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_EDG_BOTH,
392 edge_types & CNTRL_EDG_BOTH);
393}
394
395static void control_rx_s_carrier_window(struct cx23885_dev *dev,
396 unsigned int carrier,
397 unsigned int *carrier_range_low,
398 unsigned int *carrier_range_high)
399{
400 u32 v;
401 unsigned int c16 = carrier * 16;
402
403 if (*carrier_range_low < DIV_ROUND_CLOSEST(c16, 16 + 3)) {
404 v = CNTRL_WIN_3_4;
405 *carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 4);
406 } else {
407 v = CNTRL_WIN_3_3;
408 *carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 3);
409 }
410
411 if (*carrier_range_high > DIV_ROUND_CLOSEST(c16, 16 - 3)) {
412 v |= CNTRL_WIN_4_3;
413 *carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 4);
414 } else {
415 v |= CNTRL_WIN_3_3;
416 *carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 3);
417 }
418 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_WIN, v);
419}
420
421static inline void control_tx_polarity_invert(struct cx23885_dev *dev,
422 bool invert)
423{
424 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_CPL,
425 invert ? CNTRL_CPL : 0);
426}
427
428/*
429 * IR Rx & Tx Clock Register helpers
430 */
431static unsigned int txclk_tx_s_carrier(struct cx23885_dev *dev,
432 unsigned int freq,
433 u16 *divider)
434{
435 *divider = carrier_freq_to_clock_divider(freq);
436 cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider);
437 return clock_divider_to_carrier_freq(*divider);
438}
439
440static unsigned int rxclk_rx_s_carrier(struct cx23885_dev *dev,
441 unsigned int freq,
442 u16 *divider)
443{
444 *divider = carrier_freq_to_clock_divider(freq);
445 cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider);
446 return clock_divider_to_carrier_freq(*divider);
447}
448
449static u32 txclk_tx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns,
450 u16 *divider)
451{
452 u64 pulse_clocks;
453
454 if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS)
455 ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
456 pulse_clocks = ns_to_pulse_clocks(ns);
457 *divider = pulse_clocks_to_clock_divider(pulse_clocks);
458 cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider);
459 return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider);
460}
461
462static u32 rxclk_rx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns,
463 u16 *divider)
464{
465 u64 pulse_clocks;
466
467 if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS)
468 ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
469 pulse_clocks = ns_to_pulse_clocks(ns);
470 *divider = pulse_clocks_to_clock_divider(pulse_clocks);
471 cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider);
472 return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider);
473}
474
475/*
476 * IR Tx Carrier Duty Cycle register helpers
477 */
478static unsigned int cduty_tx_s_duty_cycle(struct cx23885_dev *dev,
479 unsigned int duty_cycle)
480{
481 u32 n;
482 n = DIV_ROUND_CLOSEST(duty_cycle * 100, 625); /* 16ths of 100% */
483 if (n != 0)
484 n--;
485 if (n > 15)
486 n = 15;
487 cx23888_ir_write4(dev, CX23888_IR_CDUTY_REG, n);
488 return DIV_ROUND_CLOSEST((n + 1) * 100, 16);
489}
490
491/*
492 * IR Filter Register helpers
493 */
494static u32 filter_rx_s_min_width(struct cx23885_dev *dev, u32 min_width_ns)
495{
496 u32 count = ns_to_lpf_count(min_width_ns);
497 cx23888_ir_write4(dev, CX23888_IR_FILTR_REG, count);
498 return lpf_count_to_ns(count);
499}
500
501/*
502 * IR IRQ Enable Register helpers
503 */
504static inline void irqenable_rx(struct cx23885_dev *dev, u32 mask)
505{
506 mask &= (IRQEN_RTE | IRQEN_ROE | IRQEN_RSE);
507 cx23888_ir_and_or4(dev, CX23888_IR_IRQEN_REG,
508 ~(IRQEN_RTE | IRQEN_ROE | IRQEN_RSE), mask);
509}
510
511static inline void irqenable_tx(struct cx23885_dev *dev, u32 mask)
512{
513 mask &= IRQEN_TSE;
514 cx23888_ir_and_or4(dev, CX23888_IR_IRQEN_REG, ~IRQEN_TSE, mask);
515}
516
517/*
518 * V4L2 Subdevice IR Ops
519 */
520static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
521 bool *handled)
522{
523 struct cx23888_ir_state *state = to_state(sd);
524 struct cx23885_dev *dev = state->dev;
525
526 u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG);
527 u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
528 u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG);
529
530 u32 rx_data[FIFO_RX_DEPTH];
531 int i, j, k;
532 u32 events, v;
533 int tsr, rsr, rto, ror, tse, rse, rte, roe, kror;
534
535 tsr = stats & STATS_TSR; /* Tx FIFO Service Request */
536 rsr = stats & STATS_RSR; /* Rx FIFO Service Request */
537 rto = stats & STATS_RTO; /* Rx Pulse Width Timer Time Out */
538 ror = stats & STATS_ROR; /* Rx FIFO Over Run */
539
540 tse = irqen & IRQEN_TSE; /* Tx FIFO Service Request IRQ Enable */
541 rse = irqen & IRQEN_RSE; /* Rx FIFO Service Reuqest IRQ Enable */
542 rte = irqen & IRQEN_RTE; /* Rx Pulse Width Timer Time Out IRQ Enable */
543 roe = irqen & IRQEN_ROE; /* Rx FIFO Over Run IRQ Enable */
544
545 *handled = false;
546 v4l2_dbg(2, ir_888_debug, sd, "IRQ Status: %s %s %s %s %s %s\n",
547 tsr ? "tsr" : " ", rsr ? "rsr" : " ",
548 rto ? "rto" : " ", ror ? "ror" : " ",
549 stats & STATS_TBY ? "tby" : " ",
550 stats & STATS_RBY ? "rby" : " ");
551
552 v4l2_dbg(2, ir_888_debug, sd, "IRQ Enables: %s %s %s %s\n",
553 tse ? "tse" : " ", rse ? "rse" : " ",
554 rte ? "rte" : " ", roe ? "roe" : " ");
555
556 /*
557 * Transmitter interrupt service
558 */
559 if (tse && tsr) {
560 /*
561 * TODO:
562 * Check the watermark threshold setting
563 * Pull FIFO_TX_DEPTH or FIFO_TX_DEPTH/2 entries from tx_kfifo
564 * Push the data to the hardware FIFO.
565 * If there was nothing more to send in the tx_kfifo, disable
566 * the TSR IRQ and notify the v4l2_device.
567 * If there was something in the tx_kfifo, check the tx_kfifo
568 * level and notify the v4l2_device, if it is low.
569 */
570 /* For now, inhibit TSR interrupt until Tx is implemented */
571 irqenable_tx(dev, 0);
572 events = V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ;
573 v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_TX_NOTIFY, &events);
574 *handled = true;
575 }
576
577 /*
578 * Receiver interrupt service
579 */
580 kror = 0;
581 if ((rse && rsr) || (rte && rto)) {
582 /*
583 * Receive data on RSR to clear the STATS_RSR.
584 * Receive data on RTO, since we may not have yet hit the RSR
585 * watermark when we receive the RTO.
586 */
587 for (i = 0, v = FIFO_RX_NDV;
588 (v & FIFO_RX_NDV) && !kror; i = 0) {
589 for (j = 0;
590 (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) {
591 v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG);
592 rx_data[i++] = v & ~FIFO_RX_NDV;
593 }
594 if (i == 0)
595 break;
596 j = i * sizeof(u32);
597 k = kfifo_put(state->rx_kfifo,
598 (unsigned char *) rx_data, j);
599 if (k != j)
600 kror++; /* rx_kfifo over run */
601 }
602 *handled = true;
603 }
604
605 events = 0;
606 v = 0;
607 if (kror) {
608 events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN;
609 v4l2_err(sd, "IR receiver software FIFO overrun\n");
610 }
611 if (roe && ror) {
612 /*
613 * The RX FIFO Enable (CNTRL_RFE) must be toggled to clear
614 * the Rx FIFO Over Run status (STATS_ROR)
615 */
616 v |= CNTRL_RFE;
617 events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN;
618 v4l2_err(sd, "IR receiver hardware FIFO overrun\n");
619 }
620 if (rte && rto) {
621 /*
622 * The IR Receiver Enable (CNTRL_RXE) must be toggled to clear
623 * the Rx Pulse Width Timer Time Out (STATS_RTO)
624 */
625 v |= CNTRL_RXE;
626 events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED;
627 }
628 if (v) {
629 /* Clear STATS_ROR & STATS_RTO as needed by reseting hardware */
630 cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl & ~v);
631 cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl);
632 *handled = true;
633 }
634 if (kfifo_len(state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2)
635 events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
636
637 if (events)
638 v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events);
639 return 0;
640}
641
642/* Receiver */
643static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
644 ssize_t *num)
645{
646 struct cx23888_ir_state *state = to_state(sd);
647 bool invert = (bool) atomic_read(&state->rx_invert);
648 u16 divider = (u16) atomic_read(&state->rxclk_divider);
649
650 unsigned int i, n;
651 u32 *p;
652 u32 u, v;
653
654 n = count / sizeof(u32) * sizeof(u32);
655 if (n == 0) {
656 *num = 0;
657 return 0;
658 }
659
660 n = kfifo_get(state->rx_kfifo, buf, n);
661
662 n /= sizeof(u32);
663 *num = n * sizeof(u32);
664
665 for (p = (u32 *) buf, i = 0; i < n; p++, i++) {
666 if ((*p & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
667 *p = V4L2_SUBDEV_IR_PULSE_RX_SEQ_END;
668 v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n");
669 continue;
670 }
671
672 u = (*p & FIFO_RXTX_LVL) ? V4L2_SUBDEV_IR_PULSE_LEVEL_MASK : 0;
673 if (invert)
674 u = u ? 0 : V4L2_SUBDEV_IR_PULSE_LEVEL_MASK;
675
676 v = (u32) pulse_width_count_to_ns((u16) (*p & FIFO_RXTX),
677 divider);
678 if (v >= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS)
679 v = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS - 1;
680
681 *p = u | v;
682
683 v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns %s\n",
684 v, u ? "mark" : "space");
685 }
686 return 0;
687}
688
689static int cx23888_ir_rx_g_parameters(struct v4l2_subdev *sd,
690 struct v4l2_subdev_ir_parameters *p)
691{
692 struct cx23888_ir_state *state = to_state(sd);
693 mutex_lock(&state->rx_params_lock);
694 memcpy(p, &state->rx_params, sizeof(struct v4l2_subdev_ir_parameters));
695 mutex_unlock(&state->rx_params_lock);
696 return 0;
697}
698
699static int cx23888_ir_rx_shutdown(struct v4l2_subdev *sd)
700{
701 struct cx23888_ir_state *state = to_state(sd);
702 struct cx23885_dev *dev = state->dev;
703
704 mutex_lock(&state->rx_params_lock);
705
706 /* Disable or slow down all IR Rx circuits and counters */
707 irqenable_rx(dev, 0);
708 control_rx_enable(dev, false);
709 control_rx_demodulation_enable(dev, false);
710 control_rx_s_edge_detection(dev, CNTRL_EDG_NONE);
711 filter_rx_s_min_width(dev, 0);
712 cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, RXCLK_RCD);
713
714 state->rx_params.shutdown = true;
715
716 mutex_unlock(&state->rx_params_lock);
717 return 0;
718}
719
720static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd,
721 struct v4l2_subdev_ir_parameters *p)
722{
723 struct cx23888_ir_state *state = to_state(sd);
724 struct cx23885_dev *dev = state->dev;
725 struct v4l2_subdev_ir_parameters *o = &state->rx_params;
726 u16 rxclk_divider;
727
728 if (p->shutdown)
729 return cx23888_ir_rx_shutdown(sd);
730
731 if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
732 return -ENOSYS;
733
734 mutex_lock(&state->rx_params_lock);
735
736 o->shutdown = p->shutdown;
737
738 o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
739
740 o->bytes_per_data_element = p->bytes_per_data_element = sizeof(u32);
741
742 /* Before we tweak the hardware, we have to disable the receiver */
743 irqenable_rx(dev, 0);
744 control_rx_enable(dev, false);
745
746 control_rx_demodulation_enable(dev, p->modulation);
747 o->modulation = p->modulation;
748
749 if (p->modulation) {
750 p->carrier_freq = rxclk_rx_s_carrier(dev, p->carrier_freq,
751 &rxclk_divider);
752
753 o->carrier_freq = p->carrier_freq;
754
755 o->duty_cycle = p->duty_cycle = 50;
756
757 control_rx_s_carrier_window(dev, p->carrier_freq,
758 &p->carrier_range_lower,
759 &p->carrier_range_upper);
760 o->carrier_range_lower = p->carrier_range_lower;
761 o->carrier_range_upper = p->carrier_range_upper;
762 } else {
763 p->max_pulse_width =
764 rxclk_rx_s_max_pulse_width(dev, p->max_pulse_width,
765 &rxclk_divider);
766 o->max_pulse_width = p->max_pulse_width;
767 }
768 atomic_set(&state->rxclk_divider, rxclk_divider);
769
770 p->noise_filter_min_width =
771 filter_rx_s_min_width(dev, p->noise_filter_min_width);
772 o->noise_filter_min_width = p->noise_filter_min_width;
773
774 p->resolution = clock_divider_to_resolution(rxclk_divider);
775 o->resolution = p->resolution;
776
777 /* FIXME - make this dependent on resolution for better performance */
778 control_rx_irq_watermark(dev, RX_FIFO_HALF_FULL);
779
780 control_rx_s_edge_detection(dev, CNTRL_EDG_BOTH);
781
782 o->invert = p->invert;
783 atomic_set(&state->rx_invert, p->invert);
784
785 o->interrupt_enable = p->interrupt_enable;
786 o->enable = p->enable;
787 if (p->enable) {
788 kfifo_reset(state->rx_kfifo);
789 if (p->interrupt_enable)
790 irqenable_rx(dev, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE);
791 control_rx_enable(dev, p->enable);
792 }
793
794 mutex_unlock(&state->rx_params_lock);
795 return 0;
796}
797
798/* Transmitter */
799static int cx23888_ir_tx_write(struct v4l2_subdev *sd, u8 *buf, size_t count,
800 ssize_t *num)
801{
802 struct cx23888_ir_state *state = to_state(sd);
803 struct cx23885_dev *dev = state->dev;
804 /* For now enable the Tx FIFO Service interrupt & pretend we did work */
805 irqenable_tx(dev, IRQEN_TSE);
806 *num = count;
807 return 0;
808}
809
810static int cx23888_ir_tx_g_parameters(struct v4l2_subdev *sd,
811 struct v4l2_subdev_ir_parameters *p)
812{
813 struct cx23888_ir_state *state = to_state(sd);
814 mutex_lock(&state->tx_params_lock);
815 memcpy(p, &state->tx_params, sizeof(struct v4l2_subdev_ir_parameters));
816 mutex_unlock(&state->tx_params_lock);
817 return 0;
818}
819
820static int cx23888_ir_tx_shutdown(struct v4l2_subdev *sd)
821{
822 struct cx23888_ir_state *state = to_state(sd);
823 struct cx23885_dev *dev = state->dev;
824
825 mutex_lock(&state->tx_params_lock);
826
827 /* Disable or slow down all IR Tx circuits and counters */
828 irqenable_tx(dev, 0);
829 control_tx_enable(dev, false);
830 control_tx_modulation_enable(dev, false);
831 cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, TXCLK_TCD);
832
833 state->tx_params.shutdown = true;
834
835 mutex_unlock(&state->tx_params_lock);
836 return 0;
837}
838
839static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd,
840 struct v4l2_subdev_ir_parameters *p)
841{
842 struct cx23888_ir_state *state = to_state(sd);
843 struct cx23885_dev *dev = state->dev;
844 struct v4l2_subdev_ir_parameters *o = &state->tx_params;
845 u16 txclk_divider;
846
847 if (p->shutdown)
848 return cx23888_ir_tx_shutdown(sd);
849
850 if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
851 return -ENOSYS;
852
853 mutex_lock(&state->tx_params_lock);
854
855 o->shutdown = p->shutdown;
856
857 o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
858
859 o->bytes_per_data_element = p->bytes_per_data_element = sizeof(u32);
860
861 /* Before we tweak the hardware, we have to disable the transmitter */
862 irqenable_tx(dev, 0);
863 control_tx_enable(dev, false);
864
865 control_tx_modulation_enable(dev, p->modulation);
866 o->modulation = p->modulation;
867
868 if (p->modulation) {
869 p->carrier_freq = txclk_tx_s_carrier(dev, p->carrier_freq,
870 &txclk_divider);
871 o->carrier_freq = p->carrier_freq;
872
873 p->duty_cycle = cduty_tx_s_duty_cycle(dev, p->duty_cycle);
874 o->duty_cycle = p->duty_cycle;
875 } else {
876 p->max_pulse_width =
877 txclk_tx_s_max_pulse_width(dev, p->max_pulse_width,
878 &txclk_divider);
879 o->max_pulse_width = p->max_pulse_width;
880 }
881 atomic_set(&state->txclk_divider, txclk_divider);
882
883 p->resolution = clock_divider_to_resolution(txclk_divider);
884 o->resolution = p->resolution;
885
886 /* FIXME - make this dependent on resolution for better performance */
887 control_tx_irq_watermark(dev, TX_FIFO_HALF_EMPTY);
888
889 control_tx_polarity_invert(dev, p->invert);
890 o->invert = p->invert;
891
892 o->interrupt_enable = p->interrupt_enable;
893 o->enable = p->enable;
894 if (p->enable) {
895 kfifo_reset(state->tx_kfifo);
896 if (p->interrupt_enable)
897 irqenable_tx(dev, IRQEN_TSE);
898 control_tx_enable(dev, p->enable);
899 }
900
901 mutex_unlock(&state->tx_params_lock);
902 return 0;
903}
904
905
906/*
907 * V4L2 Subdevice Core Ops
908 */
909static int cx23888_ir_log_status(struct v4l2_subdev *sd)
910{
911 struct cx23888_ir_state *state = to_state(sd);
912 struct cx23885_dev *dev = state->dev;
913 char *s;
914 int i, j;
915
916 u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG);
917 u32 txclk = cx23888_ir_read4(dev, CX23888_IR_TXCLK_REG) & TXCLK_TCD;
918 u32 rxclk = cx23888_ir_read4(dev, CX23888_IR_RXCLK_REG) & RXCLK_RCD;
919 u32 cduty = cx23888_ir_read4(dev, CX23888_IR_CDUTY_REG) & CDUTY_CDC;
920 u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG);
921 u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
922 u32 filtr = cx23888_ir_read4(dev, CX23888_IR_FILTR_REG) & FILTR_LPF;
923
924 v4l2_info(sd, "IR Receiver:\n");
925 v4l2_info(sd, "\tEnabled: %s\n",
926 cntrl & CNTRL_RXE ? "yes" : "no");
927 v4l2_info(sd, "\tDemodulation from a carrier: %s\n",
928 cntrl & CNTRL_DMD ? "enabled" : "disabled");
929 v4l2_info(sd, "\tFIFO: %s\n",
930 cntrl & CNTRL_RFE ? "enabled" : "disabled");
931 switch (cntrl & CNTRL_EDG) {
932 case CNTRL_EDG_NONE:
933 s = "disabled";
934 break;
935 case CNTRL_EDG_FALL:
936 s = "falling edge";
937 break;
938 case CNTRL_EDG_RISE:
939 s = "rising edge";
940 break;
941 case CNTRL_EDG_BOTH:
942 s = "rising & falling edges";
943 break;
944 default:
945 s = "??? edge";
946 break;
947 }
948 v4l2_info(sd, "\tPulse timers' start/stop trigger: %s\n", s);
949 v4l2_info(sd, "\tFIFO data on pulse timer overflow: %s\n",
950 cntrl & CNTRL_R ? "not loaded" : "overflow marker");
951 v4l2_info(sd, "\tFIFO interrupt watermark: %s\n",
952 cntrl & CNTRL_RIC ? "not empty" : "half full or greater");
953 v4l2_info(sd, "\tLoopback mode: %s\n",
954 cntrl & CNTRL_LBM ? "loopback active" : "normal receive");
955 if (cntrl & CNTRL_DMD) {
956 v4l2_info(sd, "\tExpected carrier (16 clocks): %u Hz\n",
957 clock_divider_to_carrier_freq(rxclk));
958 switch (cntrl & CNTRL_WIN) {
959 case CNTRL_WIN_3_3:
960 i = 3;
961 j = 3;
962 break;
963 case CNTRL_WIN_4_3:
964 i = 4;
965 j = 3;
966 break;
967 case CNTRL_WIN_3_4:
968 i = 3;
969 j = 4;
970 break;
971 case CNTRL_WIN_4_4:
972 i = 4;
973 j = 4;
974 break;
975 default:
976 i = 0;
977 j = 0;
978 break;
979 }
980 v4l2_info(sd, "\tNext carrier edge window: 16 clocks "
981 "-%1d/+%1d, %u to %u Hz\n", i, j,
982 clock_divider_to_freq(rxclk, 16 + j),
983 clock_divider_to_freq(rxclk, 16 - i));
984 } else {
985 v4l2_info(sd, "\tMax measurable pulse width: %u us, "
986 "%llu ns\n",
987 pulse_width_count_to_us(FIFO_RXTX, rxclk),
988 pulse_width_count_to_ns(FIFO_RXTX, rxclk));
989 }
990 v4l2_info(sd, "\tLow pass filter: %s\n",
991 filtr ? "enabled" : "disabled");
992 if (filtr)
993 v4l2_info(sd, "\tMin acceptable pulse width (LPF): %u us, "
994 "%u ns\n",
995 lpf_count_to_us(filtr),
996 lpf_count_to_ns(filtr));
997 v4l2_info(sd, "\tPulse width timer timed-out: %s\n",
998 stats & STATS_RTO ? "yes" : "no");
999 v4l2_info(sd, "\tPulse width timer time-out intr: %s\n",
1000 irqen & IRQEN_RTE ? "enabled" : "disabled");
1001 v4l2_info(sd, "\tFIFO overrun: %s\n",
1002 stats & STATS_ROR ? "yes" : "no");
1003 v4l2_info(sd, "\tFIFO overrun interrupt: %s\n",
1004 irqen & IRQEN_ROE ? "enabled" : "disabled");
1005 v4l2_info(sd, "\tBusy: %s\n",
1006 stats & STATS_RBY ? "yes" : "no");
1007 v4l2_info(sd, "\tFIFO service requested: %s\n",
1008 stats & STATS_RSR ? "yes" : "no");
1009 v4l2_info(sd, "\tFIFO service request interrupt: %s\n",
1010 irqen & IRQEN_RSE ? "enabled" : "disabled");
1011
1012 v4l2_info(sd, "IR Transmitter:\n");
1013 v4l2_info(sd, "\tEnabled: %s\n",
1014 cntrl & CNTRL_TXE ? "yes" : "no");
1015 v4l2_info(sd, "\tModulation onto a carrier: %s\n",
1016 cntrl & CNTRL_MOD ? "enabled" : "disabled");
1017 v4l2_info(sd, "\tFIFO: %s\n",
1018 cntrl & CNTRL_TFE ? "enabled" : "disabled");
1019 v4l2_info(sd, "\tFIFO interrupt watermark: %s\n",
1020 cntrl & CNTRL_TIC ? "not empty" : "half full or less");
1021 v4l2_info(sd, "\tSignal polarity: %s\n",
1022 cntrl & CNTRL_CPL ? "0:mark 1:space" : "0:space 1:mark");
1023 if (cntrl & CNTRL_MOD) {
1024 v4l2_info(sd, "\tCarrier (16 clocks): %u Hz\n",
1025 clock_divider_to_carrier_freq(txclk));
1026 v4l2_info(sd, "\tCarrier duty cycle: %2u/16\n",
1027 cduty + 1);
1028 } else {
1029 v4l2_info(sd, "\tMax pulse width: %u us, "
1030 "%llu ns\n",
1031 pulse_width_count_to_us(FIFO_RXTX, txclk),
1032 pulse_width_count_to_ns(FIFO_RXTX, txclk));
1033 }
1034 v4l2_info(sd, "\tBusy: %s\n",
1035 stats & STATS_TBY ? "yes" : "no");
1036 v4l2_info(sd, "\tFIFO service requested: %s\n",
1037 stats & STATS_TSR ? "yes" : "no");
1038 v4l2_info(sd, "\tFIFO service request interrupt: %s\n",
1039 irqen & IRQEN_TSE ? "enabled" : "disabled");
1040
1041 return 0;
1042}
1043
1044static inline int cx23888_ir_dbg_match(const struct v4l2_dbg_match *match)
1045{
1046 return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 2;
1047}
1048
1049static int cx23888_ir_g_chip_ident(struct v4l2_subdev *sd,
1050 struct v4l2_dbg_chip_ident *chip)
1051{
1052 struct cx23888_ir_state *state = to_state(sd);
1053
1054 if (cx23888_ir_dbg_match(&chip->match)) {
1055 chip->ident = state->id;
1056 chip->revision = state->rev;
1057 }
1058 return 0;
1059}
1060
1061#ifdef CONFIG_VIDEO_ADV_DEBUG
1062static int cx23888_ir_g_register(struct v4l2_subdev *sd,
1063 struct v4l2_dbg_register *reg)
1064{
1065 struct cx23888_ir_state *state = to_state(sd);
1066 u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg;
1067
1068 if (!cx23888_ir_dbg_match(&reg->match))
1069 return -EINVAL;
1070 if ((addr & 0x3) != 0)
1071 return -EINVAL;
1072 if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG)
1073 return -EINVAL;
1074 if (!capable(CAP_SYS_ADMIN))
1075 return -EPERM;
1076 reg->size = 4;
1077 reg->val = cx23888_ir_read4(state->dev, addr);
1078 return 0;
1079}
1080
1081static int cx23888_ir_s_register(struct v4l2_subdev *sd,
1082 struct v4l2_dbg_register *reg)
1083{
1084 struct cx23888_ir_state *state = to_state(sd);
1085 u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg;
1086
1087 if (!cx23888_ir_dbg_match(&reg->match))
1088 return -EINVAL;
1089 if ((addr & 0x3) != 0)
1090 return -EINVAL;
1091 if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG)
1092 return -EINVAL;
1093 if (!capable(CAP_SYS_ADMIN))
1094 return -EPERM;
1095 cx23888_ir_write4(state->dev, addr, reg->val);
1096 return 0;
1097}
1098#endif
1099
1100static const struct v4l2_subdev_core_ops cx23888_ir_core_ops = {
1101 .g_chip_ident = cx23888_ir_g_chip_ident,
1102 .log_status = cx23888_ir_log_status,
1103#ifdef CONFIG_VIDEO_ADV_DEBUG
1104 .g_register = cx23888_ir_g_register,
1105 .s_register = cx23888_ir_s_register,
1106#endif
1107};
1108
1109static const struct v4l2_subdev_ir_ops cx23888_ir_ir_ops = {
1110 .interrupt_service_routine = cx23888_ir_irq_handler,
1111
1112 .rx_read = cx23888_ir_rx_read,
1113 .rx_g_parameters = cx23888_ir_rx_g_parameters,
1114 .rx_s_parameters = cx23888_ir_rx_s_parameters,
1115
1116 .tx_write = cx23888_ir_tx_write,
1117 .tx_g_parameters = cx23888_ir_tx_g_parameters,
1118 .tx_s_parameters = cx23888_ir_tx_s_parameters,
1119};
1120
1121static const struct v4l2_subdev_ops cx23888_ir_controller_ops = {
1122 .core = &cx23888_ir_core_ops,
1123 .ir = &cx23888_ir_ir_ops,
1124};
1125
1126static const struct v4l2_subdev_ir_parameters default_rx_params = {
1127 .bytes_per_data_element = sizeof(u32),
1128 .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
1129
1130 .enable = false,
1131 .interrupt_enable = false,
1132 .shutdown = true,
1133
1134 .modulation = true,
1135 .carrier_freq = 36000, /* 36 kHz - RC-5, RC-6, and RC-6A carrier */
1136
1137 /* RC-5: 666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */
1138 /* RC-6A: 333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */
1139 .noise_filter_min_width = 333333, /* ns */
1140 .carrier_range_lower = 35000,
1141 .carrier_range_upper = 37000,
1142 .invert = false,
1143};
1144
1145static const struct v4l2_subdev_ir_parameters default_tx_params = {
1146 .bytes_per_data_element = sizeof(u32),
1147 .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
1148
1149 .enable = false,
1150 .interrupt_enable = false,
1151 .shutdown = true,
1152
1153 .modulation = true,
1154 .carrier_freq = 36000, /* 36 kHz - RC-5 carrier */
1155 .duty_cycle = 25, /* 25 % - RC-5 carrier */
1156 .invert = false,
1157};
1158
1159int cx23888_ir_probe(struct cx23885_dev *dev)
1160{
1161 struct cx23888_ir_state *state;
1162 struct v4l2_subdev *sd;
1163 struct v4l2_subdev_ir_parameters default_params;
1164 int ret;
1165
1166 state = kzalloc(sizeof(struct cx23888_ir_state), GFP_KERNEL);
1167 if (state == NULL)
1168 return -ENOMEM;
1169
1170 spin_lock_init(&state->rx_kfifo_lock);
1171 state->rx_kfifo = kfifo_alloc(CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL,
1172 &state->rx_kfifo_lock);
1173 if (state->rx_kfifo == NULL)
1174 return -ENOMEM;
1175
1176 spin_lock_init(&state->tx_kfifo_lock);
1177 state->tx_kfifo = kfifo_alloc(CX23888_IR_TX_KFIFO_SIZE, GFP_KERNEL,
1178 &state->tx_kfifo_lock);
1179 if (state->tx_kfifo == NULL) {
1180 kfifo_free(state->rx_kfifo);
1181 return -ENOMEM;
1182 }
1183
1184 state->dev = dev;
1185 state->id = V4L2_IDENT_CX23888_IR;
1186 state->rev = 0;
1187 sd = &state->sd;
1188
1189 v4l2_subdev_init(sd, &cx23888_ir_controller_ops);
1190 v4l2_set_subdevdata(sd, state);
1191 /* FIXME - fix the formatting of dev->v4l2_dev.name and use it */
1192 snprintf(sd->name, sizeof(sd->name), "%s/888-ir", dev->name);
1193 sd->grp_id = CX23885_HW_888_IR;
1194
1195 ret = v4l2_device_register_subdev(&dev->v4l2_dev, sd);
1196 if (ret == 0) {
1197 /*
1198 * Ensure no interrupts arrive from '888 specific conditions,
1199 * since we ignore them in this driver to have commonality with
1200 * similar IR controller cores.
1201 */
1202 cx23888_ir_write4(dev, CX23888_IR_IRQEN_REG, 0);
1203
1204 mutex_init(&state->rx_params_lock);
1205 memcpy(&default_params, &default_rx_params,
1206 sizeof(struct v4l2_subdev_ir_parameters));
1207 v4l2_subdev_call(sd, ir, rx_s_parameters, &default_params);
1208
1209 mutex_init(&state->tx_params_lock);
1210 memcpy(&default_params, &default_tx_params,
1211 sizeof(struct v4l2_subdev_ir_parameters));
1212 v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params);
1213 } else {
1214 kfifo_free(state->rx_kfifo);
1215 kfifo_free(state->tx_kfifo);
1216 }
1217 return ret;
1218}
1219
1220int cx23888_ir_remove(struct cx23885_dev *dev)
1221{
1222 struct v4l2_subdev *sd;
1223 struct cx23888_ir_state *state;
1224
1225 sd = cx23885_find_hw(dev, CX23885_HW_888_IR);
1226 if (sd == NULL)
1227 return -ENODEV;
1228
1229 cx23888_ir_rx_shutdown(sd);
1230 cx23888_ir_tx_shutdown(sd);
1231
1232 state = to_state(sd);
1233 v4l2_device_unregister_subdev(sd);
1234 kfifo_free(state->rx_kfifo);
1235 kfifo_free(state->tx_kfifo);
1236 kfree(state);
1237 /* Nothing more to free() as state held the actual v4l2_subdev object */
1238 return 0;
1239}
diff --git a/drivers/media/video/cx23885/cx23888-ir.h b/drivers/media/video/cx23885/cx23888-ir.h
new file mode 100644
index 000000000000..3d446f9eb94b
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23888-ir.h
@@ -0,0 +1,28 @@
1/*
2 * Driver for the Conexant CX23885/7/8 PCIe bridge
3 *
4 * CX23888 Integrated Consumer Infrared Controller
5 *
6 * Copyright (C) 2009 Andy Walls <awalls@radix.net>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 * 02110-1301, USA.
22 */
23
24#ifndef _CX23888_IR_H_
25#define _CX23888_IR_H_
26int cx23888_ir_probe(struct cx23885_dev *dev);
27int cx23888_ir_remove(struct cx23885_dev *dev);
28#endif