Merge commit '33f4a54037590ce6bf13e3568e33685dbe752588'

* commit '33f4a54037590ce6bf13e3568e33685dbe752588':
  fiq_debugger: tty write to tty fifo
  ARM: dts: rockchip: rv1106 boards: Add sdmmc idle state support
  ARM: dts: rockchip: rv1126: Add sdmmc idle state support
  ARM: dts: rockchip: add idle state for sdmmc of rv1106-pinctrl
  ARM: dts: rockchip: add idle state for sdmmc of rv1126-pinctrl
  media: i2c: max96712: version 1.04.00
  media: rockchip: vicap: fixes s_selection, support to set crop area
  media: rockchip: vicap: only enum outout formats that terminal sensor support to use
  media: rockchip: vicap: add security testing for output format
  arm64: dts: rockchip: rk3528-demo: Enable dfi
  arm64: dts: rockchip: rk3528-evb: Enable dfi
  arm64: dts: rockchip: rk3528: Add ddr related nodes
  PM / devfreq: rockchip_dmc: Add support for rk3528
  dt-bindings: devfreq: rockchip_dmc: Add rk3528 support
  PM / devfreq: rockchip-dfi: Add support for rk3528 dfi
  dt-bindings: devfreq: rockchip_dfi: Add rk3528 support

Change-Id: I57b0ee5b5bbbcbba0c40f447f4a866775d2743c7
This commit is contained in:
Tao Huang
2023-06-09 20:35:02 +08:00
27 changed files with 1009 additions and 378 deletions

View File

@@ -10,6 +10,7 @@ Required properties:
- "rockchip,rk3328-dfi" - for RK3328 SoCs.
- "rockchip,rk3368-dfi" - for RK3368 SoCs.
- "rockchip,rk3399-dfi" - for RK3399 SoCs.
- "rockchip,rk3528-dfi" - for RK3528 SoCs.
- "rockchip,rk3562-dfi" - for RK3562 SoCs.
- "rockchip,rk3568-dfi" - for RK3568 SoCs.
- "rockchip,rv1126-dfi" - for RV1126 SoCs.

View File

@@ -10,6 +10,7 @@ Required properties:
- "rockchip,rk3308-dmc" - for RK3308 SoCs.
- "rockchip,rk3328-dmc" - for RK3328 SoCs.
- "rockchip,rk3399-dmc" - for RK3399 SoCs.
- "rockchip,rk3528-dmc" - for RK3528 SoCs.
- "rockchip,rk3562-dmc" - for RK3562 SoCs.
- "rockchip,rk3568-dmc" - for RK3568 SoCs.
- "rockchip,rk3588-dmc" - for RK3588 SoCs.

View File

@@ -81,8 +81,9 @@
cap-mmc-highspeed;
cap-sd-highspeed;
disable-wp;
pinctrl-names = "default";
pinctrl-names = "normal", "idle";
pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>;
pinctrl-1 = <&sdmmc0_idle_pins &sdmmc0_det>;
status = "okay";
};

View File

@@ -286,8 +286,9 @@
cap-sdio-irq;
keep-power-in-suspend;
non-removable;
pinctrl-names = "default";
pinctrl-names = "normal", "idle";
pinctrl-0 = <&sdmmc1m1_cmd &sdmmc1m1_clk &sdmmc1m1_bus4>;
pinctrl-1 = <&sdmmc1m1_idle_pins>;
no-prescan-powerup;
post-power-on-delay-ms = <0>;
status = "okay";

View File

@@ -287,8 +287,9 @@
cap-sdio-irq;
keep-power-in-suspend;
non-removable;
pinctrl-names = "default";
pinctrl-names = "normal", "idle";
pinctrl-0 = <&sdmmc1m1_cmd &sdmmc1m1_clk &sdmmc1m1_bus4>;
pinctrl-1 = <&sdmmc1m1_idle_pins>;
no-prescan-powerup;
post-power-on-delay-ms = <0>;
status = "okay";

View File

@@ -288,8 +288,9 @@
cap-mmc-highspeed;
cap-sd-highspeed;
disable-wp;
pinctrl-names = "default";
pinctrl-names = "normal", "idle";
pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>;
pinctrl-1 = <&sdmmc0_idle_pins &sdmmc0_det>;
status = "okay";
};

View File

@@ -731,6 +731,17 @@
/* sdmmc0_det */
<3 RK_PA1 1 &pcfg_pull_up>;
};
/omit-if-no-ref/
sdmmc0_idle_pins: sdmmc0-idle-pins {
rockchip,pins =
<3 RK_PA2 RK_FUNC_GPIO &pcfg_pull_down>,
<3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_down>,
<3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_down>,
<3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_down>,
<3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_down>,
<3 RK_PA7 RK_FUNC_GPIO &pcfg_pull_down>;
};
};
sdmmc1 {
@@ -768,6 +779,17 @@
<2 RK_PA3 1 &pcfg_pull_up_drv_level_2>;
};
/omit-if-no-ref/
sdmmc1m0_idle_pins: sdmmc1m0-idle-pins {
rockchip,pins =
<2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>,
<2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_down>,
<2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_down>,
<2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_down>,
<2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_down>,
<2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_down>;
};
/omit-if-no-ref/
sdmmc1m1_bus4: sdmmc1m1-bus4 {
rockchip,pins =
@@ -794,6 +816,17 @@
/* sdmmc1_cmd_m1 */
<1 RK_PC3 5 &pcfg_pull_up_drv_level_2>;
};
/omit-if-no-ref/
sdmmc1m1_idle_pins: sdmmc1m1-idle-pins {
rockchip,pins =
<1 RK_PC0 RK_FUNC_GPIO &pcfg_pull_down>,
<1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>,
<1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>,
<1 RK_PC3 RK_FUNC_GPIO &pcfg_pull_down>,
<1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_down>,
<1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_down>;
};
};
spi0 {

View File

@@ -61,8 +61,9 @@
cap-mmc-highspeed;
cap-sd-highspeed;
disable-wp;
pinctrl-names = "default";
pinctrl-names = "normal", "idle";
pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>;
pinctrl-1 = <&sdmmc0_idle_pins &sdmmc0_det>;
vmmc-supply = <&vcc3v3_sd>;
status = "okay";
};

View File

@@ -150,8 +150,9 @@
cap-mmc-highspeed;
cap-sd-highspeed;
disable-wp;
pinctrl-names = "default";
pinctrl-names = "normal", "idle";
pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>;
pinctrl-1 = <&sdmmc0_idle_pins &sdmmc0_det>;
sd-uhs-sdr12;
sd-uhs-sdr25;
sd-uhs-sdr50;

View File

@@ -150,8 +150,9 @@
cap-mmc-highspeed;
cap-sd-highspeed;
disable-wp;
pinctrl-names = "default";
pinctrl-names = "normal", "idle";
pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>;
pinctrl-1 = <&sdmmc0_idle_pins &sdmmc0_det>;
sd-uhs-sdr12;
sd-uhs-sdr25;
sd-uhs-sdr50;

View File

@@ -140,8 +140,9 @@
cap-mmc-highspeed;
cap-sd-highspeed;
disable-wp;
pinctrl-names = "default";
pinctrl-names = "normal", "idle";
pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>;
pinctrl-1 = <&sdmmc0_idle_pins &sdmmc0_det>;
sd-uhs-sdr12;
sd-uhs-sdr25;
sd-uhs-sdr50;

View File

@@ -393,8 +393,9 @@
cap-mmc-highspeed;
cap-sd-highspeed;
disable-wp;
pinctrl-names = "default";
pinctrl-names = "normal", "idle";
pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>;
pinctrl-1 = <&sdmmc0_idle_pins &sdmmc0_det>;
vmmc-supply = <&vcc3v3_sd>;
status = "okay";
};

View File

@@ -263,8 +263,9 @@
cap-mmc-highspeed;
cap-sd-highspeed;
disable-wp;
pinctrl-names = "default";
pinctrl-names = "normal", "idle";
pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>;
pinctrl-1 = <&sdmmc0_idle_pins &sdmmc0_det>;
vmmc-supply = <&vcc3v3_sd>;
status = "okay";
};

View File

@@ -263,8 +263,9 @@
cap-mmc-highspeed;
cap-sd-highspeed;
disable-wp;
pinctrl-names = "default";
pinctrl-names = "normal", "idle";
pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>;
pinctrl-1 = <&sdmmc0_idle_pins &sdmmc0_det>;
vmmc-supply = <&vcc3v3_sd>;
status = "okay";
};

View File

@@ -1220,6 +1220,17 @@
/* sdmmc0_pwr */
<0 RK_PC0 1 &pcfg_pull_none>;
};
/omit-if-no-ref/
sdmmc0_idle_pins: sdmmc0-idle-pins {
rockchip,pins =
<1 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>,
<1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_down>,
<1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_down>,
<1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_down>,
<1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_down>,
<1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_down>;
};
};
spi0 {
/omit-if-no-ref/

View File

@@ -2371,8 +2371,9 @@
clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
fifo-depth = <0x100>;
max-frequency = <200000000>;
pinctrl-names = "default";
pinctrl-names = "normal", "idle";
pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>;
pinctrl-1 = <&sdmmc0_idle_pins &sdmmc0_det>;
status = "disabled";
};

View File

@@ -258,6 +258,10 @@
status = "okay";
};
&dfi {
status = "okay";
};
&display_subsystem {
status = "okay";
};

View File

@@ -292,6 +292,10 @@
status = "okay";
};
&dfi {
status = "okay";
};
&display_subsystem {
status = "okay";
};

View File

@@ -366,9 +366,20 @@
dmc: dmc {
compatible = "rockchip,rk3528-dmc";
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "complete";
devfreq-events = <&dfi>;
clocks = <&scmi_clk SCMI_CLK_DDR>;
clock-names = "dmc_clk";
operating-points-v2 = <&dmc_opp_table>;
upthreshold = <40>;
downdifferential = <20>;
system-status-level = <
/* system status freq level */
SYS_STATUS_NORMAL DMC_FREQ_LEVEL_HIGH
>;
auto-min-freq = <324000>;
auto-freq-en = <0>;
status = "disabled";
};
@@ -1544,6 +1555,13 @@
};
};
dfi: dfi@ff930000 {
reg = <0x0 0xff930000 0x0 0x400>;
compatible = "rockchip,rk3528-dfi";
rockchip,grf = <&grf>;
status = "disabled";
};
spi0: spi@ff9c0000 {
compatible = "rockchip,rk3066-spi";
reg = <0x0 0xff9c0000 0x0 0x1000>;

View File

@@ -52,6 +52,10 @@
#define RK3368_DFI_EN (0x30003 << 5)
#define RK3368_DFI_DIS (0x30000 << 5)
#define RK3528_PMUGRF_OFFSET 0x70000
#define RK3528_PMUGRF_OS_REG18 0x248
#define RK3528_PMUGRF_OS_REG19 0x24c
#define MAX_DMC_NUM_CH 4
#define READ_DRAMTYPE_INFO(n) (((n) >> 13) & 0x7)
#define READ_CH_INFO(n) (((n) >> 28) & 0x3)
@@ -722,6 +726,41 @@ static __maybe_unused __init int rk3328_dfi_init(struct platform_device *pdev,
return 0;
}
static __maybe_unused __init int rk3528_dfi_init(struct platform_device *pdev,
struct rockchip_dfi *data,
struct devfreq_event_desc *desc)
{
struct device_node *np = pdev->dev.of_node, *node;
struct resource *res;
u32 val_18, val_19;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
data->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(data->regs))
return PTR_ERR(data->regs);
node = of_parse_phandle(np, "rockchip,grf", 0);
if (node) {
data->regmap_grf = syscon_node_to_regmap(node);
if (IS_ERR(data->regmap_grf))
return PTR_ERR(data->regmap_grf);
}
regmap_read(data->regmap_grf, RK3528_PMUGRF_OFFSET + RK3528_PMUGRF_OS_REG18, &val_18);
regmap_read(data->regmap_grf, RK3528_PMUGRF_OFFSET + RK3528_PMUGRF_OS_REG19, &val_19);
if (READ_SYSREG_VERSION(val_19) >= 0x3)
data->dram_type = READ_DRAMTYPE_INFO_V3(val_18, val_19);
else
data->dram_type = READ_DRAMTYPE_INFO(val_18);
data->count_rate = 2;
data->ch_msk = 1;
data->clk = NULL;
desc->ops = &rockchip_dfi_ops;
return 0;
}
static const struct of_device_id rockchip_dfi_id_match[] = {
#ifdef CONFIG_CPU_PX30
{ .compatible = "rockchip,px30-dfi", .data = px30_dfi_init },
@@ -744,6 +783,9 @@ static const struct of_device_id rockchip_dfi_id_match[] = {
#ifdef CONFIG_CPU_RK3399
{ .compatible = "rockchip,rk3399-dfi", .data = rockchip_dfi_init },
#endif
#ifdef CONFIG_CPU_RK3528
{ .compatible = "rockchip,rk3528-dfi", .data = rk3528_dfi_init },
#endif
#ifdef CONFIG_CPU_RK3562
{ .compatible = "rockchip,rk3562-dfi", .data = px30_dfi_init },
#endif

View File

@@ -1771,6 +1771,79 @@ static __maybe_unused int rk3399_dmc_init(struct platform_device *pdev,
return 0;
}
static __maybe_unused int rk3528_dmc_init(struct platform_device *pdev,
struct rockchip_dmcfreq *dmcfreq)
{
struct arm_smccc_res res;
int ret;
int complt_irq;
u32 complt_hwirq;
struct irq_data *complt_irq_data;
res = sip_smc_dram(0, 0, ROCKCHIP_SIP_CONFIG_DRAM_GET_VERSION);
dev_notice(&pdev->dev, "current ATF version 0x%lx\n", res.a1);
if (res.a0 || res.a1 < 0x100) {
dev_err(&pdev->dev, "trusted firmware need update to V1.00 and above.\n");
return -ENXIO;
}
/*
* first 4KB is used for interface parameters
* after 4KB is dts parameters
* request share memory size 4KB * 2
*/
res = sip_smc_request_share_mem(2, SHARE_PAGE_TYPE_DDR);
if (res.a0 != 0) {
dev_err(&pdev->dev, "no ATF memory for init\n");
return -ENOMEM;
}
ddr_psci_param = (struct share_params *)res.a1;
/* Clear ddr_psci_param, size is 4KB * 2 */
memset_io(ddr_psci_param, 0x0, 4096 * 2);
wait_ctrl.dcf_en = 0;
init_waitqueue_head(&wait_ctrl.wait_wq);
wait_ctrl.wait_en = 1;
wait_ctrl.wait_time_out_ms = 17 * 5;
complt_irq = platform_get_irq_byname(pdev, "complete");
if (complt_irq < 0) {
dev_err(&pdev->dev, "no IRQ for complt_irq: %d\n", complt_irq);
return complt_irq;
}
wait_ctrl.complt_irq = complt_irq;
ret = devm_request_irq(&pdev->dev, complt_irq, wait_dcf_complete_irq,
0, dev_name(&pdev->dev), &wait_ctrl);
if (ret < 0) {
dev_err(&pdev->dev, "cannot request complt_irq\n");
return ret;
}
disable_irq(complt_irq);
complt_irq_data = irq_get_irq_data(complt_irq);
complt_hwirq = irqd_to_hwirq(complt_irq_data);
ddr_psci_param->complt_hwirq = complt_hwirq;
res = sip_smc_dram(SHARE_PAGE_TYPE_DDR, 0, ROCKCHIP_SIP_CONFIG_DRAM_INIT);
if (res.a0) {
dev_err(&pdev->dev, "rockchip_sip_config_dram_init error:%lx\n", res.a0);
return -ENOMEM;
}
ret = rockchip_get_freq_info(dmcfreq);
if (ret < 0) {
dev_err(&pdev->dev, "cannot get frequency info\n");
return ret;
}
dmcfreq->is_set_rate_direct = true;
dmcfreq->set_auto_self_refresh = rockchip_ddr_set_auto_self_refresh;
return 0;
}
static __maybe_unused int rk3568_dmc_init(struct platform_device *pdev,
struct rockchip_dmcfreq *dmcfreq)
{
@@ -2039,7 +2112,7 @@ static const struct of_device_id rockchip_dmcfreq_of_match[] = {
{ .compatible = "rockchip,rk3399-dmc", .data = rk3399_dmc_init },
#endif
#if IS_ENABLED(CONFIG_CPU_RK3528)
{ .compatible = "rockchip,rk3528-dmc", .data = NULL },
{ .compatible = "rockchip,rk3528-dmc", .data = rk3528_dmc_init },
#endif
#if IS_ENABLED(CONFIG_CPU_RK3562)
{ .compatible = "rockchip,rk3562-dmc", .data = rk3568_dmc_init },

File diff suppressed because it is too large Load Diff

View File

@@ -345,8 +345,35 @@ static const struct cif_output_fmt out_fmts[] = {
.raw_bpp = 10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SRGGB16,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 16,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGRBG16,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 16,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGBRG16,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 16,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SBGGR16,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 16,
.fmt_type = CIF_FMT_TYPE_RAW,
}
/* TODO: We can support NV12M/NV21M/NV16M/NV61M too */
};
@@ -524,6 +551,136 @@ static const struct cif_input_fmt in_fmts[] = {
}
};
static int rkcif_output_fmt_check(struct rkcif_stream *stream,
const struct cif_output_fmt *output_fmt)
{
const struct cif_input_fmt *input_fmt = stream->cif_fmt_in;
struct csi_channel_info *channel = &stream->cifdev->channels[stream->id];
int ret = -EINVAL;
switch (input_fmt->mbus_code) {
case MEDIA_BUS_FMT_YUYV8_2X8:
case MEDIA_BUS_FMT_YVYU8_2X8:
case MEDIA_BUS_FMT_UYVY8_2X8:
case MEDIA_BUS_FMT_VYUY8_2X8:
if (output_fmt->fourcc == V4L2_PIX_FMT_NV16 ||
output_fmt->fourcc == V4L2_PIX_FMT_NV61 ||
output_fmt->fourcc == V4L2_PIX_FMT_NV12 ||
output_fmt->fourcc == V4L2_PIX_FMT_NV21 ||
output_fmt->fourcc == V4L2_PIX_FMT_YUYV ||
output_fmt->fourcc == V4L2_PIX_FMT_YVYU ||
output_fmt->fourcc == V4L2_PIX_FMT_UYVY ||
output_fmt->fourcc == V4L2_PIX_FMT_VYUY)
ret = 0;
break;
case MEDIA_BUS_FMT_SBGGR8_1X8:
case MEDIA_BUS_FMT_SGBRG8_1X8:
case MEDIA_BUS_FMT_SGRBG8_1X8:
case MEDIA_BUS_FMT_SRGGB8_1X8:
case MEDIA_BUS_FMT_Y8_1X8:
if (output_fmt->fourcc == V4L2_PIX_FMT_SRGGB8 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGRBG8 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGBRG8 ||
output_fmt->fourcc == V4L2_PIX_FMT_SBGGR8 ||
output_fmt->fourcc == V4L2_PIX_FMT_GREY)
ret = 0;
break;
case MEDIA_BUS_FMT_SBGGR10_1X10:
case MEDIA_BUS_FMT_SGBRG10_1X10:
case MEDIA_BUS_FMT_SGRBG10_1X10:
case MEDIA_BUS_FMT_SRGGB10_1X10:
case MEDIA_BUS_FMT_Y10_1X10:
if (output_fmt->fourcc == V4L2_PIX_FMT_SRGGB10 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGRBG10 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGBRG10 ||
output_fmt->fourcc == V4L2_PIX_FMT_SBGGR10 ||
output_fmt->fourcc == V4L2_PIX_FMT_Y10)
ret = 0;
break;
case MEDIA_BUS_FMT_SBGGR12_1X12:
case MEDIA_BUS_FMT_SGBRG12_1X12:
case MEDIA_BUS_FMT_SGRBG12_1X12:
case MEDIA_BUS_FMT_SRGGB12_1X12:
case MEDIA_BUS_FMT_Y12_1X12:
if (output_fmt->fourcc == V4L2_PIX_FMT_SRGGB12 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGRBG12 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGBRG12 ||
output_fmt->fourcc == V4L2_PIX_FMT_SBGGR12 ||
output_fmt->fourcc == V4L2_PIX_FMT_Y12)
ret = 0;
break;
case MEDIA_BUS_FMT_RGB888_1X24:
case MEDIA_BUS_FMT_BGR888_1X24:
if (output_fmt->fourcc == V4L2_PIX_FMT_RGB24 ||
output_fmt->fourcc == V4L2_PIX_FMT_BGR24)
ret = 0;
break;
case MEDIA_BUS_FMT_RGB565_1X16:
if (output_fmt->fourcc == V4L2_PIX_FMT_RGB565)
ret = 0;
break;
case MEDIA_BUS_FMT_EBD_1X8:
if (output_fmt->fourcc == V4l2_PIX_FMT_EBD8 ||
(channel->data_bit == 8 &&
(output_fmt->fourcc == V4L2_PIX_FMT_SRGGB8 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGRBG8 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGBRG8 ||
output_fmt->fourcc == V4L2_PIX_FMT_SBGGR8)) ||
(channel->data_bit == 10 &&
(output_fmt->fourcc == V4L2_PIX_FMT_SRGGB10 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGRBG10 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGBRG10 ||
output_fmt->fourcc == V4L2_PIX_FMT_SBGGR10)) ||
(channel->data_bit == 12 &&
(output_fmt->fourcc == V4L2_PIX_FMT_SRGGB12 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGRBG12 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGBRG12 ||
output_fmt->fourcc == V4L2_PIX_FMT_SBGGR12)) ||
(channel->data_bit == 16 &&
(output_fmt->fourcc == V4L2_PIX_FMT_SRGGB16 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGRBG16 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGBRG16 ||
output_fmt->fourcc == V4L2_PIX_FMT_SBGGR16)))
ret = 0;
break;
case MEDIA_BUS_FMT_SPD_2X8:
if (output_fmt->fourcc == V4l2_PIX_FMT_SPD16 ||
(channel->data_bit == 8 &&
(output_fmt->fourcc == V4L2_PIX_FMT_SRGGB8 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGRBG8 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGBRG8 ||
output_fmt->fourcc == V4L2_PIX_FMT_SBGGR8)) ||
(channel->data_bit == 10 &&
(output_fmt->fourcc == V4L2_PIX_FMT_SRGGB10 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGRBG10 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGBRG10 ||
output_fmt->fourcc == V4L2_PIX_FMT_SBGGR10)) ||
(channel->data_bit == 12 &&
(output_fmt->fourcc == V4L2_PIX_FMT_SRGGB12 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGRBG12 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGBRG12 ||
output_fmt->fourcc == V4L2_PIX_FMT_SBGGR12)) ||
(channel->data_bit == 16 &&
(output_fmt->fourcc == V4L2_PIX_FMT_SRGGB16 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGRBG16 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGBRG16 ||
output_fmt->fourcc == V4L2_PIX_FMT_SBGGR16)))
ret = 0;
break;
default:
break;
}
if (ret)
v4l2_err(&stream->cifdev->v4l2_dev,
"input mbus_code 0x%x, can't transform to %c%c%c%c\n",
input_fmt->mbus_code,
output_fmt->fourcc & 0xff,
(output_fmt->fourcc >> 8) & 0xff,
(output_fmt->fourcc >> 16) & 0xff,
(output_fmt->fourcc >> 24) & 0xff);
return ret;
}
static int rkcif_stop_dma_capture(struct rkcif_stream *stream);
struct rkcif_rx_buffer *to_cif_rx_buf(struct rkisp_rx_buf *dbufs)
@@ -5742,6 +5899,10 @@ int rkcif_set_fmt(struct rkcif_stream *stream,
return -EINVAL;
}
ret = rkcif_output_fmt_check(stream, fmt);
if (ret)
return -EINVAL;
if (dev->terminal_sensor.sd) {
ret = v4l2_subdev_call(dev->terminal_sensor.sd,
core, ioctl,
@@ -6164,12 +6325,42 @@ static int rkcif_enum_fmt_vid_cap_mplane(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
const struct cif_output_fmt *fmt = NULL;
struct rkcif_stream *stream = video_drvdata(file);
struct rkcif_device *dev = stream->cifdev;
const struct cif_input_fmt *cif_fmt_in = NULL;
struct v4l2_rect input_rect;
int i = 0;
int ret = 0;
int fource_idx = 0;
if (f->index >= ARRAY_SIZE(out_fmts))
return -EINVAL;
fmt = &out_fmts[f->index];
f->pixelformat = fmt->fourcc;
if (dev->terminal_sensor.sd) {
cif_fmt_in = get_input_fmt(dev->terminal_sensor.sd,
&input_rect, stream->id,
&dev->channels[stream->id]);
stream->cif_fmt_in = cif_fmt_in;
} else {
v4l2_err(&stream->cifdev->v4l2_dev,
"terminal subdev does not exist\n");
return -EINVAL;
}
if (f->index != 0)
fource_idx = stream->new_fource_idx;
for (i = fource_idx; i < ARRAY_SIZE(out_fmts); i++) {
fmt = &out_fmts[i];
ret = rkcif_output_fmt_check(stream, fmt);
if (!ret) {
f->pixelformat = fmt->fourcc;
stream->new_fource_idx = i + 1;
break;
}
}
if (i == ARRAY_SIZE(out_fmts))
return -EINVAL;
switch (f->pixelformat) {
case V4l2_PIX_FMT_EBD8:
@@ -6263,6 +6454,9 @@ static int rkcif_s_selection(struct file *file, void *fh,
struct rkcif_device *dev = stream->cifdev;
struct v4l2_subdev *sensor_sd;
struct v4l2_subdev_selection sd_sel;
const struct v4l2_rect *rect = &s->r;
struct v4l2_rect sensor_crop;
struct v4l2_rect *raw_rect = &dev->terminal_sensor.raw_rect;
u16 pad = 0;
int ret = 0;
@@ -6271,18 +6465,69 @@ static int rkcif_s_selection(struct file *file, void *fh,
goto err;
}
sensor_sd = get_remote_sensor(stream, &pad);
if (s->target == V4L2_SEL_TGT_CROP_BOUNDS) {
sensor_sd = get_remote_sensor(stream, &pad);
sd_sel.r = s->r;
sd_sel.pad = pad;
sd_sel.target = s->target;
sd_sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
sd_sel.r = s->r;
sd_sel.pad = pad;
sd_sel.target = s->target;
sd_sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
ret = v4l2_subdev_call(sensor_sd, pad, set_selection, NULL, &sd_sel);
if (!ret) {
s->r = sd_sel.r;
v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, "%s: pad:%d, which:%d, target:%d\n",
__func__, pad, sd_sel.which, sd_sel.target);
ret = v4l2_subdev_call(sensor_sd, pad, set_selection, NULL, &sd_sel);
if (!ret) {
s->r = sd_sel.r;
v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, "%s: pad:%d, which:%d, target:%d\n",
__func__, pad, sd_sel.which, sd_sel.target);
}
} else if (s->target == V4L2_SEL_TGT_CROP) {
ret = rkcif_sanity_check_fmt(stream, rect);
if (ret) {
v4l2_err(&dev->v4l2_dev, "set crop failed\n");
return ret;
}
if (stream->crop_mask & CROP_SRC_SENSOR) {
sensor_crop = stream->crop[CROP_SRC_SENSOR];
if (rect->left + rect->width > sensor_crop.width ||
rect->top + rect->height > sensor_crop.height) {
v4l2_err(&dev->v4l2_dev,
"crop size is bigger than sensor input:left:%d, top:%d, width:%d, height:%d\n",
sensor_crop.left, sensor_crop.top,
sensor_crop.width, sensor_crop.height);
return -EINVAL;
}
} else {
if (rect->left + rect->width > raw_rect->width ||
rect->top + rect->height > raw_rect->height) {
v4l2_err(&dev->v4l2_dev,
"crop size is bigger than sensor raw input:left:%d, top:%d, width:%d, height:%d\n",
raw_rect->left, raw_rect->top,
raw_rect->width, raw_rect->height);
return -EINVAL;
}
}
stream->crop[CROP_SRC_USR] = *rect;
stream->crop_enable = true;
stream->crop_mask |= CROP_SRC_USR_MASK;
stream->crop[CROP_SRC_ACT] = stream->crop[CROP_SRC_USR];
if (stream->crop_mask & CROP_SRC_SENSOR) {
sensor_crop = stream->crop[CROP_SRC_SENSOR];
stream->crop[CROP_SRC_ACT].left = sensor_crop.left + stream->crop[CROP_SRC_USR].left;
stream->crop[CROP_SRC_ACT].top = sensor_crop.top + stream->crop[CROP_SRC_USR].top;
}
if (stream->state == RKCIF_STATE_STREAMING) {
stream->crop_dyn_en = true;
v4l2_info(&dev->v4l2_dev, "enable dynamic crop, S_SELECTION(%ux%u@%u:%u) target: %d\n",
rect->width, rect->height, rect->left, rect->top, s->target);
} else {
v4l2_info(&dev->v4l2_dev, "static crop, S_SELECTION(%ux%u@%u:%u) target: %d\n",
rect->width, rect->height, rect->left, rect->top, s->target);
}
} else {
goto err;
}
return ret;

View File

@@ -535,6 +535,7 @@ struct rkcif_stream {
struct list_head vb_done_list;
int last_rx_buf_idx;
int last_frame_idx;
int new_fource_idx;
bool stopping;
bool crop_enable;
bool crop_dyn_en;

View File

@@ -1201,6 +1201,15 @@ static void fiq_tty_close(struct tty_struct *tty, struct file *filp)
tty_port_close(tty->port, tty, filp);
}
void fiq_tty_wake_up(struct platform_device *pdev)
{
struct fiq_debugger_state *state = platform_get_drvdata(pdev);
if (tty_port_initialized(&state->tty_port))
tty_port_tty_wakeup(&state->tty_port);
}
EXPORT_SYMBOL_GPL(fiq_tty_wake_up);
static int fiq_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
int i;
@@ -1211,6 +1220,11 @@ static int fiq_tty_write(struct tty_struct *tty, const unsigned char *buf, int c
if (!state->console_enable)
return count;
#ifdef CONFIG_RK_CONSOLE_THREAD
if (state->pdata->tty_write)
return state->pdata->tty_write(state->pdev, buf, count);
#endif
fiq_debugger_uart_enable(state);
#ifndef CONFIG_RK_CONSOLE_THREAD
spin_lock_irq(&state->console_lock);
@@ -1227,7 +1241,15 @@ static int fiq_tty_write(struct tty_struct *tty, const unsigned char *buf, int c
static unsigned int fiq_tty_write_room(struct tty_struct *tty)
{
return 16;
#ifdef CONFIG_RK_CONSOLE_THREAD
int line = tty->index;
struct fiq_debugger_state **states = tty->driver->driver_state;
struct fiq_debugger_state *state = states[line];
if (state->pdata->write_room)
return state->pdata->write_room(state->pdev);
#endif
return 2048;
}
#ifdef CONFIG_CONSOLE_POLL

View File

@@ -63,6 +63,8 @@ struct fiq_debugger_pdata {
#ifdef CONFIG_RK_CONSOLE_THREAD
void (*console_write)(struct platform_device *pdev, const char *s,
unsigned int count);
int (*tty_write)(struct platform_device *pdev, const char *s, int count);
int (*write_room)(struct platform_device *pdev);
#endif
#ifdef CONFIG_FIQ_DEBUGGER_TRUST_ZONE
void (*switch_cpu)(struct platform_device *pdev, u32 cpu);
@@ -75,4 +77,5 @@ void gic_set_irq_secure(struct irq_data *d);
void gic_set_irq_priority(struct irq_data *d, u8 pri);
#endif
void fiq_tty_wake_up(struct platform_device *pdev);
#endif

View File

@@ -229,23 +229,32 @@ static void debug_flush(struct platform_device *pdev)
#ifdef CONFIG_RK_CONSOLE_THREAD
#define FIFO_SIZE SZ_64K
#define LINE_MAX 1024
#define TTY_FIFO_SIZE SZ_64K
static DEFINE_KFIFO(fifo, unsigned char, FIFO_SIZE);
static char console_buf[LINE_MAX]; /* avoid FRAME WARN */
static DEFINE_KFIFO(tty_fifo, unsigned char, TTY_FIFO_SIZE);
static bool console_thread_stop; /* write on console_write */
static bool console_thread_running; /* write on console_thread */
static unsigned int console_dropped_messages;
static int write_room(struct platform_device *pdev)
{
return (TTY_FIFO_SIZE - kfifo_len(&tty_fifo));
}
static void console_putc(struct platform_device *pdev, unsigned int c)
{
struct rk_fiq_debugger *t;
unsigned int count = 500;
unsigned int count = 2; /* loop 2 times is enough */
unsigned long us = 400; /* the time to send 60 byte for baudrate 1500000 */
t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
if (t->baudrate == 115200)
us = 5160; /* the time to send 60 byte for baudrate 115200 */
while (!(rk_fiq_read(t, UART_USR) & UART_USR_TX_FIFO_NOT_FULL) &&
count--)
usleep_range(200, 210);
usleep_range(us, us + us / 20);
rk_fiq_write(t, c, UART_TX);
}
@@ -253,12 +262,16 @@ static void console_putc(struct platform_device *pdev, unsigned int c)
static void console_flush(struct platform_device *pdev)
{
struct rk_fiq_debugger *t;
unsigned int count = 500;
unsigned int count = 2; /* loop 2 times is enough */
unsigned long us = 428; /* the time to send 64 byte for baudrate 1500000 */
t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
if (t->baudrate == 115200)
us = 5500; /* the time to send 64 byte for baudrate 115200 */
while (!(rk_fiq_read_lsr(t) & UART_LSR_TEMT) && count--)
usleep_range(200, 210);
usleep_range(us, us + us / 20);
}
static void console_put(struct platform_device *pdev,
@@ -281,17 +294,47 @@ static void debug_put(struct platform_device *pdev,
}
}
static void wake_up_console_thread(struct task_struct *console_task)
{
/*
* Avoid dead lock on console_task->pi_lock and console_lock
* when call printk() in try_to_wake_up().
*
* cpu0 hold console_lock, then try lock pi_lock fail:
* printk()->vprintk_emit()->console_unlock()->try_to_wake_up()
* ->lock(pi_lock)->deadlock
*
* cpu1 hold pi_lock, then try lock console_lock fail:
* console_thread()->console_put()->usleep_range()->run_hrtimer()
* ->hrtimer_wakeup()->try_to_wake_up()[hold_pi_lock]->printk()
* ->vprintk_emit()->console_trylock_spining()->cpu_relax()->deadlock
*
* if cpu0 does not hold console_lock, cpu1 also deadlock on pi_lock:
* ...->hrtimer_wakeup()->try_to_wake_up()[hold_pi_lock]->printk()
* ->vprintk_emit()->console_unlock()->try_to_wake_up()
* ->lock(pi_lock)->deadlock
*
* so when console_task is running on usleep_range(), printk()
* should not wakeup console_task to avoid lock(pi_lock) again,
* as run_hrtimer() will wakeup console_task later.
* console_thread_running==false guarantee that console_task
* is not running on usleep_range().
*/
if (!READ_ONCE(console_thread_running))
wake_up_process(console_task);
}
static int console_thread(void *data)
{
struct platform_device *pdev = data;
char *buf = console_buf;
unsigned int len;
char buf[64], c = 0;
unsigned int len = 0, len_tty = 0;
while (1) {
unsigned int dropped;
set_current_state(TASK_INTERRUPTIBLE);
if (kfifo_is_empty(&fifo)) {
if (kfifo_is_empty(&fifo) && kfifo_is_empty(&tty_fifo)) {
smp_store_mb(console_thread_running, false);
schedule();
smp_store_mb(console_thread_running, true);
@@ -299,18 +342,31 @@ static int console_thread(void *data)
if (kthread_should_stop())
break;
set_current_state(TASK_RUNNING);
while (!console_thread_stop) {
len = kfifo_out(&fifo, buf, LINE_MAX);
if (!len)
break;
console_put(pdev, buf, len);
while (!console_thread_stop && (!kfifo_is_empty(&fifo) || !kfifo_is_empty(&tty_fifo))) {
while (kfifo_get(&fifo, &c)) {
console_put(pdev, &c, 1);
if (c == '\n')
break;
}
while (kfifo_get(&tty_fifo, &c)) {
console_putc(pdev, c);
len_tty++;
if (c == '\n')
break;
}
}
if (len_tty > 0)
fiq_tty_wake_up(pdev);
len_tty = 0;
dropped = console_dropped_messages;
if (dropped && !console_thread_stop) {
console_dropped_messages = 0;
smp_wmb();
len = snprintf(buf, LINE_MAX,
"** %u console messages dropped **\n",
len = sprintf(buf, "** %u console messages dropped **\n",
dropped);
console_put(pdev, buf, len);
}
@@ -346,43 +402,35 @@ static void console_write(struct platform_device *pdev, const char *s, unsigned
} else if (count) {
unsigned int ret = 0;
if (kfifo_len(&fifo) + count < FIFO_SIZE)
if (kfifo_len(&fifo) + count <= FIFO_SIZE)
ret = kfifo_in(&fifo, s, count);
if (!ret) {
console_dropped_messages++;
smp_wmb();
} else {
/*
* Avoid dead lock on console_task->pi_lock and console_lock
* when call printk() in try_to_wake_up().
*
* cpu0 hold console_lock, then try lock pi_lock fail:
* printk()->vprintk_emit()->console_unlock()->try_to_wake_up()
* ->lock(pi_lock)->deadlock
*
* cpu1 hold pi_lock, then try lock console_lock fail:
* console_thread()->console_put()->usleep_range()->run_hrtimer()
* ->hrtimer_wakeup()->try_to_wake_up()[hold_pi_lock]->printk()
* ->vprintk_emit()->console_trylock_spining()->cpu_relax()->deadlock
*
* if cpu0 does not hold console_lock, cpu1 also deadlock on pi_lock:
* ...->hrtimer_wakeup()->try_to_wake_up()[hold_pi_lock]->printk()
* ->vprintk_emit()->console_unlock()->try_to_wake_up()
* ->lock(pi_lock)->deadlock
*
* so when console_task is running on usleep_range(), printk()
* should not wakeup console_task to avoid lock(pi_lock) again,
* as run_hrtimer() will wakeup console_task later.
* console_thread_running==false guarantee that console_task
* is not running on usleep_range().
*/
if (!READ_ONCE(console_thread_running))
wake_up_process(t->console_task);
wake_up_console_thread(t->console_task);
}
}
}
#endif
static int tty_write(struct platform_device *pdev, const char *s, int count)
{
unsigned int ret = 0;
struct rk_fiq_debugger *t;
t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
if (count > 0) {
if (kfifo_len(&tty_fifo) + count <= TTY_FIFO_SIZE)
ret = kfifo_in(&tty_fifo, s, count);
if (ret <= 0)
return 0;
wake_up_console_thread(t->console_task);
}
return count;
}
#endif
static void fiq_enable(struct platform_device *pdev, unsigned int irq, bool on)
{
@@ -889,8 +937,11 @@ static void rk_serial_debug_init(void __iomem *base, phys_addr_t phy_base,
#ifdef CONFIG_RK_CONSOLE_THREAD
t->console_task = kthread_run(console_thread, pdev, "kconsole");
if (!IS_ERR(t->console_task))
if (!IS_ERR(t->console_task)) {
t->pdata.console_write = console_write;
t->pdata.tty_write = tty_write;
t->pdata.write_room = write_room;
}
#endif
pdev->name = "fiq_debugger";