hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/media/i2c/ov6650.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * V4L2 subdevice driver for OmniVision OV6650 Camera Sensor
34 *
....@@ -15,13 +16,9 @@
1516 * Copyright (C) 2008 Magnus Damm
1617 * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
1718 *
18
- * Hardware specific bits initialy based on former work by Matt Callow
19
+ * Hardware specific bits initially based on former work by Matt Callow
1920 * drivers/media/video/omap/sensor_ov6650.c
2021 * Copyright (C) 2006 Matt Callow
21
- *
22
- * This program is free software; you can redistribute it and/or modify
23
- * it under the terms of the GNU General Public License version 2 as
24
- * published by the Free Software Foundation.
2522 */
2623
2724 #include <linux/bitops.h>
....@@ -127,12 +124,13 @@
127124
128125 #define DEF_AECH 0x4D
129126
130
-#define CLKRC_6MHz 0x00
127
+#define CLKRC_8MHz 0x00
131128 #define CLKRC_12MHz 0x40
132129 #define CLKRC_16MHz 0x80
133130 #define CLKRC_24MHz 0xc0
134131 #define CLKRC_DIV_MASK 0x3f
135132 #define GET_CLKRC_DIV(x) (((x) & CLKRC_DIV_MASK) + 1)
133
+#define DEF_CLKRC 0x00
136134
137135 #define COMA_RESET BIT(7)
138136 #define COMA_QCIF BIT(5)
....@@ -199,12 +197,33 @@
199197 struct v4l2_clk *clk;
200198 bool half_scale; /* scale down output by 2 */
201199 struct v4l2_rect rect; /* sensor cropping window */
202
- unsigned long pclk_limit; /* from host */
203
- unsigned long pclk_max; /* from resolution and format */
204200 struct v4l2_fract tpf; /* as requested with s_frame_interval */
205201 u32 code;
206202 };
207203
204
+struct ov6650_xclk {
205
+ unsigned long rate;
206
+ u8 clkrc;
207
+};
208
+
209
+static const struct ov6650_xclk ov6650_xclk[] = {
210
+{
211
+ .rate = 8000000,
212
+ .clkrc = CLKRC_8MHz,
213
+},
214
+{
215
+ .rate = 12000000,
216
+ .clkrc = CLKRC_12MHz,
217
+},
218
+{
219
+ .rate = 16000000,
220
+ .clkrc = CLKRC_16MHz,
221
+},
222
+{
223
+ .rate = 24000000,
224
+ .clkrc = CLKRC_24MHz,
225
+},
226
+};
208227
209228 static u32 ov6650_codes[] = {
210229 MEDIA_BUS_FMT_YUYV8_2X8,
....@@ -459,7 +478,6 @@
459478
460479 switch (sel->target) {
461480 case V4L2_SEL_TGT_CROP_BOUNDS:
462
- case V4L2_SEL_TGT_CROP_DEFAULT:
463481 sel->r.left = DEF_HSTRT << 1;
464482 sel->r.top = DEF_VSTRT << 1;
465483 sel->r.width = W_CIF;
....@@ -549,22 +567,7 @@
549567 return width > rect->width >> 1 || height > rect->height >> 1;
550568 }
551569
552
-static u8 to_clkrc(struct v4l2_fract *timeperframe,
553
- unsigned long pclk_limit, unsigned long pclk_max)
554
-{
555
- unsigned long pclk;
556
-
557
- if (timeperframe->numerator && timeperframe->denominator)
558
- pclk = pclk_max * timeperframe->denominator /
559
- (FRAME_RATE_MAX * timeperframe->numerator);
560
- else
561
- pclk = pclk_max;
562
-
563
- if (pclk_limit && pclk_limit < pclk)
564
- pclk = pclk_limit;
565
-
566
- return (pclk_max - 1) / pclk;
567
-}
570
+#define to_clkrc(div) ((div) - 1)
568571
569572 /* set the format we will capture in */
570573 static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
....@@ -583,8 +586,7 @@
583586 .r.height = mf->height << half_scale,
584587 };
585588 u32 code = mf->code;
586
- unsigned long mclk, pclk;
587
- u8 coma_set = 0, coma_mask = 0, coml_set, coml_mask, clkrc;
589
+ u8 coma_set = 0, coma_mask = 0, coml_set, coml_mask;
588590 int ret;
589591
590592 /* select color matrix configuration for given color encoding */
....@@ -638,38 +640,22 @@
638640 code == MEDIA_BUS_FMT_SBGGR8_1X8) {
639641 coml_mask = COML_ONE_CHANNEL;
640642 coml_set = 0;
641
- priv->pclk_max = 4000000;
642643 } else {
643644 coml_mask = 0;
644645 coml_set = COML_ONE_CHANNEL;
645
- priv->pclk_max = 8000000;
646646 }
647647
648648 if (half_scale) {
649649 dev_dbg(&client->dev, "max resolution: QCIF\n");
650650 coma_set |= COMA_QCIF;
651
- priv->pclk_max /= 2;
652651 } else {
653652 dev_dbg(&client->dev, "max resolution: CIF\n");
654653 coma_mask |= COMA_QCIF;
655654 }
656655
657
- clkrc = CLKRC_12MHz;
658
- mclk = 12000000;
659
- priv->pclk_limit = 1334000;
660
- dev_dbg(&client->dev, "using 12MHz input clock\n");
661
-
662
- clkrc |= to_clkrc(&priv->tpf, priv->pclk_limit, priv->pclk_max);
663
-
664
- pclk = priv->pclk_max / GET_CLKRC_DIV(clkrc);
665
- dev_dbg(&client->dev, "pixel clock divider: %ld.%ld\n",
666
- mclk / pclk, 10 * mclk % pclk / pclk);
667
-
668656 ret = ov6650_set_selection(sd, NULL, &sel);
669657 if (!ret)
670658 ret = ov6650_reg_rmw(client, REG_COMA, coma_set, coma_mask);
671
- if (!ret)
672
- ret = ov6650_reg_write(client, REG_CLKRC, clkrc);
673659 if (!ret) {
674660 priv->half_scale = half_scale;
675661
....@@ -699,7 +685,7 @@
699685 switch (mf->code) {
700686 case MEDIA_BUS_FMT_Y10_1X10:
701687 mf->code = MEDIA_BUS_FMT_Y8_1X8;
702
- /* fall through */
688
+ fallthrough;
703689 case MEDIA_BUS_FMT_Y8_1X8:
704690 case MEDIA_BUS_FMT_YVYU8_2X8:
705691 case MEDIA_BUS_FMT_YUYV8_2X8:
....@@ -708,7 +694,7 @@
708694 break;
709695 default:
710696 mf->code = MEDIA_BUS_FMT_SBGGR8_1X8;
711
- /* fall through */
697
+ fallthrough;
712698 case MEDIA_BUS_FMT_SBGGR8_1X8:
713699 break;
714700 }
....@@ -758,9 +744,7 @@
758744 struct i2c_client *client = v4l2_get_subdevdata(sd);
759745 struct ov6650 *priv = to_ov6650(client);
760746
761
- ival->interval.numerator = GET_CLKRC_DIV(to_clkrc(&priv->tpf,
762
- priv->pclk_limit, priv->pclk_max));
763
- ival->interval.denominator = FRAME_RATE_MAX;
747
+ ival->interval = priv->tpf;
764748
765749 dev_dbg(&client->dev, "Frame interval: %u/%u s\n",
766750 ival->interval.numerator, ival->interval.denominator);
....@@ -775,7 +759,6 @@
775759 struct ov6650 *priv = to_ov6650(client);
776760 struct v4l2_fract *tpf = &ival->interval;
777761 int div, ret;
778
- u8 clkrc;
779762
780763 if (tpf->numerator == 0 || tpf->denominator == 0)
781764 div = 1; /* Reset to full rate */
....@@ -787,19 +770,12 @@
787770 else if (div > GET_CLKRC_DIV(CLKRC_DIV_MASK))
788771 div = GET_CLKRC_DIV(CLKRC_DIV_MASK);
789772
790
- /*
791
- * Keep result to be used as tpf limit
792
- * for subseqent clock divider calculations
793
- */
794
- priv->tpf.numerator = div;
795
- priv->tpf.denominator = FRAME_RATE_MAX;
796
-
797
- clkrc = to_clkrc(&priv->tpf, priv->pclk_limit, priv->pclk_max);
798
-
799
- ret = ov6650_reg_rmw(client, REG_CLKRC, clkrc, CLKRC_DIV_MASK);
773
+ ret = ov6650_reg_rmw(client, REG_CLKRC, to_clkrc(div), CLKRC_DIV_MASK);
800774 if (!ret) {
801
- tpf->numerator = GET_CLKRC_DIV(clkrc);
802
- tpf->denominator = FRAME_RATE_MAX;
775
+ priv->tpf.numerator = div;
776
+ priv->tpf.denominator = FRAME_RATE_MAX;
777
+
778
+ *tpf = priv->tpf;
803779 }
804780
805781 return ret;
....@@ -821,7 +797,7 @@
821797 }
822798
823799 /* program default register values */
824
-static int ov6650_prog_dflt(struct i2c_client *client)
800
+static int ov6650_prog_dflt(struct i2c_client *client, u8 clkrc)
825801 {
826802 int ret;
827803
....@@ -829,16 +805,21 @@
829805
830806 ret = ov6650_reg_write(client, REG_COMA, 0); /* ~COMA_RESET */
831807 if (!ret)
808
+ ret = ov6650_reg_write(client, REG_CLKRC, clkrc);
809
+ if (!ret)
832810 ret = ov6650_reg_rmw(client, REG_COMB, 0, COMB_BAND_FILTER);
833811
834812 return ret;
835813 }
836814
837
-static int ov6650_video_probe(struct i2c_client *client)
815
+static int ov6650_video_probe(struct v4l2_subdev *sd)
838816 {
817
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
839818 struct ov6650 *priv = to_ov6650(client);
840
- u8 pidh, pidl, midh, midl;
841
- int ret;
819
+ const struct ov6650_xclk *xclk = NULL;
820
+ unsigned long rate;
821
+ u8 pidh, pidl, midh, midl;
822
+ int i, ret = 0;
842823
843824 priv->clk = v4l2_clk_get(&client->dev, NULL);
844825 if (IS_ERR(priv->clk)) {
....@@ -847,7 +828,34 @@
847828 return ret;
848829 }
849830
850
- ret = ov6650_s_power(&priv->subdev, 1);
831
+ rate = v4l2_clk_get_rate(priv->clk);
832
+ for (i = 0; rate && i < ARRAY_SIZE(ov6650_xclk); i++) {
833
+ if (rate != ov6650_xclk[i].rate)
834
+ continue;
835
+
836
+ xclk = &ov6650_xclk[i];
837
+ dev_info(&client->dev, "using host default clock rate %lukHz\n",
838
+ rate / 1000);
839
+ break;
840
+ }
841
+ for (i = 0; !xclk && i < ARRAY_SIZE(ov6650_xclk); i++) {
842
+ ret = v4l2_clk_set_rate(priv->clk, ov6650_xclk[i].rate);
843
+ if (ret || v4l2_clk_get_rate(priv->clk) != ov6650_xclk[i].rate)
844
+ continue;
845
+
846
+ xclk = &ov6650_xclk[i];
847
+ dev_info(&client->dev, "using negotiated clock rate %lukHz\n",
848
+ xclk->rate / 1000);
849
+ break;
850
+ }
851
+ if (!xclk) {
852
+ dev_err(&client->dev, "unable to get supported clock rate\n");
853
+ if (!ret)
854
+ ret = -EINVAL;
855
+ goto eclkput;
856
+ }
857
+
858
+ ret = ov6650_s_power(sd, 1);
851859 if (ret < 0)
852860 goto eclkput;
853861
....@@ -880,12 +888,17 @@
880888
881889 ret = ov6650_reset(client);
882890 if (!ret)
883
- ret = ov6650_prog_dflt(client);
891
+ ret = ov6650_prog_dflt(client, xclk->clkrc);
892
+ if (!ret) {
893
+ struct v4l2_mbus_framefmt mf = ov6650_def_fmt;
894
+
895
+ ret = ov6650_s_fmt(sd, &mf);
896
+ }
884897 if (!ret)
885898 ret = v4l2_ctrl_handler_setup(&priv->hdl);
886899
887900 done:
888
- ov6650_s_power(&priv->subdev, 0);
901
+ ov6650_s_power(sd, 0);
889902 if (!ret)
890903 return 0;
891904 eclkput:
....@@ -908,55 +921,74 @@
908921 };
909922
910923 /* Request bus settings on camera side */
911
-static int ov6650_g_mbus_config(struct v4l2_subdev *sd,
912
- struct v4l2_mbus_config *cfg)
924
+static int ov6650_get_mbus_config(struct v4l2_subdev *sd,
925
+ unsigned int pad,
926
+ struct v4l2_mbus_config *cfg)
913927 {
928
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
929
+ u8 comj, comf;
930
+ int ret;
914931
915
- cfg->flags = V4L2_MBUS_MASTER |
916
- V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING |
917
- V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW |
918
- V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW |
919
- V4L2_MBUS_DATA_ACTIVE_HIGH;
932
+ ret = ov6650_reg_read(client, REG_COMJ, &comj);
933
+ if (ret)
934
+ return ret;
935
+
936
+ ret = ov6650_reg_read(client, REG_COMF, &comf);
937
+ if (ret)
938
+ return ret;
939
+
940
+ cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_DATA_ACTIVE_HIGH
941
+ | ((comj & COMJ_VSYNC_HIGH) ? V4L2_MBUS_VSYNC_ACTIVE_HIGH
942
+ : V4L2_MBUS_VSYNC_ACTIVE_LOW)
943
+ | ((comf & COMF_HREF_LOW) ? V4L2_MBUS_HSYNC_ACTIVE_LOW
944
+ : V4L2_MBUS_HSYNC_ACTIVE_HIGH)
945
+ | ((comj & COMJ_PCLK_RISING) ? V4L2_MBUS_PCLK_SAMPLE_RISING
946
+ : V4L2_MBUS_PCLK_SAMPLE_FALLING);
920947 cfg->type = V4L2_MBUS_PARALLEL;
921948
922949 return 0;
923950 }
924951
925952 /* Alter bus settings on camera side */
926
-static int ov6650_s_mbus_config(struct v4l2_subdev *sd,
927
- const struct v4l2_mbus_config *cfg)
953
+static int ov6650_set_mbus_config(struct v4l2_subdev *sd,
954
+ unsigned int pad,
955
+ struct v4l2_mbus_config *cfg)
928956 {
929957 struct i2c_client *client = v4l2_get_subdevdata(sd);
930
- int ret;
958
+ int ret = 0;
931959
932960 if (cfg->flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
933961 ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_PCLK_RISING, 0);
934
- else
962
+ else if (cfg->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
935963 ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_PCLK_RISING);
936964 if (ret)
937965 return ret;
938966
939967 if (cfg->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
940968 ret = ov6650_reg_rmw(client, REG_COMF, COMF_HREF_LOW, 0);
941
- else
969
+ else if (cfg->flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
942970 ret = ov6650_reg_rmw(client, REG_COMF, 0, COMF_HREF_LOW);
943971 if (ret)
944972 return ret;
945973
946974 if (cfg->flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
947975 ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_VSYNC_HIGH, 0);
948
- else
976
+ else if (cfg->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
949977 ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_VSYNC_HIGH);
978
+ if (ret)
979
+ return ret;
950980
951
- return ret;
981
+ /*
982
+ * Update the configuration to report what is actually applied to
983
+ * the hardware.
984
+ */
985
+ return ov6650_get_mbus_config(sd, pad, cfg);
952986 }
953987
954988 static const struct v4l2_subdev_video_ops ov6650_video_ops = {
955989 .s_stream = ov6650_s_stream,
956990 .g_frame_interval = ov6650_g_frame_interval,
957991 .s_frame_interval = ov6650_s_frame_interval,
958
- .g_mbus_config = ov6650_g_mbus_config,
959
- .s_mbus_config = ov6650_s_mbus_config,
960992 };
961993
962994 static const struct v4l2_subdev_pad_ops ov6650_pad_ops = {
....@@ -965,12 +997,18 @@
965997 .set_selection = ov6650_set_selection,
966998 .get_fmt = ov6650_get_fmt,
967999 .set_fmt = ov6650_set_fmt,
1000
+ .get_mbus_config = ov6650_get_mbus_config,
1001
+ .set_mbus_config = ov6650_set_mbus_config,
9681002 };
9691003
9701004 static const struct v4l2_subdev_ops ov6650_subdev_ops = {
9711005 .core = &ov6650_core_ops,
9721006 .video = &ov6650_video_ops,
9731007 .pad = &ov6650_pad_ops,
1008
+};
1009
+
1010
+static const struct v4l2_subdev_internal_ops ov6650_internal_ops = {
1011
+ .registered = ov6650_video_probe,
9741012 };
9751013
9761014 /*
....@@ -1017,8 +1055,10 @@
10171055 V4L2_CID_GAMMA, 0, 0xff, 1, 0x12);
10181056
10191057 priv->subdev.ctrl_handler = &priv->hdl;
1020
- if (priv->hdl.error)
1021
- return priv->hdl.error;
1058
+ if (priv->hdl.error) {
1059
+ ret = priv->hdl.error;
1060
+ goto ectlhdlfree;
1061
+ }
10221062
10231063 v4l2_ctrl_auto_cluster(2, &priv->autogain, 0, true);
10241064 v4l2_ctrl_auto_cluster(3, &priv->autowb, 0, true);
....@@ -1029,12 +1069,18 @@
10291069 priv->rect.top = DEF_VSTRT << 1;
10301070 priv->rect.width = W_CIF;
10311071 priv->rect.height = H_CIF;
1032
- priv->half_scale = false;
1033
- priv->code = MEDIA_BUS_FMT_YUYV8_2X8;
10341072
1035
- ret = ov6650_video_probe(client);
1036
- if (ret)
1037
- v4l2_ctrl_handler_free(&priv->hdl);
1073
+ /* Hardware default frame interval */
1074
+ priv->tpf.numerator = GET_CLKRC_DIV(DEF_CLKRC);
1075
+ priv->tpf.denominator = FRAME_RATE_MAX;
1076
+
1077
+ priv->subdev.internal_ops = &ov6650_internal_ops;
1078
+
1079
+ ret = v4l2_async_register_subdev(&priv->subdev);
1080
+ if (!ret)
1081
+ return 0;
1082
+ectlhdlfree:
1083
+ v4l2_ctrl_handler_free(&priv->hdl);
10381084
10391085 return ret;
10401086 }
....@@ -1044,7 +1090,7 @@
10441090 struct ov6650 *priv = to_ov6650(client);
10451091
10461092 v4l2_clk_put(priv->clk);
1047
- v4l2_device_unregister_subdev(&priv->subdev);
1093
+ v4l2_async_unregister_subdev(&priv->subdev);
10481094 v4l2_ctrl_handler_free(&priv->hdl);
10491095 return 0;
10501096 }
....@@ -1066,6 +1112,6 @@
10661112
10671113 module_i2c_driver(ov6650_i2c_driver);
10681114
1069
-MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV6650");
1070
-MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>");
1115
+MODULE_DESCRIPTION("V4L2 subdevice driver for OmniVision OV6650 camera sensor");
1116
+MODULE_AUTHOR("Janusz Krzysztofik <jmkrzyszt@gmail.com");
10711117 MODULE_LICENSE("GPL v2");