linux/drivers/media/platform/ti-vpe/cal.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * TI Camera Access Layer (CAL) - Driver
   4 *
   5 * Copyright (c) 2015-2020 Texas Instruments Inc.
   6 *
   7 * Authors:
   8 *      Benoit Parrot <bparrot@ti.com>
   9 *      Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  10 */
  11
  12#include <linux/clk.h>
  13#include <linux/interrupt.h>
  14#include <linux/mfd/syscon.h>
  15#include <linux/module.h>
  16#include <linux/of_device.h>
  17#include <linux/platform_device.h>
  18#include <linux/pm_runtime.h>
  19#include <linux/regmap.h>
  20#include <linux/slab.h>
  21#include <linux/videodev2.h>
  22
  23#include <media/media-device.h>
  24#include <media/v4l2-async.h>
  25#include <media/v4l2-common.h>
  26#include <media/v4l2-device.h>
  27#include <media/videobuf2-core.h>
  28#include <media/videobuf2-dma-contig.h>
  29
  30#include "cal.h"
  31#include "cal_regs.h"
  32
  33MODULE_DESCRIPTION("TI CAL driver");
  34MODULE_AUTHOR("Benoit Parrot, <bparrot@ti.com>");
  35MODULE_LICENSE("GPL v2");
  36MODULE_VERSION("0.1.0");
  37
  38int cal_video_nr = -1;
  39module_param_named(video_nr, cal_video_nr, uint, 0644);
  40MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
  41
  42unsigned int cal_debug;
  43module_param_named(debug, cal_debug, uint, 0644);
  44MODULE_PARM_DESC(debug, "activates debug info");
  45
  46#ifdef CONFIG_VIDEO_TI_CAL_MC
  47#define CAL_MC_API_DEFAULT 1
  48#else
  49#define CAL_MC_API_DEFAULT 0
  50#endif
  51
  52bool cal_mc_api = CAL_MC_API_DEFAULT;
  53module_param_named(mc_api, cal_mc_api, bool, 0444);
  54MODULE_PARM_DESC(mc_api, "activates the MC API");
  55
  56/* ------------------------------------------------------------------
  57 *      Format Handling
  58 * ------------------------------------------------------------------
  59 */
  60
  61const struct cal_format_info cal_formats[] = {
  62        {
  63                .fourcc         = V4L2_PIX_FMT_YUYV,
  64                .code           = MEDIA_BUS_FMT_YUYV8_2X8,
  65                .bpp            = 16,
  66        }, {
  67                .fourcc         = V4L2_PIX_FMT_UYVY,
  68                .code           = MEDIA_BUS_FMT_UYVY8_2X8,
  69                .bpp            = 16,
  70        }, {
  71                .fourcc         = V4L2_PIX_FMT_YVYU,
  72                .code           = MEDIA_BUS_FMT_YVYU8_2X8,
  73                .bpp            = 16,
  74        }, {
  75                .fourcc         = V4L2_PIX_FMT_VYUY,
  76                .code           = MEDIA_BUS_FMT_VYUY8_2X8,
  77                .bpp            = 16,
  78        }, {
  79                .fourcc         = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
  80                .code           = MEDIA_BUS_FMT_RGB565_2X8_LE,
  81                .bpp            = 16,
  82        }, {
  83                .fourcc         = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
  84                .code           = MEDIA_BUS_FMT_RGB565_2X8_BE,
  85                .bpp            = 16,
  86        }, {
  87                .fourcc         = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
  88                .code           = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
  89                .bpp            = 16,
  90        }, {
  91                .fourcc         = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
  92                .code           = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
  93                .bpp            = 16,
  94        }, {
  95                .fourcc         = V4L2_PIX_FMT_RGB24, /* rgb */
  96                .code           = MEDIA_BUS_FMT_RGB888_2X12_LE,
  97                .bpp            = 24,
  98        }, {
  99                .fourcc         = V4L2_PIX_FMT_BGR24, /* bgr */
 100                .code           = MEDIA_BUS_FMT_RGB888_2X12_BE,
 101                .bpp            = 24,
 102        }, {
 103                .fourcc         = V4L2_PIX_FMT_RGB32, /* argb */
 104                .code           = MEDIA_BUS_FMT_ARGB8888_1X32,
 105                .bpp            = 32,
 106        }, {
 107                .fourcc         = V4L2_PIX_FMT_SBGGR8,
 108                .code           = MEDIA_BUS_FMT_SBGGR8_1X8,
 109                .bpp            = 8,
 110        }, {
 111                .fourcc         = V4L2_PIX_FMT_SGBRG8,
 112                .code           = MEDIA_BUS_FMT_SGBRG8_1X8,
 113                .bpp            = 8,
 114        }, {
 115                .fourcc         = V4L2_PIX_FMT_SGRBG8,
 116                .code           = MEDIA_BUS_FMT_SGRBG8_1X8,
 117                .bpp            = 8,
 118        }, {
 119                .fourcc         = V4L2_PIX_FMT_SRGGB8,
 120                .code           = MEDIA_BUS_FMT_SRGGB8_1X8,
 121                .bpp            = 8,
 122        }, {
 123                .fourcc         = V4L2_PIX_FMT_SBGGR10,
 124                .code           = MEDIA_BUS_FMT_SBGGR10_1X10,
 125                .bpp            = 10,
 126        }, {
 127                .fourcc         = V4L2_PIX_FMT_SGBRG10,
 128                .code           = MEDIA_BUS_FMT_SGBRG10_1X10,
 129                .bpp            = 10,
 130        }, {
 131                .fourcc         = V4L2_PIX_FMT_SGRBG10,
 132                .code           = MEDIA_BUS_FMT_SGRBG10_1X10,
 133                .bpp            = 10,
 134        }, {
 135                .fourcc         = V4L2_PIX_FMT_SRGGB10,
 136                .code           = MEDIA_BUS_FMT_SRGGB10_1X10,
 137                .bpp            = 10,
 138        }, {
 139                .fourcc         = V4L2_PIX_FMT_SBGGR12,
 140                .code           = MEDIA_BUS_FMT_SBGGR12_1X12,
 141                .bpp            = 12,
 142        }, {
 143                .fourcc         = V4L2_PIX_FMT_SGBRG12,
 144                .code           = MEDIA_BUS_FMT_SGBRG12_1X12,
 145                .bpp            = 12,
 146        }, {
 147                .fourcc         = V4L2_PIX_FMT_SGRBG12,
 148                .code           = MEDIA_BUS_FMT_SGRBG12_1X12,
 149                .bpp            = 12,
 150        }, {
 151                .fourcc         = V4L2_PIX_FMT_SRGGB12,
 152                .code           = MEDIA_BUS_FMT_SRGGB12_1X12,
 153                .bpp            = 12,
 154        },
 155};
 156
 157const unsigned int cal_num_formats = ARRAY_SIZE(cal_formats);
 158
 159const struct cal_format_info *cal_format_by_fourcc(u32 fourcc)
 160{
 161        unsigned int i;
 162
 163        for (i = 0; i < ARRAY_SIZE(cal_formats); ++i) {
 164                if (cal_formats[i].fourcc == fourcc)
 165                        return &cal_formats[i];
 166        }
 167
 168        return NULL;
 169}
 170
 171const struct cal_format_info *cal_format_by_code(u32 code)
 172{
 173        unsigned int i;
 174
 175        for (i = 0; i < ARRAY_SIZE(cal_formats); ++i) {
 176                if (cal_formats[i].code == code)
 177                        return &cal_formats[i];
 178        }
 179
 180        return NULL;
 181}
 182
 183/* ------------------------------------------------------------------
 184 *      Platform Data
 185 * ------------------------------------------------------------------
 186 */
 187
 188static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
 189        {
 190                .fields = {
 191                        [F_CTRLCLKEN] = { 10, 10 },
 192                        [F_CAMMODE] = { 11, 12 },
 193                        [F_LANEENABLE] = { 13, 16 },
 194                        [F_CSI_MODE] = { 17, 17 },
 195                },
 196                .num_lanes = 4,
 197        },
 198        {
 199                .fields = {
 200                        [F_CTRLCLKEN] = { 0, 0 },
 201                        [F_CAMMODE] = { 1, 2 },
 202                        [F_LANEENABLE] = { 3, 4 },
 203                        [F_CSI_MODE] = { 5, 5 },
 204                },
 205                .num_lanes = 2,
 206        },
 207};
 208
 209static const struct cal_data dra72x_cal_data = {
 210        .camerarx = dra72x_cal_camerarx,
 211        .num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
 212};
 213
 214static const struct cal_data dra72x_es1_cal_data = {
 215        .camerarx = dra72x_cal_camerarx,
 216        .num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
 217        .flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
 218};
 219
 220static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
 221        {
 222                .fields = {
 223                        [F_CTRLCLKEN] = { 8, 8 },
 224                        [F_CAMMODE] = { 9, 10 },
 225                        [F_CSI_MODE] = { 11, 11 },
 226                        [F_LANEENABLE] = { 27, 31 },
 227                },
 228                .num_lanes = 5,
 229        },
 230        {
 231                .fields = {
 232                        [F_CTRLCLKEN] = { 0, 0 },
 233                        [F_CAMMODE] = { 1, 2 },
 234                        [F_CSI_MODE] = { 3, 3 },
 235                        [F_LANEENABLE] = { 24, 26 },
 236                },
 237                .num_lanes = 3,
 238        },
 239};
 240
 241static const struct cal_data dra76x_cal_data = {
 242        .camerarx = dra76x_cal_csi_phy,
 243        .num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
 244};
 245
 246static const struct cal_camerarx_data am654_cal_csi_phy[] = {
 247        {
 248                .fields = {
 249                        [F_CTRLCLKEN] = { 15, 15 },
 250                        [F_CAMMODE] = { 24, 25 },
 251                        [F_LANEENABLE] = { 0, 4 },
 252                },
 253                .num_lanes = 5,
 254        },
 255};
 256
 257static const struct cal_data am654_cal_data = {
 258        .camerarx = am654_cal_csi_phy,
 259        .num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
 260};
 261
 262/* ------------------------------------------------------------------
 263 *      I/O Register Accessors
 264 * ------------------------------------------------------------------
 265 */
 266
 267void cal_quickdump_regs(struct cal_dev *cal)
 268{
 269        unsigned int i;
 270
 271        cal_info(cal, "CAL Registers @ 0x%pa:\n", &cal->res->start);
 272        print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
 273                       (__force const void *)cal->base,
 274                       resource_size(cal->res), false);
 275
 276        for (i = 0; i < cal->data->num_csi2_phy; ++i) {
 277                struct cal_camerarx *phy = cal->phy[i];
 278
 279                cal_info(cal, "CSI2 Core %u Registers @ %pa:\n", i,
 280                         &phy->res->start);
 281                print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
 282                               (__force const void *)phy->base,
 283                               resource_size(phy->res),
 284                               false);
 285        }
 286}
 287
 288/* ------------------------------------------------------------------
 289 *      Context Management
 290 * ------------------------------------------------------------------
 291 */
 292
 293#define CAL_MAX_PIX_PROC 4
 294
 295static int cal_reserve_pix_proc(struct cal_dev *cal)
 296{
 297        unsigned long ret;
 298
 299        spin_lock(&cal->v4l2_dev.lock);
 300
 301        ret = find_first_zero_bit(&cal->reserved_pix_proc_mask, CAL_MAX_PIX_PROC);
 302
 303        if (ret == CAL_MAX_PIX_PROC) {
 304                spin_unlock(&cal->v4l2_dev.lock);
 305                return -ENOSPC;
 306        }
 307
 308        cal->reserved_pix_proc_mask |= BIT(ret);
 309
 310        spin_unlock(&cal->v4l2_dev.lock);
 311
 312        return ret;
 313}
 314
 315static void cal_release_pix_proc(struct cal_dev *cal, unsigned int pix_proc_num)
 316{
 317        spin_lock(&cal->v4l2_dev.lock);
 318
 319        cal->reserved_pix_proc_mask &= ~BIT(pix_proc_num);
 320
 321        spin_unlock(&cal->v4l2_dev.lock);
 322}
 323
 324static void cal_ctx_csi2_config(struct cal_ctx *ctx)
 325{
 326        u32 val;
 327
 328        val = cal_read(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx));
 329        cal_set_field(&val, ctx->cport, CAL_CSI2_CTX_CPORT_MASK);
 330        /*
 331         * DT type: MIPI CSI-2 Specs
 332         *   0x1: All - DT filter is disabled
 333         *  0x24: RGB888 1 pixel  = 3 bytes
 334         *  0x2B: RAW10  4 pixels = 5 bytes
 335         *  0x2A: RAW8   1 pixel  = 1 byte
 336         *  0x1E: YUV422 2 pixels = 4 bytes
 337         */
 338        cal_set_field(&val, ctx->datatype, CAL_CSI2_CTX_DT_MASK);
 339        cal_set_field(&val, ctx->vc, CAL_CSI2_CTX_VC_MASK);
 340        cal_set_field(&val, ctx->v_fmt.fmt.pix.height, CAL_CSI2_CTX_LINES_MASK);
 341        cal_set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK);
 342        cal_set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE,
 343                      CAL_CSI2_CTX_PACK_MODE_MASK);
 344        cal_write(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx), val);
 345        ctx_dbg(3, ctx, "CAL_CSI2_CTX(%u, %u) = 0x%08x\n",
 346                ctx->phy->instance, ctx->csi2_ctx,
 347                cal_read(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx)));
 348}
 349
 350static void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
 351{
 352        u32 val, extract, pack;
 353
 354        switch (ctx->fmtinfo->bpp) {
 355        case 8:
 356                extract = CAL_PIX_PROC_EXTRACT_B8;
 357                pack = CAL_PIX_PROC_PACK_B8;
 358                break;
 359        case 10:
 360                extract = CAL_PIX_PROC_EXTRACT_B10_MIPI;
 361                pack = CAL_PIX_PROC_PACK_B16;
 362                break;
 363        case 12:
 364                extract = CAL_PIX_PROC_EXTRACT_B12_MIPI;
 365                pack = CAL_PIX_PROC_PACK_B16;
 366                break;
 367        case 16:
 368                extract = CAL_PIX_PROC_EXTRACT_B16_LE;
 369                pack = CAL_PIX_PROC_PACK_B16;
 370                break;
 371        default:
 372                /*
 373                 * If you see this warning then it means that you added
 374                 * some new entry in the cal_formats[] array with a different
 375                 * bit per pixel values then the one supported below.
 376                 * Either add support for the new bpp value below or adjust
 377                 * the new entry to use one of the value below.
 378                 *
 379                 * Instead of failing here just use 8 bpp as a default.
 380                 */
 381                dev_warn_once(ctx->cal->dev,
 382                              "%s:%d:%s: bpp:%d unsupported! Overwritten with 8.\n",
 383                              __FILE__, __LINE__, __func__, ctx->fmtinfo->bpp);
 384                extract = CAL_PIX_PROC_EXTRACT_B8;
 385                pack = CAL_PIX_PROC_PACK_B8;
 386                break;
 387        }
 388
 389        val = cal_read(ctx->cal, CAL_PIX_PROC(ctx->pix_proc));
 390        cal_set_field(&val, extract, CAL_PIX_PROC_EXTRACT_MASK);
 391        cal_set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK);
 392        cal_set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK);
 393        cal_set_field(&val, pack, CAL_PIX_PROC_PACK_MASK);
 394        cal_set_field(&val, ctx->cport, CAL_PIX_PROC_CPORT_MASK);
 395        cal_set_field(&val, 1, CAL_PIX_PROC_EN_MASK);
 396        cal_write(ctx->cal, CAL_PIX_PROC(ctx->pix_proc), val);
 397        ctx_dbg(3, ctx, "CAL_PIX_PROC(%u) = 0x%08x\n", ctx->pix_proc,
 398                cal_read(ctx->cal, CAL_PIX_PROC(ctx->pix_proc)));
 399}
 400
 401static void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
 402{
 403        unsigned int stride = ctx->v_fmt.fmt.pix.bytesperline;
 404        u32 val;
 405
 406        val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx));
 407        cal_set_field(&val, ctx->cport, CAL_WR_DMA_CTRL_CPORT_MASK);
 408        cal_set_field(&val, ctx->v_fmt.fmt.pix.height,
 409                      CAL_WR_DMA_CTRL_YSIZE_MASK);
 410        cal_set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT,
 411                      CAL_WR_DMA_CTRL_DTAG_MASK);
 412        cal_set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR,
 413                      CAL_WR_DMA_CTRL_PATTERN_MASK);
 414        cal_set_field(&val, 1, CAL_WR_DMA_CTRL_STALL_RD_MASK);
 415        cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx), val);
 416        ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->dma_ctx,
 417                cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx)));
 418
 419        cal_write_field(ctx->cal, CAL_WR_DMA_OFST(ctx->dma_ctx),
 420                        stride / 16, CAL_WR_DMA_OFST_MASK);
 421        ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->dma_ctx,
 422                cal_read(ctx->cal, CAL_WR_DMA_OFST(ctx->dma_ctx)));
 423
 424        val = cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->dma_ctx));
 425        /* 64 bit word means no skipping */
 426        cal_set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK);
 427        /*
 428         * The XSIZE field is expressed in 64-bit units and prevents overflows
 429         * in case of synchronization issues by limiting the number of bytes
 430         * written per line.
 431         */
 432        cal_set_field(&val, stride / 8, CAL_WR_DMA_XSIZE_MASK);
 433        cal_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->dma_ctx), val);
 434        ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->dma_ctx,
 435                cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->dma_ctx)));
 436}
 437
 438void cal_ctx_set_dma_addr(struct cal_ctx *ctx, dma_addr_t addr)
 439{
 440        cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->dma_ctx), addr);
 441}
 442
 443static void cal_ctx_wr_dma_enable(struct cal_ctx *ctx)
 444{
 445        u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx));
 446
 447        cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST,
 448                      CAL_WR_DMA_CTRL_MODE_MASK);
 449        cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx), val);
 450}
 451
 452static void cal_ctx_wr_dma_disable(struct cal_ctx *ctx)
 453{
 454        u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx));
 455
 456        cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_DIS,
 457                      CAL_WR_DMA_CTRL_MODE_MASK);
 458        cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx), val);
 459}
 460
 461static bool cal_ctx_wr_dma_stopped(struct cal_ctx *ctx)
 462{
 463        bool stopped;
 464
 465        spin_lock_irq(&ctx->dma.lock);
 466        stopped = ctx->dma.state == CAL_DMA_STOPPED;
 467        spin_unlock_irq(&ctx->dma.lock);
 468
 469        return stopped;
 470}
 471
 472int cal_ctx_prepare(struct cal_ctx *ctx)
 473{
 474        int ret;
 475
 476        ctx->use_pix_proc = !ctx->fmtinfo->meta;
 477
 478        if (ctx->use_pix_proc) {
 479                ret = cal_reserve_pix_proc(ctx->cal);
 480                if (ret < 0) {
 481                        ctx_err(ctx, "Failed to reserve pix proc: %d\n", ret);
 482                        return ret;
 483                }
 484
 485                ctx->pix_proc = ret;
 486        }
 487
 488        return 0;
 489}
 490
 491void cal_ctx_unprepare(struct cal_ctx *ctx)
 492{
 493        if (ctx->use_pix_proc)
 494                cal_release_pix_proc(ctx->cal, ctx->pix_proc);
 495}
 496
 497void cal_ctx_start(struct cal_ctx *ctx)
 498{
 499        ctx->sequence = 0;
 500        ctx->dma.state = CAL_DMA_RUNNING;
 501
 502        /* Configure the CSI-2, pixel processing and write DMA contexts. */
 503        cal_ctx_csi2_config(ctx);
 504        if (ctx->use_pix_proc)
 505                cal_ctx_pix_proc_config(ctx);
 506        cal_ctx_wr_dma_config(ctx);
 507
 508        /* Enable IRQ_WDMA_END and IRQ_WDMA_START. */
 509        cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(1),
 510                  CAL_HL_IRQ_WDMA_END_MASK(ctx->dma_ctx));
 511        cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(2),
 512                  CAL_HL_IRQ_WDMA_START_MASK(ctx->dma_ctx));
 513
 514        cal_ctx_wr_dma_enable(ctx);
 515}
 516
 517void cal_ctx_stop(struct cal_ctx *ctx)
 518{
 519        long timeout;
 520
 521        /*
 522         * Request DMA stop and wait until it completes. If completion times
 523         * out, forcefully disable the DMA.
 524         */
 525        spin_lock_irq(&ctx->dma.lock);
 526        ctx->dma.state = CAL_DMA_STOP_REQUESTED;
 527        spin_unlock_irq(&ctx->dma.lock);
 528
 529        timeout = wait_event_timeout(ctx->dma.wait, cal_ctx_wr_dma_stopped(ctx),
 530                                     msecs_to_jiffies(500));
 531        if (!timeout) {
 532                ctx_err(ctx, "failed to disable dma cleanly\n");
 533                cal_ctx_wr_dma_disable(ctx);
 534        }
 535
 536        /* Disable IRQ_WDMA_END and IRQ_WDMA_START. */
 537        cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(1),
 538                  CAL_HL_IRQ_WDMA_END_MASK(ctx->dma_ctx));
 539        cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(2),
 540                  CAL_HL_IRQ_WDMA_START_MASK(ctx->dma_ctx));
 541
 542        ctx->dma.state = CAL_DMA_STOPPED;
 543
 544        /* Disable CSI2 context */
 545        cal_write(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx), 0);
 546
 547        /* Disable pix proc */
 548        if (ctx->use_pix_proc)
 549                cal_write(ctx->cal, CAL_PIX_PROC(ctx->pix_proc), 0);
 550}
 551
 552/* ------------------------------------------------------------------
 553 *      IRQ Handling
 554 * ------------------------------------------------------------------
 555 */
 556
 557static inline void cal_irq_wdma_start(struct cal_ctx *ctx)
 558{
 559        spin_lock(&ctx->dma.lock);
 560
 561        if (ctx->dma.state == CAL_DMA_STOP_REQUESTED) {
 562                /*
 563                 * If a stop is requested, disable the write DMA context
 564                 * immediately. The CAL_WR_DMA_CTRL_j.MODE field is shadowed,
 565                 * the current frame will complete and the DMA will then stop.
 566                 */
 567                cal_ctx_wr_dma_disable(ctx);
 568                ctx->dma.state = CAL_DMA_STOP_PENDING;
 569        } else if (!list_empty(&ctx->dma.queue) && !ctx->dma.pending) {
 570                /*
 571                 * Otherwise, if a new buffer is available, queue it to the
 572                 * hardware.
 573                 */
 574                struct cal_buffer *buf;
 575                dma_addr_t addr;
 576
 577                buf = list_first_entry(&ctx->dma.queue, struct cal_buffer,
 578                                       list);
 579                addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
 580                cal_ctx_set_dma_addr(ctx, addr);
 581
 582                ctx->dma.pending = buf;
 583                list_del(&buf->list);
 584        }
 585
 586        spin_unlock(&ctx->dma.lock);
 587}
 588
 589static inline void cal_irq_wdma_end(struct cal_ctx *ctx)
 590{
 591        struct cal_buffer *buf = NULL;
 592
 593        spin_lock(&ctx->dma.lock);
 594
 595        /* If the DMA context was stopping, it is now stopped. */
 596        if (ctx->dma.state == CAL_DMA_STOP_PENDING) {
 597                ctx->dma.state = CAL_DMA_STOPPED;
 598                wake_up(&ctx->dma.wait);
 599        }
 600
 601        /* If a new buffer was queued, complete the current buffer. */
 602        if (ctx->dma.pending) {
 603                buf = ctx->dma.active;
 604                ctx->dma.active = ctx->dma.pending;
 605                ctx->dma.pending = NULL;
 606        }
 607
 608        spin_unlock(&ctx->dma.lock);
 609
 610        if (buf) {
 611                buf->vb.vb2_buf.timestamp = ktime_get_ns();
 612                buf->vb.field = ctx->v_fmt.fmt.pix.field;
 613                buf->vb.sequence = ctx->sequence++;
 614                vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 615        }
 616}
 617
 618static irqreturn_t cal_irq(int irq_cal, void *data)
 619{
 620        struct cal_dev *cal = data;
 621        u32 status;
 622
 623        status = cal_read(cal, CAL_HL_IRQSTATUS(0));
 624        if (status) {
 625                unsigned int i;
 626
 627                cal_write(cal, CAL_HL_IRQSTATUS(0), status);
 628
 629                if (status & CAL_HL_IRQ_OCPO_ERR_MASK)
 630                        dev_err_ratelimited(cal->dev, "OCPO ERROR\n");
 631
 632                for (i = 0; i < cal->data->num_csi2_phy; ++i) {
 633                        if (status & CAL_HL_IRQ_CIO_MASK(i)) {
 634                                u32 cio_stat = cal_read(cal,
 635                                                        CAL_CSI2_COMPLEXIO_IRQSTATUS(i));
 636
 637                                dev_err_ratelimited(cal->dev,
 638                                                    "CIO%u error: %#08x\n", i, cio_stat);
 639
 640                                cal_write(cal, CAL_CSI2_COMPLEXIO_IRQSTATUS(i),
 641                                          cio_stat);
 642                        }
 643
 644                        if (status & CAL_HL_IRQ_VC_MASK(i)) {
 645                                u32 vc_stat = cal_read(cal, CAL_CSI2_VC_IRQSTATUS(i));
 646
 647                                dev_err_ratelimited(cal->dev,
 648                                                    "CIO%u VC error: %#08x\n",
 649                                                    i, vc_stat);
 650
 651                                cal_write(cal, CAL_CSI2_VC_IRQSTATUS(i), vc_stat);
 652                        }
 653                }
 654        }
 655
 656        /* Check which DMA just finished */
 657        status = cal_read(cal, CAL_HL_IRQSTATUS(1));
 658        if (status) {
 659                unsigned int i;
 660
 661                /* Clear Interrupt status */
 662                cal_write(cal, CAL_HL_IRQSTATUS(1), status);
 663
 664                for (i = 0; i < cal->num_contexts; ++i) {
 665                        if (status & CAL_HL_IRQ_WDMA_END_MASK(i))
 666                                cal_irq_wdma_end(cal->ctx[i]);
 667                }
 668        }
 669
 670        /* Check which DMA just started */
 671        status = cal_read(cal, CAL_HL_IRQSTATUS(2));
 672        if (status) {
 673                unsigned int i;
 674
 675                /* Clear Interrupt status */
 676                cal_write(cal, CAL_HL_IRQSTATUS(2), status);
 677
 678                for (i = 0; i < cal->num_contexts; ++i) {
 679                        if (status & CAL_HL_IRQ_WDMA_START_MASK(i))
 680                                cal_irq_wdma_start(cal->ctx[i]);
 681                }
 682        }
 683
 684        return IRQ_HANDLED;
 685}
 686
 687/* ------------------------------------------------------------------
 688 *      Asynchronous V4L2 subdev binding
 689 * ------------------------------------------------------------------
 690 */
 691
 692struct cal_v4l2_async_subdev {
 693        struct v4l2_async_subdev asd; /* Must be first */
 694        struct cal_camerarx *phy;
 695};
 696
 697static inline struct cal_v4l2_async_subdev *
 698to_cal_asd(struct v4l2_async_subdev *asd)
 699{
 700        return container_of(asd, struct cal_v4l2_async_subdev, asd);
 701}
 702
 703static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
 704                                    struct v4l2_subdev *subdev,
 705                                    struct v4l2_async_subdev *asd)
 706{
 707        struct cal_camerarx *phy = to_cal_asd(asd)->phy;
 708        int pad;
 709        int ret;
 710
 711        if (phy->source) {
 712                phy_info(phy, "Rejecting subdev %s (Already set!!)",
 713                         subdev->name);
 714                return 0;
 715        }
 716
 717        phy->source = subdev;
 718        phy_dbg(1, phy, "Using source %s for capture\n", subdev->name);
 719
 720        pad = media_entity_get_fwnode_pad(&subdev->entity,
 721                                          of_fwnode_handle(phy->source_ep_node),
 722                                          MEDIA_PAD_FL_SOURCE);
 723        if (pad < 0) {
 724                phy_err(phy, "Source %s has no connected source pad\n",
 725                        subdev->name);
 726                return pad;
 727        }
 728
 729        ret = media_create_pad_link(&subdev->entity, pad,
 730                                    &phy->subdev.entity, CAL_CAMERARX_PAD_SINK,
 731                                    MEDIA_LNK_FL_IMMUTABLE |
 732                                    MEDIA_LNK_FL_ENABLED);
 733        if (ret) {
 734                phy_err(phy, "Failed to create media link for source %s\n",
 735                        subdev->name);
 736                return ret;
 737        }
 738
 739        return 0;
 740}
 741
 742static int cal_async_notifier_complete(struct v4l2_async_notifier *notifier)
 743{
 744        struct cal_dev *cal = container_of(notifier, struct cal_dev, notifier);
 745        unsigned int i;
 746        int ret;
 747
 748        for (i = 0; i < cal->num_contexts; ++i) {
 749                ret = cal_ctx_v4l2_register(cal->ctx[i]);
 750                if (ret)
 751                        goto err_ctx_unreg;
 752        }
 753
 754        if (!cal_mc_api)
 755                return 0;
 756
 757        ret = v4l2_device_register_subdev_nodes(&cal->v4l2_dev);
 758        if (ret)
 759                goto err_ctx_unreg;
 760
 761        return 0;
 762
 763err_ctx_unreg:
 764        for (; i > 0; --i) {
 765                if (!cal->ctx[i - 1])
 766                        continue;
 767
 768                cal_ctx_v4l2_unregister(cal->ctx[i - 1]);
 769        }
 770
 771        return ret;
 772}
 773
 774static const struct v4l2_async_notifier_operations cal_async_notifier_ops = {
 775        .bound = cal_async_notifier_bound,
 776        .complete = cal_async_notifier_complete,
 777};
 778
 779static int cal_async_notifier_register(struct cal_dev *cal)
 780{
 781        unsigned int i;
 782        int ret;
 783
 784        v4l2_async_notifier_init(&cal->notifier);
 785        cal->notifier.ops = &cal_async_notifier_ops;
 786
 787        for (i = 0; i < cal->data->num_csi2_phy; ++i) {
 788                struct cal_camerarx *phy = cal->phy[i];
 789                struct cal_v4l2_async_subdev *casd;
 790                struct fwnode_handle *fwnode;
 791
 792                if (!phy->source_node)
 793                        continue;
 794
 795                fwnode = of_fwnode_handle(phy->source_node);
 796                casd = v4l2_async_notifier_add_fwnode_subdev(&cal->notifier,
 797                                                             fwnode,
 798                                                             struct cal_v4l2_async_subdev);
 799                if (IS_ERR(casd)) {
 800                        phy_err(phy, "Failed to add subdev to notifier\n");
 801                        ret = PTR_ERR(casd);
 802                        goto error;
 803                }
 804
 805                casd->phy = phy;
 806        }
 807
 808        ret = v4l2_async_notifier_register(&cal->v4l2_dev, &cal->notifier);
 809        if (ret) {
 810                cal_err(cal, "Error registering async notifier\n");
 811                goto error;
 812        }
 813
 814        return 0;
 815
 816error:
 817        v4l2_async_notifier_cleanup(&cal->notifier);
 818        return ret;
 819}
 820
 821static void cal_async_notifier_unregister(struct cal_dev *cal)
 822{
 823        v4l2_async_notifier_unregister(&cal->notifier);
 824        v4l2_async_notifier_cleanup(&cal->notifier);
 825}
 826
 827/* ------------------------------------------------------------------
 828 *      Media and V4L2 device handling
 829 * ------------------------------------------------------------------
 830 */
 831
 832/*
 833 * Register user-facing devices. To be called at the end of the probe function
 834 * when all resources are initialized and ready.
 835 */
 836static int cal_media_register(struct cal_dev *cal)
 837{
 838        int ret;
 839
 840        ret = media_device_register(&cal->mdev);
 841        if (ret) {
 842                cal_err(cal, "Failed to register media device\n");
 843                return ret;
 844        }
 845
 846        /*
 847         * Register the async notifier. This may trigger registration of the
 848         * V4L2 video devices if all subdevs are ready.
 849         */
 850        ret = cal_async_notifier_register(cal);
 851        if (ret) {
 852                media_device_unregister(&cal->mdev);
 853                return ret;
 854        }
 855
 856        return 0;
 857}
 858
 859/*
 860 * Unregister the user-facing devices, but don't free memory yet. To be called
 861 * at the beginning of the remove function, to disallow access from userspace.
 862 */
 863static void cal_media_unregister(struct cal_dev *cal)
 864{
 865        unsigned int i;
 866
 867        /* Unregister all the V4L2 video devices. */
 868        for (i = 0; i < cal->num_contexts; i++)
 869                cal_ctx_v4l2_unregister(cal->ctx[i]);
 870
 871        cal_async_notifier_unregister(cal);
 872        media_device_unregister(&cal->mdev);
 873}
 874
 875/*
 876 * Initialize the in-kernel objects. To be called at the beginning of the probe
 877 * function, before the V4L2 device is used by the driver.
 878 */
 879static int cal_media_init(struct cal_dev *cal)
 880{
 881        struct media_device *mdev = &cal->mdev;
 882        int ret;
 883
 884        mdev->dev = cal->dev;
 885        mdev->hw_revision = cal->revision;
 886        strscpy(mdev->model, "CAL", sizeof(mdev->model));
 887        snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
 888                 dev_name(mdev->dev));
 889        media_device_init(mdev);
 890
 891        /*
 892         * Initialize the V4L2 device (despite the function name, this performs
 893         * initialization, not registration).
 894         */
 895        cal->v4l2_dev.mdev = mdev;
 896        ret = v4l2_device_register(cal->dev, &cal->v4l2_dev);
 897        if (ret) {
 898                cal_err(cal, "Failed to register V4L2 device\n");
 899                return ret;
 900        }
 901
 902        vb2_dma_contig_set_max_seg_size(cal->dev, DMA_BIT_MASK(32));
 903
 904        return 0;
 905}
 906
 907/*
 908 * Cleanup the in-kernel objects, freeing memory. To be called at the very end
 909 * of the remove sequence, when nothing (including userspace) can access the
 910 * objects anymore.
 911 */
 912static void cal_media_cleanup(struct cal_dev *cal)
 913{
 914        v4l2_device_unregister(&cal->v4l2_dev);
 915        media_device_cleanup(&cal->mdev);
 916
 917        vb2_dma_contig_clear_max_seg_size(cal->dev);
 918}
 919
 920/* ------------------------------------------------------------------
 921 *      Initialization and module stuff
 922 * ------------------------------------------------------------------
 923 */
 924
 925static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
 926{
 927        struct cal_ctx *ctx;
 928        int ret;
 929
 930        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 931        if (!ctx)
 932                return NULL;
 933
 934        ctx->cal = cal;
 935        ctx->phy = cal->phy[inst];
 936        ctx->dma_ctx = inst;
 937        ctx->csi2_ctx = inst;
 938        ctx->cport = inst;
 939        ctx->vc = 0;
 940        ctx->datatype = CAL_CSI2_CTX_DT_ANY;
 941
 942        ret = cal_ctx_v4l2_init(ctx);
 943        if (ret)
 944                return NULL;
 945
 946        return ctx;
 947}
 948
 949static void cal_ctx_destroy(struct cal_ctx *ctx)
 950{
 951        cal_ctx_v4l2_cleanup(ctx);
 952
 953        kfree(ctx);
 954}
 955
 956static const struct of_device_id cal_of_match[] = {
 957        {
 958                .compatible = "ti,dra72-cal",
 959                .data = (void *)&dra72x_cal_data,
 960        },
 961        {
 962                .compatible = "ti,dra72-pre-es2-cal",
 963                .data = (void *)&dra72x_es1_cal_data,
 964        },
 965        {
 966                .compatible = "ti,dra76-cal",
 967                .data = (void *)&dra76x_cal_data,
 968        },
 969        {
 970                .compatible = "ti,am654-cal",
 971                .data = (void *)&am654_cal_data,
 972        },
 973        {},
 974};
 975MODULE_DEVICE_TABLE(of, cal_of_match);
 976
 977/* Get hardware revision and info. */
 978
 979#define CAL_HL_HWINFO_VALUE             0xa3c90469
 980
 981static void cal_get_hwinfo(struct cal_dev *cal)
 982{
 983        u32 hwinfo;
 984
 985        cal->revision = cal_read(cal, CAL_HL_REVISION);
 986        switch (FIELD_GET(CAL_HL_REVISION_SCHEME_MASK, cal->revision)) {
 987        case CAL_HL_REVISION_SCHEME_H08:
 988                cal_dbg(3, cal, "CAL HW revision %lu.%lu.%lu (0x%08x)\n",
 989                        FIELD_GET(CAL_HL_REVISION_MAJOR_MASK, cal->revision),
 990                        FIELD_GET(CAL_HL_REVISION_MINOR_MASK, cal->revision),
 991                        FIELD_GET(CAL_HL_REVISION_RTL_MASK, cal->revision),
 992                        cal->revision);
 993                break;
 994
 995        case CAL_HL_REVISION_SCHEME_LEGACY:
 996        default:
 997                cal_info(cal, "Unexpected CAL HW revision 0x%08x\n",
 998                         cal->revision);
 999                break;
1000        }
1001
1002        hwinfo = cal_read(cal, CAL_HL_HWINFO);
1003        if (hwinfo != CAL_HL_HWINFO_VALUE)
1004                cal_info(cal, "CAL_HL_HWINFO = 0x%08x, expected 0x%08x\n",
1005                         hwinfo, CAL_HL_HWINFO_VALUE);
1006}
1007
1008static int cal_init_camerarx_regmap(struct cal_dev *cal)
1009{
1010        struct platform_device *pdev = to_platform_device(cal->dev);
1011        struct device_node *np = cal->dev->of_node;
1012        struct regmap_config config = { };
1013        struct regmap *syscon;
1014        struct resource *res;
1015        unsigned int offset;
1016        void __iomem *base;
1017
1018        syscon = syscon_regmap_lookup_by_phandle_args(np, "ti,camerrx-control",
1019                                                      1, &offset);
1020        if (!IS_ERR(syscon)) {
1021                cal->syscon_camerrx = syscon;
1022                cal->syscon_camerrx_offset = offset;
1023                return 0;
1024        }
1025
1026        dev_warn(cal->dev, "failed to get ti,camerrx-control: %ld\n",
1027                 PTR_ERR(syscon));
1028
1029        /*
1030         * Backward DTS compatibility. If syscon entry is not present then
1031         * check if the camerrx_control resource is present.
1032         */
1033        res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1034                                           "camerrx_control");
1035        base = devm_ioremap_resource(cal->dev, res);
1036        if (IS_ERR(base)) {
1037                cal_err(cal, "failed to ioremap camerrx_control\n");
1038                return PTR_ERR(base);
1039        }
1040
1041        cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
1042                res->name, &res->start, &res->end);
1043
1044        config.reg_bits = 32;
1045        config.reg_stride = 4;
1046        config.val_bits = 32;
1047        config.max_register = resource_size(res) - 4;
1048
1049        syscon = regmap_init_mmio(NULL, base, &config);
1050        if (IS_ERR(syscon)) {
1051                pr_err("regmap init failed\n");
1052                return PTR_ERR(syscon);
1053        }
1054
1055        /*
1056         * In this case the base already point to the direct CM register so no
1057         * need for an offset.
1058         */
1059        cal->syscon_camerrx = syscon;
1060        cal->syscon_camerrx_offset = 0;
1061
1062        return 0;
1063}
1064
1065static int cal_probe(struct platform_device *pdev)
1066{
1067        struct cal_dev *cal;
1068        bool connected = false;
1069        unsigned int i;
1070        int ret;
1071        int irq;
1072
1073        cal = devm_kzalloc(&pdev->dev, sizeof(*cal), GFP_KERNEL);
1074        if (!cal)
1075                return -ENOMEM;
1076
1077        cal->data = of_device_get_match_data(&pdev->dev);
1078        if (!cal->data) {
1079                dev_err(&pdev->dev, "Could not get feature data based on compatible version\n");
1080                return -ENODEV;
1081        }
1082
1083        cal->dev = &pdev->dev;
1084        platform_set_drvdata(pdev, cal);
1085
1086        /* Acquire resources: clocks, CAMERARX regmap, I/O memory and IRQ. */
1087        cal->fclk = devm_clk_get(&pdev->dev, "fck");
1088        if (IS_ERR(cal->fclk)) {
1089                dev_err(&pdev->dev, "cannot get CAL fclk\n");
1090                return PTR_ERR(cal->fclk);
1091        }
1092
1093        ret = cal_init_camerarx_regmap(cal);
1094        if (ret < 0)
1095                return ret;
1096
1097        cal->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1098                                                "cal_top");
1099        cal->base = devm_ioremap_resource(&pdev->dev, cal->res);
1100        if (IS_ERR(cal->base))
1101                return PTR_ERR(cal->base);
1102
1103        cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
1104                cal->res->name, &cal->res->start, &cal->res->end);
1105
1106        irq = platform_get_irq(pdev, 0);
1107        cal_dbg(1, cal, "got irq# %d\n", irq);
1108        ret = devm_request_irq(&pdev->dev, irq, cal_irq, 0, CAL_MODULE_NAME,
1109                               cal);
1110        if (ret)
1111                return ret;
1112
1113        /* Read the revision and hardware info to verify hardware access. */
1114        pm_runtime_enable(&pdev->dev);
1115        ret = pm_runtime_resume_and_get(&pdev->dev);
1116        if (ret)
1117                goto error_pm_runtime;
1118
1119        cal_get_hwinfo(cal);
1120        pm_runtime_put_sync(&pdev->dev);
1121
1122        /* Initialize the media device. */
1123        ret = cal_media_init(cal);
1124        if (ret < 0)
1125                goto error_pm_runtime;
1126
1127        /* Create CAMERARX PHYs. */
1128        for (i = 0; i < cal->data->num_csi2_phy; ++i) {
1129                cal->phy[i] = cal_camerarx_create(cal, i);
1130                if (IS_ERR(cal->phy[i])) {
1131                        ret = PTR_ERR(cal->phy[i]);
1132                        cal->phy[i] = NULL;
1133                        goto error_camerarx;
1134                }
1135
1136                if (cal->phy[i]->source_node)
1137                        connected = true;
1138        }
1139
1140        if (!connected) {
1141                cal_err(cal, "Neither port is configured, no point in staying up\n");
1142                ret = -ENODEV;
1143                goto error_camerarx;
1144        }
1145
1146        /* Create contexts. */
1147        for (i = 0; i < cal->data->num_csi2_phy; ++i) {
1148                if (!cal->phy[i]->source_node)
1149                        continue;
1150
1151                cal->ctx[cal->num_contexts] = cal_ctx_create(cal, i);
1152                if (!cal->ctx[cal->num_contexts]) {
1153                        cal_err(cal, "Failed to create context %u\n", cal->num_contexts);
1154                        ret = -ENODEV;
1155                        goto error_context;
1156                }
1157
1158                cal->num_contexts++;
1159        }
1160
1161        /* Register the media device. */
1162        ret = cal_media_register(cal);
1163        if (ret)
1164                goto error_context;
1165
1166        return 0;
1167
1168error_context:
1169        for (i = 0; i < cal->num_contexts; i++)
1170                cal_ctx_destroy(cal->ctx[i]);
1171
1172error_camerarx:
1173        for (i = 0; i < cal->data->num_csi2_phy; i++)
1174                cal_camerarx_destroy(cal->phy[i]);
1175
1176        cal_media_cleanup(cal);
1177
1178error_pm_runtime:
1179        pm_runtime_disable(&pdev->dev);
1180
1181        return ret;
1182}
1183
1184static int cal_remove(struct platform_device *pdev)
1185{
1186        struct cal_dev *cal = platform_get_drvdata(pdev);
1187        unsigned int i;
1188        int ret;
1189
1190        cal_dbg(1, cal, "Removing %s\n", CAL_MODULE_NAME);
1191
1192        ret = pm_runtime_resume_and_get(&pdev->dev);
1193
1194        cal_media_unregister(cal);
1195
1196        for (i = 0; i < cal->data->num_csi2_phy; i++)
1197                cal_camerarx_disable(cal->phy[i]);
1198
1199        for (i = 0; i < cal->num_contexts; i++)
1200                cal_ctx_destroy(cal->ctx[i]);
1201
1202        for (i = 0; i < cal->data->num_csi2_phy; i++)
1203                cal_camerarx_destroy(cal->phy[i]);
1204
1205        cal_media_cleanup(cal);
1206
1207        if (ret >= 0)
1208                pm_runtime_put_sync(&pdev->dev);
1209        pm_runtime_disable(&pdev->dev);
1210
1211        return 0;
1212}
1213
1214static int cal_runtime_resume(struct device *dev)
1215{
1216        struct cal_dev *cal = dev_get_drvdata(dev);
1217        unsigned int i;
1218        u32 val;
1219
1220        if (cal->data->flags & DRA72_CAL_PRE_ES2_LDO_DISABLE) {
1221                /*
1222                 * Apply errata on both port everytime we (re-)enable
1223                 * the clock
1224                 */
1225                for (i = 0; i < cal->data->num_csi2_phy; i++)
1226                        cal_camerarx_i913_errata(cal->phy[i]);
1227        }
1228
1229        /*
1230         * Enable global interrupts that are not related to a particular
1231         * CAMERARAX or context.
1232         */
1233        cal_write(cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
1234
1235        val = cal_read(cal, CAL_CTRL);
1236        cal_set_field(&val, CAL_CTRL_BURSTSIZE_BURST128,
1237                      CAL_CTRL_BURSTSIZE_MASK);
1238        cal_set_field(&val, 0xf, CAL_CTRL_TAGCNT_MASK);
1239        cal_set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED,
1240                      CAL_CTRL_POSTED_WRITES_MASK);
1241        cal_set_field(&val, 0xff, CAL_CTRL_MFLAGL_MASK);
1242        cal_set_field(&val, 0xff, CAL_CTRL_MFLAGH_MASK);
1243        cal_write(cal, CAL_CTRL, val);
1244        cal_dbg(3, cal, "CAL_CTRL = 0x%08x\n", cal_read(cal, CAL_CTRL));
1245
1246        return 0;
1247}
1248
1249static const struct dev_pm_ops cal_pm_ops = {
1250        .runtime_resume = cal_runtime_resume,
1251};
1252
1253static struct platform_driver cal_pdrv = {
1254        .probe          = cal_probe,
1255        .remove         = cal_remove,
1256        .driver         = {
1257                .name   = CAL_MODULE_NAME,
1258                .pm     = &cal_pm_ops,
1259                .of_match_table = cal_of_match,
1260        },
1261};
1262
1263module_platform_driver(cal_pdrv);
1264