cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

camss-vfe.c (38862B)


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