brintos

brintos / linux-shallow public Read only

0
0
Text · 26.0 KiB · 2184c90 Raw
1067 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (C) 2021 Intel Corporation3 4#include <linux/acpi.h>5#include <linux/delay.h>6#include <linux/i2c.h>7#include <linux/module.h>8#include <linux/pm_runtime.h>9#include <media/v4l2-ctrls.h>10#include <media/v4l2-device.h>11#include <linux/unaligned.h>12 13#define IMX208_REG_MODE_SELECT		0x010014#define IMX208_MODE_STANDBY		0x0015#define IMX208_MODE_STREAMING		0x0116 17/* Chip ID */18#define IMX208_REG_CHIP_ID		0x000019#define IMX208_CHIP_ID			0x020820 21/* V_TIMING internal */22#define IMX208_REG_VTS			0x034023#define IMX208_VTS_60FPS		0x047224#define IMX208_VTS_BINNING		0x023925#define IMX208_VTS_60FPS_MIN		0x045826#define IMX208_VTS_BINNING_MIN		0x023027#define IMX208_VTS_MAX			0xffff28 29/* HBLANK control - read only */30#define IMX208_PPL_384MHZ		224831#define IMX208_PPL_96MHZ		224832 33/* Exposure control */34#define IMX208_REG_EXPOSURE		0x020235#define IMX208_EXPOSURE_MIN		436#define IMX208_EXPOSURE_STEP		137#define IMX208_EXPOSURE_DEFAULT		0x19038#define IMX208_EXPOSURE_MAX		6553539 40/* Analog gain control */41#define IMX208_REG_ANALOG_GAIN		0x020442#define IMX208_ANA_GAIN_MIN		043#define IMX208_ANA_GAIN_MAX		0x00e044#define IMX208_ANA_GAIN_STEP		145#define IMX208_ANA_GAIN_DEFAULT		0x046 47/* Digital gain control */48#define IMX208_REG_GR_DIGITAL_GAIN	0x020e49#define IMX208_REG_R_DIGITAL_GAIN	0x021050#define IMX208_REG_B_DIGITAL_GAIN	0x021251#define IMX208_REG_GB_DIGITAL_GAIN	0x021452#define IMX208_DIGITAL_GAIN_SHIFT	853 54/* Orientation */55#define IMX208_REG_ORIENTATION_CONTROL	0x010156 57/* Test Pattern Control */58#define IMX208_REG_TEST_PATTERN_MODE	0x060059#define IMX208_TEST_PATTERN_DISABLE	0x060#define IMX208_TEST_PATTERN_SOLID_COLOR	0x161#define IMX208_TEST_PATTERN_COLOR_BARS	0x262#define IMX208_TEST_PATTERN_GREY_COLOR	0x363#define IMX208_TEST_PATTERN_PN9		0x464#define IMX208_TEST_PATTERN_FIX_1	0x10065#define IMX208_TEST_PATTERN_FIX_2	0x10166#define IMX208_TEST_PATTERN_FIX_3	0x10267#define IMX208_TEST_PATTERN_FIX_4	0x10368#define IMX208_TEST_PATTERN_FIX_5	0x10469#define IMX208_TEST_PATTERN_FIX_6	0x10570 71/* OTP Access */72#define IMX208_OTP_BASE			0x350073#define IMX208_OTP_SIZE			4074 75struct imx208_reg {76	u16 address;77	u8 val;78};79 80struct imx208_reg_list {81	u32 num_of_regs;82	const struct imx208_reg *regs;83};84 85/* Link frequency config */86struct imx208_link_freq_config {87	u32 pixels_per_line;88 89	/* PLL registers for this link frequency */90	struct imx208_reg_list reg_list;91};92 93/* Mode : resolution and related config&values */94struct imx208_mode {95	/* Frame width */96	u32 width;97	/* Frame height */98	u32 height;99 100	/* V-timing */101	u32 vts_def;102	u32 vts_min;103 104	/* Index of Link frequency config to be used */105	u32 link_freq_index;106	/* Default register values */107	struct imx208_reg_list reg_list;108};109 110static const struct imx208_reg pll_ctrl_reg[] = {111	{0x0305, 0x02},112	{0x0307, 0x50},113	{0x303C, 0x3C},114};115 116static const struct imx208_reg mode_1936x1096_60fps_regs[] = {117	{0x0340, 0x04},118	{0x0341, 0x72},119	{0x0342, 0x04},120	{0x0343, 0x64},121	{0x034C, 0x07},122	{0x034D, 0x90},123	{0x034E, 0x04},124	{0x034F, 0x48},125	{0x0381, 0x01},126	{0x0383, 0x01},127	{0x0385, 0x01},128	{0x0387, 0x01},129	{0x3048, 0x00},130	{0x3050, 0x01},131	{0x30D5, 0x00},132	{0x3301, 0x00},133	{0x3318, 0x62},134	{0x0202, 0x01},135	{0x0203, 0x90},136	{0x0205, 0x00},137};138 139static const struct imx208_reg mode_968_548_60fps_regs[] = {140	{0x0340, 0x02},141	{0x0341, 0x39},142	{0x0342, 0x08},143	{0x0343, 0xC8},144	{0x034C, 0x03},145	{0x034D, 0xC8},146	{0x034E, 0x02},147	{0x034F, 0x24},148	{0x0381, 0x01},149	{0x0383, 0x03},150	{0x0385, 0x01},151	{0x0387, 0x03},152	{0x3048, 0x01},153	{0x3050, 0x02},154	{0x30D5, 0x03},155	{0x3301, 0x10},156	{0x3318, 0x75},157	{0x0202, 0x01},158	{0x0203, 0x90},159	{0x0205, 0x00},160};161 162static const s64 imx208_discrete_digital_gain[] = {163	1, 2, 4, 8, 16,164};165 166static const char * const imx208_test_pattern_menu[] = {167	"Disabled",168	"Solid Color",169	"100% Color Bar",170	"Fade to Grey Color Bar",171	"PN9",172	"Fixed Pattern1",173	"Fixed Pattern2",174	"Fixed Pattern3",175	"Fixed Pattern4",176	"Fixed Pattern5",177	"Fixed Pattern6"178};179 180static const int imx208_test_pattern_val[] = {181	IMX208_TEST_PATTERN_DISABLE,182	IMX208_TEST_PATTERN_SOLID_COLOR,183	IMX208_TEST_PATTERN_COLOR_BARS,184	IMX208_TEST_PATTERN_GREY_COLOR,185	IMX208_TEST_PATTERN_PN9,186	IMX208_TEST_PATTERN_FIX_1,187	IMX208_TEST_PATTERN_FIX_2,188	IMX208_TEST_PATTERN_FIX_3,189	IMX208_TEST_PATTERN_FIX_4,190	IMX208_TEST_PATTERN_FIX_5,191	IMX208_TEST_PATTERN_FIX_6,192};193 194/* Configurations for supported link frequencies */195#define IMX208_MHZ			(1000 * 1000ULL)196#define IMX208_LINK_FREQ_384MHZ		(384ULL * IMX208_MHZ)197#define IMX208_LINK_FREQ_96MHZ		(96ULL * IMX208_MHZ)198 199#define IMX208_DATA_RATE_DOUBLE		2200#define IMX208_NUM_OF_LANES		2201#define IMX208_PIXEL_BITS		10202 203enum {204	IMX208_LINK_FREQ_384MHZ_INDEX,205	IMX208_LINK_FREQ_96MHZ_INDEX,206};207 208/*209 * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample210 * data rate => double data rate; number of lanes => 2; bits per pixel => 10211 */212static u64 link_freq_to_pixel_rate(u64 f)213{214	f *= IMX208_DATA_RATE_DOUBLE * IMX208_NUM_OF_LANES;215	do_div(f, IMX208_PIXEL_BITS);216 217	return f;218}219 220/* Menu items for LINK_FREQ V4L2 control */221static const s64 link_freq_menu_items[] = {222	[IMX208_LINK_FREQ_384MHZ_INDEX] = IMX208_LINK_FREQ_384MHZ,223	[IMX208_LINK_FREQ_96MHZ_INDEX] = IMX208_LINK_FREQ_96MHZ,224};225 226/* Link frequency configs */227static const struct imx208_link_freq_config link_freq_configs[] = {228	[IMX208_LINK_FREQ_384MHZ_INDEX] = {229		.pixels_per_line = IMX208_PPL_384MHZ,230		.reg_list = {231			.num_of_regs = ARRAY_SIZE(pll_ctrl_reg),232			.regs = pll_ctrl_reg,233		}234	},235	[IMX208_LINK_FREQ_96MHZ_INDEX] = {236		.pixels_per_line = IMX208_PPL_96MHZ,237		.reg_list = {238			.num_of_regs = ARRAY_SIZE(pll_ctrl_reg),239			.regs = pll_ctrl_reg,240		}241	},242};243 244/* Mode configs */245static const struct imx208_mode supported_modes[] = {246	{247		.width = 1936,248		.height = 1096,249		.vts_def = IMX208_VTS_60FPS,250		.vts_min = IMX208_VTS_60FPS_MIN,251		.reg_list = {252			.num_of_regs = ARRAY_SIZE(mode_1936x1096_60fps_regs),253			.regs = mode_1936x1096_60fps_regs,254		},255		.link_freq_index = IMX208_LINK_FREQ_384MHZ_INDEX,256	},257	{258		.width = 968,259		.height = 548,260		.vts_def = IMX208_VTS_BINNING,261		.vts_min = IMX208_VTS_BINNING_MIN,262		.reg_list = {263			.num_of_regs = ARRAY_SIZE(mode_968_548_60fps_regs),264			.regs = mode_968_548_60fps_regs,265		},266		.link_freq_index = IMX208_LINK_FREQ_96MHZ_INDEX,267	},268};269 270struct imx208 {271	struct v4l2_subdev sd;272	struct media_pad pad;273 274	struct v4l2_ctrl_handler ctrl_handler;275	/* V4L2 Controls */276	struct v4l2_ctrl *link_freq;277	struct v4l2_ctrl *pixel_rate;278	struct v4l2_ctrl *vblank;279	struct v4l2_ctrl *hblank;280	struct v4l2_ctrl *vflip;281	struct v4l2_ctrl *hflip;282 283	/* Current mode */284	const struct imx208_mode *cur_mode;285 286	/*287	 * Mutex for serialized access:288	 * Protect sensor set pad format and start/stop streaming safely.289	 * Protect access to sensor v4l2 controls.290	 */291	struct mutex imx208_mx;292 293	/* OTP data */294	bool otp_read;295	char otp_data[IMX208_OTP_SIZE];296 297	/* True if the device has been identified */298	bool identified;299};300 301static inline struct imx208 *to_imx208(struct v4l2_subdev *_sd)302{303	return container_of(_sd, struct imx208, sd);304}305 306/* Get bayer order based on flip setting. */307static u32 imx208_get_format_code(struct imx208 *imx208)308{309	/*310	 * Only one bayer order is supported.311	 * It depends on the flip settings.312	 */313	static const u32 codes[2][2] = {314		{ MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, },315		{ MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, },316	};317 318	return codes[imx208->vflip->val][imx208->hflip->val];319}320 321/* Read registers up to 4 at a time */322static int imx208_read_reg(struct imx208 *imx208, u16 reg, u32 len, u32 *val)323{324	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);325	struct i2c_msg msgs[2];326	u8 addr_buf[2] = { reg >> 8, reg & 0xff };327	u8 data_buf[4] = { 0, };328	int ret;329 330	if (len > 4)331		return -EINVAL;332 333	/* Write register address */334	msgs[0].addr = client->addr;335	msgs[0].flags = 0;336	msgs[0].len = ARRAY_SIZE(addr_buf);337	msgs[0].buf = addr_buf;338 339	/* Read data from register */340	msgs[1].addr = client->addr;341	msgs[1].flags = I2C_M_RD;342	msgs[1].len = len;343	msgs[1].buf = &data_buf[4 - len];344 345	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));346	if (ret != ARRAY_SIZE(msgs))347		return -EIO;348 349	*val = get_unaligned_be32(data_buf);350 351	return 0;352}353 354/* Write registers up to 4 at a time */355static int imx208_write_reg(struct imx208 *imx208, u16 reg, u32 len, u32 val)356{357	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);358	u8 buf[6];359 360	if (len > 4)361		return -EINVAL;362 363	put_unaligned_be16(reg, buf);364	put_unaligned_be32(val << (8 * (4 - len)), buf + 2);365	if (i2c_master_send(client, buf, len + 2) != len + 2)366		return -EIO;367 368	return 0;369}370 371/* Write a list of registers */372static int imx208_write_regs(struct imx208 *imx208,373			     const struct imx208_reg *regs, u32 len)374{375	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);376	unsigned int i;377	int ret;378 379	for (i = 0; i < len; i++) {380		ret = imx208_write_reg(imx208, regs[i].address, 1,381				       regs[i].val);382		if (ret) {383			dev_err_ratelimited(&client->dev,384					    "Failed to write reg 0x%4.4x. error = %d\n",385					    regs[i].address, ret);386 387			return ret;388		}389	}390 391	return 0;392}393 394/* Open sub-device */395static int imx208_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)396{397	struct v4l2_mbus_framefmt *try_fmt =398		v4l2_subdev_state_get_format(fh->state, 0);399 400	/* Initialize try_fmt */401	try_fmt->width = supported_modes[0].width;402	try_fmt->height = supported_modes[0].height;403	try_fmt->code = MEDIA_BUS_FMT_SRGGB10_1X10;404	try_fmt->field = V4L2_FIELD_NONE;405 406	return 0;407}408 409static int imx208_update_digital_gain(struct imx208 *imx208, u32 len, u32 val)410{411	int ret;412 413	val = imx208_discrete_digital_gain[val] << IMX208_DIGITAL_GAIN_SHIFT;414 415	ret = imx208_write_reg(imx208, IMX208_REG_GR_DIGITAL_GAIN, 2, val);416	if (ret)417		return ret;418 419	ret = imx208_write_reg(imx208, IMX208_REG_GB_DIGITAL_GAIN, 2, val);420	if (ret)421		return ret;422 423	ret = imx208_write_reg(imx208, IMX208_REG_R_DIGITAL_GAIN, 2, val);424	if (ret)425		return ret;426 427	return imx208_write_reg(imx208, IMX208_REG_B_DIGITAL_GAIN, 2, val);428}429 430static int imx208_set_ctrl(struct v4l2_ctrl *ctrl)431{432	struct imx208 *imx208 =433		container_of(ctrl->handler, struct imx208, ctrl_handler);434	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);435	int ret;436 437	/*438	 * Applying V4L2 control value only happens439	 * when power is up for streaming440	 */441	if (!pm_runtime_get_if_in_use(&client->dev))442		return 0;443 444	switch (ctrl->id) {445	case V4L2_CID_ANALOGUE_GAIN:446		ret = imx208_write_reg(imx208, IMX208_REG_ANALOG_GAIN,447				       2, ctrl->val);448		break;449	case V4L2_CID_EXPOSURE:450		ret = imx208_write_reg(imx208, IMX208_REG_EXPOSURE,451				       2, ctrl->val);452		break;453	case V4L2_CID_DIGITAL_GAIN:454		ret = imx208_update_digital_gain(imx208, 2, ctrl->val);455		break;456	case V4L2_CID_VBLANK:457		/* Update VTS that meets expected vertical blanking */458		ret = imx208_write_reg(imx208, IMX208_REG_VTS, 2,459				       imx208->cur_mode->height + ctrl->val);460		break;461	case V4L2_CID_TEST_PATTERN:462		ret = imx208_write_reg(imx208, IMX208_REG_TEST_PATTERN_MODE,463				       2, imx208_test_pattern_val[ctrl->val]);464		break;465	case V4L2_CID_HFLIP:466	case V4L2_CID_VFLIP:467		ret = imx208_write_reg(imx208, IMX208_REG_ORIENTATION_CONTROL,468				       1,469				       imx208->hflip->val |470				       imx208->vflip->val << 1);471		break;472	default:473		ret = -EINVAL;474		dev_err(&client->dev,475			"ctrl(id:0x%x,val:0x%x) is not handled\n",476			ctrl->id, ctrl->val);477		break;478	}479 480	pm_runtime_put(&client->dev);481 482	return ret;483}484 485static const struct v4l2_ctrl_ops imx208_ctrl_ops = {486	.s_ctrl = imx208_set_ctrl,487};488 489static const struct v4l2_ctrl_config imx208_digital_gain_control = {490	.ops = &imx208_ctrl_ops,491	.id = V4L2_CID_DIGITAL_GAIN,492	.name = "Digital Gain",493	.type = V4L2_CTRL_TYPE_INTEGER_MENU,494	.min = 0,495	.max = ARRAY_SIZE(imx208_discrete_digital_gain) - 1,496	.step = 0,497	.def = 0,498	.menu_skip_mask = 0,499	.qmenu_int = imx208_discrete_digital_gain,500};501 502static int imx208_enum_mbus_code(struct v4l2_subdev *sd,503				 struct v4l2_subdev_state *sd_state,504				 struct v4l2_subdev_mbus_code_enum *code)505{506	struct imx208 *imx208 = to_imx208(sd);507 508	if (code->index > 0)509		return -EINVAL;510 511	code->code = imx208_get_format_code(imx208);512 513	return 0;514}515 516static int imx208_enum_frame_size(struct v4l2_subdev *sd,517				  struct v4l2_subdev_state *sd_state,518				  struct v4l2_subdev_frame_size_enum *fse)519{520	struct imx208 *imx208 = to_imx208(sd);521 522	if (fse->index >= ARRAY_SIZE(supported_modes))523		return -EINVAL;524 525	if (fse->code != imx208_get_format_code(imx208))526		return -EINVAL;527 528	fse->min_width = supported_modes[fse->index].width;529	fse->max_width = fse->min_width;530	fse->min_height = supported_modes[fse->index].height;531	fse->max_height = fse->min_height;532 533	return 0;534}535 536static void imx208_mode_to_pad_format(struct imx208 *imx208,537				      const struct imx208_mode *mode,538				      struct v4l2_subdev_format *fmt)539{540	fmt->format.width = mode->width;541	fmt->format.height = mode->height;542	fmt->format.code = imx208_get_format_code(imx208);543	fmt->format.field = V4L2_FIELD_NONE;544}545 546static int __imx208_get_pad_format(struct imx208 *imx208,547				   struct v4l2_subdev_state *sd_state,548				   struct v4l2_subdev_format *fmt)549{550	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)551		fmt->format = *v4l2_subdev_state_get_format(sd_state,552							    fmt->pad);553	else554		imx208_mode_to_pad_format(imx208, imx208->cur_mode, fmt);555 556	return 0;557}558 559static int imx208_get_pad_format(struct v4l2_subdev *sd,560				 struct v4l2_subdev_state *sd_state,561				 struct v4l2_subdev_format *fmt)562{563	struct imx208 *imx208 = to_imx208(sd);564	int ret;565 566	mutex_lock(&imx208->imx208_mx);567	ret = __imx208_get_pad_format(imx208, sd_state, fmt);568	mutex_unlock(&imx208->imx208_mx);569 570	return ret;571}572 573static int imx208_set_pad_format(struct v4l2_subdev *sd,574				 struct v4l2_subdev_state *sd_state,575				 struct v4l2_subdev_format *fmt)576{577	struct imx208 *imx208 = to_imx208(sd);578	const struct imx208_mode *mode;579	s32 vblank_def;580	s32 vblank_min;581	s64 h_blank;582	s64 pixel_rate;583	s64 link_freq;584 585	mutex_lock(&imx208->imx208_mx);586 587	fmt->format.code = imx208_get_format_code(imx208);588	mode = v4l2_find_nearest_size(supported_modes,589				      ARRAY_SIZE(supported_modes), width, height,590				      fmt->format.width, fmt->format.height);591	imx208_mode_to_pad_format(imx208, mode, fmt);592	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {593		*v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format;594	} else {595		imx208->cur_mode = mode;596		__v4l2_ctrl_s_ctrl(imx208->link_freq, mode->link_freq_index);597		link_freq = link_freq_menu_items[mode->link_freq_index];598		pixel_rate = link_freq_to_pixel_rate(link_freq);599		__v4l2_ctrl_s_ctrl_int64(imx208->pixel_rate, pixel_rate);600		/* Update limits and set FPS to default */601		vblank_def = imx208->cur_mode->vts_def -602			     imx208->cur_mode->height;603		vblank_min = imx208->cur_mode->vts_min -604			     imx208->cur_mode->height;605		__v4l2_ctrl_modify_range(imx208->vblank, vblank_min,606					 IMX208_VTS_MAX - imx208->cur_mode->height,607					 1, vblank_def);608		__v4l2_ctrl_s_ctrl(imx208->vblank, vblank_def);609		h_blank =610			link_freq_configs[mode->link_freq_index].pixels_per_line611			 - imx208->cur_mode->width;612		__v4l2_ctrl_modify_range(imx208->hblank, h_blank,613					 h_blank, 1, h_blank);614	}615 616	mutex_unlock(&imx208->imx208_mx);617 618	return 0;619}620 621static int imx208_identify_module(struct imx208 *imx208)622{623	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);624	int ret;625	u32 val;626 627	if (imx208->identified)628		return 0;629 630	ret = imx208_read_reg(imx208, IMX208_REG_CHIP_ID,631			      2, &val);632	if (ret) {633		dev_err(&client->dev, "failed to read chip id %x\n",634			IMX208_CHIP_ID);635		return ret;636	}637 638	if (val != IMX208_CHIP_ID) {639		dev_err(&client->dev, "chip id mismatch: %x!=%x\n",640			IMX208_CHIP_ID, val);641		return -EIO;642	}643 644	imx208->identified = true;645 646	return 0;647}648 649/* Start streaming */650static int imx208_start_streaming(struct imx208 *imx208)651{652	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);653	const struct imx208_reg_list *reg_list;654	int ret, link_freq_index;655 656	ret = imx208_identify_module(imx208);657	if (ret)658		return ret;659 660	/* Setup PLL */661	link_freq_index = imx208->cur_mode->link_freq_index;662	reg_list = &link_freq_configs[link_freq_index].reg_list;663	ret = imx208_write_regs(imx208, reg_list->regs, reg_list->num_of_regs);664	if (ret) {665		dev_err(&client->dev, "%s failed to set plls\n", __func__);666		return ret;667	}668 669	/* Apply default values of current mode */670	reg_list = &imx208->cur_mode->reg_list;671	ret = imx208_write_regs(imx208, reg_list->regs, reg_list->num_of_regs);672	if (ret) {673		dev_err(&client->dev, "%s failed to set mode\n", __func__);674		return ret;675	}676 677	/* Apply customized values from user */678	ret =  __v4l2_ctrl_handler_setup(imx208->sd.ctrl_handler);679	if (ret)680		return ret;681 682	/* set stream on register */683	return imx208_write_reg(imx208, IMX208_REG_MODE_SELECT,684				1, IMX208_MODE_STREAMING);685}686 687/* Stop streaming */688static int imx208_stop_streaming(struct imx208 *imx208)689{690	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);691	int ret;692 693	/* set stream off register */694	ret = imx208_write_reg(imx208, IMX208_REG_MODE_SELECT,695			       1, IMX208_MODE_STANDBY);696	if (ret)697		dev_err(&client->dev, "%s failed to set stream\n", __func__);698 699	/*700	 * Return success even if it was an error, as there is nothing the701	 * caller can do about it.702	 */703	return 0;704}705 706static int imx208_set_stream(struct v4l2_subdev *sd, int enable)707{708	struct imx208 *imx208 = to_imx208(sd);709	struct i2c_client *client = v4l2_get_subdevdata(sd);710	int ret = 0;711 712	mutex_lock(&imx208->imx208_mx);713 714	if (enable) {715		ret = pm_runtime_resume_and_get(&client->dev);716		if (ret) {717			mutex_unlock(&imx208->imx208_mx);718			return ret;719		}720 721		/*722		 * Apply default & customized values723		 * and then start streaming.724		 */725		ret = imx208_start_streaming(imx208);726		if (ret)727			goto err_rpm_put;728	} else {729		imx208_stop_streaming(imx208);730		pm_runtime_put(&client->dev);731	}732 733	mutex_unlock(&imx208->imx208_mx);734 735	/* vflip and hflip cannot change during streaming */736	v4l2_ctrl_grab(imx208->vflip, enable);737	v4l2_ctrl_grab(imx208->hflip, enable);738 739	return ret;740 741err_rpm_put:742	pm_runtime_put(&client->dev);743	mutex_unlock(&imx208->imx208_mx);744 745	return ret;746}747 748/* Verify chip ID */749static const struct v4l2_subdev_video_ops imx208_video_ops = {750	.s_stream = imx208_set_stream,751};752 753static const struct v4l2_subdev_pad_ops imx208_pad_ops = {754	.enum_mbus_code = imx208_enum_mbus_code,755	.get_fmt = imx208_get_pad_format,756	.set_fmt = imx208_set_pad_format,757	.enum_frame_size = imx208_enum_frame_size,758};759 760static const struct v4l2_subdev_ops imx208_subdev_ops = {761	.video = &imx208_video_ops,762	.pad = &imx208_pad_ops,763};764 765static const struct v4l2_subdev_internal_ops imx208_internal_ops = {766	.open = imx208_open,767};768 769static int imx208_read_otp(struct imx208 *imx208)770{771	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);772	struct i2c_msg msgs[2];773	u8 addr_buf[2] = { IMX208_OTP_BASE >> 8, IMX208_OTP_BASE & 0xff };774	int ret = 0;775 776	mutex_lock(&imx208->imx208_mx);777 778	if (imx208->otp_read)779		goto out_unlock;780 781	ret = pm_runtime_resume_and_get(&client->dev);782	if (ret)783		goto out_unlock;784 785	ret = imx208_identify_module(imx208);786	if (ret)787		goto out_pm_put;788 789	/* Write register address */790	msgs[0].addr = client->addr;791	msgs[0].flags = 0;792	msgs[0].len = ARRAY_SIZE(addr_buf);793	msgs[0].buf = addr_buf;794 795	/* Read data from registers */796	msgs[1].addr = client->addr;797	msgs[1].flags = I2C_M_RD;798	msgs[1].len = sizeof(imx208->otp_data);799	msgs[1].buf = imx208->otp_data;800 801	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));802	if (ret == ARRAY_SIZE(msgs)) {803		imx208->otp_read = true;804		ret = 0;805	}806 807out_pm_put:808	pm_runtime_put(&client->dev);809 810out_unlock:811	mutex_unlock(&imx208->imx208_mx);812 813	return ret;814}815 816static ssize_t otp_read(struct file *filp, struct kobject *kobj,817			struct bin_attribute *bin_attr,818			char *buf, loff_t off, size_t count)819{820	struct i2c_client *client = to_i2c_client(kobj_to_dev(kobj));821	struct v4l2_subdev *sd = i2c_get_clientdata(client);822	struct imx208 *imx208 = to_imx208(sd);823	int ret;824 825	ret = imx208_read_otp(imx208);826	if (ret)827		return ret;828 829	memcpy(buf, &imx208->otp_data[off], count);830	return count;831}832 833static const BIN_ATTR_RO(otp, IMX208_OTP_SIZE);834 835/* Initialize control handlers */836static int imx208_init_controls(struct imx208 *imx208)837{838	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);839	struct v4l2_ctrl_handler *ctrl_hdlr = &imx208->ctrl_handler;840	s64 exposure_max;841	s64 vblank_def;842	s64 vblank_min;843	s64 pixel_rate_min;844	s64 pixel_rate_max;845	int ret;846 847	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8);848	if (ret)849		return ret;850 851	mutex_init(&imx208->imx208_mx);852	ctrl_hdlr->lock = &imx208->imx208_mx;853	imx208->link_freq =854		v4l2_ctrl_new_int_menu(ctrl_hdlr,855				       &imx208_ctrl_ops,856				       V4L2_CID_LINK_FREQ,857				       ARRAY_SIZE(link_freq_menu_items) - 1,858				       0, link_freq_menu_items);859 860	if (imx208->link_freq)861		imx208->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;862 863	pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]);864	pixel_rate_min =865		link_freq_to_pixel_rate(link_freq_menu_items[ARRAY_SIZE(link_freq_menu_items) - 1]);866	/* By default, PIXEL_RATE is read only */867	imx208->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx208_ctrl_ops,868					       V4L2_CID_PIXEL_RATE,869					       pixel_rate_min, pixel_rate_max,870					       1, pixel_rate_max);871 872	vblank_def = imx208->cur_mode->vts_def - imx208->cur_mode->height;873	vblank_min = imx208->cur_mode->vts_min - imx208->cur_mode->height;874	imx208->vblank =875		v4l2_ctrl_new_std(ctrl_hdlr, &imx208_ctrl_ops, V4L2_CID_VBLANK,876				  vblank_min,877				  IMX208_VTS_MAX - imx208->cur_mode->height, 1,878				  vblank_def);879 880	imx208->hblank =881		v4l2_ctrl_new_std(ctrl_hdlr, &imx208_ctrl_ops, V4L2_CID_HBLANK,882				  IMX208_PPL_384MHZ - imx208->cur_mode->width,883				  IMX208_PPL_384MHZ - imx208->cur_mode->width,884				  1,885				  IMX208_PPL_384MHZ - imx208->cur_mode->width);886 887	if (imx208->hblank)888		imx208->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;889 890	exposure_max = imx208->cur_mode->vts_def - 8;891	v4l2_ctrl_new_std(ctrl_hdlr, &imx208_ctrl_ops, V4L2_CID_EXPOSURE,892			  IMX208_EXPOSURE_MIN, exposure_max,893			  IMX208_EXPOSURE_STEP, IMX208_EXPOSURE_DEFAULT);894 895	imx208->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx208_ctrl_ops,896					  V4L2_CID_HFLIP, 0, 1, 1, 0);897	if (imx208->hflip)898		imx208->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;899	imx208->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx208_ctrl_ops,900					  V4L2_CID_VFLIP, 0, 1, 1, 0);901	if (imx208->vflip)902		imx208->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;903 904	v4l2_ctrl_new_std(ctrl_hdlr, &imx208_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,905			  IMX208_ANA_GAIN_MIN, IMX208_ANA_GAIN_MAX,906			  IMX208_ANA_GAIN_STEP, IMX208_ANA_GAIN_DEFAULT);907 908	v4l2_ctrl_new_custom(ctrl_hdlr, &imx208_digital_gain_control, NULL);909 910	v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx208_ctrl_ops,911				     V4L2_CID_TEST_PATTERN,912				     ARRAY_SIZE(imx208_test_pattern_menu) - 1,913				     0, 0, imx208_test_pattern_menu);914 915	if (ctrl_hdlr->error) {916		ret = ctrl_hdlr->error;917		dev_err(&client->dev, "%s control init failed (%d)\n",918			__func__, ret);919		goto error;920	}921 922	imx208->sd.ctrl_handler = ctrl_hdlr;923 924	return 0;925 926error:927	v4l2_ctrl_handler_free(ctrl_hdlr);928	mutex_destroy(&imx208->imx208_mx);929 930	return ret;931}932 933static void imx208_free_controls(struct imx208 *imx208)934{935	v4l2_ctrl_handler_free(imx208->sd.ctrl_handler);936}937 938static int imx208_probe(struct i2c_client *client)939{940	struct imx208 *imx208;941	int ret;942	bool full_power;943	u32 val = 0;944 945	device_property_read_u32(&client->dev, "clock-frequency", &val);946	if (val != 19200000) {947		dev_err(&client->dev,948			"Unsupported clock-frequency %u. Expected 19200000.\n",949			val);950		return -EINVAL;951	}952 953	imx208 = devm_kzalloc(&client->dev, sizeof(*imx208), GFP_KERNEL);954	if (!imx208)955		return -ENOMEM;956 957	/* Initialize subdev */958	v4l2_i2c_subdev_init(&imx208->sd, client, &imx208_subdev_ops);959 960	full_power = acpi_dev_state_d0(&client->dev);961	if (full_power) {962		/* Check module identity */963		ret = imx208_identify_module(imx208);964		if (ret) {965			dev_err(&client->dev, "failed to find sensor: %d", ret);966			goto error_probe;967		}968	}969 970	/* Set default mode to max resolution */971	imx208->cur_mode = &supported_modes[0];972 973	ret = imx208_init_controls(imx208);974	if (ret) {975		dev_err(&client->dev, "failed to init controls: %d", ret);976		goto error_probe;977	}978 979	/* Initialize subdev */980	imx208->sd.internal_ops = &imx208_internal_ops;981	imx208->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;982	imx208->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;983 984	/* Initialize source pad */985	imx208->pad.flags = MEDIA_PAD_FL_SOURCE;986	ret = media_entity_pads_init(&imx208->sd.entity, 1, &imx208->pad);987	if (ret) {988		dev_err(&client->dev, "%s failed:%d\n", __func__, ret);989		goto error_handler_free;990	}991 992	ret = v4l2_async_register_subdev_sensor(&imx208->sd);993	if (ret < 0)994		goto error_media_entity;995 996	ret = device_create_bin_file(&client->dev, &bin_attr_otp);997	if (ret) {998		dev_err(&client->dev, "sysfs otp creation failed\n");999		goto error_async_subdev;1000	}1001 1002	/* Set the device's state to active if it's in D0 state. */1003	if (full_power)1004		pm_runtime_set_active(&client->dev);1005	pm_runtime_enable(&client->dev);1006	pm_runtime_idle(&client->dev);1007 1008	return 0;1009 1010error_async_subdev:1011	v4l2_async_unregister_subdev(&imx208->sd);1012 1013error_media_entity:1014	media_entity_cleanup(&imx208->sd.entity);1015 1016error_handler_free:1017	imx208_free_controls(imx208);1018 1019error_probe:1020	mutex_destroy(&imx208->imx208_mx);1021 1022	return ret;1023}1024 1025static void imx208_remove(struct i2c_client *client)1026{1027	struct v4l2_subdev *sd = i2c_get_clientdata(client);1028	struct imx208 *imx208 = to_imx208(sd);1029 1030	device_remove_bin_file(&client->dev, &bin_attr_otp);1031	v4l2_async_unregister_subdev(sd);1032	media_entity_cleanup(&sd->entity);1033	imx208_free_controls(imx208);1034 1035	pm_runtime_disable(&client->dev);1036	pm_runtime_set_suspended(&client->dev);1037 1038	mutex_destroy(&imx208->imx208_mx);1039}1040 1041#ifdef CONFIG_ACPI1042static const struct acpi_device_id imx208_acpi_ids[] = {1043	{ "INT3478" },1044	{ /* sentinel */ }1045};1046 1047MODULE_DEVICE_TABLE(acpi, imx208_acpi_ids);1048#endif1049 1050static struct i2c_driver imx208_i2c_driver = {1051	.driver = {1052		.name = "imx208",1053		.acpi_match_table = ACPI_PTR(imx208_acpi_ids),1054	},1055	.probe = imx208_probe,1056	.remove = imx208_remove,1057	.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,1058};1059 1060module_i2c_driver(imx208_i2c_driver);1061 1062MODULE_AUTHOR("Yeh, Andy <andy.yeh@intel.com>");1063MODULE_AUTHOR("Chen, Ping-chung <ping-chung.chen@intel.com>");1064MODULE_AUTHOR("Shawn Tu");1065MODULE_DESCRIPTION("Sony IMX208 sensor driver");1066MODULE_LICENSE("GPL v2");1067