^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * mt9t112 Camera Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2018 Jacopo Mondi <jacopo+renesas@jmondi.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2009 Renesas Solutions Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Kuninori Morimoto <morimoto.kuninori@renesas.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Based on ov772x driver, mt9m111 driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (C) 2008 Kuninori Morimoto <morimoto.kuninori@renesas.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Copyright (C) 2008 Magnus Damm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * TODO: This driver lacks support for frame rate control due to missing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * register level documentation and suitable hardware for testing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * v4l-utils compliance tools will report errors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/v4l2-mediabus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <media/i2c/mt9t112.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <media/v4l2-common.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <media/v4l2-image-sizes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <media/v4l2-subdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* you can check PLL/clock info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* #define EXT_CLOCK 24000000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * macro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) ***********************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * frame size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define MAX_WIDTH 2048
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define MAX_HEIGHT 1536
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * macro of read/write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define ECHECKER(ret, x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) (ret) = (x); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if ((ret) < 0) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return (ret); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define mt9t112_reg_write(ret, client, a, b) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) ECHECKER(ret, __mt9t112_reg_write(client, a, b))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define mt9t112_mcu_write(ret, client, a, b) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ECHECKER(ret, __mt9t112_mcu_write(client, a, b))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define mt9t112_reg_mask_set(ret, client, a, b, c) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) ECHECKER(ret, __mt9t112_reg_mask_set(client, a, b, c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define mt9t112_mcu_mask_set(ret, client, a, b, c) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ECHECKER(ret, __mt9t112_mcu_mask_set(client, a, b, c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define mt9t112_reg_read(ret, client, a) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) ECHECKER(ret, __mt9t112_reg_read(client, a))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * Logical address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define _VAR(id, offset, base) (base | (id & 0x1f) << 10 | (offset & 0x3ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define VAR(id, offset) _VAR(id, offset, 0x0000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define VAR8(id, offset) _VAR(id, offset, 0x8000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) ***********************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct mt9t112_format {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) u32 code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) enum v4l2_colorspace colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) u16 fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) u16 order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct mt9t112_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct v4l2_subdev subdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct mt9t112_platform_data *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct v4l2_rect frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct gpio_desc *standby_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) const struct mt9t112_format *format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) int num_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) bool init_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * supported format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ***********************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static const struct mt9t112_format mt9t112_cfmts[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .code = MEDIA_BUS_FMT_UYVY8_2X8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .fmt = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .order = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .code = MEDIA_BUS_FMT_VYUY8_2X8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .fmt = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .order = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .code = MEDIA_BUS_FMT_YUYV8_2X8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .fmt = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .order = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .code = MEDIA_BUS_FMT_YVYU8_2X8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .fmt = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .order = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .fmt = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .order = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .code = MEDIA_BUS_FMT_RGB565_2X8_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .fmt = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .order = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * general function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ***********************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static struct mt9t112_priv *to_mt9t112(const struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return container_of(i2c_get_clientdata(client),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct mt9t112_priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static int __mt9t112_reg_read(const struct i2c_client *client, u16 command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct i2c_msg msg[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) u8 buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) command = swab16(command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) msg[0].addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) msg[0].flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) msg[0].len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) msg[0].buf = (u8 *)&command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) msg[1].addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) msg[1].flags = I2C_M_RD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) msg[1].len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) msg[1].buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * If return value of this function is < 0, it means error, else,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * below 16bit is valid data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ret = i2c_transfer(client->adapter, msg, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) memcpy(&ret, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return swab16(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static int __mt9t112_reg_write(const struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) u16 command, u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct i2c_msg msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) u8 buf[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) command = swab16(command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) data = swab16(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) memcpy(buf + 0, &command, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) memcpy(buf + 2, &data, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) msg.addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) msg.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) msg.len = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) msg.buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * i2c_transfer return message length, but this function should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * return 0 if correct case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) ret = i2c_transfer(client->adapter, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return ret >= 0 ? 0 : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static int __mt9t112_reg_mask_set(const struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) u16 command, u16 mask, u16 set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) int val = __mt9t112_reg_read(client, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) val &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) val |= set & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return __mt9t112_reg_write(client, command, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* mcu access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static int __mt9t112_mcu_read(const struct i2c_client *client, u16 command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) ret = __mt9t112_reg_write(client, 0x098E, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return __mt9t112_reg_read(client, 0x0990);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static int __mt9t112_mcu_write(const struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) u16 command, u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ret = __mt9t112_reg_write(client, 0x098E, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return __mt9t112_reg_write(client, 0x0990, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static int __mt9t112_mcu_mask_set(const struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) u16 command, u16 mask, u16 set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) int val = __mt9t112_mcu_read(client, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) val &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) val |= set & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return __mt9t112_mcu_write(client, command, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static int mt9t112_reset(const struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) mt9t112_reg_mask_set(ret, client, 0x001a, 0x0001, 0x0001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) usleep_range(1000, 5000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) mt9t112_reg_mask_set(ret, client, 0x001a, 0x0001, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) #ifndef EXT_CLOCK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) #define CLOCK_INFO(a, b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) #define CLOCK_INFO(a, b) mt9t112_clock_info(a, b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static int mt9t112_clock_info(const struct i2c_client *client, u32 ext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) int m, n, p1, p2, p3, p4, p5, p6, p7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) u32 vco, clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) char *enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) ext /= 1000; /* kbyte order */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) mt9t112_reg_read(n, client, 0x0012);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) p1 = n & 0x000f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) n = n >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) p2 = n & 0x000f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) n = n >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) p3 = n & 0x000f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) mt9t112_reg_read(n, client, 0x002a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) p4 = n & 0x000f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) n = n >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) p5 = n & 0x000f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) n = n >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) p6 = n & 0x000f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) mt9t112_reg_read(n, client, 0x002c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) p7 = n & 0x000f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) mt9t112_reg_read(n, client, 0x0010);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) m = n & 0x00ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) n = (n >> 8) & 0x003f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) enable = ((ext < 6000) || (ext > 54000)) ? "X" : "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) dev_dbg(&client->dev, "EXTCLK : %10u K %s\n", ext, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) vco = 2 * m * ext / (n + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) enable = ((vco < 384000) || (vco > 768000)) ? "X" : "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) dev_dbg(&client->dev, "VCO : %10u K %s\n", vco, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) clk = vco / (p1 + 1) / (p2 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) enable = (clk > 96000) ? "X" : "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) dev_dbg(&client->dev, "PIXCLK : %10u K %s\n", clk, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) clk = vco / (p3 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) enable = (clk > 768000) ? "X" : "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) dev_dbg(&client->dev, "MIPICLK : %10u K %s\n", clk, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) clk = vco / (p6 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) enable = (clk > 96000) ? "X" : "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) dev_dbg(&client->dev, "MCU CLK : %10u K %s\n", clk, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) clk = vco / (p5 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) enable = (clk > 54000) ? "X" : "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) dev_dbg(&client->dev, "SOC CLK : %10u K %s\n", clk, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) clk = vco / (p4 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) enable = (clk > 70000) ? "X" : "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) dev_dbg(&client->dev, "Sensor CLK : %10u K %s\n", clk, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) clk = vco / (p7 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) dev_dbg(&client->dev, "External sensor : %10u K\n", clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) clk = ext / (n + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) enable = ((clk < 2000) || (clk > 24000)) ? "X" : "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) dev_dbg(&client->dev, "PFD : %10u K %s\n", clk, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static int mt9t112_set_a_frame_size(const struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) u16 width, u16 height)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) u16 wstart = (MAX_WIDTH - width) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) u16 hstart = (MAX_HEIGHT - height) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /* (Context A) Image Width/Height. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) mt9t112_mcu_write(ret, client, VAR(26, 0), width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) mt9t112_mcu_write(ret, client, VAR(26, 2), height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /* (Context A) Output Width/Height. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) mt9t112_mcu_write(ret, client, VAR(18, 43), 8 + width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) mt9t112_mcu_write(ret, client, VAR(18, 45), 8 + height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /* (Context A) Start Row/Column. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) mt9t112_mcu_write(ret, client, VAR(18, 2), 4 + hstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) mt9t112_mcu_write(ret, client, VAR(18, 4), 4 + wstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /* (Context A) End Row/Column. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) mt9t112_mcu_write(ret, client, VAR(18, 6), 11 + height + hstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) mt9t112_mcu_write(ret, client, VAR(18, 8), 11 + width + wstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x06);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static int mt9t112_set_pll_dividers(const struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) u8 m, u8 n, u8 p1, u8 p2, u8 p3, u8 p4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) u8 p5, u8 p6, u8 p7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /* N/M */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) val = (n << 8) | (m << 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) mt9t112_reg_mask_set(ret, client, 0x0010, 0x3fff, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) /* P1/P2/P3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) val = ((p3 & 0x0F) << 8) | ((p2 & 0x0F) << 4) | ((p1 & 0x0F) << 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) mt9t112_reg_mask_set(ret, client, 0x0012, 0x0fff, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /* P4/P5/P6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) val = (0x7 << 12) | ((p6 & 0x0F) << 8) | ((p5 & 0x0F) << 4) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) ((p4 & 0x0F) << 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) mt9t112_reg_mask_set(ret, client, 0x002A, 0x7fff, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* P7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) val = (0x1 << 12) | ((p7 & 0x0F) << 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) mt9t112_reg_mask_set(ret, client, 0x002C, 0x100f, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static int mt9t112_init_pll(const struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct mt9t112_priv *priv = to_mt9t112(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) int data, i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) mt9t112_reg_mask_set(ret, client, 0x0014, 0x003, 0x0001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /* PLL control: BYPASS PLL = 8517. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) mt9t112_reg_write(ret, client, 0x0014, 0x2145);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) /* Replace these registers when new timing parameters are generated. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) mt9t112_set_pll_dividers(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) priv->info->divider.m, priv->info->divider.n,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) priv->info->divider.p1, priv->info->divider.p2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) priv->info->divider.p3, priv->info->divider.p4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) priv->info->divider.p5, priv->info->divider.p6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) priv->info->divider.p7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * TEST_BYPASS on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * PLL_ENABLE on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * SEL_LOCK_DET on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * TEST_BYPASS off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) mt9t112_reg_write(ret, client, 0x0014, 0x2525);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) mt9t112_reg_write(ret, client, 0x0014, 0x2527);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) mt9t112_reg_write(ret, client, 0x0014, 0x3427);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) mt9t112_reg_write(ret, client, 0x0014, 0x3027);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) mdelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * PLL_BYPASS off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * Reference clock count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * I2C Master Clock Divider
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) mt9t112_reg_write(ret, client, 0x0014, 0x3046);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) /* JPEG initialization workaround */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) mt9t112_reg_write(ret, client, 0x0016, 0x0400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) mt9t112_reg_write(ret, client, 0x0022, 0x0190);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) mt9t112_reg_write(ret, client, 0x3B84, 0x0212);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) /* External sensor clock is PLL bypass. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) mt9t112_reg_write(ret, client, 0x002E, 0x0500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) mt9t112_reg_mask_set(ret, client, 0x0018, 0x0002, 0x0002);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) mt9t112_reg_mask_set(ret, client, 0x3B82, 0x0004, 0x0004);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /* MCU disabled. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) mt9t112_reg_mask_set(ret, client, 0x0018, 0x0004, 0x0004);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /* Out of standby. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) mt9t112_reg_mask_set(ret, client, 0x0018, 0x0001, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) mdelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * Standby Workaround
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * Disable Secondary I2C Pads
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) mt9t112_reg_write(ret, client, 0x0614, 0x0001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) mt9t112_reg_write(ret, client, 0x0614, 0x0001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) mt9t112_reg_write(ret, client, 0x0614, 0x0001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) mt9t112_reg_write(ret, client, 0x0614, 0x0001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) mt9t112_reg_write(ret, client, 0x0614, 0x0001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) mt9t112_reg_write(ret, client, 0x0614, 0x0001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /* Poll to verify out of standby. Must Poll this bit. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) for (i = 0; i < 100; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) mt9t112_reg_read(data, client, 0x0018);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (!(data & 0x4000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) mdelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) static int mt9t112_init_setting(const struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) /* Adaptive Output Clock (A) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) mt9t112_mcu_mask_set(ret, client, VAR(26, 160), 0x0040, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* Read Mode (A) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) mt9t112_mcu_write(ret, client, VAR(18, 12), 0x0024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* Fine Correction (A) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) mt9t112_mcu_write(ret, client, VAR(18, 15), 0x00CC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /* Fine IT Min (A) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) mt9t112_mcu_write(ret, client, VAR(18, 17), 0x01f1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /* Fine IT Max Margin (A) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) mt9t112_mcu_write(ret, client, VAR(18, 19), 0x00fF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) /* Base Frame Lines (A) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) mt9t112_mcu_write(ret, client, VAR(18, 29), 0x032D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /* Min Line Length (A) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) mt9t112_mcu_write(ret, client, VAR(18, 31), 0x073a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) /* Line Length (A) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) mt9t112_mcu_write(ret, client, VAR(18, 37), 0x07d0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /* Adaptive Output Clock (B) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) mt9t112_mcu_mask_set(ret, client, VAR(27, 160), 0x0040, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) /* Row Start (B) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) mt9t112_mcu_write(ret, client, VAR(18, 74), 0x004);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) /* Column Start (B) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) mt9t112_mcu_write(ret, client, VAR(18, 76), 0x004);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /* Row End (B) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) mt9t112_mcu_write(ret, client, VAR(18, 78), 0x60B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /* Column End (B) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) mt9t112_mcu_write(ret, client, VAR(18, 80), 0x80B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /* Fine Correction (B) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) mt9t112_mcu_write(ret, client, VAR(18, 87), 0x008C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) /* Fine IT Min (B) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) mt9t112_mcu_write(ret, client, VAR(18, 89), 0x01F1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /* Fine IT Max Margin (B) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) mt9t112_mcu_write(ret, client, VAR(18, 91), 0x00FF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /* Base Frame Lines (B) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) mt9t112_mcu_write(ret, client, VAR(18, 101), 0x0668);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /* Min Line Length (B) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) mt9t112_mcu_write(ret, client, VAR(18, 103), 0x0AF0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) /* Line Length (B) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) mt9t112_mcu_write(ret, client, VAR(18, 109), 0x0AF0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) * Flicker Detection registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * This section should be replaced whenever new timing file is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * generated. All the following registers need to be replaced.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) * Following registers are generated from Register Wizard but user can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * modify them. For detail see auto flicker detection tuning.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) /* FD_FDPERIOD_SELECT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) mt9t112_mcu_write(ret, client, VAR8(8, 5), 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /* PRI_B_CONFIG_FD_ALGO_RUN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) mt9t112_mcu_write(ret, client, VAR(27, 17), 0x0003);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /* PRI_A_CONFIG_FD_ALGO_RUN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) mt9t112_mcu_write(ret, client, VAR(26, 17), 0x0003);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * AFD range detection tuning registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) /* Search_f1_50 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) mt9t112_mcu_write(ret, client, VAR8(18, 165), 0x25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) /* Search_f2_50 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) mt9t112_mcu_write(ret, client, VAR8(18, 166), 0x28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /* Search_f1_60 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) mt9t112_mcu_write(ret, client, VAR8(18, 167), 0x2C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) /* Search_f2_60 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) mt9t112_mcu_write(ret, client, VAR8(18, 168), 0x2F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /* Period_50Hz (A) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) mt9t112_mcu_write(ret, client, VAR8(18, 68), 0xBA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) /* Secret register by Aptina. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) /* Period_50Hz (A MSB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) mt9t112_mcu_write(ret, client, VAR8(18, 303), 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) /* Period_60Hz (A) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) mt9t112_mcu_write(ret, client, VAR8(18, 69), 0x9B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) /* Secret register by Aptina. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /* Period_60Hz (A MSB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) mt9t112_mcu_write(ret, client, VAR8(18, 301), 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /* Period_50Hz (B) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) mt9t112_mcu_write(ret, client, VAR8(18, 140), 0x82);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) /* Secret register by Aptina. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) /* Period_50Hz (B) MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) mt9t112_mcu_write(ret, client, VAR8(18, 304), 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) /* Period_60Hz (B) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) mt9t112_mcu_write(ret, client, VAR8(18, 141), 0x6D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) /* Secret register by Aptina. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* Period_60Hz (B) MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) mt9t112_mcu_write(ret, client, VAR8(18, 302), 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) /* FD Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) mt9t112_mcu_write(ret, client, VAR8(8, 2), 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) /* Stat_min */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) mt9t112_mcu_write(ret, client, VAR8(8, 9), 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /* Stat_max */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) mt9t112_mcu_write(ret, client, VAR8(8, 10), 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /* Min_amplitude */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) mt9t112_mcu_write(ret, client, VAR8(8, 12), 0x0A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /* RX FIFO Watermark (A) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) mt9t112_mcu_write(ret, client, VAR(18, 70), 0x0014);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) /* RX FIFO Watermark (B) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) mt9t112_mcu_write(ret, client, VAR(18, 142), 0x0014);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* MCLK: 16MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) * PCLK: 73MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * CorePixCLK: 36.5 MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) mt9t112_mcu_write(ret, client, VAR8(18, 0x0044), 133);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) mt9t112_mcu_write(ret, client, VAR8(18, 0x0045), 110);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) mt9t112_mcu_write(ret, client, VAR8(18, 0x008c), 130);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) mt9t112_mcu_write(ret, client, VAR8(18, 0x008d), 108);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) mt9t112_mcu_write(ret, client, VAR8(18, 0x00A5), 27);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) mt9t112_mcu_write(ret, client, VAR8(18, 0x00a6), 30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) mt9t112_mcu_write(ret, client, VAR8(18, 0x00a7), 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) mt9t112_mcu_write(ret, client, VAR8(18, 0x00a8), 35);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) static int mt9t112_auto_focus_setting(const struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) mt9t112_mcu_write(ret, client, VAR(12, 13), 0x000F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) mt9t112_mcu_write(ret, client, VAR(12, 23), 0x0F0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x06);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) mt9t112_reg_write(ret, client, 0x0614, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) mt9t112_mcu_write(ret, client, VAR8(12, 2), 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) mt9t112_mcu_write(ret, client, VAR(12, 3), 0x0002);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) mt9t112_mcu_write(ret, client, VAR(17, 3), 0x8001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) mt9t112_mcu_write(ret, client, VAR(17, 11), 0x0025);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) mt9t112_mcu_write(ret, client, VAR(17, 13), 0x0193);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) mt9t112_mcu_write(ret, client, VAR8(17, 33), 0x18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) static int mt9t112_auto_focus_trigger(const struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) mt9t112_mcu_write(ret, client, VAR8(12, 25), 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) static int mt9t112_init_camera(const struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) ECHECKER(ret, mt9t112_reset(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) ECHECKER(ret, mt9t112_init_pll(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) ECHECKER(ret, mt9t112_init_setting(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) ECHECKER(ret, mt9t112_auto_focus_setting(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) mt9t112_reg_mask_set(ret, client, 0x0018, 0x0004, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) /* Analog setting B.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) mt9t112_reg_write(ret, client, 0x3084, 0x2409);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) mt9t112_reg_write(ret, client, 0x3092, 0x0A49);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) mt9t112_reg_write(ret, client, 0x3094, 0x4949);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) mt9t112_reg_write(ret, client, 0x3096, 0x4950);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * Disable adaptive clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * PRI_A_CONFIG_JPEG_OB_TX_CONTROL_VAR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * PRI_B_CONFIG_JPEG_OB_TX_CONTROL_VAR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) mt9t112_mcu_write(ret, client, VAR(26, 160), 0x0A2E);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) mt9t112_mcu_write(ret, client, VAR(27, 160), 0x0A2E);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) * Configure Status in Status_before_length Format and enable header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * PRI_B_CONFIG_JPEG_OB_TX_CONTROL_VAR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) mt9t112_mcu_write(ret, client, VAR(27, 144), 0x0CB4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * Enable JPEG in context B.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) * PRI_B_CONFIG_JPEG_OB_TX_CONTROL_VAR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) mt9t112_mcu_write(ret, client, VAR8(27, 142), 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) /* Disable Dac_TXLO. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) mt9t112_reg_write(ret, client, 0x316C, 0x350F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) /* Set max slew rates. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) mt9t112_reg_write(ret, client, 0x1E, 0x777);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) /************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * v4l2_subdev_core_ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) ***********************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) #ifdef CONFIG_VIDEO_ADV_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) static int mt9t112_g_register(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct v4l2_dbg_register *reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct i2c_client *client = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) reg->size = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) mt9t112_reg_read(ret, client, reg->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) reg->val = (__u64)ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) static int mt9t112_s_register(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) const struct v4l2_dbg_register *reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) struct i2c_client *client = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) mt9t112_reg_write(ret, client, reg->reg, reg->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) static int mt9t112_power_on(struct mt9t112_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) ret = clk_prepare_enable(priv->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (priv->standby_gpio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) gpiod_set_value(priv->standby_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) static int mt9t112_power_off(struct mt9t112_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) clk_disable_unprepare(priv->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (priv->standby_gpio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) gpiod_set_value(priv->standby_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) static int mt9t112_s_power(struct v4l2_subdev *sd, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) struct i2c_client *client = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) struct mt9t112_priv *priv = to_mt9t112(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return on ? mt9t112_power_on(priv) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) mt9t112_power_off(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) static const struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) #ifdef CONFIG_VIDEO_ADV_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) .g_register = mt9t112_g_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) .s_register = mt9t112_s_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) .s_power = mt9t112_s_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) /************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * v4l2_subdev_video_ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) **********************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) static int mt9t112_s_stream(struct v4l2_subdev *sd, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) struct i2c_client *client = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) struct mt9t112_priv *priv = to_mt9t112(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (!enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) /* FIXME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * If user selected large output size, and used it long time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) * mt9t112 camera will be very warm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) * But current driver can not stop mt9t112 camera.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) * So, set small size here to solve this problem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) mt9t112_set_a_frame_size(client, VGA_WIDTH, VGA_HEIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (!priv->init_done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) u16 param = MT9T112_FLAG_PCLK_RISING_EDGE & priv->info->flags ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 0x0001 : 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) ECHECKER(ret, mt9t112_init_camera(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) /* Invert PCLK (Data sampled on falling edge of pixclk). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) mt9t112_reg_write(ret, client, 0x3C20, param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) priv->init_done = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) mt9t112_mcu_write(ret, client, VAR(26, 7), priv->format->fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) mt9t112_mcu_write(ret, client, VAR(26, 9), priv->format->order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x06);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) mt9t112_set_a_frame_size(client, priv->frame.width, priv->frame.height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) ECHECKER(ret, mt9t112_auto_focus_trigger(client));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) dev_dbg(&client->dev, "format : %d\n", priv->format->code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) dev_dbg(&client->dev, "size : %d x %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) priv->frame.width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) priv->frame.height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) CLOCK_INFO(client, EXT_CLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) static int mt9t112_set_params(struct mt9t112_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) const struct v4l2_rect *rect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) u32 code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) * get color format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) for (i = 0; i < priv->num_formats; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (mt9t112_cfmts[i].code == code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (i == priv->num_formats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) priv->frame = *rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) * frame size check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) v4l_bound_align_image(&priv->frame.width, 0, MAX_WIDTH, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) &priv->frame.height, 0, MAX_HEIGHT, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) priv->format = mt9t112_cfmts + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) static int mt9t112_get_selection(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) struct v4l2_subdev_selection *sel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) struct i2c_client *client = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) struct mt9t112_priv *priv = to_mt9t112(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) switch (sel->target) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) case V4L2_SEL_TGT_CROP_BOUNDS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) sel->r.left = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) sel->r.top = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) sel->r.width = MAX_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) sel->r.height = MAX_HEIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) case V4L2_SEL_TGT_CROP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) sel->r = priv->frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) static int mt9t112_set_selection(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) struct v4l2_subdev_selection *sel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) struct i2c_client *client = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) struct mt9t112_priv *priv = to_mt9t112(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) const struct v4l2_rect *rect = &sel->r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) sel->target != V4L2_SEL_TGT_CROP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) return mt9t112_set_params(priv, rect, priv->format->code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) static int mt9t112_get_fmt(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) struct v4l2_subdev_format *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) struct v4l2_mbus_framefmt *mf = &format->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) struct i2c_client *client = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) struct mt9t112_priv *priv = to_mt9t112(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (format->pad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) mf->width = priv->frame.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) mf->height = priv->frame.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) mf->colorspace = priv->format->colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) mf->code = priv->format->code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) mf->field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) static int mt9t112_s_fmt(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) struct v4l2_mbus_framefmt *mf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) struct i2c_client *client = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) struct mt9t112_priv *priv = to_mt9t112(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) struct v4l2_rect rect = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) .width = mf->width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) .height = mf->height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) .left = priv->frame.left,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) .top = priv->frame.top,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) ret = mt9t112_set_params(priv, &rect, mf->code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) mf->colorspace = priv->format->colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) static int mt9t112_set_fmt(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) struct v4l2_subdev_format *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) struct i2c_client *client = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) struct v4l2_mbus_framefmt *mf = &format->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) struct mt9t112_priv *priv = to_mt9t112(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (format->pad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) for (i = 0; i < priv->num_formats; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (mt9t112_cfmts[i].code == mf->code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (i == priv->num_formats) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) mf->colorspace = V4L2_COLORSPACE_JPEG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) mf->colorspace = mt9t112_cfmts[i].colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) v4l_bound_align_image(&mf->width, 0, MAX_WIDTH, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) &mf->height, 0, MAX_HEIGHT, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) mf->field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) return mt9t112_s_fmt(sd, mf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) cfg->try_fmt = *mf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) static int mt9t112_enum_mbus_code(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) struct v4l2_subdev_mbus_code_enum *code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) struct i2c_client *client = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) struct mt9t112_priv *priv = to_mt9t112(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) if (code->pad || code->index >= priv->num_formats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) code->code = mt9t112_cfmts[code->index].code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) static const struct v4l2_subdev_video_ops mt9t112_subdev_video_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) .s_stream = mt9t112_s_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) static const struct v4l2_subdev_pad_ops mt9t112_subdev_pad_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) .enum_mbus_code = mt9t112_enum_mbus_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) .get_selection = mt9t112_get_selection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) .set_selection = mt9t112_set_selection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) .get_fmt = mt9t112_get_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) .set_fmt = mt9t112_set_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) /************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) * i2c driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) ***********************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) static const struct v4l2_subdev_ops mt9t112_subdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) .core = &mt9t112_subdev_core_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) .video = &mt9t112_subdev_video_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) .pad = &mt9t112_subdev_pad_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) static int mt9t112_camera_probe(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) struct mt9t112_priv *priv = to_mt9t112(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) const char *devname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) int chipid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) ret = mt9t112_s_power(&priv->subdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) /* Check and show chip ID. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) mt9t112_reg_read(chipid, client, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) switch (chipid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) case 0x2680:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) devname = "mt9t111";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) priv->num_formats = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) case 0x2682:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) devname = "mt9t112";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) priv->num_formats = ARRAY_SIZE(mt9t112_cfmts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) dev_err(&client->dev, "Product ID error %04x\n", chipid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) dev_info(&client->dev, "%s chip ID %04x\n", devname, chipid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) mt9t112_s_power(&priv->subdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) static int mt9t112_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) const struct i2c_device_id *did)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) struct mt9t112_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (!client->dev.platform_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) dev_err(&client->dev, "mt9t112: missing platform data!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) priv->info = client->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) priv->init_done = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) v4l2_i2c_subdev_init(&priv->subdev, client, &mt9t112_subdev_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) priv->clk = devm_clk_get(&client->dev, "extclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (PTR_ERR(priv->clk) == -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) priv->clk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) } else if (IS_ERR(priv->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) dev_err(&client->dev, "Unable to get clock \"extclk\"\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) return PTR_ERR(priv->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) priv->standby_gpio = devm_gpiod_get_optional(&client->dev, "standby",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) GPIOD_OUT_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (IS_ERR(priv->standby_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) dev_err(&client->dev, "Unable to get gpio \"standby\"\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) return PTR_ERR(priv->standby_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) ret = mt9t112_camera_probe(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) return v4l2_async_register_subdev(&priv->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) static int mt9t112_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) struct mt9t112_priv *priv = to_mt9t112(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) clk_disable_unprepare(priv->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) v4l2_async_unregister_subdev(&priv->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) static const struct i2c_device_id mt9t112_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) { "mt9t112", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) MODULE_DEVICE_TABLE(i2c, mt9t112_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) static struct i2c_driver mt9t112_i2c_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) .name = "mt9t112",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) .probe = mt9t112_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) .remove = mt9t112_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) .id_table = mt9t112_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) module_i2c_driver(mt9t112_i2c_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) MODULE_DESCRIPTION("V4L2 driver for MT9T111/MT9T112 camera sensor");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) MODULE_AUTHOR("Kuninori Morimoto");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) MODULE_LICENSE("GPL v2");