// SPDX-License-Identifier: GPL-2.0
/*
* Driver for GalaxyCore gc08a3 image sensor
*
* Copyright 2024 MediaTek
*
* Zhi Mao <zhi.mao@mediatek.com>
*/
#include <linux/array_size.h>
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/container_of.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/math64.h>
#include <linux/mod_devicetable.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/types.h>
#include <linux/units.h>
#include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
#define GC08A3_REG_TEST_PATTERN_EN CCI_REG8(0x008c)
#define GC08A3_REG_TEST_PATTERN_IDX CCI_REG8(0x008d)
#define GC08A3_TEST_PATTERN_EN 0x01
#define GC08A3_STREAMING_REG CCI_REG8(0x0100)
#define GC08A3_FLIP_REG CCI_REG8(0x0101)
#define GC08A3_FLIP_H_MASK BIT(0)
#define GC08A3_FLIP_V_MASK BIT(1)
#define GC08A3_EXP_REG CCI_REG16(0x0202)
#define GC08A3_EXP_MARGIN 16
#define GC08A3_EXP_MIN 4
#define GC08A3_EXP_STEP 1
#define GC08A3_AGAIN_REG CCI_REG16(0x0204)
#define GC08A3_AGAIN_MIN 1024
#define GC08A3_AGAIN_MAX (1024 * 16)
#define GC08A3_AGAIN_STEP 1
#define GC08A3_FRAME_LENGTH_REG CCI_REG16(0x0340)
#define GC08A3_VTS_MAX 0xfff0
#define GC08A3_REG_CHIP_ID CCI_REG16(0x03f0)
#define GC08A3_CHIP_ID 0x08a3
#define GC08A3_NATIVE_WIDTH 3264
#define GC08A3_NATIVE_HEIGHT 2448
#define GC08A3_DEFAULT_CLK_FREQ (24 * HZ_PER_MHZ)
#define GC08A3_MBUS_CODE MEDIA_BUS_FMT_SRGGB10_1X10
#define GC08A3_DATA_LANES 4
#define GC08A3_RGB_DEPTH 10
#define GC08A3_SLEEP_US (2 * USEC_PER_MSEC)
static const char *const gc08a3_test_pattern_menu[] = {
"No Pattern", "Solid Black", "Colour Bar", "Solid White",
"Solid Red", "Solid Green", "Solid Blue", "Solid Yellow",
};
static const s64 gc08a3_link_freq_menu_items[] = {
(336 * HZ_PER_MHZ),
(207 * HZ_PER_MHZ),
};
static const char *const gc08a3_supply_name[] = {
"avdd",
"dvdd",
"dovdd",
};
struct gc08a3 {
struct device *dev;
struct v4l2_subdev sd;
struct media_pad pad;
struct clk *xclk;
struct regulator_bulk_data supplies[ARRAY_SIZE(gc08a3_supply_name)];
struct gpio_desc *reset_gpio;
struct v4l2_ctrl_handler ctrls;
struct v4l2_ctrl *pixel_rate;
struct v4l2_ctrl *link_freq;
struct v4l2_ctrl *exposure;
struct v4l2_ctrl *vblank;
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *hflip;
struct v4l2_ctrl *vflip;
struct regmap *regmap;
unsigned long link_freq_bitmap;
const struct gc08a3_mode *cur_mode;
};
struct gc08a3_reg_list {
u32 num_of_regs;
const struct cci_reg_sequence *regs;
};
static const struct cci_reg_sequence mode_3264x2448[] = {
/* system */
{ CCI_REG8(0x0336), 0x70 },
{ CCI_REG8(0x0383), 0xbb },
{ CCI_REG8(0x0344), 0x00 },
{ CCI_REG8(0x0345), 0x06 },
{ CCI_REG8(0x0346), 0x00 },
{ CCI_REG8(0x0347), 0x04 },
{ CCI_REG8(0x0348), 0x0c },