linux/drivers/media/video/omap3isp/ispccdc.c
<<
>>
Prefs
   1/*
   2 * ispccdc.c
   3 *
   4 * TI OMAP3 ISP - CCDC module
   5 *
   6 * Copyright (C) 2009-2010 Nokia Corporation
   7 * Copyright (C) 2009 Texas Instruments, Inc.
   8 *
   9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  10 *           Sakari Ailus <sakari.ailus@iki.fi>
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License version 2 as
  14 * published by the Free Software Foundation.
  15 *
  16 * This program is distributed in the hope that it will be useful, but
  17 * WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  19 * General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  24 * 02110-1301 USA
  25 */
  26
  27#include <linux/module.h>
  28#include <linux/uaccess.h>
  29#include <linux/delay.h>
  30#include <linux/device.h>
  31#include <linux/dma-mapping.h>
  32#include <linux/mm.h>
  33#include <linux/sched.h>
  34#include <media/v4l2-event.h>
  35
  36#include "isp.h"
  37#include "ispreg.h"
  38#include "ispccdc.h"
  39
  40static struct v4l2_mbus_framefmt *
  41__ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
  42                  unsigned int pad, enum v4l2_subdev_format_whence which);
  43
  44static const unsigned int ccdc_fmts[] = {
  45        V4L2_MBUS_FMT_Y8_1X8,
  46        V4L2_MBUS_FMT_Y10_1X10,
  47        V4L2_MBUS_FMT_Y12_1X12,
  48        V4L2_MBUS_FMT_SGRBG8_1X8,
  49        V4L2_MBUS_FMT_SRGGB8_1X8,
  50        V4L2_MBUS_FMT_SBGGR8_1X8,
  51        V4L2_MBUS_FMT_SGBRG8_1X8,
  52        V4L2_MBUS_FMT_SGRBG10_1X10,
  53        V4L2_MBUS_FMT_SRGGB10_1X10,
  54        V4L2_MBUS_FMT_SBGGR10_1X10,
  55        V4L2_MBUS_FMT_SGBRG10_1X10,
  56        V4L2_MBUS_FMT_SGRBG12_1X12,
  57        V4L2_MBUS_FMT_SRGGB12_1X12,
  58        V4L2_MBUS_FMT_SBGGR12_1X12,
  59        V4L2_MBUS_FMT_SGBRG12_1X12,
  60};
  61
  62/*
  63 * ccdc_print_status - Print current CCDC Module register values.
  64 * @ccdc: Pointer to ISP CCDC device.
  65 *
  66 * Also prints other debug information stored in the CCDC module.
  67 */
  68#define CCDC_PRINT_REGISTER(isp, name)\
  69        dev_dbg(isp->dev, "###CCDC " #name "=0x%08x\n", \
  70                isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_##name))
  71
  72static void ccdc_print_status(struct isp_ccdc_device *ccdc)
  73{
  74        struct isp_device *isp = to_isp_device(ccdc);
  75
  76        dev_dbg(isp->dev, "-------------CCDC Register dump-------------\n");
  77
  78        CCDC_PRINT_REGISTER(isp, PCR);
  79        CCDC_PRINT_REGISTER(isp, SYN_MODE);
  80        CCDC_PRINT_REGISTER(isp, HD_VD_WID);
  81        CCDC_PRINT_REGISTER(isp, PIX_LINES);
  82        CCDC_PRINT_REGISTER(isp, HORZ_INFO);
  83        CCDC_PRINT_REGISTER(isp, VERT_START);
  84        CCDC_PRINT_REGISTER(isp, VERT_LINES);
  85        CCDC_PRINT_REGISTER(isp, CULLING);
  86        CCDC_PRINT_REGISTER(isp, HSIZE_OFF);
  87        CCDC_PRINT_REGISTER(isp, SDOFST);
  88        CCDC_PRINT_REGISTER(isp, SDR_ADDR);
  89        CCDC_PRINT_REGISTER(isp, CLAMP);
  90        CCDC_PRINT_REGISTER(isp, DCSUB);
  91        CCDC_PRINT_REGISTER(isp, COLPTN);
  92        CCDC_PRINT_REGISTER(isp, BLKCMP);
  93        CCDC_PRINT_REGISTER(isp, FPC);
  94        CCDC_PRINT_REGISTER(isp, FPC_ADDR);
  95        CCDC_PRINT_REGISTER(isp, VDINT);
  96        CCDC_PRINT_REGISTER(isp, ALAW);
  97        CCDC_PRINT_REGISTER(isp, REC656IF);
  98        CCDC_PRINT_REGISTER(isp, CFG);
  99        CCDC_PRINT_REGISTER(isp, FMTCFG);
 100        CCDC_PRINT_REGISTER(isp, FMT_HORZ);
 101        CCDC_PRINT_REGISTER(isp, FMT_VERT);
 102        CCDC_PRINT_REGISTER(isp, PRGEVEN0);
 103        CCDC_PRINT_REGISTER(isp, PRGEVEN1);
 104        CCDC_PRINT_REGISTER(isp, PRGODD0);
 105        CCDC_PRINT_REGISTER(isp, PRGODD1);
 106        CCDC_PRINT_REGISTER(isp, VP_OUT);
 107        CCDC_PRINT_REGISTER(isp, LSC_CONFIG);
 108        CCDC_PRINT_REGISTER(isp, LSC_INITIAL);
 109        CCDC_PRINT_REGISTER(isp, LSC_TABLE_BASE);
 110        CCDC_PRINT_REGISTER(isp, LSC_TABLE_OFFSET);
 111
 112        dev_dbg(isp->dev, "--------------------------------------------\n");
 113}
 114
 115/*
 116 * omap3isp_ccdc_busy - Get busy state of the CCDC.
 117 * @ccdc: Pointer to ISP CCDC device.
 118 */
 119int omap3isp_ccdc_busy(struct isp_ccdc_device *ccdc)
 120{
 121        struct isp_device *isp = to_isp_device(ccdc);
 122
 123        return isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR) &
 124                ISPCCDC_PCR_BUSY;
 125}
 126
 127/* -----------------------------------------------------------------------------
 128 * Lens Shading Compensation
 129 */
 130
 131/*
 132 * ccdc_lsc_validate_config - Check that LSC configuration is valid.
 133 * @ccdc: Pointer to ISP CCDC device.
 134 * @lsc_cfg: the LSC configuration to check.
 135 *
 136 * Returns 0 if the LSC configuration is valid, or -EINVAL if invalid.
 137 */
 138static int ccdc_lsc_validate_config(struct isp_ccdc_device *ccdc,
 139                                    struct omap3isp_ccdc_lsc_config *lsc_cfg)
 140{
 141        struct isp_device *isp = to_isp_device(ccdc);
 142        struct v4l2_mbus_framefmt *format;
 143        unsigned int paxel_width, paxel_height;
 144        unsigned int paxel_shift_x, paxel_shift_y;
 145        unsigned int min_width, min_height, min_size;
 146        unsigned int input_width, input_height;
 147
 148        paxel_shift_x = lsc_cfg->gain_mode_m;
 149        paxel_shift_y = lsc_cfg->gain_mode_n;
 150
 151        if ((paxel_shift_x < 2) || (paxel_shift_x > 6) ||
 152            (paxel_shift_y < 2) || (paxel_shift_y > 6)) {
 153                dev_dbg(isp->dev, "CCDC: LSC: Invalid paxel size\n");
 154                return -EINVAL;
 155        }
 156
 157        if (lsc_cfg->offset & 3) {
 158                dev_dbg(isp->dev, "CCDC: LSC: Offset must be a multiple of "
 159                        "4\n");
 160                return -EINVAL;
 161        }
 162
 163        if ((lsc_cfg->initial_x & 1) || (lsc_cfg->initial_y & 1)) {
 164                dev_dbg(isp->dev, "CCDC: LSC: initial_x and y must be even\n");
 165                return -EINVAL;
 166        }
 167
 168        format = __ccdc_get_format(ccdc, NULL, CCDC_PAD_SINK,
 169                                   V4L2_SUBDEV_FORMAT_ACTIVE);
 170        input_width = format->width;
 171        input_height = format->height;
 172
 173        /* Calculate minimum bytesize for validation */
 174        paxel_width = 1 << paxel_shift_x;
 175        min_width = ((input_width + lsc_cfg->initial_x + paxel_width - 1)
 176                     >> paxel_shift_x) + 1;
 177
 178        paxel_height = 1 << paxel_shift_y;
 179        min_height = ((input_height + lsc_cfg->initial_y + paxel_height - 1)
 180                     >> paxel_shift_y) + 1;
 181
 182        min_size = 4 * min_width * min_height;
 183        if (min_size > lsc_cfg->size) {
 184                dev_dbg(isp->dev, "CCDC: LSC: too small table\n");
 185                return -EINVAL;
 186        }
 187        if (lsc_cfg->offset < (min_width * 4)) {
 188                dev_dbg(isp->dev, "CCDC: LSC: Offset is too small\n");
 189                return -EINVAL;
 190        }
 191        if ((lsc_cfg->size / lsc_cfg->offset) < min_height) {
 192                dev_dbg(isp->dev, "CCDC: LSC: Wrong size/offset combination\n");
 193                return -EINVAL;
 194        }
 195        return 0;
 196}
 197
 198/*
 199 * ccdc_lsc_program_table - Program Lens Shading Compensation table address.
 200 * @ccdc: Pointer to ISP CCDC device.
 201 */
 202static void ccdc_lsc_program_table(struct isp_ccdc_device *ccdc, u32 addr)
 203{
 204        isp_reg_writel(to_isp_device(ccdc), addr,
 205                       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE);
 206}
 207
 208/*
 209 * ccdc_lsc_setup_regs - Configures the lens shading compensation module
 210 * @ccdc: Pointer to ISP CCDC device.
 211 */
 212static void ccdc_lsc_setup_regs(struct isp_ccdc_device *ccdc,
 213                                struct omap3isp_ccdc_lsc_config *cfg)
 214{
 215        struct isp_device *isp = to_isp_device(ccdc);
 216        int reg;
 217
 218        isp_reg_writel(isp, cfg->offset, OMAP3_ISP_IOMEM_CCDC,
 219                       ISPCCDC_LSC_TABLE_OFFSET);
 220
 221        reg = 0;
 222        reg |= cfg->gain_mode_n << ISPCCDC_LSC_GAIN_MODE_N_SHIFT;
 223        reg |= cfg->gain_mode_m << ISPCCDC_LSC_GAIN_MODE_M_SHIFT;
 224        reg |= cfg->gain_format << ISPCCDC_LSC_GAIN_FORMAT_SHIFT;
 225        isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG);
 226
 227        reg = 0;
 228        reg &= ~ISPCCDC_LSC_INITIAL_X_MASK;
 229        reg |= cfg->initial_x << ISPCCDC_LSC_INITIAL_X_SHIFT;
 230        reg &= ~ISPCCDC_LSC_INITIAL_Y_MASK;
 231        reg |= cfg->initial_y << ISPCCDC_LSC_INITIAL_Y_SHIFT;
 232        isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_CCDC,
 233                       ISPCCDC_LSC_INITIAL);
 234}
 235
 236static int ccdc_lsc_wait_prefetch(struct isp_ccdc_device *ccdc)
 237{
 238        struct isp_device *isp = to_isp_device(ccdc);
 239        unsigned int wait;
 240
 241        isp_reg_writel(isp, IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ,
 242                       OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
 243
 244        /* timeout 1 ms */
 245        for (wait = 0; wait < 1000; wait++) {
 246                if (isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS) &
 247                                  IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ) {
 248                        isp_reg_writel(isp, IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ,
 249                                       OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
 250                        return 0;
 251                }
 252
 253                rmb();
 254                udelay(1);
 255        }
 256
 257        return -ETIMEDOUT;
 258}
 259
 260/*
 261 * __ccdc_lsc_enable - Enables/Disables the Lens Shading Compensation module.
 262 * @ccdc: Pointer to ISP CCDC device.
 263 * @enable: 0 Disables LSC, 1 Enables LSC.
 264 */
 265static int __ccdc_lsc_enable(struct isp_ccdc_device *ccdc, int enable)
 266{
 267        struct isp_device *isp = to_isp_device(ccdc);
 268        const struct v4l2_mbus_framefmt *format =
 269                __ccdc_get_format(ccdc, NULL, CCDC_PAD_SINK,
 270                                  V4L2_SUBDEV_FORMAT_ACTIVE);
 271
 272        if ((format->code != V4L2_MBUS_FMT_SGRBG10_1X10) &&
 273            (format->code != V4L2_MBUS_FMT_SRGGB10_1X10) &&
 274            (format->code != V4L2_MBUS_FMT_SBGGR10_1X10) &&
 275            (format->code != V4L2_MBUS_FMT_SGBRG10_1X10))
 276                return -EINVAL;
 277
 278        if (enable)
 279                omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_LSC_READ);
 280
 281        isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG,
 282                        ISPCCDC_LSC_ENABLE, enable ? ISPCCDC_LSC_ENABLE : 0);
 283
 284        if (enable) {
 285                if (ccdc_lsc_wait_prefetch(ccdc) < 0) {
 286                        isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC,
 287                                    ISPCCDC_LSC_CONFIG, ISPCCDC_LSC_ENABLE);
 288                        ccdc->lsc.state = LSC_STATE_STOPPED;
 289                        dev_warn(to_device(ccdc), "LSC prefecth timeout\n");
 290                        return -ETIMEDOUT;
 291                }
 292                ccdc->lsc.state = LSC_STATE_RUNNING;
 293        } else {
 294                ccdc->lsc.state = LSC_STATE_STOPPING;
 295        }
 296
 297        return 0;
 298}
 299
 300static int ccdc_lsc_busy(struct isp_ccdc_device *ccdc)
 301{
 302        struct isp_device *isp = to_isp_device(ccdc);
 303
 304        return isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG) &
 305                             ISPCCDC_LSC_BUSY;
 306}
 307
 308/* __ccdc_lsc_configure - Apply a new configuration to the LSC engine
 309 * @ccdc: Pointer to ISP CCDC device
 310 * @req: New configuration request
 311 *
 312 * context: in_interrupt()
 313 */
 314static int __ccdc_lsc_configure(struct isp_ccdc_device *ccdc,
 315                                struct ispccdc_lsc_config_req *req)
 316{
 317        if (!req->enable)
 318                return -EINVAL;
 319
 320        if (ccdc_lsc_validate_config(ccdc, &req->config) < 0) {
 321                dev_dbg(to_device(ccdc), "Discard LSC configuration\n");
 322                return -EINVAL;
 323        }
 324
 325        if (ccdc_lsc_busy(ccdc))
 326                return -EBUSY;
 327
 328        ccdc_lsc_setup_regs(ccdc, &req->config);
 329        ccdc_lsc_program_table(ccdc, req->table);
 330        return 0;
 331}
 332
 333/*
 334 * ccdc_lsc_error_handler - Handle LSC prefetch error scenario.
 335 * @ccdc: Pointer to ISP CCDC device.
 336 *
 337 * Disables LSC, and defers enablement to shadow registers update time.
 338 */
 339static void ccdc_lsc_error_handler(struct isp_ccdc_device *ccdc)
 340{
 341        struct isp_device *isp = to_isp_device(ccdc);
 342        /*
 343         * From OMAP3 TRM: When this event is pending, the module
 344         * goes into transparent mode (output =input). Normal
 345         * operation can be resumed at the start of the next frame
 346         * after:
 347         *  1) Clearing this event
 348         *  2) Disabling the LSC module
 349         *  3) Enabling it
 350         */
 351        isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG,
 352                    ISPCCDC_LSC_ENABLE);
 353        ccdc->lsc.state = LSC_STATE_STOPPED;
 354}
 355
 356static void ccdc_lsc_free_request(struct isp_ccdc_device *ccdc,
 357                                  struct ispccdc_lsc_config_req *req)
 358{
 359        struct isp_device *isp = to_isp_device(ccdc);
 360
 361        if (req == NULL)
 362                return;
 363
 364        if (req->iovm)
 365                dma_unmap_sg(isp->dev, req->iovm->sgt->sgl,
 366                             req->iovm->sgt->nents, DMA_TO_DEVICE);
 367        if (req->table)
 368                iommu_vfree(isp->iommu, req->table);
 369        kfree(req);
 370}
 371
 372static void ccdc_lsc_free_queue(struct isp_ccdc_device *ccdc,
 373                                struct list_head *queue)
 374{
 375        struct ispccdc_lsc_config_req *req, *n;
 376        unsigned long flags;
 377
 378        spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
 379        list_for_each_entry_safe(req, n, queue, list) {
 380                list_del(&req->list);
 381                spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
 382                ccdc_lsc_free_request(ccdc, req);
 383                spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
 384        }
 385        spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
 386}
 387
 388static void ccdc_lsc_free_table_work(struct work_struct *work)
 389{
 390        struct isp_ccdc_device *ccdc;
 391        struct ispccdc_lsc *lsc;
 392
 393        lsc = container_of(work, struct ispccdc_lsc, table_work);
 394        ccdc = container_of(lsc, struct isp_ccdc_device, lsc);
 395
 396        ccdc_lsc_free_queue(ccdc, &lsc->free_queue);
 397}
 398
 399/*
 400 * ccdc_lsc_config - Configure the LSC module from a userspace request
 401 *
 402 * Store the request LSC configuration in the LSC engine request pointer. The
 403 * configuration will be applied to the hardware when the CCDC will be enabled,
 404 * or at the next LSC interrupt if the CCDC is already running.
 405 */
 406static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
 407                           struct omap3isp_ccdc_update_config *config)
 408{
 409        struct isp_device *isp = to_isp_device(ccdc);
 410        struct ispccdc_lsc_config_req *req;
 411        unsigned long flags;
 412        void *table;
 413        u16 update;
 414        int ret;
 415
 416        update = config->update &
 417                 (OMAP3ISP_CCDC_CONFIG_LSC | OMAP3ISP_CCDC_TBL_LSC);
 418        if (!update)
 419                return 0;
 420
 421        if (update != (OMAP3ISP_CCDC_CONFIG_LSC | OMAP3ISP_CCDC_TBL_LSC)) {
 422                dev_dbg(to_device(ccdc), "%s: Both LSC configuration and table "
 423                        "need to be supplied\n", __func__);
 424                return -EINVAL;
 425        }
 426
 427        req = kzalloc(sizeof(*req), GFP_KERNEL);
 428        if (req == NULL)
 429                return -ENOMEM;
 430
 431        if (config->flag & OMAP3ISP_CCDC_CONFIG_LSC) {
 432                if (copy_from_user(&req->config, config->lsc_cfg,
 433                                   sizeof(req->config))) {
 434                        ret = -EFAULT;
 435                        goto done;
 436                }
 437
 438                req->enable = 1;
 439
 440                req->table = iommu_vmalloc(isp->iommu, 0, req->config.size,
 441                                           IOMMU_FLAG);
 442                if (IS_ERR_VALUE(req->table)) {
 443                        req->table = 0;
 444                        ret = -ENOMEM;
 445                        goto done;
 446                }
 447
 448                req->iovm = find_iovm_area(isp->iommu, req->table);
 449                if (req->iovm == NULL) {
 450                        ret = -ENOMEM;
 451                        goto done;
 452                }
 453
 454                if (!dma_map_sg(isp->dev, req->iovm->sgt->sgl,
 455                                req->iovm->sgt->nents, DMA_TO_DEVICE)) {
 456                        ret = -ENOMEM;
 457                        req->iovm = NULL;
 458                        goto done;
 459                }
 460
 461                dma_sync_sg_for_cpu(isp->dev, req->iovm->sgt->sgl,
 462                                    req->iovm->sgt->nents, DMA_TO_DEVICE);
 463
 464                table = da_to_va(isp->iommu, req->table);
 465                if (copy_from_user(table, config->lsc, req->config.size)) {
 466                        ret = -EFAULT;
 467                        goto done;
 468                }
 469
 470                dma_sync_sg_for_device(isp->dev, req->iovm->sgt->sgl,
 471                                       req->iovm->sgt->nents, DMA_TO_DEVICE);
 472        }
 473
 474        spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
 475        if (ccdc->lsc.request) {
 476                list_add_tail(&ccdc->lsc.request->list, &ccdc->lsc.free_queue);
 477                schedule_work(&ccdc->lsc.table_work);
 478        }
 479        ccdc->lsc.request = req;
 480        spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
 481
 482        ret = 0;
 483
 484done:
 485        if (ret < 0)
 486                ccdc_lsc_free_request(ccdc, req);
 487
 488        return ret;
 489}
 490
 491static inline int ccdc_lsc_is_configured(struct isp_ccdc_device *ccdc)
 492{
 493        unsigned long flags;
 494
 495        spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
 496        if (ccdc->lsc.active) {
 497                spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
 498                return 1;
 499        }
 500        spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
 501        return 0;
 502}
 503
 504static int ccdc_lsc_enable(struct isp_ccdc_device *ccdc)
 505{
 506        struct ispccdc_lsc *lsc = &ccdc->lsc;
 507
 508        if (lsc->state != LSC_STATE_STOPPED)
 509                return -EINVAL;
 510
 511        if (lsc->active) {
 512                list_add_tail(&lsc->active->list, &lsc->free_queue);
 513                lsc->active = NULL;
 514        }
 515
 516        if (__ccdc_lsc_configure(ccdc, lsc->request) < 0) {
 517                omap3isp_sbl_disable(to_isp_device(ccdc),
 518                                OMAP3_ISP_SBL_CCDC_LSC_READ);
 519                list_add_tail(&lsc->request->list, &lsc->free_queue);
 520                lsc->request = NULL;
 521                goto done;
 522        }
 523
 524        lsc->active = lsc->request;
 525        lsc->request = NULL;
 526        __ccdc_lsc_enable(ccdc, 1);
 527
 528done:
 529        if (!list_empty(&lsc->free_queue))
 530                schedule_work(&lsc->table_work);
 531
 532        return 0;
 533}
 534
 535/* -----------------------------------------------------------------------------
 536 * Parameters configuration
 537 */
 538
 539/*
 540 * ccdc_configure_clamp - Configure optical-black or digital clamping
 541 * @ccdc: Pointer to ISP CCDC device.
 542 *
 543 * The CCDC performs either optical-black or digital clamp. Configure and enable
 544 * the selected clamp method.
 545 */
 546static void ccdc_configure_clamp(struct isp_ccdc_device *ccdc)
 547{
 548        struct isp_device *isp = to_isp_device(ccdc);
 549        u32 clamp;
 550
 551        if (ccdc->obclamp) {
 552                clamp  = ccdc->clamp.obgain << ISPCCDC_CLAMP_OBGAIN_SHIFT;
 553                clamp |= ccdc->clamp.oblen << ISPCCDC_CLAMP_OBSLEN_SHIFT;
 554                clamp |= ccdc->clamp.oblines << ISPCCDC_CLAMP_OBSLN_SHIFT;
 555                clamp |= ccdc->clamp.obstpixel << ISPCCDC_CLAMP_OBST_SHIFT;
 556                isp_reg_writel(isp, clamp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP);
 557        } else {
 558                isp_reg_writel(isp, ccdc->clamp.dcsubval,
 559                               OMAP3_ISP_IOMEM_CCDC, ISPCCDC_DCSUB);
 560        }
 561
 562        isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP,
 563                        ISPCCDC_CLAMP_CLAMPEN,
 564                        ccdc->obclamp ? ISPCCDC_CLAMP_CLAMPEN : 0);
 565}
 566
 567/*
 568 * ccdc_configure_fpc - Configure Faulty Pixel Correction
 569 * @ccdc: Pointer to ISP CCDC device.
 570 */
 571static void ccdc_configure_fpc(struct isp_ccdc_device *ccdc)
 572{
 573        struct isp_device *isp = to_isp_device(ccdc);
 574
 575        isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC, ISPCCDC_FPC_FPCEN);
 576
 577        if (!ccdc->fpc_en)
 578                return;
 579
 580        isp_reg_writel(isp, ccdc->fpc.fpcaddr, OMAP3_ISP_IOMEM_CCDC,
 581                       ISPCCDC_FPC_ADDR);
 582        /* The FPNUM field must be set before enabling FPC. */
 583        isp_reg_writel(isp, (ccdc->fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT),
 584                       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
 585        isp_reg_writel(isp, (ccdc->fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT) |
 586                       ISPCCDC_FPC_FPCEN, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
 587}
 588
 589/*
 590 * ccdc_configure_black_comp - Configure Black Level Compensation.
 591 * @ccdc: Pointer to ISP CCDC device.
 592 */
 593static void ccdc_configure_black_comp(struct isp_ccdc_device *ccdc)
 594{
 595        struct isp_device *isp = to_isp_device(ccdc);
 596        u32 blcomp;
 597
 598        blcomp  = ccdc->blcomp.b_mg << ISPCCDC_BLKCMP_B_MG_SHIFT;
 599        blcomp |= ccdc->blcomp.gb_g << ISPCCDC_BLKCMP_GB_G_SHIFT;
 600        blcomp |= ccdc->blcomp.gr_cy << ISPCCDC_BLKCMP_GR_CY_SHIFT;
 601        blcomp |= ccdc->blcomp.r_ye << ISPCCDC_BLKCMP_R_YE_SHIFT;
 602
 603        isp_reg_writel(isp, blcomp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP);
 604}
 605
 606/*
 607 * ccdc_configure_lpf - Configure Low-Pass Filter (LPF).
 608 * @ccdc: Pointer to ISP CCDC device.
 609 */
 610static void ccdc_configure_lpf(struct isp_ccdc_device *ccdc)
 611{
 612        struct isp_device *isp = to_isp_device(ccdc);
 613
 614        isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE,
 615                        ISPCCDC_SYN_MODE_LPF,
 616                        ccdc->lpf ? ISPCCDC_SYN_MODE_LPF : 0);
 617}
 618
 619/*
 620 * ccdc_configure_alaw - Configure A-law compression.
 621 * @ccdc: Pointer to ISP CCDC device.
 622 */
 623static void ccdc_configure_alaw(struct isp_ccdc_device *ccdc)
 624{
 625        struct isp_device *isp = to_isp_device(ccdc);
 626        u32 alaw = 0;
 627
 628        switch (ccdc->syncif.datsz) {
 629        case 8:
 630                return;
 631
 632        case 10:
 633                alaw = ISPCCDC_ALAW_GWDI_9_0;
 634                break;
 635        case 11:
 636                alaw = ISPCCDC_ALAW_GWDI_10_1;
 637                break;
 638        case 12:
 639                alaw = ISPCCDC_ALAW_GWDI_11_2;
 640                break;
 641        case 13:
 642                alaw = ISPCCDC_ALAW_GWDI_12_3;
 643                break;
 644        }
 645
 646        if (ccdc->alaw)
 647                alaw |= ISPCCDC_ALAW_CCDTBL;
 648
 649        isp_reg_writel(isp, alaw, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW);
 650}
 651
 652/*
 653 * ccdc_config_imgattr - Configure sensor image specific attributes.
 654 * @ccdc: Pointer to ISP CCDC device.
 655 * @colptn: Color pattern of the sensor.
 656 */
 657static void ccdc_config_imgattr(struct isp_ccdc_device *ccdc, u32 colptn)
 658{
 659        struct isp_device *isp = to_isp_device(ccdc);
 660
 661        isp_reg_writel(isp, colptn, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN);
 662}
 663
 664/*
 665 * ccdc_config - Set CCDC configuration from userspace
 666 * @ccdc: Pointer to ISP CCDC device.
 667 * @userspace_add: Structure containing CCDC configuration sent from userspace.
 668 *
 669 * Returns 0 if successful, -EINVAL if the pointer to the configuration
 670 * structure is null, or the copy_from_user function fails to copy user space
 671 * memory to kernel space memory.
 672 */
 673static int ccdc_config(struct isp_ccdc_device *ccdc,
 674                       struct omap3isp_ccdc_update_config *ccdc_struct)
 675{
 676        struct isp_device *isp = to_isp_device(ccdc);
 677        unsigned long flags;
 678
 679        spin_lock_irqsave(&ccdc->lock, flags);
 680        ccdc->shadow_update = 1;
 681        spin_unlock_irqrestore(&ccdc->lock, flags);
 682
 683        if (OMAP3ISP_CCDC_ALAW & ccdc_struct->update) {
 684                ccdc->alaw = !!(OMAP3ISP_CCDC_ALAW & ccdc_struct->flag);
 685                ccdc->update |= OMAP3ISP_CCDC_ALAW;
 686        }
 687
 688        if (OMAP3ISP_CCDC_LPF & ccdc_struct->update) {
 689                ccdc->lpf = !!(OMAP3ISP_CCDC_LPF & ccdc_struct->flag);
 690                ccdc->update |= OMAP3ISP_CCDC_LPF;
 691        }
 692
 693        if (OMAP3ISP_CCDC_BLCLAMP & ccdc_struct->update) {
 694                if (copy_from_user(&ccdc->clamp, ccdc_struct->bclamp,
 695                                   sizeof(ccdc->clamp))) {
 696                        ccdc->shadow_update = 0;
 697                        return -EFAULT;
 698                }
 699
 700                ccdc->obclamp = !!(OMAP3ISP_CCDC_BLCLAMP & ccdc_struct->flag);
 701                ccdc->update |= OMAP3ISP_CCDC_BLCLAMP;
 702        }
 703
 704        if (OMAP3ISP_CCDC_BCOMP & ccdc_struct->update) {
 705                if (copy_from_user(&ccdc->blcomp, ccdc_struct->blcomp,
 706                                   sizeof(ccdc->blcomp))) {
 707                        ccdc->shadow_update = 0;
 708                        return -EFAULT;
 709                }
 710
 711                ccdc->update |= OMAP3ISP_CCDC_BCOMP;
 712        }
 713
 714        ccdc->shadow_update = 0;
 715
 716        if (OMAP3ISP_CCDC_FPC & ccdc_struct->update) {
 717                u32 table_old = 0;
 718                u32 table_new;
 719                u32 size;
 720
 721                if (ccdc->state != ISP_PIPELINE_STREAM_STOPPED)
 722                        return -EBUSY;
 723
 724                ccdc->fpc_en = !!(OMAP3ISP_CCDC_FPC & ccdc_struct->flag);
 725
 726                if (ccdc->fpc_en) {
 727                        if (copy_from_user(&ccdc->fpc, ccdc_struct->fpc,
 728                                           sizeof(ccdc->fpc)))
 729                                return -EFAULT;
 730
 731                        /*
 732                         * table_new must be 64-bytes aligned, but it's
 733                         * already done by iommu_vmalloc().
 734                         */
 735                        size = ccdc->fpc.fpnum * 4;
 736                        table_new = iommu_vmalloc(isp->iommu, 0, size,
 737                                                  IOMMU_FLAG);
 738                        if (IS_ERR_VALUE(table_new))
 739                                return -ENOMEM;
 740
 741                        if (copy_from_user(da_to_va(isp->iommu, table_new),
 742                                           (__force void __user *)
 743                                           ccdc->fpc.fpcaddr, size)) {
 744                                iommu_vfree(isp->iommu, table_new);
 745                                return -EFAULT;
 746                        }
 747
 748                        table_old = ccdc->fpc.fpcaddr;
 749                        ccdc->fpc.fpcaddr = table_new;
 750                }
 751
 752                ccdc_configure_fpc(ccdc);
 753                if (table_old != 0)
 754                        iommu_vfree(isp->iommu, table_old);
 755        }
 756
 757        return ccdc_lsc_config(ccdc, ccdc_struct);
 758}
 759
 760static void ccdc_apply_controls(struct isp_ccdc_device *ccdc)
 761{
 762        if (ccdc->update & OMAP3ISP_CCDC_ALAW) {
 763                ccdc_configure_alaw(ccdc);
 764                ccdc->update &= ~OMAP3ISP_CCDC_ALAW;
 765        }
 766
 767        if (ccdc->update & OMAP3ISP_CCDC_LPF) {
 768                ccdc_configure_lpf(ccdc);
 769                ccdc->update &= ~OMAP3ISP_CCDC_LPF;
 770        }
 771
 772        if (ccdc->update & OMAP3ISP_CCDC_BLCLAMP) {
 773                ccdc_configure_clamp(ccdc);
 774                ccdc->update &= ~OMAP3ISP_CCDC_BLCLAMP;
 775        }
 776
 777        if (ccdc->update & OMAP3ISP_CCDC_BCOMP) {
 778                ccdc_configure_black_comp(ccdc);
 779                ccdc->update &= ~OMAP3ISP_CCDC_BCOMP;
 780        }
 781}
 782
 783/*
 784 * omap3isp_ccdc_restore_context - Restore values of the CCDC module registers
 785 * @dev: Pointer to ISP device
 786 */
 787void omap3isp_ccdc_restore_context(struct isp_device *isp)
 788{
 789        struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
 790
 791        isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, ISPCCDC_CFG_VDLC);
 792
 793        ccdc->update = OMAP3ISP_CCDC_ALAW | OMAP3ISP_CCDC_LPF
 794                     | OMAP3ISP_CCDC_BLCLAMP | OMAP3ISP_CCDC_BCOMP;
 795        ccdc_apply_controls(ccdc);
 796        ccdc_configure_fpc(ccdc);
 797}
 798
 799/* -----------------------------------------------------------------------------
 800 * Format- and pipeline-related configuration helpers
 801 */
 802
 803/*
 804 * ccdc_config_vp - Configure the Video Port.
 805 * @ccdc: Pointer to ISP CCDC device.
 806 */
 807static void ccdc_config_vp(struct isp_ccdc_device *ccdc)
 808{
 809        struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
 810        struct isp_device *isp = to_isp_device(ccdc);
 811        unsigned long l3_ick = pipe->l3_ick;
 812        unsigned int max_div = isp->revision == ISP_REVISION_15_0 ? 64 : 8;
 813        unsigned int div = 0;
 814        u32 fmtcfg_vp;
 815
 816        fmtcfg_vp = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG)
 817                  & ~(ISPCCDC_FMTCFG_VPIN_MASK | ISPCCDC_FMTCFG_VPIF_FRQ_MASK);
 818
 819        switch (ccdc->syncif.datsz) {
 820        case 8:
 821        case 10:
 822                fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0;
 823                break;
 824        case 11:
 825                fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_10_1;
 826                break;
 827        case 12:
 828                fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_11_2;
 829                break;
 830        case 13:
 831                fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3;
 832                break;
 833        };
 834
 835        if (pipe->input)
 836                div = DIV_ROUND_UP(l3_ick, pipe->max_rate);
 837        else if (ccdc->vpcfg.pixelclk)
 838                div = l3_ick / ccdc->vpcfg.pixelclk;
 839
 840        div = clamp(div, 2U, max_div);
 841        fmtcfg_vp |= (div - 2) << ISPCCDC_FMTCFG_VPIF_FRQ_SHIFT;
 842
 843        isp_reg_writel(isp, fmtcfg_vp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
 844}
 845
 846/*
 847 * ccdc_enable_vp - Enable Video Port.
 848 * @ccdc: Pointer to ISP CCDC device.
 849 * @enable: 0 Disables VP, 1 Enables VP
 850 *
 851 * This is needed for outputting image to Preview, H3A and HIST ISP submodules.
 852 */
 853static void ccdc_enable_vp(struct isp_ccdc_device *ccdc, u8 enable)
 854{
 855        struct isp_device *isp = to_isp_device(ccdc);
 856
 857        isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
 858                        ISPCCDC_FMTCFG_VPEN, enable ? ISPCCDC_FMTCFG_VPEN : 0);
 859}
 860
 861/*
 862 * ccdc_config_outlineoffset - Configure memory saving output line offset
 863 * @ccdc: Pointer to ISP CCDC device.
 864 * @offset: Address offset to start a new line. Must be twice the
 865 *          Output width and aligned on 32 byte boundary
 866 * @oddeven: Specifies the odd/even line pattern to be chosen to store the
 867 *           output.
 868 * @numlines: Set the value 0-3 for +1-4lines, 4-7 for -1-4lines.
 869 *
 870 * - Configures the output line offset when stored in memory
 871 * - Sets the odd/even line pattern to store the output
 872 *    (EVENEVEN (1), ODDEVEN (2), EVENODD (3), ODDODD (4))
 873 * - Configures the number of even and odd line fields in case of rearranging
 874 * the lines.
 875 */
 876static void ccdc_config_outlineoffset(struct isp_ccdc_device *ccdc,
 877                                        u32 offset, u8 oddeven, u8 numlines)
 878{
 879        struct isp_device *isp = to_isp_device(ccdc);
 880
 881        isp_reg_writel(isp, offset & 0xffff,
 882                       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF);
 883
 884        isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
 885                    ISPCCDC_SDOFST_FINV);
 886
 887        isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
 888                    ISPCCDC_SDOFST_FOFST_4L);
 889
 890        switch (oddeven) {
 891        case EVENEVEN:
 892                isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
 893                            (numlines & 0x7) << ISPCCDC_SDOFST_LOFST0_SHIFT);
 894                break;
 895        case ODDEVEN:
 896                isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
 897                            (numlines & 0x7) << ISPCCDC_SDOFST_LOFST1_SHIFT);
 898                break;
 899        case EVENODD:
 900                isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
 901                            (numlines & 0x7) << ISPCCDC_SDOFST_LOFST2_SHIFT);
 902                break;
 903        case ODDODD:
 904                isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
 905                            (numlines & 0x7) << ISPCCDC_SDOFST_LOFST3_SHIFT);
 906                break;
 907        default:
 908                break;
 909        }
 910}
 911
 912/*
 913 * ccdc_set_outaddr - Set memory address to save output image
 914 * @ccdc: Pointer to ISP CCDC device.
 915 * @addr: ISP MMU Mapped 32-bit memory address aligned on 32 byte boundary.
 916 *
 917 * Sets the memory address where the output will be saved.
 918 */
 919static void ccdc_set_outaddr(struct isp_ccdc_device *ccdc, u32 addr)
 920{
 921        struct isp_device *isp = to_isp_device(ccdc);
 922
 923        isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR);
 924}
 925
 926/*
 927 * omap3isp_ccdc_max_rate - Calculate maximum input data rate based on the input
 928 * @ccdc: Pointer to ISP CCDC device.
 929 * @max_rate: Maximum calculated data rate.
 930 *
 931 * Returns in *max_rate less value between calculated and passed
 932 */
 933void omap3isp_ccdc_max_rate(struct isp_ccdc_device *ccdc,
 934                            unsigned int *max_rate)
 935{
 936        struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
 937        unsigned int rate;
 938
 939        if (pipe == NULL)
 940                return;
 941
 942        /*
 943         * TRM says that for parallel sensors the maximum data rate
 944         * should be 90% form L3/2 clock, otherwise just L3/2.
 945         */
 946        if (ccdc->input == CCDC_INPUT_PARALLEL)
 947                rate = pipe->l3_ick / 2 * 9 / 10;
 948        else
 949                rate = pipe->l3_ick / 2;
 950
 951        *max_rate = min(*max_rate, rate);
 952}
 953
 954/*
 955 * ccdc_config_sync_if - Set CCDC sync interface configuration
 956 * @ccdc: Pointer to ISP CCDC device.
 957 * @syncif: Structure containing the sync parameters like field state, CCDC in
 958 *          master/slave mode, raw/yuv data, polarity of data, field, hs, vs
 959 *          signals.
 960 */
 961static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc,
 962                                struct ispccdc_syncif *syncif)
 963{
 964        struct isp_device *isp = to_isp_device(ccdc);
 965        u32 syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC,
 966                                     ISPCCDC_SYN_MODE);
 967
 968        syn_mode |= ISPCCDC_SYN_MODE_VDHDEN;
 969
 970        if (syncif->fldstat)
 971                syn_mode |= ISPCCDC_SYN_MODE_FLDSTAT;
 972        else
 973                syn_mode &= ~ISPCCDC_SYN_MODE_FLDSTAT;
 974
 975        syn_mode &= ~ISPCCDC_SYN_MODE_DATSIZ_MASK;
 976        switch (syncif->datsz) {
 977        case 8:
 978                syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8;
 979                break;
 980        case 10:
 981                syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_10;
 982                break;
 983        case 11:
 984                syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_11;
 985                break;
 986        case 12:
 987                syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_12;
 988                break;
 989        };
 990
 991        if (syncif->fldmode)
 992                syn_mode |= ISPCCDC_SYN_MODE_FLDMODE;
 993        else
 994                syn_mode &= ~ISPCCDC_SYN_MODE_FLDMODE;
 995
 996        if (syncif->datapol)
 997                syn_mode |= ISPCCDC_SYN_MODE_DATAPOL;
 998        else
 999                syn_mode &= ~ISPCCDC_SYN_MODE_DATAPOL;
1000
1001        if (syncif->fldpol)
1002                syn_mode |= ISPCCDC_SYN_MODE_FLDPOL;
1003        else
1004                syn_mode &= ~ISPCCDC_SYN_MODE_FLDPOL;
1005
1006        if (syncif->hdpol)
1007                syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
1008        else
1009                syn_mode &= ~ISPCCDC_SYN_MODE_HDPOL;
1010
1011        if (syncif->vdpol)
1012                syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
1013        else
1014                syn_mode &= ~ISPCCDC_SYN_MODE_VDPOL;
1015
1016        if (syncif->ccdc_mastermode) {
1017                syn_mode |= ISPCCDC_SYN_MODE_FLDOUT | ISPCCDC_SYN_MODE_VDHDOUT;
1018                isp_reg_writel(isp,
1019                               syncif->hs_width << ISPCCDC_HD_VD_WID_HDW_SHIFT
1020                             | syncif->vs_width << ISPCCDC_HD_VD_WID_VDW_SHIFT,
1021                               OMAP3_ISP_IOMEM_CCDC,
1022                               ISPCCDC_HD_VD_WID);
1023
1024                isp_reg_writel(isp,
1025                               syncif->ppln << ISPCCDC_PIX_LINES_PPLN_SHIFT
1026                             | syncif->hlprf << ISPCCDC_PIX_LINES_HLPRF_SHIFT,
1027                               OMAP3_ISP_IOMEM_CCDC,
1028                               ISPCCDC_PIX_LINES);
1029        } else
1030                syn_mode &= ~(ISPCCDC_SYN_MODE_FLDOUT |
1031                              ISPCCDC_SYN_MODE_VDHDOUT);
1032
1033        isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
1034
1035        if (!syncif->bt_r656_en)
1036                isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
1037                            ISPCCDC_REC656IF_R656ON);
1038}
1039
1040/* CCDC formats descriptions */
1041static const u32 ccdc_sgrbg_pattern =
1042        ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
1043        ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
1044        ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
1045        ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
1046        ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
1047        ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
1048        ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
1049        ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
1050        ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
1051        ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
1052        ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
1053        ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
1054        ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
1055        ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
1056        ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
1057        ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
1058
1059static const u32 ccdc_srggb_pattern =
1060        ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
1061        ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
1062        ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
1063        ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
1064        ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
1065        ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
1066        ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
1067        ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
1068        ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
1069        ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
1070        ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
1071        ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
1072        ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
1073        ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
1074        ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
1075        ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
1076
1077static const u32 ccdc_sbggr_pattern =
1078        ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
1079        ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
1080        ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
1081        ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
1082        ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
1083        ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
1084        ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
1085        ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
1086        ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
1087        ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
1088        ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
1089        ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
1090        ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
1091        ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
1092        ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
1093        ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
1094
1095static const u32 ccdc_sgbrg_pattern =
1096        ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
1097        ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
1098        ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
1099        ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
1100        ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
1101        ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
1102        ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
1103        ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
1104        ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
1105        ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
1106        ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
1107        ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
1108        ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
1109        ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
1110        ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
1111        ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
1112
1113static void ccdc_configure(struct isp_ccdc_device *ccdc)
1114{
1115        struct isp_device *isp = to_isp_device(ccdc);
1116        struct isp_parallel_platform_data *pdata = NULL;
1117        struct v4l2_subdev *sensor;
1118        struct v4l2_mbus_framefmt *format;
1119        const struct isp_format_info *fmt_info;
1120        struct v4l2_subdev_format fmt_src;
1121        unsigned int depth_out;
1122        unsigned int depth_in = 0;
1123        struct media_pad *pad;
1124        unsigned long flags;
1125        unsigned int shift;
1126        u32 syn_mode;
1127        u32 ccdc_pattern;
1128
1129        pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]);
1130        sensor = media_entity_to_v4l2_subdev(pad->entity);
1131        if (ccdc->input == CCDC_INPUT_PARALLEL)
1132                pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv)
1133                        ->bus.parallel;
1134
1135        /* Compute shift value for lane shifter to configure the bridge. */
1136        fmt_src.pad = pad->index;
1137        fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1138        if (!v4l2_subdev_call(sensor, pad, get_fmt, NULL, &fmt_src)) {
1139                fmt_info = omap3isp_video_format_info(fmt_src.format.code);
1140                depth_in = fmt_info->bpp;
1141        }
1142
1143        fmt_info = omap3isp_video_format_info
1144                (isp->isp_ccdc.formats[CCDC_PAD_SINK].code);
1145        depth_out = fmt_info->bpp;
1146
1147        shift = depth_in - depth_out;
1148        omap3isp_configure_bridge(isp, ccdc->input, pdata, shift);
1149
1150        ccdc->syncif.datsz = depth_out;
1151        ccdc_config_sync_if(ccdc, &ccdc->syncif);
1152
1153        /* CCDC_PAD_SINK */
1154        format = &ccdc->formats[CCDC_PAD_SINK];
1155
1156        syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
1157
1158        /* Use the raw, unprocessed data when writing to memory. The H3A and
1159         * histogram modules are still fed with lens shading corrected data.
1160         */
1161        syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
1162
1163        if (ccdc->output & CCDC_OUTPUT_MEMORY)
1164                syn_mode |= ISPCCDC_SYN_MODE_WEN;
1165        else
1166                syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
1167
1168        if (ccdc->output & CCDC_OUTPUT_RESIZER)
1169                syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
1170        else
1171                syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
1172
1173        /* Use PACK8 mode for 1byte per pixel formats. */
1174        if (omap3isp_video_format_info(format->code)->bpp <= 8)
1175                syn_mode |= ISPCCDC_SYN_MODE_PACK8;
1176        else
1177                syn_mode &= ~ISPCCDC_SYN_MODE_PACK8;
1178
1179        isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
1180
1181        /* Mosaic filter */
1182        switch (format->code) {
1183        case V4L2_MBUS_FMT_SRGGB10_1X10:
1184        case V4L2_MBUS_FMT_SRGGB12_1X12:
1185                ccdc_pattern = ccdc_srggb_pattern;
1186                break;
1187        case V4L2_MBUS_FMT_SBGGR10_1X10:
1188        case V4L2_MBUS_FMT_SBGGR12_1X12:
1189                ccdc_pattern = ccdc_sbggr_pattern;
1190                break;
1191        case V4L2_MBUS_FMT_SGBRG10_1X10:
1192        case V4L2_MBUS_FMT_SGBRG12_1X12:
1193                ccdc_pattern = ccdc_sgbrg_pattern;
1194                break;
1195        default:
1196                /* Use GRBG */
1197                ccdc_pattern = ccdc_sgrbg_pattern;
1198                break;
1199        }
1200        ccdc_config_imgattr(ccdc, ccdc_pattern);
1201
1202        /* Generate VD0 on the last line of the image and VD1 on the
1203         * 2/3 height line.
1204         */
1205        isp_reg_writel(isp, ((format->height - 2) << ISPCCDC_VDINT_0_SHIFT) |
1206                       ((format->height * 2 / 3) << ISPCCDC_VDINT_1_SHIFT),
1207                       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VDINT);
1208
1209        /* CCDC_PAD_SOURCE_OF */
1210        format = &ccdc->formats[CCDC_PAD_SOURCE_OF];
1211
1212        isp_reg_writel(isp, (0 << ISPCCDC_HORZ_INFO_SPH_SHIFT) |
1213                       ((format->width - 1) << ISPCCDC_HORZ_INFO_NPH_SHIFT),
1214                       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO);
1215        isp_reg_writel(isp, 0 << ISPCCDC_VERT_START_SLV0_SHIFT,
1216                       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_START);
1217        isp_reg_writel(isp, (format->height - 1)
1218                        << ISPCCDC_VERT_LINES_NLV_SHIFT,
1219                       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_LINES);
1220
1221        ccdc_config_outlineoffset(ccdc, ccdc->video_out.bpl_value, 0, 0);
1222
1223        /* CCDC_PAD_SOURCE_VP */
1224        format = &ccdc->formats[CCDC_PAD_SOURCE_VP];
1225
1226        isp_reg_writel(isp, (0 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
1227                       (format->width << ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
1228                       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ);
1229        isp_reg_writel(isp, (0 << ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
1230                       ((format->height + 1) << ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
1231                       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT);
1232
1233        isp_reg_writel(isp, (format->width << ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
1234                       (format->height << ISPCCDC_VP_OUT_VERT_NUM_SHIFT),
1235                       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT);
1236
1237        spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
1238        if (ccdc->lsc.request == NULL)
1239                goto unlock;
1240
1241        WARN_ON(ccdc->lsc.active);
1242
1243        /* Get last good LSC configuration. If it is not supported for
1244         * the current active resolution discard it.
1245         */
1246        if (ccdc->lsc.active == NULL &&
1247            __ccdc_lsc_configure(ccdc, ccdc->lsc.request) == 0) {
1248                ccdc->lsc.active = ccdc->lsc.request;
1249        } else {
1250                list_add_tail(&ccdc->lsc.request->list, &ccdc->lsc.free_queue);
1251                schedule_work(&ccdc->lsc.table_work);
1252        }
1253
1254        ccdc->lsc.request = NULL;
1255
1256unlock:
1257        spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
1258
1259        ccdc_apply_controls(ccdc);
1260}
1261
1262static void __ccdc_enable(struct isp_ccdc_device *ccdc, int enable)
1263{
1264        struct isp_device *isp = to_isp_device(ccdc);
1265
1266        isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR,
1267                        ISPCCDC_PCR_EN, enable ? ISPCCDC_PCR_EN : 0);
1268}
1269
1270static int ccdc_disable(struct isp_ccdc_device *ccdc)
1271{
1272        unsigned long flags;
1273        int ret = 0;
1274
1275        spin_lock_irqsave(&ccdc->lock, flags);
1276        if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS)
1277                ccdc->stopping = CCDC_STOP_REQUEST;
1278        spin_unlock_irqrestore(&ccdc->lock, flags);
1279
1280        ret = wait_event_timeout(ccdc->wait,
1281                                 ccdc->stopping == CCDC_STOP_FINISHED,
1282                                 msecs_to_jiffies(2000));
1283        if (ret == 0) {
1284                ret = -ETIMEDOUT;
1285                dev_warn(to_device(ccdc), "CCDC stop timeout!\n");
1286        }
1287
1288        omap3isp_sbl_disable(to_isp_device(ccdc), OMAP3_ISP_SBL_CCDC_LSC_READ);
1289
1290        mutex_lock(&ccdc->ioctl_lock);
1291        ccdc_lsc_free_request(ccdc, ccdc->lsc.request);
1292        ccdc->lsc.request = ccdc->lsc.active;
1293        ccdc->lsc.active = NULL;
1294        cancel_work_sync(&ccdc->lsc.table_work);
1295        ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
1296        mutex_unlock(&ccdc->ioctl_lock);
1297
1298        ccdc->stopping = CCDC_STOP_NOT_REQUESTED;
1299
1300        return ret > 0 ? 0 : ret;
1301}
1302
1303static void ccdc_enable(struct isp_ccdc_device *ccdc)
1304{
1305        if (ccdc_lsc_is_configured(ccdc))
1306                __ccdc_lsc_enable(ccdc, 1);
1307        __ccdc_enable(ccdc, 1);
1308}
1309
1310/* -----------------------------------------------------------------------------
1311 * Interrupt handling
1312 */
1313
1314/*
1315 * ccdc_sbl_busy - Poll idle state of CCDC and related SBL memory write bits
1316 * @ccdc: Pointer to ISP CCDC device.
1317 *
1318 * Returns zero if the CCDC is idle and the image has been written to
1319 * memory, too.
1320 */
1321static int ccdc_sbl_busy(struct isp_ccdc_device *ccdc)
1322{
1323        struct isp_device *isp = to_isp_device(ccdc);
1324
1325        return omap3isp_ccdc_busy(ccdc)
1326                | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_0) &
1327                   ISPSBL_CCDC_WR_0_DATA_READY)
1328                | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_1) &
1329                   ISPSBL_CCDC_WR_0_DATA_READY)
1330                | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_2) &
1331                   ISPSBL_CCDC_WR_0_DATA_READY)
1332                | (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_3) &
1333                   ISPSBL_CCDC_WR_0_DATA_READY);
1334}
1335
1336/*
1337 * ccdc_sbl_wait_idle - Wait until the CCDC and related SBL are idle
1338 * @ccdc: Pointer to ISP CCDC device.
1339 * @max_wait: Max retry count in us for wait for idle/busy transition.
1340 */
1341static int ccdc_sbl_wait_idle(struct isp_ccdc_device *ccdc,
1342                              unsigned int max_wait)
1343{
1344        unsigned int wait = 0;
1345
1346        if (max_wait == 0)
1347                max_wait = 10000; /* 10 ms */
1348
1349        for (wait = 0; wait <= max_wait; wait++) {
1350                if (!ccdc_sbl_busy(ccdc))
1351                        return 0;
1352
1353                rmb();
1354                udelay(1);
1355        }
1356
1357        return -EBUSY;
1358}
1359
1360/* __ccdc_handle_stopping - Handle CCDC and/or LSC stopping sequence
1361 * @ccdc: Pointer to ISP CCDC device.
1362 * @event: Pointing which event trigger handler
1363 *
1364 * Return 1 when the event and stopping request combination is satisfied,
1365 * zero otherwise.
1366 */
1367static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event)
1368{
1369        int rval = 0;
1370
1371        switch ((ccdc->stopping & 3) | event) {
1372        case CCDC_STOP_REQUEST | CCDC_EVENT_VD1:
1373                if (ccdc->lsc.state != LSC_STATE_STOPPED)
1374                        __ccdc_lsc_enable(ccdc, 0);
1375                __ccdc_enable(ccdc, 0);
1376                ccdc->stopping = CCDC_STOP_EXECUTED;
1377                return 1;
1378
1379        case CCDC_STOP_EXECUTED | CCDC_EVENT_VD0:
1380                ccdc->stopping |= CCDC_STOP_CCDC_FINISHED;
1381                if (ccdc->lsc.state == LSC_STATE_STOPPED)
1382                        ccdc->stopping |= CCDC_STOP_LSC_FINISHED;
1383                rval = 1;
1384                break;
1385
1386        case CCDC_STOP_EXECUTED | CCDC_EVENT_LSC_DONE:
1387                ccdc->stopping |= CCDC_STOP_LSC_FINISHED;
1388                rval = 1;
1389                break;
1390
1391        case CCDC_STOP_EXECUTED | CCDC_EVENT_VD1:
1392                return 1;
1393        }
1394
1395        if (ccdc->stopping == CCDC_STOP_FINISHED) {
1396                wake_up(&ccdc->wait);
1397                rval = 1;
1398        }
1399
1400        return rval;
1401}
1402
1403static void ccdc_hs_vs_isr(struct isp_ccdc_device *ccdc)
1404{
1405        struct video_device *vdev = &ccdc->subdev.devnode;
1406        struct v4l2_event event;
1407
1408        memset(&event, 0, sizeof(event));
1409        event.type = V4L2_EVENT_OMAP3ISP_HS_VS;
1410
1411        v4l2_event_queue(vdev, &event);
1412}
1413
1414/*
1415 * ccdc_lsc_isr - Handle LSC events
1416 * @ccdc: Pointer to ISP CCDC device.
1417 * @events: LSC events
1418 */
1419static void ccdc_lsc_isr(struct isp_ccdc_device *ccdc, u32 events)
1420{
1421        unsigned long flags;
1422
1423        if (events & IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ) {
1424                ccdc_lsc_error_handler(ccdc);
1425                ccdc->error = 1;
1426                dev_dbg(to_device(ccdc), "lsc prefetch error\n");
1427        }
1428
1429        if (!(events & IRQ0STATUS_CCDC_LSC_DONE_IRQ))
1430                return;
1431
1432        /* LSC_DONE interrupt occur, there are two cases
1433         * 1. stopping for reconfiguration
1434         * 2. stopping because of STREAM OFF command
1435         */
1436        spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
1437
1438        if (ccdc->lsc.state == LSC_STATE_STOPPING)
1439                ccdc->lsc.state = LSC_STATE_STOPPED;
1440
1441        if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_LSC_DONE))
1442                goto done;
1443
1444        if (ccdc->lsc.state != LSC_STATE_RECONFIG)
1445                goto done;
1446
1447        /* LSC is in STOPPING state, change to the new state */
1448        ccdc->lsc.state = LSC_STATE_STOPPED;
1449
1450        /* This is an exception. Start of frame and LSC_DONE interrupt
1451         * have been received on the same time. Skip this event and wait
1452         * for better times.
1453         */
1454        if (events & IRQ0STATUS_HS_VS_IRQ)
1455                goto done;
1456
1457        /* The LSC engine is stopped at this point. Enable it if there's a
1458         * pending request.
1459         */
1460        if (ccdc->lsc.request == NULL)
1461                goto done;
1462
1463        ccdc_lsc_enable(ccdc);
1464
1465done:
1466        spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
1467}
1468
1469static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc)
1470{
1471        struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
1472        struct isp_device *isp = to_isp_device(ccdc);
1473        struct isp_buffer *buffer;
1474        int restart = 0;
1475
1476        /* The CCDC generates VD0 interrupts even when disabled (the datasheet
1477         * doesn't explicitly state if that's supposed to happen or not, so it
1478         * can be considered as a hardware bug or as a feature, but we have to
1479         * deal with it anyway). Disabling the CCDC when no buffer is available
1480         * would thus not be enough, we need to handle the situation explicitly.
1481         */
1482        if (list_empty(&ccdc->video_out.dmaqueue))
1483                goto done;
1484
1485        /* We're in continuous mode, and memory writes were disabled due to a
1486         * buffer underrun. Reenable them now that we have a buffer. The buffer
1487         * address has been set in ccdc_video_queue.
1488         */
1489        if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS && ccdc->underrun) {
1490                restart = 1;
1491                ccdc->underrun = 0;
1492                goto done;
1493        }
1494
1495        if (ccdc_sbl_wait_idle(ccdc, 1000)) {
1496                dev_info(isp->dev, "CCDC won't become idle!\n");
1497                goto done;
1498        }
1499
1500        buffer = omap3isp_video_buffer_next(&ccdc->video_out, ccdc->error);
1501        if (buffer != NULL) {
1502                ccdc_set_outaddr(ccdc, buffer->isp_addr);
1503                restart = 1;
1504        }
1505
1506        pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
1507
1508        if (ccdc->state == ISP_PIPELINE_STREAM_SINGLESHOT &&
1509            isp_pipeline_ready(pipe))
1510                omap3isp_pipeline_set_stream(pipe,
1511                                        ISP_PIPELINE_STREAM_SINGLESHOT);
1512
1513done:
1514        ccdc->error = 0;
1515        return restart;
1516}
1517
1518/*
1519 * ccdc_vd0_isr - Handle VD0 event
1520 * @ccdc: Pointer to ISP CCDC device.
1521 *
1522 * Executes LSC deferred enablement before next frame starts.
1523 */
1524static void ccdc_vd0_isr(struct isp_ccdc_device *ccdc)
1525{
1526        unsigned long flags;
1527        int restart = 0;
1528
1529        if (ccdc->output & CCDC_OUTPUT_MEMORY)
1530                restart = ccdc_isr_buffer(ccdc);
1531
1532        spin_lock_irqsave(&ccdc->lock, flags);
1533        if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_VD0)) {
1534                spin_unlock_irqrestore(&ccdc->lock, flags);
1535                return;
1536        }
1537
1538        if (!ccdc->shadow_update)
1539                ccdc_apply_controls(ccdc);
1540        spin_unlock_irqrestore(&ccdc->lock, flags);
1541
1542        if (restart)
1543                ccdc_enable(ccdc);
1544}
1545
1546/*
1547 * ccdc_vd1_isr - Handle VD1 event
1548 * @ccdc: Pointer to ISP CCDC device.
1549 */
1550static void ccdc_vd1_isr(struct isp_ccdc_device *ccdc)
1551{
1552        unsigned long flags;
1553
1554        spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
1555
1556        /*
1557         * Depending on the CCDC pipeline state, CCDC stopping should be
1558         * handled differently. In SINGLESHOT we emulate an internal CCDC
1559         * stopping because the CCDC hw works only in continuous mode.
1560         * When CONTINUOUS pipeline state is used and the CCDC writes it's
1561         * data to memory the CCDC and LSC are stopped immediately but
1562         * without change the CCDC stopping state machine. The CCDC
1563         * stopping state machine should be used only when user request
1564         * for stopping is received (SINGLESHOT is an exeption).
1565         */
1566        switch (ccdc->state) {
1567        case ISP_PIPELINE_STREAM_SINGLESHOT:
1568                ccdc->stopping = CCDC_STOP_REQUEST;
1569                break;
1570
1571        case ISP_PIPELINE_STREAM_CONTINUOUS:
1572                if (ccdc->output & CCDC_OUTPUT_MEMORY) {
1573                        if (ccdc->lsc.state != LSC_STATE_STOPPED)
1574                                __ccdc_lsc_enable(ccdc, 0);
1575                        __ccdc_enable(ccdc, 0);
1576                }
1577                break;
1578
1579        case ISP_PIPELINE_STREAM_STOPPED:
1580                break;
1581        }
1582
1583        if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_VD1))
1584                goto done;
1585
1586        if (ccdc->lsc.request == NULL)
1587                goto done;
1588
1589        /*
1590         * LSC need to be reconfigured. Stop it here and on next LSC_DONE IRQ
1591         * do the appropriate changes in registers
1592         */
1593        if (ccdc->lsc.state == LSC_STATE_RUNNING) {
1594                __ccdc_lsc_enable(ccdc, 0);
1595                ccdc->lsc.state = LSC_STATE_RECONFIG;
1596                goto done;
1597        }
1598
1599        /* LSC has been in STOPPED state, enable it */
1600        if (ccdc->lsc.state == LSC_STATE_STOPPED)
1601                ccdc_lsc_enable(ccdc);
1602
1603done:
1604        spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
1605}
1606
1607/*
1608 * omap3isp_ccdc_isr - Configure CCDC during interframe time.
1609 * @ccdc: Pointer to ISP CCDC device.
1610 * @events: CCDC events
1611 */
1612int omap3isp_ccdc_isr(struct isp_ccdc_device *ccdc, u32 events)
1613{
1614        if (ccdc->state == ISP_PIPELINE_STREAM_STOPPED)
1615                return 0;
1616
1617        if (events & IRQ0STATUS_CCDC_VD1_IRQ)
1618                ccdc_vd1_isr(ccdc);
1619
1620        ccdc_lsc_isr(ccdc, events);
1621
1622        if (events & IRQ0STATUS_CCDC_VD0_IRQ)
1623                ccdc_vd0_isr(ccdc);
1624
1625        if (events & IRQ0STATUS_HS_VS_IRQ)
1626                ccdc_hs_vs_isr(ccdc);
1627
1628        return 0;
1629}
1630
1631/* -----------------------------------------------------------------------------
1632 * ISP video operations
1633 */
1634
1635static int ccdc_video_queue(struct isp_video *video, struct isp_buffer *buffer)
1636{
1637        struct isp_ccdc_device *ccdc = &video->isp->isp_ccdc;
1638
1639        if (!(ccdc->output & CCDC_OUTPUT_MEMORY))
1640                return -ENODEV;
1641
1642        ccdc_set_outaddr(ccdc, buffer->isp_addr);
1643
1644        /* We now have a buffer queued on the output, restart the pipeline
1645         * on the next CCDC interrupt if running in continuous mode (or when
1646         * starting the stream).
1647         */
1648        ccdc->underrun = 1;
1649
1650        return 0;
1651}
1652
1653static const struct isp_video_operations ccdc_video_ops = {
1654        .queue = ccdc_video_queue,
1655};
1656
1657/* -----------------------------------------------------------------------------
1658 * V4L2 subdev operations
1659 */
1660
1661/*
1662 * ccdc_ioctl - CCDC module private ioctl's
1663 * @sd: ISP CCDC V4L2 subdevice
1664 * @cmd: ioctl command
1665 * @arg: ioctl argument
1666 *
1667 * Return 0 on success or a negative error code otherwise.
1668 */
1669static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
1670{
1671        struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
1672        int ret;
1673
1674        switch (cmd) {
1675        case VIDIOC_OMAP3ISP_CCDC_CFG:
1676                mutex_lock(&ccdc->ioctl_lock);
1677                ret = ccdc_config(ccdc, arg);
1678                mutex_unlock(&ccdc->ioctl_lock);
1679                break;
1680
1681        default:
1682                return -ENOIOCTLCMD;
1683        }
1684
1685        return ret;
1686}
1687
1688static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
1689                                struct v4l2_event_subscription *sub)
1690{
1691        if (sub->type != V4L2_EVENT_OMAP3ISP_HS_VS)
1692                return -EINVAL;
1693
1694        return v4l2_event_subscribe(fh, sub);
1695}
1696
1697static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
1698                                  struct v4l2_event_subscription *sub)
1699{
1700        return v4l2_event_unsubscribe(fh, sub);
1701}
1702
1703/*
1704 * ccdc_set_stream - Enable/Disable streaming on the CCDC module
1705 * @sd: ISP CCDC V4L2 subdevice
1706 * @enable: Enable/disable stream
1707 *
1708 * When writing to memory, the CCDC hardware can't be enabled without a memory
1709 * buffer to write to. As the s_stream operation is called in response to a
1710 * STREAMON call without any buffer queued yet, just update the enabled field
1711 * and return immediately. The CCDC will be enabled in ccdc_isr_buffer().
1712 *
1713 * When not writing to memory enable the CCDC immediately.
1714 */
1715static int ccdc_set_stream(struct v4l2_subdev *sd, int enable)
1716{
1717        struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
1718        struct isp_device *isp = to_isp_device(ccdc);
1719        int ret = 0;
1720
1721        if (ccdc->state == ISP_PIPELINE_STREAM_STOPPED) {
1722                if (enable == ISP_PIPELINE_STREAM_STOPPED)
1723                        return 0;
1724
1725                omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_CCDC);
1726                isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
1727                            ISPCCDC_CFG_VDLC);
1728
1729                ccdc_configure(ccdc);
1730
1731                /* TODO: Don't configure the video port if all of its output
1732                 * links are inactive.
1733                 */
1734                ccdc_config_vp(ccdc);
1735                ccdc_enable_vp(ccdc, 1);
1736                ccdc->error = 0;
1737                ccdc_print_status(ccdc);
1738        }
1739
1740        switch (enable) {
1741        case ISP_PIPELINE_STREAM_CONTINUOUS:
1742                if (ccdc->output & CCDC_OUTPUT_MEMORY)
1743                        omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_WRITE);
1744
1745                if (ccdc->underrun || !(ccdc->output & CCDC_OUTPUT_MEMORY))
1746                        ccdc_enable(ccdc);
1747
1748                ccdc->underrun = 0;
1749                break;
1750
1751        case ISP_PIPELINE_STREAM_SINGLESHOT:
1752                if (ccdc->output & CCDC_OUTPUT_MEMORY &&
1753                    ccdc->state != ISP_PIPELINE_STREAM_SINGLESHOT)
1754                        omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_WRITE);
1755
1756                ccdc_enable(ccdc);
1757                break;
1758
1759        case ISP_PIPELINE_STREAM_STOPPED:
1760                ret = ccdc_disable(ccdc);
1761                if (ccdc->output & CCDC_OUTPUT_MEMORY)
1762                        omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CCDC_WRITE);
1763                omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_CCDC);
1764                ccdc->underrun = 0;
1765                break;
1766        }
1767
1768        ccdc->state = enable;
1769        return ret;
1770}
1771
1772static struct v4l2_mbus_framefmt *
1773__ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
1774                  unsigned int pad, enum v4l2_subdev_format_whence which)
1775{
1776        if (which == V4L2_SUBDEV_FORMAT_TRY)
1777                return v4l2_subdev_get_try_format(fh, pad);
1778        else
1779                return &ccdc->formats[pad];
1780}
1781
1782/*
1783 * ccdc_try_format - Try video format on a pad
1784 * @ccdc: ISP CCDC device
1785 * @fh : V4L2 subdev file handle
1786 * @pad: Pad number
1787 * @fmt: Format
1788 */
1789static void
1790ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
1791                unsigned int pad, struct v4l2_mbus_framefmt *fmt,
1792                enum v4l2_subdev_format_whence which)
1793{
1794        struct v4l2_mbus_framefmt *format;
1795        const struct isp_format_info *info;
1796        unsigned int width = fmt->width;
1797        unsigned int height = fmt->height;
1798        unsigned int i;
1799
1800        switch (pad) {
1801        case CCDC_PAD_SINK:
1802                /* TODO: If the CCDC output formatter pad is connected directly
1803                 * to the resizer, only YUV formats can be used.
1804                 */
1805                for (i = 0; i < ARRAY_SIZE(ccdc_fmts); i++) {
1806                        if (fmt->code == ccdc_fmts[i])
1807                                break;
1808                }
1809
1810                /* If not found, use SGRBG10 as default */
1811                if (i >= ARRAY_SIZE(ccdc_fmts))
1812                        fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
1813
1814                /* Clamp the input size. */
1815                fmt->width = clamp_t(u32, width, 32, 4096);
1816                fmt->height = clamp_t(u32, height, 32, 4096);
1817                break;
1818
1819        case CCDC_PAD_SOURCE_OF:
1820                format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
1821                memcpy(fmt, format, sizeof(*fmt));
1822
1823                /* The data formatter truncates the number of horizontal output
1824                 * pixels to a multiple of 16. To avoid clipping data, allow
1825                 * callers to request an output size bigger than the input size
1826                 * up to the nearest multiple of 16.
1827                 */
1828                fmt->width = clamp_t(u32, width, 32, (fmt->width + 15) & ~15);
1829                fmt->width &= ~15;
1830                fmt->height = clamp_t(u32, height, 32, fmt->height);
1831                break;
1832
1833        case CCDC_PAD_SOURCE_VP:
1834                format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
1835                memcpy(fmt, format, sizeof(*fmt));
1836
1837                /* The video port interface truncates the data to 10 bits. */
1838                info = omap3isp_video_format_info(fmt->code);
1839                fmt->code = info->truncated;
1840
1841                /* The number of lines that can be clocked out from the video
1842                 * port output must be at least one line less than the number
1843                 * of input lines.
1844                 */
1845                fmt->width = clamp_t(u32, width, 32, fmt->width);
1846                fmt->height = clamp_t(u32, height, 32, fmt->height - 1);
1847                break;
1848        }
1849
1850        /* Data is written to memory unpacked, each 10-bit or 12-bit pixel is
1851         * stored on 2 bytes.
1852         */
1853        fmt->colorspace = V4L2_COLORSPACE_SRGB;
1854        fmt->field = V4L2_FIELD_NONE;
1855}
1856
1857/*
1858 * ccdc_enum_mbus_code - Handle pixel format enumeration
1859 * @sd     : pointer to v4l2 subdev structure
1860 * @fh : V4L2 subdev file handle
1861 * @code   : pointer to v4l2_subdev_mbus_code_enum structure
1862 * return -EINVAL or zero on success
1863 */
1864static int ccdc_enum_mbus_code(struct v4l2_subdev *sd,
1865                               struct v4l2_subdev_fh *fh,
1866                               struct v4l2_subdev_mbus_code_enum *code)
1867{
1868        struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
1869        struct v4l2_mbus_framefmt *format;
1870
1871        switch (code->pad) {
1872        case CCDC_PAD_SINK:
1873                if (code->index >= ARRAY_SIZE(ccdc_fmts))
1874                        return -EINVAL;
1875
1876                code->code = ccdc_fmts[code->index];
1877                break;
1878
1879        case CCDC_PAD_SOURCE_OF:
1880        case CCDC_PAD_SOURCE_VP:
1881                /* No format conversion inside CCDC */
1882                if (code->index != 0)
1883                        return -EINVAL;
1884
1885                format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK,
1886                                           V4L2_SUBDEV_FORMAT_TRY);
1887
1888                code->code = format->code;
1889                break;
1890
1891        default:
1892                return -EINVAL;
1893        }
1894
1895        return 0;
1896}
1897
1898static int ccdc_enum_frame_size(struct v4l2_subdev *sd,
1899                                struct v4l2_subdev_fh *fh,
1900                                struct v4l2_subdev_frame_size_enum *fse)
1901{
1902        struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
1903        struct v4l2_mbus_framefmt format;
1904
1905        if (fse->index != 0)
1906                return -EINVAL;
1907
1908        format.code = fse->code;
1909        format.width = 1;
1910        format.height = 1;
1911        ccdc_try_format(ccdc, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
1912        fse->min_width = format.width;
1913        fse->min_height = format.height;
1914
1915        if (format.code != fse->code)
1916                return -EINVAL;
1917
1918        format.code = fse->code;
1919        format.width = -1;
1920        format.height = -1;
1921        ccdc_try_format(ccdc, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
1922        fse->max_width = format.width;
1923        fse->max_height = format.height;
1924
1925        return 0;
1926}
1927
1928/*
1929 * ccdc_get_format - Retrieve the video format on a pad
1930 * @sd : ISP CCDC V4L2 subdevice
1931 * @fh : V4L2 subdev file handle
1932 * @fmt: Format
1933 *
1934 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
1935 * to the format type.
1936 */
1937static int ccdc_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1938                           struct v4l2_subdev_format *fmt)
1939{
1940        struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
1941        struct v4l2_mbus_framefmt *format;
1942
1943        format = __ccdc_get_format(ccdc, fh, fmt->pad, fmt->which);
1944        if (format == NULL)
1945                return -EINVAL;
1946
1947        fmt->format = *format;
1948        return 0;
1949}
1950
1951/*
1952 * ccdc_set_format - Set the video format on a pad
1953 * @sd : ISP CCDC V4L2 subdevice
1954 * @fh : V4L2 subdev file handle
1955 * @fmt: Format
1956 *
1957 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
1958 * to the format type.
1959 */
1960static int ccdc_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1961                           struct v4l2_subdev_format *fmt)
1962{
1963        struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
1964        struct v4l2_mbus_framefmt *format;
1965
1966        format = __ccdc_get_format(ccdc, fh, fmt->pad, fmt->which);
1967        if (format == NULL)
1968                return -EINVAL;
1969
1970        ccdc_try_format(ccdc, fh, fmt->pad, &fmt->format, fmt->which);
1971        *format = fmt->format;
1972
1973        /* Propagate the format from sink to source */
1974        if (fmt->pad == CCDC_PAD_SINK) {
1975                format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SOURCE_OF,
1976                                           fmt->which);
1977                *format = fmt->format;
1978                ccdc_try_format(ccdc, fh, CCDC_PAD_SOURCE_OF, format,
1979                                fmt->which);
1980
1981                format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SOURCE_VP,
1982                                           fmt->which);
1983                *format = fmt->format;
1984                ccdc_try_format(ccdc, fh, CCDC_PAD_SOURCE_VP, format,
1985                                fmt->which);
1986        }
1987
1988        return 0;
1989}
1990
1991/*
1992 * ccdc_init_formats - Initialize formats on all pads
1993 * @sd: ISP CCDC V4L2 subdevice
1994 * @fh: V4L2 subdev file handle
1995 *
1996 * Initialize all pad formats with default values. If fh is not NULL, try
1997 * formats are initialized on the file handle. Otherwise active formats are
1998 * initialized on the device.
1999 */
2000static int ccdc_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
2001{
2002        struct v4l2_subdev_format format;
2003
2004        memset(&format, 0, sizeof(format));
2005        format.pad = CCDC_PAD_SINK;
2006        format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
2007        format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
2008        format.format.width = 4096;
2009        format.format.height = 4096;
2010        ccdc_set_format(sd, fh, &format);
2011
2012        return 0;
2013}
2014
2015/* V4L2 subdev core operations */
2016static const struct v4l2_subdev_core_ops ccdc_v4l2_core_ops = {
2017        .ioctl = ccdc_ioctl,
2018        .subscribe_event = ccdc_subscribe_event,
2019        .unsubscribe_event = ccdc_unsubscribe_event,
2020};
2021
2022/* V4L2 subdev video operations */
2023static const struct v4l2_subdev_video_ops ccdc_v4l2_video_ops = {
2024        .s_stream = ccdc_set_stream,
2025};
2026
2027/* V4L2 subdev pad operations */
2028static const struct v4l2_subdev_pad_ops ccdc_v4l2_pad_ops = {
2029        .enum_mbus_code = ccdc_enum_mbus_code,
2030        .enum_frame_size = ccdc_enum_frame_size,
2031        .get_fmt = ccdc_get_format,
2032        .set_fmt = ccdc_set_format,
2033};
2034
2035/* V4L2 subdev operations */
2036static const struct v4l2_subdev_ops ccdc_v4l2_ops = {
2037        .core = &ccdc_v4l2_core_ops,
2038        .video = &ccdc_v4l2_video_ops,
2039        .pad = &ccdc_v4l2_pad_ops,
2040};
2041
2042/* V4L2 subdev internal operations */
2043static const struct v4l2_subdev_internal_ops ccdc_v4l2_internal_ops = {
2044        .open = ccdc_init_formats,
2045};
2046
2047/* -----------------------------------------------------------------------------
2048 * Media entity operations
2049 */
2050
2051/*
2052 * ccdc_link_setup - Setup CCDC connections
2053 * @entity: CCDC media entity
2054 * @local: Pad at the local end of the link
2055 * @remote: Pad at the remote end of the link
2056 * @flags: Link flags
2057 *
2058 * return -EINVAL or zero on success
2059 */
2060static int ccdc_link_setup(struct media_entity *entity,
2061                           const struct media_pad *local,
2062                           const struct media_pad *remote, u32 flags)
2063{
2064        struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
2065        struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
2066        struct isp_device *isp = to_isp_device(ccdc);
2067
2068        switch (local->index | media_entity_type(remote->entity)) {
2069        case CCDC_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
2070                /* Read from the sensor (parallel interface), CCP2, CSI2a or
2071                 * CSI2c.
2072                 */
2073                if (!(flags & MEDIA_LNK_FL_ENABLED)) {
2074                        ccdc->input = CCDC_INPUT_NONE;
2075                        break;
2076                }
2077
2078                if (ccdc->input != CCDC_INPUT_NONE)
2079                        return -EBUSY;
2080
2081                if (remote->entity == &isp->isp_ccp2.subdev.entity)
2082                        ccdc->input = CCDC_INPUT_CCP2B;
2083                else if (remote->entity == &isp->isp_csi2a.subdev.entity)
2084                        ccdc->input = CCDC_INPUT_CSI2A;
2085                else if (remote->entity == &isp->isp_csi2c.subdev.entity)
2086                        ccdc->input = CCDC_INPUT_CSI2C;
2087                else
2088                        ccdc->input = CCDC_INPUT_PARALLEL;
2089
2090                break;
2091
2092        /*
2093         * The ISP core doesn't support pipelines with multiple video outputs.
2094         * Revisit this when it will be implemented, and return -EBUSY for now.
2095         */
2096
2097        case CCDC_PAD_SOURCE_VP | MEDIA_ENT_T_V4L2_SUBDEV:
2098                /* Write to preview engine, histogram and H3A. When none of
2099                 * those links are active, the video port can be disabled.
2100                 */
2101                if (flags & MEDIA_LNK_FL_ENABLED) {
2102                        if (ccdc->output & ~CCDC_OUTPUT_PREVIEW)
2103                                return -EBUSY;
2104                        ccdc->output |= CCDC_OUTPUT_PREVIEW;
2105                } else {
2106                        ccdc->output &= ~CCDC_OUTPUT_PREVIEW;
2107                }
2108                break;
2109
2110        case CCDC_PAD_SOURCE_OF | MEDIA_ENT_T_DEVNODE:
2111                /* Write to memory */
2112                if (flags & MEDIA_LNK_FL_ENABLED) {
2113                        if (ccdc->output & ~CCDC_OUTPUT_MEMORY)
2114                                return -EBUSY;
2115                        ccdc->output |= CCDC_OUTPUT_MEMORY;
2116                } else {
2117                        ccdc->output &= ~CCDC_OUTPUT_MEMORY;
2118                }
2119                break;
2120
2121        case CCDC_PAD_SOURCE_OF | MEDIA_ENT_T_V4L2_SUBDEV:
2122                /* Write to resizer */
2123                if (flags & MEDIA_LNK_FL_ENABLED) {
2124                        if (ccdc->output & ~CCDC_OUTPUT_RESIZER)
2125                                return -EBUSY;
2126                        ccdc->output |= CCDC_OUTPUT_RESIZER;
2127                } else {
2128                        ccdc->output &= ~CCDC_OUTPUT_RESIZER;
2129                }
2130                break;
2131
2132        default:
2133                return -EINVAL;
2134        }
2135
2136        return 0;
2137}
2138
2139/* media operations */
2140static const struct media_entity_operations ccdc_media_ops = {
2141        .link_setup = ccdc_link_setup,
2142};
2143
2144/*
2145 * ccdc_init_entities - Initialize V4L2 subdev and media entity
2146 * @ccdc: ISP CCDC module
2147 *
2148 * Return 0 on success and a negative error code on failure.
2149 */
2150static int ccdc_init_entities(struct isp_ccdc_device *ccdc)
2151{
2152        struct v4l2_subdev *sd = &ccdc->subdev;
2153        struct media_pad *pads = ccdc->pads;
2154        struct media_entity *me = &sd->entity;
2155        int ret;
2156
2157        ccdc->input = CCDC_INPUT_NONE;
2158
2159        v4l2_subdev_init(sd, &ccdc_v4l2_ops);
2160        sd->internal_ops = &ccdc_v4l2_internal_ops;
2161        strlcpy(sd->name, "OMAP3 ISP CCDC", sizeof(sd->name));
2162        sd->grp_id = 1 << 16;   /* group ID for isp subdevs */
2163        v4l2_set_subdevdata(sd, ccdc);
2164        sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
2165        sd->nevents = OMAP3ISP_CCDC_NEVENTS;
2166
2167        pads[CCDC_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
2168        pads[CCDC_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE;
2169        pads[CCDC_PAD_SOURCE_OF].flags = MEDIA_PAD_FL_SOURCE;
2170
2171        me->ops = &ccdc_media_ops;
2172        ret = media_entity_init(me, CCDC_PADS_NUM, pads, 0);
2173        if (ret < 0)
2174                return ret;
2175
2176        ccdc_init_formats(sd, NULL);
2177
2178        ccdc->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2179        ccdc->video_out.ops = &ccdc_video_ops;
2180        ccdc->video_out.isp = to_isp_device(ccdc);
2181        ccdc->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
2182        ccdc->video_out.bpl_alignment = 32;
2183
2184        ret = omap3isp_video_init(&ccdc->video_out, "CCDC");
2185        if (ret < 0)
2186                return ret;
2187
2188        /* Connect the CCDC subdev to the video node. */
2189        ret = media_entity_create_link(&ccdc->subdev.entity, CCDC_PAD_SOURCE_OF,
2190                        &ccdc->video_out.video.entity, 0, 0);
2191        if (ret < 0)
2192                return ret;
2193
2194        return 0;
2195}
2196
2197void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc)
2198{
2199        media_entity_cleanup(&ccdc->subdev.entity);
2200
2201        v4l2_device_unregister_subdev(&ccdc->subdev);
2202        omap3isp_video_unregister(&ccdc->video_out);
2203}
2204
2205int omap3isp_ccdc_register_entities(struct isp_ccdc_device *ccdc,
2206        struct v4l2_device *vdev)
2207{
2208        int ret;
2209
2210        /* Register the subdev and video node. */
2211        ret = v4l2_device_register_subdev(vdev, &ccdc->subdev);
2212        if (ret < 0)
2213                goto error;
2214
2215        ret = omap3isp_video_register(&ccdc->video_out, vdev);
2216        if (ret < 0)
2217                goto error;
2218
2219        return 0;
2220
2221error:
2222        omap3isp_ccdc_unregister_entities(ccdc);
2223        return ret;
2224}
2225
2226/* -----------------------------------------------------------------------------
2227 * ISP CCDC initialisation and cleanup
2228 */
2229
2230/*
2231 * omap3isp_ccdc_init - CCDC module initialization.
2232 * @dev: Device pointer specific to the OMAP3 ISP.
2233 *
2234 * TODO: Get the initialisation values from platform data.
2235 *
2236 * Return 0 on success or a negative error code otherwise.
2237 */
2238int omap3isp_ccdc_init(struct isp_device *isp)
2239{
2240        struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
2241
2242        spin_lock_init(&ccdc->lock);
2243        init_waitqueue_head(&ccdc->wait);
2244        mutex_init(&ccdc->ioctl_lock);
2245
2246        ccdc->stopping = CCDC_STOP_NOT_REQUESTED;
2247
2248        INIT_WORK(&ccdc->lsc.table_work, ccdc_lsc_free_table_work);
2249        ccdc->lsc.state = LSC_STATE_STOPPED;
2250        INIT_LIST_HEAD(&ccdc->lsc.free_queue);
2251        spin_lock_init(&ccdc->lsc.req_lock);
2252
2253        ccdc->syncif.ccdc_mastermode = 0;
2254        ccdc->syncif.datapol = 0;
2255        ccdc->syncif.datsz = 0;
2256        ccdc->syncif.fldmode = 0;
2257        ccdc->syncif.fldout = 0;
2258        ccdc->syncif.fldpol = 0;
2259        ccdc->syncif.fldstat = 0;
2260        ccdc->syncif.hdpol = 0;
2261        ccdc->syncif.vdpol = 0;
2262
2263        ccdc->clamp.oblen = 0;
2264        ccdc->clamp.dcsubval = 0;
2265
2266        ccdc->vpcfg.pixelclk = 0;
2267
2268        ccdc->update = OMAP3ISP_CCDC_BLCLAMP;
2269        ccdc_apply_controls(ccdc);
2270
2271        return ccdc_init_entities(ccdc);
2272}
2273
2274/*
2275 * omap3isp_ccdc_cleanup - CCDC module cleanup.
2276 * @dev: Device pointer specific to the OMAP3 ISP.
2277 */
2278void omap3isp_ccdc_cleanup(struct isp_device *isp)
2279{
2280        struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
2281
2282        /* Free LSC requests. As the CCDC is stopped there's no active request,
2283         * so only the pending request and the free queue need to be handled.
2284         */
2285        ccdc_lsc_free_request(ccdc, ccdc->lsc.request);
2286        cancel_work_sync(&ccdc->lsc.table_work);
2287        ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
2288
2289        if (ccdc->fpc.fpcaddr != 0)
2290                iommu_vfree(isp->iommu, ccdc->fpc.fpcaddr);
2291}
2292