diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2009-02-19 04:36:36 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-30 11:42:57 -0400 |
commit | c2179ad87240cf31b751f198c55140211e8cef89 (patch) | |
tree | 32d3bd98208430cd74e9da9a9826e4affb419379 /drivers/media/video/bt819.c | |
parent | 8e4e1d8054b037e867849162ba78cf9b153b0dcc (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>
Diffstat (limited to 'drivers/media/video/bt819.c')
-rw-r--r-- | drivers/media/video/bt819.c | 477 |
1 files changed, 252 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 | ||
43 | MODULE_DESCRIPTION("Brooktree-819 video decoder driver"); | 42 | MODULE_DESCRIPTION("Brooktree-819 video decoder driver"); |
@@ -48,13 +47,18 @@ static int debug; | |||
48 | module_param(debug, int, 0); | 47 | module_param(debug, int, 0); |
49 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); | 48 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); |
50 | 49 | ||
50 | static unsigned short normal_i2c[] = { 0x8a >> 1, I2C_CLIENT_END }; | ||
51 | |||
52 | I2C_CLIENT_INSMOD; | ||
53 | |||
51 | /* ----------------------------------------------------------------------- */ | 54 | /* ----------------------------------------------------------------------- */ |
52 | 55 | ||
53 | struct bt819 { | 56 | struct 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 | ||
70 | static inline struct bt819 *to_bt819(struct v4l2_subdev *sd) | ||
71 | { | ||
72 | return container_of(sd, struct bt819, sd); | ||
73 | } | ||
74 | |||
66 | struct timing { | 75 | struct 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 | ||
83 | static inline int bt819_write(struct i2c_client *client, u8 reg, u8 value) | 92 | static 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 | ||
91 | static inline int bt819_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value) | 100 | static 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 | ||
99 | static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned int len) | 106 | static 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 | ||
138 | static inline int bt819_read(struct i2c_client *client, u8 reg) | 146 | static 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 | ||
143 | static int bt819_init(struct i2c_client *client) | 153 | static 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 | ||
206 | static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg) | 215 | static 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); | 238 | static 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 */ | 243 | static 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 | |||
248 | static 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) { | 290 | static 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: | 313 | static 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: | 326 | static 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: | 351 | static 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: | 399 | static 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 | ||
422 | static 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 | |||
430 | static 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 | ||
440 | static unsigned short normal_i2c[] = { 0x8a >> 1, I2C_CLIENT_END }; | 437 | static 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 | ||
442 | I2C_CLIENT_INSMOD; | 444 | static const struct v4l2_subdev_tuner_ops bt819_tuner_ops = { |
445 | .s_std = bt819_s_std, | ||
446 | }; | ||
447 | |||
448 | static 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 | |||
455 | static 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 | ||
444 | static int bt819_probe(struct i2c_client *client, | 463 | static 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 | ||
494 | static int bt819_remove(struct i2c_client *client) | 518 | static 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 | ||