mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 01:49:46 +00:00
drm/vc4: Add support for per plane scaling filter selection
Seeing as the HVS can be configured with regard the scaling filter, and DRM now supports selecting scaling filters at a per CRTC or per plane level, we can implement it. Default remains as the Mitchell/Netravali filter, but nearest neighbour is now also implemented. Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
This commit is contained in:
committed by
Dom Cobley
parent
c1a5d0bcc3
commit
19b0cf1461
@@ -348,6 +348,7 @@ struct vc4_hvs {
|
||||
struct work_struct free_dlist_work;
|
||||
|
||||
struct drm_mm_node mitchell_netravali_filter;
|
||||
struct drm_mm_node nearest_neighbour_filter;
|
||||
|
||||
struct debugfs_regset32 regset;
|
||||
|
||||
|
||||
@@ -412,6 +412,9 @@ static int vc4_hvs_debugfs_dlist_allocs(struct seq_file *m, void *data)
|
||||
static const u32 mitchell_netravali_1_3_1_3_kernel[] =
|
||||
VC4_LINEAR_PHASE_KERNEL(0, -2, -6, -8, -10, -8, -3, 2, 18,
|
||||
50, 82, 119, 155, 187, 213, 227);
|
||||
static const u32 nearest_neighbour_kernel[] =
|
||||
VC4_LINEAR_PHASE_KERNEL(0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 255, 255, 255, 255);
|
||||
|
||||
static int vc4_hvs_upload_linear_kernel(struct vc4_hvs *hvs,
|
||||
struct drm_mm_node *space,
|
||||
@@ -2067,14 +2070,19 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Upload filter kernels. We only have the one for now, so we
|
||||
* keep it around for the lifetime of the driver.
|
||||
/* Upload filter kernels. We only have the two for now, so we
|
||||
* keep them around for the lifetime of the driver.
|
||||
*/
|
||||
ret = vc4_hvs_upload_linear_kernel(hvs,
|
||||
&hvs->mitchell_netravali_filter,
|
||||
mitchell_netravali_1_3_1_3_kernel);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = vc4_hvs_upload_linear_kernel(hvs,
|
||||
&hvs->nearest_neighbour_filter,
|
||||
nearest_neighbour_kernel);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = vc4_hvs_cob_init(hvs);
|
||||
if (ret)
|
||||
@@ -2127,6 +2135,8 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master,
|
||||
|
||||
if (drm_mm_node_allocated(&vc4->hvs->mitchell_netravali_filter))
|
||||
drm_mm_remove_node(&vc4->hvs->mitchell_netravali_filter);
|
||||
if (drm_mm_node_allocated(&vc4->hvs->nearest_neighbour_filter))
|
||||
drm_mm_remove_node(&vc4->hvs->nearest_neighbour_filter);
|
||||
|
||||
drm_mm_for_each_node_safe(node, next, &vc4->hvs->dlist_mm)
|
||||
drm_mm_remove_node(node);
|
||||
|
||||
@@ -597,7 +597,8 @@ static void vc4_write_tpz(struct vc4_plane_state *vc4_state, u32 src, u32 dst)
|
||||
#define PHASE_BITS 6
|
||||
|
||||
static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst,
|
||||
u32 xy, int channel, int chroma_offset)
|
||||
u32 xy, int channel, int chroma_offset,
|
||||
bool no_interpolate)
|
||||
{
|
||||
struct vc4_dev *vc4 = to_vc4_dev(vc4_state->base.plane->dev);
|
||||
u32 scale = src / dst;
|
||||
@@ -649,6 +650,7 @@ static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst,
|
||||
phase &= SCALER_PPF_IPHASE_MASK;
|
||||
|
||||
vc4_dlist_write(vc4_state,
|
||||
(no_interpolate ? SCALER_PPF_NOINTERP : 0) |
|
||||
SCALER_PPF_AGC |
|
||||
VC4_SET_FIELD(scale, SCALER_PPF_SCALE) |
|
||||
/*
|
||||
@@ -844,14 +846,16 @@ static void vc4_write_scaling_parameters(struct drm_plane_state *state,
|
||||
if (vc4_state->x_scaling[channel] == VC4_SCALING_PPF) {
|
||||
vc4_write_ppf(vc4_state, vc4_state->src_w[channel],
|
||||
vc4_state->crtc_w, vc4_state->src_x, channel,
|
||||
state->chroma_siting_h);
|
||||
state->chroma_siting_h,
|
||||
state->scaling_filter == DRM_SCALING_FILTER_NEAREST_NEIGHBOR);
|
||||
}
|
||||
|
||||
/* Ch0 V-PPF Words 0-1: Scaling Parameters, Context */
|
||||
if (vc4_state->y_scaling[channel] == VC4_SCALING_PPF) {
|
||||
vc4_write_ppf(vc4_state, vc4_state->src_h[channel],
|
||||
vc4_state->crtc_h, vc4_state->src_y, channel,
|
||||
state->chroma_siting_v);
|
||||
state->chroma_siting_v,
|
||||
state->scaling_filter == DRM_SCALING_FILTER_NEAREST_NEIGHBOR);
|
||||
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
|
||||
}
|
||||
|
||||
@@ -1660,7 +1664,18 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
|
||||
vc4_state->y_scaling[0] == VC4_SCALING_PPF ||
|
||||
vc4_state->x_scaling[1] == VC4_SCALING_PPF ||
|
||||
vc4_state->y_scaling[1] == VC4_SCALING_PPF) {
|
||||
u32 kernel = VC4_SET_FIELD(vc4->hvs->mitchell_netravali_filter.start,
|
||||
struct drm_mm_node *filter;
|
||||
|
||||
switch (state->scaling_filter) {
|
||||
case DRM_SCALING_FILTER_DEFAULT:
|
||||
default:
|
||||
filter = &vc4->hvs->mitchell_netravali_filter;
|
||||
break;
|
||||
case DRM_SCALING_FILTER_NEAREST_NEIGHBOR:
|
||||
filter = &vc4->hvs->nearest_neighbour_filter;
|
||||
break;
|
||||
}
|
||||
u32 kernel = VC4_SET_FIELD(filter->start,
|
||||
SCALER_PPF_KERNEL_OFFSET);
|
||||
|
||||
/* HPPF plane 0 */
|
||||
@@ -2072,9 +2087,19 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
|
||||
vc4_state->y_scaling[0] == VC4_SCALING_PPF ||
|
||||
vc4_state->x_scaling[1] == VC4_SCALING_PPF ||
|
||||
vc4_state->y_scaling[1] == VC4_SCALING_PPF) {
|
||||
u32 kernel =
|
||||
VC4_SET_FIELD(vc4->hvs->mitchell_netravali_filter.start,
|
||||
SCALER_PPF_KERNEL_OFFSET);
|
||||
struct drm_mm_node *filter;
|
||||
|
||||
switch (state->scaling_filter) {
|
||||
case DRM_SCALING_FILTER_DEFAULT:
|
||||
default:
|
||||
filter = &vc4->hvs->mitchell_netravali_filter;
|
||||
break;
|
||||
case DRM_SCALING_FILTER_NEAREST_NEIGHBOR:
|
||||
filter = &vc4->hvs->nearest_neighbour_filter;
|
||||
break;
|
||||
}
|
||||
u32 kernel = VC4_SET_FIELD(filter->start,
|
||||
SCALER_PPF_KERNEL_OFFSET);
|
||||
|
||||
/* HPPF plane 0 */
|
||||
vc4_dlist_write(vc4_state, kernel);
|
||||
@@ -2567,6 +2592,10 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
|
||||
DRM_COLOR_YCBCR_BT709,
|
||||
DRM_COLOR_YCBCR_LIMITED_RANGE);
|
||||
|
||||
drm_plane_create_scaling_filter_property(plane,
|
||||
BIT(DRM_SCALING_FILTER_DEFAULT) |
|
||||
BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
|
||||
|
||||
drm_plane_create_chroma_siting_properties(plane, 0, 0);
|
||||
|
||||
if (type == DRM_PLANE_TYPE_PRIMARY)
|
||||
|
||||
Reference in New Issue
Block a user