[PATCH 1/3] staging: xm2mvscale: Driver support for Xilinx M2M Video Scaler

Rohit Athavale rohit.athavale at xilinx.com
Wed Feb 21 02:40:33 UTC 2018


This commit adds driver support for the pre-release Xilinx M2M Video
Scaler IP. There are three parts to this driver :

 - The Hardware/IP layer that reads and writes register of the IP
   contained in the scaler_hw_xm2m.c
 - The set of ioctls that applications would need to know contained
   in ioctl_xm2mvsc.h
 - The char driver that consumes the IP layer in xm2m_vscale.c

Signed-off-by: Rohit Athavale <rohit.athavale at xilinx.com>
---
 drivers/staging/Kconfig                       |   2 +
 drivers/staging/Makefile                      |   1 +
 drivers/staging/xm2mvscale/Kconfig            |  12 +
 drivers/staging/xm2mvscale/Makefile           |   3 +
 drivers/staging/xm2mvscale/ioctl_xm2mvsc.h    | 134 ++++
 drivers/staging/xm2mvscale/scaler_hw_xm2m.c   | 945 ++++++++++++++++++++++++++
 drivers/staging/xm2mvscale/scaler_hw_xm2m.h   | 152 +++++
 drivers/staging/xm2mvscale/xm2m_vscale.c      | 783 +++++++++++++++++++++
 drivers/staging/xm2mvscale/xvm2mvsc_hw_regs.h | 204 ++++++
 9 files changed, 2236 insertions(+)
 create mode 100644 drivers/staging/xm2mvscale/Kconfig
 create mode 100644 drivers/staging/xm2mvscale/Makefile
 create mode 100644 drivers/staging/xm2mvscale/ioctl_xm2mvsc.h
 create mode 100644 drivers/staging/xm2mvscale/scaler_hw_xm2m.c
 create mode 100644 drivers/staging/xm2mvscale/scaler_hw_xm2m.h
 create mode 100644 drivers/staging/xm2mvscale/xm2m_vscale.c
 create mode 100644 drivers/staging/xm2mvscale/xvm2mvsc_hw_regs.h

diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index e95ab68..3ee3a3e 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -122,4 +122,6 @@ source "drivers/staging/vboxvideo/Kconfig"

 source "drivers/staging/pi433/Kconfig"

+source "drivers/staging/xm2mvscale/Kconfig"
+
 endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index af8cd6a..29ce417 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -52,3 +52,4 @@ obj-$(CONFIG_BCM2835_VCHIQ)   += vc04_services/
 obj-$(CONFIG_CRYPTO_DEV_CCREE) += ccree/
 obj-$(CONFIG_DRM_VBOXVIDEO)    += vboxvideo/
 obj-$(CONFIG_PI433)            += pi433/
+obj-$(CONFIG_XILINX_M2M_VSC)   += xm2mvscale/
diff --git a/drivers/staging/xm2mvscale/Kconfig b/drivers/staging/xm2mvscale/Kconfig
new file mode 100644
index 0000000..68ccbca
--- /dev/null
+++ b/drivers/staging/xm2mvscale/Kconfig
@@ -0,0 +1,12 @@
+config XILINX_M2M_VSC
+       tristate "Xilinx M2M Video Scaler"
+       depends on ARCH_ZYNQMP && OF
+       select DMA_SHARED_BUFFER
+       ---help---
+         This driver is developed for Xilinx M2M Video Scaler IP,
+         designed to allow passage of frame buffers from the source
+         kernel sub-system, apply video scaling and forward to the
+         sink kernel sub-system.
+
+         To compile this driver as a module, choose M here.
+         If unsure, choose N.
diff --git a/drivers/staging/xm2mvscale/Makefile b/drivers/staging/xm2mvscale/Makefile
new file mode 100644
index 0000000..ec777e1
--- /dev/null
+++ b/drivers/staging/xm2mvscale/Makefile
@@ -0,0 +1,3 @@
+xm2m_vscale_drv-y := scaler_hw_xm2m.o
+xm2m_vscale_drv-y += xm2m_vscale.o
+obj-$(CONFIG_XILINX_M2M_VSC) += xm2m_vscale_drv.o
diff --git a/drivers/staging/xm2mvscale/ioctl_xm2mvsc.h b/drivers/staging/xm2mvscale/ioctl_xm2mvsc.h
new file mode 100644
index 0000000..03bd7ab
--- /dev/null
+++ b/drivers/staging/xm2mvscale/ioctl_xm2mvsc.h
@@ -0,0 +1,134 @@
+/*
+ * Xilinx Memory-to-Memory Video Scaler IP
+ *
+ * Copyright (C) 2018 Xilinx, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+ */
+#ifndef __IOCTL_XM2MVSC_H__
+#define __IOCTL_XM2MVSC_H__
+
+/* Xilinx Video Specific Color/Pixel Formats */
+enum xm2mvsc_pix_fmt {
+       XILINX_FRMBUF_FMT_RGBX8 = 10,
+       XILINX_FRMBUF_FMT_YUVX8,
+       XILINX_FRMBUF_FMT_YUYV8,
+       XILINX_FRMBUF_FMT_RGBA8,
+       XILINX_FRMBUF_FMT_YUVA8,
+       XILINX_FRMBUF_FMT_RGBX10,
+       XILINX_FRMBUF_FMT_YUVX10,
+       /* RGB565 takes the value of 17 */
+       XILINX_FRMBUF_FMT_Y_UV8 = 18,
+       XILINX_FRMBUF_FMT_Y_UV8_420,
+       XILINX_FRMBUF_FMT_RGB8,
+       XILINX_FRMBUF_FMT_YUV8,
+       XILINX_FRMBUF_FMT_Y_UV10,
+       XILINX_FRMBUF_FMT_Y_UV10_420,
+       XILINX_FRMBUF_FMT_Y8,
+       XILINX_FRMBUF_FMT_Y10,
+       XILINX_FRMBUF_FMT_BGRA8,
+       XILINX_FRMBUF_FMT_BGRX8,
+       XILINX_FRMBUF_FMT_UYVY8,
+       XILINX_FRMBUF_FMT_BGR8,
+};
+
+/* struct xm2mvsc_qdata - Struct to enqueue a descriptor
+ * @srcbuf_ht: Height of source buffer
+ * @srcbuf_wt: Width of source buffer
+ * @srcbuf_bpp: Bytes per pixel of source buffer
+ * @srcbuf_cft: Color/Pixel format of source buffer
+ * @srcbuf_size: Size of the source buffer requested
+ * @srcbuf_mmap: Identify if srcbuf is mmap'ed
+ * @srcbuf_stride: Stride of the source buffer
+ * @dstbuf_ht: Height of destination buffer
+ * @dstbuf_wt: Width of destination buffer
+ * @dstbuf_bpp: Bytes per pixel of destination buffer
+ * @dstbuf_cft: Color/Pixel format of source buffer
+ * @dstbuf_size: Size of the source buffer requested
+ * @dstbuf_mmap: Identify if srcbuf is mmap'ed
+ * @dstbuf_stride: Stride of the source buffer
+ * @dstbuf_cft: Color Format of destination buffer
+ * @desc_id: Keep a track of the descriptors
+ */
+struct xm2mvsc_qdata {
+       /* Source information */
+       u32 srcbuf_ht;
+       u32 srcbuf_wt;
+       u32 srcbuf_bpp;
+       enum xm2mvsc_pix_fmt srcbuf_cft;
+       size_t srcbuf_size;
+       /* srcbuf_mmap : For use by the library, do not touch */
+       bool srcbuf_mmap;
+       u16 srcbuf_stride;
+       /* Destination information */
+       u32 dstbuf_ht;
+       u32 dstbuf_wt;
+       u32 dstbuf_bpp;
+       enum xm2mvsc_pix_fmt dstbuf_cft;
+       size_t dstbuf_size;
+       /* dstbuf_mmap : For use by the library, do not touch */
+       bool dstbuf_mmap;
+       u16 dstbuf_stride;
+       u32 desc_id;
+};
+
+/**
+ * struct xm2mvsc_dqdata - Struct to dequeue a completed descriptor
+ * @desc_id: Descriptor ID that needs to be dequeued
+ */
+struct xm2mvsc_dqdata {
+       u32 desc_id;
+};
+
+/**
+ * struct xm2mvsc_batch - Struct to specify the batch size
+ * @batch_size: Number of channels the scaler should operate per scaling op
+ */
+struct xm2mvsc_batch {
+       u16 batch_size;
+};
+
+/* XM2MVSCALE IOCTL LIST */
+#define XM2MVSC_MAGIC          'X'
+
+/*
+ * DOC: XM2MVSC_ENQUEUE
+ * Enqueue  a descriptor that describes the scaling operation for a channel.
+ * Returns the descriptor ID
+ */
+#define XM2MVSC_ENQUEUE                _IOWR(XM2MVSC_MAGIC, 1, struct xm2mvsc_qdata *)
+
+/*
+ * DOC: XM2MVSC_START
+ * Start the M2M Scaler IP. Driver will operate on descriptors in the
+ * pending list.
+ */
+#define XM2MVSC_START          _IO(XM2MVSC_MAGIC, 2)
+
+/*
+ * DOC: XM2MVSC_DEQUEUE
+ * Dequeue a descriptor by providing the driver with information about the
+ * descriptor that needs to be dequeued.
+ */
+#define XM2MVSC_DEQUEUE                _IOW(XM2MVSC_MAGIC, 3, struct xm2mvsc_dqdata *)
+
+/*
+ * DOC: XM2MVSC_STOP
+ * Stop the M2M Scaler IP. Clear driver state and reset the IP.
+ */
+#define XM2MVSC_STOP           _IO(XM2MVSC_MAGIC, 4)
+
+/*
+ * DOC: XM2MVSC_FREE
+ * Free a descriptor after being dequeued via XM2MVSC_DEQUEUE ioctl.
+ */
+#define XM2MVSC_FREE           _IOW(XM2MVSC_MAGIC, 5, struct xm2mvsc_dqdata *)
+
+/*
+ * DOC: XM2MVSC_BATCH_SIZE
+ * Set the batch size that the M2M Scaler IP should use when programming the
+ * scaler. Driver may reject the incoming batch size.
+ */
+#define XM2MVSC_BATCH_SIZE     _IOW(XM2MVSC_MAGIC, 6, struct xm2mvsc_batch *)
+
+#endif /* __IOCTL_XM2MVSC_H__ */
diff --git a/drivers/staging/xm2mvscale/scaler_hw_xm2m.c b/drivers/staging/xm2mvscale/scaler_hw_xm2m.c
new file mode 100644
index 0000000..a6e35ae
--- /dev/null
+++ b/drivers/staging/xm2mvscale/scaler_hw_xm2m.c
@@ -0,0 +1,945 @@
+/*
+ * Xilinx Memory-to-Memory Video Scaler IP
+ *
+ * Copyright (C) 2018 Xilinx, Inc. All rights reserved.
+ *
+ * Description:
+ * This driver is developed for the Xilinx M2M Video Scaler IP. It allows
+ * userspace to access the IP registers and takes care of interrupt handling
+ * and framebuffer programming within the driver.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/bitops.h>
+
+#include "xvm2mvsc_hw_regs.h"
+#include "scaler_hw_xm2m.h"
+
+/* H-scaler coefficients for 6, 8, 10 and 12 tap filters */
+static const u16
+xhsc_coeff_taps6[XSCALER_MAX_PHASES][XV_SCALER_TAPS_6] = {
+       {  -132,   236,  3824,   236,  -132,    64, },
+       {  -116,   184,  3816,   292,  -144,    64, },
+       {  -100,   132,  3812,   348,  -160,    64, },
+       {   -88,    84,  3808,   404,  -176,    64, },
+       {   -72,    36,  3796,   464,  -192,    64, },
+       {   -60,    -8,  3780,   524,  -208,    68, },
+       {   -48,   -52,  3768,   588,  -228,    68, },
+       {   -32,   -96,  3748,   652,  -244,    68, },
+       {   -20,  -136,  3724,   716,  -260,    72, },
+       {    -8,  -172,  3696,   784,  -276,    72, },
+       {     0,  -208,  3676,   848,  -292,    72, },
+       {    12,  -244,  3640,   920,  -308,    76, },
+       {    20,  -276,  3612,   988,  -324,    76, },
+       {    32,  -304,  3568,  1060,  -340,    80, },
+       {    40,  -332,  3532,  1132,  -356,    80, },
+       {    48,  -360,  3492,  1204,  -372,    84, },
+       {    56,  -384,  3448,  1276,  -388,    88, },
+       {    64,  -408,  3404,  1352,  -404,    88, },
+       {    72,  -428,  3348,  1428,  -416,    92, },
+       {    76,  -448,  3308,  1500,  -432,    92, },
+       {    84,  -464,  3248,  1576,  -444,    96, },
+       {    88,  -480,  3200,  1652,  -460,    96, },
+       {    92,  -492,  3140,  1728,  -472,   100, },
+       {    96,  -504,  3080,  1804,  -484,   104, },
+       {   100,  -516,  3020,  1880,  -492,   104, },
+       {   104,  -524,  2956,  1960,  -504,   104, },
+       {   104,  -532,  2892,  2036,  -512,   108, },
+       {   108,  -540,  2832,  2108,  -520,   108, },
+       {   108,  -544,  2764,  2184,  -528,   112, },
+       {   112,  -544,  2688,  2260,  -532,   112, },
+       {   112,  -548,  2624,  2336,  -540,   112, },
+       {   112,  -548,  2556,  2408,  -544,   112, },
+       {   112,  -544,  2480,  2480,  -544,   112, },
+       {   112,  -544,  2408,  2556,  -548,   112, },
+       {   112,  -540,  2336,  2624,  -548,   112, },
+       {   112,  -532,  2260,  2688,  -544,   112, },
+       {   112,  -528,  2184,  2764,  -544,   108, },
+       {   108,  -520,  2108,  2832,  -540,   108, },
+       {   108,  -512,  2036,  2892,  -532,   104, },
+       {   104,  -504,  1960,  2956,  -524,   104, },
+       {   104,  -492,  1880,  3020,  -516,   100, },
+       {   104,  -484,  1804,  3080,  -504,    96, },
+       {   100,  -472,  1728,  3140,  -492,    92, },
+       {    96,  -460,  1652,  3200,  -480,    88, },
+       {    96,  -444,  1576,  3248,  -464,    84, },
+       {    92,  -432,  1500,  3308,  -448,    76, },
+       {    92,  -416,  1428,  3348,  -428,    72, },
+       {    88,  -404,  1352,  3404,  -408,    64, },
+       {    88,  -388,  1276,  3448,  -384,    56, },
+       {    84,  -372,  1204,  3492,  -360,    48, },
+       {    80,  -356,  1132,  3532,  -332,    40, },
+       {    80,  -340,  1060,  3568,  -304,    32, },
+       {    76,  -324,   988,  3612,  -276,    20, },
+       {    76,  -308,   920,  3640,  -244,    12, },
+       {    72,  -292,   848,  3676,  -208,     0, },
+       {    72,  -276,   784,  3696,  -172,    -8, },
+       {    72,  -260,   716,  3724,  -136,   -20, },
+       {    68,  -244,   652,  3748,   -96,   -32, },
+       {    68,  -228,   588,  3768,   -52,   -48, },
+       {    68,  -208,   524,  3780,    -8,   -60, },
+       {    64,  -192,   464,  3796,    36,   -72, },
+       {    64,  -176,   404,  3808,    84,   -88, },
+       {    64,  -160,   348,  3812,   132,  -100, },
+       {    64,  -144,   292,  3816,   184,  -116, }
+};
+
+static const u16
+xhsc_coeff_taps8[XSCALER_MAX_PHASES][XV_SCALER_TAPS_8] = {
+       {-5, 309, 1023, 1445, 1034, 317, -3, -24, },
+       {-6, 300, 1011, 1445, 1045, 326, -1, -24, },
+       {-7, 291, 1000, 1444, 1056, 336, 0, -24, },
+       {-9, 282, 988, 1444, 1067, 345, 2, -24, },
+       {-10, 274, 977, 1443, 1078, 354, 4, -24, },
+       {-11, 266, 965, 1441, 1089, 364, 6, -24, },
+       {-12, 258, 953, 1440, 1100, 373, 8, -24, },
+       {-13, 250, 942, 1438, 1110, 383, 10, -24, },
+       {-14, 242, 930, 1437, 1121, 393, 12, -24, },
+       {-15, 234, 918, 1434, 1131, 403, 14, -24, },
+       {-16, 226, 906, 1432, 1142, 413, 17, -24, },
+       {-17, 219, 894, 1430, 1152, 423, 19, -24, },
+       {-17, 211, 882, 1427, 1162, 433, 22, -24, },
+       {-18, 204, 870, 1424, 1172, 443, 24, -24, },
+       {-19, 197, 858, 1420, 1182, 454, 27, -24, },
+       {-19, 190, 846, 1417, 1191, 464, 30, -24, },
+       {-20, 183, 834, 1413, 1201, 475, 33, -24, },
+       {-20, 176, 822, 1409, 1210, 486, 36, -24, },
+       {-21, 170, 810, 1405, 1220, 497, 39, -24, },
+       {-21, 163, 798, 1401, 1229, 507, 42, -24, },
+       {-22, 157, 786, 1396, 1238, 518, 46, -24, },
+       {-22, 151, 774, 1392, 1247, 529, 49, -24, },
+       {-22, 144, 762, 1387, 1255, 540, 53, -24, },
+       {-23, 139, 750, 1382, 1264, 552, 57, -24, },
+       {-23, 133, 738, 1376, 1272, 563, 60, -24, },
+       {-23, 127, 726, 1371, 1280, 574, 64, -24, },
+       {-23, 121, 714, 1365, 1288, 586, 69, -24, },
+       {-23, 116, 703, 1359, 1296, 597, 73, -24, },
+       {-24, 111, 691, 1353, 1304, 609, 77, -24, },
+       {-24, 105, 679, 1346, 1312, 620, 81, -24, },
+       {-24, 100, 667, 1340, 1319, 632, 86, -24, },
+       {-24, 96, 655, 1333, 1326, 644, 91, -24, },
+       {-24, 91, 644, 1326, 1333, 655, 96, -24, },
+       {-24, 86, 632, 1319, 1340, 667, 100, -24, },
+       {-24, 81, 620, 1312, 1346, 679, 105, -24, },
+       {-24, 77, 609, 1304, 1353, 691, 111, -24, },
+       {-24, 73, 597, 1296, 1359, 703, 116, -23, },
+       {-24, 69, 586, 1288, 1365, 714, 121, -23, },
+       {-24, 64, 574, 1280, 1371, 726, 127, -23, },
+       {-24, 60, 563, 1272, 1376, 738, 133, -23, },
+       {-24, 57, 552, 1264, 1382, 750, 139, -23, },
+       {-24, 53, 540, 1255, 1387, 762, 144, -22, },
+       {-24, 49, 529, 1247, 1392, 774, 151, -22, },
+       {-24, 46, 518, 1238, 1396, 786, 157, -22, },
+       {-24, 42, 507, 1229, 1401, 798, 163, -21, },
+       {-24, 39, 497, 1220, 1405, 810, 170, -21, },
+       {-24, 36, 486, 1210, 1409, 822, 176, -20, },
+       {-24, 33, 475, 1201, 1413, 834, 183, -20, },
+       {-24, 30, 464, 1191, 1417, 846, 190, -19, },
+       {-24, 27, 454, 1182, 1420, 858, 197, -19, },
+       {-24, 24, 443, 1172, 1424, 870, 204, -18, },
+       {-24, 22, 433, 1162, 1427, 882, 211, -17, },
+       {-24, 19, 423, 1152, 1430, 894, 219, -17, },
+       {-24, 17, 413, 1142, 1432, 906, 226, -16, },
+       {-24, 14, 403, 1131, 1434, 918, 234, -15, },
+       {-24, 12, 393, 1121, 1437, 930, 242, -14, },
+       {-24, 10, 383, 1110, 1438, 942, 250, -13, },
+       {-24, 8, 373, 1100, 1440, 953, 258, -12, },
+       {-24, 6, 364, 1089, 1441, 965, 266, -11, },
+       {-24, 4, 354, 1078, 1443, 977, 274, -10, },
+       {-24, 2, 345, 1067, 1444, 988, 282, -9, },
+       {-24, 0, 336, 1056, 1444, 1000, 291, -7, },
+       {-24, -1, 326, 1045, 1445, 1011, 300, -6, },
+       {-24, -3, 317, 1034, 1445, 1023, 309, -5, },
+};
+
+static const u16
+xhsc_coeff_taps10[XSCALER_MAX_PHASES][XV_SCALER_TAPS_10] = {
+       {59, 224, 507, 790, 911, 793, 512, 227, 61, 13, },
+       {58, 220, 502, 786, 911, 797, 516, 231, 62, 13, },
+       {56, 216, 497, 783, 911, 800, 521, 235, 64, 13, },
+       {55, 213, 492, 779, 910, 804, 526, 238, 65, 13, },
+       {54, 209, 487, 775, 910, 807, 531, 242, 67, 14, },
+       {52, 206, 482, 772, 910, 810, 536, 246, 69, 14, },
+       {51, 202, 477, 768, 909, 813, 541, 250, 70, 14, },
+       {50, 199, 473, 764, 909, 817, 545, 254, 72, 14, },
+       {48, 195, 468, 760, 908, 820, 550, 258, 74, 15, },
+       {47, 192, 463, 756, 908, 823, 555, 262, 76, 15, },
+       {46, 188, 458, 752, 907, 826, 560, 266, 78, 15, },
+       {45, 185, 453, 748, 906, 829, 565, 270, 79, 16, },
+       {44, 182, 448, 744, 906, 832, 569, 274, 81, 16, },
+       {42, 179, 444, 740, 905, 835, 574, 278, 83, 16, },
+       {41, 175, 439, 736, 904, 837, 579, 282, 85, 17, },
+       {40, 172, 434, 732, 903, 840, 584, 286, 87, 17, },
+       {39, 169, 429, 728, 902, 843, 589, 290, 89, 18, },
+       {38, 166, 425, 724, 901, 846, 593, 294, 91, 18, },
+       {37, 163, 420, 720, 900, 848, 598, 298, 93, 18, },
+       {36, 160, 415, 716, 899, 851, 603, 302, 95, 19, },
+       {35, 157, 410, 711, 897, 854, 608, 307, 98, 19, },
+       {34, 154, 406, 707, 896, 856, 612, 311, 100, 20, },
+       {33, 151, 401, 703, 895, 859, 617, 315, 102, 20, },
+       {33, 148, 396, 698, 893, 861, 622, 320, 104, 21, },
+       {32, 145, 392, 694, 892, 863, 626, 324, 107, 21, },
+       {31, 142, 387, 690, 890, 866, 631, 328, 109, 22, },
+       {30, 140, 382, 685, 889, 868, 636, 333, 111, 23, },
+       {29, 137, 378, 681, 887, 870, 640, 337, 114, 23, },
+       {28, 134, 373, 677, 886, 872, 645, 342, 116, 24, },
+       {28, 131, 369, 672, 884, 874, 649, 346, 119, 24, },
+       {27, 129, 364, 668, 882, 876, 654, 350, 121, 25, },
+       {26, 126, 359, 663, 880, 878, 659, 355, 124, 26, },
+       {26, 124, 355, 659, 878, 880, 663, 359, 126, 26, },
+       {25, 121, 350, 654, 876, 882, 668, 364, 129, 27, },
+       {24, 119, 346, 649, 874, 884, 672, 369, 131, 28, },
+       {24, 116, 342, 645, 872, 886, 677, 373, 134, 28, },
+       {23, 114, 337, 640, 870, 887, 681, 378, 137, 29, },
+       {23, 111, 333, 636, 868, 889, 685, 382, 140, 30, },
+       {22, 109, 328, 631, 866, 890, 690, 387, 142, 31, },
+       {21, 107, 324, 626, 863, 892, 694, 392, 145, 32, },
+       {21, 104, 320, 622, 861, 893, 698, 396, 148, 33, },
+       {20, 102, 315, 617, 859, 895, 703, 401, 151, 33, },
+       {20, 100, 311, 612, 856, 896, 707, 406, 154, 34, },
+       {19, 98, 307, 608, 854, 897, 711, 410, 157, 35, },
+       {19, 95, 302, 603, 851, 899, 716, 415, 160, 36, },
+       {18, 93, 298, 598, 848, 900, 720, 420, 163, 37, },
+       {18, 91, 294, 593, 846, 901, 724, 425, 166, 38, },
+       {18, 89, 290, 589, 843, 902, 728, 429, 169, 39, },
+       {17, 87, 286, 584, 840, 903, 732, 434, 172, 40, },
+       {17, 85, 282, 579, 837, 904, 736, 439, 175, 41, },
+       {16, 83, 278, 574, 835, 905, 740, 444, 179, 42, },
+       {16, 81, 274, 569, 832, 906, 744, 448, 182, 44, },
+       {16, 79, 270, 565, 829, 906, 748, 453, 185, 45, },
+       {15, 78, 266, 560, 826, 907, 752, 458, 188, 46, },
+       {15, 76, 262, 555, 823, 908, 756, 463, 192, 47, },
+       {15, 74, 258, 550, 820, 908, 760, 468, 195, 48, },
+       {14, 72, 254, 545, 817, 909, 764, 473, 199, 50, },
+       {14, 70, 250, 541, 813, 909, 768, 477, 202, 51, },
+       {14, 69, 246, 536, 810, 910, 772, 482, 206, 52, },
+       {14, 67, 242, 531, 807, 910, 775, 487, 209, 54, },
+       {13, 65, 238, 526, 804, 910, 779, 492, 213, 55, },
+       {13, 64, 235, 521, 800, 911, 783, 497, 216, 56, },
+       {13, 62, 231, 516, 797, 911, 786, 502, 220, 58, },
+       {13, 61, 227, 512, 793, 911, 790, 507, 224, 59, },
+};
+
+static const u16
+xhsc_coeff_taps12[XSCALER_MAX_PHASES][XV_SCALER_TAPS_12] = {
+       {48, 143, 307, 504, 667, 730, 669, 507, 310, 145, 49, 18, },
+       {47, 141, 304, 501, 665, 730, 670, 510, 313, 147, 50, 18, },
+       {46, 138, 301, 498, 663, 730, 672, 513, 316, 149, 51, 18, },
+       {45, 136, 298, 495, 661, 730, 674, 516, 319, 151, 52, 18, },
+       {44, 134, 295, 492, 659, 730, 676, 519, 322, 153, 53, 18, },
+       {44, 132, 292, 489, 657, 730, 677, 522, 325, 155, 54, 18, },
+       {43, 130, 289, 486, 655, 729, 679, 525, 328, 157, 55, 19, },
+       {42, 129, 287, 483, 653, 729, 681, 528, 331, 160, 56, 19, },
+       {41, 127, 284, 480, 651, 729, 683, 531, 334, 162, 57, 19, },
+       {40, 125, 281, 477, 648, 729, 684, 534, 337, 164, 58, 19, },
+       {40, 123, 278, 474, 646, 728, 686, 537, 340, 166, 59, 20, },
+       {39, 121, 275, 471, 644, 728, 687, 539, 343, 169, 60, 20, },
+       {38, 119, 272, 468, 642, 727, 689, 542, 346, 171, 61, 20, },
+       {37, 117, 269, 465, 640, 727, 690, 545, 349, 173, 62, 20, },
+       {37, 115, 266, 461, 638, 727, 692, 548, 353, 175, 63, 21, },
+       {36, 114, 264, 458, 635, 726, 693, 551, 356, 178, 65, 21, },
+       {35, 112, 261, 455, 633, 726, 695, 554, 359, 180, 66, 21, },
+       {35, 110, 258, 452, 631, 725, 696, 556, 362, 183, 67, 21, },
+       {34, 108, 255, 449, 628, 724, 698, 559, 365, 185, 68, 22, },
+       {33, 107, 252, 446, 626, 724, 699, 562, 368, 187, 69, 22, },
+       {33, 105, 250, 443, 624, 723, 700, 565, 371, 190, 71, 22, },
+       {32, 103, 247, 440, 621, 723, 702, 567, 374, 192, 72, 23, },
+       {32, 101, 244, 437, 619, 722, 703, 570, 377, 195, 73, 23, },
+       {31, 100, 241, 433, 617, 721, 704, 573, 380, 197, 75, 23, },
+       {31, 98, 239, 430, 614, 720, 705, 576, 383, 200, 76, 24, },
+       {30, 97, 236, 427, 612, 720, 707, 578, 387, 202, 77, 24, },
+       {29, 95, 233, 424, 609, 719, 708, 581, 390, 205, 79, 24, },
+       {29, 93, 231, 421, 607, 718, 709, 584, 393, 207, 80, 25, },
+       {28, 92, 228, 418, 604, 717, 710, 586, 396, 210, 81, 25, },
+       {28, 90, 225, 415, 602, 716, 711, 589, 399, 212, 83, 26, },
+       {27, 89, 223, 412, 599, 715, 712, 591, 402, 215, 84, 26, },
+       {27, 87, 220, 408, 597, 714, 713, 594, 405, 217, 86, 27, },
+       {27, 86, 217, 405, 594, 713, 714, 597, 408, 220, 87, 27, },
+       {26, 84, 215, 402, 591, 712, 715, 599, 412, 223, 89, 27, },
+       {26, 83, 212, 399, 589, 711, 716, 602, 415, 225, 90, 28, },
+       {25, 81, 210, 396, 586, 710, 717, 604, 418, 228, 92, 28, },
+       {25, 80, 207, 393, 584, 709, 718, 607, 421, 231, 93, 29, },
+       {24, 79, 205, 390, 581, 708, 719, 609, 424, 233, 95, 29, },
+       {24, 77, 202, 387, 578, 707, 720, 612, 427, 236, 97, 30, },
+       {24, 76, 200, 383, 576, 705, 720, 614, 430, 239, 98, 31, },
+       {23, 75, 197, 380, 573, 704, 721, 617, 433, 241, 100, 31, },
+       {23, 73, 195, 377, 570, 703, 722, 619, 437, 244, 101, 32, },
+       {23, 72, 192, 374, 567, 702, 723, 621, 440, 247, 103, 32, },
+       {22, 71, 190, 371, 565, 700, 723, 624, 443, 250, 105, 33, },
+       {22, 69, 187, 368, 562, 699, 724, 626, 446, 252, 107, 33, },
+       {22, 68, 185, 365, 559, 698, 724, 628, 449, 255, 108, 34, },
+       {21, 67, 183, 362, 556, 696, 725, 631, 452, 258, 110, 35, },
+       {21, 66, 180, 359, 554, 695, 726, 633, 455, 261, 112, 35, },
+       {21, 65, 178, 356, 551, 693, 726, 635, 458, 264, 114, 36, },
+       {21, 63, 175, 353, 548, 692, 727, 638, 461, 266, 115, 37, },
+       {20, 62, 173, 349, 545, 690, 727, 640, 465, 269, 117, 37, },
+       {20, 61, 171, 346, 542, 689, 727, 642, 468, 272, 119, 38, },
+       {20, 60, 169, 343, 539, 687, 728, 644, 471, 275, 121, 39, },
+       {20, 59, 166, 340, 537, 686, 728, 646, 474, 278, 123, 40, },
+       {19, 58, 164, 337, 534, 684, 729, 648, 477, 281, 125, 40, },
+       {19, 57, 162, 334, 531, 683, 729, 651, 480, 284, 127, 41, },
+       {19, 56, 160, 331, 528, 681, 729, 653, 483, 287, 129, 42, },
+       {19, 55, 157, 328, 525, 679, 729, 655, 486, 289, 130, 43, },
+       {18, 54, 155, 325, 522, 677, 730, 657, 489, 292, 132, 44, },
+       {18, 53, 153, 322, 519, 676, 730, 659, 492, 295, 134, 44, },
+       {18, 52, 151, 319, 516, 674, 730, 661, 495, 298, 136, 45, },
+       {18, 51, 149, 316, 513, 672, 730, 663, 498, 301, 138, 46, },
+       {18, 50, 147, 313, 510, 670, 730, 665, 501, 304, 141, 47, },
+       {18, 49, 145, 310, 507, 669, 730, 667, 504, 307, 143, 48, },
+};
+
+/* V-scaler coefficients for 6, 8, 10 and 12 tap filters */
+static const u16
+xvsc_coeff_taps6[XSCALER_MAX_PHASES][XV_SCALER_TAPS_6] = {
+       {-132, 236, 3824, 236, -132, 64, },
+       {-116, 184, 3816, 292, -144, 64, },
+       {-100, 132, 3812, 348, -160, 64, },
+       {-88, 84, 3808, 404, -176, 64, },
+       {-72, 36, 3796, 464, -192, 64, },
+       {-60, -8, 3780, 524, -208, 68, },
+       {-48, -52, 3768, 588, -228, 68, },
+       {-32, -96, 3748, 652, -244, 68, },
+       {-20, -136, 3724, 716, -260, 72, },
+       {-8,  -172, 3696, 784, -276, 72, },
+       {0, -208, 3676,  848, -292, 72, },
+       {12, -244, 3640, 920, -308, 76, },
+       {20, -276, 3612, 988, -324, 76, },
+       {32, -304, 3568, 1060, -340, 80, },
+       {40, -332, 3532, 1132, -356, 80, },
+       {48, -360, 3492, 1204, -372, 84, },
+       {56, -384, 3448, 1276, -388, 88, },
+       {64, -408, 3404, 1352, -404, 88, },
+       {72, -428, 3348, 1428, -416, 92, },
+       {76, -448, 3308, 1500, -432, 92, },
+       {84, -464, 3248, 1576, -444, 96, },
+       {88, -480, 3200, 1652, -460, 96, },
+       {92, -492, 3140, 1728, -472, 100, },
+       {96, -504, 3080, 1804, -484, 104, },
+       {100, -516, 3020, 1880, -492, 104, },
+       {104, -524, 2956, 1960, -504, 104, },
+       {104, -532, 2892, 2036, -512, 108, },
+       {108, -540, 2832, 2108, -520, 108, },
+       {108, -544, 2764, 2184, -528, 112, },
+       {112, -544, 2688, 2260, -532, 112, },
+       {112, -548, 2624, 2336, -540, 112, },
+       {112, -548, 2556, 2408, -544, 112, },
+       {112, -544, 2480, 2480, -544, 112, },
+       {112, -544, 2408, 2556, -548, 112, },
+       {112, -540, 2336, 2624, -548, 112, },
+       {112, -532, 2260, 2688, -544, 112, },
+       {112, -528, 2184, 2764, -544, 108, },
+       {108, -520, 2108, 2832, -540, 108, },
+       {108, -512, 2036, 2892, -532, 104, },
+       {104, -504, 1960, 2956, -524, 104, },
+       {104, -492, 1880, 3020, -516, 100, },
+       {104, -484, 1804, 3080, -504, 96, },
+       {100, -472, 1728, 3140, -492, 92, },
+       { 96, -460, 1652, 3200, -480, 88, },
+       { 96, -444, 1576, 3248, -464, 84, },
+       { 92, -432, 1500, 3308, -448, 76, },
+       { 92, -416, 1428, 3348, -428, 72, },
+       { 88, -404, 1352, 3404, -408, 64, },
+       { 88, -388, 1276, 3448, -384, 56, },
+       { 84, -372, 1204, 3492, -360, 48, },
+       { 80, -356, 1132, 3532, -332, 40, },
+       { 80, -340, 1060, 3568, -304, 32, },
+       { 76, -324, 988, 3612, -276, 20, },
+       { 76, -308, 920, 3640, -244, 12, },
+       { 72, -292, 848, 3676, -208, 0, },
+       { 72, -276, 784, 3696, -172, -8, },
+       { 72, -260, 716, 3724, -136, -20, },
+       { 68, -244, 652, 3748, -96, -32, },
+       { 68, -228, 588, 3768, -52, -48, },
+       { 68, -208, 524, 3780, -8, -60, },
+       { 64, -192, 464, 3796, 36, -72, },
+       { 64, -176, 404, 3808, 84, -88, },
+       { 64, -160, 348, 3812,  132, -100, },
+       { 64, -144, 292, 3816,  184, -116, }
+};
+
+static const u16
+xvsc_coeff_taps8[XSCALER_MAX_PHASES][XV_SCALER_TAPS_8] = {
+       {-5, 309, 1023, 1445, 1034, 317, -3, -24, },
+       {-6, 300, 1011, 1445, 1045, 326, -1, -24, },
+       {-7, 291, 1000, 1444, 1056, 336, 0, -24, },
+       {-9, 282, 988, 1444, 1067, 345, 2, -24, },
+       {-10, 274, 977, 1443, 1078, 354, 4, -24, },
+       {-11, 266, 965, 1441, 1089, 364, 6, -24, },
+       {-12, 258, 953, 1440, 1100, 373, 8, -24, },
+       {-13, 250, 942, 1438, 1110, 383, 10, -24, },
+       {-14, 242, 930, 1437, 1121, 393, 12, -24, },
+       {-15, 234, 918, 1434, 1131, 403, 14, -24, },
+       {-16, 226, 906, 1432, 1142, 413, 17, -24, },
+       {-17, 219, 894, 1430, 1152, 423, 19, -24, },
+       {-17, 211, 882, 1427, 1162, 433, 22, -24, },
+       {-18, 204, 870, 1424, 1172, 443, 24, -24, },
+       {-19, 197, 858, 1420, 1182, 454, 27, -24, },
+       {-19, 190, 846, 1417, 1191, 464, 30, -24, },
+       {-20, 183, 834, 1413, 1201, 475, 33, -24, },
+       {-20, 176, 822, 1409, 1210, 486, 36, -24, },
+       {-21, 170, 810, 1405, 1220, 497, 39, -24, },
+       {-21, 163, 798, 1401, 1229, 507, 42, -24, },
+       {-22, 157, 786, 1396, 1238, 518, 46, -24, },
+       {-22, 151, 774, 1392, 1247, 529, 49, -24, },
+       {-22, 144, 762, 1387, 1255, 540, 53, -24, },
+       {-23, 139, 750, 1382, 1264, 552, 57, -24, },
+       {-23, 133, 738, 1376, 1272, 563, 60, -24, },
+       {-23, 127, 726, 1371, 1280, 574, 64, -24, },
+       {-23, 121, 714, 1365, 1288, 586, 69, -24, },
+       {-23, 116, 703, 1359, 1296, 597, 73, -24, },
+       {-24, 111, 691, 1353, 1304, 609, 77, -24, },
+       {-24, 105, 679, 1346, 1312, 620, 81, -24, },
+       {-24, 100, 667, 1340, 1319, 632, 86, -24, },
+       {-24, 96, 655, 1333, 1326, 644, 91, -24, },
+       {-24, 91, 644, 1326, 1333, 655, 96, -24, },
+       {-24, 86, 632, 1319, 1340, 667, 100, -24, },
+       {-24, 81, 620, 1312, 1346, 679, 105, -24, },
+       {-24, 77, 609, 1304, 1353, 691, 111, -24, },
+       {-24, 73, 597, 1296, 1359, 703, 116, -23, },
+       {-24, 69, 586, 1288, 1365, 714, 121, -23, },
+       {-24, 64, 574, 1280, 1371, 726, 127, -23, },
+       {-24, 60, 563, 1272, 1376, 738, 133, -23, },
+       {-24, 57, 552, 1264, 1382, 750, 139, -23, },
+       {-24, 53, 540, 1255, 1387, 762, 144, -22, },
+       {-24, 49, 529, 1247, 1392, 774, 151, -22, },
+       {-24, 46, 518, 1238, 1396, 786, 157, -22, },
+       {-24, 42, 507, 1229, 1401, 798, 163, -21, },
+       {-24, 39, 497, 1220, 1405, 810, 170, -21, },
+       {-24, 36, 486, 1210, 1409, 822, 176, -20, },
+       {-24, 33, 475, 1201, 1413, 834, 183, -20, },
+       {-24, 30, 464, 1191, 1417, 846, 190, -19, },
+       {-24, 27, 454, 1182, 1420, 858, 197, -19, },
+       {-24, 24, 443, 1172, 1424, 870, 204, -18, },
+       {-24, 22, 433, 1162, 1427, 882, 211, -17, },
+       {-24, 19, 423, 1152, 1430, 894, 219, -17, },
+       {-24, 17, 413, 1142, 1432, 906, 226, -16, },
+       {-24, 14, 403, 1131, 1434, 918, 234, -15, },
+       {-24, 12, 393, 1121, 1437, 930, 242, -14, },
+       {-24, 10, 383, 1110, 1438, 942, 250, -13, },
+       {-24, 8, 373, 1100, 1440, 953, 258, -12, },
+       {-24, 6, 364, 1089, 1441, 965, 266, -11, },
+       {-24, 4, 354, 1078, 1443, 977, 274, -10, },
+       {-24, 2, 345, 1067, 1444, 988, 282, -9, },
+       {-24, 0, 336, 1056, 1444, 1000, 291, -7, },
+       {-24, -1, 326, 1045, 1445, 1011, 300, -6, },
+       {-24, -3, 317, 1034, 1445, 1023, 309, -5, },
+};
+
+static const u16
+xvsc_coeff_taps10[XSCALER_MAX_PHASES][XV_SCALER_TAPS_10] = {
+       {59, 224, 507, 790, 911, 793, 512, 227, 61, 13, },
+       {58, 220, 502, 786, 911, 797, 516, 231, 62, 13, },
+       {56, 216, 497, 783, 911, 800, 521, 235, 64, 13, },
+       {55, 213, 492, 779, 910, 804, 526, 238, 65, 13, },
+       {54, 209, 487, 775, 910, 807, 531, 242, 67, 14, },
+       {52, 206, 482, 772, 910, 810, 536, 246, 69, 14, },
+       {51, 202, 477, 768, 909, 813, 541, 250, 70, 14, },
+       {50, 199, 473, 764, 909, 817, 545, 254, 72, 14, },
+       {48, 195, 468, 760, 908, 820, 550, 258, 74, 15, },
+       {47, 192, 463, 756, 908, 823, 555, 262, 76, 15, },
+       {46, 188, 458, 752, 907, 826, 560, 266, 78, 15, },
+       {45, 185, 453, 748, 906, 829, 565, 270, 79, 16, },
+       {44, 182, 448, 744, 906, 832, 569, 274, 81, 16, },
+       {42, 179, 444, 740, 905, 835, 574, 278, 83, 16, },
+       {41, 175, 439, 736, 904, 837, 579, 282, 85, 17, },
+       {40, 172, 434, 732, 903, 840, 584, 286, 87, 17, },
+       {39, 169, 429, 728, 902, 843, 589, 290, 89, 18, },
+       {38, 166, 425, 724, 901, 846, 593, 294, 91, 18, },
+       {37, 163, 420, 720, 900, 848, 598, 298, 93, 18, },
+       {36, 160, 415, 716, 899, 851, 603, 302, 95, 19, },
+       {35, 157, 410, 711, 897, 854, 608, 307, 98, 19, },
+       {34, 154, 406, 707, 896, 856, 612, 311, 100, 20, },
+       {33, 151, 401, 703, 895, 859, 617, 315, 102, 20, },
+       {33, 148, 396, 698, 893, 861, 622, 320, 104, 21, },
+       {32, 145, 392, 694, 892, 863, 626, 324, 107, 21, },
+       {31, 142, 387, 690, 890, 866, 631, 328, 109, 22, },
+       {30, 140, 382, 685, 889, 868, 636, 333, 111, 23, },
+       {29, 137, 378, 681, 887, 870, 640, 337, 114, 23, },
+       {28, 134, 373, 677, 886, 872, 645, 342, 116, 24, },
+       {28, 131, 369, 672, 884, 874, 649, 346, 119, 24, },
+       {27, 129, 364, 668, 882, 876, 654, 350, 121, 25, },
+       {26, 126, 359, 663, 880, 878, 659, 355, 124, 26, },
+       {26, 124, 355, 659, 878, 880, 663, 359, 126, 26, },
+       {25, 121, 350, 654, 876, 882, 668, 364, 129, 27, },
+       {24, 119, 346, 649, 874, 884, 672, 369, 131, 28, },
+       {24, 116, 342, 645, 872, 886, 677, 373, 134, 28, },
+       {23, 114, 337, 640, 870, 887, 681, 378, 137, 29, },
+       {23, 111, 333, 636, 868, 889, 685, 382, 140, 30, },
+       {22, 109, 328, 631, 866, 890, 690, 387, 142, 31, },
+       {21, 107, 324, 626, 863, 892, 694, 392, 145, 32, },
+       {21, 104, 320, 622, 861, 893, 698, 396, 148, 33, },
+       {20, 102, 315, 617, 859, 895, 703, 401, 151, 33, },
+       {20, 100, 311, 612, 856, 896, 707, 406, 154, 34, },
+       {19, 98, 307, 608, 854, 897, 711, 410, 157, 35, },
+       {19, 95, 302, 603, 851, 899, 716, 415, 160, 36, },
+       {18, 93, 298, 598, 848, 900, 720, 420, 163, 37, },
+       {18, 91, 294, 593, 846, 901, 724, 425, 166, 38, },
+       {18, 89, 290, 589, 843, 902, 728, 429, 169, 39, },
+       {17, 87, 286, 584, 840, 903, 732, 434, 172, 40, },
+       {17, 85, 282, 579, 837, 904, 736, 439, 175, 41, },
+       {16, 83, 278, 574, 835, 905, 740, 444, 179, 42, },
+       {16, 81, 274, 569, 832, 906, 744, 448, 182, 44, },
+       {16, 79, 270, 565, 829, 906, 748, 453, 185, 45, },
+       {15, 78, 266, 560, 826, 907, 752, 458, 188, 46, },
+       {15, 76, 262, 555, 823, 908, 756, 463, 192, 47, },
+       {15, 74, 258, 550, 820, 908, 760, 468, 195, 48, },
+       {14, 72, 254, 545, 817, 909, 764, 473, 199, 50, },
+       {14, 70, 250, 541, 813, 909, 768, 477, 202, 51, },
+       {14, 69, 246, 536, 810, 910, 772, 482, 206, 52, },
+       {14, 67, 242, 531, 807, 910, 775, 487, 209, 54, },
+       {13, 65, 238, 526, 804, 910, 779, 492, 213, 55, },
+       {13, 64, 235, 521, 800, 911, 783, 497, 216, 56, },
+       {13, 62, 231, 516, 797, 911, 786, 502, 220, 58, },
+       {13, 61, 227, 512, 793, 911, 790, 507, 224, 59, },
+};
+
+static const u16
+xvsc_coeff_taps12[XSCALER_MAX_PHASES][XV_SCALER_TAPS_12] = {
+       {48, 143, 307, 504, 667, 730, 669, 507, 310, 145, 49, 18, },
+       {47, 141, 304, 501, 665, 730, 670, 510, 313, 147, 50, 18, },
+       {46, 138, 301, 498, 663, 730, 672, 513, 316, 149, 51, 18, },
+       {45, 136, 298, 495, 661, 730, 674, 516, 319, 151, 52, 18, },
+       {44, 134, 295, 492, 659, 730, 676, 519, 322, 153, 53, 18, },
+       {44, 132, 292, 489, 657, 730, 677, 522, 325, 155, 54, 18, },
+       {43, 130, 289, 486, 655, 729, 679, 525, 328, 157, 55, 19, },
+       {42, 129, 287, 483, 653, 729, 681, 528, 331, 160, 56, 19, },
+       {41, 127, 284, 480, 651, 729, 683, 531, 334, 162, 57, 19, },
+       {40, 125, 281, 477, 648, 729, 684, 534, 337, 164, 58, 19, },
+       {40, 123, 278, 474, 646, 728, 686, 537, 340, 166, 59, 20, },
+       {39, 121, 275, 471, 644, 728, 687, 539, 343, 169, 60, 20, },
+       {38, 119, 272, 468, 642, 727, 689, 542, 346, 171, 61, 20, },
+       {37, 117, 269, 465, 640, 727, 690, 545, 349, 173, 62, 20, },
+       {37, 115, 266, 461, 638, 727, 692, 548, 353, 175, 63, 21, },
+       {36, 114, 264, 458, 635, 726, 693, 551, 356, 178, 65, 21, },
+       {35, 112, 261, 455, 633, 726, 695, 554, 359, 180, 66, 21, },
+       {35, 110, 258, 452, 631, 725, 696, 556, 362, 183, 67, 21, },
+       {34, 108, 255, 449, 628, 724, 698, 559, 365, 185, 68, 22, },
+       {33, 107, 252, 446, 626, 724, 699, 562, 368, 187, 69, 22, },
+       {33, 105, 250, 443, 624, 723, 700, 565, 371, 190, 71, 22, },
+       {32, 103, 247, 440, 621, 723, 702, 567, 374, 192, 72, 23, },
+       {32, 101, 244, 437, 619, 722, 703, 570, 377, 195, 73, 23, },
+       {31, 100, 241, 433, 617, 721, 704, 573, 380, 197, 75, 23, },
+       {31, 98, 239, 430, 614, 720, 705, 576, 383, 200, 76, 24, },
+       {30, 97, 236, 427, 612, 720, 707, 578, 387, 202, 77, 24, },
+       {29, 95, 233, 424, 609, 719, 708, 581, 390, 205, 79, 24, },
+       {29, 93, 231, 421, 607, 718, 709, 584, 393, 207, 80, 25, },
+       {28, 92, 228, 418, 604, 717, 710, 586, 396, 210, 81, 25, },
+       {28, 90, 225, 415, 602, 716, 711, 589, 399, 212, 83, 26, },
+       {27, 89, 223, 412, 599, 715, 712, 591, 402, 215, 84, 26, },
+       {27, 87, 220, 408, 597, 714, 713, 594, 405, 217, 86, 27, },
+       {27, 86, 217, 405, 594, 713, 714, 597, 408, 220, 87, 27, },
+       {26, 84, 215, 402, 591, 712, 715, 599, 412, 223, 89, 27, },
+       {26, 83, 212, 399, 589, 711, 716, 602, 415, 225, 90, 28, },
+       {25, 81, 210, 396, 586, 710, 717, 604, 418, 228, 92, 28, },
+       {25, 80, 207, 393, 584, 709, 718, 607, 421, 231, 93, 29, },
+       {24, 79, 205, 390, 581, 708, 719, 609, 424, 233, 95, 29, },
+       {24, 77, 202, 387, 578, 707, 720, 612, 427, 236, 97, 30, },
+       {24, 76, 200, 383, 576, 705, 720, 614, 430, 239, 98, 31, },
+       {23, 75, 197, 380, 573, 704, 721, 617, 433, 241, 100, 31, },
+       {23, 73, 195, 377, 570, 703, 722, 619, 437, 244, 101, 32, },
+       {23, 72, 192, 374, 567, 702, 723, 621, 440, 247, 103, 32, },
+       {22, 71, 190, 371, 565, 700, 723, 624, 443, 250, 105, 33, },
+       {22, 69, 187, 368, 562, 699, 724, 626, 446, 252, 107, 33, },
+       {22, 68, 185, 365, 559, 698, 724, 628, 449, 255, 108, 34, },
+       {21, 67, 183, 362, 556, 696, 725, 631, 452, 258, 110, 35, },
+       {21, 66, 180, 359, 554, 695, 726, 633, 455, 261, 112, 35, },
+       {21, 65, 178, 356, 551, 693, 726, 635, 458, 264, 114, 36, },
+       {21, 63, 175, 353, 548, 692, 727, 638, 461, 266, 115, 37, },
+       {20, 62, 173, 349, 545, 690, 727, 640, 465, 269, 117, 37, },
+       {20, 61, 171, 346, 542, 689, 727, 642, 468, 272, 119, 38, },
+       {20, 60, 169, 343, 539, 687, 728, 644, 471, 275, 121, 39, },
+       {20, 59, 166, 340, 537, 686, 728, 646, 474, 278, 123, 40, },
+       {19, 58, 164, 337, 534, 684, 729, 648, 477, 281, 125, 40, },
+       {19, 57, 162, 334, 531, 683, 729, 651, 480, 284, 127, 41, },
+       {19, 56, 160, 331, 528, 681, 729, 653, 483, 287, 129, 42, },
+       {19, 55, 157, 328, 525, 679, 729, 655, 486, 289, 130, 43, },
+       {18, 54, 155, 325, 522, 677, 730, 657, 489, 292, 132, 44, },
+       {18, 53, 153, 322, 519, 676, 730, 659, 492, 295, 134, 44, },
+       {18, 52, 151, 319, 516, 674, 730, 661, 495, 298, 136, 45, },
+       {18, 51, 149, 316, 513, 672, 730, 663, 498, 301, 138, 46, },
+       {18, 50, 147, 313, 510, 670, 730, 665, 501, 304, 141, 47, },
+       {18, 49, 145, 310, 507, 669, 730, 667, 504, 307, 143, 48, },
+};
+
+/* Mask definitions for Low and high 16 bits in a 32 bit number */
+#define XHSC_MASK_LOW_16BITS           GENMASK(15, 0)
+#define XHSC_MASK_HIGH_16BITS          GENMASK(31, 16)
+#define XHSC_MASK_LOW_32BITS           GENMASK(31, 0)
+
+static void
+xv_hscaler_load_ext_coeff(struct xm2m_scaler_hw *xscaler,
+                         const short *coeff, u32 ntaps)
+{
+       unsigned int i, j, pad, offset;
+       const u32 nphases = XSCALER_MAX_PHASES;
+
+       /* Determine if coefficient needs padding (effective vs. max taps) */
+       pad = XV_SCALER_MAX_TAPS - ntaps;
+       offset = pad >> 1;
+
+       memset(xscaler->hscaler_coeff, 0, sizeof(xscaler->hscaler_coeff));
+
+       /* Load coefficients into scaler coefficient table */
+       for (i = 0; i < nphases; i++) {
+               for (j = 0; j < ntaps; ++j)
+                       xscaler->hscaler_coeff[i][j + offset] =
+                                               coeff[i * ntaps + j];
+       }
+}
+
+#define XSCALER_BITSHIFT_16            (16)
+static void xv_hscaler_set_coeff(struct xm2m_scaler_hw *xscaler,
+                                const u32 base_addr)
+{
+       int val, i, j, offset, rd_indx;
+       u32 ntaps = xscaler->num_taps;
+       const u32 nphases = XSCALER_MAX_PHASES;
+
+       offset = (XV_SCALER_MAX_TAPS - ntaps) / 2;
+       for (i = 0; i < nphases; i++) {
+               for (j = 0; j < ntaps / 2; j++) {
+                       rd_indx = j * 2 + offset;
+                       val = (xscaler->hscaler_coeff[i][rd_indx + 1] <<
+                              XSCALER_BITSHIFT_16) |
+                              (xscaler->hscaler_coeff[i][rd_indx] &
+                              XHSC_MASK_LOW_16BITS);
+                        xvip_write(xscaler, base_addr +
+                                   ((i * ntaps / 2 + j) * 4), val);
+               }
+       }
+}
+
+static void
+xv_vscaler_load_ext_coeff(struct xm2m_scaler_hw *xscaler,
+                         const short *coeff, const u32 ntaps)
+{
+       int i, j, pad, offset;
+       const u32 nphases = XSCALER_MAX_PHASES;
+
+       /* Determine if coefficient needs padding (effective vs. max taps) */
+       pad = XV_SCALER_MAX_TAPS - ntaps;
+       offset = pad ? (pad >> 1) : 0;
+
+       /* Zero Entire Array */
+       memset(xscaler->vscaler_coeff, 0, sizeof(xscaler->vscaler_coeff));
+
+       /* Load User defined coefficients into scaler coefficient table */
+       for (i = 0; i < nphases; i++) {
+               for (j = 0; j < ntaps; ++j)
+                       xscaler->vscaler_coeff[i][j + offset] =
+                                               coeff[i * ntaps + j];
+       }
+}
+
+#define XVSC_MASK_LOW_16BITS            GENMASK(15, 0)
+static void xv_vscaler_set_coeff(struct xm2m_scaler_hw *xscaler,
+                                const u32 base_addr)
+{
+       int val, i, j, offset, rd_indx;
+       u32 ntaps   = xscaler->num_taps;
+       const u32 nphases = XSCALER_MAX_PHASES;
+
+       offset = (XV_SCALER_MAX_TAPS - ntaps) / 2;
+
+       for (i = 0; i < nphases; i++) {
+               for (j = 0; j < ntaps / 2; j++) {
+                       rd_indx = j * 2 + offset;
+                       val = (xscaler->vscaler_coeff[i][rd_indx + 1] <<
+                              XSCALER_BITSHIFT_16) |
+                              (xscaler->vscaler_coeff[i][rd_indx] &
+                              XVSC_MASK_LOW_16BITS);
+                       xvip_write(xscaler,
+                                  base_addr + ((i * ntaps / 2 + j) * 4), val);
+               }
+       }
+}
+
+void xm2mvsc_initialize_coeff_banks(struct xm2m_scaler_hw *hw)
+{
+       /* Bank 0 is init as 6 tap filter for 6, 8, 10 & 12 tap filters */
+        xv_hscaler_load_ext_coeff(hw, &xhsc_coeff_taps6[0][0],
+                                  XV_SCALER_TAPS_6);
+        xv_hscaler_set_coeff(hw, XM2MVSC_HFLTCOEFF(0));
+        xv_vscaler_load_ext_coeff(hw, &xvsc_coeff_taps6[0][0],
+                                  XV_SCALER_TAPS_6);
+        xv_vscaler_set_coeff(hw, XM2MVSC_VFLTCOEFF(0));
+        dev_dbg(hw->dev, "%s: Init Bank 0", __func__);
+       /* Bank 1 is init as 8 tap filter for 8, 10 & 12 tap filters */
+       if (hw->num_taps == XV_SCALER_TAPS_8 ||
+           hw->num_taps == XV_SCALER_TAPS_10 ||
+           hw->num_taps == XV_SCALER_TAPS_12) {
+               xv_hscaler_load_ext_coeff(hw, &xhsc_coeff_taps8[0][0],
+                                         XV_SCALER_TAPS_8);
+               xv_hscaler_set_coeff(hw, XM2MVSC_HFLTCOEFF(1));
+               xv_vscaler_load_ext_coeff(hw, &xvsc_coeff_taps8[0][0],
+                                         XV_SCALER_TAPS_8);
+               xv_vscaler_set_coeff(hw, XM2MVSC_VFLTCOEFF(1));
+               dev_dbg(hw->dev, "%s: Init Bank 1", __func__);
+       }
+       /* Bank 2 is init as 8 tap filter for 10 & 12 tap filters */
+       if (hw->num_taps == XV_SCALER_TAPS_10 ||
+           hw->num_taps == XV_SCALER_TAPS_12) {
+               xv_hscaler_load_ext_coeff(hw, &xhsc_coeff_taps10[0][0],
+                                         XV_SCALER_TAPS_10);
+               xv_hscaler_set_coeff(hw, XM2MVSC_HFLTCOEFF(2));
+               xv_vscaler_load_ext_coeff(hw, &xvsc_coeff_taps10[0][0],
+                                         XV_SCALER_TAPS_10);
+               xv_vscaler_set_coeff(hw, XM2MVSC_VFLTCOEFF(2));
+               dev_dbg(hw->dev, "%s: Init Bank 2", __func__);
+       }
+       /* Bank 3 is init as 8 tap filter for 12 tap filters */
+       if (hw->num_taps == XV_SCALER_TAPS_12) {
+               xv_hscaler_load_ext_coeff(hw, &xhsc_coeff_taps12[0][0],
+                                         XV_SCALER_TAPS_12);
+               xv_hscaler_set_coeff(hw, XM2MVSC_HFLTCOEFF(3));
+               xv_vscaler_load_ext_coeff(hw, &xvsc_coeff_taps12[0][0],
+                                         XV_SCALER_TAPS_12);
+               xv_vscaler_set_coeff(hw, XM2MVSC_VFLTCOEFF(3));
+               dev_dbg(hw->dev, "%s: Init Bank 2", __func__);
+       }
+}
+
+/**
+ * xm2mvsc_select_coeff_bank - Selection of Scaler coefficients of operation
+ * @xscaler: Scaler device information
+ * @width_in: Width of input video
+ * @width_out: Width of desired output video
+ * @height_in : Height of the input video
+ * @height_out : Height of the output video
+ * @filter_bank : Filter bank to be set by the function
+ *
+ * There are instances when a N-tap filter might operate in an M-tap
+ * configuration where N > M.
+ *
+ * For example :
+ * Depending on the ratio of scaling (while downscaling), a 12-tap
+ * filter may operate with 10 tap coefficients and zero-pads the remaining
+ * coefficients.
+ *
+ * While upscaling the driver will program 6-tap filter coefficients
+ * in any N-tap configurations (for N >= 6).
+ *
+ * This selection is adopted by the as it gives optimal
+ * video output determined by repeated testing of the IP
+ *
+ * Return: Will return 0 if successful. Returns -EINVAL on an unsupported
+ * H-scaler number of taps.
+ */
+static void xm2mvsc_select_coeff_bank(struct xm2m_scaler_hw *xscaler,
+                                     const u32 width_in,
+                                     const u32 width_out,
+                                     const u32 height_in,
+                                     const u32 height_out,
+                                     u8 *filter_bank)
+{
+       u16 hscale_ratio;
+       u16 vscale_ratio;
+       u16 selection_ratio;
+
+       hscale_ratio = (width_in * 10) / width_out;
+       vscale_ratio = (height_in * 10) / height_out;
+       selection_ratio = (hscale_ratio > vscale_ratio ?
+                          hscale_ratio : vscale_ratio);
+       /*
+        * Scale Down Mode will use dynamic filter selection logic
+        * Scale Up Mode (including 1:1) will always use 6 tap filter
+        */
+       if (selection_ratio > 10) {
+               switch (xscaler->num_taps) {
+               case XV_SCALER_TAPS_6:
+                       *filter_bank = FILTER_BANK_TAPS_6;
+                       break;
+               case XV_SCALER_TAPS_8:
+                       if (selection_ratio > 15)
+                               *filter_bank = FILTER_BANK_TAPS_8;
+                       else
+                               *filter_bank = FILTER_BANK_TAPS_6;
+                       break;
+               case XV_SCALER_TAPS_10:
+                       if (selection_ratio > 25)
+                               *filter_bank = FILTER_BANK_TAPS_10;
+                       else if (selection_ratio > 15)
+                               *filter_bank = FILTER_BANK_TAPS_8;
+                       else
+                               *filter_bank = FILTER_BANK_TAPS_6;
+                       break;
+               case XV_SCALER_TAPS_12:
+                       if (selection_ratio > 35)
+                               *filter_bank = FILTER_BANK_TAPS_12;
+                       else if (selection_ratio > 25)
+                               *filter_bank = FILTER_BANK_TAPS_10;
+                       else if (selection_ratio > 15)
+                               *filter_bank = FILTER_BANK_TAPS_8;
+                       else
+                               *filter_bank = FILTER_BANK_TAPS_6;
+                       break;
+               default:
+                       /* Should never get here */
+                       WARN(1, "Impossible scaler tap selection");
+                       return;
+               }
+       } else {
+               *filter_bank = FILTER_BANK_TAPS_6;
+       }
+}
+
+static void xm2mvsc_set_color_format(struct xm2m_vscale_desc *desc)
+{
+       xvip_write(&desc->xm2mvsc_dev->hw,
+                  XM2MVSC_PIXELFMT_IN(desc->channel_offset),
+                  desc->data.srcbuf_cft);
+       xvip_write(&desc->xm2mvsc_dev->hw,
+                  XM2MVSC_PIXELFMT_OUT(desc->channel_offset),
+                  desc->data.dstbuf_cft);
+}
+
+#define STEP_PRECISION (65536)
+static void xm2mvsc_program_scaler(struct xm2m_vscale_desc *desc)
+{
+       desc->line_rate =
+           (desc->data.srcbuf_ht * STEP_PRECISION) / desc->data.dstbuf_ht;
+       xvip_write(&desc->xm2mvsc_dev->hw,
+                  XM2MVSC_LINERATE(desc->channel_offset),
+                  desc->line_rate);
+       desc->pixel_rate =
+           (desc->data.srcbuf_wt * STEP_PRECISION) / desc->data.dstbuf_wt;
+       xvip_write(&desc->xm2mvsc_dev->hw,
+                  XM2MVSC_PIXELRATE(desc->channel_offset),
+                  desc->pixel_rate);
+       xm2mvsc_select_coeff_bank(&desc->xm2mvsc_dev->hw,
+                                 desc->data.srcbuf_wt, desc->data.dstbuf_wt,
+                                 desc->data.srcbuf_ht, desc->data.dstbuf_ht,
+                                 &desc->filter_bank);
+       xvip_write(&desc->xm2mvsc_dev->hw,
+                  XM2MVSC_FILTER_BANK(desc->channel_offset),
+                  desc->filter_bank);
+       xm2mvsc_set_color_format(desc);
+}
+
+void xm2mvsc_write_desc(struct xm2m_vscale_desc *desc)
+{
+       WARN(!desc, "%s : desc is NULL", __func__);
+       if (!desc)
+               return;
+       WARN(!desc->xm2mvsc_dev,
+            "%s: desc->xm2mvsc_dev is NULL for desc_id = %d",
+            __func__, desc->data.desc_id);
+       if (!desc->xm2mvsc_dev)
+               return;
+       dev_dbg(desc->xm2mvsc_dev->dev,
+               "%s: Writing desc %d with chan offset = %d",
+               __func__, desc->data.desc_id, desc->channel_offset);
+       xm2mvsc_program_scaler(desc);
+       xvip_write(&desc->xm2mvsc_dev->hw,
+                  XM2MVSC_HEIGHT_IN(desc->channel_offset),
+                  desc->data.srcbuf_ht);
+       xvip_write(&desc->xm2mvsc_dev->hw,
+                  XM2MVSC_WIDTH_IN(desc->channel_offset),
+                  desc->data.srcbuf_wt);
+       xvip_write(&desc->xm2mvsc_dev->hw,
+                  XM2MVSC_HEIGHT_OUT(desc->channel_offset),
+                  desc->data.dstbuf_ht);
+       xvip_write(&desc->xm2mvsc_dev->hw,
+                  XM2MVSC_WIDTH_OUT(desc->channel_offset),
+                  desc->data.dstbuf_wt);
+       xvip_write(&desc->xm2mvsc_dev->hw,
+                  XM2MVSC_SRC_BUF1(desc->channel_offset),
+                  desc->srcbuf_addr);
+       xvip_write(&desc->xm2mvsc_dev->hw,
+                  XM2MVSC_DST_BUF1(desc->channel_offset),
+                  desc->dstbuf_addr);
+       xvip_write(&desc->xm2mvsc_dev->hw,
+                  XM2MVSC_STRIDE_IN(desc->channel_offset),
+                  desc->data.srcbuf_stride);
+       xvip_write(&desc->xm2mvsc_dev->hw,
+                  XM2MVSC_STRIDE_OUT(desc->channel_offset),
+                  desc->data.dstbuf_stride);
+}
+
+#define XM2MVSC_GLOBAL_ENABLE_IRQ      BIT(0)
+#define XM2MVSC_IRQ_AP_DONE            BIT(0)
+#define XM2MVSC_IRQ_AP_READY           BIT(1)
+#define XM2MVSC_START_SCALING          BIT(0)
+void xm2mvsc_start_scaling(const struct xm2m_scaler_hw *hw, const u8 batch_size)
+{
+       WARN(!hw, "%s: hw is NULL", __func__);
+       if (!hw)
+               return;
+       /* Enable Interrupt on IER register */
+       xvip_write(hw, XM2MVSC_IER, XM2MVSC_IRQ_AP_DONE);
+       /* Enable Global IER */
+       xvip_write(hw, XM2MVSC_GIE, XM2MVSC_GLOBAL_ENABLE_IRQ);
+       /* Write Number of Outputs */
+       xvip_write(hw, XM2MVSC_NUM_OUTS, batch_size);
+       /* Start IP with Auto-Restart Disabled */
+       xvip_write(hw, XM2MVSC_AP_CTRL, XM2MVSC_START_SCALING);
+}
+
+void xm2mvsc_log_register(const struct xm2m_scaler_hw *hw, const u8 chan_off)
+{
+       dev_dbg(hw->dev, "-------- %s : XM2MVSC HW REG Channel %d --------",
+               __func__, chan_off);
+       dev_dbg(hw->dev, "CTRL = 0x%x", xvip_read(hw, XM2MVSC_AP_CTRL));
+       dev_dbg(hw->dev, "GIE  = 0x%x", xvip_read(hw, XM2MVSC_GIE));
+       dev_dbg(hw->dev, "IER  = 0x%x", xvip_read(hw, XM2MVSC_IER));
+       dev_dbg(hw->dev, "ISR  = 0x%x", xvip_read(hw, XM2MVSC_ISR));
+       dev_dbg(hw->dev, "Num Outs = %d", xvip_read(hw, XM2MVSC_NUM_OUTS));
+       dev_dbg(hw->dev, "SRC1 = 0x%x",
+               xvip_read(hw, XM2MVSC_SRC_BUF1(chan_off)));
+       dev_dbg(hw->dev, "SRC2 = 0x%x",
+               xvip_read(hw, XM2MVSC_SRC_BUF2(chan_off)));
+       dev_dbg(hw->dev, "HT_IN  = %d",
+               xvip_read(hw, XM2MVSC_HEIGHT_IN(chan_off)));
+       dev_dbg(hw->dev, "WT_IN  = %d",
+               xvip_read(hw, XM2MVSC_WIDTH_IN(chan_off)));
+       dev_dbg(hw->dev, "HT_OUT = %d",
+               xvip_read(hw, XM2MVSC_HEIGHT_OUT(chan_off)));
+       dev_dbg(hw->dev, "WT_OUT = %d",
+               xvip_read(hw, XM2MVSC_WIDTH_OUT(chan_off)));
+       dev_dbg(hw->dev, "Stride In = %d",
+               xvip_read(hw, XM2MVSC_STRIDE_IN(chan_off)));
+       dev_dbg(hw->dev, "Stride Out = %d",
+               xvip_read(hw, XM2MVSC_STRIDE_OUT(chan_off)));
+       dev_dbg(hw->dev, "Pixel Fmt In = %d",
+               xvip_read(hw, XM2MVSC_PIXELFMT_IN(chan_off)));
+       dev_dbg(hw->dev, "Pixel Fmt Out = %d",
+               xvip_read(hw, XM2MVSC_PIXELFMT_OUT(chan_off)));
+       dev_dbg(hw->dev, "PixRate  = 0x%x",
+               xvip_read(hw, XM2MVSC_PIXELRATE(chan_off)));
+       dev_dbg(hw->dev, "LineRate = 0x%x",
+               xvip_read(hw, XM2MVSC_LINERATE(chan_off)));
+       dev_dbg(hw->dev, "DST1 = 0x%x",
+               xvip_read(hw, XM2MVSC_DST_BUF1(chan_off)));
+       dev_dbg(hw->dev, "DST2 = 0x%x",
+               xvip_read(hw, XM2MVSC_DST_BUF2(chan_off)));
+       dev_dbg(hw->dev, "Filter Bank = %d",
+               xvip_read(hw, XM2MVSC_FILTER_BANK(chan_off)));
+}
+
+void xm2mvsc_stop_scaling(const struct xm2m_scaler_hw *hw)
+{
+       WARN(!hw, "%s: hw is NULL", __func__);
+       if (!hw)
+               return;
+       /* Disable Interrupt on IER Register */
+       xvip_write(hw, XM2MVSC_IER, 0);
+       /* Disable Global IER */
+       xvip_write(hw, XM2MVSC_GIE, 0);
+       /* Stop IP */
+       xvip_write(hw, XM2MVSC_AP_CTRL, 0);
+}
+
+u32 xm2mvsc_get_irq_status(const struct xm2m_scaler_hw *hw)
+{
+       u32 status;
+
+       WARN_ON(!hw || IS_ERR(hw));
+       status = xvip_read(hw, XM2MVSC_ISR);
+       status &=  (XM2MVSC_IRQ_AP_DONE);
+       if (status) {
+               xvip_write(hw, XM2MVSC_ISR, status);
+               return status;
+       }
+       return 0;
+}
diff --git a/drivers/staging/xm2mvscale/scaler_hw_xm2m.h b/drivers/staging/xm2mvscale/scaler_hw_xm2m.h
new file mode 100644
index 0000000..1429791
--- /dev/null
+++ b/drivers/staging/xm2mvscale/scaler_hw_xm2m.h
@@ -0,0 +1,152 @@
+/*
+ * Xilinx Memory-to-Memory Video Scaler IP
+ *
+ * Copyright (C) 2018 Xilinx, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __SCALER_HW_XM2M_H__
+#define __SCALER_HW_XM2M_H__
+
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/types.h>
+
+#include "ioctl_xm2mvsc.h"
+
+#define XSCALER_MAX_WIDTH               (3840)
+#define XSCALER_MAX_HEIGHT              (2160)
+#define XSCALER_MAX_PHASES              (64)
+
+#define XV_SCALER_MAX_TAPS             (12)
+
+#define XV_SCALER_TAPS_6               (6)
+#define XV_SCALER_TAPS_8               (8)
+#define XV_SCALER_TAPS_10              (10)
+#define XV_SCALER_TAPS_12              (12)
+
+/* Filter bank ID  for various filter tap configurations */
+enum xm2mvsc_filter_bank_id {
+       FILTER_BANK_TAPS_6 = 0,
+       FILTER_BANK_TAPS_8,
+       FILTER_BANK_TAPS_10,
+       FILTER_BANK_TAPS_12,
+};
+
+#define XSCALER_BATCH_SIZE_MAX         (8)
+#define XSCALER_BATCH_SIZE_MIN         (1)
+
+struct xm2m_vscale_dev;
+
+/**
+ * struct xm2m_scaler_hw - Scaler Hardware Info
+ * @regs: IO mapped base address of the HW/IP
+ * @dev: Pointer to struct device instance
+ * @num_taps: Polyhphase filter taps Scaler IP
+ * @max_chan: Maximum number of Scaling Channels
+ * @max_pixels: Maximum number of pixel supported in a line
+ * @max_lines: Maximum number of lines supported in a frame
+ * @hscaler_coeff: Array of filter coefficients for the Horizontal Scaler
+ * @vscaler_coeff: Array of filter coefficients for the Vertical Scaler
+ */
+struct xm2m_scaler_hw {
+       void __iomem *regs;
+       struct device *dev;
+       u32 num_taps;
+       u32 max_chan;
+       u32 max_pixels;
+       u32 max_lines;
+       short hscaler_coeff[XSCALER_MAX_PHASES][XV_SCALER_MAX_TAPS];
+       short vscaler_coeff[XSCALER_MAX_PHASES][XV_SCALER_MAX_TAPS];
+};
+
+/**
+ * struct xm2m_vscale_desc - Video Scale Frame Descriptor
+ * @data: Data enqueued by the application
+ * @line_rate: Line rate needed by a scaling channel
+ * @pixel_rate: Pixel rate needed by a scaling channel
+ * @filter_bank: Filter Bank ID needed to source filter coefficients
+ * @channel_offset: Channel offset of the descriptor mapping to HW register
+ * @srcbuf_addr: physical address of source buffer
+ * @dstbuf_addr: physical address of destination buffer
+ * @xm2mvsc_dev: Pointer to parent xm2mvsc driver structure
+ * @node: List node to control descriptors in lists
+ * @src_kaddr: Kernel VA for source buffer allocated by the driver
+ * @dst_kaddr: Kernel VA for destination buffer allocated by the driver
+ */
+struct xm2m_vscale_desc {
+       struct xm2mvsc_qdata data;
+       u32 line_rate;
+       u32 pixel_rate;
+       u8 filter_bank;
+       u8 channel_offset;
+       dma_addr_t srcbuf_addr;
+       dma_addr_t dstbuf_addr;
+       struct xm2m_vscale_dev *xm2mvsc_dev;
+       struct list_head node;
+       void *src_kaddr;
+       void *dst_kaddr;
+};
+
+/**
+ * struct xm2m_vscale_dev - Xilinx M2M Scaler Device
+ * @dev: Pointer to struct device instance used by the driver
+ * @hw: HW/IP specific structure describing the capabilities
+ * @lock: Spinlock to protect driver data structures
+ * @pending_list: List containing descriptors not yet processed
+ * @ongoing_list: List containing descriptors that are in-flight
+ * @done_list: List containing descriptors that are done processing
+ * @free_list: List containing descriptors that need to be freed
+ * @waitq: Wait queue used by the driver
+ * @irq: IRQ number
+ * @chdev: Char device handle
+ * @id: Device instance ID
+ * @rst_gpio: GPIO reset line to bring VPSS Scaler out of reset
+ * @desc_count: Desc Count issued by the driver
+ * @user_count: Count of users who have opened the device
+ * @batch_size: Number of channel actively used in a scaling operation
+ * @ongoing_count: Number of channels already used in the ongoing operation
+ */
+struct xm2m_vscale_dev {
+       struct device *dev;
+       struct xm2m_scaler_hw hw;
+       /* Synchronize access to lists */
+       spinlock_t lock;
+       struct list_head pending_list;
+       struct list_head ongoing_list;
+       struct list_head done_list;
+       struct list_head free_list;
+       wait_queue_head_t waitq;
+       int irq;
+       struct cdev chdev;
+       u32 id;
+       struct gpio_desc *rst_gpio;
+       atomic_t desc_count;
+       atomic_t user_count;
+       u16 batch_size;
+       atomic_t ongoing_count;
+};
+
+static inline u32 xvip_read(const struct xm2m_scaler_hw *hw, const u32 addr)
+{
+       return ioread32(hw->regs + addr);
+}
+
+static inline void xvip_write(const struct xm2m_scaler_hw *hw,
+                             const u32 addr, const u32 value)
+{
+       iowrite32(value, hw->regs + addr);
+}
+
+void xm2mvsc_write_desc(struct xm2m_vscale_desc *desc);
+void xm2mvsc_start_scaling(const struct xm2m_scaler_hw *hw,
+                          const u8 batch_size);
+void xm2mvsc_stop_scaling(const struct xm2m_scaler_hw *hw);
+u32 xm2mvsc_get_irq_status(const struct xm2m_scaler_hw *hw);
+void xm2mvsc_log_register(const struct xm2m_scaler_hw *hw, const u8 chan_off);
+void xm2mvsc_initialize_coeff_banks(struct xm2m_scaler_hw *hw);
+
+#endif /* __XM2M_SCALER_SETUP_H__ */
diff --git a/drivers/staging/xm2mvscale/xm2m_vscale.c b/drivers/staging/xm2mvscale/xm2m_vscale.c
new file mode 100644
index 0000000..429cd7c
--- /dev/null
+++ b/drivers/staging/xm2mvscale/xm2m_vscale.c
@@ -0,0 +1,783 @@
+/*
+ * Xilinx Memory-to-Memory Video Scaler IP
+ *
+ * Copyright (C) 2018 Xilinx, Inc. All rights reserved.
+ *
+ * Description:
+ * This driver is developed for the Xilinx M2M Video Scaler IP. It allows
+ * userspace to operate upon the IP and takes care of interrupt handling
+ * and framebuffer programming within the driver.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/cdev.h>
+#include <linux/dma-buf.h>
+#include <linux/fs.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+
+#include "scaler_hw_xm2m.h"
+#include "ioctl_xm2mvsc.h"
+
+/* Forward Declaration */
+static int xm2mvsc_ioctl_stop(struct xm2m_vscale_dev *xm2mvsc);
+
+/* Module Parameters */
+static struct class *xm2mvsc_class;
+static dev_t xm2mvsc_devt;
+static atomic_t xm2mvsc_ndevs = ATOMIC_INIT(0);
+
+#define DRIVER_NAME    "xilinx-m2m-scaler"
+#define DRIVER_VERSION "0.4"
+#define DRIVER_MAX_DEV (10)
+
+static int xm2mvsc_open(struct inode *iptr, struct file *fptr)
+{
+       struct xm2m_vscale_dev *xm2mvsc;
+
+       xm2mvsc = container_of(iptr->i_cdev, struct xm2m_vscale_dev, chdev);
+       if (!xm2mvsc) {
+               pr_err("%s: failed to get xm2mvsc driver handle", __func__);
+               return -EAGAIN;
+       }
+       fptr->private_data = xm2mvsc;
+       xm2mvsc->batch_size = XSCALER_BATCH_SIZE_MIN;
+       atomic_inc(&xm2mvsc->user_count);
+       return 0;
+}
+
+static int xm2mvsc_release(struct inode *iptr, struct file *fptr)
+{
+       struct xm2m_vscale_dev *xm2mvsc;
+
+       xm2mvsc = container_of(iptr->i_cdev, struct xm2m_vscale_dev, chdev);
+       if (!xm2mvsc) {
+               pr_err("%s: failed to get xm2mvsc driver handle", __func__);
+               return -EAGAIN;
+       }
+       if (atomic_dec_and_test(&xm2mvsc->user_count)) {
+               /* Reset IP and clear driver state */
+               dev_dbg(xm2mvsc->dev,
+                       "%s: Stopping and clearing device", __func__);
+               (void)xm2mvsc_ioctl_stop(xm2mvsc);
+               atomic_set(&xm2mvsc->desc_count, 0);
+               atomic_set(&xm2mvsc->ongoing_count, 0);
+       }
+       dev_dbg(xm2mvsc->dev, "%s: user count = %d",
+               __func__, atomic_read(&xm2mvsc->user_count));
+       return 0;
+}
+
+#define XM2MVSC_MAX_WIDTH      (3840)
+#define XM2MVSC_MAX_HEIGHT     (2160)
+#define XM2MVSC_MIN_WIDTH      (32)
+#define XM2MVSC_MIN_HEIGHT     (32)
+static int xm2mvsc_verify_desc(struct xm2m_vscale_desc *desc)
+{
+       if (!desc)
+               return -EIO;
+       if (desc->data.srcbuf_ht > XM2MVSC_MAX_HEIGHT ||
+           desc->data.srcbuf_ht < XM2MVSC_MIN_HEIGHT ||
+           desc->data.dstbuf_ht > XM2MVSC_MAX_HEIGHT ||
+           desc->data.dstbuf_ht < XM2MVSC_MIN_HEIGHT)
+               return -EINVAL;
+       if (desc->data.srcbuf_wt > XM2MVSC_MAX_WIDTH ||
+           desc->data.srcbuf_wt < XM2MVSC_MIN_WIDTH ||
+           desc->data.dstbuf_wt > XM2MVSC_MAX_WIDTH ||
+           desc->data.dstbuf_wt < XM2MVSC_MIN_WIDTH)
+               return -EINVAL;
+       return 0;
+}
+
+static int xm2mvsc_ioctl_batch_size(struct xm2m_vscale_dev *xm2mvsc,
+                                   void __user *arg)
+{
+       int ret;
+       struct xm2mvsc_batch *batch;
+
+       batch = kzalloc(sizeof(*batch), GFP_KERNEL);
+       if (!batch)
+               return -ENOMEM;
+       ret = copy_from_user(batch, arg, sizeof(*batch));
+       if (ret) {
+               dev_err(xm2mvsc->dev,
+                       "%s: Failed to copy from user", __func__);
+               kfree(batch);
+               return -EFAULT;
+       }
+
+       if (!batch->batch_size || batch->batch_size > xm2mvsc->hw.max_chan) {
+               dev_err(xm2mvsc->dev,
+                       "Invalid batch size passed %d", batch->batch_size);
+               kfree(batch);
+               return -EINVAL;
+       }
+       xm2mvsc->batch_size = batch->batch_size;
+       kfree(batch);
+       return 0;
+}
+
+static int xm2mvsc_ioctl_enqueue(struct xm2m_vscale_dev *xm2mvsc,
+                                void __user *arg)
+{
+       struct xm2m_vscale_desc *desc;
+       int ret;
+       unsigned long flags;
+
+       desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+       if (!desc)
+               return -ENOMEM;
+       ret = copy_from_user(&desc->data, arg, sizeof(desc->data));
+       if (ret)  {
+               dev_err(xm2mvsc->dev, "%s: Failed to copy from user", __func__);
+               return -EFAULT;
+       }
+       ret = xm2mvsc_verify_desc(desc);
+       if (ret < 0)
+               return ret;
+       /* Assign xm2m_vscale_dev handle */
+       desc->xm2mvsc_dev = xm2mvsc;
+       desc->data.desc_id = atomic_add_return(1, &xm2mvsc->desc_count);
+       desc->src_kaddr = dma_alloc_coherent(xm2mvsc->dev,
+                                            desc->data.srcbuf_size,
+                                            &desc->srcbuf_addr,
+                                            GFP_KERNEL | GFP_DMA32);
+       if (!desc->src_kaddr)
+               return -ENOMEM;
+       desc->dst_kaddr = dma_alloc_coherent(xm2mvsc->dev,
+                                            desc->data.dstbuf_size,
+                                            &desc->dstbuf_addr,
+                                            GFP_KERNEL | GFP_DMA32);
+       if (!desc->dst_kaddr)
+               return -ENOMEM;
+       spin_lock_irqsave(&xm2mvsc->lock, flags);
+       list_add_tail(&desc->node, &xm2mvsc->pending_list);
+       spin_unlock_irqrestore(&xm2mvsc->lock, flags);
+       if (copy_to_user(arg, &desc->data, sizeof(desc->data))) {
+               dev_err(xm2mvsc->dev,
+                       "%s : Failed to copy to user for desc_id = %d",
+                       __func__, desc->data.desc_id);
+               return -EFAULT;
+       }
+       dev_dbg(xm2mvsc->dev, "%s: Desc_id = %d", __func__, desc->data.desc_id);
+       return 0;
+}
+
+static int xm2mvsc_complete(struct xm2m_vscale_dev *xm2mvsc)
+{
+       struct xm2m_vscale_desc *desc, *next;
+       unsigned long flags;
+
+       spin_lock_irqsave(&xm2mvsc->lock, flags);
+       list_for_each_entry_safe(desc, next, &xm2mvsc->ongoing_list, node) {
+               list_del(&desc->node);
+               list_add_tail(&desc->node, &xm2mvsc->done_list);
+               atomic_dec(&xm2mvsc->ongoing_count);
+       }
+       spin_unlock_irqrestore(&xm2mvsc->lock, flags);
+       dev_dbg(xm2mvsc->dev, "%s: ongoing_count = %d",
+               __func__, atomic_read(&xm2mvsc->ongoing_count));
+       return 0;
+}
+
+static int xm2mvsc_ready(struct xm2m_vscale_dev *xm2mvsc)
+{
+       unsigned long flags;
+       struct xm2m_vscale_desc *desc, *next;
+
+       spin_lock_irqsave(&xm2mvsc->lock, flags);
+       if (list_empty_careful(&xm2mvsc->pending_list)) {
+               spin_unlock_irqrestore(&xm2mvsc->lock, flags);
+               return -EAGAIN;
+       }
+       if (atomic_read(&xm2mvsc->ongoing_count) < xm2mvsc->batch_size) {
+               list_for_each_entry_safe(desc, next,
+                                        &xm2mvsc->pending_list, node) {
+                       list_del(&desc->node);
+                       desc->channel_offset =
+                               atomic_read(&xm2mvsc->ongoing_count);
+                       WARN(desc->channel_offset > xm2mvsc->hw.max_chan,
+                            "%s: Channel offset is beyond supported max",
+                            __func__);
+                       list_add_tail(&desc->node, &xm2mvsc->ongoing_list);
+                       atomic_inc(&xm2mvsc->ongoing_count);
+                       dev_dbg(xm2mvsc->dev,
+                               "%s: Desc_id=%d offset=%d ongoing count=%d",
+                               __func__, desc->data.desc_id,
+                               desc->channel_offset,
+                               atomic_read(&xm2mvsc->ongoing_count));
+               }
+       }
+       spin_unlock_irqrestore(&xm2mvsc->lock, flags);
+
+       if (atomic_read(&xm2mvsc->ongoing_count) == xm2mvsc->batch_size) {
+               list_for_each_entry_safe(desc, next,
+                                        &xm2mvsc->ongoing_list, node) {
+                       xm2mvsc_write_desc(desc);
+               }
+               dev_dbg(xm2mvsc->dev, "%s: xm2mvsc_start_scaling", __func__);
+               /* Start the IP */
+               xm2mvsc_start_scaling(&xm2mvsc->hw, xm2mvsc->batch_size);
+       }
+       return 0;
+}
+
+/* Can be called from IRQ Handler, not allowed to sleep */
+static int xm2mvsc_start_running(struct xm2m_vscale_dev *xm2mvsc)
+{
+       /* Process and make ready */
+       return xm2mvsc_ready(xm2mvsc);
+}
+
+/*
+ * Implementation may need to change to coalesce
+ * completion of multiple buffers
+ */
+static int xm2mvsc_ioctl_dequeue(struct xm2m_vscale_dev *xm2mvsc,
+                                void __user *arg)
+{
+       struct xm2mvsc_dqdata *dqdata;
+       struct xm2m_vscale_desc *desc, *next;
+       unsigned long flags;
+
+       dqdata = kzalloc(sizeof(*dqdata), GFP_KERNEL);
+       if (!dqdata)
+               return -ENOMEM;
+
+       if (copy_from_user(dqdata, arg, sizeof(*dqdata))) {
+               dev_err(xm2mvsc->dev, "%s: Failed to copy from user", __func__);
+               return -EFAULT;
+       }
+
+       /* Underflow or ioctl called too early, try later */
+       spin_lock_irqsave(&xm2mvsc->lock, flags);
+       if (list_empty_careful(&xm2mvsc->done_list)) {
+               spin_unlock_irqrestore(&xm2mvsc->lock, flags);
+               dev_err(xm2mvsc->dev,
+                       "%s: failed as done list empty", __func__);
+               return -EAGAIN;
+       }
+       /* Search through the done list, move to free list if found */
+       list_for_each_entry_safe(desc, next, &xm2mvsc->done_list, node) {
+               if (desc->data.desc_id == dqdata->desc_id) {
+                       list_del(&desc->node);
+                       list_add_tail(&desc->node, &xm2mvsc->free_list);
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&xm2mvsc->lock, flags);
+
+       /* Reached end of the list */
+       if (!desc || desc->data.desc_id != dqdata->desc_id) {
+               dev_err(xm2mvsc->dev,
+                       "%s: Unable to find desc_id = %d in done list",
+                       __func__, dqdata->desc_id);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int xm2mvsc_ioctl_start(struct xm2m_vscale_dev *xm2mvsc)
+{
+       return xm2mvsc_start_running(xm2mvsc);
+}
+
+static void xm2mvsc_free_desc_list(struct list_head *list)
+{
+       struct xm2m_vscale_desc *desc, *next;
+
+       list_for_each_entry_safe(desc, next, list, node) {
+               list_del(&desc->node);
+               kfree(desc);
+       }
+}
+
+/*  PS GPIO RESET MACROS */
+#define XM2MVSC_RESET_ASSERT   (0x1)
+#define XM2MVSC_RESET_DEASSERT (0x0)
+
+static void xm2mvsc_reset(struct xm2m_vscale_dev *xm2mvsc)
+{
+       gpiod_set_value_cansleep(xm2mvsc->rst_gpio, XM2MVSC_RESET_ASSERT);
+       gpiod_set_value_cansleep(xm2mvsc->rst_gpio, XM2MVSC_RESET_DEASSERT);
+}
+
+static void xm2mvsc_clear_state(struct xm2m_vscale_dev *xm2mvsc)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&xm2mvsc->lock, flags);
+       xm2mvsc_free_desc_list(&xm2mvsc->pending_list);
+       xm2mvsc_free_desc_list(&xm2mvsc->ongoing_list);
+       xm2mvsc_free_desc_list(&xm2mvsc->done_list);
+       xm2mvsc_free_desc_list(&xm2mvsc->free_list);
+       spin_unlock_irqrestore(&xm2mvsc->lock, flags);
+
+       spin_lock_irqsave(&xm2mvsc->lock, flags);
+       INIT_LIST_HEAD(&xm2mvsc->pending_list);
+       INIT_LIST_HEAD(&xm2mvsc->ongoing_list);
+       INIT_LIST_HEAD(&xm2mvsc->done_list);
+       INIT_LIST_HEAD(&xm2mvsc->free_list);
+       spin_unlock_irqrestore(&xm2mvsc->lock, flags);
+}
+
+static int xm2mvsc_ioctl_stop(struct xm2m_vscale_dev *xm2mvsc)
+{
+       xm2mvsc_clear_state(xm2mvsc);
+       /* Reset IP */
+       xm2mvsc_stop_scaling(&xm2mvsc->hw);
+       xm2mvsc_reset(xm2mvsc);
+       return 0;
+}
+
+static int xm2mvsc_ioctl_free(struct xm2m_vscale_dev *xm2mvsc,
+                             void __user *arg)
+{
+       struct xm2mvsc_dqdata *dqdata;
+       struct xm2m_vscale_desc *desc, *next;
+       int ret;
+
+       dqdata = kzalloc(sizeof(*desc), GFP_KERNEL);
+       if (!dqdata)
+               return -ENOMEM;
+
+       ret = copy_from_user(dqdata, arg, sizeof(*dqdata));
+       if (ret < 0) {
+               dev_err(xm2mvsc->dev,
+                       "%s: Failed to copy from user", __func__);
+               return -EFAULT;
+       }
+
+       list_for_each_entry_safe(desc, next, &xm2mvsc->free_list, node) {
+               if (desc->data.desc_id == dqdata->desc_id) {
+                       list_del(&desc->node);
+                       break;
+               }
+       }
+
+       if (!desc || desc->data.desc_id != dqdata->desc_id) {
+               dev_err(xm2mvsc->dev,
+                       "%s: Desc_id = %d not found in free list",
+                       __func__, dqdata->desc_id);
+               kfree(dqdata);
+               return -EBADF;
+       }
+
+       dma_free_coherent(xm2mvsc->dev, desc->data.srcbuf_size,
+                         desc->src_kaddr, desc->srcbuf_addr);
+       dma_free_coherent(xm2mvsc->dev, desc->data.dstbuf_size,
+                         desc->dst_kaddr, desc->dstbuf_addr);
+       kfree(dqdata);
+       kfree(desc);
+       return 0;
+}
+
+static long xm2mvsc_ioctl(struct file *fptr,
+                         unsigned int cmd, unsigned long data)
+{
+       struct xm2m_vscale_dev *xm2mvsc;
+       void __user *arg;
+       int ret;
+
+       xm2mvsc = fptr->private_data;
+       arg = (void __user *)data;
+
+       if (!xm2mvsc || !arg) {
+               pr_err("%s: file op error", __func__);
+               return -EIO;
+       }
+
+       switch (cmd) {
+       case XM2MVSC_ENQUEUE:
+               ret = xm2mvsc_ioctl_enqueue(xm2mvsc, arg);
+               if (ret < 0)
+                       return ret;
+               return 0;
+       case XM2MVSC_DEQUEUE:
+               ret = xm2mvsc_ioctl_dequeue(xm2mvsc, arg);
+               if (ret < 0)
+                       return ret;
+               return 0;
+       case XM2MVSC_START:
+               ret = xm2mvsc_ioctl_start(xm2mvsc);
+               if (ret < 0)
+                       return ret;
+               return 0;
+       case XM2MVSC_STOP:
+               ret = xm2mvsc_ioctl_stop(xm2mvsc);
+               if (ret < 0)
+                       return ret;
+               return 0;
+       case XM2MVSC_FREE:
+               ret = xm2mvsc_ioctl_free(xm2mvsc, arg);
+               if (ret < 0)
+                       return ret;
+               return 0;
+       case XM2MVSC_BATCH_SIZE:
+               ret = xm2mvsc_ioctl_batch_size(xm2mvsc, arg);
+               if (ret < 0)
+                       return ret;
+               return 0;
+       default:
+               dev_err(xm2mvsc->dev, "Unsupported ioctl cmd");
+               return -EINVAL;
+       }
+}
+
+static void xm2mvsc_mmap_open(struct vm_area_struct *vma)
+{
+}
+
+static void xm2mvsc_mmap_close(struct vm_area_struct *vma)
+{
+}
+
+static const struct vm_operations_struct xm2mvsc_vm_ops = {
+       .open = xm2mvsc_mmap_open,
+       .close = xm2mvsc_mmap_close,
+};
+
+/*
+ * First call  maps the source buffer,
+ * second call maps the destination buffer
+ */
+static int xm2mvsc_mmap(struct file *fptr, struct vm_area_struct *vma)
+{
+       struct xm2m_vscale_dev *xm2mvsc = fptr->private_data;
+       struct xm2m_vscale_desc *desc, *next;
+       int ret, desc_id;
+       unsigned long flags;
+
+       if (!xm2mvsc) {
+               pr_err("xm2mvsc file private data is NULL");
+               return -EIO;
+       }
+
+       desc_id = vma->vm_pgoff;
+
+       spin_lock_irqsave(&xm2mvsc->lock, flags);
+       list_for_each_entry_safe(desc, next, &xm2mvsc->pending_list, node) {
+               if (desc->data.desc_id == desc_id)
+                       break;
+       }
+       spin_unlock_irqrestore(&xm2mvsc->lock, flags);
+       if (!desc || desc->data.desc_id != desc_id) {
+               dev_err(xm2mvsc->dev,
+                       "Unable to find desc_id = %d in pending list",
+                       desc_id);
+               return -EIO;
+       }
+       if (!desc->src_kaddr && !desc->dst_kaddr) {
+               dev_err(xm2mvsc->dev, "Enqueue before mmap for desc_id = %d",
+                       desc->data.desc_id);
+       }
+       if (desc->data.srcbuf_mmap && desc->data.dstbuf_mmap) {
+               dev_err(xm2mvsc->dev,
+                       "Src and Dest buffs already mmap'ed for desc_id = %d",
+                       desc->data.desc_id);
+               return -EIO;
+       }
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+       if (!desc->data.srcbuf_mmap) {
+               ret = remap_pfn_range(vma, vma->vm_start,
+                                     desc->srcbuf_addr >> PAGE_SHIFT,
+                                     vma->vm_end - vma->vm_start,
+                                     vma->vm_page_prot);
+               if (ret) {
+                       dev_err(xm2mvsc->dev,
+                               "mmap op failed for srcbuf of desc_id = %d",
+                               desc->data.desc_id);
+                       ret = -EAGAIN;
+                       goto error_mmap;
+               }
+               desc->data.srcbuf_mmap = true;
+               goto success_mmap;
+       }
+       if (!desc->data.dstbuf_mmap) {
+               ret = remap_pfn_range(vma, vma->vm_start,
+                                     desc->dstbuf_addr >> PAGE_SHIFT,
+                                     vma->vm_end - vma->vm_start,
+                                     vma->vm_page_prot);
+               if (ret) {
+                       dev_err(xm2mvsc->dev,
+                               "mmap op failed for dstbuf of desc_id = %d",
+                               desc->data.desc_id);
+                       ret = -EAGAIN;
+                       goto error_mmap;
+               }
+               desc->data.dstbuf_mmap = true;
+               goto success_mmap;
+       }
+success_mmap:
+       vma->vm_private_data = xm2mvsc;
+       xm2mvsc_mmap_open(vma);
+       vma->vm_ops = &xm2mvsc_vm_ops;
+       return 0;
+error_mmap:
+       dev_err(xm2mvsc->dev, "%s: failed %d", __func__, ret);
+       return ret;
+}
+
+static unsigned int xm2mvsc_poll(struct file *fptr, poll_table *wait)
+{
+       struct xm2m_vscale_dev *xm2mvsc = fptr->private_data;
+
+       if (!xm2mvsc)
+               return 0;
+
+       poll_wait(fptr, &xm2mvsc->waitq, wait);
+       if (!list_empty_careful(&xm2mvsc->done_list))
+               return POLLIN | POLLPRI;
+       return 0;
+}
+
+static const struct file_operations xm2mvsc_fops = {
+       .open = xm2mvsc_open,
+       .release = xm2mvsc_release,
+       .unlocked_ioctl = xm2mvsc_ioctl,
+       .poll = xm2mvsc_poll,
+       .mmap = xm2mvsc_mmap,
+};
+
+static irqreturn_t xm2mvsc_intr_handler(int irq, void *ctx)
+{
+       u32 status;
+       struct xm2m_vscale_dev *xm2mvsc = (struct xm2m_vscale_dev *)ctx;
+
+       WARN(!xm2mvsc, "%s: xm2mvsc is NULL", __func__);
+       WARN(xm2mvsc->irq != irq,
+            "IRQ registered %d does not match IRQ received %d",
+            xm2mvsc->irq, irq);
+
+       status = xm2mvsc_get_irq_status(&xm2mvsc->hw);
+       if (status) {
+               /* The ongoing descriptors list should be cleared */
+               (void)xm2mvsc_complete(xm2mvsc);
+               wake_up_interruptible(&xm2mvsc->waitq);
+               /* Program next operation if any*/
+               (void)xm2mvsc_start_running(xm2mvsc);
+               return IRQ_HANDLED;
+       }
+       return IRQ_NONE;
+}
+
+#define XM2MVSC_OF_TAPS                "xlnx,scaler-num-taps"
+#define XM2MVSC_OF_MAX_CHAN    "xlnx,scaler-max-chan"
+static int xm2m_vscale_parse_dt_prop(struct xm2m_vscale_dev *xm2mvsc)
+{
+       struct device_node *node;
+       int ret;
+
+       if (!xm2mvsc)
+               return -EIO;
+       node = xm2mvsc->dev->of_node;
+
+       ret = of_property_read_u32(node, XM2MVSC_OF_TAPS,
+                                  &xm2mvsc->hw.num_taps);
+       if (ret < 0)
+               return ret;
+       switch (xm2mvsc->hw.num_taps) {
+       case XV_SCALER_TAPS_6:
+       case XV_SCALER_TAPS_8:
+       case XV_SCALER_TAPS_10:
+       case XV_SCALER_TAPS_12:
+               break;
+       default:
+               dev_err(xm2mvsc->dev,
+                       "Unsupported M2M Scaler taps : %d",
+                       xm2mvsc->hw.num_taps);
+               return -EINVAL;
+       }
+
+       ret = of_property_read_u32(node, XM2MVSC_OF_MAX_CHAN,
+                                  &xm2mvsc->hw.max_chan);
+       if (ret < 0)
+               return ret;
+       if (xm2mvsc->hw.max_chan < XSCALER_BATCH_SIZE_MIN ||
+           xm2mvsc->hw.max_chan > XSCALER_BATCH_SIZE_MAX) {
+               dev_err(xm2mvsc->dev,
+                       "Invalid maximum scaler channels : %d",
+                       xm2mvsc->hw.max_chan);
+               return -EINVAL;
+       }
+       /* Reset PS GPIO specifier is optional for now */
+       xm2mvsc->rst_gpio = devm_gpiod_get(xm2mvsc->dev,
+                                          "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(xm2mvsc->rst_gpio)) {
+               if (PTR_ERR(xm2mvsc->rst_gpio) != -EPROBE_DEFER) {
+                       dev_err(xm2mvsc->dev,
+                               "Reset GPIO specifier not setup in DT");
+               }
+               return PTR_ERR(xm2mvsc->rst_gpio);
+       }
+
+       xm2mvsc->irq = irq_of_parse_and_map(node, 0);
+       if (xm2mvsc->irq < 0) {
+               dev_err(xm2mvsc->dev, "Unable to get IRQ");
+               return xm2mvsc->irq;
+       }
+
+       return 0;
+}
+
+static int xm2m_vscale_probe(struct platform_device *pdev)
+{
+       struct xm2m_vscale_dev *xm2mvsc;
+       struct device *dc;
+       struct resource *res;
+       int ret;
+
+       if (atomic_read(&xm2mvsc_ndevs) >= DRIVER_MAX_DEV) {
+               dev_err(&pdev->dev,
+                       "Unable to create xm2mvsc devices beyond max %d",
+                       DRIVER_MAX_DEV);
+               return -EIO;
+       }
+
+       xm2mvsc = devm_kzalloc(&pdev->dev, sizeof(*xm2mvsc), GFP_KERNEL);
+       if (!xm2mvsc)
+               return -ENOMEM;
+       xm2mvsc->dev = &pdev->dev;
+       xm2mvsc->hw.dev = &pdev->dev;
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       xm2mvsc->hw.regs = devm_ioremap_resource(xm2mvsc->dev, res);
+       if (IS_ERR(xm2mvsc->hw.regs))
+               return PTR_ERR(xm2mvsc->hw.regs);
+       ret = xm2m_vscale_parse_dt_prop(xm2mvsc);
+       if (ret < 0)
+               return ret;
+       xm2mvsc_reset(xm2mvsc);
+
+       /* Initialize Scaler Properties */
+       xm2mvsc->hw.max_lines = XM2MVSC_MAX_HEIGHT;
+       xm2mvsc->hw.max_pixels = XM2MVSC_MAX_WIDTH;
+       xm2mvsc_initialize_coeff_banks(&xm2mvsc->hw);
+
+       init_waitqueue_head(&xm2mvsc->waitq);
+       spin_lock_init(&xm2mvsc->lock);
+       INIT_LIST_HEAD(&xm2mvsc->pending_list);
+       INIT_LIST_HEAD(&xm2mvsc->ongoing_list);
+       INIT_LIST_HEAD(&xm2mvsc->done_list);
+       INIT_LIST_HEAD(&xm2mvsc->free_list);
+       ret = devm_request_irq(xm2mvsc->dev, xm2mvsc->irq,
+                              xm2mvsc_intr_handler, IRQF_SHARED,
+                              DRIVER_NAME, xm2mvsc);
+       if (ret < 0) {
+               dev_err(xm2mvsc->dev, "Unable to register IRQ");
+               return ret;
+       }
+
+       cdev_init(&xm2mvsc->chdev, &xm2mvsc_fops);
+       xm2mvsc->chdev.owner = THIS_MODULE;
+       xm2mvsc->id = atomic_read(&xm2mvsc_ndevs);
+       ret = cdev_add(&xm2mvsc->chdev,
+                      MKDEV(MAJOR(xm2mvsc_devt), xm2mvsc->id), 1);
+       if (ret < 0) {
+               dev_err(xm2mvsc->dev, "cdev_add failed");
+               return ret;
+       }
+
+       if (!xm2mvsc_class) {
+               dev_err(xm2mvsc->dev, "xm2mvsc device class not created");
+               goto err_cdev;
+       }
+       dc = device_create(xm2mvsc_class, xm2mvsc->dev,
+                          MKDEV(MAJOR(xm2mvsc_devt), xm2mvsc->id),
+                          xm2mvsc, "xm2mvsc%d", xm2mvsc->id);
+       if (IS_ERR(dc)) {
+               ret = PTR_ERR(dc);
+               dev_err(xm2mvsc->dev, "Unable to create device");
+               goto err_cdev;
+       }
+       platform_set_drvdata(pdev, xm2mvsc);
+       dev_info(xm2mvsc->dev,
+                "Xilinx M2M Video Scaler %d tap %d channel device probe complete",
+                xm2mvsc->hw.num_taps, xm2mvsc->hw.max_chan);
+       atomic_inc(&xm2mvsc_ndevs);
+       return 0;
+err_cdev:
+       cdev_del(&xm2mvsc->chdev);
+       return ret;
+}
+
+static int xm2m_vscale_remove(struct platform_device *pdev)
+{
+       struct xm2m_vscale_dev *xm2mvsc;
+
+       xm2mvsc = platform_get_drvdata(pdev);
+       if (!xm2mvsc || !xm2mvsc_class)
+               return -EIO;
+       device_destroy(xm2mvsc_class,
+                      MKDEV(MAJOR(xm2mvsc_devt), xm2mvsc->id));
+       cdev_del(&xm2mvsc->chdev);
+       atomic_dec(&xm2mvsc_ndevs);
+       return 0;
+}
+
+static const struct of_device_id xm2mvsc_of_match[] = {
+       { .compatible = "xlnx,v-m2m-scaler", },
+       { /* end of table*/ }
+};
+MODULE_DEVICE_TABLE(of, xm2mvsc_of_match);
+
+static struct platform_driver xm2mvsc_driver = {
+       .driver = {
+               .name = DRIVER_NAME,
+               .of_match_table = xm2mvsc_of_match,
+       },
+       .probe = xm2m_vscale_probe,
+       .remove = xm2m_vscale_remove,
+};
+
+static int __init xm2mvsc_init_mod(void)
+{
+       int err;
+
+       xm2mvsc_class = class_create(THIS_MODULE, DRIVER_NAME);
+       if (IS_ERR(xm2mvsc_class)) {
+               pr_err("%s : Unable to create xm2mvsc class", __func__);
+               return PTR_ERR(xm2mvsc_class);
+       }
+       err = alloc_chrdev_region(&xm2mvsc_devt, 0,
+                                 DRIVER_MAX_DEV, DRIVER_NAME);
+       if (err < 0) {
+               pr_err("%s: Unable to get major number for xm2mvsc", __func__);
+               goto err_class;
+       }
+       err = platform_driver_register(&xm2mvsc_driver);
+       if (err < 0) {
+               pr_err("%s: Unable to register %s driver",
+                      __func__, DRIVER_NAME);
+               goto err_pdrv;
+       }
+       return 0;
+err_pdrv:
+       unregister_chrdev_region(xm2mvsc_devt, DRIVER_MAX_DEV);
+err_class:
+       class_destroy(xm2mvsc_class);
+       return err;
+}
+
+static void __exit xm2mvsc_cleanup_mod(void)
+{
+       platform_driver_unregister(&xm2mvsc_driver);
+       unregister_chrdev_region(xm2mvsc_devt, DRIVER_MAX_DEV);
+       class_destroy(xm2mvsc_class);
+       xm2mvsc_class = NULL;
+}
+module_init(xm2mvsc_init_mod);
+module_exit(xm2mvsc_cleanup_mod);
+
+MODULE_AUTHOR("Xilinx Inc.");
+MODULE_DESCRIPTION("Xilinx M2M Video Scaler IP Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/staging/xm2mvscale/xvm2mvsc_hw_regs.h b/drivers/staging/xm2mvscale/xvm2mvsc_hw_regs.h
new file mode 100644
index 0000000..966d3c8
--- /dev/null
+++ b/drivers/staging/xm2mvscale/xvm2mvsc_hw_regs.h
@@ -0,0 +1,204 @@
+// ==============================================================
+// File generated by Vivado(TM) HLS - High-Level Synthesis from
+// C, C++ and SystemC
+// Version: 2018.1.0
+// Copyright (C) 1986-2018 Xilinx, Inc. All Rights Reserved.
+// SPDX-License-Identifier: GPL-2.0
+// ==============================================================
+
+// CTRL
+// 0x0000 : Control signals
+//          bit 0  - ap_start (Read/Write/COH)
+//          bit 1  - ap_done (Read/COR)
+//          bit 2  - ap_idle (Read)
+//          bit 3  - ap_ready (Read)
+//          bit 7  - auto_restart (Read/Write)
+//          others - reserved
+// 0x0004 : Global Interrupt Enable Register
+//          bit 0  - Global Interrupt Enable (Read/Write)
+//          others - reserved
+// 0x0008 : IP Interrupt Enable Register (Read/Write)
+//          bit 0  - Channel 0 (ap_done)
+//          bit 1  - Channel 1 (ap_ready)
+//          others - reserved
+// 0x000c : IP Interrupt Status Register (Read/TOW)
+//          bit 0  - Channel 0 (ap_done)
+//          bit 1  - Channel 1 (ap_ready)
+//          others - reserved
+// 0x0010 : Data signal of HwReg_num_outs
+//          bit 7~0 - HwReg_num_outs[7:0] (Read/Write)
+//          others  - reserved
+// 0x0014 : reserved
+// 0x0100 : Data signal of HwReg_WidthIn_0
+//          bit 15~0 - HwReg_WidthIn_0[15:0] (Read/Write)
+//          others   - reserved
+// 0x0104 : reserved
+// 0x0108 : Data signal of HwReg_WidthOut_0
+//          bit 15~0 - HwReg_WidthOut_0[15:0] (Read/Write)
+//          others   - reserved
+// 0x010c : reserved
+// 0x0110 : Data signal of HwReg_HeightIn_0
+//          bit 15~0 - HwReg_HeightIn_0[15:0] (Read/Write)
+//          others   - reserved
+// 0x0114 : reserved
+// 0x0118 : Data signal of HwReg_HeightOut_0
+//          bit 15~0 - HwReg_HeightOut_0[15:0] (Read/Write)
+//          others   - reserved
+// 0x011c : reserved
+// 0x0120 : Data signal of HwReg_LineRate_0
+//          bit 31~0 - HwReg_LineRate_0[31:0] (Read/Write)
+// 0x0124 : reserved
+// 0x0128 : Data signal of HwReg_PixelRate_0
+//          bit 31~0 - HwReg_PixelRate_0[31:0] (Read/Write)
+// 0x012c : reserved
+// 0x0130 : Data signal of HwReg_InPixelFmt_0
+//          bit 7~0 - HwReg_InPixelFmt_0[7:0] (Read/Write)
+//          others  - reserved
+// 0x0134 : reserved
+// 0x0138 : Data signal of HwReg_OutPixelFmt_0
+//          bit 7~0 - HwReg_OutPixelFmt_0[7:0] (Read/Write)
+//          others  - reserved
+// 0x013c : reserved
+// 0x0140 : Data signal of HwReg_FiltIdx_0
+//          bit 7~0 - HwReg_FiltIdx_0[7:0] (Read/Write)
+//          others  - reserved
+// 0x0144 : reserved
+// 0x0150 : Data signal of HwReg_InStride_0
+//          bit 15~0 - HwReg_InStride_0[15:0] (Read/Write)
+//          others   - reserved
+// 0x0154 : reserved
+// 0x0158 : Data signal of HwReg_OutStride_0
+//          bit 15~0 - HwReg_OutStride_0[15:0] (Read/Write)
+//          others   - reserved
+// 0x015c : reserved
+// 0x0160 : Data signal of HwReg_srcImgBuf0_0
+//          bit 31~0 - HwReg_srcImgBuf0_0[31:0] (Read/Write)
+// 0x0164 : reserved
+// 0x0170 : Data signal of HwReg_srcImgBuf1_0
+//          bit 31~0 - HwReg_srcImgBuf1_0[31:0] (Read/Write)
+// 0x0174 : reserved
+// 0x0190 : Data signal of HwReg_dstImgBuf0_0
+//          bit 31~0 - HwReg_dstImgBuf0_0[31:0] (Read/Write)
+// 0x0194 : reserved
+// 0x0200 : Data signal of HwReg_dstImgBuf1_0
+//          bit 31~0 - HwReg_dstImgBuf1_0[31:0] (Read/Write)
+// 0x0204 : reserved
+// 0x1500 : Data signal of HwReg_WidthIn_7
+//          bit 15~0 - HwReg_WidthIn_7[15:0] (Read/Write)
+//          others   - reserved
+// 0x1504 : reserved
+// 0x1508 : Data signal of HwReg_WidthOut_7
+//          bit 15~0 - HwReg_WidthOut_7[15:0] (Read/Write)
+//          others   - reserved
+// 0x150c : reserved
+// 0x1510 : Data signal of HwReg_HeightIn_7
+//          bit 15~0 - HwReg_HeightIn_7[15:0] (Read/Write)
+//          others   - reserved
+// 0x1514 : reserved
+// 0x1518 : Data signal of HwReg_HeightOut_7
+//          bit 15~0 - HwReg_HeightOut_7[15:0] (Read/Write)
+//          others   - reserved
+// 0x151c : reserved
+// 0x1520 : Data signal of HwReg_LineRate_7
+//          bit 31~0 - HwReg_LineRate_7[31:0] (Read/Write)
+// 0x1524 : reserved
+// 0x1528 : Data signal of HwReg_PixelRate_7
+//          bit 31~0 - HwReg_PixelRate_7[31:0] (Read/Write)
+// 0x152c : reserved
+// 0x1530 : Data signal of HwReg_InPixelFmt_7
+//          bit 7~0 - HwReg_InPixelFmt_7[7:0] (Read/Write)
+//          others  - reserved
+// 0x1534 : reserved
+// 0x1538 : Data signal of HwReg_OutPixelFmt_7
+//          bit 7~0 - HwReg_OutPixelFmt_7[7:0] (Read/Write)
+//          others  - reserved
+// 0x153c : reserved
+// 0x1540 : Data signal of HwReg_FiltIdx_7
+//          bit 7~0 - HwReg_FiltIdx_7[7:0] (Read/Write)
+//          others  - reserved
+// 0x1544 : reserved
+// 0x1550 : Data signal of HwReg_InStride_7
+//          bit 15~0 - HwReg_InStride_7[15:0] (Read/Write)
+//          others   - reserved
+// 0x1554 : reserved
+// 0x1558 : Data signal of HwReg_OutStride_7
+//          bit 15~0 - HwReg_OutStride_7[15:0] (Read/Write)
+//          others   - reserved
+// 0x155c : reserved
+// 0x1560 : Data signal of HwReg_srcImgBuf0_7
+//          bit 31~0 - HwReg_srcImgBuf0_7[31:0] (Read/Write)
+// 0x1564 : reserved
+// 0x1570 : Data signal of HwReg_srcImgBuf1_7
+//          bit 31~0 - HwReg_srcImgBuf1_7[31:0] (Read/Write)
+// 0x1574 : reserved
+// 0x1590 : Data signal of HwReg_dstImgBuf0_7
+//          bit 31~0 - HwReg_dstImgBuf0_7[31:0] (Read/Write)
+// 0x1594 : reserved
+// 0x1600 : Data signal of HwReg_dstImgBuf1_7
+//          bit 31~0 - HwReg_dstImgBuf1_7[31:0] (Read/Write)
+// 0x1604 : reserved
+// 0x2000 ~
+// 0x23ff : Memory 'HwReg_mm_vfltCoeff_L' (384 * 16b)
+//          Word n : bit [15: 0] - HwReg_mm_vfltCoeff_L[2n]
+//                   bit [31:16] - HwReg_mm_vfltCoeff_L[2n+1]
+// 0x2800 ~
+// 0x2bff : Memory 'HwReg_mm_vfltCoeff_H' (384 * 16b)
+//          Word n : bit [15: 0] - HwReg_mm_vfltCoeff_H[2n]
+//                   bit [31:16] - HwReg_mm_vfltCoeff_H[2n+1]
+// 0x4000 ~
+// 0x43ff : Memory 'HwReg_mm_hfltCoeff_L' (384 * 16b)
+//          Word n : bit [15: 0] - HwReg_mm_hfltCoeff_L[2n]
+//                   bit [31:16] - HwReg_mm_hfltCoeff_L[2n+1]
+// 0x4800 ~
+// 0x4bff : Memory 'HwReg_mm_hfltCoeff_H' (384 * 16b)
+//          Word n : bit [15: 0] - HwReg_mm_hfltCoeff_H[2n]
+//                   bit [31:16] - HwReg_mm_hfltCoeff_H[2n+1]
+// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write,
+//  COH = Clear on Handshake)
+#ifndef __HW_REGS_XM2MVSC_H__
+#define __HW_REGS_XM2MVSC_H__
+
+#define XM2MVSC_AP_CTRL                        0x0000
+#define XM2MVSC_GIE                    0x0004
+#define XM2MVSC_IER                    0x0008
+#define XM2MVSC_ISR                    0x000c
+#define XM2MVSC_NUM_OUTS               0x0010
+
+#define XM2MVSC_WIDTHIN_0              0x0100
+#define XM2MVSC_WIDTHOUT_0             0x0108
+#define XM2MVSC_HEIGHTIN_0             0x0110
+#define XM2MVSC_HEIGHTOUT_0            0x0118
+#define XM2MVSC_LINERATE_0             0x0120
+#define XM2MVSC_PIXELRATE_0            0x0128
+#define XM2MVSC_INPIXELFMT_0           0x0130
+#define XM2MVSC_OUTPIXELFMT_0          0x0138
+#define XM2MVSC_FILTIDX_0              0x0140
+#define XM2MVSC_INSTRIDE_0             0x0150
+#define XM2MVSC_OUTSTRIDE_0            0x0158
+#define XM2MVSC_SRCIMGBUF0_0           0x0160
+#define XM2MVSC_SRCIMGBUF1_0           0x0170
+#define XM2MVSC_DSTIMGBUF0_0           0x0190
+#define XM2MVSC_DSTIMGBUF1_0           0x0200
+
+#define XM2MVSC_WIDTH_IN(x)    (XM2MVSC_WIDTHIN_0     + 0x200 * (x))
+#define XM2MVSC_WIDTH_OUT(x)   (XM2MVSC_WIDTHOUT_0    + 0x200 * (x))
+#define XM2MVSC_HEIGHT_IN(x)   (XM2MVSC_HEIGHTIN_0    + 0x200 * (x))
+#define XM2MVSC_HEIGHT_OUT(x)  (XM2MVSC_HEIGHTOUT_0   + 0x200 * (x))
+#define XM2MVSC_LINERATE(x)    (XM2MVSC_LINERATE_0    + 0x200 * (x))
+#define XM2MVSC_PIXELRATE(x)   (XM2MVSC_PIXELRATE_0   + 0x200 * (x))
+#define XM2MVSC_PIXELFMT_IN(x) (XM2MVSC_INPIXELFMT_0  + 0x200 * (x))
+#define XM2MVSC_PIXELFMT_OUT(x)        (XM2MVSC_OUTPIXELFMT_0 + 0x200 * (x))
+#define XM2MVSC_FILTER_BANK(x) (XM2MVSC_FILTIDX_0     + 0x200 * (x))
+#define XM2MVSC_STRIDE_IN(x)   (XM2MVSC_INSTRIDE_0    + 0x200 * (x))
+#define XM2MVSC_STRIDE_OUT(x)  (XM2MVSC_OUTSTRIDE_0   + 0x200 * (x))
+#define XM2MVSC_SRC_BUF1(x)    (XM2MVSC_SRCIMGBUF0_0  + 0x200 * (x))
+#define XM2MVSC_SRC_BUF2(x)    (XM2MVSC_SRCIMGBUF1_0  + 0x200 * (x))
+#define XM2MVSC_DST_BUF1(x)    (XM2MVSC_DSTIMGBUF0_0  + 0x200 * (x))
+#define XM2MVSC_DST_BUF2(x)    (XM2MVSC_DSTIMGBUF1_0  + 0x200 * (x))
+
+#define XM2MVSC_VFLTCOEFF_L            0x2000
+#define XM2MVSC_VFLTCOEFF(x)   (XM2MVSC_VFLTCOEFF_L + 0x800 * (x))
+#define XM2MVSC_HFLTCOEFF_L            0x4000
+#define XM2MVSC_HFLTCOEFF(x)   (XM2MVSC_HFLTCOEFF_L + 0x800 * (x))
+
+#endif /* __HW_REGS_XM2MVSC_H__ */
--
1.9.1

This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.


More information about the devel mailing list