diff options
Diffstat (limited to 'drivers/media/video/saa5249.c')
-rw-r--r-- | drivers/media/video/saa5249.c | 71 |
1 files changed, 45 insertions, 26 deletions
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index e29765192469..48b27fe48087 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c | |||
@@ -50,15 +50,17 @@ | |||
50 | #include <linux/mutex.h> | 50 | #include <linux/mutex.h> |
51 | #include <linux/delay.h> | 51 | #include <linux/delay.h> |
52 | #include <linux/videotext.h> | 52 | #include <linux/videotext.h> |
53 | #include <linux/videodev.h> | 53 | #include <linux/videodev2.h> |
54 | #include <media/v4l2-common.h> | 54 | #include <media/v4l2-device.h> |
55 | #include <media/v4l2-chip-ident.h> | ||
55 | #include <media/v4l2-ioctl.h> | 56 | #include <media/v4l2-ioctl.h> |
56 | #include <media/v4l2-i2c-drv-legacy.h> | 57 | #include <media/v4l2-i2c-drv.h> |
57 | 58 | ||
58 | MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>"); | 59 | MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>"); |
59 | MODULE_DESCRIPTION("Philips SAA5249 Teletext decoder driver"); | 60 | MODULE_DESCRIPTION("Philips SAA5249 Teletext decoder driver"); |
60 | MODULE_LICENSE("GPL"); | 61 | MODULE_LICENSE("GPL"); |
61 | 62 | ||
63 | |||
62 | #define VTX_VER_MAJ 1 | 64 | #define VTX_VER_MAJ 1 |
63 | #define VTX_VER_MIN 8 | 65 | #define VTX_VER_MIN 8 |
64 | 66 | ||
@@ -95,17 +97,23 @@ typedef struct { | |||
95 | 97 | ||
96 | struct saa5249_device | 98 | struct saa5249_device |
97 | { | 99 | { |
100 | struct v4l2_subdev sd; | ||
101 | struct video_device *vdev; | ||
98 | vdau_t vdau[NUM_DAUS]; /* Data for virtual DAUs (the 5249 only has one */ | 102 | vdau_t vdau[NUM_DAUS]; /* Data for virtual DAUs (the 5249 only has one */ |
99 | /* real DAU, so we have to simulate some more) */ | 103 | /* real DAU, so we have to simulate some more) */ |
100 | int vtx_use_count; | 104 | int vtx_use_count; |
101 | int is_searching[NUM_DAUS]; | 105 | int is_searching[NUM_DAUS]; |
102 | int disp_mode; | 106 | int disp_mode; |
103 | int virtual_mode; | 107 | int virtual_mode; |
104 | struct i2c_client *client; | ||
105 | unsigned long in_use; | 108 | unsigned long in_use; |
106 | struct mutex lock; | 109 | struct mutex lock; |
107 | }; | 110 | }; |
108 | 111 | ||
112 | static inline struct saa5249_device *to_dev(struct v4l2_subdev *sd) | ||
113 | { | ||
114 | return container_of(sd, struct saa5249_device, sd); | ||
115 | } | ||
116 | |||
109 | 117 | ||
110 | #define CCTWR 34 /* I²C write/read-address of vtx-chip */ | 118 | #define CCTWR 34 /* I²C write/read-address of vtx-chip */ |
111 | #define CCTRD 35 | 119 | #define CCTRD 35 |
@@ -147,12 +155,13 @@ static void jdelay(unsigned long delay) | |||
147 | 155 | ||
148 | static int i2c_sendbuf(struct saa5249_device *t, int reg, int count, u8 *data) | 156 | static int i2c_sendbuf(struct saa5249_device *t, int reg, int count, u8 *data) |
149 | { | 157 | { |
158 | struct i2c_client *client = v4l2_get_subdevdata(&t->sd); | ||
150 | char buf[64]; | 159 | char buf[64]; |
151 | 160 | ||
152 | buf[0] = reg; | 161 | buf[0] = reg; |
153 | memcpy(buf+1, data, count); | 162 | memcpy(buf+1, data, count); |
154 | 163 | ||
155 | if (i2c_master_send(t->client, buf, count + 1) == count + 1) | 164 | if (i2c_master_send(client, buf, count + 1) == count + 1) |
156 | return 0; | 165 | return 0; |
157 | return -1; | 166 | return -1; |
158 | } | 167 | } |
@@ -180,7 +189,9 @@ static int i2c_senddata(struct saa5249_device *t, ...) | |||
180 | 189 | ||
181 | static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf) | 190 | static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf) |
182 | { | 191 | { |
183 | if(i2c_master_recv(t->client, buf, count)!=count) | 192 | struct i2c_client *client = v4l2_get_subdevdata(&t->sd); |
193 | |||
194 | if (i2c_master_recv(client, buf, count) != count) | ||
184 | return -1; | 195 | return -1; |
185 | return 0; | 196 | return 0; |
186 | } | 197 | } |
@@ -497,9 +508,6 @@ static int saa5249_open(struct file *file) | |||
497 | struct saa5249_device *t = video_drvdata(file); | 508 | struct saa5249_device *t = video_drvdata(file); |
498 | int pgbuf; | 509 | int pgbuf; |
499 | 510 | ||
500 | if (t->client == NULL) | ||
501 | return -ENODEV; | ||
502 | |||
503 | if (test_and_set_bit(0, &t->in_use)) | 511 | if (test_and_set_bit(0, &t->in_use)) |
504 | return -EBUSY; | 512 | return -EBUSY; |
505 | 513 | ||
@@ -553,18 +561,28 @@ static struct video_device saa_template = | |||
553 | .release = video_device_release, | 561 | .release = video_device_release, |
554 | }; | 562 | }; |
555 | 563 | ||
556 | /* Addresses to scan */ | 564 | static int saa5249_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) |
557 | static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; | 565 | { |
566 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
567 | |||
568 | return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA5249, 0); | ||
569 | } | ||
558 | 570 | ||
559 | I2C_CLIENT_INSMOD; | 571 | static const struct v4l2_subdev_core_ops saa5249_core_ops = { |
572 | .g_chip_ident = saa5249_g_chip_ident, | ||
573 | }; | ||
574 | |||
575 | static const struct v4l2_subdev_ops saa5249_ops = { | ||
576 | .core = &saa5249_core_ops, | ||
577 | }; | ||
560 | 578 | ||
561 | static int saa5249_probe(struct i2c_client *client, | 579 | static int saa5249_probe(struct i2c_client *client, |
562 | const struct i2c_device_id *id) | 580 | const struct i2c_device_id *id) |
563 | { | 581 | { |
564 | int pgbuf; | 582 | int pgbuf; |
565 | int err; | 583 | int err; |
566 | struct video_device *vd; | ||
567 | struct saa5249_device *t; | 584 | struct saa5249_device *t; |
585 | struct v4l2_subdev *sd; | ||
568 | 586 | ||
569 | v4l_info(client, "chip found @ 0x%x (%s)\n", | 587 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
570 | client->addr << 1, client->adapter->name); | 588 | client->addr << 1, client->adapter->name); |
@@ -573,16 +591,17 @@ static int saa5249_probe(struct i2c_client *client, | |||
573 | t = kzalloc(sizeof(*t), GFP_KERNEL); | 591 | t = kzalloc(sizeof(*t), GFP_KERNEL); |
574 | if (t == NULL) | 592 | if (t == NULL) |
575 | return -ENOMEM; | 593 | return -ENOMEM; |
594 | sd = &t->sd; | ||
595 | v4l2_i2c_subdev_init(sd, client, &saa5249_ops); | ||
576 | mutex_init(&t->lock); | 596 | mutex_init(&t->lock); |
577 | 597 | ||
578 | /* Now create a video4linux device */ | 598 | /* Now create a video4linux device */ |
579 | vd = kmalloc(sizeof(struct video_device), GFP_KERNEL); | 599 | t->vdev = video_device_alloc(); |
580 | if (vd == NULL) { | 600 | if (t->vdev == NULL) { |
581 | kfree(client); | 601 | kfree(client); |
582 | return -ENOMEM; | 602 | return -ENOMEM; |
583 | } | 603 | } |
584 | i2c_set_clientdata(client, vd); | 604 | memcpy(t->vdev, &saa_template, sizeof(*t->vdev)); |
585 | memcpy(vd, &saa_template, sizeof(*vd)); | ||
586 | 605 | ||
587 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { | 606 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { |
588 | memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); | 607 | memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); |
@@ -593,26 +612,27 @@ static int saa5249_probe(struct i2c_client *client, | |||
593 | t->vdau[pgbuf].stopped = true; | 612 | t->vdau[pgbuf].stopped = true; |
594 | t->is_searching[pgbuf] = false; | 613 | t->is_searching[pgbuf] = false; |
595 | } | 614 | } |
596 | video_set_drvdata(vd, t); | 615 | video_set_drvdata(t->vdev, t); |
597 | 616 | ||
598 | /* Register it */ | 617 | /* Register it */ |
599 | err = video_register_device(vd, VFL_TYPE_VTX, -1); | 618 | err = video_register_device(t->vdev, VFL_TYPE_VTX, -1); |
600 | if (err < 0) { | 619 | if (err < 0) { |
601 | kfree(t); | 620 | kfree(t); |
602 | kfree(vd); | 621 | video_device_release(t->vdev); |
622 | t->vdev = NULL; | ||
603 | return err; | 623 | return err; |
604 | } | 624 | } |
605 | t->client = client; | ||
606 | return 0; | 625 | return 0; |
607 | } | 626 | } |
608 | 627 | ||
609 | static int saa5249_remove(struct i2c_client *client) | 628 | static int saa5249_remove(struct i2c_client *client) |
610 | { | 629 | { |
611 | struct video_device *vd = i2c_get_clientdata(client); | 630 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
631 | struct saa5249_device *t = to_dev(sd); | ||
612 | 632 | ||
613 | video_unregister_device(vd); | 633 | video_unregister_device(t->vdev); |
614 | kfree(video_get_drvdata(vd)); | 634 | v4l2_device_unregister_subdev(sd); |
615 | kfree(vd); | 635 | kfree(t); |
616 | return 0; | 636 | return 0; |
617 | } | 637 | } |
618 | 638 | ||
@@ -624,7 +644,6 @@ MODULE_DEVICE_TABLE(i2c, saa5249_id); | |||
624 | 644 | ||
625 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | 645 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
626 | .name = "saa5249", | 646 | .name = "saa5249", |
627 | .driverid = I2C_DRIVERID_SAA5249, | ||
628 | .probe = saa5249_probe, | 647 | .probe = saa5249_probe, |
629 | .remove = saa5249_remove, | 648 | .remove = saa5249_remove, |
630 | .id_table = saa5249_id, | 649 | .id_table = saa5249_id, |