mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 10:31:46 +09:00
Merge commit 'd4a3012c2476400a7fa77dd204c2266c375b8961'
* commit 'd4a3012c2476400a7fa77dd204c2266c375b8961': video: rockchip: rga3: remove dependency on CONFIG_IOMMU_IOVA media: rockchip: avsp: add support for fbce head offset media: rockchip: fec: add module parameter user_debug drm/rockchip: dw-dp: mst mode don't allow external bridge create connector drm/rockchip: dp_aux_client: parse timing by child node name arm64: dts: rockchip: rv1126b-evb2-v10: fixes error of cam reset pin of sc850sl media: rockchip: fec: add support for offset and stride configuration arm64: dts: rockchip: rv1126b: update opp-table for cpu/npu clk: rockchip: clk-pvtpll: update cpu/npu pvtpll config for rv1126b PCI: rockchip: dw_ep: Support rockchip,ep-power-independent PCI: rockchip: dw-ep: Support setting link_gen PCI: rockchip: dw-ep: Support ltssm fifo debug PCI: rockchip: dw-ep: Support BAR1 and BAR5 mmap misc: rockchip: pcie-rkep: Support BAR1 and BAR5 mmap PCI: rockchip: dw-ep: Support link up status double check media: i2c: sc450ai: adjust 2lane setting vblank value video: rockchip: rga3: fix crash caused by vir_addr call in 'mm' debug mode Change-Id: I3699ca41f8387c56fef9f10e41f07dd969a0f65e
This commit is contained in:
@@ -585,7 +585,7 @@
|
||||
};
|
||||
|
||||
&sc850sl {
|
||||
reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_LOW>;
|
||||
reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
&sdmmc0 {
|
||||
|
||||
@@ -308,15 +308,15 @@
|
||||
nvmem-cell-names = "leakage";
|
||||
|
||||
rockchip,pvtm-voltage-sel = <
|
||||
0 1639 0
|
||||
1640 1684 1
|
||||
1685 1729 2
|
||||
1730 1774 3
|
||||
1775 1819 4
|
||||
1820 1864 5
|
||||
1865 1909 6
|
||||
1910 1954 7
|
||||
1955 1999 8
|
||||
0 1669 0
|
||||
1670 1714 1
|
||||
1715 1759 2
|
||||
1760 1804 3
|
||||
1805 1849 4
|
||||
1850 1894 5
|
||||
1895 1939 6
|
||||
1940 1984 7
|
||||
1985 2029 8
|
||||
>;
|
||||
rockchip,pvtm-pvtpll;
|
||||
rockchip,pvtm-offset = <0x54>;
|
||||
@@ -354,52 +354,44 @@
|
||||
};
|
||||
opp-1200000000 {
|
||||
opp-hz = /bits/ 64 <1200000000>;
|
||||
opp-microvolt = <900000 900000 1050000>;
|
||||
opp-microvolt = <900000 900000 1100000>;
|
||||
opp-microvolt-L0 = <950000 950000 1100000>;
|
||||
opp-microvolt-L1 = <925000 925000 1100000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
opp-1296000000 {
|
||||
opp-hz = /bits/ 64 <1296000000>;
|
||||
opp-microvolt = <900000 900000 1050000>;
|
||||
opp-microvolt = <950000 950000 1100000>;
|
||||
opp-microvolt-L0 = <1000000 1000000 1100000>;
|
||||
opp-microvolt-L1 = <975000 975000 1100000>;
|
||||
opp-microvolt-L2 = <950000 950000 1100000>;
|
||||
opp-microvolt-L3 = <925000 925000 1100000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
opp-1416000000 {
|
||||
opp-hz = /bits/ 64 <1416000000>;
|
||||
opp-microvolt = <900000 900000 1050000>;
|
||||
opp-microvolt = <950000 950000 1100000>;
|
||||
opp-microvolt-L0 = <1025000 1025000 1100000>;
|
||||
opp-microvolt-L1 = <1000000 1000000 1100000>;
|
||||
opp-microvolt-L2 = <975000 975000 1100000>;
|
||||
opp-microvolt-L3 = <950000 950000 1100000>;
|
||||
opp-microvolt-L4 = <925000 925000 1100000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
opp-1512000000 {
|
||||
opp-hz = /bits/ 64 <1512000000>;
|
||||
opp-microvolt = <900000 900000 1050000>;
|
||||
opp-microvolt = <950000 950000 1100000>;
|
||||
opp-microvolt-L0 = <1050000 1050000 1100000>;
|
||||
opp-microvolt-L1 = <1025000 1025000 1100000>;
|
||||
opp-microvolt-L2 = <1000000 1000000 1100000>;
|
||||
opp-microvolt-L3 = <975000 975000 1100000>;
|
||||
opp-microvolt-L4 = <950000 950000 1100000>;
|
||||
opp-microvolt-L5 = <925000 925000 1100000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
opp-1608000000 {
|
||||
opp-hz = /bits/ 64 <1608000000>;
|
||||
opp-microvolt = <900000 900000 1050000>;
|
||||
opp-microvolt = <950000 950000 1100000>;
|
||||
opp-microvolt-L0 = <1100000 1100000 1100000>;
|
||||
opp-microvolt-L1 = <1075000 1075000 1100000>;
|
||||
opp-microvolt-L2 = <1050000 1050000 1100000>;
|
||||
opp-microvolt-L3 = <1025000 1025000 1100000>;
|
||||
opp-microvolt-L4 = <1000000 1000000 1100000>;
|
||||
opp-microvolt-L5 = <975000 975000 1100000>;
|
||||
opp-microvolt-L6 = <950000 950000 1100000>;
|
||||
opp-microvolt-L7 = <925000 925000 1100000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
};
|
||||
@@ -3321,37 +3313,31 @@
|
||||
|
||||
opp-396000000 {
|
||||
opp-hz = /bits/ 64 <396000000>;
|
||||
opp-microvolt = <850000 850000 1000000>;
|
||||
opp-microvolt = <850000 850000 1050000>;
|
||||
opp-microvolt-L0 = <900000 900000 1050000>;
|
||||
opp-microvolt-L1 = <875000 875000 1050000>;
|
||||
};
|
||||
opp-700000000 {
|
||||
opp-hz = /bits/ 64 <700000000>;
|
||||
opp-microvolt = <850000 850000 1000000>;
|
||||
opp-microvolt = <850000 850000 1050000>;
|
||||
opp-microvolt-L0 = <900000 900000 1050000>;
|
||||
opp-microvolt-L1 = <875000 875000 1050000>;
|
||||
};
|
||||
opp-800000000 {
|
||||
opp-hz = /bits/ 64 <800000000>;
|
||||
opp-microvolt = <850000 850000 1000000>;
|
||||
opp-microvolt = <900000 900000 1050000>;
|
||||
opp-microvolt-L0 = <925000 925000 1050000>;
|
||||
opp-microvolt-L1 = <900000 900000 1050000>;
|
||||
opp-microvolt-L2 = <875000 875000 1050000>;
|
||||
};
|
||||
opp-900000000 {
|
||||
opp-hz = /bits/ 64 <900000000>;
|
||||
opp-microvolt = <900000 900000 1000000>;
|
||||
opp-microvolt = <950000 950000 1050000>;
|
||||
opp-microvolt-L0 = <975000 975000 1050000>;
|
||||
opp-microvolt-L1 = <950000 950000 1050000>;
|
||||
opp-microvolt-L2 = <925000 925000 1050000>;
|
||||
};
|
||||
opp-950000000 {
|
||||
opp-hz = /bits/ 64 <950000000>;
|
||||
opp-microvolt = <900000 900000 1050000>;
|
||||
opp-microvolt = <950000 950000 1050000>;
|
||||
opp-microvolt-L0 = <1000000 1000000 1050000>;
|
||||
opp-microvolt-L1 = <975000 975000 1050000>;
|
||||
opp-microvolt-L2 = <950000 950000 1050000>;
|
||||
opp-microvolt-L3 = <925000 925000 1050000>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -152,10 +152,10 @@ static struct pvtpll_table rv1126b_aisp_pvtpll_table[] = {
|
||||
|
||||
static struct pvtpll_table rv1126b_core_pvtpll_table[] = {
|
||||
/* rate_hz, ring_sel, length */
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(1608000000, 0, 30, 0),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(1512000000, 0, 30, 7),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(1416000000, 0, 34, 6),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(1296000000, 0, 38, 5),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(1608000000, 0, 30, 7),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(1512000000, 0, 30, 5),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(1416000000, 0, 34, 4),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(1296000000, 0, 38, 3),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(1200000000, 0, 38, 3),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(1008000000, 0, 52, 3),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(816000000, 0, 84, 3),
|
||||
@@ -173,10 +173,10 @@ static struct pvtpll_table rv1126b_isp_pvtpll_table[] = {
|
||||
|
||||
static struct pvtpll_table rv1126b_npu_pvtpll_table[] = {
|
||||
/* rate_hz, ring_se, length, volt_sel_thr */
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(1000000000, 0, 12, 7),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(950000000, 0, 12, 5),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(900000000, 0, 14, 4),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(800000000, 0, 16, 4),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(1000000000, 0, 12, 5),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(950000000, 0, 12, 3),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(900000000, 0, 14, 2),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(800000000, 0, 16, 2),
|
||||
ROCKCHIP_PVTPLL_VOLT_SEL(700000000, 0, 36, 3),
|
||||
};
|
||||
|
||||
|
||||
@@ -4145,7 +4145,8 @@ static int dw_dp_mst_find_ext_bridges(struct dw_dp *dp)
|
||||
return ret;
|
||||
|
||||
if (mst_enc->next_bridge) {
|
||||
ret = drm_bridge_attach(&mst_enc->encoder, mst_enc->next_bridge, NULL, 0);
|
||||
ret = drm_bridge_attach(&mst_enc->encoder, mst_enc->next_bridge, NULL,
|
||||
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dp->dev, "failed to attach next bridge: %d\n", ret);
|
||||
return ret;
|
||||
|
||||
@@ -183,6 +183,7 @@ static int rockchip_dp_aux_client_parse(struct rockchip_dp_aux_client *aux_clien
|
||||
struct drm_display_mode mode_buf, *mode = &mode_buf;
|
||||
int rc, port_num, i;
|
||||
struct edid *edid;
|
||||
char name[10];
|
||||
|
||||
const u8 edid_buf[EDID_LENGTH] = {
|
||||
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x44, 0x6D,
|
||||
@@ -205,13 +206,18 @@ static int rockchip_dp_aux_client_parse(struct rockchip_dp_aux_client *aux_clien
|
||||
if (!ports)
|
||||
return -ENOMEM;
|
||||
|
||||
i = 0;
|
||||
for_each_child_of_node(of_node, node) {
|
||||
for (i = 0; i < port_num; i++) {
|
||||
struct display_timing dt;
|
||||
struct videomode vm;
|
||||
|
||||
snprintf(name, sizeof(name), "mst-dp%d", i);
|
||||
node = of_get_child_by_name(of_node, name);
|
||||
if (!node)
|
||||
return -EINVAL;
|
||||
|
||||
edid = kzalloc(sizeof(*edid), GFP_KERNEL);
|
||||
if (!edid) {
|
||||
of_node_put(node);
|
||||
rc = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
@@ -222,13 +228,13 @@ static int rockchip_dp_aux_client_parse(struct rockchip_dp_aux_client *aux_clien
|
||||
drm_display_mode_from_videomode(&vm, mode);
|
||||
rockchip_dp_sim_update_dtd(edid, mode);
|
||||
}
|
||||
of_node_put(node);
|
||||
|
||||
rockchip_dp_sim_update_checksum(edid);
|
||||
memcpy(&ports[i], &output_port, sizeof(*ports));
|
||||
ports[i].peer_guid[0] = i;
|
||||
ports[i].edid = (u8 *)edid;
|
||||
ports[i].edid_size = sizeof(*edid);
|
||||
i++;
|
||||
}
|
||||
|
||||
rc = rockchip_dp_mst_sim_update(aux_client->mst_ctx, port_num, ports);
|
||||
|
||||
@@ -408,10 +408,11 @@ static const struct regval sc450ai_linear_10_2688x1520_30fps_2lane_regs[] = {
|
||||
{0x3209, 0x80},
|
||||
{0x320a, 0x05},
|
||||
{0x320b, 0xf0},
|
||||
{0x320c, 0x02},
|
||||
{0x320c, 0x02}, //hts
|
||||
{0x320d, 0xee},
|
||||
{0x320e, 0x06},
|
||||
{0x320f, 0x18},
|
||||
{0x320e, 0x06}, //vts
|
||||
// {0x320f, 0x18},
|
||||
{0x320f, 0x38},
|
||||
{0x3214, 0x11},
|
||||
{0x3215, 0x11},
|
||||
{0x3220, 0x00},
|
||||
@@ -1197,7 +1198,7 @@ static const struct sc450ai_mode supported_modes_2lane[] = {
|
||||
},
|
||||
.exp_def = 0x0080,//mark
|
||||
.hts_def = 0x2ee * 4,
|
||||
.vts_def = 0x0618,
|
||||
.vts_def = 0x0638,
|
||||
.bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
|
||||
.reg_list = sc450ai_linear_10_2688x1520_30fps_2lane_regs,
|
||||
.hdr_mode = NO_HDR,
|
||||
|
||||
@@ -342,12 +342,14 @@ static int avsp_rcs_run(struct file *file, struct rkavsp_rcs_in_out *buf)
|
||||
writel(val, base + AVSP_RCS_WR_C_BASE);
|
||||
break;
|
||||
case AVSP_MODE_FBCE:
|
||||
out_offs = rcs_wr_stride_c * in_h;
|
||||
c_addr = val + (rcs_out_start_offset / 64) * 16;
|
||||
writel(c_addr, base + AVSP_RCS_WR_C_BASE);
|
||||
val += ((rcs_out_start_offset / 64) * 384);
|
||||
out_offs = rcs_wr_stride_c * in_h + ((rcs_out_start_offset / 64) * 384);
|
||||
val += out_offs;
|
||||
writel(val, base + AVSP_RCS_WR_Y_BASE);
|
||||
|
||||
val = out_offs;
|
||||
writel(val << 4, base + AVSP_RCS_WR_FBCE_HEAD_OFFSET);
|
||||
break;
|
||||
default:
|
||||
val += (rcs_out_start_offset * 6);
|
||||
|
||||
@@ -21,6 +21,10 @@ static int rkfec_cache_linesize = 2;
|
||||
module_param_named(cache_linesize, rkfec_cache_linesize, int, 0644);
|
||||
MODULE_PARM_DESC(cache_linesize, "Cache linesize (0-3)");
|
||||
|
||||
static int rkfec_user_debug;
|
||||
module_param_named(user_debug, rkfec_user_debug, int, 0644);
|
||||
MODULE_PARM_DESC(user_debug, "Debug level (0-6)");
|
||||
|
||||
#if IS_LINUX_VERSION_AT_LEAST_6_1
|
||||
#define GET_SG_TABLE(mem_ops, off_buf) mem_ops->cookie(&(off_buf)->vb, (off_buf)->mem)
|
||||
#else
|
||||
@@ -273,8 +277,13 @@ static int fec_running(struct file *file, struct rkfec_in_out *buf)
|
||||
u32 val;
|
||||
u32 in_w = buf->in_width, in_h = buf->in_height;
|
||||
u32 out_w = buf->out_width, out_h = buf->out_height;
|
||||
/* Calculate virtual width in bytes */
|
||||
u32 in_stride, out_stride_y, out_stride_uv;
|
||||
/* Calculate uv offset in bytes */
|
||||
u32 in_uv_offset, out_uv_offset;
|
||||
/* Calculate byte offset based on pixel offset */
|
||||
u32 in_y_start = 0, in_uv_start = 0, out_y_start = 0, out_uv_start = 0;
|
||||
u32 y_base, c_base;
|
||||
void __iomem *base = ofl->hw->base_addr;
|
||||
int ret = -EINVAL;
|
||||
ktime_t t = 0;
|
||||
@@ -289,6 +298,11 @@ static int fec_running(struct file *file, struct rkfec_in_out *buf)
|
||||
buf->out_fourcc, buf->out_fourcc >> 8,
|
||||
buf->out_fourcc >> 16, buf->out_fourcc >> 24);
|
||||
|
||||
v4l2_dbg(3, rkfec_debug, &ofl->v4l2_dev,
|
||||
"in: stride %d, offset %d, out: stride %d, offset %d\n",
|
||||
buf->buf_cfg.in_stride, buf->buf_cfg.in_offs,
|
||||
buf->buf_cfg.out_stride, buf->buf_cfg.out_offs);
|
||||
|
||||
if (hw->fec_ver == RKFEC_V20) {
|
||||
if (hw->soft_reset)
|
||||
hw->soft_reset(hw);
|
||||
@@ -310,14 +324,18 @@ static int fec_running(struct file *file, struct rkfec_in_out *buf)
|
||||
case V4L2_PIX_FMT_NV12:
|
||||
in_fmt = SW_FEC_RD_FMT(1);
|
||||
rd_mode = SW_FEC_RD_MODE(0);
|
||||
in_stride = (buf->buf_cfg.in_stride + 15) / 16 * 16;
|
||||
in_stride = ALIGN(buf->buf_cfg.in_stride, 16);
|
||||
in_uv_offset = in_stride * in_h;
|
||||
in_y_start = buf->buf_cfg.in_offs;
|
||||
in_uv_start = in_y_start;
|
||||
break;
|
||||
case V4L2_PIX_FMT_TILE420:
|
||||
in_fmt = SW_FEC_RD_FMT(0);
|
||||
rd_mode = SW_FEC_RD_MODE(1);
|
||||
in_stride = (buf->buf_cfg.in_stride * 6 + 15) / 16 * 16;
|
||||
in_stride = ALIGN(buf->buf_cfg.in_stride * 6, 16);
|
||||
in_uv_offset = in_stride * in_h;
|
||||
in_y_start = buf->buf_cfg.in_offs * 6;
|
||||
in_uv_start = in_y_start;
|
||||
break;
|
||||
default:
|
||||
v4l2_err(&ofl->v4l2_dev,
|
||||
@@ -331,16 +349,20 @@ static int fec_running(struct file *file, struct rkfec_in_out *buf)
|
||||
case V4L2_PIX_FMT_NV12:
|
||||
out_fmt = SW_FEC_WR_FMT(1);
|
||||
wr_mode = SW_FEC_WR_MODE(0);
|
||||
out_stride_y = (buf->buf_cfg.out_stride + 15) / 16 * 16;
|
||||
out_stride_y = ALIGN(buf->buf_cfg.out_stride, 16);
|
||||
out_stride_uv = out_stride_y;
|
||||
out_uv_offset = out_stride_y * out_h;
|
||||
out_y_start = buf->buf_cfg.out_offs;
|
||||
out_uv_start = out_y_start;
|
||||
break;
|
||||
case V4L2_PIX_FMT_TILE420:
|
||||
out_fmt = SW_FEC_WR_FMT(0);
|
||||
wr_mode = SW_FEC_WR_MODE(1);
|
||||
out_stride_y = (buf->buf_cfg.out_stride * 6 + 15) / 16 * 16;
|
||||
out_stride_y = ALIGN(buf->buf_cfg.out_stride * 6, 16);
|
||||
out_stride_uv = out_stride_y;
|
||||
out_uv_offset = out_stride_y * out_h;
|
||||
out_y_start = buf->buf_cfg.out_offs * 6;
|
||||
out_uv_start = out_y_start;
|
||||
break;
|
||||
case V4L2_PIX_FMT_FBC0:
|
||||
out_fmt = SW_FEC_WR_FMT(0);
|
||||
@@ -349,13 +371,24 @@ static int fec_running(struct file *file, struct rkfec_in_out *buf)
|
||||
out_stride_uv = (buf->buf_cfg.out_stride + 63) / 64 * 16;
|
||||
// Head stride is c channel
|
||||
out_uv_offset = out_stride_uv * out_h / 4;
|
||||
out_y_start = buf->buf_cfg.out_offs / 64 * 384;
|
||||
out_uv_start = buf->buf_cfg.out_offs / 64 * 16;
|
||||
break;
|
||||
case V4L2_PIX_FMT_QUAD:
|
||||
out_fmt = SW_FEC_WR_FMT(0);
|
||||
wr_mode = SW_FEC_WR_MODE(3);
|
||||
out_stride_y = (buf->buf_cfg.out_stride * 3 + 15) / 16 * 16;
|
||||
out_stride_y = ALIGN(buf->buf_cfg.out_stride * 3, 16);
|
||||
out_stride_uv = out_stride_y;
|
||||
out_uv_offset = out_stride_y * out_h;
|
||||
|
||||
if (buf->buf_cfg.out_offs > 0) {
|
||||
v4l2_err(&ofl->v4l2_dev,
|
||||
"Offset is not supported in %c%c%c%c\n",
|
||||
buf->out_fourcc, buf->out_fourcc >> 8,
|
||||
buf->out_fourcc >> 16, buf->out_fourcc >> 24);
|
||||
out_y_start = 0;
|
||||
out_uv_start = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
v4l2_err(&ofl->v4l2_dev, "no support out format:%c%c%c%c\n",
|
||||
@@ -372,11 +405,10 @@ static int fec_running(struct file *file, struct rkfec_in_out *buf)
|
||||
sg_talbe = GET_SG_TABLE(mem_ops, off_buf);
|
||||
if (!sg_talbe)
|
||||
goto free_buf;
|
||||
val = sg_dma_address(sg_talbe->sgl);
|
||||
val += buf->buf_cfg.in_offs;
|
||||
writel(val, base + RKFEC_RD_Y_BASE);
|
||||
val += in_uv_offset;
|
||||
writel(val, base + RKFEC_RD_C_BASE);
|
||||
y_base = sg_dma_address(sg_talbe->sgl);
|
||||
c_base = y_base + in_uv_offset;
|
||||
writel(y_base + in_y_start, base + RKFEC_RD_Y_BASE);
|
||||
writel(c_base + in_uv_start, base + RKFEC_RD_C_BASE);
|
||||
|
||||
/* output picture buf */
|
||||
off_buf = buf_add(file, buf->buf_cfg.out_pic_fd, buf->buf_cfg.out_size);
|
||||
@@ -386,21 +418,21 @@ static int fec_running(struct file *file, struct rkfec_in_out *buf)
|
||||
sg_talbe = GET_SG_TABLE(mem_ops, off_buf);
|
||||
if (!sg_talbe)
|
||||
goto free_buf;
|
||||
val = sg_dma_address(sg_talbe->sgl);
|
||||
if (buf->out_fourcc == V4L2_PIX_FMT_FBC0) {
|
||||
val += buf->buf_cfg.out_offs;
|
||||
writel(val, base + RKFEC_WR_C_BASE);
|
||||
val += out_uv_offset;
|
||||
writel(val, base + RKFEC_WR_Y_BASE);
|
||||
c_base = sg_dma_address(sg_talbe->sgl);
|
||||
y_base = c_base + out_uv_offset;
|
||||
|
||||
val = SW_FEC_WR_FBCE_HEAD_OFFSET(out_uv_offset);
|
||||
writel(val, base + RKFEC_WR_FBCE_HEAD_OFFSET);
|
||||
if (buf->buf_cfg.out_offs > 0)
|
||||
writel((out_uv_offset + out_y_start) << 4,
|
||||
base + RKFEC_WR_FBCE_HEAD_OFFSET);
|
||||
else
|
||||
writel(out_uv_offset << 4, base + RKFEC_WR_FBCE_HEAD_OFFSET);
|
||||
} else {
|
||||
val += buf->buf_cfg.out_offs;
|
||||
writel(val, base + RKFEC_WR_Y_BASE);
|
||||
val += out_uv_offset;
|
||||
writel(val, base + RKFEC_WR_C_BASE);
|
||||
y_base = sg_dma_address(sg_talbe->sgl);
|
||||
c_base = y_base + out_uv_offset;
|
||||
}
|
||||
writel(y_base + out_y_start, base + RKFEC_WR_Y_BASE);
|
||||
writel(c_base + out_uv_start, base + RKFEC_WR_C_BASE);
|
||||
|
||||
/* lut buf */
|
||||
off_buf = buf_add(file, buf->buf_cfg.lut_fd, buf->buf_cfg.lut_size);
|
||||
@@ -465,14 +497,16 @@ static int fec_running(struct file *file, struct rkfec_in_out *buf)
|
||||
ofl->in_fmt.width = in_w;
|
||||
ofl->in_fmt.height = in_h;
|
||||
ofl->in_fmt.pixelformat = buf->in_fourcc;
|
||||
ofl->in_fmt.bytesperline = buf->buf_cfg.in_stride;
|
||||
ofl->in_fmt.bytesperline = in_stride;
|
||||
ofl->in_fmt.sizeimage = buf->buf_cfg.in_size;
|
||||
ofl->in_fmt.offset = buf->buf_cfg.in_offs;
|
||||
|
||||
ofl->out_fmt.width = out_w;
|
||||
ofl->out_fmt.height = out_h;
|
||||
ofl->out_fmt.pixelformat = buf->out_fourcc;
|
||||
ofl->out_fmt.bytesperline = buf->buf_cfg.out_stride;
|
||||
ofl->out_fmt.bytesperline = out_stride_y;
|
||||
ofl->out_fmt.sizeimage = buf->buf_cfg.out_size;
|
||||
ofl->out_fmt.offset = buf->buf_cfg.out_offs;
|
||||
|
||||
ret = wait_for_completion_timeout(&ofl->cmpl, msecs_to_jiffies(300));
|
||||
if (!ret) {
|
||||
|
||||
@@ -37,13 +37,21 @@ static void offline_fec_show_hw(struct seq_file *p, struct rkfec_hw_dev *hw)
|
||||
"4x4"
|
||||
};
|
||||
|
||||
static const char * const cacheline[] = {
|
||||
"64B",
|
||||
"64B",
|
||||
"128B",
|
||||
"128B"
|
||||
};
|
||||
|
||||
if (hw->dev->power.usage_count.counter <= 0) {
|
||||
seq_printf(p, "\n%s\n", "HW close");
|
||||
return;
|
||||
}
|
||||
|
||||
val = readl(hw->base_addr + RKFEC_CTRL);
|
||||
seq_printf(p, "%-10s RD_fmt:%s RD_mode:%s WR_fmt:%s WR_mode:%s WR_fbce:%s (0x%x)\n", "CTRL",
|
||||
seq_printf(p, "%-10s RD_fmt:%s RD_mode:%s WR_fmt:%s WR_mode:%s WR_fbce_unc:%s (0x%x)\n",
|
||||
"CTRL",
|
||||
val & BIT(2) ? "semi" : "interleave",
|
||||
(val >> 4) & 0x3 ? "semi" : "rast",
|
||||
val & BIT(8) ? "semi" : "interleave", wr_mode[val >> 9],
|
||||
@@ -75,6 +83,9 @@ static void offline_fec_show_hw(struct seq_file *p, struct rkfec_hw_dev *hw)
|
||||
|
||||
val = readl(hw->base_addr + RKFEC_STATUS1);
|
||||
seq_printf(p, "%-10s 0x%x\n", "STATUS1", val & 0x3FFFFF);
|
||||
|
||||
val = readl(hw->base_addr + RKFEC_CACHE_CTRL);
|
||||
seq_printf(p, "%-10s %s\n", "Cacheline", cacheline[(val >> 4) & 0x3]);
|
||||
}
|
||||
|
||||
static int offline_fec_show(struct seq_file *p, void *v)
|
||||
@@ -110,7 +121,7 @@ static int offline_fec_show(struct seq_file *p, void *v)
|
||||
ofl->debug.frameloss,
|
||||
ofl->debug.frame_timeout_cnt);
|
||||
|
||||
seq_printf(p, "%-10s Format:%c%c%c%c Size:%dx%d Sizeimage(%d) (frame:%d rate:%dms frameloss:%d\n",
|
||||
seq_printf(p, "%-10s Format:%c%c%c%c Size:%dx%d Offset(%d) Sizeimage(%d) (frame:%d rate:%dms frameloss:%d\n",
|
||||
"Output",
|
||||
ofl->out_fmt.pixelformat,
|
||||
ofl->out_fmt.pixelformat >> 8,
|
||||
@@ -118,6 +129,7 @@ static int offline_fec_show(struct seq_file *p, void *v)
|
||||
ofl->out_fmt.pixelformat >> 24,
|
||||
ofl->out_fmt.width,
|
||||
ofl->out_fmt.height,
|
||||
ofl->out_fmt.offset,
|
||||
ofl->out_fmt.sizeimage,
|
||||
ofl->curr_frame.fe_seq,
|
||||
(u32)(ofl->curr_frame.fe_timestamp - ofl->prev_frame.fe_timestamp) / 1000 / 1000,
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
#include "stream.h"
|
||||
#include "common.h"
|
||||
|
||||
static int rkfec_user_debug;
|
||||
module_param_named(user_debug, rkfec_user_debug, int, 0644);
|
||||
MODULE_PARM_DESC(user_debug, "Debug level (0-6)");
|
||||
|
||||
struct rkispp_fec_buf {
|
||||
struct list_head list;
|
||||
struct file *file;
|
||||
|
||||
@@ -558,6 +558,14 @@ static int pcie_rkep_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
}
|
||||
addr = pci_resource_start(dev, 0);
|
||||
break;
|
||||
case PCIE_EP_MMAP_RESOURCE_BAR1:
|
||||
bar_size = pci_resource_len(dev, 1);
|
||||
if (size > bar_size) {
|
||||
dev_warn(&pcie_rkep->pdev->dev, "bar1 mmap size is out of limitation\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
addr = pci_resource_start(dev, 1);
|
||||
break;
|
||||
case PCIE_EP_MMAP_RESOURCE_BAR2:
|
||||
bar_size = pci_resource_len(dev, 2);
|
||||
if (size > bar_size) {
|
||||
@@ -574,6 +582,14 @@ static int pcie_rkep_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
}
|
||||
addr = pci_resource_start(dev, 4);
|
||||
break;
|
||||
case PCIE_EP_MMAP_RESOURCE_BAR5:
|
||||
bar_size = pci_resource_len(dev, 5);
|
||||
if (size > bar_size) {
|
||||
dev_warn(&pcie_rkep->pdev->dev, "bar5 mmap size is out of limitation\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
addr = pci_resource_start(dev, 5);
|
||||
break;
|
||||
case PCIE_EP_MMAP_RESOURCE_USER_MEM:
|
||||
if (size > RKEP_USER_MEM_SIZE) {
|
||||
dev_warn(&pcie_rkep->pdev->dev, "mmap size is out of limitation\n");
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <uapi/linux/rk-pcie-ep.h>
|
||||
|
||||
#include "../../pci.h"
|
||||
#include "../rockchip-pcie-dma.h"
|
||||
#include "pcie-designware.h"
|
||||
#include "pcie-dw-dmatest.h"
|
||||
@@ -35,6 +36,17 @@
|
||||
|
||||
#define to_rockchip_pcie(x) dev_get_drvdata((x)->dev)
|
||||
|
||||
#define RK_PCIE_DBG 0
|
||||
|
||||
#define PCIE_CLIENT_DBG_FIFO_MODE_CON 0x310
|
||||
#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0 0x320
|
||||
#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1 0x324
|
||||
#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0 0x328
|
||||
#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1 0x32c
|
||||
#define PCIE_CLIENT_DBG_FIFO_STATUS 0x350
|
||||
#define PCIE_CLIENT_DBG_TRANSITION_DATA 0xffff0000
|
||||
#define PCIE_CLIENT_DBF_EN 0xffff0007
|
||||
|
||||
#define PCIE_DMA_OFFSET 0x380000
|
||||
|
||||
#define PCIE_DMA_CTRL_OFF 0x8
|
||||
@@ -114,6 +126,8 @@
|
||||
#define PCIE_BAR_MAX_NUM 6
|
||||
#define PCIE_HOTRESET_TMOUT_US 10000
|
||||
|
||||
#define PCIE_WAKE_DELAY_US 2000 /* 2 ms */
|
||||
|
||||
struct rockchip_pcie {
|
||||
struct dw_pcie pci;
|
||||
void __iomem *apb_base;
|
||||
@@ -121,7 +135,11 @@ struct rockchip_pcie {
|
||||
struct clk_bulk_data *clks;
|
||||
int clk_cnt;
|
||||
struct reset_control *rst;
|
||||
struct gpio_desc *rst_gpio;
|
||||
struct gpio_desc *perst_gpio;
|
||||
struct gpio_desc *wake_gpio;
|
||||
int perst_irq;
|
||||
bool ep_power_independent;
|
||||
struct completion ep_perst_deassert_complete;
|
||||
unsigned long *ib_window_map;
|
||||
unsigned long *ob_window_map;
|
||||
u32 num_ib_windows;
|
||||
@@ -160,6 +178,8 @@ static const struct of_device_id rockchip_pcie_ep_of_match[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE(of, rockchip_pcie_ep_of_match);
|
||||
|
||||
static irqreturn_t rockchip_pcie_perst_irq_handler(int irq, void *arg);
|
||||
|
||||
static void rockchip_pcie_devmode_update(struct rockchip_pcie *rockchip, int mode, int submode)
|
||||
{
|
||||
rockchip->obj_info->devmode.mode = mode;
|
||||
@@ -215,10 +235,24 @@ static int rockchip_pcie_get_io_resource(struct platform_device *pdev,
|
||||
char name[8];
|
||||
int i, idx;
|
||||
|
||||
rockchip->rst_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_IN);
|
||||
if (IS_ERR(rockchip->rst_gpio)) {
|
||||
rockchip->perst_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_IN);
|
||||
if (IS_ERR(rockchip->perst_gpio)) {
|
||||
dev_err(dev, "Failed to get reset gpio\n");
|
||||
return PTR_ERR(rockchip->rst_gpio);
|
||||
return PTR_ERR(rockchip->perst_gpio);
|
||||
}
|
||||
|
||||
if (device_property_read_bool(dev, "rockchip,ep-power-independent")) {
|
||||
rockchip->ep_power_independent = true;
|
||||
if (!rockchip->perst_gpio) {
|
||||
dev_err(dev, "When the EP power supply is independent of the RC, the perst_gpio is necessary\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
rockchip->wake_gpio = devm_gpiod_get_optional(dev, "wake", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(rockchip->wake_gpio)) {
|
||||
dev_err(dev, "Failed to get wake gpio\n");
|
||||
return PTR_ERR(rockchip->wake_gpio);
|
||||
}
|
||||
|
||||
apb_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcie-apb");
|
||||
@@ -311,6 +345,8 @@ static int rockchip_pcie_get_io_resource(struct platform_device *pdev,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rockchip->pci.link_gen = of_pci_get_max_link_speed(np);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -350,7 +386,17 @@ static int rockchip_pcie_get_resource(struct platform_device *pdev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (rockchip->perst_gpio) {
|
||||
rockchip->perst_irq = gpiod_to_irq(rockchip->perst_gpio);
|
||||
ret = devm_request_threaded_irq(&pdev->dev, rockchip->perst_irq, NULL,
|
||||
rockchip_pcie_perst_irq_handler,
|
||||
IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN,
|
||||
"perst_irq", rockchip);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "Failed to request PERST IRQ\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rockchip_pci_find_ext_capability(struct rockchip_pcie *rockchip, int cap)
|
||||
@@ -423,6 +469,11 @@ static void rockchip_pcie_resize_bar_nsticky(struct rockchip_pcie *rockchip)
|
||||
dw_pcie_writel_dbi(pci, resbar_base + 0x8 + bar * 0x8, 0x2c0);
|
||||
rockchip_pcie_ep_set_bar_flag(rockchip, bar, PCI_BASE_ADDRESS_MEM_TYPE_32);
|
||||
|
||||
bar = BAR_1;
|
||||
dw_pcie_writel_dbi(pci, resbar_base + 0x4 + bar * 0x8, 0x10);
|
||||
dw_pcie_writel_dbi(pci, resbar_base + 0x8 + bar * 0x8, 0xc0);
|
||||
rockchip_pcie_ep_set_bar_flag(rockchip, bar, PCI_BASE_ADDRESS_MEM_TYPE_32);
|
||||
|
||||
bar = BAR_2;
|
||||
dw_pcie_writel_dbi(pci, resbar_base + 0x4 + bar * 0x8, 0x400);
|
||||
dw_pcie_writel_dbi(pci, resbar_base + 0x8 + bar * 0x8, 0x6c0);
|
||||
@@ -434,11 +485,18 @@ static void rockchip_pcie_resize_bar_nsticky(struct rockchip_pcie *rockchip)
|
||||
dw_pcie_writel_dbi(pci, resbar_base + 0x8 + bar * 0x8, 0xc0);
|
||||
rockchip_pcie_ep_set_bar_flag(rockchip, bar, PCI_BASE_ADDRESS_MEM_TYPE_32);
|
||||
|
||||
bar = BAR_5;
|
||||
dw_pcie_writel_dbi(pci, resbar_base + 0x4 + bar * 0x8, 0x10);
|
||||
dw_pcie_writel_dbi(pci, resbar_base + 0x8 + bar * 0x8, 0xc0);
|
||||
rockchip_pcie_ep_set_bar_flag(rockchip, bar, PCI_BASE_ADDRESS_MEM_TYPE_32);
|
||||
|
||||
/* Disable BAR1 BAR5*/
|
||||
bar = BAR_1;
|
||||
dw_pcie_writel_dbi(pci, PCIE_TYPE0_HDR_DBI2_OFFSET + 0x10 + bar * 4, 0);
|
||||
if (!rockchip->ib_target_size[bar])
|
||||
dw_pcie_writel_dbi(pci, PCIE_TYPE0_HDR_DBI2_OFFSET + 0x10 + bar * 4, 0);
|
||||
bar = BAR_5;
|
||||
dw_pcie_writel_dbi(pci, PCIE_TYPE0_HDR_DBI2_OFFSET + 0x10 + bar * 4, 0);
|
||||
if (!rockchip->ib_target_size[bar])
|
||||
dw_pcie_writel_dbi(pci, PCIE_TYPE0_HDR_DBI2_OFFSET + 0x10 + bar * 4, 0);
|
||||
dw_pcie_dbi_ro_wr_dis(&rockchip->pci);
|
||||
}
|
||||
|
||||
@@ -531,6 +589,38 @@ static int rockchip_pcie_poll_irq_user(struct rockchip_pcie *rockchip, struct pc
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_pcie_perst_deassert(struct rockchip_pcie *rockchip)
|
||||
{
|
||||
gpiod_set_value_cansleep(rockchip->wake_gpio, 0);
|
||||
usleep_range(PCIE_WAKE_DELAY_US, PCIE_WAKE_DELAY_US + 500);
|
||||
gpiod_set_value_cansleep(rockchip->wake_gpio, 1);
|
||||
|
||||
if (rockchip->ep_power_independent)
|
||||
complete(&rockchip->ep_perst_deassert_complete);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t rockchip_pcie_perst_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct rockchip_pcie *rockchip = arg;
|
||||
struct device *dev = rockchip->pci.dev;
|
||||
u32 perst;
|
||||
|
||||
perst = gpiod_get_value(rockchip->perst_gpio);
|
||||
if (perst) {
|
||||
dev_dbg(dev, "PERST asserted by host. Shutting down the PCIe link!\n");
|
||||
} else {
|
||||
dev_dbg(dev, "PERST de-asserted by host. Starting link training!\n");
|
||||
rockchip_pcie_perst_deassert(rockchip);
|
||||
}
|
||||
|
||||
irq_set_irq_type(gpiod_to_irq(rockchip->perst_gpio),
|
||||
(perst ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t rockchip_pcie_sys_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct rockchip_pcie *rockchip = arg;
|
||||
@@ -654,6 +744,18 @@ static int rockchip_pcie_init_host(struct rockchip_pcie *rockchip)
|
||||
struct device *dev = rockchip->pci.dev;
|
||||
int ret;
|
||||
|
||||
if (rockchip->ep_power_independent && gpiod_get_value(rockchip->perst_gpio)) {
|
||||
init_completion(&rockchip->ep_perst_deassert_complete);
|
||||
dev_info(dev, "Waiting for perst# de-assert\n");
|
||||
enable_irq(rockchip->perst_irq);
|
||||
ret = wait_for_completion_timeout(&rockchip->ep_perst_deassert_complete, 30 * HZ);
|
||||
if (!ret) {
|
||||
dev_err(dev, "Not waiting for a valid PERST signal\n");
|
||||
return ret;
|
||||
}
|
||||
dev_info(dev, "perst# de-assert\n");
|
||||
}
|
||||
|
||||
ret = clk_bulk_prepare_enable(rockchip->clk_cnt, rockchip->clks);
|
||||
if (ret)
|
||||
return 0;
|
||||
@@ -739,12 +841,39 @@ static void rockchip_pcie_hide_broken_ats_cap(struct dw_pcie *pci)
|
||||
dw_pcie_dbi_ro_wr_dis(pci);
|
||||
}
|
||||
|
||||
static void rockchip_pcie_enable_debug(struct rockchip_pcie *rockchip)
|
||||
{
|
||||
rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_DBG_TRANSITION_DATA,
|
||||
PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0);
|
||||
rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_DBG_TRANSITION_DATA,
|
||||
PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1);
|
||||
rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_DBG_TRANSITION_DATA,
|
||||
PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0);
|
||||
rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_DBG_TRANSITION_DATA,
|
||||
PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1);
|
||||
rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_DBF_EN,
|
||||
PCIE_CLIENT_DBG_FIFO_MODE_CON);
|
||||
}
|
||||
|
||||
static void rockchip_pcie_debug_dump(struct rockchip_pcie *rockchip)
|
||||
{
|
||||
#if RK_PCIE_DBG
|
||||
u32 loop;
|
||||
|
||||
dev_info(rockchip->pci.dev, "ltssm = 0x%x\n",
|
||||
rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_LTSSM_STATUS));
|
||||
for (loop = 0; loop < 64; loop++)
|
||||
dev_info(rockchip->pci.dev, "fifo_status = 0x%x\n",
|
||||
rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_DBG_FIFO_STATUS));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int rockchip_pcie_config_host(struct rockchip_pcie *rockchip)
|
||||
{
|
||||
struct device *dev = rockchip->pci.dev;
|
||||
struct dw_pcie *pci = &rockchip->pci;
|
||||
u32 reg, val;
|
||||
int ret, retry, i;
|
||||
int ret, retries, i;
|
||||
|
||||
/* Detecting ATU features to achieve DWC ATU interface development */
|
||||
dw_pcie_iatu_detect(&rockchip->pci);
|
||||
@@ -810,8 +939,10 @@ static int rockchip_pcie_config_host(struct rockchip_pcie *rockchip)
|
||||
dev_info(dev, "hot reset ever\n");
|
||||
}
|
||||
rockchip_pcie_writel_apb(rockchip, reg, PCIE_CLIENT_INTR_STATUS_MISC);
|
||||
rockchip_pcie_enable_debug(rockchip);
|
||||
|
||||
for (retry = 0; retry < 1000; retry++) {
|
||||
retries = 1000;
|
||||
for (i = 0; i < retries; i++) {
|
||||
if (dw_pcie_link_up(&rockchip->pci)) {
|
||||
/*
|
||||
* We may be here in case of L0 in Gen1. But if EP is capable
|
||||
@@ -820,18 +951,23 @@ static int rockchip_pcie_config_host(struct rockchip_pcie *rockchip)
|
||||
* that LTSSM max timeout is 24ms per period, we can wait a bit
|
||||
* more for Gen switch.
|
||||
*/
|
||||
msleep(2000);
|
||||
dev_info(dev, "PCIe Link up, LTSSM is 0x%x\n",
|
||||
rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_LTSSM_STATUS));
|
||||
break;
|
||||
msleep(50);
|
||||
/* In case link drop after linkup, double check it */
|
||||
if (dw_pcie_link_up(pci)) {
|
||||
dev_info(pci->dev, "PCIe Link up, LTSSM is 0x%x\n",
|
||||
rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_LTSSM_STATUS));
|
||||
rockchip_pcie_debug_dump(rockchip);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dev_info_ratelimited(dev, "PCIe Linking... LTSSM is 0x%x\n",
|
||||
rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_LTSSM_STATUS));
|
||||
rockchip_pcie_debug_dump(rockchip);
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
if (retry >= 10000) {
|
||||
if (i >= retries) {
|
||||
ret = -ENODEV;
|
||||
return ret;
|
||||
}
|
||||
@@ -1153,6 +1289,13 @@ static int pcie_ep_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
}
|
||||
addr = rockchip->ib_target_address[0];
|
||||
break;
|
||||
case PCIE_EP_MMAP_RESOURCE_BAR1:
|
||||
if (size > rockchip->ib_target_size[1]) {
|
||||
dev_warn(rockchip->pci.dev, "bar1 mmap size is out of limitation\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
addr = rockchip->ib_target_address[1];
|
||||
break;
|
||||
case PCIE_EP_MMAP_RESOURCE_BAR2:
|
||||
if (size > rockchip->ib_target_size[2]) {
|
||||
dev_warn(rockchip->pci.dev, "bar2 mmap size is out of limitation\n");
|
||||
@@ -1160,6 +1303,13 @@ static int pcie_ep_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
}
|
||||
addr = rockchip->ib_target_address[2];
|
||||
break;
|
||||
case PCIE_EP_MMAP_RESOURCE_BAR5:
|
||||
if (size > rockchip->ib_target_size[5]) {
|
||||
dev_warn(rockchip->pci.dev, "bar5 mmap size is out of limitation\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
addr = rockchip->ib_target_address[5];
|
||||
break;
|
||||
default:
|
||||
dev_err(rockchip->pci.dev, "cur mmap_res %d is unsurreport\n", rockchip->cur_mmap_res);
|
||||
return -EINVAL;
|
||||
@@ -1265,11 +1415,54 @@ deinit_host:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused rockchip_dw_pcie_suspend(struct device *dev)
|
||||
{
|
||||
struct rockchip_pcie *rockchip = dev_get_drvdata(dev);
|
||||
|
||||
rockchip_pcie_deinit_host(rockchip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused rockchip_dw_pcie_resume(struct device *dev)
|
||||
{
|
||||
struct rockchip_pcie *rockchip = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = rockchip_pcie_init_host(rockchip);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to init host!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rockchip_pcie_config_host(rockchip);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to config host!\n");
|
||||
goto deinit_host;
|
||||
}
|
||||
|
||||
gpiod_set_value_cansleep(rockchip->wake_gpio, 0);
|
||||
usleep_range(PCIE_WAKE_DELAY_US, PCIE_WAKE_DELAY_US + 500);
|
||||
gpiod_set_value_cansleep(rockchip->wake_gpio, 1);
|
||||
|
||||
return ret;
|
||||
deinit_host:
|
||||
rockchip_pcie_deinit_host(rockchip);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops rockchip_dw_pcie_pm_ops = {
|
||||
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(rockchip_dw_pcie_suspend,
|
||||
rockchip_dw_pcie_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver rk_plat_pcie_driver = {
|
||||
.driver = {
|
||||
.name = "rk-pcie-ep",
|
||||
.of_match_table = rockchip_pcie_ep_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
.pm = &rockchip_dw_pcie_pm_ops,
|
||||
},
|
||||
.probe = rockchip_pcie_ep_probe,
|
||||
};
|
||||
|
||||
@@ -26,18 +26,18 @@ int rga_buf_size_cal(unsigned long yrgb_addr, unsigned long uv_addr,
|
||||
int rga_virtual_memory_check(void *vaddr, u32 w, u32 h, u32 format, int fd);
|
||||
int rga_dma_memory_check(struct rga_dma_buffer *rga_dma_buffer, struct rga_img_info_t *img);
|
||||
|
||||
int rga_iommu_map_sgt(struct sg_table *sgt, size_t size,
|
||||
struct rga_dma_buffer *buffer,
|
||||
struct device *rga_dev);
|
||||
int rga_iommu_map(phys_addr_t paddr, size_t size,
|
||||
struct rga_dma_buffer *buffer,
|
||||
struct device *rga_dev);
|
||||
void rga_iommu_unmap(struct rga_dma_buffer *buffer);
|
||||
int rga_dma_map_phys_addr(phys_addr_t phys_addr, size_t size, struct rga_dma_buffer *buffer,
|
||||
enum dma_data_direction dir, struct device *map_dev);
|
||||
void rga_dma_unmap_phys_addr(struct rga_dma_buffer *buffer);
|
||||
|
||||
int rga_dma_map_sgt(struct sg_table *sgt, struct rga_dma_buffer *buffer,
|
||||
enum dma_data_direction dir, struct device *map_dev);
|
||||
void rga_dma_unmap_sgt(struct rga_dma_buffer *buffer);
|
||||
|
||||
int rga_dma_map_buf(struct dma_buf *dma_buf, struct rga_dma_buffer *rga_dma_buffer,
|
||||
enum dma_data_direction dir, struct device *rga_dev);
|
||||
enum dma_data_direction dir, struct device *map_dev);
|
||||
int rga_dma_map_fd(int fd, struct rga_dma_buffer *rga_dma_buffer,
|
||||
enum dma_data_direction dir, struct device *rga_dev);
|
||||
enum dma_data_direction dir, struct device *map_dev);
|
||||
void rga_dma_unmap_buf(struct rga_dma_buffer *rga_dma_buffer);
|
||||
|
||||
void rga_dma_sync_flush_range(void *pstart, void *pend, struct rga_scheduler_t *scheduler);
|
||||
|
||||
@@ -182,8 +182,11 @@ struct rga_dma_buffer {
|
||||
*/
|
||||
size_t offset;
|
||||
|
||||
/* The scheduler of the mapping */
|
||||
struct rga_scheduler_t *scheduler;
|
||||
/*
|
||||
* The device used by dma-buf mapping, which usually corresponds to the
|
||||
* default domain or the current device.
|
||||
*/
|
||||
struct device *map_dev;
|
||||
};
|
||||
|
||||
struct rga_virt_addr {
|
||||
@@ -192,6 +195,7 @@ struct rga_virt_addr {
|
||||
struct page **pages;
|
||||
int pages_order;
|
||||
int page_count;
|
||||
/* Actual effective size */
|
||||
unsigned long size;
|
||||
|
||||
/* The offset of the first page of the virtual address */
|
||||
@@ -227,6 +231,9 @@ struct rga_internal_buffer {
|
||||
|
||||
struct kref refcount;
|
||||
struct rga_session *session;
|
||||
|
||||
/* The scheduler of the mapping */
|
||||
struct rga_scheduler_t *scheduler;
|
||||
};
|
||||
|
||||
struct rga_scheduler_t;
|
||||
|
||||
@@ -42,7 +42,7 @@ static inline bool rga_mm_is_invalid_dma_buffer(struct rga_dma_buffer *buffer)
|
||||
if (buffer == NULL)
|
||||
return true;
|
||||
|
||||
return buffer->scheduler == NULL ? true : false;
|
||||
return buffer->map_dev == NULL ? true : false;
|
||||
}
|
||||
|
||||
struct rga_internal_buffer *rga_mm_lookup_handle(struct rga_mm *mm_session, uint32_t handle);
|
||||
|
||||
@@ -286,7 +286,7 @@ static int rga_mm_session_show(struct seq_file *m, void *data)
|
||||
(unsigned long)dump_buffer->dma_buffer->iova,
|
||||
dump_buffer->dma_buffer->sgt,
|
||||
dump_buffer->dma_buffer->size,
|
||||
dump_buffer->dma_buffer->scheduler->core);
|
||||
dump_buffer->scheduler->core);
|
||||
|
||||
if (dump_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS)
|
||||
seq_printf(m, "\t is contiguous, pa = 0x%lx\n",
|
||||
@@ -310,7 +310,7 @@ static int rga_mm_session_show(struct seq_file *m, void *data)
|
||||
(unsigned long)dump_buffer->dma_buffer->offset,
|
||||
dump_buffer->dma_buffer->sgt,
|
||||
dump_buffer->dma_buffer->size,
|
||||
dump_buffer->dma_buffer->scheduler->core);
|
||||
dump_buffer->scheduler->core);
|
||||
|
||||
if (dump_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS)
|
||||
seq_printf(m, "\t is contiguous, pa = 0x%lx\n",
|
||||
|
||||
@@ -11,20 +11,6 @@
|
||||
#include "rga_job.h"
|
||||
#include "rga_debugger.h"
|
||||
|
||||
static int rga_dma_info_to_prot(enum dma_data_direction dir)
|
||||
{
|
||||
switch (dir) {
|
||||
case DMA_BIDIRECTIONAL:
|
||||
return IOMMU_READ | IOMMU_WRITE;
|
||||
case DMA_TO_DEVICE:
|
||||
return IOMMU_READ;
|
||||
case DMA_FROM_DEVICE:
|
||||
return IOMMU_WRITE;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int rga_buf_size_cal(unsigned long yrgb_addr, unsigned long uv_addr,
|
||||
unsigned long v_addr, int format, uint32_t w,
|
||||
uint32_t h, unsigned long *StartAddr, unsigned long *size)
|
||||
@@ -198,165 +184,6 @@ int rga_buf_size_cal(unsigned long yrgb_addr, unsigned long uv_addr,
|
||||
return pageCount;
|
||||
}
|
||||
|
||||
static dma_addr_t rga_iommu_dma_alloc_iova(struct iommu_domain *domain,
|
||||
size_t size, u64 dma_limit,
|
||||
struct device *dev)
|
||||
{
|
||||
struct rga_iommu_dma_cookie *cookie = (void *)domain->iova_cookie;
|
||||
struct iova_domain *iovad = &cookie->iovad;
|
||||
unsigned long shift, iova_len, iova = 0;
|
||||
|
||||
shift = iova_shift(iovad);
|
||||
iova_len = size >> shift;
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||
/*
|
||||
* Freeing non-power-of-two-sized allocations back into the IOVA caches
|
||||
* will come back to bite us badly, so we have to waste a bit of space
|
||||
* rounding up anything cacheable to make sure that can't happen. The
|
||||
* order of the unadjusted size will still match upon freeing.
|
||||
*/
|
||||
if (iova_len < (1 << (IOVA_RANGE_CACHE_MAX_SIZE - 1)))
|
||||
iova_len = roundup_pow_of_two(iova_len);
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
|
||||
dma_limit = min_not_zero(dma_limit, dev->bus_dma_limit);
|
||||
#else
|
||||
if (dev->bus_dma_mask)
|
||||
dma_limit &= dev->bus_dma_mask;
|
||||
#endif
|
||||
|
||||
if (domain->geometry.force_aperture)
|
||||
dma_limit = min(dma_limit, (u64)domain->geometry.aperture_end);
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 19, 111) && \
|
||||
LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
|
||||
iova = alloc_iova_fast(iovad, iova_len,
|
||||
min_t(dma_addr_t, dma_limit >> shift, iovad->end_pfn),
|
||||
true);
|
||||
#else
|
||||
iova = alloc_iova_fast(iovad, iova_len, dma_limit >> shift, true);
|
||||
#endif
|
||||
|
||||
return (dma_addr_t)iova << shift;
|
||||
}
|
||||
|
||||
static void rga_iommu_dma_free_iova(struct iommu_domain *domain,
|
||||
dma_addr_t iova, size_t size)
|
||||
{
|
||||
struct rga_iommu_dma_cookie *cookie = (void *)domain->iova_cookie;
|
||||
struct iova_domain *iovad = &cookie->iovad;
|
||||
|
||||
free_iova_fast(iovad, iova_pfn(iovad, iova), size >> iova_shift(iovad));
|
||||
}
|
||||
|
||||
static inline struct iommu_domain *rga_iommu_get_dma_domain(struct device *dev)
|
||||
{
|
||||
return iommu_get_domain_for_dev(dev);
|
||||
}
|
||||
|
||||
void rga_iommu_unmap(struct rga_dma_buffer *buffer)
|
||||
{
|
||||
if (buffer == NULL)
|
||||
return;
|
||||
if (buffer->iova == 0)
|
||||
return;
|
||||
|
||||
iommu_unmap(buffer->domain, buffer->iova, buffer->size);
|
||||
rga_iommu_dma_free_iova(buffer->domain, buffer->iova, buffer->size);
|
||||
}
|
||||
|
||||
int rga_iommu_map_sgt(struct sg_table *sgt, size_t size,
|
||||
struct rga_dma_buffer *buffer,
|
||||
struct device *rga_dev)
|
||||
{
|
||||
struct iommu_domain *domain = NULL;
|
||||
struct rga_iommu_dma_cookie *cookie;
|
||||
struct iova_domain *iovad;
|
||||
dma_addr_t iova;
|
||||
size_t map_size;
|
||||
unsigned long align_size;
|
||||
|
||||
if (sgt == NULL) {
|
||||
rga_err("can not map iommu, because sgt is null!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
domain = rga_iommu_get_dma_domain(rga_dev);
|
||||
cookie = (void *)domain->iova_cookie;
|
||||
iovad = &cookie->iovad;
|
||||
align_size = iova_align(iovad, size);
|
||||
|
||||
if (DEBUGGER_EN(MSG))
|
||||
rga_log("iova_align size = %ld", align_size);
|
||||
|
||||
iova = rga_iommu_dma_alloc_iova(domain, align_size, rga_dev->coherent_dma_mask, rga_dev);
|
||||
if (!iova) {
|
||||
rga_err("rga_iommu_dma_alloc_iova failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
map_size = iommu_map_sg(domain, iova, sgt->sgl, sgt->orig_nents,
|
||||
rga_dma_info_to_prot(DMA_BIDIRECTIONAL));
|
||||
if (map_size < align_size) {
|
||||
rga_err("iommu can not map sgt to iova");
|
||||
rga_iommu_dma_free_iova(domain, iova, align_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buffer->domain = domain;
|
||||
buffer->iova = iova;
|
||||
buffer->size = align_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rga_iommu_map(phys_addr_t paddr, size_t size,
|
||||
struct rga_dma_buffer *buffer,
|
||||
struct device *rga_dev)
|
||||
{
|
||||
int ret;
|
||||
struct iommu_domain *domain = NULL;
|
||||
struct rga_iommu_dma_cookie *cookie;
|
||||
struct iova_domain *iovad;
|
||||
dma_addr_t iova;
|
||||
unsigned long align_size;
|
||||
|
||||
if (paddr == 0) {
|
||||
rga_err("can not map iommu, because phys_addr is 0!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
domain = rga_iommu_get_dma_domain(rga_dev);
|
||||
cookie = (void *)domain->iova_cookie;
|
||||
iovad = &cookie->iovad;
|
||||
align_size = iova_align(iovad, size);
|
||||
|
||||
if (DEBUGGER_EN(MSG))
|
||||
rga_log("iova_align size = %ld", align_size);
|
||||
|
||||
iova = rga_iommu_dma_alloc_iova(domain, align_size, rga_dev->coherent_dma_mask, rga_dev);
|
||||
if (!iova) {
|
||||
rga_err("rga_iommu_dma_alloc_iova failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = iommu_map(domain, iova, paddr, align_size,
|
||||
rga_dma_info_to_prot(DMA_BIDIRECTIONAL));
|
||||
if (ret) {
|
||||
rga_err("iommu can not map phys_addr to iova");
|
||||
rga_iommu_dma_free_iova(domain, iova, align_size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
buffer->domain = domain;
|
||||
buffer->iova = iova;
|
||||
buffer->size = align_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rga_virtual_memory_check(void *vaddr, u32 w, u32 h, u32 format, int fd)
|
||||
{
|
||||
int bits = 32;
|
||||
@@ -424,8 +251,67 @@ int rga_dma_memory_check(struct rga_dma_buffer *rga_dma_buffer, struct rga_img_i
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rga_dma_map_phys_addr(phys_addr_t phys_addr, size_t size, struct rga_dma_buffer *buffer,
|
||||
enum dma_data_direction dir, struct device *map_dev)
|
||||
{
|
||||
dma_addr_t addr;
|
||||
|
||||
addr = dma_map_resource(map_dev, phys_addr, size, dir, 0);
|
||||
if (addr == DMA_MAPPING_ERROR) {
|
||||
rga_err("dma_map_resouce failed!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buffer->dma_addr = addr;
|
||||
buffer->dir = dir;
|
||||
buffer->size = size;
|
||||
buffer->map_dev = map_dev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rga_dma_unmap_phys_addr(struct rga_dma_buffer *buffer)
|
||||
{
|
||||
dma_unmap_resource(buffer->map_dev, buffer->dma_addr, buffer->size, buffer->dir, 0);
|
||||
}
|
||||
|
||||
int rga_dma_map_sgt(struct sg_table *sgt, struct rga_dma_buffer *buffer,
|
||||
enum dma_data_direction dir, struct device *map_dev)
|
||||
{
|
||||
int i, ret = 0;
|
||||
struct scatterlist *sg = NULL;
|
||||
|
||||
ret = dma_map_sg(map_dev, sgt->sgl, sgt->orig_nents, dir);
|
||||
if (ret <= 0) {
|
||||
rga_err("dma_map_sg failed! ret = %d\n", ret);
|
||||
return ret < 0 ? ret : -EINVAL;
|
||||
}
|
||||
sgt->nents = ret;
|
||||
|
||||
buffer->sgt = sgt;
|
||||
buffer->dma_addr = sg_dma_address(sgt->sgl);
|
||||
buffer->dir = dir;
|
||||
buffer->size = 0;
|
||||
for_each_sgtable_sg(sgt, sg, i)
|
||||
buffer->size += sg_dma_len(sg);
|
||||
buffer->map_dev = map_dev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rga_dma_unmap_sgt(struct rga_dma_buffer *buffer)
|
||||
{
|
||||
if (!buffer->sgt)
|
||||
return;
|
||||
|
||||
dma_unmap_sg(buffer->map_dev,
|
||||
buffer->sgt->sgl,
|
||||
buffer->sgt->orig_nents,
|
||||
buffer->dir);
|
||||
}
|
||||
|
||||
int rga_dma_map_buf(struct dma_buf *dma_buf, struct rga_dma_buffer *rga_dma_buffer,
|
||||
enum dma_data_direction dir, struct device *rga_dev)
|
||||
enum dma_data_direction dir, struct device *map_dev)
|
||||
{
|
||||
struct dma_buf_attachment *attach = NULL;
|
||||
struct sg_table *sgt = NULL;
|
||||
@@ -439,7 +325,7 @@ int rga_dma_map_buf(struct dma_buf *dma_buf, struct rga_dma_buffer *rga_dma_buff
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
attach = dma_buf_attach(dma_buf, rga_dev);
|
||||
attach = dma_buf_attach(dma_buf, map_dev);
|
||||
if (IS_ERR(attach)) {
|
||||
ret = PTR_ERR(attach);
|
||||
rga_err("Failed to attach dma_buf, ret[%d]\n", ret);
|
||||
@@ -461,6 +347,7 @@ int rga_dma_map_buf(struct dma_buf *dma_buf, struct rga_dma_buffer *rga_dma_buff
|
||||
rga_dma_buffer->size = 0;
|
||||
for_each_sgtable_sg(sgt, sg, i)
|
||||
rga_dma_buffer->size += sg_dma_len(sg);
|
||||
rga_dma_buffer->map_dev = map_dev;
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -475,7 +362,7 @@ err_get_attach:
|
||||
}
|
||||
|
||||
int rga_dma_map_fd(int fd, struct rga_dma_buffer *rga_dma_buffer,
|
||||
enum dma_data_direction dir, struct device *rga_dev)
|
||||
enum dma_data_direction dir, struct device *map_dev)
|
||||
{
|
||||
struct dma_buf *dma_buf = NULL;
|
||||
struct dma_buf_attachment *attach = NULL;
|
||||
@@ -490,7 +377,7 @@ int rga_dma_map_fd(int fd, struct rga_dma_buffer *rga_dma_buffer,
|
||||
return ret;
|
||||
}
|
||||
|
||||
attach = dma_buf_attach(dma_buf, rga_dev);
|
||||
attach = dma_buf_attach(dma_buf, map_dev);
|
||||
if (IS_ERR(attach)) {
|
||||
ret = PTR_ERR(attach);
|
||||
rga_err("Failed to attach dma_buf, ret[%d]\n", ret);
|
||||
@@ -512,6 +399,7 @@ int rga_dma_map_fd(int fd, struct rga_dma_buffer *rga_dma_buffer,
|
||||
rga_dma_buffer->size = 0;
|
||||
for_each_sgtable_sg(sgt, sg, i)
|
||||
rga_dma_buffer->size += sg_dma_len(sg);
|
||||
rga_dma_buffer->map_dev = map_dev;
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -551,12 +439,12 @@ int rga_dma_free(struct rga_dma_buffer *buffer)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dma_free_coherent(buffer->scheduler->dev, buffer->size, buffer->vaddr, buffer->dma_addr);
|
||||
dma_free_coherent(buffer->map_dev, buffer->size, buffer->vaddr, buffer->dma_addr);
|
||||
buffer->vaddr = NULL;
|
||||
buffer->dma_addr = 0;
|
||||
buffer->iova = 0;
|
||||
buffer->size = 0;
|
||||
buffer->scheduler = NULL;
|
||||
buffer->map_dev = NULL;
|
||||
|
||||
kfree(buffer);
|
||||
|
||||
@@ -581,7 +469,7 @@ struct rga_dma_buffer *rga_dma_alloc_coherent(struct rga_scheduler_t *scheduler,
|
||||
|
||||
buffer->size = align_size;
|
||||
buffer->dma_addr = dma_addr;
|
||||
buffer->scheduler = scheduler;
|
||||
buffer->map_dev = scheduler->dev;
|
||||
if (scheduler->data->mmu == RGA_IOMMU)
|
||||
buffer->iova = buffer->dma_addr;
|
||||
|
||||
|
||||
@@ -179,11 +179,10 @@ static struct sg_table *rga_alloc_sgt(struct rga_virt_addr *virt_addr)
|
||||
}
|
||||
|
||||
/* get sg form pages. */
|
||||
/* iova requires minimum page alignment, so sgt cannot have offset */
|
||||
ret = sg_alloc_table_from_pages(sgt,
|
||||
virt_addr->pages,
|
||||
virt_addr->page_count,
|
||||
0,
|
||||
virt_addr->offset,
|
||||
virt_addr->size,
|
||||
GFP_KERNEL);
|
||||
if (ret) {
|
||||
@@ -232,7 +231,6 @@ static int rga_alloc_virt_addr(struct rga_virt_addr **virt_addr_p,
|
||||
unsigned int count;
|
||||
int img_size;
|
||||
size_t offset;
|
||||
unsigned long size;
|
||||
struct page **pages = NULL;
|
||||
struct rga_virt_addr *virt_addr = NULL;
|
||||
|
||||
@@ -246,10 +244,9 @@ static int rga_alloc_virt_addr(struct rga_virt_addr **virt_addr_p,
|
||||
|
||||
offset = viraddr & (~PAGE_MASK);
|
||||
count = RGA_GET_PAGE_COUNT(img_size + offset);
|
||||
size = count * PAGE_SIZE;
|
||||
if (!size) {
|
||||
rga_err("failed to calculating buffer size! size = %ld, count = %d, offset = %ld\n",
|
||||
size, count, (unsigned long)offset);
|
||||
if (!count) {
|
||||
rga_err("failed to calculating buffer size! img_size = %d, count = %d, offset = %ld\n",
|
||||
img_size, count, (unsigned long)offset);
|
||||
rga_dump_memory_parm(memory_parm);
|
||||
return -EFAULT;
|
||||
}
|
||||
@@ -292,7 +289,7 @@ static int rga_alloc_virt_addr(struct rga_virt_addr **virt_addr_p,
|
||||
virt_addr->pages = pages;
|
||||
virt_addr->pages_order = order;
|
||||
virt_addr->page_count = count;
|
||||
virt_addr->size = size;
|
||||
virt_addr->size = img_size;
|
||||
virt_addr->offset = offset;
|
||||
virt_addr->result = result;
|
||||
|
||||
@@ -398,18 +395,17 @@ static int rga_mm_map_dma_buffer(struct rga_external_buffer *external_buffer,
|
||||
return ex_buffer_size == 0 ? -EINVAL : ex_buffer_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* dma-buf api needs to use default_domain of main dev,
|
||||
* and not IOMMU for devices without iommu_info ptr.
|
||||
*/
|
||||
map_dev = scheduler->iommu_info ? scheduler->iommu_info->default_dev : scheduler->dev;
|
||||
|
||||
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
|
||||
if (buffer == NULL) {
|
||||
rga_err("%s alloc internal_buffer error!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* dma-buf api needs to use default_domain of main dev,
|
||||
* and not IOMMU for devices without iommu_info ptr.
|
||||
*/
|
||||
map_dev = scheduler->iommu_info ? scheduler->iommu_info->default_dev : scheduler->dev;
|
||||
switch (external_buffer->type) {
|
||||
case RGA_DMA_BUFFER:
|
||||
ret = rga_dma_map_fd((int)external_buffer->memory,
|
||||
@@ -440,8 +436,6 @@ static int rga_mm_map_dma_buffer(struct rga_external_buffer *external_buffer,
|
||||
goto unmap_buffer;
|
||||
}
|
||||
|
||||
buffer->scheduler = scheduler;
|
||||
|
||||
if (scheduler->data->mmu == RGA_IOMMU)
|
||||
buffer->iova = buffer->dma_addr;
|
||||
|
||||
@@ -473,6 +467,8 @@ static int rga_mm_map_dma_buffer(struct rga_external_buffer *external_buffer,
|
||||
internal_buffer->dma_buffer = buffer;
|
||||
internal_buffer->mm_flag = mm_flag;
|
||||
internal_buffer->phys_addr = phys_addr ? phys_addr : 0;
|
||||
internal_buffer->size = buffer->size - buffer->offset;
|
||||
internal_buffer->scheduler = scheduler;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -492,19 +488,7 @@ static void rga_mm_unmap_virt_addr(struct rga_internal_buffer *internal_buffer)
|
||||
if (rga_mm_is_invalid_dma_buffer(internal_buffer->dma_buffer))
|
||||
return;
|
||||
|
||||
switch (internal_buffer->dma_buffer->scheduler->data->mmu) {
|
||||
case RGA_IOMMU:
|
||||
rga_iommu_unmap(internal_buffer->dma_buffer);
|
||||
break;
|
||||
case RGA_MMU:
|
||||
dma_unmap_sg(internal_buffer->dma_buffer->scheduler->dev,
|
||||
internal_buffer->dma_buffer->sgt->sgl,
|
||||
internal_buffer->dma_buffer->sgt->orig_nents,
|
||||
DMA_BIDIRECTIONAL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
rga_dma_unmap_sgt(internal_buffer->dma_buffer);
|
||||
|
||||
if (internal_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS &&
|
||||
internal_buffer->phys_addr > 0)
|
||||
@@ -532,6 +516,7 @@ static int rga_mm_map_virt_addr(struct rga_external_buffer *external_buffer,
|
||||
struct sg_table *sgt;
|
||||
struct rga_virt_addr *virt_addr;
|
||||
struct rga_dma_buffer *buffer;
|
||||
struct device *map_dev;
|
||||
struct rga_scheduler_t *scheduler;
|
||||
|
||||
scheduler = job ? job->scheduler :
|
||||
@@ -578,6 +563,11 @@ static int rga_mm_map_virt_addr(struct rga_external_buffer *external_buffer,
|
||||
}
|
||||
|
||||
mm_flag |= RGA_MEM_PHYSICAL_CONTIGUOUS;
|
||||
} else if (scheduler->data->mmu == RGA_NONE_MMU) {
|
||||
rga_err("Current %s[%d] cannot support physically discontinuous virtual address!\n",
|
||||
rga_get_mmu_type_str(scheduler->data->mmu), scheduler->data->mmu);
|
||||
ret = -EOPNOTSUPP;
|
||||
goto free_sgt;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -601,47 +591,28 @@ static int rga_mm_map_virt_addr(struct rga_external_buffer *external_buffer,
|
||||
goto free_sgt;
|
||||
}
|
||||
|
||||
switch (scheduler->data->mmu) {
|
||||
case RGA_IOMMU:
|
||||
ret = rga_iommu_map_sgt(sgt, virt_addr->size, buffer, scheduler->dev);
|
||||
if (ret < 0) {
|
||||
rga_err("%s core[%d] iommu_map virtual address error!\n",
|
||||
__func__, scheduler->core);
|
||||
goto free_dma_buffer;
|
||||
}
|
||||
|
||||
buffer->dma_addr = buffer->iova;
|
||||
|
||||
break;
|
||||
case RGA_MMU:
|
||||
ret = dma_map_sg(scheduler->dev, sgt->sgl, sgt->orig_nents, DMA_BIDIRECTIONAL);
|
||||
if (ret == 0) {
|
||||
rga_err("%s core[%d] dma_map_sgt error! va = 0x%lx, nents = %d\n",
|
||||
__func__, scheduler->core,
|
||||
(unsigned long)virt_addr->addr, sgt->orig_nents);
|
||||
ret = -EINVAL;
|
||||
goto free_dma_buffer;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS)
|
||||
break;
|
||||
|
||||
rga_err("Current %s[%d] cannot support physically discontinuous virtual address!\n",
|
||||
rga_get_mmu_type_str(scheduler->data->mmu), scheduler->data->mmu);
|
||||
ret = -EOPNOTSUPP;
|
||||
/*
|
||||
* dma-buf api needs to use default_domain of main dev,
|
||||
* and not IOMMU for devices without iommu_info ptr.
|
||||
*/
|
||||
map_dev = scheduler->iommu_info ? scheduler->iommu_info->default_dev : scheduler->dev;
|
||||
ret = rga_dma_map_sgt(sgt, buffer, DMA_BIDIRECTIONAL, map_dev);
|
||||
if (ret < 0) {
|
||||
rga_err("%s core[%d] rga map sgt failed! va = 0x%lx, orig_nents = %d\n",
|
||||
__func__, scheduler->core,
|
||||
(unsigned long)virt_addr->addr, sgt->orig_nents);
|
||||
goto free_dma_buffer;
|
||||
}
|
||||
|
||||
buffer->sgt = sgt;
|
||||
buffer->offset = virt_addr->offset;
|
||||
buffer->size = virt_addr->size;
|
||||
buffer->scheduler = scheduler;
|
||||
if (scheduler->data->mmu == RGA_IOMMU)
|
||||
buffer->iova = buffer->dma_addr;
|
||||
|
||||
internal_buffer->virt_addr = virt_addr;
|
||||
internal_buffer->dma_buffer = buffer;
|
||||
internal_buffer->mm_flag = mm_flag;
|
||||
internal_buffer->phys_addr = phys_addr ? phys_addr + virt_addr->offset : 0;
|
||||
internal_buffer->size = buffer->size - buffer->offset;
|
||||
internal_buffer->scheduler = scheduler;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -661,16 +632,12 @@ put_current_mm:
|
||||
|
||||
static void rga_mm_unmap_phys_addr(struct rga_internal_buffer *internal_buffer)
|
||||
{
|
||||
WARN_ON(internal_buffer->dma_buffer == NULL);
|
||||
if (internal_buffer->dma_buffer != NULL) {
|
||||
rga_dma_unmap_phys_addr(internal_buffer->dma_buffer);
|
||||
kfree(internal_buffer->dma_buffer);
|
||||
internal_buffer->dma_buffer = NULL;
|
||||
}
|
||||
|
||||
if (rga_mm_is_invalid_dma_buffer(internal_buffer->dma_buffer))
|
||||
return;
|
||||
|
||||
if (internal_buffer->dma_buffer->scheduler->data->mmu == RGA_IOMMU)
|
||||
rga_iommu_unmap(internal_buffer->dma_buffer);
|
||||
|
||||
kfree(internal_buffer->dma_buffer);
|
||||
internal_buffer->dma_buffer = NULL;
|
||||
internal_buffer->phys_addr = 0;
|
||||
internal_buffer->size = 0;
|
||||
}
|
||||
@@ -683,7 +650,8 @@ static int rga_mm_map_phys_addr(struct rga_external_buffer *external_buffer,
|
||||
phys_addr_t phys_addr;
|
||||
int buffer_size;
|
||||
uint32_t mm_flag = 0;
|
||||
struct rga_dma_buffer *buffer;
|
||||
struct rga_dma_buffer *buffer = NULL;
|
||||
struct device *map_dev;
|
||||
struct rga_scheduler_t *scheduler;
|
||||
|
||||
scheduler = job ? job->scheduler :
|
||||
@@ -717,26 +685,34 @@ static int rga_mm_map_phys_addr(struct rga_external_buffer *external_buffer,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
|
||||
if (buffer == NULL) {
|
||||
rga_err("%s alloc internal dma buffer error!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (scheduler->data->mmu == RGA_IOMMU) {
|
||||
ret = rga_iommu_map(phys_addr, buffer_size, buffer, scheduler->dev);
|
||||
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
|
||||
if (buffer == NULL) {
|
||||
rga_err("%s alloc internal dma buffer error!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* dma-buf api needs to use default_domain of main dev,
|
||||
* and not IOMMU for devices without iommu_info ptr.
|
||||
*/
|
||||
map_dev = scheduler->iommu_info ?
|
||||
scheduler->iommu_info->default_dev : scheduler->dev;
|
||||
ret = rga_dma_map_phys_addr(phys_addr, buffer_size, buffer,
|
||||
DMA_BIDIRECTIONAL, map_dev);
|
||||
if (ret < 0) {
|
||||
rga_err("%s core[%d] map phys_addr error!\n", __func__, scheduler->core);
|
||||
goto free_dma_buffer;
|
||||
}
|
||||
|
||||
buffer->iova = buffer->dma_addr;
|
||||
}
|
||||
|
||||
buffer->scheduler = scheduler;
|
||||
|
||||
internal_buffer->phys_addr = phys_addr;
|
||||
internal_buffer->size = buffer_size;
|
||||
internal_buffer->mm_flag = mm_flag;
|
||||
internal_buffer->dma_buffer = buffer;
|
||||
internal_buffer->mm_flag = mm_flag;
|
||||
internal_buffer->phys_addr = phys_addr;
|
||||
internal_buffer->size = buffer ? buffer->size : buffer_size;
|
||||
internal_buffer->scheduler = scheduler;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -785,8 +761,6 @@ static int rga_mm_map_buffer(struct rga_external_buffer *external_buffer,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
internal_buffer->size = internal_buffer->dma_buffer->size -
|
||||
internal_buffer->dma_buffer->offset;
|
||||
internal_buffer->mm_flag |= RGA_MEM_NEED_USE_IOMMU;
|
||||
break;
|
||||
case RGA_VIRTUAL_ADDRESS:
|
||||
@@ -796,8 +770,6 @@ static int rga_mm_map_buffer(struct rga_external_buffer *external_buffer,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
internal_buffer->size = internal_buffer->virt_addr->size -
|
||||
internal_buffer->virt_addr->offset;
|
||||
internal_buffer->mm_flag |= RGA_MEM_NEED_USE_IOMMU;
|
||||
break;
|
||||
case RGA_PHYSICAL_ADDRESS:
|
||||
@@ -1002,7 +974,7 @@ void rga_mm_dump_buffer(struct rga_internal_buffer *dump_buffer)
|
||||
(unsigned long)dump_buffer->dma_buffer->offset,
|
||||
dump_buffer->dma_buffer->sgt,
|
||||
dump_buffer->dma_buffer->size,
|
||||
dump_buffer->dma_buffer->scheduler->core);
|
||||
dump_buffer->scheduler->core);
|
||||
|
||||
if (dump_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS)
|
||||
rga_log("is contiguous, pa = 0x%lx\n",
|
||||
@@ -1026,7 +998,7 @@ void rga_mm_dump_buffer(struct rga_internal_buffer *dump_buffer)
|
||||
(unsigned long)dump_buffer->dma_buffer->offset,
|
||||
dump_buffer->dma_buffer->sgt,
|
||||
dump_buffer->dma_buffer->size,
|
||||
dump_buffer->dma_buffer->scheduler->core);
|
||||
dump_buffer->scheduler->core);
|
||||
|
||||
if (dump_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS)
|
||||
rga_buf_log(dump_buffer, "is contiguous, pa = 0x%lx\n",
|
||||
@@ -1034,6 +1006,16 @@ void rga_mm_dump_buffer(struct rga_internal_buffer *dump_buffer)
|
||||
break;
|
||||
case RGA_PHYSICAL_ADDRESS:
|
||||
rga_buf_log(dump_buffer, "pa = 0x%lx\n", (unsigned long)dump_buffer->phys_addr);
|
||||
|
||||
if (rga_mm_is_invalid_dma_buffer(dump_buffer->dma_buffer))
|
||||
break;
|
||||
|
||||
rga_buf_log(dump_buffer, "iova = 0x%lx, dma_addr = 0x%lx, offset = 0x%lx, size = %ld, map_core = 0x%x\n",
|
||||
(unsigned long)dump_buffer->dma_buffer->iova,
|
||||
(unsigned long)dump_buffer->dma_buffer->dma_addr,
|
||||
(unsigned long)dump_buffer->dma_buffer->offset,
|
||||
dump_buffer->dma_buffer->size,
|
||||
dump_buffer->scheduler->core);
|
||||
break;
|
||||
default:
|
||||
rga_buf_err(dump_buffer, "Illegal buffer! type= %d\n", dump_buffer->type);
|
||||
@@ -1129,7 +1111,7 @@ static int rga_mm_sgt_to_page_table(struct sg_table *sg,
|
||||
* The length of each sgl is expected to be obtained here, not
|
||||
* the length of the entire dma_buf, so sg_dma_len() is not used.
|
||||
*/
|
||||
len = sgl->length >> PAGE_SHIFT;
|
||||
len = (sgl->length + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
|
||||
|
||||
if (use_dma_address)
|
||||
/*
|
||||
@@ -1148,6 +1130,8 @@ static int rga_mm_sgt_to_page_table(struct sg_table *sg,
|
||||
else
|
||||
Address = sg_phys(sgl);
|
||||
|
||||
Address &= PAGE_MASK;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (mapped_size + i >= pageCount) {
|
||||
break_flag = 1;
|
||||
@@ -1335,16 +1319,26 @@ static int rga_mm_sync_dma_sg_for_device(struct rga_internal_buffer *buffer,
|
||||
struct rga_scheduler_t *scheduler;
|
||||
ktime_t timestamp = ktime_get();
|
||||
|
||||
scheduler = buffer->dma_buffer->scheduler;
|
||||
scheduler = buffer->scheduler;
|
||||
if (scheduler == NULL) {
|
||||
rga_job_err(job, "%s(%d), failed to get scheduler, core = 0x%x\n",
|
||||
__func__, __LINE__, job->core);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS &&
|
||||
scheduler->data->mmu != RGA_IOMMU) {
|
||||
dma_sync_single_for_device(scheduler->dev, buffer->phys_addr, buffer->size, dir);
|
||||
if (buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) {
|
||||
if (scheduler->data->mmu == RGA_IOMMU) {
|
||||
if (rga_mm_is_invalid_dma_buffer(buffer->dma_buffer)) {
|
||||
rga_job_err(job, "invalid dma-buffer with IOMMU device!\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
dma_sync_single_for_device(buffer->dma_buffer->map_dev,
|
||||
buffer->dma_buffer->iova, buffer->dma_buffer->size, dir);
|
||||
} else {
|
||||
dma_sync_single_for_device(scheduler->dev,
|
||||
buffer->phys_addr, buffer->size, dir);
|
||||
}
|
||||
} else {
|
||||
sgt = rga_mm_lookup_sgt(buffer);
|
||||
if (sgt == NULL) {
|
||||
@@ -1372,16 +1366,26 @@ static int rga_mm_sync_dma_sg_for_cpu(struct rga_internal_buffer *buffer,
|
||||
struct rga_scheduler_t *scheduler;
|
||||
ktime_t timestamp = ktime_get();
|
||||
|
||||
scheduler = buffer->dma_buffer->scheduler;
|
||||
scheduler = buffer->scheduler;
|
||||
if (scheduler == NULL) {
|
||||
rga_job_err(job, "%s(%d), failed to get scheduler, core = 0x%x\n",
|
||||
__func__, __LINE__, job->core);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS &&
|
||||
scheduler->data->mmu != RGA_IOMMU) {
|
||||
dma_sync_single_for_cpu(scheduler->dev, buffer->phys_addr, buffer->size, dir);
|
||||
if (buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) {
|
||||
if (scheduler->data->mmu == RGA_IOMMU) {
|
||||
if (rga_mm_is_invalid_dma_buffer(buffer->dma_buffer)) {
|
||||
rga_job_err(job, "invalid dma-buffer with IOMMU device!\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
dma_sync_single_for_cpu(buffer->dma_buffer->map_dev,
|
||||
buffer->dma_buffer->iova, buffer->dma_buffer->size, dir);
|
||||
} else {
|
||||
dma_sync_single_for_cpu(scheduler->dev,
|
||||
buffer->phys_addr, buffer->size, dir);
|
||||
}
|
||||
} else {
|
||||
sgt = rga_mm_lookup_sgt(buffer);
|
||||
if (sgt == NULL) {
|
||||
@@ -1920,6 +1924,8 @@ static int rga_mm_map_channel_job_buffer(struct rga_job *job,
|
||||
goto error_free_buffer;
|
||||
}
|
||||
|
||||
buffer->session = job->session;
|
||||
|
||||
if (DEBUGGER_EN(MM)) {
|
||||
rga_job_log(job, "map buffer:\n");
|
||||
rga_mm_dump_buffer(buffer);
|
||||
|
||||
@@ -69,6 +69,8 @@ enum pcie_ep_mmap_resource {
|
||||
PCIE_EP_MMAP_RESOURCE_USER_MEM,
|
||||
PCIE_EP_MMAP_RESOURCE_RK3568_RC_DBI,
|
||||
PCIE_EP_MMAP_RESOURCE_RK3588_RC_DBI,
|
||||
PCIE_EP_MMAP_RESOURCE_BAR1,
|
||||
PCIE_EP_MMAP_RESOURCE_BAR5,
|
||||
PCIE_EP_MMAP_RESOURCE_MAX,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user