linux/drivers/gpu/drm/arm/malidp_hw.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 *
   4 * (C) COPYRIGHT 2013-2016 ARM Limited. All rights reserved.
   5 *
   6 * ARM Mali DP hardware manipulation routines.
   7 */
   8
   9#ifndef __MALIDP_HW_H__
  10#define __MALIDP_HW_H__
  11
  12#include <linux/bitops.h>
  13#include "malidp_regs.h"
  14
  15struct videomode;
  16struct clk;
  17
  18/* Mali DP IP blocks */
  19enum {
  20        MALIDP_DE_BLOCK = 0,
  21        MALIDP_SE_BLOCK,
  22        MALIDP_DC_BLOCK
  23};
  24
  25/* Mali DP layer IDs */
  26enum {
  27        DE_VIDEO1 = BIT(0),
  28        DE_GRAPHICS1 = BIT(1),
  29        DE_GRAPHICS2 = BIT(2), /* used only in DP500 */
  30        DE_VIDEO2 = BIT(3),
  31        DE_SMART = BIT(4),
  32        SE_MEMWRITE = BIT(5),
  33};
  34
  35enum rotation_features {
  36        ROTATE_NONE,            /* does not support rotation at all */
  37        ROTATE_ANY,             /* supports rotation on any buffers */
  38        ROTATE_COMPRESSED,      /* supports rotation only on compressed buffers */
  39};
  40
  41struct malidp_format_id {
  42        u32 format;             /* DRM fourcc */
  43        u8 layer;               /* bitmask of layers supporting it */
  44        u8 id;                  /* used internally */
  45};
  46
  47#define MALIDP_INVALID_FORMAT_ID        0xff
  48
  49/*
  50 * hide the differences between register maps
  51 * by using a common structure to hold the
  52 * base register offsets
  53 */
  54
  55struct malidp_irq_map {
  56        u32 irq_mask;           /* mask of IRQs that can be enabled in the block */
  57        u32 vsync_irq;          /* IRQ bit used for signaling during VSYNC */
  58        u32 err_mask;           /* mask of bits that represent errors */
  59};
  60
  61struct malidp_layer {
  62        u16 id;                 /* layer ID */
  63        u16 base;               /* address offset for the register bank */
  64        u16 ptr;                /* address offset for the pointer register */
  65        u16 stride_offset;      /* offset to the first stride register. */
  66        s16 yuv2rgb_offset;     /* offset to the YUV->RGB matrix entries */
  67        u16 mmu_ctrl_offset;    /* offset to the MMU control register */
  68        enum rotation_features rot;     /* type of rotation supported */
  69        /* address offset for the AFBC decoder registers */
  70        u16 afbc_decoder_offset;
  71};
  72
  73enum malidp_scaling_coeff_set {
  74        MALIDP_UPSCALING_COEFFS = 1,
  75        MALIDP_DOWNSCALING_1_5_COEFFS = 2,
  76        MALIDP_DOWNSCALING_2_COEFFS = 3,
  77        MALIDP_DOWNSCALING_2_75_COEFFS = 4,
  78        MALIDP_DOWNSCALING_4_COEFFS = 5,
  79};
  80
  81struct malidp_se_config {
  82        u8 scale_enable : 1;
  83        u8 enhancer_enable : 1;
  84        u8 hcoeff : 3;
  85        u8 vcoeff : 3;
  86        u8 plane_src_id;
  87        u16 input_w, input_h;
  88        u16 output_w, output_h;
  89        u32 h_init_phase, h_delta_phase;
  90        u32 v_init_phase, v_delta_phase;
  91};
  92
  93/* regmap features */
  94#define MALIDP_REGMAP_HAS_CLEARIRQ                              BIT(0)
  95#define MALIDP_DEVICE_AFBC_SUPPORT_SPLIT                        BIT(1)
  96#define MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT             BIT(2)
  97#define MALIDP_DEVICE_AFBC_YUYV_USE_422_P2                      BIT(3)
  98
  99struct malidp_hw_regmap {
 100        /* address offset of the DE register bank */
 101        /* is always 0x0000 */
 102        /* address offset of the DE coefficients registers */
 103        const u16 coeffs_base;
 104        /* address offset of the SE registers bank */
 105        const u16 se_base;
 106        /* address offset of the DC registers bank */
 107        const u16 dc_base;
 108
 109        /* address offset for the output depth register */
 110        const u16 out_depth_base;
 111
 112        /* bitmap with register map features */
 113        const u8 features;
 114
 115        /* list of supported layers */
 116        const u8 n_layers;
 117        const struct malidp_layer *layers;
 118
 119        const struct malidp_irq_map de_irq_map;
 120        const struct malidp_irq_map se_irq_map;
 121        const struct malidp_irq_map dc_irq_map;
 122
 123        /* list of supported pixel formats for each layer */
 124        const struct malidp_format_id *pixel_formats;
 125        const u8 n_pixel_formats;
 126
 127        /* pitch alignment requirement in bytes */
 128        const u8 bus_align_bytes;
 129};
 130
 131/* device features */
 132/* Unlike DP550/650, DP500 has 3 stride registers in its video layer. */
 133#define MALIDP_DEVICE_LV_HAS_3_STRIDES  BIT(0)
 134
 135struct malidp_hw_device;
 136
 137/*
 138 * Static structure containing hardware specific data and pointers to
 139 * functions that behave differently between various versions of the IP.
 140 */
 141struct malidp_hw {
 142        const struct malidp_hw_regmap map;
 143
 144        /*
 145         * Validate the driver instance against the hardware bits
 146         */
 147        int (*query_hw)(struct malidp_hw_device *hwdev);
 148
 149        /*
 150         * Set the hardware into config mode, ready to accept mode changes
 151         */
 152        void (*enter_config_mode)(struct malidp_hw_device *hwdev);
 153
 154        /*
 155         * Tell hardware to exit configuration mode
 156         */
 157        void (*leave_config_mode)(struct malidp_hw_device *hwdev);
 158
 159        /*
 160         * Query if hardware is in configuration mode
 161         */
 162        bool (*in_config_mode)(struct malidp_hw_device *hwdev);
 163
 164        /*
 165         * Set/clear configuration valid flag for hardware parameters that can
 166         * be changed outside the configuration mode to the given value.
 167         * Hardware will use the new settings when config valid is set,
 168         * after the end of the current buffer scanout, and will ignore
 169         * any new values for those parameters if config valid flag is cleared
 170         */
 171        void (*set_config_valid)(struct malidp_hw_device *hwdev, u8 value);
 172
 173        /*
 174         * Set a new mode in hardware. Requires the hardware to be in
 175         * configuration mode before this function is called.
 176         */
 177        void (*modeset)(struct malidp_hw_device *hwdev, struct videomode *m);
 178
 179        /*
 180         * Calculate the required rotation memory given the active area
 181         * and the buffer format.
 182         */
 183        int (*rotmem_required)(struct malidp_hw_device *hwdev, u16 w, u16 h,
 184                               u32 fmt, bool has_modifier);
 185
 186        int (*se_set_scaling_coeffs)(struct malidp_hw_device *hwdev,
 187                                     struct malidp_se_config *se_config,
 188                                     struct malidp_se_config *old_config);
 189
 190        long (*se_calc_mclk)(struct malidp_hw_device *hwdev,
 191                             struct malidp_se_config *se_config,
 192                             struct videomode *vm);
 193        /*
 194         * Enable writing to memory the content of the next frame
 195         * @param hwdev - malidp_hw_device structure containing the HW description
 196         * @param addrs - array of addresses for each plane
 197         * @param pitches - array of pitches for each plane
 198         * @param num_planes - number of planes to be written
 199         * @param w - width of the output frame
 200         * @param h - height of the output frame
 201         * @param fmt_id - internal format ID of output buffer
 202         */
 203        int (*enable_memwrite)(struct malidp_hw_device *hwdev, dma_addr_t *addrs,
 204                               s32 *pitches, int num_planes, u16 w, u16 h, u32 fmt_id,
 205                               const s16 *rgb2yuv_coeffs);
 206
 207        /*
 208         * Disable the writing to memory of the next frame's content.
 209         */
 210        void (*disable_memwrite)(struct malidp_hw_device *hwdev);
 211
 212        u8 features;
 213};
 214
 215/* Supported variants of the hardware */
 216enum {
 217        MALIDP_500 = 0,
 218        MALIDP_550,
 219        MALIDP_650,
 220        /* keep the next entry last */
 221        MALIDP_MAX_DEVICES
 222};
 223
 224extern const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES];
 225
 226/*
 227 * Structure used by the driver during runtime operation.
 228 */
 229struct malidp_hw_device {
 230        struct malidp_hw *hw;
 231        void __iomem *regs;
 232
 233        /* APB clock */
 234        struct clk *pclk;
 235        /* AXI clock */
 236        struct clk *aclk;
 237        /* main clock for display core */
 238        struct clk *mclk;
 239        /* pixel clock for display core */
 240        struct clk *pxlclk;
 241
 242        u8 min_line_size;
 243        u16 max_line_size;
 244        u32 output_color_depth;
 245
 246        /* track the device PM state */
 247        bool pm_suspended;
 248
 249        /* track the SE memory writeback state */
 250        u8 mw_state;
 251
 252        /* size of memory used for rotating layers, up to two banks available */
 253        u32 rotation_memory[2];
 254
 255        /* priority level of RQOS register used for driven the ARQOS signal */
 256        u32 arqos_value;
 257};
 258
 259static inline u32 malidp_hw_read(struct malidp_hw_device *hwdev, u32 reg)
 260{
 261        WARN_ON(hwdev->pm_suspended);
 262        return readl(hwdev->regs + reg);
 263}
 264
 265static inline void malidp_hw_write(struct malidp_hw_device *hwdev,
 266                                   u32 value, u32 reg)
 267{
 268        WARN_ON(hwdev->pm_suspended);
 269        writel(value, hwdev->regs + reg);
 270}
 271
 272static inline void malidp_hw_setbits(struct malidp_hw_device *hwdev,
 273                                     u32 mask, u32 reg)
 274{
 275        u32 data = malidp_hw_read(hwdev, reg);
 276
 277        data |= mask;
 278        malidp_hw_write(hwdev, data, reg);
 279}
 280
 281static inline void malidp_hw_clearbits(struct malidp_hw_device *hwdev,
 282                                       u32 mask, u32 reg)
 283{
 284        u32 data = malidp_hw_read(hwdev, reg);
 285
 286        data &= ~mask;
 287        malidp_hw_write(hwdev, data, reg);
 288}
 289
 290static inline u32 malidp_get_block_base(struct malidp_hw_device *hwdev,
 291                                        u8 block)
 292{
 293        switch (block) {
 294        case MALIDP_SE_BLOCK:
 295                return hwdev->hw->map.se_base;
 296        case MALIDP_DC_BLOCK:
 297                return hwdev->hw->map.dc_base;
 298        }
 299
 300        return 0;
 301}
 302
 303static inline void malidp_hw_disable_irq(struct malidp_hw_device *hwdev,
 304                                         u8 block, u32 irq)
 305{
 306        u32 base = malidp_get_block_base(hwdev, block);
 307
 308        malidp_hw_clearbits(hwdev, irq, base + MALIDP_REG_MASKIRQ);
 309}
 310
 311static inline void malidp_hw_enable_irq(struct malidp_hw_device *hwdev,
 312                                        u8 block, u32 irq)
 313{
 314        u32 base = malidp_get_block_base(hwdev, block);
 315
 316        malidp_hw_setbits(hwdev, irq, base + MALIDP_REG_MASKIRQ);
 317}
 318
 319int malidp_de_irq_init(struct drm_device *drm, int irq);
 320void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev);
 321void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev);
 322void malidp_de_irq_fini(struct malidp_hw_device *hwdev);
 323int malidp_se_irq_init(struct drm_device *drm, int irq);
 324void malidp_se_irq_fini(struct malidp_hw_device *hwdev);
 325
 326u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
 327                           u8 layer_id, u32 format, bool has_modifier);
 328
 329int malidp_format_get_bpp(u32 fmt);
 330
 331static inline u8 malidp_hw_get_pitch_align(struct malidp_hw_device *hwdev, bool rotated)
 332{
 333        /*
 334         * only hardware that cannot do 8 bytes bus alignments have further
 335         * constraints on rotated planes
 336         */
 337        if (hwdev->hw->map.bus_align_bytes == 8)
 338                return 8;
 339        else
 340                return hwdev->hw->map.bus_align_bytes << (rotated ? 2 : 0);
 341}
 342
 343/* U16.16 */
 344#define FP_1_00000      0x00010000      /* 1.0 */
 345#define FP_0_66667      0x0000AAAA      /* 0.6667 = 1/1.5 */
 346#define FP_0_50000      0x00008000      /* 0.5 = 1/2 */
 347#define FP_0_36363      0x00005D17      /* 0.36363 = 1/2.75 */
 348#define FP_0_25000      0x00004000      /* 0.25 = 1/4 */
 349
 350static inline enum malidp_scaling_coeff_set
 351malidp_se_select_coeffs(u32 upscale_factor)
 352{
 353        return (upscale_factor >= FP_1_00000) ? MALIDP_UPSCALING_COEFFS :
 354               (upscale_factor >= FP_0_66667) ? MALIDP_DOWNSCALING_1_5_COEFFS :
 355               (upscale_factor >= FP_0_50000) ? MALIDP_DOWNSCALING_2_COEFFS :
 356               (upscale_factor >= FP_0_36363) ? MALIDP_DOWNSCALING_2_75_COEFFS :
 357               MALIDP_DOWNSCALING_4_COEFFS;
 358}
 359
 360#undef FP_0_25000
 361#undef FP_0_36363
 362#undef FP_0_50000
 363#undef FP_0_66667
 364#undef FP_1_00000
 365
 366static inline void malidp_se_set_enh_coeffs(struct malidp_hw_device *hwdev)
 367{
 368        static const s32 enhancer_coeffs[] = {
 369                -8, -8, -8, -8, 128, -8, -8, -8, -8
 370        };
 371        u32 val = MALIDP_SE_SET_ENH_LIMIT_LOW(MALIDP_SE_ENH_LOW_LEVEL) |
 372                  MALIDP_SE_SET_ENH_LIMIT_HIGH(MALIDP_SE_ENH_HIGH_LEVEL);
 373        u32 image_enh = hwdev->hw->map.se_base +
 374                        ((hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ) ?
 375                         0x10 : 0xC) + MALIDP_SE_IMAGE_ENH;
 376        u32 enh_coeffs = image_enh + MALIDP_SE_ENH_COEFF0;
 377        int i;
 378
 379        malidp_hw_write(hwdev, val, image_enh);
 380        for (i = 0; i < ARRAY_SIZE(enhancer_coeffs); ++i)
 381                malidp_hw_write(hwdev, enhancer_coeffs[i], enh_coeffs + i * 4);
 382}
 383
 384/*
 385 * background color components are defined as 12bits values,
 386 * they will be shifted right when stored on hardware that
 387 * supports only 8bits per channel
 388 */
 389#define MALIDP_BGND_COLOR_R             0x000
 390#define MALIDP_BGND_COLOR_G             0x000
 391#define MALIDP_BGND_COLOR_B             0x000
 392
 393#define MALIDP_COLORADJ_NUM_COEFFS      12
 394#define MALIDP_COEFFTAB_NUM_COEFFS      64
 395
 396#define MALIDP_GAMMA_LUT_SIZE           4096
 397
 398#define AFBC_SIZE_MASK          AFBC_FORMAT_MOD_BLOCK_SIZE_MASK
 399#define AFBC_SIZE_16X16         AFBC_FORMAT_MOD_BLOCK_SIZE_16x16
 400#define AFBC_YTR                AFBC_FORMAT_MOD_YTR
 401#define AFBC_SPARSE             AFBC_FORMAT_MOD_SPARSE
 402#define AFBC_CBR                AFBC_FORMAT_MOD_CBR
 403#define AFBC_SPLIT              AFBC_FORMAT_MOD_SPLIT
 404#define AFBC_TILED              AFBC_FORMAT_MOD_TILED
 405#define AFBC_SC                 AFBC_FORMAT_MOD_SC
 406
 407#define AFBC_MOD_VALID_BITS     (AFBC_SIZE_MASK | AFBC_YTR | AFBC_SPLIT | \
 408                                 AFBC_SPARSE | AFBC_CBR | AFBC_TILED | AFBC_SC)
 409
 410extern const u64 malidp_format_modifiers[];
 411
 412#endif  /* __MALIDP_HW_H__ */
 413