linux/drivers/media/platform/qcom/camss/camss-vfe.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * camss-vfe.c
   4 *
   5 * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module
   6 *
   7 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
   8 * Copyright (C) 2015-2018 Linaro Ltd.
   9 */
  10#include <linux/clk.h>
  11#include <linux/completion.h>
  12#include <linux/interrupt.h>
  13#include <linux/iommu.h>
  14#include <linux/mutex.h>
  15#include <linux/of.h>
  16#include <linux/platform_device.h>
  17#include <linux/pm_runtime.h>
  18#include <linux/spinlock_types.h>
  19#include <linux/spinlock.h>
  20#include <media/media-entity.h>
  21#include <media/v4l2-device.h>
  22#include <media/v4l2-subdev.h>
  23
  24#include "camss-vfe.h"
  25#include "camss.h"
  26
  27#define MSM_VFE_NAME "msm_vfe"
  28
  29/* VFE reset timeout */
  30#define VFE_RESET_TIMEOUT_MS 50
  31
  32#define SCALER_RATIO_MAX 16
  33
  34struct vfe_format {
  35        u32 code;
  36        u8 bpp;
  37};
  38
  39static const struct vfe_format formats_rdi_8x16[] = {
  40        { MEDIA_BUS_FMT_UYVY8_2X8, 8 },
  41        { MEDIA_BUS_FMT_VYUY8_2X8, 8 },
  42        { MEDIA_BUS_FMT_YUYV8_2X8, 8 },
  43        { MEDIA_BUS_FMT_YVYU8_2X8, 8 },
  44        { MEDIA_BUS_FMT_SBGGR8_1X8, 8 },
  45        { MEDIA_BUS_FMT_SGBRG8_1X8, 8 },
  46        { MEDIA_BUS_FMT_SGRBG8_1X8, 8 },
  47        { MEDIA_BUS_FMT_SRGGB8_1X8, 8 },
  48        { MEDIA_BUS_FMT_SBGGR10_1X10, 10 },
  49        { MEDIA_BUS_FMT_SGBRG10_1X10, 10 },
  50        { MEDIA_BUS_FMT_SGRBG10_1X10, 10 },
  51        { MEDIA_BUS_FMT_SRGGB10_1X10, 10 },
  52        { MEDIA_BUS_FMT_SBGGR12_1X12, 12 },
  53        { MEDIA_BUS_FMT_SGBRG12_1X12, 12 },
  54        { MEDIA_BUS_FMT_SGRBG12_1X12, 12 },
  55        { MEDIA_BUS_FMT_SRGGB12_1X12, 12 },
  56        { MEDIA_BUS_FMT_Y10_1X10, 10 },
  57};
  58
  59static const struct vfe_format formats_pix_8x16[] = {
  60        { MEDIA_BUS_FMT_UYVY8_2X8, 8 },
  61        { MEDIA_BUS_FMT_VYUY8_2X8, 8 },
  62        { MEDIA_BUS_FMT_YUYV8_2X8, 8 },
  63        { MEDIA_BUS_FMT_YVYU8_2X8, 8 },
  64};
  65
  66static const struct vfe_format formats_rdi_8x96[] = {
  67        { MEDIA_BUS_FMT_UYVY8_2X8, 8 },
  68        { MEDIA_BUS_FMT_VYUY8_2X8, 8 },
  69        { MEDIA_BUS_FMT_YUYV8_2X8, 8 },
  70        { MEDIA_BUS_FMT_YVYU8_2X8, 8 },
  71        { MEDIA_BUS_FMT_SBGGR8_1X8, 8 },
  72        { MEDIA_BUS_FMT_SGBRG8_1X8, 8 },
  73        { MEDIA_BUS_FMT_SGRBG8_1X8, 8 },
  74        { MEDIA_BUS_FMT_SRGGB8_1X8, 8 },
  75        { MEDIA_BUS_FMT_SBGGR10_1X10, 10 },
  76        { MEDIA_BUS_FMT_SGBRG10_1X10, 10 },
  77        { MEDIA_BUS_FMT_SGRBG10_1X10, 10 },
  78        { MEDIA_BUS_FMT_SRGGB10_1X10, 10 },
  79        { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 16 },
  80        { MEDIA_BUS_FMT_SBGGR12_1X12, 12 },
  81        { MEDIA_BUS_FMT_SGBRG12_1X12, 12 },
  82        { MEDIA_BUS_FMT_SGRBG12_1X12, 12 },
  83        { MEDIA_BUS_FMT_SRGGB12_1X12, 12 },
  84        { MEDIA_BUS_FMT_SBGGR14_1X14, 14 },
  85        { MEDIA_BUS_FMT_SGBRG14_1X14, 14 },
  86        { MEDIA_BUS_FMT_SGRBG14_1X14, 14 },
  87        { MEDIA_BUS_FMT_SRGGB14_1X14, 14 },
  88        { MEDIA_BUS_FMT_Y10_1X10, 10 },
  89        { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 16 },
  90};
  91
  92static const struct vfe_format formats_pix_8x96[] = {
  93        { MEDIA_BUS_FMT_UYVY8_2X8, 8 },
  94        { MEDIA_BUS_FMT_VYUY8_2X8, 8 },
  95        { MEDIA_BUS_FMT_YUYV8_2X8, 8 },
  96        { MEDIA_BUS_FMT_YVYU8_2X8, 8 },
  97};
  98
  99static const struct vfe_format formats_rdi_845[] = {
 100        { MEDIA_BUS_FMT_UYVY8_2X8, 8 },
 101        { MEDIA_BUS_FMT_VYUY8_2X8, 8 },
 102        { MEDIA_BUS_FMT_YUYV8_2X8, 8 },
 103        { MEDIA_BUS_FMT_YVYU8_2X8, 8 },
 104        { MEDIA_BUS_FMT_SBGGR8_1X8, 8 },
 105        { MEDIA_BUS_FMT_SGBRG8_1X8, 8 },
 106        { MEDIA_BUS_FMT_SGRBG8_1X8, 8 },
 107        { MEDIA_BUS_FMT_SRGGB8_1X8, 8 },
 108        { MEDIA_BUS_FMT_SBGGR10_1X10, 10 },
 109        { MEDIA_BUS_FMT_SGBRG10_1X10, 10 },
 110        { MEDIA_BUS_FMT_SGRBG10_1X10, 10 },
 111        { MEDIA_BUS_FMT_SRGGB10_1X10, 10 },
 112        { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 16 },
 113        { MEDIA_BUS_FMT_SBGGR12_1X12, 12 },
 114        { MEDIA_BUS_FMT_SGBRG12_1X12, 12 },
 115        { MEDIA_BUS_FMT_SGRBG12_1X12, 12 },
 116        { MEDIA_BUS_FMT_SRGGB12_1X12, 12 },
 117        { MEDIA_BUS_FMT_SBGGR14_1X14, 14 },
 118        { MEDIA_BUS_FMT_SGBRG14_1X14, 14 },
 119        { MEDIA_BUS_FMT_SGRBG14_1X14, 14 },
 120        { MEDIA_BUS_FMT_SRGGB14_1X14, 14 },
 121        { MEDIA_BUS_FMT_Y10_1X10, 10 },
 122        { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 16 },
 123};
 124
 125/*
 126 * vfe_get_bpp - map media bus format to bits per pixel
 127 * @formats: supported media bus formats array
 128 * @nformats: size of @formats array
 129 * @code: media bus format code
 130 *
 131 * Return number of bits per pixel
 132 */
 133static u8 vfe_get_bpp(const struct vfe_format *formats,
 134                      unsigned int nformats, u32 code)
 135{
 136        unsigned int i;
 137
 138        for (i = 0; i < nformats; i++)
 139                if (code == formats[i].code)
 140                        return formats[i].bpp;
 141
 142        WARN(1, "Unknown format\n");
 143
 144        return formats[0].bpp;
 145}
 146
 147static u32 vfe_find_code(u32 *code, unsigned int n_code,
 148                         unsigned int index, u32 req_code)
 149{
 150        int i;
 151
 152        if (!req_code && (index >= n_code))
 153                return 0;
 154
 155        for (i = 0; i < n_code; i++)
 156                if (req_code) {
 157                        if (req_code == code[i])
 158                                return req_code;
 159                } else {
 160                        if (i == index)
 161                                return code[i];
 162                }
 163
 164        return code[0];
 165}
 166
 167static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
 168                            unsigned int index, u32 src_req_code)
 169{
 170        struct vfe_device *vfe = to_vfe(line);
 171
 172        if (vfe->camss->version == CAMSS_8x16)
 173                switch (sink_code) {
 174                case MEDIA_BUS_FMT_YUYV8_2X8:
 175                {
 176                        u32 src_code[] = {
 177                                MEDIA_BUS_FMT_YUYV8_2X8,
 178                                MEDIA_BUS_FMT_YUYV8_1_5X8,
 179                        };
 180
 181                        return vfe_find_code(src_code, ARRAY_SIZE(src_code),
 182                                             index, src_req_code);
 183                }
 184                case MEDIA_BUS_FMT_YVYU8_2X8:
 185                {
 186                        u32 src_code[] = {
 187                                MEDIA_BUS_FMT_YVYU8_2X8,
 188                                MEDIA_BUS_FMT_YVYU8_1_5X8,
 189                        };
 190
 191                        return vfe_find_code(src_code, ARRAY_SIZE(src_code),
 192                                             index, src_req_code);
 193                }
 194                case MEDIA_BUS_FMT_UYVY8_2X8:
 195                {
 196                        u32 src_code[] = {
 197                                MEDIA_BUS_FMT_UYVY8_2X8,
 198                                MEDIA_BUS_FMT_UYVY8_1_5X8,
 199                        };
 200
 201                        return vfe_find_code(src_code, ARRAY_SIZE(src_code),
 202                                             index, src_req_code);
 203                }
 204                case MEDIA_BUS_FMT_VYUY8_2X8:
 205                {
 206                        u32 src_code[] = {
 207                                MEDIA_BUS_FMT_VYUY8_2X8,
 208                                MEDIA_BUS_FMT_VYUY8_1_5X8,
 209                        };
 210
 211                        return vfe_find_code(src_code, ARRAY_SIZE(src_code),
 212                                             index, src_req_code);
 213                }
 214                default:
 215                        if (index > 0)
 216                                return 0;
 217
 218                        return sink_code;
 219                }
 220        else if (vfe->camss->version == CAMSS_8x96 ||
 221                 vfe->camss->version == CAMSS_660 ||
 222                 vfe->camss->version == CAMSS_845)
 223                switch (sink_code) {
 224                case MEDIA_BUS_FMT_YUYV8_2X8:
 225                {
 226                        u32 src_code[] = {
 227                                MEDIA_BUS_FMT_YUYV8_2X8,
 228                                MEDIA_BUS_FMT_YVYU8_2X8,
 229                                MEDIA_BUS_FMT_UYVY8_2X8,
 230                                MEDIA_BUS_FMT_VYUY8_2X8,
 231                                MEDIA_BUS_FMT_YUYV8_1_5X8,
 232                        };
 233
 234                        return vfe_find_code(src_code, ARRAY_SIZE(src_code),
 235                                             index, src_req_code);
 236                }
 237                case MEDIA_BUS_FMT_YVYU8_2X8:
 238                {
 239                        u32 src_code[] = {
 240                                MEDIA_BUS_FMT_YVYU8_2X8,
 241                                MEDIA_BUS_FMT_YUYV8_2X8,
 242                                MEDIA_BUS_FMT_UYVY8_2X8,
 243                                MEDIA_BUS_FMT_VYUY8_2X8,
 244                                MEDIA_BUS_FMT_YVYU8_1_5X8,
 245                        };
 246
 247                        return vfe_find_code(src_code, ARRAY_SIZE(src_code),
 248                                             index, src_req_code);
 249                }
 250                case MEDIA_BUS_FMT_UYVY8_2X8:
 251                {
 252                        u32 src_code[] = {
 253                                MEDIA_BUS_FMT_UYVY8_2X8,
 254                                MEDIA_BUS_FMT_YUYV8_2X8,
 255                                MEDIA_BUS_FMT_YVYU8_2X8,
 256                                MEDIA_BUS_FMT_VYUY8_2X8,
 257                                MEDIA_BUS_FMT_UYVY8_1_5X8,
 258                        };
 259
 260                        return vfe_find_code(src_code, ARRAY_SIZE(src_code),
 261                                             index, src_req_code);
 262                }
 263                case MEDIA_BUS_FMT_VYUY8_2X8:
 264                {
 265                        u32 src_code[] = {
 266                                MEDIA_BUS_FMT_VYUY8_2X8,
 267                                MEDIA_BUS_FMT_YUYV8_2X8,
 268                                MEDIA_BUS_FMT_YVYU8_2X8,
 269                                MEDIA_BUS_FMT_UYVY8_2X8,
 270                                MEDIA_BUS_FMT_VYUY8_1_5X8,
 271                        };
 272
 273                        return vfe_find_code(src_code, ARRAY_SIZE(src_code),
 274                                             index, src_req_code);
 275                }
 276                default:
 277                        if (index > 0)
 278                                return 0;
 279
 280                        return sink_code;
 281                }
 282        else
 283                return 0;
 284}
 285
 286int vfe_reset(struct vfe_device *vfe)
 287{
 288        unsigned long time;
 289
 290        reinit_completion(&vfe->reset_complete);
 291
 292        vfe->ops->global_reset(vfe);
 293
 294        time = wait_for_completion_timeout(&vfe->reset_complete,
 295                msecs_to_jiffies(VFE_RESET_TIMEOUT_MS));
 296        if (!time) {
 297                dev_err(vfe->camss->dev, "VFE reset timeout\n");
 298                return -EIO;
 299        }
 300
 301        return 0;
 302}
 303
 304static void vfe_init_outputs(struct vfe_device *vfe)
 305{
 306        int i;
 307
 308        for (i = 0; i < vfe->line_num; i++) {
 309                struct vfe_output *output = &vfe->line[i].output;
 310
 311                output->state = VFE_OUTPUT_OFF;
 312                output->buf[0] = NULL;
 313                output->buf[1] = NULL;
 314                INIT_LIST_HEAD(&output->pending_bufs);
 315        }
 316}
 317
 318static void vfe_reset_output_maps(struct vfe_device *vfe)
 319{
 320        int i;
 321
 322        for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++)
 323                vfe->wm_output_map[i] = VFE_LINE_NONE;
 324}
 325
 326int vfe_reserve_wm(struct vfe_device *vfe, enum vfe_line_id line_id)
 327{
 328        int ret = -EBUSY;
 329        int i;
 330
 331        for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++) {
 332                if (vfe->wm_output_map[i] == VFE_LINE_NONE) {
 333                        vfe->wm_output_map[i] = line_id;
 334                        ret = i;
 335                        break;
 336                }
 337        }
 338
 339        return ret;
 340}
 341
 342int vfe_release_wm(struct vfe_device *vfe, u8 wm)
 343{
 344        if (wm >= ARRAY_SIZE(vfe->wm_output_map))
 345                return -EINVAL;
 346
 347        vfe->wm_output_map[wm] = VFE_LINE_NONE;
 348
 349        return 0;
 350}
 351
 352struct camss_buffer *vfe_buf_get_pending(struct vfe_output *output)
 353{
 354        struct camss_buffer *buffer = NULL;
 355
 356        if (!list_empty(&output->pending_bufs)) {
 357                buffer = list_first_entry(&output->pending_bufs,
 358                                          struct camss_buffer,
 359                                          queue);
 360                list_del(&buffer->queue);
 361        }
 362
 363        return buffer;
 364}
 365
 366void vfe_buf_add_pending(struct vfe_output *output,
 367                         struct camss_buffer *buffer)
 368{
 369        INIT_LIST_HEAD(&buffer->queue);
 370        list_add_tail(&buffer->queue, &output->pending_bufs);
 371}
 372
 373/*
 374 * vfe_buf_flush_pending - Flush all pending buffers.
 375 * @output: VFE output
 376 * @state: vb2 buffer state
 377 */
 378static void vfe_buf_flush_pending(struct vfe_output *output,
 379                                  enum vb2_buffer_state state)
 380{
 381        struct camss_buffer *buf;
 382        struct camss_buffer *t;
 383
 384        list_for_each_entry_safe(buf, t, &output->pending_bufs, queue) {
 385                vb2_buffer_done(&buf->vb.vb2_buf, state);
 386                list_del(&buf->queue);
 387        }
 388}
 389
 390int vfe_put_output(struct vfe_line *line)
 391{
 392        struct vfe_device *vfe = to_vfe(line);
 393        struct vfe_output *output = &line->output;
 394        unsigned long flags;
 395        unsigned int i;
 396
 397        spin_lock_irqsave(&vfe->output_lock, flags);
 398
 399        for (i = 0; i < output->wm_num; i++)
 400                vfe_release_wm(vfe, output->wm_idx[i]);
 401
 402        output->state = VFE_OUTPUT_OFF;
 403
 404        spin_unlock_irqrestore(&vfe->output_lock, flags);
 405        return 0;
 406}
 407
 408/**
 409 * vfe_isr_comp_done() - Process composite image done interrupt
 410 * @vfe: VFE Device
 411 * @comp: Composite image id
 412 */
 413void vfe_isr_comp_done(struct vfe_device *vfe, u8 comp)
 414{
 415        unsigned int i;
 416
 417        for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++)
 418                if (vfe->wm_output_map[i] == VFE_LINE_PIX) {
 419                        vfe->isr_ops.wm_done(vfe, i);
 420                        break;
 421                }
 422}
 423
 424void vfe_isr_reset_ack(struct vfe_device *vfe)
 425{
 426        complete(&vfe->reset_complete);
 427}
 428
 429/*
 430 * vfe_set_clock_rates - Calculate and set clock rates on VFE module
 431 * @vfe: VFE device
 432 *
 433 * Return 0 on success or a negative error code otherwise
 434 */
 435static int vfe_set_clock_rates(struct vfe_device *vfe)
 436{
 437        struct device *dev = vfe->camss->dev;
 438        u64 pixel_clock[VFE_LINE_NUM_MAX];
 439        int i, j;
 440        int ret;
 441
 442        for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) {
 443                ret = camss_get_pixel_clock(&vfe->line[i].subdev.entity,
 444                                            &pixel_clock[i]);
 445                if (ret)
 446                        pixel_clock[i] = 0;
 447        }
 448
 449        for (i = 0; i < vfe->nclocks; i++) {
 450                struct camss_clock *clock = &vfe->clock[i];
 451
 452                if (!strcmp(clock->name, "vfe0") ||
 453                    !strcmp(clock->name, "vfe1") ||
 454                    !strcmp(clock->name, "vfe_lite")) {
 455                        u64 min_rate = 0;
 456                        long rate;
 457
 458                        for (j = VFE_LINE_RDI0; j < vfe->line_num; j++) {
 459                                u32 tmp;
 460                                u8 bpp;
 461
 462                                if (j == VFE_LINE_PIX) {
 463                                        tmp = pixel_clock[j];
 464                                } else {
 465                                        struct vfe_line *l = &vfe->line[j];
 466
 467                                        bpp = vfe_get_bpp(l->formats,
 468                                                l->nformats,
 469                                                l->fmt[MSM_VFE_PAD_SINK].code);
 470                                        tmp = pixel_clock[j] * bpp / 64;
 471                                }
 472
 473                                if (min_rate < tmp)
 474                                        min_rate = tmp;
 475                        }
 476
 477                        camss_add_clock_margin(&min_rate);
 478
 479                        for (j = 0; j < clock->nfreqs; j++)
 480                                if (min_rate < clock->freq[j])
 481                                        break;
 482
 483                        if (j == clock->nfreqs) {
 484                                dev_err(dev,
 485                                        "Pixel clock is too high for VFE");
 486                                return -EINVAL;
 487                        }
 488
 489                        /* if sensor pixel clock is not available */
 490                        /* set highest possible VFE clock rate */
 491                        if (min_rate == 0)
 492                                j = clock->nfreqs - 1;
 493
 494                        rate = clk_round_rate(clock->clk, clock->freq[j]);
 495                        if (rate < 0) {
 496                                dev_err(dev, "clk round rate failed: %ld\n",
 497                                        rate);
 498                                return -EINVAL;
 499                        }
 500
 501                        ret = clk_set_rate(clock->clk, rate);
 502                        if (ret < 0) {
 503                                dev_err(dev, "clk set rate failed: %d\n", ret);
 504                                return ret;
 505                        }
 506                }
 507        }
 508
 509        return 0;
 510}
 511
 512/*
 513 * vfe_check_clock_rates - Check current clock rates on VFE module
 514 * @vfe: VFE device
 515 *
 516 * Return 0 if current clock rates are suitable for a new pipeline
 517 * or a negative error code otherwise
 518 */
 519static int vfe_check_clock_rates(struct vfe_device *vfe)
 520{
 521        u64 pixel_clock[VFE_LINE_NUM_MAX];
 522        int i, j;
 523        int ret;
 524
 525        for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) {
 526                ret = camss_get_pixel_clock(&vfe->line[i].subdev.entity,
 527                                            &pixel_clock[i]);
 528                if (ret)
 529                        pixel_clock[i] = 0;
 530        }
 531
 532        for (i = 0; i < vfe->nclocks; i++) {
 533                struct camss_clock *clock = &vfe->clock[i];
 534
 535                if (!strcmp(clock->name, "vfe0") ||
 536                    !strcmp(clock->name, "vfe1")) {
 537                        u64 min_rate = 0;
 538                        unsigned long rate;
 539
 540                        for (j = VFE_LINE_RDI0; j < vfe->line_num; j++) {
 541                                u32 tmp;
 542                                u8 bpp;
 543
 544                                if (j == VFE_LINE_PIX) {
 545                                        tmp = pixel_clock[j];
 546                                } else {
 547                                        struct vfe_line *l = &vfe->line[j];
 548
 549                                        bpp = vfe_get_bpp(l->formats,
 550                                                l->nformats,
 551                                                l->fmt[MSM_VFE_PAD_SINK].code);
 552                                        tmp = pixel_clock[j] * bpp / 64;
 553                                }
 554
 555                                if (min_rate < tmp)
 556                                        min_rate = tmp;
 557                        }
 558
 559                        camss_add_clock_margin(&min_rate);
 560
 561                        rate = clk_get_rate(clock->clk);
 562                        if (rate < min_rate)
 563                                return -EBUSY;
 564                }
 565        }
 566
 567        return 0;
 568}
 569
 570/*
 571 * vfe_get - Power up and reset VFE module
 572 * @vfe: VFE Device
 573 *
 574 * Return 0 on success or a negative error code otherwise
 575 */
 576static int vfe_get(struct vfe_device *vfe)
 577{
 578        int ret;
 579
 580        mutex_lock(&vfe->power_lock);
 581
 582        if (vfe->power_count == 0) {
 583                ret = vfe->ops->pm_domain_on(vfe);
 584                if (ret < 0)
 585                        goto error_pm_domain;
 586
 587                ret = pm_runtime_resume_and_get(vfe->camss->dev);
 588                if (ret < 0)
 589                        goto error_domain_off;
 590
 591                ret = vfe_set_clock_rates(vfe);
 592                if (ret < 0)
 593                        goto error_pm_runtime_get;
 594
 595                ret = camss_enable_clocks(vfe->nclocks, vfe->clock,
 596                                          vfe->camss->dev);
 597                if (ret < 0)
 598                        goto error_pm_runtime_get;
 599
 600                ret = vfe_reset(vfe);
 601                if (ret < 0)
 602                        goto error_reset;
 603
 604                vfe_reset_output_maps(vfe);
 605
 606                vfe_init_outputs(vfe);
 607        } else {
 608                ret = vfe_check_clock_rates(vfe);
 609                if (ret < 0)
 610                        goto error_pm_runtime_get;
 611        }
 612        vfe->power_count++;
 613
 614        mutex_unlock(&vfe->power_lock);
 615
 616        return 0;
 617
 618error_reset:
 619        camss_disable_clocks(vfe->nclocks, vfe->clock);
 620
 621error_pm_runtime_get:
 622        pm_runtime_put_sync(vfe->camss->dev);
 623error_domain_off:
 624        vfe->ops->pm_domain_off(vfe);
 625
 626error_pm_domain:
 627        mutex_unlock(&vfe->power_lock);
 628
 629        return ret;
 630}
 631
 632/*
 633 * vfe_put - Power down VFE module
 634 * @vfe: VFE Device
 635 */
 636static void vfe_put(struct vfe_device *vfe)
 637{
 638        mutex_lock(&vfe->power_lock);
 639
 640        if (vfe->power_count == 0) {
 641                dev_err(vfe->camss->dev, "vfe power off on power_count == 0\n");
 642                goto exit;
 643        } else if (vfe->power_count == 1) {
 644                if (vfe->was_streaming) {
 645                        vfe->was_streaming = 0;
 646                        vfe->ops->vfe_halt(vfe);
 647                }
 648                camss_disable_clocks(vfe->nclocks, vfe->clock);
 649                pm_runtime_put_sync(vfe->camss->dev);
 650                vfe->ops->pm_domain_off(vfe);
 651        }
 652
 653        vfe->power_count--;
 654
 655exit:
 656        mutex_unlock(&vfe->power_lock);
 657}
 658
 659/*
 660 * vfe_flush_buffers - Return all vb2 buffers
 661 * @vid: Video device structure
 662 * @state: vb2 buffer state of the returned buffers
 663 *
 664 * Return all buffers to vb2. This includes queued pending buffers (still
 665 * unused) and any buffers given to the hardware but again still not used.
 666 *
 667 * Return 0 on success or a negative error code otherwise
 668 */
 669int vfe_flush_buffers(struct camss_video *vid,
 670                      enum vb2_buffer_state state)
 671{
 672        struct vfe_line *line = container_of(vid, struct vfe_line, video_out);
 673        struct vfe_device *vfe = to_vfe(line);
 674        struct vfe_output *output;
 675        unsigned long flags;
 676
 677        output = &line->output;
 678
 679        spin_lock_irqsave(&vfe->output_lock, flags);
 680
 681        vfe_buf_flush_pending(output, state);
 682
 683        if (output->buf[0])
 684                vb2_buffer_done(&output->buf[0]->vb.vb2_buf, state);
 685
 686        if (output->buf[1])
 687                vb2_buffer_done(&output->buf[1]->vb.vb2_buf, state);
 688
 689        if (output->last_buffer) {
 690                vb2_buffer_done(&output->last_buffer->vb.vb2_buf, state);
 691                output->last_buffer = NULL;
 692        }
 693
 694        spin_unlock_irqrestore(&vfe->output_lock, flags);
 695
 696        return 0;
 697}
 698
 699/*
 700 * vfe_set_power - Power on/off VFE module
 701 * @sd: VFE V4L2 subdevice
 702 * @on: Requested power state
 703 *
 704 * Return 0 on success or a negative error code otherwise
 705 */
 706static int vfe_set_power(struct v4l2_subdev *sd, int on)
 707{
 708        struct vfe_line *line = v4l2_get_subdevdata(sd);
 709        struct vfe_device *vfe = to_vfe(line);
 710        int ret;
 711
 712        if (on) {
 713                ret = vfe_get(vfe);
 714                if (ret < 0)
 715                        return ret;
 716
 717                vfe->ops->hw_version_read(vfe, vfe->camss->dev);
 718        } else {
 719                vfe_put(vfe);
 720        }
 721
 722        return 0;
 723}
 724
 725/*
 726 * vfe_set_stream - Enable/disable streaming on VFE module
 727 * @sd: VFE V4L2 subdevice
 728 * @enable: Requested streaming state
 729 *
 730 * Main configuration of VFE module is triggered here.
 731 *
 732 * Return 0 on success or a negative error code otherwise
 733 */
 734static int vfe_set_stream(struct v4l2_subdev *sd, int enable)
 735{
 736        struct vfe_line *line = v4l2_get_subdevdata(sd);
 737        struct vfe_device *vfe = to_vfe(line);
 738        int ret;
 739
 740        if (enable) {
 741                ret = vfe->ops->vfe_enable(line);
 742                if (ret < 0)
 743                        dev_err(vfe->camss->dev,
 744                                "Failed to enable vfe outputs\n");
 745        } else {
 746                ret = vfe->ops->vfe_disable(line);
 747                if (ret < 0)
 748                        dev_err(vfe->camss->dev,
 749                                "Failed to disable vfe outputs\n");
 750        }
 751
 752        return ret;
 753}
 754
 755/*
 756 * __vfe_get_format - Get pointer to format structure
 757 * @line: VFE line
 758 * @cfg: V4L2 subdev pad configuration
 759 * @pad: pad from which format is requested
 760 * @which: TRY or ACTIVE format
 761 *
 762 * Return pointer to TRY or ACTIVE format structure
 763 */
 764static struct v4l2_mbus_framefmt *
 765__vfe_get_format(struct vfe_line *line,
 766                 struct v4l2_subdev_state *sd_state,
 767                 unsigned int pad,
 768                 enum v4l2_subdev_format_whence which)
 769{
 770        if (which == V4L2_SUBDEV_FORMAT_TRY)
 771                return v4l2_subdev_get_try_format(&line->subdev, sd_state,
 772                                                  pad);
 773
 774        return &line->fmt[pad];
 775}
 776
 777/*
 778 * __vfe_get_compose - Get pointer to compose selection structure
 779 * @line: VFE line
 780 * @cfg: V4L2 subdev pad configuration
 781 * @which: TRY or ACTIVE format
 782 *
 783 * Return pointer to TRY or ACTIVE compose rectangle structure
 784 */
 785static struct v4l2_rect *
 786__vfe_get_compose(struct vfe_line *line,
 787                  struct v4l2_subdev_state *sd_state,
 788                  enum v4l2_subdev_format_whence which)
 789{
 790        if (which == V4L2_SUBDEV_FORMAT_TRY)
 791                return v4l2_subdev_get_try_compose(&line->subdev, sd_state,
 792                                                   MSM_VFE_PAD_SINK);
 793
 794        return &line->compose;
 795}
 796
 797/*
 798 * __vfe_get_crop - Get pointer to crop selection structure
 799 * @line: VFE line
 800 * @cfg: V4L2 subdev pad configuration
 801 * @which: TRY or ACTIVE format
 802 *
 803 * Return pointer to TRY or ACTIVE crop rectangle structure
 804 */
 805static struct v4l2_rect *
 806__vfe_get_crop(struct vfe_line *line,
 807               struct v4l2_subdev_state *sd_state,
 808               enum v4l2_subdev_format_whence which)
 809{
 810        if (which == V4L2_SUBDEV_FORMAT_TRY)
 811                return v4l2_subdev_get_try_crop(&line->subdev, sd_state,
 812                                                MSM_VFE_PAD_SRC);
 813
 814        return &line->crop;
 815}
 816
 817/*
 818 * vfe_try_format - Handle try format by pad subdev method
 819 * @line: VFE line
 820 * @cfg: V4L2 subdev pad configuration
 821 * @pad: pad on which format is requested
 822 * @fmt: pointer to v4l2 format structure
 823 * @which: wanted subdev format
 824 */
 825static void vfe_try_format(struct vfe_line *line,
 826                           struct v4l2_subdev_state *sd_state,
 827                           unsigned int pad,
 828                           struct v4l2_mbus_framefmt *fmt,
 829                           enum v4l2_subdev_format_whence which)
 830{
 831        unsigned int i;
 832        u32 code;
 833
 834        switch (pad) {
 835        case MSM_VFE_PAD_SINK:
 836                /* Set format on sink pad */
 837
 838                for (i = 0; i < line->nformats; i++)
 839                        if (fmt->code == line->formats[i].code)
 840                                break;
 841
 842                /* If not found, use UYVY as default */
 843                if (i >= line->nformats)
 844                        fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
 845
 846                fmt->width = clamp_t(u32, fmt->width, 1, 8191);
 847                fmt->height = clamp_t(u32, fmt->height, 1, 8191);
 848
 849                fmt->field = V4L2_FIELD_NONE;
 850                fmt->colorspace = V4L2_COLORSPACE_SRGB;
 851
 852                break;
 853
 854        case MSM_VFE_PAD_SRC:
 855                /* Set and return a format same as sink pad */
 856                code = fmt->code;
 857
 858                *fmt = *__vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK,
 859                                         which);
 860
 861                fmt->code = vfe_src_pad_code(line, fmt->code, 0, code);
 862
 863                if (line->id == VFE_LINE_PIX) {
 864                        struct v4l2_rect *rect;
 865
 866                        rect = __vfe_get_crop(line, sd_state, which);
 867
 868                        fmt->width = rect->width;
 869                        fmt->height = rect->height;
 870                }
 871
 872                break;
 873        }
 874
 875        fmt->colorspace = V4L2_COLORSPACE_SRGB;
 876}
 877
 878/*
 879 * vfe_try_compose - Handle try compose selection by pad subdev method
 880 * @line: VFE line
 881 * @cfg: V4L2 subdev pad configuration
 882 * @rect: pointer to v4l2 rect structure
 883 * @which: wanted subdev format
 884 */
 885static void vfe_try_compose(struct vfe_line *line,
 886                            struct v4l2_subdev_state *sd_state,
 887                            struct v4l2_rect *rect,
 888                            enum v4l2_subdev_format_whence which)
 889{
 890        struct v4l2_mbus_framefmt *fmt;
 891
 892        fmt = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK, which);
 893
 894        if (rect->width > fmt->width)
 895                rect->width = fmt->width;
 896
 897        if (rect->height > fmt->height)
 898                rect->height = fmt->height;
 899
 900        if (fmt->width > rect->width * SCALER_RATIO_MAX)
 901                rect->width = (fmt->width + SCALER_RATIO_MAX - 1) /
 902                                                        SCALER_RATIO_MAX;
 903
 904        rect->width &= ~0x1;
 905
 906        if (fmt->height > rect->height * SCALER_RATIO_MAX)
 907                rect->height = (fmt->height + SCALER_RATIO_MAX - 1) /
 908                                                        SCALER_RATIO_MAX;
 909
 910        if (rect->width < 16)
 911                rect->width = 16;
 912
 913        if (rect->height < 4)
 914                rect->height = 4;
 915}
 916
 917/*
 918 * vfe_try_crop - Handle try crop selection by pad subdev method
 919 * @line: VFE line
 920 * @cfg: V4L2 subdev pad configuration
 921 * @rect: pointer to v4l2 rect structure
 922 * @which: wanted subdev format
 923 */
 924static void vfe_try_crop(struct vfe_line *line,
 925                         struct v4l2_subdev_state *sd_state,
 926                         struct v4l2_rect *rect,
 927                         enum v4l2_subdev_format_whence which)
 928{
 929        struct v4l2_rect *compose;
 930
 931        compose = __vfe_get_compose(line, sd_state, which);
 932
 933        if (rect->width > compose->width)
 934                rect->width = compose->width;
 935
 936        if (rect->width + rect->left > compose->width)
 937                rect->left = compose->width - rect->width;
 938
 939        if (rect->height > compose->height)
 940                rect->height = compose->height;
 941
 942        if (rect->height + rect->top > compose->height)
 943                rect->top = compose->height - rect->height;
 944
 945        /* wm in line based mode writes multiple of 16 horizontally */
 946        rect->left += (rect->width & 0xf) >> 1;
 947        rect->width &= ~0xf;
 948
 949        if (rect->width < 16) {
 950                rect->left = 0;
 951                rect->width = 16;
 952        }
 953
 954        if (rect->height < 4) {
 955                rect->top = 0;
 956                rect->height = 4;
 957        }
 958}
 959
 960/*
 961 * vfe_enum_mbus_code - Handle pixel format enumeration
 962 * @sd: VFE V4L2 subdevice
 963 * @cfg: V4L2 subdev pad configuration
 964 * @code: pointer to v4l2_subdev_mbus_code_enum structure
 965 *
 966 * return -EINVAL or zero on success
 967 */
 968static int vfe_enum_mbus_code(struct v4l2_subdev *sd,
 969                              struct v4l2_subdev_state *sd_state,
 970                              struct v4l2_subdev_mbus_code_enum *code)
 971{
 972        struct vfe_line *line = v4l2_get_subdevdata(sd);
 973
 974        if (code->pad == MSM_VFE_PAD_SINK) {
 975                if (code->index >= line->nformats)
 976                        return -EINVAL;
 977
 978                code->code = line->formats[code->index].code;
 979        } else {
 980                struct v4l2_mbus_framefmt *sink_fmt;
 981
 982                sink_fmt = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK,
 983                                            code->which);
 984
 985                code->code = vfe_src_pad_code(line, sink_fmt->code,
 986                                              code->index, 0);
 987                if (!code->code)
 988                        return -EINVAL;
 989        }
 990
 991        return 0;
 992}
 993
 994/*
 995 * vfe_enum_frame_size - Handle frame size enumeration
 996 * @sd: VFE V4L2 subdevice
 997 * @cfg: V4L2 subdev pad configuration
 998 * @fse: pointer to v4l2_subdev_frame_size_enum structure
 999 *
1000 * Return -EINVAL or zero on success
1001 */
1002static int vfe_enum_frame_size(struct v4l2_subdev *sd,
1003                               struct v4l2_subdev_state *sd_state,
1004                               struct v4l2_subdev_frame_size_enum *fse)
1005{
1006        struct vfe_line *line = v4l2_get_subdevdata(sd);
1007        struct v4l2_mbus_framefmt format;
1008
1009        if (fse->index != 0)
1010                return -EINVAL;
1011
1012        format.code = fse->code;
1013        format.width = 1;
1014        format.height = 1;
1015        vfe_try_format(line, sd_state, fse->pad, &format, fse->which);
1016        fse->min_width = format.width;
1017        fse->min_height = format.height;
1018
1019        if (format.code != fse->code)
1020                return -EINVAL;
1021
1022        format.code = fse->code;
1023        format.width = -1;
1024        format.height = -1;
1025        vfe_try_format(line, sd_state, fse->pad, &format, fse->which);
1026        fse->max_width = format.width;
1027        fse->max_height = format.height;
1028
1029        return 0;
1030}
1031
1032/*
1033 * vfe_get_format - Handle get format by pads subdev method
1034 * @sd: VFE V4L2 subdevice
1035 * @cfg: V4L2 subdev pad configuration
1036 * @fmt: pointer to v4l2 subdev format structure
1037 *
1038 * Return -EINVAL or zero on success
1039 */
1040static int vfe_get_format(struct v4l2_subdev *sd,
1041                          struct v4l2_subdev_state *sd_state,
1042                          struct v4l2_subdev_format *fmt)
1043{
1044        struct vfe_line *line = v4l2_get_subdevdata(sd);
1045        struct v4l2_mbus_framefmt *format;
1046
1047        format = __vfe_get_format(line, sd_state, fmt->pad, fmt->which);
1048        if (format == NULL)
1049                return -EINVAL;
1050
1051        fmt->format = *format;
1052
1053        return 0;
1054}
1055
1056static int vfe_set_selection(struct v4l2_subdev *sd,
1057                             struct v4l2_subdev_state *sd_state,
1058                             struct v4l2_subdev_selection *sel);
1059
1060/*
1061 * vfe_set_format - Handle set format by pads subdev method
1062 * @sd: VFE V4L2 subdevice
1063 * @cfg: V4L2 subdev pad configuration
1064 * @fmt: pointer to v4l2 subdev format structure
1065 *
1066 * Return -EINVAL or zero on success
1067 */
1068static int vfe_set_format(struct v4l2_subdev *sd,
1069                          struct v4l2_subdev_state *sd_state,
1070                          struct v4l2_subdev_format *fmt)
1071{
1072        struct vfe_line *line = v4l2_get_subdevdata(sd);
1073        struct v4l2_mbus_framefmt *format;
1074
1075        format = __vfe_get_format(line, sd_state, fmt->pad, fmt->which);
1076        if (format == NULL)
1077                return -EINVAL;
1078
1079        vfe_try_format(line, sd_state, fmt->pad, &fmt->format, fmt->which);
1080        *format = fmt->format;
1081
1082        if (fmt->pad == MSM_VFE_PAD_SINK) {
1083                struct v4l2_subdev_selection sel = { 0 };
1084                int ret;
1085
1086                /* Propagate the format from sink to source */
1087                format = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SRC,
1088                                          fmt->which);
1089
1090                *format = fmt->format;
1091                vfe_try_format(line, sd_state, MSM_VFE_PAD_SRC, format,
1092                               fmt->which);
1093
1094                if (line->id != VFE_LINE_PIX)
1095                        return 0;
1096
1097                /* Reset sink pad compose selection */
1098                sel.which = fmt->which;
1099                sel.pad = MSM_VFE_PAD_SINK;
1100                sel.target = V4L2_SEL_TGT_COMPOSE;
1101                sel.r.width = fmt->format.width;
1102                sel.r.height = fmt->format.height;
1103                ret = vfe_set_selection(sd, sd_state, &sel);
1104                if (ret < 0)
1105                        return ret;
1106        }
1107
1108        return 0;
1109}
1110
1111/*
1112 * vfe_get_selection - Handle get selection by pads subdev method
1113 * @sd: VFE V4L2 subdevice
1114 * @cfg: V4L2 subdev pad configuration
1115 * @sel: pointer to v4l2 subdev selection structure
1116 *
1117 * Return -EINVAL or zero on success
1118 */
1119static int vfe_get_selection(struct v4l2_subdev *sd,
1120                             struct v4l2_subdev_state *sd_state,
1121                             struct v4l2_subdev_selection *sel)
1122{
1123        struct vfe_line *line = v4l2_get_subdevdata(sd);
1124        struct v4l2_subdev_format fmt = { 0 };
1125        struct v4l2_rect *rect;
1126        int ret;
1127
1128        if (line->id != VFE_LINE_PIX)
1129                return -EINVAL;
1130
1131        if (sel->pad == MSM_VFE_PAD_SINK)
1132                switch (sel->target) {
1133                case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1134                        fmt.pad = sel->pad;
1135                        fmt.which = sel->which;
1136                        ret = vfe_get_format(sd, sd_state, &fmt);
1137                        if (ret < 0)
1138                                return ret;
1139
1140                        sel->r.left = 0;
1141                        sel->r.top = 0;
1142                        sel->r.width = fmt.format.width;
1143                        sel->r.height = fmt.format.height;
1144                        break;
1145                case V4L2_SEL_TGT_COMPOSE:
1146                        rect = __vfe_get_compose(line, sd_state, sel->which);
1147                        if (rect == NULL)
1148                                return -EINVAL;
1149
1150                        sel->r = *rect;
1151                        break;
1152                default:
1153                        return -EINVAL;
1154                }
1155        else if (sel->pad == MSM_VFE_PAD_SRC)
1156                switch (sel->target) {
1157                case V4L2_SEL_TGT_CROP_BOUNDS:
1158                        rect = __vfe_get_compose(line, sd_state, sel->which);
1159                        if (rect == NULL)
1160                                return -EINVAL;
1161
1162                        sel->r.left = rect->left;
1163                        sel->r.top = rect->top;
1164                        sel->r.width = rect->width;
1165                        sel->r.height = rect->height;
1166                        break;
1167                case V4L2_SEL_TGT_CROP:
1168                        rect = __vfe_get_crop(line, sd_state, sel->which);
1169                        if (rect == NULL)
1170                                return -EINVAL;
1171
1172                        sel->r = *rect;
1173                        break;
1174                default:
1175                        return -EINVAL;
1176                }
1177
1178        return 0;
1179}
1180
1181/*
1182 * vfe_set_selection - Handle set selection by pads subdev method
1183 * @sd: VFE V4L2 subdevice
1184 * @cfg: V4L2 subdev pad configuration
1185 * @sel: pointer to v4l2 subdev selection structure
1186 *
1187 * Return -EINVAL or zero on success
1188 */
1189static int vfe_set_selection(struct v4l2_subdev *sd,
1190                             struct v4l2_subdev_state *sd_state,
1191                             struct v4l2_subdev_selection *sel)
1192{
1193        struct vfe_line *line = v4l2_get_subdevdata(sd);
1194        struct v4l2_rect *rect;
1195        int ret;
1196
1197        if (line->id != VFE_LINE_PIX)
1198                return -EINVAL;
1199
1200        if (sel->target == V4L2_SEL_TGT_COMPOSE &&
1201                sel->pad == MSM_VFE_PAD_SINK) {
1202                struct v4l2_subdev_selection crop = { 0 };
1203
1204                rect = __vfe_get_compose(line, sd_state, sel->which);
1205                if (rect == NULL)
1206                        return -EINVAL;
1207
1208                vfe_try_compose(line, sd_state, &sel->r, sel->which);
1209                *rect = sel->r;
1210
1211                /* Reset source crop selection */
1212                crop.which = sel->which;
1213                crop.pad = MSM_VFE_PAD_SRC;
1214                crop.target = V4L2_SEL_TGT_CROP;
1215                crop.r = *rect;
1216                ret = vfe_set_selection(sd, sd_state, &crop);
1217        } else if (sel->target == V4L2_SEL_TGT_CROP &&
1218                sel->pad == MSM_VFE_PAD_SRC) {
1219                struct v4l2_subdev_format fmt = { 0 };
1220
1221                rect = __vfe_get_crop(line, sd_state, sel->which);
1222                if (rect == NULL)
1223                        return -EINVAL;
1224
1225                vfe_try_crop(line, sd_state, &sel->r, sel->which);
1226                *rect = sel->r;
1227
1228                /* Reset source pad format width and height */
1229                fmt.which = sel->which;
1230                fmt.pad = MSM_VFE_PAD_SRC;
1231                ret = vfe_get_format(sd, sd_state, &fmt);
1232                if (ret < 0)
1233                        return ret;
1234
1235                fmt.format.width = rect->width;
1236                fmt.format.height = rect->height;
1237                ret = vfe_set_format(sd, sd_state, &fmt);
1238        } else {
1239                ret = -EINVAL;
1240        }
1241
1242        return ret;
1243}
1244
1245/*
1246 * vfe_init_formats - Initialize formats on all pads
1247 * @sd: VFE V4L2 subdevice
1248 * @fh: V4L2 subdev file handle
1249 *
1250 * Initialize all pad formats with default values.
1251 *
1252 * Return 0 on success or a negative error code otherwise
1253 */
1254static int vfe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1255{
1256        struct v4l2_subdev_format format = {
1257                .pad = MSM_VFE_PAD_SINK,
1258                .which = fh ? V4L2_SUBDEV_FORMAT_TRY :
1259                              V4L2_SUBDEV_FORMAT_ACTIVE,
1260                .format = {
1261                        .code = MEDIA_BUS_FMT_UYVY8_2X8,
1262                        .width = 1920,
1263                        .height = 1080
1264                }
1265        };
1266
1267        return vfe_set_format(sd, fh ? fh->state : NULL, &format);
1268}
1269
1270/*
1271 * msm_vfe_subdev_init - Initialize VFE device structure and resources
1272 * @vfe: VFE device
1273 * @res: VFE module resources table
1274 *
1275 * Return 0 on success or a negative error code otherwise
1276 */
1277int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe,
1278                        const struct resources *res, u8 id)
1279{
1280        struct device *dev = camss->dev;
1281        struct platform_device *pdev = to_platform_device(dev);
1282        struct resource *r;
1283        int i, j;
1284        int ret;
1285
1286        switch (camss->version) {
1287        case CAMSS_8x16:
1288                vfe->ops = &vfe_ops_4_1;
1289                break;
1290        case CAMSS_8x96:
1291                vfe->ops = &vfe_ops_4_7;
1292                break;
1293        case CAMSS_660:
1294                vfe->ops = &vfe_ops_4_8;
1295                break;
1296
1297        case CAMSS_845:
1298                vfe->ops = &vfe_ops_170;
1299                break;
1300        default:
1301                return -EINVAL;
1302        }
1303        vfe->ops->subdev_init(dev, vfe);
1304
1305        /* Memory */
1306
1307        vfe->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]);
1308        if (IS_ERR(vfe->base)) {
1309                dev_err(dev, "could not map memory\n");
1310                return PTR_ERR(vfe->base);
1311        }
1312
1313        /* Interrupt */
1314
1315        r = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1316                                         res->interrupt[0]);
1317        if (!r) {
1318                dev_err(dev, "missing IRQ\n");
1319                return -EINVAL;
1320        }
1321
1322        vfe->irq = r->start;
1323        snprintf(vfe->irq_name, sizeof(vfe->irq_name), "%s_%s%d",
1324                 dev_name(dev), MSM_VFE_NAME, vfe->id);
1325        ret = devm_request_irq(dev, vfe->irq, vfe->ops->isr,
1326                               IRQF_TRIGGER_RISING, vfe->irq_name, vfe);
1327        if (ret < 0) {
1328                dev_err(dev, "request_irq failed: %d\n", ret);
1329                return ret;
1330        }
1331
1332        /* Clocks */
1333
1334        vfe->nclocks = 0;
1335        while (res->clock[vfe->nclocks])
1336                vfe->nclocks++;
1337
1338        vfe->clock = devm_kcalloc(dev, vfe->nclocks, sizeof(*vfe->clock),
1339                                  GFP_KERNEL);
1340        if (!vfe->clock)
1341                return -ENOMEM;
1342
1343        for (i = 0; i < vfe->nclocks; i++) {
1344                struct camss_clock *clock = &vfe->clock[i];
1345
1346                clock->clk = devm_clk_get(dev, res->clock[i]);
1347                if (IS_ERR(clock->clk))
1348                        return PTR_ERR(clock->clk);
1349
1350                clock->name = res->clock[i];
1351
1352                clock->nfreqs = 0;
1353                while (res->clock_rate[i][clock->nfreqs])
1354                        clock->nfreqs++;
1355
1356                if (!clock->nfreqs) {
1357                        clock->freq = NULL;
1358                        continue;
1359                }
1360
1361                clock->freq = devm_kcalloc(dev,
1362                                           clock->nfreqs,
1363                                           sizeof(*clock->freq),
1364                                           GFP_KERNEL);
1365                if (!clock->freq)
1366                        return -ENOMEM;
1367
1368                for (j = 0; j < clock->nfreqs; j++)
1369                        clock->freq[j] = res->clock_rate[i][j];
1370        }
1371
1372        mutex_init(&vfe->power_lock);
1373        vfe->power_count = 0;
1374
1375        mutex_init(&vfe->stream_lock);
1376        vfe->stream_count = 0;
1377
1378        spin_lock_init(&vfe->output_lock);
1379
1380        vfe->camss = camss;
1381        vfe->id = id;
1382        vfe->reg_update = 0;
1383
1384        for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) {
1385                struct vfe_line *l = &vfe->line[i];
1386
1387                l->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1388                l->video_out.camss = camss;
1389                l->id = i;
1390                init_completion(&l->output.sof);
1391                init_completion(&l->output.reg_update);
1392
1393                if (camss->version == CAMSS_8x16) {
1394                        if (i == VFE_LINE_PIX) {
1395                                l->formats = formats_pix_8x16;
1396                                l->nformats = ARRAY_SIZE(formats_pix_8x16);
1397                        } else {
1398                                l->formats = formats_rdi_8x16;
1399                                l->nformats = ARRAY_SIZE(formats_rdi_8x16);
1400                        }
1401                } else if (camss->version == CAMSS_8x96 ||
1402                           camss->version == CAMSS_660) {
1403                        if (i == VFE_LINE_PIX) {
1404                                l->formats = formats_pix_8x96;
1405                                l->nformats = ARRAY_SIZE(formats_pix_8x96);
1406                        } else {
1407                                l->formats = formats_rdi_8x96;
1408                                l->nformats = ARRAY_SIZE(formats_rdi_8x96);
1409                        }
1410                } else if (camss->version == CAMSS_845) {
1411                        l->formats = formats_rdi_845;
1412                        l->nformats = ARRAY_SIZE(formats_rdi_845);
1413                } else {
1414                        return -EINVAL;
1415                }
1416        }
1417
1418        init_completion(&vfe->reset_complete);
1419        init_completion(&vfe->halt_complete);
1420
1421        return 0;
1422}
1423
1424/*
1425 * msm_vfe_get_vfe_id - Get VFE HW module id
1426 * @entity: Pointer to VFE media entity structure
1427 * @id: Return CSID HW module id here
1428 */
1429void msm_vfe_get_vfe_id(struct media_entity *entity, u8 *id)
1430{
1431        struct v4l2_subdev *sd;
1432        struct vfe_line *line;
1433        struct vfe_device *vfe;
1434
1435        sd = media_entity_to_v4l2_subdev(entity);
1436        line = v4l2_get_subdevdata(sd);
1437        vfe = to_vfe(line);
1438
1439        *id = vfe->id;
1440}
1441
1442/*
1443 * msm_vfe_get_vfe_line_id - Get VFE line id by media entity
1444 * @entity: Pointer to VFE media entity structure
1445 * @id: Return VFE line id here
1446 */
1447void msm_vfe_get_vfe_line_id(struct media_entity *entity, enum vfe_line_id *id)
1448{
1449        struct v4l2_subdev *sd;
1450        struct vfe_line *line;
1451
1452        sd = media_entity_to_v4l2_subdev(entity);
1453        line = v4l2_get_subdevdata(sd);
1454
1455        *id = line->id;
1456}
1457
1458/*
1459 * vfe_link_setup - Setup VFE connections
1460 * @entity: Pointer to media entity structure
1461 * @local: Pointer to local pad
1462 * @remote: Pointer to remote pad
1463 * @flags: Link flags
1464 *
1465 * Return 0 on success
1466 */
1467static int vfe_link_setup(struct media_entity *entity,
1468                          const struct media_pad *local,
1469                          const struct media_pad *remote, u32 flags)
1470{
1471        if (flags & MEDIA_LNK_FL_ENABLED)
1472                if (media_entity_remote_pad(local))
1473                        return -EBUSY;
1474
1475        return 0;
1476}
1477
1478static const struct v4l2_subdev_core_ops vfe_core_ops = {
1479        .s_power = vfe_set_power,
1480};
1481
1482static const struct v4l2_subdev_video_ops vfe_video_ops = {
1483        .s_stream = vfe_set_stream,
1484};
1485
1486static const struct v4l2_subdev_pad_ops vfe_pad_ops = {
1487        .enum_mbus_code = vfe_enum_mbus_code,
1488        .enum_frame_size = vfe_enum_frame_size,
1489        .get_fmt = vfe_get_format,
1490        .set_fmt = vfe_set_format,
1491        .get_selection = vfe_get_selection,
1492        .set_selection = vfe_set_selection,
1493};
1494
1495static const struct v4l2_subdev_ops vfe_v4l2_ops = {
1496        .core = &vfe_core_ops,
1497        .video = &vfe_video_ops,
1498        .pad = &vfe_pad_ops,
1499};
1500
1501static const struct v4l2_subdev_internal_ops vfe_v4l2_internal_ops = {
1502        .open = vfe_init_formats,
1503};
1504
1505static const struct media_entity_operations vfe_media_ops = {
1506        .link_setup = vfe_link_setup,
1507        .link_validate = v4l2_subdev_link_validate,
1508};
1509
1510/*
1511 * msm_vfe_register_entities - Register subdev node for VFE module
1512 * @vfe: VFE device
1513 * @v4l2_dev: V4L2 device
1514 *
1515 * Initialize and register a subdev node for the VFE module. Then
1516 * call msm_video_register() to register the video device node which
1517 * will be connected to this subdev node. Then actually create the
1518 * media link between them.
1519 *
1520 * Return 0 on success or a negative error code otherwise
1521 */
1522int msm_vfe_register_entities(struct vfe_device *vfe,
1523                              struct v4l2_device *v4l2_dev)
1524{
1525        struct device *dev = vfe->camss->dev;
1526        struct v4l2_subdev *sd;
1527        struct media_pad *pads;
1528        struct camss_video *video_out;
1529        int ret;
1530        int i;
1531
1532        for (i = 0; i < vfe->line_num; i++) {
1533                char name[32];
1534
1535                sd = &vfe->line[i].subdev;
1536                pads = vfe->line[i].pads;
1537                video_out = &vfe->line[i].video_out;
1538
1539                v4l2_subdev_init(sd, &vfe_v4l2_ops);
1540                sd->internal_ops = &vfe_v4l2_internal_ops;
1541                sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1542                if (i == VFE_LINE_PIX)
1543                        snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d_%s",
1544                                 MSM_VFE_NAME, vfe->id, "pix");
1545                else
1546                        snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d_%s%d",
1547                                 MSM_VFE_NAME, vfe->id, "rdi", i);
1548
1549                v4l2_set_subdevdata(sd, &vfe->line[i]);
1550
1551                ret = vfe_init_formats(sd, NULL);
1552                if (ret < 0) {
1553                        dev_err(dev, "Failed to init format: %d\n", ret);
1554                        goto error_init;
1555                }
1556
1557                pads[MSM_VFE_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1558                pads[MSM_VFE_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
1559
1560                sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
1561                sd->entity.ops = &vfe_media_ops;
1562                ret = media_entity_pads_init(&sd->entity, MSM_VFE_PADS_NUM,
1563                                             pads);
1564                if (ret < 0) {
1565                        dev_err(dev, "Failed to init media entity: %d\n", ret);
1566                        goto error_init;
1567                }
1568
1569                ret = v4l2_device_register_subdev(v4l2_dev, sd);
1570                if (ret < 0) {
1571                        dev_err(dev, "Failed to register subdev: %d\n", ret);
1572                        goto error_reg_subdev;
1573                }
1574
1575                video_out->ops = &vfe->video_ops;
1576                video_out->bpl_alignment = 8;
1577                video_out->line_based = 0;
1578                if (i == VFE_LINE_PIX) {
1579                        video_out->bpl_alignment = 16;
1580                        video_out->line_based = 1;
1581                }
1582                snprintf(name, ARRAY_SIZE(name), "%s%d_%s%d",
1583                         MSM_VFE_NAME, vfe->id, "video", i);
1584                ret = msm_video_register(video_out, v4l2_dev, name,
1585                                         i == VFE_LINE_PIX ? 1 : 0);
1586                if (ret < 0) {
1587                        dev_err(dev, "Failed to register video node: %d\n",
1588                                ret);
1589                        goto error_reg_video;
1590                }
1591
1592                ret = media_create_pad_link(
1593                                &sd->entity, MSM_VFE_PAD_SRC,
1594                                &video_out->vdev.entity, 0,
1595                                MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
1596                if (ret < 0) {
1597                        dev_err(dev, "Failed to link %s->%s entities: %d\n",
1598                                sd->entity.name, video_out->vdev.entity.name,
1599                                ret);
1600                        goto error_link;
1601                }
1602        }
1603
1604        return 0;
1605
1606error_link:
1607        msm_video_unregister(video_out);
1608
1609error_reg_video:
1610        v4l2_device_unregister_subdev(sd);
1611
1612error_reg_subdev:
1613        media_entity_cleanup(&sd->entity);
1614
1615error_init:
1616        for (i--; i >= 0; i--) {
1617                sd = &vfe->line[i].subdev;
1618                video_out = &vfe->line[i].video_out;
1619
1620                msm_video_unregister(video_out);
1621                v4l2_device_unregister_subdev(sd);
1622                media_entity_cleanup(&sd->entity);
1623        }
1624
1625        return ret;
1626}
1627
1628/*
1629 * msm_vfe_unregister_entities - Unregister VFE module subdev node
1630 * @vfe: VFE device
1631 */
1632void msm_vfe_unregister_entities(struct vfe_device *vfe)
1633{
1634        int i;
1635
1636        mutex_destroy(&vfe->power_lock);
1637        mutex_destroy(&vfe->stream_lock);
1638
1639        for (i = 0; i < vfe->line_num; i++) {
1640                struct v4l2_subdev *sd = &vfe->line[i].subdev;
1641                struct camss_video *video_out = &vfe->line[i].video_out;
1642
1643                msm_video_unregister(video_out);
1644                v4l2_device_unregister_subdev(sd);
1645                media_entity_cleanup(&sd->entity);
1646        }
1647}
1648