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.athav...@xilinx.com>
---
 drivers/staging/Kconfig                       |   2 +
 drivers/staging/Makefile                      |   1 +
 drivers/staging/xm2mvscale/Kconfig            |  11 +
 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      | 768 +++++++++++++++++++++
 drivers/staging/xm2mvscale/xvm2mvsc_hw_regs.h | 204 ++++++
 9 files changed, 2220 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..949a8e4
--- /dev/null
+++ b/drivers/staging/xm2mvscale/Kconfig
@@ -0,0 +1,11 @@
+config XILINX_M2M_VSC
+       tristate "Xilinx M2M Video Scaler"
+       depends on ARCH_ZYNQMP && OF
+       ---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..b294d31
--- /dev/null
+++ b/drivers/staging/xm2mvscale/xm2m_vscale.c
@@ -0,0 +1,768 @@
+/*
+ * 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;
+       }
+}
+
+/*
+ * 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;
+       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

Reply via email to