File Index
Files and directories
Sign in
FILE

camss-vfe.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/qcom/camss/camss-vfe.c C
   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_domain.h>
  18#include <linux/pm_runtime.h>
  19#include <linux/spinlock_types.h>
  20#include <linux/spinlock.h>
  21#include <media/media-entity.h>
  22#include <media/v4l2-device.h>
  23#include <media/v4l2-subdev.h>
  24
  25#include "camss-vfe.h"
  26#include "camss.h"
  27
  28#define MSM_VFE_NAME "msm_vfe"
  29
  30/* VFE reset timeout */
  31#define VFE_RESET_TIMEOUT_MS 50
  32
  33#define SCALER_RATIO_MAX 16
  34
  35#define VFE_HW_VERSION		0x0
  36#define		HW_VERSION_STEPPING	0
  37#define		HW_VERSION_REVISION	16
  38#define		HW_VERSION_GENERATION	28
  39
  40static const struct camss_format_info formats_rdi_8x16[] = {
  41	{ MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_UYVY, 1,
  42	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
  43	{ MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_VYUY, 1,
  44	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
  45	{ MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_YUYV, 1,
  46	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
  47	{ MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_YVYU, 1,
  48	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
  49	{ MEDIA_BUS_FMT_SBGGR8_1X8, 8, V4L2_PIX_FMT_SBGGR8, 1,
  50	  PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
  51	{ MEDIA_BUS_FMT_SGBRG8_1X8, 8, V4L2_PIX_FMT_SGBRG8, 1,
  52	  PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
  53	{ MEDIA_BUS_FMT_SGRBG8_1X8, 8, V4L2_PIX_FMT_SGRBG8, 1,
  54	  PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
  55	{ MEDIA_BUS_FMT_SRGGB8_1X8, 8, V4L2_PIX_FMT_SRGGB8, 1,
  56	  PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
  57	{ MEDIA_BUS_FMT_SBGGR10_1X10, 10, V4L2_PIX_FMT_SBGGR10P, 1,
  58	  PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
  59	{ MEDIA_BUS_FMT_SGBRG10_1X10, 10, V4L2_PIX_FMT_SGBRG10P, 1,
  60	  PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
  61	{ MEDIA_BUS_FMT_SGRBG10_1X10, 10, V4L2_PIX_FMT_SGRBG10P, 1,
  62	  PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
  63	{ MEDIA_BUS_FMT_SRGGB10_1X10, 10, V4L2_PIX_FMT_SRGGB10P, 1,
  64	  PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
  65	{ MEDIA_BUS_FMT_SBGGR12_1X12, 12, V4L2_PIX_FMT_SBGGR12P, 1,
  66	  PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
  67	{ MEDIA_BUS_FMT_SGBRG12_1X12, 12, V4L2_PIX_FMT_SGBRG12P, 1,
  68	  PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
  69	{ MEDIA_BUS_FMT_SGRBG12_1X12, 12, V4L2_PIX_FMT_SGRBG12P, 1,
  70	  PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
  71	{ MEDIA_BUS_FMT_SRGGB12_1X12, 12, V4L2_PIX_FMT_SRGGB12P, 1,
  72	  PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
  73	{ MEDIA_BUS_FMT_Y10_1X10, 10, V4L2_PIX_FMT_Y10P, 1,
  74	  PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
  75};
  76
  77static const struct camss_format_info formats_rdi_8x96[] = {
  78	{ MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_UYVY, 1,
  79	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
  80	{ MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_VYUY, 1,
  81	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
  82	{ MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_YUYV, 1,
  83	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
  84	{ MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_YVYU, 1,
  85	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
  86	{ MEDIA_BUS_FMT_SBGGR8_1X8, 8, V4L2_PIX_FMT_SBGGR8, 1,
  87	  PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
  88	{ MEDIA_BUS_FMT_SGBRG8_1X8, 8, V4L2_PIX_FMT_SGBRG8, 1,
  89	  PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
  90	{ MEDIA_BUS_FMT_SGRBG8_1X8, 8, V4L2_PIX_FMT_SGRBG8, 1,
  91	  PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
  92	{ MEDIA_BUS_FMT_SRGGB8_1X8, 8, V4L2_PIX_FMT_SRGGB8, 1,
  93	  PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
  94	{ MEDIA_BUS_FMT_SBGGR10_1X10, 10, V4L2_PIX_FMT_SBGGR10P, 1,
  95	  PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
  96	{ MEDIA_BUS_FMT_SGBRG10_1X10, 10, V4L2_PIX_FMT_SGBRG10P, 1,
  97	  PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
  98	{ MEDIA_BUS_FMT_SGRBG10_1X10, 10, V4L2_PIX_FMT_SGRBG10P, 1,
  99	  PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
 100	{ MEDIA_BUS_FMT_SRGGB10_1X10, 10, V4L2_PIX_FMT_SRGGB10P, 1,
 101	  PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
 102	{ MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 16, V4L2_PIX_FMT_SBGGR10, 1,
 103	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
 104	{ MEDIA_BUS_FMT_SBGGR12_1X12, 12, V4L2_PIX_FMT_SBGGR12P, 1,
 105	  PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
 106	{ MEDIA_BUS_FMT_SGBRG12_1X12, 12, V4L2_PIX_FMT_SGBRG12P, 1,
 107	  PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
 108	{ MEDIA_BUS_FMT_SGRBG12_1X12, 12, V4L2_PIX_FMT_SGRBG12P, 1,
 109	  PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
 110	{ MEDIA_BUS_FMT_SRGGB12_1X12, 12, V4L2_PIX_FMT_SRGGB12P, 1,
 111	  PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
 112	{ MEDIA_BUS_FMT_SBGGR14_1X14, 14, V4L2_PIX_FMT_SBGGR14P, 1,
 113	  PER_PLANE_DATA(0, 1, 1, 1, 1, 14) },
 114	{ MEDIA_BUS_FMT_SGBRG14_1X14, 14, V4L2_PIX_FMT_SGBRG14P, 1,
 115	  PER_PLANE_DATA(0, 1, 1, 1, 1, 14) },
 116	{ MEDIA_BUS_FMT_SGRBG14_1X14, 14, V4L2_PIX_FMT_SGRBG14P, 1,
 117	  PER_PLANE_DATA(0, 1, 1, 1, 1, 14) },
 118	{ MEDIA_BUS_FMT_SRGGB14_1X14, 14, V4L2_PIX_FMT_SRGGB14P, 1,
 119	  PER_PLANE_DATA(0, 1, 1, 1, 1, 14) },
 120	{ MEDIA_BUS_FMT_Y10_1X10, 10, V4L2_PIX_FMT_Y10P, 1,
 121	  PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
 122	{ MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 16, V4L2_PIX_FMT_Y10, 1,
 123	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
 124};
 125
 126static const struct camss_format_info formats_rdi_845[] = {
 127	{ MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_UYVY, 1,
 128	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
 129	{ MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_VYUY, 1,
 130	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
 131	{ MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_YUYV, 1,
 132	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
 133	{ MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_YVYU, 1,
 134	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
 135	{ MEDIA_BUS_FMT_SBGGR8_1X8, 8, V4L2_PIX_FMT_SBGGR8, 1,
 136	  PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
 137	{ MEDIA_BUS_FMT_SGBRG8_1X8, 8, V4L2_PIX_FMT_SGBRG8, 1,
 138	  PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
 139	{ MEDIA_BUS_FMT_SGRBG8_1X8, 8, V4L2_PIX_FMT_SGRBG8, 1,
 140	  PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
 141	{ MEDIA_BUS_FMT_SRGGB8_1X8, 8, V4L2_PIX_FMT_SRGGB8, 1,
 142	  PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
 143	{ MEDIA_BUS_FMT_SBGGR10_1X10, 10, V4L2_PIX_FMT_SBGGR10P, 1,
 144	  PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
 145	{ MEDIA_BUS_FMT_SGBRG10_1X10, 10, V4L2_PIX_FMT_SGBRG10P, 1,
 146	  PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
 147	{ MEDIA_BUS_FMT_SGRBG10_1X10, 10, V4L2_PIX_FMT_SGRBG10P, 1,
 148	  PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
 149	{ MEDIA_BUS_FMT_SRGGB10_1X10, 10, V4L2_PIX_FMT_SRGGB10P, 1,
 150	  PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
 151	{ MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 16, V4L2_PIX_FMT_SBGGR10, 1,
 152	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
 153	{ MEDIA_BUS_FMT_SBGGR12_1X12, 12, V4L2_PIX_FMT_SBGGR12P, 1,
 154	  PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
 155	{ MEDIA_BUS_FMT_SGBRG12_1X12, 12, V4L2_PIX_FMT_SGBRG12P, 1,
 156	  PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
 157	{ MEDIA_BUS_FMT_SGRBG12_1X12, 12, V4L2_PIX_FMT_SGRBG12P, 1,
 158	  PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
 159	{ MEDIA_BUS_FMT_SRGGB12_1X12, 12, V4L2_PIX_FMT_SRGGB12P, 1,
 160	  PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
 161	{ MEDIA_BUS_FMT_SBGGR14_1X14, 14, V4L2_PIX_FMT_SBGGR14P, 1,
 162	  PER_PLANE_DATA(0, 1, 1, 1, 1, 14) },
 163	{ MEDIA_BUS_FMT_SGBRG14_1X14, 14, V4L2_PIX_FMT_SGBRG14P, 1,
 164	  PER_PLANE_DATA(0, 1, 1, 1, 1, 14) },
 165	{ MEDIA_BUS_FMT_SGRBG14_1X14, 14, V4L2_PIX_FMT_SGRBG14P, 1,
 166	  PER_PLANE_DATA(0, 1, 1, 1, 1, 14) },
 167	{ MEDIA_BUS_FMT_SRGGB14_1X14, 14, V4L2_PIX_FMT_SRGGB14P, 1,
 168	  PER_PLANE_DATA(0, 1, 1, 1, 1, 14) },
 169	{ MEDIA_BUS_FMT_Y8_1X8, 8, V4L2_PIX_FMT_GREY, 1,
 170	  PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
 171	{ MEDIA_BUS_FMT_Y10_1X10, 10, V4L2_PIX_FMT_Y10P, 1,
 172	  PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
 173	{ MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 16, V4L2_PIX_FMT_Y10, 1,
 174	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
 175};
 176
 177static const struct camss_format_info formats_pix_8x16[] = {
 178	{ MEDIA_BUS_FMT_YUYV8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1,
 179	  PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
 180	{ MEDIA_BUS_FMT_YVYU8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1,
 181	  PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
 182	{ MEDIA_BUS_FMT_UYVY8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1,
 183	  PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
 184	{ MEDIA_BUS_FMT_VYUY8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1,
 185	  PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
 186	{ MEDIA_BUS_FMT_YUYV8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1,
 187	  PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
 188	{ MEDIA_BUS_FMT_YVYU8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1,
 189	  PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
 190	{ MEDIA_BUS_FMT_UYVY8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1,
 191	  PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
 192	{ MEDIA_BUS_FMT_VYUY8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1,
 193	  PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
 194	{ MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_NV16, 1,
 195	  PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
 196	{ MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_NV16, 1,
 197	  PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
 198	{ MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_NV16, 1,
 199	  PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
 200	{ MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_NV16, 1,
 201	  PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
 202	{ MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_NV61, 1,
 203	  PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
 204	{ MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_NV61, 1,
 205	  PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
 206	{ MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_NV61, 1,
 207	  PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
 208	{ MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_NV61, 1,
 209	  PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
 210};
 211
 212static const struct camss_format_info formats_pix_8x96[] = {
 213	{ MEDIA_BUS_FMT_YUYV8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1,
 214	  PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
 215	{ MEDIA_BUS_FMT_YVYU8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1,
 216	  PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
 217	{ MEDIA_BUS_FMT_UYVY8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1,
 218	  PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
 219	{ MEDIA_BUS_FMT_VYUY8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1,
 220	  PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
 221	{ MEDIA_BUS_FMT_YUYV8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1,
 222	  PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
 223	{ MEDIA_BUS_FMT_YVYU8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1,
 224	  PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
 225	{ MEDIA_BUS_FMT_UYVY8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1,
 226	  PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
 227	{ MEDIA_BUS_FMT_VYUY8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1,
 228	  PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
 229	{ MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_NV16, 1,
 230	  PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
 231	{ MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_NV16, 1,
 232	  PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
 233	{ MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_NV16, 1,
 234	  PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
 235	{ MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_NV16, 1,
 236	  PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
 237	{ MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_NV61, 1,
 238	  PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
 239	{ MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_NV61, 1,
 240	  PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
 241	{ MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_NV61, 1,
 242	  PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
 243	{ MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_NV61, 1,
 244	  PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
 245	{ MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_UYVY, 1,
 246	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
 247	{ MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_VYUY, 1,
 248	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
 249	{ MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_YUYV, 1,
 250	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
 251	{ MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_YVYU, 1,
 252	  PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
 253};
 254
 255const struct camss_formats vfe_formats_rdi_8x16 = {
 256	.nformats = ARRAY_SIZE(formats_rdi_8x16),
 257	.formats = formats_rdi_8x16
 258};
 259
 260const struct camss_formats vfe_formats_pix_8x16 = {
 261	.nformats = ARRAY_SIZE(formats_pix_8x16),
 262	.formats = formats_pix_8x16
 263};
 264
 265const struct camss_formats vfe_formats_rdi_8x96 = {
 266	.nformats = ARRAY_SIZE(formats_rdi_8x96),
 267	.formats = formats_rdi_8x96
 268};
 269
 270const struct camss_formats vfe_formats_pix_8x96 = {
 271	.nformats = ARRAY_SIZE(formats_pix_8x96),
 272	.formats = formats_pix_8x96
 273};
 274
 275const struct camss_formats vfe_formats_rdi_845 = {
 276	.nformats = ARRAY_SIZE(formats_rdi_845),
 277	.formats = formats_rdi_845
 278};
 279
 280/* TODO: Replace with pix formats */
 281const struct camss_formats vfe_formats_pix_845 = {
 282	.nformats = ARRAY_SIZE(formats_rdi_845),
 283	.formats = formats_rdi_845
 284};
 285
 286static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
 287			    unsigned int index, u32 src_req_code)
 288{
 289	struct vfe_device *vfe = to_vfe(line);
 290
 291	switch (vfe->camss->res->version) {
 292	case CAMSS_8x16:
 293	case CAMSS_8x39:
 294	case CAMSS_8x53:
 295		switch (sink_code) {
 296		case MEDIA_BUS_FMT_YUYV8_1X16:
 297		{
 298			u32 src_code[] = {
 299				MEDIA_BUS_FMT_YUYV8_1X16,
 300				MEDIA_BUS_FMT_YUYV8_1_5X8,
 301			};
 302
 303			return camss_format_find_code(src_code, ARRAY_SIZE(src_code),
 304						      index, src_req_code);
 305		}
 306		case MEDIA_BUS_FMT_YVYU8_1X16:
 307		{
 308			u32 src_code[] = {
 309				MEDIA_BUS_FMT_YVYU8_1X16,
 310				MEDIA_BUS_FMT_YVYU8_1_5X8,
 311			};
 312
 313			return camss_format_find_code(src_code, ARRAY_SIZE(src_code),
 314						      index, src_req_code);
 315		}
 316		case MEDIA_BUS_FMT_UYVY8_1X16:
 317		{
 318			u32 src_code[] = {
 319				MEDIA_BUS_FMT_UYVY8_1X16,
 320				MEDIA_BUS_FMT_UYVY8_1_5X8,
 321			};
 322
 323			return camss_format_find_code(src_code, ARRAY_SIZE(src_code),
 324						      index, src_req_code);
 325		}
 326		case MEDIA_BUS_FMT_VYUY8_1X16:
 327		{
 328			u32 src_code[] = {
 329				MEDIA_BUS_FMT_VYUY8_1X16,
 330				MEDIA_BUS_FMT_VYUY8_1_5X8,
 331			};
 332
 333			return camss_format_find_code(src_code, ARRAY_SIZE(src_code),
 334						      index, src_req_code);
 335		}
 336		default:
 337			if (index > 0)
 338				return 0;
 339
 340			return sink_code;
 341		}
 342		break;
 343	case CAMSS_660:
 344	case CAMSS_2290:
 345	case CAMSS_7280:
 346	case CAMSS_8x96:
 347	case CAMSS_8250:
 348	case CAMSS_8280XP:
 349	case CAMSS_8300:
 350	case CAMSS_845:
 351	case CAMSS_8550:
 352	case CAMSS_8650:
 353	case CAMSS_8775P:
 354	case CAMSS_X1E80100:
 355		switch (sink_code) {
 356		case MEDIA_BUS_FMT_YUYV8_1X16:
 357		{
 358			u32 src_code[] = {
 359				MEDIA_BUS_FMT_YUYV8_1X16,
 360				MEDIA_BUS_FMT_YVYU8_1X16,
 361				MEDIA_BUS_FMT_UYVY8_1X16,
 362				MEDIA_BUS_FMT_VYUY8_1X16,
 363				MEDIA_BUS_FMT_YUYV8_1_5X8,
 364			};
 365
 366			return camss_format_find_code(src_code, ARRAY_SIZE(src_code),
 367						      index, src_req_code);
 368		}
 369		case MEDIA_BUS_FMT_YVYU8_1X16:
 370		{
 371			u32 src_code[] = {
 372				MEDIA_BUS_FMT_YVYU8_1X16,
 373				MEDIA_BUS_FMT_YUYV8_1X16,
 374				MEDIA_BUS_FMT_UYVY8_1X16,
 375				MEDIA_BUS_FMT_VYUY8_1X16,
 376				MEDIA_BUS_FMT_YVYU8_1_5X8,
 377			};
 378
 379			return camss_format_find_code(src_code, ARRAY_SIZE(src_code),
 380						      index, src_req_code);
 381		}
 382		case MEDIA_BUS_FMT_UYVY8_1X16:
 383		{
 384			u32 src_code[] = {
 385				MEDIA_BUS_FMT_UYVY8_1X16,
 386				MEDIA_BUS_FMT_YUYV8_1X16,
 387				MEDIA_BUS_FMT_YVYU8_1X16,
 388				MEDIA_BUS_FMT_VYUY8_1X16,
 389				MEDIA_BUS_FMT_UYVY8_1_5X8,
 390			};
 391
 392			return camss_format_find_code(src_code, ARRAY_SIZE(src_code),
 393						      index, src_req_code);
 394		}
 395		case MEDIA_BUS_FMT_VYUY8_1X16:
 396		{
 397			u32 src_code[] = {
 398				MEDIA_BUS_FMT_VYUY8_1X16,
 399				MEDIA_BUS_FMT_YUYV8_1X16,
 400				MEDIA_BUS_FMT_YVYU8_1X16,
 401				MEDIA_BUS_FMT_UYVY8_1X16,
 402				MEDIA_BUS_FMT_VYUY8_1_5X8,
 403			};
 404
 405			return camss_format_find_code(src_code, ARRAY_SIZE(src_code),
 406						      index, src_req_code);
 407		}
 408		default:
 409			if (index > 0)
 410				return 0;
 411
 412			return sink_code;
 413		}
 414		break;
 415	default:
 416		WARN(1, "Unsupported HW version: %x\n",
 417		     vfe->camss->res->version);
 418		break;
 419	}
 420	return 0;
 421}
 422
 423/*
 424 * vfe_hw_version - Process write master done interrupt
 425 * @vfe: VFE Device
 426 *
 427 * Return vfe hw version
 428 */
 429u32 vfe_hw_version(struct vfe_device *vfe)
 430{
 431	u32 hw_version = readl_relaxed(vfe->base + VFE_HW_VERSION);
 432
 433	u32 gen = (hw_version >> HW_VERSION_GENERATION) & 0xF;
 434	u32 rev = (hw_version >> HW_VERSION_REVISION) & 0xFFF;
 435	u32 step = (hw_version >> HW_VERSION_STEPPING) & 0xFFFF;
 436
 437	dev_dbg(vfe->camss->dev, "VFE:%d HW Version = %u.%u.%u\n",
 438		vfe->id, gen, rev, step);
 439
 440	return hw_version;
 441}
 442
 443/*
 444 * vfe_buf_done - Process write master done interrupt
 445 * @vfe: VFE Device
 446 * @wm: Write master id
 447 */
 448void vfe_buf_done(struct vfe_device *vfe, int wm)
 449{
 450	struct vfe_line *line = &vfe->line[vfe->wm_output_map[wm]];
 451	const struct vfe_hw_ops *ops = vfe->res->hw_ops;
 452	struct camss_buffer *ready_buf;
 453	struct vfe_output *output;
 454	unsigned long flags;
 455	u32 index;
 456	u64 ts = ktime_get_ns();
 457
 458	spin_lock_irqsave(&vfe->output_lock, flags);
 459
 460	if (vfe->wm_output_map[wm] == VFE_LINE_NONE) {
 461		dev_err_ratelimited(vfe->camss->dev,
 462				    "Received wm done for unmapped index\n");
 463		goto out_unlock;
 464	}
 465	output = &vfe->line[vfe->wm_output_map[wm]].output;
 466
 467	ready_buf = output->buf[0];
 468	if (!ready_buf) {
 469		dev_err_ratelimited(vfe->camss->dev,
 470				    "Missing ready buf %d!\n", output->state);
 471		goto out_unlock;
 472	}
 473
 474	ready_buf->vb.vb2_buf.timestamp = ts;
 475	ready_buf->vb.sequence = output->sequence++;
 476
 477	index = 0;
 478	output->buf[0] = output->buf[1];
 479	if (output->buf[0])
 480		index = 1;
 481
 482	output->buf[index] = vfe_buf_get_pending(output);
 483
 484	if (output->buf[index]) {
 485		ops->vfe_wm_update(vfe, output->wm_idx[0],
 486				   output->buf[index]->addr[0],
 487				   line);
 488		ops->reg_update(vfe, line->id);
 489	} else {
 490		output->gen2.active_num--;
 491	}
 492
 493	spin_unlock_irqrestore(&vfe->output_lock, flags);
 494
 495	vb2_buffer_done(&ready_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 496
 497	return;
 498
 499out_unlock:
 500	spin_unlock_irqrestore(&vfe->output_lock, flags);
 501}
 502
 503int vfe_enable_output_v2(struct vfe_line *line)
 504{
 505	struct vfe_device *vfe = to_vfe(line);
 506	struct vfe_output *output = &line->output;
 507	const struct vfe_hw_ops *ops = vfe->res->hw_ops;
 508	struct media_pad *sensor_pad;
 509	unsigned long flags;
 510	unsigned int frame_skip = 0;
 511	unsigned int i;
 512
 513	sensor_pad = camss_find_sensor_pad(&line->subdev.entity);
 514	if (sensor_pad) {
 515		struct v4l2_subdev *subdev =
 516			media_entity_to_v4l2_subdev(sensor_pad->entity);
 517
 518		v4l2_subdev_call(subdev, sensor, g_skip_frames, &frame_skip);
 519		/* Max frame skip is 29 frames */
 520		if (frame_skip > VFE_FRAME_DROP_VAL - 1)
 521			frame_skip = VFE_FRAME_DROP_VAL - 1;
 522	}
 523
 524	spin_lock_irqsave(&vfe->output_lock, flags);
 525
 526	ops->reg_update_clear(vfe, line->id);
 527
 528	if (output->state > VFE_OUTPUT_RESERVED) {
 529		dev_err(vfe->camss->dev,
 530			"Output is not in reserved state %d\n",
 531			output->state);
 532		spin_unlock_irqrestore(&vfe->output_lock, flags);
 533		return -EINVAL;
 534	}
 535
 536	WARN_ON(output->gen2.active_num);
 537
 538	output->state = VFE_OUTPUT_ON;
 539
 540	output->sequence = 0;
 541	output->wait_reg_update = 0;
 542	reinit_completion(&output->reg_update);
 543
 544	ops->vfe_wm_start(vfe, output->wm_idx[0], line);
 545
 546	for (i = 0; i < CAMSS_INIT_BUF_COUNT; i++) {
 547		output->buf[i] = vfe_buf_get_pending(output);
 548		if (!output->buf[i])
 549			break;
 550		output->gen2.active_num++;
 551		ops->vfe_wm_update(vfe, output->wm_idx[0],
 552				   output->buf[i]->addr[0], line);
 553		ops->reg_update(vfe, line->id);
 554	}
 555
 556	spin_unlock_irqrestore(&vfe->output_lock, flags);
 557
 558	return 0;
 559}
 560
 561/*
 562 * vfe_queue_buffer_v2 - Add empty buffer
 563 * @vid: Video device structure
 564 * @buf: Buffer to be enqueued
 565 *
 566 * Add an empty buffer - depending on the current number of buffers it will be
 567 * put in pending buffer queue or directly given to the hardware to be filled.
 568 *
 569 * Return 0 on success or a negative error code otherwise
 570 */
 571int vfe_queue_buffer_v2(struct camss_video *vid,
 572			struct camss_buffer *buf)
 573{
 574	struct vfe_line *line = container_of(vid, struct vfe_line, video_out);
 575	struct vfe_device *vfe = to_vfe(line);
 576	const struct vfe_hw_ops *ops = vfe->res->hw_ops;
 577	struct vfe_output *output;
 578	unsigned long flags;
 579
 580	output = &line->output;
 581
 582	spin_lock_irqsave(&vfe->output_lock, flags);
 583
 584	if (output->state == VFE_OUTPUT_ON &&
 585	    output->gen2.active_num < 2) {
 586		output->buf[output->gen2.active_num++] = buf;
 587		ops->vfe_wm_update(vfe, output->wm_idx[0],
 588				   buf->addr[0], line);
 589		ops->reg_update(vfe, line->id);
 590	} else {
 591		vfe_buf_add_pending(output, buf);
 592	}
 593
 594	spin_unlock_irqrestore(&vfe->output_lock, flags);
 595
 596	return 0;
 597}
 598
 599/*
 600 * vfe_enable_v2 - Enable streaming on VFE line
 601 * @line: VFE line
 602 *
 603 * Return 0 on success or a negative error code otherwise
 604 */
 605int vfe_enable_v2(struct vfe_line *line)
 606{
 607	struct vfe_device *vfe = to_vfe(line);
 608	const struct vfe_hw_ops *ops = vfe->res->hw_ops;
 609	int ret;
 610
 611	mutex_lock(&vfe->stream_lock);
 612
 613	if (vfe->res->hw_ops->enable_irq)
 614		ops->enable_irq(vfe);
 615
 616	vfe->stream_count++;
 617
 618	mutex_unlock(&vfe->stream_lock);
 619
 620	ret = vfe_get_output_v2(line);
 621	if (ret < 0)
 622		goto error_get_output;
 623
 624	ret = vfe_enable_output_v2(line);
 625	if (ret < 0)
 626		goto error_enable_output;
 627
 628	vfe->was_streaming = 1;
 629
 630	return 0;
 631
 632error_enable_output:
 633	vfe_put_output(line);
 634
 635error_get_output:
 636	mutex_lock(&vfe->stream_lock);
 637
 638	vfe->stream_count--;
 639
 640	mutex_unlock(&vfe->stream_lock);
 641
 642	return ret;
 643}
 644
 645/*
 646 * vfe_get_output_v2 - Get vfe output port for corresponding VFE line
 647 * @line: VFE line
 648 *
 649 * Return 0 on success or a negative error code otherwise
 650 */
 651int vfe_get_output_v2(struct vfe_line *line)
 652{
 653	struct vfe_device *vfe = to_vfe(line);
 654	struct vfe_output *output;
 655	unsigned long flags;
 656
 657	spin_lock_irqsave(&vfe->output_lock, flags);
 658
 659	output = &line->output;
 660	if (output->state > VFE_OUTPUT_RESERVED) {
 661		dev_err(vfe->camss->dev, "Output is running\n");
 662		goto error;
 663	}
 664
 665	output->wm_num = 1;
 666
 667	/* Correspondence between VFE line number and WM number.
 668	 * line 0 -> RDI 0, line 1 -> RDI1, line 2 -> RDI2, line 3 -> PIX/RDI3
 669	 * Note this 1:1 mapping will not work for PIX streams.
 670	 */
 671	output->wm_idx[0] = line->id;
 672	vfe->wm_output_map[line->id] = line->id;
 673
 674	output->drop_update_idx = 0;
 675
 676	spin_unlock_irqrestore(&vfe->output_lock, flags);
 677
 678	return 0;
 679
 680error:
 681	spin_unlock_irqrestore(&vfe->output_lock, flags);
 682	output->state = VFE_OUTPUT_OFF;
 683
 684	return -EINVAL;
 685}
 686
 687int vfe_reset(struct vfe_device *vfe)
 688{
 689	unsigned long time;
 690
 691	reinit_completion(&vfe->reset_complete);
 692
 693	vfe->res->hw_ops->global_reset(vfe);
 694
 695	time = wait_for_completion_timeout(&vfe->reset_complete,
 696		msecs_to_jiffies(VFE_RESET_TIMEOUT_MS));
 697	if (!time) {
 698		dev_err(vfe->camss->dev, "VFE reset timeout\n");
 699		return -EIO;
 700	}
 701
 702	return 0;
 703}
 704
 705static void vfe_init_outputs(struct vfe_device *vfe)
 706{
 707	int i;
 708
 709	for (i = 0; i < vfe->res->line_num; i++) {
 710		struct vfe_output *output = &vfe->line[i].output;
 711
 712		output->state = VFE_OUTPUT_OFF;
 713		output->buf[0] = NULL;
 714		output->buf[1] = NULL;
 715		INIT_LIST_HEAD(&output->pending_bufs);
 716	}
 717}
 718
 719static void vfe_reset_output_maps(struct vfe_device *vfe)
 720{
 721	int i;
 722
 723	for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++)
 724		vfe->wm_output_map[i] = VFE_LINE_NONE;
 725}
 726
 727int vfe_reserve_wm(struct vfe_device *vfe, enum vfe_line_id line_id)
 728{
 729	int ret = -EBUSY;
 730	int i;
 731
 732	for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++) {
 733		if (vfe->wm_output_map[i] == VFE_LINE_NONE) {
 734			vfe->wm_output_map[i] = line_id;
 735			ret = i;
 736			break;
 737		}
 738	}
 739
 740	return ret;
 741}
 742
 743int vfe_release_wm(struct vfe_device *vfe, u8 wm)
 744{
 745	if (wm >= ARRAY_SIZE(vfe->wm_output_map))
 746		return -EINVAL;
 747
 748	vfe->wm_output_map[wm] = VFE_LINE_NONE;
 749
 750	return 0;
 751}
 752
 753struct camss_buffer *vfe_buf_get_pending(struct vfe_output *output)
 754{
 755	struct camss_buffer *buffer = NULL;
 756
 757	if (!list_empty(&output->pending_bufs)) {
 758		buffer = list_first_entry(&output->pending_bufs,
 759					  struct camss_buffer,
 760					  queue);
 761		list_del(&buffer->queue);
 762	}
 763
 764	return buffer;
 765}
 766
 767void vfe_buf_add_pending(struct vfe_output *output,
 768			 struct camss_buffer *buffer)
 769{
 770	INIT_LIST_HEAD(&buffer->queue);
 771	list_add_tail(&buffer->queue, &output->pending_bufs);
 772}
 773
 774/*
 775 * vfe_buf_flush_pending - Flush all pending buffers.
 776 * @output: VFE output
 777 * @state: vb2 buffer state
 778 */
 779static void vfe_buf_flush_pending(struct vfe_output *output,
 780				  enum vb2_buffer_state state)
 781{
 782	struct camss_buffer *buf;
 783	struct camss_buffer *t;
 784
 785	list_for_each_entry_safe(buf, t, &output->pending_bufs, queue) {
 786		vb2_buffer_done(&buf->vb.vb2_buf, state);
 787		list_del(&buf->queue);
 788	}
 789}
 790
 791int vfe_put_output(struct vfe_line *line)
 792{
 793	struct vfe_device *vfe = to_vfe(line);
 794	struct vfe_output *output = &line->output;
 795	unsigned long flags;
 796	unsigned int i;
 797
 798	spin_lock_irqsave(&vfe->output_lock, flags);
 799
 800	for (i = 0; i < output->wm_num; i++)
 801		vfe_release_wm(vfe, output->wm_idx[i]);
 802
 803	output->state = VFE_OUTPUT_OFF;
 804
 805	spin_unlock_irqrestore(&vfe->output_lock, flags);
 806	return 0;
 807}
 808
 809static int vfe_disable_output(struct vfe_line *line)
 810{
 811	struct vfe_device *vfe = to_vfe(line);
 812	struct vfe_output *output = &line->output;
 813	unsigned long flags;
 814	unsigned int i;
 815
 816	spin_lock_irqsave(&vfe->output_lock, flags);
 817	for (i = 0; i < output->wm_num; i++)
 818		vfe->res->hw_ops->vfe_wm_stop(vfe, output->wm_idx[i]);
 819	output->gen2.active_num = 0;
 820	spin_unlock_irqrestore(&vfe->output_lock, flags);
 821
 822	return vfe_reset(vfe);
 823}
 824
 825/*
 826 * vfe_disable - Disable streaming on VFE line
 827 * @line: VFE line
 828 *
 829 * Return 0 on success or a negative error code otherwise
 830 */
 831int vfe_disable(struct vfe_line *line)
 832{
 833	struct vfe_device *vfe = to_vfe(line);
 834	int ret;
 835
 836	ret = vfe_disable_output(line);
 837	if (ret)
 838		goto error;
 839
 840	vfe_put_output(line);
 841
 842	mutex_lock(&vfe->stream_lock);
 843
 844	vfe->stream_count--;
 845
 846	mutex_unlock(&vfe->stream_lock);
 847
 848error:
 849	return ret;
 850}
 851
 852/**
 853 * vfe_isr_comp_done() - Process composite image done interrupt
 854 * @vfe: VFE Device
 855 * @comp: Composite image id
 856 */
 857void vfe_isr_comp_done(struct vfe_device *vfe, u8 comp)
 858{
 859	unsigned int i;
 860
 861	for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++)
 862		if (vfe->wm_output_map[i] == VFE_LINE_PIX) {
 863			vfe->isr_ops.wm_done(vfe, i);
 864			break;
 865		}
 866}
 867
 868void vfe_isr_reset_ack(struct vfe_device *vfe)
 869{
 870	complete(&vfe->reset_complete);
 871}
 872
 873/*
 874 * vfe_pm_domain_off - Disable power domains specific to this VFE.
 875 * @vfe: VFE Device
 876 */
 877void vfe_pm_domain_off(struct vfe_device *vfe)
 878{
 879	if (!vfe->genpd)
 880		return;
 881
 882	device_link_del(vfe->genpd_link);
 883	vfe->genpd_link = NULL;
 884}
 885
 886/*
 887 * vfe_pm_domain_on - Enable power domains specific to this VFE.
 888 * @vfe: VFE Device
 889 */
 890int vfe_pm_domain_on(struct vfe_device *vfe)
 891{
 892	struct camss *camss = vfe->camss;
 893
 894	if (!vfe->genpd)
 895		return 0;
 896
 897	vfe->genpd_link = device_link_add(camss->dev, vfe->genpd,
 898					  DL_FLAG_STATELESS |
 899					  DL_FLAG_PM_RUNTIME |
 900					  DL_FLAG_RPM_ACTIVE);
 901	if (!vfe->genpd_link)
 902		return -EINVAL;
 903
 904	return 0;
 905}
 906
 907static int vfe_match_clock_names(struct vfe_device *vfe,
 908				 struct camss_clock *clock)
 909{
 910	char vfe_name[7]; /* vfeXXX\0 */
 911	char vfe_lite_name[12]; /* vfe_liteXXX\0 */
 912
 913	snprintf(vfe_name, sizeof(vfe_name), "vfe%d", vfe->id);
 914	snprintf(vfe_lite_name, sizeof(vfe_lite_name), "vfe_lite%d", vfe->id);
 915
 916	return (!strcmp(clock->name, vfe_name) ||
 917		!strcmp(clock->name, vfe_lite_name) ||
 918		!strcmp(clock->name, "vfe_lite") ||
 919		!strcmp(clock->name, "camnoc_axi") ||
 920		!strcmp(clock->name, "camnoc_rt_axi"));
 921}
 922
 923/*
 924 * vfe_check_clock_levels - Calculate and set clock rates on VFE module
 925 * @clock: clocks data
 926 *
 927 * Return false if there is no non-zero clock level and true otherwise.
 928 */
 929static bool vfe_check_clock_levels(struct camss_clock *clock)
 930{
 931	int i;
 932
 933	for (i = 0; i < clock->nfreqs; i++)
 934		if (clock->freq[i])
 935			return true;
 936	return false;
 937}
 938
 939/*
 940 * vfe_set_clock_rates - Calculate and set clock rates on VFE module
 941 * @vfe: VFE device
 942 *
 943 * Return 0 on success or a negative error code otherwise
 944 */
 945static int vfe_set_clock_rates(struct vfe_device *vfe)
 946{
 947	struct device *dev = vfe->camss->dev;
 948	u64 pixel_clock[VFE_LINE_NUM_MAX];
 949	int i, j;
 950	int ret;
 951
 952	for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) {
 953		ret = camss_get_pixel_clock(&vfe->line[i].subdev.entity,
 954					    &pixel_clock[i]);
 955		if (ret)
 956			pixel_clock[i] = 0;
 957	}
 958
 959	for (i = 0; i < vfe->nclocks; i++) {
 960		struct camss_clock *clock = &vfe->clock[i];
 961
 962		if (vfe_match_clock_names(vfe, clock) && vfe_check_clock_levels(clock)) {
 963			u64 min_rate = 0;
 964			long rate;
 965
 966			for (j = VFE_LINE_RDI0; j < vfe->res->line_num; j++) {
 967				u32 tmp;
 968				u8 bpp;
 969
 970				if (j == VFE_LINE_PIX) {
 971					tmp = pixel_clock[j];
 972				} else {
 973					struct vfe_line *l = &vfe->line[j];
 974
 975					bpp = camss_format_get_bpp(l->formats,
 976								   l->nformats,
 977								   l->fmt[MSM_VFE_PAD_SINK].code);
 978					tmp = pixel_clock[j] * bpp / 64;
 979				}
 980
 981				if (min_rate < tmp)
 982					min_rate = tmp;
 983			}
 984
 985			camss_add_clock_margin(&min_rate);
 986
 987			for (j = 0; j < clock->nfreqs; j++)
 988				if (min_rate < clock->freq[j])
 989					break;
 990
 991			if (j == clock->nfreqs) {
 992				dev_err(dev,
 993					"Pixel clock is too high for VFE");
 994				return -EINVAL;
 995			}
 996
 997			/* if sensor pixel clock is not available */
 998			/* set highest possible VFE clock rate */
 999			if (min_rate == 0)
1000				j = clock->nfreqs - 1;
1001
1002			rate = clk_round_rate(clock->clk, clock->freq[j]);
1003			if (rate < 0) {
1004				dev_err(dev, "clk round rate failed: %ld\n",
1005					rate);
1006				return -EINVAL;
1007			}
1008
1009			ret = clk_set_rate(clock->clk, rate);
1010			if (ret < 0) {
1011				dev_err(dev, "clk set rate failed: %d\n", ret);
1012				return ret;
1013			}
1014		}
1015	}
1016
1017	return 0;
1018}
1019
1020/*
1021 * vfe_check_clock_rates - Check current clock rates on VFE module
1022 * @vfe: VFE device
1023 *
1024 * Return 0 if current clock rates are suitable for a new pipeline
1025 * or a negative error code otherwise
1026 */
1027static int vfe_check_clock_rates(struct vfe_device *vfe)
1028{
1029	u64 pixel_clock[VFE_LINE_NUM_MAX];
1030	int i, j;
1031	int ret;
1032
1033	for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) {
1034		ret = camss_get_pixel_clock(&vfe->line[i].subdev.entity,
1035					    &pixel_clock[i]);
1036		if (ret)
1037			pixel_clock[i] = 0;
1038	}
1039
1040	for (i = 0; i < vfe->nclocks; i++) {
1041		struct camss_clock *clock = &vfe->clock[i];
1042
1043		if (vfe_match_clock_names(vfe, clock) && vfe_check_clock_levels(clock)) {
1044			u64 min_rate = 0;
1045			unsigned long rate;
1046
1047			for (j = VFE_LINE_RDI0; j < vfe->res->line_num; j++) {
1048				u32 tmp;
1049				u8 bpp;
1050
1051				if (j == VFE_LINE_PIX) {
1052					tmp = pixel_clock[j];
1053				} else {
1054					struct vfe_line *l = &vfe->line[j];
1055
1056					bpp = camss_format_get_bpp(l->formats,
1057								   l->nformats,
1058								   l->fmt[MSM_VFE_PAD_SINK].code);
1059					tmp = pixel_clock[j] * bpp / 64;
1060				}
1061
1062				if (min_rate < tmp)
1063					min_rate = tmp;
1064			}
1065
1066			camss_add_clock_margin(&min_rate);
1067
1068			rate = clk_get_rate(clock->clk);
1069			if (rate < min_rate)
1070				return -EBUSY;
1071		}
1072	}
1073
1074	return 0;
1075}
1076
1077/*
1078 * vfe_get - Power up and reset VFE module
1079 * @vfe: VFE Device
1080 *
1081 * Return 0 on success or a negative error code otherwise
1082 */
1083int vfe_get(struct vfe_device *vfe)
1084{
1085	int ret;
1086
1087	mutex_lock(&vfe->power_lock);
1088
1089	if (vfe->power_count == 0) {
1090		ret = vfe->res->hw_ops->pm_domain_on(vfe);
1091		if (ret < 0)
1092			goto error_pm_domain;
1093
1094		ret = pm_runtime_resume_and_get(vfe->camss->dev);
1095		if (ret < 0)
1096			goto error_domain_off;
1097
1098		ret = vfe_set_clock_rates(vfe);
1099		if (ret < 0)
1100			goto error_pm_runtime_get;
1101
1102		ret = camss_enable_clocks(vfe->nclocks, vfe->clock,
1103					  vfe->camss->dev);
1104		if (ret < 0)
1105			goto error_pm_runtime_get;
1106
1107		ret = vfe_reset(vfe);
1108		if (ret < 0)
1109			goto error_reset;
1110
1111		vfe_reset_output_maps(vfe);
1112
1113		vfe_init_outputs(vfe);
1114
1115		vfe->res->hw_ops->hw_version(vfe);
1116	} else {
1117		ret = vfe_check_clock_rates(vfe);
1118		if (ret < 0)
1119			goto error_pm_domain;
1120	}
1121	vfe->power_count++;
1122
1123	mutex_unlock(&vfe->power_lock);
1124
1125	return 0;
1126
1127error_reset:
1128	camss_disable_clocks(vfe->nclocks, vfe->clock);
1129
1130error_pm_runtime_get:
1131	pm_runtime_put_sync(vfe->camss->dev);
1132error_domain_off:
1133	vfe->res->hw_ops->pm_domain_off(vfe);
1134
1135error_pm_domain:
1136	mutex_unlock(&vfe->power_lock);
1137
1138	return ret;
1139}
1140
1141/*
1142 * vfe_put - Power down VFE module
1143 * @vfe: VFE Device
1144 */
1145void vfe_put(struct vfe_device *vfe)
1146{
1147	mutex_lock(&vfe->power_lock);
1148
1149	if (vfe->power_count == 0) {
1150		dev_err(vfe->camss->dev, "vfe power off on power_count == 0\n");
1151		goto exit;
1152	} else if (vfe->power_count == 1) {
1153		if (vfe->was_streaming) {
1154			vfe->was_streaming = 0;
1155			vfe->res->hw_ops->vfe_halt(vfe);
1156		}
1157		camss_disable_clocks(vfe->nclocks, vfe->clock);
1158		pm_runtime_put_sync(vfe->camss->dev);
1159		vfe->res->hw_ops->pm_domain_off(vfe);
1160	}
1161
1162	vfe->power_count--;
1163
1164exit:
1165	mutex_unlock(&vfe->power_lock);
1166}
1167
1168/*
1169 * vfe_flush_buffers - Return all vb2 buffers
1170 * @vid: Video device structure
1171 * @state: vb2 buffer state of the returned buffers
1172 *
1173 * Return all buffers to vb2. This includes queued pending buffers (still
1174 * unused) and any buffers given to the hardware but again still not used.
1175 *
1176 * Return 0 on success or a negative error code otherwise
1177 */
1178int vfe_flush_buffers(struct camss_video *vid,
1179		      enum vb2_buffer_state state)
1180{
1181	struct vfe_line *line = container_of(vid, struct vfe_line, video_out);
1182	struct vfe_device *vfe = to_vfe(line);
1183	struct vfe_output *output;
1184	unsigned long flags;
1185
1186	output = &line->output;
1187
1188	spin_lock_irqsave(&vfe->output_lock, flags);
1189
1190	vfe_buf_flush_pending(output, state);
1191
1192	if (output->buf[0])
1193		vb2_buffer_done(&output->buf[0]->vb.vb2_buf, state);
1194
1195	if (output->buf[1])
1196		vb2_buffer_done(&output->buf[1]->vb.vb2_buf, state);
1197
1198	if (output->last_buffer) {
1199		vb2_buffer_done(&output->last_buffer->vb.vb2_buf, state);
1200		output->last_buffer = NULL;
1201	}
1202
1203	spin_unlock_irqrestore(&vfe->output_lock, flags);
1204
1205	return 0;
1206}
1207
1208/*
1209 * vfe_set_power - Power on/off VFE module
1210 * @sd: VFE V4L2 subdevice
1211 * @on: Requested power state
1212 *
1213 * Return 0 on success or a negative error code otherwise
1214 */
1215static int vfe_set_power(struct v4l2_subdev *sd, int on)
1216{
1217	struct vfe_line *line = v4l2_get_subdevdata(sd);
1218	struct vfe_device *vfe = to_vfe(line);
1219	int ret;
1220
1221	if (on) {
1222		ret = vfe_get(vfe);
1223		if (ret < 0)
1224			return ret;
1225	} else {
1226		vfe_put(vfe);
1227	}
1228
1229	return 0;
1230}
1231
1232/*
1233 * vfe_set_stream - Enable/disable streaming on VFE module
1234 * @sd: VFE V4L2 subdevice
1235 * @enable: Requested streaming state
1236 *
1237 * Main configuration of VFE module is triggered here.
1238 *
1239 * Return 0 on success or a negative error code otherwise
1240 */
1241static int vfe_set_stream(struct v4l2_subdev *sd, int enable)
1242{
1243	struct vfe_line *line = v4l2_get_subdevdata(sd);
1244	struct vfe_device *vfe = to_vfe(line);
1245	int ret;
1246
1247	if (enable) {
1248		line->output.state = VFE_OUTPUT_RESERVED;
1249		ret = vfe->res->hw_ops->vfe_enable(line);
1250		if (ret < 0)
1251			dev_err(vfe->camss->dev,
1252				"Failed to enable vfe outputs\n");
1253	} else {
1254		ret = vfe->res->hw_ops->vfe_disable(line);
1255		if (ret < 0)
1256			dev_err(vfe->camss->dev,
1257				"Failed to disable vfe outputs\n");
1258	}
1259
1260	return ret;
1261}
1262
1263/*
1264 * __vfe_get_format - Get pointer to format structure
1265 * @line: VFE line
1266 * @sd_state: V4L2 subdev state
1267 * @pad: pad from which format is requested
1268 * @which: TRY or ACTIVE format
1269 *
1270 * Return pointer to TRY or ACTIVE format structure
1271 */
1272static struct v4l2_mbus_framefmt *
1273__vfe_get_format(struct vfe_line *line,
1274		 struct v4l2_subdev_state *sd_state,
1275		 unsigned int pad,
1276		 enum v4l2_subdev_format_whence which)
1277{
1278	if (which == V4L2_SUBDEV_FORMAT_TRY)
1279		return v4l2_subdev_state_get_format(sd_state, pad);
1280
1281	return &line->fmt[pad];
1282}
1283
1284/*
1285 * __vfe_get_compose - Get pointer to compose selection structure
1286 * @line: VFE line
1287 * @sd_state: V4L2 subdev state
1288 * @which: TRY or ACTIVE format
1289 *
1290 * Return pointer to TRY or ACTIVE compose rectangle structure
1291 */
1292static struct v4l2_rect *
1293__vfe_get_compose(struct vfe_line *line,
1294		  struct v4l2_subdev_state *sd_state,
1295		  enum v4l2_subdev_format_whence which)
1296{
1297	if (which == V4L2_SUBDEV_FORMAT_TRY)
1298		return v4l2_subdev_state_get_compose(sd_state,
1299						     MSM_VFE_PAD_SINK);
1300
1301	return &line->compose;
1302}
1303
1304/*
1305 * __vfe_get_crop - Get pointer to crop selection structure
1306 * @line: VFE line
1307 * @sd_state: V4L2 subdev state
1308 * @which: TRY or ACTIVE format
1309 *
1310 * Return pointer to TRY or ACTIVE crop rectangle structure
1311 */
1312static struct v4l2_rect *
1313__vfe_get_crop(struct vfe_line *line,
1314	       struct v4l2_subdev_state *sd_state,
1315	       enum v4l2_subdev_format_whence which)
1316{
1317	if (which == V4L2_SUBDEV_FORMAT_TRY)
1318		return v4l2_subdev_state_get_crop(sd_state, MSM_VFE_PAD_SRC);
1319
1320	return &line->crop;
1321}
1322
1323/*
1324 * vfe_try_format - Handle try format by pad subdev method
1325 * @line: VFE line
1326 * @sd_state: V4L2 subdev state
1327 * @pad: pad on which format is requested
1328 * @fmt: pointer to v4l2 format structure
1329 * @which: wanted subdev format
1330 */
1331static void vfe_try_format(struct vfe_line *line,
1332			   struct v4l2_subdev_state *sd_state,
1333			   unsigned int pad,
1334			   struct v4l2_mbus_framefmt *fmt,
1335			   enum v4l2_subdev_format_whence which)
1336{
1337	unsigned int i;
1338	u32 code;
1339
1340	switch (pad) {
1341	case MSM_VFE_PAD_SINK:
1342		/* Set format on sink pad */
1343
1344		for (i = 0; i < line->nformats; i++)
1345			if (fmt->code == line->formats[i].code)
1346				break;
1347
1348		/* If not found, use UYVY as default */
1349		if (i >= line->nformats)
1350			fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
1351
1352		fmt->width = clamp_t(u32, fmt->width, 1, 8191);
1353		fmt->height = clamp_t(u32, fmt->height, 1, 8191);
1354
1355		fmt->field = V4L2_FIELD_NONE;
1356		fmt->colorspace = V4L2_COLORSPACE_SRGB;
1357
1358		break;
1359
1360	case MSM_VFE_PAD_SRC:
1361		/* Set and return a format same as sink pad */
1362		code = fmt->code;
1363
1364		*fmt = *__vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK,
1365					 which);
1366
1367		fmt->code = vfe_src_pad_code(line, fmt->code, 0, code);
1368
1369		if (line->id == VFE_LINE_PIX) {
1370			struct v4l2_rect *rect;
1371
1372			rect = __vfe_get_crop(line, sd_state, which);
1373
1374			fmt->width = rect->width;
1375			fmt->height = rect->height;
1376		}
1377
1378		break;
1379	}
1380
1381	fmt->colorspace = V4L2_COLORSPACE_SRGB;
1382}
1383
1384/*
1385 * vfe_try_compose - Handle try compose selection by pad subdev method
1386 * @line: VFE line
1387 * @sd_state: V4L2 subdev state
1388 * @rect: pointer to v4l2 rect structure
1389 * @which: wanted subdev format
1390 */
1391static void vfe_try_compose(struct vfe_line *line,
1392			    struct v4l2_subdev_state *sd_state,
1393			    struct v4l2_rect *rect,
1394			    enum v4l2_subdev_format_whence which)
1395{
1396	struct v4l2_mbus_framefmt *fmt;
1397
1398	fmt = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK, which);
1399
1400	if (rect->width > fmt->width)
1401		rect->width = fmt->width;
1402
1403	if (rect->height > fmt->height)
1404		rect->height = fmt->height;
1405
1406	if (fmt->width > rect->width * SCALER_RATIO_MAX)
1407		rect->width = (fmt->width + SCALER_RATIO_MAX - 1) /
1408							SCALER_RATIO_MAX;
1409
1410	rect->width &= ~0x1;
1411
1412	if (fmt->height > rect->height * SCALER_RATIO_MAX)
1413		rect->height = (fmt->height + SCALER_RATIO_MAX - 1) /
1414							SCALER_RATIO_MAX;
1415
1416	if (rect->width < 16)
1417		rect->width = 16;
1418
1419	if (rect->height < 4)
1420		rect->height = 4;
1421}
1422
1423/*
1424 * vfe_try_crop - Handle try crop selection by pad subdev method
1425 * @line: VFE line
1426 * @sd_state: V4L2 subdev state
1427 * @rect: pointer to v4l2 rect structure
1428 * @which: wanted subdev format
1429 */
1430static void vfe_try_crop(struct vfe_line *line,
1431			 struct v4l2_subdev_state *sd_state,
1432			 struct v4l2_rect *rect,
1433			 enum v4l2_subdev_format_whence which)
1434{
1435	struct v4l2_rect *compose;
1436
1437	compose = __vfe_get_compose(line, sd_state, which);
1438
1439	if (rect->width > compose->width)
1440		rect->width = compose->width;
1441
1442	if (rect->width + rect->left > compose->width)
1443		rect->left = compose->width - rect->width;
1444
1445	if (rect->height > compose->height)
1446		rect->height = compose->height;
1447
1448	if (rect->height + rect->top > compose->height)
1449		rect->top = compose->height - rect->height;
1450
1451	/* wm in line based mode writes multiple of 16 horizontally */
1452	rect->left += (rect->width & 0xf) >> 1;
1453	rect->width &= ~0xf;
1454
1455	if (rect->width < 16) {
1456		rect->left = 0;
1457		rect->width = 16;
1458	}
1459
1460	if (rect->height < 4) {
1461		rect->top = 0;
1462		rect->height = 4;
1463	}
1464}
1465
1466/*
1467 * vfe_enum_mbus_code - Handle pixel format enumeration
1468 * @sd: VFE V4L2 subdevice
1469 * @sd_state: V4L2 subdev state
1470 * @code: pointer to v4l2_subdev_mbus_code_enum structure
1471 *
1472 * return -EINVAL or zero on success
1473 */
1474static int vfe_enum_mbus_code(struct v4l2_subdev *sd,
1475			      struct v4l2_subdev_state *sd_state,
1476			      struct v4l2_subdev_mbus_code_enum *code)
1477{
1478	struct vfe_line *line = v4l2_get_subdevdata(sd);
1479
1480	if (code->pad == MSM_VFE_PAD_SINK) {
1481		if (code->index >= line->nformats)
1482			return -EINVAL;
1483
1484		code->code = line->formats[code->index].code;
1485	} else {
1486		struct v4l2_mbus_framefmt *sink_fmt;
1487
1488		sink_fmt = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK,
1489					    code->which);
1490
1491		code->code = vfe_src_pad_code(line, sink_fmt->code,
1492					      code->index, 0);
1493		if (!code->code)
1494			return -EINVAL;
1495	}
1496
1497	return 0;
1498}
1499
1500/*
1501 * vfe_enum_frame_size - Handle frame size enumeration
1502 * @sd: VFE V4L2 subdevice
1503 * @sd_state: V4L2 subdev state
1504 * @fse: pointer to v4l2_subdev_frame_size_enum structure
1505 *
1506 * Return -EINVAL or zero on success
1507 */
1508static int vfe_enum_frame_size(struct v4l2_subdev *sd,
1509			       struct v4l2_subdev_state *sd_state,
1510			       struct v4l2_subdev_frame_size_enum *fse)
1511{
1512	struct vfe_line *line = v4l2_get_subdevdata(sd);
1513	struct v4l2_mbus_framefmt format;
1514
1515	if (fse->index != 0)
1516		return -EINVAL;
1517
1518	format.code = fse->code;
1519	format.width = 1;
1520	format.height = 1;
1521	vfe_try_format(line, sd_state, fse->pad, &format, fse->which);
1522	fse->min_width = format.width;
1523	fse->min_height = format.height;
1524
1525	if (format.code != fse->code)
1526		return -EINVAL;
1527
1528	format.code = fse->code;
1529	format.width = -1;
1530	format.height = -1;
1531	vfe_try_format(line, sd_state, fse->pad, &format, fse->which);
1532	fse->max_width = format.width;
1533	fse->max_height = format.height;
1534
1535	return 0;
1536}
1537
1538/*
1539 * vfe_get_format - Handle get format by pads subdev method
1540 * @sd: VFE V4L2 subdevice
1541 * @sd_state: V4L2 subdev state
1542 * @fmt: pointer to v4l2 subdev format structure
1543 *
1544 * Return -EINVAL or zero on success
1545 */
1546static int vfe_get_format(struct v4l2_subdev *sd,
1547			  struct v4l2_subdev_state *sd_state,
1548			  struct v4l2_subdev_format *fmt)
1549{
1550	struct vfe_line *line = v4l2_get_subdevdata(sd);
1551	struct v4l2_mbus_framefmt *format;
1552
1553	format = __vfe_get_format(line, sd_state, fmt->pad, fmt->which);
1554	if (format == NULL)
1555		return -EINVAL;
1556
1557	fmt->format = *format;
1558
1559	return 0;
1560}
1561
1562static int vfe_set_selection(struct v4l2_subdev *sd,
1563			     struct v4l2_subdev_state *sd_state,
1564			     struct v4l2_subdev_selection *sel);
1565
1566/*
1567 * vfe_set_format - Handle set format by pads subdev method
1568 * @sd: VFE V4L2 subdevice
1569 * @sd_state: V4L2 subdev state
1570 * @fmt: pointer to v4l2 subdev format structure
1571 *
1572 * Return -EINVAL or zero on success
1573 */
1574static int vfe_set_format(struct v4l2_subdev *sd,
1575			  struct v4l2_subdev_state *sd_state,
1576			  struct v4l2_subdev_format *fmt)
1577{
1578	struct vfe_line *line = v4l2_get_subdevdata(sd);
1579	struct v4l2_mbus_framefmt *format;
1580
1581	format = __vfe_get_format(line, sd_state, fmt->pad, fmt->which);
1582	if (format == NULL)
1583		return -EINVAL;
1584
1585	vfe_try_format(line, sd_state, fmt->pad, &fmt->format, fmt->which);
1586	*format = fmt->format;
1587
1588	if (fmt->pad == MSM_VFE_PAD_SINK) {
1589		struct v4l2_subdev_selection sel = { 0 };
1590		int ret;
1591
1592		/* Propagate the format from sink to source */
1593		format = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SRC,
1594					  fmt->which);
1595
1596		*format = fmt->format;
1597		vfe_try_format(line, sd_state, MSM_VFE_PAD_SRC, format,
1598			       fmt->which);
1599
1600		if (line->id != VFE_LINE_PIX)
1601			return 0;
1602
1603		/* Reset sink pad compose selection */
1604		sel.which = fmt->which;
1605		sel.pad = MSM_VFE_PAD_SINK;
1606		sel.target = V4L2_SEL_TGT_COMPOSE;
1607		sel.r.width = fmt->format.width;
1608		sel.r.height = fmt->format.height;
1609		ret = vfe_set_selection(sd, sd_state, &sel);
1610		if (ret < 0)
1611			return ret;
1612	}
1613
1614	return 0;
1615}
1616
1617/*
1618 * vfe_get_selection - Handle get selection by pads subdev method
1619 * @sd: VFE V4L2 subdevice
1620 * @sd_state: V4L2 subdev state
1621 * @sel: pointer to v4l2 subdev selection structure
1622 *
1623 * Return -EINVAL or zero on success
1624 */
1625static int vfe_get_selection(struct v4l2_subdev *sd,
1626			     struct v4l2_subdev_state *sd_state,
1627			     struct v4l2_subdev_selection *sel)
1628{
1629	struct vfe_line *line = v4l2_get_subdevdata(sd);
1630	struct v4l2_subdev_format fmt = { 0 };
1631	struct v4l2_rect *rect;
1632	int ret;
1633
1634	if (line->id != VFE_LINE_PIX)
1635		return -EINVAL;
1636
1637	if (sel->pad == MSM_VFE_PAD_SINK)
1638		switch (sel->target) {
1639		case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1640			fmt.pad = sel->pad;
1641			fmt.which = sel->which;
1642			ret = vfe_get_format(sd, sd_state, &fmt);
1643			if (ret < 0)
1644				return ret;
1645
1646			sel->r.left = 0;
1647			sel->r.top = 0;
1648			sel->r.width = fmt.format.width;
1649			sel->r.height = fmt.format.height;
1650			break;
1651		case V4L2_SEL_TGT_COMPOSE:
1652			rect = __vfe_get_compose(line, sd_state, sel->which);
1653			if (rect == NULL)
1654				return -EINVAL;
1655
1656			sel->r = *rect;
1657			break;
1658		default:
1659			return -EINVAL;
1660		}
1661	else if (sel->pad == MSM_VFE_PAD_SRC)
1662		switch (sel->target) {
1663		case V4L2_SEL_TGT_CROP_BOUNDS:
1664			rect = __vfe_get_compose(line, sd_state, sel->which);
1665			if (rect == NULL)
1666				return -EINVAL;
1667
1668			sel->r.left = rect->left;
1669			sel->r.top = rect->top;
1670			sel->r.width = rect->width;
1671			sel->r.height = rect->height;
1672			break;
1673		case V4L2_SEL_TGT_CROP:
1674			rect = __vfe_get_crop(line, sd_state, sel->which);
1675			if (rect == NULL)
1676				return -EINVAL;
1677
1678			sel->r = *rect;
1679			break;
1680		default:
1681			return -EINVAL;
1682		}
1683
1684	return 0;
1685}
1686
1687/*
1688 * vfe_set_selection - Handle set selection by pads subdev method
1689 * @sd: VFE V4L2 subdevice
1690 * @sd_state: V4L2 subdev state
1691 * @sel: pointer to v4l2 subdev selection structure
1692 *
1693 * Return -EINVAL or zero on success
1694 */
1695static int vfe_set_selection(struct v4l2_subdev *sd,
1696			     struct v4l2_subdev_state *sd_state,
1697			     struct v4l2_subdev_selection *sel)
1698{
1699	struct vfe_line *line = v4l2_get_subdevdata(sd);
1700	struct v4l2_rect *rect;
1701	int ret;
1702
1703	if (line->id != VFE_LINE_PIX)
1704		return -EINVAL;
1705
1706	if (sel->target == V4L2_SEL_TGT_COMPOSE &&
1707		sel->pad == MSM_VFE_PAD_SINK) {
1708		struct v4l2_subdev_selection crop = { 0 };
1709
1710		rect = __vfe_get_compose(line, sd_state, sel->which);
1711		if (rect == NULL)
1712			return -EINVAL;
1713
1714		vfe_try_compose(line, sd_state, &sel->r, sel->which);
1715		*rect = sel->r;
1716
1717		/* Reset source crop selection */
1718		crop.which = sel->which;
1719		crop.pad = MSM_VFE_PAD_SRC;
1720		crop.target = V4L2_SEL_TGT_CROP;
1721		crop.r = *rect;
1722		ret = vfe_set_selection(sd, sd_state, &crop);
1723	} else if (sel->target == V4L2_SEL_TGT_CROP &&
1724		sel->pad == MSM_VFE_PAD_SRC) {
1725		struct v4l2_subdev_format fmt = { 0 };
1726
1727		rect = __vfe_get_crop(line, sd_state, sel->which);
1728		if (rect == NULL)
1729			return -EINVAL;
1730
1731		vfe_try_crop(line, sd_state, &sel->r, sel->which);
1732		*rect = sel->r;
1733
1734		/* Reset source pad format width and height */
1735		fmt.which = sel->which;
1736		fmt.pad = MSM_VFE_PAD_SRC;
1737		ret = vfe_get_format(sd, sd_state, &fmt);
1738		if (ret < 0)
1739			return ret;
1740
1741		fmt.format.width = rect->width;
1742		fmt.format.height = rect->height;
1743		ret = vfe_set_format(sd, sd_state, &fmt);
1744	} else {
1745		ret = -EINVAL;
1746	}
1747
1748	return ret;
1749}
1750
1751/*
1752 * vfe_init_formats - Initialize formats on all pads
1753 * @sd: VFE V4L2 subdevice
1754 * @fh: V4L2 subdev file handle
1755 *
1756 * Initialize all pad formats with default values.
1757 *
1758 * Return 0 on success or a negative error code otherwise
1759 */
1760static int vfe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1761{
1762	struct v4l2_subdev_format format = {
1763		.pad = MSM_VFE_PAD_SINK,
1764		.which = fh ? V4L2_SUBDEV_FORMAT_TRY :
1765			      V4L2_SUBDEV_FORMAT_ACTIVE,
1766		.format = {
1767			.code = MEDIA_BUS_FMT_UYVY8_1X16,
1768			.width = 1920,
1769			.height = 1080
1770		}
1771	};
1772
1773	return vfe_set_format(sd, fh ? fh->state : NULL, &format);
1774}
1775
1776/*
1777 * msm_vfe_subdev_init - Initialize VFE device structure and resources
1778 * @vfe: VFE device
1779 * @res: VFE module resources table
1780 *
1781 * Return 0 on success or a negative error code otherwise
1782 */
1783int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe,
1784			const struct camss_subdev_resources *res, u8 id)
1785{
1786	struct device *dev = camss->dev;
1787	struct platform_device *pdev = to_platform_device(dev);
1788	int i, j;
1789	int ret;
1790
1791	if (!res->vfe.line_num)
1792		return -EINVAL;
1793
1794	vfe->res = &res->vfe;
1795	vfe->res->hw_ops->subdev_init(dev, vfe);
1796
1797	/* Power domain */
1798
1799	if (res->vfe.pd_name) {
1800		vfe->genpd = dev_pm_domain_attach_by_name(camss->dev,
1801							  res->vfe.pd_name);
1802		if (IS_ERR(vfe->genpd)) {
1803			ret = PTR_ERR(vfe->genpd);
1804			return ret;
1805		}
1806	}
1807
1808	if (!vfe->genpd && res->vfe.has_pd) {
1809		/*
1810		 * Legacy magic index.
1811		 * Requires
1812		 * power-domain = <VFE_X>,
1813		 *                <VFE_Y>,
1814		 *                <TITAN_TOP>
1815		 * id must correspondng to the index of the VFE which must
1816		 * come before the TOP GDSC. VFE Lite has no individually
1817		 * collapasible domain which is why id < vfe_num is a valid
1818		 * check.
1819		 */
1820		vfe->genpd = dev_pm_domain_attach_by_id(camss->dev, id);
1821		if (IS_ERR(vfe->genpd))
1822			return PTR_ERR(vfe->genpd);
1823	}
1824
1825	/* Memory */
1826
1827	vfe->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]);
1828	if (IS_ERR(vfe->base)) {
1829		dev_err(dev, "could not map memory\n");
1830		return PTR_ERR(vfe->base);
1831	}
1832
1833	if (vfe->res->has_vbif) {
1834		vfe->vbif_base = devm_platform_ioremap_resource_byname(pdev,
1835								       vfe->res->vbif_name);
1836		if (IS_ERR(vfe->vbif_base)) {
1837			dev_err(dev, "could not map vbif memory\n");
1838			return PTR_ERR(vfe->vbif_base);
1839		}
1840	}
1841
1842	/* Interrupt */
1843
1844	ret = platform_get_irq_byname(pdev, res->interrupt[0]);
1845	if (ret < 0)
1846		return ret;
1847
1848	vfe->irq = ret;
1849	snprintf(vfe->irq_name, sizeof(vfe->irq_name), "%s_%s%d",
1850		 dev_name(dev), MSM_VFE_NAME, id);
1851	ret = devm_request_irq(dev, vfe->irq, vfe->res->hw_ops->isr,
1852			       IRQF_TRIGGER_RISING, vfe->irq_name, vfe);
1853	if (ret < 0) {
1854		dev_err(dev, "request_irq failed: %d\n", ret);
1855		return ret;
1856	}
1857
1858	/* Clocks */
1859
1860	vfe->nclocks = 0;
1861	while (res->clock[vfe->nclocks])
1862		vfe->nclocks++;
1863
1864	vfe->clock = devm_kcalloc(dev, vfe->nclocks, sizeof(*vfe->clock),
1865				  GFP_KERNEL);
1866	if (!vfe->clock)
1867		return -ENOMEM;
1868
1869	for (i = 0; i < vfe->nclocks; i++) {
1870		struct camss_clock *clock = &vfe->clock[i];
1871
1872		clock->clk = devm_clk_get(dev, res->clock[i]);
1873		if (IS_ERR(clock->clk))
1874			return PTR_ERR(clock->clk);
1875
1876		clock->name = res->clock[i];
1877
1878		clock->nfreqs = 0;
1879		while (res->clock_rate[i][clock->nfreqs])
1880			clock->nfreqs++;
1881
1882		if (!clock->nfreqs) {
1883			clock->freq = NULL;
1884			continue;
1885		}
1886
1887		clock->freq = devm_kcalloc(dev,
1888					   clock->nfreqs,
1889					   sizeof(*clock->freq),
1890					   GFP_KERNEL);
1891		if (!clock->freq)
1892			return -ENOMEM;
1893
1894		for (j = 0; j < clock->nfreqs; j++)
1895			clock->freq[j] = res->clock_rate[i][j];
1896	}
1897
1898	mutex_init(&vfe->power_lock);
1899	vfe->power_count = 0;
1900
1901	mutex_init(&vfe->stream_lock);
1902	vfe->stream_count = 0;
1903
1904	spin_lock_init(&vfe->output_lock);
1905
1906	vfe->camss = camss;
1907	vfe->id = id;
1908	vfe->reg_update = 0;
1909
1910	for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) {
1911		struct vfe_line *l = &vfe->line[i];
1912
1913		l->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1914		l->video_out.camss = camss;
1915		l->id = i;
1916		init_completion(&l->output.sof);
1917		init_completion(&l->output.reg_update);
1918
1919		if (i == VFE_LINE_PIX) {
1920			l->nformats = res->vfe.formats_pix->nformats;
1921			l->formats = res->vfe.formats_pix->formats;
1922		} else {
1923			l->nformats = res->vfe.formats_rdi->nformats;
1924			l->formats = res->vfe.formats_rdi->formats;
1925		}
1926	}
1927
1928	init_completion(&vfe->reset_complete);
1929	init_completion(&vfe->halt_complete);
1930
1931	return 0;
1932}
1933
1934/*
1935 * msm_vfe_genpd_cleanup - Cleanup VFE genpd linkages
1936 * @vfe: VFE device
1937 */
1938void msm_vfe_genpd_cleanup(struct vfe_device *vfe)
1939{
1940	if (vfe->genpd_link)
1941		device_link_del(vfe->genpd_link);
1942
1943	if (vfe->genpd)
1944		dev_pm_domain_detach(vfe->genpd, true);
1945}
1946
1947/*
1948 * vfe_link_setup - Setup VFE connections
1949 * @entity: Pointer to media entity structure
1950 * @local: Pointer to local pad
1951 * @remote: Pointer to remote pad
1952 * @flags: Link flags
1953 *
1954 * Return 0 on success
1955 */
1956static int vfe_link_setup(struct media_entity *entity,
1957			  const struct media_pad *local,
1958			  const struct media_pad *remote, u32 flags)
1959{
1960	if (flags & MEDIA_LNK_FL_ENABLED)
1961		if (media_pad_remote_pad_first(local))
1962			return -EBUSY;
1963
1964	return 0;
1965}
1966
1967static const struct v4l2_subdev_core_ops vfe_core_ops = {
1968	.s_power = vfe_set_power,
1969};
1970
1971static const struct v4l2_subdev_video_ops vfe_video_ops = {
1972	.s_stream = vfe_set_stream,
1973};
1974
1975static const struct v4l2_subdev_pad_ops vfe_pad_ops = {
1976	.enum_mbus_code = vfe_enum_mbus_code,
1977	.enum_frame_size = vfe_enum_frame_size,
1978	.get_fmt = vfe_get_format,
1979	.set_fmt = vfe_set_format,
1980	.get_selection = vfe_get_selection,
1981	.set_selection = vfe_set_selection,
1982};
1983
1984static const struct v4l2_subdev_ops vfe_v4l2_ops = {
1985	.core = &vfe_core_ops,
1986	.video = &vfe_video_ops,
1987	.pad = &vfe_pad_ops,
1988};
1989
1990static const struct v4l2_subdev_internal_ops vfe_v4l2_internal_ops = {
1991	.open = vfe_init_formats,
1992};
1993
1994static const struct media_entity_operations vfe_media_ops = {
1995	.link_setup = vfe_link_setup,
1996	.link_validate = v4l2_subdev_link_validate,
1997};
1998
1999static int vfe_bpl_align(struct vfe_device *vfe)
2000{
2001	int ret = 8;
2002
2003	switch (vfe->camss->res->version) {
2004	case CAMSS_7280:
2005	case CAMSS_8250:
2006	case CAMSS_8280XP:
2007	case CAMSS_8300:
2008	case CAMSS_845:
2009	case CAMSS_8550:
2010	case CAMSS_8650:
2011	case CAMSS_8775P:
2012	case CAMSS_X1E80100:
2013		ret = 16;
2014		break;
2015	default:
2016		break;
2017	}
2018
2019	return ret;
2020}
2021
2022/*
2023 * msm_vfe_register_entities - Register subdev node for VFE module
2024 * @vfe: VFE device
2025 * @v4l2_dev: V4L2 device
2026 *
2027 * Initialize and register a subdev node for the VFE module. Then
2028 * call msm_video_register() to register the video device node which
2029 * will be connected to this subdev node. Then actually create the
2030 * media link between them.
2031 *
2032 * Return 0 on success or a negative error code otherwise
2033 */
2034int msm_vfe_register_entities(struct vfe_device *vfe,
2035			      struct v4l2_device *v4l2_dev)
2036{
2037	struct device *dev = vfe->camss->dev;
2038	struct v4l2_subdev *sd;
2039	struct media_pad *pads;
2040	struct camss_video *video_out;
2041	int ret;
2042	int i;
2043
2044	for (i = 0; i < vfe->res->line_num; i++) {
2045		char name[32];
2046
2047		sd = &vfe->line[i].subdev;
2048		pads = vfe->line[i].pads;
2049		video_out = &vfe->line[i].video_out;
2050
2051		v4l2_subdev_init(sd, &vfe_v4l2_ops);
2052		sd->internal_ops = &vfe_v4l2_internal_ops;
2053		sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
2054		if (i == VFE_LINE_PIX)
2055			snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d_%s",
2056				 MSM_VFE_NAME, vfe->id, "pix");
2057		else
2058			snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d_%s%d",
2059				 MSM_VFE_NAME, vfe->id, "rdi", i);
2060
2061		v4l2_set_subdevdata(sd, &vfe->line[i]);
2062
2063		ret = vfe_init_formats(sd, NULL);
2064		if (ret < 0) {
2065			dev_err(dev, "Failed to init format: %d\n", ret);
2066			goto error_init;
2067		}
2068
2069		pads[MSM_VFE_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
2070		pads[MSM_VFE_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
2071
2072		sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
2073		sd->entity.ops = &vfe_media_ops;
2074		ret = media_entity_pads_init(&sd->entity, MSM_VFE_PADS_NUM,
2075					     pads);
2076		if (ret < 0) {
2077			dev_err(dev, "Failed to init media entity: %d\n", ret);
2078			goto error_init;
2079		}
2080
2081		ret = v4l2_device_register_subdev(v4l2_dev, sd);
2082		if (ret < 0) {
2083			dev_err(dev, "Failed to register subdev: %d\n", ret);
2084			goto error_reg_subdev;
2085		}
2086
2087		video_out->ops = &vfe->video_ops;
2088		video_out->bpl_alignment = vfe_bpl_align(vfe);
2089		video_out->line_based = 0;
2090		if (i == VFE_LINE_PIX) {
2091			video_out->bpl_alignment = 16;
2092			video_out->line_based = 1;
2093		}
2094
2095		video_out->nformats = vfe->line[i].nformats;
2096		video_out->formats = vfe->line[i].formats;
2097
2098		snprintf(name, ARRAY_SIZE(name), "%s%d_%s%d",
2099			 MSM_VFE_NAME, vfe->id, "video", i);
2100		ret = msm_video_register(video_out, v4l2_dev, name);
2101		if (ret < 0) {
2102			dev_err(dev, "Failed to register video node: %d\n",
2103				ret);
2104			goto error_reg_video;
2105		}
2106
2107		ret = media_create_pad_link(
2108				&sd->entity, MSM_VFE_PAD_SRC,
2109				&video_out->vdev.entity, 0,
2110				MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
2111		if (ret < 0) {
2112			dev_err(dev, "Failed to link %s->%s entities: %d\n",
2113				sd->entity.name, video_out->vdev.entity.name,
2114				ret);
2115			goto error_link;
2116		}
2117	}
2118
2119	return 0;
2120
2121error_link:
2122	msm_video_unregister(video_out);
2123
2124error_reg_video:
2125	v4l2_device_unregister_subdev(sd);
2126
2127error_reg_subdev:
2128	media_entity_cleanup(&sd->entity);
2129
2130error_init:
2131	for (i--; i >= 0; i--) {
2132		sd = &vfe->line[i].subdev;
2133		video_out = &vfe->line[i].video_out;
2134
2135		msm_video_unregister(video_out);
2136		v4l2_device_unregister_subdev(sd);
2137		media_entity_cleanup(&sd->entity);
2138	}
2139
2140	return ret;
2141}
2142
2143/*
2144 * msm_vfe_unregister_entities - Unregister VFE module subdev node
2145 * @vfe: VFE device
2146 */
2147void msm_vfe_unregister_entities(struct vfe_device *vfe)
2148{
2149	int i;
2150
2151	mutex_destroy(&vfe->power_lock);
2152	mutex_destroy(&vfe->stream_lock);
2153
2154	for (i = 0; i < vfe->res->line_num; i++) {
2155		struct v4l2_subdev *sd = &vfe->line[i].subdev;
2156		struct camss_video *video_out = &vfe->line[i].video_out;
2157
2158		msm_video_unregister(video_out);
2159		v4l2_device_unregister_subdev(sd);
2160		media_entity_cleanup(&sd->entity);
2161	}
2162}
2163
2164bool vfe_is_lite(struct vfe_device *vfe)
2165{
2166	return vfe->camss->res->vfe_res[vfe->id].vfe.is_lite;
2167}
~/ Read-only file preview.