diff options
Diffstat (limited to 'drivers/media/video/tcm825x.c')
-rw-r--r-- | drivers/media/video/tcm825x.c | 128 |
1 files changed, 57 insertions, 71 deletions
diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c index 3a139f288a9d..41cd6a0b0485 100644 --- a/drivers/media/video/tcm825x.c +++ b/drivers/media/video/tcm825x.c | |||
@@ -470,46 +470,6 @@ static int tcm825x_configure(struct v4l2_int_device *s) | |||
470 | return 0; | 470 | return 0; |
471 | } | 471 | } |
472 | 472 | ||
473 | /* | ||
474 | * Given the image capture format in pix, the nominal frame period in | ||
475 | * timeperframe, calculate the required xclk frequency. | ||
476 | * | ||
477 | * TCM825X input frequency characteristics are: | ||
478 | * Minimum 11.9 MHz, Typical 24.57 MHz and maximum 25/27 MHz | ||
479 | */ | ||
480 | #define XCLK_MIN 11900000 | ||
481 | #define XCLK_MAX 25000000 | ||
482 | |||
483 | static int ioctl_g_ext_clk(struct v4l2_int_device *s, u32 *xclk) | ||
484 | { | ||
485 | struct tcm825x_sensor *sensor = s->priv; | ||
486 | struct v4l2_fract *timeperframe = &sensor->timeperframe; | ||
487 | u32 tgt_xclk; /* target xclk */ | ||
488 | u32 tgt_fps; /* target frames per secound */ | ||
489 | |||
490 | tgt_fps = timeperframe->denominator / timeperframe->numerator; | ||
491 | |||
492 | tgt_xclk = (tgt_fps <= HIGH_FPS_MODE_LOWER_LIMIT) ? | ||
493 | (2457 * tgt_fps) / MAX_HALF_FPS : | ||
494 | (2457 * tgt_fps) / MAX_FPS; | ||
495 | tgt_xclk *= 10000; | ||
496 | |||
497 | tgt_xclk = min(tgt_xclk, (u32)XCLK_MAX); | ||
498 | tgt_xclk = max(tgt_xclk, (u32)XCLK_MIN); | ||
499 | |||
500 | *xclk = tgt_xclk; | ||
501 | |||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | static int ioctl_s_ext_clk(struct v4l2_int_device *s, u32 xclk) | ||
506 | { | ||
507 | if (xclk > XCLK_MAX || xclk < XCLK_MIN) | ||
508 | return -EINVAL; | ||
509 | |||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | static int ioctl_queryctrl(struct v4l2_int_device *s, | 473 | static int ioctl_queryctrl(struct v4l2_int_device *s, |
514 | struct v4l2_queryctrl *qc) | 474 | struct v4l2_queryctrl *qc) |
515 | { | 475 | { |
@@ -756,6 +716,41 @@ static int ioctl_s_power(struct v4l2_int_device *s, int on) | |||
756 | return sensor->platform_data->power_set(on); | 716 | return sensor->platform_data->power_set(on); |
757 | } | 717 | } |
758 | 718 | ||
719 | /* | ||
720 | * Given the image capture format in pix, the nominal frame period in | ||
721 | * timeperframe, calculate the required xclk frequency. | ||
722 | * | ||
723 | * TCM825X input frequency characteristics are: | ||
724 | * Minimum 11.9 MHz, Typical 24.57 MHz and maximum 25/27 MHz | ||
725 | */ | ||
726 | |||
727 | static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) | ||
728 | { | ||
729 | struct tcm825x_sensor *sensor = s->priv; | ||
730 | struct v4l2_fract *timeperframe = &sensor->timeperframe; | ||
731 | u32 tgt_xclk; /* target xclk */ | ||
732 | u32 tgt_fps; /* target frames per secound */ | ||
733 | int rval; | ||
734 | |||
735 | rval = sensor->platform_data->ifparm(p); | ||
736 | if (rval) | ||
737 | return rval; | ||
738 | |||
739 | tgt_fps = timeperframe->denominator / timeperframe->numerator; | ||
740 | |||
741 | tgt_xclk = (tgt_fps <= HIGH_FPS_MODE_LOWER_LIMIT) ? | ||
742 | (2457 * tgt_fps) / MAX_HALF_FPS : | ||
743 | (2457 * tgt_fps) / MAX_FPS; | ||
744 | tgt_xclk *= 10000; | ||
745 | |||
746 | tgt_xclk = min(tgt_xclk, (u32)TCM825X_XCLK_MAX); | ||
747 | tgt_xclk = max(tgt_xclk, (u32)TCM825X_XCLK_MIN); | ||
748 | |||
749 | p->u.bt656.clock_curr = tgt_xclk; | ||
750 | |||
751 | return 0; | ||
752 | } | ||
753 | |||
759 | static int ioctl_g_needs_reset(struct v4l2_int_device *s, void *buf) | 754 | static int ioctl_g_needs_reset(struct v4l2_int_device *s, void *buf) |
760 | { | 755 | { |
761 | struct tcm825x_sensor *sensor = s->priv; | 756 | struct tcm825x_sensor *sensor = s->priv; |
@@ -793,43 +788,39 @@ static int ioctl_dev_init(struct v4l2_int_device *s) | |||
793 | return 0; | 788 | return 0; |
794 | } | 789 | } |
795 | 790 | ||
796 | #define NUM_IOCTLS 17 | 791 | static struct v4l2_int_ioctl_desc tcm825x_ioctl_desc[] = { |
797 | |||
798 | static struct v4l2_int_ioctl_desc tcm825x_ioctl_desc[NUM_IOCTLS] = { | ||
799 | { vidioc_int_dev_init_num, | 792 | { vidioc_int_dev_init_num, |
800 | (v4l2_int_ioctl_func *)&ioctl_dev_init }, | 793 | (v4l2_int_ioctl_func *)ioctl_dev_init }, |
801 | { vidioc_int_dev_exit_num, | 794 | { vidioc_int_dev_exit_num, |
802 | (v4l2_int_ioctl_func *)&ioctl_dev_exit }, | 795 | (v4l2_int_ioctl_func *)ioctl_dev_exit }, |
803 | { vidioc_int_s_power_num, | 796 | { vidioc_int_s_power_num, |
804 | (v4l2_int_ioctl_func *)&ioctl_s_power }, | 797 | (v4l2_int_ioctl_func *)ioctl_s_power }, |
805 | { vidioc_int_g_ext_clk_num, | 798 | { vidioc_int_g_ifparm_num, |
806 | (v4l2_int_ioctl_func *)&ioctl_g_ext_clk }, | 799 | (v4l2_int_ioctl_func *)ioctl_g_ifparm }, |
807 | { vidioc_int_s_ext_clk_num, | ||
808 | (v4l2_int_ioctl_func *)&ioctl_s_ext_clk }, | ||
809 | { vidioc_int_g_needs_reset_num, | 800 | { vidioc_int_g_needs_reset_num, |
810 | (v4l2_int_ioctl_func *)&ioctl_g_needs_reset }, | 801 | (v4l2_int_ioctl_func *)ioctl_g_needs_reset }, |
811 | { vidioc_int_reset_num, | 802 | { vidioc_int_reset_num, |
812 | (v4l2_int_ioctl_func *)&ioctl_reset }, | 803 | (v4l2_int_ioctl_func *)ioctl_reset }, |
813 | { vidioc_int_init_num, | 804 | { vidioc_int_init_num, |
814 | (v4l2_int_ioctl_func *)&ioctl_init }, | 805 | (v4l2_int_ioctl_func *)ioctl_init }, |
815 | { vidioc_int_enum_fmt_cap_num, | 806 | { vidioc_int_enum_fmt_cap_num, |
816 | (v4l2_int_ioctl_func *)&ioctl_enum_fmt_cap }, | 807 | (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap }, |
817 | { vidioc_int_try_fmt_cap_num, | 808 | { vidioc_int_try_fmt_cap_num, |
818 | (v4l2_int_ioctl_func *)&ioctl_try_fmt_cap }, | 809 | (v4l2_int_ioctl_func *)ioctl_try_fmt_cap }, |
819 | { vidioc_int_g_fmt_cap_num, | 810 | { vidioc_int_g_fmt_cap_num, |
820 | (v4l2_int_ioctl_func *)&ioctl_g_fmt_cap }, | 811 | (v4l2_int_ioctl_func *)ioctl_g_fmt_cap }, |
821 | { vidioc_int_s_fmt_cap_num, | 812 | { vidioc_int_s_fmt_cap_num, |
822 | (v4l2_int_ioctl_func *)&ioctl_s_fmt_cap }, | 813 | (v4l2_int_ioctl_func *)ioctl_s_fmt_cap }, |
823 | { vidioc_int_g_parm_num, | 814 | { vidioc_int_g_parm_num, |
824 | (v4l2_int_ioctl_func *)&ioctl_g_parm }, | 815 | (v4l2_int_ioctl_func *)ioctl_g_parm }, |
825 | { vidioc_int_s_parm_num, | 816 | { vidioc_int_s_parm_num, |
826 | (v4l2_int_ioctl_func *)&ioctl_s_parm }, | 817 | (v4l2_int_ioctl_func *)ioctl_s_parm }, |
827 | { vidioc_int_queryctrl_num, | 818 | { vidioc_int_queryctrl_num, |
828 | (v4l2_int_ioctl_func *)&ioctl_queryctrl }, | 819 | (v4l2_int_ioctl_func *)ioctl_queryctrl }, |
829 | { vidioc_int_g_ctrl_num, | 820 | { vidioc_int_g_ctrl_num, |
830 | (v4l2_int_ioctl_func *)&ioctl_g_ctrl }, | 821 | (v4l2_int_ioctl_func *)ioctl_g_ctrl }, |
831 | { vidioc_int_s_ctrl_num, | 822 | { vidioc_int_s_ctrl_num, |
832 | (v4l2_int_ioctl_func *)&ioctl_s_ctrl }, | 823 | (v4l2_int_ioctl_func *)ioctl_s_ctrl }, |
833 | }; | 824 | }; |
834 | 825 | ||
835 | static struct v4l2_int_slave tcm825x_slave = { | 826 | static struct v4l2_int_slave tcm825x_slave = { |
@@ -894,16 +885,16 @@ static int __exit tcm825x_remove(struct i2c_client *client) | |||
894 | } | 885 | } |
895 | 886 | ||
896 | static struct i2c_driver tcm825x_i2c_driver = { | 887 | static struct i2c_driver tcm825x_i2c_driver = { |
897 | .driver = { | 888 | .driver = { |
898 | .name = TCM825X_NAME, | 889 | .name = TCM825X_NAME, |
899 | }, | 890 | }, |
900 | .probe = &tcm825x_probe, | 891 | .probe = tcm825x_probe, |
901 | .remove = __exit_p(&tcm825x_remove), | 892 | .remove = __exit_p(tcm825x_remove), |
902 | }; | 893 | }; |
903 | 894 | ||
904 | static struct tcm825x_sensor tcm825x = { | 895 | static struct tcm825x_sensor tcm825x = { |
905 | .timeperframe = { | 896 | .timeperframe = { |
906 | .numerator = 1, | 897 | .numerator = 1, |
907 | .denominator = DEFAULT_FPS, | 898 | .denominator = DEFAULT_FPS, |
908 | }, | 899 | }, |
909 | }; | 900 | }; |
@@ -911,11 +902,6 @@ static struct tcm825x_sensor tcm825x = { | |||
911 | static int __init tcm825x_init(void) | 902 | static int __init tcm825x_init(void) |
912 | { | 903 | { |
913 | int rval; | 904 | int rval; |
914 | int i = 0; | ||
915 | |||
916 | /* Just an experiment --- don't use *_cb functions yet. */ | ||
917 | tcm825x_ioctl_desc[i++] = vidioc_int_dev_init_cb(&ioctl_dev_init); | ||
918 | BUG_ON(i >= NUM_IOCTLS); | ||
919 | 905 | ||
920 | rval = i2c_add_driver(&tcm825x_i2c_driver); | 906 | rval = i2c_add_driver(&tcm825x_i2c_driver); |
921 | if (rval) | 907 | if (rval) |