brintos

brintos / linux-shallow public Read only

0
0
Text · 54.0 KiB · 28e56f6 Raw
1973 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Microchip Image Sensor Controller (ISC) common driver base4 *5 * Copyright (C) 2016-2019 Microchip Technology, Inc.6 *7 * Author: Songjun Wu8 * Author: Eugen Hristev <eugen.hristev@microchip.com>9 *10 */11#include <linux/delay.h>12#include <linux/interrupt.h>13#include <linux/math64.h>14#include <linux/module.h>15#include <linux/of.h>16#include <linux/of_graph.h>17#include <linux/platform_device.h>18#include <linux/pm_runtime.h>19#include <linux/regmap.h>20#include <linux/videodev2.h>21#include <linux/atmel-isc-media.h>22 23#include <media/v4l2-ctrls.h>24#include <media/v4l2-device.h>25#include <media/v4l2-event.h>26#include <media/v4l2-image-sizes.h>27#include <media/v4l2-ioctl.h>28#include <media/v4l2-fwnode.h>29#include <media/v4l2-subdev.h>30#include <media/videobuf2-dma-contig.h>31 32#include "microchip-isc-regs.h"33#include "microchip-isc.h"34 35#define ISC_IS_FORMAT_RAW(mbus_code) \36	(((mbus_code) & 0xf000) == 0x3000)37 38#define ISC_IS_FORMAT_GREY(mbus_code) \39	(((mbus_code) == MEDIA_BUS_FMT_Y10_1X10) | \40	(((mbus_code) == MEDIA_BUS_FMT_Y8_1X8)))41 42static inline void isc_update_v4l2_ctrls(struct isc_device *isc)43{44	struct isc_ctrls *ctrls = &isc->ctrls;45 46	/* In here we set the v4l2 controls w.r.t. our pipeline config */47	v4l2_ctrl_s_ctrl(isc->r_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_R]);48	v4l2_ctrl_s_ctrl(isc->b_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_B]);49	v4l2_ctrl_s_ctrl(isc->gr_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_GR]);50	v4l2_ctrl_s_ctrl(isc->gb_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_GB]);51 52	v4l2_ctrl_s_ctrl(isc->r_off_ctrl, ctrls->offset[ISC_HIS_CFG_MODE_R]);53	v4l2_ctrl_s_ctrl(isc->b_off_ctrl, ctrls->offset[ISC_HIS_CFG_MODE_B]);54	v4l2_ctrl_s_ctrl(isc->gr_off_ctrl, ctrls->offset[ISC_HIS_CFG_MODE_GR]);55	v4l2_ctrl_s_ctrl(isc->gb_off_ctrl, ctrls->offset[ISC_HIS_CFG_MODE_GB]);56}57 58static inline void isc_update_awb_ctrls(struct isc_device *isc)59{60	struct isc_ctrls *ctrls = &isc->ctrls;61 62	/* In here we set our actual hw pipeline config */63 64	regmap_write(isc->regmap, ISC_WB_O_RGR,65		     ((ctrls->offset[ISC_HIS_CFG_MODE_R])) |66		     ((ctrls->offset[ISC_HIS_CFG_MODE_GR]) << 16));67	regmap_write(isc->regmap, ISC_WB_O_BGB,68		     ((ctrls->offset[ISC_HIS_CFG_MODE_B])) |69		     ((ctrls->offset[ISC_HIS_CFG_MODE_GB]) << 16));70	regmap_write(isc->regmap, ISC_WB_G_RGR,71		     ctrls->gain[ISC_HIS_CFG_MODE_R] |72		     (ctrls->gain[ISC_HIS_CFG_MODE_GR] << 16));73	regmap_write(isc->regmap, ISC_WB_G_BGB,74		     ctrls->gain[ISC_HIS_CFG_MODE_B] |75		     (ctrls->gain[ISC_HIS_CFG_MODE_GB] << 16));76}77 78static inline void isc_reset_awb_ctrls(struct isc_device *isc)79{80	unsigned int c;81 82	for (c = ISC_HIS_CFG_MODE_GR; c <= ISC_HIS_CFG_MODE_B; c++) {83		/* gains have a fixed point at 9 decimals */84		isc->ctrls.gain[c] = 1 << 9;85		/* offsets are in 2's complements */86		isc->ctrls.offset[c] = 0;87	}88}89 90static int isc_queue_setup(struct vb2_queue *vq,91			   unsigned int *nbuffers, unsigned int *nplanes,92			   unsigned int sizes[], struct device *alloc_devs[])93{94	struct isc_device *isc = vb2_get_drv_priv(vq);95	unsigned int size = isc->fmt.fmt.pix.sizeimage;96 97	if (*nplanes)98		return sizes[0] < size ? -EINVAL : 0;99 100	*nplanes = 1;101	sizes[0] = size;102 103	return 0;104}105 106static int isc_buffer_prepare(struct vb2_buffer *vb)107{108	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);109	struct isc_device *isc = vb2_get_drv_priv(vb->vb2_queue);110	unsigned long size = isc->fmt.fmt.pix.sizeimage;111 112	if (vb2_plane_size(vb, 0) < size) {113		dev_err(isc->dev, "buffer too small (%lu < %lu)\n",114			vb2_plane_size(vb, 0), size);115		return -EINVAL;116	}117 118	vb2_set_plane_payload(vb, 0, size);119 120	vbuf->field = isc->fmt.fmt.pix.field;121 122	return 0;123}124 125static void isc_crop_pfe(struct isc_device *isc)126{127	struct regmap *regmap = isc->regmap;128	u32 h, w;129 130	h = isc->fmt.fmt.pix.height;131	w = isc->fmt.fmt.pix.width;132 133	/*134	 * In case the sensor is not RAW, it will output a pixel (12-16 bits)135	 * with two samples on the ISC Data bus (which is 8-12)136	 * ISC will count each sample, so, we need to multiply these values137	 * by two, to get the real number of samples for the required pixels.138	 */139	if (!ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code)) {140		h <<= 1;141		w <<= 1;142	}143 144	/*145	 * We limit the column/row count that the ISC will output according146	 * to the configured resolution that we want.147	 * This will avoid the situation where the sensor is misconfigured,148	 * sending more data, and the ISC will just take it and DMA to memory,149	 * causing corruption.150	 */151	regmap_write(regmap, ISC_PFE_CFG1,152		     (ISC_PFE_CFG1_COLMIN(0) & ISC_PFE_CFG1_COLMIN_MASK) |153		     (ISC_PFE_CFG1_COLMAX(w - 1) & ISC_PFE_CFG1_COLMAX_MASK));154 155	regmap_write(regmap, ISC_PFE_CFG2,156		     (ISC_PFE_CFG2_ROWMIN(0) & ISC_PFE_CFG2_ROWMIN_MASK) |157		     (ISC_PFE_CFG2_ROWMAX(h - 1) & ISC_PFE_CFG2_ROWMAX_MASK));158 159	regmap_update_bits(regmap, ISC_PFE_CFG0,160			   ISC_PFE_CFG0_COLEN | ISC_PFE_CFG0_ROWEN,161			   ISC_PFE_CFG0_COLEN | ISC_PFE_CFG0_ROWEN);162}163 164static void isc_start_dma(struct isc_device *isc)165{166	struct regmap *regmap = isc->regmap;167	u32 sizeimage = isc->fmt.fmt.pix.sizeimage;168	u32 dctrl_dview;169	dma_addr_t addr0;170 171	addr0 = vb2_dma_contig_plane_dma_addr(&isc->cur_frm->vb.vb2_buf, 0);172	regmap_write(regmap, ISC_DAD0 + isc->offsets.dma, addr0);173 174	switch (isc->config.fourcc) {175	case V4L2_PIX_FMT_YUV420:176		regmap_write(regmap, ISC_DAD1 + isc->offsets.dma,177			     addr0 + (sizeimage * 2) / 3);178		regmap_write(regmap, ISC_DAD2 + isc->offsets.dma,179			     addr0 + (sizeimage * 5) / 6);180		break;181	case V4L2_PIX_FMT_YUV422P:182		regmap_write(regmap, ISC_DAD1 + isc->offsets.dma,183			     addr0 + sizeimage / 2);184		regmap_write(regmap, ISC_DAD2 + isc->offsets.dma,185			     addr0 + (sizeimage * 3) / 4);186		break;187	default:188		break;189	}190 191	dctrl_dview = isc->config.dctrl_dview;192 193	regmap_write(regmap, ISC_DCTRL + isc->offsets.dma,194		     dctrl_dview | ISC_DCTRL_IE_IS);195	spin_lock(&isc->awb_lock);196	regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_CAPTURE);197	spin_unlock(&isc->awb_lock);198}199 200static void isc_set_pipeline(struct isc_device *isc, u32 pipeline)201{202	struct regmap *regmap = isc->regmap;203	struct isc_ctrls *ctrls = &isc->ctrls;204	u32 val, bay_cfg;205	const u32 *gamma;206	unsigned int i;207 208	/* WB-->CFA-->CC-->GAM-->CSC-->CBC-->SUB422-->SUB420 */209	for (i = 0; i < ISC_PIPE_LINE_NODE_NUM; i++) {210		val = pipeline & BIT(i) ? 1 : 0;211		regmap_field_write(isc->pipeline[i], val);212	}213 214	if (!pipeline)215		return;216 217	bay_cfg = isc->config.sd_format->cfa_baycfg;218 219	regmap_write(regmap, ISC_WB_CFG, bay_cfg);220	isc_update_awb_ctrls(isc);221	isc_update_v4l2_ctrls(isc);222 223	regmap_write(regmap, ISC_CFA_CFG, bay_cfg | ISC_CFA_CFG_EITPOL);224 225	gamma = &isc->gamma_table[ctrls->gamma_index][0];226	regmap_bulk_write(regmap, ISC_GAM_BENTRY, gamma, GAMMA_ENTRIES);227	regmap_bulk_write(regmap, ISC_GAM_GENTRY, gamma, GAMMA_ENTRIES);228	regmap_bulk_write(regmap, ISC_GAM_RENTRY, gamma, GAMMA_ENTRIES);229 230	isc->config_dpc(isc);231	isc->config_csc(isc);232	isc->config_cbc(isc);233	isc->config_cc(isc);234	isc->config_gam(isc);235}236 237static int isc_update_profile(struct isc_device *isc)238{239	struct regmap *regmap = isc->regmap;240	u32 sr;241	int counter = 100;242 243	regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_UPPRO);244 245	regmap_read(regmap, ISC_CTRLSR, &sr);246	while ((sr & ISC_CTRL_UPPRO) && counter--) {247		usleep_range(1000, 2000);248		regmap_read(regmap, ISC_CTRLSR, &sr);249	}250 251	if (counter < 0) {252		v4l2_warn(&isc->v4l2_dev, "Time out to update profile\n");253		return -ETIMEDOUT;254	}255 256	return 0;257}258 259static void isc_set_histogram(struct isc_device *isc, bool enable)260{261	struct regmap *regmap = isc->regmap;262	struct isc_ctrls *ctrls = &isc->ctrls;263 264	if (enable) {265		regmap_write(regmap, ISC_HIS_CFG + isc->offsets.his,266			     ISC_HIS_CFG_MODE_GR |267			     (isc->config.sd_format->cfa_baycfg268					<< ISC_HIS_CFG_BAYSEL_SHIFT) |269					ISC_HIS_CFG_RAR);270		regmap_write(regmap, ISC_HIS_CTRL + isc->offsets.his,271			     ISC_HIS_CTRL_EN);272		regmap_write(regmap, ISC_INTEN, ISC_INT_HISDONE);273		ctrls->hist_id = ISC_HIS_CFG_MODE_GR;274		isc_update_profile(isc);275		regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_HISREQ);276 277		ctrls->hist_stat = HIST_ENABLED;278	} else {279		regmap_write(regmap, ISC_INTDIS, ISC_INT_HISDONE);280		regmap_write(regmap, ISC_HIS_CTRL + isc->offsets.his,281			     ISC_HIS_CTRL_DIS);282 283		ctrls->hist_stat = HIST_DISABLED;284	}285}286 287static int isc_configure(struct isc_device *isc)288{289	struct regmap *regmap = isc->regmap;290	u32 pfe_cfg0, dcfg, mask, pipeline;291	struct isc_subdev_entity *subdev = isc->current_subdev;292 293	pfe_cfg0 = isc->config.sd_format->pfe_cfg0_bps;294	pipeline = isc->config.bits_pipeline;295 296	dcfg = isc->config.dcfg_imode | isc->dcfg;297 298	pfe_cfg0  |= subdev->pfe_cfg0 | ISC_PFE_CFG0_MODE_PROGRESSIVE;299	mask = ISC_PFE_CFG0_BPS_MASK | ISC_PFE_CFG0_HPOL_LOW |300	       ISC_PFE_CFG0_VPOL_LOW | ISC_PFE_CFG0_PPOL_LOW |301	       ISC_PFE_CFG0_MODE_MASK | ISC_PFE_CFG0_CCIR_CRC |302	       ISC_PFE_CFG0_CCIR656 | ISC_PFE_CFG0_MIPI;303 304	regmap_update_bits(regmap, ISC_PFE_CFG0, mask, pfe_cfg0);305 306	isc->config_rlp(isc);307 308	regmap_write(regmap, ISC_DCFG + isc->offsets.dma, dcfg);309 310	/* Set the pipeline */311	isc_set_pipeline(isc, pipeline);312 313	/*314	 * The current implemented histogram is available for RAW R, B, GB, GR315	 * channels. We need to check if sensor is outputting RAW BAYER316	 */317	if (isc->ctrls.awb &&318	    ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code))319		isc_set_histogram(isc, true);320	else321		isc_set_histogram(isc, false);322 323	/* Update profile */324	return isc_update_profile(isc);325}326 327static int isc_prepare_streaming(struct vb2_queue *vq)328{329	struct isc_device *isc = vb2_get_drv_priv(vq);330 331	return media_pipeline_start(isc->video_dev.entity.pads, &isc->mpipe);332}333 334static int isc_start_streaming(struct vb2_queue *vq, unsigned int count)335{336	struct isc_device *isc = vb2_get_drv_priv(vq);337	struct regmap *regmap = isc->regmap;338	struct isc_buffer *buf;339	unsigned long flags;340	int ret;341 342	/* Enable stream on the sub device */343	ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 1);344	if (ret && ret != -ENOIOCTLCMD) {345		dev_err(isc->dev, "stream on failed in subdev %d\n", ret);346		goto err_start_stream;347	}348 349	ret = pm_runtime_resume_and_get(isc->dev);350	if (ret < 0) {351		dev_err(isc->dev, "RPM resume failed in subdev %d\n",352			ret);353		goto err_pm_get;354	}355 356	ret = isc_configure(isc);357	if (unlikely(ret))358		goto err_configure;359 360	/* Enable DMA interrupt */361	regmap_write(regmap, ISC_INTEN, ISC_INT_DDONE);362 363	spin_lock_irqsave(&isc->dma_queue_lock, flags);364 365	isc->sequence = 0;366	isc->stop = false;367	reinit_completion(&isc->comp);368 369	isc->cur_frm = list_first_entry(&isc->dma_queue,370					struct isc_buffer, list);371	list_del(&isc->cur_frm->list);372 373	isc_crop_pfe(isc);374	isc_start_dma(isc);375 376	spin_unlock_irqrestore(&isc->dma_queue_lock, flags);377 378	/* if we streaming from RAW, we can do one-shot white balance adj */379	if (ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code))380		v4l2_ctrl_activate(isc->do_wb_ctrl, true);381 382	return 0;383 384err_configure:385	pm_runtime_put_sync(isc->dev);386err_pm_get:387	v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 0);388 389err_start_stream:390	spin_lock_irqsave(&isc->dma_queue_lock, flags);391	list_for_each_entry(buf, &isc->dma_queue, list)392		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);393	INIT_LIST_HEAD(&isc->dma_queue);394	spin_unlock_irqrestore(&isc->dma_queue_lock, flags);395 396	return ret;397}398 399static void isc_unprepare_streaming(struct vb2_queue *vq)400{401	struct isc_device *isc = vb2_get_drv_priv(vq);402 403	/* Stop media pipeline */404	media_pipeline_stop(isc->video_dev.entity.pads);405}406 407static void isc_stop_streaming(struct vb2_queue *vq)408{409	struct isc_device *isc = vb2_get_drv_priv(vq);410	unsigned long flags;411	struct isc_buffer *buf;412	int ret;413 414	mutex_lock(&isc->awb_mutex);415	v4l2_ctrl_activate(isc->do_wb_ctrl, false);416 417	isc->stop = true;418 419	/* Wait until the end of the current frame */420	if (isc->cur_frm && !wait_for_completion_timeout(&isc->comp, 5 * HZ))421		dev_err(isc->dev, "Timeout waiting for end of the capture\n");422 423	mutex_unlock(&isc->awb_mutex);424 425	/* Disable DMA interrupt */426	regmap_write(isc->regmap, ISC_INTDIS, ISC_INT_DDONE);427 428	pm_runtime_put_sync(isc->dev);429 430	/* Disable stream on the sub device */431	ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 0);432	if (ret && ret != -ENOIOCTLCMD)433		dev_err(isc->dev, "stream off failed in subdev\n");434 435	/* Release all active buffers */436	spin_lock_irqsave(&isc->dma_queue_lock, flags);437	if (unlikely(isc->cur_frm)) {438		vb2_buffer_done(&isc->cur_frm->vb.vb2_buf,439				VB2_BUF_STATE_ERROR);440		isc->cur_frm = NULL;441	}442	list_for_each_entry(buf, &isc->dma_queue, list)443		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);444	INIT_LIST_HEAD(&isc->dma_queue);445	spin_unlock_irqrestore(&isc->dma_queue_lock, flags);446}447 448static void isc_buffer_queue(struct vb2_buffer *vb)449{450	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);451	struct isc_buffer *buf = container_of(vbuf, struct isc_buffer, vb);452	struct isc_device *isc = vb2_get_drv_priv(vb->vb2_queue);453	unsigned long flags;454 455	spin_lock_irqsave(&isc->dma_queue_lock, flags);456	if (!isc->cur_frm && list_empty(&isc->dma_queue) &&457	    vb2_start_streaming_called(vb->vb2_queue)) {458		isc->cur_frm = buf;459		isc_start_dma(isc);460	} else {461		list_add_tail(&buf->list, &isc->dma_queue);462	}463	spin_unlock_irqrestore(&isc->dma_queue_lock, flags);464}465 466static const struct vb2_ops isc_vb2_ops = {467	.queue_setup		= isc_queue_setup,468	.wait_prepare		= vb2_ops_wait_prepare,469	.wait_finish		= vb2_ops_wait_finish,470	.buf_prepare		= isc_buffer_prepare,471	.start_streaming	= isc_start_streaming,472	.stop_streaming		= isc_stop_streaming,473	.buf_queue		= isc_buffer_queue,474	.prepare_streaming	= isc_prepare_streaming,475	.unprepare_streaming	= isc_unprepare_streaming,476};477 478static int isc_querycap(struct file *file, void *priv,479			struct v4l2_capability *cap)480{481	strscpy(cap->driver, "microchip-isc", sizeof(cap->driver));482	strscpy(cap->card, "Microchip Image Sensor Controller", sizeof(cap->card));483 484	return 0;485}486 487static int isc_enum_fmt_vid_cap(struct file *file, void *priv,488				struct v4l2_fmtdesc *f)489{490	struct isc_device *isc = video_drvdata(file);491	u32 index = f->index;492	u32 i, supported_index = 0;493	struct isc_format *fmt;494 495	/*496	 * If we are not asked a specific mbus_code, we have to report all497	 * the formats that we can output.498	 */499	if (!f->mbus_code) {500		if (index >= isc->controller_formats_size)501			return -EINVAL;502 503		f->pixelformat = isc->controller_formats[index].fourcc;504 505		return 0;506	}507 508	/*509	 * If a specific mbus_code is requested, check if we support510	 * this mbus_code as input for the ISC.511	 * If it's supported, then we report the corresponding pixelformat512	 * as first possible option for the ISC.513	 * E.g. mbus MEDIA_BUS_FMT_YUYV8_2X8 and report514	 * 'YUYV' (YUYV 4:2:2)515	 */516	fmt = isc_find_format_by_code(isc, f->mbus_code, &i);517	if (!fmt)518		return -EINVAL;519 520	if (!index) {521		f->pixelformat = fmt->fourcc;522 523		return 0;524	}525 526	supported_index++;527 528	/* If the index is not raw, we don't have anymore formats to report */529	if (!ISC_IS_FORMAT_RAW(f->mbus_code))530		return -EINVAL;531 532	/*533	 * We are asked for a specific mbus code, which is raw.534	 * We have to search through the formats we can convert to.535	 * We have to skip the raw formats, we cannot convert to raw.536	 * E.g. 'AR12' (16-bit ARGB 4-4-4-4), 'AR15' (16-bit ARGB 1-5-5-5), etc.537	 */538	for (i = 0; i < isc->controller_formats_size; i++) {539		if (isc->controller_formats[i].raw)540			continue;541		if (index == supported_index) {542			f->pixelformat = isc->controller_formats[i].fourcc;543			return 0;544		}545		supported_index++;546	}547 548	return -EINVAL;549}550 551static int isc_g_fmt_vid_cap(struct file *file, void *priv,552			     struct v4l2_format *fmt)553{554	struct isc_device *isc = video_drvdata(file);555 556	*fmt = isc->fmt;557 558	return 0;559}560 561/*562 * Checks the current configured format, if ISC can output it,563 * considering which type of format the ISC receives from the sensor564 */565static int isc_try_validate_formats(struct isc_device *isc)566{567	int ret;568	bool bayer = false, yuv = false, rgb = false, grey = false;569 570	/* all formats supported by the RLP module are OK */571	switch (isc->try_config.fourcc) {572	case V4L2_PIX_FMT_SBGGR8:573	case V4L2_PIX_FMT_SGBRG8:574	case V4L2_PIX_FMT_SGRBG8:575	case V4L2_PIX_FMT_SRGGB8:576	case V4L2_PIX_FMT_SBGGR10:577	case V4L2_PIX_FMT_SGBRG10:578	case V4L2_PIX_FMT_SGRBG10:579	case V4L2_PIX_FMT_SRGGB10:580	case V4L2_PIX_FMT_SBGGR12:581	case V4L2_PIX_FMT_SGBRG12:582	case V4L2_PIX_FMT_SGRBG12:583	case V4L2_PIX_FMT_SRGGB12:584		ret = 0;585		bayer = true;586		break;587 588	case V4L2_PIX_FMT_YUV420:589	case V4L2_PIX_FMT_YUV422P:590	case V4L2_PIX_FMT_YUYV:591	case V4L2_PIX_FMT_UYVY:592	case V4L2_PIX_FMT_VYUY:593		ret = 0;594		yuv = true;595		break;596 597	case V4L2_PIX_FMT_RGB565:598	case V4L2_PIX_FMT_ABGR32:599	case V4L2_PIX_FMT_XBGR32:600	case V4L2_PIX_FMT_ARGB444:601	case V4L2_PIX_FMT_ARGB555:602		ret = 0;603		rgb = true;604		break;605	case V4L2_PIX_FMT_GREY:606	case V4L2_PIX_FMT_Y10:607	case V4L2_PIX_FMT_Y16:608		ret = 0;609		grey = true;610		break;611	default:612	/* any other different formats are not supported */613		dev_err(isc->dev, "Requested unsupported format.\n");614		ret = -EINVAL;615	}616	dev_dbg(isc->dev,617		"Format validation, requested rgb=%u, yuv=%u, grey=%u, bayer=%u\n",618		rgb, yuv, grey, bayer);619 620	if (bayer &&621	    !ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) {622		dev_err(isc->dev, "Cannot output RAW if we do not receive RAW.\n");623		return -EINVAL;624	}625 626	if (grey && !ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code) &&627	    !ISC_IS_FORMAT_GREY(isc->try_config.sd_format->mbus_code)) {628		dev_err(isc->dev, "Cannot output GREY if we do not receive RAW/GREY.\n");629		return -EINVAL;630	}631 632	if ((rgb || bayer || yuv) &&633	    ISC_IS_FORMAT_GREY(isc->try_config.sd_format->mbus_code)) {634		dev_err(isc->dev, "Cannot convert GREY to another format.\n");635		return -EINVAL;636	}637 638	return ret;639}640 641/*642 * Configures the RLP and DMA modules, depending on the output format643 * configured for the ISC.644 * If direct_dump == true, just dump raw data 8/16 bits depending on format.645 */646static int isc_try_configure_rlp_dma(struct isc_device *isc, bool direct_dump)647{648	isc->try_config.rlp_cfg_mode = 0;649 650	switch (isc->try_config.fourcc) {651	case V4L2_PIX_FMT_SBGGR8:652	case V4L2_PIX_FMT_SGBRG8:653	case V4L2_PIX_FMT_SGRBG8:654	case V4L2_PIX_FMT_SRGGB8:655		isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8;656		isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED8;657		isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED;658		isc->try_config.bpp = 8;659		isc->try_config.bpp_v4l2 = 8;660		break;661	case V4L2_PIX_FMT_SBGGR10:662	case V4L2_PIX_FMT_SGBRG10:663	case V4L2_PIX_FMT_SGRBG10:664	case V4L2_PIX_FMT_SRGGB10:665		isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT10;666		isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16;667		isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED;668		isc->try_config.bpp = 16;669		isc->try_config.bpp_v4l2 = 16;670		break;671	case V4L2_PIX_FMT_SBGGR12:672	case V4L2_PIX_FMT_SGBRG12:673	case V4L2_PIX_FMT_SGRBG12:674	case V4L2_PIX_FMT_SRGGB12:675		isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT12;676		isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16;677		isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED;678		isc->try_config.bpp = 16;679		isc->try_config.bpp_v4l2 = 16;680		break;681	case V4L2_PIX_FMT_RGB565:682		isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_RGB565;683		isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16;684		isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED;685		isc->try_config.bpp = 16;686		isc->try_config.bpp_v4l2 = 16;687		break;688	case V4L2_PIX_FMT_ARGB444:689		isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB444;690		isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16;691		isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED;692		isc->try_config.bpp = 16;693		isc->try_config.bpp_v4l2 = 16;694		break;695	case V4L2_PIX_FMT_ARGB555:696		isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB555;697		isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16;698		isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED;699		isc->try_config.bpp = 16;700		isc->try_config.bpp_v4l2 = 16;701		break;702	case V4L2_PIX_FMT_ABGR32:703	case V4L2_PIX_FMT_XBGR32:704		isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB32;705		isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED32;706		isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED;707		isc->try_config.bpp = 32;708		isc->try_config.bpp_v4l2 = 32;709		break;710	case V4L2_PIX_FMT_YUV420:711		isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YYCC;712		isc->try_config.dcfg_imode = ISC_DCFG_IMODE_YC420P;713		isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PLANAR;714		isc->try_config.bpp = 12;715		isc->try_config.bpp_v4l2 = 8; /* only first plane */716		break;717	case V4L2_PIX_FMT_YUV422P:718		isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YYCC;719		isc->try_config.dcfg_imode = ISC_DCFG_IMODE_YC422P;720		isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PLANAR;721		isc->try_config.bpp = 16;722		isc->try_config.bpp_v4l2 = 8; /* only first plane */723		break;724	case V4L2_PIX_FMT_YUYV:725		isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YCYC | ISC_RLP_CFG_YMODE_YUYV;726		isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED32;727		isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED;728		isc->try_config.bpp = 16;729		isc->try_config.bpp_v4l2 = 16;730		break;731	case V4L2_PIX_FMT_UYVY:732		isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YCYC | ISC_RLP_CFG_YMODE_UYVY;733		isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED32;734		isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED;735		isc->try_config.bpp = 16;736		isc->try_config.bpp_v4l2 = 16;737		break;738	case V4L2_PIX_FMT_VYUY:739		isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YCYC | ISC_RLP_CFG_YMODE_VYUY;740		isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED32;741		isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED;742		isc->try_config.bpp = 16;743		isc->try_config.bpp_v4l2 = 16;744		break;745	case V4L2_PIX_FMT_GREY:746		isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DATY8;747		isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED8;748		isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED;749		isc->try_config.bpp = 8;750		isc->try_config.bpp_v4l2 = 8;751		break;752	case V4L2_PIX_FMT_Y16:753		isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DATY10 | ISC_RLP_CFG_LSH;754		fallthrough;755	case V4L2_PIX_FMT_Y10:756		isc->try_config.rlp_cfg_mode |= ISC_RLP_CFG_MODE_DATY10;757		isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16;758		isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED;759		isc->try_config.bpp = 16;760		isc->try_config.bpp_v4l2 = 16;761		break;762	default:763		return -EINVAL;764	}765 766	if (direct_dump) {767		isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8;768		isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED8;769		isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED;770		return 0;771	}772 773	return 0;774}775 776/*777 * Configuring pipeline modules, depending on which format the ISC outputs778 * and considering which format it has as input from the sensor.779 */780static int isc_try_configure_pipeline(struct isc_device *isc)781{782	switch (isc->try_config.fourcc) {783	case V4L2_PIX_FMT_RGB565:784	case V4L2_PIX_FMT_ARGB555:785	case V4L2_PIX_FMT_ARGB444:786	case V4L2_PIX_FMT_ABGR32:787	case V4L2_PIX_FMT_XBGR32:788		/* if sensor format is RAW, we convert inside ISC */789		if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) {790			isc->try_config.bits_pipeline = CFA_ENABLE |791				WB_ENABLE | GAM_ENABLES | DPC_BLCENABLE |792				CC_ENABLE;793		} else {794			isc->try_config.bits_pipeline = 0x0;795		}796		break;797	case V4L2_PIX_FMT_YUV420:798		/* if sensor format is RAW, we convert inside ISC */799		if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) {800			isc->try_config.bits_pipeline = CFA_ENABLE |801				CSC_ENABLE | GAM_ENABLES | WB_ENABLE |802				SUB420_ENABLE | SUB422_ENABLE | CBC_ENABLE |803				DPC_BLCENABLE;804		} else {805			isc->try_config.bits_pipeline = 0x0;806		}807		break;808	case V4L2_PIX_FMT_YUV422P:809		/* if sensor format is RAW, we convert inside ISC */810		if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) {811			isc->try_config.bits_pipeline = CFA_ENABLE |812				CSC_ENABLE | WB_ENABLE | GAM_ENABLES |813				SUB422_ENABLE | CBC_ENABLE | DPC_BLCENABLE;814		} else {815			isc->try_config.bits_pipeline = 0x0;816		}817		break;818	case V4L2_PIX_FMT_YUYV:819	case V4L2_PIX_FMT_UYVY:820	case V4L2_PIX_FMT_VYUY:821		/* if sensor format is RAW, we convert inside ISC */822		if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) {823			isc->try_config.bits_pipeline = CFA_ENABLE |824				CSC_ENABLE | WB_ENABLE | GAM_ENABLES |825				SUB422_ENABLE | CBC_ENABLE | DPC_BLCENABLE;826		} else {827			isc->try_config.bits_pipeline = 0x0;828		}829		break;830	case V4L2_PIX_FMT_GREY:831	case V4L2_PIX_FMT_Y16:832		/* if sensor format is RAW, we convert inside ISC */833		if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) {834			isc->try_config.bits_pipeline = CFA_ENABLE |835				CSC_ENABLE | WB_ENABLE | GAM_ENABLES |836				CBC_ENABLE | DPC_BLCENABLE;837		} else {838			isc->try_config.bits_pipeline = 0x0;839		}840		break;841	default:842		if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code))843			isc->try_config.bits_pipeline = WB_ENABLE | DPC_BLCENABLE;844		else845			isc->try_config.bits_pipeline = 0x0;846	}847 848	/* Tune the pipeline to product specific */849	isc->adapt_pipeline(isc);850 851	return 0;852}853 854static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f)855{856	struct v4l2_pix_format *pixfmt = &f->fmt.pix;857	unsigned int i;858 859	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)860		return -EINVAL;861 862	isc->try_config.fourcc = isc->controller_formats[0].fourcc;863 864	/* find if the format requested is supported */865	for (i = 0; i < isc->controller_formats_size; i++)866		if (isc->controller_formats[i].fourcc == pixfmt->pixelformat) {867			isc->try_config.fourcc = pixfmt->pixelformat;868			break;869		}870 871	isc_try_configure_rlp_dma(isc, false);872 873	/* Limit to Microchip ISC hardware capabilities */874	v4l_bound_align_image(&pixfmt->width, 16, isc->max_width, 0,875			      &pixfmt->height, 16, isc->max_height, 0, 0);876	/* If we did not find the requested format, we will fallback here */877	pixfmt->pixelformat = isc->try_config.fourcc;878	pixfmt->colorspace = V4L2_COLORSPACE_SRGB;879	pixfmt->field = V4L2_FIELD_NONE;880 881	pixfmt->bytesperline = (pixfmt->width * isc->try_config.bpp_v4l2) >> 3;882	pixfmt->sizeimage = ((pixfmt->width * isc->try_config.bpp) >> 3) *883			     pixfmt->height;884 885	isc->try_fmt = *f;886 887	return 0;888}889 890static int isc_set_fmt(struct isc_device *isc, struct v4l2_format *f)891{892	isc_try_fmt(isc, f);893 894	/* make the try configuration active */895	isc->config = isc->try_config;896	isc->fmt = isc->try_fmt;897 898	dev_dbg(isc->dev, "ISC set_fmt to %.4s @%dx%d\n",899		(char *)&f->fmt.pix.pixelformat,900		f->fmt.pix.width, f->fmt.pix.height);901 902	return 0;903}904 905static int isc_link_validate(struct media_link *link)906{907	struct video_device *vdev =908		media_entity_to_video_device(link->sink->entity);909	struct isc_device *isc = video_get_drvdata(vdev);910	int ret;911	int i;912	struct isc_format *sd_fmt = NULL;913	struct v4l2_pix_format *pixfmt = &isc->fmt.fmt.pix;914	struct v4l2_subdev_format format = {915		.which = V4L2_SUBDEV_FORMAT_ACTIVE,916		.pad = isc->remote_pad,917	};918 919	/* Get current format from subdev */920	ret = v4l2_subdev_call(isc->current_subdev->sd, pad, get_fmt, NULL,921			       &format);922	if (ret)923		return ret;924 925	/* Identify the subdev's format configuration */926	for (i = 0; i < isc->formats_list_size; i++)927		if (isc->formats_list[i].mbus_code == format.format.code) {928			sd_fmt = &isc->formats_list[i];929			break;930		}931 932	/* Check if the format is not supported */933	if (!sd_fmt) {934		dev_err(isc->dev,935			"Current subdevice is streaming a media bus code that is not supported 0x%x\n",936			format.format.code);937		return -EPIPE;938	}939 940	/* At this moment we know which format the subdev will use */941	isc->try_config.sd_format = sd_fmt;942 943	/* If the sensor is not RAW, we can only do a direct dump */944	if (!ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code))945		isc_try_configure_rlp_dma(isc, true);946 947	/* Limit to Microchip ISC hardware capabilities */948	v4l_bound_align_image(&format.format.width, 16, isc->max_width, 0,949			      &format.format.height, 16, isc->max_height, 0, 0);950 951	/* Check if the frame size is the same. Otherwise we may overflow */952	if (pixfmt->height != format.format.height ||953	    pixfmt->width != format.format.width) {954		dev_err(isc->dev,955			"ISC not configured with the proper frame size: %dx%d\n",956			format.format.width, format.format.height);957		return -EPIPE;958	}959 960	dev_dbg(isc->dev,961		"Identified subdev using format %.4s with %dx%d %d bpp\n",962		(char *)&sd_fmt->fourcc, pixfmt->width, pixfmt->height,963		isc->try_config.bpp);964 965	/* Reset and restart AWB if the subdevice changed the format */966	if (isc->try_config.sd_format && isc->config.sd_format &&967	    isc->try_config.sd_format != isc->config.sd_format) {968		isc->ctrls.hist_stat = HIST_INIT;969		isc_reset_awb_ctrls(isc);970		isc_update_v4l2_ctrls(isc);971	}972 973	/* Validate formats */974	ret = isc_try_validate_formats(isc);975	if (ret)976		return ret;977 978	/* Configure ISC pipeline for the config */979	ret = isc_try_configure_pipeline(isc);980	if (ret)981		return ret;982 983	isc->config = isc->try_config;984 985	dev_dbg(isc->dev, "New ISC configuration in place\n");986 987	return 0;988}989 990static int isc_s_fmt_vid_cap(struct file *file, void *priv,991			     struct v4l2_format *f)992{993	struct isc_device *isc = video_drvdata(file);994 995	if (vb2_is_busy(&isc->vb2_vidq))996		return -EBUSY;997 998	return isc_set_fmt(isc, f);999}1000 1001static int isc_try_fmt_vid_cap(struct file *file, void *priv,1002			       struct v4l2_format *f)1003{1004	struct isc_device *isc = video_drvdata(file);1005 1006	return isc_try_fmt(isc, f);1007}1008 1009static int isc_enum_input(struct file *file, void *priv,1010			  struct v4l2_input *inp)1011{1012	if (inp->index != 0)1013		return -EINVAL;1014 1015	inp->type = V4L2_INPUT_TYPE_CAMERA;1016	inp->std = 0;1017	strscpy(inp->name, "Camera", sizeof(inp->name));1018 1019	return 0;1020}1021 1022static int isc_g_input(struct file *file, void *priv, unsigned int *i)1023{1024	*i = 0;1025 1026	return 0;1027}1028 1029static int isc_s_input(struct file *file, void *priv, unsigned int i)1030{1031	if (i > 0)1032		return -EINVAL;1033 1034	return 0;1035}1036 1037static int isc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)1038{1039	struct isc_device *isc = video_drvdata(file);1040 1041	return v4l2_g_parm_cap(video_devdata(file), isc->current_subdev->sd, a);1042}1043 1044static int isc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)1045{1046	struct isc_device *isc = video_drvdata(file);1047 1048	return v4l2_s_parm_cap(video_devdata(file), isc->current_subdev->sd, a);1049}1050 1051static int isc_enum_framesizes(struct file *file, void *fh,1052			       struct v4l2_frmsizeenum *fsize)1053{1054	struct isc_device *isc = video_drvdata(file);1055	int ret = -EINVAL;1056	int i;1057 1058	if (fsize->index)1059		return -EINVAL;1060 1061	for (i = 0; i < isc->controller_formats_size; i++)1062		if (isc->controller_formats[i].fourcc == fsize->pixel_format)1063			ret = 0;1064 1065	if (ret)1066		return ret;1067 1068	fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;1069 1070	fsize->stepwise.min_width = 16;1071	fsize->stepwise.max_width = isc->max_width;1072	fsize->stepwise.min_height = 16;1073	fsize->stepwise.max_height = isc->max_height;1074	fsize->stepwise.step_width = 1;1075	fsize->stepwise.step_height = 1;1076 1077	return 0;1078}1079 1080static const struct v4l2_ioctl_ops isc_ioctl_ops = {1081	.vidioc_querycap		= isc_querycap,1082	.vidioc_enum_fmt_vid_cap	= isc_enum_fmt_vid_cap,1083	.vidioc_g_fmt_vid_cap		= isc_g_fmt_vid_cap,1084	.vidioc_s_fmt_vid_cap		= isc_s_fmt_vid_cap,1085	.vidioc_try_fmt_vid_cap		= isc_try_fmt_vid_cap,1086 1087	.vidioc_enum_input		= isc_enum_input,1088	.vidioc_g_input			= isc_g_input,1089	.vidioc_s_input			= isc_s_input,1090 1091	.vidioc_reqbufs			= vb2_ioctl_reqbufs,1092	.vidioc_querybuf		= vb2_ioctl_querybuf,1093	.vidioc_qbuf			= vb2_ioctl_qbuf,1094	.vidioc_expbuf			= vb2_ioctl_expbuf,1095	.vidioc_dqbuf			= vb2_ioctl_dqbuf,1096	.vidioc_create_bufs		= vb2_ioctl_create_bufs,1097	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,1098	.vidioc_streamon		= vb2_ioctl_streamon,1099	.vidioc_streamoff		= vb2_ioctl_streamoff,1100 1101	.vidioc_g_parm			= isc_g_parm,1102	.vidioc_s_parm			= isc_s_parm,1103	.vidioc_enum_framesizes		= isc_enum_framesizes,1104 1105	.vidioc_log_status		= v4l2_ctrl_log_status,1106	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,1107	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,1108};1109 1110static int isc_open(struct file *file)1111{1112	struct isc_device *isc = video_drvdata(file);1113	struct v4l2_subdev *sd = isc->current_subdev->sd;1114	int ret;1115 1116	if (mutex_lock_interruptible(&isc->lock))1117		return -ERESTARTSYS;1118 1119	ret = v4l2_fh_open(file);1120	if (ret < 0)1121		goto unlock;1122 1123	if (!v4l2_fh_is_singular_file(file))1124		goto unlock;1125 1126	ret = v4l2_subdev_call(sd, core, s_power, 1);1127	if (ret < 0 && ret != -ENOIOCTLCMD) {1128		v4l2_fh_release(file);1129		goto unlock;1130	}1131 1132	ret = isc_set_fmt(isc, &isc->fmt);1133	if (ret) {1134		v4l2_subdev_call(sd, core, s_power, 0);1135		v4l2_fh_release(file);1136	}1137 1138unlock:1139	mutex_unlock(&isc->lock);1140	return ret;1141}1142 1143static int isc_release(struct file *file)1144{1145	struct isc_device *isc = video_drvdata(file);1146	struct v4l2_subdev *sd = isc->current_subdev->sd;1147	bool fh_singular;1148	int ret;1149 1150	mutex_lock(&isc->lock);1151 1152	fh_singular = v4l2_fh_is_singular_file(file);1153 1154	ret = _vb2_fop_release(file, NULL);1155 1156	if (fh_singular)1157		v4l2_subdev_call(sd, core, s_power, 0);1158 1159	mutex_unlock(&isc->lock);1160 1161	return ret;1162}1163 1164static const struct v4l2_file_operations isc_fops = {1165	.owner		= THIS_MODULE,1166	.open		= isc_open,1167	.release	= isc_release,1168	.unlocked_ioctl	= video_ioctl2,1169	.read		= vb2_fop_read,1170	.mmap		= vb2_fop_mmap,1171	.poll		= vb2_fop_poll,1172};1173 1174irqreturn_t microchip_isc_interrupt(int irq, void *dev_id)1175{1176	struct isc_device *isc = (struct isc_device *)dev_id;1177	struct regmap *regmap = isc->regmap;1178	u32 isc_intsr, isc_intmask, pending;1179	irqreturn_t ret = IRQ_NONE;1180 1181	regmap_read(regmap, ISC_INTSR, &isc_intsr);1182	regmap_read(regmap, ISC_INTMASK, &isc_intmask);1183 1184	pending = isc_intsr & isc_intmask;1185 1186	if (likely(pending & ISC_INT_DDONE)) {1187		spin_lock(&isc->dma_queue_lock);1188		if (isc->cur_frm) {1189			struct vb2_v4l2_buffer *vbuf = &isc->cur_frm->vb;1190			struct vb2_buffer *vb = &vbuf->vb2_buf;1191 1192			vb->timestamp = ktime_get_ns();1193			vbuf->sequence = isc->sequence++;1194			vb2_buffer_done(vb, VB2_BUF_STATE_DONE);1195			isc->cur_frm = NULL;1196		}1197 1198		if (!list_empty(&isc->dma_queue) && !isc->stop) {1199			isc->cur_frm = list_first_entry(&isc->dma_queue,1200							struct isc_buffer, list);1201			list_del(&isc->cur_frm->list);1202 1203			isc_start_dma(isc);1204		}1205 1206		if (isc->stop)1207			complete(&isc->comp);1208 1209		ret = IRQ_HANDLED;1210		spin_unlock(&isc->dma_queue_lock);1211	}1212 1213	if (pending & ISC_INT_HISDONE) {1214		schedule_work(&isc->awb_work);1215		ret = IRQ_HANDLED;1216	}1217 1218	return ret;1219}1220EXPORT_SYMBOL_GPL(microchip_isc_interrupt);1221 1222static void isc_hist_count(struct isc_device *isc, u32 *min, u32 *max)1223{1224	struct regmap *regmap = isc->regmap;1225	struct isc_ctrls *ctrls = &isc->ctrls;1226	u32 *hist_count = &ctrls->hist_count[ctrls->hist_id];1227	u32 *hist_entry = &ctrls->hist_entry[0];1228	u32 i;1229 1230	*min = 0;1231	*max = HIST_ENTRIES;1232 1233	regmap_bulk_read(regmap, ISC_HIS_ENTRY + isc->offsets.his_entry,1234			 hist_entry, HIST_ENTRIES);1235 1236	*hist_count = 0;1237	/*1238	 * we deliberately ignore the end of the histogram,1239	 * the most white pixels1240	 */1241	for (i = 1; i < HIST_ENTRIES; i++) {1242		if (*hist_entry && !*min)1243			*min = i;1244		if (*hist_entry)1245			*max = i;1246		*hist_count += i * (*hist_entry++);1247	}1248 1249	if (!*min)1250		*min = 1;1251 1252	dev_dbg(isc->dev, "isc wb: hist_id %u, hist_count %u",1253		ctrls->hist_id, *hist_count);1254}1255 1256static void isc_wb_update(struct isc_ctrls *ctrls)1257{1258	struct isc_device *isc = container_of(ctrls, struct isc_device, ctrls);1259	u32 *hist_count = &ctrls->hist_count[0];1260	u32 c, offset[4];1261	u64 avg = 0;1262	/* We compute two gains, stretch gain and grey world gain */1263	u32 s_gain[4], gw_gain[4];1264 1265	/*1266	 * According to Grey World, we need to set gains for R/B to normalize1267	 * them towards the green channel.1268	 * Thus we want to keep Green as fixed and adjust only Red/Blue1269	 * Compute the average of the both green channels first1270	 */1271	avg = (u64)hist_count[ISC_HIS_CFG_MODE_GR] +1272		(u64)hist_count[ISC_HIS_CFG_MODE_GB];1273	avg >>= 1;1274 1275	dev_dbg(isc->dev, "isc wb: green components average %llu\n", avg);1276 1277	/* Green histogram is null, nothing to do */1278	if (!avg)1279		return;1280 1281	for (c = ISC_HIS_CFG_MODE_GR; c <= ISC_HIS_CFG_MODE_B; c++) {1282		/*1283		 * the color offset is the minimum value of the histogram.1284		 * we stretch this color to the full range by substracting1285		 * this value from the color component.1286		 */1287		offset[c] = ctrls->hist_minmax[c][HIST_MIN_INDEX];1288		/*1289		 * The offset is always at least 1. If the offset is 1, we do1290		 * not need to adjust it, so our result must be zero.1291		 * the offset is computed in a histogram on 9 bits (0..512)1292		 * but the offset in register is based on1293		 * 12 bits pipeline (0..4096).1294		 * we need to shift with the 3 bits that the histogram is1295		 * ignoring1296		 */1297		ctrls->offset[c] = (offset[c] - 1) << 3;1298 1299		/*1300		 * the offset is then taken and converted to 2's complements,1301		 * and must be negative, as we subtract this value from the1302		 * color components1303		 */1304		ctrls->offset[c] = -ctrls->offset[c];1305 1306		/*1307		 * the stretch gain is the total number of histogram bins1308		 * divided by the actual range of color component (Max - Min)1309		 * If we compute gain like this, the actual color component1310		 * will be stretched to the full histogram.1311		 * We need to shift 9 bits for precision, we have 9 bits for1312		 * decimals1313		 */1314		s_gain[c] = (HIST_ENTRIES << 9) /1315			(ctrls->hist_minmax[c][HIST_MAX_INDEX] -1316			ctrls->hist_minmax[c][HIST_MIN_INDEX] + 1);1317 1318		/*1319		 * Now we have to compute the gain w.r.t. the average.1320		 * Add/lose gain to the component towards the average.1321		 * If it happens that the component is zero, use the1322		 * fixed point value : 1.0 gain.1323		 */1324		if (hist_count[c])1325			gw_gain[c] = div_u64(avg << 9, hist_count[c]);1326		else1327			gw_gain[c] = 1 << 9;1328 1329		dev_dbg(isc->dev,1330			"isc wb: component %d, s_gain %u, gw_gain %u\n",1331			c, s_gain[c], gw_gain[c]);1332		/* multiply both gains and adjust for decimals */1333		ctrls->gain[c] = s_gain[c] * gw_gain[c];1334		ctrls->gain[c] >>= 9;1335 1336		/* make sure we are not out of range */1337		ctrls->gain[c] = clamp_val(ctrls->gain[c], 0, GENMASK(12, 0));1338 1339		dev_dbg(isc->dev, "isc wb: component %d, final gain %u\n",1340			c, ctrls->gain[c]);1341	}1342}1343 1344static void isc_awb_work(struct work_struct *w)1345{1346	struct isc_device *isc =1347		container_of(w, struct isc_device, awb_work);1348	struct regmap *regmap = isc->regmap;1349	struct isc_ctrls *ctrls = &isc->ctrls;1350	u32 hist_id = ctrls->hist_id;1351	u32 baysel;1352	unsigned long flags;1353	u32 min, max;1354	int ret;1355 1356	if (ctrls->hist_stat != HIST_ENABLED)1357		return;1358 1359	isc_hist_count(isc, &min, &max);1360 1361	dev_dbg(isc->dev,1362		"isc wb mode %d: hist min %u , max %u\n", hist_id, min, max);1363 1364	ctrls->hist_minmax[hist_id][HIST_MIN_INDEX] = min;1365	ctrls->hist_minmax[hist_id][HIST_MAX_INDEX] = max;1366 1367	if (hist_id != ISC_HIS_CFG_MODE_B) {1368		hist_id++;1369	} else {1370		isc_wb_update(ctrls);1371		hist_id = ISC_HIS_CFG_MODE_GR;1372	}1373 1374	ctrls->hist_id = hist_id;1375	baysel = isc->config.sd_format->cfa_baycfg << ISC_HIS_CFG_BAYSEL_SHIFT;1376 1377	ret = pm_runtime_resume_and_get(isc->dev);1378	if (ret < 0)1379		return;1380 1381	/*1382	 * only update if we have all the required histograms and controls1383	 * if awb has been disabled, we need to reset registers as well.1384	 */1385	if (hist_id == ISC_HIS_CFG_MODE_GR || ctrls->awb == ISC_WB_NONE) {1386		/*1387		 * It may happen that DMA Done IRQ will trigger while we are1388		 * updating white balance registers here.1389		 * In that case, only parts of the controls have been updated.1390		 * We can avoid that by locking the section.1391		 */1392		spin_lock_irqsave(&isc->awb_lock, flags);1393		isc_update_awb_ctrls(isc);1394		spin_unlock_irqrestore(&isc->awb_lock, flags);1395 1396		/*1397		 * if we are doing just the one time white balance adjustment,1398		 * we are basically done.1399		 */1400		if (ctrls->awb == ISC_WB_ONETIME) {1401			dev_info(isc->dev,1402				 "Completed one time white-balance adjustment.\n");1403			/* update the v4l2 controls values */1404			isc_update_v4l2_ctrls(isc);1405			ctrls->awb = ISC_WB_NONE;1406		}1407	}1408	regmap_write(regmap, ISC_HIS_CFG + isc->offsets.his,1409		     hist_id | baysel | ISC_HIS_CFG_RAR);1410 1411	/*1412	 * We have to make sure the streaming has not stopped meanwhile.1413	 * ISC requires a frame to clock the internal profile update.1414	 * To avoid issues, lock the sequence with a mutex1415	 */1416	mutex_lock(&isc->awb_mutex);1417 1418	/* streaming is not active anymore */1419	if (isc->stop) {1420		mutex_unlock(&isc->awb_mutex);1421		return;1422	}1423 1424	isc_update_profile(isc);1425 1426	mutex_unlock(&isc->awb_mutex);1427 1428	/* if awb has been disabled, we don't need to start another histogram */1429	if (ctrls->awb)1430		regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_HISREQ);1431 1432	pm_runtime_put_sync(isc->dev);1433}1434 1435static int isc_s_ctrl(struct v4l2_ctrl *ctrl)1436{1437	struct isc_device *isc = container_of(ctrl->handler,1438					     struct isc_device, ctrls.handler);1439	struct isc_ctrls *ctrls = &isc->ctrls;1440 1441	if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)1442		return 0;1443 1444	switch (ctrl->id) {1445	case V4L2_CID_BRIGHTNESS:1446		ctrls->brightness = ctrl->val & ISC_CBC_BRIGHT_MASK;1447		break;1448	case V4L2_CID_CONTRAST:1449		ctrls->contrast = ctrl->val & ISC_CBC_CONTRAST_MASK;1450		break;1451	case V4L2_CID_GAMMA:1452		ctrls->gamma_index = ctrl->val;1453		break;1454	default:1455		return -EINVAL;1456	}1457 1458	return 0;1459}1460 1461static const struct v4l2_ctrl_ops isc_ctrl_ops = {1462	.s_ctrl	= isc_s_ctrl,1463};1464 1465static int isc_s_awb_ctrl(struct v4l2_ctrl *ctrl)1466{1467	struct isc_device *isc = container_of(ctrl->handler,1468					     struct isc_device, ctrls.handler);1469	struct isc_ctrls *ctrls = &isc->ctrls;1470 1471	if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)1472		return 0;1473 1474	switch (ctrl->id) {1475	case V4L2_CID_AUTO_WHITE_BALANCE:1476		if (ctrl->val == 1)1477			ctrls->awb = ISC_WB_AUTO;1478		else1479			ctrls->awb = ISC_WB_NONE;1480 1481		/* configure the controls with new values from v4l2 */1482		if (ctrl->cluster[ISC_CTRL_R_GAIN]->is_new)1483			ctrls->gain[ISC_HIS_CFG_MODE_R] = isc->r_gain_ctrl->val;1484		if (ctrl->cluster[ISC_CTRL_B_GAIN]->is_new)1485			ctrls->gain[ISC_HIS_CFG_MODE_B] = isc->b_gain_ctrl->val;1486		if (ctrl->cluster[ISC_CTRL_GR_GAIN]->is_new)1487			ctrls->gain[ISC_HIS_CFG_MODE_GR] = isc->gr_gain_ctrl->val;1488		if (ctrl->cluster[ISC_CTRL_GB_GAIN]->is_new)1489			ctrls->gain[ISC_HIS_CFG_MODE_GB] = isc->gb_gain_ctrl->val;1490 1491		if (ctrl->cluster[ISC_CTRL_R_OFF]->is_new)1492			ctrls->offset[ISC_HIS_CFG_MODE_R] = isc->r_off_ctrl->val;1493		if (ctrl->cluster[ISC_CTRL_B_OFF]->is_new)1494			ctrls->offset[ISC_HIS_CFG_MODE_B] = isc->b_off_ctrl->val;1495		if (ctrl->cluster[ISC_CTRL_GR_OFF]->is_new)1496			ctrls->offset[ISC_HIS_CFG_MODE_GR] = isc->gr_off_ctrl->val;1497		if (ctrl->cluster[ISC_CTRL_GB_OFF]->is_new)1498			ctrls->offset[ISC_HIS_CFG_MODE_GB] = isc->gb_off_ctrl->val;1499 1500		isc_update_awb_ctrls(isc);1501 1502		mutex_lock(&isc->awb_mutex);1503		if (vb2_is_streaming(&isc->vb2_vidq)) {1504			/*1505			 * If we are streaming, we can update profile to1506			 * have the new settings in place.1507			 */1508			isc_update_profile(isc);1509		} else {1510			/*1511			 * The auto cluster will activate automatically this1512			 * control. This has to be deactivated when not1513			 * streaming.1514			 */1515			v4l2_ctrl_activate(isc->do_wb_ctrl, false);1516		}1517		mutex_unlock(&isc->awb_mutex);1518 1519		/* if we have autowhitebalance on, start histogram procedure */1520		if (ctrls->awb == ISC_WB_AUTO &&1521		    vb2_is_streaming(&isc->vb2_vidq) &&1522		    ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code))1523			isc_set_histogram(isc, true);1524 1525		/*1526		 * for one time whitebalance adjustment, check the button,1527		 * if it's pressed, perform the one time operation.1528		 */1529		if (ctrls->awb == ISC_WB_NONE &&1530		    ctrl->cluster[ISC_CTRL_DO_WB]->is_new &&1531		    !(ctrl->cluster[ISC_CTRL_DO_WB]->flags &1532		    V4L2_CTRL_FLAG_INACTIVE)) {1533			ctrls->awb = ISC_WB_ONETIME;1534			isc_set_histogram(isc, true);1535			dev_dbg(isc->dev, "One time white-balance started.\n");1536		}1537		return 0;1538	}1539	return 0;1540}1541 1542static int isc_g_volatile_awb_ctrl(struct v4l2_ctrl *ctrl)1543{1544	struct isc_device *isc = container_of(ctrl->handler,1545					     struct isc_device, ctrls.handler);1546	struct isc_ctrls *ctrls = &isc->ctrls;1547 1548	switch (ctrl->id) {1549	/* being a cluster, this id will be called for every control */1550	case V4L2_CID_AUTO_WHITE_BALANCE:1551		ctrl->cluster[ISC_CTRL_R_GAIN]->val =1552					ctrls->gain[ISC_HIS_CFG_MODE_R];1553		ctrl->cluster[ISC_CTRL_B_GAIN]->val =1554					ctrls->gain[ISC_HIS_CFG_MODE_B];1555		ctrl->cluster[ISC_CTRL_GR_GAIN]->val =1556					ctrls->gain[ISC_HIS_CFG_MODE_GR];1557		ctrl->cluster[ISC_CTRL_GB_GAIN]->val =1558					ctrls->gain[ISC_HIS_CFG_MODE_GB];1559 1560		ctrl->cluster[ISC_CTRL_R_OFF]->val =1561			ctrls->offset[ISC_HIS_CFG_MODE_R];1562		ctrl->cluster[ISC_CTRL_B_OFF]->val =1563			ctrls->offset[ISC_HIS_CFG_MODE_B];1564		ctrl->cluster[ISC_CTRL_GR_OFF]->val =1565			ctrls->offset[ISC_HIS_CFG_MODE_GR];1566		ctrl->cluster[ISC_CTRL_GB_OFF]->val =1567			ctrls->offset[ISC_HIS_CFG_MODE_GB];1568		break;1569	}1570	return 0;1571}1572 1573static const struct v4l2_ctrl_ops isc_awb_ops = {1574	.s_ctrl = isc_s_awb_ctrl,1575	.g_volatile_ctrl = isc_g_volatile_awb_ctrl,1576};1577 1578#define ISC_CTRL_OFF(_name, _id, _name_str) \1579	static const struct v4l2_ctrl_config _name = { \1580		.ops = &isc_awb_ops, \1581		.id = _id, \1582		.name = _name_str, \1583		.type = V4L2_CTRL_TYPE_INTEGER, \1584		.flags = V4L2_CTRL_FLAG_SLIDER, \1585		.min = -4095, \1586		.max = 4095, \1587		.step = 1, \1588		.def = 0, \1589	}1590 1591ISC_CTRL_OFF(isc_r_off_ctrl, ISC_CID_R_OFFSET, "Red Component Offset");1592ISC_CTRL_OFF(isc_b_off_ctrl, ISC_CID_B_OFFSET, "Blue Component Offset");1593ISC_CTRL_OFF(isc_gr_off_ctrl, ISC_CID_GR_OFFSET, "Green Red Component Offset");1594ISC_CTRL_OFF(isc_gb_off_ctrl, ISC_CID_GB_OFFSET, "Green Blue Component Offset");1595 1596#define ISC_CTRL_GAIN(_name, _id, _name_str) \1597	static const struct v4l2_ctrl_config _name = { \1598		.ops = &isc_awb_ops, \1599		.id = _id, \1600		.name = _name_str, \1601		.type = V4L2_CTRL_TYPE_INTEGER, \1602		.flags = V4L2_CTRL_FLAG_SLIDER, \1603		.min = 0, \1604		.max = 8191, \1605		.step = 1, \1606		.def = 512, \1607	}1608 1609ISC_CTRL_GAIN(isc_r_gain_ctrl, ISC_CID_R_GAIN, "Red Component Gain");1610ISC_CTRL_GAIN(isc_b_gain_ctrl, ISC_CID_B_GAIN, "Blue Component Gain");1611ISC_CTRL_GAIN(isc_gr_gain_ctrl, ISC_CID_GR_GAIN, "Green Red Component Gain");1612ISC_CTRL_GAIN(isc_gb_gain_ctrl, ISC_CID_GB_GAIN, "Green Blue Component Gain");1613 1614static int isc_ctrl_init(struct isc_device *isc)1615{1616	const struct v4l2_ctrl_ops *ops = &isc_ctrl_ops;1617	struct isc_ctrls *ctrls = &isc->ctrls;1618	struct v4l2_ctrl_handler *hdl = &ctrls->handler;1619	int ret;1620 1621	ctrls->hist_stat = HIST_INIT;1622	isc_reset_awb_ctrls(isc);1623 1624	ret = v4l2_ctrl_handler_init(hdl, 13);1625	if (ret < 0)1626		return ret;1627 1628	/* Initialize product specific controls. For example, contrast */1629	isc->config_ctrls(isc, ops);1630 1631	ctrls->brightness = 0;1632 1633	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -1024, 1023, 1, 0);1634	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAMMA, 0, isc->gamma_max, 1,1635			  isc->gamma_max);1636	isc->awb_ctrl = v4l2_ctrl_new_std(hdl, &isc_awb_ops,1637					  V4L2_CID_AUTO_WHITE_BALANCE,1638					  0, 1, 1, 1);1639 1640	/* do_white_balance is a button, so min,max,step,default are ignored */1641	isc->do_wb_ctrl = v4l2_ctrl_new_std(hdl, &isc_awb_ops,1642					    V4L2_CID_DO_WHITE_BALANCE,1643					    0, 0, 0, 0);1644 1645	if (!isc->do_wb_ctrl) {1646		ret = hdl->error;1647		v4l2_ctrl_handler_free(hdl);1648		return ret;1649	}1650 1651	v4l2_ctrl_activate(isc->do_wb_ctrl, false);1652 1653	isc->r_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_r_gain_ctrl, NULL);1654	isc->b_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_b_gain_ctrl, NULL);1655	isc->gr_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gr_gain_ctrl, NULL);1656	isc->gb_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gb_gain_ctrl, NULL);1657	isc->r_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_r_off_ctrl, NULL);1658	isc->b_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_b_off_ctrl, NULL);1659	isc->gr_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gr_off_ctrl, NULL);1660	isc->gb_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gb_off_ctrl, NULL);1661 1662	/*1663	 * The cluster is in auto mode with autowhitebalance enabled1664	 * and manual mode otherwise.1665	 */1666	v4l2_ctrl_auto_cluster(10, &isc->awb_ctrl, 0, true);1667 1668	v4l2_ctrl_handler_setup(hdl);1669 1670	return 0;1671}1672 1673static int isc_async_bound(struct v4l2_async_notifier *notifier,1674			   struct v4l2_subdev *subdev,1675			   struct v4l2_async_connection *asd)1676{1677	struct isc_device *isc = container_of(notifier->v4l2_dev,1678					      struct isc_device, v4l2_dev);1679	struct isc_subdev_entity *subdev_entity =1680		container_of(notifier, struct isc_subdev_entity, notifier);1681	int pad;1682 1683	if (video_is_registered(&isc->video_dev)) {1684		dev_err(isc->dev, "only supports one sub-device.\n");1685		return -EBUSY;1686	}1687 1688	subdev_entity->sd = subdev;1689 1690	pad = media_entity_get_fwnode_pad(&subdev->entity, asd->match.fwnode,1691					  MEDIA_PAD_FL_SOURCE);1692	if (pad < 0) {1693		dev_err(isc->dev, "failed to find pad for %s\n", subdev->name);1694		return pad;1695	}1696 1697	isc->remote_pad = pad;1698 1699	return 0;1700}1701 1702static void isc_async_unbind(struct v4l2_async_notifier *notifier,1703			     struct v4l2_subdev *subdev,1704			     struct v4l2_async_connection *asd)1705{1706	struct isc_device *isc = container_of(notifier->v4l2_dev,1707					      struct isc_device, v4l2_dev);1708	mutex_destroy(&isc->awb_mutex);1709	cancel_work_sync(&isc->awb_work);1710	video_unregister_device(&isc->video_dev);1711	v4l2_ctrl_handler_free(&isc->ctrls.handler);1712}1713 1714struct isc_format *isc_find_format_by_code(struct isc_device *isc,1715					   unsigned int code, int *index)1716{1717	struct isc_format *fmt = &isc->formats_list[0];1718	unsigned int i;1719 1720	for (i = 0; i < isc->formats_list_size; i++) {1721		if (fmt->mbus_code == code) {1722			*index = i;1723			return fmt;1724		}1725 1726		fmt++;1727	}1728 1729	return NULL;1730}1731EXPORT_SYMBOL_GPL(isc_find_format_by_code);1732 1733static int isc_set_default_fmt(struct isc_device *isc)1734{1735	struct v4l2_format f = {1736		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,1737		.fmt.pix = {1738			.width		= VGA_WIDTH,1739			.height		= VGA_HEIGHT,1740			.field		= V4L2_FIELD_NONE,1741			.pixelformat	= isc->controller_formats[0].fourcc,1742		},1743	};1744	int ret;1745 1746	ret = isc_try_fmt(isc, &f);1747	if (ret)1748		return ret;1749 1750	isc->fmt = f;1751	return 0;1752}1753 1754static int isc_async_complete(struct v4l2_async_notifier *notifier)1755{1756	struct isc_device *isc = container_of(notifier->v4l2_dev,1757					      struct isc_device, v4l2_dev);1758	struct video_device *vdev = &isc->video_dev;1759	struct vb2_queue *q = &isc->vb2_vidq;1760	int ret = 0;1761 1762	INIT_WORK(&isc->awb_work, isc_awb_work);1763 1764	ret = v4l2_device_register_subdev_nodes(&isc->v4l2_dev);1765	if (ret < 0) {1766		dev_err(isc->dev, "Failed to register subdev nodes\n");1767		return ret;1768	}1769 1770	isc->current_subdev = container_of(notifier,1771					   struct isc_subdev_entity, notifier);1772	mutex_init(&isc->lock);1773	mutex_init(&isc->awb_mutex);1774 1775	init_completion(&isc->comp);1776 1777	/* Initialize videobuf2 queue */1778	q->type			= V4L2_BUF_TYPE_VIDEO_CAPTURE;1779	q->io_modes		= VB2_MMAP | VB2_DMABUF | VB2_READ;1780	q->drv_priv		= isc;1781	q->buf_struct_size	= sizeof(struct isc_buffer);1782	q->ops			= &isc_vb2_ops;1783	q->mem_ops		= &vb2_dma_contig_memops;1784	q->timestamp_flags	= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;1785	q->lock			= &isc->lock;1786	q->min_queued_buffers	= 1;1787	q->dev			= isc->dev;1788 1789	ret = vb2_queue_init(q);1790	if (ret < 0) {1791		dev_err(isc->dev, "vb2_queue_init() failed: %d\n", ret);1792		goto isc_async_complete_err;1793	}1794 1795	/* Init video dma queues */1796	INIT_LIST_HEAD(&isc->dma_queue);1797	spin_lock_init(&isc->dma_queue_lock);1798	spin_lock_init(&isc->awb_lock);1799 1800	ret = isc_set_default_fmt(isc);1801	if (ret) {1802		dev_err(isc->dev, "Could not set default format\n");1803		goto isc_async_complete_err;1804	}1805 1806	ret = isc_ctrl_init(isc);1807	if (ret) {1808		dev_err(isc->dev, "Init isc ctrols failed: %d\n", ret);1809		goto isc_async_complete_err;1810	}1811 1812	/* Register video device */1813	strscpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name));1814	vdev->release		= video_device_release_empty;1815	vdev->fops		= &isc_fops;1816	vdev->ioctl_ops		= &isc_ioctl_ops;1817	vdev->v4l2_dev		= &isc->v4l2_dev;1818	vdev->vfl_dir		= VFL_DIR_RX;1819	vdev->queue		= q;1820	vdev->lock		= &isc->lock;1821	vdev->ctrl_handler	= &isc->ctrls.handler;1822	vdev->device_caps	= V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |1823				  V4L2_CAP_IO_MC;1824	video_set_drvdata(vdev, isc);1825 1826	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);1827	if (ret < 0) {1828		dev_err(isc->dev, "video_register_device failed: %d\n", ret);1829		goto isc_async_complete_err;1830	}1831 1832	ret = isc_scaler_link(isc);1833	if (ret < 0)1834		goto isc_async_complete_unregister_device;1835 1836	ret = media_device_register(&isc->mdev);1837	if (ret < 0)1838		goto isc_async_complete_unregister_device;1839 1840	return 0;1841 1842isc_async_complete_unregister_device:1843	video_unregister_device(vdev);1844 1845isc_async_complete_err:1846	mutex_destroy(&isc->awb_mutex);1847	mutex_destroy(&isc->lock);1848	return ret;1849}1850 1851const struct v4l2_async_notifier_operations microchip_isc_async_ops = {1852	.bound = isc_async_bound,1853	.unbind = isc_async_unbind,1854	.complete = isc_async_complete,1855};1856EXPORT_SYMBOL_GPL(microchip_isc_async_ops);1857 1858void microchip_isc_subdev_cleanup(struct isc_device *isc)1859{1860	struct isc_subdev_entity *subdev_entity;1861 1862	list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {1863		v4l2_async_nf_unregister(&subdev_entity->notifier);1864		v4l2_async_nf_cleanup(&subdev_entity->notifier);1865	}1866 1867	INIT_LIST_HEAD(&isc->subdev_entities);1868}1869EXPORT_SYMBOL_GPL(microchip_isc_subdev_cleanup);1870 1871int microchip_isc_pipeline_init(struct isc_device *isc)1872{1873	struct device *dev = isc->dev;1874	struct regmap *regmap = isc->regmap;1875	struct regmap_field *regs;1876	unsigned int i;1877 1878	/*1879	 * DPCEN-->GDCEN-->BLCEN-->WB-->CFA-->CC-->1880	 * GAM-->VHXS-->CSC-->CBC-->SUB422-->SUB4201881	 */1882	const struct reg_field regfields[ISC_PIPE_LINE_NODE_NUM] = {1883		REG_FIELD(ISC_DPC_CTRL, 0, 0),1884		REG_FIELD(ISC_DPC_CTRL, 1, 1),1885		REG_FIELD(ISC_DPC_CTRL, 2, 2),1886		REG_FIELD(ISC_WB_CTRL, 0, 0),1887		REG_FIELD(ISC_CFA_CTRL, 0, 0),1888		REG_FIELD(ISC_CC_CTRL, 0, 0),1889		REG_FIELD(ISC_GAM_CTRL, 0, 0),1890		REG_FIELD(ISC_GAM_CTRL, 1, 1),1891		REG_FIELD(ISC_GAM_CTRL, 2, 2),1892		REG_FIELD(ISC_GAM_CTRL, 3, 3),1893		REG_FIELD(ISC_VHXS_CTRL, 0, 0),1894		REG_FIELD(ISC_CSC_CTRL + isc->offsets.csc, 0, 0),1895		REG_FIELD(ISC_CBC_CTRL + isc->offsets.cbc, 0, 0),1896		REG_FIELD(ISC_SUB422_CTRL + isc->offsets.sub422, 0, 0),1897		REG_FIELD(ISC_SUB420_CTRL + isc->offsets.sub420, 0, 0),1898	};1899 1900	for (i = 0; i < ISC_PIPE_LINE_NODE_NUM; i++) {1901		regs = devm_regmap_field_alloc(dev, regmap, regfields[i]);1902		if (IS_ERR(regs))1903			return PTR_ERR(regs);1904 1905		isc->pipeline[i] =  regs;1906	}1907 1908	return 0;1909}1910EXPORT_SYMBOL_GPL(microchip_isc_pipeline_init);1911 1912static const struct media_entity_operations isc_entity_operations = {1913	.link_validate = isc_link_validate,1914};1915 1916int isc_mc_init(struct isc_device *isc, u32 ver)1917{1918	const struct of_device_id *match;1919	int ret;1920 1921	isc->video_dev.entity.function = MEDIA_ENT_F_IO_V4L;1922	isc->video_dev.entity.flags = MEDIA_ENT_FL_DEFAULT;1923	isc->video_dev.entity.ops = &isc_entity_operations;1924 1925	isc->pads[ISC_PAD_SINK].flags = MEDIA_PAD_FL_SINK;1926 1927	ret = media_entity_pads_init(&isc->video_dev.entity, ISC_PADS_NUM,1928				     isc->pads);1929	if (ret < 0) {1930		dev_err(isc->dev, "media entity init failed\n");1931		return ret;1932	}1933 1934	isc->mdev.dev = isc->dev;1935 1936	match = of_match_node(isc->dev->driver->of_match_table,1937			      isc->dev->of_node);1938 1939	strscpy(isc->mdev.driver_name, KBUILD_MODNAME,1940		sizeof(isc->mdev.driver_name));1941	strscpy(isc->mdev.model, match->compatible, sizeof(isc->mdev.model));1942	isc->mdev.hw_revision = ver;1943 1944	media_device_init(&isc->mdev);1945 1946	isc->v4l2_dev.mdev = &isc->mdev;1947 1948	return isc_scaler_init(isc);1949}1950EXPORT_SYMBOL_GPL(isc_mc_init);1951 1952void isc_mc_cleanup(struct isc_device *isc)1953{1954	media_entity_cleanup(&isc->video_dev.entity);1955	media_device_cleanup(&isc->mdev);1956}1957EXPORT_SYMBOL_GPL(isc_mc_cleanup);1958 1959/* regmap configuration */1960#define MICROCHIP_ISC_REG_MAX    0xd5c1961const struct regmap_config microchip_isc_regmap_config = {1962	.reg_bits       = 32,1963	.reg_stride     = 4,1964	.val_bits       = 32,1965	.max_register	= MICROCHIP_ISC_REG_MAX,1966};1967EXPORT_SYMBOL_GPL(microchip_isc_regmap_config);1968 1969MODULE_AUTHOR("Songjun Wu");1970MODULE_AUTHOR("Eugen Hristev");1971MODULE_DESCRIPTION("Microchip ISC common code base");1972MODULE_LICENSE("GPL v2");1973