File Index
Files and directories
Sign in
FILE

ov7740.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/i2c/ov7740.c C
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (c) 2017 Microchip Corporation.
   3
   4#include <linux/clk.h>
   5#include <linux/delay.h>
   6#include <linux/gpio/consumer.h>
   7#include <linux/i2c.h>
   8#include <linux/module.h>
   9#include <linux/pm_runtime.h>
  10#include <linux/regmap.h>
  11#include <media/v4l2-ctrls.h>
  12#include <media/v4l2-event.h>
  13#include <media/v4l2-image-sizes.h>
  14#include <media/v4l2-subdev.h>
  15
  16#define REG_OUTSIZE_LSB 0x34
  17
  18/* OV7740 register tables */
  19#define REG_GAIN	0x00	/* Gain lower 8 bits (rest in vref) */
  20#define REG_BGAIN	0x01	/* blue gain */
  21#define REG_RGAIN	0x02	/* red gain */
  22#define REG_GGAIN	0x03	/* green gain */
  23#define REG_REG04	0x04	/* analog setting, don't change*/
  24#define REG_BAVG	0x05	/* b channel average */
  25#define REG_GAVG	0x06	/* g channel average */
  26#define REG_RAVG	0x07	/* r channel average */
  27
  28#define REG_REG0C	0x0C	/* filp enable */
  29#define REG0C_IMG_FLIP		0x80
  30#define REG0C_IMG_MIRROR	0x40
  31
  32#define REG_REG0E	0x0E	/* blc line */
  33#define REG_HAEC	0x0F	/* auto exposure cntrl */
  34#define REG_AEC		0x10	/* auto exposure cntrl */
  35
  36#define REG_CLK		0x11	/* Clock control */
  37#define REG_REG55	0x55	/* Clock PLL DIV/PreDiv */
  38
  39#define REG_REG12	0x12
  40
  41#define REG_REG13	0x13	/* auto/manual AGC, AEC, Write Balance*/
  42#define REG13_AEC_EN	0x01
  43#define REG13_AGC_EN	0x04
  44
  45#define REG_REG14	0x14
  46#define REG_CTRL15	0x15
  47#define REG15_GAIN_MSB	0x03
  48
  49#define REG_REG16	0x16
  50
  51#define REG_MIDH	0x1C	/* manufacture id byte */
  52#define REG_MIDL	0x1D	/* manufacture id byre */
  53#define REG_PIDH	0x0A	/* Product ID MSB */
  54#define REG_PIDL	0x0B	/* Product ID LSB */
  55
  56#define REG_84		0x84	/* lots of stuff */
  57#define REG_REG38	0x38	/* sub-addr */
  58
  59#define REG_AHSTART	0x17	/* Horiz start high bits */
  60#define REG_AHSIZE	0x18
  61#define REG_AVSTART	0x19	/* Vert start high bits */
  62#define REG_AVSIZE	0x1A
  63#define REG_PSHFT	0x1b	/* Pixel delay after HREF */
  64
  65#define REG_HOUTSIZE	0x31
  66#define REG_VOUTSIZE	0x32
  67#define REG_HVSIZEOFF	0x33
  68#define REG_REG34	0x34	/* DSP output size H/V LSB*/
  69
  70#define REG_ISP_CTRL00	0x80
  71#define ISPCTRL00_AWB_EN	0x10
  72#define ISPCTRL00_AWB_GAIN_EN	0x04
  73
  74#define	REG_YGAIN	0xE2	/* ygain for contrast control */
  75
  76#define	REG_YBRIGHT	  0xE3
  77#define	REG_SGNSET	  0xE4
  78#define	SGNSET_YBRIGHT_MASK	  0x08
  79
  80#define REG_USAT	0xDD
  81#define REG_VSAT	0xDE
  82
  83
  84struct ov7740 {
  85	struct v4l2_subdev subdev;
  86	struct media_pad pad;
  87	struct v4l2_mbus_framefmt format;
  88	const struct ov7740_pixfmt *fmt;  /* Current format */
  89	const struct ov7740_framesize *frmsize;
  90	struct regmap *regmap;
  91	struct clk *xvclk;
  92	struct v4l2_ctrl_handler ctrl_handler;
  93	struct {
  94		/* gain cluster */
  95		struct v4l2_ctrl *auto_gain;
  96		struct v4l2_ctrl *gain;
  97	};
  98	struct {
  99		struct v4l2_ctrl *auto_wb;
 100		struct v4l2_ctrl *blue_balance;
 101		struct v4l2_ctrl *red_balance;
 102	};
 103	struct {
 104		struct v4l2_ctrl *hflip;
 105		struct v4l2_ctrl *vflip;
 106	};
 107	struct {
 108		/* exposure cluster */
 109		struct v4l2_ctrl *auto_exposure;
 110		struct v4l2_ctrl *exposure;
 111	};
 112	struct {
 113		/* saturation/hue cluster */
 114		struct v4l2_ctrl *saturation;
 115		struct v4l2_ctrl *hue;
 116	};
 117	struct v4l2_ctrl *brightness;
 118	struct v4l2_ctrl *contrast;
 119
 120	struct mutex mutex;	/* To serialize asynchronous callbacks */
 121
 122	struct gpio_desc *resetb_gpio;
 123	struct gpio_desc *pwdn_gpio;
 124};
 125
 126struct ov7740_pixfmt {
 127	u32 mbus_code;
 128	enum v4l2_colorspace colorspace;
 129	const struct reg_sequence *regs;
 130	u32 reg_num;
 131};
 132
 133struct ov7740_framesize {
 134	u16 width;
 135	u16 height;
 136	const struct reg_sequence *regs;
 137	u32 reg_num;
 138};
 139
 140static const struct reg_sequence ov7740_vga[] = {
 141	{0x55, 0x40},
 142	{0x11, 0x02},
 143
 144	{0xd5, 0x10},
 145	{0x0c, 0x12},
 146	{0x0d, 0x34},
 147	{0x17, 0x25},
 148	{0x18, 0xa0},
 149	{0x19, 0x03},
 150	{0x1a, 0xf0},
 151	{0x1b, 0x89},
 152	{0x22, 0x03},
 153	{0x29, 0x18},
 154	{0x2b, 0xf8},
 155	{0x2c, 0x01},
 156	{REG_HOUTSIZE, 0xa0},
 157	{REG_VOUTSIZE, 0xf0},
 158	{0x33, 0xc4},
 159	{REG_OUTSIZE_LSB, 0x0},
 160	{0x35, 0x05},
 161	{0x04, 0x60},
 162	{0x27, 0x80},
 163	{0x3d, 0x0f},
 164	{0x3e, 0x80},
 165	{0x3f, 0x40},
 166	{0x40, 0x7f},
 167	{0x41, 0x6a},
 168	{0x42, 0x29},
 169	{0x44, 0x22},
 170	{0x45, 0x41},
 171	{0x47, 0x02},
 172	{0x49, 0x64},
 173	{0x4a, 0xa1},
 174	{0x4b, 0x40},
 175	{0x4c, 0x1a},
 176	{0x4d, 0x50},
 177	{0x4e, 0x13},
 178	{0x64, 0x00},
 179	{0x67, 0x88},
 180	{0x68, 0x1a},
 181
 182	{0x14, 0x28},
 183	{0x24, 0x3c},
 184	{0x25, 0x30},
 185	{0x26, 0x72},
 186	{0x50, 0x97},
 187	{0x51, 0x1f},
 188	{0x52, 0x00},
 189	{0x53, 0x00},
 190	{0x20, 0x00},
 191	{0x21, 0xcf},
 192	{0x50, 0x4b},
 193	{0x38, 0x14},
 194	{0xe9, 0x00},
 195	{0x56, 0x55},
 196	{0x57, 0xff},
 197	{0x58, 0xff},
 198	{0x59, 0xff},
 199	{0x5f, 0x04},
 200	{0xec, 0x00},
 201	{0x13, 0xff},
 202
 203	{0x81, 0x3f},
 204	{0x82, 0x32},
 205	{0x38, 0x11},
 206	{0x84, 0x70},
 207	{0x85, 0x00},
 208	{0x86, 0x03},
 209	{0x87, 0x01},
 210	{0x88, 0x05},
 211	{0x89, 0x30},
 212	{0x8d, 0x30},
 213	{0x8f, 0x85},
 214	{0x93, 0x30},
 215	{0x95, 0x85},
 216	{0x99, 0x30},
 217	{0x9b, 0x85},
 218
 219	{0x9c, 0x08},
 220	{0x9d, 0x12},
 221	{0x9e, 0x23},
 222	{0x9f, 0x45},
 223	{0xa0, 0x55},
 224	{0xa1, 0x64},
 225	{0xa2, 0x72},
 226	{0xa3, 0x7f},
 227	{0xa4, 0x8b},
 228	{0xa5, 0x95},
 229	{0xa6, 0xa7},
 230	{0xa7, 0xb5},
 231	{0xa8, 0xcb},
 232	{0xa9, 0xdd},
 233	{0xaa, 0xec},
 234	{0xab, 0x1a},
 235
 236	{0xce, 0x78},
 237	{0xcf, 0x6e},
 238	{0xd0, 0x0a},
 239	{0xd1, 0x0c},
 240	{0xd2, 0x84},
 241	{0xd3, 0x90},
 242	{0xd4, 0x1e},
 243
 244	{0x5a, 0x24},
 245	{0x5b, 0x1f},
 246	{0x5c, 0x88},
 247	{0x5d, 0x60},
 248
 249	{0xac, 0x6e},
 250	{0xbe, 0xff},
 251	{0xbf, 0x00},
 252
 253	{0x0f, 0x1d},
 254	{0x0f, 0x1f},
 255};
 256
 257static const struct ov7740_framesize ov7740_framesizes[] = {
 258	{
 259		.width		= VGA_WIDTH,
 260		.height		= VGA_HEIGHT,
 261		.regs		= ov7740_vga,
 262		.reg_num	= ARRAY_SIZE(ov7740_vga),
 263	},
 264};
 265
 266#ifdef CONFIG_VIDEO_ADV_DEBUG
 267static int ov7740_get_register(struct v4l2_subdev *sd,
 268			       struct v4l2_dbg_register *reg)
 269{
 270	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
 271	struct regmap *regmap = ov7740->regmap;
 272	unsigned int val = 0;
 273	int ret;
 274
 275	ret = regmap_read(regmap, reg->reg & 0xff, &val);
 276	reg->val = val;
 277	reg->size = 1;
 278
 279	return ret;
 280}
 281
 282static int ov7740_set_register(struct v4l2_subdev *sd,
 283			       const struct v4l2_dbg_register *reg)
 284{
 285	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
 286	struct regmap *regmap = ov7740->regmap;
 287
 288	regmap_write(regmap, reg->reg & 0xff, reg->val & 0xff);
 289
 290	return 0;
 291}
 292#endif
 293
 294static int ov7740_set_power(struct ov7740 *ov7740, int on)
 295{
 296	int ret;
 297
 298	if (on) {
 299		ret = clk_prepare_enable(ov7740->xvclk);
 300		if (ret)
 301			return ret;
 302
 303		if (ov7740->pwdn_gpio)
 304			gpiod_direction_output(ov7740->pwdn_gpio, 0);
 305
 306		if (ov7740->resetb_gpio) {
 307			gpiod_set_value(ov7740->resetb_gpio, 1);
 308			usleep_range(500, 1000);
 309			gpiod_set_value(ov7740->resetb_gpio, 0);
 310			usleep_range(3000, 5000);
 311		}
 312	} else {
 313		clk_disable_unprepare(ov7740->xvclk);
 314
 315		if (ov7740->pwdn_gpio)
 316			gpiod_direction_output(ov7740->pwdn_gpio, 0);
 317	}
 318
 319	return 0;
 320}
 321
 322static const struct v4l2_subdev_core_ops ov7740_subdev_core_ops = {
 323	.log_status = v4l2_ctrl_subdev_log_status,
 324#ifdef CONFIG_VIDEO_ADV_DEBUG
 325	.g_register = ov7740_get_register,
 326	.s_register = ov7740_set_register,
 327#endif
 328	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
 329	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
 330};
 331
 332static int ov7740_set_white_balance(struct ov7740 *ov7740, int awb)
 333{
 334	struct regmap *regmap = ov7740->regmap;
 335	unsigned int value;
 336	int ret;
 337
 338	ret = regmap_read(regmap, REG_ISP_CTRL00, &value);
 339	if (!ret) {
 340		if (awb)
 341			value |= (ISPCTRL00_AWB_EN | ISPCTRL00_AWB_GAIN_EN);
 342		else
 343			value &= ~(ISPCTRL00_AWB_EN | ISPCTRL00_AWB_GAIN_EN);
 344		ret = regmap_write(regmap, REG_ISP_CTRL00, value);
 345		if (ret)
 346			return ret;
 347	}
 348
 349	if (!awb) {
 350		ret = regmap_write(regmap, REG_BGAIN,
 351				   ov7740->blue_balance->val);
 352		if (ret)
 353			return ret;
 354
 355		ret = regmap_write(regmap, REG_RGAIN, ov7740->red_balance->val);
 356		if (ret)
 357			return ret;
 358	}
 359
 360	return 0;
 361}
 362
 363static int ov7740_set_saturation(struct regmap *regmap, int value)
 364{
 365	int ret;
 366
 367	ret = regmap_write(regmap, REG_USAT, (unsigned char)value);
 368	if (ret)
 369		return ret;
 370
 371	return regmap_write(regmap, REG_VSAT, (unsigned char)value);
 372}
 373
 374static int ov7740_set_gain(struct regmap *regmap, int value)
 375{
 376	int ret;
 377
 378	ret = regmap_write(regmap, REG_GAIN, value & 0xff);
 379	if (ret)
 380		return ret;
 381
 382	ret = regmap_update_bits(regmap, REG_CTRL15,
 383				 REG15_GAIN_MSB, (value >> 8) & 0x3);
 384	if (!ret)
 385		ret = regmap_update_bits(regmap, REG_REG13, REG13_AGC_EN, 0);
 386
 387	return ret;
 388}
 389
 390static int ov7740_set_autogain(struct regmap *regmap, int value)
 391{
 392	unsigned int reg;
 393	int ret;
 394
 395	ret = regmap_read(regmap, REG_REG13, &reg);
 396	if (ret)
 397		return ret;
 398	if (value)
 399		reg |= REG13_AGC_EN;
 400	else
 401		reg &= ~REG13_AGC_EN;
 402	return regmap_write(regmap, REG_REG13, reg);
 403}
 404
 405static int ov7740_set_brightness(struct regmap *regmap, int value)
 406{
 407	/* Turn off AEC/AGC */
 408	regmap_update_bits(regmap, REG_REG13, REG13_AEC_EN, 0);
 409	regmap_update_bits(regmap, REG_REG13, REG13_AGC_EN, 0);
 410
 411	if (value >= 0) {
 412		regmap_write(regmap, REG_YBRIGHT, (unsigned char)value);
 413		regmap_update_bits(regmap, REG_SGNSET, SGNSET_YBRIGHT_MASK, 0);
 414	} else{
 415		regmap_write(regmap, REG_YBRIGHT, (unsigned char)(-value));
 416		regmap_update_bits(regmap, REG_SGNSET, SGNSET_YBRIGHT_MASK, 1);
 417	}
 418
 419	return 0;
 420}
 421
 422static int ov7740_set_contrast(struct regmap *regmap, int value)
 423{
 424	return regmap_write(regmap, REG_YGAIN, (unsigned char)value);
 425}
 426
 427static int ov7740_get_gain(struct ov7740 *ov7740, struct v4l2_ctrl *ctrl)
 428{
 429	struct regmap *regmap = ov7740->regmap;
 430	unsigned int value0, value1;
 431	int ret;
 432
 433	if (!ctrl->val)
 434		return 0;
 435
 436	ret = regmap_read(regmap, REG_GAIN, &value0);
 437	if (ret)
 438		return ret;
 439	ret = regmap_read(regmap, REG_CTRL15, &value1);
 440	if (ret)
 441		return ret;
 442
 443	ov7740->gain->val = (value1 << 8) | (value0 & 0xff);
 444
 445	return 0;
 446}
 447
 448static int ov7740_get_exp(struct ov7740 *ov7740, struct v4l2_ctrl *ctrl)
 449{
 450	struct regmap *regmap = ov7740->regmap;
 451	unsigned int value0, value1;
 452	int ret;
 453
 454	if (ctrl->val == V4L2_EXPOSURE_MANUAL)
 455		return 0;
 456
 457	ret = regmap_read(regmap, REG_AEC, &value0);
 458	if (ret)
 459		return ret;
 460	ret = regmap_read(regmap, REG_HAEC, &value1);
 461	if (ret)
 462		return ret;
 463
 464	ov7740->exposure->val = (value1 << 8) | (value0 & 0xff);
 465
 466	return 0;
 467}
 468
 469static int ov7740_set_exp(struct regmap *regmap, int value)
 470{
 471	int ret;
 472
 473	/* Turn off AEC/AGC */
 474	ret = regmap_update_bits(regmap, REG_REG13,
 475				 REG13_AEC_EN | REG13_AGC_EN, 0);
 476	if (ret)
 477		return ret;
 478
 479	ret = regmap_write(regmap, REG_AEC, (unsigned char)value);
 480	if (ret)
 481		return ret;
 482
 483	return regmap_write(regmap, REG_HAEC, (unsigned char)(value >> 8));
 484}
 485
 486static int ov7740_set_autoexp(struct regmap *regmap,
 487			      enum v4l2_exposure_auto_type value)
 488{
 489	unsigned int reg;
 490	int ret;
 491
 492	ret = regmap_read(regmap, REG_REG13, &reg);
 493	if (!ret) {
 494		if (value == V4L2_EXPOSURE_AUTO)
 495			reg |= (REG13_AEC_EN | REG13_AGC_EN);
 496		else
 497			reg &= ~(REG13_AEC_EN | REG13_AGC_EN);
 498		ret = regmap_write(regmap, REG_REG13, reg);
 499	}
 500
 501	return ret;
 502}
 503
 504
 505static int ov7740_get_volatile_ctrl(struct v4l2_ctrl *ctrl)
 506{
 507	struct ov7740 *ov7740 = container_of(ctrl->handler,
 508					     struct ov7740, ctrl_handler);
 509	int ret;
 510
 511	switch (ctrl->id) {
 512	case V4L2_CID_AUTOGAIN:
 513		ret = ov7740_get_gain(ov7740, ctrl);
 514		break;
 515	case V4L2_CID_EXPOSURE_AUTO:
 516		ret = ov7740_get_exp(ov7740, ctrl);
 517		break;
 518	default:
 519		ret = -EINVAL;
 520		break;
 521	}
 522	return ret;
 523}
 524
 525static int ov7740_set_ctrl(struct v4l2_ctrl *ctrl)
 526{
 527	struct ov7740 *ov7740 = container_of(ctrl->handler,
 528					     struct ov7740, ctrl_handler);
 529	struct i2c_client *client = v4l2_get_subdevdata(&ov7740->subdev);
 530	struct regmap *regmap = ov7740->regmap;
 531	int ret;
 532	u8 val;
 533
 534	if (!pm_runtime_get_if_in_use(&client->dev))
 535		return 0;
 536
 537	switch (ctrl->id) {
 538	case V4L2_CID_AUTO_WHITE_BALANCE:
 539		ret = ov7740_set_white_balance(ov7740, ctrl->val);
 540		break;
 541	case V4L2_CID_SATURATION:
 542		ret = ov7740_set_saturation(regmap, ctrl->val);
 543		break;
 544	case V4L2_CID_BRIGHTNESS:
 545		ret = ov7740_set_brightness(regmap, ctrl->val);
 546		break;
 547	case V4L2_CID_CONTRAST:
 548		ret = ov7740_set_contrast(regmap, ctrl->val);
 549		break;
 550	case V4L2_CID_VFLIP:
 551		val = ctrl->val ? REG0C_IMG_FLIP : 0x00;
 552		ret = regmap_update_bits(regmap, REG_REG0C,
 553					 REG0C_IMG_FLIP, val);
 554		break;
 555	case V4L2_CID_HFLIP:
 556		val = ctrl->val ? REG0C_IMG_MIRROR : 0x00;
 557		ret = regmap_update_bits(regmap, REG_REG0C,
 558					 REG0C_IMG_MIRROR, val);
 559		break;
 560	case V4L2_CID_AUTOGAIN:
 561		if (!ctrl->val)
 562			ret = ov7740_set_gain(regmap, ov7740->gain->val);
 563		else
 564			ret = ov7740_set_autogain(regmap, ctrl->val);
 565		break;
 566
 567	case V4L2_CID_EXPOSURE_AUTO:
 568		if (ctrl->val == V4L2_EXPOSURE_MANUAL)
 569			ret = ov7740_set_exp(regmap, ov7740->exposure->val);
 570		else
 571			ret = ov7740_set_autoexp(regmap, ctrl->val);
 572		break;
 573	default:
 574		ret = -EINVAL;
 575		break;
 576	}
 577
 578	pm_runtime_put(&client->dev);
 579
 580	return ret;
 581}
 582
 583static const struct v4l2_ctrl_ops ov7740_ctrl_ops = {
 584	.g_volatile_ctrl = ov7740_get_volatile_ctrl,
 585	.s_ctrl = ov7740_set_ctrl,
 586};
 587
 588static int ov7740_start_streaming(struct ov7740 *ov7740)
 589{
 590	int ret;
 591
 592	if (ov7740->fmt) {
 593		ret = regmap_multi_reg_write(ov7740->regmap,
 594					     ov7740->fmt->regs,
 595					     ov7740->fmt->reg_num);
 596		if (ret)
 597			return ret;
 598	}
 599
 600	if (ov7740->frmsize) {
 601		ret = regmap_multi_reg_write(ov7740->regmap,
 602					     ov7740->frmsize->regs,
 603					     ov7740->frmsize->reg_num);
 604		if (ret)
 605			return ret;
 606	}
 607
 608	return __v4l2_ctrl_handler_setup(ov7740->subdev.ctrl_handler);
 609}
 610
 611static int ov7740_set_stream(struct v4l2_subdev *sd, int enable)
 612{
 613	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
 614	struct i2c_client *client = v4l2_get_subdevdata(sd);
 615	int ret = 0;
 616
 617	mutex_lock(&ov7740->mutex);
 618
 619	if (enable) {
 620		ret = pm_runtime_resume_and_get(&client->dev);
 621		if (ret < 0)
 622			goto err_unlock;
 623
 624		ret = ov7740_start_streaming(ov7740);
 625		if (ret)
 626			goto err_rpm_put;
 627	} else {
 628		pm_runtime_put(&client->dev);
 629	}
 630
 631	mutex_unlock(&ov7740->mutex);
 632	return ret;
 633
 634err_rpm_put:
 635	pm_runtime_put(&client->dev);
 636err_unlock:
 637	mutex_unlock(&ov7740->mutex);
 638	return ret;
 639}
 640
 641static const struct v4l2_subdev_video_ops ov7740_subdev_video_ops = {
 642	.s_stream = ov7740_set_stream,
 643};
 644
 645static const struct reg_sequence ov7740_format_yuyv[] = {
 646	{0x12, 0x00},
 647	{0x36, 0x3f},
 648	{0x80, 0x7f},
 649	{0x83, 0x01},
 650};
 651
 652static const struct reg_sequence ov7740_format_bggr8[] = {
 653	{0x36, 0x2f},
 654	{0x80, 0x01},
 655	{0x83, 0x04},
 656};
 657
 658static const struct ov7740_pixfmt ov7740_formats[] = {
 659	{
 660		.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
 661		.colorspace = V4L2_COLORSPACE_SRGB,
 662		.regs = ov7740_format_yuyv,
 663		.reg_num = ARRAY_SIZE(ov7740_format_yuyv),
 664	},
 665	{
 666		.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
 667		.colorspace = V4L2_COLORSPACE_SRGB,
 668		.regs = ov7740_format_bggr8,
 669		.reg_num = ARRAY_SIZE(ov7740_format_bggr8),
 670	}
 671};
 672#define N_OV7740_FMTS ARRAY_SIZE(ov7740_formats)
 673
 674static int ov7740_enum_mbus_code(struct v4l2_subdev *sd,
 675				 struct v4l2_subdev_state *sd_state,
 676				 struct v4l2_subdev_mbus_code_enum *code)
 677{
 678	if (code->pad || code->index >= N_OV7740_FMTS)
 679		return -EINVAL;
 680
 681	code->code = ov7740_formats[code->index].mbus_code;
 682
 683	return 0;
 684}
 685
 686static int ov7740_enum_frame_interval(struct v4l2_subdev *sd,
 687				struct v4l2_subdev_state *sd_state,
 688				struct v4l2_subdev_frame_interval_enum *fie)
 689{
 690	if (fie->pad)
 691		return -EINVAL;
 692
 693	if (fie->index >= 1)
 694		return -EINVAL;
 695
 696	if ((fie->width != VGA_WIDTH) || (fie->height != VGA_HEIGHT))
 697		return -EINVAL;
 698
 699	fie->interval.numerator = 1;
 700	fie->interval.denominator = 60;
 701
 702	return 0;
 703}
 704
 705static int ov7740_enum_frame_size(struct v4l2_subdev *sd,
 706				  struct v4l2_subdev_state *sd_state,
 707				  struct v4l2_subdev_frame_size_enum *fse)
 708{
 709	if (fse->pad)
 710		return -EINVAL;
 711
 712	if (fse->index > 0)
 713		return -EINVAL;
 714
 715	fse->min_width = fse->max_width = VGA_WIDTH;
 716	fse->min_height = fse->max_height = VGA_HEIGHT;
 717
 718	return 0;
 719}
 720
 721static int ov7740_try_fmt_internal(struct v4l2_subdev *sd,
 722				   struct v4l2_mbus_framefmt *fmt,
 723				   const struct ov7740_pixfmt **ret_fmt,
 724				   const struct ov7740_framesize **ret_frmsize)
 725{
 726	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
 727	const struct ov7740_framesize *fsize = &ov7740_framesizes[0];
 728	int index, i;
 729
 730	for (index = 0; index < N_OV7740_FMTS; index++) {
 731		if (ov7740_formats[index].mbus_code == fmt->code)
 732			break;
 733	}
 734	if (index >= N_OV7740_FMTS) {
 735		/* default to first format */
 736		index = 0;
 737		fmt->code = ov7740_formats[0].mbus_code;
 738	}
 739	if (ret_fmt != NULL)
 740		*ret_fmt = ov7740_formats + index;
 741
 742	for (i = 0; i < ARRAY_SIZE(ov7740_framesizes); i++) {
 743		if ((fsize->width >= fmt->width) &&
 744		    (fsize->height >= fmt->height)) {
 745			fmt->width = fsize->width;
 746			fmt->height = fsize->height;
 747			break;
 748		}
 749
 750		fsize++;
 751	}
 752	if (i >= ARRAY_SIZE(ov7740_framesizes)) {
 753		fsize = &ov7740_framesizes[0];
 754		fmt->width = fsize->width;
 755		fmt->height = fsize->height;
 756	}
 757	if (ret_frmsize != NULL)
 758		*ret_frmsize = fsize;
 759
 760	fmt->field = V4L2_FIELD_NONE;
 761	fmt->colorspace = ov7740_formats[index].colorspace;
 762
 763	ov7740->format = *fmt;
 764
 765	return 0;
 766}
 767
 768static int ov7740_set_fmt(struct v4l2_subdev *sd,
 769			  struct v4l2_subdev_state *sd_state,
 770			  struct v4l2_subdev_format *format)
 771{
 772	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
 773	const struct ov7740_pixfmt *ovfmt;
 774	const struct ov7740_framesize *fsize;
 775	struct v4l2_mbus_framefmt *mbus_fmt;
 776	int ret;
 777
 778	mutex_lock(&ov7740->mutex);
 779	if (format->pad) {
 780		ret = -EINVAL;
 781		goto error;
 782	}
 783
 784	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
 785		ret = ov7740_try_fmt_internal(sd, &format->format, NULL, NULL);
 786		if (ret)
 787			goto error;
 788
 789		mbus_fmt = v4l2_subdev_state_get_format(sd_state, format->pad);
 790		*mbus_fmt = format->format;
 791		mutex_unlock(&ov7740->mutex);
 792		return 0;
 793	}
 794
 795	ret = ov7740_try_fmt_internal(sd, &format->format, &ovfmt, &fsize);
 796	if (ret)
 797		goto error;
 798
 799	ov7740->fmt = ovfmt;
 800	ov7740->frmsize = fsize;
 801
 802	mutex_unlock(&ov7740->mutex);
 803	return 0;
 804
 805error:
 806	mutex_unlock(&ov7740->mutex);
 807	return ret;
 808}
 809
 810static int ov7740_get_fmt(struct v4l2_subdev *sd,
 811			  struct v4l2_subdev_state *sd_state,
 812			  struct v4l2_subdev_format *format)
 813{
 814	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
 815	struct v4l2_mbus_framefmt *mbus_fmt;
 816
 817	mutex_lock(&ov7740->mutex);
 818	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
 819		mbus_fmt = v4l2_subdev_state_get_format(sd_state, 0);
 820		format->format = *mbus_fmt;
 821	} else {
 822		format->format = ov7740->format;
 823	}
 824	mutex_unlock(&ov7740->mutex);
 825
 826	return 0;
 827}
 828
 829static int ov7740_get_frame_interval(struct v4l2_subdev *sd,
 830				     struct v4l2_subdev_state *sd_state,
 831				     struct v4l2_subdev_frame_interval *ival)
 832{
 833	struct v4l2_fract *tpf = &ival->interval;
 834
 835	tpf->numerator = 1;
 836	tpf->denominator = 60;
 837
 838	return 0;
 839}
 840
 841static const struct v4l2_subdev_pad_ops ov7740_subdev_pad_ops = {
 842	.enum_frame_interval = ov7740_enum_frame_interval,
 843	.enum_frame_size = ov7740_enum_frame_size,
 844	.enum_mbus_code = ov7740_enum_mbus_code,
 845	.get_fmt = ov7740_get_fmt,
 846	.set_fmt = ov7740_set_fmt,
 847	.get_frame_interval = ov7740_get_frame_interval,
 848	.set_frame_interval = ov7740_get_frame_interval,
 849};
 850
 851static const struct v4l2_subdev_ops ov7740_subdev_ops = {
 852	.core	= &ov7740_subdev_core_ops,
 853	.video	= &ov7740_subdev_video_ops,
 854	.pad	= &ov7740_subdev_pad_ops,
 855};
 856
 857static void ov7740_get_default_format(struct v4l2_subdev *sd,
 858				      struct v4l2_mbus_framefmt *format)
 859{
 860	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
 861
 862	format->width = ov7740->frmsize->width;
 863	format->height = ov7740->frmsize->height;
 864	format->colorspace = ov7740->fmt->colorspace;
 865	format->code = ov7740->fmt->mbus_code;
 866	format->field = V4L2_FIELD_NONE;
 867}
 868
 869static int ov7740_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 870{
 871	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
 872	struct v4l2_mbus_framefmt *format =
 873				v4l2_subdev_state_get_format(fh->state, 0);
 874
 875	mutex_lock(&ov7740->mutex);
 876	ov7740_get_default_format(sd, format);
 877	mutex_unlock(&ov7740->mutex);
 878
 879	return 0;
 880}
 881
 882static const struct v4l2_subdev_internal_ops ov7740_subdev_internal_ops = {
 883	.open = ov7740_open,
 884};
 885
 886static int ov7740_probe_dt(struct i2c_client *client,
 887			   struct ov7740 *ov7740)
 888{
 889	ov7740->resetb_gpio = devm_gpiod_get_optional(&client->dev, "reset",
 890			GPIOD_OUT_HIGH);
 891	if (IS_ERR(ov7740->resetb_gpio)) {
 892		dev_info(&client->dev, "can't get %s GPIO\n", "reset");
 893		return PTR_ERR(ov7740->resetb_gpio);
 894	}
 895
 896	ov7740->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown",
 897			GPIOD_OUT_LOW);
 898	if (IS_ERR(ov7740->pwdn_gpio)) {
 899		dev_info(&client->dev, "can't get %s GPIO\n", "powerdown");
 900		return PTR_ERR(ov7740->pwdn_gpio);
 901	}
 902
 903	return 0;
 904}
 905
 906static int ov7740_detect(struct ov7740 *ov7740)
 907{
 908	struct regmap *regmap = ov7740->regmap;
 909	unsigned int midh, midl, pidh, pidl;
 910	int ret;
 911
 912	ret = regmap_read(regmap, REG_MIDH, &midh);
 913	if (ret)
 914		return ret;
 915	if (midh != 0x7f)
 916		return -ENODEV;
 917
 918	ret = regmap_read(regmap, REG_MIDL, &midl);
 919	if (ret)
 920		return ret;
 921	if (midl != 0xa2)
 922		return -ENODEV;
 923
 924	ret = regmap_read(regmap, REG_PIDH, &pidh);
 925	if (ret)
 926		return ret;
 927	if (pidh != 0x77)
 928		return -ENODEV;
 929
 930	ret = regmap_read(regmap, REG_PIDL, &pidl);
 931	if (ret)
 932		return ret;
 933	if ((pidl != 0x40) && (pidl != 0x41) && (pidl != 0x42))
 934		return -ENODEV;
 935
 936	return 0;
 937}
 938
 939static int ov7740_init_controls(struct ov7740 *ov7740)
 940{
 941	struct i2c_client *client = v4l2_get_subdevdata(&ov7740->subdev);
 942	struct v4l2_ctrl_handler *ctrl_hdlr = &ov7740->ctrl_handler;
 943	int ret;
 944
 945	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);
 946	if (ret < 0)
 947		return ret;
 948
 949	ctrl_hdlr->lock = &ov7740->mutex;
 950	ov7740->auto_wb = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
 951					  V4L2_CID_AUTO_WHITE_BALANCE,
 952					  0, 1, 1, 1);
 953	ov7740->blue_balance = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
 954					       V4L2_CID_BLUE_BALANCE,
 955					       0, 0xff, 1, 0x80);
 956	ov7740->red_balance = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
 957					      V4L2_CID_RED_BALANCE,
 958					      0, 0xff, 1, 0x80);
 959
 960	ov7740->brightness = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
 961					     V4L2_CID_BRIGHTNESS,
 962					     -255, 255, 1, 0);
 963	ov7740->contrast = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
 964					   V4L2_CID_CONTRAST,
 965					   0, 127, 1, 0x20);
 966	ov7740->saturation = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
 967			  V4L2_CID_SATURATION, 0, 256, 1, 0x80);
 968	ov7740->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
 969					V4L2_CID_HFLIP, 0, 1, 1, 0);
 970	ov7740->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
 971					V4L2_CID_VFLIP, 0, 1, 1, 0);
 972
 973	ov7740->gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
 974				       V4L2_CID_GAIN, 0, 1023, 1, 500);
 975
 976	ov7740->auto_gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
 977					    V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
 978
 979	ov7740->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
 980					   V4L2_CID_EXPOSURE, 0, 65535, 1, 500);
 981
 982	ov7740->auto_exposure = v4l2_ctrl_new_std_menu(ctrl_hdlr,
 983					&ov7740_ctrl_ops,
 984					V4L2_CID_EXPOSURE_AUTO,
 985					V4L2_EXPOSURE_MANUAL, 0,
 986					V4L2_EXPOSURE_AUTO);
 987
 988	v4l2_ctrl_auto_cluster(3, &ov7740->auto_wb, 0, false);
 989	v4l2_ctrl_auto_cluster(2, &ov7740->auto_gain, 0, true);
 990	v4l2_ctrl_auto_cluster(2, &ov7740->auto_exposure,
 991			       V4L2_EXPOSURE_MANUAL, true);
 992
 993	if (ctrl_hdlr->error) {
 994		ret = ctrl_hdlr->error;
 995		dev_err(&client->dev, "controls initialisation failed (%d)\n",
 996			ret);
 997		goto error;
 998	}
 999
1000	ret = v4l2_ctrl_handler_setup(ctrl_hdlr);
1001	if (ret) {
1002		dev_err(&client->dev, "%s control init failed (%d)\n",
1003			__func__, ret);
1004		goto error;
1005	}
1006
1007	ov7740->subdev.ctrl_handler = ctrl_hdlr;
1008	return 0;
1009
1010error:
1011	v4l2_ctrl_handler_free(ctrl_hdlr);
1012	mutex_destroy(&ov7740->mutex);
1013	return ret;
1014}
1015
1016static void ov7740_free_controls(struct ov7740 *ov7740)
1017{
1018	v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
1019	mutex_destroy(&ov7740->mutex);
1020}
1021
1022#define OV7740_MAX_REGISTER     0xff
1023static const struct regmap_config ov7740_regmap_config = {
1024	.reg_bits	= 8,
1025	.val_bits	= 8,
1026	.max_register	= OV7740_MAX_REGISTER,
1027};
1028
1029static int ov7740_probe(struct i2c_client *client)
1030{
1031	struct ov7740 *ov7740;
1032	struct v4l2_subdev *sd;
1033	int ret;
1034
1035	ov7740 = devm_kzalloc(&client->dev, sizeof(*ov7740), GFP_KERNEL);
1036	if (!ov7740)
1037		return -ENOMEM;
1038
1039	ov7740->xvclk = devm_v4l2_sensor_clk_get(&client->dev, "xvclk");
1040	if (IS_ERR(ov7740->xvclk))
1041		return dev_err_probe(&client->dev, PTR_ERR(ov7740->xvclk),
1042				     "OV7740: fail to get xvclk\n");
1043
1044	ret = ov7740_probe_dt(client, ov7740);
1045	if (ret)
1046		return ret;
1047
1048	ov7740->regmap = devm_regmap_init_sccb(client, &ov7740_regmap_config);
1049	if (IS_ERR(ov7740->regmap)) {
1050		ret = PTR_ERR(ov7740->regmap);
1051		dev_err(&client->dev, "Failed to allocate register map: %d\n",
1052			ret);
1053		return ret;
1054	}
1055
1056	sd = &ov7740->subdev;
1057	v4l2_i2c_subdev_init(sd, client, &ov7740_subdev_ops);
1058
1059	sd->internal_ops = &ov7740_subdev_internal_ops;
1060	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
1061
1062	ov7740->pad.flags = MEDIA_PAD_FL_SOURCE;
1063	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
1064	ret = media_entity_pads_init(&sd->entity, 1, &ov7740->pad);
1065	if (ret)
1066		return ret;
1067
1068	ret = ov7740_set_power(ov7740, 1);
1069	if (ret)
1070		return ret;
1071
1072	pm_runtime_set_active(&client->dev);
1073	pm_runtime_enable(&client->dev);
1074
1075	ret = ov7740_detect(ov7740);
1076	if (ret)
1077		goto error_detect;
1078
1079	mutex_init(&ov7740->mutex);
1080
1081	ret = ov7740_init_controls(ov7740);
1082	if (ret)
1083		goto error_init_controls;
1084
1085	v4l_info(client, "chip found @ 0x%02x (%s)\n",
1086			client->addr << 1, client->adapter->name);
1087
1088	ov7740->fmt = &ov7740_formats[0];
1089	ov7740->frmsize = &ov7740_framesizes[0];
1090
1091	ov7740_get_default_format(sd, &ov7740->format);
1092
1093	ret = v4l2_async_register_subdev(sd);
1094	if (ret)
1095		goto error_async_register;
1096
1097	pm_runtime_idle(&client->dev);
1098
1099	return 0;
1100
1101error_async_register:
1102	v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
1103error_init_controls:
1104	ov7740_free_controls(ov7740);
1105error_detect:
1106	pm_runtime_disable(&client->dev);
1107	pm_runtime_set_suspended(&client->dev);
1108	ov7740_set_power(ov7740, 0);
1109	media_entity_cleanup(&ov7740->subdev.entity);
1110
1111	return ret;
1112}
1113
1114static void ov7740_remove(struct i2c_client *client)
1115{
1116	struct v4l2_subdev *sd = i2c_get_clientdata(client);
1117	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
1118
1119	mutex_destroy(&ov7740->mutex);
1120	v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
1121	media_entity_cleanup(&ov7740->subdev.entity);
1122	v4l2_async_unregister_subdev(sd);
1123	ov7740_free_controls(ov7740);
1124
1125	pm_runtime_get_sync(&client->dev);
1126	pm_runtime_disable(&client->dev);
1127	pm_runtime_set_suspended(&client->dev);
1128	pm_runtime_put_noidle(&client->dev);
1129
1130	ov7740_set_power(ov7740, 0);
1131}
1132
1133static int __maybe_unused ov7740_runtime_suspend(struct device *dev)
1134{
1135	struct v4l2_subdev *sd = dev_get_drvdata(dev);
1136	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
1137
1138	ov7740_set_power(ov7740, 0);
1139
1140	return 0;
1141}
1142
1143static int __maybe_unused ov7740_runtime_resume(struct device *dev)
1144{
1145	struct v4l2_subdev *sd = dev_get_drvdata(dev);
1146	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
1147
1148	return ov7740_set_power(ov7740, 1);
1149}
1150
1151static const struct i2c_device_id ov7740_id[] = {
1152	{ "ov7740" },
1153	{ /* sentinel */ }
1154};
1155MODULE_DEVICE_TABLE(i2c, ov7740_id);
1156
1157static const struct dev_pm_ops ov7740_pm_ops = {
1158	SET_RUNTIME_PM_OPS(ov7740_runtime_suspend, ov7740_runtime_resume, NULL)
1159};
1160
1161static const struct of_device_id ov7740_of_match[] = {
1162	{.compatible = "ovti,ov7740", },
1163	{ /* sentinel */ },
1164};
1165MODULE_DEVICE_TABLE(of, ov7740_of_match);
1166
1167static struct i2c_driver ov7740_i2c_driver = {
1168	.driver = {
1169		.name = "ov7740",
1170		.pm = &ov7740_pm_ops,
1171		.of_match_table = ov7740_of_match,
1172	},
1173	.probe    = ov7740_probe,
1174	.remove   = ov7740_remove,
1175	.id_table = ov7740_id,
1176};
1177module_i2c_driver(ov7740_i2c_driver);
1178
1179MODULE_DESCRIPTION("The V4L2 driver for Omnivision 7740 sensor");
1180MODULE_AUTHOR("Songjun Wu <songjun.wu@atmel.com>");
1181MODULE_LICENSE("GPL v2");
~/ Read-only file preview.