root/drivers/media/usb/gspca/m5602/m5602_mt9m111.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mt9m111_probe
  2. mt9m111_init
  3. mt9m111_init_controls
  4. mt9m111_start
  5. mt9m111_disconnect
  6. mt9m111_set_hvflip
  7. mt9m111_set_auto_white_balance
  8. mt9m111_set_gain
  9. mt9m111_set_green_balance
  10. mt9m111_set_blue_balance
  11. mt9m111_set_red_balance
  12. mt9m111_s_ctrl
  13. mt9m111_dump_registers

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Driver for the mt9m111 sensor
   4  *
   5  * Copyright (C) 2008 Erik Andrén
   6  * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
   7  * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
   8  *
   9  * Portions of code to USB interface and ALi driver software,
  10  * Copyright (c) 2006 Willem Duinker
  11  * v4l2 interface modeled after the V4L2 driver
  12  * for SN9C10x PC Camera Controllers
  13  */
  14 
  15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  16 
  17 #include "m5602_mt9m111.h"
  18 
  19 static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl);
  20 static void mt9m111_dump_registers(struct sd *sd);
  21 
  22 static const unsigned char preinit_mt9m111[][4] = {
  23         {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
  24         {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
  25         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
  26         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
  27         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
  28         {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
  29         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
  30         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
  31 
  32         {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
  33         {SENSOR, MT9M111_SC_RESET,
  34                 MT9M111_RESET |
  35                 MT9M111_RESTART |
  36                 MT9M111_ANALOG_STANDBY |
  37                 MT9M111_CHIP_DISABLE,
  38                 MT9M111_SHOW_BAD_FRAMES |
  39                 MT9M111_RESTART_BAD_FRAMES |
  40                 MT9M111_SYNCHRONIZE_CHANGES},
  41 
  42         {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
  43         {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
  44         {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
  45         {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
  46         {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
  47         {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
  48         {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
  49         {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
  50 
  51         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
  52         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
  53         {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
  54         {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
  55         {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
  56         {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
  57 
  58         {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}
  59 };
  60 
  61 static const unsigned char init_mt9m111[][4] = {
  62         {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
  63         {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
  64         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
  65         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
  66         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
  67         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
  68 
  69         {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
  70         {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
  71         {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
  72         {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
  73         {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
  74         {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
  75         {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
  76         {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
  77         {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
  78         {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
  79 
  80         {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
  81         {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
  82         {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
  83         {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
  84         {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00,
  85                         MT9M111_CP_OPERATING_MODE_CTL},
  86         {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
  87         {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00,
  88                                 MT9M111_2D_DEFECT_CORRECTION_ENABLE},
  89         {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00,
  90                                 MT9M111_2D_DEFECT_CORRECTION_ENABLE},
  91         {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
  92         {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
  93         {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
  94         {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
  95         {SENSOR, 0xcd, 0x00, 0x0e},
  96         {SENSOR, 0xd0, 0x00, 0x40},
  97 
  98         {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
  99         {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
 100         {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
 101 
 102         {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
 103         {SENSOR, 0x33, 0x03, 0x49},
 104         {SENSOR, 0x34, 0xc0, 0x19},
 105         {SENSOR, 0x3f, 0x20, 0x20},
 106         {SENSOR, 0x40, 0x20, 0x20},
 107         {SENSOR, 0x5a, 0xc0, 0x0a},
 108         {SENSOR, 0x70, 0x7b, 0x0a},
 109         {SENSOR, 0x71, 0xff, 0x00},
 110         {SENSOR, 0x72, 0x19, 0x0e},
 111         {SENSOR, 0x73, 0x18, 0x0f},
 112         {SENSOR, 0x74, 0x57, 0x32},
 113         {SENSOR, 0x75, 0x56, 0x34},
 114         {SENSOR, 0x76, 0x73, 0x35},
 115         {SENSOR, 0x77, 0x30, 0x12},
 116         {SENSOR, 0x78, 0x79, 0x02},
 117         {SENSOR, 0x79, 0x75, 0x06},
 118         {SENSOR, 0x7a, 0x77, 0x0a},
 119         {SENSOR, 0x7b, 0x78, 0x09},
 120         {SENSOR, 0x7c, 0x7d, 0x06},
 121         {SENSOR, 0x7d, 0x31, 0x10},
 122         {SENSOR, 0x7e, 0x00, 0x7e},
 123         {SENSOR, 0x80, 0x59, 0x04},
 124         {SENSOR, 0x81, 0x59, 0x04},
 125         {SENSOR, 0x82, 0x57, 0x0a},
 126         {SENSOR, 0x83, 0x58, 0x0b},
 127         {SENSOR, 0x84, 0x47, 0x0c},
 128         {SENSOR, 0x85, 0x48, 0x0e},
 129         {SENSOR, 0x86, 0x5b, 0x02},
 130         {SENSOR, 0x87, 0x00, 0x5c},
 131         {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, MT9M111_SEL_CONTEXT_B},
 132         {SENSOR, 0x60, 0x00, 0x80},
 133         {SENSOR, 0x61, 0x00, 0x00},
 134         {SENSOR, 0x62, 0x00, 0x00},
 135         {SENSOR, 0x63, 0x00, 0x00},
 136         {SENSOR, 0x64, 0x00, 0x00},
 137 
 138         {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, /* 13 */
 139         {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, /* 18 */
 140         {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, /* 1024 */
 141         {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, /* 1296 */
 142         {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, /* 352 */
 143         {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, /* 17 */
 144         {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, /* 352 */
 145         {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, /* 17 */
 146         {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, /* 271 */
 147         {SENSOR, 0x30, 0x04, 0x00},
 148         /* Set number of blank rows chosen to 400 */
 149         {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
 150 };
 151 
 152 static const unsigned char start_mt9m111[][4] = {
 153         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
 154         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
 155         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
 156         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
 157         {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
 158         {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
 159         {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
 160         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 161         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 162         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 163         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 164 };
 165 
 166 static struct v4l2_pix_format mt9m111_modes[] = {
 167         {
 168                 640,
 169                 480,
 170                 V4L2_PIX_FMT_SBGGR8,
 171                 V4L2_FIELD_NONE,
 172                 .sizeimage = 640 * 480,
 173                 .bytesperline = 640,
 174                 .colorspace = V4L2_COLORSPACE_SRGB,
 175                 .priv = 0
 176         }
 177 };
 178 
 179 static const struct v4l2_ctrl_ops mt9m111_ctrl_ops = {
 180         .s_ctrl = mt9m111_s_ctrl,
 181 };
 182 
 183 static const struct v4l2_ctrl_config mt9m111_greenbal_cfg = {
 184         .ops    = &mt9m111_ctrl_ops,
 185         .id     = M5602_V4L2_CID_GREEN_BALANCE,
 186         .name   = "Green Balance",
 187         .type   = V4L2_CTRL_TYPE_INTEGER,
 188         .min    = 0,
 189         .max    = 0x7ff,
 190         .step   = 1,
 191         .def    = MT9M111_GREEN_GAIN_DEFAULT,
 192         .flags  = V4L2_CTRL_FLAG_SLIDER,
 193 };
 194 
 195 int mt9m111_probe(struct sd *sd)
 196 {
 197         u8 data[2] = {0x00, 0x00};
 198         int i, rc = 0;
 199         struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 200 
 201         if (force_sensor) {
 202                 if (force_sensor == MT9M111_SENSOR) {
 203                         pr_info("Forcing a %s sensor\n", mt9m111.name);
 204                         goto sensor_found;
 205                 }
 206                 /* If we want to force another sensor, don't try to probe this
 207                  * one */
 208                 return -ENODEV;
 209         }
 210 
 211         gspca_dbg(gspca_dev, D_PROBE, "Probing for a mt9m111 sensor\n");
 212 
 213         /* Do the preinit */
 214         for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
 215                 if (preinit_mt9m111[i][0] == BRIDGE) {
 216                         rc |= m5602_write_bridge(sd,
 217                                 preinit_mt9m111[i][1],
 218                                 preinit_mt9m111[i][2]);
 219                 } else {
 220                         data[0] = preinit_mt9m111[i][2];
 221                         data[1] = preinit_mt9m111[i][3];
 222                         rc |= m5602_write_sensor(sd,
 223                                 preinit_mt9m111[i][1], data, 2);
 224                 }
 225         }
 226         if (rc < 0)
 227                 return rc;
 228 
 229         if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
 230                 return -ENODEV;
 231 
 232         if ((data[0] == 0x14) && (data[1] == 0x3a)) {
 233                 pr_info("Detected a mt9m111 sensor\n");
 234                 goto sensor_found;
 235         }
 236 
 237         return -ENODEV;
 238 
 239 sensor_found:
 240         sd->gspca_dev.cam.cam_mode = mt9m111_modes;
 241         sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes);
 242 
 243         return 0;
 244 }
 245 
 246 int mt9m111_init(struct sd *sd)
 247 {
 248         int i, err = 0;
 249 
 250         /* Init the sensor */
 251         for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
 252                 u8 data[2];
 253 
 254                 if (init_mt9m111[i][0] == BRIDGE) {
 255                         err = m5602_write_bridge(sd,
 256                                 init_mt9m111[i][1],
 257                                 init_mt9m111[i][2]);
 258                 } else {
 259                         data[0] = init_mt9m111[i][2];
 260                         data[1] = init_mt9m111[i][3];
 261                         err = m5602_write_sensor(sd,
 262                                 init_mt9m111[i][1], data, 2);
 263                 }
 264         }
 265 
 266         if (dump_sensor)
 267                 mt9m111_dump_registers(sd);
 268 
 269         return 0;
 270 }
 271 
 272 int mt9m111_init_controls(struct sd *sd)
 273 {
 274         struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
 275 
 276         sd->gspca_dev.vdev.ctrl_handler = hdl;
 277         v4l2_ctrl_handler_init(hdl, 7);
 278 
 279         sd->auto_white_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
 280                                                V4L2_CID_AUTO_WHITE_BALANCE,
 281                                                0, 1, 1, 0);
 282         sd->green_bal = v4l2_ctrl_new_custom(hdl, &mt9m111_greenbal_cfg, NULL);
 283         sd->red_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
 284                                         V4L2_CID_RED_BALANCE, 0, 0x7ff, 1,
 285                                         MT9M111_RED_GAIN_DEFAULT);
 286         sd->blue_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
 287                                         V4L2_CID_BLUE_BALANCE, 0, 0x7ff, 1,
 288                                         MT9M111_BLUE_GAIN_DEFAULT);
 289 
 290         v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_GAIN, 0,
 291                           (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2, 1,
 292                           MT9M111_DEFAULT_GAIN);
 293 
 294         sd->hflip = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_HFLIP,
 295                                       0, 1, 1, 0);
 296         sd->vflip = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_VFLIP,
 297                                       0, 1, 1, 0);
 298 
 299         if (hdl->error) {
 300                 pr_err("Could not initialize controls\n");
 301                 return hdl->error;
 302         }
 303 
 304         v4l2_ctrl_auto_cluster(4, &sd->auto_white_bal, 0, false);
 305         v4l2_ctrl_cluster(2, &sd->hflip);
 306 
 307         return 0;
 308 }
 309 
 310 int mt9m111_start(struct sd *sd)
 311 {
 312         int i, err = 0;
 313         u8 data[2];
 314         struct cam *cam = &sd->gspca_dev.cam;
 315         struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 316 
 317         int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1;
 318         int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
 319 
 320         for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) {
 321                 if (start_mt9m111[i][0] == BRIDGE) {
 322                         err = m5602_write_bridge(sd,
 323                                 start_mt9m111[i][1],
 324                                 start_mt9m111[i][2]);
 325                 } else {
 326                         data[0] = start_mt9m111[i][2];
 327                         data[1] = start_mt9m111[i][3];
 328                         err = m5602_write_sensor(sd,
 329                                 start_mt9m111[i][1], data, 2);
 330                 }
 331         }
 332         if (err < 0)
 333                 return err;
 334 
 335         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
 336         if (err < 0)
 337                 return err;
 338 
 339         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
 340         if (err < 0)
 341                 return err;
 342 
 343         for (i = 0; i < 2 && !err; i++)
 344                 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
 345         if (err < 0)
 346                 return err;
 347 
 348         err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
 349         if (err < 0)
 350                 return err;
 351 
 352         err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
 353         if (err < 0)
 354                 return err;
 355 
 356         for (i = 0; i < 2 && !err; i++)
 357                 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
 358         if (err < 0)
 359                 return err;
 360 
 361         err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
 362                                  (width >> 8) & 0xff);
 363         if (err < 0)
 364                 return err;
 365 
 366         err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, width & 0xff);
 367         if (err < 0)
 368                 return err;
 369 
 370         err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
 371         if (err < 0)
 372                 return err;
 373 
 374         switch (width) {
 375         case 640:
 376                 gspca_dbg(gspca_dev, D_CONF, "Configuring camera for VGA mode\n");
 377                 break;
 378 
 379         case 320:
 380                 gspca_dbg(gspca_dev, D_CONF, "Configuring camera for QVGA mode\n");
 381                 break;
 382         }
 383         return err;
 384 }
 385 
 386 void mt9m111_disconnect(struct sd *sd)
 387 {
 388         sd->sensor = NULL;
 389 }
 390 
 391 static int mt9m111_set_hvflip(struct gspca_dev *gspca_dev)
 392 {
 393         int err;
 394         u8 data[2] = {0x00, 0x00};
 395         struct sd *sd = (struct sd *) gspca_dev;
 396         int hflip;
 397         int vflip;
 398 
 399         gspca_dbg(gspca_dev, D_CONF, "Set hvflip to %d %d\n",
 400                   sd->hflip->val, sd->vflip->val);
 401 
 402         /* The mt9m111 is flipped by default */
 403         hflip = !sd->hflip->val;
 404         vflip = !sd->vflip->val;
 405 
 406         /* Set the correct page map */
 407         err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
 408         if (err < 0)
 409                 return err;
 410 
 411         data[0] = MT9M111_RMB_OVER_SIZED;
 412         if (gspca_dev->pixfmt.width == 640) {
 413                 data[1] = MT9M111_RMB_ROW_SKIP_2X |
 414                           MT9M111_RMB_COLUMN_SKIP_2X |
 415                           (hflip << 1) | vflip;
 416         } else {
 417                 data[1] = MT9M111_RMB_ROW_SKIP_4X |
 418                           MT9M111_RMB_COLUMN_SKIP_4X |
 419                           (hflip << 1) | vflip;
 420         }
 421         err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
 422                                         data, 2);
 423         return err;
 424 }
 425 
 426 static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
 427                                           __s32 val)
 428 {
 429         struct sd *sd = (struct sd *) gspca_dev;
 430         int err;
 431         u8 data[2];
 432 
 433         err = m5602_read_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
 434         if (err < 0)
 435                 return err;
 436 
 437         data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1));
 438 
 439         err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
 440 
 441         gspca_dbg(gspca_dev, D_CONF, "Set auto white balance %d\n", val);
 442         return err;
 443 }
 444 
 445 static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 446 {
 447         int err, tmp;
 448         u8 data[2] = {0x00, 0x00};
 449         struct sd *sd = (struct sd *) gspca_dev;
 450 
 451         /* Set the correct page map */
 452         err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
 453         if (err < 0)
 454                 return err;
 455 
 456         if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
 457                 return -EINVAL;
 458 
 459         if ((val >= INITIAL_MAX_GAIN * 2 * 2) &&
 460             (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2))
 461                 tmp = (1 << 10) | (val << 9) |
 462                                 (val << 8) | (val / 8);
 463         else if ((val >= INITIAL_MAX_GAIN * 2) &&
 464                  (val <  INITIAL_MAX_GAIN * 2 * 2))
 465                 tmp = (1 << 9) | (1 << 8) | (val / 4);
 466         else if ((val >= INITIAL_MAX_GAIN) &&
 467                  (val < INITIAL_MAX_GAIN * 2))
 468                 tmp = (1 << 8) | (val / 2);
 469         else
 470                 tmp = val;
 471 
 472         data[1] = (tmp & 0xff);
 473         data[0] = (tmp & 0xff00) >> 8;
 474         gspca_dbg(gspca_dev, D_CONF, "tmp=%d, data[1]=%d, data[0]=%d\n", tmp,
 475                   data[1], data[0]);
 476 
 477         err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
 478                                    data, 2);
 479 
 480         return err;
 481 }
 482 
 483 static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
 484 {
 485         int err;
 486         u8 data[2];
 487         struct sd *sd = (struct sd *) gspca_dev;
 488 
 489         data[1] = (val & 0xff);
 490         data[0] = (val & 0xff00) >> 8;
 491 
 492         gspca_dbg(gspca_dev, D_CONF, "Set green balance %d\n", val);
 493         err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN,
 494                                  data, 2);
 495         if (err < 0)
 496                 return err;
 497 
 498         return m5602_write_sensor(sd, MT9M111_SC_GREEN_2_GAIN,
 499                                   data, 2);
 500 }
 501 
 502 static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
 503 {
 504         u8 data[2];
 505         struct sd *sd = (struct sd *) gspca_dev;
 506 
 507         data[1] = (val & 0xff);
 508         data[0] = (val & 0xff00) >> 8;
 509 
 510         gspca_dbg(gspca_dev, D_CONF, "Set blue balance %d\n", val);
 511 
 512         return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN,
 513                                   data, 2);
 514 }
 515 
 516 static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
 517 {
 518         u8 data[2];
 519         struct sd *sd = (struct sd *) gspca_dev;
 520 
 521         data[1] = (val & 0xff);
 522         data[0] = (val & 0xff00) >> 8;
 523 
 524         gspca_dbg(gspca_dev, D_CONF, "Set red balance %d\n", val);
 525 
 526         return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN,
 527                                   data, 2);
 528 }
 529 
 530 static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl)
 531 {
 532         struct gspca_dev *gspca_dev =
 533                 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 534         struct sd *sd = (struct sd *) gspca_dev;
 535         int err;
 536 
 537         if (!gspca_dev->streaming)
 538                 return 0;
 539 
 540         switch (ctrl->id) {
 541         case V4L2_CID_AUTO_WHITE_BALANCE:
 542                 err = mt9m111_set_auto_white_balance(gspca_dev, ctrl->val);
 543                 if (err || ctrl->val)
 544                         return err;
 545                 err = mt9m111_set_green_balance(gspca_dev, sd->green_bal->val);
 546                 if (err)
 547                         return err;
 548                 err = mt9m111_set_red_balance(gspca_dev, sd->red_bal->val);
 549                 if (err)
 550                         return err;
 551                 err = mt9m111_set_blue_balance(gspca_dev, sd->blue_bal->val);
 552                 break;
 553         case V4L2_CID_GAIN:
 554                 err = mt9m111_set_gain(gspca_dev, ctrl->val);
 555                 break;
 556         case V4L2_CID_HFLIP:
 557                 err = mt9m111_set_hvflip(gspca_dev);
 558                 break;
 559         default:
 560                 return -EINVAL;
 561         }
 562 
 563         return err;
 564 }
 565 
 566 static void mt9m111_dump_registers(struct sd *sd)
 567 {
 568         u8 address, value[2] = {0x00, 0x00};
 569 
 570         pr_info("Dumping the mt9m111 register state\n");
 571 
 572         pr_info("Dumping the mt9m111 sensor core registers\n");
 573         value[1] = MT9M111_SENSOR_CORE;
 574         m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
 575         for (address = 0; address < 0xff; address++) {
 576                 m5602_read_sensor(sd, address, value, 2);
 577                 pr_info("register 0x%x contains 0x%x%x\n",
 578                         address, value[0], value[1]);
 579         }
 580 
 581         pr_info("Dumping the mt9m111 color pipeline registers\n");
 582         value[1] = MT9M111_COLORPIPE;
 583         m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
 584         for (address = 0; address < 0xff; address++) {
 585                 m5602_read_sensor(sd, address, value, 2);
 586                 pr_info("register 0x%x contains 0x%x%x\n",
 587                         address, value[0], value[1]);
 588         }
 589 
 590         pr_info("Dumping the mt9m111 camera control registers\n");
 591         value[1] = MT9M111_CAMERA_CONTROL;
 592         m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
 593         for (address = 0; address < 0xff; address++) {
 594                 m5602_read_sensor(sd, address, value, 2);
 595                 pr_info("register 0x%x contains 0x%x%x\n",
 596                         address, value[0], value[1]);
 597         }
 598 
 599         pr_info("mt9m111 register state dump complete\n");
 600 }

/* [<][>][^][v][top][bottom][index][help] */