1 /* 2 * Copyright (C) 2012 Samsung Electronics Co.Ltd 3 * Authors: 4 * Eunchul Kim <chulspro.kim@samsung.com> 5 * Jinyoung Jeon <jy0.jeon@samsung.com> 6 * Sangmin Lee <lsmin.lee@samsung.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 */ 14 #include <linux/kernel.h> 15 #include <linux/platform_device.h> 16 #include <linux/clk.h> 17 #include <linux/pm_runtime.h> 18 #include <linux/mfd/syscon.h> 19 #include <linux/regmap.h> 20 21 #include <drm/drmP.h> 22 #include <drm/exynos_drm.h> 23 #include "regs-gsc.h" 24 #include "exynos_drm_drv.h" 25 #include "exynos_drm_ipp.h" 26 #include "exynos_drm_gsc.h" 27 28 /* 29 * GSC stands for General SCaler and 30 * supports image scaler/rotator and input/output DMA operations. 31 * input DMA reads image data from the memory. 32 * output DMA writes image data to memory. 33 * GSC supports image rotation and image effect functions. 34 * 35 * M2M operation : supports crop/scale/rotation/csc so on. 36 * Memory ----> GSC H/W ----> Memory. 37 * Writeback operation : supports cloned screen with FIMD. 38 * FIMD ----> GSC H/W ----> Memory. 39 * Output operation : supports direct display using local path. 40 * Memory ----> GSC H/W ----> FIMD, Mixer. 41 */ 42 43 /* 44 * TODO 45 * 1. check suspend/resume api if needed. 46 * 2. need to check use case platform_device_id. 47 * 3. check src/dst size with, height. 48 * 4. added check_prepare api for right register. 49 * 5. need to add supported list in prop_list. 50 * 6. check prescaler/scaler optimization. 51 */ 52 53 #define GSC_MAX_DEVS 4 54 #define GSC_MAX_SRC 4 55 #define GSC_MAX_DST 16 56 #define GSC_RESET_TIMEOUT 50 57 #define GSC_BUF_STOP 1 58 #define GSC_BUF_START 2 59 #define GSC_REG_SZ 16 60 #define GSC_WIDTH_ITU_709 1280 61 #define GSC_SC_UP_MAX_RATIO 65536 62 #define GSC_SC_DOWN_RATIO_7_8 74898 63 #define GSC_SC_DOWN_RATIO_6_8 87381 64 #define GSC_SC_DOWN_RATIO_5_8 104857 65 #define GSC_SC_DOWN_RATIO_4_8 131072 66 #define GSC_SC_DOWN_RATIO_3_8 174762 67 #define GSC_SC_DOWN_RATIO_2_8 262144 68 #define GSC_REFRESH_MIN 12 69 #define GSC_REFRESH_MAX 60 70 #define GSC_CROP_MAX 8192 71 #define GSC_CROP_MIN 32 72 #define GSC_SCALE_MAX 4224 73 #define GSC_SCALE_MIN 32 74 #define GSC_COEF_RATIO 7 75 #define GSC_COEF_PHASE 9 76 #define GSC_COEF_ATTR 16 77 #define GSC_COEF_H_8T 8 78 #define GSC_COEF_V_4T 4 79 #define GSC_COEF_DEPTH 3 80 81 #define get_gsc_context(dev) platform_get_drvdata(to_platform_device(dev)) 82 #define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\ 83 struct gsc_context, ippdrv); 84 #define gsc_read(offset) readl(ctx->regs + (offset)) 85 #define gsc_write(cfg, offset) writel(cfg, ctx->regs + (offset)) 86 87 /* 88 * A structure of scaler. 89 * 90 * @range: narrow, wide. 91 * @pre_shfactor: pre sclaer shift factor. 92 * @pre_hratio: horizontal ratio of the prescaler. 93 * @pre_vratio: vertical ratio of the prescaler. 94 * @main_hratio: the main scaler's horizontal ratio. 95 * @main_vratio: the main scaler's vertical ratio. 96 */ 97 struct gsc_scaler { 98 bool range; 99 u32 pre_shfactor; 100 u32 pre_hratio; 101 u32 pre_vratio; 102 unsigned long main_hratio; 103 unsigned long main_vratio; 104 }; 105 106 /* 107 * A structure of scaler capability. 108 * 109 * find user manual 49.2 features. 110 * @tile_w: tile mode or rotation width. 111 * @tile_h: tile mode or rotation height. 112 * @w: other cases width. 113 * @h: other cases height. 114 */ 115 struct gsc_capability { 116 /* tile or rotation */ 117 u32 tile_w; 118 u32 tile_h; 119 /* other cases */ 120 u32 w; 121 u32 h; 122 }; 123 124 /* 125 * A structure of gsc context. 126 * 127 * @ippdrv: prepare initialization using ippdrv. 128 * @regs_res: register resources. 129 * @regs: memory mapped io registers. 130 * @sysreg: handle to SYSREG block regmap. 131 * @lock: locking of operations. 132 * @gsc_clk: gsc gate clock. 133 * @sc: scaler infomations. 134 * @id: gsc id. 135 * @irq: irq number. 136 * @rotation: supports rotation of src. 137 * @suspended: qos operations. 138 */ 139 struct gsc_context { 140 struct exynos_drm_ippdrv ippdrv; 141 struct resource *regs_res; 142 void __iomem *regs; 143 struct regmap *sysreg; 144 struct mutex lock; 145 struct clk *gsc_clk; 146 struct gsc_scaler sc; 147 int id; 148 int irq; 149 bool rotation; 150 bool suspended; 151 }; 152 153 /* 8-tap Filter Coefficient */ 154 static const int h_coef_8t[GSC_COEF_RATIO][GSC_COEF_ATTR][GSC_COEF_H_8T] = { 155 { /* Ratio <= 65536 (~8:8) */ 156 { 0, 0, 0, 128, 0, 0, 0, 0 }, 157 { -1, 2, -6, 127, 7, -2, 1, 0 }, 158 { -1, 4, -12, 125, 16, -5, 1, 0 }, 159 { -1, 5, -15, 120, 25, -8, 2, 0 }, 160 { -1, 6, -18, 114, 35, -10, 3, -1 }, 161 { -1, 6, -20, 107, 46, -13, 4, -1 }, 162 { -2, 7, -21, 99, 57, -16, 5, -1 }, 163 { -1, 6, -20, 89, 68, -18, 5, -1 }, 164 { -1, 6, -20, 79, 79, -20, 6, -1 }, 165 { -1, 5, -18, 68, 89, -20, 6, -1 }, 166 { -1, 5, -16, 57, 99, -21, 7, -2 }, 167 { -1, 4, -13, 46, 107, -20, 6, -1 }, 168 { -1, 3, -10, 35, 114, -18, 6, -1 }, 169 { 0, 2, -8, 25, 120, -15, 5, -1 }, 170 { 0, 1, -5, 16, 125, -12, 4, -1 }, 171 { 0, 1, -2, 7, 127, -6, 2, -1 } 172 }, { /* 65536 < Ratio <= 74898 (~8:7) */ 173 { 3, -8, 14, 111, 13, -8, 3, 0 }, 174 { 2, -6, 7, 112, 21, -10, 3, -1 }, 175 { 2, -4, 1, 110, 28, -12, 4, -1 }, 176 { 1, -2, -3, 106, 36, -13, 4, -1 }, 177 { 1, -1, -7, 103, 44, -15, 4, -1 }, 178 { 1, 1, -11, 97, 53, -16, 4, -1 }, 179 { 0, 2, -13, 91, 61, -16, 4, -1 }, 180 { 0, 3, -15, 85, 69, -17, 4, -1 }, 181 { 0, 3, -16, 77, 77, -16, 3, 0 }, 182 { -1, 4, -17, 69, 85, -15, 3, 0 }, 183 { -1, 4, -16, 61, 91, -13, 2, 0 }, 184 { -1, 4, -16, 53, 97, -11, 1, 1 }, 185 { -1, 4, -15, 44, 103, -7, -1, 1 }, 186 { -1, 4, -13, 36, 106, -3, -2, 1 }, 187 { -1, 4, -12, 28, 110, 1, -4, 2 }, 188 { -1, 3, -10, 21, 112, 7, -6, 2 } 189 }, { /* 74898 < Ratio <= 87381 (~8:6) */ 190 { 2, -11, 25, 96, 25, -11, 2, 0 }, 191 { 2, -10, 19, 96, 31, -12, 2, 0 }, 192 { 2, -9, 14, 94, 37, -12, 2, 0 }, 193 { 2, -8, 10, 92, 43, -12, 1, 0 }, 194 { 2, -7, 5, 90, 49, -12, 1, 0 }, 195 { 2, -5, 1, 86, 55, -12, 0, 1 }, 196 { 2, -4, -2, 82, 61, -11, -1, 1 }, 197 { 1, -3, -5, 77, 67, -9, -1, 1 }, 198 { 1, -2, -7, 72, 72, -7, -2, 1 }, 199 { 1, -1, -9, 67, 77, -5, -3, 1 }, 200 { 1, -1, -11, 61, 82, -2, -4, 2 }, 201 { 1, 0, -12, 55, 86, 1, -5, 2 }, 202 { 0, 1, -12, 49, 90, 5, -7, 2 }, 203 { 0, 1, -12, 43, 92, 10, -8, 2 }, 204 { 0, 2, -12, 37, 94, 14, -9, 2 }, 205 { 0, 2, -12, 31, 96, 19, -10, 2 } 206 }, { /* 87381 < Ratio <= 104857 (~8:5) */ 207 { -1, -8, 33, 80, 33, -8, -1, 0 }, 208 { -1, -8, 28, 80, 37, -7, -2, 1 }, 209 { 0, -8, 24, 79, 41, -7, -2, 1 }, 210 { 0, -8, 20, 78, 46, -6, -3, 1 }, 211 { 0, -8, 16, 76, 50, -4, -3, 1 }, 212 { 0, -7, 13, 74, 54, -3, -4, 1 }, 213 { 1, -7, 10, 71, 58, -1, -5, 1 }, 214 { 1, -6, 6, 68, 62, 1, -5, 1 }, 215 { 1, -6, 4, 65, 65, 4, -6, 1 }, 216 { 1, -5, 1, 62, 68, 6, -6, 1 }, 217 { 1, -5, -1, 58, 71, 10, -7, 1 }, 218 { 1, -4, -3, 54, 74, 13, -7, 0 }, 219 { 1, -3, -4, 50, 76, 16, -8, 0 }, 220 { 1, -3, -6, 46, 78, 20, -8, 0 }, 221 { 1, -2, -7, 41, 79, 24, -8, 0 }, 222 { 1, -2, -7, 37, 80, 28, -8, -1 } 223 }, { /* 104857 < Ratio <= 131072 (~8:4) */ 224 { -3, 0, 35, 64, 35, 0, -3, 0 }, 225 { -3, -1, 32, 64, 38, 1, -3, 0 }, 226 { -2, -2, 29, 63, 41, 2, -3, 0 }, 227 { -2, -3, 27, 63, 43, 4, -4, 0 }, 228 { -2, -3, 24, 61, 46, 6, -4, 0 }, 229 { -2, -3, 21, 60, 49, 7, -4, 0 }, 230 { -1, -4, 19, 59, 51, 9, -4, -1 }, 231 { -1, -4, 16, 57, 53, 12, -4, -1 }, 232 { -1, -4, 14, 55, 55, 14, -4, -1 }, 233 { -1, -4, 12, 53, 57, 16, -4, -1 }, 234 { -1, -4, 9, 51, 59, 19, -4, -1 }, 235 { 0, -4, 7, 49, 60, 21, -3, -2 }, 236 { 0, -4, 6, 46, 61, 24, -3, -2 }, 237 { 0, -4, 4, 43, 63, 27, -3, -2 }, 238 { 0, -3, 2, 41, 63, 29, -2, -2 }, 239 { 0, -3, 1, 38, 64, 32, -1, -3 } 240 }, { /* 131072 < Ratio <= 174762 (~8:3) */ 241 { -1, 8, 33, 48, 33, 8, -1, 0 }, 242 { -1, 7, 31, 49, 35, 9, -1, -1 }, 243 { -1, 6, 30, 49, 36, 10, -1, -1 }, 244 { -1, 5, 28, 48, 38, 12, -1, -1 }, 245 { -1, 4, 26, 48, 39, 13, 0, -1 }, 246 { -1, 3, 24, 47, 41, 15, 0, -1 }, 247 { -1, 2, 23, 47, 42, 16, 0, -1 }, 248 { -1, 2, 21, 45, 43, 18, 1, -1 }, 249 { -1, 1, 19, 45, 45, 19, 1, -1 }, 250 { -1, 1, 18, 43, 45, 21, 2, -1 }, 251 { -1, 0, 16, 42, 47, 23, 2, -1 }, 252 { -1, 0, 15, 41, 47, 24, 3, -1 }, 253 { -1, 0, 13, 39, 48, 26, 4, -1 }, 254 { -1, -1, 12, 38, 48, 28, 5, -1 }, 255 { -1, -1, 10, 36, 49, 30, 6, -1 }, 256 { -1, -1, 9, 35, 49, 31, 7, -1 } 257 }, { /* 174762 < Ratio <= 262144 (~8:2) */ 258 { 2, 13, 30, 38, 30, 13, 2, 0 }, 259 { 2, 12, 29, 38, 30, 14, 3, 0 }, 260 { 2, 11, 28, 38, 31, 15, 3, 0 }, 261 { 2, 10, 26, 38, 32, 16, 4, 0 }, 262 { 1, 10, 26, 37, 33, 17, 4, 0 }, 263 { 1, 9, 24, 37, 34, 18, 5, 0 }, 264 { 1, 8, 24, 37, 34, 19, 5, 0 }, 265 { 1, 7, 22, 36, 35, 20, 6, 1 }, 266 { 1, 6, 21, 36, 36, 21, 6, 1 }, 267 { 1, 6, 20, 35, 36, 22, 7, 1 }, 268 { 0, 5, 19, 34, 37, 24, 8, 1 }, 269 { 0, 5, 18, 34, 37, 24, 9, 1 }, 270 { 0, 4, 17, 33, 37, 26, 10, 1 }, 271 { 0, 4, 16, 32, 38, 26, 10, 2 }, 272 { 0, 3, 15, 31, 38, 28, 11, 2 }, 273 { 0, 3, 14, 30, 38, 29, 12, 2 } 274 } 275 }; 276 277 /* 4-tap Filter Coefficient */ 278 static const int v_coef_4t[GSC_COEF_RATIO][GSC_COEF_ATTR][GSC_COEF_V_4T] = { 279 { /* Ratio <= 65536 (~8:8) */ 280 { 0, 128, 0, 0 }, 281 { -4, 127, 5, 0 }, 282 { -6, 124, 11, -1 }, 283 { -8, 118, 19, -1 }, 284 { -8, 111, 27, -2 }, 285 { -8, 102, 37, -3 }, 286 { -8, 92, 48, -4 }, 287 { -7, 81, 59, -5 }, 288 { -6, 70, 70, -6 }, 289 { -5, 59, 81, -7 }, 290 { -4, 48, 92, -8 }, 291 { -3, 37, 102, -8 }, 292 { -2, 27, 111, -8 }, 293 { -1, 19, 118, -8 }, 294 { -1, 11, 124, -6 }, 295 { 0, 5, 127, -4 } 296 }, { /* 65536 < Ratio <= 74898 (~8:7) */ 297 { 8, 112, 8, 0 }, 298 { 4, 111, 14, -1 }, 299 { 1, 109, 20, -2 }, 300 { -2, 105, 27, -2 }, 301 { -3, 100, 34, -3 }, 302 { -5, 93, 43, -3 }, 303 { -5, 86, 51, -4 }, 304 { -5, 77, 60, -4 }, 305 { -5, 69, 69, -5 }, 306 { -4, 60, 77, -5 }, 307 { -4, 51, 86, -5 }, 308 { -3, 43, 93, -5 }, 309 { -3, 34, 100, -3 }, 310 { -2, 27, 105, -2 }, 311 { -2, 20, 109, 1 }, 312 { -1, 14, 111, 4 } 313 }, { /* 74898 < Ratio <= 87381 (~8:6) */ 314 { 16, 96, 16, 0 }, 315 { 12, 97, 21, -2 }, 316 { 8, 96, 26, -2 }, 317 { 5, 93, 32, -2 }, 318 { 2, 89, 39, -2 }, 319 { 0, 84, 46, -2 }, 320 { -1, 79, 53, -3 }, 321 { -2, 73, 59, -2 }, 322 { -2, 66, 66, -2 }, 323 { -2, 59, 73, -2 }, 324 { -3, 53, 79, -1 }, 325 { -2, 46, 84, 0 }, 326 { -2, 39, 89, 2 }, 327 { -2, 32, 93, 5 }, 328 { -2, 26, 96, 8 }, 329 { -2, 21, 97, 12 } 330 }, { /* 87381 < Ratio <= 104857 (~8:5) */ 331 { 22, 84, 22, 0 }, 332 { 18, 85, 26, -1 }, 333 { 14, 84, 31, -1 }, 334 { 11, 82, 36, -1 }, 335 { 8, 79, 42, -1 }, 336 { 6, 76, 47, -1 }, 337 { 4, 72, 52, 0 }, 338 { 2, 68, 58, 0 }, 339 { 1, 63, 63, 1 }, 340 { 0, 58, 68, 2 }, 341 { 0, 52, 72, 4 }, 342 { -1, 47, 76, 6 }, 343 { -1, 42, 79, 8 }, 344 { -1, 36, 82, 11 }, 345 { -1, 31, 84, 14 }, 346 { -1, 26, 85, 18 } 347 }, { /* 104857 < Ratio <= 131072 (~8:4) */ 348 { 26, 76, 26, 0 }, 349 { 22, 76, 30, 0 }, 350 { 19, 75, 34, 0 }, 351 { 16, 73, 38, 1 }, 352 { 13, 71, 43, 1 }, 353 { 10, 69, 47, 2 }, 354 { 8, 66, 51, 3 }, 355 { 6, 63, 55, 4 }, 356 { 5, 59, 59, 5 }, 357 { 4, 55, 63, 6 }, 358 { 3, 51, 66, 8 }, 359 { 2, 47, 69, 10 }, 360 { 1, 43, 71, 13 }, 361 { 1, 38, 73, 16 }, 362 { 0, 34, 75, 19 }, 363 { 0, 30, 76, 22 } 364 }, { /* 131072 < Ratio <= 174762 (~8:3) */ 365 { 29, 70, 29, 0 }, 366 { 26, 68, 32, 2 }, 367 { 23, 67, 36, 2 }, 368 { 20, 66, 39, 3 }, 369 { 17, 65, 43, 3 }, 370 { 15, 63, 46, 4 }, 371 { 12, 61, 50, 5 }, 372 { 10, 58, 53, 7 }, 373 { 8, 56, 56, 8 }, 374 { 7, 53, 58, 10 }, 375 { 5, 50, 61, 12 }, 376 { 4, 46, 63, 15 }, 377 { 3, 43, 65, 17 }, 378 { 3, 39, 66, 20 }, 379 { 2, 36, 67, 23 }, 380 { 2, 32, 68, 26 } 381 }, { /* 174762 < Ratio <= 262144 (~8:2) */ 382 { 32, 64, 32, 0 }, 383 { 28, 63, 34, 3 }, 384 { 25, 62, 37, 4 }, 385 { 22, 62, 40, 4 }, 386 { 19, 61, 43, 5 }, 387 { 17, 59, 46, 6 }, 388 { 15, 58, 48, 7 }, 389 { 13, 55, 51, 9 }, 390 { 11, 53, 53, 11 }, 391 { 9, 51, 55, 13 }, 392 { 7, 48, 58, 15 }, 393 { 6, 46, 59, 17 }, 394 { 5, 43, 61, 19 }, 395 { 4, 40, 62, 22 }, 396 { 4, 37, 62, 25 }, 397 { 3, 34, 63, 28 } 398 } 399 }; 400 401 static int gsc_sw_reset(struct gsc_context *ctx) 402 { 403 u32 cfg; 404 int count = GSC_RESET_TIMEOUT; 405 406 /* s/w reset */ 407 cfg = (GSC_SW_RESET_SRESET); 408 gsc_write(cfg, GSC_SW_RESET); 409 410 /* wait s/w reset complete */ 411 while (count--) { 412 cfg = gsc_read(GSC_SW_RESET); 413 if (!cfg) 414 break; 415 usleep_range(1000, 2000); 416 } 417 418 if (cfg) { 419 DRM_ERROR("failed to reset gsc h/w.\n"); 420 return -EBUSY; 421 } 422 423 /* reset sequence */ 424 cfg = gsc_read(GSC_IN_BASE_ADDR_Y_MASK); 425 cfg |= (GSC_IN_BASE_ADDR_MASK | 426 GSC_IN_BASE_ADDR_PINGPONG(0)); 427 gsc_write(cfg, GSC_IN_BASE_ADDR_Y_MASK); 428 gsc_write(cfg, GSC_IN_BASE_ADDR_CB_MASK); 429 gsc_write(cfg, GSC_IN_BASE_ADDR_CR_MASK); 430 431 cfg = gsc_read(GSC_OUT_BASE_ADDR_Y_MASK); 432 cfg |= (GSC_OUT_BASE_ADDR_MASK | 433 GSC_OUT_BASE_ADDR_PINGPONG(0)); 434 gsc_write(cfg, GSC_OUT_BASE_ADDR_Y_MASK); 435 gsc_write(cfg, GSC_OUT_BASE_ADDR_CB_MASK); 436 gsc_write(cfg, GSC_OUT_BASE_ADDR_CR_MASK); 437 438 return 0; 439 } 440 441 static void gsc_set_gscblk_fimd_wb(struct gsc_context *ctx, bool enable) 442 { 443 unsigned int gscblk_cfg; 444 445 if (!ctx->sysreg) 446 return; 447 448 regmap_read(ctx->sysreg, SYSREG_GSCBLK_CFG1, &gscblk_cfg); 449 450 if (enable) 451 gscblk_cfg |= GSC_BLK_DISP1WB_DEST(ctx->id) | 452 GSC_BLK_GSCL_WB_IN_SRC_SEL(ctx->id) | 453 GSC_BLK_SW_RESET_WB_DEST(ctx->id); 454 else 455 gscblk_cfg |= GSC_BLK_PXLASYNC_LO_MASK_WB(ctx->id); 456 457 regmap_write(ctx->sysreg, SYSREG_GSCBLK_CFG1, gscblk_cfg); 458 } 459 460 static void gsc_handle_irq(struct gsc_context *ctx, bool enable, 461 bool overflow, bool done) 462 { 463 u32 cfg; 464 465 DRM_DEBUG_KMS("enable[%d]overflow[%d]level[%d]\n", 466 enable, overflow, done); 467 468 cfg = gsc_read(GSC_IRQ); 469 cfg |= (GSC_IRQ_OR_MASK | GSC_IRQ_FRMDONE_MASK); 470 471 if (enable) 472 cfg |= GSC_IRQ_ENABLE; 473 else 474 cfg &= ~GSC_IRQ_ENABLE; 475 476 if (overflow) 477 cfg &= ~GSC_IRQ_OR_MASK; 478 else 479 cfg |= GSC_IRQ_OR_MASK; 480 481 if (done) 482 cfg &= ~GSC_IRQ_FRMDONE_MASK; 483 else 484 cfg |= GSC_IRQ_FRMDONE_MASK; 485 486 gsc_write(cfg, GSC_IRQ); 487 } 488 489 490 static int gsc_src_set_fmt(struct device *dev, u32 fmt) 491 { 492 struct gsc_context *ctx = get_gsc_context(dev); 493 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; 494 u32 cfg; 495 496 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt); 497 498 cfg = gsc_read(GSC_IN_CON); 499 cfg &= ~(GSC_IN_RGB_TYPE_MASK | GSC_IN_YUV422_1P_ORDER_MASK | 500 GSC_IN_CHROMA_ORDER_MASK | GSC_IN_FORMAT_MASK | 501 GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE | 502 GSC_IN_CHROM_STRIDE_SEL_MASK | GSC_IN_RB_SWAP_MASK); 503 504 switch (fmt) { 505 case DRM_FORMAT_RGB565: 506 cfg |= GSC_IN_RGB565; 507 break; 508 case DRM_FORMAT_XRGB8888: 509 cfg |= GSC_IN_XRGB8888; 510 break; 511 case DRM_FORMAT_BGRX8888: 512 cfg |= (GSC_IN_XRGB8888 | GSC_IN_RB_SWAP); 513 break; 514 case DRM_FORMAT_YUYV: 515 cfg |= (GSC_IN_YUV422_1P | 516 GSC_IN_YUV422_1P_ORDER_LSB_Y | 517 GSC_IN_CHROMA_ORDER_CBCR); 518 break; 519 case DRM_FORMAT_YVYU: 520 cfg |= (GSC_IN_YUV422_1P | 521 GSC_IN_YUV422_1P_ORDER_LSB_Y | 522 GSC_IN_CHROMA_ORDER_CRCB); 523 break; 524 case DRM_FORMAT_UYVY: 525 cfg |= (GSC_IN_YUV422_1P | 526 GSC_IN_YUV422_1P_OEDER_LSB_C | 527 GSC_IN_CHROMA_ORDER_CBCR); 528 break; 529 case DRM_FORMAT_VYUY: 530 cfg |= (GSC_IN_YUV422_1P | 531 GSC_IN_YUV422_1P_OEDER_LSB_C | 532 GSC_IN_CHROMA_ORDER_CRCB); 533 break; 534 case DRM_FORMAT_NV21: 535 case DRM_FORMAT_NV61: 536 cfg |= (GSC_IN_CHROMA_ORDER_CRCB | 537 GSC_IN_YUV420_2P); 538 break; 539 case DRM_FORMAT_YUV422: 540 cfg |= GSC_IN_YUV422_3P; 541 break; 542 case DRM_FORMAT_YUV420: 543 case DRM_FORMAT_YVU420: 544 cfg |= GSC_IN_YUV420_3P; 545 break; 546 case DRM_FORMAT_NV12: 547 case DRM_FORMAT_NV16: 548 cfg |= (GSC_IN_CHROMA_ORDER_CBCR | 549 GSC_IN_YUV420_2P); 550 break; 551 default: 552 dev_err(ippdrv->dev, "invalid target yuv order 0x%x.\n", fmt); 553 return -EINVAL; 554 } 555 556 gsc_write(cfg, GSC_IN_CON); 557 558 return 0; 559 } 560 561 static int gsc_src_set_transf(struct device *dev, 562 enum drm_exynos_degree degree, 563 enum drm_exynos_flip flip, bool *swap) 564 { 565 struct gsc_context *ctx = get_gsc_context(dev); 566 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; 567 u32 cfg; 568 569 DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree, flip); 570 571 cfg = gsc_read(GSC_IN_CON); 572 cfg &= ~GSC_IN_ROT_MASK; 573 574 switch (degree) { 575 case EXYNOS_DRM_DEGREE_0: 576 if (flip & EXYNOS_DRM_FLIP_VERTICAL) 577 cfg |= GSC_IN_ROT_XFLIP; 578 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) 579 cfg |= GSC_IN_ROT_YFLIP; 580 break; 581 case EXYNOS_DRM_DEGREE_90: 582 if (flip & EXYNOS_DRM_FLIP_VERTICAL) 583 cfg |= GSC_IN_ROT_90_XFLIP; 584 else if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) 585 cfg |= GSC_IN_ROT_90_YFLIP; 586 else 587 cfg |= GSC_IN_ROT_90; 588 break; 589 case EXYNOS_DRM_DEGREE_180: 590 cfg |= GSC_IN_ROT_180; 591 if (flip & EXYNOS_DRM_FLIP_VERTICAL) 592 cfg &= ~GSC_IN_ROT_XFLIP; 593 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) 594 cfg &= ~GSC_IN_ROT_YFLIP; 595 break; 596 case EXYNOS_DRM_DEGREE_270: 597 cfg |= GSC_IN_ROT_270; 598 if (flip & EXYNOS_DRM_FLIP_VERTICAL) 599 cfg &= ~GSC_IN_ROT_XFLIP; 600 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) 601 cfg &= ~GSC_IN_ROT_YFLIP; 602 break; 603 default: 604 dev_err(ippdrv->dev, "invalid degree value %d.\n", degree); 605 return -EINVAL; 606 } 607 608 gsc_write(cfg, GSC_IN_CON); 609 610 ctx->rotation = (cfg & GSC_IN_ROT_90) ? 1 : 0; 611 *swap = ctx->rotation; 612 613 return 0; 614 } 615 616 static int gsc_src_set_size(struct device *dev, int swap, 617 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz) 618 { 619 struct gsc_context *ctx = get_gsc_context(dev); 620 struct drm_exynos_pos img_pos = *pos; 621 struct gsc_scaler *sc = &ctx->sc; 622 u32 cfg; 623 624 DRM_DEBUG_KMS("swap[%d]x[%d]y[%d]w[%d]h[%d]\n", 625 swap, pos->x, pos->y, pos->w, pos->h); 626 627 if (swap) { 628 img_pos.w = pos->h; 629 img_pos.h = pos->w; 630 } 631 632 /* pixel offset */ 633 cfg = (GSC_SRCIMG_OFFSET_X(img_pos.x) | 634 GSC_SRCIMG_OFFSET_Y(img_pos.y)); 635 gsc_write(cfg, GSC_SRCIMG_OFFSET); 636 637 /* cropped size */ 638 cfg = (GSC_CROPPED_WIDTH(img_pos.w) | 639 GSC_CROPPED_HEIGHT(img_pos.h)); 640 gsc_write(cfg, GSC_CROPPED_SIZE); 641 642 DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", sz->hsize, sz->vsize); 643 644 /* original size */ 645 cfg = gsc_read(GSC_SRCIMG_SIZE); 646 cfg &= ~(GSC_SRCIMG_HEIGHT_MASK | 647 GSC_SRCIMG_WIDTH_MASK); 648 649 cfg |= (GSC_SRCIMG_WIDTH(sz->hsize) | 650 GSC_SRCIMG_HEIGHT(sz->vsize)); 651 652 gsc_write(cfg, GSC_SRCIMG_SIZE); 653 654 cfg = gsc_read(GSC_IN_CON); 655 cfg &= ~GSC_IN_RGB_TYPE_MASK; 656 657 DRM_DEBUG_KMS("width[%d]range[%d]\n", pos->w, sc->range); 658 659 if (pos->w >= GSC_WIDTH_ITU_709) 660 if (sc->range) 661 cfg |= GSC_IN_RGB_HD_WIDE; 662 else 663 cfg |= GSC_IN_RGB_HD_NARROW; 664 else 665 if (sc->range) 666 cfg |= GSC_IN_RGB_SD_WIDE; 667 else 668 cfg |= GSC_IN_RGB_SD_NARROW; 669 670 gsc_write(cfg, GSC_IN_CON); 671 672 return 0; 673 } 674 675 static int gsc_src_set_buf_seq(struct gsc_context *ctx, u32 buf_id, 676 enum drm_exynos_ipp_buf_type buf_type) 677 { 678 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; 679 bool masked; 680 u32 cfg; 681 u32 mask = 0x00000001 << buf_id; 682 683 DRM_DEBUG_KMS("buf_id[%d]buf_type[%d]\n", buf_id, buf_type); 684 685 /* mask register set */ 686 cfg = gsc_read(GSC_IN_BASE_ADDR_Y_MASK); 687 688 switch (buf_type) { 689 case IPP_BUF_ENQUEUE: 690 masked = false; 691 break; 692 case IPP_BUF_DEQUEUE: 693 masked = true; 694 break; 695 default: 696 dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n"); 697 return -EINVAL; 698 } 699 700 /* sequence id */ 701 cfg &= ~mask; 702 cfg |= masked << buf_id; 703 gsc_write(cfg, GSC_IN_BASE_ADDR_Y_MASK); 704 gsc_write(cfg, GSC_IN_BASE_ADDR_CB_MASK); 705 gsc_write(cfg, GSC_IN_BASE_ADDR_CR_MASK); 706 707 return 0; 708 } 709 710 static int gsc_src_set_addr(struct device *dev, 711 struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id, 712 enum drm_exynos_ipp_buf_type buf_type) 713 { 714 struct gsc_context *ctx = get_gsc_context(dev); 715 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; 716 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node; 717 struct drm_exynos_ipp_property *property; 718 719 if (!c_node) { 720 DRM_ERROR("failed to get c_node.\n"); 721 return -EFAULT; 722 } 723 724 property = &c_node->property; 725 726 DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n", 727 property->prop_id, buf_id, buf_type); 728 729 if (buf_id > GSC_MAX_SRC) { 730 dev_info(ippdrv->dev, "invalid buf_id %d.\n", buf_id); 731 return -EINVAL; 732 } 733 734 /* address register set */ 735 switch (buf_type) { 736 case IPP_BUF_ENQUEUE: 737 gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y], 738 GSC_IN_BASE_ADDR_Y(buf_id)); 739 gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB], 740 GSC_IN_BASE_ADDR_CB(buf_id)); 741 gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR], 742 GSC_IN_BASE_ADDR_CR(buf_id)); 743 break; 744 case IPP_BUF_DEQUEUE: 745 gsc_write(0x0, GSC_IN_BASE_ADDR_Y(buf_id)); 746 gsc_write(0x0, GSC_IN_BASE_ADDR_CB(buf_id)); 747 gsc_write(0x0, GSC_IN_BASE_ADDR_CR(buf_id)); 748 break; 749 default: 750 /* bypass */ 751 break; 752 } 753 754 return gsc_src_set_buf_seq(ctx, buf_id, buf_type); 755 } 756 757 static struct exynos_drm_ipp_ops gsc_src_ops = { 758 .set_fmt = gsc_src_set_fmt, 759 .set_transf = gsc_src_set_transf, 760 .set_size = gsc_src_set_size, 761 .set_addr = gsc_src_set_addr, 762 }; 763 764 static int gsc_dst_set_fmt(struct device *dev, u32 fmt) 765 { 766 struct gsc_context *ctx = get_gsc_context(dev); 767 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; 768 u32 cfg; 769 770 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt); 771 772 cfg = gsc_read(GSC_OUT_CON); 773 cfg &= ~(GSC_OUT_RGB_TYPE_MASK | GSC_OUT_YUV422_1P_ORDER_MASK | 774 GSC_OUT_CHROMA_ORDER_MASK | GSC_OUT_FORMAT_MASK | 775 GSC_OUT_CHROM_STRIDE_SEL_MASK | GSC_OUT_RB_SWAP_MASK | 776 GSC_OUT_GLOBAL_ALPHA_MASK); 777 778 switch (fmt) { 779 case DRM_FORMAT_RGB565: 780 cfg |= GSC_OUT_RGB565; 781 break; 782 case DRM_FORMAT_XRGB8888: 783 cfg |= GSC_OUT_XRGB8888; 784 break; 785 case DRM_FORMAT_BGRX8888: 786 cfg |= (GSC_OUT_XRGB8888 | GSC_OUT_RB_SWAP); 787 break; 788 case DRM_FORMAT_YUYV: 789 cfg |= (GSC_OUT_YUV422_1P | 790 GSC_OUT_YUV422_1P_ORDER_LSB_Y | 791 GSC_OUT_CHROMA_ORDER_CBCR); 792 break; 793 case DRM_FORMAT_YVYU: 794 cfg |= (GSC_OUT_YUV422_1P | 795 GSC_OUT_YUV422_1P_ORDER_LSB_Y | 796 GSC_OUT_CHROMA_ORDER_CRCB); 797 break; 798 case DRM_FORMAT_UYVY: 799 cfg |= (GSC_OUT_YUV422_1P | 800 GSC_OUT_YUV422_1P_OEDER_LSB_C | 801 GSC_OUT_CHROMA_ORDER_CBCR); 802 break; 803 case DRM_FORMAT_VYUY: 804 cfg |= (GSC_OUT_YUV422_1P | 805 GSC_OUT_YUV422_1P_OEDER_LSB_C | 806 GSC_OUT_CHROMA_ORDER_CRCB); 807 break; 808 case DRM_FORMAT_NV21: 809 case DRM_FORMAT_NV61: 810 cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV420_2P); 811 break; 812 case DRM_FORMAT_YUV422: 813 case DRM_FORMAT_YUV420: 814 case DRM_FORMAT_YVU420: 815 cfg |= GSC_OUT_YUV420_3P; 816 break; 817 case DRM_FORMAT_NV12: 818 case DRM_FORMAT_NV16: 819 cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | 820 GSC_OUT_YUV420_2P); 821 break; 822 default: 823 dev_err(ippdrv->dev, "invalid target yuv order 0x%x.\n", fmt); 824 return -EINVAL; 825 } 826 827 gsc_write(cfg, GSC_OUT_CON); 828 829 return 0; 830 } 831 832 static int gsc_dst_set_transf(struct device *dev, 833 enum drm_exynos_degree degree, 834 enum drm_exynos_flip flip, bool *swap) 835 { 836 struct gsc_context *ctx = get_gsc_context(dev); 837 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; 838 u32 cfg; 839 840 DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree, flip); 841 842 cfg = gsc_read(GSC_IN_CON); 843 cfg &= ~GSC_IN_ROT_MASK; 844 845 switch (degree) { 846 case EXYNOS_DRM_DEGREE_0: 847 if (flip & EXYNOS_DRM_FLIP_VERTICAL) 848 cfg |= GSC_IN_ROT_XFLIP; 849 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) 850 cfg |= GSC_IN_ROT_YFLIP; 851 break; 852 case EXYNOS_DRM_DEGREE_90: 853 if (flip & EXYNOS_DRM_FLIP_VERTICAL) 854 cfg |= GSC_IN_ROT_90_XFLIP; 855 else if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) 856 cfg |= GSC_IN_ROT_90_YFLIP; 857 else 858 cfg |= GSC_IN_ROT_90; 859 break; 860 case EXYNOS_DRM_DEGREE_180: 861 cfg |= GSC_IN_ROT_180; 862 if (flip & EXYNOS_DRM_FLIP_VERTICAL) 863 cfg &= ~GSC_IN_ROT_XFLIP; 864 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) 865 cfg &= ~GSC_IN_ROT_YFLIP; 866 break; 867 case EXYNOS_DRM_DEGREE_270: 868 cfg |= GSC_IN_ROT_270; 869 if (flip & EXYNOS_DRM_FLIP_VERTICAL) 870 cfg &= ~GSC_IN_ROT_XFLIP; 871 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) 872 cfg &= ~GSC_IN_ROT_YFLIP; 873 break; 874 default: 875 dev_err(ippdrv->dev, "invalid degree value %d.\n", degree); 876 return -EINVAL; 877 } 878 879 gsc_write(cfg, GSC_IN_CON); 880 881 ctx->rotation = (cfg & GSC_IN_ROT_90) ? 1 : 0; 882 *swap = ctx->rotation; 883 884 return 0; 885 } 886 887 static int gsc_get_ratio_shift(u32 src, u32 dst, u32 *ratio) 888 { 889 DRM_DEBUG_KMS("src[%d]dst[%d]\n", src, dst); 890 891 if (src >= dst * 8) { 892 DRM_ERROR("failed to make ratio and shift.\n"); 893 return -EINVAL; 894 } else if (src >= dst * 4) 895 *ratio = 4; 896 else if (src >= dst * 2) 897 *ratio = 2; 898 else 899 *ratio = 1; 900 901 return 0; 902 } 903 904 static void gsc_get_prescaler_shfactor(u32 hratio, u32 vratio, u32 *shfactor) 905 { 906 if (hratio == 4 && vratio == 4) 907 *shfactor = 4; 908 else if ((hratio == 4 && vratio == 2) || 909 (hratio == 2 && vratio == 4)) 910 *shfactor = 3; 911 else if ((hratio == 4 && vratio == 1) || 912 (hratio == 1 && vratio == 4) || 913 (hratio == 2 && vratio == 2)) 914 *shfactor = 2; 915 else if (hratio == 1 && vratio == 1) 916 *shfactor = 0; 917 else 918 *shfactor = 1; 919 } 920 921 static int gsc_set_prescaler(struct gsc_context *ctx, struct gsc_scaler *sc, 922 struct drm_exynos_pos *src, struct drm_exynos_pos *dst) 923 { 924 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; 925 u32 cfg; 926 u32 src_w, src_h, dst_w, dst_h; 927 int ret = 0; 928 929 src_w = src->w; 930 src_h = src->h; 931 932 if (ctx->rotation) { 933 dst_w = dst->h; 934 dst_h = dst->w; 935 } else { 936 dst_w = dst->w; 937 dst_h = dst->h; 938 } 939 940 ret = gsc_get_ratio_shift(src_w, dst_w, &sc->pre_hratio); 941 if (ret) { 942 dev_err(ippdrv->dev, "failed to get ratio horizontal.\n"); 943 return ret; 944 } 945 946 ret = gsc_get_ratio_shift(src_h, dst_h, &sc->pre_vratio); 947 if (ret) { 948 dev_err(ippdrv->dev, "failed to get ratio vertical.\n"); 949 return ret; 950 } 951 952 DRM_DEBUG_KMS("pre_hratio[%d]pre_vratio[%d]\n", 953 sc->pre_hratio, sc->pre_vratio); 954 955 sc->main_hratio = (src_w << 16) / dst_w; 956 sc->main_vratio = (src_h << 16) / dst_h; 957 958 DRM_DEBUG_KMS("main_hratio[%ld]main_vratio[%ld]\n", 959 sc->main_hratio, sc->main_vratio); 960 961 gsc_get_prescaler_shfactor(sc->pre_hratio, sc->pre_vratio, 962 &sc->pre_shfactor); 963 964 DRM_DEBUG_KMS("pre_shfactor[%d]\n", sc->pre_shfactor); 965 966 cfg = (GSC_PRESC_SHFACTOR(sc->pre_shfactor) | 967 GSC_PRESC_H_RATIO(sc->pre_hratio) | 968 GSC_PRESC_V_RATIO(sc->pre_vratio)); 969 gsc_write(cfg, GSC_PRE_SCALE_RATIO); 970 971 return ret; 972 } 973 974 static void gsc_set_h_coef(struct gsc_context *ctx, unsigned long main_hratio) 975 { 976 int i, j, k, sc_ratio; 977 978 if (main_hratio <= GSC_SC_UP_MAX_RATIO) 979 sc_ratio = 0; 980 else if (main_hratio <= GSC_SC_DOWN_RATIO_7_8) 981 sc_ratio = 1; 982 else if (main_hratio <= GSC_SC_DOWN_RATIO_6_8) 983 sc_ratio = 2; 984 else if (main_hratio <= GSC_SC_DOWN_RATIO_5_8) 985 sc_ratio = 3; 986 else if (main_hratio <= GSC_SC_DOWN_RATIO_4_8) 987 sc_ratio = 4; 988 else if (main_hratio <= GSC_SC_DOWN_RATIO_3_8) 989 sc_ratio = 5; 990 else 991 sc_ratio = 6; 992 993 for (i = 0; i < GSC_COEF_PHASE; i++) 994 for (j = 0; j < GSC_COEF_H_8T; j++) 995 for (k = 0; k < GSC_COEF_DEPTH; k++) 996 gsc_write(h_coef_8t[sc_ratio][i][j], 997 GSC_HCOEF(i, j, k)); 998 } 999 1000 static void gsc_set_v_coef(struct gsc_context *ctx, unsigned long main_vratio) 1001 { 1002 int i, j, k, sc_ratio; 1003 1004 if (main_vratio <= GSC_SC_UP_MAX_RATIO) 1005 sc_ratio = 0; 1006 else if (main_vratio <= GSC_SC_DOWN_RATIO_7_8) 1007 sc_ratio = 1; 1008 else if (main_vratio <= GSC_SC_DOWN_RATIO_6_8) 1009 sc_ratio = 2; 1010 else if (main_vratio <= GSC_SC_DOWN_RATIO_5_8) 1011 sc_ratio = 3; 1012 else if (main_vratio <= GSC_SC_DOWN_RATIO_4_8) 1013 sc_ratio = 4; 1014 else if (main_vratio <= GSC_SC_DOWN_RATIO_3_8) 1015 sc_ratio = 5; 1016 else 1017 sc_ratio = 6; 1018 1019 for (i = 0; i < GSC_COEF_PHASE; i++) 1020 for (j = 0; j < GSC_COEF_V_4T; j++) 1021 for (k = 0; k < GSC_COEF_DEPTH; k++) 1022 gsc_write(v_coef_4t[sc_ratio][i][j], 1023 GSC_VCOEF(i, j, k)); 1024 } 1025 1026 static void gsc_set_scaler(struct gsc_context *ctx, struct gsc_scaler *sc) 1027 { 1028 u32 cfg; 1029 1030 DRM_DEBUG_KMS("main_hratio[%ld]main_vratio[%ld]\n", 1031 sc->main_hratio, sc->main_vratio); 1032 1033 gsc_set_h_coef(ctx, sc->main_hratio); 1034 cfg = GSC_MAIN_H_RATIO_VALUE(sc->main_hratio); 1035 gsc_write(cfg, GSC_MAIN_H_RATIO); 1036 1037 gsc_set_v_coef(ctx, sc->main_vratio); 1038 cfg = GSC_MAIN_V_RATIO_VALUE(sc->main_vratio); 1039 gsc_write(cfg, GSC_MAIN_V_RATIO); 1040 } 1041 1042 static int gsc_dst_set_size(struct device *dev, int swap, 1043 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz) 1044 { 1045 struct gsc_context *ctx = get_gsc_context(dev); 1046 struct drm_exynos_pos img_pos = *pos; 1047 struct gsc_scaler *sc = &ctx->sc; 1048 u32 cfg; 1049 1050 DRM_DEBUG_KMS("swap[%d]x[%d]y[%d]w[%d]h[%d]\n", 1051 swap, pos->x, pos->y, pos->w, pos->h); 1052 1053 if (swap) { 1054 img_pos.w = pos->h; 1055 img_pos.h = pos->w; 1056 } 1057 1058 /* pixel offset */ 1059 cfg = (GSC_DSTIMG_OFFSET_X(pos->x) | 1060 GSC_DSTIMG_OFFSET_Y(pos->y)); 1061 gsc_write(cfg, GSC_DSTIMG_OFFSET); 1062 1063 /* scaled size */ 1064 cfg = (GSC_SCALED_WIDTH(img_pos.w) | GSC_SCALED_HEIGHT(img_pos.h)); 1065 gsc_write(cfg, GSC_SCALED_SIZE); 1066 1067 DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", sz->hsize, sz->vsize); 1068 1069 /* original size */ 1070 cfg = gsc_read(GSC_DSTIMG_SIZE); 1071 cfg &= ~(GSC_DSTIMG_HEIGHT_MASK | 1072 GSC_DSTIMG_WIDTH_MASK); 1073 cfg |= (GSC_DSTIMG_WIDTH(sz->hsize) | 1074 GSC_DSTIMG_HEIGHT(sz->vsize)); 1075 gsc_write(cfg, GSC_DSTIMG_SIZE); 1076 1077 cfg = gsc_read(GSC_OUT_CON); 1078 cfg &= ~GSC_OUT_RGB_TYPE_MASK; 1079 1080 DRM_DEBUG_KMS("width[%d]range[%d]\n", pos->w, sc->range); 1081 1082 if (pos->w >= GSC_WIDTH_ITU_709) 1083 if (sc->range) 1084 cfg |= GSC_OUT_RGB_HD_WIDE; 1085 else 1086 cfg |= GSC_OUT_RGB_HD_NARROW; 1087 else 1088 if (sc->range) 1089 cfg |= GSC_OUT_RGB_SD_WIDE; 1090 else 1091 cfg |= GSC_OUT_RGB_SD_NARROW; 1092 1093 gsc_write(cfg, GSC_OUT_CON); 1094 1095 return 0; 1096 } 1097 1098 static int gsc_dst_get_buf_seq(struct gsc_context *ctx) 1099 { 1100 u32 cfg, i, buf_num = GSC_REG_SZ; 1101 u32 mask = 0x00000001; 1102 1103 cfg = gsc_read(GSC_OUT_BASE_ADDR_Y_MASK); 1104 1105 for (i = 0; i < GSC_REG_SZ; i++) 1106 if (cfg & (mask << i)) 1107 buf_num--; 1108 1109 DRM_DEBUG_KMS("buf_num[%d]\n", buf_num); 1110 1111 return buf_num; 1112 } 1113 1114 static int gsc_dst_set_buf_seq(struct gsc_context *ctx, u32 buf_id, 1115 enum drm_exynos_ipp_buf_type buf_type) 1116 { 1117 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; 1118 bool masked; 1119 u32 cfg; 1120 u32 mask = 0x00000001 << buf_id; 1121 int ret = 0; 1122 1123 DRM_DEBUG_KMS("buf_id[%d]buf_type[%d]\n", buf_id, buf_type); 1124 1125 mutex_lock(&ctx->lock); 1126 1127 /* mask register set */ 1128 cfg = gsc_read(GSC_OUT_BASE_ADDR_Y_MASK); 1129 1130 switch (buf_type) { 1131 case IPP_BUF_ENQUEUE: 1132 masked = false; 1133 break; 1134 case IPP_BUF_DEQUEUE: 1135 masked = true; 1136 break; 1137 default: 1138 dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n"); 1139 ret = -EINVAL; 1140 goto err_unlock; 1141 } 1142 1143 /* sequence id */ 1144 cfg &= ~mask; 1145 cfg |= masked << buf_id; 1146 gsc_write(cfg, GSC_OUT_BASE_ADDR_Y_MASK); 1147 gsc_write(cfg, GSC_OUT_BASE_ADDR_CB_MASK); 1148 gsc_write(cfg, GSC_OUT_BASE_ADDR_CR_MASK); 1149 1150 /* interrupt enable */ 1151 if (buf_type == IPP_BUF_ENQUEUE && 1152 gsc_dst_get_buf_seq(ctx) >= GSC_BUF_START) 1153 gsc_handle_irq(ctx, true, false, true); 1154 1155 /* interrupt disable */ 1156 if (buf_type == IPP_BUF_DEQUEUE && 1157 gsc_dst_get_buf_seq(ctx) <= GSC_BUF_STOP) 1158 gsc_handle_irq(ctx, false, false, true); 1159 1160 err_unlock: 1161 mutex_unlock(&ctx->lock); 1162 return ret; 1163 } 1164 1165 static int gsc_dst_set_addr(struct device *dev, 1166 struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id, 1167 enum drm_exynos_ipp_buf_type buf_type) 1168 { 1169 struct gsc_context *ctx = get_gsc_context(dev); 1170 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; 1171 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node; 1172 struct drm_exynos_ipp_property *property; 1173 1174 if (!c_node) { 1175 DRM_ERROR("failed to get c_node.\n"); 1176 return -EFAULT; 1177 } 1178 1179 property = &c_node->property; 1180 1181 DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n", 1182 property->prop_id, buf_id, buf_type); 1183 1184 if (buf_id > GSC_MAX_DST) { 1185 dev_info(ippdrv->dev, "invalid buf_id %d.\n", buf_id); 1186 return -EINVAL; 1187 } 1188 1189 /* address register set */ 1190 switch (buf_type) { 1191 case IPP_BUF_ENQUEUE: 1192 gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y], 1193 GSC_OUT_BASE_ADDR_Y(buf_id)); 1194 gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB], 1195 GSC_OUT_BASE_ADDR_CB(buf_id)); 1196 gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR], 1197 GSC_OUT_BASE_ADDR_CR(buf_id)); 1198 break; 1199 case IPP_BUF_DEQUEUE: 1200 gsc_write(0x0, GSC_OUT_BASE_ADDR_Y(buf_id)); 1201 gsc_write(0x0, GSC_OUT_BASE_ADDR_CB(buf_id)); 1202 gsc_write(0x0, GSC_OUT_BASE_ADDR_CR(buf_id)); 1203 break; 1204 default: 1205 /* bypass */ 1206 break; 1207 } 1208 1209 return gsc_dst_set_buf_seq(ctx, buf_id, buf_type); 1210 } 1211 1212 static struct exynos_drm_ipp_ops gsc_dst_ops = { 1213 .set_fmt = gsc_dst_set_fmt, 1214 .set_transf = gsc_dst_set_transf, 1215 .set_size = gsc_dst_set_size, 1216 .set_addr = gsc_dst_set_addr, 1217 }; 1218 1219 static int gsc_clk_ctrl(struct gsc_context *ctx, bool enable) 1220 { 1221 DRM_DEBUG_KMS("enable[%d]\n", enable); 1222 1223 if (enable) { 1224 clk_prepare_enable(ctx->gsc_clk); 1225 ctx->suspended = false; 1226 } else { 1227 clk_disable_unprepare(ctx->gsc_clk); 1228 ctx->suspended = true; 1229 } 1230 1231 return 0; 1232 } 1233 1234 static int gsc_get_src_buf_index(struct gsc_context *ctx) 1235 { 1236 u32 cfg, curr_index, i; 1237 u32 buf_id = GSC_MAX_SRC; 1238 int ret; 1239 1240 DRM_DEBUG_KMS("gsc id[%d]\n", ctx->id); 1241 1242 cfg = gsc_read(GSC_IN_BASE_ADDR_Y_MASK); 1243 curr_index = GSC_IN_CURR_GET_INDEX(cfg); 1244 1245 for (i = curr_index; i < GSC_MAX_SRC; i++) { 1246 if (!((cfg >> i) & 0x1)) { 1247 buf_id = i; 1248 break; 1249 } 1250 } 1251 1252 if (buf_id == GSC_MAX_SRC) { 1253 DRM_ERROR("failed to get in buffer index.\n"); 1254 return -EINVAL; 1255 } 1256 1257 ret = gsc_src_set_buf_seq(ctx, buf_id, IPP_BUF_DEQUEUE); 1258 if (ret < 0) { 1259 DRM_ERROR("failed to dequeue.\n"); 1260 return ret; 1261 } 1262 1263 DRM_DEBUG_KMS("cfg[0x%x]curr_index[%d]buf_id[%d]\n", cfg, 1264 curr_index, buf_id); 1265 1266 return buf_id; 1267 } 1268 1269 static int gsc_get_dst_buf_index(struct gsc_context *ctx) 1270 { 1271 u32 cfg, curr_index, i; 1272 u32 buf_id = GSC_MAX_DST; 1273 int ret; 1274 1275 DRM_DEBUG_KMS("gsc id[%d]\n", ctx->id); 1276 1277 cfg = gsc_read(GSC_OUT_BASE_ADDR_Y_MASK); 1278 curr_index = GSC_OUT_CURR_GET_INDEX(cfg); 1279 1280 for (i = curr_index; i < GSC_MAX_DST; i++) { 1281 if (!((cfg >> i) & 0x1)) { 1282 buf_id = i; 1283 break; 1284 } 1285 } 1286 1287 if (buf_id == GSC_MAX_DST) { 1288 DRM_ERROR("failed to get out buffer index.\n"); 1289 return -EINVAL; 1290 } 1291 1292 ret = gsc_dst_set_buf_seq(ctx, buf_id, IPP_BUF_DEQUEUE); 1293 if (ret < 0) { 1294 DRM_ERROR("failed to dequeue.\n"); 1295 return ret; 1296 } 1297 1298 DRM_DEBUG_KMS("cfg[0x%x]curr_index[%d]buf_id[%d]\n", cfg, 1299 curr_index, buf_id); 1300 1301 return buf_id; 1302 } 1303 1304 static irqreturn_t gsc_irq_handler(int irq, void *dev_id) 1305 { 1306 struct gsc_context *ctx = dev_id; 1307 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; 1308 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node; 1309 struct drm_exynos_ipp_event_work *event_work = 1310 c_node->event_work; 1311 u32 status; 1312 int buf_id[EXYNOS_DRM_OPS_MAX]; 1313 1314 DRM_DEBUG_KMS("gsc id[%d]\n", ctx->id); 1315 1316 status = gsc_read(GSC_IRQ); 1317 if (status & GSC_IRQ_STATUS_OR_IRQ) { 1318 dev_err(ippdrv->dev, "occurred overflow at %d, status 0x%x.\n", 1319 ctx->id, status); 1320 return IRQ_NONE; 1321 } 1322 1323 if (status & GSC_IRQ_STATUS_OR_FRM_DONE) { 1324 dev_dbg(ippdrv->dev, "occurred frame done at %d, status 0x%x.\n", 1325 ctx->id, status); 1326 1327 buf_id[EXYNOS_DRM_OPS_SRC] = gsc_get_src_buf_index(ctx); 1328 if (buf_id[EXYNOS_DRM_OPS_SRC] < 0) 1329 return IRQ_HANDLED; 1330 1331 buf_id[EXYNOS_DRM_OPS_DST] = gsc_get_dst_buf_index(ctx); 1332 if (buf_id[EXYNOS_DRM_OPS_DST] < 0) 1333 return IRQ_HANDLED; 1334 1335 DRM_DEBUG_KMS("buf_id_src[%d]buf_id_dst[%d]\n", 1336 buf_id[EXYNOS_DRM_OPS_SRC], buf_id[EXYNOS_DRM_OPS_DST]); 1337 1338 event_work->ippdrv = ippdrv; 1339 event_work->buf_id[EXYNOS_DRM_OPS_SRC] = 1340 buf_id[EXYNOS_DRM_OPS_SRC]; 1341 event_work->buf_id[EXYNOS_DRM_OPS_DST] = 1342 buf_id[EXYNOS_DRM_OPS_DST]; 1343 queue_work(ippdrv->event_workq, &event_work->work); 1344 } 1345 1346 return IRQ_HANDLED; 1347 } 1348 1349 static int gsc_init_prop_list(struct exynos_drm_ippdrv *ippdrv) 1350 { 1351 struct drm_exynos_ipp_prop_list *prop_list = &ippdrv->prop_list; 1352 1353 prop_list->version = 1; 1354 prop_list->writeback = 1; 1355 prop_list->refresh_min = GSC_REFRESH_MIN; 1356 prop_list->refresh_max = GSC_REFRESH_MAX; 1357 prop_list->flip = (1 << EXYNOS_DRM_FLIP_VERTICAL) | 1358 (1 << EXYNOS_DRM_FLIP_HORIZONTAL); 1359 prop_list->degree = (1 << EXYNOS_DRM_DEGREE_0) | 1360 (1 << EXYNOS_DRM_DEGREE_90) | 1361 (1 << EXYNOS_DRM_DEGREE_180) | 1362 (1 << EXYNOS_DRM_DEGREE_270); 1363 prop_list->csc = 1; 1364 prop_list->crop = 1; 1365 prop_list->crop_max.hsize = GSC_CROP_MAX; 1366 prop_list->crop_max.vsize = GSC_CROP_MAX; 1367 prop_list->crop_min.hsize = GSC_CROP_MIN; 1368 prop_list->crop_min.vsize = GSC_CROP_MIN; 1369 prop_list->scale = 1; 1370 prop_list->scale_max.hsize = GSC_SCALE_MAX; 1371 prop_list->scale_max.vsize = GSC_SCALE_MAX; 1372 prop_list->scale_min.hsize = GSC_SCALE_MIN; 1373 prop_list->scale_min.vsize = GSC_SCALE_MIN; 1374 1375 return 0; 1376 } 1377 1378 static inline bool gsc_check_drm_flip(enum drm_exynos_flip flip) 1379 { 1380 switch (flip) { 1381 case EXYNOS_DRM_FLIP_NONE: 1382 case EXYNOS_DRM_FLIP_VERTICAL: 1383 case EXYNOS_DRM_FLIP_HORIZONTAL: 1384 case EXYNOS_DRM_FLIP_BOTH: 1385 return true; 1386 default: 1387 DRM_DEBUG_KMS("invalid flip\n"); 1388 return false; 1389 } 1390 } 1391 1392 static int gsc_ippdrv_check_property(struct device *dev, 1393 struct drm_exynos_ipp_property *property) 1394 { 1395 struct gsc_context *ctx = get_gsc_context(dev); 1396 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; 1397 struct drm_exynos_ipp_prop_list *pp = &ippdrv->prop_list; 1398 struct drm_exynos_ipp_config *config; 1399 struct drm_exynos_pos *pos; 1400 struct drm_exynos_sz *sz; 1401 bool swap; 1402 int i; 1403 1404 for_each_ipp_ops(i) { 1405 if ((i == EXYNOS_DRM_OPS_SRC) && 1406 (property->cmd == IPP_CMD_WB)) 1407 continue; 1408 1409 config = &property->config[i]; 1410 pos = &config->pos; 1411 sz = &config->sz; 1412 1413 /* check for flip */ 1414 if (!gsc_check_drm_flip(config->flip)) { 1415 DRM_ERROR("invalid flip.\n"); 1416 goto err_property; 1417 } 1418 1419 /* check for degree */ 1420 switch (config->degree) { 1421 case EXYNOS_DRM_DEGREE_90: 1422 case EXYNOS_DRM_DEGREE_270: 1423 swap = true; 1424 break; 1425 case EXYNOS_DRM_DEGREE_0: 1426 case EXYNOS_DRM_DEGREE_180: 1427 swap = false; 1428 break; 1429 default: 1430 DRM_ERROR("invalid degree.\n"); 1431 goto err_property; 1432 } 1433 1434 /* check for buffer bound */ 1435 if ((pos->x + pos->w > sz->hsize) || 1436 (pos->y + pos->h > sz->vsize)) { 1437 DRM_ERROR("out of buf bound.\n"); 1438 goto err_property; 1439 } 1440 1441 /* check for crop */ 1442 if ((i == EXYNOS_DRM_OPS_SRC) && (pp->crop)) { 1443 if (swap) { 1444 if ((pos->h < pp->crop_min.hsize) || 1445 (sz->vsize > pp->crop_max.hsize) || 1446 (pos->w < pp->crop_min.vsize) || 1447 (sz->hsize > pp->crop_max.vsize)) { 1448 DRM_ERROR("out of crop size.\n"); 1449 goto err_property; 1450 } 1451 } else { 1452 if ((pos->w < pp->crop_min.hsize) || 1453 (sz->hsize > pp->crop_max.hsize) || 1454 (pos->h < pp->crop_min.vsize) || 1455 (sz->vsize > pp->crop_max.vsize)) { 1456 DRM_ERROR("out of crop size.\n"); 1457 goto err_property; 1458 } 1459 } 1460 } 1461 1462 /* check for scale */ 1463 if ((i == EXYNOS_DRM_OPS_DST) && (pp->scale)) { 1464 if (swap) { 1465 if ((pos->h < pp->scale_min.hsize) || 1466 (sz->vsize > pp->scale_max.hsize) || 1467 (pos->w < pp->scale_min.vsize) || 1468 (sz->hsize > pp->scale_max.vsize)) { 1469 DRM_ERROR("out of scale size.\n"); 1470 goto err_property; 1471 } 1472 } else { 1473 if ((pos->w < pp->scale_min.hsize) || 1474 (sz->hsize > pp->scale_max.hsize) || 1475 (pos->h < pp->scale_min.vsize) || 1476 (sz->vsize > pp->scale_max.vsize)) { 1477 DRM_ERROR("out of scale size.\n"); 1478 goto err_property; 1479 } 1480 } 1481 } 1482 } 1483 1484 return 0; 1485 1486 err_property: 1487 for_each_ipp_ops(i) { 1488 if ((i == EXYNOS_DRM_OPS_SRC) && 1489 (property->cmd == IPP_CMD_WB)) 1490 continue; 1491 1492 config = &property->config[i]; 1493 pos = &config->pos; 1494 sz = &config->sz; 1495 1496 DRM_ERROR("[%s]f[%d]r[%d]pos[%d %d %d %d]sz[%d %d]\n", 1497 i ? "dst" : "src", config->flip, config->degree, 1498 pos->x, pos->y, pos->w, pos->h, 1499 sz->hsize, sz->vsize); 1500 } 1501 1502 return -EINVAL; 1503 } 1504 1505 1506 static int gsc_ippdrv_reset(struct device *dev) 1507 { 1508 struct gsc_context *ctx = get_gsc_context(dev); 1509 struct gsc_scaler *sc = &ctx->sc; 1510 int ret; 1511 1512 /* reset h/w block */ 1513 ret = gsc_sw_reset(ctx); 1514 if (ret < 0) { 1515 dev_err(dev, "failed to reset hardware.\n"); 1516 return ret; 1517 } 1518 1519 /* scaler setting */ 1520 memset(&ctx->sc, 0x0, sizeof(ctx->sc)); 1521 sc->range = true; 1522 1523 return 0; 1524 } 1525 1526 static int gsc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd) 1527 { 1528 struct gsc_context *ctx = get_gsc_context(dev); 1529 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; 1530 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node; 1531 struct drm_exynos_ipp_property *property; 1532 struct drm_exynos_ipp_config *config; 1533 struct drm_exynos_pos img_pos[EXYNOS_DRM_OPS_MAX]; 1534 struct drm_exynos_ipp_set_wb set_wb; 1535 u32 cfg; 1536 int ret, i; 1537 1538 DRM_DEBUG_KMS("cmd[%d]\n", cmd); 1539 1540 if (!c_node) { 1541 DRM_ERROR("failed to get c_node.\n"); 1542 return -EINVAL; 1543 } 1544 1545 property = &c_node->property; 1546 1547 gsc_handle_irq(ctx, true, false, true); 1548 1549 for_each_ipp_ops(i) { 1550 config = &property->config[i]; 1551 img_pos[i] = config->pos; 1552 } 1553 1554 switch (cmd) { 1555 case IPP_CMD_M2M: 1556 /* enable one shot */ 1557 cfg = gsc_read(GSC_ENABLE); 1558 cfg &= ~(GSC_ENABLE_ON_CLEAR_MASK | 1559 GSC_ENABLE_CLK_GATE_MODE_MASK); 1560 cfg |= GSC_ENABLE_ON_CLEAR_ONESHOT; 1561 gsc_write(cfg, GSC_ENABLE); 1562 1563 /* src dma memory */ 1564 cfg = gsc_read(GSC_IN_CON); 1565 cfg &= ~(GSC_IN_PATH_MASK | GSC_IN_LOCAL_SEL_MASK); 1566 cfg |= GSC_IN_PATH_MEMORY; 1567 gsc_write(cfg, GSC_IN_CON); 1568 1569 /* dst dma memory */ 1570 cfg = gsc_read(GSC_OUT_CON); 1571 cfg |= GSC_OUT_PATH_MEMORY; 1572 gsc_write(cfg, GSC_OUT_CON); 1573 break; 1574 case IPP_CMD_WB: 1575 set_wb.enable = 1; 1576 set_wb.refresh = property->refresh_rate; 1577 gsc_set_gscblk_fimd_wb(ctx, set_wb.enable); 1578 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb); 1579 1580 /* src local path */ 1581 cfg = gsc_read(GSC_IN_CON); 1582 cfg &= ~(GSC_IN_PATH_MASK | GSC_IN_LOCAL_SEL_MASK); 1583 cfg |= (GSC_IN_PATH_LOCAL | GSC_IN_LOCAL_FIMD_WB); 1584 gsc_write(cfg, GSC_IN_CON); 1585 1586 /* dst dma memory */ 1587 cfg = gsc_read(GSC_OUT_CON); 1588 cfg |= GSC_OUT_PATH_MEMORY; 1589 gsc_write(cfg, GSC_OUT_CON); 1590 break; 1591 case IPP_CMD_OUTPUT: 1592 /* src dma memory */ 1593 cfg = gsc_read(GSC_IN_CON); 1594 cfg &= ~(GSC_IN_PATH_MASK | GSC_IN_LOCAL_SEL_MASK); 1595 cfg |= GSC_IN_PATH_MEMORY; 1596 gsc_write(cfg, GSC_IN_CON); 1597 1598 /* dst local path */ 1599 cfg = gsc_read(GSC_OUT_CON); 1600 cfg |= GSC_OUT_PATH_MEMORY; 1601 gsc_write(cfg, GSC_OUT_CON); 1602 break; 1603 default: 1604 ret = -EINVAL; 1605 dev_err(dev, "invalid operations.\n"); 1606 return ret; 1607 } 1608 1609 ret = gsc_set_prescaler(ctx, &ctx->sc, 1610 &img_pos[EXYNOS_DRM_OPS_SRC], 1611 &img_pos[EXYNOS_DRM_OPS_DST]); 1612 if (ret) { 1613 dev_err(dev, "failed to set prescaler.\n"); 1614 return ret; 1615 } 1616 1617 gsc_set_scaler(ctx, &ctx->sc); 1618 1619 cfg = gsc_read(GSC_ENABLE); 1620 cfg |= GSC_ENABLE_ON; 1621 gsc_write(cfg, GSC_ENABLE); 1622 1623 return 0; 1624 } 1625 1626 static void gsc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd) 1627 { 1628 struct gsc_context *ctx = get_gsc_context(dev); 1629 struct drm_exynos_ipp_set_wb set_wb = {0, 0}; 1630 u32 cfg; 1631 1632 DRM_DEBUG_KMS("cmd[%d]\n", cmd); 1633 1634 switch (cmd) { 1635 case IPP_CMD_M2M: 1636 /* bypass */ 1637 break; 1638 case IPP_CMD_WB: 1639 gsc_set_gscblk_fimd_wb(ctx, set_wb.enable); 1640 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb); 1641 break; 1642 case IPP_CMD_OUTPUT: 1643 default: 1644 dev_err(dev, "invalid operations.\n"); 1645 break; 1646 } 1647 1648 gsc_handle_irq(ctx, false, false, true); 1649 1650 /* reset sequence */ 1651 gsc_write(0xff, GSC_OUT_BASE_ADDR_Y_MASK); 1652 gsc_write(0xff, GSC_OUT_BASE_ADDR_CB_MASK); 1653 gsc_write(0xff, GSC_OUT_BASE_ADDR_CR_MASK); 1654 1655 cfg = gsc_read(GSC_ENABLE); 1656 cfg &= ~GSC_ENABLE_ON; 1657 gsc_write(cfg, GSC_ENABLE); 1658 } 1659 1660 static int gsc_probe(struct platform_device *pdev) 1661 { 1662 struct device *dev = &pdev->dev; 1663 struct gsc_context *ctx; 1664 struct resource *res; 1665 struct exynos_drm_ippdrv *ippdrv; 1666 int ret; 1667 1668 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 1669 if (!ctx) 1670 return -ENOMEM; 1671 1672 if (dev->of_node) { 1673 ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node, 1674 "samsung,sysreg"); 1675 if (IS_ERR(ctx->sysreg)) { 1676 dev_warn(dev, "failed to get system register.\n"); 1677 ctx->sysreg = NULL; 1678 } 1679 } 1680 1681 /* clock control */ 1682 ctx->gsc_clk = devm_clk_get(dev, "gscl"); 1683 if (IS_ERR(ctx->gsc_clk)) { 1684 dev_err(dev, "failed to get gsc clock.\n"); 1685 return PTR_ERR(ctx->gsc_clk); 1686 } 1687 1688 /* resource memory */ 1689 ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1690 ctx->regs = devm_ioremap_resource(dev, ctx->regs_res); 1691 if (IS_ERR(ctx->regs)) 1692 return PTR_ERR(ctx->regs); 1693 1694 /* resource irq */ 1695 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 1696 if (!res) { 1697 dev_err(dev, "failed to request irq resource.\n"); 1698 return -ENOENT; 1699 } 1700 1701 ctx->irq = res->start; 1702 ret = devm_request_threaded_irq(dev, ctx->irq, NULL, gsc_irq_handler, 1703 IRQF_ONESHOT, "drm_gsc", ctx); 1704 if (ret < 0) { 1705 dev_err(dev, "failed to request irq.\n"); 1706 return ret; 1707 } 1708 1709 /* context initailization */ 1710 ctx->id = pdev->id; 1711 1712 ippdrv = &ctx->ippdrv; 1713 ippdrv->dev = dev; 1714 ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &gsc_src_ops; 1715 ippdrv->ops[EXYNOS_DRM_OPS_DST] = &gsc_dst_ops; 1716 ippdrv->check_property = gsc_ippdrv_check_property; 1717 ippdrv->reset = gsc_ippdrv_reset; 1718 ippdrv->start = gsc_ippdrv_start; 1719 ippdrv->stop = gsc_ippdrv_stop; 1720 ret = gsc_init_prop_list(ippdrv); 1721 if (ret < 0) { 1722 dev_err(dev, "failed to init property list.\n"); 1723 return ret; 1724 } 1725 1726 DRM_DEBUG_KMS("id[%d]ippdrv[%pK]\n", ctx->id, ippdrv); 1727 1728 mutex_init(&ctx->lock); 1729 platform_set_drvdata(pdev, ctx); 1730 1731 pm_runtime_enable(dev); 1732 1733 ret = exynos_drm_ippdrv_register(ippdrv); 1734 if (ret < 0) { 1735 dev_err(dev, "failed to register drm gsc device.\n"); 1736 goto err_ippdrv_register; 1737 } 1738 1739 dev_info(dev, "drm gsc registered successfully.\n"); 1740 1741 return 0; 1742 1743 err_ippdrv_register: 1744 pm_runtime_disable(dev); 1745 return ret; 1746 } 1747 1748 static int gsc_remove(struct platform_device *pdev) 1749 { 1750 struct device *dev = &pdev->dev; 1751 struct gsc_context *ctx = get_gsc_context(dev); 1752 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; 1753 1754 exynos_drm_ippdrv_unregister(ippdrv); 1755 mutex_destroy(&ctx->lock); 1756 1757 pm_runtime_set_suspended(dev); 1758 pm_runtime_disable(dev); 1759 1760 return 0; 1761 } 1762 1763 static int __maybe_unused gsc_runtime_suspend(struct device *dev) 1764 { 1765 struct gsc_context *ctx = get_gsc_context(dev); 1766 1767 DRM_DEBUG_KMS("id[%d]\n", ctx->id); 1768 1769 return gsc_clk_ctrl(ctx, false); 1770 } 1771 1772 static int __maybe_unused gsc_runtime_resume(struct device *dev) 1773 { 1774 struct gsc_context *ctx = get_gsc_context(dev); 1775 1776 DRM_DEBUG_KMS("id[%d]\n", ctx->id); 1777 1778 return gsc_clk_ctrl(ctx, true); 1779 } 1780 1781 static const struct dev_pm_ops gsc_pm_ops = { 1782 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 1783 pm_runtime_force_resume) 1784 SET_RUNTIME_PM_OPS(gsc_runtime_suspend, gsc_runtime_resume, NULL) 1785 }; 1786 1787 static const struct of_device_id exynos_drm_gsc_of_match[] = { 1788 { .compatible = "samsung,exynos5-gsc" }, 1789 { }, 1790 }; 1791 MODULE_DEVICE_TABLE(of, exynos_drm_gsc_of_match); 1792 1793 struct platform_driver gsc_driver = { 1794 .probe = gsc_probe, 1795 .remove = gsc_remove, 1796 .driver = { 1797 .name = "exynos-drm-gsc", 1798 .owner = THIS_MODULE, 1799 .pm = &gsc_pm_ops, 1800 .of_match_table = of_match_ptr(exynos_drm_gsc_of_match), 1801 }, 1802 }; 1803 1804