aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/saa7185.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/saa7185.c')
-rw-r--r--drivers/media/video/saa7185.c217
1 files changed, 119 insertions, 98 deletions
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index fc51e6c9cb95..b4eb66253bc2 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -30,51 +30,61 @@
30#include <asm/uaccess.h> 30#include <asm/uaccess.h>
31#include <linux/i2c.h> 31#include <linux/i2c.h>
32#include <linux/i2c-id.h> 32#include <linux/i2c-id.h>
33#include <linux/videodev.h> 33#include <linux/videodev2.h>
34#include <linux/video_encoder.h> 34#include <media/v4l2-device.h>
35#include <media/v4l2-common.h> 35#include <media/v4l2-chip-ident.h>
36#include <media/v4l2-i2c-drv-legacy.h> 36#include <media/v4l2-i2c-drv-legacy.h>
37 37
38MODULE_DESCRIPTION("Philips SAA7185 video encoder driver"); 38MODULE_DESCRIPTION("Philips SAA7185 video encoder driver");
39MODULE_AUTHOR("Dave Perks"); 39MODULE_AUTHOR("Dave Perks");
40MODULE_LICENSE("GPL"); 40MODULE_LICENSE("GPL");
41 41
42
43static int debug; 42static int debug;
44module_param(debug, int, 0); 43module_param(debug, int, 0);
45MODULE_PARM_DESC(debug, "Debug level (0-1)"); 44MODULE_PARM_DESC(debug, "Debug level (0-1)");
46 45
46static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
47
48I2C_CLIENT_INSMOD;
49
47/* ----------------------------------------------------------------------- */ 50/* ----------------------------------------------------------------------- */
48 51
49struct saa7185 { 52struct saa7185 {
53 struct v4l2_subdev sd;
50 unsigned char reg[128]; 54 unsigned char reg[128];
51 55
52 v4l2_std_id norm; 56 v4l2_std_id norm;
53 int bright;
54 int contrast;
55 int hue;
56 int sat;
57}; 57};
58 58
59static inline struct saa7185 *to_saa7185(struct v4l2_subdev *sd)
60{
61 return container_of(sd, struct saa7185, sd);
62}
63
59/* ----------------------------------------------------------------------- */ 64/* ----------------------------------------------------------------------- */
60 65
61static inline int saa7185_read(struct i2c_client *client) 66static inline int saa7185_read(struct v4l2_subdev *sd)
62{ 67{
68 struct i2c_client *client = v4l2_get_subdevdata(sd);
69
63 return i2c_smbus_read_byte(client); 70 return i2c_smbus_read_byte(client);
64} 71}
65 72
66static int saa7185_write(struct i2c_client *client, u8 reg, u8 value) 73static int saa7185_write(struct v4l2_subdev *sd, u8 reg, u8 value)
67{ 74{
68 struct saa7185 *encoder = i2c_get_clientdata(client); 75 struct i2c_client *client = v4l2_get_subdevdata(sd);
76 struct saa7185 *encoder = to_saa7185(sd);
69 77
70 v4l_dbg(1, debug, client, "%02x set to %02x\n", reg, value); 78 v4l2_dbg(1, debug, sd, "%02x set to %02x\n", reg, value);
71 encoder->reg[reg] = value; 79 encoder->reg[reg] = value;
72 return i2c_smbus_write_byte_data(client, reg, value); 80 return i2c_smbus_write_byte_data(client, reg, value);
73} 81}
74 82
75static int saa7185_write_block(struct i2c_client *client, 83static int saa7185_write_block(struct v4l2_subdev *sd,
76 const u8 *data, unsigned int len) 84 const u8 *data, unsigned int len)
77{ 85{
86 struct i2c_client *client = v4l2_get_subdevdata(sd);
87 struct saa7185 *encoder = to_saa7185(sd);
78 int ret = -1; 88 int ret = -1;
79 u8 reg; 89 u8 reg;
80 90
@@ -82,7 +92,6 @@ static int saa7185_write_block(struct i2c_client *client,
82 * the adapter understands raw I2C */ 92 * the adapter understands raw I2C */
83 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 93 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
84 /* do raw I2C, not smbus compatible */ 94 /* do raw I2C, not smbus compatible */
85 struct saa7185 *encoder = i2c_get_clientdata(client);
86 u8 block_data[32]; 95 u8 block_data[32];
87 int block_len; 96 int block_len;
88 97
@@ -103,7 +112,7 @@ static int saa7185_write_block(struct i2c_client *client,
103 /* do some slow I2C emulation kind of thing */ 112 /* do some slow I2C emulation kind of thing */
104 while (len >= 2) { 113 while (len >= 2) {
105 reg = *data++; 114 reg = *data++;
106 ret = saa7185_write(client, reg, *data++); 115 ret = saa7185_write(sd, reg, *data++);
107 if (ret < 0) 116 if (ret < 0)
108 break; 117 break;
109 len -= 2; 118 len -= 2;
@@ -212,101 +221,111 @@ static const unsigned char init_ntsc[] = {
212 0x66, 0x21, /* FSC3 */ 221 0x66, 0x21, /* FSC3 */
213}; 222};
214 223
215static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) 224
225static int saa7185_init(struct v4l2_subdev *sd, u32 val)
226{
227 struct saa7185 *encoder = to_saa7185(sd);
228
229 saa7185_write_block(sd, init_common, sizeof(init_common));
230 if (encoder->norm & V4L2_STD_NTSC)
231 saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
232 else
233 saa7185_write_block(sd, init_pal, sizeof(init_pal));
234 return 0;
235}
236
237static int saa7185_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
238{
239 struct saa7185 *encoder = to_saa7185(sd);
240
241 if (std & V4L2_STD_NTSC)
242 saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
243 else if (std & V4L2_STD_PAL)
244 saa7185_write_block(sd, init_pal, sizeof(init_pal));
245 else
246 return -EINVAL;
247 encoder->norm = std;
248 return 0;
249}
250
251static int saa7185_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
216{ 252{
217 struct saa7185 *encoder = i2c_get_clientdata(client); 253 struct saa7185 *encoder = to_saa7185(sd);
218 254
219 switch (cmd) { 255 /* RJ: route->input = 0: input is from SA7111
220 case VIDIOC_INT_INIT: 256 route->input = 1: input is from ZR36060 */
221 saa7185_write_block(client, init_common, 257
222 sizeof(init_common)); 258 switch (route->input) {
223 if (encoder->norm & V4L2_STD_NTSC) 259 case 0:
224 saa7185_write_block(client, init_ntsc, 260 /* turn off colorbar */
225 sizeof(init_ntsc)); 261 saa7185_write(sd, 0x3a, 0x0f);
226 else 262 /* Switch RTCE to 1 */
227 saa7185_write_block(client, init_pal, 263 saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08);
228 sizeof(init_pal)); 264 saa7185_write(sd, 0x6e, 0x01);
229 break; 265 break;
230 266
231 case VIDIOC_INT_S_STD_OUTPUT: 267 case 1:
232 { 268 /* turn off colorbar */
233 v4l2_std_id *iarg = arg; 269 saa7185_write(sd, 0x3a, 0x0f);
234 270 /* Switch RTCE to 0 */
235 //saa7185_write_block(client, init_common, sizeof(init_common)); 271 saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00);
236 272 /* SW: a slight sync problem... */
237 if (*iarg & V4L2_STD_NTSC) 273 saa7185_write(sd, 0x6e, 0x00);
238 saa7185_write_block(client, init_ntsc,
239 sizeof(init_ntsc));
240 else if (*iarg & V4L2_STD_PAL)
241 saa7185_write_block(client, init_pal,
242 sizeof(init_pal));
243 else
244 return -EINVAL;
245 encoder->norm = *iarg;
246 break; 274 break;
247 }
248 275
249 case VIDIOC_INT_S_VIDEO_ROUTING: 276 case 2:
250 { 277 /* turn on colorbar */
251 struct v4l2_routing *route = arg; 278 saa7185_write(sd, 0x3a, 0x8f);
252 279 /* Switch RTCE to 0 */
253 /* RJ: route->input = 0: input is from SA7111 280 saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08);
254 route->input = 1: input is from ZR36060 */ 281 /* SW: a slight sync problem... */
255 282 saa7185_write(sd, 0x6e, 0x01);
256 switch (route->input) {
257 case 0:
258 /* turn off colorbar */
259 saa7185_write(client, 0x3a, 0x0f);
260 /* Switch RTCE to 1 */
261 saa7185_write(client, 0x61,
262 (encoder->reg[0x61] & 0xf7) | 0x08);
263 saa7185_write(client, 0x6e, 0x01);
264 break;
265
266 case 1:
267 /* turn off colorbar */
268 saa7185_write(client, 0x3a, 0x0f);
269 /* Switch RTCE to 0 */
270 saa7185_write(client, 0x61,
271 (encoder->reg[0x61] & 0xf7) | 0x00);
272 /* SW: a slight sync problem... */
273 saa7185_write(client, 0x6e, 0x00);
274 break;
275
276 case 2:
277 /* turn on colorbar */
278 saa7185_write(client, 0x3a, 0x8f);
279 /* Switch RTCE to 0 */
280 saa7185_write(client, 0x61,
281 (encoder->reg[0x61] & 0xf7) | 0x08);
282 /* SW: a slight sync problem... */
283 saa7185_write(client, 0x6e, 0x01);
284 break;
285
286 default:
287 return -EINVAL;
288 }
289 break; 283 break;
290 }
291 284
292 default: 285 default:
293 return -EINVAL; 286 return -EINVAL;
294 } 287 }
295
296 return 0; 288 return 0;
297} 289}
298 290
291static int saa7185_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
292{
293 struct i2c_client *client = v4l2_get_subdevdata(sd);
294
295 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7185, 0);
296}
297
298static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg)
299{
300 return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
301}
302
299/* ----------------------------------------------------------------------- */ 303/* ----------------------------------------------------------------------- */
300 304
301static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; 305static const struct v4l2_subdev_core_ops saa7185_core_ops = {
306 .g_chip_ident = saa7185_g_chip_ident,
307 .init = saa7185_init,
308};
302 309
303I2C_CLIENT_INSMOD; 310static const struct v4l2_subdev_video_ops saa7185_video_ops = {
311 .s_std_output = saa7185_s_std_output,
312 .s_routing = saa7185_s_routing,
313};
314
315static const struct v4l2_subdev_ops saa7185_ops = {
316 .core = &saa7185_core_ops,
317 .video = &saa7185_video_ops,
318};
319
320
321/* ----------------------------------------------------------------------- */
304 322
305static int saa7185_probe(struct i2c_client *client, 323static int saa7185_probe(struct i2c_client *client,
306 const struct i2c_device_id *id) 324 const struct i2c_device_id *id)
307{ 325{
308 int i; 326 int i;
309 struct saa7185 *encoder; 327 struct saa7185 *encoder;
328 struct v4l2_subdev *sd;
310 329
311 /* Check if the adapter supports the needed features */ 330 /* Check if the adapter supports the needed features */
312 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 331 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -319,26 +338,28 @@ static int saa7185_probe(struct i2c_client *client,
319 if (encoder == NULL) 338 if (encoder == NULL)
320 return -ENOMEM; 339 return -ENOMEM;
321 encoder->norm = V4L2_STD_NTSC; 340 encoder->norm = V4L2_STD_NTSC;
322 i2c_set_clientdata(client, encoder); 341 sd = &encoder->sd;
342 v4l2_i2c_subdev_init(sd, client, &saa7185_ops);
323 343
324 i = saa7185_write_block(client, init_common, sizeof(init_common)); 344 i = saa7185_write_block(sd, init_common, sizeof(init_common));
325 if (i >= 0) 345 if (i >= 0)
326 i = saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); 346 i = saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
327 if (i < 0) 347 if (i < 0)
328 v4l_dbg(1, debug, client, "init error %d\n", i); 348 v4l2_dbg(1, debug, sd, "init error %d\n", i);
329 else 349 else
330 v4l_dbg(1, debug, client, "revision 0x%x\n", 350 v4l2_dbg(1, debug, sd, "revision 0x%x\n",
331 saa7185_read(client) >> 5); 351 saa7185_read(sd) >> 5);
332 return 0; 352 return 0;
333} 353}
334 354
335static int saa7185_remove(struct i2c_client *client) 355static int saa7185_remove(struct i2c_client *client)
336{ 356{
337 struct saa7185 *encoder = i2c_get_clientdata(client); 357 struct v4l2_subdev *sd = i2c_get_clientdata(client);
338 358 struct saa7185 *encoder = to_saa7185(sd);
339 saa7185_write(client, 0x61, (encoder->reg[0x61]) | 0x40); /* SW: output off is active */
340 //saa7185_write(client, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */
341 359
360 v4l2_device_unregister_subdev(sd);
361 /* SW: output off is active */
362 saa7185_write(sd, 0x61, (encoder->reg[0x61]) | 0x40);
342 kfree(encoder); 363 kfree(encoder);
343 return 0; 364 return 0;
344} 365}