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