linux/drivers/media/i2c/gc0308.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Driver for the GalaxyCore GC0308 camera sensor.
 *
 * Copyright (c) 2023 Sebastian Reichel <[email protected]>
 */

#include <linux/clk.h>
#include <linux/device.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>

#include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>

/* Analog & CISCTL*/
#define GC0308_CHIP_ID
#define GC0308_HBLANK
#define GC0308_VBLANK
#define GC0308_EXP
#define GC0308_ROW_START
#define GC0308_COL_START
#define GC0308_WIN_HEIGHT
#define GC0308_WIN_WIDTH
#define GC0308_VS_START_TIME
#define GC0308_VS_END_TIME
#define GC0308_VB_HB
#define GC0308_RSH_WIDTH
#define GC0308_TSP_WIDTH
#define GC0308_SAMPLE_HOLD_DELAY
#define GC0308_ROW_TAIL_WIDTH
#define GC0308_CISCTL_MODE1
#define GC0308_CISCTL_MODE2
#define GC0308_CISCTL_MODE3
#define GC0308_CISCTL_MODE4
#define GC0308_ANALOG_MODE1
#define GC0308_ANALOG_MODE2
#define GC0308_HRST_RSG_V18
#define GC0308_VREF_V25
#define GC0308_ADC_R
#define GC0308_PAD_DRV
#define GC0308_SOFT_RESET

/* ISP */
#define GC0308_BLOCK_EN1
#define GC0308_BLOCK_EN2
#define GC0308_AAAA_EN
#define GC0308_SPECIAL_EFFECT
#define GC0308_OUT_FORMAT
#define GC0308_OUT_EN
#define GC0308_SYNC_MODE
#define GC0308_CLK_DIV_MODE
#define GC0308_BYPASS_MODE
#define GC0308_CLK_GATING
#define GC0308_DITHER_MODE
#define GC0308_DITHER_BIT
#define GC0308_DEBUG_MODE1
#define GC0308_DEBUG_MODE2
#define GC0308_DEBUG_MODE3
#define GC0308_CROP_WIN_MODE
#define GC0308_CROP_WIN_Y1
#define GC0308_CROP_WIN_X1
#define GC0308_CROP_WIN_HEIGHT
#define GC0308_CROP_WIN_WIDTH

/* BLK */
#define GC0308_BLK_MODE
#define GC0308_BLK_LIMIT_VAL
#define GC0308_GLOBAL_OFF
#define GC0308_CURRENT_R_OFF
#define GC0308_CURRENT_G_OFF
#define GC0308_CURRENT_B_OFF
#define GC0308_CURRENT_R_DARK_CURRENT
#define GC0308_CURRENT_G_DARK_CURRENT
#define GC0308_CURRENT_B_DARK_CURRENT
#define GC0308_EXP_RATE_DARKC
#define GC0308_OFF_SUBMODE
#define GC0308_DARKC_SUBMODE
#define GC0308_MANUAL_G1_OFF
#define GC0308_MANUAL_R1_OFF
#define GC0308_MANUAL_B2_OFF
#define GC0308_MANUAL_G2_OFF

/* PREGAIN */
#define GC0308_GLOBAL_GAIN
#define GC0308_AUTO_PREGAIN
#define GC0308_AUTO_POSTGAIN
#define GC0308_CHANNEL_GAIN_G1
#define GC0308_CHANNEL_GAIN_R
#define GC0308_CHANNEL_GAIN_B
#define GC0308_CHANNEL_GAIN_G2
#define GC0308_R_RATIO
#define GC0308_G_RATIO
#define GC0308_B_RATIO
#define GC0308_AWB_R_GAIN
#define GC0308_AWB_G_GAIN
#define GC0308_AWB_B_GAIN
#define GC0308_LSC_DEC_LVL1
#define GC0308_LSC_DEC_LVL2
#define GC0308_LSC_DEC_LVL3

/* DNDD */
#define GC0308_DN_MODE_EN
#define GC0308_DN_MODE_RATIO
#define GC0308_DN_BILAT_B_BASE
#define GC0308_DN_B_INCR
#define GC0308_DN_BILAT_N_BASE
#define GC0308_DN_N_INCR
#define GC0308_DD_DARK_BRIGHT_TH
#define GC0308_DD_FLAT_TH
#define GC0308_DD_LIMIT

/* ASDE - Auto Saturation De-noise and Edge-Enhancement */
#define GC0308_ASDE_GAIN_TRESH
#define GC0308_ASDE_GAIN_MODE
#define GC0308_ASDE_DN_SLOPE
#define GC0308_ASDE_DD_BRIGHT
#define GC0308_ASDE_DD_LIMIT
#define GC0308_ASDE_AUTO_EE1
#define GC0308_ASDE_AUTO_EE2
#define GC0308_ASDE_AUTO_SAT_DEC_SLOPE
#define GC0308_ASDE_AUTO_SAT_LOW_LIMIT

/* INTPEE - Interpolation and Edge-Enhancement */
#define GC0308_EEINTP_MODE_1
#define GC0308_EEINTP_MODE_2
#define GC0308_DIRECTION_TH1
#define GC0308_DIRECTION_TH2
#define GC0308_DIFF_HV_TI_TH
#define GC0308_EDGE12_EFFECT
#define GC0308_EDGE_POS_RATIO
#define GC0308_EDGE1_MINMAX
#define GC0308_EDGE2_MINMAX
#define GC0308_EDGE12_TH
#define GC0308_EDGE_MAX

/* ABB - Auto Black Balance */
#define GC0308_ABB_MODE
#define GC0308_ABB_TARGET_AVGH
#define GC0308_ABB_TARGET_AVGL
#define GC0308_ABB_LIMIT_VAL
#define GC0308_ABB_SPEED
#define GC0308_CURR_R_BLACK_LVL
#define GC0308_CURR_G_BLACK_LVL
#define GC0308_CURR_B_BLACK_LVL
#define GC0308_CURR_R_BLACK_FACTOR
#define GC0308_CURR_G_BLACK_FACTOR
#define GC0308_CURR_B_BLACK_FACTOR

/* LSC - Lens Shading Correction */
#define GC0308_LSC_RED_B2
#define GC0308_LSC_GREEN_B2
#define GC0308_LSC_BLUE_B2
#define GC0308_LSC_RED_B4
#define GC0308_LSC_GREEN_B4
#define GC0308_LSC_BLUE_B4
#define GC0308_LSC_ROW_CENTER
#define GC0308_LSC_COL_CENTER

/* CC - Channel Coefficient */
#define GC0308_CC_MATRIX_C11
#define GC0308_CC_MATRIX_C12
#define GC0308_CC_MATRIX_C13
#define GC0308_CC_MATRIX_C21
#define GC0308_CC_MATRIX_C22
#define GC0308_CC_MATRIX_C23
#define GC0308_CC_MATRIX_C41
#define GC0308_CC_MATRIX_C42
#define GC0308_CC_MATRIX_C43

/* GAMMA */
#define GC0308_GAMMA_OUT0
#define GC0308_GAMMA_OUT1
#define GC0308_GAMMA_OUT2
#define GC0308_GAMMA_OUT3
#define GC0308_GAMMA_OUT4
#define GC0308_GAMMA_OUT5
#define GC0308_GAMMA_OUT6
#define GC0308_GAMMA_OUT7
#define GC0308_GAMMA_OUT8
#define GC0308_GAMMA_OUT9
#define GC0308_GAMMA_OUT10
#define GC0308_GAMMA_OUT11
#define GC0308_GAMMA_OUT12
#define GC0308_GAMMA_OUT13
#define GC0308_GAMMA_OUT14
#define GC0308_GAMMA_OUT15
#define GC0308_GAMMA_OUT16

/* YCP */
#define GC0308_GLOBAL_SATURATION
#define GC0308_SATURATION_CB
#define GC0308_SATURATION_CR
#define GC0308_LUMA_CONTRAST
#define GC0308_CONTRAST_CENTER
#define GC0308_LUMA_OFFSET
#define GC0308_SKIN_CB_CENTER
#define GC0308_SKIN_CR_CENTER
#define GC0308_SKIN_RADIUS_SQUARE
#define GC0308_SKIN_BRIGHTNESS
#define GC0308_FIXED_CB
#define GC0308_FIXED_CR
#define GC0308_EDGE_DEC_SA
#define GC0308_AUTO_GRAY_MODE
#define GC0308_SATURATION_SUB_STRENGTH
#define GC0308_Y_GAMMA_OUT0
#define GC0308_Y_GAMMA_OUT1
#define GC0308_Y_GAMMA_OUT2
#define GC0308_Y_GAMMA_OUT3
#define GC0308_Y_GAMMA_OUT4
#define GC0308_Y_GAMMA_OUT5
#define GC0308_Y_GAMMA_OUT6
#define GC0308_Y_GAMMA_OUT7
#define GC0308_Y_GAMMA_OUT8
#define GC0308_Y_GAMMA_OUT9
#define GC0308_Y_GAMMA_OUT10
#define GC0308_Y_GAMMA_OUT11
#define GC0308_Y_GAMMA_OUT12

/* AEC - Automatic Exposure Control */
#define GC0308_AEC_MODE1
#define GC0308_AEC_MODE2
#define GC0308_AEC_MODE3
#define GC0308_AEC_TARGET_Y
#define GC0308_Y_AVG
#define GC0308_AEC_HIGH_LOW_RANGE
#define GC0308_AEC_IGNORE
#define GC0308_AEC_LIMIT_HIGH_RANGE
#define GC0308_AEC_R_OFFSET
#define GC0308_AEC_GB_OFFSET
#define GC0308_AEC_SLOW_MARGIN
#define GC0308_AEC_FAST_MARGIN
#define GC0308_AEC_EXP_CHANGE_GAIN
#define GC0308_AEC_STEP2_SUNLIGHT
#define GC0308_AEC_I_FRAMES
#define GC0308_AEC_I_STOP_L_MARGIN
#define GC0308_AEC_I_STOP_MARGIN
#define GC0308_ANTI_FLICKER_STEP
#define GC0308_EXP_LVL_1
#define GC0308_EXP_LVL_2
#define GC0308_EXP_LVL_3
#define GC0308_EXP_LVL_4
#define GC0308_MAX_EXP_LVL
#define GC0308_EXP_MIN_L
#define GC0308_MAX_POST_DF_GAIN
#define GC0308_MAX_PRE_DG_GAIN

/* ABS */
#define GC0308_ABS_RANGE_COMP
#define GC0308_ABS_STOP_MARGIN
#define GC0308_Y_S_COMP
#define GC0308_Y_STRETCH_LIMIT
#define GC0308_Y_TILT
#define GC0308_Y_STRETCH

/* Measure Window */
#define GC0308_BIG_WIN_X0
#define GC0308_BIG_WIN_Y0
#define GC0308_BIG_WIN_X1
#define GC0308_BIG_WIN_Y1
#define GC0308_DIFF_Y_BIG_THD

/* OUT Module (P1) */
#define GC0308_CLOSE_FRAME_EN
#define GC0308_CLOSE_FRAME_NUM1
#define GC0308_CLOSE_FRAME_NUM2
#define GC0308_BAYER_MODE
#define GC0308_SUBSAMPLE
#define GC0308_SUBMODE
#define GC0308_SUB_ROW_N1
#define GC0308_SUB_ROW_N2
#define GC0308_SUB_COL_N1
#define GC0308_SUB_COL_N2

/* AWB (P1) - Auto White Balance */
#define GC0308_AWB_RGB_HIGH_LOW
#define GC0308_AWB_Y_TO_C_DIFF2
#define GC0308_AWB_C_MAX
#define GC0308_AWB_C_INTER
#define GC0308_AWB_C_INTER2
#define GC0308_AWB_C_MAX_BIG
#define GC0308_AWB_Y_HIGH
#define GC0308_AWB_NUMBER_LIMIT
#define GC0308_KWIN_RATIO
#define GC0308_KWIN_THD
#define GC0308_LIGHT_GAIN_RANGE
#define GC0308_SMALL_WIN_WIDTH_STEP
#define GC0308_SMALL_WIN_HEIGHT_STEP
#define GC0308_AWB_YELLOW_TH
#define GC0308_AWB_MODE
#define GC0308_AWB_ADJUST_SPEED
#define GC0308_AWB_EVERY_N
#define GC0308_R_AVG_USE
#define GC0308_G_AVG_USE
#define GC0308_B_AVG_USE

#define GC0308_HBLANK_MIN
#define GC0308_HBLANK_MAX
#define GC0308_HBLANK_DEF

#define GC0308_VBLANK_MIN
#define GC0308_VBLANK_MAX
#define GC0308_VBLANK_DEF

#define GC0308_PIXEL_RATE

/*
 * frame_time = (BT + height + 8) * row_time
 * width = 640 (driver does not change window size)
 * height = 480 (driver does not change window size)
 * row_time = HBLANK + SAMPLE_HOLD_DELAY + width + 8 + 4
 *
 * When EXP_TIME > (BT + height):
 *     BT = EXP_TIME - height - 8 - VS_START_TIME + VS_END_TIME
 * else:
 *     BT = VBLANK + VS_START_TIME + VS_END_TIME
 *
 * max is 30 FPS
 *
 * In my tests frame rate mostly depends on exposure time. Unfortuantely
 * it's unclear how this is calculated exactly. Also since we enable AEC,
 * the frame times vary depending on ambient light conditions.
 */
#define GC0308_FRAME_RATE_MAX

enum gc0308_exp_val {};

static const s64 gc0308_exposure_menu[] =;

struct gc0308_exposure {};

#define GC0308_EXPOSURE(luma_offset_reg, aec_target_y_reg)

static const struct gc0308_exposure gc0308_exposure_values[] =;

struct gc0308_awb_gains {};

#define GC0308_AWB_GAINS(red, green, blue)

static const struct gc0308_awb_gains gc0308_awb_gains[] =;

struct gc0308_format {};

#define GC0308_FORMAT(v4l2_code, gc0308_regval)

static const struct gc0308_format gc0308_formats[] =;

struct gc0308_frame_size {};

#define GC0308_FRAME_SIZE(s, w, h)

static const struct gc0308_frame_size gc0308_frame_sizes[] =;

struct gc0308_mode_registers {};

struct gc0308 {};

static inline struct gc0308 *to_gc0308(struct v4l2_subdev *sd)
{}

static const struct regmap_range_cfg gc0308_ranges[] =;

static const struct regmap_config gc0308_regmap_config =;

static const struct cci_reg_sequence sensor_default_regs[] =;

struct gc0308_colormode {};

#define GC0308_COLOR_FX(reg_special_effect, reg_dbg_mode1, reg_block_en1, \
			reg_aec_mode3, reg_eeintp_mode_2, reg_edge12_effect, \
			reg_luma_contrast, reg_contrast_center, \
			reg_fixed_cb, reg_fixed_cr)

static const struct gc0308_colormode gc0308_colormodes[] =;

static int gc0308_power_on(struct device *dev)
{}

static int gc0308_power_off(struct device *dev)
{}

#ifdef CONFIG_VIDEO_ADV_DEBUG
static int gc0308_g_register(struct v4l2_subdev *sd,
			     struct v4l2_dbg_register *reg)
{}

static int gc0308_s_register(struct v4l2_subdev *sd,
			     const struct v4l2_dbg_register *reg)
{}
#endif

static int gc0308_set_exposure(struct gc0308 *gc0308, enum gc0308_exp_val exp)
{}

static int gc0308_set_awb_mode(struct gc0308 *gc0308,
			       enum v4l2_auto_n_preset_white_balance val)
{}

static int gc0308_set_colormode(struct gc0308 *gc0308, enum v4l2_colorfx mode)
{}

static int gc0308_set_power_line_freq(struct gc0308 *gc0308, int frequency)
{}

static int gc0308_update_mirror(struct gc0308 *gc0308)
{}

static int gc0308_update_blanking(struct gc0308 *gc0308)
{}

static int _gc0308_s_ctrl(struct v4l2_ctrl *ctrl)
{}

static int gc0308_s_ctrl(struct v4l2_ctrl *ctrl)
{}

static const struct v4l2_ctrl_ops gc0308_ctrl_ops =;

static const struct v4l2_subdev_core_ops gc0308_core_ops =;

static int gc0308_enum_mbus_code(struct v4l2_subdev *sd,
				 struct v4l2_subdev_state *sd_state,
				 struct v4l2_subdev_mbus_code_enum *code)
{}

static int gc0308_get_format_idx(u32 code)
{}

static int gc0308_enum_frame_size(struct v4l2_subdev *subdev,
				  struct v4l2_subdev_state *sd_state,
				  struct v4l2_subdev_frame_size_enum *fse)
{}

static void gc0308_update_pad_format(const struct gc0308_frame_size *mode,
				     struct v4l2_mbus_framefmt *fmt, u32 code)
{}

static int gc0308_set_format(struct v4l2_subdev *sd,
			     struct v4l2_subdev_state *sd_state,
			     struct v4l2_subdev_format *fmt)
{}

static int gc0308_init_state(struct v4l2_subdev *sd,
			     struct v4l2_subdev_state *sd_state)
{}

static const struct v4l2_subdev_pad_ops gc0308_pad_ops =;

static int gc0308_set_resolution(struct gc0308 *gc0308, int *ret)
{}

static int gc0308_start_stream(struct gc0308 *gc0308)
{}

static int gc0308_stop_stream(struct gc0308 *gc0308)
{}

static int gc0308_s_stream(struct v4l2_subdev *sd, int enable)
{}

static const struct v4l2_subdev_video_ops gc0308_video_ops =;

static const struct v4l2_subdev_ops gc0308_subdev_ops =;

static const struct v4l2_subdev_internal_ops gc0308_internal_ops =;

static int gc0308_bus_config(struct gc0308 *gc0308)
{}

static const char * const gc0308_test_pattern_menu[] =;

static int gc0308_init_controls(struct gc0308 *gc0308)
{}

static int gc0308_probe(struct i2c_client *client)
{}

static void gc0308_remove(struct i2c_client *client)
{}

static const struct dev_pm_ops gc0308_pm_ops =;

static const struct of_device_id gc0308_of_match[] =;
MODULE_DEVICE_TABLE(of, gc0308_of_match);

static struct i2c_driver gc0308_i2c_driver =;
module_i2c_driver();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();