aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2006-03-29 12:56:17 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-04-02 03:55:51 -0400
commitadd953cecba870f4ad7730bd0a6d5eaaabeac3bc (patch)
treee42b154981058ffcc2205ccb31b73b5c7e4b9db5 /drivers/media/video
parent7061561e640c2947ab93c4e2a437327657c4482e (diff)
V4L/DVB (3665): Add new NEC uPD64031A and uPD64083 i2c drivers
- Add support for the uPD64031A NEC Electronics Ghost Reduction i2c device - Add support for the uPD6408x NEC Electronics 3-Dimensional Y/C separation i2c device. Signed-off-by: Takahiro Adachi <tadachi@tadachi-net.com> Signed-off-by: Takeru Komoriya <komoriya@paken.org> Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/Kconfig37
-rw-r--r--drivers/media/video/Makefile2
-rw-r--r--drivers/media/video/upd64031a.c287
-rw-r--r--drivers/media/video/upd64083.c262
4 files changed, 581 insertions, 7 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index e19c403c3214..fb5be2606203 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -300,7 +300,7 @@ config VIDEO_OVCAMCHIP
300 camera drivers. 300 camera drivers.
301 301
302 To compile this driver as a module, choose M here: the 302 To compile this driver as a module, choose M here: the
303 module will be called ovcamchip 303 module will be called ovcamchip.
304 304
305config VIDEO_M32R_AR 305config VIDEO_M32R_AR
306 tristate "AR devices" 306 tristate "AR devices"
@@ -330,7 +330,7 @@ config VIDEO_MSP3400
330 Support for the Micronas MSP34xx series of audio decoders. 330 Support for the Micronas MSP34xx series of audio decoders.
331 331
332 To compile this driver as a module, choose M here: the 332 To compile this driver as a module, choose M here: the
333 module will be called msp3400 333 module will be called msp3400.
334 334
335config VIDEO_CS53L32A 335config VIDEO_CS53L32A
336 tristate "Cirrus Logic CS53L32A audio ADC" 336 tristate "Cirrus Logic CS53L32A audio ADC"
@@ -340,7 +340,7 @@ config VIDEO_CS53L32A
340 stereo A/D converter. 340 stereo A/D converter.
341 341
342 To compile this driver as a module, choose M here: the 342 To compile this driver as a module, choose M here: the
343 module will be called cs53l32a 343 module will be called cs53l32a.
344 344
345config VIDEO_WM8775 345config VIDEO_WM8775
346 tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer" 346 tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer"
@@ -350,7 +350,7 @@ config VIDEO_WM8775
350 performance stereo A/D Converter with a 4 channel input mixer. 350 performance stereo A/D Converter with a 4 channel input mixer.
351 351
352 To compile this driver as a module, choose M here: the 352 To compile this driver as a module, choose M here: the
353 module will be called wm8775 353 module will be called wm8775.
354 354
355config VIDEO_WM8739 355config VIDEO_WM8739
356 tristate "Wolfson Microelectronics WM8739 stereo audio ADC" 356 tristate "Wolfson Microelectronics WM8739 stereo audio ADC"
@@ -360,7 +360,7 @@ config VIDEO_WM8739
360 stereo A/D Converter. 360 stereo A/D Converter.
361 361
362 To compile this driver as a module, choose M here: the 362 To compile this driver as a module, choose M here: the
363 module will be called wm8739 363 module will be called wm8739.
364 364
365source "drivers/media/video/cx25840/Kconfig" 365source "drivers/media/video/cx25840/Kconfig"
366 366
@@ -371,7 +371,7 @@ config VIDEO_SAA711X
371 Support for the Philips SAA7113/4/5 video decoders. 371 Support for the Philips SAA7113/4/5 video decoders.
372 372
373 To compile this driver as a module, choose M here: the 373 To compile this driver as a module, choose M here: the
374 module will be called saa7115 374 module will be called saa7115.
375 375
376config VIDEO_SAA7127 376config VIDEO_SAA7127
377 tristate "Philips SAA7127/9 digital video encoders" 377 tristate "Philips SAA7127/9 digital video encoders"
@@ -380,7 +380,30 @@ config VIDEO_SAA7127
380 Support for the Philips SAA7127/9 digital video encoders. 380 Support for the Philips SAA7127/9 digital video encoders.
381 381
382 To compile this driver as a module, choose M here: the 382 To compile this driver as a module, choose M here: the
383 module will be called saa7127 383 module will be called saa7127.
384
385config VIDEO_UPD64031A
386 tristate "NEC Electronics uPD64031A Ghost Reduction"
387 depends on VIDEO_DEV && I2C && EXPERIMENTAL
388 ---help---
389 Support for the NEC Electronics uPD64031A Ghost Reduction
390 video chip. It is most often found in NTSC TV cards made for
391 Japan and is used to reduce the 'ghosting' effect that can
392 be present in analog TV broadcasts.
393
394 To compile this driver as a module, choose M here: the
395 module will be called upd64031a.
396
397config VIDEO_UPD64083
398 tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation"
399 depends on VIDEO_DEV && I2C && EXPERIMENTAL
400 ---help---
401 Support for the NEC Electronics uPD64083 3-Dimensional Y/C
402 separation video chip. It is used to improve the quality of
403 the colors of a composite signal.
404
405 To compile this driver as a module, choose M here: the
406 module will be called upd64083.
384 407
385endmenu # encoder / decoder chips 408endmenu # encoder / decoder chips
386 409
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 6cb296541706..4092a5e37ffc 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -65,6 +65,8 @@ obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o
65obj-$(CONFIG_VIDEO_CX25840) += cx25840/ 65obj-$(CONFIG_VIDEO_CX25840) += cx25840/
66obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o 66obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
67obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o 67obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
68obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
69obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
68 70
69obj-$(CONFIG_USB_DABUSB) += dabusb.o 71obj-$(CONFIG_USB_DABUSB) += dabusb.o
70obj-$(CONFIG_USB_DSBR) += dsbr100.o 72obj-$(CONFIG_USB_DSBR) += dsbr100.o
diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c
new file mode 100644
index 000000000000..bab5beadc6ae
--- /dev/null
+++ b/drivers/media/video/upd64031a.c
@@ -0,0 +1,287 @@
1/*
2 * upd64031A - NEC Electronics Ghost Reduction for NTSC in Japan
3 *
4 * 2003 by T.Adachi <tadachi@tadachi-net.com>
5 * 2003 by Takeru KOMORIYA <komoriya@paken.org>
6 * 2006 by Hans Verkuil <hverkuil@xs4all.nl>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23
24#include <linux/version.h>
25#include <linux/module.h>
26#include <linux/kernel.h>
27#include <linux/i2c.h>
28#include <linux/videodev2.h>
29#include <media/v4l2-common.h>
30#include <media/upd64031a.h>
31
32// --------------------- read registers functions define -----------------------
33
34/* bit masks */
35#define GR_MODE_MASK 0xc0
36#define DIRECT_3DYCS_CONNECT_MASK 0xc0
37#define SYNC_CIRCUIT_MASK 0xa0
38
39// -----------------------------------------------------------------------------
40
41MODULE_DESCRIPTION("uPD64031A driver");
42MODULE_AUTHOR("T. Adachi, Takeru KOMORIYA, Hans Verkuil");
43MODULE_LICENSE("GPL");
44
45static int debug = 0;
46module_param(debug, int, 0644);
47
48MODULE_PARM_DESC(debug, "Debug level (0-1)");
49
50static unsigned short normal_i2c[] = { 0x24 >> 1, 0x26 >> 1, I2C_CLIENT_END };
51
52
53I2C_CLIENT_INSMOD;
54
55enum {
56 R00 = 0, R01, R02, R03, R04,
57 R05, R06, R07, R08, R09,
58 R0A, R0B, R0C, R0D, R0E, R0F,
59 /* unused registers
60 R10, R11, R12, R13, R14,
61 R15, R16, R17,
62 */
63 TOT_REGS
64};
65
66struct upd64031a_state {
67 u8 regs[TOT_REGS];
68 u8 gr_mode;
69 u8 direct_3dycs_connect;
70 u8 ext_comp_sync;
71 u8 ext_vert_sync;
72};
73
74static u8 upd64031a_init[] = {
75 0x00, 0xb8, 0x48, 0xd2, 0xe6,
76 0x03, 0x10, 0x0b, 0xaf, 0x7f,
77 0x00, 0x00, 0x1d, 0x5e, 0x00,
78 0xd0
79};
80
81/* ------------------------------------------------------------------------ */
82
83static u8 upd64031a_read(struct i2c_client *client, u8 reg)
84{
85 u8 buf[2];
86
87 if (reg >= sizeof(buf))
88 return 0xff;
89 i2c_master_recv(client, buf, 2);
90 return buf[reg];
91}
92
93/* ------------------------------------------------------------------------ */
94
95static void upd64031a_write(struct i2c_client *client, u8 reg, u8 val)
96{
97 u8 buf[2];
98
99 buf[0] = reg;
100 buf[1] = val;
101 v4l_dbg(1, debug, client, "writing reg addr: %02X val: %02X\n", reg, val);
102 if (i2c_master_send(client, buf, 2) != 2)
103 v4l_err(client, "I/O error write 0x%02x/0x%02x\n", reg, val);
104}
105
106/* ------------------------------------------------------------------------ */
107
108/* The input changed due to new input or channel changed */
109static void upd64031a_change(struct i2c_client *client)
110{
111 struct upd64031a_state *state = i2c_get_clientdata(client);
112 u8 reg = state->regs[R00];
113
114 v4l_dbg(1, debug, client, "changed input or channel\n");
115 upd64031a_write(client, R00, reg | 0x10);
116 upd64031a_write(client, R00, reg & ~0x10);
117}
118
119/* ------------------------------------------------------------------------ */
120
121static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void *arg)
122{
123 struct upd64031a_state *state = i2c_get_clientdata(client);
124 struct v4l2_routing *route = arg;
125
126 switch (cmd) {
127 case VIDIOC_S_FREQUENCY:
128 upd64031a_change(client);
129 break;
130
131 case VIDIOC_INT_G_VIDEO_ROUTING:
132 route->input = (state->gr_mode >> 6) |
133 (state->direct_3dycs_connect >> 4) |
134 (state->ext_comp_sync >> 1) |
135 (state->ext_vert_sync >> 2);
136 route->output = 0;
137 break;
138
139 case VIDIOC_INT_S_VIDEO_ROUTING:
140 {
141 u8 r00, r05, r08;
142
143 state->gr_mode = (route->input & 3) << 6;
144 state->direct_3dycs_connect = (route->input & 0xc) << 4;
145 state->ext_comp_sync = (route->input & UPD64031A_COMPOSITE_EXTERNAL) << 1;
146 state->ext_vert_sync = (route->input & UPD64031A_VERTICAL_EXTERNAL) << 2;
147 r00 = (state->regs[R00] & ~GR_MODE_MASK) | state->gr_mode;
148 r05 = (state->regs[R00] & ~SYNC_CIRCUIT_MASK) |
149 state->ext_comp_sync | state->ext_vert_sync;
150 r08 = (state->regs[R08] & ~DIRECT_3DYCS_CONNECT_MASK) |
151 state->direct_3dycs_connect;
152 upd64031a_write(client, R00, r00);
153 upd64031a_write(client, R05, r05);
154 upd64031a_write(client, R08, r08);
155 upd64031a_change(client);
156 break;
157 }
158
159 case VIDIOC_LOG_STATUS:
160 v4l_info(client, "Status: SA00=0x%02x SA01=0x%02x\n",
161 upd64031a_read(client, 0), upd64031a_read(client, 1));
162 break;
163
164#ifdef CONFIG_VIDEO_ADV_DEBUG
165 case VIDIOC_INT_G_REGISTER:
166 {
167 struct v4l2_register *reg = arg;
168
169 if (reg->i2c_id != I2C_DRIVERID_UPD64031A)
170 return -EINVAL;
171 reg->val = upd64031a_read(client, reg->reg & 0xff);
172 break;
173 }
174
175 case VIDIOC_INT_S_REGISTER:
176 {
177 struct v4l2_register *reg = arg;
178 u8 addr = reg->reg & 0xff;
179 u8 val = reg->val & 0xff;
180
181 if (reg->i2c_id != I2C_DRIVERID_UPD64031A)
182 return -EINVAL;
183 if (!capable(CAP_SYS_ADMIN))
184 return -EPERM;
185 upd64031a_write(client, addr, val);
186 break;
187 }
188#endif
189
190 default:
191 break;
192 }
193 return 0;
194}
195
196/* ------------------------------------------------------------------------ */
197
198/* i2c implementation */
199
200static struct i2c_driver i2c_driver;
201
202static int upd64031a_attach(struct i2c_adapter *adapter, int address, int kind)
203{
204 struct i2c_client *client;
205 struct upd64031a_state *state;
206 int i;
207
208 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
209 return 0;
210
211 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
212 if (client == NULL) {
213 return -ENOMEM;
214 }
215
216 client->addr = address;
217 client->adapter = adapter;
218 client->driver = &i2c_driver;
219 snprintf(client->name, sizeof(client->name) - 1, "uPD64031A");
220
221 v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
222
223 state = kmalloc(sizeof(struct upd64031a_state), GFP_KERNEL);
224 if (state == NULL) {
225 kfree(client);
226 return -ENOMEM;
227 }
228 i2c_set_clientdata(client, state);
229 memcpy(state->regs, upd64031a_init, sizeof(state->regs));
230 state->gr_mode = UPD64031A_GR_ON << 6;
231 state->direct_3dycs_connect = UPD64031A_3DYCS_COMPOSITE << 4;
232 state->ext_comp_sync = state->ext_vert_sync = 0;
233 for (i = 0; i < TOT_REGS; i++) {
234 upd64031a_write(client, i, state->regs[i]);
235 }
236
237 i2c_attach_client(client);
238
239 return 0;
240}
241
242static int upd64031a_probe(struct i2c_adapter *adapter)
243{
244 if (adapter->class & I2C_CLASS_TV_ANALOG)
245 return i2c_probe(adapter, &addr_data, upd64031a_attach);
246 return 0;
247}
248
249static int upd64031a_detach(struct i2c_client *client)
250{
251 int err;
252
253 err = i2c_detach_client(client);
254 if (err)
255 return err;
256
257 kfree(client);
258 return 0;
259}
260
261/* ----------------------------------------------------------------------- */
262
263/* i2c implementation */
264static struct i2c_driver i2c_driver = {
265 .driver = {
266 .name = "upd64031a",
267 },
268 .id = I2C_DRIVERID_UPD64031A,
269 .attach_adapter = upd64031a_probe,
270 .detach_client = upd64031a_detach,
271 .command = upd64031a_command,
272};
273
274
275static int __init upd64031a_init_module(void)
276{
277 return i2c_add_driver(&i2c_driver);
278}
279
280static void __exit upd64031a_exit_module(void)
281{
282 i2c_del_driver(&i2c_driver);
283}
284
285module_init(upd64031a_init_module);
286module_exit(upd64031a_exit_module);
287
diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c
new file mode 100644
index 000000000000..c3a7ffe5c267
--- /dev/null
+++ b/drivers/media/video/upd64083.c
@@ -0,0 +1,262 @@
1/*
2 * upd6408x - NEC Electronics 3-Dimensional Y/C separation driver
3 *
4 * 2003 by T.Adachi (tadachi@tadachi-net.com)
5 * 2003 by Takeru KOMORIYA <komoriya@paken.org>
6 * 2006 by Hans Verkuil <hverkuil@xs4all.nl>
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 02110-1301, USA.
21 */
22
23#include <linux/version.h>
24#include <linux/module.h>
25#include <linux/kernel.h>
26#include <linux/i2c.h>
27#include <linux/videodev2.h>
28#include <media/v4l2-common.h>
29#include <media/upd64083.h>
30
31MODULE_DESCRIPTION("uPD64083 driver");
32MODULE_AUTHOR("T. Adachi, Takeru KOMORIYA, Hans Verkuil");
33MODULE_LICENSE("GPL");
34
35static int debug = 0;
36module_param(debug, bool, 0644);
37
38MODULE_PARM_DESC(debug, "Debug level (0-1)");
39
40static unsigned short normal_i2c[] = { 0xb8 >> 1, 0xba >> 1, I2C_CLIENT_END };
41
42
43I2C_CLIENT_INSMOD;
44
45enum {
46 R00 = 0, R01, R02, R03, R04,
47 R05, R06, R07, R08, R09,
48 R0A, R0B, R0C, R0D, R0E, R0F,
49 R10, R11, R12, R13, R14,
50 R15, R16,
51 TOT_REGS
52};
53
54struct upd64083_state {
55 u8 mode;
56 u8 ext_y_adc;
57 u8 regs[TOT_REGS];
58};
59
60/* Initial values when used in combination with the
61 NEC upd64031a ghost reduction chip. */
62static u8 upd64083_init[] = {
63 0x1f, 0x01, 0xa0, 0x2d, 0x29, /* we use EXCSS=0 */
64 0x36, 0xdd, 0x05, 0x56, 0x48,
65 0x00, 0x3a, 0xa0, 0x05, 0x08,
66 0x44, 0x60, 0x08, 0x52, 0xf8,
67 0x53, 0x60, 0x10
68};
69
70/* ------------------------------------------------------------------------ */
71
72static void upd64083_log_status(struct i2c_client *client)
73{
74 u8 buf[7];
75
76 i2c_master_recv(client, buf, 7);
77 v4l_info(client, "Status: SA00=%02x SA01=%02x SA02=%02x SA03=%02x "
78 "SA04=%02x SA05=%02x SA06=%02x\n",
79 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
80}
81
82/* ------------------------------------------------------------------------ */
83
84static void upd64083_write(struct i2c_client *client, u8 reg, u8 val)
85{
86 u8 buf[2];
87
88 buf[0] = reg;
89 buf[1] = val;
90 v4l_dbg(1, debug, client, "writing reg addr: %02x val: %02x\n", reg, val);
91 if (i2c_master_send(client, buf, 2) != 2)
92 v4l_err(client, "I/O error write 0x%02x/0x%02x\n", reg, val);
93}
94
95/* ------------------------------------------------------------------------ */
96
97#ifdef CONFIG_VIDEO_ADV_DEBUG
98static u8 upd64083_read(struct i2c_client *client, u8 reg)
99{
100 u8 buf[7];
101
102 if (reg >= sizeof(buf))
103 return 0xff;
104 i2c_master_recv(client, buf, sizeof(buf));
105 return buf[reg];
106}
107#endif
108
109/* ------------------------------------------------------------------------ */
110
111static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *arg)
112{
113 struct upd64083_state *state = i2c_get_clientdata(client);
114 struct v4l2_routing *route = arg;
115
116 switch (cmd) {
117 case VIDIOC_INT_G_VIDEO_ROUTING:
118 route->input = (state->mode >> 6) | (state->ext_y_adc >> 3);
119 route->output = 0;
120 break;
121
122 case VIDIOC_INT_S_VIDEO_ROUTING:
123 {
124 u8 r00, r02;
125
126 if (route->input > 7 || (route->input & 6) == 6)
127 return -EINVAL;
128 state->mode = (route->input & 3) << 6;
129 state->ext_y_adc = (route->input & UPD64083_EXT_Y_ADC) << 3;
130 r00 = (state->regs[R00] & ~(3 << 6)) | state->mode;
131 r02 = (state->regs[R02] & ~(1 << 5)) | state->ext_y_adc;
132 upd64083_write(client, R00, r00);
133 upd64083_write(client, R02, r02);
134 break;
135 }
136
137 case VIDIOC_LOG_STATUS:
138 upd64083_log_status(client);
139 break;
140
141#ifdef CONFIG_VIDEO_ADV_DEBUG
142 case VIDIOC_INT_G_REGISTER:
143 {
144 struct v4l2_register *reg = arg;
145
146 if (reg->i2c_id != I2C_DRIVERID_UPD64083)
147 return -EINVAL;
148 reg->val = upd64083_read(client, reg->reg & 0xff);
149 break;
150 }
151
152 case VIDIOC_INT_S_REGISTER:
153 {
154 struct v4l2_register *reg = arg;
155 u8 addr = reg->reg & 0xff;
156 u8 val = reg->val & 0xff;
157
158 if (reg->i2c_id != I2C_DRIVERID_UPD64083)
159 return -EINVAL;
160 if (!capable(CAP_SYS_ADMIN))
161 return -EPERM;
162 upd64083_write(client, addr, val);
163 break;
164 }
165#endif
166 default:
167 break;
168 }
169
170 return 0;
171}
172
173/* ------------------------------------------------------------------------ */
174
175/* i2c implementation */
176
177static struct i2c_driver i2c_driver;
178
179static int upd64083_attach(struct i2c_adapter *adapter, int address, int kind)
180{
181 struct i2c_client *client;
182 struct upd64083_state *state;
183 int i;
184
185 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
186 return 0;
187
188 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
189 if (client == NULL) {
190 return -ENOMEM;
191 }
192
193 client->addr = address;
194 client->adapter = adapter;
195 client->driver = &i2c_driver;
196 snprintf(client->name, sizeof(client->name) - 1, "uPD64083");
197
198 v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
199
200 state = kmalloc(sizeof(struct upd64083_state), GFP_KERNEL);
201 if (state == NULL) {
202 kfree(client);
203 return -ENOMEM;
204 }
205 i2c_set_clientdata(client, state);
206 /* Initially assume that a ghost reduction chip is present */
207 state->mode = 0; /* YCS mode */
208 state->ext_y_adc = (1 << 5);
209 memcpy(state->regs, upd64083_init, TOT_REGS);
210 for (i = 0; i < TOT_REGS; i++) {
211 upd64083_write(client, i, state->regs[i]);
212 }
213 i2c_attach_client(client);
214
215 return 0;
216}
217
218static int upd64083_probe(struct i2c_adapter *adapter)
219{
220 if (adapter->class & I2C_CLASS_TV_ANALOG)
221 return i2c_probe(adapter, &addr_data, upd64083_attach);
222 return 0;
223}
224
225static int upd64083_detach(struct i2c_client *client)
226{
227 int err;
228
229 err = i2c_detach_client(client);
230 if (err)
231 return err;
232
233 kfree(client);
234 return 0;
235}
236
237/* ----------------------------------------------------------------------- */
238
239/* i2c implementation */
240static struct i2c_driver i2c_driver = {
241 .driver = {
242 .name = "upd64083",
243 },
244 .id = I2C_DRIVERID_UPD64083,
245 .attach_adapter = upd64083_probe,
246 .detach_client = upd64083_detach,
247 .command = upd64083_command,
248};
249
250
251static int __init upd64083_init_module(void)
252{
253 return i2c_add_driver(&i2c_driver);
254}
255
256static void __exit upd64083_exit_module(void)
257{
258 i2c_del_driver(&i2c_driver);
259}
260
261module_init(upd64083_init_module);
262module_exit(upd64083_exit_module);