Commit 8ba85306 authored by Archit Taneja's avatar Archit Taneja Committed by Tomi Valkeinen

OMAPDSS: DIPSC: Relax scaling limitations when in memory to memory mode

The scalers of overlays and writeback do not have any constraints on downscale
ratio when operating in memory to memory mode.

This is because in memory to memory mode, we aren't connected to a display which
needs data output at the rate of pixel clock. The scalers can perform as much
downscaling as needed, the rate at which the scaler outputs is adjusted
accordingly.

Relax constraints related to downscaling based on whether the input overlays are
connected to writeback in memory to memory mode. We pass a mem_to_mem boolean
parameter to dispc_ovl_setup() from APPLY. This is currently set to false, this
will later be configured to the correct value based on whether the overlay is
connected to writeback or not. Do the same later for writeback when writeback is
configured.

In the scaling calculation code, we calculate the minimum amount of core clock we
need to achieve the required downscaling. If we are in memory to memory mode, we
set this to a very small value(1 in this case), this value would always be
lesser than the actual DISPC core clock value, and hence the scaling checks
would succeed.

We take care that pixel clock isn't calculated for writeback and the overlays
connected to it when in memory to memory mode. A pixel clock in such cases
doesn't make sense.
Signed-off-by: default avatarArchit Taneja <archit@ti.com>
parent 3e8a6ff2
...@@ -584,7 +584,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl) ...@@ -584,7 +584,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode); replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings); r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);
if (r) { if (r) {
/* /*
* We can't do much here, as this function can be called from * We can't do much here, as this function can be called from
......
...@@ -91,9 +91,10 @@ struct dispc_features { ...@@ -91,9 +91,10 @@ struct dispc_features {
u16 width, u16 height, u16 out_width, u16 out_height, u16 width, u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode, bool *five_taps, enum omap_color_mode color_mode, bool *five_taps,
int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
u16 pos_x, unsigned long *core_clk); u16 pos_x, unsigned long *core_clk, bool mem_to_mem);
unsigned long (*calc_core_clk) (enum omap_plane plane, unsigned long (*calc_core_clk) (enum omap_plane plane,
u16 width, u16 height, u16 out_width, u16 out_height); u16 width, u16 height, u16 out_width, u16 out_height,
bool mem_to_mem);
u8 num_fifos; u8 num_fifos;
/* swap GFX & WB fifos */ /* swap GFX & WB fifos */
...@@ -2012,7 +2013,7 @@ static unsigned long calc_core_clk_five_taps(enum omap_plane plane, ...@@ -2012,7 +2013,7 @@ static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
} }
static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width, static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width,
u16 height, u16 out_width, u16 out_height) u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
{ {
unsigned long pclk = dispc_plane_pclk_rate(plane); unsigned long pclk = dispc_plane_pclk_rate(plane);
...@@ -2023,7 +2024,7 @@ static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width, ...@@ -2023,7 +2024,7 @@ static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width,
} }
static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width, static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
u16 height, u16 out_width, u16 out_height) u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
{ {
unsigned int hf, vf; unsigned int hf, vf;
unsigned long pclk = dispc_plane_pclk_rate(plane); unsigned long pclk = dispc_plane_pclk_rate(plane);
...@@ -2050,9 +2051,20 @@ static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width, ...@@ -2050,9 +2051,20 @@ static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
} }
static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width, static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
u16 height, u16 out_width, u16 out_height) u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
{ {
unsigned long pclk = dispc_plane_pclk_rate(plane); unsigned long pclk;
/*
* If the overlay/writeback is in mem to mem mode, there are no
* downscaling limitations with respect to pixel clock, return 1 as
* required core clock to represent that we have sufficient enough
* core clock to do maximum downscaling
*/
if (mem_to_mem)
return 1;
pclk = dispc_plane_pclk_rate(plane);
if (width > out_width) if (width > out_width)
return DIV_ROUND_UP(pclk, out_width) * width; return DIV_ROUND_UP(pclk, out_width) * width;
...@@ -2065,7 +2077,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane, ...@@ -2065,7 +2077,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
u16 width, u16 height, u16 out_width, u16 out_height, u16 width, u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode, bool *five_taps, enum omap_color_mode color_mode, bool *five_taps,
int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
u16 pos_x, unsigned long *core_clk) u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
{ {
int error; int error;
u16 in_width, in_height; u16 in_width, in_height;
...@@ -2079,7 +2091,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane, ...@@ -2079,7 +2091,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
in_height = DIV_ROUND_UP(height, *decim_y); in_height = DIV_ROUND_UP(height, *decim_y);
in_width = DIV_ROUND_UP(width, *decim_x); in_width = DIV_ROUND_UP(width, *decim_x);
*core_clk = dispc.feat->calc_core_clk(plane, in_width, *core_clk = dispc.feat->calc_core_clk(plane, in_width,
in_height, out_width, out_height); in_height, out_width, out_height, mem_to_mem);
error = (in_width > maxsinglelinewidth || !*core_clk || error = (in_width > maxsinglelinewidth || !*core_clk ||
*core_clk > dispc_core_clk_rate()); *core_clk > dispc_core_clk_rate());
if (error) { if (error) {
...@@ -2106,7 +2118,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane, ...@@ -2106,7 +2118,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
u16 width, u16 height, u16 out_width, u16 out_height, u16 width, u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode, bool *five_taps, enum omap_color_mode color_mode, bool *five_taps,
int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
u16 pos_x, unsigned long *core_clk) u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
{ {
int error; int error;
u16 in_width, in_height; u16 in_width, in_height;
...@@ -2130,7 +2142,8 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane, ...@@ -2130,7 +2142,8 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
*five_taps = false; *five_taps = false;
if (!*five_taps) if (!*five_taps)
*core_clk = dispc.feat->calc_core_clk(plane, in_width, *core_clk = dispc.feat->calc_core_clk(plane, in_width,
in_height, out_width, out_height); in_height, out_width, out_height,
mem_to_mem);
error = (error || in_width > maxsinglelinewidth * 2 || error = (error || in_width > maxsinglelinewidth * 2 ||
(in_width > maxsinglelinewidth && *five_taps) || (in_width > maxsinglelinewidth && *five_taps) ||
...@@ -2171,7 +2184,7 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane, ...@@ -2171,7 +2184,7 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
u16 width, u16 height, u16 out_width, u16 out_height, u16 width, u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode, bool *five_taps, enum omap_color_mode color_mode, bool *five_taps,
int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
u16 pos_x, unsigned long *core_clk) u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
{ {
u16 in_width, in_width_max; u16 in_width, in_width_max;
int decim_x_min = *decim_x; int decim_x_min = *decim_x;
...@@ -2179,8 +2192,13 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane, ...@@ -2179,8 +2192,13 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
const int maxsinglelinewidth = const int maxsinglelinewidth =
dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
unsigned long pclk = dispc_plane_pclk_rate(plane); unsigned long pclk = dispc_plane_pclk_rate(plane);
const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
in_width_max = dispc_core_clk_rate() / DIV_ROUND_UP(pclk, out_width); if (mem_to_mem)
in_width_max = DIV_ROUND_UP(out_width, maxdownscale);
else
in_width_max = dispc_core_clk_rate() /
DIV_ROUND_UP(pclk, out_width);
*decim_x = DIV_ROUND_UP(width, in_width_max); *decim_x = DIV_ROUND_UP(width, in_width_max);
...@@ -2199,7 +2217,7 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane, ...@@ -2199,7 +2217,7 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
} }
*core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height, *core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height,
out_width, out_height); out_width, out_height, mem_to_mem);
return 0; return 0;
} }
...@@ -2209,7 +2227,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, ...@@ -2209,7 +2227,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
u16 width, u16 height, u16 out_width, u16 out_height, u16 width, u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode, bool *five_taps, enum omap_color_mode color_mode, bool *five_taps,
int *x_predecim, int *y_predecim, u16 pos_x, int *x_predecim, int *y_predecim, u16 pos_x,
enum omap_dss_rotation_type rotation_type) enum omap_dss_rotation_type rotation_type, bool mem_to_mem)
{ {
const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
const int max_decim_limit = 16; const int max_decim_limit = 16;
...@@ -2247,7 +2265,8 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, ...@@ -2247,7 +2265,8 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height, ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height,
out_width, out_height, color_mode, five_taps, out_width, out_height, color_mode, five_taps,
x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk); x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
mem_to_mem);
if (ret) if (ret)
return ret; return ret;
...@@ -2273,7 +2292,8 @@ static int dispc_ovl_setup_common(enum omap_plane plane, ...@@ -2273,7 +2292,8 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
u16 out_width, u16 out_height, enum omap_color_mode color_mode, u16 out_width, u16 out_height, enum omap_color_mode color_mode,
u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha, u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha,
u8 global_alpha, enum omap_dss_rotation_type rotation_type, u8 global_alpha, enum omap_dss_rotation_type rotation_type,
bool replication, const struct omap_video_timings *mgr_timings) bool replication, const struct omap_video_timings *mgr_timings,
bool mem_to_mem)
{ {
bool five_taps = true; bool five_taps = true;
bool fieldmode = 0; bool fieldmode = 0;
...@@ -2314,7 +2334,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane, ...@@ -2314,7 +2334,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width, r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width,
in_height, out_width, out_height, color_mode, in_height, out_width, out_height, color_mode,
&five_taps, &x_predecim, &y_predecim, pos_x, &five_taps, &x_predecim, &y_predecim, pos_x,
rotation_type); rotation_type, mem_to_mem);
if (r) if (r)
return r; return r;
...@@ -2412,7 +2432,8 @@ static int dispc_ovl_setup_common(enum omap_plane plane, ...@@ -2412,7 +2432,8 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
} }
int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
bool replication, const struct omap_video_timings *mgr_timings) bool replication, const struct omap_video_timings *mgr_timings,
bool mem_to_mem)
{ {
int r; int r;
struct omap_overlay *ovl = omap_dss_get_overlay(plane); struct omap_overlay *ovl = omap_dss_get_overlay(plane);
...@@ -2430,7 +2451,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, ...@@ -2430,7 +2451,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height, oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
oi->out_width, oi->out_height, oi->color_mode, oi->rotation, oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha, oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
oi->rotation_type, replication, mgr_timings); oi->rotation_type, replication, mgr_timings, mem_to_mem);
return r; return r;
} }
......
...@@ -445,7 +445,8 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, ...@@ -445,7 +445,8 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
bool manual_update); bool manual_update);
int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
bool replication, const struct omap_video_timings *mgr_timings); bool replication, const struct omap_video_timings *mgr_timings,
bool mem_to_mem);
int dispc_ovl_enable(enum omap_plane plane, bool enable); int dispc_ovl_enable(enum omap_plane plane, bool enable);
void dispc_ovl_set_channel_out(enum omap_plane plane, void dispc_ovl_set_channel_out(enum omap_plane plane,
enum omap_channel channel); enum omap_channel channel);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment