aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2009-09-26 22:17:30 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-12-05 15:40:16 -0500
commit29f8a0a50ac32ac4bc1937dcfdf8de6c406a5f10 (patch)
tree8a7406ebbb15dd7743543901eaeafc00708d31c5 /drivers
parent74618244003a5a9e11240af8c5795ae747d9a2e0 (diff)
V4L/DVB (13086): cx23885: Add skeleton v4l2_subdev for the CX23888 integrated IR controller
This change adds a skeletal implementation of a v4l2_subdevice to provide encapsulation and abstraction of the CX23888's integrated consumer infrared controller. This change also instantiates the cx23888_ir subdev for the HVR-1850 which has IR hardware physically wired up to a CX23888. The cx23888_ir subdev code is being written with long-term objectives to: 1. port it to the cx25840 module for the CX2584x, CX2583x, CX23885, & CX231xx IR controllers 2. possibly port it to the cx18 module for the CX23418 IR controller 3. have the IR subdevice accessed abstractly in the cx23885 module, so the driver can ignore the difference between the CX23885 and CX23888. Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/cx23885/Makefile2
-rw-r--r--drivers/media/video/cx23885/cx23885-cards.c11
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c20
-rw-r--r--drivers/media/video/cx23885/cx23885-ioctl.c11
-rw-r--r--drivers/media/video/cx23885/cx23885.h8
-rw-r--r--drivers/media/video/cx23885/cx23888-ir.c233
-rw-r--r--drivers/media/video/cx23885/cx23888-ir.h28
7 files changed, 310 insertions, 3 deletions
diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile
index 93a954c23f42..3832a1cb768d 100644
--- a/drivers/media/video/cx23885/Makefile
+++ b/drivers/media/video/cx23885/Makefile
@@ -1,6 +1,6 @@
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 cx23885-ioctl.o \ 3 cx23885-ioctl.o cx23888-ir.o \
4 netup-init.o cimax2.o netup-eeprom.o 4 netup-init.o cimax2.o netup-eeprom.o
5 5
6obj-$(CONFIG_VIDEO_CX23885) += cx23885.o 6obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
index bfdf79f1033c..4b5aa08036fa 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 */
@@ -801,6 +802,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
801 802
802int cx23885_ir_init(struct cx23885_dev *dev) 803int cx23885_ir_init(struct cx23885_dev *dev)
803{ 804{
805 int ret = 0;
804 switch (dev->board) { 806 switch (dev->board) {
805 case CX23885_BOARD_HAUPPAUGE_HVR1250: 807 case CX23885_BOARD_HAUPPAUGE_HVR1250:
806 case CX23885_BOARD_HAUPPAUGE_HVR1500: 808 case CX23885_BOARD_HAUPPAUGE_HVR1500:
@@ -812,15 +814,20 @@ int cx23885_ir_init(struct cx23885_dev *dev)
812 case CX23885_BOARD_HAUPPAUGE_HVR1275: 814 case CX23885_BOARD_HAUPPAUGE_HVR1275:
813 case CX23885_BOARD_HAUPPAUGE_HVR1255: 815 case CX23885_BOARD_HAUPPAUGE_HVR1255:
814 case CX23885_BOARD_HAUPPAUGE_HVR1210: 816 case CX23885_BOARD_HAUPPAUGE_HVR1210:
815 case CX23885_BOARD_HAUPPAUGE_HVR1850:
816 /* FIXME: Implement me */ 817 /* FIXME: Implement me */
817 break; 818 break;
819 case CX23885_BOARD_HAUPPAUGE_HVR1850:
820 ret = cx23888_ir_probe(dev);
821 if (ret)
822 break;
823 dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR);
824 break;
818 case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: 825 case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
819 request_module("ir-kbd-i2c"); 826 request_module("ir-kbd-i2c");
820 break; 827 break;
821 } 828 }
822 829
823 return 0; 830 return ret;
824} 831}
825 832
826void cx23885_card_setup(struct cx23885_dev *dev) 833void cx23885_card_setup(struct cx23885_dev *dev)
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index c31284ba19dd..73be16b0d2a0 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -32,6 +32,7 @@
32 32
33#include "cx23885.h" 33#include "cx23885.h"
34#include "cimax2.h" 34#include "cimax2.h"
35#include "cx23888-ir.h"
35 36
36MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); 37MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
37MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); 38MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
@@ -753,6 +754,23 @@ static void cx23885_dev_checkrevision(struct cx23885_dev *dev)
753 __func__, dev->hwrevision); 754 __func__, dev->hwrevision);
754} 755}
755 756
757/* Find the first v4l2_subdev member of the group id in hw */
758struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw)
759{
760 struct v4l2_subdev *result = NULL;
761 struct v4l2_subdev *sd;
762
763 spin_lock(&dev->v4l2_dev.lock);
764 v4l2_device_for_each_subdev(sd, &dev->v4l2_dev) {
765 if (sd->grp_id == hw) {
766 result = sd;
767 break;
768 }
769 }
770 spin_unlock(&dev->v4l2_dev.lock);
771 return result;
772}
773
756static int cx23885_dev_setup(struct cx23885_dev *dev) 774static int cx23885_dev_setup(struct cx23885_dev *dev)
757{ 775{
758 int i; 776 int i;
@@ -1914,6 +1932,8 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev)
1914 1932
1915 cx23885_shutdown(dev); 1933 cx23885_shutdown(dev);
1916 1934
1935 cx23888_ir_remove(dev);
1936
1917 pci_disable_device(pci_dev); 1937 pci_disable_device(pci_dev);
1918 1938
1919 /* unregister stuff */ 1939 /* unregister stuff */
diff --git a/drivers/media/video/cx23885/cx23885-ioctl.c b/drivers/media/video/cx23885/cx23885-ioctl.c
index 3a497b6c4fd7..dfb4627fb340 100644
--- a/drivers/media/video/cx23885/cx23885-ioctl.c
+++ b/drivers/media/video/cx23885/cx23885-ioctl.c
@@ -65,6 +65,17 @@ int cx23885_g_chip_ident(struct file *file, void *fh,
65 chip->revision = 0; 65 chip->revision = 0;
66 } 66 }
67 break; 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;
68 default: 79 default:
69 err = -EINVAL; /* per V4L2 spec */ 80 err = -EINVAL; /* per V4L2 spec */
70 break; 81 break;
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
index f4c4108f23f3..f7ed146566d9 100644
--- a/drivers/media/video/cx23885/cx23885.h
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -355,6 +355,7 @@ struct cx23885_dev {
355 unsigned char radio_addr; 355 unsigned char radio_addr;
356 unsigned int has_radio; 356 unsigned int has_radio;
357 struct v4l2_subdev *sd_cx25840; 357 struct v4l2_subdev *sd_cx25840;
358 struct v4l2_subdev *sd_ir;
358 359
359 /* V4l */ 360 /* V4l */
360 u32 freq; 361 u32 freq;
@@ -383,6 +384,13 @@ static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev)
383#define call_all(dev, o, f, args...) \ 384#define call_all(dev, o, f, args...) \
384 v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) 385 v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args)
385 386
387#define CX23885_HW_888_IR (1 << 0)
388
389#define call_hw(dev, grpid, o, f, args...) \
390 v4l2_device_call_all(&dev->v4l2_dev, grpid, o, f, ##args)
391
392extern struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw);
393
386extern struct list_head cx23885_devlist; 394extern struct list_head cx23885_devlist;
387 395
388#define SRAM_CH01 0 /* Video A */ 396#define SRAM_CH01 0 /* Video A */
diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c
new file mode 100644
index 000000000000..12df0e3a2354
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23888-ir.c
@@ -0,0 +1,233 @@
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 <media/v4l2-device.h>
25#include <media/v4l2-chip-ident.h>
26
27#include "cx23885.h"
28
29#define CX23888_IR_REG_BASE 0x170000
30/*
31 * These CX23888 register offsets have a straightforward one to one mapping
32 * to the CX23885 register offsets of 0x200 through 0x218
33 */
34#define CX23888_IR_CNTRL_REG 0x170000
35#define CX23888_IR_TXCLK_REG 0x170004
36#define CX23888_IR_RXCLK_REG 0x170008
37#define CX23888_IR_CDUTY_REG 0x17000C
38#define CX23888_IR_STATS_REG 0x170010
39#define CX23888_IR_IRQEN_REG 0x170014
40#define CX23888_IR_FILTR_REG 0x170018
41/* This register doesn't follow the pattern; it's 0x23C on a CX23885 */
42#define CX23888_IR_FIFO_REG 0x170040
43
44/* CX23888 unique registers */
45#define CX23888_IR_SEEDP_REG 0x17001C
46#define CX23888_IR_TIMOL_REG 0x170020
47#define CX23888_IR_WAKE0_REG 0x170024
48#define CX23888_IR_WAKE1_REG 0x170028
49#define CX23888_IR_WAKE2_REG 0x17002C
50#define CX23888_IR_MASK0_REG 0x170030
51#define CX23888_IR_MASK1_REG 0x170034
52#define CX23888_IR_MAKS2_REG 0x170038
53#define CX23888_IR_DPIPG_REG 0x17003C
54#define CX23888_IR_LEARN_REG 0x170044
55
56
57struct cx23888_ir_state {
58 struct v4l2_subdev sd;
59 struct cx23885_dev *dev;
60 u32 id;
61 u32 rev;
62};
63
64static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd)
65{
66 return v4l2_get_subdevdata(sd);
67}
68
69static int cx23888_ir_write(struct cx23885_dev *dev, u32 addr, u8 value)
70{
71 u32 reg = (addr & ~3);
72 int shift = (addr & 3) * 8;
73 u32 x = cx_read(reg);
74
75 x = (x & ~(0xff << shift)) | ((u32)value << shift);
76 cx_write(reg, x);
77 return 0;
78}
79
80static
81inline int cx23888_ir_write4(struct cx23885_dev *dev, u32 addr, u32 value)
82{
83 cx_write(addr, value);
84 return 0;
85}
86
87static u8 cx23888_ir_read(struct cx23885_dev *dev, u32 addr)
88{
89 u32 x = cx_read((addr & ~3));
90 int shift = (addr & 3) * 8;
91
92 return (x >> shift) & 0xff;
93}
94
95static inline u32 cx23888_ir_read4(struct cx23885_dev *dev, u32 addr)
96{
97 return cx_read(addr);
98}
99
100static int cx23888_ir_and_or(struct cx23885_dev *dev, u32 addr,
101 unsigned and_mask, u8 or_value)
102{
103 return cx23888_ir_write(dev, addr,
104 (cx23888_ir_read(dev, addr) & and_mask) |
105 or_value);
106}
107
108static inline int cx23888_ir_and_or4(struct cx23885_dev *dev, u32 addr,
109 u32 and_mask, u32 or_value)
110{
111 cx_andor(addr, and_mask, or_value);
112 return 0;
113}
114
115static int cx23888_ir_log_status(struct v4l2_subdev *sd)
116{
117 struct cx23888_ir_state *state = to_state(sd);
118 struct cx23885_dev *dev = state->dev;
119 u8 cntrl = cx23888_ir_read(dev, CX23888_IR_CNTRL_REG+1);
120 v4l2_info(sd, "receiver %sabled\n", cntrl & 0x1 ? "en" : "dis");
121 v4l2_info(sd, "transmitter %sabled\n", cntrl & 0x2 ? "en" : "dis");
122 return 0;
123}
124
125static inline int cx23888_ir_dbg_match(const struct v4l2_dbg_match *match)
126{
127 return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 2;
128}
129
130static int cx23888_ir_g_chip_ident(struct v4l2_subdev *sd,
131 struct v4l2_dbg_chip_ident *chip)
132{
133 struct cx23888_ir_state *state = to_state(sd);
134
135 if (cx23888_ir_dbg_match(&chip->match)) {
136 chip->ident = state->id;
137 chip->revision = state->rev;
138 }
139 return 0;
140}
141
142#ifdef CONFIG_VIDEO_ADV_DEBUG
143static int cx23888_ir_g_register(struct v4l2_subdev *sd,
144 struct v4l2_dbg_register *reg)
145{
146 struct cx23888_ir_state *state = to_state(sd);
147 u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg;
148
149 if (!cx23888_ir_dbg_match(&reg->match))
150 return -EINVAL;
151 if ((addr & 0x3) != 0)
152 return -EINVAL;
153 if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG)
154 return -EINVAL;
155 if (!capable(CAP_SYS_ADMIN))
156 return -EPERM;
157 reg->size = 4;
158 reg->val = cx23888_ir_read4(state->dev, addr);
159 return 0;
160}
161
162static int cx23888_ir_s_register(struct v4l2_subdev *sd,
163 struct v4l2_dbg_register *reg)
164{
165 struct cx23888_ir_state *state = to_state(sd);
166 u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg;
167
168 if (!cx23888_ir_dbg_match(&reg->match))
169 return -EINVAL;
170 if ((addr & 0x3) != 0)
171 return -EINVAL;
172 if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG)
173 return -EINVAL;
174 if (!capable(CAP_SYS_ADMIN))
175 return -EPERM;
176 cx23888_ir_write4(state->dev, addr, reg->val);
177 return 0;
178}
179#endif
180
181static const struct v4l2_subdev_core_ops cx23888_ir_core_ops = {
182 .g_chip_ident = cx23888_ir_g_chip_ident,
183 .log_status = cx23888_ir_log_status,
184#ifdef CONFIG_VIDEO_ADV_DEBUG
185 .g_register = cx23888_ir_g_register,
186 .s_register = cx23888_ir_s_register,
187#endif
188};
189
190static const struct v4l2_subdev_ops cx23888_ir_controller_ops = {
191 .core = &cx23888_ir_core_ops,
192};
193
194int cx23888_ir_probe(struct cx23885_dev *dev)
195{
196 struct cx23888_ir_state *state;
197 struct v4l2_subdev *sd;
198
199 state = kzalloc(sizeof(struct cx23888_ir_state), GFP_KERNEL);
200 if (state == NULL)
201 return -ENOMEM;
202
203 state->dev = dev;
204 state->id = V4L2_IDENT_CX23888_IR;
205 state->rev = 0;
206 sd = &state->sd;
207
208 v4l2_subdev_init(sd, &cx23888_ir_controller_ops);
209 v4l2_set_subdevdata(sd, state);
210 /* FIXME - fix the formatting of dev->v4l2_dev.name and use it */
211 snprintf(sd->name, sizeof(sd->name), "%s/888-ir", dev->name);
212 sd->grp_id = CX23885_HW_888_IR;
213 return v4l2_device_register_subdev(&dev->v4l2_dev, sd);
214}
215
216int cx23888_ir_remove(struct cx23885_dev *dev)
217{
218 struct v4l2_subdev *sd;
219 struct cx23888_ir_state *state;
220
221 sd = cx23885_find_hw(dev, CX23885_HW_888_IR);
222 if (sd == NULL)
223 return -ENODEV;
224
225 /* Disable receiver and transmitter */
226 cx23888_ir_and_or(dev, CX23888_IR_CNTRL_REG+1, 0xfc, 0);
227
228 state = to_state(sd);
229 v4l2_device_unregister_subdev(sd);
230 kfree(state);
231 /* Nothing more to free() as state held the actual v4l2_subdev object */
232 return 0;
233}
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