aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2009-02-19 04:36:36 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:42:57 -0400
commitc2179ad87240cf31b751f198c55140211e8cef89 (patch)
tree32d3bd98208430cd74e9da9a9826e4affb419379
parent8e4e1d8054b037e867849162ba78cf9b153b0dcc (diff)
V4L/DVB (10719): bt819: convert to v4l2_subdev.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/bt819.c477
-rw-r--r--include/media/v4l2-chip-ident.h5
2 files changed, 257 insertions, 225 deletions
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index b8109a1b50ce..ce2a8f3ef64d 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -29,15 +29,14 @@
29 */ 29 */
30 30
31#include <linux/module.h> 31#include <linux/module.h>
32#include <linux/delay.h>
33#include <linux/types.h> 32#include <linux/types.h>
34#include <linux/ioctl.h> 33#include <linux/ioctl.h>
35#include <asm/uaccess.h> 34#include <asm/uaccess.h>
36#include <linux/i2c.h> 35#include <linux/i2c.h>
37#include <linux/i2c-id.h> 36#include <linux/i2c-id.h>
38#include <linux/videodev.h> 37#include <linux/videodev2.h>
39#include <linux/video_decoder.h> 38#include <media/v4l2-device.h>
40#include <media/v4l2-common.h> 39#include <media/v4l2-chip-ident.h>
41#include <media/v4l2-i2c-drv-legacy.h> 40#include <media/v4l2-i2c-drv-legacy.h>
42 41
43MODULE_DESCRIPTION("Brooktree-819 video decoder driver"); 42MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
@@ -48,13 +47,18 @@ static int debug;
48module_param(debug, int, 0); 47module_param(debug, int, 0);
49MODULE_PARM_DESC(debug, "Debug level (0-1)"); 48MODULE_PARM_DESC(debug, "Debug level (0-1)");
50 49
50static unsigned short normal_i2c[] = { 0x8a >> 1, I2C_CLIENT_END };
51
52I2C_CLIENT_INSMOD;
53
51/* ----------------------------------------------------------------------- */ 54/* ----------------------------------------------------------------------- */
52 55
53struct bt819 { 56struct bt819 {
57 struct v4l2_subdev sd;
54 unsigned char reg[32]; 58 unsigned char reg[32];
55 59
56 int initialized;
57 v4l2_std_id norm; 60 v4l2_std_id norm;
61 int ident;
58 int input; 62 int input;
59 int enable; 63 int enable;
60 int bright; 64 int bright;
@@ -63,6 +67,11 @@ struct bt819 {
63 int sat; 67 int sat;
64}; 68};
65 69
70static inline struct bt819 *to_bt819(struct v4l2_subdev *sd)
71{
72 return container_of(sd, struct bt819, sd);
73}
74
66struct timing { 75struct timing {
67 int hactive; 76 int hactive;
68 int hdelay; 77 int hdelay;
@@ -80,24 +89,23 @@ static struct timing timing_data[] = {
80 89
81/* ----------------------------------------------------------------------- */ 90/* ----------------------------------------------------------------------- */
82 91
83static inline int bt819_write(struct i2c_client *client, u8 reg, u8 value) 92static inline int bt819_write(struct bt819 *decoder, u8 reg, u8 value)
84{ 93{
85 struct bt819 *decoder = i2c_get_clientdata(client); 94 struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
86 95
87 decoder->reg[reg] = value; 96 decoder->reg[reg] = value;
88 return i2c_smbus_write_byte_data(client, reg, value); 97 return i2c_smbus_write_byte_data(client, reg, value);
89} 98}
90 99
91static inline int bt819_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value) 100static inline int bt819_setbit(struct bt819 *decoder, u8 reg, u8 bit, u8 value)
92{ 101{
93 struct bt819 *decoder = i2c_get_clientdata(client); 102 return bt819_write(decoder, reg,
94
95 return bt819_write(client, reg,
96 (decoder->reg[reg] & ~(1 << bit)) | (value ? (1 << bit) : 0)); 103 (decoder->reg[reg] & ~(1 << bit)) | (value ? (1 << bit) : 0));
97} 104}
98 105
99static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned int len) 106static int bt819_write_block(struct bt819 *decoder, const u8 *data, unsigned int len)
100{ 107{
108 struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
101 int ret = -1; 109 int ret = -1;
102 u8 reg; 110 u8 reg;
103 111
@@ -105,7 +113,6 @@ static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned
105 * the adapter understands raw I2C */ 113 * the adapter understands raw I2C */
106 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 114 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
107 /* do raw I2C, not smbus compatible */ 115 /* do raw I2C, not smbus compatible */
108 struct bt819 *decoder = i2c_get_clientdata(client);
109 u8 block_data[32]; 116 u8 block_data[32];
110 int block_len; 117 int block_len;
111 118
@@ -126,7 +133,8 @@ static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned
126 /* do some slow I2C emulation kind of thing */ 133 /* do some slow I2C emulation kind of thing */
127 while (len >= 2) { 134 while (len >= 2) {
128 reg = *data++; 135 reg = *data++;
129 if ((ret = bt819_write(client, reg, *data++)) < 0) 136 ret = bt819_write(decoder, reg, *data++);
137 if (ret < 0)
130 break; 138 break;
131 len -= 2; 139 len -= 2;
132 } 140 }
@@ -135,15 +143,15 @@ static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned
135 return ret; 143 return ret;
136} 144}
137 145
138static inline int bt819_read(struct i2c_client *client, u8 reg) 146static inline int bt819_read(struct bt819 *decoder, u8 reg)
139{ 147{
148 struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
149
140 return i2c_smbus_read_byte_data(client, reg); 150 return i2c_smbus_read_byte_data(client, reg);
141} 151}
142 152
143static int bt819_init(struct i2c_client *client) 153static int bt819_init(struct v4l2_subdev *sd)
144{ 154{
145 struct bt819 *decoder = i2c_get_clientdata(client);
146
147 static unsigned char init[] = { 155 static unsigned char init[] = {
148 /*0x1f, 0x00,*/ /* Reset */ 156 /*0x1f, 0x00,*/ /* Reset */
149 0x01, 0x59, /* 0x01 input format */ 157 0x01, 0x59, /* 0x01 input format */
@@ -178,6 +186,7 @@ static int bt819_init(struct i2c_client *client)
178 0x1a, 0x80, /* 0x1a ADC Interface */ 186 0x1a, 0x80, /* 0x1a ADC Interface */
179 }; 187 };
180 188
189 struct bt819 *decoder = to_bt819(sd);
181 struct timing *timing = &timing_data[(decoder->norm & V4L2_STD_525_60) ? 1 : 0]; 190 struct timing *timing = &timing_data[(decoder->norm & V4L2_STD_525_60) ? 1 : 0];
182 191
183 init[0x03 * 2 - 1] = 192 init[0x03 * 2 - 1] =
@@ -194,277 +203,297 @@ static int bt819_init(struct i2c_client *client)
194 /* 0x15 in array is address 0x19 */ 203 /* 0x15 in array is address 0x19 */
195 init[0x15 * 2 - 1] = (decoder->norm & V4L2_STD_625_50) ? 115 : 93; /* Chroma burst delay */ 204 init[0x15 * 2 - 1] = (decoder->norm & V4L2_STD_625_50) ? 115 : 93; /* Chroma burst delay */
196 /* reset */ 205 /* reset */
197 bt819_write(client, 0x1f, 0x00); 206 bt819_write(decoder, 0x1f, 0x00);
198 mdelay(1); 207 mdelay(1);
199 208
200 /* init */ 209 /* init */
201 return bt819_write_block(client, init, sizeof(init)); 210 return bt819_write_block(decoder, init, sizeof(init));
202} 211}
203 212
204/* ----------------------------------------------------------------------- */ 213/* ----------------------------------------------------------------------- */
205 214
206static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg) 215static int bt819_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd)
207{ 216{
208 int temp; 217 struct bt819 *decoder = to_bt819(sd);
218 int status = bt819_read(decoder, 0x00);
219 int res = V4L2_IN_ST_NO_SIGNAL;
220 v4l2_std_id std;
221
222 if ((status & 0x80))
223 res = 0;
224
225 if ((status & 0x10))
226 std = V4L2_STD_PAL;
227 else
228 std = V4L2_STD_NTSC;
229 if (pstd)
230 *pstd = std;
231 if (pstatus)
232 *pstatus = status;
233
234 v4l2_dbg(1, debug, sd, "get status %x\n", status);
235 return 0;
236}
209 237
210 struct bt819 *decoder = i2c_get_clientdata(client); 238static int bt819_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
239{
240 return bt819_status(sd, NULL, std);
241}
211 242
212 if (!decoder->initialized) { /* First call to bt819_init could be */ 243static int bt819_g_input_status(struct v4l2_subdev *sd, u32 *status)
213 bt819_init(client); /* without #FRST = 0 */ 244{
214 decoder->initialized = 1; 245 return bt819_status(sd, status, NULL);
246}
247
248static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
249{
250 struct bt819 *decoder = to_bt819(sd);
251 struct timing *timing = NULL;
252
253 v4l2_dbg(1, debug, sd, "set norm %llx\n", std);
254
255 if (std & V4L2_STD_NTSC) {
256 bt819_setbit(decoder, 0x01, 0, 1);
257 bt819_setbit(decoder, 0x01, 1, 0);
258 bt819_setbit(decoder, 0x01, 5, 0);
259 bt819_write(decoder, 0x18, 0x68);
260 bt819_write(decoder, 0x19, 0x5d);
261 /* bt819_setbit(decoder, 0x1a, 5, 1); */
262 timing = &timing_data[1];
263 } else if (std & V4L2_STD_PAL) {
264 bt819_setbit(decoder, 0x01, 0, 1);
265 bt819_setbit(decoder, 0x01, 1, 1);
266 bt819_setbit(decoder, 0x01, 5, 1);
267 bt819_write(decoder, 0x18, 0x7f);
268 bt819_write(decoder, 0x19, 0x72);
269 /* bt819_setbit(decoder, 0x1a, 5, 0); */
270 timing = &timing_data[0];
271 } else {
272 v4l2_dbg(1, debug, sd, "unsupported norm %llx\n", std);
273 return -EINVAL;
215 } 274 }
275 bt819_write(decoder, 0x03,
276 (((timing->vdelay >> 8) & 0x03) << 6) |
277 (((timing->vactive >> 8) & 0x03) << 4) |
278 (((timing->hdelay >> 8) & 0x03) << 2) |
279 ((timing->hactive >> 8) & 0x03));
280 bt819_write(decoder, 0x04, timing->vdelay & 0xff);
281 bt819_write(decoder, 0x05, timing->vactive & 0xff);
282 bt819_write(decoder, 0x06, timing->hdelay & 0xff);
283 bt819_write(decoder, 0x07, timing->hactive & 0xff);
284 bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff);
285 bt819_write(decoder, 0x09, timing->hscale & 0xff);
286 decoder->norm = std;
287 return 0;
288}
216 289
217 switch (cmd) { 290static int bt819_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
218 case VIDIOC_INT_INIT: 291{
219 /* This is just for testing!!! */ 292 struct bt819 *decoder = to_bt819(sd);
220 bt819_init(client);
221 break;
222 293
223 case VIDIOC_QUERYSTD: 294 v4l2_dbg(1, debug, sd, "set input %x\n", route->input);
224 case VIDIOC_INT_G_INPUT_STATUS: {
225 int *iarg = arg;
226 v4l2_std_id *istd = arg;
227 int status;
228 int res = V4L2_IN_ST_NO_SIGNAL;
229 v4l2_std_id std;
230
231 status = bt819_read(client, 0x00);
232 if ((status & 0x80))
233 res = 0;
234
235 if ((status & 0x10))
236 std = V4L2_STD_PAL;
237 else
238 std = V4L2_STD_NTSC;
239 if (cmd == VIDIOC_QUERYSTD)
240 *istd = std;
241 else
242 *iarg = res;
243
244 v4l_dbg(1, debug, client, "get status %x\n", *iarg);
245 break;
246 }
247 295
248 case VIDIOC_S_STD: 296 if (route->input < 0 || route->input > 7)
249 { 297 return -EINVAL;
250 v4l2_std_id *iarg = arg;
251 struct timing *timing = NULL;
252
253 v4l_dbg(1, debug, client, "set norm %llx\n", *iarg);
254
255 if (*iarg & V4L2_STD_NTSC) {
256 bt819_setbit(client, 0x01, 0, 1);
257 bt819_setbit(client, 0x01, 1, 0);
258 bt819_setbit(client, 0x01, 5, 0);
259 bt819_write(client, 0x18, 0x68);
260 bt819_write(client, 0x19, 0x5d);
261 /* bt819_setbit(client, 0x1a, 5, 1); */
262 timing = &timing_data[1];
263 } else if (*iarg & V4L2_STD_PAL) {
264 bt819_setbit(client, 0x01, 0, 1);
265 bt819_setbit(client, 0x01, 1, 1);
266 bt819_setbit(client, 0x01, 5, 1);
267 bt819_write(client, 0x18, 0x7f);
268 bt819_write(client, 0x19, 0x72);
269 /* bt819_setbit(client, 0x1a, 5, 0); */
270 timing = &timing_data[0];
271 } else {
272 v4l_dbg(1, debug, client, "unsupported norm %llx\n", *iarg);
273 return -EINVAL;
274 }
275/* case VIDEO_MODE_AUTO:
276 bt819_setbit(client, 0x01, 0, 0);
277 bt819_setbit(client, 0x01, 1, 0);*/
278
279 bt819_write(client, 0x03,
280 (((timing->vdelay >> 8) & 0x03) << 6) |
281 (((timing->vactive >> 8) & 0x03) << 4) |
282 (((timing->hdelay >> 8) & 0x03) << 2) |
283 ((timing->hactive >> 8) & 0x03));
284 bt819_write(client, 0x04, timing->vdelay & 0xff);
285 bt819_write(client, 0x05, timing->vactive & 0xff);
286 bt819_write(client, 0x06, timing->hdelay & 0xff);
287 bt819_write(client, 0x07, timing->hactive & 0xff);
288 bt819_write(client, 0x08, (timing->hscale >> 8) & 0xff);
289 bt819_write(client, 0x09, timing->hscale & 0xff);
290 decoder->norm = *iarg;
291 break;
292 }
293 298
294 case VIDIOC_INT_S_VIDEO_ROUTING: 299 if (decoder->input != route->input) {
295 { 300 decoder->input = route->input;
296 struct v4l2_routing *route = arg; 301 /* select mode */
297 302 if (decoder->input == 0) {
298 v4l_dbg(1, debug, client, "set input %x\n", route->input); 303 bt819_setbit(decoder, 0x0b, 6, 0);
299 304 bt819_setbit(decoder, 0x1a, 1, 1);
300 if (route->input < 0 || route->input > 7) 305 } else {
301 return -EINVAL; 306 bt819_setbit(decoder, 0x0b, 6, 1);
302 307 bt819_setbit(decoder, 0x1a, 1, 0);
303 if (decoder->input != route->input) {
304 decoder->input = route->input;
305 /* select mode */
306 if (decoder->input == 0) {
307 bt819_setbit(client, 0x0b, 6, 0);
308 bt819_setbit(client, 0x1a, 1, 1);
309 } else {
310 bt819_setbit(client, 0x0b, 6, 1);
311 bt819_setbit(client, 0x1a, 1, 0);
312 }
313 } 308 }
314 break;
315 } 309 }
310 return 0;
311}
316 312
317 case VIDIOC_STREAMON: 313static int bt819_s_stream(struct v4l2_subdev *sd, int enable)
318 case VIDIOC_STREAMOFF: 314{
319 { 315 struct bt819 *decoder = to_bt819(sd);
320 int enable = cmd == VIDIOC_STREAMON;
321 316
322 v4l_dbg(1, debug, client, "enable output %x\n", enable); 317 v4l2_dbg(1, debug, sd, "enable output %x\n", enable);
323 318
324 if (decoder->enable != enable) { 319 if (decoder->enable != enable) {
325 decoder->enable = enable; 320 decoder->enable = enable;
326 bt819_setbit(client, 0x16, 7, !enable); 321 bt819_setbit(decoder, 0x16, 7, !enable);
327 }
328 break;
329 } 322 }
323 return 0;
324}
330 325
331 case VIDIOC_QUERYCTRL: 326static int bt819_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
332 { 327{
333 struct v4l2_queryctrl *qc = arg; 328 switch (qc->id) {
334 329 case V4L2_CID_BRIGHTNESS:
335 switch (qc->id) { 330 v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
336 case V4L2_CID_BRIGHTNESS: 331 break;
337 v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
338 break;
339
340 case V4L2_CID_CONTRAST:
341 v4l2_ctrl_query_fill(qc, 0, 511, 1, 256);
342 break;
343 332
344 case V4L2_CID_SATURATION: 333 case V4L2_CID_CONTRAST:
345 v4l2_ctrl_query_fill(qc, 0, 511, 1, 256); 334 v4l2_ctrl_query_fill(qc, 0, 511, 1, 256);
346 break; 335 break;
347 336
348 case V4L2_CID_HUE: 337 case V4L2_CID_SATURATION:
349 v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); 338 v4l2_ctrl_query_fill(qc, 0, 511, 1, 256);
350 break; 339 break;
351 340
352 default: 341 case V4L2_CID_HUE:
353 return -EINVAL; 342 v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
354 }
355 break; 343 break;
344
345 default:
346 return -EINVAL;
356 } 347 }
348 return 0;
349}
357 350
358 case VIDIOC_S_CTRL: 351static int bt819_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
359 { 352{
360 struct v4l2_control *ctrl = arg; 353 struct bt819 *decoder = to_bt819(sd);
354 int temp;
361 355
362 switch (ctrl->id) { 356 switch (ctrl->id) {
363 case V4L2_CID_BRIGHTNESS: 357 case V4L2_CID_BRIGHTNESS:
364 if (decoder->bright != ctrl->value) { 358 if (decoder->bright == ctrl->value)
365 decoder->bright = ctrl->value;
366 bt819_write(client, 0x0a, decoder->bright);
367 }
368 break; 359 break;
360 decoder->bright = ctrl->value;
361 bt819_write(decoder, 0x0a, decoder->bright);
362 break;
369 363
370 case V4L2_CID_CONTRAST: 364 case V4L2_CID_CONTRAST:
371 if (decoder->contrast != ctrl->value) { 365 if (decoder->contrast == ctrl->value)
372 decoder->contrast = ctrl->value;
373 bt819_write(client, 0x0c,
374 decoder->contrast & 0xff);
375 bt819_setbit(client, 0x0b, 2,
376 ((decoder->contrast >> 8) & 0x01));
377 }
378 break; 366 break;
367 decoder->contrast = ctrl->value;
368 bt819_write(decoder, 0x0c, decoder->contrast & 0xff);
369 bt819_setbit(decoder, 0x0b, 2, ((decoder->contrast >> 8) & 0x01));
370 break;
379 371
380 case V4L2_CID_SATURATION: 372 case V4L2_CID_SATURATION:
381 if (decoder->sat != ctrl->value) { 373 if (decoder->sat == ctrl->value)
382 decoder->sat = ctrl->value;
383 bt819_write(client, 0x0d,
384 (decoder->sat >> 7) & 0xff);
385 bt819_setbit(client, 0x0b, 1,
386 ((decoder->sat >> 15) & 0x01));
387
388 /* Ratio between U gain and V gain must stay the same as
389 the ratio between the default U and V gain values. */
390 temp = (decoder->sat * 180) / 254;
391 bt819_write(client, 0x0e, (temp >> 7) & 0xff);
392 bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01);
393 }
394 break; 374 break;
375 decoder->sat = ctrl->value;
376 bt819_write(decoder, 0x0d, (decoder->sat >> 7) & 0xff);
377 bt819_setbit(decoder, 0x0b, 1, ((decoder->sat >> 15) & 0x01));
378
379 /* Ratio between U gain and V gain must stay the same as
380 the ratio between the default U and V gain values. */
381 temp = (decoder->sat * 180) / 254;
382 bt819_write(decoder, 0x0e, (temp >> 7) & 0xff);
383 bt819_setbit(decoder, 0x0b, 0, (temp >> 15) & 0x01);
384 break;
395 385
396 case V4L2_CID_HUE: 386 case V4L2_CID_HUE:
397 if (decoder->hue != ctrl->value) { 387 if (decoder->hue == ctrl->value)
398 decoder->hue = ctrl->value;
399 bt819_write(client, 0x0f, decoder->hue);
400 }
401 break; 388 break;
402 default: 389 decoder->hue = ctrl->value;
403 return -EINVAL; 390 bt819_write(decoder, 0x0f, decoder->hue);
404 }
405 break; 391 break;
392
393 default:
394 return -EINVAL;
406 } 395 }
396 return 0;
397}
407 398
408 case VIDIOC_G_CTRL: 399static int bt819_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
409 { 400{
410 struct v4l2_control *ctrl = arg; 401 struct bt819 *decoder = to_bt819(sd);
411 402
412 switch (ctrl->id) { 403 switch (ctrl->id) {
413 case V4L2_CID_BRIGHTNESS: 404 case V4L2_CID_BRIGHTNESS:
414 ctrl->value = decoder->bright; 405 ctrl->value = decoder->bright;
415 break; 406 break;
416 case V4L2_CID_CONTRAST: 407 case V4L2_CID_CONTRAST:
417 ctrl->value = decoder->contrast; 408 ctrl->value = decoder->contrast;
418 break; 409 break;
419 case V4L2_CID_SATURATION: 410 case V4L2_CID_SATURATION:
420 ctrl->value = decoder->sat; 411 ctrl->value = decoder->sat;
421 break; 412 break;
422 case V4L2_CID_HUE: 413 case V4L2_CID_HUE:
423 ctrl->value = decoder->hue; 414 ctrl->value = decoder->hue;
424 break;
425 default:
426 return -EINVAL;
427 }
428 break; 415 break;
429 }
430
431 default: 416 default:
432 return -EINVAL; 417 return -EINVAL;
433 } 418 }
434
435 return 0; 419 return 0;
436} 420}
437 421
422static int bt819_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
423{
424 struct bt819 *decoder = to_bt819(sd);
425 struct i2c_client *client = v4l2_get_subdevdata(sd);
426
427 return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0);
428}
429
430static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg)
431{
432 return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
433}
434
438/* ----------------------------------------------------------------------- */ 435/* ----------------------------------------------------------------------- */
439 436
440static unsigned short normal_i2c[] = { 0x8a >> 1, I2C_CLIENT_END }; 437static const struct v4l2_subdev_core_ops bt819_core_ops = {
438 .g_chip_ident = bt819_g_chip_ident,
439 .g_ctrl = bt819_g_ctrl,
440 .s_ctrl = bt819_s_ctrl,
441 .queryctrl = bt819_queryctrl,
442};
441 443
442I2C_CLIENT_INSMOD; 444static const struct v4l2_subdev_tuner_ops bt819_tuner_ops = {
445 .s_std = bt819_s_std,
446};
447
448static const struct v4l2_subdev_video_ops bt819_video_ops = {
449 .s_routing = bt819_s_routing,
450 .s_stream = bt819_s_stream,
451 .querystd = bt819_querystd,
452 .g_input_status = bt819_g_input_status,
453};
454
455static const struct v4l2_subdev_ops bt819_ops = {
456 .core = &bt819_core_ops,
457 .tuner = &bt819_tuner_ops,
458 .video = &bt819_video_ops,
459};
460
461/* ----------------------------------------------------------------------- */
443 462
444static int bt819_probe(struct i2c_client *client, 463static int bt819_probe(struct i2c_client *client,
445 const struct i2c_device_id *id) 464 const struct i2c_device_id *id)
446{ 465{
447 int i, ver; 466 int i, ver;
448 struct bt819 *decoder; 467 struct bt819 *decoder;
468 struct v4l2_subdev *sd;
449 const char *name; 469 const char *name;
450 470
451 /* Check if the adapter supports the needed features */ 471 /* Check if the adapter supports the needed features */
452 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 472 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
453 return -ENODEV; 473 return -ENODEV;
454 474
455 ver = bt819_read(client, 0x17); 475 decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL);
476 if (decoder == NULL)
477 return -ENOMEM;
478 sd = &decoder->sd;
479 v4l2_i2c_subdev_init(sd, client, &bt819_ops);
480
481 ver = bt819_read(decoder, 0x17);
456 switch (ver & 0xf0) { 482 switch (ver & 0xf0) {
457 case 0x70: 483 case 0x70:
458 name = "bt819a"; 484 name = "bt819a";
485 decoder->ident = V4L2_IDENT_BT819A;
459 break; 486 break;
460 case 0x60: 487 case 0x60:
461 name = "bt817a"; 488 name = "bt817a";
489 decoder->ident = V4L2_IDENT_BT817A;
462 break; 490 break;
463 case 0x20: 491 case 0x20:
464 name = "bt815a"; 492 name = "bt815a";
493 decoder->ident = V4L2_IDENT_BT815A;
465 break; 494 break;
466 default: 495 default:
467 v4l_dbg(1, debug, client, 496 v4l2_dbg(1, debug, sd,
468 "unknown chip version 0x%02x\n", ver); 497 "unknown chip version 0x%02x\n", ver);
469 return -ENODEV; 498 return -ENODEV;
470 } 499 }
@@ -472,28 +501,26 @@ static int bt819_probe(struct i2c_client *client,
472 v4l_info(client, "%s found @ 0x%x (%s)\n", name, 501 v4l_info(client, "%s found @ 0x%x (%s)\n", name,
473 client->addr << 1, client->adapter->name); 502 client->addr << 1, client->adapter->name);
474 503
475 decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL);
476 if (decoder == NULL)
477 return -ENOMEM;
478 decoder->norm = V4L2_STD_NTSC; 504 decoder->norm = V4L2_STD_NTSC;
479 decoder->input = 0; 505 decoder->input = 0;
480 decoder->enable = 1; 506 decoder->enable = 1;
481 decoder->bright = 0; 507 decoder->bright = 0;
482 decoder->contrast = 0xd8; /* 100% of original signal */ 508 decoder->contrast = 0xd8; /* 100% of original signal */
483 decoder->hue = 0; 509 decoder->hue = 0;
484 decoder->sat = 0xfe; /* 100% of original signal */ 510 decoder->sat = 0xfe; /* 100% of original signal */
485 decoder->initialized = 0;
486 i2c_set_clientdata(client, decoder);
487 511
488 i = bt819_init(client); 512 i = bt819_init(sd);
489 if (i < 0) 513 if (i < 0)
490 v4l_dbg(1, debug, client, "init status %d\n", i); 514 v4l2_dbg(1, debug, sd, "init status %d\n", i);
491 return 0; 515 return 0;
492} 516}
493 517
494static int bt819_remove(struct i2c_client *client) 518static int bt819_remove(struct i2c_client *client)
495{ 519{
496 kfree(i2c_get_clientdata(client)); 520 struct v4l2_subdev *sd = i2c_get_clientdata(client);
521
522 v4l2_device_unregister_subdev(sd);
523 kfree(to_bt819(sd));
497 return 0; 524 return 0;
498} 525}
499 526
diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h
index cfb236e5a1cc..0766106beb82 100644
--- a/include/media/v4l2-chip-ident.h
+++ b/include/media/v4l2-chip-ident.h
@@ -71,6 +71,11 @@ enum {
71 V4L2_IDENT_CX23416 = 416, 71 V4L2_IDENT_CX23416 = 416,
72 V4L2_IDENT_CX23418 = 418, 72 V4L2_IDENT_CX23418 = 418,
73 73
74 /* module bt819: reserved range 810-819 */
75 V4L2_IDENT_BT815A = 815,
76 V4L2_IDENT_BT817A = 817,
77 V4L2_IDENT_BT819A = 819,
78
74 /* module bt866: just ident 866 */ 79 /* module bt866: just ident 866 */
75 V4L2_IDENT_BT866 = 866, 80 V4L2_IDENT_BT866 = 866,
76 81