brintos

brintos / linux-shallow public Read only

0
0
Text · 75.8 KiB · 5f0b0ad Raw
2502 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * mt9m114.c onsemi MT9M114 sensor driver4 *5 * Copyright (c) 2020-2023 Laurent Pinchart <laurent.pinchart@ideasonboard.com>6 * Copyright (c) 2012 Analog Devices Inc.7 *8 * Almost complete rewrite of work by Scott Jiang <Scott.Jiang.Linux@gmail.com>9 * itself based on work from Andrew Chew <achew@nvidia.com>.10 */11 12#include <linux/clk.h>13#include <linux/delay.h>14#include <linux/errno.h>15#include <linux/gpio/consumer.h>16#include <linux/i2c.h>17#include <linux/mod_devicetable.h>18#include <linux/module.h>19#include <linux/mutex.h>20#include <linux/pm_runtime.h>21#include <linux/regmap.h>22#include <linux/regulator/consumer.h>23#include <linux/types.h>24#include <linux/videodev2.h>25 26#include <media/v4l2-async.h>27#include <media/v4l2-cci.h>28#include <media/v4l2-ctrls.h>29#include <media/v4l2-device.h>30#include <media/v4l2-fwnode.h>31#include <media/v4l2-mediabus.h>32#include <media/v4l2-subdev.h>33 34/* Sysctl registers */35#define MT9M114_CHIP_ID					CCI_REG16(0x0000)36#define MT9M114_COMMAND_REGISTER			CCI_REG16(0x0080)37#define MT9M114_COMMAND_REGISTER_APPLY_PATCH			BIT(0)38#define MT9M114_COMMAND_REGISTER_SET_STATE			BIT(1)39#define MT9M114_COMMAND_REGISTER_REFRESH			BIT(2)40#define MT9M114_COMMAND_REGISTER_WAIT_FOR_EVENT			BIT(3)41#define MT9M114_COMMAND_REGISTER_OK				BIT(15)42#define MT9M114_RESET_AND_MISC_CONTROL			CCI_REG16(0x001a)43#define MT9M114_RESET_SOC					BIT(0)44#define MT9M114_PAD_SLEW				CCI_REG16(0x001e)45#define MT9M114_PAD_CONTROL				CCI_REG16(0x0032)46 47/* XDMA registers */48#define MT9M114_ACCESS_CTL_STAT				CCI_REG16(0x0982)49#define MT9M114_PHYSICAL_ADDRESS_ACCESS			CCI_REG16(0x098a)50#define MT9M114_LOGICAL_ADDRESS_ACCESS			CCI_REG16(0x098e)51 52/* Sensor Core registers */53#define MT9M114_COARSE_INTEGRATION_TIME			CCI_REG16(0x3012)54#define MT9M114_FINE_INTEGRATION_TIME			CCI_REG16(0x3014)55#define MT9M114_RESET_REGISTER				CCI_REG16(0x301a)56#define MT9M114_RESET_REGISTER_LOCK_REG				BIT(3)57#define MT9M114_RESET_REGISTER_MASK_BAD				BIT(9)58#define MT9M114_FLASH					CCI_REG16(0x3046)59#define MT9M114_GREEN1_GAIN				CCI_REG16(0x3056)60#define MT9M114_BLUE_GAIN				CCI_REG16(0x3058)61#define MT9M114_RED_GAIN				CCI_REG16(0x305a)62#define MT9M114_GREEN2_GAIN				CCI_REG16(0x305c)63#define MT9M114_GLOBAL_GAIN				CCI_REG16(0x305e)64#define MT9M114_GAIN_DIGITAL_GAIN(n)				((n) << 12)65#define MT9M114_GAIN_DIGITAL_GAIN_MASK				(0xf << 12)66#define MT9M114_GAIN_ANALOG_GAIN(n)				((n) << 0)67#define MT9M114_GAIN_ANALOG_GAIN_MASK				(0xff << 0)68#define MT9M114_CUSTOMER_REV				CCI_REG16(0x31fe)69 70/* Monitor registers */71#define MT9M114_MON_MAJOR_VERSION			CCI_REG16(0x8000)72#define MT9M114_MON_MINOR_VERSION			CCI_REG16(0x8002)73#define MT9M114_MON_RELEASE_VERSION			CCI_REG16(0x8004)74 75/* Auto-Exposure Track registers */76#define MT9M114_AE_TRACK_ALGO				CCI_REG16(0xa804)77#define MT9M114_AE_TRACK_EXEC_AUTOMATIC_EXPOSURE		BIT(0)78#define MT9M114_AE_TRACK_AE_TRACKING_DAMPENING_SPEED	CCI_REG8(0xa80a)79 80/* Color Correction Matrix registers */81#define MT9M114_CCM_ALGO				CCI_REG16(0xb404)82#define MT9M114_CCM_EXEC_CALC_CCM_MATRIX			BIT(4)83#define MT9M114_CCM_DELTA_GAIN				CCI_REG8(0xb42a)84 85/* Camera Control registers */86#define MT9M114_CAM_SENSOR_CFG_Y_ADDR_START		CCI_REG16(0xc800)87#define MT9M114_CAM_SENSOR_CFG_X_ADDR_START		CCI_REG16(0xc802)88#define MT9M114_CAM_SENSOR_CFG_Y_ADDR_END		CCI_REG16(0xc804)89#define MT9M114_CAM_SENSOR_CFG_X_ADDR_END		CCI_REG16(0xc806)90#define MT9M114_CAM_SENSOR_CFG_PIXCLK			CCI_REG32(0xc808)91#define MT9M114_CAM_SENSOR_CFG_ROW_SPEED		CCI_REG16(0xc80c)92#define MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MIN	CCI_REG16(0xc80e)93#define MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MAX	CCI_REG16(0xc810)94#define MT9M114_CAM_SENSOR_CFG_FRAME_LENGTH_LINES	CCI_REG16(0xc812)95#define MT9M114_CAM_SENSOR_CFG_FRAME_LENGTH_LINES_MAX		6553596#define MT9M114_CAM_SENSOR_CFG_LINE_LENGTH_PCK		CCI_REG16(0xc814)97#define MT9M114_CAM_SENSOR_CFG_LINE_LENGTH_PCK_MAX		819198#define MT9M114_CAM_SENSOR_CFG_FINE_CORRECTION		CCI_REG16(0xc816)99#define MT9M114_CAM_SENSOR_CFG_CPIPE_LAST_ROW		CCI_REG16(0xc818)100#define MT9M114_CAM_SENSOR_CFG_REG_0_DATA		CCI_REG16(0xc826)101#define MT9M114_CAM_SENSOR_CONTROL_READ_MODE		CCI_REG16(0xc834)102#define MT9M114_CAM_SENSOR_CONTROL_HORZ_MIRROR_EN		BIT(0)103#define MT9M114_CAM_SENSOR_CONTROL_VERT_FLIP_EN			BIT(1)104#define MT9M114_CAM_SENSOR_CONTROL_X_READ_OUT_NORMAL		(0 << 4)105#define MT9M114_CAM_SENSOR_CONTROL_X_READ_OUT_SKIPPING		(1 << 4)106#define MT9M114_CAM_SENSOR_CONTROL_X_READ_OUT_AVERAGE		(2 << 4)107#define MT9M114_CAM_SENSOR_CONTROL_X_READ_OUT_SUMMING		(3 << 4)108#define MT9M114_CAM_SENSOR_CONTROL_X_READ_OUT_MASK		(3 << 4)109#define MT9M114_CAM_SENSOR_CONTROL_Y_READ_OUT_NORMAL		(0 << 8)110#define MT9M114_CAM_SENSOR_CONTROL_Y_READ_OUT_SKIPPING		(1 << 8)111#define MT9M114_CAM_SENSOR_CONTROL_Y_READ_OUT_SUMMING		(3 << 8)112#define MT9M114_CAM_SENSOR_CONTROL_Y_READ_OUT_MASK		(3 << 8)113#define MT9M114_CAM_SENSOR_CONTROL_ANALOG_GAIN		CCI_REG16(0xc836)114#define MT9M114_CAM_SENSOR_CONTROL_COARSE_INTEGRATION_TIME	CCI_REG16(0xc83c)115#define MT9M114_CAM_SENSOR_CONTROL_FINE_INTEGRATION_TIME	CCI_REG16(0xc83e)116#define MT9M114_CAM_MODE_SELECT				CCI_REG8(0xc84c)117#define MT9M114_CAM_MODE_SELECT_NORMAL				(0 << 0)118#define MT9M114_CAM_MODE_SELECT_LENS_CALIBRATION		(1 << 0)119#define MT9M114_CAM_MODE_SELECT_TEST_PATTERN			(2 << 0)120#define MT9M114_CAM_MODE_TEST_PATTERN_SELECT		CCI_REG8(0xc84d)121#define MT9M114_CAM_MODE_TEST_PATTERN_SELECT_SOLID		(1 << 0)122#define MT9M114_CAM_MODE_TEST_PATTERN_SELECT_SOLID_BARS		(4 << 0)123#define MT9M114_CAM_MODE_TEST_PATTERN_SELECT_RANDOM		(5 << 0)124#define MT9M114_CAM_MODE_TEST_PATTERN_SELECT_FADING_BARS	(8 << 0)125#define MT9M114_CAM_MODE_TEST_PATTERN_SELECT_WALKING_1S_10B	(10 << 0)126#define MT9M114_CAM_MODE_TEST_PATTERN_SELECT_WALKING_1S_8B	(11 << 0)127#define MT9M114_CAM_MODE_TEST_PATTERN_RED		CCI_REG16(0xc84e)128#define MT9M114_CAM_MODE_TEST_PATTERN_GREEN		CCI_REG16(0xc850)129#define MT9M114_CAM_MODE_TEST_PATTERN_BLUE		CCI_REG16(0xc852)130#define MT9M114_CAM_CROP_WINDOW_XOFFSET			CCI_REG16(0xc854)131#define MT9M114_CAM_CROP_WINDOW_YOFFSET			CCI_REG16(0xc856)132#define MT9M114_CAM_CROP_WINDOW_WIDTH			CCI_REG16(0xc858)133#define MT9M114_CAM_CROP_WINDOW_HEIGHT			CCI_REG16(0xc85a)134#define MT9M114_CAM_CROP_CROPMODE			CCI_REG8(0xc85c)135#define MT9M114_CAM_CROP_MODE_AE_AUTO_CROP_EN			BIT(0)136#define MT9M114_CAM_CROP_MODE_AWB_AUTO_CROP_EN			BIT(1)137#define MT9M114_CAM_OUTPUT_WIDTH			CCI_REG16(0xc868)138#define MT9M114_CAM_OUTPUT_HEIGHT			CCI_REG16(0xc86a)139#define MT9M114_CAM_OUTPUT_FORMAT			CCI_REG16(0xc86c)140#define MT9M114_CAM_OUTPUT_FORMAT_SWAP_RED_BLUE			BIT(0)141#define MT9M114_CAM_OUTPUT_FORMAT_SWAP_BYTES			BIT(1)142#define MT9M114_CAM_OUTPUT_FORMAT_MONO_ENABLE			BIT(2)143#define MT9M114_CAM_OUTPUT_FORMAT_BT656_ENABLE			BIT(3)144#define MT9M114_CAM_OUTPUT_FORMAT_BT656_CROP_SCALE_DISABLE	BIT(4)145#define MT9M114_CAM_OUTPUT_FORMAT_FVLV_DISABLE			BIT(5)146#define MT9M114_CAM_OUTPUT_FORMAT_FORMAT_YUV			(0 << 8)147#define MT9M114_CAM_OUTPUT_FORMAT_FORMAT_RGB			(1 << 8)148#define MT9M114_CAM_OUTPUT_FORMAT_FORMAT_BAYER			(2 << 8)149#define MT9M114_CAM_OUTPUT_FORMAT_FORMAT_NONE			(3 << 8)150#define MT9M114_CAM_OUTPUT_FORMAT_FORMAT_MASK			(3 << 8)151#define MT9M114_CAM_OUTPUT_FORMAT_BAYER_FORMAT_RAWR10		(0 << 10)152#define MT9M114_CAM_OUTPUT_FORMAT_BAYER_FORMAT_PRELSC_8_2	(1 << 10)153#define MT9M114_CAM_OUTPUT_FORMAT_BAYER_FORMAT_POSTLSC_8_2	(2 << 10)154#define MT9M114_CAM_OUTPUT_FORMAT_BAYER_FORMAT_PROCESSED8	(3 << 10)155#define MT9M114_CAM_OUTPUT_FORMAT_BAYER_FORMAT_MASK		(3 << 10)156#define MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_565RGB		(0 << 12)157#define MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_555RGB		(1 << 12)158#define MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_444xRGB		(2 << 12)159#define MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_444RGBx		(3 << 12)160#define MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_MASK		(3 << 12)161#define MT9M114_CAM_OUTPUT_FORMAT_YUV			CCI_REG16(0xc86e)162#define MT9M114_CAM_OUTPUT_FORMAT_YUV_CLIP			BIT(5)163#define MT9M114_CAM_OUTPUT_FORMAT_YUV_AUV_OFFSET		BIT(4)164#define MT9M114_CAM_OUTPUT_FORMAT_YUV_SELECT_601		BIT(3)165#define MT9M114_CAM_OUTPUT_FORMAT_YUV_NORMALISE			BIT(2)166#define MT9M114_CAM_OUTPUT_FORMAT_YUV_SAMPLING_EVEN_UV		(0 << 0)167#define MT9M114_CAM_OUTPUT_FORMAT_YUV_SAMPLING_ODD_UV		(1 << 0)168#define MT9M114_CAM_OUTPUT_FORMAT_YUV_SAMPLING_EVENU_ODDV	(2 << 0)169#define MT9M114_CAM_OUTPUT_Y_OFFSET			CCI_REG8(0xc870)170#define MT9M114_CAM_AET_AEMODE				CCI_REG8(0xc878)171#define MT9M114_CAM_AET_EXEC_SET_INDOOR				BIT(0)172#define MT9M114_CAM_AET_DISCRETE_FRAMERATE			BIT(1)173#define MT9M114_CAM_AET_ADAPTATIVE_TARGET_LUMA			BIT(2)174#define MT9M114_CAM_AET_ADAPTATIVE_SKIP_FRAMES			BIT(3)175#define MT9M114_CAM_AET_SKIP_FRAMES			CCI_REG8(0xc879)176#define MT9M114_CAM_AET_TARGET_AVERAGE_LUMA		CCI_REG8(0xc87a)177#define MT9M114_CAM_AET_TARGET_AVERAGE_LUMA_DARK	CCI_REG8(0xc87b)178#define MT9M114_CAM_AET_BLACK_CLIPPING_TARGET		CCI_REG16(0xc87c)179#define MT9M114_CAM_AET_AE_MIN_VIRT_INT_TIME_PCLK	CCI_REG16(0xc87e)180#define MT9M114_CAM_AET_AE_MIN_VIRT_DGAIN		CCI_REG16(0xc880)181#define MT9M114_CAM_AET_AE_MAX_VIRT_DGAIN		CCI_REG16(0xc882)182#define MT9M114_CAM_AET_AE_MIN_VIRT_AGAIN		CCI_REG16(0xc884)183#define MT9M114_CAM_AET_AE_MAX_VIRT_AGAIN		CCI_REG16(0xc886)184#define MT9M114_CAM_AET_AE_VIRT_GAIN_TH_EG		CCI_REG16(0xc888)185#define MT9M114_CAM_AET_AE_EG_GATE_PERCENTAGE		CCI_REG8(0xc88a)186#define MT9M114_CAM_AET_FLICKER_FREQ_HZ			CCI_REG8(0xc88b)187#define MT9M114_CAM_AET_MAX_FRAME_RATE			CCI_REG16(0xc88c)188#define MT9M114_CAM_AET_MIN_FRAME_RATE			CCI_REG16(0xc88e)189#define MT9M114_CAM_AET_TARGET_GAIN			CCI_REG16(0xc890)190#define MT9M114_CAM_AWB_CCM_L(n)			CCI_REG16(0xc892 + (n) * 2)191#define MT9M114_CAM_AWB_CCM_M(n)			CCI_REG16(0xc8a4 + (n) * 2)192#define MT9M114_CAM_AWB_CCM_R(n)			CCI_REG16(0xc8b6 + (n) * 2)193#define MT9M114_CAM_AWB_CCM_L_RG_GAIN			CCI_REG16(0xc8c8)194#define MT9M114_CAM_AWB_CCM_L_BG_GAIN			CCI_REG16(0xc8ca)195#define MT9M114_CAM_AWB_CCM_M_RG_GAIN			CCI_REG16(0xc8cc)196#define MT9M114_CAM_AWB_CCM_M_BG_GAIN			CCI_REG16(0xc8ce)197#define MT9M114_CAM_AWB_CCM_R_RG_GAIN			CCI_REG16(0xc8d0)198#define MT9M114_CAM_AWB_CCM_R_BG_GAIN			CCI_REG16(0xc8d2)199#define MT9M114_CAM_AWB_CCM_L_CTEMP			CCI_REG16(0xc8d4)200#define MT9M114_CAM_AWB_CCM_M_CTEMP			CCI_REG16(0xc8d6)201#define MT9M114_CAM_AWB_CCM_R_CTEMP			CCI_REG16(0xc8d8)202#define MT9M114_CAM_AWB_AWB_XSCALE			CCI_REG8(0xc8f2)203#define MT9M114_CAM_AWB_AWB_YSCALE			CCI_REG8(0xc8f3)204#define MT9M114_CAM_AWB_AWB_WEIGHTS(n)			CCI_REG16(0xc8f4 + (n) * 2)205#define MT9M114_CAM_AWB_AWB_XSHIFT_PRE_ADJ		CCI_REG16(0xc904)206#define MT9M114_CAM_AWB_AWB_YSHIFT_PRE_ADJ		CCI_REG16(0xc906)207#define MT9M114_CAM_AWB_AWBMODE				CCI_REG8(0xc909)208#define MT9M114_CAM_AWB_MODE_AUTO				BIT(1)209#define MT9M114_CAM_AWB_MODE_EXCLUSIVE_AE			BIT(0)210#define MT9M114_CAM_AWB_K_R_L				CCI_REG8(0xc90c)211#define MT9M114_CAM_AWB_K_G_L				CCI_REG8(0xc90d)212#define MT9M114_CAM_AWB_K_B_L				CCI_REG8(0xc90e)213#define MT9M114_CAM_AWB_K_R_R				CCI_REG8(0xc90f)214#define MT9M114_CAM_AWB_K_G_R				CCI_REG8(0xc910)215#define MT9M114_CAM_AWB_K_B_R				CCI_REG8(0xc911)216#define MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XSTART		CCI_REG16(0xc914)217#define MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YSTART		CCI_REG16(0xc916)218#define MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XEND		CCI_REG16(0xc918)219#define MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YEND		CCI_REG16(0xc91a)220#define MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XSTART	CCI_REG16(0xc91c)221#define MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YSTART	CCI_REG16(0xc91e)222#define MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XEND		CCI_REG16(0xc920)223#define MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YEND		CCI_REG16(0xc922)224#define MT9M114_CAM_LL_LLMODE				CCI_REG16(0xc924)225#define MT9M114_CAM_LL_START_BRIGHTNESS			CCI_REG16(0xc926)226#define MT9M114_CAM_LL_STOP_BRIGHTNESS			CCI_REG16(0xc928)227#define MT9M114_CAM_LL_START_SATURATION			CCI_REG8(0xc92a)228#define MT9M114_CAM_LL_END_SATURATION			CCI_REG8(0xc92b)229#define MT9M114_CAM_LL_START_DESATURATION		CCI_REG8(0xc92c)230#define MT9M114_CAM_LL_END_DESATURATION			CCI_REG8(0xc92d)231#define MT9M114_CAM_LL_START_DEMOSAICING		CCI_REG8(0xc92e)232#define MT9M114_CAM_LL_START_AP_GAIN			CCI_REG8(0xc92f)233#define MT9M114_CAM_LL_START_AP_THRESH			CCI_REG8(0xc930)234#define MT9M114_CAM_LL_STOP_DEMOSAICING			CCI_REG8(0xc931)235#define MT9M114_CAM_LL_STOP_AP_GAIN			CCI_REG8(0xc932)236#define MT9M114_CAM_LL_STOP_AP_THRESH			CCI_REG8(0xc933)237#define MT9M114_CAM_LL_START_NR_RED			CCI_REG8(0xc934)238#define MT9M114_CAM_LL_START_NR_GREEN			CCI_REG8(0xc935)239#define MT9M114_CAM_LL_START_NR_BLUE			CCI_REG8(0xc936)240#define MT9M114_CAM_LL_START_NR_THRESH			CCI_REG8(0xc937)241#define MT9M114_CAM_LL_STOP_NR_RED			CCI_REG8(0xc938)242#define MT9M114_CAM_LL_STOP_NR_GREEN			CCI_REG8(0xc939)243#define MT9M114_CAM_LL_STOP_NR_BLUE			CCI_REG8(0xc93a)244#define MT9M114_CAM_LL_STOP_NR_THRESH			CCI_REG8(0xc93b)245#define MT9M114_CAM_LL_START_CONTRAST_BM		CCI_REG16(0xc93c)246#define MT9M114_CAM_LL_STOP_CONTRAST_BM			CCI_REG16(0xc93e)247#define MT9M114_CAM_LL_GAMMA				CCI_REG16(0xc940)248#define MT9M114_CAM_LL_START_CONTRAST_GRADIENT		CCI_REG8(0xc942)249#define MT9M114_CAM_LL_STOP_CONTRAST_GRADIENT		CCI_REG8(0xc943)250#define MT9M114_CAM_LL_START_CONTRAST_LUMA_PERCENTAGE	CCI_REG8(0xc944)251#define MT9M114_CAM_LL_STOP_CONTRAST_LUMA_PERCENTAGE	CCI_REG8(0xc945)252#define MT9M114_CAM_LL_START_GAIN_METRIC		CCI_REG16(0xc946)253#define MT9M114_CAM_LL_STOP_GAIN_METRIC			CCI_REG16(0xc948)254#define MT9M114_CAM_LL_START_FADE_TO_BLACK_LUMA		CCI_REG16(0xc94a)255#define MT9M114_CAM_LL_STOP_FADE_TO_BLACK_LUMA		CCI_REG16(0xc94c)256#define MT9M114_CAM_LL_CLUSTER_DC_TH_BM			CCI_REG16(0xc94e)257#define MT9M114_CAM_LL_CLUSTER_DC_GATE_PERCENTAGE	CCI_REG8(0xc950)258#define MT9M114_CAM_LL_SUMMING_SENSITIVITY_FACTOR	CCI_REG8(0xc951)259#define MT9M114_CAM_LL_START_TARGET_LUMA_BM		CCI_REG16(0xc952)260#define MT9M114_CAM_LL_STOP_TARGET_LUMA_BM		CCI_REG16(0xc954)261#define MT9M114_CAM_PGA_PGA_CONTROL			CCI_REG16(0xc95e)262#define MT9M114_CAM_SYSCTL_PLL_ENABLE			CCI_REG8(0xc97e)263#define MT9M114_CAM_SYSCTL_PLL_ENABLE_VALUE			BIT(0)264#define MT9M114_CAM_SYSCTL_PLL_DIVIDER_M_N		CCI_REG16(0xc980)265#define MT9M114_CAM_SYSCTL_PLL_DIVIDER_VALUE(m, n)		(((n) << 8) | (m))266#define MT9M114_CAM_SYSCTL_PLL_DIVIDER_P		CCI_REG16(0xc982)267#define MT9M114_CAM_SYSCTL_PLL_DIVIDER_P_VALUE(p)		((p) << 8)268#define MT9M114_CAM_PORT_OUTPUT_CONTROL			CCI_REG16(0xc984)269#define MT9M114_CAM_PORT_PORT_SELECT_PARALLEL			(0 << 0)270#define MT9M114_CAM_PORT_PORT_SELECT_MIPI			(1 << 0)271#define MT9M114_CAM_PORT_CLOCK_SLOWDOWN				BIT(3)272#define MT9M114_CAM_PORT_TRUNCATE_RAW_BAYER			BIT(4)273#define MT9M114_CAM_PORT_PIXCLK_GATE				BIT(5)274#define MT9M114_CAM_PORT_CONT_MIPI_CLK				BIT(6)275#define MT9M114_CAM_PORT_CHAN_NUM(vc)				((vc) << 8)276#define MT9M114_CAM_PORT_MIPI_TIMING_T_HS_ZERO		CCI_REG16(0xc988)277#define MT9M114_CAM_PORT_MIPI_TIMING_T_HS_ZERO_VALUE(n)		((n) << 8)278#define MT9M114_CAM_PORT_MIPI_TIMING_T_HS_EXIT_TRAIL	CCI_REG16(0xc98a)279#define MT9M114_CAM_PORT_MIPI_TIMING_T_HS_EXIT_VALUE(n)		((n) << 8)280#define MT9M114_CAM_PORT_MIPI_TIMING_T_HS_TRAIL_VALUE(n)	((n) << 0)281#define MT9M114_CAM_PORT_MIPI_TIMING_T_CLK_POST_PRE	CCI_REG16(0xc98c)282#define MT9M114_CAM_PORT_MIPI_TIMING_T_CLK_POST_VALUE(n)	((n) << 8)283#define MT9M114_CAM_PORT_MIPI_TIMING_T_CLK_PRE_VALUE(n)		((n) << 0)284#define MT9M114_CAM_PORT_MIPI_TIMING_T_CLK_TRAIL_ZERO	CCI_REG16(0xc98e)285#define MT9M114_CAM_PORT_MIPI_TIMING_T_CLK_TRAIL_VALUE(n)	((n) << 8)286#define MT9M114_CAM_PORT_MIPI_TIMING_T_CLK_ZERO_VALUE(n)	((n) << 0)287 288/* System Manager registers */289#define MT9M114_SYSMGR_NEXT_STATE			CCI_REG8(0xdc00)290#define MT9M114_SYSMGR_CURRENT_STATE			CCI_REG8(0xdc01)291#define MT9M114_SYSMGR_CMD_STATUS			CCI_REG8(0xdc02)292 293/* Patch Loader registers */294#define MT9M114_PATCHLDR_LOADER_ADDRESS			CCI_REG16(0xe000)295#define MT9M114_PATCHLDR_PATCH_ID			CCI_REG16(0xe002)296#define MT9M114_PATCHLDR_FIRMWARE_ID			CCI_REG32(0xe004)297#define MT9M114_PATCHLDR_APPLY_STATUS			CCI_REG8(0xe008)298#define MT9M114_PATCHLDR_NUM_PATCHES			CCI_REG8(0xe009)299#define MT9M114_PATCHLDR_PATCH_ID_0			CCI_REG16(0xe00a)300#define MT9M114_PATCHLDR_PATCH_ID_1			CCI_REG16(0xe00c)301#define MT9M114_PATCHLDR_PATCH_ID_2			CCI_REG16(0xe00e)302#define MT9M114_PATCHLDR_PATCH_ID_3			CCI_REG16(0xe010)303#define MT9M114_PATCHLDR_PATCH_ID_4			CCI_REG16(0xe012)304#define MT9M114_PATCHLDR_PATCH_ID_5			CCI_REG16(0xe014)305#define MT9M114_PATCHLDR_PATCH_ID_6			CCI_REG16(0xe016)306#define MT9M114_PATCHLDR_PATCH_ID_7			CCI_REG16(0xe018)307 308/* SYS_STATE values (for SYSMGR_NEXT_STATE and SYSMGR_CURRENT_STATE) */309#define MT9M114_SYS_STATE_ENTER_CONFIG_CHANGE		0x28310#define MT9M114_SYS_STATE_STREAMING			0x31311#define MT9M114_SYS_STATE_START_STREAMING		0x34312#define MT9M114_SYS_STATE_ENTER_SUSPEND			0x40313#define MT9M114_SYS_STATE_SUSPENDED			0x41314#define MT9M114_SYS_STATE_ENTER_STANDBY			0x50315#define MT9M114_SYS_STATE_STANDBY			0x52316#define MT9M114_SYS_STATE_LEAVE_STANDBY			0x54317 318/* Result status of last SET_STATE comamnd */319#define MT9M114_SET_STATE_RESULT_ENOERR			0x00320#define MT9M114_SET_STATE_RESULT_EINVAL			0x0c321#define MT9M114_SET_STATE_RESULT_ENOSPC			0x0d322 323/*324 * The minimum amount of horizontal and vertical blanking is undocumented. The325 * minimum values that have been seen in register lists are 303 and 38, use326 * them.327 *328 * Set the default to achieve 1280x960 at 30fps.329 */330#define MT9M114_MIN_HBLANK				303331#define MT9M114_MIN_VBLANK				38332#define MT9M114_DEF_HBLANK				323333#define MT9M114_DEF_VBLANK				39334 335#define MT9M114_DEF_FRAME_RATE				30336#define MT9M114_MAX_FRAME_RATE				120337 338#define MT9M114_PIXEL_ARRAY_WIDTH			1296U339#define MT9M114_PIXEL_ARRAY_HEIGHT			976U340 341/*342 * These values are not well documented and are semi-arbitrary. The pixel array343 * minimum output size is 8 pixels larger than the minimum scaler cropped input344 * width to account for the demosaicing.345 */346#define MT9M114_PIXEL_ARRAY_MIN_OUTPUT_WIDTH		(32U + 8U)347#define MT9M114_PIXEL_ARRAY_MIN_OUTPUT_HEIGHT		(32U + 8U)348#define MT9M114_SCALER_CROPPED_INPUT_WIDTH		32U349#define MT9M114_SCALER_CROPPED_INPUT_HEIGHT		32U350 351/* Indices into the mt9m114.ifp.tpg array. */352#define MT9M114_TPG_PATTERN				0353#define MT9M114_TPG_RED					1354#define MT9M114_TPG_GREEN				2355#define MT9M114_TPG_BLUE				3356 357/* -----------------------------------------------------------------------------358 * Data Structures359 */360 361enum mt9m114_format_flag {362	MT9M114_FMT_FLAG_PARALLEL = BIT(0),363	MT9M114_FMT_FLAG_CSI2 = BIT(1),364};365 366struct mt9m114_format_info {367	u32 code;368	u32 output_format;369	u32 flags;370};371 372struct mt9m114 {373	struct i2c_client *client;374	struct regmap *regmap;375 376	struct clk *clk;377	struct gpio_desc *reset;378	struct regulator_bulk_data supplies[3];379	struct v4l2_fwnode_endpoint bus_cfg;380 381	struct {382		unsigned int m;383		unsigned int n;384		unsigned int p;385	} pll;386 387	unsigned int pixrate;388	bool streaming;389 390	/* Pixel Array */391	struct {392		struct v4l2_subdev sd;393		struct media_pad pad;394 395		struct v4l2_ctrl_handler hdl;396		struct v4l2_ctrl *exposure;397		struct v4l2_ctrl *gain;398		struct v4l2_ctrl *hblank;399		struct v4l2_ctrl *vblank;400	} pa;401 402	/* Image Flow Processor */403	struct {404		struct v4l2_subdev sd;405		struct media_pad pads[2];406 407		struct v4l2_ctrl_handler hdl;408		unsigned int frame_rate;409 410		struct v4l2_ctrl *tpg[4];411	} ifp;412};413 414/* -----------------------------------------------------------------------------415 * Formats416 */417 418static const struct mt9m114_format_info mt9m114_format_infos[] = {419	{420		/*421		 * The first two entries are used as defaults, for parallel and422		 * CSI-2 buses respectively. Keep them in that order.423		 */424		.code = MEDIA_BUS_FMT_UYVY8_2X8,425		.flags = MT9M114_FMT_FLAG_PARALLEL,426		.output_format = MT9M114_CAM_OUTPUT_FORMAT_FORMAT_YUV,427	}, {428		.code = MEDIA_BUS_FMT_UYVY8_1X16,429		.flags = MT9M114_FMT_FLAG_CSI2,430		.output_format = MT9M114_CAM_OUTPUT_FORMAT_FORMAT_YUV,431	}, {432		.code = MEDIA_BUS_FMT_YUYV8_2X8,433		.flags = MT9M114_FMT_FLAG_PARALLEL,434		.output_format = MT9M114_CAM_OUTPUT_FORMAT_FORMAT_YUV435			       | MT9M114_CAM_OUTPUT_FORMAT_SWAP_BYTES,436	}, {437		.code = MEDIA_BUS_FMT_YUYV8_1X16,438		.flags = MT9M114_FMT_FLAG_CSI2,439		.output_format = MT9M114_CAM_OUTPUT_FORMAT_FORMAT_YUV440			       | MT9M114_CAM_OUTPUT_FORMAT_SWAP_BYTES,441	}, {442		.code = MEDIA_BUS_FMT_RGB565_2X8_LE,443		.flags = MT9M114_FMT_FLAG_PARALLEL,444		.output_format = MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_565RGB445			       | MT9M114_CAM_OUTPUT_FORMAT_FORMAT_RGB446			       | MT9M114_CAM_OUTPUT_FORMAT_SWAP_BYTES,447	}, {448		.code = MEDIA_BUS_FMT_RGB565_2X8_BE,449		.flags = MT9M114_FMT_FLAG_PARALLEL,450		.output_format = MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_565RGB451			       | MT9M114_CAM_OUTPUT_FORMAT_FORMAT_RGB,452	}, {453		.code = MEDIA_BUS_FMT_RGB565_1X16,454		.flags = MT9M114_FMT_FLAG_CSI2,455		.output_format = MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_565RGB456			       | MT9M114_CAM_OUTPUT_FORMAT_FORMAT_RGB,457	}, {458		.code = MEDIA_BUS_FMT_SGRBG8_1X8,459		.output_format = MT9M114_CAM_OUTPUT_FORMAT_BAYER_FORMAT_PROCESSED8460			       | MT9M114_CAM_OUTPUT_FORMAT_FORMAT_BAYER,461		.flags = MT9M114_FMT_FLAG_PARALLEL | MT9M114_FMT_FLAG_CSI2,462	}, {463		/* Keep the format compatible with the IFP sink pad last. */464		.code = MEDIA_BUS_FMT_SGRBG10_1X10,465		.output_format = MT9M114_CAM_OUTPUT_FORMAT_BAYER_FORMAT_RAWR10466			| MT9M114_CAM_OUTPUT_FORMAT_FORMAT_BAYER,467		.flags = MT9M114_FMT_FLAG_PARALLEL | MT9M114_FMT_FLAG_CSI2,468	}469};470 471static const struct mt9m114_format_info *472mt9m114_default_format_info(struct mt9m114 *sensor)473{474	if (sensor->bus_cfg.bus_type == V4L2_MBUS_CSI2_DPHY)475		return &mt9m114_format_infos[1];476	else477		return &mt9m114_format_infos[0];478}479 480static const struct mt9m114_format_info *481mt9m114_format_info(struct mt9m114 *sensor, unsigned int pad, u32 code)482{483	const unsigned int num_formats = ARRAY_SIZE(mt9m114_format_infos);484	unsigned int flag;485	unsigned int i;486 487	switch (pad) {488	case 0:489		return &mt9m114_format_infos[num_formats - 1];490 491	case 1:492		if (sensor->bus_cfg.bus_type == V4L2_MBUS_CSI2_DPHY)493			flag = MT9M114_FMT_FLAG_CSI2;494		else495			flag = MT9M114_FMT_FLAG_PARALLEL;496 497		for (i = 0; i < num_formats; ++i) {498			const struct mt9m114_format_info *info =499				&mt9m114_format_infos[i];500 501			if (info->code == code && info->flags & flag)502				return info;503		}504 505		return mt9m114_default_format_info(sensor);506 507	default:508		return NULL;509	}510}511 512/* -----------------------------------------------------------------------------513 * Initialization514 */515 516static const struct cci_reg_sequence mt9m114_init[] = {517	{ MT9M114_RESET_REGISTER, MT9M114_RESET_REGISTER_MASK_BAD |518				  MT9M114_RESET_REGISTER_LOCK_REG |519				  0x0010 },520 521	/* Sensor optimization */522	{ CCI_REG16(0x316a), 0x8270 },523	{ CCI_REG16(0x316c), 0x8270 },524	{ CCI_REG16(0x3ed0), 0x2305 },525	{ CCI_REG16(0x3ed2), 0x77cf },526	{ CCI_REG16(0x316e), 0x8202 },527	{ CCI_REG16(0x3180), 0x87ff },528	{ CCI_REG16(0x30d4), 0x6080 },529	{ CCI_REG16(0xa802), 0x0008 },530 531	{ CCI_REG16(0x3e14), 0xff39 },532 533	/* APGA */534	{ MT9M114_CAM_PGA_PGA_CONTROL,			0x0000 },535 536	/* Automatic White balance */537	{ MT9M114_CAM_AWB_CCM_L(0),			0x0267 },538	{ MT9M114_CAM_AWB_CCM_L(1),			0xff1a },539	{ MT9M114_CAM_AWB_CCM_L(2),			0xffb3 },540	{ MT9M114_CAM_AWB_CCM_L(3),			0xff80 },541	{ MT9M114_CAM_AWB_CCM_L(4),			0x0166 },542	{ MT9M114_CAM_AWB_CCM_L(5),			0x0003 },543	{ MT9M114_CAM_AWB_CCM_L(6),			0xff9a },544	{ MT9M114_CAM_AWB_CCM_L(7),			0xfeb4 },545	{ MT9M114_CAM_AWB_CCM_L(8),			0x024d },546	{ MT9M114_CAM_AWB_CCM_M(0),			0x01bf },547	{ MT9M114_CAM_AWB_CCM_M(1),			0xff01 },548	{ MT9M114_CAM_AWB_CCM_M(2),			0xfff3 },549	{ MT9M114_CAM_AWB_CCM_M(3),			0xff75 },550	{ MT9M114_CAM_AWB_CCM_M(4),			0x0198 },551	{ MT9M114_CAM_AWB_CCM_M(5),			0xfffd },552	{ MT9M114_CAM_AWB_CCM_M(6),			0xff9a },553	{ MT9M114_CAM_AWB_CCM_M(7),			0xfee7 },554	{ MT9M114_CAM_AWB_CCM_M(8),			0x02a8 },555	{ MT9M114_CAM_AWB_CCM_R(0),			0x01d9 },556	{ MT9M114_CAM_AWB_CCM_R(1),			0xff26 },557	{ MT9M114_CAM_AWB_CCM_R(2),			0xfff3 },558	{ MT9M114_CAM_AWB_CCM_R(3),			0xffb3 },559	{ MT9M114_CAM_AWB_CCM_R(4),			0x0132 },560	{ MT9M114_CAM_AWB_CCM_R(5),			0xffe8 },561	{ MT9M114_CAM_AWB_CCM_R(6),			0xffda },562	{ MT9M114_CAM_AWB_CCM_R(7),			0xfecd },563	{ MT9M114_CAM_AWB_CCM_R(8),			0x02c2 },564	{ MT9M114_CAM_AWB_CCM_L_RG_GAIN,		0x0075 },565	{ MT9M114_CAM_AWB_CCM_L_BG_GAIN,		0x011c },566	{ MT9M114_CAM_AWB_CCM_M_RG_GAIN,		0x009a },567	{ MT9M114_CAM_AWB_CCM_M_BG_GAIN,		0x0105 },568	{ MT9M114_CAM_AWB_CCM_R_RG_GAIN,		0x00a4 },569	{ MT9M114_CAM_AWB_CCM_R_BG_GAIN,		0x00ac },570	{ MT9M114_CAM_AWB_CCM_L_CTEMP,			0x0a8c },571	{ MT9M114_CAM_AWB_CCM_M_CTEMP,			0x0f0a },572	{ MT9M114_CAM_AWB_CCM_R_CTEMP,			0x1964 },573	{ MT9M114_CAM_AWB_AWB_XSHIFT_PRE_ADJ,		51 },574	{ MT9M114_CAM_AWB_AWB_YSHIFT_PRE_ADJ,		60 },575	{ MT9M114_CAM_AWB_AWB_XSCALE,			3 },576	{ MT9M114_CAM_AWB_AWB_YSCALE,			2 },577	{ MT9M114_CAM_AWB_AWB_WEIGHTS(0),		0x0000 },578	{ MT9M114_CAM_AWB_AWB_WEIGHTS(1),		0x0000 },579	{ MT9M114_CAM_AWB_AWB_WEIGHTS(2),		0x0000 },580	{ MT9M114_CAM_AWB_AWB_WEIGHTS(3),		0xe724 },581	{ MT9M114_CAM_AWB_AWB_WEIGHTS(4),		0x1583 },582	{ MT9M114_CAM_AWB_AWB_WEIGHTS(5),		0x2045 },583	{ MT9M114_CAM_AWB_AWB_WEIGHTS(6),		0x03ff },584	{ MT9M114_CAM_AWB_AWB_WEIGHTS(7),		0x007c },585	{ MT9M114_CAM_AWB_K_R_L,			0x80 },586	{ MT9M114_CAM_AWB_K_G_L,			0x80 },587	{ MT9M114_CAM_AWB_K_B_L,			0x80 },588	{ MT9M114_CAM_AWB_K_R_R,			0x88 },589	{ MT9M114_CAM_AWB_K_G_R,			0x80 },590	{ MT9M114_CAM_AWB_K_B_R,			0x80 },591 592	/* Low-Light Image Enhancements */593	{ MT9M114_CAM_LL_START_BRIGHTNESS,		0x0020 },594	{ MT9M114_CAM_LL_STOP_BRIGHTNESS,		0x009a },595	{ MT9M114_CAM_LL_START_GAIN_METRIC,		0x0070 },596	{ MT9M114_CAM_LL_STOP_GAIN_METRIC,		0x00f3 },597	{ MT9M114_CAM_LL_START_CONTRAST_LUMA_PERCENTAGE, 0x20 },598	{ MT9M114_CAM_LL_STOP_CONTRAST_LUMA_PERCENTAGE,	0x9a },599	{ MT9M114_CAM_LL_START_SATURATION,		0x80 },600	{ MT9M114_CAM_LL_END_SATURATION,		0x4b },601	{ MT9M114_CAM_LL_START_DESATURATION,		0x00 },602	{ MT9M114_CAM_LL_END_DESATURATION,		0xff },603	{ MT9M114_CAM_LL_START_DEMOSAICING,		0x3c },604	{ MT9M114_CAM_LL_START_AP_GAIN,			0x02 },605	{ MT9M114_CAM_LL_START_AP_THRESH,		0x06 },606	{ MT9M114_CAM_LL_STOP_DEMOSAICING,		0x64 },607	{ MT9M114_CAM_LL_STOP_AP_GAIN,			0x01 },608	{ MT9M114_CAM_LL_STOP_AP_THRESH,		0x0c },609	{ MT9M114_CAM_LL_START_NR_RED,			0x3c },610	{ MT9M114_CAM_LL_START_NR_GREEN,		0x3c },611	{ MT9M114_CAM_LL_START_NR_BLUE,			0x3c },612	{ MT9M114_CAM_LL_START_NR_THRESH,		0x0f },613	{ MT9M114_CAM_LL_STOP_NR_RED,			0x64 },614	{ MT9M114_CAM_LL_STOP_NR_GREEN,			0x64 },615	{ MT9M114_CAM_LL_STOP_NR_BLUE,			0x64 },616	{ MT9M114_CAM_LL_STOP_NR_THRESH,		0x32 },617	{ MT9M114_CAM_LL_START_CONTRAST_BM,		0x0020 },618	{ MT9M114_CAM_LL_STOP_CONTRAST_BM,		0x009a },619	{ MT9M114_CAM_LL_GAMMA,				0x00dc },620	{ MT9M114_CAM_LL_START_CONTRAST_GRADIENT,	0x38 },621	{ MT9M114_CAM_LL_STOP_CONTRAST_GRADIENT,	0x30 },622	{ MT9M114_CAM_LL_START_CONTRAST_LUMA_PERCENTAGE, 0x50 },623	{ MT9M114_CAM_LL_STOP_CONTRAST_LUMA_PERCENTAGE,	0x19 },624	{ MT9M114_CAM_LL_START_FADE_TO_BLACK_LUMA,	0x0230 },625	{ MT9M114_CAM_LL_STOP_FADE_TO_BLACK_LUMA,	0x0010 },626	{ MT9M114_CAM_LL_CLUSTER_DC_TH_BM,		0x01cd },627	{ MT9M114_CAM_LL_CLUSTER_DC_GATE_PERCENTAGE,	0x05 },628	{ MT9M114_CAM_LL_SUMMING_SENSITIVITY_FACTOR,	0x40 },629 630	/* Auto-Exposure */631	{ MT9M114_CAM_AET_TARGET_AVERAGE_LUMA_DARK,	0x1b },632	{ MT9M114_CAM_AET_AEMODE,			0x00 },633	{ MT9M114_CAM_AET_TARGET_GAIN,			0x0080 },634	{ MT9M114_CAM_AET_AE_MAX_VIRT_AGAIN,		0x0100 },635	{ MT9M114_CAM_AET_BLACK_CLIPPING_TARGET,	0x005a },636 637	{ MT9M114_CCM_DELTA_GAIN,			0x05 },638	{ MT9M114_AE_TRACK_AE_TRACKING_DAMPENING_SPEED,	0x20 },639 640	/* Pixel array timings and integration time */641	{ MT9M114_CAM_SENSOR_CFG_ROW_SPEED,		1 },642	{ MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MIN,	219 },643	{ MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MAX,	1459 },644	{ MT9M114_CAM_SENSOR_CFG_FINE_CORRECTION,	96 },645	{ MT9M114_CAM_SENSOR_CFG_REG_0_DATA,		32 },646 647	/* Miscellaneous settings */648	{ MT9M114_PAD_SLEW,				0x0777 },649};650 651/* -----------------------------------------------------------------------------652 * Hardware Configuration653 */654 655/* Wait for a command to complete. */656static int mt9m114_poll_command(struct mt9m114 *sensor, u32 command)657{658	unsigned int i;659	u64 value;660	int ret;661 662	for (i = 0; i < 100; ++i) {663		ret = cci_read(sensor->regmap, MT9M114_COMMAND_REGISTER, &value,664			       NULL);665		if (ret < 0)666			return ret;667 668		if (!(value & command))669			break;670 671		usleep_range(5000, 6000);672	}673 674	if (value & command) {675		dev_err(&sensor->client->dev, "Command %u completion timeout\n",676			command);677		return -ETIMEDOUT;678	}679 680	if (!(value & MT9M114_COMMAND_REGISTER_OK)) {681		dev_err(&sensor->client->dev, "Command %u failed\n", command);682		return -EIO;683	}684 685	return 0;686}687 688/* Wait for a state to be entered. */689static int mt9m114_poll_state(struct mt9m114 *sensor, u32 state)690{691	unsigned int i;692	u64 value;693	int ret;694 695	for (i = 0; i < 100; ++i) {696		ret = cci_read(sensor->regmap, MT9M114_SYSMGR_CURRENT_STATE,697			       &value, NULL);698		if (ret < 0)699			return ret;700 701		if (value == state)702			return 0;703 704		usleep_range(1000, 1500);705	}706 707	dev_err(&sensor->client->dev, "Timeout waiting for state 0x%02x\n",708		state);709	return -ETIMEDOUT;710}711 712static int mt9m114_set_state(struct mt9m114 *sensor, u8 next_state)713{714	int ret = 0;715 716	/* Set the next desired state and start the state transition. */717	cci_write(sensor->regmap, MT9M114_SYSMGR_NEXT_STATE, next_state, &ret);718	cci_write(sensor->regmap, MT9M114_COMMAND_REGISTER,719		  MT9M114_COMMAND_REGISTER_OK |720		  MT9M114_COMMAND_REGISTER_SET_STATE, &ret);721	if (ret < 0)722		return ret;723 724	/* Wait for the state transition to complete. */725	ret = mt9m114_poll_command(sensor, MT9M114_COMMAND_REGISTER_SET_STATE);726	if (ret < 0)727		return ret;728 729	return 0;730}731 732static int mt9m114_initialize(struct mt9m114 *sensor)733{734	u32 value;735	int ret;736 737	ret = cci_multi_reg_write(sensor->regmap, mt9m114_init,738				  ARRAY_SIZE(mt9m114_init), NULL);739	if (ret < 0) {740		dev_err(&sensor->client->dev,741			"Failed to initialize the sensor\n");742		return ret;743	}744 745	/* Configure the PLL. */746	cci_write(sensor->regmap, MT9M114_CAM_SYSCTL_PLL_ENABLE,747		  MT9M114_CAM_SYSCTL_PLL_ENABLE_VALUE, &ret);748	cci_write(sensor->regmap, MT9M114_CAM_SYSCTL_PLL_DIVIDER_M_N,749		  MT9M114_CAM_SYSCTL_PLL_DIVIDER_VALUE(sensor->pll.m,750						       sensor->pll.n),751		  &ret);752	cci_write(sensor->regmap, MT9M114_CAM_SYSCTL_PLL_DIVIDER_P,753		  MT9M114_CAM_SYSCTL_PLL_DIVIDER_P_VALUE(sensor->pll.p), &ret);754	cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CFG_PIXCLK,755		  sensor->pixrate, &ret);756 757	/* Configure the output mode. */758	if (sensor->bus_cfg.bus_type == V4L2_MBUS_CSI2_DPHY) {759		value = MT9M114_CAM_PORT_PORT_SELECT_MIPI760		      | MT9M114_CAM_PORT_CHAN_NUM(0)761		      | 0x8000;762		if (!(sensor->bus_cfg.bus.mipi_csi2.flags &763		      V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK))764			value |= MT9M114_CAM_PORT_CONT_MIPI_CLK;765	} else {766		value = MT9M114_CAM_PORT_PORT_SELECT_PARALLEL767		      | 0x8000;768	}769	cci_write(sensor->regmap, MT9M114_CAM_PORT_OUTPUT_CONTROL, value, &ret);770	if (ret < 0)771		return ret;772 773	ret = mt9m114_set_state(sensor, MT9M114_SYS_STATE_ENTER_CONFIG_CHANGE);774	if (ret < 0)775		return ret;776 777	ret = mt9m114_set_state(sensor, MT9M114_SYS_STATE_ENTER_SUSPEND);778	if (ret < 0)779		return ret;780 781	return 0;782}783 784static int mt9m114_configure(struct mt9m114 *sensor,785			     struct v4l2_subdev_state *pa_state,786			     struct v4l2_subdev_state *ifp_state)787{788	const struct v4l2_mbus_framefmt *pa_format;789	const struct v4l2_rect *pa_crop;790	const struct mt9m114_format_info *ifp_info;791	const struct v4l2_mbus_framefmt *ifp_format;792	const struct v4l2_rect *ifp_crop;793	const struct v4l2_rect *ifp_compose;794	unsigned int hratio, vratio;795	u64 output_format;796	u64 read_mode;797	int ret = 0;798 799	pa_format = v4l2_subdev_state_get_format(pa_state, 0);800	pa_crop = v4l2_subdev_state_get_crop(pa_state, 0);801 802	ifp_format = v4l2_subdev_state_get_format(ifp_state, 1);803	ifp_info = mt9m114_format_info(sensor, 1, ifp_format->code);804	ifp_crop = v4l2_subdev_state_get_crop(ifp_state, 0);805	ifp_compose = v4l2_subdev_state_get_compose(ifp_state, 0);806 807	ret = cci_read(sensor->regmap, MT9M114_CAM_SENSOR_CONTROL_READ_MODE,808		       &read_mode, NULL);809	if (ret < 0)810		return ret;811 812	ret = cci_read(sensor->regmap, MT9M114_CAM_OUTPUT_FORMAT,813		       &output_format, NULL);814	if (ret < 0)815		return ret;816 817	hratio = pa_crop->width / pa_format->width;818	vratio = pa_crop->height / pa_format->height;819 820	/*821	 * Pixel array crop and binning. The CAM_SENSOR_CFG_CPIPE_LAST_ROW822	 * register isn't clearly documented, but is always set to the number823	 * of active rows minus 4 divided by the vertical binning factor in all824	 * example sensor modes.825	 */826	cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CFG_X_ADDR_START,827		  pa_crop->left, &ret);828	cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CFG_Y_ADDR_START,829		  pa_crop->top, &ret);830	cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CFG_X_ADDR_END,831		  pa_crop->width + pa_crop->left - 1, &ret);832	cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CFG_Y_ADDR_END,833		  pa_crop->height + pa_crop->top - 1, &ret);834	cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CFG_CPIPE_LAST_ROW,835		  (pa_crop->height - 4) / vratio - 1, &ret);836 837	read_mode &= ~(MT9M114_CAM_SENSOR_CONTROL_X_READ_OUT_MASK |838		       MT9M114_CAM_SENSOR_CONTROL_Y_READ_OUT_MASK);839 840	if (hratio > 1)841		read_mode |= MT9M114_CAM_SENSOR_CONTROL_X_READ_OUT_SUMMING;842	if (vratio > 1)843		read_mode |= MT9M114_CAM_SENSOR_CONTROL_Y_READ_OUT_SUMMING;844 845	cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CONTROL_READ_MODE,846		  read_mode, &ret);847 848	/*849	 * Color pipeline (IFP) cropping and scaling. Subtract 4 from the left850	 * and top coordinates to compensate for the lines and columns removed851	 * by demosaicing that are taken into account in the crop rectangle but852	 * not in the hardware.853	 */854	cci_write(sensor->regmap, MT9M114_CAM_CROP_WINDOW_XOFFSET,855		  ifp_crop->left - 4, &ret);856	cci_write(sensor->regmap, MT9M114_CAM_CROP_WINDOW_YOFFSET,857		  ifp_crop->top - 4, &ret);858	cci_write(sensor->regmap, MT9M114_CAM_CROP_WINDOW_WIDTH,859		  ifp_crop->width, &ret);860	cci_write(sensor->regmap, MT9M114_CAM_CROP_WINDOW_HEIGHT,861		  ifp_crop->height, &ret);862 863	cci_write(sensor->regmap, MT9M114_CAM_OUTPUT_WIDTH,864		  ifp_compose->width, &ret);865	cci_write(sensor->regmap, MT9M114_CAM_OUTPUT_HEIGHT,866		  ifp_compose->height, &ret);867 868	/* AWB and AE windows, use the full frame. */869	cci_write(sensor->regmap, MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XSTART,870		  0, &ret);871	cci_write(sensor->regmap, MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YSTART,872		  0, &ret);873	cci_write(sensor->regmap, MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XEND,874		  ifp_compose->width - 1, &ret);875	cci_write(sensor->regmap, MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YEND,876		  ifp_compose->height - 1, &ret);877 878	cci_write(sensor->regmap, MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XSTART,879		  0, &ret);880	cci_write(sensor->regmap, MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YSTART,881		  0, &ret);882	cci_write(sensor->regmap, MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XEND,883		  ifp_compose->width / 5 - 1, &ret);884	cci_write(sensor->regmap, MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YEND,885		  ifp_compose->height / 5 - 1, &ret);886 887	cci_write(sensor->regmap, MT9M114_CAM_CROP_CROPMODE,888		  MT9M114_CAM_CROP_MODE_AWB_AUTO_CROP_EN |889		  MT9M114_CAM_CROP_MODE_AE_AUTO_CROP_EN, &ret);890 891	/* Set the media bus code. */892	output_format &= ~(MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_MASK |893			   MT9M114_CAM_OUTPUT_FORMAT_BAYER_FORMAT_MASK |894			   MT9M114_CAM_OUTPUT_FORMAT_FORMAT_MASK |895			   MT9M114_CAM_OUTPUT_FORMAT_SWAP_BYTES |896			   MT9M114_CAM_OUTPUT_FORMAT_SWAP_RED_BLUE);897	output_format |= ifp_info->output_format;898 899	cci_write(sensor->regmap, MT9M114_CAM_OUTPUT_FORMAT,900		  output_format, &ret);901 902	return ret;903}904 905static int mt9m114_set_frame_rate(struct mt9m114 *sensor)906{907	u16 frame_rate = sensor->ifp.frame_rate << 8;908	int ret = 0;909 910	cci_write(sensor->regmap, MT9M114_CAM_AET_MIN_FRAME_RATE,911		  frame_rate, &ret);912	cci_write(sensor->regmap, MT9M114_CAM_AET_MAX_FRAME_RATE,913		  frame_rate, &ret);914 915	return ret;916}917 918static int mt9m114_start_streaming(struct mt9m114 *sensor,919				   struct v4l2_subdev_state *pa_state,920				   struct v4l2_subdev_state *ifp_state)921{922	int ret;923 924	ret = pm_runtime_resume_and_get(&sensor->client->dev);925	if (ret)926		return ret;927 928	ret = mt9m114_configure(sensor, pa_state, ifp_state);929	if (ret)930		goto error;931 932	ret = mt9m114_set_frame_rate(sensor);933	if (ret)934		goto error;935 936	ret = __v4l2_ctrl_handler_setup(&sensor->pa.hdl);937	if (ret)938		goto error;939 940	ret = __v4l2_ctrl_handler_setup(&sensor->ifp.hdl);941	if (ret)942		goto error;943 944	/*945	 * The Change-Config state is transient and moves to the streaming946	 * state automatically.947	 */948	ret = mt9m114_set_state(sensor, MT9M114_SYS_STATE_ENTER_CONFIG_CHANGE);949	if (ret)950		goto error;951 952	sensor->streaming = true;953 954	return 0;955 956error:957	pm_runtime_mark_last_busy(&sensor->client->dev);958	pm_runtime_put_autosuspend(&sensor->client->dev);959 960	return ret;961}962 963static int mt9m114_stop_streaming(struct mt9m114 *sensor)964{965	int ret;966 967	sensor->streaming = false;968 969	ret = mt9m114_set_state(sensor, MT9M114_SYS_STATE_ENTER_SUSPEND);970 971	pm_runtime_mark_last_busy(&sensor->client->dev);972	pm_runtime_put_autosuspend(&sensor->client->dev);973 974	return ret;975}976 977/* -----------------------------------------------------------------------------978 * Common Subdev Operations979 */980 981static const struct media_entity_operations mt9m114_entity_ops = {982	.link_validate = v4l2_subdev_link_validate,983};984 985/* -----------------------------------------------------------------------------986 * Pixel Array Control Operations987 */988 989static inline struct mt9m114 *pa_ctrl_to_mt9m114(struct v4l2_ctrl *ctrl)990{991	return container_of(ctrl->handler, struct mt9m114, pa.hdl);992}993 994static int mt9m114_pa_g_ctrl(struct v4l2_ctrl *ctrl)995{996	struct mt9m114 *sensor = pa_ctrl_to_mt9m114(ctrl);997	u64 value;998	int ret;999 1000	if (!pm_runtime_get_if_in_use(&sensor->client->dev))1001		return 0;1002 1003	switch (ctrl->id) {1004	case V4L2_CID_EXPOSURE:1005		ret = cci_read(sensor->regmap,1006			       MT9M114_CAM_SENSOR_CONTROL_COARSE_INTEGRATION_TIME,1007			       &value, NULL);1008		if (ret)1009			break;1010 1011		ctrl->val = value;1012		break;1013 1014	case V4L2_CID_ANALOGUE_GAIN:1015		ret = cci_read(sensor->regmap,1016			       MT9M114_CAM_SENSOR_CONTROL_ANALOG_GAIN,1017			       &value, NULL);1018		if (ret)1019			break;1020 1021		ctrl->val = value;1022		break;1023 1024	default:1025		ret = -EINVAL;1026		break;1027	}1028 1029	pm_runtime_mark_last_busy(&sensor->client->dev);1030	pm_runtime_put_autosuspend(&sensor->client->dev);1031 1032	return ret;1033}1034 1035static int mt9m114_pa_s_ctrl(struct v4l2_ctrl *ctrl)1036{1037	struct mt9m114 *sensor = pa_ctrl_to_mt9m114(ctrl);1038	const struct v4l2_mbus_framefmt *format;1039	struct v4l2_subdev_state *state;1040	int ret = 0;1041	u64 mask;1042 1043	/* V4L2 controls values are applied only when power is up. */1044	if (!pm_runtime_get_if_in_use(&sensor->client->dev))1045		return 0;1046 1047	state = v4l2_subdev_get_locked_active_state(&sensor->pa.sd);1048	format = v4l2_subdev_state_get_format(state, 0);1049 1050	switch (ctrl->id) {1051	case V4L2_CID_HBLANK:1052		cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CFG_LINE_LENGTH_PCK,1053			  ctrl->val + format->width, &ret);1054		break;1055 1056	case V4L2_CID_VBLANK:1057		cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CFG_FRAME_LENGTH_LINES,1058			  ctrl->val + format->height, &ret);1059		break;1060 1061	case V4L2_CID_EXPOSURE:1062		cci_write(sensor->regmap,1063			  MT9M114_CAM_SENSOR_CONTROL_COARSE_INTEGRATION_TIME,1064			  ctrl->val, &ret);1065		break;1066 1067	case V4L2_CID_ANALOGUE_GAIN:1068		/*1069		 * The CAM_SENSOR_CONTROL_ANALOG_GAIN contains linear analog1070		 * gain values that are mapped to the GLOBAL_GAIN register1071		 * values by the sensor firmware.1072		 */1073		cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CONTROL_ANALOG_GAIN,1074			  ctrl->val, &ret);1075		break;1076 1077	case V4L2_CID_HFLIP:1078		mask = MT9M114_CAM_SENSOR_CONTROL_HORZ_MIRROR_EN;1079		ret = cci_update_bits(sensor->regmap,1080				      MT9M114_CAM_SENSOR_CONTROL_READ_MODE,1081				      mask, ctrl->val ? mask : 0, NULL);1082		break;1083 1084	case V4L2_CID_VFLIP:1085		mask = MT9M114_CAM_SENSOR_CONTROL_VERT_FLIP_EN;1086		ret = cci_update_bits(sensor->regmap,1087				      MT9M114_CAM_SENSOR_CONTROL_READ_MODE,1088				      mask, ctrl->val ? mask : 0, NULL);1089		break;1090 1091	default:1092		ret = -EINVAL;1093		break;1094	}1095 1096	pm_runtime_mark_last_busy(&sensor->client->dev);1097	pm_runtime_put_autosuspend(&sensor->client->dev);1098 1099	return ret;1100}1101 1102static const struct v4l2_ctrl_ops mt9m114_pa_ctrl_ops = {1103	.g_volatile_ctrl = mt9m114_pa_g_ctrl,1104	.s_ctrl = mt9m114_pa_s_ctrl,1105};1106 1107static void mt9m114_pa_ctrl_update_exposure(struct mt9m114 *sensor, bool manual)1108{1109	/*1110	 * Update the volatile flag on the manual exposure and gain controls.1111	 * If the controls have switched to manual, read their current value1112	 * from the hardware to ensure that control read and write operations1113	 * will behave correctly1114	 */1115	if (manual) {1116		mt9m114_pa_g_ctrl(sensor->pa.exposure);1117		sensor->pa.exposure->cur.val = sensor->pa.exposure->val;1118		sensor->pa.exposure->flags &= ~V4L2_CTRL_FLAG_VOLATILE;1119 1120		mt9m114_pa_g_ctrl(sensor->pa.gain);1121		sensor->pa.gain->cur.val = sensor->pa.gain->val;1122		sensor->pa.gain->flags &= ~V4L2_CTRL_FLAG_VOLATILE;1123	} else {1124		sensor->pa.exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;1125		sensor->pa.gain->flags |= V4L2_CTRL_FLAG_VOLATILE;1126	}1127}1128 1129static void mt9m114_pa_ctrl_update_blanking(struct mt9m114 *sensor,1130					    const struct v4l2_mbus_framefmt *format)1131{1132	unsigned int max_blank;1133 1134	/* Update the blanking controls ranges based on the output size. */1135	max_blank = MT9M114_CAM_SENSOR_CFG_LINE_LENGTH_PCK_MAX1136		  - format->width;1137	__v4l2_ctrl_modify_range(sensor->pa.hblank, MT9M114_MIN_HBLANK,1138				 max_blank, 1, MT9M114_DEF_HBLANK);1139 1140	max_blank = MT9M114_CAM_SENSOR_CFG_FRAME_LENGTH_LINES_MAX1141		  - format->height;1142	__v4l2_ctrl_modify_range(sensor->pa.vblank, MT9M114_MIN_VBLANK,1143				 max_blank, 1, MT9M114_DEF_VBLANK);1144}1145 1146/* -----------------------------------------------------------------------------1147 * Pixel Array Subdev Operations1148 */1149 1150static inline struct mt9m114 *pa_to_mt9m114(struct v4l2_subdev *sd)1151{1152	return container_of(sd, struct mt9m114, pa.sd);1153}1154 1155static int mt9m114_pa_init_state(struct v4l2_subdev *sd,1156				 struct v4l2_subdev_state *state)1157{1158	struct v4l2_mbus_framefmt *format;1159	struct v4l2_rect *crop;1160 1161	crop = v4l2_subdev_state_get_crop(state, 0);1162 1163	crop->left = 0;1164	crop->top = 0;1165	crop->width = MT9M114_PIXEL_ARRAY_WIDTH;1166	crop->height = MT9M114_PIXEL_ARRAY_HEIGHT;1167 1168	format = v4l2_subdev_state_get_format(state, 0);1169 1170	format->width = MT9M114_PIXEL_ARRAY_WIDTH;1171	format->height = MT9M114_PIXEL_ARRAY_HEIGHT;1172	format->code = MEDIA_BUS_FMT_SGRBG10_1X10;1173	format->field = V4L2_FIELD_NONE;1174	format->colorspace = V4L2_COLORSPACE_RAW;1175	format->ycbcr_enc = V4L2_YCBCR_ENC_601;1176	format->quantization = V4L2_QUANTIZATION_FULL_RANGE;1177	format->xfer_func = V4L2_XFER_FUNC_NONE;1178 1179	return 0;1180}1181 1182static int mt9m114_pa_enum_mbus_code(struct v4l2_subdev *sd,1183				     struct v4l2_subdev_state *state,1184				     struct v4l2_subdev_mbus_code_enum *code)1185{1186	if (code->index > 0)1187		return -EINVAL;1188 1189	code->code = MEDIA_BUS_FMT_SGRBG10_1X10;1190 1191	return 0;1192}1193 1194static int mt9m114_pa_enum_framesizes(struct v4l2_subdev *sd,1195				      struct v4l2_subdev_state *state,1196				      struct v4l2_subdev_frame_size_enum *fse)1197{1198	if (fse->index > 1)1199		return -EINVAL;1200 1201	if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)1202		return -EINVAL;1203 1204	/* Report binning capability through frame size enumeration. */1205	fse->min_width = MT9M114_PIXEL_ARRAY_WIDTH / (fse->index + 1);1206	fse->max_width = MT9M114_PIXEL_ARRAY_WIDTH / (fse->index + 1);1207	fse->min_height = MT9M114_PIXEL_ARRAY_HEIGHT / (fse->index + 1);1208	fse->max_height = MT9M114_PIXEL_ARRAY_HEIGHT / (fse->index + 1);1209 1210	return 0;1211}1212 1213static int mt9m114_pa_set_fmt(struct v4l2_subdev *sd,1214			      struct v4l2_subdev_state *state,1215			      struct v4l2_subdev_format *fmt)1216{1217	struct mt9m114 *sensor = pa_to_mt9m114(sd);1218	struct v4l2_mbus_framefmt *format;1219	struct v4l2_rect *crop;1220	unsigned int hscale;1221	unsigned int vscale;1222 1223	crop = v4l2_subdev_state_get_crop(state, fmt->pad);1224	format = v4l2_subdev_state_get_format(state, fmt->pad);1225 1226	/* The sensor can bin horizontally and vertically. */1227	hscale = DIV_ROUND_CLOSEST(crop->width, fmt->format.width ? : 1);1228	vscale = DIV_ROUND_CLOSEST(crop->height, fmt->format.height ? : 1);1229	format->width = crop->width / clamp(hscale, 1U, 2U);1230	format->height = crop->height / clamp(vscale, 1U, 2U);1231 1232	fmt->format = *format;1233 1234	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)1235		mt9m114_pa_ctrl_update_blanking(sensor, format);1236 1237	return 0;1238}1239 1240static int mt9m114_pa_get_selection(struct v4l2_subdev *sd,1241				    struct v4l2_subdev_state *state,1242				    struct v4l2_subdev_selection *sel)1243{1244	switch (sel->target) {1245	case V4L2_SEL_TGT_CROP:1246		sel->r = *v4l2_subdev_state_get_crop(state, sel->pad);1247		return 0;1248 1249	case V4L2_SEL_TGT_CROP_DEFAULT:1250	case V4L2_SEL_TGT_CROP_BOUNDS:1251	case V4L2_SEL_TGT_NATIVE_SIZE:1252		sel->r.left = 0;1253		sel->r.top = 0;1254		sel->r.width = MT9M114_PIXEL_ARRAY_WIDTH;1255		sel->r.height = MT9M114_PIXEL_ARRAY_HEIGHT;1256		return 0;1257 1258	default:1259		return -EINVAL;1260	}1261}1262 1263static int mt9m114_pa_set_selection(struct v4l2_subdev *sd,1264				    struct v4l2_subdev_state *state,1265				    struct v4l2_subdev_selection *sel)1266{1267	struct mt9m114 *sensor = pa_to_mt9m114(sd);1268	struct v4l2_mbus_framefmt *format;1269	struct v4l2_rect *crop;1270 1271	if (sel->target != V4L2_SEL_TGT_CROP)1272		return -EINVAL;1273 1274	crop = v4l2_subdev_state_get_crop(state, sel->pad);1275	format = v4l2_subdev_state_get_format(state, sel->pad);1276 1277	/*1278	 * Clamp the crop rectangle. The vertical coordinates must be even, and1279	 * the horizontal coordinates must be a multiple of 4.1280	 *1281	 * FIXME: The horizontal coordinates must be a multiple of 8 when1282	 * binning, but binning is configured after setting the selection, so1283	 * we can't know tell here if it will be used.1284	 */1285	crop->left = ALIGN(sel->r.left, 4);1286	crop->top = ALIGN(sel->r.top, 2);1287	crop->width = clamp_t(unsigned int, ALIGN(sel->r.width, 4),1288			      MT9M114_PIXEL_ARRAY_MIN_OUTPUT_WIDTH,1289			      MT9M114_PIXEL_ARRAY_WIDTH - crop->left);1290	crop->height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),1291			       MT9M114_PIXEL_ARRAY_MIN_OUTPUT_HEIGHT,1292			       MT9M114_PIXEL_ARRAY_HEIGHT - crop->top);1293 1294	sel->r = *crop;1295 1296	/* Reset the format. */1297	format->width = crop->width;1298	format->height = crop->height;1299 1300	if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE)1301		mt9m114_pa_ctrl_update_blanking(sensor, format);1302 1303	return 0;1304}1305 1306static const struct v4l2_subdev_pad_ops mt9m114_pa_pad_ops = {1307	.enum_mbus_code = mt9m114_pa_enum_mbus_code,1308	.enum_frame_size = mt9m114_pa_enum_framesizes,1309	.get_fmt = v4l2_subdev_get_fmt,1310	.set_fmt = mt9m114_pa_set_fmt,1311	.get_selection = mt9m114_pa_get_selection,1312	.set_selection = mt9m114_pa_set_selection,1313};1314 1315static const struct v4l2_subdev_ops mt9m114_pa_ops = {1316	.pad = &mt9m114_pa_pad_ops,1317};1318 1319static const struct v4l2_subdev_internal_ops mt9m114_pa_internal_ops = {1320	.init_state = mt9m114_pa_init_state,1321};1322 1323static int mt9m114_pa_init(struct mt9m114 *sensor)1324{1325	struct v4l2_ctrl_handler *hdl = &sensor->pa.hdl;1326	struct v4l2_subdev *sd = &sensor->pa.sd;1327	struct media_pad *pads = &sensor->pa.pad;1328	const struct v4l2_mbus_framefmt *format;1329	struct v4l2_subdev_state *state;1330	unsigned int max_exposure;1331	int ret;1332 1333	/* Initialize the subdev. */1334	v4l2_subdev_init(sd, &mt9m114_pa_ops);1335	sd->internal_ops = &mt9m114_pa_internal_ops;1336	v4l2_i2c_subdev_set_name(sd, sensor->client, NULL, " pixel array");1337 1338	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;1339	sd->owner = THIS_MODULE;1340	sd->dev = &sensor->client->dev;1341	v4l2_set_subdevdata(sd, sensor->client);1342 1343	/* Initialize the media entity. */1344	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;1345	sd->entity.ops = &mt9m114_entity_ops;1346	pads[0].flags = MEDIA_PAD_FL_SOURCE;1347	ret = media_entity_pads_init(&sd->entity, 1, pads);1348	if (ret < 0)1349		return ret;1350 1351	/* Initialize the control handler. */1352	v4l2_ctrl_handler_init(hdl, 7);1353 1354	/* The range of the HBLANK and VBLANK controls will be updated below. */1355	sensor->pa.hblank = v4l2_ctrl_new_std(hdl, &mt9m114_pa_ctrl_ops,1356					      V4L2_CID_HBLANK,1357					      MT9M114_DEF_HBLANK,1358					      MT9M114_DEF_HBLANK, 1,1359					      MT9M114_DEF_HBLANK);1360	sensor->pa.vblank = v4l2_ctrl_new_std(hdl, &mt9m114_pa_ctrl_ops,1361					      V4L2_CID_VBLANK,1362					      MT9M114_DEF_VBLANK,1363					      MT9M114_DEF_VBLANK, 1,1364					      MT9M114_DEF_VBLANK);1365 1366	/*1367	 * The maximum coarse integration time is the frame length in lines1368	 * minus two. The default is taken directly from the datasheet, but1369	 * makes little sense as auto-exposure is enabled by default.1370	 */1371	max_exposure = MT9M114_PIXEL_ARRAY_HEIGHT + MT9M114_MIN_VBLANK - 2;1372	sensor->pa.exposure = v4l2_ctrl_new_std(hdl, &mt9m114_pa_ctrl_ops,1373						V4L2_CID_EXPOSURE, 1,1374						max_exposure, 1, 16);1375	if (sensor->pa.exposure)1376		sensor->pa.exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;1377 1378	sensor->pa.gain = v4l2_ctrl_new_std(hdl, &mt9m114_pa_ctrl_ops,1379					    V4L2_CID_ANALOGUE_GAIN, 1,1380					    511, 1, 32);1381	if (sensor->pa.gain)1382		sensor->pa.gain->flags |= V4L2_CTRL_FLAG_VOLATILE;1383 1384	v4l2_ctrl_new_std(hdl, &mt9m114_pa_ctrl_ops,1385			  V4L2_CID_PIXEL_RATE,1386			  sensor->pixrate, sensor->pixrate, 1,1387			  sensor->pixrate);1388 1389	v4l2_ctrl_new_std(hdl, &mt9m114_pa_ctrl_ops,1390			  V4L2_CID_HFLIP,1391			  0, 1, 1, 0);1392	v4l2_ctrl_new_std(hdl, &mt9m114_pa_ctrl_ops,1393			  V4L2_CID_VFLIP,1394			  0, 1, 1, 0);1395 1396	if (hdl->error) {1397		ret = hdl->error;1398		goto error;1399	}1400 1401	sd->state_lock = hdl->lock;1402 1403	ret = v4l2_subdev_init_finalize(sd);1404	if (ret)1405		goto error;1406 1407	/* Update the range of the blanking controls based on the format. */1408	state = v4l2_subdev_lock_and_get_active_state(sd);1409	format = v4l2_subdev_state_get_format(state, 0);1410	mt9m114_pa_ctrl_update_blanking(sensor, format);1411	v4l2_subdev_unlock_state(state);1412 1413	sd->ctrl_handler = hdl;1414 1415	return 0;1416 1417error:1418	v4l2_ctrl_handler_free(&sensor->pa.hdl);1419	media_entity_cleanup(&sensor->pa.sd.entity);1420	return ret;1421}1422 1423static void mt9m114_pa_cleanup(struct mt9m114 *sensor)1424{1425	v4l2_ctrl_handler_free(&sensor->pa.hdl);1426	media_entity_cleanup(&sensor->pa.sd.entity);1427}1428 1429/* -----------------------------------------------------------------------------1430 * Image Flow Processor Control Operations1431 */1432 1433static const char * const mt9m114_test_pattern_menu[] = {1434	"Disabled",1435	"Solid Color",1436	"100% Color Bars",1437	"Pseudo-Random",1438	"Fade-to-Gray Color Bars",1439	"Walking Ones 10-bit",1440	"Walking Ones 8-bit",1441};1442 1443/* Keep in sync with mt9m114_test_pattern_menu */1444static const unsigned int mt9m114_test_pattern_value[] = {1445	MT9M114_CAM_MODE_TEST_PATTERN_SELECT_SOLID,1446	MT9M114_CAM_MODE_TEST_PATTERN_SELECT_SOLID_BARS,1447	MT9M114_CAM_MODE_TEST_PATTERN_SELECT_RANDOM,1448	MT9M114_CAM_MODE_TEST_PATTERN_SELECT_FADING_BARS,1449	MT9M114_CAM_MODE_TEST_PATTERN_SELECT_WALKING_1S_10B,1450	MT9M114_CAM_MODE_TEST_PATTERN_SELECT_WALKING_1S_8B,1451};1452 1453static inline struct mt9m114 *ifp_ctrl_to_mt9m114(struct v4l2_ctrl *ctrl)1454{1455	return container_of(ctrl->handler, struct mt9m114, ifp.hdl);1456}1457 1458static int mt9m114_ifp_s_ctrl(struct v4l2_ctrl *ctrl)1459{1460	struct mt9m114 *sensor = ifp_ctrl_to_mt9m114(ctrl);1461	u32 value;1462	int ret = 0;1463 1464	if (ctrl->id == V4L2_CID_EXPOSURE_AUTO)1465		mt9m114_pa_ctrl_update_exposure(sensor,1466						ctrl->val != V4L2_EXPOSURE_AUTO);1467 1468	/* V4L2 controls values are applied only when power is up. */1469	if (!pm_runtime_get_if_in_use(&sensor->client->dev))1470		return 0;1471 1472	switch (ctrl->id) {1473	case V4L2_CID_AUTO_WHITE_BALANCE:1474		/* Control both the AWB mode and the CCM algorithm. */1475		if (ctrl->val)1476			value = MT9M114_CAM_AWB_MODE_AUTO1477			      | MT9M114_CAM_AWB_MODE_EXCLUSIVE_AE;1478		else1479			value = 0;1480 1481		cci_write(sensor->regmap, MT9M114_CAM_AWB_AWBMODE, value, &ret);1482 1483		if (ctrl->val)1484			value = MT9M114_CCM_EXEC_CALC_CCM_MATRIX | 0x22;1485		else1486			value = 0;1487 1488		cci_write(sensor->regmap, MT9M114_CCM_ALGO, value, &ret);1489		break;1490 1491	case V4L2_CID_EXPOSURE_AUTO:1492		if (ctrl->val == V4L2_EXPOSURE_AUTO)1493			value = MT9M114_AE_TRACK_EXEC_AUTOMATIC_EXPOSURE1494			      | 0x00fe;1495		else1496			value = 0;1497 1498		cci_write(sensor->regmap, MT9M114_AE_TRACK_ALGO, value, &ret);1499		if (ret)1500			break;1501 1502		break;1503 1504	case V4L2_CID_TEST_PATTERN:1505	case V4L2_CID_TEST_PATTERN_RED:1506	case V4L2_CID_TEST_PATTERN_GREENR:1507	case V4L2_CID_TEST_PATTERN_BLUE: {1508		unsigned int pattern = sensor->ifp.tpg[MT9M114_TPG_PATTERN]->val;1509 1510		if (pattern) {1511			cci_write(sensor->regmap, MT9M114_CAM_MODE_SELECT,1512				  MT9M114_CAM_MODE_SELECT_TEST_PATTERN, &ret);1513			cci_write(sensor->regmap,1514				  MT9M114_CAM_MODE_TEST_PATTERN_SELECT,1515				  mt9m114_test_pattern_value[pattern - 1], &ret);1516			cci_write(sensor->regmap,1517				  MT9M114_CAM_MODE_TEST_PATTERN_RED,1518				  sensor->ifp.tpg[MT9M114_TPG_RED]->val, &ret);1519			cci_write(sensor->regmap,1520				  MT9M114_CAM_MODE_TEST_PATTERN_GREEN,1521				  sensor->ifp.tpg[MT9M114_TPG_GREEN]->val, &ret);1522			cci_write(sensor->regmap,1523				  MT9M114_CAM_MODE_TEST_PATTERN_BLUE,1524				  sensor->ifp.tpg[MT9M114_TPG_BLUE]->val, &ret);1525		} else {1526			cci_write(sensor->regmap, MT9M114_CAM_MODE_SELECT,1527				  MT9M114_CAM_MODE_SELECT_NORMAL, &ret);1528		}1529 1530		/*1531		 * A Config-Change needs to be issued for the change to take1532		 * effect. If we're not streaming ignore this, the change will1533		 * be applied when the stream is started.1534		 */1535		if (ret || !sensor->streaming)1536			break;1537 1538		ret = mt9m114_set_state(sensor,1539					MT9M114_SYS_STATE_ENTER_CONFIG_CHANGE);1540		break;1541	}1542 1543	default:1544		ret = -EINVAL;1545		break;1546	}1547 1548	pm_runtime_mark_last_busy(&sensor->client->dev);1549	pm_runtime_put_autosuspend(&sensor->client->dev);1550 1551	return ret;1552}1553 1554static const struct v4l2_ctrl_ops mt9m114_ifp_ctrl_ops = {1555	.s_ctrl = mt9m114_ifp_s_ctrl,1556};1557 1558/* -----------------------------------------------------------------------------1559 * Image Flow Processor Subdev Operations1560 */1561 1562static inline struct mt9m114 *ifp_to_mt9m114(struct v4l2_subdev *sd)1563{1564	return container_of(sd, struct mt9m114, ifp.sd);1565}1566 1567static int mt9m114_ifp_s_stream(struct v4l2_subdev *sd, int enable)1568{1569	struct mt9m114 *sensor = ifp_to_mt9m114(sd);1570	struct v4l2_subdev_state *pa_state;1571	struct v4l2_subdev_state *ifp_state;1572	int ret;1573 1574	if (!enable)1575		return mt9m114_stop_streaming(sensor);1576 1577	ifp_state = v4l2_subdev_lock_and_get_active_state(&sensor->ifp.sd);1578	pa_state = v4l2_subdev_lock_and_get_active_state(&sensor->pa.sd);1579 1580	ret = mt9m114_start_streaming(sensor, pa_state, ifp_state);1581 1582	v4l2_subdev_unlock_state(pa_state);1583	v4l2_subdev_unlock_state(ifp_state);1584 1585	return ret;1586}1587 1588static int mt9m114_ifp_get_frame_interval(struct v4l2_subdev *sd,1589					  struct v4l2_subdev_state *sd_state,1590					  struct v4l2_subdev_frame_interval *interval)1591{1592	struct v4l2_fract *ival = &interval->interval;1593	struct mt9m114 *sensor = ifp_to_mt9m114(sd);1594 1595	/*1596	 * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L21597	 * subdev active state API.1598	 */1599	if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)1600		return -EINVAL;1601 1602	mutex_lock(sensor->ifp.hdl.lock);1603 1604	ival->numerator = 1;1605	ival->denominator = sensor->ifp.frame_rate;1606 1607	mutex_unlock(sensor->ifp.hdl.lock);1608 1609	return 0;1610}1611 1612static int mt9m114_ifp_set_frame_interval(struct v4l2_subdev *sd,1613					  struct v4l2_subdev_state *sd_state,1614					  struct v4l2_subdev_frame_interval *interval)1615{1616	struct v4l2_fract *ival = &interval->interval;1617	struct mt9m114 *sensor = ifp_to_mt9m114(sd);1618	int ret = 0;1619 1620	/*1621	 * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L21622	 * subdev active state API.1623	 */1624	if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)1625		return -EINVAL;1626 1627	mutex_lock(sensor->ifp.hdl.lock);1628 1629	if (ival->numerator != 0 && ival->denominator != 0)1630		sensor->ifp.frame_rate = min_t(unsigned int,1631					       ival->denominator / ival->numerator,1632					       MT9M114_MAX_FRAME_RATE);1633	else1634		sensor->ifp.frame_rate = MT9M114_MAX_FRAME_RATE;1635 1636	ival->numerator = 1;1637	ival->denominator = sensor->ifp.frame_rate;1638 1639	if (sensor->streaming)1640		ret = mt9m114_set_frame_rate(sensor);1641 1642	mutex_unlock(sensor->ifp.hdl.lock);1643 1644	return ret;1645}1646 1647static int mt9m114_ifp_init_state(struct v4l2_subdev *sd,1648				  struct v4l2_subdev_state *state)1649{1650	struct mt9m114 *sensor = ifp_to_mt9m114(sd);1651	struct v4l2_mbus_framefmt *format;1652	struct v4l2_rect *crop;1653	struct v4l2_rect *compose;1654 1655	format = v4l2_subdev_state_get_format(state, 0);1656 1657	format->width = MT9M114_PIXEL_ARRAY_WIDTH;1658	format->height = MT9M114_PIXEL_ARRAY_HEIGHT;1659	format->code = MEDIA_BUS_FMT_SGRBG10_1X10;1660	format->field = V4L2_FIELD_NONE;1661	format->colorspace = V4L2_COLORSPACE_RAW;1662	format->ycbcr_enc = V4L2_YCBCR_ENC_601;1663	format->quantization = V4L2_QUANTIZATION_FULL_RANGE;1664	format->xfer_func = V4L2_XFER_FUNC_NONE;1665 1666	crop = v4l2_subdev_state_get_crop(state, 0);1667 1668	crop->left = 4;1669	crop->top = 4;1670	crop->width = format->width - 8;1671	crop->height = format->height - 8;1672 1673	compose = v4l2_subdev_state_get_compose(state, 0);1674 1675	compose->left = 0;1676	compose->top = 0;1677	compose->width = crop->width;1678	compose->height = crop->height;1679 1680	format = v4l2_subdev_state_get_format(state, 1);1681 1682	format->width = compose->width;1683	format->height = compose->height;1684	format->code = mt9m114_default_format_info(sensor)->code;1685	format->field = V4L2_FIELD_NONE;1686	format->colorspace = V4L2_COLORSPACE_SRGB;1687	format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;1688	format->quantization = V4L2_QUANTIZATION_DEFAULT;1689	format->xfer_func = V4L2_XFER_FUNC_DEFAULT;1690 1691	return 0;1692}1693 1694static int mt9m114_ifp_enum_mbus_code(struct v4l2_subdev *sd,1695				      struct v4l2_subdev_state *state,1696				      struct v4l2_subdev_mbus_code_enum *code)1697{1698	const unsigned int num_formats = ARRAY_SIZE(mt9m114_format_infos);1699	struct mt9m114 *sensor = ifp_to_mt9m114(sd);1700	unsigned int index = 0;1701	unsigned int flag;1702	unsigned int i;1703 1704	switch (code->pad) {1705	case 0:1706		if (code->index != 0)1707			return -EINVAL;1708 1709		code->code = mt9m114_format_infos[num_formats - 1].code;1710		return 0;1711 1712	case 1:1713		if (sensor->bus_cfg.bus_type == V4L2_MBUS_CSI2_DPHY)1714			flag = MT9M114_FMT_FLAG_CSI2;1715		else1716			flag = MT9M114_FMT_FLAG_PARALLEL;1717 1718		for (i = 0; i < num_formats; ++i) {1719			const struct mt9m114_format_info *info =1720				&mt9m114_format_infos[i];1721 1722			if (info->flags & flag) {1723				if (index == code->index) {1724					code->code = info->code;1725					return 0;1726				}1727 1728				index++;1729			}1730		}1731 1732		return -EINVAL;1733 1734	default:1735		return -EINVAL;1736	}1737}1738 1739static int mt9m114_ifp_enum_framesizes(struct v4l2_subdev *sd,1740				       struct v4l2_subdev_state *state,1741				       struct v4l2_subdev_frame_size_enum *fse)1742{1743	struct mt9m114 *sensor = ifp_to_mt9m114(sd);1744	const struct mt9m114_format_info *info;1745 1746	if (fse->index > 0)1747		return -EINVAL;1748 1749	info = mt9m114_format_info(sensor, fse->pad, fse->code);1750	if (!info || info->code != fse->code)1751		return -EINVAL;1752 1753	if (fse->pad == 0) {1754		fse->min_width = MT9M114_PIXEL_ARRAY_MIN_OUTPUT_WIDTH;1755		fse->max_width = MT9M114_PIXEL_ARRAY_WIDTH;1756		fse->min_height = MT9M114_PIXEL_ARRAY_MIN_OUTPUT_HEIGHT;1757		fse->max_height = MT9M114_PIXEL_ARRAY_HEIGHT;1758	} else {1759		const struct v4l2_rect *crop;1760 1761		crop = v4l2_subdev_state_get_crop(state, 0);1762 1763		fse->max_width = crop->width;1764		fse->max_height = crop->height;1765 1766		fse->min_width = fse->max_width / 4;1767		fse->min_height = fse->max_height / 4;1768	}1769 1770	return 0;1771}1772 1773static int mt9m114_ifp_enum_frameintervals(struct v4l2_subdev *sd,1774					   struct v4l2_subdev_state *state,1775					   struct v4l2_subdev_frame_interval_enum *fie)1776{1777	struct mt9m114 *sensor = ifp_to_mt9m114(sd);1778	const struct mt9m114_format_info *info;1779 1780	if (fie->index > 0)1781		return -EINVAL;1782 1783	info = mt9m114_format_info(sensor, fie->pad, fie->code);1784	if (!info || info->code != fie->code)1785		return -EINVAL;1786 1787	fie->interval.numerator = 1;1788	fie->interval.denominator = MT9M114_MAX_FRAME_RATE;1789 1790	return 0;1791}1792 1793static int mt9m114_ifp_set_fmt(struct v4l2_subdev *sd,1794			       struct v4l2_subdev_state *state,1795			       struct v4l2_subdev_format *fmt)1796{1797	struct mt9m114 *sensor = ifp_to_mt9m114(sd);1798	struct v4l2_mbus_framefmt *format;1799 1800	format = v4l2_subdev_state_get_format(state, fmt->pad);1801 1802	if (fmt->pad == 0) {1803		/* Only the size can be changed on the sink pad. */1804		format->width = clamp(ALIGN(fmt->format.width, 8),1805				      MT9M114_PIXEL_ARRAY_MIN_OUTPUT_WIDTH,1806				      MT9M114_PIXEL_ARRAY_WIDTH);1807		format->height = clamp(ALIGN(fmt->format.height, 8),1808				       MT9M114_PIXEL_ARRAY_MIN_OUTPUT_HEIGHT,1809				       MT9M114_PIXEL_ARRAY_HEIGHT);1810	} else {1811		const struct mt9m114_format_info *info;1812 1813		/* Only the media bus code can be changed on the source pad. */1814		info = mt9m114_format_info(sensor, 1, fmt->format.code);1815 1816		format->code = info->code;1817 1818		/* If the output format is RAW10, bypass the scaler. */1819		if (format->code == MEDIA_BUS_FMT_SGRBG10_1X10)1820			*format = *v4l2_subdev_state_get_format(state, 0);1821	}1822 1823	fmt->format = *format;1824 1825	return 0;1826}1827 1828static int mt9m114_ifp_get_selection(struct v4l2_subdev *sd,1829				     struct v4l2_subdev_state *state,1830				     struct v4l2_subdev_selection *sel)1831{1832	const struct v4l2_mbus_framefmt *format;1833	const struct v4l2_rect *crop;1834	int ret = 0;1835 1836	/* Crop and compose are only supported on the sink pad. */1837	if (sel->pad != 0)1838		return -EINVAL;1839 1840	switch (sel->target) {1841	case V4L2_SEL_TGT_CROP:1842		sel->r = *v4l2_subdev_state_get_crop(state, 0);1843		break;1844 1845	case V4L2_SEL_TGT_CROP_DEFAULT:1846	case V4L2_SEL_TGT_CROP_BOUNDS:1847		/*1848		 * The crop default and bounds are equal to the sink1849		 * format size minus 4 pixels on each side for demosaicing.1850		 */1851		format = v4l2_subdev_state_get_format(state, 0);1852 1853		sel->r.left = 4;1854		sel->r.top = 4;1855		sel->r.width = format->width - 8;1856		sel->r.height = format->height - 8;1857		break;1858 1859	case V4L2_SEL_TGT_COMPOSE:1860		sel->r = *v4l2_subdev_state_get_compose(state, 0);1861		break;1862 1863	case V4L2_SEL_TGT_COMPOSE_DEFAULT:1864	case V4L2_SEL_TGT_COMPOSE_BOUNDS:1865		/*1866		 * The compose default and bounds sizes are equal to the sink1867		 * crop rectangle size.1868		 */1869		crop = v4l2_subdev_state_get_crop(state, 0);1870		sel->r.left = 0;1871		sel->r.top = 0;1872		sel->r.width = crop->width;1873		sel->r.height = crop->height;1874		break;1875 1876	default:1877		ret = -EINVAL;1878		break;1879	}1880 1881	return ret;1882}1883 1884static int mt9m114_ifp_set_selection(struct v4l2_subdev *sd,1885				     struct v4l2_subdev_state *state,1886				     struct v4l2_subdev_selection *sel)1887{1888	struct v4l2_mbus_framefmt *format;1889	struct v4l2_rect *crop;1890	struct v4l2_rect *compose;1891 1892	if (sel->target != V4L2_SEL_TGT_CROP &&1893	    sel->target != V4L2_SEL_TGT_COMPOSE)1894		return -EINVAL;1895 1896	/* Crop and compose are only supported on the sink pad. */1897	if (sel->pad != 0)1898		return -EINVAL;1899 1900	format = v4l2_subdev_state_get_format(state, 0);1901	crop = v4l2_subdev_state_get_crop(state, 0);1902	compose = v4l2_subdev_state_get_compose(state, 0);1903 1904	if (sel->target == V4L2_SEL_TGT_CROP) {1905		/*1906		 * Clamp the crop rectangle. Demosaicing removes 4 pixels on1907		 * each side of the image.1908		 */1909		crop->left = clamp_t(unsigned int, ALIGN(sel->r.left, 2), 4,1910				     format->width - 4 -1911				     MT9M114_SCALER_CROPPED_INPUT_WIDTH);1912		crop->top = clamp_t(unsigned int, ALIGN(sel->r.top, 2), 4,1913				    format->height - 4 -1914				    MT9M114_SCALER_CROPPED_INPUT_HEIGHT);1915		crop->width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),1916				      MT9M114_SCALER_CROPPED_INPUT_WIDTH,1917				      format->width - 4 - crop->left);1918		crop->height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),1919				       MT9M114_SCALER_CROPPED_INPUT_HEIGHT,1920				       format->height - 4 - crop->top);1921 1922		sel->r = *crop;1923 1924		/* Propagate to the compose rectangle. */1925		compose->width = crop->width;1926		compose->height = crop->height;1927	} else {1928		/*1929		 * Clamp the compose rectangle. The scaler can only downscale.1930		 */1931		compose->left = 0;1932		compose->top = 0;1933		compose->width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),1934					 MT9M114_SCALER_CROPPED_INPUT_WIDTH,1935					 crop->width);1936		compose->height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),1937					  MT9M114_SCALER_CROPPED_INPUT_HEIGHT,1938					  crop->height);1939 1940		sel->r = *compose;1941	}1942 1943	/* Propagate the compose rectangle to the source format. */1944	format = v4l2_subdev_state_get_format(state, 1);1945	format->width = compose->width;1946	format->height = compose->height;1947 1948	return 0;1949}1950 1951static void mt9m114_ifp_unregistered(struct v4l2_subdev *sd)1952{1953	struct mt9m114 *sensor = ifp_to_mt9m114(sd);1954 1955	v4l2_device_unregister_subdev(&sensor->pa.sd);1956}1957 1958static int mt9m114_ifp_registered(struct v4l2_subdev *sd)1959{1960	struct mt9m114 *sensor = ifp_to_mt9m114(sd);1961	int ret;1962 1963	ret = v4l2_device_register_subdev(sd->v4l2_dev, &sensor->pa.sd);1964	if (ret < 0) {1965		dev_err(&sensor->client->dev,1966			"Failed to register pixel array subdev\n");1967		return ret;1968	}1969 1970	ret = media_create_pad_link(&sensor->pa.sd.entity, 0,1971				    &sensor->ifp.sd.entity, 0,1972				    MEDIA_LNK_FL_ENABLED |1973				    MEDIA_LNK_FL_IMMUTABLE);1974	if (ret < 0) {1975		dev_err(&sensor->client->dev,1976			"Failed to link pixel array to ifp\n");1977		v4l2_device_unregister_subdev(&sensor->pa.sd);1978		return ret;1979	}1980 1981	return 0;1982}1983 1984static const struct v4l2_subdev_video_ops mt9m114_ifp_video_ops = {1985	.s_stream = mt9m114_ifp_s_stream,1986};1987 1988static const struct v4l2_subdev_pad_ops mt9m114_ifp_pad_ops = {1989	.enum_mbus_code = mt9m114_ifp_enum_mbus_code,1990	.enum_frame_size = mt9m114_ifp_enum_framesizes,1991	.enum_frame_interval = mt9m114_ifp_enum_frameintervals,1992	.get_fmt = v4l2_subdev_get_fmt,1993	.set_fmt = mt9m114_ifp_set_fmt,1994	.get_selection = mt9m114_ifp_get_selection,1995	.set_selection = mt9m114_ifp_set_selection,1996	.get_frame_interval = mt9m114_ifp_get_frame_interval,1997	.set_frame_interval = mt9m114_ifp_set_frame_interval,1998};1999 2000static const struct v4l2_subdev_ops mt9m114_ifp_ops = {2001	.video = &mt9m114_ifp_video_ops,2002	.pad = &mt9m114_ifp_pad_ops,2003};2004 2005static const struct v4l2_subdev_internal_ops mt9m114_ifp_internal_ops = {2006	.init_state = mt9m114_ifp_init_state,2007	.registered = mt9m114_ifp_registered,2008	.unregistered = mt9m114_ifp_unregistered,2009};2010 2011static int mt9m114_ifp_init(struct mt9m114 *sensor)2012{2013	struct v4l2_subdev *sd = &sensor->ifp.sd;2014	struct media_pad *pads = sensor->ifp.pads;2015	struct v4l2_ctrl_handler *hdl = &sensor->ifp.hdl;2016	struct v4l2_ctrl *link_freq;2017	int ret;2018 2019	/* Initialize the subdev. */2020	v4l2_i2c_subdev_init(sd, sensor->client, &mt9m114_ifp_ops);2021	v4l2_i2c_subdev_set_name(sd, sensor->client, NULL, " ifp");2022 2023	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;2024	sd->internal_ops = &mt9m114_ifp_internal_ops;2025 2026	/* Initialize the media entity. */2027	sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_ISP;2028	sd->entity.ops = &mt9m114_entity_ops;2029	pads[0].flags = MEDIA_PAD_FL_SINK;2030	pads[1].flags = MEDIA_PAD_FL_SOURCE;2031	ret = media_entity_pads_init(&sd->entity, 2, pads);2032	if (ret < 0)2033		return ret;2034 2035	sensor->ifp.frame_rate = MT9M114_DEF_FRAME_RATE;2036 2037	/* Initialize the control handler. */2038	v4l2_ctrl_handler_init(hdl, 8);2039	v4l2_ctrl_new_std(hdl, &mt9m114_ifp_ctrl_ops,2040			  V4L2_CID_AUTO_WHITE_BALANCE,2041			  0, 1, 1, 1);2042	v4l2_ctrl_new_std_menu(hdl, &mt9m114_ifp_ctrl_ops,2043			       V4L2_CID_EXPOSURE_AUTO,2044			       V4L2_EXPOSURE_MANUAL, 0,2045			       V4L2_EXPOSURE_AUTO);2046 2047	link_freq = v4l2_ctrl_new_int_menu(hdl, &mt9m114_ifp_ctrl_ops,2048					   V4L2_CID_LINK_FREQ,2049					   sensor->bus_cfg.nr_of_link_frequencies - 1,2050					   0, sensor->bus_cfg.link_frequencies);2051	if (link_freq)2052		link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;2053 2054	v4l2_ctrl_new_std(hdl, &mt9m114_ifp_ctrl_ops,2055			  V4L2_CID_PIXEL_RATE,2056			  sensor->pixrate, sensor->pixrate, 1,2057			  sensor->pixrate);2058 2059	sensor->ifp.tpg[MT9M114_TPG_PATTERN] =2060		v4l2_ctrl_new_std_menu_items(hdl, &mt9m114_ifp_ctrl_ops,2061					     V4L2_CID_TEST_PATTERN,2062					     ARRAY_SIZE(mt9m114_test_pattern_menu) - 1,2063					     0, 0, mt9m114_test_pattern_menu);2064	sensor->ifp.tpg[MT9M114_TPG_RED] =2065		v4l2_ctrl_new_std(hdl, &mt9m114_ifp_ctrl_ops,2066				  V4L2_CID_TEST_PATTERN_RED,2067				  0, 1023, 1, 1023);2068	sensor->ifp.tpg[MT9M114_TPG_GREEN] =2069		v4l2_ctrl_new_std(hdl, &mt9m114_ifp_ctrl_ops,2070				  V4L2_CID_TEST_PATTERN_GREENR,2071				  0, 1023, 1, 1023);2072	sensor->ifp.tpg[MT9M114_TPG_BLUE] =2073		v4l2_ctrl_new_std(hdl, &mt9m114_ifp_ctrl_ops,2074				  V4L2_CID_TEST_PATTERN_BLUE,2075				  0, 1023, 1, 1023);2076 2077	v4l2_ctrl_cluster(ARRAY_SIZE(sensor->ifp.tpg), sensor->ifp.tpg);2078 2079	if (hdl->error) {2080		ret = hdl->error;2081		goto error;2082	}2083 2084	sd->ctrl_handler = hdl;2085	sd->state_lock = hdl->lock;2086 2087	ret = v4l2_subdev_init_finalize(sd);2088	if (ret)2089		goto error;2090 2091	return 0;2092 2093error:2094	v4l2_ctrl_handler_free(&sensor->ifp.hdl);2095	media_entity_cleanup(&sensor->ifp.sd.entity);2096	return ret;2097}2098 2099static void mt9m114_ifp_cleanup(struct mt9m114 *sensor)2100{2101	v4l2_ctrl_handler_free(&sensor->ifp.hdl);2102	media_entity_cleanup(&sensor->ifp.sd.entity);2103}2104 2105/* -----------------------------------------------------------------------------2106 * Power Management2107 */2108 2109static int mt9m114_power_on(struct mt9m114 *sensor)2110{2111	int ret;2112 2113	/* Enable power and clocks. */2114	ret = regulator_bulk_enable(ARRAY_SIZE(sensor->supplies),2115				    sensor->supplies);2116	if (ret < 0)2117		return ret;2118 2119	ret = clk_prepare_enable(sensor->clk);2120	if (ret < 0)2121		goto error_regulator;2122 2123	/* Perform a hard reset if available, or a soft reset otherwise. */2124	if (sensor->reset) {2125		long freq = clk_get_rate(sensor->clk);2126		unsigned int duration;2127 2128		/*2129		 * The minimum duration is 50 clock cycles, thus typically2130		 * around 2µs. Double it to be safe.2131		 */2132		duration = DIV_ROUND_UP(2 * 50 * 1000000, freq);2133 2134		gpiod_set_value(sensor->reset, 1);2135		fsleep(duration);2136		gpiod_set_value(sensor->reset, 0);2137	} else {2138		/*2139		 * The power may have just been turned on, we need to wait for2140		 * the sensor to be ready to accept I2C commands.2141		 */2142		usleep_range(44500, 50000);2143 2144		cci_write(sensor->regmap, MT9M114_RESET_AND_MISC_CONTROL,2145			  MT9M114_RESET_SOC, &ret);2146		cci_write(sensor->regmap, MT9M114_RESET_AND_MISC_CONTROL, 0,2147			  &ret);2148 2149		if (ret < 0) {2150			dev_err(&sensor->client->dev, "Soft reset failed\n");2151			goto error_clock;2152		}2153	}2154 2155	/*2156	 * Wait for the sensor to be ready to accept I2C commands by polling the2157	 * command register to wait for initialization to complete.2158	 */2159	usleep_range(44500, 50000);2160 2161	ret = mt9m114_poll_command(sensor, MT9M114_COMMAND_REGISTER_SET_STATE);2162	if (ret < 0)2163		goto error_clock;2164 2165	if (sensor->bus_cfg.bus_type == V4L2_MBUS_PARALLEL) {2166		/*2167		 * In parallel mode (OE set to low), the sensor will enter the2168		 * streaming state after initialization. Enter the standby2169		 * manually to stop streaming.2170		 */2171		ret = mt9m114_set_state(sensor,2172					MT9M114_SYS_STATE_ENTER_STANDBY);2173		if (ret < 0)2174			goto error_clock;2175	}2176 2177	/*2178	 * Before issuing any Set-State command, we must ensure that the sensor2179	 * reaches the standby mode (either initiated manually above in2180	 * parallel mode, or automatically after reset in MIPI mode).2181	 */2182	ret = mt9m114_poll_state(sensor, MT9M114_SYS_STATE_STANDBY);2183	if (ret < 0)2184		goto error_clock;2185 2186	return 0;2187 2188error_clock:2189	clk_disable_unprepare(sensor->clk);2190error_regulator:2191	regulator_bulk_disable(ARRAY_SIZE(sensor->supplies), sensor->supplies);2192	return ret;2193}2194 2195static void mt9m114_power_off(struct mt9m114 *sensor)2196{2197	clk_disable_unprepare(sensor->clk);2198	regulator_bulk_disable(ARRAY_SIZE(sensor->supplies), sensor->supplies);2199}2200 2201static int __maybe_unused mt9m114_runtime_resume(struct device *dev)2202{2203	struct v4l2_subdev *sd = dev_get_drvdata(dev);2204	struct mt9m114 *sensor = ifp_to_mt9m114(sd);2205	int ret;2206 2207	ret = mt9m114_power_on(sensor);2208	if (ret)2209		return ret;2210 2211	ret = mt9m114_initialize(sensor);2212	if (ret) {2213		mt9m114_power_off(sensor);2214		return ret;2215	}2216 2217	return 0;2218}2219 2220static int __maybe_unused mt9m114_runtime_suspend(struct device *dev)2221{2222	struct v4l2_subdev *sd = dev_get_drvdata(dev);2223	struct mt9m114 *sensor = ifp_to_mt9m114(sd);2224 2225	mt9m114_power_off(sensor);2226 2227	return 0;2228}2229 2230static const struct dev_pm_ops mt9m114_pm_ops = {2231	SET_RUNTIME_PM_OPS(mt9m114_runtime_suspend, mt9m114_runtime_resume, NULL)2232};2233 2234/* -----------------------------------------------------------------------------2235 * Probe & Remove2236 */2237 2238static int mt9m114_clk_init(struct mt9m114 *sensor)2239{2240	unsigned int link_freq;2241 2242	/* Hardcode the PLL multiplier and dividers to default settings. */2243	sensor->pll.m = 32;2244	sensor->pll.n = 1;2245	sensor->pll.p = 7;2246 2247	/*2248	 * Calculate the pixel rate and link frequency. The CSI-2 bus is clocked2249	 * for 16-bit per pixel, transmitted in DDR over a single lane. For2250	 * parallel mode, the sensor ouputs one pixel in two PIXCLK cycles.2251	 */2252	sensor->pixrate = clk_get_rate(sensor->clk) * sensor->pll.m2253			/ ((sensor->pll.n + 1) * (sensor->pll.p + 1));2254 2255	link_freq = sensor->bus_cfg.bus_type == V4L2_MBUS_CSI2_DPHY2256		  ? sensor->pixrate * 8 : sensor->pixrate * 2;2257 2258	if (sensor->bus_cfg.nr_of_link_frequencies != 1 ||2259	    sensor->bus_cfg.link_frequencies[0] != link_freq) {2260		dev_err(&sensor->client->dev, "Unsupported DT link-frequencies\n");2261		return -EINVAL;2262	}2263 2264	return 0;2265}2266 2267static int mt9m114_identify(struct mt9m114 *sensor)2268{2269	u64 major, minor, release, customer;2270	u64 value;2271	int ret;2272 2273	ret = cci_read(sensor->regmap, MT9M114_CHIP_ID, &value, NULL);2274	if (ret) {2275		dev_err(&sensor->client->dev, "Failed to read chip ID\n");2276		return -ENXIO;2277	}2278 2279	if (value != 0x2481) {2280		dev_err(&sensor->client->dev, "Invalid chip ID 0x%04llx\n",2281			value);2282		return -ENXIO;2283	}2284 2285	cci_read(sensor->regmap, MT9M114_MON_MAJOR_VERSION, &major, &ret);2286	cci_read(sensor->regmap, MT9M114_MON_MINOR_VERSION, &minor, &ret);2287	cci_read(sensor->regmap, MT9M114_MON_RELEASE_VERSION, &release, &ret);2288	cci_read(sensor->regmap, MT9M114_CUSTOMER_REV, &customer, &ret);2289	if (ret) {2290		dev_err(&sensor->client->dev, "Failed to read version\n");2291		return -ENXIO;2292	}2293 2294	dev_dbg(&sensor->client->dev,2295		"monitor v%llu.%llu.%04llx customer rev 0x%04llx\n",2296		major, minor, release, customer);2297 2298	return 0;2299}2300 2301static int mt9m114_parse_dt(struct mt9m114 *sensor)2302{2303	struct fwnode_handle *fwnode = dev_fwnode(&sensor->client->dev);2304	struct fwnode_handle *ep;2305	int ret;2306 2307	ep = fwnode_graph_get_next_endpoint(fwnode, NULL);2308	if (!ep) {2309		dev_err(&sensor->client->dev, "No endpoint found\n");2310		return -EINVAL;2311	}2312 2313	sensor->bus_cfg.bus_type = V4L2_MBUS_UNKNOWN;2314	ret = v4l2_fwnode_endpoint_alloc_parse(ep, &sensor->bus_cfg);2315	fwnode_handle_put(ep);2316	if (ret < 0) {2317		dev_err(&sensor->client->dev, "Failed to parse endpoint\n");2318		goto error;2319	}2320 2321	switch (sensor->bus_cfg.bus_type) {2322	case V4L2_MBUS_CSI2_DPHY:2323	case V4L2_MBUS_PARALLEL:2324		break;2325 2326	default:2327		dev_err(&sensor->client->dev, "unsupported bus type %u\n",2328			sensor->bus_cfg.bus_type);2329		ret = -EINVAL;2330		goto error;2331	}2332 2333	return 0;2334 2335error:2336	v4l2_fwnode_endpoint_free(&sensor->bus_cfg);2337	return ret;2338}2339 2340static int mt9m114_probe(struct i2c_client *client)2341{2342	struct device *dev = &client->dev;2343	struct mt9m114 *sensor;2344	int ret;2345 2346	sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);2347	if (!sensor)2348		return -ENOMEM;2349 2350	sensor->client = client;2351 2352	sensor->regmap = devm_cci_regmap_init_i2c(client, 16);2353	if (IS_ERR(sensor->regmap)) {2354		dev_err(dev, "Unable to initialize I2C\n");2355		return -ENODEV;2356	}2357 2358	ret = mt9m114_parse_dt(sensor);2359	if (ret < 0)2360		return ret;2361 2362	/* Acquire clocks, GPIOs and regulators. */2363	sensor->clk = devm_clk_get(dev, NULL);2364	if (IS_ERR(sensor->clk)) {2365		ret = PTR_ERR(sensor->clk);2366		dev_err_probe(dev, ret, "Failed to get clock\n");2367		goto error_ep_free;2368	}2369 2370	sensor->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);2371	if (IS_ERR(sensor->reset)) {2372		ret = PTR_ERR(sensor->reset);2373		dev_err_probe(dev, ret, "Failed to get reset GPIO\n");2374		goto error_ep_free;2375	}2376 2377	sensor->supplies[0].supply = "vddio";2378	sensor->supplies[1].supply = "vdd";2379	sensor->supplies[2].supply = "vaa";2380 2381	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(sensor->supplies),2382				      sensor->supplies);2383	if (ret < 0) {2384		dev_err_probe(dev, ret, "Failed to get regulators\n");2385		goto error_ep_free;2386	}2387 2388	ret = mt9m114_clk_init(sensor);2389	if (ret)2390		goto error_ep_free;2391 2392	/*2393	 * Identify the sensor. The driver supports runtime PM, but needs to2394	 * work when runtime PM is disabled in the kernel. To that end, power2395	 * the sensor on manually here, and initialize it after identification2396	 * to reach the same state as if resumed through runtime PM.2397	 */2398	ret = mt9m114_power_on(sensor);2399	if (ret < 0) {2400		dev_err_probe(dev, ret, "Could not power on the device\n");2401		goto error_ep_free;2402	}2403 2404	ret = mt9m114_identify(sensor);2405	if (ret < 0)2406		goto error_power_off;2407 2408	ret = mt9m114_initialize(sensor);2409	if (ret < 0)2410		goto error_power_off;2411 2412	/*2413	 * Enable runtime PM with autosuspend. As the device has been powered2414	 * manually, mark it as active, and increase the usage count without2415	 * resuming the device.2416	 */2417	pm_runtime_set_active(dev);2418	pm_runtime_get_noresume(dev);2419	pm_runtime_enable(dev);2420	pm_runtime_set_autosuspend_delay(dev, 1000);2421	pm_runtime_use_autosuspend(dev);2422 2423	/* Initialize the subdevices. */2424	ret = mt9m114_pa_init(sensor);2425	if (ret < 0)2426		goto error_pm_cleanup;2427 2428	ret = mt9m114_ifp_init(sensor);2429	if (ret < 0)2430		goto error_pa_cleanup;2431 2432	ret = v4l2_async_register_subdev(&sensor->ifp.sd);2433	if (ret < 0)2434		goto error_ifp_cleanup;2435 2436	/*2437	 * Decrease the PM usage count. The device will get suspended after the2438	 * autosuspend delay, turning the power off.2439	 */2440	pm_runtime_mark_last_busy(dev);2441	pm_runtime_put_autosuspend(dev);2442 2443	return 0;2444 2445error_ifp_cleanup:2446	mt9m114_ifp_cleanup(sensor);2447error_pa_cleanup:2448	mt9m114_pa_cleanup(sensor);2449error_pm_cleanup:2450	pm_runtime_disable(dev);2451	pm_runtime_put_noidle(dev);2452error_power_off:2453	mt9m114_power_off(sensor);2454error_ep_free:2455	v4l2_fwnode_endpoint_free(&sensor->bus_cfg);2456	return ret;2457}2458 2459static void mt9m114_remove(struct i2c_client *client)2460{2461	struct v4l2_subdev *sd = i2c_get_clientdata(client);2462	struct mt9m114 *sensor = ifp_to_mt9m114(sd);2463	struct device *dev = &client->dev;2464 2465	v4l2_async_unregister_subdev(&sensor->ifp.sd);2466 2467	mt9m114_ifp_cleanup(sensor);2468	mt9m114_pa_cleanup(sensor);2469	v4l2_fwnode_endpoint_free(&sensor->bus_cfg);2470 2471	/*2472	 * Disable runtime PM. In case runtime PM is disabled in the kernel,2473	 * make sure to turn power off manually.2474	 */2475	pm_runtime_disable(dev);2476	if (!pm_runtime_status_suspended(dev))2477		mt9m114_power_off(sensor);2478	pm_runtime_set_suspended(dev);2479}2480 2481static const struct of_device_id mt9m114_of_ids[] = {2482	{ .compatible = "onnn,mt9m114" },2483	{ /* sentinel */ },2484};2485MODULE_DEVICE_TABLE(of, mt9m114_of_ids);2486 2487static struct i2c_driver mt9m114_driver = {2488	.driver = {2489		.name	= "mt9m114",2490		.pm	= &mt9m114_pm_ops,2491		.of_match_table = mt9m114_of_ids,2492	},2493	.probe		= mt9m114_probe,2494	.remove		= mt9m114_remove,2495};2496 2497module_i2c_driver(mt9m114_driver);2498 2499MODULE_DESCRIPTION("onsemi MT9M114 Sensor Driver");2500MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");2501MODULE_LICENSE("GPL");2502