diff --git a/libavutil/cpu.c b/libavutil/cpu.c
index 6548cc3042..52f6b9a3bf 100644
--- a/libavutil/cpu.c
+++ b/libavutil/cpu.c
@@ -51,6 +51,8 @@ static atomic_int cpu_flags = ATOMIC_VAR_INIT(-1);
 
 static int get_cpu_flags(void)
 {
+    if (ARCH_MIPS)
+        return ff_get_cpu_flags_mips();
     if (ARCH_AARCH64)
         return ff_get_cpu_flags_aarch64();
     if (ARCH_ARM)
@@ -169,6 +171,9 @@ int av_parse_cpu_flags(const char *s)
         { "armv8",    NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV8    },    .unit = "flags" },
         { "neon",     NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_NEON     },    .unit = "flags" },
         { "vfp",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP      },    .unit = "flags" },
+#elif ARCH_MIPS
+        { "mmi",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MMI      },    .unit = "flags" },
+        { "msa",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MSA      },    .unit = "flags" },
 #endif
         { NULL },
     };
@@ -250,6 +255,9 @@ int av_parse_cpu_caps(unsigned *flags, const char *s)
         { "armv8",    NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV8    },    .unit = "flags" },
         { "neon",     NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_NEON     },    .unit = "flags" },
         { "vfp",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP      },    .unit = "flags" },
+#elif ARCH_MIPS
+        { "mmi",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MMI      },    .unit = "flags" },
+        { "msa",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MSA      },    .unit = "flags" },
 #endif
         { NULL },
     };
@@ -308,6 +316,8 @@ int av_cpu_count(void)
 
 size_t av_cpu_max_align(void)
 {
+    if (ARCH_MIPS)
+        return ff_get_cpu_max_align_mips();
     if (ARCH_AARCH64)
         return ff_get_cpu_max_align_aarch64();
     if (ARCH_ARM)
diff --git a/libavutil/cpu.h b/libavutil/cpu.h
index 8bb9eb606b..83099dd969 100644
--- a/libavutil/cpu.h
+++ b/libavutil/cpu.h
@@ -71,6 +71,9 @@
 #define AV_CPU_FLAG_VFP_VM       (1 << 7) ///< VFPv2 vector mode, deprecated in ARMv7-A and unavailable in various CPUs implementations
 #define AV_CPU_FLAG_SETEND       (1 <<16)
 
+#define AV_CPU_FLAG_MMI          (1 << 0)
+#define AV_CPU_FLAG_MSA          (1 << 1)
+
 /**
  * Return the flags which specify extensions supported by the CPU.
  * The returned value is affected by av_force_cpu_flags() if that was used
diff --git a/libavutil/cpu_internal.h b/libavutil/cpu_internal.h
index 37122d1c5f..889764320b 100644
--- a/libavutil/cpu_internal.h
+++ b/libavutil/cpu_internal.h
@@ -41,11 +41,13 @@
 #define CPUEXT_FAST(flags, cpuext) CPUEXT_SUFFIX_FAST(flags, , cpuext)
 #define CPUEXT_SLOW(flags, cpuext) CPUEXT_SUFFIX_SLOW(flags, , cpuext)
 
+int ff_get_cpu_flags_mips(void);
 int ff_get_cpu_flags_aarch64(void);
 int ff_get_cpu_flags_arm(void);
 int ff_get_cpu_flags_ppc(void);
 int ff_get_cpu_flags_x86(void);
 
+size_t ff_get_cpu_max_align_mips(void);
 size_t ff_get_cpu_max_align_aarch64(void);
 size_t ff_get_cpu_max_align_arm(void);
 size_t ff_get_cpu_max_align_ppc(void);
diff --git a/libavutil/mips/Makefile b/libavutil/mips/Makefile
index dbfa5aa341..5f8c9b64e9 100644
--- a/libavutil/mips/Makefile
+++ b/libavutil/mips/Makefile
@@ -1 +1 @@
-OBJS += mips/float_dsp_mips.o
+OBJS += mips/float_dsp_mips.o mips/cpu.o
diff --git a/libavutil/mips/cpu.c b/libavutil/mips/cpu.c
new file mode 100644
index 0000000000..e9e291a45a
--- /dev/null
+++ b/libavutil/mips/cpu.c
@@ -0,0 +1,134 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/cpu.h"
+#include "libavutil/cpu_internal.h"
+#include "config.h"
+#if defined __linux__ || defined __ANDROID__
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/auxv.h>
+#include "asmdefs.h"
+#include "libavutil/avstring.h"
+#endif
+
+#if defined __linux__ || defined __ANDROID__
+
+#define HWCAP_LOONGSON_CPUCFG (1 << 14)
+
+static int cpucfg_available(void)
+{
+    return getauxval(AT_HWCAP) & HWCAP_LOONGSON_CPUCFG;
+}
+
+/* Most toolchains have no CPUCFG support yet */
+static uint32_t read_cpucfg(uint32_t reg)
+{
+	uint32_t __res;
+
+	__asm__ __volatile__(
+		"parse_r __res,%0\n\t"
+		"parse_r reg,%1\n\t"
+		".insn \n\t"
+		".word (0xc8080118 | (reg << 21) | (__res << 11))\n\t"
+		:"=r"(__res)
+		:"r"(reg)
+		:
+		);
+	return __res;
+}
+
+#define LOONGSON_CFG1 0x1
+
+#define LOONGSON_CFG1_MMI	(1 << 4)
+#define LOONGSON_CFG1_MSA1	(1 << 5)
+
+static int cpu_flags_cpucfg(void)
+{
+    int flags = 0;
+    uint32_t cfg1 = read_cpucfg(LOONGSON_CFG1);
+
+    if (cfg1 & LOONGSON_CFG1_MMI)
+        flags |= AV_CPU_FLAG_MMI;
+
+    if (cfg1 & LOONGSON_CFG1_MMI)
+        flags |= AV_CPU_FLAG_MSA;
+
+    return flags;
+}
+
+static int cpu_flags_cpuinfo(void)
+{
+    FILE *f = fopen("/proc/cpuinfo", "r");
+    char buf[200];
+    int flags = 0;
+
+    if (!f)
+        return -1;
+
+    while (fgets(buf, sizeof(buf), f)) {
+        /* Legacy kernel may not export MMI in ASEs implemented */
+        if (av_strstart(buf, "cpu model", NULL)) {
+            if (strstr(buf, "Loongson-3 "))
+                flags |= AV_CPU_FLAG_MMI;
+        }
+
+        if (av_strstart(buf, "ASEs implemented", NULL)) {
+            if (strstr(buf, " loongson-mmi"))
+                flags |= AV_CPU_FLAG_MMI;
+            if (strstr(buf, " msa"))
+                flags |= AV_CPU_FLAG_MSA;
+
+            break;
+        }
+    }
+    fclose(f);
+    return flags;
+}
+#endif
+
+int ff_get_cpu_flags_mips(void)
+{
+#if defined __linux__ || defined __ANDROID__
+    if (cpucfg_available())
+        return cpu_flags_cpucfg();
+    else
+        return cpu_flags_cpuinfo();
+#else
+    /* Assume no SIMD ASE supported */
+    return 0;
+#endif
+}
+
+size_t ff_get_cpu_max_align_mips(void)
+{
+    int flags = av_get_cpu_flags();
+
+    if (flags & AV_CPU_FLAG_MSA)
+        return 16;
+
+    /* 
+     * MMI itself is 64-bit but quad word load & store 
+     * needs 128-bit align.
+     */
+    if (flags & AV_CPU_FLAG_MMI)
+        return 16;
+
+    return 8;
+}
diff --git a/libavutil/mips/cpu.h b/libavutil/mips/cpu.h
new file mode 100644
index 0000000000..615dc49759
--- /dev/null
+++ b/libavutil/mips/cpu.h
@@ -0,0 +1,28 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_MIPS_CPU_H
+#define AVUTIL_MIPS_CPU_H
+
+#include "libavutil/cpu.h"
+#include "libavutil/cpu_internal.h"
+
+#define have_mmi(flags) CPUEXT(flags, MMI)
+#define have_msa(flags) CPUEXT(flags, MSA)
+
+#endif /* AVUTIL_MIPS_CPU_H */
diff --git a/libavutil/tests/cpu.c b/libavutil/tests/cpu.c
index ce45b715a0..c853371fb3 100644
--- a/libavutil/tests/cpu.c
+++ b/libavutil/tests/cpu.c
@@ -49,6 +49,9 @@ static const struct {
     { AV_CPU_FLAG_SETEND,    "setend"     },
 #elif ARCH_PPC
     { AV_CPU_FLAG_ALTIVEC,   "altivec"    },
+#elif ARCH_MIPS
+    { AV_CPU_FLAG_MMI,       "mmi"        },
+    { AV_CPU_FLAG_MSA,       "msa"        },
 #elif ARCH_X86
     { AV_CPU_FLAG_MMX,       "mmx"        },
     { AV_CPU_FLAG_MMXEXT,    "mmxext"     },
diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c
index 899f68bb32..b3ac76c325 100644
--- a/tests/checkasm/checkasm.c
+++ b/tests/checkasm/checkasm.c
@@ -213,6 +213,9 @@ static const struct {
     { "ALTIVEC",  "altivec",  AV_CPU_FLAG_ALTIVEC },
     { "VSX",      "vsx",      AV_CPU_FLAG_VSX },
     { "POWER8",   "power8",   AV_CPU_FLAG_POWER8 },
+#elif ARCH_MIPS
+    { "MMI",      "mmi",      AV_CPU_FLAG_MMI },
+    { "MSA",      "msa",      AV_CPU_FLAG_MSA },
 #elif ARCH_X86
     { "MMX",      "mmx",      AV_CPU_FLAG_MMX|AV_CPU_FLAG_CMOV },
     { "MMXEXT",   "mmxext",   AV_CPU_FLAG_MMXEXT },
