Merge commit '0c4fa77794ce128089a9f9523d4615d4f2835ec5'

* commit '0c4fa77794ce128089a9f9523d4615d4f2835ec5':
  rpmsg: rockchip_test: add delay compensation
  media: rockchip: isp: add iqtool video for isp21
  arm64: dts: rockchip: rk3399pro-npu: dis u1 and u2 state for dwc3
  arm64: dts: rockchip: rk1808: dis u1 and u2 state for dwc3
  arm64: dts: rockchip: dis u1 and u2 state for rk3528 dwc3
  ARM: dts: rockchip: update rk808 for rk3288-evb-rk808-linux.dts
  ARM: dts: rockchip: Add mmc aliases for rk3288-linux.dtsi
  drm/bridge: synopsys: dw-hdmi-qp: Fix frl switch error when switching resolution and color at the same time
  ARM: configs: enable HDMI and MULTICODECS for rockchip_linux_defconfig
  UPSTREAM: ASoC: rt5640: Remove the sysclk and sysclk_src checking
  video: rockchip: mpp: fix some iommu hdl register issue
  media: rockchip: isp: fix get tb info
  soc: rockchip: rockchip_system_monitor: Don't init wide temp when tz is NULL
  video: rockchip: mpp: fix task re-add running_list issue
  arm64: dts: rockchip: rk3588-evb3-lp5: update for v11 board
  media: rockchip: isp: fix list buf delete err
  soc: rockchip: amp: include rockchip_amp.h for function prototypes
  arm64: dts: rockchip: rk3562-rk817-tablet: adjust vcm configs to reduce noise
  media: i2c: dw9763: optimize open/close procedure to reduce noise
  UPSTREAM: dt-bindings: usb: snps,dwc3: Add 'snps,parkmode-disable-hs-quirk' quirk

Change-Id: Iaab1b5d91a4a16c24fb30938d520087b77861a73
This commit is contained in:
Tao Huang
2023-08-28 19:19:25 +08:00
24 changed files with 411 additions and 142 deletions

View File

@@ -222,6 +222,11 @@ properties:
When set, all SuperSpeed bus instances in park mode are disabled.
type: boolean
snps,parkmode-disable-hs-quirk:
description:
When set, all HighSpeed bus instances in park mode are disabled.
type: boolean
snps,dis_metastability_quirk:
description:
When set, disable metastability workaround. CAUTION! Use only if you are

View File

@@ -1,42 +1,4 @@
/*
* This file is dual-licensed: you can use it either under the terms
* of the GPL or the X11 license, at your option. Note that this dual
* licensing only applies to this file, and not this project as a
* whole.
*
* a) This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Or, alternatively,
*
* b) Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/dts-v1/;
#include "rk3288-evb.dtsi"
@@ -262,7 +224,8 @@
regulator-max-microvolt = <3300000>;
regulator-name = "vcca_codec";
regulator-state-mem {
regulator-off-in-suspend;
regulator-on-in-suspend;
regulator-suspend-microvolt = <3300000>;
};
};
@@ -282,10 +245,10 @@
regulator-always-on;
regulator-boot-on;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-max-microvolt = <1800000>;
regulator-name = "vcc_wl";
regulator-state-mem {
regulator-off-in-suspend;
regulator-on-in-suspend;
};
};
@@ -296,8 +259,7 @@
regulator-max-microvolt = <3300000>;
regulator-name = "vccio_sd";
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <3300000>;
regulator-off-in-suspend;
};
};
@@ -340,7 +302,7 @@
regulator-boot-on;
regulator-name = "vcc_sd";
regulator-state-mem {
regulator-on-in-suspend;
regulator-off-in-suspend;
};
};

View File

@@ -7,6 +7,13 @@
#include "rk3288-dram-default-timing.dtsi"
/ {
aliases {
mshc0 = &emmc;
mshc1 = &sdmmc;
mshc2 = &sdio0;
mshc3 = &sdio1;
};
chosen {
bootargs = "earlycon=uart8250,mmio32,0xff690000 console=ttyFIQ0 vmalloc=496M rw root=PARTUUID=614e0000-0000 rootfstype=ext4 rootwait";
};

View File

@@ -333,7 +333,9 @@ CONFIG_SND_SOC_ROCKCHIP=y
CONFIG_SND_SOC_ROCKCHIP_SAI=y
CONFIG_SND_SOC_ROCKCHIP_SPDIF=y
CONFIG_SND_SOC_ROCKCHIP_MAX98090=y
CONFIG_SND_SOC_ROCKCHIP_MULTICODECS=y
CONFIG_SND_SOC_ROCKCHIP_RT5645=y
CONFIG_SND_SOC_ROCKCHIP_HDMI=y
CONFIG_SND_SOC_ES8311=y
CONFIG_SND_SOC_ES8323=y
CONFIG_SND_SOC_ES8396=y

View File

@@ -378,7 +378,8 @@
phy-names = "usb2-phy", "usb3-phy";
phy_type = "utmi_wide";
snps,dis_enblslpm_quirk;
snps,dis-u1u2-quirk;
snps,dis-u1-entry-quirk;
snps,dis-u2-entry-quirk;
snps,dis-u2-freeclk-exists-quirk;
snps,dis_u2_susphy_quirk;
snps,dis_u3_susphy_quirk;

View File

@@ -149,7 +149,8 @@
phy-names = "usb2-phy", "usb3-phy";
phy_type = "utmi_wide";
snps,dis_enblslpm_quirk;
snps,dis-u1u2-quirk;
snps,dis-u1-entry-quirk;
snps,dis-u2-entry-quirk;
snps,dis-u2-freeclk-exists-quirk;
snps,dis_u2_susphy_quirk;
snps,dis_u3_susphy_quirk;

View File

@@ -644,7 +644,8 @@
resets = <&cru SRST_ARESETN_USB3OTG>;
reset-names = "usb3-otg";
snps,dis_enblslpm_quirk;
snps,dis-u1u2-quirk;
snps,dis-u1-entry-quirk;
snps,dis-u2-entry-quirk;
snps,dis-u2-freeclk-exists-quirk;
snps,dis-del-phy-power-chg-quirk;
snps,dis-tx-ipgap-linecheck-quirk;

View File

@@ -89,10 +89,11 @@
compatible = "dongwoon,dw9763";
status = "okay";
reg = <0x0c>;
avdd-supply = <&vcc2v8_dvp>;
rockchip,vcm-max-current = <120>;
rockchip,vcm-start-current = <20>;
rockchip,vcm-rated-current = <90>;
rockchip,vcm-step-mode = <3>;
rockchip,vcm-start-current = <25>;
rockchip,vcm-rated-current = <100>;
rockchip,vcm-step-mode = <4>;
rockchip,vcm-t-src = <0x20>;
rockchip,vcm-t-div = <1>;
rockchip,camera-module-index = <0>;

View File

@@ -67,7 +67,7 @@
fan: pwm-fan {
compatible = "pwm-fan";
#cooling-cells = <2>;
pwms = <&pwm6 0 50000 0>;
pwms = <&pwm5 0 50000 0>;
cooling-levels = <0 50 100 150 200 255>;
rockchip,temp-trips = <
50000 1
@@ -815,20 +815,20 @@
};
};
&hdmi1 {
&hdmi0 {
enable-gpios = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>;
status = "okay";
};
&hdmi1_in_vp0 {
&hdmi0_in_vp0 {
status = "okay";
};
&hdmi1_sound {
&hdmi0_sound {
status = "okay";
};
&hdptxphy_hdmi1 {
&hdptxphy_hdmi0 {
status = "okay";
};
@@ -889,9 +889,9 @@
&i2c2 {
status = "okay";
usbc0: fusb302@22 {
compatible = "fcs,fusb302";
reg = <0x22>;
usbc0: husb311@4e {
compatible = "hynetek,husb311";
reg = <0x4e>;
interrupt-parent = <&gpio0>;
interrupts = <RK_PD3 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
@@ -1011,7 +1011,7 @@
};
};
&i2s6_8ch {
&i2s5_8ch {
status = "okay";
};
@@ -1138,8 +1138,8 @@
};
};
&pwm6 {
pinctrl-0 = <&pwm6m1_pins>;
&pwm5 {
pinctrl-0 = <&pwm5m1_pins>;
status = "okay";
};

View File

@@ -2599,7 +2599,7 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector,
hdmi_modb(hdmi, PKTSCHED_GCP_TX_EN, PKTSCHED_GCP_TX_EN, PKTSCHED_PKT_EN);
mdelay(50);
} else if (!hdmi->disabled) {
if (mode.clock > 600000)
if (hdmi->previous_mode.clock > 600000 && mode.clock > 600000)
hdmi->frl_switch = true;
hdmi->update = false;
crtc_state->mode_changed = true;

View File

@@ -15,12 +15,14 @@
#include <media/v4l2-device.h>
#include <linux/rk_vcm_head.h>
#include <linux/compat.h>
#include <linux/regulator/consumer.h>
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x0)
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x1)
#define DW9763_NAME "dw9763"
#define DW9763_MAX_CURRENT 120U
#define DW9763_MAX_REG 1023U
#define DW9763_GRADUAL_MOVELENS_STEPS 32
#define DW9763_DEFAULT_START_CURRENT 20
#define DW9763_DEFAULT_RATED_CURRENT 90
@@ -41,6 +43,10 @@ enum mode_e {
DIRECT_MODE,
};
static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (0-2)");
/* dw9763 device structure */
struct dw9763_device {
struct v4l2_ctrl_handler ctrls_vcm;
@@ -69,6 +75,8 @@ struct dw9763_device {
struct rk_cam_vcm_cfg vcm_cfg;
int max_ma;
struct mutex lock;
struct regulator *supply;
bool power_on;
};
static inline struct dw9763_device *to_dw9763_vcm(struct v4l2_ctrl *ctrl)
@@ -88,6 +96,7 @@ static int dw9763_write_reg(struct i2c_client *client, u8 reg,
u8 buf[5];
u8 *val_p;
__be32 val_be;
struct dw9763_device *dev_vcm = i2c_get_clientdata(client);
if (len > 4)
return -EINVAL;
@@ -106,7 +115,7 @@ static int dw9763_write_reg(struct i2c_client *client, u8 reg,
dev_err(&client->dev, "Failed to write 0x%04x,0x%x\n", reg, val);
return -EIO;
}
dev_dbg(&client->dev, "succeed to write 0x%04x,0x%x\n", reg, val);
v4l2_dbg(1, debug, &dev_vcm->sd, "succeed to write 0x%04x,0x%x\n", reg, val);
return 0;
}
@@ -120,6 +129,7 @@ static int dw9763_read_reg(struct i2c_client *client,
u8 *data_be_p;
__be32 data_be = 0;
int ret;
struct dw9763_device *dev_vcm = i2c_get_clientdata(client);
if (len > 4 || !len)
return -EINVAL;
@@ -143,6 +153,8 @@ static int dw9763_read_reg(struct i2c_client *client,
*val = be32_to_cpu(data_be);
v4l2_dbg(1, debug, &dev_vcm->sd, "succeed to read 0x%04x,0x%x\n", reg, *val);
return 0;
}
@@ -204,11 +216,11 @@ static unsigned int dw9763_move_time(struct dw9763_device *dev_vcm,
break;
}
dev_dbg(&client->dev,
v4l2_dbg(1, debug, &dev_vcm->sd,
"%s: vcm_movefull_t is: %d us\n",
__func__, move_time_us);
return move_time_us;
return ((move_time_us + 500) / 1000);
}
static int dw9763_set_dac(struct dw9763_device *dev_vcm,
@@ -228,7 +240,7 @@ static int dw9763_set_dac(struct dw9763_device *dev_vcm,
ret = dw9763_write_reg(client, 0x03, 2, dest_dac);
if (ret != 0)
goto err;
dev_dbg(&client->dev,
v4l2_dbg(1, debug, &dev_vcm->sd,
"%s: set reg val %d\n", __func__, dest_dac);
return ret;
@@ -249,7 +261,7 @@ static int dw9763_get_dac(struct dw9763_device *dev_vcm, unsigned int *cur_dac)
goto err;
*cur_dac = abs_step;
dev_dbg(&client->dev, "%s: get dac %d\n", __func__, *cur_dac);
v4l2_dbg(1, debug, &dev_vcm->sd, "%s: get dac %d\n", __func__, *cur_dac);
return 0;
@@ -279,7 +291,7 @@ static int dw9763_get_pos(struct dw9763_device *dev_vcm,
abs_step = 0;
*cur_pos = abs_step;
dev_dbg(&client->dev, "%s: get position %d\n", __func__, *cur_pos);
v4l2_dbg(1, debug, &dev_vcm->sd, "%s: get position %d\n", __func__, *cur_pos);
return 0;
err:
@@ -293,7 +305,6 @@ static int dw9763_set_pos(struct dw9763_device *dev_vcm,
{
int ret;
unsigned int position = 0;
struct i2c_client *client = dev_vcm->client;
if (dest_pos >= VCMDRV_MAX_LOG)
position = dev_vcm->start_current;
@@ -308,7 +319,8 @@ static int dw9763_set_pos(struct dw9763_device *dev_vcm,
dev_vcm->current_related_pos = dest_pos;
ret = dw9763_set_dac(dev_vcm, position);
dev_dbg(&client->dev, "%s: set position %d, dac %d\n", __func__, dest_pos, position);
v4l2_dbg(1, debug, &dev_vcm->sd, "%s: set position %d, dac %d\n",
__func__, dest_pos, position);
return ret;
}
@@ -331,7 +343,7 @@ static int dw9763_set_ctrl(struct v4l2_ctrl *ctrl)
long mv_us;
int ret = 0;
dev_dbg(&client->dev, "ctrl->id: 0x%x, ctrl->val: 0x%x\n",
v4l2_dbg(1, debug, &dev_vcm->sd, "ctrl->id: 0x%x, ctrl->val: 0x%x\n",
ctrl->id, ctrl->val);
if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) {
@@ -345,9 +357,9 @@ static int dw9763_set_ctrl(struct v4l2_ctrl *ctrl)
ret = dw9763_set_pos(dev_vcm, dest_pos);
dev_vcm->move_us = dev_vcm->vcm_movefull_t;
dev_vcm->move_us = dev_vcm->vcm_movefull_t * 1000;
dev_dbg(&client->dev,
v4l2_dbg(1, debug, &dev_vcm->sd,
"dest_pos %d, move_us %ld\n",
dest_pos, dev_vcm->move_us);
@@ -373,9 +385,19 @@ static const struct v4l2_ctrl_ops dw9763_vcm_ctrl_ops = {
.s_ctrl = dw9763_set_ctrl,
};
static int dw9763_init(struct i2c_client *client);
static int dw9763_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
int rval;
struct dw9763_device *dev_vcm = sd_to_dw9763_vcm(sd);
unsigned int move_time;
int dac = dev_vcm->start_current;
struct i2c_client *client = dev_vcm->client;
#ifdef CONFIG_PM
v4l2_info(sd, "%s: enter, power.usage_count(%d)!\n", __func__,
atomic_read(&sd->dev->power.usage_count));
#endif
rval = pm_runtime_get_sync(sd->dev);
if (rval < 0) {
@@ -383,12 +405,72 @@ static int dw9763_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
return rval;
}
dw9763_init(client);
v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n",
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
move_time = 1000 * dw9763_move_time(dev_vcm, DW9763_GRADUAL_MOVELENS_STEPS);
while (dac <= dev_vcm->current_lens_pos) {
dw9763_set_dac(dev_vcm, dac);
usleep_range(move_time, move_time + 100);
dac += DW9763_GRADUAL_MOVELENS_STEPS;
if (dac > dev_vcm->current_lens_pos)
break;
}
if (dac > dev_vcm->current_lens_pos) {
dac = dev_vcm->current_lens_pos;
dw9763_set_dac(dev_vcm, dac);
}
#ifdef CONFIG_PM
v4l2_info(sd, "%s: exit, power.usage_count(%d)!\n", __func__,
atomic_read(&sd->dev->power.usage_count));
#endif
return 0;
}
static int dw9763_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct dw9763_device *dev_vcm = sd_to_dw9763_vcm(sd);
int dac = dev_vcm->current_lens_pos;
unsigned int move_time;
int ret;
struct i2c_client *client = dev_vcm->client;
#ifdef CONFIG_PM
v4l2_info(sd, "%s: enter, power.usage_count(%d)!\n", __func__,
atomic_read(&sd->dev->power.usage_count));
#endif
v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n",
__func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos);
dac -= DW9763_GRADUAL_MOVELENS_STEPS;
move_time = 1000 * dw9763_move_time(dev_vcm, DW9763_GRADUAL_MOVELENS_STEPS);
while (dac >= DW9763_GRADUAL_MOVELENS_STEPS) {
dw9763_set_dac(dev_vcm, dac);
usleep_range(move_time, move_time + 1000);
dac -= DW9763_GRADUAL_MOVELENS_STEPS;
if (dac <= 0)
break;
}
if (dac < DW9763_GRADUAL_MOVELENS_STEPS) {
dac = DW9763_GRADUAL_MOVELENS_STEPS / 2;
dw9763_set_dac(dev_vcm, dac);
}
/* set to power down mode */
ret = dw9763_write_reg(client, 0x02, 1, 0x01);
if (ret)
dev_err(&client->dev, "failed to set power down mode!\n");
pm_runtime_put(sd->dev);
#ifdef CONFIG_PM
v4l2_info(sd, "%s: exit, power.usage_count(%d)!\n", __func__,
atomic_read(&sd->dev->power.usage_count));
#endif
return 0;
}
@@ -442,7 +524,7 @@ static long dw9763_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
vcm_tim->vcm_end_t.tv_sec = dev_vcm->end_move_tv.tv_sec;
vcm_tim->vcm_end_t.tv_usec = dev_vcm->end_move_tv.tv_usec;
dev_dbg(&client->dev, "dw9763_get_move_res 0x%lx, 0x%lx, 0x%lx, 0x%lx\n",
v4l2_dbg(1, debug, &dev_vcm->sd, "dw9763_get_move_res 0x%lx, 0x%lx, 0x%lx, 0x%lx\n",
vcm_tim->vcm_start_t.tv_sec,
vcm_tim->vcm_start_t.tv_usec,
vcm_tim->vcm_end_t.tv_sec,
@@ -634,13 +716,50 @@ static inline int remove_sysfs_interfaces(struct device *dev)
}
#endif
static int __dw9763_set_power(struct dw9763_device *dw9763_dev, bool on)
static int __dw9763_set_power(struct dw9763_device *dw9763, bool on)
{
if (dw9763_dev->power_gpio)
gpiod_direction_output(dw9763_dev->power_gpio, on);
usleep_range(10000, 11000);
struct i2c_client *client = dw9763->client;
int ret = 0;
return 0;
dev_info(&client->dev, "%s(%d) on(%d)\n", __func__, __LINE__, on);
if (dw9763->power_on == !!on)
goto unlock_and_return;
if (on) {
ret = regulator_enable(dw9763->supply);
if (ret < 0) {
dev_err(&client->dev, "Failed to enable regulator\n");
goto unlock_and_return;
}
dw9763->power_on = true;
} else {
ret = regulator_disable(dw9763->supply);
if (ret < 0) {
dev_err(&client->dev, "Failed to disable regulator\n");
goto unlock_and_return;
}
dw9763->power_on = false;
}
unlock_and_return:
return ret;
}
static int dw9763_configure_regulator(struct dw9763_device *dw9763)
{
struct i2c_client *client = dw9763->client;
int ret = 0;
dw9763->supply = devm_regulator_get(&client->dev, "avdd");
if (IS_ERR(dw9763->supply)) {
ret = PTR_ERR(dw9763->supply);
if (ret != -EPROBE_DEFER)
dev_err(&client->dev, "could not get regulator avdd\n");
return ret;
}
dw9763->power_on = false;
return ret;
}
static int __maybe_unused dw9763_check_id(struct dw9763_device *dw9763_dev)
@@ -662,20 +781,6 @@ static int __maybe_unused dw9763_check_id(struct dw9763_device *dw9763_dev)
"Detected dw9763 vcm id:0x%x\n", DW9763_CHIP_ID);
return 0;
}
static int dw9763_probe_init(struct i2c_client *client)
{
int ret = 0;
/* Default goto power down mode when finished probe */
ret = dw9763_write_reg(client, 0x02, 1, 0x01);
if (ret)
goto err;
return 0;
err:
dev_err(&client->dev, "probe init failed with error %d\n", ret);
return -1;
}
static int dw9763_probe(struct i2c_client *client,
const struct i2c_device_id *id)
@@ -765,9 +870,11 @@ static int dw9763_probe(struct i2c_client *client,
dev_warn(&client->dev,
"Failed to get power-gpios, maybe no use\n");
}
/* enter power down mode */
dw9763_probe_init(client);
ret = dw9763_configure_regulator(dw9763_dev);
if (ret) {
dev_err(&client->dev, "Failed to get power regulator!\n");
return ret;
}
v4l2_i2c_subdev_init(&dw9763_dev->sd, client, &dw9763_ops);
dw9763_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@@ -781,6 +888,10 @@ static int dw9763_probe(struct i2c_client *client,
if (ret < 0)
goto err_cleanup;
ret = dw9763_check_id(dw9763_dev);
if (ret)
goto err_power_off;
sd = &dw9763_dev->sd;
sd->entity.function = MEDIA_ENT_F_LENS;
@@ -823,6 +934,9 @@ static int dw9763_probe(struct i2c_client *client,
dev_info(&client->dev, "probing successful\n");
return 0;
err_power_off:
__dw9763_set_power(dw9763_dev, false);
err_cleanup:
dw9763_subdev_cleanup(dw9763_dev);
@@ -845,21 +959,18 @@ static int dw9763_init(struct i2c_client *client)
{
struct dw9763_device *dev_vcm = i2c_get_clientdata(client);
int ret = 0;
u32 ring = 0;
u32 mode_val = 0;
u32 algo_time = 0;
if (dev_vcm->step_mode == DIRECT_MODE)
return 0;
/* Delay 200us~300us */
usleep_range(200, 300);
ret = dw9763_write_reg(client, 0x02, 1, 0x00);
if (ret)
goto err;
usleep_range(100, 200);
if (dev_vcm->step_mode != DIRECT_MODE)
ring = 0x02;
ret = dw9763_write_reg(client, 0x02, 1, ring);
usleep_range(200, 300);
ret = dw9763_write_reg(client, 0x02, 1, 0x02);
if (ret)
goto err;
switch (dev_vcm->step_mode) {
@@ -893,13 +1004,15 @@ err:
static int __maybe_unused dw9763_vcm_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
int ret = 0;
struct dw9763_device *dev_vcm = i2c_get_clientdata(client);
struct v4l2_subdev *sd = &(dev_vcm->sd);
/* set to power down mode */
ret = dw9763_write_reg(client, 0x02, 1, 0x01);
if (ret)
dev_err(&client->dev, "failed to set power down mode!\n");
#ifdef CONFIG_PM
v4l2_dbg(1, debug, sd, "%s: enter, power.usage_count(%d)!\n", __func__,
atomic_read(&sd->dev->power.usage_count));
#endif
__dw9763_set_power(dev_vcm, false);
return 0;
}
@@ -907,9 +1020,14 @@ static int __maybe_unused dw9763_vcm_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct dw9763_device *dev_vcm = i2c_get_clientdata(client);
struct v4l2_subdev *sd = &(dev_vcm->sd);
#ifdef CONFIG_PM
v4l2_dbg(1, debug, sd, "%s: enter, power.usage_count(%d)!\n", __func__,
atomic_read(&sd->dev->power.usage_count));
#endif
__dw9763_set_power(dev_vcm, true);
dw9763_init(client);
dw9763_set_pos(dev_vcm, dev_vcm->current_related_pos);
return 0;
}

View File

@@ -1206,6 +1206,9 @@ static int mi_frame_end(struct rkisp_stream *stream, u32 state)
unsigned long lock_flags = 0;
int i = 0;
if (stream->id == RKISP_STREAM_VIR)
return 0;
if (!stream->next_buf && stream->streaming &&
dev->dmarx_dev.trigger == T_MANUAL &&
is_rdbk_stream(stream))
@@ -1218,6 +1221,7 @@ static int mi_frame_end(struct rkisp_stream *stream, u32 state)
(!interlaced ||
(stream->u.sp.field_rec == RKISP_FIELD_ODD &&
stream->u.sp.field == RKISP_FIELD_EVEN))) {
struct rkisp_stream *vir = &dev->cap_dev.stream[RKISP_STREAM_VIR];
struct vb2_buffer *vb2_buf = &stream->curr_buf->vb.vb2_buf;
u64 ns = 0;
@@ -1268,7 +1272,16 @@ static int mi_frame_end(struct rkisp_stream *stream, u32 state)
rdbk_frame_end(stream);
}
} else {
rkisp_stream_buf_done(stream, stream->curr_buf);
if (vir->streaming && vir->conn_id == stream->id) {
spin_lock_irqsave(&vir->vbq_lock, lock_flags);
list_add_tail(&stream->curr_buf->queue,
&dev->cap_dev.vir_cpy.queue);
spin_unlock_irqrestore(&vir->vbq_lock, lock_flags);
if (!completion_done(&dev->cap_dev.vir_cpy.cmpl))
complete(&dev->cap_dev.vir_cpy.cmpl);
} else {
rkisp_stream_buf_done(stream, stream->curr_buf);
}
}
stream->curr_buf = NULL;
@@ -1379,6 +1392,98 @@ static void rkisp_stream_stop(struct rkisp_stream *stream)
stream->interlaced = false;
}
static void vir_cpy_image(struct work_struct *work)
{
struct rkisp_vir_cpy *cpy =
container_of(work, struct rkisp_vir_cpy, work);
struct rkisp_stream *vir = cpy->stream;
struct rkisp_buffer *src_buf = NULL;
unsigned long lock_flags = 0;
u32 i;
v4l2_dbg(1, rkisp_debug, &vir->ispdev->v4l2_dev,
"%s enter\n", __func__);
vir->streaming = true;
spin_lock_irqsave(&vir->vbq_lock, lock_flags);
if (!list_empty(&cpy->queue)) {
src_buf = list_first_entry(&cpy->queue,
struct rkisp_buffer, queue);
list_del(&src_buf->queue);
}
spin_unlock_irqrestore(&vir->vbq_lock, lock_flags);
while (src_buf || vir->streaming) {
if (vir->stopping || !vir->streaming)
goto end;
if (!src_buf)
wait_for_completion(&cpy->cmpl);
vir->frame_end = false;
spin_lock_irqsave(&vir->vbq_lock, lock_flags);
if (!src_buf && !list_empty(&cpy->queue)) {
src_buf = list_first_entry(&cpy->queue,
struct rkisp_buffer, queue);
list_del(&src_buf->queue);
}
if (src_buf && !vir->curr_buf && !list_empty(&vir->buf_queue)) {
vir->curr_buf = list_first_entry(&vir->buf_queue,
struct rkisp_buffer, queue);
list_del(&vir->curr_buf->queue);
}
spin_unlock_irqrestore(&vir->vbq_lock, lock_flags);
if (!vir->curr_buf || !src_buf)
goto end;
for (i = 0; i < vir->out_isp_fmt.mplanes; i++) {
u32 payload_size = vir->out_fmt.plane_fmt[i].sizeimage;
void *src = vb2_plane_vaddr(&src_buf->vb.vb2_buf, i);
void *dst = vb2_plane_vaddr(&vir->curr_buf->vb.vb2_buf, i);
if (!src || !dst)
break;
vb2_set_plane_payload(&vir->curr_buf->vb.vb2_buf, i, payload_size);
memcpy(dst, src, payload_size);
}
vir->curr_buf->vb.sequence = src_buf->vb.sequence;
vir->curr_buf->vb.vb2_buf.timestamp = src_buf->vb.vb2_buf.timestamp;
vb2_buffer_done(&vir->curr_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
vir->curr_buf = NULL;
end:
if (src_buf)
vb2_buffer_done(&src_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
src_buf = NULL;
spin_lock_irqsave(&vir->vbq_lock, lock_flags);
if (!list_empty(&cpy->queue)) {
src_buf = list_first_entry(&cpy->queue,
struct rkisp_buffer, queue);
list_del(&src_buf->queue);
} else if (vir->stopping) {
vir->streaming = false;
}
spin_unlock_irqrestore(&vir->vbq_lock, lock_flags);
}
vir->frame_end = true;
if (vir->stopping) {
vir->stopping = false;
vir->streaming = false;
wake_up(&vir->done);
}
v4l2_dbg(1, rkisp_debug, &vir->ispdev->v4l2_dev,
"%s exit\n", __func__);
}
/*
* Most of registers inside rockchip isp1 have shadow register since
* they must be not changed during processing a frame.
@@ -1571,6 +1676,21 @@ static void rkisp_stop_streaming(struct vb2_queue *queue)
if (!stream->streaming)
goto end;
if (stream->id == RKISP_STREAM_VIR) {
stream->stopping = true;
wait_event_timeout(stream->done,
stream->frame_end,
msecs_to_jiffies(500));
stream->streaming = false;
stream->stopping = false;
destroy_buf_queue(stream, VB2_BUF_STATE_ERROR);
if (!completion_done(&dev->cap_dev.vir_cpy.cmpl))
complete(&dev->cap_dev.vir_cpy.cmpl);
stream->conn_id = -1;
goto end;
}
rkisp_stream_stop(stream);
if (stream->id == RKISP_STREAM_MP ||
stream->id == RKISP_STREAM_SP) {
@@ -1652,6 +1772,28 @@ rkisp_start_streaming(struct vb2_queue *queue, unsigned int count)
return -EBUSY;
}
if (stream->id == RKISP_STREAM_VIR) {
struct rkisp_stream *t = &dev->cap_dev.stream[stream->conn_id];
if (t->streaming) {
INIT_WORK(&dev->cap_dev.vir_cpy.work, vir_cpy_image);
init_completion(&dev->cap_dev.vir_cpy.cmpl);
INIT_LIST_HEAD(&dev->cap_dev.vir_cpy.queue);
dev->cap_dev.vir_cpy.stream = stream;
schedule_work(&dev->cap_dev.vir_cpy.work);
ret = 0;
} else {
v4l2_err(&dev->v4l2_dev,
"no stream enable for iqtool\n");
destroy_buf_queue(stream, VB2_BUF_STATE_QUEUED);
ret = -EINVAL;
}
mutex_unlock(&dev->hw_dev->dev_lock);
return ret;
}
memset(&stream->dbg, 0, sizeof(stream->dbg));
atomic_inc(&dev->cap_dev.refcnt);
if (!dev->isp_inp || !stream->linked) {
@@ -1787,7 +1929,7 @@ static int rkisp_stream_init(struct rkisp_device *dev, u32 id)
switch (id) {
case RKISP_STREAM_SP:
strlcpy(vdev->name, SP_VDEV_NAME,
strscpy(vdev->name, SP_VDEV_NAME,
sizeof(vdev->name));
stream->ops = &rkisp_sp_streams_ops;
stream->config = &rkisp_sp_stream_config;
@@ -1795,25 +1937,32 @@ static int rkisp_stream_init(struct rkisp_device *dev, u32 id)
stream->config->fmt_size = ARRAY_SIZE(sp_fmts);
break;
case RKISP_STREAM_DMATX0:
strlcpy(vdev->name, DMATX0_VDEV_NAME,
strscpy(vdev->name, DMATX0_VDEV_NAME,
sizeof(vdev->name));
stream->ops = &rkisp2_dmatx0_streams_ops;
stream->config = &rkisp2_dmatx0_stream_config;
break;
case RKISP_STREAM_DMATX2:
strlcpy(vdev->name, DMATX2_VDEV_NAME,
strscpy(vdev->name, DMATX2_VDEV_NAME,
sizeof(vdev->name));
stream->ops = &rkisp2_dmatx2_streams_ops;
stream->config = &rkisp2_dmatx1_stream_config;
break;
case RKISP_STREAM_DMATX3:
strlcpy(vdev->name, DMATX3_VDEV_NAME,
strscpy(vdev->name, DMATX3_VDEV_NAME,
sizeof(vdev->name));
stream->ops = &rkisp2_dmatx3_streams_ops;
stream->config = &rkisp2_dmatx3_stream_config;
break;
case RKISP_STREAM_VIR:
strscpy(vdev->name, VIR_VDEV_NAME,
sizeof(vdev->name));
stream->ops = NULL;
stream->config = &rkisp_mp_stream_config;
stream->conn_id = -1;
break;
default:
strlcpy(vdev->name, MP_VDEV_NAME,
strscpy(vdev->name, MP_VDEV_NAME,
sizeof(vdev->name));
stream->ops = &rkisp_mp_streams_ops;
stream->config = &rkisp_mp_stream_config;
@@ -1857,8 +2006,13 @@ int rkisp_register_stream_v21(struct rkisp_device *dev)
ret = rkisp_stream_init(dev, RKISP_STREAM_DMATX3);
if (ret < 0)
goto err_free_tx2;
ret = rkisp_stream_init(dev, RKISP_STREAM_VIR);
if (ret < 0)
goto err_free_tx3;
return 0;
err_free_tx3:
rkisp_unregister_stream_vdev(&cap_dev->stream[RKISP_STREAM_DMATX3]);
err_free_tx2:
rkisp_unregister_stream_vdev(&cap_dev->stream[RKISP_STREAM_DMATX2]);
err_free_tx0:
@@ -1886,6 +2040,8 @@ void rkisp_unregister_stream_v21(struct rkisp_device *dev)
rkisp_unregister_stream_vdev(stream);
stream = &cap_dev->stream[RKISP_STREAM_DMATX3];
rkisp_unregister_stream_vdev(stream);
stream = &cap_dev->stream[RKISP_STREAM_VIR];
rkisp_unregister_stream_vdev(stream);
}
/**************** Interrupter Handler ****************/
@@ -1905,7 +2061,7 @@ void rkisp_mi_v21_isr(u32 mis_val, struct rkisp_device *dev)
for (i = 0; i < RKISP_MAX_STREAM; ++i) {
stream = &dev->cap_dev.stream[i];
if (!(mis_val & CIF_MI_FRAME(stream)))
if (!(mis_val & CIF_MI_FRAME(stream)) || stream->id == RKISP_STREAM_VIR)
continue;
if (i == RKISP_STREAM_DMATX0)

View File

@@ -977,7 +977,10 @@ static int mi_frame_end(struct rkisp_stream *stream, u32 state)
(stream->frame_early && state == FRAME_IRQ))
goto end;
} else {
spin_lock_irqsave(&stream->vbq_lock, lock_flags);
buf = stream->curr_buf;
stream->curr_buf = NULL;
spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
}
if (buf) {

View File

@@ -1408,7 +1408,10 @@ static int mi_frame_end(struct rkisp_stream *stream, u32 state)
(stream->frame_early && state == FRAME_IRQ))
goto end;
} else {
spin_lock_irqsave(&stream->vbq_lock, lock_flags);
buf = stream->curr_buf;
stream->curr_buf = NULL;
spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
}
if (buf) {

View File

@@ -3860,18 +3860,18 @@ void rkisp_chk_tb_over(struct rkisp_device *isp_dev)
/* wait for all isp dev to register */
if (head->camera_num > 1) {
if (head->camera_num > hw->dev_num) {
v4l2_err(&isp_dev->v4l2_dev,
"thunderboot invalid camera num:%d, dev num:%d\n",
head->camera_num, hw->dev_num);
goto end;
}
while (timeout--) {
if (hw->dev_num >= head->camera_num &&
hw->isp[hw->dev_num - 1]->is_probe_end)
break;
usleep_range(200, 210);
}
if (head->camera_num > hw->dev_num) {
v4l2_err(&isp_dev->v4l2_dev,
"thunderboot invalid camera num:%d, dev num:%d\n",
head->camera_num, hw->dev_num);
goto end;
}
}
for (i = 0; i < head->camera_num; i++)
rkisp_save_tb_info(hw->isp[i]);

View File

@@ -6,17 +6,22 @@
* Author: Hongming Zou <hongming.zou@rock-chips.com>
*/
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/rpmsg.h>
#include <linux/rpmsg/rockchip_rpmsg.h>
#include <linux/time.h>
#include <linux/virtio.h>
#define LINUX_TEST_MSG_1 "Announce master ept id!"
#define LINUX_TEST_MSG_2 "Rockchip rpmsg linux test pingpong!"
#define MSG_LIMIT 100
#define MSG_LIMIT 10000
struct instance_data {
/* different processor cores may need to adjust the value of this definition */
#define LINUX_RPMSG_COMPENSATION (1) //ms
struct rpmsg_info_t {
int rx_count;
};
@@ -25,18 +30,19 @@ static int rockchip_rpmsg_test_cb(struct rpmsg_device *rp, void *payload,
{
int ret;
uint32_t remote_ept_id;
struct instance_data *idata = dev_get_drvdata(&rp->dev);
struct rpmsg_info_t *info = dev_get_drvdata(&rp->dev);
remote_ept_id = src;
dev_info(&rp->dev, "rx msg %s rx_count %d(remote_ept_id: 0x%x)\n",
(char *)payload, ++idata->rx_count, remote_ept_id);
(char *)payload, ++info->rx_count, remote_ept_id);
/* test should not live forever */
if (idata->rx_count >= MSG_LIMIT) {
if (info->rx_count >= MSG_LIMIT) {
dev_info(&rp->dev, "Rockchip rpmsg test exit!\n");
return 0;
}
mdelay(LINUX_RPMSG_COMPENSATION);
/* send a new message now */
ret = rpmsg_sendto(rp->ept, LINUX_TEST_MSG_2, strlen(LINUX_TEST_MSG_2), remote_ept_id);
if (ret)
@@ -48,17 +54,17 @@ static int rockchip_rpmsg_test_probe(struct rpmsg_device *rp)
{
int ret;
uint32_t master_ept_id, remote_ept_id;
struct instance_data *idata;
struct rpmsg_info_t *info;
master_ept_id = rp->src;
remote_ept_id = rp->dst;
dev_info(&rp->dev, "new channel: 0x%x -> 0x%x!\n", master_ept_id, remote_ept_id);
idata = devm_kzalloc(&rp->dev, sizeof(*idata), GFP_KERNEL);
if (!idata)
info = devm_kzalloc(&rp->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
dev_set_drvdata(&rp->dev, idata);
dev_set_drvdata(&rp->dev, info);
/*
* send a message to our remote processor, and tell remote
@@ -69,7 +75,7 @@ static int rockchip_rpmsg_test_probe(struct rpmsg_device *rp)
dev_err(&rp->dev, "rpmsg_send failed: %d\n", ret);
return ret;
}
mdelay(LINUX_RPMSG_COMPENSATION);
ret = rpmsg_sendto(rp->ept, LINUX_TEST_MSG_2, strlen(LINUX_TEST_MSG_2), remote_ept_id);
if (ret) {
dev_err(&rp->dev, "rpmsg_send failed: %d\n", ret);

View File

@@ -14,6 +14,7 @@
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/rockchip/rockchip_sip.h>
#include <soc/rockchip/rockchip_amp.h>
#define RK_CPU_STATUS_OFF 0
#define RK_CPU_STATUS_ON 1

View File

@@ -586,6 +586,7 @@ static void mpp_task_timeout_work(struct work_struct *work_s)
mpp_dev_reset(mpp);
mpp_power_off(mpp);
mpp_iommu_dev_deactivate(mpp->iommu_info, mpp);
set_bit(TASK_STATE_TIMEOUT, &task->state);
set_bit(TASK_STATE_DONE, &task->state);
/* Wake up the GET thread */

View File

@@ -453,6 +453,9 @@ static int mpp_iommu_handle(struct iommu_domain *iommu,
return 0;
}
if (mpp->cur_task)
mpp_task_dump_mem_region(mpp, mpp->cur_task);
if (mpp->dev_ops && mpp->dev_ops->dump_dev)
mpp->dev_ops->dump_dev(mpp);
else

View File

@@ -1315,7 +1315,7 @@ static int rkvdec_3328_init(struct mpp_dev *mpp)
goto done;
}
dec->aux_iova = -1;
mpp->iommu_info->hdl = rkvdec_3328_iommu_hdl;
mpp->fault_handler = rkvdec_3328_iommu_hdl;
ret = rkvdec_devfreq_init(mpp);
done:

View File

@@ -1541,7 +1541,7 @@ static int rkvdec2_core_probe(struct platform_device *pdev)
mpp->dev_ops->task_worker = rkvdec2_hard_ccu_worker;
irq_proc = rkvdec2_hard_ccu_irq;
}
mpp->iommu_info->hdl = rkvdec2_ccu_iommu_fault_handle;
mpp->fault_handler = rkvdec2_ccu_iommu_fault_handle;
kthread_init_work(&mpp->work, mpp->dev_ops->task_worker);
/* get irq request */

View File

@@ -2328,9 +2328,7 @@ static int rkvdec2_hard_ccu_enqueue(struct rkvdec2_ccu *ccu,
writel(RKVDEC_CCU_BIT_CFG_DONE, ccu->reg_base + RKVDEC_CCU_CFG_DONE_BASE);
mpp_task_run_end(mpp_task, timing_en);
/* pending to running */
set_bit(TASK_STATE_RUNNING, &mpp_task->state);
mpp_taskqueue_pending_to_run(queue, mpp_task);
mpp_dbg_ccu("session %d task %d iova=%08x task->state=%lx link_mode=%08x\n",
mpp_task->session->index, mpp_task->task_index,
(u32)task->table->iova, mpp_task->state,
@@ -2503,6 +2501,7 @@ void rkvdec2_hard_ccu_worker(struct kthread_work *work_s)
rkvdec2_ccu_power_on(queue, dec->ccu);
rkvdec2_hard_ccu_enqueue(dec->ccu, mpp_task, queue, mpp);
mpp_taskqueue_pending_to_run(queue, mpp_task);
}
/* 4. poweroff when running and pending list are empty */

View File

@@ -1190,7 +1190,7 @@ static int rkvenc_init(struct mpp_dev *mpp)
}
INIT_WORK(&enc->iommu_work, rkvenc_iommu_handle_work);
mpp->iommu_info->hdl = rkvenc_iommu_fault_handle;
mpp->fault_handler = rkvenc_iommu_fault_handle;
return ret;
}

View File

@@ -2445,8 +2445,7 @@ static int rkvenc_core_probe(struct platform_device *pdev)
}
mpp->session_max_buffers = RKVENC_SESSION_MAX_BUFFERS;
enc->hw_info = to_rkvenc_info(mpp->var->hw_info);
if (mpp->iommu_info)
mpp->iommu_info->hdl = rkvenc2_iommu_fault_handle;
mpp->fault_handler = rkvenc2_iommu_fault_handle;
rkvenc_procfs_init(mpp);
rkvenc_procfs_ccu_init(mpp);