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 const struct malidp_hw_regmap map; 125 void __iomem *regs; 126 127 /* APB clock */ 128 struct clk *pclk; 129 /* AXI clock */ 130 struct clk *aclk; 131 /* main clock for display core */ 132 struct clk *mclk; 133 /* pixel clock for display core */ 134 struct clk *pxlclk; 135 136 /* 137 * Validate the driver instance against the hardware bits 138 */ 139 int (*query_hw)(struct malidp_hw_device *hwdev); 140 141 /* 142 * Set the hardware into config mode, ready to accept mode changes 143 */ 144 void (*enter_config_mode)(struct malidp_hw_device *hwdev); 145 146 /* 147 * Tell hardware to exit configuration mode 148 */ 149 void (*leave_config_mode)(struct malidp_hw_device *hwdev); 150 151 /* 152 * Query if hardware is in configuration mode 153 */ 154 bool (*in_config_mode)(struct malidp_hw_device *hwdev); 155 156 /* 157 * Set configuration valid flag for hardware parameters that can 158 * be changed outside the configuration mode. Hardware will use 159 * the new settings when config valid is set after the end of the 160 * current buffer scanout 161 */ 162 void (*set_config_valid)(struct malidp_hw_device *hwdev); 163 164 /* 165 * Set a new mode in hardware. Requires the hardware to be in 166 * configuration mode before this function is called. 167 */ 168 void (*modeset)(struct malidp_hw_device *hwdev, struct videomode *m); 169 170 /* 171 * Calculate the required rotation memory given the active area 172 * and the buffer format. 173 */ 174 int (*rotmem_required)(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt); 175 176 int (*se_set_scaling_coeffs)(struct malidp_hw_device *hwdev, 177 struct malidp_se_config *se_config, 178 struct malidp_se_config *old_config); 179 180 long (*se_calc_mclk)(struct malidp_hw_device *hwdev, 181 struct malidp_se_config *se_config, 182 struct videomode *vm); 183 184 u8 features; 185 186 u8 min_line_size; 187 u16 max_line_size; 188 189 /* track the device PM state */ 190 bool pm_suspended; 191 192 /* size of memory used for rotating layers, up to two banks available */ 193 u32 rotation_memory[2]; 194 }; 195 196 /* Supported variants of the hardware */ 197 enum { 198 MALIDP_500 = 0, 199 MALIDP_550, 200 MALIDP_650, 201 /* keep the next entry last */ 202 MALIDP_MAX_DEVICES 203 }; 204 205 extern const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES]; 206 207 static inline u32 malidp_hw_read(struct malidp_hw_device *hwdev, u32 reg) 208 { 209 WARN_ON(hwdev->pm_suspended); 210 return readl(hwdev->regs + reg); 211 } 212 213 static inline void malidp_hw_write(struct malidp_hw_device *hwdev, 214 u32 value, u32 reg) 215 { 216 WARN_ON(hwdev->pm_suspended); 217 writel(value, hwdev->regs + reg); 218 } 219 220 static inline void malidp_hw_setbits(struct malidp_hw_device *hwdev, 221 u32 mask, u32 reg) 222 { 223 u32 data = malidp_hw_read(hwdev, reg); 224 225 data |= mask; 226 malidp_hw_write(hwdev, data, reg); 227 } 228 229 static inline void malidp_hw_clearbits(struct malidp_hw_device *hwdev, 230 u32 mask, u32 reg) 231 { 232 u32 data = malidp_hw_read(hwdev, reg); 233 234 data &= ~mask; 235 malidp_hw_write(hwdev, data, reg); 236 } 237 238 static inline u32 malidp_get_block_base(struct malidp_hw_device *hwdev, 239 u8 block) 240 { 241 switch (block) { 242 case MALIDP_SE_BLOCK: 243 return hwdev->map.se_base; 244 case MALIDP_DC_BLOCK: 245 return hwdev->map.dc_base; 246 } 247 248 return 0; 249 } 250 251 static inline void malidp_hw_disable_irq(struct malidp_hw_device *hwdev, 252 u8 block, u32 irq) 253 { 254 u32 base = malidp_get_block_base(hwdev, block); 255 256 malidp_hw_clearbits(hwdev, irq, base + MALIDP_REG_MASKIRQ); 257 } 258 259 static inline void malidp_hw_enable_irq(struct malidp_hw_device *hwdev, 260 u8 block, u32 irq) 261 { 262 u32 base = malidp_get_block_base(hwdev, block); 263 264 malidp_hw_setbits(hwdev, irq, base + MALIDP_REG_MASKIRQ); 265 } 266 267 int malidp_de_irq_init(struct drm_device *drm, int irq); 268 void malidp_de_irq_fini(struct drm_device *drm); 269 int malidp_se_irq_init(struct drm_device *drm, int irq); 270 void malidp_se_irq_fini(struct drm_device *drm); 271 272 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map, 273 u8 layer_id, u32 format); 274 275 static inline bool malidp_hw_pitch_valid(struct malidp_hw_device *hwdev, 276 unsigned int pitch) 277 { 278 return !(pitch & (hwdev->map.bus_align_bytes - 1)); 279 } 280 281 /* U16.16 */ 282 #define FP_1_00000 0x00010000 /* 1.0 */ 283 #define FP_0_66667 0x0000AAAA /* 0.6667 = 1/1.5 */ 284 #define FP_0_50000 0x00008000 /* 0.5 = 1/2 */ 285 #define FP_0_36363 0x00005D17 /* 0.36363 = 1/2.75 */ 286 #define FP_0_25000 0x00004000 /* 0.25 = 1/4 */ 287 288 static inline enum malidp_scaling_coeff_set 289 malidp_se_select_coeffs(u32 upscale_factor) 290 { 291 return (upscale_factor >= FP_1_00000) ? MALIDP_UPSCALING_COEFFS : 292 (upscale_factor >= FP_0_66667) ? MALIDP_DOWNSCALING_1_5_COEFFS : 293 (upscale_factor >= FP_0_50000) ? MALIDP_DOWNSCALING_2_COEFFS : 294 (upscale_factor >= FP_0_36363) ? MALIDP_DOWNSCALING_2_75_COEFFS : 295 MALIDP_DOWNSCALING_4_COEFFS; 296 } 297 298 #undef FP_0_25000 299 #undef FP_0_36363 300 #undef FP_0_50000 301 #undef FP_0_66667 302 #undef FP_1_00000 303 304 static inline void malidp_se_set_enh_coeffs(struct malidp_hw_device *hwdev) 305 { 306 static const s32 enhancer_coeffs[] = { 307 -8, -8, -8, -8, 128, -8, -8, -8, -8 308 }; 309 u32 val = MALIDP_SE_SET_ENH_LIMIT_LOW(MALIDP_SE_ENH_LOW_LEVEL) | 310 MALIDP_SE_SET_ENH_LIMIT_HIGH(MALIDP_SE_ENH_HIGH_LEVEL); 311 u32 image_enh = hwdev->map.se_base + 312 ((hwdev->map.features & MALIDP_REGMAP_HAS_CLEARIRQ) ? 313 0x10 : 0xC) + MALIDP_SE_IMAGE_ENH; 314 u32 enh_coeffs = image_enh + MALIDP_SE_ENH_COEFF0; 315 int i; 316 317 malidp_hw_write(hwdev, val, image_enh); 318 for (i = 0; i < ARRAY_SIZE(enhancer_coeffs); ++i) 319 malidp_hw_write(hwdev, enhancer_coeffs[i], enh_coeffs + i * 4); 320 } 321 322 /* 323 * background color components are defined as 12bits values, 324 * they will be shifted right when stored on hardware that 325 * supports only 8bits per channel 326 */ 327 #define MALIDP_BGND_COLOR_R 0x000 328 #define MALIDP_BGND_COLOR_G 0x000 329 #define MALIDP_BGND_COLOR_B 0x000 330 331 #define MALIDP_COLORADJ_NUM_COEFFS 12 332 #define MALIDP_COEFFTAB_NUM_COEFFS 64 333 334 #define MALIDP_GAMMA_LUT_SIZE 4096 335 336 #endif /* __MALIDP_HW_H__ */ 337