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