blob: 7ba15c885d28610fb1f3ac2d320c743223ebf16b [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2020 Bitland Inc.
// Copyright 2020 Google LLC.
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <media/media-entity.h>
#include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
/* External clock frequency supported by the driver */
#define GC5035_MCLK_RATE 24000000UL
/* Number of lanes supported by this driver */
#define GC5035_DATA_LANES 2
/* Bits per sample of sensor output */
#define GC5035_BITS_PER_SAMPLE 10
/* System registers (accessible regardless of the page. */
/* Chip ID */
#define GC5035_REG_CHIP_ID_H 0xf0
#define GC5035_REG_CHIP_ID_L 0xf1
#define GC5035_CHIP_ID 0x5035
#define GC5035_ID(_msb, _lsb) ((_msb) << 8 | (_lsb))
/* Register page selection register */
#define GC5035_PAGE_REG 0xfe
/* Page 0 registers */
/* Exposure control */
#define GC5035_REG_EXPOSURE_H 0x03
#define GC5035_REG_EXPOSURE_L 0x04
#define GC5035_EXPOSURE_H_MASK 0x3f
#define GC5035_EXPOSURE_MIN 4
#define GC5035_EXPOSURE_STEP 4
/* Analog gain control */
#define GC5035_REG_ANALOG_GAIN 0xb6
#define GC5035_ANALOG_GAIN_MIN 0
#define GC5035_ANALOG_GAIN_MAX 31
#define GC5035_ANALOG_GAIN_STEP 1
#define GC5035_ANALOG_GAIN_DEFAULT GC5035_ANALOG_GAIN_MIN
/* Digital gain control */
#define GC5035_REG_DIGI_GAIN_H 0xb1
#define GC5035_REG_DIGI_GAIN_L 0xb2
#define GC5035_DGAIN_H_MASK 0x0f
#define GC5035_DGAIN_L_MASK 0xfc
#define GC5035_DGAIN_L_SHIFT 2
#define GC5035_DIGI_GAIN_MIN 0
#define GC5035_DIGI_GAIN_MAX 1023
#define GC5035_DIGI_GAIN_STEP 1
#define GC5035_DIGI_GAIN_DEFAULT GC5035_DIGI_GAIN_MAX
/* Vblank control */
#define GC5035_REG_VTS_H 0x41
#define GC5035_REG_VTS_L 0x42
#define GC5035_VTS_H_MASK 0x3f
#define GC5035_VTS_MAX 16383
#define GC5035_EXPOSURE_MARGIN 16
#define GC5035_REG_CTRL_MODE 0x3e
#define GC5035_MODE_SW_STANDBY 0x01
#define GC5035_MODE_STREAMING 0x91
/* Page 1 registers */
/* Test pattern control */
#define GC5035_REG_TEST_PATTERN 0x8c
#define GC5035_TEST_PATTERN_ENABLE 0x11
#define GC5035_TEST_PATTERN_DISABLE 0x10
/* Page 2 registers */
/* OTP access registers */
#define GC5035_REG_OTP_MODE 0xf3
#define GC5035_OTP_PRE_READ 0x20
#define GC5035_OTP_READ_MODE 0x12
#define GC5035_OTP_READ_DONE 0x00
#define GC5035_REG_OTP_DATA 0x6c
#define GC5035_REG_OTP_ACCESS_ADDR_H 0x69
#define GC5035_REG_OTP_ACCESS_ADDR_L 0x6a
#define GC5035_OTP_ACCESS_ADDR_H_MASK 0x1f
#define GC5035_OTP_ADDR_MASK 0x1fff
#define GC5035_OTP_ADDR_SHIFT 3
#define GC5035_REG_DD_TOTALNUM_H 0x01
#define GC5035_REG_DD_TOTALNUM_L 0x02
#define GC5035_DD_TOTALNUM_H_MASK 0x07
#define GC5035_REG_DD_LOAD_STATUS 0x06
#define GC5035_OTP_BIT_LOAD BIT(0)
/* OTP-related definitions */
#define GC5035_OTP_ID_SIZE 9
#define GC5035_OTP_ID_DATA_OFFSET 0x0020
#define GC5035_OTP_DATA_LENGTH 1024
/* OTP DPC parameters */
#define GC5035_OTP_DPC_FLAG_OFFSET 0x0068
#define GC5035_OTP_DPC_FLAG_MASK 0x03
#define GC5035_OTP_FLAG_EMPTY 0x00
#define GC5035_OTP_FLAG_VALID 0x01
#define GC5035_OTP_DPC_TOTAL_NUMBER_OFFSET 0x0070
#define GC5035_OTP_DPC_ERROR_NUMBER_OFFSET 0x0078
/* OTP register parameters */
#define GC5035_OTP_REG_FLAG_OFFSET 0x0880
#define GC5035_OTP_REG_DATA_OFFSET 0x0888
#define GC5035_OTP_REG_ADDR_OFFSET 1
#define GC5035_OTP_REG_VAL_OFFSET 2
#define GC5035_OTP_PAGE_FLAG_OFFSET 3
#define GC5035_OTP_PER_PAGE_SIZE 4
#define GC5035_OTP_REG_PAGE_MASK 0x07
#define GC5035_OTP_REG_MAX_GROUP 5
#define GC5035_OTP_REG_BYTE_PER_GROUP 5
#define GC5035_OTP_REG_PER_GROUP 2
#define GC5035_OTP_REG_BYTE_PER_REG 2
#define GC5035_OTP_REG_DATA_SIZE 25
#define GC5035_OTP_REG_SIZE 10
#define GC5035_DD_DELAY_US (10 * 1000)
#define GC5035_DD_TIMEOUT_US (100 * 1000)
static const char * const gc5035_supplies[] = {
/*
* Requested separately due to power sequencing needs:
* "iovdd", * Power supply for I/O circuits *
*/
"dvdd12", /* Digital core power */
"avdd28", /* Analog power */
};
struct gc5035_regval {
u8 addr;
u8 val;
};
struct gc5035_reg {
u8 page;
struct gc5035_regval regval;
};
struct gc5035_otp_regs {
unsigned int num_regs;
struct gc5035_reg regs[GC5035_OTP_REG_SIZE];
};
struct gc5035_dpc {
bool valid;
unsigned int total_num;
};
struct gc5035_mode {
u32 width;
u32 height;
u32 max_fps;
u32 hts_def;
u32 vts_def;
u32 exp_def;
const struct gc5035_regval *reg_list;
size_t num_regs;
};
struct gc5035 {
struct i2c_client *client;
struct clk *mclk;
unsigned long mclk_rate;
struct gpio_desc *resetb_gpio;
struct gpio_desc *pwdn_gpio;
struct regulator *iovdd_supply;
struct regulator_bulk_data supplies[ARRAY_SIZE(gc5035_supplies)];
struct v4l2_subdev subdev;
struct media_pad pad;
struct v4l2_ctrl_handler ctrl_handler;
struct v4l2_ctrl *exposure;
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *vblank;
bool otp_read;
u8 otp_id[GC5035_OTP_ID_SIZE];
struct gc5035_dpc dpc;
struct gc5035_otp_regs otp_regs;
/*
* Serialize control access, get/set format, get selection
* and start streaming.
*/
struct mutex mutex;
bool streaming;
const struct gc5035_mode *cur_mode;
};
static inline struct gc5035 *to_gc5035(struct v4l2_subdev *sd)
{
return container_of(sd, struct gc5035, subdev);
}
static const struct gc5035_regval gc5035_otp_init_regs[] = {
{0xfc, 0x01},
{0xf4, 0x40},
{0xf5, 0xe9},
{0xf6, 0x14},
{0xf8, 0x49},
{0xf9, 0x82},
{0xfa, 0x00},
{0xfc, 0x81},
{0xfe, 0x00},
{0x36, 0x01},
{0xd3, 0x87},
{0x36, 0x00},
{0x33, 0x00},
{0xf7, 0x01},
{0xfc, 0x8e},
{0xfe, 0x00},
{0xee, 0x30},
{0xfa, 0x10},
{0xf5, 0xe9},
{0xfe, 0x02},
{0x67, 0xc0},
{0x59, 0x3f},
{0x55, 0x84},
{0x65, 0x80},
{0x66, 0x03},
{0xfe, 0x00},
};
static const struct gc5035_regval gc5035_otp_exit_regs[] = {
{0xfe, 0x02},
{0x67, 0x00},
{0xfe, 0x00},
{0xfa, 0x00},
};
static const struct gc5035_regval gc5035_dd_auto_load_regs[] = {
{0xfe, 0x02},
{0xbe, 0x00},
{0xa9, 0x01},
{0x09, 0x33},
};
static const struct gc5035_regval gc5035_otp_dd_regs[] = {
{0x03, 0x00},
{0x04, 0x80},
{0x95, 0x0a},
{0x96, 0x30},
{0x97, 0x0a},
{0x98, 0x32},
{0x99, 0x07},
{0x9a, 0xa9},
{0xf3, 0x80},
};
static const struct gc5035_regval gc5035_otp_dd_enable_regs[] = {
{0xbe, 0x01},
{0x09, 0x00},
{0xfe, 0x01},
{0x80, 0x02},
{0xfe, 0x00},
};
/*
* Xclk 24Mhz
* Pclk 87.6Mhz
* grabwindow_width 2592
* grabwindow_height 1944
* max_framerate 30fps
* mipi_datarate per lane 876Mbps
*/
static const struct gc5035_regval gc5035_global_regs[] = {
/*init*/
{0xfc, 0x01},
{0xf4, 0x40},
{0xf5, 0xe9},
{0xf6, 0x14},
{0xf8, 0x49},
{0xf9, 0x82},
{0xfa, 0x00},
{0xfc, 0x81},
{0xfe, 0x00},
{0x36, 0x01},
{0xd3, 0x87},
{0x36, 0x00},
{0x33, 0x00},
{0xfe, 0x03},
{0x01, 0xe7},
{0xf7, 0x01},
{0xfc, 0x8f},
{0xfc, 0x8f},
{0xfc, 0x8e},
{0xfe, 0x00},
{0xee, 0x30},
{0x87, 0x18},
{0xfe, 0x01},
{0x8c, 0x90},
{0xfe, 0x00},
/* Analog & CISCTL */
{0xfe, 0x00},
{0x05, 0x02},
{0x06, 0xda},
{0x9d, 0x0c},
{0x09, 0x00},
{0x0a, 0x04},
{0x0b, 0x00},
{0x0c, 0x03},
{0x0d, 0x07},
{0x0e, 0xa8},
{0x0f, 0x0a},
{0x10, 0x30},
{0x11, 0x02},
{0x17, 0x80},
{0x19, 0x05},
{0xfe, 0x02},
{0x30, 0x03},
{0x31, 0x03},
{0xfe, 0x00},
{0xd9, 0xc0},
{0x1b, 0x20},
{0x21, 0x48},
{0x28, 0x22},
{0x29, 0x58},
{0x44, 0x20},
{0x4b, 0x10},
{0x4e, 0x1a},
{0x50, 0x11},
{0x52, 0x33},
{0x53, 0x44},
{0x55, 0x10},
{0x5b, 0x11},
{0xc5, 0x02},
{0x8c, 0x1a},
{0xfe, 0x02},
{0x33, 0x05},
{0x32, 0x38},
{0xfe, 0x00},
{0x91, 0x80},
{0x92, 0x28},
{0x93, 0x20},
{0x95, 0xa0},
{0x96, 0xe0},
{0xd5, 0xfc},
{0x97, 0x28},
{0x16, 0x0c},
{0x1a, 0x1a},
{0x1f, 0x11},
{0x20, 0x10},
{0x46, 0x83},
{0x4a, 0x04},
{0x54, 0x02},
{0x62, 0x00},
{0x72, 0x8f},
{0x73, 0x89},
{0x7a, 0x05},
{0x7d, 0xcc},
{0x90, 0x00},
{0xce, 0x18},
{0xd0, 0xb2},
{0xd2, 0x40},
{0xe6, 0xe0},
{0xfe, 0x02},
{0x12, 0x01},
{0x13, 0x01},
{0x14, 0x01},
{0x15, 0x02},
{0x22, 0x7c},
{0x91, 0x00},
{0x92, 0x00},
{0x93, 0x00},
{0x94, 0x00},
{0xfe, 0x00},
{0xfc, 0x88},
{0xfe, 0x10},
{0xfe, 0x00},
{0xfc, 0x8e},
{0xfe, 0x00},
{0xfe, 0x00},
{0xfe, 0x00},
{0xfc, 0x88},
{0xfe, 0x10},
{0xfe, 0x00},
{0xfc, 0x8e},
/* Gain */
{0xfe, 0x00},
{0xb0, 0x6e},
{0xb1, 0x01},
{0xb2, 0x00},
{0xb3, 0x00},
{0xb4, 0x00},
{0xb6, 0x00},
/* ISP */
{0xfe, 0x01},
{0x53, 0x00},
{0x89, 0x03},
{0x60, 0x40},
/* BLK */
{0xfe, 0x01},
{0x42, 0x21},
{0x49, 0x03},
{0x4a, 0xff},
{0x4b, 0xc0},
{0x55, 0x00},
/* Anti_blooming */
{0xfe, 0x01},
{0x41, 0x28},
{0x4c, 0x00},
{0x4d, 0x00},
{0x4e, 0x3c},
{0x44, 0x08},
{0x48, 0x02},
/* Crop */
{0xfe, 0x01},
{0x91, 0x00},
{0x92, 0x08},
{0x93, 0x00},
{0x94, 0x07},
{0x95, 0x07},
{0x96, 0x98},
{0x97, 0x0a},
{0x98, 0x20},
{0x99, 0x00},
/* MIPI */
{0xfe, 0x03},
{0x02, 0x57},
{0x03, 0xb7},
{0x15, 0x14},
{0x18, 0x0f},
{0x21, 0x22},
{0x22, 0x06},
{0x23, 0x48},
{0x24, 0x12},
{0x25, 0x28},
{0x26, 0x08},
{0x29, 0x06},
{0x2a, 0x58},
{0x2b, 0x08},
{0xfe, 0x01},
{0x8c, 0x10},
{0xfe, 0x00},
{0x3e, 0x01},
};
/*
* Xclk 24Mhz
* Pclk 87.6Mhz
* grabwindow_width 2592
* grabwindow_height 1944
* max_framerate 30fps
* mipi_datarate per lane 876Mbps
*/
static const struct gc5035_regval gc5035_2592x1944_regs[] = {
/* System */
{0xfe, 0x00},
{0x3e, 0x01},
{0xfc, 0x01},
{0xf4, 0x40},
{0xf5, 0xe9},
{0xf6, 0x14},
{0xf8, 0x49},
{0xf9, 0x82},
{0xfa, 0x00},
{0xfc, 0x81},
{0xfe, 0x00},
{0x36, 0x01},
{0xd3, 0x87},
{0x36, 0x00},
{0x33, 0x00},
{0xfe, 0x03},
{0x01, 0xe7},
{0xf7, 0x01},
{0xfc, 0x8f},
{0xfc, 0x8f},
{0xfc, 0x8e},
{0xfe, 0x00},
{0xee, 0x30},
{0x87, 0x18},
{0xfe, 0x01},
{0x8c, 0x90},
{0xfe, 0x00},
/* Analog & CISCTL */
{0xfe, 0x00},
{0x05, 0x02},
{0x06, 0xda},
{0x9d, 0x0c},
{0x09, 0x00},
{0x0a, 0x04},
{0x0b, 0x00},
{0x0c, 0x03},
{0x0d, 0x07},
{0x0e, 0xa8},
{0x0f, 0x0a},
{0x10, 0x30},
{0x21, 0x48},
{0x29, 0x58},
{0x44, 0x20},
{0x4e, 0x1a},
{0x8c, 0x1a},
{0x91, 0x80},
{0x92, 0x28},
{0x93, 0x20},
{0x95, 0xa0},
{0x96, 0xe0},
{0xd5, 0xfc},
{0x97, 0x28},
{0x1f, 0x11},
{0xce, 0x18},
{0xd0, 0xb2},
{0xfe, 0x02},
{0x14, 0x01},
{0x15, 0x02},
{0xfe, 0x00},
{0xfc, 0x88},
{0xfe, 0x10},
{0xfe, 0x00},
{0xfc, 0x8e},
{0xfe, 0x00},
{0xfe, 0x00},
{0xfe, 0x00},
{0xfc, 0x88},
{0xfe, 0x10},
{0xfe, 0x00},
{0xfc, 0x8e},
/* BLK */
{0xfe, 0x01},
{0x49, 0x03},
{0x4a, 0xff},
{0x4b, 0xc0},
/* Anti_blooming */
{0xfe, 0x01},
{0x4e, 0x3c},
{0x44, 0x08},
/* Crop */
{0xfe, 0x01},
{0x91, 0x00},
{0x92, 0x08},
{0x93, 0x00},
{0x94, 0x07},
{0x95, 0x07},
{0x96, 0x98},
{0x97, 0x0a},
{0x98, 0x20},
{0x99, 0x00},
/* MIPI */
{0xfe, 0x03},
{0x02, 0x57},
{0x22, 0x06},
{0x26, 0x08},
{0x29, 0x06},
{0x2b, 0x08},
{0xfe, 0x01},
{0x8c, 0x10},
{0xfe, 0x00},
{0x3e, 0x91},
};
/*
* Xclk 24Mhz
* Pclk 87.6Mhz
* grabwindow_width 1296
* grabwindow_height 972
* mipi_datarate per lane 876Mbps
*/
static const struct gc5035_regval gc5035_1296x972_regs[] = {
/*NULL*/
{0xfe, 0x00},
{0x3e, 0x01},
{0xfc, 0x01},
{0xf4, 0x40},
{0xf5, 0xe4},
{0xf6, 0x14},
{0xf8, 0x49},
{0xf9, 0x12},
{0xfa, 0x01},
{0xfc, 0x81},
{0xfe, 0x00},
{0x36, 0x01},
{0xd3, 0x87},
{0x36, 0x00},
{0x33, 0x20},
{0xfe, 0x03},
{0x01, 0x87},
{0xf7, 0x11},
{0xfc, 0x8f},
{0xfc, 0x8f},
{0xfc, 0x8e},
{0xfe, 0x00},
{0xee, 0x30},
{0x87, 0x18},
{0xfe, 0x01},
{0x8c, 0x90},
{0xfe, 0x00},
/* Analog & CISCTL */
{0xfe, 0x00},
{0x05, 0x02},
{0x06, 0xda},
{0x9d, 0x0c},
{0x09, 0x00},
{0x0a, 0x04},
{0x0b, 0x00},
{0x0c, 0x03},
{0x0d, 0x07},
{0x0e, 0xa8},
{0x0f, 0x0a},
{0x10, 0x30},
{0x21, 0x60},
{0x29, 0x30},
{0x44, 0x18},
{0x4e, 0x20},
{0x8c, 0x20},
{0x91, 0x15},
{0x92, 0x3a},
{0x93, 0x20},
{0x95, 0x45},
{0x96, 0x35},
{0xd5, 0xf0},
{0x97, 0x20},
{0x1f, 0x19},
{0xce, 0x18},
{0xd0, 0xb3},
{0xfe, 0x02},
{0x14, 0x02},
{0x15, 0x00},
{0xfe, 0x00},
{0xfc, 0x88},
{0xfe, 0x10},
{0xfe, 0x00},
{0xfc, 0x8e},
{0xfe, 0x00},
{0xfe, 0x00},
{0xfe, 0x00},
{0xfc, 0x88},
{0xfe, 0x10},
{0xfe, 0x00},
{0xfc, 0x8e},
/* BLK */
{0xfe, 0x01},
{0x49, 0x00},
{0x4a, 0x01},
{0x4b, 0xf8},
/* Anti_blooming */
{0xfe, 0x01},
{0x4e, 0x06},
{0x44, 0x02},
/* Crop */
{0xfe, 0x01},
{0x91, 0x00},
{0x92, 0x04},
{0x93, 0x00},
{0x94, 0x03},
{0x95, 0x03},
{0x96, 0xcc},
{0x97, 0x05},
{0x98, 0x10},
{0x99, 0x00},
/* MIPI */
{0xfe, 0x03},
{0x02, 0x58},
{0x22, 0x03},
{0x26, 0x06},
{0x29, 0x03},
{0x2b, 0x06},
{0xfe, 0x01},
{0x8c, 0x10},
};
/*
* Xclk 24Mhz
* Pclk 87.6Mhz
* linelength 672{0x2a0)
* framelength 2232{0x8b8)
* grabwindow_width 1280
* grabwindow_height 720
* max_framerate 30fps
* mipi_datarate per lane 876Mbps
*/
static const struct gc5035_regval gc5035_1280x720_regs[] = {
/* System */
{0xfe, 0x00},
{0x3e, 0x01},
{0xfc, 0x01},
{0xf4, 0x40},
{0xf5, 0xe4},
{0xf6, 0x14},
{0xf8, 0x49},
{0xf9, 0x12},
{0xfa, 0x01},
{0xfc, 0x81},
{0xfe, 0x00},
{0x36, 0x01},
{0xd3, 0x87},
{0x36, 0x00},
{0x33, 0x20},
{0xfe, 0x03},
{0x01, 0x87},
{0xf7, 0x11},
{0xfc, 0x8f},
{0xfc, 0x8f},
{0xfc, 0x8e},
{0xfe, 0x00},
{0xee, 0x30},
{0x87, 0x18},
{0xfe, 0x01},
{0x8c, 0x90},
{0xfe, 0x00},
/* Analog & CISCTL */
{0xfe, 0x00},
{0x05, 0x02},
{0x06, 0xda},
{0x9d, 0x0c},
{0x09, 0x00},
{0x0a, 0x04},
{0x0b, 0x00},
{0x0c, 0x03},
{0x0d, 0x07},
{0x0e, 0xa8},
{0x0f, 0x0a},
{0x10, 0x30},
{0x21, 0x60},
{0x29, 0x30},
{0x44, 0x18},
{0x4e, 0x20},
{0x8c, 0x20},
{0x91, 0x15},
{0x92, 0x3a},
{0x93, 0x20},
{0x95, 0x45},
{0x96, 0x35},
{0xd5, 0xf0},
{0x97, 0x20},
{0x1f, 0x19},
{0xce, 0x18},
{0xd0, 0xb3},
{0xfe, 0x02},
{0x14, 0x02},
{0x15, 0x00},
{0xfe, 0x00},
{0xfc, 0x88},
{0xfe, 0x10},
{0xfe, 0x00},
{0xfc, 0x8e},
{0xfe, 0x00},
{0xfe, 0x00},
{0xfe, 0x00},
{0xfc, 0x88},
{0xfe, 0x10},
{0xfe, 0x00},
{0xfc, 0x8e},
/* BLK */
{0xfe, 0x01},
{0x49, 0x00},
{0x4a, 0x01},
{0x4b, 0xf8},
/* Anti_blooming */
{0xfe, 0x01},
{0x4e, 0x06},
{0x44, 0x02},
/* Crop */
{0xfe, 0x01},
{0x91, 0x00},
{0x92, 0x0a},
{0x93, 0x00},
{0x94, 0x0b},
{0x95, 0x02},
{0x96, 0xd0},
{0x97, 0x05},
{0x98, 0x00},
{0x99, 0x00},
/* MIPI */
{0xfe, 0x03},
{0x02, 0x58},
{0x22, 0x03},
{0x26, 0x06},
{0x29, 0x03},
{0x2b, 0x06},
{0xfe, 0x01},
{0x8c, 0x10},
{0xfe, 0x00},
{0x3e, 0x91},
};
static const struct gc5035_mode gc5035_modes[] = {
{
.width = 2592,
.height = 1944,
.max_fps = 30,
.exp_def = 0x258,
.hts_def = 2920,
.vts_def = 2008,
.reg_list = gc5035_2592x1944_regs,
.num_regs = ARRAY_SIZE(gc5035_2592x1944_regs),
},
{
.width = 1296,
.height = 972,
.max_fps = 30,
.exp_def = 0x258,
.hts_def = 1460,
.vts_def = 2008,
.reg_list = gc5035_1296x972_regs,
.num_regs = ARRAY_SIZE(gc5035_1296x972_regs),
},
{
.width = 1280,
.height = 720,
.max_fps = 60,
.exp_def = 0x258,
.hts_def = 1896,
.vts_def = 1536,
.reg_list = gc5035_1280x720_regs,
.num_regs = ARRAY_SIZE(gc5035_1280x720_regs),
},
};
static const char * const gc5035_test_pattern_menu[] = {
"Disabled",
"Color Bar",
};
static const s64 gc5035_link_freqs[] = {
438000000,
};
static u64 gc5035_link_to_pixel_rate(u32 f_index)
{
u64 pixel_rate = gc5035_link_freqs[f_index] * 2 * GC5035_DATA_LANES;
do_div(pixel_rate, GC5035_BITS_PER_SAMPLE);
return pixel_rate;
}
static int gc5035_write_reg(struct gc5035 *gc5035, u8 reg, u8 val)
{
return i2c_smbus_write_byte_data(gc5035->client, reg, val);
}
static int gc5035_write_array(struct gc5035 *gc5035,
const struct gc5035_regval *regs,
size_t num_regs)
{
unsigned int i;
int ret;
for (i = 0; i < num_regs; i++) {
ret = gc5035_write_reg(gc5035, regs[i].addr, regs[i].val);
if (ret)
return ret;
}
return 0;
}
static int gc5035_read_reg(struct gc5035 *gc5035, u8 reg, u8 *val)
{
int ret;
ret = i2c_smbus_read_byte_data(gc5035->client, reg);
if (ret < 0)
return ret;
*val = (unsigned char)ret;
return 0;
}
static int gc5035_otp_read_data(struct gc5035 *gc5035, u16 bit_addr, u8 *data,
size_t length)
{
size_t i;
int ret;
if (WARN_ON(bit_addr % 8))
return -EINVAL;
if (WARN_ON(bit_addr / 8 + length > GC5035_OTP_DATA_LENGTH))
return -EINVAL;
ret = gc5035_write_reg(gc5035, GC5035_PAGE_REG, 2);
if (ret)
return ret;
ret = gc5035_write_reg(gc5035, GC5035_REG_OTP_ACCESS_ADDR_H,
(bit_addr >> 8) &
GC5035_OTP_ACCESS_ADDR_H_MASK);
if (ret)
return ret;
ret = gc5035_write_reg(gc5035, GC5035_REG_OTP_ACCESS_ADDR_L,
bit_addr & 0xff);
if (ret)
return ret;
ret = gc5035_write_reg(gc5035, GC5035_REG_OTP_MODE,
GC5035_OTP_PRE_READ);
if (ret)
goto out_read_done;
ret = gc5035_write_reg(gc5035, GC5035_REG_OTP_MODE,
GC5035_OTP_READ_MODE);
if (ret)
goto out_read_done;
for (i = 0; i < length; i++) {
ret = gc5035_read_reg(gc5035, GC5035_REG_OTP_DATA, &data[i]);
if (ret)
goto out_read_done;
}
out_read_done:
gc5035_write_reg(gc5035, GC5035_REG_OTP_MODE, GC5035_OTP_READ_DONE);
return ret;
}
static int gc5035_read_otp_regs(struct gc5035 *gc5035)
{
struct device *dev = &gc5035->client->dev;
struct gc5035_otp_regs *otp_regs = &gc5035->otp_regs;
u8 regs[GC5035_OTP_REG_DATA_SIZE] = {0};
unsigned int i, j;
u8 flag;
int ret;
ret = gc5035_otp_read_data(gc5035, GC5035_OTP_REG_FLAG_OFFSET,
&flag, 1);
if (ret) {
dev_err(dev, "failed to read otp reg flag\n");
return ret;
}
dev_dbg(dev, "register update flag = 0x%x\n", flag);
gc5035->otp_regs.num_regs = 0;
if (flag != GC5035_OTP_FLAG_VALID)
return 0;
ret = gc5035_otp_read_data(gc5035, GC5035_OTP_REG_DATA_OFFSET,
regs, sizeof(regs));
if (ret) {
dev_err(dev, "failed to read otp reg data\n");
return ret;
}
for (i = 0; i < GC5035_OTP_REG_MAX_GROUP; i++) {
unsigned int base_group = i * GC5035_OTP_REG_BYTE_PER_GROUP;
for (j = 0; j < GC5035_OTP_REG_PER_GROUP; j++) {
struct gc5035_reg *reg;
if (!(regs[base_group] &
BIT((GC5035_OTP_PER_PAGE_SIZE * j +
GC5035_OTP_PAGE_FLAG_OFFSET))))
continue;
reg = &otp_regs->regs[otp_regs->num_regs++];
reg->page = (regs[base_group] >>
(GC5035_OTP_PER_PAGE_SIZE * j)) &
GC5035_OTP_REG_PAGE_MASK;
reg->regval.addr = regs[base_group + j *
GC5035_OTP_REG_BYTE_PER_REG +
GC5035_OTP_REG_ADDR_OFFSET];
reg->regval.val = regs[base_group + j *
GC5035_OTP_REG_BYTE_PER_REG +
GC5035_OTP_REG_VAL_OFFSET];
}
}
return 0;
}
static int gc5035_read_dpc(struct gc5035 *gc5035)
{
struct device *dev = &gc5035->client->dev;
struct gc5035_dpc *dpc = &gc5035->dpc;
u8 dpc_flag = 0;
u8 error_number = 0;
u8 total_number = 0;
int ret;
ret = gc5035_otp_read_data(gc5035, GC5035_OTP_DPC_FLAG_OFFSET,
&dpc_flag, 1);
if (ret) {
dev_err(dev, "failed to read dpc flag\n");
return ret;
}
dev_dbg(dev, "dpc flag = 0x%x\n", dpc_flag);
dpc->valid = false;
switch (dpc_flag & GC5035_OTP_DPC_FLAG_MASK) {
case GC5035_OTP_FLAG_EMPTY:
dev_dbg(dev, "dpc info is empty!!\n");
break;
case GC5035_OTP_FLAG_VALID:
dev_dbg(dev, "dpc info is valid!\n");
ret = gc5035_otp_read_data(gc5035,
GC5035_OTP_DPC_TOTAL_NUMBER_OFFSET,
&total_number, 1);
if (ret) {
dev_err(dev, "failed to read dpc total number\n");
return ret;
}
ret = gc5035_otp_read_data(gc5035,
GC5035_OTP_DPC_ERROR_NUMBER_OFFSET,
&error_number, 1);
if (ret) {
dev_err(dev, "failed to read dpc error number\n");
return ret;
}
dpc->total_num = total_number + error_number;
dpc->valid = true;
dev_dbg(dev, "total_num = %d\n", dpc->total_num);
break;
default:
break;
}
return ret;
}
static int gc5035_otp_read_sensor_info(struct gc5035 *gc5035)
{
int ret;
ret = gc5035_read_dpc(gc5035);
if (ret)
return ret;
return gc5035_read_otp_regs(gc5035);
}
static int gc5035_check_dd_load_status(struct gc5035 *gc5035)
{
u8 status;
int ret;
ret = gc5035_read_reg(gc5035, GC5035_REG_DD_LOAD_STATUS, &status);
if (ret)
return ret;
if (status & GC5035_OTP_BIT_LOAD)
return status;
else
return 0;
}
static int gc5035_otp_update_dd(struct gc5035 *gc5035)
{
struct device *dev = &gc5035->client->dev;
struct gc5035_dpc *dpc = &gc5035->dpc;
int val, ret;
if (!dpc->valid) {
dev_dbg(dev, "DPC table invalid, not updating DD.\n");
return 0;
}
dev_dbg(dev, "DD auto load start\n");
ret = gc5035_write_array(gc5035, gc5035_dd_auto_load_regs,
ARRAY_SIZE(gc5035_dd_auto_load_regs));
if (ret) {
dev_err(dev, "failed to write dd auto load reg\n");
return ret;
}
ret = gc5035_write_reg(gc5035, GC5035_REG_DD_TOTALNUM_H,
(dpc->total_num >> 8) &
GC5035_DD_TOTALNUM_H_MASK);
if (ret)
return ret;
ret = gc5035_write_reg(gc5035, GC5035_REG_DD_TOTALNUM_L,
dpc->total_num & 0xff);
if (ret)
return ret;
ret = gc5035_write_array(gc5035, gc5035_otp_dd_regs,
ARRAY_SIZE(gc5035_otp_dd_regs));
if (ret)
return ret;
/* Wait for DD to finish loading automatically */
ret = readx_poll_timeout(gc5035_check_dd_load_status, gc5035,
val, val <= 0, GC5035_DD_DELAY_US,
GC5035_DD_TIMEOUT_US);
if (ret < 0) {
dev_err(dev, "DD load timeout\n");
return -EFAULT;
}
if (val < 0) {
dev_err(dev, "DD load failure\n");
return val;
}
ret = gc5035_write_array(gc5035, gc5035_otp_dd_enable_regs,
ARRAY_SIZE(gc5035_otp_dd_enable_regs));
if (ret)
return ret;
return 0;
}
static int gc5035_otp_update_regs(struct gc5035 *gc5035)
{
struct device *dev = &gc5035->client->dev;
struct gc5035_otp_regs *otp_regs = &gc5035->otp_regs;
unsigned int i;
int ret;
dev_dbg(dev, "reg count = %d\n", otp_regs->num_regs);
for (i = 0; i < otp_regs->num_regs; i++) {
ret = gc5035_write_reg(gc5035, GC5035_PAGE_REG,
otp_regs->regs[i].page);
if (ret)
return ret;
ret = gc5035_write_reg(gc5035,
otp_regs->regs[i].regval.addr,
otp_regs->regs[i].regval.val);
if (ret)
return ret;
}
return 0;
}
static int gc5035_otp_update(struct gc5035 *gc5035)
{
struct device *dev = &gc5035->client->dev;
int ret;
ret = gc5035_otp_update_dd(gc5035);
if (ret) {
dev_err(dev, "failed to update otp dd\n");
return ret;
}
ret = gc5035_otp_update_regs(gc5035);
if (ret) {
dev_err(dev, "failed to update otp regs\n");
return ret;
}
return ret;
}
static int gc5035_set_otp_config(struct gc5035 *gc5035)
{
struct device *dev = &gc5035->client->dev;
u8 otp_id[GC5035_OTP_ID_SIZE];
int ret;
ret = gc5035_write_array(gc5035, gc5035_otp_init_regs,
ARRAY_SIZE(gc5035_otp_init_regs));
if (ret) {
dev_err(dev, "failed to write otp init reg\n");
return ret;
}
ret = gc5035_otp_read_data(gc5035, GC5035_OTP_ID_DATA_OFFSET,
&otp_id[0], GC5035_OTP_ID_SIZE);
if (ret) {
dev_err(dev, "failed to read otp id\n");
goto out_otp_exit;
}
if (!gc5035->otp_read || memcmp(gc5035->otp_id, otp_id, sizeof(otp_id))) {
dev_dbg(dev, "reading OTP configuration\n");
memset(&gc5035->otp_regs, 0, sizeof(gc5035->otp_regs));
memset(&gc5035->dpc, 0, sizeof(gc5035->dpc));
memcpy(gc5035->otp_id, otp_id, sizeof(gc5035->otp_id));
ret = gc5035_otp_read_sensor_info(gc5035);
if (ret < 0) {
dev_err(dev, "failed to read otp info\n");
goto out_otp_exit;
}
gc5035->otp_read = true;
}
ret = gc5035_otp_update(gc5035);
if (ret < 0)
return ret;
out_otp_exit:
ret = gc5035_write_array(gc5035, gc5035_otp_exit_regs,
ARRAY_SIZE(gc5035_otp_exit_regs));
if (ret) {
dev_err(dev, "failed to write otp exit reg\n");
return ret;
}
return ret;
}
static int gc5035_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *fmt)
{
struct gc5035 *gc5035 = to_gc5035(sd);
const struct gc5035_mode *mode;
s64 h_blank, vblank_def;
mode = v4l2_find_nearest_size(gc5035_modes,
ARRAY_SIZE(gc5035_modes), width,
height, fmt->format.width,
fmt->format.height);
fmt->format.code = MEDIA_BUS_FMT_SRGGB10_1X10;
fmt->format.width = mode->width;
fmt->format.height = mode->height;
fmt->format.field = V4L2_FIELD_NONE;
mutex_lock(&gc5035->mutex);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
*v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
} else {
gc5035->cur_mode = mode;
h_blank = mode->hts_def - mode->width;
__v4l2_ctrl_modify_range(gc5035->hblank, h_blank,
h_blank, 1, h_blank);
vblank_def = round_up(mode->vts_def, 4) - mode->height;
__v4l2_ctrl_modify_range(gc5035->vblank, vblank_def,
GC5035_VTS_MAX - mode->height,
4, vblank_def);
}
mutex_unlock(&gc5035->mutex);
return 0;
}
static int gc5035_get_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *fmt)
{
struct gc5035 *gc5035 = to_gc5035(sd);
const struct gc5035_mode *mode = gc5035->cur_mode;
mutex_lock(&gc5035->mutex);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
} else {
fmt->format.width = mode->width;
fmt->format.height = mode->height;
fmt->format.code = MEDIA_BUS_FMT_SRGGB10_1X10;
fmt->format.field = V4L2_FIELD_NONE;
}
mutex_unlock(&gc5035->mutex);
return 0;
}
static int gc5035_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->index != 0)
return -EINVAL;
code->code = MEDIA_BUS_FMT_SRGGB10_1X10;
return 0;
}
static int gc5035_enum_frame_sizes(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_frame_size_enum *fse)
{
if (fse->index >= ARRAY_SIZE(gc5035_modes))
return -EINVAL;
if (fse->code != MEDIA_BUS_FMT_SRGGB10_1X10)
return -EINVAL;
fse->min_width = gc5035_modes[fse->index].width;
fse->max_width = gc5035_modes[fse->index].width;
fse->max_height = gc5035_modes[fse->index].height;
fse->min_height = gc5035_modes[fse->index].height;
return 0;
}
static int __gc5035_start_stream(struct gc5035 *gc5035)
{
int ret;
ret = gc5035_write_array(gc5035, gc5035_global_regs,
ARRAY_SIZE(gc5035_global_regs));
if (ret)
return ret;
ret = gc5035_set_otp_config(gc5035);
if (ret)
return ret;
ret = gc5035_write_array(gc5035, gc5035->cur_mode->reg_list,
gc5035->cur_mode->num_regs);
if (ret)
return ret;
/* In case these controls are set before streaming */
ret = __v4l2_ctrl_handler_setup(&gc5035->ctrl_handler);
if (ret)
return ret;
gc5035_write_reg(gc5035, GC5035_PAGE_REG, 0);
if (ret)
return ret;
return gc5035_write_reg(gc5035, GC5035_REG_CTRL_MODE,
GC5035_MODE_STREAMING);
}
static int __gc5035_stop_stream(struct gc5035 *gc5035)
{
int ret;
ret = gc5035_write_reg(gc5035, GC5035_PAGE_REG, 0);
if (ret)
return ret;
return gc5035_write_reg(gc5035, GC5035_REG_CTRL_MODE,
GC5035_MODE_SW_STANDBY);
}
static int gc5035_s_stream(struct v4l2_subdev *sd, int on)
{
struct gc5035 *gc5035 = to_gc5035(sd);
struct i2c_client *client = gc5035->client;
int ret = 0;
mutex_lock(&gc5035->mutex);
on = !!on;
if (on == gc5035->streaming)
goto unlock_and_return;
if (on) {
ret = pm_runtime_get_sync(&client->dev);
if (ret < 0) {
pm_runtime_put_noidle(&client->dev);
goto unlock_and_return;
}
ret = __gc5035_start_stream(gc5035);
if (ret) {
dev_err(&client->dev, "start stream failed\n");
pm_runtime_put(&client->dev);
goto unlock_and_return;
}
} else {
__gc5035_stop_stream(gc5035);
pm_runtime_put(&client->dev);
}
gc5035->streaming = on;
unlock_and_return:
mutex_unlock(&gc5035->mutex);
return ret;
}
static int gc5035_runtime_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct gc5035 *gc5035 = to_gc5035(sd);
unsigned long delay;
int ret;
/* IOVDD must be enabled first. */
ret = regulator_enable(gc5035->iovdd_supply);
if (ret) {
dev_err(dev, "Failed to enable iovdd regulator: %d\n", ret);
return ret;
}
/* Wait at least 50 us between IOVDD and AVDD/DVDD. */
usleep_range(50, 150);
ret = regulator_bulk_enable(ARRAY_SIZE(gc5035_supplies),
gc5035->supplies);
if (ret) {
dev_err(dev, "Failed to enable regulators: %d\n", ret);
goto disable_iovdd;
}
gpiod_set_value_cansleep(gc5035->resetb_gpio, 0);
gpiod_set_value_cansleep(gc5035->pwdn_gpio, 0);
ret = clk_prepare_enable(gc5035->mclk);
if (ret < 0) {
dev_err(dev, "Failed to enable mclk\n");
goto enable_pwdn;
}
/* min. 1200 MCLK cycles required before first I2C transaction. */
delay = DIV_ROUND_UP(1200UL * USEC_PER_SEC, gc5035->mclk_rate);
usleep_range(delay, delay + 200);
return 0;
enable_pwdn:
gpiod_set_value_cansleep(gc5035->pwdn_gpio, 1);
gpiod_set_value_cansleep(gc5035->resetb_gpio, 1);
regulator_bulk_disable(ARRAY_SIZE(gc5035_supplies), gc5035->supplies);
disable_iovdd:
regulator_disable(gc5035->iovdd_supply);
return ret;
}
static int gc5035_runtime_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct gc5035 *gc5035 = to_gc5035(sd);
unsigned long delay;
/* min. 2000 MCLK cycles required after streaming stops. */
delay = DIV_ROUND_UP(2000UL * USEC_PER_SEC, gc5035->mclk_rate);
usleep_range(delay, delay + 200);
clk_disable_unprepare(gc5035->mclk);
gpiod_set_value_cansleep(gc5035->pwdn_gpio, 1);
gpiod_set_value_cansleep(gc5035->resetb_gpio, 1);
regulator_bulk_disable(ARRAY_SIZE(gc5035_supplies), gc5035->supplies);
regulator_disable(gc5035->iovdd_supply);
return 0;
}
static int gc5035_entity_init_cfg(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg)
{
struct v4l2_subdev_format fmt = {
.which = V4L2_SUBDEV_FORMAT_TRY,
.format = {
.width = 2592,
.height = 1944,
}
};
gc5035_set_fmt(subdev, cfg, &fmt);
return 0;
}
static const struct dev_pm_ops gc5035_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(gc5035_runtime_suspend,
gc5035_runtime_resume, NULL)
};
static const struct v4l2_subdev_video_ops gc5035_video_ops = {
.s_stream = gc5035_s_stream,
};
static const struct v4l2_subdev_pad_ops gc5035_pad_ops = {
.init_cfg = gc5035_entity_init_cfg,
.enum_mbus_code = gc5035_enum_mbus_code,
.enum_frame_size = gc5035_enum_frame_sizes,
.get_fmt = gc5035_get_fmt,
.set_fmt = gc5035_set_fmt,
};
static const struct v4l2_subdev_ops gc5035_subdev_ops = {
.video = &gc5035_video_ops,
.pad = &gc5035_pad_ops,
};
static const struct media_entity_operations gc5035_subdev_entity_ops = {
.link_validate = v4l2_subdev_link_validate,
};
static int gc5035_set_exposure(struct gc5035 *gc5035, int val)
{
int ret;
ret = gc5035_write_reg(gc5035, GC5035_PAGE_REG, 0);
if (ret)
return ret;
ret = gc5035_write_reg(gc5035, GC5035_REG_EXPOSURE_H,
(val >> 8) & GC5035_EXPOSURE_H_MASK);
if (ret)
return ret;
return gc5035_write_reg(gc5035, GC5035_REG_EXPOSURE_L, val & 0xff);
}
static int gc5035_set_analogue_gain(struct gc5035 *gc5035, int val)
{
int ret;
ret = gc5035_write_reg(gc5035, GC5035_PAGE_REG, 0);
if (ret)
return ret;
return gc5035_write_reg(gc5035, GC5035_REG_ANALOG_GAIN, val);
}
static int gc5035_set_digital_gain(struct gc5035 *gc5035, int val)
{
int ret;
ret = gc5035_write_reg(gc5035, GC5035_PAGE_REG, 0);
if (ret)
return ret;
ret = gc5035_write_reg(gc5035, GC5035_REG_DIGI_GAIN_H,
(val >> (8 - GC5035_DGAIN_L_SHIFT))
& GC5035_DGAIN_H_MASK);
if (ret)
return ret;
return gc5035_write_reg(gc5035, GC5035_REG_DIGI_GAIN_L,
(val << GC5035_DGAIN_L_SHIFT)
& GC5035_DGAIN_L_MASK);
}
static int gc5035_set_vblank(struct gc5035 *gc5035, int val)
{
int frame_length = 0;
int ret;
frame_length = val + gc5035->cur_mode->height;
ret = gc5035_write_reg(gc5035, GC5035_PAGE_REG, 0);
if (ret)
return ret;
ret = gc5035_write_reg(gc5035, GC5035_REG_VTS_H,
(frame_length >> 8) & GC5035_VTS_H_MASK);
if (ret)
return ret;
return gc5035_write_reg(gc5035, GC5035_REG_VTS_L, frame_length & 0xff);
}
static int gc5035_enable_test_pattern(struct gc5035 *gc5035, int pattern)
{
int ret;
if (pattern)
pattern = GC5035_TEST_PATTERN_ENABLE;
else
pattern = GC5035_TEST_PATTERN_DISABLE;
ret = gc5035_write_reg(gc5035, GC5035_PAGE_REG, 1);
if (ret)
return ret;
ret = gc5035_write_reg(gc5035, GC5035_REG_TEST_PATTERN, pattern);
if (ret)
return ret;
return gc5035_write_reg(gc5035, GC5035_PAGE_REG, 0);
}
static int gc5035_set_ctrl(struct v4l2_ctrl *ctrl)
{
struct gc5035 *gc5035 = container_of(ctrl->handler,
struct gc5035, ctrl_handler);
struct i2c_client *client = gc5035->client;
s64 max;
int ret;
/* Propagate change of current control to all related controls */
switch (ctrl->id) {
case V4L2_CID_VBLANK:
/* Update max exposure while meeting expected vblanking */
max = gc5035->cur_mode->height + ctrl->val
- GC5035_EXPOSURE_MARGIN;
__v4l2_ctrl_modify_range(gc5035->exposure,
gc5035->exposure->minimum, max,
gc5035->exposure->step,
gc5035->exposure->default_value);
break;
}
if (!pm_runtime_get_if_in_use(&client->dev))
return 0;
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
ret = gc5035_set_exposure(gc5035, ctrl->val);
break;
case V4L2_CID_ANALOGUE_GAIN:
ret = gc5035_set_analogue_gain(gc5035, ctrl->val);
break;
case V4L2_CID_DIGITAL_GAIN:
ret = gc5035_set_digital_gain(gc5035, ctrl->val);
break;
case V4L2_CID_VBLANK:
ret = gc5035_set_vblank(gc5035, ctrl->val);
break;
case V4L2_CID_TEST_PATTERN:
ret = gc5035_enable_test_pattern(gc5035, ctrl->val);
break;
default:
ret = -EINVAL;
break;
};
pm_runtime_put(&client->dev);
return ret;
}
static const struct v4l2_ctrl_ops gc5035_ctrl_ops = {
.s_ctrl = gc5035_set_ctrl,
};
static int gc5035_initialize_controls(struct gc5035 *gc5035)
{
const struct gc5035_mode *mode;
struct v4l2_ctrl_handler *handler;
struct v4l2_ctrl *ctrl;
u64 exposure_max, pixel_rate;
u32 h_blank, vblank_def;
int ret;
handler = &gc5035->ctrl_handler;
mode = gc5035->cur_mode;
ret = v4l2_ctrl_handler_init(handler, 8);
if (ret)
return ret;
handler->lock = &gc5035->mutex;
ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ,
0, 0, gc5035_link_freqs);
if (ctrl)
ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
pixel_rate = gc5035_link_to_pixel_rate(0);
v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE,
0, pixel_rate, 1, pixel_rate);
h_blank = mode->hts_def - mode->width;
gc5035->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
h_blank, h_blank, 1, h_blank);
if (gc5035->hblank)
gc5035->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
vblank_def = round_up(mode->vts_def, 4) - mode->height;
gc5035->vblank = v4l2_ctrl_new_std(handler, &gc5035_ctrl_ops,
V4L2_CID_VBLANK, vblank_def,
GC5035_VTS_MAX - mode->height,
4, vblank_def);
exposure_max = mode->vts_def - GC5035_EXPOSURE_MARGIN;
gc5035->exposure = v4l2_ctrl_new_std(handler, &gc5035_ctrl_ops,
V4L2_CID_EXPOSURE,
GC5035_EXPOSURE_MIN, exposure_max,
GC5035_EXPOSURE_STEP,
mode->exp_def);
v4l2_ctrl_new_std(handler, &gc5035_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
GC5035_ANALOG_GAIN_MIN, GC5035_ANALOG_GAIN_MAX,
GC5035_ANALOG_GAIN_STEP, GC5035_ANALOG_GAIN_DEFAULT);
v4l2_ctrl_new_std(handler, &gc5035_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
GC5035_DIGI_GAIN_MIN, GC5035_DIGI_GAIN_MAX,
GC5035_DIGI_GAIN_STEP, GC5035_DIGI_GAIN_DEFAULT);
v4l2_ctrl_new_std_menu_items(handler, &gc5035_ctrl_ops,
V4L2_CID_TEST_PATTERN,
ARRAY_SIZE(gc5035_test_pattern_menu) - 1,
0, 0, gc5035_test_pattern_menu);
if (handler->error) {
ret = handler->error;
dev_err(&gc5035->client->dev,
"Failed to init controls(%d)\n", ret);
goto err_free_handler;
}
gc5035->subdev.ctrl_handler = handler;
return 0;
err_free_handler:
v4l2_ctrl_handler_free(handler);
return ret;
}
static int gc5035_check_sensor_id(struct gc5035 *gc5035,
struct i2c_client *client)
{
struct device *dev = &gc5035->client->dev;
u16 id;
u8 pid = 0;
u8 ver = 0;
int ret;
ret = gc5035_read_reg(gc5035, GC5035_REG_CHIP_ID_H, &pid);
if (ret)
return ret;
ret = gc5035_read_reg(gc5035, GC5035_REG_CHIP_ID_L, &ver);
if (ret)
return ret;
id = GC5035_ID(pid, ver);
if (id != GC5035_CHIP_ID) {
dev_err(dev, "Unexpected sensor id(%04x)\n", id);
return -EINVAL;
}
dev_dbg(dev, "Detected GC%04x sensor\n", id);
return 0;
}
static int gc5035_get_hwcfg(struct gc5035 *gc5035)
{
struct device *dev = &gc5035->client->dev;
struct v4l2_fwnode_endpoint bus_cfg = {
.bus_type = V4L2_MBUS_CSI2_DPHY
};
struct fwnode_handle *ep;
struct fwnode_handle *fwnode = dev_fwnode(dev);
unsigned long link_freq_mask = 0;
unsigned int i, j;
int ret;
if (!fwnode)
return -ENODEV;
ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
if (!ep)
return -ENODEV;
ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
if (ret)
goto out;
dev_dbg(dev, "num of link freqs: %d", bus_cfg.nr_of_link_frequencies);
if (!bus_cfg.nr_of_link_frequencies) {
dev_warn(dev, "no link frequencies defined");
goto out;
}
for (i = 0; i < ARRAY_SIZE(gc5035_link_freqs); ++i) {
for (j = 0; j < bus_cfg.nr_of_link_frequencies; j++) {
if (bus_cfg.link_frequencies[j]
== gc5035_link_freqs[i]) {
link_freq_mask |= BIT(i);
dev_dbg(dev, "Link frequency %lld supported\n",
gc5035_link_freqs[i]);
break;
}
}
}
if (!link_freq_mask) {
dev_err(dev, "No supported link frequencies found\n");
ret = -EINVAL;
goto out;
}
out:
v4l2_fwnode_endpoint_free(&bus_cfg);
fwnode_handle_put(ep);
return ret;
}
static int gc5035_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct gc5035 *gc5035;
struct v4l2_subdev *sd;
int ret, i;
u32 freq;
gc5035 = devm_kzalloc(dev, sizeof(*gc5035), GFP_KERNEL);
if (!gc5035)
return -ENOMEM;
gc5035->client = client;
gc5035->cur_mode = &gc5035_modes[0];
gc5035->mclk = devm_clk_get(dev, "mclk");
if (IS_ERR(gc5035->mclk))
return dev_err_probe(dev, PTR_ERR(gc5035->mclk), "Failed to get mclk\n");
ret = device_property_read_u32(dev, "clock-frequency", &freq);
if (ret < 0)
return dev_err_probe(dev, ret, "Failed to get clock-frequency\n");
if (freq != GC5035_MCLK_RATE)
dev_warn(dev, "Given clock-frequency %u is different from expected %lu\n",
freq, GC5035_MCLK_RATE);
ret = gc5035_get_hwcfg(gc5035);
if (ret < 0)
return dev_err_probe(dev, ret, "Failed to get hardware config\n");
ret = clk_set_rate(gc5035->mclk, freq);
if (ret < 0)
return dev_err_probe(dev, ret, "Failed to set mclk rate\n");
gc5035->mclk_rate = clk_get_rate(gc5035->mclk);
if (gc5035->mclk_rate != freq)
dev_warn(dev, "mclk rate set to %lu instead of requested %u\n",
gc5035->mclk_rate, freq);
gc5035->pwdn_gpio = devm_gpiod_get_optional(dev, "pwdn", GPIOD_OUT_HIGH);
if (IS_ERR(gc5035->pwdn_gpio))
return dev_err_probe(dev, PTR_ERR(gc5035->pwdn_gpio),
"Failed to get pwdn-gpios\n");
gc5035->resetb_gpio = devm_gpiod_get(dev, "resetb", GPIOD_OUT_HIGH);
if (IS_ERR(gc5035->resetb_gpio))
return dev_err_probe(dev, PTR_ERR(gc5035->resetb_gpio),
"Failed to get resetb-gpios\n");
gc5035->iovdd_supply = devm_regulator_get(dev, "iovdd");
if (IS_ERR(gc5035->iovdd_supply))
return dev_err_probe(dev, PTR_ERR(gc5035->iovdd_supply),
"Failed to get iovdd regulator\n");
for (i = 0; i < ARRAY_SIZE(gc5035_supplies); i++)
gc5035->supplies[i].supply = gc5035_supplies[i];
ret = devm_regulator_bulk_get(&gc5035->client->dev,
ARRAY_SIZE(gc5035_supplies),
gc5035->supplies);
if (ret)
return dev_err_probe(dev, ret, "Failed to get regulators\n");
mutex_init(&gc5035->mutex);
sd = &gc5035->subdev;
v4l2_i2c_subdev_init(sd, client, &gc5035_subdev_ops);
ret = gc5035_initialize_controls(gc5035);
if (ret) {
dev_err_probe(dev, ret, "Failed to initialize controls\n");
goto err_destroy_mutex;
}
ret = gc5035_runtime_resume(dev);
if (ret) {
dev_err_probe(dev, ret, "Failed to power on\n");
goto err_free_handler;
}
ret = gc5035_check_sensor_id(gc5035, client);
if (ret) {
dev_err_probe(dev, ret, "Sensor ID check failed\n");
goto err_power_off;
}
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
sd->entity.ops = &gc5035_subdev_entity_ops;
sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
gc5035->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&sd->entity, 1, &gc5035->pad);
if (ret < 0) {
dev_err_probe(dev, ret, "Failed to initialize pads\n");
goto err_power_off;
}
ret = v4l2_async_register_subdev_sensor_common(sd);
if (ret) {
dev_err_probe(dev, ret, "v4l2 async register subdev failed\n");
goto err_clean_entity;
}
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
pm_runtime_idle(dev);
return 0;
err_clean_entity:
media_entity_cleanup(&sd->entity);
err_power_off:
gc5035_runtime_suspend(dev);
err_free_handler:
v4l2_ctrl_handler_free(&gc5035->ctrl_handler);
err_destroy_mutex:
mutex_destroy(&gc5035->mutex);
return ret;
}
static int gc5035_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct gc5035 *gc5035 = to_gc5035(sd);
v4l2_async_unregister_subdev(sd);
media_entity_cleanup(&sd->entity);
v4l2_ctrl_handler_free(&gc5035->ctrl_handler);
mutex_destroy(&gc5035->mutex);
pm_runtime_disable(&client->dev);
if (!pm_runtime_status_suspended(&client->dev))
gc5035_runtime_suspend(&client->dev);
pm_runtime_set_suspended(&client->dev);
return 0;
}
static const struct of_device_id gc5035_of_match[] = {
{ .compatible = "galaxycore,gc5035" },
{},
};
MODULE_DEVICE_TABLE(of, gc5035_of_match);
static struct i2c_driver gc5035_i2c_driver = {
.driver = {
.name = "gc5035",
.pm = &gc5035_pm_ops,
.of_match_table = gc5035_of_match,
},
.probe_new = &gc5035_probe,
.remove = &gc5035_remove,
};
module_i2c_driver(gc5035_i2c_driver);
MODULE_AUTHOR("Hao He <hao.he@bitland.com.cn>");
MODULE_AUTHOR("Xingyu Wu <wuxy@bitland.com.cn>");
MODULE_AUTHOR("Tomasz Figa <tfiga@chromium.org>");
MODULE_DESCRIPTION("GalaxyCore gc5035 sensor driver");
MODULE_LICENSE("GPL v2");