Commit 9864fd76 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-vc4-next-2016-02-17' of github.com:anholt/linux into drm-next

This pull request brings in overlay plane support for vc4.

* tag 'drm-vc4-next-2016-02-17' of github.com:anholt/linux:
  drm/vc4: Add support for YUV planes.
  drm/vc4: Add support a few more RGB display plane formats.
  drm/vc4: Add support for scaling of display planes.
  drm/vc4: Fix which value is being used for source image size.
  drm/vc4: Add more display planes to each CRTC.
  drm/vc4: Make the CRTCs cooperate on allocating display lists.
  drm/vc4: Add a proper short-circut path for legacy cursor updates.
  drm/vc4: Move the plane clipping/scaling setup to a separate function.
  drm/vc4: Add missing __iomem annotation to hw_dlist.
  drm/vc4: Improve comments on vc4_plane_state members.
parents 5263925c fc04023f
......@@ -49,22 +49,27 @@ struct vc4_crtc {
/* Which HVS channel we're using for our CRTC. */
int channel;
/* Pointer to the actual hardware display list memory for the
* crtc.
*/
u32 __iomem *dlist;
u32 dlist_size; /* in dwords */
struct drm_pending_vblank_event *event;
};
struct vc4_crtc_state {
struct drm_crtc_state base;
/* Dlist area for this CRTC configuration. */
struct drm_mm_node mm;
};
static inline struct vc4_crtc *
to_vc4_crtc(struct drm_crtc *crtc)
{
return (struct vc4_crtc *)crtc;
}
static inline struct vc4_crtc_state *
to_vc4_crtc_state(struct drm_crtc_state *crtc_state)
{
return (struct vc4_crtc_state *)crtc_state;
}
struct vc4_crtc_data {
/* Which channel of the HVS this pixelvalve sources from. */
int hvs_channel;
......@@ -319,11 +324,13 @@ static void vc4_crtc_enable(struct drm_crtc *crtc)
static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
struct drm_crtc_state *state)
{
struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state);
struct drm_device *dev = crtc->dev;
struct vc4_dev *vc4 = to_vc4_dev(dev);
struct drm_plane *plane;
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
unsigned long flags;
u32 dlist_count = 0;
int ret;
/* The pixelvalve can only feed one encoder (and encoders are
* 1:1 with connectors.)
......@@ -346,18 +353,12 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
dlist_count++; /* Account for SCALER_CTL0_END. */
if (!vc4_crtc->dlist || dlist_count > vc4_crtc->dlist_size) {
vc4_crtc->dlist = ((u32 __iomem *)vc4->hvs->dlist +
HVS_BOOTLOADER_DLIST_END);
vc4_crtc->dlist_size = ((SCALER_DLIST_SIZE >> 2) -
HVS_BOOTLOADER_DLIST_END);
if (dlist_count > vc4_crtc->dlist_size) {
DRM_DEBUG_KMS("dlist too large for CRTC (%d > %d).\n",
dlist_count, vc4_crtc->dlist_size);
return -EINVAL;
}
}
spin_lock_irqsave(&vc4->hvs->mm_lock, flags);
ret = drm_mm_insert_node(&vc4->hvs->dlist_mm, &vc4_state->mm,
dlist_count, 1, 0);
spin_unlock_irqrestore(&vc4->hvs->mm_lock, flags);
if (ret)
return ret;
return 0;
}
......@@ -368,47 +369,29 @@ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_device *dev = crtc->dev;
struct vc4_dev *vc4 = to_vc4_dev(dev);
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
struct drm_plane *plane;
bool debug_dump_regs = false;
u32 __iomem *dlist_next = vc4_crtc->dlist;
u32 __iomem *dlist_start = vc4->hvs->dlist + vc4_state->mm.start;
u32 __iomem *dlist_next = dlist_start;
if (debug_dump_regs) {
DRM_INFO("CRTC %d HVS before:\n", drm_crtc_index(crtc));
vc4_hvs_dump_state(dev);
}
/* Copy all the active planes' dlist contents to the hardware dlist.
*
* XXX: If the new display list was large enough that it
* overlapped a currently-read display list, we need to do
* something like disable scanout before putting in the new
* list. For now, we're safe because we only have the two
* planes.
*/
/* Copy all the active planes' dlist contents to the hardware dlist. */
drm_atomic_crtc_for_each_plane(plane, crtc) {
dlist_next += vc4_plane_write_dlist(plane, dlist_next);
}
if (dlist_next == vc4_crtc->dlist) {
/* If no planes were enabled, use the SCALER_CTL0_END
* at the start of the display list memory (in the
* bootloader section). We'll rewrite that
* SCALER_CTL0_END, just in case, though.
*/
writel(SCALER_CTL0_END, vc4->hvs->dlist);
HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel), 0);
} else {
writel(SCALER_CTL0_END, dlist_next);
dlist_next++;
HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
(u32 __iomem *)vc4_crtc->dlist -
(u32 __iomem *)vc4->hvs->dlist);
WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm.size);
/* Make the next display list start after ours. */
vc4_crtc->dlist_size -= (dlist_next - vc4_crtc->dlist);
vc4_crtc->dlist = dlist_next;
}
HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
vc4_state->mm.start);
if (debug_dump_regs) {
DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc));
......@@ -573,6 +556,36 @@ static int vc4_page_flip(struct drm_crtc *crtc,
return drm_atomic_helper_page_flip(crtc, fb, event, flags);
}
static struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc)
{
struct vc4_crtc_state *vc4_state;
vc4_state = kzalloc(sizeof(*vc4_state), GFP_KERNEL);
if (!vc4_state)
return NULL;
__drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
return &vc4_state->base;
}
static void vc4_crtc_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state)
{
struct vc4_dev *vc4 = to_vc4_dev(crtc->dev);
struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state);
if (vc4_state->mm.allocated) {
unsigned long flags;
spin_lock_irqsave(&vc4->hvs->mm_lock, flags);
drm_mm_remove_node(&vc4_state->mm);
spin_unlock_irqrestore(&vc4->hvs->mm_lock, flags);
}
__drm_atomic_helper_crtc_destroy_state(crtc, state);
}
static const struct drm_crtc_funcs vc4_crtc_funcs = {
.set_config = drm_atomic_helper_set_config,
.destroy = vc4_crtc_destroy,
......@@ -581,8 +594,8 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = {
.cursor_set = NULL, /* handled by drm_mode_cursor_universal */
.cursor_move = NULL, /* handled by drm_mode_cursor_universal */
.reset = drm_atomic_helper_crtc_reset,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
.atomic_duplicate_state = vc4_crtc_duplicate_state,
.atomic_destroy_state = vc4_crtc_destroy_state,
};
static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
......@@ -644,9 +657,9 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
struct vc4_dev *vc4 = to_vc4_dev(drm);
struct vc4_crtc *vc4_crtc;
struct drm_crtc *crtc;
struct drm_plane *primary_plane, *cursor_plane;
struct drm_plane *primary_plane, *cursor_plane, *destroy_plane, *temp;
const struct of_device_id *match;
int ret;
int ret, i;
vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
if (!vc4_crtc)
......@@ -675,27 +688,49 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
goto err;
}
cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR);
if (IS_ERR(cursor_plane)) {
dev_err(dev, "failed to construct cursor plane\n");
ret = PTR_ERR(cursor_plane);
goto err_primary;
}
drm_crtc_init_with_planes(drm, crtc, primary_plane, cursor_plane,
drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
&vc4_crtc_funcs, NULL);
drm_crtc_helper_add(crtc, &vc4_crtc_helper_funcs);
primary_plane->crtc = crtc;
cursor_plane->crtc = crtc;
vc4->crtc[drm_crtc_index(crtc)] = vc4_crtc;
vc4_crtc->channel = vc4_crtc->data->hvs_channel;
/* Set up some arbitrary number of planes. We're not limited
* by a set number of physical registers, just the space in
* the HVS (16k) and how small an plane can be (28 bytes).
* However, each plane we set up takes up some memory, and
* increases the cost of looping over planes, which atomic
* modesetting does quite a bit. As a result, we pick a
* modest number of planes to expose, that should hopefully
* still cover any sane usecase.
*/
for (i = 0; i < 8; i++) {
struct drm_plane *plane =
vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY);
if (IS_ERR(plane))
continue;
plane->possible_crtcs = 1 << drm_crtc_index(crtc);
}
/* Set up the legacy cursor after overlay initialization,
* since we overlay planes on the CRTC in the order they were
* initialized.
*/
cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR);
if (!IS_ERR(cursor_plane)) {
cursor_plane->possible_crtcs = 1 << drm_crtc_index(crtc);
cursor_plane->crtc = crtc;
crtc->cursor = cursor_plane;
}
CRTC_WRITE(PV_INTEN, 0);
CRTC_WRITE(PV_INTSTAT, PV_INT_VFP_START);
ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
vc4_crtc_irq_handler, 0, "vc4 crtc", vc4_crtc);
if (ret)
goto err_cursor;
goto err_destroy_planes;
vc4_set_crtc_possible_masks(drm, crtc);
......@@ -703,10 +738,12 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
return 0;
err_cursor:
cursor_plane->funcs->destroy(cursor_plane);
err_primary:
primary_plane->funcs->destroy(primary_plane);
err_destroy_planes:
list_for_each_entry_safe(destroy_plane, temp,
&drm->mode_config.plane_list, head) {
if (destroy_plane->possible_crtcs == 1 << drm_crtc_index(crtc))
destroy_plane->funcs->destroy(destroy_plane);
}
err:
return ret;
}
......
......@@ -149,7 +149,17 @@ struct vc4_v3d {
struct vc4_hvs {
struct platform_device *pdev;
void __iomem *regs;
void __iomem *dlist;
u32 __iomem *dlist;
/* Memory manager for CRTCs to allocate space in the display
* list. Units are dwords.
*/
struct drm_mm dlist_mm;
/* Memory manager for the LBM memory used by HVS scaling. */
struct drm_mm lbm_mm;
spinlock_t mm_lock;
struct drm_mm_node mitchell_netravali_filter;
};
struct vc4_plane {
......
......@@ -100,12 +100,76 @@ int vc4_hvs_debugfs_regs(struct seq_file *m, void *unused)
}
#endif
/* The filter kernel is composed of dwords each containing 3 9-bit
* signed integers packed next to each other.
*/
#define VC4_INT_TO_COEFF(coeff) (coeff & 0x1ff)
#define VC4_PPF_FILTER_WORD(c0, c1, c2) \
((((c0) & 0x1ff) << 0) | \
(((c1) & 0x1ff) << 9) | \
(((c2) & 0x1ff) << 18))
/* The whole filter kernel is arranged as the coefficients 0-16 going
* up, then a pad, then 17-31 going down and reversed within the
* dwords. This means that a linear phase kernel (where it's
* symmetrical at the boundary between 15 and 16) has the last 5
* dwords matching the first 5, but reversed.
*/
#define VC4_LINEAR_PHASE_KERNEL(c0, c1, c2, c3, c4, c5, c6, c7, c8, \
c9, c10, c11, c12, c13, c14, c15) \
{VC4_PPF_FILTER_WORD(c0, c1, c2), \
VC4_PPF_FILTER_WORD(c3, c4, c5), \
VC4_PPF_FILTER_WORD(c6, c7, c8), \
VC4_PPF_FILTER_WORD(c9, c10, c11), \
VC4_PPF_FILTER_WORD(c12, c13, c14), \
VC4_PPF_FILTER_WORD(c15, c15, 0)}
#define VC4_LINEAR_PHASE_KERNEL_DWORDS 6
#define VC4_KERNEL_DWORDS (VC4_LINEAR_PHASE_KERNEL_DWORDS * 2 - 1)
/* Recommended B=1/3, C=1/3 filter choice from Mitchell/Netravali.
* http://www.cs.utexas.edu/~fussell/courses/cs384g/lectures/mitchell/Mitchell.pdf
*/
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 int vc4_hvs_upload_linear_kernel(struct vc4_hvs *hvs,
struct drm_mm_node *space,
const u32 *kernel)
{
int ret, i;
u32 __iomem *dst_kernel;
ret = drm_mm_insert_node(&hvs->dlist_mm, space, VC4_KERNEL_DWORDS, 1,
0);
if (ret) {
DRM_ERROR("Failed to allocate space for filter kernel: %d\n",
ret);
return ret;
}
dst_kernel = hvs->dlist + space->start;
for (i = 0; i < VC4_KERNEL_DWORDS; i++) {
if (i < VC4_LINEAR_PHASE_KERNEL_DWORDS)
writel(kernel[i], &dst_kernel[i]);
else {
writel(kernel[VC4_KERNEL_DWORDS - i - 1],
&dst_kernel[i]);
}
}
return 0;
}
static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
struct drm_device *drm = dev_get_drvdata(master);
struct vc4_dev *vc4 = drm->dev_private;
struct vc4_hvs *hvs = NULL;
int ret;
hvs = devm_kzalloc(&pdev->dev, sizeof(*hvs), GFP_KERNEL);
if (!hvs)
......@@ -119,6 +183,33 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
hvs->dlist = hvs->regs + SCALER_DLIST_START;
spin_lock_init(&hvs->mm_lock);
/* Set up the HVS display list memory manager. We never
* overwrite the setup from the bootloader (just 128b out of
* our 16K), since we don't want to scramble the screen when
* transitioning from the firmware's boot setup to runtime.
*/
drm_mm_init(&hvs->dlist_mm,
HVS_BOOTLOADER_DLIST_END,
(SCALER_DLIST_SIZE >> 2) - HVS_BOOTLOADER_DLIST_END);
/* Set up the HVS LBM memory manager. We could have some more
* complicated data structure that allowed reuse of LBM areas
* between planes when they don't overlap on the screen, but
* for now we just allocate globally.
*/
drm_mm_init(&hvs->lbm_mm, 0, 96 * 1024);
/* Upload filter kernels. We only have the one for now, so we
* keep it 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;
vc4->hvs = hvs;
return 0;
}
......@@ -129,6 +220,12 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master,
struct drm_device *drm = dev_get_drvdata(master);
struct vc4_dev *vc4 = drm->dev_private;
if (vc4->hvs->mitchell_netravali_filter.allocated)
drm_mm_remove_node(&vc4->hvs->mitchell_netravali_filter);
drm_mm_takedown(&vc4->hvs->dlist_mm);
drm_mm_takedown(&vc4->hvs->lbm_mm);
vc4->hvs = NULL;
}
......
......@@ -49,6 +49,15 @@ vc4_atomic_complete_commit(struct vc4_commit *c)
drm_atomic_helper_commit_modeset_enables(dev, state);
/* Make sure that drm_atomic_helper_wait_for_vblanks()
* actually waits for vblank. If we're doing a full atomic
* modeset (as opposed to a vc4_update_plane() short circuit),
* then we need to wait for scanout to be done with our
* display lists before we free it and potentially reallocate
* and overwrite the dlist memory with a new modeset.
*/
state->legacy_cursor_update = false;
drm_atomic_helper_wait_for_vblanks(dev, state);
drm_atomic_helper_cleanup_planes(dev, state);
......
This diff is collapsed.
......@@ -503,7 +503,12 @@ enum hvs_pixel_format {
HVS_PIXEL_FORMAT_RGB888 = 5,
HVS_PIXEL_FORMAT_RGBA6666 = 6,
/* 32bpp */
HVS_PIXEL_FORMAT_RGBA8888 = 7
HVS_PIXEL_FORMAT_RGBA8888 = 7,
HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE = 8,
HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE = 9,
HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE = 10,
HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE = 11,
};
/* Note: the LSB is the rightmost character shown. Only valid for
......@@ -536,6 +541,21 @@ enum hvs_pixel_format {
#define SCALER_CTL0_ORDER_MASK VC4_MASK(14, 13)
#define SCALER_CTL0_ORDER_SHIFT 13
#define SCALER_CTL0_SCL1_MASK VC4_MASK(10, 8)
#define SCALER_CTL0_SCL1_SHIFT 8
#define SCALER_CTL0_SCL0_MASK VC4_MASK(7, 5)
#define SCALER_CTL0_SCL0_SHIFT 5
#define SCALER_CTL0_SCL_H_PPF_V_PPF 0
#define SCALER_CTL0_SCL_H_TPZ_V_PPF 1
#define SCALER_CTL0_SCL_H_PPF_V_TPZ 2
#define SCALER_CTL0_SCL_H_TPZ_V_TPZ 3
#define SCALER_CTL0_SCL_H_PPF_V_NONE 4
#define SCALER_CTL0_SCL_H_NONE_V_PPF 5
#define SCALER_CTL0_SCL_H_NONE_V_TPZ 6
#define SCALER_CTL0_SCL_H_TPZ_V_NONE 7
/* Set to indicate no scaling. */
#define SCALER_CTL0_UNITY BIT(4)
......@@ -551,6 +571,12 @@ enum hvs_pixel_format {
#define SCALER_POS0_START_X_MASK VC4_MASK(11, 0)
#define SCALER_POS0_START_X_SHIFT 0
#define SCALER_POS1_SCL_HEIGHT_MASK VC4_MASK(27, 16)
#define SCALER_POS1_SCL_HEIGHT_SHIFT 16
#define SCALER_POS1_SCL_WIDTH_MASK VC4_MASK(11, 0)
#define SCALER_POS1_SCL_WIDTH_SHIFT 0
#define SCALER_POS2_ALPHA_MODE_MASK VC4_MASK(31, 30)
#define SCALER_POS2_ALPHA_MODE_SHIFT 30
#define SCALER_POS2_ALPHA_MODE_PIPELINE 0
......@@ -564,6 +590,80 @@ enum hvs_pixel_format {
#define SCALER_POS2_WIDTH_MASK VC4_MASK(11, 0)
#define SCALER_POS2_WIDTH_SHIFT 0
/* Color Space Conversion words. Some values are S2.8 signed
* integers, except that the 2 integer bits map as {0x0: 0, 0x1: 1,
* 0x2: 2, 0x3: -1}
*/
/* bottom 8 bits of S2.8 contribution of Cr to Blue */
#define SCALER_CSC0_COEF_CR_BLU_MASK VC4_MASK(31, 24)
#define SCALER_CSC0_COEF_CR_BLU_SHIFT 24
/* Signed offset to apply to Y before CSC. (Y' = Y + YY_OFS) */
#define SCALER_CSC0_COEF_YY_OFS_MASK VC4_MASK(23, 16)
#define SCALER_CSC0_COEF_YY_OFS_SHIFT 16
/* Signed offset to apply to CB before CSC (Cb' = Cb - 128 + CB_OFS). */
#define SCALER_CSC0_COEF_CB_OFS_MASK VC4_MASK(15, 8)
#define SCALER_CSC0_COEF_CB_OFS_SHIFT 8
/* Signed offset to apply to CB before CSC (Cr' = Cr - 128 + CR_OFS). */
#define SCALER_CSC0_COEF_CR_OFS_MASK VC4_MASK(7, 0)
#define SCALER_CSC0_COEF_CR_OFS_SHIFT 0
#define SCALER_CSC0_ITR_R_601_5 0x00f00000
#define SCALER_CSC0_ITR_R_709_3 0x00f00000
#define SCALER_CSC0_JPEG_JFIF 0x00000000
/* S2.8 contribution of Cb to Green */
#define SCALER_CSC1_COEF_CB_GRN_MASK VC4_MASK(31, 22)
#define SCALER_CSC1_COEF_CB_GRN_SHIFT 22
/* S2.8 contribution of Cr to Green */
#define SCALER_CSC1_COEF_CR_GRN_MASK VC4_MASK(21, 12)
#define SCALER_CSC1_COEF_CR_GRN_SHIFT 12
/* S2.8 contribution of Y to all of RGB */
#define SCALER_CSC1_COEF_YY_ALL_MASK VC4_MASK(11, 2)
#define SCALER_CSC1_COEF_YY_ALL_SHIFT 2
/* top 2 bits of S2.8 contribution of Cr to Blue */
#define SCALER_CSC1_COEF_CR_BLU_MASK VC4_MASK(1, 0)
#define SCALER_CSC1_COEF_CR_BLU_SHIFT 0
#define SCALER_CSC1_ITR_R_601_5 0xe73304a8
#define SCALER_CSC1_ITR_R_709_3 0xf2b784a8
#define SCALER_CSC1_JPEG_JFIF 0xea34a400
/* S2.8 contribution of Cb to Red */
#define SCALER_CSC2_COEF_CB_RED_MASK VC4_MASK(29, 20)
#define SCALER_CSC2_COEF_CB_RED_SHIFT 20
/* S2.8 contribution of Cr to Red */
#define SCALER_CSC2_COEF_CR_RED_MASK VC4_MASK(19, 10)
#define SCALER_CSC2_COEF_CR_RED_SHIFT 10
/* S2.8 contribution of Cb to Blue */
#define SCALER_CSC2_COEF_CB_BLU_MASK VC4_MASK(19, 10)
#define SCALER_CSC2_COEF_CB_BLU_SHIFT 10
#define SCALER_CSC2_ITR_R_601_5 0x00066204
#define SCALER_CSC2_ITR_R_709_3 0x00072a1c
#define SCALER_CSC2_JPEG_JFIF 0x000599c5
#define SCALER_TPZ0_VERT_RECALC BIT(31)
#define SCALER_TPZ0_SCALE_MASK VC4_MASK(28, 8)
#define SCALER_TPZ0_SCALE_SHIFT 8
#define SCALER_TPZ0_IPHASE_MASK VC4_MASK(7, 0)
#define SCALER_TPZ0_IPHASE_SHIFT 0
#define SCALER_TPZ1_RECIP_MASK VC4_MASK(15, 0)
#define SCALER_TPZ1_RECIP_SHIFT 0
/* Skips interpolating coefficients to 64 phases, so just 8 are used.
* Required for nearest neighbor.
*/
#define SCALER_PPF_NOINTERP BIT(31)
/* Replaes the highest valued coefficient with one that makes all 4
* sum to unity.
*/
#define SCALER_PPF_AGC BIT(30)
#define SCALER_PPF_SCALE_MASK VC4_MASK(24, 8)
#define SCALER_PPF_SCALE_SHIFT 8
#define SCALER_PPF_IPHASE_MASK VC4_MASK(6, 0)
#define SCALER_PPF_IPHASE_SHIFT 0
#define SCALER_PPF_KERNEL_OFFSET_MASK VC4_MASK(13, 0)
#define SCALER_PPF_KERNEL_OFFSET_SHIFT 0
#define SCALER_PPF_KERNEL_UNCACHED BIT(31)
#define SCALER_SRC_PITCH_MASK VC4_MASK(15, 0)
#define SCALER_SRC_PITCH_SHIFT 0
......
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