1
0
Fork 0

MLK-18162 gpu: imx: dpu: Abstract fetch unit concept

This patch abstracts fetch unit concept for all the fetch units
we have - fetchdecode, fetcheco, fetchlayer and fetchwarp.
They have some similar features and operations which are suitable
to be abstracted.  A lot of boilerplate code is removed.

Signed-off-by: Liu Ying <victor.liu@nxp.com>
pull/10/head
Liu Ying 2018-04-25 13:45:30 +08:00 committed by Jason Liu
parent 1473536864
commit 549f1b74ba
13 changed files with 1151 additions and 2384 deletions

View File

@ -342,16 +342,14 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
struct dpu_plane *dplane; struct dpu_plane *dplane;
struct drm_plane *plane; struct drm_plane *plane;
struct dpu_plane_res *res; struct dpu_plane_res *res;
struct dpu_fetchdecode *fd = NULL; struct dpu_fetchunit *fu;
struct dpu_fetchlayer *fl = NULL; struct dpu_fetchunit *fe = NULL;
struct dpu_fetchwarp *fw = NULL;
struct dpu_fetcheco *fe = NULL;
struct dpu_hscaler *hs = NULL; struct dpu_hscaler *hs = NULL;
struct dpu_vscaler *vs = NULL; struct dpu_vscaler *vs = NULL;
struct dpu_layerblend *lb; struct dpu_layerblend *lb;
struct dpu_extdst *ed; struct dpu_extdst *ed;
extdst_src_sel_t ed_src; extdst_src_sel_t ed_src;
int fu_id, lb_id, fu_type; int lb_id;
bool crtc_disabling_on_primary = false; bool crtc_disabling_on_primary = false;
old_dpstate = old_dcstate->dpu_plane_states[i]; old_dpstate = old_dcstate->dpu_plane_states[i];
@ -362,26 +360,10 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
dplane = to_dpu_plane(plane_state->plane); dplane = to_dpu_plane(plane_state->plane);
res = &dplane->grp->res; res = &dplane->grp->res;
fu_type = source_to_type(old_dpstate->source); fu = dpstate_to_fu(old_dpstate);
fu_id = source_to_id(old_dpstate->source); if (!fu)
if (fu_id < 0)
return; return;
switch (fu_type) {
case DPU_PLANE_SRC_FD:
fd = res->fd[fu_id];
break;
case DPU_PLANE_SRC_FL:
fl = res->fl[fu_id];
break;
case DPU_PLANE_SRC_FW:
fw = res->fw[fu_id];
break;
default:
WARN_ON(1);
return;
}
lb_id = blend_to_id(old_dpstate->blend); lb_id = blend_to_id(old_dpstate->blend);
if (lb_id < 0) if (lb_id < 0)
return; return;
@ -389,10 +371,10 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
lb = res->lb[lb_id]; lb = res->lb[lb_id];
layerblend_pixengcfg_clken(lb, CLKEN__DISABLE); layerblend_pixengcfg_clken(lb, CLKEN__DISABLE);
if (fd) { if (fetchunit_is_fetchdecode(fu)) {
fe = fetchdecode_get_fetcheco(fd); fe = fetchdecode_get_fetcheco(fu);
hs = fetchdecode_get_hscaler(fd); hs = fetchdecode_get_hscaler(fu);
vs = fetchdecode_get_vscaler(fd); vs = fetchdecode_get_vscaler(fu);
hscaler_pixengcfg_clken(hs, CLKEN__DISABLE); hscaler_pixengcfg_clken(hs, CLKEN__DISABLE);
vscaler_pixengcfg_clken(vs, CLKEN__DISABLE); vscaler_pixengcfg_clken(vs, CLKEN__DISABLE);
hscaler_mode(hs, SCALER_NEUTRAL); hscaler_mode(hs, SCALER_NEUTRAL);
@ -411,29 +393,18 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
crtc_disabling_on_primary = true; crtc_disabling_on_primary = true;
if (crtc_disabling_on_primary && old_dpstate->use_prefetch) { if (crtc_disabling_on_primary && old_dpstate->use_prefetch) {
if (fd) { fu->ops->pin_off(fu);
fetchdecode_pin_off(fd); if (fetchunit_is_fetchdecode(fu) &&
if (fetcheco_is_enabled(fe)) fe->ops->is_enabled(fe))
fetcheco_pin_off(fe); fe->ops->pin_off(fe);
} else if (fl) {
fetchlayer_pin_off(fl);
} else if (fw) {
fetchwarp_pin_off(fw);
}
} else { } else {
if (fd) { fu->ops->disable_src_buf(fu);
fetchdecode_source_buffer_disable(fd); fu->ops->unpin_off(fu);
fetchdecode_pixengcfg_dynamic_src_sel(fd, if (fetchunit_is_fetchdecode(fu)) {
fetchdecode_pixengcfg_dynamic_src_sel(fu,
FD_SRC_DISABLE); FD_SRC_DISABLE);
fetcheco_source_buffer_disable(fe); fe->ops->disable_src_buf(fe);
fetchdecode_unpin_off(fd); fe->ops->unpin_off(fe);
fetcheco_unpin_off(fe);
} else if (fl) {
fetchlayer_source_buffer_disable(fl, 0);
fetchlayer_unpin_off(fl);
} else if (fw) {
fetchwarp_source_buffer_disable(fw, 0);
fetchwarp_unpin_off(fw);
} }
} }
} }
@ -484,76 +455,38 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc,
for (i = 0; i < dpu_crtc->hw_plane_num; i++) { for (i = 0; i < dpu_crtc->hw_plane_num; i++) {
struct dpu_plane_state *old_dpstate; struct dpu_plane_state *old_dpstate;
struct drm_plane_state *plane_state; struct dpu_fetchunit *fu;
struct dpu_plane *dplane; struct dpu_fetchunit *fe;
struct dpu_plane_res *res;
struct dpu_fetchdecode *fd = NULL;
struct dpu_fetchlayer *fl = NULL;
struct dpu_fetchwarp *fw = NULL;
struct dpu_fetcheco *fe;
struct dpu_hscaler *hs; struct dpu_hscaler *hs;
struct dpu_vscaler *vs; struct dpu_vscaler *vs;
int fu_id, fu_type;
old_dpstate = old_dcstate->dpu_plane_states[i]; old_dpstate = old_dcstate->dpu_plane_states[i];
if (!old_dpstate) if (!old_dpstate)
continue; continue;
plane_state = &old_dpstate->base; fu = dpstate_to_fu(old_dpstate);
dplane = to_dpu_plane(plane_state->plane); if (!fu)
res = &dplane->grp->res;
fu_type = source_to_type(old_dpstate->source);
fu_id = source_to_id(old_dpstate->source);
if (fu_id < 0)
return; return;
switch (fu_type) { if (!fu->ops->is_enabled(fu) || fu->ops->is_pinned_off(fu))
case DPU_PLANE_SRC_FD: fu->ops->set_stream_id(fu, DPU_PLANE_SRC_DISABLED);
fd = res->fd[fu_id];
break;
case DPU_PLANE_SRC_FL:
fl = res->fl[fu_id];
break;
case DPU_PLANE_SRC_FW:
fw = res->fw[fu_id];
break;
default:
WARN_ON(1);
return;
}
if (fd) { if (fetchunit_is_fetchdecode(fu)) {
if (!fetchdecode_is_enabled(fd) || fe = fetchdecode_get_fetcheco(fu);
fetchdecode_is_pinned_off(fd)) if (!fe->ops->is_enabled(fe) ||
fetchdecode_set_stream_id(fd, fe->ops->is_pinned_off(fe))
fe->ops->set_stream_id(fe,
DPU_PLANE_SRC_DISABLED); DPU_PLANE_SRC_DISABLED);
fe = fetchdecode_get_fetcheco(fd); hs = fetchdecode_get_hscaler(fu);
if (!fetcheco_is_enabled(fe) ||
fetcheco_is_pinned_off(fe))
fetcheco_set_stream_id(fe,
DPU_PLANE_SRC_DISABLED);
hs = fetchdecode_get_hscaler(fd);
if (!hscaler_is_enabled(hs)) if (!hscaler_is_enabled(hs))
hscaler_set_stream_id(hs, hscaler_set_stream_id(hs,
DPU_PLANE_SRC_DISABLED); DPU_PLANE_SRC_DISABLED);
vs = fetchdecode_get_vscaler(fd); vs = fetchdecode_get_vscaler(fu);
if (!vscaler_is_enabled(vs)) if (!vscaler_is_enabled(vs))
vscaler_set_stream_id(vs, vscaler_set_stream_id(vs,
DPU_PLANE_SRC_DISABLED); DPU_PLANE_SRC_DISABLED);
} else if (fl) {
if (!fetchlayer_is_enabled(fl, 0) ||
fetchlayer_is_pinned_off(fl))
fetchlayer_set_stream_id(fl,
DPU_PLANE_SRC_DISABLED);
} else if (fw) {
if (!fetchwarp_is_enabled(fw, 0) ||
fetchwarp_is_pinned_off(fw))
fetchwarp_set_stream_id(fw,
DPU_PLANE_SRC_DISABLED);
} }
} }
} }

View File

@ -133,16 +133,13 @@ dpu_atomic_assign_plane_source_per_crtc(struct drm_plane_state **states, int n)
struct dpu_plane *dplane; struct dpu_plane *dplane;
struct dpu_plane_grp *grp; struct dpu_plane_grp *grp;
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
struct dpu_fetchdecode *fd; struct dpu_fetchunit *fu;
struct dpu_fetcheco *fe; struct dpu_fetchunit *fe;
struct dpu_fetchlayer *fl;
struct dpu_fetchwarp *fw;
struct dpu_hscaler *hs; struct dpu_hscaler *hs;
struct dpu_vscaler *vs; struct dpu_vscaler *vs;
unsigned int sid, src_sid; unsigned int sid, src_sid;
unsigned int num_planes; unsigned int num_planes;
int i, j, k, l, m; int i, j, k, l, m;
int fu_id, fu_type;
int total_asrc_num; int total_asrc_num;
u32 src_a_mask, cap_mask, fe_mask, hs_mask, vs_mask; u32 src_a_mask, cap_mask, fe_mask, hs_mask, vs_mask;
bool need_fetcheco, need_hscaler, need_vscaler; bool need_fetcheco, need_hscaler, need_vscaler;
@ -178,49 +175,23 @@ dpu_atomic_assign_plane_source_per_crtc(struct drm_plane_state **states, int n)
for (k = 0; k < total_asrc_num; k++) { for (k = 0; k < total_asrc_num; k++) {
m = ffs(src_a_mask) - 1; m = ffs(src_a_mask) - 1;
fu_type = source_to_type(sources[m]); fu = source_to_fu(&grp->res, sources[m]);
fu_id = source_to_id(sources[m]); if (!fu)
return -EINVAL;
switch (fu_type) { /* avoid on-the-fly/hot migration */
case DPU_PLANE_SRC_FL: src_sid = fu->ops->get_stream_id(fu);
fl = grp->res.fl[fu_id]; if (src_sid && src_sid != BIT(sid))
goto next;
if (fmt_is_yuv || need_fetcheco || if (fetchunit_is_fetchdecode(fu)) {
need_hscaler || need_vscaler) cap_mask = fetchdecode_get_vproc_mask(fu);
goto next;
/* avoid on-the-fly/hot migration */
src_sid = fetchlayer_get_stream_id(fl);
if (src_sid && src_sid != BIT(sid))
goto next;
break;
case DPU_PLANE_SRC_FW:
fw = grp->res.fw[fu_id];
if (fmt_is_yuv || need_fetcheco ||
need_hscaler || need_vscaler)
goto next;
/* avoid on-the-fly/hot migration */
src_sid = fetchwarp_get_stream_id(fw);
if (src_sid && src_sid != BIT(sid))
goto next;
break;
case DPU_PLANE_SRC_FD:
fd = grp->res.fd[fu_id];
/* avoid on-the-fly/hot migration */
src_sid = fetchdecode_get_stream_id(fd);
if (src_sid && src_sid != BIT(sid))
goto next;
cap_mask = fetchdecode_get_vproc_mask(fd);
if (need_fetcheco) { if (need_fetcheco) {
fe = fetchdecode_get_fetcheco(fd); fe = fetchdecode_get_fetcheco(fu);
/* avoid on-the-fly/hot migration */ /* avoid on-the-fly/hot migration */
src_sid = fetcheco_get_stream_id(fe); src_sid = fu->ops->get_stream_id(fe);
if (src_sid && src_sid != BIT(sid)) if (src_sid && src_sid != BIT(sid))
goto next; goto next;
@ -237,7 +208,7 @@ dpu_atomic_assign_plane_source_per_crtc(struct drm_plane_state **states, int n)
} }
if (need_hscaler) { if (need_hscaler) {
hs = fetchdecode_get_hscaler(fd); hs = fetchdecode_get_hscaler(fu);
/* avoid on-the-fly/hot migration */ /* avoid on-the-fly/hot migration */
src_sid = hscaler_get_stream_id(hs); src_sid = hscaler_get_stream_id(hs);
@ -257,7 +228,7 @@ dpu_atomic_assign_plane_source_per_crtc(struct drm_plane_state **states, int n)
} }
if (need_vscaler) { if (need_vscaler) {
vs = fetchdecode_get_vscaler(fd); vs = fetchdecode_get_vscaler(fu);
/* avoid on-the-fly/hot migration */ /* avoid on-the-fly/hot migration */
src_sid = vscaler_get_stream_id(vs); src_sid = vscaler_get_stream_id(vs);
@ -275,9 +246,10 @@ dpu_atomic_assign_plane_source_per_crtc(struct drm_plane_state **states, int n)
if (grp->src_use_vproc_mask & vs_mask) if (grp->src_use_vproc_mask & vs_mask)
goto next; goto next;
} }
break; } else {
default: if (fmt_is_yuv || need_fetcheco ||
return -EINVAL; need_hscaler || need_vscaler)
goto next;
} }
grp->src_a_mask &= ~BIT(m); grp->src_a_mask &= ~BIT(m);

View File

@ -19,6 +19,7 @@
#include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
#include <drm/drm_plane_helper.h> #include <drm/drm_plane_helper.h>
#include <video/dpu.h> #include <video/dpu.h>
#include <video/imx8-prefetch.h>
#include "dpu-plane.h" #include "dpu-plane.h"
#include "imx-drm.h" #include "imx-drm.h"
@ -220,17 +221,15 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state) struct drm_plane_state *state)
{ {
struct dpu_plane *dplane = to_dpu_plane(plane); struct dpu_plane *dplane = to_dpu_plane(plane);
struct dpu_plane_res *res = &dplane->grp->res;
struct dpu_plane_state *dpstate = to_dpu_plane_state(state); struct dpu_plane_state *dpstate = to_dpu_plane_state(state);
struct drm_crtc_state *crtc_state; struct drm_crtc_state *crtc_state;
struct drm_framebuffer *fb = state->fb; struct drm_framebuffer *fb = state->fb;
struct dpu_fetchdecode *fd = NULL; struct dpu_fetchunit *fu;
struct dpu_fetchlayer *fl = NULL; struct dprc *dprc;
struct dpu_fetchwarp *fw = NULL;
dma_addr_t baseaddr, uv_baseaddr = 0; dma_addr_t baseaddr, uv_baseaddr = 0;
u32 src_w = state->src_w >> 16, src_h = state->src_h >> 16, u32 src_w = state->src_w >> 16, src_h = state->src_h >> 16,
src_x = state->src_x >> 16, src_y = state->src_y >> 16; src_x = state->src_x >> 16, src_y = state->src_y >> 16;
int bpp, fu_id, fu_type; int bpp;
bool fb_is_interlaced; bool fb_is_interlaced;
/* pure software check */ /* pure software check */
@ -258,6 +257,12 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
if (!state->crtc) if (!state->crtc)
return -EINVAL; return -EINVAL;
fu = dpstate_to_fu(dpstate);
if (!fu)
return -EINVAL;
dprc = fu->dprc;
fb_is_interlaced = !!(fb->flags & DRM_MODE_FB_INTERLACED); fb_is_interlaced = !!(fb->flags & DRM_MODE_FB_INTERLACED);
if (fb->modifier && if (fb->modifier &&
@ -331,32 +336,10 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
break; break;
} }
fu_type = source_to_type(dpstate->source); if (dprc &&
fu_id = source_to_id(dpstate->source); dprc_format_supported(dprc, fb->format->format, fb->modifier) &&
if (fu_id < 0) dprc_stride_supported(dprc, fb->pitches[0], fb->pitches[1],
return -EINVAL; src_w, fb->format->format))
switch (fu_type) {
case DPU_PLANE_SRC_FD:
fd = res->fd[fu_id];
break;
case DPU_PLANE_SRC_FL:
fl = res->fl[fu_id];
break;
case DPU_PLANE_SRC_FW:
fw = res->fw[fu_id];
break;
default:
return -EINVAL;
}
if (fetchunit_has_prefetch(fd, fl, fw) &&
fetchunit_prefetch_format_supported(fd, fl, fw, fb->format->format,
fb->modifier) &&
fetchunit_prefetch_stride_supported(fd, fl, fw, fb->pitches[0],
fb->pitches[1],
src_w,
fb->format->format))
dpstate->use_prefetch = true; dpstate->use_prefetch = true;
else else
dpstate->use_prefetch = false; dpstate->use_prefetch = false;
@ -404,10 +387,9 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
} }
if (dpstate->use_prefetch && if (dpstate->use_prefetch &&
!fetchunit_prefetch_stride_double_check(fd, fl, fw, fb->pitches[0], !dprc_stride_double_check(dprc, fb->pitches[0], fb->pitches[1],
fb->pitches[1], src_w, fb->format->format,
src_w, fb->format->format, baseaddr, uv_baseaddr)) {
baseaddr, uv_baseaddr)) {
if (fb->modifier) if (fb->modifier)
return -EINVAL; return -EINVAL;
@ -431,10 +413,9 @@ static void dpu_plane_atomic_update(struct drm_plane *plane,
struct dpu_plane_state *dpstate = to_dpu_plane_state(state); struct dpu_plane_state *dpstate = to_dpu_plane_state(state);
struct drm_framebuffer *fb = state->fb; struct drm_framebuffer *fb = state->fb;
struct dpu_plane_res *res = &dplane->grp->res; struct dpu_plane_res *res = &dplane->grp->res;
struct dpu_fetchdecode *fd = NULL; struct dpu_fetchunit *fu;
struct dpu_fetchlayer *fl = NULL; struct dpu_fetchunit *fe = NULL;
struct dpu_fetchwarp *fw = NULL; struct dprc *dprc;
struct dpu_fetcheco *fe = NULL;
struct dpu_hscaler *hs = NULL; struct dpu_hscaler *hs = NULL;
struct dpu_vscaler *vs = NULL; struct dpu_vscaler *vs = NULL;
struct dpu_layerblend *lb; struct dpu_layerblend *lb;
@ -446,10 +427,8 @@ static void dpu_plane_atomic_update(struct drm_plane *plane,
dpu_block_id_t fe_id, vs_id = ID_NONE, hs_id; dpu_block_id_t fe_id, vs_id = ID_NONE, hs_id;
lb_sec_sel_t lb_src = dpstate->source; lb_sec_sel_t lb_src = dpstate->source;
unsigned int src_w, src_h, src_x, src_y; unsigned int src_w, src_h, src_x, src_y;
int bpp, fu_id, lb_id, fu_type; int bpp, lb_id;
bool need_fetcheco = false, need_hscaler = false, need_vscaler = false; bool need_fetcheco = false, need_hscaler = false, need_vscaler = false;
bool need_fetchdecode = false, need_fetchlayer = false,
need_fetchwarp = false;
bool prefetch_start = false, aux_prefetch_start = false; bool prefetch_start = false, aux_prefetch_start = false;
bool need_modeset; bool need_modeset;
bool is_overlay = plane->type == DRM_PLANE_TYPE_OVERLAY; bool is_overlay = plane->type == DRM_PLANE_TYPE_OVERLAY;
@ -465,28 +444,11 @@ static void dpu_plane_atomic_update(struct drm_plane *plane,
need_modeset = drm_atomic_crtc_needs_modeset(state->crtc->state); need_modeset = drm_atomic_crtc_needs_modeset(state->crtc->state);
fb_is_interlaced = !!(fb->flags & DRM_MODE_FB_INTERLACED); fb_is_interlaced = !!(fb->flags & DRM_MODE_FB_INTERLACED);
fu_type = source_to_type(dpstate->source); fu = dpstate_to_fu(dpstate);
fu_id = source_to_id(dpstate->source); if (!fu)
if (fu_id < 0)
return; return;
switch (fu_type) { dprc = fu->dprc;
case DPU_PLANE_SRC_FD:
need_fetchdecode = true;
fd = res->fd[fu_id];
break;
case DPU_PLANE_SRC_FL:
need_fetchlayer = true;
fl = res->fl[fu_id];
break;
case DPU_PLANE_SRC_FW:
need_fetchwarp = true;
fw = res->fw[fu_id];
break;
default:
WARN_ON(1);
return;
}
lb_id = blend_to_id(dpstate->blend); lb_id = blend_to_id(dpstate->blend);
if (lb_id < 0) if (lb_id < 0)
@ -499,24 +461,24 @@ static void dpu_plane_atomic_update(struct drm_plane *plane,
src_x = state->src_x >> 16; src_x = state->src_x >> 16;
src_y = state->src_y >> 16; src_y = state->src_y >> 16;
if (need_fetchdecode) { if (fetchunit_is_fetchdecode(fu)) {
if (fetchdecode_need_fetcheco(fd, fb->format->format)) { if (fetchdecode_need_fetcheco(fu, fb->format->format)) {
need_fetcheco = true; need_fetcheco = true;
fe = fetchdecode_get_fetcheco(fd); fe = fetchdecode_get_fetcheco(fu);
if (IS_ERR(fe)) if (IS_ERR(fe))
return; return;
} }
if (src_w != state->crtc_w) { if (src_w != state->crtc_w) {
need_hscaler = true; need_hscaler = true;
hs = fetchdecode_get_hscaler(fd); hs = fetchdecode_get_hscaler(fu);
if (IS_ERR(hs)) if (IS_ERR(hs))
return; return;
} }
if ((src_h != state->crtc_h) || fb_is_interlaced) { if ((src_h != state->crtc_h) || fb_is_interlaced) {
need_vscaler = true; need_vscaler = true;
vs = fetchdecode_get_vscaler(fd); vs = fetchdecode_get_vscaler(fu);
if (IS_ERR(vs)) if (IS_ERR(vs))
return; return;
} }
@ -540,82 +502,27 @@ static void dpu_plane_atomic_update(struct drm_plane *plane,
if (need_fetcheco) if (need_fetcheco)
uv_baseaddr = drm_plane_state_to_uvbaseaddr(state); uv_baseaddr = drm_plane_state_to_uvbaseaddr(state);
if (dpstate->use_prefetch) { if (dpstate->use_prefetch &&
if (need_fetchdecode && (fu->ops->get_stream_id(fu) == DPU_PLANE_SRC_DISABLED ||
(fetchdecode_get_stream_id(fd) == DPU_PLANE_SRC_DISABLED || need_modeset))
need_modeset)) prefetch_start = true;
prefetch_start = true;
if (need_fetchlayer && fu->ops->set_burstlength(fu, baseaddr, dpstate->use_prefetch);
(fetchlayer_get_stream_id(fl) == DPU_PLANE_SRC_DISABLED || fu->ops->set_src_bpp(fu, bpp);
need_modeset)) fu->ops->set_src_stride(fu, src_w, bpp, fb->pitches[0],
prefetch_start = true; baseaddr, dpstate->use_prefetch);
fu->ops->set_src_buf_dimensions(fu, src_w, src_h, 0, fb_is_interlaced);
if (need_fetchwarp && fu->ops->set_fmt(fu, fb->format->format, fb_is_interlaced);
(fetchwarp_get_stream_id(fw) == DPU_PLANE_SRC_DISABLED || fu->ops->enable_src_buf(fu);
need_modeset)) fu->ops->set_framedimensions(fu, src_w, src_h, fb_is_interlaced);
prefetch_start = true; fu->ops->set_baseaddress(fu, baseaddr);
} fu->ops->set_stream_id(fu, dplane->stream_id ?
if (need_fetchdecode) {
fetchdecode_set_burstlength(fd, baseaddr,
dpstate->use_prefetch);
fetchdecode_source_bpp(fd, bpp);
fetchdecode_source_stride(fd, src_w, bpp, fb->pitches[0],
baseaddr, dpstate->use_prefetch);
fetchdecode_src_buf_dimensions(fd, src_w, src_h,
fb_is_interlaced);
fetchdecode_set_fmt(fd, fb->format->format, fb_is_interlaced);
fetchdecode_source_buffer_enable(fd);
fetchdecode_framedimensions(fd, src_w, src_h,
fb_is_interlaced);
fetchdecode_baseaddress(fd, baseaddr);
fetchdecode_set_stream_id(fd, dplane->stream_id ?
DPU_PLANE_SRC_TO_DISP_STREAM1 : DPU_PLANE_SRC_TO_DISP_STREAM1 :
DPU_PLANE_SRC_TO_DISP_STREAM0); DPU_PLANE_SRC_TO_DISP_STREAM0);
fetchdecode_unpin_off(fd); fu->ops->unpin_off(fu);
dev_dbg(dev, "[PLANE:%d:%s] fetchdecode-0x%02x\n", dev_dbg(dev, "[PLANE:%d:%s] %s-0x%02x\n",
plane->base.id, plane->name, fu_id); plane->base.id, plane->name, fu->name, fu->id);
}
if (need_fetchlayer) {
fetchlayer_set_burstlength(fl, baseaddr, dpstate->use_prefetch);
fetchlayer_source_bpp(fl, 0, bpp);
fetchlayer_source_stride(fl, 0, src_w, bpp, fb->pitches[0],
baseaddr, dpstate->use_prefetch);
fetchlayer_src_buf_dimensions(fl, 0, src_w, src_h);
fetchlayer_set_fmt(fl, 0, fb->format->format);
fetchlayer_source_buffer_enable(fl, 0);
fetchlayer_framedimensions(fl, src_w, src_h);
fetchlayer_baseaddress(fl, 0, baseaddr);
fetchlayer_set_stream_id(fl, dplane->stream_id ?
DPU_PLANE_SRC_TO_DISP_STREAM1 :
DPU_PLANE_SRC_TO_DISP_STREAM0);
fetchlayer_unpin_off(fl);
dev_dbg(dev, "[PLANE:%d:%s] fetchlayer-0x%02x\n",
plane->base.id, plane->name, fu_id);
}
if (need_fetchwarp) {
fetchwarp_set_burstlength(fw, baseaddr, dpstate->use_prefetch);
fetchwarp_source_bpp(fw, 0, bpp);
fetchwarp_source_stride(fw, 0, src_w, bpp, fb->pitches[0],
baseaddr, dpstate->use_prefetch);
fetchwarp_src_buf_dimensions(fw, 0, src_w, src_h);
fetchwarp_set_fmt(fw, 0, fb->format->format);
fetchwarp_source_buffer_enable(fw, 0);
fetchwarp_framedimensions(fw, src_w, src_h);
fetchwarp_baseaddress(fw, 0, baseaddr);
fetchwarp_set_stream_id(fw, dplane->stream_id ?
DPU_PLANE_SRC_TO_DISP_STREAM1 :
DPU_PLANE_SRC_TO_DISP_STREAM0);
fetchwarp_unpin_off(fw);
dev_dbg(dev, "[PLANE:%d:%s] fetchwarp-0x%02x\n",
plane->base.id, plane->name, fu_id);
}
if (need_fetcheco) { if (need_fetcheco) {
fe_id = fetcheco_get_block_id(fe); fe_id = fetcheco_get_block_id(fe);
@ -623,33 +530,35 @@ static void dpu_plane_atomic_update(struct drm_plane *plane,
return; return;
if (dpstate->use_prefetch && if (dpstate->use_prefetch &&
(fetcheco_get_stream_id(fe) == DPU_PLANE_SRC_DISABLED || (fe->ops->get_stream_id(fe) == DPU_PLANE_SRC_DISABLED ||
need_modeset)) need_modeset))
aux_prefetch_start = true; aux_prefetch_start = true;
fetchdecode_pixengcfg_dynamic_src_sel(fd, fetchdecode_pixengcfg_dynamic_src_sel(fu,
(fd_dynamic_src_sel_t)fe_id); (fd_dynamic_src_sel_t)fe_id);
fetcheco_set_burstlength(fe, uv_baseaddr, fe->ops->set_burstlength(fe, uv_baseaddr,
dpstate->use_prefetch); dpstate->use_prefetch);
fetcheco_source_bpp(fe, 16); fe->ops->set_src_bpp(fe, 16);
fetcheco_source_stride(fe, src_w, bpp, fb->pitches[1], fe->ops->set_src_stride(fe, src_w, bpp, fb->pitches[1],
uv_baseaddr, dpstate->use_prefetch); uv_baseaddr, dpstate->use_prefetch);
fetcheco_set_fmt(fe, fb->format->format); fe->ops->set_fmt(fe, fb->format->format, fb_is_interlaced);
fetcheco_src_buf_dimensions(fe, src_w, src_h, fe->ops->set_src_buf_dimensions(fe, src_w, src_h,
fb->format->format, fb_is_interlaced); fb->format->format,
fetcheco_framedimensions(fe, src_w, src_h, fb_is_interlaced); fb_is_interlaced);
fetcheco_baseaddress(fe, uv_baseaddr); fe->ops->set_framedimensions(fe, src_w, src_h,
fetcheco_source_buffer_enable(fe); fb_is_interlaced);
fetcheco_set_stream_id(fe, dplane->stream_id ? fe->ops->set_baseaddress(fe, uv_baseaddr);
fe->ops->enable_src_buf(fe);
fe->ops->set_stream_id(fe, dplane->stream_id ?
DPU_PLANE_SRC_TO_DISP_STREAM1 : DPU_PLANE_SRC_TO_DISP_STREAM1 :
DPU_PLANE_SRC_TO_DISP_STREAM0); DPU_PLANE_SRC_TO_DISP_STREAM0);
fetcheco_unpin_off(fe); fe->ops->unpin_off(fe);
dev_dbg(dev, "[PLANE:%d:%s] fetcheco-0x%02x\n", dev_dbg(dev, "[PLANE:%d:%s] %s-0x%02x\n",
plane->base.id, plane->name, fe_id); plane->base.id, plane->name, fe->name, fe_id);
} else { } else {
if (fd) if (fetchunit_is_fetchdecode(fu))
fetchdecode_pixengcfg_dynamic_src_sel(fd, fetchdecode_pixengcfg_dynamic_src_sel(fu,
FD_SRC_DISABLE); FD_SRC_DISABLE);
} }
@ -707,21 +616,19 @@ static void dpu_plane_atomic_update(struct drm_plane *plane,
} }
if (dpstate->use_prefetch) { if (dpstate->use_prefetch) {
fetchunit_configure_prefetch(fd, fl, fw, dplane->stream_id, dprc_configure(dprc, dplane->stream_id,
src_w, src_h, src_x, src_y, src_w, src_h, src_x, src_y,
fb->pitches[0], fb->format->format, fb->pitches[0], fb->format->format,
fb->modifier, fb->modifier, baseaddr, uv_baseaddr,
baseaddr, uv_baseaddr, prefetch_start, aux_prefetch_start,
prefetch_start, fb_is_interlaced);
aux_prefetch_start,
fb_is_interlaced);
if (prefetch_start || aux_prefetch_start) if (prefetch_start || aux_prefetch_start)
fetchunit_enable_prefetch(fd, fl, fw); dprc_enable(dprc);
fetchunit_reg_update_prefetch(fd, fl, fw); dprc_reg_update(dprc);
if (prefetch_start || aux_prefetch_start) { if (prefetch_start || aux_prefetch_start) {
fetchunit_prefetch_first_frame_handle(fd, fl, fw); dprc_first_frame_handle(dprc);
if (!need_modeset && is_overlay) if (!need_modeset && is_overlay)
framegen_wait_for_frame_counter_moving(fg); framegen_wait_for_frame_counter_moving(fg);
@ -729,8 +636,8 @@ static void dpu_plane_atomic_update(struct drm_plane *plane,
dev_dbg(dev, "[PLANE:%d:%s] use prefetch\n", dev_dbg(dev, "[PLANE:%d:%s] use prefetch\n",
plane->base.id, plane->name); plane->base.id, plane->name);
} else if (fetchunit_has_prefetch(fd, fl, fw)) { } else if (dprc) {
fetchunit_disable_prefetch(fd, fl, fw); dprc_disable(dprc);
dev_dbg(dev, "[PLANE:%d:%s] bypass prefetch\n", dev_dbg(dev, "[PLANE:%d:%s] bypass prefetch\n",
plane->base.id, plane->name); plane->base.id, plane->name);

View File

@ -128,6 +128,37 @@ static inline int source_to_id(lb_sec_sel_t source)
return -EINVAL; return -EINVAL;
} }
static inline struct dpu_fetchunit *
source_to_fu(struct dpu_plane_res *res, lb_sec_sel_t source)
{
int fu_type = source_to_type(source);
int fu_id = source_to_id(source);
if (fu_type < 0 || fu_id < 0)
return NULL;
switch (fu_type) {
case DPU_PLANE_SRC_FD:
return res->fd[fu_id];
case DPU_PLANE_SRC_FL:
return res->fl[fu_id];
case DPU_PLANE_SRC_FW:
return res->fw[fu_id];
}
return NULL;
}
static inline struct dpu_fetchunit *
dpstate_to_fu(struct dpu_plane_state *dpstate)
{
struct drm_plane *plane = dpstate->base.plane;
struct dpu_plane *dplane = to_dpu_plane(plane);
struct dpu_plane_res *res = &dplane->grp->res;
return source_to_fu(res, dpstate->source);
}
static inline int blend_to_id(dpu_block_id_t blend) static inline int blend_to_id(dpu_block_id_t blend)
{ {
int i; int i;

View File

@ -2,5 +2,6 @@ obj-$(CONFIG_IMX_DPU_CORE) += imx-dpu-core.o
imx-dpu-core-objs := dpu-common.o dpu-constframe.o dpu-disengcfg.o \ imx-dpu-core-objs := dpu-common.o dpu-constframe.o dpu-disengcfg.o \
dpu-extdst.o dpu-fetchdecode.o dpu-fetcheco.o \ dpu-extdst.o dpu-fetchdecode.o dpu-fetcheco.o \
dpu-fetchlayer.o dpu-fetchwarp.o dpu-framegen.o \ dpu-fetchlayer.o dpu-fetchwarp.o dpu-fetchunit.o \
dpu-hscaler.o dpu-layerblend.o dpu-tcon.o dpu-vscaler.o dpu-framegen.o dpu-hscaler.o dpu-layerblend.o \
dpu-tcon.o dpu-vscaler.o

View File

@ -661,157 +661,6 @@ u32 dpu_vproc_get_vscale_cap(u32 cap_mask)
} }
EXPORT_SYMBOL_GPL(dpu_vproc_get_vscale_cap); EXPORT_SYMBOL_GPL(dpu_vproc_get_vscale_cap);
bool fetchunit_has_prefetch(struct dpu_fetchdecode *fd,
struct dpu_fetchlayer *fl,
struct dpu_fetchwarp *fw)
{
if (fd)
return fetchdecode_has_prefetch(fd);
else if (fl)
return fetchlayer_has_prefetch(fl);
else
return fetchwarp_has_prefetch(fw);
}
EXPORT_SYMBOL_GPL(fetchunit_has_prefetch);
bool fetchunit_prefetch_format_supported(struct dpu_fetchdecode *fd,
struct dpu_fetchlayer *fl,
struct dpu_fetchwarp *fw,
u32 format, u64 modifier)
{
if (fd)
return fetchdecode_prefetch_format_supported(fd,
format, modifier);
else if (fl)
return fetchlayer_prefetch_format_supported(fl,
format, modifier);
else
return fetchwarp_prefetch_format_supported(fw,
format, modifier);
}
EXPORT_SYMBOL_GPL(fetchunit_prefetch_format_supported);
bool fetchunit_prefetch_stride_supported(struct dpu_fetchdecode *fd,
struct dpu_fetchlayer *fl,
struct dpu_fetchwarp *fw,
unsigned int stride,
unsigned int uv_stride,
unsigned int width,
u32 format)
{
if (fd)
return fetchdecode_prefetch_stride_supported(fd,
stride, uv_stride, width, format);
else if (fl)
return fetchlayer_prefetch_stride_supported(fl,
stride, width, format);
else
return fetchwarp_prefetch_stride_supported(fw,
stride, width, format);
}
EXPORT_SYMBOL_GPL(fetchunit_prefetch_stride_supported);
bool fetchunit_prefetch_stride_double_check(struct dpu_fetchdecode *fd,
struct dpu_fetchlayer *fl,
struct dpu_fetchwarp *fw,
unsigned int stride,
unsigned int uv_stride,
unsigned int width,
u32 format,
dma_addr_t baseaddr,
dma_addr_t uv_baseaddr)
{
if (fd)
return fetchdecode_prefetch_stride_double_check(fd, stride,
uv_stride, width, format, baseaddr, uv_baseaddr);
else if (fl)
return fetchlayer_prefetch_stride_double_check(fl, stride,
width, format, baseaddr);
else
return fetchwarp_prefetch_stride_double_check(fw, stride,
width, format, baseaddr);
}
EXPORT_SYMBOL_GPL(fetchunit_prefetch_stride_double_check);
void fetchunit_configure_prefetch(struct dpu_fetchdecode *fd,
struct dpu_fetchlayer *fl,
struct dpu_fetchwarp *fw,
unsigned int stream_id,
unsigned int width, unsigned int height,
unsigned int x_offset, unsigned int y_offset,
unsigned int stride, u32 format, u64 modifier,
unsigned long baddr, unsigned long uv_baddr,
bool start, bool aux_start,
bool fb_is_interlaced)
{
if (fd)
fetchdecode_configure_prefetch(fd, stream_id, width, height,
x_offset, y_offset, stride,
format, modifier, baddr, uv_baddr,
start, aux_start, fb_is_interlaced);
else if (fl)
fetchlayer_configure_prefetch(fl, stream_id, width, height,
x_offset, y_offset, stride,
format, modifier, baddr, start);
else
fetchwarp_configure_prefetch(fw, stream_id, width, height,
x_offset, y_offset, stride,
format, modifier, baddr, start);
}
EXPORT_SYMBOL_GPL(fetchunit_configure_prefetch);
void fetchunit_enable_prefetch(struct dpu_fetchdecode *fd,
struct dpu_fetchlayer *fl,
struct dpu_fetchwarp *fw)
{
if (fd)
fetchdecode_enable_prefetch(fd);
else if (fl)
fetchlayer_enable_prefetch(fl);
else
fetchwarp_enable_prefetch(fw);
}
EXPORT_SYMBOL_GPL(fetchunit_enable_prefetch);
void fetchunit_reg_update_prefetch(struct dpu_fetchdecode *fd,
struct dpu_fetchlayer *fl,
struct dpu_fetchwarp *fw)
{
if (fd)
fetchdecode_reg_update_prefetch(fd);
else if (fl)
fetchlayer_reg_update_prefetch(fl);
else
fetchwarp_reg_update_prefetch(fw);
}
EXPORT_SYMBOL_GPL(fetchunit_reg_update_prefetch);
void fetchunit_prefetch_first_frame_handle(struct dpu_fetchdecode *fd,
struct dpu_fetchlayer *fl,
struct dpu_fetchwarp *fw)
{
if (fd)
fetchdecode_prefetch_first_frame_handle(fd);
else if (fl)
fetchlayer_prefetch_first_frame_handle(fl);
else
fetchwarp_prefetch_first_frame_handle(fw);
}
EXPORT_SYMBOL_GPL(fetchunit_prefetch_first_frame_handle);
void fetchunit_disable_prefetch(struct dpu_fetchdecode *fd,
struct dpu_fetchlayer *fl,
struct dpu_fetchwarp *fw)
{
if (fd)
fetchdecode_disable_prefetch(fd);
else if (fl)
fetchlayer_disable_prefetch(fl);
else
fetchwarp_disable_prefetch(fw);
}
EXPORT_SYMBOL_GPL(fetchunit_disable_prefetch);
int dpu_format_horz_chroma_subsampling(u32 format) int dpu_format_horz_chroma_subsampling(u32 format)
{ {
switch (format) { switch (format) {
@ -961,9 +810,7 @@ static int dpu_submodules_init(struct dpu_soc *dpu,
/* get DPR channel for submodules */ /* get DPR channel for submodules */
if (devtype->has_prefetch) { if (devtype->has_prefetch) {
struct dpu_fetchdecode *fd; struct dpu_fetchunit *fu;
struct dpu_fetchlayer *fl;
struct dpu_fetchwarp *fw;
struct dprc *dprc; struct dprc *dprc;
int i; int i;
@ -974,9 +821,9 @@ static int dpu_submodules_init(struct dpu_soc *dpu,
if (!dprc) if (!dprc)
return -EPROBE_DEFER; return -EPROBE_DEFER;
fd = dpu_fd_get(dpu, i); fu = dpu_fd_get(dpu, i);
fetchdecode_get_dprc(fd, dprc); fetchunit_get_dprc(fu, dprc);
dpu_fd_put(fd); dpu_fd_put(fu);
} }
for (i = 0; i < fls->num; i++) { for (i = 0; i < fls->num; i++) {
@ -986,9 +833,9 @@ static int dpu_submodules_init(struct dpu_soc *dpu,
if (!dprc) if (!dprc)
return -EPROBE_DEFER; return -EPROBE_DEFER;
fl = dpu_fl_get(dpu, i); fu = dpu_fl_get(dpu, i);
fetchlayer_get_dprc(fl, dprc); fetchunit_get_dprc(fu, dprc);
dpu_fl_put(fl); dpu_fl_put(fu);
} }
for (i = 0; i < fws->num; i++) { for (i = 0; i < fws->num; i++) {
@ -998,9 +845,9 @@ static int dpu_submodules_init(struct dpu_soc *dpu,
if (!dprc) if (!dprc)
return -EPROBE_DEFER; return -EPROBE_DEFER;
fw = dpu_fw_get(dpu, fw_ids[i]); fu = dpu_fw_get(dpu, fw_ids[i]);
fetchwarp_get_dprc(fw, dprc); fetchunit_get_dprc(fu, dprc);
dpu_fw_put(fw); dpu_fw_put(fu);
} }
} }
@ -1540,10 +1387,13 @@ static irqreturn_t dpu_dpr0_irq_handler(int irq, void *desc)
{ {
struct dpu_soc *dpu = desc; struct dpu_soc *dpu = desc;
const struct dpu_unit *fls = dpu->devtype->fls; const struct dpu_unit *fls = dpu->devtype->fls;
struct dpu_fetchunit *fu;
int i; int i;
for (i = 0; i < fls->num; i++) for (i = 0; i < fls->num; i++) {
fetchlayer_prefetch_irq_handle(dpu->fl_priv[i]); fu = dpu->fl_priv[i];
dprc_irq_handle(fu->dprc);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -1553,13 +1403,18 @@ static irqreturn_t dpu_dpr1_irq_handler(int irq, void *desc)
struct dpu_soc *dpu = desc; struct dpu_soc *dpu = desc;
const struct dpu_unit *fds = dpu->devtype->fds; const struct dpu_unit *fds = dpu->devtype->fds;
const struct dpu_unit *fws = dpu->devtype->fws; const struct dpu_unit *fws = dpu->devtype->fws;
struct dpu_fetchunit *fu;
int i; int i;
for (i = 0; i < fds->num; i++) for (i = 0; i < fds->num; i++) {
fetchdecode_prefetch_irq_handle(dpu->fd_priv[i]); fu = dpu->fd_priv[i];
dprc_irq_handle(fu->dprc);
}
for (i = 0; i < fws->num; i++) for (i = 0; i < fws->num; i++) {
fetchwarp_prefetch_irq_handle(dpu->fw_priv[i]); fu = dpu->fw_priv[i];
dprc_irq_handle(fu->dprc);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }

View File

@ -19,7 +19,6 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/types.h> #include <linux/types.h>
#include <video/dpu.h> #include <video/dpu.h>
#include <video/imx8-prefetch.h>
#include "dpu-prv.h" #include "dpu-prv.h"
#define FD_NUM_V1 4 #define FD_NUM_V1 4
@ -98,56 +97,24 @@ static const shadow_load_req_t fd_shdlreqs[] = {
}; };
struct dpu_fetchdecode { struct dpu_fetchdecode {
void __iomem *pec_base; struct dpu_fetchunit fu;
void __iomem *base;
struct mutex mutex;
int id;
bool inuse;
bool pin_off;
struct dpu_soc *dpu;
fetchtype_t fetchtype; fetchtype_t fetchtype;
shadow_load_req_t shdlreq; shadow_load_req_t shdlreq;
/* see DPU_PLANE_SRC_xxx */
unsigned int stream_id;
struct dprc *dprc;
}; };
static inline u32 dpu_pec_fd_read(struct dpu_fetchdecode *fd, int fetchdecode_pixengcfg_dynamic_src_sel(struct dpu_fetchunit *fu,
unsigned int offset)
{
return readl(fd->pec_base + offset);
}
static inline void dpu_pec_fd_write(struct dpu_fetchdecode *fd, u32 value,
unsigned int offset)
{
writel(value, fd->pec_base + offset);
}
static inline u32 dpu_fd_read(struct dpu_fetchdecode *fd, unsigned int offset)
{
return readl(fd->base + offset);
}
static inline void dpu_fd_write(struct dpu_fetchdecode *fd, u32 value,
unsigned int offset)
{
writel(value, fd->base + offset);
}
int fetchdecode_pixengcfg_dynamic_src_sel(struct dpu_fetchdecode *fd,
fd_dynamic_src_sel_t src) fd_dynamic_src_sel_t src)
{ {
struct dpu_soc *dpu = fd->dpu; struct dpu_soc *dpu = fu->dpu;
const struct dpu_devtype *devtype = dpu->devtype; const struct dpu_devtype *devtype = dpu->devtype;
int i; int i;
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
if (devtype->version == DPU_V1) { if (devtype->version == DPU_V1) {
for (i = 0; i < SRC_NUM_V1; i++) { for (i = 0; i < SRC_NUM_V1; i++) {
if (fd_srcs_v1[fd->id][i] == src) { if (fd_srcs_v1[fu->id][i] == src) {
dpu_pec_fd_write(fd, src, PIXENGCFG_DYNAMIC); dpu_pec_fu_write(fu, src, PIXENGCFG_DYNAMIC);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
return 0; return 0;
} }
} }
@ -159,119 +126,50 @@ int fetchdecode_pixengcfg_dynamic_src_sel(struct dpu_fetchdecode *fd,
return -EINVAL; return -EINVAL;
for (i = 0; i < SRC_NUM_V2; i++) { for (i = 0; i < SRC_NUM_V2; i++) {
if (fd_srcs_v2[fd->id][i] == src) { if (fd_srcs_v2[fu->id][i] == src) {
mapped_src = block_id_map[src]; mapped_src = block_id_map[src];
if (WARN_ON(mapped_src == NA)) if (WARN_ON(mapped_src == NA))
return -EINVAL; return -EINVAL;
dpu_pec_fd_write(fd, mapped_src, dpu_pec_fu_write(fu, mapped_src,
PIXENGCFG_DYNAMIC); PIXENGCFG_DYNAMIC);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
return 0; return 0;
} }
} }
} else { } else {
WARN_ON(1); WARN_ON(1);
} }
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
return -EINVAL; return -EINVAL;
} }
EXPORT_SYMBOL_GPL(fetchdecode_pixengcfg_dynamic_src_sel); EXPORT_SYMBOL_GPL(fetchdecode_pixengcfg_dynamic_src_sel);
static inline u32 rgb_color(u8 r, u8 g, u8 b, u8 a) static void
fetchdecode_set_baseaddress(struct dpu_fetchunit *fu, dma_addr_t paddr)
{ {
return (r << 24) | (g << 16) | (b << 8) | a; mutex_lock(&fu->mutex);
dpu_fu_write(fu, paddr, BASEADDRESS0);
mutex_unlock(&fu->mutex);
} }
static inline u32 yuv_color(u8 y, u8 u, u8 v) static void fetchdecode_set_src_bpp(struct dpu_fetchunit *fu, int bpp)
{
return (y << 24) | (u << 16) | (v << 8);
}
void fetchdecode_shden(struct dpu_fetchdecode *fd, bool enable)
{ {
u32 val; u32 val;
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
val = dpu_fd_read(fd, STATICCONTROL); val = dpu_fu_read(fu, SOURCEBUFFERATTRIBUTES0);
if (enable)
val |= SHDEN;
else
val &= ~SHDEN;
dpu_fd_write(fd, val, STATICCONTROL);
mutex_unlock(&fd->mutex);
}
EXPORT_SYMBOL_GPL(fetchdecode_shden);
void fetchdecode_baddr_autoupdate(struct dpu_fetchdecode *fd, u8 layer_mask)
{
u32 val;
mutex_lock(&fd->mutex);
val = dpu_fd_read(fd, STATICCONTROL);
val &= ~BASEADDRESSAUTOUPDATE_MASK;
val |= BASEADDRESSAUTOUPDATE(layer_mask);
dpu_fd_write(fd, val, STATICCONTROL);
mutex_unlock(&fd->mutex);
}
EXPORT_SYMBOL_GPL(fetchdecode_baddr_autoupdate);
void fetchdecode_set_burstlength(struct dpu_fetchdecode *fd, dma_addr_t baddr,
bool use_prefetch)
{
struct dpu_soc *dpu = fd->dpu;
unsigned int burst_size, burst_length;
u32 val;
if (use_prefetch) {
/*
* address TKT343664:
* fetch unit base address has to align to burst size
*/
burst_size = 1 << (ffs(baddr) - 1);
burst_size = min(burst_size, 128U);
burst_length = burst_size / 8;
} else {
burst_length = 16;
}
mutex_lock(&fd->mutex);
val = dpu_fd_read(fd, BURSTBUFFERMANAGEMENT);
val &= ~SETBURSTLENGTH_MASK;
val |= SETBURSTLENGTH(burst_length);
dpu_fd_write(fd, val, BURSTBUFFERMANAGEMENT);
mutex_unlock(&fd->mutex);
dev_dbg(dpu->dev, "FetchDecode%d burst length is %u\n",
fd->id, burst_length);
}
EXPORT_SYMBOL_GPL(fetchdecode_set_burstlength);
void fetchdecode_baseaddress(struct dpu_fetchdecode *fd, dma_addr_t paddr)
{
mutex_lock(&fd->mutex);
dpu_fd_write(fd, paddr, BASEADDRESS0);
mutex_unlock(&fd->mutex);
}
EXPORT_SYMBOL_GPL(fetchdecode_baseaddress);
void fetchdecode_source_bpp(struct dpu_fetchdecode *fd, int bpp)
{
u32 val;
mutex_lock(&fd->mutex);
val = dpu_fd_read(fd, SOURCEBUFFERATTRIBUTES0);
val &= ~0x3f0000; val &= ~0x3f0000;
val |= BITSPERPIXEL(bpp); val |= BITSPERPIXEL(bpp);
dpu_fd_write(fd, val, SOURCEBUFFERATTRIBUTES0); dpu_fu_write(fu, val, SOURCEBUFFERATTRIBUTES0);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchdecode_source_bpp);
void fetchdecode_source_stride(struct dpu_fetchdecode *fd, unsigned int width, static void
int bpp, unsigned int stride, fetchdecode_set_src_stride(struct dpu_fetchunit *fu,
dma_addr_t baddr, bool use_prefetch) unsigned int width, int bpp, unsigned int stride,
dma_addr_t baddr, bool use_prefetch)
{ {
unsigned int burst_size; unsigned int burst_size;
u32 val; u32 val;
@ -292,17 +190,18 @@ void fetchdecode_source_stride(struct dpu_fetchdecode *fd, unsigned int width,
stride = round_up(stride, burst_size); stride = round_up(stride, burst_size);
} }
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
val = dpu_fd_read(fd, SOURCEBUFFERATTRIBUTES0); val = dpu_fu_read(fu, SOURCEBUFFERATTRIBUTES0);
val &= ~0xffff; val &= ~0xffff;
val |= STRIDE(stride); val |= STRIDE(stride);
dpu_fd_write(fd, val, SOURCEBUFFERATTRIBUTES0); dpu_fu_write(fu, val, SOURCEBUFFERATTRIBUTES0);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchdecode_source_stride);
void fetchdecode_src_buf_dimensions(struct dpu_fetchdecode *fd, unsigned int w, static void
unsigned int h, bool deinterlace) fetchdecode_set_src_buf_dimensions(struct dpu_fetchunit *fu,
unsigned int w, unsigned int h,
u32 unused, bool deinterlace)
{ {
u32 val; u32 val;
@ -311,13 +210,13 @@ void fetchdecode_src_buf_dimensions(struct dpu_fetchdecode *fd, unsigned int w,
val = LINEWIDTH(w) | LINECOUNT(h); val = LINEWIDTH(w) | LINECOUNT(h);
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
dpu_fd_write(fd, val, SOURCEBUFFERDIMENSION0); dpu_fu_write(fu, val, SOURCEBUFFERDIMENSION0);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchdecode_src_buf_dimensions);
void fetchdecode_set_fmt(struct dpu_fetchdecode *fd, u32 fmt, bool deinterlace) static void
fetchdecode_set_fmt(struct dpu_fetchunit *fu, u32 fmt, bool deinterlace)
{ {
u32 val, bits, shift; u32 val, bits, shift;
bool is_planar_yuv = false, is_rastermode_yuv422 = false; bool is_planar_yuv = false, is_rastermode_yuv422 = false;
@ -357,8 +256,8 @@ void fetchdecode_set_fmt(struct dpu_fetchdecode *fd, u32 fmt, bool deinterlace)
break; break;
} }
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
val = dpu_fd_read(fd, CONTROL); val = dpu_fu_read(fu, CONTROL);
val &= ~YUV422UPSAMPLINGMODE_MASK; val &= ~YUV422UPSAMPLINGMODE_MASK;
val &= ~INPUTSELECT_MASK; val &= ~INPUTSELECT_MASK;
val &= ~RASTERMODE_MASK; val &= ~RASTERMODE_MASK;
@ -374,9 +273,9 @@ void fetchdecode_set_fmt(struct dpu_fetchdecode *fd, u32 fmt, bool deinterlace)
val |= RASTERMODE(RASTERMODE__YUV422); val |= RASTERMODE(RASTERMODE__YUV422);
else else
val |= RASTERMODE(RASTERMODE__NORMAL); val |= RASTERMODE(RASTERMODE__NORMAL);
dpu_fd_write(fd, val, CONTROL); dpu_fu_write(fu, val, CONTROL);
val = dpu_fd_read(fd, LAYERPROPERTY0); val = dpu_fu_read(fu, LAYERPROPERTY0);
val &= ~YUVCONVERSIONMODE_MASK; val &= ~YUVCONVERSIONMODE_MASK;
if (need_csc) if (need_csc)
/* /*
@ -389,8 +288,8 @@ void fetchdecode_set_fmt(struct dpu_fetchdecode *fd, u32 fmt, bool deinterlace)
val |= YUVCONVERSIONMODE(YUVCONVERSIONMODE__ITU601_FR); val |= YUVCONVERSIONMODE(YUVCONVERSIONMODE__ITU601_FR);
else else
val |= YUVCONVERSIONMODE(YUVCONVERSIONMODE__OFF); val |= YUVCONVERSIONMODE(YUVCONVERSIONMODE__OFF);
dpu_fd_write(fd, val, LAYERPROPERTY0); dpu_fu_write(fu, val, LAYERPROPERTY0);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
for (i = 0; i < ARRAY_SIZE(dpu_pixel_format_matrix); i++) { for (i = 0; i < ARRAY_SIZE(dpu_pixel_format_matrix); i++) {
if (dpu_pixel_format_matrix[i].pixel_format == fmt) { if (dpu_pixel_format_matrix[i].pixel_format == fmt) {
@ -402,95 +301,93 @@ void fetchdecode_set_fmt(struct dpu_fetchdecode *fd, u32 fmt, bool deinterlace)
shift &= ~(U_SHIFT_MASK | V_SHIFT_MASK); shift &= ~(U_SHIFT_MASK | V_SHIFT_MASK);
} }
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
dpu_fd_write(fd, bits, COLORCOMPONENTBITS0); dpu_fu_write(fu, bits, COLORCOMPONENTBITS0);
dpu_fd_write(fd, shift, COLORCOMPONENTSHIFT0); dpu_fu_write(fu, shift, COLORCOMPONENTSHIFT0);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
return; return;
} }
} }
WARN_ON(1); WARN_ON(1);
} }
EXPORT_SYMBOL_GPL(fetchdecode_set_fmt);
void fetchdecode_layeroffset(struct dpu_fetchdecode *fd, unsigned int x, void fetchdecode_layeroffset(struct dpu_fetchunit *fu, unsigned int x,
unsigned int y) unsigned int y)
{ {
u32 val; u32 val;
val = LAYERXOFFSET(x) | LAYERYOFFSET(y); val = LAYERXOFFSET(x) | LAYERYOFFSET(y);
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
dpu_fd_write(fd, val, LAYEROFFSET0); dpu_fu_write(fu, val, LAYEROFFSET0);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchdecode_layeroffset); EXPORT_SYMBOL_GPL(fetchdecode_layeroffset);
void fetchdecode_clipoffset(struct dpu_fetchdecode *fd, unsigned int x, void fetchdecode_clipoffset(struct dpu_fetchunit *fu, unsigned int x,
unsigned int y) unsigned int y)
{ {
u32 val; u32 val;
val = CLIPWINDOWXOFFSET(x) | CLIPWINDOWYOFFSET(y); val = CLIPWINDOWXOFFSET(x) | CLIPWINDOWYOFFSET(y);
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
dpu_fd_write(fd, val, CLIPWINDOWOFFSET0); dpu_fu_write(fu, val, CLIPWINDOWOFFSET0);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchdecode_clipoffset); EXPORT_SYMBOL_GPL(fetchdecode_clipoffset);
void fetchdecode_source_buffer_enable(struct dpu_fetchdecode *fd) static void fetchdecode_enable_src_buf(struct dpu_fetchunit *fu)
{ {
u32 val; u32 val;
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
val = dpu_fd_read(fd, LAYERPROPERTY0); val = dpu_fu_read(fu, LAYERPROPERTY0);
val |= SOURCEBUFFERENABLE; val |= SOURCEBUFFERENABLE;
dpu_fd_write(fd, val, LAYERPROPERTY0); dpu_fu_write(fu, val, LAYERPROPERTY0);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchdecode_source_buffer_enable);
void fetchdecode_source_buffer_disable(struct dpu_fetchdecode *fd) static void fetchdecode_disable_src_buf(struct dpu_fetchunit *fu)
{ {
u32 val; u32 val;
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
val = dpu_fd_read(fd, LAYERPROPERTY0); val = dpu_fu_read(fu, LAYERPROPERTY0);
val &= ~SOURCEBUFFERENABLE; val &= ~SOURCEBUFFERENABLE;
dpu_fd_write(fd, val, LAYERPROPERTY0); dpu_fu_write(fu, val, LAYERPROPERTY0);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchdecode_source_buffer_disable);
bool fetchdecode_is_enabled(struct dpu_fetchdecode *fd) static bool fetchdecode_is_enabled(struct dpu_fetchunit *fu)
{ {
u32 val; u32 val;
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
val = dpu_fd_read(fd, LAYERPROPERTY0); val = dpu_fu_read(fu, LAYERPROPERTY0);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
return !!(val & SOURCEBUFFERENABLE); return !!(val & SOURCEBUFFERENABLE);
} }
EXPORT_SYMBOL_GPL(fetchdecode_is_enabled);
void fetchdecode_clipdimensions(struct dpu_fetchdecode *fd, unsigned int w, void fetchdecode_clipdimensions(struct dpu_fetchunit *fu, unsigned int w,
unsigned int h) unsigned int h)
{ {
u32 val; u32 val;
val = CLIPWINDOWWIDTH(w) | CLIPWINDOWHEIGHT(h); val = CLIPWINDOWWIDTH(w) | CLIPWINDOWHEIGHT(h);
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
dpu_fd_write(fd, val, CLIPWINDOWDIMENSIONS0); dpu_fu_write(fu, val, CLIPWINDOWDIMENSIONS0);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchdecode_clipdimensions); EXPORT_SYMBOL_GPL(fetchdecode_clipdimensions);
void fetchdecode_framedimensions(struct dpu_fetchdecode *fd, unsigned int w, static void
unsigned int h, bool deinterlace) fetchdecode_set_framedimensions(struct dpu_fetchunit *fu,
unsigned int w, unsigned int h,
bool deinterlace)
{ {
u32 val; u32 val;
@ -499,101 +396,95 @@ void fetchdecode_framedimensions(struct dpu_fetchdecode *fd, unsigned int w,
val = FRAMEWIDTH(w) | FRAMEHEIGHT(h); val = FRAMEWIDTH(w) | FRAMEHEIGHT(h);
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
dpu_fd_write(fd, val, FRAMEDIMENSIONS); dpu_fu_write(fu, val, FRAMEDIMENSIONS);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchdecode_framedimensions);
void fetchdecode_rgb_constantcolor(struct dpu_fetchdecode *fd, void fetchdecode_rgb_constantcolor(struct dpu_fetchunit *fu,
u8 r, u8 g, u8 b, u8 a) u8 r, u8 g, u8 b, u8 a)
{ {
u32 val; u32 val;
val = rgb_color(r, g, b, a); val = rgb_color(r, g, b, a);
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
dpu_fd_write(fd, val, CONSTANTCOLOR0); dpu_fu_write(fu, val, CONSTANTCOLOR0);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchdecode_rgb_constantcolor); EXPORT_SYMBOL_GPL(fetchdecode_rgb_constantcolor);
void fetchdecode_yuv_constantcolor(struct dpu_fetchdecode *fd, u8 y, u8 u, u8 v) void fetchdecode_yuv_constantcolor(struct dpu_fetchunit *fu, u8 y, u8 u, u8 v)
{ {
u32 val; u32 val;
val = yuv_color(y, u, v); val = yuv_color(y, u, v);
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
dpu_fd_write(fd, val, CONSTANTCOLOR0); dpu_fu_write(fu, val, CONSTANTCOLOR0);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchdecode_yuv_constantcolor); EXPORT_SYMBOL_GPL(fetchdecode_yuv_constantcolor);
void fetchdecode_controltrigger(struct dpu_fetchdecode *fd, bool trigger) static void fetchdecode_set_controltrigger(struct dpu_fetchunit *fu)
{ {
u32 val; mutex_lock(&fu->mutex);
dpu_fu_write(fu, SHDTOKGEN, CONTROLTRIGGER);
val = trigger ? SHDTOKGEN : 0; mutex_unlock(&fu->mutex);
mutex_lock(&fd->mutex);
dpu_fd_write(fd, val, CONTROLTRIGGER);
mutex_unlock(&fd->mutex);
} }
EXPORT_SYMBOL_GPL(fetchdecode_controltrigger);
int fetchdecode_fetchtype(struct dpu_fetchdecode *fd, fetchtype_t *type) int fetchdecode_fetchtype(struct dpu_fetchunit *fu, fetchtype_t *type)
{ {
struct dpu_soc *dpu = fd->dpu; struct dpu_soc *dpu = fu->dpu;
u32 val; u32 val;
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
val = dpu_fd_read(fd, FETCHTYPE); val = dpu_fu_read(fu, FETCHTYPE);
val &= FETCHTYPE_MASK; val &= FETCHTYPE_MASK;
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
switch (val) { switch (val) {
case FETCHTYPE__DECODE: case FETCHTYPE__DECODE:
dev_dbg(dpu->dev, "FetchDecode%d with RL and RLAD decoder\n", dev_dbg(dpu->dev, "FetchDecode%d with RL and RLAD decoder\n",
fd->id); fu->id);
break; break;
case FETCHTYPE__LAYER: case FETCHTYPE__LAYER:
dev_dbg(dpu->dev, "FetchDecode%d with fractional " dev_dbg(dpu->dev, "FetchDecode%d with fractional "
"plane(8 layers)\n", fd->id); "plane(8 layers)\n", fu->id);
break; break;
case FETCHTYPE__WARP: case FETCHTYPE__WARP:
dev_dbg(dpu->dev, "FetchDecode%d with arbitrary warping and " dev_dbg(dpu->dev, "FetchDecode%d with arbitrary warping and "
"fractional plane(8 layers)\n", fd->id); "fractional plane(8 layers)\n", fu->id);
break; break;
case FETCHTYPE__ECO: case FETCHTYPE__ECO:
dev_dbg(dpu->dev, "FetchDecode%d with minimum feature set for " dev_dbg(dpu->dev, "FetchDecode%d with minimum feature set for "
"alpha, chroma and coordinate planes\n", "alpha, chroma and coordinate planes\n",
fd->id); fu->id);
break; break;
case FETCHTYPE__PERSP: case FETCHTYPE__PERSP:
dev_dbg(dpu->dev, "FetchDecode%d with affine, perspective and " dev_dbg(dpu->dev, "FetchDecode%d with affine, perspective and "
"arbitrary warping\n", fd->id); "arbitrary warping\n", fu->id);
break; break;
case FETCHTYPE__ROT: case FETCHTYPE__ROT:
dev_dbg(dpu->dev, "FetchDecode%d with affine and arbitrary " dev_dbg(dpu->dev, "FetchDecode%d with affine and arbitrary "
"warping\n", fd->id); "warping\n", fu->id);
break; break;
case FETCHTYPE__DECODEL: case FETCHTYPE__DECODEL:
dev_dbg(dpu->dev, "FetchDecode%d with RL and RLAD decoder, " dev_dbg(dpu->dev, "FetchDecode%d with RL and RLAD decoder, "
"reduced feature set\n", fd->id); "reduced feature set\n", fu->id);
break; break;
case FETCHTYPE__LAYERL: case FETCHTYPE__LAYERL:
dev_dbg(dpu->dev, "FetchDecode%d with fractional " dev_dbg(dpu->dev, "FetchDecode%d with fractional "
"plane(8 layers), reduced feature set\n", "plane(8 layers), reduced feature set\n",
fd->id); fu->id);
break; break;
case FETCHTYPE__ROTL: case FETCHTYPE__ROTL:
dev_dbg(dpu->dev, "FetchDecode%d with affine and arbitrary " dev_dbg(dpu->dev, "FetchDecode%d with affine and arbitrary "
"warping, reduced feature set\n", fd->id); "warping, reduced feature set\n", fu->id);
break; break;
default: default:
dev_warn(dpu->dev, "Invalid fetch type %u for FetchDecode%d\n", dev_warn(dpu->dev, "Invalid fetch type %u for FetchDecode%d\n",
val, fd->id); val, fu->id);
return -EINVAL; return -EINVAL;
} }
@ -602,11 +493,11 @@ int fetchdecode_fetchtype(struct dpu_fetchdecode *fd, fetchtype_t *type)
} }
EXPORT_SYMBOL_GPL(fetchdecode_fetchtype); EXPORT_SYMBOL_GPL(fetchdecode_fetchtype);
shadow_load_req_t fetchdecode_to_shdldreq_t(struct dpu_fetchdecode *fd) shadow_load_req_t fetchdecode_to_shdldreq_t(struct dpu_fetchunit *fu)
{ {
shadow_load_req_t t = 0; shadow_load_req_t t = 0;
switch (fd->id) { switch (fu->id) {
case 0: case 0:
t = SHLDREQID_FETCHDECODE0; t = SHLDREQID_FETCHDECODE0;
break; break;
@ -627,28 +518,28 @@ shadow_load_req_t fetchdecode_to_shdldreq_t(struct dpu_fetchdecode *fd)
} }
EXPORT_SYMBOL_GPL(fetchdecode_to_shdldreq_t); EXPORT_SYMBOL_GPL(fetchdecode_to_shdldreq_t);
u32 fetchdecode_get_vproc_mask(struct dpu_fetchdecode *fd) u32 fetchdecode_get_vproc_mask(struct dpu_fetchunit *fu)
{ {
struct dpu_soc *dpu = fd->dpu; struct dpu_soc *dpu = fu->dpu;
const struct dpu_devtype *devtype = dpu->devtype; const struct dpu_devtype *devtype = dpu->devtype;
return devtype->version == DPU_V1 ? return devtype->version == DPU_V1 ?
fd_vproc_cap_v1[fd->id] : fd_vproc_cap_v2[fd->id]; fd_vproc_cap_v1[fu->id] : fd_vproc_cap_v2[fu->id];
} }
EXPORT_SYMBOL_GPL(fetchdecode_get_vproc_mask); EXPORT_SYMBOL_GPL(fetchdecode_get_vproc_mask);
struct dpu_fetcheco *fetchdecode_get_fetcheco(struct dpu_fetchdecode *fd) struct dpu_fetchunit *fetchdecode_get_fetcheco(struct dpu_fetchunit *fu)
{ {
struct dpu_soc *dpu = fd->dpu; struct dpu_soc *dpu = fu->dpu;
switch (fd->id) { switch (fu->id) {
case 0: case 0:
case 1: case 1:
return dpu->fe_priv[fd->id]; return dpu->fe_priv[fu->id];
case 2: case 2:
case 3: case 3:
/* TODO: for DPU v1, add FetchEco2 support */ /* TODO: for DPU v1, add FetchEco2 support */
return dpu->fe_priv[fd->id - 2]; return dpu->fe_priv[fu->id - 2];
default: default:
WARN_ON(1); WARN_ON(1);
} }
@ -657,9 +548,9 @@ struct dpu_fetcheco *fetchdecode_get_fetcheco(struct dpu_fetchdecode *fd)
} }
EXPORT_SYMBOL_GPL(fetchdecode_get_fetcheco); EXPORT_SYMBOL_GPL(fetchdecode_get_fetcheco);
bool fetchdecode_need_fetcheco(struct dpu_fetchdecode *fd, u32 fmt) bool fetchdecode_need_fetcheco(struct dpu_fetchunit *fu, u32 fmt)
{ {
struct dpu_fetcheco *fe = fetchdecode_get_fetcheco(fd); struct dpu_fetchunit *fe = fetchdecode_get_fetcheco(fu);
if (IS_ERR_OR_NULL(fe)) if (IS_ERR_OR_NULL(fe))
return false; return false;
@ -678,11 +569,11 @@ bool fetchdecode_need_fetcheco(struct dpu_fetchdecode *fd, u32 fmt)
} }
EXPORT_SYMBOL_GPL(fetchdecode_need_fetcheco); EXPORT_SYMBOL_GPL(fetchdecode_need_fetcheco);
struct dpu_hscaler *fetchdecode_get_hscaler(struct dpu_fetchdecode *fd) struct dpu_hscaler *fetchdecode_get_hscaler(struct dpu_fetchunit *fu)
{ {
struct dpu_soc *dpu = fd->dpu; struct dpu_soc *dpu = fu->dpu;
switch (fd->id) { switch (fu->id) {
case 0: case 0:
case 2: case 2:
return dpu->hs_priv[0]; return dpu->hs_priv[0];
@ -697,11 +588,11 @@ struct dpu_hscaler *fetchdecode_get_hscaler(struct dpu_fetchdecode *fd)
} }
EXPORT_SYMBOL_GPL(fetchdecode_get_hscaler); EXPORT_SYMBOL_GPL(fetchdecode_get_hscaler);
struct dpu_vscaler *fetchdecode_get_vscaler(struct dpu_fetchdecode *fd) struct dpu_vscaler *fetchdecode_get_vscaler(struct dpu_fetchunit *fu)
{ {
struct dpu_soc *dpu = fd->dpu; struct dpu_soc *dpu = fu->dpu;
switch (fd->id) { switch (fu->id) {
case 0: case 0:
case 2: case 2:
return dpu->vs_priv[0]; return dpu->vs_priv[0];
@ -716,168 +607,9 @@ struct dpu_vscaler *fetchdecode_get_vscaler(struct dpu_fetchdecode *fd)
} }
EXPORT_SYMBOL_GPL(fetchdecode_get_vscaler); EXPORT_SYMBOL_GPL(fetchdecode_get_vscaler);
unsigned int fetchdecode_get_stream_id(struct dpu_fetchdecode *fd) struct dpu_fetchunit *dpu_fd_get(struct dpu_soc *dpu, int id)
{ {
return fd->stream_id; struct dpu_fetchunit *fu;
}
EXPORT_SYMBOL_GPL(fetchdecode_get_stream_id);
void fetchdecode_set_stream_id(struct dpu_fetchdecode *fd, unsigned int id)
{
switch (id) {
case DPU_PLANE_SRC_TO_DISP_STREAM0:
case DPU_PLANE_SRC_TO_DISP_STREAM1:
case DPU_PLANE_SRC_DISABLED:
fd->stream_id = id;
break;
default:
WARN_ON(1);
}
}
EXPORT_SYMBOL_GPL(fetchdecode_set_stream_id);
void
fetchdecode_configure_prefetch(struct dpu_fetchdecode *fd,
unsigned int stream_id,
unsigned int width, unsigned int height,
unsigned int x_offset, unsigned int y_offset,
unsigned int stride, u32 format, u64 modifier,
unsigned long baddr, unsigned long uv_baddr,
bool start, bool aux_start,
bool fb_is_interlaced)
{
if (WARN_ON(!fd || !fd->dprc))
return;
dprc_configure(fd->dprc,
stream_id, width, height, x_offset, y_offset, stride,
format, modifier, baddr, uv_baddr, start, aux_start,
fb_is_interlaced);
}
EXPORT_SYMBOL_GPL(fetchdecode_configure_prefetch);
void fetchdecode_enable_prefetch(struct dpu_fetchdecode *fd)
{
if (WARN_ON(!fd || !fd->dprc))
return;
dprc_enable(fd->dprc);
}
EXPORT_SYMBOL_GPL(fetchdecode_enable_prefetch);
void fetchdecode_disable_prefetch(struct dpu_fetchdecode *fd)
{
if (WARN_ON(!fd || !fd->dprc))
return;
dprc_disable(fd->dprc);
}
EXPORT_SYMBOL_GPL(fetchdecode_disable_prefetch);
void fetchdecode_reg_update_prefetch(struct dpu_fetchdecode *fd)
{
if (WARN_ON(!fd || !fd->dprc))
return;
dprc_reg_update(fd->dprc);
}
EXPORT_SYMBOL_GPL(fetchdecode_reg_update_prefetch);
void fetchdecode_prefetch_first_frame_handle(struct dpu_fetchdecode *fd)
{
if (WARN_ON(!fd || !fd->dprc))
return;
dprc_first_frame_handle(fd->dprc);
}
EXPORT_SYMBOL_GPL(fetchdecode_prefetch_first_frame_handle);
void fetchdecode_prefetch_irq_handle(struct dpu_fetchdecode *fd)
{
if (WARN_ON(!fd || !fd->dprc))
return;
dprc_irq_handle(fd->dprc);
}
EXPORT_SYMBOL_GPL(fetchdecode_prefetch_irq_handle);
void fetchdecode_prefetch_enable_first_frame_irq(struct dpu_fetchdecode *fd)
{
if (WARN_ON(!fd || !fd->dprc))
return;
dprc_enable_ctrl_done_irq(fd->dprc);
}
EXPORT_SYMBOL_GPL(fetchdecode_prefetch_enable_first_frame_irq);
bool fetchdecode_has_prefetch(struct dpu_fetchdecode *fd)
{
return !!fd->dprc;
}
EXPORT_SYMBOL_GPL(fetchdecode_has_prefetch);
bool fetchdecode_prefetch_format_supported(struct dpu_fetchdecode *fd,
u32 format, u64 modifier)
{
if (WARN_ON(!fd || !fd->dprc))
return false;
return dprc_format_supported(fd->dprc, format, modifier);
}
EXPORT_SYMBOL_GPL(fetchdecode_prefetch_format_supported);
bool fetchdecode_prefetch_stride_supported(struct dpu_fetchdecode *fd,
unsigned int stride,
unsigned int uv_stride,
unsigned int width,
u32 format)
{
if (WARN_ON(!fd || !fd->dprc))
return false;
return dprc_stride_supported(fd->dprc,
stride, uv_stride, width, format);
}
EXPORT_SYMBOL_GPL(fetchdecode_prefetch_stride_supported);
bool fetchdecode_prefetch_stride_double_check(struct dpu_fetchdecode *fd,
unsigned int stride,
unsigned int uv_stride,
unsigned int width,
u32 format,
dma_addr_t baseaddr,
dma_addr_t uv_baseaddr)
{
if (WARN_ON(!fd || !fd->dprc))
return false;
return dprc_stride_double_check(fd->dprc,
stride, uv_stride, width, format,
baseaddr, uv_baseaddr);
}
EXPORT_SYMBOL_GPL(fetchdecode_prefetch_stride_double_check);
void fetchdecode_pin_off(struct dpu_fetchdecode *fd)
{
fd->pin_off = true;
}
EXPORT_SYMBOL_GPL(fetchdecode_pin_off);
void fetchdecode_unpin_off(struct dpu_fetchdecode *fd)
{
fd->pin_off = false;
}
EXPORT_SYMBOL_GPL(fetchdecode_unpin_off);
bool fetchdecode_is_pinned_off(struct dpu_fetchdecode *fd)
{
return fd->pin_off;
}
EXPORT_SYMBOL_GPL(fetchdecode_is_pinned_off);
struct dpu_fetchdecode *dpu_fd_get(struct dpu_soc *dpu, int id)
{
struct dpu_fetchdecode *fd;
int i; int i;
for (i = 0; i < ARRAY_SIZE(fd_ids); i++) for (i = 0; i < ARRAY_SIZE(fd_ids); i++)
@ -887,36 +619,55 @@ struct dpu_fetchdecode *dpu_fd_get(struct dpu_soc *dpu, int id)
if (i == ARRAY_SIZE(fd_ids)) if (i == ARRAY_SIZE(fd_ids))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
fd = dpu->fd_priv[i]; fu = dpu->fd_priv[i];
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
if (fd->inuse) { if (fu->inuse) {
fd = ERR_PTR(-EBUSY); fu = ERR_PTR(-EBUSY);
goto out; goto out;
} }
fd->inuse = true; fu->inuse = true;
out: out:
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
return fd; return fu;
} }
EXPORT_SYMBOL_GPL(dpu_fd_get); EXPORT_SYMBOL_GPL(dpu_fd_get);
void dpu_fd_put(struct dpu_fetchdecode *fd) void dpu_fd_put(struct dpu_fetchunit *fu)
{ {
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
fd->inuse = false; fu->inuse = false;
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(dpu_fd_put); EXPORT_SYMBOL_GPL(dpu_fd_put);
static const struct dpu_fetchunit_ops fd_ops = {
.set_burstlength = fetchunit_set_burstlength,
.set_baseaddress = fetchdecode_set_baseaddress,
.set_src_bpp = fetchdecode_set_src_bpp,
.set_src_stride = fetchdecode_set_src_stride,
.set_src_buf_dimensions = fetchdecode_set_src_buf_dimensions,
.set_fmt = fetchdecode_set_fmt,
.enable_src_buf = fetchdecode_enable_src_buf,
.disable_src_buf = fetchdecode_disable_src_buf,
.is_enabled = fetchdecode_is_enabled,
.set_framedimensions = fetchdecode_set_framedimensions,
.set_controltrigger = fetchdecode_set_controltrigger,
.get_stream_id = fetchunit_get_stream_id,
.set_stream_id = fetchunit_set_stream_id,
.pin_off = fetchunit_pin_off,
.unpin_off = fetchunit_unpin_off,
.is_pinned_off = fetchunit_is_pinned_off,
};
void _dpu_fd_init(struct dpu_soc *dpu, unsigned int id) void _dpu_fd_init(struct dpu_soc *dpu, unsigned int id)
{ {
struct dpu_fetchdecode *fd; struct dpu_fetchunit *fu;
int i; int i;
for (i = 0; i < ARRAY_SIZE(fd_ids); i++) for (i = 0; i < ARRAY_SIZE(fd_ids); i++)
@ -926,53 +677,58 @@ void _dpu_fd_init(struct dpu_soc *dpu, unsigned int id)
if (WARN_ON(i == ARRAY_SIZE(fd_ids))) if (WARN_ON(i == ARRAY_SIZE(fd_ids)))
return; return;
fd = dpu->fd_priv[i]; fu = dpu->fd_priv[i];
fetchdecode_pixengcfg_dynamic_src_sel(fd, FD_SRC_DISABLE); fetchdecode_pixengcfg_dynamic_src_sel(fu, FD_SRC_DISABLE);
fetchdecode_baddr_autoupdate(fd, 0x0); fetchunit_baddr_autoupdate(fu, 0x0);
fetchdecode_shden(fd, true); fetchunit_shden(fu, true);
mutex_lock(&fd->mutex); mutex_lock(&fu->mutex);
dpu_fd_write(fd, SETNUMBUFFERS(16) | SETBURSTLENGTH(16), dpu_fu_write(fu, SETNUMBUFFERS(16) | SETBURSTLENGTH(16),
BURSTBUFFERMANAGEMENT); BURSTBUFFERMANAGEMENT);
mutex_unlock(&fd->mutex); mutex_unlock(&fu->mutex);
} }
int dpu_fd_init(struct dpu_soc *dpu, unsigned int id, int dpu_fd_init(struct dpu_soc *dpu, unsigned int id,
unsigned long pec_base, unsigned long base) unsigned long pec_base, unsigned long base)
{ {
struct dpu_fetchdecode *fd; struct dpu_fetchdecode *fd;
struct dpu_fetchunit *fu;
int ret, i; int ret, i;
fd = devm_kzalloc(dpu->dev, sizeof(*fd), GFP_KERNEL); fd = devm_kzalloc(dpu->dev, sizeof(*fd), GFP_KERNEL);
if (!fd) if (!fd)
return -ENOMEM; return -ENOMEM;
dpu->fd_priv[id] = fd; fu = &fd->fu;
dpu->fd_priv[id] = fu;
fd->pec_base = devm_ioremap(dpu->dev, pec_base, SZ_16); fu->pec_base = devm_ioremap(dpu->dev, pec_base, SZ_16);
if (!fd->pec_base) if (!fu->pec_base)
return -ENOMEM; return -ENOMEM;
fd->base = devm_ioremap(dpu->dev, base, SZ_1K); fu->base = devm_ioremap(dpu->dev, base, SZ_1K);
if (!fd->base) if (!fu->base)
return -ENOMEM; return -ENOMEM;
fd->dpu = dpu; fu->dpu = dpu;
fd->id = id; fu->id = id;
fu->type = FU_T_FD;
fu->ops = &fd_ops;
fu->name = "fetchdecode";
for (i = 0; i < ARRAY_SIZE(fd_ids); i++) { for (i = 0; i < ARRAY_SIZE(fd_ids); i++) {
if (fd_ids[i] == id) { if (fd_ids[i] == id) {
fd->shdlreq = fd_shdlreqs[i]; fd->shdlreq = fd_shdlreqs[i];
break; break;
} }
} }
mutex_init(&fd->mutex); mutex_init(&fu->mutex);
ret = fetchdecode_pixengcfg_dynamic_src_sel(fd, FD_SRC_DISABLE); ret = fetchdecode_pixengcfg_dynamic_src_sel(fu, FD_SRC_DISABLE);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = fetchdecode_fetchtype(fd, &fd->fetchtype); ret = fetchdecode_fetchtype(fu, &fd->fetchtype);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -980,11 +736,3 @@ int dpu_fd_init(struct dpu_soc *dpu, unsigned int id,
return 0; return 0;
} }
void fetchdecode_get_dprc(struct dpu_fetchdecode *fd, void *data)
{
if (WARN_ON(!fd))
return;
fd->dprc = data;
}

View File

@ -40,146 +40,13 @@
#define HIDDENSTATUS 0x54 #define HIDDENSTATUS 0x54
struct dpu_fetcheco { struct dpu_fetcheco {
void __iomem *pec_base; struct dpu_fetchunit fu;
void __iomem *base;
struct mutex mutex;
int id;
bool inuse;
bool pin_off;
struct dpu_soc *dpu;
/* see DPU_PLANE_SRC_xxx */
unsigned int stream_id;
}; };
static inline u32 dpu_pec_fe_read(struct dpu_fetcheco *fe, unsigned int offset) static void
{ fetcheco_set_src_buf_dimensions(struct dpu_fetchunit *fu,
return readl(fe->pec_base + offset); unsigned int w, unsigned int h,
} u32 fmt, bool deinterlace)
static inline void dpu_pec_fe_write(struct dpu_fetcheco *fe, u32 value,
unsigned int offset)
{
writel(value, fe->pec_base + offset);
}
static inline u32 dpu_fe_read(struct dpu_fetcheco *fe, unsigned int offset)
{
return readl(fe->base + offset);
}
static inline void dpu_fe_write(struct dpu_fetcheco *fe, u32 value,
unsigned int offset)
{
writel(value, fe->base + offset);
}
void fetcheco_shden(struct dpu_fetcheco *fe, bool enable)
{
u32 val;
mutex_lock(&fe->mutex);
val = dpu_fe_read(fe, STATICCONTROL);
if (enable)
val |= SHDEN;
else
val &= ~SHDEN;
dpu_fe_write(fe, val, STATICCONTROL);
mutex_unlock(&fe->mutex);
}
EXPORT_SYMBOL_GPL(fetcheco_shden);
void fetcheco_set_burstlength(struct dpu_fetcheco *fe, dma_addr_t baddr,
bool use_prefetch)
{
struct dpu_soc *dpu = fe->dpu;
unsigned int burst_size, burst_length;
u32 val;
if (use_prefetch) {
/*
* address TKT343664:
* fetch unit base address has to align to burst size
*/
burst_size = 1 << (ffs(baddr) - 1);
burst_size = min(burst_size, 128U);
burst_length = burst_size / 8;
} else {
burst_length = 16;
}
mutex_lock(&fe->mutex);
val = dpu_fe_read(fe, BURSTBUFFERMANAGEMENT);
val &= ~SETBURSTLENGTH_MASK;
val |= SETBURSTLENGTH(burst_length);
dpu_fe_write(fe, val, BURSTBUFFERMANAGEMENT);
mutex_unlock(&fe->mutex);
dev_dbg(dpu->dev, "FetchEco%d burst length is %u\n",
fe->id, burst_length);
}
EXPORT_SYMBOL_GPL(fetcheco_set_burstlength);
void fetcheco_baseaddress(struct dpu_fetcheco *fe, dma_addr_t paddr)
{
mutex_lock(&fe->mutex);
dpu_fe_write(fe, paddr, BASEADDRESS0);
mutex_unlock(&fe->mutex);
}
EXPORT_SYMBOL_GPL(fetcheco_baseaddress);
void fetcheco_source_bpp(struct dpu_fetcheco *fe, int bpp)
{
u32 val;
mutex_lock(&fe->mutex);
val = dpu_fe_read(fe, SOURCEBUFFERATTRIBUTES0);
val &= ~0x3f0000;
val |= BITSPERPIXEL(bpp);
dpu_fe_write(fe, val, SOURCEBUFFERATTRIBUTES0);
mutex_unlock(&fe->mutex);
}
EXPORT_SYMBOL_GPL(fetcheco_source_bpp);
/*
* The arguments width and bpp are valid only when use_prefetch is true.
* Since the pixel format has to be NV12 or NV21 when use_prefetch is true,
* we assume width stands for how many UV we have in bytes for one line,
* while bpp should be 8bits for every U or V component.
*/
void fetcheco_source_stride(struct dpu_fetcheco *fe, unsigned int width,
int bpp, unsigned int stride,
dma_addr_t baddr, bool use_prefetch)
{
unsigned int burst_size;
u32 val;
if (use_prefetch) {
/*
* address TKT343664:
* fetch unit base address has to align to burst size
*/
burst_size = 1 << (ffs(baddr) - 1);
burst_size = min(burst_size, 128U);
stride = width * (bpp >> 3);
/*
* address TKT339017:
* fixup for burst size vs stride mismatch
*/
stride = round_up(stride, burst_size);
}
mutex_lock(&fe->mutex);
val = dpu_fe_read(fe, SOURCEBUFFERATTRIBUTES0);
val &= ~0xffff;
val |= STRIDE(stride);
dpu_fe_write(fe, val, SOURCEBUFFERATTRIBUTES0);
mutex_unlock(&fe->mutex);
}
EXPORT_SYMBOL_GPL(fetcheco_source_stride);
void fetcheco_src_buf_dimensions(struct dpu_fetcheco *fe, unsigned int w,
unsigned int h, u32 fmt, bool deinterlace)
{ {
int width, height; int width, height;
u32 val; u32 val;
@ -207,13 +74,12 @@ void fetcheco_src_buf_dimensions(struct dpu_fetcheco *fe, unsigned int w,
val = LINEWIDTH(width) | LINECOUNT(height); val = LINEWIDTH(width) | LINECOUNT(height);
mutex_lock(&fe->mutex); mutex_lock(&fu->mutex);
dpu_fe_write(fe, val, SOURCEBUFFERDIMENSION0); dpu_fu_write(fu, val, SOURCEBUFFERDIMENSION0);
mutex_unlock(&fe->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetcheco_src_buf_dimensions);
void fetcheco_set_fmt(struct dpu_fetcheco *fe, u32 fmt) static void fetcheco_set_fmt(struct dpu_fetchunit *fu, u32 fmt, bool unused)
{ {
u32 val, bits, shift; u32 val, bits, shift;
int i, hsub, vsub; int i, hsub, vsub;
@ -258,17 +124,17 @@ void fetcheco_set_fmt(struct dpu_fetcheco *fe, u32 fmt)
return; return;
} }
mutex_lock(&fe->mutex); mutex_lock(&fu->mutex);
val = dpu_fe_read(fe, FRAMERESAMPLING); val = dpu_fu_read(fu, FRAMERESAMPLING);
val &= ~(DELTAX_MASK | DELTAY_MASK); val &= ~(DELTAX_MASK | DELTAY_MASK);
val |= DELTAX(x) | DELTAY(y); val |= DELTAX(x) | DELTAY(y);
dpu_fe_write(fe, val, FRAMERESAMPLING); dpu_fu_write(fu, val, FRAMERESAMPLING);
val = dpu_fe_read(fe, CONTROL); val = dpu_fu_read(fu, CONTROL);
val &= ~RASTERMODE_MASK; val &= ~RASTERMODE_MASK;
val |= RASTERMODE(RASTERMODE__NORMAL); val |= RASTERMODE(RASTERMODE__NORMAL);
dpu_fe_write(fe, val, CONTROL); dpu_fu_write(fu, val, CONTROL);
mutex_unlock(&fe->mutex); mutex_unlock(&fu->mutex);
for (i = 0; i < ARRAY_SIZE(dpu_pixel_format_matrix); i++) { for (i = 0; i < ARRAY_SIZE(dpu_pixel_format_matrix); i++) {
if (dpu_pixel_format_matrix[i].pixel_format == fmt) { if (dpu_pixel_format_matrix[i].pixel_format == fmt) {
@ -278,95 +144,60 @@ void fetcheco_set_fmt(struct dpu_fetcheco *fe, u32 fmt)
bits &= ~Y_BITS_MASK; bits &= ~Y_BITS_MASK;
shift &= ~Y_SHIFT_MASK; shift &= ~Y_SHIFT_MASK;
mutex_lock(&fe->mutex); mutex_lock(&fu->mutex);
dpu_fe_write(fe, bits, COLORCOMPONENTBITS0); dpu_fu_write(fu, bits, COLORCOMPONENTBITS0);
dpu_fe_write(fe, shift, COLORCOMPONENTSHIFT0); dpu_fu_write(fu, shift, COLORCOMPONENTSHIFT0);
mutex_unlock(&fe->mutex); mutex_unlock(&fu->mutex);
return; return;
} }
} }
WARN_ON(1); WARN_ON(1);
} }
EXPORT_SYMBOL_GPL(fetcheco_set_fmt);
void fetcheco_layeroffset(struct dpu_fetcheco *fe, unsigned int x, void fetcheco_layeroffset(struct dpu_fetchunit *fu, unsigned int x,
unsigned int y) unsigned int y)
{ {
u32 val; u32 val;
val = LAYERXOFFSET(x) | LAYERYOFFSET(y); val = LAYERXOFFSET(x) | LAYERYOFFSET(y);
mutex_lock(&fe->mutex); mutex_lock(&fu->mutex);
dpu_fe_write(fe, val, LAYEROFFSET0); dpu_fu_write(fu, val, LAYEROFFSET0);
mutex_unlock(&fe->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetcheco_layeroffset); EXPORT_SYMBOL_GPL(fetcheco_layeroffset);
void fetcheco_clipoffset(struct dpu_fetcheco *fe, unsigned int x, void fetcheco_clipoffset(struct dpu_fetchunit *fu, unsigned int x,
unsigned int y) unsigned int y)
{ {
u32 val; u32 val;
val = CLIPWINDOWXOFFSET(x) | CLIPWINDOWYOFFSET(y); val = CLIPWINDOWXOFFSET(x) | CLIPWINDOWYOFFSET(y);
mutex_lock(&fe->mutex); mutex_lock(&fu->mutex);
dpu_fe_write(fe, val, CLIPWINDOWOFFSET0); dpu_fu_write(fu, val, CLIPWINDOWOFFSET0);
mutex_unlock(&fe->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetcheco_clipoffset); EXPORT_SYMBOL_GPL(fetcheco_clipoffset);
void fetcheco_clipdimensions(struct dpu_fetcheco *fe, unsigned int w, void fetcheco_clipdimensions(struct dpu_fetchunit *fu, unsigned int w,
unsigned int h) unsigned int h)
{ {
u32 val; u32 val;
val = CLIPWINDOWWIDTH(w) | CLIPWINDOWHEIGHT(h); val = CLIPWINDOWWIDTH(w) | CLIPWINDOWHEIGHT(h);
mutex_lock(&fe->mutex); mutex_lock(&fu->mutex);
dpu_fe_write(fe, val, CLIPWINDOWDIMENSIONS0); dpu_fu_write(fu, val, CLIPWINDOWDIMENSIONS0);
mutex_unlock(&fe->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetcheco_clipdimensions); EXPORT_SYMBOL_GPL(fetcheco_clipdimensions);
void fetcheco_source_buffer_enable(struct dpu_fetcheco *fe) static void
{ fetcheco_set_framedimensions(struct dpu_fetchunit *fu,
u32 val; unsigned int w, unsigned int h,
bool deinterlace)
mutex_lock(&fe->mutex);
val = dpu_fe_read(fe, LAYERPROPERTY0);
val |= SOURCEBUFFERENABLE;
dpu_fe_write(fe, val, LAYERPROPERTY0);
mutex_unlock(&fe->mutex);
}
EXPORT_SYMBOL_GPL(fetcheco_source_buffer_enable);
void fetcheco_source_buffer_disable(struct dpu_fetcheco *fe)
{
u32 val;
mutex_lock(&fe->mutex);
val = dpu_fe_read(fe, LAYERPROPERTY0);
val &= ~SOURCEBUFFERENABLE;
dpu_fe_write(fe, val, LAYERPROPERTY0);
mutex_unlock(&fe->mutex);
}
EXPORT_SYMBOL_GPL(fetcheco_source_buffer_disable);
bool fetcheco_is_enabled(struct dpu_fetcheco *fe)
{
u32 val;
mutex_lock(&fe->mutex);
val = dpu_fe_read(fe, LAYERPROPERTY0);
mutex_unlock(&fe->mutex);
return !!(val & SOURCEBUFFERENABLE);
}
EXPORT_SYMBOL_GPL(fetcheco_is_enabled);
void fetcheco_framedimensions(struct dpu_fetcheco *fe, unsigned int w,
unsigned int h, bool deinterlace)
{ {
u32 val; u32 val;
@ -375,90 +206,84 @@ void fetcheco_framedimensions(struct dpu_fetcheco *fe, unsigned int w,
val = FRAMEWIDTH(w) | FRAMEHEIGHT(h); val = FRAMEWIDTH(w) | FRAMEHEIGHT(h);
mutex_lock(&fe->mutex); mutex_lock(&fu->mutex);
dpu_fe_write(fe, val, FRAMEDIMENSIONS); dpu_fu_write(fu, val, FRAMEDIMENSIONS);
mutex_unlock(&fe->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetcheco_framedimensions);
void fetcheco_frameresampling(struct dpu_fetcheco *fe, unsigned int x, void fetcheco_frameresampling(struct dpu_fetchunit *fu, unsigned int x,
unsigned int y) unsigned int y)
{ {
u32 val; u32 val;
mutex_lock(&fe->mutex); mutex_lock(&fu->mutex);
val = dpu_fe_read(fe, FRAMERESAMPLING); val = dpu_fu_read(fu, FRAMERESAMPLING);
val &= ~(DELTAX_MASK | DELTAY_MASK); val &= ~(DELTAX_MASK | DELTAY_MASK);
val |= DELTAX(x) | DELTAY(y); val |= DELTAX(x) | DELTAY(y);
dpu_fe_write(fe, val, FRAMERESAMPLING); dpu_fu_write(fu, val, FRAMERESAMPLING);
mutex_unlock(&fe->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetcheco_frameresampling); EXPORT_SYMBOL_GPL(fetcheco_frameresampling);
void fetcheco_controltrigger(struct dpu_fetcheco *fe, bool trigger) static void fetcheco_set_controltrigger(struct dpu_fetchunit *fu)
{ {
u32 val; mutex_lock(&fu->mutex);
dpu_fu_write(fu, SHDTOKGEN, CONTROLTRIGGER);
val = trigger ? SHDTOKGEN : 0; mutex_unlock(&fu->mutex);
mutex_lock(&fe->mutex);
dpu_fe_write(fe, val, CONTROLTRIGGER);
mutex_unlock(&fe->mutex);
} }
EXPORT_SYMBOL_GPL(fetcheco_controltrigger);
int fetcheco_fetchtype(struct dpu_fetcheco *fe, fetchtype_t *type) int fetcheco_fetchtype(struct dpu_fetchunit *fu, fetchtype_t *type)
{ {
struct dpu_soc *dpu = fe->dpu; struct dpu_soc *dpu = fu->dpu;
u32 val; u32 val;
mutex_lock(&fe->mutex); mutex_lock(&fu->mutex);
val = dpu_fe_read(fe, FETCHTYPE); val = dpu_fu_read(fu, FETCHTYPE);
val &= FETCHTYPE_MASK; val &= FETCHTYPE_MASK;
mutex_unlock(&fe->mutex); mutex_unlock(&fu->mutex);
switch (val) { switch (val) {
case FETCHTYPE__DECODE: case FETCHTYPE__DECODE:
dev_dbg(dpu->dev, "FetchEco%d with RL and RLAD decoder\n", dev_dbg(dpu->dev, "FetchEco%d with RL and RLAD decoder\n",
fe->id); fu->id);
break; break;
case FETCHTYPE__LAYER: case FETCHTYPE__LAYER:
dev_dbg(dpu->dev, "FetchEco%d with fractional " dev_dbg(dpu->dev, "FetchEco%d with fractional "
"plane(8 layers)\n", fe->id); "plane(8 layers)\n", fu->id);
break; break;
case FETCHTYPE__WARP: case FETCHTYPE__WARP:
dev_dbg(dpu->dev, "FetchEco%d with arbitrary warping and " dev_dbg(dpu->dev, "FetchEco%d with arbitrary warping and "
"fractional plane(8 layers)\n", fe->id); "fractional plane(8 layers)\n", fu->id);
break; break;
case FETCHTYPE__ECO: case FETCHTYPE__ECO:
dev_dbg(dpu->dev, "FetchEco%d with minimum feature set for " dev_dbg(dpu->dev, "FetchEco%d with minimum feature set for "
"alpha, chroma and coordinate planes\n", "alpha, chroma and coordinate planes\n",
fe->id); fu->id);
break; break;
case FETCHTYPE__PERSP: case FETCHTYPE__PERSP:
dev_dbg(dpu->dev, "FetchEco%d with affine, perspective and " dev_dbg(dpu->dev, "FetchEco%d with affine, perspective and "
"arbitrary warping\n", fe->id); "arbitrary warping\n", fu->id);
break; break;
case FETCHTYPE__ROT: case FETCHTYPE__ROT:
dev_dbg(dpu->dev, "FetchEco%d with affine and arbitrary " dev_dbg(dpu->dev, "FetchEco%d with affine and arbitrary "
"warping\n", fe->id); "warping\n", fu->id);
break; break;
case FETCHTYPE__DECODEL: case FETCHTYPE__DECODEL:
dev_dbg(dpu->dev, "FetchEco%d with RL and RLAD decoder, " dev_dbg(dpu->dev, "FetchEco%d with RL and RLAD decoder, "
"reduced feature set\n", fe->id); "reduced feature set\n", fu->id);
break; break;
case FETCHTYPE__LAYERL: case FETCHTYPE__LAYERL:
dev_dbg(dpu->dev, "FetchEco%d with fractional " dev_dbg(dpu->dev, "FetchEco%d with fractional "
"plane(8 layers), reduced feature set\n", "plane(8 layers), reduced feature set\n",
fe->id); fu->id);
break; break;
case FETCHTYPE__ROTL: case FETCHTYPE__ROTL:
dev_dbg(dpu->dev, "FetchEco%d with affine and arbitrary " dev_dbg(dpu->dev, "FetchEco%d with affine and arbitrary "
"warping, reduced feature set\n", fe->id); "warping, reduced feature set\n", fu->id);
break; break;
default: default:
dev_warn(dpu->dev, "Invalid fetch type %u for FetchEco%d\n", dev_warn(dpu->dev, "Invalid fetch type %u for FetchEco%d\n",
val, fe->id); val, fu->id);
return -EINVAL; return -EINVAL;
} }
@ -467,9 +292,9 @@ int fetcheco_fetchtype(struct dpu_fetcheco *fe, fetchtype_t *type)
} }
EXPORT_SYMBOL_GPL(fetcheco_fetchtype); EXPORT_SYMBOL_GPL(fetcheco_fetchtype);
dpu_block_id_t fetcheco_get_block_id(struct dpu_fetcheco *fe) dpu_block_id_t fetcheco_get_block_id(struct dpu_fetchunit *fu)
{ {
switch (fe->id) { switch (fu->id) {
case 0: case 0:
return ID_FETCHECO0; return ID_FETCHECO0;
case 1: case 1:
@ -486,47 +311,9 @@ dpu_block_id_t fetcheco_get_block_id(struct dpu_fetcheco *fe)
} }
EXPORT_SYMBOL_GPL(fetcheco_get_block_id); EXPORT_SYMBOL_GPL(fetcheco_get_block_id);
unsigned int fetcheco_get_stream_id(struct dpu_fetcheco *fe) struct dpu_fetchunit *dpu_fe_get(struct dpu_soc *dpu, int id)
{ {
return fe->stream_id; struct dpu_fetchunit *fu;
}
EXPORT_SYMBOL_GPL(fetcheco_get_stream_id);
void fetcheco_set_stream_id(struct dpu_fetcheco *fe, unsigned int id)
{
switch (id) {
case DPU_PLANE_SRC_TO_DISP_STREAM0:
case DPU_PLANE_SRC_TO_DISP_STREAM1:
case DPU_PLANE_SRC_DISABLED:
fe->stream_id = id;
break;
default:
WARN_ON(1);
}
}
EXPORT_SYMBOL_GPL(fetcheco_set_stream_id);
void fetcheco_pin_off(struct dpu_fetcheco *fe)
{
fe->pin_off = true;
}
EXPORT_SYMBOL_GPL(fetcheco_pin_off);
void fetcheco_unpin_off(struct dpu_fetcheco *fe)
{
fe->pin_off = false;
}
EXPORT_SYMBOL_GPL(fetcheco_unpin_off);
bool fetcheco_is_pinned_off(struct dpu_fetcheco *fe)
{
return fe->pin_off;
}
EXPORT_SYMBOL_GPL(fetcheco_is_pinned_off);
struct dpu_fetcheco *dpu_fe_get(struct dpu_soc *dpu, int id)
{
struct dpu_fetcheco *fe;
int i; int i;
for (i = 0; i < ARRAY_SIZE(fe_ids); i++) for (i = 0; i < ARRAY_SIZE(fe_ids); i++)
@ -536,36 +323,55 @@ struct dpu_fetcheco *dpu_fe_get(struct dpu_soc *dpu, int id)
if (i == ARRAY_SIZE(fe_ids)) if (i == ARRAY_SIZE(fe_ids))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
fe = dpu->fe_priv[i]; fu = dpu->fe_priv[i];
mutex_lock(&fe->mutex); mutex_lock(&fu->mutex);
if (fe->inuse) { if (fu->inuse) {
fe = ERR_PTR(-EBUSY); fu = ERR_PTR(-EBUSY);
goto out; goto out;
} }
fe->inuse = true; fu->inuse = true;
out: out:
mutex_unlock(&fe->mutex); mutex_unlock(&fu->mutex);
return fe; return fu;
} }
EXPORT_SYMBOL_GPL(dpu_fe_get); EXPORT_SYMBOL_GPL(dpu_fe_get);
void dpu_fe_put(struct dpu_fetcheco *fe) void dpu_fe_put(struct dpu_fetchunit *fu)
{ {
mutex_lock(&fe->mutex); mutex_lock(&fu->mutex);
fe->inuse = false; fu->inuse = false;
mutex_unlock(&fe->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(dpu_fe_put); EXPORT_SYMBOL_GPL(dpu_fe_put);
static const struct dpu_fetchunit_ops fe_ops = {
.set_burstlength = fetchunit_set_burstlength,
.set_baseaddress = fetchunit_set_baseaddress,
.set_src_bpp = fetchunit_set_src_bpp,
.set_src_stride = fetchunit_set_src_stride,
.set_src_buf_dimensions = fetcheco_set_src_buf_dimensions,
.set_fmt = fetcheco_set_fmt,
.enable_src_buf = fetchunit_enable_src_buf,
.disable_src_buf = fetchunit_disable_src_buf,
.is_enabled = fetchunit_is_enabled,
.set_framedimensions = fetcheco_set_framedimensions,
.set_controltrigger = fetcheco_set_controltrigger,
.get_stream_id = fetchunit_get_stream_id,
.set_stream_id = fetchunit_set_stream_id,
.pin_off = fetchunit_pin_off,
.unpin_off = fetchunit_unpin_off,
.is_pinned_off = fetchunit_is_pinned_off,
};
void _dpu_fe_init(struct dpu_soc *dpu, unsigned int id) void _dpu_fe_init(struct dpu_soc *dpu, unsigned int id)
{ {
struct dpu_fetcheco *fe; struct dpu_fetchunit *fu;
int i; int i;
for (i = 0; i < ARRAY_SIZE(fe_ids); i++) for (i = 0; i < ARRAY_SIZE(fe_ids); i++)
@ -575,20 +381,21 @@ void _dpu_fe_init(struct dpu_soc *dpu, unsigned int id)
if (WARN_ON(i == ARRAY_SIZE(fe_ids))) if (WARN_ON(i == ARRAY_SIZE(fe_ids)))
return; return;
fe = dpu->fe_priv[i]; fu = dpu->fe_priv[i];
fetcheco_shden(fe, true); fetchunit_shden(fu, true);
mutex_lock(&fe->mutex); mutex_lock(&fu->mutex);
dpu_fe_write(fe, SETNUMBUFFERS(16) | SETBURSTLENGTH(16), dpu_fu_write(fu, SETNUMBUFFERS(16) | SETBURSTLENGTH(16),
BURSTBUFFERMANAGEMENT); BURSTBUFFERMANAGEMENT);
mutex_unlock(&fe->mutex); mutex_unlock(&fu->mutex);
} }
int dpu_fe_init(struct dpu_soc *dpu, unsigned int id, int dpu_fe_init(struct dpu_soc *dpu, unsigned int id,
unsigned long pec_base, unsigned long base) unsigned long pec_base, unsigned long base)
{ {
struct dpu_fetcheco *fe; struct dpu_fetcheco *fe;
struct dpu_fetchunit *fu;
int i; int i;
fe = devm_kzalloc(dpu->dev, sizeof(*fe), GFP_KERNEL); fe = devm_kzalloc(dpu->dev, sizeof(*fe), GFP_KERNEL);
@ -599,19 +406,24 @@ int dpu_fe_init(struct dpu_soc *dpu, unsigned int id,
if (fe_ids[i] == id) if (fe_ids[i] == id)
break; break;
dpu->fe_priv[i] = fe; fu = &fe->fu;
dpu->fe_priv[i] = fu;
fe->pec_base = devm_ioremap(dpu->dev, pec_base, SZ_16); fu->pec_base = devm_ioremap(dpu->dev, pec_base, SZ_16);
if (!fe->pec_base) if (!fu->pec_base)
return -ENOMEM; return -ENOMEM;
fe->base = devm_ioremap(dpu->dev, base, SZ_128); fu->base = devm_ioremap(dpu->dev, base, SZ_128);
if (!fe->base) if (!fu->base)
return -ENOMEM; return -ENOMEM;
fe->dpu = dpu; fu->dpu = dpu;
fe->id = id; fu->id = id;
mutex_init(&fe->mutex); fu->type = FU_T_FE;
fu->ops = &fe_ops;
fu->name = "fetcheco";
mutex_init(&fu->mutex);
_dpu_fe_init(dpu, id); _dpu_fe_init(dpu, id);

View File

@ -19,7 +19,6 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/types.h> #include <linux/types.h>
#include <video/dpu.h> #include <video/dpu.h>
#include <video/imx8-prefetch.h>
#include "dpu-prv.h" #include "dpu-prv.h"
#define PIXENGCFG_STATUS 0x8 #define PIXENGCFG_STATUS 0x8
@ -50,351 +49,150 @@ static const shadow_load_req_t fl_shdlreqs[] = {
}; };
struct dpu_fetchlayer { struct dpu_fetchlayer {
void __iomem *pec_base; struct dpu_fetchunit fu;
void __iomem *base;
struct mutex mutex;
int id;
bool inuse;
bool pin_off;
struct dpu_soc *dpu;
fetchtype_t fetchtype; fetchtype_t fetchtype;
shadow_load_req_t shdlreq; shadow_load_req_t shdlreq;
/* see DPU_PLANE_SRC_xxx */
unsigned int stream_id;
struct dprc *dprc;
}; };
static inline u32 dpu_fl_read(struct dpu_fetchlayer *fl, unsigned int offset) static void
{ fetchlayer_set_src_buf_dimensions(struct dpu_fetchunit *fu,
return readl(fl->base + offset); unsigned int w, unsigned int h,
} u32 unused1, bool unused2)
static inline void dpu_fl_write(struct dpu_fetchlayer *fl, u32 value,
unsigned int offset)
{
writel(value, fl->base + offset);
}
static inline u32 rgb_color(u8 r, u8 g, u8 b, u8 a)
{
return (r << 24) | (g << 16) | (b << 8) | a;
}
static inline u32 yuv_color(u8 y, u8 u, u8 v)
{
return (y << 24) | (u << 16) | (v << 8);
}
void fetchlayer_shden(struct dpu_fetchlayer *fl, bool enable)
{
u32 val;
mutex_lock(&fl->mutex);
val = dpu_fl_read(fl, STATICCONTROL);
if (enable)
val |= SHDEN;
else
val &= ~SHDEN;
dpu_fl_write(fl, val, STATICCONTROL);
mutex_unlock(&fl->mutex);
}
EXPORT_SYMBOL_GPL(fetchlayer_shden);
void fetchlayer_baddr_autoupdate(struct dpu_fetchlayer *fl, u8 layer_mask)
{
u32 val;
mutex_lock(&fl->mutex);
val = dpu_fl_read(fl, STATICCONTROL);
val &= ~BASEADDRESSAUTOUPDATE_MASK;
val |= BASEADDRESSAUTOUPDATE(layer_mask);
dpu_fl_write(fl, val, STATICCONTROL);
mutex_unlock(&fl->mutex);
}
EXPORT_SYMBOL_GPL(fetchlayer_baddr_autoupdate);
void fetchlayer_shdldreq_sticky(struct dpu_fetchlayer *fl, u8 layer_mask)
{
u32 val;
mutex_lock(&fl->mutex);
val = dpu_fl_read(fl, STATICCONTROL);
val &= ~SHDLDREQSTICKY_MASK;
val |= SHDLDREQSTICKY(layer_mask);
dpu_fl_write(fl, val, STATICCONTROL);
mutex_unlock(&fl->mutex);
}
EXPORT_SYMBOL_GPL(fetchlayer_shdldreq_sticky);
void fetchlayer_set_burstlength(struct dpu_fetchlayer *fl, dma_addr_t baddr,
bool use_prefetch)
{
struct dpu_soc *dpu = fl->dpu;
unsigned int burst_size, burst_length;
u32 val;
if (use_prefetch) {
/*
* address TKT343664:
* fetch unit base address has to align to burst size
*/
burst_size = 1 << (ffs(baddr) - 1);
burst_size = min(burst_size, 128U);
burst_length = burst_size / 8;
} else {
burst_length = 16;
}
mutex_lock(&fl->mutex);
val = dpu_fl_read(fl, BURSTBUFFERMANAGEMENT);
val &= ~SETBURSTLENGTH_MASK;
val |= SETBURSTLENGTH(burst_length);
dpu_fl_write(fl, val, BURSTBUFFERMANAGEMENT);
mutex_unlock(&fl->mutex);
dev_dbg(dpu->dev, "FetchLayer%d burst length is %u\n",
fl->id, burst_length);
}
EXPORT_SYMBOL_GPL(fetchlayer_set_burstlength);
void fetchlayer_baseaddress(struct dpu_fetchlayer *fl, unsigned int index,
dma_addr_t paddr)
{
mutex_lock(&fl->mutex);
dpu_fl_write(fl, paddr, BASEADDRESS(index));
mutex_unlock(&fl->mutex);
}
EXPORT_SYMBOL_GPL(fetchlayer_baseaddress);
void fetchlayer_source_bpp(struct dpu_fetchlayer *fl, unsigned int index,
int bpp)
{
u32 val;
mutex_lock(&fl->mutex);
val = dpu_fl_read(fl, SOURCEBUFFERATTRIBUTES(index));
val &= ~0x3f0000;
val |= BITSPERPIXEL(bpp);
dpu_fl_write(fl, val, SOURCEBUFFERATTRIBUTES(index));
mutex_unlock(&fl->mutex);
}
EXPORT_SYMBOL_GPL(fetchlayer_source_bpp);
void fetchlayer_source_stride(struct dpu_fetchlayer *fl, unsigned int index,
unsigned int width, int bpp, unsigned int stride,
dma_addr_t baddr, bool use_prefetch)
{
unsigned int burst_size;
u32 val;
if (use_prefetch) {
/*
* address TKT343664:
* fetch unit base address has to align to burst size
*/
burst_size = 1 << (ffs(baddr) - 1);
burst_size = min(burst_size, 128U);
stride = width * (bpp >> 3);
/*
* address TKT339017:
* fixup for burst size vs stride mismatch
*/
stride = round_up(stride, burst_size);
}
mutex_lock(&fl->mutex);
val = dpu_fl_read(fl, SOURCEBUFFERATTRIBUTES(index));
val &= ~0xffff;
val |= STRIDE(stride);
dpu_fl_write(fl, val, SOURCEBUFFERATTRIBUTES(index));
mutex_unlock(&fl->mutex);
}
EXPORT_SYMBOL_GPL(fetchlayer_source_stride);
void fetchlayer_src_buf_dimensions(struct dpu_fetchlayer *fl,
unsigned int index, unsigned int w,
unsigned int h)
{ {
u32 val; u32 val;
val = LINEWIDTH(w) | LINECOUNT(h); val = LINEWIDTH(w) | LINECOUNT(h);
mutex_lock(&fl->mutex); mutex_lock(&fu->mutex);
dpu_fl_write(fl, val, SOURCEBUFFERDIMENSION(index)); dpu_fu_write(fu, val, SOURCEBUFFERDIMENSION(fu->sub_id));
mutex_unlock(&fl->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchlayer_src_buf_dimensions);
void fetchlayer_set_fmt(struct dpu_fetchlayer *fl, unsigned int index, u32 fmt) static void fetchlayer_set_fmt(struct dpu_fetchunit *fu, u32 fmt, bool unused)
{ {
u32 val, bits, shift; u32 val, bits, shift;
int i; int i, sub_id = fu->sub_id;
mutex_lock(&fl->mutex); mutex_lock(&fu->mutex);
val = dpu_fl_read(fl, LAYERPROPERTY(index)); val = dpu_fu_read(fu, LAYERPROPERTY(sub_id));
val &= ~YUVCONVERSIONMODE_MASK; val &= ~YUVCONVERSIONMODE_MASK;
val |= YUVCONVERSIONMODE(YUVCONVERSIONMODE__OFF); val |= YUVCONVERSIONMODE(YUVCONVERSIONMODE__OFF);
dpu_fl_write(fl, val, LAYERPROPERTY(index)); dpu_fu_write(fu, val, LAYERPROPERTY(sub_id));
mutex_unlock(&fl->mutex); mutex_unlock(&fu->mutex);
for (i = 0; i < ARRAY_SIZE(dpu_pixel_format_matrix); i++) { for (i = 0; i < ARRAY_SIZE(dpu_pixel_format_matrix); i++) {
if (dpu_pixel_format_matrix[i].pixel_format == fmt) { if (dpu_pixel_format_matrix[i].pixel_format == fmt) {
bits = dpu_pixel_format_matrix[i].bits; bits = dpu_pixel_format_matrix[i].bits;
shift = dpu_pixel_format_matrix[i].shift; shift = dpu_pixel_format_matrix[i].shift;
mutex_lock(&fl->mutex); mutex_lock(&fu->mutex);
dpu_fl_write(fl, bits, COLORCOMPONENTBITS(index)); dpu_fu_write(fu, bits, COLORCOMPONENTBITS(sub_id));
dpu_fl_write(fl, shift, COLORCOMPONENTSHIFT(index)); dpu_fu_write(fu, shift, COLORCOMPONENTSHIFT(sub_id));
mutex_unlock(&fl->mutex); mutex_unlock(&fu->mutex);
return; return;
} }
} }
WARN_ON(1); WARN_ON(1);
} }
EXPORT_SYMBOL_GPL(fetchlayer_set_fmt);
void fetchlayer_source_buffer_enable(struct dpu_fetchlayer *fl, static void
unsigned int index) fetchlayer_set_framedimensions(struct dpu_fetchunit *fu, unsigned int w,
{ unsigned int h, bool unused)
u32 val;
mutex_lock(&fl->mutex);
val = dpu_fl_read(fl, LAYERPROPERTY(index));
val |= SOURCEBUFFERENABLE;
dpu_fl_write(fl, val, LAYERPROPERTY(index));
mutex_unlock(&fl->mutex);
}
EXPORT_SYMBOL_GPL(fetchlayer_source_buffer_enable);
void fetchlayer_source_buffer_disable(struct dpu_fetchlayer *fl,
unsigned int index)
{
u32 val;
mutex_lock(&fl->mutex);
val = dpu_fl_read(fl, LAYERPROPERTY(index));
val &= ~SOURCEBUFFERENABLE;
dpu_fl_write(fl, val, LAYERPROPERTY(index));
mutex_unlock(&fl->mutex);
}
EXPORT_SYMBOL_GPL(fetchlayer_source_buffer_disable);
bool fetchlayer_is_enabled(struct dpu_fetchlayer *fl, unsigned int index)
{
u32 val;
mutex_lock(&fl->mutex);
val = dpu_fl_read(fl, LAYERPROPERTY(index));
mutex_unlock(&fl->mutex);
return !!(val & SOURCEBUFFERENABLE);
}
EXPORT_SYMBOL_GPL(fetchlayer_is_enabled);
void fetchlayer_framedimensions(struct dpu_fetchlayer *fl, unsigned int w,
unsigned int h)
{ {
u32 val; u32 val;
val = FRAMEWIDTH(w) | FRAMEHEIGHT(h); val = FRAMEWIDTH(w) | FRAMEHEIGHT(h);
mutex_lock(&fl->mutex); mutex_lock(&fu->mutex);
dpu_fl_write(fl, val, FRAMEDIMENSIONS); dpu_fu_write(fu, val, FRAMEDIMENSIONS);
mutex_unlock(&fl->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchlayer_framedimensions);
void fetchlayer_rgb_constantcolor(struct dpu_fetchlayer *fl, void fetchlayer_rgb_constantcolor(struct dpu_fetchunit *fu,
u8 r, u8 g, u8 b, u8 a) u8 r, u8 g, u8 b, u8 a)
{ {
u32 val; u32 val;
val = rgb_color(r, g, b, a); val = rgb_color(r, g, b, a);
mutex_lock(&fl->mutex); mutex_lock(&fu->mutex);
dpu_fl_write(fl, val, CONSTANTCOLOR(fl->id)); dpu_fu_write(fu, val, CONSTANTCOLOR(fu->id));
mutex_unlock(&fl->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchlayer_rgb_constantcolor); EXPORT_SYMBOL_GPL(fetchlayer_rgb_constantcolor);
void fetchlayer_yuv_constantcolor(struct dpu_fetchlayer *fl, u8 y, u8 u, u8 v) void fetchlayer_yuv_constantcolor(struct dpu_fetchunit *fu, u8 y, u8 u, u8 v)
{ {
u32 val; u32 val;
val = yuv_color(y, u, v); val = yuv_color(y, u, v);
mutex_lock(&fl->mutex); mutex_lock(&fu->mutex);
dpu_fl_write(fl, val, CONSTANTCOLOR(fl->id)); dpu_fu_write(fu, val, CONSTANTCOLOR(fu->id));
mutex_unlock(&fl->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchlayer_yuv_constantcolor); EXPORT_SYMBOL_GPL(fetchlayer_yuv_constantcolor);
void fetchlayer_controltrigger(struct dpu_fetchlayer *fl, bool trigger) static void fetchlayer_set_controltrigger(struct dpu_fetchunit *fu)
{ {
u32 val; mutex_lock(&fu->mutex);
dpu_fu_write(fu, SHDTOKGEN, CONTROLTRIGGER);
val = trigger ? SHDTOKGEN : 0; mutex_unlock(&fu->mutex);
mutex_lock(&fl->mutex);
dpu_fl_write(fl, val, CONTROLTRIGGER);
mutex_unlock(&fl->mutex);
} }
EXPORT_SYMBOL_GPL(fetchlayer_controltrigger);
int fetchlayer_fetchtype(struct dpu_fetchlayer *fl, fetchtype_t *type) int fetchlayer_fetchtype(struct dpu_fetchunit *fu, fetchtype_t *type)
{ {
struct dpu_soc *dpu = fl->dpu; struct dpu_soc *dpu = fu->dpu;
u32 val; u32 val;
mutex_lock(&fl->mutex); mutex_lock(&fu->mutex);
val = dpu_fl_read(fl, FETCHTYPE); val = dpu_fu_read(fu, FETCHTYPE);
val &= FETCHTYPE_MASK; val &= FETCHTYPE_MASK;
mutex_unlock(&fl->mutex); mutex_unlock(&fu->mutex);
switch (val) { switch (val) {
case FETCHTYPE__DECODE: case FETCHTYPE__DECODE:
dev_dbg(dpu->dev, "FetchLayer%d with RL and RLAD decoder\n", dev_dbg(dpu->dev, "FetchLayer%d with RL and RLAD decoder\n",
fl->id); fu->id);
break; break;
case FETCHTYPE__LAYER: case FETCHTYPE__LAYER:
dev_dbg(dpu->dev, "FetchLayer%d with fractional " dev_dbg(dpu->dev, "FetchLayer%d with fractional "
"plane(8 layers)\n", fl->id); "plane(8 layers)\n", fu->id);
break; break;
case FETCHTYPE__WARP: case FETCHTYPE__WARP:
dev_dbg(dpu->dev, "FetchLayer%d with arbitrary warping and " dev_dbg(dpu->dev, "FetchLayer%d with arbitrary warping and "
"fractional plane(8 layers)\n", fl->id); "fractional plane(8 layers)\n", fu->id);
break; break;
case FETCHTYPE__ECO: case FETCHTYPE__ECO:
dev_dbg(dpu->dev, "FetchLayer%d with minimum feature set for " dev_dbg(dpu->dev, "FetchLayer%d with minimum feature set for "
"alpha, chroma and coordinate planes\n", "alpha, chroma and coordinate planes\n",
fl->id); fu->id);
break; break;
case FETCHTYPE__PERSP: case FETCHTYPE__PERSP:
dev_dbg(dpu->dev, "FetchLayer%d with affine, perspective and " dev_dbg(dpu->dev, "FetchLayer%d with affine, perspective and "
"arbitrary warping\n", fl->id); "arbitrary warping\n", fu->id);
break; break;
case FETCHTYPE__ROT: case FETCHTYPE__ROT:
dev_dbg(dpu->dev, "FetchLayer%d with affine and arbitrary " dev_dbg(dpu->dev, "FetchLayer%d with affine and arbitrary "
"warping\n", fl->id); "warping\n", fu->id);
break; break;
case FETCHTYPE__DECODEL: case FETCHTYPE__DECODEL:
dev_dbg(dpu->dev, "FetchLayer%d with RL and RLAD decoder, " dev_dbg(dpu->dev, "FetchLayer%d with RL and RLAD decoder, "
"reduced feature set\n", fl->id); "reduced feature set\n", fu->id);
break; break;
case FETCHTYPE__LAYERL: case FETCHTYPE__LAYERL:
dev_dbg(dpu->dev, "FetchLayer%d with fractional " dev_dbg(dpu->dev, "FetchLayer%d with fractional "
"plane(8 layers), reduced feature set\n", "plane(8 layers), reduced feature set\n",
fl->id); fu->id);
break; break;
case FETCHTYPE__ROTL: case FETCHTYPE__ROTL:
dev_dbg(dpu->dev, "FetchLayer%d with affine and arbitrary " dev_dbg(dpu->dev, "FetchLayer%d with affine and arbitrary "
"warping, reduced feature set\n", fl->id); "warping, reduced feature set\n", fu->id);
break; break;
default: default:
dev_warn(dpu->dev, "Invalid fetch type %u for FetchLayer%d\n", dev_warn(dpu->dev, "Invalid fetch type %u for FetchLayer%d\n",
val, fl->id); val, fu->id);
return -EINVAL; return -EINVAL;
} }
@ -403,159 +201,9 @@ int fetchlayer_fetchtype(struct dpu_fetchlayer *fl, fetchtype_t *type)
} }
EXPORT_SYMBOL_GPL(fetchlayer_fetchtype); EXPORT_SYMBOL_GPL(fetchlayer_fetchtype);
unsigned int fetchlayer_get_stream_id(struct dpu_fetchlayer *fl) struct dpu_fetchunit *dpu_fl_get(struct dpu_soc *dpu, int id)
{ {
return fl->stream_id; struct dpu_fetchunit *fu;
}
EXPORT_SYMBOL_GPL(fetchlayer_get_stream_id);
void fetchlayer_set_stream_id(struct dpu_fetchlayer *fl, unsigned int id)
{
switch (id) {
case DPU_PLANE_SRC_TO_DISP_STREAM0:
case DPU_PLANE_SRC_TO_DISP_STREAM1:
case DPU_PLANE_SRC_DISABLED:
fl->stream_id = id;
break;
default:
WARN_ON(1);
}
}
EXPORT_SYMBOL_GPL(fetchlayer_set_stream_id);
void
fetchlayer_configure_prefetch(struct dpu_fetchlayer *fl, unsigned int stream_id,
unsigned int width, unsigned int height,
unsigned int x_offset, unsigned int y_offset,
unsigned int stride, u32 format, u64 modifier,
unsigned long baddr, bool start)
{
if (WARN_ON(!fl || !fl->dprc))
return;
dprc_configure(fl->dprc,
stream_id, width, height, x_offset, y_offset, stride,
format, modifier, baddr, 0, start, false, false);
}
EXPORT_SYMBOL_GPL(fetchlayer_configure_prefetch);
void fetchlayer_enable_prefetch(struct dpu_fetchlayer *fl)
{
if (WARN_ON(!fl || !fl->dprc))
return;
dprc_enable(fl->dprc);
}
EXPORT_SYMBOL_GPL(fetchlayer_enable_prefetch);
void fetchlayer_disable_prefetch(struct dpu_fetchlayer *fl)
{
if (WARN_ON(!fl || !fl->dprc))
return;
dprc_disable(fl->dprc);
}
EXPORT_SYMBOL_GPL(fetchlayer_disable_prefetch);
void fetchlayer_reg_update_prefetch(struct dpu_fetchlayer *fl)
{
if (WARN_ON(!fl || !fl->dprc))
return;
dprc_reg_update(fl->dprc);
}
EXPORT_SYMBOL_GPL(fetchlayer_reg_update_prefetch);
void fetchlayer_prefetch_first_frame_handle(struct dpu_fetchlayer *fl)
{
if (WARN_ON(!fl || !fl->dprc))
return;
dprc_first_frame_handle(fl->dprc);
}
EXPORT_SYMBOL_GPL(fetchlayer_prefetch_first_frame_handle);
void fetchlayer_prefetch_irq_handle(struct dpu_fetchlayer *fl)
{
if (WARN_ON(!fl || !fl->dprc))
return;
dprc_irq_handle(fl->dprc);
}
EXPORT_SYMBOL_GPL(fetchlayer_prefetch_irq_handle);
void fetchlayer_prefetch_enable_first_frame_irq(struct dpu_fetchlayer *fl)
{
if (WARN_ON(!fl || !fl->dprc))
return;
dprc_enable_ctrl_done_irq(fl->dprc);
}
EXPORT_SYMBOL_GPL(fetchlayer_prefetch_enable_first_frame_irq);
bool fetchlayer_has_prefetch(struct dpu_fetchlayer *fl)
{
return !!fl->dprc;
}
EXPORT_SYMBOL_GPL(fetchlayer_has_prefetch);
bool fetchlayer_prefetch_format_supported(struct dpu_fetchlayer *fl,
u32 format, u64 modifier)
{
if (WARN_ON(!fl || !fl->dprc))
return false;
return dprc_format_supported(fl->dprc, format, modifier);
}
EXPORT_SYMBOL_GPL(fetchlayer_prefetch_format_supported);
bool fetchlayer_prefetch_stride_supported(struct dpu_fetchlayer *fl,
unsigned int stride,
unsigned int width,
u32 format)
{
if (WARN_ON(!fl || !fl->dprc))
return false;
return dprc_stride_supported(fl->dprc, stride, 0, width, format);
}
EXPORT_SYMBOL_GPL(fetchlayer_prefetch_stride_supported);
bool fetchlayer_prefetch_stride_double_check(struct dpu_fetchlayer *fl,
unsigned int stride,
unsigned int width,
u32 format,
dma_addr_t baseaddr)
{
if (WARN_ON(!fl || !fl->dprc))
return false;
return dprc_stride_double_check(fl->dprc, stride, 0, width, format,
baseaddr, 0);
}
EXPORT_SYMBOL_GPL(fetchlayer_prefetch_stride_double_check);
void fetchlayer_pin_off(struct dpu_fetchlayer *fl)
{
fl->pin_off = true;
}
EXPORT_SYMBOL_GPL(fetchlayer_pin_off);
void fetchlayer_unpin_off(struct dpu_fetchlayer *fl)
{
fl->pin_off = false;
}
EXPORT_SYMBOL_GPL(fetchlayer_unpin_off);
bool fetchlayer_is_pinned_off(struct dpu_fetchlayer *fl)
{
return fl->pin_off;
}
EXPORT_SYMBOL_GPL(fetchlayer_is_pinned_off);
struct dpu_fetchlayer *dpu_fl_get(struct dpu_soc *dpu, int id)
{
struct dpu_fetchlayer *fl;
int i; int i;
for (i = 0; i < ARRAY_SIZE(fl_ids); i++) for (i = 0; i < ARRAY_SIZE(fl_ids); i++)
@ -565,36 +213,55 @@ struct dpu_fetchlayer *dpu_fl_get(struct dpu_soc *dpu, int id)
if (i == ARRAY_SIZE(fl_ids)) if (i == ARRAY_SIZE(fl_ids))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
fl = dpu->fl_priv[i]; fu = dpu->fl_priv[i];
mutex_lock(&fl->mutex); mutex_lock(&fu->mutex);
if (fl->inuse) { if (fu->inuse) {
fl = ERR_PTR(-EBUSY); fu = ERR_PTR(-EBUSY);
goto out; goto out;
} }
fl->inuse = true; fu->inuse = true;
out: out:
mutex_unlock(&fl->mutex); mutex_unlock(&fu->mutex);
return fl; return fu;
} }
EXPORT_SYMBOL_GPL(dpu_fl_get); EXPORT_SYMBOL_GPL(dpu_fl_get);
void dpu_fl_put(struct dpu_fetchlayer *fl) void dpu_fl_put(struct dpu_fetchunit *fu)
{ {
mutex_lock(&fl->mutex); mutex_lock(&fu->mutex);
fl->inuse = false; fu->inuse = false;
mutex_unlock(&fl->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(dpu_fl_put); EXPORT_SYMBOL_GPL(dpu_fl_put);
static const struct dpu_fetchunit_ops fl_ops = {
.set_burstlength = fetchunit_set_burstlength,
.set_baseaddress = fetchunit_set_baseaddress,
.set_src_bpp = fetchunit_set_src_bpp,
.set_src_stride = fetchunit_set_src_stride,
.set_src_buf_dimensions = fetchlayer_set_src_buf_dimensions,
.set_fmt = fetchlayer_set_fmt,
.enable_src_buf = fetchunit_enable_src_buf,
.disable_src_buf = fetchunit_disable_src_buf,
.is_enabled = fetchunit_is_enabled,
.set_framedimensions = fetchlayer_set_framedimensions,
.set_controltrigger = fetchlayer_set_controltrigger,
.get_stream_id = fetchunit_get_stream_id,
.set_stream_id = fetchunit_set_stream_id,
.pin_off = fetchunit_pin_off,
.unpin_off = fetchunit_unpin_off,
.is_pinned_off = fetchunit_is_pinned_off,
};
void _dpu_fl_init(struct dpu_soc *dpu, unsigned int id) void _dpu_fl_init(struct dpu_soc *dpu, unsigned int id)
{ {
struct dpu_fetchlayer *fl; struct dpu_fetchunit *fu;
int i; int i;
for (i = 0; i < ARRAY_SIZE(fl_ids); i++) for (i = 0; i < ARRAY_SIZE(fl_ids); i++)
@ -604,51 +271,56 @@ void _dpu_fl_init(struct dpu_soc *dpu, unsigned int id)
if (WARN_ON(i == ARRAY_SIZE(fl_ids))) if (WARN_ON(i == ARRAY_SIZE(fl_ids)))
return; return;
fl = dpu->fl_priv[i]; fu = dpu->fl_priv[i];
fetchlayer_baddr_autoupdate(fl, 0x0); fetchunit_baddr_autoupdate(fu, 0x0);
fetchlayer_shden(fl, true); fetchunit_shden(fu, true);
fetchlayer_shdldreq_sticky(fl, 0xFF); fetchunit_shdldreq_sticky(fu, 0xFF);
for (i = 0; i < DPU_FRAC_PLANE_LAYER_NUM; i++) fetchunit_disable_src_buf(fu);
fetchlayer_source_buffer_disable(fl, i);
mutex_lock(&fl->mutex); mutex_lock(&fu->mutex);
dpu_fl_write(fl, SETNUMBUFFERS(16) | SETBURSTLENGTH(16), dpu_fu_write(fu, SETNUMBUFFERS(16) | SETBURSTLENGTH(16),
BURSTBUFFERMANAGEMENT); BURSTBUFFERMANAGEMENT);
mutex_unlock(&fl->mutex); mutex_unlock(&fu->mutex);
} }
int dpu_fl_init(struct dpu_soc *dpu, unsigned int id, int dpu_fl_init(struct dpu_soc *dpu, unsigned int id,
unsigned long pec_base, unsigned long base) unsigned long pec_base, unsigned long base)
{ {
struct dpu_fetchlayer *fl; struct dpu_fetchlayer *fl;
struct dpu_fetchunit *fu;
int ret, i; int ret, i;
fl = devm_kzalloc(dpu->dev, sizeof(*fl), GFP_KERNEL); fl = devm_kzalloc(dpu->dev, sizeof(*fl), GFP_KERNEL);
if (!fl) if (!fl)
return -ENOMEM; return -ENOMEM;
dpu->fl_priv[id] = fl; fu = &fl->fu;
dpu->fl_priv[id] = fu;
fl->pec_base = devm_ioremap(dpu->dev, base, SZ_16); fu->pec_base = devm_ioremap(dpu->dev, base, SZ_16);
if (!fl->pec_base) if (!fu->pec_base)
return -ENOMEM; return -ENOMEM;
fl->base = devm_ioremap(dpu->dev, base, SZ_512); fu->base = devm_ioremap(dpu->dev, base, SZ_512);
if (!fl->base) if (!fu->base)
return -ENOMEM; return -ENOMEM;
fl->dpu = dpu; fu->dpu = dpu;
fl->id = id; fu->id = id;
fu->sub_id = 0;
fu->type = FU_T_FL;
fu->ops = &fl_ops;
fu->name = "fetchlayer";
for (i = 0; i < ARRAY_SIZE(fl_ids); i++) { for (i = 0; i < ARRAY_SIZE(fl_ids); i++) {
if (fl_ids[i] == id) { if (fl_ids[i] == id) {
fl->shdlreq = fl_shdlreqs[i]; fl->shdlreq = fl_shdlreqs[i];
break; break;
} }
} }
mutex_init(&fl->mutex); mutex_init(&fu->mutex);
ret = fetchlayer_fetchtype(fl, &fl->fetchtype); ret = fetchlayer_fetchtype(fu, &fl->fetchtype);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -656,11 +328,3 @@ int dpu_fl_init(struct dpu_soc *dpu, unsigned int id,
return 0; return 0;
} }
void fetchlayer_get_dprc(struct dpu_fetchlayer *fl, void *data)
{
if (WARN_ON(!fl))
return;
fl->dprc = data;
}

View File

@ -0,0 +1,292 @@
/*
* Copyright 2018 NXP
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <video/dpu.h>
#include "dpu-prv.h"
#define BASEADDRESS(n) (0x10 + (n) * 0x28)
#define SOURCEBUFFERATTRIBUTES(n) (0x14 + (n) * 0x28)
#define SOURCEBUFFERDIMENSION(n) (0x18 + (n) * 0x28)
#define COLORCOMPONENTBITS(n) (0x1C + (n) * 0x28)
#define COLORCOMPONENTSHIFT(n) (0x20 + (n) * 0x28)
#define LAYEROFFSET(n) (0x24 + (n) * 0x28)
#define CLIPWINDOWOFFSET(n) (0x28 + (n) * 0x28)
#define CLIPWINDOWDIMENSIONS(n) (0x2C + (n) * 0x28)
#define CONSTANTCOLOR(n) (0x30 + (n) * 0x28)
#define LAYERPROPERTY(n) (0x34 + (n) * 0x28)
void fetchunit_get_dprc(struct dpu_fetchunit *fu, void *data)
{
if (WARN_ON(!fu))
return;
fu->dprc = data;
}
EXPORT_SYMBOL_GPL(fetchunit_get_dprc);
void fetchunit_shden(struct dpu_fetchunit *fu, bool enable)
{
u32 val;
mutex_lock(&fu->mutex);
val = dpu_fu_read(fu, STATICCONTROL);
if (enable)
val |= SHDEN;
else
val &= ~SHDEN;
dpu_fu_write(fu, val, STATICCONTROL);
mutex_unlock(&fu->mutex);
}
EXPORT_SYMBOL_GPL(fetchunit_shden);
void fetchunit_baddr_autoupdate(struct dpu_fetchunit *fu, u8 layer_mask)
{
u32 val;
mutex_lock(&fu->mutex);
val = dpu_fu_read(fu, STATICCONTROL);
val &= ~BASEADDRESSAUTOUPDATE_MASK;
val |= BASEADDRESSAUTOUPDATE(layer_mask);
dpu_fu_write(fu, val, STATICCONTROL);
mutex_unlock(&fu->mutex);
}
EXPORT_SYMBOL_GPL(fetchunit_baddr_autoupdate);
void fetchunit_shdldreq_sticky(struct dpu_fetchunit *fu, u8 layer_mask)
{
u32 val;
mutex_lock(&fu->mutex);
val = dpu_fu_read(fu, STATICCONTROL);
val &= ~SHDLDREQSTICKY_MASK;
val |= SHDLDREQSTICKY(layer_mask);
dpu_fu_write(fu, val, STATICCONTROL);
mutex_unlock(&fu->mutex);
}
EXPORT_SYMBOL_GPL(fetchunit_shdldreq_sticky);
void fetchunit_set_burstlength(struct dpu_fetchunit *fu, dma_addr_t baddr,
bool use_prefetch)
{
struct dpu_soc *dpu = fu->dpu;
unsigned int burst_size, burst_length;
u32 val;
if (use_prefetch) {
/*
* address TKT343664:
* fetch unit base address has to align to burst size
*/
burst_size = 1 << (ffs(baddr) - 1);
burst_size = min(burst_size, 128U);
burst_length = burst_size / 8;
} else {
burst_length = 16;
}
mutex_lock(&fu->mutex);
val = dpu_fu_read(fu, BURSTBUFFERMANAGEMENT);
val &= ~SETBURSTLENGTH_MASK;
val |= SETBURSTLENGTH(burst_length);
dpu_fu_write(fu, val, BURSTBUFFERMANAGEMENT);
mutex_unlock(&fu->mutex);
dev_dbg(dpu->dev, "%s%d burst length is %u\n",
fu->name, fu->id, burst_length);
}
EXPORT_SYMBOL_GPL(fetchunit_set_burstlength);
void fetchunit_set_baseaddress(struct dpu_fetchunit *fu, dma_addr_t paddr)
{
mutex_lock(&fu->mutex);
dpu_fu_write(fu, paddr, BASEADDRESS(fu->sub_id));
mutex_unlock(&fu->mutex);
}
EXPORT_SYMBOL_GPL(fetchunit_set_baseaddress);
void fetchunit_set_src_bpp(struct dpu_fetchunit *fu, int bpp)
{
u32 val;
mutex_lock(&fu->mutex);
val = dpu_fu_read(fu, SOURCEBUFFERATTRIBUTES(fu->sub_id));
val &= ~0x3f0000;
val |= BITSPERPIXEL(bpp);
dpu_fu_write(fu, val, SOURCEBUFFERATTRIBUTES(fu->sub_id));
mutex_unlock(&fu->mutex);
}
EXPORT_SYMBOL_GPL(fetchunit_set_src_bpp);
/*
* The arguments width and bpp are valid only when use_prefetch is true.
* For fetcheco, since the pixel format has to be NV12 or NV21 when
* use_prefetch is true, we assume width stands for how many UV we have
* in bytes for one line, while bpp should be 8bits for every U or V component.
*/
void fetchunit_set_src_stride(struct dpu_fetchunit *fu,
unsigned int width, int bpp, unsigned int stride,
dma_addr_t baddr, bool use_prefetch)
{
unsigned int burst_size;
u32 val;
if (use_prefetch) {
/*
* address TKT343664:
* fetch unit base address has to align to burst size
*/
burst_size = 1 << (ffs(baddr) - 1);
burst_size = min(burst_size, 128U);
stride = width * (bpp >> 3);
/*
* address TKT339017:
* fixup for burst size vs stride mismatch
*/
stride = round_up(stride, burst_size);
}
mutex_lock(&fu->mutex);
val = dpu_fu_read(fu, SOURCEBUFFERATTRIBUTES(fu->sub_id));
val &= ~0xffff;
val |= STRIDE(stride);
dpu_fu_write(fu, val, SOURCEBUFFERATTRIBUTES(fu->sub_id));
mutex_unlock(&fu->mutex);
}
EXPORT_SYMBOL_GPL(fetchunit_set_src_stride);
void fetchunit_enable_src_buf(struct dpu_fetchunit *fu)
{
u32 val;
mutex_lock(&fu->mutex);
val = dpu_fu_read(fu, LAYERPROPERTY(fu->sub_id));
val |= SOURCEBUFFERENABLE;
dpu_fu_write(fu, val, LAYERPROPERTY(fu->sub_id));
mutex_unlock(&fu->mutex);
}
EXPORT_SYMBOL_GPL(fetchunit_enable_src_buf);
void fetchunit_disable_src_buf(struct dpu_fetchunit *fu)
{
u32 val;
mutex_lock(&fu->mutex);
val = dpu_fu_read(fu, LAYERPROPERTY(fu->sub_id));
val &= ~SOURCEBUFFERENABLE;
dpu_fu_write(fu, val, LAYERPROPERTY(fu->sub_id));
mutex_unlock(&fu->mutex);
}
EXPORT_SYMBOL_GPL(fetchunit_disable_src_buf);
bool fetchunit_is_enabled(struct dpu_fetchunit *fu)
{
u32 val;
mutex_lock(&fu->mutex);
val = dpu_fu_read(fu, LAYERPROPERTY(fu->sub_id));
mutex_unlock(&fu->mutex);
return !!(val & SOURCEBUFFERENABLE);
}
EXPORT_SYMBOL_GPL(fetchunit_is_enabled);
unsigned int fetchunit_get_stream_id(struct dpu_fetchunit *fu)
{
if (WARN_ON(!fu))
return DPU_PLANE_SRC_DISABLED;
return fu->stream_id;
}
EXPORT_SYMBOL_GPL(fetchunit_get_stream_id);
void fetchunit_set_stream_id(struct dpu_fetchunit *fu, unsigned int id)
{
if (WARN_ON(!fu))
return;
switch (id) {
case DPU_PLANE_SRC_TO_DISP_STREAM0:
case DPU_PLANE_SRC_TO_DISP_STREAM1:
case DPU_PLANE_SRC_DISABLED:
fu->stream_id = id;
break;
default:
WARN_ON(1);
}
}
EXPORT_SYMBOL_GPL(fetchunit_set_stream_id);
void fetchunit_pin_off(struct dpu_fetchunit *fu)
{
if (WARN_ON(!fu))
return;
fu->pin_off = true;
}
EXPORT_SYMBOL_GPL(fetchunit_pin_off);
void fetchunit_unpin_off(struct dpu_fetchunit *fu)
{
if (WARN_ON(!fu))
return;
fu->pin_off = false;
}
EXPORT_SYMBOL_GPL(fetchunit_unpin_off);
bool fetchunit_is_pinned_off(struct dpu_fetchunit *fu)
{
if (WARN_ON(!fu))
return false;
return fu->pin_off;
}
EXPORT_SYMBOL_GPL(fetchunit_is_pinned_off);
bool fetchunit_is_fetchdecode(struct dpu_fetchunit *fu)
{
if (WARN_ON(!fu))
return false;
return fu->type == FU_T_FD;
}
EXPORT_SYMBOL_GPL(fetchunit_is_fetchdecode);
bool fetchunit_is_fetcheco(struct dpu_fetchunit *fu)
{
if (WARN_ON(!fu))
return false;
return fu->type == FU_T_FE;
}
EXPORT_SYMBOL_GPL(fetchunit_is_fetcheco);
bool fetchunit_is_fetchlayer(struct dpu_fetchunit *fu)
{
if (WARN_ON(!fu))
return false;
return fu->type == FU_T_FL;
}
EXPORT_SYMBOL_GPL(fetchunit_is_fetchlayer);
bool fetchunit_is_fetchwarp(struct dpu_fetchunit *fu)
{
if (WARN_ON(!fu))
return false;
return fu->type == FU_T_FW;
}
EXPORT_SYMBOL_GPL(fetchunit_is_fetchwarp);

View File

@ -18,7 +18,6 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/types.h> #include <linux/types.h>
#include <video/dpu.h> #include <video/dpu.h>
#include <video/imx8-prefetch.h>
#include "dpu-prv.h" #include "dpu-prv.h"
#define PIXENGCFG_STATUS 0x8 #define PIXENGCFG_STATUS 0x8
@ -51,349 +50,149 @@
#define HIDDENSTATUS 0x18c #define HIDDENSTATUS 0x18c
struct dpu_fetchwarp { struct dpu_fetchwarp {
void __iomem *pec_base; struct dpu_fetchunit fu;
void __iomem *base;
struct mutex mutex;
int id;
bool inuse;
bool pin_off;
struct dpu_soc *dpu;
fetchtype_t fetchtype; fetchtype_t fetchtype;
/* see DPU_PLANE_SRC_xxx */
unsigned int stream_id;
struct dprc *dprc;
}; };
static inline u32 dpu_fw_read(struct dpu_fetchwarp *fw, unsigned int offset) static void
{ fetchwarp_set_src_buf_dimensions(struct dpu_fetchunit *fu,
return readl(fw->base + offset); unsigned int w, unsigned int h,
} u32 unused1, bool unused2)
static inline void dpu_fw_write(struct dpu_fetchwarp *fw, u32 value,
unsigned int offset)
{
writel(value, fw->base + offset);
}
static inline u32 rgb_color(u8 r, u8 g, u8 b, u8 a)
{
return (r << 24) | (g << 16) | (b << 8) | a;
}
static inline u32 yuv_color(u8 y, u8 u, u8 v)
{
return (y << 24) | (u << 16) | (v << 8);
}
void fetchwarp_shden(struct dpu_fetchwarp *fw, bool enable)
{
u32 val;
mutex_lock(&fw->mutex);
val = dpu_fw_read(fw, STATICCONTROL);
if (enable)
val |= SHDEN;
else
val &= ~SHDEN;
dpu_fw_write(fw, val, STATICCONTROL);
mutex_unlock(&fw->mutex);
}
EXPORT_SYMBOL_GPL(fetchwarp_shden);
void fetchwarp_baddr_autoupdate(struct dpu_fetchwarp *fw, u8 layer_mask)
{
u32 val;
mutex_lock(&fw->mutex);
val = dpu_fw_read(fw, STATICCONTROL);
val &= ~BASEADDRESSAUTOUPDATE_MASK;
val |= BASEADDRESSAUTOUPDATE(layer_mask);
dpu_fw_write(fw, val, STATICCONTROL);
mutex_unlock(&fw->mutex);
}
EXPORT_SYMBOL_GPL(fetchwarp_baddr_autoupdate);
void fetchwarp_shdldreq_sticky(struct dpu_fetchwarp *fw, u8 layer_mask)
{
u32 val;
mutex_lock(&fw->mutex);
val = dpu_fw_read(fw, STATICCONTROL);
val &= ~SHDLDREQSTICKY_MASK;
val |= SHDLDREQSTICKY(layer_mask);
dpu_fw_write(fw, val, STATICCONTROL);
mutex_unlock(&fw->mutex);
}
EXPORT_SYMBOL_GPL(fetchwarp_shdldreq_sticky);
void fetchwarp_set_burstlength(struct dpu_fetchwarp *fw, dma_addr_t baddr,
bool use_prefetch)
{
struct dpu_soc *dpu = fw->dpu;
unsigned int burst_size, burst_length;
u32 val;
if (use_prefetch) {
/*
* address TKT343664:
* fetch unit base address has to align to burst size
*/
burst_size = 1 << (ffs(baddr) - 1);
burst_size = min(burst_size, 128U);
burst_length = burst_size / 8;
} else {
burst_length = 16;
}
mutex_lock(&fw->mutex);
val = dpu_fw_read(fw, BURSTBUFFERMANAGEMENT);
val &= ~SETBURSTLENGTH_MASK;
val |= SETBURSTLENGTH(burst_length);
dpu_fw_write(fw, val, BURSTBUFFERMANAGEMENT);
mutex_unlock(&fw->mutex);
dev_dbg(dpu->dev, "FetchWarp%d burst length is %u\n",
fw->id, burst_length);
}
EXPORT_SYMBOL_GPL(fetchwarp_set_burstlength);
void fetchwarp_baseaddress(struct dpu_fetchwarp *fw, unsigned int index,
dma_addr_t paddr)
{
mutex_lock(&fw->mutex);
dpu_fw_write(fw, paddr, BASEADDRESS(index));
mutex_unlock(&fw->mutex);
}
EXPORT_SYMBOL_GPL(fetchwarp_baseaddress);
void fetchwarp_source_bpp(struct dpu_fetchwarp *fw, unsigned int index,
int bpp)
{
u32 val;
mutex_lock(&fw->mutex);
val = dpu_fw_read(fw, SOURCEBUFFERATTRIBUTES(index));
val &= ~0x3f0000;
val |= BITSPERPIXEL(bpp);
dpu_fw_write(fw, val, SOURCEBUFFERATTRIBUTES(index));
mutex_unlock(&fw->mutex);
}
EXPORT_SYMBOL_GPL(fetchwarp_source_bpp);
void fetchwarp_source_stride(struct dpu_fetchwarp *fw, unsigned int index,
unsigned int width, int bpp, unsigned int stride,
dma_addr_t baddr, bool use_prefetch)
{
unsigned int burst_size;
u32 val;
if (use_prefetch) {
/*
* address TKT343664:
* fetch unit base address has to align to burst size
*/
burst_size = 1 << (ffs(baddr) - 1);
burst_size = min(burst_size, 128U);
stride = width * (bpp >> 3);
/*
* address TKT339017:
* fixup for burst size vs stride mismatch
*/
stride = round_up(stride, burst_size);
}
mutex_lock(&fw->mutex);
val = dpu_fw_read(fw, SOURCEBUFFERATTRIBUTES(index));
val &= ~0xffff;
val |= STRIDE(stride);
dpu_fw_write(fw, val, SOURCEBUFFERATTRIBUTES(index));
mutex_unlock(&fw->mutex);
}
EXPORT_SYMBOL_GPL(fetchwarp_source_stride);
void fetchwarp_src_buf_dimensions(struct dpu_fetchwarp *fw,
unsigned int index, unsigned int w,
unsigned int h)
{ {
u32 val; u32 val;
val = LINEWIDTH(w) | LINECOUNT(h); val = LINEWIDTH(w) | LINECOUNT(h);
mutex_lock(&fw->mutex); mutex_lock(&fu->mutex);
dpu_fw_write(fw, val, SOURCEBUFFERDIMENSION(index)); dpu_fu_write(fu, val, SOURCEBUFFERDIMENSION(fu->sub_id));
mutex_unlock(&fw->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchwarp_src_buf_dimensions);
void fetchwarp_set_fmt(struct dpu_fetchwarp *fw, unsigned int index, u32 fmt) static void fetchwarp_set_fmt(struct dpu_fetchunit *fu,
u32 fmt, bool unused)
{ {
u32 val, bits, shift; u32 val, bits, shift;
int i; int i, sub_id = fu->sub_id;
mutex_lock(&fw->mutex); mutex_lock(&fu->mutex);
val = dpu_fw_read(fw, LAYERPROPERTY(index)); val = dpu_fu_read(fu, LAYERPROPERTY(sub_id));
val &= ~YUVCONVERSIONMODE_MASK; val &= ~YUVCONVERSIONMODE_MASK;
dpu_fw_write(fw, val, LAYERPROPERTY(index)); dpu_fu_write(fu, val, LAYERPROPERTY(sub_id));
mutex_unlock(&fw->mutex); mutex_unlock(&fu->mutex);
for (i = 0; i < ARRAY_SIZE(dpu_pixel_format_matrix); i++) { for (i = 0; i < ARRAY_SIZE(dpu_pixel_format_matrix); i++) {
if (dpu_pixel_format_matrix[i].pixel_format == fmt) { if (dpu_pixel_format_matrix[i].pixel_format == fmt) {
bits = dpu_pixel_format_matrix[i].bits; bits = dpu_pixel_format_matrix[i].bits;
shift = dpu_pixel_format_matrix[i].shift; shift = dpu_pixel_format_matrix[i].shift;
mutex_lock(&fw->mutex); mutex_lock(&fu->mutex);
dpu_fw_write(fw, bits, COLORCOMPONENTBITS(index)); dpu_fu_write(fu, bits, COLORCOMPONENTBITS(sub_id));
dpu_fw_write(fw, shift, COLORCOMPONENTSHIFT(index)); dpu_fu_write(fu, shift, COLORCOMPONENTSHIFT(sub_id));
mutex_unlock(&fw->mutex); mutex_unlock(&fu->mutex);
return; return;
} }
} }
WARN_ON(1); WARN_ON(1);
} }
EXPORT_SYMBOL_GPL(fetchwarp_set_fmt);
void fetchwarp_source_buffer_enable(struct dpu_fetchwarp *fw, static void
unsigned int index) fetchwarp_set_framedimensions(struct dpu_fetchunit *fu,
{ unsigned int w, unsigned int h, bool unused)
u32 val;
mutex_lock(&fw->mutex);
val = dpu_fw_read(fw, LAYERPROPERTY(index));
val |= SOURCEBUFFERENABLE;
dpu_fw_write(fw, val, LAYERPROPERTY(index));
mutex_unlock(&fw->mutex);
}
EXPORT_SYMBOL_GPL(fetchwarp_source_buffer_enable);
void fetchwarp_source_buffer_disable(struct dpu_fetchwarp *fw,
unsigned int index)
{
u32 val;
mutex_lock(&fw->mutex);
val = dpu_fw_read(fw, LAYERPROPERTY(index));
val &= ~SOURCEBUFFERENABLE;
dpu_fw_write(fw, val, LAYERPROPERTY(index));
mutex_unlock(&fw->mutex);
}
EXPORT_SYMBOL_GPL(fetchwarp_source_buffer_disable);
bool fetchwarp_is_enabled(struct dpu_fetchwarp *fw, unsigned int index)
{
u32 val;
mutex_lock(&fw->mutex);
val = dpu_fw_read(fw, LAYERPROPERTY(index));
mutex_unlock(&fw->mutex);
return !!(val & SOURCEBUFFERENABLE);
}
EXPORT_SYMBOL_GPL(fetchwarp_is_enabled);
void fetchwarp_framedimensions(struct dpu_fetchwarp *fw, unsigned int w,
unsigned int h)
{ {
u32 val; u32 val;
val = FRAMEWIDTH(w) | FRAMEHEIGHT(h); val = FRAMEWIDTH(w) | FRAMEHEIGHT(h);
mutex_lock(&fw->mutex); mutex_lock(&fu->mutex);
dpu_fw_write(fw, val, FRAMEDIMENSIONS); dpu_fu_write(fu, val, FRAMEDIMENSIONS);
mutex_unlock(&fw->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchwarp_framedimensions);
void fetchwarp_rgb_constantcolor(struct dpu_fetchwarp *fw, void fetchwarp_rgb_constantcolor(struct dpu_fetchunit *fu,
u8 r, u8 g, u8 b, u8 a) u8 r, u8 g, u8 b, u8 a)
{ {
u32 val; u32 val;
val = rgb_color(r, g, b, a); val = rgb_color(r, g, b, a);
mutex_lock(&fw->mutex); mutex_lock(&fu->mutex);
dpu_fw_write(fw, val, CONSTANTCOLOR(fw->id)); dpu_fu_write(fu, val, CONSTANTCOLOR(fu->id));
mutex_unlock(&fw->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchwarp_rgb_constantcolor); EXPORT_SYMBOL_GPL(fetchwarp_rgb_constantcolor);
void fetchwarp_yuv_constantcolor(struct dpu_fetchwarp *fw, u8 y, u8 u, u8 v) void fetchwarp_yuv_constantcolor(struct dpu_fetchunit *fu, u8 y, u8 u, u8 v)
{ {
u32 val; u32 val;
val = yuv_color(y, u, v); val = yuv_color(y, u, v);
mutex_lock(&fw->mutex); mutex_lock(&fu->mutex);
dpu_fw_write(fw, val, CONSTANTCOLOR(fw->id)); dpu_fu_write(fu, val, CONSTANTCOLOR(fu->id));
mutex_unlock(&fw->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(fetchwarp_yuv_constantcolor); EXPORT_SYMBOL_GPL(fetchwarp_yuv_constantcolor);
void fetchwarp_controltrigger(struct dpu_fetchwarp *fw, bool trigger) static void fetchwarp_set_controltrigger(struct dpu_fetchunit *fu)
{ {
u32 val; mutex_lock(&fu->mutex);
dpu_fu_write(fu, SHDTOKGEN, CONTROLTRIGGER);
val = trigger ? SHDTOKGEN : 0; mutex_unlock(&fu->mutex);
mutex_lock(&fw->mutex);
dpu_fw_write(fw, val, CONTROLTRIGGER);
mutex_unlock(&fw->mutex);
} }
EXPORT_SYMBOL_GPL(fetchwarp_controltrigger);
int fetchwarp_fetchtype(struct dpu_fetchwarp *fw, fetchtype_t *type) int fetchwarp_fetchtype(struct dpu_fetchunit *fu, fetchtype_t *type)
{ {
struct dpu_soc *dpu = fw->dpu; struct dpu_soc *dpu = fu->dpu;
u32 val; u32 val;
mutex_lock(&fw->mutex); mutex_lock(&fu->mutex);
val = dpu_fw_read(fw, FETCHTYPE); val = dpu_fu_read(fu, FETCHTYPE);
val &= FETCHTYPE_MASK; val &= FETCHTYPE_MASK;
mutex_unlock(&fw->mutex); mutex_unlock(&fu->mutex);
switch (val) { switch (val) {
case FETCHTYPE__DECODE: case FETCHTYPE__DECODE:
dev_dbg(dpu->dev, "FetchWarp%d with RL and RLAD decoder\n", dev_dbg(dpu->dev, "FetchWarp%d with RL and RLAD decoder\n",
fw->id); fu->id);
break; break;
case FETCHTYPE__LAYER: case FETCHTYPE__LAYER:
dev_dbg(dpu->dev, "FetchWarp%d with fractional " dev_dbg(dpu->dev, "FetchWarp%d with fractional "
"plane(8 layers)\n", fw->id); "plane(8 layers)\n", fu->id);
break; break;
case FETCHTYPE__WARP: case FETCHTYPE__WARP:
dev_dbg(dpu->dev, "FetchWarp%d with arbitrary warping and " dev_dbg(dpu->dev, "FetchWarp%d with arbitrary warping and "
"fractional plane(8 layers)\n", fw->id); "fractional plane(8 layers)\n", fu->id);
break; break;
case FETCHTYPE__ECO: case FETCHTYPE__ECO:
dev_dbg(dpu->dev, "FetchWarp%d with minimum feature set for " dev_dbg(dpu->dev, "FetchWarp%d with minimum feature set for "
"alpha, chroma and coordinate planes\n", "alpha, chroma and coordinate planes\n",
fw->id); fu->id);
break; break;
case FETCHTYPE__PERSP: case FETCHTYPE__PERSP:
dev_dbg(dpu->dev, "FetchWarp%d with affine, perspective and " dev_dbg(dpu->dev, "FetchWarp%d with affine, perspective and "
"arbitrary warping\n", fw->id); "arbitrary warping\n", fu->id);
break; break;
case FETCHTYPE__ROT: case FETCHTYPE__ROT:
dev_dbg(dpu->dev, "FetchWarp%d with affine and arbitrary " dev_dbg(dpu->dev, "FetchWarp%d with affine and arbitrary "
"warping\n", fw->id); "warping\n", fu->id);
break; break;
case FETCHTYPE__DECODEL: case FETCHTYPE__DECODEL:
dev_dbg(dpu->dev, "FetchWarp%d with RL and RLAD decoder, " dev_dbg(dpu->dev, "FetchWarp%d with RL and RLAD decoder, "
"reduced feature set\n", fw->id); "reduced feature set\n", fu->id);
break; break;
case FETCHTYPE__LAYERL: case FETCHTYPE__LAYERL:
dev_dbg(dpu->dev, "FetchWarp%d with fractional " dev_dbg(dpu->dev, "FetchWarp%d with fractional "
"plane(8 layers), reduced feature set\n", "plane(8 layers), reduced feature set\n",
fw->id); fu->id);
break; break;
case FETCHTYPE__ROTL: case FETCHTYPE__ROTL:
dev_dbg(dpu->dev, "FetchWarp%d with affine and arbitrary " dev_dbg(dpu->dev, "FetchWarp%d with affine and arbitrary "
"warping, reduced feature set\n", fw->id); "warping, reduced feature set\n", fu->id);
break; break;
default: default:
dev_warn(dpu->dev, "Invalid fetch type %u for FetchWarp%d\n", dev_warn(dpu->dev, "Invalid fetch type %u for FetchWarp%d\n",
val, fw->id); val, fu->id);
return -EINVAL; return -EINVAL;
} }
@ -402,159 +201,9 @@ int fetchwarp_fetchtype(struct dpu_fetchwarp *fw, fetchtype_t *type)
} }
EXPORT_SYMBOL_GPL(fetchwarp_fetchtype); EXPORT_SYMBOL_GPL(fetchwarp_fetchtype);
unsigned int fetchwarp_get_stream_id(struct dpu_fetchwarp *fw) struct dpu_fetchunit *dpu_fw_get(struct dpu_soc *dpu, int id)
{ {
return fw->stream_id; struct dpu_fetchunit *fu;
}
EXPORT_SYMBOL_GPL(fetchwarp_get_stream_id);
void fetchwarp_set_stream_id(struct dpu_fetchwarp *fw, unsigned int id)
{
switch (id) {
case DPU_PLANE_SRC_TO_DISP_STREAM0:
case DPU_PLANE_SRC_TO_DISP_STREAM1:
case DPU_PLANE_SRC_DISABLED:
fw->stream_id = id;
break;
default:
WARN_ON(1);
}
}
EXPORT_SYMBOL_GPL(fetchwarp_set_stream_id);
void
fetchwarp_configure_prefetch(struct dpu_fetchwarp *fw, unsigned int stream_id,
unsigned int width, unsigned int height,
unsigned int x_offset, unsigned int y_offset,
unsigned int stride, u32 format, u64 modifier,
unsigned long baddr, bool start)
{
if (WARN_ON(!fw || !fw->dprc))
return;
dprc_configure(fw->dprc,
stream_id, width, height, x_offset, y_offset, stride,
format, modifier, baddr, 0, start, false, false);
}
EXPORT_SYMBOL_GPL(fetchwarp_configure_prefetch);
void fetchwarp_enable_prefetch(struct dpu_fetchwarp *fw)
{
if (WARN_ON(!fw || !fw->dprc))
return;
dprc_enable(fw->dprc);
}
EXPORT_SYMBOL_GPL(fetchwarp_enable_prefetch);
void fetchwarp_disable_prefetch(struct dpu_fetchwarp *fw)
{
if (WARN_ON(!fw || !fw->dprc))
return;
dprc_disable(fw->dprc);
}
EXPORT_SYMBOL_GPL(fetchwarp_disable_prefetch);
void fetchwarp_reg_update_prefetch(struct dpu_fetchwarp *fw)
{
if (WARN_ON(!fw || !fw->dprc))
return;
dprc_reg_update(fw->dprc);
}
EXPORT_SYMBOL_GPL(fetchwarp_reg_update_prefetch);
void fetchwarp_prefetch_first_frame_handle(struct dpu_fetchwarp *fw)
{
if (WARN_ON(!fw || !fw->dprc))
return;
dprc_first_frame_handle(fw->dprc);
}
EXPORT_SYMBOL_GPL(fetchwarp_prefetch_first_frame_handle);
void fetchwarp_prefetch_irq_handle(struct dpu_fetchwarp *fw)
{
if (WARN_ON(!fw || !fw->dprc))
return;
dprc_irq_handle(fw->dprc);
}
EXPORT_SYMBOL_GPL(fetchwarp_prefetch_irq_handle);
void fetchwarp_prefetch_enable_first_frame_irq(struct dpu_fetchwarp *fw)
{
if (WARN_ON(!fw || !fw->dprc))
return;
dprc_enable_ctrl_done_irq(fw->dprc);
}
EXPORT_SYMBOL_GPL(fetchwarp_prefetch_enable_first_frame_irq);
bool fetchwarp_has_prefetch(struct dpu_fetchwarp *fw)
{
return !!fw->dprc;
}
EXPORT_SYMBOL_GPL(fetchwarp_has_prefetch);
bool fetchwarp_prefetch_format_supported(struct dpu_fetchwarp *fw,
u32 format, u64 modifier)
{
if (WARN_ON(!fw || !fw->dprc))
return false;
return dprc_format_supported(fw->dprc, format, modifier);
}
EXPORT_SYMBOL_GPL(fetchwarp_prefetch_format_supported);
bool fetchwarp_prefetch_stride_supported(struct dpu_fetchwarp *fw,
unsigned int stride,
unsigned int width,
u32 format)
{
if (WARN_ON(!fw || !fw->dprc))
return false;
return dprc_stride_supported(fw->dprc, stride, 0, width, format);
}
EXPORT_SYMBOL_GPL(fetchwarp_prefetch_stride_supported);
bool fetchwarp_prefetch_stride_double_check(struct dpu_fetchwarp *fw,
unsigned int stride,
unsigned int width,
u32 format,
dma_addr_t baseaddr)
{
if (WARN_ON(!fw || !fw->dprc))
return false;
return dprc_stride_double_check(fw->dprc, stride, 0, width, format,
baseaddr, 0);
}
EXPORT_SYMBOL_GPL(fetchwarp_prefetch_stride_double_check);
void fetchwarp_pin_off(struct dpu_fetchwarp *fw)
{
fw->pin_off = true;
}
EXPORT_SYMBOL_GPL(fetchwarp_pin_off);
void fetchwarp_unpin_off(struct dpu_fetchwarp *fw)
{
fw->pin_off = false;
}
EXPORT_SYMBOL_GPL(fetchwarp_unpin_off);
bool fetchwarp_is_pinned_off(struct dpu_fetchwarp *fw)
{
return fw->pin_off;
}
EXPORT_SYMBOL_GPL(fetchwarp_is_pinned_off);
struct dpu_fetchwarp *dpu_fw_get(struct dpu_soc *dpu, int id)
{
struct dpu_fetchwarp *fw;
int i; int i;
for (i = 0; i < ARRAY_SIZE(fw_ids); i++) for (i = 0; i < ARRAY_SIZE(fw_ids); i++)
@ -564,36 +213,55 @@ struct dpu_fetchwarp *dpu_fw_get(struct dpu_soc *dpu, int id)
if (i == ARRAY_SIZE(fw_ids)) if (i == ARRAY_SIZE(fw_ids))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
fw = dpu->fw_priv[i]; fu = dpu->fw_priv[i];
mutex_lock(&fw->mutex); mutex_lock(&fu->mutex);
if (fw->inuse) { if (fu->inuse) {
fw = ERR_PTR(-EBUSY); fu = ERR_PTR(-EBUSY);
goto out; goto out;
} }
fw->inuse = true; fu->inuse = true;
out: out:
mutex_unlock(&fw->mutex); mutex_unlock(&fu->mutex);
return fw; return fu;
} }
EXPORT_SYMBOL_GPL(dpu_fw_get); EXPORT_SYMBOL_GPL(dpu_fw_get);
void dpu_fw_put(struct dpu_fetchwarp *fw) void dpu_fw_put(struct dpu_fetchunit *fu)
{ {
mutex_lock(&fw->mutex); mutex_lock(&fu->mutex);
fw->inuse = false; fu->inuse = false;
mutex_unlock(&fw->mutex); mutex_unlock(&fu->mutex);
} }
EXPORT_SYMBOL_GPL(dpu_fw_put); EXPORT_SYMBOL_GPL(dpu_fw_put);
static const struct dpu_fetchunit_ops fw_ops = {
.set_burstlength = fetchunit_set_burstlength,
.set_baseaddress = fetchunit_set_baseaddress,
.set_src_bpp = fetchunit_set_src_bpp,
.set_src_stride = fetchunit_set_src_stride,
.set_src_buf_dimensions = fetchwarp_set_src_buf_dimensions,
.set_fmt = fetchwarp_set_fmt,
.enable_src_buf = fetchunit_enable_src_buf,
.disable_src_buf = fetchunit_disable_src_buf,
.is_enabled = fetchunit_is_enabled,
.set_framedimensions = fetchwarp_set_framedimensions,
.set_controltrigger = fetchwarp_set_controltrigger,
.get_stream_id = fetchunit_get_stream_id,
.set_stream_id = fetchunit_set_stream_id,
.pin_off = fetchunit_pin_off,
.unpin_off = fetchunit_unpin_off,
.is_pinned_off = fetchunit_is_pinned_off,
};
void _dpu_fw_init(struct dpu_soc *dpu, unsigned int id) void _dpu_fw_init(struct dpu_soc *dpu, unsigned int id)
{ {
struct dpu_fetchwarp *fw; struct dpu_fetchunit *fu;
int i; int i;
for (i = 0; i < ARRAY_SIZE(fw_ids); i++) for (i = 0; i < ARRAY_SIZE(fw_ids); i++)
@ -603,24 +271,24 @@ void _dpu_fw_init(struct dpu_soc *dpu, unsigned int id)
if (WARN_ON(i == ARRAY_SIZE(fw_ids))) if (WARN_ON(i == ARRAY_SIZE(fw_ids)))
return; return;
fw = dpu->fw_priv[i]; fu = dpu->fw_priv[i];
fetchwarp_baddr_autoupdate(fw, 0x0); fetchunit_baddr_autoupdate(fu, 0x0);
fetchwarp_shden(fw, true); fetchunit_shden(fu, true);
fetchwarp_shdldreq_sticky(fw, 0xFF); fetchunit_shdldreq_sticky(fu, 0xFF);
for (i = 0; i < DPU_FRAC_PLANE_LAYER_NUM; i++) fetchunit_disable_src_buf(fu);
fetchwarp_source_buffer_disable(fw, i);
mutex_lock(&fw->mutex); mutex_lock(&fu->mutex);
dpu_fw_write(fw, SETNUMBUFFERS(16) | SETBURSTLENGTH(16), dpu_fu_write(fu, SETNUMBUFFERS(16) | SETBURSTLENGTH(16),
BURSTBUFFERMANAGEMENT); BURSTBUFFERMANAGEMENT);
mutex_unlock(&fw->mutex); mutex_unlock(&fu->mutex);
} }
int dpu_fw_init(struct dpu_soc *dpu, unsigned int id, int dpu_fw_init(struct dpu_soc *dpu, unsigned int id,
unsigned long pec_base, unsigned long base) unsigned long pec_base, unsigned long base)
{ {
struct dpu_fetchwarp *fw; struct dpu_fetchwarp *fw;
struct dpu_fetchunit *fu;
int i, ret; int i, ret;
fw = devm_kzalloc(dpu->dev, sizeof(*fw), GFP_KERNEL); fw = devm_kzalloc(dpu->dev, sizeof(*fw), GFP_KERNEL);
@ -631,22 +299,27 @@ int dpu_fw_init(struct dpu_soc *dpu, unsigned int id,
if (fw_ids[i] == id) if (fw_ids[i] == id)
break; break;
dpu->fw_priv[i] = fw; fu = &fw->fu;
dpu->fw_priv[i] = fu;
fw->pec_base = devm_ioremap(dpu->dev, base, SZ_16); fu->pec_base = devm_ioremap(dpu->dev, base, SZ_16);
if (!fw->pec_base) if (!fu->pec_base)
return -ENOMEM; return -ENOMEM;
fw->base = devm_ioremap(dpu->dev, base, SZ_512); fu->base = devm_ioremap(dpu->dev, base, SZ_512);
if (!fw->base) if (!fu->base)
return -ENOMEM; return -ENOMEM;
fw->dpu = dpu; fu->dpu = dpu;
fw->id = id; fu->id = id;
fu->sub_id = 0;
fu->type = FU_T_FW;
fu->ops = &fw_ops;
fu->name = "fetchwarp";
mutex_init(&fw->mutex); mutex_init(&fu->mutex);
ret = fetchwarp_fetchtype(fw, &fw->fetchtype); ret = fetchwarp_fetchtype(fu, &fw->fetchtype);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -654,11 +327,3 @@ int dpu_fw_init(struct dpu_soc *dpu, unsigned int id,
return 0; return 0;
} }
void fetchwarp_get_dprc(struct dpu_fetchwarp *fw, void *data)
{
if (WARN_ON(!fw))
return;
fw->dprc = data;
}

View File

@ -16,6 +16,7 @@
#define __DPU_PRV_H__ #define __DPU_PRV_H__
#include <drm/drm_fourcc.h> #include <drm/drm_fourcc.h>
#include <video/dpu.h>
#define NA 0xDEADBEEF /* not available */ #define NA 0xDEADBEEF /* not available */
@ -238,11 +239,11 @@ struct dpu_soc {
struct dpu_constframe *cf_priv[4]; struct dpu_constframe *cf_priv[4];
struct dpu_disengcfg *dec_priv[2]; struct dpu_disengcfg *dec_priv[2];
struct dpu_extdst *ed_priv[4]; struct dpu_extdst *ed_priv[4];
struct dpu_fetchdecode *fd_priv[4]; struct dpu_fetchunit *fd_priv[4];
struct dpu_fetcheco *fe_priv[4]; struct dpu_fetchunit *fe_priv[4];
struct dpu_framegen *fg_priv[2]; struct dpu_framegen *fg_priv[2];
struct dpu_fetchlayer *fl_priv[2]; struct dpu_fetchunit *fl_priv[2];
struct dpu_fetchwarp *fw_priv[1]; struct dpu_fetchunit *fw_priv[1];
struct dpu_hscaler *hs_priv[3]; struct dpu_hscaler *hs_priv[3];
struct dpu_layerblend *lb_priv[7]; struct dpu_layerblend *lb_priv[7];
struct dpu_tcon *tcon_priv[2]; struct dpu_tcon *tcon_priv[2];
@ -288,9 +289,37 @@ DECLARE_DPU_UNIT_INIT_FUNC(lb);
DECLARE_DPU_UNIT_INIT_FUNC(tcon); DECLARE_DPU_UNIT_INIT_FUNC(tcon);
DECLARE_DPU_UNIT_INIT_FUNC(vs); DECLARE_DPU_UNIT_INIT_FUNC(vs);
void fetchdecode_get_dprc(struct dpu_fetchdecode *fd, void *data); static inline u32 dpu_pec_fu_read(struct dpu_fetchunit *fu, unsigned int offset)
void fetchlayer_get_dprc(struct dpu_fetchlayer *fl, void *data); {
void fetchwarp_get_dprc(struct dpu_fetchwarp *fw, void *data); return readl(fu->pec_base + offset);
}
static inline void dpu_pec_fu_write(struct dpu_fetchunit *fu, u32 value,
unsigned int offset)
{
writel(value, fu->pec_base + offset);
}
static inline u32 dpu_fu_read(struct dpu_fetchunit *fu, unsigned int offset)
{
return readl(fu->base + offset);
}
static inline void dpu_fu_write(struct dpu_fetchunit *fu, u32 value,
unsigned int offset)
{
writel(value, fu->base + offset);
}
static inline u32 rgb_color(u8 r, u8 g, u8 b, u8 a)
{
return (r << 24) | (g << 16) | (b << 8) | a;
}
static inline u32 yuv_color(u8 y, u8 u, u8 v)
{
return (y << 24) | (u << 16) | (v << 8);
}
static const unsigned int cf_ids[] = {0, 1, 4, 5}; static const unsigned int cf_ids[] = {0, 1, 4, 5};
static const unsigned int dec_ids[] = {0, 1}; static const unsigned int dec_ids[] = {0, 1};

View File

@ -18,6 +18,7 @@
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_modes.h> #include <drm/drm_modes.h>
#include <video/imx8-prefetch.h>
#include <video/videomode.h> #include <video/videomode.h>
struct dpu_soc; struct dpu_soc;
@ -418,6 +419,70 @@ typedef enum {
CLKEN__FULL = 0x3, CLKEN__FULL = 0x3,
} pixengcfg_clken_t; } pixengcfg_clken_t;
/* fetch unit types */
enum {
FU_T_NA,
FU_T_FD,
FU_T_FE,
FU_T_FL,
FU_T_FW,
};
struct dpu_fetchunit;
struct dpu_fetchunit_ops {
void (*set_burstlength)(struct dpu_fetchunit *fu,
dma_addr_t baddr, bool use_prefetch);
void (*set_baseaddress)(struct dpu_fetchunit *fu, dma_addr_t paddr);
void (*set_src_bpp)(struct dpu_fetchunit *fu, int bpp);
void (*set_src_stride)(struct dpu_fetchunit *fu,
unsigned int width, int bpp, unsigned int stride,
dma_addr_t baddr, bool use_prefetch);
void (*set_src_buf_dimensions)(struct dpu_fetchunit *fu,
unsigned int w, unsigned int h, u32 fmt,
bool deinterlace);
void (*set_fmt)(struct dpu_fetchunit *fu, u32 fmt, bool deinterlace);
void (*enable_src_buf)(struct dpu_fetchunit *fu);
void (*disable_src_buf)(struct dpu_fetchunit *fu);
bool (*is_enabled)(struct dpu_fetchunit *fu);
void (*set_framedimensions)(struct dpu_fetchunit *fu,
unsigned int w, unsigned int h,
bool deinterlace);
void (*set_controltrigger)(struct dpu_fetchunit *fu);
unsigned int (*get_stream_id)(struct dpu_fetchunit *fu);
void (*set_stream_id)(struct dpu_fetchunit *fu, unsigned int id);
void (*pin_off)(struct dpu_fetchunit *fu);
void (*unpin_off)(struct dpu_fetchunit *fu);
bool (*is_pinned_off)(struct dpu_fetchunit *fu);
};
struct dpu_fetchunit {
void __iomem *pec_base;
void __iomem *base;
char *name;
struct mutex mutex;
int id;
int sub_id; /* for fractional fetch units */
int type;
bool inuse;
struct dpu_soc *dpu;
/* see DPU_PLANE_SRC_xxx */
unsigned int stream_id;
bool pin_off;
struct dprc *dprc;
const struct dpu_fetchunit_ops *ops;
};
int dpu_map_inner_irq(struct dpu_soc *dpu, int irq); int dpu_map_inner_irq(struct dpu_soc *dpu, int irq);
/* Constant Frame Unit */ /* Constant Frame Unit */
@ -467,239 +532,54 @@ struct dpu_extdst *dpu_ed_get(struct dpu_soc *dpu, int id);
void dpu_ed_put(struct dpu_extdst *ed); void dpu_ed_put(struct dpu_extdst *ed);
/* Fetch Decode Unit */ /* Fetch Decode Unit */
struct dpu_fetchdecode; int fetchdecode_pixengcfg_dynamic_src_sel(struct dpu_fetchunit *fu,
int fetchdecode_pixengcfg_dynamic_src_sel(struct dpu_fetchdecode *fd,
fd_dynamic_src_sel_t src); fd_dynamic_src_sel_t src);
void fetchdecode_shden(struct dpu_fetchdecode *fd, bool enable); void fetchdecode_layeroffset(struct dpu_fetchunit *fd, unsigned int x,
void fetchdecode_baddr_autoupdate(struct dpu_fetchdecode *fd, u8 layer_mask);
void fetchdecode_set_burstlength(struct dpu_fetchdecode *fd, dma_addr_t baddr,
bool use_prefetch);
void fetchdecode_baseaddress(struct dpu_fetchdecode *fd, dma_addr_t paddr);
void fetchdecode_source_bpp(struct dpu_fetchdecode *fd, int bpp);
void fetchdecode_source_stride(struct dpu_fetchdecode *fd, unsigned int width,
int bpp, unsigned int stride,
dma_addr_t baddr, bool use_prefetch);
void fetchdecode_src_buf_dimensions(struct dpu_fetchdecode *fd, unsigned int w,
unsigned int h, bool deinterlace);
void fetchdecode_set_fmt(struct dpu_fetchdecode *fd, u32 fmt, bool deinterlace);
void fetchdecode_layeroffset(struct dpu_fetchdecode *fd, unsigned int x,
unsigned int y); unsigned int y);
void fetchdecode_clipoffset(struct dpu_fetchdecode *fd, unsigned int x, void fetchdecode_clipoffset(struct dpu_fetchunit *fd, unsigned int x,
unsigned int y); unsigned int y);
void fetchdecode_clipdimensions(struct dpu_fetchdecode *fd, unsigned int w, void fetchdecode_clipdimensions(struct dpu_fetchunit *fd, unsigned int w,
unsigned int h); unsigned int h);
void fetchdecode_source_buffer_enable(struct dpu_fetchdecode *fd); void fetchdecode_rgb_constantcolor(struct dpu_fetchunit *fd,
void fetchdecode_source_buffer_disable(struct dpu_fetchdecode *fd);
bool fetchdecode_is_enabled(struct dpu_fetchdecode *fd);
void fetchdecode_framedimensions(struct dpu_fetchdecode *fd, unsigned int w,
unsigned int h, bool deinterlace);
void fetchdecode_rgb_constantcolor(struct dpu_fetchdecode *fd,
u8 r, u8 g, u8 b, u8 a); u8 r, u8 g, u8 b, u8 a);
void fetchdecode_yuv_constantcolor(struct dpu_fetchdecode *fd, void fetchdecode_yuv_constantcolor(struct dpu_fetchunit *fd,
u8 y, u8 u, u8 v); u8 y, u8 u, u8 v);
void fetchdecode_controltrigger(struct dpu_fetchdecode *fd, bool trigger); int fetchdecode_fetchtype(struct dpu_fetchunit *fd, fetchtype_t *type);
int fetchdecode_fetchtype(struct dpu_fetchdecode *fd, fetchtype_t *type); shadow_load_req_t fetchdecode_to_shdldreq_t(struct dpu_fetchunit *fd);
shadow_load_req_t fetchdecode_to_shdldreq_t(struct dpu_fetchdecode *fd); u32 fetchdecode_get_vproc_mask(struct dpu_fetchunit *fd);
u32 fetchdecode_get_vproc_mask(struct dpu_fetchdecode *fd); bool fetchdecode_need_fetcheco(struct dpu_fetchunit *fd, u32 fmt);
bool fetchdecode_need_fetcheco(struct dpu_fetchdecode *fd, u32 fmt); struct dpu_fetchunit *dpu_fd_get(struct dpu_soc *dpu, int id);
unsigned int fetchdecode_get_stream_id(struct dpu_fetchdecode *fd); void dpu_fd_put(struct dpu_fetchunit *fu);
void fetchdecode_set_stream_id(struct dpu_fetchdecode *fd, unsigned int id);
void
fetchdecode_configure_prefetch(struct dpu_fetchdecode *fd,
unsigned int stream_id,
unsigned int width, unsigned int height,
unsigned int x_offset, unsigned int y_offset,
unsigned int stride, u32 format, u64 modifier,
unsigned long baddr, unsigned long uv_baddr,
bool start, bool aux_start,
bool fb_is_interlaced);
void fetchdecode_enable_prefetch(struct dpu_fetchdecode *fd);
void fetchdecode_disable_prefetch(struct dpu_fetchdecode *fd);
void fetchdecode_reg_update_prefetch(struct dpu_fetchdecode *fd);
void fetchdecode_prefetch_first_frame_handle(struct dpu_fetchdecode *fd);
void fetchdecode_prefetch_irq_handle(struct dpu_fetchdecode *fd);
void fetchdecode_prefetch_enable_first_frame_irq(struct dpu_fetchdecode *fd);
bool fetchdecode_has_prefetch(struct dpu_fetchdecode *fd);
bool fetchdecode_prefetch_format_supported(struct dpu_fetchdecode *fd,
u32 format, u64 modifier);
bool fetchdecode_prefetch_stride_supported(struct dpu_fetchdecode *fd,
unsigned int stride,
unsigned int uv_stride,
unsigned int width,
u32 format);
bool fetchdecode_prefetch_stride_double_check(struct dpu_fetchdecode *fd,
unsigned int stride,
unsigned int uv_stride,
unsigned int width,
u32 format,
dma_addr_t baseaddr,
dma_addr_t uv_baseaddr);
void fetchdecode_pin_off(struct dpu_fetchdecode *fd);
void fetchdecode_unpin_off(struct dpu_fetchdecode *fd);
bool fetchdecode_is_pinned_off(struct dpu_fetchdecode *fd);
struct dpu_fetchdecode *dpu_fd_get(struct dpu_soc *dpu, int id);
void dpu_fd_put(struct dpu_fetchdecode *fd);
/* Fetch ECO Unit */ /* Fetch ECO Unit */
struct dpu_fetcheco; void fetcheco_layeroffset(struct dpu_fetchunit *fu, unsigned int x,
void fetcheco_shden(struct dpu_fetcheco *fe, bool enable);
void fetcheco_set_burstlength(struct dpu_fetcheco *fe, dma_addr_t baddr,
bool use_prefetch);
void fetcheco_baseaddress(struct dpu_fetcheco *fe, dma_addr_t paddr);
void fetcheco_source_bpp(struct dpu_fetcheco *fe, int bpp);
void fetcheco_source_stride(struct dpu_fetcheco *fe, unsigned int width,
int bpp, unsigned int stride,
dma_addr_t baddr, bool use_prefetch);
void fetcheco_src_buf_dimensions(struct dpu_fetcheco *fe, unsigned int w,
unsigned int h, u32 fmt, bool deinterlace);
void fetcheco_set_fmt(struct dpu_fetcheco *fe, u32 fmt);
void fetcheco_layeroffset(struct dpu_fetcheco *fe, unsigned int x,
unsigned int y); unsigned int y);
void fetcheco_clipoffset(struct dpu_fetcheco *fe, unsigned int x, void fetcheco_clipoffset(struct dpu_fetchunit *fu, unsigned int x,
unsigned int y); unsigned int y);
void fetcheco_clipdimensions(struct dpu_fetcheco *fe, unsigned int w, void fetcheco_clipdimensions(struct dpu_fetchunit *fu, unsigned int w,
unsigned int h); unsigned int h);
void fetcheco_source_buffer_enable(struct dpu_fetcheco *fe); void fetcheco_frameresampling(struct dpu_fetchunit *fu, unsigned int x,
void fetcheco_source_buffer_disable(struct dpu_fetcheco *fe);
bool fetcheco_is_enabled(struct dpu_fetcheco *fe);
void fetcheco_framedimensions(struct dpu_fetcheco *fe, unsigned int w,
unsigned int h, bool deinterlace);
void fetcheco_frameresampling(struct dpu_fetcheco *fe, unsigned int x,
unsigned int y); unsigned int y);
void fetcheco_controltrigger(struct dpu_fetcheco *fe, bool trigger); int fetcheco_fetchtype(struct dpu_fetchunit *fu, fetchtype_t *type);
int fetcheco_fetchtype(struct dpu_fetcheco *fe, fetchtype_t *type); dpu_block_id_t fetcheco_get_block_id(struct dpu_fetchunit *fu);
dpu_block_id_t fetcheco_get_block_id(struct dpu_fetcheco *fe); struct dpu_fetchunit *dpu_fe_get(struct dpu_soc *dpu, int id);
unsigned int fetcheco_get_stream_id(struct dpu_fetcheco *fe); void dpu_fe_put(struct dpu_fetchunit *fu);
void fetcheco_set_stream_id(struct dpu_fetcheco *fe, unsigned int id);
void fetcheco_pin_off(struct dpu_fetcheco *fe);
void fetcheco_unpin_off(struct dpu_fetcheco *fe);
bool fetcheco_is_pinned_off(struct dpu_fetcheco *fe);
struct dpu_fetcheco *dpu_fe_get(struct dpu_soc *dpu, int id);
void dpu_fe_put(struct dpu_fetcheco *fe);
/* Fetch Layer Unit */ /* Fetch Layer Unit */
struct dpu_fetchlayer; void fetchlayer_rgb_constantcolor(struct dpu_fetchunit *fu,
void fetchlayer_shden(struct dpu_fetchlayer *fl, bool enable);
void fetchlayer_baddr_autoupdate(struct dpu_fetchlayer *fl, u8 layer_mask);
void fetchlayer_shdldreq_sticky(struct dpu_fetchlayer *fl, u8 layer_mask);
void fetchlayer_set_burstlength(struct dpu_fetchlayer *fl, dma_addr_t baddr,
bool use_prefetch);
void fetchlayer_baseaddress(struct dpu_fetchlayer *fl, unsigned int index,
dma_addr_t paddr);
void fetchlayer_source_bpp(struct dpu_fetchlayer *fl, unsigned int index,
int bpp);
void fetchlayer_source_stride(struct dpu_fetchlayer *fl, unsigned int index,
unsigned int width, int bpp, unsigned int stride,
dma_addr_t baddr, bool use_prefetch);
void fetchlayer_src_buf_dimensions(struct dpu_fetchlayer *fl,
unsigned int index, unsigned int w,
unsigned int h);
void fetchlayer_set_fmt(struct dpu_fetchlayer *fl, unsigned int index, u32 fmt);
void fetchlayer_source_buffer_enable(struct dpu_fetchlayer *fl,
unsigned int index);
void fetchlayer_source_buffer_disable(struct dpu_fetchlayer *fl,
unsigned int index);
bool fetchlayer_is_enabled(struct dpu_fetchlayer *fl, unsigned int index);
void fetchlayer_framedimensions(struct dpu_fetchlayer *fl, unsigned int w,
unsigned int h);
void fetchlayer_rgb_constantcolor(struct dpu_fetchlayer *fl,
u8 r, u8 g, u8 b, u8 a); u8 r, u8 g, u8 b, u8 a);
void fetchlayer_yuv_constantcolor(struct dpu_fetchlayer *fl, u8 y, u8 u, u8 v); void fetchlayer_yuv_constantcolor(struct dpu_fetchunit *fu, u8 y, u8 u, u8 v);
void fetchlayer_controltrigger(struct dpu_fetchlayer *fl, bool trigger); int fetchlayer_fetchtype(struct dpu_fetchunit *fu, fetchtype_t *type);
int fetchlayer_fetchtype(struct dpu_fetchlayer *fl, fetchtype_t *type); struct dpu_fetchunit *dpu_fl_get(struct dpu_soc *dpu, int id);
unsigned int fetchlayer_get_stream_id(struct dpu_fetchlayer *fl); void dpu_fl_put(struct dpu_fetchunit *fu);
void fetchlayer_set_stream_id(struct dpu_fetchlayer *fl, unsigned int id);
void
fetchlayer_configure_prefetch(struct dpu_fetchlayer *fl, unsigned int stream_id,
unsigned int width, unsigned int height,
unsigned int x_offset, unsigned int y_offset,
unsigned int stride, u32 format, u64 modifier,
unsigned long baddr, bool start);
void fetchlayer_enable_prefetch(struct dpu_fetchlayer *fl);
void fetchlayer_disable_prefetch(struct dpu_fetchlayer *fl);
void fetchlayer_reg_update_prefetch(struct dpu_fetchlayer *fl);
void fetchlayer_prefetch_first_frame_handle(struct dpu_fetchlayer *fl);
void fetchlayer_prefetch_irq_handle(struct dpu_fetchlayer *fl);
void fetchlayer_prefetch_enable_first_frame_irq(struct dpu_fetchlayer *fl);
bool fetchlayer_has_prefetch(struct dpu_fetchlayer *fl);
bool fetchlayer_prefetch_format_supported(struct dpu_fetchlayer *fl,
u32 format, u64 modifier);
bool fetchlayer_prefetch_stride_supported(struct dpu_fetchlayer *fl,
unsigned int stride,
unsigned int width,
u32 format);
bool fetchlayer_prefetch_stride_double_check(struct dpu_fetchlayer *fl,
unsigned int stride,
unsigned int width,
u32 format,
dma_addr_t baseaddr);
void fetchlayer_pin_off(struct dpu_fetchlayer *fl);
void fetchlayer_unpin_off(struct dpu_fetchlayer *fl);
bool fetchlayer_is_pinned_off(struct dpu_fetchlayer *fl);
struct dpu_fetchlayer *dpu_fl_get(struct dpu_soc *dpu, int id);
void dpu_fl_put(struct dpu_fetchlayer *fl);
/* Fetch Warp Unit */ /* Fetch Warp Unit */
struct dpu_fetchwarp; void fetchwarp_rgb_constantcolor(struct dpu_fetchunit *fu,
void fetchwarp_shden(struct dpu_fetchwarp *fw, bool enable);
void fetchwarp_baddr_autoupdate(struct dpu_fetchwarp *fw, u8 layer_mask);
void fetchwarp_shdldreq_sticky(struct dpu_fetchwarp *fw, u8 layer_mask);
void fetchwarp_set_burstlength(struct dpu_fetchwarp *fw, dma_addr_t baddr,
bool use_prefetch);
void fetchwarp_baseaddress(struct dpu_fetchwarp *fw, unsigned int index,
dma_addr_t paddr);
void fetchwarp_source_bpp(struct dpu_fetchwarp *fw, unsigned int index,
int bpp);
void fetchwarp_source_stride(struct dpu_fetchwarp *fw, unsigned int index,
unsigned int width, int bpp, unsigned int stride,
dma_addr_t baddr, bool use_prefetch);
void fetchwarp_src_buf_dimensions(struct dpu_fetchwarp *fw,
unsigned int index, unsigned int w,
unsigned int h);
void fetchwarp_set_fmt(struct dpu_fetchwarp *fw, unsigned int index, u32 fmt);
void fetchwarp_source_buffer_enable(struct dpu_fetchwarp *fw,
unsigned int index);
void fetchwarp_source_buffer_disable(struct dpu_fetchwarp *fw,
unsigned int index);
bool fetchwarp_is_enabled(struct dpu_fetchwarp *fw, unsigned int index);
void fetchwarp_framedimensions(struct dpu_fetchwarp *fw, unsigned int w,
unsigned int h);
void fetchwarp_rgb_constantcolor(struct dpu_fetchwarp *fw,
u8 r, u8 g, u8 b, u8 a); u8 r, u8 g, u8 b, u8 a);
void fetchwarp_yuv_constantcolor(struct dpu_fetchwarp *fw, u8 y, u8 u, u8 v); void fetchwarp_yuv_constantcolor(struct dpu_fetchunit *fu, u8 y, u8 u, u8 v);
void fetchwarp_controltrigger(struct dpu_fetchwarp *fw, bool trigger); int fetchwarp_fetchtype(struct dpu_fetchunit *fu, fetchtype_t *type);
int fetchwarp_fetchtype(struct dpu_fetchwarp *fw, fetchtype_t *type); struct dpu_fetchunit *dpu_fw_get(struct dpu_soc *dpu, int id);
unsigned int fetchwarp_get_stream_id(struct dpu_fetchwarp *fw); void dpu_fw_put(struct dpu_fetchunit *fu);
void fetchwarp_set_stream_id(struct dpu_fetchwarp *fw, unsigned int id);
void
fetchwarp_configure_prefetch(struct dpu_fetchwarp *fw, unsigned int stream_id,
unsigned int width, unsigned int height,
unsigned int x_offset, unsigned int y_offset,
unsigned int stride, u32 format, u64 modifier,
unsigned long baddr, bool start);
void fetchwarp_enable_prefetch(struct dpu_fetchwarp *fw);
void fetchwarp_disable_prefetch(struct dpu_fetchwarp *fw);
void fetchwarp_reg_update_prefetch(struct dpu_fetchwarp *fw);
void fetchwarp_prefetch_first_frame_handle(struct dpu_fetchwarp *fw);
void fetchwarp_prefetch_irq_handle(struct dpu_fetchwarp *fw);
void fetchwarp_prefetch_enable_first_frame_irq(struct dpu_fetchwarp *fw);
bool fetchwarp_has_prefetch(struct dpu_fetchwarp *fw);
bool fetchwarp_prefetch_format_supported(struct dpu_fetchwarp *fw,
u32 format, u64 modifier);
bool fetchwarp_prefetch_stride_supported(struct dpu_fetchwarp *fw,
unsigned int stride,
unsigned int width,
u32 format);
bool fetchwarp_prefetch_stride_double_check(struct dpu_fetchwarp *fw,
unsigned int stride,
unsigned int width,
u32 format,
dma_addr_t baseaddr);
void fetchwarp_pin_off(struct dpu_fetchwarp *fw);
void fetchwarp_unpin_off(struct dpu_fetchwarp *fw);
bool fetchwarp_is_pinned_off(struct dpu_fetchwarp *fw);
struct dpu_fetchwarp *dpu_fw_get(struct dpu_soc *dpu, int id);
void dpu_fw_put(struct dpu_fetchwarp *fw);
/* Frame Generator Unit */ /* Frame Generator Unit */
struct dpu_framegen; struct dpu_framegen;
@ -790,9 +670,9 @@ void vscaler_set_stream_id(struct dpu_vscaler *vs, unsigned int id);
struct dpu_vscaler *dpu_vs_get(struct dpu_soc *dpu, int id); struct dpu_vscaler *dpu_vs_get(struct dpu_soc *dpu, int id);
void dpu_vs_put(struct dpu_vscaler *vs); void dpu_vs_put(struct dpu_vscaler *vs);
struct dpu_fetcheco *fetchdecode_get_fetcheco(struct dpu_fetchdecode *fd); struct dpu_fetchunit *fetchdecode_get_fetcheco(struct dpu_fetchunit *fu);
struct dpu_hscaler *fetchdecode_get_hscaler(struct dpu_fetchdecode *fd); struct dpu_hscaler *fetchdecode_get_hscaler(struct dpu_fetchunit *fu);
struct dpu_vscaler *fetchdecode_get_vscaler(struct dpu_fetchdecode *fd); struct dpu_vscaler *fetchdecode_get_vscaler(struct dpu_fetchunit *fu);
bool dpu_has_prefetch_fixup(struct dpu_soc *dpu); bool dpu_has_prefetch_fixup(struct dpu_soc *dpu);
@ -804,51 +684,29 @@ u32 dpu_vproc_get_fetcheco_cap(u32 cap_mask);
u32 dpu_vproc_get_hscale_cap(u32 cap_mask); u32 dpu_vproc_get_hscale_cap(u32 cap_mask);
u32 dpu_vproc_get_vscale_cap(u32 cap_mask); u32 dpu_vproc_get_vscale_cap(u32 cap_mask);
bool fetchunit_has_prefetch(struct dpu_fetchdecode *fd, void fetchunit_get_dprc(struct dpu_fetchunit *fu, void *data);
struct dpu_fetchlayer *fl, void fetchunit_shden(struct dpu_fetchunit *fu, bool enable);
struct dpu_fetchwarp *fw); void fetchunit_baddr_autoupdate(struct dpu_fetchunit *fu, u8 layer_mask);
bool fetchunit_prefetch_format_supported(struct dpu_fetchdecode *fd, void fetchunit_shdldreq_sticky(struct dpu_fetchunit *fu, u8 layer_mask);
struct dpu_fetchlayer *fl, void fetchunit_set_burstlength(struct dpu_fetchunit *fu, dma_addr_t baddr,
struct dpu_fetchwarp *fw, bool use_prefetch);
u32 format, u64 modifier); void fetchunit_set_baseaddress(struct dpu_fetchunit *fu, dma_addr_t paddr);
bool fetchunit_prefetch_stride_supported(struct dpu_fetchdecode *fd, void fetchunit_set_src_bpp(struct dpu_fetchunit *fu, int bpp);
struct dpu_fetchlayer *fl, void fetchunit_set_src_stride(struct dpu_fetchunit *fu,
struct dpu_fetchwarp *fw, unsigned int width, int bpp, unsigned int stride,
unsigned int stride, dma_addr_t baddr, bool use_prefetch);
unsigned int uv_stride, void fetchunit_enable_src_buf(struct dpu_fetchunit *fu);
unsigned int width, void fetchunit_disable_src_buf(struct dpu_fetchunit *fu);
u32 format); bool fetchunit_is_enabled(struct dpu_fetchunit *fu);
bool fetchunit_prefetch_stride_double_check(struct dpu_fetchdecode *fd, unsigned int fetchunit_get_stream_id(struct dpu_fetchunit *fu);
struct dpu_fetchlayer *fl, void fetchunit_set_stream_id(struct dpu_fetchunit *fu, unsigned int id);
struct dpu_fetchwarp *fw, void fetchunit_pin_off(struct dpu_fetchunit *fu);
unsigned int stride, void fetchunit_unpin_off(struct dpu_fetchunit *fu);
unsigned int uv_stride, bool fetchunit_is_pinned_off(struct dpu_fetchunit *fu);
unsigned int width, bool fetchunit_is_fetchdecode(struct dpu_fetchunit *fu);
u32 format, bool fetchunit_is_fetcheco(struct dpu_fetchunit *fu);
dma_addr_t baseaddr, bool fetchunit_is_fetchlayer(struct dpu_fetchunit *fu);
dma_addr_t uv_baseaddr); bool fetchunit_is_fetchwarp(struct dpu_fetchunit *fu);
void fetchunit_configure_prefetch(struct dpu_fetchdecode *fd,
struct dpu_fetchlayer *fl,
struct dpu_fetchwarp *fw,
unsigned int stream_id,
unsigned int width, unsigned int height,
unsigned int x_offset, unsigned int y_offset,
unsigned int stride, u32 format, u64 modifier,
unsigned long baddr, unsigned long uv_baddr,
bool start, bool aux_start,
bool fb_is_interlaced);
void fetchunit_enable_prefetch(struct dpu_fetchdecode *fd,
struct dpu_fetchlayer *fl,
struct dpu_fetchwarp *fw);
void fetchunit_reg_update_prefetch(struct dpu_fetchdecode *fd,
struct dpu_fetchlayer *fl,
struct dpu_fetchwarp *fw);
void fetchunit_prefetch_first_frame_handle(struct dpu_fetchdecode *fd,
struct dpu_fetchlayer *fl,
struct dpu_fetchwarp *fw);
void fetchunit_disable_prefetch(struct dpu_fetchdecode *fd,
struct dpu_fetchlayer *fl,
struct dpu_fetchwarp *fw);
/* dpu blit engine */ /* dpu blit engine */
struct dpu_bliteng; struct dpu_bliteng;
@ -887,10 +745,10 @@ void dpu_be_configure_prefetch(struct dpu_bliteng *dpu_be,
struct dpu_plane_res { struct dpu_plane_res {
struct dpu_constframe *cf[2]; struct dpu_constframe *cf[2];
struct dpu_extdst *ed[2]; struct dpu_extdst *ed[2];
struct dpu_fetchdecode *fd[MAX_FD_NUM]; struct dpu_fetchunit *fd[MAX_FD_NUM];
struct dpu_fetcheco *fe[2]; struct dpu_fetchunit *fe[2];
struct dpu_fetchlayer *fl[MAX_FL_NUM]; struct dpu_fetchunit *fl[MAX_FL_NUM];
struct dpu_fetchwarp *fw[MAX_FW_NUM]; struct dpu_fetchunit *fw[MAX_FW_NUM];
struct dpu_framegen *fg[2]; struct dpu_framegen *fg[2];
struct dpu_hscaler *hs[2]; struct dpu_hscaler *hs[2];
struct dpu_layerblend *lb[MAX_LB_NUM]; struct dpu_layerblend *lb[MAX_LB_NUM];