Skip to content

Commit d6a3a3f

Browse files
6by9pelwell
authored andcommitted
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>
1 parent e4c2a77 commit d6a3a3f

File tree

3 files changed

+52
-11
lines changed

3 files changed

+52
-11
lines changed

drivers/gpu/drm/vc4/vc4_drv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ struct vc4_hvs {
358358
struct work_struct free_dlist_work;
359359

360360
struct drm_mm_node mitchell_netravali_filter;
361+
struct drm_mm_node nearest_neighbour_filter;
361362

362363
struct debugfs_regset32 regset;
363364

drivers/gpu/drm/vc4/vc4_hvs.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,9 @@ static int vc4_hvs_debugfs_dlist_allocs(struct seq_file *m, void *data)
469469
static const u32 mitchell_netravali_1_3_1_3_kernel[] =
470470
VC4_LINEAR_PHASE_KERNEL(0, -2, -6, -8, -10, -8, -3, 2, 18,
471471
50, 82, 119, 155, 187, 213, 227);
472+
static const u32 nearest_neighbour_kernel[] =
473+
VC4_LINEAR_PHASE_KERNEL(0, 0, 0, 0, 0, 0, 0, 0,
474+
1, 1, 1, 1, 255, 255, 255, 255);
472475

473476
static int vc4_hvs_upload_linear_kernel(struct vc4_hvs *hvs,
474477
struct drm_mm_node *space,
@@ -2300,14 +2303,19 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
23002303
if (ret)
23012304
return ret;
23022305

2303-
/* Upload filter kernels. We only have the one for now, so we
2304-
* keep it around for the lifetime of the driver.
2306+
/* Upload filter kernels. We only have the two for now, so we
2307+
* keep them around for the lifetime of the driver.
23052308
*/
23062309
ret = vc4_hvs_upload_linear_kernel(hvs,
23072310
&hvs->mitchell_netravali_filter,
23082311
mitchell_netravali_1_3_1_3_kernel);
23092312
if (ret)
23102313
return ret;
2314+
ret = vc4_hvs_upload_linear_kernel(hvs,
2315+
&hvs->nearest_neighbour_filter,
2316+
nearest_neighbour_kernel);
2317+
if (ret)
2318+
return ret;
23112319

23122320
ret = vc4_hvs_cob_init(hvs);
23132321
if (ret)
@@ -2333,6 +2341,8 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master,
23332341

23342342
if (drm_mm_node_allocated(&vc4->hvs->mitchell_netravali_filter))
23352343
drm_mm_remove_node(&vc4->hvs->mitchell_netravali_filter);
2344+
if (drm_mm_node_allocated(&vc4->hvs->nearest_neighbour_filter))
2345+
drm_mm_remove_node(&vc4->hvs->nearest_neighbour_filter);
23362346

23372347
drm_mm_for_each_node_safe(node, next, &vc4->hvs->dlist_mm)
23382348
drm_mm_remove_node(node);

drivers/gpu/drm/vc4/vc4_plane.c

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,9 @@ static void vc4_write_tpz(struct vc4_plane_state *vc4_state, u32 src, u32 dst)
573573
/* phase magnitude bits */
574574
#define PHASE_BITS 6
575575

576-
static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst, u32 xy, int channel, int chroma_offset)
576+
static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst,
577+
u32 xy, int channel, int chroma_offset,
578+
bool no_interpolate)
577579
{
578580
struct vc4_dev *vc4 = to_vc4_dev(vc4_state->base.plane->dev);
579581
u32 scale = src / dst;
@@ -612,6 +614,7 @@ static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst, u
612614
phase &= SCALER_PPF_IPHASE_MASK;
613615

614616
vc4_dlist_write(vc4_state,
617+
no_interpolate ? SCALER_PPF_NOINTERP : 0 |
615618
SCALER_PPF_AGC |
616619
VC4_SET_FIELD(scale, SCALER_PPF_SCALE) |
617620
/*
@@ -806,15 +809,17 @@ static void vc4_write_scaling_parameters(struct drm_plane_state *state,
806809
/* Ch0 H-PPF Word 0: Scaling Parameters */
807810
if (vc4_state->x_scaling[channel] == VC4_SCALING_PPF) {
808811
vc4_write_ppf(vc4_state,
809-
vc4_state->src_w[channel], vc4_state->crtc_w, vc4_state->src_x, channel,
810-
state->chroma_siting_h);
812+
vc4_state->src_w[channel], vc4_state->crtc_w, vc4_state->src_x,
813+
channel, state->chroma_siting_h,
814+
state->scaling_filter == DRM_SCALING_FILTER_NEAREST_NEIGHBOR);
811815
}
812816

813817
/* Ch0 V-PPF Words 0-1: Scaling Parameters, Context */
814818
if (vc4_state->y_scaling[channel] == VC4_SCALING_PPF) {
815819
vc4_write_ppf(vc4_state,
816-
vc4_state->src_h[channel], vc4_state->crtc_h, vc4_state->src_y, channel,
817-
state->chroma_siting_v);
820+
vc4_state->src_h[channel], vc4_state->crtc_h, vc4_state->src_y,
821+
channel, state->chroma_siting_v,
822+
state->scaling_filter == DRM_SCALING_FILTER_NEAREST_NEIGHBOR);
818823
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
819824
}
820825

@@ -1547,7 +1552,18 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
15471552
vc4_state->y_scaling[0] == VC4_SCALING_PPF ||
15481553
vc4_state->x_scaling[1] == VC4_SCALING_PPF ||
15491554
vc4_state->y_scaling[1] == VC4_SCALING_PPF) {
1550-
u32 kernel = VC4_SET_FIELD(vc4->hvs->mitchell_netravali_filter.start,
1555+
struct drm_mm_node *filter;
1556+
1557+
switch (state->scaling_filter) {
1558+
case DRM_SCALING_FILTER_DEFAULT:
1559+
default:
1560+
filter = &vc4->hvs->mitchell_netravali_filter;
1561+
break;
1562+
case DRM_SCALING_FILTER_NEAREST_NEIGHBOR:
1563+
filter = &vc4->hvs->nearest_neighbour_filter;
1564+
break;
1565+
}
1566+
u32 kernel = VC4_SET_FIELD(filter->start,
15511567
SCALER_PPF_KERNEL_OFFSET);
15521568

15531569
/* HPPF plane 0 */
@@ -1958,9 +1974,19 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
19581974
vc4_state->y_scaling[0] == VC4_SCALING_PPF ||
19591975
vc4_state->x_scaling[1] == VC4_SCALING_PPF ||
19601976
vc4_state->y_scaling[1] == VC4_SCALING_PPF) {
1961-
u32 kernel =
1962-
VC4_SET_FIELD(vc4->hvs->mitchell_netravali_filter.start,
1963-
SCALER_PPF_KERNEL_OFFSET);
1977+
struct drm_mm_node *filter;
1978+
1979+
switch (state->scaling_filter) {
1980+
case DRM_SCALING_FILTER_DEFAULT:
1981+
default:
1982+
filter = &vc4->hvs->mitchell_netravali_filter;
1983+
break;
1984+
case DRM_SCALING_FILTER_NEAREST_NEIGHBOR:
1985+
filter = &vc4->hvs->nearest_neighbour_filter;
1986+
break;
1987+
}
1988+
u32 kernel = VC4_SET_FIELD(filter->start,
1989+
SCALER_PPF_KERNEL_OFFSET);
19641990

19651991
/* HPPF plane 0 */
19661992
vc4_dlist_write(vc4_state, kernel);
@@ -2442,6 +2468,10 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
24422468
DRM_COLOR_YCBCR_BT709,
24432469
DRM_COLOR_YCBCR_LIMITED_RANGE);
24442470

2471+
drm_plane_create_scaling_filter_property(plane,
2472+
BIT(DRM_SCALING_FILTER_DEFAULT) |
2473+
BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
2474+
24452475
drm_plane_create_chroma_siting_properties(plane, 0, 0);
24462476

24472477
if (type == DRM_PLANE_TYPE_PRIMARY)

0 commit comments

Comments
 (0)