rockchip_ebc: extend mode and add zero_waveform ioctl
Extend mode ioctl to get/set the dither mode and the redraw delay. Add zero_waveform ioctl that causes the controller to drive the display with an all-neutral phase buffer. This allows measuring the VCOM using the following protocol: 1. Perform IOCTL zero_waveform(set_zero_waveform_mode=1, zero_waveform_mode=1) 2. Confirm that the phase buffer is all zero. zero_waveform_mode needs to be 1 after ICTL zero_waveform(set_zero_waveform_mode=0). 3. Perform the VCOM measurement. 4. Perform IOCTL zero_waveform(set_zero_waveform_mode=1, zero_waveform_mode=0)
This commit is contained in:
parent
519e00dd66
commit
6fce0ee56e
3 changed files with 218 additions and 58 deletions
|
@ -166,13 +166,15 @@ MODULE_FIRMWARE(EBC_CUSTOM_WF);
|
||||||
|
|
||||||
static const char *custom_wf_magic_version = "CLUT0002";
|
static const char *custom_wf_magic_version = "CLUT0002";
|
||||||
|
|
||||||
#define ROCKCHIP_EBC_WORK_ITEM_CHANGE_LUT 1
|
#define ROCKCHIP_EBC_WORK_ITEM_CHANGE_LUT BIT(0)
|
||||||
#define ROCKCHIP_EBC_WORK_ITEM_GLOBAL_REFRESH 2
|
#define ROCKCHIP_EBC_WORK_ITEM_GLOBAL_REFRESH BIT(1)
|
||||||
#define ROCKCHIP_EBC_WORK_ITEM_INIT 4
|
#define ROCKCHIP_EBC_WORK_ITEM_INIT BIT(2)
|
||||||
#define ROCKCHIP_EBC_WORK_ITEM_SUSPEND 8
|
#define ROCKCHIP_EBC_WORK_ITEM_SUSPEND BIT(3)
|
||||||
#define ROCKCHIP_EBC_WORK_ITEM_RESCHEDULE 16
|
#define ROCKCHIP_EBC_WORK_ITEM_RESCHEDULE BIT(4)
|
||||||
#define ROCKCHIP_EBC_WORK_ITEM_ENABLE_FAST_MODE 32
|
#define ROCKCHIP_EBC_WORK_ITEM_ENABLE_NORMAL_MODE BIT(5)
|
||||||
#define ROCKCHIP_EBC_WORK_ITEM_DISABLE_FAST_MODE 64
|
#define ROCKCHIP_EBC_WORK_ITEM_ENABLE_FAST_MODE BIT(6)
|
||||||
|
#define ROCKCHIP_EBC_WORK_ITEM_ENABLE_ZERO_WAVEFORM_MODE BIT(7)
|
||||||
|
#define ROCKCHIP_EBC_WORK_ITEM_DISABLE_ZERO_WAVEFORM_MODE BIT(8)
|
||||||
|
|
||||||
static const u8 dither_bayer_04[] = {
|
static const u8 dither_bayer_04[] = {
|
||||||
7, 8, 2, 10, 7, 8, 2, 10, 7, 8, 2, 10, 7, 8, 2, 10,
|
7, 8, 2, 10, 7, 8, 2, 10, 7, 8, 2, 10, 7, 8, 2, 10,
|
||||||
|
@ -512,35 +514,90 @@ static int ioctl_mode(struct drm_device *dev, void *data,
|
||||||
struct rockchip_ebc *ebc = dev_get_drvdata(dev->dev);
|
struct rockchip_ebc *ebc = dev_get_drvdata(dev->dev);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (mode->set_mode) {
|
if (mode->set_driver_mode) {
|
||||||
spin_lock(&ebc->work_item_lock);
|
spin_lock(&ebc->work_item_lock);
|
||||||
switch (mode->mode) {
|
switch (mode->driver_mode) {
|
||||||
case ROCKCHIP_EBC_MODE_NORMAL:
|
case ROCKCHIP_EBC_DRIVER_MODE_NORMAL:
|
||||||
ebc->work_item |=
|
ebc->work_item |=
|
||||||
ROCKCHIP_EBC_WORK_ITEM_DISABLE_FAST_MODE;
|
ROCKCHIP_EBC_WORK_ITEM_ENABLE_NORMAL_MODE;
|
||||||
ebc->work_item &=
|
|
||||||
~ROCKCHIP_EBC_WORK_ITEM_ENABLE_FAST_MODE;
|
|
||||||
break;
|
break;
|
||||||
case ROCKCHIP_EBC_MODE_FAST:
|
case ROCKCHIP_EBC_DRIVER_MODE_FAST:
|
||||||
ebc->work_item |=
|
ebc->work_item |=
|
||||||
ROCKCHIP_EBC_WORK_ITEM_ENABLE_FAST_MODE;
|
ROCKCHIP_EBC_WORK_ITEM_ENABLE_FAST_MODE;
|
||||||
ebc->work_item &=
|
|
||||||
~ROCKCHIP_EBC_WORK_ITEM_DISABLE_FAST_MODE;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -EINVAL;
|
ret |= -EINVAL;
|
||||||
}
|
}
|
||||||
spin_unlock(&ebc->work_item_lock);
|
spin_unlock(&ebc->work_item_lock);
|
||||||
} else {
|
} else {
|
||||||
if (ebc->fast_mode)
|
mode->driver_mode = ebc->driver_mode;
|
||||||
mode->mode = ROCKCHIP_EBC_MODE_FAST;
|
}
|
||||||
else
|
if (mode->set_dither_mode) {
|
||||||
mode->mode = ROCKCHIP_EBC_MODE_NORMAL;
|
switch (mode->dither_mode) {
|
||||||
|
case ROCKCHIP_EBC_DITHER_MODE_BAYER:
|
||||||
|
ebc->dithering_texture_size_hint = 4;
|
||||||
|
ebc->dithering_texture = dither_bayer_04;
|
||||||
|
break;
|
||||||
|
case ROCKCHIP_EBC_DITHER_MODE_BLUE_NOISE_16:
|
||||||
|
ebc->dithering_texture_size_hint = 4;
|
||||||
|
ebc->dithering_texture = dither_blue_noise_16;
|
||||||
|
ebc->dithering_texture_size_hint = 16;
|
||||||
|
break;
|
||||||
|
case ROCKCHIP_EBC_DITHER_MODE_BLUE_NOISE_32:
|
||||||
|
ebc->dithering_texture = dither_blue_noise_32;
|
||||||
|
ebc->dithering_texture_size_hint = 32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret |= -EINVAL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ebc->dithering_texture == dither_bayer_04)
|
||||||
|
mode->dither_mode = ROCKCHIP_EBC_DITHER_MODE_BAYER;
|
||||||
|
else if (ebc->dithering_texture == dither_blue_noise_16)
|
||||||
|
mode->dither_mode =
|
||||||
|
ROCKCHIP_EBC_DITHER_MODE_BLUE_NOISE_16;
|
||||||
|
else if (ebc->dithering_texture == dither_blue_noise_32)
|
||||||
|
mode->dither_mode =
|
||||||
|
ROCKCHIP_EBC_DITHER_MODE_BLUE_NOISE_32;
|
||||||
|
}
|
||||||
|
if (mode->set_redraw_delay) {
|
||||||
|
if (mode->redraw_delay != redraw_delay) {
|
||||||
|
redraw_delay = mode->redraw_delay;
|
||||||
|
spin_lock(&ebc->work_item_lock);
|
||||||
|
ebc->work_item |= ROCKCHIP_EBC_WORK_ITEM_CHANGE_LUT;
|
||||||
|
spin_unlock(&ebc->work_item_lock);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mode->redraw_delay = ebc->redraw_delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ioctl_zero_waveform(struct drm_device *dev, void *data,
|
||||||
|
struct drm_file *file_priv)
|
||||||
|
{
|
||||||
|
struct drm_rockchip_ebc_zero_waveform *zero_waveform = data;
|
||||||
|
struct rockchip_ebc *ebc = dev_get_drvdata(dev->dev);
|
||||||
|
|
||||||
|
if (zero_waveform->set_zero_waveform_mode) {
|
||||||
|
spin_lock(&ebc->work_item_lock);
|
||||||
|
if (zero_waveform->zero_waveform_mode)
|
||||||
|
ebc->work_item |=
|
||||||
|
ROCKCHIP_EBC_WORK_ITEM_ENABLE_ZERO_WAVEFORM_MODE;
|
||||||
|
else
|
||||||
|
ebc->work_item |=
|
||||||
|
ROCKCHIP_EBC_WORK_ITEM_DISABLE_ZERO_WAVEFORM_MODE;
|
||||||
|
spin_unlock(&ebc->work_item_lock);
|
||||||
|
} else {
|
||||||
|
zero_waveform->zero_waveform_mode =
|
||||||
|
ebc->driver_mode ==
|
||||||
|
ROCKCHIP_EBC_DRIVER_MODE_ZERO_WAVEFORM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
|
static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
|
||||||
DRM_IOCTL_DEF_DRV(ROCKCHIP_EBC_GLOBAL_REFRESH,
|
DRM_IOCTL_DEF_DRV(ROCKCHIP_EBC_GLOBAL_REFRESH,
|
||||||
ioctl_trigger_global_refresh, DRM_RENDER_ALLOW),
|
ioctl_trigger_global_refresh, DRM_RENDER_ALLOW),
|
||||||
|
@ -551,6 +608,8 @@ static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] =
|
||||||
DRM_IOCTL_DEF_DRV(ROCKCHIP_EBC_RECT_HINTS, ioctl_rect_hints,
|
DRM_IOCTL_DEF_DRV(ROCKCHIP_EBC_RECT_HINTS, ioctl_rect_hints,
|
||||||
DRM_RENDER_ALLOW),
|
DRM_RENDER_ALLOW),
|
||||||
DRM_IOCTL_DEF_DRV(ROCKCHIP_EBC_MODE, ioctl_mode, DRM_RENDER_ALLOW),
|
DRM_IOCTL_DEF_DRV(ROCKCHIP_EBC_MODE, ioctl_mode, DRM_RENDER_ALLOW),
|
||||||
|
DRM_IOCTL_DEF_DRV(ROCKCHIP_EBC_ZERO_WAVEFORM, ioctl_zero_waveform,
|
||||||
|
DRM_RENDER_ALLOW),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct drm_driver rockchip_ebc_drm_driver = {
|
static const struct drm_driver rockchip_ebc_drm_driver = {
|
||||||
|
@ -648,6 +707,7 @@ static void rockchip_ebc_change_lut(struct rockchip_ebc *ebc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ebc->redraw_delay = redraw_delay = redraw_delay - waiting_remaining;
|
||||||
// TODO: generalise for temperature ranges for which more than 31 phases are required
|
// TODO: generalise for temperature ranges for which more than 31 phases are required
|
||||||
ebc->inner_0_15 = lut->lut[(0xf << ROCKCHIP_EBC_CUSTOM_WF_SEQ_SHIFT) +
|
ebc->inner_0_15 = lut->lut[(0xf << ROCKCHIP_EBC_CUSTOM_WF_SEQ_SHIFT) +
|
||||||
lut->offsets[ROCKCHIP_EBC_CUSTOM_WF_DU]];
|
lut->offsets[ROCKCHIP_EBC_CUSTOM_WF_DU]];
|
||||||
|
@ -680,7 +740,7 @@ static void rockchip_ebc_partial_refresh(struct rockchip_ebc *ebc,
|
||||||
struct drm_rect clip_ongoing = DRM_RECT_EMPTY_EXTANDABLE;
|
struct drm_rect clip_ongoing = DRM_RECT_EMPTY_EXTANDABLE;
|
||||||
|
|
||||||
struct drm_rect clip_ongoing_or_waiting = clip_ongoing;
|
struct drm_rect clip_ongoing_or_waiting = clip_ongoing;
|
||||||
u8 work_item = ebc->work_item;
|
u32 work_item = ebc->work_item;
|
||||||
ktime_t time_last_start = ktime_get();
|
ktime_t time_last_start = ktime_get();
|
||||||
|
|
||||||
// TODO: move into logic setting these values
|
// TODO: move into logic setting these values
|
||||||
|
@ -709,7 +769,9 @@ static void rockchip_ebc_partial_refresh(struct rockchip_ebc *ebc,
|
||||||
bool awaiting_completion = false;
|
bool awaiting_completion = false;
|
||||||
bool awaiting_start = false;
|
bool awaiting_start = false;
|
||||||
bool no_schedule_until_clip_empty = false;
|
bool no_schedule_until_clip_empty = false;
|
||||||
bool is_enabling_fast_mode = false, is_disabling_fast_mode = false;
|
int enabling_mode = ebc->driver_mode;
|
||||||
|
int zero_waveform_mode_num_zero_phase_buffers = 0;
|
||||||
|
bool inhibit_suspend = false;
|
||||||
bool is_suspending = false;
|
bool is_suspending = false;
|
||||||
ktime_t time_last_report = ktime_get();
|
ktime_t time_last_report = ktime_get();
|
||||||
int num_frames_since_last_report = 0;
|
int num_frames_since_last_report = 0;
|
||||||
|
@ -730,17 +792,50 @@ static void rockchip_ebc_partial_refresh(struct rockchip_ebc *ebc,
|
||||||
work_item |= ebc->work_item;
|
work_item |= ebc->work_item;
|
||||||
ebc->work_item = 0;
|
ebc->work_item = 0;
|
||||||
spin_unlock(&ebc->work_item_lock);
|
spin_unlock(&ebc->work_item_lock);
|
||||||
|
if (ebc->driver_mode ==
|
||||||
|
ROCKCHIP_EBC_DRIVER_MODE_ZERO_WAVEFORM &&
|
||||||
|
!(work_item &
|
||||||
|
ROCKCHIP_EBC_WORK_ITEM_DISABLE_ZERO_WAVEFORM_MODE)) {
|
||||||
|
pr_err("Ignoring work items until zero waveform mode is left explicitly");
|
||||||
|
work_item = 0;
|
||||||
|
}
|
||||||
if ((work_item &
|
if ((work_item &
|
||||||
ROCKCHIP_EBC_WORK_ITEM_ENABLE_FAST_MODE) &&
|
ROCKCHIP_EBC_WORK_ITEM_DISABLE_ZERO_WAVEFORM_MODE) &&
|
||||||
!ebc->fast_mode) {
|
(ebc->driver_mode ==
|
||||||
|
ROCKCHIP_EBC_DRIVER_MODE_ZERO_WAVEFORM)) {
|
||||||
|
pr_warn("Disabling zero waveform mode");
|
||||||
|
inhibit_suspend = false;
|
||||||
|
// Make sure to set a mode
|
||||||
|
if (!(work_item &
|
||||||
|
(ROCKCHIP_EBC_WORK_ITEM_ENABLE_ZERO_WAVEFORM_MODE |
|
||||||
|
ROCKCHIP_EBC_WORK_ITEM_ENABLE_FAST_MODE |
|
||||||
|
ROCKCHIP_EBC_WORK_ITEM_ENABLE_NORMAL_MODE))) {
|
||||||
|
work_item |=
|
||||||
|
ROCKCHIP_EBC_WORK_ITEM_ENABLE_NORMAL_MODE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((work_item &
|
||||||
|
ROCKCHIP_EBC_WORK_ITEM_ENABLE_ZERO_WAVEFORM_MODE) &&
|
||||||
|
(ebc->driver_mode !=
|
||||||
|
ROCKCHIP_EBC_DRIVER_MODE_ZERO_WAVEFORM)) {
|
||||||
|
pr_info("Enabling zero waveform mode, finishing ongoing updates");
|
||||||
|
// Finish ongoing updates to resume with a zero-only inner/outer buffer
|
||||||
no_schedule_until_clip_empty = true;
|
no_schedule_until_clip_empty = true;
|
||||||
is_enabling_fast_mode = true;
|
zero_waveform_mode_num_zero_phase_buffers = 0;
|
||||||
|
enabling_mode =
|
||||||
|
ROCKCHIP_EBC_DRIVER_MODE_ZERO_WAVEFORM;
|
||||||
|
inhibit_suspend = true;
|
||||||
|
} else if ((work_item &
|
||||||
|
ROCKCHIP_EBC_WORK_ITEM_ENABLE_FAST_MODE) &&
|
||||||
|
ebc->driver_mode != ROCKCHIP_EBC_DRIVER_MODE_FAST) {
|
||||||
|
no_schedule_until_clip_empty = true;
|
||||||
|
enabling_mode = ROCKCHIP_EBC_DRIVER_MODE_FAST;
|
||||||
work_item |= ROCKCHIP_EBC_WORK_ITEM_GLOBAL_REFRESH;
|
work_item |= ROCKCHIP_EBC_WORK_ITEM_GLOBAL_REFRESH;
|
||||||
} else if ((work_item &
|
} else if ((work_item &
|
||||||
ROCKCHIP_EBC_WORK_ITEM_DISABLE_FAST_MODE) &&
|
ROCKCHIP_EBC_WORK_ITEM_ENABLE_NORMAL_MODE) &&
|
||||||
ebc->fast_mode) {
|
ebc->driver_mode != ROCKCHIP_EBC_DRIVER_MODE_NORMAL) {
|
||||||
no_schedule_until_clip_empty = true;
|
no_schedule_until_clip_empty = true;
|
||||||
is_disabling_fast_mode = true;
|
enabling_mode = ROCKCHIP_EBC_DRIVER_MODE_NORMAL;
|
||||||
}
|
}
|
||||||
if (work_item & ROCKCHIP_EBC_WORK_ITEM_CHANGE_LUT) {
|
if (work_item & ROCKCHIP_EBC_WORK_ITEM_CHANGE_LUT) {
|
||||||
rockchip_ebc_change_lut(ebc);
|
rockchip_ebc_change_lut(ebc);
|
||||||
|
@ -769,9 +864,14 @@ static void rockchip_ebc_partial_refresh(struct rockchip_ebc *ebc,
|
||||||
ebc->suspend_was_requested = 1;
|
ebc->suspend_was_requested = 1;
|
||||||
} else if (work_item &
|
} else if (work_item &
|
||||||
ROCKCHIP_EBC_WORK_ITEM_GLOBAL_REFRESH) {
|
ROCKCHIP_EBC_WORK_ITEM_GLOBAL_REFRESH) {
|
||||||
if (ebc->fast_mode || is_enabling_fast_mode) {
|
if (ebc->driver_mode ==
|
||||||
ebc->fast_mode = false;
|
ROCKCHIP_EBC_DRIVER_MODE_FAST ||
|
||||||
is_enabling_fast_mode = true;
|
enabling_mode ==
|
||||||
|
ROCKCHIP_EBC_DRIVER_MODE_FAST) {
|
||||||
|
ebc->driver_mode = ROCKCHIP_EBC_DRIVER_MODE_NORMAL;
|
||||||
|
enabling_mode =
|
||||||
|
ROCKCHIP_EBC_DRIVER_MODE_FAST;
|
||||||
|
// TODO: use NEON implementation
|
||||||
for (int i = 0; i < ebc->num_pixels; ++i) {
|
for (int i = 0; i < ebc->num_pixels; ++i) {
|
||||||
u8 prelim = prelim_target[i] & 0xf0;
|
u8 prelim = prelim_target[i] & 0xf0;
|
||||||
prelim_target[i] = prelim | prelim >> 4;
|
prelim_target[i] = prelim | prelim >> 4;
|
||||||
|
@ -781,12 +881,14 @@ static void rockchip_ebc_partial_refresh(struct rockchip_ebc *ebc,
|
||||||
kernel_neon_begin();
|
kernel_neon_begin();
|
||||||
rockchip_ebc_schedule_advance_neon(ebc, prelim_target, hints, phase_buffer, &clip_ongoing, &clip_ongoing_or_waiting, 0, ROCKCHIP_EBC_CUSTOM_WF_GC16, 0, ROCKCHIP_EBC_HINT_REDRAW, true);
|
rockchip_ebc_schedule_advance_neon(ebc, prelim_target, hints, phase_buffer, &clip_ongoing, &clip_ongoing_or_waiting, 0, ROCKCHIP_EBC_CUSTOM_WF_GC16, 0, ROCKCHIP_EBC_HINT_REDRAW, true);
|
||||||
kernel_neon_end();
|
kernel_neon_end();
|
||||||
|
// Skip a single advance as we have performed one just now
|
||||||
skip_advance = true;
|
skip_advance = true;
|
||||||
no_schedule_until_clip_empty = true;
|
no_schedule_until_clip_empty = true;
|
||||||
ebc->suspend_was_requested = 0;
|
ebc->suspend_was_requested = 0;
|
||||||
}
|
}
|
||||||
work_item = 0;
|
work_item = 0;
|
||||||
} else if (drm_rect_width(&clip_ongoing_or_waiting) <= 0 &&
|
} else if (drm_rect_width(&clip_ongoing_or_waiting) <= 0 &&
|
||||||
|
!inhibit_suspend &&
|
||||||
(is_suspending ||
|
(is_suspending ||
|
||||||
((drm_rect_width(&clip_incoming) <= 0) &&
|
((drm_rect_width(&clip_incoming) <= 0) &&
|
||||||
(ktime_ms_delta(ktime_get(), time_last_start) >
|
(ktime_ms_delta(ktime_get(), time_last_start) >
|
||||||
|
@ -799,10 +901,18 @@ static void rockchip_ebc_partial_refresh(struct rockchip_ebc *ebc,
|
||||||
&clip_ongoing_or_waiting, &clip_incoming);
|
&clip_ongoing_or_waiting, &clip_incoming);
|
||||||
clip_incoming = DRM_RECT_EMPTY_EXTANDABLE;
|
clip_incoming = DRM_RECT_EMPTY_EXTANDABLE;
|
||||||
}
|
}
|
||||||
pr_debug("%s frame=%d clip_ongoing=" DRM_RECT_FMT " clip_ongoing_or_waiting=" DRM_RECT_FMT " work_item=%d no_schedule_until_clip_empty=%d time_elapsed_since_last_start=%llu", __func__, frame, DRM_RECT_ARG(&clip_ongoing), DRM_RECT_ARG(&clip_ongoing_or_waiting), work_item, no_schedule_until_clip_empty, ktime_ms_delta(ktime_get(), time_last_start));
|
pr_debug(
|
||||||
|
"%s frame=%d clip_ongoing=" DRM_RECT_FMT
|
||||||
|
" clip_ongoing_or_waiting=" DRM_RECT_FMT
|
||||||
|
" work_item=%d no_schedule_until_clip_empty=%d time_elapsed_since_last_start=%llu",
|
||||||
|
__func__, frame, DRM_RECT_ARG(&clip_ongoing),
|
||||||
|
DRM_RECT_ARG(&clip_ongoing_or_waiting), work_item,
|
||||||
|
no_schedule_until_clip_empty,
|
||||||
|
ktime_ms_delta(ktime_get(), time_last_start));
|
||||||
|
pr_debug("%s ebc->driver_mode=%d enabling_mode=%d", __func__, ebc->driver_mode, enabling_mode);
|
||||||
if (drm_rect_width(&clip_ongoing_or_waiting) > 0 &&
|
if (drm_rect_width(&clip_ongoing_or_waiting) > 0 &&
|
||||||
!skip_advance) {
|
!skip_advance) {
|
||||||
if (ebc->fast_mode) {
|
if (ebc->driver_mode == ROCKCHIP_EBC_DRIVER_MODE_FAST) {
|
||||||
kernel_neon_begin();
|
kernel_neon_begin();
|
||||||
rockchip_ebc_schedule_advance_fast_neon(
|
rockchip_ebc_schedule_advance_fast_neon(
|
||||||
ebc, prelim_target, hints,
|
ebc, prelim_target, hints,
|
||||||
|
@ -811,7 +921,7 @@ static void rockchip_ebc_partial_refresh(struct rockchip_ebc *ebc,
|
||||||
early_cancellation_addition, 0, 0, 0,
|
early_cancellation_addition, 0, 0, 0,
|
||||||
!no_schedule_until_clip_empty && !work_item);
|
!no_schedule_until_clip_empty && !work_item);
|
||||||
kernel_neon_end();
|
kernel_neon_end();
|
||||||
} else {
|
} else if (ebc->driver_mode == ROCKCHIP_EBC_DRIVER_MODE_NORMAL) {
|
||||||
kernel_neon_begin();
|
kernel_neon_begin();
|
||||||
rockchip_ebc_schedule_advance_neon(
|
rockchip_ebc_schedule_advance_neon(
|
||||||
ebc, prelim_target, hints,
|
ebc, prelim_target, hints,
|
||||||
|
@ -824,14 +934,24 @@ static void rockchip_ebc_partial_refresh(struct rockchip_ebc *ebc,
|
||||||
}
|
}
|
||||||
if (drm_rect_width(&clip_ongoing) <= 0 &&
|
if (drm_rect_width(&clip_ongoing) <= 0 &&
|
||||||
no_schedule_until_clip_empty) {
|
no_schedule_until_clip_empty) {
|
||||||
no_schedule_until_clip_empty = false;
|
if (enabling_mode ==
|
||||||
if (is_enabling_fast_mode) {
|
ROCKCHIP_EBC_DRIVER_MODE_ZERO_WAVEFORM &&
|
||||||
ebc->fast_mode = true;
|
zero_waveform_mode_num_zero_phase_buffers < 2) {
|
||||||
is_enabling_fast_mode = false;
|
memset(phase_buffer, 0, ebc->phase_size);
|
||||||
}
|
if (++zero_waveform_mode_num_zero_phase_buffers >=
|
||||||
if (is_disabling_fast_mode) {
|
2) {
|
||||||
ebc->fast_mode = false;
|
ebc->driver_mode =
|
||||||
is_disabling_fast_mode = false;
|
ROCKCHIP_EBC_DRIVER_MODE_ZERO_WAVEFORM;
|
||||||
|
pr_info("Zero waveform mode enabled");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (enabling_mode) {
|
||||||
|
case ROCKCHIP_EBC_DRIVER_MODE_NORMAL:
|
||||||
|
case ROCKCHIP_EBC_DRIVER_MODE_FAST:
|
||||||
|
ebc->driver_mode = enabling_mode;
|
||||||
|
no_schedule_until_clip_empty = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pr_debug("%s schedul2 frame=%d clip_ongoing=" DRM_RECT_FMT " clip_ongoing_or_waiting=" DRM_RECT_FMT,
|
pr_debug("%s schedul2 frame=%d clip_ongoing=" DRM_RECT_FMT " clip_ongoing_or_waiting=" DRM_RECT_FMT,
|
||||||
|
@ -854,7 +974,9 @@ static void rockchip_ebc_partial_refresh(struct rockchip_ebc *ebc,
|
||||||
num_frames_since_last_report = 0;
|
num_frames_since_last_report = 0;
|
||||||
max_advance_time_since_last_report = 0;
|
max_advance_time_since_last_report = 0;
|
||||||
}
|
}
|
||||||
awaiting_start = drm_rect_width(&clip_ongoing) > 0;
|
awaiting_start = drm_rect_width(&clip_ongoing) > 0 ||
|
||||||
|
ebc->driver_mode ==
|
||||||
|
ROCKCHIP_EBC_DRIVER_MODE_ZERO_WAVEFORM;
|
||||||
if (awaiting_start) {
|
if (awaiting_start) {
|
||||||
// TODO: make sure we've synced all zeros as well
|
// TODO: make sure we've synced all zeros as well
|
||||||
int win_start = clip_ongoing.y1 * ebc->phase_pitch + (direct_mode ? clip_ongoing.x1 / 4 : clip_ongoing.x1);
|
int win_start = clip_ongoing.y1 * ebc->phase_pitch + (direct_mode ? clip_ongoing.x1 / 4 : clip_ongoing.x1);
|
||||||
|
@ -925,7 +1047,7 @@ static void rockchip_ebc_partial_refresh(struct rockchip_ebc *ebc,
|
||||||
s64 switch_buffer = 11700 - delta_advance - delta_wait - 1000;
|
s64 switch_buffer = 11700 - delta_advance - delta_wait - 1000;
|
||||||
|
|
||||||
// TODO: consider adding || !work_item
|
// TODO: consider adding || !work_item
|
||||||
while(!is_suspending) {
|
while(!is_suspending && ebc->driver_mode != ROCKCHIP_EBC_DRIVER_MODE_ZERO_WAVEFORM) {
|
||||||
spin_lock(&ctx->buffer_switch_lock);
|
spin_lock(&ctx->buffer_switch_lock);
|
||||||
ctx->refresh_index = ctx->next_refresh_index;
|
ctx->refresh_index = ctx->next_refresh_index;
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
@ -2059,7 +2181,8 @@ static int rockchip_ebc_probe(struct platform_device *pdev)
|
||||||
*((u32 *) ebc->hardware_wf + 32) = 0xaaaaaaaa;
|
*((u32 *) ebc->hardware_wf + 32) = 0xaaaaaaaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
ebc->fast_mode = false;
|
ebc->driver_mode = ROCKCHIP_EBC_DRIVER_MODE_NORMAL;
|
||||||
|
ebc->redraw_delay = redraw_delay;
|
||||||
|
|
||||||
// Sensible temperature default
|
// Sensible temperature default
|
||||||
ebc->temperature = temp_override > 0 ? temp_override : 25;
|
ebc->temperature = temp_override > 0 ? temp_override : 25;
|
||||||
|
|
|
@ -120,10 +120,11 @@ struct rockchip_ebc {
|
||||||
u8 dithering_texture_size_hint;
|
u8 dithering_texture_size_hint;
|
||||||
// whether we use direct mode or 3WIN mode. Only 3WIN mode is implemented right now
|
// whether we use direct mode or 3WIN mode. Only 3WIN mode is implemented right now
|
||||||
bool direct_mode;
|
bool direct_mode;
|
||||||
bool fast_mode;
|
int driver_mode;
|
||||||
|
int redraw_delay;
|
||||||
// Used to change the driver LUT due to temperature update, trigger a global refresh, or buffer changes
|
// Used to change the driver LUT due to temperature update, trigger a global refresh, or buffer changes
|
||||||
spinlock_t work_item_lock;
|
spinlock_t work_item_lock;
|
||||||
u8 work_item;
|
u32 work_item;
|
||||||
// used to detect when we are suspending so we can do different things to
|
// used to detect when we are suspending so we can do different things to
|
||||||
// the ebc display depending on whether we are sleeping or suspending
|
// the ebc display depending on whether we are sleeping or suspending
|
||||||
int suspend_was_requested;
|
int suspend_was_requested;
|
||||||
|
|
|
@ -17,8 +17,13 @@ extern "C" {
|
||||||
#define ROCKCHIP_EBC_HINT_REDRAW 1 << 7
|
#define ROCKCHIP_EBC_HINT_REDRAW 1 << 7
|
||||||
#define ROCKCHIP_EBC_HINT_MASK 0xf0
|
#define ROCKCHIP_EBC_HINT_MASK 0xf0
|
||||||
|
|
||||||
#define ROCKCHIP_EBC_MODE_NORMAL 0
|
#define ROCKCHIP_EBC_DRIVER_MODE_NORMAL 0
|
||||||
#define ROCKCHIP_EBC_MODE_FAST 1
|
#define ROCKCHIP_EBC_DRIVER_MODE_FAST 1
|
||||||
|
#define ROCKCHIP_EBC_DRIVER_MODE_ZERO_WAVEFORM 8
|
||||||
|
|
||||||
|
#define ROCKCHIP_EBC_DITHER_MODE_BAYER 0
|
||||||
|
#define ROCKCHIP_EBC_DITHER_MODE_BLUE_NOISE_16 1
|
||||||
|
#define ROCKCHIP_EBC_DITHER_MODE_BLUE_NOISE_32 2
|
||||||
|
|
||||||
struct drm_rockchip_ebc_trigger_global_refresh {
|
struct drm_rockchip_ebc_trigger_global_refresh {
|
||||||
bool trigger_global_refresh;
|
bool trigger_global_refresh;
|
||||||
|
@ -87,24 +92,55 @@ struct drm_rockchip_ebc_rect_hints {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct drm_rockchip_ebc_mode - Query and set driver mode.
|
* struct drm_rockchip_ebc_mode - Query and set driver/dither modes and
|
||||||
* @set_mode: apply mode instead of reading it to the same field.
|
* redraw delay
|
||||||
* @mode: one of ROCKCHIP_EBC_MODE_NORMAL or ROCKCHIP_EBC_MODE_FAST.
|
* @set_driver_mode: apply driver_mode instead of reading it to the same
|
||||||
* @padding: 64bit alignment padding.
|
* field.
|
||||||
|
* @driver_mode: one of ROCKCHIP_EBC_DRIVER_MODE_NORMAL or
|
||||||
|
* ROCKCHIP_EBC_DRIVER_MODE_FAST.
|
||||||
|
* @set_dither_mode: apply dither_mode instead of reading it to the same
|
||||||
|
* field.
|
||||||
|
* @dither_mode: one of ROCKCHIP_EBC_DITHER_MODE_BAYER,
|
||||||
|
* ROCKCHIP_EBC_DITHER_MODE_BLUE_NOISE_16, or
|
||||||
|
* ROCKCHIP_EBC_DITHER_MODE_BLUE_NOISE_32.
|
||||||
|
* @redraw_delay: number of hardware frames to delay redraws.
|
||||||
|
* @set_redraw_delay: apply redraw_delay instead of reading it to the same
|
||||||
|
* field.
|
||||||
*/
|
*/
|
||||||
struct drm_rockchip_ebc_mode {
|
struct drm_rockchip_ebc_mode {
|
||||||
__u8 set_mode;
|
__u8 set_driver_mode;
|
||||||
__u8 mode;
|
__u8 driver_mode;
|
||||||
__u8 padding[6];
|
__u8 set_dither_mode;
|
||||||
|
__u8 dither_mode;
|
||||||
|
__u16 redraw_delay;
|
||||||
|
__u8 set_redraw_delay;
|
||||||
|
__u8 _pad;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DRM_ROCKCHIP_EBC_NUM_IOCTLS 0x05
|
/**
|
||||||
|
* struct drm_rockchip_ebc_zero_waveform- Query and enable/disable zero
|
||||||
|
* waveform mode
|
||||||
|
* @set_zero_waveform_mode: apply zero_waveform_mode instead of reading it to
|
||||||
|
* the same field.
|
||||||
|
* @zero_waveform_mode: 0 for disable(d), 1 for enable(d)
|
||||||
|
*/
|
||||||
|
struct drm_rockchip_ebc_zero_waveform {
|
||||||
|
__u8 set_zero_waveform_mode;
|
||||||
|
__u8 zero_waveform_mode;
|
||||||
|
__u8 _pad[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DRM_ROCKCHIP_EBC_NUM_IOCTLS 0x06
|
||||||
|
|
||||||
#define DRM_IOCTL_ROCKCHIP_EBC_GLOBAL_REFRESH DRM_IOWR(DRM_COMMAND_BASE + 0x00, struct drm_rockchip_ebc_trigger_global_refresh)
|
#define DRM_IOCTL_ROCKCHIP_EBC_GLOBAL_REFRESH DRM_IOWR(DRM_COMMAND_BASE + 0x00, struct drm_rockchip_ebc_trigger_global_refresh)
|
||||||
#define DRM_IOCTL_ROCKCHIP_EBC_OFF_SCREEN DRM_IOW(DRM_COMMAND_BASE + 0x01, struct drm_rockchip_ebc_off_screen)
|
#define DRM_IOCTL_ROCKCHIP_EBC_OFF_SCREEN DRM_IOW(DRM_COMMAND_BASE + 0x01, struct drm_rockchip_ebc_off_screen)
|
||||||
#define DRM_IOCTL_ROCKCHIP_EBC_EXTRACT_FBS DRM_IOWR(DRM_COMMAND_BASE + 0x02, struct drm_rockchip_ebc_extract_fbs)
|
#define DRM_IOCTL_ROCKCHIP_EBC_EXTRACT_FBS DRM_IOWR(DRM_COMMAND_BASE + 0x02, struct drm_rockchip_ebc_extract_fbs)
|
||||||
#define DRM_IOCTL_ROCKCHIP_EBC_RECT_HINTS DRM_IOW(DRM_COMMAND_BASE + 0x03, struct drm_rockchip_ebc_rect_hints)
|
#define DRM_IOCTL_ROCKCHIP_EBC_RECT_HINTS DRM_IOW(DRM_COMMAND_BASE + 0x03, struct drm_rockchip_ebc_rect_hints)
|
||||||
#define DRM_IOCTL_ROCKCHIP_EBC_MODE DRM_IOWR(DRM_COMMAND_BASE + 0x04, struct drm_rockchip_ebc_mode)
|
#define DRM_IOCTL_ROCKCHIP_EBC_MODE DRM_IOWR(DRM_COMMAND_BASE + 0x04, struct drm_rockchip_ebc_mode)
|
||||||
|
#define DRM_IOCTL_ROCKCHIP_EBC_ZERO_WAVEFORM DRM_IOWR(DRM_COMMAND_BASE + 0x05, struct drm_rockchip_ebc_zero_waveform)
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __ROCKCHIP_EBC_DRM_H__*/
|
#endif /* __ROCKCHIP_EBC_DRM_H__*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue