18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Driver for the mt9m111 sensor 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2008 Erik Andrén 68c2ecf20Sopenharmony_ci * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. 78c2ecf20Sopenharmony_ci * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Portions of code to USB interface and ALi driver software, 108c2ecf20Sopenharmony_ci * Copyright (c) 2006 Willem Duinker 118c2ecf20Sopenharmony_ci * v4l2 interface modeled after the V4L2 driver 128c2ecf20Sopenharmony_ci * for SN9C10x PC Camera Controllers 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "m5602_mt9m111.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl); 208c2ecf20Sopenharmony_cistatic void mt9m111_dump_registers(struct sd *sd); 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic const unsigned char preinit_mt9m111[][4] = { 238c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, 248c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, 258c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, 268c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, 278c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, 288c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, 298c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, 308c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, 338c2ecf20Sopenharmony_ci {SENSOR, MT9M111_SC_RESET, 348c2ecf20Sopenharmony_ci MT9M111_RESET | 358c2ecf20Sopenharmony_ci MT9M111_RESTART | 368c2ecf20Sopenharmony_ci MT9M111_ANALOG_STANDBY | 378c2ecf20Sopenharmony_ci MT9M111_CHIP_DISABLE, 388c2ecf20Sopenharmony_ci MT9M111_SHOW_BAD_FRAMES | 398c2ecf20Sopenharmony_ci MT9M111_RESTART_BAD_FRAMES | 408c2ecf20Sopenharmony_ci MT9M111_SYNCHRONIZE_CHANGES}, 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, 438c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, 448c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, 458c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, 468c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, 478c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, 488c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, 498c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, 528c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, 538c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, 548c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, 558c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, 568c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00} 598c2ecf20Sopenharmony_ci}; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic const unsigned char init_mt9m111[][4] = { 628c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, 638c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, 648c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, 658c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, 668c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, 678c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, 708c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, 718c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, 728c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, 738c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, 748c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, 758c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, 768c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, 778c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, 788c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, 818c2ecf20Sopenharmony_ci {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, 828c2ecf20Sopenharmony_ci {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, 838c2ecf20Sopenharmony_ci {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, 848c2ecf20Sopenharmony_ci {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 858c2ecf20Sopenharmony_ci MT9M111_CP_OPERATING_MODE_CTL}, 868c2ecf20Sopenharmony_ci {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, 878c2ecf20Sopenharmony_ci {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 888c2ecf20Sopenharmony_ci MT9M111_2D_DEFECT_CORRECTION_ENABLE}, 898c2ecf20Sopenharmony_ci {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 908c2ecf20Sopenharmony_ci MT9M111_2D_DEFECT_CORRECTION_ENABLE}, 918c2ecf20Sopenharmony_ci {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, 928c2ecf20Sopenharmony_ci {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, 938c2ecf20Sopenharmony_ci {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, 948c2ecf20Sopenharmony_ci {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, 958c2ecf20Sopenharmony_ci {SENSOR, 0xcd, 0x00, 0x0e}, 968c2ecf20Sopenharmony_ci {SENSOR, 0xd0, 0x00, 0x40}, 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, 998c2ecf20Sopenharmony_ci {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, 1008c2ecf20Sopenharmony_ci {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, 1038c2ecf20Sopenharmony_ci {SENSOR, 0x33, 0x03, 0x49}, 1048c2ecf20Sopenharmony_ci {SENSOR, 0x34, 0xc0, 0x19}, 1058c2ecf20Sopenharmony_ci {SENSOR, 0x3f, 0x20, 0x20}, 1068c2ecf20Sopenharmony_ci {SENSOR, 0x40, 0x20, 0x20}, 1078c2ecf20Sopenharmony_ci {SENSOR, 0x5a, 0xc0, 0x0a}, 1088c2ecf20Sopenharmony_ci {SENSOR, 0x70, 0x7b, 0x0a}, 1098c2ecf20Sopenharmony_ci {SENSOR, 0x71, 0xff, 0x00}, 1108c2ecf20Sopenharmony_ci {SENSOR, 0x72, 0x19, 0x0e}, 1118c2ecf20Sopenharmony_ci {SENSOR, 0x73, 0x18, 0x0f}, 1128c2ecf20Sopenharmony_ci {SENSOR, 0x74, 0x57, 0x32}, 1138c2ecf20Sopenharmony_ci {SENSOR, 0x75, 0x56, 0x34}, 1148c2ecf20Sopenharmony_ci {SENSOR, 0x76, 0x73, 0x35}, 1158c2ecf20Sopenharmony_ci {SENSOR, 0x77, 0x30, 0x12}, 1168c2ecf20Sopenharmony_ci {SENSOR, 0x78, 0x79, 0x02}, 1178c2ecf20Sopenharmony_ci {SENSOR, 0x79, 0x75, 0x06}, 1188c2ecf20Sopenharmony_ci {SENSOR, 0x7a, 0x77, 0x0a}, 1198c2ecf20Sopenharmony_ci {SENSOR, 0x7b, 0x78, 0x09}, 1208c2ecf20Sopenharmony_ci {SENSOR, 0x7c, 0x7d, 0x06}, 1218c2ecf20Sopenharmony_ci {SENSOR, 0x7d, 0x31, 0x10}, 1228c2ecf20Sopenharmony_ci {SENSOR, 0x7e, 0x00, 0x7e}, 1238c2ecf20Sopenharmony_ci {SENSOR, 0x80, 0x59, 0x04}, 1248c2ecf20Sopenharmony_ci {SENSOR, 0x81, 0x59, 0x04}, 1258c2ecf20Sopenharmony_ci {SENSOR, 0x82, 0x57, 0x0a}, 1268c2ecf20Sopenharmony_ci {SENSOR, 0x83, 0x58, 0x0b}, 1278c2ecf20Sopenharmony_ci {SENSOR, 0x84, 0x47, 0x0c}, 1288c2ecf20Sopenharmony_ci {SENSOR, 0x85, 0x48, 0x0e}, 1298c2ecf20Sopenharmony_ci {SENSOR, 0x86, 0x5b, 0x02}, 1308c2ecf20Sopenharmony_ci {SENSOR, 0x87, 0x00, 0x5c}, 1318c2ecf20Sopenharmony_ci {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, MT9M111_SEL_CONTEXT_B}, 1328c2ecf20Sopenharmony_ci {SENSOR, 0x60, 0x00, 0x80}, 1338c2ecf20Sopenharmony_ci {SENSOR, 0x61, 0x00, 0x00}, 1348c2ecf20Sopenharmony_ci {SENSOR, 0x62, 0x00, 0x00}, 1358c2ecf20Sopenharmony_ci {SENSOR, 0x63, 0x00, 0x00}, 1368c2ecf20Sopenharmony_ci {SENSOR, 0x64, 0x00, 0x00}, 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, /* 13 */ 1398c2ecf20Sopenharmony_ci {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, /* 18 */ 1408c2ecf20Sopenharmony_ci {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, /* 1024 */ 1418c2ecf20Sopenharmony_ci {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, /* 1296 */ 1428c2ecf20Sopenharmony_ci {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, /* 352 */ 1438c2ecf20Sopenharmony_ci {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, /* 17 */ 1448c2ecf20Sopenharmony_ci {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, /* 352 */ 1458c2ecf20Sopenharmony_ci {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, /* 17 */ 1468c2ecf20Sopenharmony_ci {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, /* 271 */ 1478c2ecf20Sopenharmony_ci {SENSOR, 0x30, 0x04, 0x00}, 1488c2ecf20Sopenharmony_ci /* Set number of blank rows chosen to 400 */ 1498c2ecf20Sopenharmony_ci {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90}, 1508c2ecf20Sopenharmony_ci}; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic const unsigned char start_mt9m111[][4] = { 1538c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, 1548c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, 1558c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, 1568c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, 1578c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, 1588c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, 1598c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, 1608c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, 1618c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, 1628c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, 1638c2ecf20Sopenharmony_ci {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, 1648c2ecf20Sopenharmony_ci}; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistatic struct v4l2_pix_format mt9m111_modes[] = { 1678c2ecf20Sopenharmony_ci { 1688c2ecf20Sopenharmony_ci 640, 1698c2ecf20Sopenharmony_ci 480, 1708c2ecf20Sopenharmony_ci V4L2_PIX_FMT_SBGGR8, 1718c2ecf20Sopenharmony_ci V4L2_FIELD_NONE, 1728c2ecf20Sopenharmony_ci .sizeimage = 640 * 480, 1738c2ecf20Sopenharmony_ci .bytesperline = 640, 1748c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 1758c2ecf20Sopenharmony_ci .priv = 0 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci}; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops mt9m111_ctrl_ops = { 1808c2ecf20Sopenharmony_ci .s_ctrl = mt9m111_s_ctrl, 1818c2ecf20Sopenharmony_ci}; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config mt9m111_greenbal_cfg = { 1848c2ecf20Sopenharmony_ci .ops = &mt9m111_ctrl_ops, 1858c2ecf20Sopenharmony_ci .id = M5602_V4L2_CID_GREEN_BALANCE, 1868c2ecf20Sopenharmony_ci .name = "Green Balance", 1878c2ecf20Sopenharmony_ci .type = V4L2_CTRL_TYPE_INTEGER, 1888c2ecf20Sopenharmony_ci .min = 0, 1898c2ecf20Sopenharmony_ci .max = 0x7ff, 1908c2ecf20Sopenharmony_ci .step = 1, 1918c2ecf20Sopenharmony_ci .def = MT9M111_GREEN_GAIN_DEFAULT, 1928c2ecf20Sopenharmony_ci .flags = V4L2_CTRL_FLAG_SLIDER, 1938c2ecf20Sopenharmony_ci}; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ciint mt9m111_probe(struct sd *sd) 1968c2ecf20Sopenharmony_ci{ 1978c2ecf20Sopenharmony_ci u8 data[2] = {0x00, 0x00}; 1988c2ecf20Sopenharmony_ci int i, err; 1998c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci if (force_sensor) { 2028c2ecf20Sopenharmony_ci if (force_sensor == MT9M111_SENSOR) { 2038c2ecf20Sopenharmony_ci pr_info("Forcing a %s sensor\n", mt9m111.name); 2048c2ecf20Sopenharmony_ci goto sensor_found; 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ci /* If we want to force another sensor, don't try to probe this 2078c2ecf20Sopenharmony_ci * one */ 2088c2ecf20Sopenharmony_ci return -ENODEV; 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Probing for a mt9m111 sensor\n"); 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci /* Do the preinit */ 2148c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) { 2158c2ecf20Sopenharmony_ci if (preinit_mt9m111[i][0] == BRIDGE) { 2168c2ecf20Sopenharmony_ci err = m5602_write_bridge(sd, 2178c2ecf20Sopenharmony_ci preinit_mt9m111[i][1], 2188c2ecf20Sopenharmony_ci preinit_mt9m111[i][2]); 2198c2ecf20Sopenharmony_ci } else { 2208c2ecf20Sopenharmony_ci data[0] = preinit_mt9m111[i][2]; 2218c2ecf20Sopenharmony_ci data[1] = preinit_mt9m111[i][3]; 2228c2ecf20Sopenharmony_ci err = m5602_write_sensor(sd, 2238c2ecf20Sopenharmony_ci preinit_mt9m111[i][1], data, 2); 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci if (err < 0) 2268c2ecf20Sopenharmony_ci return err; 2278c2ecf20Sopenharmony_ci } 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2)) 2308c2ecf20Sopenharmony_ci return -ENODEV; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci if ((data[0] == 0x14) && (data[1] == 0x3a)) { 2338c2ecf20Sopenharmony_ci pr_info("Detected a mt9m111 sensor\n"); 2348c2ecf20Sopenharmony_ci goto sensor_found; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci return -ENODEV; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_cisensor_found: 2408c2ecf20Sopenharmony_ci sd->gspca_dev.cam.cam_mode = mt9m111_modes; 2418c2ecf20Sopenharmony_ci sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci return 0; 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ciint mt9m111_init(struct sd *sd) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci int i, err = 0; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci /* Init the sensor */ 2518c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) { 2528c2ecf20Sopenharmony_ci u8 data[2]; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci if (init_mt9m111[i][0] == BRIDGE) { 2558c2ecf20Sopenharmony_ci err = m5602_write_bridge(sd, 2568c2ecf20Sopenharmony_ci init_mt9m111[i][1], 2578c2ecf20Sopenharmony_ci init_mt9m111[i][2]); 2588c2ecf20Sopenharmony_ci } else { 2598c2ecf20Sopenharmony_ci data[0] = init_mt9m111[i][2]; 2608c2ecf20Sopenharmony_ci data[1] = init_mt9m111[i][3]; 2618c2ecf20Sopenharmony_ci err = m5602_write_sensor(sd, 2628c2ecf20Sopenharmony_ci init_mt9m111[i][1], data, 2); 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci if (dump_sensor) 2678c2ecf20Sopenharmony_ci mt9m111_dump_registers(sd); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci return 0; 2708c2ecf20Sopenharmony_ci} 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ciint mt9m111_init_controls(struct sd *sd) 2738c2ecf20Sopenharmony_ci{ 2748c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci sd->gspca_dev.vdev.ctrl_handler = hdl; 2778c2ecf20Sopenharmony_ci v4l2_ctrl_handler_init(hdl, 7); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci sd->auto_white_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, 2808c2ecf20Sopenharmony_ci V4L2_CID_AUTO_WHITE_BALANCE, 2818c2ecf20Sopenharmony_ci 0, 1, 1, 0); 2828c2ecf20Sopenharmony_ci sd->green_bal = v4l2_ctrl_new_custom(hdl, &mt9m111_greenbal_cfg, NULL); 2838c2ecf20Sopenharmony_ci sd->red_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, 2848c2ecf20Sopenharmony_ci V4L2_CID_RED_BALANCE, 0, 0x7ff, 1, 2858c2ecf20Sopenharmony_ci MT9M111_RED_GAIN_DEFAULT); 2868c2ecf20Sopenharmony_ci sd->blue_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, 2878c2ecf20Sopenharmony_ci V4L2_CID_BLUE_BALANCE, 0, 0x7ff, 1, 2888c2ecf20Sopenharmony_ci MT9M111_BLUE_GAIN_DEFAULT); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_GAIN, 0, 2918c2ecf20Sopenharmony_ci (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2, 1, 2928c2ecf20Sopenharmony_ci MT9M111_DEFAULT_GAIN); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci sd->hflip = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_HFLIP, 2958c2ecf20Sopenharmony_ci 0, 1, 1, 0); 2968c2ecf20Sopenharmony_ci sd->vflip = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_VFLIP, 2978c2ecf20Sopenharmony_ci 0, 1, 1, 0); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci if (hdl->error) { 3008c2ecf20Sopenharmony_ci pr_err("Could not initialize controls\n"); 3018c2ecf20Sopenharmony_ci return hdl->error; 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci v4l2_ctrl_auto_cluster(4, &sd->auto_white_bal, 0, false); 3058c2ecf20Sopenharmony_ci v4l2_ctrl_cluster(2, &sd->hflip); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci return 0; 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ciint mt9m111_start(struct sd *sd) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci int i, err = 0; 3138c2ecf20Sopenharmony_ci u8 data[2]; 3148c2ecf20Sopenharmony_ci struct cam *cam = &sd->gspca_dev.cam; 3158c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1; 3188c2ecf20Sopenharmony_ci int height = cam->cam_mode[sd->gspca_dev.curr_mode].height; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) { 3218c2ecf20Sopenharmony_ci if (start_mt9m111[i][0] == BRIDGE) { 3228c2ecf20Sopenharmony_ci err = m5602_write_bridge(sd, 3238c2ecf20Sopenharmony_ci start_mt9m111[i][1], 3248c2ecf20Sopenharmony_ci start_mt9m111[i][2]); 3258c2ecf20Sopenharmony_ci } else { 3268c2ecf20Sopenharmony_ci data[0] = start_mt9m111[i][2]; 3278c2ecf20Sopenharmony_ci data[1] = start_mt9m111[i][3]; 3288c2ecf20Sopenharmony_ci err = m5602_write_sensor(sd, 3298c2ecf20Sopenharmony_ci start_mt9m111[i][1], data, 2); 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci } 3328c2ecf20Sopenharmony_ci if (err < 0) 3338c2ecf20Sopenharmony_ci return err; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff); 3368c2ecf20Sopenharmony_ci if (err < 0) 3378c2ecf20Sopenharmony_ci return err; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff)); 3408c2ecf20Sopenharmony_ci if (err < 0) 3418c2ecf20Sopenharmony_ci return err; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci for (i = 0; i < 2 && !err; i++) 3448c2ecf20Sopenharmony_ci err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); 3458c2ecf20Sopenharmony_ci if (err < 0) 3468c2ecf20Sopenharmony_ci return err; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); 3498c2ecf20Sopenharmony_ci if (err < 0) 3508c2ecf20Sopenharmony_ci return err; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2); 3538c2ecf20Sopenharmony_ci if (err < 0) 3548c2ecf20Sopenharmony_ci return err; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci for (i = 0; i < 2 && !err; i++) 3578c2ecf20Sopenharmony_ci err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0); 3588c2ecf20Sopenharmony_ci if (err < 0) 3598c2ecf20Sopenharmony_ci return err; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 3628c2ecf20Sopenharmony_ci (width >> 8) & 0xff); 3638c2ecf20Sopenharmony_ci if (err < 0) 3648c2ecf20Sopenharmony_ci return err; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, width & 0xff); 3678c2ecf20Sopenharmony_ci if (err < 0) 3688c2ecf20Sopenharmony_ci return err; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); 3718c2ecf20Sopenharmony_ci if (err < 0) 3728c2ecf20Sopenharmony_ci return err; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci switch (width) { 3758c2ecf20Sopenharmony_ci case 640: 3768c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_CONF, "Configuring camera for VGA mode\n"); 3778c2ecf20Sopenharmony_ci break; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci case 320: 3808c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_CONF, "Configuring camera for QVGA mode\n"); 3818c2ecf20Sopenharmony_ci break; 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci return err; 3848c2ecf20Sopenharmony_ci} 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_civoid mt9m111_disconnect(struct sd *sd) 3878c2ecf20Sopenharmony_ci{ 3888c2ecf20Sopenharmony_ci sd->sensor = NULL; 3898c2ecf20Sopenharmony_ci} 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_cistatic int mt9m111_set_hvflip(struct gspca_dev *gspca_dev) 3928c2ecf20Sopenharmony_ci{ 3938c2ecf20Sopenharmony_ci int err; 3948c2ecf20Sopenharmony_ci u8 data[2] = {0x00, 0x00}; 3958c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 3968c2ecf20Sopenharmony_ci int hflip; 3978c2ecf20Sopenharmony_ci int vflip; 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_CONF, "Set hvflip to %d %d\n", 4008c2ecf20Sopenharmony_ci sd->hflip->val, sd->vflip->val); 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci /* The mt9m111 is flipped by default */ 4038c2ecf20Sopenharmony_ci hflip = !sd->hflip->val; 4048c2ecf20Sopenharmony_ci vflip = !sd->vflip->val; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci /* Set the correct page map */ 4078c2ecf20Sopenharmony_ci err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); 4088c2ecf20Sopenharmony_ci if (err < 0) 4098c2ecf20Sopenharmony_ci return err; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci data[0] = MT9M111_RMB_OVER_SIZED; 4128c2ecf20Sopenharmony_ci if (gspca_dev->pixfmt.width == 640) { 4138c2ecf20Sopenharmony_ci data[1] = MT9M111_RMB_ROW_SKIP_2X | 4148c2ecf20Sopenharmony_ci MT9M111_RMB_COLUMN_SKIP_2X | 4158c2ecf20Sopenharmony_ci (hflip << 1) | vflip; 4168c2ecf20Sopenharmony_ci } else { 4178c2ecf20Sopenharmony_ci data[1] = MT9M111_RMB_ROW_SKIP_4X | 4188c2ecf20Sopenharmony_ci MT9M111_RMB_COLUMN_SKIP_4X | 4198c2ecf20Sopenharmony_ci (hflip << 1) | vflip; 4208c2ecf20Sopenharmony_ci } 4218c2ecf20Sopenharmony_ci err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, 4228c2ecf20Sopenharmony_ci data, 2); 4238c2ecf20Sopenharmony_ci return err; 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_cistatic int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev, 4278c2ecf20Sopenharmony_ci __s32 val) 4288c2ecf20Sopenharmony_ci{ 4298c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 4308c2ecf20Sopenharmony_ci int err; 4318c2ecf20Sopenharmony_ci u8 data[2]; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci err = m5602_read_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2); 4348c2ecf20Sopenharmony_ci if (err < 0) 4358c2ecf20Sopenharmony_ci return err; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1)); 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2); 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_CONF, "Set auto white balance %d\n", val); 4428c2ecf20Sopenharmony_ci return err; 4438c2ecf20Sopenharmony_ci} 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_cistatic int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) 4468c2ecf20Sopenharmony_ci{ 4478c2ecf20Sopenharmony_ci int err, tmp; 4488c2ecf20Sopenharmony_ci u8 data[2] = {0x00, 0x00}; 4498c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci /* Set the correct page map */ 4528c2ecf20Sopenharmony_ci err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); 4538c2ecf20Sopenharmony_ci if (err < 0) 4548c2ecf20Sopenharmony_ci return err; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2) 4578c2ecf20Sopenharmony_ci return -EINVAL; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci if ((val >= INITIAL_MAX_GAIN * 2 * 2) && 4608c2ecf20Sopenharmony_ci (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2)) 4618c2ecf20Sopenharmony_ci tmp = (1 << 10) | (val << 9) | 4628c2ecf20Sopenharmony_ci (val << 8) | (val / 8); 4638c2ecf20Sopenharmony_ci else if ((val >= INITIAL_MAX_GAIN * 2) && 4648c2ecf20Sopenharmony_ci (val < INITIAL_MAX_GAIN * 2 * 2)) 4658c2ecf20Sopenharmony_ci tmp = (1 << 9) | (1 << 8) | (val / 4); 4668c2ecf20Sopenharmony_ci else if ((val >= INITIAL_MAX_GAIN) && 4678c2ecf20Sopenharmony_ci (val < INITIAL_MAX_GAIN * 2)) 4688c2ecf20Sopenharmony_ci tmp = (1 << 8) | (val / 2); 4698c2ecf20Sopenharmony_ci else 4708c2ecf20Sopenharmony_ci tmp = val; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci data[1] = (tmp & 0xff); 4738c2ecf20Sopenharmony_ci data[0] = (tmp & 0xff00) >> 8; 4748c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_CONF, "tmp=%d, data[1]=%d, data[0]=%d\n", tmp, 4758c2ecf20Sopenharmony_ci data[1], data[0]); 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN, 4788c2ecf20Sopenharmony_ci data, 2); 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci return err; 4818c2ecf20Sopenharmony_ci} 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_cistatic int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val) 4848c2ecf20Sopenharmony_ci{ 4858c2ecf20Sopenharmony_ci int err; 4868c2ecf20Sopenharmony_ci u8 data[2]; 4878c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci data[1] = (val & 0xff); 4908c2ecf20Sopenharmony_ci data[0] = (val & 0xff00) >> 8; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_CONF, "Set green balance %d\n", val); 4938c2ecf20Sopenharmony_ci err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN, 4948c2ecf20Sopenharmony_ci data, 2); 4958c2ecf20Sopenharmony_ci if (err < 0) 4968c2ecf20Sopenharmony_ci return err; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci return m5602_write_sensor(sd, MT9M111_SC_GREEN_2_GAIN, 4998c2ecf20Sopenharmony_ci data, 2); 5008c2ecf20Sopenharmony_ci} 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_cistatic int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) 5038c2ecf20Sopenharmony_ci{ 5048c2ecf20Sopenharmony_ci u8 data[2]; 5058c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci data[1] = (val & 0xff); 5088c2ecf20Sopenharmony_ci data[0] = (val & 0xff00) >> 8; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_CONF, "Set blue balance %d\n", val); 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN, 5138c2ecf20Sopenharmony_ci data, 2); 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_cistatic int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) 5178c2ecf20Sopenharmony_ci{ 5188c2ecf20Sopenharmony_ci u8 data[2]; 5198c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci data[1] = (val & 0xff); 5228c2ecf20Sopenharmony_ci data[0] = (val & 0xff00) >> 8; 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_CONF, "Set red balance %d\n", val); 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN, 5278c2ecf20Sopenharmony_ci data, 2); 5288c2ecf20Sopenharmony_ci} 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_cistatic int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = 5338c2ecf20Sopenharmony_ci container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 5348c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 5358c2ecf20Sopenharmony_ci int err; 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci if (!gspca_dev->streaming) 5388c2ecf20Sopenharmony_ci return 0; 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci switch (ctrl->id) { 5418c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_WHITE_BALANCE: 5428c2ecf20Sopenharmony_ci err = mt9m111_set_auto_white_balance(gspca_dev, ctrl->val); 5438c2ecf20Sopenharmony_ci if (err || ctrl->val) 5448c2ecf20Sopenharmony_ci return err; 5458c2ecf20Sopenharmony_ci err = mt9m111_set_green_balance(gspca_dev, sd->green_bal->val); 5468c2ecf20Sopenharmony_ci if (err) 5478c2ecf20Sopenharmony_ci return err; 5488c2ecf20Sopenharmony_ci err = mt9m111_set_red_balance(gspca_dev, sd->red_bal->val); 5498c2ecf20Sopenharmony_ci if (err) 5508c2ecf20Sopenharmony_ci return err; 5518c2ecf20Sopenharmony_ci err = mt9m111_set_blue_balance(gspca_dev, sd->blue_bal->val); 5528c2ecf20Sopenharmony_ci break; 5538c2ecf20Sopenharmony_ci case V4L2_CID_GAIN: 5548c2ecf20Sopenharmony_ci err = mt9m111_set_gain(gspca_dev, ctrl->val); 5558c2ecf20Sopenharmony_ci break; 5568c2ecf20Sopenharmony_ci case V4L2_CID_HFLIP: 5578c2ecf20Sopenharmony_ci err = mt9m111_set_hvflip(gspca_dev); 5588c2ecf20Sopenharmony_ci break; 5598c2ecf20Sopenharmony_ci default: 5608c2ecf20Sopenharmony_ci return -EINVAL; 5618c2ecf20Sopenharmony_ci } 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci return err; 5648c2ecf20Sopenharmony_ci} 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_cistatic void mt9m111_dump_registers(struct sd *sd) 5678c2ecf20Sopenharmony_ci{ 5688c2ecf20Sopenharmony_ci u8 address, value[2] = {0x00, 0x00}; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci pr_info("Dumping the mt9m111 register state\n"); 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci pr_info("Dumping the mt9m111 sensor core registers\n"); 5738c2ecf20Sopenharmony_ci value[1] = MT9M111_SENSOR_CORE; 5748c2ecf20Sopenharmony_ci m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); 5758c2ecf20Sopenharmony_ci for (address = 0; address < 0xff; address++) { 5768c2ecf20Sopenharmony_ci m5602_read_sensor(sd, address, value, 2); 5778c2ecf20Sopenharmony_ci pr_info("register 0x%x contains 0x%x%x\n", 5788c2ecf20Sopenharmony_ci address, value[0], value[1]); 5798c2ecf20Sopenharmony_ci } 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci pr_info("Dumping the mt9m111 color pipeline registers\n"); 5828c2ecf20Sopenharmony_ci value[1] = MT9M111_COLORPIPE; 5838c2ecf20Sopenharmony_ci m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); 5848c2ecf20Sopenharmony_ci for (address = 0; address < 0xff; address++) { 5858c2ecf20Sopenharmony_ci m5602_read_sensor(sd, address, value, 2); 5868c2ecf20Sopenharmony_ci pr_info("register 0x%x contains 0x%x%x\n", 5878c2ecf20Sopenharmony_ci address, value[0], value[1]); 5888c2ecf20Sopenharmony_ci } 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci pr_info("Dumping the mt9m111 camera control registers\n"); 5918c2ecf20Sopenharmony_ci value[1] = MT9M111_CAMERA_CONTROL; 5928c2ecf20Sopenharmony_ci m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); 5938c2ecf20Sopenharmony_ci for (address = 0; address < 0xff; address++) { 5948c2ecf20Sopenharmony_ci m5602_read_sensor(sd, address, value, 2); 5958c2ecf20Sopenharmony_ci pr_info("register 0x%x contains 0x%x%x\n", 5968c2ecf20Sopenharmony_ci address, value[0], value[1]); 5978c2ecf20Sopenharmony_ci } 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci pr_info("mt9m111 register state dump complete\n"); 6008c2ecf20Sopenharmony_ci} 601