root/drivers/gpu/ipu-v3/ipu-ic.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ipu_ic_read
  2. ipu_ic_write
  3. init_csc
  4. calc_resize_coeffs
  5. ipu_ic_task_enable
  6. ipu_ic_task_disable
  7. ipu_ic_task_graphics_init
  8. ipu_ic_task_init_rsc
  9. ipu_ic_task_init
  10. ipu_ic_task_idma_init
  11. ipu_irt_enable
  12. ipu_irt_disable
  13. ipu_ic_enable
  14. ipu_ic_disable
  15. ipu_ic_get
  16. ipu_ic_put
  17. ipu_ic_init
  18. ipu_ic_exit
  19. ipu_ic_dump

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright (C) 2012-2014 Mentor Graphics Inc.
   4  * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
   5  */
   6 
   7 #include <linux/types.h>
   8 #include <linux/init.h>
   9 #include <linux/errno.h>
  10 #include <linux/spinlock.h>
  11 #include <linux/bitrev.h>
  12 #include <linux/io.h>
  13 #include <linux/err.h>
  14 #include <linux/sizes.h>
  15 #include "ipu-prv.h"
  16 
  17 /* IC Register Offsets */
  18 #define IC_CONF                 0x0000
  19 #define IC_PRP_ENC_RSC          0x0004
  20 #define IC_PRP_VF_RSC           0x0008
  21 #define IC_PP_RSC               0x000C
  22 #define IC_CMBP_1               0x0010
  23 #define IC_CMBP_2               0x0014
  24 #define IC_IDMAC_1              0x0018
  25 #define IC_IDMAC_2              0x001C
  26 #define IC_IDMAC_3              0x0020
  27 #define IC_IDMAC_4              0x0024
  28 
  29 /* IC Register Fields */
  30 #define IC_CONF_PRPENC_EN       (1 << 0)
  31 #define IC_CONF_PRPENC_CSC1     (1 << 1)
  32 #define IC_CONF_PRPENC_ROT_EN   (1 << 2)
  33 #define IC_CONF_PRPVF_EN        (1 << 8)
  34 #define IC_CONF_PRPVF_CSC1      (1 << 9)
  35 #define IC_CONF_PRPVF_CSC2      (1 << 10)
  36 #define IC_CONF_PRPVF_CMB       (1 << 11)
  37 #define IC_CONF_PRPVF_ROT_EN    (1 << 12)
  38 #define IC_CONF_PP_EN           (1 << 16)
  39 #define IC_CONF_PP_CSC1         (1 << 17)
  40 #define IC_CONF_PP_CSC2         (1 << 18)
  41 #define IC_CONF_PP_CMB          (1 << 19)
  42 #define IC_CONF_PP_ROT_EN       (1 << 20)
  43 #define IC_CONF_IC_GLB_LOC_A    (1 << 28)
  44 #define IC_CONF_KEY_COLOR_EN    (1 << 29)
  45 #define IC_CONF_RWS_EN          (1 << 30)
  46 #define IC_CONF_CSI_MEM_WR_EN   (1 << 31)
  47 
  48 #define IC_IDMAC_1_CB0_BURST_16         (1 << 0)
  49 #define IC_IDMAC_1_CB1_BURST_16         (1 << 1)
  50 #define IC_IDMAC_1_CB2_BURST_16         (1 << 2)
  51 #define IC_IDMAC_1_CB3_BURST_16         (1 << 3)
  52 #define IC_IDMAC_1_CB4_BURST_16         (1 << 4)
  53 #define IC_IDMAC_1_CB5_BURST_16         (1 << 5)
  54 #define IC_IDMAC_1_CB6_BURST_16         (1 << 6)
  55 #define IC_IDMAC_1_CB7_BURST_16         (1 << 7)
  56 #define IC_IDMAC_1_PRPENC_ROT_MASK      (0x7 << 11)
  57 #define IC_IDMAC_1_PRPENC_ROT_OFFSET    11
  58 #define IC_IDMAC_1_PRPVF_ROT_MASK       (0x7 << 14)
  59 #define IC_IDMAC_1_PRPVF_ROT_OFFSET     14
  60 #define IC_IDMAC_1_PP_ROT_MASK          (0x7 << 17)
  61 #define IC_IDMAC_1_PP_ROT_OFFSET        17
  62 #define IC_IDMAC_1_PP_FLIP_RS           (1 << 22)
  63 #define IC_IDMAC_1_PRPVF_FLIP_RS        (1 << 21)
  64 #define IC_IDMAC_1_PRPENC_FLIP_RS       (1 << 20)
  65 
  66 #define IC_IDMAC_2_PRPENC_HEIGHT_MASK   (0x3ff << 0)
  67 #define IC_IDMAC_2_PRPENC_HEIGHT_OFFSET 0
  68 #define IC_IDMAC_2_PRPVF_HEIGHT_MASK    (0x3ff << 10)
  69 #define IC_IDMAC_2_PRPVF_HEIGHT_OFFSET  10
  70 #define IC_IDMAC_2_PP_HEIGHT_MASK       (0x3ff << 20)
  71 #define IC_IDMAC_2_PP_HEIGHT_OFFSET     20
  72 
  73 #define IC_IDMAC_3_PRPENC_WIDTH_MASK    (0x3ff << 0)
  74 #define IC_IDMAC_3_PRPENC_WIDTH_OFFSET  0
  75 #define IC_IDMAC_3_PRPVF_WIDTH_MASK     (0x3ff << 10)
  76 #define IC_IDMAC_3_PRPVF_WIDTH_OFFSET   10
  77 #define IC_IDMAC_3_PP_WIDTH_MASK        (0x3ff << 20)
  78 #define IC_IDMAC_3_PP_WIDTH_OFFSET      20
  79 
  80 struct ic_task_regoffs {
  81         u32 rsc;
  82         u32 tpmem_csc[2];
  83 };
  84 
  85 struct ic_task_bitfields {
  86         u32 ic_conf_en;
  87         u32 ic_conf_rot_en;
  88         u32 ic_conf_cmb_en;
  89         u32 ic_conf_csc1_en;
  90         u32 ic_conf_csc2_en;
  91         u32 ic_cmb_galpha_bit;
  92 };
  93 
  94 static const struct ic_task_regoffs ic_task_reg[IC_NUM_TASKS] = {
  95         [IC_TASK_ENCODER] = {
  96                 .rsc = IC_PRP_ENC_RSC,
  97                 .tpmem_csc = {0x2008, 0},
  98         },
  99         [IC_TASK_VIEWFINDER] = {
 100                 .rsc = IC_PRP_VF_RSC,
 101                 .tpmem_csc = {0x4028, 0x4040},
 102         },
 103         [IC_TASK_POST_PROCESSOR] = {
 104                 .rsc = IC_PP_RSC,
 105                 .tpmem_csc = {0x6060, 0x6078},
 106         },
 107 };
 108 
 109 static const struct ic_task_bitfields ic_task_bit[IC_NUM_TASKS] = {
 110         [IC_TASK_ENCODER] = {
 111                 .ic_conf_en = IC_CONF_PRPENC_EN,
 112                 .ic_conf_rot_en = IC_CONF_PRPENC_ROT_EN,
 113                 .ic_conf_cmb_en = 0,    /* NA */
 114                 .ic_conf_csc1_en = IC_CONF_PRPENC_CSC1,
 115                 .ic_conf_csc2_en = 0,   /* NA */
 116                 .ic_cmb_galpha_bit = 0, /* NA */
 117         },
 118         [IC_TASK_VIEWFINDER] = {
 119                 .ic_conf_en = IC_CONF_PRPVF_EN,
 120                 .ic_conf_rot_en = IC_CONF_PRPVF_ROT_EN,
 121                 .ic_conf_cmb_en = IC_CONF_PRPVF_CMB,
 122                 .ic_conf_csc1_en = IC_CONF_PRPVF_CSC1,
 123                 .ic_conf_csc2_en = IC_CONF_PRPVF_CSC2,
 124                 .ic_cmb_galpha_bit = 0,
 125         },
 126         [IC_TASK_POST_PROCESSOR] = {
 127                 .ic_conf_en = IC_CONF_PP_EN,
 128                 .ic_conf_rot_en = IC_CONF_PP_ROT_EN,
 129                 .ic_conf_cmb_en = IC_CONF_PP_CMB,
 130                 .ic_conf_csc1_en = IC_CONF_PP_CSC1,
 131                 .ic_conf_csc2_en = IC_CONF_PP_CSC2,
 132                 .ic_cmb_galpha_bit = 8,
 133         },
 134 };
 135 
 136 struct ipu_ic_priv;
 137 
 138 struct ipu_ic {
 139         enum ipu_ic_task task;
 140         const struct ic_task_regoffs *reg;
 141         const struct ic_task_bitfields *bit;
 142 
 143         struct ipu_ic_colorspace in_cs;
 144         struct ipu_ic_colorspace g_in_cs;
 145         struct ipu_ic_colorspace out_cs;
 146 
 147         bool graphics;
 148         bool rotation;
 149         bool in_use;
 150 
 151         struct ipu_ic_priv *priv;
 152 };
 153 
 154 struct ipu_ic_priv {
 155         void __iomem *base;
 156         void __iomem *tpmem_base;
 157         spinlock_t lock;
 158         struct ipu_soc *ipu;
 159         int use_count;
 160         int irt_use_count;
 161         struct ipu_ic task[IC_NUM_TASKS];
 162 };
 163 
 164 static inline u32 ipu_ic_read(struct ipu_ic *ic, unsigned offset)
 165 {
 166         return readl(ic->priv->base + offset);
 167 }
 168 
 169 static inline void ipu_ic_write(struct ipu_ic *ic, u32 value, unsigned offset)
 170 {
 171         writel(value, ic->priv->base + offset);
 172 }
 173 
 174 static int init_csc(struct ipu_ic *ic,
 175                     const struct ipu_ic_csc *csc,
 176                     int csc_index)
 177 {
 178         struct ipu_ic_priv *priv = ic->priv;
 179         u32 __iomem *base;
 180         const u16 (*c)[3];
 181         const u16 *a;
 182         u32 param;
 183 
 184         base = (u32 __iomem *)
 185                 (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]);
 186 
 187         /* Cast to unsigned */
 188         c = (const u16 (*)[3])csc->params.coeff;
 189         a = (const u16 *)csc->params.offset;
 190 
 191         param = ((a[0] & 0x1f) << 27) | ((c[0][0] & 0x1ff) << 18) |
 192                 ((c[1][1] & 0x1ff) << 9) | (c[2][2] & 0x1ff);
 193         writel(param, base++);
 194 
 195         param = ((a[0] & 0x1fe0) >> 5) | (csc->params.scale << 8) |
 196                 (csc->params.sat << 10);
 197         writel(param, base++);
 198 
 199         param = ((a[1] & 0x1f) << 27) | ((c[0][1] & 0x1ff) << 18) |
 200                 ((c[1][0] & 0x1ff) << 9) | (c[2][0] & 0x1ff);
 201         writel(param, base++);
 202 
 203         param = ((a[1] & 0x1fe0) >> 5);
 204         writel(param, base++);
 205 
 206         param = ((a[2] & 0x1f) << 27) | ((c[0][2] & 0x1ff) << 18) |
 207                 ((c[1][2] & 0x1ff) << 9) | (c[2][1] & 0x1ff);
 208         writel(param, base++);
 209 
 210         param = ((a[2] & 0x1fe0) >> 5);
 211         writel(param, base++);
 212 
 213         return 0;
 214 }
 215 
 216 static int calc_resize_coeffs(struct ipu_ic *ic,
 217                               u32 in_size, u32 out_size,
 218                               u32 *resize_coeff,
 219                               u32 *downsize_coeff)
 220 {
 221         struct ipu_ic_priv *priv = ic->priv;
 222         struct ipu_soc *ipu = priv->ipu;
 223         u32 temp_size, temp_downsize;
 224 
 225         /*
 226          * Input size cannot be more than 4096, and output size cannot
 227          * be more than 1024
 228          */
 229         if (in_size > 4096) {
 230                 dev_err(ipu->dev, "Unsupported resize (in_size > 4096)\n");
 231                 return -EINVAL;
 232         }
 233         if (out_size > 1024) {
 234                 dev_err(ipu->dev, "Unsupported resize (out_size > 1024)\n");
 235                 return -EINVAL;
 236         }
 237 
 238         /* Cannot downsize more than 4:1 */
 239         if ((out_size << 2) < in_size) {
 240                 dev_err(ipu->dev, "Unsupported downsize\n");
 241                 return -EINVAL;
 242         }
 243 
 244         /* Compute downsizing coefficient */
 245         temp_downsize = 0;
 246         temp_size = in_size;
 247         while (((temp_size > 1024) || (temp_size >= out_size * 2)) &&
 248                (temp_downsize < 2)) {
 249                 temp_size >>= 1;
 250                 temp_downsize++;
 251         }
 252         *downsize_coeff = temp_downsize;
 253 
 254         /*
 255          * compute resizing coefficient using the following equation:
 256          * resize_coeff = M * (SI - 1) / (SO - 1)
 257          * where M = 2^13, SI = input size, SO = output size
 258          */
 259         *resize_coeff = (8192L * (temp_size - 1)) / (out_size - 1);
 260         if (*resize_coeff >= 16384L) {
 261                 dev_err(ipu->dev, "Warning! Overflow on resize coeff.\n");
 262                 *resize_coeff = 0x3FFF;
 263         }
 264 
 265         return 0;
 266 }
 267 
 268 void ipu_ic_task_enable(struct ipu_ic *ic)
 269 {
 270         struct ipu_ic_priv *priv = ic->priv;
 271         unsigned long flags;
 272         u32 ic_conf;
 273 
 274         spin_lock_irqsave(&priv->lock, flags);
 275 
 276         ic_conf = ipu_ic_read(ic, IC_CONF);
 277 
 278         ic_conf |= ic->bit->ic_conf_en;
 279 
 280         if (ic->rotation)
 281                 ic_conf |= ic->bit->ic_conf_rot_en;
 282 
 283         if (ic->in_cs.cs != ic->out_cs.cs)
 284                 ic_conf |= ic->bit->ic_conf_csc1_en;
 285 
 286         if (ic->graphics) {
 287                 ic_conf |= ic->bit->ic_conf_cmb_en;
 288                 ic_conf |= ic->bit->ic_conf_csc1_en;
 289 
 290                 if (ic->g_in_cs.cs != ic->out_cs.cs)
 291                         ic_conf |= ic->bit->ic_conf_csc2_en;
 292         }
 293 
 294         ipu_ic_write(ic, ic_conf, IC_CONF);
 295 
 296         spin_unlock_irqrestore(&priv->lock, flags);
 297 }
 298 EXPORT_SYMBOL_GPL(ipu_ic_task_enable);
 299 
 300 void ipu_ic_task_disable(struct ipu_ic *ic)
 301 {
 302         struct ipu_ic_priv *priv = ic->priv;
 303         unsigned long flags;
 304         u32 ic_conf;
 305 
 306         spin_lock_irqsave(&priv->lock, flags);
 307 
 308         ic_conf = ipu_ic_read(ic, IC_CONF);
 309 
 310         ic_conf &= ~(ic->bit->ic_conf_en |
 311                      ic->bit->ic_conf_csc1_en |
 312                      ic->bit->ic_conf_rot_en);
 313         if (ic->bit->ic_conf_csc2_en)
 314                 ic_conf &= ~ic->bit->ic_conf_csc2_en;
 315         if (ic->bit->ic_conf_cmb_en)
 316                 ic_conf &= ~ic->bit->ic_conf_cmb_en;
 317 
 318         ipu_ic_write(ic, ic_conf, IC_CONF);
 319 
 320         spin_unlock_irqrestore(&priv->lock, flags);
 321 }
 322 EXPORT_SYMBOL_GPL(ipu_ic_task_disable);
 323 
 324 int ipu_ic_task_graphics_init(struct ipu_ic *ic,
 325                               const struct ipu_ic_colorspace *g_in_cs,
 326                               bool galpha_en, u32 galpha,
 327                               bool colorkey_en, u32 colorkey)
 328 {
 329         struct ipu_ic_priv *priv = ic->priv;
 330         struct ipu_ic_csc csc2;
 331         unsigned long flags;
 332         u32 reg, ic_conf;
 333         int ret = 0;
 334 
 335         if (ic->task == IC_TASK_ENCODER)
 336                 return -EINVAL;
 337 
 338         spin_lock_irqsave(&priv->lock, flags);
 339 
 340         ic_conf = ipu_ic_read(ic, IC_CONF);
 341 
 342         if (!(ic_conf & ic->bit->ic_conf_csc1_en)) {
 343                 struct ipu_ic_csc csc1;
 344 
 345                 ret = ipu_ic_calc_csc(&csc1,
 346                                       V4L2_YCBCR_ENC_601,
 347                                       V4L2_QUANTIZATION_FULL_RANGE,
 348                                       IPUV3_COLORSPACE_RGB,
 349                                       V4L2_YCBCR_ENC_601,
 350                                       V4L2_QUANTIZATION_FULL_RANGE,
 351                                       IPUV3_COLORSPACE_RGB);
 352                 if (ret)
 353                         goto unlock;
 354 
 355                 /* need transparent CSC1 conversion */
 356                 ret = init_csc(ic, &csc1, 0);
 357                 if (ret)
 358                         goto unlock;
 359         }
 360 
 361         ic->g_in_cs = *g_in_cs;
 362         csc2.in_cs = ic->g_in_cs;
 363         csc2.out_cs = ic->out_cs;
 364 
 365         ret = __ipu_ic_calc_csc(&csc2);
 366         if (ret)
 367                 goto unlock;
 368 
 369         ret = init_csc(ic, &csc2, 1);
 370         if (ret)
 371                 goto unlock;
 372 
 373         if (galpha_en) {
 374                 ic_conf |= IC_CONF_IC_GLB_LOC_A;
 375                 reg = ipu_ic_read(ic, IC_CMBP_1);
 376                 reg &= ~(0xff << ic->bit->ic_cmb_galpha_bit);
 377                 reg |= (galpha << ic->bit->ic_cmb_galpha_bit);
 378                 ipu_ic_write(ic, reg, IC_CMBP_1);
 379         } else
 380                 ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
 381 
 382         if (colorkey_en) {
 383                 ic_conf |= IC_CONF_KEY_COLOR_EN;
 384                 ipu_ic_write(ic, colorkey, IC_CMBP_2);
 385         } else
 386                 ic_conf &= ~IC_CONF_KEY_COLOR_EN;
 387 
 388         ipu_ic_write(ic, ic_conf, IC_CONF);
 389 
 390         ic->graphics = true;
 391 unlock:
 392         spin_unlock_irqrestore(&priv->lock, flags);
 393         return ret;
 394 }
 395 EXPORT_SYMBOL_GPL(ipu_ic_task_graphics_init);
 396 
 397 int ipu_ic_task_init_rsc(struct ipu_ic *ic,
 398                          const struct ipu_ic_csc *csc,
 399                          int in_width, int in_height,
 400                          int out_width, int out_height,
 401                          u32 rsc)
 402 {
 403         struct ipu_ic_priv *priv = ic->priv;
 404         u32 downsize_coeff, resize_coeff;
 405         unsigned long flags;
 406         int ret = 0;
 407 
 408         if (!rsc) {
 409                 /* Setup vertical resizing */
 410 
 411                 ret = calc_resize_coeffs(ic, in_height, out_height,
 412                                          &resize_coeff, &downsize_coeff);
 413                 if (ret)
 414                         return ret;
 415 
 416                 rsc = (downsize_coeff << 30) | (resize_coeff << 16);
 417 
 418                 /* Setup horizontal resizing */
 419                 ret = calc_resize_coeffs(ic, in_width, out_width,
 420                                          &resize_coeff, &downsize_coeff);
 421                 if (ret)
 422                         return ret;
 423 
 424                 rsc |= (downsize_coeff << 14) | resize_coeff;
 425         }
 426 
 427         spin_lock_irqsave(&priv->lock, flags);
 428 
 429         ipu_ic_write(ic, rsc, ic->reg->rsc);
 430 
 431         /* Setup color space conversion */
 432         ic->in_cs = csc->in_cs;
 433         ic->out_cs = csc->out_cs;
 434 
 435         ret = init_csc(ic, csc, 0);
 436 
 437         spin_unlock_irqrestore(&priv->lock, flags);
 438         return ret;
 439 }
 440 
 441 int ipu_ic_task_init(struct ipu_ic *ic,
 442                      const struct ipu_ic_csc *csc,
 443                      int in_width, int in_height,
 444                      int out_width, int out_height)
 445 {
 446         return ipu_ic_task_init_rsc(ic, csc,
 447                                     in_width, in_height,
 448                                     out_width, out_height, 0);
 449 }
 450 EXPORT_SYMBOL_GPL(ipu_ic_task_init);
 451 
 452 int ipu_ic_task_idma_init(struct ipu_ic *ic, struct ipuv3_channel *channel,
 453                           u32 width, u32 height, int burst_size,
 454                           enum ipu_rotate_mode rot)
 455 {
 456         struct ipu_ic_priv *priv = ic->priv;
 457         struct ipu_soc *ipu = priv->ipu;
 458         u32 ic_idmac_1, ic_idmac_2, ic_idmac_3;
 459         u32 temp_rot = bitrev8(rot) >> 5;
 460         bool need_hor_flip = false;
 461         unsigned long flags;
 462         int ret = 0;
 463 
 464         if ((burst_size != 8) && (burst_size != 16)) {
 465                 dev_err(ipu->dev, "Illegal burst length for IC\n");
 466                 return -EINVAL;
 467         }
 468 
 469         width--;
 470         height--;
 471 
 472         if (temp_rot & 0x2)     /* Need horizontal flip */
 473                 need_hor_flip = true;
 474 
 475         spin_lock_irqsave(&priv->lock, flags);
 476 
 477         ic_idmac_1 = ipu_ic_read(ic, IC_IDMAC_1);
 478         ic_idmac_2 = ipu_ic_read(ic, IC_IDMAC_2);
 479         ic_idmac_3 = ipu_ic_read(ic, IC_IDMAC_3);
 480 
 481         switch (channel->num) {
 482         case IPUV3_CHANNEL_IC_PP_MEM:
 483                 if (burst_size == 16)
 484                         ic_idmac_1 |= IC_IDMAC_1_CB2_BURST_16;
 485                 else
 486                         ic_idmac_1 &= ~IC_IDMAC_1_CB2_BURST_16;
 487 
 488                 if (need_hor_flip)
 489                         ic_idmac_1 |= IC_IDMAC_1_PP_FLIP_RS;
 490                 else
 491                         ic_idmac_1 &= ~IC_IDMAC_1_PP_FLIP_RS;
 492 
 493                 ic_idmac_2 &= ~IC_IDMAC_2_PP_HEIGHT_MASK;
 494                 ic_idmac_2 |= height << IC_IDMAC_2_PP_HEIGHT_OFFSET;
 495 
 496                 ic_idmac_3 &= ~IC_IDMAC_3_PP_WIDTH_MASK;
 497                 ic_idmac_3 |= width << IC_IDMAC_3_PP_WIDTH_OFFSET;
 498                 break;
 499         case IPUV3_CHANNEL_MEM_IC_PP:
 500                 if (burst_size == 16)
 501                         ic_idmac_1 |= IC_IDMAC_1_CB5_BURST_16;
 502                 else
 503                         ic_idmac_1 &= ~IC_IDMAC_1_CB5_BURST_16;
 504                 break;
 505         case IPUV3_CHANNEL_MEM_ROT_PP:
 506                 ic_idmac_1 &= ~IC_IDMAC_1_PP_ROT_MASK;
 507                 ic_idmac_1 |= temp_rot << IC_IDMAC_1_PP_ROT_OFFSET;
 508                 break;
 509         case IPUV3_CHANNEL_MEM_IC_PRP_VF:
 510                 if (burst_size == 16)
 511                         ic_idmac_1 |= IC_IDMAC_1_CB6_BURST_16;
 512                 else
 513                         ic_idmac_1 &= ~IC_IDMAC_1_CB6_BURST_16;
 514                 break;
 515         case IPUV3_CHANNEL_IC_PRP_ENC_MEM:
 516                 if (burst_size == 16)
 517                         ic_idmac_1 |= IC_IDMAC_1_CB0_BURST_16;
 518                 else
 519                         ic_idmac_1 &= ~IC_IDMAC_1_CB0_BURST_16;
 520 
 521                 if (need_hor_flip)
 522                         ic_idmac_1 |= IC_IDMAC_1_PRPENC_FLIP_RS;
 523                 else
 524                         ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_FLIP_RS;
 525 
 526                 ic_idmac_2 &= ~IC_IDMAC_2_PRPENC_HEIGHT_MASK;
 527                 ic_idmac_2 |= height << IC_IDMAC_2_PRPENC_HEIGHT_OFFSET;
 528 
 529                 ic_idmac_3 &= ~IC_IDMAC_3_PRPENC_WIDTH_MASK;
 530                 ic_idmac_3 |= width << IC_IDMAC_3_PRPENC_WIDTH_OFFSET;
 531                 break;
 532         case IPUV3_CHANNEL_MEM_ROT_ENC:
 533                 ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_ROT_MASK;
 534                 ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPENC_ROT_OFFSET;
 535                 break;
 536         case IPUV3_CHANNEL_IC_PRP_VF_MEM:
 537                 if (burst_size == 16)
 538                         ic_idmac_1 |= IC_IDMAC_1_CB1_BURST_16;
 539                 else
 540                         ic_idmac_1 &= ~IC_IDMAC_1_CB1_BURST_16;
 541 
 542                 if (need_hor_flip)
 543                         ic_idmac_1 |= IC_IDMAC_1_PRPVF_FLIP_RS;
 544                 else
 545                         ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_FLIP_RS;
 546 
 547                 ic_idmac_2 &= ~IC_IDMAC_2_PRPVF_HEIGHT_MASK;
 548                 ic_idmac_2 |= height << IC_IDMAC_2_PRPVF_HEIGHT_OFFSET;
 549 
 550                 ic_idmac_3 &= ~IC_IDMAC_3_PRPVF_WIDTH_MASK;
 551                 ic_idmac_3 |= width << IC_IDMAC_3_PRPVF_WIDTH_OFFSET;
 552                 break;
 553         case IPUV3_CHANNEL_MEM_ROT_VF:
 554                 ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_ROT_MASK;
 555                 ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPVF_ROT_OFFSET;
 556                 break;
 557         case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:
 558                 if (burst_size == 16)
 559                         ic_idmac_1 |= IC_IDMAC_1_CB3_BURST_16;
 560                 else
 561                         ic_idmac_1 &= ~IC_IDMAC_1_CB3_BURST_16;
 562                 break;
 563         case IPUV3_CHANNEL_G_MEM_IC_PP:
 564                 if (burst_size == 16)
 565                         ic_idmac_1 |= IC_IDMAC_1_CB4_BURST_16;
 566                 else
 567                         ic_idmac_1 &= ~IC_IDMAC_1_CB4_BURST_16;
 568                 break;
 569         case IPUV3_CHANNEL_VDI_MEM_IC_VF:
 570                 if (burst_size == 16)
 571                         ic_idmac_1 |= IC_IDMAC_1_CB7_BURST_16;
 572                 else
 573                         ic_idmac_1 &= ~IC_IDMAC_1_CB7_BURST_16;
 574                 break;
 575         default:
 576                 goto unlock;
 577         }
 578 
 579         ipu_ic_write(ic, ic_idmac_1, IC_IDMAC_1);
 580         ipu_ic_write(ic, ic_idmac_2, IC_IDMAC_2);
 581         ipu_ic_write(ic, ic_idmac_3, IC_IDMAC_3);
 582 
 583         if (ipu_rot_mode_is_irt(rot))
 584                 ic->rotation = true;
 585 
 586 unlock:
 587         spin_unlock_irqrestore(&priv->lock, flags);
 588         return ret;
 589 }
 590 EXPORT_SYMBOL_GPL(ipu_ic_task_idma_init);
 591 
 592 static void ipu_irt_enable(struct ipu_ic *ic)
 593 {
 594         struct ipu_ic_priv *priv = ic->priv;
 595 
 596         if (!priv->irt_use_count)
 597                 ipu_module_enable(priv->ipu, IPU_CONF_ROT_EN);
 598 
 599         priv->irt_use_count++;
 600 }
 601 
 602 static void ipu_irt_disable(struct ipu_ic *ic)
 603 {
 604         struct ipu_ic_priv *priv = ic->priv;
 605 
 606         if (priv->irt_use_count) {
 607                 if (!--priv->irt_use_count)
 608                         ipu_module_disable(priv->ipu, IPU_CONF_ROT_EN);
 609         }
 610 }
 611 
 612 int ipu_ic_enable(struct ipu_ic *ic)
 613 {
 614         struct ipu_ic_priv *priv = ic->priv;
 615         unsigned long flags;
 616 
 617         spin_lock_irqsave(&priv->lock, flags);
 618 
 619         if (!priv->use_count)
 620                 ipu_module_enable(priv->ipu, IPU_CONF_IC_EN);
 621 
 622         priv->use_count++;
 623 
 624         if (ic->rotation)
 625                 ipu_irt_enable(ic);
 626 
 627         spin_unlock_irqrestore(&priv->lock, flags);
 628 
 629         return 0;
 630 }
 631 EXPORT_SYMBOL_GPL(ipu_ic_enable);
 632 
 633 int ipu_ic_disable(struct ipu_ic *ic)
 634 {
 635         struct ipu_ic_priv *priv = ic->priv;
 636         unsigned long flags;
 637 
 638         spin_lock_irqsave(&priv->lock, flags);
 639 
 640         priv->use_count--;
 641 
 642         if (!priv->use_count)
 643                 ipu_module_disable(priv->ipu, IPU_CONF_IC_EN);
 644 
 645         if (priv->use_count < 0)
 646                 priv->use_count = 0;
 647 
 648         if (ic->rotation)
 649                 ipu_irt_disable(ic);
 650 
 651         ic->rotation = ic->graphics = false;
 652 
 653         spin_unlock_irqrestore(&priv->lock, flags);
 654 
 655         return 0;
 656 }
 657 EXPORT_SYMBOL_GPL(ipu_ic_disable);
 658 
 659 struct ipu_ic *ipu_ic_get(struct ipu_soc *ipu, enum ipu_ic_task task)
 660 {
 661         struct ipu_ic_priv *priv = ipu->ic_priv;
 662         unsigned long flags;
 663         struct ipu_ic *ic, *ret;
 664 
 665         if (task >= IC_NUM_TASKS)
 666                 return ERR_PTR(-EINVAL);
 667 
 668         ic = &priv->task[task];
 669 
 670         spin_lock_irqsave(&priv->lock, flags);
 671 
 672         if (ic->in_use) {
 673                 ret = ERR_PTR(-EBUSY);
 674                 goto unlock;
 675         }
 676 
 677         ic->in_use = true;
 678         ret = ic;
 679 
 680 unlock:
 681         spin_unlock_irqrestore(&priv->lock, flags);
 682         return ret;
 683 }
 684 EXPORT_SYMBOL_GPL(ipu_ic_get);
 685 
 686 void ipu_ic_put(struct ipu_ic *ic)
 687 {
 688         struct ipu_ic_priv *priv = ic->priv;
 689         unsigned long flags;
 690 
 691         spin_lock_irqsave(&priv->lock, flags);
 692         ic->in_use = false;
 693         spin_unlock_irqrestore(&priv->lock, flags);
 694 }
 695 EXPORT_SYMBOL_GPL(ipu_ic_put);
 696 
 697 int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
 698                 unsigned long base, unsigned long tpmem_base)
 699 {
 700         struct ipu_ic_priv *priv;
 701         int i;
 702 
 703         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 704         if (!priv)
 705                 return -ENOMEM;
 706 
 707         ipu->ic_priv = priv;
 708 
 709         spin_lock_init(&priv->lock);
 710         priv->base = devm_ioremap(dev, base, PAGE_SIZE);
 711         if (!priv->base)
 712                 return -ENOMEM;
 713         priv->tpmem_base = devm_ioremap(dev, tpmem_base, SZ_64K);
 714         if (!priv->tpmem_base)
 715                 return -ENOMEM;
 716 
 717         dev_dbg(dev, "IC base: 0x%08lx remapped to %p\n", base, priv->base);
 718 
 719         priv->ipu = ipu;
 720 
 721         for (i = 0; i < IC_NUM_TASKS; i++) {
 722                 priv->task[i].task = i;
 723                 priv->task[i].priv = priv;
 724                 priv->task[i].reg = &ic_task_reg[i];
 725                 priv->task[i].bit = &ic_task_bit[i];
 726         }
 727 
 728         return 0;
 729 }
 730 
 731 void ipu_ic_exit(struct ipu_soc *ipu)
 732 {
 733 }
 734 
 735 void ipu_ic_dump(struct ipu_ic *ic)
 736 {
 737         struct ipu_ic_priv *priv = ic->priv;
 738         struct ipu_soc *ipu = priv->ipu;
 739 
 740         dev_dbg(ipu->dev, "IC_CONF = \t0x%08X\n",
 741                 ipu_ic_read(ic, IC_CONF));
 742         dev_dbg(ipu->dev, "IC_PRP_ENC_RSC = \t0x%08X\n",
 743                 ipu_ic_read(ic, IC_PRP_ENC_RSC));
 744         dev_dbg(ipu->dev, "IC_PRP_VF_RSC = \t0x%08X\n",
 745                 ipu_ic_read(ic, IC_PRP_VF_RSC));
 746         dev_dbg(ipu->dev, "IC_PP_RSC = \t0x%08X\n",
 747                 ipu_ic_read(ic, IC_PP_RSC));
 748         dev_dbg(ipu->dev, "IC_CMBP_1 = \t0x%08X\n",
 749                 ipu_ic_read(ic, IC_CMBP_1));
 750         dev_dbg(ipu->dev, "IC_CMBP_2 = \t0x%08X\n",
 751                 ipu_ic_read(ic, IC_CMBP_2));
 752         dev_dbg(ipu->dev, "IC_IDMAC_1 = \t0x%08X\n",
 753                 ipu_ic_read(ic, IC_IDMAC_1));
 754         dev_dbg(ipu->dev, "IC_IDMAC_2 = \t0x%08X\n",
 755                 ipu_ic_read(ic, IC_IDMAC_2));
 756         dev_dbg(ipu->dev, "IC_IDMAC_3 = \t0x%08X\n",
 757                 ipu_ic_read(ic, IC_IDMAC_3));
 758         dev_dbg(ipu->dev, "IC_IDMAC_4 = \t0x%08X\n",
 759                 ipu_ic_read(ic, IC_IDMAC_4));
 760 }
 761 EXPORT_SYMBOL_GPL(ipu_ic_dump);

/* [<][>][^][v][top][bottom][index][help] */