aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/rj54n1cb0c.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2009-12-11 09:46:49 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-12-16 06:27:29 -0500
commit760697beca338599a65484389c7abbe54aedb664 (patch)
tree515735429d2240629a6f048ab1a7fefaf5299e46 /drivers/media/video/rj54n1cb0c.c
parent9a74251d8bee7a25fee89a0be3ccea73e01c1a05 (diff)
V4L/DVB (13659): soc-camera: convert to the new mediabus API
Convert soc-camera core and all soc-camera drivers to the new mediabus API. This also takes soc-camera client drivers one step closer to also be usable with generic v4l2-subdev host drivers. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Acked-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/rj54n1cb0c.c')
-rw-r--r--drivers/media/video/rj54n1cb0c.c201
1 files changed, 149 insertions, 52 deletions
diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c
index 373f2a30a677..7b08bff443f5 100644
--- a/drivers/media/video/rj54n1cb0c.c
+++ b/drivers/media/video/rj54n1cb0c.c
@@ -16,6 +16,7 @@
16#include <media/v4l2-subdev.h> 16#include <media/v4l2-subdev.h>
17#include <media/v4l2-chip-ident.h> 17#include <media/v4l2-chip-ident.h>
18#include <media/soc_camera.h> 18#include <media/soc_camera.h>
19#include <media/soc_mediabus.h>
19 20
20#define RJ54N1_DEV_CODE 0x0400 21#define RJ54N1_DEV_CODE 0x0400
21#define RJ54N1_DEV_CODE2 0x0401 22#define RJ54N1_DEV_CODE2 0x0401
@@ -85,18 +86,35 @@
85 86
86/* I2C addresses: 0x50, 0x51, 0x60, 0x61 */ 87/* I2C addresses: 0x50, 0x51, 0x60, 0x61 */
87 88
88static const struct soc_camera_data_format rj54n1_colour_formats[] = { 89/* RJ54N1CB0C has only one fixed colorspace per pixelcode */
89 { 90struct rj54n1_datafmt {
90 .name = "YUYV", 91 enum v4l2_mbus_pixelcode code;
91 .depth = 16, 92 enum v4l2_colorspace colorspace;
92 .fourcc = V4L2_PIX_FMT_YUYV, 93};
93 .colorspace = V4L2_COLORSPACE_JPEG, 94
94 }, { 95/* Find a data format by a pixel code in an array */
95 .name = "RGB565", 96static const struct rj54n1_datafmt *rj54n1_find_datafmt(
96 .depth = 16, 97 enum v4l2_mbus_pixelcode code, const struct rj54n1_datafmt *fmt,
97 .fourcc = V4L2_PIX_FMT_RGB565, 98 int n)
98 .colorspace = V4L2_COLORSPACE_SRGB, 99{
99 } 100 int i;
101 for (i = 0; i < n; i++)
102 if (fmt[i].code == code)
103 return fmt + i;
104
105 return NULL;
106}
107
108static const struct rj54n1_datafmt rj54n1_colour_fmts[] = {
109 {V4L2_MBUS_FMT_YUYV8_2X8_LE, V4L2_COLORSPACE_JPEG},
110 {V4L2_MBUS_FMT_YVYU8_2X8_LE, V4L2_COLORSPACE_JPEG},
111 {V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},
112 {V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB},
113 {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
114 {V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE, V4L2_COLORSPACE_SRGB},
115 {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},
116 {V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE, V4L2_COLORSPACE_SRGB},
117 {V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
100}; 118};
101 119
102struct rj54n1_clock_div { 120struct rj54n1_clock_div {
@@ -109,12 +127,12 @@ struct rj54n1_clock_div {
109 127
110struct rj54n1 { 128struct rj54n1 {
111 struct v4l2_subdev subdev; 129 struct v4l2_subdev subdev;
130 const struct rj54n1_datafmt *fmt;
112 struct v4l2_rect rect; /* Sensor window */ 131 struct v4l2_rect rect; /* Sensor window */
113 unsigned short width; /* Output window */ 132 unsigned short width; /* Output window */
114 unsigned short height; 133 unsigned short height;
115 unsigned short resize; /* Sensor * 1024 / resize = Output */ 134 unsigned short resize; /* Sensor * 1024 / resize = Output */
116 struct rj54n1_clock_div clk_div; 135 struct rj54n1_clock_div clk_div;
117 u32 fourcc;
118 unsigned short scale; 136 unsigned short scale;
119 u8 bank; 137 u8 bank;
120}; 138};
@@ -440,6 +458,16 @@ static int reg_write_multiple(struct i2c_client *client,
440 return 0; 458 return 0;
441} 459}
442 460
461static int rj54n1_enum_fmt(struct v4l2_subdev *sd, int index,
462 enum v4l2_mbus_pixelcode *code)
463{
464 if ((unsigned int)index >= ARRAY_SIZE(rj54n1_colour_fmts))
465 return -EINVAL;
466
467 *code = rj54n1_colour_fmts[index].code;
468 return 0;
469}
470
443static int rj54n1_s_stream(struct v4l2_subdev *sd, int enable) 471static int rj54n1_s_stream(struct v4l2_subdev *sd, int enable)
444{ 472{
445 /* TODO: start / stop streaming */ 473 /* TODO: start / stop streaming */
@@ -527,16 +555,17 @@ static int rj54n1_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
527 return 0; 555 return 0;
528} 556}
529 557
530static int rj54n1_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) 558static int rj54n1_g_fmt(struct v4l2_subdev *sd,
559 struct v4l2_mbus_framefmt *mf)
531{ 560{
532 struct i2c_client *client = sd->priv; 561 struct i2c_client *client = sd->priv;
533 struct rj54n1 *rj54n1 = to_rj54n1(client); 562 struct rj54n1 *rj54n1 = to_rj54n1(client);
534 struct v4l2_pix_format *pix = &f->fmt.pix;
535 563
536 pix->pixelformat = rj54n1->fourcc; 564 mf->code = rj54n1->fmt->code;
537 pix->field = V4L2_FIELD_NONE; 565 mf->colorspace = rj54n1->fmt->colorspace;
538 pix->width = rj54n1->width; 566 mf->field = V4L2_FIELD_NONE;
539 pix->height = rj54n1->height; 567 mf->width = rj54n1->width;
568 mf->height = rj54n1->height;
540 569
541 return 0; 570 return 0;
542} 571}
@@ -787,26 +816,44 @@ static int rj54n1_reg_init(struct i2c_client *client)
787} 816}
788 817
789/* FIXME: streaming output only up to 800x600 is functional */ 818/* FIXME: streaming output only up to 800x600 is functional */
790static int rj54n1_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) 819static int rj54n1_try_fmt(struct v4l2_subdev *sd,
820 struct v4l2_mbus_framefmt *mf)
791{ 821{
792 struct v4l2_pix_format *pix = &f->fmt.pix; 822 struct i2c_client *client = sd->priv;
823 struct rj54n1 *rj54n1 = to_rj54n1(client);
824 const struct rj54n1_datafmt *fmt;
825 int align = mf->code == V4L2_MBUS_FMT_SBGGR10_1X10 ||
826 mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE ||
827 mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE ||
828 mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE ||
829 mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE;
830
831 dev_dbg(&client->dev, "%s: code = %d, width = %u, height = %u\n",
832 __func__, mf->code, mf->width, mf->height);
833
834 fmt = rj54n1_find_datafmt(mf->code, rj54n1_colour_fmts,
835 ARRAY_SIZE(rj54n1_colour_fmts));
836 if (!fmt) {
837 fmt = rj54n1->fmt;
838 mf->code = fmt->code;
839 }
793 840
794 pix->field = V4L2_FIELD_NONE; 841 mf->field = V4L2_FIELD_NONE;
842 mf->colorspace = fmt->colorspace;
795 843
796 if (pix->width > 800) 844 v4l_bound_align_image(&mf->width, 112, RJ54N1_MAX_WIDTH, align,
797 pix->width = 800; 845 &mf->height, 84, RJ54N1_MAX_HEIGHT, align, 0);
798 if (pix->height > 600)
799 pix->height = 600;
800 846
801 return 0; 847 return 0;
802} 848}
803 849
804static int rj54n1_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) 850static int rj54n1_s_fmt(struct v4l2_subdev *sd,
851 struct v4l2_mbus_framefmt *mf)
805{ 852{
806 struct i2c_client *client = sd->priv; 853 struct i2c_client *client = sd->priv;
807 struct rj54n1 *rj54n1 = to_rj54n1(client); 854 struct rj54n1 *rj54n1 = to_rj54n1(client);
808 struct v4l2_pix_format *pix = &f->fmt.pix; 855 const struct rj54n1_datafmt *fmt;
809 unsigned int output_w, output_h, 856 unsigned int output_w, output_h, max_w, max_h,
810 input_w = rj54n1->rect.width, input_h = rj54n1->rect.height; 857 input_w = rj54n1->rect.width, input_h = rj54n1->rect.height;
811 int ret; 858 int ret;
812 859
@@ -814,7 +861,7 @@ static int rj54n1_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
814 * The host driver can call us without .try_fmt(), so, we have to take 861 * The host driver can call us without .try_fmt(), so, we have to take
815 * care ourseleves 862 * care ourseleves
816 */ 863 */
817 ret = rj54n1_try_fmt(sd, f); 864 ret = rj54n1_try_fmt(sd, mf);
818 865
819 /* 866 /*
820 * Verify if the sensor has just been powered on. TODO: replace this 867 * Verify if the sensor has just been powered on. TODO: replace this
@@ -832,49 +879,101 @@ static int rj54n1_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
832 } 879 }
833 880
834 /* RA_SEL_UL is only relevant for raw modes, ignored otherwise. */ 881 /* RA_SEL_UL is only relevant for raw modes, ignored otherwise. */
835 switch (pix->pixelformat) { 882 switch (mf->code) {
836 case V4L2_PIX_FMT_YUYV: 883 case V4L2_MBUS_FMT_YUYV8_2X8_LE:
837 ret = reg_write(client, RJ54N1_OUT_SEL, 0); 884 ret = reg_write(client, RJ54N1_OUT_SEL, 0);
838 if (!ret) 885 if (!ret)
839 ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); 886 ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
840 break; 887 break;
841 case V4L2_PIX_FMT_RGB565: 888 case V4L2_MBUS_FMT_YVYU8_2X8_LE:
889 ret = reg_write(client, RJ54N1_OUT_SEL, 0);
890 if (!ret)
891 ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
892 break;
893 case V4L2_MBUS_FMT_RGB565_2X8_LE:
842 ret = reg_write(client, RJ54N1_OUT_SEL, 0x11); 894 ret = reg_write(client, RJ54N1_OUT_SEL, 0x11);
843 if (!ret) 895 if (!ret)
844 ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); 896 ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
845 break; 897 break;
898 case V4L2_MBUS_FMT_RGB565_2X8_BE:
899 ret = reg_write(client, RJ54N1_OUT_SEL, 0x11);
900 if (!ret)
901 ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
902 break;
903 case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE:
904 ret = reg_write(client, RJ54N1_OUT_SEL, 4);
905 if (!ret)
906 ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
907 if (!ret)
908 ret = reg_write(client, RJ54N1_RA_SEL_UL, 0);
909 break;
910 case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE:
911 ret = reg_write(client, RJ54N1_OUT_SEL, 4);
912 if (!ret)
913 ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
914 if (!ret)
915 ret = reg_write(client, RJ54N1_RA_SEL_UL, 8);
916 break;
917 case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE:
918 ret = reg_write(client, RJ54N1_OUT_SEL, 4);
919 if (!ret)
920 ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
921 if (!ret)
922 ret = reg_write(client, RJ54N1_RA_SEL_UL, 0);
923 break;
924 case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE:
925 ret = reg_write(client, RJ54N1_OUT_SEL, 4);
926 if (!ret)
927 ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
928 if (!ret)
929 ret = reg_write(client, RJ54N1_RA_SEL_UL, 8);
930 break;
931 case V4L2_MBUS_FMT_SBGGR10_1X10:
932 ret = reg_write(client, RJ54N1_OUT_SEL, 5);
933 break;
846 default: 934 default:
847 ret = -EINVAL; 935 ret = -EINVAL;
848 } 936 }
849 937
938 /* Special case: a raw mode with 10 bits of data per clock tick */
939 if (!ret)
940 ret = reg_set(client, RJ54N1_OCLK_SEL_EN,
941 (mf->code == V4L2_MBUS_FMT_SBGGR10_1X10) << 1, 2);
942
850 if (ret < 0) 943 if (ret < 0)
851 return ret; 944 return ret;
852 945
853 /* Supported scales 1:1 - 1:16 */ 946 /* Supported scales 1:1 >= scale > 1:16 */
854 if (pix->width < input_w / 16) 947 max_w = mf->width * (16 * 1024 - 1) / 1024;
855 pix->width = input_w / 16; 948 if (input_w > max_w)
856 if (pix->height < input_h / 16) 949 input_w = max_w;
857 pix->height = input_h / 16; 950 max_h = mf->height * (16 * 1024 - 1) / 1024;
951 if (input_h > max_h)
952 input_h = max_h;
858 953
859 output_w = pix->width; 954 output_w = mf->width;
860 output_h = pix->height; 955 output_h = mf->height;
861 956
862 ret = rj54n1_sensor_scale(sd, &input_w, &input_h, &output_w, &output_h); 957 ret = rj54n1_sensor_scale(sd, &input_w, &input_h, &output_w, &output_h);
863 if (ret < 0) 958 if (ret < 0)
864 return ret; 959 return ret;
865 960
866 rj54n1->fourcc = pix->pixelformat; 961 fmt = rj54n1_find_datafmt(mf->code, rj54n1_colour_fmts,
962 ARRAY_SIZE(rj54n1_colour_fmts));
963
964 rj54n1->fmt = fmt;
867 rj54n1->resize = ret; 965 rj54n1->resize = ret;
868 rj54n1->rect.width = input_w; 966 rj54n1->rect.width = input_w;
869 rj54n1->rect.height = input_h; 967 rj54n1->rect.height = input_h;
870 rj54n1->width = output_w; 968 rj54n1->width = output_w;
871 rj54n1->height = output_h; 969 rj54n1->height = output_h;
872 970
873 pix->width = output_w; 971 mf->width = output_w;
874 pix->height = output_h; 972 mf->height = output_h;
875 pix->field = V4L2_FIELD_NONE; 973 mf->field = V4L2_FIELD_NONE;
974 mf->colorspace = fmt->colorspace;
876 975
877 return ret; 976 return 0;
878} 977}
879 978
880static int rj54n1_g_chip_ident(struct v4l2_subdev *sd, 979static int rj54n1_g_chip_ident(struct v4l2_subdev *sd,
@@ -1054,9 +1153,10 @@ static struct v4l2_subdev_core_ops rj54n1_subdev_core_ops = {
1054 1153
1055static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = { 1154static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = {
1056 .s_stream = rj54n1_s_stream, 1155 .s_stream = rj54n1_s_stream,
1057 .s_fmt = rj54n1_s_fmt, 1156 .s_mbus_fmt = rj54n1_s_fmt,
1058 .g_fmt = rj54n1_g_fmt, 1157 .g_mbus_fmt = rj54n1_g_fmt,
1059 .try_fmt = rj54n1_try_fmt, 1158 .try_mbus_fmt = rj54n1_try_fmt,
1159 .enum_mbus_fmt = rj54n1_enum_fmt,
1060 .g_crop = rj54n1_g_crop, 1160 .g_crop = rj54n1_g_crop,
1061 .cropcap = rj54n1_cropcap, 1161 .cropcap = rj54n1_cropcap,
1062}; 1162};
@@ -1153,7 +1253,7 @@ static int rj54n1_probe(struct i2c_client *client,
1153 rj54n1->rect.height = RJ54N1_MAX_HEIGHT; 1253 rj54n1->rect.height = RJ54N1_MAX_HEIGHT;
1154 rj54n1->width = RJ54N1_MAX_WIDTH; 1254 rj54n1->width = RJ54N1_MAX_WIDTH;
1155 rj54n1->height = RJ54N1_MAX_HEIGHT; 1255 rj54n1->height = RJ54N1_MAX_HEIGHT;
1156 rj54n1->fourcc = V4L2_PIX_FMT_YUYV; 1256 rj54n1->fmt = &rj54n1_colour_fmts[0];
1157 rj54n1->resize = 1024; 1257 rj54n1->resize = 1024;
1158 1258
1159 ret = rj54n1_video_probe(icd, client); 1259 ret = rj54n1_video_probe(icd, client);
@@ -1164,9 +1264,6 @@ static int rj54n1_probe(struct i2c_client *client,
1164 return ret; 1264 return ret;
1165 } 1265 }
1166 1266
1167 icd->formats = rj54n1_colour_formats;
1168 icd->num_formats = ARRAY_SIZE(rj54n1_colour_formats);
1169
1170 return ret; 1267 return ret;
1171} 1268}
1172 1269