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 }; 63 64 enum malidp_scaling_coeff_set { 65 MALIDP_UPSCALING_COEFFS = 1, 66 MALIDP_DOWNSCALING_1_5_COEFFS = 2, 67 MALIDP_DOWNSCALING_2_COEFFS = 3, 68 MALIDP_DOWNSCALING_2_75_COEFFS = 4, 69 MALIDP_DOWNSCALING_4_COEFFS = 5, 70 }; 71 72 struct malidp_se_config { 73 u8 scale_enable : 1; 74 u8 enhancer_enable : 1; 75 u8 hcoeff : 3; 76 u8 vcoeff : 3; 77 u8 plane_src_id; 78 u16 input_w, input_h; 79 u16 output_w, output_h; 80 u32 h_init_phase, h_delta_phase; 81 u32 v_init_phase, v_delta_phase; 82 }; 83 84 /* regmap features */ 85 #define MALIDP_REGMAP_HAS_CLEARIRQ (1 << 0) 86 87 struct malidp_hw_regmap { 88 /* address offset of the DE register bank */ 89 /* is always 0x0000 */ 90 /* address offset of the DE coefficients registers */ 91 const u16 coeffs_base; 92 /* address offset of the SE registers bank */ 93 const u16 se_base; 94 /* address offset of the DC registers bank */ 95 const u16 dc_base; 96 97 /* address offset for the output depth register */ 98 const u16 out_depth_base; 99 100 /* bitmap with register map features */ 101 const u8 features; 102 103 /* list of supported layers */ 104 const u8 n_layers; 105 const struct malidp_layer *layers; 106 107 const struct malidp_irq_map de_irq_map; 108 const struct malidp_irq_map se_irq_map; 109 const struct malidp_irq_map dc_irq_map; 110 111 /* list of supported pixel formats for each layer */ 112 const struct malidp_format_id *pixel_formats; 113 const u8 n_pixel_formats; 114 115 /* pitch alignment requirement in bytes */ 116 const u8 bus_align_bytes; 117 }; 118 119 /* device features */ 120 /* Unlike DP550/650, DP500 has 3 stride registers in its video layer. */ 121 #define MALIDP_DEVICE_LV_HAS_3_STRIDES BIT(0) 122 123 struct malidp_hw_device; 124 125 /* 126 * Static structure containing hardware specific data and pointers to 127 * functions that behave differently between various versions of the IP. 128 */ 129 struct malidp_hw { 130 const struct malidp_hw_regmap map; 131 132 /* 133 * Validate the driver instance against the hardware bits 134 */ 135 int (*query_hw)(struct malidp_hw_device *hwdev); 136 137 /* 138 * Set the hardware into config mode, ready to accept mode changes 139 */ 140 void (*enter_config_mode)(struct malidp_hw_device *hwdev); 141 142 /* 143 * Tell hardware to exit configuration mode 144 */ 145 void (*leave_config_mode)(struct malidp_hw_device *hwdev); 146 147 /* 148 * Query if hardware is in configuration mode 149 */ 150 bool (*in_config_mode)(struct malidp_hw_device *hwdev); 151 152 /* 153 * Set configuration valid flag for hardware parameters that can 154 * be changed outside the configuration mode. Hardware will use 155 * the new settings when config valid is set after the end of the 156 * current buffer scanout 157 */ 158 void (*set_config_valid)(struct malidp_hw_device *hwdev); 159 160 /* 161 * Set a new mode in hardware. Requires the hardware to be in 162 * configuration mode before this function is called. 163 */ 164 void (*modeset)(struct malidp_hw_device *hwdev, struct videomode *m); 165 166 /* 167 * Calculate the required rotation memory given the active area 168 * and the buffer format. 169 */ 170 int (*rotmem_required)(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt); 171 172 int (*se_set_scaling_coeffs)(struct malidp_hw_device *hwdev, 173 struct malidp_se_config *se_config, 174 struct malidp_se_config *old_config); 175 176 long (*se_calc_mclk)(struct malidp_hw_device *hwdev, 177 struct malidp_se_config *se_config, 178 struct videomode *vm); 179 180 u8 features; 181 }; 182 183 /* Supported variants of the hardware */ 184 enum { 185 MALIDP_500 = 0, 186 MALIDP_550, 187 MALIDP_650, 188 /* keep the next entry last */ 189 MALIDP_MAX_DEVICES 190 }; 191 192 extern const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES]; 193 194 /* 195 * Structure used by the driver during runtime operation. 196 */ 197 struct malidp_hw_device { 198 struct malidp_hw *hw; 199 void __iomem *regs; 200 201 /* APB clock */ 202 struct clk *pclk; 203 /* AXI clock */ 204 struct clk *aclk; 205 /* main clock for display core */ 206 struct clk *mclk; 207 /* pixel clock for display core */ 208 struct clk *pxlclk; 209 210 u8 min_line_size; 211 u16 max_line_size; 212 213 /* track the device PM state */ 214 bool pm_suspended; 215 216 /* size of memory used for rotating layers, up to two banks available */ 217 u32 rotation_memory[2]; 218 }; 219 220 static inline u32 malidp_hw_read(struct malidp_hw_device *hwdev, u32 reg) 221 { 222 WARN_ON(hwdev->pm_suspended); 223 return readl(hwdev->regs + reg); 224 } 225 226 static inline void malidp_hw_write(struct malidp_hw_device *hwdev, 227 u32 value, u32 reg) 228 { 229 WARN_ON(hwdev->pm_suspended); 230 writel(value, hwdev->regs + reg); 231 } 232 233 static inline void malidp_hw_setbits(struct malidp_hw_device *hwdev, 234 u32 mask, u32 reg) 235 { 236 u32 data = malidp_hw_read(hwdev, reg); 237 238 data |= mask; 239 malidp_hw_write(hwdev, data, reg); 240 } 241 242 static inline void malidp_hw_clearbits(struct malidp_hw_device *hwdev, 243 u32 mask, u32 reg) 244 { 245 u32 data = malidp_hw_read(hwdev, reg); 246 247 data &= ~mask; 248 malidp_hw_write(hwdev, data, reg); 249 } 250 251 static inline u32 malidp_get_block_base(struct malidp_hw_device *hwdev, 252 u8 block) 253 { 254 switch (block) { 255 case MALIDP_SE_BLOCK: 256 return hwdev->hw->map.se_base; 257 case MALIDP_DC_BLOCK: 258 return hwdev->hw->map.dc_base; 259 } 260 261 return 0; 262 } 263 264 static inline void malidp_hw_disable_irq(struct malidp_hw_device *hwdev, 265 u8 block, u32 irq) 266 { 267 u32 base = malidp_get_block_base(hwdev, block); 268 269 malidp_hw_clearbits(hwdev, irq, base + MALIDP_REG_MASKIRQ); 270 } 271 272 static inline void malidp_hw_enable_irq(struct malidp_hw_device *hwdev, 273 u8 block, u32 irq) 274 { 275 u32 base = malidp_get_block_base(hwdev, block); 276 277 malidp_hw_setbits(hwdev, irq, base + MALIDP_REG_MASKIRQ); 278 } 279 280 int malidp_de_irq_init(struct drm_device *drm, int irq); 281 void malidp_de_irq_fini(struct drm_device *drm); 282 int malidp_se_irq_init(struct drm_device *drm, int irq); 283 void malidp_se_irq_fini(struct drm_device *drm); 284 285 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map, 286 u8 layer_id, u32 format); 287 288 static inline bool malidp_hw_pitch_valid(struct malidp_hw_device *hwdev, 289 unsigned int pitch) 290 { 291 return !(pitch & (hwdev->hw->map.bus_align_bytes - 1)); 292 } 293 294 /* U16.16 */ 295 #define FP_1_00000 0x00010000 /* 1.0 */ 296 #define FP_0_66667 0x0000AAAA /* 0.6667 = 1/1.5 */ 297 #define FP_0_50000 0x00008000 /* 0.5 = 1/2 */ 298 #define FP_0_36363 0x00005D17 /* 0.36363 = 1/2.75 */ 299 #define FP_0_25000 0x00004000 /* 0.25 = 1/4 */ 300 301 static inline enum malidp_scaling_coeff_set 302 malidp_se_select_coeffs(u32 upscale_factor) 303 { 304 return (upscale_factor >= FP_1_00000) ? MALIDP_UPSCALING_COEFFS : 305 (upscale_factor >= FP_0_66667) ? MALIDP_DOWNSCALING_1_5_COEFFS : 306 (upscale_factor >= FP_0_50000) ? MALIDP_DOWNSCALING_2_COEFFS : 307 (upscale_factor >= FP_0_36363) ? MALIDP_DOWNSCALING_2_75_COEFFS : 308 MALIDP_DOWNSCALING_4_COEFFS; 309 } 310 311 #undef FP_0_25000 312 #undef FP_0_36363 313 #undef FP_0_50000 314 #undef FP_0_66667 315 #undef FP_1_00000 316 317 static inline void malidp_se_set_enh_coeffs(struct malidp_hw_device *hwdev) 318 { 319 static const s32 enhancer_coeffs[] = { 320 -8, -8, -8, -8, 128, -8, -8, -8, -8 321 }; 322 u32 val = MALIDP_SE_SET_ENH_LIMIT_LOW(MALIDP_SE_ENH_LOW_LEVEL) | 323 MALIDP_SE_SET_ENH_LIMIT_HIGH(MALIDP_SE_ENH_HIGH_LEVEL); 324 u32 image_enh = hwdev->hw->map.se_base + 325 ((hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ) ? 326 0x10 : 0xC) + MALIDP_SE_IMAGE_ENH; 327 u32 enh_coeffs = image_enh + MALIDP_SE_ENH_COEFF0; 328 int i; 329 330 malidp_hw_write(hwdev, val, image_enh); 331 for (i = 0; i < ARRAY_SIZE(enhancer_coeffs); ++i) 332 malidp_hw_write(hwdev, enhancer_coeffs[i], enh_coeffs + i * 4); 333 } 334 335 /* 336 * background color components are defined as 12bits values, 337 * they will be shifted right when stored on hardware that 338 * supports only 8bits per channel 339 */ 340 #define MALIDP_BGND_COLOR_R 0x000 341 #define MALIDP_BGND_COLOR_G 0x000 342 #define MALIDP_BGND_COLOR_B 0x000 343 344 #define MALIDP_COLORADJ_NUM_COEFFS 12 345 #define MALIDP_COEFFTAB_NUM_COEFFS 64 346 347 #define MALIDP_GAMMA_LUT_SIZE 4096 348 349 #endif /* __MALIDP_HW_H__ */ 350