// SPDX-License-Identifier: GPL-2.0 /* * A V4L2 driver for Sony IMX219 cameras. * Copyright (C) 2019, Raspberry Pi (Trading) Ltd * * Based on Sony imx258 camera driver * Copyright (C) 2018 Intel Corporation * * DT / fwnode changes, and regulator / GPIO control taken from imx214 driver * Copyright 2018 Qtechnology A/S * * Flip handling taken from the Sony IMX319 driver. * Copyright (C) 2018 Intel Corporation * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define IMX219_REG_VALUE_08BIT 1 #define IMX219_REG_VALUE_16BIT 2 #define IMX219_REG_MODE_SELECT 0x0100 #define IMX219_MODE_STANDBY 0x00 #define IMX219_MODE_STREAMING 0x01 /* Chip ID */ #define IMX219_REG_CHIP_ID 0x0000 #define IMX219_CHIP_ID 0x0219 /* External clock frequency is 24.0M */ #define IMX219_XCLK_FREQ 24000000 /* Pixel rate is fixed at 182.4M for all the modes */ #define IMX219_PIXEL_RATE 182400000 #define IMX219_DEFAULT_LINK_FREQ 456000000 /* V_TIMING internal */ #define IMX219_REG_VTS 0x0160 #define IMX219_VTS_15FPS 0x0dc6 #define IMX219_VTS_30FPS_1080P 0x06e3 #define IMX219_VTS_30FPS_BINNED 0x06e3 #define IMX219_VTS_30FPS_640x480 0x06e3 #define IMX219_VTS_MAX 0xffff #define IMX219_VBLANK_MIN 4 /*Frame Length Line*/ #define IMX219_FLL_MIN 0x08a6 #define IMX219_FLL_MAX 0xffff #define IMX219_FLL_STEP 1 #define IMX219_FLL_DEFAULT 0x0c98 /* HBLANK control - read only */ #define IMX219_PPL_DEFAULT 3448 /* Exposure control */ #define IMX219_REG_EXPOSURE 0x015a #define IMX219_EXPOSURE_MIN 4 #define IMX219_EXPOSURE_STEP 1 #define IMX219_EXPOSURE_DEFAULT 0x640 #define IMX219_EXPOSURE_MAX 65535 /* Analog gain control */ #define IMX219_REG_ANALOG_GAIN 0x0157 #define IMX219_ANA_GAIN_MIN 0 #define IMX219_ANA_GAIN_MAX 232 #define IMX219_ANA_GAIN_STEP 1 #define IMX219_ANA_GAIN_DEFAULT 0x0 /* Digital gain control */ #define IMX219_REG_DIGITAL_GAIN 0x0158 #define IMX219_DGTL_GAIN_MIN 0x0100 #define IMX219_DGTL_GAIN_MAX 0x0fff #define IMX219_DGTL_GAIN_DEFAULT 0x0100 #define IMX219_DGTL_GAIN_STEP 1 #define IMX219_REG_ORIENTATION 0x0172 /* Binning Mode */ #define IMX219_REG_BINNING_MODE 0x0174 #define IMX219_BINNING_NONE 0x0000 #define IMX219_BINNING_2X2 0x0101 #define IMX219_BINNING_2X2_ANALOG 0x0303 /* Test Pattern Control */ #define IMX219_REG_TEST_PATTERN 0x0600 #define IMX219_TEST_PATTERN_DISABLE 0 #define IMX219_TEST_PATTERN_SOLID_COLOR 1 #define IMX219_TEST_PATTERN_COLOR_BARS 2 #define IMX219_TEST_PATTERN_GREY_COLOR 3 #define IMX219_TEST_PATTERN_PN9 4 /* Test pattern colour components */ #define IMX219_REG_TESTP_RED 0x0602 #define IMX219_REG_TESTP_GREENR 0x0604 #define IMX219_REG_TESTP_BLUE 0x0606 #define IMX219_REG_TESTP_GREENB 0x0608 #define IMX219_TESTP_COLOUR_MIN 0 #define IMX219_TESTP_COLOUR_MAX 0x03ff #define IMX219_TESTP_COLOUR_STEP 1 #define IMX219_TESTP_RED_DEFAULT IMX219_TESTP_COLOUR_MAX #define IMX219_TESTP_GREENR_DEFAULT 0 #define IMX219_TESTP_BLUE_DEFAULT 0 #define IMX219_TESTP_GREENB_DEFAULT 0 /* IMX219 native and active pixel array size. */ #define IMX219_NATIVE_WIDTH 3296U #define IMX219_NATIVE_HEIGHT 2480U #define IMX219_PIXEL_ARRAY_LEFT 8U #define IMX219_PIXEL_ARRAY_TOP 8U #define IMX219_PIXEL_ARRAY_WIDTH 3280U #define IMX219_PIXEL_ARRAY_HEIGHT 2464U struct imx219_reg { u16 address; u8 val; }; struct imx219_reg_list { unsigned int num_of_regs; const struct imx219_reg *regs; }; /* Mode : resolution and related config&values */ struct imx219_mode { /* Frame width */ unsigned int width; /* Frame height */ unsigned int height; /* Analog crop rectangle. */ struct v4l2_rect crop; /* V-timing */ unsigned int vts_def; /* Default register values */ struct imx219_reg_list reg_list; /* 2x2 binning is used */ bool binning; }; static const struct imx219_reg imx219_common_regs[] = { {0x0100, 0x00}, /* Mode Select */ /* To Access Addresses 3000-5fff, send the following commands */ {0x30eb, 0x0c}, {0x30eb, 0x05}, {0x300a, 0xff}, {0x300b, 0xff}, {0x30eb, 0x05}, {0x30eb, 0x09}, /* PLL Clock Table */ {0x0301, 0x05}, /* VTPXCK_DIV */ {0x0303, 0x01}, /* VTSYSCK_DIV */ {0x0304, 0x03}, /* PREPLLCK_VT_DIV 0x03 = AUTO set */ {0x0305, 0x03}, /* PREPLLCK_OP_DIV 0x03 = AUTO set */ {0x0306, 0x00}, /* PLL_VT_MPY */ {0x0307, 0x39}, {0x030b, 0x01}, /* OP_SYS_CLK_DIV */ {0x030c, 0x00}, /* PLL_OP_MPY */ {0x030d, 0x72}, /* Undocumented registers */ {0x455e, 0x00}, {0x471e, 0x4b}, {0x4767, 0x0f}, {0x4750, 0x14}, {0x4540, 0x00}, {0x47b4, 0x14}, {0x4713, 0x30}, {0x478b, 0x10}, {0x478f, 0x10}, {0x4793, 0x10}, {0x4797, 0x0e}, {0x479b, 0x0e}, /* Frame Bank Register Group "A" */ {0x0162, 0x0d}, /* Line_Length_A */ {0x0163, 0x78}, {0x0170, 0x01}, /* X_ODD_INC_A */ {0x0171, 0x01}, /* Y_ODD_INC_A */ /* Output setup registers */ {0x0114, 0x01}, /* CSI 2-Lane Mode */ {0x0128, 0x00}, /* DPHY Auto Mode */ {0x012a, 0x18}, /* EXCK_Freq */ {0x012b, 0x00}, }; /* * Register sets lifted off the i2C interface from the Raspberry Pi firmware * driver. * 3280x2464 = mode 2, 1920x1080 = mode 1, 1640x1232 = mode 4, 640x480 = mode 7. */ static const struct imx219_reg mode_3280x2464_regs[] = { {0x0164, 0x00}, {0x0165, 0x00}, {0x0166, 0x0c}, {0x0167, 0xcf}, {0x0168, 0x00}, {0x0169, 0x00}, {0x016a, 0x09}, {0x016b, 0x9f}, {0x016c, 0x0c}, {0x016d, 0xd0}, {0x016e, 0x09}, {0x016f, 0xa0}, {0x0624, 0x0c}, {0x0625, 0xd0}, {0x0626, 0x09}, {0x0627, 0xa0}, }; static const struct imx219_reg mode_1920_1080_regs[] = { {0x0164, 0x02}, {0x0165, 0xa8}, {0x0166, 0x0a}, {0x0167, 0x27}, {0x0168, 0x02}, {0x0169, 0xb4}, {0x016a, 0x06}, {0x016b, 0xeb}, {0x016c, 0x07}, {0x016d, 0x80}, {0x016e, 0x04}, {0x016f, 0x38}, {0x0624, 0x07}, {0x0625, 0x80}, {0x0626, 0x04}, {0x0627, 0x38}, }; static const struct imx219_reg mode_1640_1232_regs[] = { {0x0164, 0x00}, {0x0165, 0x00}, {0x0166, 0x0c}, {0x0167, 0xcf}, {0x0168, 0x00}, {0x0169, 0x00}, {0x016a, 0x09}, {0x016b, 0x9f}, {0x016c, 0x06}, {0x016d, 0x68}, {0x016e, 0x04}, {0x016f, 0xd0}, {0x0624, 0x06}, {0x0625, 0x68}, {0x0626, 0x04}, {0x0627, 0xd0}, }; static const struct imx219_reg mode_640_480_regs[] = { {0x0164, 0x03}, {0x0165, 0xe8}, {0x0166, 0x08}, {0x0167, 0xe7}, {0x0168, 0x02}, {0x0169, 0xf0}, {0x016a, 0x06}, {0x016b, 0xaf}, {0x016c, 0x02}, {0x016d, 0x80}, {0x016e, 0x01}, {0x016f, 0xe0}, {0x0624, 0x06}, {0x0625, 0x68}, {0x0626, 0x04}, {0x0627, 0xd0}, }; static const struct imx219_reg raw8_framefmt_regs[] = { {0x018c, 0x08}, {0x018d, 0x08}, {0x0309, 0x08}, }; static const struct imx219_reg raw10_framefmt_regs[] = { {0x018c, 0x0a}, {0x018d, 0x0a}, {0x0309, 0x0a}, }; static const char * const imx219_test_pattern_menu[] = { "Disabled", "Color Bars", "Solid Color", "Grey Color Bars", "PN9" }; static const int imx219_test_pattern_val[] = { IMX219_TEST_PATTERN_DISABLE, IMX219_TEST_PATTERN_COLOR_BARS, IMX219_TEST_PATTERN_SOLID_COLOR, IMX219_TEST_PATTERN_GREY_COLOR, IMX219_TEST_PATTERN_PN9, }; /* regulator supplies */ static const char * const imx219_supply_name[] = { /* Supplies can be enabled in any order */ "VANA", /* Analog (2.8V) supply */ "VDIG", /* Digital Core (1.8V) supply */ "VDDL", /* IF (1.2V) supply */ }; #define IMX219_NUM_SUPPLIES ARRAY_SIZE(imx219_supply_name) /* * The supported formats. * This table MUST contain 4 entries per format, to cover the various flip * combinations in the order * - no flip * - h flip * - v flip * - h&v flips */ static const u32 codes[] = { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8, }; /* * Initialisation delay between XCLR low->high and the moment when the sensor * can start capture (i.e. can leave software stanby) must be not less than: * t4 + max(t5, t6 +