mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 14:44:10 +08:00
drm/komeda: Add the initial scaler support for CORE
This patch add the initial and necessary logic for CORE to support scaler: - Complete the struct komeda_scaler and komeda_scaler_state for adding the scaler specific features and capablities. - Implement komeda_scaler_validate to check the scaler with the data flow configurations. - Enable scaling support for plane input path (layer input data flow). v2: Fix a typo, and rename "needs_scaling" to "en_scaling" Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com> Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
This commit is contained in:
parent
7fded557c4
commit
502932a03f
@ -126,6 +126,20 @@ komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id)
|
||||
return c;
|
||||
}
|
||||
|
||||
struct komeda_component *
|
||||
komeda_pipeline_get_first_component(struct komeda_pipeline *pipe,
|
||||
u32 comp_mask)
|
||||
{
|
||||
struct komeda_component *c = NULL;
|
||||
int id;
|
||||
|
||||
id = find_first_bit((unsigned long *)&comp_mask, 32);
|
||||
if (id < 32)
|
||||
c = komeda_pipeline_get_component(pipe, id);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/** komeda_component_add - Add a component to &komeda_pipeline */
|
||||
struct komeda_component *
|
||||
komeda_component_add(struct komeda_pipeline *pipe,
|
||||
|
@ -244,11 +244,17 @@ struct komeda_layer_state {
|
||||
|
||||
struct komeda_scaler {
|
||||
struct komeda_component base;
|
||||
/* scaler features and caps */
|
||||
struct malidp_range hsize, vsize;
|
||||
u32 max_upscaling;
|
||||
u32 max_downscaling;
|
||||
};
|
||||
|
||||
struct komeda_scaler_state {
|
||||
struct komeda_component_state base;
|
||||
u16 hsize_in, vsize_in;
|
||||
u16 hsize_out, vsize_out;
|
||||
u8 en_scaling : 1,
|
||||
en_alpha : 1; /* enable alpha processing */
|
||||
};
|
||||
|
||||
struct komeda_compiz {
|
||||
@ -307,6 +313,7 @@ struct komeda_data_flow_cfg {
|
||||
u32 rot;
|
||||
int blending_zorder;
|
||||
u8 pixel_blend_mode, layer_alpha;
|
||||
u8 en_scaling : 1;
|
||||
};
|
||||
|
||||
/** struct komeda_pipeline_funcs */
|
||||
@ -407,6 +414,9 @@ void komeda_pipeline_destroy(struct komeda_dev *mdev,
|
||||
int komeda_assemble_pipelines(struct komeda_dev *mdev);
|
||||
struct komeda_component *
|
||||
komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id);
|
||||
struct komeda_component *
|
||||
komeda_pipeline_get_first_component(struct komeda_pipeline *pipe,
|
||||
u32 comp_mask);
|
||||
|
||||
void komeda_pipeline_dump_register(struct komeda_pipeline *pipe,
|
||||
struct seq_file *sf);
|
||||
@ -423,6 +433,14 @@ komeda_component_add(struct komeda_pipeline *pipe,
|
||||
void komeda_component_destroy(struct komeda_dev *mdev,
|
||||
struct komeda_component *c);
|
||||
|
||||
static inline struct komeda_component *
|
||||
komeda_component_pickup_output(struct komeda_component *c, u32 avail_comps)
|
||||
{
|
||||
u32 avail_inputs = c->supported_outputs & (avail_comps);
|
||||
|
||||
return komeda_pipeline_get_first_component(c->pipeline, avail_inputs);
|
||||
}
|
||||
|
||||
struct komeda_plane_state;
|
||||
struct komeda_crtc_state;
|
||||
struct komeda_crtc;
|
||||
|
@ -249,6 +249,26 @@ komeda_component_validate_private(struct komeda_component *c,
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Get current available scaler from the component->supported_outputs */
|
||||
static struct komeda_scaler *
|
||||
komeda_component_get_avail_scaler(struct komeda_component *c,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct komeda_pipeline_state *pipe_st;
|
||||
u32 avail_scalers;
|
||||
|
||||
pipe_st = komeda_pipeline_get_state(c->pipeline, state);
|
||||
if (!pipe_st)
|
||||
return NULL;
|
||||
|
||||
avail_scalers = (pipe_st->active_comps & KOMEDA_PIPELINE_SCALERS) ^
|
||||
KOMEDA_PIPELINE_SCALERS;
|
||||
|
||||
c = komeda_component_pickup_output(c, avail_scalers);
|
||||
|
||||
return to_scaler(c);
|
||||
}
|
||||
|
||||
static int
|
||||
komeda_layer_check_cfg(struct komeda_layer *layer,
|
||||
struct komeda_plane_state *kplane_st,
|
||||
@ -355,6 +375,98 @@ komeda_wb_layer_validate(struct komeda_layer *wb_layer,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool scaling_ratio_valid(u32 size_in, u32 size_out,
|
||||
u32 max_upscaling, u32 max_downscaling)
|
||||
{
|
||||
if (size_out > size_in * max_upscaling)
|
||||
return false;
|
||||
else if (size_in > size_out * max_downscaling)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
komeda_scaler_check_cfg(struct komeda_scaler *scaler,
|
||||
struct komeda_data_flow_cfg *dflow)
|
||||
{
|
||||
u32 hsize_in, vsize_in, hsize_out, vsize_out;
|
||||
|
||||
hsize_in = dflow->in_w;
|
||||
vsize_in = dflow->in_h;
|
||||
hsize_out = dflow->out_w;
|
||||
vsize_out = dflow->out_h;
|
||||
|
||||
if (!in_range(&scaler->hsize, hsize_in) ||
|
||||
!in_range(&scaler->hsize, hsize_out)) {
|
||||
DRM_DEBUG_ATOMIC("Invalid horizontal sizes");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!in_range(&scaler->vsize, vsize_in) ||
|
||||
!in_range(&scaler->vsize, vsize_out)) {
|
||||
DRM_DEBUG_ATOMIC("Invalid vertical sizes");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!scaling_ratio_valid(hsize_in, hsize_out, scaler->max_upscaling,
|
||||
scaler->max_downscaling)) {
|
||||
DRM_DEBUG_ATOMIC("Invalid horizontal scaling ratio");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!scaling_ratio_valid(vsize_in, vsize_out, scaler->max_upscaling,
|
||||
scaler->max_downscaling)) {
|
||||
DRM_DEBUG_ATOMIC("Invalid vertical scaling ratio");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
komeda_scaler_validate(void *user,
|
||||
struct komeda_crtc_state *kcrtc_st,
|
||||
struct komeda_data_flow_cfg *dflow)
|
||||
{
|
||||
struct drm_atomic_state *drm_st = kcrtc_st->base.state;
|
||||
struct komeda_component_state *c_st;
|
||||
struct komeda_scaler_state *st;
|
||||
struct komeda_scaler *scaler;
|
||||
int err = 0;
|
||||
|
||||
if (!dflow->en_scaling)
|
||||
return 0;
|
||||
|
||||
scaler = komeda_component_get_avail_scaler(dflow->input.component,
|
||||
drm_st);
|
||||
if (!scaler) {
|
||||
DRM_DEBUG_ATOMIC("No scaler available");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = komeda_scaler_check_cfg(scaler, dflow);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
c_st = komeda_component_get_state_and_set_user(&scaler->base,
|
||||
drm_st, user, kcrtc_st->base.crtc);
|
||||
if (IS_ERR(c_st))
|
||||
return PTR_ERR(c_st);
|
||||
|
||||
st = to_scaler_st(c_st);
|
||||
|
||||
st->hsize_in = dflow->in_w;
|
||||
st->vsize_in = dflow->in_h;
|
||||
st->hsize_out = dflow->out_w;
|
||||
st->vsize_out = dflow->out_h;
|
||||
st->en_scaling = dflow->en_scaling;
|
||||
/* Enable alpha processing if the next stage needs the pixel alpha */
|
||||
st->en_alpha = dflow->pixel_blend_mode != DRM_MODE_BLEND_PIXEL_NONE;
|
||||
|
||||
komeda_component_add_input(&st->base, &dflow->input, 0);
|
||||
komeda_component_set_output(&dflow->input, &scaler->base, 0);
|
||||
return err;
|
||||
}
|
||||
|
||||
void pipeline_composition_size(struct komeda_crtc_state *kcrtc_st,
|
||||
u16 *hsize, u16 *vsize)
|
||||
{
|
||||
@ -520,6 +632,10 @@ int komeda_build_layer_data_flow(struct komeda_layer *layer,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = komeda_scaler_validate(plane, kcrtc_st, dflow);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = komeda_compiz_set_input(pipe->compiz, kcrtc_st, dflow);
|
||||
|
||||
return err;
|
||||
|
@ -16,6 +16,7 @@ komeda_plane_init_data_flow(struct drm_plane_state *st,
|
||||
struct komeda_data_flow_cfg *dflow)
|
||||
{
|
||||
struct drm_framebuffer *fb = st->fb;
|
||||
u32 w, h;
|
||||
|
||||
memset(dflow, 0, sizeof(*dflow));
|
||||
|
||||
@ -36,6 +37,13 @@ komeda_plane_init_data_flow(struct drm_plane_state *st,
|
||||
dflow->in_w = st->src_w >> 16;
|
||||
dflow->in_h = st->src_h >> 16;
|
||||
|
||||
w = dflow->in_w;
|
||||
h = dflow->in_h;
|
||||
if (drm_rotation_90_or_270(dflow->rot))
|
||||
swap(w, h);
|
||||
|
||||
dflow->en_scaling = (w != dflow->out_w) || (h != dflow->out_h);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user