1766 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Samsung LSI S5C73M3 8M pixel camera driver4 *5 * Copyright (C) 2012, Samsung Electronics, Co., Ltd.6 * Sylwester Nawrocki <s.nawrocki@samsung.com>7 * Andrzej Hajda <a.hajda@samsung.com>8 */9 10#include <linux/clk.h>11#include <linux/delay.h>12#include <linux/firmware.h>13#include <linux/gpio/consumer.h>14#include <linux/i2c.h>15#include <linux/init.h>16#include <linux/media.h>17#include <linux/module.h>18#include <linux/of_graph.h>19#include <linux/regulator/consumer.h>20#include <linux/sizes.h>21#include <linux/slab.h>22#include <linux/spi/spi.h>23#include <linux/videodev2.h>24#include <media/media-entity.h>25#include <media/v4l2-ctrls.h>26#include <media/v4l2-device.h>27#include <media/v4l2-subdev.h>28#include <media/v4l2-mediabus.h>29#include <media/v4l2-fwnode.h>30 31#include "s5c73m3.h"32 33int s5c73m3_dbg;34module_param_named(debug, s5c73m3_dbg, int, 0644);35 36static int boot_from_rom = 1;37module_param(boot_from_rom, int, 0644);38 39static int update_fw;40module_param(update_fw, int, 0644);41 42#define S5C73M3_EMBEDDED_DATA_MAXLEN SZ_4K43#define S5C73M3_MIPI_DATA_LANES 444#define S5C73M3_CLK_NAME "cis_extclk"45 46static const char * const s5c73m3_supply_names[S5C73M3_MAX_SUPPLIES] = {47 "vdd-int", /* Digital Core supply (1.2V), CAM_ISP_CORE_1.2V */48 "vdda", /* Analog Core supply (1.2V), CAM_SENSOR_CORE_1.2V */49 "vdd-reg", /* Regulator input supply (2.8V), CAM_SENSOR_A2.8V */50 "vddio-host", /* Digital Host I/O power supply (1.8V...2.8V),51 CAM_ISP_SENSOR_1.8V */52 "vddio-cis", /* Digital CIS I/O power (1.2V...1.8V),53 CAM_ISP_MIPI_1.2V */54 "vdd-af", /* Lens, CAM_AF_2.8V */55};56 57static const struct s5c73m3_frame_size s5c73m3_isp_resolutions[] = {58 { 320, 240, COMM_CHG_MODE_YUV_320_240 },59 { 352, 288, COMM_CHG_MODE_YUV_352_288 },60 { 640, 480, COMM_CHG_MODE_YUV_640_480 },61 { 880, 720, COMM_CHG_MODE_YUV_880_720 },62 { 960, 720, COMM_CHG_MODE_YUV_960_720 },63 { 1008, 672, COMM_CHG_MODE_YUV_1008_672 },64 { 1184, 666, COMM_CHG_MODE_YUV_1184_666 },65 { 1280, 720, COMM_CHG_MODE_YUV_1280_720 },66 { 1536, 864, COMM_CHG_MODE_YUV_1536_864 },67 { 1600, 1200, COMM_CHG_MODE_YUV_1600_1200 },68 { 1632, 1224, COMM_CHG_MODE_YUV_1632_1224 },69 { 1920, 1080, COMM_CHG_MODE_YUV_1920_1080 },70 { 1920, 1440, COMM_CHG_MODE_YUV_1920_1440 },71 { 2304, 1296, COMM_CHG_MODE_YUV_2304_1296 },72 { 3264, 2448, COMM_CHG_MODE_YUV_3264_2448 },73};74 75static const struct s5c73m3_frame_size s5c73m3_jpeg_resolutions[] = {76 { 640, 480, COMM_CHG_MODE_JPEG_640_480 },77 { 800, 450, COMM_CHG_MODE_JPEG_800_450 },78 { 800, 600, COMM_CHG_MODE_JPEG_800_600 },79 { 1024, 768, COMM_CHG_MODE_JPEG_1024_768 },80 { 1280, 720, COMM_CHG_MODE_JPEG_1280_720 },81 { 1280, 960, COMM_CHG_MODE_JPEG_1280_960 },82 { 1600, 900, COMM_CHG_MODE_JPEG_1600_900 },83 { 1600, 1200, COMM_CHG_MODE_JPEG_1600_1200 },84 { 2048, 1152, COMM_CHG_MODE_JPEG_2048_1152 },85 { 2048, 1536, COMM_CHG_MODE_JPEG_2048_1536 },86 { 2560, 1440, COMM_CHG_MODE_JPEG_2560_1440 },87 { 2560, 1920, COMM_CHG_MODE_JPEG_2560_1920 },88 { 3264, 1836, COMM_CHG_MODE_JPEG_3264_1836 },89 { 3264, 2176, COMM_CHG_MODE_JPEG_3264_2176 },90 { 3264, 2448, COMM_CHG_MODE_JPEG_3264_2448 },91};92 93static const struct s5c73m3_frame_size * const s5c73m3_resolutions[] = {94 [RES_ISP] = s5c73m3_isp_resolutions,95 [RES_JPEG] = s5c73m3_jpeg_resolutions96};97 98static const int s5c73m3_resolutions_len[] = {99 [RES_ISP] = ARRAY_SIZE(s5c73m3_isp_resolutions),100 [RES_JPEG] = ARRAY_SIZE(s5c73m3_jpeg_resolutions)101};102 103static const struct s5c73m3_interval s5c73m3_intervals[] = {104 { COMM_FRAME_RATE_FIXED_7FPS, {142857, 1000000}, {3264, 2448} },105 { COMM_FRAME_RATE_FIXED_15FPS, {66667, 1000000}, {3264, 2448} },106 { COMM_FRAME_RATE_FIXED_20FPS, {50000, 1000000}, {2304, 1296} },107 { COMM_FRAME_RATE_FIXED_30FPS, {33333, 1000000}, {2304, 1296} },108};109 110#define S5C73M3_DEFAULT_FRAME_INTERVAL 3 /* 30 fps */111 112static void s5c73m3_fill_mbus_fmt(struct v4l2_mbus_framefmt *mf,113 const struct s5c73m3_frame_size *fs,114 u32 code)115{116 mf->width = fs->width;117 mf->height = fs->height;118 mf->code = code;119 mf->colorspace = V4L2_COLORSPACE_JPEG;120 mf->field = V4L2_FIELD_NONE;121}122 123static int s5c73m3_i2c_write(struct i2c_client *client, u16 addr, u16 data)124{125 u8 buf[4] = { addr >> 8, addr & 0xff, data >> 8, data & 0xff };126 127 int ret = i2c_master_send(client, buf, sizeof(buf));128 129 v4l_dbg(4, s5c73m3_dbg, client, "%s: addr 0x%04x, data 0x%04x\n",130 __func__, addr, data);131 132 if (ret == 4)133 return 0;134 135 return ret < 0 ? ret : -EREMOTEIO;136}137 138static int s5c73m3_i2c_read(struct i2c_client *client, u16 addr, u16 *data)139{140 int ret;141 u8 rbuf[2], wbuf[2] = { addr >> 8, addr & 0xff };142 struct i2c_msg msg[2] = {143 {144 .addr = client->addr,145 .flags = 0,146 .len = sizeof(wbuf),147 .buf = wbuf148 }, {149 .addr = client->addr,150 .flags = I2C_M_RD,151 .len = sizeof(rbuf),152 .buf = rbuf153 }154 };155 /*156 * Issue repeated START after writing 2 address bytes and157 * just one STOP only after reading the data bytes.158 */159 ret = i2c_transfer(client->adapter, msg, 2);160 if (ret == 2) {161 *data = be16_to_cpup((__be16 *)rbuf);162 v4l2_dbg(4, s5c73m3_dbg, client,163 "%s: addr: 0x%04x, data: 0x%04x\n",164 __func__, addr, *data);165 return 0;166 }167 168 v4l2_err(client, "I2C read failed: addr: %04x, (%d)\n", addr, ret);169 170 return ret >= 0 ? -EREMOTEIO : ret;171}172 173int s5c73m3_write(struct s5c73m3 *state, u32 addr, u16 data)174{175 struct i2c_client *client = state->i2c_client;176 int ret;177 178 if ((addr ^ state->i2c_write_address) & 0xffff0000) {179 ret = s5c73m3_i2c_write(client, REG_CMDWR_ADDRH, addr >> 16);180 if (ret < 0) {181 state->i2c_write_address = 0;182 return ret;183 }184 }185 186 if ((addr ^ state->i2c_write_address) & 0xffff) {187 ret = s5c73m3_i2c_write(client, REG_CMDWR_ADDRL, addr & 0xffff);188 if (ret < 0) {189 state->i2c_write_address = 0;190 return ret;191 }192 }193 194 state->i2c_write_address = addr;195 196 ret = s5c73m3_i2c_write(client, REG_CMDBUF_ADDR, data);197 if (ret < 0)198 return ret;199 200 state->i2c_write_address += 2;201 202 return ret;203}204 205int s5c73m3_read(struct s5c73m3 *state, u32 addr, u16 *data)206{207 struct i2c_client *client = state->i2c_client;208 int ret;209 210 if ((addr ^ state->i2c_read_address) & 0xffff0000) {211 ret = s5c73m3_i2c_write(client, REG_CMDRD_ADDRH, addr >> 16);212 if (ret < 0) {213 state->i2c_read_address = 0;214 return ret;215 }216 }217 218 if ((addr ^ state->i2c_read_address) & 0xffff) {219 ret = s5c73m3_i2c_write(client, REG_CMDRD_ADDRL, addr & 0xffff);220 if (ret < 0) {221 state->i2c_read_address = 0;222 return ret;223 }224 }225 226 state->i2c_read_address = addr;227 228 ret = s5c73m3_i2c_read(client, REG_CMDBUF_ADDR, data);229 if (ret < 0)230 return ret;231 232 state->i2c_read_address += 2;233 234 return ret;235}236 237static int s5c73m3_check_status(struct s5c73m3 *state, unsigned int value)238{239 unsigned long start = jiffies;240 unsigned long end = start + msecs_to_jiffies(2000);241 int ret;242 u16 status;243 int count = 0;244 245 do {246 ret = s5c73m3_read(state, REG_STATUS, &status);247 if (ret < 0 || status == value)248 break;249 usleep_range(500, 1000);250 ++count;251 } while (time_is_after_jiffies(end));252 253 if (count > 0)254 v4l2_dbg(1, s5c73m3_dbg, &state->sensor_sd,255 "status check took %dms\n",256 jiffies_to_msecs(jiffies - start));257 258 if (ret == 0 && status != value) {259 u16 i2c_status = 0;260 u16 i2c_seq_status = 0;261 262 s5c73m3_read(state, REG_I2C_STATUS, &i2c_status);263 s5c73m3_read(state, REG_I2C_SEQ_STATUS, &i2c_seq_status);264 265 v4l2_err(&state->sensor_sd,266 "wrong status %#x, expected: %#x, i2c_status: %#x/%#x\n",267 status, value, i2c_status, i2c_seq_status);268 269 return -ETIMEDOUT;270 }271 272 return ret;273}274 275int s5c73m3_isp_command(struct s5c73m3 *state, u16 command, u16 data)276{277 int ret;278 279 ret = s5c73m3_check_status(state, REG_STATUS_ISP_COMMAND_COMPLETED);280 if (ret < 0)281 return ret;282 283 ret = s5c73m3_write(state, 0x00095000, command);284 if (ret < 0)285 return ret;286 287 ret = s5c73m3_write(state, 0x00095002, data);288 if (ret < 0)289 return ret;290 291 return s5c73m3_write(state, REG_STATUS, 0x0001);292}293 294static int s5c73m3_isp_comm_result(struct s5c73m3 *state, u16 command,295 u16 *data)296{297 return s5c73m3_read(state, COMM_RESULT_OFFSET + command, data);298}299 300static int s5c73m3_set_af_softlanding(struct s5c73m3 *state)301{302 unsigned long start = jiffies;303 u16 af_softlanding;304 int count = 0;305 int ret;306 const char *msg;307 308 ret = s5c73m3_isp_command(state, COMM_AF_SOFTLANDING,309 COMM_AF_SOFTLANDING_ON);310 if (ret < 0) {311 v4l2_info(&state->sensor_sd, "AF soft-landing failed\n");312 return ret;313 }314 315 for (;;) {316 ret = s5c73m3_isp_comm_result(state, COMM_AF_SOFTLANDING,317 &af_softlanding);318 if (ret < 0) {319 msg = "failed";320 break;321 }322 if (af_softlanding == COMM_AF_SOFTLANDING_RES_COMPLETE) {323 msg = "succeeded";324 break;325 }326 if (++count > 100) {327 ret = -ETIME;328 msg = "timed out";329 break;330 }331 msleep(25);332 }333 334 v4l2_info(&state->sensor_sd, "AF soft-landing %s after %dms\n",335 msg, jiffies_to_msecs(jiffies - start));336 337 return ret;338}339 340static int s5c73m3_load_fw(struct v4l2_subdev *sd)341{342 struct s5c73m3 *state = sensor_sd_to_s5c73m3(sd);343 struct i2c_client *client = state->i2c_client;344 const struct firmware *fw;345 int ret;346 char fw_name[20];347 348 snprintf(fw_name, sizeof(fw_name), "SlimISP_%.2s.bin",349 state->fw_file_version);350 ret = request_firmware(&fw, fw_name, &client->dev);351 if (ret < 0) {352 v4l2_err(sd, "Firmware request failed (%s)\n", fw_name);353 return -EINVAL;354 }355 356 v4l2_info(sd, "Loading firmware (%s, %zu B)\n", fw_name, fw->size);357 358 ret = s5c73m3_spi_write(state, fw->data, fw->size, 64);359 360 if (ret >= 0)361 state->isp_ready = 1;362 else363 v4l2_err(sd, "SPI write failed\n");364 365 release_firmware(fw);366 367 return ret;368}369 370static int s5c73m3_set_frame_size(struct s5c73m3 *state)371{372 const struct s5c73m3_frame_size *prev_size =373 state->sensor_pix_size[RES_ISP];374 const struct s5c73m3_frame_size *cap_size =375 state->sensor_pix_size[RES_JPEG];376 unsigned int chg_mode;377 378 v4l2_dbg(1, s5c73m3_dbg, &state->sensor_sd,379 "Preview size: %dx%d, reg_val: 0x%x\n",380 prev_size->width, prev_size->height, prev_size->reg_val);381 382 chg_mode = prev_size->reg_val | COMM_CHG_MODE_NEW;383 384 if (state->mbus_code == S5C73M3_JPEG_FMT) {385 v4l2_dbg(1, s5c73m3_dbg, &state->sensor_sd,386 "Capture size: %dx%d, reg_val: 0x%x\n",387 cap_size->width, cap_size->height, cap_size->reg_val);388 chg_mode |= cap_size->reg_val;389 }390 391 return s5c73m3_isp_command(state, COMM_CHG_MODE, chg_mode);392}393 394static int s5c73m3_set_frame_rate(struct s5c73m3 *state)395{396 int ret;397 398 if (state->ctrls.stabilization->val)399 return 0;400 401 if (WARN_ON(state->fiv == NULL))402 return -EINVAL;403 404 ret = s5c73m3_isp_command(state, COMM_FRAME_RATE, state->fiv->fps_reg);405 if (!ret)406 state->apply_fiv = 0;407 408 return ret;409}410 411static int __s5c73m3_s_stream(struct s5c73m3 *state, struct v4l2_subdev *sd,412 int on)413{414 u16 mode;415 int ret;416 417 if (on && state->apply_fmt) {418 if (state->mbus_code == S5C73M3_JPEG_FMT)419 mode = COMM_IMG_OUTPUT_INTERLEAVED;420 else421 mode = COMM_IMG_OUTPUT_YUV;422 423 ret = s5c73m3_isp_command(state, COMM_IMG_OUTPUT, mode);424 if (!ret)425 ret = s5c73m3_set_frame_size(state);426 if (ret)427 return ret;428 state->apply_fmt = 0;429 }430 431 ret = s5c73m3_isp_command(state, COMM_SENSOR_STREAMING, !!on);432 if (ret)433 return ret;434 435 state->streaming = !!on;436 437 if (!on)438 return 0;439 440 if (state->apply_fiv) {441 ret = s5c73m3_set_frame_rate(state);442 if (ret < 0)443 v4l2_err(sd, "Error setting frame rate(%d)\n", ret);444 }445 446 return s5c73m3_check_status(state, REG_STATUS_ISP_COMMAND_COMPLETED);447}448 449static int s5c73m3_oif_s_stream(struct v4l2_subdev *sd, int on)450{451 struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);452 int ret;453 454 mutex_lock(&state->lock);455 ret = __s5c73m3_s_stream(state, sd, on);456 mutex_unlock(&state->lock);457 458 return ret;459}460 461static int s5c73m3_system_status_wait(struct s5c73m3 *state, u32 value,462 unsigned int delay, unsigned int steps)463{464 u16 reg = 0;465 466 while (steps-- > 0) {467 int ret = s5c73m3_read(state, 0x30100010, ®);468 if (ret < 0)469 return ret;470 if (reg == value)471 return 0;472 usleep_range(delay, delay + 25);473 }474 return -ETIMEDOUT;475}476 477static int s5c73m3_read_fw_version(struct s5c73m3 *state)478{479 struct v4l2_subdev *sd = &state->sensor_sd;480 int i, ret;481 u16 data[2];482 int offset;483 484 offset = state->isp_ready ? 0x60 : 0;485 486 for (i = 0; i < S5C73M3_SENSOR_FW_LEN / 2; i++) {487 ret = s5c73m3_read(state, offset + i * 2, data);488 if (ret < 0)489 return ret;490 state->sensor_fw[i * 2] = (char)(*data & 0xff);491 state->sensor_fw[i * 2 + 1] = (char)(*data >> 8);492 }493 state->sensor_fw[S5C73M3_SENSOR_FW_LEN] = '\0';494 495 496 for (i = 0; i < S5C73M3_SENSOR_TYPE_LEN / 2; i++) {497 ret = s5c73m3_read(state, offset + 6 + i * 2, data);498 if (ret < 0)499 return ret;500 state->sensor_type[i * 2] = (char)(*data & 0xff);501 state->sensor_type[i * 2 + 1] = (char)(*data >> 8);502 }503 state->sensor_type[S5C73M3_SENSOR_TYPE_LEN] = '\0';504 505 ret = s5c73m3_read(state, offset + 0x14, data);506 if (ret >= 0) {507 ret = s5c73m3_read(state, offset + 0x16, data + 1);508 if (ret >= 0)509 state->fw_size = data[0] + (data[1] << 16);510 }511 512 v4l2_info(sd, "Sensor type: %s, FW version: %s\n",513 state->sensor_type, state->sensor_fw);514 return ret;515}516 517static int s5c73m3_fw_update_from(struct s5c73m3 *state)518{519 struct v4l2_subdev *sd = &state->sensor_sd;520 u16 status = COMM_FW_UPDATE_NOT_READY;521 int ret;522 int count = 0;523 524 v4l2_warn(sd, "Updating F-ROM firmware.\n");525 do {526 if (status == COMM_FW_UPDATE_NOT_READY) {527 ret = s5c73m3_isp_command(state, COMM_FW_UPDATE, 0);528 if (ret < 0)529 return ret;530 }531 532 ret = s5c73m3_read(state, 0x00095906, &status);533 if (ret < 0)534 return ret;535 switch (status) {536 case COMM_FW_UPDATE_FAIL:537 v4l2_warn(sd, "Updating F-ROM firmware failed.\n");538 return -EIO;539 case COMM_FW_UPDATE_SUCCESS:540 v4l2_warn(sd, "Updating F-ROM firmware finished.\n");541 return 0;542 }543 ++count;544 msleep(20);545 } while (count < 500);546 547 v4l2_warn(sd, "Updating F-ROM firmware timed-out.\n");548 return -ETIMEDOUT;549}550 551static int s5c73m3_spi_boot(struct s5c73m3 *state, bool load_fw)552{553 struct v4l2_subdev *sd = &state->sensor_sd;554 int ret;555 556 /* Run ARM MCU */557 ret = s5c73m3_write(state, 0x30000004, 0xffff);558 if (ret < 0)559 return ret;560 561 usleep_range(400, 500);562 563 /* Check booting status */564 ret = s5c73m3_system_status_wait(state, 0x0c, 100, 3);565 if (ret < 0) {566 v4l2_err(sd, "booting failed: %d\n", ret);567 return ret;568 }569 570 /* P,M,S and Boot Mode */571 ret = s5c73m3_write(state, 0x30100014, 0x2146);572 if (ret < 0)573 return ret;574 575 ret = s5c73m3_write(state, 0x30100010, 0x210c);576 if (ret < 0)577 return ret;578 579 usleep_range(200, 250);580 581 /* Check SPI status */582 ret = s5c73m3_system_status_wait(state, 0x210d, 100, 300);583 if (ret < 0)584 v4l2_err(sd, "SPI not ready: %d\n", ret);585 586 /* Firmware download over SPI */587 if (load_fw)588 s5c73m3_load_fw(sd);589 590 /* MCU reset */591 ret = s5c73m3_write(state, 0x30000004, 0xfffd);592 if (ret < 0)593 return ret;594 595 /* Remap */596 ret = s5c73m3_write(state, 0x301000a4, 0x0183);597 if (ret < 0)598 return ret;599 600 /* MCU restart */601 ret = s5c73m3_write(state, 0x30000004, 0xffff);602 if (ret < 0 || !load_fw)603 return ret;604 605 ret = s5c73m3_read_fw_version(state);606 if (ret < 0)607 return ret;608 609 if (load_fw && update_fw) {610 ret = s5c73m3_fw_update_from(state);611 update_fw = 0;612 }613 614 return ret;615}616 617static int s5c73m3_set_timing_register_for_vdd(struct s5c73m3 *state)618{619 static const u32 regs[][2] = {620 { 0x30100018, 0x0618 },621 { 0x3010001c, 0x10c1 },622 { 0x30100020, 0x249e }623 };624 int ret;625 int i;626 627 for (i = 0; i < ARRAY_SIZE(regs); i++) {628 ret = s5c73m3_write(state, regs[i][0], regs[i][1]);629 if (ret < 0)630 return ret;631 }632 633 return 0;634}635 636static void s5c73m3_set_fw_file_version(struct s5c73m3 *state)637{638 switch (state->sensor_fw[0]) {639 case 'G':640 case 'O':641 state->fw_file_version[0] = 'G';642 break;643 case 'S':644 case 'Z':645 state->fw_file_version[0] = 'Z';646 break;647 }648 649 switch (state->sensor_fw[1]) {650 case 'C'...'F':651 state->fw_file_version[1] = state->sensor_fw[1];652 break;653 }654}655 656static int s5c73m3_get_fw_version(struct s5c73m3 *state)657{658 struct v4l2_subdev *sd = &state->sensor_sd;659 int ret;660 661 /* Run ARM MCU */662 ret = s5c73m3_write(state, 0x30000004, 0xffff);663 if (ret < 0)664 return ret;665 usleep_range(400, 500);666 667 /* Check booting status */668 ret = s5c73m3_system_status_wait(state, 0x0c, 100, 3);669 if (ret < 0) {670 671 v4l2_err(sd, "%s: booting failed: %d\n", __func__, ret);672 return ret;673 }674 675 /* Change I/O Driver Current in order to read from F-ROM */676 ret = s5c73m3_write(state, 0x30100120, 0x0820);677 ret = s5c73m3_write(state, 0x30100124, 0x0820);678 679 /* Offset Setting */680 ret = s5c73m3_write(state, 0x00010418, 0x0008);681 682 /* P,M,S and Boot Mode */683 ret = s5c73m3_write(state, 0x30100014, 0x2146);684 if (ret < 0)685 return ret;686 ret = s5c73m3_write(state, 0x30100010, 0x230c);687 if (ret < 0)688 return ret;689 690 usleep_range(200, 250);691 692 /* Check SPI status */693 ret = s5c73m3_system_status_wait(state, 0x230e, 100, 300);694 if (ret < 0)695 v4l2_err(sd, "SPI not ready: %d\n", ret);696 697 /* ARM reset */698 ret = s5c73m3_write(state, 0x30000004, 0xfffd);699 if (ret < 0)700 return ret;701 702 /* Remap */703 ret = s5c73m3_write(state, 0x301000a4, 0x0183);704 if (ret < 0)705 return ret;706 707 s5c73m3_set_timing_register_for_vdd(state);708 709 ret = s5c73m3_read_fw_version(state);710 711 s5c73m3_set_fw_file_version(state);712 713 return ret;714}715 716static int s5c73m3_rom_boot(struct s5c73m3 *state, bool load_fw)717{718 static const u32 boot_regs[][2] = {719 { 0x3100010c, 0x0044 },720 { 0x31000108, 0x000d },721 { 0x31000304, 0x0001 },722 { 0x00010000, 0x5800 },723 { 0x00010002, 0x0002 },724 { 0x31000000, 0x0001 },725 { 0x30100014, 0x1b85 },726 { 0x30100010, 0x230c }727 };728 struct v4l2_subdev *sd = &state->sensor_sd;729 int i, ret;730 731 /* Run ARM MCU */732 ret = s5c73m3_write(state, 0x30000004, 0xffff);733 if (ret < 0)734 return ret;735 usleep_range(400, 450);736 737 /* Check booting status */738 ret = s5c73m3_system_status_wait(state, 0x0c, 100, 4);739 if (ret < 0) {740 v4l2_err(sd, "Booting failed: %d\n", ret);741 return ret;742 }743 744 for (i = 0; i < ARRAY_SIZE(boot_regs); i++) {745 ret = s5c73m3_write(state, boot_regs[i][0], boot_regs[i][1]);746 if (ret < 0)747 return ret;748 }749 msleep(200);750 751 /* Check the binary read status */752 ret = s5c73m3_system_status_wait(state, 0x230e, 1000, 150);753 if (ret < 0) {754 v4l2_err(sd, "Binary read failed: %d\n", ret);755 return ret;756 }757 758 /* ARM reset */759 ret = s5c73m3_write(state, 0x30000004, 0xfffd);760 if (ret < 0)761 return ret;762 /* Remap */763 ret = s5c73m3_write(state, 0x301000a4, 0x0183);764 if (ret < 0)765 return ret;766 /* MCU re-start */767 ret = s5c73m3_write(state, 0x30000004, 0xffff);768 if (ret < 0)769 return ret;770 771 state->isp_ready = 1;772 773 return s5c73m3_read_fw_version(state);774}775 776static int s5c73m3_isp_init(struct s5c73m3 *state)777{778 int ret;779 780 state->i2c_read_address = 0;781 state->i2c_write_address = 0;782 783 ret = s5c73m3_i2c_write(state->i2c_client, AHB_MSB_ADDR_PTR, 0x3310);784 if (ret < 0)785 return ret;786 787 if (boot_from_rom)788 return s5c73m3_rom_boot(state, true);789 else790 return s5c73m3_spi_boot(state, true);791}792 793static const struct s5c73m3_frame_size *s5c73m3_find_frame_size(794 struct v4l2_mbus_framefmt *fmt,795 enum s5c73m3_resolution_types idx)796{797 const struct s5c73m3_frame_size *fs;798 const struct s5c73m3_frame_size *best_fs;799 int best_dist = INT_MAX;800 int i;801 802 fs = s5c73m3_resolutions[idx];803 best_fs = NULL;804 for (i = 0; i < s5c73m3_resolutions_len[idx]; ++i) {805 int dist = abs(fs->width - fmt->width) +806 abs(fs->height - fmt->height);807 if (dist < best_dist) {808 best_dist = dist;809 best_fs = fs;810 }811 ++fs;812 }813 814 return best_fs;815}816 817static void s5c73m3_oif_try_format(struct s5c73m3 *state,818 struct v4l2_subdev_state *sd_state,819 struct v4l2_subdev_format *fmt,820 const struct s5c73m3_frame_size **fs)821{822 u32 code;823 824 switch (fmt->pad) {825 case OIF_ISP_PAD:826 *fs = s5c73m3_find_frame_size(&fmt->format, RES_ISP);827 code = S5C73M3_ISP_FMT;828 break;829 case OIF_JPEG_PAD:830 *fs = s5c73m3_find_frame_size(&fmt->format, RES_JPEG);831 code = S5C73M3_JPEG_FMT;832 break;833 case OIF_SOURCE_PAD:834 default:835 if (fmt->format.code == S5C73M3_JPEG_FMT)836 code = S5C73M3_JPEG_FMT;837 else838 code = S5C73M3_ISP_FMT;839 840 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)841 *fs = state->oif_pix_size[RES_ISP];842 else843 *fs = s5c73m3_find_frame_size(v4l2_subdev_state_get_format(sd_state, OIF_ISP_PAD),844 RES_ISP);845 break;846 }847 848 s5c73m3_fill_mbus_fmt(&fmt->format, *fs, code);849}850 851static void s5c73m3_try_format(struct s5c73m3 *state,852 struct v4l2_subdev_state *sd_state,853 struct v4l2_subdev_format *fmt,854 const struct s5c73m3_frame_size **fs)855{856 u32 code;857 858 if (fmt->pad == S5C73M3_ISP_PAD) {859 *fs = s5c73m3_find_frame_size(&fmt->format, RES_ISP);860 code = S5C73M3_ISP_FMT;861 } else {862 *fs = s5c73m3_find_frame_size(&fmt->format, RES_JPEG);863 code = S5C73M3_JPEG_FMT;864 }865 866 s5c73m3_fill_mbus_fmt(&fmt->format, *fs, code);867}868 869static int s5c73m3_oif_get_frame_interval(struct v4l2_subdev *sd,870 struct v4l2_subdev_state *sd_state,871 struct v4l2_subdev_frame_interval *fi)872{873 struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);874 875 /*876 * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2877 * subdev active state API.878 */879 if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)880 return -EINVAL;881 882 if (fi->pad != OIF_SOURCE_PAD)883 return -EINVAL;884 885 mutex_lock(&state->lock);886 fi->interval = state->fiv->interval;887 mutex_unlock(&state->lock);888 889 return 0;890}891 892static int __s5c73m3_set_frame_interval(struct s5c73m3 *state,893 struct v4l2_subdev_frame_interval *fi)894{895 const struct s5c73m3_frame_size *prev_size =896 state->sensor_pix_size[RES_ISP];897 const struct s5c73m3_interval *fiv = &s5c73m3_intervals[0];898 unsigned int ret, min_err = UINT_MAX;899 unsigned int i, fr_time;900 901 if (fi->interval.denominator == 0)902 return -EINVAL;903 904 fr_time = fi->interval.numerator * 1000 / fi->interval.denominator;905 906 for (i = 0; i < ARRAY_SIZE(s5c73m3_intervals); i++) {907 const struct s5c73m3_interval *iv = &s5c73m3_intervals[i];908 909 if (prev_size->width > iv->size.width ||910 prev_size->height > iv->size.height)911 continue;912 913 ret = abs(iv->interval.numerator / 1000 - fr_time);914 if (ret < min_err) {915 fiv = iv;916 min_err = ret;917 }918 }919 state->fiv = fiv;920 921 v4l2_dbg(1, s5c73m3_dbg, &state->sensor_sd,922 "Changed frame interval to %u us\n", fiv->interval.numerator);923 return 0;924}925 926static int s5c73m3_oif_set_frame_interval(struct v4l2_subdev *sd,927 struct v4l2_subdev_state *sd_state,928 struct v4l2_subdev_frame_interval *fi)929{930 struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);931 int ret;932 933 /*934 * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2935 * subdev active state API.936 */937 if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)938 return -EINVAL;939 940 if (fi->pad != OIF_SOURCE_PAD)941 return -EINVAL;942 943 v4l2_dbg(1, s5c73m3_dbg, sd, "Setting %d/%d frame interval\n",944 fi->interval.numerator, fi->interval.denominator);945 946 mutex_lock(&state->lock);947 948 ret = __s5c73m3_set_frame_interval(state, fi);949 if (!ret) {950 if (state->streaming)951 ret = s5c73m3_set_frame_rate(state);952 else953 state->apply_fiv = 1;954 }955 mutex_unlock(&state->lock);956 return ret;957}958 959static int s5c73m3_oif_enum_frame_interval(struct v4l2_subdev *sd,960 struct v4l2_subdev_state *sd_state,961 struct v4l2_subdev_frame_interval_enum *fie)962{963 struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);964 const struct s5c73m3_interval *fi;965 int ret = 0;966 967 if (fie->pad != OIF_SOURCE_PAD)968 return -EINVAL;969 if (fie->index >= ARRAY_SIZE(s5c73m3_intervals))970 return -EINVAL;971 972 mutex_lock(&state->lock);973 fi = &s5c73m3_intervals[fie->index];974 if (fie->width > fi->size.width || fie->height > fi->size.height)975 ret = -EINVAL;976 else977 fie->interval = fi->interval;978 mutex_unlock(&state->lock);979 980 return ret;981}982 983static int s5c73m3_oif_get_pad_code(int pad, int index)984{985 if (pad == OIF_SOURCE_PAD) {986 if (index > 1)987 return -EINVAL;988 return (index == 0) ? S5C73M3_ISP_FMT : S5C73M3_JPEG_FMT;989 }990 991 if (index > 0)992 return -EINVAL;993 994 return (pad == OIF_ISP_PAD) ? S5C73M3_ISP_FMT : S5C73M3_JPEG_FMT;995}996 997static int s5c73m3_get_fmt(struct v4l2_subdev *sd,998 struct v4l2_subdev_state *sd_state,999 struct v4l2_subdev_format *fmt)1000{1001 struct s5c73m3 *state = sensor_sd_to_s5c73m3(sd);1002 const struct s5c73m3_frame_size *fs;1003 u32 code;1004 1005 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {1006 fmt->format = *v4l2_subdev_state_get_format(sd_state,1007 fmt->pad);1008 return 0;1009 }1010 1011 mutex_lock(&state->lock);1012 1013 switch (fmt->pad) {1014 case S5C73M3_ISP_PAD:1015 code = S5C73M3_ISP_FMT;1016 fs = state->sensor_pix_size[RES_ISP];1017 break;1018 case S5C73M3_JPEG_PAD:1019 code = S5C73M3_JPEG_FMT;1020 fs = state->sensor_pix_size[RES_JPEG];1021 break;1022 default:1023 mutex_unlock(&state->lock);1024 return -EINVAL;1025 }1026 s5c73m3_fill_mbus_fmt(&fmt->format, fs, code);1027 1028 mutex_unlock(&state->lock);1029 return 0;1030}1031 1032static int s5c73m3_oif_get_fmt(struct v4l2_subdev *sd,1033 struct v4l2_subdev_state *sd_state,1034 struct v4l2_subdev_format *fmt)1035{1036 struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);1037 const struct s5c73m3_frame_size *fs;1038 u32 code;1039 1040 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {1041 fmt->format = *v4l2_subdev_state_get_format(sd_state,1042 fmt->pad);1043 return 0;1044 }1045 1046 mutex_lock(&state->lock);1047 1048 switch (fmt->pad) {1049 case OIF_ISP_PAD:1050 code = S5C73M3_ISP_FMT;1051 fs = state->oif_pix_size[RES_ISP];1052 break;1053 case OIF_JPEG_PAD:1054 code = S5C73M3_JPEG_FMT;1055 fs = state->oif_pix_size[RES_JPEG];1056 break;1057 case OIF_SOURCE_PAD:1058 code = state->mbus_code;1059 fs = state->oif_pix_size[RES_ISP];1060 break;1061 default:1062 mutex_unlock(&state->lock);1063 return -EINVAL;1064 }1065 s5c73m3_fill_mbus_fmt(&fmt->format, fs, code);1066 1067 mutex_unlock(&state->lock);1068 return 0;1069}1070 1071static int s5c73m3_set_fmt(struct v4l2_subdev *sd,1072 struct v4l2_subdev_state *sd_state,1073 struct v4l2_subdev_format *fmt)1074{1075 const struct s5c73m3_frame_size *frame_size = NULL;1076 struct s5c73m3 *state = sensor_sd_to_s5c73m3(sd);1077 struct v4l2_mbus_framefmt *mf;1078 int ret = 0;1079 1080 mutex_lock(&state->lock);1081 1082 s5c73m3_try_format(state, sd_state, fmt, &frame_size);1083 1084 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {1085 mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);1086 *mf = fmt->format;1087 } else {1088 switch (fmt->pad) {1089 case S5C73M3_ISP_PAD:1090 state->sensor_pix_size[RES_ISP] = frame_size;1091 break;1092 case S5C73M3_JPEG_PAD:1093 state->sensor_pix_size[RES_JPEG] = frame_size;1094 break;1095 default:1096 ret = -EBUSY;1097 }1098 1099 if (state->streaming)1100 ret = -EBUSY;1101 else1102 state->apply_fmt = 1;1103 }1104 1105 mutex_unlock(&state->lock);1106 1107 return ret;1108}1109 1110static int s5c73m3_oif_set_fmt(struct v4l2_subdev *sd,1111 struct v4l2_subdev_state *sd_state,1112 struct v4l2_subdev_format *fmt)1113{1114 const struct s5c73m3_frame_size *frame_size = NULL;1115 struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);1116 struct v4l2_mbus_framefmt *mf;1117 int ret = 0;1118 1119 mutex_lock(&state->lock);1120 1121 s5c73m3_oif_try_format(state, sd_state, fmt, &frame_size);1122 1123 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {1124 mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);1125 *mf = fmt->format;1126 if (fmt->pad == OIF_ISP_PAD) {1127 mf = v4l2_subdev_state_get_format(sd_state,1128 OIF_SOURCE_PAD);1129 mf->width = fmt->format.width;1130 mf->height = fmt->format.height;1131 }1132 } else {1133 switch (fmt->pad) {1134 case OIF_ISP_PAD:1135 state->oif_pix_size[RES_ISP] = frame_size;1136 break;1137 case OIF_JPEG_PAD:1138 state->oif_pix_size[RES_JPEG] = frame_size;1139 break;1140 case OIF_SOURCE_PAD:1141 state->mbus_code = fmt->format.code;1142 break;1143 default:1144 ret = -EBUSY;1145 }1146 1147 if (state->streaming)1148 ret = -EBUSY;1149 else1150 state->apply_fmt = 1;1151 }1152 1153 mutex_unlock(&state->lock);1154 1155 return ret;1156}1157 1158static int s5c73m3_oif_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,1159 struct v4l2_mbus_frame_desc *fd)1160{1161 struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);1162 int i;1163 1164 if (pad != OIF_SOURCE_PAD || fd == NULL)1165 return -EINVAL;1166 1167 mutex_lock(&state->lock);1168 fd->num_entries = 2;1169 for (i = 0; i < fd->num_entries; i++)1170 fd->entry[i] = state->frame_desc.entry[i];1171 mutex_unlock(&state->lock);1172 1173 return 0;1174}1175 1176static int s5c73m3_oif_set_frame_desc(struct v4l2_subdev *sd, unsigned int pad,1177 struct v4l2_mbus_frame_desc *fd)1178{1179 struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);1180 struct v4l2_mbus_frame_desc *frame_desc = &state->frame_desc;1181 int i;1182 1183 if (pad != OIF_SOURCE_PAD || fd == NULL)1184 return -EINVAL;1185 1186 fd->entry[0].length = 10 * SZ_1M;1187 fd->entry[1].length = max_t(u32, fd->entry[1].length,1188 S5C73M3_EMBEDDED_DATA_MAXLEN);1189 fd->num_entries = 2;1190 1191 mutex_lock(&state->lock);1192 for (i = 0; i < fd->num_entries; i++)1193 frame_desc->entry[i] = fd->entry[i];1194 mutex_unlock(&state->lock);1195 1196 return 0;1197}1198 1199static int s5c73m3_enum_mbus_code(struct v4l2_subdev *sd,1200 struct v4l2_subdev_state *sd_state,1201 struct v4l2_subdev_mbus_code_enum *code)1202{1203 static const int codes[] = {1204 [S5C73M3_ISP_PAD] = S5C73M3_ISP_FMT,1205 [S5C73M3_JPEG_PAD] = S5C73M3_JPEG_FMT};1206 1207 if (code->index > 0 || code->pad >= S5C73M3_NUM_PADS)1208 return -EINVAL;1209 1210 code->code = codes[code->pad];1211 1212 return 0;1213}1214 1215static int s5c73m3_oif_enum_mbus_code(struct v4l2_subdev *sd,1216 struct v4l2_subdev_state *sd_state,1217 struct v4l2_subdev_mbus_code_enum *code)1218{1219 int ret;1220 1221 ret = s5c73m3_oif_get_pad_code(code->pad, code->index);1222 if (ret < 0)1223 return ret;1224 1225 code->code = ret;1226 1227 return 0;1228}1229 1230static int s5c73m3_enum_frame_size(struct v4l2_subdev *sd,1231 struct v4l2_subdev_state *sd_state,1232 struct v4l2_subdev_frame_size_enum *fse)1233{1234 int idx;1235 1236 if (fse->pad == S5C73M3_ISP_PAD) {1237 if (fse->code != S5C73M3_ISP_FMT)1238 return -EINVAL;1239 idx = RES_ISP;1240 } else{1241 if (fse->code != S5C73M3_JPEG_FMT)1242 return -EINVAL;1243 idx = RES_JPEG;1244 }1245 1246 if (fse->index >= s5c73m3_resolutions_len[idx])1247 return -EINVAL;1248 1249 fse->min_width = s5c73m3_resolutions[idx][fse->index].width;1250 fse->max_width = fse->min_width;1251 fse->max_height = s5c73m3_resolutions[idx][fse->index].height;1252 fse->min_height = fse->max_height;1253 1254 return 0;1255}1256 1257static int s5c73m3_oif_enum_frame_size(struct v4l2_subdev *sd,1258 struct v4l2_subdev_state *sd_state,1259 struct v4l2_subdev_frame_size_enum *fse)1260{1261 struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);1262 int idx;1263 1264 if (fse->pad == OIF_SOURCE_PAD) {1265 if (fse->index > 0)1266 return -EINVAL;1267 1268 switch (fse->code) {1269 case S5C73M3_JPEG_FMT:1270 case S5C73M3_ISP_FMT: {1271 unsigned w, h;1272 1273 if (fse->which == V4L2_SUBDEV_FORMAT_TRY) {1274 struct v4l2_mbus_framefmt *mf;1275 1276 mf = v4l2_subdev_state_get_format(sd_state,1277 OIF_ISP_PAD);1278 1279 w = mf->width;1280 h = mf->height;1281 } else {1282 const struct s5c73m3_frame_size *fs;1283 1284 fs = state->oif_pix_size[RES_ISP];1285 w = fs->width;1286 h = fs->height;1287 }1288 fse->max_width = fse->min_width = w;1289 fse->max_height = fse->min_height = h;1290 return 0;1291 }1292 default:1293 return -EINVAL;1294 }1295 }1296 1297 if (fse->code != s5c73m3_oif_get_pad_code(fse->pad, 0))1298 return -EINVAL;1299 1300 if (fse->pad == OIF_JPEG_PAD)1301 idx = RES_JPEG;1302 else1303 idx = RES_ISP;1304 1305 if (fse->index >= s5c73m3_resolutions_len[idx])1306 return -EINVAL;1307 1308 fse->min_width = s5c73m3_resolutions[idx][fse->index].width;1309 fse->max_width = fse->min_width;1310 fse->max_height = s5c73m3_resolutions[idx][fse->index].height;1311 fse->min_height = fse->max_height;1312 1313 return 0;1314}1315 1316static int s5c73m3_oif_log_status(struct v4l2_subdev *sd)1317{1318 struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);1319 1320 v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name);1321 1322 v4l2_info(sd, "power: %d, apply_fmt: %d\n", state->power,1323 state->apply_fmt);1324 1325 return 0;1326}1327 1328static int s5c73m3_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)1329{1330 struct v4l2_mbus_framefmt *mf;1331 1332 mf = v4l2_subdev_state_get_format(fh->state, S5C73M3_ISP_PAD);1333 s5c73m3_fill_mbus_fmt(mf, &s5c73m3_isp_resolutions[1],1334 S5C73M3_ISP_FMT);1335 1336 mf = v4l2_subdev_state_get_format(fh->state, S5C73M3_JPEG_PAD);1337 s5c73m3_fill_mbus_fmt(mf, &s5c73m3_jpeg_resolutions[1],1338 S5C73M3_JPEG_FMT);1339 1340 return 0;1341}1342 1343static int s5c73m3_oif_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)1344{1345 struct v4l2_mbus_framefmt *mf;1346 1347 mf = v4l2_subdev_state_get_format(fh->state, OIF_ISP_PAD);1348 s5c73m3_fill_mbus_fmt(mf, &s5c73m3_isp_resolutions[1],1349 S5C73M3_ISP_FMT);1350 1351 mf = v4l2_subdev_state_get_format(fh->state, OIF_JPEG_PAD);1352 s5c73m3_fill_mbus_fmt(mf, &s5c73m3_jpeg_resolutions[1],1353 S5C73M3_JPEG_FMT);1354 1355 mf = v4l2_subdev_state_get_format(fh->state, OIF_SOURCE_PAD);1356 s5c73m3_fill_mbus_fmt(mf, &s5c73m3_isp_resolutions[1],1357 S5C73M3_ISP_FMT);1358 return 0;1359}1360 1361static int __s5c73m3_power_on(struct s5c73m3 *state)1362{1363 int i, ret;1364 1365 for (i = 0; i < S5C73M3_MAX_SUPPLIES; i++) {1366 ret = regulator_enable(state->supplies[i].consumer);1367 if (ret)1368 goto err_reg_dis;1369 }1370 1371 ret = clk_set_rate(state->clock, state->mclk_frequency);1372 if (ret < 0)1373 goto err_reg_dis;1374 1375 ret = clk_prepare_enable(state->clock);1376 if (ret < 0)1377 goto err_reg_dis;1378 1379 v4l2_dbg(1, s5c73m3_dbg, &state->oif_sd, "clock frequency: %ld\n",1380 clk_get_rate(state->clock));1381 1382 gpiod_set_value(state->stby, 0);1383 usleep_range(100, 200);1384 gpiod_set_value(state->reset, 0);1385 usleep_range(50, 100);1386 1387 return 0;1388 1389err_reg_dis:1390 for (--i; i >= 0; i--)1391 regulator_disable(state->supplies[i].consumer);1392 return ret;1393}1394 1395/*1396 * This function has been created just to avoid a smatch warning,1397 * please do not merge into __s5c73m3_power_off() until you have1398 * confirmed that it does not introduce a new warning.1399 */1400static void s5c73m3_enable_clk(struct s5c73m3 *state)1401{1402 clk_prepare_enable(state->clock);1403}1404 1405static int __s5c73m3_power_off(struct s5c73m3 *state)1406{1407 int i, ret;1408 1409 gpiod_set_value(state->reset, 1);1410 usleep_range(10, 50);1411 gpiod_set_value(state->stby, 1);1412 usleep_range(100, 200);1413 1414 clk_disable_unprepare(state->clock);1415 1416 state->streaming = 0;1417 state->isp_ready = 0;1418 1419 for (i = S5C73M3_MAX_SUPPLIES - 1; i >= 0; i--) {1420 ret = regulator_disable(state->supplies[i].consumer);1421 if (ret)1422 goto err;1423 }1424 1425 return 0;1426err:1427 for (++i; i < S5C73M3_MAX_SUPPLIES; i++) {1428 int r = regulator_enable(state->supplies[i].consumer);1429 if (r < 0)1430 v4l2_err(&state->oif_sd, "Failed to re-enable %s: %d\n",1431 state->supplies[i].supply, r);1432 }1433 1434 s5c73m3_enable_clk(state);1435 1436 return ret;1437}1438 1439static int s5c73m3_oif_set_power(struct v4l2_subdev *sd, int on)1440{1441 struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);1442 int ret = 0;1443 1444 mutex_lock(&state->lock);1445 1446 if (on && !state->power) {1447 ret = __s5c73m3_power_on(state);1448 if (!ret)1449 ret = s5c73m3_isp_init(state);1450 if (!ret) {1451 state->apply_fiv = 1;1452 state->apply_fmt = 1;1453 }1454 } else if (state->power == !on) {1455 ret = s5c73m3_set_af_softlanding(state);1456 if (!ret)1457 ret = __s5c73m3_power_off(state);1458 else1459 v4l2_err(sd, "Soft landing lens failed\n");1460 }1461 if (!ret)1462 state->power += on ? 1 : -1;1463 1464 v4l2_dbg(1, s5c73m3_dbg, sd, "%s: power: %d\n",1465 __func__, state->power);1466 1467 mutex_unlock(&state->lock);1468 return ret;1469}1470 1471static int s5c73m3_oif_registered(struct v4l2_subdev *sd)1472{1473 struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);1474 int ret;1475 1476 ret = v4l2_device_register_subdev(sd->v4l2_dev, &state->sensor_sd);1477 if (ret) {1478 v4l2_err(sd->v4l2_dev, "Failed to register %s\n",1479 state->oif_sd.name);1480 return ret;1481 }1482 1483 ret = media_create_pad_link(&state->sensor_sd.entity,1484 S5C73M3_ISP_PAD, &state->oif_sd.entity, OIF_ISP_PAD,1485 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);1486 1487 ret = media_create_pad_link(&state->sensor_sd.entity,1488 S5C73M3_JPEG_PAD, &state->oif_sd.entity, OIF_JPEG_PAD,1489 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);1490 1491 return ret;1492}1493 1494static void s5c73m3_oif_unregistered(struct v4l2_subdev *sd)1495{1496 struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);1497 v4l2_device_unregister_subdev(&state->sensor_sd);1498}1499 1500static const struct v4l2_subdev_internal_ops s5c73m3_internal_ops = {1501 .open = s5c73m3_open,1502};1503 1504static const struct v4l2_subdev_pad_ops s5c73m3_pad_ops = {1505 .enum_mbus_code = s5c73m3_enum_mbus_code,1506 .enum_frame_size = s5c73m3_enum_frame_size,1507 .get_fmt = s5c73m3_get_fmt,1508 .set_fmt = s5c73m3_set_fmt,1509};1510 1511static const struct v4l2_subdev_ops s5c73m3_subdev_ops = {1512 .pad = &s5c73m3_pad_ops,1513};1514 1515static const struct v4l2_subdev_internal_ops oif_internal_ops = {1516 .registered = s5c73m3_oif_registered,1517 .unregistered = s5c73m3_oif_unregistered,1518 .open = s5c73m3_oif_open,1519};1520 1521static const struct v4l2_subdev_pad_ops s5c73m3_oif_pad_ops = {1522 .enum_mbus_code = s5c73m3_oif_enum_mbus_code,1523 .enum_frame_size = s5c73m3_oif_enum_frame_size,1524 .enum_frame_interval = s5c73m3_oif_enum_frame_interval,1525 .get_fmt = s5c73m3_oif_get_fmt,1526 .set_fmt = s5c73m3_oif_set_fmt,1527 .get_frame_interval = s5c73m3_oif_get_frame_interval,1528 .set_frame_interval = s5c73m3_oif_set_frame_interval,1529 .get_frame_desc = s5c73m3_oif_get_frame_desc,1530 .set_frame_desc = s5c73m3_oif_set_frame_desc,1531};1532 1533static const struct v4l2_subdev_core_ops s5c73m3_oif_core_ops = {1534 .s_power = s5c73m3_oif_set_power,1535 .log_status = s5c73m3_oif_log_status,1536};1537 1538static const struct v4l2_subdev_video_ops s5c73m3_oif_video_ops = {1539 .s_stream = s5c73m3_oif_s_stream,1540};1541 1542static const struct v4l2_subdev_ops oif_subdev_ops = {1543 .core = &s5c73m3_oif_core_ops,1544 .pad = &s5c73m3_oif_pad_ops,1545 .video = &s5c73m3_oif_video_ops,1546};1547 1548static int s5c73m3_get_dt_data(struct s5c73m3 *state)1549{1550 struct device *dev = &state->i2c_client->dev;1551 struct device_node *node = dev->of_node;1552 struct device_node *node_ep;1553 struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };1554 int ret;1555 1556 if (!node)1557 return -EINVAL;1558 1559 state->clock = devm_clk_get(dev, S5C73M3_CLK_NAME);1560 if (IS_ERR(state->clock))1561 return PTR_ERR(state->clock);1562 1563 if (of_property_read_u32(node, "clock-frequency",1564 &state->mclk_frequency)) {1565 state->mclk_frequency = S5C73M3_DEFAULT_MCLK_FREQ;1566 dev_info(dev, "using default %u Hz clock frequency\n",1567 state->mclk_frequency);1568 }1569 1570 /* Request GPIO lines asserted */1571 state->stby = devm_gpiod_get(dev, "standby", GPIOD_OUT_HIGH);1572 if (IS_ERR(state->stby))1573 return dev_err_probe(dev, PTR_ERR(state->stby),1574 "failed to request gpio S5C73M3_STBY\n");1575 gpiod_set_consumer_name(state->stby, "S5C73M3_STBY");1576 state->reset = devm_gpiod_get(dev, "xshutdown", GPIOD_OUT_HIGH);1577 if (IS_ERR(state->reset))1578 return dev_err_probe(dev, PTR_ERR(state->reset),1579 "failed to request gpio S5C73M3_RST\n");1580 gpiod_set_consumer_name(state->reset, "S5C73M3_RST");1581 1582 node_ep = of_graph_get_endpoint_by_regs(node, 0, -1);1583 if (!node_ep) {1584 dev_warn(dev, "no endpoint defined for node: %pOF\n", node);1585 return 0;1586 }1587 1588 ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(node_ep), &ep);1589 of_node_put(node_ep);1590 if (ret)1591 return ret;1592 1593 if (ep.bus_type != V4L2_MBUS_CSI2_DPHY) {1594 dev_err(dev, "unsupported bus type\n");1595 return -EINVAL;1596 }1597 /*1598 * Number of MIPI CSI-2 data lanes is currently not configurable,1599 * always a default value of 4 lanes is used.1600 */1601 if (ep.bus.mipi_csi2.num_data_lanes != S5C73M3_MIPI_DATA_LANES)1602 dev_info(dev, "falling back to 4 MIPI CSI-2 data lanes\n");1603 1604 return 0;1605}1606 1607static int s5c73m3_probe(struct i2c_client *client)1608{1609 struct device *dev = &client->dev;1610 struct v4l2_subdev *sd;1611 struct v4l2_subdev *oif_sd;1612 struct s5c73m3 *state;1613 int ret, i;1614 1615 state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);1616 if (!state)1617 return -ENOMEM;1618 1619 state->i2c_client = client;1620 ret = s5c73m3_get_dt_data(state);1621 if (ret < 0)1622 return ret;1623 1624 mutex_init(&state->lock);1625 sd = &state->sensor_sd;1626 oif_sd = &state->oif_sd;1627 1628 v4l2_subdev_init(sd, &s5c73m3_subdev_ops);1629 sd->owner = client->dev.driver->owner;1630 v4l2_set_subdevdata(sd, state);1631 strscpy(sd->name, "S5C73M3", sizeof(sd->name));1632 1633 sd->internal_ops = &s5c73m3_internal_ops;1634 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;1635 1636 state->sensor_pads[S5C73M3_JPEG_PAD].flags = MEDIA_PAD_FL_SOURCE;1637 state->sensor_pads[S5C73M3_ISP_PAD].flags = MEDIA_PAD_FL_SOURCE;1638 sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;1639 1640 ret = media_entity_pads_init(&sd->entity, S5C73M3_NUM_PADS,1641 state->sensor_pads);1642 if (ret < 0)1643 return ret;1644 1645 v4l2_i2c_subdev_init(oif_sd, client, &oif_subdev_ops);1646 /* Static name; NEVER use in new drivers! */1647 strscpy(oif_sd->name, "S5C73M3-OIF", sizeof(oif_sd->name));1648 1649 oif_sd->internal_ops = &oif_internal_ops;1650 oif_sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;1651 1652 state->oif_pads[OIF_ISP_PAD].flags = MEDIA_PAD_FL_SINK;1653 state->oif_pads[OIF_JPEG_PAD].flags = MEDIA_PAD_FL_SINK;1654 state->oif_pads[OIF_SOURCE_PAD].flags = MEDIA_PAD_FL_SOURCE;1655 oif_sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER;1656 1657 ret = media_entity_pads_init(&oif_sd->entity, OIF_NUM_PADS,1658 state->oif_pads);1659 if (ret < 0)1660 return ret;1661 1662 for (i = 0; i < S5C73M3_MAX_SUPPLIES; i++)1663 state->supplies[i].supply = s5c73m3_supply_names[i];1664 1665 ret = devm_regulator_bulk_get(dev, S5C73M3_MAX_SUPPLIES,1666 state->supplies);1667 if (ret) {1668 dev_err(dev, "failed to get regulators\n");1669 goto out_err;1670 }1671 1672 ret = s5c73m3_init_controls(state);1673 if (ret)1674 goto out_err;1675 1676 state->sensor_pix_size[RES_ISP] = &s5c73m3_isp_resolutions[1];1677 state->sensor_pix_size[RES_JPEG] = &s5c73m3_jpeg_resolutions[1];1678 state->oif_pix_size[RES_ISP] = state->sensor_pix_size[RES_ISP];1679 state->oif_pix_size[RES_JPEG] = state->sensor_pix_size[RES_JPEG];1680 1681 state->mbus_code = S5C73M3_ISP_FMT;1682 1683 state->fiv = &s5c73m3_intervals[S5C73M3_DEFAULT_FRAME_INTERVAL];1684 1685 state->fw_file_version[0] = 'G';1686 state->fw_file_version[1] = 'C';1687 1688 ret = s5c73m3_register_spi_driver(state);1689 if (ret < 0)1690 goto out_err;1691 1692 oif_sd->dev = dev;1693 1694 ret = __s5c73m3_power_on(state);1695 if (ret < 0)1696 goto out_err1;1697 1698 ret = s5c73m3_get_fw_version(state);1699 __s5c73m3_power_off(state);1700 1701 if (ret < 0) {1702 dev_err(dev, "Device detection failed: %d\n", ret);1703 goto out_err1;1704 }1705 1706 ret = v4l2_async_register_subdev(oif_sd);1707 if (ret < 0)1708 goto out_err1;1709 1710 v4l2_info(sd, "%s: completed successfully\n", __func__);1711 return 0;1712 1713out_err1:1714 s5c73m3_unregister_spi_driver(state);1715out_err:1716 media_entity_cleanup(&sd->entity);1717 return ret;1718}1719 1720static void s5c73m3_remove(struct i2c_client *client)1721{1722 struct v4l2_subdev *oif_sd = i2c_get_clientdata(client);1723 struct s5c73m3 *state = oif_sd_to_s5c73m3(oif_sd);1724 struct v4l2_subdev *sensor_sd = &state->sensor_sd;1725 1726 v4l2_async_unregister_subdev(oif_sd);1727 1728 v4l2_ctrl_handler_free(oif_sd->ctrl_handler);1729 media_entity_cleanup(&oif_sd->entity);1730 1731 v4l2_device_unregister_subdev(sensor_sd);1732 media_entity_cleanup(&sensor_sd->entity);1733 1734 s5c73m3_unregister_spi_driver(state);1735}1736 1737static const struct i2c_device_id s5c73m3_id[] = {1738 { DRIVER_NAME },1739 { }1740};1741MODULE_DEVICE_TABLE(i2c, s5c73m3_id);1742 1743#ifdef CONFIG_OF1744static const struct of_device_id s5c73m3_of_match[] = {1745 { .compatible = "samsung,s5c73m3" },1746 { }1747};1748MODULE_DEVICE_TABLE(of, s5c73m3_of_match);1749#endif1750 1751static struct i2c_driver s5c73m3_i2c_driver = {1752 .driver = {1753 .of_match_table = of_match_ptr(s5c73m3_of_match),1754 .name = DRIVER_NAME,1755 },1756 .probe = s5c73m3_probe,1757 .remove = s5c73m3_remove,1758 .id_table = s5c73m3_id,1759};1760 1761module_i2c_driver(s5c73m3_i2c_driver);1762 1763MODULE_DESCRIPTION("Samsung S5C73M3 camera driver");1764MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");1765MODULE_LICENSE("GPL");1766