// 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 /* Chip ID */ #define IMX219_REG_CHIP_ID CCI_REG16(0x0000) #define IMX219_CHIP_ID 0x0219 #define IMX219_REG_MODE_SELECT CCI_REG8(0x0100) #define IMX219_MODE_STANDBY 0x00 #define IMX219_MODE_STREAMING 0x01 #define IMX219_REG_CSI_LANE_MODE CCI_REG8(0x0114) #define IMX219_CSI_2_LANE_MODE 0x01 #define IMX219_CSI_4_LANE_MODE 0x03 #define IMX219_REG_DPHY_CTRL CCI_REG8(0x0128) #define IMX219_DPHY_CTRL_TIMING_AUTO 0 #define IMX219_DPHY_CTRL_TIMING_MANUAL 1 #define IMX219_REG_EXCK_FREQ CCI_REG16(0x012a) #define IMX219_EXCK_FREQ(n) ((n) * 256) /* n expressed in MHz */ /* Analog gain control */ #define IMX219_REG_ANALOG_GAIN CCI_REG8(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 CCI_REG16(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 /* Exposure control */ #define IMX219_REG_EXPOSURE CCI_REG16(0x015a) #define IMX219_EXPOSURE_MIN 4 #define IMX219_EXPOSURE_STEP 1 #define IMX219_EXPOSURE_DEFAULT 0x640 #define IMX219_EXPOSURE_MAX 65535 /* V_TIMING internal */ #define IMX219_REG_VTS CCI_REG16(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 #define IMX219_REG_LINE_LENGTH_A CCI_REG16(0x0162) #define IMX219_REG_X_ADD_STA_A CCI_REG16(0x0164) #define IMX219_REG_X_ADD_END_A CCI_REG16(0x0166) #define IMX219_REG_Y_ADD_STA_A CCI_REG16(0x0168) #define IMX219_REG_Y_ADD_END_A CCI_REG16(0x016a) #define IMX219_REG_X_OUTPUT_SIZE CCI_REG16(0x016c) #define IMX219_REG_Y_OUTPUT_SIZE CCI_REG16(0x016e) #define IMX219_REG_X_ODD_INC_A CCI_REG8(0x0170) #define IMX219_REG_Y_ODD_INC_A CCI_REG8(0x0171) #define IMX219_REG_ORIENTATION CCI_REG8(0x0172) /* Binning Mode */ #define IMX219_REG_BINNING_MODE CCI_REG16(0x0174) #define IMX219_BINNING_NONE 0x0000 #define IMX219_BINNING_2X2 0x0101 #define IMX219_BINNING_2X2_ANALOG 0x0303 #define IMX219_REG_CSI_DATA_FORMAT_A CCI_REG16(0x018c) /* PLL Settings */ #define IMX219_REG_VTPXCK_DIV CCI_REG8(0x0301) #define IMX219_REG_VTSYCK_DIV CCI_REG8(0x0303) #define IMX219_REG_PREPLLCK_VT_DIV CCI_REG8(0x0304) #define IMX219_REG_PREPLLCK_OP_DIV CCI_REG8(0x0305) #define IMX219_REG_PLL_VT_MPY CCI_REG16(0x0306) #define IMX219_REG_OPPXCK_DIV CCI_REG8(0x0309) #define IMX219_REG_OPSYCK_DIV CCI_REG8(0x030b) #define IMX219_REG_PLL_OP_MPY CCI_REG16(0x030c) /* Test Pattern Control */ #define IMX219_REG_TEST_PATTERN CCI_REG16(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 CCI_REG16(0x0602) #define IMX219_REG_TESTP_GREENR CCI_REG16(0x0604) #define IMX219_REG_TESTP_BLUE CCI_REG16(0x0606) #define IMX219_REG_TESTP_GREENB CCI_REG16(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 #define IMX219_REG_TP_WINDOW_WIDTH CCI_REG16(0x0624) #define IMX219_REG_TP_WINDOW_HEIGHT CCI_REG16(0x0626) /* External clock frequency is 24.0M */ #define IMX219_XCLK_FREQ 24000000 /* Pixel rate is fixed for all the modes */ #define IMX219_PIXEL_RATE 182400000 #define IMX219_PIXEL_RATE_4LANE 280800000 #define IMX219_DEFAULT_LINK_FREQ 456000000 #define IMX219_DEFAULT_LINK_FREQ_4LANE 363000000 /* 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_list { unsigned int num_of_regs; const struct cci_reg_sequence *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 cci_reg_sequence imx219_common_regs[] = { { IMX219_REG_MODE_SELECT, 0x00 }, /* Mode Select */ /* To Access Addresses 3000-5fff, send the following commands */ { CCI_REG8(0x30eb), 0x0c }, { CCI_REG8(0x30eb), 0x05 }, { CCI_REG8(0x300a), 0xff }, { CCI_REG8(0x300b), 0xff }, { CCI_REG8(0x30eb), 0x05 }, { CCI_REG8(0x30eb), 0x09 }, /* PLL Clock Table */ { IMX219_REG_VTPXCK_DIV, 5 }, { IMX219_REG_VTSYCK_DIV, 1 }, { IMX219_REG_PREPLLCK_VT_DIV, 3 }, /* 0x03 = AUTO set */ { IMX219_REG_PREPLLCK_OP_DIV, 3 }, /* 0x03 = AUTO set */ { IMX219_REG_PLL_VT_MPY, 57 }, { IMX219_REG_OPSYCK_DIV, 1 }, { IMX219_REG_PLL_OP_MPY, 114 }, /* Undocumented registers */ { CCI_REG8(0x455e), 0x00 }, { CCI_REG8(0x471e), 0x4b }, { CCI_REG8(0x4767), 0x0f }, { CCI_REG8(0x4750), 0x14 }, { CCI_REG8(0x4540), 0x00 }, { CCI_REG8(0x47b4), 0x14 }, { CCI_REG8(0x4713), 0x30 }, { CCI_REG8(0x478b), 0x10 }, { CCI_REG8(0x478f), 0x10 }, { CCI_REG8(0x4793), 0x10 }, { CCI_REG8(0x4797), 0x0e }, { CCI_REG8(0x479b), 0x0e }, /* Frame Bank Register Group "A" */ { IMX219_REG_LINE_LENGTH_A, 3448 }, { IMX219_REG_X_ODD_INC_A, 1 }, { IMX219_REG_Y_ODD_INC_A, 1 }, /* Output setup registers */ { IMX219_REG_DPHY_CTRL, IMX219_DPHY_CTRL_TIMING_AUTO }, { IMX219_REG_EXCK_FREQ, IMX219_EXCK_FREQ(IMX219_XCLK_FREQ / 1000000) }, }; /* * 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 cci_reg_sequence mode_3280x2464_regs[] = { { IMX219_REG_X_ADD_STA_A, 0 }, { IMX219_REG_X_ADD_END_A, 3279 }, { IMX219_REG_Y_ADD_STA_A, 0 }, { IMX219_REG_Y_ADD_END_A, 2463 }, { IMX219_REG_X_OUTPUT_SIZE, 3280 }, { IMX219_REG_Y_OUTPUT_SIZE, 2464 }, { IMX219_REG_TP_WINDOW_WIDTH, 3280 }, { IMX219_REG_TP_WINDOW_HEIGHT, 2464 }, }; static const struct cci_reg_sequence mode_1920_1080_regs[] = { { IMX219_REG_X_ADD_STA_A, 680 }, { IMX219_REG_X_ADD_END_A, 2599 }, { IMX219_REG_Y_ADD_STA_A, 692 }, { IMX219_REG_Y_ADD_END_A, 1771 }, { IMX219_REG_X_OUTPUT_SIZE, 1920 }, { IMX219_REG_Y_OUTPUT_SIZE, 1080 }, { IMX219_REG_TP_WINDOW_WIDTH, 1920 }, { IMX219_REG_TP_WINDOW_HEIGHT, 1080 }, }; static const struct cci_reg_sequence mode_1640_1232_regs[] = { { IMX219_REG_X_ADD_STA_A, 0 }, { IMX219_REG_X_ADD_END_A, 3279 }, { IMX219_REG_Y_ADD_STA_A, 0 }, { IMX219_REG_Y_ADD_END_A, 2463 }, { IMX219_REG_X_OUTPUT_SIZE, 1640 }, { IMX219_REG_Y_OUTPUT_SIZE, 1232 }, { IMX219_REG_TP_WINDOW_WIDTH, 1640 }, { IMX219_REG_TP_WINDOW_HEIGHT, 1232 }, }; static const struct cci_reg_sequence mode_640_480_regs[] = { { IMX219_REG_X_ADD_STA_A, 1000 }, { IMX219_REG_X_ADD_END_A, 2279 }, { IMX219_REG_Y_ADD_STA_A, 752 }, { IMX219_REG_Y_ADD_END_A, 1711 }, { IMX219_REG_X_OUTPUT_SIZE, 640 }, { IMX219_REG_Y_OUTPUT_SIZE, 480 }, { IMX219_REG_TP_WINDOW_WIDTH, 1640 }, { IMX219_REG_TP_WINDOW_HEIGHT, 1232 }, }; static const struct cci_reg_sequence raw8_framefmt_regs[] = { { IMX219_REG_CSI_DATA_FORMAT_A, 0x0808 }, { IMX219_REG_OPPXCK_DIV, 8 }, }; static const struct cci_reg_sequence raw10_framefmt_regs[] = { { IMX219_REG_CSI_DATA_FORMAT_A, 0x0a0a }, { IMX219_REG_OPPXCK_DIV, 10 }, }; static const s64 imx219_link_freq_menu[] = { IMX219_DEFAULT_LINK_FREQ, }; static const s64 imx219_link_freq_4lane_menu[] = { IMX219_DEFAULT_LINK_FREQ_4LANE, }; 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 imx219_mbus_formats[] = { 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 +