Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[sfrench/cifs-2.6.git] / drivers / media / video / cx23885 / cx23885-ioctl.c
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@md.metrocast.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
27 int 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
104 static 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
115 static 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
134 int 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
158 static 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
169 static 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
185 int 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