diff options
-rw-r--r-- | drivers/media/video/Kconfig | 2 | ||||
-rw-r--r-- | drivers/media/video/pms.c | 472 |
2 files changed, 287 insertions, 187 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 82ae85c975f5..9dc74c93bf24 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -600,7 +600,7 @@ source "drivers/media/video/bt8xx/Kconfig" | |||
600 | 600 | ||
601 | config VIDEO_PMS | 601 | config VIDEO_PMS |
602 | tristate "Mediavision Pro Movie Studio Video For Linux" | 602 | tristate "Mediavision Pro Movie Studio Video For Linux" |
603 | depends on ISA && VIDEO_V4L1 | 603 | depends on ISA && VIDEO_V4L2 |
604 | help | 604 | help |
605 | Say Y if you have such a thing. | 605 | Say Y if you have such a thing. |
606 | 606 | ||
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 2919aa42c94e..73ec970ca5ca 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c | |||
@@ -14,8 +14,10 @@ | |||
14 | * unless the userspace driver also doesn't work for you... | 14 | * unless the userspace driver also doesn't work for you... |
15 | * | 15 | * |
16 | * Changes: | 16 | * Changes: |
17 | * 08/07/2003 Daniele Bellucci <bellucda@tiscali.it> | 17 | * 25-11-2009 Hans Verkuil <hverkuil@xs4all.nl> |
18 | * - pms_capture: report back -EFAULT | 18 | * - converted to version 2 of the V4L API. |
19 | * 08/07/2003 Daniele Bellucci <bellucda@tiscali.it> | ||
20 | * - pms_capture: report back -EFAULT | ||
19 | */ | 21 | */ |
20 | 22 | ||
21 | #include <linux/module.h> | 23 | #include <linux/module.h> |
@@ -27,20 +29,21 @@ | |||
27 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
28 | #include <linux/ioport.h> | 30 | #include <linux/ioport.h> |
29 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/version.h> | ||
33 | #include <linux/mutex.h> | ||
34 | #include <asm/uaccess.h> | ||
30 | #include <asm/io.h> | 35 | #include <asm/io.h> |
31 | #include <linux/videodev.h> | 36 | |
37 | #include <linux/videodev2.h> | ||
32 | #include <media/v4l2-common.h> | 38 | #include <media/v4l2-common.h> |
33 | #include <media/v4l2-ioctl.h> | 39 | #include <media/v4l2-ioctl.h> |
34 | #include <media/v4l2-device.h> | 40 | #include <media/v4l2-device.h> |
35 | #include <linux/mutex.h> | ||
36 | |||
37 | #include <asm/uaccess.h> | ||
38 | 41 | ||
39 | MODULE_LICENSE("GPL"); | 42 | MODULE_LICENSE("GPL"); |
40 | 43 | ||
41 | 44 | ||
42 | #define MOTOROLA 1 | 45 | #define MOTOROLA 1 |
43 | #define PHILIPS2 2 | 46 | #define PHILIPS2 2 /* SAA7191 */ |
44 | #define PHILIPS1 3 | 47 | #define PHILIPS1 3 |
45 | #define MVVMEMORYWIDTH 0x40 /* 512 bytes */ | 48 | #define MVVMEMORYWIDTH 0x40 /* 512 bytes */ |
46 | 49 | ||
@@ -54,9 +57,11 @@ struct i2c_info { | |||
54 | struct pms { | 57 | struct pms { |
55 | struct v4l2_device v4l2_dev; | 58 | struct v4l2_device v4l2_dev; |
56 | struct video_device vdev; | 59 | struct video_device vdev; |
57 | struct video_picture picture; | ||
58 | int height; | 60 | int height; |
59 | int width; | 61 | int width; |
62 | int depth; | ||
63 | int input; | ||
64 | s32 brightness, saturation, hue, contrast; | ||
60 | unsigned long in_use; | 65 | unsigned long in_use; |
61 | struct mutex lock; | 66 | struct mutex lock; |
62 | int i2c_count; | 67 | int i2c_count; |
@@ -64,6 +69,7 @@ struct pms { | |||
64 | 69 | ||
65 | int decoder; | 70 | int decoder; |
66 | int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ | 71 | int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ |
72 | v4l2_std_id std; | ||
67 | int io; | 73 | int io; |
68 | int data; | 74 | int data; |
69 | void __iomem *mem; | 75 | void __iomem *mem; |
@@ -209,7 +215,19 @@ static void pms_i2c_andor(struct pms *dev, int slave, int sub, int and, int or) | |||
209 | 215 | ||
210 | static void pms_videosource(struct pms *dev, short source) | 216 | static void pms_videosource(struct pms *dev, short source) |
211 | { | 217 | { |
212 | mvv_write(dev, 0x2E, source ? 0x31 : 0x30); | 218 | switch (dev->decoder) { |
219 | case MOTOROLA: | ||
220 | break; | ||
221 | case PHILIPS2: | ||
222 | pms_i2c_andor(dev, 0x8a, 0x06, 0x7f, source ? 0x80 : 0); | ||
223 | break; | ||
224 | case PHILIPS1: | ||
225 | break; | ||
226 | } | ||
227 | mvv_write(dev, 0x2E, 0x31); | ||
228 | /* Was: mvv_write(dev, 0x2E, source ? 0x31 : 0x30); | ||
229 | But could not make this work correctly. Only Composite input | ||
230 | worked for me. */ | ||
213 | } | 231 | } |
214 | 232 | ||
215 | static void pms_hue(struct pms *dev, short hue) | 233 | static void pms_hue(struct pms *dev, short hue) |
@@ -227,14 +245,14 @@ static void pms_hue(struct pms *dev, short hue) | |||
227 | } | 245 | } |
228 | } | 246 | } |
229 | 247 | ||
230 | static void pms_colour(struct pms *dev, short colour) | 248 | static void pms_saturation(struct pms *dev, short sat) |
231 | { | 249 | { |
232 | switch (dev->decoder) { | 250 | switch (dev->decoder) { |
233 | case MOTOROLA: | 251 | case MOTOROLA: |
234 | pms_i2c_write(dev, 0x8a, 0x00, colour); | 252 | pms_i2c_write(dev, 0x8a, 0x00, sat); |
235 | break; | 253 | break; |
236 | case PHILIPS1: | 254 | case PHILIPS1: |
237 | pms_i2c_write(dev, 0x42, 0x12, colour); | 255 | pms_i2c_write(dev, 0x42, 0x12, sat); |
238 | break; | 256 | break; |
239 | } | 257 | } |
240 | } | 258 | } |
@@ -467,7 +485,7 @@ static void pms_swsense(struct pms *dev, short sense) | |||
467 | 485 | ||
468 | static void pms_framerate(struct pms *dev, short frr) | 486 | static void pms_framerate(struct pms *dev, short frr) |
469 | { | 487 | { |
470 | int fps = (dev->standard == 1) ? 30 : 25; | 488 | int fps = (dev->std & V4L2_STD_525_60) ? 30 : 25; |
471 | 489 | ||
472 | if (frr == 0) | 490 | if (frr == 0) |
473 | return; | 491 | return; |
@@ -557,7 +575,7 @@ static void pms_resolution(struct pms *dev, short width, short height) | |||
557 | mvv_write(dev, 0x18, fg_height); | 575 | mvv_write(dev, 0x18, fg_height); |
558 | mvv_write(dev, 0x19, fg_height >> 8); | 576 | mvv_write(dev, 0x19, fg_height >> 8); |
559 | 577 | ||
560 | if (dev->standard == 1) { | 578 | if (dev->std & V4L2_STD_525_60) { |
561 | mvv_write(dev, 0x1a, 0xfc); | 579 | mvv_write(dev, 0x1a, 0xfc); |
562 | mvv_write(dev, 0x1b, 0x00); | 580 | mvv_write(dev, 0x1b, 0x00); |
563 | if (height > fg_height) | 581 | if (height > fg_height) |
@@ -581,7 +599,7 @@ static void pms_resolution(struct pms *dev, short width, short height) | |||
581 | mvv_write(dev, 0x22, width + 8); | 599 | mvv_write(dev, 0x22, width + 8); |
582 | mvv_write(dev, 0x23, (width + 8) >> 8); | 600 | mvv_write(dev, 0x23, (width + 8) >> 8); |
583 | 601 | ||
584 | if (dev->standard == 1) | 602 | if (dev->std & V4L2_STD_525_60) |
585 | pms_horzdeci(dev, width, 640); | 603 | pms_horzdeci(dev, width, 640); |
586 | else | 604 | else |
587 | pms_horzdeci(dev, width + 8, 768); | 605 | pms_horzdeci(dev, width + 8, 768); |
@@ -654,192 +672,252 @@ static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count) | |||
654 | * Video4linux interfacing | 672 | * Video4linux interfacing |
655 | */ | 673 | */ |
656 | 674 | ||
657 | static long pms_do_ioctl(struct file *file, unsigned int cmd, void *arg) | 675 | static int pms_querycap(struct file *file, void *priv, |
676 | struct v4l2_capability *vcap) | ||
658 | { | 677 | { |
659 | struct pms *dev = video_drvdata(file); | 678 | struct pms *dev = video_drvdata(file); |
660 | 679 | ||
661 | switch (cmd) { | 680 | strlcpy(vcap->driver, dev->v4l2_dev.name, sizeof(vcap->driver)); |
662 | case VIDIOCGCAP: { | 681 | strlcpy(vcap->card, "Mediavision PMS", sizeof(vcap->card)); |
663 | struct video_capability *b = arg; | 682 | strlcpy(vcap->bus_info, "ISA", sizeof(vcap->bus_info)); |
664 | 683 | vcap->version = KERNEL_VERSION(0, 0, 3); | |
665 | strcpy(b->name, "Mediavision PMS"); | 684 | vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; |
666 | b->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; | 685 | return 0; |
667 | b->channels = 4; | 686 | } |
668 | b->audios = 0; | ||
669 | b->maxwidth = 640; | ||
670 | b->maxheight = 480; | ||
671 | b->minwidth = 16; | ||
672 | b->minheight = 16; | ||
673 | return 0; | ||
674 | } | ||
675 | case VIDIOCGCHAN: { | ||
676 | struct video_channel *v = arg; | ||
677 | |||
678 | if (v->channel < 0 || v->channel > 3) | ||
679 | return -EINVAL; | ||
680 | v->flags = 0; | ||
681 | v->tuners = 1; | ||
682 | /* Good question.. its composite or SVHS so.. */ | ||
683 | v->type = VIDEO_TYPE_CAMERA; | ||
684 | switch (v->channel) { | ||
685 | case 0: | ||
686 | strcpy(v->name, "Composite"); | ||
687 | break; | ||
688 | case 1: | ||
689 | strcpy(v->name, "SVideo"); | ||
690 | break; | ||
691 | case 2: | ||
692 | strcpy(v->name, "Composite(VCR)"); | ||
693 | break; | ||
694 | case 3: | ||
695 | strcpy(v->name, "SVideo(VCR)"); | ||
696 | break; | ||
697 | } | ||
698 | return 0; | ||
699 | } | ||
700 | case VIDIOCSCHAN: { | ||
701 | struct video_channel *v = arg; | ||
702 | |||
703 | if (v->channel < 0 || v->channel > 3) | ||
704 | return -EINVAL; | ||
705 | mutex_lock(&dev->lock); | ||
706 | pms_videosource(dev, v->channel & 1); | ||
707 | pms_vcrinput(dev, v->channel >> 1); | ||
708 | mutex_unlock(&dev->lock); | ||
709 | return 0; | ||
710 | } | ||
711 | case VIDIOCGTUNER: { | ||
712 | struct video_tuner *v = arg; | ||
713 | |||
714 | if (v->tuner) | ||
715 | return -EINVAL; | ||
716 | strcpy(v->name, "Format"); | ||
717 | v->rangelow = 0; | ||
718 | v->rangehigh = 0; | ||
719 | v->flags = VIDEO_TUNER_PAL | VIDEO_TUNER_NTSC | VIDEO_TUNER_SECAM; | ||
720 | switch (dev->standard) { | ||
721 | case 0: | ||
722 | v->mode = VIDEO_MODE_AUTO; | ||
723 | break; | ||
724 | case 1: | ||
725 | v->mode = VIDEO_MODE_NTSC; | ||
726 | break; | ||
727 | case 2: | ||
728 | v->mode = VIDEO_MODE_PAL; | ||
729 | break; | ||
730 | case 3: | ||
731 | v->mode = VIDEO_MODE_SECAM; | ||
732 | break; | ||
733 | } | ||
734 | return 0; | ||
735 | } | ||
736 | case VIDIOCSTUNER: { | ||
737 | struct video_tuner *v = arg; | ||
738 | |||
739 | if (v->tuner) | ||
740 | return -EINVAL; | ||
741 | mutex_lock(&dev->lock); | ||
742 | switch (v->mode) { | ||
743 | case VIDEO_MODE_AUTO: | ||
744 | pms_framerate(dev, 25); | ||
745 | pms_secamcross(dev, 0); | ||
746 | pms_format(dev, 0); | ||
747 | break; | ||
748 | case VIDEO_MODE_NTSC: | ||
749 | pms_framerate(dev, 30); | ||
750 | pms_secamcross(dev, 0); | ||
751 | pms_format(dev, 1); | ||
752 | break; | ||
753 | case VIDEO_MODE_PAL: | ||
754 | pms_framerate(dev, 25); | ||
755 | pms_secamcross(dev, 0); | ||
756 | pms_format(dev, 2); | ||
757 | break; | ||
758 | case VIDEO_MODE_SECAM: | ||
759 | pms_framerate(dev, 25); | ||
760 | pms_secamcross(dev, 1); | ||
761 | pms_format(dev, 2); | ||
762 | break; | ||
763 | default: | ||
764 | mutex_unlock(&dev->lock); | ||
765 | return -EINVAL; | ||
766 | } | ||
767 | mutex_unlock(&dev->lock); | ||
768 | return 0; | ||
769 | } | ||
770 | case VIDIOCGPICT: { | ||
771 | struct video_picture *p = arg; | ||
772 | 687 | ||
773 | *p = dev->picture; | 688 | static int pms_enum_input(struct file *file, void *fh, struct v4l2_input *vin) |
774 | return 0; | 689 | { |
775 | } | 690 | static const char *inputs[4] = { |
776 | case VIDIOCSPICT: { | 691 | "Composite", |
777 | struct video_picture *p = arg; | 692 | "S-Video", |
693 | "Composite (VCR)", | ||
694 | "S-Video (VCR)" | ||
695 | }; | ||
778 | 696 | ||
779 | if (!((p->palette == VIDEO_PALETTE_RGB565 && p->depth == 16) || | 697 | if (vin->index > 3) |
780 | (p->palette == VIDEO_PALETTE_RGB555 && p->depth == 15))) | 698 | return -EINVAL; |
781 | return -EINVAL; | 699 | strlcpy(vin->name, inputs[vin->index], sizeof(vin->name)); |
782 | dev->picture = *p; | 700 | vin->type = V4L2_INPUT_TYPE_CAMERA; |
701 | vin->audioset = 0; | ||
702 | vin->tuner = 0; | ||
703 | vin->std = V4L2_STD_ALL; | ||
704 | vin->status = 0; | ||
705 | return 0; | ||
706 | } | ||
783 | 707 | ||
784 | /* | 708 | static int pms_g_input(struct file *file, void *fh, unsigned int *inp) |
785 | * Now load the card. | 709 | { |
786 | */ | 710 | struct pms *dev = video_drvdata(file); |
787 | 711 | ||
788 | mutex_lock(&dev->lock); | 712 | *inp = dev->input; |
789 | pms_brightness(dev, p->brightness >> 8); | 713 | return 0; |
790 | pms_hue(dev, p->hue >> 8); | 714 | } |
791 | pms_colour(dev, p->colour >> 8); | 715 | |
792 | pms_contrast(dev, p->contrast >> 8); | 716 | static int pms_s_input(struct file *file, void *fh, unsigned int inp) |
793 | mutex_unlock(&dev->lock); | 717 | { |
794 | return 0; | 718 | struct pms *dev = video_drvdata(file); |
719 | |||
720 | if (inp > 3) | ||
721 | return -EINVAL; | ||
722 | |||
723 | mutex_lock(&dev->lock); | ||
724 | dev->input = inp; | ||
725 | pms_videosource(dev, inp & 1); | ||
726 | pms_vcrinput(dev, inp >> 1); | ||
727 | mutex_unlock(&dev->lock); | ||
728 | return 0; | ||
729 | } | ||
730 | |||
731 | static int pms_g_std(struct file *file, void *fh, v4l2_std_id *std) | ||
732 | { | ||
733 | struct pms *dev = video_drvdata(file); | ||
734 | |||
735 | *std = dev->std; | ||
736 | return 0; | ||
737 | } | ||
738 | |||
739 | static int pms_s_std(struct file *file, void *fh, v4l2_std_id *std) | ||
740 | { | ||
741 | struct pms *dev = video_drvdata(file); | ||
742 | int ret = 0; | ||
743 | |||
744 | dev->std = *std; | ||
745 | mutex_lock(&dev->lock); | ||
746 | if (dev->std & V4L2_STD_NTSC) { | ||
747 | pms_framerate(dev, 30); | ||
748 | pms_secamcross(dev, 0); | ||
749 | pms_format(dev, 1); | ||
750 | } else if (dev->std & V4L2_STD_PAL) { | ||
751 | pms_framerate(dev, 25); | ||
752 | pms_secamcross(dev, 0); | ||
753 | pms_format(dev, 2); | ||
754 | } else if (dev->std & V4L2_STD_SECAM) { | ||
755 | pms_framerate(dev, 25); | ||
756 | pms_secamcross(dev, 1); | ||
757 | pms_format(dev, 2); | ||
758 | } else { | ||
759 | ret = -EINVAL; | ||
795 | } | 760 | } |
796 | case VIDIOCSWIN: { | 761 | /* |
797 | struct video_window *vw = arg; | 762 | switch (v->mode) { |
798 | 763 | case VIDEO_MODE_AUTO: | |
799 | if (vw->flags) | 764 | pms_framerate(dev, 25); |
800 | return -EINVAL; | 765 | pms_secamcross(dev, 0); |
801 | if (vw->clipcount) | 766 | pms_format(dev, 0); |
802 | return -EINVAL; | 767 | break; |
803 | if (vw->height < 16 || vw->height > 480) | 768 | }*/ |
804 | return -EINVAL; | 769 | mutex_unlock(&dev->lock); |
805 | if (vw->width < 16 || vw->width > 640) | 770 | return 0; |
806 | return -EINVAL; | 771 | } |
807 | dev->width = vw->width; | 772 | |
808 | dev->height = vw->height; | 773 | static int pms_queryctrl(struct file *file, void *priv, |
809 | mutex_lock(&dev->lock); | 774 | struct v4l2_queryctrl *qc) |
810 | pms_resolution(dev, dev->width, dev->height); | 775 | { |
811 | /* Ok we figured out what to use from our wide choice */ | 776 | switch (qc->id) { |
812 | mutex_unlock(&dev->lock); | 777 | case V4L2_CID_BRIGHTNESS: |
813 | return 0; | 778 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 139); |
779 | case V4L2_CID_CONTRAST: | ||
780 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 70); | ||
781 | case V4L2_CID_SATURATION: | ||
782 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 64); | ||
783 | case V4L2_CID_HUE: | ||
784 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 0); | ||
814 | } | 785 | } |
815 | case VIDIOCGWIN: { | 786 | return -EINVAL; |
816 | struct video_window *vw = arg; | 787 | } |
817 | 788 | ||
818 | memset(vw, 0, sizeof(*vw)); | 789 | static int pms_g_ctrl(struct file *file, void *priv, |
819 | vw->width = dev->width; | 790 | struct v4l2_control *ctrl) |
820 | vw->height = dev->height; | 791 | { |
821 | return 0; | 792 | struct pms *dev = video_drvdata(file); |
793 | int ret = 0; | ||
794 | |||
795 | switch (ctrl->id) { | ||
796 | case V4L2_CID_BRIGHTNESS: | ||
797 | ctrl->value = dev->brightness; | ||
798 | break; | ||
799 | case V4L2_CID_CONTRAST: | ||
800 | ctrl->value = dev->contrast; | ||
801 | break; | ||
802 | case V4L2_CID_SATURATION: | ||
803 | ctrl->value = dev->saturation; | ||
804 | break; | ||
805 | case V4L2_CID_HUE: | ||
806 | ctrl->value = dev->hue; | ||
807 | break; | ||
808 | default: | ||
809 | ret = -EINVAL; | ||
810 | break; | ||
822 | } | 811 | } |
823 | case VIDIOCKEY: | 812 | return ret; |
824 | return 0; | 813 | } |
825 | case VIDIOCCAPTURE: | 814 | |
826 | case VIDIOCGFBUF: | 815 | static int pms_s_ctrl(struct file *file, void *priv, |
827 | case VIDIOCSFBUF: | 816 | struct v4l2_control *ctrl) |
828 | case VIDIOCGFREQ: | 817 | { |
829 | case VIDIOCSFREQ: | 818 | struct pms *dev = video_drvdata(file); |
830 | case VIDIOCGAUDIO: | 819 | int ret = 0; |
831 | case VIDIOCSAUDIO: | 820 | |
832 | return -EINVAL; | 821 | mutex_lock(&dev->lock); |
822 | switch (ctrl->id) { | ||
823 | case V4L2_CID_BRIGHTNESS: | ||
824 | dev->brightness = ctrl->value; | ||
825 | pms_brightness(dev, dev->brightness); | ||
826 | break; | ||
827 | case V4L2_CID_CONTRAST: | ||
828 | dev->contrast = ctrl->value; | ||
829 | pms_contrast(dev, dev->contrast); | ||
830 | break; | ||
831 | case V4L2_CID_SATURATION: | ||
832 | dev->saturation = ctrl->value; | ||
833 | pms_saturation(dev, dev->saturation); | ||
834 | break; | ||
835 | case V4L2_CID_HUE: | ||
836 | dev->hue = ctrl->value; | ||
837 | pms_hue(dev, dev->hue); | ||
838 | break; | ||
833 | default: | 839 | default: |
834 | return -ENOIOCTLCMD; | 840 | ret = -EINVAL; |
841 | break; | ||
835 | } | 842 | } |
843 | mutex_unlock(&dev->lock); | ||
844 | return ret; | ||
845 | } | ||
846 | |||
847 | static int pms_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
848 | { | ||
849 | struct pms *dev = video_drvdata(file); | ||
850 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
851 | |||
852 | pix->width = dev->width; | ||
853 | pix->height = dev->height; | ||
854 | pix->pixelformat = dev->width == 15 ? | ||
855 | V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB565; | ||
856 | pix->field = V4L2_FIELD_NONE; | ||
857 | pix->bytesperline = 2 * dev->width; | ||
858 | pix->sizeimage = 2 * dev->width * dev->height; | ||
859 | /* Just a guess */ | ||
860 | pix->colorspace = V4L2_COLORSPACE_SRGB; | ||
861 | return 0; | ||
862 | } | ||
863 | |||
864 | static int pms_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
865 | { | ||
866 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
867 | |||
868 | if (pix->height < 16 || pix->height > 480) | ||
869 | return -EINVAL; | ||
870 | if (pix->width < 16 || pix->width > 640) | ||
871 | return -EINVAL; | ||
872 | if (pix->pixelformat != V4L2_PIX_FMT_RGB555 && | ||
873 | pix->pixelformat != V4L2_PIX_FMT_RGB565) | ||
874 | return -EINVAL; | ||
875 | pix->field = V4L2_FIELD_NONE; | ||
876 | pix->bytesperline = 2 * pix->width; | ||
877 | pix->sizeimage = 2 * pix->width * pix->height; | ||
878 | /* Just a guess */ | ||
879 | pix->colorspace = V4L2_COLORSPACE_SRGB; | ||
836 | return 0; | 880 | return 0; |
837 | } | 881 | } |
838 | 882 | ||
839 | static long pms_ioctl(struct file *file, | 883 | static int pms_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) |
840 | unsigned int cmd, unsigned long arg) | ||
841 | { | 884 | { |
842 | return video_usercopy(file, cmd, arg, pms_do_ioctl); | 885 | struct pms *dev = video_drvdata(file); |
886 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
887 | int ret = pms_try_fmt_vid_cap(file, fh, fmt); | ||
888 | |||
889 | if (ret) | ||
890 | return ret; | ||
891 | mutex_lock(&dev->lock); | ||
892 | dev->width = pix->width; | ||
893 | dev->height = pix->height; | ||
894 | dev->depth = (pix->pixelformat == V4L2_PIX_FMT_RGB555) ? 15 : 16; | ||
895 | pms_resolution(dev, dev->width, dev->height); | ||
896 | /* Ok we figured out what to use from our wide choice */ | ||
897 | mutex_unlock(&dev->lock); | ||
898 | return 0; | ||
899 | } | ||
900 | |||
901 | static int pms_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) | ||
902 | { | ||
903 | static struct v4l2_fmtdesc formats[] = { | ||
904 | { 0, 0, 0, | ||
905 | "RGB 5:5:5", V4L2_PIX_FMT_RGB555, | ||
906 | { 0, 0, 0, 0 } | ||
907 | }, | ||
908 | { 0, 0, 0, | ||
909 | "RGB 5:6:5", V4L2_PIX_FMT_RGB565, | ||
910 | { 0, 0, 0, 0 } | ||
911 | }, | ||
912 | }; | ||
913 | enum v4l2_buf_type type = fmt->type; | ||
914 | |||
915 | if (fmt->index > 1) | ||
916 | return -EINVAL; | ||
917 | |||
918 | *fmt = formats[fmt->index]; | ||
919 | fmt->type = type; | ||
920 | return 0; | ||
843 | } | 921 | } |
844 | 922 | ||
845 | static ssize_t pms_read(struct file *file, char __user *buf, | 923 | static ssize_t pms_read(struct file *file, char __user *buf, |
@@ -849,7 +927,7 @@ static ssize_t pms_read(struct file *file, char __user *buf, | |||
849 | int len; | 927 | int len; |
850 | 928 | ||
851 | mutex_lock(&dev->lock); | 929 | mutex_lock(&dev->lock); |
852 | len = pms_capture(dev, buf, (dev->picture.depth == 16) ? 0 : 1, count); | 930 | len = pms_capture(dev, buf, (dev->depth == 15), count); |
853 | mutex_unlock(&dev->lock); | 931 | mutex_unlock(&dev->lock); |
854 | return len; | 932 | return len; |
855 | } | 933 | } |
@@ -873,10 +951,25 @@ static const struct v4l2_file_operations pms_fops = { | |||
873 | .owner = THIS_MODULE, | 951 | .owner = THIS_MODULE, |
874 | .open = pms_exclusive_open, | 952 | .open = pms_exclusive_open, |
875 | .release = pms_exclusive_release, | 953 | .release = pms_exclusive_release, |
876 | .ioctl = pms_ioctl, | 954 | .ioctl = video_ioctl2, |
877 | .read = pms_read, | 955 | .read = pms_read, |
878 | }; | 956 | }; |
879 | 957 | ||
958 | static const struct v4l2_ioctl_ops pms_ioctl_ops = { | ||
959 | .vidioc_querycap = pms_querycap, | ||
960 | .vidioc_g_input = pms_g_input, | ||
961 | .vidioc_s_input = pms_s_input, | ||
962 | .vidioc_enum_input = pms_enum_input, | ||
963 | .vidioc_g_std = pms_g_std, | ||
964 | .vidioc_s_std = pms_s_std, | ||
965 | .vidioc_queryctrl = pms_queryctrl, | ||
966 | .vidioc_g_ctrl = pms_g_ctrl, | ||
967 | .vidioc_s_ctrl = pms_s_ctrl, | ||
968 | .vidioc_enum_fmt_vid_cap = pms_enum_fmt_vid_cap, | ||
969 | .vidioc_g_fmt_vid_cap = pms_g_fmt_vid_cap, | ||
970 | .vidioc_s_fmt_vid_cap = pms_s_fmt_vid_cap, | ||
971 | .vidioc_try_fmt_vid_cap = pms_try_fmt_vid_cap, | ||
972 | }; | ||
880 | 973 | ||
881 | /* | 974 | /* |
882 | * Probe for and initialise the Mediavision PMS | 975 | * Probe for and initialise the Mediavision PMS |
@@ -1032,11 +1125,18 @@ static int __init pms_init(void) | |||
1032 | strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); | 1125 | strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); |
1033 | dev->vdev.v4l2_dev = v4l2_dev; | 1126 | dev->vdev.v4l2_dev = v4l2_dev; |
1034 | dev->vdev.fops = &pms_fops; | 1127 | dev->vdev.fops = &pms_fops; |
1128 | dev->vdev.ioctl_ops = &pms_ioctl_ops; | ||
1035 | dev->vdev.release = video_device_release_empty; | 1129 | dev->vdev.release = video_device_release_empty; |
1036 | video_set_drvdata(&dev->vdev, dev); | 1130 | video_set_drvdata(&dev->vdev, dev); |
1037 | mutex_init(&dev->lock); | 1131 | mutex_init(&dev->lock); |
1132 | dev->std = V4L2_STD_NTSC_M; | ||
1038 | dev->height = 240; | 1133 | dev->height = 240; |
1039 | dev->width = 320; | 1134 | dev->width = 320; |
1135 | dev->depth = 15; | ||
1136 | dev->brightness = 139; | ||
1137 | dev->contrast = 70; | ||
1138 | dev->hue = 0; | ||
1139 | dev->saturation = 64; | ||
1040 | pms_swsense(dev, 75); | 1140 | pms_swsense(dev, 75); |
1041 | pms_resolution(dev, 320, 240); | 1141 | pms_resolution(dev, 320, 240); |
1042 | pms_videosource(dev, 0); | 1142 | pms_videosource(dev, 0); |