root/drivers/gpu/drm/arm/malidp_hw.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. malidp500_query_hw
  2. malidp500_enter_config_mode
  3. malidp500_leave_config_mode
  4. malidp500_in_config_mode
  5. malidp500_set_config_valid
  6. malidp500_modeset
  7. malidp_format_get_bpp
  8. malidp500_rotmem_required
  9. malidp500_se_write_pp_coefftab
  10. malidp500_se_set_scaling_coeffs
  11. malidp500_se_calc_mclk
  12. malidp500_enable_memwrite
  13. malidp500_disable_memwrite
  14. malidp550_query_hw
  15. malidp550_enter_config_mode
  16. malidp550_leave_config_mode
  17. malidp550_in_config_mode
  18. malidp550_set_config_valid
  19. malidp550_modeset
  20. malidpx50_get_bytes_per_column
  21. malidp550_rotmem_required
  22. malidp650_rotmem_required
  23. malidp550_se_set_scaling_coeffs
  24. malidp550_se_calc_mclk
  25. malidp550_enable_memwrite
  26. malidp550_disable_memwrite
  27. malidp650_query_hw
  28. malidp_hw_get_format_id
  29. malidp_hw_format_is_linear_only
  30. malidp_hw_format_is_afbc_only
  31. malidp_hw_clear_irq
  32. malidp_de_irq
  33. malidp_de_irq_thread_handler
  34. malidp_de_irq_hw_init
  35. malidp_de_irq_init
  36. malidp_de_irq_fini
  37. malidp_se_irq
  38. malidp_se_irq_hw_init
  39. malidp_se_irq_thread_handler
  40. malidp_se_irq_init
  41. malidp_se_irq_fini

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
   4  * Author: Liviu Dudau <Liviu.Dudau@arm.com>
   5  *
   6  * ARM Mali DP500/DP550/DP650 hardware manipulation routines. This is where
   7  * the difference between various versions of the hardware is being dealt with
   8  * in an attempt to provide to the rest of the driver code a unified view
   9  */
  10 
  11 #include <linux/clk.h>
  12 #include <linux/delay.h>
  13 #include <linux/types.h>
  14 #include <linux/io.h>
  15 
  16 #include <video/videomode.h>
  17 #include <video/display_timing.h>
  18 
  19 #include <drm/drm_fourcc.h>
  20 #include <drm/drm_vblank.h>
  21 #include <drm/drm_print.h>
  22 
  23 #include "malidp_drv.h"
  24 #include "malidp_hw.h"
  25 #include "malidp_mw.h"
  26 
  27 enum {
  28         MW_NOT_ENABLED = 0,     /* SE writeback not enabled */
  29         MW_ONESHOT,             /* SE in one-shot mode for writeback */
  30         MW_START,               /* SE started writeback */
  31         MW_RESTART,             /* SE will start another writeback after this one */
  32         MW_STOP,                /* SE needs to stop after this writeback */
  33 };
  34 
  35 static const struct malidp_format_id malidp500_de_formats[] = {
  36         /*    fourcc,   layers supporting the format,     internal id  */
  37         { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  0 },
  38         { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  1 },
  39         { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  2 },
  40         { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  3 },
  41         { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  4 },
  42         { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  5 },
  43         { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  6 },
  44         { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  7 },
  45         { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  8 },
  46         { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  9 },
  47         { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 10 },
  48         { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 11 },
  49         { DRM_FORMAT_UYVY, DE_VIDEO1, 12 },
  50         { DRM_FORMAT_YUYV, DE_VIDEO1, 13 },
  51         { DRM_FORMAT_NV12, DE_VIDEO1 | SE_MEMWRITE, 14 },
  52         { DRM_FORMAT_YUV420, DE_VIDEO1, 15 },
  53         { DRM_FORMAT_XYUV8888, DE_VIDEO1, 16 },
  54         /* These are supported with AFBC only */
  55         { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1, 14 },
  56         { DRM_FORMAT_VUY888, DE_VIDEO1, 16 },
  57         { DRM_FORMAT_VUY101010, DE_VIDEO1, 17 },
  58         { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1, 18 }
  59 };
  60 
  61 #define MALIDP_ID(__group, __format) \
  62         ((((__group) & 0x7) << 3) | ((__format) & 0x7))
  63 
  64 #define AFBC_YUV_422_FORMAT_ID  MALIDP_ID(5, 1)
  65 
  66 #define MALIDP_COMMON_FORMATS \
  67         /*    fourcc,   layers supporting the format,      internal id   */ \
  68         { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 0) }, \
  69         { DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 1) }, \
  70         { DRM_FORMAT_RGBA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 2) }, \
  71         { DRM_FORMAT_BGRA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 3) }, \
  72         { DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 0) }, \
  73         { DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 1) }, \
  74         { DRM_FORMAT_RGBA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 2) }, \
  75         { DRM_FORMAT_BGRA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 3) }, \
  76         { DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 0) }, \
  77         { DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 1) }, \
  78         { DRM_FORMAT_RGBX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 2) }, \
  79         { DRM_FORMAT_BGRX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 3) }, \
  80         { DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 0) }, \
  81         { DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 1) }, \
  82         { DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 0) }, \
  83         { DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 1) }, \
  84         { DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 2) }, \
  85         { DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 3) }, \
  86         /* This is only supported with linear modifier */       \
  87         { DRM_FORMAT_XYUV8888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) },\
  88         /* This is only supported with AFBC modifier */         \
  89         { DRM_FORMAT_VUY888, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 0) }, \
  90         { DRM_FORMAT_YUYV, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 2) },    \
  91         /* This is only supported with linear modifier */ \
  92         { DRM_FORMAT_UYVY, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 3) },    \
  93         { DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(5, 6) },      \
  94         /* This is only supported with AFBC modifier */ \
  95         { DRM_FORMAT_YUV420_8BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 6) }, \
  96         { DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) }, \
  97         /* This is only supported with linear modifier */ \
  98         { DRM_FORMAT_XVYU2101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
  99         /* This is only supported with AFBC modifier */ \
 100         { DRM_FORMAT_VUY101010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 0)}, \
 101         { DRM_FORMAT_X0L2, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 6)}, \
 102         /* This is only supported with AFBC modifier */ \
 103         { DRM_FORMAT_YUV420_10BIT, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}, \
 104         { DRM_FORMAT_P010, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(6, 7)}
 105 
 106 static const struct malidp_format_id malidp550_de_formats[] = {
 107         MALIDP_COMMON_FORMATS,
 108 };
 109 
 110 static const struct malidp_format_id malidp650_de_formats[] = {
 111         MALIDP_COMMON_FORMATS,
 112         { DRM_FORMAT_X0L0, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 4)},
 113 };
 114 
 115 static const struct malidp_layer malidp500_layers[] = {
 116         /* id, base address, fb pointer address base, stride offset,
 117          *      yuv2rgb matrix offset, mmu control register offset, rotation_features
 118          */
 119         { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE,
 120                 MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY,
 121                 MALIDP500_DE_LV_AD_CTRL },
 122         { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE,
 123                 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
 124                 MALIDP500_DE_LG1_AD_CTRL },
 125         { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE,
 126                 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
 127                 MALIDP500_DE_LG2_AD_CTRL },
 128 };
 129 
 130 static const struct malidp_layer malidp550_layers[] = {
 131         /* id, base address, fb pointer address base, stride offset,
 132          *      yuv2rgb matrix offset, mmu control register offset, rotation_features
 133          */
 134         { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
 135                 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
 136                 MALIDP550_DE_LV1_AD_CTRL },
 137         { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
 138                 MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
 139                 MALIDP550_DE_LG_AD_CTRL },
 140         { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
 141                 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
 142                 MALIDP550_DE_LV2_AD_CTRL },
 143         { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
 144                 MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE, 0 },
 145 };
 146 
 147 static const struct malidp_layer malidp650_layers[] = {
 148         /* id, base address, fb pointer address base, stride offset,
 149          *      yuv2rgb matrix offset, mmu control register offset,
 150          *      rotation_features
 151          */
 152         { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
 153                 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
 154                 MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY,
 155                 MALIDP550_DE_LV1_AD_CTRL },
 156         { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
 157                 MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL,
 158                 ROTATE_COMPRESSED, MALIDP550_DE_LG_AD_CTRL },
 159         { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
 160                 MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
 161                 MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY,
 162                 MALIDP550_DE_LV2_AD_CTRL },
 163         { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
 164                 MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL,
 165                 ROTATE_NONE, 0 },
 166 };
 167 
 168 const u64 malidp_format_modifiers[] = {
 169         /* All RGB formats (except XRGB, RGBX, XBGR, BGRX) */
 170         DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE),
 171         DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR),
 172 
 173         /* All RGB formats > 16bpp (except XRGB, RGBX, XBGR, BGRX) */
 174         DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE | AFBC_SPLIT),
 175 
 176         /* All 8 or 10 bit YUV 444 formats. */
 177         /* In DP550, 10 bit YUV 420 format also supported */
 178         DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE | AFBC_SPLIT),
 179 
 180         /* YUV 420, 422 P1 8 bit and YUV 444 8 bit/10 bit formats */
 181         DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE),
 182         DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16),
 183 
 184         /* YUV 420, 422 P1 8, 10 bit formats */
 185         DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR | AFBC_SPARSE),
 186         DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR),
 187 
 188         /* All formats */
 189         DRM_FORMAT_MOD_LINEAR,
 190 
 191         DRM_FORMAT_MOD_INVALID
 192 };
 193 
 194 #define SE_N_SCALING_COEFFS     96
 195 static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = {
 196         [MALIDP_UPSCALING_COEFFS - 1] = {
 197                 0x0000, 0x0001, 0x0007, 0x0011, 0x001e, 0x002e, 0x003f, 0x0052,
 198                 0x0064, 0x0073, 0x007d, 0x0080, 0x007a, 0x006c, 0x0053, 0x002f,
 199                 0x0000, 0x3fc6, 0x3f83, 0x3f39, 0x3eea, 0x3e9b, 0x3e4f, 0x3e0a,
 200                 0x3dd4, 0x3db0, 0x3da2, 0x3db1, 0x3dde, 0x3e2f, 0x3ea5, 0x3f40,
 201                 0x0000, 0x00e5, 0x01ee, 0x0315, 0x0456, 0x05aa, 0x0709, 0x086c,
 202                 0x09c9, 0x0b15, 0x0c4a, 0x0d5d, 0x0e4a, 0x0f06, 0x0f91, 0x0fe5,
 203                 0x1000, 0x0fe5, 0x0f91, 0x0f06, 0x0e4a, 0x0d5d, 0x0c4a, 0x0b15,
 204                 0x09c9, 0x086c, 0x0709, 0x05aa, 0x0456, 0x0315, 0x01ee, 0x00e5,
 205                 0x0000, 0x3f40, 0x3ea5, 0x3e2f, 0x3dde, 0x3db1, 0x3da2, 0x3db0,
 206                 0x3dd4, 0x3e0a, 0x3e4f, 0x3e9b, 0x3eea, 0x3f39, 0x3f83, 0x3fc6,
 207                 0x0000, 0x002f, 0x0053, 0x006c, 0x007a, 0x0080, 0x007d, 0x0073,
 208                 0x0064, 0x0052, 0x003f, 0x002e, 0x001e, 0x0011, 0x0007, 0x0001
 209         },
 210         [MALIDP_DOWNSCALING_1_5_COEFFS - 1] = {
 211                 0x0059, 0x004f, 0x0041, 0x002e, 0x0016, 0x3ffb, 0x3fd9, 0x3fb4,
 212                 0x3f8c, 0x3f62, 0x3f36, 0x3f09, 0x3edd, 0x3eb3, 0x3e8d, 0x3e6c,
 213                 0x3e52, 0x3e3f, 0x3e35, 0x3e37, 0x3e46, 0x3e61, 0x3e8c, 0x3ec5,
 214                 0x3f0f, 0x3f68, 0x3fd1, 0x004a, 0x00d3, 0x0169, 0x020b, 0x02b8,
 215                 0x036e, 0x042d, 0x04f2, 0x05b9, 0x0681, 0x0745, 0x0803, 0x08ba,
 216                 0x0965, 0x0a03, 0x0a91, 0x0b0d, 0x0b75, 0x0bc6, 0x0c00, 0x0c20,
 217                 0x0c28, 0x0c20, 0x0c00, 0x0bc6, 0x0b75, 0x0b0d, 0x0a91, 0x0a03,
 218                 0x0965, 0x08ba, 0x0803, 0x0745, 0x0681, 0x05b9, 0x04f2, 0x042d,
 219                 0x036e, 0x02b8, 0x020b, 0x0169, 0x00d3, 0x004a, 0x3fd1, 0x3f68,
 220                 0x3f0f, 0x3ec5, 0x3e8c, 0x3e61, 0x3e46, 0x3e37, 0x3e35, 0x3e3f,
 221                 0x3e52, 0x3e6c, 0x3e8d, 0x3eb3, 0x3edd, 0x3f09, 0x3f36, 0x3f62,
 222                 0x3f8c, 0x3fb4, 0x3fd9, 0x3ffb, 0x0016, 0x002e, 0x0041, 0x004f
 223         },
 224         [MALIDP_DOWNSCALING_2_COEFFS - 1] = {
 225                 0x3f19, 0x3f03, 0x3ef0, 0x3edf, 0x3ed0, 0x3ec5, 0x3ebd, 0x3eb9,
 226                 0x3eb9, 0x3ebf, 0x3eca, 0x3ed9, 0x3eef, 0x3f0a, 0x3f2c, 0x3f52,
 227                 0x3f7f, 0x3fb0, 0x3fe8, 0x0026, 0x006a, 0x00b4, 0x0103, 0x0158,
 228                 0x01b1, 0x020d, 0x026c, 0x02cd, 0x032f, 0x0392, 0x03f4, 0x0455,
 229                 0x04b4, 0x051e, 0x0585, 0x05eb, 0x064c, 0x06a8, 0x06fe, 0x074e,
 230                 0x0796, 0x07d5, 0x080c, 0x0839, 0x085c, 0x0875, 0x0882, 0x0887,
 231                 0x0881, 0x0887, 0x0882, 0x0875, 0x085c, 0x0839, 0x080c, 0x07d5,
 232                 0x0796, 0x074e, 0x06fe, 0x06a8, 0x064c, 0x05eb, 0x0585, 0x051e,
 233                 0x04b4, 0x0455, 0x03f4, 0x0392, 0x032f, 0x02cd, 0x026c, 0x020d,
 234                 0x01b1, 0x0158, 0x0103, 0x00b4, 0x006a, 0x0026, 0x3fe8, 0x3fb0,
 235                 0x3f7f, 0x3f52, 0x3f2c, 0x3f0a, 0x3eef, 0x3ed9, 0x3eca, 0x3ebf,
 236                 0x3eb9, 0x3eb9, 0x3ebd, 0x3ec5, 0x3ed0, 0x3edf, 0x3ef0, 0x3f03
 237         },
 238         [MALIDP_DOWNSCALING_2_75_COEFFS - 1] = {
 239                 0x3f51, 0x3f60, 0x3f71, 0x3f84, 0x3f98, 0x3faf, 0x3fc8, 0x3fe3,
 240                 0x0000, 0x001f, 0x0040, 0x0064, 0x008a, 0x00b1, 0x00da, 0x0106,
 241                 0x0133, 0x0160, 0x018e, 0x01bd, 0x01ec, 0x021d, 0x024e, 0x0280,
 242                 0x02b2, 0x02e4, 0x0317, 0x0349, 0x037c, 0x03ad, 0x03df, 0x0410,
 243                 0x0440, 0x0468, 0x048f, 0x04b3, 0x04d6, 0x04f8, 0x0516, 0x0533,
 244                 0x054e, 0x0566, 0x057c, 0x0590, 0x05a0, 0x05ae, 0x05ba, 0x05c3,
 245                 0x05c9, 0x05c3, 0x05ba, 0x05ae, 0x05a0, 0x0590, 0x057c, 0x0566,
 246                 0x054e, 0x0533, 0x0516, 0x04f8, 0x04d6, 0x04b3, 0x048f, 0x0468,
 247                 0x0440, 0x0410, 0x03df, 0x03ad, 0x037c, 0x0349, 0x0317, 0x02e4,
 248                 0x02b2, 0x0280, 0x024e, 0x021d, 0x01ec, 0x01bd, 0x018e, 0x0160,
 249                 0x0133, 0x0106, 0x00da, 0x00b1, 0x008a, 0x0064, 0x0040, 0x001f,
 250                 0x0000, 0x3fe3, 0x3fc8, 0x3faf, 0x3f98, 0x3f84, 0x3f71, 0x3f60
 251         },
 252         [MALIDP_DOWNSCALING_4_COEFFS - 1] = {
 253                 0x0094, 0x00a9, 0x00be, 0x00d4, 0x00ea, 0x0101, 0x0118, 0x012f,
 254                 0x0148, 0x0160, 0x017a, 0x0193, 0x01ae, 0x01c8, 0x01e4, 0x01ff,
 255                 0x021c, 0x0233, 0x024a, 0x0261, 0x0278, 0x028f, 0x02a6, 0x02bd,
 256                 0x02d4, 0x02eb, 0x0302, 0x0319, 0x032f, 0x0346, 0x035d, 0x0374,
 257                 0x038a, 0x0397, 0x03a3, 0x03af, 0x03bb, 0x03c6, 0x03d1, 0x03db,
 258                 0x03e4, 0x03ed, 0x03f6, 0x03fe, 0x0406, 0x040d, 0x0414, 0x041a,
 259                 0x0420, 0x041a, 0x0414, 0x040d, 0x0406, 0x03fe, 0x03f6, 0x03ed,
 260                 0x03e4, 0x03db, 0x03d1, 0x03c6, 0x03bb, 0x03af, 0x03a3, 0x0397,
 261                 0x038a, 0x0374, 0x035d, 0x0346, 0x032f, 0x0319, 0x0302, 0x02eb,
 262                 0x02d4, 0x02bd, 0x02a6, 0x028f, 0x0278, 0x0261, 0x024a, 0x0233,
 263                 0x021c, 0x01ff, 0x01e4, 0x01c8, 0x01ae, 0x0193, 0x017a, 0x0160,
 264                 0x0148, 0x012f, 0x0118, 0x0101, 0x00ea, 0x00d4, 0x00be, 0x00a9
 265         },
 266 };
 267 
 268 #define MALIDP_DE_DEFAULT_PREFETCH_START        5
 269 
 270 static int malidp500_query_hw(struct malidp_hw_device *hwdev)
 271 {
 272         u32 conf = malidp_hw_read(hwdev, MALIDP500_CONFIG_ID);
 273         /* bit 4 of the CONFIG_ID register holds the line size multiplier */
 274         u8 ln_size_mult = conf & 0x10 ? 2 : 1;
 275 
 276         hwdev->min_line_size = 2;
 277         hwdev->max_line_size = SZ_2K * ln_size_mult;
 278         hwdev->rotation_memory[0] = SZ_1K * 64 * ln_size_mult;
 279         hwdev->rotation_memory[1] = 0; /* no second rotation memory bank */
 280 
 281         return 0;
 282 }
 283 
 284 static void malidp500_enter_config_mode(struct malidp_hw_device *hwdev)
 285 {
 286         u32 status, count = 100;
 287 
 288         malidp_hw_setbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
 289         while (count) {
 290                 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
 291                 if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
 292                         break;
 293                 /*
 294                  * entering config mode can take as long as the rendering
 295                  * of a full frame, hence the long sleep here
 296                  */
 297                 usleep_range(1000, 10000);
 298                 count--;
 299         }
 300         WARN(count == 0, "timeout while entering config mode");
 301 }
 302 
 303 static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev)
 304 {
 305         u32 status, count = 100;
 306 
 307         malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
 308         malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
 309         while (count) {
 310                 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
 311                 if ((status & MALIDP500_DC_CONFIG_REQ) == 0)
 312                         break;
 313                 usleep_range(100, 1000);
 314                 count--;
 315         }
 316         WARN(count == 0, "timeout while leaving config mode");
 317 }
 318 
 319 static bool malidp500_in_config_mode(struct malidp_hw_device *hwdev)
 320 {
 321         u32 status;
 322 
 323         status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
 324         if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
 325                 return true;
 326 
 327         return false;
 328 }
 329 
 330 static void malidp500_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
 331 {
 332         if (value)
 333                 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
 334         else
 335                 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
 336 }
 337 
 338 static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
 339 {
 340         u32 val = 0;
 341 
 342         malidp_hw_write(hwdev, hwdev->output_color_depth,
 343                 hwdev->hw->map.out_depth_base);
 344         malidp_hw_clearbits(hwdev, MALIDP500_DC_CLEAR_MASK, MALIDP500_DC_CONTROL);
 345         if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
 346                 val |= MALIDP500_HSYNCPOL;
 347         if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
 348                 val |= MALIDP500_VSYNCPOL;
 349         val |= MALIDP_DE_DEFAULT_PREFETCH_START;
 350         malidp_hw_setbits(hwdev, val, MALIDP500_DC_CONTROL);
 351 
 352         /*
 353          * Mali-DP500 encodes the background color like this:
 354          *    - red   @ MALIDP500_BGND_COLOR[12:0]
 355          *    - green @ MALIDP500_BGND_COLOR[27:16]
 356          *    - blue  @ (MALIDP500_BGND_COLOR + 4)[12:0]
 357          */
 358         val = ((MALIDP_BGND_COLOR_G & 0xfff) << 16) |
 359               (MALIDP_BGND_COLOR_R & 0xfff);
 360         malidp_hw_write(hwdev, val, MALIDP500_BGND_COLOR);
 361         malidp_hw_write(hwdev, MALIDP_BGND_COLOR_B, MALIDP500_BGND_COLOR + 4);
 362 
 363         val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
 364                 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
 365         malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
 366 
 367         val = MALIDP500_DE_V_FRONTPORCH(mode->vfront_porch) |
 368                 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
 369         malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
 370 
 371         val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
 372                 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
 373         malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
 374 
 375         val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
 376         malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
 377 
 378         if (mode->flags & DISPLAY_FLAGS_INTERLACED)
 379                 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
 380         else
 381                 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
 382 }
 383 
 384 int malidp_format_get_bpp(u32 fmt)
 385 {
 386         const struct drm_format_info *info = drm_format_info(fmt);
 387         int bpp = info->cpp[0] * 8;
 388 
 389         if (bpp == 0) {
 390                 switch (fmt) {
 391                 case DRM_FORMAT_VUY101010:
 392                         bpp = 30;
 393                         break;
 394                 case DRM_FORMAT_YUV420_10BIT:
 395                         bpp = 15;
 396                         break;
 397                 case DRM_FORMAT_YUV420_8BIT:
 398                         bpp = 12;
 399                         break;
 400                 default:
 401                         bpp = 0;
 402                 }
 403         }
 404 
 405         return bpp;
 406 }
 407 
 408 static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
 409                                      u16 h, u32 fmt, bool has_modifier)
 410 {
 411         /*
 412          * Each layer needs enough rotation memory to fit 8 lines
 413          * worth of pixel data. Required size is then:
 414          *    size = rotated_width * (bpp / 8) * 8;
 415          */
 416         int bpp = malidp_format_get_bpp(fmt);
 417 
 418         return w * bpp;
 419 }
 420 
 421 static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
 422                                            u32 direction,
 423                                            u16 addr,
 424                                            u8 coeffs_id)
 425 {
 426         int i;
 427         u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL;
 428 
 429         malidp_hw_write(hwdev,
 430                         direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK),
 431                         scaling_control + MALIDP_SE_COEFFTAB_ADDR);
 432         for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i)
 433                 malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA(
 434                                 dp500_se_scaling_coeffs[coeffs_id][i]),
 435                                 scaling_control + MALIDP_SE_COEFFTAB_DATA);
 436 }
 437 
 438 static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
 439                                            struct malidp_se_config *se_config,
 440                                            struct malidp_se_config *old_config)
 441 {
 442         /* Get array indices into dp500_se_scaling_coeffs. */
 443         u8 h = (u8)se_config->hcoeff - 1;
 444         u8 v = (u8)se_config->vcoeff - 1;
 445 
 446         if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) ||
 447                     v >= ARRAY_SIZE(dp500_se_scaling_coeffs)))
 448                 return -EINVAL;
 449 
 450         if ((h == v) && (se_config->hcoeff != old_config->hcoeff ||
 451                          se_config->vcoeff != old_config->vcoeff)) {
 452                 malidp500_se_write_pp_coefftab(hwdev,
 453                                                (MALIDP_SE_V_COEFFTAB |
 454                                                 MALIDP_SE_H_COEFFTAB),
 455                                                0, v);
 456         } else {
 457                 if (se_config->vcoeff != old_config->vcoeff)
 458                         malidp500_se_write_pp_coefftab(hwdev,
 459                                                        MALIDP_SE_V_COEFFTAB,
 460                                                        0, v);
 461                 if (se_config->hcoeff != old_config->hcoeff)
 462                         malidp500_se_write_pp_coefftab(hwdev,
 463                                                        MALIDP_SE_H_COEFFTAB,
 464                                                        0, h);
 465         }
 466 
 467         return 0;
 468 }
 469 
 470 static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
 471                                    struct malidp_se_config *se_config,
 472                                    struct videomode *vm)
 473 {
 474         unsigned long mclk;
 475         unsigned long pxlclk = vm->pixelclock; /* Hz */
 476         unsigned long htotal = vm->hactive + vm->hfront_porch +
 477                                vm->hback_porch + vm->hsync_len;
 478         unsigned long input_size = se_config->input_w * se_config->input_h;
 479         unsigned long a = 10;
 480         long ret;
 481 
 482         /*
 483          * mclk = max(a, 1.5) * pxlclk
 484          *
 485          * To avoid float calculaiton, using 15 instead of 1.5 and div by
 486          * 10 to get mclk.
 487          */
 488         if (se_config->scale_enable) {
 489                 a = 15 * input_size / (htotal * se_config->output_h);
 490                 if (a < 15)
 491                         a = 15;
 492         }
 493         mclk = a * pxlclk / 10;
 494         ret = clk_get_rate(hwdev->mclk);
 495         if (ret < mclk) {
 496                 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
 497                                  mclk / 1000);
 498                 return -EINVAL;
 499         }
 500         return ret;
 501 }
 502 
 503 static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
 504                                      dma_addr_t *addrs, s32 *pitches,
 505                                      int num_planes, u16 w, u16 h, u32 fmt_id,
 506                                      const s16 *rgb2yuv_coeffs)
 507 {
 508         u32 base = MALIDP500_SE_MEMWRITE_BASE;
 509         u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
 510 
 511         /* enable the scaling engine block */
 512         malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
 513 
 514         /* restart the writeback if already enabled */
 515         if (hwdev->mw_state != MW_NOT_ENABLED)
 516                 hwdev->mw_state = MW_RESTART;
 517         else
 518                 hwdev->mw_state = MW_START;
 519 
 520         malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
 521         switch (num_planes) {
 522         case 2:
 523                 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
 524                 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
 525                 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
 526                 /* fall through */
 527         case 1:
 528                 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
 529                 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
 530                 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
 531                 break;
 532         default:
 533                 WARN(1, "Invalid number of planes");
 534         }
 535 
 536         malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
 537                         MALIDP500_SE_MEMWRITE_OUT_SIZE);
 538 
 539         if (rgb2yuv_coeffs) {
 540                 int i;
 541 
 542                 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
 543                         malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
 544                                         MALIDP500_SE_RGB_YUV_COEFFS + i * 4);
 545                 }
 546         }
 547 
 548         malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
 549 
 550         return 0;
 551 }
 552 
 553 static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev)
 554 {
 555         u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
 556 
 557         if (hwdev->mw_state == MW_START || hwdev->mw_state == MW_RESTART)
 558                 hwdev->mw_state = MW_STOP;
 559         malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
 560         malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
 561 }
 562 
 563 static int malidp550_query_hw(struct malidp_hw_device *hwdev)
 564 {
 565         u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
 566         u8 ln_size = (conf >> 4) & 0x3, rsize;
 567 
 568         hwdev->min_line_size = 2;
 569 
 570         switch (ln_size) {
 571         case 0:
 572                 hwdev->max_line_size = SZ_2K;
 573                 /* two banks of 64KB for rotation memory */
 574                 rsize = 64;
 575                 break;
 576         case 1:
 577                 hwdev->max_line_size = SZ_4K;
 578                 /* two banks of 128KB for rotation memory */
 579                 rsize = 128;
 580                 break;
 581         case 2:
 582                 hwdev->max_line_size = 1280;
 583                 /* two banks of 40KB for rotation memory */
 584                 rsize = 40;
 585                 break;
 586         case 3:
 587                 /* reserved value */
 588                 hwdev->max_line_size = 0;
 589                 return -EINVAL;
 590         }
 591 
 592         hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
 593         return 0;
 594 }
 595 
 596 static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev)
 597 {
 598         u32 status, count = 100;
 599 
 600         malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
 601         while (count) {
 602                 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
 603                 if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
 604                         break;
 605                 /*
 606                  * entering config mode can take as long as the rendering
 607                  * of a full frame, hence the long sleep here
 608                  */
 609                 usleep_range(1000, 10000);
 610                 count--;
 611         }
 612         WARN(count == 0, "timeout while entering config mode");
 613 }
 614 
 615 static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
 616 {
 617         u32 status, count = 100;
 618 
 619         malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
 620         malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
 621         while (count) {
 622                 status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
 623                 if ((status & MALIDP550_DC_CONFIG_REQ) == 0)
 624                         break;
 625                 usleep_range(100, 1000);
 626                 count--;
 627         }
 628         WARN(count == 0, "timeout while leaving config mode");
 629 }
 630 
 631 static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev)
 632 {
 633         u32 status;
 634 
 635         status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
 636         if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
 637                 return true;
 638 
 639         return false;
 640 }
 641 
 642 static void malidp550_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
 643 {
 644         if (value)
 645                 malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
 646         else
 647                 malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
 648 }
 649 
 650 static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
 651 {
 652         u32 val = MALIDP_DE_DEFAULT_PREFETCH_START;
 653 
 654         malidp_hw_write(hwdev, hwdev->output_color_depth,
 655                 hwdev->hw->map.out_depth_base);
 656         malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL);
 657         /*
 658          * Mali-DP550 and Mali-DP650 encode the background color like this:
 659          *   - red   @ MALIDP550_DE_BGND_COLOR[23:16]
 660          *   - green @ MALIDP550_DE_BGND_COLOR[15:8]
 661          *   - blue  @ MALIDP550_DE_BGND_COLOR[7:0]
 662          *
 663          * We need to truncate the least significant 4 bits from the default
 664          * MALIDP_BGND_COLOR_x values
 665          */
 666         val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) |
 667               (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) |
 668               ((MALIDP_BGND_COLOR_B >> 4) & 0xff);
 669         malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR);
 670 
 671         val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
 672                 MALIDP_DE_H_BACKPORCH(mode->hback_porch);
 673         malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
 674 
 675         val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) |
 676                 MALIDP_DE_V_BACKPORCH(mode->vback_porch);
 677         malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
 678 
 679         val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
 680                 MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
 681         if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
 682                 val |= MALIDP550_HSYNCPOL;
 683         if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
 684                 val |= MALIDP550_VSYNCPOL;
 685         malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
 686 
 687         val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
 688         malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
 689 
 690         if (mode->flags & DISPLAY_FLAGS_INTERLACED)
 691                 malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
 692         else
 693                 malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
 694 }
 695 
 696 static int malidpx50_get_bytes_per_column(u32 fmt)
 697 {
 698         u32 bytes_per_column;
 699 
 700         switch (fmt) {
 701         /* 8 lines at 4 bytes per pixel */
 702         case DRM_FORMAT_ARGB2101010:
 703         case DRM_FORMAT_ABGR2101010:
 704         case DRM_FORMAT_RGBA1010102:
 705         case DRM_FORMAT_BGRA1010102:
 706         case DRM_FORMAT_ARGB8888:
 707         case DRM_FORMAT_ABGR8888:
 708         case DRM_FORMAT_RGBA8888:
 709         case DRM_FORMAT_BGRA8888:
 710         case DRM_FORMAT_XRGB8888:
 711         case DRM_FORMAT_XBGR8888:
 712         case DRM_FORMAT_RGBX8888:
 713         case DRM_FORMAT_BGRX8888:
 714         case DRM_FORMAT_RGB888:
 715         case DRM_FORMAT_BGR888:
 716         /* 16 lines at 2 bytes per pixel */
 717         case DRM_FORMAT_RGBA5551:
 718         case DRM_FORMAT_ABGR1555:
 719         case DRM_FORMAT_RGB565:
 720         case DRM_FORMAT_BGR565:
 721         case DRM_FORMAT_UYVY:
 722         case DRM_FORMAT_YUYV:
 723         case DRM_FORMAT_X0L0:
 724                 bytes_per_column = 32;
 725                 break;
 726         /* 16 lines at 1.5 bytes per pixel */
 727         case DRM_FORMAT_NV12:
 728         case DRM_FORMAT_YUV420:
 729         /* 8 lines at 3 bytes per pixel */
 730         case DRM_FORMAT_VUY888:
 731         /* 16 lines at 12 bits per pixel */
 732         case DRM_FORMAT_YUV420_8BIT:
 733         /* 8 lines at 3 bytes per pixel */
 734         case DRM_FORMAT_P010:
 735                 bytes_per_column = 24;
 736                 break;
 737         /* 8 lines at 30 bits per pixel */
 738         case DRM_FORMAT_VUY101010:
 739         /* 16 lines at 15 bits per pixel */
 740         case DRM_FORMAT_YUV420_10BIT:
 741                 bytes_per_column = 30;
 742                 break;
 743         default:
 744                 return -EINVAL;
 745         }
 746 
 747         return bytes_per_column;
 748 }
 749 
 750 static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
 751                                      u16 h, u32 fmt, bool has_modifier)
 752 {
 753         int bytes_per_column = 0;
 754 
 755         switch (fmt) {
 756         /* 8 lines at 15 bits per pixel */
 757         case DRM_FORMAT_YUV420_10BIT:
 758                 bytes_per_column = 15;
 759                 break;
 760         /* Uncompressed YUV 420 10 bit single plane cannot be rotated */
 761         case DRM_FORMAT_X0L2:
 762                 if (has_modifier)
 763                         bytes_per_column = 8;
 764                 else
 765                         return -EINVAL;
 766                 break;
 767         default:
 768                 bytes_per_column = malidpx50_get_bytes_per_column(fmt);
 769         }
 770 
 771         if (bytes_per_column == -EINVAL)
 772                 return bytes_per_column;
 773 
 774         return w * bytes_per_column;
 775 }
 776 
 777 static int malidp650_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
 778                                      u16 h, u32 fmt, bool has_modifier)
 779 {
 780         int bytes_per_column = 0;
 781 
 782         switch (fmt) {
 783         /* 16 lines at 2 bytes per pixel */
 784         case DRM_FORMAT_X0L2:
 785                 bytes_per_column = 32;
 786                 break;
 787         default:
 788                 bytes_per_column = malidpx50_get_bytes_per_column(fmt);
 789         }
 790 
 791         if (bytes_per_column == -EINVAL)
 792                 return bytes_per_column;
 793 
 794         return w * bytes_per_column;
 795 }
 796 
 797 static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
 798                                            struct malidp_se_config *se_config,
 799                                            struct malidp_se_config *old_config)
 800 {
 801         u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) |
 802                    MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK);
 803         u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) |
 804                         MALIDP550_SE_CTL_HCSEL(se_config->hcoeff);
 805 
 806         malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL);
 807         malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL);
 808         return 0;
 809 }
 810 
 811 static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
 812                                    struct malidp_se_config *se_config,
 813                                    struct videomode *vm)
 814 {
 815         unsigned long mclk;
 816         unsigned long pxlclk = vm->pixelclock;
 817         unsigned long htotal = vm->hactive + vm->hfront_porch +
 818                                vm->hback_porch + vm->hsync_len;
 819         unsigned long numerator = 1, denominator = 1;
 820         long ret;
 821 
 822         if (se_config->scale_enable) {
 823                 numerator = max(se_config->input_w, se_config->output_w) *
 824                             se_config->input_h;
 825                 numerator += se_config->output_w *
 826                              (se_config->output_h -
 827                               min(se_config->input_h, se_config->output_h));
 828                 denominator = (htotal - 2) * se_config->output_h;
 829         }
 830 
 831         /* mclk can't be slower than pxlclk. */
 832         if (numerator < denominator)
 833                 numerator = denominator = 1;
 834         mclk = (pxlclk * numerator) / denominator;
 835         ret = clk_get_rate(hwdev->mclk);
 836         if (ret < mclk) {
 837                 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
 838                                  mclk / 1000);
 839                 return -EINVAL;
 840         }
 841         return ret;
 842 }
 843 
 844 static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
 845                                      dma_addr_t *addrs, s32 *pitches,
 846                                      int num_planes, u16 w, u16 h, u32 fmt_id,
 847                                      const s16 *rgb2yuv_coeffs)
 848 {
 849         u32 base = MALIDP550_SE_MEMWRITE_BASE;
 850         u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
 851 
 852         /* enable the scaling engine block */
 853         malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
 854 
 855         hwdev->mw_state = MW_ONESHOT;
 856 
 857         malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
 858         switch (num_planes) {
 859         case 2:
 860                 malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
 861                 malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
 862                 malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
 863                 /* fall through */
 864         case 1:
 865                 malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
 866                 malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
 867                 malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
 868                 break;
 869         default:
 870                 WARN(1, "Invalid number of planes");
 871         }
 872 
 873         malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
 874                         MALIDP550_SE_MEMWRITE_OUT_SIZE);
 875         malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
 876                           MALIDP550_SE_CONTROL);
 877 
 878         if (rgb2yuv_coeffs) {
 879                 int i;
 880 
 881                 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
 882                         malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
 883                                         MALIDP550_SE_RGB_YUV_COEFFS + i * 4);
 884                 }
 885         }
 886 
 887         return 0;
 888 }
 889 
 890 static void malidp550_disable_memwrite(struct malidp_hw_device *hwdev)
 891 {
 892         u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
 893 
 894         malidp_hw_clearbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
 895                             MALIDP550_SE_CONTROL);
 896         malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
 897 }
 898 
 899 static int malidp650_query_hw(struct malidp_hw_device *hwdev)
 900 {
 901         u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
 902         u8 ln_size = (conf >> 4) & 0x3, rsize;
 903 
 904         hwdev->min_line_size = 4;
 905 
 906         switch (ln_size) {
 907         case 0:
 908         case 2:
 909                 /* reserved values */
 910                 hwdev->max_line_size = 0;
 911                 return -EINVAL;
 912         case 1:
 913                 hwdev->max_line_size = SZ_4K;
 914                 /* two banks of 128KB for rotation memory */
 915                 rsize = 128;
 916                 break;
 917         case 3:
 918                 hwdev->max_line_size = 2560;
 919                 /* two banks of 80KB for rotation memory */
 920                 rsize = 80;
 921         }
 922 
 923         hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
 924         return 0;
 925 }
 926 
 927 const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
 928         [MALIDP_500] = {
 929                 .map = {
 930                         .coeffs_base = MALIDP500_COEFFS_BASE,
 931                         .se_base = MALIDP500_SE_BASE,
 932                         .dc_base = MALIDP500_DC_BASE,
 933                         .out_depth_base = MALIDP500_OUTPUT_DEPTH,
 934                         .features = 0,  /* no CLEARIRQ register */
 935                         .n_layers = ARRAY_SIZE(malidp500_layers),
 936                         .layers = malidp500_layers,
 937                         .de_irq_map = {
 938                                 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
 939                                             MALIDP500_DE_IRQ_AXI_ERR |
 940                                             MALIDP500_DE_IRQ_VSYNC |
 941                                             MALIDP500_DE_IRQ_GLOBAL,
 942                                 .vsync_irq = MALIDP500_DE_IRQ_VSYNC,
 943                                 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
 944                                             MALIDP500_DE_IRQ_AXI_ERR |
 945                                             MALIDP500_DE_IRQ_SATURATION,
 946                         },
 947                         .se_irq_map = {
 948                                 .irq_mask = MALIDP500_SE_IRQ_CONF_MODE |
 949                                             MALIDP500_SE_IRQ_CONF_VALID |
 950                                             MALIDP500_SE_IRQ_GLOBAL,
 951                                 .vsync_irq = MALIDP500_SE_IRQ_CONF_VALID,
 952                                 .err_mask = MALIDP500_SE_IRQ_INIT_BUSY |
 953                                             MALIDP500_SE_IRQ_AXI_ERROR |
 954                                             MALIDP500_SE_IRQ_OVERRUN,
 955                         },
 956                         .dc_irq_map = {
 957                                 .irq_mask = MALIDP500_DE_IRQ_CONF_VALID,
 958                                 .vsync_irq = MALIDP500_DE_IRQ_CONF_VALID,
 959                         },
 960                         .pixel_formats = malidp500_de_formats,
 961                         .n_pixel_formats = ARRAY_SIZE(malidp500_de_formats),
 962                         .bus_align_bytes = 8,
 963                 },
 964                 .query_hw = malidp500_query_hw,
 965                 .enter_config_mode = malidp500_enter_config_mode,
 966                 .leave_config_mode = malidp500_leave_config_mode,
 967                 .in_config_mode = malidp500_in_config_mode,
 968                 .set_config_valid = malidp500_set_config_valid,
 969                 .modeset = malidp500_modeset,
 970                 .rotmem_required = malidp500_rotmem_required,
 971                 .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs,
 972                 .se_calc_mclk = malidp500_se_calc_mclk,
 973                 .enable_memwrite = malidp500_enable_memwrite,
 974                 .disable_memwrite = malidp500_disable_memwrite,
 975                 .features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
 976         },
 977         [MALIDP_550] = {
 978                 .map = {
 979                         .coeffs_base = MALIDP550_COEFFS_BASE,
 980                         .se_base = MALIDP550_SE_BASE,
 981                         .dc_base = MALIDP550_DC_BASE,
 982                         .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
 983                         .features = MALIDP_REGMAP_HAS_CLEARIRQ |
 984                                     MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
 985                                     MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT |
 986                                     MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
 987                         .n_layers = ARRAY_SIZE(malidp550_layers),
 988                         .layers = malidp550_layers,
 989                         .de_irq_map = {
 990                                 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
 991                                             MALIDP550_DE_IRQ_VSYNC,
 992                                 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
 993                                 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
 994                                             MALIDP550_DE_IRQ_SATURATION |
 995                                             MALIDP550_DE_IRQ_AXI_ERR,
 996                         },
 997                         .se_irq_map = {
 998                                 .irq_mask = MALIDP550_SE_IRQ_EOW,
 999                                 .vsync_irq = MALIDP550_SE_IRQ_EOW,
1000                                 .err_mask  = MALIDP550_SE_IRQ_AXI_ERR |
1001                                              MALIDP550_SE_IRQ_OVR |
1002                                              MALIDP550_SE_IRQ_IBSY,
1003                         },
1004                         .dc_irq_map = {
1005                                 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1006                                             MALIDP550_DC_IRQ_SE,
1007                                 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1008                         },
1009                         .pixel_formats = malidp550_de_formats,
1010                         .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
1011                         .bus_align_bytes = 8,
1012                 },
1013                 .query_hw = malidp550_query_hw,
1014                 .enter_config_mode = malidp550_enter_config_mode,
1015                 .leave_config_mode = malidp550_leave_config_mode,
1016                 .in_config_mode = malidp550_in_config_mode,
1017                 .set_config_valid = malidp550_set_config_valid,
1018                 .modeset = malidp550_modeset,
1019                 .rotmem_required = malidp550_rotmem_required,
1020                 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1021                 .se_calc_mclk = malidp550_se_calc_mclk,
1022                 .enable_memwrite = malidp550_enable_memwrite,
1023                 .disable_memwrite = malidp550_disable_memwrite,
1024                 .features = 0,
1025         },
1026         [MALIDP_650] = {
1027                 .map = {
1028                         .coeffs_base = MALIDP550_COEFFS_BASE,
1029                         .se_base = MALIDP550_SE_BASE,
1030                         .dc_base = MALIDP550_DC_BASE,
1031                         .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
1032                         .features = MALIDP_REGMAP_HAS_CLEARIRQ |
1033                                     MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
1034                                     MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
1035                         .n_layers = ARRAY_SIZE(malidp650_layers),
1036                         .layers = malidp650_layers,
1037                         .de_irq_map = {
1038                                 .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
1039                                             MALIDP650_DE_IRQ_DRIFT |
1040                                             MALIDP550_DE_IRQ_VSYNC,
1041                                 .vsync_irq = MALIDP550_DE_IRQ_VSYNC,
1042                                 .err_mask = MALIDP_DE_IRQ_UNDERRUN |
1043                                             MALIDP650_DE_IRQ_DRIFT |
1044                                             MALIDP550_DE_IRQ_SATURATION |
1045                                             MALIDP550_DE_IRQ_AXI_ERR |
1046                                             MALIDP650_DE_IRQ_ACEV1 |
1047                                             MALIDP650_DE_IRQ_ACEV2 |
1048                                             MALIDP650_DE_IRQ_ACEG |
1049                                             MALIDP650_DE_IRQ_AXIEP,
1050                         },
1051                         .se_irq_map = {
1052                                 .irq_mask = MALIDP550_SE_IRQ_EOW,
1053                                 .vsync_irq = MALIDP550_SE_IRQ_EOW,
1054                                 .err_mask = MALIDP550_SE_IRQ_AXI_ERR |
1055                                             MALIDP550_SE_IRQ_OVR |
1056                                             MALIDP550_SE_IRQ_IBSY,
1057                         },
1058                         .dc_irq_map = {
1059                                 .irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
1060                                             MALIDP550_DC_IRQ_SE,
1061                                 .vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
1062                         },
1063                         .pixel_formats = malidp650_de_formats,
1064                         .n_pixel_formats = ARRAY_SIZE(malidp650_de_formats),
1065                         .bus_align_bytes = 16,
1066                 },
1067                 .query_hw = malidp650_query_hw,
1068                 .enter_config_mode = malidp550_enter_config_mode,
1069                 .leave_config_mode = malidp550_leave_config_mode,
1070                 .in_config_mode = malidp550_in_config_mode,
1071                 .set_config_valid = malidp550_set_config_valid,
1072                 .modeset = malidp550_modeset,
1073                 .rotmem_required = malidp650_rotmem_required,
1074                 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
1075                 .se_calc_mclk = malidp550_se_calc_mclk,
1076                 .enable_memwrite = malidp550_enable_memwrite,
1077                 .disable_memwrite = malidp550_disable_memwrite,
1078                 .features = 0,
1079         },
1080 };
1081 
1082 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
1083                            u8 layer_id, u32 format, bool has_modifier)
1084 {
1085         unsigned int i;
1086 
1087         for (i = 0; i < map->n_pixel_formats; i++) {
1088                 if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
1089                     (map->pixel_formats[i].format == format)) {
1090                         /*
1091                          * In some DP550 and DP650, DRM_FORMAT_YUYV + AFBC modifier
1092                          * is supported by a different h/w format id than
1093                          * DRM_FORMAT_YUYV (only).
1094                          */
1095                         if (format == DRM_FORMAT_YUYV &&
1096                             (has_modifier) &&
1097                             (map->features & MALIDP_DEVICE_AFBC_YUYV_USE_422_P2))
1098                                 return AFBC_YUV_422_FORMAT_ID;
1099                         else
1100                                 return map->pixel_formats[i].id;
1101                 }
1102         }
1103 
1104         return MALIDP_INVALID_FORMAT_ID;
1105 }
1106 
1107 bool malidp_hw_format_is_linear_only(u32 format)
1108 {
1109         switch (format) {
1110         case DRM_FORMAT_ARGB2101010:
1111         case DRM_FORMAT_RGBA1010102:
1112         case DRM_FORMAT_BGRA1010102:
1113         case DRM_FORMAT_ARGB8888:
1114         case DRM_FORMAT_RGBA8888:
1115         case DRM_FORMAT_BGRA8888:
1116         case DRM_FORMAT_XBGR8888:
1117         case DRM_FORMAT_XRGB8888:
1118         case DRM_FORMAT_RGBX8888:
1119         case DRM_FORMAT_BGRX8888:
1120         case DRM_FORMAT_RGB888:
1121         case DRM_FORMAT_RGB565:
1122         case DRM_FORMAT_ARGB1555:
1123         case DRM_FORMAT_RGBA5551:
1124         case DRM_FORMAT_BGRA5551:
1125         case DRM_FORMAT_UYVY:
1126         case DRM_FORMAT_XYUV8888:
1127         case DRM_FORMAT_XVYU2101010:
1128         case DRM_FORMAT_X0L2:
1129         case DRM_FORMAT_X0L0:
1130                 return true;
1131         default:
1132                 return false;
1133         }
1134 }
1135 
1136 bool malidp_hw_format_is_afbc_only(u32 format)
1137 {
1138         switch (format) {
1139         case DRM_FORMAT_VUY888:
1140         case DRM_FORMAT_VUY101010:
1141         case DRM_FORMAT_YUV420_8BIT:
1142         case DRM_FORMAT_YUV420_10BIT:
1143                 return true;
1144         default:
1145                 return false;
1146         }
1147 }
1148 
1149 static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
1150 {
1151         u32 base = malidp_get_block_base(hwdev, block);
1152 
1153         if (hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ)
1154                 malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ);
1155         else
1156                 malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS);
1157 }
1158 
1159 static irqreturn_t malidp_de_irq(int irq, void *arg)
1160 {
1161         struct drm_device *drm = arg;
1162         struct malidp_drm *malidp = drm->dev_private;
1163         struct malidp_hw_device *hwdev;
1164         struct malidp_hw *hw;
1165         const struct malidp_irq_map *de;
1166         u32 status, mask, dc_status;
1167         irqreturn_t ret = IRQ_NONE;
1168 
1169         hwdev = malidp->dev;
1170         hw = hwdev->hw;
1171         de = &hw->map.de_irq_map;
1172 
1173         /*
1174          * if we are suspended it is likely that we were invoked because
1175          * we share an interrupt line with some other driver, don't try
1176          * to read the hardware registers
1177          */
1178         if (hwdev->pm_suspended)
1179                 return IRQ_NONE;
1180 
1181         /* first handle the config valid IRQ */
1182         dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1183         if (dc_status & hw->map.dc_irq_map.vsync_irq) {
1184                 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
1185                 /* do we have a page flip event? */
1186                 if (malidp->event != NULL) {
1187                         spin_lock(&drm->event_lock);
1188                         drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
1189                         malidp->event = NULL;
1190                         spin_unlock(&drm->event_lock);
1191                 }
1192                 atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE);
1193                 ret = IRQ_WAKE_THREAD;
1194         }
1195 
1196         status = malidp_hw_read(hwdev, MALIDP_REG_STATUS);
1197         if (!(status & de->irq_mask))
1198                 return ret;
1199 
1200         mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
1201         /* keep the status of the enabled interrupts, plus the error bits */
1202         status &= (mask | de->err_mask);
1203         if ((status & de->vsync_irq) && malidp->crtc.enabled)
1204                 drm_crtc_handle_vblank(&malidp->crtc);
1205 
1206 #ifdef CONFIG_DEBUG_FS
1207         if (status & de->err_mask) {
1208                 malidp_error(malidp, &malidp->de_errors, status,
1209                              drm_crtc_vblank_count(&malidp->crtc));
1210         }
1211 #endif
1212         malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);
1213 
1214         return (ret == IRQ_NONE) ? IRQ_HANDLED : ret;
1215 }
1216 
1217 static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg)
1218 {
1219         struct drm_device *drm = arg;
1220         struct malidp_drm *malidp = drm->dev_private;
1221 
1222         wake_up(&malidp->wq);
1223 
1224         return IRQ_HANDLED;
1225 }
1226 
1227 void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev)
1228 {
1229         /* ensure interrupts are disabled */
1230         malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1231         malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1232         malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1233         malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1234 
1235         /* first enable the DC block IRQs */
1236         malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
1237                              hwdev->hw->map.dc_irq_map.irq_mask);
1238 
1239         /* now enable the DE block IRQs */
1240         malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
1241                              hwdev->hw->map.de_irq_map.irq_mask);
1242 }
1243 
1244 int malidp_de_irq_init(struct drm_device *drm, int irq)
1245 {
1246         struct malidp_drm *malidp = drm->dev_private;
1247         struct malidp_hw_device *hwdev = malidp->dev;
1248         int ret;
1249 
1250         /* ensure interrupts are disabled */
1251         malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1252         malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1253         malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1254         malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1255 
1256         ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq,
1257                                         malidp_de_irq_thread_handler,
1258                                         IRQF_SHARED, "malidp-de", drm);
1259         if (ret < 0) {
1260                 DRM_ERROR("failed to install DE IRQ handler\n");
1261                 return ret;
1262         }
1263 
1264         malidp_de_irq_hw_init(hwdev);
1265 
1266         return 0;
1267 }
1268 
1269 void malidp_de_irq_fini(struct malidp_hw_device *hwdev)
1270 {
1271         malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
1272                               hwdev->hw->map.de_irq_map.irq_mask);
1273         malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK,
1274                               hwdev->hw->map.dc_irq_map.irq_mask);
1275 }
1276 
1277 static irqreturn_t malidp_se_irq(int irq, void *arg)
1278 {
1279         struct drm_device *drm = arg;
1280         struct malidp_drm *malidp = drm->dev_private;
1281         struct malidp_hw_device *hwdev = malidp->dev;
1282         struct malidp_hw *hw = hwdev->hw;
1283         const struct malidp_irq_map *se = &hw->map.se_irq_map;
1284         u32 status, mask;
1285 
1286         /*
1287          * if we are suspended it is likely that we were invoked because
1288          * we share an interrupt line with some other driver, don't try
1289          * to read the hardware registers
1290          */
1291         if (hwdev->pm_suspended)
1292                 return IRQ_NONE;
1293 
1294         status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS);
1295         if (!(status & (se->irq_mask | se->err_mask)))
1296                 return IRQ_NONE;
1297 
1298 #ifdef CONFIG_DEBUG_FS
1299         if (status & se->err_mask)
1300                 malidp_error(malidp, &malidp->se_errors, status,
1301                              drm_crtc_vblank_count(&malidp->crtc));
1302 #endif
1303         mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ);
1304         status &= mask;
1305 
1306         if (status & se->vsync_irq) {
1307                 switch (hwdev->mw_state) {
1308                 case MW_ONESHOT:
1309                         drm_writeback_signal_completion(&malidp->mw_connector, 0);
1310                         break;
1311                 case MW_STOP:
1312                         drm_writeback_signal_completion(&malidp->mw_connector, 0);
1313                         /* disable writeback after stop */
1314                         hwdev->mw_state = MW_NOT_ENABLED;
1315                         break;
1316                 case MW_RESTART:
1317                         drm_writeback_signal_completion(&malidp->mw_connector, 0);
1318                         /* fall through - to a new start */
1319                 case MW_START:
1320                         /* writeback started, need to emulate one-shot mode */
1321                         hw->disable_memwrite(hwdev);
1322                         /*
1323                          * only set config_valid HW bit if there is no other update
1324                          * in progress or if we raced ahead of the DE IRQ handler
1325                          * and config_valid flag will not be update until later
1326                          */
1327                         status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1328                         if ((atomic_read(&malidp->config_valid) != MALIDP_CONFIG_START) ||
1329                             (status & hw->map.dc_irq_map.vsync_irq))
1330                                 hw->set_config_valid(hwdev, 1);
1331                         break;
1332                 }
1333         }
1334 
1335         malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status);
1336 
1337         return IRQ_HANDLED;
1338 }
1339 
1340 void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev)
1341 {
1342         /* ensure interrupts are disabled */
1343         malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1344         malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1345 
1346         malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK,
1347                              hwdev->hw->map.se_irq_map.irq_mask);
1348 }
1349 
1350 static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
1351 {
1352         return IRQ_HANDLED;
1353 }
1354 
1355 int malidp_se_irq_init(struct drm_device *drm, int irq)
1356 {
1357         struct malidp_drm *malidp = drm->dev_private;
1358         struct malidp_hw_device *hwdev = malidp->dev;
1359         int ret;
1360 
1361         /* ensure interrupts are disabled */
1362         malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1363         malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1364 
1365         ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq,
1366                                         malidp_se_irq_thread_handler,
1367                                         IRQF_SHARED, "malidp-se", drm);
1368         if (ret < 0) {
1369                 DRM_ERROR("failed to install SE IRQ handler\n");
1370                 return ret;
1371         }
1372 
1373         hwdev->mw_state = MW_NOT_ENABLED;
1374         malidp_se_irq_hw_init(hwdev);
1375 
1376         return 0;
1377 }
1378 
1379 void malidp_se_irq_fini(struct malidp_hw_device *hwdev)
1380 {
1381         malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK,
1382                               hwdev->hw->map.se_irq_map.irq_mask);
1383 }

/* [<][>][^][v][top][bottom][index][help] */