Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  *
0004  * (C) COPYRIGHT 2013-2016 ARM Limited. All rights reserved.
0005  *
0006  * ARM Mali DP hardware manipulation routines.
0007  */
0008 
0009 #ifndef __MALIDP_HW_H__
0010 #define __MALIDP_HW_H__
0011 
0012 #include <linux/bitops.h>
0013 #include "malidp_regs.h"
0014 
0015 struct videomode;
0016 struct clk;
0017 
0018 /* Mali DP IP blocks */
0019 enum {
0020     MALIDP_DE_BLOCK = 0,
0021     MALIDP_SE_BLOCK,
0022     MALIDP_DC_BLOCK
0023 };
0024 
0025 /* Mali DP layer IDs */
0026 enum {
0027     DE_VIDEO1 = BIT(0),
0028     DE_GRAPHICS1 = BIT(1),
0029     DE_GRAPHICS2 = BIT(2), /* used only in DP500 */
0030     DE_VIDEO2 = BIT(3),
0031     DE_SMART = BIT(4),
0032     SE_MEMWRITE = BIT(5),
0033 };
0034 
0035 enum rotation_features {
0036     ROTATE_NONE,        /* does not support rotation at all */
0037     ROTATE_ANY,     /* supports rotation on any buffers */
0038     ROTATE_COMPRESSED,  /* supports rotation only on compressed buffers */
0039 };
0040 
0041 struct malidp_format_id {
0042     u32 format;     /* DRM fourcc */
0043     u8 layer;       /* bitmask of layers supporting it */
0044     u8 id;          /* used internally */
0045 };
0046 
0047 #define MALIDP_INVALID_FORMAT_ID    0xff
0048 
0049 /*
0050  * hide the differences between register maps
0051  * by using a common structure to hold the
0052  * base register offsets
0053  */
0054 
0055 struct malidp_irq_map {
0056     u32 irq_mask;       /* mask of IRQs that can be enabled in the block */
0057     u32 vsync_irq;      /* IRQ bit used for signaling during VSYNC */
0058     u32 err_mask;       /* mask of bits that represent errors */
0059 };
0060 
0061 struct malidp_layer {
0062     u16 id;         /* layer ID */
0063     u16 base;       /* address offset for the register bank */
0064     u16 ptr;        /* address offset for the pointer register */
0065     u16 stride_offset;  /* offset to the first stride register. */
0066     s16 yuv2rgb_offset; /* offset to the YUV->RGB matrix entries */
0067     u16 mmu_ctrl_offset;    /* offset to the MMU control register */
0068     enum rotation_features rot; /* type of rotation supported */
0069     /* address offset for the AFBC decoder registers */
0070     u16 afbc_decoder_offset;
0071 };
0072 
0073 enum malidp_scaling_coeff_set {
0074     MALIDP_UPSCALING_COEFFS = 1,
0075     MALIDP_DOWNSCALING_1_5_COEFFS = 2,
0076     MALIDP_DOWNSCALING_2_COEFFS = 3,
0077     MALIDP_DOWNSCALING_2_75_COEFFS = 4,
0078     MALIDP_DOWNSCALING_4_COEFFS = 5,
0079 };
0080 
0081 struct malidp_se_config {
0082     u8 scale_enable : 1;
0083     u8 enhancer_enable : 1;
0084     u8 hcoeff : 3;
0085     u8 vcoeff : 3;
0086     u8 plane_src_id;
0087     u16 input_w, input_h;
0088     u16 output_w, output_h;
0089     u32 h_init_phase, h_delta_phase;
0090     u32 v_init_phase, v_delta_phase;
0091 };
0092 
0093 /* regmap features */
0094 #define MALIDP_REGMAP_HAS_CLEARIRQ              BIT(0)
0095 #define MALIDP_DEVICE_AFBC_SUPPORT_SPLIT            BIT(1)
0096 #define MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT     BIT(2)
0097 #define MALIDP_DEVICE_AFBC_YUYV_USE_422_P2          BIT(3)
0098 
0099 struct malidp_hw_regmap {
0100     /* address offset of the DE register bank */
0101     /* is always 0x0000 */
0102     /* address offset of the DE coefficients registers */
0103     const u16 coeffs_base;
0104     /* address offset of the SE registers bank */
0105     const u16 se_base;
0106     /* address offset of the DC registers bank */
0107     const u16 dc_base;
0108 
0109     /* address offset for the output depth register */
0110     const u16 out_depth_base;
0111 
0112     /* bitmap with register map features */
0113     const u8 features;
0114 
0115     /* list of supported layers */
0116     const u8 n_layers;
0117     const struct malidp_layer *layers;
0118 
0119     const struct malidp_irq_map de_irq_map;
0120     const struct malidp_irq_map se_irq_map;
0121     const struct malidp_irq_map dc_irq_map;
0122 
0123     /* list of supported pixel formats for each layer */
0124     const struct malidp_format_id *pixel_formats;
0125     const u8 n_pixel_formats;
0126 
0127     /* pitch alignment requirement in bytes */
0128     const u8 bus_align_bytes;
0129 };
0130 
0131 /* device features */
0132 /* Unlike DP550/650, DP500 has 3 stride registers in its video layer. */
0133 #define MALIDP_DEVICE_LV_HAS_3_STRIDES  BIT(0)
0134 
0135 struct malidp_hw_device;
0136 
0137 /*
0138  * Static structure containing hardware specific data and pointers to
0139  * functions that behave differently between various versions of the IP.
0140  */
0141 struct malidp_hw {
0142     const struct malidp_hw_regmap map;
0143 
0144     /*
0145      * Validate the driver instance against the hardware bits
0146      */
0147     int (*query_hw)(struct malidp_hw_device *hwdev);
0148 
0149     /*
0150      * Set the hardware into config mode, ready to accept mode changes
0151      */
0152     void (*enter_config_mode)(struct malidp_hw_device *hwdev);
0153 
0154     /*
0155      * Tell hardware to exit configuration mode
0156      */
0157     void (*leave_config_mode)(struct malidp_hw_device *hwdev);
0158 
0159     /*
0160      * Query if hardware is in configuration mode
0161      */
0162     bool (*in_config_mode)(struct malidp_hw_device *hwdev);
0163 
0164     /*
0165      * Set/clear configuration valid flag for hardware parameters that can
0166      * be changed outside the configuration mode to the given value.
0167      * Hardware will use the new settings when config valid is set,
0168      * after the end of the current buffer scanout, and will ignore
0169      * any new values for those parameters if config valid flag is cleared
0170      */
0171     void (*set_config_valid)(struct malidp_hw_device *hwdev, u8 value);
0172 
0173     /*
0174      * Set a new mode in hardware. Requires the hardware to be in
0175      * configuration mode before this function is called.
0176      */
0177     void (*modeset)(struct malidp_hw_device *hwdev, struct videomode *m);
0178 
0179     /*
0180      * Calculate the required rotation memory given the active area
0181      * and the buffer format.
0182      */
0183     int (*rotmem_required)(struct malidp_hw_device *hwdev, u16 w, u16 h,
0184                    u32 fmt, bool has_modifier);
0185 
0186     int (*se_set_scaling_coeffs)(struct malidp_hw_device *hwdev,
0187                      struct malidp_se_config *se_config,
0188                      struct malidp_se_config *old_config);
0189 
0190     long (*se_calc_mclk)(struct malidp_hw_device *hwdev,
0191                  struct malidp_se_config *se_config,
0192                  struct videomode *vm);
0193     /*
0194      * Enable writing to memory the content of the next frame
0195      * @param hwdev - malidp_hw_device structure containing the HW description
0196      * @param addrs - array of addresses for each plane
0197      * @param pitches - array of pitches for each plane
0198      * @param num_planes - number of planes to be written
0199      * @param w - width of the output frame
0200      * @param h - height of the output frame
0201      * @param fmt_id - internal format ID of output buffer
0202      */
0203     int (*enable_memwrite)(struct malidp_hw_device *hwdev, dma_addr_t *addrs,
0204                    s32 *pitches, int num_planes, u16 w, u16 h, u32 fmt_id,
0205                    const s16 *rgb2yuv_coeffs);
0206 
0207     /*
0208      * Disable the writing to memory of the next frame's content.
0209      */
0210     void (*disable_memwrite)(struct malidp_hw_device *hwdev);
0211 
0212     u8 features;
0213 };
0214 
0215 /* Supported variants of the hardware */
0216 enum {
0217     MALIDP_500 = 0,
0218     MALIDP_550,
0219     MALIDP_650,
0220     /* keep the next entry last */
0221     MALIDP_MAX_DEVICES
0222 };
0223 
0224 extern const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES];
0225 
0226 /*
0227  * Structure used by the driver during runtime operation.
0228  */
0229 struct malidp_hw_device {
0230     struct malidp_hw *hw;
0231     void __iomem *regs;
0232 
0233     /* APB clock */
0234     struct clk *pclk;
0235     /* AXI clock */
0236     struct clk *aclk;
0237     /* main clock for display core */
0238     struct clk *mclk;
0239     /* pixel clock for display core */
0240     struct clk *pxlclk;
0241 
0242     u8 min_line_size;
0243     u16 max_line_size;
0244     u32 output_color_depth;
0245 
0246     /* track the device PM state */
0247     bool pm_suspended;
0248 
0249     /* track the SE memory writeback state */
0250     u8 mw_state;
0251 
0252     /* size of memory used for rotating layers, up to two banks available */
0253     u32 rotation_memory[2];
0254 
0255     /* priority level of RQOS register used for driven the ARQOS signal */
0256     u32 arqos_value;
0257 };
0258 
0259 static inline u32 malidp_hw_read(struct malidp_hw_device *hwdev, u32 reg)
0260 {
0261     WARN_ON(hwdev->pm_suspended);
0262     return readl(hwdev->regs + reg);
0263 }
0264 
0265 static inline void malidp_hw_write(struct malidp_hw_device *hwdev,
0266                    u32 value, u32 reg)
0267 {
0268     WARN_ON(hwdev->pm_suspended);
0269     writel(value, hwdev->regs + reg);
0270 }
0271 
0272 static inline void malidp_hw_setbits(struct malidp_hw_device *hwdev,
0273                      u32 mask, u32 reg)
0274 {
0275     u32 data = malidp_hw_read(hwdev, reg);
0276 
0277     data |= mask;
0278     malidp_hw_write(hwdev, data, reg);
0279 }
0280 
0281 static inline void malidp_hw_clearbits(struct malidp_hw_device *hwdev,
0282                        u32 mask, u32 reg)
0283 {
0284     u32 data = malidp_hw_read(hwdev, reg);
0285 
0286     data &= ~mask;
0287     malidp_hw_write(hwdev, data, reg);
0288 }
0289 
0290 static inline u32 malidp_get_block_base(struct malidp_hw_device *hwdev,
0291                     u8 block)
0292 {
0293     switch (block) {
0294     case MALIDP_SE_BLOCK:
0295         return hwdev->hw->map.se_base;
0296     case MALIDP_DC_BLOCK:
0297         return hwdev->hw->map.dc_base;
0298     }
0299 
0300     return 0;
0301 }
0302 
0303 static inline void malidp_hw_disable_irq(struct malidp_hw_device *hwdev,
0304                      u8 block, u32 irq)
0305 {
0306     u32 base = malidp_get_block_base(hwdev, block);
0307 
0308     malidp_hw_clearbits(hwdev, irq, base + MALIDP_REG_MASKIRQ);
0309 }
0310 
0311 static inline void malidp_hw_enable_irq(struct malidp_hw_device *hwdev,
0312                     u8 block, u32 irq)
0313 {
0314     u32 base = malidp_get_block_base(hwdev, block);
0315 
0316     malidp_hw_setbits(hwdev, irq, base + MALIDP_REG_MASKIRQ);
0317 }
0318 
0319 int malidp_de_irq_init(struct drm_device *drm, int irq);
0320 void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev);
0321 void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev);
0322 void malidp_de_irq_fini(struct malidp_hw_device *hwdev);
0323 int malidp_se_irq_init(struct drm_device *drm, int irq);
0324 void malidp_se_irq_fini(struct malidp_hw_device *hwdev);
0325 
0326 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
0327                u8 layer_id, u32 format, bool has_modifier);
0328 
0329 int malidp_format_get_bpp(u32 fmt);
0330 
0331 static inline u8 malidp_hw_get_pitch_align(struct malidp_hw_device *hwdev, bool rotated)
0332 {
0333     /*
0334      * only hardware that cannot do 8 bytes bus alignments have further
0335      * constraints on rotated planes
0336      */
0337     if (hwdev->hw->map.bus_align_bytes == 8)
0338         return 8;
0339     else
0340         return hwdev->hw->map.bus_align_bytes << (rotated ? 2 : 0);
0341 }
0342 
0343 /* U16.16 */
0344 #define FP_1_00000  0x00010000  /* 1.0 */
0345 #define FP_0_66667  0x0000AAAA  /* 0.6667 = 1/1.5 */
0346 #define FP_0_50000  0x00008000  /* 0.5 = 1/2 */
0347 #define FP_0_36363  0x00005D17  /* 0.36363 = 1/2.75 */
0348 #define FP_0_25000  0x00004000  /* 0.25 = 1/4 */
0349 
0350 static inline enum malidp_scaling_coeff_set
0351 malidp_se_select_coeffs(u32 upscale_factor)
0352 {
0353     return (upscale_factor >= FP_1_00000) ? MALIDP_UPSCALING_COEFFS :
0354            (upscale_factor >= FP_0_66667) ? MALIDP_DOWNSCALING_1_5_COEFFS :
0355            (upscale_factor >= FP_0_50000) ? MALIDP_DOWNSCALING_2_COEFFS :
0356            (upscale_factor >= FP_0_36363) ? MALIDP_DOWNSCALING_2_75_COEFFS :
0357            MALIDP_DOWNSCALING_4_COEFFS;
0358 }
0359 
0360 #undef FP_0_25000
0361 #undef FP_0_36363
0362 #undef FP_0_50000
0363 #undef FP_0_66667
0364 #undef FP_1_00000
0365 
0366 static inline void malidp_se_set_enh_coeffs(struct malidp_hw_device *hwdev)
0367 {
0368     static const s32 enhancer_coeffs[] = {
0369         -8, -8, -8, -8, 128, -8, -8, -8, -8
0370     };
0371     u32 val = MALIDP_SE_SET_ENH_LIMIT_LOW(MALIDP_SE_ENH_LOW_LEVEL) |
0372           MALIDP_SE_SET_ENH_LIMIT_HIGH(MALIDP_SE_ENH_HIGH_LEVEL);
0373     u32 image_enh = hwdev->hw->map.se_base +
0374             ((hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ) ?
0375              0x10 : 0xC) + MALIDP_SE_IMAGE_ENH;
0376     u32 enh_coeffs = image_enh + MALIDP_SE_ENH_COEFF0;
0377     int i;
0378 
0379     malidp_hw_write(hwdev, val, image_enh);
0380     for (i = 0; i < ARRAY_SIZE(enhancer_coeffs); ++i)
0381         malidp_hw_write(hwdev, enhancer_coeffs[i], enh_coeffs + i * 4);
0382 }
0383 
0384 /*
0385  * background color components are defined as 12bits values,
0386  * they will be shifted right when stored on hardware that
0387  * supports only 8bits per channel
0388  */
0389 #define MALIDP_BGND_COLOR_R     0x000
0390 #define MALIDP_BGND_COLOR_G     0x000
0391 #define MALIDP_BGND_COLOR_B     0x000
0392 
0393 #define MALIDP_COLORADJ_NUM_COEFFS  12
0394 #define MALIDP_COEFFTAB_NUM_COEFFS  64
0395 
0396 #define MALIDP_GAMMA_LUT_SIZE       4096
0397 
0398 #define AFBC_SIZE_MASK      AFBC_FORMAT_MOD_BLOCK_SIZE_MASK
0399 #define AFBC_SIZE_16X16     AFBC_FORMAT_MOD_BLOCK_SIZE_16x16
0400 #define AFBC_YTR        AFBC_FORMAT_MOD_YTR
0401 #define AFBC_SPARSE     AFBC_FORMAT_MOD_SPARSE
0402 #define AFBC_CBR        AFBC_FORMAT_MOD_CBR
0403 #define AFBC_SPLIT      AFBC_FORMAT_MOD_SPLIT
0404 #define AFBC_TILED      AFBC_FORMAT_MOD_TILED
0405 #define AFBC_SC         AFBC_FORMAT_MOD_SC
0406 
0407 #define AFBC_MOD_VALID_BITS (AFBC_SIZE_MASK | AFBC_YTR | AFBC_SPLIT | \
0408                  AFBC_SPARSE | AFBC_CBR | AFBC_TILED | AFBC_SC)
0409 
0410 extern const u64 malidp_format_modifiers[];
0411 
0412 #endif  /* __MALIDP_HW_H__ */