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
 293static void cal_ctx_csi2_config(struct cal_ctx *ctx)
 294{
 295        u32 val;
 296
 297        val = cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index));
 298        cal_set_field(&val, ctx->cport, CAL_CSI2_CTX_CPORT_MASK);
 299        /*
 300         * DT type: MIPI CSI-2 Specs
 301         *   0x1: All - DT filter is disabled
 302         *  0x24: RGB888 1 pixel  = 3 bytes
 303         *  0x2B: RAW10  4 pixels = 5 bytes
 304         *  0x2A: RAW8   1 pixel  = 1 byte
 305         *  0x1E: YUV422 2 pixels = 4 bytes
 306         */
 307        cal_set_field(&val, 0x1, CAL_CSI2_CTX_DT_MASK);
 308        cal_set_field(&val, 0, CAL_CSI2_CTX_VC_MASK);
 309        cal_set_field(&val, ctx->v_fmt.fmt.pix.height, CAL_CSI2_CTX_LINES_MASK);
 310        cal_set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK);
 311        cal_set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE,
 312                      CAL_CSI2_CTX_PACK_MODE_MASK);
 313        cal_write(ctx->cal, CAL_CSI2_CTX0(ctx->index), val);
 314        ctx_dbg(3, ctx, "CAL_CSI2_CTX0(%d) = 0x%08x\n", ctx->index,
 315                cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index)));
 316}
 317
 318static void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
 319{
 320        u32 val, extract, pack;
 321
 322        switch (ctx->fmtinfo->bpp) {
 323        case 8:
 324                extract = CAL_PIX_PROC_EXTRACT_B8;
 325                pack = CAL_PIX_PROC_PACK_B8;
 326                break;
 327        case 10:
 328                extract = CAL_PIX_PROC_EXTRACT_B10_MIPI;
 329                pack = CAL_PIX_PROC_PACK_B16;
 330                break;
 331        case 12:
 332                extract = CAL_PIX_PROC_EXTRACT_B12_MIPI;
 333                pack = CAL_PIX_PROC_PACK_B16;
 334                break;
 335        case 16:
 336                extract = CAL_PIX_PROC_EXTRACT_B16_LE;
 337                pack = CAL_PIX_PROC_PACK_B16;
 338                break;
 339        default:
 340                /*
 341                 * If you see this warning then it means that you added
 342                 * some new entry in the cal_formats[] array with a different
 343                 * bit per pixel values then the one supported below.
 344                 * Either add support for the new bpp value below or adjust
 345                 * the new entry to use one of the value below.
 346                 *
 347                 * Instead of failing here just use 8 bpp as a default.
 348                 */
 349                dev_warn_once(ctx->cal->dev,
 350                              "%s:%d:%s: bpp:%d unsupported! Overwritten with 8.\n",
 351                              __FILE__, __LINE__, __func__, ctx->fmtinfo->bpp);
 352                extract = CAL_PIX_PROC_EXTRACT_B8;
 353                pack = CAL_PIX_PROC_PACK_B8;
 354                break;
 355        }
 356
 357        val = cal_read(ctx->cal, CAL_PIX_PROC(ctx->index));
 358        cal_set_field(&val, extract, CAL_PIX_PROC_EXTRACT_MASK);
 359        cal_set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK);
 360        cal_set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK);
 361        cal_set_field(&val, pack, CAL_PIX_PROC_PACK_MASK);
 362        cal_set_field(&val, ctx->cport, CAL_PIX_PROC_CPORT_MASK);
 363        cal_set_field(&val, 1, CAL_PIX_PROC_EN_MASK);
 364        cal_write(ctx->cal, CAL_PIX_PROC(ctx->index), val);
 365        ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->index,
 366                cal_read(ctx->cal, CAL_PIX_PROC(ctx->index)));
 367}
 368
 369static void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
 370{
 371        unsigned int stride = ctx->v_fmt.fmt.pix.bytesperline;
 372        u32 val;
 373
 374        val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
 375        cal_set_field(&val, ctx->cport, CAL_WR_DMA_CTRL_CPORT_MASK);
 376        cal_set_field(&val, ctx->v_fmt.fmt.pix.height,
 377                      CAL_WR_DMA_CTRL_YSIZE_MASK);
 378        cal_set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT,
 379                      CAL_WR_DMA_CTRL_DTAG_MASK);
 380        cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST,
 381                      CAL_WR_DMA_CTRL_MODE_MASK);
 382        cal_set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR,
 383                      CAL_WR_DMA_CTRL_PATTERN_MASK);
 384        cal_set_field(&val, 1, CAL_WR_DMA_CTRL_STALL_RD_MASK);
 385        cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val);
 386        ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->index,
 387                cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index)));
 388
 389        cal_write_field(ctx->cal, CAL_WR_DMA_OFST(ctx->index),
 390                        stride / 16, CAL_WR_DMA_OFST_MASK);
 391        ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->index,
 392                cal_read(ctx->cal, CAL_WR_DMA_OFST(ctx->index)));
 393
 394        val = cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index));
 395        /* 64 bit word means no skipping */
 396        cal_set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK);
 397        /*
 398         * The XSIZE field is expressed in 64-bit units and prevents overflows
 399         * in case of synchronization issues by limiting the number of bytes
 400         * written per line.
 401         */
 402        cal_set_field(&val, stride / 8, CAL_WR_DMA_XSIZE_MASK);
 403        cal_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index), val);
 404        ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->index,
 405                cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index)));
 406
 407        val = cal_read(ctx->cal, CAL_CTRL);
 408        cal_set_field(&val, CAL_CTRL_BURSTSIZE_BURST128,
 409                      CAL_CTRL_BURSTSIZE_MASK);
 410        cal_set_field(&val, 0xF, CAL_CTRL_TAGCNT_MASK);
 411        cal_set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED,
 412                      CAL_CTRL_POSTED_WRITES_MASK);
 413        cal_set_field(&val, 0xFF, CAL_CTRL_MFLAGL_MASK);
 414        cal_set_field(&val, 0xFF, CAL_CTRL_MFLAGH_MASK);
 415        cal_write(ctx->cal, CAL_CTRL, val);
 416        ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", cal_read(ctx->cal, CAL_CTRL));
 417}
 418
 419void cal_ctx_set_dma_addr(struct cal_ctx *ctx, dma_addr_t addr)
 420{
 421        cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->index), addr);
 422}
 423
 424static void cal_ctx_wr_dma_disable(struct cal_ctx *ctx)
 425{
 426        u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
 427
 428        cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_DIS,
 429                      CAL_WR_DMA_CTRL_MODE_MASK);
 430        cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val);
 431}
 432
 433static bool cal_ctx_wr_dma_stopped(struct cal_ctx *ctx)
 434{
 435        bool stopped;
 436
 437        spin_lock_irq(&ctx->dma.lock);
 438        stopped = ctx->dma.state == CAL_DMA_STOPPED;
 439        spin_unlock_irq(&ctx->dma.lock);
 440
 441        return stopped;
 442}
 443
 444void cal_ctx_start(struct cal_ctx *ctx)
 445{
 446        ctx->sequence = 0;
 447        ctx->dma.state = CAL_DMA_RUNNING;
 448
 449        /* Configure the CSI-2, pixel processing and write DMA contexts. */
 450        cal_ctx_csi2_config(ctx);
 451        cal_ctx_pix_proc_config(ctx);
 452        cal_ctx_wr_dma_config(ctx);
 453
 454        /* Enable IRQ_WDMA_END and IRQ_WDMA_START. */
 455        cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(1),
 456                  CAL_HL_IRQ_MASK(ctx->index));
 457        cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(2),
 458                  CAL_HL_IRQ_MASK(ctx->index));
 459}
 460
 461void cal_ctx_stop(struct cal_ctx *ctx)
 462{
 463        long timeout;
 464
 465        /*
 466         * Request DMA stop and wait until it completes. If completion times
 467         * out, forcefully disable the DMA.
 468         */
 469        spin_lock_irq(&ctx->dma.lock);
 470        ctx->dma.state = CAL_DMA_STOP_REQUESTED;
 471        spin_unlock_irq(&ctx->dma.lock);
 472
 473        timeout = wait_event_timeout(ctx->dma.wait, cal_ctx_wr_dma_stopped(ctx),
 474                                     msecs_to_jiffies(500));
 475        if (!timeout) {
 476                ctx_err(ctx, "failed to disable dma cleanly\n");
 477                cal_ctx_wr_dma_disable(ctx);
 478        }
 479
 480        /* Disable IRQ_WDMA_END and IRQ_WDMA_START. */
 481        cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(1),
 482                  CAL_HL_IRQ_MASK(ctx->index));
 483        cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(2),
 484                  CAL_HL_IRQ_MASK(ctx->index));
 485
 486        ctx->dma.state = CAL_DMA_STOPPED;
 487}
 488
 489/* ------------------------------------------------------------------
 490 *      IRQ Handling
 491 * ------------------------------------------------------------------
 492 */
 493
 494static inline void cal_irq_wdma_start(struct cal_ctx *ctx)
 495{
 496        spin_lock(&ctx->dma.lock);
 497
 498        if (ctx->dma.state == CAL_DMA_STOP_REQUESTED) {
 499                /*
 500                 * If a stop is requested, disable the write DMA context
 501                 * immediately. The CAL_WR_DMA_CTRL_j.MODE field is shadowed,
 502                 * the current frame will complete and the DMA will then stop.
 503                 */
 504                cal_ctx_wr_dma_disable(ctx);
 505                ctx->dma.state = CAL_DMA_STOP_PENDING;
 506        } else if (!list_empty(&ctx->dma.queue) && !ctx->dma.pending) {
 507                /*
 508                 * Otherwise, if a new buffer is available, queue it to the
 509                 * hardware.
 510                 */
 511                struct cal_buffer *buf;
 512                dma_addr_t addr;
 513
 514                buf = list_first_entry(&ctx->dma.queue, struct cal_buffer,
 515                                       list);
 516                addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
 517                cal_ctx_set_dma_addr(ctx, addr);
 518
 519                ctx->dma.pending = buf;
 520                list_del(&buf->list);
 521        }
 522
 523        spin_unlock(&ctx->dma.lock);
 524}
 525
 526static inline void cal_irq_wdma_end(struct cal_ctx *ctx)
 527{
 528        struct cal_buffer *buf = NULL;
 529
 530        spin_lock(&ctx->dma.lock);
 531
 532        /* If the DMA context was stopping, it is now stopped. */
 533        if (ctx->dma.state == CAL_DMA_STOP_PENDING) {
 534                ctx->dma.state = CAL_DMA_STOPPED;
 535                wake_up(&ctx->dma.wait);
 536        }
 537
 538        /* If a new buffer was queued, complete the current buffer. */
 539        if (ctx->dma.pending) {
 540                buf = ctx->dma.active;
 541                ctx->dma.active = ctx->dma.pending;
 542                ctx->dma.pending = NULL;
 543        }
 544
 545        spin_unlock(&ctx->dma.lock);
 546
 547        if (buf) {
 548                buf->vb.vb2_buf.timestamp = ktime_get_ns();
 549                buf->vb.field = ctx->v_fmt.fmt.pix.field;
 550                buf->vb.sequence = ctx->sequence++;
 551                vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 552        }
 553}
 554
 555static irqreturn_t cal_irq(int irq_cal, void *data)
 556{
 557        struct cal_dev *cal = data;
 558        u32 status;
 559
 560        status = cal_read(cal, CAL_HL_IRQSTATUS(0));
 561        if (status) {
 562                unsigned int i;
 563
 564                cal_write(cal, CAL_HL_IRQSTATUS(0), status);
 565
 566                if (status & CAL_HL_IRQ_OCPO_ERR_MASK)
 567                        dev_err_ratelimited(cal->dev, "OCPO ERROR\n");
 568
 569                for (i = 0; i < cal->data->num_csi2_phy; ++i) {
 570                        if (status & CAL_HL_IRQ_CIO_MASK(i)) {
 571                                u32 cio_stat = cal_read(cal,
 572                                                        CAL_CSI2_COMPLEXIO_IRQSTATUS(i));
 573
 574                                dev_err_ratelimited(cal->dev,
 575                                                    "CIO%u error: %#08x\n", i, cio_stat);
 576
 577                                cal_write(cal, CAL_CSI2_COMPLEXIO_IRQSTATUS(i),
 578                                          cio_stat);
 579                        }
 580                }
 581        }
 582
 583        /* Check which DMA just finished */
 584        status = cal_read(cal, CAL_HL_IRQSTATUS(1));
 585        if (status) {
 586                unsigned int i;
 587
 588                /* Clear Interrupt status */
 589                cal_write(cal, CAL_HL_IRQSTATUS(1), status);
 590
 591                for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
 592                        if (status & CAL_HL_IRQ_MASK(i))
 593                                cal_irq_wdma_end(cal->ctx[i]);
 594                }
 595        }
 596
 597        /* Check which DMA just started */
 598        status = cal_read(cal, CAL_HL_IRQSTATUS(2));
 599        if (status) {
 600                unsigned int i;
 601
 602                /* Clear Interrupt status */
 603                cal_write(cal, CAL_HL_IRQSTATUS(2), status);
 604
 605                for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
 606                        if (status & CAL_HL_IRQ_MASK(i))
 607                                cal_irq_wdma_start(cal->ctx[i]);
 608                }
 609        }
 610
 611        return IRQ_HANDLED;
 612}
 613
 614/* ------------------------------------------------------------------
 615 *      Asynchronous V4L2 subdev binding
 616 * ------------------------------------------------------------------
 617 */
 618
 619struct cal_v4l2_async_subdev {
 620        struct v4l2_async_subdev asd; /* Must be first */
 621        struct cal_camerarx *phy;
 622};
 623
 624static inline struct cal_v4l2_async_subdev *
 625to_cal_asd(struct v4l2_async_subdev *asd)
 626{
 627        return container_of(asd, struct cal_v4l2_async_subdev, asd);
 628}
 629
 630static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
 631                                    struct v4l2_subdev *subdev,
 632                                    struct v4l2_async_subdev *asd)
 633{
 634        struct cal_camerarx *phy = to_cal_asd(asd)->phy;
 635        int pad;
 636        int ret;
 637
 638        if (phy->sensor) {
 639                phy_info(phy, "Rejecting subdev %s (Already set!!)",
 640                         subdev->name);
 641                return 0;
 642        }
 643
 644        phy->sensor = subdev;
 645        phy_dbg(1, phy, "Using sensor %s for capture\n", subdev->name);
 646
 647        pad = media_entity_get_fwnode_pad(&subdev->entity,
 648                                          of_fwnode_handle(phy->sensor_ep_node),
 649                                          MEDIA_PAD_FL_SOURCE);
 650        if (pad < 0) {
 651                phy_err(phy, "Sensor %s has no connected source pad\n",
 652                        subdev->name);
 653                return pad;
 654        }
 655
 656        ret = media_create_pad_link(&subdev->entity, pad,
 657                                    &phy->subdev.entity, CAL_CAMERARX_PAD_SINK,
 658                                    MEDIA_LNK_FL_IMMUTABLE |
 659                                    MEDIA_LNK_FL_ENABLED);
 660        if (ret) {
 661                phy_err(phy, "Failed to create media link for sensor %s\n",
 662                        subdev->name);
 663                return ret;
 664        }
 665
 666        return 0;
 667}
 668
 669static int cal_async_notifier_complete(struct v4l2_async_notifier *notifier)
 670{
 671        struct cal_dev *cal = container_of(notifier, struct cal_dev, notifier);
 672        unsigned int i;
 673        int ret = 0;
 674
 675        for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
 676                if (cal->ctx[i])
 677                        cal_ctx_v4l2_register(cal->ctx[i]);
 678        }
 679
 680        if (cal_mc_api)
 681                ret = v4l2_device_register_subdev_nodes(&cal->v4l2_dev);
 682
 683        return ret;
 684}
 685
 686static const struct v4l2_async_notifier_operations cal_async_notifier_ops = {
 687        .bound = cal_async_notifier_bound,
 688        .complete = cal_async_notifier_complete,
 689};
 690
 691static int cal_async_notifier_register(struct cal_dev *cal)
 692{
 693        unsigned int i;
 694        int ret;
 695
 696        v4l2_async_notifier_init(&cal->notifier);
 697        cal->notifier.ops = &cal_async_notifier_ops;
 698
 699        for (i = 0; i < cal->data->num_csi2_phy; ++i) {
 700                struct cal_camerarx *phy = cal->phy[i];
 701                struct cal_v4l2_async_subdev *casd;
 702                struct fwnode_handle *fwnode;
 703
 704                if (!phy->sensor_node)
 705                        continue;
 706
 707                fwnode = of_fwnode_handle(phy->sensor_node);
 708                casd = v4l2_async_notifier_add_fwnode_subdev(&cal->notifier,
 709                                                             fwnode,
 710                                                             struct cal_v4l2_async_subdev);
 711                if (IS_ERR(casd)) {
 712                        phy_err(phy, "Failed to add subdev to notifier\n");
 713                        ret = PTR_ERR(casd);
 714                        goto error;
 715                }
 716
 717                casd->phy = phy;
 718        }
 719
 720        ret = v4l2_async_notifier_register(&cal->v4l2_dev, &cal->notifier);
 721        if (ret) {
 722                cal_err(cal, "Error registering async notifier\n");
 723                goto error;
 724        }
 725
 726        return 0;
 727
 728error:
 729        v4l2_async_notifier_cleanup(&cal->notifier);
 730        return ret;
 731}
 732
 733static void cal_async_notifier_unregister(struct cal_dev *cal)
 734{
 735        v4l2_async_notifier_unregister(&cal->notifier);
 736        v4l2_async_notifier_cleanup(&cal->notifier);
 737}
 738
 739/* ------------------------------------------------------------------
 740 *      Media and V4L2 device handling
 741 * ------------------------------------------------------------------
 742 */
 743
 744/*
 745 * Register user-facing devices. To be called at the end of the probe function
 746 * when all resources are initialized and ready.
 747 */
 748static int cal_media_register(struct cal_dev *cal)
 749{
 750        int ret;
 751
 752        ret = media_device_register(&cal->mdev);
 753        if (ret) {
 754                cal_err(cal, "Failed to register media device\n");
 755                return ret;
 756        }
 757
 758        /*
 759         * Register the async notifier. This may trigger registration of the
 760         * V4L2 video devices if all subdevs are ready.
 761         */
 762        ret = cal_async_notifier_register(cal);
 763        if (ret) {
 764                media_device_unregister(&cal->mdev);
 765                return ret;
 766        }
 767
 768        return 0;
 769}
 770
 771/*
 772 * Unregister the user-facing devices, but don't free memory yet. To be called
 773 * at the beginning of the remove function, to disallow access from userspace.
 774 */
 775static void cal_media_unregister(struct cal_dev *cal)
 776{
 777        unsigned int i;
 778
 779        /* Unregister all the V4L2 video devices. */
 780        for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
 781                if (cal->ctx[i])
 782                        cal_ctx_v4l2_unregister(cal->ctx[i]);
 783        }
 784
 785        cal_async_notifier_unregister(cal);
 786        media_device_unregister(&cal->mdev);
 787}
 788
 789/*
 790 * Initialize the in-kernel objects. To be called at the beginning of the probe
 791 * function, before the V4L2 device is used by the driver.
 792 */
 793static int cal_media_init(struct cal_dev *cal)
 794{
 795        struct media_device *mdev = &cal->mdev;
 796        int ret;
 797
 798        mdev->dev = cal->dev;
 799        mdev->hw_revision = cal->revision;
 800        strscpy(mdev->model, "CAL", sizeof(mdev->model));
 801        snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
 802                 dev_name(mdev->dev));
 803        media_device_init(mdev);
 804
 805        /*
 806         * Initialize the V4L2 device (despite the function name, this performs
 807         * initialization, not registration).
 808         */
 809        cal->v4l2_dev.mdev = mdev;
 810        ret = v4l2_device_register(cal->dev, &cal->v4l2_dev);
 811        if (ret) {
 812                cal_err(cal, "Failed to register V4L2 device\n");
 813                return ret;
 814        }
 815
 816        vb2_dma_contig_set_max_seg_size(cal->dev, DMA_BIT_MASK(32));
 817
 818        return 0;
 819}
 820
 821/*
 822 * Cleanup the in-kernel objects, freeing memory. To be called at the very end
 823 * of the remove sequence, when nothing (including userspace) can access the
 824 * objects anymore.
 825 */
 826static void cal_media_cleanup(struct cal_dev *cal)
 827{
 828        unsigned int i;
 829
 830        for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
 831                if (cal->ctx[i])
 832                        cal_ctx_v4l2_cleanup(cal->ctx[i]);
 833        }
 834
 835        v4l2_device_unregister(&cal->v4l2_dev);
 836        media_device_cleanup(&cal->mdev);
 837
 838        vb2_dma_contig_clear_max_seg_size(cal->dev);
 839}
 840
 841/* ------------------------------------------------------------------
 842 *      Initialization and module stuff
 843 * ------------------------------------------------------------------
 844 */
 845
 846static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
 847{
 848        struct cal_ctx *ctx;
 849        int ret;
 850
 851        ctx = devm_kzalloc(cal->dev, sizeof(*ctx), GFP_KERNEL);
 852        if (!ctx)
 853                return NULL;
 854
 855        ctx->cal = cal;
 856        ctx->phy = cal->phy[inst];
 857        ctx->index = inst;
 858        ctx->cport = inst;
 859
 860        ret = cal_ctx_v4l2_init(ctx);
 861        if (ret)
 862                return NULL;
 863
 864        return ctx;
 865}
 866
 867static const struct of_device_id cal_of_match[] = {
 868        {
 869                .compatible = "ti,dra72-cal",
 870                .data = (void *)&dra72x_cal_data,
 871        },
 872        {
 873                .compatible = "ti,dra72-pre-es2-cal",
 874                .data = (void *)&dra72x_es1_cal_data,
 875        },
 876        {
 877                .compatible = "ti,dra76-cal",
 878                .data = (void *)&dra76x_cal_data,
 879        },
 880        {
 881                .compatible = "ti,am654-cal",
 882                .data = (void *)&am654_cal_data,
 883        },
 884        {},
 885};
 886MODULE_DEVICE_TABLE(of, cal_of_match);
 887
 888/* Get hardware revision and info. */
 889
 890#define CAL_HL_HWINFO_VALUE             0xa3c90469
 891
 892static void cal_get_hwinfo(struct cal_dev *cal)
 893{
 894        u32 hwinfo;
 895
 896        cal->revision = cal_read(cal, CAL_HL_REVISION);
 897        switch (FIELD_GET(CAL_HL_REVISION_SCHEME_MASK, cal->revision)) {
 898        case CAL_HL_REVISION_SCHEME_H08:
 899                cal_dbg(3, cal, "CAL HW revision %lu.%lu.%lu (0x%08x)\n",
 900                        FIELD_GET(CAL_HL_REVISION_MAJOR_MASK, cal->revision),
 901                        FIELD_GET(CAL_HL_REVISION_MINOR_MASK, cal->revision),
 902                        FIELD_GET(CAL_HL_REVISION_RTL_MASK, cal->revision),
 903                        cal->revision);
 904                break;
 905
 906        case CAL_HL_REVISION_SCHEME_LEGACY:
 907        default:
 908                cal_info(cal, "Unexpected CAL HW revision 0x%08x\n",
 909                         cal->revision);
 910                break;
 911        }
 912
 913        hwinfo = cal_read(cal, CAL_HL_HWINFO);
 914        if (hwinfo != CAL_HL_HWINFO_VALUE)
 915                cal_info(cal, "CAL_HL_HWINFO = 0x%08x, expected 0x%08x\n",
 916                         hwinfo, CAL_HL_HWINFO_VALUE);
 917}
 918
 919static int cal_init_camerarx_regmap(struct cal_dev *cal)
 920{
 921        struct platform_device *pdev = to_platform_device(cal->dev);
 922        struct device_node *np = cal->dev->of_node;
 923        struct regmap_config config = { };
 924        struct regmap *syscon;
 925        struct resource *res;
 926        unsigned int offset;
 927        void __iomem *base;
 928
 929        syscon = syscon_regmap_lookup_by_phandle_args(np, "ti,camerrx-control",
 930                                                      1, &offset);
 931        if (!IS_ERR(syscon)) {
 932                cal->syscon_camerrx = syscon;
 933                cal->syscon_camerrx_offset = offset;
 934                return 0;
 935        }
 936
 937        dev_warn(cal->dev, "failed to get ti,camerrx-control: %ld\n",
 938                 PTR_ERR(syscon));
 939
 940        /*
 941         * Backward DTS compatibility. If syscon entry is not present then
 942         * check if the camerrx_control resource is present.
 943         */
 944        res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 945                                           "camerrx_control");
 946        base = devm_ioremap_resource(cal->dev, res);
 947        if (IS_ERR(base)) {
 948                cal_err(cal, "failed to ioremap camerrx_control\n");
 949                return PTR_ERR(base);
 950        }
 951
 952        cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
 953                res->name, &res->start, &res->end);
 954
 955        config.reg_bits = 32;
 956        config.reg_stride = 4;
 957        config.val_bits = 32;
 958        config.max_register = resource_size(res) - 4;
 959
 960        syscon = regmap_init_mmio(NULL, base, &config);
 961        if (IS_ERR(syscon)) {
 962                pr_err("regmap init failed\n");
 963                return PTR_ERR(syscon);
 964        }
 965
 966        /*
 967         * In this case the base already point to the direct CM register so no
 968         * need for an offset.
 969         */
 970        cal->syscon_camerrx = syscon;
 971        cal->syscon_camerrx_offset = 0;
 972
 973        return 0;
 974}
 975
 976static int cal_probe(struct platform_device *pdev)
 977{
 978        struct cal_dev *cal;
 979        struct cal_ctx *ctx;
 980        bool connected = false;
 981        unsigned int i;
 982        int ret;
 983        int irq;
 984
 985        cal = devm_kzalloc(&pdev->dev, sizeof(*cal), GFP_KERNEL);
 986        if (!cal)
 987                return -ENOMEM;
 988
 989        cal->data = of_device_get_match_data(&pdev->dev);
 990        if (!cal->data) {
 991                dev_err(&pdev->dev, "Could not get feature data based on compatible version\n");
 992                return -ENODEV;
 993        }
 994
 995        cal->dev = &pdev->dev;
 996        platform_set_drvdata(pdev, cal);
 997
 998        /* Acquire resources: clocks, CAMERARX regmap, I/O memory and IRQ. */
 999        cal->fclk = devm_clk_get(&pdev->dev, "fck");
1000        if (IS_ERR(cal->fclk)) {
1001                dev_err(&pdev->dev, "cannot get CAL fclk\n");
1002                return PTR_ERR(cal->fclk);
1003        }
1004
1005        ret = cal_init_camerarx_regmap(cal);
1006        if (ret < 0)
1007                return ret;
1008
1009        cal->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1010                                                "cal_top");
1011        cal->base = devm_ioremap_resource(&pdev->dev, cal->res);
1012        if (IS_ERR(cal->base))
1013                return PTR_ERR(cal->base);
1014
1015        cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
1016                cal->res->name, &cal->res->start, &cal->res->end);
1017
1018        irq = platform_get_irq(pdev, 0);
1019        cal_dbg(1, cal, "got irq# %d\n", irq);
1020        ret = devm_request_irq(&pdev->dev, irq, cal_irq, 0, CAL_MODULE_NAME,
1021                               cal);
1022        if (ret)
1023                return ret;
1024
1025        /* Read the revision and hardware info to verify hardware access. */
1026        pm_runtime_enable(&pdev->dev);
1027        ret = pm_runtime_resume_and_get(&pdev->dev);
1028        if (ret)
1029                goto error_pm_runtime;
1030
1031        cal_get_hwinfo(cal);
1032        pm_runtime_put_sync(&pdev->dev);
1033
1034        /* Initialize the media device. */
1035        ret = cal_media_init(cal);
1036        if (ret < 0)
1037                goto error_pm_runtime;
1038
1039        /* Create CAMERARX PHYs. */
1040        for (i = 0; i < cal->data->num_csi2_phy; ++i) {
1041                cal->phy[i] = cal_camerarx_create(cal, i);
1042                if (IS_ERR(cal->phy[i])) {
1043                        ret = PTR_ERR(cal->phy[i]);
1044                        cal->phy[i] = NULL;
1045                        goto error_camerarx;
1046                }
1047
1048                if (cal->phy[i]->sensor_node)
1049                        connected = true;
1050        }
1051
1052        if (!connected) {
1053                cal_err(cal, "Neither port is configured, no point in staying up\n");
1054                ret = -ENODEV;
1055                goto error_camerarx;
1056        }
1057
1058        /* Create contexts. */
1059        for (i = 0; i < cal->data->num_csi2_phy; ++i) {
1060                if (!cal->phy[i]->sensor_node)
1061                        continue;
1062
1063                cal->ctx[i] = cal_ctx_create(cal, i);
1064                if (!cal->ctx[i]) {
1065                        cal_err(cal, "Failed to create context %u\n", i);
1066                        ret = -ENODEV;
1067                        goto error_context;
1068                }
1069        }
1070
1071        /* Register the media device. */
1072        ret = cal_media_register(cal);
1073        if (ret)
1074                goto error_context;
1075
1076        return 0;
1077
1078error_context:
1079        for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
1080                ctx = cal->ctx[i];
1081                if (ctx)
1082                        cal_ctx_v4l2_cleanup(ctx);
1083        }
1084
1085error_camerarx:
1086        for (i = 0; i < cal->data->num_csi2_phy; i++)
1087                cal_camerarx_destroy(cal->phy[i]);
1088
1089        cal_media_cleanup(cal);
1090
1091error_pm_runtime:
1092        pm_runtime_disable(&pdev->dev);
1093
1094        return ret;
1095}
1096
1097static int cal_remove(struct platform_device *pdev)
1098{
1099        struct cal_dev *cal = platform_get_drvdata(pdev);
1100        unsigned int i;
1101        int ret;
1102
1103        cal_dbg(1, cal, "Removing %s\n", CAL_MODULE_NAME);
1104
1105        ret = pm_runtime_resume_and_get(&pdev->dev);
1106
1107        cal_media_unregister(cal);
1108
1109        for (i = 0; i < ARRAY_SIZE(cal->phy); i++) {
1110                if (cal->phy[i])
1111                        cal_camerarx_disable(cal->phy[i]);
1112        }
1113
1114        cal_media_cleanup(cal);
1115
1116        for (i = 0; i < cal->data->num_csi2_phy; i++)
1117                cal_camerarx_destroy(cal->phy[i]);
1118
1119        if (ret >= 0)
1120                pm_runtime_put_sync(&pdev->dev);
1121        pm_runtime_disable(&pdev->dev);
1122
1123        return 0;
1124}
1125
1126static int cal_runtime_resume(struct device *dev)
1127{
1128        struct cal_dev *cal = dev_get_drvdata(dev);
1129        unsigned int i;
1130
1131        if (cal->data->flags & DRA72_CAL_PRE_ES2_LDO_DISABLE) {
1132                /*
1133                 * Apply errata on both port everytime we (re-)enable
1134                 * the clock
1135                 */
1136                for (i = 0; i < cal->data->num_csi2_phy; i++)
1137                        cal_camerarx_i913_errata(cal->phy[i]);
1138        }
1139
1140        /*
1141         * Enable global interrupts that are not related to a particular
1142         * CAMERARAX or context.
1143         */
1144        cal_write(cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
1145
1146        return 0;
1147}
1148
1149static const struct dev_pm_ops cal_pm_ops = {
1150        .runtime_resume = cal_runtime_resume,
1151};
1152
1153static struct platform_driver cal_pdrv = {
1154        .probe          = cal_probe,
1155        .remove         = cal_remove,
1156        .driver         = {
1157                .name   = CAL_MODULE_NAME,
1158                .pm     = &cal_pm_ops,
1159                .of_match_table = cal_of_match,
1160        },
1161};
1162
1163module_platform_driver(cal_pdrv);
1164