Merge commit 'c5179f362ee7db1a1771295badff67b014db03f5'

* commit 'c5179f362ee7db1a1771295badff67b014db03f5': (22 commits)
  tee: optee: interrupt an RPC depend on shutdown flag
  media: rockchip: isp: sync irq_ends
  mfd: rkx110_x120: cru: fix to get a avialble pll rate
  arm64: dts: rockchip: rk3562: adjust regulator-init-microvolt of vdd_cpu/vdd_logic for rk3562 boards
  arm64: dts: rockchip: rk3562: adjust low-temp-min-volt for cpu/dmc
  media: i2c: add sc830ai sensor driver
  dmaengine: pl330: Use tasklet_hi_schedule
  mtd: spinand: XINCUN: Support new device XCSP1AAPK
  arm64: dts: rockchip: rk3562-amp: change mcu ram address
  media: i2c: lt8668sx: add lt8668sx hdmi2csi driver
  video: rockchip: mpp: remove av1dec l2 cache
  ARM: rockchip: rv1106_pm: do wdt save/restore
  media: rockchip: isp: add buf cnt info to procfs
  media: rockchip: isp: fix wait timeout with thunderboot
  arm64: dts: rockchip: rk3528: Add thermal for macphy
  ARM: dts: rv1106: Add thermal for macphy
  net: phy: RK630: Add dynamically adjusting the configuration
  drm/bridge: dw-hdmi-qp: Fixes compilation errors when cec core is not compiled
  drm/bridge: synopsys: Fixes compilation errors when cec core is not compiled
  media: i2c: imx415 adapt sleep_wakeup
  ...

Change-Id: I854d3c5a417d626ae2559264ce87a046dc65529a
This commit is contained in:
Tao Huang
2024-01-12 19:09:39 +08:00
34 changed files with 4410 additions and 173 deletions

View File

@@ -1359,6 +1359,7 @@
nvmem-cells = <&macphy_txlevel>;
nvmem-cell-names = "txlevel";
bgs,increment = <2>;
rockchip,thermal-zone = "soc-thermal";
};
};

View File

@@ -98,6 +98,8 @@ static void __iomem *firewall_syssram_base;
static void __iomem *pmu_base;
static void __iomem *nstimer_base;
static void __iomem *stimer_base;
static void __iomem *wdt_ns_base;
static void __iomem *wdt_s_base;
static void __iomem *mbox_base;
static void __iomem *ddrc_base;
static void __iomem *ioc_base[5];
@@ -178,6 +180,10 @@ static struct reg_region vd_log_reg_rgns[] = {
{ REG_REGION(0x304, 0x32c, 4, &pericru_base, WMSK_VAL)},
{ REG_REGION(0x800, 0x81c, 4, &pericru_base, WMSK_VAL)},
/* peri_grf */
{ REG_REGION(0x000, 0x004, 4, &perigrf_base, WMSK_VAL)},
{ REG_REGION(0x090, 0x094, 4, &perigrf_base, WMSK_VAL)},
/* peri_sgrf */
{ REG_REGION(0x004, 0x014, 4, &perisgrf_base, 0)},
{ REG_REGION(0x000, 0x000, 4, &perisgrf_base, 0)},
@@ -284,6 +290,14 @@ static struct reg_region vd_log_reg_rgns[] = {
{ REG_REGION(0x10, 0x10, 4, &stimer_base, 0)},
{ REG_REGION(0x20, 0x24, 4, &stimer_base, 0)},
{ REG_REGION(0x30, 0x30, 4, &stimer_base, 0)},
/* wdt_ns */
{ REG_REGION(0x04, 0x04, 4, &wdt_ns_base, 0)},
{ REG_REGION(0x00, 0x00, 4, &wdt_ns_base, 0)},
/* wdt_s */
{ REG_REGION(0x04, 0x04, 4, &wdt_s_base, 0)},
{ REG_REGION(0x00, 0x00, 4, &wdt_s_base, 0)},
};
static int is_rv1103, is_rv1106;
@@ -1040,6 +1054,15 @@ static void vd_log_regs_restore(void)
writel_relaxed(WITH_16BITS_WMSK(cru_mode), cru_base + 0x280);
gic400_restore();
writel_relaxed(0xffff0000, pmugrf_base + RV1106_PMUGRF_SOC_CON(4));
writel_relaxed(0xffff0000, pmugrf_base + RV1106_PMUGRF_SOC_CON(5));
if (readl_relaxed(wdt_ns_base + RV1106_WDT_CR) & 0x1)
writel_relaxed(0x76, wdt_ns_base + RV1106_WDT_CRR);
if (readl_relaxed(wdt_s_base + RV1106_WDT_CR) & 0x1)
writel_relaxed(0x76, wdt_s_base + RV1106_WDT_CRR);
}
static void rkpm_reg_rgns_init(void)
@@ -1182,6 +1205,9 @@ static int __init rv1106_suspend_init(struct device_node *np)
nstimer_base = dev_reg_base + RV1106_NSTIMER_OFFSET;
stimer_base = dev_reg_base + RV1106_STIMER_OFFSET;
wdt_ns_base = dev_reg_base + RV1106_WDTNS_OFFSET;
wdt_s_base = dev_reg_base + RV1106_WDTS_OFFSET;
pmu_base = dev_reg_base + RV1106_PMU_OFFSET;
uartdbg_base = dev_reg_base + RV1106_UART2_OFFSET;
pmupvtm_base = dev_reg_base + RV1106_PMUPVTM_OFFSET;

View File

@@ -56,6 +56,8 @@
#define RV1106_NSTIMER_OFFSET 0x580000
#define RV1106_STIMER_OFFSET 0x590000
#define RV1106_WDTNS_OFFSET 0x5a0000
#define RV1106_WDTS_OFFSET 0x5b0000
#define RV1106_MBOX_OFFSET 0x5c0000
#define RV1106_PMUSRAM_OFFSET 0x670000
#define RV1106_DDRC_OFFSET 0x800000
@@ -185,6 +187,14 @@
#define RV1106_PMU_INFO_TX_CON 0x150
#define RV1106_PMU_SYS_REG(i) (0x1c0 + (i) * 4)
/* wdt */
#define RV1106_WDT_CR 0x0
#define RV1106_WDT_TORR 0x4
#define RV1106_WDT_CCVR 0x8
#define RV1106_WDT_CRR 0xc
#define RV1106_WDT_STAT 0x10
#define RV1106_WDT_EOI 0x14
#define PMU_SUSPEND_MAGIC 0x02468ace
#define PMU_RESUME_MAGIC 0x13579bdf

View File

@@ -2095,6 +2095,7 @@
pinctrl-0 = <&fephym0_led_link &fephym0_led_spd>;
nvmem-cells = <&macphy_txlevel>;
nvmem-cell-names = "txlevel";
rockchip,thermal-zone = "soc-thermal";
};
};

View File

@@ -29,7 +29,13 @@
/* remote amp core address */
amp_shmem_reserved: amp-shmem@7800000 {
reg = <0x0 0x7800000 0x0 0x400000>;
reg = <0x0 0x7800000 0x0 0x300000>;
no-map;
};
/* mcu address */
mcu_reserved: mcu@7b00000 {
reg = <0x0 0x7b00000 0x0 0x100000>;
no-map;
};
@@ -43,13 +49,6 @@
reg = <0x0 0x08000000 0x0 0x100000>;
no-map;
};
/* mcu address */
mcu_reserved: mcu@8200000 {
reg = <0x0 0x8200000 0x0 0x100000>;
no-map;
};
};
rpmsg: rpmsg@7c00000 {

View File

@@ -167,6 +167,8 @@
};
&cpu0_opp_table {
rockchip,low-temp-min-volt = <1000000>;
opp-408000000 {
/delete-property/ opp-suspend;
};
@@ -680,7 +682,7 @@
regulator-boot-on;
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1350000>;
regulator-init-microvolt = <900000>;
regulator-init-microvolt = <950000>;
regulator-ramp-delay = <6001>;
regulator-initial-mode = <0x2>;
regulator-name = "vdd_logic";
@@ -695,7 +697,7 @@
regulator-boot-on;
regulator-min-microvolt = <825000>;
regulator-max-microvolt = <1350000>;
regulator-init-microvolt = <900000>;
regulator-init-microvolt = <1000000>;
regulator-ramp-delay = <6001>;
regulator-initial-mode = <0x2>;
regulator-name = "vdd_cpu";

View File

@@ -76,7 +76,7 @@
regulator-boot-on;
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1350000>;
regulator-init-microvolt = <900000>;
regulator-init-microvolt = <950000>;
regulator-ramp-delay = <6001>;
regulator-initial-mode = <0x2>;
regulator-name = "vdd_logic";
@@ -90,7 +90,7 @@
regulator-boot-on;
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1350000>;
regulator-init-microvolt = <900000>;
regulator-init-microvolt = <1050000>;
regulator-ramp-delay = <6001>;
regulator-initial-mode = <0x2>;
regulator-name = "vdd_cpu";

View File

@@ -601,7 +601,7 @@
regulator-boot-on;
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1350000>;
regulator-init-microvolt = <900000>;
regulator-init-microvolt = <950000>;
regulator-ramp-delay = <6001>;
regulator-initial-mode = <0x2>;
regulator-name = "vdd_logic";
@@ -616,7 +616,7 @@
regulator-boot-on;
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1350000>;
regulator-init-microvolt = <900000>;
regulator-init-microvolt = <1050000>;
regulator-ramp-delay = <6001>;
regulator-initial-mode = <0x2>;
regulator-name = "vdd_cpu";

View File

@@ -72,7 +72,7 @@
regulator-boot-on;
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1350000>;
regulator-init-microvolt = <900000>;
regulator-init-microvolt = <950000>;
regulator-ramp-delay = <6001>;
regulator-initial-mode = <0x2>;
regulator-name = "vdd_logic";
@@ -87,7 +87,7 @@
regulator-boot-on;
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1350000>;
regulator-init-microvolt = <900000>;
regulator-init-microvolt = <1050000>;
regulator-ramp-delay = <6001>;
regulator-initial-mode = <0x2>;
regulator-name = "vdd_cpu";

View File

@@ -273,7 +273,7 @@
rockchip,grf = <&sys_grf>;
rockchip,temp-hysteresis = <5000>;
rockchip,low-temp = <10000>;
rockchip,low-temp-min-volt = <925000>;
rockchip,low-temp-min-volt = <1050000>;
opp-408000000 {
opp-hz = /bits/ 64 <408000000>;
@@ -501,7 +501,7 @@
rockchip,temp-hysteresis = <5000>;
rockchip,low-temp = <10000>;
rockchip,low-temp-min-volt = <900000>;
rockchip,low-temp-min-volt = <950000>;
rockchip,leakage-voltage-sel = <
1 15 0

View File

@@ -180,7 +180,7 @@
regulator-boot-on;
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1350000>;
regulator-init-microvolt = <900000>;
regulator-init-microvolt = <950000>;
regulator-ramp-delay = <6001>;
regulator-initial-mode = <0x2>;
regulator-name = "vdd_logic";
@@ -194,7 +194,7 @@
regulator-boot-on;
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1350000>;
regulator-init-microvolt = <900000>;
regulator-init-microvolt = <1050000>;
regulator-ramp-delay = <6001>;
regulator-initial-mode = <0x2>;
regulator-name = "vdd_cpu";

View File

@@ -1758,7 +1758,7 @@ static void dma_pl330_rqcb(struct dma_pl330_desc *desc, enum pl330_op_err err)
spin_unlock_irqrestore(&pch->lock, flags);
tasklet_schedule(&pch->task);
tasklet_hi_schedule(&pch->task);
}
static void pl330_dotask(struct tasklet_struct *t)

View File

@@ -3276,8 +3276,10 @@ void dw_hdmi_qp_cec_set_hpd(struct dw_hdmi_qp *hdmi, bool plug_in, bool change)
CEC_PHYS_ADDR_INVALID);
if (hdmi->bridge.dev) {
#if IS_REACHABLE(CONFIG_DRM_DW_HDMI_CEC)
if (change && hdmi->cec_adap && hdmi->cec_adap->devnode.registered)
cec_queue_pin_hpd_event(hdmi->cec_adap, plug_in, ktime_get());
#endif
drm_bridge_hpd_notify(&hdmi->bridge, status);
}
}

View File

@@ -433,10 +433,12 @@ static void repo_hpd_event(struct work_struct *p_work)
if (change) {
if (hdmi->plat_data->set_ddc_io)
hdmi->plat_data->set_ddc_io(data, hdmi->hpd_state);
#if IS_REACHABLE(CONFIG_DRM_DW_HDMI_CEC)
if (hdmi->cec_adap->devnode.registered)
cec_queue_pin_hpd_event(hdmi->cec_adap,
hdmi->hpd_state,
ktime_get());
#endif
}
drm_bridge_hpd_notify(&hdmi->bridge, status);
}

View File

@@ -1962,6 +1962,16 @@ config VIDEO_SC5336
This is a Video4Linux2 sensor driver for the SmartSens
SC5336 camera.
config VIDEO_SC830AI
tristate "SmartSens SC830AI sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the SmartSens
SC830AI camera.
config VIDEO_SC850SL
tristate "SmartSens SC850SL sensor support"
depends on I2C && VIDEO_DEV
@@ -2605,6 +2615,19 @@ config VIDEO_LT8619C
To compile this driver as a module, choose M here: the
module will be called lt8619c.
config VIDEO_LT8668SX
tristate "Lontium LT8668SX decoder"
depends on VIDEO_DEV && I2C
select HDMI
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
Support for the Lontium LT8668SX series type-c/hdmi to MIPI CSI-2 bridge.
To compile this driver as a module, choose M here: the
module will be called lt8668sx.
config VIDEO_MAX9286
tristate "Maxim MAX9286 GMSL deserializer support"
depends on I2C && I2C_MUX

View File

@@ -116,6 +116,7 @@ obj-$(CONFIG_VIDEO_LT6911UXE) += lt6911uxe.o
obj-$(CONFIG_VIDEO_LT7911D) += lt7911d.o
obj-$(CONFIG_VIDEO_LT7911UXC) += lt7911uxc.o
obj-$(CONFIG_VIDEO_LT8619C) += lt8619c.o
obj-$(CONFIG_VIDEO_LT8668SX) += lt8668sx.o
obj-$(CONFIG_VIDEO_M52790) += m52790.o
obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/
obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o
@@ -245,6 +246,7 @@ obj-$(CONFIG_VIDEO_SC500AI) += sc500ai.o
obj-$(CONFIG_VIDEO_SC501AI) += sc501ai.o
obj-$(CONFIG_VIDEO_SC530AI) += sc530ai.o
obj-$(CONFIG_VIDEO_SC5336) += sc5336.o
obj-$(CONFIG_VIDEO_SC830AI) += sc830ai.o
obj-$(CONFIG_VIDEO_SC850SL) += sc850sl.o
obj-$(CONFIG_VIDEO_SENSOR_ADAPTER) += sensor_adapter.o
obj-$(CONFIG_VIDEO_SGM3784) += sgm3784.o

View File

@@ -53,6 +53,8 @@
#include <media/v4l2-fwnode.h>
#include <linux/of_graph.h>
#include "../platform/rockchip/isp/rkisp_tb_helper.h"
#include "cam-tb-setup.h"
#include "cam-sleep-wakeup.h"
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x08)
@@ -242,6 +244,7 @@ struct imx415 {
bool has_init_exp;
struct preisp_hdrae_exp_s init_hdrae_exp;
struct v4l2_fwnode_endpoint bus_cfg;
struct cam_sw_info *cam_sw_inf;
};
static struct rkmodule_csi_dphy_param dcphy_param = {
@@ -2426,11 +2429,6 @@ int __imx415_power_on(struct imx415 *imx415)
}
if (!imx415->is_thunderboot) {
ret = regulator_bulk_enable(IMX415_NUM_SUPPLIES, imx415->supplies);
if (ret < 0) {
dev_err(dev, "Failed to enable regulators\n");
goto err_pinctrl;
}
if (!IS_ERR(imx415->power_gpio))
gpiod_direction_output(imx415->power_gpio, 1);
/* At least 500ns between power raising and XCLR */
@@ -2454,18 +2452,28 @@ int __imx415_power_on(struct imx415 *imx415)
goto err_clk;
}
cam_sw_regulator_bulk_init(imx415->cam_sw_inf, IMX415_NUM_SUPPLIES, imx415->supplies);
if (imx415->is_thunderboot)
return 0;
/* At least 20us between XCLR and I2C communication */
if (!imx415->is_thunderboot)
usleep_range(20*1000, 30*1000);
usleep_range(20*1000, 30*1000);
ret = regulator_bulk_enable(IMX415_NUM_SUPPLIES, imx415->supplies);
if (ret < 0) {
dev_err(dev, "Failed to enable regulators\n");
goto err_pinctrl;
}
return 0;
err_pinctrl:
clk_disable_unprepare(imx415->xvclk);
err_clk:
if (!IS_ERR(imx415->reset_gpio))
gpiod_direction_output(imx415->reset_gpio, 1);
regulator_bulk_disable(IMX415_NUM_SUPPLIES, imx415->supplies);
err_pinctrl:
if (!IS_ERR_OR_NULL(imx415->pins_sleep))
pinctrl_select_state(imx415->pinctrl, imx415->pins_sleep);
@@ -2500,6 +2508,51 @@ static void __imx415_power_off(struct imx415 *imx415)
regulator_bulk_disable(IMX415_NUM_SUPPLIES, imx415->supplies);
}
#if IS_REACHABLE(CONFIG_VIDEO_CAM_SLEEP_WAKEUP)
static int __maybe_unused imx415_resume(struct device *dev)
{
int ret;
struct i2c_client *client = to_i2c_client(dev);
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct imx415 *imx415 = to_imx415(sd);
cam_sw_prepare_wakeup(imx415->cam_sw_inf, dev);
usleep_range(4000, 5000);
cam_sw_write_array(imx415->cam_sw_inf);
if (__v4l2_ctrl_handler_setup(&imx415->ctrl_handler))
dev_err(dev, "__v4l2_ctrl_handler_setup fail!");
if (imx415->has_init_exp && imx415->cur_mode != NO_HDR) { // hdr mode
ret = imx415_ioctl(&imx415->subdev, PREISP_CMD_SET_HDRAE_EXP,
&imx415->cam_sw_inf->hdr_ae);
if (ret) {
dev_err(&imx415->client->dev, "set exp fail in hdr mode\n");
return ret;
}
}
return 0;
}
static int __maybe_unused imx415_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct imx415 *imx415 = to_imx415(sd);
cam_sw_write_array_cb_init(imx415->cam_sw_inf, client,
(void *)imx415->cur_mode->reg_list,
(sensor_write_array)imx415_write_array);
cam_sw_prepare_sleep(imx415->cam_sw_inf);
return 0;
}
#else
#define imx415_resume NULL
#define imx415_suspend NULL
#endif
static int __maybe_unused imx415_runtime_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -2605,6 +2658,7 @@ static int imx415_get_selection(struct v4l2_subdev *sd,
static const struct dev_pm_ops imx415_pm_ops = {
SET_RUNTIME_PM_OPS(imx415_runtime_suspend,
imx415_runtime_resume, NULL)
SET_LATE_SYSTEM_SLEEP_PM_OPS(imx415_suspend, imx415_resume)
};
#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
@@ -3018,6 +3072,14 @@ static int imx415_probe(struct i2c_client *client,
goto err_power_off;
#endif
if (!imx415->cam_sw_inf) {
imx415->cam_sw_inf = cam_sw_init();
cam_sw_clk_init(imx415->cam_sw_inf, imx415->xvclk, imx415->cur_mode->xvclk);
cam_sw_reset_pin_init(imx415->cam_sw_inf, imx415->reset_gpio, 1);
if (!IS_ERR(imx415->power_gpio))
cam_sw_pwdn_pin_init(imx415->cam_sw_inf, imx415->power_gpio, 0);
}
memset(facing, 0, sizeof(facing));
if (strcmp(imx415->module_facing, "back") == 0)
facing[0] = 'b';
@@ -3065,6 +3127,8 @@ static void imx415_remove(struct i2c_client *client)
v4l2_ctrl_handler_free(&imx415->ctrl_handler);
mutex_destroy(&imx415->mutex);
cam_sw_deinit(imx415->cam_sw_inf);
pm_runtime_disable(&client->dev);
if (!pm_runtime_status_suspended(&client->dev))
__imx415_power_off(imx415);

1794
drivers/media/i2c/lt8668sx.c Normal file

File diff suppressed because it is too large Load Diff

1930
drivers/media/i2c/sc830ai.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -81,6 +81,7 @@ MODULE_PARM_DESC(low_latency, "low_latency en(0-1)");
#define NO_LOCK_CFG_RETRY_TIME 300
#define WAIT_LOCK_STABLE_TIME 20
#define WAIT_AVI_PKT_TIME 300
#define BIG_CPU_PHY_ID 5
#define is_validfs(x) (x == 32000 || \
x == 44100 || \
@@ -4589,9 +4590,9 @@ static int hdmirx_probe(struct platform_device *pdev)
struct v4l2_device *v4l2_dev;
struct v4l2_ctrl_handler *hdl;
struct resource *res;
int ret, irq, cpu_aff;
struct hdmirx_cec_data cec_data;
struct cpumask cpumask;
int ret, irq, cpu_aff, phy_cpuid, i;
hdmirx_dev = devm_kzalloc(dev, sizeof(*hdmirx_dev), GFP_KERNEL);
if (!hdmirx_dev)
@@ -4618,12 +4619,22 @@ static int hdmirx_probe(struct platform_device *pdev)
* in order to quickly respond to FIQ and prevent them from affecting
* each other.
*/
if (sip_cpu_logical_map_mpidr(0) == 0) {
cpu_aff = sip_cpu_logical_map_mpidr(5);
hdmirx_dev->bound_cpu = 5;
} else {
cpu_aff = sip_cpu_logical_map_mpidr(1);
hdmirx_dev->bound_cpu = 1;
for (i = 0; i < 8; i++) {
cpu_aff = sip_cpu_logical_map_mpidr(i);
phy_cpuid = (cpu_aff >> 8) & 0xf;
if (phy_cpuid == BIG_CPU_PHY_ID) {
hdmirx_dev->bound_cpu = i;
hdmirx_dev->phy_cpuid = phy_cpuid;
break;
}
}
if (!hdmirx_dev->phy_cpuid) {
dev_info(dev, "%s: Failed to get phy_cpuid, use default BIG_CPU_PHY_ID!\n",
__func__);
cpu_aff = BIG_CPU_PHY_ID << 8;
hdmirx_dev->bound_cpu = BIG_CPU_PHY_ID;
hdmirx_dev->phy_cpuid = BIG_CPU_PHY_ID;
}
sip_fiq_control(RK_SIP_FIQ_CTRL_SET_AFF, RK_IRQ_HDMIRX_HDMI, cpu_aff);

View File

@@ -475,6 +475,23 @@ void rkisp_stream_buf_done_early(struct rkisp_device *dev)
}
}
int rkisp_stream_buf_cnt(struct rkisp_stream *stream)
{
unsigned long lock_flags = 0;
struct rkisp_buffer *buf, *tmp;
int cnt = 0;
spin_lock_irqsave(&stream->vbq_lock, lock_flags);
list_for_each_entry_safe(buf, tmp, &stream->buf_queue, queue)
cnt++;
if (stream->curr_buf)
cnt++;
if (stream->next_buf && stream->next_buf != stream->curr_buf)
cnt++;
spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
return cnt;
}
struct stream_config rkisp_mp_stream_config = {
/* constraints */
.max_rsz_width = STREAM_MAX_MP_RSZ_OUTPUT_WIDTH,

View File

@@ -342,4 +342,5 @@ int rkisp_fop_release(struct file *file);
int rkisp_get_tb_stream_info(struct rkisp_stream *stream,
struct rkisp_tb_stream_info *info);
int rkisp_free_tb_stream_buf(struct rkisp_stream *stream);
int rkisp_stream_buf_cnt(struct rkisp_stream *stream);
#endif /* _RKISP_PATH_VIDEO_H */

View File

@@ -833,6 +833,7 @@ static int isp_show(struct seq_file *p, void *v)
struct rkisp_device *dev = p->private;
struct rkisp_isp_subdev *sdev = &dev->isp_sdev;
struct rkisp_sensor_info *sensor = dev->active_sensor;
struct rkisp_stream *stream;
u32 val = 0;
seq_printf(p, "%-10s Version:v%02x.%02x.%02x\n",
@@ -864,7 +865,9 @@ static int isp_show(struct seq_file *p, void *v)
return 0;
if (IS_HDR_RDBK(dev->hdr.op_mode)) {
seq_printf(p, "%-10s mode:frame%d (frame:%d rate:%dms %s time:%dms frameloss:%d) cnt(total:%d X1:%d X2:%d X3:%d)\n",
stream = &dev->dmarx_dev.stream[RKISP_STREAM_RAWRD2];
seq_printf(p, "%-10s mode:frame%d (frame:%d rate:%dms state:%s time:%dms frameloss:%d)"
" cnt(total:%d X1:%d X2:%d X3:%d) rd_bufcnt:%d\n",
"Isp Read",
dev->rd_mode - 3,
dev->dmarx_dev.cur_frame.id,
@@ -875,12 +878,13 @@ static int isp_show(struct seq_file *p, void *v)
dev->rdbk_cnt,
dev->rdbk_cnt_x1,
dev->rdbk_cnt_x2,
dev->rdbk_cnt_x3);
dev->rdbk_cnt_x3,
rkisp_stream_buf_cnt(stream));
seq_printf(p, "\t hw link:%d idle:%d vir(mode:%d index:%d)\n",
dev->hw_dev->dev_link_num, dev->hw_dev->is_idle,
dev->multi_mode, dev->multi_index);
} else {
seq_printf(p, "%-10s frame:%d %s time:%dms v-blank:%dus\n",
seq_printf(p, "%-10s frame:%d state:%s time:%dms v-blank:%dus\n",
"Isp online",
sdev->dbg.id,
(dev->isp_state & ISP_FRAME_END) ? "idle" : "working",
@@ -899,11 +903,11 @@ static int isp_show(struct seq_file *p, void *v)
dev->br_dev.dbg.interval / 1000 / 1000,
dev->br_dev.dbg.frameloss);
for (val = 0; val < RKISP_MAX_STREAM; val++) {
struct rkisp_stream *stream = &dev->cap_dev.stream[val];
stream = &dev->cap_dev.stream[val];
if (!stream->streaming)
continue;
seq_printf(p, "%-10s %s Format:%c%c%c%c Size:%dx%d Dcrop(%d,%d|%dx%d) (frame:%d rate:%dms delay:%dms frameloss:%d)\n",
seq_printf(p, "%-10s %s Format:%c%c%c%c Size:%dx%d Dcrop(%d,%d|%dx%d)"
" (frame:%d rate:%dms delay:%dms frameloss:%d bufcnt:%d)\n",
"Output",
stream->vnode.vdev.name,
stream->out_fmt.pixelformat,
@@ -919,7 +923,8 @@ static int isp_show(struct seq_file *p, void *v)
stream->dbg.id,
stream->dbg.interval / 1000 / 1000,
stream->dbg.delay / 1000 / 1000,
stream->dbg.frameloss);
stream->dbg.frameloss,
rkisp_stream_buf_cnt(stream));
}
switch (dev->isp_ver) {

View File

@@ -1059,8 +1059,10 @@ static void rkisp_rdbk_work(struct work_struct *work)
void rkisp_check_idle(struct rkisp_device *dev, u32 irq)
{
unsigned long lock_flags = 0;
u32 val = 0;
spin_lock_irqsave(&dev->hw_dev->rdbk_lock, lock_flags);
dev->irq_ends |= (irq & dev->irq_ends_mask);
v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev,
"%s irq:0x%x ends:0x%x mask:0x%x\n",
@@ -1072,8 +1074,11 @@ void rkisp_check_idle(struct rkisp_device *dev, u32 irq)
complete(&dev->hw_dev->monitor.cmpl);
}
if ((dev->irq_ends & dev->irq_ends_mask) != dev->irq_ends_mask ||
!IS_HDR_RDBK(dev->rd_mode))
!IS_HDR_RDBK(dev->rd_mode)) {
spin_unlock_irqrestore(&dev->hw_dev->rdbk_lock, lock_flags);
return;
}
spin_unlock_irqrestore(&dev->hw_dev->rdbk_lock, lock_flags);
if (dev->sw_rd_cnt)
goto end;
@@ -1920,6 +1925,9 @@ static void rkisp_start_3a_run(struct rkisp_device *dev)
return;
v4l2_event_queue(vdev, &ev);
/* thunderboot no need to wait aiq first param */
if (dev->is_pre_on)
return;
/* rk3326/px30 require first params queued before
* rkisp_params_configure_isp() called
*/

View File

@@ -263,6 +263,7 @@ static HAL_Status RKX11x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
uint32_t pll;
uint8_t overMax = 0;
HAL_Status ret = HAL_OK;
int i;
if (clockName == RKX110_CLK_D_DSI_0_PATTERN_GEN ||
clockName == RKX110_CLK_D_DSI_1_PATTERN_GEN) {
@@ -326,12 +327,21 @@ static HAL_Status RKX11x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
/* PLL change closest new rate <= 1200M if need */
if (!pRate) {
pRate = (_MHZ(1200) / rate) * rate;
}
ret = RKX11x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
if (!rate || rate > _MHZ(1200))
return HAL_ERROR;
for (i = _MHZ(1200) / rate; i > _MHZ(24) / rate; i--) {
pRate = i * rate;
ret = RKX11x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret == HAL_OK)
break;
}
if (ret != HAL_OK)
return ret;
} else {
ret = RKX11x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
}
}
/* if success, continue to set divider */

View File

@@ -304,6 +304,7 @@ static HAL_Status RKX11x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
uint32_t pll;
uint8_t overMax = 0;
HAL_Status ret = HAL_OK;
int i;
if (clockName == RKX110_CLK_D_DSI_0_PATTERN_GEN) {
clockName = RKX111_CPS_DCLK_D_DSI_0_REC;
@@ -371,12 +372,21 @@ static HAL_Status RKX11x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
/* PLL change closest new rate <= 1200M if need */
if (!pRate) {
pRate = (_MHZ(1200) / rate) * rate;
}
ret = RKX11x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
if (!rate || rate > _MHZ(1200))
return HAL_ERROR;
for (i = _MHZ(1200) / rate; i > _MHZ(24) / rate; i--) {
pRate = i * rate;
ret = RKX11x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret == HAL_OK)
break;
}
if (ret != HAL_OK)
return ret;
} else {
ret = RKX11x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
}
}
/* if success, continue to set divider */

View File

@@ -252,6 +252,7 @@ static HAL_Status RKX12x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
uint32_t pll;
uint8_t overMax;
HAL_Status ret = HAL_OK;
int i;
switch (clockName) {
case RKX120_CPS_PLL_TXPLL:
@@ -298,12 +299,21 @@ static HAL_Status RKX12x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
/* PLL change closest new rate <= 1200M if need */
if (!pRate) {
pRate = (_MHZ(1200) / rate) * rate;
}
ret = RKX12x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
if (!rate || rate > _MHZ(1200))
return HAL_ERROR;
for (i = _MHZ(1200) / rate; i > _MHZ(24) / rate; i--) {
pRate = i * rate;
ret = RKX12x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret == HAL_OK)
break;
}
if (ret != HAL_OK)
return ret;
} else {
ret = RKX12x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
}
}
/* if success, continue to set divider */

View File

@@ -263,6 +263,7 @@ static HAL_Status RKX12x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
uint32_t pll;
uint8_t overMax;
HAL_Status ret = HAL_OK;
int i;
switch (clockName) {
case RKX120_CPS_PLL_TXPLL:
@@ -309,12 +310,21 @@ static HAL_Status RKX12x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
/* PLL change closest new rate <= 1200M if need */
if (!pRate) {
pRate = (_MHZ(1200) / rate) * rate;
}
ret = RKX12x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
if (!rate || rate > _MHZ(1200))
return HAL_ERROR;
for (i = _MHZ(1200) / rate; i > _MHZ(24) / rate; i--) {
pRate = i * rate;
ret = RKX12x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret == HAL_OK)
break;
}
if (ret != HAL_OK)
return ret;
} else {
ret = RKX12x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
}
}
/* if success, continue to set divider */

View File

@@ -92,6 +92,15 @@ static const struct spinand_info xincun_spinand_table[] = {
&update_cache_variants),
SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&xcsp2aapk_ooblayout, xcsp2aapk_ecc_get_status)),
SPINAND_INFO("XCSP1AAPK",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x01),
NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
NAND_ECCREQ(8, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&xcsp2aapk_ooblayout, xcsp2aapk_ecc_get_status)),
};
static const struct spinand_manufacturer_ops xincun_spinand_manuf_ops = {

View File

@@ -20,6 +20,7 @@
#include <linux/of_irq.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
#include <linux/thermal.h>
#include <linux/wakelock.h>
#define RK630_PHY_ID 0x00441400
@@ -71,6 +72,39 @@
#define T22_TX_LEVEL_100M 0x2d
#define T22_TX_LEVEL_10M 0x32
/* Long network cable parameters */
#define RX_DETECT_SCHEDULE_TIME 500 /* ms */
#define RX_DETECT_INIT_WAIT_TIME 2000 /* ms */
#define RX_DETECT_MAX_COUNT (5000 / RX_DETECT_SCHEDULE_TIME)
#define ALL_RX_DETECT_MAX_COUNT (2 * RX_DETECT_MAX_COUNT)
#define LINKED_MAX_COUNT (10000 / RX_DETECT_SCHEDULE_TIME)
#define ALL_LINKED_MAX_COUNT (2 * LINKED_MAX_COUNT)
#define RX_PACKET_RECEIVED_COUNTS 3 /* packets */
#define RX_PACKET_RECEIVED_LOST 15 /* percent */
#define RX_SIGNAL_DETECT_TEMP 85000
struct rk630_phy_switched {
/* record state */
bool config;
bool config_mode_10M;
bool finished;
/* detected process */
unsigned int detected_count;
bool config_rx_signal;
int old_link;
/* linked process */
unsigned int linked_count;
int rx_pkt_cnt;
int rx_crc_err_cnt;
int lost_percent;
};
struct rk630_phy_priv {
struct phy_device *phydev;
bool ieee;
@@ -78,6 +112,13 @@ struct rk630_phy_priv {
struct wake_lock wol_wake_lock;
int tx_level_100M;
int tx_level_10M;
struct rk630_phy_switched switched;
/* mutex protect variables between notify thread and delayed work */
struct mutex lock;
struct delayed_work service_task;
struct thermal_zone_device *tz;
bool disable_switch;
};
static void rk630_phy_t22_get_tx_level_from_efuse(struct phy_device *phydev)
@@ -192,6 +233,17 @@ static void rk630_phy_set_uaps(struct phy_device *phydev, bool enable)
phy_write(phydev, REG_PAGE_SEL, 0x0000);
}
static bool rk630_phy_rx_signal_detected(struct phy_device *phydev)
{
u32 value;
/* Switch to page 0 */
phy_write(phydev, REG_PAGE_SEL, 0x0000);
value = phy_read(phydev, 25);
return (value & BIT(15)) ? false : true;
}
static void rk630_phy_s40_config_init(struct phy_device *phydev)
{
phy_write(phydev, 0, phy_read(phydev, 0) & ~BIT(13));
@@ -229,8 +281,8 @@ static void rk630_phy_t22_config_init(struct phy_device *phydev)
phy_write(phydev, REG_PAGE_SEL, 0x0100);
/* Enable offset clock */
phy_write(phydev, 0x10, 0xfbfe);
/* Disable APS */
phy_write(phydev, REG_PAGE1_APS_CTRL, 0x4824);
/* Disable APS & Rx detected time 2s, default is 4s */
phy_write(phydev, REG_PAGE1_APS_CTRL, 0x4822);
/* Switch to page 2 */
phy_write(phydev, REG_PAGE_SEL, 0x0200);
/* PHYAFE TRX optimization */
@@ -242,7 +294,15 @@ static void rk630_phy_t22_config_init(struct phy_device *phydev)
/* PHYAFE Gain optimization */
phy_write(phydev, REG_PAGE6_GAIN_ANONTROL, 0x0400);
/* PHYAFE EQ optimization */
phy_write(phydev, REG_PAGE6_AFE_TX_CTRL, 0x1088);
if (priv->disable_switch) {
/* Rx detected default threshold 160 mv */
phy_write(phydev, REG_PAGE6_AFE_TX_CTRL, 0x1088);
} else {
/* Rx detected threshold 260 mv */
phy_write(phydev, REG_PAGE6_AFE_TX_CTRL, 0x10c8);
priv->switched.config_rx_signal = true;
}
if (priv->tx_level_100M <= 0 || priv->tx_level_10M <= 0)
rk630_phy_t22_get_tx_level_from_efuse(phydev);
@@ -305,23 +365,305 @@ static int rk630_phy_config_init(struct phy_device *phydev)
return 0;
}
static void rk630_link_change_notify(struct phy_device *phydev)
/* config0(default) and config1(0x555e) switched for 100/10M speed */
static bool rk630_phy_switch_config(struct phy_device *phydev, bool config)
{
struct rk630_phy_priv *priv = phydev->priv;
if (priv->switched.config != config) {
int val;
val = config ? 0x555e : 0x5540;
phy_write(priv->phydev, REG_PAGE_SEL, 0x0600);
phy_write(priv->phydev, REG_PAGE6_ADC_ANONTROL, val);
phy_write(priv->phydev, REG_PAGE_SEL, 0x0000);
priv->switched.config = config;
return true;
}
return false;
}
/* 10M speed configuration */
static void rk630_phy_10m_switch_config(struct phy_device *phydev, bool config)
{
struct rk630_phy_priv *priv = phydev->priv;
unsigned int val;
if (phydev->state == PHY_RUNNING || phydev->state == PHY_NOLINK) {
/* Switch to page 6 */
phy_write(phydev, REG_PAGE_SEL, 0x0600);
if (config == priv->switched.config_mode_10M)
return;
phy_write(phydev, REG_PAGE_SEL, 0x0600);
val = phy_read(phydev, REG_PAGE6_AFE_TX_CTRL);
val &= ~GENMASK(14, 13);
if (config && !priv->switched.config_mode_10M)
val |= BIT(13);
priv->switched.config_mode_10M = config;
phy_write(phydev, REG_PAGE6_AFE_TX_CTRL, val);
phy_write(priv->phydev, REG_PAGE_SEL, 0x0000);
}
static void rk630_phy_switch_rx_signal_config(struct phy_device *phydev,
bool config)
{
struct rk630_phy_priv *priv = phydev->priv;
if (priv->switched.config_rx_signal != config) {
int val;
phy_write(priv->phydev, REG_PAGE_SEL, 0x0600);
val = phy_read(phydev, REG_PAGE6_AFE_TX_CTRL);
val &= ~GENMASK(14, 13);
if (phydev->speed == SPEED_10 && phydev->link)
val |= BIT(13);
val &= ~GENMASK(7, 6);
if (config)
val |= GENMASK(7, 6);
else
val |= BIT(7);
phy_write(phydev, REG_PAGE6_AFE_TX_CTRL, val);
/* Switch to page 0 */
phy_write(phydev, REG_PAGE_SEL, 0x0000);
phy_write(priv->phydev, REG_PAGE_SEL, 0x0000);
priv->switched.config_rx_signal = config;
}
}
static void rk630_phy_packet_statistics(struct phy_device *phydev,
int *total_cnt, int *crc_err_cnt)
{
struct rk630_phy_priv *priv = phydev->priv;
phy_write(priv->phydev, REG_PAGE_SEL, 0x0900);
*total_cnt = phy_read(priv->phydev, 0x1b) << 16;
*total_cnt |= phy_read(priv->phydev, 0x1c);
*crc_err_cnt = phy_read(priv->phydev, 0x1d) << 16;
*crc_err_cnt |= phy_read(priv->phydev, 0x1e);
phy_write(phydev, REG_PAGE_SEL, 0x0000);
}
static bool rk630_phy_switch_config_by_packets(struct phy_device *phydev)
{
struct rk630_phy_priv *priv = phydev->priv;
int rx_pkt_cnt, rx_crc_err_cnt;
int total_cnt, total_crc_err_cnt;
int lost_percent;
rk630_phy_packet_statistics(phydev, &total_cnt, &total_crc_err_cnt);
rx_pkt_cnt = total_cnt - priv->switched.rx_pkt_cnt;
rx_crc_err_cnt = total_crc_err_cnt - priv->switched.rx_crc_err_cnt;
priv->switched.rx_pkt_cnt = total_cnt;
priv->switched.rx_crc_err_cnt = total_crc_err_cnt;
/* less than the minimal received packets during some time */
if (rx_pkt_cnt < RX_PACKET_RECEIVED_COUNTS)
return true;
/* Percents packets lost is not good during some time */
lost_percent = (rx_crc_err_cnt * 100 / rx_pkt_cnt) > RX_PACKET_RECEIVED_LOST;
/* Just compare with config0's packet lost, update config if it is better
* than config0.
*/
if (((rx_crc_err_cnt * 100 / rx_pkt_cnt) > RX_PACKET_RECEIVED_LOST) &&
lost_percent > priv->switched.lost_percent) {
/* Only save config0 lost percent */
if (!priv->switched.config)
priv->switched.lost_percent = lost_percent;
return true;
}
/* Only save config0 lost percent */
if (!priv->switched.config)
priv->switched.lost_percent = lost_percent;
return false;
}
static void rk630_phy_service_task(struct work_struct *work)
{
struct rk630_phy_priv *priv = container_of(work, struct rk630_phy_priv,
service_task.work);
unsigned int delay_time;
int ret, temp;
mutex_lock(&priv->lock);
if (priv->disable_switch) {
mutex_unlock(&priv->lock);
return;
}
if (!priv->phydev->link) {
bool signal_detected;
signal_detected = rk630_phy_rx_signal_detected(priv->phydev);
/* Read signal */
if (!signal_detected) {
/* Slow schedule work for 2 * SCHEDULE_TIME, if no signal */
priv->switched.detected_count = 0;
priv->switched.lost_percent = 0;
priv->switched.finished = false;
priv->switched.linked_count = 0;
delay_time = 2 * RX_DETECT_SCHEDULE_TIME;
/* Goto default config if no rj45 signal plugin */
rk630_phy_switch_config(priv->phydev, false);
/* Also go to 10M default config */
rk630_phy_10m_switch_config(priv->phydev, false);
} else {
priv->switched.detected_count++;
/* Fast schedule work for 1 * SCHEDULE_TIME, if signal
* detected.
*/
delay_time = RX_DETECT_SCHEDULE_TIME;
if (priv->switched.detected_count == RX_DETECT_MAX_COUNT &&
!priv->switched.finished) {
/* After it, there is no link, Might be a long cable,
* config1 switched to get better performance during
* some time.
*/
rk630_phy_switch_config(priv->phydev, true);
} else if (priv->switched.detected_count == ALL_RX_DETECT_MAX_COUNT &&
!priv->switched.finished) {
/* After another detect, we lost the last chance,
* go back to default config0.
*/
rk630_phy_switch_config(priv->phydev, false);
priv->switched.finished = true;
} else if (priv->switched.detected_count > ALL_RX_DETECT_MAX_COUNT ||
priv->switched.finished) {
/* Slow schedule work for 2 * SCHEDULE_TIME, if
* detected finish.
*/
delay_time = 2 * RX_DETECT_SCHEDULE_TIME;
}
}
} else {
/* Detect the packet count and crc error count statistics */
priv->switched.linked_count++;
/* Fast schedule work for 1 * SCHEDULE_TIME, if linkup detected */
delay_time = RX_DETECT_SCHEDULE_TIME;
if (priv->switched.linked_count == LINKED_MAX_COUNT &&
!priv->switched.finished) {
if (rk630_phy_switch_config_by_packets(priv->phydev)) {
/* Config1 switched to get better performance */
rk630_phy_switch_config(priv->phydev, true);
/* Also go to 10M default config */
if (priv->switched.config && priv->phydev->speed == SPEED_10)
rk630_phy_10m_switch_config(priv->phydev, true);
}
} else if (priv->switched.linked_count == ALL_LINKED_MAX_COUNT &&
!priv->switched.finished) {
/* If config switched, we lost the last chance, return to
* default config0.
*/
if (rk630_phy_switch_config_by_packets(priv->phydev)) {
rk630_phy_switch_config(priv->phydev, false);
rk630_phy_10m_switch_config(priv->phydev, false);
}
priv->switched.finished = true;
} else if (priv->switched.linked_count > ALL_LINKED_MAX_COUNT ||
priv->switched.finished) {
/* Slow schedule work for 2 * SCHEDULE_TIME, if linkup
* detected finish.
*/
delay_time = 2 * RX_DETECT_SCHEDULE_TIME;
}
}
if (priv->tz) {
ret = thermal_zone_get_temp(priv->tz, &temp);
if (ret || temp == THERMAL_TEMP_INVALID)
phydev_err(priv->phydev,
"failed to read out thermal zone (%d)\n", ret);
else
rk630_phy_switch_rx_signal_config(priv->phydev,
(temp > RX_SIGNAL_DETECT_TEMP) ? false : true);
}
schedule_delayed_work(&priv->service_task, msecs_to_jiffies(delay_time));
mutex_unlock(&priv->lock);
}
static void rk630_phy_link_change_notify(struct phy_device *phydev)
{
struct rk630_phy_priv *priv = phydev->priv;
if (phydev->mdio.addr == PHY_ADDR_T22) {
mutex_lock(&priv->lock);
if (priv->disable_switch) {
mutex_unlock(&priv->lock);
return;
}
if (priv->switched.old_link && !phydev->link) {
priv->switched.old_link = 0;
priv->switched.linked_count = 0;
schedule_delayed_work(&priv->service_task,
msecs_to_jiffies(RX_DETECT_SCHEDULE_TIME));
} else if (!priv->switched.old_link && phydev->link) {
/* If linked, keep current config, but if the linked is
* 10M speed, and config1 has been enabled, also switched
* the 10M config.
*/
if (priv->switched.config && phydev->speed == SPEED_10)
rk630_phy_10m_switch_config(phydev, true);
priv->switched.old_link = 1;
priv->switched.detected_count = 0;
/* Record base packet statistics to compare later, if linked */
if (!priv->switched.linked_count)
rk630_phy_packet_statistics(priv->phydev,
&priv->switched.rx_pkt_cnt,
&priv->switched.rx_crc_err_cnt);
schedule_delayed_work(&priv->service_task,
msecs_to_jiffies(RX_DETECT_SCHEDULE_TIME));
}
mutex_unlock(&priv->lock);
}
}
static ssize_t rk630_phy_disable_switch_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct phy_device *phydev = to_phy_device(dev);
struct rk630_phy_priv *priv = phydev->priv;
int ret;
bool disabled;
ret = kstrtobool(buf, &disabled);
if (ret)
return count;
mutex_lock(&priv->lock);
if (disabled) {
cancel_delayed_work_sync(&priv->service_task);
/* Save to default config */
rk630_phy_10m_switch_config(priv->phydev, false);
rk630_phy_switch_rx_signal_config(priv->phydev, false);
rk630_phy_switch_config(priv->phydev, false);
memset(&priv->switched, 0, sizeof(struct rk630_phy_switched));
} else {
priv->switched.old_link = phydev->link;
/* Rx detected threshold 260 mv */
rk630_phy_switch_rx_signal_config(priv->phydev, true);
schedule_delayed_work(&priv->service_task,
msecs_to_jiffies(RX_DETECT_INIT_WAIT_TIME));
}
priv->disable_switch = disabled;
dev_info(dev, "rk630 phy disable switch to %s\n", disabled ? "true" : "false");
mutex_unlock(&priv->lock);
return count;
}
static DEVICE_ATTR_WO(rk630_phy_disable_switch);
static irqreturn_t rk630_wol_irq_thread(int irq, void *dev_id)
{
struct rk630_phy_priv *priv = (struct rk630_phy_priv *)dev_id;
@@ -334,6 +676,7 @@ static irqreturn_t rk630_wol_irq_thread(int irq, void *dev_id)
static int rk630_phy_probe(struct phy_device *phydev)
{
struct rk630_phy_priv *priv;
const char *tz_name;
int ret;
priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
@@ -362,6 +705,23 @@ static int rk630_phy_probe(struct phy_device *phydev)
enable_irq_wake(priv->wol_irq);
}
mutex_init(&priv->lock);
INIT_DELAYED_WORK(&priv->service_task, rk630_phy_service_task);
priv->disable_switch = of_property_read_bool(phydev->mdio.dev.of_node,
"rk630,phy-disable-switch");
of_property_read_string(phydev->mdio.dev.of_node, "rockchip,thermal-zone",
&tz_name);
priv->tz = thermal_zone_get_zone_by_name(tz_name);
if (IS_ERR(priv->tz)) {
pr_warn("Error getting thermal zone, not yet ready?\n");
priv->tz = NULL;
}
ret = device_create_file(&phydev->mdio.dev, &dev_attr_rk630_phy_disable_switch);
if (ret)
return ret;
priv->phydev = phydev;
return 0;
@@ -384,6 +744,10 @@ static int rk630_phy_suspend(struct phy_device *phydev)
phy_write(phydev, REG_INTERRUPT_MASK, BIT(14));
enable_irq(priv->wol_irq);
}
if (!priv->disable_switch)
cancel_delayed_work_sync(&priv->service_task);
return genphy_suspend(phydev);
}
@@ -397,6 +761,10 @@ static int rk630_phy_resume(struct phy_device *phydev)
disable_irq(priv->wol_irq);
}
if (!priv->disable_switch)
schedule_delayed_work(&priv->service_task,
msecs_to_jiffies(RX_DETECT_INIT_WAIT_TIME));
return genphy_resume(phydev);
}
@@ -407,7 +775,7 @@ static struct phy_driver rk630_phy_driver[] = {
.name = "RK630 PHY",
.features = PHY_BASIC_FEATURES,
.flags = 0,
.link_change_notify = rk630_link_change_notify,
.link_change_notify = rk630_phy_link_change_notify,
.probe = rk630_phy_probe,
.remove = rk630_phy_remove,
.soft_reset = genphy_soft_reset,

View File

@@ -92,6 +92,7 @@ struct optee_supp {
struct list_head reqs;
struct idr idr;
struct completion reqs_c;
bool shutdown;
};
struct optee_smc {

View File

@@ -7,6 +7,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/arm-smccc.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -1352,6 +1353,11 @@ static void optee_shutdown(struct platform_device *pdev)
{
struct optee *optee = platform_get_drvdata(pdev);
/* Tell requesting thread to interrupt an RPC */
smp_store_mb(optee->supp.shutdown, true);
/* Wait requesting thread to release resources */
mdelay(200);
if (!optee->rpc_param_count)
optee_disable_shm_cache(optee);
}

View File

@@ -82,7 +82,6 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
struct optee_supp_req *req;
bool interruptable;
u32 ret;
unsigned long timeleft;
int id;
struct optee_supp_req *get_req;
@@ -117,14 +116,12 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
* exclusive access again.
*/
while (wait_for_completion_interruptible(&req->c)) {
pr_err("Warning, Interrupting an RPC to supplicant!\n");
timeleft = wait_for_completion_timeout(&req->c, msecs_to_jiffies(2000));
if (timeleft) {
/* get completion, it means tee-supplicant is alive. */
break;
} else {
/* timeout, it means tee-supplicant is dead, interrupting an RPC. */
if (supp->shutdown) {
/* Reboot happen, tee-supplicant is dead, interrupt an RPC */
interruptable = true;
} else {
/* Deep sleep, tee-supplicant is freeze, wait tee-supplicant */
continue;
}
mutex_lock(&supp->mutex);

View File

@@ -467,87 +467,6 @@ free_task:
#define AV1_PP_TILE_SIZE GENMASK_ULL(10, 9)
#define AV1_PP_TILE_16X16 BIT(10)
#define AV1_PP_OUT_LUMA_ADR_INDEX 326
#define AV1_PP_OUT_CHROMA_ADR_INDEX 328
#define AV1_L2_CACHE_SHAPER_CTRL 0x20
#define AV1_L2_CACHE_SHAPER_EN BIT(0)
#define AV1_L2_CACHE_INT_MASK 0x30
#define AV1_L2_CACHE_PP0_Y_CONFIG0 0x84
#define AV1_L2_CACHE_PP0_Y_CONFIG2 0x8c
#define AV1_L2_CACHE_PP0_Y_CONFIG3 0x90
#define AV1_L2_CACHE_PP0_U_CONFIG0 0x98
#define AV1_L2_CACHE_PP0_U_CONFIG2 0xa0
#define AV1_L2_CACHE_PP0_U_CONFIG3 0xa4
#define AV1_L2_CACHE_RD_ONLY_CTRL 0x204
#define AV1_L2_CACHE_RD_ONLY_CONFIG 0x208
static int av1dec_set_l2_cache(struct av1dec_dev *dec, struct av1dec_task *task)
{
int val;
u32 *regs = (u32 *)task->reg_class[0].data;
u32 width = (regs[4] >> 19) * 8;
u32 height = ((regs[4] >> 6) & 0x1fff) * 8;
u32 pixel_width = (((regs[322]) >> 27) & 0x1F) == 1 ? 8 : 16;
u32 pre_fetch_height = 136;
u32 max_h;
u32 line_cnt;
u32 line_size;
u32 line_stride;
/* channel 4, PPU0_Y Configuration */
/* afbc sharper can't use open cache.
* afbc out must be tile 16x16.
*/
if ((regs[AV1_PP_CONFIG_INDEX] & AV1_PP_TILE_SIZE) != AV1_PP_TILE_16X16) {
line_size = MPP_ALIGN(MPP_ALIGN(width * pixel_width, 8) / 8, 16);
line_stride = MPP_ALIGN(MPP_ALIGN(width * pixel_width, 8) / 8, 16) >> 4;
line_cnt = height;
max_h = pre_fetch_height;
writel_relaxed(regs[AV1_PP_OUT_LUMA_ADR_INDEX] + 0x1,
dec->reg_base[AV1DEC_CLASS_CACHE] + AV1_L2_CACHE_PP0_Y_CONFIG0);
val = line_size | (line_stride << 16);
writel_relaxed(val, dec->reg_base[AV1DEC_CLASS_CACHE] + AV1_L2_CACHE_PP0_Y_CONFIG2);
val = line_cnt | (max_h << 16);
writel_relaxed(val, dec->reg_base[AV1DEC_CLASS_CACHE] + AV1_L2_CACHE_PP0_Y_CONFIG3);
/* channel 5, PPU0_U Configuration */
line_size = MPP_ALIGN(MPP_ALIGN(width * pixel_width, 8) / 8, 16);
line_stride = MPP_ALIGN(MPP_ALIGN(width * pixel_width, 8) / 8, 16) >> 4;
line_cnt = height >> 1;
max_h = pre_fetch_height >> 1;
writel_relaxed(regs[AV1_PP_OUT_CHROMA_ADR_INDEX] + 0x1,
dec->reg_base[AV1DEC_CLASS_CACHE] + AV1_L2_CACHE_PP0_U_CONFIG0);
val = line_size | (line_stride << 16);
writel_relaxed(val, dec->reg_base[AV1DEC_CLASS_CACHE] + AV1_L2_CACHE_PP0_U_CONFIG2);
val = line_cnt | (max_h << 16);
writel_relaxed(val, dec->reg_base[AV1DEC_CLASS_CACHE] + AV1_L2_CACHE_PP0_U_CONFIG3);
/* mask cache irq */
writel_relaxed(0xf, dec->reg_base[AV1DEC_CLASS_CACHE] + AV1_L2_CACHE_INT_MASK);
/* shaper enable */
writel_relaxed(AV1_L2_CACHE_SHAPER_EN,
dec->reg_base[AV1DEC_CLASS_CACHE] + AV1_L2_CACHE_SHAPER_CTRL);
/* not enable cache en when multi tiles */
if (!(regs[10] & BIT(1)))
/* cache all en */
writel_relaxed(0x00000001, dec->reg_base[AV1DEC_CLASS_CACHE] +
AV1_L2_CACHE_RD_ONLY_CONFIG);
/* reorder_e and cache_e */
writel_relaxed(0x00000081, dec->reg_base[AV1DEC_CLASS_CACHE] +
AV1_L2_CACHE_RD_ONLY_CTRL);
/* wmb */
wmb();
}
return 0;
}
#define REG_CONTROL 0x20
#define REG_INTRENBL 0x34
#define REG_ACKNOWLEDGE 0x38
@@ -656,7 +575,6 @@ static int av1dec_run(struct mpp_dev *mpp, struct mpp_task *mpp_task)
mpp_debug_enter();
mpp_iommu_flush_tlb(mpp->iommu_info);
av1dec_set_l2_cache(dec, task);
av1dec_set_afbc(dec, task);
for (i = 0; i < task->w_req_cnt; i++) {