1406 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Driver for MT9M111/MT9M112/MT9M131 CMOS Image Sensor from Micron/Aptina4 *5 * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr>6 */7#include <linux/clk.h>8#include <linux/videodev2.h>9#include <linux/slab.h>10#include <linux/i2c.h>11#include <linux/log2.h>12#include <linux/delay.h>13#include <linux/regulator/consumer.h>14#include <linux/v4l2-mediabus.h>15#include <linux/module.h>16#include <linux/property.h>17 18#include <media/v4l2-async.h>19#include <media/v4l2-common.h>20#include <media/v4l2-ctrls.h>21#include <media/v4l2-device.h>22#include <media/v4l2-event.h>23#include <media/v4l2-fwnode.h>24 25/*26 * MT9M111, MT9M112 and MT9M131:27 * i2c address is 0x48 or 0x5d (depending on SADDR pin)28 * The platform has to define struct i2c_board_info objects and link to them29 * from struct soc_camera_host_desc30 */31 32/*33 * Sensor core register addresses (0x000..0x0ff)34 */35#define MT9M111_CHIP_VERSION 0x00036#define MT9M111_ROW_START 0x00137#define MT9M111_COLUMN_START 0x00238#define MT9M111_WINDOW_HEIGHT 0x00339#define MT9M111_WINDOW_WIDTH 0x00440#define MT9M111_HORIZONTAL_BLANKING_B 0x00541#define MT9M111_VERTICAL_BLANKING_B 0x00642#define MT9M111_HORIZONTAL_BLANKING_A 0x00743#define MT9M111_VERTICAL_BLANKING_A 0x00844#define MT9M111_SHUTTER_WIDTH 0x00945#define MT9M111_ROW_SPEED 0x00a46#define MT9M111_EXTRA_DELAY 0x00b47#define MT9M111_SHUTTER_DELAY 0x00c48#define MT9M111_RESET 0x00d49#define MT9M111_READ_MODE_B 0x02050#define MT9M111_READ_MODE_A 0x02151#define MT9M111_FLASH_CONTROL 0x02352#define MT9M111_GREEN1_GAIN 0x02b53#define MT9M111_BLUE_GAIN 0x02c54#define MT9M111_RED_GAIN 0x02d55#define MT9M111_GREEN2_GAIN 0x02e56#define MT9M111_GLOBAL_GAIN 0x02f57#define MT9M111_CONTEXT_CONTROL 0x0c858#define MT9M111_PAGE_MAP 0x0f059#define MT9M111_BYTE_WISE_ADDR 0x0f160 61#define MT9M111_RESET_SYNC_CHANGES (1 << 15)62#define MT9M111_RESET_RESTART_BAD_FRAME (1 << 9)63#define MT9M111_RESET_SHOW_BAD_FRAMES (1 << 8)64#define MT9M111_RESET_RESET_SOC (1 << 5)65#define MT9M111_RESET_OUTPUT_DISABLE (1 << 4)66#define MT9M111_RESET_CHIP_ENABLE (1 << 3)67#define MT9M111_RESET_ANALOG_STANDBY (1 << 2)68#define MT9M111_RESET_RESTART_FRAME (1 << 1)69#define MT9M111_RESET_RESET_MODE (1 << 0)70 71#define MT9M111_RM_FULL_POWER_RD (0 << 10)72#define MT9M111_RM_LOW_POWER_RD (1 << 10)73#define MT9M111_RM_COL_SKIP_4X (1 << 5)74#define MT9M111_RM_ROW_SKIP_4X (1 << 4)75#define MT9M111_RM_COL_SKIP_2X (1 << 3)76#define MT9M111_RM_ROW_SKIP_2X (1 << 2)77#define MT9M111_RMB_MIRROR_COLS (1 << 1)78#define MT9M111_RMB_MIRROR_ROWS (1 << 0)79#define MT9M111_CTXT_CTRL_RESTART (1 << 15)80#define MT9M111_CTXT_CTRL_DEFECTCOR_B (1 << 12)81#define MT9M111_CTXT_CTRL_RESIZE_B (1 << 10)82#define MT9M111_CTXT_CTRL_CTRL2_B (1 << 9)83#define MT9M111_CTXT_CTRL_GAMMA_B (1 << 8)84#define MT9M111_CTXT_CTRL_XENON_EN (1 << 7)85#define MT9M111_CTXT_CTRL_READ_MODE_B (1 << 3)86#define MT9M111_CTXT_CTRL_LED_FLASH_EN (1 << 2)87#define MT9M111_CTXT_CTRL_VBLANK_SEL_B (1 << 1)88#define MT9M111_CTXT_CTRL_HBLANK_SEL_B (1 << 0)89 90/*91 * Colorpipe register addresses (0x100..0x1ff)92 */93#define MT9M111_OPER_MODE_CTRL 0x10694#define MT9M111_OUTPUT_FORMAT_CTRL 0x10895#define MT9M111_TPG_CTRL 0x14896#define MT9M111_REDUCER_XZOOM_B 0x1a097#define MT9M111_REDUCER_XSIZE_B 0x1a198#define MT9M111_REDUCER_YZOOM_B 0x1a399#define MT9M111_REDUCER_YSIZE_B 0x1a4100#define MT9M111_REDUCER_XZOOM_A 0x1a6101#define MT9M111_REDUCER_XSIZE_A 0x1a7102#define MT9M111_REDUCER_YZOOM_A 0x1a9103#define MT9M111_REDUCER_YSIZE_A 0x1aa104#define MT9M111_EFFECTS_MODE 0x1e2105 106#define MT9M111_OUTPUT_FORMAT_CTRL2_A 0x13a107#define MT9M111_OUTPUT_FORMAT_CTRL2_B 0x19b108 109#define MT9M111_OPMODE_AUTOEXPO_EN (1 << 14)110#define MT9M111_OPMODE_AUTOWHITEBAL_EN (1 << 1)111#define MT9M111_OUTFMT_FLIP_BAYER_COL (1 << 9)112#define MT9M111_OUTFMT_FLIP_BAYER_ROW (1 << 8)113#define MT9M111_OUTFMT_PROCESSED_BAYER (1 << 14)114#define MT9M111_OUTFMT_BYPASS_IFP (1 << 10)115#define MT9M111_OUTFMT_INV_PIX_CLOCK (1 << 9)116#define MT9M111_OUTFMT_RGB (1 << 8)117#define MT9M111_OUTFMT_RGB565 (0 << 6)118#define MT9M111_OUTFMT_RGB555 (1 << 6)119#define MT9M111_OUTFMT_RGB444x (2 << 6)120#define MT9M111_OUTFMT_RGBx444 (3 << 6)121#define MT9M111_OUTFMT_TST_RAMP_OFF (0 << 4)122#define MT9M111_OUTFMT_TST_RAMP_COL (1 << 4)123#define MT9M111_OUTFMT_TST_RAMP_ROW (2 << 4)124#define MT9M111_OUTFMT_TST_RAMP_FRAME (3 << 4)125#define MT9M111_OUTFMT_SHIFT_3_UP (1 << 3)126#define MT9M111_OUTFMT_AVG_CHROMA (1 << 2)127#define MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN (1 << 1)128#define MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B (1 << 0)129#define MT9M111_TPG_SEL_MASK GENMASK(2, 0)130#define MT9M111_EFFECTS_MODE_MASK GENMASK(2, 0)131#define MT9M111_RM_PWR_MASK BIT(10)132#define MT9M111_RM_SKIP2_MASK GENMASK(3, 2)133 134/*135 * Camera control register addresses (0x200..0x2ff not implemented)136 */137 138#define reg_read(reg) mt9m111_reg_read(client, MT9M111_##reg)139#define reg_write(reg, val) mt9m111_reg_write(client, MT9M111_##reg, (val))140#define reg_set(reg, val) mt9m111_reg_set(client, MT9M111_##reg, (val))141#define reg_clear(reg, val) mt9m111_reg_clear(client, MT9M111_##reg, (val))142#define reg_mask(reg, val, mask) mt9m111_reg_mask(client, MT9M111_##reg, \143 (val), (mask))144 145#define MT9M111_MIN_DARK_ROWS 8146#define MT9M111_MIN_DARK_COLS 26147#define MT9M111_MAX_HEIGHT 1024148#define MT9M111_MAX_WIDTH 1280149 150struct mt9m111_context {151 u16 read_mode;152 u16 blanking_h;153 u16 blanking_v;154 u16 reducer_xzoom;155 u16 reducer_yzoom;156 u16 reducer_xsize;157 u16 reducer_ysize;158 u16 output_fmt_ctrl2;159 u16 control;160};161 162static struct mt9m111_context context_a = {163 .read_mode = MT9M111_READ_MODE_A,164 .blanking_h = MT9M111_HORIZONTAL_BLANKING_A,165 .blanking_v = MT9M111_VERTICAL_BLANKING_A,166 .reducer_xzoom = MT9M111_REDUCER_XZOOM_A,167 .reducer_yzoom = MT9M111_REDUCER_YZOOM_A,168 .reducer_xsize = MT9M111_REDUCER_XSIZE_A,169 .reducer_ysize = MT9M111_REDUCER_YSIZE_A,170 .output_fmt_ctrl2 = MT9M111_OUTPUT_FORMAT_CTRL2_A,171 .control = MT9M111_CTXT_CTRL_RESTART,172};173 174static struct mt9m111_context context_b = {175 .read_mode = MT9M111_READ_MODE_B,176 .blanking_h = MT9M111_HORIZONTAL_BLANKING_B,177 .blanking_v = MT9M111_VERTICAL_BLANKING_B,178 .reducer_xzoom = MT9M111_REDUCER_XZOOM_B,179 .reducer_yzoom = MT9M111_REDUCER_YZOOM_B,180 .reducer_xsize = MT9M111_REDUCER_XSIZE_B,181 .reducer_ysize = MT9M111_REDUCER_YSIZE_B,182 .output_fmt_ctrl2 = MT9M111_OUTPUT_FORMAT_CTRL2_B,183 .control = MT9M111_CTXT_CTRL_RESTART |184 MT9M111_CTXT_CTRL_DEFECTCOR_B | MT9M111_CTXT_CTRL_RESIZE_B |185 MT9M111_CTXT_CTRL_CTRL2_B | MT9M111_CTXT_CTRL_GAMMA_B |186 MT9M111_CTXT_CTRL_READ_MODE_B | MT9M111_CTXT_CTRL_VBLANK_SEL_B |187 MT9M111_CTXT_CTRL_HBLANK_SEL_B,188};189 190/* MT9M111 has only one fixed colorspace per pixelcode */191struct mt9m111_datafmt {192 u32 code;193 enum v4l2_colorspace colorspace;194};195 196static const struct mt9m111_datafmt mt9m111_colour_fmts[] = {197 {MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_SRGB},198 {MEDIA_BUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_SRGB},199 {MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_SRGB},200 {MEDIA_BUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_SRGB},201 {MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},202 {MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},203 {MEDIA_BUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},204 {MEDIA_BUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB},205 {MEDIA_BUS_FMT_BGR565_2X8_LE, V4L2_COLORSPACE_SRGB},206 {MEDIA_BUS_FMT_BGR565_2X8_BE, V4L2_COLORSPACE_SRGB},207 {MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},208 {MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},209};210 211enum mt9m111_mode_id {212 MT9M111_MODE_SXGA_8FPS,213 MT9M111_MODE_SXGA_15FPS,214 MT9M111_MODE_QSXGA_30FPS,215 MT9M111_NUM_MODES,216};217 218struct mt9m111_mode_info {219 unsigned int sensor_w;220 unsigned int sensor_h;221 unsigned int max_image_w;222 unsigned int max_image_h;223 unsigned int max_fps;224 unsigned int reg_val;225 unsigned int reg_mask;226};227 228struct mt9m111 {229 struct v4l2_subdev subdev;230 struct v4l2_ctrl_handler hdl;231 struct v4l2_ctrl *gain;232 struct mt9m111_context *ctx;233 struct v4l2_rect rect; /* cropping rectangle */234 struct clk *clk;235 unsigned int width; /* output */236 unsigned int height; /* sizes */237 struct v4l2_fract frame_interval;238 const struct mt9m111_mode_info *current_mode;239 struct mutex power_lock; /* lock to protect power_count */240 int power_count;241 const struct mt9m111_datafmt *fmt;242 int lastpage; /* PageMap cache value */243 struct regulator *regulator;244 bool is_streaming;245 /* user point of view - 0: falling 1: rising edge */246 unsigned int pclk_sample:1;247 struct media_pad pad;248};249 250static const struct mt9m111_mode_info mt9m111_mode_data[MT9M111_NUM_MODES] = {251 [MT9M111_MODE_SXGA_8FPS] = {252 .sensor_w = 1280,253 .sensor_h = 1024,254 .max_image_w = 1280,255 .max_image_h = 1024,256 .max_fps = 8,257 .reg_val = MT9M111_RM_LOW_POWER_RD,258 .reg_mask = MT9M111_RM_PWR_MASK | MT9M111_RM_SKIP2_MASK,259 },260 [MT9M111_MODE_SXGA_15FPS] = {261 .sensor_w = 1280,262 .sensor_h = 1024,263 .max_image_w = 1280,264 .max_image_h = 1024,265 .max_fps = 15,266 .reg_val = MT9M111_RM_FULL_POWER_RD,267 .reg_mask = MT9M111_RM_PWR_MASK | MT9M111_RM_SKIP2_MASK,268 },269 [MT9M111_MODE_QSXGA_30FPS] = {270 .sensor_w = 1280,271 .sensor_h = 1024,272 .max_image_w = 640,273 .max_image_h = 512,274 .max_fps = 30,275 .reg_val = MT9M111_RM_LOW_POWER_RD | MT9M111_RM_COL_SKIP_2X |276 MT9M111_RM_ROW_SKIP_2X,277 .reg_mask = MT9M111_RM_PWR_MASK | MT9M111_RM_SKIP2_MASK,278 },279};280 281/* Find a data format by a pixel code */282static const struct mt9m111_datafmt *mt9m111_find_datafmt(struct mt9m111 *mt9m111,283 u32 code)284{285 int i;286 for (i = 0; i < ARRAY_SIZE(mt9m111_colour_fmts); i++)287 if (mt9m111_colour_fmts[i].code == code)288 return mt9m111_colour_fmts + i;289 290 return mt9m111->fmt;291}292 293static struct mt9m111 *to_mt9m111(const struct i2c_client *client)294{295 return container_of(i2c_get_clientdata(client), struct mt9m111, subdev);296}297 298static int reg_page_map_set(struct i2c_client *client, const u16 reg)299{300 int ret;301 u16 page;302 struct mt9m111 *mt9m111 = to_mt9m111(client);303 304 page = (reg >> 8);305 if (page == mt9m111->lastpage)306 return 0;307 if (page > 2)308 return -EINVAL;309 310 ret = i2c_smbus_write_word_swapped(client, MT9M111_PAGE_MAP, page);311 if (!ret)312 mt9m111->lastpage = page;313 return ret;314}315 316static int mt9m111_reg_read(struct i2c_client *client, const u16 reg)317{318 int ret;319 320 ret = reg_page_map_set(client, reg);321 if (!ret)322 ret = i2c_smbus_read_word_swapped(client, reg & 0xff);323 324 dev_dbg(&client->dev, "read reg.%03x -> %04x\n", reg, ret);325 return ret;326}327 328static int mt9m111_reg_write(struct i2c_client *client, const u16 reg,329 const u16 data)330{331 int ret;332 333 ret = reg_page_map_set(client, reg);334 if (!ret)335 ret = i2c_smbus_write_word_swapped(client, reg & 0xff, data);336 dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);337 return ret;338}339 340static int mt9m111_reg_set(struct i2c_client *client, const u16 reg,341 const u16 data)342{343 int ret;344 345 ret = mt9m111_reg_read(client, reg);346 if (ret >= 0)347 ret = mt9m111_reg_write(client, reg, ret | data);348 return ret;349}350 351static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg,352 const u16 data)353{354 int ret;355 356 ret = mt9m111_reg_read(client, reg);357 if (ret >= 0)358 ret = mt9m111_reg_write(client, reg, ret & ~data);359 return ret;360}361 362static int mt9m111_reg_mask(struct i2c_client *client, const u16 reg,363 const u16 data, const u16 mask)364{365 int ret;366 367 ret = mt9m111_reg_read(client, reg);368 if (ret >= 0)369 ret = mt9m111_reg_write(client, reg, (ret & ~mask) | data);370 return ret;371}372 373static int mt9m111_set_context(struct mt9m111 *mt9m111,374 struct mt9m111_context *ctx)375{376 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);377 return reg_write(CONTEXT_CONTROL, ctx->control);378}379 380static int mt9m111_setup_rect_ctx(struct mt9m111 *mt9m111,381 struct mt9m111_context *ctx, struct v4l2_rect *rect,382 unsigned int width, unsigned int height)383{384 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);385 int ret = mt9m111_reg_write(client, ctx->reducer_xzoom, rect->width);386 if (!ret)387 ret = mt9m111_reg_write(client, ctx->reducer_yzoom, rect->height);388 if (!ret)389 ret = mt9m111_reg_write(client, ctx->reducer_xsize, width);390 if (!ret)391 ret = mt9m111_reg_write(client, ctx->reducer_ysize, height);392 return ret;393}394 395static int mt9m111_setup_geometry(struct mt9m111 *mt9m111, struct v4l2_rect *rect,396 int width, int height, u32 code)397{398 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);399 int ret;400 401 ret = reg_write(COLUMN_START, rect->left);402 if (!ret)403 ret = reg_write(ROW_START, rect->top);404 405 if (!ret)406 ret = reg_write(WINDOW_WIDTH, rect->width);407 if (!ret)408 ret = reg_write(WINDOW_HEIGHT, rect->height);409 410 if (code != MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE) {411 /* IFP in use, down-scaling possible */412 if (!ret)413 ret = mt9m111_setup_rect_ctx(mt9m111, &context_b,414 rect, width, height);415 if (!ret)416 ret = mt9m111_setup_rect_ctx(mt9m111, &context_a,417 rect, width, height);418 }419 420 dev_dbg(&client->dev, "%s(%x): %ux%u@%u:%u -> %ux%u = %d\n",421 __func__, code, rect->width, rect->height, rect->left, rect->top,422 width, height, ret);423 424 return ret;425}426 427static int mt9m111_enable(struct mt9m111 *mt9m111)428{429 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);430 return reg_write(RESET, MT9M111_RESET_CHIP_ENABLE);431}432 433static int mt9m111_reset(struct mt9m111 *mt9m111)434{435 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);436 int ret;437 438 ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);439 if (!ret)440 ret = reg_set(RESET, MT9M111_RESET_RESET_SOC);441 if (!ret)442 ret = reg_clear(RESET, MT9M111_RESET_RESET_MODE443 | MT9M111_RESET_RESET_SOC);444 445 return ret;446}447 448static int mt9m111_set_selection(struct v4l2_subdev *sd,449 struct v4l2_subdev_state *sd_state,450 struct v4l2_subdev_selection *sel)451{452 struct i2c_client *client = v4l2_get_subdevdata(sd);453 struct mt9m111 *mt9m111 = to_mt9m111(client);454 struct v4l2_rect rect = sel->r;455 int width, height;456 int ret, align = 0;457 458 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||459 sel->target != V4L2_SEL_TGT_CROP)460 return -EINVAL;461 462 if (mt9m111->fmt->code == MEDIA_BUS_FMT_SBGGR8_1X8 ||463 mt9m111->fmt->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE) {464 /* Bayer format - even size lengths */465 align = 1;466 /* Let the user play with the starting pixel */467 }468 469 /* FIXME: the datasheet doesn't specify minimum sizes */470 v4l_bound_align_image(&rect.width, 2, MT9M111_MAX_WIDTH, align,471 &rect.height, 2, MT9M111_MAX_HEIGHT, align, 0);472 rect.left = clamp(rect.left, MT9M111_MIN_DARK_COLS,473 MT9M111_MIN_DARK_COLS + MT9M111_MAX_WIDTH -474 (__s32)rect.width);475 rect.top = clamp(rect.top, MT9M111_MIN_DARK_ROWS,476 MT9M111_MIN_DARK_ROWS + MT9M111_MAX_HEIGHT -477 (__s32)rect.height);478 479 width = min(mt9m111->width, rect.width);480 height = min(mt9m111->height, rect.height);481 482 ret = mt9m111_setup_geometry(mt9m111, &rect, width, height, mt9m111->fmt->code);483 if (!ret) {484 mt9m111->rect = rect;485 mt9m111->width = width;486 mt9m111->height = height;487 }488 489 return ret;490}491 492static int mt9m111_get_selection(struct v4l2_subdev *sd,493 struct v4l2_subdev_state *sd_state,494 struct v4l2_subdev_selection *sel)495{496 struct i2c_client *client = v4l2_get_subdevdata(sd);497 struct mt9m111 *mt9m111 = to_mt9m111(client);498 499 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)500 return -EINVAL;501 502 switch (sel->target) {503 case V4L2_SEL_TGT_CROP_BOUNDS:504 sel->r.left = MT9M111_MIN_DARK_COLS;505 sel->r.top = MT9M111_MIN_DARK_ROWS;506 sel->r.width = MT9M111_MAX_WIDTH;507 sel->r.height = MT9M111_MAX_HEIGHT;508 return 0;509 case V4L2_SEL_TGT_CROP:510 sel->r = mt9m111->rect;511 return 0;512 default:513 return -EINVAL;514 }515}516 517static int mt9m111_get_fmt(struct v4l2_subdev *sd,518 struct v4l2_subdev_state *sd_state,519 struct v4l2_subdev_format *format)520{521 struct v4l2_mbus_framefmt *mf = &format->format;522 struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);523 524 if (format->pad)525 return -EINVAL;526 527 if (format->which == V4L2_SUBDEV_FORMAT_TRY) {528 mf = v4l2_subdev_state_get_format(sd_state, format->pad);529 format->format = *mf;530 return 0;531 }532 533 mf->width = mt9m111->width;534 mf->height = mt9m111->height;535 mf->code = mt9m111->fmt->code;536 mf->colorspace = mt9m111->fmt->colorspace;537 mf->field = V4L2_FIELD_NONE;538 mf->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;539 mf->quantization = V4L2_QUANTIZATION_DEFAULT;540 mf->xfer_func = V4L2_XFER_FUNC_DEFAULT;541 542 return 0;543}544 545static int mt9m111_set_pixfmt(struct mt9m111 *mt9m111,546 u32 code)547{548 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);549 u16 data_outfmt2, mask_outfmt2 = MT9M111_OUTFMT_PROCESSED_BAYER |550 MT9M111_OUTFMT_BYPASS_IFP | MT9M111_OUTFMT_RGB |551 MT9M111_OUTFMT_RGB565 | MT9M111_OUTFMT_RGB555 |552 MT9M111_OUTFMT_RGB444x | MT9M111_OUTFMT_RGBx444 |553 MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN |554 MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;555 int ret;556 557 switch (code) {558 case MEDIA_BUS_FMT_SBGGR8_1X8:559 data_outfmt2 = MT9M111_OUTFMT_PROCESSED_BAYER |560 MT9M111_OUTFMT_RGB;561 break;562 case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:563 data_outfmt2 = MT9M111_OUTFMT_BYPASS_IFP | MT9M111_OUTFMT_RGB;564 break;565 case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:566 data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555 |567 MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;568 break;569 case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:570 data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555;571 break;572 case MEDIA_BUS_FMT_RGB565_2X8_LE:573 data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |574 MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;575 break;576 case MEDIA_BUS_FMT_RGB565_2X8_BE:577 data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565;578 break;579 case MEDIA_BUS_FMT_BGR565_2X8_BE:580 data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |581 MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;582 break;583 case MEDIA_BUS_FMT_BGR565_2X8_LE:584 data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |585 MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN |586 MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;587 break;588 case MEDIA_BUS_FMT_UYVY8_2X8:589 data_outfmt2 = 0;590 break;591 case MEDIA_BUS_FMT_VYUY8_2X8:592 data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;593 break;594 case MEDIA_BUS_FMT_YUYV8_2X8:595 data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;596 break;597 case MEDIA_BUS_FMT_YVYU8_2X8:598 data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN |599 MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;600 break;601 default:602 dev_err(&client->dev, "Pixel format not handled: %x\n", code);603 return -EINVAL;604 }605 606 /* receiver samples on falling edge, chip-hw default is rising */607 if (mt9m111->pclk_sample == 0)608 mask_outfmt2 |= MT9M111_OUTFMT_INV_PIX_CLOCK;609 610 ret = mt9m111_reg_mask(client, context_a.output_fmt_ctrl2,611 data_outfmt2, mask_outfmt2);612 if (!ret)613 ret = mt9m111_reg_mask(client, context_b.output_fmt_ctrl2,614 data_outfmt2, mask_outfmt2);615 616 return ret;617}618 619static int mt9m111_set_fmt(struct v4l2_subdev *sd,620 struct v4l2_subdev_state *sd_state,621 struct v4l2_subdev_format *format)622{623 struct v4l2_mbus_framefmt *mf = &format->format;624 struct i2c_client *client = v4l2_get_subdevdata(sd);625 struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);626 const struct mt9m111_datafmt *fmt;627 struct v4l2_rect *rect = &mt9m111->rect;628 bool bayer;629 int ret;630 631 if (mt9m111->is_streaming)632 return -EBUSY;633 634 if (format->pad)635 return -EINVAL;636 637 fmt = mt9m111_find_datafmt(mt9m111, mf->code);638 639 bayer = fmt->code == MEDIA_BUS_FMT_SBGGR8_1X8 ||640 fmt->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE;641 642 /*643 * With Bayer format enforce even side lengths, but let the user play644 * with the starting pixel645 */646 if (bayer) {647 rect->width = ALIGN(rect->width, 2);648 rect->height = ALIGN(rect->height, 2);649 }650 651 if (fmt->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE) {652 /* IFP bypass mode, no scaling */653 mf->width = rect->width;654 mf->height = rect->height;655 } else {656 /* No upscaling */657 if (mf->width > rect->width)658 mf->width = rect->width;659 if (mf->height > rect->height)660 mf->height = rect->height;661 }662 663 dev_dbg(&client->dev, "%s(): %ux%u, code=%x\n", __func__,664 mf->width, mf->height, fmt->code);665 666 mf->code = fmt->code;667 mf->colorspace = fmt->colorspace;668 mf->field = V4L2_FIELD_NONE;669 mf->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;670 mf->quantization = V4L2_QUANTIZATION_DEFAULT;671 mf->xfer_func = V4L2_XFER_FUNC_DEFAULT;672 673 if (format->which == V4L2_SUBDEV_FORMAT_TRY) {674 *v4l2_subdev_state_get_format(sd_state, 0) = *mf;675 return 0;676 }677 678 ret = mt9m111_setup_geometry(mt9m111, rect, mf->width, mf->height, mf->code);679 if (!ret)680 ret = mt9m111_set_pixfmt(mt9m111, mf->code);681 if (!ret) {682 mt9m111->width = mf->width;683 mt9m111->height = mf->height;684 mt9m111->fmt = fmt;685 }686 687 return ret;688}689 690static const struct mt9m111_mode_info *691mt9m111_find_mode(struct mt9m111 *mt9m111, unsigned int req_fps,692 unsigned int width, unsigned int height)693{694 const struct mt9m111_mode_info *mode;695 struct v4l2_rect *sensor_rect = &mt9m111->rect;696 unsigned int gap, gap_best = (unsigned int) -1;697 int i, best_gap_idx = MT9M111_MODE_SXGA_15FPS;698 bool skip_30fps = false;699 700 /*701 * The fps selection is based on the row, column skipping mechanism.702 * So ensure that the sensor window is set to default else the fps703 * aren't calculated correctly within the sensor hw.704 */705 if (sensor_rect->width != MT9M111_MAX_WIDTH ||706 sensor_rect->height != MT9M111_MAX_HEIGHT) {707 dev_info(mt9m111->subdev.dev,708 "Framerate selection is not supported for cropped "709 "images\n");710 return NULL;711 }712 713 /* 30fps only supported for images not exceeding 640x512 */714 if (width > MT9M111_MAX_WIDTH / 2 || height > MT9M111_MAX_HEIGHT / 2) {715 dev_dbg(mt9m111->subdev.dev,716 "Framerates > 15fps are supported only for images "717 "not exceeding 640x512\n");718 skip_30fps = true;719 }720 721 /* find best matched fps */722 for (i = 0; i < MT9M111_NUM_MODES; i++) {723 unsigned int fps = mt9m111_mode_data[i].max_fps;724 725 if (fps == 30 && skip_30fps)726 continue;727 728 gap = abs(fps - req_fps);729 if (gap < gap_best) {730 best_gap_idx = i;731 gap_best = gap;732 }733 }734 735 /*736 * Use context a/b default timing values instead of calculate blanking737 * timing values.738 */739 mode = &mt9m111_mode_data[best_gap_idx];740 mt9m111->ctx = (best_gap_idx == MT9M111_MODE_QSXGA_30FPS) ? &context_a :741 &context_b;742 return mode;743}744 745#ifdef CONFIG_VIDEO_ADV_DEBUG746static int mt9m111_g_register(struct v4l2_subdev *sd,747 struct v4l2_dbg_register *reg)748{749 struct i2c_client *client = v4l2_get_subdevdata(sd);750 int val;751 752 if (reg->reg > 0x2ff)753 return -EINVAL;754 755 val = mt9m111_reg_read(client, reg->reg);756 reg->size = 2;757 reg->val = (u64)val;758 759 if (reg->val > 0xffff)760 return -EIO;761 762 return 0;763}764 765static int mt9m111_s_register(struct v4l2_subdev *sd,766 const struct v4l2_dbg_register *reg)767{768 struct i2c_client *client = v4l2_get_subdevdata(sd);769 770 if (reg->reg > 0x2ff)771 return -EINVAL;772 773 if (mt9m111_reg_write(client, reg->reg, reg->val) < 0)774 return -EIO;775 776 return 0;777}778#endif779 780static int mt9m111_set_flip(struct mt9m111 *mt9m111, int flip, int mask)781{782 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);783 int ret;784 785 if (flip)786 ret = mt9m111_reg_set(client, mt9m111->ctx->read_mode, mask);787 else788 ret = mt9m111_reg_clear(client, mt9m111->ctx->read_mode, mask);789 790 return ret;791}792 793static int mt9m111_get_global_gain(struct mt9m111 *mt9m111)794{795 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);796 int data;797 798 data = reg_read(GLOBAL_GAIN);799 if (data >= 0)800 return (data & 0x2f) * (1 << ((data >> 10) & 1)) *801 (1 << ((data >> 9) & 1));802 return data;803}804 805static int mt9m111_set_global_gain(struct mt9m111 *mt9m111, int gain)806{807 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);808 u16 val;809 810 if (gain > 63 * 2 * 2)811 return -EINVAL;812 813 if ((gain >= 64 * 2) && (gain < 63 * 2 * 2))814 val = (1 << 10) | (1 << 9) | (gain / 4);815 else if ((gain >= 64) && (gain < 64 * 2))816 val = (1 << 9) | (gain / 2);817 else818 val = gain;819 820 return reg_write(GLOBAL_GAIN, val);821}822 823static int mt9m111_set_autoexposure(struct mt9m111 *mt9m111, int val)824{825 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);826 827 if (val == V4L2_EXPOSURE_AUTO)828 return reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);829 return reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);830}831 832static int mt9m111_set_autowhitebalance(struct mt9m111 *mt9m111, int on)833{834 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);835 836 if (on)837 return reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);838 return reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);839}840 841static const char * const mt9m111_test_pattern_menu[] = {842 "Disabled",843 "Vertical monochrome gradient",844 "Flat color type 1",845 "Flat color type 2",846 "Flat color type 3",847 "Flat color type 4",848 "Flat color type 5",849 "Color bar",850};851 852static int mt9m111_set_test_pattern(struct mt9m111 *mt9m111, int val)853{854 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);855 856 return mt9m111_reg_mask(client, MT9M111_TPG_CTRL, val,857 MT9M111_TPG_SEL_MASK);858}859 860static int mt9m111_set_colorfx(struct mt9m111 *mt9m111, int val)861{862 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);863 static const struct v4l2_control colorfx[] = {864 { V4L2_COLORFX_NONE, 0 },865 { V4L2_COLORFX_BW, 1 },866 { V4L2_COLORFX_SEPIA, 2 },867 { V4L2_COLORFX_NEGATIVE, 3 },868 { V4L2_COLORFX_SOLARIZATION, 4 },869 };870 int i;871 872 for (i = 0; i < ARRAY_SIZE(colorfx); i++) {873 if (colorfx[i].id == val) {874 return mt9m111_reg_mask(client, MT9M111_EFFECTS_MODE,875 colorfx[i].value,876 MT9M111_EFFECTS_MODE_MASK);877 }878 }879 880 return -EINVAL;881}882 883static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl)884{885 struct mt9m111 *mt9m111 = container_of(ctrl->handler,886 struct mt9m111, hdl);887 888 switch (ctrl->id) {889 case V4L2_CID_VFLIP:890 return mt9m111_set_flip(mt9m111, ctrl->val,891 MT9M111_RMB_MIRROR_ROWS);892 case V4L2_CID_HFLIP:893 return mt9m111_set_flip(mt9m111, ctrl->val,894 MT9M111_RMB_MIRROR_COLS);895 case V4L2_CID_GAIN:896 return mt9m111_set_global_gain(mt9m111, ctrl->val);897 case V4L2_CID_EXPOSURE_AUTO:898 return mt9m111_set_autoexposure(mt9m111, ctrl->val);899 case V4L2_CID_AUTO_WHITE_BALANCE:900 return mt9m111_set_autowhitebalance(mt9m111, ctrl->val);901 case V4L2_CID_TEST_PATTERN:902 return mt9m111_set_test_pattern(mt9m111, ctrl->val);903 case V4L2_CID_COLORFX:904 return mt9m111_set_colorfx(mt9m111, ctrl->val);905 }906 907 return -EINVAL;908}909 910static int mt9m111_suspend(struct mt9m111 *mt9m111)911{912 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);913 int ret;914 915 v4l2_ctrl_s_ctrl(mt9m111->gain, mt9m111_get_global_gain(mt9m111));916 917 ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);918 if (!ret)919 ret = reg_set(RESET, MT9M111_RESET_RESET_SOC |920 MT9M111_RESET_OUTPUT_DISABLE |921 MT9M111_RESET_ANALOG_STANDBY);922 if (!ret)923 ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE);924 925 return ret;926}927 928static void mt9m111_restore_state(struct mt9m111 *mt9m111)929{930 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);931 932 mt9m111_set_context(mt9m111, mt9m111->ctx);933 mt9m111_set_pixfmt(mt9m111, mt9m111->fmt->code);934 mt9m111_setup_geometry(mt9m111, &mt9m111->rect,935 mt9m111->width, mt9m111->height, mt9m111->fmt->code);936 v4l2_ctrl_handler_setup(&mt9m111->hdl);937 mt9m111_reg_mask(client, mt9m111->ctx->read_mode,938 mt9m111->current_mode->reg_val,939 mt9m111->current_mode->reg_mask);940}941 942static int mt9m111_resume(struct mt9m111 *mt9m111)943{944 int ret = mt9m111_enable(mt9m111);945 if (!ret)946 ret = mt9m111_reset(mt9m111);947 if (!ret)948 mt9m111_restore_state(mt9m111);949 950 return ret;951}952 953static int mt9m111_init(struct mt9m111 *mt9m111)954{955 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);956 int ret;957 958 ret = mt9m111_enable(mt9m111);959 if (!ret)960 ret = mt9m111_reset(mt9m111);961 if (!ret)962 ret = mt9m111_set_context(mt9m111, mt9m111->ctx);963 if (ret)964 dev_err(&client->dev, "mt9m111 init failed: %d\n", ret);965 return ret;966}967 968static int mt9m111_power_on(struct mt9m111 *mt9m111)969{970 struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);971 int ret;972 973 ret = clk_prepare_enable(mt9m111->clk);974 if (ret < 0)975 return ret;976 977 ret = regulator_enable(mt9m111->regulator);978 if (ret < 0)979 goto out_clk_disable;980 981 ret = mt9m111_resume(mt9m111);982 if (ret < 0)983 goto out_regulator_disable;984 985 return 0;986 987out_regulator_disable:988 regulator_disable(mt9m111->regulator);989 990out_clk_disable:991 clk_disable_unprepare(mt9m111->clk);992 993 dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret);994 995 return ret;996}997 998static void mt9m111_power_off(struct mt9m111 *mt9m111)999{1000 mt9m111_suspend(mt9m111);1001 regulator_disable(mt9m111->regulator);1002 clk_disable_unprepare(mt9m111->clk);1003}1004 1005static int mt9m111_s_power(struct v4l2_subdev *sd, int on)1006{1007 struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);1008 int ret = 0;1009 1010 mutex_lock(&mt9m111->power_lock);1011 1012 /*1013 * If the power count is modified from 0 to != 0 or from != 0 to 0,1014 * update the power state.1015 */1016 if (mt9m111->power_count == !on) {1017 if (on)1018 ret = mt9m111_power_on(mt9m111);1019 else1020 mt9m111_power_off(mt9m111);1021 }1022 1023 if (!ret) {1024 /* Update the power count. */1025 mt9m111->power_count += on ? 1 : -1;1026 WARN_ON(mt9m111->power_count < 0);1027 }1028 1029 mutex_unlock(&mt9m111->power_lock);1030 return ret;1031}1032 1033static const struct v4l2_ctrl_ops mt9m111_ctrl_ops = {1034 .s_ctrl = mt9m111_s_ctrl,1035};1036 1037static const struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = {1038 .s_power = mt9m111_s_power,1039 .log_status = v4l2_ctrl_subdev_log_status,1040 .subscribe_event = v4l2_ctrl_subdev_subscribe_event,1041 .unsubscribe_event = v4l2_event_subdev_unsubscribe,1042#ifdef CONFIG_VIDEO_ADV_DEBUG1043 .g_register = mt9m111_g_register,1044 .s_register = mt9m111_s_register,1045#endif1046};1047 1048static int mt9m111_get_frame_interval(struct v4l2_subdev *sd,1049 struct v4l2_subdev_state *sd_state,1050 struct v4l2_subdev_frame_interval *fi)1051{1052 struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);1053 1054 /*1055 * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L21056 * subdev active state API.1057 */1058 if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)1059 return -EINVAL;1060 1061 fi->interval = mt9m111->frame_interval;1062 1063 return 0;1064}1065 1066static int mt9m111_set_frame_interval(struct v4l2_subdev *sd,1067 struct v4l2_subdev_state *sd_state,1068 struct v4l2_subdev_frame_interval *fi)1069{1070 struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);1071 const struct mt9m111_mode_info *mode;1072 struct v4l2_fract *fract = &fi->interval;1073 int fps;1074 1075 if (mt9m111->is_streaming)1076 return -EBUSY;1077 1078 /*1079 * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L21080 * subdev active state API.1081 */1082 if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)1083 return -EINVAL;1084 1085 if (fi->pad != 0)1086 return -EINVAL;1087 1088 if (fract->numerator == 0) {1089 fract->denominator = 30;1090 fract->numerator = 1;1091 }1092 1093 fps = DIV_ROUND_CLOSEST(fract->denominator, fract->numerator);1094 1095 /* Find best fitting mode. Do not update the mode if no one was found. */1096 mode = mt9m111_find_mode(mt9m111, fps, mt9m111->width, mt9m111->height);1097 if (!mode)1098 return 0;1099 1100 if (mode->max_fps != fps) {1101 fract->denominator = mode->max_fps;1102 fract->numerator = 1;1103 }1104 1105 mt9m111->current_mode = mode;1106 mt9m111->frame_interval = fi->interval;1107 1108 return 0;1109}1110 1111static int mt9m111_enum_mbus_code(struct v4l2_subdev *sd,1112 struct v4l2_subdev_state *sd_state,1113 struct v4l2_subdev_mbus_code_enum *code)1114{1115 if (code->pad || code->index >= ARRAY_SIZE(mt9m111_colour_fmts))1116 return -EINVAL;1117 1118 code->code = mt9m111_colour_fmts[code->index].code;1119 return 0;1120}1121 1122static int mt9m111_s_stream(struct v4l2_subdev *sd, int enable)1123{1124 struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);1125 1126 mt9m111->is_streaming = !!enable;1127 return 0;1128}1129 1130static int mt9m111_init_state(struct v4l2_subdev *sd,1131 struct v4l2_subdev_state *sd_state)1132{1133 struct v4l2_mbus_framefmt *format =1134 v4l2_subdev_state_get_format(sd_state, 0);1135 1136 format->width = MT9M111_MAX_WIDTH;1137 format->height = MT9M111_MAX_HEIGHT;1138 format->code = mt9m111_colour_fmts[0].code;1139 format->colorspace = mt9m111_colour_fmts[0].colorspace;1140 format->field = V4L2_FIELD_NONE;1141 format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;1142 format->quantization = V4L2_QUANTIZATION_DEFAULT;1143 format->xfer_func = V4L2_XFER_FUNC_DEFAULT;1144 1145 return 0;1146}1147 1148static int mt9m111_get_mbus_config(struct v4l2_subdev *sd,1149 unsigned int pad,1150 struct v4l2_mbus_config *cfg)1151{1152 struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);1153 1154 cfg->type = V4L2_MBUS_PARALLEL;1155 1156 cfg->bus.parallel.flags = V4L2_MBUS_MASTER |1157 V4L2_MBUS_HSYNC_ACTIVE_HIGH |1158 V4L2_MBUS_VSYNC_ACTIVE_HIGH |1159 V4L2_MBUS_DATA_ACTIVE_HIGH;1160 1161 cfg->bus.parallel.flags |= mt9m111->pclk_sample ?1162 V4L2_MBUS_PCLK_SAMPLE_RISING :1163 V4L2_MBUS_PCLK_SAMPLE_FALLING;1164 1165 return 0;1166}1167 1168static const struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {1169 .s_stream = mt9m111_s_stream,1170};1171 1172static const struct v4l2_subdev_pad_ops mt9m111_subdev_pad_ops = {1173 .enum_mbus_code = mt9m111_enum_mbus_code,1174 .get_selection = mt9m111_get_selection,1175 .set_selection = mt9m111_set_selection,1176 .get_fmt = mt9m111_get_fmt,1177 .set_fmt = mt9m111_set_fmt,1178 .get_frame_interval = mt9m111_get_frame_interval,1179 .set_frame_interval = mt9m111_set_frame_interval,1180 .get_mbus_config = mt9m111_get_mbus_config,1181};1182 1183static const struct v4l2_subdev_ops mt9m111_subdev_ops = {1184 .core = &mt9m111_subdev_core_ops,1185 .video = &mt9m111_subdev_video_ops,1186 .pad = &mt9m111_subdev_pad_ops,1187};1188 1189static const struct v4l2_subdev_internal_ops mt9m111_internal_ops = {1190 .init_state = mt9m111_init_state,1191};1192 1193/*1194 * Interface active, can use i2c. If it fails, it can indeed mean, that1195 * this wasn't our capture interface, so, we wait for the right one1196 */1197static int mt9m111_video_probe(struct i2c_client *client)1198{1199 struct mt9m111 *mt9m111 = to_mt9m111(client);1200 s32 data;1201 int ret;1202 1203 ret = mt9m111_s_power(&mt9m111->subdev, 1);1204 if (ret < 0)1205 return ret;1206 1207 data = reg_read(CHIP_VERSION);1208 1209 switch (data) {1210 case 0x143a: /* MT9M111 or MT9M131 */1211 dev_info(&client->dev,1212 "Detected a MT9M111/MT9M131 chip ID %x\n", data);1213 break;1214 case 0x148c: /* MT9M112 */1215 dev_info(&client->dev, "Detected a MT9M112 chip ID %x\n", data);1216 break;1217 default:1218 dev_err(&client->dev,1219 "No MT9M111/MT9M112/MT9M131 chip detected register read %x\n",1220 data);1221 ret = -ENODEV;1222 goto done;1223 }1224 1225 ret = mt9m111_init(mt9m111);1226 if (ret)1227 goto done;1228 1229 ret = v4l2_ctrl_handler_setup(&mt9m111->hdl);1230 1231done:1232 mt9m111_s_power(&mt9m111->subdev, 0);1233 return ret;1234}1235 1236static int mt9m111_probe_fw(struct i2c_client *client, struct mt9m111 *mt9m111)1237{1238 struct v4l2_fwnode_endpoint bus_cfg = {1239 .bus_type = V4L2_MBUS_PARALLEL1240 };1241 struct fwnode_handle *np;1242 int ret;1243 1244 np = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL);1245 if (!np)1246 return -EINVAL;1247 1248 ret = v4l2_fwnode_endpoint_parse(np, &bus_cfg);1249 if (ret)1250 goto out_put_fw;1251 1252 mt9m111->pclk_sample = !!(bus_cfg.bus.parallel.flags &1253 V4L2_MBUS_PCLK_SAMPLE_RISING);1254 1255out_put_fw:1256 fwnode_handle_put(np);1257 return ret;1258}1259 1260static int mt9m111_probe(struct i2c_client *client)1261{1262 struct mt9m111 *mt9m111;1263 struct i2c_adapter *adapter = client->adapter;1264 int ret;1265 1266 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {1267 dev_warn(&adapter->dev,1268 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");1269 return -EIO;1270 }1271 1272 mt9m111 = devm_kzalloc(&client->dev, sizeof(struct mt9m111), GFP_KERNEL);1273 if (!mt9m111)1274 return -ENOMEM;1275 1276 if (dev_fwnode(&client->dev)) {1277 ret = mt9m111_probe_fw(client, mt9m111);1278 if (ret)1279 return ret;1280 }1281 1282 mt9m111->clk = devm_clk_get(&client->dev, "mclk");1283 if (IS_ERR(mt9m111->clk))1284 return PTR_ERR(mt9m111->clk);1285 1286 mt9m111->regulator = devm_regulator_get(&client->dev, "vdd");1287 if (IS_ERR(mt9m111->regulator)) {1288 dev_err(&client->dev, "regulator not found: %ld\n",1289 PTR_ERR(mt9m111->regulator));1290 return PTR_ERR(mt9m111->regulator);1291 }1292 1293 /* Default HIGHPOWER context */1294 mt9m111->ctx = &context_b;1295 1296 v4l2_i2c_subdev_init(&mt9m111->subdev, client, &mt9m111_subdev_ops);1297 mt9m111->subdev.internal_ops = &mt9m111_internal_ops;1298 mt9m111->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |1299 V4L2_SUBDEV_FL_HAS_EVENTS;1300 1301 v4l2_ctrl_handler_init(&mt9m111->hdl, 7);1302 v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,1303 V4L2_CID_VFLIP, 0, 1, 1, 0);1304 v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,1305 V4L2_CID_HFLIP, 0, 1, 1, 0);1306 v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,1307 V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);1308 mt9m111->gain = v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,1309 V4L2_CID_GAIN, 0, 63 * 2 * 2, 1, 32);1310 v4l2_ctrl_new_std_menu(&mt9m111->hdl,1311 &mt9m111_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,1312 V4L2_EXPOSURE_AUTO);1313 v4l2_ctrl_new_std_menu_items(&mt9m111->hdl,1314 &mt9m111_ctrl_ops, V4L2_CID_TEST_PATTERN,1315 ARRAY_SIZE(mt9m111_test_pattern_menu) - 1, 0, 0,1316 mt9m111_test_pattern_menu);1317 v4l2_ctrl_new_std_menu(&mt9m111->hdl, &mt9m111_ctrl_ops,1318 V4L2_CID_COLORFX, V4L2_COLORFX_SOLARIZATION,1319 ~(BIT(V4L2_COLORFX_NONE) |1320 BIT(V4L2_COLORFX_BW) |1321 BIT(V4L2_COLORFX_SEPIA) |1322 BIT(V4L2_COLORFX_NEGATIVE) |1323 BIT(V4L2_COLORFX_SOLARIZATION)),1324 V4L2_COLORFX_NONE);1325 mt9m111->subdev.ctrl_handler = &mt9m111->hdl;1326 if (mt9m111->hdl.error) {1327 ret = mt9m111->hdl.error;1328 return ret;1329 }1330 1331 mt9m111->pad.flags = MEDIA_PAD_FL_SOURCE;1332 mt9m111->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;1333 ret = media_entity_pads_init(&mt9m111->subdev.entity, 1, &mt9m111->pad);1334 if (ret < 0)1335 goto out_hdlfree;1336 1337 mt9m111->current_mode = &mt9m111_mode_data[MT9M111_MODE_SXGA_15FPS];1338 mt9m111->frame_interval.numerator = 1;1339 mt9m111->frame_interval.denominator = mt9m111->current_mode->max_fps;1340 1341 /* Second stage probe - when a capture adapter is there */1342 mt9m111->rect.left = MT9M111_MIN_DARK_COLS;1343 mt9m111->rect.top = MT9M111_MIN_DARK_ROWS;1344 mt9m111->rect.width = MT9M111_MAX_WIDTH;1345 mt9m111->rect.height = MT9M111_MAX_HEIGHT;1346 mt9m111->width = mt9m111->rect.width;1347 mt9m111->height = mt9m111->rect.height;1348 mt9m111->fmt = &mt9m111_colour_fmts[0];1349 mt9m111->lastpage = -1;1350 mutex_init(&mt9m111->power_lock);1351 1352 ret = mt9m111_video_probe(client);1353 if (ret < 0)1354 goto out_entityclean;1355 1356 mt9m111->subdev.dev = &client->dev;1357 ret = v4l2_async_register_subdev(&mt9m111->subdev);1358 if (ret < 0)1359 goto out_entityclean;1360 1361 return 0;1362 1363out_entityclean:1364 media_entity_cleanup(&mt9m111->subdev.entity);1365out_hdlfree:1366 v4l2_ctrl_handler_free(&mt9m111->hdl);1367 1368 return ret;1369}1370 1371static void mt9m111_remove(struct i2c_client *client)1372{1373 struct mt9m111 *mt9m111 = to_mt9m111(client);1374 1375 v4l2_async_unregister_subdev(&mt9m111->subdev);1376 media_entity_cleanup(&mt9m111->subdev.entity);1377 v4l2_ctrl_handler_free(&mt9m111->hdl);1378}1379static const struct of_device_id mt9m111_of_match[] = {1380 { .compatible = "micron,mt9m111", },1381 {},1382};1383MODULE_DEVICE_TABLE(of, mt9m111_of_match);1384 1385static const struct i2c_device_id mt9m111_id[] = {1386 { "mt9m111" },1387 { }1388};1389MODULE_DEVICE_TABLE(i2c, mt9m111_id);1390 1391static struct i2c_driver mt9m111_i2c_driver = {1392 .driver = {1393 .name = "mt9m111",1394 .of_match_table = mt9m111_of_match,1395 },1396 .probe = mt9m111_probe,1397 .remove = mt9m111_remove,1398 .id_table = mt9m111_id,1399};1400 1401module_i2c_driver(mt9m111_i2c_driver);1402 1403MODULE_DESCRIPTION("Micron/Aptina MT9M111/MT9M112/MT9M131 Camera driver");1404MODULE_AUTHOR("Robert Jarzmik");1405MODULE_LICENSE("GPL");1406