20 #include <linux/module.h>
21 #include <linux/i2c.h>
22 #include <linux/slab.h>
23 #include <linux/kernel.h>
26 #include <linux/videodev2.h>
33 #define GET_ID(val) ((val & 0xF8) >> 3)
34 #define GET_REV(val) (val & 0x07)
47 #define VDELAY_LO 0x08
48 #define VACTIVE_LO 0x09
49 #define HDELAY_LO 0x0A
50 #define HACTIVE_LO 0x0B
52 #define VSCALE_LO 0x0D
54 #define HSCALE_LO 0x0F
57 #define SHARPNESS 0x12
91 #define ANAPLLCTL 0x4C
126 #define VBIDELAY 0x6F
157 #define OEN_TRI_SEL_MASK 0x07
158 #define OEN_TRI_SEL_ALL_ON 0x00
159 #define OEN_TRI_SEL_ALL_OFF_r0 0x06
160 #define OEN_TRI_SEL_ALL_OFF_r1 0x07
166 #define VSSL_VSYNC 0x00
167 #define VSSL_VACT 0x10
168 #define VSSL_FIELD 0x20
169 #define VSSL_VVALID 0x30
170 #define VSSL_ZERO 0x70
174 #define HSSL_HACT 0x00
175 #define HSSL_HSYNC 0x01
176 #define HSSL_DVALID 0x02
177 #define HSSL_HLOCK 0x03
178 #define HSSL_ASYNCW 0x04
179 #define HSSL_ZERO 0x07
186 #define ACNTL1_PDN_MASK 0x0e
192 #define ACNTL2_PDN_MASK 0x40
198 #define RTSEL_MASK 0x07
199 #define RTSEL_VLOSS 0x00
200 #define RTSEL_HLOCK 0x01
201 #define RTSEL_SLOCK 0x02
202 #define RTSEL_VLOCK 0x03
203 #define RTSEL_MONO 0x04
204 #define RTSEL_DET50 0x05
205 #define RTSEL_FIELD 0x06
206 #define RTSEL_RTCO 0x07
209 #define HSYNC_START 0x0260
210 #define HSYNC_END 0x0300
246 .name =
"NTSC CCIR601",
253 .name =
"NTSC SQ (CIF)",
260 .name =
"NTSC CCIR601 (CIF)",
267 .name =
"NTSC SQ (QCIF)",
274 .name =
"NTSC CCIR601 (QCIF)",
291 .name =
"PAL CCIR601",
298 .name =
"PAL SQ (CIF)",
305 .name =
"PAL CCIR601 (CIF)",
312 .name =
"PAL SQ (QCIF)",
319 .name =
"PAL CCIR601 (QCIF)",
349 static int tw9910_set_scale(
struct i2c_client *client,
355 (scale->
vscale & 0x0F00) >> 4 |
356 (scale->
hscale & 0x0F00) >> 8);
371 static int tw9910_set_hsync(
struct i2c_client *client)
391 ret = tw9910_mask_set(client,
HSLOWCTL, 0x77,
398 static void tw9910_reset(
struct i2c_client *client)
434 scale = tw9910_ntsc_scales;
437 scale = tw9910_pal_scales;
443 for (i = 0; i <
size; i++) {
444 tmp =
abs(width - scale[i].width) +
445 abs(height - scale[i].height);
458 static int tw9910_s_stream(
struct v4l2_subdev *
sd,
int enable)
460 struct i2c_client *client = v4l2_get_subdevdata(sd);
474 dev_err(&client->
dev,
"un-supported revision\n");
488 priv->
scale->height);
495 return tw9910_power(client, enable);
500 struct i2c_client *client = v4l2_get_subdevdata(sd);
510 struct i2c_client *client = v4l2_get_subdevdata(sd);
513 if (!(norm & (V4L2_STD_NTSC | V4L2_STD_PAL)))
521 static int tw9910_g_chip_ident(
struct v4l2_subdev *sd,
524 struct i2c_client *client = v4l2_get_subdevdata(sd);
533 #ifdef CONFIG_VIDEO_ADV_DEBUG
534 static int tw9910_g_register(
struct v4l2_subdev *sd,
537 struct i2c_client *client = v4l2_get_subdevdata(sd);
556 static int tw9910_s_register(
struct v4l2_subdev *sd,
559 struct i2c_client *client = v4l2_get_subdevdata(sd);
561 if (reg->
reg > 0xff ||
569 static int tw9910_s_power(
struct v4l2_subdev *sd,
int on)
571 struct i2c_client *client = v4l2_get_subdevdata(sd);
574 return soc_camera_set_power(&client->
dev, icl, on);
579 struct i2c_client *client = v4l2_get_subdevdata(sd);
587 priv->
scale = tw9910_select_norm(priv->
norm, *width, *height);
589 goto tw9910_set_fmt_error;
594 tw9910_reset(client);
600 if (SOCAM_DATAWIDTH_16 == priv->
info->buswidth)
603 ret = tw9910_mask_set(client,
OPFORM,
LEN, val);
605 goto tw9910_set_fmt_error;
610 switch (priv->
info->mpout) {
633 goto tw9910_set_fmt_error;
638 ret = tw9910_set_scale(client, priv->
scale);
640 goto tw9910_set_fmt_error;
645 ret = tw9910_set_hsync(client);
647 goto tw9910_set_fmt_error;
649 *width = priv->
scale->width;
650 *height = priv->
scale->height;
654 tw9910_set_fmt_error:
656 tw9910_reset(client);
664 struct i2c_client *client = v4l2_get_subdevdata(sd);
669 if (priv->
norm & V4L2_STD_NTSC) {
683 struct i2c_client *client = v4l2_get_subdevdata(sd);
688 if (priv->
norm & V4L2_STD_NTSC) {
704 struct v4l2_mbus_framefmt *mf)
706 struct i2c_client *client = v4l2_get_subdevdata(sd);
710 priv->
scale = tw9910_select_norm(priv->
norm, 640, 480);
715 mf->width = priv->
scale->width;
716 mf->height = priv->
scale->height;
725 struct v4l2_mbus_framefmt *mf)
727 u32 width = mf->width, height = mf->height;
741 ret = tw9910_set_frame(sd, &width, &height);
750 struct v4l2_mbus_framefmt *mf)
752 struct i2c_client *client = v4l2_get_subdevdata(sd);
759 dev_err(&client->
dev,
"Field type %d invalid.\n", mf->field);
769 scale = tw9910_select_norm(priv->
norm, mf->width, mf->height);
773 mf->width = scale->
width;
774 mf->height = scale->
height;
779 static int tw9910_video_probe(
struct i2c_client *client)
788 if (SOCAM_DATAWIDTH_16 != priv->
info->buswidth &&
789 SOCAM_DATAWIDTH_8 != priv->
info->buswidth) {
794 ret = tw9910_s_power(&priv->
subdev, 1);
809 "Product ID error %x:%x\n",
816 "tw9910 Product ID %0x:%0x\n",
id, priv->
revision);
821 tw9910_s_power(&priv->
subdev, 0);
826 .g_chip_ident = tw9910_g_chip_ident,
827 .s_std = tw9910_s_std,
828 .g_std = tw9910_g_std,
829 #ifdef CONFIG_VIDEO_ADV_DEBUG
830 .g_register = tw9910_g_register,
831 .s_register = tw9910_s_register,
833 .s_power = tw9910_s_power,
846 static int tw9910_g_mbus_config(
struct v4l2_subdev *sd,
849 struct i2c_client *client = v4l2_get_subdevdata(sd);
862 static int tw9910_s_mbus_config(
struct v4l2_subdev *sd,
865 struct i2c_client *client = v4l2_get_subdevdata(sd);
886 .s_stream = tw9910_s_stream,
887 .g_mbus_fmt = tw9910_g_fmt,
888 .s_mbus_fmt = tw9910_s_fmt,
889 .try_mbus_fmt = tw9910_try_fmt,
890 .cropcap = tw9910_cropcap,
891 .g_crop = tw9910_g_crop,
892 .enum_mbus_fmt = tw9910_enum_fmt,
893 .g_mbus_config = tw9910_g_mbus_config,
894 .s_mbus_config = tw9910_s_mbus_config,
898 .core = &tw9910_subdev_core_ops,
899 .video = &tw9910_subdev_video_ops,
906 static int tw9910_probe(
struct i2c_client *client,
917 if (!icl || !icl->
priv) {
918 dev_err(&client->
dev,
"TW9910: missing platform data!\n");
926 "I2C-Adapter doesn't support "
927 "I2C_FUNC_SMBUS_BYTE_DATA\n");
939 ret = tw9910_video_probe(client);
946 static int tw9910_remove(
struct i2c_client *client)
960 static struct i2c_driver tw9910_i2c_driver = {
964 .probe = tw9910_probe,
965 .remove = tw9910_remove,
966 .id_table = tw9910_id,