0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <linux/clk.h>
0019 #include <linux/delay.h>
0020 #include <linux/gpio/consumer.h>
0021 #include <linux/i2c.h>
0022 #include <linux/init.h>
0023 #include <linux/kernel.h>
0024 #include <linux/module.h>
0025 #include <linux/slab.h>
0026 #include <linux/v4l2-mediabus.h>
0027 #include <linux/videodev2.h>
0028
0029 #include <media/i2c/tw9910.h>
0030 #include <media/v4l2-subdev.h>
0031
0032 #define GET_ID(val) ((val & 0xF8) >> 3)
0033 #define GET_REV(val) (val & 0x07)
0034
0035
0036
0037
0038 #define ID 0x00
0039 #define STATUS1 0x01
0040 #define INFORM 0x02
0041 #define OPFORM 0x03
0042 #define DLYCTR 0x04
0043 #define OUTCTR1 0x05
0044 #define ACNTL1 0x06
0045 #define CROP_HI 0x07
0046 #define VDELAY_LO 0x08
0047 #define VACTIVE_LO 0x09
0048 #define HDELAY_LO 0x0A
0049 #define HACTIVE_LO 0x0B
0050 #define CNTRL1 0x0C
0051 #define VSCALE_LO 0x0D
0052 #define SCALE_HI 0x0E
0053 #define HSCALE_LO 0x0F
0054 #define BRIGHT 0x10
0055 #define CONTRAST 0x11
0056 #define SHARPNESS 0x12
0057 #define SAT_U 0x13
0058 #define SAT_V 0x14
0059 #define HUE 0x15
0060 #define CORING1 0x17
0061 #define CORING2 0x18
0062 #define VBICNTL 0x19
0063 #define ACNTL2 0x1A
0064 #define OUTCTR2 0x1B
0065 #define SDT 0x1C
0066 #define SDTR 0x1D
0067 #define TEST 0x1F
0068 #define CLMPG 0x20
0069 #define IAGC 0x21
0070 #define AGCGAIN 0x22
0071 #define PEAKWT 0x23
0072 #define CLMPL 0x24
0073 #define SYNCT 0x25
0074 #define MISSCNT 0x26
0075 #define PCLAMP 0x27
0076 #define VCNTL1 0x28
0077 #define VCNTL2 0x29
0078 #define CKILL 0x2A
0079 #define COMB 0x2B
0080 #define LDLY 0x2C
0081 #define MISC1 0x2D
0082 #define LOOP 0x2E
0083 #define MISC2 0x2F
0084 #define MVSN 0x30
0085 #define STATUS2 0x31
0086 #define HFREF 0x32
0087 #define CLMD 0x33
0088 #define IDCNTL 0x34
0089 #define CLCNTL1 0x35
0090 #define ANAPLLCTL 0x4C
0091 #define VBIMIN 0x4D
0092 #define HSLOWCTL 0x4E
0093 #define WSS3 0x4F
0094 #define FILLDATA 0x50
0095 #define SDID 0x51
0096 #define DID 0x52
0097 #define WSS1 0x53
0098 #define WSS2 0x54
0099 #define VVBI 0x55
0100 #define LCTL6 0x56
0101 #define LCTL7 0x57
0102 #define LCTL8 0x58
0103 #define LCTL9 0x59
0104 #define LCTL10 0x5A
0105 #define LCTL11 0x5B
0106 #define LCTL12 0x5C
0107 #define LCTL13 0x5D
0108 #define LCTL14 0x5E
0109 #define LCTL15 0x5F
0110 #define LCTL16 0x60
0111 #define LCTL17 0x61
0112 #define LCTL18 0x62
0113 #define LCTL19 0x63
0114 #define LCTL20 0x64
0115 #define LCTL21 0x65
0116 #define LCTL22 0x66
0117 #define LCTL23 0x67
0118 #define LCTL24 0x68
0119 #define LCTL25 0x69
0120 #define LCTL26 0x6A
0121 #define HSBEGIN 0x6B
0122 #define HSEND 0x6C
0123 #define OVSDLY 0x6D
0124 #define OVSEND 0x6E
0125 #define VBIDELAY 0x6F
0126
0127
0128
0129
0130
0131
0132 #define FC27_ON 0x40
0133 #define FC27_FF 0x00
0134
0135
0136 #define IFSEL_S 0x10
0137 #define IFSEL_C 0x00
0138
0139 #define YSEL_M0 0x00
0140 #define YSEL_M1 0x04
0141 #define YSEL_M2 0x08
0142 #define YSEL_M3 0x10
0143
0144
0145 #define MODE 0x80
0146
0147 #define LEN 0x40
0148
0149 #define LLCMODE 0x20
0150
0151 #define AINC 0x10
0152
0153
0154 #define VSCTL 0x08
0155
0156 #define OEN_TRI_SEL_MASK 0x07
0157 #define OEN_TRI_SEL_ALL_ON 0x00
0158 #define OEN_TRI_SEL_ALL_OFF_r0 0x06
0159 #define OEN_TRI_SEL_ALL_OFF_r1 0x07
0160
0161
0162 #define VSP_LO 0x00
0163 #define VSP_HI 0x80
0164
0165 #define VSSL_VSYNC 0x00
0166 #define VSSL_VACT 0x10
0167 #define VSSL_FIELD 0x20
0168 #define VSSL_VVALID 0x30
0169 #define VSSL_ZERO 0x70
0170 #define HSP_LOW 0x00
0171 #define HSP_HI 0x08
0172
0173 #define HSSL_HACT 0x00
0174 #define HSSL_HSYNC 0x01
0175 #define HSSL_DVALID 0x02
0176 #define HSSL_HLOCK 0x03
0177 #define HSSL_ASYNCW 0x04
0178 #define HSSL_ZERO 0x07
0179
0180
0181 #define SRESET 0x80
0182
0183
0184
0185 #define ACNTL1_PDN_MASK 0x0e
0186 #define CLK_PDN 0x08
0187 #define Y_PDN 0x04
0188 #define C_PDN 0x02
0189
0190
0191 #define ACNTL2_PDN_MASK 0x40
0192 #define PLL_PDN 0x40
0193
0194
0195
0196
0197 #define RTSEL_MASK 0x07
0198 #define RTSEL_VLOSS 0x00
0199 #define RTSEL_HLOCK 0x01
0200 #define RTSEL_SLOCK 0x02
0201 #define RTSEL_VLOCK 0x03
0202 #define RTSEL_MONO 0x04
0203 #define RTSEL_DET50 0x05
0204 #define RTSEL_FIELD 0x06
0205 #define RTSEL_RTCO 0x07
0206
0207
0208 #define HSYNC_START 0x0260
0209 #define HSYNC_END 0x0300
0210
0211
0212
0213
0214
0215 struct regval_list {
0216 unsigned char reg_num;
0217 unsigned char value;
0218 };
0219
0220 struct tw9910_scale_ctrl {
0221 char *name;
0222 unsigned short width;
0223 unsigned short height;
0224 u16 hscale;
0225 u16 vscale;
0226 };
0227
0228 struct tw9910_priv {
0229 struct v4l2_subdev subdev;
0230 struct clk *clk;
0231 struct tw9910_video_info *info;
0232 struct gpio_desc *pdn_gpio;
0233 struct gpio_desc *rstb_gpio;
0234 const struct tw9910_scale_ctrl *scale;
0235 v4l2_std_id norm;
0236 u32 revision;
0237 };
0238
0239 static const struct tw9910_scale_ctrl tw9910_ntsc_scales[] = {
0240 {
0241 .name = "NTSC SQ",
0242 .width = 640,
0243 .height = 480,
0244 .hscale = 0x0100,
0245 .vscale = 0x0100,
0246 },
0247 {
0248 .name = "NTSC CCIR601",
0249 .width = 720,
0250 .height = 480,
0251 .hscale = 0x0100,
0252 .vscale = 0x0100,
0253 },
0254 {
0255 .name = "NTSC SQ (CIF)",
0256 .width = 320,
0257 .height = 240,
0258 .hscale = 0x0200,
0259 .vscale = 0x0200,
0260 },
0261 {
0262 .name = "NTSC CCIR601 (CIF)",
0263 .width = 360,
0264 .height = 240,
0265 .hscale = 0x0200,
0266 .vscale = 0x0200,
0267 },
0268 {
0269 .name = "NTSC SQ (QCIF)",
0270 .width = 160,
0271 .height = 120,
0272 .hscale = 0x0400,
0273 .vscale = 0x0400,
0274 },
0275 {
0276 .name = "NTSC CCIR601 (QCIF)",
0277 .width = 180,
0278 .height = 120,
0279 .hscale = 0x0400,
0280 .vscale = 0x0400,
0281 },
0282 };
0283
0284 static const struct tw9910_scale_ctrl tw9910_pal_scales[] = {
0285 {
0286 .name = "PAL SQ",
0287 .width = 768,
0288 .height = 576,
0289 .hscale = 0x0100,
0290 .vscale = 0x0100,
0291 },
0292 {
0293 .name = "PAL CCIR601",
0294 .width = 720,
0295 .height = 576,
0296 .hscale = 0x0100,
0297 .vscale = 0x0100,
0298 },
0299 {
0300 .name = "PAL SQ (CIF)",
0301 .width = 384,
0302 .height = 288,
0303 .hscale = 0x0200,
0304 .vscale = 0x0200,
0305 },
0306 {
0307 .name = "PAL CCIR601 (CIF)",
0308 .width = 360,
0309 .height = 288,
0310 .hscale = 0x0200,
0311 .vscale = 0x0200,
0312 },
0313 {
0314 .name = "PAL SQ (QCIF)",
0315 .width = 192,
0316 .height = 144,
0317 .hscale = 0x0400,
0318 .vscale = 0x0400,
0319 },
0320 {
0321 .name = "PAL CCIR601 (QCIF)",
0322 .width = 180,
0323 .height = 144,
0324 .hscale = 0x0400,
0325 .vscale = 0x0400,
0326 },
0327 };
0328
0329
0330
0331
0332 static struct tw9910_priv *to_tw9910(const struct i2c_client *client)
0333 {
0334 return container_of(i2c_get_clientdata(client), struct tw9910_priv,
0335 subdev);
0336 }
0337
0338 static int tw9910_mask_set(struct i2c_client *client, u8 command,
0339 u8 mask, u8 set)
0340 {
0341 s32 val = i2c_smbus_read_byte_data(client, command);
0342
0343 if (val < 0)
0344 return val;
0345
0346 val &= ~mask;
0347 val |= set & mask;
0348
0349 return i2c_smbus_write_byte_data(client, command, val);
0350 }
0351
0352 static int tw9910_set_scale(struct i2c_client *client,
0353 const struct tw9910_scale_ctrl *scale)
0354 {
0355 int ret;
0356
0357 ret = i2c_smbus_write_byte_data(client, SCALE_HI,
0358 (scale->vscale & 0x0F00) >> 4 |
0359 (scale->hscale & 0x0F00) >> 8);
0360 if (ret < 0)
0361 return ret;
0362
0363 ret = i2c_smbus_write_byte_data(client, HSCALE_LO,
0364 scale->hscale & 0x00FF);
0365 if (ret < 0)
0366 return ret;
0367
0368 ret = i2c_smbus_write_byte_data(client, VSCALE_LO,
0369 scale->vscale & 0x00FF);
0370
0371 return ret;
0372 }
0373
0374 static int tw9910_set_hsync(struct i2c_client *client)
0375 {
0376 struct tw9910_priv *priv = to_tw9910(client);
0377 int ret;
0378
0379
0380 ret = i2c_smbus_write_byte_data(client, HSBEGIN,
0381 (HSYNC_START & 0x07F8) >> 3);
0382 if (ret < 0)
0383 return ret;
0384
0385
0386 ret = i2c_smbus_write_byte_data(client, HSEND,
0387 (HSYNC_END & 0x07F8) >> 3);
0388 if (ret < 0)
0389 return ret;
0390
0391
0392
0393 if (priv->revision == 1)
0394 ret = tw9910_mask_set(client, HSLOWCTL, 0x77,
0395 (HSYNC_START & 0x0007) << 4 |
0396 (HSYNC_END & 0x0007));
0397
0398 return ret;
0399 }
0400
0401 static void tw9910_reset(struct i2c_client *client)
0402 {
0403 tw9910_mask_set(client, ACNTL1, SRESET, SRESET);
0404 usleep_range(1000, 5000);
0405 }
0406
0407 static int tw9910_power(struct i2c_client *client, int enable)
0408 {
0409 int ret;
0410 u8 acntl1;
0411 u8 acntl2;
0412
0413 if (enable) {
0414 acntl1 = 0;
0415 acntl2 = 0;
0416 } else {
0417 acntl1 = CLK_PDN | Y_PDN | C_PDN;
0418 acntl2 = PLL_PDN;
0419 }
0420
0421 ret = tw9910_mask_set(client, ACNTL1, ACNTL1_PDN_MASK, acntl1);
0422 if (ret < 0)
0423 return ret;
0424
0425 return tw9910_mask_set(client, ACNTL2, ACNTL2_PDN_MASK, acntl2);
0426 }
0427
0428 static const struct tw9910_scale_ctrl *tw9910_select_norm(v4l2_std_id norm,
0429 u32 width, u32 height)
0430 {
0431 const struct tw9910_scale_ctrl *scale;
0432 const struct tw9910_scale_ctrl *ret = NULL;
0433 __u32 diff = 0xffffffff, tmp;
0434 int size, i;
0435
0436 if (norm & V4L2_STD_NTSC) {
0437 scale = tw9910_ntsc_scales;
0438 size = ARRAY_SIZE(tw9910_ntsc_scales);
0439 } else if (norm & V4L2_STD_PAL) {
0440 scale = tw9910_pal_scales;
0441 size = ARRAY_SIZE(tw9910_pal_scales);
0442 } else {
0443 return NULL;
0444 }
0445
0446 for (i = 0; i < size; i++) {
0447 tmp = abs(width - scale[i].width) +
0448 abs(height - scale[i].height);
0449 if (tmp < diff) {
0450 diff = tmp;
0451 ret = scale + i;
0452 }
0453 }
0454
0455 return ret;
0456 }
0457
0458
0459
0460
0461 static int tw9910_s_stream(struct v4l2_subdev *sd, int enable)
0462 {
0463 struct i2c_client *client = v4l2_get_subdevdata(sd);
0464 struct tw9910_priv *priv = to_tw9910(client);
0465 u8 val;
0466 int ret;
0467
0468 if (!enable) {
0469 switch (priv->revision) {
0470 case 0:
0471 val = OEN_TRI_SEL_ALL_OFF_r0;
0472 break;
0473 case 1:
0474 val = OEN_TRI_SEL_ALL_OFF_r1;
0475 break;
0476 default:
0477 dev_err(&client->dev, "un-supported revision\n");
0478 return -EINVAL;
0479 }
0480 } else {
0481 val = OEN_TRI_SEL_ALL_ON;
0482
0483 if (!priv->scale) {
0484 dev_err(&client->dev, "norm select error\n");
0485 return -EPERM;
0486 }
0487
0488 dev_dbg(&client->dev, "%s %dx%d\n",
0489 priv->scale->name,
0490 priv->scale->width,
0491 priv->scale->height);
0492 }
0493
0494 ret = tw9910_mask_set(client, OPFORM, OEN_TRI_SEL_MASK, val);
0495 if (ret < 0)
0496 return ret;
0497
0498 return tw9910_power(client, enable);
0499 }
0500
0501 static int tw9910_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm)
0502 {
0503 struct i2c_client *client = v4l2_get_subdevdata(sd);
0504 struct tw9910_priv *priv = to_tw9910(client);
0505
0506 *norm = priv->norm;
0507
0508 return 0;
0509 }
0510
0511 static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
0512 {
0513 struct i2c_client *client = v4l2_get_subdevdata(sd);
0514 struct tw9910_priv *priv = to_tw9910(client);
0515 const unsigned int hact = 720;
0516 const unsigned int hdelay = 15;
0517 unsigned int vact;
0518 unsigned int vdelay;
0519 int ret;
0520
0521 if (!(norm & (V4L2_STD_NTSC | V4L2_STD_PAL)))
0522 return -EINVAL;
0523
0524 priv->norm = norm;
0525 if (norm & V4L2_STD_525_60) {
0526 vact = 240;
0527 vdelay = 18;
0528 ret = tw9910_mask_set(client, VVBI, 0x10, 0x10);
0529 } else {
0530 vact = 288;
0531 vdelay = 24;
0532 ret = tw9910_mask_set(client, VVBI, 0x10, 0x00);
0533 }
0534 if (!ret)
0535 ret = i2c_smbus_write_byte_data(client, CROP_HI,
0536 ((vdelay >> 2) & 0xc0) |
0537 ((vact >> 4) & 0x30) |
0538 ((hdelay >> 6) & 0x0c) |
0539 ((hact >> 8) & 0x03));
0540 if (!ret)
0541 ret = i2c_smbus_write_byte_data(client, VDELAY_LO,
0542 vdelay & 0xff);
0543 if (!ret)
0544 ret = i2c_smbus_write_byte_data(client, VACTIVE_LO,
0545 vact & 0xff);
0546
0547 return ret;
0548 }
0549
0550 #ifdef CONFIG_VIDEO_ADV_DEBUG
0551 static int tw9910_g_register(struct v4l2_subdev *sd,
0552 struct v4l2_dbg_register *reg)
0553 {
0554 struct i2c_client *client = v4l2_get_subdevdata(sd);
0555 int ret;
0556
0557 if (reg->reg > 0xff)
0558 return -EINVAL;
0559
0560 reg->size = 1;
0561 ret = i2c_smbus_read_byte_data(client, reg->reg);
0562 if (ret < 0)
0563 return ret;
0564
0565
0566
0567
0568
0569 reg->val = (__u64)ret;
0570
0571 return 0;
0572 }
0573
0574 static int tw9910_s_register(struct v4l2_subdev *sd,
0575 const struct v4l2_dbg_register *reg)
0576 {
0577 struct i2c_client *client = v4l2_get_subdevdata(sd);
0578
0579 if (reg->reg > 0xff ||
0580 reg->val > 0xff)
0581 return -EINVAL;
0582
0583 return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
0584 }
0585 #endif
0586
0587 static void tw9910_set_gpio_value(struct gpio_desc *desc, int value)
0588 {
0589 if (desc) {
0590 gpiod_set_value(desc, value);
0591 usleep_range(500, 1000);
0592 }
0593 }
0594
0595 static int tw9910_power_on(struct tw9910_priv *priv)
0596 {
0597 struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev);
0598 int ret;
0599
0600 if (priv->clk) {
0601 ret = clk_prepare_enable(priv->clk);
0602 if (ret)
0603 return ret;
0604 }
0605
0606 tw9910_set_gpio_value(priv->pdn_gpio, 0);
0607
0608
0609
0610
0611
0612
0613
0614 priv->rstb_gpio = gpiod_get_optional(&client->dev, "rstb",
0615 GPIOD_OUT_LOW);
0616 if (IS_ERR(priv->rstb_gpio)) {
0617 dev_info(&client->dev, "Unable to get GPIO \"rstb\"");
0618 clk_disable_unprepare(priv->clk);
0619 tw9910_set_gpio_value(priv->pdn_gpio, 1);
0620 return PTR_ERR(priv->rstb_gpio);
0621 }
0622
0623 if (priv->rstb_gpio) {
0624 tw9910_set_gpio_value(priv->rstb_gpio, 1);
0625 tw9910_set_gpio_value(priv->rstb_gpio, 0);
0626
0627 gpiod_put(priv->rstb_gpio);
0628 }
0629
0630 return 0;
0631 }
0632
0633 static int tw9910_power_off(struct tw9910_priv *priv)
0634 {
0635 clk_disable_unprepare(priv->clk);
0636 tw9910_set_gpio_value(priv->pdn_gpio, 1);
0637
0638 return 0;
0639 }
0640
0641 static int tw9910_s_power(struct v4l2_subdev *sd, int on)
0642 {
0643 struct i2c_client *client = v4l2_get_subdevdata(sd);
0644 struct tw9910_priv *priv = to_tw9910(client);
0645
0646 return on ? tw9910_power_on(priv) : tw9910_power_off(priv);
0647 }
0648
0649 static int tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height)
0650 {
0651 struct i2c_client *client = v4l2_get_subdevdata(sd);
0652 struct tw9910_priv *priv = to_tw9910(client);
0653 int ret = -EINVAL;
0654 u8 val;
0655
0656
0657 priv->scale = tw9910_select_norm(priv->norm, *width, *height);
0658 if (!priv->scale)
0659 goto tw9910_set_fmt_error;
0660
0661
0662 tw9910_reset(client);
0663
0664
0665 val = 0x00;
0666 if (priv->info->buswidth == 16)
0667 val = LEN;
0668
0669 ret = tw9910_mask_set(client, OPFORM, LEN, val);
0670 if (ret < 0)
0671 goto tw9910_set_fmt_error;
0672
0673
0674 switch (priv->info->mpout) {
0675 case TW9910_MPO_VLOSS:
0676 val = RTSEL_VLOSS; break;
0677 case TW9910_MPO_HLOCK:
0678 val = RTSEL_HLOCK; break;
0679 case TW9910_MPO_SLOCK:
0680 val = RTSEL_SLOCK; break;
0681 case TW9910_MPO_VLOCK:
0682 val = RTSEL_VLOCK; break;
0683 case TW9910_MPO_MONO:
0684 val = RTSEL_MONO; break;
0685 case TW9910_MPO_DET50:
0686 val = RTSEL_DET50; break;
0687 case TW9910_MPO_FIELD:
0688 val = RTSEL_FIELD; break;
0689 case TW9910_MPO_RTCO:
0690 val = RTSEL_RTCO; break;
0691 default:
0692 val = 0;
0693 }
0694
0695 ret = tw9910_mask_set(client, VBICNTL, RTSEL_MASK, val);
0696 if (ret < 0)
0697 goto tw9910_set_fmt_error;
0698
0699
0700 ret = tw9910_set_scale(client, priv->scale);
0701 if (ret < 0)
0702 goto tw9910_set_fmt_error;
0703
0704
0705 ret = tw9910_set_hsync(client);
0706 if (ret < 0)
0707 goto tw9910_set_fmt_error;
0708
0709 *width = priv->scale->width;
0710 *height = priv->scale->height;
0711
0712 return ret;
0713
0714 tw9910_set_fmt_error:
0715
0716 tw9910_reset(client);
0717 priv->scale = NULL;
0718
0719 return ret;
0720 }
0721
0722 static int tw9910_get_selection(struct v4l2_subdev *sd,
0723 struct v4l2_subdev_state *sd_state,
0724 struct v4l2_subdev_selection *sel)
0725 {
0726 struct i2c_client *client = v4l2_get_subdevdata(sd);
0727 struct tw9910_priv *priv = to_tw9910(client);
0728
0729 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
0730 return -EINVAL;
0731
0732 if (sel->target > V4L2_SEL_TGT_CROP_BOUNDS)
0733 return -EINVAL;
0734
0735 sel->r.left = 0;
0736 sel->r.top = 0;
0737 if (priv->norm & V4L2_STD_NTSC) {
0738 sel->r.width = 640;
0739 sel->r.height = 480;
0740 } else {
0741 sel->r.width = 768;
0742 sel->r.height = 576;
0743 }
0744
0745 return 0;
0746 }
0747
0748 static int tw9910_get_fmt(struct v4l2_subdev *sd,
0749 struct v4l2_subdev_state *sd_state,
0750 struct v4l2_subdev_format *format)
0751 {
0752 struct v4l2_mbus_framefmt *mf = &format->format;
0753 struct i2c_client *client = v4l2_get_subdevdata(sd);
0754 struct tw9910_priv *priv = to_tw9910(client);
0755
0756 if (format->pad)
0757 return -EINVAL;
0758
0759 if (!priv->scale) {
0760 priv->scale = tw9910_select_norm(priv->norm, 640, 480);
0761 if (!priv->scale)
0762 return -EINVAL;
0763 }
0764
0765 mf->width = priv->scale->width;
0766 mf->height = priv->scale->height;
0767 mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
0768 mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
0769 mf->field = V4L2_FIELD_INTERLACED_BT;
0770
0771 return 0;
0772 }
0773
0774 static int tw9910_s_fmt(struct v4l2_subdev *sd,
0775 struct v4l2_mbus_framefmt *mf)
0776 {
0777 u32 width = mf->width, height = mf->height;
0778 int ret;
0779
0780 WARN_ON(mf->field != V4L2_FIELD_ANY &&
0781 mf->field != V4L2_FIELD_INTERLACED_BT);
0782
0783
0784 if (mf->code != MEDIA_BUS_FMT_UYVY8_2X8)
0785 return -EINVAL;
0786
0787 mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
0788
0789 ret = tw9910_set_frame(sd, &width, &height);
0790 if (ret)
0791 return ret;
0792
0793 mf->width = width;
0794 mf->height = height;
0795
0796 return 0;
0797 }
0798
0799 static int tw9910_set_fmt(struct v4l2_subdev *sd,
0800 struct v4l2_subdev_state *sd_state,
0801 struct v4l2_subdev_format *format)
0802 {
0803 struct v4l2_mbus_framefmt *mf = &format->format;
0804 struct i2c_client *client = v4l2_get_subdevdata(sd);
0805 struct tw9910_priv *priv = to_tw9910(client);
0806 const struct tw9910_scale_ctrl *scale;
0807
0808 if (format->pad)
0809 return -EINVAL;
0810
0811 if (mf->field == V4L2_FIELD_ANY) {
0812 mf->field = V4L2_FIELD_INTERLACED_BT;
0813 } else if (mf->field != V4L2_FIELD_INTERLACED_BT) {
0814 dev_err(&client->dev, "Field type %d invalid\n", mf->field);
0815 return -EINVAL;
0816 }
0817
0818 mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
0819 mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
0820
0821
0822 scale = tw9910_select_norm(priv->norm, mf->width, mf->height);
0823 if (!scale)
0824 return -EINVAL;
0825
0826 mf->width = scale->width;
0827 mf->height = scale->height;
0828
0829 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
0830 return tw9910_s_fmt(sd, mf);
0831
0832 sd_state->pads->try_fmt = *mf;
0833
0834 return 0;
0835 }
0836
0837 static int tw9910_video_probe(struct i2c_client *client)
0838 {
0839 struct tw9910_priv *priv = to_tw9910(client);
0840 s32 id;
0841 int ret;
0842
0843
0844 if (priv->info->buswidth != 16 && priv->info->buswidth != 8) {
0845 dev_err(&client->dev, "bus width error\n");
0846 return -ENODEV;
0847 }
0848
0849 ret = tw9910_s_power(&priv->subdev, 1);
0850 if (ret < 0)
0851 return ret;
0852
0853
0854
0855
0856
0857 id = i2c_smbus_read_byte_data(client, ID);
0858 priv->revision = GET_REV(id);
0859 id = GET_ID(id);
0860
0861 if (id != 0x0b || priv->revision > 0x01) {
0862 dev_err(&client->dev, "Product ID error %x:%x\n",
0863 id, priv->revision);
0864 ret = -ENODEV;
0865 goto done;
0866 }
0867
0868 dev_info(&client->dev, "tw9910 Product ID %0x:%0x\n",
0869 id, priv->revision);
0870
0871 priv->norm = V4L2_STD_NTSC;
0872 priv->scale = &tw9910_ntsc_scales[0];
0873
0874 done:
0875 tw9910_s_power(&priv->subdev, 0);
0876
0877 return ret;
0878 }
0879
0880 static const struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
0881 #ifdef CONFIG_VIDEO_ADV_DEBUG
0882 .g_register = tw9910_g_register,
0883 .s_register = tw9910_s_register,
0884 #endif
0885 .s_power = tw9910_s_power,
0886 };
0887
0888 static int tw9910_enum_mbus_code(struct v4l2_subdev *sd,
0889 struct v4l2_subdev_state *sd_state,
0890 struct v4l2_subdev_mbus_code_enum *code)
0891 {
0892 if (code->pad || code->index)
0893 return -EINVAL;
0894
0895 code->code = MEDIA_BUS_FMT_UYVY8_2X8;
0896
0897 return 0;
0898 }
0899
0900 static int tw9910_g_tvnorms(struct v4l2_subdev *sd, v4l2_std_id *norm)
0901 {
0902 *norm = V4L2_STD_NTSC | V4L2_STD_PAL;
0903
0904 return 0;
0905 }
0906
0907 static const struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {
0908 .s_std = tw9910_s_std,
0909 .g_std = tw9910_g_std,
0910 .s_stream = tw9910_s_stream,
0911 .g_tvnorms = tw9910_g_tvnorms,
0912 };
0913
0914 static const struct v4l2_subdev_pad_ops tw9910_subdev_pad_ops = {
0915 .enum_mbus_code = tw9910_enum_mbus_code,
0916 .get_selection = tw9910_get_selection,
0917 .get_fmt = tw9910_get_fmt,
0918 .set_fmt = tw9910_set_fmt,
0919 };
0920
0921 static const struct v4l2_subdev_ops tw9910_subdev_ops = {
0922 .core = &tw9910_subdev_core_ops,
0923 .video = &tw9910_subdev_video_ops,
0924 .pad = &tw9910_subdev_pad_ops,
0925 };
0926
0927
0928
0929
0930
0931 static int tw9910_probe(struct i2c_client *client,
0932 const struct i2c_device_id *did)
0933
0934 {
0935 struct tw9910_priv *priv;
0936 struct tw9910_video_info *info;
0937 struct i2c_adapter *adapter = client->adapter;
0938 int ret;
0939
0940 if (!client->dev.platform_data) {
0941 dev_err(&client->dev, "TW9910: missing platform data!\n");
0942 return -EINVAL;
0943 }
0944
0945 info = client->dev.platform_data;
0946
0947 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
0948 dev_err(&client->dev,
0949 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE_DATA\n");
0950 return -EIO;
0951 }
0952
0953 priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
0954 if (!priv)
0955 return -ENOMEM;
0956
0957 priv->info = info;
0958
0959 v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops);
0960
0961 priv->clk = clk_get(&client->dev, "xti");
0962 if (PTR_ERR(priv->clk) == -ENOENT) {
0963 priv->clk = NULL;
0964 } else if (IS_ERR(priv->clk)) {
0965 dev_err(&client->dev, "Unable to get xti clock\n");
0966 return PTR_ERR(priv->clk);
0967 }
0968
0969 priv->pdn_gpio = gpiod_get_optional(&client->dev, "pdn",
0970 GPIOD_OUT_HIGH);
0971 if (IS_ERR(priv->pdn_gpio)) {
0972 dev_info(&client->dev, "Unable to get GPIO \"pdn\"");
0973 ret = PTR_ERR(priv->pdn_gpio);
0974 goto error_clk_put;
0975 }
0976
0977 ret = tw9910_video_probe(client);
0978 if (ret < 0)
0979 goto error_gpio_put;
0980
0981 ret = v4l2_async_register_subdev(&priv->subdev);
0982 if (ret)
0983 goto error_gpio_put;
0984
0985 return ret;
0986
0987 error_gpio_put:
0988 if (priv->pdn_gpio)
0989 gpiod_put(priv->pdn_gpio);
0990 error_clk_put:
0991 clk_put(priv->clk);
0992
0993 return ret;
0994 }
0995
0996 static int tw9910_remove(struct i2c_client *client)
0997 {
0998 struct tw9910_priv *priv = to_tw9910(client);
0999
1000 if (priv->pdn_gpio)
1001 gpiod_put(priv->pdn_gpio);
1002 clk_put(priv->clk);
1003 v4l2_async_unregister_subdev(&priv->subdev);
1004
1005 return 0;
1006 }
1007
1008 static const struct i2c_device_id tw9910_id[] = {
1009 { "tw9910", 0 },
1010 { }
1011 };
1012 MODULE_DEVICE_TABLE(i2c, tw9910_id);
1013
1014 static struct i2c_driver tw9910_i2c_driver = {
1015 .driver = {
1016 .name = "tw9910",
1017 },
1018 .probe = tw9910_probe,
1019 .remove = tw9910_remove,
1020 .id_table = tw9910_id,
1021 };
1022
1023 module_i2c_driver(tw9910_i2c_driver);
1024
1025 MODULE_DESCRIPTION("V4L2 driver for TW9910 video decoder");
1026 MODULE_AUTHOR("Kuninori Morimoto");
1027 MODULE_LICENSE("GPL v2");