mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
media: spi: add driver for rk1608
Change-Id: I8508668fcd1e35c49fe581875fcf9045e004ae9c Signed-off-by: Hu Kejun <william.hu@rock-chips.com>
This commit is contained in:
@@ -9,6 +9,15 @@ config VIDEO_GS1662
|
||||
---help---
|
||||
Enable the GS1662 driver which serializes video streams.
|
||||
|
||||
config VIDEO_ROCKCHIP_PREISP
|
||||
tristate "Rockchip Image Signal Pre-processing driver"
|
||||
depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && SPI_MASTER
|
||||
depends on ARCH_ROCKCHIP || COMPILE_TEST
|
||||
select V4L2_FWNODE
|
||||
default n
|
||||
help
|
||||
Support for Pre-isp on the rockchip SoC.
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
obj-$(CONFIG_VIDEO_GS1662) += gs1662.o
|
||||
obj-$(CONFIG_VIDEO_ROCKCHIP_PREISP) += rk1608_dphy.o rk1608.o
|
||||
|
||||
1596
drivers/media/spi/rk1608.c
Normal file
1596
drivers/media/spi/rk1608.c
Normal file
File diff suppressed because it is too large
Load Diff
484
drivers/media/spi/rk1608.h
Normal file
484
drivers/media/spi/rk1608.h
Normal file
@@ -0,0 +1,484 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/**
|
||||
* Rockchip rk1608 driver
|
||||
*
|
||||
* Copyright (C) 2017-2018 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __RK1608_H__
|
||||
#define __RK1608_H__
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include "rk1608_dphy.h"
|
||||
|
||||
#define RK1608_OP_TRY_MAX 3
|
||||
#define RK1608_OP_TRY_DELAY 10
|
||||
#define RK1608_CMD_WRITE 0x00000011
|
||||
#define RK1608_CMD_WRITE_REG0 0X00010011
|
||||
#define RK1608_CMD_WRITE_REG1 0X00020011
|
||||
#define RK1608_CMD_READ 0x00000077
|
||||
#define RK1608_CMD_READ_BEGIN 0x000000aa
|
||||
#define RK1608_CMD_QUERY 0x000000ff
|
||||
#define RK1608_CMD_QUERY_REG2 0x000001ff
|
||||
#define RK1608_STATE_ID_MASK 0xffff0000
|
||||
#define RK1608_STATE_ID 0X16080000
|
||||
#define RK1608_STATE_MASK 0x0000ffff
|
||||
#define APB_CMD_WRITE_REG1 0X00020011
|
||||
#define RK1608_R_MSG_QUEUE_ADDR 0x60050000
|
||||
|
||||
#define RK1608_IRQ_TYPE_MSG 0x12345678
|
||||
#define BOOT_REQUEST_ADDR 0x18000010
|
||||
#define RK1608_HEAD_ADDR 0x60000000
|
||||
#define RK1608_FW_NAME "rk1608.rkl"
|
||||
#define RK1608_S_MSG_QUEUE_ADDR 0x60050010
|
||||
#define RK1608_PMU_SYS_REG0 0x120000f0
|
||||
#define RK1608_MSG_QUEUE_OK_MASK 0xffff0001
|
||||
#define RK1608_MSG_QUEUE_OK_TAG 0x16080001
|
||||
#define RK1608_MAX_OP_BYTES 60000
|
||||
#define MSG_SYNC_TIMEOUT 50
|
||||
|
||||
#define BOOT_FLAG_CRC (0x01 << 0)
|
||||
#define BOOT_FLAG_EXE (0x01 << 1)
|
||||
#define BOOT_FLAG_LOAD_PMEM (0x01 << 2)
|
||||
#define BOOT_FLAG_ACK (0x01 << 3)
|
||||
#define BOOT_FLAG_READ_WAIT (0x01 << 4)
|
||||
#define BOOT_FLAG_BOOT_REQUEST (0x01 << 5)
|
||||
|
||||
#define DEBUG_DUMP_ALL_SEND_RECV_MSG 0
|
||||
#define RK1608_MCLK_RATE (24 * 1000 * 1000ul)
|
||||
#define SENSOR_TIMEOUT 1000
|
||||
|
||||
#define OPM_SLAVE_MODE 0x100000
|
||||
#define RSD_SEL_2CYC 0x008000
|
||||
#define DFS_SEL_16BIT 0x000002
|
||||
#define SPI_CTRL0 0x11060000
|
||||
#define SPI_ENR 0x11060008
|
||||
#define CRUPMU_CLKSEL14_CON 0x12008098
|
||||
#define PMUGRF_GPIO1A_E 0x12030040
|
||||
#define PMUGRF_GPIO1B_E 0x12030044
|
||||
#define BIT7_6_SEL_8MA 0xf000a000
|
||||
#define BIT1_0_SEL_8MA 0x000f000a
|
||||
#define SPI0_PLL_SEL_APLL 0xff004000
|
||||
#define INVALID_ID -1
|
||||
#define RK1608_MAX_SEC_NUM 10
|
||||
|
||||
#define ISP_DSP_HDRAE_MAXGRIDITEMS 225
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef MSB2LSB32
|
||||
#define MSB2LSB32(x) ((((u32)(x) & 0x80808080) >> 7) | \
|
||||
(((u32)(x) & 0x40404040) >> 5) | \
|
||||
(((u32)(x) & 0x20202020) >> 3) | \
|
||||
(((u32)(x) & 0x10101010) >> 1) | \
|
||||
(((u32)(x) & 0x08080808) << 1) | \
|
||||
(((u32)(x) & 0x04040404) << 3) | \
|
||||
(((u32)(x) & 0x02020202) << 5) | \
|
||||
(((u32)(x) & 0x01010101) << 7))
|
||||
#endif
|
||||
|
||||
struct rk1608_state {
|
||||
struct v4l2_subdev sd;
|
||||
struct rk1608_dphy *dphy[2];
|
||||
struct mutex lock; /* protect resource */
|
||||
struct mutex sensor_lock; /* protect sensor */
|
||||
struct mutex send_msg_lock; /* protect msg */
|
||||
spinlock_t hdrae_lock; /* protect hdrae parameter */
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct gpio_desc *irq_gpio;
|
||||
int irq;
|
||||
struct gpio_desc *wakeup_gpio;
|
||||
struct gpio_desc *aesync_gpio;
|
||||
struct v4l2_subdev *sensor[4];
|
||||
struct device *dev;
|
||||
struct spi_device *spi;
|
||||
int power_count;
|
||||
int msg_num;
|
||||
u32 link_nums;
|
||||
u32 sensor_cnt;
|
||||
u32 sensor_nums[2];
|
||||
u32 msg_done[8];
|
||||
wait_queue_head_t msg_wait;
|
||||
struct media_pad pad;
|
||||
struct v4l2_ctrl *link_freq;
|
||||
struct v4l2_ctrl *pixel_rate;
|
||||
struct v4l2_ctrl *hblank;
|
||||
struct v4l2_ctrl *vblank;
|
||||
struct v4l2_ctrl *exposure;
|
||||
struct v4l2_ctrl *gain;
|
||||
struct v4l2_ctrl_handler ctrl_handler;
|
||||
s64 link_freqs;
|
||||
u32 max_speed_hz;
|
||||
u32 min_speed_hz;
|
||||
struct preisp_hdrae_para_s hdrae_para;
|
||||
struct preisp_hdrae_exp_s hdrae_exp;
|
||||
u32 set_exp_cnt;
|
||||
const char *firm_name;
|
||||
};
|
||||
|
||||
struct rk1608_section {
|
||||
union {
|
||||
u32 offset;
|
||||
u32 wait_value;
|
||||
};
|
||||
u32 size;
|
||||
union {
|
||||
u32 load_addr;
|
||||
u32 wait_addr;
|
||||
};
|
||||
u16 wait_time;
|
||||
u16 timeout;
|
||||
u16 crc_16;
|
||||
u8 flag;
|
||||
u8 type;
|
||||
};
|
||||
|
||||
struct rk1608_header {
|
||||
char version[32];
|
||||
u32 header_size;
|
||||
u32 section_count;
|
||||
struct rk1608_section sections[RK1608_MAX_SEC_NUM];
|
||||
};
|
||||
|
||||
struct rk1608_boot_req {
|
||||
u32 flag;
|
||||
u32 load_addr;
|
||||
u32 boot_len;
|
||||
u8 status;
|
||||
u8 dummy[2];
|
||||
u8 cmd;
|
||||
};
|
||||
|
||||
struct rk1608_msg_queue {
|
||||
u32 buf_head; /* msg buffer head */
|
||||
u32 buf_tail; /* msg buffer tail */
|
||||
u32 cur_send; /* current msg send position */
|
||||
u32 cur_recv; /* current msg receive position */
|
||||
};
|
||||
|
||||
struct msg {
|
||||
u32 size; /* unit 4 bytes */
|
||||
u16 type;
|
||||
union {
|
||||
u8 camera_id;
|
||||
u8 core_id;
|
||||
} id;
|
||||
union {
|
||||
u8 sync;
|
||||
u8 log_level;
|
||||
s8 err;
|
||||
} mux;
|
||||
};
|
||||
|
||||
struct msg_init {
|
||||
struct msg msg_head;
|
||||
u32 i2c_bus;
|
||||
u32 i2c_clk;
|
||||
s8 in_mipi_phy;
|
||||
s8 out_mipi_phy;
|
||||
s8 mipi_lane;
|
||||
s8 bayer;
|
||||
u8 sensor_name[32];
|
||||
u8 i2c_slave_addr;
|
||||
};
|
||||
|
||||
struct preisp_vc_cfg {
|
||||
s8 data_id;
|
||||
s8 decode_format;
|
||||
s8 flag;
|
||||
s8 unused;
|
||||
|
||||
u16 width;
|
||||
u16 height;
|
||||
};
|
||||
|
||||
struct msg_in_size {
|
||||
struct msg msg_head;
|
||||
struct preisp_vc_cfg channel[2];
|
||||
};
|
||||
|
||||
struct msg_out_size_head {
|
||||
struct msg msg_head;
|
||||
u16 width;
|
||||
u16 height;
|
||||
u32 mipi_clk;
|
||||
u16 line_length_pclk;
|
||||
u16 frame_length_lines;
|
||||
u8 mipi_lane;
|
||||
};
|
||||
|
||||
struct msg_set_output_size {
|
||||
struct msg_out_size_head head;
|
||||
struct preisp_vc_cfg channel[2];
|
||||
};
|
||||
|
||||
enum ISP_AE_Bayer_Mode_e {
|
||||
BAYER_MODE_MIN = 0,
|
||||
BAYER_MODE_BGGR = 1,
|
||||
BAYER_MODE_GRBG = 2,
|
||||
BAYER_MODE_GBRG = 3,
|
||||
BAYER_MODE_RGGB = 4,
|
||||
BAYER_MODE_MAX = 5
|
||||
};
|
||||
|
||||
struct ISP_AE_YCOEFF_s {
|
||||
int rcoef;
|
||||
int gcoef;
|
||||
int bcoef;
|
||||
int offset;
|
||||
};
|
||||
|
||||
enum ISP_AE_Hist_Mode_e {
|
||||
AE_HISTSTATICMODE_INVALID = 0,
|
||||
AE_HISTSTATICMODE_Y,
|
||||
AE_HISTSTATICMODE_R,
|
||||
AE_HISTSTATICMODE_G,
|
||||
AE_HISTSTATICMODE_B,
|
||||
AE_HISTSTATICMODE_MAX
|
||||
};
|
||||
|
||||
enum ISP_AE_Grid_Mode_e {
|
||||
AE_MEASURE_GRID_INVALID = 0,
|
||||
AE_MEASURE_GRID_1X1,
|
||||
AE_MEASURE_GRID_5X5,
|
||||
AE_MEASURE_GRID_9X9,
|
||||
AE_MEASURE_GRID_15X15,
|
||||
AE_MEASURE_GRID_MAX
|
||||
};
|
||||
|
||||
struct ISP_DSP_hdrae_cfg_s {
|
||||
enum ISP_AE_Bayer_Mode_e bayer_mode;
|
||||
enum ISP_AE_Grid_Mode_e grid_mode;
|
||||
u8 weight[ISP_DSP_HDRAE_MAXGRIDITEMS];
|
||||
enum ISP_AE_Hist_Mode_e hist_mode;
|
||||
struct ISP_AE_YCOEFF_s ycoeff;
|
||||
u8 imgbits;
|
||||
u16 width;
|
||||
u16 height;
|
||||
u16 frames;
|
||||
};
|
||||
|
||||
struct msg_set_sensor_info_s {
|
||||
struct msg msg_head;
|
||||
u32 set_exp_cnt;
|
||||
u16 r_gain;
|
||||
u16 b_gain;
|
||||
u16 gr_gain;
|
||||
u16 gb_gain;
|
||||
u32 exp_time[3];
|
||||
u32 exp_gain[3];
|
||||
u32 reg_exp_time[3];
|
||||
u32 reg_exp_gain[3];
|
||||
s32 lsc_table[17 * 17];
|
||||
struct ISP_DSP_hdrae_cfg_s dsp_hdrae;
|
||||
};
|
||||
|
||||
enum {
|
||||
/* AP -> RK1608
|
||||
* 1 msg of sensor
|
||||
*/
|
||||
id_msg_init_sensor_t = 0x0001,
|
||||
id_msg_set_input_size_t,
|
||||
id_msg_set_output_size_t,
|
||||
id_msg_set_stream_in_on_t,
|
||||
id_msg_set_stream_in_off_t,
|
||||
id_msg_set_stream_out_on_t,
|
||||
id_msg_set_stream_out_off_t,
|
||||
|
||||
/* AP -> RK1608
|
||||
* 2 msg of take picture
|
||||
*/
|
||||
id_msg_take_picture_t = 0x0021,
|
||||
id_msg_take_picture_done_t,
|
||||
|
||||
/* AP -> RK1608
|
||||
* 3 msg of realtime parameter
|
||||
*/
|
||||
id_msg_rt_args_t = 0x0031,
|
||||
id_msg_set_sensor_info_t,
|
||||
|
||||
/* AP -> RK1608
|
||||
* 4 msg of power manager
|
||||
*/
|
||||
id_msg_set_sys_mode_bypass_t = 0x0200,
|
||||
id_msg_set_sys_mode_standby_t,
|
||||
id_msg_set_sys_mode_idle_enable_t,
|
||||
id_msg_set_sys_mode_idle_disable_t,
|
||||
id_msg_set_sys_mode_slave_dsp_on_t,
|
||||
id_msg_set_sys_mode_slave_dsp_off_t,
|
||||
|
||||
/* AP -> RK1608
|
||||
* 5 msg of debug config
|
||||
*/
|
||||
id_msg_set_log_level_t = 0x0250,
|
||||
|
||||
/* RK1608 -> AP
|
||||
* 6 response of sensor msg
|
||||
*/
|
||||
id_msg_init_sensor_ret_t = 0x0301,
|
||||
id_msg_set_input_size_ret_t,
|
||||
id_msg_set_output_size_ret_t,
|
||||
id_msg_set_stream_in_on_ret_t,
|
||||
id_msg_set_stream_in_off_ret_t,
|
||||
id_msg_set_stream_out_on_ret_t,
|
||||
id_msg_set_stream_out_off_ret_t,
|
||||
|
||||
/* RK1608 -> AP
|
||||
* 7 response of take picture msg
|
||||
*/
|
||||
id_msg_take_picture_ret_t = 0x0320,
|
||||
id_msg_take_picture_done_ret_t,
|
||||
|
||||
/* RK1608 -> AP
|
||||
* 8 response of realtime parameter msg
|
||||
*/
|
||||
id_msg_rt_args_ret_t = 0x0330,
|
||||
|
||||
/* rk1608 -> AP */
|
||||
id_msg_do_i2c_t = 0x0390,
|
||||
/* AP -> rk1608 */
|
||||
id_msg_do_i2c_ret_t,
|
||||
|
||||
/* RK1608 -> AP
|
||||
* 9 msg of print log
|
||||
*/
|
||||
id_msg_rk1608_log_t = 0x0400,
|
||||
|
||||
/* dsi2csi dump */
|
||||
id_msg_dsi2sci_rgb_dump_t = 0x6000,
|
||||
id_msg_dsi2sci_nv12_dump_t = 0x6001,
|
||||
|
||||
/* RK1608 -> AP
|
||||
* 10 msg of xfile
|
||||
*/
|
||||
id_msg_xfile_import_t = 0x8000 + 0x0600,
|
||||
id_msg_xfile_export_t,
|
||||
id_msg_xfile_mkdir_t
|
||||
};
|
||||
|
||||
static int rk1608_send_msg_to_dsp(struct rk1608_state *pdata, struct msg *m);
|
||||
/**
|
||||
* rk1608_write - RK1608 synchronous write
|
||||
*
|
||||
* @spi: spi device
|
||||
* @addr: resource address
|
||||
* @data: data buffer
|
||||
* @data_len: data buffer size, in bytes
|
||||
* Context: can sleep
|
||||
*
|
||||
* It returns zero on success, else a negative error code.
|
||||
*/
|
||||
static int rk1608_write(struct spi_device *spi, s32 addr,
|
||||
const s32 *data, size_t data_len);
|
||||
|
||||
/**
|
||||
* rk1608_safe_write - RK1608 synchronous write with state check
|
||||
*
|
||||
* @spi: spi device
|
||||
* @addr: resource address
|
||||
* @data: data buffer
|
||||
* @data_len: data buffer size, in bytes
|
||||
* Context: can sleep
|
||||
*
|
||||
* It returns zero on success, else operation state code.
|
||||
*/
|
||||
static int rk1608_safe_write(struct spi_device *spi,
|
||||
s32 addr, const s32 *data, size_t data_len);
|
||||
|
||||
/**
|
||||
* rk1608_read - RK1608 synchronous read
|
||||
*
|
||||
* @spi: spi device
|
||||
* @addr: resource address
|
||||
* @data: data buffer [out]
|
||||
* @data_len: data buffer size, in bytes
|
||||
* Context: can sleep
|
||||
*
|
||||
* It returns zero on success, else a negative error code.
|
||||
*/
|
||||
static int rk1608_read(struct spi_device *spi, s32 addr,
|
||||
s32 *data, size_t data_len);
|
||||
|
||||
/**
|
||||
* rk1608_safe_read - RK1608 synchronous read with state check
|
||||
*
|
||||
* @spi: spi device
|
||||
* @addr: resource address
|
||||
* @data: data buffer [out]
|
||||
* @data_len: data buffer size, in bytes
|
||||
* Context: can sleep
|
||||
*
|
||||
* It returns zero on success, else operation state code.
|
||||
*/
|
||||
static int rk1608_safe_read(struct spi_device *spi,
|
||||
s32 addr, s32 *data, size_t data_len);
|
||||
|
||||
/**
|
||||
* rk1608_operation_query - RK1608 last operation state query
|
||||
*
|
||||
* @spi: spi device
|
||||
* @state: last operation state [out]
|
||||
* Context: can sleep
|
||||
*
|
||||
* It returns zero on success, else a negative error code.
|
||||
*/
|
||||
static int rk1608_operation_query(struct spi_device *spi, s32 *state);
|
||||
|
||||
/**
|
||||
* rk1608_interrupt_request - RK1608 request a rk1608 interrupt
|
||||
*
|
||||
* @spi: spi device
|
||||
* @interrupt_num: interrupt identification
|
||||
* Context: can sleep
|
||||
*
|
||||
* It returns zero on success, else a negative error code.
|
||||
*/
|
||||
static int rk1608_interrupt_request(struct spi_device *spi,
|
||||
s32 interrupt_num);
|
||||
|
||||
static int rk1608_read_wait(struct spi_device *spi,
|
||||
const struct rk1608_section *sec);
|
||||
|
||||
static int rk1608_boot_request(struct spi_device *spi,
|
||||
const struct rk1608_section *sec);
|
||||
|
||||
static int rk1608_download_section(struct spi_device *spi, const u8 *data,
|
||||
const struct rk1608_section *sec);
|
||||
/**
|
||||
* rk1608_download_fw: - rk1608 firmware download through spi
|
||||
*
|
||||
* @spi: spi device
|
||||
* @fw_name: name of firmware file, NULL for default firmware name
|
||||
* Context: can sleep
|
||||
*
|
||||
* It returns zero on success, else a negative error code.
|
||||
**/
|
||||
static int rk1608_download_fw(struct spi_device *spi, const char *fw_name);
|
||||
|
||||
/**
|
||||
* rk1608_msq_read_head - read rk1608 msg queue head
|
||||
*
|
||||
* @spi: spi device
|
||||
* @addr: msg queue head addr
|
||||
* @m: msg queue pointer
|
||||
*
|
||||
* It returns zero on success, else a negative error code.
|
||||
*/
|
||||
static int rk1608_msq_read_head(struct spi_device *spi,
|
||||
u32 addr, struct rk1608_msg_queue *q);
|
||||
|
||||
/**
|
||||
* rk1608_msq_recv_msg - receive a msg from RK1608 -> AP msg queue
|
||||
*
|
||||
* @q: msg queue
|
||||
* @m: a msg pointer buf [out]
|
||||
*
|
||||
* need call rk1608_msq_free_received_msg to free msg after msg use done
|
||||
*
|
||||
* It returns zero on success, else a negative error code.
|
||||
*/
|
||||
static int rk1608_msq_recv_msg(struct spi_device *spi, struct msg **m);
|
||||
#endif
|
||||
532
drivers/media/spi/rk1608_dphy.c
Normal file
532
drivers/media/spi/rk1608_dphy.c
Normal file
@@ -0,0 +1,532 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/**
|
||||
* Rockchip rk1608 driver
|
||||
*
|
||||
* Copyright (C) 2017-2018 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/rk-preisp.h>
|
||||
#include <linux/rkisp1-config.h>
|
||||
#include "rk1608_dphy.h"
|
||||
|
||||
/**
|
||||
* Rk1608 is used as the Pre-ISP to link on Soc, which mainly has two
|
||||
* functions. One is to download the firmware of RK1608, and the other
|
||||
* is to match the extra sensor such as camera and enable sensor by
|
||||
* calling sensor's s_power.
|
||||
* |-----------------------|
|
||||
* | Sensor Camera |
|
||||
* |-----------------------|
|
||||
* |-----------||----------|
|
||||
* |-----------||----------|
|
||||
* |-----------\/----------|
|
||||
* | Pre-ISP RK1608 |
|
||||
* |-----------------------|
|
||||
* |-----------||----------|
|
||||
* |-----------||----------|
|
||||
* |-----------\/----------|
|
||||
* | Rockchip Soc |
|
||||
* |-----------------------|
|
||||
* Data Transfer As shown above. In RK1608, the data received from the
|
||||
* extra sensor,and it is passed to the Soc through ISP.
|
||||
*/
|
||||
|
||||
static inline struct rk1608_dphy *to_state(struct v4l2_subdev *sd)
|
||||
{
|
||||
return container_of(sd, struct rk1608_dphy, sd);
|
||||
}
|
||||
|
||||
static int rk1608_s_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
{
|
||||
struct v4l2_ctrl *remote_ctrl;
|
||||
struct rk1608_dphy *pdata = to_state(sd);
|
||||
|
||||
pdata->rk1608_sd->grp_id = pdata->sd.grp_id;
|
||||
remote_ctrl = v4l2_ctrl_find(pdata->rk1608_sd->ctrl_handler,
|
||||
V4L2_CID_HBLANK);
|
||||
if (remote_ctrl) {
|
||||
v4l2_ctrl_g_ctrl(remote_ctrl);
|
||||
__v4l2_ctrl_modify_range(pdata->hblank,
|
||||
remote_ctrl->minimum,
|
||||
remote_ctrl->maximum,
|
||||
remote_ctrl->step,
|
||||
remote_ctrl->default_value);
|
||||
}
|
||||
|
||||
remote_ctrl = v4l2_ctrl_find(pdata->rk1608_sd->ctrl_handler,
|
||||
V4L2_CID_VBLANK);
|
||||
if (remote_ctrl) {
|
||||
v4l2_ctrl_g_ctrl(remote_ctrl);
|
||||
__v4l2_ctrl_modify_range(pdata->vblank,
|
||||
remote_ctrl->minimum,
|
||||
remote_ctrl->maximum,
|
||||
remote_ctrl->step,
|
||||
remote_ctrl->default_value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk1608_s_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
{
|
||||
struct rk1608_dphy *pdata = to_state(sd);
|
||||
|
||||
pdata->rk1608_sd->grp_id = sd->grp_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk1608_sensor_power(struct v4l2_subdev *sd, int on)
|
||||
{
|
||||
int ret = 0;
|
||||
struct rk1608_dphy *pdata = to_state(sd);
|
||||
|
||||
pdata->rk1608_sd->grp_id = sd->grp_id;
|
||||
ret = v4l2_subdev_call(pdata->rk1608_sd, core, s_power, on);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk1608_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
{
|
||||
struct rk1608_dphy *pdata = to_state(sd);
|
||||
|
||||
pdata->rk1608_sd->grp_id = sd->grp_id;
|
||||
v4l2_subdev_call(pdata->rk1608_sd, video, s_stream, enable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk1608_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_pad_config *cfg,
|
||||
struct v4l2_subdev_mbus_code_enum *code)
|
||||
{
|
||||
struct rk1608_dphy *pdata = to_state(sd);
|
||||
|
||||
if (code->index > 0)
|
||||
return -EINVAL;
|
||||
|
||||
code->code = pdata->mf.code;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk1608_get_fmt(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_pad_config *cfg,
|
||||
struct v4l2_subdev_format *fmt)
|
||||
{
|
||||
struct v4l2_mbus_framefmt *mf = &fmt->format;
|
||||
struct rk1608_dphy *pdata = to_state(sd);
|
||||
|
||||
mf->code = pdata->mf.code;
|
||||
mf->width = pdata->mf.width;
|
||||
mf->height = pdata->mf.height;
|
||||
mf->field = pdata->mf.field;
|
||||
mf->colorspace = pdata->mf.colorspace;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk1608_set_fmt(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_pad_config *cfg,
|
||||
struct v4l2_subdev_format *fmt)
|
||||
{
|
||||
struct v4l2_ctrl *remote_ctrl;
|
||||
struct rk1608_dphy *pdata = to_state(sd);
|
||||
|
||||
pdata->rk1608_sd->grp_id = pdata->sd.grp_id;
|
||||
remote_ctrl = v4l2_ctrl_find(pdata->rk1608_sd->ctrl_handler,
|
||||
V4L2_CID_HBLANK);
|
||||
if (remote_ctrl) {
|
||||
v4l2_ctrl_g_ctrl(remote_ctrl);
|
||||
__v4l2_ctrl_modify_range(pdata->hblank,
|
||||
remote_ctrl->minimum,
|
||||
remote_ctrl->maximum,
|
||||
remote_ctrl->step,
|
||||
remote_ctrl->default_value);
|
||||
}
|
||||
|
||||
remote_ctrl = v4l2_ctrl_find(pdata->rk1608_sd->ctrl_handler,
|
||||
V4L2_CID_VBLANK);
|
||||
if (remote_ctrl) {
|
||||
v4l2_ctrl_g_ctrl(remote_ctrl);
|
||||
__v4l2_ctrl_modify_range(pdata->vblank,
|
||||
remote_ctrl->minimum,
|
||||
remote_ctrl->maximum,
|
||||
remote_ctrl->step,
|
||||
remote_ctrl->default_value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk1608_g_frame_interval(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_frame_interval *fi)
|
||||
{
|
||||
struct rk1608_dphy *pdata = to_state(sd);
|
||||
|
||||
pdata->rk1608_sd->grp_id = sd->grp_id;
|
||||
v4l2_subdev_call(pdata->rk1608_sd,
|
||||
video,
|
||||
g_frame_interval,
|
||||
fi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long rk1608_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
{
|
||||
struct rk1608_dphy *pdata = to_state(sd);
|
||||
long ret;
|
||||
|
||||
switch (cmd) {
|
||||
case PREISP_CMD_SAVE_HDRAE_PARAM:
|
||||
case PREISP_CMD_SET_HDRAE_EXP:
|
||||
pdata->rk1608_sd->grp_id = pdata->sd.grp_id;
|
||||
ret = v4l2_subdev_call(pdata->rk1608_sd, core, ioctl,
|
||||
cmd, arg);
|
||||
return ret;
|
||||
}
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long rk1608_compat_ioctl32(struct v4l2_subdev *sd,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
void __user *up = compat_ptr(arg);
|
||||
struct preisp_hdrae_exp_s hdrae_exp;
|
||||
|
||||
switch (cmd) {
|
||||
case PREISP_CMD_SET_HDRAE_EXP:
|
||||
if (copy_from_user(&hdrae_exp, up, sizeof(hdrae_exp)))
|
||||
return -EFAULT;
|
||||
|
||||
return rk1608_ioctl(sd, cmd, &hdrae_exp);
|
||||
}
|
||||
|
||||
return -ENOTTY;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int rk1608_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
struct v4l2_ctrl *remote_ctrl;
|
||||
struct rk1608_dphy *pdata =
|
||||
container_of(ctrl->handler,
|
||||
struct rk1608_dphy, ctrl_handler);
|
||||
|
||||
pdata->rk1608_sd->grp_id = pdata->sd.grp_id;
|
||||
remote_ctrl = v4l2_ctrl_find(pdata->rk1608_sd->ctrl_handler,
|
||||
ctrl->id);
|
||||
if (remote_ctrl) {
|
||||
ctrl->val = v4l2_ctrl_g_ctrl(remote_ctrl);
|
||||
__v4l2_ctrl_modify_range(ctrl,
|
||||
remote_ctrl->minimum,
|
||||
remote_ctrl->maximum,
|
||||
remote_ctrl->step,
|
||||
remote_ctrl->default_value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk1608_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
int ret = 0;
|
||||
struct v4l2_ctrl *remote_ctrl;
|
||||
struct rk1608_dphy *pdata =
|
||||
container_of(ctrl->handler,
|
||||
struct rk1608_dphy, ctrl_handler);
|
||||
|
||||
pdata->rk1608_sd->grp_id = pdata->sd.grp_id;
|
||||
remote_ctrl = v4l2_ctrl_find(pdata->rk1608_sd->ctrl_handler,
|
||||
ctrl->id);
|
||||
if (remote_ctrl)
|
||||
ret = v4l2_ctrl_s_ctrl(remote_ctrl, ctrl->val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct v4l2_ctrl_ops rk1608_ctrl_ops = {
|
||||
.g_volatile_ctrl = rk1608_g_volatile_ctrl,
|
||||
.s_ctrl = rk1608_set_ctrl,
|
||||
};
|
||||
|
||||
static const struct v4l2_ctrl_config rk1608_priv_ctrls[] = {
|
||||
{
|
||||
.ops = NULL,
|
||||
.id = CIFISP_CID_EMB_VC,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Embedded visual channel",
|
||||
.min = 0,
|
||||
.max = 3,
|
||||
.def = 0,
|
||||
.step = 1,
|
||||
}, {
|
||||
.ops = NULL,
|
||||
.id = CIFISP_CID_EMB_DT,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Embedded data type",
|
||||
.min = 0,
|
||||
.max = 0xff,
|
||||
.def = 0x30,
|
||||
.step = 1,
|
||||
}
|
||||
};
|
||||
|
||||
static int rk1608_initialize_controls(struct rk1608_dphy *dphy)
|
||||
{
|
||||
u32 i;
|
||||
int ret;
|
||||
s64 pixel_rate, pixel_bit;
|
||||
struct v4l2_ctrl_handler *handler;
|
||||
unsigned long flags = V4L2_CTRL_FLAG_VOLATILE |
|
||||
V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
|
||||
|
||||
handler = &dphy->ctrl_handler;
|
||||
ret = v4l2_ctrl_handler_init(handler, 8);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dphy->link_freq = v4l2_ctrl_new_int_menu(handler, NULL,
|
||||
V4L2_CID_LINK_FREQ, 0,
|
||||
0, &dphy->link_freqs);
|
||||
if (dphy->link_freq)
|
||||
dphy->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
|
||||
|
||||
switch (dphy->data_type) {
|
||||
case 0x2b:
|
||||
pixel_bit = 10;
|
||||
break;
|
||||
case 0x2c:
|
||||
pixel_bit = 12;
|
||||
break;
|
||||
default:
|
||||
pixel_bit = 8;
|
||||
break;
|
||||
}
|
||||
pixel_rate = V4L2_CID_LINK_FREQ * dphy->mipi_lane * 2 / pixel_bit;
|
||||
dphy->pixel_rate = v4l2_ctrl_new_std(handler, NULL,
|
||||
V4L2_CID_PIXEL_RATE,
|
||||
0, pixel_rate, 1, pixel_rate);
|
||||
|
||||
dphy->hblank = v4l2_ctrl_new_std(handler,
|
||||
&rk1608_ctrl_ops,
|
||||
V4L2_CID_HBLANK,
|
||||
0, 0x7FFFFFFF, 1, 0);
|
||||
if (dphy->hblank)
|
||||
dphy->hblank->flags |= flags;
|
||||
|
||||
dphy->vblank = v4l2_ctrl_new_std(handler,
|
||||
&rk1608_ctrl_ops,
|
||||
V4L2_CID_VBLANK,
|
||||
0, 0x7FFFFFFF, 1, 0);
|
||||
if (dphy->vblank)
|
||||
dphy->vblank->flags |= flags;
|
||||
|
||||
dphy->exposure = v4l2_ctrl_new_std(handler,
|
||||
&rk1608_ctrl_ops,
|
||||
V4L2_CID_EXPOSURE,
|
||||
0, 0x7FFFFFFF, 1, 0);
|
||||
if (dphy->exposure)
|
||||
dphy->exposure->flags |= flags;
|
||||
|
||||
dphy->gain = v4l2_ctrl_new_std(handler,
|
||||
&rk1608_ctrl_ops,
|
||||
V4L2_CID_ANALOGUE_GAIN,
|
||||
0, 0x7FFFFFFF, 1, 0);
|
||||
if (dphy->gain)
|
||||
dphy->gain->flags |= flags;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rk1608_priv_ctrls); i++)
|
||||
v4l2_ctrl_new_custom(handler, &rk1608_priv_ctrls[i], NULL);
|
||||
|
||||
if (handler->error) {
|
||||
ret = handler->error;
|
||||
dev_err(dphy->dev,
|
||||
"Failed to init controls(%d)\n", ret);
|
||||
goto err_free_handler;
|
||||
}
|
||||
|
||||
dphy->sd.ctrl_handler = handler;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_handler:
|
||||
v4l2_ctrl_handler_free(handler);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct v4l2_subdev_internal_ops dphy_subdev_internal_ops = {
|
||||
.open = rk1608_s_open,
|
||||
.close = rk1608_s_close,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_video_ops rk1608_subdev_video_ops = {
|
||||
.s_stream = rk1608_s_stream,
|
||||
.g_frame_interval = rk1608_g_frame_interval,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_pad_ops rk1608_subdev_pad_ops = {
|
||||
.enum_mbus_code = rk1608_enum_mbus_code,
|
||||
.get_fmt = rk1608_get_fmt,
|
||||
.set_fmt = rk1608_set_fmt,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_core_ops rk1608_core_ops = {
|
||||
.s_power = rk1608_sensor_power,
|
||||
.ioctl = rk1608_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl32 = rk1608_compat_ioctl32,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_ops dphy_subdev_ops = {
|
||||
.core = &rk1608_core_ops,
|
||||
.video = &rk1608_subdev_video_ops,
|
||||
.pad = &rk1608_subdev_pad_ops,
|
||||
};
|
||||
|
||||
static int rk1608_dphy_dt_property(struct rk1608_dphy *dphy)
|
||||
{
|
||||
int ret = 0;
|
||||
struct device_node *node = dphy->dev->of_node;
|
||||
|
||||
ret = of_property_read_u32(node, "id", &dphy->sd.grp_id);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get id!");
|
||||
ret = of_property_read_u32(node, "cam_nums", &dphy->cam_nums);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get cam_nums!");
|
||||
ret = of_property_read_u32(node, "data_type", &dphy->data_type);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get data_type!");
|
||||
ret = of_property_read_u32(node, "in_mipi", &dphy->in_mipi);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get in_mipi!");
|
||||
ret = of_property_read_u32(node, "out_mipi", &dphy->out_mipi);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get out_mipi!");
|
||||
ret = of_property_read_u32(node, "mipi_lane", &dphy->mipi_lane);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get mipi_lane!");
|
||||
ret = of_property_read_u32(node, "field", &dphy->mf.field);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get field!");
|
||||
ret = of_property_read_u32(node, "colorspace", &dphy->mf.colorspace);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get colorspace!");
|
||||
ret = of_property_read_u32(node, "code", &dphy->mf.code);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get code!");
|
||||
ret = of_property_read_u32(node, "width", &dphy->mf.width);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get width!");
|
||||
ret = of_property_read_u32(node, "height", &dphy->mf.height);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get height!");
|
||||
ret = of_property_read_u32(node, "htotal", &dphy->htotal);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get htotal!");
|
||||
ret = of_property_read_u32(node, "vtotal", &dphy->vtotal);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get vtotal!");
|
||||
ret = of_property_read_u64(node, "link-freqs", &dphy->link_freqs);
|
||||
if (ret)
|
||||
dev_warn(dphy->dev, "Can not get link_freqs!");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk1608_dphy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rk1608_dphy *dphy;
|
||||
struct v4l2_subdev *sd;
|
||||
int ret = 0;
|
||||
|
||||
dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
|
||||
if (!dphy)
|
||||
return -ENOMEM;
|
||||
dphy->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, dphy);
|
||||
sd = &dphy->sd;
|
||||
sd->dev = &pdev->dev;
|
||||
v4l2_subdev_init(sd, &dphy_subdev_ops);
|
||||
rk1608_dphy_dt_property(dphy);
|
||||
|
||||
snprintf(sd->name, sizeof(sd->name), "RK1608-dphy%d", sd->grp_id);
|
||||
rk1608_initialize_controls(dphy);
|
||||
sd->internal_ops = &dphy_subdev_internal_ops;
|
||||
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
dphy->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||
sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
|
||||
|
||||
ret = media_entity_init(&sd->entity, 1, &dphy->pad, 0);
|
||||
if (ret < 0)
|
||||
goto handler_err;
|
||||
ret = v4l2_async_register_subdev(sd);
|
||||
if (ret < 0)
|
||||
goto register_err;
|
||||
|
||||
dev_info(dphy->dev, "RK1608-dphy(%d) probe success!\n", sd->grp_id);
|
||||
|
||||
return 0;
|
||||
register_err:
|
||||
media_entity_cleanup(&sd->entity);
|
||||
handler_err:
|
||||
v4l2_ctrl_handler_free(dphy->sd.ctrl_handler);
|
||||
devm_kfree(&pdev->dev, dphy);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk1608_dphy_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rk1608_dphy *dphy = platform_get_drvdata(pdev);
|
||||
|
||||
v4l2_async_unregister_subdev(&dphy->sd);
|
||||
media_entity_cleanup(&dphy->sd.entity);
|
||||
v4l2_ctrl_handler_free(&dphy->ctrl_handler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id dphy_of_match[] = {
|
||||
{ .compatible = "rockchip,rk1608-dphy" },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, rk1608_of_match);
|
||||
|
||||
static struct platform_driver rk1608_dphy_drv = {
|
||||
.driver = {
|
||||
.of_match_table = of_match_ptr(dphy_of_match),
|
||||
.name = "RK1608-dphy",
|
||||
},
|
||||
.probe = rk1608_dphy_probe,
|
||||
.remove = rk1608_dphy_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(rk1608_dphy_drv);
|
||||
|
||||
MODULE_AUTHOR("Rockchip Camera/ISP team");
|
||||
MODULE_DESCRIPTION("A DSP driver for rk1608 chip");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
25
drivers/media/spi/rk1608_dphy.h
Normal file
25
drivers/media/spi/rk1608_dphy.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
struct rk1608_dphy {
|
||||
struct v4l2_subdev sd;
|
||||
struct v4l2_subdev *rk1608_sd;
|
||||
struct platform_device *pdev;
|
||||
struct device *dev;
|
||||
struct media_pad pad;
|
||||
struct v4l2_mbus_framefmt mf;
|
||||
struct v4l2_ctrl *link_freq;
|
||||
struct v4l2_ctrl *pixel_rate;
|
||||
struct v4l2_ctrl *hblank;
|
||||
struct v4l2_ctrl *vblank;
|
||||
struct v4l2_ctrl *exposure;
|
||||
struct v4l2_ctrl *gain;
|
||||
struct v4l2_ctrl_handler ctrl_handler;
|
||||
u32 cam_nums;
|
||||
u32 in_mipi;
|
||||
u32 out_mipi;
|
||||
u32 mipi_lane;
|
||||
u32 data_type;
|
||||
u32 htotal;
|
||||
u32 vtotal;
|
||||
s64 link_freqs;
|
||||
};
|
||||
56
include/uapi/linux/rk-preisp.h
Normal file
56
include/uapi/linux/rk-preisp.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* SPDX-License-Identifier: ((GPL-2.0+ WITH Linux-syscall-note) OR MIT) */
|
||||
/*
|
||||
* Rockchip preisp driver
|
||||
* Copyright (C) 2018 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef _UAPI_RKPREISP_H
|
||||
#define _UAPI_RKPREISP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define PREISP_LSCTBL_SIZE 289
|
||||
|
||||
#define PREISP_CMD_SET_HDRAE_EXP \
|
||||
_IOW('V', BASE_VIDIOC_PRIVATE + 0, struct preisp_hdrae_exp_s)
|
||||
|
||||
#define PREISP_CMD_SAVE_HDRAE_PARAM \
|
||||
_IOW('V', BASE_VIDIOC_PRIVATE + 1, struct preisp_hdrae_para_s)
|
||||
|
||||
/**
|
||||
* struct preisp_hdrae_para_s - awb and lsc para for preisp
|
||||
*
|
||||
* @r_gain: awb r gain
|
||||
* @b_gain: awb b gain
|
||||
* @gr_gain: awb gr gain
|
||||
* @gb_gain: awb gb gain
|
||||
* @lsc_table: lsc data of gr
|
||||
*/
|
||||
struct preisp_hdrae_para_s {
|
||||
unsigned short r_gain;
|
||||
unsigned short b_gain;
|
||||
unsigned short gr_gain;
|
||||
unsigned short gb_gain;
|
||||
int lsc_table[PREISP_LSCTBL_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct preisp_hdrae_exp_s - hdrae exposure
|
||||
*
|
||||
*/
|
||||
struct preisp_hdrae_exp_s {
|
||||
unsigned int long_exp_reg;
|
||||
unsigned int long_gain_reg;
|
||||
unsigned int middle_exp_reg;
|
||||
unsigned int middle_gain_reg;
|
||||
unsigned int short_exp_reg;
|
||||
unsigned int short_gain_reg;
|
||||
unsigned int long_exp_val;
|
||||
unsigned int long_gain_val;
|
||||
unsigned int middle_exp_val;
|
||||
unsigned int middle_gain_val;
|
||||
unsigned int short_exp_val;
|
||||
unsigned int short_gain_val;
|
||||
};
|
||||
|
||||
#endif /* _UAPI_RKPREISP_H */
|
||||
Reference in New Issue
Block a user