brintos

brintos / linux-shallow public Read only

0
0
Text · 28.0 KiB · 78d5d40 Raw
1233 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (c) 2022 Intel Corporation.3 4#include <linux/unaligned.h>5#include <linux/acpi.h>6#include <linux/clk.h>7#include <linux/delay.h>8#include <linux/gpio/consumer.h>9#include <linux/i2c.h>10#include <linux/module.h>11#include <linux/pm_runtime.h>12#include <linux/regulator/consumer.h>13#include <media/v4l2-ctrls.h>14#include <media/v4l2-device.h>15#include <media/v4l2-fwnode.h>16 17#define OG01A1B_REG_VALUE_08BIT		118#define OG01A1B_REG_VALUE_16BIT		219#define OG01A1B_REG_VALUE_24BIT		320 21#define OG01A1B_LINK_FREQ_500MHZ	500000000ULL22#define OG01A1B_SCLK			120000000LL23#define OG01A1B_MCLK			1920000024#define OG01A1B_DATA_LANES		225#define OG01A1B_RGB_DEPTH		1026 27#define OG01A1B_REG_CHIP_ID		0x300a28#define OG01A1B_CHIP_ID			0x47014129 30#define OG01A1B_REG_MODE_SELECT		0x010031#define OG01A1B_MODE_STANDBY		0x0032#define OG01A1B_MODE_STREAMING		0x0133 34/* vertical-timings from sensor */35#define OG01A1B_REG_VTS			0x380e36#define OG01A1B_VTS_120FPS		0x049837#define OG01A1B_VTS_120FPS_MIN		0x049838#define OG01A1B_VTS_MAX			0x7fff39 40/* horizontal-timings from sensor */41#define OG01A1B_REG_HTS			0x380c42 43/* Exposure controls from sensor */44#define OG01A1B_REG_EXPOSURE		0x350145#define	OG01A1B_EXPOSURE_MIN		146#define OG01A1B_EXPOSURE_MAX_MARGIN	1447#define	OG01A1B_EXPOSURE_STEP		148 49/* Analog gain controls from sensor */50#define OG01A1B_REG_ANALOG_GAIN		0x350851#define	OG01A1B_ANAL_GAIN_MIN		1652#define	OG01A1B_ANAL_GAIN_MAX		248 /* Max = 15.5x */53#define	OG01A1B_ANAL_GAIN_STEP		154 55/* Digital gain controls from sensor */56#define OG01A1B_REG_DIG_GAIN		0x350a57#define OG01A1B_DGTL_GAIN_MIN		102458#define OG01A1B_DGTL_GAIN_MAX		16384 /* Max = 16x */59#define OG01A1B_DGTL_GAIN_STEP		160#define OG01A1B_DGTL_GAIN_DEFAULT	102461 62/* Group Access */63#define OG01A1B_REG_GROUP_ACCESS	0x320864#define OG01A1B_GROUP_HOLD_START	0x065#define OG01A1B_GROUP_HOLD_END		0x1066#define OG01A1B_GROUP_HOLD_LAUNCH	0xa067 68/* Test Pattern Control */69#define OG01A1B_REG_TEST_PATTERN	0x510070#define OG01A1B_TEST_PATTERN_ENABLE	BIT(7)71#define OG01A1B_TEST_PATTERN_BAR_SHIFT	272 73#define to_og01a1b(_sd)			container_of(_sd, struct og01a1b, sd)74 75enum {76	OG01A1B_LINK_FREQ_1000MBPS,77};78 79struct og01a1b_reg {80	u16 address;81	u8 val;82};83 84struct og01a1b_reg_list {85	u32 num_of_regs;86	const struct og01a1b_reg *regs;87};88 89struct og01a1b_link_freq_config {90	const struct og01a1b_reg_list reg_list;91};92 93struct og01a1b_mode {94	/* Frame width in pixels */95	u32 width;96 97	/* Frame height in pixels */98	u32 height;99 100	/* Horizontal timining size */101	u32 hts;102 103	/* Default vertical timining size */104	u32 vts_def;105 106	/* Min vertical timining size */107	u32 vts_min;108 109	/* Link frequency needed for this resolution */110	u32 link_freq_index;111 112	/* Sensor register settings for this resolution */113	const struct og01a1b_reg_list reg_list;114};115 116static const struct og01a1b_reg mipi_data_rate_1000mbps[] = {117	{0x0103, 0x01},118	{0x0303, 0x02},119	{0x0304, 0x00},120	{0x0305, 0xd2},121	{0x0323, 0x02},122	{0x0324, 0x01},123	{0x0325, 0x77},124};125 126static const struct og01a1b_reg mode_1280x1024_regs[] = {127	{0x0300, 0x0a},128	{0x0301, 0x29},129	{0x0302, 0x31},130	{0x0303, 0x02},131	{0x0304, 0x00},132	{0x0305, 0xd2},133	{0x0306, 0x00},134	{0x0307, 0x01},135	{0x0308, 0x02},136	{0x0309, 0x00},137	{0x0310, 0x00},138	{0x0311, 0x00},139	{0x0312, 0x07},140	{0x0313, 0x00},141	{0x0314, 0x00},142	{0x0315, 0x00},143	{0x0320, 0x02},144	{0x0321, 0x01},145	{0x0322, 0x01},146	{0x0323, 0x02},147	{0x0324, 0x01},148	{0x0325, 0x77},149	{0x0326, 0xce},150	{0x0327, 0x04},151	{0x0329, 0x02},152	{0x032a, 0x04},153	{0x032b, 0x04},154	{0x032c, 0x02},155	{0x032d, 0x01},156	{0x032e, 0x00},157	{0x300d, 0x02},158	{0x300e, 0x04},159	{0x3021, 0x08},160	{0x301e, 0x03},161	{0x3103, 0x00},162	{0x3106, 0x08},163	{0x3107, 0x40},164	{0x3216, 0x01},165	{0x3217, 0x00},166	{0x3218, 0xc0},167	{0x3219, 0x55},168	{0x3500, 0x00},169	{0x3501, 0x04},170	{0x3502, 0x8a},171	{0x3506, 0x01},172	{0x3507, 0x72},173	{0x3508, 0x01},174	{0x3509, 0x00},175	{0x350a, 0x01},176	{0x350b, 0x00},177	{0x350c, 0x00},178	{0x3541, 0x00},179	{0x3542, 0x40},180	{0x3605, 0xe0},181	{0x3606, 0x41},182	{0x3614, 0x20},183	{0x3620, 0x0b},184	{0x3630, 0x07},185	{0x3636, 0xa0},186	{0x3637, 0xf9},187	{0x3638, 0x09},188	{0x3639, 0x38},189	{0x363f, 0x09},190	{0x3640, 0x17},191	{0x3662, 0x04},192	{0x3665, 0x80},193	{0x3670, 0x68},194	{0x3674, 0x00},195	{0x3677, 0x3f},196	{0x3679, 0x00},197	{0x369f, 0x19},198	{0x36a0, 0x03},199	{0x36a2, 0x19},200	{0x36a3, 0x03},201	{0x370d, 0x66},202	{0x370f, 0x00},203	{0x3710, 0x03},204	{0x3715, 0x03},205	{0x3716, 0x03},206	{0x3717, 0x06},207	{0x3733, 0x00},208	{0x3778, 0x00},209	{0x37a8, 0x0f},210	{0x37a9, 0x01},211	{0x37aa, 0x07},212	{0x37bd, 0x1c},213	{0x37c1, 0x2f},214	{0x37c3, 0x09},215	{0x37c8, 0x1d},216	{0x37ca, 0x30},217	{0x37df, 0x00},218	{0x3800, 0x00},219	{0x3801, 0x00},220	{0x3802, 0x00},221	{0x3803, 0x00},222	{0x3804, 0x05},223	{0x3805, 0x0f},224	{0x3806, 0x04},225	{0x3807, 0x0f},226	{0x3808, 0x05},227	{0x3809, 0x00},228	{0x380a, 0x04},229	{0x380b, 0x00},230	{0x380c, 0x03},231	{0x380d, 0x50},232	{0x380e, 0x04},233	{0x380f, 0x98},234	{0x3810, 0x00},235	{0x3811, 0x08},236	{0x3812, 0x00},237	{0x3813, 0x08},238	{0x3814, 0x11},239	{0x3815, 0x11},240	{0x3820, 0x40},241	{0x3821, 0x04},242	{0x3826, 0x00},243	{0x3827, 0x00},244	{0x382a, 0x08},245	{0x382b, 0x52},246	{0x382d, 0xba},247	{0x383d, 0x14},248	{0x384a, 0xa2},249	{0x3866, 0x0e},250	{0x3867, 0x07},251	{0x3884, 0x00},252	{0x3885, 0x08},253	{0x3893, 0x68},254	{0x3894, 0x2a},255	{0x3898, 0x00},256	{0x3899, 0x31},257	{0x389a, 0x04},258	{0x389b, 0x00},259	{0x389c, 0x0b},260	{0x389d, 0xad},261	{0x389f, 0x08},262	{0x38a0, 0x00},263	{0x38a1, 0x00},264	{0x38a8, 0x70},265	{0x38ac, 0xea},266	{0x38b2, 0x00},267	{0x38b3, 0x08},268	{0x38bc, 0x20},269	{0x38c4, 0x0c},270	{0x38c5, 0x3a},271	{0x38c7, 0x3a},272	{0x38e1, 0xc0},273	{0x38ec, 0x3c},274	{0x38f0, 0x09},275	{0x38f1, 0x6f},276	{0x38fe, 0x3c},277	{0x391e, 0x00},278	{0x391f, 0x00},279	{0x3920, 0xa5},280	{0x3921, 0x00},281	{0x3922, 0x00},282	{0x3923, 0x00},283	{0x3924, 0x05},284	{0x3925, 0x00},285	{0x3926, 0x00},286	{0x3927, 0x00},287	{0x3928, 0x1a},288	{0x3929, 0x01},289	{0x392a, 0xb4},290	{0x392b, 0x00},291	{0x392c, 0x10},292	{0x392f, 0x40},293	{0x4000, 0xcf},294	{0x4003, 0x40},295	{0x4008, 0x00},296	{0x4009, 0x07},297	{0x400a, 0x02},298	{0x400b, 0x54},299	{0x400c, 0x00},300	{0x400d, 0x07},301	{0x4010, 0xc0},302	{0x4012, 0x02},303	{0x4014, 0x04},304	{0x4015, 0x04},305	{0x4017, 0x02},306	{0x4042, 0x01},307	{0x4306, 0x04},308	{0x4307, 0x12},309	{0x4509, 0x00},310	{0x450b, 0x83},311	{0x4604, 0x68},312	{0x4608, 0x0a},313	{0x4700, 0x06},314	{0x4800, 0x64},315	{0x481b, 0x3c},316	{0x4825, 0x32},317	{0x4833, 0x18},318	{0x4837, 0x0f},319	{0x4850, 0x40},320	{0x4860, 0x00},321	{0x4861, 0xec},322	{0x4864, 0x00},323	{0x4883, 0x00},324	{0x4888, 0x90},325	{0x4889, 0x05},326	{0x488b, 0x04},327	{0x4f00, 0x04},328	{0x4f10, 0x04},329	{0x4f21, 0x01},330	{0x4f22, 0x40},331	{0x4f23, 0x44},332	{0x4f24, 0x51},333	{0x4f25, 0x41},334	{0x5000, 0x1f},335	{0x500a, 0x00},336	{0x5100, 0x00},337	{0x5111, 0x20},338	{0x3020, 0x20},339	{0x3613, 0x03},340	{0x38c9, 0x02},341	{0x5304, 0x01},342	{0x3620, 0x08},343	{0x3639, 0x58},344	{0x363a, 0x10},345	{0x3674, 0x04},346	{0x3780, 0xff},347	{0x3781, 0xff},348	{0x3782, 0x00},349	{0x3783, 0x01},350	{0x3798, 0xa3},351	{0x37aa, 0x10},352	{0x38a8, 0xf0},353	{0x38c4, 0x09},354	{0x38c5, 0xb0},355	{0x38df, 0x80},356	{0x38ff, 0x05},357	{0x4010, 0xf1},358	{0x4011, 0x70},359	{0x3667, 0x80},360	{0x4d00, 0x4a},361	{0x4d01, 0x18},362	{0x4d02, 0xbb},363	{0x4d03, 0xde},364	{0x4d04, 0x93},365	{0x4d05, 0xff},366	{0x4d09, 0x0a},367	{0x37aa, 0x16},368	{0x3606, 0x42},369	{0x3605, 0x00},370	{0x36a2, 0x17},371	{0x300d, 0x0a},372	{0x4d00, 0x4d},373	{0x4d01, 0x95},374	{0x3d8C, 0x70},375	{0x3d8d, 0xE9},376	{0x5300, 0x00},377	{0x5301, 0x10},378	{0x5302, 0x00},379	{0x5303, 0xE3},380	{0x3d88, 0x00},381	{0x3d89, 0x10},382	{0x3d8a, 0x00},383	{0x3d8b, 0xE3},384	{0x4f22, 0x00},385};386 387static const char * const og01a1b_test_pattern_menu[] = {388	"Disabled",389	"Standard Color Bar",390	"Top-Bottom Darker Color Bar",391	"Right-Left Darker Color Bar",392	"Bottom-Top Darker Color Bar"393};394 395static const s64 link_freq_menu_items[] = {396	OG01A1B_LINK_FREQ_500MHZ,397};398 399static const struct og01a1b_link_freq_config link_freq_configs[] = {400	[OG01A1B_LINK_FREQ_1000MBPS] = {401		.reg_list = {402			.num_of_regs = ARRAY_SIZE(mipi_data_rate_1000mbps),403			.regs = mipi_data_rate_1000mbps,404		}405	}406};407 408static const struct og01a1b_mode supported_modes[] = {409	{410		.width = 1280,411		.height = 1024,412		.hts = 848,413		.vts_def = OG01A1B_VTS_120FPS,414		.vts_min = OG01A1B_VTS_120FPS_MIN,415		.reg_list = {416			.num_of_regs = ARRAY_SIZE(mode_1280x1024_regs),417			.regs = mode_1280x1024_regs,418		},419		.link_freq_index = OG01A1B_LINK_FREQ_1000MBPS,420	},421};422 423struct og01a1b {424	struct clk *xvclk;425	struct gpio_desc *reset_gpio;426	struct regulator *avdd;427	struct regulator *dovdd;428	struct regulator *dvdd;429 430	struct v4l2_subdev sd;431	struct media_pad pad;432	struct v4l2_ctrl_handler ctrl_handler;433 434	/* V4L2 Controls */435	struct v4l2_ctrl *link_freq;436	struct v4l2_ctrl *pixel_rate;437	struct v4l2_ctrl *vblank;438	struct v4l2_ctrl *hblank;439	struct v4l2_ctrl *exposure;440 441	/* Current mode */442	const struct og01a1b_mode *cur_mode;443 444	/* To serialize asynchronus callbacks */445	struct mutex mutex;446};447 448static u64 to_pixel_rate(u32 f_index)449{450	u64 pixel_rate = link_freq_menu_items[f_index] * 2 * OG01A1B_DATA_LANES;451 452	do_div(pixel_rate, OG01A1B_RGB_DEPTH);453 454	return pixel_rate;455}456 457static u64 to_pixels_per_line(u32 hts, u32 f_index)458{459	u64 ppl = hts * to_pixel_rate(f_index);460 461	do_div(ppl, OG01A1B_SCLK);462 463	return ppl;464}465 466static int og01a1b_read_reg(struct og01a1b *og01a1b, u16 reg, u16 len, u32 *val)467{468	struct i2c_client *client = v4l2_get_subdevdata(&og01a1b->sd);469	struct i2c_msg msgs[2];470	u8 addr_buf[2];471	u8 data_buf[4] = {0};472	int ret;473 474	if (len > 4)475		return -EINVAL;476 477	put_unaligned_be16(reg, addr_buf);478	msgs[0].addr = client->addr;479	msgs[0].flags = 0;480	msgs[0].len = sizeof(addr_buf);481	msgs[0].buf = addr_buf;482	msgs[1].addr = client->addr;483	msgs[1].flags = I2C_M_RD;484	msgs[1].len = len;485	msgs[1].buf = &data_buf[4 - len];486 487	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));488	if (ret != ARRAY_SIZE(msgs))489		return -EIO;490 491	*val = get_unaligned_be32(data_buf);492 493	return 0;494}495 496static int og01a1b_write_reg(struct og01a1b *og01a1b, u16 reg, u16 len, u32 val)497{498	struct i2c_client *client = v4l2_get_subdevdata(&og01a1b->sd);499	u8 buf[6];500 501	if (len > 4)502		return -EINVAL;503 504	put_unaligned_be16(reg, buf);505	put_unaligned_be32(val << 8 * (4 - len), buf + 2);506	if (i2c_master_send(client, buf, len + 2) != len + 2)507		return -EIO;508 509	return 0;510}511 512static int og01a1b_write_reg_list(struct og01a1b *og01a1b,513				  const struct og01a1b_reg_list *r_list)514{515	struct i2c_client *client = v4l2_get_subdevdata(&og01a1b->sd);516	unsigned int i;517	int ret;518 519	for (i = 0; i < r_list->num_of_regs; i++) {520		ret = og01a1b_write_reg(og01a1b, r_list->regs[i].address, 1,521					r_list->regs[i].val);522		if (ret) {523			dev_err_ratelimited(&client->dev,524					    "failed to write reg 0x%4.4x. error = %d",525					    r_list->regs[i].address, ret);526			return ret;527		}528	}529 530	return 0;531}532 533static int og01a1b_test_pattern(struct og01a1b *og01a1b, u32 pattern)534{535	if (pattern)536		pattern = (pattern - 1) << OG01A1B_TEST_PATTERN_BAR_SHIFT |537			  OG01A1B_TEST_PATTERN_ENABLE;538 539	return og01a1b_write_reg(og01a1b, OG01A1B_REG_TEST_PATTERN,540				 OG01A1B_REG_VALUE_08BIT, pattern);541}542 543static int og01a1b_set_ctrl(struct v4l2_ctrl *ctrl)544{545	struct og01a1b *og01a1b = container_of(ctrl->handler,546					       struct og01a1b, ctrl_handler);547	struct i2c_client *client = v4l2_get_subdevdata(&og01a1b->sd);548	s64 exposure_max;549	int ret = 0;550 551	/* Propagate change of current control to all related controls */552	if (ctrl->id == V4L2_CID_VBLANK) {553		/* Update max exposure while meeting expected vblanking */554		exposure_max = og01a1b->cur_mode->height + ctrl->val -555			       OG01A1B_EXPOSURE_MAX_MARGIN;556		__v4l2_ctrl_modify_range(og01a1b->exposure,557					 og01a1b->exposure->minimum,558					 exposure_max, og01a1b->exposure->step,559					 exposure_max);560	}561 562	/* V4L2 controls values will be applied only when power is already up */563	if (!pm_runtime_get_if_in_use(&client->dev))564		return 0;565 566	switch (ctrl->id) {567	case V4L2_CID_ANALOGUE_GAIN:568		ret = og01a1b_write_reg(og01a1b, OG01A1B_REG_ANALOG_GAIN,569					OG01A1B_REG_VALUE_16BIT,570					ctrl->val << 4);571		break;572 573	case V4L2_CID_DIGITAL_GAIN:574		ret = og01a1b_write_reg(og01a1b, OG01A1B_REG_DIG_GAIN,575					OG01A1B_REG_VALUE_24BIT,576					ctrl->val << 6);577		break;578 579	case V4L2_CID_EXPOSURE:580		ret = og01a1b_write_reg(og01a1b, OG01A1B_REG_EXPOSURE,581					OG01A1B_REG_VALUE_16BIT, ctrl->val);582		break;583 584	case V4L2_CID_VBLANK:585		ret = og01a1b_write_reg(og01a1b, OG01A1B_REG_VTS,586					OG01A1B_REG_VALUE_16BIT,587					og01a1b->cur_mode->height + ctrl->val);588		break;589 590	case V4L2_CID_TEST_PATTERN:591		ret = og01a1b_test_pattern(og01a1b, ctrl->val);592		break;593 594	default:595		ret = -EINVAL;596		break;597	}598 599	pm_runtime_put(&client->dev);600 601	return ret;602}603 604static const struct v4l2_ctrl_ops og01a1b_ctrl_ops = {605	.s_ctrl = og01a1b_set_ctrl,606};607 608static int og01a1b_init_controls(struct og01a1b *og01a1b)609{610	struct v4l2_ctrl_handler *ctrl_hdlr;611	s64 exposure_max, h_blank;612	int ret;613 614	ctrl_hdlr = &og01a1b->ctrl_handler;615	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8);616	if (ret)617		return ret;618 619	ctrl_hdlr->lock = &og01a1b->mutex;620	og01a1b->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,621						    &og01a1b_ctrl_ops,622						    V4L2_CID_LINK_FREQ,623						    ARRAY_SIZE624						    (link_freq_menu_items) - 1,625						    0, link_freq_menu_items);626	if (og01a1b->link_freq)627		og01a1b->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;628 629	og01a1b->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &og01a1b_ctrl_ops,630						V4L2_CID_PIXEL_RATE, 0,631						to_pixel_rate632						(OG01A1B_LINK_FREQ_1000MBPS),633						1,634						to_pixel_rate635						(OG01A1B_LINK_FREQ_1000MBPS));636	og01a1b->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &og01a1b_ctrl_ops,637					    V4L2_CID_VBLANK,638					    og01a1b->cur_mode->vts_min -639					    og01a1b->cur_mode->height,640					    OG01A1B_VTS_MAX -641					    og01a1b->cur_mode->height, 1,642					    og01a1b->cur_mode->vts_def -643					    og01a1b->cur_mode->height);644	h_blank = to_pixels_per_line(og01a1b->cur_mode->hts,645				     og01a1b->cur_mode->link_freq_index) -646				     og01a1b->cur_mode->width;647	og01a1b->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &og01a1b_ctrl_ops,648					    V4L2_CID_HBLANK, h_blank, h_blank,649					    1, h_blank);650	if (og01a1b->hblank)651		og01a1b->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;652 653	v4l2_ctrl_new_std(ctrl_hdlr, &og01a1b_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,654			  OG01A1B_ANAL_GAIN_MIN, OG01A1B_ANAL_GAIN_MAX,655			  OG01A1B_ANAL_GAIN_STEP, OG01A1B_ANAL_GAIN_MIN);656	v4l2_ctrl_new_std(ctrl_hdlr, &og01a1b_ctrl_ops, V4L2_CID_DIGITAL_GAIN,657			  OG01A1B_DGTL_GAIN_MIN, OG01A1B_DGTL_GAIN_MAX,658			  OG01A1B_DGTL_GAIN_STEP, OG01A1B_DGTL_GAIN_DEFAULT);659	exposure_max = (og01a1b->cur_mode->vts_def -660			OG01A1B_EXPOSURE_MAX_MARGIN);661	og01a1b->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &og01a1b_ctrl_ops,662					      V4L2_CID_EXPOSURE,663					      OG01A1B_EXPOSURE_MIN,664					      exposure_max,665					      OG01A1B_EXPOSURE_STEP,666					      exposure_max);667	v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &og01a1b_ctrl_ops,668				     V4L2_CID_TEST_PATTERN,669				     ARRAY_SIZE(og01a1b_test_pattern_menu) - 1,670				     0, 0, og01a1b_test_pattern_menu);671 672	if (ctrl_hdlr->error)673		return ctrl_hdlr->error;674 675	og01a1b->sd.ctrl_handler = ctrl_hdlr;676 677	return 0;678}679 680static void og01a1b_update_pad_format(const struct og01a1b_mode *mode,681				      struct v4l2_mbus_framefmt *fmt)682{683	fmt->width = mode->width;684	fmt->height = mode->height;685	fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;686	fmt->field = V4L2_FIELD_NONE;687}688 689static int og01a1b_start_streaming(struct og01a1b *og01a1b)690{691	struct i2c_client *client = v4l2_get_subdevdata(&og01a1b->sd);692	const struct og01a1b_reg_list *reg_list;693	int link_freq_index, ret;694 695	link_freq_index = og01a1b->cur_mode->link_freq_index;696	reg_list = &link_freq_configs[link_freq_index].reg_list;697 698	ret = og01a1b_write_reg_list(og01a1b, reg_list);699	if (ret) {700		dev_err(&client->dev, "failed to set plls");701		return ret;702	}703 704	reg_list = &og01a1b->cur_mode->reg_list;705	ret = og01a1b_write_reg_list(og01a1b, reg_list);706	if (ret) {707		dev_err(&client->dev, "failed to set mode");708		return ret;709	}710 711	ret = __v4l2_ctrl_handler_setup(og01a1b->sd.ctrl_handler);712	if (ret)713		return ret;714 715	ret = og01a1b_write_reg(og01a1b, OG01A1B_REG_MODE_SELECT,716				OG01A1B_REG_VALUE_08BIT,717				OG01A1B_MODE_STREAMING);718	if (ret) {719		dev_err(&client->dev, "failed to set stream");720		return ret;721	}722 723	return 0;724}725 726static void og01a1b_stop_streaming(struct og01a1b *og01a1b)727{728	struct i2c_client *client = v4l2_get_subdevdata(&og01a1b->sd);729 730	if (og01a1b_write_reg(og01a1b, OG01A1B_REG_MODE_SELECT,731			      OG01A1B_REG_VALUE_08BIT, OG01A1B_MODE_STANDBY))732		dev_err(&client->dev, "failed to set stream");733}734 735static int og01a1b_set_stream(struct v4l2_subdev *sd, int enable)736{737	struct og01a1b *og01a1b = to_og01a1b(sd);738	struct i2c_client *client = v4l2_get_subdevdata(sd);739	int ret = 0;740 741	mutex_lock(&og01a1b->mutex);742	if (enable) {743		ret = pm_runtime_resume_and_get(&client->dev);744		if (ret) {745			mutex_unlock(&og01a1b->mutex);746			return ret;747		}748 749		ret = og01a1b_start_streaming(og01a1b);750		if (ret) {751			enable = 0;752			og01a1b_stop_streaming(og01a1b);753			pm_runtime_put(&client->dev);754		}755	} else {756		og01a1b_stop_streaming(og01a1b);757		pm_runtime_put(&client->dev);758	}759 760	mutex_unlock(&og01a1b->mutex);761 762	return ret;763}764 765static int og01a1b_set_format(struct v4l2_subdev *sd,766			      struct v4l2_subdev_state *sd_state,767			      struct v4l2_subdev_format *fmt)768{769	struct og01a1b *og01a1b = to_og01a1b(sd);770	const struct og01a1b_mode *mode;771	s32 vblank_def, h_blank;772 773	mode = v4l2_find_nearest_size(supported_modes,774				      ARRAY_SIZE(supported_modes), width,775				      height, fmt->format.width,776				      fmt->format.height);777 778	mutex_lock(&og01a1b->mutex);779	og01a1b_update_pad_format(mode, &fmt->format);780	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {781		*v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format;782	} else {783		og01a1b->cur_mode = mode;784		__v4l2_ctrl_s_ctrl(og01a1b->link_freq, mode->link_freq_index);785		__v4l2_ctrl_s_ctrl_int64(og01a1b->pixel_rate,786					 to_pixel_rate(mode->link_freq_index));787 788		/* Update limits and set FPS to default */789		vblank_def = mode->vts_def - mode->height;790		__v4l2_ctrl_modify_range(og01a1b->vblank,791					 mode->vts_min - mode->height,792					 OG01A1B_VTS_MAX - mode->height, 1,793					 vblank_def);794		__v4l2_ctrl_s_ctrl(og01a1b->vblank, vblank_def);795		h_blank = to_pixels_per_line(mode->hts, mode->link_freq_index) -796			  mode->width;797		__v4l2_ctrl_modify_range(og01a1b->hblank, h_blank, h_blank, 1,798					 h_blank);799	}800 801	mutex_unlock(&og01a1b->mutex);802 803	return 0;804}805 806static int og01a1b_get_format(struct v4l2_subdev *sd,807			      struct v4l2_subdev_state *sd_state,808			      struct v4l2_subdev_format *fmt)809{810	struct og01a1b *og01a1b = to_og01a1b(sd);811 812	mutex_lock(&og01a1b->mutex);813	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)814		fmt->format = *v4l2_subdev_state_get_format(sd_state,815							    fmt->pad);816	else817		og01a1b_update_pad_format(og01a1b->cur_mode, &fmt->format);818 819	mutex_unlock(&og01a1b->mutex);820 821	return 0;822}823 824static int og01a1b_enum_mbus_code(struct v4l2_subdev *sd,825				  struct v4l2_subdev_state *sd_state,826				  struct v4l2_subdev_mbus_code_enum *code)827{828	if (code->index > 0)829		return -EINVAL;830 831	code->code = MEDIA_BUS_FMT_SGRBG10_1X10;832 833	return 0;834}835 836static int og01a1b_enum_frame_size(struct v4l2_subdev *sd,837				   struct v4l2_subdev_state *sd_state,838				   struct v4l2_subdev_frame_size_enum *fse)839{840	if (fse->index >= ARRAY_SIZE(supported_modes))841		return -EINVAL;842 843	if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)844		return -EINVAL;845 846	fse->min_width = supported_modes[fse->index].width;847	fse->max_width = fse->min_width;848	fse->min_height = supported_modes[fse->index].height;849	fse->max_height = fse->min_height;850 851	return 0;852}853 854static int og01a1b_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)855{856	struct og01a1b *og01a1b = to_og01a1b(sd);857 858	mutex_lock(&og01a1b->mutex);859	og01a1b_update_pad_format(&supported_modes[0],860				  v4l2_subdev_state_get_format(fh->state, 0));861	mutex_unlock(&og01a1b->mutex);862 863	return 0;864}865 866static const struct v4l2_subdev_video_ops og01a1b_video_ops = {867	.s_stream = og01a1b_set_stream,868};869 870static const struct v4l2_subdev_pad_ops og01a1b_pad_ops = {871	.set_fmt = og01a1b_set_format,872	.get_fmt = og01a1b_get_format,873	.enum_mbus_code = og01a1b_enum_mbus_code,874	.enum_frame_size = og01a1b_enum_frame_size,875};876 877static const struct v4l2_subdev_ops og01a1b_subdev_ops = {878	.video = &og01a1b_video_ops,879	.pad = &og01a1b_pad_ops,880};881 882static const struct media_entity_operations og01a1b_subdev_entity_ops = {883	.link_validate = v4l2_subdev_link_validate,884};885 886static const struct v4l2_subdev_internal_ops og01a1b_internal_ops = {887	.open = og01a1b_open,888};889 890static int og01a1b_identify_module(struct og01a1b *og01a1b)891{892	struct i2c_client *client = v4l2_get_subdevdata(&og01a1b->sd);893	int ret;894	u32 val;895 896	ret = og01a1b_read_reg(og01a1b, OG01A1B_REG_CHIP_ID,897			       OG01A1B_REG_VALUE_24BIT, &val);898	if (ret)899		return ret;900 901	if (val != OG01A1B_CHIP_ID) {902		dev_err(&client->dev, "chip id mismatch: %x!=%x",903			OG01A1B_CHIP_ID, val);904		return -ENXIO;905	}906 907	return 0;908}909 910static int og01a1b_check_hwcfg(struct og01a1b *og01a1b)911{912	struct i2c_client *client = v4l2_get_subdevdata(&og01a1b->sd);913	struct device *dev = &client->dev;914	struct fwnode_handle *ep;915	struct fwnode_handle *fwnode = dev_fwnode(dev);916	struct v4l2_fwnode_endpoint bus_cfg = {917		.bus_type = V4L2_MBUS_CSI2_DPHY918	};919	u32 mclk;920	int ret;921	unsigned int i, j;922 923	if (!fwnode)924		return -ENXIO;925 926	ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk);927	if (ret) {928		if (!og01a1b->xvclk) {929			dev_err(dev, "can't get clock frequency");930			return ret;931		}932 933		mclk = clk_get_rate(og01a1b->xvclk);934	}935 936	if (mclk != OG01A1B_MCLK) {937		dev_err(dev, "external clock %d is not supported", mclk);938		return -EINVAL;939	}940 941	ep = fwnode_graph_get_next_endpoint(fwnode, NULL);942	if (!ep)943		return -ENXIO;944 945	ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);946	fwnode_handle_put(ep);947	if (ret)948		return ret;949 950	if (bus_cfg.bus.mipi_csi2.num_data_lanes != OG01A1B_DATA_LANES) {951		dev_err(dev, "number of CSI2 data lanes %d is not supported",952			bus_cfg.bus.mipi_csi2.num_data_lanes);953		ret = -EINVAL;954		goto check_hwcfg_error;955	}956 957	if (!bus_cfg.nr_of_link_frequencies) {958		dev_err(dev, "no link frequencies defined");959		ret = -EINVAL;960		goto check_hwcfg_error;961	}962 963	for (i = 0; i < ARRAY_SIZE(link_freq_menu_items); i++) {964		for (j = 0; j < bus_cfg.nr_of_link_frequencies; j++) {965			if (link_freq_menu_items[i] ==966				bus_cfg.link_frequencies[j])967				break;968		}969 970		if (j == bus_cfg.nr_of_link_frequencies) {971			dev_err(dev, "no link frequency %lld supported",972				link_freq_menu_items[i]);973			ret = -EINVAL;974			goto check_hwcfg_error;975		}976	}977 978check_hwcfg_error:979	v4l2_fwnode_endpoint_free(&bus_cfg);980 981	return ret;982}983 984/* Power/clock management functions */985static int og01a1b_power_on(struct device *dev)986{987	unsigned long delay = DIV_ROUND_UP(8192UL * USEC_PER_SEC, OG01A1B_MCLK);988	struct v4l2_subdev *sd = dev_get_drvdata(dev);989	struct og01a1b *og01a1b = to_og01a1b(sd);990	int ret;991 992	if (og01a1b->avdd) {993		ret = regulator_enable(og01a1b->avdd);994		if (ret)995			return ret;996	}997 998	if (og01a1b->dovdd) {999		ret = regulator_enable(og01a1b->dovdd);1000		if (ret)1001			goto avdd_disable;1002	}1003 1004	if (og01a1b->dvdd) {1005		ret = regulator_enable(og01a1b->dvdd);1006		if (ret)1007			goto dovdd_disable;1008	}1009 1010	ret = clk_prepare_enable(og01a1b->xvclk);1011	if (ret)1012		goto dvdd_disable;1013 1014	gpiod_set_value_cansleep(og01a1b->reset_gpio, 0);1015 1016	if (og01a1b->reset_gpio)1017		usleep_range(5 * USEC_PER_MSEC, 6 * USEC_PER_MSEC);1018	else if (og01a1b->xvclk)1019		usleep_range(delay, 2 * delay);1020 1021	return 0;1022 1023dvdd_disable:1024	if (og01a1b->dvdd)1025		regulator_disable(og01a1b->dvdd);1026dovdd_disable:1027	if (og01a1b->dovdd)1028		regulator_disable(og01a1b->dovdd);1029avdd_disable:1030	if (og01a1b->avdd)1031		regulator_disable(og01a1b->avdd);1032 1033	return ret;1034}1035 1036static int og01a1b_power_off(struct device *dev)1037{1038	unsigned long delay = DIV_ROUND_UP(512 * USEC_PER_SEC, OG01A1B_MCLK);1039	struct v4l2_subdev *sd = dev_get_drvdata(dev);1040	struct og01a1b *og01a1b = to_og01a1b(sd);1041 1042	if (og01a1b->xvclk)1043		usleep_range(delay, 2 * delay);1044 1045	clk_disable_unprepare(og01a1b->xvclk);1046 1047	gpiod_set_value_cansleep(og01a1b->reset_gpio, 1);1048 1049	if (og01a1b->dvdd)1050		regulator_disable(og01a1b->dvdd);1051 1052	if (og01a1b->dovdd)1053		regulator_disable(og01a1b->dovdd);1054 1055	if (og01a1b->avdd)1056		regulator_disable(og01a1b->avdd);1057 1058	return 0;1059}1060 1061static void og01a1b_remove(struct i2c_client *client)1062{1063	struct v4l2_subdev *sd = i2c_get_clientdata(client);1064	struct og01a1b *og01a1b = to_og01a1b(sd);1065 1066	v4l2_async_unregister_subdev(sd);1067	media_entity_cleanup(&sd->entity);1068	v4l2_ctrl_handler_free(sd->ctrl_handler);1069	pm_runtime_disable(&client->dev);1070	mutex_destroy(&og01a1b->mutex);1071}1072 1073static int og01a1b_probe(struct i2c_client *client)1074{1075	struct og01a1b *og01a1b;1076	int ret;1077 1078	og01a1b = devm_kzalloc(&client->dev, sizeof(*og01a1b), GFP_KERNEL);1079	if (!og01a1b)1080		return -ENOMEM;1081 1082	v4l2_i2c_subdev_init(&og01a1b->sd, client, &og01a1b_subdev_ops);1083 1084	og01a1b->xvclk = devm_clk_get_optional(&client->dev, NULL);1085	if (IS_ERR(og01a1b->xvclk)) {1086		ret = PTR_ERR(og01a1b->xvclk);1087		dev_err(&client->dev, "failed to get xvclk clock: %d\n", ret);1088		return ret;1089	}1090 1091	ret = og01a1b_check_hwcfg(og01a1b);1092	if (ret) {1093		dev_err(&client->dev, "failed to check HW configuration: %d",1094			ret);1095		return ret;1096	}1097 1098	og01a1b->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",1099						      GPIOD_OUT_LOW);1100	if (IS_ERR(og01a1b->reset_gpio)) {1101		dev_err(&client->dev, "cannot get reset GPIO\n");1102		return PTR_ERR(og01a1b->reset_gpio);1103	}1104 1105	og01a1b->avdd = devm_regulator_get_optional(&client->dev, "avdd");1106	if (IS_ERR(og01a1b->avdd)) {1107		ret = PTR_ERR(og01a1b->avdd);1108		if (ret != -ENODEV) {1109			dev_err_probe(&client->dev, ret,1110				      "Failed to get 'avdd' regulator\n");1111			return ret;1112		}1113 1114		og01a1b->avdd = NULL;1115	}1116 1117	og01a1b->dovdd = devm_regulator_get_optional(&client->dev, "dovdd");1118	if (IS_ERR(og01a1b->dovdd)) {1119		ret = PTR_ERR(og01a1b->dovdd);1120		if (ret != -ENODEV) {1121			dev_err_probe(&client->dev, ret,1122				      "Failed to get 'dovdd' regulator\n");1123			return ret;1124		}1125 1126		og01a1b->dovdd = NULL;1127	}1128 1129	og01a1b->dvdd = devm_regulator_get_optional(&client->dev, "dvdd");1130	if (IS_ERR(og01a1b->dvdd)) {1131		ret = PTR_ERR(og01a1b->dvdd);1132		if (ret != -ENODEV) {1133			dev_err_probe(&client->dev, ret,1134				      "Failed to get 'dvdd' regulator\n");1135			return ret;1136		}1137 1138		og01a1b->dvdd = NULL;1139	}1140 1141	/* The sensor must be powered on to read the CHIP_ID register */1142	ret = og01a1b_power_on(&client->dev);1143	if (ret)1144		return ret;1145 1146	ret = og01a1b_identify_module(og01a1b);1147	if (ret) {1148		dev_err(&client->dev, "failed to find sensor: %d", ret);1149		goto power_off;1150	}1151 1152	mutex_init(&og01a1b->mutex);1153	og01a1b->cur_mode = &supported_modes[0];1154	ret = og01a1b_init_controls(og01a1b);1155	if (ret) {1156		dev_err(&client->dev, "failed to init controls: %d", ret);1157		goto probe_error_v4l2_ctrl_handler_free;1158	}1159 1160	og01a1b->sd.internal_ops = &og01a1b_internal_ops;1161	og01a1b->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;1162	og01a1b->sd.entity.ops = &og01a1b_subdev_entity_ops;1163	og01a1b->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;1164	og01a1b->pad.flags = MEDIA_PAD_FL_SOURCE;1165	ret = media_entity_pads_init(&og01a1b->sd.entity, 1, &og01a1b->pad);1166	if (ret) {1167		dev_err(&client->dev, "failed to init entity pads: %d", ret);1168		goto probe_error_v4l2_ctrl_handler_free;1169	}1170 1171	ret = v4l2_async_register_subdev_sensor(&og01a1b->sd);1172	if (ret < 0) {1173		dev_err(&client->dev, "failed to register V4L2 subdev: %d",1174			ret);1175		goto probe_error_media_entity_cleanup;1176	}1177 1178	/* Enable runtime PM and turn off the device */1179	pm_runtime_set_active(&client->dev);1180	pm_runtime_enable(&client->dev);1181	pm_runtime_idle(&client->dev);1182 1183	return 0;1184 1185probe_error_media_entity_cleanup:1186	media_entity_cleanup(&og01a1b->sd.entity);1187 1188probe_error_v4l2_ctrl_handler_free:1189	v4l2_ctrl_handler_free(og01a1b->sd.ctrl_handler);1190	mutex_destroy(&og01a1b->mutex);1191 1192power_off:1193	og01a1b_power_off(&client->dev);1194 1195	return ret;1196}1197 1198static const struct dev_pm_ops og01a1b_pm_ops = {1199	SET_RUNTIME_PM_OPS(og01a1b_power_off, og01a1b_power_on, NULL)1200};1201 1202#ifdef CONFIG_ACPI1203static const struct acpi_device_id og01a1b_acpi_ids[] = {1204	{"OVTI01AC"},1205	{}1206};1207 1208MODULE_DEVICE_TABLE(acpi, og01a1b_acpi_ids);1209#endif1210 1211static const struct of_device_id og01a1b_of_match[] = {1212	{ .compatible = "ovti,og01a1b" },1213	{ /* sentinel */ }1214};1215MODULE_DEVICE_TABLE(of, og01a1b_of_match);1216 1217static struct i2c_driver og01a1b_i2c_driver = {1218	.driver = {1219		.name = "og01a1b",1220		.pm = &og01a1b_pm_ops,1221		.acpi_match_table = ACPI_PTR(og01a1b_acpi_ids),1222		.of_match_table = og01a1b_of_match,1223	},1224	.probe = og01a1b_probe,1225	.remove = og01a1b_remove,1226};1227 1228module_i2c_driver(og01a1b_i2c_driver);1229 1230MODULE_AUTHOR("Shawn Tu");1231MODULE_DESCRIPTION("OmniVision OG01A1B sensor driver");1232MODULE_LICENSE("GPL v2");1233