diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2017-11-01 23:16:19 +0300 |
---|---|---|
committer | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2017-11-20 22:14:22 +0300 |
commit | a01cb8ba3f6282934cff65e89ab36b18b14cbe27 (patch) | |
tree | 691bc30cc8bd0eb5007f207e019ca1ad275b4599 /drivers | |
parent | 10b47ee02d1ae66160058241cf5b962f64e81b47 (diff) | |
download | linux-a01cb8ba3f6282934cff65e89ab36b18b14cbe27.tar.xz |
drm: Move drm_plane_helper_check_state() into drm_atomic_helper.c
drm_plane_helper_check_update() isn't a transitional helper, so let's
rename it to drm_atomic_helper_check_plane_state() and move it into
drm_atomic_helper.c.
v2: Fix the WARNs about plane_state->crtc matching crtc_state->crtc
Cc: Daniel Vetter <daniel@ffwll.ch>
Suggested-by: Daniel Vetter <daniel@ffwll.ch>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20171101201619.6175-1-ville.syrjala@linux.intel.com
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/arm/hdlcd_crtc.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_planes.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_atomic_helper.c | 94 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_plane_helper.c | 102 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_simple_kms_helper.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/imx/ipuv3-plane.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/mediatek/mtk_drm_plane.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/meson/meson_plane.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/zte/zx_plane.c | 15 |
15 files changed, 162 insertions, 159 deletions
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 14721723fa8a..63511a3bbf6c 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -252,10 +252,10 @@ static int hdlcd_plane_atomic_check(struct drm_plane *plane, clip.x2 = crtc_state->adjusted_mode.hdisplay; clip.y2 = crtc_state->adjusted_mode.vdisplay; - return drm_plane_helper_check_state(state, crtc_state, &clip, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - false, true); + return drm_atomic_helper_check_plane_state(state, crtc_state, &clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + false, true); } static void hdlcd_plane_atomic_update(struct drm_plane *plane, diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 492d99dd55d4..72a07950167e 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -150,8 +150,8 @@ static int malidp_se_check_scaling(struct malidp_plane *mp, clip.x2 = crtc_state->adjusted_mode.hdisplay; clip.y2 = crtc_state->adjusted_mode.vdisplay; - ret = drm_plane_helper_check_state(state, crtc_state, &clip, - 0, INT_MAX, true, true); + ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, + 0, INT_MAX, true, true); if (ret) return ret; diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 07d4058d97d0..ce6d11ae9e26 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -696,6 +696,100 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, EXPORT_SYMBOL(drm_atomic_helper_check_modeset); /** + * drm_atomic_helper_check_plane_state() - Check plane state for validity + * @plane_state: plane state to check + * @crtc_state: crtc state to check + * @clip: integer clipping coordinates + * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point + * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point + * @can_position: is it legal to position the plane such that it + * doesn't cover the entire crtc? This will generally + * only be false for primary planes. + * @can_update_disabled: can the plane be updated while the crtc + * is disabled? + * + * Checks that a desired plane update is valid, and updates various + * bits of derived state (clipped coordinates etc.). Drivers that provide + * their own plane handling rather than helper-provided implementations may + * still wish to call this function to avoid duplication of error checking + * code. + * + * RETURNS: + * Zero if update appears valid, error code on failure + */ +int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state, + const struct drm_crtc_state *crtc_state, + const struct drm_rect *clip, + int min_scale, + int max_scale, + bool can_position, + bool can_update_disabled) +{ + struct drm_framebuffer *fb = plane_state->fb; + struct drm_rect *src = &plane_state->src; + struct drm_rect *dst = &plane_state->dst; + unsigned int rotation = plane_state->rotation; + int hscale, vscale; + + WARN_ON(plane_state->crtc && plane_state->crtc != crtc_state->crtc); + + *src = drm_plane_state_src(plane_state); + *dst = drm_plane_state_dest(plane_state); + + if (!fb) { + plane_state->visible = false; + return 0; + } + + /* crtc should only be NULL when disabling (i.e., !fb) */ + if (WARN_ON(!plane_state->crtc)) { + plane_state->visible = false; + return 0; + } + + if (!crtc_state->enable && !can_update_disabled) { + DRM_DEBUG_KMS("Cannot update plane of a disabled CRTC.\n"); + return -EINVAL; + } + + drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation); + + /* Check scaling */ + hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale); + vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale); + if (hscale < 0 || vscale < 0) { + DRM_DEBUG_KMS("Invalid scaling of plane\n"); + drm_rect_debug_print("src: ", &plane_state->src, true); + drm_rect_debug_print("dst: ", &plane_state->dst, false); + return -ERANGE; + } + + plane_state->visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale); + + drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation); + + if (!plane_state->visible) + /* + * Plane isn't visible; some drivers can handle this + * so we just return success here. Drivers that can't + * (including those that use the primary plane helper's + * update function) will return an error from their + * update_plane handler. + */ + return 0; + + if (!can_position && !drm_rect_equals(dst, clip)) { + DRM_DEBUG_KMS("Plane must cover entire CRTC\n"); + drm_rect_debug_print("dst: ", dst, false); + drm_rect_debug_print("clip: ", clip, false); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_helper_check_plane_state); + +/** * drm_atomic_helper_check_planes - validate state object for planes changes * @dev: DRM device * @state: the driver state object diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index eef0ffcd7ed5..f1be8cd4e387 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -100,100 +100,6 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc, } /** - * drm_plane_helper_check_state() - Check plane state for validity - * @plane_state: plane state to check - * @crtc_state: crtc state to check - * @clip: integer clipping coordinates - * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point - * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point - * @can_position: is it legal to position the plane such that it - * doesn't cover the entire crtc? This will generally - * only be false for primary planes. - * @can_update_disabled: can the plane be updated while the crtc - * is disabled? - * - * Checks that a desired plane update is valid, and updates various - * bits of derived state (clipped coordinates etc.). Drivers that provide - * their own plane handling rather than helper-provided implementations may - * still wish to call this function to avoid duplication of error checking - * code. - * - * RETURNS: - * Zero if update appears valid, error code on failure - */ -int drm_plane_helper_check_state(struct drm_plane_state *plane_state, - const struct drm_crtc_state *crtc_state, - const struct drm_rect *clip, - int min_scale, - int max_scale, - bool can_position, - bool can_update_disabled) -{ - struct drm_framebuffer *fb = plane_state->fb; - struct drm_rect *src = &plane_state->src; - struct drm_rect *dst = &plane_state->dst; - unsigned int rotation = plane_state->rotation; - int hscale, vscale; - - WARN_ON(plane_state->crtc && plane_state->crtc != crtc_state->crtc); - - *src = drm_plane_state_src(plane_state); - *dst = drm_plane_state_dest(plane_state); - - if (!fb) { - plane_state->visible = false; - return 0; - } - - /* crtc should only be NULL when disabling (i.e., !fb) */ - if (WARN_ON(!plane_state->crtc)) { - plane_state->visible = false; - return 0; - } - - if (!crtc_state->enable && !can_update_disabled) { - DRM_DEBUG_KMS("Cannot update plane of a disabled CRTC.\n"); - return -EINVAL; - } - - drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation); - - /* Check scaling */ - hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale); - vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale); - if (hscale < 0 || vscale < 0) { - DRM_DEBUG_KMS("Invalid scaling of plane\n"); - drm_rect_debug_print("src: ", &plane_state->src, true); - drm_rect_debug_print("dst: ", &plane_state->dst, false); - return -ERANGE; - } - - plane_state->visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale); - - drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation); - - if (!plane_state->visible) - /* - * Plane isn't visible; some drivers can handle this - * so we just return success here. Drivers that can't - * (including those that use the primary plane helper's - * update function) will return an error from their - * update_plane handler. - */ - return 0; - - if (!can_position && !drm_rect_equals(dst, clip)) { - DRM_DEBUG_KMS("Plane must cover entire CRTC\n"); - drm_rect_debug_print("dst: ", dst, false); - drm_rect_debug_print("clip: ", clip, false); - return -EINVAL; - } - - return 0; -} -EXPORT_SYMBOL(drm_plane_helper_check_state); - -/** * drm_plane_helper_check_update() - Check plane update for validity * @plane: plane object to update * @crtc: owning CRTC of owning plane @@ -254,10 +160,10 @@ int drm_plane_helper_check_update(struct drm_plane *plane, }; int ret; - ret = drm_plane_helper_check_state(&plane_state, &crtc_state, clip, - min_scale, max_scale, - can_position, - can_update_disabled); + ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, + clip, min_scale, max_scale, + can_position, + can_update_disabled); if (ret) return ret; diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index d428c805025c..9f3b1c94802b 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c @@ -103,10 +103,11 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane, clip.x2 = crtc_state->adjusted_mode.hdisplay; clip.y2 = crtc_state->adjusted_mode.vdisplay; - ret = drm_plane_helper_check_state(plane_state, crtc_state, &clip, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - false, true); + ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state, + &clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + false, true); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5e75d762745a..97406166417d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9418,12 +9418,12 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, u32 offset; int ret; - ret = drm_plane_helper_check_state(&plane_state->base, - &crtc_state->base, - &plane_state->clip, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - true, true); + ret = drm_atomic_helper_check_plane_state(&plane_state->base, + &crtc_state->base, + &plane_state->clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + true, true); if (ret) return ret; @@ -12842,11 +12842,11 @@ intel_check_primary_plane(struct intel_plane *plane, can_position = true; } - ret = drm_plane_helper_check_state(&state->base, - &crtc_state->base, - &state->clip, - min_scale, max_scale, - can_position, true); + ret = drm_atomic_helper_check_plane_state(&state->base, + &crtc_state->base, + &state->clip, + min_scale, max_scale, + can_position, true); if (ret) return ret; diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 51b23ac175e3..5a67daedcf4d 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -342,10 +342,10 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, clip.y1 = 0; clip.x2 = crtc_state->adjusted_mode.hdisplay; clip.y2 = crtc_state->adjusted_mode.vdisplay; - ret = drm_plane_helper_check_state(state, crtc_state, &clip, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - can_position, true); + ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + can_position, true); if (ret) return ret; diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c index 7ebb33657704..5ef898b93d8d 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c @@ -111,10 +111,10 @@ static int mtk_plane_atomic_check(struct drm_plane *plane, clip.x2 = crtc_state->mode.hdisplay; clip.y2 = crtc_state->mode.vdisplay; - return drm_plane_helper_check_state(state, crtc_state, &clip, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - true, true); + return drm_atomic_helper_check_plane_state(state, crtc_state, &clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + true, true); } static void mtk_plane_atomic_update(struct drm_plane *plane, diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c index 2a00b720c371..d0a6ac8390f3 100644 --- a/drivers/gpu/drm/meson/meson_plane.c +++ b/drivers/gpu/drm/meson/meson_plane.c @@ -61,10 +61,10 @@ static int meson_plane_atomic_check(struct drm_plane *plane, clip.x2 = crtc_state->mode.hdisplay; clip.y2 = crtc_state->mode.vdisplay; - return drm_plane_helper_check_state(state, crtc_state, &clip, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - true, true); + return drm_atomic_helper_check_plane_state(state, crtc_state, &clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + true, true); } /* Takes a fixed 16.16 number and converts it to integer. */ diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 1c194a9453d9..df3360acacca 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -348,8 +348,9 @@ static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state, min_scale = FRAC_16_16(1, 8); max_scale = FRAC_16_16(8, 1); - ret = drm_plane_helper_check_state(state, crtc_state, &clip, - min_scale, max_scale, true, true); + ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, + min_scale, max_scale, + true, true); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 0738ae1f6cf4..9fc8fe017118 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -1143,11 +1143,11 @@ nv50_curs_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, { int ret; - ret = drm_plane_helper_check_state(&asyw->state, &asyh->state, - &asyw->clip, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - true, true); + ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state, + &asyw->clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + true, true); asyh->curs.visible = asyw->state.visible; if (ret || !asyh->curs.visible) return ret; @@ -1433,11 +1433,11 @@ nv50_base_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, if (!fb->format->depth) return -EINVAL; - ret = drm_plane_helper_check_state(&asyw->state, &asyh->state, - &asyw->clip, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - false, true); + ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state, + &asyw->clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + false, true); if (ret) return ret; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 36d0f101e30d..ba7505292b78 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -659,9 +659,9 @@ static int vop_plane_atomic_check(struct drm_plane *plane, clip.x2 = crtc_state->adjusted_mode.hdisplay; clip.y2 = crtc_state->adjusted_mode.vdisplay; - ret = drm_plane_helper_check_state(state, crtc_state, &clip, - min_scale, max_scale, - true, true); + ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, + min_scale, max_scale, + true, true); if (ret) return ret; diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 08b899fd74fc..91919d52b207 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -500,8 +500,8 @@ static int tegra_plane_state_add(struct tegra_plane *plane, clip.y2 = crtc_state->mode.vdisplay; /* Check plane state for visibility and calculate clipping bounds */ - err = drm_plane_helper_check_state(state, crtc_state, &clip, - 0, INT_MAX, true, true); + err = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, + 0, INT_MAX, true, true); if (err < 0) return err; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 91555c0370e1..13ac2c5a04ee 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -454,10 +454,10 @@ int vmw_du_primary_plane_atomic_check(struct drm_plane *plane, clip.y2 = crtc_state->adjusted_mode.vdisplay; } - ret = drm_plane_helper_check_state(state, crtc_state, &clip, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - false, true); + ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + false, true); if (!ret && new_fb) { struct drm_crtc *crtc = state->crtc; diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c index ee0002529b8f..68fd2e2dc78a 100644 --- a/drivers/gpu/drm/zte/zx_plane.c +++ b/drivers/gpu/drm/zte/zx_plane.c @@ -80,9 +80,9 @@ static int zx_vl_plane_atomic_check(struct drm_plane *plane, clip.x2 = crtc_state->adjusted_mode.hdisplay; clip.y2 = crtc_state->adjusted_mode.vdisplay; - return drm_plane_helper_check_state(plane_state, crtc_state, &clip, - min_scale, max_scale, - true, true); + return drm_atomic_helper_check_plane_state(plane_state, crtc_state, + &clip, min_scale, max_scale, + true, true); } static int zx_vl_get_fmt(uint32_t format) @@ -315,10 +315,11 @@ static int zx_gl_plane_atomic_check(struct drm_plane *plane, clip.x2 = crtc_state->adjusted_mode.hdisplay; clip.y2 = crtc_state->adjusted_mode.vdisplay; - return drm_plane_helper_check_state(plane_state, crtc_state, &clip, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - false, true); + return drm_atomic_helper_check_plane_state(plane_state, crtc_state, + &clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + false, true); } static int zx_gl_get_fmt(uint32_t format) |