Merge commit 'dddd9eb669ee835e62a13c1ac6703efa77776fb2'

* commit 'dddd9eb669ee835e62a13c1ac6703efa77776fb2':
  drm/rockchip: vop2: Clear vcstate output_type when crtc disable
  ARM: dts: rockchip: rk3506: Set mac_ptp_ref clocks rate 62.5M defaultly
  firmware: rockchip_sip: allocate a separate stack for fiq-debugger callback
  firmware: rockchip_sip: don't update fiq_target_cpu in sip_fiq_debugger_uart_irq_tf_init
  pinctrl: rockchip: add debug information when switching pinctrl to gpio.
  media: rockchip: isp: add RKISP_VICAP_CMD_SOF cmd
  include: rkcif-config: add commands to support get sensor exp
  media: i2c: imx415 support get exp info from sensor register
  include: rk-camera-module.h add cmd to get sensor exp and delay info
  ARM: dts: rockchip: rk3506g-iotest: add IR transmit mode for pwm test
  pwm: rockchip: add support for IR NEC transmit

Change-Id: I930dd167377e51bfa1027dfd667a5f687159e498
This commit is contained in:
Tao Huang
2024-12-11 20:19:35 +08:00
10 changed files with 580 additions and 7 deletions

View File

@@ -79,6 +79,9 @@
resets = <&cru SRST_A_MAC0>;
reset-names = "stmmaceth";
assigned-clocks = <&cru CLK_MAC0_PTP>;
assigned-clock-rates = <62500000>;
snps,mixed-burst;
snps,tso;
@@ -130,6 +133,9 @@
resets = <&cru SRST_A_MAC1>;
reset-names = "stmmaceth";
assigned-clocks = <&cru CLK_MAC1_PTP>;
assigned-clock-rates = <62500000>;
snps,mixed-burst;
snps,tso;

View File

@@ -3,6 +3,7 @@
* Copyright (c) 2024 Rockchip Electronics Co., Ltd.
*/
#ifndef IR_TRANSMIT_TEST
/ {
pwm_rockchip_test: pwm-rockchip-test {
compatible = "pwm-rockchip-test";
@@ -32,6 +33,7 @@
"pwm1_7";
};
};
#endif
/* use GPIO0_B0 ~ GPIO0_C3(rm_io8 ~ rm_io19) by default */
&pwm0_4ch_0 {
@@ -159,3 +161,37 @@
assigned-clock-rates = <100000000>;
};
#endif
#ifdef IR_TRANSMIT_TEST
&pwm1_8ch_0 {
rockchip,pwm-ir-transmit;
};
&pwm1_8ch_1 {
rockchip,pwm-ir-transmit;
};
&pwm1_8ch_2 {
rockchip,pwm-ir-transmit;
};
&pwm1_8ch_3 {
rockchip,pwm-ir-transmit;
};
&pwm1_8ch_4 {
rockchip,pwm-ir-transmit;
};
&pwm1_8ch_5 {
rockchip,pwm-ir-transmit;
};
&pwm1_8ch_6 {
rockchip,pwm-ir-transmit;
};
&pwm1_8ch_7 {
rockchip,pwm-ir-transmit;
};
#endif

View File

@@ -366,13 +366,17 @@ EXPORT_SYMBOL_GPL(sip_hdcp_config);
*/
#ifdef CONFIG_ARM64
#define SIP_UARTDBG_FN SIP_UARTDBG_CFG64
#define SIP_FIQ_DBG_STACK_SIZE IRQ_STACK_SIZE
#else
#define SIP_UARTDBG_FN SIP_UARTDBG_CFG
#define SIP_FIQ_DBG_STACK_SIZE SZ_8K
static int firmware_64_32bit;
#endif
static int fiq_sip_enabled;
static int fiq_target_cpu;
static unsigned long fiq_stack_top;
static phys_addr_t ft_fiq_mem_phy;
static void __iomem *ft_fiq_mem_base;
static sip_fiq_debugger_uart_irq_tf_cb_t sip_fiq_debugger_uart_irq_tf;
@@ -481,13 +485,26 @@ int sip_fiq_debugger_uart_irq_tf_init(u32 irq_id, sip_fiq_debugger_uart_irq_tf_c
{
struct arm_smccc_res res;
fiq_target_cpu = 0;
/* Alloc a page for fiq_debugger's stack */
if (fiq_stack_top == 0) {
fiq_stack_top = __get_free_pages(GFP_KERNEL | __GFP_ZERO,
get_order(SIP_FIQ_DBG_STACK_SIZE));
if (fiq_stack_top) {
fiq_stack_top += SIP_FIQ_DBG_STACK_SIZE;
} else {
pr_err("%s: alloc stack failed\n", __func__);
return -ENOMEM;
}
}
/* init fiq debugger callback */
sip_fiq_debugger_uart_irq_tf = callback_fn;
res = __invoke_sip_fn_smc(SIP_UARTDBG_FN, irq_id,
(unsigned long)sip_fiq_debugger_uart_irq_tf_cb,
UARTDBG_CFG_INIT);
arm_smccc_smc(SIP_UARTDBG_FN,
irq_id,
(unsigned long)sip_fiq_debugger_uart_irq_tf_cb,
UARTDBG_CFG_INIT,
fiq_stack_top, 0, 0, 0, &res);
if (IS_SIP_ERROR(res.a0)) {
pr_err("%s error: %d\n", __func__, (int)res.a0);
return res.a0;

View File

@@ -5267,6 +5267,7 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
vop2->active_display_mask &= ~BIT(vp->id);
vcstate->splice_mode = false;
vcstate->output_flags = 0;
vcstate->output_type = 0;
vp->splice_mode_right = false;
vp->loader_protect = false;
splice_vp->splice_mode_right = false;

View File

@@ -247,6 +247,11 @@ struct imx415 {
struct cam_sw_info *cam_sw_inf;
int rhs1_old;
int rhs2_old;
u32 cur_exposure[3];
u32 cur_gain[3];
u32 pclk;
u32 tline;
bool is_tline_init;
};
static struct rkmodule_csi_dphy_param dcphy_param = {
@@ -1626,6 +1631,123 @@ static void imx415_get_module_inf(struct imx415 *imx415,
strlcpy(inf->base.lens, imx415->len_name, sizeof(inf->base.lens));
}
static void imx415_get_pclk_and_tline(struct imx415 *imx415)
{
const struct imx415_mode *mode = imx415->cur_mode;
imx415->pclk = (u32)div_u64((u64)mode->hts_def * mode->vts_def *
mode->max_fps.denominator, mode->max_fps.numerator);
imx415->tline = (u32)div_u64((u64)mode->hts_def * 1000000000, imx415->pclk);
}
static void imx415_hdr_exposure_readback(struct imx415 *imx415)
{
u32 shr, shr_l, shr_m, shr_h;
u32 rhs, rhs_l, rhs_m, rhs_h;
u32 gain, gain_l, gain_h;
int ret = 0;
if (!imx415->is_tline_init) {
imx415_get_pclk_and_tline(imx415);
imx415->is_tline_init = true;
}
ret = imx415_read_reg(imx415->client, IMX415_LF_EXPO_REG_L,
IMX415_REG_VALUE_08BIT, &shr_l);
ret |= imx415_read_reg(imx415->client, IMX415_LF_EXPO_REG_M,
IMX415_REG_VALUE_08BIT, &shr_m);
ret |= imx415_read_reg(imx415->client, IMX415_LF_EXPO_REG_H,
IMX415_REG_VALUE_08BIT, &shr_h);
if (!ret) {
shr = (shr_h << 16) | (shr_m << 8) | shr_l;
imx415->cur_exposure[0] = (imx415->cur_vts - shr) * imx415->tline;
} else {
dev_err(&imx415->client->dev,
"imx415 get exposure of long frame failed!\n");
}
ret = imx415_read_reg(imx415->client, IMX415_LF_GAIN_REG_H,
IMX415_REG_VALUE_08BIT, &gain_h);
ret |= imx415_read_reg(imx415->client, IMX415_LF_GAIN_REG_L,
IMX415_REG_VALUE_08BIT, &gain_l);
if (!ret) {
gain = (gain_h << 8) | gain_l;
imx415->cur_gain[0] = gain * 300;//step=0.3db,factor=1000
} else {
dev_err(&imx415->client->dev,
"imx415 get gain of long frame failed!\n");
}
ret = imx415_read_reg(imx415->client, IMX415_SF1_EXPO_REG_L,
IMX415_REG_VALUE_08BIT, &shr_l);
ret |= imx415_read_reg(imx415->client, IMX415_SF1_EXPO_REG_M,
IMX415_REG_VALUE_08BIT, &shr_m);
ret |= imx415_read_reg(imx415->client, IMX415_SF1_EXPO_REG_H,
IMX415_REG_VALUE_08BIT, &shr_h);
ret |= imx415_read_reg(imx415->client, IMX415_RHS1_REG_L,
IMX415_REG_VALUE_08BIT, &rhs_l);
ret |= imx415_read_reg(imx415->client, IMX415_RHS1_REG_M,
IMX415_REG_VALUE_08BIT, &rhs_m);
ret |= imx415_read_reg(imx415->client, IMX415_RHS1_REG_H,
IMX415_REG_VALUE_08BIT, &rhs_h);
if (!ret) {
shr = (shr_h << 16) | (shr_m << 8) | shr_l;
rhs = (rhs_h << 16) | (rhs_m << 8) | rhs_l;
imx415->cur_exposure[1] = (rhs - shr) * imx415->tline;
} else {
dev_err(&imx415->client->dev,
"imx415 get exposure of %s frame failed!\n",
imx415->cur_mode->hdr_mode == HDR_X2 ?
"short" : "middle");
}
ret = imx415_read_reg(imx415->client, IMX415_SF1_GAIN_REG_H,
IMX415_REG_VALUE_08BIT, &gain_h);
ret |= imx415_read_reg(imx415->client, IMX415_SF1_GAIN_REG_L,
IMX415_REG_VALUE_08BIT, &gain_l);
if (!ret) {
gain = (gain_h << 8) | gain_l;
imx415->cur_gain[1] = gain * 300;//step=0.3db,factor=1000
} else {
dev_err(&imx415->client->dev,
"imx415 get gain of %s frame failed!\n",
imx415->cur_mode->hdr_mode == HDR_X2 ?
"short" : "middle");
}
if (imx415->cur_mode->hdr_mode == HDR_X3) {
ret = imx415_read_reg(imx415->client, IMX415_SF2_EXPO_REG_L,
IMX415_REG_VALUE_08BIT, &shr_l);
ret |= imx415_read_reg(imx415->client, IMX415_SF2_EXPO_REG_M,
IMX415_REG_VALUE_08BIT, &shr_m);
ret |= imx415_read_reg(imx415->client, IMX415_SF2_EXPO_REG_H,
IMX415_REG_VALUE_08BIT, &shr_h);
ret |= imx415_read_reg(imx415->client, IMX415_RHS2_REG_L,
IMX415_REG_VALUE_08BIT, &rhs_l);
ret |= imx415_read_reg(imx415->client, IMX415_RHS2_REG_M,
IMX415_REG_VALUE_08BIT, &rhs_m);
ret |= imx415_read_reg(imx415->client, IMX415_RHS2_REG_H,
IMX415_REG_VALUE_08BIT, &rhs_h);
if (!ret) {
shr = (shr_h << 16) | (shr_m << 8) | shr_l;
rhs = (rhs_h << 16) | (rhs_m << 8) | rhs_l;
imx415->cur_exposure[2] = (rhs - shr) * imx415->tline;
} else {
dev_err(&imx415->client->dev,
"imx415 get exposure of short frame failed!\n");
}
ret = imx415_read_reg(imx415->client, IMX415_SF2_GAIN_REG_H,
IMX415_REG_VALUE_08BIT, &gain_h);
ret |= imx415_read_reg(imx415->client, IMX415_SF2_GAIN_REG_L,
IMX415_REG_VALUE_08BIT, &gain_l);
if (!ret) {
gain = (gain_h << 8) | gain_l;
imx415->cur_gain[2] = gain * 300;//step=0.3db,factor=1000
} else {
dev_err(&imx415->client->dev,
"imx415 get gain of short frame failed!\n");
}
}
}
static int imx415_set_hdrae_3frame(struct imx415 *imx415,
struct preisp_hdrae_exp_s *ae)
{
@@ -1877,6 +1999,7 @@ static int imx415_set_hdrae_3frame(struct imx415 *imx415,
ret |= imx415_write_reg(client, IMX415_GROUP_HOLD_REG,
IMX415_REG_VALUE_08BIT, IMX415_GROUP_HOLD_END);
imx415_hdr_exposure_readback(imx415);
return ret;
}
@@ -2035,6 +2158,7 @@ static int imx415_set_hdrae(struct imx415 *imx415,
ret |= imx415_write_reg(client, IMX415_GROUP_HOLD_REG,
IMX415_REG_VALUE_08BIT, IMX415_GROUP_HOLD_END);
imx415_hdr_exposure_readback(imx415);
return ret;
}
@@ -2060,6 +2184,9 @@ static long imx415_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
u64 pixel_rate = 0;
struct rkmodule_csi_dphy_param *dphy_param;
u8 lanes = imx415->bus_cfg.bus.mipi_csi2.num_data_lanes;
struct rkmodule_exp_delay *exp_delay;
struct rkmodule_exp_info *exp_info;
int idx_max = 0;
switch (cmd) {
case PREISP_CMD_SET_HDRAE_EXP:
@@ -2152,6 +2279,30 @@ static long imx415_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
} else
ret = -EINVAL;
break;
case RKMODULE_GET_EXP_DELAY:
exp_delay = (struct rkmodule_exp_delay *)arg;
exp_delay->exp_delay = 2;
exp_delay->gain_delay = 2;
exp_delay->vts_delay = 1;
break;
case RKMODULE_GET_EXP_INFO:
exp_info = (struct rkmodule_exp_info *)arg;
if (imx415->cur_mode->hdr_mode == NO_HDR)
idx_max = 1;
else if (imx415->cur_mode->hdr_mode == HDR_X2)
idx_max = 2;
else
idx_max = 3;
for (i = 0; i < idx_max; i++) {
exp_info->exp[i] = imx415->cur_exposure[i];
exp_info->gain[i] = imx415->cur_gain[i];
}
exp_info->hts = imx415->cur_mode->hts_def;
exp_info->vts = imx415->cur_vts;
exp_info->pclk = imx415->pclk;
exp_info->gain_mode.gain_mode = RKMODULE_GAIN_MODE_DB;
exp_info->gain_mode.factor = 1000;
break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -2174,6 +2325,8 @@ static long imx415_compat_ioctl32(struct v4l2_subdev *sd,
u32 stream;
u32 brl = 0;
struct rkmodule_csi_dphy_param *dphy_param;
struct rkmodule_exp_delay *exp_delay;
struct rkmodule_exp_info *exp_info;
switch (cmd) {
case RKMODULE_GET_MODULE_INFO:
@@ -2292,7 +2445,36 @@ static long imx415_compat_ioctl32(struct v4l2_subdev *sd,
}
kfree(dphy_param);
break;
case RKMODULE_GET_EXP_DELAY:
exp_delay = kzalloc(sizeof(*exp_delay), GFP_KERNEL);
if (!exp_delay) {
ret = -ENOMEM;
return ret;
}
ret = imx415_ioctl(sd, cmd, exp_delay);
if (!ret) {
ret = copy_to_user(up, exp_delay, sizeof(*exp_delay));
if (ret)
ret = -EFAULT;
}
kfree(exp_delay);
break;
case RKMODULE_GET_EXP_INFO:
exp_info = kzalloc(sizeof(*exp_info), GFP_KERNEL);
if (!exp_info) {
ret = -ENOMEM;
return ret;
}
ret = imx415_ioctl(sd, cmd, exp_info);
if (!ret) {
ret = copy_to_user(up, exp_info, sizeof(*exp_info));
if (ret)
ret = -EFAULT;
}
kfree(exp_info);
break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -2302,7 +2484,6 @@ static long imx415_compat_ioctl32(struct v4l2_subdev *sd,
}
#endif
static int __imx415_start_stream(struct imx415 *imx415)
{
int ret;
@@ -2315,6 +2496,7 @@ static int __imx415_start_stream(struct imx415 *imx415)
if (ret)
return ret;
}
imx415_get_pclk_and_tline(imx415);
/* In case these controls are set before streaming */
ret = __v4l2_ctrl_handler_setup(&imx415->ctrl_handler);
@@ -2340,6 +2522,7 @@ static int __imx415_stop_stream(struct imx415 *imx415)
imx415->has_init_exp = false;
if (imx415->is_thunderboot)
imx415->is_first_streamoff = true;
imx415->is_tline_init = false;
return imx415_write_reg(imx415->client, IMX415_REG_CTRL_MODE,
IMX415_REG_VALUE_08BIT, 1);
}
@@ -2697,6 +2880,48 @@ static const struct v4l2_subdev_ops imx415_subdev_ops = {
.pad = &imx415_pad_ops,
};
static void imx415_exposure_readback(struct imx415 *imx415)
{
u32 shr, shr_l, shr_m, shr_h;
int ret = 0;
if (!imx415->is_tline_init) {
imx415_get_pclk_and_tline(imx415);
imx415->is_tline_init = true;
}
ret = imx415_read_reg(imx415->client, IMX415_LF_EXPO_REG_L,
IMX415_REG_VALUE_08BIT, &shr_l);
ret |= imx415_read_reg(imx415->client, IMX415_LF_EXPO_REG_M,
IMX415_REG_VALUE_08BIT, &shr_m);
ret |= imx415_read_reg(imx415->client, IMX415_LF_EXPO_REG_H,
IMX415_REG_VALUE_08BIT, &shr_h);
if (!ret) {
shr = (shr_h << 16) | (shr_m << 8) | shr_l;
imx415->cur_exposure[0] = (imx415->cur_vts - shr) * imx415->tline;
}
}
static void imx415_gain_readback(struct imx415 *imx415)
{
int ret = 0;
u32 gain, gain_l, gain_h;
if (!imx415->is_tline_init) {
imx415_get_pclk_and_tline(imx415);
imx415->is_tline_init = true;
}
ret = imx415_read_reg(imx415->client, IMX415_LF_GAIN_REG_H,
IMX415_REG_VALUE_08BIT,
&gain_h);
ret |= imx415_read_reg(imx415->client, IMX415_LF_GAIN_REG_L,
IMX415_REG_VALUE_08BIT,
&gain_l);
gain = (gain_h << 8) | gain_l;
imx415->cur_gain[0] = gain * 300;//step=0.3db,factor=1000
}
static int imx415_set_ctrl(struct v4l2_ctrl *ctrl)
{
struct imx415 *imx415 = container_of(ctrl->handler,
@@ -2738,6 +2963,7 @@ static int imx415_set_ctrl(struct v4l2_ctrl *ctrl)
ret |= imx415_write_reg(imx415->client, IMX415_LF_EXPO_REG_H,
IMX415_REG_VALUE_08BIT,
IMX415_FETCH_EXP_H(shr0));
imx415_exposure_readback(imx415);
dev_dbg(&client->dev, "set exposure(shr0) %d = cur_vts(%d) - val(%d)\n",
shr0, imx415->cur_vts, ctrl->val);
break;
@@ -2750,6 +2976,7 @@ static int imx415_set_ctrl(struct v4l2_ctrl *ctrl)
ret |= imx415_write_reg(imx415->client, IMX415_LF_GAIN_REG_L,
IMX415_REG_VALUE_08BIT,
IMX415_FETCH_GAIN_L(ctrl->val));
imx415_gain_readback(imx415);
dev_dbg(&client->dev, "set analog gain 0x%x\n",
ctrl->val);
break;
@@ -2871,12 +3098,10 @@ static int imx415_initialize_controls(struct imx415 *imx415)
V4L2_CID_EXPOSURE, IMX415_EXPOSURE_MIN,
exposure_max, IMX415_EXPOSURE_STEP,
mode->exp_def);
imx415->anal_a_gain = v4l2_ctrl_new_std(handler, &imx415_ctrl_ops,
V4L2_CID_ANALOGUE_GAIN, IMX415_GAIN_MIN,
IMX415_GAIN_MAX, IMX415_GAIN_STEP,
IMX415_GAIN_DEFAULT);
v4l2_ctrl_new_std(handler, &imx415_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
v4l2_ctrl_new_std(handler, &imx415_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
@@ -2889,6 +3114,7 @@ static int imx415_initialize_controls(struct imx415 *imx415)
imx415->subdev.ctrl_handler = handler;
imx415->has_init_exp = false;
imx415->is_tline_init = false;
return 0;

View File

@@ -27,6 +27,9 @@
#define RKISP_VICAP_CMD_HW_LINK \
_IOW('V', BASE_VIDIOC_PRIVATE + 6, int)
#define RKISP_VICAP_CMD_SOF \
_IOW('V', BASE_VIDIOC_PRIVATE + 7, struct rkisp_vicap_sof)
#define RKISP_VICAP_BUF_CNT 3
#define RKISP_VICAP_BUF_CNT_MAX 8
#define RKISP_RX_BUF_POOL_MAX (RKISP_VICAP_BUF_CNT_MAX * 3)
@@ -90,4 +93,19 @@ struct rkisp_rx_buf {
bool is_uncompact;
};
struct rkisp_vicap_sof {
u64 timestamp;
u32 sequence;
u32 exp[3];
u32 gain[3];
u32 hts;
u32 vts;
u32 pclk;
__u32 dcg_used;
__u32 dcg_val[3];
struct rkmodule_dcg_ratio dcg_ratio;
struct rkmodule_gain_mode gain_mode;
bool is_exp_active;
};
#endif

View File

@@ -4238,8 +4238,19 @@ static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
{
struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
struct rockchip_pin_bank *bank;
struct pin_desc *desc;
int mux, pin = offset % 32;
static unsigned long bitmap[BITS_TO_LONGS(2048)];
bank = pin_to_bank(info, offset);
mux = rockchip_get_mux(bank, pin);
desc = pin_desc_get(pctldev, offset);
if (offset < 2048 && !test_bit(offset, bitmap) && desc->mux_owner && mux) {
set_bit(offset, bitmap);
WARN(1, "pin %u already requested by %s; switch mux %d to GPIO\n",
offset, desc->mux_owner, mux);
}
return rockchip_set_mux(bank, offset - bank->pin_base, RK_FUNC_GPIO);
}

View File

@@ -20,10 +20,13 @@
#include <linux/pwm.h>
#include <linux/pwm-rockchip.h>
#include <linux/time.h>
#include <media/rc-core.h>
#include "pwm-rockchip-irq-callbacks.h"
#define PWM_MAX_CHANNEL_NUM 8
#define PWM_IR_TRANSMIT_BUFFER_SIZE 7
/*
* regs for pwm v1-v3
*/
@@ -101,6 +104,9 @@
#define CLK_PRESCALE(v) HIWORD_UPDATE(v, 0, 2)
#define CLK_SCALE(v) HIWORD_UPDATE(v, 4, 12)
#define CLK_SRC_SEL(v) HIWORD_UPDATE(v, 13, 14)
#define SRC_CLK_PWM 0
#define SRC_CLK_PWM_OSC 1
#define SRC_CLK_PWM_RC 2
#define CLK_GLOBAL_SEL(v) HIWORD_UPDATE(v, 15, 15)
/* CTRL */
#define CTRL_V4 0xc
@@ -220,6 +226,46 @@
#define GLOBAL_CTRL 0xc4
#define GLOBAL_PWM_EN(v) HIWORD_UPDATE(v, 0, 0)
#define GLOBAL_PWM_UPDATE_EN(v) HIWORD_UPDATE(v, 1, 1)
/* IR_TRANS_ARBITER */
#define IR_TRANS_ARBITER 0x180
#define IR_TRANS_GRANT_SHIFT 0
#define IR_TRANS_READ_LOCK_SHIFT 16
/* IR_TRANS_CTRL0 */
#define IR_TRANS_CTRL0 0x184
#define IR_TRANS_OUT_ENABLE(v) HIWORD_UPDATE(v, 0, 0)
#define IR_TRANS_DUTY_POL(v) HIWORD_UPDATE(v, 1, 1)
#define IR_TRANS_INACTIVE_POL(v) HIWORD_UPDATE(v, 2, 2)
#define IR_TRANS_MODE(v) HIWORD_UPDATE(v, 3, 3)
#define IR_TRANS_FORMAT(v) HIWORD_UPDATE(v, 4, 7)
#define NEC_WITH_SIMPLE_REPEAT_CODE 0
#define NEC_WITH_FULL_REPEAT_CODE 1
#define TC9012 2
#define SONY 3
/* IR_TRANS_CTRL1 */
#define IR_TRANS_CTRL1 0x188
#define IR_TRANS_RPT(v) HIWORD_UPDATE(v, 0, 15)
/* IR_TRANS_PRE */
#define IR_TRANS_PRE 0x18c
#define IR_TRANS_OUT_LOW_PRELOAD_SHIFT 0
#define IR_TRANS_OUT_HIGH_PRELOAD_SHIFT 16
/* IR_TRANS_SPRE */
#define IR_TRANS_SPRE 0x190
#define IR_TRANS_OUT_HIGH_SIMPLE_PRELOAD_SHIFT 0
/* IR_TRANS_LD */
#define IR_TRANS_LD 0x194
#define IR_TRANS_OUT_DATA_LOW_PERIOD_SHIFT 0
/* IR_TRANS_HD */
#define IR_TRANS_HD 0x198
#define IR_TRANS_OUT_HIGH_PERIOD_FOR_ZERO_SHIFT 0
#define IR_TRANS_OUT_HIGH_PERIOD_FOR_ONE_SHIFT 16
/* IR_TRANS_BURST_FRAME */
#define IR_TRANS_BURST_FRAME 0x19c
#define IR_TRANS_OUT_FRAME_PERIOD_SHIFT 0
#define IR_TRANS_OUT_FRAME_PERIOD_MASK (0x3ffff << IR_TRANS_OUT_FRAME_PERIOD_SHIFT)
#define IR_TRANS_OUT_BURST_PERIOD_SHIFT 20
/* IR_TRANS_DATA_VALUE */
#define IR_TRANS_DATA_VALUE 0x1a0
#define IR_TRANS_OUT_VALUE_SHIFT 0
/* FREQ_ARBITER */
#define FREQ_ARBITER 0x1c0
#define FREQ_GRANT_SHIFT 0
@@ -264,6 +310,7 @@ struct rockchip_pwm_chip {
const struct rockchip_pwm_biphasic_config *biphasic_config;
struct resource *res;
struct dentry *debugfs;
struct completion ir_trans_completion;
void __iomem *base;
unsigned long clk_rate;
unsigned long is_clk_enabled;
@@ -273,6 +320,7 @@ struct rockchip_pwm_chip {
bool capture_en;
bool wave_en;
bool global_ctrl_grant;
bool ir_trans_support;
bool freq_meter_support;
bool counter_support;
bool wave_support;
@@ -322,6 +370,7 @@ struct rockchip_pwm_funcs {
struct rockchip_pwm_biphasic_config *config);
int (*get_biphasic_result)(struct pwm_chip *chip, struct pwm_device *pwm,
unsigned long *biphasic_res);
int (*ir_transmit)(struct pwm_chip *chip, unsigned int *txbuf, unsigned int count);
irqreturn_t (*irq_handler)(int irq, void *data);
};
@@ -713,6 +762,13 @@ static irqreturn_t rockchip_pwm_irq_v4(int irq, void *data)
ret = IRQ_HANDLED;
}
if (val & IR_TRANS_END_INT) {
writel_relaxed(IR_TRANS_END_INT, pc->base + INTSTS);
complete(&pc->ir_trans_completion);
ret = IRQ_HANDLED;
}
return ret;
}
@@ -1844,6 +1900,143 @@ int rockchip_pwm_get_biphasic_result(struct pwm_device *pwm, unsigned long *biph
}
EXPORT_SYMBOL_GPL(rockchip_pwm_get_biphasic_result);
#ifdef CONFIG_RC_CORE
static int rockchip_pwm_ir_transmit_v4(struct pwm_chip *chip, unsigned int *txbuf,
unsigned int count)
{
struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
u32 arbiter;
u32 preload, spreload;
u32 low_period, high_period;
u32 tx_value;
u32 timeout_ms;
u32 val;
int ret = 0;
if (count != PWM_IR_TRANSMIT_BUFFER_SIZE) {
dev_err(chip->dev, "Unsupported ir transmit buf size: %d\n", count);
return -EINVAL;
}
ret = clk_enable(pc->clk);
if (ret)
return ret;
arbiter = BIT(pc->channel_id) << IR_TRANS_READ_LOCK_SHIFT |
BIT(pc->channel_id) << IR_TRANS_GRANT_SHIFT;
writel_relaxed(arbiter, pc->base + IR_TRANS_ARBITER);
val = readl_relaxed(pc->base + IR_TRANS_ARBITER);
if (!(val & arbiter)) {
dev_err(chip->dev, "Failed to abtain ir transmit arbitration for PWM%d\n",
pc->channel_id);
ret = -EINVAL;
goto err_clk;
}
reinit_completion(&pc->ir_trans_completion);
/*
* Each value in the txbuf[] is in microseconds(us).
* txbuf[0]: the low duration of NEC leader code.
* txbuf[1]: the high duration of NEC leader code.
* txbuf[2]: the high duration of NEC repeat code.
* txbuf[3]: the low duration of NEC logic '0' and '1'.
* txbuf[4]: the high duration of NEC logic '0'.
* txbuf[5]: the high duration of NEC logic '1'.
* txbuf[6]:
* bit[31:24] bit[23:16] bit[15:8] bit[7:0]
* address code address inverted code command code command inverted code
*/
preload = txbuf[0] << IR_TRANS_OUT_LOW_PRELOAD_SHIFT |
txbuf[1] << IR_TRANS_OUT_HIGH_PRELOAD_SHIFT;
spreload = txbuf[2] << IR_TRANS_OUT_HIGH_SIMPLE_PRELOAD_SHIFT;
low_period = txbuf[3] << IR_TRANS_OUT_DATA_LOW_PERIOD_SHIFT;
high_period = txbuf[4] << IR_TRANS_OUT_HIGH_PERIOD_FOR_ZERO_SHIFT |
txbuf[5] << IR_TRANS_OUT_HIGH_PERIOD_FOR_ONE_SHIFT;
tx_value = txbuf[6] << IR_TRANS_OUT_VALUE_SHIFT;
/* Set the dclk to 1M */
writel_relaxed(CLK_SCALE(0x32), pc->base + CLK_CTRL);
writel_relaxed(PWM_CLK_EN(true), pc->base + ENABLE);
writel_relaxed(IR_TRANS_END_INT_EN(true), pc->base + INT_EN);
writel_relaxed(preload, pc->base + IR_TRANS_PRE);
writel_relaxed(spreload, pc->base + IR_TRANS_SPRE);
writel_relaxed(low_period, pc->base + IR_TRANS_LD);
writel_relaxed(high_period, pc->base + IR_TRANS_HD);
writel_relaxed(tx_value, pc->base + IR_TRANS_DATA_VALUE);
val = readl_relaxed(pc->base + IR_TRANS_BURST_FRAME);
timeout_ms = ((val & IR_TRANS_OUT_FRAME_PERIOD_MASK) >>
IR_TRANS_OUT_FRAME_PERIOD_SHIFT) / 1000;
writel_relaxed(IR_TRANS_INACTIVE_POL(true) | IR_TRANS_OUT_ENABLE(true),
pc->base + IR_TRANS_CTRL0);
ret = wait_for_completion_timeout(&pc->ir_trans_completion,
msecs_to_jiffies(timeout_ms * 3 / 2));
if (!ret) {
dev_err(chip->dev, "Failed to wait for PWM%d ir transmit to complete\n",
pc->channel_id);
ret = -ETIMEDOUT;
}
writel_relaxed(IR_TRANS_OUT_ENABLE(false), pc->base + IR_TRANS_CTRL0);
writel_relaxed(IR_TRANS_END_INT_EN(false), pc->base + INT_EN);
writel_relaxed(PWM_CLK_EN(false), pc->base + ENABLE);
writel_relaxed(0, pc->base + IR_TRANS_ARBITER);
err_clk:
clk_disable(pc->clk);
return ret ? ret : count;
}
static int rockchip_pwm_ir_transmit(struct rc_dev *dev, unsigned int *txbuf, unsigned int count)
{
struct rockchip_pwm_chip *pc = dev->priv;
struct pwm_chip *chip = &pc->chip;
struct pwm_state curstate;
int ret;
if (!pc->data->funcs.ir_transmit) {
dev_err(chip->dev, "Unsupported ir transmit mode\n");
return -EINVAL;
}
pwm_get_state(&pc->chip.pwms[0], &curstate);
if (curstate.enabled) {
dev_err(chip->dev, "Failed to enable ir transmit mode because PWM%d is busy\n",
pc->channel_id);
return -EBUSY;
}
ret = pinctrl_select_state(pc->pinctrl, pc->active_state);
if (ret) {
dev_err(chip->dev, "Failed to select pinctrl state\n");
return ret;
}
ret = clk_enable(pc->pclk);
if (ret)
return ret;
ret = pc->data->funcs.ir_transmit(chip, txbuf, count);
if (ret < 0)
dev_err(chip->dev, "Failed to transmit ir buf\n");
clk_disable(pc->pclk);
return ret;
}
#else
static int rockchip_pwm_ir_transmit_v4(struct pwm_chip *chip, unsigned int *txbuf,
unsigned int count)
{
return count;
}
#endif
#ifdef CONFIG_DEBUG_FS
static int rockchip_pwm_debugfs_show(struct seq_file *s, void *data)
{
@@ -2034,6 +2227,7 @@ static const struct rockchip_pwm_data pwm_data_v4 = {
.set_wave = rockchip_pwm_set_wave_v4,
.set_biphasic = rockchip_pwm_set_biphasic_v4,
.get_biphasic_result = rockchip_pwm_get_biphasic_result_v4,
.ir_transmit = rockchip_pwm_ir_transmit_v4,
.irq_handler = rockchip_pwm_irq_v4,
},
};
@@ -2140,6 +2334,7 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
if (pc->main_version >= 4) {
version = readl_relaxed(pc->base + pc->data->regs.version);
pc->channel_id = (version & CHANNLE_INDEX_MASK) >> CHANNLE_INDEX_SHIFT;
pc->ir_trans_support = !!(version & IR_TRANS_SUPPORT);
pc->freq_meter_support = !!(version & FREQ_METER_SUPPORT);
pc->counter_support = !!(version & COUNTER_SUPPORT);
pc->wave_support = !!(version & WAVE_SUPPORT);
@@ -2218,6 +2413,27 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
}
}
#ifdef CONFIG_RC_CORE
if (pc->ir_trans_support &&
device_property_present(&pdev->dev, "rockchip,pwm-ir-transmit")) {
struct rc_dev *rcdev;
init_completion(&pc->ir_trans_completion);
rcdev = devm_rc_allocate_device(&pdev->dev, RC_DRIVER_IR_RAW_TX);
if (!rcdev)
goto err_pclk;
rcdev->priv = pc;
rcdev->driver_name = "rockchip-pwm-ir-tx";
rcdev->device_name = "Rockchip IR TX";
rcdev->tx_ir = rockchip_pwm_ir_transmit;
ret = devm_rc_register_device(&pdev->dev, rcdev);
if (ret < 0)
goto err_pclk;
}
#endif
rockchip_pwm_debugfs_init(pc);
/* Keep the PWM clk enabled if the PWM appears to be up and running. */

View File

@@ -198,6 +198,12 @@
#define RKCIS_CMD_SELECT_SETTING \
_IOW('V', BASE_VIDIOC_PRIVATE + 44, struct rk_sensor_setting)
#define RKMODULE_GET_EXP_DELAY \
_IOR('V', BASE_VIDIOC_PRIVATE + 45, struct rkmodule_exp_delay)
#define RKMODULE_GET_EXP_INFO \
_IOR('V', BASE_VIDIOC_PRIVATE + 46, struct rkmodule_exp_info)
struct rkmodule_i2cdev_info {
__u8 slave_addr;
} __attribute__ ((packed));
@@ -856,4 +862,37 @@ struct rk_sensor_setting {
__u32 mode;
} __attribute__ ((packed));
struct rkmodule_exp_delay {
__u32 exp_delay;
__u32 gain_delay;
__u32 vts_delay;
__u32 dcg_delay;
__u32 reserved[2];
} __attribute__ ((packed));
enum rkmodule_gain_mode_e {
RKMODULE_GAIN_MODE_LINEAR,
RKMODULE_GAIN_MODE_DB,
};
struct rkmodule_gain_mode {
__u32 gain_mode;
__u32 factor;
} __attribute__ ((packed));
struct rkmodule_exp_info {
__u32 exp[3];
__u32 gain[3];
__u32 exp_reg[3];
__u32 gain_reg[3];
__u32 hts;
__u32 vts;
__u32 pclk;
__u32 dcg_used;
__u32 dcg_val[3];
struct rkmodule_dcg_ratio dcg_ratio;
struct rkmodule_gain_mode gain_mode;
__u32 reserved[6];
} __attribute__ ((packed));
#endif /* _UAPI_RKMODULE_CAMERA_H */

View File

@@ -83,6 +83,9 @@
#define RKCIF_CMD_SET_SENSOR_FLIP_END \
_IOWR('V', BASE_VIDIOC_PRIVATE + 21, int)
#define RKCIF_CMD_SUPPORT_GET_EXP \
_IOWR('V', BASE_VIDIOC_PRIVATE + 22, int)
/* cif memory mode
* 0: raw12/raw10/raw8 8bit memory compact
* 1: raw12/raw10 16bit memory one pixel