File Index
Files and directories
Sign in
FILE

tw9910.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/i2c/tw9910.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * tw9910 Video Driver
   4 *
   5 * Copyright (C) 2017 Jacopo Mondi <jacopo+renesas@jmondi.org>
   6 *
   7 * Copyright (C) 2008 Renesas Solutions Corp.
   8 * Kuninori Morimoto <morimoto.kuninori@renesas.com>
   9 *
  10 * Based on ov772x driver,
  11 *
  12 * Copyright (C) 2008 Kuninori Morimoto <morimoto.kuninori@renesas.com>
  13 * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
  14 * Copyright (C) 2008 Magnus Damm
  15 * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
  16 */
  17
  18#include <linux/clk.h>
  19#include <linux/delay.h>
  20#include <linux/gpio/consumer.h>
  21#include <linux/i2c.h>
  22#include <linux/init.h>
  23#include <linux/kernel.h>
  24#include <linux/module.h>
  25#include <linux/slab.h>
  26#include <linux/v4l2-mediabus.h>
  27#include <linux/videodev2.h>
  28
  29#include <media/i2c/tw9910.h>
  30#include <media/v4l2-subdev.h>
  31
  32#define GET_ID(val)  ((val & 0xF8) >> 3)
  33#define GET_REV(val) (val & 0x07)
  34
  35/*
  36 * register offset
  37 */
  38#define ID		0x00 /* Product ID Code Register */
  39#define STATUS1		0x01 /* Chip Status Register I */
  40#define INFORM		0x02 /* Input Format */
  41#define OPFORM		0x03 /* Output Format Control Register */
  42#define DLYCTR		0x04 /* Hysteresis and HSYNC Delay Control */
  43#define OUTCTR1		0x05 /* Output Control I */
  44#define ACNTL1		0x06 /* Analog Control Register 1 */
  45#define CROP_HI		0x07 /* Cropping Register, High */
  46#define VDELAY_LO	0x08 /* Vertical Delay Register, Low */
  47#define VACTIVE_LO	0x09 /* Vertical Active Register, Low */
  48#define HDELAY_LO	0x0A /* Horizontal Delay Register, Low */
  49#define HACTIVE_LO	0x0B /* Horizontal Active Register, Low */
  50#define CNTRL1		0x0C /* Control Register I */
  51#define VSCALE_LO	0x0D /* Vertical Scaling Register, Low */
  52#define SCALE_HI	0x0E /* Scaling Register, High */
  53#define HSCALE_LO	0x0F /* Horizontal Scaling Register, Low */
  54#define BRIGHT		0x10 /* BRIGHTNESS Control Register */
  55#define CONTRAST	0x11 /* CONTRAST Control Register */
  56#define SHARPNESS	0x12 /* SHARPNESS Control Register I */
  57#define SAT_U		0x13 /* Chroma (U) Gain Register */
  58#define SAT_V		0x14 /* Chroma (V) Gain Register */
  59#define HUE		0x15 /* Hue Control Register */
  60#define CORING1		0x17
  61#define CORING2		0x18 /* Coring and IF compensation */
  62#define VBICNTL		0x19 /* VBI Control Register */
  63#define ACNTL2		0x1A /* Analog Control 2 */
  64#define OUTCTR2		0x1B /* Output Control 2 */
  65#define SDT		0x1C /* Standard Selection */
  66#define SDTR		0x1D /* Standard Recognition */
  67#define TEST		0x1F /* Test Control Register */
  68#define CLMPG		0x20 /* Clamping Gain */
  69#define IAGC		0x21 /* Individual AGC Gain */
  70#define AGCGAIN		0x22 /* AGC Gain */
  71#define PEAKWT		0x23 /* White Peak Threshold */
  72#define CLMPL		0x24 /* Clamp level */
  73#define SYNCT		0x25 /* Sync Amplitude */
  74#define MISSCNT		0x26 /* Sync Miss Count Register */
  75#define PCLAMP		0x27 /* Clamp Position Register */
  76#define VCNTL1		0x28 /* Vertical Control I */
  77#define VCNTL2		0x29 /* Vertical Control II */
  78#define CKILL		0x2A /* Color Killer Level Control */
  79#define COMB		0x2B /* Comb Filter Control */
  80#define LDLY		0x2C /* Luma Delay and H Filter Control */
  81#define MISC1		0x2D /* Miscellaneous Control I */
  82#define LOOP		0x2E /* LOOP Control Register */
  83#define MISC2		0x2F /* Miscellaneous Control II */
  84#define MVSN		0x30 /* Macrovision Detection */
  85#define STATUS2		0x31 /* Chip STATUS II */
  86#define HFREF		0x32 /* H monitor */
  87#define CLMD		0x33 /* CLAMP MODE */
  88#define IDCNTL		0x34 /* ID Detection Control */
  89#define CLCNTL1		0x35 /* Clamp Control I */
  90#define ANAPLLCTL	0x4C
  91#define VBIMIN		0x4D
  92#define HSLOWCTL	0x4E
  93#define WSS3		0x4F
  94#define FILLDATA	0x50
  95#define SDID		0x51
  96#define DID		0x52
  97#define WSS1		0x53
  98#define WSS2		0x54
  99#define VVBI		0x55
 100#define LCTL6		0x56
 101#define LCTL7		0x57
 102#define LCTL8		0x58
 103#define LCTL9		0x59
 104#define LCTL10		0x5A
 105#define LCTL11		0x5B
 106#define LCTL12		0x5C
 107#define LCTL13		0x5D
 108#define LCTL14		0x5E
 109#define LCTL15		0x5F
 110#define LCTL16		0x60
 111#define LCTL17		0x61
 112#define LCTL18		0x62
 113#define LCTL19		0x63
 114#define LCTL20		0x64
 115#define LCTL21		0x65
 116#define LCTL22		0x66
 117#define LCTL23		0x67
 118#define LCTL24		0x68
 119#define LCTL25		0x69
 120#define LCTL26		0x6A
 121#define HSBEGIN		0x6B
 122#define HSEND		0x6C
 123#define OVSDLY		0x6D
 124#define OVSEND		0x6E
 125#define VBIDELAY	0x6F
 126
 127/*
 128 * register detail
 129 */
 130
 131/* INFORM */
 132#define FC27_ON     0x40 /* 1 : Input crystal clock frequency is 27MHz */
 133#define FC27_FF     0x00 /* 0 : Square pixel mode. */
 134			 /*     Must use 24.54MHz for 60Hz field rate */
 135			 /*     source or 29.5MHz for 50Hz field rate */
 136#define IFSEL_S     0x10 /* 01 : S-video decoding */
 137#define IFSEL_C     0x00 /* 00 : Composite video decoding */
 138			 /* Y input video selection */
 139#define YSEL_M0     0x00 /*  00 : Mux0 selected */
 140#define YSEL_M1     0x04 /*  01 : Mux1 selected */
 141#define YSEL_M2     0x08 /*  10 : Mux2 selected */
 142#define YSEL_M3     0x10 /*  11 : Mux3 selected */
 143
 144/* OPFORM */
 145#define MODE        0x80 /* 0 : CCIR601 compatible YCrCb 4:2:2 format */
 146			 /* 1 : ITU-R-656 compatible data sequence format */
 147#define LEN         0x40 /* 0 : 8-bit YCrCb 4:2:2 output format */
 148			 /* 1 : 16-bit YCrCb 4:2:2 output format.*/
 149#define LLCMODE     0x20 /* 1 : LLC output mode. */
 150			 /* 0 : free-run output mode */
 151#define AINC        0x10 /* Serial interface auto-indexing control */
 152			 /* 0 : auto-increment */
 153			 /* 1 : non-auto */
 154#define VSCTL       0x08 /* 1 : Vertical out ctrl by DVALID */
 155			 /* 0 : Vertical out ctrl by HACTIVE and DVALID */
 156#define OEN_TRI_SEL_MASK	0x07
 157#define OEN_TRI_SEL_ALL_ON	0x00 /* Enable output for Rev0/Rev1 */
 158#define OEN_TRI_SEL_ALL_OFF_r0	0x06 /* All tri-stated for Rev0 */
 159#define OEN_TRI_SEL_ALL_OFF_r1	0x07 /* All tri-stated for Rev1 */
 160
 161/* OUTCTR1 */
 162#define VSP_LO      0x00 /* 0 : VS pin output polarity is active low */
 163#define VSP_HI      0x80 /* 1 : VS pin output polarity is active high. */
 164			 /* VS pin output control */
 165#define VSSL_VSYNC  0x00 /*   0 : VSYNC  */
 166#define VSSL_VACT   0x10 /*   1 : VACT   */
 167#define VSSL_FIELD  0x20 /*   2 : FIELD  */
 168#define VSSL_VVALID 0x30 /*   3 : VVALID */
 169#define VSSL_ZERO   0x70 /*   7 : 0      */
 170#define HSP_LOW     0x00 /* 0 : HS pin output polarity is active low */
 171#define HSP_HI      0x08 /* 1 : HS pin output polarity is active high.*/
 172			 /* HS pin output control */
 173#define HSSL_HACT   0x00 /*   0 : HACT   */
 174#define HSSL_HSYNC  0x01 /*   1 : HSYNC  */
 175#define HSSL_DVALID 0x02 /*   2 : DVALID */
 176#define HSSL_HLOCK  0x03 /*   3 : HLOCK  */
 177#define HSSL_ASYNCW 0x04 /*   4 : ASYNCW */
 178#define HSSL_ZERO   0x07 /*   7 : 0      */
 179
 180/* ACNTL1 */
 181#define SRESET      0x80 /* resets the device to its default state
 182			  * but all register content remain unchanged.
 183			  * This bit is self-resetting.
 184			  */
 185#define ACNTL1_PDN_MASK	0x0e
 186#define CLK_PDN		0x08 /* system clock power down */
 187#define Y_PDN		0x04 /* Luma ADC power down */
 188#define C_PDN		0x02 /* Chroma ADC power down */
 189
 190/* ACNTL2 */
 191#define ACNTL2_PDN_MASK	0x40
 192#define PLL_PDN		0x40 /* PLL power down */
 193
 194/* VBICNTL */
 195
 196/* RTSEL : control the real time signal output from the MPOUT pin */
 197#define RTSEL_MASK  0x07
 198#define RTSEL_VLOSS 0x00 /* 0000 = Video loss */
 199#define RTSEL_HLOCK 0x01 /* 0001 = H-lock */
 200#define RTSEL_SLOCK 0x02 /* 0010 = S-lock */
 201#define RTSEL_VLOCK 0x03 /* 0011 = V-lock */
 202#define RTSEL_MONO  0x04 /* 0100 = MONO */
 203#define RTSEL_DET50 0x05 /* 0101 = DET50 */
 204#define RTSEL_FIELD 0x06 /* 0110 = FIELD */
 205#define RTSEL_RTCO  0x07 /* 0111 = RTCO ( Real Time Control ) */
 206
 207/* HSYNC start and end are constant for now */
 208#define HSYNC_START	0x0260
 209#define HSYNC_END	0x0300
 210
 211/*
 212 * structure
 213 */
 214
 215struct tw9910_scale_ctrl {
 216	char           *name;
 217	unsigned short  width;
 218	unsigned short  height;
 219	u16             hscale;
 220	u16             vscale;
 221};
 222
 223struct tw9910_priv {
 224	struct v4l2_subdev		subdev;
 225	struct clk			*clk;
 226	struct tw9910_video_info	*info;
 227	struct gpio_desc		*pdn_gpio;
 228	struct gpio_desc		*rstb_gpio;
 229	const struct tw9910_scale_ctrl	*scale;
 230	v4l2_std_id			norm;
 231	u32				revision;
 232};
 233
 234static const struct tw9910_scale_ctrl tw9910_ntsc_scales[] = {
 235	{
 236		.name   = "NTSC SQ",
 237		.width  = 640,
 238		.height = 480,
 239		.hscale = 0x0100,
 240		.vscale = 0x0100,
 241	},
 242	{
 243		.name   = "NTSC CCIR601",
 244		.width  = 720,
 245		.height = 480,
 246		.hscale = 0x0100,
 247		.vscale = 0x0100,
 248	},
 249	{
 250		.name   = "NTSC SQ (CIF)",
 251		.width  = 320,
 252		.height = 240,
 253		.hscale = 0x0200,
 254		.vscale = 0x0200,
 255	},
 256	{
 257		.name   = "NTSC CCIR601 (CIF)",
 258		.width  = 360,
 259		.height = 240,
 260		.hscale = 0x0200,
 261		.vscale = 0x0200,
 262	},
 263	{
 264		.name   = "NTSC SQ (QCIF)",
 265		.width  = 160,
 266		.height = 120,
 267		.hscale = 0x0400,
 268		.vscale = 0x0400,
 269	},
 270	{
 271		.name   = "NTSC CCIR601 (QCIF)",
 272		.width  = 180,
 273		.height = 120,
 274		.hscale = 0x0400,
 275		.vscale = 0x0400,
 276	},
 277};
 278
 279static const struct tw9910_scale_ctrl tw9910_pal_scales[] = {
 280	{
 281		.name   = "PAL SQ",
 282		.width  = 768,
 283		.height = 576,
 284		.hscale = 0x0100,
 285		.vscale = 0x0100,
 286	},
 287	{
 288		.name   = "PAL CCIR601",
 289		.width  = 720,
 290		.height = 576,
 291		.hscale = 0x0100,
 292		.vscale = 0x0100,
 293	},
 294	{
 295		.name   = "PAL SQ (CIF)",
 296		.width  = 384,
 297		.height = 288,
 298		.hscale = 0x0200,
 299		.vscale = 0x0200,
 300	},
 301	{
 302		.name   = "PAL CCIR601 (CIF)",
 303		.width  = 360,
 304		.height = 288,
 305		.hscale = 0x0200,
 306		.vscale = 0x0200,
 307	},
 308	{
 309		.name   = "PAL SQ (QCIF)",
 310		.width  = 192,
 311		.height = 144,
 312		.hscale = 0x0400,
 313		.vscale = 0x0400,
 314	},
 315	{
 316		.name   = "PAL CCIR601 (QCIF)",
 317		.width  = 180,
 318		.height = 144,
 319		.hscale = 0x0400,
 320		.vscale = 0x0400,
 321	},
 322};
 323
 324/*
 325 * general function
 326 */
 327static struct tw9910_priv *to_tw9910(const struct i2c_client *client)
 328{
 329	return container_of(i2c_get_clientdata(client), struct tw9910_priv,
 330			    subdev);
 331}
 332
 333static int tw9910_mask_set(struct i2c_client *client, u8 command,
 334			   u8 mask, u8 set)
 335{
 336	s32 val = i2c_smbus_read_byte_data(client, command);
 337
 338	if (val < 0)
 339		return val;
 340
 341	val &= ~mask;
 342	val |= set & mask;
 343
 344	return i2c_smbus_write_byte_data(client, command, val);
 345}
 346
 347static int tw9910_set_scale(struct i2c_client *client,
 348			    const struct tw9910_scale_ctrl *scale)
 349{
 350	int ret;
 351
 352	ret = i2c_smbus_write_byte_data(client, SCALE_HI,
 353					(scale->vscale & 0x0F00) >> 4 |
 354					(scale->hscale & 0x0F00) >> 8);
 355	if (ret < 0)
 356		return ret;
 357
 358	ret = i2c_smbus_write_byte_data(client, HSCALE_LO,
 359					scale->hscale & 0x00FF);
 360	if (ret < 0)
 361		return ret;
 362
 363	ret = i2c_smbus_write_byte_data(client, VSCALE_LO,
 364					scale->vscale & 0x00FF);
 365
 366	return ret;
 367}
 368
 369static int tw9910_set_hsync(struct i2c_client *client)
 370{
 371	struct tw9910_priv *priv = to_tw9910(client);
 372	int ret;
 373
 374	/* bit 10 - 3 */
 375	ret = i2c_smbus_write_byte_data(client, HSBEGIN,
 376					(HSYNC_START & 0x07F8) >> 3);
 377	if (ret < 0)
 378		return ret;
 379
 380	/* bit 10 - 3 */
 381	ret = i2c_smbus_write_byte_data(client, HSEND,
 382					(HSYNC_END & 0x07F8) >> 3);
 383	if (ret < 0)
 384		return ret;
 385
 386	/* So far only revisions 0 and 1 have been seen. */
 387	/* bit 2 - 0 */
 388	if (priv->revision == 1)
 389		ret = tw9910_mask_set(client, HSLOWCTL, 0x77,
 390				      (HSYNC_START & 0x0007) << 4 |
 391				      (HSYNC_END   & 0x0007));
 392
 393	return ret;
 394}
 395
 396static void tw9910_reset(struct i2c_client *client)
 397{
 398	tw9910_mask_set(client, ACNTL1, SRESET, SRESET);
 399	usleep_range(1000, 5000);
 400}
 401
 402static int tw9910_power(struct i2c_client *client, int enable)
 403{
 404	int ret;
 405	u8 acntl1;
 406	u8 acntl2;
 407
 408	if (enable) {
 409		acntl1 = 0;
 410		acntl2 = 0;
 411	} else {
 412		acntl1 = CLK_PDN | Y_PDN | C_PDN;
 413		acntl2 = PLL_PDN;
 414	}
 415
 416	ret = tw9910_mask_set(client, ACNTL1, ACNTL1_PDN_MASK, acntl1);
 417	if (ret < 0)
 418		return ret;
 419
 420	return tw9910_mask_set(client, ACNTL2, ACNTL2_PDN_MASK, acntl2);
 421}
 422
 423static const struct tw9910_scale_ctrl *tw9910_select_norm(v4l2_std_id norm,
 424							  u32 width, u32 height)
 425{
 426	const struct tw9910_scale_ctrl *scale;
 427	const struct tw9910_scale_ctrl *ret = NULL;
 428	__u32 diff = 0xffffffff, tmp;
 429	int size, i;
 430
 431	if (norm & V4L2_STD_NTSC) {
 432		scale = tw9910_ntsc_scales;
 433		size = ARRAY_SIZE(tw9910_ntsc_scales);
 434	} else if (norm & V4L2_STD_PAL) {
 435		scale = tw9910_pal_scales;
 436		size = ARRAY_SIZE(tw9910_pal_scales);
 437	} else {
 438		return NULL;
 439	}
 440
 441	for (i = 0; i < size; i++) {
 442		tmp = abs(width - scale[i].width) +
 443		      abs(height - scale[i].height);
 444		if (tmp < diff) {
 445			diff = tmp;
 446			ret = scale + i;
 447		}
 448	}
 449
 450	return ret;
 451}
 452
 453/*
 454 * subdevice operations
 455 */
 456static int tw9910_s_stream(struct v4l2_subdev *sd, int enable)
 457{
 458	struct i2c_client *client = v4l2_get_subdevdata(sd);
 459	struct tw9910_priv *priv = to_tw9910(client);
 460	u8 val;
 461	int ret;
 462
 463	if (!enable) {
 464		switch (priv->revision) {
 465		case 0:
 466			val = OEN_TRI_SEL_ALL_OFF_r0;
 467			break;
 468		case 1:
 469			val = OEN_TRI_SEL_ALL_OFF_r1;
 470			break;
 471		default:
 472			dev_err(&client->dev, "un-supported revision\n");
 473			return -EINVAL;
 474		}
 475	} else {
 476		val = OEN_TRI_SEL_ALL_ON;
 477
 478		if (!priv->scale) {
 479			dev_err(&client->dev, "norm select error\n");
 480			return -EPERM;
 481		}
 482
 483		dev_dbg(&client->dev, "%s %dx%d\n",
 484			priv->scale->name,
 485			priv->scale->width,
 486			priv->scale->height);
 487	}
 488
 489	ret = tw9910_mask_set(client, OPFORM, OEN_TRI_SEL_MASK, val);
 490	if (ret < 0)
 491		return ret;
 492
 493	return tw9910_power(client, enable);
 494}
 495
 496static int tw9910_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm)
 497{
 498	struct i2c_client *client = v4l2_get_subdevdata(sd);
 499	struct tw9910_priv *priv = to_tw9910(client);
 500
 501	*norm = priv->norm;
 502
 503	return 0;
 504}
 505
 506static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
 507{
 508	struct i2c_client *client = v4l2_get_subdevdata(sd);
 509	struct tw9910_priv *priv = to_tw9910(client);
 510	const unsigned int hact = 720;
 511	const unsigned int hdelay = 15;
 512	unsigned int vact;
 513	unsigned int vdelay;
 514	int ret;
 515
 516	if (!(norm & (V4L2_STD_NTSC | V4L2_STD_PAL)))
 517		return -EINVAL;
 518
 519	priv->norm = norm;
 520	if (norm & V4L2_STD_525_60) {
 521		vact = 240;
 522		vdelay = 18;
 523		ret = tw9910_mask_set(client, VVBI, 0x10, 0x10);
 524	} else {
 525		vact = 288;
 526		vdelay = 24;
 527		ret = tw9910_mask_set(client, VVBI, 0x10, 0x00);
 528	}
 529	if (!ret)
 530		ret = i2c_smbus_write_byte_data(client, CROP_HI,
 531						((vdelay >> 2) & 0xc0)	|
 532						((vact >> 4) & 0x30)	|
 533						((hdelay >> 6) & 0x0c)	|
 534						((hact >> 8) & 0x03));
 535	if (!ret)
 536		ret = i2c_smbus_write_byte_data(client, VDELAY_LO,
 537						vdelay & 0xff);
 538	if (!ret)
 539		ret = i2c_smbus_write_byte_data(client, VACTIVE_LO,
 540						vact & 0xff);
 541
 542	return ret;
 543}
 544
 545#ifdef CONFIG_VIDEO_ADV_DEBUG
 546static int tw9910_g_register(struct v4l2_subdev *sd,
 547			     struct v4l2_dbg_register *reg)
 548{
 549	struct i2c_client *client = v4l2_get_subdevdata(sd);
 550	int ret;
 551
 552	if (reg->reg > 0xff)
 553		return -EINVAL;
 554
 555	reg->size = 1;
 556	ret = i2c_smbus_read_byte_data(client, reg->reg);
 557	if (ret < 0)
 558		return ret;
 559
 560	/*
 561	 * ret      = int
 562	 * reg->val = __u64
 563	 */
 564	reg->val = (__u64)ret;
 565
 566	return 0;
 567}
 568
 569static int tw9910_s_register(struct v4l2_subdev *sd,
 570			     const struct v4l2_dbg_register *reg)
 571{
 572	struct i2c_client *client = v4l2_get_subdevdata(sd);
 573
 574	if (reg->reg > 0xff ||
 575	    reg->val > 0xff)
 576		return -EINVAL;
 577
 578	return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
 579}
 580#endif
 581
 582static void tw9910_set_gpio_value(struct gpio_desc *desc, int value)
 583{
 584	if (desc) {
 585		gpiod_set_value(desc, value);
 586		usleep_range(500, 1000);
 587	}
 588}
 589
 590static int tw9910_power_on(struct tw9910_priv *priv)
 591{
 592	struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev);
 593	int ret;
 594
 595	if (priv->clk) {
 596		ret = clk_prepare_enable(priv->clk);
 597		if (ret)
 598			return ret;
 599	}
 600
 601	tw9910_set_gpio_value(priv->pdn_gpio, 0);
 602
 603	/*
 604	 * FIXME: The reset signal is connected to a shared GPIO on some
 605	 * platforms (namely the SuperH Migo-R). Until a framework becomes
 606	 * available to handle this cleanly, request the GPIO temporarily
 607	 * to avoid conflicts.
 608	 */
 609	priv->rstb_gpio = gpiod_get_optional(&client->dev, "rstb",
 610					     GPIOD_OUT_LOW);
 611	if (IS_ERR(priv->rstb_gpio)) {
 612		dev_info(&client->dev, "Unable to get GPIO \"rstb\"");
 613		clk_disable_unprepare(priv->clk);
 614		tw9910_set_gpio_value(priv->pdn_gpio, 1);
 615		return PTR_ERR(priv->rstb_gpio);
 616	}
 617
 618	if (priv->rstb_gpio) {
 619		tw9910_set_gpio_value(priv->rstb_gpio, 1);
 620		tw9910_set_gpio_value(priv->rstb_gpio, 0);
 621
 622		gpiod_put(priv->rstb_gpio);
 623	}
 624
 625	return 0;
 626}
 627
 628static int tw9910_power_off(struct tw9910_priv *priv)
 629{
 630	clk_disable_unprepare(priv->clk);
 631	tw9910_set_gpio_value(priv->pdn_gpio, 1);
 632
 633	return 0;
 634}
 635
 636static int tw9910_s_power(struct v4l2_subdev *sd, int on)
 637{
 638	struct i2c_client *client = v4l2_get_subdevdata(sd);
 639	struct tw9910_priv *priv = to_tw9910(client);
 640
 641	return on ? tw9910_power_on(priv) : tw9910_power_off(priv);
 642}
 643
 644static int tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height)
 645{
 646	struct i2c_client *client = v4l2_get_subdevdata(sd);
 647	struct tw9910_priv *priv = to_tw9910(client);
 648	int ret = -EINVAL;
 649	u8 val;
 650
 651	/* Select suitable norm. */
 652	priv->scale = tw9910_select_norm(priv->norm, *width, *height);
 653	if (!priv->scale)
 654		goto tw9910_set_fmt_error;
 655
 656	/* Reset hardware. */
 657	tw9910_reset(client);
 658
 659	/* Set bus width. */
 660	val = 0x00;
 661	if (priv->info->buswidth == 16)
 662		val = LEN;
 663
 664	ret = tw9910_mask_set(client, OPFORM, LEN, val);
 665	if (ret < 0)
 666		goto tw9910_set_fmt_error;
 667
 668	/* Select MPOUT behavior. */
 669	switch (priv->info->mpout) {
 670	case TW9910_MPO_VLOSS:
 671		val = RTSEL_VLOSS; break;
 672	case TW9910_MPO_HLOCK:
 673		val = RTSEL_HLOCK; break;
 674	case TW9910_MPO_SLOCK:
 675		val = RTSEL_SLOCK; break;
 676	case TW9910_MPO_VLOCK:
 677		val = RTSEL_VLOCK; break;
 678	case TW9910_MPO_MONO:
 679		val = RTSEL_MONO;  break;
 680	case TW9910_MPO_DET50:
 681		val = RTSEL_DET50; break;
 682	case TW9910_MPO_FIELD:
 683		val = RTSEL_FIELD; break;
 684	case TW9910_MPO_RTCO:
 685		val = RTSEL_RTCO;  break;
 686	default:
 687		val = 0;
 688	}
 689
 690	ret = tw9910_mask_set(client, VBICNTL, RTSEL_MASK, val);
 691	if (ret < 0)
 692		goto tw9910_set_fmt_error;
 693
 694	/* Set scale. */
 695	ret = tw9910_set_scale(client, priv->scale);
 696	if (ret < 0)
 697		goto tw9910_set_fmt_error;
 698
 699	/* Set hsync. */
 700	ret = tw9910_set_hsync(client);
 701	if (ret < 0)
 702		goto tw9910_set_fmt_error;
 703
 704	*width = priv->scale->width;
 705	*height = priv->scale->height;
 706
 707	return ret;
 708
 709tw9910_set_fmt_error:
 710
 711	tw9910_reset(client);
 712	priv->scale = NULL;
 713
 714	return ret;
 715}
 716
 717static int tw9910_get_selection(struct v4l2_subdev *sd,
 718				struct v4l2_subdev_state *sd_state,
 719				struct v4l2_subdev_selection *sel)
 720{
 721	struct i2c_client *client = v4l2_get_subdevdata(sd);
 722	struct tw9910_priv *priv = to_tw9910(client);
 723
 724	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
 725		return -EINVAL;
 726	/* Only CROP, CROP_DEFAULT and CROP_BOUNDS are supported. */
 727	if (sel->target > V4L2_SEL_TGT_CROP_BOUNDS)
 728		return -EINVAL;
 729
 730	sel->r.left	= 0;
 731	sel->r.top	= 0;
 732	if (priv->norm & V4L2_STD_NTSC) {
 733		sel->r.width	= 640;
 734		sel->r.height	= 480;
 735	} else {
 736		sel->r.width	= 768;
 737		sel->r.height	= 576;
 738	}
 739
 740	return 0;
 741}
 742
 743static int tw9910_get_fmt(struct v4l2_subdev *sd,
 744			  struct v4l2_subdev_state *sd_state,
 745			  struct v4l2_subdev_format *format)
 746{
 747	struct v4l2_mbus_framefmt *mf = &format->format;
 748	struct i2c_client *client = v4l2_get_subdevdata(sd);
 749	struct tw9910_priv *priv = to_tw9910(client);
 750
 751	if (format->pad)
 752		return -EINVAL;
 753
 754	if (!priv->scale) {
 755		priv->scale = tw9910_select_norm(priv->norm, 640, 480);
 756		if (!priv->scale)
 757			return -EINVAL;
 758	}
 759
 760	mf->width	= priv->scale->width;
 761	mf->height	= priv->scale->height;
 762	mf->code	= MEDIA_BUS_FMT_UYVY8_2X8;
 763	mf->colorspace	= V4L2_COLORSPACE_SMPTE170M;
 764	mf->field	= V4L2_FIELD_INTERLACED_BT;
 765
 766	return 0;
 767}
 768
 769static int tw9910_s_fmt(struct v4l2_subdev *sd,
 770			struct v4l2_mbus_framefmt *mf)
 771{
 772	u32 width = mf->width, height = mf->height;
 773	int ret;
 774
 775	WARN_ON(mf->field != V4L2_FIELD_ANY &&
 776		mf->field != V4L2_FIELD_INTERLACED_BT);
 777
 778	/* Check color format. */
 779	if (mf->code != MEDIA_BUS_FMT_UYVY8_2X8)
 780		return -EINVAL;
 781
 782	mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
 783
 784	ret = tw9910_set_frame(sd, &width, &height);
 785	if (ret)
 786		return ret;
 787
 788	mf->width	= width;
 789	mf->height	= height;
 790
 791	return 0;
 792}
 793
 794static int tw9910_set_fmt(struct v4l2_subdev *sd,
 795			  struct v4l2_subdev_state *sd_state,
 796			  struct v4l2_subdev_format *format)
 797{
 798	struct v4l2_mbus_framefmt *mf = &format->format;
 799	struct i2c_client *client = v4l2_get_subdevdata(sd);
 800	struct tw9910_priv *priv = to_tw9910(client);
 801	const struct tw9910_scale_ctrl *scale;
 802
 803	if (format->pad)
 804		return -EINVAL;
 805
 806	if (mf->field == V4L2_FIELD_ANY) {
 807		mf->field = V4L2_FIELD_INTERLACED_BT;
 808	} else if (mf->field != V4L2_FIELD_INTERLACED_BT) {
 809		dev_err(&client->dev, "Field type %d invalid\n", mf->field);
 810		return -EINVAL;
 811	}
 812
 813	mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
 814	mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
 815
 816	/* Select suitable norm. */
 817	scale = tw9910_select_norm(priv->norm, mf->width, mf->height);
 818	if (!scale)
 819		return -EINVAL;
 820
 821	mf->width	= scale->width;
 822	mf->height	= scale->height;
 823
 824	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
 825		return tw9910_s_fmt(sd, mf);
 826
 827	return 0;
 828}
 829
 830static int tw9910_video_probe(struct i2c_client *client)
 831{
 832	struct tw9910_priv *priv = to_tw9910(client);
 833	s32 id;
 834	int ret;
 835
 836	/* TW9910 only use 8 or 16 bit bus width. */
 837	if (priv->info->buswidth != 16 && priv->info->buswidth != 8) {
 838		dev_err(&client->dev, "bus width error\n");
 839		return -ENODEV;
 840	}
 841
 842	ret = tw9910_s_power(&priv->subdev, 1);
 843	if (ret < 0)
 844		return ret;
 845
 846	/*
 847	 * Check and show Product ID.
 848	 * So far only revisions 0 and 1 have been seen.
 849	 */
 850	id = i2c_smbus_read_byte_data(client, ID);
 851	priv->revision = GET_REV(id);
 852	id = GET_ID(id);
 853
 854	if (id != 0x0b || priv->revision > 0x01) {
 855		dev_err(&client->dev, "Product ID error %x:%x\n",
 856			id, priv->revision);
 857		ret = -ENODEV;
 858		goto done;
 859	}
 860
 861	dev_info(&client->dev, "tw9910 Product ID %0x:%0x\n",
 862		 id, priv->revision);
 863
 864	priv->norm = V4L2_STD_NTSC;
 865	priv->scale = &tw9910_ntsc_scales[0];
 866
 867done:
 868	tw9910_s_power(&priv->subdev, 0);
 869
 870	return ret;
 871}
 872
 873static const struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
 874#ifdef CONFIG_VIDEO_ADV_DEBUG
 875	.g_register	= tw9910_g_register,
 876	.s_register	= tw9910_s_register,
 877#endif
 878	.s_power	= tw9910_s_power,
 879};
 880
 881static int tw9910_enum_mbus_code(struct v4l2_subdev *sd,
 882				 struct v4l2_subdev_state *sd_state,
 883				 struct v4l2_subdev_mbus_code_enum *code)
 884{
 885	if (code->pad || code->index)
 886		return -EINVAL;
 887
 888	code->code = MEDIA_BUS_FMT_UYVY8_2X8;
 889
 890	return 0;
 891}
 892
 893static int tw9910_g_tvnorms(struct v4l2_subdev *sd, v4l2_std_id *norm)
 894{
 895	*norm = V4L2_STD_NTSC | V4L2_STD_PAL;
 896
 897	return 0;
 898}
 899
 900static const struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {
 901	.s_std		= tw9910_s_std,
 902	.g_std		= tw9910_g_std,
 903	.s_stream	= tw9910_s_stream,
 904	.g_tvnorms	= tw9910_g_tvnorms,
 905};
 906
 907static const struct v4l2_subdev_pad_ops tw9910_subdev_pad_ops = {
 908	.enum_mbus_code = tw9910_enum_mbus_code,
 909	.get_selection	= tw9910_get_selection,
 910	.get_fmt	= tw9910_get_fmt,
 911	.set_fmt	= tw9910_set_fmt,
 912};
 913
 914static const struct v4l2_subdev_ops tw9910_subdev_ops = {
 915	.core	= &tw9910_subdev_core_ops,
 916	.video	= &tw9910_subdev_video_ops,
 917	.pad	= &tw9910_subdev_pad_ops,
 918};
 919
 920/*
 921 * i2c_driver function
 922 */
 923
 924static int tw9910_probe(struct i2c_client *client)
 925
 926{
 927	struct tw9910_priv		*priv;
 928	struct tw9910_video_info	*info;
 929	struct i2c_adapter		*adapter = client->adapter;
 930	int ret;
 931
 932	if (!client->dev.platform_data) {
 933		dev_err(&client->dev, "TW9910: missing platform data!\n");
 934		return -EINVAL;
 935	}
 936
 937	info = client->dev.platform_data;
 938
 939	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
 940		dev_err(&client->dev,
 941			"I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE_DATA\n");
 942		return -EIO;
 943	}
 944
 945	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
 946	if (!priv)
 947		return -ENOMEM;
 948
 949	priv->info = info;
 950
 951	v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops);
 952
 953	priv->clk = clk_get(&client->dev, "xti");
 954	if (PTR_ERR(priv->clk) == -ENOENT) {
 955		priv->clk = NULL;
 956	} else if (IS_ERR(priv->clk)) {
 957		dev_err(&client->dev, "Unable to get xti clock\n");
 958		return PTR_ERR(priv->clk);
 959	}
 960
 961	priv->pdn_gpio = gpiod_get_optional(&client->dev, "pdn",
 962					    GPIOD_OUT_HIGH);
 963	if (IS_ERR(priv->pdn_gpio)) {
 964		dev_info(&client->dev, "Unable to get GPIO \"pdn\"");
 965		ret = PTR_ERR(priv->pdn_gpio);
 966		goto error_clk_put;
 967	}
 968
 969	ret = tw9910_video_probe(client);
 970	if (ret < 0)
 971		goto error_gpio_put;
 972
 973	ret = v4l2_async_register_subdev(&priv->subdev);
 974	if (ret)
 975		goto error_gpio_put;
 976
 977	return ret;
 978
 979error_gpio_put:
 980	if (priv->pdn_gpio)
 981		gpiod_put(priv->pdn_gpio);
 982error_clk_put:
 983	clk_put(priv->clk);
 984
 985	return ret;
 986}
 987
 988static void tw9910_remove(struct i2c_client *client)
 989{
 990	struct tw9910_priv *priv = to_tw9910(client);
 991
 992	if (priv->pdn_gpio)
 993		gpiod_put(priv->pdn_gpio);
 994	clk_put(priv->clk);
 995	v4l2_async_unregister_subdev(&priv->subdev);
 996}
 997
 998static const struct i2c_device_id tw9910_id[] = {
 999	{ "tw9910" },
1000	{ }
1001};
1002MODULE_DEVICE_TABLE(i2c, tw9910_id);
1003
1004static struct i2c_driver tw9910_i2c_driver = {
1005	.driver = {
1006		.name = "tw9910",
1007	},
1008	.probe    = tw9910_probe,
1009	.remove   = tw9910_remove,
1010	.id_table = tw9910_id,
1011};
1012
1013module_i2c_driver(tw9910_i2c_driver);
1014
1015MODULE_DESCRIPTION("V4L2 driver for TW9910 video decoder");
1016MODULE_AUTHOR("Kuninori Morimoto");
1017MODULE_LICENSE("GPL v2");
~/ Read-only file preview.