Commit 64a0d642 authored by Siarhei Siamashka's avatar Siarhei Siamashka
Browse files

sunxi: Only enable scaler for the layer when it is really necessary



Now the scaler is enabled for the sunxi disp layer only when we want
to use it for YUV format with XV. Whenever the layer is configured
for RGB format or deactivated, the scaler gets disabled.

This should make the driver more friendly to the other potential
scaled layer users. The total number of available scalers is only
2 for Allwinner A10 and only 1 for Allwinner A13.

The potential drawback is that now we may get an error when trying
to enable the scaler (if somebody else has used up all the available
scalers) instead of always having it reserved and ready for use.
Signed-off-by: default avatarSiarhei Siamashka <siarhei.siamashka@gmail.com>
parent 6eb2defc
......@@ -266,6 +266,28 @@ int sunxi_hw_cursor_hide(sunxi_disp_t *ctx)
* Support for scaled layers *
*****************************************************************************/
static int sunxi_layer_change_work_mode(sunxi_disp_t *ctx, int new_mode)
{
__disp_layer_info_t layer_info;
uint32_t tmp[4];
if (ctx->layer_id < 0)
return -1;
tmp[0] = ctx->fb_id;
tmp[1] = ctx->layer_id;
tmp[2] = (uintptr_t)&layer_info;
if (ioctl(ctx->fd_disp, DISP_CMD_LAYER_GET_PARA, tmp) < 0)
return -1;
layer_info.mode = new_mode;
tmp[0] = ctx->fb_id;
tmp[1] = ctx->layer_id;
tmp[2] = (uintptr_t)&layer_info;
return ioctl(ctx->fd_disp, DISP_CMD_LAYER_SET_PARA, tmp);
}
int sunxi_layer_reserve(sunxi_disp_t *ctx)
{
__disp_layer_info_t layer_info;
......@@ -279,23 +301,19 @@ int sunxi_layer_reserve(sunxi_disp_t *ctx)
if (ctx->layer_id < 0)
return -1;
/* also try to enable scaler for this layer */
/* Initially set the layer configuration to something reasonable */
tmp[0] = ctx->fb_id;
tmp[1] = ctx->layer_id;
tmp[2] = (uintptr_t)&layer_info;
if (ioctl(ctx->fd_disp, DISP_CMD_LAYER_GET_PARA, tmp) < 0)
return ctx->layer_id;
return -1;
layer_info.mode = DISP_LAYER_WORK_MODE_SCALER;
/* the screen and overlay layers need to be in different pipes */
layer_info.pipe = 1;
layer_info.alpha_en = 1;
layer_info.alpha_val = 255;
/* Initially set "layer_info.fb" to something reasonable in order to avoid
* "[DISP] not supported scaler input pixel format:0 in Scaler_sw_para_to_reg1"
* warning in dmesg log */
layer_info.fb.addr[0] = ctx->framebuffer_paddr;
layer_info.fb.size.width = 1;
layer_info.fb.size.height = 1;
......@@ -306,9 +324,18 @@ int sunxi_layer_reserve(sunxi_disp_t *ctx)
tmp[0] = ctx->fb_id;
tmp[1] = ctx->layer_id;
tmp[2] = (uintptr_t)&layer_info;
if (ioctl(ctx->fd_disp, DISP_CMD_LAYER_SET_PARA, tmp) >= 0)
if (ioctl(ctx->fd_disp, DISP_CMD_LAYER_SET_PARA, tmp) < 0)
return -1;
/* Now probe the scaler mode to see if there is a free scaler available */
if (sunxi_layer_change_work_mode(ctx, DISP_LAYER_WORK_MODE_SCALER) == 0)
ctx->layer_has_scaler = 1;
/* Revert back to normal mode */
sunxi_layer_change_work_mode(ctx, DISP_LAYER_WORK_MODE_NORMAL);
ctx->layer_scaler_is_enabled = 0;
ctx->layer_format = DISP_FORMAT_ARGB8888;
return ctx->layer_id;
}
......@@ -344,6 +371,13 @@ int sunxi_layer_set_x8r8g8b8_input_buffer(sunxi_disp_t *ctx,
if (ctx->layer_id < 0)
return -1;
if (ctx->layer_scaler_is_enabled) {
if (sunxi_layer_change_work_mode(ctx, DISP_LAYER_WORK_MODE_NORMAL) == 0)
ctx->layer_scaler_is_enabled = 0;
else
return -1;
}
fb.addr[0] = ctx->framebuffer_paddr + offset_in_framebuffer;
fb.size.width = stride;
fb.size.height = height;
......@@ -357,6 +391,8 @@ int sunxi_layer_set_x8r8g8b8_input_buffer(sunxi_disp_t *ctx,
if (ioctl(ctx->fd_disp, DISP_CMD_LAYER_SET_FB, &tmp) < 0)
return -1;
ctx->layer_format = fb.format;
tmp[0] = ctx->fb_id;
tmp[1] = ctx->layer_id;
tmp[2] = (uintptr_t)&rect;
......@@ -381,6 +417,13 @@ int sunxi_layer_set_yuv420_input_buffer(sunxi_disp_t *ctx,
if (ctx->layer_id < 0)
return -1;
if (!ctx->layer_scaler_is_enabled) {
if (sunxi_layer_change_work_mode(ctx, DISP_LAYER_WORK_MODE_SCALER) == 0)
ctx->layer_scaler_is_enabled = 1;
else
return -1;
}
fb.addr[0] = ctx->framebuffer_paddr + y_offset_in_framebuffer;
fb.addr[1] = ctx->framebuffer_paddr + u_offset_in_framebuffer;
fb.addr[2] = ctx->framebuffer_paddr + v_offset_in_framebuffer;
......@@ -396,6 +439,8 @@ int sunxi_layer_set_yuv420_input_buffer(sunxi_disp_t *ctx,
if (ioctl(ctx->fd_disp, DISP_CMD_LAYER_SET_FB, &tmp) < 0)
return -1;
ctx->layer_format = fb.format;
tmp[0] = ctx->fb_id;
tmp[1] = ctx->layer_id;
tmp[2] = (uintptr_t)&rect;
......@@ -423,6 +468,12 @@ int sunxi_layer_show(sunxi_disp_t *ctx)
if (ctx->layer_id < 0)
return -1;
/* YUV formats need to use a scaler */
if (ctx->layer_format == DISP_FORMAT_YUV420 && !ctx->layer_scaler_is_enabled) {
if (sunxi_layer_change_work_mode(ctx, DISP_LAYER_WORK_MODE_SCALER) == 0)
ctx->layer_scaler_is_enabled = 1;
}
tmp[0] = ctx->fb_id;
tmp[1] = ctx->layer_id;
return ioctl(ctx->fd_disp, DISP_CMD_LAYER_OPEN, &tmp);
......@@ -436,6 +487,12 @@ int sunxi_layer_hide(sunxi_disp_t *ctx)
if (ctx->layer_id < 0)
return -1;
/* If the layer is hidden, there is no need to keep the scaler occupied */
if (ctx->layer_scaler_is_enabled) {
if (sunxi_layer_change_work_mode(ctx, DISP_LAYER_WORK_MODE_NORMAL) == 0)
ctx->layer_scaler_is_enabled = 0;
}
tmp[0] = ctx->fb_id;
tmp[1] = ctx->layer_id;
return ioctl(ctx->fd_disp, DISP_CMD_LAYER_CLOSE, &tmp);
......
......@@ -56,6 +56,9 @@ typedef struct {
int layer_id;
int layer_has_scaler;
int layer_scaler_is_enabled;
int layer_format;
/* G2D accelerated implementation of blt2d_i interface */
blt2d_i blt2d;
/* Optional fallback interface to handle unsupported operations */
......
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