diff options
Diffstat (limited to 'drivers/media/video/saa5246a.c')
-rw-r--r-- | drivers/media/video/saa5246a.c | 69 |
1 files changed, 45 insertions, 24 deletions
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index 8f117bd50b86..da47b2f05288 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c | |||
@@ -46,10 +46,11 @@ | |||
46 | #include <linux/smp_lock.h> | 46 | #include <linux/smp_lock.h> |
47 | #include <linux/mutex.h> | 47 | #include <linux/mutex.h> |
48 | #include <linux/videotext.h> | 48 | #include <linux/videotext.h> |
49 | #include <linux/videodev.h> | 49 | #include <linux/videodev2.h> |
50 | #include <media/v4l2-common.h> | 50 | #include <media/v4l2-device.h> |
51 | #include <media/v4l2-chip-ident.h> | ||
51 | #include <media/v4l2-ioctl.h> | 52 | #include <media/v4l2-ioctl.h> |
52 | #include <media/v4l2-i2c-drv-legacy.h> | 53 | #include <media/v4l2-i2c-drv.h> |
53 | 54 | ||
54 | MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>"); | 55 | MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>"); |
55 | MODULE_DESCRIPTION("Philips SAA5246A, SAA5281 Teletext decoder driver"); | 56 | MODULE_DESCRIPTION("Philips SAA5246A, SAA5281 Teletext decoder driver"); |
@@ -388,13 +389,19 @@ MODULE_LICENSE("GPL"); | |||
388 | 389 | ||
389 | struct saa5246a_device | 390 | struct saa5246a_device |
390 | { | 391 | { |
392 | struct v4l2_subdev sd; | ||
393 | struct video_device *vdev; | ||
391 | u8 pgbuf[NUM_DAUS][VTX_VIRTUALSIZE]; | 394 | u8 pgbuf[NUM_DAUS][VTX_VIRTUALSIZE]; |
392 | int is_searching[NUM_DAUS]; | 395 | int is_searching[NUM_DAUS]; |
393 | struct i2c_client *client; | ||
394 | unsigned long in_use; | 396 | unsigned long in_use; |
395 | struct mutex lock; | 397 | struct mutex lock; |
396 | }; | 398 | }; |
397 | 399 | ||
400 | static inline struct saa5246a_device *to_dev(struct v4l2_subdev *sd) | ||
401 | { | ||
402 | return container_of(sd, struct saa5246a_device, sd); | ||
403 | } | ||
404 | |||
398 | static struct video_device saa_template; /* Declared near bottom */ | 405 | static struct video_device saa_template; /* Declared near bottom */ |
399 | 406 | ||
400 | /* | 407 | /* |
@@ -403,12 +410,13 @@ static struct video_device saa_template; /* Declared near bottom */ | |||
403 | 410 | ||
404 | static int i2c_sendbuf(struct saa5246a_device *t, int reg, int count, u8 *data) | 411 | static int i2c_sendbuf(struct saa5246a_device *t, int reg, int count, u8 *data) |
405 | { | 412 | { |
413 | struct i2c_client *client = v4l2_get_subdevdata(&t->sd); | ||
406 | char buf[64]; | 414 | char buf[64]; |
407 | 415 | ||
408 | buf[0] = reg; | 416 | buf[0] = reg; |
409 | memcpy(buf+1, data, count); | 417 | memcpy(buf+1, data, count); |
410 | 418 | ||
411 | if(i2c_master_send(t->client, buf, count+1)==count+1) | 419 | if (i2c_master_send(client, buf, count + 1) == count + 1) |
412 | return 0; | 420 | return 0; |
413 | return -1; | 421 | return -1; |
414 | } | 422 | } |
@@ -436,7 +444,9 @@ static int i2c_senddata(struct saa5246a_device *t, ...) | |||
436 | */ | 444 | */ |
437 | static int i2c_getdata(struct saa5246a_device *t, int count, u8 *buf) | 445 | static int i2c_getdata(struct saa5246a_device *t, int count, u8 *buf) |
438 | { | 446 | { |
439 | if(i2c_master_recv(t->client, buf, count)!=count) | 447 | struct i2c_client *client = v4l2_get_subdevdata(&t->sd); |
448 | |||
449 | if (i2c_master_recv(client, buf, count) != count) | ||
440 | return -1; | 450 | return -1; |
441 | return 0; | 451 | return 0; |
442 | } | 452 | } |
@@ -961,9 +971,6 @@ static int saa5246a_open(struct file *file) | |||
961 | { | 971 | { |
962 | struct saa5246a_device *t = video_drvdata(file); | 972 | struct saa5246a_device *t = video_drvdata(file); |
963 | 973 | ||
964 | if (t->client == NULL) | ||
965 | return -ENODEV; | ||
966 | |||
967 | if (test_and_set_bit(0, &t->in_use)) | 974 | if (test_and_set_bit(0, &t->in_use)) |
968 | return -EBUSY; | 975 | return -EBUSY; |
969 | 976 | ||
@@ -1033,18 +1040,29 @@ static struct video_device saa_template = | |||
1033 | .minor = -1, | 1040 | .minor = -1, |
1034 | }; | 1041 | }; |
1035 | 1042 | ||
1036 | /* Addresses to scan */ | 1043 | static int saa5246a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) |
1037 | static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; | 1044 | { |
1045 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1046 | |||
1047 | return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA5246A, 0); | ||
1048 | } | ||
1049 | |||
1050 | static const struct v4l2_subdev_core_ops saa5246a_core_ops = { | ||
1051 | .g_chip_ident = saa5246a_g_chip_ident, | ||
1052 | }; | ||
1053 | |||
1054 | static const struct v4l2_subdev_ops saa5246a_ops = { | ||
1055 | .core = &saa5246a_core_ops, | ||
1056 | }; | ||
1038 | 1057 | ||
1039 | I2C_CLIENT_INSMOD; | ||
1040 | 1058 | ||
1041 | static int saa5246a_probe(struct i2c_client *client, | 1059 | static int saa5246a_probe(struct i2c_client *client, |
1042 | const struct i2c_device_id *id) | 1060 | const struct i2c_device_id *id) |
1043 | { | 1061 | { |
1044 | int pgbuf; | 1062 | int pgbuf; |
1045 | int err; | 1063 | int err; |
1046 | struct video_device *vd; | ||
1047 | struct saa5246a_device *t; | 1064 | struct saa5246a_device *t; |
1065 | struct v4l2_subdev *sd; | ||
1048 | 1066 | ||
1049 | v4l_info(client, "chip found @ 0x%x (%s)\n", | 1067 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
1050 | client->addr << 1, client->adapter->name); | 1068 | client->addr << 1, client->adapter->name); |
@@ -1053,40 +1071,43 @@ static int saa5246a_probe(struct i2c_client *client, | |||
1053 | t = kzalloc(sizeof(*t), GFP_KERNEL); | 1071 | t = kzalloc(sizeof(*t), GFP_KERNEL); |
1054 | if (t == NULL) | 1072 | if (t == NULL) |
1055 | return -ENOMEM; | 1073 | return -ENOMEM; |
1074 | sd = &t->sd; | ||
1075 | v4l2_i2c_subdev_init(sd, client, &saa5246a_ops); | ||
1056 | mutex_init(&t->lock); | 1076 | mutex_init(&t->lock); |
1057 | 1077 | ||
1058 | /* Now create a video4linux device */ | 1078 | /* Now create a video4linux device */ |
1059 | vd = video_device_alloc(); | 1079 | t->vdev = video_device_alloc(); |
1060 | if (vd == NULL) { | 1080 | if (t->vdev == NULL) { |
1061 | kfree(t); | 1081 | kfree(t); |
1062 | return -ENOMEM; | 1082 | return -ENOMEM; |
1063 | } | 1083 | } |
1064 | i2c_set_clientdata(client, vd); | 1084 | memcpy(t->vdev, &saa_template, sizeof(*t->vdev)); |
1065 | memcpy(vd, &saa_template, sizeof(*vd)); | ||
1066 | 1085 | ||
1067 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { | 1086 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { |
1068 | memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0])); | 1087 | memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0])); |
1069 | t->is_searching[pgbuf] = false; | 1088 | t->is_searching[pgbuf] = false; |
1070 | } | 1089 | } |
1071 | video_set_drvdata(vd, t); | 1090 | video_set_drvdata(t->vdev, t); |
1072 | 1091 | ||
1073 | /* Register it */ | 1092 | /* Register it */ |
1074 | err = video_register_device(vd, VFL_TYPE_VTX, -1); | 1093 | err = video_register_device(t->vdev, VFL_TYPE_VTX, -1); |
1075 | if (err < 0) { | 1094 | if (err < 0) { |
1076 | kfree(t); | 1095 | kfree(t); |
1077 | video_device_release(vd); | 1096 | video_device_release(t->vdev); |
1097 | t->vdev = NULL; | ||
1078 | return err; | 1098 | return err; |
1079 | } | 1099 | } |
1080 | t->client = client; | ||
1081 | return 0; | 1100 | return 0; |
1082 | } | 1101 | } |
1083 | 1102 | ||
1084 | static int saa5246a_remove(struct i2c_client *client) | 1103 | static int saa5246a_remove(struct i2c_client *client) |
1085 | { | 1104 | { |
1086 | struct video_device *vd = i2c_get_clientdata(client); | 1105 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
1106 | struct saa5246a_device *t = to_dev(sd); | ||
1087 | 1107 | ||
1088 | video_unregister_device(vd); | 1108 | video_unregister_device(t->vdev); |
1089 | kfree(video_get_drvdata(vd)); | 1109 | v4l2_device_unregister_subdev(sd); |
1110 | kfree(t); | ||
1090 | return 0; | 1111 | return 0; |
1091 | } | 1112 | } |
1092 | 1113 | ||