aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-10 18:09:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-10 18:09:54 -0400
commit7ae0dea900b027cd90e8a3e14deca9a19e17638b (patch)
tree428cbe411bba90f6580ae21338276c949e91f23a /drivers/media
parent6c74700fdb8e3bc34c31790384a8ec16c4fefd97 (diff)
parent560afa7d85bdfb294506afd3032c315e6827824f (diff)
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (94 commits) V4L/DVB: tvp7002: fix write to H-PLL Feedback Divider LSB register V4L/DVB: dvb: siano: free spinlock before schedule() V4L/DVB: media: video: pvrusb2: remove custom hex_to_bin() V4L/DVB: drivers: usbvideo: remove custom implementation of hex_to_bin() V4L/DVB: Report supported QAM modes on bt8xx V4L/DVB: media: ir-keytable: null dereference in debug code V4L/DVB: ivtv: convert to the new control framework V4L/DVB: ivtv: convert gpio subdev to new control framework V4L/DVB: wm8739: convert to the new control framework V4L/DVB: cs53l32a: convert to new control framework V4L/DVB: wm8775: convert to the new control framework V4L/DVB: cx2341x: convert to the control framework V4L/DVB: cx25840: convert to the new control framework V4L/DVB: cx25840/ivtv: replace ugly priv control with s_config V4L/DVB: saa717x: convert to the new control framework V4L/DVB: msp3400: convert to the new control framework V4L/DVB: saa7115: convert to the new control framework V4L/DVB: v4l2: hook up the new control framework into the core framework V4L/DVB: Documentation: add v4l2-controls.txt documenting the new controls API V4L/DVB: v4l2-ctrls: Whitespace cleanups ...
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/IR/Kconfig36
-rw-r--r--drivers/media/IR/Makefile2
-rw-r--r--drivers/media/IR/ene_ir.c1023
-rw-r--r--drivers/media/IR/ene_ir.h235
-rw-r--r--drivers/media/IR/imon.c20
-rw-r--r--drivers/media/IR/ir-core-priv.h13
-rw-r--r--drivers/media/IR/ir-jvc-decoder.c14
-rw-r--r--drivers/media/IR/ir-keytable.c13
-rw-r--r--drivers/media/IR/ir-lirc-codec.c124
-rw-r--r--drivers/media/IR/ir-nec-decoder.c25
-rw-r--r--drivers/media/IR/ir-raw-event.c159
-rw-r--r--drivers/media/IR/ir-sysfs.c2
-rw-r--r--drivers/media/IR/keymaps/Makefile2
-rw-r--r--drivers/media/IR/keymaps/rc-empty.c44
-rw-r--r--drivers/media/IR/keymaps/rc-rc5-streamzap.c81
-rw-r--r--drivers/media/IR/keymaps/rc-rc6-mce.c2
-rw-r--r--drivers/media/IR/mceusb.c21
-rw-r--r--drivers/media/IR/rc-map.c23
-rw-r--r--drivers/media/IR/streamzap.c741
-rw-r--r--drivers/media/common/tuners/Kconfig2
-rw-r--r--drivers/media/dvb/bt8xx/dst.c10
-rw-r--r--drivers/media/dvb/frontends/Kconfig2
-rw-r--r--drivers/media/dvb/siano/smscoreapi.c6
-rw-r--r--drivers/media/video/Kconfig16
-rw-r--r--drivers/media/video/Makefile3
-rw-r--r--drivers/media/video/cs53l32a.c107
-rw-r--r--drivers/media/video/cx2341x.c747
-rw-r--r--drivers/media/video/cx23885/Kconfig2
-rw-r--r--drivers/media/video/cx23885/Makefile5
-rw-r--r--drivers/media/video/cx23885/cx23885-av.c35
-rw-r--r--drivers/media/video/cx23885/cx23885-av.h27
-rw-r--r--drivers/media/video/cx23885/cx23885-cards.c114
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c124
-rw-r--r--drivers/media/video/cx23885/cx23885-i2c.c27
-rw-r--r--drivers/media/video/cx23885/cx23885-input.c72
-rw-r--r--drivers/media/video/cx23885/cx23885-ir.c24
-rw-r--r--drivers/media/video/cx23885/cx23885-reg.h1
-rw-r--r--drivers/media/video/cx23885/cx23885-vbi.c2
-rw-r--r--drivers/media/video/cx23885/cx23885-video.c23
-rw-r--r--drivers/media/video/cx23885/cx23885.h9
-rw-r--r--drivers/media/video/cx23885/cx23888-ir.c142
-rw-r--r--drivers/media/video/cx25840/Makefile2
-rw-r--r--drivers/media/video/cx25840/cx25840-audio.c144
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c540
-rw-r--r--drivers/media/video/cx25840/cx25840-core.h52
-rw-r--r--drivers/media/video/cx25840/cx25840-ir.c1279
-rw-r--r--drivers/media/video/gspca/gspca.c21
-rw-r--r--drivers/media/video/gspca/sonixj.c10
-rw-r--r--drivers/media/video/gspca/sq930x.c347
-rw-r--r--drivers/media/video/gspca/t613.c4
-rw-r--r--drivers/media/video/gspca/vc032x.c360
-rw-r--r--drivers/media/video/gspca/zc3xx.c1715
-rw-r--r--drivers/media/video/ivtv/ivtv-controls.c276
-rw-r--r--drivers/media/video/ivtv/ivtv-controls.h6
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c26
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h4
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c23
-rw-r--r--drivers/media/video/ivtv/ivtv-firmware.c6
-rw-r--r--drivers/media/video/ivtv/ivtv-gpio.c77
-rw-r--r--drivers/media/video/ivtv/ivtv-i2c.c7
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c31
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c24
-rw-r--r--drivers/media/video/msp3400-driver.c248
-rw-r--r--drivers/media/video/msp3400-driver.h18
-rw-r--r--drivers/media/video/msp3400-kthreads.c16
-rw-r--r--drivers/media/video/mt9m111.c40
-rw-r--r--drivers/media/video/mx2_camera.c4
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-debugifc.c14
-rw-r--r--drivers/media/video/s5p-fimc/Makefile3
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.c1586
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.h471
-rw-r--r--drivers/media/video/s5p-fimc/fimc-reg.c527
-rw-r--r--drivers/media/video/s5p-fimc/regs-fimc.h293
-rw-r--r--drivers/media/video/saa7115.c183
-rw-r--r--drivers/media/video/saa717x.c323
-rw-r--r--drivers/media/video/soc_camera.c9
-rw-r--r--drivers/media/video/tvp7002.c10
-rw-r--r--drivers/media/video/usbvideo/usbvideo.c12
-rw-r--r--drivers/media/video/uvc/uvc_driver.c9
-rw-r--r--drivers/media/video/uvc/uvc_queue.c13
-rw-r--r--drivers/media/video/uvc/uvc_video.c19
-rw-r--r--drivers/media/video/uvc/uvcvideo.h5
-rw-r--r--drivers/media/video/v4l2-common.c479
-rw-r--r--drivers/media/video/v4l2-ctrls.c1851
-rw-r--r--drivers/media/video/v4l2-dev.c8
-rw-r--r--drivers/media/video/v4l2-device.c7
-rw-r--r--drivers/media/video/v4l2-ioctl.c46
-rw-r--r--drivers/media/video/wm8739.c179
-rw-r--r--drivers/media/video/wm8775.c79
89 files changed, 11955 insertions, 3531 deletions
diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig
index 999a8250b3c..30e04915a25 100644
--- a/drivers/media/IR/Kconfig
+++ b/drivers/media/IR/Kconfig
@@ -1,8 +1,10 @@
1config IR_CORE 1menuconfig IR_CORE
2 tristate 2 tristate "Infrared remote controller adapters"
3 depends on INPUT 3 depends on INPUT
4 default INPUT 4 default INPUT
5 5
6if IR_CORE
7
6config VIDEO_IR 8config VIDEO_IR
7 tristate 9 tristate
8 depends on IR_CORE 10 depends on IR_CORE
@@ -16,7 +18,7 @@ config LIRC
16 Enable this option to build the Linux Infrared Remote 18 Enable this option to build the Linux Infrared Remote
17 Control (LIRC) core device interface driver. The LIRC 19 Control (LIRC) core device interface driver. The LIRC
18 interface passes raw IR to and from userspace, where the 20 interface passes raw IR to and from userspace, where the
19 LIRC daemon handles protocol decoding for IR reception ann 21 LIRC daemon handles protocol decoding for IR reception and
20 encoding for IR transmitting (aka "blasting"). 22 encoding for IR transmitting (aka "blasting").
21 23
22source "drivers/media/IR/keymaps/Kconfig" 24source "drivers/media/IR/keymaps/Kconfig"
@@ -103,3 +105,31 @@ config IR_MCEUSB
103 105
104 To compile this driver as a module, choose M here: the 106 To compile this driver as a module, choose M here: the
105 module will be called mceusb. 107 module will be called mceusb.
108
109config IR_ENE
110 tristate "ENE eHome Receiver/Transciever (pnp id: ENE0100/ENE02xxx)"
111 depends on PNP
112 depends on IR_CORE
113 ---help---
114 Say Y here to enable support for integrated infrared receiver
115 /transciever made by ENE.
116
117 You can see if you have it by looking at lspnp output.
118 Output should include ENE0100 ENE0200 or something similiar.
119
120 To compile this driver as a module, choose M here: the
121 module will be called ene_ir.
122
123config IR_STREAMZAP
124 tristate "Streamzap PC Remote IR Receiver"
125 depends on USB_ARCH_HAS_HCD
126 depends on IR_CORE
127 select USB
128 ---help---
129 Say Y here if you want to use a Streamzap PC Remote
130 Infrared Receiver.
131
132 To compile this driver as a module, choose M here: the
133 module will be called streamzap.
134
135endif #IR_CORE
diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile
index 2ae4f3abfdb..53676838fe9 100644
--- a/drivers/media/IR/Makefile
+++ b/drivers/media/IR/Makefile
@@ -16,3 +16,5 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
16# stand-alone IR receivers/transmitters 16# stand-alone IR receivers/transmitters
17obj-$(CONFIG_IR_IMON) += imon.o 17obj-$(CONFIG_IR_IMON) += imon.o
18obj-$(CONFIG_IR_MCEUSB) += mceusb.o 18obj-$(CONFIG_IR_MCEUSB) += mceusb.o
19obj-$(CONFIG_IR_ENE) += ene_ir.o
20obj-$(CONFIG_IR_STREAMZAP) += streamzap.o
diff --git a/drivers/media/IR/ene_ir.c b/drivers/media/IR/ene_ir.c
new file mode 100644
index 00000000000..5447750f5e3
--- /dev/null
+++ b/drivers/media/IR/ene_ir.c
@@ -0,0 +1,1023 @@
1/*
2 * driver for ENE KB3926 B/C/D CIR (pnp id: ENE0XXX)
3 *
4 * Copyright (C) 2010 Maxim Levitsky <maximlevitsky@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 * USA
20 */
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/pnp.h>
25#include <linux/io.h>
26#include <linux/interrupt.h>
27#include <linux/sched.h>
28#include <linux/slab.h>
29#include <linux/input.h>
30#include <media/ir-core.h>
31#include <media/ir-common.h>
32#include "ene_ir.h"
33
34
35static int sample_period = -1;
36static int enable_idle = 1;
37static int input = 1;
38static int debug;
39static int txsim;
40
41static int ene_irq_status(struct ene_device *dev);
42
43/* read a hardware register */
44static u8 ene_hw_read_reg(struct ene_device *dev, u16 reg)
45{
46 u8 retval;
47 outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
48 outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
49 retval = inb(dev->hw_io + ENE_IO);
50
51 ene_dbg_verbose("reg %04x == %02x", reg, retval);
52 return retval;
53}
54
55/* write a hardware register */
56static void ene_hw_write_reg(struct ene_device *dev, u16 reg, u8 value)
57{
58 outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
59 outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
60 outb(value, dev->hw_io + ENE_IO);
61
62 ene_dbg_verbose("reg %04x <- %02x", reg, value);
63}
64
65/* change specific bits in hardware register */
66static void ene_hw_write_reg_mask(struct ene_device *dev,
67 u16 reg, u8 value, u8 mask)
68{
69 u8 regvalue;
70
71 outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
72 outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
73
74 regvalue = inb(dev->hw_io + ENE_IO) & ~mask;
75 regvalue |= (value & mask);
76 outb(regvalue, dev->hw_io + ENE_IO);
77
78 ene_dbg_verbose("reg %04x <- %02x (mask=%02x)", reg, value, mask);
79}
80
81/* detect hardware features */
82static int ene_hw_detect(struct ene_device *dev)
83{
84 u8 chip_major, chip_minor;
85 u8 hw_revision, old_ver;
86 u8 tmp;
87 u8 fw_capabilities;
88 int pll_freq;
89
90 tmp = ene_hw_read_reg(dev, ENE_HW_UNK);
91 ene_hw_write_reg(dev, ENE_HW_UNK, tmp & ~ENE_HW_UNK_CLR);
92
93 chip_major = ene_hw_read_reg(dev, ENE_HW_VER_MAJOR);
94 chip_minor = ene_hw_read_reg(dev, ENE_HW_VER_MINOR);
95
96 ene_hw_write_reg(dev, ENE_HW_UNK, tmp);
97 hw_revision = ene_hw_read_reg(dev, ENE_HW_VERSION);
98 old_ver = ene_hw_read_reg(dev, ENE_HW_VER_OLD);
99
100 pll_freq = (ene_hw_read_reg(dev, ENE_PLLFRH) << 4) +
101 (ene_hw_read_reg(dev, ENE_PLLFRL) >> 4);
102
103 if (pll_freq != 1000)
104 dev->rx_period_adjust = 4;
105 else
106 dev->rx_period_adjust = 2;
107
108
109 ene_printk(KERN_NOTICE, "PLL freq = %d\n", pll_freq);
110
111 if (hw_revision == 0xFF) {
112
113 ene_printk(KERN_WARNING, "device seems to be disabled\n");
114 ene_printk(KERN_WARNING,
115 "send a mail to lirc-list@lists.sourceforge.net\n");
116 ene_printk(KERN_WARNING, "please attach output of acpidump\n");
117 return -ENODEV;
118 }
119
120 if (chip_major == 0x33) {
121 ene_printk(KERN_WARNING, "chips 0x33xx aren't supported\n");
122 return -ENODEV;
123 }
124
125 if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) {
126 dev->hw_revision = ENE_HW_C;
127 } else if (old_ver == 0x24 && hw_revision == 0xC0) {
128 dev->hw_revision = ENE_HW_B;
129 ene_printk(KERN_NOTICE, "KB3926B detected\n");
130 } else {
131 dev->hw_revision = ENE_HW_D;
132 ene_printk(KERN_WARNING,
133 "unknown ENE chip detected, assuming KB3926D\n");
134 ene_printk(KERN_WARNING,
135 "driver support might be not complete");
136
137 }
138
139 ene_printk(KERN_DEBUG,
140 "chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x\n",
141 chip_major, chip_minor, old_ver, hw_revision);
142
143 /* detect features hardware supports */
144 if (dev->hw_revision < ENE_HW_C)
145 return 0;
146
147 fw_capabilities = ene_hw_read_reg(dev, ENE_FW2);
148 ene_dbg("Firmware capabilities: %02x", fw_capabilities);
149
150 dev->hw_gpio40_learning = fw_capabilities & ENE_FW2_GP40_AS_LEARN;
151 dev->hw_learning_and_tx_capable = fw_capabilities & ENE_FW2_LEARNING;
152
153 dev->hw_fan_as_normal_input = dev->hw_learning_and_tx_capable &&
154 (fw_capabilities & ENE_FW2_FAN_AS_NRML_IN);
155
156 ene_printk(KERN_NOTICE, "hardware features:\n");
157 ene_printk(KERN_NOTICE,
158 "learning and transmit %s, gpio40_learn %s, fan_in %s\n",
159 dev->hw_learning_and_tx_capable ? "on" : "off",
160 dev->hw_gpio40_learning ? "on" : "off",
161 dev->hw_fan_as_normal_input ? "on" : "off");
162
163 if (dev->hw_learning_and_tx_capable) {
164 ene_printk(KERN_WARNING,
165 "Device supports transmitting, but that support is\n");
166 ene_printk(KERN_WARNING,
167 "lightly tested. Please test it and mail\n");
168 ene_printk(KERN_WARNING,
169 "lirc-list@lists.sourceforge.net\n");
170 }
171 return 0;
172}
173
174/* this enables/disables IR input via gpio40*/
175static void ene_enable_gpio40_receive(struct ene_device *dev, int enable)
176{
177 ene_hw_write_reg_mask(dev, ENE_CIR_CONF2, enable ?
178 0 : ENE_CIR_CONF2_GPIO40DIS,
179 ENE_CIR_CONF2_GPIO40DIS);
180}
181
182/* this enables/disables IR via standard input */
183static void ene_enable_normal_receive(struct ene_device *dev, int enable)
184{
185 ene_hw_write_reg(dev, ENE_CIR_CONF1, enable ? ENE_CIR_CONF1_RX_ON : 0);
186}
187
188/* this enables/disables IR input via unused fan tachtometer input */
189static void ene_enable_fan_receive(struct ene_device *dev, int enable)
190{
191 if (!enable)
192 ene_hw_write_reg(dev, ENE_FAN_AS_IN1, 0);
193 else {
194 ene_hw_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN);
195 ene_hw_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN);
196 }
197 dev->rx_fan_input_inuse = enable;
198}
199
200
201/* Sense current received carrier */
202static int ene_rx_sense_carrier(struct ene_device *dev)
203{
204 int period = ene_hw_read_reg(dev, ENE_RX_CARRIER);
205 int carrier;
206 ene_dbg("RX: hardware carrier period = %02x", period);
207
208 if (!(period & ENE_RX_CARRIER_VALID))
209 return 0;
210
211 period &= ~ENE_RX_CARRIER_VALID;
212
213 if (!period)
214 return 0;
215
216 carrier = 2000000 / period;
217 ene_dbg("RX: sensed carrier = %d Hz", carrier);
218 return carrier;
219}
220
221/* determine which input to use*/
222static void ene_rx_set_inputs(struct ene_device *dev)
223{
224 int learning_mode = dev->learning_enabled;
225
226 ene_dbg("RX: setup receiver, learning mode = %d", learning_mode);
227
228 ene_enable_normal_receive(dev, 1);
229
230 /* old hardware doesn't support learning mode for sure */
231 if (dev->hw_revision <= ENE_HW_B)
232 return;
233
234 /* receiver not learning capable, still set gpio40 correctly */
235 if (!dev->hw_learning_and_tx_capable) {
236 ene_enable_gpio40_receive(dev, !dev->hw_gpio40_learning);
237 return;
238 }
239
240 /* enable learning mode */
241 if (learning_mode) {
242 ene_enable_gpio40_receive(dev, dev->hw_gpio40_learning);
243
244 /* fan input is not used for learning */
245 if (dev->hw_fan_as_normal_input)
246 ene_enable_fan_receive(dev, 0);
247
248 /* disable learning mode */
249 } else {
250 if (dev->hw_fan_as_normal_input) {
251 ene_enable_fan_receive(dev, 1);
252 ene_enable_normal_receive(dev, 0);
253 } else
254 ene_enable_gpio40_receive(dev,
255 !dev->hw_gpio40_learning);
256 }
257
258 /* set few additional settings for this mode */
259 ene_hw_write_reg_mask(dev, ENE_CIR_CONF1, learning_mode ?
260 ENE_CIR_CONF1_LEARN1 : 0, ENE_CIR_CONF1_LEARN1);
261
262 ene_hw_write_reg_mask(dev, ENE_CIR_CONF2, learning_mode ?
263 ENE_CIR_CONF2_LEARN2 : 0, ENE_CIR_CONF2_LEARN2);
264
265 if (dev->rx_fan_input_inuse) {
266 dev->props->rx_resolution = ENE_SAMPLE_PERIOD_FAN * 1000;
267
268 dev->props->timeout =
269 ENE_FAN_VALUE_MASK * ENE_SAMPLE_PERIOD_FAN * 1000;
270 } else {
271 dev->props->rx_resolution = sample_period * 1000;
272 dev->props->timeout = ENE_MAXGAP * 1000;
273 }
274}
275
276/* Enable the device for receive */
277static void ene_rx_enable(struct ene_device *dev)
278{
279 u8 reg_value;
280
281 if (dev->hw_revision < ENE_HW_C) {
282 ene_hw_write_reg(dev, ENEB_IRQ, dev->irq << 1);
283 ene_hw_write_reg(dev, ENEB_IRQ_UNK1, 0x01);
284 } else {
285 reg_value = ene_hw_read_reg(dev, ENEC_IRQ) & 0xF0;
286 reg_value |= ENEC_IRQ_UNK_EN;
287 reg_value &= ~ENEC_IRQ_STATUS;
288 reg_value |= (dev->irq & ENEC_IRQ_MASK);
289 ene_hw_write_reg(dev, ENEC_IRQ, reg_value);
290 ene_hw_write_reg(dev, ENE_TX_UNK1, 0x63);
291 }
292
293 ene_hw_write_reg(dev, ENE_CIR_CONF2, 0x00);
294 ene_rx_set_inputs(dev);
295
296 /* set sampling period */
297 ene_hw_write_reg(dev, ENE_CIR_SAMPLE_PERIOD, sample_period);
298
299 /* ack any pending irqs - just in case */
300 ene_irq_status(dev);
301
302 /* enable firmware bits */
303 ene_hw_write_reg_mask(dev, ENE_FW1,
304 ENE_FW1_ENABLE | ENE_FW1_IRQ,
305 ENE_FW1_ENABLE | ENE_FW1_IRQ);
306
307 /* enter idle mode */
308 ir_raw_event_set_idle(dev->idev, 1);
309 ir_raw_event_reset(dev->idev);
310
311}
312
313/* Disable the device receiver */
314static void ene_rx_disable(struct ene_device *dev)
315{
316 /* disable inputs */
317 ene_enable_normal_receive(dev, 0);
318
319 if (dev->hw_fan_as_normal_input)
320 ene_enable_fan_receive(dev, 0);
321
322 /* disable hardware IRQ and firmware flag */
323 ene_hw_write_reg_mask(dev, ENE_FW1, 0, ENE_FW1_ENABLE | ENE_FW1_IRQ);
324
325 ir_raw_event_set_idle(dev->idev, 1);
326 ir_raw_event_reset(dev->idev);
327}
328
329
330/* prepare transmission */
331static void ene_tx_prepare(struct ene_device *dev)
332{
333 u8 conf1;
334
335 conf1 = ene_hw_read_reg(dev, ENE_CIR_CONF1);
336 dev->saved_conf1 = conf1;
337
338 if (dev->hw_revision == ENE_HW_C)
339 conf1 &= ~ENE_CIR_CONF1_TX_CLEAR;
340
341 /* Enable TX engine */
342 conf1 |= ENE_CIR_CONF1_TX_ON;
343
344 /* Set carrier */
345 if (dev->tx_period) {
346
347 /* NOTE: duty cycle handling is just a guess, it might
348 not be aviable. Default values were tested */
349 int tx_period_in500ns = dev->tx_period * 2;
350
351 int tx_pulse_width_in_500ns =
352 tx_period_in500ns / (100 / dev->tx_duty_cycle);
353
354 if (!tx_pulse_width_in_500ns)
355 tx_pulse_width_in_500ns = 1;
356
357 ene_dbg("TX: pulse distance = %d * 500 ns", tx_period_in500ns);
358 ene_dbg("TX: pulse width = %d * 500 ns",
359 tx_pulse_width_in_500ns);
360
361 ene_hw_write_reg(dev, ENE_TX_PERIOD, ENE_TX_PERIOD_UNKBIT |
362 tx_period_in500ns);
363
364 ene_hw_write_reg(dev, ENE_TX_PERIOD_PULSE,
365 tx_pulse_width_in_500ns);
366
367 conf1 |= ENE_CIR_CONF1_TX_CARR;
368 } else
369 conf1 &= ~ENE_CIR_CONF1_TX_CARR;
370
371 ene_hw_write_reg(dev, ENE_CIR_CONF1, conf1);
372
373}
374
375/* end transmission */
376static void ene_tx_complete(struct ene_device *dev)
377{
378 ene_hw_write_reg(dev, ENE_CIR_CONF1, dev->saved_conf1);
379 dev->tx_buffer = NULL;
380}
381
382/* set transmit mask */
383static void ene_tx_hw_set_transmiter_mask(struct ene_device *dev)
384{
385 u8 txport1 = ene_hw_read_reg(dev, ENE_TX_PORT1) & ~ENE_TX_PORT1_EN;
386 u8 txport2 = ene_hw_read_reg(dev, ENE_TX_PORT2) & ~ENE_TX_PORT2_EN;
387
388 if (dev->transmitter_mask & 0x01)
389 txport1 |= ENE_TX_PORT1_EN;
390
391 if (dev->transmitter_mask & 0x02)
392 txport2 |= ENE_TX_PORT2_EN;
393
394 ene_hw_write_reg(dev, ENE_TX_PORT1, txport1);
395 ene_hw_write_reg(dev, ENE_TX_PORT2, txport2);
396}
397
398/* TX one sample - must be called with dev->hw_lock*/
399static void ene_tx_sample(struct ene_device *dev)
400{
401 u8 raw_tx;
402 u32 sample;
403
404 if (!dev->tx_buffer) {
405 ene_dbg("TX: attempt to transmit NULL buffer");
406 return;
407 }
408
409 /* Grab next TX sample */
410 if (!dev->tx_sample) {
411again:
412 if (dev->tx_pos == dev->tx_len + 1) {
413 if (!dev->tx_done) {
414 ene_dbg("TX: no more data to send");
415 dev->tx_done = 1;
416 goto exit;
417 } else {
418 ene_dbg("TX: last sample sent by hardware");
419 ene_tx_complete(dev);
420 complete(&dev->tx_complete);
421 return;
422 }
423 }
424
425 sample = dev->tx_buffer[dev->tx_pos++];
426 dev->tx_sample_pulse = !dev->tx_sample_pulse;
427
428 ene_dbg("TX: sample %8d (%s)", sample, dev->tx_sample_pulse ?
429 "pulse" : "space");
430
431 dev->tx_sample = DIV_ROUND_CLOSEST(sample, ENE_TX_SMPL_PERIOD);
432
433 /* guard against too short samples */
434 if (!dev->tx_sample)
435 goto again;
436 }
437
438 raw_tx = min(dev->tx_sample , (unsigned int)ENE_TX_SMLP_MASK);
439 dev->tx_sample -= raw_tx;
440
441 if (dev->tx_sample_pulse)
442 raw_tx |= ENE_TX_PULSE_MASK;
443
444 ene_hw_write_reg(dev, ENE_TX_INPUT1 + dev->tx_reg, raw_tx);
445 dev->tx_reg = !dev->tx_reg;
446exit:
447 /* simulate TX done interrupt */
448 if (txsim)
449 mod_timer(&dev->tx_sim_timer, jiffies + HZ / 500);
450}
451
452/* timer to simulate tx done interrupt */
453static void ene_tx_irqsim(unsigned long data)
454{
455 struct ene_device *dev = (struct ene_device *)data;
456 unsigned long flags;
457
458 spin_lock_irqsave(&dev->hw_lock, flags);
459 ene_tx_sample(dev);
460 spin_unlock_irqrestore(&dev->hw_lock, flags);
461}
462
463
464/* read irq status and ack it */
465static int ene_irq_status(struct ene_device *dev)
466{
467 u8 irq_status;
468 u8 fw_flags1, fw_flags2;
469 int cur_rx_pointer;
470 int retval = 0;
471
472 fw_flags2 = ene_hw_read_reg(dev, ENE_FW2);
473 cur_rx_pointer = !!(fw_flags2 & ENE_FW2_BUF_HIGH);
474
475 if (dev->hw_revision < ENE_HW_C) {
476 irq_status = ene_hw_read_reg(dev, ENEB_IRQ_STATUS);
477
478 if (!(irq_status & ENEB_IRQ_STATUS_IR))
479 return 0;
480
481 ene_hw_write_reg(dev, ENEB_IRQ_STATUS,
482 irq_status & ~ENEB_IRQ_STATUS_IR);
483 dev->rx_pointer = cur_rx_pointer;
484 return ENE_IRQ_RX;
485 }
486
487 irq_status = ene_hw_read_reg(dev, ENEC_IRQ);
488
489 if (!(irq_status & ENEC_IRQ_STATUS))
490 return 0;
491
492 /* original driver does that twice - a workaround ? */
493 ene_hw_write_reg(dev, ENEC_IRQ, irq_status & ~ENEC_IRQ_STATUS);
494 ene_hw_write_reg(dev, ENEC_IRQ, irq_status & ~ENEC_IRQ_STATUS);
495
496 /* clear unknown flag in F8F9 */
497 if (fw_flags2 & ENE_FW2_IRQ_CLR)
498 ene_hw_write_reg(dev, ENE_FW2, fw_flags2 & ~ENE_FW2_IRQ_CLR);
499
500 /* check if this is a TX interrupt */
501 fw_flags1 = ene_hw_read_reg(dev, ENE_FW1);
502 if (fw_flags1 & ENE_FW1_TXIRQ) {
503 ene_hw_write_reg(dev, ENE_FW1, fw_flags1 & ~ENE_FW1_TXIRQ);
504 retval |= ENE_IRQ_TX;
505 }
506
507 /* Check if this is RX interrupt */
508 if (dev->rx_pointer != cur_rx_pointer) {
509 retval |= ENE_IRQ_RX;
510 dev->rx_pointer = cur_rx_pointer;
511
512 } else if (!(retval & ENE_IRQ_TX)) {
513 ene_dbg("RX: interrupt without change in RX pointer(%d)",
514 dev->rx_pointer);
515 retval |= ENE_IRQ_RX;
516 }
517
518 if ((retval & ENE_IRQ_RX) && (retval & ENE_IRQ_TX))
519 ene_dbg("both RX and TX interrupt at same time");
520
521 return retval;
522}
523
524/* interrupt handler */
525static irqreturn_t ene_isr(int irq, void *data)
526{
527 u16 hw_value;
528 int i, hw_sample;
529 int pulse;
530 int irq_status;
531 unsigned long flags;
532 int carrier = 0;
533 irqreturn_t retval = IRQ_NONE;
534 struct ene_device *dev = (struct ene_device *)data;
535 struct ir_raw_event ev;
536
537
538 spin_lock_irqsave(&dev->hw_lock, flags);
539 irq_status = ene_irq_status(dev);
540
541 if (!irq_status)
542 goto unlock;
543
544 retval = IRQ_HANDLED;
545
546 if (irq_status & ENE_IRQ_TX) {
547
548 if (!dev->hw_learning_and_tx_capable) {
549 ene_dbg("TX interrupt on unsupported device!");
550 goto unlock;
551 }
552 ene_tx_sample(dev);
553 }
554
555 if (!(irq_status & ENE_IRQ_RX))
556 goto unlock;
557
558
559 if (dev->carrier_detect_enabled || debug)
560 carrier = ene_rx_sense_carrier(dev);
561#if 0
562 /* TODO */
563 if (dev->carrier_detect_enabled && carrier)
564 ir_raw_event_report_frequency(dev->idev, carrier);
565#endif
566
567 for (i = 0; i < ENE_SAMPLES_SIZE; i++) {
568 hw_value = ene_hw_read_reg(dev,
569 ENE_SAMPLE_BUFFER + dev->rx_pointer * 4 + i);
570
571 if (dev->rx_fan_input_inuse) {
572 /* read high part of the sample */
573 hw_value |= ene_hw_read_reg(dev,
574 ENE_SAMPLE_BUFFER_FAN +
575 dev->rx_pointer * 4 + i) << 8;
576 pulse = hw_value & ENE_FAN_SMPL_PULS_MSK;
577
578 /* clear space bit, and other unused bits */
579 hw_value &= ENE_FAN_VALUE_MASK;
580 hw_sample = hw_value * ENE_SAMPLE_PERIOD_FAN;
581
582 } else {
583 pulse = !(hw_value & ENE_SAMPLE_SPC_MASK);
584 hw_value &= ENE_SAMPLE_VALUE_MASK;
585 hw_sample = hw_value * sample_period;
586
587 if (dev->rx_period_adjust) {
588 hw_sample *= (100 - dev->rx_period_adjust);
589 hw_sample /= 100;
590 }
591 }
592 /* no more data */
593 if (!(hw_value))
594 break;
595
596 ene_dbg("RX: %d (%s)", hw_sample, pulse ? "pulse" : "space");
597
598
599 ev.duration = hw_sample * 1000;
600 ev.pulse = pulse;
601 ir_raw_event_store_with_filter(dev->idev, &ev);
602 }
603
604 ir_raw_event_handle(dev->idev);
605unlock:
606 spin_unlock_irqrestore(&dev->hw_lock, flags);
607 return retval;
608}
609
610/* Initialize default settings */
611static void ene_setup_settings(struct ene_device *dev)
612{
613 dev->tx_period = 32;
614 dev->tx_duty_cycle = 25; /*%*/
615 dev->transmitter_mask = 3;
616
617 /* Force learning mode if (input == 2), otherwise
618 let user set it with LIRC_SET_REC_CARRIER */
619 dev->learning_enabled =
620 (input == 2 && dev->hw_learning_and_tx_capable);
621
622 dev->rx_pointer = -1;
623
624}
625
626/* outside interface: called on first open*/
627static int ene_open(void *data)
628{
629 struct ene_device *dev = (struct ene_device *)data;
630 unsigned long flags;
631
632 spin_lock_irqsave(&dev->hw_lock, flags);
633 dev->in_use = 1;
634 ene_setup_settings(dev);
635 ene_rx_enable(dev);
636 spin_unlock_irqrestore(&dev->hw_lock, flags);
637 return 0;
638}
639
640/* outside interface: called on device close*/
641static void ene_close(void *data)
642{
643 struct ene_device *dev = (struct ene_device *)data;
644 unsigned long flags;
645 spin_lock_irqsave(&dev->hw_lock, flags);
646
647 ene_rx_disable(dev);
648 dev->in_use = 0;
649 spin_unlock_irqrestore(&dev->hw_lock, flags);
650}
651
652/* outside interface: set transmitter mask */
653static int ene_set_tx_mask(void *data, u32 tx_mask)
654{
655 struct ene_device *dev = (struct ene_device *)data;
656 unsigned long flags;
657 ene_dbg("TX: attempt to set transmitter mask %02x", tx_mask);
658
659 /* invalid txmask */
660 if (!tx_mask || tx_mask & ~0x3) {
661 ene_dbg("TX: invalid mask");
662 /* return count of transmitters */
663 return 2;
664 }
665
666 spin_lock_irqsave(&dev->hw_lock, flags);
667 dev->transmitter_mask = tx_mask;
668 spin_unlock_irqrestore(&dev->hw_lock, flags);
669 return 0;
670}
671
672/* outside interface : set tx carrier */
673static int ene_set_tx_carrier(void *data, u32 carrier)
674{
675 struct ene_device *dev = (struct ene_device *)data;
676 unsigned long flags;
677 u32 period = 1000000 / carrier; /* (1 / freq) (* # usec in 1 sec) */
678
679 ene_dbg("TX: attempt to set tx carrier to %d kHz", carrier);
680
681 if (period && (period > ENE_TX_PERIOD_MAX ||
682 period < ENE_TX_PERIOD_MIN)) {
683
684 ene_dbg("TX: out of range %d-%d carrier, "
685 "falling back to 32 kHz",
686 1000 / ENE_TX_PERIOD_MIN,
687 1000 / ENE_TX_PERIOD_MAX);
688
689 period = 32; /* this is just a coincidence!!! */
690 }
691 ene_dbg("TX: set carrier to %d kHz", carrier);
692
693 spin_lock_irqsave(&dev->hw_lock, flags);
694 dev->tx_period = period;
695 spin_unlock_irqrestore(&dev->hw_lock, flags);
696 return 0;
697}
698
699
700/* outside interface: enable learning mode */
701static int ene_set_learning_mode(void *data, int enable)
702{
703 struct ene_device *dev = (struct ene_device *)data;
704 unsigned long flags;
705 if (enable == dev->learning_enabled)
706 return 0;
707
708 spin_lock_irqsave(&dev->hw_lock, flags);
709 dev->learning_enabled = enable;
710 ene_rx_set_inputs(dev);
711 spin_unlock_irqrestore(&dev->hw_lock, flags);
712 return 0;
713}
714
715/* outside interface: set rec carrier */
716static int ene_set_rec_carrier(void *data, u32 min, u32 max)
717{
718 struct ene_device *dev = (struct ene_device *)data;
719 ene_set_learning_mode(dev,
720 max > ENE_NORMAL_RX_HI || min < ENE_NORMAL_RX_LOW);
721 return 0;
722}
723
724/* outside interface: enable or disable idle mode */
725static void ene_rx_set_idle(void *data, int idle)
726{
727 struct ene_device *dev = (struct ene_device *)data;
728 ene_dbg("%sabling idle mode", idle ? "en" : "dis");
729
730 ene_hw_write_reg_mask(dev, ENE_CIR_SAMPLE_PERIOD,
731 (enable_idle && idle) ? 0 : ENE_CIR_SAMPLE_OVERFLOW,
732 ENE_CIR_SAMPLE_OVERFLOW);
733}
734
735
736/* outside interface: transmit */
737static int ene_transmit(void *data, int *buf, u32 n)
738{
739 struct ene_device *dev = (struct ene_device *)data;
740 unsigned long flags;
741
742 dev->tx_buffer = buf;
743 dev->tx_len = n / sizeof(int);
744 dev->tx_pos = 0;
745 dev->tx_reg = 0;
746 dev->tx_done = 0;
747 dev->tx_sample = 0;
748 dev->tx_sample_pulse = 0;
749
750 ene_dbg("TX: %d samples", dev->tx_len);
751
752 spin_lock_irqsave(&dev->hw_lock, flags);
753
754 ene_tx_hw_set_transmiter_mask(dev);
755 ene_tx_prepare(dev);
756
757 /* Transmit first two samples */
758 ene_tx_sample(dev);
759 ene_tx_sample(dev);
760
761 spin_unlock_irqrestore(&dev->hw_lock, flags);
762
763 if (wait_for_completion_timeout(&dev->tx_complete, 2 * HZ) == 0) {
764 ene_dbg("TX: timeout");
765 spin_lock_irqsave(&dev->hw_lock, flags);
766 ene_tx_complete(dev);
767 spin_unlock_irqrestore(&dev->hw_lock, flags);
768 } else
769 ene_dbg("TX: done");
770 return n;
771}
772
773
774/* probe entry */
775static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
776{
777 int error = -ENOMEM;
778 struct ir_dev_props *ir_props;
779 struct input_dev *input_dev;
780 struct ene_device *dev;
781
782 /* allocate memory */
783 input_dev = input_allocate_device();
784 ir_props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
785 dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL);
786
787 if (!input_dev || !ir_props || !dev)
788 goto error;
789
790 /* validate resources */
791 error = -ENODEV;
792
793 if (!pnp_port_valid(pnp_dev, 0) ||
794 pnp_port_len(pnp_dev, 0) < ENE_MAX_IO)
795 goto error;
796
797 if (!pnp_irq_valid(pnp_dev, 0))
798 goto error;
799
800 dev->hw_io = pnp_port_start(pnp_dev, 0);
801 dev->irq = pnp_irq(pnp_dev, 0);
802 spin_lock_init(&dev->hw_lock);
803
804 /* claim the resources */
805 error = -EBUSY;
806 if (!request_region(dev->hw_io, ENE_MAX_IO, ENE_DRIVER_NAME))
807 goto error;
808
809 if (request_irq(dev->irq, ene_isr,
810 IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev))
811 goto error;
812
813 pnp_set_drvdata(pnp_dev, dev);
814 dev->pnp_dev = pnp_dev;
815
816 /* detect hardware version and features */
817 error = ene_hw_detect(dev);
818 if (error)
819 goto error;
820
821 ene_setup_settings(dev);
822
823 if (!dev->hw_learning_and_tx_capable && txsim) {
824 dev->hw_learning_and_tx_capable = 1;
825 setup_timer(&dev->tx_sim_timer, ene_tx_irqsim,
826 (long unsigned int)dev);
827 ene_printk(KERN_WARNING,
828 "Simulation of TX activated\n");
829 }
830
831 ir_props->driver_type = RC_DRIVER_IR_RAW;
832 ir_props->allowed_protos = IR_TYPE_ALL;
833 ir_props->priv = dev;
834 ir_props->open = ene_open;
835 ir_props->close = ene_close;
836 ir_props->min_timeout = ENE_MINGAP * 1000;
837 ir_props->max_timeout = ENE_MAXGAP * 1000;
838 ir_props->timeout = ENE_MAXGAP * 1000;
839
840 if (dev->hw_revision == ENE_HW_B)
841 ir_props->s_idle = ene_rx_set_idle;
842
843
844 dev->props = ir_props;
845 dev->idev = input_dev;
846
847 /* don't allow too short/long sample periods */
848 if (sample_period < 5 || sample_period > 0x7F)
849 sample_period = -1;
850
851 /* choose default sample period */
852 if (sample_period == -1) {
853
854 sample_period = 50;
855
856 /* on revB, hardware idle mode eats first sample
857 if we set too low sample period */
858 if (dev->hw_revision == ENE_HW_B && enable_idle)
859 sample_period = 75;
860 }
861
862 ir_props->rx_resolution = sample_period * 1000;
863
864 if (dev->hw_learning_and_tx_capable) {
865
866 ir_props->s_learning_mode = ene_set_learning_mode;
867
868 if (input == 0)
869 ir_props->s_rx_carrier_range = ene_set_rec_carrier;
870
871 init_completion(&dev->tx_complete);
872 ir_props->tx_ir = ene_transmit;
873 ir_props->s_tx_mask = ene_set_tx_mask;
874 ir_props->s_tx_carrier = ene_set_tx_carrier;
875 ir_props->tx_resolution = ENE_TX_SMPL_PERIOD * 1000;
876 /* ir_props->s_carrier_report = ene_set_carrier_report; */
877 }
878
879
880 device_set_wakeup_capable(&pnp_dev->dev, 1);
881 device_set_wakeup_enable(&pnp_dev->dev, 1);
882
883 if (dev->hw_learning_and_tx_capable)
884 input_dev->name = "ENE eHome Infrared Remote Transceiver";
885 else
886 input_dev->name = "ENE eHome Infrared Remote Receiver";
887
888
889 error = -ENODEV;
890 if (ir_input_register(input_dev, RC_MAP_RC6_MCE, ir_props,
891 ENE_DRIVER_NAME))
892 goto error;
893
894
895 ene_printk(KERN_NOTICE, "driver has been succesfully loaded\n");
896 return 0;
897error:
898 if (dev->irq)
899 free_irq(dev->irq, dev);
900 if (dev->hw_io)
901 release_region(dev->hw_io, ENE_MAX_IO);
902
903 input_free_device(input_dev);
904 kfree(ir_props);
905 kfree(dev);
906 return error;
907}
908
909/* main unload function */
910static void ene_remove(struct pnp_dev *pnp_dev)
911{
912 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
913 unsigned long flags;
914
915 spin_lock_irqsave(&dev->hw_lock, flags);
916 ene_rx_disable(dev);
917 spin_unlock_irqrestore(&dev->hw_lock, flags);
918
919 free_irq(dev->irq, dev);
920 release_region(dev->hw_io, ENE_MAX_IO);
921 ir_input_unregister(dev->idev);
922 kfree(dev->props);
923 kfree(dev);
924}
925
926/* enable wake on IR (wakes on specific button on original remote) */
927static void ene_enable_wake(struct ene_device *dev, int enable)
928{
929 enable = enable && device_may_wakeup(&dev->pnp_dev->dev);
930
931 ene_dbg("wake on IR %s", enable ? "enabled" : "disabled");
932
933 ene_hw_write_reg_mask(dev, ENE_FW1, enable ?
934 ENE_FW1_WAKE : 0, ENE_FW1_WAKE);
935}
936
937#ifdef CONFIG_PM
938static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
939{
940 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
941 ene_enable_wake(dev, 1);
942 return 0;
943}
944
945static int ene_resume(struct pnp_dev *pnp_dev)
946{
947 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
948 if (dev->in_use)
949 ene_rx_enable(dev);
950
951 ene_enable_wake(dev, 0);
952 return 0;
953}
954#endif
955
956static void ene_shutdown(struct pnp_dev *pnp_dev)
957{
958 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
959 ene_enable_wake(dev, 1);
960}
961
962static const struct pnp_device_id ene_ids[] = {
963 {.id = "ENE0100",},
964 {.id = "ENE0200",},
965 {.id = "ENE0201",},
966 {.id = "ENE0202",},
967 {},
968};
969
970static struct pnp_driver ene_driver = {
971 .name = ENE_DRIVER_NAME,
972 .id_table = ene_ids,
973 .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
974
975 .probe = ene_probe,
976 .remove = __devexit_p(ene_remove),
977#ifdef CONFIG_PM
978 .suspend = ene_suspend,
979 .resume = ene_resume,
980#endif
981 .shutdown = ene_shutdown,
982};
983
984static int __init ene_init(void)
985{
986 return pnp_register_driver(&ene_driver);
987}
988
989static void ene_exit(void)
990{
991 pnp_unregister_driver(&ene_driver);
992}
993
994module_param(sample_period, int, S_IRUGO);
995MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)");
996
997module_param(enable_idle, bool, S_IRUGO | S_IWUSR);
998MODULE_PARM_DESC(enable_idle,
999 "Enables turning off signal sampling after long inactivity time; "
1000 "if disabled might help detecting input signal (default: enabled)"
1001 " (KB3926B only)");
1002
1003module_param(input, bool, S_IRUGO);
1004MODULE_PARM_DESC(input, "select which input to use "
1005 "0 - auto, 1 - standard, 2 - wideband(KB3926C+)");
1006
1007module_param(debug, int, S_IRUGO | S_IWUSR);
1008MODULE_PARM_DESC(debug, "Enable debug (debug=2 verbose debug output)");
1009
1010module_param(txsim, bool, S_IRUGO);
1011MODULE_PARM_DESC(txsim,
1012 "Simulate TX features on unsupported hardware (dangerous)");
1013
1014MODULE_DEVICE_TABLE(pnp, ene_ids);
1015MODULE_DESCRIPTION
1016 ("Infrared input driver for KB3926B/KB3926C/KB3926D "
1017 "(aka ENE0100/ENE0200/ENE0201) CIR port");
1018
1019MODULE_AUTHOR("Maxim Levitsky");
1020MODULE_LICENSE("GPL");
1021
1022module_init(ene_init);
1023module_exit(ene_exit);
diff --git a/drivers/media/IR/ene_ir.h b/drivers/media/IR/ene_ir.h
new file mode 100644
index 00000000000..54c76af0d03
--- /dev/null
+++ b/drivers/media/IR/ene_ir.h
@@ -0,0 +1,235 @@
1/*
2 * driver for ENE KB3926 B/C/D CIR (also known as ENE0XXX)
3 *
4 * Copyright (C) 2010 Maxim Levitsky <maximlevitsky@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 * USA
20 */
21#include <linux/spinlock.h>
22
23
24/* hardware address */
25#define ENE_STATUS 0 /* hardware status - unused */
26#define ENE_ADDR_HI 1 /* hi byte of register address */
27#define ENE_ADDR_LO 2 /* low byte of register address */
28#define ENE_IO 3 /* read/write window */
29#define ENE_MAX_IO 4
30
31/* 8 bytes of samples, divided in 2 halfs*/
32#define ENE_SAMPLE_BUFFER 0xF8F0 /* regular sample buffer */
33#define ENE_SAMPLE_SPC_MASK 0x80 /* sample is space */
34#define ENE_SAMPLE_VALUE_MASK 0x7F
35#define ENE_SAMPLE_OVERFLOW 0x7F
36#define ENE_SAMPLES_SIZE 4
37
38/* fan input sample buffer */
39#define ENE_SAMPLE_BUFFER_FAN 0xF8FB /* this buffer holds high byte of */
40 /* each sample of normal buffer */
41#define ENE_FAN_SMPL_PULS_MSK 0x8000 /* this bit of combined sample */
42 /* if set, says that sample is pulse */
43#define ENE_FAN_VALUE_MASK 0x0FFF /* mask for valid bits of the value */
44
45/* first firmware register */
46#define ENE_FW1 0xF8F8
47#define ENE_FW1_ENABLE 0x01 /* enable fw processing */
48#define ENE_FW1_TXIRQ 0x02 /* TX interrupt pending */
49#define ENE_FW1_WAKE 0x40 /* enable wake from S3 */
50#define ENE_FW1_IRQ 0x80 /* enable interrupt */
51
52/* second firmware register */
53#define ENE_FW2 0xF8F9
54#define ENE_FW2_BUF_HIGH 0x01 /* which half of the buffer to read */
55#define ENE_FW2_IRQ_CLR 0x04 /* clear this on IRQ */
56#define ENE_FW2_GP40_AS_LEARN 0x08 /* normal input is used as */
57 /* learning input */
58#define ENE_FW2_FAN_AS_NRML_IN 0x40 /* fan is used as normal input */
59#define ENE_FW2_LEARNING 0x80 /* hardware supports learning and TX */
60
61/* transmitter ports */
62#define ENE_TX_PORT2 0xFC01 /* this enables one or both */
63#define ENE_TX_PORT2_EN 0x20 /* TX ports */
64#define ENE_TX_PORT1 0xFC08
65#define ENE_TX_PORT1_EN 0x02
66
67/* IRQ registers block (for revision B) */
68#define ENEB_IRQ 0xFD09 /* IRQ number */
69#define ENEB_IRQ_UNK1 0xFD17 /* unknown setting = 1 */
70#define ENEB_IRQ_STATUS 0xFD80 /* irq status */
71#define ENEB_IRQ_STATUS_IR 0x20 /* IR irq */
72
73/* fan as input settings - only if learning capable */
74#define ENE_FAN_AS_IN1 0xFE30 /* fan init reg 1 */
75#define ENE_FAN_AS_IN1_EN 0xCD
76#define ENE_FAN_AS_IN2 0xFE31 /* fan init reg 2 */
77#define ENE_FAN_AS_IN2_EN 0x03
78#define ENE_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */
79
80/* IRQ registers block (for revision C,D) */
81#define ENEC_IRQ 0xFE9B /* new irq settings register */
82#define ENEC_IRQ_MASK 0x0F /* irq number mask */
83#define ENEC_IRQ_UNK_EN 0x10 /* always enabled */
84#define ENEC_IRQ_STATUS 0x20 /* irq status and ACK */
85
86/* CIR block settings */
87#define ENE_CIR_CONF1 0xFEC0
88#define ENE_CIR_CONF1_TX_CLEAR 0x01 /* clear that on revC */
89 /* while transmitting */
90#define ENE_CIR_CONF1_RX_ON 0x07 /* normal receiver enabled */
91#define ENE_CIR_CONF1_LEARN1 0x08 /* enabled on learning mode */
92#define ENE_CIR_CONF1_TX_ON 0x30 /* enabled on transmit */
93#define ENE_CIR_CONF1_TX_CARR 0x80 /* send TX carrier or not */
94
95#define ENE_CIR_CONF2 0xFEC1 /* unknown setting = 0 */
96#define ENE_CIR_CONF2_LEARN2 0x10 /* set on enable learning */
97#define ENE_CIR_CONF2_GPIO40DIS 0x20 /* disable input via gpio40 */
98
99#define ENE_CIR_SAMPLE_PERIOD 0xFEC8 /* sample period in us */
100#define ENE_CIR_SAMPLE_OVERFLOW 0x80 /* interrupt on overflows if set */
101
102
103/* Two byte tx buffer */
104#define ENE_TX_INPUT1 0xFEC9
105#define ENE_TX_INPUT2 0xFECA
106#define ENE_TX_PULSE_MASK 0x80 /* Transmitted sample is pulse */
107#define ENE_TX_SMLP_MASK 0x7F
108#define ENE_TX_SMPL_PERIOD 50 /* transmit sample period - fixed */
109
110
111/* Unknown TX setting - TX sample period ??? */
112#define ENE_TX_UNK1 0xFECB /* set to 0x63 */
113
114/* Current received carrier period */
115#define ENE_RX_CARRIER 0xFECC /* RX period (500 ns) */
116#define ENE_RX_CARRIER_VALID 0x80 /* Register content valid */
117
118
119/* TX period (1/carrier) */
120#define ENE_TX_PERIOD 0xFECE /* TX period (500 ns) */
121#define ENE_TX_PERIOD_UNKBIT 0x80 /* This bit set on transmit*/
122#define ENE_TX_PERIOD_PULSE 0xFECF /* TX pulse period (500 ns)*/
123
124/* Hardware versions */
125#define ENE_HW_VERSION 0xFF00 /* hardware revision */
126#define ENE_PLLFRH 0xFF16
127#define ENE_PLLFRL 0xFF17
128
129#define ENE_HW_UNK 0xFF1D
130#define ENE_HW_UNK_CLR 0x04
131#define ENE_HW_VER_MAJOR 0xFF1E /* chip version */
132#define ENE_HW_VER_MINOR 0xFF1F
133#define ENE_HW_VER_OLD 0xFD00
134
135/* Normal/Learning carrier ranges - only valid if we have learning input*/
136/* TODO: test */
137#define ENE_NORMAL_RX_LOW 34
138#define ENE_NORMAL_RX_HI 38
139
140/* Tx carrier range */
141/* Hardware might be able to do more, but this range is enough for
142 all purposes */
143#define ENE_TX_PERIOD_MAX 32 /* corresponds to 29.4 kHz */
144#define ENE_TX_PERIOD_MIN 16 /* corrsponds to 62.5 kHz */
145
146
147
148/* Minimal and maximal gaps */
149
150/* Normal case:
151 Minimal gap is 0x7F * sample period
152 Maximum gap depends on hardware.
153 For KB3926B, it is unlimited, for newer models its around
154 250000, after which HW stops sending samples, and that is
155 not possible to change */
156
157/* Fan case:
158 Both minimal and maximal gaps are same, and equal to 0xFFF * 0x61
159 And there is nothing to change this setting
160*/
161
162#define ENE_MAXGAP 250000
163#define ENE_MINGAP (127 * sample_period)
164
165/******************************************************************************/
166
167#define ENE_DRIVER_NAME "ene_ir"
168
169#define ENE_IRQ_RX 1
170#define ENE_IRQ_TX 2
171
172#define ENE_HW_B 1 /* 3926B */
173#define ENE_HW_C 2 /* 3926C */
174#define ENE_HW_D 3 /* 3926D */
175
176#define ene_printk(level, text, ...) \
177 printk(level ENE_DRIVER_NAME ": " text, ## __VA_ARGS__)
178
179#define ene_dbg(text, ...) \
180 if (debug) \
181 printk(KERN_DEBUG \
182 ENE_DRIVER_NAME ": " text "\n" , ## __VA_ARGS__)
183
184#define ene_dbg_verbose(text, ...) \
185 if (debug > 1) \
186 printk(KERN_DEBUG \
187 ENE_DRIVER_NAME ": " text "\n" , ## __VA_ARGS__)
188
189
190struct ene_device {
191 struct pnp_dev *pnp_dev;
192 struct input_dev *idev;
193 struct ir_dev_props *props;
194 int in_use;
195
196 /* hw IO settings */
197 unsigned long hw_io;
198 int irq;
199 spinlock_t hw_lock;
200
201 /* HW features */
202 int hw_revision; /* hardware revision */
203 bool hw_learning_and_tx_capable; /* learning capable */
204 bool hw_gpio40_learning; /* gpio40 is learning */
205 bool hw_fan_as_normal_input; /* fan input is used as */
206 /* regular input */
207 /* HW state*/
208 int rx_pointer; /* hw pointer to rx buffer */
209 bool rx_fan_input_inuse; /* is fan input in use for rx*/
210 int tx_reg; /* current reg used for TX */
211 u8 saved_conf1; /* saved FEC0 reg */
212
213 /* TX sample handling */
214 unsigned int tx_sample; /* current sample for TX */
215 bool tx_sample_pulse; /* current sample is pulse */
216
217 /* TX buffer */
218 int *tx_buffer; /* input samples buffer*/
219 int tx_pos; /* position in that bufer */
220 int tx_len; /* current len of tx buffer */
221 int tx_done; /* done transmitting */
222 /* one more sample pending*/
223 struct completion tx_complete; /* TX completion */
224 struct timer_list tx_sim_timer;
225
226 /* TX settings */
227 int tx_period;
228 int tx_duty_cycle;
229 int transmitter_mask;
230
231 /* RX settings */
232 bool learning_enabled; /* learning input enabled */
233 bool carrier_detect_enabled; /* carrier detect enabled */
234 int rx_period_adjust;
235};
diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c
index 65c125e44e9..c185422ef28 100644
--- a/drivers/media/IR/imon.c
+++ b/drivers/media/IR/imon.c
@@ -87,7 +87,6 @@ static ssize_t lcd_write(struct file *file, const char *buf,
87struct imon_context { 87struct imon_context {
88 struct device *dev; 88 struct device *dev;
89 struct ir_dev_props *props; 89 struct ir_dev_props *props;
90 struct ir_input_dev *ir;
91 /* Newer devices have two interfaces */ 90 /* Newer devices have two interfaces */
92 struct usb_device *usbdev_intf0; 91 struct usb_device *usbdev_intf0;
93 struct usb_device *usbdev_intf1; 92 struct usb_device *usbdev_intf1;
@@ -1656,7 +1655,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
1656{ 1655{
1657 struct input_dev *idev; 1656 struct input_dev *idev;
1658 struct ir_dev_props *props; 1657 struct ir_dev_props *props;
1659 struct ir_input_dev *ir;
1660 int ret, i; 1658 int ret, i;
1661 1659
1662 idev = input_allocate_device(); 1660 idev = input_allocate_device();
@@ -1671,12 +1669,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
1671 goto props_alloc_failed; 1669 goto props_alloc_failed;
1672 } 1670 }
1673 1671
1674 ir = kzalloc(sizeof(struct ir_input_dev), GFP_KERNEL);
1675 if (!ir) {
1676 dev_err(ictx->dev, "remote ir input dev allocation failed\n");
1677 goto ir_dev_alloc_failed;
1678 }
1679
1680 snprintf(ictx->name_idev, sizeof(ictx->name_idev), 1672 snprintf(ictx->name_idev, sizeof(ictx->name_idev),
1681 "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product); 1673 "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product);
1682 idev->name = ictx->name_idev; 1674 idev->name = ictx->name_idev;
@@ -1706,14 +1698,9 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
1706 props->change_protocol = imon_ir_change_protocol; 1698 props->change_protocol = imon_ir_change_protocol;
1707 ictx->props = props; 1699 ictx->props = props;
1708 1700
1709 ictx->ir = ir;
1710 memcpy(&ir->dev, ictx->dev, sizeof(struct device));
1711
1712 usb_to_input_id(ictx->usbdev_intf0, &idev->id); 1701 usb_to_input_id(ictx->usbdev_intf0, &idev->id);
1713 idev->dev.parent = ictx->dev; 1702 idev->dev.parent = ictx->dev;
1714 1703
1715 input_set_drvdata(idev, ir);
1716
1717 ret = ir_input_register(idev, RC_MAP_IMON_PAD, props, MOD_NAME); 1704 ret = ir_input_register(idev, RC_MAP_IMON_PAD, props, MOD_NAME);
1718 if (ret < 0) { 1705 if (ret < 0) {
1719 dev_err(ictx->dev, "remote input dev register failed\n"); 1706 dev_err(ictx->dev, "remote input dev register failed\n");
@@ -1723,8 +1710,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
1723 return idev; 1710 return idev;
1724 1711
1725idev_register_failed: 1712idev_register_failed:
1726 kfree(ir);
1727ir_dev_alloc_failed:
1728 kfree(props); 1713 kfree(props);
1729props_alloc_failed: 1714props_alloc_failed:
1730 input_free_device(idev); 1715 input_free_device(idev);
@@ -1944,7 +1929,6 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
1944 1929
1945urb_submit_failed: 1930urb_submit_failed:
1946 ir_input_unregister(ictx->idev); 1931 ir_input_unregister(ictx->idev);
1947 input_free_device(ictx->idev);
1948idev_setup_failed: 1932idev_setup_failed:
1949find_endpoint_failed: 1933find_endpoint_failed:
1950 mutex_unlock(&ictx->lock); 1934 mutex_unlock(&ictx->lock);
@@ -2014,10 +1998,8 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf,
2014 return ictx; 1998 return ictx;
2015 1999
2016urb_submit_failed: 2000urb_submit_failed:
2017 if (ictx->touch) { 2001 if (ictx->touch)
2018 input_unregister_device(ictx->touch); 2002 input_unregister_device(ictx->touch);
2019 input_free_device(ictx->touch);
2020 }
2021touch_setup_failed: 2003touch_setup_failed:
2022find_endpoint_failed: 2004find_endpoint_failed:
2023 mutex_unlock(&ictx->lock); 2005 mutex_unlock(&ictx->lock);
diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h
index babd52061bc..a85a8c7c905 100644
--- a/drivers/media/IR/ir-core-priv.h
+++ b/drivers/media/IR/ir-core-priv.h
@@ -32,7 +32,7 @@ struct ir_raw_handler {
32 32
33struct ir_raw_event_ctrl { 33struct ir_raw_event_ctrl {
34 struct list_head list; /* to keep track of raw clients */ 34 struct list_head list; /* to keep track of raw clients */
35 struct work_struct rx_work; /* for the rx decoding workqueue */ 35 struct task_struct *thread;
36 struct kfifo kfifo; /* fifo for the pulse/space durations */ 36 struct kfifo kfifo; /* fifo for the pulse/space durations */
37 ktime_t last_event; /* when last event occurred */ 37 ktime_t last_event; /* when last event occurred */
38 enum raw_event_type last_type; /* last event type */ 38 enum raw_event_type last_type; /* last event type */
@@ -41,10 +41,13 @@ struct ir_raw_event_ctrl {
41 41
42 /* raw decoder state follows */ 42 /* raw decoder state follows */
43 struct ir_raw_event prev_ev; 43 struct ir_raw_event prev_ev;
44 struct ir_raw_event this_ev;
44 struct nec_dec { 45 struct nec_dec {
45 int state; 46 int state;
46 unsigned count; 47 unsigned count;
47 u32 bits; 48 u32 bits;
49 bool is_nec_x;
50 bool necx_repeat;
48 } nec; 51 } nec;
49 struct rc5_dec { 52 struct rc5_dec {
50 int state; 53 int state;
@@ -76,7 +79,7 @@ struct ir_raw_event_ctrl {
76 struct lirc_codec { 79 struct lirc_codec {
77 struct ir_input_dev *ir_dev; 80 struct ir_input_dev *ir_dev;
78 struct lirc_driver *drv; 81 struct lirc_driver *drv;
79 int lircdata; 82 int carrier_low;
80 } lirc; 83 } lirc;
81}; 84};
82 85
@@ -104,10 +107,9 @@ static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration)
104 ev->duration -= duration; 107 ev->duration -= duration;
105} 108}
106 109
107#define TO_US(duration) (((duration) + 500) / 1000) 110#define TO_US(duration) DIV_ROUND_CLOSEST((duration), 1000)
108#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space") 111#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space")
109#define IS_RESET(ev) (ev.duration == 0) 112#define IS_RESET(ev) (ev.duration == 0)
110
111/* 113/*
112 * Routines from ir-sysfs.c - Meant to be called only internally inside 114 * Routines from ir-sysfs.c - Meant to be called only internally inside
113 * ir-core 115 * ir-core
@@ -126,7 +128,8 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler);
126void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); 128void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
127void ir_raw_init(void); 129void ir_raw_init(void);
128 130
129 131int ir_rcmap_init(void);
132void ir_rcmap_cleanup(void);
130/* 133/*
131 * Decoder initialization code 134 * Decoder initialization code
132 * 135 *
diff --git a/drivers/media/IR/ir-jvc-decoder.c b/drivers/media/IR/ir-jvc-decoder.c
index 8894d8b3604..77a89c4de01 100644
--- a/drivers/media/IR/ir-jvc-decoder.c
+++ b/drivers/media/IR/ir-jvc-decoder.c
@@ -32,6 +32,7 @@ enum jvc_state {
32 STATE_BIT_SPACE, 32 STATE_BIT_SPACE,
33 STATE_TRAILER_PULSE, 33 STATE_TRAILER_PULSE,
34 STATE_TRAILER_SPACE, 34 STATE_TRAILER_SPACE,
35 STATE_CHECK_REPEAT,
35}; 36};
36 37
37/** 38/**
@@ -60,6 +61,7 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
60 IR_dprintk(2, "JVC decode started at state %d (%uus %s)\n", 61 IR_dprintk(2, "JVC decode started at state %d (%uus %s)\n",
61 data->state, TO_US(ev.duration), TO_STR(ev.pulse)); 62 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
62 63
64again:
63 switch (data->state) { 65 switch (data->state) {
64 66
65 case STATE_INACTIVE: 67 case STATE_INACTIVE:
@@ -149,8 +151,18 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
149 } 151 }
150 152
151 data->count = 0; 153 data->count = 0;
152 data->state = STATE_BIT_PULSE; 154 data->state = STATE_CHECK_REPEAT;
153 return 0; 155 return 0;
156
157 case STATE_CHECK_REPEAT:
158 if (!ev.pulse)
159 break;
160
161 if (eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2))
162 data->state = STATE_INACTIVE;
163 else
164 data->state = STATE_BIT_PULSE;
165 goto again;
154 } 166 }
155 167
156out: 168out:
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c
index 15a0f192d41..7e82a9df726 100644
--- a/drivers/media/IR/ir-keytable.c
+++ b/drivers/media/IR/ir-keytable.c
@@ -339,6 +339,8 @@ void ir_repeat(struct input_dev *dev)
339 339
340 spin_lock_irqsave(&ir->keylock, flags); 340 spin_lock_irqsave(&ir->keylock, flags);
341 341
342 input_event(dev, EV_MSC, MSC_SCAN, ir->last_scancode);
343
342 if (!ir->keypressed) 344 if (!ir->keypressed)
343 goto out; 345 goto out;
344 346
@@ -370,6 +372,8 @@ void ir_keydown(struct input_dev *dev, int scancode, u8 toggle)
370 372
371 spin_lock_irqsave(&ir->keylock, flags); 373 spin_lock_irqsave(&ir->keylock, flags);
372 374
375 input_event(dev, EV_MSC, MSC_SCAN, scancode);
376
373 /* Repeat event? */ 377 /* Repeat event? */
374 if (ir->keypressed && 378 if (ir->keypressed &&
375 ir->last_scancode == scancode && 379 ir->last_scancode == scancode &&
@@ -383,9 +387,11 @@ void ir_keydown(struct input_dev *dev, int scancode, u8 toggle)
383 ir->last_toggle = toggle; 387 ir->last_toggle = toggle;
384 ir->last_keycode = keycode; 388 ir->last_keycode = keycode;
385 389
390
386 if (keycode == KEY_RESERVED) 391 if (keycode == KEY_RESERVED)
387 goto out; 392 goto out;
388 393
394
389 /* Register a keypress */ 395 /* Register a keypress */
390 ir->keypressed = true; 396 ir->keypressed = true;
391 IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", 397 IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n",
@@ -428,7 +434,7 @@ static void ir_close(struct input_dev *input_dev)
428 */ 434 */
429int __ir_input_register(struct input_dev *input_dev, 435int __ir_input_register(struct input_dev *input_dev,
430 const struct ir_scancode_table *rc_tab, 436 const struct ir_scancode_table *rc_tab,
431 const struct ir_dev_props *props, 437 struct ir_dev_props *props,
432 const char *driver_name) 438 const char *driver_name)
433{ 439{
434 struct ir_input_dev *ir_dev; 440 struct ir_input_dev *ir_dev;
@@ -480,6 +486,8 @@ int __ir_input_register(struct input_dev *input_dev,
480 486
481 set_bit(EV_KEY, input_dev->evbit); 487 set_bit(EV_KEY, input_dev->evbit);
482 set_bit(EV_REP, input_dev->evbit); 488 set_bit(EV_REP, input_dev->evbit);
489 set_bit(EV_MSC, input_dev->evbit);
490 set_bit(MSC_SCAN, input_dev->mscbit);
483 491
484 if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) { 492 if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) {
485 rc = -ENOMEM; 493 rc = -ENOMEM;
@@ -499,7 +507,8 @@ int __ir_input_register(struct input_dev *input_dev,
499 507
500 IR_dprintk(1, "Registered input device on %s for %s remote%s.\n", 508 IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
501 driver_name, rc_tab->name, 509 driver_name, rc_tab->name,
502 ir_dev->props->driver_type == RC_DRIVER_IR_RAW ? " in raw mode" : ""); 510 (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?
511 " in raw mode" : "");
503 512
504 return 0; 513 return 0;
505 514
diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c
index 3ba482d96c4..77b5946413c 100644
--- a/drivers/media/IR/ir-lirc-codec.c
+++ b/drivers/media/IR/ir-lirc-codec.c
@@ -32,6 +32,7 @@
32static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) 32static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
33{ 33{
34 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); 34 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
35 int sample;
35 36
36 if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC)) 37 if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
37 return 0; 38 return 0;
@@ -39,18 +40,20 @@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
39 if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf) 40 if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
40 return -EINVAL; 41 return -EINVAL;
41 42
43 if (IS_RESET(ev))
44 return 0;
45
42 IR_dprintk(2, "LIRC data transfer started (%uus %s)\n", 46 IR_dprintk(2, "LIRC data transfer started (%uus %s)\n",
43 TO_US(ev.duration), TO_STR(ev.pulse)); 47 TO_US(ev.duration), TO_STR(ev.pulse));
44 48
45 ir_dev->raw->lirc.lircdata += ev.duration / 1000; 49 sample = ev.duration / 1000;
46 if (ev.pulse) 50 if (ev.pulse)
47 ir_dev->raw->lirc.lircdata |= PULSE_BIT; 51 sample |= PULSE_BIT;
48 52
49 lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, 53 lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
50 (unsigned char *) &ir_dev->raw->lirc.lircdata); 54 (unsigned char *) &sample);
51 wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); 55 wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
52 56
53 ir_dev->raw->lirc.lircdata = 0;
54 57
55 return 0; 58 return 0;
56} 59}
@@ -92,13 +95,14 @@ out:
92 return ret; 95 return ret;
93} 96}
94 97
95static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) 98static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
99 unsigned long __user arg)
96{ 100{
97 struct lirc_codec *lirc; 101 struct lirc_codec *lirc;
98 struct ir_input_dev *ir_dev; 102 struct ir_input_dev *ir_dev;
99 int ret = 0; 103 int ret = 0;
100 void *drv_data; 104 void *drv_data;
101 unsigned long val; 105 unsigned long val = 0;
102 106
103 lirc = lirc_get_pdata(filep); 107 lirc = lirc_get_pdata(filep);
104 if (!lirc) 108 if (!lirc)
@@ -110,47 +114,106 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long ar
110 114
111 drv_data = ir_dev->props->priv; 115 drv_data = ir_dev->props->priv;
112 116
113 switch (cmd) { 117 if (_IOC_DIR(cmd) & _IOC_WRITE) {
114 case LIRC_SET_TRANSMITTER_MASK:
115 ret = get_user(val, (unsigned long *)arg); 118 ret = get_user(val, (unsigned long *)arg);
116 if (ret) 119 if (ret)
117 return ret; 120 return ret;
121 }
122
123 switch (cmd) {
118 124
119 if (ir_dev->props && ir_dev->props->s_tx_mask) 125 /* legacy support */
126 case LIRC_GET_SEND_MODE:
127 val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK;
128 break;
129
130 case LIRC_SET_SEND_MODE:
131 if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
132 return -EINVAL;
133 break;
134
135 /* TX settings */
136 case LIRC_SET_TRANSMITTER_MASK:
137 if (ir_dev->props->s_tx_mask)
120 ret = ir_dev->props->s_tx_mask(drv_data, (u32)val); 138 ret = ir_dev->props->s_tx_mask(drv_data, (u32)val);
121 else 139 else
122 return -EINVAL; 140 return -EINVAL;
123 break; 141 break;
124 142
125 case LIRC_SET_SEND_CARRIER: 143 case LIRC_SET_SEND_CARRIER:
126 ret = get_user(val, (unsigned long *)arg); 144 if (ir_dev->props->s_tx_carrier)
127 if (ret)
128 return ret;
129
130 if (ir_dev->props && ir_dev->props->s_tx_carrier)
131 ir_dev->props->s_tx_carrier(drv_data, (u32)val); 145 ir_dev->props->s_tx_carrier(drv_data, (u32)val);
132 else 146 else
133 return -EINVAL; 147 return -EINVAL;
134 break; 148 break;
135 149
136 case LIRC_GET_SEND_MODE: 150 case LIRC_SET_SEND_DUTY_CYCLE:
137 val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK; 151 if (!ir_dev->props->s_tx_duty_cycle)
138 ret = put_user(val, (unsigned long *)arg); 152 return -ENOSYS;
153
154 if (val <= 0 || val >= 100)
155 return -EINVAL;
156
157 ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val);
139 break; 158 break;
140 159
141 case LIRC_SET_SEND_MODE: 160 /* RX settings */
142 ret = get_user(val, (unsigned long *)arg); 161 case LIRC_SET_REC_CARRIER:
143 if (ret) 162 if (ir_dev->props->s_rx_carrier_range)
144 return ret; 163 ret = ir_dev->props->s_rx_carrier_range(
164 ir_dev->props->priv,
165 ir_dev->raw->lirc.carrier_low, val);
166 else
167 return -ENOSYS;
145 168
146 if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) 169 if (!ret)
170 ir_dev->raw->lirc.carrier_low = 0;
171 break;
172
173 case LIRC_SET_REC_CARRIER_RANGE:
174 if (val >= 0)
175 ir_dev->raw->lirc.carrier_low = val;
176 break;
177
178
179 case LIRC_GET_REC_RESOLUTION:
180 val = ir_dev->props->rx_resolution;
181 break;
182
183 case LIRC_SET_WIDEBAND_RECEIVER:
184 if (ir_dev->props->s_learning_mode)
185 return ir_dev->props->s_learning_mode(
186 ir_dev->props->priv, !!val);
187 else
188 return -ENOSYS;
189
190 /* Generic timeout support */
191 case LIRC_GET_MIN_TIMEOUT:
192 if (!ir_dev->props->max_timeout)
193 return -ENOSYS;
194 val = ir_dev->props->min_timeout / 1000;
195 break;
196
197 case LIRC_GET_MAX_TIMEOUT:
198 if (!ir_dev->props->max_timeout)
199 return -ENOSYS;
200 val = ir_dev->props->max_timeout / 1000;
201 break;
202
203 case LIRC_SET_REC_TIMEOUT:
204 if (val < ir_dev->props->min_timeout ||
205 val > ir_dev->props->max_timeout)
147 return -EINVAL; 206 return -EINVAL;
207 ir_dev->props->timeout = val * 1000;
148 break; 208 break;
149 209
150 default: 210 default:
151 return lirc_dev_fop_ioctl(filep, cmd, arg); 211 return lirc_dev_fop_ioctl(filep, cmd, arg);
152 } 212 }
153 213
214 if (_IOC_DIR(cmd) & _IOC_READ)
215 ret = put_user(val, (unsigned long *)arg);
216
154 return ret; 217 return ret;
155} 218}
156 219
@@ -196,13 +259,28 @@ static int ir_lirc_register(struct input_dev *input_dev)
196 259
197 features = LIRC_CAN_REC_MODE2; 260 features = LIRC_CAN_REC_MODE2;
198 if (ir_dev->props->tx_ir) { 261 if (ir_dev->props->tx_ir) {
262
199 features |= LIRC_CAN_SEND_PULSE; 263 features |= LIRC_CAN_SEND_PULSE;
200 if (ir_dev->props->s_tx_mask) 264 if (ir_dev->props->s_tx_mask)
201 features |= LIRC_CAN_SET_TRANSMITTER_MASK; 265 features |= LIRC_CAN_SET_TRANSMITTER_MASK;
202 if (ir_dev->props->s_tx_carrier) 266 if (ir_dev->props->s_tx_carrier)
203 features |= LIRC_CAN_SET_SEND_CARRIER; 267 features |= LIRC_CAN_SET_SEND_CARRIER;
268
269 if (ir_dev->props->s_tx_duty_cycle)
270 features |= LIRC_CAN_SET_REC_DUTY_CYCLE;
204 } 271 }
205 272
273 if (ir_dev->props->s_rx_carrier_range)
274 features |= LIRC_CAN_SET_REC_CARRIER |
275 LIRC_CAN_SET_REC_CARRIER_RANGE;
276
277 if (ir_dev->props->s_learning_mode)
278 features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
279
280 if (ir_dev->props->max_timeout)
281 features |= LIRC_CAN_SET_REC_TIMEOUT;
282
283
206 snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", 284 snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
207 ir_dev->driver_name); 285 ir_dev->driver_name);
208 drv->minor = -1; 286 drv->minor = -1;
@@ -224,8 +302,6 @@ static int ir_lirc_register(struct input_dev *input_dev)
224 302
225 ir_dev->raw->lirc.drv = drv; 303 ir_dev->raw->lirc.drv = drv;
226 ir_dev->raw->lirc.ir_dev = ir_dev; 304 ir_dev->raw->lirc.ir_dev = ir_dev;
227 ir_dev->raw->lirc.lircdata = PULSE_MASK;
228
229 return 0; 305 return 0;
230 306
231lirc_register_failed: 307lirc_register_failed:
diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c
index 52e0f378ae3..d597421d654 100644
--- a/drivers/media/IR/ir-nec-decoder.c
+++ b/drivers/media/IR/ir-nec-decoder.c
@@ -20,12 +20,13 @@
20#define NEC_HEADER_PULSE (16 * NEC_UNIT) 20#define NEC_HEADER_PULSE (16 * NEC_UNIT)
21#define NECX_HEADER_PULSE (8 * NEC_UNIT) /* Less common NEC variant */ 21#define NECX_HEADER_PULSE (8 * NEC_UNIT) /* Less common NEC variant */
22#define NEC_HEADER_SPACE (8 * NEC_UNIT) 22#define NEC_HEADER_SPACE (8 * NEC_UNIT)
23#define NEC_REPEAT_SPACE (8 * NEC_UNIT) 23#define NEC_REPEAT_SPACE (4 * NEC_UNIT)
24#define NEC_BIT_PULSE (1 * NEC_UNIT) 24#define NEC_BIT_PULSE (1 * NEC_UNIT)
25#define NEC_BIT_0_SPACE (1 * NEC_UNIT) 25#define NEC_BIT_0_SPACE (1 * NEC_UNIT)
26#define NEC_BIT_1_SPACE (3 * NEC_UNIT) 26#define NEC_BIT_1_SPACE (3 * NEC_UNIT)
27#define NEC_TRAILER_PULSE (1 * NEC_UNIT) 27#define NEC_TRAILER_PULSE (1 * NEC_UNIT)
28#define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */ 28#define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */
29#define NECX_REPEAT_BITS 1
29 30
30enum nec_state { 31enum nec_state {
31 STATE_INACTIVE, 32 STATE_INACTIVE,
@@ -67,8 +68,12 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
67 if (!ev.pulse) 68 if (!ev.pulse)
68 break; 69 break;
69 70
70 if (!eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2) && 71 if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2)) {
71 !eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2)) 72 data->is_nec_x = false;
73 data->necx_repeat = false;
74 } else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))
75 data->is_nec_x = true;
76 else
72 break; 77 break;
73 78
74 data->count = 0; 79 data->count = 0;
@@ -105,6 +110,17 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
105 if (ev.pulse) 110 if (ev.pulse)
106 break; 111 break;
107 112
113 if (data->necx_repeat && data->count == NECX_REPEAT_BITS &&
114 geq_margin(ev.duration,
115 NEC_TRAILER_SPACE, NEC_UNIT / 2)) {
116 IR_dprintk(1, "Repeat last key\n");
117 ir_repeat(input_dev);
118 data->state = STATE_INACTIVE;
119 return 0;
120
121 } else if (data->count > NECX_REPEAT_BITS)
122 data->necx_repeat = false;
123
108 data->bits <<= 1; 124 data->bits <<= 1;
109 if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2)) 125 if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
110 data->bits |= 1; 126 data->bits |= 1;
@@ -159,6 +175,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
159 IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); 175 IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
160 } 176 }
161 177
178 if (data->is_nec_x)
179 data->necx_repeat = true;
180
162 ir_keydown(input_dev, scancode, 0); 181 ir_keydown(input_dev, scancode, 0);
163 data->state = STATE_INACTIVE; 182 data->state = STATE_INACTIVE;
164 return 0; 183 return 0;
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c
index 6f192ef31db..43094e7eccf 100644
--- a/drivers/media/IR/ir-raw-event.c
+++ b/drivers/media/IR/ir-raw-event.c
@@ -12,9 +12,10 @@
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 */ 13 */
14 14
15#include <linux/workqueue.h> 15#include <linux/kthread.h>
16#include <linux/spinlock.h> 16#include <linux/mutex.h>
17#include <linux/sched.h> 17#include <linux/sched.h>
18#include <linux/freezer.h>
18#include "ir-core-priv.h" 19#include "ir-core-priv.h"
19 20
20/* Define the max number of pulse/space transitions to buffer */ 21/* Define the max number of pulse/space transitions to buffer */
@@ -24,7 +25,7 @@
24static LIST_HEAD(ir_raw_client_list); 25static LIST_HEAD(ir_raw_client_list);
25 26
26/* Used to handle IR raw handler extensions */ 27/* Used to handle IR raw handler extensions */
27static DEFINE_SPINLOCK(ir_raw_handler_lock); 28static DEFINE_MUTEX(ir_raw_handler_lock);
28static LIST_HEAD(ir_raw_handler_list); 29static LIST_HEAD(ir_raw_handler_list);
29static u64 available_protocols; 30static u64 available_protocols;
30 31
@@ -33,20 +34,30 @@ static u64 available_protocols;
33static struct work_struct wq_load; 34static struct work_struct wq_load;
34#endif 35#endif
35 36
36static void ir_raw_event_work(struct work_struct *work) 37static int ir_raw_event_thread(void *data)
37{ 38{
38 struct ir_raw_event ev; 39 struct ir_raw_event ev;
39 struct ir_raw_handler *handler; 40 struct ir_raw_handler *handler;
40 struct ir_raw_event_ctrl *raw = 41 struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
41 container_of(work, struct ir_raw_event_ctrl, rx_work); 42
42 43 while (!kthread_should_stop()) {
43 while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) { 44 try_to_freeze();
44 spin_lock(&ir_raw_handler_lock); 45
45 list_for_each_entry(handler, &ir_raw_handler_list, list) 46 mutex_lock(&ir_raw_handler_lock);
46 handler->decode(raw->input_dev, ev); 47
47 spin_unlock(&ir_raw_handler_lock); 48 while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) {
48 raw->prev_ev = ev; 49 list_for_each_entry(handler, &ir_raw_handler_list, list)
50 handler->decode(raw->input_dev, ev);
51 raw->prev_ev = ev;
52 }
53
54 mutex_unlock(&ir_raw_handler_lock);
55
56 set_current_state(TASK_INTERRUPTIBLE);
57 schedule();
49 } 58 }
59
60 return 0;
50} 61}
51 62
52/** 63/**
@@ -66,6 +77,9 @@ int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev)
66 if (!ir->raw) 77 if (!ir->raw)
67 return -EINVAL; 78 return -EINVAL;
68 79
80 IR_dprintk(2, "sample: (05%dus %s)\n",
81 TO_US(ev->duration), TO_STR(ev->pulse));
82
69 if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) 83 if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
70 return -ENOMEM; 84 return -ENOMEM;
71 85
@@ -126,6 +140,90 @@ int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type typ
126EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); 140EXPORT_SYMBOL_GPL(ir_raw_event_store_edge);
127 141
128/** 142/**
143 * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing
144 * @input_dev: the struct input_dev device descriptor
145 * @type: the type of the event that has occurred
146 *
147 * This routine (which may be called from an interrupt context) works
148 * in similiar manner to ir_raw_event_store_edge.
149 * This routine is intended for devices with limited internal buffer
150 * It automerges samples of same type, and handles timeouts
151 */
152int ir_raw_event_store_with_filter(struct input_dev *input_dev,
153 struct ir_raw_event *ev)
154{
155 struct ir_input_dev *ir = input_get_drvdata(input_dev);
156 struct ir_raw_event_ctrl *raw = ir->raw;
157
158 if (!raw || !ir->props)
159 return -EINVAL;
160
161 /* Ignore spaces in idle mode */
162 if (ir->idle && !ev->pulse)
163 return 0;
164 else if (ir->idle)
165 ir_raw_event_set_idle(input_dev, 0);
166
167 if (!raw->this_ev.duration) {
168 raw->this_ev = *ev;
169 } else if (ev->pulse == raw->this_ev.pulse) {
170 raw->this_ev.duration += ev->duration;
171 } else {
172 ir_raw_event_store(input_dev, &raw->this_ev);
173 raw->this_ev = *ev;
174 }
175
176 /* Enter idle mode if nessesary */
177 if (!ev->pulse && ir->props->timeout &&
178 raw->this_ev.duration >= ir->props->timeout)
179 ir_raw_event_set_idle(input_dev, 1);
180 return 0;
181}
182EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter);
183
184void ir_raw_event_set_idle(struct input_dev *input_dev, int idle)
185{
186 struct ir_input_dev *ir = input_get_drvdata(input_dev);
187 struct ir_raw_event_ctrl *raw = ir->raw;
188 ktime_t now;
189 u64 delta;
190
191 if (!ir->props)
192 return;
193
194 if (!ir->raw)
195 goto out;
196
197 if (idle) {
198 IR_dprintk(2, "enter idle mode\n");
199 raw->last_event = ktime_get();
200 } else {
201 IR_dprintk(2, "exit idle mode\n");
202
203 now = ktime_get();
204 delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event));
205
206 WARN_ON(raw->this_ev.pulse);
207
208 raw->this_ev.duration =
209 min(raw->this_ev.duration + delta,
210 (u64)IR_MAX_DURATION);
211
212 ir_raw_event_store(input_dev, &raw->this_ev);
213
214 if (raw->this_ev.duration == IR_MAX_DURATION)
215 ir_raw_event_reset(input_dev);
216
217 raw->this_ev.duration = 0;
218 }
219out:
220 if (ir->props->s_idle)
221 ir->props->s_idle(ir->props->priv, idle);
222 ir->idle = idle;
223}
224EXPORT_SYMBOL_GPL(ir_raw_event_set_idle);
225
226/**
129 * ir_raw_event_handle() - schedules the decoding of stored ir data 227 * ir_raw_event_handle() - schedules the decoding of stored ir data
130 * @input_dev: the struct input_dev device descriptor 228 * @input_dev: the struct input_dev device descriptor
131 * 229 *
@@ -138,7 +236,7 @@ void ir_raw_event_handle(struct input_dev *input_dev)
138 if (!ir->raw) 236 if (!ir->raw)
139 return; 237 return;
140 238
141 schedule_work(&ir->raw->rx_work); 239 wake_up_process(ir->raw->thread);
142} 240}
143EXPORT_SYMBOL_GPL(ir_raw_event_handle); 241EXPORT_SYMBOL_GPL(ir_raw_event_handle);
144 242
@@ -147,9 +245,9 @@ u64
147ir_raw_get_allowed_protocols() 245ir_raw_get_allowed_protocols()
148{ 246{
149 u64 protocols; 247 u64 protocols;
150 spin_lock(&ir_raw_handler_lock); 248 mutex_lock(&ir_raw_handler_lock);
151 protocols = available_protocols; 249 protocols = available_protocols;
152 spin_unlock(&ir_raw_handler_lock); 250 mutex_unlock(&ir_raw_handler_lock);
153 return protocols; 251 return protocols;
154} 252}
155 253
@@ -167,7 +265,7 @@ int ir_raw_event_register(struct input_dev *input_dev)
167 return -ENOMEM; 265 return -ENOMEM;
168 266
169 ir->raw->input_dev = input_dev; 267 ir->raw->input_dev = input_dev;
170 INIT_WORK(&ir->raw->rx_work, ir_raw_event_work); 268
171 ir->raw->enabled_protocols = ~0; 269 ir->raw->enabled_protocols = ~0;
172 rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, 270 rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
173 GFP_KERNEL); 271 GFP_KERNEL);
@@ -177,12 +275,21 @@ int ir_raw_event_register(struct input_dev *input_dev)
177 return rc; 275 return rc;
178 } 276 }
179 277
180 spin_lock(&ir_raw_handler_lock); 278 ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw,
279 "rc%u", (unsigned int)ir->devno);
280
281 if (IS_ERR(ir->raw->thread)) {
282 kfree(ir->raw);
283 ir->raw = NULL;
284 return PTR_ERR(ir->raw->thread);
285 }
286
287 mutex_lock(&ir_raw_handler_lock);
181 list_add_tail(&ir->raw->list, &ir_raw_client_list); 288 list_add_tail(&ir->raw->list, &ir_raw_client_list);
182 list_for_each_entry(handler, &ir_raw_handler_list, list) 289 list_for_each_entry(handler, &ir_raw_handler_list, list)
183 if (handler->raw_register) 290 if (handler->raw_register)
184 handler->raw_register(ir->raw->input_dev); 291 handler->raw_register(ir->raw->input_dev);
185 spin_unlock(&ir_raw_handler_lock); 292 mutex_unlock(&ir_raw_handler_lock);
186 293
187 return 0; 294 return 0;
188} 295}
@@ -195,14 +302,14 @@ void ir_raw_event_unregister(struct input_dev *input_dev)
195 if (!ir->raw) 302 if (!ir->raw)
196 return; 303 return;
197 304
198 cancel_work_sync(&ir->raw->rx_work); 305 kthread_stop(ir->raw->thread);
199 306
200 spin_lock(&ir_raw_handler_lock); 307 mutex_lock(&ir_raw_handler_lock);
201 list_del(&ir->raw->list); 308 list_del(&ir->raw->list);
202 list_for_each_entry(handler, &ir_raw_handler_list, list) 309 list_for_each_entry(handler, &ir_raw_handler_list, list)
203 if (handler->raw_unregister) 310 if (handler->raw_unregister)
204 handler->raw_unregister(ir->raw->input_dev); 311 handler->raw_unregister(ir->raw->input_dev);
205 spin_unlock(&ir_raw_handler_lock); 312 mutex_unlock(&ir_raw_handler_lock);
206 313
207 kfifo_free(&ir->raw->kfifo); 314 kfifo_free(&ir->raw->kfifo);
208 kfree(ir->raw); 315 kfree(ir->raw);
@@ -217,13 +324,13 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
217{ 324{
218 struct ir_raw_event_ctrl *raw; 325 struct ir_raw_event_ctrl *raw;
219 326
220 spin_lock(&ir_raw_handler_lock); 327 mutex_lock(&ir_raw_handler_lock);
221 list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); 328 list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
222 if (ir_raw_handler->raw_register) 329 if (ir_raw_handler->raw_register)
223 list_for_each_entry(raw, &ir_raw_client_list, list) 330 list_for_each_entry(raw, &ir_raw_client_list, list)
224 ir_raw_handler->raw_register(raw->input_dev); 331 ir_raw_handler->raw_register(raw->input_dev);
225 available_protocols |= ir_raw_handler->protocols; 332 available_protocols |= ir_raw_handler->protocols;
226 spin_unlock(&ir_raw_handler_lock); 333 mutex_unlock(&ir_raw_handler_lock);
227 334
228 return 0; 335 return 0;
229} 336}
@@ -233,13 +340,13 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
233{ 340{
234 struct ir_raw_event_ctrl *raw; 341 struct ir_raw_event_ctrl *raw;
235 342
236 spin_lock(&ir_raw_handler_lock); 343 mutex_lock(&ir_raw_handler_lock);
237 list_del(&ir_raw_handler->list); 344 list_del(&ir_raw_handler->list);
238 if (ir_raw_handler->raw_unregister) 345 if (ir_raw_handler->raw_unregister)
239 list_for_each_entry(raw, &ir_raw_client_list, list) 346 list_for_each_entry(raw, &ir_raw_client_list, list)
240 ir_raw_handler->raw_unregister(raw->input_dev); 347 ir_raw_handler->raw_unregister(raw->input_dev);
241 available_protocols &= ~ir_raw_handler->protocols; 348 available_protocols &= ~ir_raw_handler->protocols;
242 spin_unlock(&ir_raw_handler_lock); 349 mutex_unlock(&ir_raw_handler_lock);
243} 350}
244EXPORT_SYMBOL(ir_raw_handler_unregister); 351EXPORT_SYMBOL(ir_raw_handler_unregister);
245 352
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
index 6273047e915..96dafc425c8 100644
--- a/drivers/media/IR/ir-sysfs.c
+++ b/drivers/media/IR/ir-sysfs.c
@@ -325,6 +325,7 @@ static int __init ir_core_init(void)
325 325
326 /* Initialize/load the decoders/keymap code that will be used */ 326 /* Initialize/load the decoders/keymap code that will be used */
327 ir_raw_init(); 327 ir_raw_init();
328 ir_rcmap_init();
328 329
329 return 0; 330 return 0;
330} 331}
@@ -332,6 +333,7 @@ static int __init ir_core_init(void)
332static void __exit ir_core_exit(void) 333static void __exit ir_core_exit(void)
333{ 334{
334 class_unregister(&ir_input_class); 335 class_unregister(&ir_input_class);
336 ir_rcmap_cleanup();
335} 337}
336 338
337module_init(ir_core_init); 339module_init(ir_core_init);
diff --git a/drivers/media/IR/keymaps/Makefile b/drivers/media/IR/keymaps/Makefile
index cbee06243b5..950e5d953c6 100644
--- a/drivers/media/IR/keymaps/Makefile
+++ b/drivers/media/IR/keymaps/Makefile
@@ -19,7 +19,6 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
19 rc-dm1105-nec.o \ 19 rc-dm1105-nec.o \
20 rc-dntv-live-dvb-t.o \ 20 rc-dntv-live-dvb-t.o \
21 rc-dntv-live-dvbt-pro.o \ 21 rc-dntv-live-dvbt-pro.o \
22 rc-empty.o \
23 rc-em-terratec.o \ 22 rc-em-terratec.o \
24 rc-encore-enltv2.o \ 23 rc-encore-enltv2.o \
25 rc-encore-enltv.o \ 24 rc-encore-enltv.o \
@@ -59,6 +58,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
59 rc-purpletv.o \ 58 rc-purpletv.o \
60 rc-pv951.o \ 59 rc-pv951.o \
61 rc-rc5-hauppauge-new.o \ 60 rc-rc5-hauppauge-new.o \
61 rc-rc5-streamzap.o \
62 rc-rc5-tv.o \ 62 rc-rc5-tv.o \
63 rc-rc6-mce.o \ 63 rc-rc6-mce.o \
64 rc-real-audio-220-32-keys.o \ 64 rc-real-audio-220-32-keys.o \
diff --git a/drivers/media/IR/keymaps/rc-empty.c b/drivers/media/IR/keymaps/rc-empty.c
deleted file mode 100644
index 3b338d84b47..00000000000
--- a/drivers/media/IR/keymaps/rc-empty.c
+++ /dev/null
@@ -1,44 +0,0 @@
1/* empty.h - Keytable for empty Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/* empty keytable, can be used as placeholder for not-yet created keytables */
16
17static struct ir_scancode empty[] = {
18 { 0x2a, KEY_COFFEE },
19};
20
21static struct rc_keymap empty_map = {
22 .map = {
23 .scan = empty,
24 .size = ARRAY_SIZE(empty),
25 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
26 .name = RC_MAP_EMPTY,
27 }
28};
29
30static int __init init_rc_map_empty(void)
31{
32 return ir_register_map(&empty_map);
33}
34
35static void __exit exit_rc_map_empty(void)
36{
37 ir_unregister_map(&empty_map);
38}
39
40module_init(init_rc_map_empty)
41module_exit(exit_rc_map_empty)
42
43MODULE_LICENSE("GPL");
44MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/IR/keymaps/rc-rc5-streamzap.c b/drivers/media/IR/keymaps/rc-rc5-streamzap.c
new file mode 100644
index 00000000000..4c19c58b46d
--- /dev/null
+++ b/drivers/media/IR/keymaps/rc-rc5-streamzap.c
@@ -0,0 +1,81 @@
1/* rc-rc5-streamzap.c - Keytable for Streamzap PC Remote, for use
2 * with the Streamzap PC Remote IR Receiver.
3 *
4 * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <media/rc-map.h>
13
14static struct ir_scancode rc5_streamzap[] = {
15/*
16 * FIXME: The Streamzap remote isn't actually true RC-5, it has an extra
17 * bit in it, which presently throws the in-kernel RC-5 decoder for a loop.
18 * We either have to enhance the decoder to support it, add a new decoder,
19 * or just rely on lirc userspace decoding.
20 */
21 { 0x00, KEY_NUMERIC_0 },
22 { 0x01, KEY_NUMERIC_1 },
23 { 0x02, KEY_NUMERIC_2 },
24 { 0x03, KEY_NUMERIC_3 },
25 { 0x04, KEY_NUMERIC_4 },
26 { 0x05, KEY_NUMERIC_5 },
27 { 0x06, KEY_NUMERIC_6 },
28 { 0x07, KEY_NUMERIC_7 },
29 { 0x08, KEY_NUMERIC_8 },
30 { 0x0a, KEY_POWER },
31 { 0x0b, KEY_MUTE },
32 { 0x0c, KEY_CHANNELUP },
33 { 0x0d, KEY_VOLUMEUP },
34 { 0x0e, KEY_CHANNELDOWN },
35 { 0x0f, KEY_VOLUMEDOWN },
36 { 0x10, KEY_UP },
37 { 0x11, KEY_LEFT },
38 { 0x12, KEY_OK },
39 { 0x13, KEY_RIGHT },
40 { 0x14, KEY_DOWN },
41 { 0x15, KEY_MENU },
42 { 0x16, KEY_EXIT },
43 { 0x17, KEY_PLAY },
44 { 0x18, KEY_PAUSE },
45 { 0x19, KEY_STOP },
46 { 0x1a, KEY_BACK },
47 { 0x1b, KEY_FORWARD },
48 { 0x1c, KEY_RECORD },
49 { 0x1d, KEY_REWIND },
50 { 0x1e, KEY_FASTFORWARD },
51 { 0x20, KEY_RED },
52 { 0x21, KEY_GREEN },
53 { 0x22, KEY_YELLOW },
54 { 0x23, KEY_BLUE },
55
56};
57
58static struct rc_keymap rc5_streamzap_map = {
59 .map = {
60 .scan = rc5_streamzap,
61 .size = ARRAY_SIZE(rc5_streamzap),
62 .ir_type = IR_TYPE_RC5,
63 .name = RC_MAP_RC5_STREAMZAP,
64 }
65};
66
67static int __init init_rc_map_rc5_streamzap(void)
68{
69 return ir_register_map(&rc5_streamzap_map);
70}
71
72static void __exit exit_rc_map_rc5_streamzap(void)
73{
74 ir_unregister_map(&rc5_streamzap_map);
75}
76
77module_init(init_rc_map_rc5_streamzap)
78module_exit(exit_rc_map_rc5_streamzap)
79
80MODULE_LICENSE("GPL");
81MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff --git a/drivers/media/IR/keymaps/rc-rc6-mce.c b/drivers/media/IR/keymaps/rc-rc6-mce.c
index c6726a8039b..64264f7f838 100644
--- a/drivers/media/IR/keymaps/rc-rc6-mce.c
+++ b/drivers/media/IR/keymaps/rc-rc6-mce.c
@@ -74,6 +74,8 @@ static struct ir_scancode rc6_mce[] = {
74 { 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */ 74 { 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */
75 { 0x800f044d, KEY_TITLE }, 75 { 0x800f044d, KEY_TITLE },
76 76
77 { 0x800f044e, KEY_PRINT }, /* Print - HP OEM version of remote */
78
77 { 0x800f040c, KEY_POWER }, 79 { 0x800f040c, KEY_POWER },
78 { 0x800f040d, KEY_PROG1 }, /* Windows MCE button */ 80 { 0x800f040d, KEY_PROG1 }, /* Windows MCE button */
79 81
diff --git a/drivers/media/IR/mceusb.c b/drivers/media/IR/mceusb.c
index 78bf7f77a1a..ac6bb2c01a4 100644
--- a/drivers/media/IR/mceusb.c
+++ b/drivers/media/IR/mceusb.c
@@ -228,7 +228,6 @@ static struct usb_device_id std_tx_mask_list[] = {
228/* data structure for each usb transceiver */ 228/* data structure for each usb transceiver */
229struct mceusb_dev { 229struct mceusb_dev {
230 /* ir-core bits */ 230 /* ir-core bits */
231 struct ir_input_dev *irdev;
232 struct ir_dev_props *props; 231 struct ir_dev_props *props;
233 struct ir_raw_event rawir; 232 struct ir_raw_event rawir;
234 233
@@ -428,7 +427,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
428 } 427 }
429} 428}
430 429
431static void usb_async_callback(struct urb *urb, struct pt_regs *regs) 430static void mce_async_callback(struct urb *urb, struct pt_regs *regs)
432{ 431{
433 struct mceusb_dev *ir; 432 struct mceusb_dev *ir;
434 int len; 433 int len;
@@ -477,7 +476,7 @@ static void mce_request_packet(struct mceusb_dev *ir,
477 /* outbound data */ 476 /* outbound data */
478 usb_fill_int_urb(async_urb, ir->usbdev, 477 usb_fill_int_urb(async_urb, ir->usbdev,
479 usb_sndintpipe(ir->usbdev, ep->bEndpointAddress), 478 usb_sndintpipe(ir->usbdev, ep->bEndpointAddress),
480 async_buf, size, (usb_complete_t) usb_async_callback, 479 async_buf, size, (usb_complete_t)mce_async_callback,
481 ir, ep->bInterval); 480 ir, ep->bInterval);
482 memcpy(async_buf, data, size); 481 memcpy(async_buf, data, size);
483 482
@@ -739,7 +738,7 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
739 738
740 if (ir->send_flags == RECV_FLAG_IN_PROGRESS) { 739 if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {
741 ir->send_flags = SEND_FLAG_COMPLETE; 740 ir->send_flags = SEND_FLAG_COMPLETE;
742 dev_dbg(&ir->irdev->dev, "setup answer received %d bytes\n", 741 dev_dbg(ir->dev, "setup answer received %d bytes\n",
743 buf_len); 742 buf_len);
744 } 743 }
745 744
@@ -861,7 +860,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
861{ 860{
862 struct input_dev *idev; 861 struct input_dev *idev;
863 struct ir_dev_props *props; 862 struct ir_dev_props *props;
864 struct ir_input_dev *irdev;
865 struct device *dev = ir->dev; 863 struct device *dev = ir->dev;
866 int ret = -ENODEV; 864 int ret = -ENODEV;
867 865
@@ -878,12 +876,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
878 goto props_alloc_failed; 876 goto props_alloc_failed;
879 } 877 }
880 878
881 irdev = kzalloc(sizeof(struct ir_input_dev), GFP_KERNEL);
882 if (!irdev) {
883 dev_err(dev, "remote ir input dev allocation failed\n");
884 goto ir_dev_alloc_failed;
885 }
886
887 snprintf(ir->name, sizeof(ir->name), "Media Center Ed. eHome " 879 snprintf(ir->name, sizeof(ir->name), "Media Center Ed. eHome "
888 "Infrared Remote Transceiver (%04x:%04x)", 880 "Infrared Remote Transceiver (%04x:%04x)",
889 le16_to_cpu(ir->usbdev->descriptor.idVendor), 881 le16_to_cpu(ir->usbdev->descriptor.idVendor),
@@ -902,9 +894,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
902 props->tx_ir = mceusb_tx_ir; 894 props->tx_ir = mceusb_tx_ir;
903 895
904 ir->props = props; 896 ir->props = props;
905 ir->irdev = irdev;
906
907 input_set_drvdata(idev, irdev);
908 897
909 ret = ir_input_register(idev, RC_MAP_RC6_MCE, props, DRIVER_NAME); 898 ret = ir_input_register(idev, RC_MAP_RC6_MCE, props, DRIVER_NAME);
910 if (ret < 0) { 899 if (ret < 0) {
@@ -915,8 +904,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
915 return idev; 904 return idev;
916 905
917irdev_failed: 906irdev_failed:
918 kfree(irdev);
919ir_dev_alloc_failed:
920 kfree(props); 907 kfree(props);
921props_alloc_failed: 908props_alloc_failed:
922 input_free_device(idev); 909 input_free_device(idev);
@@ -932,7 +919,6 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
932 struct usb_endpoint_descriptor *ep = NULL; 919 struct usb_endpoint_descriptor *ep = NULL;
933 struct usb_endpoint_descriptor *ep_in = NULL; 920 struct usb_endpoint_descriptor *ep_in = NULL;
934 struct usb_endpoint_descriptor *ep_out = NULL; 921 struct usb_endpoint_descriptor *ep_out = NULL;
935 struct usb_host_config *config;
936 struct mceusb_dev *ir = NULL; 922 struct mceusb_dev *ir = NULL;
937 int pipe, maxp, i; 923 int pipe, maxp, i;
938 char buf[63], name[128] = ""; 924 char buf[63], name[128] = "";
@@ -942,7 +928,6 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
942 928
943 dev_dbg(&intf->dev, ": %s called\n", __func__); 929 dev_dbg(&intf->dev, ": %s called\n", __func__);
944 930
945 config = dev->actconfig;
946 idesc = intf->cur_altsetting; 931 idesc = intf->cur_altsetting;
947 932
948 is_gen3 = usb_match_id(intf, gen3_list) ? 1 : 0; 933 is_gen3 = usb_match_id(intf, gen3_list) ? 1 : 0;
diff --git a/drivers/media/IR/rc-map.c b/drivers/media/IR/rc-map.c
index 46a8f1524b5..689143f2fff 100644
--- a/drivers/media/IR/rc-map.c
+++ b/drivers/media/IR/rc-map.c
@@ -82,3 +82,26 @@ void ir_unregister_map(struct rc_keymap *map)
82} 82}
83EXPORT_SYMBOL_GPL(ir_unregister_map); 83EXPORT_SYMBOL_GPL(ir_unregister_map);
84 84
85
86static struct ir_scancode empty[] = {
87 { 0x2a, KEY_COFFEE },
88};
89
90static struct rc_keymap empty_map = {
91 .map = {
92 .scan = empty,
93 .size = ARRAY_SIZE(empty),
94 .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
95 .name = RC_MAP_EMPTY,
96 }
97};
98
99int ir_rcmap_init(void)
100{
101 return ir_register_map(&empty_map);
102}
103
104void ir_rcmap_cleanup(void)
105{
106 ir_unregister_map(&empty_map);
107}
diff --git a/drivers/media/IR/streamzap.c b/drivers/media/IR/streamzap.c
new file mode 100644
index 00000000000..058e29fd478
--- /dev/null
+++ b/drivers/media/IR/streamzap.c
@@ -0,0 +1,741 @@
1/*
2 * Streamzap Remote Control driver
3 *
4 * Copyright (c) 2005 Christoph Bartelmus <lirc@bartelmus.de>
5 * Copyright (c) 2010 Jarod Wilson <jarod@wilsonet.com>
6 *
7 * This driver was based on the work of Greg Wickham and Adrian
8 * Dewhurst. It was substantially rewritten to support correct signal
9 * gaps and now maintains a delay buffer, which is used to present
10 * consistent timing behaviour to user space applications. Without the
11 * delay buffer an ugly hack would be required in lircd, which can
12 * cause sluggish signal decoding in certain situations.
13 *
14 * Ported to in-kernel ir-core interface by Jarod Wilson
15 *
16 * This driver is based on the USB skeleton driver packaged with the
17 * kernel; copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com)
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 */
33
34#include <linux/device.h>
35#include <linux/module.h>
36#include <linux/slab.h>
37#include <linux/usb.h>
38#include <linux/input.h>
39#include <media/ir-core.h>
40
41#define DRIVER_VERSION "1.60"
42#define DRIVER_NAME "streamzap"
43#define DRIVER_DESC "Streamzap Remote Control driver"
44
45#ifdef CONFIG_USB_DEBUG
46static int debug = 1;
47#else
48static int debug;
49#endif
50
51#define USB_STREAMZAP_VENDOR_ID 0x0e9c
52#define USB_STREAMZAP_PRODUCT_ID 0x0000
53
54/* table of devices that work with this driver */
55static struct usb_device_id streamzap_table[] = {
56 /* Streamzap Remote Control */
57 { USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) },
58 /* Terminating entry */
59 { }
60};
61
62MODULE_DEVICE_TABLE(usb, streamzap_table);
63
64#define STREAMZAP_PULSE_MASK 0xf0
65#define STREAMZAP_SPACE_MASK 0x0f
66#define STREAMZAP_TIMEOUT 0xff
67#define STREAMZAP_RESOLUTION 256
68
69/* number of samples buffered */
70#define SZ_BUF_LEN 128
71
72enum StreamzapDecoderState {
73 PulseSpace,
74 FullPulse,
75 FullSpace,
76 IgnorePulse
77};
78
79/* structure to hold our device specific stuff */
80struct streamzap_ir {
81
82 /* ir-core */
83 struct ir_dev_props *props;
84 struct ir_raw_event rawir;
85
86 /* core device info */
87 struct device *dev;
88 struct input_dev *idev;
89
90 /* usb */
91 struct usb_device *usbdev;
92 struct usb_interface *interface;
93 struct usb_endpoint_descriptor *endpoint;
94 struct urb *urb_in;
95
96 /* buffer & dma */
97 unsigned char *buf_in;
98 dma_addr_t dma_in;
99 unsigned int buf_in_len;
100
101 /* timer used to support delay buffering */
102 struct timer_list delay_timer;
103 bool timer_running;
104 spinlock_t timer_lock;
105 struct timer_list flush_timer;
106 bool flush;
107
108 /* delay buffer */
109 struct kfifo fifo;
110 bool fifo_initialized;
111
112 /* track what state we're in */
113 enum StreamzapDecoderState decoder_state;
114 /* tracks whether we are currently receiving some signal */
115 bool idle;
116 /* sum of signal lengths received since signal start */
117 unsigned long sum;
118 /* start time of signal; necessary for gap tracking */
119 struct timeval signal_last;
120 struct timeval signal_start;
121 /* bool timeout_enabled; */
122
123 char name[128];
124 char phys[64];
125};
126
127
128/* local function prototypes */
129static int streamzap_probe(struct usb_interface *interface,
130 const struct usb_device_id *id);
131static void streamzap_disconnect(struct usb_interface *interface);
132static void streamzap_callback(struct urb *urb);
133static int streamzap_suspend(struct usb_interface *intf, pm_message_t message);
134static int streamzap_resume(struct usb_interface *intf);
135
136/* usb specific object needed to register this driver with the usb subsystem */
137static struct usb_driver streamzap_driver = {
138 .name = DRIVER_NAME,
139 .probe = streamzap_probe,
140 .disconnect = streamzap_disconnect,
141 .suspend = streamzap_suspend,
142 .resume = streamzap_resume,
143 .id_table = streamzap_table,
144};
145
146static void streamzap_stop_timer(struct streamzap_ir *sz)
147{
148 unsigned long flags;
149
150 spin_lock_irqsave(&sz->timer_lock, flags);
151 if (sz->timer_running) {
152 sz->timer_running = false;
153 spin_unlock_irqrestore(&sz->timer_lock, flags);
154 del_timer_sync(&sz->delay_timer);
155 } else {
156 spin_unlock_irqrestore(&sz->timer_lock, flags);
157 }
158}
159
160static void streamzap_flush_timeout(unsigned long arg)
161{
162 struct streamzap_ir *sz = (struct streamzap_ir *)arg;
163
164 dev_info(sz->dev, "%s: callback firing\n", __func__);
165
166 /* finally start accepting data */
167 sz->flush = false;
168}
169
170static void streamzap_delay_timeout(unsigned long arg)
171{
172 struct streamzap_ir *sz = (struct streamzap_ir *)arg;
173 struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
174 unsigned long flags;
175 int len, ret;
176 static unsigned long delay;
177 bool wake = false;
178
179 /* deliver data every 10 ms */
180 delay = msecs_to_jiffies(10);
181
182 spin_lock_irqsave(&sz->timer_lock, flags);
183
184 if (kfifo_len(&sz->fifo) > 0) {
185 ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
186 if (ret != sizeof(rawir))
187 dev_err(sz->dev, "Problem w/kfifo_out...\n");
188 ir_raw_event_store(sz->idev, &rawir);
189 wake = true;
190 }
191
192 len = kfifo_len(&sz->fifo);
193 if (len > 0) {
194 while ((len < SZ_BUF_LEN / 2) &&
195 (len < SZ_BUF_LEN * sizeof(int))) {
196 ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
197 if (ret != sizeof(rawir))
198 dev_err(sz->dev, "Problem w/kfifo_out...\n");
199 ir_raw_event_store(sz->idev, &rawir);
200 wake = true;
201 len = kfifo_len(&sz->fifo);
202 }
203 if (sz->timer_running)
204 mod_timer(&sz->delay_timer, jiffies + delay);
205
206 } else {
207 sz->timer_running = false;
208 }
209
210 if (wake)
211 ir_raw_event_handle(sz->idev);
212
213 spin_unlock_irqrestore(&sz->timer_lock, flags);
214}
215
216static void streamzap_flush_delay_buffer(struct streamzap_ir *sz)
217{
218 struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
219 bool wake = false;
220 int ret;
221
222 while (kfifo_len(&sz->fifo) > 0) {
223 ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
224 if (ret != sizeof(rawir))
225 dev_err(sz->dev, "Problem w/kfifo_out...\n");
226 ir_raw_event_store(sz->idev, &rawir);
227 wake = true;
228 }
229
230 if (wake)
231 ir_raw_event_handle(sz->idev);
232}
233
234static void sz_push(struct streamzap_ir *sz)
235{
236 struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
237 unsigned long flags;
238 int ret;
239
240 spin_lock_irqsave(&sz->timer_lock, flags);
241 if (kfifo_len(&sz->fifo) >= sizeof(int) * SZ_BUF_LEN) {
242 ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
243 if (ret != sizeof(rawir))
244 dev_err(sz->dev, "Problem w/kfifo_out...\n");
245 ir_raw_event_store(sz->idev, &rawir);
246 }
247
248 kfifo_in(&sz->fifo, &sz->rawir, sizeof(rawir));
249
250 if (!sz->timer_running) {
251 sz->delay_timer.expires = jiffies + (HZ / 10);
252 add_timer(&sz->delay_timer);
253 sz->timer_running = true;
254 }
255
256 spin_unlock_irqrestore(&sz->timer_lock, flags);
257}
258
259static void sz_push_full_pulse(struct streamzap_ir *sz,
260 unsigned char value)
261{
262 if (sz->idle) {
263 long deltv;
264
265 sz->signal_last = sz->signal_start;
266 do_gettimeofday(&sz->signal_start);
267
268 deltv = sz->signal_start.tv_sec - sz->signal_last.tv_sec;
269 sz->rawir.pulse = false;
270 if (deltv > 15) {
271 /* really long time */
272 sz->rawir.duration = IR_MAX_DURATION;
273 } else {
274 sz->rawir.duration = (int)(deltv * 1000000 +
275 sz->signal_start.tv_usec -
276 sz->signal_last.tv_usec);
277 sz->rawir.duration -= sz->sum;
278 sz->rawir.duration *= 1000;
279 sz->rawir.duration &= IR_MAX_DURATION;
280 }
281 dev_dbg(sz->dev, "ls %u\n", sz->rawir.duration);
282 sz_push(sz);
283
284 sz->idle = 0;
285 sz->sum = 0;
286 }
287
288 sz->rawir.pulse = true;
289 sz->rawir.duration = ((int) value) * STREAMZAP_RESOLUTION;
290 sz->rawir.duration += STREAMZAP_RESOLUTION / 2;
291 sz->sum += sz->rawir.duration;
292 sz->rawir.duration *= 1000;
293 sz->rawir.duration &= IR_MAX_DURATION;
294 dev_dbg(sz->dev, "p %u\n", sz->rawir.duration);
295 sz_push(sz);
296}
297
298static void sz_push_half_pulse(struct streamzap_ir *sz,
299 unsigned char value)
300{
301 sz_push_full_pulse(sz, (value & STREAMZAP_PULSE_MASK) >> 4);
302}
303
304static void sz_push_full_space(struct streamzap_ir *sz,
305 unsigned char value)
306{
307 sz->rawir.pulse = false;
308 sz->rawir.duration = ((int) value) * STREAMZAP_RESOLUTION;
309 sz->rawir.duration += STREAMZAP_RESOLUTION / 2;
310 sz->sum += sz->rawir.duration;
311 sz->rawir.duration *= 1000;
312 dev_dbg(sz->dev, "s %u\n", sz->rawir.duration);
313 sz_push(sz);
314}
315
316static void sz_push_half_space(struct streamzap_ir *sz,
317 unsigned long value)
318{
319 sz_push_full_space(sz, value & STREAMZAP_SPACE_MASK);
320}
321
322/**
323 * streamzap_callback - usb IRQ handler callback
324 *
325 * This procedure is invoked on reception of data from
326 * the usb remote.
327 */
328static void streamzap_callback(struct urb *urb)
329{
330 struct streamzap_ir *sz;
331 unsigned int i;
332 int len;
333 #if 0
334 static int timeout = (((STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION) &
335 IR_MAX_DURATION) | 0x03000000);
336 #endif
337
338 if (!urb)
339 return;
340
341 sz = urb->context;
342 len = urb->actual_length;
343
344 switch (urb->status) {
345 case -ECONNRESET:
346 case -ENOENT:
347 case -ESHUTDOWN:
348 /*
349 * this urb is terminated, clean up.
350 * sz might already be invalid at this point
351 */
352 dev_err(sz->dev, "urb terminated, status: %d\n", urb->status);
353 return;
354 default:
355 break;
356 }
357
358 dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
359 if (!sz->flush) {
360 for (i = 0; i < urb->actual_length; i++) {
361 dev_dbg(sz->dev, "%d: %x\n", i,
362 (unsigned char)sz->buf_in[i]);
363 switch (sz->decoder_state) {
364 case PulseSpace:
365 if ((sz->buf_in[i] & STREAMZAP_PULSE_MASK) ==
366 STREAMZAP_PULSE_MASK) {
367 sz->decoder_state = FullPulse;
368 continue;
369 } else if ((sz->buf_in[i] & STREAMZAP_SPACE_MASK)
370 == STREAMZAP_SPACE_MASK) {
371 sz_push_half_pulse(sz, sz->buf_in[i]);
372 sz->decoder_state = FullSpace;
373 continue;
374 } else {
375 sz_push_half_pulse(sz, sz->buf_in[i]);
376 sz_push_half_space(sz, sz->buf_in[i]);
377 }
378 break;
379 case FullPulse:
380 sz_push_full_pulse(sz, sz->buf_in[i]);
381 sz->decoder_state = IgnorePulse;
382 break;
383 case FullSpace:
384 if (sz->buf_in[i] == STREAMZAP_TIMEOUT) {
385 sz->idle = 1;
386 streamzap_stop_timer(sz);
387 #if 0
388 if (sz->timeout_enabled) {
389 sz->rawir.pulse = false;
390 sz->rawir.duration = timeout;
391 sz->rawir.duration *= 1000;
392 sz_push(sz);
393 }
394 #endif
395 streamzap_flush_delay_buffer(sz);
396 } else
397 sz_push_full_space(sz, sz->buf_in[i]);
398 sz->decoder_state = PulseSpace;
399 break;
400 case IgnorePulse:
401 if ((sz->buf_in[i]&STREAMZAP_SPACE_MASK) ==
402 STREAMZAP_SPACE_MASK) {
403 sz->decoder_state = FullSpace;
404 continue;
405 }
406 sz_push_half_space(sz, sz->buf_in[i]);
407 sz->decoder_state = PulseSpace;
408 break;
409 }
410 }
411 }
412
413 usb_submit_urb(urb, GFP_ATOMIC);
414
415 return;
416}
417
418static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz)
419{
420 struct input_dev *idev;
421 struct ir_dev_props *props;
422 struct device *dev = sz->dev;
423 int ret;
424
425 idev = input_allocate_device();
426 if (!idev) {
427 dev_err(dev, "remote input dev allocation failed\n");
428 goto idev_alloc_failed;
429 }
430
431 props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
432 if (!props) {
433 dev_err(dev, "remote ir dev props allocation failed\n");
434 goto props_alloc_failed;
435 }
436
437 snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared "
438 "Receiver (%04x:%04x)",
439 le16_to_cpu(sz->usbdev->descriptor.idVendor),
440 le16_to_cpu(sz->usbdev->descriptor.idProduct));
441
442 idev->name = sz->name;
443 usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys));
444 strlcat(sz->phys, "/input0", sizeof(sz->phys));
445 idev->phys = sz->phys;
446
447 props->priv = sz;
448 props->driver_type = RC_DRIVER_IR_RAW;
449 /* FIXME: not sure about supported protocols, check on this */
450 props->allowed_protos = IR_TYPE_RC5 | IR_TYPE_RC6;
451
452 sz->props = props;
453
454 ret = ir_input_register(idev, RC_MAP_RC5_STREAMZAP, props, DRIVER_NAME);
455 if (ret < 0) {
456 dev_err(dev, "remote input device register failed\n");
457 goto irdev_failed;
458 }
459
460 return idev;
461
462irdev_failed:
463 kfree(props);
464props_alloc_failed:
465 input_free_device(idev);
466idev_alloc_failed:
467 return NULL;
468}
469
470static int streamzap_delay_buf_init(struct streamzap_ir *sz)
471{
472 int ret;
473
474 ret = kfifo_alloc(&sz->fifo, sizeof(int) * SZ_BUF_LEN,
475 GFP_KERNEL);
476 if (ret == 0)
477 sz->fifo_initialized = 1;
478
479 return ret;
480}
481
482static void streamzap_start_flush_timer(struct streamzap_ir *sz)
483{
484 sz->flush_timer.expires = jiffies + HZ;
485 sz->flush = true;
486 add_timer(&sz->flush_timer);
487
488 sz->urb_in->dev = sz->usbdev;
489 if (usb_submit_urb(sz->urb_in, GFP_ATOMIC))
490 dev_err(sz->dev, "urb submit failed\n");
491}
492
493/**
494 * streamzap_probe
495 *
496 * Called by usb-core to associated with a candidate device
497 * On any failure the return value is the ERROR
498 * On success return 0
499 */
500static int __devinit streamzap_probe(struct usb_interface *intf,
501 const struct usb_device_id *id)
502{
503 struct usb_device *usbdev = interface_to_usbdev(intf);
504 struct usb_host_interface *iface_host;
505 struct streamzap_ir *sz = NULL;
506 char buf[63], name[128] = "";
507 int retval = -ENOMEM;
508 int pipe, maxp;
509
510 /* Allocate space for device driver specific data */
511 sz = kzalloc(sizeof(struct streamzap_ir), GFP_KERNEL);
512 if (!sz)
513 return -ENOMEM;
514
515 sz->usbdev = usbdev;
516 sz->interface = intf;
517
518 /* Check to ensure endpoint information matches requirements */
519 iface_host = intf->cur_altsetting;
520
521 if (iface_host->desc.bNumEndpoints != 1) {
522 dev_err(&intf->dev, "%s: Unexpected desc.bNumEndpoints (%d)\n",
523 __func__, iface_host->desc.bNumEndpoints);
524 retval = -ENODEV;
525 goto free_sz;
526 }
527
528 sz->endpoint = &(iface_host->endpoint[0].desc);
529 if ((sz->endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
530 != USB_DIR_IN) {
531 dev_err(&intf->dev, "%s: endpoint doesn't match input device "
532 "02%02x\n", __func__, sz->endpoint->bEndpointAddress);
533 retval = -ENODEV;
534 goto free_sz;
535 }
536
537 if ((sz->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
538 != USB_ENDPOINT_XFER_INT) {
539 dev_err(&intf->dev, "%s: endpoint attributes don't match xfer "
540 "02%02x\n", __func__, sz->endpoint->bmAttributes);
541 retval = -ENODEV;
542 goto free_sz;
543 }
544
545 pipe = usb_rcvintpipe(usbdev, sz->endpoint->bEndpointAddress);
546 maxp = usb_maxpacket(usbdev, pipe, usb_pipeout(pipe));
547
548 if (maxp == 0) {
549 dev_err(&intf->dev, "%s: endpoint Max Packet Size is 0!?!\n",
550 __func__);
551 retval = -ENODEV;
552 goto free_sz;
553 }
554
555 /* Allocate the USB buffer and IRQ URB */
556 sz->buf_in = usb_alloc_coherent(usbdev, maxp, GFP_ATOMIC, &sz->dma_in);
557 if (!sz->buf_in)
558 goto free_sz;
559
560 sz->urb_in = usb_alloc_urb(0, GFP_KERNEL);
561 if (!sz->urb_in)
562 goto free_buf_in;
563
564 sz->dev = &intf->dev;
565 sz->buf_in_len = maxp;
566
567 if (usbdev->descriptor.iManufacturer
568 && usb_string(usbdev, usbdev->descriptor.iManufacturer,
569 buf, sizeof(buf)) > 0)
570 strlcpy(name, buf, sizeof(name));
571
572 if (usbdev->descriptor.iProduct
573 && usb_string(usbdev, usbdev->descriptor.iProduct,
574 buf, sizeof(buf)) > 0)
575 snprintf(name + strlen(name), sizeof(name) - strlen(name),
576 " %s", buf);
577
578 retval = streamzap_delay_buf_init(sz);
579 if (retval) {
580 dev_err(&intf->dev, "%s: delay buffer init failed\n", __func__);
581 goto free_urb_in;
582 }
583
584 sz->idev = streamzap_init_input_dev(sz);
585 if (!sz->idev)
586 goto input_dev_fail;
587
588 sz->idle = true;
589 sz->decoder_state = PulseSpace;
590 #if 0
591 /* not yet supported, depends on patches from maxim */
592 /* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */
593 sz->timeout_enabled = false;
594 sz->min_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION * 1000;
595 sz->max_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION * 1000;
596 #endif
597
598 init_timer(&sz->delay_timer);
599 sz->delay_timer.function = streamzap_delay_timeout;
600 sz->delay_timer.data = (unsigned long)sz;
601 spin_lock_init(&sz->timer_lock);
602
603 init_timer(&sz->flush_timer);
604 sz->flush_timer.function = streamzap_flush_timeout;
605 sz->flush_timer.data = (unsigned long)sz;
606
607 do_gettimeofday(&sz->signal_start);
608
609 /* Complete final initialisations */
610 usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in,
611 maxp, (usb_complete_t)streamzap_callback,
612 sz, sz->endpoint->bInterval);
613 sz->urb_in->transfer_dma = sz->dma_in;
614 sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
615
616 usb_set_intfdata(intf, sz);
617
618 streamzap_start_flush_timer(sz);
619
620 dev_info(sz->dev, "Registered %s on usb%d:%d\n", name,
621 usbdev->bus->busnum, usbdev->devnum);
622
623 return 0;
624
625input_dev_fail:
626 kfifo_free(&sz->fifo);
627free_urb_in:
628 usb_free_urb(sz->urb_in);
629free_buf_in:
630 usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in);
631free_sz:
632 kfree(sz);
633
634 return retval;
635}
636
637/**
638 * streamzap_disconnect
639 *
640 * Called by the usb core when the device is removed from the system.
641 *
642 * This routine guarantees that the driver will not submit any more urbs
643 * by clearing dev->usbdev. It is also supposed to terminate any currently
644 * active urbs. Unfortunately, usb_bulk_msg(), used in streamzap_read(),
645 * does not provide any way to do this.
646 */
647static void streamzap_disconnect(struct usb_interface *interface)
648{
649 struct streamzap_ir *sz = usb_get_intfdata(interface);
650 struct usb_device *usbdev = interface_to_usbdev(interface);
651
652 usb_set_intfdata(interface, NULL);
653
654 if (!sz)
655 return;
656
657 if (sz->flush) {
658 sz->flush = false;
659 del_timer_sync(&sz->flush_timer);
660 }
661
662 streamzap_stop_timer(sz);
663
664 sz->usbdev = NULL;
665 ir_input_unregister(sz->idev);
666 usb_kill_urb(sz->urb_in);
667 usb_free_urb(sz->urb_in);
668 usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in);
669
670 kfree(sz);
671}
672
673static int streamzap_suspend(struct usb_interface *intf, pm_message_t message)
674{
675 struct streamzap_ir *sz = usb_get_intfdata(intf);
676
677 if (sz->flush) {
678 sz->flush = false;
679 del_timer_sync(&sz->flush_timer);
680 }
681
682 streamzap_stop_timer(sz);
683
684 usb_kill_urb(sz->urb_in);
685
686 return 0;
687}
688
689static int streamzap_resume(struct usb_interface *intf)
690{
691 struct streamzap_ir *sz = usb_get_intfdata(intf);
692
693 if (sz->fifo_initialized)
694 kfifo_reset(&sz->fifo);
695
696 sz->flush_timer.expires = jiffies + HZ;
697 sz->flush = true;
698 add_timer(&sz->flush_timer);
699
700 if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) {
701 dev_err(sz->dev, "Error sumbiting urb\n");
702 return -EIO;
703 }
704
705 return 0;
706}
707
708/**
709 * streamzap_init
710 */
711static int __init streamzap_init(void)
712{
713 int ret;
714
715 /* register this driver with the USB subsystem */
716 ret = usb_register(&streamzap_driver);
717 if (ret < 0)
718 printk(KERN_ERR DRIVER_NAME ": usb register failed, "
719 "result = %d\n", ret);
720
721 return ret;
722}
723
724/**
725 * streamzap_exit
726 */
727static void __exit streamzap_exit(void)
728{
729 usb_deregister(&streamzap_driver);
730}
731
732
733module_init(streamzap_init);
734module_exit(streamzap_exit);
735
736MODULE_AUTHOR("Jarod Wilson <jarod@wilsonet.com>");
737MODULE_DESCRIPTION(DRIVER_DESC);
738MODULE_LICENSE("GPL");
739
740module_param(debug, bool, S_IRUGO | S_IWUSR);
741MODULE_PARM_DESC(debug, "Enable debugging messages");
diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig
index 409a4261e5b..b3ed5daaacf 100644
--- a/drivers/media/common/tuners/Kconfig
+++ b/drivers/media/common/tuners/Kconfig
@@ -34,7 +34,7 @@ config MEDIA_TUNER
34menuconfig MEDIA_TUNER_CUSTOMISE 34menuconfig MEDIA_TUNER_CUSTOMISE
35 bool "Customize analog and hybrid tuner modules to build" 35 bool "Customize analog and hybrid tuner modules to build"
36 depends on MEDIA_TUNER 36 depends on MEDIA_TUNER
37 default n 37 default y if EMBEDDED
38 help 38 help
39 This allows the user to deselect tuner drivers unnecessary 39 This allows the user to deselect tuner drivers unnecessary
40 for their hardware from the build. Use this option with care 40 for their hardware from the build. Use this option with care
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 248a2a9d841..caa4e18ed1c 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -1763,7 +1763,15 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
1763 .frequency_min = 137000000, 1763 .frequency_min = 137000000,
1764 .frequency_max = 858000000, 1764 .frequency_max = 858000000,
1765 .frequency_stepsize = 166667, 1765 .frequency_stepsize = 166667,
1766 .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO 1766 .caps = FE_CAN_FEC_AUTO |
1767 FE_CAN_QAM_AUTO |
1768 FE_CAN_QAM_16 |
1769 FE_CAN_QAM_32 |
1770 FE_CAN_QAM_64 |
1771 FE_CAN_QAM_128 |
1772 FE_CAN_QAM_256 |
1773 FE_CAN_TRANSMISSION_MODE_AUTO |
1774 FE_CAN_GUARD_INTERVAL_AUTO
1767 }, 1775 },
1768 1776
1769 .release = dst_release, 1777 .release = dst_release,
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 51d578a758a..b5f6a04f9c1 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -1,7 +1,7 @@
1config DVB_FE_CUSTOMISE 1config DVB_FE_CUSTOMISE
2 bool "Customise the frontend modules to build" 2 bool "Customise the frontend modules to build"
3 depends on DVB_CORE 3 depends on DVB_CORE
4 default N 4 default y if EMBEDDED
5 help 5 help
6 This allows the user to select/deselect frontend drivers for their 6 This allows the user to select/deselect frontend drivers for their
7 hardware from the build. 7 hardware from the build.
diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c
index 7f2c94a15ab..d93468cd3a8 100644
--- a/drivers/media/dvb/siano/smscoreapi.c
+++ b/drivers/media/dvb/siano/smscoreapi.c
@@ -1113,9 +1113,11 @@ struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
1113 */ 1113 */
1114 1114
1115 prepare_to_wait(&coredev->buffer_mng_waitq, &wait, TASK_INTERRUPTIBLE); 1115 prepare_to_wait(&coredev->buffer_mng_waitq, &wait, TASK_INTERRUPTIBLE);
1116 1116 if (list_empty(&coredev->buffers)) {
1117 if (list_empty(&coredev->buffers)) 1117 spin_unlock_irqrestore(&coredev->bufferslock, flags);
1118 schedule(); 1118 schedule();
1119 spin_lock_irqsave(&coredev->bufferslock, flags);
1120 }
1119 1121
1120 finish_wait(&coredev->buffer_mng_waitq, &wait); 1122 finish_wait(&coredev->buffer_mng_waitq, &wait);
1121 1123
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 2e15903b976..f6e4d047535 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -83,7 +83,7 @@ config VIDEO_FIXED_MINOR_RANGES
83 83
84config VIDEO_HELPER_CHIPS_AUTO 84config VIDEO_HELPER_CHIPS_AUTO
85 bool "Autoselect pertinent encoders/decoders and other helper chips" 85 bool "Autoselect pertinent encoders/decoders and other helper chips"
86 default y 86 default y if !EMBEDDED
87 ---help--- 87 ---help---
88 Most video cards may require additional modules to encode or 88 Most video cards may require additional modules to encode or
89 decode audio/video standards. This option will autoselect 89 decode audio/video standards. This option will autoselect
@@ -792,10 +792,11 @@ config SOC_CAMERA_MT9M001
792 and colour models. 792 and colour models.
793 793
794config SOC_CAMERA_MT9M111 794config SOC_CAMERA_MT9M111
795 tristate "mt9m111 and mt9m112 support" 795 tristate "mt9m111, mt9m112 and mt9m131 support"
796 depends on SOC_CAMERA && I2C 796 depends on SOC_CAMERA && I2C
797 help 797 help
798 This driver supports MT9M111 and MT9M112 cameras from Micron 798 This driver supports MT9M111, MT9M112 and MT9M131 cameras from
799 Micron/Aptina
799 800
800config SOC_CAMERA_MT9T031 801config SOC_CAMERA_MT9T031
801 tristate "mt9t031 support" 802 tristate "mt9t031 support"
@@ -1016,4 +1017,13 @@ config VIDEO_MEM2MEM_TESTDEV
1016 This is a virtual test device for the memory-to-memory driver 1017 This is a virtual test device for the memory-to-memory driver
1017 framework. 1018 framework.
1018 1019
1020config VIDEO_SAMSUNG_S5P_FIMC
1021 tristate "Samsung S5P FIMC (video postprocessor) driver"
1022 depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
1023 select VIDEOBUF_DMA_CONTIG
1024 select V4L2_MEM2MEM_DEV
1025 help
1026 This is a v4l2 driver for the S5P camera interface
1027 (video postprocessor)
1028
1019endif # V4L_MEM2MEM_DRIVERS 1029endif # V4L_MEM2MEM_DRIVERS
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 1051ecc602e..40f98fba5f8 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -11,7 +11,7 @@ stkwebcam-objs := stk-webcam.o stk-sensor.o
11omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o 11omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o
12 12
13videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ 13videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \
14 v4l2-event.o 14 v4l2-event.o v4l2-ctrls.o
15 15
16# V4L2 core modules 16# V4L2 core modules
17 17
@@ -163,6 +163,7 @@ obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o
163obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o 163obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
164obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o 164obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o
165obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o 165obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o
166obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/
166 167
167obj-$(CONFIG_ARCH_DAVINCI) += davinci/ 168obj-$(CONFIG_ARCH_DAVINCI) += davinci/
168 169
diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c
index 3cc135a98d8..cc9e84d75ea 100644
--- a/drivers/media/video/cs53l32a.c
+++ b/drivers/media/video/cs53l32a.c
@@ -26,10 +26,10 @@
26#include <linux/ioctl.h> 26#include <linux/ioctl.h>
27#include <asm/uaccess.h> 27#include <asm/uaccess.h>
28#include <linux/i2c.h> 28#include <linux/i2c.h>
29#include <linux/i2c-id.h>
30#include <linux/videodev2.h> 29#include <linux/videodev2.h>
31#include <media/v4l2-device.h> 30#include <media/v4l2-device.h>
32#include <media/v4l2-chip-ident.h> 31#include <media/v4l2-chip-ident.h>
32#include <media/v4l2-ctrls.h>
33#include <media/v4l2-i2c-drv.h> 33#include <media/v4l2-i2c-drv.h>
34 34
35MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC"); 35MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
@@ -43,6 +43,21 @@ module_param(debug, bool, 0644);
43MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On"); 43MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On");
44 44
45 45
46struct cs53l32a_state {
47 struct v4l2_subdev sd;
48 struct v4l2_ctrl_handler hdl;
49};
50
51static inline struct cs53l32a_state *to_state(struct v4l2_subdev *sd)
52{
53 return container_of(sd, struct cs53l32a_state, sd);
54}
55
56static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
57{
58 return &container_of(ctrl->handler, struct cs53l32a_state, hdl)->sd;
59}
60
46/* ----------------------------------------------------------------------- */ 61/* ----------------------------------------------------------------------- */
47 62
48static int cs53l32a_write(struct v4l2_subdev *sd, u8 reg, u8 value) 63static int cs53l32a_write(struct v4l2_subdev *sd, u8 reg, u8 value)
@@ -74,31 +89,20 @@ static int cs53l32a_s_routing(struct v4l2_subdev *sd,
74 return 0; 89 return 0;
75} 90}
76 91
77static int cs53l32a_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 92static int cs53l32a_s_ctrl(struct v4l2_ctrl *ctrl)
78{ 93{
79 if (ctrl->id == V4L2_CID_AUDIO_MUTE) { 94 struct v4l2_subdev *sd = to_sd(ctrl);
80 ctrl->value = (cs53l32a_read(sd, 0x03) & 0xc0) != 0;
81 return 0;
82 }
83 if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
84 return -EINVAL;
85 ctrl->value = (s8)cs53l32a_read(sd, 0x04);
86 return 0;
87}
88 95
89static int cs53l32a_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 96 switch (ctrl->id) {
90{ 97 case V4L2_CID_AUDIO_MUTE:
91 if (ctrl->id == V4L2_CID_AUDIO_MUTE) { 98 cs53l32a_write(sd, 0x03, ctrl->val ? 0xf0 : 0x30);
92 cs53l32a_write(sd, 0x03, ctrl->value ? 0xf0 : 0x30); 99 return 0;
100 case V4L2_CID_AUDIO_VOLUME:
101 cs53l32a_write(sd, 0x04, (u8)ctrl->val);
102 cs53l32a_write(sd, 0x05, (u8)ctrl->val);
93 return 0; 103 return 0;
94 } 104 }
95 if (ctrl->id != V4L2_CID_AUDIO_VOLUME) 105 return -EINVAL;
96 return -EINVAL;
97 if (ctrl->value > 12 || ctrl->value < -96)
98 return -EINVAL;
99 cs53l32a_write(sd, 0x04, (u8) ctrl->value);
100 cs53l32a_write(sd, 0x05, (u8) ctrl->value);
101 return 0;
102} 106}
103 107
104static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) 108static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
@@ -111,23 +115,30 @@ static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_id
111 115
112static int cs53l32a_log_status(struct v4l2_subdev *sd) 116static int cs53l32a_log_status(struct v4l2_subdev *sd)
113{ 117{
118 struct cs53l32a_state *state = to_state(sd);
114 u8 v = cs53l32a_read(sd, 0x01); 119 u8 v = cs53l32a_read(sd, 0x01);
115 u8 m = cs53l32a_read(sd, 0x03);
116 s8 vol = cs53l32a_read(sd, 0x04);
117 120
118 v4l2_info(sd, "Input: %d%s\n", (v >> 4) & 3, 121 v4l2_info(sd, "Input: %d\n", (v >> 4) & 3);
119 (m & 0xC0) ? " (muted)" : ""); 122 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
120 v4l2_info(sd, "Volume: %d dB\n", vol);
121 return 0; 123 return 0;
122} 124}
123 125
124/* ----------------------------------------------------------------------- */ 126/* ----------------------------------------------------------------------- */
125 127
128static const struct v4l2_ctrl_ops cs53l32a_ctrl_ops = {
129 .s_ctrl = cs53l32a_s_ctrl,
130};
131
126static const struct v4l2_subdev_core_ops cs53l32a_core_ops = { 132static const struct v4l2_subdev_core_ops cs53l32a_core_ops = {
127 .log_status = cs53l32a_log_status, 133 .log_status = cs53l32a_log_status,
128 .g_chip_ident = cs53l32a_g_chip_ident, 134 .g_chip_ident = cs53l32a_g_chip_ident,
129 .g_ctrl = cs53l32a_g_ctrl, 135 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
130 .s_ctrl = cs53l32a_s_ctrl, 136 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
137 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
138 .g_ctrl = v4l2_subdev_g_ctrl,
139 .s_ctrl = v4l2_subdev_s_ctrl,
140 .queryctrl = v4l2_subdev_queryctrl,
141 .querymenu = v4l2_subdev_querymenu,
131}; 142};
132 143
133static const struct v4l2_subdev_audio_ops cs53l32a_audio_ops = { 144static const struct v4l2_subdev_audio_ops cs53l32a_audio_ops = {
@@ -151,6 +162,7 @@ static const struct v4l2_subdev_ops cs53l32a_ops = {
151static int cs53l32a_probe(struct i2c_client *client, 162static int cs53l32a_probe(struct i2c_client *client,
152 const struct i2c_device_id *id) 163 const struct i2c_device_id *id)
153{ 164{
165 struct cs53l32a_state *state;
154 struct v4l2_subdev *sd; 166 struct v4l2_subdev *sd;
155 int i; 167 int i;
156 168
@@ -164,9 +176,10 @@ static int cs53l32a_probe(struct i2c_client *client,
164 v4l_info(client, "chip found @ 0x%x (%s)\n", 176 v4l_info(client, "chip found @ 0x%x (%s)\n",
165 client->addr << 1, client->adapter->name); 177 client->addr << 1, client->adapter->name);
166 178
167 sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); 179 state = kzalloc(sizeof(struct cs53l32a_state), GFP_KERNEL);
168 if (sd == NULL) 180 if (state == NULL)
169 return -ENOMEM; 181 return -ENOMEM;
182 sd = &state->sd;
170 v4l2_i2c_subdev_init(sd, client, &cs53l32a_ops); 183 v4l2_i2c_subdev_init(sd, client, &cs53l32a_ops);
171 184
172 for (i = 1; i <= 7; i++) { 185 for (i = 1; i <= 7; i++) {
@@ -175,15 +188,29 @@ static int cs53l32a_probe(struct i2c_client *client,
175 v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v); 188 v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v);
176 } 189 }
177 190
191 v4l2_ctrl_handler_init(&state->hdl, 2);
192 v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops,
193 V4L2_CID_AUDIO_VOLUME, -96, 12, 1, 0);
194 v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops,
195 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
196 sd->ctrl_handler = &state->hdl;
197 if (state->hdl.error) {
198 int err = state->hdl.error;
199
200 v4l2_ctrl_handler_free(&state->hdl);
201 kfree(state);
202 return err;
203 }
204
178 /* Set cs53l32a internal register for Adaptec 2010/2410 setup */ 205 /* Set cs53l32a internal register for Adaptec 2010/2410 setup */
179 206
180 cs53l32a_write(sd, 0x01, (u8) 0x21); 207 cs53l32a_write(sd, 0x01, 0x21);
181 cs53l32a_write(sd, 0x02, (u8) 0x29); 208 cs53l32a_write(sd, 0x02, 0x29);
182 cs53l32a_write(sd, 0x03, (u8) 0x30); 209 cs53l32a_write(sd, 0x03, 0x30);
183 cs53l32a_write(sd, 0x04, (u8) 0x00); 210 cs53l32a_write(sd, 0x04, 0x00);
184 cs53l32a_write(sd, 0x05, (u8) 0x00); 211 cs53l32a_write(sd, 0x05, 0x00);
185 cs53l32a_write(sd, 0x06, (u8) 0x00); 212 cs53l32a_write(sd, 0x06, 0x00);
186 cs53l32a_write(sd, 0x07, (u8) 0x00); 213 cs53l32a_write(sd, 0x07, 0x00);
187 214
188 /* Display results, should be 0x21,0x29,0x30,0x00,0x00,0x00,0x00 */ 215 /* Display results, should be 0x21,0x29,0x30,0x00,0x00,0x00,0x00 */
189 216
@@ -198,9 +225,11 @@ static int cs53l32a_probe(struct i2c_client *client,
198static int cs53l32a_remove(struct i2c_client *client) 225static int cs53l32a_remove(struct i2c_client *client)
199{ 226{
200 struct v4l2_subdev *sd = i2c_get_clientdata(client); 227 struct v4l2_subdev *sd = i2c_get_clientdata(client);
228 struct cs53l32a_state *state = to_state(sd);
201 229
202 v4l2_device_unregister_subdev(sd); 230 v4l2_device_unregister_subdev(sd);
203 kfree(sd); 231 v4l2_ctrl_handler_free(&state->hdl);
232 kfree(state);
204 return 0; 233 return 0;
205} 234}
206 235
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c
index 2bf44ef10fe..e5c3c8da4be 100644
--- a/drivers/media/video/cx2341x.c
+++ b/drivers/media/video/cx2341x.c
@@ -38,6 +38,145 @@ static int debug;
38module_param(debug, int, 0644); 38module_param(debug, int, 0644);
39MODULE_PARM_DESC(debug, "Debug level (0-1)"); 39MODULE_PARM_DESC(debug, "Debug level (0-1)");
40 40
41/********************** COMMON CODE *********************/
42
43/* definitions for audio properties bits 29-28 */
44#define CX2341X_AUDIO_ENCODING_METHOD_MPEG 0
45#define CX2341X_AUDIO_ENCODING_METHOD_AC3 1
46#define CX2341X_AUDIO_ENCODING_METHOD_LPCM 2
47
48static const char *cx2341x_get_name(u32 id)
49{
50 switch (id) {
51 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
52 return "Spatial Filter Mode";
53 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
54 return "Spatial Filter";
55 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
56 return "Spatial Luma Filter Type";
57 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
58 return "Spatial Chroma Filter Type";
59 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
60 return "Temporal Filter Mode";
61 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
62 return "Temporal Filter";
63 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
64 return "Median Filter Type";
65 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
66 return "Median Luma Filter Maximum";
67 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
68 return "Median Luma Filter Minimum";
69 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
70 return "Median Chroma Filter Maximum";
71 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
72 return "Median Chroma Filter Minimum";
73 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
74 return "Insert Navigation Packets";
75 }
76 return NULL;
77}
78
79static const char **cx2341x_get_menu(u32 id)
80{
81 static const char *cx2341x_video_spatial_filter_mode_menu[] = {
82 "Manual",
83 "Auto",
84 NULL
85 };
86
87 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
88 "Off",
89 "1D Horizontal",
90 "1D Vertical",
91 "2D H/V Separable",
92 "2D Symmetric non-separable",
93 NULL
94 };
95
96 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
97 "Off",
98 "1D Horizontal",
99 NULL
100 };
101
102 static const char *cx2341x_video_temporal_filter_mode_menu[] = {
103 "Manual",
104 "Auto",
105 NULL
106 };
107
108 static const char *cx2341x_video_median_filter_type_menu[] = {
109 "Off",
110 "Horizontal",
111 "Vertical",
112 "Horizontal/Vertical",
113 "Diagonal",
114 NULL
115 };
116
117 switch (id) {
118 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
119 return cx2341x_video_spatial_filter_mode_menu;
120 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
121 return cx2341x_video_luma_spatial_filter_type_menu;
122 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
123 return cx2341x_video_chroma_spatial_filter_type_menu;
124 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
125 return cx2341x_video_temporal_filter_mode_menu;
126 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
127 return cx2341x_video_median_filter_type_menu;
128 }
129 return NULL;
130}
131
132static void cx2341x_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
133 s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags)
134{
135 *name = cx2341x_get_name(id);
136 *flags = 0;
137
138 switch (id) {
139 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
140 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
141 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
142 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
143 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
144 *type = V4L2_CTRL_TYPE_MENU;
145 *min = 0;
146 *step = 0;
147 break;
148 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
149 *type = V4L2_CTRL_TYPE_BOOLEAN;
150 *min = 0;
151 *max = *step = 1;
152 break;
153 default:
154 *type = V4L2_CTRL_TYPE_INTEGER;
155 break;
156 }
157 switch (id) {
158 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
159 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
160 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
161 *flags |= V4L2_CTRL_FLAG_UPDATE;
162 break;
163 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
164 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
165 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
166 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
167 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
168 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
169 *flags |= V4L2_CTRL_FLAG_SLIDER;
170 break;
171 case V4L2_CID_MPEG_VIDEO_ENCODING:
172 *flags |= V4L2_CTRL_FLAG_READ_ONLY;
173 break;
174 }
175}
176
177
178/********************** OLD CODE *********************/
179
41/* Must be sorted from low to high control ID! */ 180/* Must be sorted from low to high control ID! */
42const u32 cx2341x_mpeg_ctrls[] = { 181const u32 cx2341x_mpeg_ctrls[] = {
43 V4L2_CID_MPEG_CLASS, 182 V4L2_CID_MPEG_CLASS,
@@ -134,8 +273,6 @@ static const struct cx2341x_mpeg_params default_params = {
134 .video_chroma_median_filter_top = 255, 273 .video_chroma_median_filter_top = 255,
135 .video_chroma_median_filter_bottom = 0, 274 .video_chroma_median_filter_bottom = 0,
136}; 275};
137
138
139/* Map the control ID to the correct field in the cx2341x_mpeg_params 276/* Map the control ID to the correct field in the cx2341x_mpeg_params
140 struct. Return -EINVAL if the ID is unknown, else return 0. */ 277 struct. Return -EINVAL if the ID is unknown, else return 0. */
141static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params, 278static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params,
@@ -415,83 +552,33 @@ static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
415{ 552{
416 const char *name; 553 const char *name;
417 554
418 qctrl->flags = 0;
419 switch (qctrl->id) { 555 switch (qctrl->id) {
420 /* MPEG controls */ 556 /* MPEG controls */
421 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 557 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
422 name = "Spatial Filter Mode";
423 break;
424 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: 558 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
425 name = "Spatial Filter";
426 break;
427 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 559 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
428 name = "Spatial Luma Filter Type";
429 break;
430 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 560 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
431 name = "Spatial Chroma Filter Type";
432 break;
433 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 561 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
434 name = "Temporal Filter Mode";
435 break;
436 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: 562 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
437 name = "Temporal Filter";
438 break;
439 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 563 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
440 name = "Median Filter Type";
441 break;
442 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: 564 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
443 name = "Median Luma Filter Maximum";
444 break;
445 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: 565 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
446 name = "Median Luma Filter Minimum";
447 break;
448 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: 566 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
449 name = "Median Chroma Filter Maximum";
450 break;
451 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: 567 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
452 name = "Median Chroma Filter Minimum";
453 break;
454 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: 568 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
455 name = "Insert Navigation Packets"; 569 cx2341x_ctrl_fill(qctrl->id, &name, &qctrl->type,
456 break; 570 &min, &max, &step, &def, &qctrl->flags);
571 qctrl->minimum = min;
572 qctrl->maximum = max;
573 qctrl->step = step;
574 qctrl->default_value = def;
575 qctrl->reserved[0] = qctrl->reserved[1] = 0;
576 strlcpy(qctrl->name, name, sizeof(qctrl->name));
577 return 0;
457 578
458 default: 579 default:
459 return v4l2_ctrl_query_fill(qctrl, min, max, step, def); 580 return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
460 } 581 }
461 switch (qctrl->id) {
462 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
463 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
464 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
465 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
466 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
467 qctrl->type = V4L2_CTRL_TYPE_MENU;
468 min = 0;
469 step = 1;
470 break;
471 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
472 qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
473 min = 0;
474 max = 1;
475 step = 1;
476 break;
477 default:
478 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
479 break;
480 }
481 switch (qctrl->id) {
482 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
483 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
484 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
485 qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
486 break;
487 }
488 qctrl->minimum = min;
489 qctrl->maximum = max;
490 qctrl->step = step;
491 qctrl->default_value = def;
492 qctrl->reserved[0] = qctrl->reserved[1] = 0;
493 snprintf(qctrl->name, sizeof(qctrl->name), name);
494 return 0;
495} 582}
496 583
497int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, 584int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
@@ -797,42 +884,6 @@ const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id)
797 NULL 884 NULL
798 }; 885 };
799 886
800 static const char *cx2341x_video_spatial_filter_mode_menu[] = {
801 "Manual",
802 "Auto",
803 NULL
804 };
805
806 static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
807 "Off",
808 "1D Horizontal",
809 "1D Vertical",
810 "2D H/V Separable",
811 "2D Symmetric non-separable",
812 NULL
813 };
814
815 static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
816 "Off",
817 "1D Horizontal",
818 NULL
819 };
820
821 static const char *cx2341x_video_temporal_filter_mode_menu[] = {
822 "Manual",
823 "Auto",
824 NULL
825 };
826
827 static const char *cx2341x_video_median_filter_type_menu[] = {
828 "Off",
829 "Horizontal",
830 "Vertical",
831 "Horizontal/Vertical",
832 "Diagonal",
833 NULL
834 };
835
836 switch (id) { 887 switch (id) {
837 case V4L2_CID_MPEG_STREAM_TYPE: 888 case V4L2_CID_MPEG_STREAM_TYPE:
838 return (p->capabilities & CX2341X_CAP_HAS_TS) ? 889 return (p->capabilities & CX2341X_CAP_HAS_TS) ?
@@ -844,26 +895,17 @@ const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id)
844 case V4L2_CID_MPEG_AUDIO_L3_BITRATE: 895 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
845 return NULL; 896 return NULL;
846 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 897 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
847 return cx2341x_video_spatial_filter_mode_menu;
848 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: 898 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
849 return cx2341x_video_luma_spatial_filter_type_menu;
850 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: 899 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
851 return cx2341x_video_chroma_spatial_filter_type_menu;
852 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: 900 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
853 return cx2341x_video_temporal_filter_mode_menu;
854 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: 901 case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
855 return cx2341x_video_median_filter_type_menu; 902 return cx2341x_get_menu(id);
856 default: 903 default:
857 return v4l2_ctrl_get_menu(id); 904 return v4l2_ctrl_get_menu(id);
858 } 905 }
859} 906}
860EXPORT_SYMBOL(cx2341x_ctrl_get_menu); 907EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
861 908
862/* definitions for audio properties bits 29-28 */
863#define CX2341X_AUDIO_ENCODING_METHOD_MPEG 0
864#define CX2341X_AUDIO_ENCODING_METHOD_AC3 1
865#define CX2341X_AUDIO_ENCODING_METHOD_LPCM 2
866
867static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params) 909static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
868{ 910{
869 params->audio_properties = 911 params->audio_properties =
@@ -1195,9 +1237,490 @@ void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
1195} 1237}
1196EXPORT_SYMBOL(cx2341x_log_status); 1238EXPORT_SYMBOL(cx2341x_log_status);
1197 1239
1198/*
1199 * Local variables:
1200 * c-basic-offset: 8
1201 * End:
1202 */
1203 1240
1241
1242/********************** NEW CODE *********************/
1243
1244static inline struct cx2341x_handler *to_cxhdl(struct v4l2_ctrl *ctrl)
1245{
1246 return container_of(ctrl->handler, struct cx2341x_handler, hdl);
1247}
1248
1249static int cx2341x_hdl_api(struct cx2341x_handler *hdl,
1250 u32 cmd, int args, ...)
1251{
1252 u32 data[CX2341X_MBOX_MAX_DATA];
1253 va_list vargs;
1254 int i;
1255
1256 va_start(vargs, args);
1257
1258 for (i = 0; i < args; i++)
1259 data[i] = va_arg(vargs, int);
1260 va_end(vargs);
1261 return hdl->func(hdl->priv, cmd, args, 0, data);
1262}
1263
1264/* ctrl->handler->lock is held, so it is safe to access cur.val */
1265static inline int cx2341x_neq(struct v4l2_ctrl *ctrl)
1266{
1267 return ctrl && ctrl->val != ctrl->cur.val;
1268}
1269
1270static int cx2341x_try_ctrl(struct v4l2_ctrl *ctrl)
1271{
1272 struct cx2341x_handler *hdl = to_cxhdl(ctrl);
1273 s32 val = ctrl->val;
1274
1275 switch (ctrl->id) {
1276 case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
1277 /* video gop cluster */
1278 int b = val + 1;
1279 int gop = hdl->video_gop_size->val;
1280
1281 gop = b * ((gop + b - 1) / b);
1282
1283 /* Max GOP size = 34 */
1284 while (gop > 34)
1285 gop -= b;
1286 hdl->video_gop_size->val = gop;
1287 break;
1288 }
1289
1290 case V4L2_CID_MPEG_STREAM_TYPE:
1291 /* stream type cluster */
1292 hdl->video_encoding->val =
1293 (hdl->stream_type->val == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
1294 hdl->stream_type->val == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
1295 V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :
1296 V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
1297 if (hdl->video_encoding->val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
1298 /* MPEG-1 implies CBR */
1299 hdl->video_bitrate_mode->val =
1300 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
1301 /* peak bitrate shall be >= normal bitrate */
1302 if (hdl->video_bitrate_mode->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
1303 hdl->video_bitrate_peak->val < hdl->video_bitrate->val)
1304 hdl->video_bitrate_peak->val = hdl->video_bitrate->val;
1305 break;
1306 }
1307 return 0;
1308}
1309
1310static int cx2341x_s_ctrl(struct v4l2_ctrl *ctrl)
1311{
1312 static const int mpeg_stream_type[] = {
1313 0, /* MPEG-2 PS */
1314 1, /* MPEG-2 TS */
1315 2, /* MPEG-1 SS */
1316 14, /* DVD */
1317 11, /* VCD */
1318 12, /* SVCD */
1319 };
1320 struct cx2341x_handler *hdl = to_cxhdl(ctrl);
1321 s32 val = ctrl->val;
1322 u32 props;
1323 int err;
1324
1325 switch (ctrl->id) {
1326 case V4L2_CID_MPEG_STREAM_VBI_FMT:
1327 if (hdl->ops && hdl->ops->s_stream_vbi_fmt)
1328 return hdl->ops->s_stream_vbi_fmt(hdl, val);
1329 return 0;
1330
1331 case V4L2_CID_MPEG_VIDEO_ASPECT:
1332 return cx2341x_hdl_api(hdl,
1333 CX2341X_ENC_SET_ASPECT_RATIO, 1, val + 1);
1334
1335 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
1336 return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_GOP_CLOSURE, 1, val);
1337
1338 case V4L2_CID_MPEG_AUDIO_MUTE:
1339 return cx2341x_hdl_api(hdl, CX2341X_ENC_MUTE_AUDIO, 1, val);
1340
1341 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
1342 return cx2341x_hdl_api(hdl,
1343 CX2341X_ENC_SET_FRAME_DROP_RATE, 1, val);
1344
1345 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
1346 return cx2341x_hdl_api(hdl, CX2341X_ENC_MISC, 2, 7, val);
1347
1348 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
1349 /* audio properties cluster */
1350 props = (hdl->audio_sampling_freq->val << 0) |
1351 (hdl->audio_mode->val << 8) |
1352 (hdl->audio_mode_extension->val << 10) |
1353 (hdl->audio_crc->val << 14);
1354 if (hdl->audio_emphasis->val == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
1355 props |= 3 << 12;
1356 else
1357 props |= hdl->audio_emphasis->val << 12;
1358
1359 if (hdl->audio_encoding->val == V4L2_MPEG_AUDIO_ENCODING_AC3) {
1360 props |=
1361#if 1
1362 /* Not sure if this MPEG Layer II setting is required */
1363 ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) |
1364#endif
1365 (hdl->audio_ac3_bitrate->val << 4) |
1366 (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28);
1367 } else {
1368 /* Assuming MPEG Layer II */
1369 props |=
1370 ((3 - hdl->audio_encoding->val) << 2) |
1371 ((1 + hdl->audio_l2_bitrate->val) << 4);
1372 }
1373 err = cx2341x_hdl_api(hdl,
1374 CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, props);
1375 if (err)
1376 return err;
1377
1378 hdl->audio_properties = props;
1379 if (hdl->audio_ac3_bitrate) {
1380 int is_ac3 = hdl->audio_encoding->val ==
1381 V4L2_MPEG_AUDIO_ENCODING_AC3;
1382
1383 v4l2_ctrl_activate(hdl->audio_ac3_bitrate, is_ac3);
1384 v4l2_ctrl_activate(hdl->audio_l2_bitrate, !is_ac3);
1385 }
1386 v4l2_ctrl_activate(hdl->audio_mode_extension,
1387 hdl->audio_mode->val == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO);
1388 if (cx2341x_neq(hdl->audio_sampling_freq) &&
1389 hdl->ops && hdl->ops->s_audio_sampling_freq)
1390 return hdl->ops->s_audio_sampling_freq(hdl, hdl->audio_sampling_freq->val);
1391 if (cx2341x_neq(hdl->audio_mode) &&
1392 hdl->ops && hdl->ops->s_audio_mode)
1393 return hdl->ops->s_audio_mode(hdl, hdl->audio_mode->val);
1394 return 0;
1395
1396 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
1397 /* video gop cluster */
1398 return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
1399 hdl->video_gop_size->val,
1400 hdl->video_b_frames->val + 1);
1401
1402 case V4L2_CID_MPEG_STREAM_TYPE:
1403 /* stream type cluster */
1404 err = cx2341x_hdl_api(hdl,
1405 CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[val]);
1406 if (err)
1407 return err;
1408
1409 err = cx2341x_hdl_api(hdl, CX2341X_ENC_SET_BIT_RATE, 5,
1410 hdl->video_bitrate_mode->val,
1411 hdl->video_bitrate->val,
1412 hdl->video_bitrate_peak->val / 400, 0, 0);
1413 if (err)
1414 return err;
1415
1416 v4l2_ctrl_activate(hdl->video_bitrate_mode,
1417 hdl->video_encoding->val != V4L2_MPEG_VIDEO_ENCODING_MPEG_1);
1418 v4l2_ctrl_activate(hdl->video_bitrate_peak,
1419 hdl->video_bitrate_mode->val != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR);
1420 if (cx2341x_neq(hdl->video_encoding) &&
1421 hdl->ops && hdl->ops->s_video_encoding)
1422 return hdl->ops->s_video_encoding(hdl, hdl->video_encoding->val);
1423 return 0;
1424
1425 case V4L2_CID_MPEG_VIDEO_MUTE:
1426 /* video mute cluster */
1427 return cx2341x_hdl_api(hdl, CX2341X_ENC_MUTE_VIDEO, 1,
1428 hdl->video_mute->val |
1429 (hdl->video_mute_yuv->val << 8));
1430
1431 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: {
1432 int active_filter;
1433
1434 /* video filter mode */
1435 err = cx2341x_hdl_api(hdl, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
1436 hdl->video_spatial_filter_mode->val |
1437 (hdl->video_temporal_filter_mode->val << 1),
1438 hdl->video_median_filter_type->val);
1439 if (err)
1440 return err;
1441
1442 active_filter = hdl->video_spatial_filter_mode->val !=
1443 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO;
1444 v4l2_ctrl_activate(hdl->video_spatial_filter, active_filter);
1445 v4l2_ctrl_activate(hdl->video_luma_spatial_filter_type, active_filter);
1446 v4l2_ctrl_activate(hdl->video_chroma_spatial_filter_type, active_filter);
1447 active_filter = hdl->video_temporal_filter_mode->val !=
1448 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO;
1449 v4l2_ctrl_activate(hdl->video_temporal_filter, active_filter);
1450 active_filter = hdl->video_median_filter_type->val !=
1451 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF;
1452 v4l2_ctrl_activate(hdl->video_luma_median_filter_bottom, active_filter);
1453 v4l2_ctrl_activate(hdl->video_luma_median_filter_top, active_filter);
1454 v4l2_ctrl_activate(hdl->video_chroma_median_filter_bottom, active_filter);
1455 v4l2_ctrl_activate(hdl->video_chroma_median_filter_top, active_filter);
1456 return 0;
1457 }
1458
1459 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
1460 /* video filter type cluster */
1461 return cx2341x_hdl_api(hdl,
1462 CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
1463 hdl->video_luma_spatial_filter_type->val,
1464 hdl->video_chroma_spatial_filter_type->val);
1465
1466 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
1467 /* video filter cluster */
1468 return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
1469 hdl->video_spatial_filter->val,
1470 hdl->video_temporal_filter->val);
1471
1472 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
1473 /* video median cluster */
1474 return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_CORING_LEVELS, 4,
1475 hdl->video_luma_median_filter_bottom->val,
1476 hdl->video_luma_median_filter_top->val,
1477 hdl->video_chroma_median_filter_bottom->val,
1478 hdl->video_chroma_median_filter_top->val);
1479 }
1480 return -EINVAL;
1481}
1482
1483static const struct v4l2_ctrl_ops cx2341x_ops = {
1484 .try_ctrl = cx2341x_try_ctrl,
1485 .s_ctrl = cx2341x_s_ctrl,
1486};
1487
1488static struct v4l2_ctrl *cx2341x_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
1489 u32 id, s32 min, s32 max, s32 step, s32 def)
1490{
1491 struct v4l2_ctrl_config cfg;
1492
1493 cx2341x_ctrl_fill(id, &cfg.name, &cfg.type, &min, &max, &step, &def, &cfg.flags);
1494 cfg.ops = &cx2341x_ops;
1495 cfg.id = id;
1496 cfg.min = min;
1497 cfg.max = max;
1498 cfg.def = def;
1499 if (cfg.type == V4L2_CTRL_TYPE_MENU) {
1500 cfg.step = 0;
1501 cfg.menu_skip_mask = step;
1502 cfg.qmenu = cx2341x_get_menu(id);
1503 } else {
1504 cfg.step = step;
1505 cfg.menu_skip_mask = 0;
1506 }
1507 return v4l2_ctrl_new_custom(hdl, &cfg, NULL);
1508}
1509
1510static struct v4l2_ctrl *cx2341x_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
1511 u32 id, s32 min, s32 max, s32 step, s32 def)
1512{
1513 return v4l2_ctrl_new_std(hdl, &cx2341x_ops, id, min, max, step, def);
1514}
1515
1516static struct v4l2_ctrl *cx2341x_ctrl_new_menu(struct v4l2_ctrl_handler *hdl,
1517 u32 id, s32 max, s32 mask, s32 def)
1518{
1519 return v4l2_ctrl_new_std_menu(hdl, &cx2341x_ops, id, max, mask, def);
1520}
1521
1522int cx2341x_handler_init(struct cx2341x_handler *cxhdl,
1523 unsigned nr_of_controls_hint)
1524{
1525 struct v4l2_ctrl_handler *hdl = &cxhdl->hdl;
1526 u32 caps = cxhdl->capabilities;
1527 int has_sliced_vbi = caps & CX2341X_CAP_HAS_SLICED_VBI;
1528 int has_ac3 = caps & CX2341X_CAP_HAS_AC3;
1529 int has_ts = caps & CX2341X_CAP_HAS_TS;
1530
1531 cxhdl->width = 720;
1532 cxhdl->height = 480;
1533
1534 v4l2_ctrl_handler_init(hdl, nr_of_controls_hint);
1535
1536 /* Add controls in ascending control ID order for fastest
1537 insertion time. */
1538 cxhdl->stream_type = cx2341x_ctrl_new_menu(hdl,
1539 V4L2_CID_MPEG_STREAM_TYPE,
1540 V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, has_ts ? 0 : 2,
1541 V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
1542 cxhdl->stream_vbi_fmt = cx2341x_ctrl_new_menu(hdl,
1543 V4L2_CID_MPEG_STREAM_VBI_FMT,
1544 V4L2_MPEG_STREAM_VBI_FMT_IVTV, has_sliced_vbi ? 0 : 2,
1545 V4L2_MPEG_STREAM_VBI_FMT_NONE);
1546 cxhdl->audio_sampling_freq = cx2341x_ctrl_new_menu(hdl,
1547 V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
1548 V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 0,
1549 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
1550 cxhdl->audio_encoding = cx2341x_ctrl_new_menu(hdl,
1551 V4L2_CID_MPEG_AUDIO_ENCODING,
1552 V4L2_MPEG_AUDIO_ENCODING_AC3, has_ac3 ? ~0x12 : ~0x2,
1553 V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
1554 cxhdl->audio_l2_bitrate = cx2341x_ctrl_new_menu(hdl,
1555 V4L2_CID_MPEG_AUDIO_L2_BITRATE,
1556 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 0x1ff,
1557 V4L2_MPEG_AUDIO_L2_BITRATE_224K);
1558 cxhdl->audio_mode = cx2341x_ctrl_new_menu(hdl,
1559 V4L2_CID_MPEG_AUDIO_MODE,
1560 V4L2_MPEG_AUDIO_MODE_MONO, 0,
1561 V4L2_MPEG_AUDIO_MODE_STEREO);
1562 cxhdl->audio_mode_extension = cx2341x_ctrl_new_menu(hdl,
1563 V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
1564 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 0,
1565 V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4);
1566 cxhdl->audio_emphasis = cx2341x_ctrl_new_menu(hdl,
1567 V4L2_CID_MPEG_AUDIO_EMPHASIS,
1568 V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 0,
1569 V4L2_MPEG_AUDIO_EMPHASIS_NONE);
1570 cxhdl->audio_crc = cx2341x_ctrl_new_menu(hdl,
1571 V4L2_CID_MPEG_AUDIO_CRC,
1572 V4L2_MPEG_AUDIO_CRC_CRC16, 0,
1573 V4L2_MPEG_AUDIO_CRC_NONE);
1574
1575 cx2341x_ctrl_new_std(hdl, V4L2_CID_MPEG_AUDIO_MUTE, 0, 1, 1, 0);
1576 if (has_ac3)
1577 cxhdl->audio_ac3_bitrate = cx2341x_ctrl_new_menu(hdl,
1578 V4L2_CID_MPEG_AUDIO_AC3_BITRATE,
1579 V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 0x03,
1580 V4L2_MPEG_AUDIO_AC3_BITRATE_224K);
1581 cxhdl->video_encoding = cx2341x_ctrl_new_menu(hdl,
1582 V4L2_CID_MPEG_VIDEO_ENCODING,
1583 V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 0,
1584 V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
1585 cx2341x_ctrl_new_menu(hdl,
1586 V4L2_CID_MPEG_VIDEO_ASPECT,
1587 V4L2_MPEG_VIDEO_ASPECT_221x100, 0,
1588 V4L2_MPEG_VIDEO_ASPECT_4x3);
1589 cxhdl->video_b_frames = cx2341x_ctrl_new_std(hdl,
1590 V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 33, 1, 2);
1591 cxhdl->video_gop_size = cx2341x_ctrl_new_std(hdl,
1592 V4L2_CID_MPEG_VIDEO_GOP_SIZE,
1593 1, 34, 1, cxhdl->is_50hz ? 12 : 15);
1594 cx2341x_ctrl_new_std(hdl, V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 0, 1, 1, 1);
1595 cxhdl->video_bitrate_mode = cx2341x_ctrl_new_menu(hdl,
1596 V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
1597 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
1598 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
1599 cxhdl->video_bitrate = cx2341x_ctrl_new_std(hdl,
1600 V4L2_CID_MPEG_VIDEO_BITRATE,
1601 0, 27000000, 1, 6000000);
1602 cxhdl->video_bitrate_peak = cx2341x_ctrl_new_std(hdl,
1603 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
1604 0, 27000000, 1, 8000000);
1605 cx2341x_ctrl_new_std(hdl,
1606 V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, 0, 255, 1, 0);
1607 cxhdl->video_mute = cx2341x_ctrl_new_std(hdl,
1608 V4L2_CID_MPEG_VIDEO_MUTE, 0, 1, 1, 0);
1609 cxhdl->video_mute_yuv = cx2341x_ctrl_new_std(hdl,
1610 V4L2_CID_MPEG_VIDEO_MUTE_YUV, 0, 0xffffff, 1, 0x008080);
1611
1612 /* CX23415/6 specific */
1613 cxhdl->video_spatial_filter_mode = cx2341x_ctrl_new_custom(hdl,
1614 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
1615 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
1616 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 0,
1617 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
1618 cxhdl->video_spatial_filter = cx2341x_ctrl_new_custom(hdl,
1619 V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
1620 0, 15, 1, 0);
1621 cxhdl->video_luma_spatial_filter_type = cx2341x_ctrl_new_custom(hdl,
1622 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
1623 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
1624 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
1625 0,
1626 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR);
1627 cxhdl->video_chroma_spatial_filter_type = cx2341x_ctrl_new_custom(hdl,
1628 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
1629 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
1630 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
1631 0,
1632 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR);
1633 cxhdl->video_temporal_filter_mode = cx2341x_ctrl_new_custom(hdl,
1634 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
1635 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
1636 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO,
1637 0,
1638 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
1639 cxhdl->video_temporal_filter = cx2341x_ctrl_new_custom(hdl,
1640 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
1641 0, 31, 1, 8);
1642 cxhdl->video_median_filter_type = cx2341x_ctrl_new_custom(hdl,
1643 V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
1644 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
1645 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG,
1646 0,
1647 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
1648 cxhdl->video_luma_median_filter_bottom = cx2341x_ctrl_new_custom(hdl,
1649 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
1650 0, 255, 1, 0);
1651 cxhdl->video_luma_median_filter_top = cx2341x_ctrl_new_custom(hdl,
1652 V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
1653 0, 255, 1, 255);
1654 cxhdl->video_chroma_median_filter_bottom = cx2341x_ctrl_new_custom(hdl,
1655 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
1656 0, 255, 1, 0);
1657 cxhdl->video_chroma_median_filter_top = cx2341x_ctrl_new_custom(hdl,
1658 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
1659 0, 255, 1, 255);
1660 cx2341x_ctrl_new_custom(hdl, V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,
1661 0, 1, 1, 0);
1662
1663 if (hdl->error) {
1664 int err = hdl->error;
1665
1666 v4l2_ctrl_handler_free(hdl);
1667 return err;
1668 }
1669
1670 v4l2_ctrl_cluster(8, &cxhdl->audio_sampling_freq);
1671 v4l2_ctrl_cluster(2, &cxhdl->video_b_frames);
1672 v4l2_ctrl_cluster(5, &cxhdl->stream_type);
1673 v4l2_ctrl_cluster(2, &cxhdl->video_mute);
1674 v4l2_ctrl_cluster(3, &cxhdl->video_spatial_filter_mode);
1675 v4l2_ctrl_cluster(2, &cxhdl->video_luma_spatial_filter_type);
1676 v4l2_ctrl_cluster(2, &cxhdl->video_spatial_filter);
1677 v4l2_ctrl_cluster(4, &cxhdl->video_luma_median_filter_top);
1678
1679 return 0;
1680}
1681EXPORT_SYMBOL(cx2341x_handler_init);
1682
1683void cx2341x_handler_set_50hz(struct cx2341x_handler *cxhdl, int is_50hz)
1684{
1685 cxhdl->is_50hz = is_50hz;
1686 cxhdl->video_gop_size->default_value = cxhdl->is_50hz ? 12 : 15;
1687}
1688EXPORT_SYMBOL(cx2341x_handler_set_50hz);
1689
1690int cx2341x_handler_setup(struct cx2341x_handler *cxhdl)
1691{
1692 int h = cxhdl->height;
1693 int w = cxhdl->width;
1694 int err;
1695
1696 err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_OUTPUT_PORT, 2, cxhdl->port, 0);
1697 if (err)
1698 return err;
1699 err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_FRAME_RATE, 1, cxhdl->is_50hz);
1700 if (err)
1701 return err;
1702
1703 if (v4l2_ctrl_g_ctrl(cxhdl->video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
1704 w /= 2;
1705 h /= 2;
1706 }
1707 err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
1708 if (err)
1709 return err;
1710 return v4l2_ctrl_handler_setup(&cxhdl->hdl);
1711}
1712EXPORT_SYMBOL(cx2341x_handler_setup);
1713
1714void cx2341x_handler_set_busy(struct cx2341x_handler *cxhdl, int busy)
1715{
1716 v4l2_ctrl_grab(cxhdl->audio_sampling_freq, busy);
1717 v4l2_ctrl_grab(cxhdl->audio_encoding, busy);
1718 v4l2_ctrl_grab(cxhdl->audio_l2_bitrate, busy);
1719 v4l2_ctrl_grab(cxhdl->audio_ac3_bitrate, busy);
1720 v4l2_ctrl_grab(cxhdl->stream_vbi_fmt, busy);
1721 v4l2_ctrl_grab(cxhdl->stream_type, busy);
1722 v4l2_ctrl_grab(cxhdl->video_bitrate_mode, busy);
1723 v4l2_ctrl_grab(cxhdl->video_bitrate, busy);
1724 v4l2_ctrl_grab(cxhdl->video_bitrate_peak, busy);
1725}
1726EXPORT_SYMBOL(cx2341x_handler_set_busy);
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
index bcdda9a9aa9..768f000e4b2 100644
--- a/drivers/media/video/cx23885/Kconfig
+++ b/drivers/media/video/cx23885/Kconfig
@@ -5,7 +5,7 @@ config VIDEO_CX23885
5 select VIDEO_BTCX 5 select VIDEO_BTCX
6 select VIDEO_TUNER 6 select VIDEO_TUNER
7 select VIDEO_TVEEPROM 7 select VIDEO_TVEEPROM
8 select VIDEO_IR 8 select IR_CORE
9 select VIDEOBUF_DVB 9 select VIDEOBUF_DVB
10 select VIDEOBUF_DMA_SG 10 select VIDEOBUF_DMA_SG
11 select VIDEO_CX25840 11 select VIDEO_CX25840
diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile
index 5787ae24363..e2ee95f660d 100644
--- a/drivers/media/video/cx23885/Makefile
+++ b/drivers/media/video/cx23885/Makefile
@@ -1,7 +1,8 @@
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 cx23885-ir.o cx23885-input.o cx23888-ir.o \ 3 cx23885-ioctl.o cx23885-ir.o cx23885-av.o cx23885-input.o \
4 netup-init.o cimax2.o netup-eeprom.o cx23885-f300.o 4 cx23888-ir.o netup-init.o cimax2.o netup-eeprom.o \
5 cx23885-f300.o
5 6
6obj-$(CONFIG_VIDEO_CX23885) += cx23885.o 7obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
7 8
diff --git a/drivers/media/video/cx23885/cx23885-av.c b/drivers/media/video/cx23885/cx23885-av.c
new file mode 100644
index 00000000000..134ebddd860
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-av.c
@@ -0,0 +1,35 @@
1/*
2 * Driver for the Conexant CX23885/7/8 PCIe bridge
3 *
4 * AV device support routines - non-input, non-vl42_subdev routines
5 *
6 * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.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 "cx23885.h"
25
26void cx23885_av_work_handler(struct work_struct *work)
27{
28 struct cx23885_dev *dev =
29 container_of(work, struct cx23885_dev, cx25840_work);
30 bool handled;
31
32 v4l2_subdev_call(dev->sd_cx25840, core, interrupt_service_routine,
33 PCI_MSK_AV_CORE, &handled);
34 cx23885_irq_enable(dev, PCI_MSK_AV_CORE);
35}
diff --git a/drivers/media/video/cx23885/cx23885-av.h b/drivers/media/video/cx23885/cx23885-av.h
new file mode 100644
index 00000000000..d2915c3e53a
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-av.h
@@ -0,0 +1,27 @@
1/*
2 * Driver for the Conexant CX23885/7/8 PCIe bridge
3 *
4 * AV device support routines - non-input, non-vl42_subdev routines
5 *
6 * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.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_AV_H_
25#define _CX23885_AV_H_
26void cx23885_av_work_handler(struct work_struct *work);
27#endif
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
index 2014daedee8..e76ce8709af 100644
--- a/drivers/media/video/cx23885/cx23885-cards.c
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -30,6 +30,16 @@
30#include "netup-init.h" 30#include "netup-init.h"
31#include "cx23888-ir.h" 31#include "cx23888-ir.h"
32 32
33static unsigned int enable_885_ir;
34module_param(enable_885_ir, int, 0644);
35MODULE_PARM_DESC(enable_885_ir,
36 "Enable integrated IR controller for supported\n"
37 "\t\t CX2388[57] boards that are wired for it:\n"
38 "\t\t\tHVR-1250 (reported safe)\n"
39 "\t\t\tTeVii S470 (reported unsafe)\n"
40 "\t\t This can cause an interrupt storm with some cards.\n"
41 "\t\t Default: 0 [Disabled]");
42
33/* ------------------------------------------------------------------ */ 43/* ------------------------------------------------------------------ */
34/* board config info */ 44/* board config info */
35 45
@@ -626,6 +636,9 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
626 case 79101: 636 case 79101:
627 /* WinTV-HVR1250 (PCIe, Retail, IR, half height, 637 /* WinTV-HVR1250 (PCIe, Retail, IR, half height,
628 ATSC and Basic analog */ 638 ATSC and Basic analog */
639 case 79501:
640 /* WinTV-HVR1250 (PCIe, No IR, half height,
641 ATSC [at least] and Basic analog) */
629 case 79561: 642 case 79561:
630 /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, 643 /* WinTV-HVR1250 (PCIe, OEM, No IR, half height,
631 ATSC and Basic analog */ 644 ATSC and Basic analog */
@@ -959,9 +972,37 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
959 972
960int cx23885_ir_init(struct cx23885_dev *dev) 973int cx23885_ir_init(struct cx23885_dev *dev)
961{ 974{
975 static struct v4l2_subdev_io_pin_config ir_rxtx_pin_cfg[] = {
976 {
977 .flags = V4L2_SUBDEV_IO_PIN_INPUT,
978 .pin = CX23885_PIN_IR_RX_GPIO19,
979 .function = CX23885_PAD_IR_RX,
980 .value = 0,
981 .strength = CX25840_PIN_DRIVE_MEDIUM,
982 }, {
983 .flags = V4L2_SUBDEV_IO_PIN_OUTPUT,
984 .pin = CX23885_PIN_IR_TX_GPIO20,
985 .function = CX23885_PAD_IR_TX,
986 .value = 0,
987 .strength = CX25840_PIN_DRIVE_MEDIUM,
988 }
989 };
990 const size_t ir_rxtx_pin_cfg_count = ARRAY_SIZE(ir_rxtx_pin_cfg);
991
992 static struct v4l2_subdev_io_pin_config ir_rx_pin_cfg[] = {
993 {
994 .flags = V4L2_SUBDEV_IO_PIN_INPUT,
995 .pin = CX23885_PIN_IR_RX_GPIO19,
996 .function = CX23885_PAD_IR_RX,
997 .value = 0,
998 .strength = CX25840_PIN_DRIVE_MEDIUM,
999 }
1000 };
1001 const size_t ir_rx_pin_cfg_count = ARRAY_SIZE(ir_rx_pin_cfg);
1002
1003 struct v4l2_subdev_ir_parameters params;
962 int ret = 0; 1004 int ret = 0;
963 switch (dev->board) { 1005 switch (dev->board) {
964 case CX23885_BOARD_HAUPPAUGE_HVR1250:
965 case CX23885_BOARD_HAUPPAUGE_HVR1500: 1006 case CX23885_BOARD_HAUPPAUGE_HVR1500:
966 case CX23885_BOARD_HAUPPAUGE_HVR1500Q: 1007 case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
967 case CX23885_BOARD_HAUPPAUGE_HVR1800: 1008 case CX23885_BOARD_HAUPPAUGE_HVR1800:
@@ -979,7 +1020,41 @@ int cx23885_ir_init(struct cx23885_dev *dev)
979 if (ret) 1020 if (ret)
980 break; 1021 break;
981 dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR); 1022 dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR);
982 dev->pci_irqmask |= PCI_MSK_IR; 1023 v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
1024 ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg);
1025 /*
1026 * For these boards we need to invert the Tx output via the
1027 * IR controller to have the LED off while idle
1028 */
1029 v4l2_subdev_call(dev->sd_ir, ir, tx_g_parameters, &params);
1030 params.enable = false;
1031 params.shutdown = false;
1032 params.invert_level = true;
1033 v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, &params);
1034 params.shutdown = true;
1035 v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, &params);
1036 break;
1037 case CX23885_BOARD_TEVII_S470:
1038 if (!enable_885_ir)
1039 break;
1040 dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE);
1041 if (dev->sd_ir == NULL) {
1042 ret = -ENODEV;
1043 break;
1044 }
1045 v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
1046 ir_rx_pin_cfg_count, ir_rx_pin_cfg);
1047 break;
1048 case CX23885_BOARD_HAUPPAUGE_HVR1250:
1049 if (!enable_885_ir)
1050 break;
1051 dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE);
1052 if (dev->sd_ir == NULL) {
1053 ret = -ENODEV;
1054 break;
1055 }
1056 v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
1057 ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg);
983 break; 1058 break;
984 case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: 1059 case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
985 request_module("ir-kbd-i2c"); 1060 request_module("ir-kbd-i2c");
@@ -994,11 +1069,16 @@ void cx23885_ir_fini(struct cx23885_dev *dev)
994 switch (dev->board) { 1069 switch (dev->board) {
995 case CX23885_BOARD_HAUPPAUGE_HVR1850: 1070 case CX23885_BOARD_HAUPPAUGE_HVR1850:
996 case CX23885_BOARD_HAUPPAUGE_HVR1290: 1071 case CX23885_BOARD_HAUPPAUGE_HVR1290:
997 dev->pci_irqmask &= ~PCI_MSK_IR; 1072 cx23885_irq_remove(dev, PCI_MSK_IR);
998 cx_clear(PCI_INT_MSK, PCI_MSK_IR);
999 cx23888_ir_remove(dev); 1073 cx23888_ir_remove(dev);
1000 dev->sd_ir = NULL; 1074 dev->sd_ir = NULL;
1001 break; 1075 break;
1076 case CX23885_BOARD_TEVII_S470:
1077 case CX23885_BOARD_HAUPPAUGE_HVR1250:
1078 cx23885_irq_remove(dev, PCI_MSK_AV_CORE);
1079 /* sd_ir is a duplicate pointer to the AV Core, just clear it */
1080 dev->sd_ir = NULL;
1081 break;
1002 } 1082 }
1003} 1083}
1004 1084
@@ -1007,8 +1087,13 @@ void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
1007 switch (dev->board) { 1087 switch (dev->board) {
1008 case CX23885_BOARD_HAUPPAUGE_HVR1850: 1088 case CX23885_BOARD_HAUPPAUGE_HVR1850:
1009 case CX23885_BOARD_HAUPPAUGE_HVR1290: 1089 case CX23885_BOARD_HAUPPAUGE_HVR1290:
1010 if (dev->sd_ir && (dev->pci_irqmask & PCI_MSK_IR)) 1090 if (dev->sd_ir)
1011 cx_set(PCI_INT_MSK, PCI_MSK_IR); 1091 cx23885_irq_add_enable(dev, PCI_MSK_IR);
1092 break;
1093 case CX23885_BOARD_TEVII_S470:
1094 case CX23885_BOARD_HAUPPAUGE_HVR1250:
1095 if (dev->sd_ir)
1096 cx23885_irq_add_enable(dev, PCI_MSK_AV_CORE);
1012 break; 1097 break;
1013 } 1098 }
1014} 1099}
@@ -1028,6 +1113,13 @@ void cx23885_card_setup(struct cx23885_dev *dev)
1028 1113
1029 switch (dev->board) { 1114 switch (dev->board) {
1030 case CX23885_BOARD_HAUPPAUGE_HVR1250: 1115 case CX23885_BOARD_HAUPPAUGE_HVR1250:
1116 if (dev->i2c_bus[0].i2c_rc == 0) {
1117 if (eeprom[0x80] != 0x84)
1118 hauppauge_eeprom(dev, eeprom+0xc0);
1119 else
1120 hauppauge_eeprom(dev, eeprom+0x80);
1121 }
1122 break;
1031 case CX23885_BOARD_HAUPPAUGE_HVR1500: 1123 case CX23885_BOARD_HAUPPAUGE_HVR1500:
1032 case CX23885_BOARD_HAUPPAUGE_HVR1500Q: 1124 case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
1033 case CX23885_BOARD_HAUPPAUGE_HVR1400: 1125 case CX23885_BOARD_HAUPPAUGE_HVR1400:
@@ -1136,6 +1228,11 @@ void cx23885_card_setup(struct cx23885_dev *dev)
1136 * loaded, ensure this happens. 1228 * loaded, ensure this happens.
1137 */ 1229 */
1138 switch (dev->board) { 1230 switch (dev->board) {
1231 case CX23885_BOARD_TEVII_S470:
1232 case CX23885_BOARD_HAUPPAUGE_HVR1250:
1233 /* Currently only enabled for the integrated IR controller */
1234 if (!enable_885_ir)
1235 break;
1139 case CX23885_BOARD_HAUPPAUGE_HVR1800: 1236 case CX23885_BOARD_HAUPPAUGE_HVR1800:
1140 case CX23885_BOARD_HAUPPAUGE_HVR1800lp: 1237 case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
1141 case CX23885_BOARD_HAUPPAUGE_HVR1700: 1238 case CX23885_BOARD_HAUPPAUGE_HVR1700:
@@ -1151,7 +1248,10 @@ void cx23885_card_setup(struct cx23885_dev *dev)
1151 dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, 1248 dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
1152 &dev->i2c_bus[2].i2c_adap, 1249 &dev->i2c_bus[2].i2c_adap,
1153 "cx25840", "cx25840", 0x88 >> 1, NULL); 1250 "cx25840", "cx25840", 0x88 >> 1, NULL);
1154 v4l2_subdev_call(dev->sd_cx25840, core, load_fw); 1251 if (dev->sd_cx25840) {
1252 dev->sd_cx25840->grp_id = CX23885_HW_AV_CORE;
1253 v4l2_subdev_call(dev->sd_cx25840, core, load_fw);
1254 }
1155 break; 1255 break;
1156 } 1256 }
1157 1257
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index ff76f64edac..f6b62e7398a 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -34,6 +34,7 @@
34#include "cimax2.h" 34#include "cimax2.h"
35#include "cx23888-ir.h" 35#include "cx23888-ir.h"
36#include "cx23885-ir.h" 36#include "cx23885-ir.h"
37#include "cx23885-av.h"
37#include "cx23885-input.h" 38#include "cx23885-input.h"
38 39
39MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); 40MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
@@ -299,6 +300,83 @@ static struct sram_channel cx23887_sram_channels[] = {
299 }, 300 },
300}; 301};
301 302
303void cx23885_irq_add(struct cx23885_dev *dev, u32 mask)
304{
305 unsigned long flags;
306 spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
307
308 dev->pci_irqmask |= mask;
309
310 spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
311}
312
313void cx23885_irq_add_enable(struct cx23885_dev *dev, u32 mask)
314{
315 unsigned long flags;
316 spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
317
318 dev->pci_irqmask |= mask;
319 cx_set(PCI_INT_MSK, mask);
320
321 spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
322}
323
324void cx23885_irq_enable(struct cx23885_dev *dev, u32 mask)
325{
326 u32 v;
327 unsigned long flags;
328 spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
329
330 v = mask & dev->pci_irqmask;
331 if (v)
332 cx_set(PCI_INT_MSK, v);
333
334 spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
335}
336
337static inline void cx23885_irq_enable_all(struct cx23885_dev *dev)
338{
339 cx23885_irq_enable(dev, 0xffffffff);
340}
341
342void cx23885_irq_disable(struct cx23885_dev *dev, u32 mask)
343{
344 unsigned long flags;
345 spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
346
347 cx_clear(PCI_INT_MSK, mask);
348
349 spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
350}
351
352static inline void cx23885_irq_disable_all(struct cx23885_dev *dev)
353{
354 cx23885_irq_disable(dev, 0xffffffff);
355}
356
357void cx23885_irq_remove(struct cx23885_dev *dev, u32 mask)
358{
359 unsigned long flags;
360 spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
361
362 dev->pci_irqmask &= ~mask;
363 cx_clear(PCI_INT_MSK, mask);
364
365 spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
366}
367
368static u32 cx23885_irq_get_mask(struct cx23885_dev *dev)
369{
370 u32 v;
371 unsigned long flags;
372 spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
373
374 v = cx_read(PCI_INT_MSK);
375
376 spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
377 return v;
378}
379
302static int cx23885_risc_decode(u32 risc) 380static int cx23885_risc_decode(u32 risc)
303{ 381{
304 static char *instr[16] = { 382 static char *instr[16] = {
@@ -548,7 +626,7 @@ static void cx23885_shutdown(struct cx23885_dev *dev)
548 cx_write(UART_CTL, 0); 626 cx_write(UART_CTL, 0);
549 627
550 /* Disable Interrupts */ 628 /* Disable Interrupts */
551 cx_write(PCI_INT_MSK, 0); 629 cx23885_irq_disable_all(dev);
552 cx_write(VID_A_INT_MSK, 0); 630 cx_write(VID_A_INT_MSK, 0);
553 cx_write(VID_B_INT_MSK, 0); 631 cx_write(VID_B_INT_MSK, 0);
554 cx_write(VID_C_INT_MSK, 0); 632 cx_write(VID_C_INT_MSK, 0);
@@ -774,6 +852,8 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
774{ 852{
775 int i; 853 int i;
776 854
855 spin_lock_init(&dev->pci_irqmask_lock);
856
777 mutex_init(&dev->lock); 857 mutex_init(&dev->lock);
778 mutex_init(&dev->gpio_lock); 858 mutex_init(&dev->gpio_lock);
779 859
@@ -820,9 +900,9 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
820 900
821 dev->pci_bus = dev->pci->bus->number; 901 dev->pci_bus = dev->pci->bus->number;
822 dev->pci_slot = PCI_SLOT(dev->pci->devfn); 902 dev->pci_slot = PCI_SLOT(dev->pci->devfn);
823 dev->pci_irqmask = 0x001f00; 903 cx23885_irq_add(dev, 0x001f00);
824 if (cx23885_boards[dev->board].cimax > 0) 904 if (cx23885_boards[dev->board].cimax > 0)
825 dev->pci_irqmask |= 0x01800000; /* for CiMaxes */ 905 cx23885_irq_add(dev, 0x01800000); /* for CiMaxes */
826 906
827 /* External Master 1 Bus */ 907 /* External Master 1 Bus */
828 dev->i2c_bus[0].nr = 0; 908 dev->i2c_bus[0].nr = 0;
@@ -1156,7 +1236,7 @@ static void cx23885_tsport_reg_dump(struct cx23885_tsport *port)
1156 dprintk(1, "%s() DEV_CNTRL2 0x%08X\n", __func__, 1236 dprintk(1, "%s() DEV_CNTRL2 0x%08X\n", __func__,
1157 cx_read(DEV_CNTRL2)); 1237 cx_read(DEV_CNTRL2));
1158 dprintk(1, "%s() PCI_INT_MSK 0x%08X\n", __func__, 1238 dprintk(1, "%s() PCI_INT_MSK 0x%08X\n", __func__,
1159 cx_read(PCI_INT_MSK)); 1239 cx23885_irq_get_mask(dev));
1160 dprintk(1, "%s() AUD_INT_INT_MSK 0x%08X\n", __func__, 1240 dprintk(1, "%s() AUD_INT_INT_MSK 0x%08X\n", __func__,
1161 cx_read(AUDIO_INT_INT_MSK)); 1241 cx_read(AUDIO_INT_INT_MSK));
1162 dprintk(1, "%s() AUD_INT_DMA_CTL 0x%08X\n", __func__, 1242 dprintk(1, "%s() AUD_INT_DMA_CTL 0x%08X\n", __func__,
@@ -1292,7 +1372,8 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
1292 dprintk(1, "%s() enabling TS int's and DMA\n", __func__); 1372 dprintk(1, "%s() enabling TS int's and DMA\n", __func__);
1293 cx_set(port->reg_ts_int_msk, port->ts_int_msk_val); 1373 cx_set(port->reg_ts_int_msk, port->ts_int_msk_val);
1294 cx_set(port->reg_dma_ctl, port->dma_ctl_val); 1374 cx_set(port->reg_dma_ctl, port->dma_ctl_val);
1295 cx_set(PCI_INT_MSK, dev->pci_irqmask | port->pci_irqmask); 1375 cx23885_irq_add(dev, port->pci_irqmask);
1376 cx23885_irq_enable_all(dev);
1296 break; 1377 break;
1297 default: 1378 default:
1298 BUG(); 1379 BUG();
@@ -1650,10 +1731,10 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1650 u32 ts1_status, ts1_mask; 1731 u32 ts1_status, ts1_mask;
1651 u32 ts2_status, ts2_mask; 1732 u32 ts2_status, ts2_mask;
1652 int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0; 1733 int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0;
1653 bool ir_handled = false; 1734 bool subdev_handled;
1654 1735
1655 pci_status = cx_read(PCI_INT_STAT); 1736 pci_status = cx_read(PCI_INT_STAT);
1656 pci_mask = cx_read(PCI_INT_MSK); 1737 pci_mask = cx23885_irq_get_mask(dev);
1657 vida_status = cx_read(VID_A_INT_STAT); 1738 vida_status = cx_read(VID_A_INT_STAT);
1658 vida_mask = cx_read(VID_A_INT_MSK); 1739 vida_mask = cx_read(VID_A_INT_MSK);
1659 ts1_status = cx_read(VID_B_INT_STAT); 1740 ts1_status = cx_read(VID_B_INT_STAT);
@@ -1681,7 +1762,7 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1681 PCI_MSK_VID_C | PCI_MSK_VID_B | PCI_MSK_VID_A | 1762 PCI_MSK_VID_C | PCI_MSK_VID_B | PCI_MSK_VID_A |
1682 PCI_MSK_AUD_INT | PCI_MSK_AUD_EXT | 1763 PCI_MSK_AUD_INT | PCI_MSK_AUD_EXT |
1683 PCI_MSK_GPIO0 | PCI_MSK_GPIO1 | 1764 PCI_MSK_GPIO0 | PCI_MSK_GPIO1 |
1684 PCI_MSK_IR)) { 1765 PCI_MSK_AV_CORE | PCI_MSK_IR)) {
1685 1766
1686 if (pci_status & PCI_MSK_RISC_RD) 1767 if (pci_status & PCI_MSK_RISC_RD)
1687 dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n", 1768 dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n",
@@ -1731,6 +1812,10 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1731 dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n", 1812 dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n",
1732 PCI_MSK_GPIO1); 1813 PCI_MSK_GPIO1);
1733 1814
1815 if (pci_status & PCI_MSK_AV_CORE)
1816 dprintk(7, " (PCI_MSK_AV_CORE 0x%08x)\n",
1817 PCI_MSK_AV_CORE);
1818
1734 if (pci_status & PCI_MSK_IR) 1819 if (pci_status & PCI_MSK_IR)
1735 dprintk(7, " (PCI_MSK_IR 0x%08x)\n", 1820 dprintk(7, " (PCI_MSK_IR 0x%08x)\n",
1736 PCI_MSK_IR); 1821 PCI_MSK_IR);
@@ -1765,12 +1850,22 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
1765 handled += cx23885_video_irq(dev, vida_status); 1850 handled += cx23885_video_irq(dev, vida_status);
1766 1851
1767 if (pci_status & PCI_MSK_IR) { 1852 if (pci_status & PCI_MSK_IR) {
1768 v4l2_subdev_call(dev->sd_ir, ir, interrupt_service_routine, 1853 subdev_handled = false;
1769 pci_status, &ir_handled); 1854 v4l2_subdev_call(dev->sd_ir, core, interrupt_service_routine,
1770 if (ir_handled) 1855 pci_status, &subdev_handled);
1856 if (subdev_handled)
1771 handled++; 1857 handled++;
1772 } 1858 }
1773 1859
1860 if ((pci_status & pci_mask) & PCI_MSK_AV_CORE) {
1861 cx23885_irq_disable(dev, PCI_MSK_AV_CORE);
1862 if (!schedule_work(&dev->cx25840_work))
1863 printk(KERN_ERR "%s: failed to set up deferred work for"
1864 " AV Core/IR interrupt. Interrupt is disabled"
1865 " and won't be re-enabled\n", dev->name);
1866 handled++;
1867 }
1868
1774 if (handled) 1869 if (handled)
1775 cx_write(PCI_INT_STAT, pci_status); 1870 cx_write(PCI_INT_STAT, pci_status);
1776out: 1871out:
@@ -1788,11 +1883,11 @@ static void cx23885_v4l2_dev_notify(struct v4l2_subdev *sd,
1788 dev = to_cx23885(sd->v4l2_dev); 1883 dev = to_cx23885(sd->v4l2_dev);
1789 1884
1790 switch (notification) { 1885 switch (notification) {
1791 case V4L2_SUBDEV_IR_RX_NOTIFY: /* Called in an IRQ context */ 1886 case V4L2_SUBDEV_IR_RX_NOTIFY: /* Possibly called in an IRQ context */
1792 if (sd == dev->sd_ir) 1887 if (sd == dev->sd_ir)
1793 cx23885_ir_rx_v4l2_dev_notify(sd, *(u32 *)arg); 1888 cx23885_ir_rx_v4l2_dev_notify(sd, *(u32 *)arg);
1794 break; 1889 break;
1795 case V4L2_SUBDEV_IR_TX_NOTIFY: /* Called in an IRQ context */ 1890 case V4L2_SUBDEV_IR_TX_NOTIFY: /* Possibly called in an IRQ context */
1796 if (sd == dev->sd_ir) 1891 if (sd == dev->sd_ir)
1797 cx23885_ir_tx_v4l2_dev_notify(sd, *(u32 *)arg); 1892 cx23885_ir_tx_v4l2_dev_notify(sd, *(u32 *)arg);
1798 break; 1893 break;
@@ -1801,6 +1896,7 @@ static void cx23885_v4l2_dev_notify(struct v4l2_subdev *sd,
1801 1896
1802static void cx23885_v4l2_dev_notify_init(struct cx23885_dev *dev) 1897static void cx23885_v4l2_dev_notify_init(struct cx23885_dev *dev)
1803{ 1898{
1899 INIT_WORK(&dev->cx25840_work, cx23885_av_work_handler);
1804 INIT_WORK(&dev->ir_rx_work, cx23885_ir_rx_work_handler); 1900 INIT_WORK(&dev->ir_rx_work, cx23885_ir_rx_work_handler);
1805 INIT_WORK(&dev->ir_tx_work, cx23885_ir_tx_work_handler); 1901 INIT_WORK(&dev->ir_tx_work, cx23885_ir_tx_work_handler);
1806 dev->v4l2_dev.notify = cx23885_v4l2_dev_notify; 1902 dev->v4l2_dev.notify = cx23885_v4l2_dev_notify;
@@ -1967,7 +2063,7 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
1967 2063
1968 switch (dev->board) { 2064 switch (dev->board) {
1969 case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: 2065 case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
1970 cx_set(PCI_INT_MSK, 0x01800000); /* for NetUP */ 2066 cx23885_irq_add_enable(dev, 0x01800000); /* for NetUP */
1971 break; 2067 break;
1972 } 2068 }
1973 2069
diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c
index d4746e06451..1a391486e55 100644
--- a/drivers/media/video/cx23885/cx23885-i2c.c
+++ b/drivers/media/video/cx23885/cx23885-i2c.c
@@ -99,7 +99,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
99 if (!i2c_wait_done(i2c_adap)) 99 if (!i2c_wait_done(i2c_adap))
100 return -EIO; 100 return -EIO;
101 if (!i2c_slave_did_ack(i2c_adap)) 101 if (!i2c_slave_did_ack(i2c_adap))
102 return -EIO; 102 return -ENXIO;
103 103
104 dprintk(1, "%s() returns 0\n", __func__); 104 dprintk(1, "%s() returns 0\n", __func__);
105 return 0; 105 return 0;
@@ -120,11 +120,12 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
120 cx_write(bus->reg_wdata, wdata); 120 cx_write(bus->reg_wdata, wdata);
121 cx_write(bus->reg_ctrl, ctrl); 121 cx_write(bus->reg_ctrl, ctrl);
122 122
123 retval = i2c_wait_done(i2c_adap); 123 if (!i2c_wait_done(i2c_adap))
124 if (retval < 0)
125 goto err;
126 if (retval == 0)
127 goto eio; 124 goto eio;
125 if (!i2c_slave_did_ack(i2c_adap)) {
126 retval = -ENXIO;
127 goto err;
128 }
128 if (i2c_debug) { 129 if (i2c_debug) {
129 printk(" <W %02x %02x", msg->addr << 1, msg->buf[0]); 130 printk(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
130 if (!(ctrl & I2C_NOSTOP)) 131 if (!(ctrl & I2C_NOSTOP))
@@ -145,10 +146,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
145 cx_write(bus->reg_wdata, wdata); 146 cx_write(bus->reg_wdata, wdata);
146 cx_write(bus->reg_ctrl, ctrl); 147 cx_write(bus->reg_ctrl, ctrl);
147 148
148 retval = i2c_wait_done(i2c_adap); 149 if (!i2c_wait_done(i2c_adap))
149 if (retval < 0)
150 goto err;
151 if (retval == 0)
152 goto eio; 150 goto eio;
153 if (i2c_debug) { 151 if (i2c_debug) {
154 dprintk(1, " %02x", msg->buf[cnt]); 152 dprintk(1, " %02x", msg->buf[cnt]);
@@ -185,7 +183,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
185 if (!i2c_wait_done(i2c_adap)) 183 if (!i2c_wait_done(i2c_adap))
186 return -EIO; 184 return -EIO;
187 if (!i2c_slave_did_ack(i2c_adap)) 185 if (!i2c_slave_did_ack(i2c_adap))
188 return -EIO; 186 return -ENXIO;
189 187
190 188
191 dprintk(1, "%s() returns 0\n", __func__); 189 dprintk(1, "%s() returns 0\n", __func__);
@@ -209,11 +207,12 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
209 cx_write(bus->reg_addr, msg->addr << 25); 207 cx_write(bus->reg_addr, msg->addr << 25);
210 cx_write(bus->reg_ctrl, ctrl); 208 cx_write(bus->reg_ctrl, ctrl);
211 209
212 retval = i2c_wait_done(i2c_adap); 210 if (!i2c_wait_done(i2c_adap))
213 if (retval < 0)
214 goto err;
215 if (retval == 0)
216 goto eio; 211 goto eio;
212 if (cnt == 0 && !i2c_slave_did_ack(i2c_adap)) {
213 retval = -ENXIO;
214 goto err;
215 }
217 msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff; 216 msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
218 if (i2c_debug) { 217 if (i2c_debug) {
219 dprintk(1, " %02x", msg->buf[cnt]); 218 dprintk(1, " %02x", msg->buf[cnt]);
diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c
index d0b1613ede2..bb61870b8d6 100644
--- a/drivers/media/video/cx23885/cx23885-input.c
+++ b/drivers/media/video/cx23885/cx23885-input.c
@@ -44,40 +44,26 @@
44 44
45#define MODULE_NAME "cx23885" 45#define MODULE_NAME "cx23885"
46 46
47static void convert_measurement(u32 x, struct ir_raw_event *y)
48{
49 if (x == V4L2_SUBDEV_IR_PULSE_RX_SEQ_END) {
50 y->pulse = false;
51 y->duration = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
52 return;
53 }
54
55 y->pulse = (x & V4L2_SUBDEV_IR_PULSE_LEVEL_MASK) ? true : false;
56 y->duration = x & V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
57}
58
59static void cx23885_input_process_measurements(struct cx23885_dev *dev, 47static void cx23885_input_process_measurements(struct cx23885_dev *dev,
60 bool overrun) 48 bool overrun)
61{ 49{
62 struct cx23885_kernel_ir *kernel_ir = dev->kernel_ir; 50 struct cx23885_kernel_ir *kernel_ir = dev->kernel_ir;
63 struct ir_raw_event kernel_ir_event;
64 51
65 u32 sd_ir_data[64];
66 ssize_t num; 52 ssize_t num;
67 int count, i; 53 int count, i;
68 bool handle = false; 54 bool handle = false;
55 struct ir_raw_event ir_core_event[64];
69 56
70 do { 57 do {
71 num = 0; 58 num = 0;
72 v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) sd_ir_data, 59 v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ir_core_event,
73 sizeof(sd_ir_data), &num); 60 sizeof(ir_core_event), &num);
74 61
75 count = num / sizeof(u32); 62 count = num / sizeof(struct ir_raw_event);
76 63
77 for (i = 0; i < count; i++) { 64 for (i = 0; i < count; i++) {
78 convert_measurement(sd_ir_data[i], &kernel_ir_event);
79 ir_raw_event_store(kernel_ir->inp_dev, 65 ir_raw_event_store(kernel_ir->inp_dev,
80 &kernel_ir_event); 66 &ir_core_event[i]);
81 handle = true; 67 handle = true;
82 } 68 }
83 } while (num != 0); 69 } while (num != 0);
@@ -99,8 +85,10 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
99 switch (dev->board) { 85 switch (dev->board) {
100 case CX23885_BOARD_HAUPPAUGE_HVR1850: 86 case CX23885_BOARD_HAUPPAUGE_HVR1850:
101 case CX23885_BOARD_HAUPPAUGE_HVR1290: 87 case CX23885_BOARD_HAUPPAUGE_HVR1290:
88 case CX23885_BOARD_TEVII_S470:
89 case CX23885_BOARD_HAUPPAUGE_HVR1250:
102 /* 90 /*
103 * The only board we handle right now. However other boards 91 * The only boards we handle right now. However other boards
104 * using the CX2388x integrated IR controller should be similar 92 * using the CX2388x integrated IR controller should be similar
105 */ 93 */
106 break; 94 break;
@@ -148,6 +136,7 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev)
148 switch (dev->board) { 136 switch (dev->board) {
149 case CX23885_BOARD_HAUPPAUGE_HVR1850: 137 case CX23885_BOARD_HAUPPAUGE_HVR1850:
150 case CX23885_BOARD_HAUPPAUGE_HVR1290: 138 case CX23885_BOARD_HAUPPAUGE_HVR1290:
139 case CX23885_BOARD_HAUPPAUGE_HVR1250:
151 /* 140 /*
152 * The IR controller on this board only returns pulse widths. 141 * The IR controller on this board only returns pulse widths.
153 * Any other mode setting will fail to set up the device. 142 * Any other mode setting will fail to set up the device.
@@ -170,7 +159,38 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev)
170 * mark is received as low logic level; 159 * mark is received as low logic level;
171 * falling edges are detected as rising edges; etc. 160 * falling edges are detected as rising edges; etc.
172 */ 161 */
173 params.invert = true; 162 params.invert_level = true;
163 break;
164 case CX23885_BOARD_TEVII_S470:
165 /*
166 * The IR controller on this board only returns pulse widths.
167 * Any other mode setting will fail to set up the device.
168 */
169 params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
170 params.enable = true;
171 params.interrupt_enable = true;
172 params.shutdown = false;
173
174 /* Setup for a standard NEC protocol */
175 params.carrier_freq = 37917; /* Hz, 455 kHz/12 for NEC */
176 params.carrier_range_lower = 33000; /* Hz */
177 params.carrier_range_upper = 43000; /* Hz */
178 params.duty_cycle = 33; /* percent, 33 percent for NEC */
179
180 /*
181 * NEC max pulse width: (64/3)/(455 kHz/12) * 16 nec_units
182 * (64/3)/(455 kHz/12) * 16 nec_units * 1.375 = 12378022 ns
183 */
184 params.max_pulse_width = 12378022; /* ns */
185
186 /*
187 * NEC noise filter min width: (64/3)/(455 kHz/12) * 1 nec_unit
188 * (64/3)/(455 kHz/12) * 1 nec_units * 0.625 = 351648 ns
189 */
190 params.noise_filter_min_width = 351648; /* ns */
191
192 params.modulation = false;
193 params.invert_level = true;
174 break; 194 break;
175 } 195 }
176 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params); 196 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
@@ -244,12 +264,20 @@ int cx23885_input_init(struct cx23885_dev *dev)
244 switch (dev->board) { 264 switch (dev->board) {
245 case CX23885_BOARD_HAUPPAUGE_HVR1850: 265 case CX23885_BOARD_HAUPPAUGE_HVR1850:
246 case CX23885_BOARD_HAUPPAUGE_HVR1290: 266 case CX23885_BOARD_HAUPPAUGE_HVR1290:
247 /* Integrated CX23888 IR controller */ 267 case CX23885_BOARD_HAUPPAUGE_HVR1250:
268 /* Integrated CX2388[58] IR controller */
248 driver_type = RC_DRIVER_IR_RAW; 269 driver_type = RC_DRIVER_IR_RAW;
249 allowed_protos = IR_TYPE_ALL; 270 allowed_protos = IR_TYPE_ALL;
250 /* The grey Hauppauge RC-5 remote */ 271 /* The grey Hauppauge RC-5 remote */
251 rc_map = RC_MAP_RC5_HAUPPAUGE_NEW; 272 rc_map = RC_MAP_RC5_HAUPPAUGE_NEW;
252 break; 273 break;
274 case CX23885_BOARD_TEVII_S470:
275 /* Integrated CX23885 IR controller */
276 driver_type = RC_DRIVER_IR_RAW;
277 allowed_protos = IR_TYPE_ALL;
278 /* A guess at the remote */
279 rc_map = RC_MAP_TEVII_NEC;
280 break;
253 default: 281 default:
254 return -ENODEV; 282 return -ENODEV;
255 } 283 }
diff --git a/drivers/media/video/cx23885/cx23885-ir.c b/drivers/media/video/cx23885/cx23885-ir.c
index 6ceabd4fba0..7125247dd25 100644
--- a/drivers/media/video/cx23885/cx23885-ir.c
+++ b/drivers/media/video/cx23885/cx23885-ir.c
@@ -72,7 +72,7 @@ void cx23885_ir_tx_work_handler(struct work_struct *work)
72 72
73} 73}
74 74
75/* Called in an IRQ context */ 75/* Possibly called in an IRQ context */
76void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events) 76void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
77{ 77{
78 struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev); 78 struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev);
@@ -86,10 +86,18 @@ void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
86 set_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications); 86 set_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications);
87 if (events & V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN) 87 if (events & V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN)
88 set_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications); 88 set_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications);
89 schedule_work(&dev->ir_rx_work); 89
90 /*
91 * For the integrated AV core, we are already in a workqueue context.
92 * For the CX23888 integrated IR, we are in an interrupt context.
93 */
94 if (sd == dev->sd_cx25840)
95 cx23885_ir_rx_work_handler(&dev->ir_rx_work);
96 else
97 schedule_work(&dev->ir_rx_work);
90} 98}
91 99
92/* Called in an IRQ context */ 100/* Possibly called in an IRQ context */
93void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events) 101void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
94{ 102{
95 struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev); 103 struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev);
@@ -97,5 +105,13 @@ void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
97 105
98 if (events & V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ) 106 if (events & V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ)
99 set_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications); 107 set_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications);
100 schedule_work(&dev->ir_tx_work); 108
109 /*
110 * For the integrated AV core, we are already in a workqueue context.
111 * For the CX23888 integrated IR, we are in an interrupt context.
112 */
113 if (sd == dev->sd_cx25840)
114 cx23885_ir_tx_work_handler(&dev->ir_tx_work);
115 else
116 schedule_work(&dev->ir_tx_work);
101} 117}
diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h
index c0bc9a06895..a28772db11f 100644
--- a/drivers/media/video/cx23885/cx23885-reg.h
+++ b/drivers/media/video/cx23885/cx23885-reg.h
@@ -213,6 +213,7 @@ Channel manager Data Structure entry = 20 DWORD
213#define DEV_CNTRL2 0x00040000 213#define DEV_CNTRL2 0x00040000
214 214
215#define PCI_MSK_IR (1 << 28) 215#define PCI_MSK_IR (1 << 28)
216#define PCI_MSK_AV_CORE (1 << 27)
216#define PCI_MSK_GPIO1 (1 << 24) 217#define PCI_MSK_GPIO1 (1 << 24)
217#define PCI_MSK_GPIO0 (1 << 23) 218#define PCI_MSK_GPIO0 (1 << 23)
218#define PCI_MSK_APB_DMA (1 << 12) 219#define PCI_MSK_APB_DMA (1 << 12)
diff --git a/drivers/media/video/cx23885/cx23885-vbi.c b/drivers/media/video/cx23885/cx23885-vbi.c
index 708a8c766d1..c0b60382ad1 100644
--- a/drivers/media/video/cx23885/cx23885-vbi.c
+++ b/drivers/media/video/cx23885/cx23885-vbi.c
@@ -74,7 +74,7 @@ static int cx23885_start_vbi_dma(struct cx23885_dev *dev,
74 q->count = 1; 74 q->count = 1;
75 75
76 /* enable irqs */ 76 /* enable irqs */
77 cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | 0x01); 77 cx23885_irq_add_enable(dev, 0x01);
78 cx_set(VID_A_INT_MSK, 0x000022); 78 cx_set(VID_A_INT_MSK, 0x000022);
79 79
80 /* start dma */ 80 /* start dma */
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index 4e44dcda387..da66e5f8d91 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -441,7 +441,7 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev,
441 q->count = 1; 441 q->count = 1;
442 442
443 /* enable irq */ 443 /* enable irq */
444 cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | 0x01); 444 cx23885_irq_add_enable(dev, 0x01);
445 cx_set(VID_A_INT_MSK, 0x000011); 445 cx_set(VID_A_INT_MSK, 0x000011);
446 446
447 /* start dma */ 447 /* start dma */
@@ -1205,6 +1205,21 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1205 return 0; 1205 return 0;
1206} 1206}
1207 1207
1208static int vidioc_log_status(struct file *file, void *priv)
1209{
1210 struct cx23885_fh *fh = priv;
1211 struct cx23885_dev *dev = fh->dev;
1212
1213 printk(KERN_INFO
1214 "%s/0: ============ START LOG STATUS ============\n",
1215 dev->name);
1216 call_all(dev, core, log_status);
1217 printk(KERN_INFO
1218 "%s/0: ============= END LOG STATUS =============\n",
1219 dev->name);
1220 return 0;
1221}
1222
1208static int vidioc_queryctrl(struct file *file, void *priv, 1223static int vidioc_queryctrl(struct file *file, void *priv,
1209 struct v4l2_queryctrl *qctrl) 1224 struct v4l2_queryctrl *qctrl)
1210{ 1225{
@@ -1410,6 +1425,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
1410 .vidioc_enum_input = vidioc_enum_input, 1425 .vidioc_enum_input = vidioc_enum_input,
1411 .vidioc_g_input = vidioc_g_input, 1426 .vidioc_g_input = vidioc_g_input,
1412 .vidioc_s_input = vidioc_s_input, 1427 .vidioc_s_input = vidioc_s_input,
1428 .vidioc_log_status = vidioc_log_status,
1413 .vidioc_queryctrl = vidioc_queryctrl, 1429 .vidioc_queryctrl = vidioc_queryctrl,
1414 .vidioc_g_ctrl = vidioc_g_ctrl, 1430 .vidioc_g_ctrl = vidioc_g_ctrl,
1415 .vidioc_s_ctrl = vidioc_s_ctrl, 1431 .vidioc_s_ctrl = vidioc_s_ctrl,
@@ -1449,7 +1465,7 @@ static const struct v4l2_file_operations radio_fops = {
1449void cx23885_video_unregister(struct cx23885_dev *dev) 1465void cx23885_video_unregister(struct cx23885_dev *dev)
1450{ 1466{
1451 dprintk(1, "%s()\n", __func__); 1467 dprintk(1, "%s()\n", __func__);
1452 cx_clear(PCI_INT_MSK, 1); 1468 cx23885_irq_remove(dev, 0x01);
1453 1469
1454 if (dev->video_dev) { 1470 if (dev->video_dev) {
1455 if (video_is_registered(dev->video_dev)) 1471 if (video_is_registered(dev->video_dev))
@@ -1486,7 +1502,8 @@ int cx23885_video_register(struct cx23885_dev *dev)
1486 VID_A_DMA_CTL, 0x11, 0x00); 1502 VID_A_DMA_CTL, 0x11, 0x00);
1487 1503
1488 /* Don't enable VBI yet */ 1504 /* Don't enable VBI yet */
1489 cx_set(PCI_INT_MSK, 1); 1505
1506 cx23885_irq_add_enable(dev, 0x01);
1490 1507
1491 if (TUNER_ABSENT != dev->tuner_type) { 1508 if (TUNER_ABSENT != dev->tuner_type) {
1492 struct v4l2_subdev *sd = NULL; 1509 struct v4l2_subdev *sd = NULL;
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
index a33f2b71467..ed94b17dd8a 100644
--- a/drivers/media/video/cx23885/cx23885.h
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -325,6 +325,7 @@ struct cx23885_dev {
325 u32 __iomem *lmmio; 325 u32 __iomem *lmmio;
326 u8 __iomem *bmmio; 326 u8 __iomem *bmmio;
327 int pci_irqmask; 327 int pci_irqmask;
328 spinlock_t pci_irqmask_lock; /* protects mask reg too */
328 int hwrevision; 329 int hwrevision;
329 330
330 /* This valud is board specific and is used to configure the 331 /* This valud is board specific and is used to configure the
@@ -365,6 +366,7 @@ struct cx23885_dev {
365 unsigned char radio_addr; 366 unsigned char radio_addr;
366 unsigned int has_radio; 367 unsigned int has_radio;
367 struct v4l2_subdev *sd_cx25840; 368 struct v4l2_subdev *sd_cx25840;
369 struct work_struct cx25840_work;
368 370
369 /* Infrared */ 371 /* Infrared */
370 struct v4l2_subdev *sd_ir; 372 struct v4l2_subdev *sd_ir;
@@ -403,7 +405,8 @@ static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev)
403#define call_all(dev, o, f, args...) \ 405#define call_all(dev, o, f, args...) \
404 v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) 406 v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args)
405 407
406#define CX23885_HW_888_IR (1 << 0) 408#define CX23885_HW_888_IR (1 << 0)
409#define CX23885_HW_AV_CORE (1 << 1)
407 410
408#define call_hw(dev, grpid, o, f, args...) \ 411#define call_hw(dev, grpid, o, f, args...) \
409 v4l2_device_call_all(&dev->v4l2_dev, grpid, o, f, ##args) 412 v4l2_device_call_all(&dev->v4l2_dev, grpid, o, f, ##args)
@@ -484,6 +487,10 @@ extern u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask);
484extern void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, 487extern void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask,
485 int asoutput); 488 int asoutput);
486 489
490extern void cx23885_irq_add_enable(struct cx23885_dev *dev, u32 mask);
491extern void cx23885_irq_enable(struct cx23885_dev *dev, u32 mask);
492extern void cx23885_irq_disable(struct cx23885_dev *dev, u32 mask);
493extern void cx23885_irq_remove(struct cx23885_dev *dev, u32 mask);
487 494
488/* ----------------------------------------------------------- */ 495/* ----------------------------------------------------------- */
489/* cx23885-cards.c */ 496/* cx23885-cards.c */
diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c
index f63d378257a..2502a0a6709 100644
--- a/drivers/media/video/cx23885/cx23888-ir.c
+++ b/drivers/media/video/cx23885/cx23888-ir.c
@@ -26,6 +26,7 @@
26 26
27#include <media/v4l2-device.h> 27#include <media/v4l2-device.h>
28#include <media/v4l2-chip-ident.h> 28#include <media/v4l2-chip-ident.h>
29#include <media/ir-core.h>
29 30
30#include "cx23885.h" 31#include "cx23885.h"
31 32
@@ -60,6 +61,8 @@ MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]");
60#define CNTRL_CPL 0x00001000 61#define CNTRL_CPL 0x00001000
61#define CNTRL_LBM 0x00002000 62#define CNTRL_LBM 0x00002000
62#define CNTRL_R 0x00004000 63#define CNTRL_R 0x00004000
64/* CX23888 specific control flag */
65#define CNTRL_IVO 0x00008000
63 66
64#define CX23888_IR_TXCLK_REG 0x170004 67#define CX23888_IR_TXCLK_REG 0x170004
65#define TXCLK_TCD 0x0000FFFF 68#define TXCLK_TCD 0x0000FFFF
@@ -111,8 +114,18 @@ MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]");
111#define CX23888_VIDCLK_FREQ 108000000 /* 108 MHz, BT.656 */ 114#define CX23888_VIDCLK_FREQ 108000000 /* 108 MHz, BT.656 */
112#define CX23888_IR_REFCLK_FREQ (CX23888_VIDCLK_FREQ / 2) 115#define CX23888_IR_REFCLK_FREQ (CX23888_VIDCLK_FREQ / 2)
113 116
114#define CX23888_IR_RX_KFIFO_SIZE (512 * sizeof(u32)) 117/*
115#define CX23888_IR_TX_KFIFO_SIZE (512 * sizeof(u32)) 118 * We use this union internally for convenience, but callers to tx_write
119 * and rx_read will be expecting records of type struct ir_raw_event.
120 * Always ensure the size of this union is dictated by struct ir_raw_event.
121 */
122union cx23888_ir_fifo_rec {
123 u32 hw_fifo_data;
124 struct ir_raw_event ir_core_data;
125};
126
127#define CX23888_IR_RX_KFIFO_SIZE (256 * sizeof(union cx23888_ir_fifo_rec))
128#define CX23888_IR_TX_KFIFO_SIZE (256 * sizeof(union cx23888_ir_fifo_rec))
116 129
117struct cx23888_ir_state { 130struct cx23888_ir_state {
118 struct v4l2_subdev sd; 131 struct v4l2_subdev sd;
@@ -423,6 +436,13 @@ static inline void control_tx_polarity_invert(struct cx23885_dev *dev,
423 invert ? CNTRL_CPL : 0); 436 invert ? CNTRL_CPL : 0);
424} 437}
425 438
439static inline void control_tx_level_invert(struct cx23885_dev *dev,
440 bool invert)
441{
442 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_IVO,
443 invert ? CNTRL_IVO : 0);
444}
445
426/* 446/*
427 * IR Rx & Tx Clock Register helpers 447 * IR Rx & Tx Clock Register helpers
428 */ 448 */
@@ -449,8 +469,8 @@ static u32 txclk_tx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns,
449{ 469{
450 u64 pulse_clocks; 470 u64 pulse_clocks;
451 471
452 if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS) 472 if (ns > IR_MAX_DURATION)
453 ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; 473 ns = IR_MAX_DURATION;
454 pulse_clocks = ns_to_pulse_clocks(ns); 474 pulse_clocks = ns_to_pulse_clocks(ns);
455 *divider = pulse_clocks_to_clock_divider(pulse_clocks); 475 *divider = pulse_clocks_to_clock_divider(pulse_clocks);
456 cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider); 476 cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider);
@@ -462,8 +482,8 @@ static u32 rxclk_rx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns,
462{ 482{
463 u64 pulse_clocks; 483 u64 pulse_clocks;
464 484
465 if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS) 485 if (ns > IR_MAX_DURATION)
466 ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; 486 ns = IR_MAX_DURATION;
467 pulse_clocks = ns_to_pulse_clocks(ns); 487 pulse_clocks = ns_to_pulse_clocks(ns);
468 *divider = pulse_clocks_to_clock_divider(pulse_clocks); 488 *divider = pulse_clocks_to_clock_divider(pulse_clocks);
469 cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider); 489 cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider);
@@ -526,8 +546,8 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
526 u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG); 546 u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
527 u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG); 547 u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG);
528 548
529 u32 rx_data[FIFO_RX_DEPTH]; 549 union cx23888_ir_fifo_rec rx_data[FIFO_RX_DEPTH];
530 int i, j, k; 550 unsigned int i, j, k;
531 u32 events, v; 551 u32 events, v;
532 int tsr, rsr, rto, ror, tse, rse, rte, roe, kror; 552 int tsr, rsr, rto, ror, tse, rse, rte, roe, kror;
533 553
@@ -588,11 +608,12 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
588 for (j = 0; 608 for (j = 0;
589 (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) { 609 (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) {
590 v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG); 610 v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG);
591 rx_data[i++] = v & ~FIFO_RX_NDV; 611 rx_data[i].hw_fifo_data = v & ~FIFO_RX_NDV;
612 i++;
592 } 613 }
593 if (i == 0) 614 if (i == 0)
594 break; 615 break;
595 j = i * sizeof(u32); 616 j = i * sizeof(union cx23888_ir_fifo_rec);
596 k = kfifo_in_locked(&state->rx_kfifo, 617 k = kfifo_in_locked(&state->rx_kfifo,
597 (unsigned char *) rx_data, j, 618 (unsigned char *) rx_data, j,
598 &state->rx_kfifo_lock); 619 &state->rx_kfifo_lock);
@@ -651,10 +672,11 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
651 u16 divider = (u16) atomic_read(&state->rxclk_divider); 672 u16 divider = (u16) atomic_read(&state->rxclk_divider);
652 673
653 unsigned int i, n; 674 unsigned int i, n;
654 u32 *p; 675 union cx23888_ir_fifo_rec *p;
655 u32 u, v; 676 unsigned u, v;
656 677
657 n = count / sizeof(u32) * sizeof(u32); 678 n = count / sizeof(union cx23888_ir_fifo_rec)
679 * sizeof(union cx23888_ir_fifo_rec);
658 if (n == 0) { 680 if (n == 0) {
659 *num = 0; 681 *num = 0;
660 return 0; 682 return 0;
@@ -662,26 +684,28 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
662 684
663 n = kfifo_out_locked(&state->rx_kfifo, buf, n, &state->rx_kfifo_lock); 685 n = kfifo_out_locked(&state->rx_kfifo, buf, n, &state->rx_kfifo_lock);
664 686
665 n /= sizeof(u32); 687 n /= sizeof(union cx23888_ir_fifo_rec);
666 *num = n * sizeof(u32); 688 *num = n * sizeof(union cx23888_ir_fifo_rec);
689
690 for (p = (union cx23888_ir_fifo_rec *) buf, i = 0; i < n; p++, i++) {
667 691
668 for (p = (u32 *) buf, i = 0; i < n; p++, i++) { 692 if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
669 if ((*p & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) { 693 /* Assume RTO was because of no IR light input */
670 *p = V4L2_SUBDEV_IR_PULSE_RX_SEQ_END; 694 u = 0;
671 v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n"); 695 v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n");
672 continue; 696 } else {
697 u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
698 if (invert)
699 u = u ? 0 : 1;
673 } 700 }
674 701
675 u = (*p & FIFO_RXTX_LVL) ? V4L2_SUBDEV_IR_PULSE_LEVEL_MASK : 0; 702 v = (unsigned) pulse_width_count_to_ns(
676 if (invert) 703 (u16) (p->hw_fifo_data & FIFO_RXTX), divider);
677 u = u ? 0 : V4L2_SUBDEV_IR_PULSE_LEVEL_MASK; 704 if (v > IR_MAX_DURATION)
705 v = IR_MAX_DURATION;
678 706
679 v = (u32) pulse_width_count_to_ns((u16) (*p & FIFO_RXTX), 707 p->ir_core_data.pulse = u;
680 divider); 708 p->ir_core_data.duration = v;
681 if (v >= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS)
682 v = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS - 1;
683
684 *p = u | v;
685 709
686 v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns %s\n", 710 v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns %s\n",
687 v, u ? "mark" : "space"); 711 v, u ? "mark" : "space");
@@ -740,7 +764,8 @@ static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd,
740 764
741 o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; 765 o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
742 766
743 o->bytes_per_data_element = p->bytes_per_data_element = sizeof(u32); 767 o->bytes_per_data_element = p->bytes_per_data_element
768 = sizeof(union cx23888_ir_fifo_rec);
744 769
745 /* Before we tweak the hardware, we have to disable the receiver */ 770 /* Before we tweak the hardware, we have to disable the receiver */
746 irqenable_rx(dev, 0); 771 irqenable_rx(dev, 0);
@@ -762,12 +787,15 @@ static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd,
762 &p->carrier_range_upper); 787 &p->carrier_range_upper);
763 o->carrier_range_lower = p->carrier_range_lower; 788 o->carrier_range_lower = p->carrier_range_lower;
764 o->carrier_range_upper = p->carrier_range_upper; 789 o->carrier_range_upper = p->carrier_range_upper;
790
791 p->max_pulse_width =
792 (u32) pulse_width_count_to_ns(FIFO_RXTX, rxclk_divider);
765 } else { 793 } else {
766 p->max_pulse_width = 794 p->max_pulse_width =
767 rxclk_rx_s_max_pulse_width(dev, p->max_pulse_width, 795 rxclk_rx_s_max_pulse_width(dev, p->max_pulse_width,
768 &rxclk_divider); 796 &rxclk_divider);
769 o->max_pulse_width = p->max_pulse_width;
770 } 797 }
798 o->max_pulse_width = p->max_pulse_width;
771 atomic_set(&state->rxclk_divider, rxclk_divider); 799 atomic_set(&state->rxclk_divider, rxclk_divider);
772 800
773 p->noise_filter_min_width = 801 p->noise_filter_min_width =
@@ -782,8 +810,8 @@ static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd,
782 810
783 control_rx_s_edge_detection(dev, CNTRL_EDG_BOTH); 811 control_rx_s_edge_detection(dev, CNTRL_EDG_BOTH);
784 812
785 o->invert = p->invert; 813 o->invert_level = p->invert_level;
786 atomic_set(&state->rx_invert, p->invert); 814 atomic_set(&state->rx_invert, p->invert_level);
787 815
788 o->interrupt_enable = p->interrupt_enable; 816 o->interrupt_enable = p->interrupt_enable;
789 o->enable = p->enable; 817 o->enable = p->enable;
@@ -864,7 +892,8 @@ static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd,
864 892
865 o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; 893 o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
866 894
867 o->bytes_per_data_element = p->bytes_per_data_element = sizeof(u32); 895 o->bytes_per_data_element = p->bytes_per_data_element
896 = sizeof(union cx23888_ir_fifo_rec);
868 897
869 /* Before we tweak the hardware, we have to disable the transmitter */ 898 /* Before we tweak the hardware, we have to disable the transmitter */
870 irqenable_tx(dev, 0); 899 irqenable_tx(dev, 0);
@@ -880,12 +909,15 @@ static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd,
880 909
881 p->duty_cycle = cduty_tx_s_duty_cycle(dev, p->duty_cycle); 910 p->duty_cycle = cduty_tx_s_duty_cycle(dev, p->duty_cycle);
882 o->duty_cycle = p->duty_cycle; 911 o->duty_cycle = p->duty_cycle;
912
913 p->max_pulse_width =
914 (u32) pulse_width_count_to_ns(FIFO_RXTX, txclk_divider);
883 } else { 915 } else {
884 p->max_pulse_width = 916 p->max_pulse_width =
885 txclk_tx_s_max_pulse_width(dev, p->max_pulse_width, 917 txclk_tx_s_max_pulse_width(dev, p->max_pulse_width,
886 &txclk_divider); 918 &txclk_divider);
887 o->max_pulse_width = p->max_pulse_width;
888 } 919 }
920 o->max_pulse_width = p->max_pulse_width;
889 atomic_set(&state->txclk_divider, txclk_divider); 921 atomic_set(&state->txclk_divider, txclk_divider);
890 922
891 p->resolution = clock_divider_to_resolution(txclk_divider); 923 p->resolution = clock_divider_to_resolution(txclk_divider);
@@ -894,8 +926,11 @@ static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd,
894 /* FIXME - make this dependent on resolution for better performance */ 926 /* FIXME - make this dependent on resolution for better performance */
895 control_tx_irq_watermark(dev, TX_FIFO_HALF_EMPTY); 927 control_tx_irq_watermark(dev, TX_FIFO_HALF_EMPTY);
896 928
897 control_tx_polarity_invert(dev, p->invert); 929 control_tx_polarity_invert(dev, p->invert_carrier_sense);
898 o->invert = p->invert; 930 o->invert_carrier_sense = p->invert_carrier_sense;
931
932 control_tx_level_invert(dev, p->invert_level);
933 o->invert_level = p->invert_level;
899 934
900 o->interrupt_enable = p->interrupt_enable; 935 o->interrupt_enable = p->interrupt_enable;
901 o->enable = p->enable; 936 o->enable = p->enable;
@@ -988,12 +1023,10 @@ static int cx23888_ir_log_status(struct v4l2_subdev *sd)
988 "-%1d/+%1d, %u to %u Hz\n", i, j, 1023 "-%1d/+%1d, %u to %u Hz\n", i, j,
989 clock_divider_to_freq(rxclk, 16 + j), 1024 clock_divider_to_freq(rxclk, 16 + j),
990 clock_divider_to_freq(rxclk, 16 - i)); 1025 clock_divider_to_freq(rxclk, 16 - i));
991 } else {
992 v4l2_info(sd, "\tMax measurable pulse width: %u us, "
993 "%llu ns\n",
994 pulse_width_count_to_us(FIFO_RXTX, rxclk),
995 pulse_width_count_to_ns(FIFO_RXTX, rxclk));
996 } 1026 }
1027 v4l2_info(sd, "\tMax measurable pulse width: %u us, %llu ns\n",
1028 pulse_width_count_to_us(FIFO_RXTX, rxclk),
1029 pulse_width_count_to_ns(FIFO_RXTX, rxclk));
997 v4l2_info(sd, "\tLow pass filter: %s\n", 1030 v4l2_info(sd, "\tLow pass filter: %s\n",
998 filtr ? "enabled" : "disabled"); 1031 filtr ? "enabled" : "disabled");
999 if (filtr) 1032 if (filtr)
@@ -1025,19 +1058,20 @@ static int cx23888_ir_log_status(struct v4l2_subdev *sd)
1025 cntrl & CNTRL_TFE ? "enabled" : "disabled"); 1058 cntrl & CNTRL_TFE ? "enabled" : "disabled");
1026 v4l2_info(sd, "\tFIFO interrupt watermark: %s\n", 1059 v4l2_info(sd, "\tFIFO interrupt watermark: %s\n",
1027 cntrl & CNTRL_TIC ? "not empty" : "half full or less"); 1060 cntrl & CNTRL_TIC ? "not empty" : "half full or less");
1028 v4l2_info(sd, "\tSignal polarity: %s\n", 1061 v4l2_info(sd, "\tOutput pin level inversion %s\n",
1029 cntrl & CNTRL_CPL ? "0:mark 1:space" : "0:space 1:mark"); 1062 cntrl & CNTRL_IVO ? "yes" : "no");
1063 v4l2_info(sd, "\tCarrier polarity: %s\n",
1064 cntrl & CNTRL_CPL ? "space:burst mark:noburst"
1065 : "space:noburst mark:burst");
1030 if (cntrl & CNTRL_MOD) { 1066 if (cntrl & CNTRL_MOD) {
1031 v4l2_info(sd, "\tCarrier (16 clocks): %u Hz\n", 1067 v4l2_info(sd, "\tCarrier (16 clocks): %u Hz\n",
1032 clock_divider_to_carrier_freq(txclk)); 1068 clock_divider_to_carrier_freq(txclk));
1033 v4l2_info(sd, "\tCarrier duty cycle: %2u/16\n", 1069 v4l2_info(sd, "\tCarrier duty cycle: %2u/16\n",
1034 cduty + 1); 1070 cduty + 1);
1035 } else {
1036 v4l2_info(sd, "\tMax pulse width: %u us, "
1037 "%llu ns\n",
1038 pulse_width_count_to_us(FIFO_RXTX, txclk),
1039 pulse_width_count_to_ns(FIFO_RXTX, txclk));
1040 } 1071 }
1072 v4l2_info(sd, "\tMax pulse width: %u us, %llu ns\n",
1073 pulse_width_count_to_us(FIFO_RXTX, txclk),
1074 pulse_width_count_to_ns(FIFO_RXTX, txclk));
1041 v4l2_info(sd, "\tBusy: %s\n", 1075 v4l2_info(sd, "\tBusy: %s\n",
1042 stats & STATS_TBY ? "yes" : "no"); 1076 stats & STATS_TBY ? "yes" : "no");
1043 v4l2_info(sd, "\tFIFO service requested: %s\n", 1077 v4l2_info(sd, "\tFIFO service requested: %s\n",
@@ -1111,11 +1145,10 @@ static const struct v4l2_subdev_core_ops cx23888_ir_core_ops = {
1111 .g_register = cx23888_ir_g_register, 1145 .g_register = cx23888_ir_g_register,
1112 .s_register = cx23888_ir_s_register, 1146 .s_register = cx23888_ir_s_register,
1113#endif 1147#endif
1148 .interrupt_service_routine = cx23888_ir_irq_handler,
1114}; 1149};
1115 1150
1116static const struct v4l2_subdev_ir_ops cx23888_ir_ir_ops = { 1151static const struct v4l2_subdev_ir_ops cx23888_ir_ir_ops = {
1117 .interrupt_service_routine = cx23888_ir_irq_handler,
1118
1119 .rx_read = cx23888_ir_rx_read, 1152 .rx_read = cx23888_ir_rx_read,
1120 .rx_g_parameters = cx23888_ir_rx_g_parameters, 1153 .rx_g_parameters = cx23888_ir_rx_g_parameters,
1121 .rx_s_parameters = cx23888_ir_rx_s_parameters, 1154 .rx_s_parameters = cx23888_ir_rx_s_parameters,
@@ -1131,7 +1164,7 @@ static const struct v4l2_subdev_ops cx23888_ir_controller_ops = {
1131}; 1164};
1132 1165
1133static const struct v4l2_subdev_ir_parameters default_rx_params = { 1166static const struct v4l2_subdev_ir_parameters default_rx_params = {
1134 .bytes_per_data_element = sizeof(u32), 1167 .bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec),
1135 .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH, 1168 .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
1136 1169
1137 .enable = false, 1170 .enable = false,
@@ -1146,11 +1179,11 @@ static const struct v4l2_subdev_ir_parameters default_rx_params = {
1146 .noise_filter_min_width = 333333, /* ns */ 1179 .noise_filter_min_width = 333333, /* ns */
1147 .carrier_range_lower = 35000, 1180 .carrier_range_lower = 35000,
1148 .carrier_range_upper = 37000, 1181 .carrier_range_upper = 37000,
1149 .invert = false, 1182 .invert_level = false,
1150}; 1183};
1151 1184
1152static const struct v4l2_subdev_ir_parameters default_tx_params = { 1185static const struct v4l2_subdev_ir_parameters default_tx_params = {
1153 .bytes_per_data_element = sizeof(u32), 1186 .bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec),
1154 .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH, 1187 .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
1155 1188
1156 .enable = false, 1189 .enable = false,
@@ -1160,7 +1193,8 @@ static const struct v4l2_subdev_ir_parameters default_tx_params = {
1160 .modulation = true, 1193 .modulation = true,
1161 .carrier_freq = 36000, /* 36 kHz - RC-5 carrier */ 1194 .carrier_freq = 36000, /* 36 kHz - RC-5 carrier */
1162 .duty_cycle = 25, /* 25 % - RC-5 carrier */ 1195 .duty_cycle = 25, /* 25 % - RC-5 carrier */
1163 .invert = false, 1196 .invert_level = false,
1197 .invert_carrier_sense = false,
1164}; 1198};
1165 1199
1166int cx23888_ir_probe(struct cx23885_dev *dev) 1200int cx23888_ir_probe(struct cx23885_dev *dev)
diff --git a/drivers/media/video/cx25840/Makefile b/drivers/media/video/cx25840/Makefile
index 6e8665be895..2ee96d3973b 100644
--- a/drivers/media/video/cx25840/Makefile
+++ b/drivers/media/video/cx25840/Makefile
@@ -1,5 +1,5 @@
1cx25840-objs := cx25840-core.o cx25840-audio.o cx25840-firmware.o \ 1cx25840-objs := cx25840-core.o cx25840-audio.o cx25840-firmware.o \
2 cx25840-vbi.o 2 cx25840-vbi.o cx25840-ir.o
3 3
4obj-$(CONFIG_VIDEO_CX25840) += cx25840.o 4obj-$(CONFIG_VIDEO_CX25840) += cx25840.o
5 5
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c
index 45608d50529..6faad34df3a 100644
--- a/drivers/media/video/cx25840/cx25840-audio.c
+++ b/drivers/media/video/cx25840/cx25840-audio.c
@@ -474,33 +474,10 @@ void cx25840_audio_set_path(struct i2c_client *client)
474 cx25840_and_or(client, 0x803, ~0x10, 0x10); 474 cx25840_and_or(client, 0x803, ~0x10, 0x10);
475} 475}
476 476
477static int get_volume(struct i2c_client *client)
478{
479 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
480 int vol;
481
482 if (state->unmute_volume >= 0)
483 return state->unmute_volume;
484
485 /* Volume runs +18dB to -96dB in 1/2dB steps
486 * change to fit the msp3400 -114dB to +12dB range */
487
488 /* check PATH1_VOLUME */
489 vol = 228 - cx25840_read(client, 0x8d4);
490 vol = (vol / 2) + 23;
491 return vol << 9;
492}
493
494static void set_volume(struct i2c_client *client, int volume) 477static void set_volume(struct i2c_client *client, int volume)
495{ 478{
496 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
497 int vol; 479 int vol;
498 480
499 if (state->unmute_volume >= 0) {
500 state->unmute_volume = volume;
501 return;
502 }
503
504 /* Convert the volume to msp3400 values (0-127) */ 481 /* Convert the volume to msp3400 values (0-127) */
505 vol = volume >> 9; 482 vol = volume >> 9;
506 483
@@ -517,52 +494,6 @@ static void set_volume(struct i2c_client *client, int volume)
517 cx25840_write(client, 0x8d4, 228 - (vol * 2)); 494 cx25840_write(client, 0x8d4, 228 - (vol * 2));
518} 495}
519 496
520static int get_bass(struct i2c_client *client)
521{
522 /* bass is 49 steps +12dB to -12dB */
523
524 /* check PATH1_EQ_BASS_VOL */
525 int bass = cx25840_read(client, 0x8d9) & 0x3f;
526 bass = (((48 - bass) * 0xffff) + 47) / 48;
527 return bass;
528}
529
530static void set_bass(struct i2c_client *client, int bass)
531{
532 /* PATH1_EQ_BASS_VOL */
533 cx25840_and_or(client, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
534}
535
536static int get_treble(struct i2c_client *client)
537{
538 /* treble is 49 steps +12dB to -12dB */
539
540 /* check PATH1_EQ_TREBLE_VOL */
541 int treble = cx25840_read(client, 0x8db) & 0x3f;
542 treble = (((48 - treble) * 0xffff) + 47) / 48;
543 return treble;
544}
545
546static void set_treble(struct i2c_client *client, int treble)
547{
548 /* PATH1_EQ_TREBLE_VOL */
549 cx25840_and_or(client, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
550}
551
552static int get_balance(struct i2c_client *client)
553{
554 /* balance is 7 bit, 0 to -96dB */
555
556 /* check PATH1_BAL_LEVEL */
557 int balance = cx25840_read(client, 0x8d5) & 0x7f;
558 /* check PATH1_BAL_LEFT */
559 if ((cx25840_read(client, 0x8d5) & 0x80) == 0)
560 balance = 0x80 - balance;
561 else
562 balance = 0x80 + balance;
563 return balance << 8;
564}
565
566static void set_balance(struct i2c_client *client, int balance) 497static void set_balance(struct i2c_client *client, int balance)
567{ 498{
568 int bal = balance >> 8; 499 int bal = balance >> 8;
@@ -579,31 +510,6 @@ static void set_balance(struct i2c_client *client, int balance)
579 } 510 }
580} 511}
581 512
582static int get_mute(struct i2c_client *client)
583{
584 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
585
586 return state->unmute_volume >= 0;
587}
588
589static void set_mute(struct i2c_client *client, int mute)
590{
591 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
592
593 if (mute && state->unmute_volume == -1) {
594 int vol = get_volume(client);
595
596 set_volume(client, 0);
597 state->unmute_volume = vol;
598 }
599 else if (!mute && state->unmute_volume != -1) {
600 int vol = state->unmute_volume;
601
602 state->unmute_volume = -1;
603 set_volume(client, vol);
604 }
605}
606
607int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq) 513int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
608{ 514{
609 struct i2c_client *client = v4l2_get_subdevdata(sd); 515 struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -624,25 +530,31 @@ int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
624 return retval; 530 return retval;
625} 531}
626 532
627int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 533static int cx25840_audio_s_ctrl(struct v4l2_ctrl *ctrl)
628{ 534{
535 struct v4l2_subdev *sd = to_sd(ctrl);
536 struct cx25840_state *state = to_state(sd);
629 struct i2c_client *client = v4l2_get_subdevdata(sd); 537 struct i2c_client *client = v4l2_get_subdevdata(sd);
630 538
631 switch (ctrl->id) { 539 switch (ctrl->id) {
632 case V4L2_CID_AUDIO_VOLUME: 540 case V4L2_CID_AUDIO_VOLUME:
633 ctrl->value = get_volume(client); 541 if (state->mute->val)
542 set_volume(client, 0);
543 else
544 set_volume(client, state->volume->val);
634 break; 545 break;
635 case V4L2_CID_AUDIO_BASS: 546 case V4L2_CID_AUDIO_BASS:
636 ctrl->value = get_bass(client); 547 /* PATH1_EQ_BASS_VOL */
548 cx25840_and_or(client, 0x8d9, ~0x3f,
549 48 - (ctrl->val * 48 / 0xffff));
637 break; 550 break;
638 case V4L2_CID_AUDIO_TREBLE: 551 case V4L2_CID_AUDIO_TREBLE:
639 ctrl->value = get_treble(client); 552 /* PATH1_EQ_TREBLE_VOL */
553 cx25840_and_or(client, 0x8db, ~0x3f,
554 48 - (ctrl->val * 48 / 0xffff));
640 break; 555 break;
641 case V4L2_CID_AUDIO_BALANCE: 556 case V4L2_CID_AUDIO_BALANCE:
642 ctrl->value = get_balance(client); 557 set_balance(client, ctrl->val);
643 break;
644 case V4L2_CID_AUDIO_MUTE:
645 ctrl->value = get_mute(client);
646 break; 558 break;
647 default: 559 default:
648 return -EINVAL; 560 return -EINVAL;
@@ -650,28 +562,6 @@ int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
650 return 0; 562 return 0;
651} 563}
652 564
653int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 565const struct v4l2_ctrl_ops cx25840_audio_ctrl_ops = {
654{ 566 .s_ctrl = cx25840_audio_s_ctrl,
655 struct i2c_client *client = v4l2_get_subdevdata(sd); 567};
656
657 switch (ctrl->id) {
658 case V4L2_CID_AUDIO_VOLUME:
659 set_volume(client, ctrl->value);
660 break;
661 case V4L2_CID_AUDIO_BASS:
662 set_bass(client, ctrl->value);
663 break;
664 case V4L2_CID_AUDIO_TREBLE:
665 set_treble(client, ctrl->value);
666 break;
667 case V4L2_CID_AUDIO_BALANCE:
668 set_balance(client, ctrl->value);
669 break;
670 case V4L2_CID_AUDIO_MUTE:
671 set_mute(client, ctrl->value);
672 break;
673 default:
674 return -EINVAL;
675 }
676 return 0;
677}
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index bb4872b2ceb..86ca8c2359d 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -15,6 +15,9 @@
15 * 15 *
16 * CX23885 support by Steven Toth <stoth@linuxtv.org>. 16 * CX23885 support by Steven Toth <stoth@linuxtv.org>.
17 * 17 *
18 * CX2388[578] IRQ handling, IO Pin mux configuration and other small fixes are
19 * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net>
20 *
18 * This program is free software; you can redistribute it and/or 21 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License 22 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2 23 * as published by the Free Software Foundation; either version 2
@@ -48,6 +51,28 @@ MODULE_DESCRIPTION("Conexant CX25840 audio/video decoder driver");
48MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford"); 51MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford");
49MODULE_LICENSE("GPL"); 52MODULE_LICENSE("GPL");
50 53
54#define CX25840_VID_INT_STAT_REG 0x410
55#define CX25840_VID_INT_STAT_BITS 0x0000ffff
56#define CX25840_VID_INT_MASK_BITS 0xffff0000
57#define CX25840_VID_INT_MASK_SHFT 16
58#define CX25840_VID_INT_MASK_REG 0x412
59
60#define CX23885_AUD_MC_INT_MASK_REG 0x80c
61#define CX23885_AUD_MC_INT_STAT_BITS 0xffff0000
62#define CX23885_AUD_MC_INT_CTRL_BITS 0x0000ffff
63#define CX23885_AUD_MC_INT_STAT_SHFT 16
64
65#define CX25840_AUD_INT_CTRL_REG 0x812
66#define CX25840_AUD_INT_STAT_REG 0x813
67
68#define CX23885_PIN_CTRL_IRQ_REG 0x123
69#define CX23885_PIN_CTRL_IRQ_IR_STAT 0x40
70#define CX23885_PIN_CTRL_IRQ_AUD_STAT 0x20
71#define CX23885_PIN_CTRL_IRQ_VID_STAT 0x10
72
73#define CX25840_IR_STATS_REG 0x210
74#define CX25840_IR_IRQEN_REG 0x214
75
51static int cx25840_debug; 76static int cx25840_debug;
52 77
53module_param_named(debug,cx25840_debug, int, 0644); 78module_param_named(debug,cx25840_debug, int, 0644);
@@ -80,33 +105,53 @@ int cx25840_write4(struct i2c_client *client, u16 addr, u32 value)
80 105
81u8 cx25840_read(struct i2c_client * client, u16 addr) 106u8 cx25840_read(struct i2c_client * client, u16 addr)
82{ 107{
83 u8 buffer[2]; 108 struct i2c_msg msgs[2];
84 buffer[0] = addr >> 8; 109 u8 tx_buf[2], rx_buf[1];
85 buffer[1] = addr & 0xff; 110
86 111 /* Write register address */
87 if (i2c_master_send(client, buffer, 2) < 2) 112 tx_buf[0] = addr >> 8;
88 return 0; 113 tx_buf[1] = addr & 0xff;
89 114 msgs[0].addr = client->addr;
90 if (i2c_master_recv(client, buffer, 1) < 1) 115 msgs[0].flags = 0;
116 msgs[0].len = 2;
117 msgs[0].buf = (char *) tx_buf;
118
119 /* Read data from register */
120 msgs[1].addr = client->addr;
121 msgs[1].flags = I2C_M_RD;
122 msgs[1].len = 1;
123 msgs[1].buf = (char *) rx_buf;
124
125 if (i2c_transfer(client->adapter, msgs, 2) < 2)
91 return 0; 126 return 0;
92 127
93 return buffer[0]; 128 return rx_buf[0];
94} 129}
95 130
96u32 cx25840_read4(struct i2c_client * client, u16 addr) 131u32 cx25840_read4(struct i2c_client * client, u16 addr)
97{ 132{
98 u8 buffer[4]; 133 struct i2c_msg msgs[2];
99 buffer[0] = addr >> 8; 134 u8 tx_buf[2], rx_buf[4];
100 buffer[1] = addr & 0xff; 135
101 136 /* Write register address */
102 if (i2c_master_send(client, buffer, 2) < 2) 137 tx_buf[0] = addr >> 8;
103 return 0; 138 tx_buf[1] = addr & 0xff;
104 139 msgs[0].addr = client->addr;
105 if (i2c_master_recv(client, buffer, 4) < 4) 140 msgs[0].flags = 0;
141 msgs[0].len = 2;
142 msgs[0].buf = (char *) tx_buf;
143
144 /* Read data from registers */
145 msgs[1].addr = client->addr;
146 msgs[1].flags = I2C_M_RD;
147 msgs[1].len = 4;
148 msgs[1].buf = (char *) rx_buf;
149
150 if (i2c_transfer(client->adapter, msgs, 2) < 2)
106 return 0; 151 return 0;
107 152
108 return (buffer[3] << 24) | (buffer[2] << 16) | 153 return (rx_buf[3] << 24) | (rx_buf[2] << 16) | (rx_buf[1] << 8) |
109 (buffer[1] << 8) | buffer[0]; 154 rx_buf[0];
110} 155}
111 156
112int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask, 157int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask,
@@ -117,6 +162,14 @@ int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask,
117 or_value); 162 or_value);
118} 163}
119 164
165int cx25840_and_or4(struct i2c_client *client, u16 addr, u32 and_mask,
166 u32 or_value)
167{
168 return cx25840_write4(client, addr,
169 (cx25840_read4(client, addr) & and_mask) |
170 or_value);
171}
172
120/* ----------------------------------------------------------------------- */ 173/* ----------------------------------------------------------------------- */
121 174
122static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input, 175static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input,
@@ -124,6 +177,158 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
124 177
125/* ----------------------------------------------------------------------- */ 178/* ----------------------------------------------------------------------- */
126 179
180static int cx23885_s_io_pin_config(struct v4l2_subdev *sd, size_t n,
181 struct v4l2_subdev_io_pin_config *p)
182{
183 struct i2c_client *client = v4l2_get_subdevdata(sd);
184 int i;
185 u32 pin_ctrl;
186 u8 gpio_oe, gpio_data, strength;
187
188 pin_ctrl = cx25840_read4(client, 0x120);
189 gpio_oe = cx25840_read(client, 0x160);
190 gpio_data = cx25840_read(client, 0x164);
191
192 for (i = 0; i < n; i++) {
193 strength = p[i].strength;
194 if (strength > CX25840_PIN_DRIVE_FAST)
195 strength = CX25840_PIN_DRIVE_FAST;
196
197 switch (p[i].pin) {
198 case CX23885_PIN_IRQ_N_GPIO16:
199 if (p[i].function != CX23885_PAD_IRQ_N) {
200 /* GPIO16 */
201 pin_ctrl &= ~(0x1 << 25);
202 } else {
203 /* IRQ_N */
204 if (p[i].flags &
205 (V4L2_SUBDEV_IO_PIN_DISABLE |
206 V4L2_SUBDEV_IO_PIN_INPUT)) {
207 pin_ctrl &= ~(0x1 << 25);
208 } else {
209 pin_ctrl |= (0x1 << 25);
210 }
211 if (p[i].flags &
212 V4L2_SUBDEV_IO_PIN_ACTIVE_LOW) {
213 pin_ctrl &= ~(0x1 << 24);
214 } else {
215 pin_ctrl |= (0x1 << 24);
216 }
217 }
218 break;
219 case CX23885_PIN_IR_RX_GPIO19:
220 if (p[i].function != CX23885_PAD_GPIO19) {
221 /* IR_RX */
222 gpio_oe |= (0x1 << 0);
223 pin_ctrl &= ~(0x3 << 18);
224 pin_ctrl |= (strength << 18);
225 } else {
226 /* GPIO19 */
227 gpio_oe &= ~(0x1 << 0);
228 if (p[i].flags & V4L2_SUBDEV_IO_PIN_SET_VALUE) {
229 gpio_data &= ~(0x1 << 0);
230 gpio_data |= ((p[i].value & 0x1) << 0);
231 }
232 pin_ctrl &= ~(0x3 << 12);
233 pin_ctrl |= (strength << 12);
234 }
235 break;
236 case CX23885_PIN_IR_TX_GPIO20:
237 if (p[i].function != CX23885_PAD_GPIO20) {
238 /* IR_TX */
239 gpio_oe |= (0x1 << 1);
240 if (p[i].flags & V4L2_SUBDEV_IO_PIN_DISABLE)
241 pin_ctrl &= ~(0x1 << 10);
242 else
243 pin_ctrl |= (0x1 << 10);
244 pin_ctrl &= ~(0x3 << 18);
245 pin_ctrl |= (strength << 18);
246 } else {
247 /* GPIO20 */
248 gpio_oe &= ~(0x1 << 1);
249 if (p[i].flags & V4L2_SUBDEV_IO_PIN_SET_VALUE) {
250 gpio_data &= ~(0x1 << 1);
251 gpio_data |= ((p[i].value & 0x1) << 1);
252 }
253 pin_ctrl &= ~(0x3 << 12);
254 pin_ctrl |= (strength << 12);
255 }
256 break;
257 case CX23885_PIN_I2S_SDAT_GPIO21:
258 if (p[i].function != CX23885_PAD_GPIO21) {
259 /* I2S_SDAT */
260 /* TODO: Input or Output config */
261 gpio_oe |= (0x1 << 2);
262 pin_ctrl &= ~(0x3 << 22);
263 pin_ctrl |= (strength << 22);
264 } else {
265 /* GPIO21 */
266 gpio_oe &= ~(0x1 << 2);
267 if (p[i].flags & V4L2_SUBDEV_IO_PIN_SET_VALUE) {
268 gpio_data &= ~(0x1 << 2);
269 gpio_data |= ((p[i].value & 0x1) << 2);
270 }
271 pin_ctrl &= ~(0x3 << 12);
272 pin_ctrl |= (strength << 12);
273 }
274 break;
275 case CX23885_PIN_I2S_WCLK_GPIO22:
276 if (p[i].function != CX23885_PAD_GPIO22) {
277 /* I2S_WCLK */
278 /* TODO: Input or Output config */
279 gpio_oe |= (0x1 << 3);
280 pin_ctrl &= ~(0x3 << 22);
281 pin_ctrl |= (strength << 22);
282 } else {
283 /* GPIO22 */
284 gpio_oe &= ~(0x1 << 3);
285 if (p[i].flags & V4L2_SUBDEV_IO_PIN_SET_VALUE) {
286 gpio_data &= ~(0x1 << 3);
287 gpio_data |= ((p[i].value & 0x1) << 3);
288 }
289 pin_ctrl &= ~(0x3 << 12);
290 pin_ctrl |= (strength << 12);
291 }
292 break;
293 case CX23885_PIN_I2S_BCLK_GPIO23:
294 if (p[i].function != CX23885_PAD_GPIO23) {
295 /* I2S_BCLK */
296 /* TODO: Input or Output config */
297 gpio_oe |= (0x1 << 4);
298 pin_ctrl &= ~(0x3 << 22);
299 pin_ctrl |= (strength << 22);
300 } else {
301 /* GPIO23 */
302 gpio_oe &= ~(0x1 << 4);
303 if (p[i].flags & V4L2_SUBDEV_IO_PIN_SET_VALUE) {
304 gpio_data &= ~(0x1 << 4);
305 gpio_data |= ((p[i].value & 0x1) << 4);
306 }
307 pin_ctrl &= ~(0x3 << 12);
308 pin_ctrl |= (strength << 12);
309 }
310 break;
311 }
312 }
313
314 cx25840_write(client, 0x164, gpio_data);
315 cx25840_write(client, 0x160, gpio_oe);
316 cx25840_write4(client, 0x120, pin_ctrl);
317 return 0;
318}
319
320static int common_s_io_pin_config(struct v4l2_subdev *sd, size_t n,
321 struct v4l2_subdev_io_pin_config *pincfg)
322{
323 struct cx25840_state *state = to_state(sd);
324
325 if (is_cx2388x(state))
326 return cx23885_s_io_pin_config(sd, n, pincfg);
327 return 0;
328}
329
330/* ----------------------------------------------------------------------- */
331
127static void init_dll1(struct i2c_client *client) 332static void init_dll1(struct i2c_client *client)
128{ 333{
129 /* This is the Hauppauge sequence used to 334 /* This is the Hauppauge sequence used to
@@ -420,6 +625,13 @@ static void cx23885_initialize(struct i2c_client *client)
420 625
421 /* start microcontroller */ 626 /* start microcontroller */
422 cx25840_and_or(client, 0x803, ~0x10, 0x10); 627 cx25840_and_or(client, 0x803, ~0x10, 0x10);
628
629 /* Disable and clear video interrupts - we don't use them */
630 cx25840_write4(client, CX25840_VID_INT_STAT_REG, 0xffffffff);
631
632 /* Disable and clear audio interrupts - we don't use them */
633 cx25840_write(client, CX25840_AUD_INT_CTRL_REG, 0xff);
634 cx25840_write(client, CX25840_AUD_INT_STAT_REG, 0xff);
423} 635}
424 636
425/* ----------------------------------------------------------------------- */ 637/* ----------------------------------------------------------------------- */
@@ -909,102 +1121,29 @@ static int set_v4lstd(struct i2c_client *client)
909 1121
910/* ----------------------------------------------------------------------- */ 1122/* ----------------------------------------------------------------------- */
911 1123
912static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 1124static int cx25840_s_ctrl(struct v4l2_ctrl *ctrl)
913{ 1125{
914 struct cx25840_state *state = to_state(sd); 1126 struct v4l2_subdev *sd = to_sd(ctrl);
915 struct i2c_client *client = v4l2_get_subdevdata(sd); 1127 struct i2c_client *client = v4l2_get_subdevdata(sd);
916 1128
917 switch (ctrl->id) { 1129 switch (ctrl->id) {
918 case CX25840_CID_ENABLE_PVR150_WORKAROUND:
919 state->pvr150_workaround = ctrl->value;
920 set_input(client, state->vid_input, state->aud_input);
921 break;
922
923 case V4L2_CID_BRIGHTNESS: 1130 case V4L2_CID_BRIGHTNESS:
924 if (ctrl->value < 0 || ctrl->value > 255) { 1131 cx25840_write(client, 0x414, ctrl->val - 128);
925 v4l_err(client, "invalid brightness setting %d\n",
926 ctrl->value);
927 return -ERANGE;
928 }
929
930 cx25840_write(client, 0x414, ctrl->value - 128);
931 break; 1132 break;
932 1133
933 case V4L2_CID_CONTRAST: 1134 case V4L2_CID_CONTRAST:
934 if (ctrl->value < 0 || ctrl->value > 127) { 1135 cx25840_write(client, 0x415, ctrl->val << 1);
935 v4l_err(client, "invalid contrast setting %d\n",
936 ctrl->value);
937 return -ERANGE;
938 }
939
940 cx25840_write(client, 0x415, ctrl->value << 1);
941 break; 1136 break;
942 1137
943 case V4L2_CID_SATURATION: 1138 case V4L2_CID_SATURATION:
944 if (ctrl->value < 0 || ctrl->value > 127) { 1139 cx25840_write(client, 0x420, ctrl->val << 1);
945 v4l_err(client, "invalid saturation setting %d\n", 1140 cx25840_write(client, 0x421, ctrl->val << 1);
946 ctrl->value);
947 return -ERANGE;
948 }
949
950 cx25840_write(client, 0x420, ctrl->value << 1);
951 cx25840_write(client, 0x421, ctrl->value << 1);
952 break; 1141 break;
953 1142
954 case V4L2_CID_HUE: 1143 case V4L2_CID_HUE:
955 if (ctrl->value < -128 || ctrl->value > 127) { 1144 cx25840_write(client, 0x422, ctrl->val);
956 v4l_err(client, "invalid hue setting %d\n", ctrl->value);
957 return -ERANGE;
958 }
959
960 cx25840_write(client, 0x422, ctrl->value);
961 break; 1145 break;
962 1146
963 case V4L2_CID_AUDIO_VOLUME:
964 case V4L2_CID_AUDIO_BASS:
965 case V4L2_CID_AUDIO_TREBLE:
966 case V4L2_CID_AUDIO_BALANCE:
967 case V4L2_CID_AUDIO_MUTE:
968 if (is_cx2583x(state))
969 return -EINVAL;
970 return cx25840_audio_s_ctrl(sd, ctrl);
971
972 default:
973 return -EINVAL;
974 }
975
976 return 0;
977}
978
979static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
980{
981 struct cx25840_state *state = to_state(sd);
982 struct i2c_client *client = v4l2_get_subdevdata(sd);
983
984 switch (ctrl->id) {
985 case CX25840_CID_ENABLE_PVR150_WORKAROUND:
986 ctrl->value = state->pvr150_workaround;
987 break;
988 case V4L2_CID_BRIGHTNESS:
989 ctrl->value = (s8)cx25840_read(client, 0x414) + 128;
990 break;
991 case V4L2_CID_CONTRAST:
992 ctrl->value = cx25840_read(client, 0x415) >> 1;
993 break;
994 case V4L2_CID_SATURATION:
995 ctrl->value = cx25840_read(client, 0x420) >> 1;
996 break;
997 case V4L2_CID_HUE:
998 ctrl->value = (s8)cx25840_read(client, 0x422);
999 break;
1000 case V4L2_CID_AUDIO_VOLUME:
1001 case V4L2_CID_AUDIO_BASS:
1002 case V4L2_CID_AUDIO_TREBLE:
1003 case V4L2_CID_AUDIO_BALANCE:
1004 case V4L2_CID_AUDIO_MUTE:
1005 if (is_cx2583x(state))
1006 return -EINVAL;
1007 return cx25840_audio_g_ctrl(sd, ctrl);
1008 default: 1147 default:
1009 return -EINVAL; 1148 return -EINVAL;
1010 } 1149 }
@@ -1163,8 +1302,6 @@ static void log_audio_status(struct i2c_client *client)
1163 default: p = "not defined"; 1302 default: p = "not defined";
1164 } 1303 }
1165 v4l_info(client, "Detected audio standard: %s\n", p); 1304 v4l_info(client, "Detected audio standard: %s\n", p);
1166 v4l_info(client, "Audio muted: %s\n",
1167 (state->unmute_volume >= 0) ? "yes" : "no");
1168 v4l_info(client, "Audio microcontroller: %s\n", 1305 v4l_info(client, "Audio microcontroller: %s\n",
1169 (download_ctl & 0x10) ? 1306 (download_ctl & 0x10) ?
1170 ((mute_ctl & 0x2) ? "detecting" : "running") : "stopped"); 1307 ((mute_ctl & 0x2) ? "detecting" : "running") : "stopped");
@@ -1381,40 +1518,6 @@ static int cx25840_s_stream(struct v4l2_subdev *sd, int enable)
1381 return 0; 1518 return 0;
1382} 1519}
1383 1520
1384static int cx25840_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
1385{
1386 struct cx25840_state *state = to_state(sd);
1387
1388 switch (qc->id) {
1389 case V4L2_CID_BRIGHTNESS:
1390 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
1391 case V4L2_CID_CONTRAST:
1392 case V4L2_CID_SATURATION:
1393 return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
1394 case V4L2_CID_HUE:
1395 return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
1396 default:
1397 break;
1398 }
1399 if (is_cx2583x(state))
1400 return -EINVAL;
1401
1402 switch (qc->id) {
1403 case V4L2_CID_AUDIO_VOLUME:
1404 return v4l2_ctrl_query_fill(qc, 0, 65535,
1405 65535 / 100, state->default_volume);
1406 case V4L2_CID_AUDIO_MUTE:
1407 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
1408 case V4L2_CID_AUDIO_BALANCE:
1409 case V4L2_CID_AUDIO_BASS:
1410 case V4L2_CID_AUDIO_TREBLE:
1411 return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
1412 default:
1413 return -EINVAL;
1414 }
1415 return -EINVAL;
1416}
1417
1418static int cx25840_s_std(struct v4l2_subdev *sd, v4l2_std_id std) 1521static int cx25840_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1419{ 1522{
1420 struct cx25840_state *state = to_state(sd); 1523 struct cx25840_state *state = to_state(sd);
@@ -1576,24 +1679,134 @@ static int cx25840_log_status(struct v4l2_subdev *sd)
1576 log_video_status(client); 1679 log_video_status(client);
1577 if (!is_cx2583x(state)) 1680 if (!is_cx2583x(state))
1578 log_audio_status(client); 1681 log_audio_status(client);
1682 cx25840_ir_log_status(sd);
1683 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
1684 return 0;
1685}
1686
1687static int cx25840_s_config(struct v4l2_subdev *sd, int irq, void *platform_data)
1688{
1689 struct cx25840_state *state = to_state(sd);
1690 struct i2c_client *client = v4l2_get_subdevdata(sd);
1691
1692 if (platform_data) {
1693 struct cx25840_platform_data *pdata = platform_data;
1694
1695 state->pvr150_workaround = pdata->pvr150_workaround;
1696 set_input(client, state->vid_input, state->aud_input);
1697 }
1579 return 0; 1698 return 0;
1580} 1699}
1581 1700
1701static int cx23885_irq_handler(struct v4l2_subdev *sd, u32 status,
1702 bool *handled)
1703{
1704 struct cx25840_state *state = to_state(sd);
1705 struct i2c_client *c = v4l2_get_subdevdata(sd);
1706 u8 irq_stat, aud_stat, aud_en, ir_stat, ir_en;
1707 u32 vid_stat, aud_mc_stat;
1708 bool block_handled;
1709 int ret = 0;
1710
1711 irq_stat = cx25840_read(c, CX23885_PIN_CTRL_IRQ_REG);
1712 v4l_dbg(2, cx25840_debug, c, "AV Core IRQ status (entry): %s %s %s\n",
1713 irq_stat & CX23885_PIN_CTRL_IRQ_IR_STAT ? "ir" : " ",
1714 irq_stat & CX23885_PIN_CTRL_IRQ_AUD_STAT ? "aud" : " ",
1715 irq_stat & CX23885_PIN_CTRL_IRQ_VID_STAT ? "vid" : " ");
1716
1717 if ((is_cx23885(state) || is_cx23887(state))) {
1718 ir_stat = cx25840_read(c, CX25840_IR_STATS_REG);
1719 ir_en = cx25840_read(c, CX25840_IR_IRQEN_REG);
1720 v4l_dbg(2, cx25840_debug, c,
1721 "AV Core ir IRQ status: %#04x disables: %#04x\n",
1722 ir_stat, ir_en);
1723 if (irq_stat & CX23885_PIN_CTRL_IRQ_IR_STAT) {
1724 block_handled = false;
1725 ret = cx25840_ir_irq_handler(sd,
1726 status, &block_handled);
1727 if (block_handled)
1728 *handled = true;
1729 }
1730 }
1731
1732 aud_stat = cx25840_read(c, CX25840_AUD_INT_STAT_REG);
1733 aud_en = cx25840_read(c, CX25840_AUD_INT_CTRL_REG);
1734 v4l_dbg(2, cx25840_debug, c,
1735 "AV Core audio IRQ status: %#04x disables: %#04x\n",
1736 aud_stat, aud_en);
1737 aud_mc_stat = cx25840_read4(c, CX23885_AUD_MC_INT_MASK_REG);
1738 v4l_dbg(2, cx25840_debug, c,
1739 "AV Core audio MC IRQ status: %#06x enables: %#06x\n",
1740 aud_mc_stat >> CX23885_AUD_MC_INT_STAT_SHFT,
1741 aud_mc_stat & CX23885_AUD_MC_INT_CTRL_BITS);
1742 if (irq_stat & CX23885_PIN_CTRL_IRQ_AUD_STAT) {
1743 if (aud_stat) {
1744 cx25840_write(c, CX25840_AUD_INT_STAT_REG, aud_stat);
1745 *handled = true;
1746 }
1747 }
1748
1749 vid_stat = cx25840_read4(c, CX25840_VID_INT_STAT_REG);
1750 v4l_dbg(2, cx25840_debug, c,
1751 "AV Core video IRQ status: %#06x disables: %#06x\n",
1752 vid_stat & CX25840_VID_INT_STAT_BITS,
1753 vid_stat >> CX25840_VID_INT_MASK_SHFT);
1754 if (irq_stat & CX23885_PIN_CTRL_IRQ_VID_STAT) {
1755 if (vid_stat & CX25840_VID_INT_STAT_BITS) {
1756 cx25840_write4(c, CX25840_VID_INT_STAT_REG, vid_stat);
1757 *handled = true;
1758 }
1759 }
1760
1761 irq_stat = cx25840_read(c, CX23885_PIN_CTRL_IRQ_REG);
1762 v4l_dbg(2, cx25840_debug, c, "AV Core IRQ status (exit): %s %s %s\n",
1763 irq_stat & CX23885_PIN_CTRL_IRQ_IR_STAT ? "ir" : " ",
1764 irq_stat & CX23885_PIN_CTRL_IRQ_AUD_STAT ? "aud" : " ",
1765 irq_stat & CX23885_PIN_CTRL_IRQ_VID_STAT ? "vid" : " ");
1766
1767 return ret;
1768}
1769
1770static int cx25840_irq_handler(struct v4l2_subdev *sd, u32 status,
1771 bool *handled)
1772{
1773 struct cx25840_state *state = to_state(sd);
1774
1775 *handled = false;
1776
1777 /* Only support the CX2388[578] AV Core for now */
1778 if (is_cx2388x(state))
1779 return cx23885_irq_handler(sd, status, handled);
1780
1781 return -ENODEV;
1782}
1783
1582/* ----------------------------------------------------------------------- */ 1784/* ----------------------------------------------------------------------- */
1583 1785
1786static const struct v4l2_ctrl_ops cx25840_ctrl_ops = {
1787 .s_ctrl = cx25840_s_ctrl,
1788};
1789
1584static const struct v4l2_subdev_core_ops cx25840_core_ops = { 1790static const struct v4l2_subdev_core_ops cx25840_core_ops = {
1585 .log_status = cx25840_log_status, 1791 .log_status = cx25840_log_status,
1792 .s_config = cx25840_s_config,
1586 .g_chip_ident = cx25840_g_chip_ident, 1793 .g_chip_ident = cx25840_g_chip_ident,
1587 .g_ctrl = cx25840_g_ctrl, 1794 .g_ctrl = v4l2_subdev_g_ctrl,
1588 .s_ctrl = cx25840_s_ctrl, 1795 .s_ctrl = v4l2_subdev_s_ctrl,
1589 .queryctrl = cx25840_queryctrl, 1796 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
1797 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
1798 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
1799 .queryctrl = v4l2_subdev_queryctrl,
1800 .querymenu = v4l2_subdev_querymenu,
1590 .s_std = cx25840_s_std, 1801 .s_std = cx25840_s_std,
1591 .reset = cx25840_reset, 1802 .reset = cx25840_reset,
1592 .load_fw = cx25840_load_fw, 1803 .load_fw = cx25840_load_fw,
1804 .s_io_pin_config = common_s_io_pin_config,
1593#ifdef CONFIG_VIDEO_ADV_DEBUG 1805#ifdef CONFIG_VIDEO_ADV_DEBUG
1594 .g_register = cx25840_g_register, 1806 .g_register = cx25840_g_register,
1595 .s_register = cx25840_s_register, 1807 .s_register = cx25840_s_register,
1596#endif 1808#endif
1809 .interrupt_service_routine = cx25840_irq_handler,
1597}; 1810};
1598 1811
1599static const struct v4l2_subdev_tuner_ops cx25840_tuner_ops = { 1812static const struct v4l2_subdev_tuner_ops cx25840_tuner_ops = {
@@ -1628,6 +1841,7 @@ static const struct v4l2_subdev_ops cx25840_ops = {
1628 .audio = &cx25840_audio_ops, 1841 .audio = &cx25840_audio_ops,
1629 .video = &cx25840_video_ops, 1842 .video = &cx25840_video_ops,
1630 .vbi = &cx25840_vbi_ops, 1843 .vbi = &cx25840_vbi_ops,
1844 .ir = &cx25840_ir_ops,
1631}; 1845};
1632 1846
1633/* ----------------------------------------------------------------------- */ 1847/* ----------------------------------------------------------------------- */
@@ -1675,6 +1889,7 @@ static int cx25840_probe(struct i2c_client *client,
1675{ 1889{
1676 struct cx25840_state *state; 1890 struct cx25840_state *state;
1677 struct v4l2_subdev *sd; 1891 struct v4l2_subdev *sd;
1892 int default_volume;
1678 u32 id = V4L2_IDENT_NONE; 1893 u32 id = V4L2_IDENT_NONE;
1679 u16 device_id; 1894 u16 device_id;
1680 1895
@@ -1718,6 +1933,7 @@ static int cx25840_probe(struct i2c_client *client,
1718 1933
1719 sd = &state->sd; 1934 sd = &state->sd;
1720 v4l2_i2c_subdev_init(sd, client, &cx25840_ops); 1935 v4l2_i2c_subdev_init(sd, client, &cx25840_ops);
1936
1721 switch (id) { 1937 switch (id) {
1722 case V4L2_IDENT_CX23885_AV: 1938 case V4L2_IDENT_CX23885_AV:
1723 v4l_info(client, "cx23885 A/V decoder found @ 0x%x (%s)\n", 1939 v4l_info(client, "cx23885 A/V decoder found @ 0x%x (%s)\n",
@@ -1762,22 +1978,62 @@ static int cx25840_probe(struct i2c_client *client,
1762 state->audclk_freq = 48000; 1978 state->audclk_freq = 48000;
1763 state->pvr150_workaround = 0; 1979 state->pvr150_workaround = 0;
1764 state->audmode = V4L2_TUNER_MODE_LANG1; 1980 state->audmode = V4L2_TUNER_MODE_LANG1;
1765 state->unmute_volume = -1;
1766 state->default_volume = 228 - cx25840_read(client, 0x8d4);
1767 state->default_volume = ((state->default_volume / 2) + 23) << 9;
1768 state->vbi_line_offset = 8; 1981 state->vbi_line_offset = 8;
1769 state->id = id; 1982 state->id = id;
1770 state->rev = device_id; 1983 state->rev = device_id;
1984 v4l2_ctrl_handler_init(&state->hdl, 9);
1985 v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,
1986 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1987 v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,
1988 V4L2_CID_CONTRAST, 0, 127, 1, 64);
1989 v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,
1990 V4L2_CID_SATURATION, 0, 127, 1, 64);
1991 v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,
1992 V4L2_CID_HUE, -128, 127, 1, 0);
1993 if (!is_cx2583x(state)) {
1994 default_volume = 228 - cx25840_read(client, 0x8d4);
1995 default_volume = ((default_volume / 2) + 23) << 9;
1996
1997 state->volume = v4l2_ctrl_new_std(&state->hdl,
1998 &cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME,
1999 0, 65335, 65535 / 100, default_volume);
2000 state->mute = v4l2_ctrl_new_std(&state->hdl,
2001 &cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_MUTE,
2002 0, 1, 1, 0);
2003 v4l2_ctrl_new_std(&state->hdl, &cx25840_audio_ctrl_ops,
2004 V4L2_CID_AUDIO_BALANCE,
2005 0, 65535, 65535 / 100, 32768);
2006 v4l2_ctrl_new_std(&state->hdl, &cx25840_audio_ctrl_ops,
2007 V4L2_CID_AUDIO_BASS,
2008 0, 65535, 65535 / 100, 32768);
2009 v4l2_ctrl_new_std(&state->hdl, &cx25840_audio_ctrl_ops,
2010 V4L2_CID_AUDIO_TREBLE,
2011 0, 65535, 65535 / 100, 32768);
2012 }
2013 sd->ctrl_handler = &state->hdl;
2014 if (state->hdl.error) {
2015 int err = state->hdl.error;
2016
2017 v4l2_ctrl_handler_free(&state->hdl);
2018 kfree(state);
2019 return err;
2020 }
2021 v4l2_ctrl_cluster(2, &state->volume);
2022 v4l2_ctrl_handler_setup(&state->hdl);
1771 2023
2024 cx25840_ir_probe(sd);
1772 return 0; 2025 return 0;
1773} 2026}
1774 2027
1775static int cx25840_remove(struct i2c_client *client) 2028static int cx25840_remove(struct i2c_client *client)
1776{ 2029{
1777 struct v4l2_subdev *sd = i2c_get_clientdata(client); 2030 struct v4l2_subdev *sd = i2c_get_clientdata(client);
2031 struct cx25840_state *state = to_state(sd);
1778 2032
2033 cx25840_ir_remove(sd);
1779 v4l2_device_unregister_subdev(sd); 2034 v4l2_device_unregister_subdev(sd);
1780 kfree(to_state(sd)); 2035 v4l2_ctrl_handler_free(&state->hdl);
2036 kfree(state);
1781 return 0; 2037 return 0;
1782} 2038}
1783 2039
diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h
index 04393b97156..bd4ada28b49 100644
--- a/drivers/media/video/cx25840/cx25840-core.h
+++ b/drivers/media/video/cx25840/cx25840-core.h
@@ -24,19 +24,20 @@
24#include <linux/videodev2.h> 24#include <linux/videodev2.h>
25#include <media/v4l2-device.h> 25#include <media/v4l2-device.h>
26#include <media/v4l2-chip-ident.h> 26#include <media/v4l2-chip-ident.h>
27#include <media/v4l2-ctrls.h>
27#include <linux/i2c.h> 28#include <linux/i2c.h>
28 29
29/* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is 30struct cx25840_ir_state;
30 present in Hauppauge PVR-150 (and possibly PVR-500) cards that have
31 certain NTSC tuners (tveeprom tuner model numbers 85, 99 and 112). The
32 audio autodetect fails on some channels for these models and the workaround
33 is to select the audio standard explicitly. Many thanks to Hauppauge for
34 providing this information. */
35#define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0)
36 31
37struct cx25840_state { 32struct cx25840_state {
38 struct i2c_client *c; 33 struct i2c_client *c;
39 struct v4l2_subdev sd; 34 struct v4l2_subdev sd;
35 struct v4l2_ctrl_handler hdl;
36 struct {
37 /* volume cluster */
38 struct v4l2_ctrl *volume;
39 struct v4l2_ctrl *mute;
40 };
40 int pvr150_workaround; 41 int pvr150_workaround;
41 int radio; 42 int radio;
42 v4l2_std_id std; 43 v4l2_std_id std;
@@ -44,14 +45,13 @@ struct cx25840_state {
44 enum cx25840_audio_input aud_input; 45 enum cx25840_audio_input aud_input;
45 u32 audclk_freq; 46 u32 audclk_freq;
46 int audmode; 47 int audmode;
47 int unmute_volume; /* -1 if not muted */
48 int default_volume;
49 int vbi_line_offset; 48 int vbi_line_offset;
50 u32 id; 49 u32 id;
51 u32 rev; 50 u32 rev;
52 int is_initialized; 51 int is_initialized;
53 wait_queue_head_t fw_wait; /* wake up when the fw load is finished */ 52 wait_queue_head_t fw_wait; /* wake up when the fw load is finished */
54 struct work_struct fw_work; /* work entry for fw load */ 53 struct work_struct fw_work; /* work entry for fw load */
54 struct cx25840_ir_state *ir_state;
55}; 55};
56 56
57static inline struct cx25840_state *to_state(struct v4l2_subdev *sd) 57static inline struct cx25840_state *to_state(struct v4l2_subdev *sd)
@@ -59,6 +59,11 @@ static inline struct cx25840_state *to_state(struct v4l2_subdev *sd)
59 return container_of(sd, struct cx25840_state, sd); 59 return container_of(sd, struct cx25840_state, sd);
60} 60}
61 61
62static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
63{
64 return &container_of(ctrl->handler, struct cx25840_state, hdl)->sd;
65}
66
62static inline bool is_cx2583x(struct cx25840_state *state) 67static inline bool is_cx2583x(struct cx25840_state *state)
63{ 68{
64 return state->id == V4L2_IDENT_CX25836 || 69 return state->id == V4L2_IDENT_CX25836 ||
@@ -77,6 +82,21 @@ static inline bool is_cx2388x(struct cx25840_state *state)
77 state->id == V4L2_IDENT_CX23888_AV; 82 state->id == V4L2_IDENT_CX23888_AV;
78} 83}
79 84
85static inline bool is_cx23885(struct cx25840_state *state)
86{
87 return state->id == V4L2_IDENT_CX23885_AV;
88}
89
90static inline bool is_cx23887(struct cx25840_state *state)
91{
92 return state->id == V4L2_IDENT_CX23887_AV;
93}
94
95static inline bool is_cx23888(struct cx25840_state *state)
96{
97 return state->id == V4L2_IDENT_CX23888_AV;
98}
99
80/* ----------------------------------------------------------------------- */ 100/* ----------------------------------------------------------------------- */
81/* cx25850-core.c */ 101/* cx25850-core.c */
82int cx25840_write(struct i2c_client *client, u16 addr, u8 value); 102int cx25840_write(struct i2c_client *client, u16 addr, u8 value);
@@ -84,6 +104,8 @@ int cx25840_write4(struct i2c_client *client, u16 addr, u32 value);
84u8 cx25840_read(struct i2c_client *client, u16 addr); 104u8 cx25840_read(struct i2c_client *client, u16 addr);
85u32 cx25840_read4(struct i2c_client *client, u16 addr); 105u32 cx25840_read4(struct i2c_client *client, u16 addr);
86int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value); 106int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value);
107int cx25840_and_or4(struct i2c_client *client, u16 addr, u32 and_mask,
108 u32 or_value);
87void cx25840_std_setup(struct i2c_client *client); 109void cx25840_std_setup(struct i2c_client *client);
88 110
89/* ----------------------------------------------------------------------- */ 111/* ----------------------------------------------------------------------- */
@@ -94,8 +116,8 @@ int cx25840_loadfw(struct i2c_client *client);
94/* cx25850-audio.c */ 116/* cx25850-audio.c */
95void cx25840_audio_set_path(struct i2c_client *client); 117void cx25840_audio_set_path(struct i2c_client *client);
96int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq); 118int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq);
97int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl); 119
98int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl); 120extern const struct v4l2_ctrl_ops cx25840_audio_ctrl_ops;
99 121
100/* ----------------------------------------------------------------------- */ 122/* ----------------------------------------------------------------------- */
101/* cx25850-vbi.c */ 123/* cx25850-vbi.c */
@@ -104,4 +126,12 @@ int cx25840_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *
104int cx25840_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt); 126int cx25840_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
105int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi); 127int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi);
106 128
129/* ----------------------------------------------------------------------- */
130/* cx25850-ir.c */
131extern const struct v4l2_subdev_ir_ops cx25840_ir_ops;
132int cx25840_ir_log_status(struct v4l2_subdev *sd);
133int cx25840_ir_irq_handler(struct v4l2_subdev *sd, u32 status, bool *handled);
134int cx25840_ir_probe(struct v4l2_subdev *sd);
135int cx25840_ir_remove(struct v4l2_subdev *sd);
136
107#endif 137#endif
diff --git a/drivers/media/video/cx25840/cx25840-ir.c b/drivers/media/video/cx25840/cx25840-ir.c
new file mode 100644
index 00000000000..c2b4c14dc9a
--- /dev/null
+++ b/drivers/media/video/cx25840/cx25840-ir.c
@@ -0,0 +1,1279 @@
1/*
2 * Driver for the Conexant CX2584x Audio/Video decoder chip and related cores
3 *
4 * Integrated Consumer Infrared Controller
5 *
6 * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.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/slab.h>
25#include <linux/kfifo.h>
26#include <media/cx25840.h>
27#include <media/ir-core.h>
28
29#include "cx25840-core.h"
30
31static unsigned int ir_debug;
32module_param(ir_debug, int, 0644);
33MODULE_PARM_DESC(ir_debug, "enable integrated IR debug messages");
34
35#define CX25840_IR_REG_BASE 0x200
36
37#define CX25840_IR_CNTRL_REG 0x200
38#define CNTRL_WIN_3_3 0x00000000
39#define CNTRL_WIN_4_3 0x00000001
40#define CNTRL_WIN_3_4 0x00000002
41#define CNTRL_WIN_4_4 0x00000003
42#define CNTRL_WIN 0x00000003
43#define CNTRL_EDG_NONE 0x00000000
44#define CNTRL_EDG_FALL 0x00000004
45#define CNTRL_EDG_RISE 0x00000008
46#define CNTRL_EDG_BOTH 0x0000000C
47#define CNTRL_EDG 0x0000000C
48#define CNTRL_DMD 0x00000010
49#define CNTRL_MOD 0x00000020
50#define CNTRL_RFE 0x00000040
51#define CNTRL_TFE 0x00000080
52#define CNTRL_RXE 0x00000100
53#define CNTRL_TXE 0x00000200
54#define CNTRL_RIC 0x00000400
55#define CNTRL_TIC 0x00000800
56#define CNTRL_CPL 0x00001000
57#define CNTRL_LBM 0x00002000
58#define CNTRL_R 0x00004000
59
60#define CX25840_IR_TXCLK_REG 0x204
61#define TXCLK_TCD 0x0000FFFF
62
63#define CX25840_IR_RXCLK_REG 0x208
64#define RXCLK_RCD 0x0000FFFF
65
66#define CX25840_IR_CDUTY_REG 0x20C
67#define CDUTY_CDC 0x0000000F
68
69#define CX25840_IR_STATS_REG 0x210
70#define STATS_RTO 0x00000001
71#define STATS_ROR 0x00000002
72#define STATS_RBY 0x00000004
73#define STATS_TBY 0x00000008
74#define STATS_RSR 0x00000010
75#define STATS_TSR 0x00000020
76
77#define CX25840_IR_IRQEN_REG 0x214
78#define IRQEN_RTE 0x00000001
79#define IRQEN_ROE 0x00000002
80#define IRQEN_RSE 0x00000010
81#define IRQEN_TSE 0x00000020
82#define IRQEN_MSK 0x00000033
83
84#define CX25840_IR_FILTR_REG 0x218
85#define FILTR_LPF 0x0000FFFF
86
87#define CX25840_IR_FIFO_REG 0x23C
88#define FIFO_RXTX 0x0000FFFF
89#define FIFO_RXTX_LVL 0x00010000
90#define FIFO_RXTX_RTO 0x0001FFFF
91#define FIFO_RX_NDV 0x00020000
92#define FIFO_RX_DEPTH 8
93#define FIFO_TX_DEPTH 8
94
95#define CX25840_VIDCLK_FREQ 108000000 /* 108 MHz, BT.656 */
96#define CX25840_IR_REFCLK_FREQ (CX25840_VIDCLK_FREQ / 2)
97
98/*
99 * We use this union internally for convenience, but callers to tx_write
100 * and rx_read will be expecting records of type struct ir_raw_event.
101 * Always ensure the size of this union is dictated by struct ir_raw_event.
102 */
103union cx25840_ir_fifo_rec {
104 u32 hw_fifo_data;
105 struct ir_raw_event ir_core_data;
106};
107
108#define CX25840_IR_RX_KFIFO_SIZE (256 * sizeof(union cx25840_ir_fifo_rec))
109#define CX25840_IR_TX_KFIFO_SIZE (256 * sizeof(union cx25840_ir_fifo_rec))
110
111struct cx25840_ir_state {
112 struct i2c_client *c;
113
114 struct v4l2_subdev_ir_parameters rx_params;
115 struct mutex rx_params_lock; /* protects Rx parameter settings cache */
116 atomic_t rxclk_divider;
117 atomic_t rx_invert;
118
119 struct kfifo rx_kfifo;
120 spinlock_t rx_kfifo_lock; /* protect Rx data kfifo */
121
122 struct v4l2_subdev_ir_parameters tx_params;
123 struct mutex tx_params_lock; /* protects Tx parameter settings cache */
124 atomic_t txclk_divider;
125};
126
127static inline struct cx25840_ir_state *to_ir_state(struct v4l2_subdev *sd)
128{
129 struct cx25840_state *state = to_state(sd);
130 return state ? state->ir_state : NULL;
131}
132
133
134/*
135 * Rx and Tx Clock Divider register computations
136 *
137 * Note the largest clock divider value of 0xffff corresponds to:
138 * (0xffff + 1) * 1000 / 108/2 MHz = 1,213,629.629... ns
139 * which fits in 21 bits, so we'll use unsigned int for time arguments.
140 */
141static inline u16 count_to_clock_divider(unsigned int d)
142{
143 if (d > RXCLK_RCD + 1)
144 d = RXCLK_RCD;
145 else if (d < 2)
146 d = 1;
147 else
148 d--;
149 return (u16) d;
150}
151
152static inline u16 ns_to_clock_divider(unsigned int ns)
153{
154 return count_to_clock_divider(
155 DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ / 1000000 * ns, 1000));
156}
157
158static inline unsigned int clock_divider_to_ns(unsigned int divider)
159{
160 /* Period of the Rx or Tx clock in ns */
161 return DIV_ROUND_CLOSEST((divider + 1) * 1000,
162 CX25840_IR_REFCLK_FREQ / 1000000);
163}
164
165static inline u16 carrier_freq_to_clock_divider(unsigned int freq)
166{
167 return count_to_clock_divider(
168 DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ, freq * 16));
169}
170
171static inline unsigned int clock_divider_to_carrier_freq(unsigned int divider)
172{
173 return DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ, (divider + 1) * 16);
174}
175
176static inline u16 freq_to_clock_divider(unsigned int freq,
177 unsigned int rollovers)
178{
179 return count_to_clock_divider(
180 DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ, freq * rollovers));
181}
182
183static inline unsigned int clock_divider_to_freq(unsigned int divider,
184 unsigned int rollovers)
185{
186 return DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ,
187 (divider + 1) * rollovers);
188}
189
190/*
191 * Low Pass Filter register calculations
192 *
193 * Note the largest count value of 0xffff corresponds to:
194 * 0xffff * 1000 / 108/2 MHz = 1,213,611.11... ns
195 * which fits in 21 bits, so we'll use unsigned int for time arguments.
196 */
197static inline u16 count_to_lpf_count(unsigned int d)
198{
199 if (d > FILTR_LPF)
200 d = FILTR_LPF;
201 else if (d < 4)
202 d = 0;
203 return (u16) d;
204}
205
206static inline u16 ns_to_lpf_count(unsigned int ns)
207{
208 return count_to_lpf_count(
209 DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ / 1000000 * ns, 1000));
210}
211
212static inline unsigned int lpf_count_to_ns(unsigned int count)
213{
214 /* Duration of the Low Pass Filter rejection window in ns */
215 return DIV_ROUND_CLOSEST(count * 1000,
216 CX25840_IR_REFCLK_FREQ / 1000000);
217}
218
219static inline unsigned int lpf_count_to_us(unsigned int count)
220{
221 /* Duration of the Low Pass Filter rejection window in us */
222 return DIV_ROUND_CLOSEST(count, CX25840_IR_REFCLK_FREQ / 1000000);
223}
224
225/*
226 * FIFO register pulse width count compuations
227 */
228static u32 clock_divider_to_resolution(u16 divider)
229{
230 /*
231 * Resolution is the duration of 1 tick of the readable portion of
232 * of the pulse width counter as read from the FIFO. The two lsb's are
233 * not readable, hence the << 2. This function returns ns.
234 */
235 return DIV_ROUND_CLOSEST((1 << 2) * ((u32) divider + 1) * 1000,
236 CX25840_IR_REFCLK_FREQ / 1000000);
237}
238
239static u64 pulse_width_count_to_ns(u16 count, u16 divider)
240{
241 u64 n;
242 u32 rem;
243
244 /*
245 * The 2 lsb's of the pulse width timer count are not readable, hence
246 * the (count << 2) | 0x3
247 */
248 n = (((u64) count << 2) | 0x3) * (divider + 1) * 1000; /* millicycles */
249 rem = do_div(n, CX25840_IR_REFCLK_FREQ / 1000000); /* / MHz => ns */
250 if (rem >= CX25840_IR_REFCLK_FREQ / 1000000 / 2)
251 n++;
252 return n;
253}
254
255#if 0
256/* Keep as we will need this for Transmit functionality */
257static u16 ns_to_pulse_width_count(u32 ns, u16 divider)
258{
259 u64 n;
260 u32 d;
261 u32 rem;
262
263 /*
264 * The 2 lsb's of the pulse width timer count are not accessable, hence
265 * the (1 << 2)
266 */
267 n = ((u64) ns) * CX25840_IR_REFCLK_FREQ / 1000000; /* millicycles */
268 d = (1 << 2) * ((u32) divider + 1) * 1000; /* millicycles/count */
269 rem = do_div(n, d);
270 if (rem >= d / 2)
271 n++;
272
273 if (n > FIFO_RXTX)
274 n = FIFO_RXTX;
275 else if (n == 0)
276 n = 1;
277 return (u16) n;
278}
279
280#endif
281static unsigned int pulse_width_count_to_us(u16 count, u16 divider)
282{
283 u64 n;
284 u32 rem;
285
286 /*
287 * The 2 lsb's of the pulse width timer count are not readable, hence
288 * the (count << 2) | 0x3
289 */
290 n = (((u64) count << 2) | 0x3) * (divider + 1); /* cycles */
291 rem = do_div(n, CX25840_IR_REFCLK_FREQ / 1000000); /* / MHz => us */
292 if (rem >= CX25840_IR_REFCLK_FREQ / 1000000 / 2)
293 n++;
294 return (unsigned int) n;
295}
296
297/*
298 * Pulse Clocks computations: Combined Pulse Width Count & Rx Clock Counts
299 *
300 * The total pulse clock count is an 18 bit pulse width timer count as the most
301 * significant part and (up to) 16 bit clock divider count as a modulus.
302 * When the Rx clock divider ticks down to 0, it increments the 18 bit pulse
303 * width timer count's least significant bit.
304 */
305static u64 ns_to_pulse_clocks(u32 ns)
306{
307 u64 clocks;
308 u32 rem;
309 clocks = CX25840_IR_REFCLK_FREQ / 1000000 * (u64) ns; /* millicycles */
310 rem = do_div(clocks, 1000); /* /1000 = cycles */
311 if (rem >= 1000 / 2)
312 clocks++;
313 return clocks;
314}
315
316static u16 pulse_clocks_to_clock_divider(u64 count)
317{
318 u32 rem;
319
320 rem = do_div(count, (FIFO_RXTX << 2) | 0x3);
321
322 /* net result needs to be rounded down and decremented by 1 */
323 if (count > RXCLK_RCD + 1)
324 count = RXCLK_RCD;
325 else if (count < 2)
326 count = 1;
327 else
328 count--;
329 return (u16) count;
330}
331
332/*
333 * IR Control Register helpers
334 */
335enum tx_fifo_watermark {
336 TX_FIFO_HALF_EMPTY = 0,
337 TX_FIFO_EMPTY = CNTRL_TIC,
338};
339
340enum rx_fifo_watermark {
341 RX_FIFO_HALF_FULL = 0,
342 RX_FIFO_NOT_EMPTY = CNTRL_RIC,
343};
344
345static inline void control_tx_irq_watermark(struct i2c_client *c,
346 enum tx_fifo_watermark level)
347{
348 cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~CNTRL_TIC, level);
349}
350
351static inline void control_rx_irq_watermark(struct i2c_client *c,
352 enum rx_fifo_watermark level)
353{
354 cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~CNTRL_RIC, level);
355}
356
357static inline void control_tx_enable(struct i2c_client *c, bool enable)
358{
359 cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~(CNTRL_TXE | CNTRL_TFE),
360 enable ? (CNTRL_TXE | CNTRL_TFE) : 0);
361}
362
363static inline void control_rx_enable(struct i2c_client *c, bool enable)
364{
365 cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~(CNTRL_RXE | CNTRL_RFE),
366 enable ? (CNTRL_RXE | CNTRL_RFE) : 0);
367}
368
369static inline void control_tx_modulation_enable(struct i2c_client *c,
370 bool enable)
371{
372 cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~CNTRL_MOD,
373 enable ? CNTRL_MOD : 0);
374}
375
376static inline void control_rx_demodulation_enable(struct i2c_client *c,
377 bool enable)
378{
379 cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~CNTRL_DMD,
380 enable ? CNTRL_DMD : 0);
381}
382
383static inline void control_rx_s_edge_detection(struct i2c_client *c,
384 u32 edge_types)
385{
386 cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~CNTRL_EDG_BOTH,
387 edge_types & CNTRL_EDG_BOTH);
388}
389
390static void control_rx_s_carrier_window(struct i2c_client *c,
391 unsigned int carrier,
392 unsigned int *carrier_range_low,
393 unsigned int *carrier_range_high)
394{
395 u32 v;
396 unsigned int c16 = carrier * 16;
397
398 if (*carrier_range_low < DIV_ROUND_CLOSEST(c16, 16 + 3)) {
399 v = CNTRL_WIN_3_4;
400 *carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 4);
401 } else {
402 v = CNTRL_WIN_3_3;
403 *carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 3);
404 }
405
406 if (*carrier_range_high > DIV_ROUND_CLOSEST(c16, 16 - 3)) {
407 v |= CNTRL_WIN_4_3;
408 *carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 4);
409 } else {
410 v |= CNTRL_WIN_3_3;
411 *carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 3);
412 }
413 cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~CNTRL_WIN, v);
414}
415
416static inline void control_tx_polarity_invert(struct i2c_client *c,
417 bool invert)
418{
419 cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~CNTRL_CPL,
420 invert ? CNTRL_CPL : 0);
421}
422
423/*
424 * IR Rx & Tx Clock Register helpers
425 */
426static unsigned int txclk_tx_s_carrier(struct i2c_client *c,
427 unsigned int freq,
428 u16 *divider)
429{
430 *divider = carrier_freq_to_clock_divider(freq);
431 cx25840_write4(c, CX25840_IR_TXCLK_REG, *divider);
432 return clock_divider_to_carrier_freq(*divider);
433}
434
435static unsigned int rxclk_rx_s_carrier(struct i2c_client *c,
436 unsigned int freq,
437 u16 *divider)
438{
439 *divider = carrier_freq_to_clock_divider(freq);
440 cx25840_write4(c, CX25840_IR_RXCLK_REG, *divider);
441 return clock_divider_to_carrier_freq(*divider);
442}
443
444static u32 txclk_tx_s_max_pulse_width(struct i2c_client *c, u32 ns,
445 u16 *divider)
446{
447 u64 pulse_clocks;
448
449 if (ns > IR_MAX_DURATION)
450 ns = IR_MAX_DURATION;
451 pulse_clocks = ns_to_pulse_clocks(ns);
452 *divider = pulse_clocks_to_clock_divider(pulse_clocks);
453 cx25840_write4(c, CX25840_IR_TXCLK_REG, *divider);
454 return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider);
455}
456
457static u32 rxclk_rx_s_max_pulse_width(struct i2c_client *c, u32 ns,
458 u16 *divider)
459{
460 u64 pulse_clocks;
461
462 if (ns > IR_MAX_DURATION)
463 ns = IR_MAX_DURATION;
464 pulse_clocks = ns_to_pulse_clocks(ns);
465 *divider = pulse_clocks_to_clock_divider(pulse_clocks);
466 cx25840_write4(c, CX25840_IR_RXCLK_REG, *divider);
467 return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider);
468}
469
470/*
471 * IR Tx Carrier Duty Cycle register helpers
472 */
473static unsigned int cduty_tx_s_duty_cycle(struct i2c_client *c,
474 unsigned int duty_cycle)
475{
476 u32 n;
477 n = DIV_ROUND_CLOSEST(duty_cycle * 100, 625); /* 16ths of 100% */
478 if (n != 0)
479 n--;
480 if (n > 15)
481 n = 15;
482 cx25840_write4(c, CX25840_IR_CDUTY_REG, n);
483 return DIV_ROUND_CLOSEST((n + 1) * 100, 16);
484}
485
486/*
487 * IR Filter Register helpers
488 */
489static u32 filter_rx_s_min_width(struct i2c_client *c, u32 min_width_ns)
490{
491 u32 count = ns_to_lpf_count(min_width_ns);
492 cx25840_write4(c, CX25840_IR_FILTR_REG, count);
493 return lpf_count_to_ns(count);
494}
495
496/*
497 * IR IRQ Enable Register helpers
498 */
499static inline void irqenable_rx(struct v4l2_subdev *sd, u32 mask)
500{
501 struct cx25840_state *state = to_state(sd);
502
503 if (is_cx23885(state) || is_cx23887(state))
504 mask ^= IRQEN_MSK;
505 mask &= (IRQEN_RTE | IRQEN_ROE | IRQEN_RSE);
506 cx25840_and_or4(state->c, CX25840_IR_IRQEN_REG,
507 ~(IRQEN_RTE | IRQEN_ROE | IRQEN_RSE), mask);
508}
509
510static inline void irqenable_tx(struct v4l2_subdev *sd, u32 mask)
511{
512 struct cx25840_state *state = to_state(sd);
513
514 if (is_cx23885(state) || is_cx23887(state))
515 mask ^= IRQEN_MSK;
516 mask &= IRQEN_TSE;
517 cx25840_and_or4(state->c, CX25840_IR_IRQEN_REG, ~IRQEN_TSE, mask);
518}
519
520/*
521 * V4L2 Subdevice IR Ops
522 */
523int cx25840_ir_irq_handler(struct v4l2_subdev *sd, u32 status, bool *handled)
524{
525 struct cx25840_state *state = to_state(sd);
526 struct cx25840_ir_state *ir_state = to_ir_state(sd);
527 struct i2c_client *c = NULL;
528 unsigned long flags;
529
530 union cx25840_ir_fifo_rec rx_data[FIFO_RX_DEPTH];
531 unsigned int i, j, k;
532 u32 events, v;
533 int tsr, rsr, rto, ror, tse, rse, rte, roe, kror;
534 u32 cntrl, irqen, stats;
535
536 *handled = false;
537 if (ir_state == NULL)
538 return -ENODEV;
539
540 c = ir_state->c;
541
542 /* Only support the IR controller for the CX2388[57] AV Core for now */
543 if (!(is_cx23885(state) || is_cx23887(state)))
544 return -ENODEV;
545
546 cntrl = cx25840_read4(c, CX25840_IR_CNTRL_REG);
547 irqen = cx25840_read4(c, CX25840_IR_IRQEN_REG);
548 if (is_cx23885(state) || is_cx23887(state))
549 irqen ^= IRQEN_MSK;
550 stats = cx25840_read4(c, CX25840_IR_STATS_REG);
551
552 tsr = stats & STATS_TSR; /* Tx FIFO Service Request */
553 rsr = stats & STATS_RSR; /* Rx FIFO Service Request */
554 rto = stats & STATS_RTO; /* Rx Pulse Width Timer Time Out */
555 ror = stats & STATS_ROR; /* Rx FIFO Over Run */
556
557 tse = irqen & IRQEN_TSE; /* Tx FIFO Service Request IRQ Enable */
558 rse = irqen & IRQEN_RSE; /* Rx FIFO Service Reuqest IRQ Enable */
559 rte = irqen & IRQEN_RTE; /* Rx Pulse Width Timer Time Out IRQ Enable */
560 roe = irqen & IRQEN_ROE; /* Rx FIFO Over Run IRQ Enable */
561
562 v4l2_dbg(2, ir_debug, sd, "IR IRQ Status: %s %s %s %s %s %s\n",
563 tsr ? "tsr" : " ", rsr ? "rsr" : " ",
564 rto ? "rto" : " ", ror ? "ror" : " ",
565 stats & STATS_TBY ? "tby" : " ",
566 stats & STATS_RBY ? "rby" : " ");
567
568 v4l2_dbg(2, ir_debug, sd, "IR IRQ Enables: %s %s %s %s\n",
569 tse ? "tse" : " ", rse ? "rse" : " ",
570 rte ? "rte" : " ", roe ? "roe" : " ");
571
572 /*
573 * Transmitter interrupt service
574 */
575 if (tse && tsr) {
576 /*
577 * TODO:
578 * Check the watermark threshold setting
579 * Pull FIFO_TX_DEPTH or FIFO_TX_DEPTH/2 entries from tx_kfifo
580 * Push the data to the hardware FIFO.
581 * If there was nothing more to send in the tx_kfifo, disable
582 * the TSR IRQ and notify the v4l2_device.
583 * If there was something in the tx_kfifo, check the tx_kfifo
584 * level and notify the v4l2_device, if it is low.
585 */
586 /* For now, inhibit TSR interrupt until Tx is implemented */
587 irqenable_tx(sd, 0);
588 events = V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ;
589 v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_TX_NOTIFY, &events);
590 *handled = true;
591 }
592
593 /*
594 * Receiver interrupt service
595 */
596 kror = 0;
597 if ((rse && rsr) || (rte && rto)) {
598 /*
599 * Receive data on RSR to clear the STATS_RSR.
600 * Receive data on RTO, since we may not have yet hit the RSR
601 * watermark when we receive the RTO.
602 */
603 for (i = 0, v = FIFO_RX_NDV;
604 (v & FIFO_RX_NDV) && !kror; i = 0) {
605 for (j = 0;
606 (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) {
607 v = cx25840_read4(c, CX25840_IR_FIFO_REG);
608 rx_data[i].hw_fifo_data = v & ~FIFO_RX_NDV;
609 i++;
610 }
611 if (i == 0)
612 break;
613 j = i * sizeof(union cx25840_ir_fifo_rec);
614 k = kfifo_in_locked(&ir_state->rx_kfifo,
615 (unsigned char *) rx_data, j,
616 &ir_state->rx_kfifo_lock);
617 if (k != j)
618 kror++; /* rx_kfifo over run */
619 }
620 *handled = true;
621 }
622
623 events = 0;
624 v = 0;
625 if (kror) {
626 events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN;
627 v4l2_err(sd, "IR receiver software FIFO overrun\n");
628 }
629 if (roe && ror) {
630 /*
631 * The RX FIFO Enable (CNTRL_RFE) must be toggled to clear
632 * the Rx FIFO Over Run status (STATS_ROR)
633 */
634 v |= CNTRL_RFE;
635 events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN;
636 v4l2_err(sd, "IR receiver hardware FIFO overrun\n");
637 }
638 if (rte && rto) {
639 /*
640 * The IR Receiver Enable (CNTRL_RXE) must be toggled to clear
641 * the Rx Pulse Width Timer Time Out (STATS_RTO)
642 */
643 v |= CNTRL_RXE;
644 events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED;
645 }
646 if (v) {
647 /* Clear STATS_ROR & STATS_RTO as needed by reseting hardware */
648 cx25840_write4(c, CX25840_IR_CNTRL_REG, cntrl & ~v);
649 cx25840_write4(c, CX25840_IR_CNTRL_REG, cntrl);
650 *handled = true;
651 }
652 spin_lock_irqsave(&ir_state->rx_kfifo_lock, flags);
653 if (kfifo_len(&ir_state->rx_kfifo) >= CX25840_IR_RX_KFIFO_SIZE / 2)
654 events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
655 spin_unlock_irqrestore(&ir_state->rx_kfifo_lock, flags);
656
657 if (events)
658 v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events);
659 return 0;
660}
661
662/* Receiver */
663static int cx25840_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
664 ssize_t *num)
665{
666 struct cx25840_ir_state *ir_state = to_ir_state(sd);
667 bool invert;
668 u16 divider;
669 unsigned int i, n;
670 union cx25840_ir_fifo_rec *p;
671 unsigned u, v;
672
673 if (ir_state == NULL)
674 return -ENODEV;
675
676 invert = (bool) atomic_read(&ir_state->rx_invert);
677 divider = (u16) atomic_read(&ir_state->rxclk_divider);
678
679 n = count / sizeof(union cx25840_ir_fifo_rec)
680 * sizeof(union cx25840_ir_fifo_rec);
681 if (n == 0) {
682 *num = 0;
683 return 0;
684 }
685
686 n = kfifo_out_locked(&ir_state->rx_kfifo, buf, n,
687 &ir_state->rx_kfifo_lock);
688
689 n /= sizeof(union cx25840_ir_fifo_rec);
690 *num = n * sizeof(union cx25840_ir_fifo_rec);
691
692 for (p = (union cx25840_ir_fifo_rec *) buf, i = 0; i < n; p++, i++) {
693
694 if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
695 /* Assume RTO was because of no IR light input */
696 u = 0;
697 v4l2_dbg(2, ir_debug, sd, "rx read: end of rx\n");
698 } else {
699 u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
700 if (invert)
701 u = u ? 0 : 1;
702 }
703
704 v = (unsigned) pulse_width_count_to_ns(
705 (u16) (p->hw_fifo_data & FIFO_RXTX), divider);
706 if (v > IR_MAX_DURATION)
707 v = IR_MAX_DURATION;
708
709 p->ir_core_data.pulse = u;
710 p->ir_core_data.duration = v;
711
712 v4l2_dbg(2, ir_debug, sd, "rx read: %10u ns %s\n",
713 v, u ? "mark" : "space");
714 }
715 return 0;
716}
717
718static int cx25840_ir_rx_g_parameters(struct v4l2_subdev *sd,
719 struct v4l2_subdev_ir_parameters *p)
720{
721 struct cx25840_ir_state *ir_state = to_ir_state(sd);
722
723 if (ir_state == NULL)
724 return -ENODEV;
725
726 mutex_lock(&ir_state->rx_params_lock);
727 memcpy(p, &ir_state->rx_params,
728 sizeof(struct v4l2_subdev_ir_parameters));
729 mutex_unlock(&ir_state->rx_params_lock);
730 return 0;
731}
732
733static int cx25840_ir_rx_shutdown(struct v4l2_subdev *sd)
734{
735 struct cx25840_ir_state *ir_state = to_ir_state(sd);
736 struct i2c_client *c;
737
738 if (ir_state == NULL)
739 return -ENODEV;
740
741 c = ir_state->c;
742 mutex_lock(&ir_state->rx_params_lock);
743
744 /* Disable or slow down all IR Rx circuits and counters */
745 irqenable_rx(sd, 0);
746 control_rx_enable(c, false);
747 control_rx_demodulation_enable(c, false);
748 control_rx_s_edge_detection(c, CNTRL_EDG_NONE);
749 filter_rx_s_min_width(c, 0);
750 cx25840_write4(c, CX25840_IR_RXCLK_REG, RXCLK_RCD);
751
752 ir_state->rx_params.shutdown = true;
753
754 mutex_unlock(&ir_state->rx_params_lock);
755 return 0;
756}
757
758static int cx25840_ir_rx_s_parameters(struct v4l2_subdev *sd,
759 struct v4l2_subdev_ir_parameters *p)
760{
761 struct cx25840_ir_state *ir_state = to_ir_state(sd);
762 struct i2c_client *c;
763 struct v4l2_subdev_ir_parameters *o;
764 u16 rxclk_divider;
765
766 if (ir_state == NULL)
767 return -ENODEV;
768
769 if (p->shutdown)
770 return cx25840_ir_rx_shutdown(sd);
771
772 if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
773 return -ENOSYS;
774
775 c = ir_state->c;
776 o = &ir_state->rx_params;
777
778 mutex_lock(&ir_state->rx_params_lock);
779
780 o->shutdown = p->shutdown;
781
782 p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
783 o->mode = p->mode;
784
785 p->bytes_per_data_element = sizeof(union cx25840_ir_fifo_rec);
786 o->bytes_per_data_element = p->bytes_per_data_element;
787
788 /* Before we tweak the hardware, we have to disable the receiver */
789 irqenable_rx(sd, 0);
790 control_rx_enable(c, false);
791
792 control_rx_demodulation_enable(c, p->modulation);
793 o->modulation = p->modulation;
794
795 if (p->modulation) {
796 p->carrier_freq = rxclk_rx_s_carrier(c, p->carrier_freq,
797 &rxclk_divider);
798
799 o->carrier_freq = p->carrier_freq;
800
801 p->duty_cycle = 50;
802 o->duty_cycle = p->duty_cycle;
803
804 control_rx_s_carrier_window(c, p->carrier_freq,
805 &p->carrier_range_lower,
806 &p->carrier_range_upper);
807 o->carrier_range_lower = p->carrier_range_lower;
808 o->carrier_range_upper = p->carrier_range_upper;
809
810 p->max_pulse_width =
811 (u32) pulse_width_count_to_ns(FIFO_RXTX, rxclk_divider);
812 } else {
813 p->max_pulse_width =
814 rxclk_rx_s_max_pulse_width(c, p->max_pulse_width,
815 &rxclk_divider);
816 }
817 o->max_pulse_width = p->max_pulse_width;
818 atomic_set(&ir_state->rxclk_divider, rxclk_divider);
819
820 p->noise_filter_min_width =
821 filter_rx_s_min_width(c, p->noise_filter_min_width);
822 o->noise_filter_min_width = p->noise_filter_min_width;
823
824 p->resolution = clock_divider_to_resolution(rxclk_divider);
825 o->resolution = p->resolution;
826
827 /* FIXME - make this dependent on resolution for better performance */
828 control_rx_irq_watermark(c, RX_FIFO_HALF_FULL);
829
830 control_rx_s_edge_detection(c, CNTRL_EDG_BOTH);
831
832 o->invert_level = p->invert_level;
833 atomic_set(&ir_state->rx_invert, p->invert_level);
834
835 o->interrupt_enable = p->interrupt_enable;
836 o->enable = p->enable;
837 if (p->enable) {
838 unsigned long flags;
839
840 spin_lock_irqsave(&ir_state->rx_kfifo_lock, flags);
841 kfifo_reset(&ir_state->rx_kfifo);
842 spin_unlock_irqrestore(&ir_state->rx_kfifo_lock, flags);
843 if (p->interrupt_enable)
844 irqenable_rx(sd, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE);
845 control_rx_enable(c, p->enable);
846 }
847
848 mutex_unlock(&ir_state->rx_params_lock);
849 return 0;
850}
851
852/* Transmitter */
853static int cx25840_ir_tx_write(struct v4l2_subdev *sd, u8 *buf, size_t count,
854 ssize_t *num)
855{
856 struct cx25840_ir_state *ir_state = to_ir_state(sd);
857 struct i2c_client *c;
858
859 if (ir_state == NULL)
860 return -ENODEV;
861
862 c = ir_state->c;
863#if 0
864 /*
865 * FIXME - the code below is an incomplete and untested sketch of what
866 * may need to be done. The critical part is to get 4 (or 8) pulses
867 * from the tx_kfifo, or converted from ns to the proper units from the
868 * input, and push them off to the hardware Tx FIFO right away, if the
869 * HW TX fifo needs service. The rest can be pushed to the tx_kfifo in
870 * a less critical timeframe. Also watch out for overruning the
871 * tx_kfifo - don't let it happen and let the caller know not all his
872 * pulses were written.
873 */
874 u32 *ns_pulse = (u32 *) buf;
875 unsigned int n;
876 u32 fifo_pulse[FIFO_TX_DEPTH];
877 u32 mark;
878
879 /* Compute how much we can fit in the tx kfifo */
880 n = CX25840_IR_TX_KFIFO_SIZE - kfifo_len(ir_state->tx_kfifo);
881 n = min(n, (unsigned int) count);
882 n /= sizeof(u32);
883
884 /* FIXME - turn on Tx Fifo service interrupt
885 * check hardware fifo level, and other stuff
886 */
887 for (i = 0; i < n; ) {
888 for (j = 0; j < FIFO_TX_DEPTH / 2 && i < n; j++) {
889 mark = ns_pulse[i] & LEVEL_MASK;
890 fifo_pulse[j] = ns_to_pulse_width_count(
891 ns_pulse[i] &
892 ~LEVEL_MASK,
893 ir_state->txclk_divider);
894 if (mark)
895 fifo_pulse[j] &= FIFO_RXTX_LVL;
896 i++;
897 }
898 kfifo_put(ir_state->tx_kfifo, (u8 *) fifo_pulse,
899 j * sizeof(u32));
900 }
901 *num = n * sizeof(u32);
902#else
903 /* For now enable the Tx FIFO Service interrupt & pretend we did work */
904 irqenable_tx(sd, IRQEN_TSE);
905 *num = count;
906#endif
907 return 0;
908}
909
910static int cx25840_ir_tx_g_parameters(struct v4l2_subdev *sd,
911 struct v4l2_subdev_ir_parameters *p)
912{
913 struct cx25840_ir_state *ir_state = to_ir_state(sd);
914
915 if (ir_state == NULL)
916 return -ENODEV;
917
918 mutex_lock(&ir_state->tx_params_lock);
919 memcpy(p, &ir_state->tx_params,
920 sizeof(struct v4l2_subdev_ir_parameters));
921 mutex_unlock(&ir_state->tx_params_lock);
922 return 0;
923}
924
925static int cx25840_ir_tx_shutdown(struct v4l2_subdev *sd)
926{
927 struct cx25840_ir_state *ir_state = to_ir_state(sd);
928 struct i2c_client *c;
929
930 if (ir_state == NULL)
931 return -ENODEV;
932
933 c = ir_state->c;
934 mutex_lock(&ir_state->tx_params_lock);
935
936 /* Disable or slow down all IR Tx circuits and counters */
937 irqenable_tx(sd, 0);
938 control_tx_enable(c, false);
939 control_tx_modulation_enable(c, false);
940 cx25840_write4(c, CX25840_IR_TXCLK_REG, TXCLK_TCD);
941
942 ir_state->tx_params.shutdown = true;
943
944 mutex_unlock(&ir_state->tx_params_lock);
945 return 0;
946}
947
948static int cx25840_ir_tx_s_parameters(struct v4l2_subdev *sd,
949 struct v4l2_subdev_ir_parameters *p)
950{
951 struct cx25840_ir_state *ir_state = to_ir_state(sd);
952 struct i2c_client *c;
953 struct v4l2_subdev_ir_parameters *o;
954 u16 txclk_divider;
955
956 if (ir_state == NULL)
957 return -ENODEV;
958
959 if (p->shutdown)
960 return cx25840_ir_tx_shutdown(sd);
961
962 if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
963 return -ENOSYS;
964
965 c = ir_state->c;
966 o = &ir_state->tx_params;
967 mutex_lock(&ir_state->tx_params_lock);
968
969 o->shutdown = p->shutdown;
970
971 p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
972 o->mode = p->mode;
973
974 p->bytes_per_data_element = sizeof(union cx25840_ir_fifo_rec);
975 o->bytes_per_data_element = p->bytes_per_data_element;
976
977 /* Before we tweak the hardware, we have to disable the transmitter */
978 irqenable_tx(sd, 0);
979 control_tx_enable(c, false);
980
981 control_tx_modulation_enable(c, p->modulation);
982 o->modulation = p->modulation;
983
984 if (p->modulation) {
985 p->carrier_freq = txclk_tx_s_carrier(c, p->carrier_freq,
986 &txclk_divider);
987 o->carrier_freq = p->carrier_freq;
988
989 p->duty_cycle = cduty_tx_s_duty_cycle(c, p->duty_cycle);
990 o->duty_cycle = p->duty_cycle;
991
992 p->max_pulse_width =
993 (u32) pulse_width_count_to_ns(FIFO_RXTX, txclk_divider);
994 } else {
995 p->max_pulse_width =
996 txclk_tx_s_max_pulse_width(c, p->max_pulse_width,
997 &txclk_divider);
998 }
999 o->max_pulse_width = p->max_pulse_width;
1000 atomic_set(&ir_state->txclk_divider, txclk_divider);
1001
1002 p->resolution = clock_divider_to_resolution(txclk_divider);
1003 o->resolution = p->resolution;
1004
1005 /* FIXME - make this dependent on resolution for better performance */
1006 control_tx_irq_watermark(c, TX_FIFO_HALF_EMPTY);
1007
1008 control_tx_polarity_invert(c, p->invert_carrier_sense);
1009 o->invert_carrier_sense = p->invert_carrier_sense;
1010
1011 /*
1012 * FIXME: we don't have hardware help for IO pin level inversion
1013 * here like we have on the CX23888.
1014 * Act on this with some mix of logical inversion of data levels,
1015 * carrier polarity, and carrier duty cycle.
1016 */
1017 o->invert_level = p->invert_level;
1018
1019 o->interrupt_enable = p->interrupt_enable;
1020 o->enable = p->enable;
1021 if (p->enable) {
1022 /* reset tx_fifo here */
1023 if (p->interrupt_enable)
1024 irqenable_tx(sd, IRQEN_TSE);
1025 control_tx_enable(c, p->enable);
1026 }
1027
1028 mutex_unlock(&ir_state->tx_params_lock);
1029 return 0;
1030}
1031
1032
1033/*
1034 * V4L2 Subdevice Core Ops support
1035 */
1036int cx25840_ir_log_status(struct v4l2_subdev *sd)
1037{
1038 struct cx25840_state *state = to_state(sd);
1039 struct i2c_client *c = state->c;
1040 char *s;
1041 int i, j;
1042 u32 cntrl, txclk, rxclk, cduty, stats, irqen, filtr;
1043
1044 /* The CX23888 chip doesn't have an IR controller on the A/V core */
1045 if (is_cx23888(state))
1046 return 0;
1047
1048 cntrl = cx25840_read4(c, CX25840_IR_CNTRL_REG);
1049 txclk = cx25840_read4(c, CX25840_IR_TXCLK_REG) & TXCLK_TCD;
1050 rxclk = cx25840_read4(c, CX25840_IR_RXCLK_REG) & RXCLK_RCD;
1051 cduty = cx25840_read4(c, CX25840_IR_CDUTY_REG) & CDUTY_CDC;
1052 stats = cx25840_read4(c, CX25840_IR_STATS_REG);
1053 irqen = cx25840_read4(c, CX25840_IR_IRQEN_REG);
1054 if (is_cx23885(state) || is_cx23887(state))
1055 irqen ^= IRQEN_MSK;
1056 filtr = cx25840_read4(c, CX25840_IR_FILTR_REG) & FILTR_LPF;
1057
1058 v4l2_info(sd, "IR Receiver:\n");
1059 v4l2_info(sd, "\tEnabled: %s\n",
1060 cntrl & CNTRL_RXE ? "yes" : "no");
1061 v4l2_info(sd, "\tDemodulation from a carrier: %s\n",
1062 cntrl & CNTRL_DMD ? "enabled" : "disabled");
1063 v4l2_info(sd, "\tFIFO: %s\n",
1064 cntrl & CNTRL_RFE ? "enabled" : "disabled");
1065 switch (cntrl & CNTRL_EDG) {
1066 case CNTRL_EDG_NONE:
1067 s = "disabled";
1068 break;
1069 case CNTRL_EDG_FALL:
1070 s = "falling edge";
1071 break;
1072 case CNTRL_EDG_RISE:
1073 s = "rising edge";
1074 break;
1075 case CNTRL_EDG_BOTH:
1076 s = "rising & falling edges";
1077 break;
1078 default:
1079 s = "??? edge";
1080 break;
1081 }
1082 v4l2_info(sd, "\tPulse timers' start/stop trigger: %s\n", s);
1083 v4l2_info(sd, "\tFIFO data on pulse timer overflow: %s\n",
1084 cntrl & CNTRL_R ? "not loaded" : "overflow marker");
1085 v4l2_info(sd, "\tFIFO interrupt watermark: %s\n",
1086 cntrl & CNTRL_RIC ? "not empty" : "half full or greater");
1087 v4l2_info(sd, "\tLoopback mode: %s\n",
1088 cntrl & CNTRL_LBM ? "loopback active" : "normal receive");
1089 if (cntrl & CNTRL_DMD) {
1090 v4l2_info(sd, "\tExpected carrier (16 clocks): %u Hz\n",
1091 clock_divider_to_carrier_freq(rxclk));
1092 switch (cntrl & CNTRL_WIN) {
1093 case CNTRL_WIN_3_3:
1094 i = 3;
1095 j = 3;
1096 break;
1097 case CNTRL_WIN_4_3:
1098 i = 4;
1099 j = 3;
1100 break;
1101 case CNTRL_WIN_3_4:
1102 i = 3;
1103 j = 4;
1104 break;
1105 case CNTRL_WIN_4_4:
1106 i = 4;
1107 j = 4;
1108 break;
1109 default:
1110 i = 0;
1111 j = 0;
1112 break;
1113 }
1114 v4l2_info(sd, "\tNext carrier edge window: 16 clocks "
1115 "-%1d/+%1d, %u to %u Hz\n", i, j,
1116 clock_divider_to_freq(rxclk, 16 + j),
1117 clock_divider_to_freq(rxclk, 16 - i));
1118 }
1119 v4l2_info(sd, "\tMax measurable pulse width: %u us, %llu ns\n",
1120 pulse_width_count_to_us(FIFO_RXTX, rxclk),
1121 pulse_width_count_to_ns(FIFO_RXTX, rxclk));
1122 v4l2_info(sd, "\tLow pass filter: %s\n",
1123 filtr ? "enabled" : "disabled");
1124 if (filtr)
1125 v4l2_info(sd, "\tMin acceptable pulse width (LPF): %u us, "
1126 "%u ns\n",
1127 lpf_count_to_us(filtr),
1128 lpf_count_to_ns(filtr));
1129 v4l2_info(sd, "\tPulse width timer timed-out: %s\n",
1130 stats & STATS_RTO ? "yes" : "no");
1131 v4l2_info(sd, "\tPulse width timer time-out intr: %s\n",
1132 irqen & IRQEN_RTE ? "enabled" : "disabled");
1133 v4l2_info(sd, "\tFIFO overrun: %s\n",
1134 stats & STATS_ROR ? "yes" : "no");
1135 v4l2_info(sd, "\tFIFO overrun interrupt: %s\n",
1136 irqen & IRQEN_ROE ? "enabled" : "disabled");
1137 v4l2_info(sd, "\tBusy: %s\n",
1138 stats & STATS_RBY ? "yes" : "no");
1139 v4l2_info(sd, "\tFIFO service requested: %s\n",
1140 stats & STATS_RSR ? "yes" : "no");
1141 v4l2_info(sd, "\tFIFO service request interrupt: %s\n",
1142 irqen & IRQEN_RSE ? "enabled" : "disabled");
1143
1144 v4l2_info(sd, "IR Transmitter:\n");
1145 v4l2_info(sd, "\tEnabled: %s\n",
1146 cntrl & CNTRL_TXE ? "yes" : "no");
1147 v4l2_info(sd, "\tModulation onto a carrier: %s\n",
1148 cntrl & CNTRL_MOD ? "enabled" : "disabled");
1149 v4l2_info(sd, "\tFIFO: %s\n",
1150 cntrl & CNTRL_TFE ? "enabled" : "disabled");
1151 v4l2_info(sd, "\tFIFO interrupt watermark: %s\n",
1152 cntrl & CNTRL_TIC ? "not empty" : "half full or less");
1153 v4l2_info(sd, "\tCarrier polarity: %s\n",
1154 cntrl & CNTRL_CPL ? "space:burst mark:noburst"
1155 : "space:noburst mark:burst");
1156 if (cntrl & CNTRL_MOD) {
1157 v4l2_info(sd, "\tCarrier (16 clocks): %u Hz\n",
1158 clock_divider_to_carrier_freq(txclk));
1159 v4l2_info(sd, "\tCarrier duty cycle: %2u/16\n",
1160 cduty + 1);
1161 }
1162 v4l2_info(sd, "\tMax pulse width: %u us, %llu ns\n",
1163 pulse_width_count_to_us(FIFO_RXTX, txclk),
1164 pulse_width_count_to_ns(FIFO_RXTX, txclk));
1165 v4l2_info(sd, "\tBusy: %s\n",
1166 stats & STATS_TBY ? "yes" : "no");
1167 v4l2_info(sd, "\tFIFO service requested: %s\n",
1168 stats & STATS_TSR ? "yes" : "no");
1169 v4l2_info(sd, "\tFIFO service request interrupt: %s\n",
1170 irqen & IRQEN_TSE ? "enabled" : "disabled");
1171
1172 return 0;
1173}
1174
1175
1176const struct v4l2_subdev_ir_ops cx25840_ir_ops = {
1177 .rx_read = cx25840_ir_rx_read,
1178 .rx_g_parameters = cx25840_ir_rx_g_parameters,
1179 .rx_s_parameters = cx25840_ir_rx_s_parameters,
1180
1181 .tx_write = cx25840_ir_tx_write,
1182 .tx_g_parameters = cx25840_ir_tx_g_parameters,
1183 .tx_s_parameters = cx25840_ir_tx_s_parameters,
1184};
1185
1186
1187static const struct v4l2_subdev_ir_parameters default_rx_params = {
1188 .bytes_per_data_element = sizeof(union cx25840_ir_fifo_rec),
1189 .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
1190
1191 .enable = false,
1192 .interrupt_enable = false,
1193 .shutdown = true,
1194
1195 .modulation = true,
1196 .carrier_freq = 36000, /* 36 kHz - RC-5, and RC-6 carrier */
1197
1198 /* RC-5: 666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */
1199 /* RC-6: 333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */
1200 .noise_filter_min_width = 333333, /* ns */
1201 .carrier_range_lower = 35000,
1202 .carrier_range_upper = 37000,
1203 .invert_level = false,
1204};
1205
1206static const struct v4l2_subdev_ir_parameters default_tx_params = {
1207 .bytes_per_data_element = sizeof(union cx25840_ir_fifo_rec),
1208 .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
1209
1210 .enable = false,
1211 .interrupt_enable = false,
1212 .shutdown = true,
1213
1214 .modulation = true,
1215 .carrier_freq = 36000, /* 36 kHz - RC-5 carrier */
1216 .duty_cycle = 25, /* 25 % - RC-5 carrier */
1217 .invert_level = false,
1218 .invert_carrier_sense = false,
1219};
1220
1221int cx25840_ir_probe(struct v4l2_subdev *sd)
1222{
1223 struct cx25840_state *state = to_state(sd);
1224 struct cx25840_ir_state *ir_state;
1225 struct v4l2_subdev_ir_parameters default_params;
1226
1227 /* Only init the IR controller for the CX2388[57] AV Core for now */
1228 if (!(is_cx23885(state) || is_cx23887(state)))
1229 return 0;
1230
1231 ir_state = kzalloc(sizeof(struct cx25840_ir_state), GFP_KERNEL);
1232 if (ir_state == NULL)
1233 return -ENOMEM;
1234
1235 spin_lock_init(&ir_state->rx_kfifo_lock);
1236 if (kfifo_alloc(&ir_state->rx_kfifo,
1237 CX25840_IR_RX_KFIFO_SIZE, GFP_KERNEL)) {
1238 kfree(ir_state);
1239 return -ENOMEM;
1240 }
1241
1242 ir_state->c = state->c;
1243 state->ir_state = ir_state;
1244
1245 /* Ensure no interrupts arrive yet */
1246 if (is_cx23885(state) || is_cx23887(state))
1247 cx25840_write4(ir_state->c, CX25840_IR_IRQEN_REG, IRQEN_MSK);
1248 else
1249 cx25840_write4(ir_state->c, CX25840_IR_IRQEN_REG, 0);
1250
1251 mutex_init(&ir_state->rx_params_lock);
1252 memcpy(&default_params, &default_rx_params,
1253 sizeof(struct v4l2_subdev_ir_parameters));
1254 v4l2_subdev_call(sd, ir, rx_s_parameters, &default_params);
1255
1256 mutex_init(&ir_state->tx_params_lock);
1257 memcpy(&default_params, &default_tx_params,
1258 sizeof(struct v4l2_subdev_ir_parameters));
1259 v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params);
1260
1261 return 0;
1262}
1263
1264int cx25840_ir_remove(struct v4l2_subdev *sd)
1265{
1266 struct cx25840_state *state = to_state(sd);
1267 struct cx25840_ir_state *ir_state = to_ir_state(sd);
1268
1269 if (ir_state == NULL)
1270 return -ENODEV;
1271
1272 cx25840_ir_rx_shutdown(sd);
1273 cx25840_ir_tx_shutdown(sd);
1274
1275 kfifo_free(&ir_state->rx_kfifo);
1276 kfree(ir_state);
1277 state->ir_state = NULL;
1278 return 0;
1279}
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index d951b0f0e05..b9846106913 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -55,7 +55,7 @@ MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
55MODULE_DESCRIPTION("GSPCA USB Camera Driver"); 55MODULE_DESCRIPTION("GSPCA USB Camera Driver");
56MODULE_LICENSE("GPL"); 56MODULE_LICENSE("GPL");
57 57
58#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 9, 0) 58#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 10, 0)
59 59
60#ifdef GSPCA_DEBUG 60#ifdef GSPCA_DEBUG
61int gspca_debug = D_ERR | D_PROBE; 61int gspca_debug = D_ERR | D_PROBE;
@@ -440,10 +440,15 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,
440 frame->v4l2_buf.sequence = ++gspca_dev->sequence; 440 frame->v4l2_buf.sequence = ++gspca_dev->sequence;
441 gspca_dev->image = frame->data; 441 gspca_dev->image = frame->data;
442 gspca_dev->image_len = 0; 442 gspca_dev->image_len = 0;
443 } else if (gspca_dev->last_packet_type == DISCARD_PACKET) { 443 } else {
444 if (packet_type == LAST_PACKET) 444 switch (gspca_dev->last_packet_type) {
445 gspca_dev->last_packet_type = packet_type; 445 case DISCARD_PACKET:
446 return; 446 if (packet_type == LAST_PACKET)
447 gspca_dev->last_packet_type = packet_type;
448 return;
449 case LAST_PACKET:
450 return;
451 }
447 } 452 }
448 453
449 /* append the packet to the frame buffer */ 454 /* append the packet to the frame buffer */
@@ -454,6 +459,12 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,
454 gspca_dev->frsz); 459 gspca_dev->frsz);
455 packet_type = DISCARD_PACKET; 460 packet_type = DISCARD_PACKET;
456 } else { 461 } else {
462/* !! image is NULL only when last pkt is LAST or DISCARD
463 if (gspca_dev->image == NULL) {
464 err("gspca_frame_add() image == NULL");
465 return;
466 }
467 */
457 memcpy(gspca_dev->image + gspca_dev->image_len, 468 memcpy(gspca_dev->image + gspca_dev->image_len,
458 data, len); 469 data, len);
459 gspca_dev->image_len += len; 470 gspca_dev->image_len += len;
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index ee17b034bf6..370544361be 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -66,7 +66,11 @@ struct sd {
66#define BRIDGE_SN9C110 2 66#define BRIDGE_SN9C110 2
67#define BRIDGE_SN9C120 3 67#define BRIDGE_SN9C120 3
68 u8 sensor; /* Type of image sensor chip */ 68 u8 sensor; /* Type of image sensor chip */
69enum { 69 u8 i2c_addr;
70
71 u8 jpeg_hdr[JPEG_HDR_SZ];
72};
73enum sensors {
70 SENSOR_ADCM1700, 74 SENSOR_ADCM1700,
71 SENSOR_GC0307, 75 SENSOR_GC0307,
72 SENSOR_HV7131R, 76 SENSOR_HV7131R,
@@ -81,10 +85,6 @@ enum {
81 SENSOR_PO2030N, 85 SENSOR_PO2030N,
82 SENSOR_SOI768, 86 SENSOR_SOI768,
83 SENSOR_SP80708, 87 SENSOR_SP80708,
84} sensors;
85 u8 i2c_addr;
86
87 u8 jpeg_hdr[JPEG_HDR_SZ];
88}; 88};
89 89
90/* V4L2 controls supported by the driver */ 90/* V4L2 controls supported by the driver */
diff --git a/drivers/media/video/gspca/sq930x.c b/drivers/media/video/gspca/sq930x.c
index 37cee5e063c..7ae6522d4ed 100644
--- a/drivers/media/video/gspca/sq930x.c
+++ b/drivers/media/video/gspca/sq930x.c
@@ -23,7 +23,6 @@
23#define MODULE_NAME "sq930x" 23#define MODULE_NAME "sq930x"
24 24
25#include "gspca.h" 25#include "gspca.h"
26#include "jpeg.h"
27 26
28MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>\n" 27MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>\n"
29 "Gerard Klaver <gerard at gkall dot hobby dot nl\n" 28 "Gerard Klaver <gerard at gkall dot hobby dot nl\n"
@@ -31,8 +30,6 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>\n"
31MODULE_DESCRIPTION("GSPCA/SQ930x USB Camera Driver"); 30MODULE_DESCRIPTION("GSPCA/SQ930x USB Camera Driver");
32MODULE_LICENSE("GPL"); 31MODULE_LICENSE("GPL");
33 32
34#define BULK_TRANSFER_LEN 5128
35
36/* Structure to hold all of our device specific stuff */ 33/* Structure to hold all of our device specific stuff */
37struct sd { 34struct sd {
38 struct gspca_dev gspca_dev; /* !! must be the first item */ 35 struct gspca_dev gspca_dev; /* !! must be the first item */
@@ -40,28 +37,20 @@ struct sd {
40 u16 expo; 37 u16 expo;
41 u8 gain; 38 u8 gain;
42 39
43 u8 quality; /* webcam quality 0..3 */
44#define QUALITY_DEF 1
45
46 u8 gpio[2];
47
48 u8 eof_len;
49 u8 do_ctrl; 40 u8 do_ctrl;
50 41 u8 gpio[2];
51 u8 sensor; 42 u8 sensor;
52enum { 43 u8 type;
44#define Generic 0
45#define Creative_live_motion 1
46};
47enum sensors {
53 SENSOR_ICX098BQ, 48 SENSOR_ICX098BQ,
54 SENSOR_LZ24BP, 49 SENSOR_LZ24BP,
55 SENSOR_MI0360, 50 SENSOR_MI0360,
56 SENSOR_MT9V111, 51 SENSOR_MT9V111, /* = MI360SOC */
57 SENSOR_OV7660, 52 SENSOR_OV7660,
58 SENSOR_OV9630, 53 SENSOR_OV9630,
59} sensors;
60 u8 type;
61#define Generic 0
62#define Creative_live_motion 1
63
64 u8 jpeg_hdr[JPEG_HDR_SZ];
65}; 54};
66 55
67static int sd_setexpo(struct gspca_dev *gspca_dev, __s32 val); 56static int sd_setexpo(struct gspca_dev *gspca_dev, __s32 val);
@@ -78,7 +67,7 @@ static const struct ctrl sd_ctrls[] = {
78 .minimum = 0x0001, 67 .minimum = 0x0001,
79 .maximum = 0x0fff, 68 .maximum = 0x0fff,
80 .step = 1, 69 .step = 1,
81#define EXPO_DEF 0x027d 70#define EXPO_DEF 0x0356
82 .default_value = EXPO_DEF, 71 .default_value = EXPO_DEF,
83 }, 72 },
84 .set = sd_setexpo, 73 .set = sd_setexpo,
@@ -92,7 +81,7 @@ static const struct ctrl sd_ctrls[] = {
92 .minimum = 0x01, 81 .minimum = 0x01,
93 .maximum = 0xff, 82 .maximum = 0xff,
94 .step = 1, 83 .step = 1,
95#define GAIN_DEF 0x61 84#define GAIN_DEF 0x8d
96 .default_value = GAIN_DEF, 85 .default_value = GAIN_DEF,
97 }, 86 },
98 .set = sd_setgain, 87 .set = sd_setgain,
@@ -101,30 +90,18 @@ static const struct ctrl sd_ctrls[] = {
101}; 90};
102 91
103static struct v4l2_pix_format vga_mode[] = { 92static struct v4l2_pix_format vga_mode[] = {
104 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 93 {320, 240, V4L2_PIX_FMT_SRGGB8, V4L2_FIELD_NONE,
105 .bytesperline = 160,
106 .sizeimage = 160 * 120 * 5 / 8 + 590,
107 .colorspace = V4L2_COLORSPACE_JPEG,
108 .priv = 0},
109 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
110 .bytesperline = 320, 94 .bytesperline = 320,
111 .sizeimage = 320 * 240 * 4 / 8 + 590, 95 .sizeimage = 320 * 240,
112 .colorspace = V4L2_COLORSPACE_JPEG, 96 .colorspace = V4L2_COLORSPACE_SRGB,
113 .priv = 1}, 97 .priv = 0},
114 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 98 {640, 480, V4L2_PIX_FMT_SRGGB8, V4L2_FIELD_NONE,
115 .bytesperline = 640, 99 .bytesperline = 640,
116 .sizeimage = 640 * 480 * 3 / 8 + 590, 100 .sizeimage = 640 * 480,
117 .colorspace = V4L2_COLORSPACE_JPEG, 101 .colorspace = V4L2_COLORSPACE_SRGB,
118 .priv = 2}, 102 .priv = 1},
119}; 103};
120 104
121/* JPEG quality indexed by webcam quality */
122#define QUAL_0 90
123#define QUAL_1 85
124#define QUAL_2 75
125#define QUAL_3 70
126static const u8 quality_tb[4] = { QUAL_0, QUAL_1, QUAL_2, QUAL_3 };
127
128/* sq930x registers */ 105/* sq930x registers */
129#define SQ930_CTRL_UCBUS_IO 0x0001 106#define SQ930_CTRL_UCBUS_IO 0x0001
130#define SQ930_CTRL_I2C_IO 0x0002 107#define SQ930_CTRL_I2C_IO 0x0002
@@ -302,7 +279,7 @@ static const struct i2c_write_cmd mt9v111_init_0[] = {
302 {0x01, 0x0001}, /* select IFP/SOC registers */ 279 {0x01, 0x0001}, /* select IFP/SOC registers */
303 {0x06, 0x300c}, /* operating mode control */ 280 {0x06, 0x300c}, /* operating mode control */
304 {0x08, 0xcc00}, /* output format control (RGB) */ 281 {0x08, 0xcc00}, /* output format control (RGB) */
305 {0x01, 0x0004}, /* select core registers */ 282 {0x01, 0x0004}, /* select sensor core registers */
306}; 283};
307static const struct i2c_write_cmd mt9v111_init_1[] = { 284static const struct i2c_write_cmd mt9v111_init_1[] = {
308 {0x03, 0x01e5}, /* window height */ 285 {0x03, 0x01e5}, /* window height */
@@ -330,7 +307,8 @@ static const struct i2c_write_cmd mt9v111_init_3[] = {
330 {0x62, 0x0405}, 307 {0x62, 0x0405},
331}; 308};
332static const struct i2c_write_cmd mt9v111_init_4[] = { 309static const struct i2c_write_cmd mt9v111_init_4[] = {
333 {0x05, 0x00ce}, /* horizontal blanking */ 310/* {0x05, 0x00ce}, */
311 {0x05, 0x005d}, /* horizontal blanking */
334}; 312};
335 313
336static const struct ucbus_write_cmd ov7660_start_0[] = { 314static const struct ucbus_write_cmd ov7660_start_0[] = {
@@ -343,78 +321,58 @@ static const struct ucbus_write_cmd ov9630_start_0[] = {
343 {0xf334, 0x3e}, {0xf335, 0xf8}, {0xf33f, 0x03} 321 {0xf334, 0x3e}, {0xf335, 0xf8}, {0xf33f, 0x03}
344}; 322};
345 323
324/* start parameters indexed by [sensor][mode] */
346static const struct cap_s { 325static const struct cap_s {
347 u8 cc_sizeid; 326 u8 cc_sizeid;
348 u8 cc_bytes[32]; 327 u8 cc_bytes[32];
349} capconfig[4][3] = { 328} capconfig[4][2] = {
350 [SENSOR_ICX098BQ] = { 329 [SENSOR_ICX098BQ] = {
351 {0, /* JPEG, 160x120 */ 330 {2, /* Bayer 320x240 */
331 {0x05, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee,
332 0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0,
334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
335 {4, /* Bayer 640x480 */
352 {0x01, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee, 336 {0x01, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee,
353 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, 337 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
354 0x02, 0x8b, 0x00, 0x8b, 0x00, 0x41, 0x01, 0x41, 338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355 0x01, 0x41, 0x01, 0x05, 0x40, 0x01, 0xf0, 0x00} }, 339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
356 {2, /* JPEG, 320x240 */
357 {0x01, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee,
358 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
359 0x02, 0xdf, 0x01, 0x00, 0x00, 0x3f, 0x01, 0x3f,
360 0x01, 0x00, 0x00, 0x05, 0x40, 0x01, 0xf0, 0x00} },
361 {4, /* JPEG, 640x480 */
362 {0x01, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xf0,
363 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
364 0x07, 0xe1, 0x01, 0xe1, 0x01, 0x3f, 0x01, 0x3f,
365 0x01, 0x3f, 0x01, 0x05, 0x80, 0x02, 0xe0, 0x01} },
366 }, 340 },
367 [SENSOR_LZ24BP] = { 341 [SENSOR_LZ24BP] = {
368 {0, /* JPEG, 160x120 */ 342 {2, /* Bayer 320x240 */
369 {0x01, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee, 343 {0x05, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee,
370 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, 344 0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
371 0x02, 0x8b, 0x00, 0x8b, 0x00, 0x41, 0x01, 0x41, 345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x01, 0x41, 0x01, 0x05, 0x40, 0x01, 0xf0, 0x00} }, 346 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
373 {2, /* JPEG, 320x240 */ 347 {4, /* Bayer 640x480 */
374 {0x01, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee, 348 {0x01, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee,
375 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, 349 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
376 0x02, 0xdf, 0x01, 0x00, 0x00, 0x3f, 0x01, 0x3f, 350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x01, 0x00, 0x00, 0x05, 0x40, 0x01, 0xf0, 0x00} }, 351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
378 {4, /* JPEG, 640x480 */
379 {0x01, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xf0,
380 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
381 0x07, 0xe1, 0x01, 0xe1, 0x01, 0x3f, 0x01, 0x3f,
382 0x01, 0x3f, 0x01, 0x05, 0x80, 0x02, 0xe0, 0x01} },
383 }, 352 },
384 [SENSOR_MI0360] = { 353 [SENSOR_MI0360] = {
385 {0, /* JPEG, 160x120 */ 354 {2, /* Bayer 320x240 */
386 {0x05, 0x3d, 0x20, 0x0b, 0x00, 0xbd, 0x02, 0x0b, 355 {0x05, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
387 0x02, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, 356 0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
388 0x02, 0x01, 0x01, 0x01, 0x01, 0x9f, 0x00, 0x9f, 357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
389 0x00, 0x9f, 0x01, 0x05, 0xa0, 0x00, 0x80, 0x00} }, 358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
390 {2, /* JPEG, 320x240 */ 359 {4, /* Bayer 640x480 */
391 {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1, 360 {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
392/*fixme 03 e3 */
393 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, 361 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
394 0x02, 0xdf, 0x01, 0x00, 0x00, 0x3f, 0x01, 0x3f, 362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
395 0x01, 0x00, 0x00, 0x05, 0x40, 0x01, 0xf0, 0x00} }, 363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
396 {4, /* JPEG, 640x480 */
397 {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe3,
398 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
399 0x07, 0xe1, 0x01, 0xe1, 0x01, 0x3f, 0x01, 0x3f,
400 0x01, 0x3f, 0x01, 0x05, 0x80, 0x02, 0xe0, 0x01} },
401 }, 364 },
402 [SENSOR_MT9V111] = { 365 [SENSOR_MT9V111] = {
403 {0, /* JPEG, 160x120 */ 366 {2, /* Bayer 320x240 */
404 {0x05, 0x3d, 0x20, 0x0b, 0x00, 0xbd, 0x02, 0x0b, 367 {0x05, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
405 0x02, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, 368 0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
406 0x02, 0x01, 0x01, 0x01, 0x01, 0x9f, 0x00, 0x9f, 369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
407 0x00, 0x9f, 0x01, 0x05, 0xa0, 0x00, 0x80, 0x00} }, 370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
408 {2, /* JPEG, 320x240 */ 371 {4, /* Bayer 640x480 */
409 {0x01, 0x02, 0x20, 0x03, 0x20, 0x82, 0x02, 0xe3, 372 {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
410 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
411 0x02, 0xdf, 0x01, 0x00, 0x00, 0x3f, 0x01, 0x3f,
412 0x01, 0x00, 0x00, 0x05, 0x40, 0x01, 0xf0, 0x00} },
413 {4, /* JPEG, 640x480 */
414 {0x01, 0x02, 0x20, 0x03, 0x20, 0x82, 0x02, 0xe3,
415 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, 373 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
416 0x07, 0xe1, 0x01, 0xe1, 0x01, 0x3f, 0x01, 0x3f, 374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
417 0x01, 0x3f, 0x01, 0x05, 0x80, 0x02, 0xe0, 0x01} }, 375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
418 }, 376 },
419}; 377};
420 378
@@ -864,7 +822,7 @@ static void setexposure(struct gspca_dev *gspca_dev)
864 buf[i++] = 0x35; /* reg = global gain */ 822 buf[i++] = 0x35; /* reg = global gain */
865 buf[i++] = 0x00; /* val H */ 823 buf[i++] = 0x00; /* val H */
866 buf[i++] = sensor->i2c_dum; 824 buf[i++] = sensor->i2c_dum;
867 buf[i++] = sd->gain; /* val L */ 825 buf[i++] = 0x80 + sd->gain / 2; /* val L */
868 buf[i++] = 0x00; 826 buf[i++] = 0x00;
869 buf[i++] = 0x00; 827 buf[i++] = 0x00;
870 buf[i++] = 0x00; 828 buf[i++] = 0x00;
@@ -889,10 +847,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
889 cam->nmodes = ARRAY_SIZE(vga_mode); 847 cam->nmodes = ARRAY_SIZE(vga_mode);
890 848
891 cam->bulk = 1; 849 cam->bulk = 1;
892 cam->bulk_size = BULK_TRANSFER_LEN;
893/* cam->bulk_nurbs = 2; fixme: if no setexpo sync */
894 850
895 sd->quality = QUALITY_DEF;
896 sd->gain = GAIN_DEF; 851 sd->gain = GAIN_DEF;
897 sd->expo = EXPO_DEF; 852 sd->expo = EXPO_DEF;
898 853
@@ -945,13 +900,10 @@ static int sd_init(struct gspca_dev *gspca_dev)
945 if (sd->sensor == SENSOR_MI0360) { 900 if (sd->sensor == SENSOR_MI0360) {
946 901
947 /* no sensor probe for icam tracer */ 902 /* no sensor probe for icam tracer */
948 if (gspca_dev->usb_buf[5] == 0xf6) { /* if CMOS */ 903 if (gspca_dev->usb_buf[5] == 0xf6) /* if CMOS */
949 sd->sensor = SENSOR_ICX098BQ; 904 sd->sensor = SENSOR_ICX098BQ;
950 gspca_dev->cam.cam_mode = &vga_mode[1]; 905 else
951 gspca_dev->cam.nmodes = 1; /* only 320x240 */
952 } else {
953 cmos_probe(gspca_dev); 906 cmos_probe(gspca_dev);
954 }
955 } 907 }
956 908
957 PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name); 909 PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name);
@@ -960,51 +912,24 @@ static int sd_init(struct gspca_dev *gspca_dev)
960 return gspca_dev->usb_err; 912 return gspca_dev->usb_err;
961} 913}
962 914
963/* special function to create the quantization tables of the JPEG header */
964static void sd_jpeg_set_qual(u8 *jpeg_hdr,
965 int quality)
966{
967 int i, sc1, sc2;
968
969 quality = quality_tb[quality]; /* convert to JPEG quality */
970/*
971 * approximative qualities for Y and U/V:
972 * quant = 0:94%/91% 1:91%/87% 2:82%/73% 3:69%/56%
973 * should have:
974 * quant = 0:94%/91% 1:91%/87.5% 2:81.5%/72% 3:69%/54.5%
975 */
976 sc1 = 200 - quality * 2;
977 quality = quality * 7 / 5 - 40; /* UV quality */
978 sc2 = 200 - quality * 2;
979 for (i = 0; i < 64; i++) {
980 jpeg_hdr[JPEG_QT0_OFFSET + i] =
981 (jpeg_head[JPEG_QT0_OFFSET + i] * sc1 + 50) / 100;
982 jpeg_hdr[JPEG_QT1_OFFSET + i] =
983 (jpeg_head[JPEG_QT1_OFFSET + i] * sc2 + 50) / 100;
984 }
985}
986
987/* send the start/stop commands to the webcam */ 915/* send the start/stop commands to the webcam */
988static void send_start(struct gspca_dev *gspca_dev) 916static void send_start(struct gspca_dev *gspca_dev)
989{ 917{
990 struct sd *sd = (struct sd *) gspca_dev; 918 struct sd *sd = (struct sd *) gspca_dev;
991 const struct cap_s *cap; 919 const struct cap_s *cap;
992 int mode, quality; 920 int mode;
993 921
994 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; 922 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
995 cap = &capconfig[sd->sensor][mode]; 923 cap = &capconfig[sd->sensor][mode];
996 quality = sd->quality; 924 reg_wb(gspca_dev, 0x0900 | SQ930_CTRL_CAP_START,
997 reg_wb(gspca_dev, (quality << 12) 925 0x0a00 | cap->cc_sizeid,
998 | 0x0a00 /* 900 for Bayer */
999 | SQ930_CTRL_CAP_START,
1000 0x0500 /* a00 for Bayer */
1001 | cap->cc_sizeid,
1002 cap->cc_bytes, 32); 926 cap->cc_bytes, 32);
1003}; 927}
928
1004static void send_stop(struct gspca_dev *gspca_dev) 929static void send_stop(struct gspca_dev *gspca_dev)
1005{ 930{
1006 reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0); 931 reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0);
1007}; 932}
1008 933
1009/* function called at start time before URB creation */ 934/* function called at start time before URB creation */
1010static int sd_isoc_init(struct gspca_dev *gspca_dev) 935static int sd_isoc_init(struct gspca_dev *gspca_dev)
@@ -1013,6 +938,7 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev)
1013 938
1014 gspca_dev->cam.bulk_nurbs = 1; /* there must be one URB only */ 939 gspca_dev->cam.bulk_nurbs = 1; /* there must be one URB only */
1015 sd->do_ctrl = 0; 940 sd->do_ctrl = 0;
941 gspca_dev->cam.bulk_size = gspca_dev->width * gspca_dev->height + 8;
1016 return 0; 942 return 0;
1017} 943}
1018 944
@@ -1022,11 +948,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
1022 struct sd *sd = (struct sd *) gspca_dev; 948 struct sd *sd = (struct sd *) gspca_dev;
1023 int mode; 949 int mode;
1024 950
1025 /* initialize the JPEG header */
1026 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
1027 0x21); /* JPEG 422 */
1028 sd_jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1029
1030 bridge_init(sd); 951 bridge_init(sd);
1031 global_init(sd, 0); 952 global_init(sd, 0);
1032 msleep(100); 953 msleep(100);
@@ -1071,7 +992,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
1071 ARRAY_SIZE(lz24bp_start_2), 992 ARRAY_SIZE(lz24bp_start_2),
1072 6); 993 6);
1073 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; 994 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1074 lz24bp_ppl(sd, mode == 2 ? 0x0564 : 0x0310); 995 lz24bp_ppl(sd, mode == 1 ? 0x0564 : 0x0310);
1075 msleep(10); 996 msleep(10);
1076 break; 997 break;
1077 case SENSOR_MI0360: 998 case SENSOR_MI0360:
@@ -1095,7 +1016,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
1095 /* 1st start */ 1016 /* 1st start */
1096 send_start(gspca_dev); 1017 send_start(gspca_dev);
1097 msleep(60); 1018 msleep(60);
1098 reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0x0000); 1019 send_stop(gspca_dev);
1099 1020
1100 i2c_write(sd, 1021 i2c_write(sd,
1101 mi0360_start_4, ARRAY_SIZE(mi0360_start_4)); 1022 mi0360_start_4, ARRAY_SIZE(mi0360_start_4));
@@ -1113,7 +1034,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
1113 ARRAY_SIZE(mt9v111_init_2)); 1034 ARRAY_SIZE(mt9v111_init_2));
1114 ucbus_write(gspca_dev, mt9v111_start_1, 1035 ucbus_write(gspca_dev, mt9v111_start_1,
1115 ARRAY_SIZE(mt9v111_start_1), 1036 ARRAY_SIZE(mt9v111_start_1),
1116 8); 1037 5);
1117 i2c_write(sd, mt9v111_init_3, 1038 i2c_write(sd, mt9v111_init_3,
1118 ARRAY_SIZE(mt9v111_init_3)); 1039 ARRAY_SIZE(mt9v111_init_3));
1119 i2c_write(sd, mt9v111_init_4, 1040 i2c_write(sd, mt9v111_init_4,
@@ -1125,8 +1046,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
1125out: 1046out:
1126 msleep(1000); 1047 msleep(1000);
1127 1048
1128 sd->eof_len = 0; /* init packet scan */
1129
1130 if (sd->sensor == SENSOR_MT9V111) 1049 if (sd->sensor == SENSOR_MT9V111)
1131 gpio_set(sd, SQ930_GPIO_DFL_LED, SQ930_GPIO_DFL_LED); 1050 gpio_set(sd, SQ930_GPIO_DFL_LED, SQ930_GPIO_DFL_LED);
1132 1051
@@ -1166,94 +1085,17 @@ static void sd_dq_callback(struct gspca_dev *gspca_dev)
1166 msleep(100); 1085 msleep(100);
1167} 1086}
1168 1087
1169/* move a packet adding 0x00 after 0xff */
1170static void add_packet(struct gspca_dev *gspca_dev,
1171 u8 *data,
1172 int len)
1173{
1174 int i;
1175
1176 i = 0;
1177 do {
1178 if (data[i] == 0xff) {
1179 gspca_frame_add(gspca_dev, INTER_PACKET,
1180 data, i + 1);
1181 len -= i;
1182 data += i;
1183 *data = 0x00;
1184 i = 0;
1185 }
1186 } while (++i < len);
1187 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1188}
1189
1190/* end a frame and start a new one */
1191static void eof_sof(struct gspca_dev *gspca_dev)
1192{
1193 struct sd *sd = (struct sd *) gspca_dev;
1194 static const u8 ffd9[] = {0xff, 0xd9};
1195
1196 /* if control set, stop bulk transfer */
1197 if (sd->do_ctrl
1198 && gspca_dev->last_packet_type == INTER_PACKET)
1199 gspca_dev->cam.bulk_nurbs = 0;
1200 gspca_frame_add(gspca_dev, LAST_PACKET,
1201 ffd9, 2);
1202 gspca_frame_add(gspca_dev, FIRST_PACKET,
1203 sd->jpeg_hdr, JPEG_HDR_SZ);
1204}
1205
1206static void sd_pkt_scan(struct gspca_dev *gspca_dev, 1088static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1207 u8 *data, /* isoc packet */ 1089 u8 *data, /* isoc packet */
1208 int len) /* iso packet length */ 1090 int len) /* iso packet length */
1209{ 1091{
1210 struct sd *sd = (struct sd *) gspca_dev; 1092 struct sd *sd = (struct sd *) gspca_dev;
1211 u8 *p; 1093
1212 int l; 1094 if (sd->do_ctrl)
1213 1095 gspca_dev->cam.bulk_nurbs = 0;
1214 len -= 8; /* ignore last 8 bytes (00 00 55 aa 55 aa 00 00) */ 1096 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
1215 1097 gspca_frame_add(gspca_dev, INTER_PACKET, data, len - 8);
1216 /* 1098 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1217 * the end/start of frame is indicated by
1218 * 0x00 * 16 - 0xab * 8
1219 * aligned on 8 bytes boundary
1220 */
1221 if (sd->eof_len != 0) { /* if 'abababab' in previous pkt */
1222 if (*((u32 *) data) == 0xabababab) {
1223 /*fixme: should remove previous 0000ababab*/
1224 eof_sof(gspca_dev);
1225 data += 4;
1226 len -= 4;
1227 }
1228 sd->eof_len = 0;
1229 }
1230 p = data;
1231 l = len;
1232 for (;;) {
1233 if (*((u32 *) p) == 0xabababab) {
1234 if (l < 8) { /* (may be 4 only) */
1235 sd->eof_len = 1;
1236 break;
1237 }
1238 if (*((u32 *) p + 1) == 0xabababab) {
1239 add_packet(gspca_dev, data, p - data - 16);
1240 /* remove previous zeros */
1241 eof_sof(gspca_dev);
1242 p += 8;
1243 l -= 8;
1244 if (l <= 0)
1245 return;
1246 len = l;
1247 data = p;
1248 continue;
1249 }
1250 }
1251 p += 4;
1252 l -= 4;
1253 if (l <= 0)
1254 break;
1255 }
1256 add_packet(gspca_dev, data, len);
1257} 1099}
1258 1100
1259static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) 1101static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
@@ -1291,45 +1133,6 @@ static int sd_getexpo(struct gspca_dev *gspca_dev, __s32 *val)
1291 return 0; 1133 return 0;
1292} 1134}
1293 1135
1294static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1295 struct v4l2_jpegcompression *jcomp)
1296{
1297 struct sd *sd = (struct sd *) gspca_dev;
1298 int quality;
1299
1300 if (jcomp->quality >= (QUAL_0 + QUAL_1) / 2)
1301 quality = 0;
1302 else if (jcomp->quality >= (QUAL_1 + QUAL_2) / 2)
1303 quality = 1;
1304 else if (jcomp->quality >= (QUAL_2 + QUAL_3) / 2)
1305 quality = 2;
1306 else
1307 quality = 3;
1308
1309 if (quality != sd->quality) {
1310 sd->quality = quality;
1311 if (gspca_dev->streaming) {
1312 send_stop(gspca_dev);
1313 sd_jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1314 msleep(70);
1315 send_start(gspca_dev);
1316 }
1317 }
1318 return gspca_dev->usb_err;
1319}
1320
1321static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1322 struct v4l2_jpegcompression *jcomp)
1323{
1324 struct sd *sd = (struct sd *) gspca_dev;
1325
1326 memset(jcomp, 0, sizeof *jcomp);
1327 jcomp->quality = quality_tb[sd->quality];
1328 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1329 | V4L2_JPEG_MARKER_DQT;
1330 return 0;
1331}
1332
1333/* sub-driver description */ 1136/* sub-driver description */
1334static const struct sd_desc sd_desc = { 1137static const struct sd_desc sd_desc = {
1335 .name = MODULE_NAME, 1138 .name = MODULE_NAME,
@@ -1342,8 +1145,6 @@ static const struct sd_desc sd_desc = {
1342 .stopN = sd_stopN, 1145 .stopN = sd_stopN,
1343 .pkt_scan = sd_pkt_scan, 1146 .pkt_scan = sd_pkt_scan,
1344 .dq_callback = sd_dq_callback, 1147 .dq_callback = sd_dq_callback,
1345 .get_jcomp = sd_get_jcomp,
1346 .set_jcomp = sd_set_jcomp,
1347}; 1148};
1348 1149
1349/* Table of supported USB devices */ 1150/* Table of supported USB devices */
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c
index 2a0f12d55e4..3b3b983f2b9 100644
--- a/drivers/media/video/gspca/t613.c
+++ b/drivers/media/video/gspca/t613.c
@@ -55,12 +55,12 @@ struct sd {
55 u8 effect; 55 u8 effect;
56 56
57 u8 sensor; 57 u8 sensor;
58enum { 58};
59enum sensors {
59 SENSOR_OM6802, 60 SENSOR_OM6802,
60 SENSOR_OTHER, 61 SENSOR_OTHER,
61 SENSOR_TAS5130A, 62 SENSOR_TAS5130A,
62 SENSOR_LT168G, /* must verify if this is the actual model */ 63 SENSOR_LT168G, /* must verify if this is the actual model */
63} sensors;
64}; 64};
65 65
66/* V4L2 controls supported by the driver */ 66/* V4L2 controls supported by the driver */
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c
index 031266a4081..b16fd47e8ce 100644
--- a/drivers/media/video/gspca/vc032x.c
+++ b/drivers/media/video/gspca/vc032x.c
@@ -39,6 +39,10 @@ struct sd {
39 u8 vflip; 39 u8 vflip;
40 u8 lightfreq; 40 u8 lightfreq;
41 s8 sharpness; 41 s8 sharpness;
42 u16 exposure;
43 u8 gain;
44 u8 autogain;
45 u8 backlight;
42 46
43 u8 image_offset; 47 u8 image_offset;
44 48
@@ -77,6 +81,14 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
77static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); 81static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
78static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); 82static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
79static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); 83static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
84static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
85static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
86static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
87static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
88static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
89static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
90static int sd_setbacklight(struct gspca_dev *gspca_dev, __s32 val);
91static int sd_getbacklight(struct gspca_dev *gspca_dev, __s32 *val);
80 92
81static const struct ctrl sd_ctrls[] = { 93static const struct ctrl sd_ctrls[] = {
82#define BRIGHTNESS_IDX 0 94#define BRIGHTNESS_IDX 0
@@ -185,6 +197,66 @@ static const struct ctrl sd_ctrls[] = {
185 .set = sd_setsharpness, 197 .set = sd_setsharpness,
186 .get = sd_getsharpness, 198 .get = sd_getsharpness,
187 }, 199 },
200#define GAIN_IDX 7
201 {
202 {
203 .id = V4L2_CID_GAIN,
204 .type = V4L2_CTRL_TYPE_INTEGER,
205 .name = "Gain",
206 .minimum = 0,
207 .maximum = 78,
208 .step = 1,
209#define GAIN_DEF 0
210 .default_value = GAIN_DEF,
211 },
212 .set = sd_setgain,
213 .get = sd_getgain,
214 },
215#define EXPOSURE_IDX 8
216 {
217 {
218 .id = V4L2_CID_EXPOSURE,
219 .type = V4L2_CTRL_TYPE_INTEGER,
220 .name = "Exposure",
221#define EXPOSURE_DEF 450
222 .minimum = 0,
223 .maximum = 4095,
224 .step = 1,
225 .default_value = EXPOSURE_DEF,
226 },
227 .set = sd_setexposure,
228 .get = sd_getexposure,
229 },
230#define AUTOGAIN_IDX 9
231 {
232 {
233 .id = V4L2_CID_AUTOGAIN,
234 .type = V4L2_CTRL_TYPE_BOOLEAN,
235 .name = "Automatic Gain and Exposure",
236 .minimum = 0,
237 .maximum = 1,
238 .step = 1,
239#define AUTOGAIN_DEF 1
240 .default_value = AUTOGAIN_DEF,
241 },
242 .set = sd_setautogain,
243 .get = sd_getautogain,
244 },
245#define BACKLIGHT_IDX 10
246 {
247 {
248 .id = V4L2_CID_BACKLIGHT_COMPENSATION,
249 .type = V4L2_CTRL_TYPE_BOOLEAN,
250 .name = "Backlight Compensation",
251 .minimum = 0,
252 .maximum = 15,
253 .step = 1,
254#define BACKLIGHT_DEF 15
255 .default_value = BACKLIGHT_DEF,
256 },
257 .set = sd_setbacklight,
258 .get = sd_getbacklight,
259 },
188}; 260};
189 261
190/* table of the disabled controls */ 262/* table of the disabled controls */
@@ -192,33 +264,51 @@ static u32 ctrl_dis[] = {
192/* SENSOR_HV7131R 0 */ 264/* SENSOR_HV7131R 0 */
193 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) 265 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
194 | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) 266 | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
195 | (1 << SHARPNESS_IDX), 267 | (1 << SHARPNESS_IDX)
268 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
269 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
196/* SENSOR_MI0360 1 */ 270/* SENSOR_MI0360 1 */
197 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) 271 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
198 | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) 272 | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
199 | (1 << SHARPNESS_IDX), 273 | (1 << SHARPNESS_IDX)
274 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
275 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
200/* SENSOR_MI1310_SOC 2 */ 276/* SENSOR_MI1310_SOC 2 */
201 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) 277 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
202 | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX), 278 | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
279 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
280 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
203/* SENSOR_MI1320 3 */ 281/* SENSOR_MI1320 3 */
204 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) 282 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
205 | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX), 283 | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
284 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
285 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
206/* SENSOR_MI1320_SOC 4 */ 286/* SENSOR_MI1320_SOC 4 */
207 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) 287 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
208 | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX), 288 | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
289 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
290 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
209/* SENSOR_OV7660 5 */ 291/* SENSOR_OV7660 5 */
210 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) 292 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
211 | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX), 293 | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
294 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
295 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
212/* SENSOR_OV7670 6 */ 296/* SENSOR_OV7670 6 */
213 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) 297 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
214 | (1 << SHARPNESS_IDX), 298 | (1 << SHARPNESS_IDX)
299 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
300 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
215/* SENSOR_PO1200 7 */ 301/* SENSOR_PO1200 7 */
216 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) 302 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
217 | (1 << LIGHTFREQ_IDX), 303 | (1 << LIGHTFREQ_IDX)
304 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
305 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
218/* SENSOR_PO3130NC 8 */ 306/* SENSOR_PO3130NC 8 */
219 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) 307 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
220 | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) 308 | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
221 | (1 << SHARPNESS_IDX), 309 | (1 << SHARPNESS_IDX)
310 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
311 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
222/* SENSOR_POxxxx 9 */ 312/* SENSOR_POxxxx 9 */
223 (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX), 313 (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX),
224}; 314};
@@ -2825,7 +2915,9 @@ static const u8 poxxxx_init_common[][4] = {
2825 {0x00, 0x1e, 0xc6, 0xaa}, 2915 {0x00, 0x1e, 0xc6, 0xaa},
2826 {0x00, 0x00, 0x40, 0xdd}, 2916 {0x00, 0x00, 0x40, 0xdd},
2827 {0x00, 0x1d, 0x05, 0xaa}, 2917 {0x00, 0x1d, 0x05, 0xaa},
2828 2918 {}
2919};
2920static const u8 poxxxx_gamma[][4] = {
2829 {0x00, 0xd6, 0x22, 0xaa}, /* gamma 0 */ 2921 {0x00, 0xd6, 0x22, 0xaa}, /* gamma 0 */
2830 {0x00, 0x73, 0x00, 0xaa}, 2922 {0x00, 0x73, 0x00, 0xaa},
2831 {0x00, 0x74, 0x0a, 0xaa}, 2923 {0x00, 0x74, 0x0a, 0xaa},
@@ -2867,19 +2959,9 @@ static const u8 poxxxx_init_common[][4] = {
2867 {0x00, 0x7c, 0xba, 0xaa}, 2959 {0x00, 0x7c, 0xba, 0xaa},
2868 {0x00, 0x7d, 0xd4, 0xaa}, 2960 {0x00, 0x7d, 0xd4, 0xaa},
2869 {0x00, 0x7e, 0xea, 0xaa}, 2961 {0x00, 0x7e, 0xea, 0xaa},
2870 2962 {}
2871 {0x00, 0xaa, 0xff, 0xaa}, /* back light comp */ 2963};
2872 {0x00, 0xc4, 0x03, 0xaa}, 2964static const u8 poxxxx_init_start_3[][4] = {
2873 {0x00, 0xc5, 0x19, 0xaa},
2874 {0x00, 0xc6, 0x03, 0xaa},
2875 {0x00, 0xc7, 0x91, 0xaa},
2876 {0x00, 0xc8, 0x01, 0xaa},
2877 {0x00, 0xc9, 0xdd, 0xaa},
2878 {0x00, 0xca, 0x02, 0xaa},
2879 {0x00, 0xcb, 0x37, 0xaa},
2880
2881/* read d1 */
2882 {0x00, 0xd1, 0x3c, 0xaa},
2883 {0x00, 0xb8, 0x28, 0xaa}, 2965 {0x00, 0xb8, 0x28, 0xaa},
2884 {0x00, 0xb9, 0x1e, 0xaa}, 2966 {0x00, 0xb9, 0x1e, 0xaa},
2885 {0x00, 0xb6, 0x14, 0xaa}, 2967 {0x00, 0xb6, 0x14, 0xaa},
@@ -2959,9 +3041,6 @@ static const u8 poxxxx_init_end_1[][4] = {
2959 {0x00, 0xb3, 0x08, 0xaa}, 3041 {0x00, 0xb3, 0x08, 0xaa},
2960 {0x00, 0xb4, 0x0b, 0xaa}, 3042 {0x00, 0xb4, 0x0b, 0xaa},
2961 {0x00, 0xb5, 0x0d, 0xaa}, 3043 {0x00, 0xb5, 0x0d, 0xaa},
2962 {0x00, 0x59, 0x7e, 0xaa}, /* sharpness */
2963 {0x00, 0x16, 0x00, 0xaa}, /* white balance */
2964 {0x00, 0x18, 0x00, 0xaa},
2965 {} 3044 {}
2966}; 3045};
2967static const u8 poxxxx_init_end_2[][4] = { 3046static const u8 poxxxx_init_end_2[][4] = {
@@ -3312,6 +3391,33 @@ static int sd_config(struct gspca_dev *gspca_dev,
3312 const struct usb_device_id *id) 3391 const struct usb_device_id *id)
3313{ 3392{
3314 struct sd *sd = (struct sd *) gspca_dev; 3393 struct sd *sd = (struct sd *) gspca_dev;
3394
3395 sd->bridge = id->driver_info >> 8;
3396 sd->flags = id->driver_info & 0xff;
3397
3398 if (id->idVendor == 0x046d &&
3399 (id->idProduct == 0x0892 || id->idProduct == 0x0896))
3400 sd->sensor = SENSOR_POxxxx; /* no probe */
3401
3402 sd->brightness = BRIGHTNESS_DEF;
3403 sd->contrast = CONTRAST_DEF;
3404 sd->colors = COLOR_DEF;
3405 sd->hflip = HFLIP_DEF;
3406 sd->vflip = VFLIP_DEF;
3407 sd->lightfreq = FREQ_DEF;
3408 sd->sharpness = SHARPNESS_DEF;
3409 sd->gain = GAIN_DEF;
3410 sd->exposure = EXPOSURE_DEF;
3411 sd->autogain = AUTOGAIN_DEF;
3412 sd->backlight = BACKLIGHT_DEF;
3413
3414 return 0;
3415}
3416
3417/* this function is called at probe and resume time */
3418static int sd_init(struct gspca_dev *gspca_dev)
3419{
3420 struct sd *sd = (struct sd *) gspca_dev;
3315 struct cam *cam; 3421 struct cam *cam;
3316 int sensor; 3422 int sensor;
3317 static u8 npkt[] = { /* number of packets per ISOC message */ 3423 static u8 npkt[] = { /* number of packets per ISOC message */
@@ -3327,14 +3433,11 @@ static int sd_config(struct gspca_dev *gspca_dev,
3327 128, /* POxxxx 9 */ 3433 128, /* POxxxx 9 */
3328 }; 3434 };
3329 3435
3330 cam = &gspca_dev->cam; 3436 if (sd->sensor != SENSOR_POxxxx)
3331 sd->bridge = id->driver_info >> 8;
3332 sd->flags = id->driver_info & 0xff;
3333 if (id->idVendor == 0x046d &&
3334 (id->idProduct == 0x0892 || id->idProduct == 0x0896))
3335 sensor = SENSOR_POxxxx;
3336 else
3337 sensor = vc032x_probe_sensor(gspca_dev); 3437 sensor = vc032x_probe_sensor(gspca_dev);
3438 else
3439 sensor = sd->sensor;
3440
3338 switch (sensor) { 3441 switch (sensor) {
3339 case -1: 3442 case -1:
3340 PDEBUG(D_PROBE, "Unknown sensor..."); 3443 PDEBUG(D_PROBE, "Unknown sensor...");
@@ -3373,6 +3476,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
3373 } 3476 }
3374 sd->sensor = sensor; 3477 sd->sensor = sensor;
3375 3478
3479 cam = &gspca_dev->cam;
3376 if (sd->bridge == BRIDGE_VC0321) { 3480 if (sd->bridge == BRIDGE_VC0321) {
3377 cam->cam_mode = vc0321_mode; 3481 cam->cam_mode = vc0321_mode;
3378 cam->nmodes = ARRAY_SIZE(vc0321_mode); 3482 cam->nmodes = ARRAY_SIZE(vc0321_mode);
@@ -3401,28 +3505,11 @@ static int sd_config(struct gspca_dev *gspca_dev,
3401 } 3505 }
3402 } 3506 }
3403 cam->npkt = npkt[sd->sensor]; 3507 cam->npkt = npkt[sd->sensor];
3404
3405 sd->brightness = BRIGHTNESS_DEF;
3406 sd->contrast = CONTRAST_DEF;
3407 sd->colors = COLOR_DEF;
3408 sd->hflip = HFLIP_DEF;
3409 sd->vflip = VFLIP_DEF;
3410 sd->lightfreq = FREQ_DEF;
3411 sd->sharpness = SHARPNESS_DEF;
3412
3413 gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; 3508 gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
3414 3509
3415 if (sd->sensor == SENSOR_OV7670) 3510 if (sd->sensor == SENSOR_OV7670)
3416 sd->flags |= FL_HFLIP | FL_VFLIP; 3511 sd->flags |= FL_HFLIP | FL_VFLIP;
3417 3512
3418 return 0;
3419}
3420
3421/* this function is called at probe and resume time */
3422static int sd_init(struct gspca_dev *gspca_dev)
3423{
3424 struct sd *sd = (struct sd *) gspca_dev;
3425
3426 if (sd->bridge == BRIDGE_VC0321) { 3513 if (sd->bridge == BRIDGE_VC0321) {
3427 reg_r(gspca_dev, 0x8a, 0, 3); 3514 reg_r(gspca_dev, 0x8a, 0, 3);
3428 reg_w(gspca_dev, 0x87, 0x00, 0x0f0f); 3515 reg_w(gspca_dev, 0x87, 0x00, 0x0f0f);
@@ -3433,8 +3520,8 @@ static int sd_init(struct gspca_dev *gspca_dev)
3433 if (gspca_dev->usb_buf[0] != 0) { 3520 if (gspca_dev->usb_buf[0] != 0) {
3434 reg_w(gspca_dev, 0xa0, 0x26, 0xb300); 3521 reg_w(gspca_dev, 0xa0, 0x26, 0xb300);
3435 reg_w(gspca_dev, 0xa0, 0x04, 0xb300); 3522 reg_w(gspca_dev, 0xa0, 0x04, 0xb300);
3436 reg_w(gspca_dev, 0xa0, 0x00, 0xb300);
3437 } 3523 }
3524 reg_w(gspca_dev, 0xa0, 0x00, 0xb300);
3438 } 3525 }
3439 } 3526 }
3440 return gspca_dev->usb_err; 3527 return gspca_dev->usb_err;
@@ -3551,6 +3638,82 @@ static void setsharpness(struct gspca_dev *gspca_dev)
3551 break; 3638 break;
3552 } 3639 }
3553} 3640}
3641static void setgain(struct gspca_dev *gspca_dev)
3642{
3643 struct sd *sd = (struct sd *) gspca_dev;
3644
3645 if (gspca_dev->ctrl_dis & (1 << GAIN_IDX))
3646 return;
3647 i2c_write(gspca_dev, 0x15, &sd->gain, 1);
3648}
3649
3650static void setexposure(struct gspca_dev *gspca_dev)
3651{
3652 struct sd *sd = (struct sd *) gspca_dev;
3653 u8 data;
3654
3655 if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX))
3656 return;
3657 data = sd->exposure >> 8;
3658 i2c_write(gspca_dev, 0x1a, &data, 1);
3659 data = sd->exposure;
3660 i2c_write(gspca_dev, 0x1b, &data, 1);
3661}
3662
3663static void setautogain(struct gspca_dev *gspca_dev)
3664{
3665 struct sd *sd = (struct sd *) gspca_dev;
3666 static const u8 data[2] = {0x28, 0x3c};
3667
3668 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
3669 return;
3670 i2c_write(gspca_dev, 0xd1, &data[sd->autogain], 1);
3671}
3672
3673static void setgamma(struct gspca_dev *gspca_dev)
3674{
3675/*fixme:to do */
3676 usb_exchange(gspca_dev, poxxxx_gamma);
3677}
3678
3679static void setbacklight(struct gspca_dev *gspca_dev)
3680{
3681 struct sd *sd = (struct sd *) gspca_dev;
3682 u16 v;
3683 u8 data;
3684
3685 data = (sd->backlight << 4) | 0x0f;
3686 i2c_write(gspca_dev, 0xaa, &data, 1);
3687 v = 613 + 12 * sd->backlight;
3688 data = v >> 8;
3689 i2c_write(gspca_dev, 0xc4, &data, 1);
3690 data = v;
3691 i2c_write(gspca_dev, 0xc5, &data, 1);
3692 v = 1093 - 12 * sd->backlight;
3693 data = v >> 8;
3694 i2c_write(gspca_dev, 0xc6, &data, 1);
3695 data = v;
3696 i2c_write(gspca_dev, 0xc7, &data, 1);
3697 v = 342 + 9 * sd->backlight;
3698 data = v >> 8;
3699 i2c_write(gspca_dev, 0xc8, &data, 1);
3700 data = v;
3701 i2c_write(gspca_dev, 0xc9, &data, 1);
3702 v = 702 - 9 * sd->backlight;
3703 data = v >> 8;
3704 i2c_write(gspca_dev, 0xca, &data, 1);
3705 data = v;
3706 i2c_write(gspca_dev, 0xcb, &data, 1);
3707}
3708
3709static void setwb(struct gspca_dev *gspca_dev)
3710{
3711/*fixme:to do - valid when reg d1 = 0x1c - (reg16 + reg15 = 0xa3)*/
3712 static const u8 data[2] = {0x00, 0x00};
3713
3714 i2c_write(gspca_dev, 0x16, &data[0], 1);
3715 i2c_write(gspca_dev, 0x18, &data[1], 1);
3716}
3554 3717
3555static int sd_start(struct gspca_dev *gspca_dev) 3718static int sd_start(struct gspca_dev *gspca_dev)
3556{ 3719{
@@ -3662,6 +3825,16 @@ static int sd_start(struct gspca_dev *gspca_dev)
3662 default: 3825 default:
3663/* case SENSOR_POxxxx: */ 3826/* case SENSOR_POxxxx: */
3664 usb_exchange(gspca_dev, poxxxx_init_common); 3827 usb_exchange(gspca_dev, poxxxx_init_common);
3828 setgamma(gspca_dev);
3829 setbacklight(gspca_dev);
3830 setbrightness(gspca_dev);
3831 setcontrast(gspca_dev);
3832 setcolors(gspca_dev);
3833 setsharpness(gspca_dev);
3834 setautogain(gspca_dev);
3835 setexposure(gspca_dev);
3836 setgain(gspca_dev);
3837 usb_exchange(gspca_dev, poxxxx_init_start_3);
3665 if (mode) 3838 if (mode)
3666 init = poxxxx_initQVGA; 3839 init = poxxxx_initQVGA;
3667 else 3840 else
@@ -3693,7 +3866,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
3693 break; 3866 break;
3694 } 3867 }
3695 msleep(100); 3868 msleep(100);
3696 setsharpness(gspca_dev);
3697 sethvflip(gspca_dev); 3869 sethvflip(gspca_dev);
3698 setlightfreq(gspca_dev); 3870 setlightfreq(gspca_dev);
3699 } 3871 }
@@ -3704,14 +3876,10 @@ static int sd_start(struct gspca_dev *gspca_dev)
3704 reg_w(gspca_dev, 0xa0, 0x0000, 0xbfff); 3876 reg_w(gspca_dev, 0xa0, 0x0000, 0xbfff);
3705 break; 3877 break;
3706 case SENSOR_POxxxx: 3878 case SENSOR_POxxxx:
3707 setcolors(gspca_dev);
3708 setbrightness(gspca_dev);
3709 setcontrast(gspca_dev);
3710
3711 /* led on */
3712 msleep(80);
3713 reg_w(gspca_dev, 0x89, 0xffff, 0xfdff);
3714 usb_exchange(gspca_dev, poxxxx_init_end_2); 3879 usb_exchange(gspca_dev, poxxxx_init_end_2);
3880 setwb(gspca_dev);
3881 msleep(80); /* led on */
3882 reg_w(gspca_dev, 0x89, 0xffff, 0xfdff);
3715 break; 3883 break;
3716 } 3884 }
3717 return gspca_dev->usb_err; 3885 return gspca_dev->usb_err;
@@ -3911,6 +4079,80 @@ static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
3911 return 0; 4079 return 0;
3912} 4080}
3913 4081
4082static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
4083{
4084 struct sd *sd = (struct sd *) gspca_dev;
4085
4086 sd->gain = val;
4087 if (gspca_dev->streaming)
4088 setgain(gspca_dev);
4089 return gspca_dev->usb_err;
4090}
4091
4092static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
4093{
4094 struct sd *sd = (struct sd *) gspca_dev;
4095
4096 *val = sd->gain;
4097 return 0;
4098}
4099
4100static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
4101{
4102 struct sd *sd = (struct sd *) gspca_dev;
4103
4104 sd->exposure = val;
4105 if (gspca_dev->streaming)
4106 setexposure(gspca_dev);
4107 return gspca_dev->usb_err;
4108}
4109
4110static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
4111{
4112 struct sd *sd = (struct sd *) gspca_dev;
4113
4114 *val = sd->exposure;
4115 return 0;
4116}
4117
4118static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
4119{
4120 struct sd *sd = (struct sd *) gspca_dev;
4121
4122 sd->autogain = val;
4123 if (gspca_dev->streaming)
4124 setautogain(gspca_dev);
4125
4126 return gspca_dev->usb_err;
4127}
4128
4129static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
4130{
4131 struct sd *sd = (struct sd *) gspca_dev;
4132
4133 *val = sd->autogain;
4134 return 0;
4135}
4136
4137static int sd_setbacklight(struct gspca_dev *gspca_dev, __s32 val)
4138{
4139 struct sd *sd = (struct sd *) gspca_dev;
4140
4141 sd->backlight = val;
4142 if (gspca_dev->streaming)
4143 setbacklight(gspca_dev);
4144
4145 return gspca_dev->usb_err;
4146}
4147
4148static int sd_getbacklight(struct gspca_dev *gspca_dev, __s32 *val)
4149{
4150 struct sd *sd = (struct sd *) gspca_dev;
4151
4152 *val = sd->backlight;
4153 return 0;
4154}
4155
3914static int sd_querymenu(struct gspca_dev *gspca_dev, 4156static int sd_querymenu(struct gspca_dev *gspca_dev,
3915 struct v4l2_querymenu *menu) 4157 struct v4l2_querymenu *menu)
3916{ 4158{
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
index 4473f0fb8b7..0666038a51b 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -21,7 +21,9 @@
21 21
22#define MODULE_NAME "zc3xx" 22#define MODULE_NAME "zc3xx"
23 23
24#ifdef CONFIG_INPUT
24#include <linux/input.h> 25#include <linux/input.h>
26#endif
25#include "gspca.h" 27#include "gspca.h"
26#include "jpeg.h" 28#include "jpeg.h"
27 29
@@ -50,33 +52,38 @@ struct sd {
50#define QUALITY_MAX 80 52#define QUALITY_MAX 80
51#define QUALITY_DEF 70 53#define QUALITY_DEF 70
52 54
55 u8 bridge;
53 u8 sensor; /* Type of image sensor chip */ 56 u8 sensor; /* Type of image sensor chip */
54/* !! values used in different tables */ 57 u16 chip_revision;
55#define SENSOR_ADCM2700 0
56#define SENSOR_CS2102 1
57#define SENSOR_CS2102K 2
58#define SENSOR_GC0305 3
59#define SENSOR_HDCS2020b 4
60#define SENSOR_HV7131B 5
61#define SENSOR_HV7131C 6
62#define SENSOR_ICM105A 7
63#define SENSOR_MC501CB 8
64#define SENSOR_MI0360SOC 9
65#define SENSOR_OV7620 10
66/*#define SENSOR_OV7648 10 - same values */
67#define SENSOR_OV7630C 11
68#define SENSOR_PAS106 12
69#define SENSOR_PAS202B 13
70#define SENSOR_PB0330 14 /* (MI0360) */
71#define SENSOR_PO2030 15
72#define SENSOR_TAS5130CK 16
73#define SENSOR_TAS5130CXX 17
74#define SENSOR_TAS5130C_VF0250 18
75#define SENSOR_MAX 19
76 unsigned short chip_revision;
77 58
78 u8 jpeg_hdr[JPEG_HDR_SZ]; 59 u8 jpeg_hdr[JPEG_HDR_SZ];
79}; 60};
61enum bridges {
62 BRIDGE_ZC301,
63 BRIDGE_ZC303,
64};
65enum sensors {
66 SENSOR_ADCM2700,
67 SENSOR_CS2102,
68 SENSOR_CS2102K,
69 SENSOR_GC0305,
70 SENSOR_HDCS2020b,
71 SENSOR_HV7131B,
72 SENSOR_HV7131R,
73 SENSOR_ICM105A,
74 SENSOR_MC501CB,
75 SENSOR_MT9V111_1, /* (mi360soc) zc301 */
76 SENSOR_MT9V111_3, /* (mi360soc) zc303 */
77 SENSOR_OV7620, /* OV7648 - same values */
78 SENSOR_OV7630C,
79 SENSOR_PAS106,
80 SENSOR_PAS202B,
81 SENSOR_PB0330,
82 SENSOR_PO2030,
83 SENSOR_TAS5130C,
84 SENSOR_TAS5130C_VF0250,
85 SENSOR_MAX
86};
80 87
81/* V4L2 controls supported by the driver */ 88/* V4L2 controls supported by the driver */
82static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); 89static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
@@ -2074,6 +2081,7 @@ static const struct usb_action hv7131b_NoFlikerScale[] = { /* 320x240 */
2074 {} 2081 {}
2075}; 2082};
2076 2083
2084/* from lPEPI264v.inf (hv7131b!) */
2077static const struct usb_action hv7131r_InitialScale[] = { 2085static const struct usb_action hv7131r_InitialScale[] = {
2078 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, 2086 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2079 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, 2087 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
@@ -2081,8 +2089,8 @@ static const struct usb_action hv7131r_InitialScale[] = {
2081 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, 2089 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2082 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, 2090 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
2083 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, 2091 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2084 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2085 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, 2092 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
2093 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2086 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, 2094 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2087 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, 2095 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2088 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, 2096 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
@@ -2095,6 +2103,8 @@ static const struct usb_action hv7131r_InitialScale[] = {
2095 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, 2103 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
2096 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, 2104 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
2097 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, 2105 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
2106 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
2107 {0xdd, 0x00, 0x0200},
2098 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, 2108 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2099 {0xaa, 0x01, 0x000c}, 2109 {0xaa, 0x01, 0x000c},
2100 {0xaa, 0x11, 0x0000}, 2110 {0xaa, 0x11, 0x0000},
@@ -2103,10 +2113,10 @@ static const struct usb_action hv7131r_InitialScale[] = {
2103 {0xaa, 0x15, 0x00e8}, 2113 {0xaa, 0x15, 0x00e8},
2104 {0xaa, 0x16, 0x0002}, 2114 {0xaa, 0x16, 0x0002},
2105 {0xaa, 0x17, 0x0088}, 2115 {0xaa, 0x17, 0x0088},
2106 2116 {0xaa, 0x30, 0x000b},
2107 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, 2117 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2108 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, 2118 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2109 {0xa0, 0x89, ZC3XX_R18D_YTARGET}, 2119 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
2110 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, 2120 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
2111 {0xa0, 0x00, 0x01ad}, 2121 {0xa0, 0x00, 0x01ad},
2112 {0xa0, 0xc0, 0x019b}, 2122 {0xa0, 0xc0, 0x019b},
@@ -2116,96 +2126,44 @@ static const struct usb_action hv7131r_InitialScale[] = {
2116 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, 2126 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2117 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, 2127 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2118 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, 2128 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2119 {0xa1, 0x01, 0x0002},
2120 {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT},
2121 {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND},
2122 {0xa1, 0x01, 0x0091},
2123 {0xa1, 0x01, 0x0095},
2124 {0xa1, 0x01, 0x0096},
2125
2126 {0xa1, 0x01, 0x0008},
2127 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2128 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2129 {0xa1, 0x01, 0x01c8},
2130 {0xa1, 0x01, 0x01c9},
2131 {0xa1, 0x01, 0x01ca},
2132 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2133
2134 {0xa0, 0x60, ZC3XX_R10A_RGB00}, /* matrix */
2135 {0xa0, 0xf0, ZC3XX_R10B_RGB01},
2136 {0xa0, 0xf0, ZC3XX_R10C_RGB02},
2137 {0xa0, 0xf0, ZC3XX_R10D_RGB10},
2138 {0xa0, 0x60, ZC3XX_R10E_RGB11},
2139 {0xa0, 0xf0, ZC3XX_R10F_RGB12},
2140 {0xa0, 0xf0, ZC3XX_R110_RGB20},
2141 {0xa0, 0xf0, ZC3XX_R111_RGB21},
2142 {0xa0, 0x60, ZC3XX_R112_RGB22},
2143 {0xa1, 0x01, 0x0180},
2144 {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
2145 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2146 {0xaa, 0x25, 0x0007},
2147 {0xaa, 0x26, 0x0053},
2148 {0xaa, 0x27, 0x0000},
2149
2150 {0xa0, 0x10, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 2f */
2151 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 9b */
2152 {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 80 */
2153 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
2154 {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID},
2155 {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW},
2156 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
2157 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2158 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
2159 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2160 {0xa0, 0x13, ZC3XX_R1AA_DIGITALGAINSTEP},
2161 {0xa1, 0x01, 0x001d},
2162 {0xa1, 0x01, 0x001e},
2163 {0xa1, 0x01, 0x001f},
2164 {0xa1, 0x01, 0x0020},
2165 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
2166 {0xa1, 0x01, 0x0180},
2167 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2168 {} 2129 {}
2169}; 2130};
2170
2171static const struct usb_action hv7131r_Initial[] = { 2131static const struct usb_action hv7131r_Initial[] = {
2172 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, 2132 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2173 2133 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
2174 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* diff */
2175 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, 2134 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
2176 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, 2135 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2177 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, 2136 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
2178 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, 2137 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2179
2180 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2181 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, 2138 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
2182 2139 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2183 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, 2140 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2184 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, 2141 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2185 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, 2142 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2186 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 1e0 */ 2143 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2187 2144
2188 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, 2145 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
2189 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, 2146 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
2190 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, 2147 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2191 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, 2148 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
2192 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, 2149 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2193 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, 2150 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
2194 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, 2151 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
2195 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, 2152 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
2153 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
2154 {0xdd, 0x00, 0x0200},
2196 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, 2155 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2197 {0xaa, 0x01, 0x000c}, 2156 {0xaa, 0x01, 0x000c},
2198 {0xaa, 0x11, 0x0000}, 2157 {0xaa, 0x11, 0x0000},
2199 {0xaa, 0x13, 0x0000}, 2158 {0xaa, 0x13, 0x0000},
2200 {0xaa, 0x14, 0x0001}, 2159 {0xaa, 0x14, 0x0001},
2201 {0xaa, 0x15, 0x00e8}, 2160 {0xaa, 0x15, 0x00e6},
2202 {0xaa, 0x16, 0x0002}, 2161 {0xaa, 0x16, 0x0002},
2203 {0xaa, 0x17, 0x0088}, 2162 {0xaa, 0x17, 0x0086},
2204 2163 {0xaa, 0x30, 0x000b},
2205 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00 */ 2164 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2206
2207 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, 2165 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2208 {0xa0, 0x89, ZC3XX_R18D_YTARGET}, 2166 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
2209 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, 2167 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
2210 {0xa0, 0x00, 0x01ad}, 2168 {0xa0, 0x00, 0x01ad},
2211 {0xa0, 0xc0, 0x019b}, 2169 {0xa0, 0xc0, 0x019b},
@@ -2215,58 +2173,114 @@ static const struct usb_action hv7131r_Initial[] = {
2215 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, 2173 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2216 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, 2174 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2217 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, 2175 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2218 {0xa1, 0x01, 0x0002}, 2176 {}
2219 {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT}, 2177};
2220 /* read the i2c chips ident */ 2178static const struct usb_action hv7131r_50HZ[] = {
2221 {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND},
2222 {0xa1, 0x01, 0x0091},
2223 {0xa1, 0x01, 0x0095},
2224 {0xa1, 0x01, 0x0096},
2225
2226 {0xa1, 0x01, 0x0008},
2227 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2228 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2229 {0xa1, 0x01, 0x01c8},
2230 {0xa1, 0x01, 0x01c9},
2231 {0xa1, 0x01, 0x01ca},
2232 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2233
2234 {0xa0, 0x60, ZC3XX_R10A_RGB00}, /* matrix */
2235 {0xa0, 0xf0, ZC3XX_R10B_RGB01},
2236 {0xa0, 0xf0, ZC3XX_R10C_RGB02},
2237 {0xa0, 0xf0, ZC3XX_R10D_RGB10},
2238 {0xa0, 0x60, ZC3XX_R10E_RGB11},
2239 {0xa0, 0xf0, ZC3XX_R10F_RGB12},
2240 {0xa0, 0xf0, ZC3XX_R110_RGB20},
2241 {0xa0, 0xf0, ZC3XX_R111_RGB21},
2242 {0xa0, 0x60, ZC3XX_R112_RGB22},
2243 {0xa1, 0x01, 0x0180},
2244 {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
2245 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, 2179 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2246 {0xaa, 0x25, 0x0007}, 2180 {0xa0, 0x06, ZC3XX_R190_EXPOSURELIMITHIGH},
2247 {0xaa, 0x26, 0x0053}, 2181 {0xa0, 0x68, ZC3XX_R191_EXPOSURELIMITMID},
2248 {0xaa, 0x27, 0x0000}, 2182 {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW},
2249 2183 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2250 {0xa0, 0x10, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 2f */ 2184 {0xa0, 0xea, ZC3XX_R196_ANTIFLICKERMID},
2251 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 9b */ 2185 {0xa0, 0x60, ZC3XX_R197_ANTIFLICKERLOW},
2252 {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 80 */ 2186 {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
2253 2187 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2188 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2189 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
2190 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2191 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2192 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2193 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2194 {}
2195};
2196static const struct usb_action hv7131r_50HZScale[] = {
2197 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2198 {0xa0, 0x0c, ZC3XX_R190_EXPOSURELIMITHIGH},
2199 {0xa0, 0xd1, ZC3XX_R191_EXPOSURELIMITMID},
2200 {0xa0, 0x40, ZC3XX_R192_EXPOSURELIMITLOW},
2254 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH}, 2201 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
2255 {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID}, 2202 {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID},
2256 {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW}, 2203 {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW},
2257 2204 {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
2258 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
2259 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, 2205 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2260 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
2261 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, 2206 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2262 {0xa0, 0x13, ZC3XX_R1AA_DIGITALGAINSTEP}, 2207 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
2263 {0xa1, 0x01, 0x001d}, 2208 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2264 {0xa1, 0x01, 0x001e}, 2209 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2265 {0xa1, 0x01, 0x001f}, 2210 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2266 {0xa1, 0x01, 0x0020}, 2211 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2267 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, 2212 {}
2268 {0xa1, 0x01, 0x0180}, 2213};
2269 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, 2214static const struct usb_action hv7131r_60HZ[] = {
2215 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2216 {0xa0, 0x06, ZC3XX_R190_EXPOSURELIMITHIGH},
2217 {0xa0, 0x1a, ZC3XX_R191_EXPOSURELIMITMID},
2218 {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW},
2219 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2220 {0xa0, 0xc3, ZC3XX_R196_ANTIFLICKERMID},
2221 {0xa0, 0x50, ZC3XX_R197_ANTIFLICKERLOW},
2222 {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
2223 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2224 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2225 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
2226 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2227 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2228 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2229 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2230 {}
2231};
2232static const struct usb_action hv7131r_60HZScale[] = {
2233 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2234 {0xa0, 0x0c, ZC3XX_R190_EXPOSURELIMITHIGH},
2235 {0xa0, 0x35, ZC3XX_R191_EXPOSURELIMITMID},
2236 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
2237 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
2238 {0xa0, 0x86, ZC3XX_R196_ANTIFLICKERMID},
2239 {0xa0, 0xa0, ZC3XX_R197_ANTIFLICKERLOW},
2240 {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
2241 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2242 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2243 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
2244 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2245 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2246 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2247 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2248 {}
2249};
2250static const struct usb_action hv7131r_NoFliker[] = {
2251 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2252 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},
2253 {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},
2254 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
2255 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2256 {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID},
2257 {0xa0, 0x58, ZC3XX_R197_ANTIFLICKERLOW},
2258 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
2259 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
2260 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
2261 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
2262 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2263 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2264 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2265 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2266 {}
2267};
2268static const struct usb_action hv7131r_NoFlikerScale[] = {
2269 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2270 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},
2271 {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},
2272 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
2273 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2274 {0xa0, 0x04, ZC3XX_R196_ANTIFLICKERMID},
2275 {0xa0, 0xb0, ZC3XX_R197_ANTIFLICKERLOW},
2276 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
2277 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
2278 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
2279 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
2280 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2281 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2282 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2283 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2270 {} 2284 {}
2271}; 2285};
2272 2286
@@ -3350,7 +3364,7 @@ static const struct usb_action ov7620_NoFliker[] = {
3350 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ 3364 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3351 {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,01,cc */ 3365 {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,01,cc */
3352/* {0xa0, 0x44, ZC3XX_R002_CLOCKSELECT}, * 00,02,44,cc 3366/* {0xa0, 0x44, ZC3XX_R002_CLOCKSELECT}, * 00,02,44,cc
3353 - if mode1 (320x240) */ 3367 * if mode1 (320x240) */
3354/* ?? was 3368/* ?? was
3355 {0xa0, 0x00, 0x0039}, * 00,00,00,dd * 3369 {0xa0, 0x00, 0x0039}, * 00,00,00,dd *
3356 {0xa1, 0x01, 0x0037}, */ 3370 {0xa1, 0x01, 0x0037}, */
@@ -3439,7 +3453,6 @@ static const struct usb_action ov7630c_InitialScale[] = {
3439 {0xa0, 0xf8, ZC3XX_R110_RGB20}, 3453 {0xa0, 0xf8, ZC3XX_R110_RGB20},
3440 {0xa0, 0xf8, ZC3XX_R111_RGB21}, 3454 {0xa0, 0xf8, ZC3XX_R111_RGB21},
3441 {0xa0, 0x50, ZC3XX_R112_RGB22}, 3455 {0xa0, 0x50, ZC3XX_R112_RGB22},
3442/* 0x03, */
3443 {0xa1, 0x01, 0x0008}, 3456 {0xa1, 0x01, 0x0008},
3444 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ 3457 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
3445 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ 3458 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
@@ -3719,7 +3732,7 @@ static const struct usb_action pas106b_InitialScale[] = { /* 176x144 */
3719 {0xaa, 0x0e, 0x0002}, 3732 {0xaa, 0x0e, 0x0002},
3720 {0xaa, 0x14, 0x0081}, 3733 {0xaa, 0x14, 0x0081},
3721 3734
3722/* Other registors */ 3735/* Other registers */
3723 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, 3736 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
3724/* Frame retreiving */ 3737/* Frame retreiving */
3725 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, 3738 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
@@ -3730,7 +3743,7 @@ static const struct usb_action pas106b_InitialScale[] = { /* 176x144 */
3730/* Sharpness */ 3743/* Sharpness */
3731 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, 3744 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
3732 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, 3745 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
3733/* Other registors */ 3746/* Other registers */
3734 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, 3747 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3735/* Auto exposure and white balance */ 3748/* Auto exposure and white balance */
3736 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, 3749 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
@@ -3837,7 +3850,7 @@ static const struct usb_action pas106b_Initial[] = { /* 352x288 */
3837 {0xaa, 0x0e, 0x0002}, 3850 {0xaa, 0x0e, 0x0002},
3838 {0xaa, 0x14, 0x0081}, 3851 {0xaa, 0x14, 0x0081},
3839 3852
3840/* Other registors */ 3853/* Other registers */
3841 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, 3854 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
3842/* Frame retreiving */ 3855/* Frame retreiving */
3843 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, 3856 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
@@ -3848,7 +3861,7 @@ static const struct usb_action pas106b_Initial[] = { /* 352x288 */
3848/* Sharpness */ 3861/* Sharpness */
3849 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, 3862 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
3850 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, 3863 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
3851/* Other registors */ 3864/* Other registers */
3852 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, 3865 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3853/* Auto exposure and white balance */ 3866/* Auto exposure and white balance */
3854 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, 3867 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
@@ -4241,8 +4254,8 @@ static const struct usb_action pas202b_NoFlikerScale[] = {
4241 {} 4254 {}
4242}; 4255};
4243 4256
4244/* mi0360soc and pb0330 from vm30x.inf for 0ac8:301b and 0ac8:303b 07/02/13 */ 4257/* mt9v111 (mi0360soc) and pb0330 from vm30x.inf 0ac8:301b 07/02/13 */
4245static const struct usb_action mi0360soc_Initial[] = { /* 640x480 */ 4258static const struct usb_action mt9v111_1_Initial[] = { /* 640x480 */
4246 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, 4259 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4247 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, 4260 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4248 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, 4261 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
@@ -4253,14 +4266,14 @@ static const struct usb_action mi0360soc_Initial[] = { /* 640x480 */
4253 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, 4266 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4254 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, 4267 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4255 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, 4268 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4256 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, /*jfm: was 03*/ 4269 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4257/* {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, */
4258 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, 4270 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4259 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, 4271 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4260 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, 4272 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4261 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, 4273 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4262 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, 4274 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4263 {0xdd, 0x00, 0x0200}, 4275 {0xdd, 0x00, 0x0200},
4276 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4264 {0xaa, 0x01, 0x0001}, 4277 {0xaa, 0x01, 0x0001},
4265 {0xaa, 0x06, 0x0000}, 4278 {0xaa, 0x06, 0x0000},
4266 {0xaa, 0x08, 0x0483}, 4279 {0xaa, 0x08, 0x0483},
@@ -4270,18 +4283,18 @@ static const struct usb_action mi0360soc_Initial[] = { /* 640x480 */
4270 {0xaa, 0x03, 0x01e5}, /*jfm: was 01e7*/ 4283 {0xaa, 0x03, 0x01e5}, /*jfm: was 01e7*/
4271 {0xaa, 0x04, 0x0285}, /*jfm: was 0287*/ 4284 {0xaa, 0x04, 0x0285}, /*jfm: was 0287*/
4272 {0xaa, 0x07, 0x3002}, 4285 {0xaa, 0x07, 0x3002},
4273 {0xaa, 0x20, 0x5100}, /*jfm: was 1100*/ 4286 {0xaa, 0x20, 0x5100},
4274 {0xaa, 0x35, 0x507f}, /*jfm: was 0050*/ 4287 {0xaa, 0x35, 0x507f},
4275 {0xaa, 0x30, 0x0005}, 4288 {0xaa, 0x30, 0x0005},
4276 {0xaa, 0x31, 0x0000}, 4289 {0xaa, 0x31, 0x0000},
4277 {0xaa, 0x58, 0x0078}, 4290 {0xaa, 0x58, 0x0078},
4278 {0xaa, 0x62, 0x0411}, 4291 {0xaa, 0x62, 0x0411},
4279 {0xaa, 0x2b, 0x0028}, 4292 {0xaa, 0x2b, 0x007f},
4280 {0xaa, 0x2c, 0x007f}, /*jfm: was 0030*/ 4293 {0xaa, 0x2c, 0x007f}, /*jfm: was 0030*/
4281 {0xaa, 0x2d, 0x007f}, /*jfm: was 0030*/ 4294 {0xaa, 0x2d, 0x007f}, /*jfm: was 0030*/
4282 {0xaa, 0x2e, 0x007f}, /*jfm: was 0030*/ 4295 {0xaa, 0x2e, 0x007f}, /*jfm: was 0030*/
4283 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, 4296 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4284 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /*jfm: was 37*/ 4297 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
4285 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, 4298 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4286 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, 4299 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4287 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, 4300 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
@@ -4291,12 +4304,12 @@ static const struct usb_action mi0360soc_Initial[] = { /* 640x480 */
4291 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, 4304 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4292 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, 4305 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4293 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, 4306 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4294 {0xa0, 0x6c, ZC3XX_R18D_YTARGET}, /* jfm: was 78 */ 4307 {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
4295 {0xa0, 0x61, ZC3XX_R116_RGAIN}, 4308 {0xa0, 0x61, ZC3XX_R116_RGAIN},
4296 {0xa0, 0x65, ZC3XX_R118_BGAIN}, 4309 {0xa0, 0x65, ZC3XX_R118_BGAIN},
4297 {} 4310 {}
4298}; 4311};
4299static const struct usb_action mi0360soc_InitialScale[] = { /* 320x240 */ 4312static const struct usb_action mt9v111_1_InitialScale[] = { /* 320x240 */
4300 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, 4313 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4301 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, 4314 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4302 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, 4315 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
@@ -4307,14 +4320,14 @@ static const struct usb_action mi0360soc_InitialScale[] = { /* 320x240 */
4307 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, 4320 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4308 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, 4321 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4309 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, 4322 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4310 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, /*jfm: was 03*/ 4323 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4311/* {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, */
4312 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, 4324 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4313 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, 4325 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4314 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, 4326 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4315 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, 4327 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4316 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, 4328 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4317 {0xdd, 0x00, 0x0200}, 4329 {0xdd, 0x00, 0x0200},
4330 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4318 {0xaa, 0x01, 0x0001}, 4331 {0xaa, 0x01, 0x0001},
4319 {0xaa, 0x06, 0x0000}, 4332 {0xaa, 0x06, 0x0000},
4320 {0xaa, 0x08, 0x0483}, 4333 {0xaa, 0x08, 0x0483},
@@ -4324,7 +4337,7 @@ static const struct usb_action mi0360soc_InitialScale[] = { /* 320x240 */
4324 {0xaa, 0x03, 0x01e7}, 4337 {0xaa, 0x03, 0x01e7},
4325 {0xaa, 0x04, 0x0287}, 4338 {0xaa, 0x04, 0x0287},
4326 {0xaa, 0x07, 0x3002}, 4339 {0xaa, 0x07, 0x3002},
4327 {0xaa, 0x20, 0x5100}, /*jfm: was 1100*/ 4340 {0xaa, 0x20, 0x5100},
4328 {0xaa, 0x35, 0x007f}, /*jfm: was 0050*/ 4341 {0xaa, 0x35, 0x007f}, /*jfm: was 0050*/
4329 {0xaa, 0x30, 0x0005}, 4342 {0xaa, 0x30, 0x0005},
4330 {0xaa, 0x31, 0x0000}, 4343 {0xaa, 0x31, 0x0000},
@@ -4335,7 +4348,7 @@ static const struct usb_action mi0360soc_InitialScale[] = { /* 320x240 */
4335 {0xaa, 0x2d, 0x007f}, /*jfm: was 30*/ 4348 {0xaa, 0x2d, 0x007f}, /*jfm: was 30*/
4336 {0xaa, 0x2e, 0x007f}, /*jfm: was 28*/ 4349 {0xaa, 0x2e, 0x007f}, /*jfm: was 28*/
4337 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, 4350 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4338 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /*jfm: was 37*/ 4351 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
4339 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, 4352 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4340 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, 4353 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4341 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, 4354 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
@@ -4345,12 +4358,12 @@ static const struct usb_action mi0360soc_InitialScale[] = { /* 320x240 */
4345 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, 4358 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4346 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, 4359 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4347 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, 4360 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4348 {0xa0, 0x6c, ZC3XX_R18D_YTARGET}, /*jfm: was 78*/ 4361 {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
4349 {0xa0, 0x61, ZC3XX_R116_RGAIN}, 4362 {0xa0, 0x61, ZC3XX_R116_RGAIN},
4350 {0xa0, 0x65, ZC3XX_R118_BGAIN}, 4363 {0xa0, 0x65, ZC3XX_R118_BGAIN},
4351 {} 4364 {}
4352}; 4365};
4353static const struct usb_action mi360soc_AE50HZ[] = { 4366static const struct usb_action mt9v111_1_AE50HZ[] = {
4354 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, 4367 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4355 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, 4368 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4356 {0xbb, 0x00, 0x0562}, 4369 {0xbb, 0x00, 0x0562},
@@ -4373,7 +4386,7 @@ static const struct usb_action mi360soc_AE50HZ[] = {
4373 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, 4386 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4374 {} 4387 {}
4375}; 4388};
4376static const struct usb_action mi360soc_AE50HZScale[] = { 4389static const struct usb_action mt9v111_1_AE50HZScale[] = {
4377 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, 4390 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4378 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, 4391 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4379 {0xbb, 0x00, 0x0509}, 4392 {0xbb, 0x00, 0x0509},
@@ -4395,11 +4408,11 @@ static const struct usb_action mi360soc_AE50HZScale[] = {
4395 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, 4408 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4396 {} 4409 {}
4397}; 4410};
4398static const struct usb_action mi360soc_AE60HZ[] = { 4411static const struct usb_action mt9v111_1_AE60HZ[] = {
4399 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, 4412 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4400 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, 4413 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4401 {0xbb, 0x00, 0x053d}, 4414 {0xaa, 0x05, 0x003d},
4402 {0xbb, 0x01, 0x096e}, 4415 {0xaa, 0x09, 0x016e},
4403 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, 4416 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4404 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, 4417 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4405 {0xa0, 0xdd, ZC3XX_R192_EXPOSURELIMITLOW}, 4418 {0xa0, 0xdd, ZC3XX_R192_EXPOSURELIMITLOW},
@@ -4418,7 +4431,7 @@ static const struct usb_action mi360soc_AE60HZ[] = {
4418 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, 4431 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4419 {} 4432 {}
4420}; 4433};
4421static const struct usb_action mi360soc_AE60HZScale[] = { 4434static const struct usb_action mt9v111_1_AE60HZScale[] = {
4422 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, 4435 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4423 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, 4436 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4424 {0xbb, 0x00, 0x0509}, 4437 {0xbb, 0x00, 0x0509},
@@ -4440,7 +4453,7 @@ static const struct usb_action mi360soc_AE60HZScale[] = {
4440 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, 4453 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4441 {} 4454 {}
4442}; 4455};
4443static const struct usb_action mi360soc_AENoFliker[] = { 4456static const struct usb_action mt9v111_1_AENoFliker[] = {
4444 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, 4457 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4445 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, 4458 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4446 {0xbb, 0x00, 0x0509}, 4459 {0xbb, 0x00, 0x0509},
@@ -4463,7 +4476,7 @@ static const struct usb_action mi360soc_AENoFliker[] = {
4463 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, 4476 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4464 {} 4477 {}
4465}; 4478};
4466static const struct usb_action mi360soc_AENoFlikerScale[] = { 4479static const struct usb_action mt9v111_1_AENoFlikerScale[] = {
4467 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, 4480 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4468 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, 4481 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4469 {0xbb, 0x00, 0x0534}, 4482 {0xbb, 0x00, 0x0534},
@@ -4486,6 +4499,251 @@ static const struct usb_action mi360soc_AENoFlikerScale[] = {
4486 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, 4499 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4487 {} 4500 {}
4488}; 4501};
4502/* from usbvm303.inf 0ac8:303b 07/03/25 (3 - tas5130c) */
4503static const struct usb_action mt9v111_3_Initial[] = {
4504 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4505 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4506 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4507 {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT},
4508 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4509 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4510 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4511 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4512 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4513 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4514 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4515 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4516 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4517 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4518 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4519 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4520 {0xdd, 0x00, 0x0200},
4521 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4522 {0xaa, 0x01, 0x0001}, /* select IFP/SOC registers */
4523 {0xaa, 0x06, 0x0000}, /* operating mode control */
4524 {0xaa, 0x08, 0x0483}, /* output format control */
4525 /* H red first, V red or blue first,
4526 * raw Bayer, auto flicker */
4527 {0xaa, 0x01, 0x0004}, /* select sensor core registers */
4528 {0xaa, 0x08, 0x0006}, /* row start */
4529 {0xaa, 0x02, 0x0011}, /* column start */
4530 {0xaa, 0x03, 0x01e5}, /* window height - 1 */
4531 {0xaa, 0x04, 0x0285}, /* window width - 1 */
4532 {0xaa, 0x07, 0x3002}, /* output control */
4533 {0xaa, 0x20, 0x1100}, /* read mode: bits 8 & 12 (?) */
4534 {0xaa, 0x35, 0x007f}, /* global gain */
4535 {0xaa, 0x30, 0x0005},
4536 {0xaa, 0x31, 0x0000},
4537 {0xaa, 0x58, 0x0078},
4538 {0xaa, 0x62, 0x0411},
4539 {0xaa, 0x2b, 0x007f}, /* green1 gain */
4540 {0xaa, 0x2c, 0x007f}, /* blue gain */
4541 {0xaa, 0x2d, 0x007f}, /* red gain */
4542 {0xaa, 0x2e, 0x007f}, /* green2 gain */
4543 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4544 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4545 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4546 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4547 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4548 {0xa0, 0x00, 0x01ad},
4549 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4550 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4551 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4552 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4553 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4554 {0xa0, 0x80, ZC3XX_R18D_YTARGET},
4555 {0xa0, 0x61, ZC3XX_R116_RGAIN},
4556 {0xa0, 0x65, ZC3XX_R118_BGAIN},
4557 {}
4558};
4559static const struct usb_action mt9v111_3_InitialScale[] = {
4560 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4561 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4562 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4563 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
4564 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4565 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4566 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4567 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4568 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4569 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4570 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4571 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4572 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4573 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4574 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4575 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4576 {0xdd, 0x00, 0x0200},
4577 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4578 {0xaa, 0x01, 0x0001},
4579 {0xaa, 0x06, 0x0000},
4580 {0xaa, 0x08, 0x0483},
4581 {0xaa, 0x01, 0x0004},
4582 {0xaa, 0x08, 0x0006},
4583 {0xaa, 0x02, 0x0011},
4584 {0xaa, 0x03, 0x01e7},
4585 {0xaa, 0x04, 0x0287},
4586 {0xaa, 0x07, 0x3002},
4587 {0xaa, 0x20, 0x1100},
4588 {0xaa, 0x35, 0x007f},
4589 {0xaa, 0x30, 0x0005},
4590 {0xaa, 0x31, 0x0000},
4591 {0xaa, 0x58, 0x0078},
4592 {0xaa, 0x62, 0x0411},
4593 {0xaa, 0x2b, 0x007f},
4594 {0xaa, 0x2c, 0x007f},
4595 {0xaa, 0x2d, 0x007f},
4596 {0xaa, 0x2e, 0x007f},
4597 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4598 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4599 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4600 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4601 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4602 {0xa0, 0x00, 0x01ad},
4603 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4604 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4605 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4606 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4607 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4608 {0xa0, 0x80, ZC3XX_R18D_YTARGET},
4609 {0xa0, 0x61, ZC3XX_R116_RGAIN},
4610 {0xa0, 0x65, ZC3XX_R118_BGAIN},
4611 {}
4612};
4613static const struct usb_action mt9v111_3_AE50HZ[] = {
4614 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4615 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4616 {0xaa, 0x05, 0x0009}, /* horizontal blanking */
4617 {0xaa, 0x09, 0x01ce}, /* shutter width */
4618 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4619 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4620 {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
4621 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4622 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4623 {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
4624 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4625 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4626 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4627 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4628 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4629 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4630 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4631 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4632 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4633 {}
4634};
4635static const struct usb_action mt9v111_3_AE50HZScale[] = {
4636 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4637 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4638 {0xaa, 0x05, 0x0009},
4639 {0xaa, 0x09, 0x01ce},
4640 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4641 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4642 {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
4643 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4644 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4645 {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
4646 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4647 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4648 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4649 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4650 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4651 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4652 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4653 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4654 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4655 {}
4656};
4657static const struct usb_action mt9v111_3_AE60HZ[] = {
4658 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4659 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4660 {0xaa, 0x05, 0x0009},
4661 {0xaa, 0x09, 0x0083},
4662 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4663 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4664 {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW},
4665 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4666 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4667 {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW},
4668 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4669 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4670 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4671 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4672 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4673 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4674 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4675 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4676 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4677 {}
4678};
4679static const struct usb_action mt9v111_3_AE60HZScale[] = {
4680 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4681 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4682 {0xaa, 0x05, 0x0009},
4683 {0xaa, 0x09, 0x0083},
4684 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4685 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4686 {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW},
4687 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4688 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4689 {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW},
4690 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4691 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4692 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4693 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4694 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4695 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4696 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4697 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4698 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4699 {}
4700};
4701static const struct usb_action mt9v111_3_AENoFliker[] = {
4702 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4703 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4704 {0xaa, 0x05, 0x0034},
4705 {0xaa, 0x09, 0x0260},
4706 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4707 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4708 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
4709 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4710 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4711 {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
4712 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4713 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4714 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
4715 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
4716 {0xa0, 0x34, ZC3XX_R01D_HSYNC_0},
4717 {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
4718 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4719 {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
4720 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4721 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4722 {}
4723};
4724static const struct usb_action mt9v111_3_AENoFlikerScale[] = {
4725 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4726 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4727 {0xaa, 0x05, 0x0034},
4728 {0xaa, 0x09, 0x0260},
4729 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4730 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4731 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
4732 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4733 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4734 {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
4735 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4736 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4737 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
4738 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
4739 {0xa0, 0x34, ZC3XX_R01D_HSYNC_0},
4740 {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
4741 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4742 {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
4743 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4744 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4745 {}
4746};
4489 4747
4490static const struct usb_action pb0330_Initial[] = { /* 640x480 */ 4748static const struct usb_action pb0330_Initial[] = { /* 640x480 */
4491 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, 4749 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
@@ -4928,419 +5186,7 @@ static const struct usb_action po2030_NoFliker[] = {
4928 {} 5186 {}
4929}; 5187};
4930 5188
4931/* TEST */ 5189static const struct usb_action tas5130c_InitialScale[] = { /* 320x240 */
4932static const struct usb_action tas5130cK_InitialScale[] = {
4933 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4934 {0xa0, 0x01, 0x003b},
4935 {0xa0, 0x0e, 0x003a},
4936 {0xa0, 0x01, 0x0038},
4937 {0xa0, 0x0b, 0x0039},
4938 {0xa0, 0x00, 0x0038},
4939 {0xa0, 0x0b, 0x0039},
4940 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4941 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4942 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4943 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
4944 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4945 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4946 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4947 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4948 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4949 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4950 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4951 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4952 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4953 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4954 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4955 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4956 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4957 {0xa0, 0x01, ZC3XX_R092_I2CADDRESSSELECT},
4958 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
4959 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
4960 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
4961 {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
4962 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
4963 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
4964 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
4965 {0xa0, 0x08, ZC3XX_R092_I2CADDRESSSELECT},
4966 {0xa0, 0x83, ZC3XX_R093_I2CSETVALUE},
4967 {0xa0, 0x04, ZC3XX_R094_I2CWRITEACK},
4968 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
4969 {0xa0, 0x01, ZC3XX_R092_I2CADDRESSSELECT},
4970 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
4971 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
4972 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
4973 {0xa0, 0x08, ZC3XX_R092_I2CADDRESSSELECT},
4974 {0xa0, 0x06, ZC3XX_R093_I2CSETVALUE},
4975 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
4976 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
4977 {0xa0, 0x02, ZC3XX_R092_I2CADDRESSSELECT},
4978 {0xa0, 0x11, ZC3XX_R093_I2CSETVALUE},
4979 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
4980 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
4981 {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
4982 {0xa0, 0xE7, ZC3XX_R093_I2CSETVALUE},
4983 {0xa0, 0x01, ZC3XX_R094_I2CWRITEACK},
4984 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
4985 {0xa0, 0x04, ZC3XX_R092_I2CADDRESSSELECT},
4986 {0xa0, 0x87, ZC3XX_R093_I2CSETVALUE},
4987 {0xa0, 0x02, ZC3XX_R094_I2CWRITEACK},
4988 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
4989 {0xa0, 0x07, ZC3XX_R092_I2CADDRESSSELECT},
4990 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
4991 {0xa0, 0x30, ZC3XX_R094_I2CWRITEACK},
4992 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
4993 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
4994 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
4995 {0xa0, 0x51, ZC3XX_R094_I2CWRITEACK},
4996 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
4997 {0xa0, 0x35, ZC3XX_R092_I2CADDRESSSELECT},
4998 {0xa0, 0x7F, ZC3XX_R093_I2CSETVALUE},
4999 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5000 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5001 {0xa0, 0x30, ZC3XX_R092_I2CADDRESSSELECT},
5002 {0xa0, 0x05, ZC3XX_R093_I2CSETVALUE},
5003 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5004 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5005 {0xa0, 0x31, ZC3XX_R092_I2CADDRESSSELECT},
5006 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
5007 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5008 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5009 {0xa0, 0x58, ZC3XX_R092_I2CADDRESSSELECT},
5010 {0xa0, 0x78, ZC3XX_R093_I2CSETVALUE},
5011 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5012 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5013 {0xa0, 0x62, ZC3XX_R092_I2CADDRESSSELECT},
5014 {0xa0, 0x11, ZC3XX_R093_I2CSETVALUE},
5015 {0xa0, 0x04, ZC3XX_R094_I2CWRITEACK},
5016 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5017 {0xa0, 0x2B, ZC3XX_R092_I2CADDRESSSELECT},
5018 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5019 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5020 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5021 {0xa0, 0x2c, ZC3XX_R092_I2CADDRESSSELECT},
5022 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5023 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5024 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5025 {0xa0, 0x2D, ZC3XX_R092_I2CADDRESSSELECT},
5026 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5027 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5028 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5029 {0xa0, 0x2e, ZC3XX_R092_I2CADDRESSSELECT},
5030 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5031 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5032 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5033 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
5034 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
5035 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5036 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
5037 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
5038 {0xa0, 0x09, 0x01ad},
5039 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
5040 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
5041 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
5042 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
5043 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
5044 {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
5045 {0xa0, 0x61, ZC3XX_R116_RGAIN},
5046 {0xa0, 0x65, ZC3XX_R118_BGAIN},
5047 {0xa0, 0x09, 0x01ad},
5048 {0xa0, 0x15, 0x01ae},
5049 {0xa0, 0x4c, ZC3XX_R10A_RGB00}, /* matrix */
5050 {0xa0, 0xf1, ZC3XX_R10B_RGB01},
5051 {0xa0, 0x03, ZC3XX_R10C_RGB02},
5052 {0xa0, 0xfe, ZC3XX_R10D_RGB10},
5053 {0xa0, 0x51, ZC3XX_R10E_RGB11},
5054 {0xa0, 0xf1, ZC3XX_R10F_RGB12},
5055 {0xa0, 0xec, ZC3XX_R110_RGB20},
5056 {0xa0, 0x03, ZC3XX_R111_RGB21},
5057 {0xa0, 0x51, ZC3XX_R112_RGB22},
5058 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5059 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
5060 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
5061 {0xa0, 0x38, ZC3XX_R120_GAMMA00}, /* gamma > 5 */
5062 {0xa0, 0x51, ZC3XX_R121_GAMMA01},
5063 {0xa0, 0x6e, ZC3XX_R122_GAMMA02},
5064 {0xa0, 0x8c, ZC3XX_R123_GAMMA03},
5065 {0xa0, 0xa2, ZC3XX_R124_GAMMA04},
5066 {0xa0, 0xb6, ZC3XX_R125_GAMMA05},
5067 {0xa0, 0xc8, ZC3XX_R126_GAMMA06},
5068 {0xa0, 0xd6, ZC3XX_R127_GAMMA07},
5069 {0xa0, 0xe2, ZC3XX_R128_GAMMA08},
5070 {0xa0, 0xed, ZC3XX_R129_GAMMA09},
5071 {0xa0, 0xf5, ZC3XX_R12A_GAMMA0A},
5072 {0xa0, 0xfc, ZC3XX_R12B_GAMMA0B},
5073 {0xa0, 0xff, ZC3XX_R12C_GAMMA0C},
5074 {0xa0, 0xff, ZC3XX_R12D_GAMMA0D},
5075 {0xa0, 0xff, ZC3XX_R12E_GAMMA0E},
5076 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
5077 {0xa0, 0x12, ZC3XX_R130_GAMMA10},
5078 {0xa0, 0x1b, ZC3XX_R131_GAMMA11},
5079 {0xa0, 0x1d, ZC3XX_R132_GAMMA12},
5080 {0xa0, 0x1a, ZC3XX_R133_GAMMA13},
5081 {0xa0, 0x15, ZC3XX_R134_GAMMA14},
5082 {0xa0, 0x12, ZC3XX_R135_GAMMA15},
5083 {0xa0, 0x0f, ZC3XX_R136_GAMMA16},
5084 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
5085 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
5086 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
5087 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
5088 {0xa0, 0x05, ZC3XX_R13B_GAMMA1B},
5089 {0xa0, 0x00, ZC3XX_R13C_GAMMA1C},
5090 {0xa0, 0x00, ZC3XX_R13D_GAMMA1D},
5091 {0xa0, 0x00, ZC3XX_R13E_GAMMA1E},
5092 {0xa0, 0x01, ZC3XX_R13F_GAMMA1F},
5093 {0xa0, 0x4c, ZC3XX_R10A_RGB00}, /* matrix */
5094 {0xa0, 0xf1, ZC3XX_R10B_RGB01},
5095 {0xa0, 0x03, ZC3XX_R10C_RGB02},
5096 {0xa0, 0xfe, ZC3XX_R10D_RGB10},
5097 {0xa0, 0x51, ZC3XX_R10E_RGB11},
5098 {0xa0, 0xf1, ZC3XX_R10F_RGB12},
5099 {0xa0, 0xec, ZC3XX_R110_RGB20},
5100 {0xa0, 0x03, ZC3XX_R111_RGB21},
5101 {0xa0, 0x51, ZC3XX_R112_RGB22},
5102 {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
5103 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
5104 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
5105 {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
5106 {0xa0, 0x09, ZC3XX_R093_I2CSETVALUE},
5107 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5108 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5109 {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
5110 {0xa0, 0x34, ZC3XX_R093_I2CSETVALUE},
5111 {0xa0, 0x01, ZC3XX_R094_I2CWRITEACK},
5112 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5113 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
5114 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
5115 {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
5116 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
5117 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
5118 {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
5119 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
5120 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
5121 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
5122 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
5123 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
5124 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
5125 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
5126 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
5127 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
5128 {0xa0, 0x09, 0x01ad},
5129 {0xa0, 0x15, 0x01ae},
5130 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
5131 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
5132 {}
5133};
5134
5135static const struct usb_action tas5130cK_Initial[] = {
5136 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5137 {0xa0, 0x01, 0x003b},
5138 {0xa0, 0x0e, 0x003a},
5139 {0xa0, 0x01, 0x0038},
5140 {0xa0, 0x0b, 0x0039},
5141 {0xa0, 0x00, 0x0038},
5142 {0xa0, 0x0b, 0x0039},
5143 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5144 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5145 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
5146 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
5147 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
5148 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
5149 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
5150 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
5151 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
5152 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5153 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
5154 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
5155 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
5156 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
5157 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
5158 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
5159 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5160 {0xa0, 0x01, ZC3XX_R092_I2CADDRESSSELECT},
5161 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
5162 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5163 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5164 {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
5165 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
5166 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5167 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5168 {0xa0, 0x08, ZC3XX_R092_I2CADDRESSSELECT},
5169 {0xa0, 0x83, ZC3XX_R093_I2CSETVALUE},
5170 {0xa0, 0x04, ZC3XX_R094_I2CWRITEACK},
5171 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5172 {0xa0, 0x01, ZC3XX_R092_I2CADDRESSSELECT},
5173 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
5174 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5175 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5176 {0xa0, 0x08, ZC3XX_R092_I2CADDRESSSELECT},
5177 {0xa0, 0x06, ZC3XX_R093_I2CSETVALUE},
5178 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5179 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5180 {0xa0, 0x02, ZC3XX_R092_I2CADDRESSSELECT},
5181 {0xa0, 0x11, ZC3XX_R093_I2CSETVALUE},
5182 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5183 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5184 {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
5185 {0xa0, 0xe5, ZC3XX_R093_I2CSETVALUE},
5186 {0xa0, 0x01, ZC3XX_R094_I2CWRITEACK},
5187 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5188 {0xa0, 0x04, ZC3XX_R092_I2CADDRESSSELECT},
5189 {0xa0, 0x85, ZC3XX_R093_I2CSETVALUE},
5190 {0xa0, 0x02, ZC3XX_R094_I2CWRITEACK},
5191 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5192 {0xa0, 0x07, ZC3XX_R092_I2CADDRESSSELECT},
5193 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
5194 {0xa0, 0x30, ZC3XX_R094_I2CWRITEACK},
5195 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5196 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
5197 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
5198 {0xa0, 0x51, ZC3XX_R094_I2CWRITEACK},
5199 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5200 {0xa0, 0x35, ZC3XX_R092_I2CADDRESSSELECT},
5201 {0xa0, 0x7F, ZC3XX_R093_I2CSETVALUE},
5202 {0xa0, 0x50, ZC3XX_R094_I2CWRITEACK},
5203 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5204 {0xa0, 0x30, ZC3XX_R092_I2CADDRESSSELECT},
5205 {0xa0, 0x05, ZC3XX_R093_I2CSETVALUE},
5206 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5207 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5208 {0xa0, 0x31, ZC3XX_R092_I2CADDRESSSELECT},
5209 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
5210 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5211 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5212 {0xa0, 0x58, ZC3XX_R092_I2CADDRESSSELECT},
5213 {0xa0, 0x78, ZC3XX_R093_I2CSETVALUE},
5214 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5215 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5216 {0xa0, 0x62, ZC3XX_R092_I2CADDRESSSELECT},
5217 {0xa0, 0x11, ZC3XX_R093_I2CSETVALUE},
5218 {0xa0, 0x04, ZC3XX_R094_I2CWRITEACK},
5219 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5220 {0xa0, 0x2B, ZC3XX_R092_I2CADDRESSSELECT},
5221 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5222 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5223 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5224 {0xa0, 0x2C, ZC3XX_R092_I2CADDRESSSELECT},
5225 {0xa0, 0x7F, ZC3XX_R093_I2CSETVALUE},
5226 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5227 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5228 {0xa0, 0x2D, ZC3XX_R092_I2CADDRESSSELECT},
5229 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5230 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5231 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5232 {0xa0, 0x2e, ZC3XX_R092_I2CADDRESSSELECT},
5233 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5234 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5235 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5236 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
5237 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
5238 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5239 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
5240 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
5241 {0xa0, 0x09, 0x01ad},
5242 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
5243 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
5244 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
5245 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
5246 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
5247 {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
5248 {0xa0, 0x61, ZC3XX_R116_RGAIN},
5249 {0xa0, 0x65, ZC3XX_R118_BGAIN},
5250 {0xa0, 0x09, 0x01ad},
5251 {0xa0, 0x15, 0x01ae},
5252 {0xa0, 0x4c, ZC3XX_R10A_RGB00}, /* matrix */
5253 {0xa0, 0xf1, ZC3XX_R10B_RGB01},
5254 {0xa0, 0x03, ZC3XX_R10C_RGB02},
5255 {0xa0, 0xfe, ZC3XX_R10D_RGB10},
5256 {0xa0, 0x51, ZC3XX_R10E_RGB11},
5257 {0xa0, 0xf1, ZC3XX_R10F_RGB12},
5258 {0xa0, 0xec, ZC3XX_R110_RGB20},
5259 {0xa0, 0x03, ZC3XX_R111_RGB21},
5260 {0xa0, 0x51, ZC3XX_R112_RGB22},
5261 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5262 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
5263 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
5264 {0xa0, 0x38, ZC3XX_R120_GAMMA00}, /* gamma > 5 */
5265 {0xa0, 0x51, ZC3XX_R121_GAMMA01},
5266 {0xa0, 0x6e, ZC3XX_R122_GAMMA02},
5267 {0xa0, 0x8c, ZC3XX_R123_GAMMA03},
5268 {0xa0, 0xa2, ZC3XX_R124_GAMMA04},
5269 {0xa0, 0xb6, ZC3XX_R125_GAMMA05},
5270 {0xa0, 0xc8, ZC3XX_R126_GAMMA06},
5271 {0xa0, 0xd6, ZC3XX_R127_GAMMA07},
5272 {0xa0, 0xe2, ZC3XX_R128_GAMMA08},
5273 {0xa0, 0xed, ZC3XX_R129_GAMMA09},
5274 {0xa0, 0xf5, ZC3XX_R12A_GAMMA0A},
5275 {0xa0, 0xfc, ZC3XX_R12B_GAMMA0B},
5276 {0xa0, 0xff, ZC3XX_R12C_GAMMA0C},
5277 {0xa0, 0xff, ZC3XX_R12D_GAMMA0D},
5278 {0xa0, 0xff, ZC3XX_R12E_GAMMA0E},
5279 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
5280 {0xa0, 0x12, ZC3XX_R130_GAMMA10},
5281 {0xa0, 0x1b, ZC3XX_R131_GAMMA11},
5282 {0xa0, 0x1d, ZC3XX_R132_GAMMA12},
5283 {0xa0, 0x1a, ZC3XX_R133_GAMMA13},
5284 {0xa0, 0x15, ZC3XX_R134_GAMMA14},
5285 {0xa0, 0x12, ZC3XX_R135_GAMMA15},
5286 {0xa0, 0x0f, ZC3XX_R136_GAMMA16},
5287 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
5288 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
5289 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
5290 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
5291 {0xa0, 0x05, ZC3XX_R13B_GAMMA1B},
5292 {0xa0, 0x00, ZC3XX_R13C_GAMMA1C},
5293 {0xa0, 0x00, ZC3XX_R13D_GAMMA1D},
5294 {0xa0, 0x00, ZC3XX_R13E_GAMMA1E},
5295 {0xa0, 0x01, ZC3XX_R13F_GAMMA1F},
5296 {0xa0, 0x4c, ZC3XX_R10A_RGB00}, /* matrix */
5297 {0xa0, 0xf1, ZC3XX_R10B_RGB01},
5298 {0xa0, 0x03, ZC3XX_R10C_RGB02},
5299 {0xa0, 0xfe, ZC3XX_R10D_RGB10},
5300 {0xa0, 0x51, ZC3XX_R10E_RGB11},
5301 {0xa0, 0xf1, ZC3XX_R10F_RGB12},
5302 {0xa0, 0xec, ZC3XX_R110_RGB20},
5303 {0xa0, 0x03, ZC3XX_R111_RGB21},
5304 {0xa0, 0x51, ZC3XX_R112_RGB22},
5305 {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
5306 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
5307 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
5308 {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
5309 {0xa0, 0x62, ZC3XX_R093_I2CSETVALUE},
5310 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5311 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5312 {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
5313 {0xa0, 0xaa, ZC3XX_R093_I2CSETVALUE},
5314 {0xa0, 0x01, ZC3XX_R094_I2CWRITEACK},
5315 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5316 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
5317 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
5318 {0xa0, 0x9b, ZC3XX_R192_EXPOSURELIMITLOW},
5319 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
5320 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
5321 {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW},
5322 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
5323 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
5324 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
5325 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
5326 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},
5327 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},
5328 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},
5329 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
5330 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
5331 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
5332 {0xa0, 0x09, 0x01ad},
5333 {0xa0, 0x15, 0x01ae},
5334 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
5335 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
5336 {0xa0, 0x30, 0x0007},
5337 {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},
5338 {0xa0, 0x00, 0x0007},
5339 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5340 {}
5341};
5342
5343static const struct usb_action tas5130cxx_InitialScale[] = { /* 320x240 */
5344 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, 5190 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5345 {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT}, 5191 {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT},
5346 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, 5192 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
@@ -5377,7 +5223,7 @@ static const struct usb_action tas5130cxx_InitialScale[] = { /* 320x240 */
5377 {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL}, 5223 {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
5378 {} 5224 {}
5379}; 5225};
5380static const struct usb_action tas5130cxx_Initial[] = { /* 640x480 */ 5226static const struct usb_action tas5130c_Initial[] = { /* 640x480 */
5381 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, 5227 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5382 {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, 5228 {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT},
5383 {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, 5229 {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING},
@@ -5413,7 +5259,7 @@ static const struct usb_action tas5130cxx_Initial[] = { /* 640x480 */
5413 {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL}, 5259 {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
5414 {} 5260 {}
5415}; 5261};
5416static const struct usb_action tas5130cxx_50HZ[] = { 5262static const struct usb_action tas5130c_50HZ[] = {
5417 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ 5263 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5418 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */ 5264 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5419 {0xaa, 0xa4, 0x0063}, /* 00,a4,63,aa */ 5265 {0xaa, 0xa4, 0x0063}, /* 00,a4,63,aa */
@@ -5438,7 +5284,7 @@ static const struct usb_action tas5130cxx_50HZ[] = {
5438 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, 5284 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5439 {} 5285 {}
5440}; 5286};
5441static const struct usb_action tas5130cxx_50HZScale[] = { 5287static const struct usb_action tas5130c_50HZScale[] = {
5442 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ 5288 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5443 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */ 5289 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5444 {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */ 5290 {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */
@@ -5463,7 +5309,7 @@ static const struct usb_action tas5130cxx_50HZScale[] = {
5463 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, 5309 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5464 {} 5310 {}
5465}; 5311};
5466static const struct usb_action tas5130cxx_60HZ[] = { 5312static const struct usb_action tas5130c_60HZ[] = {
5467 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ 5313 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5468 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */ 5314 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5469 {0xaa, 0xa4, 0x0036}, /* 00,a4,36,aa */ 5315 {0xaa, 0xa4, 0x0036}, /* 00,a4,36,aa */
@@ -5488,7 +5334,7 @@ static const struct usb_action tas5130cxx_60HZ[] = {
5488 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, 5334 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5489 {} 5335 {}
5490}; 5336};
5491static const struct usb_action tas5130cxx_60HZScale[] = { 5337static const struct usb_action tas5130c_60HZScale[] = {
5492 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ 5338 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5493 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */ 5339 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5494 {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */ 5340 {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */
@@ -5513,7 +5359,7 @@ static const struct usb_action tas5130cxx_60HZScale[] = {
5513 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, 5359 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5514 {} 5360 {}
5515}; 5361};
5516static const struct usb_action tas5130cxx_NoFliker[] = { 5362static const struct usb_action tas5130c_NoFliker[] = {
5517 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ 5363 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5518 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */ 5364 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5519 {0xaa, 0xa4, 0x0040}, /* 00,a4,40,aa */ 5365 {0xaa, 0xa4, 0x0040}, /* 00,a4,40,aa */
@@ -5539,7 +5385,7 @@ static const struct usb_action tas5130cxx_NoFliker[] = {
5539 {} 5385 {}
5540}; 5386};
5541 5387
5542static const struct usb_action tas5130cxx_NoFlikerScale[] = { 5388static const struct usb_action tas5130c_NoFlikerScale[] = {
5543 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ 5389 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5544 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */ 5390 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5545 {0xaa, 0xa4, 0x0090}, /* 00,a4,90,aa */ 5391 {0xaa, 0xa4, 0x0090}, /* 00,a4,90,aa */
@@ -5840,13 +5686,22 @@ static const struct usb_action tas5130c_vf0250_NoFliker[] = {
5840static u8 reg_r_i(struct gspca_dev *gspca_dev, 5686static u8 reg_r_i(struct gspca_dev *gspca_dev,
5841 u16 index) 5687 u16 index)
5842{ 5688{
5843 usb_control_msg(gspca_dev->dev, 5689 int ret;
5690
5691 if (gspca_dev->usb_err < 0)
5692 return 0;
5693 ret = usb_control_msg(gspca_dev->dev,
5844 usb_rcvctrlpipe(gspca_dev->dev, 0), 5694 usb_rcvctrlpipe(gspca_dev->dev, 0),
5845 0xa1, 5695 0xa1,
5846 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 5696 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
5847 0x01, /* value */ 5697 0x01, /* value */
5848 index, gspca_dev->usb_buf, 1, 5698 index, gspca_dev->usb_buf, 1,
5849 500); 5699 500);
5700 if (ret < 0) {
5701 PDEBUG(D_ERR, "reg_r_i err %d", ret);
5702 gspca_dev->usb_err = ret;
5703 return 0;
5704 }
5850 return gspca_dev->usb_buf[0]; 5705 return gspca_dev->usb_buf[0];
5851} 5706}
5852 5707
@@ -5860,24 +5715,32 @@ static u8 reg_r(struct gspca_dev *gspca_dev,
5860 return ret; 5715 return ret;
5861} 5716}
5862 5717
5863static void reg_w_i(struct usb_device *dev, 5718static void reg_w_i(struct gspca_dev *gspca_dev,
5864 u8 value, 5719 u8 value,
5865 u16 index) 5720 u16 index)
5866{ 5721{
5867 usb_control_msg(dev, 5722 int ret;
5868 usb_sndctrlpipe(dev, 0), 5723
5724 if (gspca_dev->usb_err < 0)
5725 return;
5726 ret = usb_control_msg(gspca_dev->dev,
5727 usb_sndctrlpipe(gspca_dev->dev, 0),
5869 0xa0, 5728 0xa0,
5870 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 5729 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
5871 value, index, NULL, 0, 5730 value, index, NULL, 0,
5872 500); 5731 500);
5732 if (ret < 0) {
5733 PDEBUG(D_ERR, "reg_w_i err %d", ret);
5734 gspca_dev->usb_err = ret;
5735 }
5873} 5736}
5874 5737
5875static void reg_w(struct usb_device *dev, 5738static void reg_w(struct gspca_dev *gspca_dev,
5876 u8 value, 5739 u8 value,
5877 u16 index) 5740 u16 index)
5878{ 5741{
5879 PDEBUG(D_USBO, "reg w [%04x] = %02x", index, value); 5742 PDEBUG(D_USBO, "reg w [%04x] = %02x", index, value);
5880 reg_w_i(dev, value, index); 5743 reg_w_i(gspca_dev, value, index);
5881} 5744}
5882 5745
5883static u16 i2c_read(struct gspca_dev *gspca_dev, 5746static u16 i2c_read(struct gspca_dev *gspca_dev,
@@ -5886,8 +5749,10 @@ static u16 i2c_read(struct gspca_dev *gspca_dev,
5886 u8 retbyte; 5749 u8 retbyte;
5887 u16 retval; 5750 u16 retval;
5888 5751
5889 reg_w_i(gspca_dev->dev, reg, 0x0092); 5752 if (gspca_dev->usb_err < 0)
5890 reg_w_i(gspca_dev->dev, 0x02, 0x0090); /* <- read command */ 5753 return 0;
5754 reg_w_i(gspca_dev, reg, 0x0092);
5755 reg_w_i(gspca_dev, 0x02, 0x0090); /* <- read command */
5891 msleep(20); 5756 msleep(20);
5892 retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ 5757 retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */
5893 if (retbyte != 0x00) 5758 if (retbyte != 0x00)
@@ -5906,10 +5771,12 @@ static u8 i2c_write(struct gspca_dev *gspca_dev,
5906{ 5771{
5907 u8 retbyte; 5772 u8 retbyte;
5908 5773
5909 reg_w_i(gspca_dev->dev, reg, 0x92); 5774 if (gspca_dev->usb_err < 0)
5910 reg_w_i(gspca_dev->dev, valL, 0x93); 5775 return 0;
5911 reg_w_i(gspca_dev->dev, valH, 0x94); 5776 reg_w_i(gspca_dev, reg, 0x92);
5912 reg_w_i(gspca_dev->dev, 0x01, 0x90); /* <- write command */ 5777 reg_w_i(gspca_dev, valL, 0x93);
5778 reg_w_i(gspca_dev, valH, 0x94);
5779 reg_w_i(gspca_dev, 0x01, 0x90); /* <- write command */
5913 msleep(1); 5780 msleep(1);
5914 retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ 5781 retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */
5915 if (retbyte != 0x00) 5782 if (retbyte != 0x00)
@@ -5925,7 +5792,7 @@ static void usb_exchange(struct gspca_dev *gspca_dev,
5925 while (action->req) { 5792 while (action->req) {
5926 switch (action->req) { 5793 switch (action->req) {
5927 case 0xa0: /* write register */ 5794 case 0xa0: /* write register */
5928 reg_w(gspca_dev->dev, action->val, action->idx); 5795 reg_w(gspca_dev, action->val, action->idx);
5929 break; 5796 break;
5930 case 0xa1: /* read status */ 5797 case 0xa1: /* read status */
5931 reg_r(gspca_dev, action->idx); 5798 reg_r(gspca_dev, action->idx);
@@ -5974,38 +5841,37 @@ static void setmatrix(struct gspca_dev *gspca_dev)
5974 static const u8 vf0250_matrix[9] = 5841 static const u8 vf0250_matrix[9] =
5975 {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b}; 5842 {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b};
5976 static const u8 *matrix_tb[SENSOR_MAX] = { 5843 static const u8 *matrix_tb[SENSOR_MAX] = {
5977 adcm2700_matrix, /* SENSOR_ADCM2700 0 */ 5844 [SENSOR_ADCM2700] = adcm2700_matrix,
5978 ov7620_matrix, /* SENSOR_CS2102 1 */ 5845 [SENSOR_CS2102] = ov7620_matrix,
5979 NULL, /* SENSOR_CS2102K 2 */ 5846 [SENSOR_CS2102K] = NULL,
5980 gc0305_matrix, /* SENSOR_GC0305 3 */ 5847 [SENSOR_GC0305] = gc0305_matrix,
5981 NULL, /* SENSOR_HDCS2020b 4 */ 5848 [SENSOR_HDCS2020b] = NULL,
5982 NULL, /* SENSOR_HV7131B 5 */ 5849 [SENSOR_HV7131B] = NULL,
5983 NULL, /* SENSOR_HV7131C 6 */ 5850 [SENSOR_HV7131R] = NULL,
5984 NULL, /* SENSOR_ICM105A 7 */ 5851 [SENSOR_ICM105A] = po2030_matrix,
5985 NULL, /* SENSOR_MC501CB 8 */ 5852 [SENSOR_MC501CB] = NULL,
5986 gc0305_matrix, /* SENSOR_MI0360SOC 9 */ 5853 [SENSOR_MT9V111_1] = gc0305_matrix,
5987 ov7620_matrix, /* SENSOR_OV7620 10 */ 5854 [SENSOR_MT9V111_3] = gc0305_matrix,
5988 NULL, /* SENSOR_OV7630C 11 */ 5855 [SENSOR_OV7620] = ov7620_matrix,
5989 NULL, /* SENSOR_PAS106 12 */ 5856 [SENSOR_OV7630C] = NULL,
5990 pas202b_matrix, /* SENSOR_PAS202B 13 */ 5857 [SENSOR_PAS106] = NULL,
5991 gc0305_matrix, /* SENSOR_PB0330 14 */ 5858 [SENSOR_PAS202B] = pas202b_matrix,
5992 po2030_matrix, /* SENSOR_PO2030 15 */ 5859 [SENSOR_PB0330] = gc0305_matrix,
5993 NULL, /* SENSOR_TAS5130CK 16 */ 5860 [SENSOR_PO2030] = po2030_matrix,
5994 tas5130c_matrix, /* SENSOR_TAS5130CXX 17 */ 5861 [SENSOR_TAS5130C] = tas5130c_matrix,
5995 vf0250_matrix, /* SENSOR_TAS5130C_VF0250 18 */ 5862 [SENSOR_TAS5130C_VF0250] = vf0250_matrix,
5996 }; 5863 };
5997 5864
5998 matrix = matrix_tb[sd->sensor]; 5865 matrix = matrix_tb[sd->sensor];
5999 if (matrix == NULL) 5866 if (matrix == NULL)
6000 return; /* matrix already loaded */ 5867 return; /* matrix already loaded */
6001 for (i = 0; i < ARRAY_SIZE(ov7620_matrix); i++) 5868 for (i = 0; i < ARRAY_SIZE(ov7620_matrix); i++)
6002 reg_w(gspca_dev->dev, matrix[i], 0x010a + i); 5869 reg_w(gspca_dev, matrix[i], 0x010a + i);
6003} 5870}
6004 5871
6005static void setsharpness(struct gspca_dev *gspca_dev) 5872static void setsharpness(struct gspca_dev *gspca_dev)
6006{ 5873{
6007 struct sd *sd = (struct sd *) gspca_dev; 5874 struct sd *sd = (struct sd *) gspca_dev;
6008 struct usb_device *dev = gspca_dev->dev;
6009 int sharpness; 5875 int sharpness;
6010 static const u8 sharpness_tb[][2] = { 5876 static const u8 sharpness_tb[][2] = {
6011 {0x02, 0x03}, 5877 {0x02, 0x03},
@@ -6015,17 +5881,16 @@ static void setsharpness(struct gspca_dev *gspca_dev)
6015 }; 5881 };
6016 5882
6017 sharpness = sd->sharpness; 5883 sharpness = sd->sharpness;
6018 reg_w(dev, sharpness_tb[sharpness][0], 0x01c6); 5884 reg_w(gspca_dev, sharpness_tb[sharpness][0], 0x01c6);
6019 reg_r(gspca_dev, 0x01c8); 5885 reg_r(gspca_dev, 0x01c8);
6020 reg_r(gspca_dev, 0x01c9); 5886 reg_r(gspca_dev, 0x01c9);
6021 reg_r(gspca_dev, 0x01ca); 5887 reg_r(gspca_dev, 0x01ca);
6022 reg_w(dev, sharpness_tb[sharpness][1], 0x01cb); 5888 reg_w(gspca_dev, sharpness_tb[sharpness][1], 0x01cb);
6023} 5889}
6024 5890
6025static void setcontrast(struct gspca_dev *gspca_dev) 5891static void setcontrast(struct gspca_dev *gspca_dev)
6026{ 5892{
6027 struct sd *sd = (struct sd *) gspca_dev; 5893 struct sd *sd = (struct sd *) gspca_dev;
6028 struct usb_device *dev = gspca_dev->dev;
6029 const u8 *Tgamma; 5894 const u8 *Tgamma;
6030 int g, i, brightness, contrast, adj, gp1, gp2; 5895 int g, i, brightness, contrast, adj, gp1, gp2;
6031 u8 gr[16]; 5896 u8 gr[16];
@@ -6063,7 +5928,7 @@ static void setcontrast(struct gspca_dev *gspca_dev)
6063 g = 0xff; 5928 g = 0xff;
6064 else if (g < 0) 5929 else if (g < 0)
6065 g = 0; 5930 g = 0;
6066 reg_w(dev, g, 0x0120 + i); /* gamma */ 5931 reg_w(gspca_dev, g, 0x0120 + i); /* gamma */
6067 if (contrast > 0) 5932 if (contrast > 0)
6068 adj--; 5933 adj--;
6069 else if (contrast < 0) 5934 else if (contrast < 0)
@@ -6077,13 +5942,12 @@ static void setcontrast(struct gspca_dev *gspca_dev)
6077 } 5942 }
6078 gr[15] = (0xff - gp2) / 2; 5943 gr[15] = (0xff - gp2) / 2;
6079 for (i = 0; i < 16; i++) 5944 for (i = 0; i < 16; i++)
6080 reg_w(dev, gr[i], 0x0130 + i); /* gradient */ 5945 reg_w(gspca_dev, gr[i], 0x0130 + i); /* gradient */
6081} 5946}
6082 5947
6083static void setquality(struct gspca_dev *gspca_dev) 5948static void setquality(struct gspca_dev *gspca_dev)
6084{ 5949{
6085 struct sd *sd = (struct sd *) gspca_dev; 5950 struct sd *sd = (struct sd *) gspca_dev;
6086 struct usb_device *dev = gspca_dev->dev;
6087 u8 frxt; 5951 u8 frxt;
6088 5952
6089 switch (sd->sensor) { 5953 switch (sd->sensor) {
@@ -6096,9 +5960,9 @@ static void setquality(struct gspca_dev *gspca_dev)
6096 return; 5960 return;
6097 } 5961 }
6098/*fixme: is it really 0008 0007 0018 for all other sensors? */ 5962/*fixme: is it really 0008 0007 0018 for all other sensors? */
6099 reg_w(dev, QUANT_VAL, 0x0008); 5963 reg_w(gspca_dev, QUANT_VAL, 0x0008);
6100 frxt = 0x30; 5964 frxt = 0x30;
6101 reg_w(dev, frxt, 0x0007); 5965 reg_w(gspca_dev, frxt, 0x0007);
6102#if QUANT_VAL == 0 || QUANT_VAL == 1 || QUANT_VAL == 2 5966#if QUANT_VAL == 0 || QUANT_VAL == 1 || QUANT_VAL == 2
6103 frxt = 0xff; 5967 frxt = 0xff;
6104#elif QUANT_VAL == 3 5968#elif QUANT_VAL == 3
@@ -6108,7 +5972,7 @@ static void setquality(struct gspca_dev *gspca_dev)
6108#else 5972#else
6109 frxt = 0x20; 5973 frxt = 0x20;
6110#endif 5974#endif
6111 reg_w(dev, frxt, 0x0018); 5975 reg_w(gspca_dev, frxt, 0x0018);
6112} 5976}
6113 5977
6114/* Matches the sensor's internal frame rate to the lighting frequency. 5978/* Matches the sensor's internal frame rate to the lighting frequency.
@@ -6116,87 +5980,86 @@ static void setquality(struct gspca_dev *gspca_dev)
6116 * 50Hz, for European and Asian lighting (default) 5980 * 50Hz, for European and Asian lighting (default)
6117 * 60Hz, for American lighting 5981 * 60Hz, for American lighting
6118 * 0 = No Fliker (for outdoore usage) 5982 * 0 = No Fliker (for outdoore usage)
6119 * Returns: 0 for success
6120 */ 5983 */
6121static int setlightfreq(struct gspca_dev *gspca_dev) 5984static void setlightfreq(struct gspca_dev *gspca_dev)
6122{ 5985{
6123 struct sd *sd = (struct sd *) gspca_dev; 5986 struct sd *sd = (struct sd *) gspca_dev;
6124 int i, mode; 5987 int i, mode;
6125 const struct usb_action *zc3_freq; 5988 const struct usb_action *zc3_freq;
6126 static const struct usb_action *freq_tb[SENSOR_MAX][6] = { 5989 static const struct usb_action *freq_tb[SENSOR_MAX][6] = {
6127/* SENSOR_ADCM2700 0 */ 5990 [SENSOR_ADCM2700] =
6128 {adcm2700_NoFliker, adcm2700_NoFliker, 5991 {adcm2700_NoFliker, adcm2700_NoFliker,
6129 adcm2700_50HZ, adcm2700_50HZ, 5992 adcm2700_50HZ, adcm2700_50HZ,
6130 adcm2700_60HZ, adcm2700_60HZ}, 5993 adcm2700_60HZ, adcm2700_60HZ},
6131/* SENSOR_CS2102 1 */ 5994 [SENSOR_CS2102] =
6132 {cs2102_NoFliker, cs2102_NoFlikerScale, 5995 {cs2102_NoFliker, cs2102_NoFlikerScale,
6133 cs2102_50HZ, cs2102_50HZScale, 5996 cs2102_50HZ, cs2102_50HZScale,
6134 cs2102_60HZ, cs2102_60HZScale}, 5997 cs2102_60HZ, cs2102_60HZScale},
6135/* SENSOR_CS2102K 2 */ 5998 [SENSOR_CS2102K] =
6136 {cs2102_NoFliker, cs2102_NoFlikerScale, 5999 {cs2102_NoFliker, cs2102_NoFlikerScale,
6137 NULL, NULL, /* currently disabled */ 6000 NULL, NULL, /* currently disabled */
6138 NULL, NULL}, 6001 NULL, NULL},
6139/* SENSOR_GC0305 3 */ 6002 [SENSOR_GC0305] =
6140 {gc0305_NoFliker, gc0305_NoFliker, 6003 {gc0305_NoFliker, gc0305_NoFliker,
6141 gc0305_50HZ, gc0305_50HZ, 6004 gc0305_50HZ, gc0305_50HZ,
6142 gc0305_60HZ, gc0305_60HZ}, 6005 gc0305_60HZ, gc0305_60HZ},
6143/* SENSOR_HDCS2020b 4 */ 6006 [SENSOR_HDCS2020b] =
6144 {hdcs2020b_NoFliker, hdcs2020b_NoFliker, 6007 {hdcs2020b_NoFliker, hdcs2020b_NoFliker,
6145 hdcs2020b_50HZ, hdcs2020b_50HZ, 6008 hdcs2020b_50HZ, hdcs2020b_50HZ,
6146 hdcs2020b_60HZ, hdcs2020b_60HZ}, 6009 hdcs2020b_60HZ, hdcs2020b_60HZ},
6147/* SENSOR_HV7131B 5 */ 6010 [SENSOR_HV7131B] =
6148 {hv7131b_NoFliker, hv7131b_NoFlikerScale, 6011 {hv7131b_NoFliker, hv7131b_NoFlikerScale,
6149 hv7131b_50HZ, hv7131b_50HZScale, 6012 hv7131b_50HZ, hv7131b_50HZScale,
6150 hv7131b_60HZ, hv7131b_60HZScale}, 6013 hv7131b_60HZ, hv7131b_60HZScale},
6151/* SENSOR_HV7131C 6 */ 6014 [SENSOR_HV7131R] =
6152 {NULL, NULL, 6015 {hv7131r_NoFliker, hv7131r_NoFlikerScale,
6153 NULL, NULL, 6016 hv7131r_50HZ, hv7131r_50HZScale,
6154 NULL, NULL}, 6017 hv7131r_60HZ, hv7131r_60HZScale},
6155/* SENSOR_ICM105A 7 */ 6018 [SENSOR_ICM105A] =
6156 {icm105a_NoFliker, icm105a_NoFlikerScale, 6019 {icm105a_NoFliker, icm105a_NoFlikerScale,
6157 icm105a_50HZ, icm105a_50HZScale, 6020 icm105a_50HZ, icm105a_50HZScale,
6158 icm105a_60HZ, icm105a_60HZScale}, 6021 icm105a_60HZ, icm105a_60HZScale},
6159/* SENSOR_MC501CB 8 */ 6022 [SENSOR_MC501CB] =
6160 {mc501cb_NoFliker, mc501cb_NoFlikerScale, 6023 {mc501cb_NoFliker, mc501cb_NoFlikerScale,
6161 mc501cb_50HZ, mc501cb_50HZScale, 6024 mc501cb_50HZ, mc501cb_50HZScale,
6162 mc501cb_60HZ, mc501cb_60HZScale}, 6025 mc501cb_60HZ, mc501cb_60HZScale},
6163/* SENSOR_MI0360SOC 9 */ 6026 [SENSOR_MT9V111_1] =
6164 {mi360soc_AENoFliker, mi360soc_AENoFlikerScale, 6027 {mt9v111_1_AENoFliker, mt9v111_1_AENoFlikerScale,
6165 mi360soc_AE50HZ, mi360soc_AE50HZScale, 6028 mt9v111_1_AE50HZ, mt9v111_1_AE50HZScale,
6166 mi360soc_AE60HZ, mi360soc_AE60HZScale}, 6029 mt9v111_1_AE60HZ, mt9v111_1_AE60HZScale},
6167/* SENSOR_OV7620 10 */ 6030 [SENSOR_MT9V111_3] =
6031 {mt9v111_3_AENoFliker, mt9v111_3_AENoFlikerScale,
6032 mt9v111_3_AE50HZ, mt9v111_3_AE50HZScale,
6033 mt9v111_3_AE60HZ, mt9v111_3_AE60HZScale},
6034 [SENSOR_OV7620] =
6168 {ov7620_NoFliker, ov7620_NoFliker, 6035 {ov7620_NoFliker, ov7620_NoFliker,
6169 ov7620_50HZ, ov7620_50HZ, 6036 ov7620_50HZ, ov7620_50HZ,
6170 ov7620_60HZ, ov7620_60HZ}, 6037 ov7620_60HZ, ov7620_60HZ},
6171/* SENSOR_OV7630C 11 */ 6038 [SENSOR_OV7630C] =
6172 {NULL, NULL, 6039 {NULL, NULL,
6173 NULL, NULL, 6040 NULL, NULL,
6174 NULL, NULL}, 6041 NULL, NULL},
6175/* SENSOR_PAS106 12 */ 6042 [SENSOR_PAS106] =
6176 {pas106b_NoFliker, pas106b_NoFliker, 6043 {pas106b_NoFliker, pas106b_NoFliker,
6177 pas106b_50HZ, pas106b_50HZ, 6044 pas106b_50HZ, pas106b_50HZ,
6178 pas106b_60HZ, pas106b_60HZ}, 6045 pas106b_60HZ, pas106b_60HZ},
6179/* SENSOR_PAS202B 13 */ 6046 [SENSOR_PAS202B] =
6180 {pas202b_NoFliker, pas202b_NoFlikerScale, 6047 {pas202b_NoFliker, pas202b_NoFlikerScale,
6181 pas202b_50HZ, pas202b_50HZScale, 6048 pas202b_50HZ, pas202b_50HZScale,
6182 pas202b_60HZ, pas202b_60HZScale}, 6049 pas202b_60HZ, pas202b_60HZScale},
6183/* SENSOR_PB0330 14 */ 6050 [SENSOR_PB0330] =
6184 {pb0330_NoFliker, pb0330_NoFlikerScale, 6051 {pb0330_NoFliker, pb0330_NoFlikerScale,
6185 pb0330_50HZ, pb0330_50HZScale, 6052 pb0330_50HZ, pb0330_50HZScale,
6186 pb0330_60HZ, pb0330_60HZScale}, 6053 pb0330_60HZ, pb0330_60HZScale},
6187/* SENSOR_PO2030 15 */ 6054 [SENSOR_PO2030] =
6188 {po2030_NoFliker, po2030_NoFliker, 6055 {po2030_NoFliker, po2030_NoFliker,
6189 po2030_50HZ, po2030_50HZ, 6056 po2030_50HZ, po2030_50HZ,
6190 po2030_60HZ, po2030_60HZ}, 6057 po2030_60HZ, po2030_60HZ},
6191/* SENSOR_TAS5130CK 16 */ 6058 [SENSOR_TAS5130C] =
6192 {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale, 6059 {tas5130c_NoFliker, tas5130c_NoFlikerScale,
6193 tas5130cxx_50HZ, tas5130cxx_50HZScale, 6060 tas5130c_50HZ, tas5130c_50HZScale,
6194 tas5130cxx_60HZ, tas5130cxx_60HZScale}, 6061 tas5130c_60HZ, tas5130c_60HZScale},
6195/* SENSOR_TAS5130CXX 17 */ 6062 [SENSOR_TAS5130C_VF0250] =
6196 {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale,
6197 tas5130cxx_50HZ, tas5130cxx_50HZScale,
6198 tas5130cxx_60HZ, tas5130cxx_60HZScale},
6199/* SENSOR_TAS5130C_VF0250 18 */
6200 {tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale, 6063 {tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale,
6201 tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale, 6064 tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale,
6202 tas5130c_vf0250_60HZ, tas5130c_vf0250_60HZScale}, 6065 tas5130c_vf0250_60HZ, tas5130c_vf0250_60HZScale},
@@ -6207,29 +6070,28 @@ static int setlightfreq(struct gspca_dev *gspca_dev)
6207 if (mode) 6070 if (mode)
6208 i++; /* 320x240 */ 6071 i++; /* 320x240 */
6209 zc3_freq = freq_tb[sd->sensor][i]; 6072 zc3_freq = freq_tb[sd->sensor][i];
6210 if (zc3_freq != NULL) { 6073 if (zc3_freq == NULL)
6211 usb_exchange(gspca_dev, zc3_freq); 6074 return;
6212 switch (sd->sensor) { 6075 usb_exchange(gspca_dev, zc3_freq);
6213 case SENSOR_GC0305: 6076 switch (sd->sensor) {
6214 if (mode /* if 320x240 */ 6077 case SENSOR_GC0305:
6215 && sd->lightfreq == 1) /* and 50Hz */ 6078 if (mode /* if 320x240 */
6216 reg_w(gspca_dev->dev, 0x85, 0x018d); 6079 && sd->lightfreq == 1) /* and 50Hz */
6217 /* win: 0x80, 0x018d */ 6080 reg_w(gspca_dev, 0x85, 0x018d);
6218 break; 6081 /* win: 0x80, 0x018d */
6219 case SENSOR_OV7620: 6082 break;
6220 if (!mode) { /* if 640x480 */ 6083 case SENSOR_OV7620:
6221 if (sd->lightfreq != 0) /* and 50 or 60 Hz */ 6084 if (!mode) { /* if 640x480 */
6222 reg_w(gspca_dev->dev, 0x40, 0x0002); 6085 if (sd->lightfreq != 0) /* and 50 or 60 Hz */
6223 else 6086 reg_w(gspca_dev, 0x40, 0x0002);
6224 reg_w(gspca_dev->dev, 0x44, 0x0002); 6087 else
6225 } 6088 reg_w(gspca_dev, 0x44, 0x0002);
6226 break;
6227 case SENSOR_PAS202B:
6228 reg_w(gspca_dev->dev, 0x00, 0x01a7);
6229 break;
6230 } 6089 }
6090 break;
6091 case SENSOR_PAS202B:
6092 reg_w(gspca_dev, 0x00, 0x01a7);
6093 break;
6231 } 6094 }
6232 return 0;
6233} 6095}
6234 6096
6235static void setautogain(struct gspca_dev *gspca_dev) 6097static void setautogain(struct gspca_dev *gspca_dev)
@@ -6241,45 +6103,46 @@ static void setautogain(struct gspca_dev *gspca_dev)
6241 autoval = 0x42; 6103 autoval = 0x42;
6242 else 6104 else
6243 autoval = 0x02; 6105 autoval = 0x02;
6244 reg_w(gspca_dev->dev, autoval, 0x0180); 6106 reg_w(gspca_dev, autoval, 0x0180);
6245} 6107}
6246 6108
6247static void send_unknown(struct usb_device *dev, int sensor) 6109static void send_unknown(struct gspca_dev *gspca_dev, int sensor)
6248{ 6110{
6249 reg_w(dev, 0x01, 0x0000); /* led off */ 6111 reg_w(gspca_dev, 0x01, 0x0000); /* led off */
6250 switch (sensor) { 6112 switch (sensor) {
6251 case SENSOR_PAS106: 6113 case SENSOR_PAS106:
6252 reg_w(dev, 0x03, 0x003a); 6114 reg_w(gspca_dev, 0x03, 0x003a);
6253 reg_w(dev, 0x0c, 0x003b); 6115 reg_w(gspca_dev, 0x0c, 0x003b);
6254 reg_w(dev, 0x08, 0x0038); 6116 reg_w(gspca_dev, 0x08, 0x0038);
6255 break; 6117 break;
6256 case SENSOR_ADCM2700: 6118 case SENSOR_ADCM2700:
6257 case SENSOR_GC0305: 6119 case SENSOR_GC0305:
6258 case SENSOR_OV7620: 6120 case SENSOR_OV7620:
6259 case SENSOR_MI0360SOC: 6121 case SENSOR_MT9V111_1:
6122 case SENSOR_MT9V111_3:
6260 case SENSOR_PB0330: 6123 case SENSOR_PB0330:
6261 case SENSOR_PO2030: 6124 case SENSOR_PO2030:
6262 reg_w(dev, 0x0d, 0x003a); 6125 reg_w(gspca_dev, 0x0d, 0x003a);
6263 reg_w(dev, 0x02, 0x003b); 6126 reg_w(gspca_dev, 0x02, 0x003b);
6264 reg_w(dev, 0x00, 0x0038); 6127 reg_w(gspca_dev, 0x00, 0x0038);
6265 break; 6128 break;
6266 case SENSOR_PAS202B: 6129 case SENSOR_PAS202B:
6267 reg_w(dev, 0x03, 0x003b); 6130 reg_w(gspca_dev, 0x03, 0x003b);
6268 reg_w(dev, 0x0c, 0x003a); 6131 reg_w(gspca_dev, 0x0c, 0x003a);
6269 reg_w(dev, 0x0b, 0x0039); 6132 reg_w(gspca_dev, 0x0b, 0x0039);
6270 reg_w(dev, 0x0b, 0x0038); 6133 reg_w(gspca_dev, 0x0b, 0x0038);
6271 break; 6134 break;
6272 } 6135 }
6273} 6136}
6274 6137
6275/* start probe 2 wires */ 6138/* start probe 2 wires */
6276static void start_2wr_probe(struct usb_device *dev, int sensor) 6139static void start_2wr_probe(struct gspca_dev *gspca_dev, int sensor)
6277{ 6140{
6278 reg_w(dev, 0x01, 0x0000); 6141 reg_w(gspca_dev, 0x01, 0x0000);
6279 reg_w(dev, sensor, 0x0010); 6142 reg_w(gspca_dev, sensor, 0x0010);
6280 reg_w(dev, 0x01, 0x0001); 6143 reg_w(gspca_dev, 0x01, 0x0001);
6281 reg_w(dev, 0x03, 0x0012); 6144 reg_w(gspca_dev, 0x03, 0x0012);
6282 reg_w(dev, 0x01, 0x0012); 6145 reg_w(gspca_dev, 0x01, 0x0012);
6283/* msleep(2); */ 6146/* msleep(2); */
6284} 6147}
6285 6148
@@ -6287,14 +6150,14 @@ static int sif_probe(struct gspca_dev *gspca_dev)
6287{ 6150{
6288 u16 checkword; 6151 u16 checkword;
6289 6152
6290 start_2wr_probe(gspca_dev->dev, 0x0f); /* PAS106 */ 6153 start_2wr_probe(gspca_dev, 0x0f); /* PAS106 */
6291 reg_w(gspca_dev->dev, 0x08, 0x008d); 6154 reg_w(gspca_dev, 0x08, 0x008d);
6292 msleep(150); 6155 msleep(150);
6293 checkword = ((i2c_read(gspca_dev, 0x00) & 0x0f) << 4) 6156 checkword = ((i2c_read(gspca_dev, 0x00) & 0x0f) << 4)
6294 | ((i2c_read(gspca_dev, 0x01) & 0xf0) >> 4); 6157 | ((i2c_read(gspca_dev, 0x01) & 0xf0) >> 4);
6295 PDEBUG(D_PROBE, "probe sif 0x%04x", checkword); 6158 PDEBUG(D_PROBE, "probe sif 0x%04x", checkword);
6296 if (checkword == 0x0007) { 6159 if (checkword == 0x0007) {
6297 send_unknown(gspca_dev->dev, SENSOR_PAS106); 6160 send_unknown(gspca_dev, SENSOR_PAS106);
6298 return 0x0f; /* PAS106 */ 6161 return 0x0f; /* PAS106 */
6299 } 6162 }
6300 return -1; 6163 return -1;
@@ -6302,23 +6165,22 @@ static int sif_probe(struct gspca_dev *gspca_dev)
6302 6165
6303static int vga_2wr_probe(struct gspca_dev *gspca_dev) 6166static int vga_2wr_probe(struct gspca_dev *gspca_dev)
6304{ 6167{
6305 struct usb_device *dev = gspca_dev->dev;
6306 u16 retword; 6168 u16 retword;
6307 6169
6308 start_2wr_probe(dev, 0x00); /* HV7131B */ 6170 start_2wr_probe(gspca_dev, 0x00); /* HV7131B */
6309 i2c_write(gspca_dev, 0x01, 0xaa, 0x00); 6171 i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
6310 retword = i2c_read(gspca_dev, 0x01); 6172 retword = i2c_read(gspca_dev, 0x01);
6311 if (retword != 0) 6173 if (retword != 0)
6312 return 0x00; /* HV7131B */ 6174 return 0x00; /* HV7131B */
6313 6175
6314 start_2wr_probe(dev, 0x04); /* CS2102 */ 6176 start_2wr_probe(gspca_dev, 0x04); /* CS2102 */
6315 i2c_write(gspca_dev, 0x01, 0xaa, 0x00); 6177 i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
6316 retword = i2c_read(gspca_dev, 0x01); 6178 retword = i2c_read(gspca_dev, 0x01);
6317 if (retword != 0) 6179 if (retword != 0)
6318 return 0x04; /* CS2102 */ 6180 return 0x04; /* CS2102 */
6319 6181
6320 start_2wr_probe(dev, 0x06); /* OmniVision */ 6182 start_2wr_probe(gspca_dev, 0x06); /* OmniVision */
6321 reg_w(dev, 0x08, 0x008d); 6183 reg_w(gspca_dev, 0x08, 0x008d);
6322 i2c_write(gspca_dev, 0x11, 0xaa, 0x00); 6184 i2c_write(gspca_dev, 0x11, 0xaa, 0x00);
6323 retword = i2c_read(gspca_dev, 0x11); 6185 retword = i2c_read(gspca_dev, 0x11);
6324 if (retword != 0) { 6186 if (retword != 0) {
@@ -6327,14 +6189,14 @@ static int vga_2wr_probe(struct gspca_dev *gspca_dev)
6327 goto ov_check; 6189 goto ov_check;
6328 } 6190 }
6329 6191
6330 start_2wr_probe(dev, 0x08); /* HDCS2020 */ 6192 start_2wr_probe(gspca_dev, 0x08); /* HDCS2020 */
6331 i2c_write(gspca_dev, 0x1c, 0x00, 0x00); 6193 i2c_write(gspca_dev, 0x1c, 0x00, 0x00);
6332 i2c_write(gspca_dev, 0x15, 0xaa, 0x00); 6194 i2c_write(gspca_dev, 0x15, 0xaa, 0x00);
6333 retword = i2c_read(gspca_dev, 0x15); 6195 retword = i2c_read(gspca_dev, 0x15);
6334 if (retword != 0) 6196 if (retword != 0)
6335 return 0x08; /* HDCS2020 */ 6197 return 0x08; /* HDCS2020 */
6336 6198
6337 start_2wr_probe(dev, 0x0a); /* PB0330 */ 6199 start_2wr_probe(gspca_dev, 0x0a); /* PB0330 */
6338 i2c_write(gspca_dev, 0x07, 0xaa, 0xaa); 6200 i2c_write(gspca_dev, 0x07, 0xaa, 0xaa);
6339 retword = i2c_read(gspca_dev, 0x07); 6201 retword = i2c_read(gspca_dev, 0x07);
6340 if (retword != 0) 6202 if (retword != 0)
@@ -6346,23 +6208,23 @@ static int vga_2wr_probe(struct gspca_dev *gspca_dev)
6346 if (retword != 0) 6208 if (retword != 0)
6347 return 0x0a; /* PB0330 ?? */ 6209 return 0x0a; /* PB0330 ?? */
6348 6210
6349 start_2wr_probe(dev, 0x0c); /* ICM105A */ 6211 start_2wr_probe(gspca_dev, 0x0c); /* ICM105A */
6350 i2c_write(gspca_dev, 0x01, 0x11, 0x00); 6212 i2c_write(gspca_dev, 0x01, 0x11, 0x00);
6351 retword = i2c_read(gspca_dev, 0x01); 6213 retword = i2c_read(gspca_dev, 0x01);
6352 if (retword != 0) 6214 if (retword != 0)
6353 return 0x0c; /* ICM105A */ 6215 return 0x0c; /* ICM105A */
6354 6216
6355 start_2wr_probe(dev, 0x0e); /* PAS202BCB */ 6217 start_2wr_probe(gspca_dev, 0x0e); /* PAS202BCB */
6356 reg_w(dev, 0x08, 0x008d); 6218 reg_w(gspca_dev, 0x08, 0x008d);
6357 i2c_write(gspca_dev, 0x03, 0xaa, 0x00); 6219 i2c_write(gspca_dev, 0x03, 0xaa, 0x00);
6358 msleep(50); 6220 msleep(50);
6359 retword = i2c_read(gspca_dev, 0x03); 6221 retword = i2c_read(gspca_dev, 0x03);
6360 if (retword != 0) { 6222 if (retword != 0) {
6361 send_unknown(dev, SENSOR_PAS202B); 6223 send_unknown(gspca_dev, SENSOR_PAS202B);
6362 return 0x0e; /* PAS202BCB */ 6224 return 0x0e; /* PAS202BCB */
6363 } 6225 }
6364 6226
6365 start_2wr_probe(dev, 0x02); /* TAS5130C */ 6227 start_2wr_probe(gspca_dev, 0x02); /* TAS5130C */
6366 i2c_write(gspca_dev, 0x01, 0xaa, 0x00); 6228 i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
6367 retword = i2c_read(gspca_dev, 0x01); 6229 retword = i2c_read(gspca_dev, 0x01);
6368 if (retword != 0) 6230 if (retword != 0)
@@ -6371,20 +6233,20 @@ ov_check:
6371 reg_r(gspca_dev, 0x0010); /* ?? */ 6233 reg_r(gspca_dev, 0x0010); /* ?? */
6372 reg_r(gspca_dev, 0x0010); 6234 reg_r(gspca_dev, 0x0010);
6373 6235
6374 reg_w(dev, 0x01, 0x0000); 6236 reg_w(gspca_dev, 0x01, 0x0000);
6375 reg_w(dev, 0x01, 0x0001); 6237 reg_w(gspca_dev, 0x01, 0x0001);
6376 reg_w(dev, 0x06, 0x0010); /* OmniVision */ 6238 reg_w(gspca_dev, 0x06, 0x0010); /* OmniVision */
6377 reg_w(dev, 0xa1, 0x008b); 6239 reg_w(gspca_dev, 0xa1, 0x008b);
6378 reg_w(dev, 0x08, 0x008d); 6240 reg_w(gspca_dev, 0x08, 0x008d);
6379 msleep(500); 6241 msleep(500);
6380 reg_w(dev, 0x01, 0x0012); 6242 reg_w(gspca_dev, 0x01, 0x0012);
6381 i2c_write(gspca_dev, 0x12, 0x80, 0x00); /* sensor reset */ 6243 i2c_write(gspca_dev, 0x12, 0x80, 0x00); /* sensor reset */
6382 retword = i2c_read(gspca_dev, 0x0a) << 8; 6244 retword = i2c_read(gspca_dev, 0x0a) << 8;
6383 retword |= i2c_read(gspca_dev, 0x0b); 6245 retword |= i2c_read(gspca_dev, 0x0b);
6384 PDEBUG(D_PROBE, "probe 2wr ov vga 0x%04x", retword); 6246 PDEBUG(D_PROBE, "probe 2wr ov vga 0x%04x", retword);
6385 switch (retword) { 6247 switch (retword) {
6386 case 0x7631: /* OV7630C */ 6248 case 0x7631: /* OV7630C */
6387 reg_w(dev, 0x06, 0x0010); 6249 reg_w(gspca_dev, 0x06, 0x0010);
6388 break; 6250 break;
6389 case 0x7620: /* OV7620 */ 6251 case 0x7620: /* OV7620 */
6390 case 0x7648: /* OV7648 */ 6252 case 0x7648: /* OV7648 */
@@ -6401,32 +6263,31 @@ struct sensor_by_chipset_revision {
6401}; 6263};
6402static const struct sensor_by_chipset_revision chipset_revision_sensor[] = { 6264static const struct sensor_by_chipset_revision chipset_revision_sensor[] = {
6403 {0xc000, 0x12}, /* TAS5130C */ 6265 {0xc000, 0x12}, /* TAS5130C */
6404 {0xc001, 0x13}, /* MI0360SOC */ 6266 {0xc001, 0x13}, /* MT9V111 */
6405 {0xe001, 0x13}, 6267 {0xe001, 0x13},
6406 {0x8001, 0x13}, 6268 {0x8001, 0x13},
6407 {0x8000, 0x14}, /* CS2102K */ 6269 {0x8000, 0x14}, /* CS2102K */
6408 {0x8400, 0x15}, /* TAS5130K */ 6270 {0x8400, 0x15}, /* MT9V111 */
6409 {0xe400, 0x15}, 6271 {0xe400, 0x15},
6410}; 6272};
6411 6273
6412static int vga_3wr_probe(struct gspca_dev *gspca_dev) 6274static int vga_3wr_probe(struct gspca_dev *gspca_dev)
6413{ 6275{
6414 struct sd *sd = (struct sd *) gspca_dev; 6276 struct sd *sd = (struct sd *) gspca_dev;
6415 struct usb_device *dev = gspca_dev->dev;
6416 int i; 6277 int i;
6417 u8 retbyte; 6278 u8 retbyte;
6418 u16 retword; 6279 u16 retword;
6419 6280
6420/*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/ 6281/*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/
6421 reg_w(dev, 0x02, 0x0010); 6282 reg_w(gspca_dev, 0x02, 0x0010);
6422 reg_r(gspca_dev, 0x0010); 6283 reg_r(gspca_dev, 0x0010);
6423 reg_w(dev, 0x01, 0x0000); 6284 reg_w(gspca_dev, 0x01, 0x0000);
6424 reg_w(dev, 0x00, 0x0010); 6285 reg_w(gspca_dev, 0x00, 0x0010);
6425 reg_w(dev, 0x01, 0x0001); 6286 reg_w(gspca_dev, 0x01, 0x0001);
6426 reg_w(dev, 0x91, 0x008b); 6287 reg_w(gspca_dev, 0x91, 0x008b);
6427 reg_w(dev, 0x03, 0x0012); 6288 reg_w(gspca_dev, 0x03, 0x0012);
6428 reg_w(dev, 0x01, 0x0012); 6289 reg_w(gspca_dev, 0x01, 0x0012);
6429 reg_w(dev, 0x05, 0x0012); 6290 reg_w(gspca_dev, 0x05, 0x0012);
6430 retword = i2c_read(gspca_dev, 0x14); 6291 retword = i2c_read(gspca_dev, 0x14);
6431 if (retword != 0) 6292 if (retword != 0)
6432 return 0x11; /* HV7131R */ 6293 return 0x11; /* HV7131R */
@@ -6437,93 +6298,90 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev)
6437 if (retword != 0) 6298 if (retword != 0)
6438 return 0x11; /* HV7131R */ 6299 return 0x11; /* HV7131R */
6439 6300
6440 reg_w(dev, 0x02, 0x0010); 6301 reg_w(gspca_dev, 0x02, 0x0010);
6441 retword = reg_r(gspca_dev, 0x000b) << 8; 6302 retword = reg_r(gspca_dev, 0x000b) << 8;
6442 retword |= reg_r(gspca_dev, 0x000a); 6303 retword |= reg_r(gspca_dev, 0x000a);
6443 PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", retword); 6304 PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", retword);
6444 reg_r(gspca_dev, 0x0010); 6305 reg_r(gspca_dev, 0x0010);
6445 /* value 0x4001 is meaningless */ 6306 if ((retword & 0xff00) == 0x6400)
6446 if (retword != 0x4001) { 6307 return 0x02; /* TAS5130C */
6447 if ((retword & 0xff00) == 0x6400) 6308 for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) {
6448 return 0x02; /* TAS5130C */ 6309 if (chipset_revision_sensor[i].revision == retword) {
6449 for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) { 6310 sd->chip_revision = retword;
6450 if (chipset_revision_sensor[i].revision == retword) { 6311 send_unknown(gspca_dev, SENSOR_PB0330);
6451 sd->chip_revision = retword; 6312 return chipset_revision_sensor[i]
6452 send_unknown(dev, SENSOR_PB0330); 6313 .internal_sensor_id;
6453 return chipset_revision_sensor[i]
6454 .internal_sensor_id;
6455 }
6456 } 6314 }
6457 } 6315 }
6458 6316
6459 reg_w(dev, 0x01, 0x0000); /* check PB0330 */ 6317 reg_w(gspca_dev, 0x01, 0x0000); /* check PB0330 */
6460 reg_w(dev, 0x01, 0x0001); 6318 reg_w(gspca_dev, 0x01, 0x0001);
6461 reg_w(dev, 0xdd, 0x008b); 6319 reg_w(gspca_dev, 0xdd, 0x008b);
6462 reg_w(dev, 0x0a, 0x0010); 6320 reg_w(gspca_dev, 0x0a, 0x0010);
6463 reg_w(dev, 0x03, 0x0012); 6321 reg_w(gspca_dev, 0x03, 0x0012);
6464 reg_w(dev, 0x01, 0x0012); 6322 reg_w(gspca_dev, 0x01, 0x0012);
6465 retword = i2c_read(gspca_dev, 0x00); 6323 retword = i2c_read(gspca_dev, 0x00);
6466 if (retword != 0) { 6324 if (retword != 0) {
6467 PDEBUG(D_PROBE, "probe 3wr vga type 0a ?"); 6325 PDEBUG(D_PROBE, "probe 3wr vga type 0a");
6468 return 0x0a; /* PB0330 */ 6326 return 0x0a; /* PB0330 */
6469 } 6327 }
6470 6328
6471 reg_w(dev, 0x01, 0x0000); 6329 reg_w(gspca_dev, 0x01, 0x0000);
6472 reg_w(dev, 0x01, 0x0001); 6330 reg_w(gspca_dev, 0x01, 0x0001);
6473 reg_w(dev, 0x98, 0x008b); 6331 reg_w(gspca_dev, 0x98, 0x008b);
6474 reg_w(dev, 0x01, 0x0010); 6332 reg_w(gspca_dev, 0x01, 0x0010);
6475 reg_w(dev, 0x03, 0x0012); 6333 reg_w(gspca_dev, 0x03, 0x0012);
6476 msleep(2); 6334 msleep(2);
6477 reg_w(dev, 0x01, 0x0012); 6335 reg_w(gspca_dev, 0x01, 0x0012);
6478 retword = i2c_read(gspca_dev, 0x00); 6336 retword = i2c_read(gspca_dev, 0x00);
6479 if (retword != 0) { 6337 if (retword != 0) {
6480 PDEBUG(D_PROBE, "probe 3wr vga type %02x", retword); 6338 PDEBUG(D_PROBE, "probe 3wr vga type %02x", retword);
6481 if (retword == 0x0011) /* VF0250 */ 6339 if (retword == 0x0011) /* VF0250 */
6482 return 0x0250; 6340 return 0x0250;
6483 if (retword == 0x0029) /* gc0305 */ 6341 if (retword == 0x0029) /* gc0305 */
6484 send_unknown(dev, SENSOR_GC0305); 6342 send_unknown(gspca_dev, SENSOR_GC0305);
6485 return retword; 6343 return retword;
6486 } 6344 }
6487 6345
6488 reg_w(dev, 0x01, 0x0000); /* check OmniVision */ 6346 reg_w(gspca_dev, 0x01, 0x0000); /* check OmniVision */
6489 reg_w(dev, 0x01, 0x0001); 6347 reg_w(gspca_dev, 0x01, 0x0001);
6490 reg_w(dev, 0xa1, 0x008b); 6348 reg_w(gspca_dev, 0xa1, 0x008b);
6491 reg_w(dev, 0x08, 0x008d); 6349 reg_w(gspca_dev, 0x08, 0x008d);
6492 reg_w(dev, 0x06, 0x0010); 6350 reg_w(gspca_dev, 0x06, 0x0010);
6493 reg_w(dev, 0x01, 0x0012); 6351 reg_w(gspca_dev, 0x01, 0x0012);
6494 reg_w(dev, 0x05, 0x0012); 6352 reg_w(gspca_dev, 0x05, 0x0012);
6495 if (i2c_read(gspca_dev, 0x1c) == 0x007f /* OV7610 - manufacturer ID */ 6353 if (i2c_read(gspca_dev, 0x1c) == 0x007f /* OV7610 - manufacturer ID */
6496 && i2c_read(gspca_dev, 0x1d) == 0x00a2) { 6354 && i2c_read(gspca_dev, 0x1d) == 0x00a2) {
6497 send_unknown(dev, SENSOR_OV7620); 6355 send_unknown(gspca_dev, SENSOR_OV7620);
6498 return 0x06; /* OmniVision confirm ? */ 6356 return 0x06; /* OmniVision confirm ? */
6499 } 6357 }
6500 6358
6501 reg_w(dev, 0x01, 0x0000); 6359 reg_w(gspca_dev, 0x01, 0x0000);
6502 reg_w(dev, 0x00, 0x0002); 6360 reg_w(gspca_dev, 0x00, 0x0002);
6503 reg_w(dev, 0x01, 0x0010); 6361 reg_w(gspca_dev, 0x01, 0x0010);
6504 reg_w(dev, 0x01, 0x0001); 6362 reg_w(gspca_dev, 0x01, 0x0001);
6505 reg_w(dev, 0xee, 0x008b); 6363 reg_w(gspca_dev, 0xee, 0x008b);
6506 reg_w(dev, 0x03, 0x0012); 6364 reg_w(gspca_dev, 0x03, 0x0012);
6507 reg_w(dev, 0x01, 0x0012); 6365 reg_w(gspca_dev, 0x01, 0x0012);
6508 reg_w(dev, 0x05, 0x0012); 6366 reg_w(gspca_dev, 0x05, 0x0012);
6509 retword = i2c_read(gspca_dev, 0x00) << 8; /* ID 0 */ 6367 retword = i2c_read(gspca_dev, 0x00) << 8; /* ID 0 */
6510 retword |= i2c_read(gspca_dev, 0x01); /* ID 1 */ 6368 retword |= i2c_read(gspca_dev, 0x01); /* ID 1 */
6511 PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", retword); 6369 PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", retword);
6512 if (retword == 0x2030) { 6370 if (retword == 0x2030) {
6513 retbyte = i2c_read(gspca_dev, 0x02); /* revision number */ 6371 retbyte = i2c_read(gspca_dev, 0x02); /* revision number */
6514 PDEBUG(D_PROBE, "sensor PO2030 rev 0x%02x", retbyte); 6372 PDEBUG(D_PROBE, "sensor PO2030 rev 0x%02x", retbyte);
6515 send_unknown(dev, SENSOR_PO2030); 6373 send_unknown(gspca_dev, SENSOR_PO2030);
6516 return retword; 6374 return retword;
6517 } 6375 }
6518 6376
6519 reg_w(dev, 0x01, 0x0000); 6377 reg_w(gspca_dev, 0x01, 0x0000);
6520 reg_w(dev, 0x0a, 0x0010); 6378 reg_w(gspca_dev, 0x0a, 0x0010);
6521 reg_w(dev, 0xd3, 0x008b); 6379 reg_w(gspca_dev, 0xd3, 0x008b);
6522 reg_w(dev, 0x01, 0x0001); 6380 reg_w(gspca_dev, 0x01, 0x0001);
6523 reg_w(dev, 0x03, 0x0012); 6381 reg_w(gspca_dev, 0x03, 0x0012);
6524 reg_w(dev, 0x01, 0x0012); 6382 reg_w(gspca_dev, 0x01, 0x0012);
6525 reg_w(dev, 0x05, 0x0012); 6383 reg_w(gspca_dev, 0x05, 0x0012);
6526 reg_w(dev, 0xd3, 0x008b); 6384 reg_w(gspca_dev, 0xd3, 0x008b);
6527 retword = i2c_read(gspca_dev, 0x01); 6385 retword = i2c_read(gspca_dev, 0x01);
6528 if (retword != 0) { 6386 if (retword != 0) {
6529 PDEBUG(D_PROBE, "probe 3wr vga type 0a ? ret: %04x", retword); 6387 PDEBUG(D_PROBE, "probe 3wr vga type 0a ? ret: %04x", retword);
@@ -6560,54 +6418,74 @@ static int sd_config(struct gspca_dev *gspca_dev,
6560 const struct usb_device_id *id) 6418 const struct usb_device_id *id)
6561{ 6419{
6562 struct sd *sd = (struct sd *) gspca_dev; 6420 struct sd *sd = (struct sd *) gspca_dev;
6421
6422 if (id->idProduct == 0x301b)
6423 sd->bridge = BRIDGE_ZC301;
6424 else
6425 sd->bridge = BRIDGE_ZC303;
6426
6427 /* define some sensors from the vendor/product */
6428 sd->sensor = id->driver_info;
6429
6430 sd->sharpness = SHARPNESS_DEF;
6431 sd->brightness = BRIGHTNESS_DEF;
6432 sd->contrast = CONTRAST_DEF;
6433 sd->autogain = AUTOGAIN_DEF;
6434 sd->lightfreq = FREQ_DEF;
6435 sd->quality = QUALITY_DEF;
6436
6437 return 0;
6438}
6439
6440/* this function is called at probe and resume time */
6441static int sd_init(struct gspca_dev *gspca_dev)
6442{
6443 struct sd *sd = (struct sd *) gspca_dev;
6563 struct cam *cam; 6444 struct cam *cam;
6564 int sensor; 6445 int sensor;
6565 static const u8 gamma[SENSOR_MAX] = { 6446 static const u8 gamma[SENSOR_MAX] = {
6566 4, /* SENSOR_ADCM2700 0 */ 6447 [SENSOR_ADCM2700] = 4,
6567 4, /* SENSOR_CS2102 1 */ 6448 [SENSOR_CS2102] = 4,
6568 5, /* SENSOR_CS2102K 2 */ 6449 [SENSOR_CS2102K] = 5,
6569 4, /* SENSOR_GC0305 3 */ 6450 [SENSOR_GC0305] = 4,
6570 4, /* SENSOR_HDCS2020b 4 */ 6451 [SENSOR_HDCS2020b] = 4,
6571 4, /* SENSOR_HV7131B 5 */ 6452 [SENSOR_HV7131B] = 4,
6572 4, /* SENSOR_HV7131C 6 */ 6453 [SENSOR_HV7131R] = 4,
6573 4, /* SENSOR_ICM105A 7 */ 6454 [SENSOR_ICM105A] = 4,
6574 4, /* SENSOR_MC501CB 8 */ 6455 [SENSOR_MC501CB] = 4,
6575 4, /* SENSOR_MI0360SOC 9 */ 6456 [SENSOR_MT9V111_1] = 4,
6576 3, /* SENSOR_OV7620 10 */ 6457 [SENSOR_MT9V111_3] = 4,
6577 4, /* SENSOR_OV7630C 11 */ 6458 [SENSOR_OV7620] = 3,
6578 4, /* SENSOR_PAS106 12 */ 6459 [SENSOR_OV7630C] = 4,
6579 4, /* SENSOR_PAS202B 13 */ 6460 [SENSOR_PAS106] = 4,
6580 4, /* SENSOR_PB0330 14 */ 6461 [SENSOR_PAS202B] = 4,
6581 4, /* SENSOR_PO2030 15 */ 6462 [SENSOR_PB0330] = 4,
6582 4, /* SENSOR_TAS5130CK 16 */ 6463 [SENSOR_PO2030] = 4,
6583 3, /* SENSOR_TAS5130CXX 17 */ 6464 [SENSOR_TAS5130C] = 3,
6584 3, /* SENSOR_TAS5130C_VF0250 18 */ 6465 [SENSOR_TAS5130C_VF0250] = 3,
6585 }; 6466 };
6586 static const u8 mode_tb[SENSOR_MAX] = { 6467 static const u8 mode_tb[SENSOR_MAX] = {
6587 2, /* SENSOR_ADCM2700 0 */ 6468 [SENSOR_ADCM2700] = 2,
6588 1, /* SENSOR_CS2102 1 */ 6469 [SENSOR_CS2102] = 1,
6589 1, /* SENSOR_CS2102K 2 */ 6470 [SENSOR_CS2102K] = 1,
6590 1, /* SENSOR_GC0305 3 */ 6471 [SENSOR_GC0305] = 1,
6591 1, /* SENSOR_HDCS2020b 4 */ 6472 [SENSOR_HDCS2020b] = 1,
6592 1, /* SENSOR_HV7131B 5 */ 6473 [SENSOR_HV7131B] = 1,
6593 1, /* SENSOR_HV7131C 6 */ 6474 [SENSOR_HV7131R] = 1,
6594 1, /* SENSOR_ICM105A 7 */ 6475 [SENSOR_ICM105A] = 1,
6595 2, /* SENSOR_MC501CB 8 */ 6476 [SENSOR_MC501CB] = 2,
6596 1, /* SENSOR_MI0360SOC 9 */ 6477 [SENSOR_MT9V111_1] = 1,
6597 2, /* SENSOR_OV7620 10 */ 6478 [SENSOR_MT9V111_3] = 1,
6598 1, /* SENSOR_OV7630C 11 */ 6479 [SENSOR_OV7620] = 2,
6599 0, /* SENSOR_PAS106 12 */ 6480 [SENSOR_OV7630C] = 1,
6600 1, /* SENSOR_PAS202B 13 */ 6481 [SENSOR_PAS106] = 0,
6601 1, /* SENSOR_PB0330 14 */ 6482 [SENSOR_PAS202B] = 1,
6602 1, /* SENSOR_PO2030 15 */ 6483 [SENSOR_PB0330] = 1,
6603 1, /* SENSOR_TAS5130CK 16 */ 6484 [SENSOR_PO2030] = 1,
6604 1, /* SENSOR_TAS5130CXX 17 */ 6485 [SENSOR_TAS5130C] = 1,
6605 1, /* SENSOR_TAS5130C_VF0250 18 */ 6486 [SENSOR_TAS5130C_VF0250] = 1,
6606 }; 6487 };
6607 6488
6608 /* define some sensors from the vendor/product */
6609 sd->sharpness = SHARPNESS_DEF;
6610 sd->sensor = id->driver_info;
6611 sensor = zcxx_probeSensor(gspca_dev); 6489 sensor = zcxx_probeSensor(gspca_dev);
6612 if (sensor >= 0) 6490 if (sensor >= 0)
6613 PDEBUG(D_PROBE, "probe sensor -> %04x", sensor); 6491 PDEBUG(D_PROBE, "probe sensor -> %04x", sensor);
@@ -6626,8 +6504,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
6626 break; 6504 break;
6627 default: 6505 default:
6628 PDEBUG(D_PROBE, 6506 PDEBUG(D_PROBE,
6629 "Sensor UNKNOWN_0 force Tas5130"); 6507 "Unknown sensor - set to TAS5130C");
6630 sd->sensor = SENSOR_TAS5130CXX; 6508 sd->sensor = SENSOR_TAS5130C;
6631 } 6509 }
6632 break; 6510 break;
6633 case 0: 6511 case 0:
@@ -6642,14 +6520,14 @@ static int sd_config(struct gspca_dev *gspca_dev,
6642 break; 6520 break;
6643 default: 6521 default:
6644/* case 2: * hv7131r */ 6522/* case 2: * hv7131r */
6645 PDEBUG(D_PROBE, "Find Sensor HV7131R(c)"); 6523 PDEBUG(D_PROBE, "Find Sensor HV7131R");
6646 sd->sensor = SENSOR_HV7131C; 6524 sd->sensor = SENSOR_HV7131R;
6647 break; 6525 break;
6648 } 6526 }
6649 break; 6527 break;
6650 case 0x02: 6528 case 0x02:
6651 PDEBUG(D_PROBE, "Sensor TAS5130C"); 6529 PDEBUG(D_PROBE, "Sensor TAS5130C");
6652 sd->sensor = SENSOR_TAS5130CXX; 6530 sd->sensor = SENSOR_TAS5130C;
6653 break; 6531 break;
6654 case 0x04: 6532 case 0x04:
6655 PDEBUG(D_PROBE, "Find Sensor CS2102"); 6533 PDEBUG(D_PROBE, "Find Sensor CS2102");
@@ -6681,17 +6559,20 @@ static int sd_config(struct gspca_dev *gspca_dev,
6681 case 0x10: 6559 case 0x10:
6682 case 0x12: 6560 case 0x12:
6683 PDEBUG(D_PROBE, "Find Sensor TAS5130C"); 6561 PDEBUG(D_PROBE, "Find Sensor TAS5130C");
6684 sd->sensor = SENSOR_TAS5130CXX; 6562 sd->sensor = SENSOR_TAS5130C;
6685 break; 6563 break;
6686 case 0x11: 6564 case 0x11:
6687 PDEBUG(D_PROBE, "Find Sensor HV7131R(c)"); 6565 PDEBUG(D_PROBE, "Find Sensor HV7131R");
6688 sd->sensor = SENSOR_HV7131C; 6566 sd->sensor = SENSOR_HV7131R;
6689 break; 6567 break;
6690 case 0x13: 6568 case 0x13:
6569 case 0x15:
6691 PDEBUG(D_PROBE, 6570 PDEBUG(D_PROBE,
6692 "Find Sensor MI0360SOC. Chip revision %x", 6571 "Sensor MT9V111. Chip revision %04x",
6693 sd->chip_revision); 6572 sd->chip_revision);
6694 sd->sensor = SENSOR_MI0360SOC; 6573 sd->sensor = sd->bridge == BRIDGE_ZC301
6574 ? SENSOR_MT9V111_1
6575 : SENSOR_MT9V111_3;
6695 break; 6576 break;
6696 case 0x14: 6577 case 0x14:
6697 PDEBUG(D_PROBE, 6578 PDEBUG(D_PROBE,
@@ -6699,12 +6580,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
6699 sd->chip_revision); 6580 sd->chip_revision);
6700 sd->sensor = SENSOR_CS2102K; 6581 sd->sensor = SENSOR_CS2102K;
6701 break; 6582 break;
6702 case 0x15:
6703 PDEBUG(D_PROBE,
6704 "Find Sensor TAS5130CK?. Chip revision %x",
6705 sd->chip_revision);
6706 sd->sensor = SENSOR_TAS5130CK;
6707 break;
6708 case 0x16: 6583 case 0x16:
6709 PDEBUG(D_PROBE, "Find Sensor ADCM2700"); 6584 PDEBUG(D_PROBE, "Find Sensor ADCM2700");
6710 sd->sensor = SENSOR_ADCM2700; 6585 sd->sensor = SENSOR_ADCM2700;
@@ -6741,13 +6616,11 @@ static int sd_config(struct gspca_dev *gspca_dev,
6741 } 6616 }
6742 if (sensor < 0x20) { 6617 if (sensor < 0x20) {
6743 if (sensor == -1 || sensor == 0x10 || sensor == 0x12) 6618 if (sensor == -1 || sensor == 0x10 || sensor == 0x12)
6744 reg_w(gspca_dev->dev, 0x02, 0x0010); 6619 reg_w(gspca_dev, 0x02, 0x0010);
6745 reg_r(gspca_dev, 0x0010); 6620 reg_r(gspca_dev, 0x0010);
6746 } 6621 }
6747 6622
6748 cam = &gspca_dev->cam; 6623 cam = &gspca_dev->cam;
6749/*fixme:test*/
6750 gspca_dev->nbalt--;
6751 switch (mode_tb[sd->sensor]) { 6624 switch (mode_tb[sd->sensor]) {
6752 case 0: 6625 case 0:
6753 cam->cam_mode = sif_mode; 6626 cam->cam_mode = sif_mode;
@@ -6763,58 +6636,62 @@ static int sd_config(struct gspca_dev *gspca_dev,
6763 cam->nmodes = ARRAY_SIZE(broken_vga_mode); 6636 cam->nmodes = ARRAY_SIZE(broken_vga_mode);
6764 break; 6637 break;
6765 } 6638 }
6766 sd->brightness = BRIGHTNESS_DEF;
6767 sd->contrast = CONTRAST_DEF;
6768 sd->gamma = gamma[sd->sensor]; 6639 sd->gamma = gamma[sd->sensor];
6769 sd->autogain = AUTOGAIN_DEF;
6770 sd->lightfreq = FREQ_DEF;
6771 sd->quality = QUALITY_DEF;
6772 6640
6773 switch (sd->sensor) { 6641 switch (sd->sensor) {
6774 case SENSOR_HV7131B:
6775 case SENSOR_HV7131C:
6776 case SENSOR_OV7630C: 6642 case SENSOR_OV7630C:
6777 gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX); 6643 gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX);
6778 break; 6644 break;
6779 } 6645 }
6780 6646
6781 return 0;
6782}
6783
6784/* this function is called at probe and resume time */
6785static int sd_init(struct gspca_dev *gspca_dev)
6786{
6787 /* switch off the led */ 6647 /* switch off the led */
6788 reg_w(gspca_dev->dev, 0x01, 0x0000); 6648 reg_w(gspca_dev, 0x01, 0x0000);
6789 return 0; 6649 return gspca_dev->usb_err;
6790} 6650}
6791 6651
6792static int sd_start(struct gspca_dev *gspca_dev) 6652static int sd_start(struct gspca_dev *gspca_dev)
6793{ 6653{
6794 struct sd *sd = (struct sd *) gspca_dev; 6654 struct sd *sd = (struct sd *) gspca_dev;
6795 struct usb_device *dev = gspca_dev->dev;
6796 int mode; 6655 int mode;
6797 static const struct usb_action *init_tb[SENSOR_MAX][2] = { 6656 static const struct usb_action *init_tb[SENSOR_MAX][2] = {
6798 {adcm2700_Initial, adcm2700_InitialScale}, /* 0 */ 6657 [SENSOR_ADCM2700] =
6799 {cs2102_Initial, cs2102_InitialScale}, /* 1 */ 6658 {adcm2700_Initial, adcm2700_InitialScale},
6800 {cs2102K_Initial, cs2102K_InitialScale}, /* 2 */ 6659 [SENSOR_CS2102] =
6801 {gc0305_Initial, gc0305_InitialScale}, /* 3 */ 6660 {cs2102_Initial, cs2102_InitialScale},
6802 {hdcs2020b_Initial, hdcs2020b_InitialScale}, /* 4 */ 6661 [SENSOR_CS2102K] =
6803 {hv7131b_Initial, hv7131b_InitialScale}, /* 5 */ 6662 {cs2102K_Initial, cs2102K_InitialScale},
6804 {hv7131r_Initial, hv7131r_InitialScale}, /* 6 */ 6663 [SENSOR_GC0305] =
6805 {icm105a_Initial, icm105a_InitialScale}, /* 7 */ 6664 {gc0305_Initial, gc0305_InitialScale},
6806 {mc501cb_Initial, mc501cb_InitialScale}, /* 8 */ 6665 [SENSOR_HDCS2020b] =
6807 {mi0360soc_Initial, mi0360soc_InitialScale}, /* 9 */ 6666 {hdcs2020b_Initial, hdcs2020b_InitialScale},
6808 {ov7620_Initial, ov7620_InitialScale}, /* 10 */ 6667 [SENSOR_HV7131B] =
6809 {ov7630c_Initial, ov7630c_InitialScale}, /* 11 */ 6668 {hv7131b_Initial, hv7131b_InitialScale},
6810 {pas106b_Initial, pas106b_InitialScale}, /* 12 */ 6669 [SENSOR_HV7131R] =
6811 {pas202b_Initial, pas202b_InitialScale}, /* 13 */ 6670 {hv7131r_Initial, hv7131r_InitialScale},
6812 {pb0330_Initial, pb0330_InitialScale}, /* 14 */ 6671 [SENSOR_ICM105A] =
6813 {po2030_Initial, po2030_InitialScale}, /* 15 */ 6672 {icm105a_Initial, icm105a_InitialScale},
6814 {tas5130cK_Initial, tas5130cK_InitialScale}, /* 16 */ 6673 [SENSOR_MC501CB] =
6815 {tas5130cxx_Initial, tas5130cxx_InitialScale}, /* 17 */ 6674 {mc501cb_Initial, mc501cb_InitialScale},
6675 [SENSOR_MT9V111_1] =
6676 {mt9v111_1_Initial, mt9v111_1_InitialScale},
6677 [SENSOR_MT9V111_3] =
6678 {mt9v111_3_Initial, mt9v111_3_InitialScale},
6679 [SENSOR_OV7620] =
6680 {ov7620_Initial, ov7620_InitialScale},
6681 [SENSOR_OV7630C] =
6682 {ov7630c_Initial, ov7630c_InitialScale},
6683 [SENSOR_PAS106] =
6684 {pas106b_Initial, pas106b_InitialScale},
6685 [SENSOR_PAS202B] =
6686 {pas202b_Initial, pas202b_InitialScale},
6687 [SENSOR_PB0330] =
6688 {pb0330_Initial, pb0330_InitialScale},
6689 [SENSOR_PO2030] =
6690 {po2030_Initial, po2030_InitialScale},
6691 [SENSOR_TAS5130C] =
6692 {tas5130c_Initial, tas5130c_InitialScale},
6693 [SENSOR_TAS5130C_VF0250] =
6816 {tas5130c_vf0250_Initial, tas5130c_vf0250_InitialScale}, 6694 {tas5130c_vf0250_Initial, tas5130c_vf0250_InitialScale},
6817 /* 18 */
6818 }; 6695 };
6819 6696
6820 /* create the JPEG header */ 6697 /* create the JPEG header */
@@ -6824,7 +6701,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
6824 6701
6825 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; 6702 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
6826 switch (sd->sensor) { 6703 switch (sd->sensor) {
6827 case SENSOR_HV7131C: 6704 case SENSOR_HV7131R:
6828 zcxx_probeSensor(gspca_dev); 6705 zcxx_probeSensor(gspca_dev);
6829 break; 6706 break;
6830 case SENSOR_PAS106: 6707 case SENSOR_PAS106:
@@ -6838,22 +6715,22 @@ static int sd_start(struct gspca_dev *gspca_dev)
6838 case SENSOR_GC0305: 6715 case SENSOR_GC0305:
6839 case SENSOR_OV7620: 6716 case SENSOR_OV7620:
6840 case SENSOR_PO2030: 6717 case SENSOR_PO2030:
6841 case SENSOR_TAS5130CXX: 6718 case SENSOR_TAS5130C:
6842 case SENSOR_TAS5130C_VF0250: 6719 case SENSOR_TAS5130C_VF0250:
6843/* msleep(100); * ?? */ 6720/* msleep(100); * ?? */
6844 reg_r(gspca_dev, 0x0002); /* --> 0x40 */ 6721 reg_r(gspca_dev, 0x0002); /* --> 0x40 */
6845 reg_w(dev, 0x09, 0x01ad); /* (from win traces) */ 6722 reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */
6846 reg_w(dev, 0x15, 0x01ae); 6723 reg_w(gspca_dev, 0x15, 0x01ae);
6847 if (sd->sensor == SENSOR_TAS5130CXX) 6724 if (sd->sensor == SENSOR_TAS5130C)
6848 break; 6725 break;
6849 reg_w(dev, 0x0d, 0x003a); 6726 reg_w(gspca_dev, 0x0d, 0x003a);
6850 reg_w(dev, 0x02, 0x003b); 6727 reg_w(gspca_dev, 0x02, 0x003b);
6851 reg_w(dev, 0x00, 0x0038); 6728 reg_w(gspca_dev, 0x00, 0x0038);
6852 break; 6729 break;
6853 case SENSOR_PAS202B: 6730 case SENSOR_PAS202B:
6854 reg_w(dev, 0x03, 0x003b); 6731 reg_w(gspca_dev, 0x03, 0x003b);
6855 reg_w(dev, 0x0c, 0x003a); 6732 reg_w(gspca_dev, 0x0c, 0x003a);
6856 reg_w(dev, 0x0b, 0x0039); 6733 reg_w(gspca_dev, 0x0b, 0x0039);
6857 break; 6734 break;
6858 } 6735 }
6859 6736
@@ -6862,15 +6739,15 @@ static int sd_start(struct gspca_dev *gspca_dev)
6862 case SENSOR_ADCM2700: 6739 case SENSOR_ADCM2700:
6863 case SENSOR_OV7620: 6740 case SENSOR_OV7620:
6864 reg_r(gspca_dev, 0x0008); 6741 reg_r(gspca_dev, 0x0008);
6865 reg_w(dev, 0x00, 0x0008); 6742 reg_w(gspca_dev, 0x00, 0x0008);
6866 break; 6743 break;
6867 case SENSOR_PAS202B: 6744 case SENSOR_PAS202B:
6868 case SENSOR_GC0305: 6745 case SENSOR_GC0305:
6869 case SENSOR_TAS5130CXX: 6746 case SENSOR_TAS5130C:
6870 reg_r(gspca_dev, 0x0008); 6747 reg_r(gspca_dev, 0x0008);
6871 /* fall thru */ 6748 /* fall thru */
6872 case SENSOR_PO2030: 6749 case SENSOR_PO2030:
6873 reg_w(dev, 0x03, 0x0008); 6750 reg_w(gspca_dev, 0x03, 0x0008);
6874 break; 6751 break;
6875 } 6752 }
6876 setsharpness(gspca_dev); 6753 setsharpness(gspca_dev);
@@ -6880,7 +6757,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
6880 case SENSOR_CS2102K: /* gamma set in xxx_Initial */ 6757 case SENSOR_CS2102K: /* gamma set in xxx_Initial */
6881 case SENSOR_HDCS2020b: 6758 case SENSOR_HDCS2020b:
6882 case SENSOR_OV7630C: 6759 case SENSOR_OV7630C:
6883 case SENSOR_TAS5130CK:
6884 break; 6760 break;
6885 default: 6761 default:
6886 setcontrast(gspca_dev); 6762 setcontrast(gspca_dev);
@@ -6891,7 +6767,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
6891 case SENSOR_OV7620: 6767 case SENSOR_OV7620:
6892 case SENSOR_PAS202B: 6768 case SENSOR_PAS202B:
6893 reg_r(gspca_dev, 0x0180); /* from win */ 6769 reg_r(gspca_dev, 0x0180); /* from win */
6894 reg_w(dev, 0x00, 0x0180); 6770 reg_w(gspca_dev, 0x00, 0x0180);
6895 break; 6771 break;
6896 default: 6772 default:
6897 setquality(gspca_dev); 6773 setquality(gspca_dev);
@@ -6901,29 +6777,29 @@ static int sd_start(struct gspca_dev *gspca_dev)
6901 6777
6902 switch (sd->sensor) { 6778 switch (sd->sensor) {
6903 case SENSOR_ADCM2700: 6779 case SENSOR_ADCM2700:
6904 reg_w(dev, 0x09, 0x01ad); /* (from win traces) */ 6780 reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */
6905 reg_w(dev, 0x15, 0x01ae); 6781 reg_w(gspca_dev, 0x15, 0x01ae);
6906 reg_w(dev, 0x02, 0x0180); 6782 reg_w(gspca_dev, 0x02, 0x0180);
6907 /* ms-win + */ 6783 /* ms-win + */
6908 reg_w(dev, 0x40, 0x0117); 6784 reg_w(gspca_dev, 0x40, 0x0117);
6909 break; 6785 break;
6910 case SENSOR_GC0305: 6786 case SENSOR_GC0305:
6911 case SENSOR_TAS5130CXX: 6787 case SENSOR_TAS5130C:
6912 reg_w(dev, 0x09, 0x01ad); /* (from win traces) */ 6788 reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */
6913 reg_w(dev, 0x15, 0x01ae); 6789 reg_w(gspca_dev, 0x15, 0x01ae);
6914 /* fall thru */ 6790 /* fall thru */
6915 case SENSOR_PAS202B: 6791 case SENSOR_PAS202B:
6916 case SENSOR_PO2030: 6792 case SENSOR_PO2030:
6917/* reg_w(dev, 0x40, ZC3XX_R117_GGAIN); * (from win traces) */ 6793/* reg_w(gspca_dev, 0x40, ZC3XX_R117_GGAIN); * (from win traces) */
6918 reg_r(gspca_dev, 0x0180); 6794 reg_r(gspca_dev, 0x0180);
6919 break; 6795 break;
6920 case SENSOR_OV7620: 6796 case SENSOR_OV7620:
6921 reg_w(dev, 0x09, 0x01ad); 6797 reg_w(gspca_dev, 0x09, 0x01ad);
6922 reg_w(dev, 0x15, 0x01ae); 6798 reg_w(gspca_dev, 0x15, 0x01ae);
6923 i2c_read(gspca_dev, 0x13); /*fixme: returns 0xa3 */ 6799 i2c_read(gspca_dev, 0x13); /*fixme: returns 0xa3 */
6924 i2c_write(gspca_dev, 0x13, 0xa3, 0x00); 6800 i2c_write(gspca_dev, 0x13, 0xa3, 0x00);
6925 /*fixme: returned value to send? */ 6801 /*fixme: returned value to send? */
6926 reg_w(dev, 0x40, 0x0117); 6802 reg_w(gspca_dev, 0x40, 0x0117);
6927 reg_r(gspca_dev, 0x0180); 6803 reg_r(gspca_dev, 0x0180);
6928 break; 6804 break;
6929 } 6805 }
@@ -6932,11 +6808,11 @@ static int sd_start(struct gspca_dev *gspca_dev)
6932 switch (sd->sensor) { 6808 switch (sd->sensor) {
6933 case SENSOR_PO2030: 6809 case SENSOR_PO2030:
6934 msleep(50); 6810 msleep(50);
6935 reg_w(dev, 0x00, 0x0007); /* (from win traces) */ 6811 reg_w(gspca_dev, 0x00, 0x0007); /* (from win traces) */
6936 reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); 6812 reg_w(gspca_dev, 0x02, ZC3XX_R008_CLOCKSETTING);
6937 break; 6813 break;
6938 } 6814 }
6939 return 0; 6815 return gspca_dev->usb_err;
6940} 6816}
6941 6817
6942/* called on streamoff with alt 0 and on disconnect */ 6818/* called on streamoff with alt 0 and on disconnect */
@@ -6946,7 +6822,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
6946 6822
6947 if (!gspca_dev->present) 6823 if (!gspca_dev->present)
6948 return; 6824 return;
6949 send_unknown(gspca_dev->dev, sd->sensor); 6825 send_unknown(gspca_dev, sd->sensor);
6950} 6826}
6951 6827
6952static void sd_pkt_scan(struct gspca_dev *gspca_dev, 6828static void sd_pkt_scan(struct gspca_dev *gspca_dev,
@@ -6981,7 +6857,7 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
6981 sd->brightness = val; 6857 sd->brightness = val;
6982 if (gspca_dev->streaming) 6858 if (gspca_dev->streaming)
6983 setcontrast(gspca_dev); 6859 setcontrast(gspca_dev);
6984 return 0; 6860 return gspca_dev->usb_err;
6985} 6861}
6986 6862
6987static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) 6863static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
@@ -6999,7 +6875,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
6999 sd->contrast = val; 6875 sd->contrast = val;
7000 if (gspca_dev->streaming) 6876 if (gspca_dev->streaming)
7001 setcontrast(gspca_dev); 6877 setcontrast(gspca_dev);
7002 return 0; 6878 return gspca_dev->usb_err;
7003} 6879}
7004 6880
7005static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) 6881static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
@@ -7017,7 +6893,7 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
7017 sd->autogain = val; 6893 sd->autogain = val;
7018 if (gspca_dev->streaming) 6894 if (gspca_dev->streaming)
7019 setautogain(gspca_dev); 6895 setautogain(gspca_dev);
7020 return 0; 6896 return gspca_dev->usb_err;
7021} 6897}
7022 6898
7023static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) 6899static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
@@ -7035,7 +6911,7 @@ static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
7035 sd->gamma = val; 6911 sd->gamma = val;
7036 if (gspca_dev->streaming) 6912 if (gspca_dev->streaming)
7037 setcontrast(gspca_dev); 6913 setcontrast(gspca_dev);
7038 return 0; 6914 return gspca_dev->usb_err;
7039} 6915}
7040 6916
7041static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val) 6917static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
@@ -7053,7 +6929,7 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
7053 sd->lightfreq = val; 6929 sd->lightfreq = val;
7054 if (gspca_dev->streaming) 6930 if (gspca_dev->streaming)
7055 setlightfreq(gspca_dev); 6931 setlightfreq(gspca_dev);
7056 return 0; 6932 return gspca_dev->usb_err;
7057} 6933}
7058 6934
7059static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) 6935static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
@@ -7071,7 +6947,7 @@ static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
7071 sd->sharpness = val; 6947 sd->sharpness = val;
7072 if (gspca_dev->streaming) 6948 if (gspca_dev->streaming)
7073 setsharpness(gspca_dev); 6949 setsharpness(gspca_dev);
7074 return 0; 6950 return gspca_dev->usb_err;
7075} 6951}
7076 6952
7077static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) 6953static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
@@ -7116,7 +6992,7 @@ static int sd_set_jcomp(struct gspca_dev *gspca_dev,
7116 sd->quality = jcomp->quality; 6992 sd->quality = jcomp->quality;
7117 if (gspca_dev->streaming) 6993 if (gspca_dev->streaming)
7118 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 6994 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
7119 return 0; 6995 return gspca_dev->usb_err;
7120} 6996}
7121 6997
7122static int sd_get_jcomp(struct gspca_dev *gspca_dev, 6998static int sd_get_jcomp(struct gspca_dev *gspca_dev,
@@ -7220,7 +7096,6 @@ static const __devinitdata struct usb_device_id device_table[] = {
7220 {USB_DEVICE(0x10fd, 0x8050)}, 7096 {USB_DEVICE(0x10fd, 0x8050)},
7221 {} /* end of entry */ 7097 {} /* end of entry */
7222}; 7098};
7223#undef DVNAME
7224MODULE_DEVICE_TABLE(usb, device_table); 7099MODULE_DEVICE_TABLE(usb, device_table);
7225 7100
7226/* -- device connect -- */ 7101/* -- device connect -- */
diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c
index b588e30cbcf..b31ee1bceef 100644
--- a/drivers/media/video/ivtv/ivtv-controls.c
+++ b/drivers/media/video/ivtv/ivtv-controls.c
@@ -17,163 +17,14 @@
17 along with this program; if not, write to the Free Software 17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */ 19 */
20#include <linux/kernel.h>
21#include <linux/slab.h>
22 20
23#include "ivtv-driver.h" 21#include "ivtv-driver.h"
24#include "ivtv-cards.h"
25#include "ivtv-ioctl.h" 22#include "ivtv-ioctl.h"
26#include "ivtv-routing.h"
27#include "ivtv-i2c.h"
28#include "ivtv-mailbox.h"
29#include "ivtv-controls.h" 23#include "ivtv-controls.h"
30 24
31/* Must be sorted from low to high control ID! */ 25static int ivtv_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt)
32static const u32 user_ctrls[] = {
33 V4L2_CID_USER_CLASS,
34 V4L2_CID_BRIGHTNESS,
35 V4L2_CID_CONTRAST,
36 V4L2_CID_SATURATION,
37 V4L2_CID_HUE,
38 V4L2_CID_AUDIO_VOLUME,
39 V4L2_CID_AUDIO_BALANCE,
40 V4L2_CID_AUDIO_BASS,
41 V4L2_CID_AUDIO_TREBLE,
42 V4L2_CID_AUDIO_MUTE,
43 V4L2_CID_AUDIO_LOUDNESS,
44 0
45};
46
47static const u32 *ctrl_classes[] = {
48 user_ctrls,
49 cx2341x_mpeg_ctrls,
50 NULL
51};
52
53
54int ivtv_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl)
55{
56 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
57 const char *name;
58
59 qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
60 if (qctrl->id == 0)
61 return -EINVAL;
62
63 switch (qctrl->id) {
64 /* Standard V4L2 controls */
65 case V4L2_CID_USER_CLASS:
66 return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0);
67 case V4L2_CID_BRIGHTNESS:
68 case V4L2_CID_HUE:
69 case V4L2_CID_SATURATION:
70 case V4L2_CID_CONTRAST:
71 if (v4l2_subdev_call(itv->sd_video, core, queryctrl, qctrl))
72 qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
73 return 0;
74
75 case V4L2_CID_AUDIO_VOLUME:
76 case V4L2_CID_AUDIO_MUTE:
77 case V4L2_CID_AUDIO_BALANCE:
78 case V4L2_CID_AUDIO_BASS:
79 case V4L2_CID_AUDIO_TREBLE:
80 case V4L2_CID_AUDIO_LOUDNESS:
81 if (v4l2_subdev_call(itv->sd_audio, core, queryctrl, qctrl))
82 qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
83 return 0;
84
85 default:
86 if (cx2341x_ctrl_query(&itv->params, qctrl))
87 qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
88 return 0;
89 }
90 strncpy(qctrl->name, name, sizeof(qctrl->name) - 1);
91 qctrl->name[sizeof(qctrl->name) - 1] = 0;
92 return 0;
93}
94
95int ivtv_querymenu(struct file *file, void *fh, struct v4l2_querymenu *qmenu)
96{
97 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
98 struct v4l2_queryctrl qctrl;
99
100 qctrl.id = qmenu->id;
101 ivtv_queryctrl(file, fh, &qctrl);
102 return v4l2_ctrl_query_menu(qmenu, &qctrl,
103 cx2341x_ctrl_get_menu(&itv->params, qmenu->id));
104}
105
106static int ivtv_try_ctrl(struct file *file, void *fh,
107 struct v4l2_ext_control *vctrl)
108{
109 struct v4l2_queryctrl qctrl;
110 const char **menu_items = NULL;
111 int err;
112
113 qctrl.id = vctrl->id;
114 err = ivtv_queryctrl(file, fh, &qctrl);
115 if (err)
116 return err;
117 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
118 menu_items = v4l2_ctrl_get_menu(qctrl.id);
119 return v4l2_ctrl_check(vctrl, &qctrl, menu_items);
120}
121
122static int ivtv_s_ctrl(struct ivtv *itv, struct v4l2_control *vctrl)
123{
124 switch (vctrl->id) {
125 /* Standard V4L2 controls */
126 case V4L2_CID_BRIGHTNESS:
127 case V4L2_CID_HUE:
128 case V4L2_CID_SATURATION:
129 case V4L2_CID_CONTRAST:
130 return v4l2_subdev_call(itv->sd_video, core, s_ctrl, vctrl);
131
132 case V4L2_CID_AUDIO_VOLUME:
133 case V4L2_CID_AUDIO_MUTE:
134 case V4L2_CID_AUDIO_BALANCE:
135 case V4L2_CID_AUDIO_BASS:
136 case V4L2_CID_AUDIO_TREBLE:
137 case V4L2_CID_AUDIO_LOUDNESS:
138 return v4l2_subdev_call(itv->sd_audio, core, s_ctrl, vctrl);
139
140 default:
141 IVTV_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id);
142 return -EINVAL;
143 }
144 return 0;
145}
146
147static int ivtv_g_ctrl(struct ivtv *itv, struct v4l2_control *vctrl)
148{ 26{
149 switch (vctrl->id) { 27 struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
150 /* Standard V4L2 controls */
151 case V4L2_CID_BRIGHTNESS:
152 case V4L2_CID_HUE:
153 case V4L2_CID_SATURATION:
154 case V4L2_CID_CONTRAST:
155 return v4l2_subdev_call(itv->sd_video, core, g_ctrl, vctrl);
156
157 case V4L2_CID_AUDIO_VOLUME:
158 case V4L2_CID_AUDIO_MUTE:
159 case V4L2_CID_AUDIO_BALANCE:
160 case V4L2_CID_AUDIO_BASS:
161 case V4L2_CID_AUDIO_TREBLE:
162 case V4L2_CID_AUDIO_LOUDNESS:
163 return v4l2_subdev_call(itv->sd_audio, core, g_ctrl, vctrl);
164 default:
165 IVTV_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id);
166 return -EINVAL;
167 }
168 return 0;
169}
170
171static int ivtv_setup_vbi_fmt(struct ivtv *itv, enum v4l2_mpeg_stream_vbi_fmt fmt)
172{
173 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE))
174 return -EINVAL;
175 if (atomic_read(&itv->capturing) > 0)
176 return -EBUSY;
177 28
178 /* First try to allocate sliced VBI buffers if needed. */ 29 /* First try to allocate sliced VBI buffers if needed. */
179 if (fmt && itv->vbi.sliced_mpeg_data[0] == NULL) { 30 if (fmt && itv->vbi.sliced_mpeg_data[0] == NULL) {
@@ -208,106 +59,43 @@ static int ivtv_setup_vbi_fmt(struct ivtv *itv, enum v4l2_mpeg_stream_vbi_fmt fm
208 return 0; 59 return 0;
209} 60}
210 61
211int ivtv_g_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) 62static int ivtv_s_video_encoding(struct cx2341x_handler *cxhdl, u32 val)
212{ 63{
213 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; 64 struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
214 struct v4l2_control ctrl; 65 int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
215 66 struct v4l2_mbus_framefmt fmt;
216 if (c->ctrl_class == V4L2_CTRL_CLASS_USER) { 67
217 int i; 68 /* fix videodecoder resolution */
218 int err = 0; 69 fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
219 70 fmt.height = cxhdl->height;
220 for (i = 0; i < c->count; i++) { 71 fmt.code = V4L2_MBUS_FMT_FIXED;
221 ctrl.id = c->controls[i].id; 72 v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &fmt);
222 ctrl.value = c->controls[i].value; 73 return 0;
223 err = ivtv_g_ctrl(itv, &ctrl);
224 c->controls[i].value = ctrl.value;
225 if (err) {
226 c->error_idx = i;
227 break;
228 }
229 }
230 return err;
231 }
232 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
233 return cx2341x_ext_ctrls(&itv->params, 0, c, VIDIOC_G_EXT_CTRLS);
234 return -EINVAL;
235} 74}
236 75
237int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) 76static int ivtv_s_audio_sampling_freq(struct cx2341x_handler *cxhdl, u32 idx)
238{ 77{
239 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; 78 static const u32 freqs[3] = { 44100, 48000, 32000 };
240 struct v4l2_control ctrl; 79 struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
241
242 if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
243 int i;
244 int err = 0;
245
246 for (i = 0; i < c->count; i++) {
247 ctrl.id = c->controls[i].id;
248 ctrl.value = c->controls[i].value;
249 err = ivtv_s_ctrl(itv, &ctrl);
250 c->controls[i].value = ctrl.value;
251 if (err) {
252 c->error_idx = i;
253 break;
254 }
255 }
256 return err;
257 }
258 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
259 static u32 freqs[3] = { 44100, 48000, 32000 };
260 struct cx2341x_mpeg_params p = itv->params;
261 int err = cx2341x_ext_ctrls(&p, atomic_read(&itv->capturing), c, VIDIOC_S_EXT_CTRLS);
262 unsigned idx;
263
264 if (err)
265 return err;
266 80
267 if (p.video_encoding != itv->params.video_encoding) { 81 /* The audio clock of the digitizer must match the codec sample
268 int is_mpeg1 = p.video_encoding == 82 rate otherwise you get some very strange effects. */
269 V4L2_MPEG_VIDEO_ENCODING_MPEG_1; 83 if (idx < ARRAY_SIZE(freqs))
270 struct v4l2_mbus_framefmt fmt; 84 ivtv_call_all(itv, audio, s_clock_freq, freqs[idx]);
271 85 return 0;
272 /* fix videodecoder resolution */
273 fmt.width = itv->params.width / (is_mpeg1 ? 2 : 1);
274 fmt.height = itv->params.height;
275 fmt.code = V4L2_MBUS_FMT_FIXED;
276 v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &fmt);
277 }
278 err = cx2341x_update(itv, ivtv_api_func, &itv->params, &p);
279 if (!err && itv->params.stream_vbi_fmt != p.stream_vbi_fmt)
280 err = ivtv_setup_vbi_fmt(itv, p.stream_vbi_fmt);
281 itv->params = p;
282 itv->dualwatch_stereo_mode = p.audio_properties & 0x0300;
283 idx = p.audio_properties & 0x03;
284 /* The audio clock of the digitizer must match the codec sample
285 rate otherwise you get some very strange effects. */
286 if (idx < ARRAY_SIZE(freqs))
287 ivtv_call_all(itv, audio, s_clock_freq, freqs[idx]);
288 return err;
289 }
290 return -EINVAL;
291} 86}
292 87
293int ivtv_try_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) 88static int ivtv_s_audio_mode(struct cx2341x_handler *cxhdl, u32 val)
294{ 89{
295 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; 90 struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
296 91
297 if (c->ctrl_class == V4L2_CTRL_CLASS_USER) { 92 itv->dualwatch_stereo_mode = val;
298 int i; 93 return 0;
299 int err = 0;
300
301 for (i = 0; i < c->count; i++) {
302 err = ivtv_try_ctrl(file, fh, &c->controls[i]);
303 if (err) {
304 c->error_idx = i;
305 break;
306 }
307 }
308 return err;
309 }
310 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
311 return cx2341x_ext_ctrls(&itv->params, atomic_read(&itv->capturing), c, VIDIOC_TRY_EXT_CTRLS);
312 return -EINVAL;
313} 94}
95
96struct cx2341x_handler_ops ivtv_cxhdl_ops = {
97 .s_audio_mode = ivtv_s_audio_mode,
98 .s_audio_sampling_freq = ivtv_s_audio_sampling_freq,
99 .s_video_encoding = ivtv_s_video_encoding,
100 .s_stream_vbi_fmt = ivtv_s_stream_vbi_fmt,
101};
diff --git a/drivers/media/video/ivtv/ivtv-controls.h b/drivers/media/video/ivtv/ivtv-controls.h
index 1c7721e23c9..d12893dd018 100644
--- a/drivers/media/video/ivtv/ivtv-controls.h
+++ b/drivers/media/video/ivtv/ivtv-controls.h
@@ -21,10 +21,6 @@
21#ifndef IVTV_CONTROLS_H 21#ifndef IVTV_CONTROLS_H
22#define IVTV_CONTROLS_H 22#define IVTV_CONTROLS_H
23 23
24int ivtv_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *a); 24extern struct cx2341x_handler_ops ivtv_cxhdl_ops;
25int ivtv_g_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *a);
26int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *a);
27int ivtv_try_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *a);
28int ivtv_querymenu(struct file *file, void *fh, struct v4l2_querymenu *a);
29 25
30#endif 26#endif
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index 07c5c18a25c..e421d15b0f5 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -53,6 +53,7 @@
53#include "ivtv-cards.h" 53#include "ivtv-cards.h"
54#include "ivtv-vbi.h" 54#include "ivtv-vbi.h"
55#include "ivtv-routing.h" 55#include "ivtv-routing.h"
56#include "ivtv-controls.h"
56#include "ivtv-gpio.h" 57#include "ivtv-gpio.h"
57 58
58#include <media/tveeprom.h> 59#include <media/tveeprom.h>
@@ -734,9 +735,8 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
734 itv->open_id = 1; 735 itv->open_id = 1;
735 736
736 /* Initial settings */ 737 /* Initial settings */
737 cx2341x_fill_defaults(&itv->params); 738 itv->cxhdl.port = CX2341X_PORT_MEMORY;
738 itv->params.port = CX2341X_PORT_MEMORY; 739 itv->cxhdl.capabilities = CX2341X_CAP_HAS_SLICED_VBI;
739 itv->params.capabilities = CX2341X_CAP_HAS_SLICED_VBI;
740 init_waitqueue_head(&itv->eos_waitq); 740 init_waitqueue_head(&itv->eos_waitq);
741 init_waitqueue_head(&itv->event_waitq); 741 init_waitqueue_head(&itv->event_waitq);
742 init_waitqueue_head(&itv->vsync_waitq); 742 init_waitqueue_head(&itv->vsync_waitq);
@@ -1006,6 +1006,13 @@ static int __devinit ivtv_probe(struct pci_dev *pdev,
1006 retval = -ENOMEM; 1006 retval = -ENOMEM;
1007 goto err; 1007 goto err;
1008 } 1008 }
1009 retval = cx2341x_handler_init(&itv->cxhdl, 50);
1010 if (retval)
1011 goto err;
1012 itv->v4l2_dev.ctrl_handler = &itv->cxhdl.hdl;
1013 itv->cxhdl.ops = &ivtv_cxhdl_ops;
1014 itv->cxhdl.priv = itv;
1015 itv->cxhdl.func = ivtv_api_func;
1009 1016
1010 IVTV_DEBUG_INFO("base addr: 0x%08x\n", itv->base_addr); 1017 IVTV_DEBUG_INFO("base addr: 0x%08x\n", itv->base_addr);
1011 1018
@@ -1127,7 +1134,7 @@ static int __devinit ivtv_probe(struct pci_dev *pdev,
1127 itv->yuv_info.v4l2_src_w = itv->yuv_info.osd_full_w; 1134 itv->yuv_info.v4l2_src_w = itv->yuv_info.osd_full_w;
1128 itv->yuv_info.v4l2_src_h = itv->yuv_info.osd_full_h; 1135 itv->yuv_info.v4l2_src_h = itv->yuv_info.osd_full_h;
1129 1136
1130 itv->params.video_gop_size = itv->is_60hz ? 15 : 12; 1137 cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz);
1131 1138
1132 itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_MPG] = 0x08000; 1139 itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_MPG] = 0x08000;
1133 itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_PCM] = 0x01200; 1140 itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_PCM] = 0x01200;
@@ -1269,15 +1276,8 @@ int ivtv_init_on_first_open(struct ivtv *itv)
1269 IVTV_DEBUG_INFO("Getting firmware version..\n"); 1276 IVTV_DEBUG_INFO("Getting firmware version..\n");
1270 ivtv_firmware_versions(itv); 1277 ivtv_firmware_versions(itv);
1271 1278
1272 if (itv->card->hw_all & IVTV_HW_CX25840) { 1279 if (itv->card->hw_all & IVTV_HW_CX25840)
1273 struct v4l2_control ctrl;
1274
1275 v4l2_subdev_call(itv->sd_video, core, load_fw); 1280 v4l2_subdev_call(itv->sd_video, core, load_fw);
1276 /* CX25840_CID_ENABLE_PVR150_WORKAROUND */
1277 ctrl.id = V4L2_CID_PRIVATE_BASE;
1278 ctrl.value = itv->pvr150_workaround;
1279 v4l2_subdev_call(itv->sd_video, core, s_ctrl, &ctrl);
1280 }
1281 1281
1282 vf.tuner = 0; 1282 vf.tuner = 0;
1283 vf.type = V4L2_TUNER_ANALOG_TV; 1283 vf.type = V4L2_TUNER_ANALOG_TV;
@@ -1329,6 +1329,8 @@ int ivtv_init_on_first_open(struct ivtv *itv)
1329 /* For cards with video out, this call needs interrupts enabled */ 1329 /* For cards with video out, this call needs interrupts enabled */
1330 ivtv_s_std(NULL, &fh, &itv->tuner_std); 1330 ivtv_s_std(NULL, &fh, &itv->tuner_std);
1331 1331
1332 /* Setup initial controls */
1333 cx2341x_handler_setup(&itv->cxhdl);
1332 return 0; 1334 return 0;
1333} 1335}
1334 1336
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index 10207124621..75803141481 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -62,6 +62,7 @@
62#include <linux/dvb/audio.h> 62#include <linux/dvb/audio.h>
63#include <media/v4l2-common.h> 63#include <media/v4l2-common.h>
64#include <media/v4l2-ioctl.h> 64#include <media/v4l2-ioctl.h>
65#include <media/v4l2-ctrls.h>
65#include <media/v4l2-device.h> 66#include <media/v4l2-device.h>
66#include <media/v4l2-fh.h> 67#include <media/v4l2-fh.h>
67#include <media/tuner.h> 68#include <media/tuner.h>
@@ -631,6 +632,8 @@ struct ivtv {
631 struct ivtv_options options; /* user options */ 632 struct ivtv_options options; /* user options */
632 633
633 struct v4l2_device v4l2_dev; 634 struct v4l2_device v4l2_dev;
635 struct cx2341x_handler cxhdl;
636 struct v4l2_ctrl_handler hdl_gpio;
634 struct v4l2_subdev sd_gpio; /* GPIO sub-device */ 637 struct v4l2_subdev sd_gpio; /* GPIO sub-device */
635 u16 instance; 638 u16 instance;
636 639
@@ -648,7 +651,6 @@ struct ivtv {
648 v4l2_std_id std_out; /* current TV output standard */ 651 v4l2_std_id std_out; /* current TV output standard */
649 u8 audio_stereo_mode; /* decoder setting how to handle stereo MPEG audio */ 652 u8 audio_stereo_mode; /* decoder setting how to handle stereo MPEG audio */
650 u8 audio_bilingual_mode; /* decoder setting how to handle bilingual MPEG audio */ 653 u8 audio_bilingual_mode; /* decoder setting how to handle bilingual MPEG audio */
651 struct cx2341x_mpeg_params params; /* current encoder parameters */
652 654
653 655
654 /* Locking */ 656 /* Locking */
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index a6a2cdb8156..d727485da88 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -150,12 +150,10 @@ void ivtv_release_stream(struct ivtv_stream *s)
150static void ivtv_dualwatch(struct ivtv *itv) 150static void ivtv_dualwatch(struct ivtv *itv)
151{ 151{
152 struct v4l2_tuner vt; 152 struct v4l2_tuner vt;
153 u32 new_bitmap;
154 u32 new_stereo_mode; 153 u32 new_stereo_mode;
155 const u32 stereo_mask = 0x0300; 154 const u32 dual = 0x02;
156 const u32 dual = 0x0200;
157 155
158 new_stereo_mode = itv->params.audio_properties & stereo_mask; 156 new_stereo_mode = v4l2_ctrl_g_ctrl(itv->cxhdl.audio_mode);
159 memset(&vt, 0, sizeof(vt)); 157 memset(&vt, 0, sizeof(vt));
160 ivtv_call_all(itv, tuner, g_tuner, &vt); 158 ivtv_call_all(itv, tuner, g_tuner, &vt);
161 if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 && (vt.rxsubchans & V4L2_TUNER_SUB_LANG2)) 159 if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 && (vt.rxsubchans & V4L2_TUNER_SUB_LANG2))
@@ -164,16 +162,10 @@ static void ivtv_dualwatch(struct ivtv *itv)
164 if (new_stereo_mode == itv->dualwatch_stereo_mode) 162 if (new_stereo_mode == itv->dualwatch_stereo_mode)
165 return; 163 return;
166 164
167 new_bitmap = new_stereo_mode | (itv->params.audio_properties & ~stereo_mask); 165 IVTV_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x.\n",
168 166 itv->dualwatch_stereo_mode, new_stereo_mode);
169 IVTV_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. new audio_bitmask=0x%ux\n", 167 if (v4l2_ctrl_s_ctrl(itv->cxhdl.audio_mode, new_stereo_mode))
170 itv->dualwatch_stereo_mode, new_stereo_mode, new_bitmap); 168 IVTV_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
171
172 if (ivtv_vapi(itv, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new_bitmap) == 0) {
173 itv->dualwatch_stereo_mode = new_stereo_mode;
174 return;
175 }
176 IVTV_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
177} 169}
178 170
179static void ivtv_update_pgm_info(struct ivtv *itv) 171static void ivtv_update_pgm_info(struct ivtv *itv)
@@ -894,7 +886,8 @@ int ivtv_v4l2_close(struct file *filp)
894 if (atomic_read(&itv->capturing) > 0) { 886 if (atomic_read(&itv->capturing) > 0) {
895 /* Undo video mute */ 887 /* Undo video mute */
896 ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1, 888 ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1,
897 itv->params.video_mute | (itv->params.video_mute_yuv << 8)); 889 v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) |
890 (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
898 } 891 }
899 /* Done! Unmute and continue. */ 892 /* Done! Unmute and continue. */
900 ivtv_unmute(itv); 893 ivtv_unmute(itv);
diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c
index d8bf2b01729..4df01947a7d 100644
--- a/drivers/media/video/ivtv/ivtv-firmware.c
+++ b/drivers/media/video/ivtv/ivtv-firmware.c
@@ -248,9 +248,9 @@ void ivtv_init_mpeg_decoder(struct ivtv *itv)
248 volatile u8 __iomem *mem_offset; 248 volatile u8 __iomem *mem_offset;
249 249
250 data[0] = 0; 250 data[0] = 0;
251 data[1] = itv->params.width; /* YUV source width */ 251 data[1] = itv->cxhdl.width; /* YUV source width */
252 data[2] = itv->params.height; 252 data[2] = itv->cxhdl.height;
253 data[3] = itv->params.audio_properties; /* Audio settings to use, 253 data[3] = itv->cxhdl.audio_properties; /* Audio settings to use,
254 bitmap. see docs. */ 254 bitmap. see docs. */
255 if (ivtv_api(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, data)) { 255 if (ivtv_api(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, data)) {
256 IVTV_ERR("ivtv_init_mpeg_decoder failed to set decoder source\n"); 256 IVTV_ERR("ivtv_init_mpeg_decoder failed to set decoder source\n");
diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c
index aede061cae5..8f0d0778905 100644
--- a/drivers/media/video/ivtv/ivtv-gpio.c
+++ b/drivers/media/video/ivtv/ivtv-gpio.c
@@ -24,6 +24,7 @@
24#include "ivtv-gpio.h" 24#include "ivtv-gpio.h"
25#include "tuner-xc2028.h" 25#include "tuner-xc2028.h"
26#include <media/tuner.h> 26#include <media/tuner.h>
27#include <media/v4l2-ctrls.h>
27 28
28/* 29/*
29 * GPIO assignment of Yuan MPG600/MPG160 30 * GPIO assignment of Yuan MPG600/MPG160
@@ -149,16 +150,10 @@ static inline struct ivtv *sd_to_ivtv(struct v4l2_subdev *sd)
149 return container_of(sd, struct ivtv, sd_gpio); 150 return container_of(sd, struct ivtv, sd_gpio);
150} 151}
151 152
152static struct v4l2_queryctrl gpio_ctrl_mute = { 153static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
153 .id = V4L2_CID_AUDIO_MUTE, 154{
154 .type = V4L2_CTRL_TYPE_BOOLEAN, 155 return &container_of(ctrl->handler, struct ivtv, hdl_gpio)->sd_gpio;
155 .name = "Mute", 156}
156 .minimum = 0,
157 .maximum = 1,
158 .step = 1,
159 .default_value = 1,
160 .flags = 0,
161};
162 157
163static int subdev_s_clock_freq(struct v4l2_subdev *sd, u32 freq) 158static int subdev_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
164{ 159{
@@ -262,40 +257,24 @@ static int subdev_s_audio_routing(struct v4l2_subdev *sd,
262 return 0; 257 return 0;
263} 258}
264 259
265static int subdev_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 260static int subdev_s_ctrl(struct v4l2_ctrl *ctrl)
266{ 261{
262 struct v4l2_subdev *sd = to_sd(ctrl);
267 struct ivtv *itv = sd_to_ivtv(sd); 263 struct ivtv *itv = sd_to_ivtv(sd);
268 u16 mask, data; 264 u16 mask, data;
269 265
270 if (ctrl->id != V4L2_CID_AUDIO_MUTE) 266 switch (ctrl->id) {
271 return -EINVAL; 267 case V4L2_CID_AUDIO_MUTE:
272 mask = itv->card->gpio_audio_mute.mask; 268 mask = itv->card->gpio_audio_mute.mask;
273 data = itv->card->gpio_audio_mute.mute; 269 data = ctrl->val ? itv->card->gpio_audio_mute.mute : 0;
274 ctrl->value = (read_reg(IVTV_REG_GPIO_OUT) & mask) == data; 270 if (mask)
275 return 0; 271 write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) |
276} 272 (data & mask), IVTV_REG_GPIO_OUT);
277 273 return 0;
278static int subdev_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 274 }
279{ 275 return -EINVAL;
280 struct ivtv *itv = sd_to_ivtv(sd);
281 u16 mask, data;
282
283 if (ctrl->id != V4L2_CID_AUDIO_MUTE)
284 return -EINVAL;
285 mask = itv->card->gpio_audio_mute.mask;
286 data = ctrl->value ? itv->card->gpio_audio_mute.mute : 0;
287 if (mask)
288 write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
289 return 0;
290} 276}
291 277
292static int subdev_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
293{
294 if (qc->id != V4L2_CID_AUDIO_MUTE)
295 return -EINVAL;
296 *qc = gpio_ctrl_mute;
297 return 0;
298}
299 278
300static int subdev_log_status(struct v4l2_subdev *sd) 279static int subdev_log_status(struct v4l2_subdev *sd)
301{ 280{
@@ -304,6 +283,7 @@ static int subdev_log_status(struct v4l2_subdev *sd)
304 IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n", 283 IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n",
305 read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT), 284 read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT),
306 read_reg(IVTV_REG_GPIO_IN)); 285 read_reg(IVTV_REG_GPIO_IN));
286 v4l2_ctrl_handler_log_status(&itv->hdl_gpio, sd->name);
307 return 0; 287 return 0;
308} 288}
309 289
@@ -327,11 +307,19 @@ static int subdev_s_video_routing(struct v4l2_subdev *sd,
327 return 0; 307 return 0;
328} 308}
329 309
310static const struct v4l2_ctrl_ops gpio_ctrl_ops = {
311 .s_ctrl = subdev_s_ctrl,
312};
313
330static const struct v4l2_subdev_core_ops subdev_core_ops = { 314static const struct v4l2_subdev_core_ops subdev_core_ops = {
331 .log_status = subdev_log_status, 315 .log_status = subdev_log_status,
332 .g_ctrl = subdev_g_ctrl, 316 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
333 .s_ctrl = subdev_s_ctrl, 317 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
334 .queryctrl = subdev_queryctrl, 318 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
319 .g_ctrl = v4l2_subdev_g_ctrl,
320 .s_ctrl = v4l2_subdev_s_ctrl,
321 .queryctrl = v4l2_subdev_queryctrl,
322 .querymenu = v4l2_subdev_querymenu,
335}; 323};
336 324
337static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = { 325static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = {
@@ -375,5 +363,12 @@ int ivtv_gpio_init(struct ivtv *itv)
375 v4l2_subdev_init(&itv->sd_gpio, &subdev_ops); 363 v4l2_subdev_init(&itv->sd_gpio, &subdev_ops);
376 snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->v4l2_dev.name); 364 snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->v4l2_dev.name);
377 itv->sd_gpio.grp_id = IVTV_HW_GPIO; 365 itv->sd_gpio.grp_id = IVTV_HW_GPIO;
366 v4l2_ctrl_handler_init(&itv->hdl_gpio, 1);
367 v4l2_ctrl_new_std(&itv->hdl_gpio, &gpio_ctrl_ops,
368 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
369 if (itv->hdl_gpio.error)
370 return itv->hdl_gpio.error;
371 itv->sd_gpio.ctrl_handler = &itv->hdl_gpio;
372 v4l2_ctrl_handler_setup(&itv->hdl_gpio);
378 return v4l2_device_register_subdev(&itv->v4l2_dev, &itv->sd_gpio); 373 return v4l2_device_register_subdev(&itv->v4l2_dev, &itv->sd_gpio);
379} 374}
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
index a5b92d109c6..d391bbdb0b8 100644
--- a/drivers/media/video/ivtv/ivtv-i2c.c
+++ b/drivers/media/video/ivtv/ivtv-i2c.c
@@ -63,6 +63,7 @@
63#include "ivtv-cards.h" 63#include "ivtv-cards.h"
64#include "ivtv-gpio.h" 64#include "ivtv-gpio.h"
65#include "ivtv-i2c.h" 65#include "ivtv-i2c.h"
66#include <media/cx25840.h>
66 67
67/* i2c implementation for cx23415/6 chip, ivtv project. 68/* i2c implementation for cx23415/6 chip, ivtv project.
68 * Author: Kevin Thayer (nufan_wfk at yahoo.com) 69 * Author: Kevin Thayer (nufan_wfk at yahoo.com)
@@ -292,6 +293,12 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
292 if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) { 293 if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) {
293 sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, 294 sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
294 adap, mod, type, 0, I2C_ADDRS(hw_addrs[idx])); 295 adap, mod, type, 0, I2C_ADDRS(hw_addrs[idx]));
296 } else if (hw == IVTV_HW_CX25840) {
297 struct cx25840_platform_data pdata;
298
299 pdata.pvr150_workaround = itv->pvr150_workaround;
300 sd = v4l2_i2c_new_subdev_cfg(&itv->v4l2_dev,
301 adap, mod, type, 0, &pdata, hw_addrs[idx], NULL);
295 } else { 302 } else {
296 sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, 303 sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
297 adap, mod, type, hw_addrs[idx], NULL); 304 adap, mod, type, hw_addrs[idx], NULL);
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 11ac2fa33ef..4eed9123683 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -162,7 +162,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed)
162 data[0] |= (speed > 1000 || speed < -1500) ? 0x40000000 : 0; 162 data[0] |= (speed > 1000 || speed < -1500) ? 0x40000000 : 0;
163 data[1] = (speed < 0); 163 data[1] = (speed < 0);
164 data[2] = speed < 0 ? 3 : 7; 164 data[2] = speed < 0 ? 3 : 7;
165 data[3] = itv->params.video_b_frames; 165 data[3] = v4l2_ctrl_g_ctrl(itv->cxhdl.video_b_frames);
166 data[4] = (speed == 1500 || speed == 500) ? itv->speed_mute_audio : 0; 166 data[4] = (speed == 1500 || speed == 500) ? itv->speed_mute_audio : 0;
167 data[5] = 0; 167 data[5] = 0;
168 data[6] = 0; 168 data[6] = 0;
@@ -339,8 +339,8 @@ static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
339 struct ivtv *itv = id->itv; 339 struct ivtv *itv = id->itv;
340 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; 340 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
341 341
342 pixfmt->width = itv->params.width; 342 pixfmt->width = itv->cxhdl.width;
343 pixfmt->height = itv->params.height; 343 pixfmt->height = itv->cxhdl.height;
344 pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M; 344 pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
345 pixfmt->field = V4L2_FIELD_INTERLACED; 345 pixfmt->field = V4L2_FIELD_INTERLACED;
346 pixfmt->priv = 0; 346 pixfmt->priv = 0;
@@ -568,7 +568,6 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
568{ 568{
569 struct ivtv_open_id *id = fh; 569 struct ivtv_open_id *id = fh;
570 struct ivtv *itv = id->itv; 570 struct ivtv *itv = id->itv;
571 struct cx2341x_mpeg_params *p = &itv->params;
572 struct v4l2_mbus_framefmt mbus_fmt; 571 struct v4l2_mbus_framefmt mbus_fmt;
573 int ret = ivtv_try_fmt_vid_cap(file, fh, fmt); 572 int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
574 int w = fmt->fmt.pix.width; 573 int w = fmt->fmt.pix.width;
@@ -577,15 +576,15 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
577 if (ret) 576 if (ret)
578 return ret; 577 return ret;
579 578
580 if (p->width == w && p->height == h) 579 if (itv->cxhdl.width == w && itv->cxhdl.height == h)
581 return 0; 580 return 0;
582 581
583 if (atomic_read(&itv->capturing) > 0) 582 if (atomic_read(&itv->capturing) > 0)
584 return -EBUSY; 583 return -EBUSY;
585 584
586 p->width = w; 585 itv->cxhdl.width = w;
587 p->height = h; 586 itv->cxhdl.height = h;
588 if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) 587 if (v4l2_ctrl_g_ctrl(itv->cxhdl.video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
589 fmt->fmt.pix.width /= 2; 588 fmt->fmt.pix.width /= 2;
590 mbus_fmt.width = fmt->fmt.pix.width; 589 mbus_fmt.width = fmt->fmt.pix.width;
591 mbus_fmt.height = h; 590 mbus_fmt.height = h;
@@ -1114,9 +1113,10 @@ int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
1114 1113
1115 itv->std = *std; 1114 itv->std = *std;
1116 itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0; 1115 itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
1117 itv->params.is_50hz = itv->is_50hz = !itv->is_60hz; 1116 itv->is_50hz = !itv->is_60hz;
1118 itv->params.width = 720; 1117 cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz);
1119 itv->params.height = itv->is_50hz ? 576 : 480; 1118 itv->cxhdl.width = 720;
1119 itv->cxhdl.height = itv->is_50hz ? 576 : 480;
1120 itv->vbi.count = itv->is_50hz ? 18 : 12; 1120 itv->vbi.count = itv->is_50hz ? 18 : 12;
1121 itv->vbi.start[0] = itv->is_50hz ? 6 : 10; 1121 itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
1122 itv->vbi.start[1] = itv->is_50hz ? 318 : 273; 1122 itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
@@ -1157,7 +1157,7 @@ int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
1157 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz); 1157 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1158 itv->main_rect.left = itv->main_rect.top = 0; 1158 itv->main_rect.left = itv->main_rect.top = 0;
1159 itv->main_rect.width = 720; 1159 itv->main_rect.width = 720;
1160 itv->main_rect.height = itv->params.height; 1160 itv->main_rect.height = itv->cxhdl.height;
1161 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, 1161 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1162 720, itv->main_rect.height, 0, 0); 1162 720, itv->main_rect.height, 0, 0);
1163 yi->main_rect = itv->main_rect; 1163 yi->main_rect = itv->main_rect;
@@ -1554,7 +1554,7 @@ static int ivtv_log_status(struct file *file, void *fh)
1554 } 1554 }
1555 IVTV_INFO("Tuner: %s\n", 1555 IVTV_INFO("Tuner: %s\n",
1556 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); 1556 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
1557 cx2341x_log_status(&itv->params, itv->v4l2_dev.name); 1557 v4l2_ctrl_handler_log_status(&itv->cxhdl.hdl, itv->v4l2_dev.name);
1558 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags); 1558 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
1559 for (i = 0; i < IVTV_MAX_STREAMS; i++) { 1559 for (i = 0; i < IVTV_MAX_STREAMS; i++) {
1560 struct ivtv_stream *s = &itv->streams[i]; 1560 struct ivtv_stream *s = &itv->streams[i];
@@ -1942,11 +1942,6 @@ static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
1942 .vidioc_s_register = ivtv_s_register, 1942 .vidioc_s_register = ivtv_s_register,
1943#endif 1943#endif
1944 .vidioc_default = ivtv_default, 1944 .vidioc_default = ivtv_default,
1945 .vidioc_queryctrl = ivtv_queryctrl,
1946 .vidioc_querymenu = ivtv_querymenu,
1947 .vidioc_g_ext_ctrls = ivtv_g_ext_ctrls,
1948 .vidioc_s_ext_ctrls = ivtv_s_ext_ctrls,
1949 .vidioc_try_ext_ctrls = ivtv_try_ext_ctrls,
1950 .vidioc_subscribe_event = ivtv_subscribe_event, 1945 .vidioc_subscribe_event = ivtv_subscribe_event,
1951 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 1946 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1952}; 1947};
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index 55df4190c28..512607e0cda 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -210,6 +210,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
210 210
211 s->vdev->num = num; 211 s->vdev->num = num;
212 s->vdev->v4l2_dev = &itv->v4l2_dev; 212 s->vdev->v4l2_dev = &itv->v4l2_dev;
213 s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler;
213 s->vdev->fops = ivtv_stream_info[type].fops; 214 s->vdev->fops = ivtv_stream_info[type].fops;
214 s->vdev->release = video_device_release; 215 s->vdev->release = video_device_release;
215 s->vdev->tvnorms = V4L2_STD_ALL; 216 s->vdev->tvnorms = V4L2_STD_ALL;
@@ -451,7 +452,6 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
451{ 452{
452 u32 data[CX2341X_MBOX_MAX_DATA]; 453 u32 data[CX2341X_MBOX_MAX_DATA];
453 struct ivtv *itv = s->itv; 454 struct ivtv *itv = s->itv;
454 struct cx2341x_mpeg_params *p = &itv->params;
455 int captype = 0, subtype = 0; 455 int captype = 0, subtype = 0;
456 int enable_passthrough = 0; 456 int enable_passthrough = 0;
457 457
@@ -472,7 +472,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
472 } 472 }
473 itv->mpg_data_received = itv->vbi_data_inserted = 0; 473 itv->mpg_data_received = itv->vbi_data_inserted = 0;
474 itv->dualwatch_jiffies = jiffies; 474 itv->dualwatch_jiffies = jiffies;
475 itv->dualwatch_stereo_mode = p->audio_properties & 0x0300; 475 itv->dualwatch_stereo_mode = v4l2_ctrl_g_ctrl(itv->cxhdl.audio_mode);
476 itv->search_pack_header = 0; 476 itv->search_pack_header = 0;
477 break; 477 break;
478 478
@@ -560,12 +560,12 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
560 itv->pgm_info_offset, itv->pgm_info_num); 560 itv->pgm_info_offset, itv->pgm_info_num);
561 561
562 /* Setup API for Stream */ 562 /* Setup API for Stream */
563 cx2341x_update(itv, ivtv_api_func, NULL, p); 563 cx2341x_handler_setup(&itv->cxhdl);
564 564
565 /* mute if capturing radio */ 565 /* mute if capturing radio */
566 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) 566 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags))
567 ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1, 567 ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1,
568 1 | (p->video_mute_yuv << 8)); 568 1 | (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
569 } 569 }
570 570
571 /* Vsync Setup */ 571 /* Vsync Setup */
@@ -581,6 +581,8 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
581 581
582 clear_bit(IVTV_F_I_EOS, &itv->i_flags); 582 clear_bit(IVTV_F_I_EOS, &itv->i_flags);
583 583
584 cx2341x_handler_set_busy(&itv->cxhdl, 1);
585
584 /* Initialize Digitizer for Capture */ 586 /* Initialize Digitizer for Capture */
585 /* Avoid tinny audio problem - ensure audio clocks are going */ 587 /* Avoid tinny audio problem - ensure audio clocks are going */
586 v4l2_subdev_call(itv->sd_audio, audio, s_stream, 1); 588 v4l2_subdev_call(itv->sd_audio, audio, s_stream, 1);
@@ -617,7 +619,6 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
617{ 619{
618 u32 data[CX2341X_MBOX_MAX_DATA]; 620 u32 data[CX2341X_MBOX_MAX_DATA];
619 struct ivtv *itv = s->itv; 621 struct ivtv *itv = s->itv;
620 struct cx2341x_mpeg_params *p = &itv->params;
621 int datatype; 622 int datatype;
622 u16 width; 623 u16 width;
623 u16 height; 624 u16 height;
@@ -627,8 +628,8 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
627 628
628 IVTV_DEBUG_INFO("Setting some initial decoder settings\n"); 629 IVTV_DEBUG_INFO("Setting some initial decoder settings\n");
629 630
630 width = p->width; 631 width = itv->cxhdl.width;
631 height = p->height; 632 height = itv->cxhdl.height;
632 633
633 /* set audio mode to left/stereo for dual/stereo mode. */ 634 /* set audio mode to left/stereo for dual/stereo mode. */
634 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); 635 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
@@ -668,7 +669,7 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
668 break; 669 break;
669 } 670 }
670 if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype, 671 if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype,
671 width, height, p->audio_properties)) { 672 width, height, itv->cxhdl.audio_properties)) {
672 IVTV_DEBUG_WARN("Couldn't initialize decoder source\n"); 673 IVTV_DEBUG_WARN("Couldn't initialize decoder source\n");
673 } 674 }
674 675
@@ -847,6 +848,8 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
847 return 0; 848 return 0;
848 } 849 }
849 850
851 cx2341x_handler_set_busy(&itv->cxhdl, 0);
852
850 /* Set the following Interrupt mask bits for capture */ 853 /* Set the following Interrupt mask bits for capture */
851 ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); 854 ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);
852 del_timer(&itv->dma_timer); 855 del_timer(&itv->dma_timer);
@@ -967,7 +970,8 @@ int ivtv_passthrough_mode(struct ivtv *itv, int enable)
967 970
968 /* Setup capture if not already done */ 971 /* Setup capture if not already done */
969 if (atomic_read(&itv->capturing) == 0) { 972 if (atomic_read(&itv->capturing) == 0) {
970 cx2341x_update(itv, ivtv_api_func, NULL, &itv->params); 973 cx2341x_handler_setup(&itv->cxhdl);
974 cx2341x_handler_set_busy(&itv->cxhdl, 1);
971 } 975 }
972 976
973 /* Start Passthrough Mode */ 977 /* Start Passthrough Mode */
@@ -988,6 +992,8 @@ int ivtv_passthrough_mode(struct ivtv *itv, int enable)
988 clear_bit(IVTV_F_S_PASSTHROUGH, &dec_stream->s_flags); 992 clear_bit(IVTV_F_S_PASSTHROUGH, &dec_stream->s_flags);
989 clear_bit(IVTV_F_S_STREAMING, &dec_stream->s_flags); 993 clear_bit(IVTV_F_S_STREAMING, &dec_stream->s_flags);
990 itv->output_mode = OUT_NONE; 994 itv->output_mode = OUT_NONE;
995 if (atomic_read(&itv->capturing) == 0)
996 cx2341x_handler_set_busy(&itv->cxhdl, 0);
991 997
992 return 0; 998 return 0;
993} 999}
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index e9df3cb02cc..0e412131da7 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -283,51 +283,6 @@ void msp_set_scart(struct i2c_client *client, int in, int out)
283 msp_write_dem(client, 0x40, state->i2s_mode); 283 msp_write_dem(client, 0x40, state->i2s_mode);
284} 284}
285 285
286void msp_set_audio(struct i2c_client *client)
287{
288 struct msp_state *state = to_state(i2c_get_clientdata(client));
289 int bal = 0, bass, treble, loudness;
290 int val = 0;
291 int reallymuted = state->muted | state->scan_in_progress;
292
293 if (!reallymuted)
294 val = (state->volume * 0x7f / 65535) << 8;
295
296 v4l_dbg(1, msp_debug, client, "mute=%s scanning=%s volume=%d\n",
297 state->muted ? "on" : "off",
298 state->scan_in_progress ? "yes" : "no",
299 state->volume);
300
301 msp_write_dsp(client, 0x0000, val);
302 msp_write_dsp(client, 0x0007, reallymuted ? 0x1 : (val | 0x1));
303 if (state->has_scart2_out_volume)
304 msp_write_dsp(client, 0x0040, reallymuted ? 0x1 : (val | 0x1));
305 if (state->has_headphones)
306 msp_write_dsp(client, 0x0006, val);
307 if (!state->has_sound_processing)
308 return;
309
310 if (val)
311 bal = (u8)((state->balance / 256) - 128);
312 bass = ((state->bass - 32768) * 0x60 / 65535) << 8;
313 treble = ((state->treble - 32768) * 0x60 / 65535) << 8;
314 loudness = state->loudness ? ((5 * 4) << 8) : 0;
315
316 v4l_dbg(1, msp_debug, client, "balance=%d bass=%d treble=%d loudness=%d\n",
317 state->balance, state->bass, state->treble, state->loudness);
318
319 msp_write_dsp(client, 0x0001, bal << 8);
320 msp_write_dsp(client, 0x0002, bass);
321 msp_write_dsp(client, 0x0003, treble);
322 msp_write_dsp(client, 0x0004, loudness);
323 if (!state->has_headphones)
324 return;
325 msp_write_dsp(client, 0x0030, bal << 8);
326 msp_write_dsp(client, 0x0031, bass);
327 msp_write_dsp(client, 0x0032, treble);
328 msp_write_dsp(client, 0x0033, loudness);
329}
330
331/* ------------------------------------------------------------------------ */ 286/* ------------------------------------------------------------------------ */
332 287
333static void msp_wake_thread(struct i2c_client *client) 288static void msp_wake_thread(struct i2c_client *client)
@@ -363,98 +318,73 @@ int msp_sleep(struct msp_state *state, int timeout)
363 318
364/* ------------------------------------------------------------------------ */ 319/* ------------------------------------------------------------------------ */
365 320
366static int msp_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 321static int msp_s_ctrl(struct v4l2_ctrl *ctrl)
367{ 322{
368 struct msp_state *state = to_state(sd); 323 struct msp_state *state = ctrl_to_state(ctrl);
324 struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
325 int val = ctrl->val;
369 326
370 switch (ctrl->id) { 327 switch (ctrl->id) {
371 case V4L2_CID_AUDIO_VOLUME: 328 case V4L2_CID_AUDIO_VOLUME: {
372 ctrl->value = state->volume; 329 /* audio volume cluster */
373 break; 330 int reallymuted = state->muted->val | state->scan_in_progress;
374 331
375 case V4L2_CID_AUDIO_MUTE: 332 if (!reallymuted)
376 ctrl->value = state->muted; 333 val = (val * 0x7f / 65535) << 8;
377 break; 334
378 335 v4l_dbg(1, msp_debug, client, "mute=%s scanning=%s volume=%d\n",
379 case V4L2_CID_AUDIO_BALANCE: 336 state->muted->val ? "on" : "off",
380 if (!state->has_sound_processing) 337 state->scan_in_progress ? "yes" : "no",
381 return -EINVAL; 338 state->volume->val);
382 ctrl->value = state->balance; 339
383 break; 340 msp_write_dsp(client, 0x0000, val);
384 341 msp_write_dsp(client, 0x0007, reallymuted ? 0x1 : (val | 0x1));
385 case V4L2_CID_AUDIO_BASS: 342 if (state->has_scart2_out_volume)
386 if (!state->has_sound_processing) 343 msp_write_dsp(client, 0x0040, reallymuted ? 0x1 : (val | 0x1));
387 return -EINVAL; 344 if (state->has_headphones)
388 ctrl->value = state->bass; 345 msp_write_dsp(client, 0x0006, val);
389 break; 346 break;
390
391 case V4L2_CID_AUDIO_TREBLE:
392 if (!state->has_sound_processing)
393 return -EINVAL;
394 ctrl->value = state->treble;
395 break;
396
397 case V4L2_CID_AUDIO_LOUDNESS:
398 if (!state->has_sound_processing)
399 return -EINVAL;
400 ctrl->value = state->loudness;
401 break;
402
403 default:
404 return -EINVAL;
405 } 347 }
406 return 0;
407}
408
409static int msp_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
410{
411 struct msp_state *state = to_state(sd);
412 struct i2c_client *client = v4l2_get_subdevdata(sd);
413
414 switch (ctrl->id) {
415 case V4L2_CID_AUDIO_VOLUME:
416 state->volume = ctrl->value;
417 if (state->volume == 0)
418 state->balance = 32768;
419 break;
420
421 case V4L2_CID_AUDIO_MUTE:
422 if (ctrl->value < 0 || ctrl->value >= 2)
423 return -ERANGE;
424 state->muted = ctrl->value;
425 break;
426 348
427 case V4L2_CID_AUDIO_BASS: 349 case V4L2_CID_AUDIO_BASS:
428 if (!state->has_sound_processing) 350 val = ((val - 32768) * 0x60 / 65535) << 8;
429 return -EINVAL; 351 msp_write_dsp(client, 0x0002, val);
430 state->bass = ctrl->value; 352 if (state->has_headphones)
353 msp_write_dsp(client, 0x0031, val);
431 break; 354 break;
432 355
433 case V4L2_CID_AUDIO_TREBLE: 356 case V4L2_CID_AUDIO_TREBLE:
434 if (!state->has_sound_processing) 357 val = ((val - 32768) * 0x60 / 65535) << 8;
435 return -EINVAL; 358 msp_write_dsp(client, 0x0003, val);
436 state->treble = ctrl->value; 359 if (state->has_headphones)
360 msp_write_dsp(client, 0x0032, val);
437 break; 361 break;
438 362
439 case V4L2_CID_AUDIO_LOUDNESS: 363 case V4L2_CID_AUDIO_LOUDNESS:
440 if (!state->has_sound_processing) 364 val = val ? ((5 * 4) << 8) : 0;
441 return -EINVAL; 365 msp_write_dsp(client, 0x0004, val);
442 state->loudness = ctrl->value; 366 if (state->has_headphones)
367 msp_write_dsp(client, 0x0033, val);
443 break; 368 break;
444 369
445 case V4L2_CID_AUDIO_BALANCE: 370 case V4L2_CID_AUDIO_BALANCE:
446 if (!state->has_sound_processing) 371 val = (u8)((val / 256) - 128);
447 return -EINVAL; 372 msp_write_dsp(client, 0x0001, val << 8);
448 state->balance = ctrl->value; 373 if (state->has_headphones)
374 msp_write_dsp(client, 0x0030, val << 8);
449 break; 375 break;
450 376
451 default: 377 default:
452 return -EINVAL; 378 return -EINVAL;
453 } 379 }
454 msp_set_audio(client);
455 return 0; 380 return 0;
456} 381}
457 382
383void msp_update_volume(struct msp_state *state)
384{
385 v4l2_ctrl_s_ctrl(state->volume, v4l2_ctrl_g_ctrl(state->volume));
386}
387
458/* --- v4l2 ioctls --- */ 388/* --- v4l2 ioctls --- */
459static int msp_s_radio(struct v4l2_subdev *sd) 389static int msp_s_radio(struct v4l2_subdev *sd)
460{ 390{
@@ -472,7 +402,7 @@ static int msp_s_radio(struct v4l2_subdev *sd)
472 msp3400c_set_mode(client, MSP_MODE_FM_RADIO); 402 msp3400c_set_mode(client, MSP_MODE_FM_RADIO);
473 msp3400c_set_carrier(client, MSP_CARRIER(10.7), 403 msp3400c_set_carrier(client, MSP_CARRIER(10.7),
474 MSP_CARRIER(10.7)); 404 MSP_CARRIER(10.7));
475 msp_set_audio(client); 405 msp_update_volume(state);
476 break; 406 break;
477 case OPMODE_AUTODETECT: 407 case OPMODE_AUTODETECT:
478 case OPMODE_AUTOSELECT: 408 case OPMODE_AUTOSELECT:
@@ -592,33 +522,6 @@ static int msp_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq)
592 return 0; 522 return 0;
593} 523}
594 524
595static int msp_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
596{
597 struct msp_state *state = to_state(sd);
598
599 switch (qc->id) {
600 case V4L2_CID_AUDIO_VOLUME:
601 return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880);
602 case V4L2_CID_AUDIO_MUTE:
603 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
604 default:
605 break;
606 }
607 if (!state->has_sound_processing)
608 return -EINVAL;
609 switch (qc->id) {
610 case V4L2_CID_AUDIO_LOUDNESS:
611 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
612 case V4L2_CID_AUDIO_BALANCE:
613 case V4L2_CID_AUDIO_BASS:
614 case V4L2_CID_AUDIO_TREBLE:
615 return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
616 default:
617 return -EINVAL;
618 }
619 return 0;
620}
621
622static int msp_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) 525static int msp_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
623{ 526{
624 struct msp_state *state = to_state(sd); 527 struct msp_state *state = to_state(sd);
@@ -633,19 +536,14 @@ static int msp_log_status(struct v4l2_subdev *sd)
633 struct msp_state *state = to_state(sd); 536 struct msp_state *state = to_state(sd);
634 struct i2c_client *client = v4l2_get_subdevdata(sd); 537 struct i2c_client *client = v4l2_get_subdevdata(sd);
635 const char *p; 538 const char *p;
539 char prefix[V4L2_SUBDEV_NAME_SIZE + 20];
636 540
637 if (state->opmode == OPMODE_AUTOSELECT) 541 if (state->opmode == OPMODE_AUTOSELECT)
638 msp_detect_stereo(client); 542 msp_detect_stereo(client);
639 v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n", 543 v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n",
640 client->name, state->rev1, state->rev2); 544 client->name, state->rev1, state->rev2);
641 v4l_info(client, "Audio: volume %d%s\n", 545 snprintf(prefix, sizeof(prefix), "%s: Audio: ", sd->name);
642 state->volume, state->muted ? " (muted)" : ""); 546 v4l2_ctrl_handler_log_status(&state->hdl, prefix);
643 if (state->has_sound_processing) {
644 v4l_info(client, "Audio: balance %d bass %d treble %d loudness %s\n",
645 state->balance, state->bass,
646 state->treble,
647 state->loudness ? "on" : "off");
648 }
649 switch (state->mode) { 547 switch (state->mode) {
650 case MSP_MODE_AM_DETECT: p = "AM (for carrier detect)"; break; 548 case MSP_MODE_AM_DETECT: p = "AM (for carrier detect)"; break;
651 case MSP_MODE_FM_RADIO: p = "FM Radio"; break; 549 case MSP_MODE_FM_RADIO: p = "FM Radio"; break;
@@ -695,12 +593,20 @@ static int msp_resume(struct i2c_client *client)
695 593
696/* ----------------------------------------------------------------------- */ 594/* ----------------------------------------------------------------------- */
697 595
596static const struct v4l2_ctrl_ops msp_ctrl_ops = {
597 .s_ctrl = msp_s_ctrl,
598};
599
698static const struct v4l2_subdev_core_ops msp_core_ops = { 600static const struct v4l2_subdev_core_ops msp_core_ops = {
699 .log_status = msp_log_status, 601 .log_status = msp_log_status,
700 .g_chip_ident = msp_g_chip_ident, 602 .g_chip_ident = msp_g_chip_ident,
701 .g_ctrl = msp_g_ctrl, 603 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
702 .s_ctrl = msp_s_ctrl, 604 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
703 .queryctrl = msp_queryctrl, 605 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
606 .g_ctrl = v4l2_subdev_g_ctrl,
607 .s_ctrl = v4l2_subdev_s_ctrl,
608 .queryctrl = v4l2_subdev_queryctrl,
609 .querymenu = v4l2_subdev_querymenu,
704 .s_std = msp_s_std, 610 .s_std = msp_s_std,
705}; 611};
706 612
@@ -728,6 +634,7 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
728{ 634{
729 struct msp_state *state; 635 struct msp_state *state;
730 struct v4l2_subdev *sd; 636 struct v4l2_subdev *sd;
637 struct v4l2_ctrl_handler *hdl;
731 int (*thread_func)(void *data) = NULL; 638 int (*thread_func)(void *data) = NULL;
732 int msp_hard; 639 int msp_hard;
733 int msp_family; 640 int msp_family;
@@ -752,13 +659,7 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
752 659
753 state->v4l2_std = V4L2_STD_NTSC; 660 state->v4l2_std = V4L2_STD_NTSC;
754 state->audmode = V4L2_TUNER_MODE_STEREO; 661 state->audmode = V4L2_TUNER_MODE_STEREO;
755 state->volume = 58880; /* 0db gain */
756 state->balance = 32768; /* 0db gain */
757 state->bass = 32768;
758 state->treble = 32768;
759 state->loudness = 0;
760 state->input = -1; 662 state->input = -1;
761 state->muted = 0;
762 state->i2s_mode = 0; 663 state->i2s_mode = 0;
763 init_waitqueue_head(&state->wq); 664 init_waitqueue_head(&state->wq);
764 /* These are the reset input/output positions */ 665 /* These are the reset input/output positions */
@@ -777,8 +678,6 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
777 return -ENODEV; 678 return -ENODEV;
778 } 679 }
779 680
780 msp_set_audio(client);
781
782 msp_family = ((state->rev1 >> 4) & 0x0f) + 3; 681 msp_family = ((state->rev1 >> 4) & 0x0f) + 3;
783 msp_product = (state->rev2 >> 8) & 0xff; 682 msp_product = (state->rev2 >> 8) & 0xff;
784 msp_prod_hi = msp_product / 10; 683 msp_prod_hi = msp_product / 10;
@@ -849,6 +748,34 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
849 state->opmode = OPMODE_MANUAL; 748 state->opmode = OPMODE_MANUAL;
850 } 749 }
851 750
751 hdl = &state->hdl;
752 v4l2_ctrl_handler_init(hdl, 6);
753 if (state->has_sound_processing) {
754 v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
755 V4L2_CID_AUDIO_BASS, 0, 65535, 65535 / 100, 32768);
756 v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
757 V4L2_CID_AUDIO_TREBLE, 0, 65535, 65535 / 100, 32768);
758 v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
759 V4L2_CID_AUDIO_LOUDNESS, 0, 1, 1, 0);
760 }
761 state->volume = v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
762 V4L2_CID_AUDIO_VOLUME, 0, 65535, 65535 / 100, 58880);
763 v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
764 V4L2_CID_AUDIO_BALANCE, 0, 65535, 65535 / 100, 32768);
765 state->muted = v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
766 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
767 sd->ctrl_handler = hdl;
768 if (hdl->error) {
769 int err = hdl->error;
770
771 v4l2_ctrl_handler_free(hdl);
772 kfree(state);
773 return err;
774 }
775
776 v4l2_ctrl_cluster(2, &state->volume);
777 v4l2_ctrl_handler_setup(hdl);
778
852 /* hello world :-) */ 779 /* hello world :-) */
853 v4l_info(client, "MSP%d4%02d%c-%c%d found @ 0x%x (%s)\n", 780 v4l_info(client, "MSP%d4%02d%c-%c%d found @ 0x%x (%s)\n",
854 msp_family, msp_product, 781 msp_family, msp_product,
@@ -903,6 +830,7 @@ static int msp_remove(struct i2c_client *client)
903 } 830 }
904 msp_reset(client); 831 msp_reset(client);
905 832
833 v4l2_ctrl_handler_free(&state->hdl);
906 kfree(state); 834 kfree(state);
907 return 0; 835 return 0;
908} 836}
diff --git a/drivers/media/video/msp3400-driver.h b/drivers/media/video/msp3400-driver.h
index d6b3e6d0eef..32a478e532f 100644
--- a/drivers/media/video/msp3400-driver.h
+++ b/drivers/media/video/msp3400-driver.h
@@ -6,6 +6,7 @@
6 6
7#include <media/msp3400.h> 7#include <media/msp3400.h>
8#include <media/v4l2-device.h> 8#include <media/v4l2-device.h>
9#include <media/v4l2-ctrls.h>
9 10
10/* ---------------------------------------------------------------------- */ 11/* ---------------------------------------------------------------------- */
11 12
@@ -51,6 +52,7 @@ extern int msp_stereo_thresh;
51 52
52struct msp_state { 53struct msp_state {
53 struct v4l2_subdev sd; 54 struct v4l2_subdev sd;
55 struct v4l2_ctrl_handler hdl;
54 int rev1, rev2; 56 int rev1, rev2;
55 int ident; 57 int ident;
56 u8 has_nicam; 58 u8 has_nicam;
@@ -87,9 +89,12 @@ struct msp_state {
87 int audmode; 89 int audmode;
88 int rxsubchans; 90 int rxsubchans;
89 91
90 int volume, muted; 92 struct {
91 int balance, loudness; 93 /* volume cluster */
92 int bass, treble; 94 struct v4l2_ctrl *volume;
95 struct v4l2_ctrl *muted;
96 };
97
93 int scan_in_progress; 98 int scan_in_progress;
94 99
95 /* thread */ 100 /* thread */
@@ -104,6 +109,11 @@ static inline struct msp_state *to_state(struct v4l2_subdev *sd)
104 return container_of(sd, struct msp_state, sd); 109 return container_of(sd, struct msp_state, sd);
105} 110}
106 111
112static inline struct msp_state *ctrl_to_state(struct v4l2_ctrl *ctrl)
113{
114 return container_of(ctrl->handler, struct msp_state, hdl);
115}
116
107/* msp3400-driver.c */ 117/* msp3400-driver.c */
108int msp_write_dem(struct i2c_client *client, int addr, int val); 118int msp_write_dem(struct i2c_client *client, int addr, int val);
109int msp_write_dsp(struct i2c_client *client, int addr, int val); 119int msp_write_dsp(struct i2c_client *client, int addr, int val);
@@ -111,7 +121,7 @@ int msp_read_dem(struct i2c_client *client, int addr);
111int msp_read_dsp(struct i2c_client *client, int addr); 121int msp_read_dsp(struct i2c_client *client, int addr);
112int msp_reset(struct i2c_client *client); 122int msp_reset(struct i2c_client *client);
113void msp_set_scart(struct i2c_client *client, int in, int out); 123void msp_set_scart(struct i2c_client *client, int in, int out);
114void msp_set_audio(struct i2c_client *client); 124void msp_update_volume(struct msp_state *state);
115int msp_sleep(struct msp_state *state, int timeout); 125int msp_sleep(struct msp_state *state, int timeout);
116 126
117/* msp3400-kthreads.c */ 127/* msp3400-kthreads.c */
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
index d5a69c5ee5e..b376fcdee65 100644
--- a/drivers/media/video/msp3400-kthreads.c
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -496,13 +496,13 @@ restart:
496 v4l_dbg(1, msp_debug, client, 496 v4l_dbg(1, msp_debug, client,
497 "thread: no carrier scan\n"); 497 "thread: no carrier scan\n");
498 state->scan_in_progress = 0; 498 state->scan_in_progress = 0;
499 msp_set_audio(client); 499 msp_update_volume(state);
500 continue; 500 continue;
501 } 501 }
502 502
503 /* mute audio */ 503 /* mute audio */
504 state->scan_in_progress = 1; 504 state->scan_in_progress = 1;
505 msp_set_audio(client); 505 msp_update_volume(state);
506 506
507 msp3400c_set_mode(client, MSP_MODE_AM_DETECT); 507 msp3400c_set_mode(client, MSP_MODE_AM_DETECT);
508 val1 = val2 = 0; 508 val1 = val2 = 0;
@@ -634,7 +634,7 @@ no_second:
634 /* unmute */ 634 /* unmute */
635 state->scan_in_progress = 0; 635 state->scan_in_progress = 0;
636 msp3400c_set_audmode(client); 636 msp3400c_set_audmode(client);
637 msp_set_audio(client); 637 msp_update_volume(state);
638 638
639 if (msp_debug) 639 if (msp_debug)
640 msp3400c_print_mode(client); 640 msp3400c_print_mode(client);
@@ -679,13 +679,13 @@ restart:
679 v4l_dbg(1, msp_debug, client, 679 v4l_dbg(1, msp_debug, client,
680 "thread: no carrier scan\n"); 680 "thread: no carrier scan\n");
681 state->scan_in_progress = 0; 681 state->scan_in_progress = 0;
682 msp_set_audio(client); 682 msp_update_volume(state);
683 continue; 683 continue;
684 } 684 }
685 685
686 /* mute audio */ 686 /* mute audio */
687 state->scan_in_progress = 1; 687 state->scan_in_progress = 1;
688 msp_set_audio(client); 688 msp_update_volume(state);
689 689
690 /* start autodetect. Note: autodetect is not supported for 690 /* start autodetect. Note: autodetect is not supported for
691 NTSC-M and radio, hence we force the standard in those 691 NTSC-M and radio, hence we force the standard in those
@@ -797,7 +797,7 @@ restart:
797 /* unmute */ 797 /* unmute */
798 msp3400c_set_audmode(client); 798 msp3400c_set_audmode(client);
799 state->scan_in_progress = 0; 799 state->scan_in_progress = 0;
800 msp_set_audio(client); 800 msp_update_volume(state);
801 801
802 /* monitor tv audio mode, the first time don't wait 802 /* monitor tv audio mode, the first time don't wait
803 so long to get a quick stereo/bilingual result */ 803 so long to get a quick stereo/bilingual result */
@@ -974,7 +974,7 @@ restart:
974 v4l_dbg(1, msp_debug, client, 974 v4l_dbg(1, msp_debug, client,
975 "thread: no carrier scan\n"); 975 "thread: no carrier scan\n");
976 state->scan_in_progress = 0; 976 state->scan_in_progress = 0;
977 msp_set_audio(client); 977 msp_update_volume(state);
978 continue; 978 continue;
979 } 979 }
980 980
@@ -1020,7 +1020,7 @@ unmute:
1020 } 1020 }
1021 1021
1022 /* unmute: dispatch sound to scart output, set scart volume */ 1022 /* unmute: dispatch sound to scart output, set scart volume */
1023 msp_set_audio(client); 1023 msp_update_volume(state);
1024 1024
1025 /* restore ACB */ 1025 /* restore ACB */
1026 if (msp_write_dsp(client, 0x13, state->acb)) 1026 if (msp_write_dsp(client, 0x13, state->acb))
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index 31cc3d04bcc..758a4db27d6 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Driver for MT9M111/MT9M112 CMOS Image Sensor from Micron 2 * Driver for MT9M111/MT9M112/MT9M131 CMOS Image Sensor from Micron/Aptina
3 * 3 *
4 * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr> 4 * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr>
5 * 5 *
@@ -19,11 +19,14 @@
19#include <media/soc_camera.h> 19#include <media/soc_camera.h>
20 20
21/* 21/*
22 * mt9m111 and mt9m112 i2c address is 0x5d or 0x48 (depending on SAddr pin) 22 * MT9M111, MT9M112 and MT9M131:
23 * i2c address is 0x48 or 0x5d (depending on SADDR pin)
23 * The platform has to define i2c_board_info and call i2c_register_board_info() 24 * The platform has to define i2c_board_info and call i2c_register_board_info()
24 */ 25 */
25 26
26/* mt9m111: Sensor register addresses */ 27/*
28 * Sensor core register addresses (0x000..0x0ff)
29 */
27#define MT9M111_CHIP_VERSION 0x000 30#define MT9M111_CHIP_VERSION 0x000
28#define MT9M111_ROW_START 0x001 31#define MT9M111_ROW_START 0x001
29#define MT9M111_COLUMN_START 0x002 32#define MT9M111_COLUMN_START 0x002
@@ -72,8 +75,9 @@
72#define MT9M111_CTXT_CTRL_LED_FLASH_EN (1 << 2) 75#define MT9M111_CTXT_CTRL_LED_FLASH_EN (1 << 2)
73#define MT9M111_CTXT_CTRL_VBLANK_SEL_B (1 << 1) 76#define MT9M111_CTXT_CTRL_VBLANK_SEL_B (1 << 1)
74#define MT9M111_CTXT_CTRL_HBLANK_SEL_B (1 << 0) 77#define MT9M111_CTXT_CTRL_HBLANK_SEL_B (1 << 0)
78
75/* 79/*
76 * mt9m111: Colorpipe register addresses (0x100..0x1ff) 80 * Colorpipe register addresses (0x100..0x1ff)
77 */ 81 */
78#define MT9M111_OPER_MODE_CTRL 0x106 82#define MT9M111_OPER_MODE_CTRL 0x106
79#define MT9M111_OUTPUT_FORMAT_CTRL 0x108 83#define MT9M111_OUTPUT_FORMAT_CTRL 0x108
@@ -109,8 +113,9 @@
109#define MT9M111_OUTFMT_SWAP_YCbCr_C_Y (1 << 1) 113#define MT9M111_OUTFMT_SWAP_YCbCr_C_Y (1 << 1)
110#define MT9M111_OUTFMT_SWAP_RGB_EVEN (1 << 1) 114#define MT9M111_OUTFMT_SWAP_RGB_EVEN (1 << 1)
111#define MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr (1 << 0) 115#define MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr (1 << 0)
116
112/* 117/*
113 * mt9m111: Camera control register addresses (0x200..0x2ff not implemented) 118 * Camera control register addresses (0x200..0x2ff not implemented)
114 */ 119 */
115 120
116#define reg_read(reg) mt9m111_reg_read(client, MT9M111_##reg) 121#define reg_read(reg) mt9m111_reg_read(client, MT9M111_##reg)
@@ -160,7 +165,8 @@ enum mt9m111_context {
160 165
161struct mt9m111 { 166struct mt9m111 {
162 struct v4l2_subdev subdev; 167 struct v4l2_subdev subdev;
163 int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ 168 int model; /* V4L2_IDENT_MT9M111 or V4L2_IDENT_MT9M112 code
169 * from v4l2-chip-ident.h */
164 enum mt9m111_context context; 170 enum mt9m111_context context;
165 struct v4l2_rect rect; 171 struct v4l2_rect rect;
166 const struct mt9m111_datafmt *fmt; 172 const struct mt9m111_datafmt *fmt;
@@ -934,7 +940,7 @@ static int mt9m111_init(struct i2c_client *client)
934 if (!ret) 940 if (!ret)
935 ret = mt9m111_set_autoexposure(client, mt9m111->autoexposure); 941 ret = mt9m111_set_autoexposure(client, mt9m111->autoexposure);
936 if (ret) 942 if (ret)
937 dev_err(&client->dev, "mt9m11x init failed: %d\n", ret); 943 dev_err(&client->dev, "mt9m111 init failed: %d\n", ret);
938 return ret; 944 return ret;
939} 945}
940 946
@@ -963,27 +969,27 @@ static int mt9m111_video_probe(struct soc_camera_device *icd,
963 mt9m111->swap_rgb_even_odd = 1; 969 mt9m111->swap_rgb_even_odd = 1;
964 mt9m111->swap_rgb_red_blue = 1; 970 mt9m111->swap_rgb_red_blue = 1;
965 971
966 ret = mt9m111_init(client);
967 if (ret)
968 goto ei2c;
969
970 data = reg_read(CHIP_VERSION); 972 data = reg_read(CHIP_VERSION);
971 973
972 switch (data) { 974 switch (data) {
973 case 0x143a: /* MT9M111 */ 975 case 0x143a: /* MT9M111 or MT9M131 */
974 mt9m111->model = V4L2_IDENT_MT9M111; 976 mt9m111->model = V4L2_IDENT_MT9M111;
977 dev_info(&client->dev,
978 "Detected a MT9M111/MT9M131 chip ID %x\n", data);
975 break; 979 break;
976 case 0x148c: /* MT9M112 */ 980 case 0x148c: /* MT9M112 */
977 mt9m111->model = V4L2_IDENT_MT9M112; 981 mt9m111->model = V4L2_IDENT_MT9M112;
982 dev_info(&client->dev, "Detected a MT9M112 chip ID %x\n", data);
978 break; 983 break;
979 default: 984 default:
980 ret = -ENODEV; 985 ret = -ENODEV;
981 dev_err(&client->dev, 986 dev_err(&client->dev,
982 "No MT9M11x chip detected, register read %x\n", data); 987 "No MT9M111/MT9M112/MT9M131 chip detected register read %x\n",
988 data);
983 goto ei2c; 989 goto ei2c;
984 } 990 }
985 991
986 dev_info(&client->dev, "Detected a MT9M11x chip ID %x\n", data); 992 ret = mt9m111_init(client);
987 993
988ei2c: 994ei2c:
989 return ret; 995 return ret;
@@ -1034,13 +1040,13 @@ static int mt9m111_probe(struct i2c_client *client,
1034 int ret; 1040 int ret;
1035 1041
1036 if (!icd) { 1042 if (!icd) {
1037 dev_err(&client->dev, "MT9M11x: missing soc-camera data!\n"); 1043 dev_err(&client->dev, "mt9m111: soc-camera data missing!\n");
1038 return -EINVAL; 1044 return -EINVAL;
1039 } 1045 }
1040 1046
1041 icl = to_soc_camera_link(icd); 1047 icl = to_soc_camera_link(icd);
1042 if (!icl) { 1048 if (!icl) {
1043 dev_err(&client->dev, "MT9M11x driver needs platform data\n"); 1049 dev_err(&client->dev, "mt9m111: driver needs platform data\n");
1044 return -EINVAL; 1050 return -EINVAL;
1045 } 1051 }
1046 1052
@@ -1114,6 +1120,6 @@ static void __exit mt9m111_mod_exit(void)
1114module_init(mt9m111_mod_init); 1120module_init(mt9m111_mod_init);
1115module_exit(mt9m111_mod_exit); 1121module_exit(mt9m111_mod_exit);
1116 1122
1117MODULE_DESCRIPTION("Micron MT9M111/MT9M112 Camera driver"); 1123MODULE_DESCRIPTION("Micron/Aptina MT9M111/MT9M112/MT9M131 Camera driver");
1118MODULE_AUTHOR("Robert Jarzmik"); 1124MODULE_AUTHOR("Robert Jarzmik");
1119MODULE_LICENSE("GPL"); 1125MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c
index 026bef0ba40..66ff174151b 100644
--- a/drivers/media/video/mx2_camera.c
+++ b/drivers/media/video/mx2_camera.c
@@ -785,6 +785,8 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd,
785 if (ret < 0) 785 if (ret < 0)
786 return ret; 786 return ret;
787 787
788 if (common_flags & SOCAM_PCLK_SAMPLE_RISING)
789 csicr1 |= CSICR1_REDGE;
788 if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) 790 if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
789 csicr1 |= CSICR1_INV_PCLK; 791 csicr1 |= CSICR1_INV_PCLK;
790 if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH) 792 if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH)
@@ -1201,7 +1203,7 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
1201 buf = list_entry(pcdev->capture.next, 1203 buf = list_entry(pcdev->capture.next,
1202 struct mx2_buffer, vb.queue); 1204 struct mx2_buffer, vb.queue);
1203 1205
1204 buf->bufnum = bufnum; 1206 buf->bufnum = !bufnum;
1205 1207
1206 list_move_tail(pcdev->capture.next, &pcdev->active_bufs); 1208 list_move_tail(pcdev->capture.next, &pcdev->active_bufs);
1207 1209
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
index e9b11e119f6..4279ebb811a 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
@@ -94,8 +94,6 @@ static int debugifc_parse_unsigned_number(const char *buf,unsigned int count,
94 u32 *num_ptr) 94 u32 *num_ptr)
95{ 95{
96 u32 result = 0; 96 u32 result = 0;
97 u32 val;
98 int ch;
99 int radix = 10; 97 int radix = 10;
100 if ((count >= 2) && (buf[0] == '0') && 98 if ((count >= 2) && (buf[0] == '0') &&
101 ((buf[1] == 'x') || (buf[1] == 'X'))) { 99 ((buf[1] == 'x') || (buf[1] == 'X'))) {
@@ -107,17 +105,9 @@ static int debugifc_parse_unsigned_number(const char *buf,unsigned int count,
107 } 105 }
108 106
109 while (count--) { 107 while (count--) {
110 ch = *buf++; 108 int val = hex_to_bin(*buf++);
111 if ((ch >= '0') && (ch <= '9')) { 109 if (val < 0 || val >= radix)
112 val = ch - '0';
113 } else if ((ch >= 'a') && (ch <= 'f')) {
114 val = ch - 'a' + 10;
115 } else if ((ch >= 'A') && (ch <= 'F')) {
116 val = ch - 'A' + 10;
117 } else {
118 return -EINVAL; 110 return -EINVAL;
119 }
120 if (val >= radix) return -EINVAL;
121 result *= radix; 111 result *= radix;
122 result += val; 112 result += val;
123 } 113 }
diff --git a/drivers/media/video/s5p-fimc/Makefile b/drivers/media/video/s5p-fimc/Makefile
new file mode 100644
index 00000000000..0d9d54132ec
--- /dev/null
+++ b/drivers/media/video/s5p-fimc/Makefile
@@ -0,0 +1,3 @@
1
2obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) := s5p-fimc.o
3s5p-fimc-y := fimc-core.o fimc-reg.o
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
new file mode 100644
index 00000000000..b151c7be8a5
--- /dev/null
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -0,0 +1,1586 @@
1/*
2 * S5P camera interface (video postprocessor) driver
3 *
4 * Copyright (c) 2010 Samsung Electronics
5 *
6 * Sylwester Nawrocki, <s.nawrocki@samsung.com>
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
10 * by the Free Software Foundation, either version 2 of the License,
11 * or (at your option) any later version.
12 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/version.h>
17#include <linux/types.h>
18#include <linux/errno.h>
19#include <linux/bug.h>
20#include <linux/interrupt.h>
21#include <linux/device.h>
22#include <linux/platform_device.h>
23#include <linux/list.h>
24#include <linux/io.h>
25#include <linux/slab.h>
26#include <linux/clk.h>
27#include <media/v4l2-ioctl.h>
28#include <media/videobuf-dma-contig.h>
29
30#include "fimc-core.h"
31
32static char *fimc_clock_name[NUM_FIMC_CLOCKS] = { "sclk_fimc", "fimc" };
33
34static struct fimc_fmt fimc_formats[] = {
35 {
36 .name = "RGB565",
37 .fourcc = V4L2_PIX_FMT_RGB565X,
38 .depth = 16,
39 .color = S5P_FIMC_RGB565,
40 .buff_cnt = 1,
41 .planes_cnt = 1
42 }, {
43 .name = "BGR666",
44 .fourcc = V4L2_PIX_FMT_BGR666,
45 .depth = 32,
46 .color = S5P_FIMC_RGB666,
47 .buff_cnt = 1,
48 .planes_cnt = 1
49 }, {
50 .name = "XRGB-8-8-8-8, 24 bpp",
51 .fourcc = V4L2_PIX_FMT_RGB24,
52 .depth = 32,
53 .color = S5P_FIMC_RGB888,
54 .buff_cnt = 1,
55 .planes_cnt = 1
56 }, {
57 .name = "YUV 4:2:2 packed, YCbYCr",
58 .fourcc = V4L2_PIX_FMT_YUYV,
59 .depth = 16,
60 .color = S5P_FIMC_YCBYCR422,
61 .buff_cnt = 1,
62 .planes_cnt = 1
63 }, {
64 .name = "YUV 4:2:2 packed, CbYCrY",
65 .fourcc = V4L2_PIX_FMT_UYVY,
66 .depth = 16,
67 .color = S5P_FIMC_CBYCRY422,
68 .buff_cnt = 1,
69 .planes_cnt = 1
70 }, {
71 .name = "YUV 4:2:2 packed, CrYCbY",
72 .fourcc = V4L2_PIX_FMT_VYUY,
73 .depth = 16,
74 .color = S5P_FIMC_CRYCBY422,
75 .buff_cnt = 1,
76 .planes_cnt = 1
77 }, {
78 .name = "YUV 4:2:2 packed, YCrYCb",
79 .fourcc = V4L2_PIX_FMT_YVYU,
80 .depth = 16,
81 .color = S5P_FIMC_YCRYCB422,
82 .buff_cnt = 1,
83 .planes_cnt = 1
84 }, {
85 .name = "YUV 4:2:2 planar, Y/Cb/Cr",
86 .fourcc = V4L2_PIX_FMT_YUV422P,
87 .depth = 12,
88 .color = S5P_FIMC_YCBCR422,
89 .buff_cnt = 1,
90 .planes_cnt = 3
91 }, {
92 .name = "YUV 4:2:2 planar, Y/CbCr",
93 .fourcc = V4L2_PIX_FMT_NV16,
94 .depth = 16,
95 .color = S5P_FIMC_YCBCR422,
96 .buff_cnt = 1,
97 .planes_cnt = 2
98 }, {
99 .name = "YUV 4:2:2 planar, Y/CrCb",
100 .fourcc = V4L2_PIX_FMT_NV61,
101 .depth = 16,
102 .color = S5P_FIMC_RGB565,
103 .buff_cnt = 1,
104 .planes_cnt = 2
105 }, {
106 .name = "YUV 4:2:0 planar, YCbCr",
107 .fourcc = V4L2_PIX_FMT_YUV420,
108 .depth = 12,
109 .color = S5P_FIMC_YCBCR420,
110 .buff_cnt = 1,
111 .planes_cnt = 3
112 }, {
113 .name = "YUV 4:2:0 planar, Y/CbCr",
114 .fourcc = V4L2_PIX_FMT_NV12,
115 .depth = 12,
116 .color = S5P_FIMC_YCBCR420,
117 .buff_cnt = 1,
118 .planes_cnt = 2
119 }
120 };
121
122static struct v4l2_queryctrl fimc_ctrls[] = {
123 {
124 .id = V4L2_CID_HFLIP,
125 .type = V4L2_CTRL_TYPE_BOOLEAN,
126 .name = "Horizontal flip",
127 .minimum = 0,
128 .maximum = 1,
129 .default_value = 0,
130 },
131 {
132 .id = V4L2_CID_VFLIP,
133 .type = V4L2_CTRL_TYPE_BOOLEAN,
134 .name = "Vertical flip",
135 .minimum = 0,
136 .maximum = 1,
137 .default_value = 0,
138 },
139 {
140 .id = V4L2_CID_ROTATE,
141 .type = V4L2_CTRL_TYPE_INTEGER,
142 .name = "Rotation (CCW)",
143 .minimum = 0,
144 .maximum = 270,
145 .step = 90,
146 .default_value = 0,
147 },
148};
149
150
151static struct v4l2_queryctrl *get_ctrl(int id)
152{
153 int i;
154
155 for (i = 0; i < ARRAY_SIZE(fimc_ctrls); ++i)
156 if (id == fimc_ctrls[i].id)
157 return &fimc_ctrls[i];
158 return NULL;
159}
160
161static int fimc_check_scaler_ratio(struct v4l2_rect *r, struct fimc_frame *f)
162{
163 if (r->width > f->width) {
164 if (f->width > (r->width * SCALER_MAX_HRATIO))
165 return -EINVAL;
166 } else {
167 if ((f->width * SCALER_MAX_HRATIO) < r->width)
168 return -EINVAL;
169 }
170
171 if (r->height > f->height) {
172 if (f->height > (r->height * SCALER_MAX_VRATIO))
173 return -EINVAL;
174 } else {
175 if ((f->height * SCALER_MAX_VRATIO) < r->height)
176 return -EINVAL;
177 }
178
179 return 0;
180}
181
182static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
183{
184 if (src >= tar * 64) {
185 return -EINVAL;
186 } else if (src >= tar * 32) {
187 *ratio = 32;
188 *shift = 5;
189 } else if (src >= tar * 16) {
190 *ratio = 16;
191 *shift = 4;
192 } else if (src >= tar * 8) {
193 *ratio = 8;
194 *shift = 3;
195 } else if (src >= tar * 4) {
196 *ratio = 4;
197 *shift = 2;
198 } else if (src >= tar * 2) {
199 *ratio = 2;
200 *shift = 1;
201 } else {
202 *ratio = 1;
203 *shift = 0;
204 }
205
206 return 0;
207}
208
209static int fimc_set_scaler_info(struct fimc_ctx *ctx)
210{
211 struct fimc_scaler *sc = &ctx->scaler;
212 struct fimc_frame *s_frame = &ctx->s_frame;
213 struct fimc_frame *d_frame = &ctx->d_frame;
214 int tx, ty, sx, sy;
215 int ret;
216
217 tx = d_frame->width;
218 ty = d_frame->height;
219 if (tx <= 0 || ty <= 0) {
220 v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
221 "invalid target size: %d x %d", tx, ty);
222 return -EINVAL;
223 }
224
225 sx = s_frame->width;
226 sy = s_frame->height;
227 if (sx <= 0 || sy <= 0) {
228 err("invalid source size: %d x %d", sx, sy);
229 return -EINVAL;
230 }
231
232 sc->real_width = sx;
233 sc->real_height = sy;
234 dbg("sx= %d, sy= %d, tx= %d, ty= %d", sx, sy, tx, ty);
235
236 ret = fimc_get_scaler_factor(sx, tx, &sc->pre_hratio, &sc->hfactor);
237 if (ret)
238 return ret;
239
240 ret = fimc_get_scaler_factor(sy, ty, &sc->pre_vratio, &sc->vfactor);
241 if (ret)
242 return ret;
243
244 sc->pre_dst_width = sx / sc->pre_hratio;
245 sc->pre_dst_height = sy / sc->pre_vratio;
246
247 sc->main_hratio = (sx << 8) / (tx << sc->hfactor);
248 sc->main_vratio = (sy << 8) / (ty << sc->vfactor);
249
250 sc->scaleup_h = (tx >= sx) ? 1 : 0;
251 sc->scaleup_v = (ty >= sy) ? 1 : 0;
252
253 /* check to see if input and output size/format differ */
254 if (s_frame->fmt->color == d_frame->fmt->color
255 && s_frame->width == d_frame->width
256 && s_frame->height == d_frame->height)
257 sc->copy_mode = 1;
258 else
259 sc->copy_mode = 0;
260
261 return 0;
262}
263
264
265static irqreturn_t fimc_isr(int irq, void *priv)
266{
267 struct fimc_vid_buffer *src_buf, *dst_buf;
268 struct fimc_dev *fimc = (struct fimc_dev *)priv;
269 struct fimc_ctx *ctx;
270
271 BUG_ON(!fimc);
272 fimc_hw_clear_irq(fimc);
273
274 spin_lock(&fimc->slock);
275
276 if (test_and_clear_bit(ST_M2M_PEND, &fimc->state)) {
277 ctx = v4l2_m2m_get_curr_priv(fimc->m2m.m2m_dev);
278 if (!ctx || !ctx->m2m_ctx)
279 goto isr_unlock;
280 src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
281 dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
282 if (src_buf && dst_buf) {
283 spin_lock(&fimc->irqlock);
284 src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE;
285 wake_up(&src_buf->vb.done);
286 wake_up(&dst_buf->vb.done);
287 spin_unlock(&fimc->irqlock);
288 v4l2_m2m_job_finish(fimc->m2m.m2m_dev, ctx->m2m_ctx);
289 }
290 }
291
292isr_unlock:
293 spin_unlock(&fimc->slock);
294 return IRQ_HANDLED;
295}
296
297/* The color format (planes_cnt, buff_cnt) must be already configured. */
298static int fimc_prepare_addr(struct fimc_ctx *ctx,
299 struct fimc_vid_buffer *buf, enum v4l2_buf_type type)
300{
301 struct fimc_frame *frame;
302 struct fimc_addr *paddr;
303 u32 pix_size;
304 int ret = 0;
305
306 frame = ctx_m2m_get_frame(ctx, type);
307 if (IS_ERR(frame))
308 return PTR_ERR(frame);
309 paddr = &frame->paddr;
310
311 if (!buf)
312 return -EINVAL;
313
314 pix_size = frame->width * frame->height;
315
316 dbg("buff_cnt= %d, planes_cnt= %d, frame->size= %d, pix_size= %d",
317 frame->fmt->buff_cnt, frame->fmt->planes_cnt,
318 frame->size, pix_size);
319
320 if (frame->fmt->buff_cnt == 1) {
321 paddr->y = videobuf_to_dma_contig(&buf->vb);
322 switch (frame->fmt->planes_cnt) {
323 case 1:
324 paddr->cb = 0;
325 paddr->cr = 0;
326 break;
327 case 2:
328 /* decompose Y into Y/Cb */
329 paddr->cb = (u32)(paddr->y + pix_size);
330 paddr->cr = 0;
331 break;
332 case 3:
333 paddr->cb = (u32)(paddr->y + pix_size);
334 /* decompose Y into Y/Cb/Cr */
335 if (S5P_FIMC_YCBCR420 == frame->fmt->color)
336 paddr->cr = (u32)(paddr->cb
337 + (pix_size >> 2));
338 else /* 422 */
339 paddr->cr = (u32)(paddr->cb
340 + (pix_size >> 1));
341 break;
342 default:
343 return -EINVAL;
344 }
345 }
346
347 dbg("PHYS_ADDR: type= %d, y= 0x%X cb= 0x%X cr= 0x%X ret= %d",
348 type, paddr->y, paddr->cb, paddr->cr, ret);
349
350 return ret;
351}
352
353/* Set order for 1 and 2 plane YCBCR 4:2:2 formats. */
354static void fimc_set_yuv_order(struct fimc_ctx *ctx)
355{
356 /* The one only mode supported in SoC. */
357 ctx->in_order_2p = S5P_FIMC_LSB_CRCB;
358 ctx->out_order_2p = S5P_FIMC_LSB_CRCB;
359
360 /* Set order for 1 plane input formats. */
361 switch (ctx->s_frame.fmt->color) {
362 case S5P_FIMC_YCRYCB422:
363 ctx->in_order_1p = S5P_FIMC_IN_YCRYCB;
364 break;
365 case S5P_FIMC_CBYCRY422:
366 ctx->in_order_1p = S5P_FIMC_IN_CBYCRY;
367 break;
368 case S5P_FIMC_CRYCBY422:
369 ctx->in_order_1p = S5P_FIMC_IN_CRYCBY;
370 break;
371 case S5P_FIMC_YCBYCR422:
372 default:
373 ctx->in_order_1p = S5P_FIMC_IN_YCBYCR;
374 break;
375 }
376 dbg("ctx->in_order_1p= %d", ctx->in_order_1p);
377
378 switch (ctx->d_frame.fmt->color) {
379 case S5P_FIMC_YCRYCB422:
380 ctx->out_order_1p = S5P_FIMC_OUT_YCRYCB;
381 break;
382 case S5P_FIMC_CBYCRY422:
383 ctx->out_order_1p = S5P_FIMC_OUT_CBYCRY;
384 break;
385 case S5P_FIMC_CRYCBY422:
386 ctx->out_order_1p = S5P_FIMC_OUT_CRYCBY;
387 break;
388 case S5P_FIMC_YCBYCR422:
389 default:
390 ctx->out_order_1p = S5P_FIMC_OUT_YCBYCR;
391 break;
392 }
393 dbg("ctx->out_order_1p= %d", ctx->out_order_1p);
394}
395
396/**
397 * fimc_prepare_config - check dimensions, operation and color mode
398 * and pre-calculate offset and the scaling coefficients.
399 *
400 * @ctx: hardware context information
401 * @flags: flags indicating which parameters to check/update
402 *
403 * Return: 0 if dimensions are valid or non zero otherwise.
404 */
405static int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags)
406{
407 struct fimc_frame *s_frame, *d_frame;
408 struct fimc_vid_buffer *buf = NULL;
409 struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
410 int ret = 0;
411
412 s_frame = &ctx->s_frame;
413 d_frame = &ctx->d_frame;
414
415 if (flags & FIMC_PARAMS) {
416 if ((ctx->out_path == FIMC_DMA) &&
417 (ctx->rotation == 90 || ctx->rotation == 270)) {
418 swap(d_frame->f_width, d_frame->f_height);
419 swap(d_frame->width, d_frame->height);
420 }
421
422 /* Prepare the output offset ratios for scaler. */
423 d_frame->dma_offset.y_h = d_frame->offs_h;
424 if (!variant->pix_hoff)
425 d_frame->dma_offset.y_h *= (d_frame->fmt->depth >> 3);
426
427 d_frame->dma_offset.y_v = d_frame->offs_v;
428
429 d_frame->dma_offset.cb_h = d_frame->offs_h;
430 d_frame->dma_offset.cb_v = d_frame->offs_v;
431
432 d_frame->dma_offset.cr_h = d_frame->offs_h;
433 d_frame->dma_offset.cr_v = d_frame->offs_v;
434
435 if (!variant->pix_hoff && d_frame->fmt->planes_cnt == 3) {
436 d_frame->dma_offset.cb_h >>= 1;
437 d_frame->dma_offset.cb_v >>= 1;
438 d_frame->dma_offset.cr_h >>= 1;
439 d_frame->dma_offset.cr_v >>= 1;
440 }
441
442 dbg("out offset: color= %d, y_h= %d, y_v= %d",
443 d_frame->fmt->color,
444 d_frame->dma_offset.y_h, d_frame->dma_offset.y_v);
445
446 /* Prepare the input offset ratios for scaler. */
447 s_frame->dma_offset.y_h = s_frame->offs_h;
448 if (!variant->pix_hoff)
449 s_frame->dma_offset.y_h *= (s_frame->fmt->depth >> 3);
450 s_frame->dma_offset.y_v = s_frame->offs_v;
451
452 s_frame->dma_offset.cb_h = s_frame->offs_h;
453 s_frame->dma_offset.cb_v = s_frame->offs_v;
454
455 s_frame->dma_offset.cr_h = s_frame->offs_h;
456 s_frame->dma_offset.cr_v = s_frame->offs_v;
457
458 if (!variant->pix_hoff && s_frame->fmt->planes_cnt == 3) {
459 s_frame->dma_offset.cb_h >>= 1;
460 s_frame->dma_offset.cb_v >>= 1;
461 s_frame->dma_offset.cr_h >>= 1;
462 s_frame->dma_offset.cr_v >>= 1;
463 }
464
465 dbg("in offset: color= %d, y_h= %d, y_v= %d",
466 s_frame->fmt->color, s_frame->dma_offset.y_h,
467 s_frame->dma_offset.y_v);
468
469 fimc_set_yuv_order(ctx);
470
471 /* Check against the scaler ratio. */
472 if (s_frame->height > (SCALER_MAX_VRATIO * d_frame->height) ||
473 s_frame->width > (SCALER_MAX_HRATIO * d_frame->width)) {
474 err("out of scaler range");
475 return -EINVAL;
476 }
477 }
478
479 /* Input DMA mode is not allowed when the scaler is disabled. */
480 ctx->scaler.enabled = 1;
481
482 if (flags & FIMC_SRC_ADDR) {
483 buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
484 ret = fimc_prepare_addr(ctx, buf,
485 V4L2_BUF_TYPE_VIDEO_OUTPUT);
486 if (ret)
487 return ret;
488 }
489
490 if (flags & FIMC_DST_ADDR) {
491 buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
492 ret = fimc_prepare_addr(ctx, buf,
493 V4L2_BUF_TYPE_VIDEO_CAPTURE);
494 }
495
496 return ret;
497}
498
499static void fimc_dma_run(void *priv)
500{
501 struct fimc_ctx *ctx = priv;
502 struct fimc_dev *fimc;
503 unsigned long flags;
504 u32 ret;
505
506 if (WARN(!ctx, "null hardware context"))
507 return;
508
509 fimc = ctx->fimc_dev;
510
511 spin_lock_irqsave(&ctx->slock, flags);
512 set_bit(ST_M2M_PEND, &fimc->state);
513
514 ctx->state |= (FIMC_SRC_ADDR | FIMC_DST_ADDR);
515 ret = fimc_prepare_config(ctx, ctx->state);
516 if (ret) {
517 err("general configuration error");
518 goto dma_unlock;
519 }
520
521 if (fimc->m2m.ctx != ctx)
522 ctx->state |= FIMC_PARAMS;
523
524 fimc_hw_set_input_addr(fimc, &ctx->s_frame.paddr);
525
526 if (ctx->state & FIMC_PARAMS) {
527 fimc_hw_set_input_path(ctx);
528 fimc_hw_set_in_dma(ctx);
529 if (fimc_set_scaler_info(ctx)) {
530 err("scaler configuration error");
531 goto dma_unlock;
532 }
533 fimc_hw_set_prescaler(ctx);
534 fimc_hw_set_scaler(ctx);
535 fimc_hw_set_target_format(ctx);
536 fimc_hw_set_rotation(ctx);
537 fimc_hw_set_effect(ctx);
538 }
539
540 fimc_hw_set_output_path(ctx);
541 if (ctx->state & (FIMC_DST_ADDR | FIMC_PARAMS))
542 fimc_hw_set_output_addr(fimc, &ctx->d_frame.paddr);
543
544 if (ctx->state & FIMC_PARAMS)
545 fimc_hw_set_out_dma(ctx);
546
547 if (ctx->scaler.enabled)
548 fimc_hw_start_scaler(fimc);
549 fimc_hw_en_capture(ctx);
550
551 ctx->state = 0;
552 fimc_hw_start_in_dma(fimc);
553
554 fimc->m2m.ctx = ctx;
555
556dma_unlock:
557 spin_unlock_irqrestore(&ctx->slock, flags);
558}
559
560static void fimc_job_abort(void *priv)
561{
562 /* Nothing done in job_abort. */
563}
564
565static void fimc_buf_release(struct videobuf_queue *vq,
566 struct videobuf_buffer *vb)
567{
568 videobuf_dma_contig_free(vq, vb);
569 vb->state = VIDEOBUF_NEEDS_INIT;
570}
571
572static int fimc_buf_setup(struct videobuf_queue *vq, unsigned int *count,
573 unsigned int *size)
574{
575 struct fimc_ctx *ctx = vq->priv_data;
576 struct fimc_frame *frame;
577
578 frame = ctx_m2m_get_frame(ctx, vq->type);
579 if (IS_ERR(frame))
580 return PTR_ERR(frame);
581
582 *size = (frame->width * frame->height * frame->fmt->depth) >> 3;
583 if (0 == *count)
584 *count = 1;
585 return 0;
586}
587
588static int fimc_buf_prepare(struct videobuf_queue *vq,
589 struct videobuf_buffer *vb, enum v4l2_field field)
590{
591 struct fimc_ctx *ctx = vq->priv_data;
592 struct v4l2_device *v4l2_dev = &ctx->fimc_dev->m2m.v4l2_dev;
593 struct fimc_frame *frame;
594 int ret;
595
596 frame = ctx_m2m_get_frame(ctx, vq->type);
597 if (IS_ERR(frame))
598 return PTR_ERR(frame);
599
600 if (vb->baddr) {
601 if (vb->bsize < frame->size) {
602 v4l2_err(v4l2_dev,
603 "User-provided buffer too small (%d < %d)\n",
604 vb->bsize, frame->size);
605 WARN_ON(1);
606 return -EINVAL;
607 }
608 } else if (vb->state != VIDEOBUF_NEEDS_INIT
609 && vb->bsize < frame->size) {
610 return -EINVAL;
611 }
612
613 vb->width = frame->width;
614 vb->height = frame->height;
615 vb->bytesperline = (frame->width * frame->fmt->depth) >> 3;
616 vb->size = frame->size;
617 vb->field = field;
618
619 if (VIDEOBUF_NEEDS_INIT == vb->state) {
620 ret = videobuf_iolock(vq, vb, NULL);
621 if (ret) {
622 v4l2_err(v4l2_dev, "Iolock failed\n");
623 fimc_buf_release(vq, vb);
624 return ret;
625 }
626 }
627 vb->state = VIDEOBUF_PREPARED;
628
629 return 0;
630}
631
632static void fimc_buf_queue(struct videobuf_queue *vq,
633 struct videobuf_buffer *vb)
634{
635 struct fimc_ctx *ctx = vq->priv_data;
636 v4l2_m2m_buf_queue(ctx->m2m_ctx, vq, vb);
637}
638
639static struct videobuf_queue_ops fimc_qops = {
640 .buf_setup = fimc_buf_setup,
641 .buf_prepare = fimc_buf_prepare,
642 .buf_queue = fimc_buf_queue,
643 .buf_release = fimc_buf_release,
644};
645
646static int fimc_m2m_querycap(struct file *file, void *priv,
647 struct v4l2_capability *cap)
648{
649 struct fimc_ctx *ctx = file->private_data;
650 struct fimc_dev *fimc = ctx->fimc_dev;
651
652 strncpy(cap->driver, fimc->pdev->name, sizeof(cap->driver) - 1);
653 strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1);
654 cap->bus_info[0] = 0;
655 cap->version = KERNEL_VERSION(1, 0, 0);
656 cap->capabilities = V4L2_CAP_STREAMING |
657 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT;
658
659 return 0;
660}
661
662static int fimc_m2m_enum_fmt(struct file *file, void *priv,
663 struct v4l2_fmtdesc *f)
664{
665 struct fimc_fmt *fmt;
666
667 if (f->index >= ARRAY_SIZE(fimc_formats))
668 return -EINVAL;
669
670 fmt = &fimc_formats[f->index];
671 strncpy(f->description, fmt->name, sizeof(f->description) - 1);
672 f->pixelformat = fmt->fourcc;
673 return 0;
674}
675
676static int fimc_m2m_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
677{
678 struct fimc_ctx *ctx = priv;
679 struct fimc_frame *frame;
680
681 frame = ctx_m2m_get_frame(ctx, f->type);
682 if (IS_ERR(frame))
683 return PTR_ERR(frame);
684
685 f->fmt.pix.width = frame->width;
686 f->fmt.pix.height = frame->height;
687 f->fmt.pix.field = V4L2_FIELD_NONE;
688 f->fmt.pix.pixelformat = frame->fmt->fourcc;
689
690 return 0;
691}
692
693static struct fimc_fmt *find_format(struct v4l2_format *f)
694{
695 struct fimc_fmt *fmt;
696 unsigned int i;
697
698 for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) {
699 fmt = &fimc_formats[i];
700 if (fmt->fourcc == f->fmt.pix.pixelformat)
701 break;
702 }
703 if (i == ARRAY_SIZE(fimc_formats))
704 return NULL;
705
706 return fmt;
707}
708
709static int fimc_m2m_try_fmt(struct file *file, void *priv,
710 struct v4l2_format *f)
711{
712 struct fimc_fmt *fmt;
713 u32 max_width, max_height, mod_x, mod_y;
714 struct fimc_ctx *ctx = priv;
715 struct fimc_dev *fimc = ctx->fimc_dev;
716 struct v4l2_pix_format *pix = &f->fmt.pix;
717 struct samsung_fimc_variant *variant = fimc->variant;
718
719 fmt = find_format(f);
720 if (!fmt) {
721 v4l2_err(&fimc->m2m.v4l2_dev,
722 "Fourcc format (0x%X) invalid.\n", pix->pixelformat);
723 return -EINVAL;
724 }
725
726 if (pix->field == V4L2_FIELD_ANY)
727 pix->field = V4L2_FIELD_NONE;
728 else if (V4L2_FIELD_NONE != pix->field)
729 return -EINVAL;
730
731 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
732 max_width = variant->scaler_dis_w;
733 max_height = variant->scaler_dis_w;
734 mod_x = variant->min_inp_pixsize;
735 mod_y = variant->min_inp_pixsize;
736 } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
737 max_width = variant->out_rot_dis_w;
738 max_height = variant->out_rot_dis_w;
739 mod_x = variant->min_out_pixsize;
740 mod_y = variant->min_out_pixsize;
741 } else {
742 err("Wrong stream type (%d)", f->type);
743 return -EINVAL;
744 }
745
746 dbg("max_w= %d, max_h= %d", max_width, max_height);
747
748 if (pix->height > max_height)
749 pix->height = max_height;
750 if (pix->width > max_width)
751 pix->width = max_width;
752
753 if (tiled_fmt(fmt)) {
754 mod_x = 64; /* 64x32 tile */
755 mod_y = 32;
756 }
757
758 dbg("mod_x= 0x%X, mod_y= 0x%X", mod_x, mod_y);
759
760 pix->width = (pix->width == 0) ? mod_x : ALIGN(pix->width, mod_x);
761 pix->height = (pix->height == 0) ? mod_y : ALIGN(pix->height, mod_y);
762
763 if (pix->bytesperline == 0 ||
764 pix->bytesperline * 8 / fmt->depth > pix->width)
765 pix->bytesperline = (pix->width * fmt->depth) >> 3;
766
767 if (pix->sizeimage == 0)
768 pix->sizeimage = pix->height * pix->bytesperline;
769
770 dbg("pix->bytesperline= %d, fmt->depth= %d",
771 pix->bytesperline, fmt->depth);
772
773 return 0;
774}
775
776
777static int fimc_m2m_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
778{
779 struct fimc_ctx *ctx = priv;
780 struct v4l2_device *v4l2_dev = &ctx->fimc_dev->m2m.v4l2_dev;
781 struct videobuf_queue *src_vq, *dst_vq;
782 struct fimc_frame *frame;
783 struct v4l2_pix_format *pix;
784 unsigned long flags;
785 int ret = 0;
786
787 BUG_ON(!ctx);
788
789 ret = fimc_m2m_try_fmt(file, priv, f);
790 if (ret)
791 return ret;
792
793 mutex_lock(&ctx->fimc_dev->lock);
794
795 src_vq = v4l2_m2m_get_src_vq(ctx->m2m_ctx);
796 dst_vq = v4l2_m2m_get_dst_vq(ctx->m2m_ctx);
797
798 mutex_lock(&src_vq->vb_lock);
799 mutex_lock(&dst_vq->vb_lock);
800
801 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
802 if (videobuf_queue_is_busy(src_vq)) {
803 v4l2_err(v4l2_dev, "%s queue busy\n", __func__);
804 ret = -EBUSY;
805 goto s_fmt_out;
806 }
807 frame = &ctx->s_frame;
808 spin_lock_irqsave(&ctx->slock, flags);
809 ctx->state |= FIMC_SRC_FMT;
810 spin_unlock_irqrestore(&ctx->slock, flags);
811
812 } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
813 if (videobuf_queue_is_busy(dst_vq)) {
814 v4l2_err(v4l2_dev, "%s queue busy\n", __func__);
815 ret = -EBUSY;
816 goto s_fmt_out;
817 }
818 frame = &ctx->d_frame;
819 spin_lock_irqsave(&ctx->slock, flags);
820 ctx->state |= FIMC_DST_FMT;
821 spin_unlock_irqrestore(&ctx->slock, flags);
822 } else {
823 v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
824 "Wrong buffer/video queue type (%d)\n", f->type);
825 return -EINVAL;
826 }
827
828 pix = &f->fmt.pix;
829 frame->fmt = find_format(f);
830 if (!frame->fmt) {
831 ret = -EINVAL;
832 goto s_fmt_out;
833 }
834
835 frame->f_width = pix->bytesperline * 8 / frame->fmt->depth;
836 frame->f_height = pix->sizeimage/pix->bytesperline;
837 frame->width = pix->width;
838 frame->height = pix->height;
839 frame->o_width = pix->width;
840 frame->o_height = pix->height;
841 frame->offs_h = 0;
842 frame->offs_v = 0;
843 frame->size = (pix->width * pix->height * frame->fmt->depth) >> 3;
844 src_vq->field = dst_vq->field = pix->field;
845 spin_lock_irqsave(&ctx->slock, flags);
846 ctx->state |= FIMC_PARAMS;
847 spin_unlock_irqrestore(&ctx->slock, flags);
848
849 dbg("f_width= %d, f_height= %d", frame->f_width, frame->f_height);
850
851s_fmt_out:
852 mutex_unlock(&dst_vq->vb_lock);
853 mutex_unlock(&src_vq->vb_lock);
854 mutex_unlock(&ctx->fimc_dev->lock);
855 return ret;
856}
857
858static int fimc_m2m_reqbufs(struct file *file, void *priv,
859 struct v4l2_requestbuffers *reqbufs)
860{
861 struct fimc_ctx *ctx = priv;
862 return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
863}
864
865static int fimc_m2m_querybuf(struct file *file, void *priv,
866 struct v4l2_buffer *buf)
867{
868 struct fimc_ctx *ctx = priv;
869 return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
870}
871
872static int fimc_m2m_qbuf(struct file *file, void *priv,
873 struct v4l2_buffer *buf)
874{
875 struct fimc_ctx *ctx = priv;
876
877 return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
878}
879
880static int fimc_m2m_dqbuf(struct file *file, void *priv,
881 struct v4l2_buffer *buf)
882{
883 struct fimc_ctx *ctx = priv;
884 return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
885}
886
887static int fimc_m2m_streamon(struct file *file, void *priv,
888 enum v4l2_buf_type type)
889{
890 struct fimc_ctx *ctx = priv;
891 return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
892}
893
894static int fimc_m2m_streamoff(struct file *file, void *priv,
895 enum v4l2_buf_type type)
896{
897 struct fimc_ctx *ctx = priv;
898 return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
899}
900
901int fimc_m2m_queryctrl(struct file *file, void *priv,
902 struct v4l2_queryctrl *qc)
903{
904 struct v4l2_queryctrl *c;
905 c = get_ctrl(qc->id);
906 if (!c)
907 return -EINVAL;
908 *qc = *c;
909 return 0;
910}
911
912int fimc_m2m_g_ctrl(struct file *file, void *priv,
913 struct v4l2_control *ctrl)
914{
915 struct fimc_ctx *ctx = priv;
916
917 switch (ctrl->id) {
918 case V4L2_CID_HFLIP:
919 ctrl->value = (FLIP_X_AXIS & ctx->flip) ? 1 : 0;
920 break;
921 case V4L2_CID_VFLIP:
922 ctrl->value = (FLIP_Y_AXIS & ctx->flip) ? 1 : 0;
923 break;
924 case V4L2_CID_ROTATE:
925 ctrl->value = ctx->rotation;
926 break;
927 default:
928 v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev, "Invalid control\n");
929 return -EINVAL;
930 }
931 dbg("ctrl->value= %d", ctrl->value);
932 return 0;
933}
934
935static int check_ctrl_val(struct fimc_ctx *ctx,
936 struct v4l2_control *ctrl)
937{
938 struct v4l2_queryctrl *c;
939 c = get_ctrl(ctrl->id);
940 if (!c)
941 return -EINVAL;
942
943 if (ctrl->value < c->minimum || ctrl->value > c->maximum
944 || (c->step != 0 && ctrl->value % c->step != 0)) {
945 v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
946 "Invalid control value\n");
947 return -ERANGE;
948 }
949
950 return 0;
951}
952
953int fimc_m2m_s_ctrl(struct file *file, void *priv,
954 struct v4l2_control *ctrl)
955{
956 struct fimc_ctx *ctx = priv;
957 struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
958 unsigned long flags;
959 int ret = 0;
960
961 ret = check_ctrl_val(ctx, ctrl);
962 if (ret)
963 return ret;
964
965 switch (ctrl->id) {
966 case V4L2_CID_HFLIP:
967 if (ctx->rotation != 0)
968 return 0;
969 if (ctrl->value)
970 ctx->flip |= FLIP_X_AXIS;
971 else
972 ctx->flip &= ~FLIP_X_AXIS;
973 break;
974
975 case V4L2_CID_VFLIP:
976 if (ctx->rotation != 0)
977 return 0;
978 if (ctrl->value)
979 ctx->flip |= FLIP_Y_AXIS;
980 else
981 ctx->flip &= ~FLIP_Y_AXIS;
982 break;
983
984 case V4L2_CID_ROTATE:
985 if (ctrl->value == 90 || ctrl->value == 270) {
986 if (ctx->out_path == FIMC_LCDFIFO &&
987 !variant->has_inp_rot) {
988 return -EINVAL;
989 } else if (ctx->in_path == FIMC_DMA &&
990 !variant->has_out_rot) {
991 return -EINVAL;
992 }
993 }
994 ctx->rotation = ctrl->value;
995 if (ctrl->value == 180)
996 ctx->flip = FLIP_XY_AXIS;
997 break;
998
999 default:
1000 v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev, "Invalid control\n");
1001 return -EINVAL;
1002 }
1003 spin_lock_irqsave(&ctx->slock, flags);
1004 ctx->state |= FIMC_PARAMS;
1005 spin_unlock_irqrestore(&ctx->slock, flags);
1006 return 0;
1007}
1008
1009
1010static int fimc_m2m_cropcap(struct file *file, void *fh,
1011 struct v4l2_cropcap *cr)
1012{
1013 struct fimc_frame *frame;
1014 struct fimc_ctx *ctx = fh;
1015
1016 frame = ctx_m2m_get_frame(ctx, cr->type);
1017 if (IS_ERR(frame))
1018 return PTR_ERR(frame);
1019
1020 cr->bounds.left = 0;
1021 cr->bounds.top = 0;
1022 cr->bounds.width = frame->f_width;
1023 cr->bounds.height = frame->f_height;
1024 cr->defrect.left = frame->offs_h;
1025 cr->defrect.top = frame->offs_v;
1026 cr->defrect.width = frame->o_width;
1027 cr->defrect.height = frame->o_height;
1028 return 0;
1029}
1030
1031static int fimc_m2m_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
1032{
1033 struct fimc_frame *frame;
1034 struct fimc_ctx *ctx = file->private_data;
1035
1036 frame = ctx_m2m_get_frame(ctx, cr->type);
1037 if (IS_ERR(frame))
1038 return PTR_ERR(frame);
1039
1040 cr->c.left = frame->offs_h;
1041 cr->c.top = frame->offs_v;
1042 cr->c.width = frame->width;
1043 cr->c.height = frame->height;
1044
1045 return 0;
1046}
1047
1048static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
1049{
1050 struct fimc_ctx *ctx = file->private_data;
1051 struct fimc_dev *fimc = ctx->fimc_dev;
1052 unsigned long flags;
1053 struct fimc_frame *f;
1054 u32 min_size;
1055 int ret = 0;
1056
1057 if (cr->c.top < 0 || cr->c.left < 0) {
1058 v4l2_err(&fimc->m2m.v4l2_dev,
1059 "doesn't support negative values for top & left\n");
1060 return -EINVAL;
1061 }
1062
1063 if (cr->c.width <= 0 || cr->c.height <= 0) {
1064 v4l2_err(&fimc->m2m.v4l2_dev,
1065 "crop width and height must be greater than 0\n");
1066 return -EINVAL;
1067 }
1068
1069 f = ctx_m2m_get_frame(ctx, cr->type);
1070 if (IS_ERR(f))
1071 return PTR_ERR(f);
1072
1073 /* Adjust to required pixel boundary. */
1074 min_size = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ?
1075 fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize;
1076
1077 cr->c.width = round_down(cr->c.width, min_size);
1078 cr->c.height = round_down(cr->c.height, min_size);
1079 cr->c.left = round_down(cr->c.left + 1, min_size);
1080 cr->c.top = round_down(cr->c.top + 1, min_size);
1081
1082 if ((cr->c.left + cr->c.width > f->o_width)
1083 || (cr->c.top + cr->c.height > f->o_height)) {
1084 v4l2_err(&fimc->m2m.v4l2_dev, "Error in S_CROP params\n");
1085 return -EINVAL;
1086 }
1087
1088 spin_lock_irqsave(&ctx->slock, flags);
1089 if ((ctx->state & FIMC_SRC_FMT) && (ctx->state & FIMC_DST_FMT)) {
1090 /* Check for the pixel scaling ratio when cropping input img. */
1091 if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1092 ret = fimc_check_scaler_ratio(&cr->c, &ctx->d_frame);
1093 else if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1094 ret = fimc_check_scaler_ratio(&cr->c, &ctx->s_frame);
1095
1096 if (ret) {
1097 spin_unlock_irqrestore(&ctx->slock, flags);
1098 v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range");
1099 return -EINVAL;
1100 }
1101 }
1102 ctx->state |= FIMC_PARAMS;
1103 spin_unlock_irqrestore(&ctx->slock, flags);
1104
1105 f->offs_h = cr->c.left;
1106 f->offs_v = cr->c.top;
1107 f->width = cr->c.width;
1108 f->height = cr->c.height;
1109 return 0;
1110}
1111
1112static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
1113 .vidioc_querycap = fimc_m2m_querycap,
1114
1115 .vidioc_enum_fmt_vid_cap = fimc_m2m_enum_fmt,
1116 .vidioc_enum_fmt_vid_out = fimc_m2m_enum_fmt,
1117
1118 .vidioc_g_fmt_vid_cap = fimc_m2m_g_fmt,
1119 .vidioc_g_fmt_vid_out = fimc_m2m_g_fmt,
1120
1121 .vidioc_try_fmt_vid_cap = fimc_m2m_try_fmt,
1122 .vidioc_try_fmt_vid_out = fimc_m2m_try_fmt,
1123
1124 .vidioc_s_fmt_vid_cap = fimc_m2m_s_fmt,
1125 .vidioc_s_fmt_vid_out = fimc_m2m_s_fmt,
1126
1127 .vidioc_reqbufs = fimc_m2m_reqbufs,
1128 .vidioc_querybuf = fimc_m2m_querybuf,
1129
1130 .vidioc_qbuf = fimc_m2m_qbuf,
1131 .vidioc_dqbuf = fimc_m2m_dqbuf,
1132
1133 .vidioc_streamon = fimc_m2m_streamon,
1134 .vidioc_streamoff = fimc_m2m_streamoff,
1135
1136 .vidioc_queryctrl = fimc_m2m_queryctrl,
1137 .vidioc_g_ctrl = fimc_m2m_g_ctrl,
1138 .vidioc_s_ctrl = fimc_m2m_s_ctrl,
1139
1140 .vidioc_g_crop = fimc_m2m_g_crop,
1141 .vidioc_s_crop = fimc_m2m_s_crop,
1142 .vidioc_cropcap = fimc_m2m_cropcap
1143
1144};
1145
1146static void queue_init(void *priv, struct videobuf_queue *vq,
1147 enum v4l2_buf_type type)
1148{
1149 struct fimc_ctx *ctx = priv;
1150 struct fimc_dev *fimc = ctx->fimc_dev;
1151
1152 videobuf_queue_dma_contig_init(vq, &fimc_qops,
1153 fimc->m2m.v4l2_dev.dev,
1154 &fimc->irqlock, type, V4L2_FIELD_NONE,
1155 sizeof(struct fimc_vid_buffer), priv);
1156}
1157
1158static int fimc_m2m_open(struct file *file)
1159{
1160 struct fimc_dev *fimc = video_drvdata(file);
1161 struct fimc_ctx *ctx = NULL;
1162 int err = 0;
1163
1164 mutex_lock(&fimc->lock);
1165 fimc->m2m.refcnt++;
1166 set_bit(ST_OUTDMA_RUN, &fimc->state);
1167 mutex_unlock(&fimc->lock);
1168
1169
1170 ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
1171 if (!ctx)
1172 return -ENOMEM;
1173
1174 file->private_data = ctx;
1175 ctx->fimc_dev = fimc;
1176 /* default format */
1177 ctx->s_frame.fmt = &fimc_formats[0];
1178 ctx->d_frame.fmt = &fimc_formats[0];
1179 /* per user process device context initialization */
1180 ctx->state = 0;
1181 ctx->flags = 0;
1182 ctx->effect.type = S5P_FIMC_EFFECT_ORIGINAL;
1183 ctx->in_path = FIMC_DMA;
1184 ctx->out_path = FIMC_DMA;
1185 spin_lock_init(&ctx->slock);
1186
1187 ctx->m2m_ctx = v4l2_m2m_ctx_init(ctx, fimc->m2m.m2m_dev, queue_init);
1188 if (IS_ERR(ctx->m2m_ctx)) {
1189 err = PTR_ERR(ctx->m2m_ctx);
1190 kfree(ctx);
1191 }
1192 return err;
1193}
1194
1195static int fimc_m2m_release(struct file *file)
1196{
1197 struct fimc_ctx *ctx = file->private_data;
1198 struct fimc_dev *fimc = ctx->fimc_dev;
1199
1200 v4l2_m2m_ctx_release(ctx->m2m_ctx);
1201 kfree(ctx);
1202 mutex_lock(&fimc->lock);
1203 if (--fimc->m2m.refcnt <= 0)
1204 clear_bit(ST_OUTDMA_RUN, &fimc->state);
1205 mutex_unlock(&fimc->lock);
1206 return 0;
1207}
1208
1209static unsigned int fimc_m2m_poll(struct file *file,
1210 struct poll_table_struct *wait)
1211{
1212 struct fimc_ctx *ctx = file->private_data;
1213 return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
1214}
1215
1216
1217static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma)
1218{
1219 struct fimc_ctx *ctx = file->private_data;
1220 return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
1221}
1222
1223static const struct v4l2_file_operations fimc_m2m_fops = {
1224 .owner = THIS_MODULE,
1225 .open = fimc_m2m_open,
1226 .release = fimc_m2m_release,
1227 .poll = fimc_m2m_poll,
1228 .ioctl = video_ioctl2,
1229 .mmap = fimc_m2m_mmap,
1230};
1231
1232static struct v4l2_m2m_ops m2m_ops = {
1233 .device_run = fimc_dma_run,
1234 .job_abort = fimc_job_abort,
1235};
1236
1237
1238static int fimc_register_m2m_device(struct fimc_dev *fimc)
1239{
1240 struct video_device *vfd;
1241 struct platform_device *pdev;
1242 struct v4l2_device *v4l2_dev;
1243 int ret = 0;
1244
1245 if (!fimc)
1246 return -ENODEV;
1247
1248 pdev = fimc->pdev;
1249 v4l2_dev = &fimc->m2m.v4l2_dev;
1250
1251 /* set name if it is empty */
1252 if (!v4l2_dev->name[0])
1253 snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
1254 "%s.m2m", dev_name(&pdev->dev));
1255
1256 ret = v4l2_device_register(&pdev->dev, v4l2_dev);
1257 if (ret)
1258 return ret;;
1259
1260 vfd = video_device_alloc();
1261 if (!vfd) {
1262 v4l2_err(v4l2_dev, "Failed to allocate video device\n");
1263 goto err_m2m_r1;
1264 }
1265
1266 vfd->fops = &fimc_m2m_fops;
1267 vfd->ioctl_ops = &fimc_m2m_ioctl_ops;
1268 vfd->minor = -1;
1269 vfd->release = video_device_release;
1270
1271 snprintf(vfd->name, sizeof(vfd->name), "%s:m2m", dev_name(&pdev->dev));
1272
1273 video_set_drvdata(vfd, fimc);
1274 platform_set_drvdata(pdev, fimc);
1275
1276 fimc->m2m.vfd = vfd;
1277 fimc->m2m.m2m_dev = v4l2_m2m_init(&m2m_ops);
1278 if (IS_ERR(fimc->m2m.m2m_dev)) {
1279 v4l2_err(v4l2_dev, "failed to initialize v4l2-m2m device\n");
1280 ret = PTR_ERR(fimc->m2m.m2m_dev);
1281 goto err_m2m_r2;
1282 }
1283
1284 ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
1285 if (ret) {
1286 v4l2_err(v4l2_dev,
1287 "%s(): failed to register video device\n", __func__);
1288 goto err_m2m_r3;
1289 }
1290 v4l2_info(v4l2_dev,
1291 "FIMC m2m driver registered as /dev/video%d\n", vfd->num);
1292
1293 return 0;
1294
1295err_m2m_r3:
1296 v4l2_m2m_release(fimc->m2m.m2m_dev);
1297err_m2m_r2:
1298 video_device_release(fimc->m2m.vfd);
1299err_m2m_r1:
1300 v4l2_device_unregister(v4l2_dev);
1301
1302 return ret;
1303}
1304
1305static void fimc_unregister_m2m_device(struct fimc_dev *fimc)
1306{
1307 if (fimc) {
1308 v4l2_m2m_release(fimc->m2m.m2m_dev);
1309 video_unregister_device(fimc->m2m.vfd);
1310 video_device_release(fimc->m2m.vfd);
1311 v4l2_device_unregister(&fimc->m2m.v4l2_dev);
1312 }
1313}
1314
1315static void fimc_clk_release(struct fimc_dev *fimc)
1316{
1317 int i;
1318 for (i = 0; i < NUM_FIMC_CLOCKS; i++) {
1319 if (fimc->clock[i]) {
1320 clk_disable(fimc->clock[i]);
1321 clk_put(fimc->clock[i]);
1322 }
1323 }
1324}
1325
1326static int fimc_clk_get(struct fimc_dev *fimc)
1327{
1328 int i;
1329 for (i = 0; i < NUM_FIMC_CLOCKS; i++) {
1330 fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clock_name[i]);
1331 if (IS_ERR(fimc->clock[i])) {
1332 dev_err(&fimc->pdev->dev,
1333 "failed to get fimc clock: %s\n",
1334 fimc_clock_name[i]);
1335 return -ENXIO;
1336 }
1337 clk_enable(fimc->clock[i]);
1338 }
1339 return 0;
1340}
1341
1342static int fimc_probe(struct platform_device *pdev)
1343{
1344 struct fimc_dev *fimc;
1345 struct resource *res;
1346 struct samsung_fimc_driverdata *drv_data;
1347 int ret = 0;
1348
1349 dev_dbg(&pdev->dev, "%s():\n", __func__);
1350
1351 drv_data = (struct samsung_fimc_driverdata *)
1352 platform_get_device_id(pdev)->driver_data;
1353
1354 if (pdev->id >= drv_data->devs_cnt) {
1355 dev_err(&pdev->dev, "Invalid platform device id: %d\n",
1356 pdev->id);
1357 return -EINVAL;
1358 }
1359
1360 fimc = kzalloc(sizeof(struct fimc_dev), GFP_KERNEL);
1361 if (!fimc)
1362 return -ENOMEM;
1363
1364 fimc->id = pdev->id;
1365 fimc->variant = drv_data->variant[fimc->id];
1366 fimc->pdev = pdev;
1367 fimc->state = ST_IDLE;
1368
1369 spin_lock_init(&fimc->irqlock);
1370 spin_lock_init(&fimc->slock);
1371
1372 mutex_init(&fimc->lock);
1373
1374 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1375 if (!res) {
1376 dev_err(&pdev->dev, "failed to find the registers\n");
1377 ret = -ENOENT;
1378 goto err_info;
1379 }
1380
1381 fimc->regs_res = request_mem_region(res->start, resource_size(res),
1382 dev_name(&pdev->dev));
1383 if (!fimc->regs_res) {
1384 dev_err(&pdev->dev, "failed to obtain register region\n");
1385 ret = -ENOENT;
1386 goto err_info;
1387 }
1388
1389 fimc->regs = ioremap(res->start, resource_size(res));
1390 if (!fimc->regs) {
1391 dev_err(&pdev->dev, "failed to map registers\n");
1392 ret = -ENXIO;
1393 goto err_req_region;
1394 }
1395
1396 ret = fimc_clk_get(fimc);
1397 if (ret)
1398 goto err_regs_unmap;
1399
1400 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1401 if (!res) {
1402 dev_err(&pdev->dev, "failed to get IRQ resource\n");
1403 ret = -ENXIO;
1404 goto err_clk;
1405 }
1406 fimc->irq = res->start;
1407
1408 fimc_hw_reset(fimc);
1409
1410 ret = request_irq(fimc->irq, fimc_isr, 0, pdev->name, fimc);
1411 if (ret) {
1412 dev_err(&pdev->dev, "failed to install irq (%d)\n", ret);
1413 goto err_clk;
1414 }
1415
1416 fimc->work_queue = create_workqueue(dev_name(&fimc->pdev->dev));
1417 if (!fimc->work_queue)
1418 goto err_irq;
1419
1420 ret = fimc_register_m2m_device(fimc);
1421 if (ret)
1422 goto err_wq;
1423
1424 fimc_hw_en_lastirq(fimc, true);
1425
1426 dev_dbg(&pdev->dev, "%s(): fimc-%d registered successfully\n",
1427 __func__, fimc->id);
1428
1429 return 0;
1430
1431err_wq:
1432 destroy_workqueue(fimc->work_queue);
1433err_irq:
1434 free_irq(fimc->irq, fimc);
1435err_clk:
1436 fimc_clk_release(fimc);
1437err_regs_unmap:
1438 iounmap(fimc->regs);
1439err_req_region:
1440 release_resource(fimc->regs_res);
1441 kfree(fimc->regs_res);
1442err_info:
1443 kfree(fimc);
1444 dev_err(&pdev->dev, "failed to install\n");
1445 return ret;
1446}
1447
1448static int __devexit fimc_remove(struct platform_device *pdev)
1449{
1450 struct fimc_dev *fimc =
1451 (struct fimc_dev *)platform_get_drvdata(pdev);
1452
1453 v4l2_info(&fimc->m2m.v4l2_dev, "Removing %s\n", pdev->name);
1454
1455 free_irq(fimc->irq, fimc);
1456
1457 fimc_hw_reset(fimc);
1458
1459 fimc_unregister_m2m_device(fimc);
1460 fimc_clk_release(fimc);
1461 iounmap(fimc->regs);
1462 release_resource(fimc->regs_res);
1463 kfree(fimc->regs_res);
1464 kfree(fimc);
1465 return 0;
1466}
1467
1468static struct samsung_fimc_variant fimc01_variant_s5p = {
1469 .has_inp_rot = 1,
1470 .has_out_rot = 1,
1471 .min_inp_pixsize = 16,
1472 .min_out_pixsize = 16,
1473
1474 .scaler_en_w = 3264,
1475 .scaler_dis_w = 8192,
1476 .in_rot_en_h = 1920,
1477 .in_rot_dis_w = 8192,
1478 .out_rot_en_w = 1920,
1479 .out_rot_dis_w = 4224,
1480};
1481
1482static struct samsung_fimc_variant fimc2_variant_s5p = {
1483 .min_inp_pixsize = 16,
1484 .min_out_pixsize = 16,
1485
1486 .scaler_en_w = 4224,
1487 .scaler_dis_w = 8192,
1488 .in_rot_en_h = 1920,
1489 .in_rot_dis_w = 8192,
1490 .out_rot_en_w = 1920,
1491 .out_rot_dis_w = 4224,
1492};
1493
1494static struct samsung_fimc_variant fimc01_variant_s5pv210 = {
1495 .has_inp_rot = 1,
1496 .has_out_rot = 1,
1497 .min_inp_pixsize = 16,
1498 .min_out_pixsize = 32,
1499
1500 .scaler_en_w = 4224,
1501 .scaler_dis_w = 8192,
1502 .in_rot_en_h = 1920,
1503 .in_rot_dis_w = 8192,
1504 .out_rot_en_w = 1920,
1505 .out_rot_dis_w = 4224,
1506};
1507
1508static struct samsung_fimc_variant fimc2_variant_s5pv210 = {
1509 .min_inp_pixsize = 16,
1510 .min_out_pixsize = 32,
1511
1512 .scaler_en_w = 1920,
1513 .scaler_dis_w = 8192,
1514 .in_rot_en_h = 1280,
1515 .in_rot_dis_w = 8192,
1516 .out_rot_en_w = 1280,
1517 .out_rot_dis_w = 1920,
1518};
1519
1520static struct samsung_fimc_driverdata fimc_drvdata_s5p = {
1521 .variant = {
1522 [0] = &fimc01_variant_s5p,
1523 [1] = &fimc01_variant_s5p,
1524 [2] = &fimc2_variant_s5p,
1525 },
1526 .devs_cnt = 3
1527};
1528
1529static struct samsung_fimc_driverdata fimc_drvdata_s5pv210 = {
1530 .variant = {
1531 [0] = &fimc01_variant_s5pv210,
1532 [1] = &fimc01_variant_s5pv210,
1533 [2] = &fimc2_variant_s5pv210,
1534 },
1535 .devs_cnt = 3
1536};
1537
1538static struct platform_device_id fimc_driver_ids[] = {
1539 {
1540 .name = "s5p-fimc",
1541 .driver_data = (unsigned long)&fimc_drvdata_s5p,
1542 }, {
1543 .name = "s5pv210-fimc",
1544 .driver_data = (unsigned long)&fimc_drvdata_s5pv210,
1545 },
1546 {},
1547};
1548MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
1549
1550static struct platform_driver fimc_driver = {
1551 .probe = fimc_probe,
1552 .remove = __devexit_p(fimc_remove),
1553 .id_table = fimc_driver_ids,
1554 .driver = {
1555 .name = MODULE_NAME,
1556 .owner = THIS_MODULE,
1557 }
1558};
1559
1560static char banner[] __initdata = KERN_INFO
1561 "S5PC Camera Interface V4L2 Driver, (c) 2010 Samsung Electronics\n";
1562
1563static int __init fimc_init(void)
1564{
1565 u32 ret;
1566 printk(banner);
1567
1568 ret = platform_driver_register(&fimc_driver);
1569 if (ret) {
1570 printk(KERN_ERR "FIMC platform driver register failed\n");
1571 return -1;
1572 }
1573 return 0;
1574}
1575
1576static void __exit fimc_exit(void)
1577{
1578 platform_driver_unregister(&fimc_driver);
1579}
1580
1581module_init(fimc_init);
1582module_exit(fimc_exit);
1583
1584MODULE_AUTHOR("Sylwester Nawrocki, s.nawrocki@samsung.com");
1585MODULE_DESCRIPTION("S3C/S5P FIMC (video postprocessor) driver");
1586MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h
new file mode 100644
index 00000000000..6b3e0cd73cd
--- /dev/null
+++ b/drivers/media/video/s5p-fimc/fimc-core.h
@@ -0,0 +1,471 @@
1/*
2 * Copyright (c) 2010 Samsung Electronics
3 *
4 * Sylwester Nawrocki, <s.nawrocki@samsung.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef FIMC_CORE_H_
12#define FIMC_CORE_H_
13
14#include <linux/types.h>
15#include <media/videobuf-core.h>
16#include <media/v4l2-device.h>
17#include <media/v4l2-mem2mem.h>
18#include <linux/videodev2.h>
19#include "regs-fimc.h"
20
21#define err(fmt, args...) \
22 printk(KERN_ERR "%s:%d: " fmt "\n", __func__, __LINE__, ##args)
23
24#ifdef DEBUG
25#define dbg(fmt, args...) \
26 printk(KERN_DEBUG "%s:%d: " fmt "\n", __func__, __LINE__, ##args)
27#else
28#define dbg(fmt, args...)
29#endif
30
31#define NUM_FIMC_CLOCKS 2
32#define MODULE_NAME "s5p-fimc"
33#define FIMC_MAX_DEVS 3
34#define FIMC_MAX_OUT_BUFS 4
35#define SCALER_MAX_HRATIO 64
36#define SCALER_MAX_VRATIO 64
37
38enum {
39 ST_IDLE,
40 ST_OUTDMA_RUN,
41 ST_M2M_PEND,
42};
43
44#define fimc_m2m_active(dev) test_bit(ST_OUTDMA_RUN, &(dev)->state)
45#define fimc_m2m_pending(dev) test_bit(ST_M2M_PEND, &(dev)->state)
46
47enum fimc_datapath {
48 FIMC_ITU_CAM_A,
49 FIMC_ITU_CAM_B,
50 FIMC_MIPI_CAM,
51 FIMC_DMA,
52 FIMC_LCDFIFO,
53 FIMC_WRITEBACK
54};
55
56enum fimc_color_fmt {
57 S5P_FIMC_RGB565,
58 S5P_FIMC_RGB666,
59 S5P_FIMC_RGB888,
60 S5P_FIMC_YCBCR420,
61 S5P_FIMC_YCBCR422,
62 S5P_FIMC_YCBYCR422,
63 S5P_FIMC_YCRYCB422,
64 S5P_FIMC_CBYCRY422,
65 S5P_FIMC_CRYCBY422,
66 S5P_FIMC_RGB30_LOCAL,
67 S5P_FIMC_YCBCR444_LOCAL,
68 S5P_FIMC_MAX_COLOR = S5P_FIMC_YCBCR444_LOCAL,
69 S5P_FIMC_COLOR_MASK = 0x0F,
70};
71
72/* Y/Cb/Cr components order at DMA output for 1 plane YCbCr 4:2:2 formats. */
73#define S5P_FIMC_OUT_CRYCBY S5P_CIOCTRL_ORDER422_CRYCBY
74#define S5P_FIMC_OUT_CBYCRY S5P_CIOCTRL_ORDER422_YCRYCB
75#define S5P_FIMC_OUT_YCRYCB S5P_CIOCTRL_ORDER422_CBYCRY
76#define S5P_FIMC_OUT_YCBYCR S5P_CIOCTRL_ORDER422_YCBYCR
77
78/* Input Y/Cb/Cr components order for 1 plane YCbCr 4:2:2 color formats. */
79#define S5P_FIMC_IN_CRYCBY S5P_MSCTRL_ORDER422_CRYCBY
80#define S5P_FIMC_IN_CBYCRY S5P_MSCTRL_ORDER422_YCRYCB
81#define S5P_FIMC_IN_YCRYCB S5P_MSCTRL_ORDER422_CBYCRY
82#define S5P_FIMC_IN_YCBYCR S5P_MSCTRL_ORDER422_YCBYCR
83
84/* Cb/Cr chrominance components order for 2 plane Y/CbCr 4:2:2 formats. */
85#define S5P_FIMC_LSB_CRCB S5P_CIOCTRL_ORDER422_2P_LSB_CRCB
86
87/* The embedded image effect selection */
88#define S5P_FIMC_EFFECT_ORIGINAL S5P_CIIMGEFF_FIN_BYPASS
89#define S5P_FIMC_EFFECT_ARBITRARY S5P_CIIMGEFF_FIN_ARBITRARY
90#define S5P_FIMC_EFFECT_NEGATIVE S5P_CIIMGEFF_FIN_NEGATIVE
91#define S5P_FIMC_EFFECT_ARTFREEZE S5P_CIIMGEFF_FIN_ARTFREEZE
92#define S5P_FIMC_EFFECT_EMBOSSING S5P_CIIMGEFF_FIN_EMBOSSING
93#define S5P_FIMC_EFFECT_SIKHOUETTE S5P_CIIMGEFF_FIN_SILHOUETTE
94
95/* The hardware context state. */
96#define FIMC_PARAMS (1 << 0)
97#define FIMC_SRC_ADDR (1 << 1)
98#define FIMC_DST_ADDR (1 << 2)
99#define FIMC_SRC_FMT (1 << 3)
100#define FIMC_DST_FMT (1 << 4)
101
102/* Image conversion flags */
103#define FIMC_IN_DMA_ACCESS_TILED (1 << 0)
104#define FIMC_IN_DMA_ACCESS_LINEAR (0 << 0)
105#define FIMC_OUT_DMA_ACCESS_TILED (1 << 1)
106#define FIMC_OUT_DMA_ACCESS_LINEAR (0 << 1)
107#define FIMC_SCAN_MODE_PROGRESSIVE (0 << 2)
108#define FIMC_SCAN_MODE_INTERLACED (1 << 2)
109/* YCbCr data dynamic range for RGB-YUV color conversion. Y/Cb/Cr: (0 ~ 255) */
110#define FIMC_COLOR_RANGE_WIDE (0 << 3)
111/* Y (16 ~ 235), Cb/Cr (16 ~ 240) */
112#define FIMC_COLOR_RANGE_NARROW (1 << 3)
113
114#define FLIP_NONE 0
115#define FLIP_X_AXIS 1
116#define FLIP_Y_AXIS 2
117#define FLIP_XY_AXIS (FLIP_X_AXIS | FLIP_Y_AXIS)
118
119/**
120 * struct fimc_fmt - the driver's internal color format data
121 * @name: format description
122 * @fourcc: the fourcc code for this format
123 * @color: the corresponding fimc_color_fmt
124 * @depth: number of bits per pixel
125 * @buff_cnt: number of physically non-contiguous data planes
126 * @planes_cnt: number of physically contiguous data planes
127 */
128struct fimc_fmt {
129 char *name;
130 u32 fourcc;
131 u32 color;
132 u32 depth;
133 u16 buff_cnt;
134 u16 planes_cnt;
135};
136
137/**
138 * struct fimc_dma_offset - pixel offset information for DMA
139 * @y_h: y value horizontal offset
140 * @y_v: y value vertical offset
141 * @cb_h: cb value horizontal offset
142 * @cb_v: cb value vertical offset
143 * @cr_h: cr value horizontal offset
144 * @cr_v: cr value vertical offset
145 */
146struct fimc_dma_offset {
147 int y_h;
148 int y_v;
149 int cb_h;
150 int cb_v;
151 int cr_h;
152 int cr_v;
153};
154
155/**
156 * struct fimc_effect - the configuration data for the "Arbitrary" image effect
157 * @type: effect type
158 * @pat_cb: cr value when type is "arbitrary"
159 * @pat_cr: cr value when type is "arbitrary"
160 */
161struct fimc_effect {
162 u32 type;
163 u8 pat_cb;
164 u8 pat_cr;
165};
166
167/**
168 * struct fimc_scaler - the configuration data for FIMC inetrnal scaler
169 *
170 * @enabled: the flag set when the scaler is used
171 * @hfactor: horizontal shift factor
172 * @vfactor: vertical shift factor
173 * @pre_hratio: horizontal ratio of the prescaler
174 * @pre_vratio: vertical ratio of the prescaler
175 * @pre_dst_width: the prescaler's destination width
176 * @pre_dst_height: the prescaler's destination height
177 * @scaleup_h: flag indicating scaling up horizontally
178 * @scaleup_v: flag indicating scaling up vertically
179 * @main_hratio: the main scaler's horizontal ratio
180 * @main_vratio: the main scaler's vertical ratio
181 * @real_width: source width - offset
182 * @real_height: source height - offset
183 * @copy_mode: flag set if one-to-one mode is used, i.e. no scaling
184 * and color format conversion
185 */
186struct fimc_scaler {
187 u32 enabled;
188 u32 hfactor;
189 u32 vfactor;
190 u32 pre_hratio;
191 u32 pre_vratio;
192 u32 pre_dst_width;
193 u32 pre_dst_height;
194 u32 scaleup_h;
195 u32 scaleup_v;
196 u32 main_hratio;
197 u32 main_vratio;
198 u32 real_width;
199 u32 real_height;
200 u32 copy_mode;
201};
202
203/**
204 * struct fimc_addr - the FIMC physical address set for DMA
205 *
206 * @y: luminance plane physical address
207 * @cb: Cb plane physical address
208 * @cr: Cr plane physical address
209 */
210struct fimc_addr {
211 u32 y;
212 u32 cb;
213 u32 cr;
214};
215
216/**
217 * struct fimc_vid_buffer - the driver's video buffer
218 * @vb: v4l videobuf buffer
219 */
220struct fimc_vid_buffer {
221 struct videobuf_buffer vb;
222};
223
224/**
225 * struct fimc_frame - input/output frame format properties
226 *
227 * @f_width: image full width (virtual screen size)
228 * @f_height: image full height (virtual screen size)
229 * @o_width: original image width as set by S_FMT
230 * @o_height: original image height as set by S_FMT
231 * @offs_h: image horizontal pixel offset
232 * @offs_v: image vertical pixel offset
233 * @width: image pixel width
234 * @height: image pixel weight
235 * @paddr: image frame buffer physical addresses
236 * @buf_cnt: number of buffers depending on a color format
237 * @size: image size in bytes
238 * @color: color format
239 * @dma_offset: DMA offset in bytes
240 */
241struct fimc_frame {
242 u32 f_width;
243 u32 f_height;
244 u32 o_width;
245 u32 o_height;
246 u32 offs_h;
247 u32 offs_v;
248 u32 width;
249 u32 height;
250 u32 size;
251 struct fimc_addr paddr;
252 struct fimc_dma_offset dma_offset;
253 struct fimc_fmt *fmt;
254};
255
256/**
257 * struct fimc_m2m_device - v4l2 memory-to-memory device data
258 * @vfd: the video device node for v4l2 m2m mode
259 * @v4l2_dev: v4l2 device for m2m mode
260 * @m2m_dev: v4l2 memory-to-memory device data
261 * @ctx: hardware context data
262 * @refcnt: the reference counter
263 */
264struct fimc_m2m_device {
265 struct video_device *vfd;
266 struct v4l2_device v4l2_dev;
267 struct v4l2_m2m_dev *m2m_dev;
268 struct fimc_ctx *ctx;
269 int refcnt;
270};
271
272/**
273 * struct samsung_fimc_variant - camera interface variant information
274 *
275 * @pix_hoff: indicate whether horizontal offset is in pixels or in bytes
276 * @has_inp_rot: set if has input rotator
277 * @has_out_rot: set if has output rotator
278 * @min_inp_pixsize: minimum input pixel size
279 * @min_out_pixsize: minimum output pixel size
280 * @scaler_en_w: maximum input pixel width when the scaler is enabled
281 * @scaler_dis_w: maximum input pixel width when the scaler is disabled
282 * @in_rot_en_h: maximum input width when the input rotator is used
283 * @in_rot_dis_w: maximum input width when the input rotator is used
284 * @out_rot_en_w: maximum output width for the output rotator enabled
285 * @out_rot_dis_w: maximum output width for the output rotator enabled
286 */
287struct samsung_fimc_variant {
288 unsigned int pix_hoff:1;
289 unsigned int has_inp_rot:1;
290 unsigned int has_out_rot:1;
291
292 u16 min_inp_pixsize;
293 u16 min_out_pixsize;
294 u16 scaler_en_w;
295 u16 scaler_dis_w;
296 u16 in_rot_en_h;
297 u16 in_rot_dis_w;
298 u16 out_rot_en_w;
299 u16 out_rot_dis_w;
300};
301
302/**
303 * struct samsung_fimc_driverdata - per-device type driver data for init time.
304 *
305 * @variant: the variant information for this driver.
306 * @dev_cnt: number of fimc sub-devices available in SoC
307 */
308struct samsung_fimc_driverdata {
309 struct samsung_fimc_variant *variant[FIMC_MAX_DEVS];
310 int devs_cnt;
311};
312
313struct fimc_ctx;
314
315/**
316 * struct fimc_subdev - abstraction for a FIMC entity
317 *
318 * @slock: the spinlock protecting this data structure
319 * @lock: the mutex protecting this data structure
320 * @pdev: pointer to the FIMC platform device
321 * @id: FIMC device index (0..2)
322 * @clock[]: the clocks required for FIMC operation
323 * @regs: the mapped hardware registers
324 * @regs_res: the resource claimed for IO registers
325 * @irq: interrupt number of the FIMC subdevice
326 * @irqlock: spinlock protecting videbuffer queue
327 * @m2m: memory-to-memory V4L2 device information
328 * @state: the FIMC device state flags
329 */
330struct fimc_dev {
331 spinlock_t slock;
332 struct mutex lock;
333 struct platform_device *pdev;
334 struct samsung_fimc_variant *variant;
335 int id;
336 struct clk *clock[NUM_FIMC_CLOCKS];
337 void __iomem *regs;
338 struct resource *regs_res;
339 int irq;
340 spinlock_t irqlock;
341 struct workqueue_struct *work_queue;
342 struct fimc_m2m_device m2m;
343 unsigned long state;
344};
345
346/**
347 * fimc_ctx - the device context data
348 *
349 * @lock: mutex protecting this data structure
350 * @s_frame: source frame properties
351 * @d_frame: destination frame properties
352 * @out_order_1p: output 1-plane YCBCR order
353 * @out_order_2p: output 2-plane YCBCR order
354 * @in_order_1p input 1-plane YCBCR order
355 * @in_order_2p: input 2-plane YCBCR order
356 * @in_path: input mode (DMA or camera)
357 * @out_path: output mode (DMA or FIFO)
358 * @scaler: image scaler properties
359 * @effect: image effect
360 * @rotation: image clockwise rotation in degrees
361 * @flip: image flip mode
362 * @flags: an additional flags for image conversion
363 * @state: flags to keep track of user configuration
364 * @fimc_dev: the FIMC device this context applies to
365 * @m2m_ctx: memory-to-memory device context
366 */
367struct fimc_ctx {
368 spinlock_t slock;
369 struct fimc_frame s_frame;
370 struct fimc_frame d_frame;
371 u32 out_order_1p;
372 u32 out_order_2p;
373 u32 in_order_1p;
374 u32 in_order_2p;
375 enum fimc_datapath in_path;
376 enum fimc_datapath out_path;
377 struct fimc_scaler scaler;
378 struct fimc_effect effect;
379 int rotation;
380 u32 flip;
381 u32 flags;
382 u32 state;
383 struct fimc_dev *fimc_dev;
384 struct v4l2_m2m_ctx *m2m_ctx;
385};
386
387
388static inline int tiled_fmt(struct fimc_fmt *fmt)
389{
390 return 0;
391}
392
393static inline void fimc_hw_clear_irq(struct fimc_dev *dev)
394{
395 u32 cfg = readl(dev->regs + S5P_CIGCTRL);
396 cfg |= S5P_CIGCTRL_IRQ_CLR;
397 writel(cfg, dev->regs + S5P_CIGCTRL);
398}
399
400static inline void fimc_hw_start_scaler(struct fimc_dev *dev)
401{
402 u32 cfg = readl(dev->regs + S5P_CISCCTRL);
403 cfg |= S5P_CISCCTRL_SCALERSTART;
404 writel(cfg, dev->regs + S5P_CISCCTRL);
405}
406
407static inline void fimc_hw_stop_scaler(struct fimc_dev *dev)
408{
409 u32 cfg = readl(dev->regs + S5P_CISCCTRL);
410 cfg &= ~S5P_CISCCTRL_SCALERSTART;
411 writel(cfg, dev->regs + S5P_CISCCTRL);
412}
413
414static inline void fimc_hw_dis_capture(struct fimc_dev *dev)
415{
416 u32 cfg = readl(dev->regs + S5P_CIIMGCPT);
417 cfg &= ~(S5P_CIIMGCPT_IMGCPTEN | S5P_CIIMGCPT_IMGCPTEN_SC);
418 writel(cfg, dev->regs + S5P_CIIMGCPT);
419}
420
421static inline void fimc_hw_start_in_dma(struct fimc_dev *dev)
422{
423 u32 cfg = readl(dev->regs + S5P_MSCTRL);
424 cfg |= S5P_MSCTRL_ENVID;
425 writel(cfg, dev->regs + S5P_MSCTRL);
426}
427
428static inline void fimc_hw_stop_in_dma(struct fimc_dev *dev)
429{
430 u32 cfg = readl(dev->regs + S5P_MSCTRL);
431 cfg &= ~S5P_MSCTRL_ENVID;
432 writel(cfg, dev->regs + S5P_MSCTRL);
433}
434
435static inline struct fimc_frame *ctx_m2m_get_frame(struct fimc_ctx *ctx,
436 enum v4l2_buf_type type)
437{
438 struct fimc_frame *frame;
439
440 if (V4L2_BUF_TYPE_VIDEO_OUTPUT == type) {
441 frame = &ctx->s_frame;
442 } else if (V4L2_BUF_TYPE_VIDEO_CAPTURE == type) {
443 frame = &ctx->d_frame;
444 } else {
445 v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
446 "Wrong buffer/video queue type (%d)\n", type);
447 return ERR_PTR(-EINVAL);
448 }
449
450 return frame;
451}
452
453/* -----------------------------------------------------*/
454/* fimc-reg.c */
455void fimc_hw_reset(struct fimc_dev *dev);
456void fimc_hw_set_rotation(struct fimc_ctx *ctx);
457void fimc_hw_set_target_format(struct fimc_ctx *ctx);
458void fimc_hw_set_out_dma(struct fimc_ctx *ctx);
459void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable);
460void fimc_hw_en_irq(struct fimc_dev *dev, int enable);
461void fimc_hw_set_prescaler(struct fimc_ctx *ctx);
462void fimc_hw_set_scaler(struct fimc_ctx *ctx);
463void fimc_hw_en_capture(struct fimc_ctx *ctx);
464void fimc_hw_set_effect(struct fimc_ctx *ctx);
465void fimc_hw_set_in_dma(struct fimc_ctx *ctx);
466void fimc_hw_set_input_path(struct fimc_ctx *ctx);
467void fimc_hw_set_output_path(struct fimc_ctx *ctx);
468void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr);
469void fimc_hw_set_output_addr(struct fimc_dev *dev, struct fimc_addr *paddr);
470
471#endif /* FIMC_CORE_H_ */
diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c
new file mode 100644
index 00000000000..5570f1ce0c9
--- /dev/null
+++ b/drivers/media/video/s5p-fimc/fimc-reg.c
@@ -0,0 +1,527 @@
1/*
2 * Register interface file for Samsung Camera Interface (FIMC) driver
3 *
4 * Copyright (c) 2010 Samsung Electronics
5 *
6 * Sylwester Nawrocki, s.nawrocki@samsung.com
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 version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <linux/io.h>
14#include <linux/delay.h>
15#include <mach/map.h>
16
17#include "fimc-core.h"
18
19
20void fimc_hw_reset(struct fimc_dev *dev)
21{
22 u32 cfg;
23
24 cfg = readl(dev->regs + S5P_CISRCFMT);
25 cfg |= S5P_CISRCFMT_ITU601_8BIT;
26 writel(cfg, dev->regs + S5P_CISRCFMT);
27
28 /* Software reset. */
29 cfg = readl(dev->regs + S5P_CIGCTRL);
30 cfg |= (S5P_CIGCTRL_SWRST | S5P_CIGCTRL_IRQ_LEVEL);
31 writel(cfg, dev->regs + S5P_CIGCTRL);
32 msleep(1);
33
34 cfg = readl(dev->regs + S5P_CIGCTRL);
35 cfg &= ~S5P_CIGCTRL_SWRST;
36 writel(cfg, dev->regs + S5P_CIGCTRL);
37
38}
39
40void fimc_hw_set_rotation(struct fimc_ctx *ctx)
41{
42 u32 cfg, flip;
43 struct fimc_dev *dev = ctx->fimc_dev;
44
45 cfg = readl(dev->regs + S5P_CITRGFMT);
46 cfg &= ~(S5P_CITRGFMT_INROT90 | S5P_CITRGFMT_OUTROT90);
47
48 flip = readl(dev->regs + S5P_MSCTRL);
49 flip &= ~S5P_MSCTRL_FLIP_MASK;
50
51 /*
52 * The input and output rotator cannot work simultaneously.
53 * Use the output rotator in output DMA mode or the input rotator
54 * in direct fifo output mode.
55 */
56 if (ctx->rotation == 90 || ctx->rotation == 270) {
57 if (ctx->out_path == FIMC_LCDFIFO) {
58 cfg |= S5P_CITRGFMT_INROT90;
59 if (ctx->rotation == 270)
60 flip |= S5P_MSCTRL_FLIP_180;
61 } else {
62 cfg |= S5P_CITRGFMT_OUTROT90;
63 if (ctx->rotation == 270)
64 cfg |= S5P_CITRGFMT_FLIP_180;
65 }
66 } else if (ctx->rotation == 180) {
67 if (ctx->out_path == FIMC_LCDFIFO)
68 flip |= S5P_MSCTRL_FLIP_180;
69 else
70 cfg |= S5P_CITRGFMT_FLIP_180;
71 }
72 if (ctx->rotation == 180 || ctx->rotation == 270)
73 writel(flip, dev->regs + S5P_MSCTRL);
74 writel(cfg, dev->regs + S5P_CITRGFMT);
75}
76
77static u32 fimc_hw_get_in_flip(u32 ctx_flip)
78{
79 u32 flip = S5P_MSCTRL_FLIP_NORMAL;
80
81 switch (ctx_flip) {
82 case FLIP_X_AXIS:
83 flip = S5P_MSCTRL_FLIP_X_MIRROR;
84 break;
85 case FLIP_Y_AXIS:
86 flip = S5P_MSCTRL_FLIP_Y_MIRROR;
87 break;
88 case FLIP_XY_AXIS:
89 flip = S5P_MSCTRL_FLIP_180;
90 break;
91 }
92
93 return flip;
94}
95
96static u32 fimc_hw_get_target_flip(u32 ctx_flip)
97{
98 u32 flip = S5P_CITRGFMT_FLIP_NORMAL;
99
100 switch (ctx_flip) {
101 case FLIP_X_AXIS:
102 flip = S5P_CITRGFMT_FLIP_X_MIRROR;
103 break;
104 case FLIP_Y_AXIS:
105 flip = S5P_CITRGFMT_FLIP_Y_MIRROR;
106 break;
107 case FLIP_XY_AXIS:
108 flip = S5P_CITRGFMT_FLIP_180;
109 break;
110 case FLIP_NONE:
111 break;
112
113 }
114 return flip;
115}
116
117void fimc_hw_set_target_format(struct fimc_ctx *ctx)
118{
119 u32 cfg;
120 struct fimc_dev *dev = ctx->fimc_dev;
121 struct fimc_frame *frame = &ctx->d_frame;
122
123 dbg("w= %d, h= %d color: %d", frame->width,
124 frame->height, frame->fmt->color);
125
126 cfg = readl(dev->regs + S5P_CITRGFMT);
127 cfg &= ~(S5P_CITRGFMT_FMT_MASK | S5P_CITRGFMT_HSIZE_MASK |
128 S5P_CITRGFMT_VSIZE_MASK);
129
130 switch (frame->fmt->color) {
131 case S5P_FIMC_RGB565:
132 case S5P_FIMC_RGB666:
133 case S5P_FIMC_RGB888:
134 cfg |= S5P_CITRGFMT_RGB;
135 break;
136 case S5P_FIMC_YCBCR420:
137 cfg |= S5P_CITRGFMT_YCBCR420;
138 break;
139 case S5P_FIMC_YCBYCR422:
140 case S5P_FIMC_YCRYCB422:
141 case S5P_FIMC_CBYCRY422:
142 case S5P_FIMC_CRYCBY422:
143 if (frame->fmt->planes_cnt == 1)
144 cfg |= S5P_CITRGFMT_YCBCR422_1P;
145 else
146 cfg |= S5P_CITRGFMT_YCBCR422;
147 break;
148 default:
149 break;
150 }
151
152 cfg |= S5P_CITRGFMT_HSIZE(frame->width);
153 cfg |= S5P_CITRGFMT_VSIZE(frame->height);
154
155 if (ctx->rotation == 0) {
156 cfg &= ~S5P_CITRGFMT_FLIP_MASK;
157 cfg |= fimc_hw_get_target_flip(ctx->flip);
158 }
159 writel(cfg, dev->regs + S5P_CITRGFMT);
160
161 cfg = readl(dev->regs + S5P_CITAREA) & ~S5P_CITAREA_MASK;
162 cfg |= (frame->width * frame->height);
163 writel(cfg, dev->regs + S5P_CITAREA);
164}
165
166static void fimc_hw_set_out_dma_size(struct fimc_ctx *ctx)
167{
168 struct fimc_dev *dev = ctx->fimc_dev;
169 struct fimc_frame *frame = &ctx->d_frame;
170 u32 cfg = 0;
171
172 if (ctx->rotation == 90 || ctx->rotation == 270) {
173 cfg |= S5P_ORIG_SIZE_HOR(frame->f_height);
174 cfg |= S5P_ORIG_SIZE_VER(frame->f_width);
175 } else {
176 cfg |= S5P_ORIG_SIZE_HOR(frame->f_width);
177 cfg |= S5P_ORIG_SIZE_VER(frame->f_height);
178 }
179 writel(cfg, dev->regs + S5P_ORGOSIZE);
180}
181
182void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
183{
184 u32 cfg;
185 struct fimc_dev *dev = ctx->fimc_dev;
186 struct fimc_frame *frame = &ctx->d_frame;
187 struct fimc_dma_offset *offset = &frame->dma_offset;
188
189 /* Set the input dma offsets. */
190 cfg = 0;
191 cfg |= S5P_CIO_OFFS_HOR(offset->y_h);
192 cfg |= S5P_CIO_OFFS_VER(offset->y_v);
193 writel(cfg, dev->regs + S5P_CIOYOFF);
194
195 cfg = 0;
196 cfg |= S5P_CIO_OFFS_HOR(offset->cb_h);
197 cfg |= S5P_CIO_OFFS_VER(offset->cb_v);
198 writel(cfg, dev->regs + S5P_CIOCBOFF);
199
200 cfg = 0;
201 cfg |= S5P_CIO_OFFS_HOR(offset->cr_h);
202 cfg |= S5P_CIO_OFFS_VER(offset->cr_v);
203 writel(cfg, dev->regs + S5P_CIOCROFF);
204
205 fimc_hw_set_out_dma_size(ctx);
206
207 /* Configure chroma components order. */
208 cfg = readl(dev->regs + S5P_CIOCTRL);
209
210 cfg &= ~(S5P_CIOCTRL_ORDER2P_MASK | S5P_CIOCTRL_ORDER422_MASK |
211 S5P_CIOCTRL_YCBCR_PLANE_MASK);
212
213 if (frame->fmt->planes_cnt == 1)
214 cfg |= ctx->out_order_1p;
215 else if (frame->fmt->planes_cnt == 2)
216 cfg |= ctx->out_order_2p | S5P_CIOCTRL_YCBCR_2PLANE;
217 else if (frame->fmt->planes_cnt == 3)
218 cfg |= S5P_CIOCTRL_YCBCR_3PLANE;
219
220 writel(cfg, dev->regs + S5P_CIOCTRL);
221}
222
223static void fimc_hw_en_autoload(struct fimc_dev *dev, int enable)
224{
225 u32 cfg = readl(dev->regs + S5P_ORGISIZE);
226 if (enable)
227 cfg |= S5P_CIREAL_ISIZE_AUTOLOAD_EN;
228 else
229 cfg &= ~S5P_CIREAL_ISIZE_AUTOLOAD_EN;
230 writel(cfg, dev->regs + S5P_ORGISIZE);
231}
232
233void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable)
234{
235 unsigned long flags;
236 u32 cfg;
237
238 spin_lock_irqsave(&dev->slock, flags);
239
240 cfg = readl(dev->regs + S5P_CIOCTRL);
241 if (enable)
242 cfg |= S5P_CIOCTRL_LASTIRQ_ENABLE;
243 else
244 cfg &= ~S5P_CIOCTRL_LASTIRQ_ENABLE;
245 writel(cfg, dev->regs + S5P_CIOCTRL);
246
247 spin_unlock_irqrestore(&dev->slock, flags);
248}
249
250void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
251{
252 struct fimc_dev *dev = ctx->fimc_dev;
253 struct fimc_scaler *sc = &ctx->scaler;
254 u32 cfg = 0, shfactor;
255
256 shfactor = 10 - (sc->hfactor + sc->vfactor);
257
258 cfg |= S5P_CISCPRERATIO_SHFACTOR(shfactor);
259 cfg |= S5P_CISCPRERATIO_HOR(sc->pre_hratio);
260 cfg |= S5P_CISCPRERATIO_VER(sc->pre_vratio);
261 writel(cfg, dev->regs + S5P_CISCPRERATIO);
262
263 cfg = 0;
264 cfg |= S5P_CISCPREDST_WIDTH(sc->pre_dst_width);
265 cfg |= S5P_CISCPREDST_HEIGHT(sc->pre_dst_height);
266 writel(cfg, dev->regs + S5P_CISCPREDST);
267}
268
269void fimc_hw_set_scaler(struct fimc_ctx *ctx)
270{
271 struct fimc_dev *dev = ctx->fimc_dev;
272 struct fimc_scaler *sc = &ctx->scaler;
273 struct fimc_frame *src_frame = &ctx->s_frame;
274 struct fimc_frame *dst_frame = &ctx->d_frame;
275 u32 cfg = 0;
276
277 if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
278 cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE);
279
280 if (!sc->enabled)
281 cfg |= S5P_CISCCTRL_SCALERBYPASS;
282
283 if (sc->scaleup_h)
284 cfg |= S5P_CISCCTRL_SCALEUP_H;
285
286 if (sc->scaleup_v)
287 cfg |= S5P_CISCCTRL_SCALEUP_V;
288
289 if (sc->copy_mode)
290 cfg |= S5P_CISCCTRL_ONE2ONE;
291
292
293 if (ctx->in_path == FIMC_DMA) {
294 if (src_frame->fmt->color == S5P_FIMC_RGB565)
295 cfg |= S5P_CISCCTRL_INRGB_FMT_RGB565;
296 else if (src_frame->fmt->color == S5P_FIMC_RGB666)
297 cfg |= S5P_CISCCTRL_INRGB_FMT_RGB666;
298 else if (src_frame->fmt->color == S5P_FIMC_RGB888)
299 cfg |= S5P_CISCCTRL_INRGB_FMT_RGB888;
300 }
301
302 if (ctx->out_path == FIMC_DMA) {
303 if (dst_frame->fmt->color == S5P_FIMC_RGB565)
304 cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB565;
305 else if (dst_frame->fmt->color == S5P_FIMC_RGB666)
306 cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB666;
307 else if (dst_frame->fmt->color == S5P_FIMC_RGB888)
308 cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888;
309 } else {
310 cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888;
311
312 if (ctx->flags & FIMC_SCAN_MODE_INTERLACED)
313 cfg |= S5P_CISCCTRL_INTERLACE;
314 }
315
316 dbg("main_hratio= 0x%X main_vratio= 0x%X",
317 sc->main_hratio, sc->main_vratio);
318
319 cfg |= S5P_CISCCTRL_SC_HORRATIO(sc->main_hratio);
320 cfg |= S5P_CISCCTRL_SC_VERRATIO(sc->main_vratio);
321
322 writel(cfg, dev->regs + S5P_CISCCTRL);
323}
324
325void fimc_hw_en_capture(struct fimc_ctx *ctx)
326{
327 struct fimc_dev *dev = ctx->fimc_dev;
328 u32 cfg;
329
330 cfg = readl(dev->regs + S5P_CIIMGCPT);
331 /* One shot mode for output DMA or freerun for FIFO. */
332 if (ctx->out_path == FIMC_DMA)
333 cfg |= S5P_CIIMGCPT_CPT_FREN_ENABLE;
334 else
335 cfg &= ~S5P_CIIMGCPT_CPT_FREN_ENABLE;
336
337 if (ctx->scaler.enabled)
338 cfg |= S5P_CIIMGCPT_IMGCPTEN_SC;
339
340 writel(cfg | S5P_CIIMGCPT_IMGCPTEN, dev->regs + S5P_CIIMGCPT);
341}
342
343void fimc_hw_set_effect(struct fimc_ctx *ctx)
344{
345 struct fimc_dev *dev = ctx->fimc_dev;
346 struct fimc_effect *effect = &ctx->effect;
347 u32 cfg = (S5P_CIIMGEFF_IE_ENABLE | S5P_CIIMGEFF_IE_SC_AFTER);
348
349 cfg |= effect->type;
350
351 if (effect->type == S5P_FIMC_EFFECT_ARBITRARY) {
352 cfg |= S5P_CIIMGEFF_PAT_CB(effect->pat_cb);
353 cfg |= S5P_CIIMGEFF_PAT_CR(effect->pat_cr);
354 }
355
356 writel(cfg, dev->regs + S5P_CIIMGEFF);
357}
358
359static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx)
360{
361 struct fimc_dev *dev = ctx->fimc_dev;
362 struct fimc_frame *frame = &ctx->s_frame;
363 u32 cfg_o = 0;
364 u32 cfg_r = 0;
365
366 if (FIMC_LCDFIFO == ctx->out_path)
367 cfg_r |= S5P_CIREAL_ISIZE_AUTOLOAD_EN;
368
369 cfg_o |= S5P_ORIG_SIZE_HOR(frame->f_width);
370 cfg_o |= S5P_ORIG_SIZE_VER(frame->f_height);
371 cfg_r |= S5P_CIREAL_ISIZE_WIDTH(frame->width);
372 cfg_r |= S5P_CIREAL_ISIZE_HEIGHT(frame->height);
373
374 writel(cfg_o, dev->regs + S5P_ORGISIZE);
375 writel(cfg_r, dev->regs + S5P_CIREAL_ISIZE);
376}
377
378void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
379{
380 struct fimc_dev *dev = ctx->fimc_dev;
381 struct fimc_frame *frame = &ctx->s_frame;
382 struct fimc_dma_offset *offset = &frame->dma_offset;
383 u32 cfg = 0;
384
385 /* Set the pixel offsets. */
386 cfg |= S5P_CIO_OFFS_HOR(offset->y_h);
387 cfg |= S5P_CIO_OFFS_VER(offset->y_v);
388 writel(cfg, dev->regs + S5P_CIIYOFF);
389
390 cfg = 0;
391 cfg |= S5P_CIO_OFFS_HOR(offset->cb_h);
392 cfg |= S5P_CIO_OFFS_VER(offset->cb_v);
393 writel(cfg, dev->regs + S5P_CIICBOFF);
394
395 cfg = 0;
396 cfg |= S5P_CIO_OFFS_HOR(offset->cr_h);
397 cfg |= S5P_CIO_OFFS_VER(offset->cr_v);
398 writel(cfg, dev->regs + S5P_CIICROFF);
399
400 /* Input original and real size. */
401 fimc_hw_set_in_dma_size(ctx);
402
403 /* Autoload is used currently only in FIFO mode. */
404 fimc_hw_en_autoload(dev, ctx->out_path == FIMC_LCDFIFO);
405
406 /* Set the input DMA to process single frame only. */
407 cfg = readl(dev->regs + S5P_MSCTRL);
408 cfg &= ~(S5P_MSCTRL_FLIP_MASK
409 | S5P_MSCTRL_INFORMAT_MASK
410 | S5P_MSCTRL_IN_BURST_COUNT_MASK
411 | S5P_MSCTRL_INPUT_MASK
412 | S5P_MSCTRL_C_INT_IN_MASK
413 | S5P_MSCTRL_2P_IN_ORDER_MASK);
414
415 cfg |= (S5P_MSCTRL_FRAME_COUNT(1) | S5P_MSCTRL_INPUT_MEMORY);
416
417 switch (frame->fmt->color) {
418 case S5P_FIMC_RGB565:
419 case S5P_FIMC_RGB666:
420 case S5P_FIMC_RGB888:
421 cfg |= S5P_MSCTRL_INFORMAT_RGB;
422 break;
423 case S5P_FIMC_YCBCR420:
424 cfg |= S5P_MSCTRL_INFORMAT_YCBCR420;
425
426 if (frame->fmt->planes_cnt == 2)
427 cfg |= ctx->in_order_2p | S5P_MSCTRL_C_INT_IN_2PLANE;
428 else
429 cfg |= S5P_MSCTRL_C_INT_IN_3PLANE;
430
431 break;
432 case S5P_FIMC_YCBYCR422:
433 case S5P_FIMC_YCRYCB422:
434 case S5P_FIMC_CBYCRY422:
435 case S5P_FIMC_CRYCBY422:
436 if (frame->fmt->planes_cnt == 1) {
437 cfg |= ctx->in_order_1p
438 | S5P_MSCTRL_INFORMAT_YCBCR422_1P;
439 } else {
440 cfg |= S5P_MSCTRL_INFORMAT_YCBCR422;
441
442 if (frame->fmt->planes_cnt == 2)
443 cfg |= ctx->in_order_2p
444 | S5P_MSCTRL_C_INT_IN_2PLANE;
445 else
446 cfg |= S5P_MSCTRL_C_INT_IN_3PLANE;
447 }
448 break;
449 default:
450 break;
451 }
452
453 /*
454 * Input DMA flip mode (and rotation).
455 * Do not allow simultaneous rotation and flipping.
456 */
457 if (!ctx->rotation && ctx->out_path == FIMC_LCDFIFO)
458 cfg |= fimc_hw_get_in_flip(ctx->flip);
459
460 writel(cfg, dev->regs + S5P_MSCTRL);
461
462 /* Input/output DMA linear/tiled mode. */
463 cfg = readl(dev->regs + S5P_CIDMAPARAM);
464 cfg &= ~S5P_CIDMAPARAM_TILE_MASK;
465
466 if (tiled_fmt(ctx->s_frame.fmt))
467 cfg |= S5P_CIDMAPARAM_R_64X32;
468
469 if (tiled_fmt(ctx->d_frame.fmt))
470 cfg |= S5P_CIDMAPARAM_W_64X32;
471
472 writel(cfg, dev->regs + S5P_CIDMAPARAM);
473}
474
475
476void fimc_hw_set_input_path(struct fimc_ctx *ctx)
477{
478 struct fimc_dev *dev = ctx->fimc_dev;
479
480 u32 cfg = readl(dev->regs + S5P_MSCTRL);
481 cfg &= ~S5P_MSCTRL_INPUT_MASK;
482
483 if (ctx->in_path == FIMC_DMA)
484 cfg |= S5P_MSCTRL_INPUT_MEMORY;
485 else
486 cfg |= S5P_MSCTRL_INPUT_EXTCAM;
487
488 writel(cfg, dev->regs + S5P_MSCTRL);
489}
490
491void fimc_hw_set_output_path(struct fimc_ctx *ctx)
492{
493 struct fimc_dev *dev = ctx->fimc_dev;
494
495 u32 cfg = readl(dev->regs + S5P_CISCCTRL);
496 cfg &= ~S5P_CISCCTRL_LCDPATHEN_FIFO;
497 if (ctx->out_path == FIMC_LCDFIFO)
498 cfg |= S5P_CISCCTRL_LCDPATHEN_FIFO;
499 writel(cfg, dev->regs + S5P_CISCCTRL);
500}
501
502void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
503{
504 u32 cfg = 0;
505
506 cfg = readl(dev->regs + S5P_CIREAL_ISIZE);
507 cfg |= S5P_CIREAL_ISIZE_ADDR_CH_DIS;
508 writel(cfg, dev->regs + S5P_CIREAL_ISIZE);
509
510 writel(paddr->y, dev->regs + S5P_CIIYSA0);
511 writel(paddr->cb, dev->regs + S5P_CIICBSA0);
512 writel(paddr->cr, dev->regs + S5P_CIICRSA0);
513
514 cfg &= ~S5P_CIREAL_ISIZE_ADDR_CH_DIS;
515 writel(cfg, dev->regs + S5P_CIREAL_ISIZE);
516}
517
518void fimc_hw_set_output_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
519{
520 int i;
521 /* Set all the output register sets to point to single video buffer. */
522 for (i = 0; i < FIMC_MAX_OUT_BUFS; i++) {
523 writel(paddr->y, dev->regs + S5P_CIOYSA(i));
524 writel(paddr->cb, dev->regs + S5P_CIOCBSA(i));
525 writel(paddr->cr, dev->regs + S5P_CIOCRSA(i));
526 }
527}
diff --git a/drivers/media/video/s5p-fimc/regs-fimc.h b/drivers/media/video/s5p-fimc/regs-fimc.h
new file mode 100644
index 00000000000..a3cfe824db0
--- /dev/null
+++ b/drivers/media/video/s5p-fimc/regs-fimc.h
@@ -0,0 +1,293 @@
1/*
2 * Register definition file for Samsung Camera Interface (FIMC) driver
3 *
4 * Copyright (c) 2010 Samsung Electronics
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef REGS_FIMC_H_
12#define REGS_FIMC_H_
13
14#define S5P_CIOYSA(__x) (0x18 + (__x) * 4)
15#define S5P_CIOCBSA(__x) (0x28 + (__x) * 4)
16#define S5P_CIOCRSA(__x) (0x38 + (__x) * 4)
17
18/* Input source format */
19#define S5P_CISRCFMT 0x00
20#define S5P_CISRCFMT_ITU601_8BIT (1 << 31)
21#define S5P_CISRCFMT_ITU601_16BIT (1 << 29)
22#define S5P_CISRCFMT_ORDER422_YCBYCR (0 << 14)
23#define S5P_CISRCFMT_ORDER422_YCRYCB (1 << 14)
24#define S5P_CISRCFMT_ORDER422_CBYCRY (2 << 14)
25#define S5P_CISRCFMT_ORDER422_CRYCBY (3 << 14)
26#define S5P_CISRCFMT_HSIZE(x) ((x) << 16)
27#define S5P_CISRCFMT_VSIZE(x) ((x) << 0)
28
29/* Window offset */
30#define S5P_CIWDOFST 0x04
31#define S5P_CIWDOFST_WINOFSEN (1 << 31)
32#define S5P_CIWDOFST_CLROVFIY (1 << 30)
33#define S5P_CIWDOFST_CLROVRLB (1 << 29)
34#define S5P_CIWDOFST_WINHOROFST_MASK (0x7ff << 16)
35#define S5P_CIWDOFST_CLROVFICB (1 << 15)
36#define S5P_CIWDOFST_CLROVFICR (1 << 14)
37#define S5P_CIWDOFST_WINHOROFST(x) ((x) << 16)
38#define S5P_CIWDOFST_WINVEROFST(x) ((x) << 0)
39#define S5P_CIWDOFST_WINVEROFST_MASK (0xfff << 0)
40
41/* Global control */
42#define S5P_CIGCTRL 0x08
43#define S5P_CIGCTRL_SWRST (1 << 31)
44#define S5P_CIGCTRL_CAMRST_A (1 << 30)
45#define S5P_CIGCTRL_SELCAM_ITU_A (1 << 29)
46#define S5P_CIGCTRL_SELCAM_ITU_MASK (1 << 29)
47#define S5P_CIGCTRL_TESTPAT_NORMAL (0 << 27)
48#define S5P_CIGCTRL_TESTPAT_COLOR_BAR (1 << 27)
49#define S5P_CIGCTRL_TESTPAT_HOR_INC (2 << 27)
50#define S5P_CIGCTRL_TESTPAT_VER_INC (3 << 27)
51#define S5P_CIGCTRL_TESTPAT_MASK (3 << 27)
52#define S5P_CIGCTRL_TESTPAT_SHIFT (27)
53#define S5P_CIGCTRL_INVPOLPCLK (1 << 26)
54#define S5P_CIGCTRL_INVPOLVSYNC (1 << 25)
55#define S5P_CIGCTRL_INVPOLHREF (1 << 24)
56#define S5P_CIGCTRL_IRQ_OVFEN (1 << 22)
57#define S5P_CIGCTRL_HREF_MASK (1 << 21)
58#define S5P_CIGCTRL_IRQ_LEVEL (1 << 20)
59#define S5P_CIGCTRL_IRQ_CLR (1 << 19)
60#define S5P_CIGCTRL_IRQ_ENABLE (1 << 16)
61#define S5P_CIGCTRL_SHDW_DISABLE (1 << 12)
62#define S5P_CIGCTRL_SELCAM_MIPI_A (1 << 7)
63#define S5P_CIGCTRL_CAMIF_SELWB (1 << 6)
64#define S5P_CIGCTRL_INVPOLHSYNC (1 << 4)
65#define S5P_CIGCTRL_SELCAM_MIPI (1 << 3)
66#define S5P_CIGCTRL_INTERLACE (1 << 0)
67
68/* Window offset 2 */
69#define S5P_CIWDOFST2 0x14
70#define S5P_CIWDOFST2_HOROFF_MASK (0xfff << 16)
71#define S5P_CIWDOFST2_VEROFF_MASK (0xfff << 0)
72#define S5P_CIWDOFST2_HOROFF(x) ((x) << 16)
73#define S5P_CIWDOFST2_VEROFF(x) ((x) << 0)
74
75/* Output DMA Y plane start address */
76#define S5P_CIOYSA1 0x18
77#define S5P_CIOYSA2 0x1c
78#define S5P_CIOYSA3 0x20
79#define S5P_CIOYSA4 0x24
80
81/* Output DMA Cb plane start address */
82#define S5P_CIOCBSA1 0x28
83#define S5P_CIOCBSA2 0x2c
84#define S5P_CIOCBSA3 0x30
85#define S5P_CIOCBSA4 0x34
86
87/* Output DMA Cr plane start address */
88#define S5P_CIOCRSA1 0x38
89#define S5P_CIOCRSA2 0x3c
90#define S5P_CIOCRSA3 0x40
91#define S5P_CIOCRSA4 0x44
92
93/* Target image format */
94#define S5P_CITRGFMT 0x48
95#define S5P_CITRGFMT_INROT90 (1 << 31)
96#define S5P_CITRGFMT_YCBCR420 (0 << 29)
97#define S5P_CITRGFMT_YCBCR422 (1 << 29)
98#define S5P_CITRGFMT_YCBCR422_1P (2 << 29)
99#define S5P_CITRGFMT_RGB (3 << 29)
100#define S5P_CITRGFMT_FMT_MASK (3 << 29)
101#define S5P_CITRGFMT_HSIZE_MASK (0xfff << 16)
102#define S5P_CITRGFMT_FLIP_SHIFT (14)
103#define S5P_CITRGFMT_FLIP_NORMAL (0 << 14)
104#define S5P_CITRGFMT_FLIP_X_MIRROR (1 << 14)
105#define S5P_CITRGFMT_FLIP_Y_MIRROR (2 << 14)
106#define S5P_CITRGFMT_FLIP_180 (3 << 14)
107#define S5P_CITRGFMT_FLIP_MASK (3 << 14)
108#define S5P_CITRGFMT_OUTROT90 (1 << 13)
109#define S5P_CITRGFMT_VSIZE_MASK (0xfff << 0)
110#define S5P_CITRGFMT_HSIZE(x) ((x) << 16)
111#define S5P_CITRGFMT_VSIZE(x) ((x) << 0)
112
113/* Output DMA control */
114#define S5P_CIOCTRL 0x4c
115#define S5P_CIOCTRL_ORDER422_MASK (3 << 0)
116#define S5P_CIOCTRL_ORDER422_CRYCBY (0 << 0)
117#define S5P_CIOCTRL_ORDER422_YCRYCB (1 << 0)
118#define S5P_CIOCTRL_ORDER422_CBYCRY (2 << 0)
119#define S5P_CIOCTRL_ORDER422_YCBYCR (3 << 0)
120#define S5P_CIOCTRL_LASTIRQ_ENABLE (1 << 2)
121#define S5P_CIOCTRL_YCBCR_3PLANE (0 << 3)
122#define S5P_CIOCTRL_YCBCR_2PLANE (1 << 3)
123#define S5P_CIOCTRL_YCBCR_PLANE_MASK (1 << 3)
124#define S5P_CIOCTRL_ORDER2P_SHIFT (24)
125#define S5P_CIOCTRL_ORDER2P_MASK (3 << 24)
126#define S5P_CIOCTRL_ORDER422_2P_LSB_CRCB (0 << 24)
127
128/* Pre-scaler control 1 */
129#define S5P_CISCPRERATIO 0x50
130#define S5P_CISCPRERATIO_SHFACTOR(x) ((x) << 28)
131#define S5P_CISCPRERATIO_HOR(x) ((x) << 16)
132#define S5P_CISCPRERATIO_VER(x) ((x) << 0)
133
134#define S5P_CISCPREDST 0x54
135#define S5P_CISCPREDST_WIDTH(x) ((x) << 16)
136#define S5P_CISCPREDST_HEIGHT(x) ((x) << 0)
137
138/* Main scaler control */
139#define S5P_CISCCTRL 0x58
140#define S5P_CISCCTRL_SCALERBYPASS (1 << 31)
141#define S5P_CISCCTRL_SCALEUP_H (1 << 30)
142#define S5P_CISCCTRL_SCALEUP_V (1 << 29)
143#define S5P_CISCCTRL_CSCR2Y_WIDE (1 << 28)
144#define S5P_CISCCTRL_CSCY2R_WIDE (1 << 27)
145#define S5P_CISCCTRL_LCDPATHEN_FIFO (1 << 26)
146#define S5P_CISCCTRL_INTERLACE (1 << 25)
147#define S5P_CISCCTRL_SCALERSTART (1 << 15)
148#define S5P_CISCCTRL_INRGB_FMT_RGB565 (0 << 13)
149#define S5P_CISCCTRL_INRGB_FMT_RGB666 (1 << 13)
150#define S5P_CISCCTRL_INRGB_FMT_RGB888 (2 << 13)
151#define S5P_CISCCTRL_INRGB_FMT_MASK (3 << 13)
152#define S5P_CISCCTRL_OUTRGB_FMT_RGB565 (0 << 11)
153#define S5P_CISCCTRL_OUTRGB_FMT_RGB666 (1 << 11)
154#define S5P_CISCCTRL_OUTRGB_FMT_RGB888 (2 << 11)
155#define S5P_CISCCTRL_OUTRGB_FMT_MASK (3 << 11)
156#define S5P_CISCCTRL_RGB_EXT (1 << 10)
157#define S5P_CISCCTRL_ONE2ONE (1 << 9)
158#define S5P_CISCCTRL_SC_HORRATIO(x) ((x) << 16)
159#define S5P_CISCCTRL_SC_VERRATIO(x) ((x) << 0)
160
161/* Target area */
162#define S5P_CITAREA 0x5c
163#define S5P_CITAREA_MASK 0x0fffffff
164
165/* General status */
166#define S5P_CISTATUS 0x64
167#define S5P_CISTATUS_OVFIY (1 << 31)
168#define S5P_CISTATUS_OVFICB (1 << 30)
169#define S5P_CISTATUS_OVFICR (1 << 29)
170#define S5P_CISTATUS_VSYNC (1 << 28)
171#define S5P_CISTATUS_WINOFF_EN (1 << 25)
172#define S5P_CISTATUS_IMGCPT_EN (1 << 22)
173#define S5P_CISTATUS_IMGCPT_SCEN (1 << 21)
174#define S5P_CISTATUS_VSYNC_A (1 << 20)
175#define S5P_CISTATUS_VSYNC_B (1 << 19)
176#define S5P_CISTATUS_OVRLB (1 << 18)
177#define S5P_CISTATUS_FRAME_END (1 << 17)
178#define S5P_CISTATUS_LASTCAPT_END (1 << 16)
179#define S5P_CISTATUS_VVALID_A (1 << 15)
180#define S5P_CISTATUS_VVALID_B (1 << 14)
181
182/* Image capture control */
183#define S5P_CIIMGCPT 0xc0
184#define S5P_CIIMGCPT_IMGCPTEN (1 << 31)
185#define S5P_CIIMGCPT_IMGCPTEN_SC (1 << 30)
186#define S5P_CIIMGCPT_CPT_FREN_ENABLE (1 << 25)
187#define S5P_CIIMGCPT_CPT_FRMOD_CNT (1 << 18)
188
189/* Frame capture sequence */
190#define S5P_CICPTSEQ 0xc4
191
192/* Image effect */
193#define S5P_CIIMGEFF 0xd0
194#define S5P_CIIMGEFF_IE_DISABLE (0 << 30)
195#define S5P_CIIMGEFF_IE_ENABLE (1 << 30)
196#define S5P_CIIMGEFF_IE_SC_BEFORE (0 << 29)
197#define S5P_CIIMGEFF_IE_SC_AFTER (1 << 29)
198#define S5P_CIIMGEFF_FIN_BYPASS (0 << 26)
199#define S5P_CIIMGEFF_FIN_ARBITRARY (1 << 26)
200#define S5P_CIIMGEFF_FIN_NEGATIVE (2 << 26)
201#define S5P_CIIMGEFF_FIN_ARTFREEZE (3 << 26)
202#define S5P_CIIMGEFF_FIN_EMBOSSING (4 << 26)
203#define S5P_CIIMGEFF_FIN_SILHOUETTE (5 << 26)
204#define S5P_CIIMGEFF_FIN_MASK (7 << 26)
205#define S5P_CIIMGEFF_PAT_CBCR_MASK ((0xff < 13) | (0xff < 0))
206#define S5P_CIIMGEFF_PAT_CB(x) ((x) << 13)
207#define S5P_CIIMGEFF_PAT_CR(x) ((x) << 0)
208
209/* Input DMA Y/Cb/Cr plane start address 0 */
210#define S5P_CIIYSA0 0xd4
211#define S5P_CIICBSA0 0xd8
212#define S5P_CIICRSA0 0xdc
213
214/* Real input DMA image size */
215#define S5P_CIREAL_ISIZE 0xf8
216#define S5P_CIREAL_ISIZE_AUTOLOAD_EN (1 << 31)
217#define S5P_CIREAL_ISIZE_ADDR_CH_DIS (1 << 30)
218#define S5P_CIREAL_ISIZE_HEIGHT(x) ((x) << 16)
219#define S5P_CIREAL_ISIZE_WIDTH(x) ((x) << 0)
220
221
222/* Input DMA control */
223#define S5P_MSCTRL 0xfc
224#define S5P_MSCTRL_IN_BURST_COUNT_MASK (3 << 24)
225#define S5P_MSCTRL_2P_IN_ORDER_MASK (3 << 16)
226#define S5P_MSCTRL_2P_IN_ORDER_SHIFT 16
227#define S5P_MSCTRL_C_INT_IN_3PLANE (0 << 15)
228#define S5P_MSCTRL_C_INT_IN_2PLANE (1 << 15)
229#define S5P_MSCTRL_C_INT_IN_MASK (1 << 15)
230#define S5P_MSCTRL_FLIP_SHIFT 13
231#define S5P_MSCTRL_FLIP_MASK (3 << 13)
232#define S5P_MSCTRL_FLIP_NORMAL (0 << 13)
233#define S5P_MSCTRL_FLIP_X_MIRROR (1 << 13)
234#define S5P_MSCTRL_FLIP_Y_MIRROR (2 << 13)
235#define S5P_MSCTRL_FLIP_180 (3 << 13)
236#define S5P_MSCTRL_ORDER422_SHIFT 4
237#define S5P_MSCTRL_ORDER422_CRYCBY (0 << 4)
238#define S5P_MSCTRL_ORDER422_YCRYCB (1 << 4)
239#define S5P_MSCTRL_ORDER422_CBYCRY (2 << 4)
240#define S5P_MSCTRL_ORDER422_YCBYCR (3 << 4)
241#define S5P_MSCTRL_ORDER422_MASK (3 << 4)
242#define S5P_MSCTRL_INPUT_EXTCAM (0 << 3)
243#define S5P_MSCTRL_INPUT_MEMORY (1 << 3)
244#define S5P_MSCTRL_INPUT_MASK (1 << 3)
245#define S5P_MSCTRL_INFORMAT_YCBCR420 (0 << 1)
246#define S5P_MSCTRL_INFORMAT_YCBCR422 (1 << 1)
247#define S5P_MSCTRL_INFORMAT_YCBCR422_1P (2 << 1)
248#define S5P_MSCTRL_INFORMAT_RGB (3 << 1)
249#define S5P_MSCTRL_INFORMAT_MASK (3 << 1)
250#define S5P_MSCTRL_ENVID (1 << 0)
251#define S5P_MSCTRL_FRAME_COUNT(x) ((x) << 24)
252
253/* Input DMA Y/Cb/Cr plane start address 1 */
254#define S5P_CIIYSA1 0x144
255#define S5P_CIICBSA1 0x148
256#define S5P_CIICRSA1 0x14c
257
258/* Output DMA Y/Cb/Cr offset */
259#define S5P_CIOYOFF 0x168
260#define S5P_CIOCBOFF 0x16c
261#define S5P_CIOCROFF 0x170
262
263/* Input DMA Y/Cb/Cr offset */
264#define S5P_CIIYOFF 0x174
265#define S5P_CIICBOFF 0x178
266#define S5P_CIICROFF 0x17c
267
268#define S5P_CIO_OFFS_VER(x) ((x) << 16)
269#define S5P_CIO_OFFS_HOR(x) ((x) << 0)
270
271/* Input DMA original image size */
272#define S5P_ORGISIZE 0x180
273
274/* Output DMA original image size */
275#define S5P_ORGOSIZE 0x184
276
277#define S5P_ORIG_SIZE_VER(x) ((x) << 16)
278#define S5P_ORIG_SIZE_HOR(x) ((x) << 0)
279
280/* Real output DMA image size (extension register) */
281#define S5P_CIEXTEN 0x188
282
283#define S5P_CIDMAPARAM 0x18c
284#define S5P_CIDMAPARAM_R_LINEAR (0 << 29)
285#define S5P_CIDMAPARAM_R_64X32 (3 << 29)
286#define S5P_CIDMAPARAM_W_LINEAR (0 << 13)
287#define S5P_CIDMAPARAM_W_64X32 (3 << 13)
288#define S5P_CIDMAPARAM_TILE_MASK ((3 << 29) | (3 << 13))
289
290/* MIPI CSI image format */
291#define S5P_CSIIMGFMT 0x194
292
293#endif /* REGS_FIMC_H_ */
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index 76da7436868..ee963f4d01b 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -45,6 +45,7 @@
45#include <linux/i2c.h> 45#include <linux/i2c.h>
46#include <linux/videodev2.h> 46#include <linux/videodev2.h>
47#include <media/v4l2-device.h> 47#include <media/v4l2-device.h>
48#include <media/v4l2-ctrls.h>
48#include <media/v4l2-chip-ident.h> 49#include <media/v4l2-chip-ident.h>
49#include <media/v4l2-i2c-drv.h> 50#include <media/v4l2-i2c-drv.h>
50#include <media/saa7115.h> 51#include <media/saa7115.h>
@@ -65,16 +66,19 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
65 66
66struct saa711x_state { 67struct saa711x_state {
67 struct v4l2_subdev sd; 68 struct v4l2_subdev sd;
69 struct v4l2_ctrl_handler hdl;
70
71 struct {
72 /* chroma gain control cluster */
73 struct v4l2_ctrl *agc;
74 struct v4l2_ctrl *gain;
75 };
76
68 v4l2_std_id std; 77 v4l2_std_id std;
69 int input; 78 int input;
70 int output; 79 int output;
71 int enable; 80 int enable;
72 int radio; 81 int radio;
73 int bright;
74 int contrast;
75 int hue;
76 int sat;
77 int chroma_agc;
78 int width; 82 int width;
79 int height; 83 int height;
80 u32 ident; 84 u32 ident;
@@ -90,6 +94,11 @@ static inline struct saa711x_state *to_state(struct v4l2_subdev *sd)
90 return container_of(sd, struct saa711x_state, sd); 94 return container_of(sd, struct saa711x_state, sd);
91} 95}
92 96
97static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
98{
99 return &container_of(ctrl->handler, struct saa711x_state, hdl)->sd;
100}
101
93/* ----------------------------------------------------------------------- */ 102/* ----------------------------------------------------------------------- */
94 103
95static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value) 104static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value)
@@ -741,96 +750,53 @@ static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
741 return 0; 750 return 0;
742} 751}
743 752
744static int saa711x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 753static int saa711x_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
745{ 754{
755 struct v4l2_subdev *sd = to_sd(ctrl);
746 struct saa711x_state *state = to_state(sd); 756 struct saa711x_state *state = to_state(sd);
747 u8 val;
748 757
749 switch (ctrl->id) { 758 switch (ctrl->id) {
750 case V4L2_CID_BRIGHTNESS:
751 if (ctrl->value < 0 || ctrl->value > 255) {
752 v4l2_err(sd, "invalid brightness setting %d\n", ctrl->value);
753 return -ERANGE;
754 }
755
756 state->bright = ctrl->value;
757 saa711x_write(sd, R_0A_LUMA_BRIGHT_CNTL, state->bright);
758 break;
759
760 case V4L2_CID_CONTRAST:
761 if (ctrl->value < 0 || ctrl->value > 127) {
762 v4l2_err(sd, "invalid contrast setting %d\n", ctrl->value);
763 return -ERANGE;
764 }
765
766 state->contrast = ctrl->value;
767 saa711x_write(sd, R_0B_LUMA_CONTRAST_CNTL, state->contrast);
768 break;
769
770 case V4L2_CID_SATURATION:
771 if (ctrl->value < 0 || ctrl->value > 127) {
772 v4l2_err(sd, "invalid saturation setting %d\n", ctrl->value);
773 return -ERANGE;
774 }
775
776 state->sat = ctrl->value;
777 saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, state->sat);
778 break;
779
780 case V4L2_CID_HUE:
781 if (ctrl->value < -128 || ctrl->value > 127) {
782 v4l2_err(sd, "invalid hue setting %d\n", ctrl->value);
783 return -ERANGE;
784 }
785
786 state->hue = ctrl->value;
787 saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, state->hue);
788 break;
789 case V4L2_CID_CHROMA_AGC: 759 case V4L2_CID_CHROMA_AGC:
790 val = saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL); 760 /* chroma gain cluster */
791 state->chroma_agc = ctrl->value; 761 if (state->agc->cur.val)
792 if (ctrl->value) 762 state->gain->cur.val =
793 val &= 0x7f; 763 saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL) & 0x7f;
794 else
795 val |= 0x80;
796 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, val);
797 break; 764 break;
798 case V4L2_CID_CHROMA_GAIN:
799 /* Chroma gain cannot be set when AGC is enabled */
800 if (state->chroma_agc == 1)
801 return -EINVAL;
802 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, ctrl->value | 0x80);
803 break;
804 default:
805 return -EINVAL;
806 } 765 }
807
808 return 0; 766 return 0;
809} 767}
810 768
811static int saa711x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 769static int saa711x_s_ctrl(struct v4l2_ctrl *ctrl)
812{ 770{
771 struct v4l2_subdev *sd = to_sd(ctrl);
813 struct saa711x_state *state = to_state(sd); 772 struct saa711x_state *state = to_state(sd);
814 773
815 switch (ctrl->id) { 774 switch (ctrl->id) {
816 case V4L2_CID_BRIGHTNESS: 775 case V4L2_CID_BRIGHTNESS:
817 ctrl->value = state->bright; 776 saa711x_write(sd, R_0A_LUMA_BRIGHT_CNTL, ctrl->val);
818 break; 777 break;
778
819 case V4L2_CID_CONTRAST: 779 case V4L2_CID_CONTRAST:
820 ctrl->value = state->contrast; 780 saa711x_write(sd, R_0B_LUMA_CONTRAST_CNTL, ctrl->val);
821 break; 781 break;
782
822 case V4L2_CID_SATURATION: 783 case V4L2_CID_SATURATION:
823 ctrl->value = state->sat; 784 saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, ctrl->val);
824 break; 785 break;
786
825 case V4L2_CID_HUE: 787 case V4L2_CID_HUE:
826 ctrl->value = state->hue; 788 saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, ctrl->val);
827 break; 789 break;
790
828 case V4L2_CID_CHROMA_AGC: 791 case V4L2_CID_CHROMA_AGC:
829 ctrl->value = state->chroma_agc; 792 /* chroma gain cluster */
830 break; 793 if (state->agc->val)
831 case V4L2_CID_CHROMA_GAIN: 794 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val);
832 ctrl->value = saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL) & 0x7f; 795 else
796 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val | 0x80);
797 v4l2_ctrl_activate(state->gain, !state->agc->val);
833 break; 798 break;
799
834 default: 800 default:
835 return -EINVAL; 801 return -EINVAL;
836 } 802 }
@@ -1223,25 +1189,6 @@ static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1223 return 0; 1189 return 0;
1224} 1190}
1225 1191
1226static int saa711x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
1227{
1228 switch (qc->id) {
1229 case V4L2_CID_BRIGHTNESS:
1230 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
1231 case V4L2_CID_CONTRAST:
1232 case V4L2_CID_SATURATION:
1233 return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
1234 case V4L2_CID_HUE:
1235 return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
1236 case V4L2_CID_CHROMA_AGC:
1237 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
1238 case V4L2_CID_CHROMA_GAIN:
1239 return v4l2_ctrl_query_fill(qc, 0, 127, 1, 48);
1240 default:
1241 return -EINVAL;
1242 }
1243}
1244
1245static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std) 1192static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1246{ 1193{
1247 struct saa711x_state *state = to_state(sd); 1194 struct saa711x_state *state = to_state(sd);
@@ -1518,17 +1465,27 @@ static int saa711x_log_status(struct v4l2_subdev *sd)
1518 break; 1465 break;
1519 } 1466 }
1520 v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height); 1467 v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height);
1468 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
1521 return 0; 1469 return 0;
1522} 1470}
1523 1471
1524/* ----------------------------------------------------------------------- */ 1472/* ----------------------------------------------------------------------- */
1525 1473
1474static const struct v4l2_ctrl_ops saa711x_ctrl_ops = {
1475 .s_ctrl = saa711x_s_ctrl,
1476 .g_volatile_ctrl = saa711x_g_volatile_ctrl,
1477};
1478
1526static const struct v4l2_subdev_core_ops saa711x_core_ops = { 1479static const struct v4l2_subdev_core_ops saa711x_core_ops = {
1527 .log_status = saa711x_log_status, 1480 .log_status = saa711x_log_status,
1528 .g_chip_ident = saa711x_g_chip_ident, 1481 .g_chip_ident = saa711x_g_chip_ident,
1529 .g_ctrl = saa711x_g_ctrl, 1482 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
1530 .s_ctrl = saa711x_s_ctrl, 1483 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
1531 .queryctrl = saa711x_queryctrl, 1484 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
1485 .g_ctrl = v4l2_subdev_g_ctrl,
1486 .s_ctrl = v4l2_subdev_s_ctrl,
1487 .queryctrl = v4l2_subdev_queryctrl,
1488 .querymenu = v4l2_subdev_querymenu,
1532 .s_std = saa711x_s_std, 1489 .s_std = saa711x_s_std,
1533 .reset = saa711x_reset, 1490 .reset = saa711x_reset,
1534 .s_gpio = saa711x_s_gpio, 1491 .s_gpio = saa711x_s_gpio,
@@ -1579,8 +1536,9 @@ static int saa711x_probe(struct i2c_client *client,
1579{ 1536{
1580 struct saa711x_state *state; 1537 struct saa711x_state *state;
1581 struct v4l2_subdev *sd; 1538 struct v4l2_subdev *sd;
1582 int i; 1539 struct v4l2_ctrl_handler *hdl;
1583 char name[17]; 1540 int i;
1541 char name[17];
1584 char chip_id; 1542 char chip_id;
1585 int autodetect = !id || id->driver_data == 1; 1543 int autodetect = !id || id->driver_data == 1;
1586 1544
@@ -1619,15 +1577,38 @@ static int saa711x_probe(struct i2c_client *client,
1619 return -ENOMEM; 1577 return -ENOMEM;
1620 sd = &state->sd; 1578 sd = &state->sd;
1621 v4l2_i2c_subdev_init(sd, client, &saa711x_ops); 1579 v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
1580
1581 hdl = &state->hdl;
1582 v4l2_ctrl_handler_init(hdl, 6);
1583 /* add in ascending ID order */
1584 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1585 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1586 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1587 V4L2_CID_CONTRAST, 0, 127, 1, 64);
1588 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1589 V4L2_CID_SATURATION, 0, 127, 1, 64);
1590 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1591 V4L2_CID_HUE, -128, 127, 1, 0);
1592 state->agc = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1593 V4L2_CID_CHROMA_AGC, 0, 1, 1, 1);
1594 state->gain = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1595 V4L2_CID_CHROMA_GAIN, 0, 127, 1, 40);
1596 state->gain->is_volatile = 1;
1597 sd->ctrl_handler = hdl;
1598 if (hdl->error) {
1599 int err = hdl->error;
1600
1601 v4l2_ctrl_handler_free(hdl);
1602 kfree(state);
1603 return err;
1604 }
1605 state->agc->flags |= V4L2_CTRL_FLAG_UPDATE;
1606 v4l2_ctrl_cluster(2, &state->agc);
1607
1622 state->input = -1; 1608 state->input = -1;
1623 state->output = SAA7115_IPORT_ON; 1609 state->output = SAA7115_IPORT_ON;
1624 state->enable = 1; 1610 state->enable = 1;
1625 state->radio = 0; 1611 state->radio = 0;
1626 state->bright = 128;
1627 state->contrast = 64;
1628 state->hue = 0;
1629 state->sat = 64;
1630 state->chroma_agc = 1;
1631 switch (chip_id) { 1612 switch (chip_id) {
1632 case '1': 1613 case '1':
1633 state->ident = V4L2_IDENT_SAA7111; 1614 state->ident = V4L2_IDENT_SAA7111;
@@ -1675,6 +1656,7 @@ static int saa711x_probe(struct i2c_client *client,
1675 if (state->ident > V4L2_IDENT_SAA7111A) 1656 if (state->ident > V4L2_IDENT_SAA7111A)
1676 saa711x_writeregs(sd, saa7115_init_misc); 1657 saa711x_writeregs(sd, saa7115_init_misc);
1677 saa711x_set_v4lstd(sd, V4L2_STD_NTSC); 1658 saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
1659 v4l2_ctrl_handler_setup(hdl);
1678 1660
1679 v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n", 1661 v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n",
1680 saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC), 1662 saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC),
@@ -1689,6 +1671,7 @@ static int saa711x_remove(struct i2c_client *client)
1689 struct v4l2_subdev *sd = i2c_get_clientdata(client); 1671 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1690 1672
1691 v4l2_device_unregister_subdev(sd); 1673 v4l2_device_unregister_subdev(sd);
1674 v4l2_ctrl_handler_free(sd->ctrl_handler);
1692 kfree(to_state(sd)); 1675 kfree(to_state(sd));
1693 return 0; 1676 return 0;
1694} 1677}
diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c
index 78d69950c00..45f8bfc1342 100644
--- a/drivers/media/video/saa717x.c
+++ b/drivers/media/video/saa717x.c
@@ -38,6 +38,7 @@
38#include <linux/videodev2.h> 38#include <linux/videodev2.h>
39#include <linux/i2c.h> 39#include <linux/i2c.h>
40#include <media/v4l2-device.h> 40#include <media/v4l2-device.h>
41#include <media/v4l2-ctrls.h>
41#include <media/v4l2-i2c-drv.h> 42#include <media/v4l2-i2c-drv.h>
42 43
43MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver"); 44MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver");
@@ -55,14 +56,11 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
55 56
56struct saa717x_state { 57struct saa717x_state {
57 struct v4l2_subdev sd; 58 struct v4l2_subdev sd;
59 struct v4l2_ctrl_handler hdl;
58 v4l2_std_id std; 60 v4l2_std_id std;
59 int input; 61 int input;
60 int enable; 62 int enable;
61 int radio; 63 int radio;
62 int bright;
63 int contrast;
64 int hue;
65 int sat;
66 int playback; 64 int playback;
67 int audio; 65 int audio;
68 int tuner_audio_mode; 66 int tuner_audio_mode;
@@ -81,6 +79,11 @@ static inline struct saa717x_state *to_state(struct v4l2_subdev *sd)
81 return container_of(sd, struct saa717x_state, sd); 79 return container_of(sd, struct saa717x_state, sd);
82} 80}
83 81
82static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
83{
84 return &container_of(ctrl->handler, struct saa717x_state, hdl)->sd;
85}
86
84/* ----------------------------------------------------------------------- */ 87/* ----------------------------------------------------------------------- */
85 88
86/* for audio mode */ 89/* for audio mode */
@@ -774,29 +777,6 @@ static void set_audio_mode(struct v4l2_subdev *sd, int audio_mode)
774 saa717x_write(sd, 0x470, reg_set_audio_template[audio_mode][1]); 777 saa717x_write(sd, 0x470, reg_set_audio_template[audio_mode][1]);
775} 778}
776 779
777/* write regs to video output level (bright,contrast,hue,sat) */
778static void set_video_output_level_regs(struct v4l2_subdev *sd,
779 struct saa717x_state *decoder)
780{
781 /* brightness ffh (bright) - 80h (ITU level) - 00h (dark) */
782 saa717x_write(sd, 0x10a, decoder->bright);
783
784 /* contrast 7fh (max: 1.984) - 44h (ITU) - 40h (1.0) -
785 0h (luminance off) 40: i2c dump
786 c0h (-1.0 inverse chrominance)
787 80h (-2.0 inverse chrominance) */
788 saa717x_write(sd, 0x10b, decoder->contrast);
789
790 /* saturation? 7fh(max)-40h(ITU)-0h(color off)
791 c0h (-1.0 inverse chrominance)
792 80h (-2.0 inverse chrominance) */
793 saa717x_write(sd, 0x10c, decoder->sat);
794
795 /* color hue (phase) control
796 7fh (+178.6) - 0h (0 normal) - 80h (-180.0) */
797 saa717x_write(sd, 0x10d, decoder->hue);
798}
799
800/* write regs to set audio volume, bass and treble */ 780/* write regs to set audio volume, bass and treble */
801static int set_audio_regs(struct v4l2_subdev *sd, 781static int set_audio_regs(struct v4l2_subdev *sd,
802 struct saa717x_state *decoder) 782 struct saa717x_state *decoder)
@@ -829,9 +809,9 @@ static int set_audio_regs(struct v4l2_subdev *sd,
829 809
830 saa717x_write(sd, 0x480, val); 810 saa717x_write(sd, 0x480, val);
831 811
832 /* bass and treble; go to another function */
833 /* set bass and treble */ 812 /* set bass and treble */
834 val = decoder->audio_main_bass | (decoder->audio_main_treble << 8); 813 val = decoder->audio_main_bass & 0x1f;
814 val |= (decoder->audio_main_treble & 0x1f) << 5;
835 saa717x_write(sd, 0x488, val); 815 saa717x_write(sd, 0x488, val);
836 return 0; 816 return 0;
837} 817}
@@ -893,218 +873,55 @@ static void set_v_scale(struct v4l2_subdev *sd, int task, int yscale)
893 saa717x_write(sd, 0x71 + task_shift, yscale >> 8); 873 saa717x_write(sd, 0x71 + task_shift, yscale >> 8);
894} 874}
895 875
896static int saa717x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 876static int saa717x_s_ctrl(struct v4l2_ctrl *ctrl)
897{
898 struct saa717x_state *state = to_state(sd);
899
900 switch (ctrl->id) {
901 case V4L2_CID_BRIGHTNESS:
902 if (ctrl->value < 0 || ctrl->value > 255) {
903 v4l2_err(sd, "invalid brightness setting %d\n", ctrl->value);
904 return -ERANGE;
905 }
906
907 state->bright = ctrl->value;
908 v4l2_dbg(1, debug, sd, "bright:%d\n", state->bright);
909 saa717x_write(sd, 0x10a, state->bright);
910 break;
911
912 case V4L2_CID_CONTRAST:
913 if (ctrl->value < 0 || ctrl->value > 127) {
914 v4l2_err(sd, "invalid contrast setting %d\n", ctrl->value);
915 return -ERANGE;
916 }
917
918 state->contrast = ctrl->value;
919 v4l2_dbg(1, debug, sd, "contrast:%d\n", state->contrast);
920 saa717x_write(sd, 0x10b, state->contrast);
921 break;
922
923 case V4L2_CID_SATURATION:
924 if (ctrl->value < 0 || ctrl->value > 127) {
925 v4l2_err(sd, "invalid saturation setting %d\n", ctrl->value);
926 return -ERANGE;
927 }
928
929 state->sat = ctrl->value;
930 v4l2_dbg(1, debug, sd, "sat:%d\n", state->sat);
931 saa717x_write(sd, 0x10c, state->sat);
932 break;
933
934 case V4L2_CID_HUE:
935 if (ctrl->value < -128 || ctrl->value > 127) {
936 v4l2_err(sd, "invalid hue setting %d\n", ctrl->value);
937 return -ERANGE;
938 }
939
940 state->hue = ctrl->value;
941 v4l2_dbg(1, debug, sd, "hue:%d\n", state->hue);
942 saa717x_write(sd, 0x10d, state->hue);
943 break;
944
945 case V4L2_CID_AUDIO_MUTE:
946 state->audio_main_mute = ctrl->value;
947 set_audio_regs(sd, state);
948 break;
949
950 case V4L2_CID_AUDIO_VOLUME:
951 state->audio_main_volume = ctrl->value;
952 set_audio_regs(sd, state);
953 break;
954
955 case V4L2_CID_AUDIO_BALANCE:
956 state->audio_main_balance = ctrl->value;
957 set_audio_regs(sd, state);
958 break;
959
960 case V4L2_CID_AUDIO_TREBLE:
961 state->audio_main_treble = ctrl->value;
962 set_audio_regs(sd, state);
963 break;
964
965 case V4L2_CID_AUDIO_BASS:
966 state->audio_main_bass = ctrl->value;
967 set_audio_regs(sd, state);
968 break;
969
970 default:
971 return -EINVAL;
972 }
973
974 return 0;
975}
976
977static int saa717x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
978{ 877{
878 struct v4l2_subdev *sd = to_sd(ctrl);
979 struct saa717x_state *state = to_state(sd); 879 struct saa717x_state *state = to_state(sd);
980 880
981 switch (ctrl->id) { 881 switch (ctrl->id) {
982 case V4L2_CID_BRIGHTNESS: 882 case V4L2_CID_BRIGHTNESS:
983 ctrl->value = state->bright; 883 saa717x_write(sd, 0x10a, ctrl->val);
984 break; 884 return 0;
985 885
986 case V4L2_CID_CONTRAST: 886 case V4L2_CID_CONTRAST:
987 ctrl->value = state->contrast; 887 saa717x_write(sd, 0x10b, ctrl->val);
988 break; 888 return 0;
989 889
990 case V4L2_CID_SATURATION: 890 case V4L2_CID_SATURATION:
991 ctrl->value = state->sat; 891 saa717x_write(sd, 0x10c, ctrl->val);
992 break; 892 return 0;
993 893
994 case V4L2_CID_HUE: 894 case V4L2_CID_HUE:
995 ctrl->value = state->hue; 895 saa717x_write(sd, 0x10d, ctrl->val);
996 break; 896 return 0;
997 897
998 case V4L2_CID_AUDIO_MUTE: 898 case V4L2_CID_AUDIO_MUTE:
999 ctrl->value = state->audio_main_mute; 899 state->audio_main_mute = ctrl->val;
1000 break; 900 break;
1001 901
1002 case V4L2_CID_AUDIO_VOLUME: 902 case V4L2_CID_AUDIO_VOLUME:
1003 ctrl->value = state->audio_main_volume; 903 state->audio_main_volume = ctrl->val;
1004 break; 904 break;
1005 905
1006 case V4L2_CID_AUDIO_BALANCE: 906 case V4L2_CID_AUDIO_BALANCE:
1007 ctrl->value = state->audio_main_balance; 907 state->audio_main_balance = ctrl->val;
1008 break; 908 break;
1009 909
1010 case V4L2_CID_AUDIO_TREBLE: 910 case V4L2_CID_AUDIO_TREBLE:
1011 ctrl->value = state->audio_main_treble; 911 state->audio_main_treble = ctrl->val;
1012 break; 912 break;
1013 913
1014 case V4L2_CID_AUDIO_BASS: 914 case V4L2_CID_AUDIO_BASS:
1015 ctrl->value = state->audio_main_bass; 915 state->audio_main_bass = ctrl->val;
1016 break; 916 break;
1017 917
1018 default: 918 default:
1019 return -EINVAL; 919 return 0;
1020 } 920 }
1021 921 set_audio_regs(sd, state);
1022 return 0; 922 return 0;
1023} 923}
1024 924
1025static struct v4l2_queryctrl saa717x_qctrl[] = {
1026 {
1027 .id = V4L2_CID_BRIGHTNESS,
1028 .type = V4L2_CTRL_TYPE_INTEGER,
1029 .name = "Brightness",
1030 .minimum = 0,
1031 .maximum = 255,
1032 .step = 1,
1033 .default_value = 128,
1034 .flags = 0,
1035 }, {
1036 .id = V4L2_CID_CONTRAST,
1037 .type = V4L2_CTRL_TYPE_INTEGER,
1038 .name = "Contrast",
1039 .minimum = 0,
1040 .maximum = 255,
1041 .step = 1,
1042 .default_value = 64,
1043 .flags = 0,
1044 }, {
1045 .id = V4L2_CID_SATURATION,
1046 .type = V4L2_CTRL_TYPE_INTEGER,
1047 .name = "Saturation",
1048 .minimum = 0,
1049 .maximum = 255,
1050 .step = 1,
1051 .default_value = 64,
1052 .flags = 0,
1053 }, {
1054 .id = V4L2_CID_HUE,
1055 .type = V4L2_CTRL_TYPE_INTEGER,
1056 .name = "Hue",
1057 .minimum = -128,
1058 .maximum = 127,
1059 .step = 1,
1060 .default_value = 0,
1061 .flags = 0,
1062 }, {
1063 .id = V4L2_CID_AUDIO_VOLUME,
1064 .type = V4L2_CTRL_TYPE_INTEGER,
1065 .name = "Volume",
1066 .minimum = 0,
1067 .maximum = 65535,
1068 .step = 65535 / 100,
1069 .default_value = 58880,
1070 .flags = 0,
1071 }, {
1072 .id = V4L2_CID_AUDIO_BALANCE,
1073 .type = V4L2_CTRL_TYPE_INTEGER,
1074 .name = "Balance",
1075 .minimum = 0,
1076 .maximum = 65535,
1077 .step = 65535 / 100,
1078 .default_value = 32768,
1079 .flags = 0,
1080 }, {
1081 .id = V4L2_CID_AUDIO_MUTE,
1082 .type = V4L2_CTRL_TYPE_BOOLEAN,
1083 .name = "Mute",
1084 .minimum = 0,
1085 .maximum = 1,
1086 .step = 1,
1087 .default_value = 1,
1088 .flags = 0,
1089 }, {
1090 .id = V4L2_CID_AUDIO_BASS,
1091 .type = V4L2_CTRL_TYPE_INTEGER,
1092 .name = "Bass",
1093 .minimum = 0,
1094 .maximum = 65535,
1095 .step = 65535 / 100,
1096 .default_value = 32768,
1097 }, {
1098 .id = V4L2_CID_AUDIO_TREBLE,
1099 .type = V4L2_CTRL_TYPE_INTEGER,
1100 .name = "Treble",
1101 .minimum = 0,
1102 .maximum = 65535,
1103 .step = 65535 / 100,
1104 .default_value = 32768,
1105 },
1106};
1107
1108static int saa717x_s_video_routing(struct v4l2_subdev *sd, 925static int saa717x_s_video_routing(struct v4l2_subdev *sd,
1109 u32 input, u32 output, u32 config) 926 u32 input, u32 output, u32 config)
1110{ 927{
@@ -1158,18 +975,6 @@ static int saa717x_s_video_routing(struct v4l2_subdev *sd,
1158 return 0; 975 return 0;
1159} 976}
1160 977
1161static int saa717x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
1162{
1163 int i;
1164
1165 for (i = 0; i < ARRAY_SIZE(saa717x_qctrl); i++)
1166 if (qc->id && qc->id == saa717x_qctrl[i].id) {
1167 memcpy(qc, &saa717x_qctrl[i], sizeof(*qc));
1168 return 0;
1169 }
1170 return -EINVAL;
1171}
1172
1173#ifdef CONFIG_VIDEO_ADV_DEBUG 978#ifdef CONFIG_VIDEO_ADV_DEBUG
1174static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) 979static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
1175{ 980{
@@ -1386,17 +1191,34 @@ static int saa717x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1386 return 0; 1191 return 0;
1387} 1192}
1388 1193
1194static int saa717x_log_status(struct v4l2_subdev *sd)
1195{
1196 struct saa717x_state *state = to_state(sd);
1197
1198 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
1199 return 0;
1200}
1201
1389/* ----------------------------------------------------------------------- */ 1202/* ----------------------------------------------------------------------- */
1390 1203
1204static const struct v4l2_ctrl_ops saa717x_ctrl_ops = {
1205 .s_ctrl = saa717x_s_ctrl,
1206};
1207
1391static const struct v4l2_subdev_core_ops saa717x_core_ops = { 1208static const struct v4l2_subdev_core_ops saa717x_core_ops = {
1392#ifdef CONFIG_VIDEO_ADV_DEBUG 1209#ifdef CONFIG_VIDEO_ADV_DEBUG
1393 .g_register = saa717x_g_register, 1210 .g_register = saa717x_g_register,
1394 .s_register = saa717x_s_register, 1211 .s_register = saa717x_s_register,
1395#endif 1212#endif
1396 .queryctrl = saa717x_queryctrl,
1397 .g_ctrl = saa717x_g_ctrl,
1398 .s_ctrl = saa717x_s_ctrl,
1399 .s_std = saa717x_s_std, 1213 .s_std = saa717x_s_std,
1214 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
1215 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
1216 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
1217 .g_ctrl = v4l2_subdev_g_ctrl,
1218 .s_ctrl = v4l2_subdev_s_ctrl,
1219 .queryctrl = v4l2_subdev_queryctrl,
1220 .querymenu = v4l2_subdev_querymenu,
1221 .log_status = saa717x_log_status,
1400}; 1222};
1401 1223
1402static const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = { 1224static const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = {
@@ -1432,6 +1254,7 @@ static int saa717x_probe(struct i2c_client *client,
1432 const struct i2c_device_id *did) 1254 const struct i2c_device_id *did)
1433{ 1255{
1434 struct saa717x_state *decoder; 1256 struct saa717x_state *decoder;
1257 struct v4l2_ctrl_handler *hdl;
1435 struct v4l2_subdev *sd; 1258 struct v4l2_subdev *sd;
1436 u8 id = 0; 1259 u8 id = 0;
1437 char *p = ""; 1260 char *p = "";
@@ -1467,16 +1290,41 @@ static int saa717x_probe(struct i2c_client *client,
1467 p = "saa7171"; 1290 p = "saa7171";
1468 v4l2_info(sd, "%s found @ 0x%x (%s)\n", p, 1291 v4l2_info(sd, "%s found @ 0x%x (%s)\n", p,
1469 client->addr << 1, client->adapter->name); 1292 client->addr << 1, client->adapter->name);
1293
1294 hdl = &decoder->hdl;
1295 v4l2_ctrl_handler_init(hdl, 9);
1296 /* add in ascending ID order */
1297 v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1298 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1299 v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1300 V4L2_CID_CONTRAST, 0, 255, 1, 68);
1301 v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1302 V4L2_CID_SATURATION, 0, 255, 1, 64);
1303 v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1304 V4L2_CID_HUE, -128, 127, 1, 0);
1305 v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1306 V4L2_CID_AUDIO_VOLUME, 0, 65535, 65535 / 100, 42000);
1307 v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1308 V4L2_CID_AUDIO_BALANCE, 0, 65535, 65535 / 100, 32768);
1309 v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1310 V4L2_CID_AUDIO_BASS, -16, 15, 1, 0);
1311 v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1312 V4L2_CID_AUDIO_TREBLE, -16, 15, 1, 0);
1313 v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1314 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
1315 sd->ctrl_handler = hdl;
1316 if (hdl->error) {
1317 int err = hdl->error;
1318
1319 v4l2_ctrl_handler_free(hdl);
1320 kfree(decoder);
1321 return err;
1322 }
1323
1470 decoder->std = V4L2_STD_NTSC; 1324 decoder->std = V4L2_STD_NTSC;
1471 decoder->input = -1; 1325 decoder->input = -1;
1472 decoder->enable = 1; 1326 decoder->enable = 1;
1473 1327
1474 /* tune these parameters */
1475 decoder->bright = 0x80;
1476 decoder->contrast = 0x44;
1477 decoder->sat = 0x40;
1478 decoder->hue = 0x00;
1479
1480 /* FIXME!! */ 1328 /* FIXME!! */
1481 decoder->playback = 0; /* initially capture mode used */ 1329 decoder->playback = 0; /* initially capture mode used */
1482 decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */ 1330 decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */
@@ -1487,23 +1335,13 @@ static int saa717x_probe(struct i2c_client *client,
1487 /* set volume, bass and treble */ 1335 /* set volume, bass and treble */
1488 decoder->audio_main_vol_l = 6; 1336 decoder->audio_main_vol_l = 6;
1489 decoder->audio_main_vol_r = 6; 1337 decoder->audio_main_vol_r = 6;
1490 decoder->audio_main_bass = 0;
1491 decoder->audio_main_treble = 0;
1492 decoder->audio_main_mute = 0;
1493 decoder->audio_main_balance = 32768;
1494 /* normalize (24 to -40 (not -84) -> 65535 to 0) */
1495 decoder->audio_main_volume =
1496 (decoder->audio_main_vol_r + 41) * 65535 / (24 - (-40));
1497 1338
1498 v4l2_dbg(1, debug, sd, "writing init values\n"); 1339 v4l2_dbg(1, debug, sd, "writing init values\n");
1499 1340
1500 /* FIXME!! */ 1341 /* FIXME!! */
1501 saa717x_write_regs(sd, reg_init_initialize); 1342 saa717x_write_regs(sd, reg_init_initialize);
1502 set_video_output_level_regs(sd, decoder); 1343
1503 /* set bass,treble to 0db 20041101 K.Ohta */ 1344 v4l2_ctrl_handler_setup(hdl);
1504 decoder->audio_main_bass = 0;
1505 decoder->audio_main_treble = 0;
1506 set_audio_regs(sd, decoder);
1507 1345
1508 set_current_state(TASK_INTERRUPTIBLE); 1346 set_current_state(TASK_INTERRUPTIBLE);
1509 schedule_timeout(2*HZ); 1347 schedule_timeout(2*HZ);
@@ -1515,6 +1353,7 @@ static int saa717x_remove(struct i2c_client *client)
1515 struct v4l2_subdev *sd = i2c_get_clientdata(client); 1353 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1516 1354
1517 v4l2_device_unregister_subdev(sd); 1355 v4l2_device_unregister_subdev(sd);
1356 v4l2_ctrl_handler_free(sd->ctrl_handler);
1518 kfree(to_state(sd)); 1357 kfree(to_state(sd));
1519 return 0; 1358 return 0;
1520} 1359}
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index f2032939fd4..a499cacec1f 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -779,9 +779,12 @@ static int soc_camera_s_crop(struct file *file, void *fh,
779 ret = ici->ops->get_crop(icd, &current_crop); 779 ret = ici->ops->get_crop(icd, &current_crop);
780 780
781 /* Prohibit window size change with initialised buffers */ 781 /* Prohibit window size change with initialised buffers */
782 if (icf->vb_vidq.bufs[0] && !ret && 782 if (ret < 0) {
783 (a->c.width != current_crop.c.width || 783 dev_err(&icd->dev,
784 a->c.height != current_crop.c.height)) { 784 "S_CROP denied: getting current crop failed\n");
785 } else if (icf->vb_vidq.bufs[0] &&
786 (a->c.width != current_crop.c.width ||
787 a->c.height != current_crop.c.height)) {
785 dev_err(&icd->dev, 788 dev_err(&icd->dev,
786 "S_CROP denied: queue initialised and sizes differ\n"); 789 "S_CROP denied: queue initialised and sizes differ\n");
787 ret = -EBUSY; 790 ret = -EBUSY;
diff --git a/drivers/media/video/tvp7002.c b/drivers/media/video/tvp7002.c
index 8085ac39244..48f5c76ab52 100644
--- a/drivers/media/video/tvp7002.c
+++ b/drivers/media/video/tvp7002.c
@@ -179,7 +179,7 @@ static const struct i2c_reg_value tvp7002_init_default[] = {
179/* Register parameters for 480P */ 179/* Register parameters for 480P */
180static const struct i2c_reg_value tvp7002_parms_480P[] = { 180static const struct i2c_reg_value tvp7002_parms_480P[] = {
181 { TVP7002_HPLL_FDBK_DIV_MSBS, 0x35, TVP7002_WRITE }, 181 { TVP7002_HPLL_FDBK_DIV_MSBS, 0x35, TVP7002_WRITE },
182 { TVP7002_HPLL_FDBK_DIV_LSBS, 0x0a, TVP7002_WRITE }, 182 { TVP7002_HPLL_FDBK_DIV_LSBS, 0xa0, TVP7002_WRITE },
183 { TVP7002_HPLL_CRTL, 0x02, TVP7002_WRITE }, 183 { TVP7002_HPLL_CRTL, 0x02, TVP7002_WRITE },
184 { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE }, 184 { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE },
185 { TVP7002_AVID_START_PIXEL_LSBS, 0x91, TVP7002_WRITE }, 185 { TVP7002_AVID_START_PIXEL_LSBS, 0x91, TVP7002_WRITE },
@@ -223,7 +223,7 @@ static const struct i2c_reg_value tvp7002_parms_576P[] = {
223/* Register parameters for 1080I60 */ 223/* Register parameters for 1080I60 */
224static const struct i2c_reg_value tvp7002_parms_1080I60[] = { 224static const struct i2c_reg_value tvp7002_parms_1080I60[] = {
225 { TVP7002_HPLL_FDBK_DIV_MSBS, 0x89, TVP7002_WRITE }, 225 { TVP7002_HPLL_FDBK_DIV_MSBS, 0x89, TVP7002_WRITE },
226 { TVP7002_HPLL_FDBK_DIV_LSBS, 0x08, TVP7002_WRITE }, 226 { TVP7002_HPLL_FDBK_DIV_LSBS, 0x80, TVP7002_WRITE },
227 { TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE }, 227 { TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE },
228 { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE }, 228 { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE },
229 { TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE }, 229 { TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE },
@@ -245,7 +245,7 @@ static const struct i2c_reg_value tvp7002_parms_1080I60[] = {
245/* Register parameters for 1080P60 */ 245/* Register parameters for 1080P60 */
246static const struct i2c_reg_value tvp7002_parms_1080P60[] = { 246static const struct i2c_reg_value tvp7002_parms_1080P60[] = {
247 { TVP7002_HPLL_FDBK_DIV_MSBS, 0x89, TVP7002_WRITE }, 247 { TVP7002_HPLL_FDBK_DIV_MSBS, 0x89, TVP7002_WRITE },
248 { TVP7002_HPLL_FDBK_DIV_LSBS, 0x08, TVP7002_WRITE }, 248 { TVP7002_HPLL_FDBK_DIV_LSBS, 0x80, TVP7002_WRITE },
249 { TVP7002_HPLL_CRTL, 0xE0, TVP7002_WRITE }, 249 { TVP7002_HPLL_CRTL, 0xE0, TVP7002_WRITE },
250 { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE }, 250 { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE },
251 { TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE }, 251 { TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE },
@@ -289,7 +289,7 @@ static const struct i2c_reg_value tvp7002_parms_1080I50[] = {
289/* Register parameters for 720P60 */ 289/* Register parameters for 720P60 */
290static const struct i2c_reg_value tvp7002_parms_720P60[] = { 290static const struct i2c_reg_value tvp7002_parms_720P60[] = {
291 { TVP7002_HPLL_FDBK_DIV_MSBS, 0x67, TVP7002_WRITE }, 291 { TVP7002_HPLL_FDBK_DIV_MSBS, 0x67, TVP7002_WRITE },
292 { TVP7002_HPLL_FDBK_DIV_LSBS, 0x02, TVP7002_WRITE }, 292 { TVP7002_HPLL_FDBK_DIV_LSBS, 0x20, TVP7002_WRITE },
293 { TVP7002_HPLL_CRTL, 0xa0, TVP7002_WRITE }, 293 { TVP7002_HPLL_CRTL, 0xa0, TVP7002_WRITE },
294 { TVP7002_HPLL_PHASE_SEL, 0x16, TVP7002_WRITE }, 294 { TVP7002_HPLL_PHASE_SEL, 0x16, TVP7002_WRITE },
295 { TVP7002_AVID_START_PIXEL_LSBS, 0x47, TVP7002_WRITE }, 295 { TVP7002_AVID_START_PIXEL_LSBS, 0x47, TVP7002_WRITE },
@@ -311,7 +311,7 @@ static const struct i2c_reg_value tvp7002_parms_720P60[] = {
311/* Register parameters for 720P50 */ 311/* Register parameters for 720P50 */
312static const struct i2c_reg_value tvp7002_parms_720P50[] = { 312static const struct i2c_reg_value tvp7002_parms_720P50[] = {
313 { TVP7002_HPLL_FDBK_DIV_MSBS, 0x7b, TVP7002_WRITE }, 313 { TVP7002_HPLL_FDBK_DIV_MSBS, 0x7b, TVP7002_WRITE },
314 { TVP7002_HPLL_FDBK_DIV_LSBS, 0x0c, TVP7002_WRITE }, 314 { TVP7002_HPLL_FDBK_DIV_LSBS, 0xc0, TVP7002_WRITE },
315 { TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE }, 315 { TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE },
316 { TVP7002_HPLL_PHASE_SEL, 0x16, TVP7002_WRITE }, 316 { TVP7002_HPLL_PHASE_SEL, 0x16, TVP7002_WRITE },
317 { TVP7002_AVID_START_PIXEL_LSBS, 0x47, TVP7002_WRITE }, 317 { TVP7002_AVID_START_PIXEL_LSBS, 0x47, TVP7002_WRITE },
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c
index 5ac37c6c431..f1fcf974496 100644
--- a/drivers/media/video/usbvideo/usbvideo.c
+++ b/drivers/media/video/usbvideo/usbvideo.c
@@ -282,19 +282,15 @@ static void usbvideo_OverlayChar(struct uvd *uvd, struct usbvideo_frame *frame,
282 }; 282 };
283 unsigned short digit; 283 unsigned short digit;
284 int ix, iy; 284 int ix, iy;
285 int value;
285 286
286 if ((uvd == NULL) || (frame == NULL)) 287 if ((uvd == NULL) || (frame == NULL))
287 return; 288 return;
288 289
289 if (ch >= '0' && ch <= '9') 290 value = hex_to_bin(ch);
290 ch -= '0'; 291 if (value < 0)
291 else if (ch >= 'A' && ch <= 'F')
292 ch = 10 + (ch - 'A');
293 else if (ch >= 'a' && ch <= 'f')
294 ch = 10 + (ch - 'a');
295 else
296 return; 292 return;
297 digit = digits[ch]; 293 digit = digits[value];
298 294
299 for (iy=0; iy < 5; iy++) { 295 for (iy=0; iy < 5; iy++) {
300 for (ix=0; ix < 3; ix++) { 296 for (ix=0; ix < 3; ix++) {
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index 7eaf99b22a4..8bdd940f32e 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -2145,6 +2145,15 @@ static struct usb_device_id uvc_ids[] = {
2145 .bInterfaceSubClass = 1, 2145 .bInterfaceSubClass = 1,
2146 .bInterfaceProtocol = 0, 2146 .bInterfaceProtocol = 0,
2147 .driver_info = UVC_QUIRK_STREAM_NO_FID }, 2147 .driver_info = UVC_QUIRK_STREAM_NO_FID },
2148 /* Miricle 307K */
2149 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
2150 | USB_DEVICE_ID_MATCH_INT_INFO,
2151 .idVendor = 0x17dc,
2152 .idProduct = 0x0202,
2153 .bInterfaceClass = USB_CLASS_VIDEO,
2154 .bInterfaceSubClass = 1,
2155 .bInterfaceProtocol = 0,
2156 .driver_info = UVC_QUIRK_STREAM_NO_FID },
2148 /* Lenovo Thinkpad SL400/SL500 */ 2157 /* Lenovo Thinkpad SL400/SL500 */
2149 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE 2158 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
2150 | USB_DEVICE_ID_MATCH_INT_INFO, 2159 | USB_DEVICE_ID_MATCH_INT_INFO,
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
index 133c78d113a..e9928a41508 100644
--- a/drivers/media/video/uvc/uvc_queue.c
+++ b/drivers/media/video/uvc/uvc_queue.c
@@ -78,12 +78,14 @@
78 * 78 *
79 */ 79 */
80 80
81void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) 81void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
82 int drop_corrupted)
82{ 83{
83 mutex_init(&queue->mutex); 84 mutex_init(&queue->mutex);
84 spin_lock_init(&queue->irqlock); 85 spin_lock_init(&queue->irqlock);
85 INIT_LIST_HEAD(&queue->mainqueue); 86 INIT_LIST_HEAD(&queue->mainqueue);
86 INIT_LIST_HEAD(&queue->irqqueue); 87 INIT_LIST_HEAD(&queue->irqqueue);
88 queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0;
87 queue->type = type; 89 queue->type = type;
88} 90}
89 91
@@ -435,8 +437,10 @@ int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
435 uvc_queue_cancel(queue, 0); 437 uvc_queue_cancel(queue, 0);
436 INIT_LIST_HEAD(&queue->mainqueue); 438 INIT_LIST_HEAD(&queue->mainqueue);
437 439
438 for (i = 0; i < queue->count; ++i) 440 for (i = 0; i < queue->count; ++i) {
441 queue->buffer[i].error = 0;
439 queue->buffer[i].state = UVC_BUF_STATE_IDLE; 442 queue->buffer[i].state = UVC_BUF_STATE_IDLE;
443 }
440 444
441 queue->flags &= ~UVC_QUEUE_STREAMING; 445 queue->flags &= ~UVC_QUEUE_STREAMING;
442 } 446 }
@@ -488,8 +492,8 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
488 struct uvc_buffer *nextbuf; 492 struct uvc_buffer *nextbuf;
489 unsigned long flags; 493 unsigned long flags;
490 494
491 if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) && 495 if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) {
492 buf->buf.length != buf->buf.bytesused) { 496 buf->error = 0;
493 buf->state = UVC_BUF_STATE_QUEUED; 497 buf->state = UVC_BUF_STATE_QUEUED;
494 buf->buf.bytesused = 0; 498 buf->buf.bytesused = 0;
495 return buf; 499 return buf;
@@ -497,6 +501,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
497 501
498 spin_lock_irqsave(&queue->irqlock, flags); 502 spin_lock_irqsave(&queue->irqlock, flags);
499 list_del(&buf->queue); 503 list_del(&buf->queue);
504 buf->error = 0;
500 buf->state = UVC_BUF_STATE_DONE; 505 buf->state = UVC_BUF_STATE_DONE;
501 if (!list_empty(&queue->irqqueue)) 506 if (!list_empty(&queue->irqqueue))
502 nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, 507 nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 53f3ef4635e..e27cf0d3b6d 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -555,6 +555,9 @@ static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream,
555 if (urb->iso_frame_desc[i].status < 0) { 555 if (urb->iso_frame_desc[i].status < 0) {
556 uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame " 556 uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame "
557 "lost (%d).\n", urb->iso_frame_desc[i].status); 557 "lost (%d).\n", urb->iso_frame_desc[i].status);
558 /* Mark the buffer as faulty. */
559 if (buf != NULL)
560 buf->error = 1;
558 continue; 561 continue;
559 } 562 }
560 563
@@ -579,8 +582,14 @@ static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream,
579 uvc_video_decode_end(stream, buf, mem, 582 uvc_video_decode_end(stream, buf, mem,
580 urb->iso_frame_desc[i].actual_length); 583 urb->iso_frame_desc[i].actual_length);
581 584
582 if (buf->state == UVC_BUF_STATE_READY) 585 if (buf->state == UVC_BUF_STATE_READY) {
586 if (buf->buf.length != buf->buf.bytesused &&
587 !(stream->cur_format->flags &
588 UVC_FMT_FLAG_COMPRESSED))
589 buf->error = 1;
590
583 buf = uvc_queue_next_buffer(&stream->queue, buf); 591 buf = uvc_queue_next_buffer(&stream->queue, buf);
592 }
584 } 593 }
585} 594}
586 595
@@ -1104,7 +1113,7 @@ int uvc_video_init(struct uvc_streaming *stream)
1104 atomic_set(&stream->active, 0); 1113 atomic_set(&stream->active, 0);
1105 1114
1106 /* Initialize the video buffers queue. */ 1115 /* Initialize the video buffers queue. */
1107 uvc_queue_init(&stream->queue, stream->type); 1116 uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param);
1108 1117
1109 /* Alternate setting 0 should be the default, yet the XBox Live Vision 1118 /* Alternate setting 0 should be the default, yet the XBox Live Vision
1110 * Cam (and possibly other devices) crash or otherwise misbehave if 1119 * Cam (and possibly other devices) crash or otherwise misbehave if
@@ -1197,12 +1206,6 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable)
1197 return 0; 1206 return 0;
1198 } 1207 }
1199 1208
1200 if ((stream->cur_format->flags & UVC_FMT_FLAG_COMPRESSED) ||
1201 uvc_no_drop_param)
1202 stream->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE;
1203 else
1204 stream->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE;
1205
1206 ret = uvc_queue_enable(&stream->queue, 1); 1209 ret = uvc_queue_enable(&stream->queue, 1);
1207 if (ret < 0) 1210 if (ret < 0)
1208 return ret; 1211 return ret;
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index ac272456fbf..bdacf3beabf 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -379,11 +379,12 @@ struct uvc_buffer {
379 struct list_head queue; 379 struct list_head queue;
380 wait_queue_head_t wait; 380 wait_queue_head_t wait;
381 enum uvc_buffer_state state; 381 enum uvc_buffer_state state;
382 unsigned int error;
382}; 383};
383 384
384#define UVC_QUEUE_STREAMING (1 << 0) 385#define UVC_QUEUE_STREAMING (1 << 0)
385#define UVC_QUEUE_DISCONNECTED (1 << 1) 386#define UVC_QUEUE_DISCONNECTED (1 << 1)
386#define UVC_QUEUE_DROP_INCOMPLETE (1 << 2) 387#define UVC_QUEUE_DROP_CORRUPTED (1 << 2)
387 388
388struct uvc_video_queue { 389struct uvc_video_queue {
389 enum v4l2_buf_type type; 390 enum v4l2_buf_type type;
@@ -562,7 +563,7 @@ extern struct uvc_driver uvc_driver;
562 563
563/* Video buffers queue management. */ 564/* Video buffers queue management. */
564extern void uvc_queue_init(struct uvc_video_queue *queue, 565extern void uvc_queue_init(struct uvc_video_queue *queue,
565 enum v4l2_buf_type type); 566 enum v4l2_buf_type type, int drop_corrupted);
566extern int uvc_alloc_buffers(struct uvc_video_queue *queue, 567extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
567 unsigned int nbuffers, unsigned int buflength); 568 unsigned int nbuffers, unsigned int buflength);
568extern int uvc_free_buffers(struct uvc_video_queue *queue); 569extern int uvc_free_buffers(struct uvc_video_queue *queue);
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 4e53b0b3339..3ce7c64e578 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -62,6 +62,7 @@
62#define __OLD_VIDIOC_ /* To allow fixing old calls*/ 62#define __OLD_VIDIOC_ /* To allow fixing old calls*/
63#include <media/v4l2-common.h> 63#include <media/v4l2-common.h>
64#include <media/v4l2-device.h> 64#include <media/v4l2-device.h>
65#include <media/v4l2-ctrls.h>
65#include <media/v4l2-chip-ident.h> 66#include <media/v4l2-chip-ident.h>
66 67
67#include <linux/videodev2.h> 68#include <linux/videodev2.h>
@@ -172,487 +173,17 @@ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
172} 173}
173EXPORT_SYMBOL(v4l2_ctrl_check); 174EXPORT_SYMBOL(v4l2_ctrl_check);
174 175
175/* Returns NULL or a character pointer array containing the menu for
176 the given control ID. The pointer array ends with a NULL pointer.
177 An empty string signifies a menu entry that is invalid. This allows
178 drivers to disable certain options if it is not supported. */
179const char **v4l2_ctrl_get_menu(u32 id)
180{
181 static const char *mpeg_audio_sampling_freq[] = {
182 "44.1 kHz",
183 "48 kHz",
184 "32 kHz",
185 NULL
186 };
187 static const char *mpeg_audio_encoding[] = {
188 "MPEG-1/2 Layer I",
189 "MPEG-1/2 Layer II",
190 "MPEG-1/2 Layer III",
191 "MPEG-2/4 AAC",
192 "AC-3",
193 NULL
194 };
195 static const char *mpeg_audio_l1_bitrate[] = {
196 "32 kbps",
197 "64 kbps",
198 "96 kbps",
199 "128 kbps",
200 "160 kbps",
201 "192 kbps",
202 "224 kbps",
203 "256 kbps",
204 "288 kbps",
205 "320 kbps",
206 "352 kbps",
207 "384 kbps",
208 "416 kbps",
209 "448 kbps",
210 NULL
211 };
212 static const char *mpeg_audio_l2_bitrate[] = {
213 "32 kbps",
214 "48 kbps",
215 "56 kbps",
216 "64 kbps",
217 "80 kbps",
218 "96 kbps",
219 "112 kbps",
220 "128 kbps",
221 "160 kbps",
222 "192 kbps",
223 "224 kbps",
224 "256 kbps",
225 "320 kbps",
226 "384 kbps",
227 NULL
228 };
229 static const char *mpeg_audio_l3_bitrate[] = {
230 "32 kbps",
231 "40 kbps",
232 "48 kbps",
233 "56 kbps",
234 "64 kbps",
235 "80 kbps",
236 "96 kbps",
237 "112 kbps",
238 "128 kbps",
239 "160 kbps",
240 "192 kbps",
241 "224 kbps",
242 "256 kbps",
243 "320 kbps",
244 NULL
245 };
246 static const char *mpeg_audio_ac3_bitrate[] = {
247 "32 kbps",
248 "40 kbps",
249 "48 kbps",
250 "56 kbps",
251 "64 kbps",
252 "80 kbps",
253 "96 kbps",
254 "112 kbps",
255 "128 kbps",
256 "160 kbps",
257 "192 kbps",
258 "224 kbps",
259 "256 kbps",
260 "320 kbps",
261 "384 kbps",
262 "448 kbps",
263 "512 kbps",
264 "576 kbps",
265 "640 kbps",
266 NULL
267 };
268 static const char *mpeg_audio_mode[] = {
269 "Stereo",
270 "Joint Stereo",
271 "Dual",
272 "Mono",
273 NULL
274 };
275 static const char *mpeg_audio_mode_extension[] = {
276 "Bound 4",
277 "Bound 8",
278 "Bound 12",
279 "Bound 16",
280 NULL
281 };
282 static const char *mpeg_audio_emphasis[] = {
283 "No Emphasis",
284 "50/15 us",
285 "CCITT J17",
286 NULL
287 };
288 static const char *mpeg_audio_crc[] = {
289 "No CRC",
290 "16-bit CRC",
291 NULL
292 };
293 static const char *mpeg_video_encoding[] = {
294 "MPEG-1",
295 "MPEG-2",
296 "MPEG-4 AVC",
297 NULL
298 };
299 static const char *mpeg_video_aspect[] = {
300 "1x1",
301 "4x3",
302 "16x9",
303 "2.21x1",
304 NULL
305 };
306 static const char *mpeg_video_bitrate_mode[] = {
307 "Variable Bitrate",
308 "Constant Bitrate",
309 NULL
310 };
311 static const char *mpeg_stream_type[] = {
312 "MPEG-2 Program Stream",
313 "MPEG-2 Transport Stream",
314 "MPEG-1 System Stream",
315 "MPEG-2 DVD-compatible Stream",
316 "MPEG-1 VCD-compatible Stream",
317 "MPEG-2 SVCD-compatible Stream",
318 NULL
319 };
320 static const char *mpeg_stream_vbi_fmt[] = {
321 "No VBI",
322 "Private packet, IVTV format",
323 NULL
324 };
325 static const char *camera_power_line_frequency[] = {
326 "Disabled",
327 "50 Hz",
328 "60 Hz",
329 NULL
330 };
331 static const char *camera_exposure_auto[] = {
332 "Auto Mode",
333 "Manual Mode",
334 "Shutter Priority Mode",
335 "Aperture Priority Mode",
336 NULL
337 };
338 static const char *colorfx[] = {
339 "None",
340 "Black & White",
341 "Sepia",
342 "Negative",
343 "Emboss",
344 "Sketch",
345 "Sky blue",
346 "Grass green",
347 "Skin whiten",
348 "Vivid",
349 NULL
350 };
351 static const char *tune_preemphasis[] = {
352 "No preemphasis",
353 "50 useconds",
354 "75 useconds",
355 NULL,
356 };
357
358 switch (id) {
359 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
360 return mpeg_audio_sampling_freq;
361 case V4L2_CID_MPEG_AUDIO_ENCODING:
362 return mpeg_audio_encoding;
363 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
364 return mpeg_audio_l1_bitrate;
365 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
366 return mpeg_audio_l2_bitrate;
367 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
368 return mpeg_audio_l3_bitrate;
369 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
370 return mpeg_audio_ac3_bitrate;
371 case V4L2_CID_MPEG_AUDIO_MODE:
372 return mpeg_audio_mode;
373 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
374 return mpeg_audio_mode_extension;
375 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
376 return mpeg_audio_emphasis;
377 case V4L2_CID_MPEG_AUDIO_CRC:
378 return mpeg_audio_crc;
379 case V4L2_CID_MPEG_VIDEO_ENCODING:
380 return mpeg_video_encoding;
381 case V4L2_CID_MPEG_VIDEO_ASPECT:
382 return mpeg_video_aspect;
383 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
384 return mpeg_video_bitrate_mode;
385 case V4L2_CID_MPEG_STREAM_TYPE:
386 return mpeg_stream_type;
387 case V4L2_CID_MPEG_STREAM_VBI_FMT:
388 return mpeg_stream_vbi_fmt;
389 case V4L2_CID_POWER_LINE_FREQUENCY:
390 return camera_power_line_frequency;
391 case V4L2_CID_EXPOSURE_AUTO:
392 return camera_exposure_auto;
393 case V4L2_CID_COLORFX:
394 return colorfx;
395 case V4L2_CID_TUNE_PREEMPHASIS:
396 return tune_preemphasis;
397 default:
398 return NULL;
399 }
400}
401EXPORT_SYMBOL(v4l2_ctrl_get_menu);
402
403/* Return the control name. */
404const char *v4l2_ctrl_get_name(u32 id)
405{
406 switch (id) {
407 /* USER controls */
408 case V4L2_CID_USER_CLASS: return "User Controls";
409 case V4L2_CID_BRIGHTNESS: return "Brightness";
410 case V4L2_CID_CONTRAST: return "Contrast";
411 case V4L2_CID_SATURATION: return "Saturation";
412 case V4L2_CID_HUE: return "Hue";
413 case V4L2_CID_AUDIO_VOLUME: return "Volume";
414 case V4L2_CID_AUDIO_BALANCE: return "Balance";
415 case V4L2_CID_AUDIO_BASS: return "Bass";
416 case V4L2_CID_AUDIO_TREBLE: return "Treble";
417 case V4L2_CID_AUDIO_MUTE: return "Mute";
418 case V4L2_CID_AUDIO_LOUDNESS: return "Loudness";
419 case V4L2_CID_BLACK_LEVEL: return "Black Level";
420 case V4L2_CID_AUTO_WHITE_BALANCE: return "White Balance, Automatic";
421 case V4L2_CID_DO_WHITE_BALANCE: return "Do White Balance";
422 case V4L2_CID_RED_BALANCE: return "Red Balance";
423 case V4L2_CID_BLUE_BALANCE: return "Blue Balance";
424 case V4L2_CID_GAMMA: return "Gamma";
425 case V4L2_CID_EXPOSURE: return "Exposure";
426 case V4L2_CID_AUTOGAIN: return "Gain, Automatic";
427 case V4L2_CID_GAIN: return "Gain";
428 case V4L2_CID_HFLIP: return "Horizontal Flip";
429 case V4L2_CID_VFLIP: return "Vertical Flip";
430 case V4L2_CID_HCENTER: return "Horizontal Center";
431 case V4L2_CID_VCENTER: return "Vertical Center";
432 case V4L2_CID_POWER_LINE_FREQUENCY: return "Power Line Frequency";
433 case V4L2_CID_HUE_AUTO: return "Hue, Automatic";
434 case V4L2_CID_WHITE_BALANCE_TEMPERATURE: return "White Balance Temperature";
435 case V4L2_CID_SHARPNESS: return "Sharpness";
436 case V4L2_CID_BACKLIGHT_COMPENSATION: return "Backlight Compensation";
437 case V4L2_CID_CHROMA_AGC: return "Chroma AGC";
438 case V4L2_CID_CHROMA_GAIN: return "Chroma Gain";
439 case V4L2_CID_COLOR_KILLER: return "Color Killer";
440 case V4L2_CID_COLORFX: return "Color Effects";
441 case V4L2_CID_AUTOBRIGHTNESS: return "Brightness, Automatic";
442 case V4L2_CID_BAND_STOP_FILTER: return "Band-Stop Filter";
443 case V4L2_CID_ROTATE: return "Rotate";
444 case V4L2_CID_BG_COLOR: return "Background Color";
445
446 /* MPEG controls */
447 case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls";
448 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: return "Audio Sampling Frequency";
449 case V4L2_CID_MPEG_AUDIO_ENCODING: return "Audio Encoding";
450 case V4L2_CID_MPEG_AUDIO_L1_BITRATE: return "Audio Layer I Bitrate";
451 case V4L2_CID_MPEG_AUDIO_L2_BITRATE: return "Audio Layer II Bitrate";
452 case V4L2_CID_MPEG_AUDIO_L3_BITRATE: return "Audio Layer III Bitrate";
453 case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: return "Audio AAC Bitrate";
454 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: return "Audio AC-3 Bitrate";
455 case V4L2_CID_MPEG_AUDIO_MODE: return "Audio Stereo Mode";
456 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: return "Audio Stereo Mode Extension";
457 case V4L2_CID_MPEG_AUDIO_EMPHASIS: return "Audio Emphasis";
458 case V4L2_CID_MPEG_AUDIO_CRC: return "Audio CRC";
459 case V4L2_CID_MPEG_AUDIO_MUTE: return "Audio Mute";
460 case V4L2_CID_MPEG_VIDEO_ENCODING: return "Video Encoding";
461 case V4L2_CID_MPEG_VIDEO_ASPECT: return "Video Aspect";
462 case V4L2_CID_MPEG_VIDEO_B_FRAMES: return "Video B Frames";
463 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: return "Video GOP Size";
464 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: return "Video GOP Closure";
465 case V4L2_CID_MPEG_VIDEO_PULLDOWN: return "Video Pulldown";
466 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: return "Video Bitrate Mode";
467 case V4L2_CID_MPEG_VIDEO_BITRATE: return "Video Bitrate";
468 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: return "Video Peak Bitrate";
469 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: return "Video Temporal Decimation";
470 case V4L2_CID_MPEG_VIDEO_MUTE: return "Video Mute";
471 case V4L2_CID_MPEG_VIDEO_MUTE_YUV: return "Video Mute YUV";
472 case V4L2_CID_MPEG_STREAM_TYPE: return "Stream Type";
473 case V4L2_CID_MPEG_STREAM_PID_PMT: return "Stream PMT Program ID";
474 case V4L2_CID_MPEG_STREAM_PID_AUDIO: return "Stream Audio Program ID";
475 case V4L2_CID_MPEG_STREAM_PID_VIDEO: return "Stream Video Program ID";
476 case V4L2_CID_MPEG_STREAM_PID_PCR: return "Stream PCR Program ID";
477 case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: return "Stream PES Audio ID";
478 case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: return "Stream PES Video ID";
479 case V4L2_CID_MPEG_STREAM_VBI_FMT: return "Stream VBI Format";
480
481 /* CAMERA controls */
482 case V4L2_CID_CAMERA_CLASS: return "Camera Controls";
483 case V4L2_CID_EXPOSURE_AUTO: return "Auto Exposure";
484 case V4L2_CID_EXPOSURE_ABSOLUTE: return "Exposure Time, Absolute";
485 case V4L2_CID_EXPOSURE_AUTO_PRIORITY: return "Exposure, Dynamic Framerate";
486 case V4L2_CID_PAN_RELATIVE: return "Pan, Relative";
487 case V4L2_CID_TILT_RELATIVE: return "Tilt, Relative";
488 case V4L2_CID_PAN_RESET: return "Pan, Reset";
489 case V4L2_CID_TILT_RESET: return "Tilt, Reset";
490 case V4L2_CID_PAN_ABSOLUTE: return "Pan, Absolute";
491 case V4L2_CID_TILT_ABSOLUTE: return "Tilt, Absolute";
492 case V4L2_CID_FOCUS_ABSOLUTE: return "Focus, Absolute";
493 case V4L2_CID_FOCUS_RELATIVE: return "Focus, Relative";
494 case V4L2_CID_FOCUS_AUTO: return "Focus, Automatic";
495 case V4L2_CID_IRIS_ABSOLUTE: return "Iris, Absolute";
496 case V4L2_CID_IRIS_RELATIVE: return "Iris, Relative";
497 case V4L2_CID_ZOOM_ABSOLUTE: return "Zoom, Absolute";
498 case V4L2_CID_ZOOM_RELATIVE: return "Zoom, Relative";
499 case V4L2_CID_ZOOM_CONTINUOUS: return "Zoom, Continuous";
500 case V4L2_CID_PRIVACY: return "Privacy";
501
502 /* FM Radio Modulator control */
503 case V4L2_CID_FM_TX_CLASS: return "FM Radio Modulator Controls";
504 case V4L2_CID_RDS_TX_DEVIATION: return "RDS Signal Deviation";
505 case V4L2_CID_RDS_TX_PI: return "RDS Program ID";
506 case V4L2_CID_RDS_TX_PTY: return "RDS Program Type";
507 case V4L2_CID_RDS_TX_PS_NAME: return "RDS PS Name";
508 case V4L2_CID_RDS_TX_RADIO_TEXT: return "RDS Radio Text";
509 case V4L2_CID_AUDIO_LIMITER_ENABLED: return "Audio Limiter Feature Enabled";
510 case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: return "Audio Limiter Release Time";
511 case V4L2_CID_AUDIO_LIMITER_DEVIATION: return "Audio Limiter Deviation";
512 case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Feature Enabled";
513 case V4L2_CID_AUDIO_COMPRESSION_GAIN: return "Audio Compression Gain";
514 case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: return "Audio Compression Threshold";
515 case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: return "Audio Compression Attack Time";
516 case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: return "Audio Compression Release Time";
517 case V4L2_CID_PILOT_TONE_ENABLED: return "Pilot Tone Feature Enabled";
518 case V4L2_CID_PILOT_TONE_DEVIATION: return "Pilot Tone Deviation";
519 case V4L2_CID_PILOT_TONE_FREQUENCY: return "Pilot Tone Frequency";
520 case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-emphasis settings";
521 case V4L2_CID_TUNE_POWER_LEVEL: return "Tune Power Level";
522 case V4L2_CID_TUNE_ANTENNA_CAPACITOR: return "Tune Antenna Capacitor";
523
524 default:
525 return NULL;
526 }
527}
528EXPORT_SYMBOL(v4l2_ctrl_get_name);
529
530/* Fill in a struct v4l2_queryctrl */ 176/* Fill in a struct v4l2_queryctrl */
531int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def) 177int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
532{ 178{
533 const char *name = v4l2_ctrl_get_name(qctrl->id); 179 const char *name;
180
181 v4l2_ctrl_fill(qctrl->id, &name, &qctrl->type,
182 &min, &max, &step, &def, &qctrl->flags);
534 183
535 qctrl->flags = 0;
536 if (name == NULL) 184 if (name == NULL)
537 return -EINVAL; 185 return -EINVAL;
538 186
539 switch (qctrl->id) {
540 case V4L2_CID_AUDIO_MUTE:
541 case V4L2_CID_AUDIO_LOUDNESS:
542 case V4L2_CID_AUTO_WHITE_BALANCE:
543 case V4L2_CID_AUTOGAIN:
544 case V4L2_CID_HFLIP:
545 case V4L2_CID_VFLIP:
546 case V4L2_CID_HUE_AUTO:
547 case V4L2_CID_CHROMA_AGC:
548 case V4L2_CID_COLOR_KILLER:
549 case V4L2_CID_MPEG_AUDIO_MUTE:
550 case V4L2_CID_MPEG_VIDEO_MUTE:
551 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
552 case V4L2_CID_MPEG_VIDEO_PULLDOWN:
553 case V4L2_CID_EXPOSURE_AUTO_PRIORITY:
554 case V4L2_CID_FOCUS_AUTO:
555 case V4L2_CID_PRIVACY:
556 case V4L2_CID_AUDIO_LIMITER_ENABLED:
557 case V4L2_CID_AUDIO_COMPRESSION_ENABLED:
558 case V4L2_CID_PILOT_TONE_ENABLED:
559 qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
560 min = 0;
561 max = step = 1;
562 break;
563 case V4L2_CID_PAN_RESET:
564 case V4L2_CID_TILT_RESET:
565 qctrl->type = V4L2_CTRL_TYPE_BUTTON;
566 qctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
567 min = max = step = def = 0;
568 break;
569 case V4L2_CID_POWER_LINE_FREQUENCY:
570 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
571 case V4L2_CID_MPEG_AUDIO_ENCODING:
572 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
573 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
574 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
575 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
576 case V4L2_CID_MPEG_AUDIO_MODE:
577 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
578 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
579 case V4L2_CID_MPEG_AUDIO_CRC:
580 case V4L2_CID_MPEG_VIDEO_ENCODING:
581 case V4L2_CID_MPEG_VIDEO_ASPECT:
582 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
583 case V4L2_CID_MPEG_STREAM_TYPE:
584 case V4L2_CID_MPEG_STREAM_VBI_FMT:
585 case V4L2_CID_EXPOSURE_AUTO:
586 case V4L2_CID_COLORFX:
587 case V4L2_CID_TUNE_PREEMPHASIS:
588 qctrl->type = V4L2_CTRL_TYPE_MENU;
589 step = 1;
590 break;
591 case V4L2_CID_RDS_TX_PS_NAME:
592 case V4L2_CID_RDS_TX_RADIO_TEXT:
593 qctrl->type = V4L2_CTRL_TYPE_STRING;
594 break;
595 case V4L2_CID_USER_CLASS:
596 case V4L2_CID_CAMERA_CLASS:
597 case V4L2_CID_MPEG_CLASS:
598 case V4L2_CID_FM_TX_CLASS:
599 qctrl->type = V4L2_CTRL_TYPE_CTRL_CLASS;
600 qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
601 min = max = step = def = 0;
602 break;
603 case V4L2_CID_BG_COLOR:
604 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
605 step = 1;
606 min = 0;
607 /* Max is calculated as RGB888 that is 2^24 */
608 max = 0xFFFFFF;
609 break;
610 default:
611 qctrl->type = V4L2_CTRL_TYPE_INTEGER;
612 break;
613 }
614 switch (qctrl->id) {
615 case V4L2_CID_MPEG_AUDIO_ENCODING:
616 case V4L2_CID_MPEG_AUDIO_MODE:
617 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
618 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
619 case V4L2_CID_MPEG_STREAM_TYPE:
620 qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
621 break;
622 case V4L2_CID_AUDIO_VOLUME:
623 case V4L2_CID_AUDIO_BALANCE:
624 case V4L2_CID_AUDIO_BASS:
625 case V4L2_CID_AUDIO_TREBLE:
626 case V4L2_CID_BRIGHTNESS:
627 case V4L2_CID_CONTRAST:
628 case V4L2_CID_SATURATION:
629 case V4L2_CID_HUE:
630 case V4L2_CID_RED_BALANCE:
631 case V4L2_CID_BLUE_BALANCE:
632 case V4L2_CID_GAMMA:
633 case V4L2_CID_SHARPNESS:
634 case V4L2_CID_CHROMA_GAIN:
635 case V4L2_CID_RDS_TX_DEVIATION:
636 case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME:
637 case V4L2_CID_AUDIO_LIMITER_DEVIATION:
638 case V4L2_CID_AUDIO_COMPRESSION_GAIN:
639 case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD:
640 case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME:
641 case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME:
642 case V4L2_CID_PILOT_TONE_DEVIATION:
643 case V4L2_CID_PILOT_TONE_FREQUENCY:
644 case V4L2_CID_TUNE_POWER_LEVEL:
645 case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
646 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
647 break;
648 case V4L2_CID_PAN_RELATIVE:
649 case V4L2_CID_TILT_RELATIVE:
650 case V4L2_CID_FOCUS_RELATIVE:
651 case V4L2_CID_IRIS_RELATIVE:
652 case V4L2_CID_ZOOM_RELATIVE:
653 qctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
654 break;
655 }
656 qctrl->minimum = min; 187 qctrl->minimum = min;
657 qctrl->maximum = max; 188 qctrl->maximum = max;
658 qctrl->step = step; 189 qctrl->step = step;
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
new file mode 100644
index 00000000000..84c1a53a727
--- /dev/null
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -0,0 +1,1851 @@
1/*
2 V4L2 controls framework implementation.
3
4 Copyright (C) 2010 Hans Verkuil <hverkuil@xs4all.nl>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/ctype.h>
22#include <media/v4l2-ioctl.h>
23#include <media/v4l2-device.h>
24#include <media/v4l2-ctrls.h>
25#include <media/v4l2-dev.h>
26
27/* Internal temporary helper struct, one for each v4l2_ext_control */
28struct ctrl_helper {
29 /* The control corresponding to the v4l2_ext_control ID field. */
30 struct v4l2_ctrl *ctrl;
31 /* Used internally to mark whether this control was already
32 processed. */
33 bool handled;
34};
35
36/* Returns NULL or a character pointer array containing the menu for
37 the given control ID. The pointer array ends with a NULL pointer.
38 An empty string signifies a menu entry that is invalid. This allows
39 drivers to disable certain options if it is not supported. */
40const char **v4l2_ctrl_get_menu(u32 id)
41{
42 static const char *mpeg_audio_sampling_freq[] = {
43 "44.1 kHz",
44 "48 kHz",
45 "32 kHz",
46 NULL
47 };
48 static const char *mpeg_audio_encoding[] = {
49 "MPEG-1/2 Layer I",
50 "MPEG-1/2 Layer II",
51 "MPEG-1/2 Layer III",
52 "MPEG-2/4 AAC",
53 "AC-3",
54 NULL
55 };
56 static const char *mpeg_audio_l1_bitrate[] = {
57 "32 kbps",
58 "64 kbps",
59 "96 kbps",
60 "128 kbps",
61 "160 kbps",
62 "192 kbps",
63 "224 kbps",
64 "256 kbps",
65 "288 kbps",
66 "320 kbps",
67 "352 kbps",
68 "384 kbps",
69 "416 kbps",
70 "448 kbps",
71 NULL
72 };
73 static const char *mpeg_audio_l2_bitrate[] = {
74 "32 kbps",
75 "48 kbps",
76 "56 kbps",
77 "64 kbps",
78 "80 kbps",
79 "96 kbps",
80 "112 kbps",
81 "128 kbps",
82 "160 kbps",
83 "192 kbps",
84 "224 kbps",
85 "256 kbps",
86 "320 kbps",
87 "384 kbps",
88 NULL
89 };
90 static const char *mpeg_audio_l3_bitrate[] = {
91 "32 kbps",
92 "40 kbps",
93 "48 kbps",
94 "56 kbps",
95 "64 kbps",
96 "80 kbps",
97 "96 kbps",
98 "112 kbps",
99 "128 kbps",
100 "160 kbps",
101 "192 kbps",
102 "224 kbps",
103 "256 kbps",
104 "320 kbps",
105 NULL
106 };
107 static const char *mpeg_audio_ac3_bitrate[] = {
108 "32 kbps",
109 "40 kbps",
110 "48 kbps",
111 "56 kbps",
112 "64 kbps",
113 "80 kbps",
114 "96 kbps",
115 "112 kbps",
116 "128 kbps",
117 "160 kbps",
118 "192 kbps",
119 "224 kbps",
120 "256 kbps",
121 "320 kbps",
122 "384 kbps",
123 "448 kbps",
124 "512 kbps",
125 "576 kbps",
126 "640 kbps",
127 NULL
128 };
129 static const char *mpeg_audio_mode[] = {
130 "Stereo",
131 "Joint Stereo",
132 "Dual",
133 "Mono",
134 NULL
135 };
136 static const char *mpeg_audio_mode_extension[] = {
137 "Bound 4",
138 "Bound 8",
139 "Bound 12",
140 "Bound 16",
141 NULL
142 };
143 static const char *mpeg_audio_emphasis[] = {
144 "No Emphasis",
145 "50/15 us",
146 "CCITT J17",
147 NULL
148 };
149 static const char *mpeg_audio_crc[] = {
150 "No CRC",
151 "16-bit CRC",
152 NULL
153 };
154 static const char *mpeg_video_encoding[] = {
155 "MPEG-1",
156 "MPEG-2",
157 "MPEG-4 AVC",
158 NULL
159 };
160 static const char *mpeg_video_aspect[] = {
161 "1x1",
162 "4x3",
163 "16x9",
164 "2.21x1",
165 NULL
166 };
167 static const char *mpeg_video_bitrate_mode[] = {
168 "Variable Bitrate",
169 "Constant Bitrate",
170 NULL
171 };
172 static const char *mpeg_stream_type[] = {
173 "MPEG-2 Program Stream",
174 "MPEG-2 Transport Stream",
175 "MPEG-1 System Stream",
176 "MPEG-2 DVD-compatible Stream",
177 "MPEG-1 VCD-compatible Stream",
178 "MPEG-2 SVCD-compatible Stream",
179 NULL
180 };
181 static const char *mpeg_stream_vbi_fmt[] = {
182 "No VBI",
183 "Private packet, IVTV format",
184 NULL
185 };
186 static const char *camera_power_line_frequency[] = {
187 "Disabled",
188 "50 Hz",
189 "60 Hz",
190 NULL
191 };
192 static const char *camera_exposure_auto[] = {
193 "Auto Mode",
194 "Manual Mode",
195 "Shutter Priority Mode",
196 "Aperture Priority Mode",
197 NULL
198 };
199 static const char *colorfx[] = {
200 "None",
201 "Black & White",
202 "Sepia",
203 "Negative",
204 "Emboss",
205 "Sketch",
206 "Sky blue",
207 "Grass green",
208 "Skin whiten",
209 "Vivid",
210 NULL
211 };
212 static const char *tune_preemphasis[] = {
213 "No preemphasis",
214 "50 useconds",
215 "75 useconds",
216 NULL,
217 };
218
219 switch (id) {
220 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
221 return mpeg_audio_sampling_freq;
222 case V4L2_CID_MPEG_AUDIO_ENCODING:
223 return mpeg_audio_encoding;
224 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
225 return mpeg_audio_l1_bitrate;
226 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
227 return mpeg_audio_l2_bitrate;
228 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
229 return mpeg_audio_l3_bitrate;
230 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
231 return mpeg_audio_ac3_bitrate;
232 case V4L2_CID_MPEG_AUDIO_MODE:
233 return mpeg_audio_mode;
234 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
235 return mpeg_audio_mode_extension;
236 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
237 return mpeg_audio_emphasis;
238 case V4L2_CID_MPEG_AUDIO_CRC:
239 return mpeg_audio_crc;
240 case V4L2_CID_MPEG_VIDEO_ENCODING:
241 return mpeg_video_encoding;
242 case V4L2_CID_MPEG_VIDEO_ASPECT:
243 return mpeg_video_aspect;
244 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
245 return mpeg_video_bitrate_mode;
246 case V4L2_CID_MPEG_STREAM_TYPE:
247 return mpeg_stream_type;
248 case V4L2_CID_MPEG_STREAM_VBI_FMT:
249 return mpeg_stream_vbi_fmt;
250 case V4L2_CID_POWER_LINE_FREQUENCY:
251 return camera_power_line_frequency;
252 case V4L2_CID_EXPOSURE_AUTO:
253 return camera_exposure_auto;
254 case V4L2_CID_COLORFX:
255 return colorfx;
256 case V4L2_CID_TUNE_PREEMPHASIS:
257 return tune_preemphasis;
258 default:
259 return NULL;
260 }
261}
262EXPORT_SYMBOL(v4l2_ctrl_get_menu);
263
264/* Return the control name. */
265const char *v4l2_ctrl_get_name(u32 id)
266{
267 switch (id) {
268 /* USER controls */
269 /* Keep the order of the 'case's the same as in videodev2.h! */
270 case V4L2_CID_USER_CLASS: return "User Controls";
271 case V4L2_CID_BRIGHTNESS: return "Brightness";
272 case V4L2_CID_CONTRAST: return "Contrast";
273 case V4L2_CID_SATURATION: return "Saturation";
274 case V4L2_CID_HUE: return "Hue";
275 case V4L2_CID_AUDIO_VOLUME: return "Volume";
276 case V4L2_CID_AUDIO_BALANCE: return "Balance";
277 case V4L2_CID_AUDIO_BASS: return "Bass";
278 case V4L2_CID_AUDIO_TREBLE: return "Treble";
279 case V4L2_CID_AUDIO_MUTE: return "Mute";
280 case V4L2_CID_AUDIO_LOUDNESS: return "Loudness";
281 case V4L2_CID_BLACK_LEVEL: return "Black Level";
282 case V4L2_CID_AUTO_WHITE_BALANCE: return "White Balance, Automatic";
283 case V4L2_CID_DO_WHITE_BALANCE: return "Do White Balance";
284 case V4L2_CID_RED_BALANCE: return "Red Balance";
285 case V4L2_CID_BLUE_BALANCE: return "Blue Balance";
286 case V4L2_CID_GAMMA: return "Gamma";
287 case V4L2_CID_EXPOSURE: return "Exposure";
288 case V4L2_CID_AUTOGAIN: return "Gain, Automatic";
289 case V4L2_CID_GAIN: return "Gain";
290 case V4L2_CID_HFLIP: return "Horizontal Flip";
291 case V4L2_CID_VFLIP: return "Vertical Flip";
292 case V4L2_CID_HCENTER: return "Horizontal Center";
293 case V4L2_CID_VCENTER: return "Vertical Center";
294 case V4L2_CID_POWER_LINE_FREQUENCY: return "Power Line Frequency";
295 case V4L2_CID_HUE_AUTO: return "Hue, Automatic";
296 case V4L2_CID_WHITE_BALANCE_TEMPERATURE: return "White Balance Temperature";
297 case V4L2_CID_SHARPNESS: return "Sharpness";
298 case V4L2_CID_BACKLIGHT_COMPENSATION: return "Backlight Compensation";
299 case V4L2_CID_CHROMA_AGC: return "Chroma AGC";
300 case V4L2_CID_COLOR_KILLER: return "Color Killer";
301 case V4L2_CID_COLORFX: return "Color Effects";
302 case V4L2_CID_AUTOBRIGHTNESS: return "Brightness, Automatic";
303 case V4L2_CID_BAND_STOP_FILTER: return "Band-Stop Filter";
304 case V4L2_CID_ROTATE: return "Rotate";
305 case V4L2_CID_BG_COLOR: return "Background Color";
306 case V4L2_CID_CHROMA_GAIN: return "Chroma Gain";
307
308 /* MPEG controls */
309 /* Keep the order of the 'case's the same as in videodev2.h! */
310 case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls";
311 case V4L2_CID_MPEG_STREAM_TYPE: return "Stream Type";
312 case V4L2_CID_MPEG_STREAM_PID_PMT: return "Stream PMT Program ID";
313 case V4L2_CID_MPEG_STREAM_PID_AUDIO: return "Stream Audio Program ID";
314 case V4L2_CID_MPEG_STREAM_PID_VIDEO: return "Stream Video Program ID";
315 case V4L2_CID_MPEG_STREAM_PID_PCR: return "Stream PCR Program ID";
316 case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: return "Stream PES Audio ID";
317 case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: return "Stream PES Video ID";
318 case V4L2_CID_MPEG_STREAM_VBI_FMT: return "Stream VBI Format";
319 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: return "Audio Sampling Frequency";
320 case V4L2_CID_MPEG_AUDIO_ENCODING: return "Audio Encoding";
321 case V4L2_CID_MPEG_AUDIO_L1_BITRATE: return "Audio Layer I Bitrate";
322 case V4L2_CID_MPEG_AUDIO_L2_BITRATE: return "Audio Layer II Bitrate";
323 case V4L2_CID_MPEG_AUDIO_L3_BITRATE: return "Audio Layer III Bitrate";
324 case V4L2_CID_MPEG_AUDIO_MODE: return "Audio Stereo Mode";
325 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: return "Audio Stereo Mode Extension";
326 case V4L2_CID_MPEG_AUDIO_EMPHASIS: return "Audio Emphasis";
327 case V4L2_CID_MPEG_AUDIO_CRC: return "Audio CRC";
328 case V4L2_CID_MPEG_AUDIO_MUTE: return "Audio Mute";
329 case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: return "Audio AAC Bitrate";
330 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: return "Audio AC-3 Bitrate";
331 case V4L2_CID_MPEG_VIDEO_ENCODING: return "Video Encoding";
332 case V4L2_CID_MPEG_VIDEO_ASPECT: return "Video Aspect";
333 case V4L2_CID_MPEG_VIDEO_B_FRAMES: return "Video B Frames";
334 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: return "Video GOP Size";
335 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: return "Video GOP Closure";
336 case V4L2_CID_MPEG_VIDEO_PULLDOWN: return "Video Pulldown";
337 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: return "Video Bitrate Mode";
338 case V4L2_CID_MPEG_VIDEO_BITRATE: return "Video Bitrate";
339 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: return "Video Peak Bitrate";
340 case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: return "Video Temporal Decimation";
341 case V4L2_CID_MPEG_VIDEO_MUTE: return "Video Mute";
342 case V4L2_CID_MPEG_VIDEO_MUTE_YUV: return "Video Mute YUV";
343
344 /* CAMERA controls */
345 /* Keep the order of the 'case's the same as in videodev2.h! */
346 case V4L2_CID_CAMERA_CLASS: return "Camera Controls";
347 case V4L2_CID_EXPOSURE_AUTO: return "Auto Exposure";
348 case V4L2_CID_EXPOSURE_ABSOLUTE: return "Exposure Time, Absolute";
349 case V4L2_CID_EXPOSURE_AUTO_PRIORITY: return "Exposure, Dynamic Framerate";
350 case V4L2_CID_PAN_RELATIVE: return "Pan, Relative";
351 case V4L2_CID_TILT_RELATIVE: return "Tilt, Relative";
352 case V4L2_CID_PAN_RESET: return "Pan, Reset";
353 case V4L2_CID_TILT_RESET: return "Tilt, Reset";
354 case V4L2_CID_PAN_ABSOLUTE: return "Pan, Absolute";
355 case V4L2_CID_TILT_ABSOLUTE: return "Tilt, Absolute";
356 case V4L2_CID_FOCUS_ABSOLUTE: return "Focus, Absolute";
357 case V4L2_CID_FOCUS_RELATIVE: return "Focus, Relative";
358 case V4L2_CID_FOCUS_AUTO: return "Focus, Automatic";
359 case V4L2_CID_ZOOM_ABSOLUTE: return "Zoom, Absolute";
360 case V4L2_CID_ZOOM_RELATIVE: return "Zoom, Relative";
361 case V4L2_CID_ZOOM_CONTINUOUS: return "Zoom, Continuous";
362 case V4L2_CID_PRIVACY: return "Privacy";
363 case V4L2_CID_IRIS_ABSOLUTE: return "Iris, Absolute";
364 case V4L2_CID_IRIS_RELATIVE: return "Iris, Relative";
365
366 /* FM Radio Modulator control */
367 /* Keep the order of the 'case's the same as in videodev2.h! */
368 case V4L2_CID_FM_TX_CLASS: return "FM Radio Modulator Controls";
369 case V4L2_CID_RDS_TX_DEVIATION: return "RDS Signal Deviation";
370 case V4L2_CID_RDS_TX_PI: return "RDS Program ID";
371 case V4L2_CID_RDS_TX_PTY: return "RDS Program Type";
372 case V4L2_CID_RDS_TX_PS_NAME: return "RDS PS Name";
373 case V4L2_CID_RDS_TX_RADIO_TEXT: return "RDS Radio Text";
374 case V4L2_CID_AUDIO_LIMITER_ENABLED: return "Audio Limiter Feature Enabled";
375 case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: return "Audio Limiter Release Time";
376 case V4L2_CID_AUDIO_LIMITER_DEVIATION: return "Audio Limiter Deviation";
377 case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Feature Enabled";
378 case V4L2_CID_AUDIO_COMPRESSION_GAIN: return "Audio Compression Gain";
379 case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: return "Audio Compression Threshold";
380 case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: return "Audio Compression Attack Time";
381 case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: return "Audio Compression Release Time";
382 case V4L2_CID_PILOT_TONE_ENABLED: return "Pilot Tone Feature Enabled";
383 case V4L2_CID_PILOT_TONE_DEVIATION: return "Pilot Tone Deviation";
384 case V4L2_CID_PILOT_TONE_FREQUENCY: return "Pilot Tone Frequency";
385 case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-emphasis settings";
386 case V4L2_CID_TUNE_POWER_LEVEL: return "Tune Power Level";
387 case V4L2_CID_TUNE_ANTENNA_CAPACITOR: return "Tune Antenna Capacitor";
388
389 default:
390 return NULL;
391 }
392}
393EXPORT_SYMBOL(v4l2_ctrl_get_name);
394
395void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
396 s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags)
397{
398 *name = v4l2_ctrl_get_name(id);
399 *flags = 0;
400
401 switch (id) {
402 case V4L2_CID_AUDIO_MUTE:
403 case V4L2_CID_AUDIO_LOUDNESS:
404 case V4L2_CID_AUTO_WHITE_BALANCE:
405 case V4L2_CID_AUTOGAIN:
406 case V4L2_CID_HFLIP:
407 case V4L2_CID_VFLIP:
408 case V4L2_CID_HUE_AUTO:
409 case V4L2_CID_CHROMA_AGC:
410 case V4L2_CID_COLOR_KILLER:
411 case V4L2_CID_MPEG_AUDIO_MUTE:
412 case V4L2_CID_MPEG_VIDEO_MUTE:
413 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
414 case V4L2_CID_MPEG_VIDEO_PULLDOWN:
415 case V4L2_CID_EXPOSURE_AUTO_PRIORITY:
416 case V4L2_CID_FOCUS_AUTO:
417 case V4L2_CID_PRIVACY:
418 case V4L2_CID_AUDIO_LIMITER_ENABLED:
419 case V4L2_CID_AUDIO_COMPRESSION_ENABLED:
420 case V4L2_CID_PILOT_TONE_ENABLED:
421 *type = V4L2_CTRL_TYPE_BOOLEAN;
422 *min = 0;
423 *max = *step = 1;
424 break;
425 case V4L2_CID_PAN_RESET:
426 case V4L2_CID_TILT_RESET:
427 *type = V4L2_CTRL_TYPE_BUTTON;
428 *flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
429 *min = *max = *step = *def = 0;
430 break;
431 case V4L2_CID_POWER_LINE_FREQUENCY:
432 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
433 case V4L2_CID_MPEG_AUDIO_ENCODING:
434 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
435 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
436 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
437 case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
438 case V4L2_CID_MPEG_AUDIO_MODE:
439 case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
440 case V4L2_CID_MPEG_AUDIO_EMPHASIS:
441 case V4L2_CID_MPEG_AUDIO_CRC:
442 case V4L2_CID_MPEG_VIDEO_ENCODING:
443 case V4L2_CID_MPEG_VIDEO_ASPECT:
444 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
445 case V4L2_CID_MPEG_STREAM_TYPE:
446 case V4L2_CID_MPEG_STREAM_VBI_FMT:
447 case V4L2_CID_EXPOSURE_AUTO:
448 case V4L2_CID_COLORFX:
449 case V4L2_CID_TUNE_PREEMPHASIS:
450 *type = V4L2_CTRL_TYPE_MENU;
451 break;
452 case V4L2_CID_RDS_TX_PS_NAME:
453 case V4L2_CID_RDS_TX_RADIO_TEXT:
454 *type = V4L2_CTRL_TYPE_STRING;
455 break;
456 case V4L2_CID_USER_CLASS:
457 case V4L2_CID_CAMERA_CLASS:
458 case V4L2_CID_MPEG_CLASS:
459 case V4L2_CID_FM_TX_CLASS:
460 *type = V4L2_CTRL_TYPE_CTRL_CLASS;
461 /* You can neither read not write these */
462 *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY;
463 *min = *max = *step = *def = 0;
464 break;
465 case V4L2_CID_BG_COLOR:
466 *type = V4L2_CTRL_TYPE_INTEGER;
467 *step = 1;
468 *min = 0;
469 /* Max is calculated as RGB888 that is 2^24 */
470 *max = 0xFFFFFF;
471 break;
472 default:
473 *type = V4L2_CTRL_TYPE_INTEGER;
474 break;
475 }
476 switch (id) {
477 case V4L2_CID_MPEG_AUDIO_ENCODING:
478 case V4L2_CID_MPEG_AUDIO_MODE:
479 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
480 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
481 case V4L2_CID_MPEG_STREAM_TYPE:
482 *flags |= V4L2_CTRL_FLAG_UPDATE;
483 break;
484 case V4L2_CID_AUDIO_VOLUME:
485 case V4L2_CID_AUDIO_BALANCE:
486 case V4L2_CID_AUDIO_BASS:
487 case V4L2_CID_AUDIO_TREBLE:
488 case V4L2_CID_BRIGHTNESS:
489 case V4L2_CID_CONTRAST:
490 case V4L2_CID_SATURATION:
491 case V4L2_CID_HUE:
492 case V4L2_CID_RED_BALANCE:
493 case V4L2_CID_BLUE_BALANCE:
494 case V4L2_CID_GAMMA:
495 case V4L2_CID_SHARPNESS:
496 case V4L2_CID_CHROMA_GAIN:
497 case V4L2_CID_RDS_TX_DEVIATION:
498 case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME:
499 case V4L2_CID_AUDIO_LIMITER_DEVIATION:
500 case V4L2_CID_AUDIO_COMPRESSION_GAIN:
501 case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD:
502 case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME:
503 case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME:
504 case V4L2_CID_PILOT_TONE_DEVIATION:
505 case V4L2_CID_PILOT_TONE_FREQUENCY:
506 case V4L2_CID_TUNE_POWER_LEVEL:
507 case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
508 *flags |= V4L2_CTRL_FLAG_SLIDER;
509 break;
510 case V4L2_CID_PAN_RELATIVE:
511 case V4L2_CID_TILT_RELATIVE:
512 case V4L2_CID_FOCUS_RELATIVE:
513 case V4L2_CID_IRIS_RELATIVE:
514 case V4L2_CID_ZOOM_RELATIVE:
515 *flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
516 break;
517 }
518}
519EXPORT_SYMBOL(v4l2_ctrl_fill);
520
521/* Helper function to determine whether the control type is compatible with
522 VIDIOC_G/S_CTRL. */
523static bool type_is_int(const struct v4l2_ctrl *ctrl)
524{
525 switch (ctrl->type) {
526 case V4L2_CTRL_TYPE_INTEGER64:
527 case V4L2_CTRL_TYPE_STRING:
528 /* Nope, these need v4l2_ext_control */
529 return false;
530 default:
531 return true;
532 }
533}
534
535/* Helper function: copy the current control value back to the caller */
536static int cur_to_user(struct v4l2_ext_control *c,
537 struct v4l2_ctrl *ctrl)
538{
539 u32 len;
540
541 switch (ctrl->type) {
542 case V4L2_CTRL_TYPE_STRING:
543 len = strlen(ctrl->cur.string);
544 if (c->size < len + 1) {
545 c->size = len + 1;
546 return -ENOSPC;
547 }
548 return copy_to_user(c->string, ctrl->cur.string,
549 len + 1) ? -EFAULT : 0;
550 case V4L2_CTRL_TYPE_INTEGER64:
551 c->value64 = ctrl->cur.val64;
552 break;
553 default:
554 c->value = ctrl->cur.val;
555 break;
556 }
557 return 0;
558}
559
560/* Helper function: copy the caller-provider value as the new control value */
561static int user_to_new(struct v4l2_ext_control *c,
562 struct v4l2_ctrl *ctrl)
563{
564 int ret;
565 u32 size;
566
567 ctrl->has_new = 1;
568 switch (ctrl->type) {
569 case V4L2_CTRL_TYPE_INTEGER64:
570 ctrl->val64 = c->value64;
571 break;
572 case V4L2_CTRL_TYPE_STRING:
573 size = c->size;
574 if (size == 0)
575 return -ERANGE;
576 if (size > ctrl->maximum + 1)
577 size = ctrl->maximum + 1;
578 ret = copy_from_user(ctrl->string, c->string, size);
579 if (!ret) {
580 char last = ctrl->string[size - 1];
581
582 ctrl->string[size - 1] = 0;
583 /* If the string was longer than ctrl->maximum,
584 then return an error. */
585 if (strlen(ctrl->string) == ctrl->maximum && last)
586 return -ERANGE;
587 }
588 return ret ? -EFAULT : 0;
589 default:
590 ctrl->val = c->value;
591 break;
592 }
593 return 0;
594}
595
596/* Helper function: copy the new control value back to the caller */
597static int new_to_user(struct v4l2_ext_control *c,
598 struct v4l2_ctrl *ctrl)
599{
600 u32 len;
601
602 switch (ctrl->type) {
603 case V4L2_CTRL_TYPE_STRING:
604 len = strlen(ctrl->string);
605 if (c->size < len + 1) {
606 c->size = ctrl->maximum + 1;
607 return -ENOSPC;
608 }
609 return copy_to_user(c->string, ctrl->string,
610 len + 1) ? -EFAULT : 0;
611 case V4L2_CTRL_TYPE_INTEGER64:
612 c->value64 = ctrl->val64;
613 break;
614 default:
615 c->value = ctrl->val;
616 break;
617 }
618 return 0;
619}
620
621/* Copy the new value to the current value. */
622static void new_to_cur(struct v4l2_ctrl *ctrl)
623{
624 if (ctrl == NULL)
625 return;
626 switch (ctrl->type) {
627 case V4L2_CTRL_TYPE_STRING:
628 /* strings are always 0-terminated */
629 strcpy(ctrl->cur.string, ctrl->string);
630 break;
631 case V4L2_CTRL_TYPE_INTEGER64:
632 ctrl->cur.val64 = ctrl->val64;
633 break;
634 default:
635 ctrl->cur.val = ctrl->val;
636 break;
637 }
638}
639
640/* Copy the current value to the new value */
641static void cur_to_new(struct v4l2_ctrl *ctrl)
642{
643 if (ctrl == NULL)
644 return;
645 switch (ctrl->type) {
646 case V4L2_CTRL_TYPE_STRING:
647 /* strings are always 0-terminated */
648 strcpy(ctrl->string, ctrl->cur.string);
649 break;
650 case V4L2_CTRL_TYPE_INTEGER64:
651 ctrl->val64 = ctrl->cur.val64;
652 break;
653 default:
654 ctrl->val = ctrl->cur.val;
655 break;
656 }
657}
658
659/* Return non-zero if one or more of the controls in the cluster has a new
660 value that differs from the current value. */
661static int cluster_changed(struct v4l2_ctrl *master)
662{
663 int diff = 0;
664 int i;
665
666 for (i = 0; !diff && i < master->ncontrols; i++) {
667 struct v4l2_ctrl *ctrl = master->cluster[i];
668
669 if (ctrl == NULL)
670 continue;
671 switch (ctrl->type) {
672 case V4L2_CTRL_TYPE_BUTTON:
673 /* Button controls are always 'different' */
674 return 1;
675 case V4L2_CTRL_TYPE_STRING:
676 /* strings are always 0-terminated */
677 diff = strcmp(ctrl->string, ctrl->cur.string);
678 break;
679 case V4L2_CTRL_TYPE_INTEGER64:
680 diff = ctrl->val64 != ctrl->cur.val64;
681 break;
682 default:
683 diff = ctrl->val != ctrl->cur.val;
684 break;
685 }
686 }
687 return diff;
688}
689
690/* Validate a new control */
691static int validate_new(struct v4l2_ctrl *ctrl)
692{
693 s32 val = ctrl->val;
694 char *s = ctrl->string;
695 u32 offset;
696 size_t len;
697
698 switch (ctrl->type) {
699 case V4L2_CTRL_TYPE_INTEGER:
700 /* Round towards the closest legal value */
701 val += ctrl->step / 2;
702 if (val < ctrl->minimum)
703 val = ctrl->minimum;
704 if (val > ctrl->maximum)
705 val = ctrl->maximum;
706 offset = val - ctrl->minimum;
707 offset = ctrl->step * (offset / ctrl->step);
708 val = ctrl->minimum + offset;
709 ctrl->val = val;
710 return 0;
711
712 case V4L2_CTRL_TYPE_BOOLEAN:
713 ctrl->val = !!ctrl->val;
714 return 0;
715
716 case V4L2_CTRL_TYPE_MENU:
717 if (val < ctrl->minimum || val > ctrl->maximum)
718 return -ERANGE;
719 if (ctrl->qmenu[val][0] == '\0' ||
720 (ctrl->menu_skip_mask & (1 << val)))
721 return -EINVAL;
722 return 0;
723
724 case V4L2_CTRL_TYPE_BUTTON:
725 case V4L2_CTRL_TYPE_CTRL_CLASS:
726 ctrl->val64 = 0;
727 return 0;
728
729 case V4L2_CTRL_TYPE_INTEGER64:
730 return 0;
731
732 case V4L2_CTRL_TYPE_STRING:
733 len = strlen(s);
734 if (len < ctrl->minimum)
735 return -ERANGE;
736 if ((len - ctrl->minimum) % ctrl->step)
737 return -ERANGE;
738 return 0;
739
740 default:
741 return -EINVAL;
742 }
743}
744
745static inline u32 node2id(struct list_head *node)
746{
747 return list_entry(node, struct v4l2_ctrl_ref, node)->ctrl->id;
748}
749
750/* Set the handler's error code if it wasn't set earlier already */
751static inline int handler_set_err(struct v4l2_ctrl_handler *hdl, int err)
752{
753 if (hdl->error == 0)
754 hdl->error = err;
755 return err;
756}
757
758/* Initialize the handler */
759int v4l2_ctrl_handler_init(struct v4l2_ctrl_handler *hdl,
760 unsigned nr_of_controls_hint)
761{
762 mutex_init(&hdl->lock);
763 INIT_LIST_HEAD(&hdl->ctrls);
764 INIT_LIST_HEAD(&hdl->ctrl_refs);
765 hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8;
766 hdl->buckets = kzalloc(sizeof(hdl->buckets[0]) * hdl->nr_of_buckets,
767 GFP_KERNEL);
768 hdl->error = hdl->buckets ? 0 : -ENOMEM;
769 return hdl->error;
770}
771EXPORT_SYMBOL(v4l2_ctrl_handler_init);
772
773/* Free all controls and control refs */
774void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl)
775{
776 struct v4l2_ctrl_ref *ref, *next_ref;
777 struct v4l2_ctrl *ctrl, *next_ctrl;
778
779 if (hdl == NULL || hdl->buckets == NULL)
780 return;
781
782 mutex_lock(&hdl->lock);
783 /* Free all nodes */
784 list_for_each_entry_safe(ref, next_ref, &hdl->ctrl_refs, node) {
785 list_del(&ref->node);
786 kfree(ref);
787 }
788 /* Free all controls owned by the handler */
789 list_for_each_entry_safe(ctrl, next_ctrl, &hdl->ctrls, node) {
790 list_del(&ctrl->node);
791 kfree(ctrl);
792 }
793 kfree(hdl->buckets);
794 hdl->buckets = NULL;
795 hdl->cached = NULL;
796 hdl->error = 0;
797 mutex_unlock(&hdl->lock);
798}
799EXPORT_SYMBOL(v4l2_ctrl_handler_free);
800
801/* For backwards compatibility: V4L2_CID_PRIVATE_BASE should no longer
802 be used except in G_CTRL, S_CTRL, QUERYCTRL and QUERYMENU when dealing
803 with applications that do not use the NEXT_CTRL flag.
804
805 We just find the n-th private user control. It's O(N), but that should not
806 be an issue in this particular case. */
807static struct v4l2_ctrl_ref *find_private_ref(
808 struct v4l2_ctrl_handler *hdl, u32 id)
809{
810 struct v4l2_ctrl_ref *ref;
811
812 id -= V4L2_CID_PRIVATE_BASE;
813 list_for_each_entry(ref, &hdl->ctrl_refs, node) {
814 /* Search for private user controls that are compatible with
815 VIDIOC_G/S_CTRL. */
816 if (V4L2_CTRL_ID2CLASS(ref->ctrl->id) == V4L2_CTRL_CLASS_USER &&
817 V4L2_CTRL_DRIVER_PRIV(ref->ctrl->id)) {
818 if (!type_is_int(ref->ctrl))
819 continue;
820 if (id == 0)
821 return ref;
822 id--;
823 }
824 }
825 return NULL;
826}
827
828/* Find a control with the given ID. */
829static struct v4l2_ctrl_ref *find_ref(struct v4l2_ctrl_handler *hdl, u32 id)
830{
831 struct v4l2_ctrl_ref *ref;
832 int bucket;
833
834 id &= V4L2_CTRL_ID_MASK;
835
836 /* Old-style private controls need special handling */
837 if (id >= V4L2_CID_PRIVATE_BASE)
838 return find_private_ref(hdl, id);
839 bucket = id % hdl->nr_of_buckets;
840
841 /* Simple optimization: cache the last control found */
842 if (hdl->cached && hdl->cached->ctrl->id == id)
843 return hdl->cached;
844
845 /* Not in cache, search the hash */
846 ref = hdl->buckets ? hdl->buckets[bucket] : NULL;
847 while (ref && ref->ctrl->id != id)
848 ref = ref->next;
849
850 if (ref)
851 hdl->cached = ref; /* cache it! */
852 return ref;
853}
854
855/* Find a control with the given ID. Take the handler's lock first. */
856static struct v4l2_ctrl_ref *find_ref_lock(
857 struct v4l2_ctrl_handler *hdl, u32 id)
858{
859 struct v4l2_ctrl_ref *ref = NULL;
860
861 if (hdl) {
862 mutex_lock(&hdl->lock);
863 ref = find_ref(hdl, id);
864 mutex_unlock(&hdl->lock);
865 }
866 return ref;
867}
868
869/* Find a control with the given ID. */
870struct v4l2_ctrl *v4l2_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id)
871{
872 struct v4l2_ctrl_ref *ref = find_ref_lock(hdl, id);
873
874 return ref ? ref->ctrl : NULL;
875}
876EXPORT_SYMBOL(v4l2_ctrl_find);
877
878/* Allocate a new v4l2_ctrl_ref and hook it into the handler. */
879static int handler_new_ref(struct v4l2_ctrl_handler *hdl,
880 struct v4l2_ctrl *ctrl)
881{
882 struct v4l2_ctrl_ref *ref;
883 struct v4l2_ctrl_ref *new_ref;
884 u32 id = ctrl->id;
885 u32 class_ctrl = V4L2_CTRL_ID2CLASS(id) | 1;
886 int bucket = id % hdl->nr_of_buckets; /* which bucket to use */
887
888 /* Automatically add the control class if it is not yet present. */
889 if (id != class_ctrl && find_ref_lock(hdl, class_ctrl) == NULL)
890 if (!v4l2_ctrl_new_std(hdl, NULL, class_ctrl, 0, 0, 0, 0))
891 return hdl->error;
892
893 if (hdl->error)
894 return hdl->error;
895
896 new_ref = kzalloc(sizeof(*new_ref), GFP_KERNEL);
897 if (!new_ref)
898 return handler_set_err(hdl, -ENOMEM);
899 new_ref->ctrl = ctrl;
900 if (ctrl->handler == hdl) {
901 /* By default each control starts in a cluster of its own.
902 new_ref->ctrl is basically a cluster array with one
903 element, so that's perfect to use as the cluster pointer.
904 But only do this for the handler that owns the control. */
905 ctrl->cluster = &new_ref->ctrl;
906 ctrl->ncontrols = 1;
907 }
908
909 INIT_LIST_HEAD(&new_ref->node);
910
911 mutex_lock(&hdl->lock);
912
913 /* Add immediately at the end of the list if the list is empty, or if
914 the last element in the list has a lower ID.
915 This ensures that when elements are added in ascending order the
916 insertion is an O(1) operation. */
917 if (list_empty(&hdl->ctrl_refs) || id > node2id(hdl->ctrl_refs.prev)) {
918 list_add_tail(&new_ref->node, &hdl->ctrl_refs);
919 goto insert_in_hash;
920 }
921
922 /* Find insert position in sorted list */
923 list_for_each_entry(ref, &hdl->ctrl_refs, node) {
924 if (ref->ctrl->id < id)
925 continue;
926 /* Don't add duplicates */
927 if (ref->ctrl->id == id) {
928 kfree(new_ref);
929 goto unlock;
930 }
931 list_add(&new_ref->node, ref->node.prev);
932 break;
933 }
934
935insert_in_hash:
936 /* Insert the control node in the hash */
937 new_ref->next = hdl->buckets[bucket];
938 hdl->buckets[bucket] = new_ref;
939
940unlock:
941 mutex_unlock(&hdl->lock);
942 return 0;
943}
944
945/* Add a new control */
946static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
947 const struct v4l2_ctrl_ops *ops,
948 u32 id, const char *name, enum v4l2_ctrl_type type,
949 s32 min, s32 max, u32 step, s32 def,
950 u32 flags, const char **qmenu, void *priv)
951{
952 struct v4l2_ctrl *ctrl;
953 unsigned sz_extra = 0;
954
955 if (hdl->error)
956 return NULL;
957
958 /* Sanity checks */
959 if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE ||
960 def < min || def > max || max < min ||
961 (type == V4L2_CTRL_TYPE_INTEGER && step == 0) ||
962 (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) ||
963 (type == V4L2_CTRL_TYPE_STRING && max == 0)) {
964 handler_set_err(hdl, -ERANGE);
965 return NULL;
966 }
967
968 if (type == V4L2_CTRL_TYPE_BUTTON)
969 flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
970 else if (type == V4L2_CTRL_TYPE_CTRL_CLASS)
971 flags |= V4L2_CTRL_FLAG_READ_ONLY;
972 else if (type == V4L2_CTRL_TYPE_STRING)
973 sz_extra += 2 * (max + 1);
974
975 ctrl = kzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL);
976 if (ctrl == NULL) {
977 handler_set_err(hdl, -ENOMEM);
978 return NULL;
979 }
980
981 INIT_LIST_HEAD(&ctrl->node);
982 ctrl->handler = hdl;
983 ctrl->ops = ops;
984 ctrl->id = id;
985 ctrl->name = name;
986 ctrl->type = type;
987 ctrl->flags = flags;
988 ctrl->minimum = min;
989 ctrl->maximum = max;
990 ctrl->step = step;
991 ctrl->qmenu = qmenu;
992 ctrl->priv = priv;
993 ctrl->cur.val = ctrl->val = ctrl->default_value = def;
994
995 if (ctrl->type == V4L2_CTRL_TYPE_STRING) {
996 ctrl->cur.string = (char *)&ctrl[1] + sz_extra - (max + 1);
997 ctrl->string = (char *)&ctrl[1] + sz_extra - 2 * (max + 1);
998 if (ctrl->minimum)
999 memset(ctrl->cur.string, ' ', ctrl->minimum);
1000 }
1001 if (handler_new_ref(hdl, ctrl)) {
1002 kfree(ctrl);
1003 return NULL;
1004 }
1005 mutex_lock(&hdl->lock);
1006 list_add_tail(&ctrl->node, &hdl->ctrls);
1007 mutex_unlock(&hdl->lock);
1008 return ctrl;
1009}
1010
1011struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
1012 const struct v4l2_ctrl_config *cfg, void *priv)
1013{
1014 bool is_menu;
1015 struct v4l2_ctrl *ctrl;
1016 const char *name = cfg->name;
1017 const char **qmenu = cfg->qmenu;
1018 enum v4l2_ctrl_type type = cfg->type;
1019 u32 flags = cfg->flags;
1020 s32 min = cfg->min;
1021 s32 max = cfg->max;
1022 u32 step = cfg->step;
1023 s32 def = cfg->def;
1024
1025 if (name == NULL)
1026 v4l2_ctrl_fill(cfg->id, &name, &type, &min, &max, &step,
1027 &def, &flags);
1028
1029 is_menu = (cfg->type == V4L2_CTRL_TYPE_MENU);
1030 if (is_menu)
1031 WARN_ON(step);
1032 else
1033 WARN_ON(cfg->menu_skip_mask);
1034 if (is_menu && qmenu == NULL)
1035 qmenu = v4l2_ctrl_get_menu(cfg->id);
1036
1037 ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->id, name,
1038 type, min, max,
1039 is_menu ? cfg->menu_skip_mask : step,
1040 def, flags, qmenu, priv);
1041 if (ctrl) {
1042 ctrl->is_private = cfg->is_private;
1043 ctrl->is_volatile = cfg->is_volatile;
1044 }
1045 return ctrl;
1046}
1047EXPORT_SYMBOL(v4l2_ctrl_new_custom);
1048
1049/* Helper function for standard non-menu controls */
1050struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
1051 const struct v4l2_ctrl_ops *ops,
1052 u32 id, s32 min, s32 max, u32 step, s32 def)
1053{
1054 const char *name;
1055 enum v4l2_ctrl_type type;
1056 u32 flags;
1057
1058 v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
1059 if (type == V4L2_CTRL_TYPE_MENU) {
1060 handler_set_err(hdl, -EINVAL);
1061 return NULL;
1062 }
1063 return v4l2_ctrl_new(hdl, ops, id, name, type,
1064 min, max, step, def, flags, NULL, NULL);
1065}
1066EXPORT_SYMBOL(v4l2_ctrl_new_std);
1067
1068/* Helper function for standard menu controls */
1069struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
1070 const struct v4l2_ctrl_ops *ops,
1071 u32 id, s32 max, s32 mask, s32 def)
1072{
1073 const char **qmenu = v4l2_ctrl_get_menu(id);
1074 const char *name;
1075 enum v4l2_ctrl_type type;
1076 s32 min;
1077 s32 step;
1078 u32 flags;
1079
1080 v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
1081 if (type != V4L2_CTRL_TYPE_MENU) {
1082 handler_set_err(hdl, -EINVAL);
1083 return NULL;
1084 }
1085 return v4l2_ctrl_new(hdl, ops, id, name, type,
1086 0, max, mask, def, flags, qmenu, NULL);
1087}
1088EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);
1089
1090/* Add a control from another handler to this handler */
1091struct v4l2_ctrl *v4l2_ctrl_add_ctrl(struct v4l2_ctrl_handler *hdl,
1092 struct v4l2_ctrl *ctrl)
1093{
1094 if (hdl == NULL || hdl->error)
1095 return NULL;
1096 if (ctrl == NULL) {
1097 handler_set_err(hdl, -EINVAL);
1098 return NULL;
1099 }
1100 if (ctrl->handler == hdl)
1101 return ctrl;
1102 return handler_new_ref(hdl, ctrl) ? NULL : ctrl;
1103}
1104EXPORT_SYMBOL(v4l2_ctrl_add_ctrl);
1105
1106/* Add the controls from another handler to our own. */
1107int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl,
1108 struct v4l2_ctrl_handler *add)
1109{
1110 struct v4l2_ctrl *ctrl;
1111 int ret = 0;
1112
1113 /* Do nothing if either handler is NULL or if they are the same */
1114 if (!hdl || !add || hdl == add)
1115 return 0;
1116 if (hdl->error)
1117 return hdl->error;
1118 mutex_lock(&add->lock);
1119 list_for_each_entry(ctrl, &add->ctrls, node) {
1120 /* Skip handler-private controls. */
1121 if (ctrl->is_private)
1122 continue;
1123 ret = handler_new_ref(hdl, ctrl);
1124 if (ret)
1125 break;
1126 }
1127 mutex_unlock(&add->lock);
1128 return ret;
1129}
1130EXPORT_SYMBOL(v4l2_ctrl_add_handler);
1131
1132/* Cluster controls */
1133void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls)
1134{
1135 int i;
1136
1137 /* The first control is the master control and it must not be NULL */
1138 BUG_ON(controls[0] == NULL);
1139
1140 for (i = 0; i < ncontrols; i++) {
1141 if (controls[i]) {
1142 controls[i]->cluster = controls;
1143 controls[i]->ncontrols = ncontrols;
1144 }
1145 }
1146}
1147EXPORT_SYMBOL(v4l2_ctrl_cluster);
1148
1149/* Activate/deactivate a control. */
1150void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active)
1151{
1152 if (ctrl == NULL)
1153 return;
1154
1155 if (!active)
1156 /* set V4L2_CTRL_FLAG_INACTIVE */
1157 set_bit(4, &ctrl->flags);
1158 else
1159 /* clear V4L2_CTRL_FLAG_INACTIVE */
1160 clear_bit(4, &ctrl->flags);
1161}
1162EXPORT_SYMBOL(v4l2_ctrl_activate);
1163
1164/* Grab/ungrab a control.
1165 Typically used when streaming starts and you want to grab controls,
1166 preventing the user from changing them.
1167
1168 Just call this and the framework will block any attempts to change
1169 these controls. */
1170void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed)
1171{
1172 if (ctrl == NULL)
1173 return;
1174
1175 if (grabbed)
1176 /* set V4L2_CTRL_FLAG_GRABBED */
1177 set_bit(1, &ctrl->flags);
1178 else
1179 /* clear V4L2_CTRL_FLAG_GRABBED */
1180 clear_bit(1, &ctrl->flags);
1181}
1182EXPORT_SYMBOL(v4l2_ctrl_grab);
1183
1184/* Log the control name and value */
1185static void log_ctrl(const struct v4l2_ctrl *ctrl,
1186 const char *prefix, const char *colon)
1187{
1188 int fl_inact = ctrl->flags & V4L2_CTRL_FLAG_INACTIVE;
1189 int fl_grabbed = ctrl->flags & V4L2_CTRL_FLAG_GRABBED;
1190
1191 if (ctrl->flags & (V4L2_CTRL_FLAG_DISABLED | V4L2_CTRL_FLAG_WRITE_ONLY))
1192 return;
1193 if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
1194 return;
1195
1196 printk(KERN_INFO "%s%s%s: ", prefix, colon, ctrl->name);
1197
1198 switch (ctrl->type) {
1199 case V4L2_CTRL_TYPE_INTEGER:
1200 printk(KERN_CONT "%d", ctrl->cur.val);
1201 break;
1202 case V4L2_CTRL_TYPE_BOOLEAN:
1203 printk(KERN_CONT "%s", ctrl->cur.val ? "true" : "false");
1204 break;
1205 case V4L2_CTRL_TYPE_MENU:
1206 printk(KERN_CONT "%s", ctrl->qmenu[ctrl->cur.val]);
1207 break;
1208 case V4L2_CTRL_TYPE_INTEGER64:
1209 printk(KERN_CONT "%lld", ctrl->cur.val64);
1210 break;
1211 case V4L2_CTRL_TYPE_STRING:
1212 printk(KERN_CONT "%s", ctrl->cur.string);
1213 break;
1214 default:
1215 printk(KERN_CONT "unknown type %d", ctrl->type);
1216 break;
1217 }
1218 if (fl_inact && fl_grabbed)
1219 printk(KERN_CONT " (inactive, grabbed)\n");
1220 else if (fl_inact)
1221 printk(KERN_CONT " (inactive)\n");
1222 else if (fl_grabbed)
1223 printk(KERN_CONT " (grabbed)\n");
1224 else
1225 printk(KERN_CONT "\n");
1226}
1227
1228/* Log all controls owned by the handler */
1229void v4l2_ctrl_handler_log_status(struct v4l2_ctrl_handler *hdl,
1230 const char *prefix)
1231{
1232 struct v4l2_ctrl *ctrl;
1233 const char *colon = "";
1234 int len;
1235
1236 if (hdl == NULL)
1237 return;
1238 if (prefix == NULL)
1239 prefix = "";
1240 len = strlen(prefix);
1241 if (len && prefix[len - 1] != ' ')
1242 colon = ": ";
1243 mutex_lock(&hdl->lock);
1244 list_for_each_entry(ctrl, &hdl->ctrls, node)
1245 if (!(ctrl->flags & V4L2_CTRL_FLAG_DISABLED))
1246 log_ctrl(ctrl, prefix, colon);
1247 mutex_unlock(&hdl->lock);
1248}
1249EXPORT_SYMBOL(v4l2_ctrl_handler_log_status);
1250
1251/* Call s_ctrl for all controls owned by the handler */
1252int v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl)
1253{
1254 struct v4l2_ctrl *ctrl;
1255 int ret = 0;
1256
1257 if (hdl == NULL)
1258 return 0;
1259 mutex_lock(&hdl->lock);
1260 list_for_each_entry(ctrl, &hdl->ctrls, node)
1261 ctrl->done = false;
1262
1263 list_for_each_entry(ctrl, &hdl->ctrls, node) {
1264 struct v4l2_ctrl *master = ctrl->cluster[0];
1265 int i;
1266
1267 /* Skip if this control was already handled by a cluster. */
1268 if (ctrl->done)
1269 continue;
1270
1271 for (i = 0; i < master->ncontrols; i++)
1272 cur_to_new(master->cluster[i]);
1273
1274 /* Skip button controls and read-only controls. */
1275 if (ctrl->type == V4L2_CTRL_TYPE_BUTTON ||
1276 (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY))
1277 continue;
1278 ret = master->ops->s_ctrl(master);
1279 if (ret)
1280 break;
1281 for (i = 0; i < master->ncontrols; i++)
1282 if (master->cluster[i])
1283 master->cluster[i]->done = true;
1284 }
1285 mutex_unlock(&hdl->lock);
1286 return ret;
1287}
1288EXPORT_SYMBOL(v4l2_ctrl_handler_setup);
1289
1290/* Implement VIDIOC_QUERYCTRL */
1291int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
1292{
1293 u32 id = qc->id & V4L2_CTRL_ID_MASK;
1294 struct v4l2_ctrl_ref *ref;
1295 struct v4l2_ctrl *ctrl;
1296
1297 if (hdl == NULL)
1298 return -EINVAL;
1299
1300 mutex_lock(&hdl->lock);
1301
1302 /* Try to find it */
1303 ref = find_ref(hdl, id);
1304
1305 if ((qc->id & V4L2_CTRL_FLAG_NEXT_CTRL) && !list_empty(&hdl->ctrl_refs)) {
1306 /* Find the next control with ID > qc->id */
1307
1308 /* Did we reach the end of the control list? */
1309 if (id >= node2id(hdl->ctrl_refs.prev)) {
1310 ref = NULL; /* Yes, so there is no next control */
1311 } else if (ref) {
1312 /* We found a control with the given ID, so just get
1313 the next one in the list. */
1314 ref = list_entry(ref->node.next, typeof(*ref), node);
1315 } else {
1316 /* No control with the given ID exists, so start
1317 searching for the next largest ID. We know there
1318 is one, otherwise the first 'if' above would have
1319 been true. */
1320 list_for_each_entry(ref, &hdl->ctrl_refs, node)
1321 if (id < ref->ctrl->id)
1322 break;
1323 }
1324 }
1325 mutex_unlock(&hdl->lock);
1326 if (!ref)
1327 return -EINVAL;
1328
1329 ctrl = ref->ctrl;
1330 memset(qc, 0, sizeof(*qc));
1331 qc->id = ctrl->id;
1332 strlcpy(qc->name, ctrl->name, sizeof(qc->name));
1333 qc->minimum = ctrl->minimum;
1334 qc->maximum = ctrl->maximum;
1335 qc->default_value = ctrl->default_value;
1336 if (qc->type == V4L2_CTRL_TYPE_MENU)
1337 qc->step = 1;
1338 else
1339 qc->step = ctrl->step;
1340 qc->flags = ctrl->flags;
1341 qc->type = ctrl->type;
1342 return 0;
1343}
1344EXPORT_SYMBOL(v4l2_queryctrl);
1345
1346int v4l2_subdev_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
1347{
1348 return v4l2_queryctrl(sd->ctrl_handler, qc);
1349}
1350EXPORT_SYMBOL(v4l2_subdev_queryctrl);
1351
1352/* Implement VIDIOC_QUERYMENU */
1353int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm)
1354{
1355 struct v4l2_ctrl *ctrl;
1356 u32 i = qm->index;
1357
1358 ctrl = v4l2_ctrl_find(hdl, qm->id);
1359 if (!ctrl)
1360 return -EINVAL;
1361
1362 qm->reserved = 0;
1363 /* Sanity checks */
1364 if (ctrl->qmenu == NULL ||
1365 i < ctrl->minimum || i > ctrl->maximum)
1366 return -EINVAL;
1367 /* Use mask to see if this menu item should be skipped */
1368 if (ctrl->menu_skip_mask & (1 << i))
1369 return -EINVAL;
1370 /* Empty menu items should also be skipped */
1371 if (ctrl->qmenu[i] == NULL || ctrl->qmenu[i][0] == '\0')
1372 return -EINVAL;
1373 strlcpy(qm->name, ctrl->qmenu[i], sizeof(qm->name));
1374 return 0;
1375}
1376EXPORT_SYMBOL(v4l2_querymenu);
1377
1378int v4l2_subdev_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qm)
1379{
1380 return v4l2_querymenu(sd->ctrl_handler, qm);
1381}
1382EXPORT_SYMBOL(v4l2_subdev_querymenu);
1383
1384
1385
1386/* Some general notes on the atomic requirements of VIDIOC_G/TRY/S_EXT_CTRLS:
1387
1388 It is not a fully atomic operation, just best-effort only. After all, if
1389 multiple controls have to be set through multiple i2c writes (for example)
1390 then some initial writes may succeed while others fail. Thus leaving the
1391 system in an inconsistent state. The question is how much effort you are
1392 willing to spend on trying to make something atomic that really isn't.
1393
1394 From the point of view of an application the main requirement is that
1395 when you call VIDIOC_S_EXT_CTRLS and some values are invalid then an
1396 error should be returned without actually affecting any controls.
1397
1398 If all the values are correct, then it is acceptable to just give up
1399 in case of low-level errors.
1400
1401 It is important though that the application can tell when only a partial
1402 configuration was done. The way we do that is through the error_idx field
1403 of struct v4l2_ext_controls: if that is equal to the count field then no
1404 controls were affected. Otherwise all controls before that index were
1405 successful in performing their 'get' or 'set' operation, the control at
1406 the given index failed, and you don't know what happened with the controls
1407 after the failed one. Since if they were part of a control cluster they
1408 could have been successfully processed (if a cluster member was encountered
1409 at index < error_idx), they could have failed (if a cluster member was at
1410 error_idx), or they may not have been processed yet (if the first cluster
1411 member appeared after error_idx).
1412
1413 It is all fairly theoretical, though. In practice all you can do is to
1414 bail out. If error_idx == count, then it is an application bug. If
1415 error_idx < count then it is only an application bug if the error code was
1416 EBUSY. That usually means that something started streaming just when you
1417 tried to set the controls. In all other cases it is a driver/hardware
1418 problem and all you can do is to retry or bail out.
1419
1420 Note that these rules do not apply to VIDIOC_TRY_EXT_CTRLS: since that
1421 never modifies controls the error_idx is just set to whatever control
1422 has an invalid value.
1423 */
1424
1425/* Prepare for the extended g/s/try functions.
1426 Find the controls in the control array and do some basic checks. */
1427static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
1428 struct v4l2_ext_controls *cs,
1429 struct ctrl_helper *helpers,
1430 bool try)
1431{
1432 u32 i;
1433
1434 for (i = 0; i < cs->count; i++) {
1435 struct v4l2_ext_control *c = &cs->controls[i];
1436 struct v4l2_ctrl *ctrl;
1437 u32 id = c->id & V4L2_CTRL_ID_MASK;
1438
1439 if (try)
1440 cs->error_idx = i;
1441
1442 if (cs->ctrl_class && V4L2_CTRL_ID2CLASS(id) != cs->ctrl_class)
1443 return -EINVAL;
1444
1445 /* Old-style private controls are not allowed for
1446 extended controls */
1447 if (id >= V4L2_CID_PRIVATE_BASE)
1448 return -EINVAL;
1449 ctrl = v4l2_ctrl_find(hdl, id);
1450 if (ctrl == NULL)
1451 return -EINVAL;
1452 if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED)
1453 return -EINVAL;
1454
1455 helpers[i].ctrl = ctrl;
1456 helpers[i].handled = false;
1457 }
1458 return 0;
1459}
1460
1461typedef int (*cluster_func)(struct v4l2_ext_control *c,
1462 struct v4l2_ctrl *ctrl);
1463
1464/* Walk over all controls in v4l2_ext_controls belonging to the same cluster
1465 and call the provided function. */
1466static int cluster_walk(unsigned from,
1467 struct v4l2_ext_controls *cs,
1468 struct ctrl_helper *helpers,
1469 cluster_func f)
1470{
1471 struct v4l2_ctrl **cluster = helpers[from].ctrl->cluster;
1472 int ret = 0;
1473 int i;
1474
1475 /* Find any controls from the same cluster and call the function */
1476 for (i = from; !ret && i < cs->count; i++) {
1477 struct v4l2_ctrl *ctrl = helpers[i].ctrl;
1478
1479 if (!helpers[i].handled && ctrl->cluster == cluster)
1480 ret = f(&cs->controls[i], ctrl);
1481 }
1482 return ret;
1483}
1484
1485static void cluster_done(unsigned from,
1486 struct v4l2_ext_controls *cs,
1487 struct ctrl_helper *helpers)
1488{
1489 struct v4l2_ctrl **cluster = helpers[from].ctrl->cluster;
1490 int i;
1491
1492 /* Find any controls from the same cluster and mark them as handled */
1493 for (i = from; i < cs->count; i++)
1494 if (helpers[i].ctrl->cluster == cluster)
1495 helpers[i].handled = true;
1496}
1497
1498/* Handles the corner case where cs->count == 0. It checks whether the
1499 specified control class exists. If that class ID is 0, then it checks
1500 whether there are any controls at all. */
1501static int class_check(struct v4l2_ctrl_handler *hdl, u32 ctrl_class)
1502{
1503 if (ctrl_class == 0)
1504 return list_empty(&hdl->ctrl_refs) ? -EINVAL : 0;
1505 return find_ref_lock(hdl, ctrl_class | 1) ? 0 : -EINVAL;
1506}
1507
1508
1509
1510/* Get extended controls. Allocates the helpers array if needed. */
1511int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs)
1512{
1513 struct ctrl_helper helper[4];
1514 struct ctrl_helper *helpers = helper;
1515 int ret;
1516 int i;
1517
1518 cs->error_idx = cs->count;
1519 cs->ctrl_class = V4L2_CTRL_ID2CLASS(cs->ctrl_class);
1520
1521 if (hdl == NULL)
1522 return -EINVAL;
1523
1524 if (cs->count == 0)
1525 return class_check(hdl, cs->ctrl_class);
1526
1527 if (cs->count > ARRAY_SIZE(helper)) {
1528 helpers = kmalloc(sizeof(helper[0]) * cs->count, GFP_KERNEL);
1529 if (helpers == NULL)
1530 return -ENOMEM;
1531 }
1532
1533 ret = prepare_ext_ctrls(hdl, cs, helpers, false);
1534
1535 for (i = 0; !ret && i < cs->count; i++)
1536 if (helpers[i].ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
1537 ret = -EACCES;
1538
1539 for (i = 0; !ret && i < cs->count; i++) {
1540 struct v4l2_ctrl *ctrl = helpers[i].ctrl;
1541 struct v4l2_ctrl *master = ctrl->cluster[0];
1542
1543 if (helpers[i].handled)
1544 continue;
1545
1546 cs->error_idx = i;
1547
1548 v4l2_ctrl_lock(master);
1549 /* g_volatile_ctrl will update the current control values */
1550 if (ctrl->is_volatile && master->ops->g_volatile_ctrl)
1551 ret = master->ops->g_volatile_ctrl(master);
1552 /* If OK, then copy the current control values to the caller */
1553 if (!ret)
1554 ret = cluster_walk(i, cs, helpers, cur_to_user);
1555 v4l2_ctrl_unlock(master);
1556 cluster_done(i, cs, helpers);
1557 }
1558
1559 if (cs->count > ARRAY_SIZE(helper))
1560 kfree(helpers);
1561 return ret;
1562}
1563EXPORT_SYMBOL(v4l2_g_ext_ctrls);
1564
1565int v4l2_subdev_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs)
1566{
1567 return v4l2_g_ext_ctrls(sd->ctrl_handler, cs);
1568}
1569EXPORT_SYMBOL(v4l2_subdev_g_ext_ctrls);
1570
1571/* Helper function to get a single control */
1572static int get_ctrl(struct v4l2_ctrl *ctrl, s32 *val)
1573{
1574 struct v4l2_ctrl *master = ctrl->cluster[0];
1575 int ret = 0;
1576
1577 if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
1578 return -EACCES;
1579
1580 v4l2_ctrl_lock(master);
1581 /* g_volatile_ctrl will update the current control values */
1582 if (ctrl->is_volatile && master->ops->g_volatile_ctrl)
1583 ret = master->ops->g_volatile_ctrl(master);
1584 *val = ctrl->cur.val;
1585 v4l2_ctrl_unlock(master);
1586 return ret;
1587}
1588
1589int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control)
1590{
1591 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id);
1592
1593 if (ctrl == NULL || !type_is_int(ctrl))
1594 return -EINVAL;
1595 return get_ctrl(ctrl, &control->value);
1596}
1597EXPORT_SYMBOL(v4l2_g_ctrl);
1598
1599int v4l2_subdev_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *control)
1600{
1601 return v4l2_g_ctrl(sd->ctrl_handler, control);
1602}
1603EXPORT_SYMBOL(v4l2_subdev_g_ctrl);
1604
1605s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl)
1606{
1607 s32 val = 0;
1608
1609 /* It's a driver bug if this happens. */
1610 WARN_ON(!type_is_int(ctrl));
1611 get_ctrl(ctrl, &val);
1612 return val;
1613}
1614EXPORT_SYMBOL(v4l2_ctrl_g_ctrl);
1615
1616
1617/* Core function that calls try/s_ctrl and ensures that the new value is
1618 copied to the current value on a set.
1619 Must be called with ctrl->handler->lock held. */
1620static int try_or_set_control_cluster(struct v4l2_ctrl *master, bool set)
1621{
1622 bool try = !set;
1623 int ret = 0;
1624 int i;
1625
1626 /* Go through the cluster and either validate the new value or
1627 (if no new value was set), copy the current value to the new
1628 value, ensuring a consistent view for the control ops when
1629 called. */
1630 for (i = 0; !ret && i < master->ncontrols; i++) {
1631 struct v4l2_ctrl *ctrl = master->cluster[i];
1632
1633 if (ctrl == NULL)
1634 continue;
1635
1636 if (ctrl->has_new) {
1637 /* Double check this: it may have changed since the
1638 last check in try_or_set_ext_ctrls(). */
1639 if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
1640 return -EBUSY;
1641
1642 /* Validate if required */
1643 if (!set)
1644 ret = validate_new(ctrl);
1645 continue;
1646 }
1647 /* No new value was set, so copy the current and force
1648 a call to try_ctrl later, since the values for the cluster
1649 may now have changed and the end result might be invalid. */
1650 try = true;
1651 cur_to_new(ctrl);
1652 }
1653
1654 /* For larger clusters you have to call try_ctrl again to
1655 verify that the controls are still valid after the
1656 'cur_to_new' above. */
1657 if (!ret && master->ops->try_ctrl && try)
1658 ret = master->ops->try_ctrl(master);
1659
1660 /* Don't set if there is no change */
1661 if (!ret && set && cluster_changed(master)) {
1662 ret = master->ops->s_ctrl(master);
1663 /* If OK, then make the new values permanent. */
1664 if (!ret)
1665 for (i = 0; i < master->ncontrols; i++)
1666 new_to_cur(master->cluster[i]);
1667 }
1668 return ret;
1669}
1670
1671/* Try or set controls. */
1672static int try_or_set_ext_ctrls(struct v4l2_ctrl_handler *hdl,
1673 struct v4l2_ext_controls *cs,
1674 struct ctrl_helper *helpers,
1675 bool set)
1676{
1677 unsigned i, j;
1678 int ret = 0;
1679
1680 cs->error_idx = cs->count;
1681 for (i = 0; i < cs->count; i++) {
1682 struct v4l2_ctrl *ctrl = helpers[i].ctrl;
1683
1684 if (!set)
1685 cs->error_idx = i;
1686
1687 if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
1688 return -EACCES;
1689 /* This test is also done in try_set_control_cluster() which
1690 is called in atomic context, so that has the final say,
1691 but it makes sense to do an up-front check as well. Once
1692 an error occurs in try_set_control_cluster() some other
1693 controls may have been set already and we want to do a
1694 best-effort to avoid that. */
1695 if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
1696 return -EBUSY;
1697 }
1698
1699 for (i = 0; !ret && i < cs->count; i++) {
1700 struct v4l2_ctrl *ctrl = helpers[i].ctrl;
1701 struct v4l2_ctrl *master = ctrl->cluster[0];
1702
1703 cs->error_idx = i;
1704
1705 if (helpers[i].handled)
1706 continue;
1707
1708 v4l2_ctrl_lock(ctrl);
1709
1710 /* Reset the 'has_new' flags of the cluster */
1711 for (j = 0; j < master->ncontrols; j++)
1712 if (master->cluster[j])
1713 master->cluster[j]->has_new = 0;
1714
1715 /* Copy the new caller-supplied control values.
1716 user_to_new() sets 'has_new' to 1. */
1717 ret = cluster_walk(i, cs, helpers, user_to_new);
1718
1719 if (!ret)
1720 ret = try_or_set_control_cluster(master, set);
1721
1722 /* Copy the new values back to userspace. */
1723 if (!ret)
1724 ret = cluster_walk(i, cs, helpers, new_to_user);
1725
1726 v4l2_ctrl_unlock(ctrl);
1727 cluster_done(i, cs, helpers);
1728 }
1729 return ret;
1730}
1731
1732/* Try or try-and-set controls */
1733static int try_set_ext_ctrls(struct v4l2_ctrl_handler *hdl,
1734 struct v4l2_ext_controls *cs,
1735 bool set)
1736{
1737 struct ctrl_helper helper[4];
1738 struct ctrl_helper *helpers = helper;
1739 int ret;
1740 int i;
1741
1742 cs->error_idx = cs->count;
1743 cs->ctrl_class = V4L2_CTRL_ID2CLASS(cs->ctrl_class);
1744
1745 if (hdl == NULL)
1746 return -EINVAL;
1747
1748 if (cs->count == 0)
1749 return class_check(hdl, cs->ctrl_class);
1750
1751 if (cs->count > ARRAY_SIZE(helper)) {
1752 helpers = kmalloc(sizeof(helper[0]) * cs->count, GFP_KERNEL);
1753 if (!helpers)
1754 return -ENOMEM;
1755 }
1756 ret = prepare_ext_ctrls(hdl, cs, helpers, !set);
1757 if (ret)
1758 goto free;
1759
1760 /* First 'try' all controls and abort on error */
1761 ret = try_or_set_ext_ctrls(hdl, cs, helpers, false);
1762 /* If this is a 'set' operation and the initial 'try' failed,
1763 then set error_idx to count to tell the application that no
1764 controls changed value yet. */
1765 if (set)
1766 cs->error_idx = cs->count;
1767 if (!ret && set) {
1768 /* Reset 'handled' state */
1769 for (i = 0; i < cs->count; i++)
1770 helpers[i].handled = false;
1771 ret = try_or_set_ext_ctrls(hdl, cs, helpers, true);
1772 }
1773
1774free:
1775 if (cs->count > ARRAY_SIZE(helper))
1776 kfree(helpers);
1777 return ret;
1778}
1779
1780int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs)
1781{
1782 return try_set_ext_ctrls(hdl, cs, false);
1783}
1784EXPORT_SYMBOL(v4l2_try_ext_ctrls);
1785
1786int v4l2_s_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs)
1787{
1788 return try_set_ext_ctrls(hdl, cs, true);
1789}
1790EXPORT_SYMBOL(v4l2_s_ext_ctrls);
1791
1792int v4l2_subdev_try_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs)
1793{
1794 return try_set_ext_ctrls(sd->ctrl_handler, cs, false);
1795}
1796EXPORT_SYMBOL(v4l2_subdev_try_ext_ctrls);
1797
1798int v4l2_subdev_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs)
1799{
1800 return try_set_ext_ctrls(sd->ctrl_handler, cs, true);
1801}
1802EXPORT_SYMBOL(v4l2_subdev_s_ext_ctrls);
1803
1804/* Helper function for VIDIOC_S_CTRL compatibility */
1805static int set_ctrl(struct v4l2_ctrl *ctrl, s32 *val)
1806{
1807 struct v4l2_ctrl *master = ctrl->cluster[0];
1808 int ret;
1809 int i;
1810
1811 v4l2_ctrl_lock(ctrl);
1812
1813 /* Reset the 'has_new' flags of the cluster */
1814 for (i = 0; i < master->ncontrols; i++)
1815 if (master->cluster[i])
1816 master->cluster[i]->has_new = 0;
1817
1818 ctrl->val = *val;
1819 ctrl->has_new = 1;
1820 ret = try_or_set_control_cluster(master, false);
1821 if (!ret)
1822 ret = try_or_set_control_cluster(master, true);
1823 *val = ctrl->cur.val;
1824 v4l2_ctrl_unlock(ctrl);
1825 return ret;
1826}
1827
1828int v4l2_s_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control)
1829{
1830 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id);
1831
1832 if (ctrl == NULL || !type_is_int(ctrl))
1833 return -EINVAL;
1834
1835 return set_ctrl(ctrl, &control->value);
1836}
1837EXPORT_SYMBOL(v4l2_s_ctrl);
1838
1839int v4l2_subdev_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *control)
1840{
1841 return v4l2_s_ctrl(sd->ctrl_handler, control);
1842}
1843EXPORT_SYMBOL(v4l2_subdev_s_ctrl);
1844
1845int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
1846{
1847 /* It's a driver bug if this happens. */
1848 WARN_ON(!type_is_int(ctrl));
1849 return set_ctrl(ctrl, &val);
1850}
1851EXPORT_SYMBOL(v4l2_ctrl_s_ctrl);
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 249af6a1d56..cb77197d480 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -428,8 +428,12 @@ static int __video_register_device(struct video_device *vdev, int type, int nr,
428 428
429 vdev->vfl_type = type; 429 vdev->vfl_type = type;
430 vdev->cdev = NULL; 430 vdev->cdev = NULL;
431 if (vdev->v4l2_dev && vdev->v4l2_dev->dev) 431 if (vdev->v4l2_dev) {
432 vdev->parent = vdev->v4l2_dev->dev; 432 if (vdev->v4l2_dev->dev)
433 vdev->parent = vdev->v4l2_dev->dev;
434 if (vdev->ctrl_handler == NULL)
435 vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler;
436 }
433 437
434 /* Part 2: find a free minor, device node number and device index. */ 438 /* Part 2: find a free minor, device node number and device index. */
435#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES 439#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES
diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
index 5a7dc4afe92..0b08f96b74a 100644
--- a/drivers/media/video/v4l2-device.c
+++ b/drivers/media/video/v4l2-device.c
@@ -26,6 +26,7 @@
26#endif 26#endif
27#include <linux/videodev2.h> 27#include <linux/videodev2.h>
28#include <media/v4l2-device.h> 28#include <media/v4l2-device.h>
29#include <media/v4l2-ctrls.h>
29 30
30int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) 31int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
31{ 32{
@@ -115,6 +116,8 @@ EXPORT_SYMBOL_GPL(v4l2_device_unregister);
115int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, 116int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
116 struct v4l2_subdev *sd) 117 struct v4l2_subdev *sd)
117{ 118{
119 int err;
120
118 /* Check for valid input */ 121 /* Check for valid input */
119 if (v4l2_dev == NULL || sd == NULL || !sd->name[0]) 122 if (v4l2_dev == NULL || sd == NULL || !sd->name[0])
120 return -EINVAL; 123 return -EINVAL;
@@ -122,6 +125,10 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
122 WARN_ON(sd->v4l2_dev != NULL); 125 WARN_ON(sd->v4l2_dev != NULL);
123 if (!try_module_get(sd->owner)) 126 if (!try_module_get(sd->owner))
124 return -ENODEV; 127 return -ENODEV;
128 /* This just returns 0 if either of the two args is NULL */
129 err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler);
130 if (err)
131 return err;
125 sd->v4l2_dev = v4l2_dev; 132 sd->v4l2_dev = v4l2_dev;
126 spin_lock(&v4l2_dev->lock); 133 spin_lock(&v4l2_dev->lock);
127 list_add_tail(&sd->list, &v4l2_dev->subdevs); 134 list_add_tail(&sd->list, &v4l2_dev->subdevs);
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 0eeceae5032..dd9283fcb56 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -26,6 +26,7 @@
26#endif 26#endif
27#include <media/v4l2-common.h> 27#include <media/v4l2-common.h>
28#include <media/v4l2-ioctl.h> 28#include <media/v4l2-ioctl.h>
29#include <media/v4l2-ctrls.h>
29#include <media/v4l2-fh.h> 30#include <media/v4l2-fh.h>
30#include <media/v4l2-event.h> 31#include <media/v4l2-event.h>
31#include <media/v4l2-chip-ident.h> 32#include <media/v4l2-chip-ident.h>
@@ -1259,9 +1260,12 @@ static long __video_do_ioctl(struct file *file,
1259 { 1260 {
1260 struct v4l2_queryctrl *p = arg; 1261 struct v4l2_queryctrl *p = arg;
1261 1262
1262 if (!ops->vidioc_queryctrl) 1263 if (vfd->ctrl_handler)
1264 ret = v4l2_queryctrl(vfd->ctrl_handler, p);
1265 else if (ops->vidioc_queryctrl)
1266 ret = ops->vidioc_queryctrl(file, fh, p);
1267 else
1263 break; 1268 break;
1264 ret = ops->vidioc_queryctrl(file, fh, p);
1265 if (!ret) 1269 if (!ret)
1266 dbgarg(cmd, "id=0x%x, type=%d, name=%s, min/max=%d/%d, " 1270 dbgarg(cmd, "id=0x%x, type=%d, name=%s, min/max=%d/%d, "
1267 "step=%d, default=%d, flags=0x%08x\n", 1271 "step=%d, default=%d, flags=0x%08x\n",
@@ -1276,7 +1280,9 @@ static long __video_do_ioctl(struct file *file,
1276 { 1280 {
1277 struct v4l2_control *p = arg; 1281 struct v4l2_control *p = arg;
1278 1282
1279 if (ops->vidioc_g_ctrl) 1283 if (vfd->ctrl_handler)
1284 ret = v4l2_g_ctrl(vfd->ctrl_handler, p);
1285 else if (ops->vidioc_g_ctrl)
1280 ret = ops->vidioc_g_ctrl(file, fh, p); 1286 ret = ops->vidioc_g_ctrl(file, fh, p);
1281 else if (ops->vidioc_g_ext_ctrls) { 1287 else if (ops->vidioc_g_ext_ctrls) {
1282 struct v4l2_ext_controls ctrls; 1288 struct v4l2_ext_controls ctrls;
@@ -1306,11 +1312,16 @@ static long __video_do_ioctl(struct file *file,
1306 struct v4l2_ext_controls ctrls; 1312 struct v4l2_ext_controls ctrls;
1307 struct v4l2_ext_control ctrl; 1313 struct v4l2_ext_control ctrl;
1308 1314
1309 if (!ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls) 1315 if (!vfd->ctrl_handler &&
1316 !ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)
1310 break; 1317 break;
1311 1318
1312 dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value); 1319 dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
1313 1320
1321 if (vfd->ctrl_handler) {
1322 ret = v4l2_s_ctrl(vfd->ctrl_handler, p);
1323 break;
1324 }
1314 if (ops->vidioc_s_ctrl) { 1325 if (ops->vidioc_s_ctrl) {
1315 ret = ops->vidioc_s_ctrl(file, fh, p); 1326 ret = ops->vidioc_s_ctrl(file, fh, p);
1316 break; 1327 break;
@@ -1332,10 +1343,12 @@ static long __video_do_ioctl(struct file *file,
1332 struct v4l2_ext_controls *p = arg; 1343 struct v4l2_ext_controls *p = arg;
1333 1344
1334 p->error_idx = p->count; 1345 p->error_idx = p->count;
1335 if (!ops->vidioc_g_ext_ctrls) 1346 if (vfd->ctrl_handler)
1336 break; 1347 ret = v4l2_g_ext_ctrls(vfd->ctrl_handler, p);
1337 if (check_ext_ctrls(p, 0)) 1348 else if (ops->vidioc_g_ext_ctrls && check_ext_ctrls(p, 0))
1338 ret = ops->vidioc_g_ext_ctrls(file, fh, p); 1349 ret = ops->vidioc_g_ext_ctrls(file, fh, p);
1350 else
1351 break;
1339 v4l_print_ext_ctrls(cmd, vfd, p, !ret); 1352 v4l_print_ext_ctrls(cmd, vfd, p, !ret);
1340 break; 1353 break;
1341 } 1354 }
@@ -1344,10 +1357,12 @@ static long __video_do_ioctl(struct file *file,
1344 struct v4l2_ext_controls *p = arg; 1357 struct v4l2_ext_controls *p = arg;
1345 1358
1346 p->error_idx = p->count; 1359 p->error_idx = p->count;
1347 if (!ops->vidioc_s_ext_ctrls) 1360 if (!vfd->ctrl_handler && !ops->vidioc_s_ext_ctrls)
1348 break; 1361 break;
1349 v4l_print_ext_ctrls(cmd, vfd, p, 1); 1362 v4l_print_ext_ctrls(cmd, vfd, p, 1);
1350 if (check_ext_ctrls(p, 0)) 1363 if (vfd->ctrl_handler)
1364 ret = v4l2_s_ext_ctrls(vfd->ctrl_handler, p);
1365 else if (check_ext_ctrls(p, 0))
1351 ret = ops->vidioc_s_ext_ctrls(file, fh, p); 1366 ret = ops->vidioc_s_ext_ctrls(file, fh, p);
1352 break; 1367 break;
1353 } 1368 }
@@ -1356,10 +1371,12 @@ static long __video_do_ioctl(struct file *file,
1356 struct v4l2_ext_controls *p = arg; 1371 struct v4l2_ext_controls *p = arg;
1357 1372
1358 p->error_idx = p->count; 1373 p->error_idx = p->count;
1359 if (!ops->vidioc_try_ext_ctrls) 1374 if (!vfd->ctrl_handler && !ops->vidioc_try_ext_ctrls)
1360 break; 1375 break;
1361 v4l_print_ext_ctrls(cmd, vfd, p, 1); 1376 v4l_print_ext_ctrls(cmd, vfd, p, 1);
1362 if (check_ext_ctrls(p, 0)) 1377 if (vfd->ctrl_handler)
1378 ret = v4l2_try_ext_ctrls(vfd->ctrl_handler, p);
1379 else if (check_ext_ctrls(p, 0))
1363 ret = ops->vidioc_try_ext_ctrls(file, fh, p); 1380 ret = ops->vidioc_try_ext_ctrls(file, fh, p);
1364 break; 1381 break;
1365 } 1382 }
@@ -1367,9 +1384,12 @@ static long __video_do_ioctl(struct file *file,
1367 { 1384 {
1368 struct v4l2_querymenu *p = arg; 1385 struct v4l2_querymenu *p = arg;
1369 1386
1370 if (!ops->vidioc_querymenu) 1387 if (vfd->ctrl_handler)
1388 ret = v4l2_querymenu(vfd->ctrl_handler, p);
1389 else if (ops->vidioc_querymenu)
1390 ret = ops->vidioc_querymenu(file, fh, p);
1391 else
1371 break; 1392 break;
1372 ret = ops->vidioc_querymenu(file, fh, p);
1373 if (!ret) 1393 if (!ret)
1374 dbgarg(cmd, "id=0x%x, index=%d, name=%s\n", 1394 dbgarg(cmd, "id=0x%x, index=%d, name=%s\n",
1375 p->id, p->index, p->name); 1395 p->id, p->index, p->name);
diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c
index a11b99b4226..d5965543eca 100644
--- a/drivers/media/video/wm8739.c
+++ b/drivers/media/video/wm8739.c
@@ -27,11 +27,11 @@
27#include <linux/ioctl.h> 27#include <linux/ioctl.h>
28#include <asm/uaccess.h> 28#include <asm/uaccess.h>
29#include <linux/i2c.h> 29#include <linux/i2c.h>
30#include <linux/i2c-id.h>
31#include <linux/videodev2.h> 30#include <linux/videodev2.h>
32#include <media/v4l2-device.h> 31#include <media/v4l2-device.h>
33#include <media/v4l2-chip-ident.h> 32#include <media/v4l2-chip-ident.h>
34#include <media/v4l2-i2c-drv.h> 33#include <media/v4l2-i2c-drv.h>
34#include <media/v4l2-ctrls.h>
35 35
36MODULE_DESCRIPTION("wm8739 driver"); 36MODULE_DESCRIPTION("wm8739 driver");
37MODULE_AUTHOR("T. Adachi, Hans Verkuil"); 37MODULE_AUTHOR("T. Adachi, Hans Verkuil");
@@ -54,12 +54,14 @@ enum {
54 54
55struct wm8739_state { 55struct wm8739_state {
56 struct v4l2_subdev sd; 56 struct v4l2_subdev sd;
57 struct v4l2_ctrl_handler hdl;
58 struct {
59 /* audio cluster */
60 struct v4l2_ctrl *volume;
61 struct v4l2_ctrl *mute;
62 struct v4l2_ctrl *balance;
63 };
57 u32 clock_freq; 64 u32 clock_freq;
58 u8 muted;
59 u16 volume;
60 u16 balance;
61 u8 vol_l; /* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
62 u8 vol_r; /* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
63}; 65};
64 66
65static inline struct wm8739_state *to_state(struct v4l2_subdev *sd) 67static inline struct wm8739_state *to_state(struct v4l2_subdev *sd)
@@ -67,6 +69,11 @@ static inline struct wm8739_state *to_state(struct v4l2_subdev *sd)
67 return container_of(sd, struct wm8739_state, sd); 69 return container_of(sd, struct wm8739_state, sd);
68} 70}
69 71
72static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
73{
74 return &container_of(ctrl->handler, struct wm8739_state, hdl)->sd;
75}
76
70/* ------------------------------------------------------------------------ */ 77/* ------------------------------------------------------------------------ */
71 78
72static int wm8739_write(struct v4l2_subdev *sd, int reg, u16 val) 79static int wm8739_write(struct v4l2_subdev *sd, int reg, u16 val)
@@ -89,58 +96,17 @@ static int wm8739_write(struct v4l2_subdev *sd, int reg, u16 val)
89 return -1; 96 return -1;
90} 97}
91 98
92/* write regs to set audio volume etc */ 99static int wm8739_s_ctrl(struct v4l2_ctrl *ctrl)
93static void wm8739_set_audio(struct v4l2_subdev *sd)
94{
95 struct wm8739_state *state = to_state(sd);
96 u16 mute = state->muted ? 0x80 : 0;
97
98 /* Volume setting: bits 0-4, 0x1f = 12 dB, 0x00 = -34.5 dB
99 * Default setting: 0x17 = 0 dB
100 */
101 wm8739_write(sd, R0, (state->vol_l & 0x1f) | mute);
102 wm8739_write(sd, R1, (state->vol_r & 0x1f) | mute);
103}
104
105static int wm8739_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
106{
107 struct wm8739_state *state = to_state(sd);
108
109 switch (ctrl->id) {
110 case V4L2_CID_AUDIO_MUTE:
111 ctrl->value = state->muted;
112 break;
113
114 case V4L2_CID_AUDIO_VOLUME:
115 ctrl->value = state->volume;
116 break;
117
118 case V4L2_CID_AUDIO_BALANCE:
119 ctrl->value = state->balance;
120 break;
121
122 default:
123 return -EINVAL;
124 }
125 return 0;
126}
127
128static int wm8739_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
129{ 100{
101 struct v4l2_subdev *sd = to_sd(ctrl);
130 struct wm8739_state *state = to_state(sd); 102 struct wm8739_state *state = to_state(sd);
131 unsigned int work_l, work_r; 103 unsigned int work_l, work_r;
104 u8 vol_l; /* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
105 u8 vol_r; /* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
106 u16 mute;
132 107
133 switch (ctrl->id) { 108 switch (ctrl->id) {
134 case V4L2_CID_AUDIO_MUTE:
135 state->muted = ctrl->value;
136 break;
137
138 case V4L2_CID_AUDIO_VOLUME: 109 case V4L2_CID_AUDIO_VOLUME:
139 state->volume = ctrl->value;
140 break;
141
142 case V4L2_CID_AUDIO_BALANCE:
143 state->balance = ctrl->value;
144 break; 110 break;
145 111
146 default: 112 default:
@@ -148,52 +114,25 @@ static int wm8739_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
148 } 114 }
149 115
150 /* normalize ( 65535 to 0 -> 31 to 0 (12dB to -34.5dB) ) */ 116 /* normalize ( 65535 to 0 -> 31 to 0 (12dB to -34.5dB) ) */
151 work_l = (min(65536 - state->balance, 32768) * state->volume) / 32768; 117 work_l = (min(65536 - state->balance->val, 32768) * state->volume->val) / 32768;
152 work_r = (min(state->balance, (u16)32768) * state->volume) / 32768; 118 work_r = (min(state->balance->val, 32768) * state->volume->val) / 32768;
153 119
154 state->vol_l = (long)work_l * 31 / 65535; 120 vol_l = (long)work_l * 31 / 65535;
155 state->vol_r = (long)work_r * 31 / 65535; 121 vol_r = (long)work_r * 31 / 65535;
156 122
157 /* set audio volume etc. */ 123 /* set audio volume etc. */
158 wm8739_set_audio(sd); 124 mute = state->mute->val ? 0x80 : 0;
125
126 /* Volume setting: bits 0-4, 0x1f = 12 dB, 0x00 = -34.5 dB
127 * Default setting: 0x17 = 0 dB
128 */
129 wm8739_write(sd, R0, (vol_l & 0x1f) | mute);
130 wm8739_write(sd, R1, (vol_r & 0x1f) | mute);
159 return 0; 131 return 0;
160} 132}
161 133
162/* ------------------------------------------------------------------------ */ 134/* ------------------------------------------------------------------------ */
163 135
164static struct v4l2_queryctrl wm8739_qctrl[] = {
165 {
166 .id = V4L2_CID_AUDIO_VOLUME,
167 .name = "Volume",
168 .minimum = 0,
169 .maximum = 65535,
170 .step = 65535/100,
171 .default_value = 58880,
172 .flags = 0,
173 .type = V4L2_CTRL_TYPE_INTEGER,
174 }, {
175 .id = V4L2_CID_AUDIO_MUTE,
176 .name = "Mute",
177 .minimum = 0,
178 .maximum = 1,
179 .step = 1,
180 .default_value = 1,
181 .flags = 0,
182 .type = V4L2_CTRL_TYPE_BOOLEAN,
183 }, {
184 .id = V4L2_CID_AUDIO_BALANCE,
185 .name = "Balance",
186 .minimum = 0,
187 .maximum = 65535,
188 .step = 65535/100,
189 .default_value = 32768,
190 .flags = 0,
191 .type = V4L2_CTRL_TYPE_INTEGER,
192 }
193};
194
195/* ------------------------------------------------------------------------ */
196
197static int wm8739_s_clock_freq(struct v4l2_subdev *sd, u32 audiofreq) 136static int wm8739_s_clock_freq(struct v4l2_subdev *sd, u32 audiofreq)
198{ 137{
199 struct wm8739_state *state = to_state(sd); 138 struct wm8739_state *state = to_state(sd);
@@ -222,18 +161,6 @@ static int wm8739_s_clock_freq(struct v4l2_subdev *sd, u32 audiofreq)
222 return 0; 161 return 0;
223} 162}
224 163
225static int wm8739_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
226{
227 int i;
228
229 for (i = 0; i < ARRAY_SIZE(wm8739_qctrl); i++)
230 if (qc->id && qc->id == wm8739_qctrl[i].id) {
231 memcpy(qc, &wm8739_qctrl[i], sizeof(*qc));
232 return 0;
233 }
234 return -EINVAL;
235}
236
237static int wm8739_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) 164static int wm8739_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
238{ 165{
239 struct i2c_client *client = v4l2_get_subdevdata(sd); 166 struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -246,21 +173,26 @@ static int wm8739_log_status(struct v4l2_subdev *sd)
246 struct wm8739_state *state = to_state(sd); 173 struct wm8739_state *state = to_state(sd);
247 174
248 v4l2_info(sd, "Frequency: %u Hz\n", state->clock_freq); 175 v4l2_info(sd, "Frequency: %u Hz\n", state->clock_freq);
249 v4l2_info(sd, "Volume L: %02x%s\n", state->vol_l & 0x1f, 176 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
250 state->muted ? " (muted)" : "");
251 v4l2_info(sd, "Volume R: %02x%s\n", state->vol_r & 0x1f,
252 state->muted ? " (muted)" : "");
253 return 0; 177 return 0;
254} 178}
255 179
256/* ----------------------------------------------------------------------- */ 180/* ----------------------------------------------------------------------- */
257 181
182static const struct v4l2_ctrl_ops wm8739_ctrl_ops = {
183 .s_ctrl = wm8739_s_ctrl,
184};
185
258static const struct v4l2_subdev_core_ops wm8739_core_ops = { 186static const struct v4l2_subdev_core_ops wm8739_core_ops = {
259 .log_status = wm8739_log_status, 187 .log_status = wm8739_log_status,
260 .g_chip_ident = wm8739_g_chip_ident, 188 .g_chip_ident = wm8739_g_chip_ident,
261 .queryctrl = wm8739_queryctrl, 189 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
262 .g_ctrl = wm8739_g_ctrl, 190 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
263 .s_ctrl = wm8739_s_ctrl, 191 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
192 .g_ctrl = v4l2_subdev_g_ctrl,
193 .s_ctrl = v4l2_subdev_s_ctrl,
194 .queryctrl = v4l2_subdev_queryctrl,
195 .querymenu = v4l2_subdev_querymenu,
264}; 196};
265 197
266static const struct v4l2_subdev_audio_ops wm8739_audio_ops = { 198static const struct v4l2_subdev_audio_ops wm8739_audio_ops = {
@@ -289,17 +221,28 @@ static int wm8739_probe(struct i2c_client *client,
289 v4l_info(client, "chip found @ 0x%x (%s)\n", 221 v4l_info(client, "chip found @ 0x%x (%s)\n",
290 client->addr << 1, client->adapter->name); 222 client->addr << 1, client->adapter->name);
291 223
292 state = kmalloc(sizeof(struct wm8739_state), GFP_KERNEL); 224 state = kzalloc(sizeof(struct wm8739_state), GFP_KERNEL);
293 if (state == NULL) 225 if (state == NULL)
294 return -ENOMEM; 226 return -ENOMEM;
295 sd = &state->sd; 227 sd = &state->sd;
296 v4l2_i2c_subdev_init(sd, client, &wm8739_ops); 228 v4l2_i2c_subdev_init(sd, client, &wm8739_ops);
297 state->vol_l = 0x17; /* 0dB */ 229 v4l2_ctrl_handler_init(&state->hdl, 2);
298 state->vol_r = 0x17; /* 0dB */ 230 state->volume = v4l2_ctrl_new_std(&state->hdl, &wm8739_ctrl_ops,
299 state->muted = 0; 231 V4L2_CID_AUDIO_VOLUME, 0, 65535, 65535 / 100, 50736);
300 state->balance = 32768; 232 state->mute = v4l2_ctrl_new_std(&state->hdl, &wm8739_ctrl_ops,
301 /* normalize (12dB(31) to -34.5dB(0) [0dB(23)] -> 65535 to 0) */ 233 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
302 state->volume = ((long)state->vol_l + 1) * 65535 / 31; 234 state->balance = v4l2_ctrl_new_std(&state->hdl, &wm8739_ctrl_ops,
235 V4L2_CID_AUDIO_BALANCE, 0, 65535, 65535 / 100, 32768);
236 sd->ctrl_handler = &state->hdl;
237 if (state->hdl.error) {
238 int err = state->hdl.error;
239
240 v4l2_ctrl_handler_free(&state->hdl);
241 kfree(state);
242 return err;
243 }
244 v4l2_ctrl_cluster(3, &state->volume);
245
303 state->clock_freq = 48000; 246 state->clock_freq = 48000;
304 247
305 /* Initialize wm8739 */ 248 /* Initialize wm8739 */
@@ -318,15 +261,17 @@ static int wm8739_probe(struct i2c_client *client,
318 /* activate */ 261 /* activate */
319 wm8739_write(sd, R9, 0x001); 262 wm8739_write(sd, R9, 0x001);
320 /* set volume/mute */ 263 /* set volume/mute */
321 wm8739_set_audio(sd); 264 v4l2_ctrl_handler_setup(&state->hdl);
322 return 0; 265 return 0;
323} 266}
324 267
325static int wm8739_remove(struct i2c_client *client) 268static int wm8739_remove(struct i2c_client *client)
326{ 269{
327 struct v4l2_subdev *sd = i2c_get_clientdata(client); 270 struct v4l2_subdev *sd = i2c_get_clientdata(client);
271 struct wm8739_state *state = to_state(sd);
328 272
329 v4l2_device_unregister_subdev(sd); 273 v4l2_device_unregister_subdev(sd);
274 v4l2_ctrl_handler_free(&state->hdl);
330 kfree(to_state(sd)); 275 kfree(to_state(sd));
331 return 0; 276 return 0;
332} 277}
diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c
index 5c2ba599c0c..23bad3fd6dc 100644
--- a/drivers/media/video/wm8775.c
+++ b/drivers/media/video/wm8775.c
@@ -35,6 +35,7 @@
35#include <linux/videodev2.h> 35#include <linux/videodev2.h>
36#include <media/v4l2-device.h> 36#include <media/v4l2-device.h>
37#include <media/v4l2-chip-ident.h> 37#include <media/v4l2-chip-ident.h>
38#include <media/v4l2-ctrls.h>
38#include <media/v4l2-i2c-drv.h> 39#include <media/v4l2-i2c-drv.h>
39 40
40MODULE_DESCRIPTION("wm8775 driver"); 41MODULE_DESCRIPTION("wm8775 driver");
@@ -53,8 +54,9 @@ enum {
53 54
54struct wm8775_state { 55struct wm8775_state {
55 struct v4l2_subdev sd; 56 struct v4l2_subdev sd;
57 struct v4l2_ctrl_handler hdl;
58 struct v4l2_ctrl *mute;
56 u8 input; /* Last selected input (0-0xf) */ 59 u8 input; /* Last selected input (0-0xf) */
57 u8 muted;
58}; 60};
59 61
60static inline struct wm8775_state *to_state(struct v4l2_subdev *sd) 62static inline struct wm8775_state *to_state(struct v4l2_subdev *sd)
@@ -62,6 +64,11 @@ static inline struct wm8775_state *to_state(struct v4l2_subdev *sd)
62 return container_of(sd, struct wm8775_state, sd); 64 return container_of(sd, struct wm8775_state, sd);
63} 65}
64 66
67static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
68{
69 return &container_of(ctrl->handler, struct wm8775_state, hdl)->sd;
70}
71
65static int wm8775_write(struct v4l2_subdev *sd, int reg, u16 val) 72static int wm8775_write(struct v4l2_subdev *sd, int reg, u16 val)
66{ 73{
67 struct i2c_client *client = v4l2_get_subdevdata(sd); 74 struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -95,7 +102,7 @@ static int wm8775_s_routing(struct v4l2_subdev *sd,
95 return -EINVAL; 102 return -EINVAL;
96 } 103 }
97 state->input = input; 104 state->input = input;
98 if (state->muted) 105 if (!v4l2_ctrl_g_ctrl(state->mute))
99 return 0; 106 return 0;
100 wm8775_write(sd, R21, 0x0c0); 107 wm8775_write(sd, R21, 0x0c0);
101 wm8775_write(sd, R14, 0x1d4); 108 wm8775_write(sd, R14, 0x1d4);
@@ -104,29 +111,21 @@ static int wm8775_s_routing(struct v4l2_subdev *sd,
104 return 0; 111 return 0;
105} 112}
106 113
107static int wm8775_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 114static int wm8775_s_ctrl(struct v4l2_ctrl *ctrl)
108{ 115{
116 struct v4l2_subdev *sd = to_sd(ctrl);
109 struct wm8775_state *state = to_state(sd); 117 struct wm8775_state *state = to_state(sd);
110 118
111 if (ctrl->id != V4L2_CID_AUDIO_MUTE) 119 switch (ctrl->id) {
112 return -EINVAL; 120 case V4L2_CID_AUDIO_MUTE:
113 ctrl->value = state->muted; 121 wm8775_write(sd, R21, 0x0c0);
114 return 0; 122 wm8775_write(sd, R14, 0x1d4);
115} 123 wm8775_write(sd, R15, 0x1d4);
116 124 if (!ctrl->val)
117static int wm8775_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 125 wm8775_write(sd, R21, 0x100 + state->input);
118{ 126 return 0;
119 struct wm8775_state *state = to_state(sd); 127 }
120 128 return -EINVAL;
121 if (ctrl->id != V4L2_CID_AUDIO_MUTE)
122 return -EINVAL;
123 state->muted = ctrl->value;
124 wm8775_write(sd, R21, 0x0c0);
125 wm8775_write(sd, R14, 0x1d4);
126 wm8775_write(sd, R15, 0x1d4);
127 if (!state->muted)
128 wm8775_write(sd, R21, 0x100 + state->input);
129 return 0;
130} 129}
131 130
132static int wm8775_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) 131static int wm8775_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
@@ -140,8 +139,8 @@ static int wm8775_log_status(struct v4l2_subdev *sd)
140{ 139{
141 struct wm8775_state *state = to_state(sd); 140 struct wm8775_state *state = to_state(sd);
142 141
143 v4l2_info(sd, "Input: %d%s\n", state->input, 142 v4l2_info(sd, "Input: %d\n", state->input);
144 state->muted ? " (muted)" : ""); 143 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
145 return 0; 144 return 0;
146} 145}
147 146
@@ -162,11 +161,20 @@ static int wm8775_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *fre
162 161
163/* ----------------------------------------------------------------------- */ 162/* ----------------------------------------------------------------------- */
164 163
164static const struct v4l2_ctrl_ops wm8775_ctrl_ops = {
165 .s_ctrl = wm8775_s_ctrl,
166};
167
165static const struct v4l2_subdev_core_ops wm8775_core_ops = { 168static const struct v4l2_subdev_core_ops wm8775_core_ops = {
166 .log_status = wm8775_log_status, 169 .log_status = wm8775_log_status,
167 .g_chip_ident = wm8775_g_chip_ident, 170 .g_chip_ident = wm8775_g_chip_ident,
168 .g_ctrl = wm8775_g_ctrl, 171 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
169 .s_ctrl = wm8775_s_ctrl, 172 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
173 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
174 .g_ctrl = v4l2_subdev_g_ctrl,
175 .s_ctrl = v4l2_subdev_s_ctrl,
176 .queryctrl = v4l2_subdev_queryctrl,
177 .querymenu = v4l2_subdev_querymenu,
170}; 178};
171 179
172static const struct v4l2_subdev_tuner_ops wm8775_tuner_ops = { 180static const struct v4l2_subdev_tuner_ops wm8775_tuner_ops = {
@@ -205,13 +213,24 @@ static int wm8775_probe(struct i2c_client *client,
205 v4l_info(client, "chip found @ 0x%02x (%s)\n", 213 v4l_info(client, "chip found @ 0x%02x (%s)\n",
206 client->addr << 1, client->adapter->name); 214 client->addr << 1, client->adapter->name);
207 215
208 state = kmalloc(sizeof(struct wm8775_state), GFP_KERNEL); 216 state = kzalloc(sizeof(struct wm8775_state), GFP_KERNEL);
209 if (state == NULL) 217 if (state == NULL)
210 return -ENOMEM; 218 return -ENOMEM;
211 sd = &state->sd; 219 sd = &state->sd;
212 v4l2_i2c_subdev_init(sd, client, &wm8775_ops); 220 v4l2_i2c_subdev_init(sd, client, &wm8775_ops);
213 state->input = 2; 221 state->input = 2;
214 state->muted = 0; 222
223 v4l2_ctrl_handler_init(&state->hdl, 1);
224 state->mute = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
225 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
226 sd->ctrl_handler = &state->hdl;
227 if (state->hdl.error) {
228 int err = state->hdl.error;
229
230 v4l2_ctrl_handler_free(&state->hdl);
231 kfree(state);
232 return err;
233 }
215 234
216 /* Initialize wm8775 */ 235 /* Initialize wm8775 */
217 236
@@ -248,9 +267,11 @@ static int wm8775_probe(struct i2c_client *client,
248static int wm8775_remove(struct i2c_client *client) 267static int wm8775_remove(struct i2c_client *client)
249{ 268{
250 struct v4l2_subdev *sd = i2c_get_clientdata(client); 269 struct v4l2_subdev *sd = i2c_get_clientdata(client);
270 struct wm8775_state *state = to_state(sd);
251 271
252 v4l2_device_unregister_subdev(sd); 272 v4l2_device_unregister_subdev(sd);
253 kfree(to_state(sd)); 273 v4l2_ctrl_handler_free(&state->hdl);
274 kfree(state);
254 return 0; 275 return 0;
255} 276}
256 277